1 /* vi: set sw=8 ts=8: */
3 * Various assembly language/system dependent hacks that are required
4 * so that we can minimize the amount of platform specific code.
7 /* Define this if the system uses RELOCA. */
8 #define ELF_USES_RELOCA
11 * Initialization sequence for a GOT.
13 #define INIT_GOT(GOT_BASE,MODULE) \
15 GOT_BASE[2] = (unsigned long)_dl_linux_resolve; \
16 GOT_BASE[1] = (unsigned long)(MODULE); \
19 /* Here we define the magic numbers that this dynamic loader should accept */
23 /* Used for error messages */
24 #define ELF_TARGET "sh64"
26 /* Need bootstrap relocations */
27 #define ARCH_NEEDS_BOOTSTRAP_RELOCS
30 extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
32 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
33 TLS variable, so undefined references should not be allowed to
35 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
36 of the main executable's symbols, as for a COPY reloc. */
37 #define elf_machine_type_class(type) \
38 ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
39 | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
41 /* Return the link-time address of _DYNAMIC. Conveniently, this is the
42 first element of the GOT. This must be inlined in a function which
44 static __always_inline Elf32_Addr elf_machine_dynamic(void)
46 register Elf32_Addr *got;
49 * The toolchain adds 32768 to the GOT address, we compensate for
50 * that in the movi/sub pair.
52 * XXX: If this is cleaned up in the toolchain, we can end up
53 * saving 2 instructions and subsequently free up r1 from the
57 "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) >> 16) & 0xffff), r2\n\t"
58 "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) & 0xffff), r2\n\t"
59 ".LZZZ1:\tptrel/u r2, tr0\n\t"
71 /* Return the run-time load address of the shared object. */
72 static __always_inline Elf32_Addr elf_machine_load_address(void)
77 "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) >> 16) & 0xffff), r0\n\t"
78 "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) & 0xffff), r0\n\t"
79 ".LZZZ2:\tptrel/u r0, tr0\n\t"
80 "movi\t(((_dl_start@GOTOFF) >> 16) & 0xffff), r2\n\t"
81 "shori\t((_dl_start@GOTOFF) & 0xffff), r2\n\t"
84 "movi\t(((_dl_start@GOT) >> 16) & 0xffff), r1\n\t"
85 "shori\t((_dl_start@GOT) & 0xffff), r1\n\t"
86 "ldx.l\tr1, r0, r1\n\t"
90 : "r0", "r1", "r2", "tr0"
97 * XXX: As we don't need to worry about r25 clobbering, we could probably
98 * get away with inlining {st,ld}{x,}.l and friends here instead and
99 * forego gcc's idea of code generation.
101 #define COPY_UNALIGNED_WORD(swp, twp, align) \
103 void *__s = (swp), *__t = (twp); \
104 unsigned char *__s1 = __s, *__t1 = __t; \
105 unsigned short *__s2 = __s, *__t2 = __t; \
106 unsigned long *__s4 = __s, *__t4 = __t; \
125 static __always_inline void
126 elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
127 Elf32_Word relative_count)
129 Elf32_Addr value, word;
130 Elf32_Rela *rpnt = (void *)rel_addr;
131 int reloc_type = ELF_R_TYPE(rpnt->r_info);
134 Elf32_Addr *const reloc_addr =
135 (void *)(load_off + rpnt->r_offset);
136 int align = (int)reloc_addr & 3;
138 switch (reloc_type) {
139 case R_SH_RELATIVE_LOW16:
140 COPY_UNALIGNED_WORD(reloc_addr, &word, align);
142 value = (rpnt->r_addend + load_off);
143 word |= (value & 0xffff) << 10;
144 COPY_UNALIGNED_WORD(&word, reloc_addr, align);
146 case R_SH_RELATIVE_MEDLOW16:
147 COPY_UNALIGNED_WORD(reloc_addr, &word, align);
149 value = (rpnt->r_addend + load_off) >> 16;
150 word |= (value & 0xffff) << 10;
151 COPY_UNALIGNED_WORD(&word, reloc_addr, align);
154 if (rpnt->r_addend) {
155 value = load_off + rpnt->r_addend;
157 COPY_UNALIGNED_WORD(reloc_addr, &value, align);
161 COPY_UNALIGNED_WORD(&value, reloc_addr, align);
166 } while (--relative_count);
167 #undef COPY_UNALIGNED_WORD