1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00
This commit is contained in:
Jakub Jelinek
2007-07-12 18:26:36 +00:00
parent 7d58530341
commit 0ecb606cb6
6215 changed files with 494638 additions and 305010 deletions

View File

@@ -1 +0,0 @@
sys/trap.h

View File

@@ -1,3 +1,6 @@
# The Sparc `long double' is a distinct type we support.
long-double-fcts = yes
ifeq ($(subdir),db2)
CPPFLAGS += -DHAVE_SPINLOCKS=1 -DHAVE_ASSEM_SPARC_GCC=1
endif

100
sysdeps/sparc/bits/link.h Normal file
View File

@@ -0,0 +1,100 @@
/* Machine-specific audit interfaces for dynamic linker. SPARC version.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _LINK_H
# error "Never include <bits/link.h> directly; use <link.h> instead."
#endif
#if __WORDSIZE == 32
typedef struct La_sparc32_regs
{
uint32_t lr_lreg[8]; /* %l0 through %l7 */
uint32_t lr_reg[6]; /* %o0 through %o5 */
uint32_t lr_sp; /* %o6 */
uint32_t lr_ra; /* %o7 */
uint32_t lr_struct; /* Pass-by-reference struct pointer */
} La_sparc32_regs;
typedef struct La_sparc32_retval
{
uint32_t lrv_reg[2]; /* %o0 and %o1 */
double lrv_fpreg[2]; /* %f0 and %f2 */
} La_sparc32_retval;
#else
typedef struct La_sparc64_regs
{
uint64_t lr_lreg[8]; /* %l0 through %l7 */
uint64_t lr_reg[6]; /* %o0 through %o5 */
uint64_t lr_sp; /* %o6 */
uint64_t lr_ra; /* %o7 */
double lr_fpreg[16]; /* %f0 through %f30 */
} La_sparc64_regs;
typedef struct La_sparc64_retval
{
uint64_t lrv_reg[4]; /* %o0 through %o3 */
double lrv_fprev[4]; /* %f0 through %f8 */
} La_sparc64_retval;
#endif
__BEGIN_DECLS
#if __WORDSIZE == 32
extern Elf32_Addr la_sparc32_gnu_pltenter (Elf32_Sym *__sym,
unsigned int __ndx,
uintptr_t *__refcook,
uintptr_t *__defcook,
La_sparc32_regs *__regs,
unsigned int *__flags,
const char *__symname,
long int *__framesizep);
extern unsigned int la_sparc32_gnu_pltexit (Elf32_Sym *__sym,
unsigned int __ndx,
uintptr_t *__refcook,
uintptr_t *__defcook,
const La_sparc32_regs *__inregs,
La_sparc32_retval *__outregs,
const char *symname);
#else
extern Elf64_Addr la_sparc64_gnu_pltenter (Elf64_Sym *__sym,
unsigned int __ndx,
uintptr_t *__refcook,
uintptr_t *__defcook,
La_sparc64_regs *__regs,
unsigned int *__flags,
const char *__symname,
long int *__framesizep);
extern unsigned int la_sparc64_gnu_pltexit (Elf64_Sym *__sym,
unsigned int __ndx,
uintptr_t *__refcook,
uintptr_t *__defcook,
const La_sparc64_regs *__inregs,
La_sparc64_retval *__outregs,
const char *symname);
#endif
__END_DECLS

View File

@@ -1,4 +1,5 @@
/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
/* Copyright (C) 1997, 1998, 1999, 2000, 2004, 2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -55,14 +56,3 @@ typedef double double_t;
# define FP_ILOGBNAN (2147483647)
#endif /* ISO C99 */
#ifndef __NO_LONG_DOUBLE_MATH
# if __WORDSIZE == 32
/* Signal that in 32bit ABI we do not really have a `long double'.
The disables the declaration of all the `long double' function
variants. */
# define __NO_LONG_DOUBLE_MATH 1
# endif
#endif

View File

@@ -0,0 +1,62 @@
/* Data for Linux/sparc version of processor capability information.
Copyright (C) 2002,2003,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* This information must be kept in sync with the _DL_HWCAP_COUNT
definition in procinfo.h.
If anything should be added here check whether the size of each string
is still ok with the given array size.
All the #ifdefs in the definitions ar equite irritating but
necessary if we want to avoid duplicating the information. There
are three different modes:
- PROCINFO_DECL is defined. This means we are only interested in
declarations.
- PROCINFO_DECL is not defined:
+ if SHARED is defined the file is included in an array
initializer. The .element = { ... } syntax is needed.
+ if SHARED is not defined a normal array initialization is
needed.
*/
#ifndef PROCINFO_CLASS
#define PROCINFO_CLASS
#endif
#if !defined PROCINFO_DECL && defined SHARED
._dl_sparc_cap_flags
#else
PROCINFO_CLASS const char _dl_sparc_cap_flags[7][7]
#endif
#ifndef PROCINFO_DECL
= { "flush", "stbar", "swap", "muldiv", "v9", "ultra3", "v9v" }
#endif
#if !defined SHARED || defined PROCINFO_DECL
;
#else
,
#endif
#undef PROCINFO_DECL
#undef PROCINFO_CLASS

View File

@@ -0,0 +1,79 @@
/* Linux/sparc version of processor capability information handling macros.
Copyright (C) 1999,2000,2001,2002,2003,2004,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jj@ultra.linux.cz>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _DL_PROCINFO_H
#define _DL_PROCINFO_H 1
#include <ldsodefs.h>
#define _DL_HWCAP_COUNT 7
static inline int
__attribute__ ((unused))
_dl_procinfo (int word)
{
int i;
_dl_printf ("AT_HWCAP: ");
for (i = 0; i < _DL_HWCAP_COUNT; ++i)
if (word & (1 << i))
_dl_printf (" %s", GLRO(dl_sparc_cap_flags)[i]);
_dl_printf ("\n");
return 0;
}
static inline const char *
__attribute__ ((unused))
_dl_hwcap_string (int idx)
{
return GLRO(dl_sparc_cap_flags)[idx];
};
static inline int
__attribute__ ((unused, always_inline))
_dl_string_hwcap (const char *str)
{
int i;
for (i = 0; i < _DL_HWCAP_COUNT; i++)
{
if (strcmp (str, GLRO(dl_sparc_cap_flags) [i]) == 0)
return i;
}
return -1;
};
#include <bits/wordsize.h>
#define HWCAP_IMPORTANT_V9 (__WORDSIZE == 64 ? 0 : HWCAP_SPARC_V9)
#define HWCAP_IMPORTANT (HWCAP_IMPORTANT_V9 | HWCAP_SPARC_ULTRA3 \
| HWCAP_SPARC_BLKINIT)
/* There are no different platforms defined. */
#define _dl_platform_string(idx) ""
/* There're no platforms to filter out. */
#define _DL_HWCAP_PLATFORM 0
#define _dl_string_platform(str) (-1)
#endif /* dl-procinfo.h */

View File

@@ -1,5 +1,5 @@
/* System-specific settings for dynamic linker code. SPARC version.
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,25 +17,8 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _DL_SYSDEP_H
#define _DL_SYSDEP_H 1
/* This macro must be defined to either 0 or 1.
If 1, then an errno global variable hidden in ld.so will work right with
all the errno-using libc code compiled for ld.so, and there is never a
need to share the errno location with libc. This is appropriate only if
all the libc functions that ld.so uses are called without PLT and always
get the versions linked into ld.so rather than the libc ones. */
#ifdef IS_IN_rtld
# define RTLD_PRIVATE_ERRNO 1
#else
# define RTLD_PRIVATE_ERRNO 0
#endif
#include_next <dl-sysdep.h>
/* _dl_argv cannot be attribute_relro, because _dl_start_user
might write into it after _dl_start returns. */
#define DL_ARGV_NOT_RELRO 1
#endif /* dl-sysdep.h */

View File

@@ -1,5 +1,6 @@
/* Inline math functions for SPARC.
Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>.
@@ -36,23 +37,52 @@
# if __WORDSIZE == 32
# define __unordered_cmp(x, y) \
# ifndef __NO_LONG_DOUBLE_MATH
# define __unordered_cmp(x, y) \
(__extension__ \
({ unsigned __r; \
if (sizeof(x) == 4 && sizeof(y) == 4) \
if (sizeof (x) == 4 && sizeof (y) == 4) \
{ \
float __x = (x); float __y = (y); \
__asm__("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \
"f" (__y) : "cc"); \
__asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \
"f" (__y) : "cc"); \
} \
else if (sizeof (x) <= 8 && sizeof (y) <= 8) \
{ \
double __x = (x); double __y = (y); \
__asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \
"f" (__y) : "cc"); \
} \
else \
{ \
long double __x = (x); long double __y = (y); \
extern int _Q_cmp (const long double a, const long double b); \
__r = _Q_cmp (__x, __y) << 10; \
} \
__r; }))
# else
# define __unordered_cmp(x, y) \
(__extension__ \
({ unsigned __r; \
if (sizeof (x) == 4 && sizeof (y) == 4) \
{ \
float __x = (x); float __y = (y); \
__asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \
"f" (__y) : "cc"); \
} \
else \
{ \
double __x = (x); double __y = (y); \
__asm__("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \
"f" (__y) : "cc"); \
__asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \
"f" (__y) : "cc"); \
} \
__r; }))
# endif
# define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10))
# define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0)
# define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10))
@@ -65,22 +95,22 @@
# define __unordered_v9cmp(x, y, op, qop) \
(__extension__ \
({ unsigned __r; \
if (sizeof(x) == 4 && sizeof(y) == 4) \
if (sizeof (x) == 4 && sizeof (y) == 4) \
{ \
float __x = (x); float __y = (y); \
__asm__("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \
: "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \
__asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \
: "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \
} \
else if (sizeof(x) <= 8 && sizeof(y) <= 8) \
else if (sizeof (x) <= 8 && sizeof (y) <= 8) \
{ \
double __x = (x); double __y = (y); \
__asm__("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \
: "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \
__asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \
: "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \
} \
else \
{ \
long double __x = (x); long double __y = (y); \
extern int _Qp_cmp(const long double *a, const long double *b); \
extern int _Qp_cmp (const long double *a, const long double *b); \
__r = qop; \
} \
__r; }))
@@ -127,11 +157,20 @@ __NTH (__signbit (double __x))
return __u.__i[0] < 0;
}
# ifndef __NO_LONG_DOUBLE_MATH
__MATH_INLINE int
__NTH (__signbitl (long double __x))
{
__extension__ union { long double __l; int __i[4]; } __u = { __l: __x };
return __u.__i[0] < 0;
}
# else
__MATH_INLINE int
__NTH (__signbitl (long double __x))
{
return __signbit ((double)__x);
}
# endif
# else /* sparc64 */
@@ -180,6 +219,13 @@ __NTH (sqrtl (long double __x))
_Qp_sqrt (&__r, &__x);
return __r;
}
# elif !defined __NO_LONG_DOUBLE_MATH
__MATH_INLINE long double
sqrtl (long double __x) __THROW
{
extern long double _Q_sqrt (__const__ long double);
return _Q_sqrt (__x);
}
# endif /* sparc64 */
# endif /* !__NO_MATH_INLINES && !GCC 3.2+ */
@@ -211,6 +257,13 @@ __ieee754_sqrtl (long double __x)
_Qp_sqrt(&__r, &__x);
return __r;
}
# elif !defined __NO_LONG_DOUBLE_MATH
__MATH_INLINE long double
__ieee754_sqrtl (long double __x)
{
extern long double _Q_sqrt (__const__ long double);
return _Q_sqrt (__x);
}
# endif /* sparc64 */
# endif /* __LIBC_INTERNAL_MATH_INLINES */
# endif /* gcc 2.8+ */

View File

@@ -1,5 +1,5 @@
/* Store current floating-point environment and clear exceptions.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
Copyright (C) 1997, 1998, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -33,3 +33,4 @@ feholdexcept (fenv_t *envp)
return 0;
}
libm_hidden_def (feholdexcept)

View File

@@ -1,5 +1,5 @@
/* Set current rounding direction.
Copyright (C) 1997 Free Software Foundation, Inc.
Copyright (C) 1997, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -35,3 +35,4 @@ fesetround (int round)
return 0;
}
libm_hidden_def (fesetround)

View File

@@ -25,12 +25,12 @@
int
__feraiseexcept (int excepts)
{
static volatile double sink;
static const struct {
double zero, one, max, min, sixteen, pi;
} c = {
0.0, 1.0, DBL_MAX, DBL_MIN, 16.0, M_PI
};
double d;
/* Raise exceptions represented by EXPECTS. But we must raise only
one signal at a time. It is important the if the overflow/underflow
@@ -39,24 +39,44 @@ __feraiseexcept (int excepts)
/* First: invalid exception. */
if ((FE_INVALID & excepts) != 0)
/* One example of a invalid operation is 0/0. */
sink = c.zero / c.zero;
{
/* One example of a invalid operation is 0/0. */
__asm ("" : "=e" (d) : "0" (c.zero));
d /= c.zero;
__asm __volatile ("" : : "e" (d));
}
/* Next: division by zero. */
if ((FE_DIVBYZERO & excepts) != 0)
sink = c.one / c.zero;
{
__asm ("" : "=e" (d) : "0" (c.one));
d /= c.zero;
__asm __volatile ("" : : "e" (d));
}
/* Next: overflow. */
if ((FE_OVERFLOW & excepts) != 0)
sink = c.max * c.max;
{
__asm ("" : "=e" (d) : "0" (c.max));
d *= d;
__asm __volatile ("" : : "e" (d));
}
/* Next: underflow. */
if ((FE_UNDERFLOW & excepts) != 0)
sink = c.min / c.sixteen;
{
__asm ("" : "=e" (d) : "0" (c.min));
d /= c.sixteen;
__asm __volatile ("" : : "e" (d));
}
/* Last: inexact. */
if ((FE_INEXACT & excepts) != 0)
sink = c.one / c.pi;
{
__asm ("" : "=e" (d) : "0" (c.one));
d /= c.pi;
__asm __volatile ("" : : "e" (d));
}
/* Success. */
return 0;

View File

@@ -1,9 +0,0 @@
dotmul.S
umul.S
divrem.m4
sdiv.S
udiv.S
rem.S
urem.S
alloca.S
ieee754.h

View File

@@ -1,5 +1,6 @@
wordsize-32
# SPARC uses IEEE 754 floating point.
ieee754/flt-32
ieee754/ldbl-128
ieee754/dbl-64
ieee754/flt-32
sparc/sparc32/soft-fp

View File

@@ -1,4 +1,5 @@
/* Copyright (C) 1991, 93, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
/* Copyright (C) 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -18,9 +19,7 @@
#include <sysdep.h>
#define _ASM 1
#define _SETJMP_H
#include <bits/setjmp.h>
#include <jmpbuf-offsets.h>
#define ENV(base,reg) [%base + (reg * 4)]
#define ST_FLUSH_WINDOWS 3
#define RW_FP [%fp + 0x48]
@@ -30,6 +29,9 @@ ENTRY(__longjmp)
use them while unwinding frames and their register windows. */
ld ENV(o0,JB_FP), %g3 /* Cache target FP in register %g3. */
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (%g3, %g3, %g4)
#endif
mov %o0, %g1 /* ENV in %g1 */
orcc %o1, %g0, %g2 /* VAL in %g2 */
be,a 0f /* Branch if zero; else skip delay slot. */
@@ -62,8 +64,15 @@ LOC(thread):
* windows.
*/
ta ST_FLUSH_WINDOWS
#ifdef PTR_DEMANGLE
ld ENV(g1,JB_PC), %g5 /* Set return PC. */
ld ENV(g1,JB_SP), %g1 /* Set saved SP on restore below. */
PTR_DEMANGLE2 (%o7, %g5, %g4)
PTR_DEMANGLE2 (%fp, %g1, %g4)
#else
ld ENV(g1,JB_PC), %o7 /* Set return PC. */
ld ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
#endif
sub %fp, 64, %sp /* Allocate a register frame. */
st %g3, RW_FP /* Set saved FP on restore below. */
retl
@@ -71,10 +80,17 @@ LOC(thread):
LOC(found):
/* We have unwound register windows so %fp matches the target. */
#ifdef PTR_DEMANGLE
PTR_DEMANGLE2 (%sp, %o0, %g4)
#else
mov %o0, %sp /* OK, install new SP. */
#endif
LOC(sp_ok):
ld ENV(g1,JB_PC), %o0 /* Extract target return PC. */
#ifdef PTR_DEMANGLE
PTR_DEMANGLE2 (%o0, %o0, %g4)
#endif
jmp %o0 + 8 /* Return there. */
mov %g2, %o0 /* Delay slot: set return value. */

View File

