diff options
Diffstat (limited to 'sysdeps/sh/sh3')
-rw-r--r-- | sysdeps/sh/sh3/__longjmp.S | 44 | ||||
-rw-r--r-- | sysdeps/sh/sh3/bits/endian.h | 13 | ||||
-rw-r--r-- | sysdeps/sh/sh3/bits/huge_val.h | 104 | ||||
-rw-r--r-- | sysdeps/sh/sh3/bits/setjmp.h | 45 | ||||
-rw-r--r-- | sysdeps/sh/sh3/bsd-_setjmp.S | 51 | ||||
-rw-r--r-- | sysdeps/sh/sh3/bsd-setjmp.S | 51 | ||||
-rw-r--r-- | sysdeps/sh/sh3/dl-machine.h | 520 | ||||
-rw-r--r-- | sysdeps/sh/sh3/setjmp.S | 67 |
8 files changed, 895 insertions, 0 deletions
diff --git a/sysdeps/sh/sh3/__longjmp.S b/sysdeps/sh/sh3/__longjmp.S new file mode 100644 index 0000000000..09f829ae37 --- /dev/null +++ b/sysdeps/sh/sh3/__longjmp.S @@ -0,0 +1,44 @@ +/* longjmp for SH. + Copyright (C) 1999, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <sysdep.h> +#define _SETJMP_H +#define _ASM +#include <bits/setjmp.h> + +/* __longjmp(jmpbuf, val) */ + +ENTRY (__longjmp) + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 + mov r5, r0 /* get the return value in place */ + tst r0, r0 + bf.s 1f + lds.l @r4+, pr + mov #1,r0 /* can't let setjmp() return zero! */ +1: + rts + ldc.l @r4+, gbr +END (__longjmp) diff --git a/sysdeps/sh/sh3/bits/endian.h b/sysdeps/sh/sh3/bits/endian.h new file mode 100644 index 0000000000..1fef1ff938 --- /dev/null +++ b/sysdeps/sh/sh3/bits/endian.h @@ -0,0 +1,13 @@ +/* SH is bi-endian but with a big-endian FPU. */ + +#ifndef _ENDIAN_H +# error "Never use <bits/endian.h> directly; include <endian.h> instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +#define __BYTE_ORDER __LITTLE_ENDIAN +#define __FLOAT_WORD_ORDER __LITTLE_ENDIAN +#else +#define __BYTE_ORDER __BIG_ENDIAN +#define __FLOAT_WORD_ORDER __BIG_ENDIAN +#endif diff --git a/sysdeps/sh/sh3/bits/huge_val.h b/sysdeps/sh/sh3/bits/huge_val.h new file mode 100644 index 0000000000..a058c999ae --- /dev/null +++ b/sysdeps/sh/sh3/bits/huge_val.h @@ -0,0 +1,104 @@ +/* `HUGE_VAL' constants for IEEE 754 machines (where it is infinity). + Used by <stdlib.h> and <math.h> functions for overflow. + SH version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _MATH_H +# error "Never use <bits/huge_val.h> directly; include <math.h> instead." +#endif + +#include <features.h> + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#ifdef __GNUC__ + +# if __GNUC_PREREQ(2,96) + +# define HUGE_VAL (__extension__ 0x1.0p2047) + +# else + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) + +# endif + +#else /* not GCC */ + +# include <endian.h> + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ + + +/* ISO C99 extensions: (float) HUGE_VALF and (long double) HUGE_VALL. */ + +#ifdef __USE_ISOC99 + +# ifdef __GNUC__ + +# if __GNUC_PREREQ(2,96) + +# define HUGE_VALF (__extension__ 0x1.0p255f) + +# else + +# define HUGE_VALF \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__SI__))); float __d; }) \ + { __l: 0x7f800000UL }).__d) + +# endif + +# else /* not GCC */ + +typedef union { unsigned char __c[4]; float __f; } __huge_valf_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VALF_bytes { 0x7f, 0x80, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VALF_bytes { 0, 0, 0x80, 0x7f } +# endif + +static __huge_valf_t __huge_valf = { __HUGE_VALF_bytes }; +# define HUGE_VALF (__huge_valf.__f) + +# endif /* GCC. */ + + +/* Generally there is no separate `long double' format and it is the + same as `double'. */ +# define HUGE_VALL HUGE_VAL + +#endif /* __USE_ISOC99. */ diff --git a/sysdeps/sh/sh3/bits/setjmp.h b/sysdeps/sh/sh3/bits/setjmp.h new file mode 100644 index 0000000000..d2c4a420cd --- /dev/null +++ b/sysdeps/sh/sh3/bits/setjmp.h @@ -0,0 +1,45 @@ +/* Copyright (C) 1999, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Define the machine-dependent type `jmp_buf'. SH version. */ + +#ifndef _SETJMP_H +# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Callee-saved registers r8 through r15. */ + int __regs[8]; + + /* Program counter. */ + void * __pc; + + /* The global pointer. */ + void * __gbr; + + } __jmp_buf[1]; +#endif + +#define JB_SIZE (4 * 10) + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < &(jmpbuf)[0].__regs[7]) diff --git a/sysdeps/sh/sh3/bsd-_setjmp.S b/sysdeps/sh/sh3/bsd-_setjmp.S new file mode 100644 index 0000000000..d787cd23d7 --- /dev/null +++ b/sysdeps/sh/sh3/bsd-_setjmp.S @@ -0,0 +1,51 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. SH version. + Copyright (C) 1999, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> + +ENTRY (_setjmp) +#ifdef SHARED + mova 1f, r0 + mov.l 1f, r1 + bra 2f + add r1, r0 + .align 2 +1: + .long _GLOBAL_OFFSET_TABLE_ +2: + mov.l 3f, r1 + mov.l @(r0,r1), r1 + jmp @r1 + mov #0, r0 + .align 2 +3: + .long C_SYMBOL_NAME(__sigsetjmp@GOT) +#else + mov.l 1f, r1 + jmp @r1 + mov #0, r0 + .align 2 +1: + .long C_SYMBOL_NAME(__sigsetjmp) +#endif +END (_setjmp) diff --git a/sysdeps/sh/sh3/bsd-setjmp.S b/sysdeps/sh/sh3/bsd-setjmp.S new file mode 100644 index 0000000000..7ffb6919da --- /dev/null +++ b/sysdeps/sh/sh3/bsd-setjmp.S @@ -0,0 +1,51 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. SH version. + Copyright (C) 1999, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> + +ENTRY (setjmp) +#ifdef SHARED + mova 1f, r0 + mov.l 1f, r1 + bra 2f + add r1, r0 + .align 2 +1: + .long _GLOBAL_OFFSET_TABLE_ +2: + mov.l 3f, r1 + mov.l @(r0,r1), r1 + jmp @r1 + mov #1, r0 + .align 2 +3: + .long C_SYMBOL_NAME(__sigsetjmp@GOT) +#else + mov.l 1f, r1 + jmp @r1 + mov #1, r0 + .align 2 +1: + .long C_SYMBOL_NAME(__sigsetjmp) +#endif +END (setjmp) diff --git a/sysdeps/sh/sh3/dl-machine.h b/sysdeps/sh/sh3/dl-machine.h new file mode 100644 index 0000000000..93a65ac03a --- /dev/null +++ b/sysdeps/sh/sh3/dl-machine.h @@ -0,0 +1,520 @@ +/* Machine-dependent ELF dynamic relocation inline functions. SH-3 version. + Copyright (C) 1999, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef dl_machine_h +#define dl_machine_h + +/* Only dummy. This doesn't work. */ + +#define ELF_MACHINE_NAME "SH" + +#include <sys/param.h> + +#include <assert.h> + +/* Return nonzero iff E_MACHINE is compatible with the running host. */ +static inline int __attribute__ ((unused)) +elf_machine_matches_host (Elf32_Half e_machine) +{ + switch (e_machine) + { + case EM_SH: + return 1; + default: + return 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. */ +static inline Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + register Elf32_Addr *got; + asm ("mov r12,%0" :"=r" (got)); + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static inline Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + Elf32_Addr addr; + asm ("mov.l .L1,r0 + mov.l .L3,r2 + add r12,r2 + mov.l @(r0,r12),r0 + bra .L2 + sub r0,r2 + .align 2 + .L1: .long _dl_start@GOT + .L3: .long _dl_start@GOTOFF + .L2: mov r2,%0" + : "=r" (addr) : : "r0", "r1", "r2"); + return addr; +} + + +/* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + +static inline int __attribute__ ((unused)) +elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) +{ + Elf32_Addr *got; + extern void _dl_runtime_resolve (Elf32_Word); + extern void _dl_runtime_profile (Elf32_Word); + + if (l->l_info[DT_JMPREL] && lazy) + { + /* The GOT entries for functions in the PLT have not yet been filled + in. Their initial contents will arrange when called to load an + offset into the .rela.plt section and _GLOBAL_OFFSET_TABLE_[1], + and then jump to _GLOBAL_OFFSET_TABLE[2]. */ + got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); + got[1] = (Elf32_Addr) l; /* Identify this shared object. */ + + /* The got[2] entry contains the address of a function which gets + called to get the address of a so far unresolved function and + jump to it. The profiling extension of the dynamic linker allows + to intercept the calls to collect information. In this case we + don't store the address in the GOT so that all future calls also + end in this function. */ + if (profile) + { + got[2] = (Elf32_Addr) &_dl_runtime_profile; + /* Say that we really want profiling and the timers are started. */ + _dl_profile_map = l; + } + else + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ + got[2] = (Elf32_Addr) &_dl_runtime_resolve; + } + return lazy; +} + +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. */ + +#define ELF_MACHINE_RUNTIME_FIXUP_ARGS int plt_type + +#ifdef SHARED +#define FUN_ADDR "\ + mov.l 1f,r2 + mova 1f,r0 + bra 2f + add r0,r2 ! Get GOT address in r2 +0: .align 2 +1: .long _GLOBAL_OFFSET_TABLE_ +2: mov.l 3f,r0 + add r2,r0" +#define GOTJMP(x) #x "@GOTOFF" +#else +#define FUN_ADDR "\ + mov.l 3f,r0" +#define GOTJMP(x) #x +#endif + +#if defined (KERNEL_MATH_EMULATION) +#define FGR_SAVE "\ + sts.l fpscr, @-r15 + mov #8,r3 + swap.w r3, r3 + lds r3, fpscr + fmov.s fr11, @-r15 + fmov.s fr10, @-r15 + fmov.s fr9, @-r15 + fmov.s fr8, @-r15 + fmov.s fr7, @-r15 + fmov.s fr6, @-r15 + fmov.s fr5, @-r15 + fmov.s fr4, @-r15" +#define FGR_LOAD "\ + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + lds.l @r15+, fpscr" +#else +#define FGR_SAVE "" +#define FGR_LOAD "" +#endif + +#ifndef PROF +# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ + .text + .globl _dl_runtime_resolve + .type _dl_runtime_resolve, @function + .align 5 +_dl_runtime_resolve: + mov.l r3,@-r15 + mov.l r4,@-r15 + mov.l r5,@-r15 + mov.l r6,@-r15 + mov.l r7,@-r15 + mov.l r12,@-r15 + movt r3 ! Save T flag. + mov.l r3,@-r15 + " FGR_SAVE " + sts.l pr,@-r15 + mov r0,r4 ! PLT type + mov r2,r5 ! link map address + " FUN_ADDR " + jsr @r0 ! Call resolver. + mov r1,r6 ! reloc offset + lds.l @r15+,pr ! Get register content back. + " FGR_LOAD " + mov.l @r15+,r3 + shal r3 ! Lode T flag. + mov.l @r15+,r12 + mov.l @r15+,r7 + mov.l @r15+,r6 + mov.l @r15+,r5 + mov.l @r15+,r4 + jmp @r0 ! Jump to function address. + mov.l @r15+,r3 + .align 2 +3: + .long " GOTJMP (fixup) " + .size _dl_runtime_resolve, .-_dl_runtime_resolve + + .globl _dl_runtime_profile + .type _dl_runtime_profile, @function + .align 5 +_dl_runtime_profile: + mov.l r3,@-r15 + mov.l r4,@-r15 + mov.l r5,@-r15 + mov.l r6,@-r15 + mov.l r7,@-r15 + mov.l r12,@-r15 + movt r3 ! Save T flag. + mov.l r3,@-r15 + " FGR_SAVE " + sts.l pr,@-r15 + mov r0,r4 ! PLT type + mov r2,r5 ! link map address + sts pr,r7 ! return address + " FUN_ADDR " + jsr @r0 ! Call resolver. + mov r1,r6 ! reloc offset + lds.l @r15+,pr ! Get register content back. + " FGR_LOAD " + mov.l @r15+,r3 + shal r3 ! Lode T flag. + mov.l @r15+,r12 + mov.l @r15+,r7 + mov.l @r15+,r6 + mov.l @r15+,r5 + mov.l @r15+,r4 + jmp @r0 ! Jump to function address. + mov.l @r15+,r3 + .align 2 +3: + .long " GOTJMP (profile_fixup) " + .size _dl_runtime_profile, .-_dl_runtime_profile + .previous +"); +#else +# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ + .text + .globl _dl_runtime_resolve + .globl _dl_runtime_profile + .type _dl_runtime_resolve, @function + .type _dl_runtime_profile, @function + .align 5 +_dl_runtime_resolve: +_dl_runtime_profile: + mov.l r3,@-r15 + mov.l r4,@-r15 + mov.l r5,@-r15 + mov.l r6,@-r15 + mov.l r7,@-r15 + mov.l r12,@-r15 + movt r3 ! Save T flag. + mov.l r3,@-r15 + " FGR_SAVE " + sts.l pr,@-r15 + mov r0,r4 ! PLT type + mov r2,r5 ! link map address + sts pr,r7 ! return address + " FUN_ADDR " + jsr @r0 ! Call resolver. + mov r1,r6 ! reloc offset + lds.l @r15+,pr ! Get register content back. + " FGR_LOAD " + mov.l @r15+,r3 + shal r3 ! Lode T flag. + mov.l @r15+,r12 + mov.l @r15+,r7 + mov.l @r15+,r6 + mov.l @r15+,r5 + mov.l @r15+,r4 + jmp @r0 ! Jump to function address. + mov.l @r15+,r3 + .align 2 +3: + .long " GOTJMP (fixup) " + .size _dl_runtime_resolve, .-_dl_runtime_resolve + .size _dl_runtime_profile, .-_dl_runtime_profile + .previous +"); +#endif + +/* Mask identifying addresses reserved for the user program, + where the dynamic linker should not map anything. */ +#define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL + +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ + +#define RTLD_START asm ("\ +.text\n\ +.globl _start\n\ +.globl _dl_start_user\n\ +_start:\n\ + mov r15,r4\n\ + mov.l .L_dl_start,r1\n\ + mova .L_dl_start,r0\n\ + add r1,r0\n\ + jsr @r0\n\ + nop\n\ +_dl_start_user:\n\ + ! Save the user entry point address in r8.\n\ + mov r0,r8\n\ + ! Point r12 at the GOT.\n\ + mov.l 1f,r12\n\ + mova 1f,r0\n\ + bra 2f\n\ + add r0,r12\n\ + .align 2\n\ +1: .long _GLOBAL_OFFSET_TABLE_\n\ +2: ! Store the highest stack address\n\ + mov.l .L_stack_end,r0\n\ + mov.l @(r0,r12),r0\n\ + mov.l r15,@r0\n\ + ! See if we were run as a command with the executable file\n\ + ! name as an extra leading argument.\n\ + mov.l .L_dl_skip_args,r0\n\ + mov.l @(r0,r12),r0\n\ + mov.l @r0,r0\n\ + ! Get the original argument count.\n\ + mov.l @r15,r5\n\ + ! Subtract _dl_skip_args from it.\n\ + sub r0,r5\n\ + ! Adjust the stack pointer to skip _dl_skip_args words.\n\ + shll2 r0\n\ + add r0,r15\n\ + ! Store back the modified argument count.\n\ + mov.l r5,@r15\n\ + ! Compute argv address and envp.\n\ + mov r15,r6\n\ + add #4,r6\n\ + mov r5,r7\n\ + shll2 r7\n\ + add r15,r7\n\ + mov.l .L_dl_loaded,r0\n\ + mov.l @(r0,r12),r0\n\ + mov.l @r0,r4\n\ + ! Call _dl_init.\n\ + mov.l .L_dl_init,r1\n\ + mova .L_dl_init,r0\n\ + add r1,r0\n\ + jsr @r0\n\ + nop\n\ +1: ! Clear the startup flag.\n\ + mov.l .L_dl_starting_up,r0\n\ + mov.l @(r0,r12),r0\n\ + mov #0,r2\n\ + mov.l r2,@r0\n\ + ! Pass our finalizer function to the user in r4, as per ELF ABI.\n\ + mov.l .L_dl_fini,r0\n\ + mov.l @(r0,r12),r4\n\ + ! Jump to the user's entry point.\n\ + jmp @r8\n\ + nop\n\ + .align 2\n\ +.L_dl_start:\n\ + .long _dl_start@PLT\n\ +.L_stack_end:\n\ + .long __libc_stack_end@GOT\n\ +.L_dl_skip_args:\n\ + .long _dl_skip_args@GOT\n\ +.L_dl_init:\n\ + .long _dl_init@PLT\n\ +.L_dl_loaded:\n\ + .long _dl_loaded@GOT\n\ +.L_dl_starting_up:\n\ + .long _dl_starting_up@GOT\n\ +.L_dl_fini:\n\ + .long _dl_fini@GOT\n\ +.previous\n\ +"); + +/* Nonzero iff TYPE should not be allowed to resolve to one of + the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_lookup_noexec_p(type) ((type) == R_SH_COPY) + +/* Nonzero iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. */ +#define elf_machine_lookup_noplt_p(type) ((type) == R_SH_JMP_SLOT) + +/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ +#define ELF_MACHINE_JMP_SLOT R_SH_JMP_SLOT + +/* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +#define DL_PLATFORM_INIT dl_platform_init () + +extern const char *_dl_platform; + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (_dl_platform != NULL && *_dl_platform == '\0') + /* Avoid an empty string which would disturb us. */ + _dl_platform = NULL; +} + +static inline Elf32_Addr +elf_machine_fixup_plt (struct link_map *map, lookup_t t, + const Elf32_Rela *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr value) +{ + return *reloc_addr = value; +} + +/* Return the final value of a plt relocation. */ +static inline Elf32_Addr +elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc, + Elf32_Addr value) +{ + return value + reloc->r_addend; +} + +#endif /* !dl_machine_h */ + +#ifdef RESOLVE + +/* SH never uses Elf32_Rel relocations. */ +#define ELF_MACHINE_NO_REL 1 + +extern char **_dl_argv; + +/* 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 Elf32_Rela *reloc, + const Elf32_Sym *sym, const struct r_found_version *version, + Elf32_Addr *const reloc_addr) +{ + if (ELF32_R_TYPE (reloc->r_info) == R_SH_RELATIVE) + { +#ifndef RTLD_BOOTSTRAP + if (map != &_dl_rtld_map) /* Already done in rtld itself. */ +#endif + *reloc_addr = map->l_addr + reloc->r_addend; + } + else if (ELF32_R_TYPE (reloc->r_info) != R_SH_NONE) + { + const Elf32_Sym *const refsym = sym; + Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info)); + if (sym) + value += sym->st_value; + value += reloc->r_addend; + + switch (ELF32_R_TYPE (reloc->r_info)) + { + case R_SH_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 + || (sym->st_size < refsym->st_size && _dl_verbose)) + { + const char *strtab; + + strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); + _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>", + ": Symbol `", strtab + refsym->st_name, + "' has different size in shared object, " + "consider re-linking\n", NULL); + } + memcpy (reloc_addr, (void *) value, MIN (sym->st_size, + refsym->st_size)); + break; + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + *reloc_addr = value; + break; + case R_SH_DIR32: + { +#ifndef RTLD_BOOTSTRAP + /* 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); + if (map == &_dl_rtld_map) + /* Undo the relocation done here during bootstrapping. + Now we will relocate it anew, possibly using a + binding found in the user program or a loaded library + rather than the dynamic linker's built-in definitions + used while loading those libraries. */ + value -= map->l_addr + refsym->st_value + reloc->r_addend; +#endif + *reloc_addr = value; + break; + } + case R_SH_REL32: + *reloc_addr = (value - (Elf32_Addr) reloc_addr); + break; + default: + _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 0); + break; + } + } +} + +static inline void +elf_machine_lazy_rel (struct link_map *map, + Elf32_Addr l_addr, const Elf32_Rela *reloc) +{ + Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset); + /* Check for unexpected PLT reloc type. */ + if (ELF32_R_TYPE (reloc->r_info) == R_SH_JMP_SLOT) + *reloc_addr += l_addr; + else + _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1); +} + +#endif /* RESOLVE */ diff --git a/sysdeps/sh/sh3/setjmp.S b/sysdeps/sh/sh3/setjmp.S new file mode 100644 index 0000000000..ea41f459de --- /dev/null +++ b/sysdeps/sh/sh3/setjmp.S @@ -0,0 +1,67 @@ +/* setjmp for SH4. + Copyright (C) 1999, 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <sysdep.h> +#define _SETJMP_H +#define _ASM +#include <bits/setjmp.h> + + /* Binary compatibility entry point. */ +ENTRY (__setjmp) + mov #0, r5 +ENTRY (__sigsetjmp) + /* Save registers */ + add #JB_SIZE, r4 + stc.l gbr, @-r4 + sts.l pr, @-r4 + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef SHARED + mov.l 1f, r1 + mova 1f, r0 + bra 2f + add r1, r0 + .align 2 +1: + .long _GLOBAL_OFFSET_TABLE_ +2: + mov.l .L1, r1 + mov.l @(r0,r1), r1 + jmp @r1 + nop + .align 2 +.L1: + .long C_SYMBOL_NAME(__sigjmp_save@GOT) +#else + mov.l .L1, r1 + jmp @r1 + nop + .align 2 +.L1: + .long C_SYMBOL_NAME(__sigjmp_save) +#endif +END (__setjmp) |