From cf29934141e8e27bd66c9a7fe4f4c217878365a7 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 21 May 2002 02:15:01 +0000 Subject: [PATCH] Update. 2002-05-17 David S. Miller * sysdeps/unix/sysv/linux/sparc/fork.S: Define _internal aliases. 2002-05-16 David S. Miller * sysdeps/sparc/sparc32/dl-machine.h (LOAD_PIC_REG): Define. (elf_machine_dynamic): Use it to force PIC register to be loaded. (elf_machine_load_address): Likewise. * sysdeps/sparc/sparc64/dl-machine.h: Mirror sparc32 changes. * sysdeps/sparc/sparc64/strncmp.S: When second argument pointer is unaligned, do not forget to fully initialize %g1 magic value. * sysdeps/unix/sysv/linux/sparc/sys/procfs.h: Fix 64-bit elf register definitions and provide 32-bit variants of structures during 64-bit builds. * soft-fp/op-1.h (_FP_FRAC_CLEAR_OVERP_1): Define. * soft-fp/op-2.h (_FP_FRAC_CLEAR_OVERP_2): Define. * soft-fp/op-4.h (_FP_FRAC_CLEAR_OVERP_4): Define. * soft-fp/op-common.h (_FP_PACK_CANONICAL): After rounding, if _FP_FRAC_OVERP_X is set, use _FP_FRAC_CLEAR_OVERP_X to clear it. (_FP_FROM_INT): Perform right shifts on unsigned integer type. Do not clear implicit one bit here, it must be done post-rounding. Only pad to the left using left shift if value uses less than the available fractional bits. --- ChangeLog | 28 ++++++++++++ soft-fp/op-1.h | 1 + soft-fp/op-2.h | 1 + soft-fp/op-4.h | 1 + soft-fp/op-common.h | 21 ++++----- sysdeps/sparc/sparc32/dl-machine.h | 16 +++++++ sysdeps/sparc/sparc64/dl-machine.h | 16 +++++++ sysdeps/sparc/sparc64/strncmp.S | 11 ++--- sysdeps/unix/sysv/linux/sparc/fork.S | 1 + sysdeps/unix/sysv/linux/sparc/sys/procfs.h | 69 +++++++++++++++++++++++++++++- 10 files changed, 149 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0f6016b..01eb95b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2002-05-17 David S. Miller + + * sysdeps/unix/sysv/linux/sparc/fork.S: Define _internal aliases. + +2002-05-16 David S. Miller + + * sysdeps/sparc/sparc32/dl-machine.h (LOAD_PIC_REG): Define. + (elf_machine_dynamic): Use it to force PIC register to be loaded. + (elf_machine_load_address): Likewise. + * sysdeps/sparc/sparc64/dl-machine.h: Mirror sparc32 changes. + + * sysdeps/sparc/sparc64/strncmp.S: When second argument pointer + is unaligned, do not forget to fully initialize %g1 magic value. + + * sysdeps/unix/sysv/linux/sparc/sys/procfs.h: Fix 64-bit elf + register definitions and provide 32-bit variants of structures + during 64-bit builds. + + * soft-fp/op-1.h (_FP_FRAC_CLEAR_OVERP_1): Define. + * soft-fp/op-2.h (_FP_FRAC_CLEAR_OVERP_2): Define. + * soft-fp/op-4.h (_FP_FRAC_CLEAR_OVERP_4): Define. + * soft-fp/op-common.h (_FP_PACK_CANONICAL): After rounding, if + _FP_FRAC_OVERP_X is set, use _FP_FRAC_CLEAR_OVERP_X to clear it. + (_FP_FROM_INT): Perform right shifts on unsigned integer type. + Do not clear implicit one bit here, it must be done post-rounding. + Only pad to the left using left shift if value uses less than the + available fractional bits. + 2002-05-20 Franz Sirl * sysdeps/powerpc/Makefile (sysdeps_routines): Use libgcc-compat diff --git a/soft-fp/op-1.h b/soft-fp/op-1.h index f732143..367ff22 100644 --- a/soft-fp/op-1.h +++ b/soft-fp/op-1.h @@ -55,6 +55,7 @@ #define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0) #define _FP_FRAC_ZEROP_1(X) (X##_f == 0) #define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs) #define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f) #define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f) #define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f) diff --git a/soft-fp/op-2.h b/soft-fp/op-2.h index 4a5add5..89da27f 100644 --- a/soft-fp/op-2.h +++ b/soft-fp/op-2.h @@ -112,6 +112,7 @@ #define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0) #define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0) #define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) #define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0) #define _FP_FRAC_GT_2(X, Y) \ (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 > Y##_f0) diff --git a/soft-fp/op-4.h b/soft-fp/op-4.h index 8200900..5e3032e 100644 --- a/soft-fp/op-4.h +++ b/soft-fp/op-4.h @@ -129,6 +129,7 @@ #define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) #define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0) #define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) #define _FP_FRAC_EQ_4(X,Y) \ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index 012e76f..232604e 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -89,11 +89,10 @@ do { \ _FP_ROUND(wc, X); \ if (_FP_FRAC_OVERP_##wc(fs, X)) \ { \ - _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \ + _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \ X##_e++; \ } \ - else \ - _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ if (X##_e >= _FP_EXPMAX_##fs) \ { \ /* overflow */ \ @@ -682,25 +681,27 @@ do { \ do { \ if (r) \ { \ + unsigned rtype ur_; \ X##_c = FP_CLS_NORMAL; \ \ if ((X##_s = (r < 0))) \ r = -r; \ \ + ur_ = (unsigned rtype) r; \ if (rsize <= _FP_W_TYPE_SIZE) \ - __FP_CLZ(X##_e, r); \ + __FP_CLZ(X##_e, ur_); \ else \ - __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \ - (_FP_W_TYPE)r); \ + __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \ + (_FP_W_TYPE)ur_); \ if (rsize < _FP_W_TYPE_SIZE) \ X##_e -= (_FP_W_TYPE_SIZE - rsize); \ X##_e = rsize - X##_e - 1; \ \ if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \ - __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \ - r &= ~((rtype)1 << X##_e); \ - _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \ - _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \ + __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\ + _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \ + if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \ + _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \ } \ else \ { \ diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h index 4534464..6977cdc 100644 --- a/sysdeps/sparc/sparc32/dl-machine.h +++ b/sysdeps/sparc/sparc32/dl-machine.h @@ -72,6 +72,17 @@ elf_machine_matches_host (const Elf32_Ehdr *ehdr) return 0; } +/* We have to do this because elf_machine_{dynamic,load_address} can be + invoked from functions that have no GOT references, and thus the compiler + has no obligation to load the PIC register. */ +#define LOAD_PIC_REG(PIC_REG) \ +do { register Elf32_Addr pc __asm("o7"); \ + __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "call 1f\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \ + "1:\tadd %1, %0, %1" \ + : "=r" (pc), "=r" (PIC_REG)); \ +} while (0) /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which @@ -80,6 +91,9 @@ static inline Elf32_Addr elf_machine_dynamic (void) { register Elf32_Addr *got asm ("%l7"); + + LOAD_PIC_REG (got); + return *got; } @@ -89,6 +103,8 @@ elf_machine_load_address (void) { register Elf32_Addr pc __asm("%o7"), pic __asm("%l7"), got; + LOAD_PIC_REG (pic); + /* Utilize the fact that a local .got entry will be partially initialized at startup awaiting its RELATIVE fixup. */ diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h index 4ced7de..fba323d 100644 --- a/sysdeps/sparc/sparc64/dl-machine.h +++ b/sysdeps/sparc/sparc64/dl-machine.h @@ -39,6 +39,18 @@ elf_machine_matches_host (const Elf64_Ehdr *ehdr) return ehdr->e_machine == EM_SPARCV9; } +/* We have to do this because elf_machine_{dynamic,load_address} can be + invoked from functions that have no GOT references, and thus the compiler + has no obligation to load the PIC register. */ +#define LOAD_PIC_REG(PIC_REG) \ +do { Elf64_Addr tmp; \ + __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "rd %%pc, %0\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ + "add %0, %1, %0" \ + : "=r" (PIC_REG), "=r" (tmp)); \ +} while (0) + /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which uses global data. */ @@ -47,6 +59,8 @@ elf_machine_dynamic (void) { register Elf64_Addr *elf_pic_register __asm__("%l7"); + LOAD_PIC_REG (elf_pic_register); + return *elf_pic_register; } @@ -56,6 +70,8 @@ elf_machine_load_address (void) { register Elf64_Addr *elf_pic_register __asm__("%l7"); + LOAD_PIC_REG (elf_pic_register); + /* We used to utilize the fact that a local .got entry will be partially initialized at startup awaiting its RELATIVE fixup: diff --git a/sysdeps/sparc/sparc64/strncmp.S b/sysdeps/sparc/sparc64/strncmp.S index 3bc21d6..31fcfee 100644 --- a/sysdeps/sparc/sparc64/strncmp.S +++ b/sysdeps/sparc/sparc64/strncmp.S @@ -290,14 +290,15 @@ ENTRY(strncmp) ldxa [%o0] ASI_PNF, %g4 /* Load */ 11: sllx %g3, 3, %g5 /* IEU0 Group */ mov 64, %g7 /* IEU1 */ - sub %o1, %g3, %o1 /* IEU0 Group */ + or %g1, %g2, %g1 /* IEU0 Group */ + sub %o1, %g3, %o1 /* IEU1 */ - sub %g7, %g5, %g7 /* IEU1 */ + sub %g7, %g5, %g7 /* IEU0 Group */ ldxa [%o1] ASI_PNF, %o4 /* Load */ - sllx %g1, 7, %g2 /* IEU0 Group */ - add %o1, 8, %o1 /* IEU1 */ + sllx %g1, 7, %g2 /* IEU1 */ + add %o1, 8, %o1 /* IEU0 Group */ /* %g1 = 0101010101010101 - %g2 = 8080808080800880 + %g2 = 8080808080808080 %g3 = %o1 alignment %g5 = number of bits to shift left %g7 = number of bits to shift right */ diff --git a/sysdeps/unix/sysv/linux/sparc/fork.S b/sysdeps/unix/sysv/linux/sparc/fork.S index 870d960..ad9f3bb 100644 --- a/sysdeps/unix/sysv/linux/sparc/fork.S +++ b/sysdeps/unix/sysv/linux/sparc/fork.S @@ -25,5 +25,6 @@ PSEUDO (__libc_fork, fork, 0) and %o0, %o1, %o0 PSEUDO_END (__libc_fork) +strong_alias (__libc_fork, __fork_internal) weak_alias (__libc_fork, __fork) weak_alias (__libc_fork, fork) diff --git a/sysdeps/unix/sysv/linux/sparc/sys/procfs.h b/sysdeps/unix/sysv/linux/sparc/sys/procfs.h index e5d35f5..2827b1e 100644 --- a/sysdeps/unix/sysv/linux/sparc/sys/procfs.h +++ b/sysdeps/unix/sysv/linux/sparc/sys/procfs.h @@ -35,7 +35,7 @@ __BEGIN_DECLS #if __WORDSIZE == 64 -#define ELF_NGREG 20 +#define ELF_NGREG 36 typedef struct { @@ -139,6 +139,73 @@ typedef __pid_t lwpid_t; typedef struct elf_prstatus prstatus_t; typedef struct elf_prpsinfo prpsinfo_t; +#if __WORDSIZE == 64 + +/* Provide 32-bit variants so that BFD can read 32-bit + core files. */ +#define ELF_NGREG32 38 +typedef struct + { + union + { + unsigned int pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned int __unused; + unsigned int pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t32; + +typedef unsigned int elf_greg_t32; +typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG32]; + +struct elf_prstatus32 + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned int pr_sigpend; /* Set of pending signals. */ + unsigned int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct + { + int tv_sec, tv_usec; + } pr_utime, /* User time. */ + pr_stime, /* System time. */ + pr_cutime, /* Cumulative user time. */ + pr_cstime; /* Cumulative system time. */ + elf_gregset_t32 pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + +struct elf_prpsinfo32 + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +typedef elf_gregset_t32 prgregset32_t; +typedef elf_fpregset_t32 prfpregset32_t; + +typedef struct elf_prstatus32 prstatus32_t; +typedef struct elf_prpsinfo32 prpsinfo32_t; + +#endif /* sparc64 */ + __END_DECLS #endif /* sys/procfs.h */ -- 2.7.4