@@ -1,5 +1,5 @@
/* Atomic operations. sparc32 version.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@@ -21,6 +21,34 @@
#ifndef _BITS_ATOMIC_H
#define _BITS_ATOMIC_H 1
#include <stdint.h>
typedef int8_t atomic8_t;
typedef uint8_t uatomic8_t;
typedef int_fast8_t atomic_fast8_t;
typedef uint_fast8_t uatomic_fast8_t;
typedef int16_t atomic16_t;
typedef uint16_t uatomic16_t;
typedef int_fast16_t atomic_fast16_t;
typedef uint_fast16_t uatomic_fast16_t;
typedef int32_t atomic32_t;
typedef uint32_t uatomic32_t;
typedef int_fast32_t atomic_fast32_t;
typedef uint_fast32_t uatomic_fast32_t;
typedef int64_t atomic64_t;
typedef uint64_t uatomic64_t;
typedef int_fast64_t atomic_fast64_t;
typedef uint_fast64_t uatomic_fast64_t;
typedef intptr_t atomicptr_t;
typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
/* We have no compare and swap, just test and set.
The following implementation contends on 64 global locks
per library and assumes no variable will be accessed using atomic.h
@@ -41,22 +69,65 @@ volatile unsigned char __sparc32_atomic_locks[64]
unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \
& 63; \
do \
__asm ("ldstub %1, %0" \
: "=r" (__old_lock), \
"=m" (__sparc32_atomic_locks[__idx]) \
: "m" (__sparc32_atomic_locks[__idx])); \
__asm __volatile ("ldstub %1, %0" \
: "=r" (__old_lock), \
"=m" (__sparc32_atomic_locks[__idx]) \
: "m" (__sparc32_atomic_locks[__idx]) \
: "memory"); \
while (__old_lock); \
} \
while (0)
#define __sparc32_atomic_do_unlock(addr) \
do \
__sparc32_atomic_locks[(((long) addr >> 2) \
^ ((long) addr >> 12)) & 63] = 0; \
{ \
__sparc32_atomic_locks[(((long) addr >> 2) \
^ ((long) addr >> 12)) & 63] = 0; \
__asm __volatile ("" ::: "memory"); \
} \
while (0)
#define __sparc32_atomic_do_lock24(addr) \
do \
{ \
unsigned int __old_lock; \
do \
__asm __volatile ("ldstub %1, %0" \
: "=r" (__old_lock), "=m" (*(addr)) \
: "m" (*(addr)) \
: "memory"); \
while (__old_lock); \
} \
while (0)
#define __sparc32_atomic_do_unlock24(addr) \
do \
{ \
*(char *) (addr) = 0; \
__asm __volatile ("" ::: "memory"); \
} \
while (0)
#ifndef SHARED
# define __v9_compare_and_exchange_val_32_acq(mem, newval, oldval) \
({ \
register __typeof (*(mem)) __acev_tmp __asm ("%g6"); \
register __typeof (mem) __acev_mem __asm ("%g1") = (mem); \
register __typeof (*(mem)) __acev_oldval __asm ("%g5"); \
__acev_tmp = (newval); \
__acev_oldval = (oldval); \
/* .word 0xcde05005 is cas [%g1], %g5, %g6. Can't use cas here though, \
because as will then mark the object file as V8+ arch. */ \
__asm __volatile (".word 0xcde05005" \
: "+r" (__acev_tmp), "=m" (*__acev_mem) \
: "r" (__acev_oldval), "m" (*__acev_mem), \
"r" (__acev_mem) : "memory"); \
__acev_tmp; })
#endif
/* The only basic operation needed is compare and exchange. */
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
#define __v7_compare_and_exchange_val_acq(mem, newval, oldval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
@@ -68,7 +139,7 @@ volatile unsigned char __sparc32_atomic_locks[64]
__sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
#define __v7_compare_and_exchange_bool_acq(mem, newval, oldval) \
({ __typeof (mem) __aceb_memp = (mem); \
int __aceb_ret; \
__typeof (*mem) __aceb_newval = (newval); \
@@ -82,4 +153,175 @@ volatile unsigned char __sparc32_atomic_locks[64]
__sparc32_atomic_do_unlock (__aceb_memp); \
__aceb_ret; })
#define __v7_exchange_acq(mem, newval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
__sparc32_atomic_do_lock (__acev_memp); \
__acev_ret = *__acev_memp; \
*__acev_memp = __acev_newval; \
__sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
#define __v7_exchange_and_add(mem, value) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
\
__sparc32_atomic_do_lock (__acev_memp); \
__acev_ret = *__acev_memp; \
*__acev_memp = __acev_ret + (value); \
__sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
/* Special versions, which guarantee that top 8 bits of all values
are cleared and use those bits as the ldstub lock. */
#define __v7_compare_and_exchange_val_24_acq(mem, newval, oldval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
__sparc32_atomic_do_lock24 (__acev_memp); \
__acev_ret = *__acev_memp & 0xffffff; \
if (__acev_ret == (oldval)) \
*__acev_memp = __acev_newval; \
else \
__sparc32_atomic_do_unlock24 (__acev_memp); \
__asm __volatile ("" ::: "memory"); \
__acev_ret; })
#define __v7_exchange_24_rel(mem, newval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
__sparc32_atomic_do_lock24 (__acev_memp); \
__acev_ret = *__acev_memp & 0xffffff; \
*__acev_memp = __acev_newval; \
__asm __volatile ("" ::: "memory"); \
__acev_ret; })
#ifdef SHARED
/* When dynamically linked, we assume pre-v9 libraries are only ever
used on pre-v9 CPU. */
# define __atomic_is_v9 0
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
__v7_compare_and_exchange_val_acq (mem, newval, oldval)
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
__v7_compare_and_exchange_bool_acq (mem, newval, oldval)
# define atomic_exchange_acq(mem, newval) \
__v7_exchange_acq (mem, newval)
# define atomic_exchange_and_add(mem, value) \
__v7_exchange_and_add (mem, value)
# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
({ \
if (sizeof (*mem) != 4) \
abort (); \
__v7_compare_and_exchange_val_24_acq (mem, newval, oldval); })
# define atomic_exchange_24_rel(mem, newval) \
({ \
if (sizeof (*mem) != 4) \
abort (); \
__v7_exchange_24_rel (mem, newval); })
#else
/* In libc.a/libpthread.a etc. we don't know if we'll be run on
pre-v9 or v9 CPU. To be interoperable with dynamically linked
apps on v9 CPUs e.g. with process shared primitives, use cas insn
on v9 CPUs and ldstub on pre-v9. */
/* Avoid <ldsodefs.h> include here. */
extern uint64_t _dl_hwcap __attribute__((weak));
# define __ATOMIC_HWCAP_SPARC_V9 16
# define __atomic_is_v9 \
(__builtin_expect (&_dl_hwcap != 0, 1) \
&& __builtin_expect (_dl_hwcap & __ATOMIC_HWCAP_SPARC_V9, \
__ATOMIC_HWCAP_SPARC_V9))
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
({ \
__typeof (*mem) __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
__acev_wret \
= __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
else \
__acev_wret \
= __v7_compare_and_exchange_val_acq (mem, newval, oldval); \
__acev_wret; })
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
({ \
int __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
{ \
__typeof (oldval) __acev_woldval = (oldval); \
__acev_wret \
= __v9_compare_and_exchange_val_32_acq (mem, newval, \
__acev_woldval) \
!= __acev_woldval; \
} \
else \
__acev_wret \
= __v7_compare_and_exchange_bool_acq (mem, newval, oldval); \
__acev_wret; })
# define atomic_exchange_rel(mem, newval) \
({ \
__typeof (*mem) __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
{ \
__typeof (mem) __acev_wmemp = (mem); \
__typeof (*(mem)) __acev_wval = (newval); \
do \
__acev_wret = *__acev_wmemp; \
while (__builtin_expect \
(__v9_compare_and_exchange_val_32_acq (__acev_wmemp,\
__acev_wval, \
__acev_wret) \
!= __acev_wret, 0)); \
} \
else \
__acev_wret = __v7_exchange_acq (mem, newval); \
__acev_wret; })
# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
({ \
__typeof (*mem) __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
__acev_wret \
= __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
else \
__acev_wret \
= __v7_compare_and_exchange_val_24_acq (mem, newval, oldval);\
__acev_wret; })
# define atomic_exchange_24_rel(mem, newval) \
({ \
__typeof (*mem) __acev_w24ret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
__acev_w24ret = atomic_exchange_rel (mem, newval); \
else \
__acev_w24ret = __v7_exchange_24_rel (mem, newval); \
__acev_w24ret; })
#endif
#endif /* bits/atomic.h */

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
/* Copyright (C) 1997, 1998, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -22,17 +22,6 @@
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
#endif
#if defined __USE_MISC || defined _ASM
# define JB_SP 0
# define JB_FP 1
# define JB_PC 2
#endif
#ifndef _ASM
typedef int __jmp_buf[3];
#endif
/* Test if longjmp to JMPBUF would unwind the frame
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((int) (address) < (jmpbuf)[JB_SP])

View File

@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. SPARC version.
Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc.
Copyright (C) 1996-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -40,13 +40,6 @@
#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */
/* Use a different preload file when running in 32-bit emulation mode
on a 64-bit host. */
#define LD_SO_PRELOAD ((GLRO(dl_hwcap) & HWCAP_SPARC_V9) \
? "/etc/ld.so.preload32" \
: "/etc/ld.so.preload")
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int
elf_machine_matches_host (const Elf32_Ehdr *ehdr)
@@ -131,30 +124,31 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
bits of %g1 with an offset into the .rela.plt section and jump to
the beginning of the PLT. */
plt = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
if (! profile)
rfunc = (Elf32_Addr) &_dl_runtime_resolve;
else
if (__builtin_expect(profile, 0))
{
rfunc = (Elf32_Addr) &_dl_runtime_profile;
if (_dl_name_match_p (GLRO(dl_profile), l))
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
GL(dl_profile_map) = l;
}
else
{
rfunc = (Elf32_Addr) &_dl_runtime_resolve;
}
/* The beginning of the PLT does:
save %sp, -64, %sp
pltpc: call _dl_runtime_resolve
nop
sethi %hi(_dl_runtime_{resolve,profile}), %g2
pltpc: jmpl %g2 + %lo(_dl_runtime_{resolve,profile}), %g2
nop
.word MAP
This saves the register window containing the arguments, and the
PC value (pltpc) implicitly saved in %o7 by the call points near the
The PC value (pltpc) saved in %g2 by the jmpl points near the
location where we store the link_map pointer for this object. */
plt[0] = OPCODE_SAVE_SP;
/* Construct PC-relative word address. */
plt[1] = OPCODE_CALL | ((rfunc - (Elf32_Addr) &plt[1]) >> 2);
plt[0] = 0x05000000 | ((rfunc >> 10) & 0x003fffff);
plt[1] = 0x85c0a000 | (rfunc & 0x3ff);
plt[2] = OPCODE_NOP; /* Fill call delay slot. */
plt[3] = (Elf32_Addr) l;
if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
@@ -190,39 +184,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
/* This code is used in dl-runtime.c to call the `fixup' function
and then redirect to the address it returns. */
#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
asm ( "\
.text\n\
.globl " #tramp_name "\n\
.type " #tramp_name ", @function\n\
.align 32\n\
" #tramp_name ":\n\
/* Set up the arguments to fixup --\n\
%o0 = link_map out of plt0\n\
%o1 = offset of reloc entry\n\
%o2 = return address */\n\
ld [%o7 + 8], %o0\n\
srl %g1, 10, %o1\n\
mov %i7, %o2\n\
call " #fixup_name "\n\
sub %o1, 4*12, %o1\n\
jmp %o0\n\
restore\n\
.size " #tramp_name ", . - " #tramp_name "\n\
.previous")
#ifndef PROF
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
#else
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
TRAMPOLINE_TEMPLATE (_dl_runtime_profile, fixup);
#endif
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
PLT entries should not be allowed to define the value.
ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
@@ -406,18 +367,25 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
#endif /* dl_machine_h */
#ifdef RESOLVE
#define ARCH_LA_PLTENTER sparc32_gnu_pltenter
#define ARCH_LA_PLTEXIT sparc32_gnu_pltexit
#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
static inline void
auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
void *const reloc_addr_arg)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const Elf32_Sym *const refsym = sym;
Elf32_Addr value;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
struct link_map *sym_map = NULL;
#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
/* This is defined in rtld.c, but nowhere in the static libc.a; make the
@@ -428,6 +396,9 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
weak_extern (_dl_rtld_map);
#endif
if (__builtin_expect (r_type == R_SPARC_NONE, 0))
return;
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))
{
@@ -435,165 +406,148 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (map != &_dl_rtld_map) /* Already done in rtld itself. */
# endif
*reloc_addr += map->l_addr + reloc->r_addend;
return;
}
#endif
#ifndef RESOLVE_CONFLICT_FIND_MAP
if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
&& sym->st_shndx != SHN_UNDEF)
{
value = map->l_addr;
}
else
{
sym_map = RESOLVE_MAP (&sym, version, r_type);
value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
}
#else
value = 0;
#endif
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
switch (r_type)
{
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
const Elf32_Sym *const refsym = sym;
# ifdef USE_TLS
struct link_map *sym_map;
# endif
#endif
Elf32_Addr value;
#ifndef RESOLVE_CONFLICT_FIND_MAP
if (sym->st_shndx != SHN_UNDEF &&
ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
case R_SPARC_COPY:
if (sym == NULL)
/* This can happen in trace mode if an object could not be
found. */
break;
if (sym->st_size > refsym->st_size
|| (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
{
value = map->l_addr;
# if defined USE_TLS && !defined RTLD_BOOTSTRAP
sym_map = map;
# endif
}
else
{
# if defined USE_TLS && !defined RTLD_BOOTSTRAP
sym_map = RESOLVE_MAP (&sym, version, r_type);
value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
# else
value = RESOLVE (&sym, version, r_type);
if (sym)
value += sym->st_value;
# endif
}
#else
value = 0;
#endif
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
const char *strtab;
switch (r_type)
{
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
case R_SPARC_COPY:
if (sym == NULL)
/* This can happen in trace mode if an object could not be
found. */
break;
if (sym->st_size > refsym->st_size
|| (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
{
const char *strtab;
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
_dl_error_printf ("\
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
_dl_error_printf ("\
%s: Symbol `%s' has different size in shared object, consider re-linking\n",
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
}
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break;
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
}
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break;
#endif
case R_SPARC_GLOB_DAT:
case R_SPARC_32:
*reloc_addr = value;
break;
case R_SPARC_JMP_SLOT:
/* At this point we don't need to bother with thread safety,
so we can optimize the first instruction of .plt out. */
sparc_fixup_plt (reloc, reloc_addr, value, 0);
break;
case R_SPARC_GLOB_DAT:
case R_SPARC_32:
*reloc_addr = value;
break;
case R_SPARC_JMP_SLOT:
/* At this point we don't need to bother with thread safety,
so we can optimize the first instruction of .plt out. */
sparc_fixup_plt (reloc, reloc_addr, value, 0);
break;
#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \
&& !defined RESOLVE_CONFLICT_FIND_MAP
case R_SPARC_TLS_DTPMOD32:
/* Get the information from the link map returned by the
resolv function. */
if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid;
break;
case R_SPARC_TLS_DTPOFF32:
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
*reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
break;
case R_SPARC_TLS_TPOFF32:
/* The offset is negative, forward from the thread pointer. */
/* We know the offset of object the symbol is contained in.
It is a negative value which will be added to the
thread pointer. */
if (sym != NULL)
{
CHECK_STATIC_TLS (map, sym_map);
*reloc_addr = sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend;
}
break;
case R_SPARC_TLS_DTPMOD32:
/* Get the information from the link map returned by the
resolv function. */
if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid;
break;
case R_SPARC_TLS_DTPOFF32:
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
*reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
break;
case R_SPARC_TLS_TPOFF32:
/* The offset is negative, forward from the thread pointer. */
/* We know the offset of object the symbol is contained in.
It is a negative value which will be added to the
thread pointer. */
if (sym != NULL)
{
CHECK_STATIC_TLS (map, sym_map);
*reloc_addr = sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend;
}
break;
# ifndef RTLD_BOOTSTRAP
case R_SPARC_TLS_LE_HIX22:
case R_SPARC_TLS_LE_LOX10:
if (sym != NULL)
{
CHECK_STATIC_TLS (map, sym_map);
value = sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend;
if (r_type == R_SPARC_TLS_LE_HIX22)
*reloc_addr = (*reloc_addr & 0xffc00000) | ((~value) >> 10);
else
*reloc_addr = (*reloc_addr & 0xffffe000) | (value & 0x3ff)
| 0x1c00;
}
break;
case R_SPARC_TLS_LE_HIX22:
case R_SPARC_TLS_LE_LOX10:
if (sym != NULL)
{
CHECK_STATIC_TLS (map, sym_map);
value = sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend;
if (r_type == R_SPARC_TLS_LE_HIX22)
*reloc_addr = (*reloc_addr & 0xffc00000) | ((~value) >> 10);
else
*reloc_addr = (*reloc_addr & 0xffffe000) | (value & 0x3ff)
| 0x1c00;
}
break;
# endif
#endif
#ifndef RTLD_BOOTSTRAP
case R_SPARC_8:
*(char *) reloc_addr = value;
break;
case R_SPARC_16:
*(short *) reloc_addr = value;
break;
case R_SPARC_DISP8:
*(char *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
break;
case R_SPARC_DISP16:
*(short *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
break;
case R_SPARC_DISP32:
*reloc_addr = (value - (Elf32_Addr) reloc_addr);
break;
case R_SPARC_LO10:
*reloc_addr = (*reloc_addr & ~0x3ff) | (value & 0x3ff);
break;
case R_SPARC_WDISP30:
*reloc_addr = ((*reloc_addr & 0xc0000000)
| ((value - (unsigned int) reloc_addr) >> 2));
break;
case R_SPARC_HI22:
*reloc_addr = (*reloc_addr & 0xffc00000) | (value >> 10);
break;
case R_SPARC_UA16:
((unsigned char *) reloc_addr_arg) [0] = value >> 8;
((unsigned char *) reloc_addr_arg) [1] = value;
break;
case R_SPARC_UA32:
((unsigned char *) reloc_addr_arg) [0] = value >> 24;
((unsigned char *) reloc_addr_arg) [1] = value >> 16;
((unsigned char *) reloc_addr_arg) [2] = value >> 8;
((unsigned char *) reloc_addr_arg) [3] = value;
break;
case R_SPARC_8:
*(char *) reloc_addr = value;
break;
case R_SPARC_16:
*(short *) reloc_addr = value;
break;
case R_SPARC_DISP8:
*(char *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
break;
case R_SPARC_DISP16:
*(short *) reloc_addr = (value - (Elf32_Addr) reloc_addr);
break;
case R_SPARC_DISP32:
*reloc_addr = (value - (Elf32_Addr) reloc_addr);
break;
case R_SPARC_LO10:
*reloc_addr = (*reloc_addr & ~0x3ff) | (value & 0x3ff);
break;
case R_SPARC_WDISP30:
*reloc_addr = ((*reloc_addr & 0xc0000000)
| ((value - (unsigned int) reloc_addr) >> 2));
break;
case R_SPARC_HI22:
*reloc_addr = (*reloc_addr & 0xffc00000) | (value >> 10);
break;
case R_SPARC_UA16:
((unsigned char *) reloc_addr_arg) [0] = value >> 8;
((unsigned char *) reloc_addr_arg) [1] = value;
break;
case R_SPARC_UA32:
((unsigned char *) reloc_addr_arg) [0] = value >> 24;
((unsigned char *) reloc_addr_arg) [1] = value >> 16;
((unsigned char *) reloc_addr_arg) [2] = value >> 8;
((unsigned char *) reloc_addr_arg) [3] = value;
break;
#endif
case R_SPARC_NONE: /* Alright, Wilbur. */
break;
#if !defined RTLD_BOOTSTRAP || defined _NDEBUG
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
#endif
}
}
}
static inline void
auto inline void
__attribute__ ((always_inline))
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
void *const reloc_addr_arg)
{
@@ -601,7 +555,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
*reloc_addr += l_addr + reloc->r_addend;
}
static inline void
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
Elf32_Addr l_addr, const Elf32_Rela *reloc)
{
@@ -617,4 +572,4 @@ elf_machine_lazy_rel (struct link_map *map,
}
}
#endif /* RESOLVE */
#endif /* RESOLVE_MAP */

View File

@@ -0,0 +1,184 @@
/* PLT trampolines. Sparc 32-bit version.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
.text
.align 32
/* %g1: PLT offset loaded by PLT entry
* %g2: callers PC, which is PLT0 + 4, and we store the
* link map at PLT0 + 12, therefore we add 8 to get
* the address of the link map
*/
.globl _dl_runtime_resolve
.type _dl_runtime_resolve, @function
_dl_runtime_resolve:
cfi_startproc
save %sp, -104, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cfi_register (%o7, %i7)
ld [%g2 + 8], %o0
srl %g1, 10, %o1
call _dl_fixup
sub %o1, 4*12, %o1
jmp %o0
restore
cfi_endproc
.size _dl_runtime_resolve, .-_dl_runtime_resolve
/* For the profiling cases we pass in our stack frame
* as the base of the La_sparc64_regs, so it looks
* like:
* %l0 %sp
* ...
* %l7 %sp + (7 * 8)
* %i0 %sp + (8 * 8)
* ...
* %i7 %sp + (15 * 8)
* %f0 %sp + (16 * 8)
* %f16 %sp + (31 * 8)
* framesize %sp + (32 * 8)
*/
.globl _dl_profile_save_regs
.type _dl_profile_save_regs, @function
_dl_profile_save_regs:
cfi_startproc
std %l0, [%sp + ( 0 * 8)]
std %l2, [%sp + ( 1 * 8)]
std %l4, [%sp + ( 2 * 8)]
std %l6, [%sp + ( 3 * 8)]
std %i0, [%sp + ( 4 * 8)]
std %i2, [%sp + ( 5 * 8)]
std %i4, [%sp + ( 6 * 8)]
std %i6, [%sp + ( 7 * 8)]
ld [%sp + (8 * 8)], %l4
retl
st %l4, [%sp + (8 * 8)]
cfi_endproc
.size _dl_profile_save_regs, .-_dl_profile_save_regs
/* If we are going to call pltexit, then we must replicate
* the caller's stack frame.
* %o0: PLT resolved function address
*/
.globl _dl_profile_invoke
.type _dl_profile_invoke, @function
_dl_profile_invoke:
cfi_startproc
sub %sp, %l0, %sp
1:
srl %l0, 3, %l7
mov %o0, %l1
mov %i0, %o0
mov %i1, %o1
mov %i2, %o2
mov %i3, %o3
mov %i4, %o4
mov %i5, %o5
mov %fp, %l2
mov %sp, %l3
1: ldd [%l2], %g2
add %l2, 0x8, %l2
subcc %l7, 1, %l7
std %g2, [%l3]
bne 1b
add %l3, 0x8, %l3
jmpl %l1, %o7
nop
std %o0, [%sp + ( 9 * 8)]
std %f0, [%sp + (10 * 8)]
mov %l5, %o0
mov %l6, %o1
add %sp, %l0, %o2
call _dl_call_pltexit
add %sp, (16 * 8), %o3
ldd [%sp + (9 * 8)], %i0
jmpl %i7 + 8, %g0
restore
cfi_endproc
.size _dl_profile_invoke, .-_dl_profile_invoke
/* %g1: PLT offset loaded by PLT entry
* %g2: callers PC, which is PLT0 + 4, and we store the
* link map at PLT0 + 12, therefore we add 8 to get
* the address of the link map
*/
.align 32
.globl _dl_runtime_profile
.type _dl_runtime_profile, @function
_dl_runtime_profile:
cfi_startproc
cmp %fp, 0
be,a 1f
mov 104, %g3
sub %fp, %sp, %g3
1: save %sp, -104, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cfi_register(%o7, %i7)
ld [%g2 + 8], %o0
srl %g1, 10, %o1
mov %i7, %o2
sub %o1, 4*12, %o1
mov %g3, %l0
mov %o0, %l5
mov %o1, %l6
call _dl_profile_save_regs
nop
mov %sp, %o3
call _dl_profile_fixup
add %sp, (9 * 8), %o4
ld [%sp + (9 * 8)], %o1
cmp %o1, 0
bgeu 1f
nop
call _dl_profile_invoke
nop
1: jmp %o0
restore
cfi_endproc
.size _dl_runtime_profile, .-_dl_runtime_profile

View File

@@ -48,6 +48,7 @@
.global _start
.type _start,#function
_start:
cfi_startproc
#ifdef SHARED
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7
@@ -59,6 +60,7 @@ _start:
drop their arguments. */
mov %g0, %fp
sub %sp, 6*4, %sp
cfi_adjust_cfa_offset(6*4)
/* Extract the arguments and environment as encoded on the stack. The
argument info starts after one register window (16 words) past the SP. */
@@ -91,4 +93,12 @@ _start:
/* Die very horribly if exit returns. */
unimp
cfi_endproc
.size _start, .-_start
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
weak_alias (__data_start, data_start)

View File

@@ -0,0 +1 @@
/* __ieee754_sqrtl is defined in q_sqrt.c. */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
#include <math.h>
#include <math_ldbl_opt.h>
double __fabs (double x)
{
return __builtin_fabs (x);
}
weak_alias (__fabs, fabs)
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
compat_symbol (libm, __fabs, fabsl, GLIBC_2_0);
#endif

View File

@@ -0,0 +1,29 @@
/* Float absolute value, sparc32 version.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
ENTRY (__fabsf)
st %o0, [%sp+64]
ld [%sp+64], %f0
retl
fabss %f0, %f0
END (__fabsf)
weak_alias (__fabsf, fabsf)

View File

@@ -0,0 +1,8 @@
#include <math.h>
#include <math_ldbl_opt.h>
long double __fabsl (long double x)
{
return __builtin_fabsl (x);
}
long_double_symbol (libm, __fabsl, fabsl);

View File

@@ -0,0 +1,22 @@
/* Private macros for accessing __jmp_buf contents. SPARC version.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#define JB_SP 0
#define JB_FP 1
#define JB_PC 2

View File

@@ -0,0 +1,48 @@
/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <jmpbuf-offsets.h>
#include <stdint.h>
#include <unwind.h>
#include <sysdep.h>
/* Test if longjmp to JMPBUF would unwind the frame
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
((int) (address) < demangle ((jmpbuf)[JB_SP]))
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
static inline uintptr_t __attribute__ ((unused))
_jmpbuf_sp (__jmp_buf regs)
{
uintptr_t sp = regs[JB_SP];
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (sp);
#endif
return sp;
}
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
/* We use the normal lobngjmp for unwinding. */
#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)

View File

@@ -32,7 +32,15 @@
.text
.align 4
0: cmp %o2, 0
ENTRY(__memchr)
andcc %o1, 0xff, %o1
sll %o1, 8, %g6
andcc %o0, 3, %g0
or %o1, %g6, %g6
sll %g6, 16, %o3
be 10f
or %o3, %g6, %g2
cmp %o2, 0
be 9f
sethi %hi(0x80808080), %o4
ldub [%o0], %g4
@@ -64,16 +72,7 @@
clr %o0
1: retl
sub %o0, 1, %o0
ENTRY(__memchr)
andcc %o1, 0xff, %o1
sll %o1, 8, %g6
andcc %o0, 3, %g0
or %o1, %g6, %g6
sll %g6, 16, %o3
bne 0b
or %o3, %g6, %g2
sethi %hi(0x80808080), %o4
10: sethi %hi(0x80808080), %o4
or %o4, %lo(0x80808080), %o3
4: sethi %hi(0x01010101), %o5
5: and %o2, 3, %g1

View File

@@ -146,28 +146,12 @@
.text
.align 4
70: andcc %o1, 1, %g0
be 4f
andcc %o1, 2, %g0
ldub [%o1 - 1], %g2
sub %o1, 1, %o1
stb %g2, [%o0 - 1]
sub %o2, 1, %o2
be 3f
sub %o0, 1, %o0
4: lduh [%o1 - 2], %g2
sub %o1, 2, %o1
sth %g2, [%o0 - 2]
sub %o2, 2, %o2
b 3f
sub %o0, 2, %o0
ENTRY(bcopy)
mov %o0, %o3
mov %o1, %o0
mov %o3, %o1
END(bcopy)
ENTRY(memmove)
cmp %o0, %o1
st %o0, [%sp + 64]
@@ -185,8 +169,26 @@ ENTRY(memmove)
cmp %o2, 15
bleu 91f
andcc %o1, 3, %g0
bne 70b
3: andcc %o1, 4, %g0
be 3f
nop
andcc %o1, 1, %g0
be 4f
andcc %o1, 2, %g0
ldub [%o1 - 1], %g2
sub %o1, 1, %o1
stb %g2, [%o0 - 1]
sub %o2, 1, %o2
be 3f
sub %o0, 1, %o0
4: lduh [%o1 - 2], %g2
sub %o1, 2, %o1
sth %g2, [%o0 - 2]
sub %o2, 2, %o2
sub %o0, 2, %o0
3: andcc %o1, 4, %g0
be 2f
mov %o2, %g1

View File

@@ -152,4 +152,4 @@ ENTRY(memset)
END(memset)
libc_hidden_builtin_def (memset)
weak_alias(__bzero, bzero)
weak_alias (__bzero, bzero)

View File

@@ -1,4 +1,5 @@
/* Copyright (C) 1991, 93, 94, 96, 97, 98, 2002 Free Software Foundation, Inc.
/* Copyright (C) 1991, 1993, 1994, 1996, 1997, 1998, 2002, 2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,9 +20,7 @@
#include <sysdep.h>
#include <sys/trap.h>
#define _ASM 1
#define _SETJMP_H
#include <bits/setjmp.h>
#include <jmpbuf-offsets.h>
ENTRY(_setjmp)
b 1f
@@ -39,9 +38,18 @@ ENTRY (__sigsetjmp)
a tail-call for simplicity; it always returns zero. */
ta ST_FLUSH_WINDOWS
#ifdef PTR_MANGLE
PTR_MANGLE (%g1, %o7, %g4)
PTR_MANGLE2 (%g2, %sp, %g4)
PTR_MANGLE2 (%g3, %fp, %g4)
st %g1, [%o0 + (JB_PC * 4)]
st %g2, [%o0 + (JB_SP * 4)]
st %g3, [%o0 + (JB_FP * 4)]
#else
st %o7, [%o0 + (JB_PC * 4)]
st %sp, [%o0 + (JB_SP * 4)]
st %fp, [%o0 + (JB_FP * 4)]
#endif
mov %o7, %g1
call __sigjmp_save

View File

@@ -1,28 +0,0 @@
q_add.c
q_cmp.c
q_cmpe.c
q_div.c
q_dtoq.c
q_feq.c
q_fge.c
q_fgt.c
q_fle.c
q_flt.c
q_fne.c
q_itoq.c
q_mul.c
q_neg.c
q_qtod.c
q_qtoi.c
q_qtos.c
q_qtoui.c
q_qtoux.c
q_qtox.c
q_sqrt.c
q_stoq.c
q_sub.c
q_uitoq.c
q_util.c
q_uxtoq.c
q_xtoq.c
sfp-machine.h

View File

@@ -1,6 +1,6 @@
# Software floating-point emulation.
# Makefile for SPARC v8 long double utility functions (_Q_*).
# Copyright (C) 1999, 2000 Free Software Foundation, Inc.
# Copyright (C) 1999, 2000, 2006 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Jakub Jelinek (jj@ultra.linux.cz).
#
@@ -20,13 +20,11 @@
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA.
# Currently gcc does not support TFmode long double on sparc32
# so these routines are not used.
#ifeq ($(subdir),soft-fp)
#sparc32-quad-routines := q_add q_cmp q_cmpe q_div q_dtoq q_feq q_fge \
# q_fgt q_fle q_flt q_fne q_itoq q_mul q_neg q_qtod q_qtoi \
# q_qtos q_qtoui q_qtoux q_qtox q_sqrt q_stoq q_sub q_uitoq \
# q_uxtoq q_xtoq q_util
#sysdep_routines += $(sparc32-quad-routines)
#
#endif
ifeq ($(subdir),soft-fp)
sparc32-quad-routines := q_add q_cmp q_cmpe q_div q_dtoq q_feq q_fge \
q_fgt q_fle q_flt q_fne q_itoq q_mul q_neg q_qtod q_qtoi \
q_qtos q_qtou q_qtoull q_qtoll q_sqrt q_stoq q_sub q_utoq \
q_ulltoq q_lltoq q_util
sysdep_routines += $(sparc32-quad-routines)
endif

View File

@@ -0,0 +1,8 @@
libc {
GLIBC_2.4 {
_Q_add; _Q_cmp; _Q_cmpe; _Q_div; _Q_dtoq; _Q_feq; _Q_fge; _Q_fgt;
_Q_fle; _Q_flt; _Q_fne; _Q_itoq; _Q_mul; _Q_neg; _Q_qtod; _Q_qtoi;
_Q_qtos; _Q_qtou; _Q_qtoull; _Q_qtoll; _Q_sqrt; _Q_stoq; _Q_sub;
_Q_utoq; _Q_ulltoq; _Q_lltoq;
}
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return a + b
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -30,10 +30,10 @@ long double _Q_add(const long double a, const long double b)
long double c;
FP_INIT_ROUNDMODE;
FP_UNPACK_Q(A, a);
FP_UNPACK_Q(B, b);
FP_UNPACK_SEMIRAW_Q(A, a);
FP_UNPACK_SEMIRAW_Q(B, b);
FP_ADD_Q(C, A, B);
FP_PACK_Q(c, C);
FP_PACK_SEMIRAW_Q(c, C);
FP_HANDLE_EXCEPTIONS;
return c;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return a / b
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -35,5 +35,5 @@ long double _Q_div(const long double a, const long double b)
FP_DIV_Q(C, A, B);
FP_PACK_Q(c, C);
FP_HANDLE_EXCEPTIONS;
return long double;
return c;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ long double _Q_dtoq(const double a)
long double c;
FP_INIT_ROUNDMODE;
FP_UNPACK_D(A, a);
FP_UNPACK_RAW_D(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(Q,D,4,2,C,A);
FP_EXTEND(Q,D,4,2,C,A);
#else
FP_CONV(Q,D,2,1,C,A);
FP_EXTEND(Q,D,2,1,C,A);
#endif
FP_PACK_Q(c, C);
FP_PACK_RAW_Q(c, C);
FP_HANDLE_EXCEPTIONS;
return c;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -30,8 +30,8 @@ long double _Q_itoq(const int a)
int b = a;
long double c;
FP_FROM_INT_Q(C, b, 32, int);
FP_PACK_Q(c, C);
FP_FROM_INT_Q(C, b, 32, unsigned int);
FP_PACK_RAW_Q(c, C);
FP_CLEAR_EXCEPTIONS;
FP_HANDLE_EXCEPTIONS;
return c;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (long double)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -23,15 +23,15 @@
#include "soft-fp.h"
#include "quad.h"
long double _Q_xtoq(const long long a)
long double _Q_lltoq(const long long a)
{
FP_DECL_EX;
FP_DECL_Q(C);
long double c;
long long b = a;
FP_FROM_INT_Q(C, b, 64, long long);
FP_PACK_Q(c, C);
FP_FROM_INT_Q(C, b, 64, unsigned long long);
FP_PACK_RAW_Q(c, C);
FP_CLEAR_EXCEPTIONS;
FP_HANDLE_EXCEPTIONS;
return c;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (double)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ double _Q_qtod(const long double a)
double r;
FP_INIT_ROUNDMODE;
FP_UNPACK_Q(A, a);
FP_UNPACK_SEMIRAW_Q(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(D,Q,2,4,R,A);
FP_TRUNC(D,Q,2,4,R,A);
#else
FP_CONV(D,Q,1,2,R,A);
FP_TRUNC(D,Q,1,2,R,A);
#endif
FP_PACK_D(r, R);
FP_PACK_SEMIRAW_D(r, R);
FP_HANDLE_EXCEPTIONS;
return r;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (int)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -28,9 +28,9 @@ int _Q_qtoi(const long double a)
{
FP_DECL_EX;
FP_DECL_Q(A);
int r;
unsigned int r;
FP_UNPACK_Q(A, a);
FP_UNPACK_RAW_Q(A, a);
FP_TO_INT_Q(r, A, 32, 1);
FP_HANDLE_EXCEPTIONS;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (long)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Return (long long)a
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -24,13 +24,13 @@
#include "soft-fp.h"
#include "quad.h"
long long _Q_qtox(const long double a)
long long _Q_qtoll(const long double a)
{
FP_DECL_EX;
FP_DECL_Q(A);
long long r;
unsigned long long r;
FP_UNPACK_Q(A, a);
FP_UNPACK_RAW_Q(A, a);
FP_TO_INT_Q(r, A, 64, 1);
FP_HANDLE_EXCEPTIONS;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (float)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ float _Q_qtos(const long double a)
float r;
FP_INIT_ROUNDMODE;
FP_UNPACK_Q(A, a);
FP_UNPACK_SEMIRAW_Q(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(S,Q,1,4,R,A);
FP_TRUNC(S,Q,1,4,R,A);
#else
FP_CONV(S,Q,1,2,R,A);
FP_TRUNC(S,Q,1,2,R,A);
#endif
FP_PACK_S(r, R);
FP_PACK_SEMIRAW_S(r, R);
FP_HANDLE_EXCEPTIONS;
return r;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (unsigned int)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -24,13 +24,13 @@
#include "soft-fp.h"
#include "quad.h"
unsigned int _Q_qtoui(const long double a)
unsigned int _Q_qtou(const long double a)
{
FP_DECL_EX;
FP_DECL_Q(A);
unsigned int r;
FP_UNPACK_Q(A, a);
FP_UNPACK_RAW_Q(A, a);
FP_TO_INT_Q(r, A, 32, -1);
FP_HANDLE_EXCEPTIONS;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (unsigned long)a
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Return (unsigned long long)a
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -24,13 +24,13 @@
#include "soft-fp.h"
#include "quad.h"
unsigned long long _Q_qtoux(const long double a)
unsigned long long _Q_qtoull(const long double a)
{
FP_DECL_EX;
FP_DECL_Q(A);
unsigned long long r;
FP_UNPACK_Q(A, a);
FP_UNPACK_RAW_Q(A, a);
FP_TO_INT_Q(r, A, 64, -1);
FP_HANDLE_EXCEPTIONS;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return sqrtl(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -36,3 +36,4 @@ long double _Q_sqrt(const long double a)
FP_HANDLE_EXCEPTIONS;
return c;
}
strong_alias (_Q_sqrt, __ieee754_sqrtl);

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
c = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,13 +31,13 @@ long double _Q_stoq(const float a)
FP_DECL_Q(C);
long double c;
FP_UNPACK_S(A, a);
FP_UNPACK_RAW_S(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(Q,S,4,1,C,A);
FP_EXTEND(Q,S,4,1,C,A);
#else
FP_CONV(Q,S,2,1,C,A);
FP_EXTEND(Q,S,2,1,C,A);
#endif
FP_PACK_Q(c, C);
FP_PACK_RAW_Q(c, C);
FP_HANDLE_EXCEPTIONS;
return c;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
c = a - b
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -30,10 +30,10 @@ long double _Q_sub(const long double a, const long double b)
long double c;
FP_INIT_ROUNDMODE;
FP_UNPACK_Q(A, a);
FP_UNPACK_Q(B, b);
FP_UNPACK_SEMIRAW_Q(A, a);
FP_UNPACK_SEMIRAW_Q(B, b);
FP_SUB_Q(C, A, B);
FP_PACK_Q(c, C);
FP_PACK_SEMIRAW_Q(c, C);
FP_HANDLE_EXCEPTIONS;
return c;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -23,15 +23,15 @@
#include "soft-fp.h"
#include "quad.h"
long double _Q_uxtoq(const unsigned long long a)
long double _Q_ulltoq(const unsigned long long a)
{
FP_DECL_EX;
FP_DECL_Q(C);
long double c;
unsigned long long b = a;
FP_FROM_INT_Q(C, b, 64, long long);
FP_PACK_Q(c, C);
FP_FROM_INT_Q(C, b, 64, unsigned long long);
FP_PACK_RAW_Q(c, C);
FP_CLEAR_EXCEPTIONS;
FP_HANDLE_EXCEPTIONS;
return c;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
c = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -23,15 +23,15 @@
#include "soft-fp.h"
#include "quad.h"
long double _Q_uitoq(const unsigned int a)
long double _Q_utoq(const unsigned int a)
{
FP_DECL_EX;
FP_DECL_Q(C);
long double c;
unsigned int b = a;
FP_FROM_INT_Q(C, b, 32, int);
FP_PACK_Q(c, C);
FP_FROM_INT_Q(C, b, 32, unsigned int);
FP_PACK_RAW_Q(c, C);
FP_CLEAR_EXCEPTIONS;
FP_HANDLE_EXCEPTIONS;
return c;

View File

@@ -1,6 +1,6 @@
/* Machine-dependent software floating-point definitions.
Sparc userland (_Q_*) version.
Copyright (C) 1997,1998,1999, 2002 Free Software Foundation, Inc.
Copyright (C) 1997,1998,1999, 2002, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com),
Jakub Jelinek (jj@ultra.linux.cz) and
@@ -22,6 +22,7 @@
02111-1307 USA. */
#include <fpu_control.h>
#include <stdlib.h>
#define _FP_W_TYPE_SIZE 32
#define _FP_W_TYPE unsigned long
@@ -208,14 +209,5 @@ do { \
" : : "r" (___Q_numbers) : "f30"); \
} \
else \
{ \
__asm__ __volatile__("\
mov %0, %%o0\n\
mov %%o7, %%g1\n\
call ___Q_simulate_exceptions\n\
mov %%g1, %%o7\
" : : "r" (_fex) : \
"g1", "g2", "g3", "g4", "g5", "o0", \
"o1", "o2", "o3", "o4", "o5", "cc"); \
} \
___Q_simulate_exceptions (_fex); \
} while (0)

View File

@@ -1,6 +0,0 @@
urem.S
umul.S
udiv.S
sdiv.S
rem.S
dotmul.S

View File

@@ -1,7 +0,0 @@
dotmul.S
hp-timing.c
rem.S
sdiv.S
udiv.S
umul.S
urem.S

View File

@@ -1,5 +1,5 @@
/* Atomic operations. sparcv9 version.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@@ -59,7 +59,7 @@ typedef uintmax_t uatomic_max_t;
__asm __volatile ("cas [%4], %2, %0" \
: "=r" (__acev_tmp), "=m" (*__acev_mem) \
: "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem), \
"0" (newval)); \
"0" (newval) : "memory"); \
__acev_tmp; })
/* This can be implemented if needed. */
@@ -74,11 +74,17 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*(mem)) == 4) \
__asm ("swap %0, %1" \
: "=m" (*__memp), "=r" (__oldval) \
: "m" (*__memp), "1" (__value)); \
: "m" (*__memp), "1" (__value) : "memory"); \
else \
abort (); \
__oldval; })
#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
#define atomic_exchange_24_rel(mem, newval) \
atomic_exchange_rel (mem, newval)
#define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \
" | #StoreLoad | #StoreStore" : : : "memory")

View File

@@ -1 +0,0 @@
sparc/sparc32/sparcv9

View File

@@ -0,0 +1,2 @@
#define XCC icc
#include <sparc64/sparcv9v/memcpy.S>

View File

@@ -0,0 +1,2 @@
#define XCC icc
#include <sparc64/sparcv9v/memset.S>

View File

@@ -38,7 +38,13 @@
.text
.align 4
10: ldub [%o1], %o5
ENTRY(__stpcpy)
andcc %o1, 3, %g0
be 20f
sethi %hi(0x80808080), %o4
ldub [%o1], %o5
stb %o5, [%o0]
cmp %o5, 0
add %o0, 1, %o0
@@ -67,11 +73,7 @@
1: retl
add %o0, -1, %o0
ENTRY(__stpcpy)
andcc %o1, 3, %g0
bne 10b
sethi %hi(0x80808080), %o4
or %o4, %lo(0x80808080), %o3
20: or %o4, %lo(0x80808080), %o3
4: sethi %hi(0x01010101), %o4
5: or %o4, %lo(0x01010101), %o2
6: andcc %o0, 3, %g0
@@ -160,6 +162,6 @@ ENTRY(__stpcpy)
nop
END(__stpcpy)
weak_alias(__stpcpy, stpcpy)
weak_alias (__stpcpy, stpcpy)
libc_hidden_def (__stpcpy)
libc_hidden_builtin_def (stpcpy)

View File

@@ -38,36 +38,14 @@
.text
.align 4
10: cmp %o4, 2
be 1f
cmp %o4, 3
ldub [%o1], %o5
add %o1, 1, %o1
stb %o5, [%o0]
be 3f
cmp %o5, 0
be 0f
add %o0, 1, %o0
1: lduh [%o1], %o5
add %o1, 2, %o1
srl %o5, 8, %o4
cmp %o4, 0
stb %o4, [%o0]
bne,a 2f
stb %o5, [%o0 + 1]
retl
mov %g2, %o0
2: andcc %o5, 0xff, %o5
bne 4f
add %o0, 2, %o0
retl
mov %g2, %o0
3: bne 4f
add %o0, 1, %o0
retl
mov %g2, %o0
11: ldub [%o0], %o5
ENTRY(strcat)
mov %o0, %g2
andcc %o0, 3, %g0
be 30f
sethi %hi(0x80808080), %o4
ldub [%o0], %o5
cmp %o5, 0
be 1f
add %o0, 1, %o0
@@ -93,12 +71,7 @@
b 3f
sub %o0, 1, %o0
ENTRY(strcat)
mov %o0, %g2
andcc %o0, 3, %g0
bne 11b
sethi %hi(0x80808080), %o4
or %o4, %lo(0x80808080), %o3
30: or %o4, %lo(0x80808080), %o3
7: sethi %hi(0x01010101), %o4
8: or %o4, %lo(0x01010101), %o2
9: ld [%o0], %o5
@@ -128,8 +101,39 @@ ENTRY(strcat)
ld [%o0], %o5
sub %o0, 1, %o0
3: andcc %o1, 3, %o4
bne 10b
4: andcc %o0, 3, %g3
be 4f
nop
cmp %o4, 2
be 11f
cmp %o4, 3
ldub [%o1], %o5
add %o1, 1, %o1
stb %o5, [%o0]
be 13f
cmp %o5, 0
be 0f
add %o0, 1, %o0
11: lduh [%o1], %o5
add %o1, 2, %o1
srl %o5, 8, %o4
cmp %o4, 0
stb %o4, [%o0]
bne,a 12f
stb %o5, [%o0 + 1]
retl
mov %g2, %o0
12: andcc %o5, 0xff, %o5
bne 4f
add %o0, 2, %o0
retl
mov %g2, %o0
13: bne 4f
add %o0, 1, %o0
retl
mov %g2, %o0
4: andcc %o0, 3, %g3
bne 12f
1: ld [%o1], %o5
add %o1, 4, %o1

View File

@@ -39,36 +39,6 @@
.text
.align 4
10: ldub [%o0], %g4
cmp %g4, %o1
be 1f
add %o0, 1, %o0
cmp %g4, 0
be 9f
andcc %o0, 3, %g0
be 4f
or %o4, %lo(0x80808080), %o3
ldub [%o0], %g4
cmp %g4, %o1
be 1f
add %o0, 1, %o0
cmp %g4, 0
be 9f
andcc %o0, 3, %g0
be 5f
sethi %hi(0x01010101), %o5
ldub [%o0], %g4
cmp %g4, %o1
be 1f
add %o0, 1, %o0
cmp %g4, 0
be 9f
or %o5, %lo(0x01010101), %o2
b 6f
ld [%o0], %g4
1: retl
sub %o0, 1, %o0
ENTRY(strchr)
andcc %o1, 0xff, %o1
be 12f
@@ -77,9 +47,40 @@ ENTRY(strchr)
or %o1, %o2, %o2
sethi %hi(0x80808080), %o4
sll %o2, 16, %o3
bne 10b
be 13f
or %o3, %o2, %g2
or %o4, %lo(0x80808080), %o3
ldub [%o0], %g4
cmp %g4, %o1
be 11f
add %o0, 1, %o0
cmp %g4, 0
be 9f
andcc %o0, 3, %g0
be 4f
or %o4, %lo(0x80808080), %o3
ldub [%o0], %g4
cmp %g4, %o1
be 11f
add %o0, 1, %o0
cmp %g4, 0
be 9f
andcc %o0, 3, %g0
be 5f
sethi %hi(0x01010101), %o5
ldub [%o0], %g4
cmp %g4, %o1
be 11f
add %o0, 1, %o0
cmp %g4, 0
be 9f
or %o5, %lo(0x01010101), %o2
b 6f
ld [%o0], %g4
11: retl
sub %o0, 1, %o0
13: or %o4, %lo(0x80808080), %o3
4: sethi %hi(0x01010101), %o5
5: or %o5, %lo(0x01010101), %o2
7: ld [%o0], %g4
@@ -278,7 +279,7 @@ ENTRY(strrchr)
mov %o5, %o0
END(strrchr)
weak_alias(strchr, index)
weak_alias(strrchr, rindex)
weak_alias (strchr, index)
weak_alias (strrchr, rindex)
libc_hidden_builtin_def (strchr)
libc_hidden_builtin_def (strrchr)

View File

@@ -38,7 +38,13 @@
.text
.align 4
10: ldub [%o0], %o4
ENTRY(strcmp)
andcc %o0, 3, %g0
be 13f
sethi %hi(0x80808080), %g1
ldub [%o0], %o4
add %o0, 1, %o0
ldub [%o1], %o5
cmp %o4, 0
@@ -76,11 +82,7 @@
2: retl
mov %o4, %o0
ENTRY(strcmp)
andcc %o0, 3, %g0
bne 10b
sethi %hi(0x80808080), %g1
or %g1, %lo(0x80808080), %o3
13: or %g1, %lo(0x80808080), %o3
4: sethi %hi(0x01010101), %g1
5: andcc %o1, 3, %g2
bne 12f

View File

@@ -38,7 +38,14 @@
.text
.align 4
1: ldub [%o1], %o5
ENTRY(strcpy)
mov %o0, %g2
andcc %o1, 3, %g0
be 10f
sethi %hi(0x80808080), %o4
ldub [%o1], %o5
stb %o5, [%o0]
cmp %o5, 0
add %o0, 1, %o0
@@ -65,12 +72,7 @@
b 6f
andcc %o0, 3, %g3
ENTRY(strcpy)
mov %o0, %g2
andcc %o1, 3, %g0
bne 1b
sethi %hi(0x80808080), %o4
or %o4, %lo(0x80808080), %o3
10: or %o4, %lo(0x80808080), %o3
4: sethi %hi(0x01010101), %o4
5: andcc %o0, 3, %g3
6: bne 10f

View File

@@ -38,39 +38,41 @@
.text
.align 4
10: ldub [%o0], %o5
ENTRY(strlen)
mov %o0, %o1
andcc %o0, 3, %g0
be 20f
sethi %hi(0x80808080), %o4
ldub [%o0], %o5
cmp %o5, 0
be 1f
be 21f
add %o0, 1, %o0
andcc %o0, 3, %g0
be 4f
or %o4, %lo(0x80808080), %o3
ldub [%o0], %o5
cmp %o5, 0
be 2f
be 22f
add %o0, 1, %o0
andcc %o0, 3, %g0
be 5f
sethi %hi(0x01010101), %o4
ldub [%o0], %o5
cmp %o5, 0
be 3f
be 23f
add %o0, 1, %o0
b 11f
or %o4, %lo(0x01010101), %o2
1: retl
21: retl
mov 0, %o0
2: retl
22: retl
mov 1, %o0
3: retl
23: retl
mov 2, %o0
ENTRY(strlen)
mov %o0, %o1
andcc %o0, 3, %g0
bne 10b
sethi %hi(0x80808080), %o4
or %o4, %lo(0x80808080), %o3
20: or %o4, %lo(0x80808080), %o3
4: sethi %hi(0x01010101), %o4
5: or %o4, %lo(0x01010101), %o2
11: ld [%o0], %o5

View File

@@ -1 +0,0 @@
hp-timing.c

View File

@@ -1,6 +1,3 @@
# The Sparc `long double' is a distinct type we support.
long-double-fcts = yes
ifeq ($(subdir),csu)
sysdep_routines += hp-timing
elide-routines.os += hp-timing

View File

@@ -5,3 +5,10 @@ libc {
__align_cpy_8; __align_cpy_16;
}
}
libm {
GLIBC_2.1 {
# A generic bug got this omitted from other configurations' version
# sets, but we always had it.
exp2l;
}
}

View File

@@ -1,5 +1,5 @@
/* Atomic operations. sparc64 version.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@@ -59,7 +59,7 @@ typedef uintmax_t uatomic_max_t;
__asm __volatile ("cas [%4], %2, %0" \
: "=r" (__acev_tmp), "=m" (*__acev_mem) \
: "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem), \
"0" (newval)); \
"0" (newval) : "memory"); \
__acev_tmp; })
#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
@@ -69,7 +69,7 @@ typedef uintmax_t uatomic_max_t;
__asm __volatile ("casx [%4], %2, %0" \
: "=r" (__acev_tmp), "=m" (*__acev_mem) \
: "r" ((long) (oldval)), "m" (*__acev_mem), \
"r" (__acev_mem), "0" ((long) (newval))); \
"r" (__acev_mem), "0" ((long) (newval)) : "memory"); \
__acev_tmp; })
#define atomic_exchange_acq(mem, newvalue) \
@@ -80,7 +80,7 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*(mem)) == 4) \
__asm ("swap %0, %1" \
: "=m" (*__memp), "=r" (__oldval) \
: "m" (*__memp), "1" (__value)); \
: "m" (*__memp), "1" (__value) : "memory"); \
else \
{ \
__val = *__memp; \
@@ -94,6 +94,12 @@ typedef uintmax_t uatomic_max_t;
} \
__oldval; })
#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
#define atomic_exchange_24_rel(mem, newval) \
atomic_exchange_rel (mem, newval)
#define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \
" | #StoreLoad | #StoreStore" : : : "memory")

View File

@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. Sparc64 version.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -18,6 +18,9 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef dl_machine_h
#define dl_machine_h
#define ELF_MACHINE_NAME "sparc64"
#include <string.h>
@@ -88,7 +91,7 @@ elf_machine_load_address (void)
/* We have 4 cases to handle. And we code different code sequences
for each one. I love V9 code models... */
static inline void
static inline void __attribute__ ((always_inline))
sparc64_fixup_plt (struct link_map *map, const Elf64_Rela *reloc,
Elf64_Addr *reloc_addr, Elf64_Addr value,
Elf64_Addr high, int t)
@@ -212,7 +215,7 @@ sparc64_fixup_plt (struct link_map *map, const Elf64_Rela *reloc,
}
}
static inline Elf64_Addr
static inline Elf64_Addr __attribute__ ((always_inline))
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf64_Rela *reloc,
Elf64_Addr *reloc_addr, Elf64_Addr value)
@@ -233,236 +236,21 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
return value;
}
#ifdef RESOLVE
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
static inline void
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version,
void *const reloc_addr_arg)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))
*reloc_addr = map->l_addr + reloc->r_addend;
# ifndef RTLD_BOOTSTRAP
else if (r_type == R_SPARC_NONE) /* Who is Wilbur? */
return;
# endif
else
#endif
{
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
const Elf64_Sym *const refsym = sym;
#endif
Elf64_Addr value;
#ifndef RESOLVE_CONFLICT_FIND_MAP
if (sym->st_shndx != SHN_UNDEF &&
ELF64_ST_BIND (sym->st_info) == STB_LOCAL)
value = map->l_addr;
else
{
value = RESOLVE (&sym, version, r_type);
if (sym)
value += sym->st_value;
}
#else
value = 0;
#endif
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
switch (r_type)
{
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
case R_SPARC_COPY:
if (sym == NULL)
/* This can happen in trace mode if an object could not be
found. */
break;
if (sym->st_size > refsym->st_size
|| (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
{
const char *strtab;
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
_dl_error_printf ("\
%s: Symbol `%s' has different size in shared object, consider re-linking\n",
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
}
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break;
#endif
case R_SPARC_64:
case R_SPARC_GLOB_DAT:
*reloc_addr = value;
break;
#ifndef RTLD_BOOTSTRAP
case R_SPARC_8:
*(char *) reloc_addr = value;
break;
case R_SPARC_16:
*(short *) reloc_addr = value;
break;
case R_SPARC_32:
*(unsigned int *) reloc_addr = value;
break;
case R_SPARC_DISP8:
*(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
break;
case R_SPARC_DISP16:
*(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
break;
case R_SPARC_DISP32:
*(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
break;
case R_SPARC_WDISP30:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xc0000000) |
((value - (Elf64_Addr) reloc_addr) >> 2));
break;
/* MEDLOW code model relocs */
case R_SPARC_LO10:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x3ff) |
(value & 0x3ff));
break;
case R_SPARC_HI22:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
(value >> 10));
break;
case R_SPARC_OLO10:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x1fff) |
(((value & 0x3ff) + ELF64_R_TYPE_DATA (reloc->r_info)) & 0x1fff));
break;
/* MEDMID code model relocs */
case R_SPARC_H44:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
(value >> 22));
break;
case R_SPARC_M44:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x3ff) |
((value >> 12) & 0x3ff));
break;
case R_SPARC_L44:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0xfff) |
(value & 0xfff));
break;
/* MEDANY code model relocs */
case R_SPARC_HH22:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
(value >> 42));
break;
case R_SPARC_HM10:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x3ff) |
((value >> 32) & 0x3ff));
break;
case R_SPARC_LM22:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
((value >> 10) & 0x003fffff));
break;
#endif
case R_SPARC_JMP_SLOT:
#ifdef RESOLVE_CONFLICT_FIND_MAP
/* R_SPARC_JMP_SLOT conflicts against .plt[32768+]
relocs should be turned into R_SPARC_64 relocs
in .gnu.conflict section.
r_addend non-zero does not mean it is a .plt[32768+]
reloc, instead it is the actual address of the function
to call. */
sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
#else
sparc64_fixup_plt (map, reloc, reloc_addr, value,
reloc->r_addend, 0);
#endif
break;
#ifndef RTLD_BOOTSTRAP
case R_SPARC_UA16:
((unsigned char *) reloc_addr_arg) [0] = value >> 8;
((unsigned char *) reloc_addr_arg) [1] = value;
break;
case R_SPARC_UA32:
((unsigned char *) reloc_addr_arg) [0] = value >> 24;
((unsigned char *) reloc_addr_arg) [1] = value >> 16;
((unsigned char *) reloc_addr_arg) [2] = value >> 8;
((unsigned char *) reloc_addr_arg) [3] = value;
break;
case R_SPARC_UA64:
if (! ((long) reloc_addr_arg & 3))
{
/* Common in .eh_frame */
((unsigned int *) reloc_addr_arg) [0] = value >> 32;
((unsigned int *) reloc_addr_arg) [1] = value;
break;
}
((unsigned char *) reloc_addr_arg) [0] = value >> 56;
((unsigned char *) reloc_addr_arg) [1] = value >> 48;
((unsigned char *) reloc_addr_arg) [2] = value >> 40;
((unsigned char *) reloc_addr_arg) [3] = value >> 32;
((unsigned char *) reloc_addr_arg) [4] = value >> 24;
((unsigned char *) reloc_addr_arg) [5] = value >> 16;
((unsigned char *) reloc_addr_arg) [6] = value >> 8;
((unsigned char *) reloc_addr_arg) [7] = value;
break;
#endif
#if !defined RTLD_BOOTSTRAP || defined _NDEBUG
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
#endif
}
}
}
static inline void
elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
void *const reloc_addr_arg)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
*reloc_addr = l_addr + reloc->r_addend;
}
static inline void
elf_machine_lazy_rel (struct link_map *map,
Elf64_Addr l_addr, const Elf64_Rela *reloc)
{
switch (ELF64_R_TYPE (reloc->r_info))
{
case R_SPARC_NONE:
break;
case R_SPARC_JMP_SLOT:
break;
default:
_dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 1);
break;
}
}
#endif /* RESOLVE */
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
PLT entries should not be allowed to define the value.
ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
of the main executable's symbols, as for a COPY reloc. */
#define elf_machine_type_class(type) \
#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
# define elf_machine_type_class(type) \
((((type) == R_SPARC_JMP_SLOT \
|| ((type) >= R_SPARC_TLS_GD_HI22 && (type) <= R_SPARC_TLS_TPOFF64)) \
* ELF_RTYPE_CLASS_PLT) \
| (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
#else
# define elf_machine_type_class(type) \
((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
#endif
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
#define ELF_MACHINE_JMP_SLOT R_SPARC_JMP_SLOT
@@ -487,74 +275,67 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
extern void _dl_runtime_profile_1 (void);
Elf64_Addr res0_addr, res1_addr;
unsigned int *plt = (void *) D_PTR (l, l_info[DT_PLTGOT]);
int i = 0;
if (! profile)
if (__builtin_expect(profile, 0))
{
res0_addr = (Elf64_Addr) &_dl_runtime_profile_0;
res1_addr = (Elf64_Addr) &_dl_runtime_profile_1;
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
GL(dl_profile_map) = l;
}
else
{
res0_addr = (Elf64_Addr) &_dl_runtime_resolve_0;
res1_addr = (Elf64_Addr) &_dl_runtime_resolve_1;
}
else
{
res0_addr = (Elf64_Addr) &_dl_runtime_profile_0;
res1_addr = (Elf64_Addr) &_dl_runtime_profile_1;
if (_dl_name_match_p (GLRO(dl_profile), l))
GL(dl_profile_map) = l;
}
/* PLT0 looks like:
save %sp, -192, %sp
sethi %hh(_dl_runtime_{resolve,profile}_0), %l0
sethi %lm(_dl_runtime_{resolve,profile}_0), %l1
or %l0, %hm(_dl_runtime_{resolve,profile}_0), %l0
or %l1, %lo(_dl_runtime_{resolve,profile}_0), %l1
sllx %l0, 32, %l0
jmpl %l0 + %l1, %l6
sethi %hi(0xffc00), %l2
sethi %uhi(_dl_runtime_{resolve,profile}_0), %g4
sethi %hi(_dl_runtime_{resolve,profile}_0), %g5
or %g4, %ulo(_dl_runtime_{resolve,profile}_0), %g4
or %g5, %lo(_dl_runtime_{resolve,profile}_0), %g5
sllx %g4, 32, %g4
add %g4, %g5, %g5
jmpl %g5, %g4
nop
*/
plt[0] = 0x9de3bf40;
plt[1] = 0x21000000 | (res0_addr >> (64 - 22));
plt[2] = 0x23000000 | ((res0_addr >> 10) & 0x003fffff);
plt[3] = 0xa0142000 | ((res0_addr >> 32) & 0x3ff);
plt[4] = 0xa2146000 | (res0_addr & 0x3ff);
plt[5] = 0xa12c3020;
plt[6] = 0xadc40011;
plt[7] = 0x250003ff;
plt[0] = 0x09000000 | (res0_addr >> (64 - 22));
plt[1] = 0x0b000000 | ((res0_addr >> 10) & 0x003fffff);
plt[2] = 0x88112000 | ((res0_addr >> 32) & 0x3ff);
plt[3] = 0x8a116000 | (res0_addr & 0x3ff);
plt[4] = 0x89293020;
plt[5] = 0x8a010005;
plt[6] = 0x89c14000;
plt[7] = 0x01000000;
/* PLT1 looks like:
save %sp, -192, %sp
sethi %hh(_dl_runtime_{resolve,profile}_1), %l0
sethi %lm(_dl_runtime_{resolve,profile}_1), %l1
or %l0, %hm(_dl_runtime_{resolve,profile}_1), %l0
or %l1, %lo(_dl_runtime_{resolve,profile}_1), %l1
sllx %l0, 32, %l0
jmpl %l0 + %l1, %l6
srlx %g1, 12, %o1
sethi %uhi(_dl_runtime_{resolve,profile}_1), %g4
sethi %hi(_dl_runtime_{resolve,profile}_1), %g5
or %g4, %ulo(_dl_runtime_{resolve,profile}_1), %g4
or %g5, %lo(_dl_runtime_{resolve,profile}_1), %g5
sllx %g4, 32, %g4
add %g4, %g5, %g5
jmpl %g5, %g4
nop
*/
plt[8 + 0] = 0x9de3bf40;
if (__builtin_expect (((res1_addr + 4) >> 32) & 0x3ff, 0))
i = 1;
else
res1_addr += 4;
plt[8 + 1] = 0x21000000 | (res1_addr >> (64 - 22));
plt[8 + 2] = 0x23000000 | ((res1_addr >> 10) & 0x003fffff);
if (__builtin_expect (i, 0))
plt[8 + 3] = 0xa0142000 | ((res1_addr >> 32) & 0x3ff);
else
plt[8 + 3] = 0xa12c3020;
plt[8 + 4] = 0xa2146000 | (res1_addr & 0x3ff);
if (__builtin_expect (i, 0))
plt[8 + 5] = 0xa12c3020;
plt[8 + 5 + i] = 0xadc40011;
plt[8 + 6 + i] = 0x9330700c;
plt[8] = 0x09000000 | (res1_addr >> (64 - 22));
plt[9] = 0x0b000000 | ((res1_addr >> 10) & 0x003fffff);
plt[10] = 0x88112000 | ((res1_addr >> 32) & 0x3ff);
plt[11] = 0x8a116000 | (res1_addr & 0x3ff);
plt[12] = 0x89293020;
plt[13] = 0x8a010005;
plt[14] = 0x89c14000;
plt[15] = 0x01000000;
/* Now put the magic cookie at the beginning of .PLT2
Entry .PLT3 is unused by this implementation. */
*((struct link_map **)(&plt[16 + 0])) = l;
*((struct link_map **)(&plt[16])) = l;
if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
|| __builtin_expect (l->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL, 0))
@@ -601,68 +382,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
/* This code is used in dl-runtime.c to call the `fixup' function
and then redirect to the address it returns. */
#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
asm ("\n" \
" .text\n" \
" .globl " #tramp_name "_0\n" \
" .type " #tramp_name "_0, @function\n" \
" .align 32\n" \
"\t" #tramp_name "_0:\n" \
" ! sethi %hi(1047552), %l2 - Done in .PLT0\n" \
" ldx [%l6 + 32 + 8], %o0\n" \
" sub %g1, %l6, %l0\n" \
" xor %l2, -1016, %l2\n" \
" sethi %hi(5120), %l3 ! 160 * 32\n" \
" add %l0, %l2, %l0\n" \
" sethi %hi(32768), %l4\n" \
" udivx %l0, %l3, %l3\n" \
" sllx %l3, 2, %l1\n" \
" add %l1, %l3, %l1\n" \
" sllx %l1, 10, %l2\n" \
" sub %l4, 4, %l4 ! No thanks to Sun for not obeying their own ABI\n" \
" sllx %l1, 5, %l1\n" \
" sub %l0, %l2, %l0\n" \
" udivx %l0, 24, %l0\n" \
" add %l0, %l4, %l0\n" \
" add %l1, %l0, %l1\n" \
" add %l1, %l1, %l0\n" \
" add %l0, %l1, %l0\n" \
" mov %i7, %o2\n" \
" call " #fixup_name "\n" \
" sllx %l0, 3, %o1\n" \
" jmp %o0\n" \
" restore\n" \
" .size " #tramp_name "_0, . - " #tramp_name "_0\n" \
"\n" \
" .globl " #tramp_name "_1\n" \
" .type " #tramp_name "_1, @function\n" \
" ! tramp_name_1 + 4 needs to be .align 32\n" \
"\t" #tramp_name "_1:\n" \
" sub %l6, 4, %l6\n" \
" ! srlx %g1, 12, %o1 - Done in .PLT1\n" \
" ldx [%l6 + 12], %o0\n" \
" add %o1, %o1, %o3\n" \
" sub %o1, 96, %o1 ! No thanks to Sun for not obeying their own ABI\n" \
" mov %i7, %o2\n" \
" call " #fixup_name "\n" \
" add %o1, %o3, %o1\n" \
" jmp %o0\n" \
" restore\n" \
" .size " #tramp_name "_1, . - " #tramp_name "_1\n" \
" .previous\n");
#ifndef PROF
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
#else
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
TRAMPOLINE_TEMPLATE (_dl_runtime_profile, fixup);
#endif
/* The PLT uses Elf64_Rela relocs. */
#define elf_machine_relplt elf_machine_rela
@@ -763,3 +482,291 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
" add %sp, 6*8, %sp\n" \
" .size _dl_start_user, . - _dl_start_user\n" \
" .previous\n");
#endif /* dl_machine_h */
#define ARCH_LA_PLTENTER sparc64_gnu_pltenter
#define ARCH_LA_PLTEXIT sparc64_gnu_pltexit
#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version,
void *const reloc_addr_arg)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
const Elf64_Sym *const refsym = sym;
#endif
Elf64_Addr value;
const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);
#if !defined RESOLVE_CONFLICT_FIND_MAP
struct link_map *sym_map = NULL;
#endif
#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
/* This is defined in rtld.c, but nowhere in the static libc.a; make the
reference weak so static programs can still link. This declaration
cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP)
because rtld.c contains the common defn for _dl_rtld_map, which is
incompatible with a weak decl in the same file. */
weak_extern (_dl_rtld_map);
#endif
if (__builtin_expect (r_type == R_SPARC_NONE, 0))
return;
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))
{
# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
if (map != &_dl_rtld_map) /* Already done in rtld itself. */
# endif
*reloc_addr += map->l_addr + reloc->r_addend;
return;
}
#endif
#ifndef RESOLVE_CONFLICT_FIND_MAP
if (__builtin_expect (ELF64_ST_BIND (sym->st_info) == STB_LOCAL, 0)
&& sym->st_shndx != SHN_UNDEF)
{
value = map->l_addr;
}
else
{
sym_map = RESOLVE_MAP (&sym, version, r_type);
value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
}
#else
value = 0;
#endif
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
switch (r_type)
{
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
case R_SPARC_COPY:
if (sym == NULL)
/* This can happen in trace mode if an object could not be
found. */
break;
if (sym->st_size > refsym->st_size
|| (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
{
const char *strtab;
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
_dl_error_printf ("\
%s: Symbol `%s' has different size in shared object, consider re-linking\n",
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
}
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break;
#endif
case R_SPARC_64:
case R_SPARC_GLOB_DAT:
*reloc_addr = value;
break;
case R_SPARC_JMP_SLOT:
#ifdef RESOLVE_CONFLICT_FIND_MAP
/* R_SPARC_JMP_SLOT conflicts against .plt[32768+]
relocs should be turned into R_SPARC_64 relocs
in .gnu.conflict section.
r_addend non-zero does not mean it is a .plt[32768+]
reloc, instead it is the actual address of the function
to call. */
sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
#else
sparc64_fixup_plt (map, reloc, reloc_addr, value, reloc->r_addend, 0);
#endif
break;
#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \
&& !defined RESOLVE_CONFLICT_FIND_MAP
case R_SPARC_TLS_DTPMOD64:
/* Get the information from the link map returned by the
resolv function. */
if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid;
break;
case R_SPARC_TLS_DTPOFF64:
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
*reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
break;
case R_SPARC_TLS_TPOFF64:
/* The offset is negative, forward from the thread pointer. */
/* We know the offset of object the symbol is contained in.
It is a negative value which will be added to the
thread pointer. */
if (sym != NULL)
{
CHECK_STATIC_TLS (map, sym_map);
*reloc_addr = sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend;
}
break;
# ifndef RTLD_BOOTSTRAP
case R_SPARC_TLS_LE_HIX22:
case R_SPARC_TLS_LE_LOX10:
if (sym != NULL)
{
CHECK_STATIC_TLS (map, sym_map);
value = sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend;
if (r_type == R_SPARC_TLS_LE_HIX22)
*reloc_addr = (*reloc_addr & 0xffc00000)
| (((~value) >> 10) & 0x3fffff);
else
*reloc_addr = (*reloc_addr & 0xffffe000) | (value & 0x3ff)
| 0x1c00;
}
break;
# endif
#endif
#ifndef RTLD_BOOTSTRAP
case R_SPARC_8:
*(char *) reloc_addr = value;
break;
case R_SPARC_16:
*(short *) reloc_addr = value;
break;
case R_SPARC_32:
*(unsigned int *) reloc_addr = value;
break;
case R_SPARC_DISP8:
*(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
break;
case R_SPARC_DISP16:
*(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
break;
case R_SPARC_DISP32:
*(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
break;
case R_SPARC_WDISP30:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xc0000000) |
(((value - (Elf64_Addr) reloc_addr) >> 2) & 0x3fffffff));
break;
/* MEDLOW code model relocs */
case R_SPARC_LO10:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x3ff) |
(value & 0x3ff));
break;
case R_SPARC_HI22:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
((value >> 10) & 0x3fffff));
break;
case R_SPARC_OLO10:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x1fff) |
(((value & 0x3ff) + ELF64_R_TYPE_DATA (reloc->r_info)) & 0x1fff));
break;
/* MEDMID code model relocs */
case R_SPARC_H44:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
((value >> 22) & 0x3fffff));
break;
case R_SPARC_M44:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x3ff) |
((value >> 12) & 0x3ff));
break;
case R_SPARC_L44:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0xfff) |
(value & 0xfff));
break;
/* MEDANY code model relocs */
case R_SPARC_HH22:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
(value >> 42));
break;
case R_SPARC_HM10:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & ~0x3ff) |
((value >> 32) & 0x3ff));
break;
case R_SPARC_LM22:
*(unsigned int *) reloc_addr =
((*(unsigned int *)reloc_addr & 0xffc00000) |
((value >> 10) & 0x003fffff));
break;
case R_SPARC_UA16:
((unsigned char *) reloc_addr_arg) [0] = value >> 8;
((unsigned char *) reloc_addr_arg) [1] = value;
break;
case R_SPARC_UA32:
((unsigned char *) reloc_addr_arg) [0] = value >> 24;
((unsigned char *) reloc_addr_arg) [1] = value >> 16;
((unsigned char *) reloc_addr_arg) [2] = value >> 8;
((unsigned char *) reloc_addr_arg) [3] = value;
break;
case R_SPARC_UA64:
if (! ((long) reloc_addr_arg & 3))
{
/* Common in .eh_frame */
((unsigned int *) reloc_addr_arg) [0] = value >> 32;
((unsigned int *) reloc_addr_arg) [1] = value;
break;
}
((unsigned char *) reloc_addr_arg) [0] = value >> 56;
((unsigned char *) reloc_addr_arg) [1] = value >> 48;
((unsigned char *) reloc_addr_arg) [2] = value >> 40;
((unsigned char *) reloc_addr_arg) [3] = value >> 32;
((unsigned char *) reloc_addr_arg) [4] = value >> 24;
((unsigned char *) reloc_addr_arg) [5] = value >> 16;
((unsigned char *) reloc_addr_arg) [6] = value >> 8;
((unsigned char *) reloc_addr_arg) [7] = value;
break;
#endif
#if !defined RTLD_BOOTSTRAP || defined _NDEBUG
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
#endif
}
}
auto inline void
__attribute__ ((always_inline))
elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
void *const reloc_addr_arg)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
*reloc_addr = l_addr + reloc->r_addend;
}
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
Elf64_Addr l_addr, const Elf64_Rela *reloc)
{
switch (ELF64_R_TYPE (reloc->r_info))
{
case R_SPARC_NONE:
break;
case R_SPARC_JMP_SLOT:
break;
default:
_dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 1);
break;
}
}
#endif /* RESOLVE_MAP */

