OSDN Git Service

ldso_sh: Provide only one definition for elf_machine_type_class
[uclinux-h8/uClibc.git] / ldso / ldso / sh / dl-sysdep.h
1 /*
2  * Various assembly language/system dependent hacks that are required
3  * so that we can minimize the amount of platform specific code.
4  */
5
6 /* Define this if the system uses RELOCA.  */
7 #define ELF_USES_RELOCA
8 #include <elf.h>
9 /*
10  * Initialization sequence for a GOT.
11  */
12 #define INIT_GOT(GOT_BASE,MODULE) \
13 {                               \
14   GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
15   GOT_BASE[1] = (unsigned long) (MODULE); \
16 }
17
18 /* Here we define the magic numbers that this dynamic loader should accept */
19 #define MAGIC1 EM_SH
20 #undef  MAGIC2
21
22 /* Used for error messages */
23 #define ELF_TARGET "sh"
24
25 struct elf_resolve;
26 extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
27
28 static __always_inline unsigned int
29 _dl_urem(unsigned int n, unsigned int base)
30 {
31   int res;
32
33         __asm__ (""\
34                 "mov    #0, r0\n\t" \
35                 "div0u\n\t" \
36                 "" \
37                 "! get one bit from the msb of the numerator into the T\n\t" \
38                 "! bit and divide it by whats in %2.  Put the answer bit\n\t" \
39                 "! into the T bit so it can come out again at the bottom\n\t" \
40                 ""                              \
41                 "rotcl  %1 ; div1 %2, r0\n\t"   \
42                 "rotcl  %1 ; div1 %2, r0\n\t"   \
43                 "rotcl  %1 ; div1 %2, r0\n\t"   \
44                 "rotcl  %1 ; div1 %2, r0\n\t"   \
45                 "rotcl  %1 ; div1 %2, r0\n\t"   \
46                 "rotcl  %1 ; div1 %2, r0\n\t"   \
47                 "rotcl  %1 ; div1 %2, r0\n\t"   \
48                 "rotcl  %1 ; div1 %2, r0\n\t"   \
49                 ""                              \
50                 "rotcl  %1 ; div1 %2, r0\n\t"   \
51                 "rotcl  %1 ; div1 %2, r0\n\t"   \
52                 "rotcl  %1 ; div1 %2, r0\n\t"   \
53                 "rotcl  %1 ; div1 %2, r0\n\t"   \
54                 "rotcl  %1 ; div1 %2, r0\n\t"   \
55                 "rotcl  %1 ; div1 %2, r0\n\t"   \
56                 "rotcl  %1 ; div1 %2, r0\n\t"   \
57                 "rotcl  %1 ; div1 %2, r0\n\t"   \
58                 ""                              \
59                 "rotcl  %1 ; div1 %2, r0\n\t"   \
60                 "rotcl  %1 ; div1 %2, r0\n\t"   \
61                 "rotcl  %1 ; div1 %2, r0\n\t"   \
62                 "rotcl  %1 ; div1 %2, r0\n\t"   \
63                 "rotcl  %1 ; div1 %2, r0\n\t"   \
64                 "rotcl  %1 ; div1 %2, r0\n\t"   \
65                 "rotcl  %1 ; div1 %2, r0\n\t"   \
66                 "rotcl  %1 ; div1 %2, r0\n\t"   \
67                 ""                              \
68                 "rotcl  %1 ; div1 %2, r0\n\t"   \
69                 "rotcl  %1 ; div1 %2, r0\n\t"   \
70                 "rotcl  %1 ; div1 %2, r0\n\t"   \
71                 "rotcl  %1 ; div1 %2, r0\n\t"   \
72                 "rotcl  %1 ; div1 %2, r0\n\t"   \
73                 "rotcl  %1 ; div1 %2, r0\n\t"   \
74                 "rotcl  %1 ; div1 %2, r0\n\t"   \
75                 "rotcl  %1 ; div1 %2, r0\n\t"   \
76                 "rotcl  %1\n\t"
77                 : "=r" (res)
78                 : "0" (n), "r" (base)
79                 : "r0","cc");
80
81         return n - (base * res);
82 }
83
84 #define do_rem(result, n, base)     ((result) = _dl_urem((n), (base)))
85
86 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
87    TLS variable, so undefined references should not be allowed to
88    define the value.
89    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
90    of the main executable's symbols, as for a COPY reloc.  */
91 # define elf_machine_type_class(type) \
92   ((((type) == R_SH_JMP_SLOT || (type) == R_SH_TLS_DTPMOD32                   \
93      || (type) == R_SH_TLS_DTPOFF32 || (type) == R_SH_TLS_TPOFF32)            \
94     * ELF_RTYPE_CLASS_PLT)                                                    \
95    | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
96
97 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
98    first element of the GOT.  This must be inlined in a function which
99    uses global data.  */
100 static __always_inline Elf32_Addr __attribute__ ((unused))
101 elf_machine_dynamic (void)
102 {
103         register Elf32_Addr *got;
104         __asm__ ("mov r12,%0" :"=r" (got));
105         return *got;
106 }
107
108 /* Return the run-time load address of the shared object.  */
109 static __always_inline Elf32_Addr __attribute__ ((unused))
110 elf_machine_load_address (void)
111 {
112         Elf32_Addr addr;
113         __asm__ ("mov.l 1f,r0\n\
114         mov.l 3f,r2\n\
115         add r12,r2\n\
116         mov.l @(r0,r12),r0\n\
117         bra 2f\n\
118          sub r0,r2\n\
119         .align 2\n\
120         1: .long _dl_start@GOT\n\
121         3: .long _dl_start@GOTOFF\n\
122         2: mov r2,%0"
123              : "=r" (addr) : : "r0", "r1", "r2");
124         return addr;
125 }
126
127 #define COPY_UNALIGNED_WORD(swp, twp, align) \
128   { \
129     void *__s = (swp), *__t = (twp); \
130     unsigned char *__s1 = __s, *__t1 = __t; \
131     unsigned short *__s2 = __s, *__t2 = __t; \
132     unsigned long *__s4 = __s, *__t4 = __t; \
133     switch ((align)) \
134     { \
135     case 0: \
136       *__t4 = *__s4; \
137       break; \
138     case 2: \
139       *__t2++ = *__s2++; \
140       *__t2 = *__s2; \
141       break; \
142     default: \
143       *__t1++ = *__s1++; \
144       *__t1++ = *__s1++; \
145       *__t1++ = *__s1++; \
146       *__t1 = *__s1; \
147       break; \
148     } \
149   }
150
151 static __always_inline void
152 elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
153                       Elf32_Word relative_count)
154 {
155         Elf32_Addr value;
156         Elf32_Rela * rpnt = (void *)rel_addr;
157
158         do {
159                 Elf32_Addr *const reloc_addr = (void *) (load_off + rpnt->r_offset);
160
161                 if (rpnt->r_addend)
162                         value = load_off + rpnt->r_addend;
163                 else {
164                         COPY_UNALIGNED_WORD (reloc_addr, &value, (int) reloc_addr & 3);
165                         value += load_off;
166                 }
167                 COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3);
168                 rpnt++;
169         } while (--relative_count);
170 #undef COPY_UNALIGNED_WORD
171 }