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