View File

@@ -0,0 +1,327 @@
/* PLT trampolines. Sparc 64-bit version.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
.text
.align 32
/* %g1: PLT offset loaded by PLT entry
* %g4: callers PC, which is PLT0 + 24, therefore we
* add (32 + 8) to get the address of PLT2 which
* is where the magic cookie is stored
*/
.globl _dl_runtime_resolve_0
.type _dl_runtime_resolve_0, @function
_dl_runtime_resolve_0:
cfi_startproc
save %sp, -192, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cfi_register(%o7, %i7)
sethi %hi(1047552), %l2
ldx [%g4 + 32 + 8], %o0
sub %g1, %g4, %l0
xor %l2, -1016, %l2
sethi %hi(5120), %l3 /* 160 * 32 */
add %l0, %l2, %l0
sethi %hi(32768), %l4
udivx %l0, %l3, %l3
sllx %l3, 2, %l1
add %l1, %l3, %l1
sllx %l1, 10, %l2
sub %l4, 4, %l4
sllx %l1, 5, %l1
sub %l0, %l2, %l0
udivx %l0, 24, %l0
add %l0, %l4, %l0
add %l1, %l0, %l1
add %l1, %l1, %l0
add %l0, %l1, %l0
call _dl_fixup
sllx %l0, 3, %o1
jmp %o0
restore
cfi_endproc
.size _dl_runtime_resolve_0, .-_dl_runtime_resolve_0
/* %g1: PLT offset loaded by PLT entry
* %g4: callers PC, which is PLT1 + 24, therefore we
* add 8 to get the address of PLT2 which
* is where the magic cookie is stored
*/
.globl _dl_runtime_resolve_1
.type _dl_runtime_resolve_1, @function
_dl_runtime_resolve_1:
cfi_startproc
save %sp, -192, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cfi_register(%o7, %i7)
srlx %g1, 12, %o1
ldx [%g4 + 8], %o0
add %o1, %o1, %o3
sub %o1, 96, %o1
call _dl_fixup
add %o1, %o3, %o1
jmp %o0
restore
cfi_endproc
.size _dl_runtime_resolve_1, .-_dl_runtime_resolve_1
/* For the profiling cases we pass in our stack frame
* as the base of the La_sparc64_regs, so it looks
* like:
* %l0 %sp
* ...
* %l7 %sp + (7 * 8)
* %i0 %sp + (8 * 8)
* ...
* %i7 %sp + (15 * 8)
* %f0 %sp + (16 * 8)
* %f16 %sp + (31 * 8)
* framesize %sp + (32 * 8)
*/
.globl _dl_profile_save_regs
.type _dl_profile_save_regs, @function
_dl_profile_save_regs:
cfi_startproc
stx %l0, [%sp + STACK_BIAS + ( 0 * 8)]
stx %l1, [%sp + STACK_BIAS + ( 1 * 8)]
stx %l2, [%sp + STACK_BIAS + ( 2 * 8)]
stx %l3, [%sp + STACK_BIAS + ( 3 * 8)]
stx %l4, [%sp + STACK_BIAS + ( 4 * 8)]
stx %l5, [%sp + STACK_BIAS + ( 5 * 8)]
stx %l6, [%sp + STACK_BIAS + ( 6 * 8)]
stx %l7, [%sp + STACK_BIAS + ( 7 * 8)]
stx %i0, [%sp + STACK_BIAS + ( 8 * 8)]
stx %i1, [%sp + STACK_BIAS + ( 9 * 8)]
stx %i2, [%sp + STACK_BIAS + (10 * 8)]
stx %i3, [%sp + STACK_BIAS + (11 * 8)]
stx %i4, [%sp + STACK_BIAS + (12 * 8)]
stx %i5, [%sp + STACK_BIAS + (13 * 8)]
stx %i6, [%sp + STACK_BIAS + (14 * 8)]
stx %i7, [%sp + STACK_BIAS + (15 * 8)]
std %f0, [%sp + STACK_BIAS + (16 * 8)]
std %f2, [%sp + STACK_BIAS + (17 * 8)]
std %f4, [%sp + STACK_BIAS + (18 * 8)]
std %f6, [%sp + STACK_BIAS + (19 * 8)]
std %f8, [%sp + STACK_BIAS + (20 * 8)]
std %f10, [%sp + STACK_BIAS + (21 * 8)]
std %f12, [%sp + STACK_BIAS + (22 * 8)]
std %f14, [%sp + STACK_BIAS + (23 * 8)]
std %f16, [%sp + STACK_BIAS + (24 * 8)]
std %f18, [%sp + STACK_BIAS + (25 * 8)]
std %f20, [%sp + STACK_BIAS + (26 * 8)]
std %f22, [%sp + STACK_BIAS + (27 * 8)]
std %f24, [%sp + STACK_BIAS + (28 * 8)]
std %f26, [%sp + STACK_BIAS + (29 * 8)]
std %f28, [%sp + STACK_BIAS + (30 * 8)]
retl
std %f30, [%sp + STACK_BIAS + (31 * 8)]
cfi_endproc
.size _dl_profile_save_regs, .-_dl_profile_save_regs
/* If we are going to call pltexit, then we must replicate
* the caller's stack frame.
* %o0: PLT resolved function address
*/
.globl _dl_profile_invoke
.type _dl_profile_invoke, @function
_dl_profile_invoke:
cfi_startproc
sub %sp, %l0, %sp
1:
srlx %l0, 3, %l7
mov %o0, %l1
mov %i0, %o0
mov %i1, %o1
mov %i2, %o2
mov %i3, %o3
mov %i4, %o4
mov %i5, %o5
add %fp, STACK_BIAS, %l2
add %sp, STACK_BIAS, %l3
1: ldx [%l2], %l4
add %l2, 0x8, %l2
subcc %l7, 1, %l7
stx %l4, [%l3]
bne,pt %xcc, 1b
add %l3, 0x8, %l3
jmpl %l1, %o7
nop
stx %o0, [%sp + STACK_BIAS + (16 * 8)]
stx %o1, [%sp + STACK_BIAS + (17 * 8)]
stx %o2, [%sp + STACK_BIAS + (18 * 8)]
stx %o3, [%sp + STACK_BIAS + (19 * 8)]
std %f0, [%sp + STACK_BIAS + (20 * 8)]
std %f2, [%sp + STACK_BIAS + (21 * 8)]
std %f4, [%sp + STACK_BIAS + (22 * 8)]
std %f8, [%sp + STACK_BIAS + (23 * 8)]
mov %l5, %o0
mov %l6, %o1
add %sp, %l0, %o2
add %sp, STACK_BIAS + (16 * 8), %o3
call _dl_call_pltexit
add %o2, STACK_BIAS, %o2
ldx [%sp + STACK_BIAS + (16 * 8)], %i0
ldx [%sp + STACK_BIAS + (17 * 8)], %i1
ldx [%sp + STACK_BIAS + (18 * 8)], %i2
ldx [%sp + STACK_BIAS + (19 * 8)], %i3
jmpl %i7 + 8, %g0
restore
cfi_endproc
.size _dl_profile_invoke, .-_dl_profile_invoke
/* %g1: PLT offset loaded by PLT entry
* %g4: callers PC, which is PLT0 + 24, therefore we
* add (32 + 8) to get the address of PLT2 which
* is where the magic cookie is stored
*/
.align 32
.globl _dl_runtime_profile_0
.type _dl_runtime_profile_0, @function
_dl_runtime_profile_0:
cfi_startproc
brz,a,pn %fp, 1f
mov 192, %g5
sub %fp, %sp, %g5
1: save %sp, -336, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cfi_register(%o7, %i7)
sethi %hi(1047552), %l2
ldx [%g4 + 32 + 8], %o0
sub %g1, %g4, %l0
xor %l2, -1016, %l2
sethi %hi(5120), %l3 /* 160 * 32 */
add %l0, %l2, %l0
sethi %hi(32768), %l4
udivx %l0, %l3, %l3
sllx %l3, 2, %l1
add %l1, %l3, %l1
sllx %l1, 10, %l2
sub %l4, 4, %l4
sllx %l1, 5, %l1
sub %l0, %l2, %l0
udivx %l0, 24, %l0
add %l0, %l4, %l0
add %l1, %l0, %l1
add %l1, %l1, %l0
add %l0, %l1, %l0
mov %i7, %o2
sllx %l0, 3, %o1
mov %g5, %l0
mov %o0, %l5
mov %o1, %l6
call _dl_profile_save_regs
nop
add %sp, STACK_BIAS, %o3
call _dl_profile_fixup
add %sp, (STACK_BIAS + (32 * 8)), %o4
ldx [%sp + STACK_BIAS + (32 * 8)], %o1
brgez,pt %o1, 1f
nop
call _dl_profile_invoke
nop
1: jmp %o0
restore
cfi_endproc
.size _dl_runtime_profile_0, .-_dl_runtime_profile_0
/* %g1: PLT offset loaded by PLT entry
* %g4: callers PC, which is PLT1 + 24, therefore we
* add 8 to get the address of PLT2 which
* is where the magic cookie is stored
*/
.globl _dl_runtime_profile_1
.type _dl_runtime_profile_1, @function
_dl_runtime_profile_1:
cfi_startproc
brz,a,pn %fp, 1f
mov 192, %g5
sub %fp, %sp, %g5
1: save %sp, -336, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
cfi_register(%o7, %i7)
srlx %g1, 12, %o1
ldx [%g4 + 8], %o0
add %o1, %o1, %o3
sub %o1, 96, %o1
mov %i7, %o2
add %o1, %o3, %o1
mov %g5, %l0
mov %o0, %l5
mov %o1, %l6
call _dl_profile_save_regs
nop
add %sp, STACK_BIAS, %o3
call _dl_profile_fixup
add %sp, (STACK_BIAS + (32 * 8)), %o4
ldx [%sp + STACK_BIAS + (32 * 8)], %o1
brgez,pt %o1, 1f
nop
call _dl_profile_invoke
nop
1: jmp %o0
restore
cfi_endproc
.size _dl_runtime_resolve_1, .-_dl_runtime_resolve_1

