OSDN Git Service

avr32: common do_rem is good for it
[uclinux-h8/uClibc.git] / ldso / ldso / avr32 / 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  * Copyright (C) 2004-2007 Atmel Corporation
6  *
7  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
8  */
9
10 /* Define this if the system uses RELOCA. */
11 #define ELF_USES_RELOCA
12
13 #include <elf.h>
14
15 #define ARCH_NUM 1
16 #define DT_AVR32_GOTSZ_IDX      (DT_NUM + OS_NUM)
17
18 #define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr)                    \
19         do {                                                            \
20                 if (dpnt->d_tag == DT_AVR32_GOTSZ)                      \
21                         dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \
22         } while (0)
23
24 /* Initialization sequence for the application/library GOT. */
25 #define INIT_GOT(GOT_BASE,MODULE)                                       \
26         do {                                                            \
27                 unsigned long _i, _nr_got;                              \
28                                                                         \
29                 GOT_BASE[0] = (unsigned long) _dl_linux_resolve;        \
30                 GOT_BASE[1] = (unsigned long) MODULE;                   \
31                                                                         \
32                 /* Add load address displacement to all GOT entries */  \
33                 _nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4; \
34                 for (_i = 2; _i < _nr_got; _i++)                                \
35                         GOT_BASE[_i] += (unsigned long)MODULE->loadaddr;        \
36         } while (0)
37
38 /* Here we define the magic numbers that this dynamic loader should accept */
39 #define MAGIC1 EM_AVR32
40 #undef MAGIC2
41
42 /* Used for error messages */
43 #define ELF_TARGET "AVR32"
44
45 /* Need bootstrap relocations */
46 #define ARCH_NEEDS_BOOTSTRAP_RELOCS
47
48 unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
49
50 #define elf_machine_type_class(type)                            \
51         ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
52
53 /* AVR32 doesn't need any COPY relocs */
54 #define DL_NO_COPY_RELOCS
55
56 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
57    first element of the GOT.  This must be inlined in a function which
58    uses global data.  */
59 static __always_inline Elf32_Addr
60 elf_machine_dynamic (void)
61 {
62         register Elf32_Addr *got __asm__("r6");
63         return *got;
64 }
65
66 /* Return the run-time load address of the shared object.  */
67 static __always_inline Elf32_Addr
68 elf_machine_load_address (void)
69 {
70         extern void __dl_start __asm__("_dl_start");
71         Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
72         Elf32_Addr pcrel_addr;
73
74         __asm__("       lddpc   %0, 2f\n"
75                "1:      add     %0, pc\n"
76                "        rjmp    3f\n"
77                "        .align  2\n"
78                "2:      .long   _dl_start - 1b\n"
79                "3:\n"
80                : "=r"(pcrel_addr) : : "cc");
81
82         return pcrel_addr - got_addr;
83 }
84
85 /*
86  * Perform any RELATIVE relocations specified by DT_RELCOUNT.
87  * Currently, we don't use that tag, but we might in the future as
88  * this would reduce the startup time somewhat (although probably not by much).
89  */
90 static __always_inline void
91 elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
92                       Elf32_Word relative_count)
93 {
94         Elf32_Rela *rpnt = (void *)rel_addr;
95
96         do {
97                 Elf32_Addr *reloc_addr;
98                 reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
99                 *reloc_addr = load_off + rpnt->r_addend;
100         } while (--relative_count);
101 }