View File

@@ -48,6 +48,7 @@
.global _start
.type _start,#function
_start:
cfi_startproc
#ifdef SHARED
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7
@@ -59,6 +60,7 @@ _start:
drop their arguments. */
mov %g0, %fp
sub %sp, 6*8, %sp
cfi_adjust_cfa_offset(6*8)
/* Extract the arguments and environment as encoded on the stack. The
argument info starts after one register window (16 words) past the SP,
@@ -92,4 +94,12 @@ _start:
/* Die very horribly if exit returns. */
illtrap 0
cfi_endproc
.size _start, .-_start
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
weak_alias (__data_start, data_start)

View File

@@ -33,14 +33,14 @@ ildouble: 1
ldouble: 1
# cacosh
Test "Real part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
double: 1
float: 7
idouble: 1
ifloat: 7
ildouble: 5
ldouble: 5
Test "Imaginary part of: cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i":
Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
double: 1
float: 3
idouble: 1
@@ -465,6 +465,11 @@ ifloat: 2
ildouble: 1
ldouble: 1
# exp2
Test "exp2 (10) == 1024":
ildouble: 2
ldouble: 2
# expm1
Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
double: 1
@@ -1192,6 +1197,10 @@ ifloat: 2
ildouble: 1
ldouble: 1
Function: "exp2":
ildouble: 2
ldouble: 2
Function: "expm1":
double: 1
float: 1

View File

@@ -0,0 +1,37 @@
/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David S. Miller <davem@davemloft.net>, 2005.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
/* Test if longjmp to JMPBUF would unwind the frame
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
((unsigned long int) (address) < (jmpbuf)->uc_mcontext.mc_fp + 2047)
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) \
< (uintptr_t) (_jmpbuf)[0].uc_mcontext.mc_fp + 2047 - (_adj))
/* We use the normal lobngjmp for unwinding. */
#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)

View File

@@ -139,5 +139,5 @@ ENTRY(memcmp)
END(memcmp)
#undef bcmp
weak_alias(memcmp, bcmp)
weak_alias (memcmp, bcmp)
libc_hidden_builtin_def (memcmp)

View File

@@ -209,6 +209,7 @@ ENTRY(bcopy)
END(bcopy)
.align 32
ENTRY(__memcpy_large)
200: be,pt %xcc, 201f /* CTI */
andcc %o0, 0x38, %g5 /* IEU1 Group */
mov 8, %g1 /* IEU0 */
@@ -443,6 +444,7 @@ END(bcopy)
stb %o5, [%o0 - 1] /* Store */
209: retl
mov %g4, %o0
END(__memcpy_large)
#ifdef USE_BPR
@@ -698,6 +700,7 @@ ENTRY(memcpy)
END(memcpy)
.align 32
ENTRY(__memmove_slowpath)
228: andcc %o2, 1, %g0 /* IEU1 Group */
be,pt %icc, 2f+4 /* CTI */
1: ldub [%o1 - 1], %o5 /* LOAD Group */
@@ -718,6 +721,7 @@ END(memcpy)
mov %g4, %o0
219: retl
nop
END(__memmove_slowpath)
.align 32
ENTRY(memmove)
@@ -914,8 +918,8 @@ ENTRY(memmove)
END(memmove)
#ifdef USE_BPR
weak_alias(memcpy, __align_cpy_1)
weak_alias(memcpy, __align_cpy_2)
weak_alias (memcpy, __align_cpy_1)
weak_alias (memcpy, __align_cpy_2)
#endif
libc_hidden_builtin_def (memcpy)
libc_hidden_builtin_def (memmove)

View File

@@ -312,4 +312,4 @@ ENTRY(__bzero)
mov %o5, %o0
END(__bzero)
weak_alias(__bzero, bzero)
weak_alias (__bzero, bzero)

View File

@@ -1,32 +0,0 @@
qp_add.c
qp_cmp.c
qp_cmpe.c
qp_div.c
qp_dtoq.c
qp_feq.c
qp_fge.c
qp_fgt.c
qp_fle.c
qp_flt.c
qp_fne.c
qp_itoq.c
qp_mul.c
qp_neg.S
qp_qtod.c
qp_qtoi.c
qp_qtos.c
qp_qtoui.c
qp_qtoux.c
qp_qtox.c
qp_sqrt.c
qp_stoq.c
qp_sub.c
qp_uitoq.c
qp_util.c
qp_uxtoq.c
qp_xtoq.c
s_frexpl.c
s_ilogbl.c
s_scalblnl.c
s_scalbnl.c
sfp-machine.h

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (*a) + (*b)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,10 +29,10 @@ void _Qp_add(long double *c, const long double *a, const long double *b)
FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C);
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_QP(B, b);
FP_UNPACK_SEMIRAW_QP(A, a);
FP_UNPACK_SEMIRAW_QP(B, b);
FP_ADD_Q(C, A, B);
FP_PACK_QP(c, C);
FP_PACK_SEMIRAW_QP(c, C);
QP_HANDLE_EXCEPTIONS(__asm (
" ldd [%1], %%f52\n"
" ldd [%1+8], %%f54\n"

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,13 +31,13 @@ void _Qp_dtoq(long double *c, const double a)
FP_DECL_Q(C);
FP_INIT_ROUNDMODE;
FP_UNPACK_D(A, a);
FP_UNPACK_RAW_D(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(Q,D,4,2,C,A);
FP_EXTEND(Q,D,4,2,C,A);
#else
FP_CONV(Q,D,2,1,C,A);
FP_EXTEND(Q,D,2,1,C,A);
#endif
FP_PACK_QP(c, C);
FP_PACK_RAW_QP(c, C);
QP_HANDLE_EXCEPTIONS(__asm (
" fdtoq %1, %%f60\n"
" std %%f60, [%0]\n"

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_itoq(long double *c, const int a)
FP_DECL_Q(C);
int b = a;
FP_FROM_INT_Q(C, b, 32, int);
FP_PACK_QP(c, C);
FP_FROM_INT_Q(C, b, 32, unsigned int);
FP_PACK_RAW_QP(c, C);
QP_NO_EXCEPTIONS;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (double)(*a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ double _Qp_qtod(const long double *a)
double r;
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_SEMIRAW_QP(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(D,Q,2,4,R,A);
FP_TRUNC(D,Q,2,4,R,A);
#else
FP_CONV(D,Q,1,2,R,A);
FP_TRUNC(D,Q,1,2,R,A);
#endif
FP_PACK_D(r, R);
FP_PACK_SEMIRAW_D(r, R);
QP_HANDLE_EXCEPTIONS(__asm (
" ldd [%1], %%f52\n"
" ldd [%1+8], %%f54\n"

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (int)(*a)
Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -28,10 +28,10 @@ int _Qp_qtoi(const long double *a)
{
FP_DECL_EX;
FP_DECL_Q(A);
int r;
unsigned int r;
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_RAW_QP(A, a);
FP_TO_INT_Q(r, A, 32, 1);
QP_HANDLE_EXCEPTIONS(
int rx;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (float)(*a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -32,13 +32,13 @@ float _Qp_qtos(const long double *a)
float r;
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_SEMIRAW_QP(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(S,Q,1,4,R,A);
FP_TRUNC(S,Q,1,4,R,A);
#else
FP_CONV(S,Q,1,2,R,A);
FP_TRUNC(S,Q,1,2,R,A);
#endif
FP_PACK_S(r, R);
FP_PACK_SEMIRAW_S(r, R);
QP_HANDLE_EXCEPTIONS(__asm (
" ldd [%1], %%f52\n"

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (unsigned int)(*a)
Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,7 +31,7 @@ unsigned int _Qp_qtoui(const long double *a)
unsigned int r;
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_RAW_QP(A, a);
FP_TO_INT_Q(r, A, 32, -1);
QP_HANDLE_EXCEPTIONS(
int rx;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (unsigned long)(*a)
Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,7 +31,7 @@ unsigned long _Qp_qtoux(const long double *a)
unsigned long r;
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_RAW_QP(A, a);
FP_TO_INT_Q(r, A, 64, -1);
QP_HANDLE_EXCEPTIONS(
unsigned long rx;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return (long)(*a)
Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -28,10 +28,10 @@ long _Qp_qtox(const long double *a)
{
FP_DECL_EX;
FP_DECL_Q(A);
long r;
unsigned long r;
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_RAW_QP(A, a);
FP_TO_INT_Q(r, A, 64, 1);
QP_HANDLE_EXCEPTIONS(
long rx;

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -31,13 +31,13 @@ void _Qp_stoq(long double *c, const float a)
FP_DECL_Q(C);
FP_INIT_ROUNDMODE;
FP_UNPACK_S(A, a);
FP_UNPACK_RAW_S(A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
FP_CONV(Q,S,4,1,C,A);
FP_EXTEND(Q,S,4,1,C,A);
#else
FP_CONV(Q,S,2,1,C,A);
FP_EXTEND(Q,S,2,1,C,A);
#endif
FP_PACK_QP(c, C);
FP_PACK_RAW_QP(c, C);
QP_HANDLE_EXCEPTIONS(__asm (
" fstoq %1, %%f60\n"
" std %%f60, [%0]\n"

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (*a) - (*b)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,10 +29,10 @@ void _Qp_sub(long double *c, const long double *a, const long double *b)
FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C);
FP_INIT_ROUNDMODE;
FP_UNPACK_QP(A, a);
FP_UNPACK_QP(B, b);
FP_UNPACK_SEMIRAW_QP(A, a);
FP_UNPACK_SEMIRAW_QP(B, b);
FP_SUB_Q(C, A, B);
FP_PACK_QP(c, C);
FP_PACK_SEMIRAW_QP(c, C);
QP_HANDLE_EXCEPTIONS(__asm (
" ldd [%1], %%f52\n"
" ldd [%1+8], %%f54\n"

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_uitoq(long double *c, const unsigned int a)
FP_DECL_Q(C);
unsigned int b = a;
FP_FROM_INT_Q(C, b, 32, int);
FP_PACK_QP(c, C);
FP_FROM_INT_Q(C, b, 32, unsigned int);
FP_PACK_RAW_QP(c, C);
QP_NO_EXCEPTIONS;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (long double)(a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_uxtoq(long double *c, const unsigned long a)
FP_DECL_Q(C);
unsigned long b = a;
FP_FROM_INT_Q(C, b, 64, long);
FP_PACK_QP(c, C);
FP_FROM_INT_Q(C, b, 64, unsigned long);
FP_PACK_RAW_QP(c, C);
QP_NO_EXCEPTIONS;
}

View File

@@ -1,6 +1,6 @@
/* Software floating-point emulation.
(*c) = (long double)(*a)
Copyright (C) 1997,1999 Free Software Foundation, Inc.
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com) and
Jakub Jelinek (jj@ultra.linux.cz).
@@ -29,7 +29,7 @@ void _Qp_xtoq(long double *c, const long a)
FP_DECL_Q(C);
long b = a;
FP_FROM_INT_Q(C, b, 64, long);
FP_PACK_QP(c, C);
FP_FROM_INT_Q(C, b, 64, unsigned long);
FP_PACK_RAW_QP(c, C);
QP_NO_EXCEPTIONS;
}

View File

@@ -1,6 +1,6 @@
/* Machine-dependent software floating-point definitions.
Sparc64 userland (_Q_* and _Qp_*) version.
Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
Copyright (C) 1997, 1998, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@cygnus.com),
Jakub Jelinek (jj@ultra.linux.cz) and
@@ -23,6 +23,7 @@
#include <fpu_control.h>
#include <fenv.h>
#include <stdlib.h>
#define _FP_W_TYPE_SIZE 64
#define _FP_W_TYPE unsigned long

View File

@@ -600,11 +600,11 @@ ENTRY(memmove)
END(memmove)
#ifdef USE_BPR
weak_alias(memcpy, __align_cpy_1)
weak_alias(memcpy, __align_cpy_2)
weak_alias(memcpy, __align_cpy_4)
weak_alias(memcpy, __align_cpy_8)
weak_alias(memcpy, __align_cpy_16)
weak_alias (memcpy, __align_cpy_1)
weak_alias (memcpy, __align_cpy_2)
weak_alias (memcpy, __align_cpy_4)
weak_alias (memcpy, __align_cpy_8)
weak_alias (memcpy, __align_cpy_16)
#endif
libc_hidden_builtin_def (memcpy)
libc_hidden_builtin_def (memmove)

View File

@@ -0,0 +1,593 @@
/* Copy SIZE bytes from SRC to DEST. For SUN4V Niagara.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David S. Miller (davem@davemloft.net)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
#define ASI_BLK_INIT_QUAD_LDD_P 0xe2
#define ASI_P 0x80
#define ASI_PNF 0x82
#define LOAD(type,addr,dest) type##a [addr] ASI_P, dest
#define LOAD_TWIN(addr_reg,dest0,dest1) \
ldda [addr_reg] ASI_BLK_INIT_QUAD_LDD_P, dest0
#define STORE(type,src,addr) type src, [addr]
#define STORE_INIT(src,addr) stxa src, [addr] %asi
#ifndef XCC
#define USE_BPR
#define XCC xcc
#endif
.register %g2,#scratch
.register %g3,#scratch
.register %g6,#scratch
.text
.align 32
ENTRY(bcopy)
sub %o1, %o0, %o4
mov %o0, %g4
cmp %o4, %o2
mov %o1, %o0
bgeu,pt %XCC, 100f
mov %g4, %o1
#ifndef USE_BPR
srl %o2, 0, %o2
#endif
brnz,pn %o2, 220f
add %o0, %o2, %o0
retl
nop
END(bcopy)
.align 32
ENTRY(memcpy)
100: /* %o0=dst, %o1=src, %o2=len */
mov %o0, %g5
cmp %o2, 0
be,pn %XCC, 85f
218: or %o0, %o1, %o3
cmp %o2, 16
blu,a,pn %XCC, 80f
or %o3, %o2, %o3
/* 2 blocks (128 bytes) is the minimum we can do the block
* copy with. We need to ensure that we'll iterate at least
* once in the block copy loop. At worst we'll need to align
* the destination to a 64-byte boundary which can chew up
* to (64 - 1) bytes from the length before we perform the
* block copy loop.
*/
cmp %o2, (2 * 64)
blu,pt %XCC, 70f
andcc %o3, 0x7, %g0
/* %o0: dst
* %o1: src
* %o2: len (known to be >= 128)
*
* The block copy loops will use %o4/%o5,%g2/%g3 as
* temporaries while copying the data.
*/
LOAD(prefetch, %o1, #one_read)
wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
/* Align destination on 64-byte boundary. */
andcc %o0, (64 - 1), %o4
be,pt %XCC, 2f
sub %o4, 64, %o4
sub %g0, %o4, %o4 ! bytes to align dst
sub %o2, %o4, %o2
1: subcc %o4, 1, %o4
LOAD(ldub, %o1, %g1)
STORE(stb, %g1, %o0)
add %o1, 1, %o1
bne,pt %XCC, 1b
add %o0, 1, %o0
/* If the source is on a 16-byte boundary we can do
* the direct block copy loop. If it is 8-byte aligned
* we can do the 16-byte loads offset by -8 bytes and the
* init stores offset by one register.
*
* If the source is not even 8-byte aligned, we need to do
* shifting and masking (basically integer faligndata).
*
* The careful bit with init stores is that if we store
* to any part of the cache line we have to store the whole
* cacheline else we can end up with corrupt L2 cache line
* contents. Since the loop works on 64-bytes of 64-byte
* aligned store data at a time, this is easy to ensure.
*/
2:
andcc %o1, (16 - 1), %o4
andn %o2, (64 - 1), %g1 ! block copy loop iterator
sub %o2, %g1, %o2 ! final sub-block copy bytes
be,pt %XCC, 50f
cmp %o4, 8
be,a,pt %XCC, 10f
sub %o1, 0x8, %o1
/* Neither 8-byte nor 16-byte aligned, shift and mask. */
mov %g1, %o4
and %o1, 0x7, %g1
sll %g1, 3, %g1
mov 64, %o3
andn %o1, 0x7, %o1
LOAD(ldx, %o1, %g2)
sub %o3, %g1, %o3
sllx %g2, %g1, %g2
#define SWIVEL_ONE_DWORD(SRC, TMP1, TMP2, PRE_VAL, PRE_SHIFT, POST_SHIFT, DST)\
LOAD(ldx, SRC, TMP1); \
srlx TMP1, PRE_SHIFT, TMP2; \
or TMP2, PRE_VAL, TMP2; \
STORE_INIT(TMP2, DST); \
sllx TMP1, POST_SHIFT, PRE_VAL;
1: add %o1, 0x8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x00)
add %o1, 0x8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x08)
add %o1, 0x8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x10)
add %o1, 0x8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x18)
add %o1, 32, %o1
LOAD(prefetch, %o1, #one_read)
sub %o1, 32 - 8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x20)
add %o1, 8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x28)
add %o1, 8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x30)
add %o1, 8, %o1
SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x38)
subcc %o4, 64, %o4
bne,pt %XCC, 1b
add %o0, 64, %o0
#undef SWIVEL_ONE_DWORD
srl %g1, 3, %g1
ba,pt %XCC, 60f
add %o1, %g1, %o1
10: /* Destination is 64-byte aligned, source was only 8-byte
* aligned but it has been subtracted by 8 and we perform
* one twin load ahead, then add 8 back into source when
* we finish the loop.
*/
LOAD_TWIN(%o1, %o4, %o5)
1: add %o1, 16, %o1
LOAD_TWIN(%o1, %g2, %g3)
add %o1, 16 + 32, %o1
LOAD(prefetch, %o1, #one_read)
sub %o1, 32, %o1
STORE_INIT(%o5, %o0 + 0x00) ! initializes cache line
STORE_INIT(%g2, %o0 + 0x08)
LOAD_TWIN(%o1, %o4, %o5)
add %o1, 16, %o1
STORE_INIT(%g3, %o0 + 0x10)
STORE_INIT(%o4, %o0 + 0x18)
LOAD_TWIN(%o1, %g2, %g3)
add %o1, 16, %o1
STORE_INIT(%o5, %o0 + 0x20)
STORE_INIT(%g2, %o0 + 0x28)
LOAD_TWIN(%o1, %o4, %o5)
STORE_INIT(%g3, %o0 + 0x30)
STORE_INIT(%o4, %o0 + 0x38)
subcc %g1, 64, %g1
bne,pt %XCC, 1b
add %o0, 64, %o0
ba,pt %XCC, 60f
add %o1, 0x8, %o1
50: /* Destination is 64-byte aligned, and source is 16-byte
* aligned.
*/
1: LOAD_TWIN(%o1, %o4, %o5)
add %o1, 16, %o1
LOAD_TWIN(%o1, %g2, %g3)
add %o1, 16 + 32, %o1
LOAD(prefetch, %o1, #one_read)
sub %o1, 32, %o1
STORE_INIT(%o4, %o0 + 0x00) ! initializes cache line
STORE_INIT(%o5, %o0 + 0x08)
LOAD_TWIN(%o1, %o4, %o5)
add %o1, 16, %o1
STORE_INIT(%g2, %o0 + 0x10)
STORE_INIT(%g3, %o0 + 0x18)
LOAD_TWIN(%o1, %g2, %g3)
add %o1, 16, %o1
STORE_INIT(%o4, %o0 + 0x20)
STORE_INIT(%o5, %o0 + 0x28)
STORE_INIT(%g2, %o0 + 0x30)
STORE_INIT(%g3, %o0 + 0x38)
subcc %g1, 64, %g1
bne,pt %XCC, 1b
add %o0, 64, %o0
/* fall through */
60:
/* %o2 contains any final bytes still needed to be copied
* over. If anything is left, we copy it one byte at a time.
*/
wr %g0, ASI_PNF, %asi
brz,pt %o2, 85f
sub %o0, %o1, %o3
ba,a,pt %XCC, 90f
.align 64
70: /* 16 < len <= 64 */
bne,pn %XCC, 75f
sub %o0, %o1, %o3
72:
andn %o2, 0xf, %o4
and %o2, 0xf, %o2
1: subcc %o4, 0x10, %o4
LOAD(ldx, %o1, %o5)
add %o1, 0x08, %o1
LOAD(ldx, %o1, %g1)
sub %o1, 0x08, %o1
STORE(stx, %o5, %o1 + %o3)
add %o1, 0x8, %o1
STORE(stx, %g1, %o1 + %o3)
bgu,pt %XCC, 1b
add %o1, 0x8, %o1
73: andcc %o2, 0x8, %g0
be,pt %XCC, 1f
nop
sub %o2, 0x8, %o2
LOAD(ldx, %o1, %o5)
STORE(stx, %o5, %o1 + %o3)
add %o1, 0x8, %o1
1: andcc %o2, 0x4, %g0
be,pt %XCC, 1f
nop
sub %o2, 0x4, %o2
LOAD(lduw, %o1, %o5)
STORE(stw, %o5, %o1 + %o3)
add %o1, 0x4, %o1
1: cmp %o2, 0
be,pt %XCC, 85f
nop
ba,pt %XCC, 90f
nop
75:
andcc %o0, 0x7, %g1
sub %g1, 0x8, %g1
be,pn %icc, 2f
sub %g0, %g1, %g1
sub %o2, %g1, %o2
1: subcc %g1, 1, %g1
LOAD(ldub, %o1, %o5)
STORE(stb, %o5, %o1 + %o3)
bgu,pt %icc, 1b
add %o1, 1, %o1
2: add %o1, %o3, %o0
andcc %o1, 0x7, %g1
bne,pt %icc, 8f
sll %g1, 3, %g1
cmp %o2, 16
bgeu,pt %icc, 72b
nop
ba,a,pt %XCC, 73b
8: mov 64, %o3
andn %o1, 0x7, %o1
LOAD(ldx, %o1, %g2)
sub %o3, %g1, %o3
andn %o2, 0x7, %o4
sllx %g2, %g1, %g2
1: add %o1, 0x8, %o1
LOAD(ldx, %o1, %g3)
subcc %o4, 0x8, %o4
srlx %g3, %o3, %o5
or %o5, %g2, %o5
STORE(stx, %o5, %o0)
add %o0, 0x8, %o0
bgu,pt %icc, 1b
sllx %g3, %g1, %g2
srl %g1, 3, %g1
andcc %o2, 0x7, %o2
be,pn %icc, 85f
add %o1, %g1, %o1
ba,pt %XCC, 90f
sub %o0, %o1, %o3
.align 64
80: /* 0 < len <= 16 */
andcc %o3, 0x3, %g0
bne,pn %XCC, 90f
sub %o0, %o1, %o3
1:
subcc %o2, 4, %o2
LOAD(lduw, %o1, %g1)
STORE(stw, %g1, %o1 + %o3)
bgu,pt %XCC, 1b
add %o1, 4, %o1
85: retl
mov %g5, %o0
.align 32
90:
subcc %o2, 1, %o2
LOAD(ldub, %o1, %g1)
STORE(stb, %g1, %o1 + %o3)
bgu,pt %XCC, 90b
add %o1, 1, %o1
retl
mov %g5, %o0
END(memcpy)
#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \
ldx [%src - offset - 0x20], %t0; \
ldx [%src - offset - 0x18], %t1; \
ldx [%src - offset - 0x10], %t2; \
ldx [%src - offset - 0x08], %t3; \
stw %t0, [%dst - offset - 0x1c]; \
srlx %t0, 32, %t0; \
stw %t0, [%dst - offset - 0x20]; \
stw %t1, [%dst - offset - 0x14]; \
srlx %t1, 32, %t1; \
stw %t1, [%dst - offset - 0x18]; \
stw %t2, [%dst - offset - 0x0c]; \
srlx %t2, 32, %t2; \
stw %t2, [%dst - offset - 0x10]; \
stw %t3, [%dst - offset - 0x04]; \
srlx %t3, 32, %t3; \
stw %t3, [%dst - offset - 0x08];
#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \
ldx [%src - offset - 0x20], %t0; \
ldx [%src - offset - 0x18], %t1; \
ldx [%src - offset - 0x10], %t2; \
ldx [%src - offset - 0x08], %t3; \
stx %t0, [%dst - offset - 0x20]; \
stx %t1, [%dst - offset - 0x18]; \
stx %t2, [%dst - offset - 0x10]; \
stx %t3, [%dst - offset - 0x08]; \
ldx [%src - offset - 0x40], %t0; \
ldx [%src - offset - 0x38], %t1; \
ldx [%src - offset - 0x30], %t2; \
ldx [%src - offset - 0x28], %t3; \
stx %t0, [%dst - offset - 0x40]; \
stx %t1, [%dst - offset - 0x38]; \
stx %t2, [%dst - offset - 0x30]; \
stx %t3, [%dst - offset - 0x28];
#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
ldx [%src + offset + 0x00], %t0; \
ldx [%src + offset + 0x08], %t1; \
stw %t0, [%dst + offset + 0x04]; \
srlx %t0, 32, %t2; \
stw %t2, [%dst + offset + 0x00]; \
stw %t1, [%dst + offset + 0x0c]; \
srlx %t1, 32, %t3; \
stw %t3, [%dst + offset + 0x08];
#define RMOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \
ldx [%src + offset + 0x00], %t0; \
ldx [%src + offset + 0x08], %t1; \
stx %t0, [%dst + offset + 0x00]; \
stx %t1, [%dst + offset + 0x08];
.align 32
228: andcc %o2, 1, %g0
be,pt %icc, 2f+4
1: ldub [%o1 - 1], %o5
sub %o1, 1, %o1
sub %o0, 1, %o0
subcc %o2, 1, %o2
be,pn %xcc, 229f
stb %o5, [%o0]
2: ldub [%o1 - 1], %o5
sub %o0, 2, %o0
ldub [%o1 - 2], %g5
sub %o1, 2, %o1
subcc %o2, 2, %o2
stb %o5, [%o0 + 1]
bne,pt %xcc, 2b
stb %g5, [%o0]
229: retl
mov %g4, %o0
out: retl
mov %g5, %o0
.align 32
ENTRY(memmove)
mov %o0, %g5
#ifndef USE_BPR
srl %o2, 0, %o2
#endif
brz,pn %o2, out
sub %o0, %o1, %o4
cmp %o4, %o2
bgeu,pt %XCC, 218b
mov %o0, %g4
add %o0, %o2, %o0
220: add %o1, %o2, %o1
cmp %o2, 15
bleu,pn %xcc, 228b
andcc %o0, 7, %g2
sub %o0, %o1, %g5
andcc %g5, 3, %o5
bne,pn %xcc, 232f
andcc %o1, 3, %g0
be,a,pt %xcc, 236f
andcc %o1, 4, %g0
andcc %o1, 1, %g0
be,pn %xcc, 4f
andcc %o1, 2, %g0
ldub [%o1 - 1], %g2
sub %o1, 1, %o1
sub %o0, 1, %o0
sub %o2, 1, %o2
be,pn %xcc, 5f
stb %g2, [%o0]
4: lduh [%o1 - 2], %g2
sub %o1, 2, %o1
sub %o0, 2, %o0
sub %o2, 2, %o2
sth %g2, [%o0]
5: andcc %o1, 4, %g0
236: be,a,pn %xcc, 2f
andcc %o2, -128, %g6
lduw [%o1 - 4], %g5
sub %o1, 4, %o1
sub %o0, 4, %o0
sub %o2, 4, %o2
stw %g5, [%o0]
andcc %o2, -128, %g6
2: be,pn %xcc, 235f
andcc %o0, 4, %g0
be,pn %xcc, 282f + 4
5: RMOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
RMOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5)
RMOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
RMOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5)
subcc %g6, 128, %g6
sub %o1, 128, %o1
bne,pt %xcc, 5b
sub %o0, 128, %o0
235: andcc %o2, 0x70, %g6
41: be,pn %xcc, 280f
andcc %o2, 8, %g0
279: rd %pc, %o5
sll %g6, 1, %g5
sub %o1, %g6, %o1
sub %o5, %g5, %o5
jmpl %o5 + %lo(280f - 279b), %g0
sub %o0, %g6, %o0
RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5)
RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5)
RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5)
RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5)
RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5)
RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5)
RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5)
280: be,pt %xcc, 281f
andcc %o2, 4, %g0
ldx [%o1 - 8], %g2
sub %o0, 8, %o0
stw %g2, [%o0 + 4]
sub %o1, 8, %o1
srlx %g2, 32, %g2
stw %g2, [%o0]
281: be,pt %xcc, 1f
andcc %o2, 2, %g0
lduw [%o1 - 4], %g2
sub %o1, 4, %o1
stw %g2, [%o0 - 4]
sub %o0, 4, %o0
1: be,pt %xcc, 1f
andcc %o2, 1, %g0
lduh [%o1 - 2], %g2
sub %o1, 2, %o1
sth %g2, [%o0 - 2]
sub %o0, 2, %o0
1: be,pt %xcc, 211f
nop
ldub [%o1 - 1], %g2
stb %g2, [%o0 - 1]
211: retl
mov %g4, %o0
282: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
subcc %g6, 128, %g6
sub %o1, 128, %o1
bne,pt %xcc, 282b
sub %o0, 128, %o0
andcc %o2, 0x70, %g6
be,pn %xcc, 284f
andcc %o2, 8, %g0
283: rd %pc, %o5
sub %o1, %g6, %o1
sub %o5, %g6, %o5
jmpl %o5 + %lo(284f - 283b), %g0
sub %o0, %g6, %o0
RMOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3)
RMOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3)
RMOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3)
RMOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3)
RMOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3)
RMOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3)
RMOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3)
284: be,pt %xcc, 285f
andcc %o2, 4, %g0
ldx [%o1 - 8], %g2
sub %o0, 8, %o0
sub %o1, 8, %o1
stx %g2, [%o0]
285: be,pt %xcc, 1f
andcc %o2, 2, %g0
lduw [%o1 - 4], %g2
sub %o0, 4, %o0
sub %o1, 4, %o1
stw %g2, [%o0]
1: be,pt %xcc, 1f
andcc %o2, 1, %g0
lduh [%o1 - 2], %g2
sub %o0, 2, %o0
sub %o1, 2, %o1
sth %g2, [%o0]
1: be,pt %xcc, 1f
nop
ldub [%o1 - 1], %g2
stb %g2, [%o0 - 1]
1: retl
mov %g4, %o0
232: ldub [%o1 - 1], %g5
sub %o1, 1, %o1
sub %o0, 1, %o0
subcc %o2, 1, %o2
bne,pt %xcc, 232b
stb %g5, [%o0]
234: retl
mov %g4, %o0
END(memmove)
#ifdef USE_BPR
weak_alias (memcpy, __align_cpy_1)
weak_alias (memcpy, __align_cpy_2)
weak_alias (memcpy, __align_cpy_4)
weak_alias (memcpy, __align_cpy_8)
weak_alias (memcpy, __align_cpy_16)
#endif
libc_hidden_builtin_def (memcpy)
libc_hidden_builtin_def (memmove)

View File

@@ -0,0 +1,127 @@
/* Set a block of memory to some byte value. For SUN4V Niagara.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David S. Miller (davem@davemloft.net)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
#define ASI_BLK_INIT_QUAD_LDD_P 0xe2
#define ASI_P 0x80
#define ASI_PNF 0x82
#ifndef XCC
#define USE_BPR
#define XCC xcc
#endif
.register %g2,#scratch
.text
.align 32
ENTRY(memset)
/* %o0=buf, %o1=pat, %o2=len */
and %o1, 0xff, %o3
mov %o2, %o1
sllx %o3, 8, %g1
or %g1, %o3, %o2
sllx %o2, 16, %g1
or %g1, %o2, %o2
sllx %o2, 32, %g1
ba,pt %XCC, 1f
or %g1, %o2, %o2
END(memset)
ENTRY(__bzero)
clr %o2
1: brz,pn %o1, 90f
mov %o0, %o3
wr %g0, ASI_P, %asi
cmp %o1, 15
bl,pn %icc, 70f
andcc %o0, 0x7, %g1
be,pt %XCC, 2f
mov 8, %g2
sub %g2, %g1, %g1
sub %o1, %g1, %o1
1: stba %o2, [%o0 + 0x00] %asi
subcc %g1, 1, %g1
bne,pt %XCC, 1b
add %o0, 1, %o0
2: cmp %o1, 128
bl,pn %icc, 60f
andcc %o0, (64 - 1), %g1
be,pt %XCC, 40f
mov 64, %g2
sub %g2, %g1, %g1
sub %o1, %g1, %o1
1: stxa %o2, [%o0 + 0x00] %asi
subcc %g1, 8, %g1
bne,pt %XCC, 1b
add %o0, 8, %o0
40:
wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
andn %o1, (64 - 1), %g1
sub %o1, %g1, %o1
50:
stxa %o2, [%o0 + 0x00] %asi
stxa %o2, [%o0 + 0x08] %asi
stxa %o2, [%o0 + 0x10] %asi
stxa %o2, [%o0 + 0x18] %asi
stxa %o2, [%o0 + 0x20] %asi
stxa %o2, [%o0 + 0x28] %asi
stxa %o2, [%o0 + 0x30] %asi
stxa %o2, [%o0 + 0x38] %asi
subcc %g1, 64, %g1
bne,pt %XCC, 50b
add %o0, 64, %o0
wr %g0, ASI_P, %asi
brz,pn %o1, 80f
60:
andncc %o1, 0x7, %g1
be,pn %XCC, 2f
sub %o1, %g1, %o1
1: stxa %o2, [%o0 + 0x00] %asi
subcc %g1, 8, %g1
bne,pt %XCC, 1b
add %o0, 8, %o0
2: brz,pt %o1, 80f
nop
70:
1: stba %o2, [%o0 + 0x00] %asi
subcc %o1, 1, %o1
bne,pt %icc, 1b
add %o0, 1, %o0
/* fallthrough */
80:
wr %g0, ASI_PNF, %asi
90:
retl
mov %o3, %o0
END(__bzero)
libc_hidden_builtin_def (memset)
weak_alias (__bzero, bzero)