]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-startup.h
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / ldso / ldso / mips / dl-startup.h
1 /* Any assembly language/system dependent hacks needed to setup boot1.c so it
2  * will work as expected and cope with whatever platform specific wierdness is
3  * needed for this architecture.
4  * Copyright (C) 2005 by Joakim Tjernlund
5  * Copyright (C) 2005 by Erik Andersen
6  */
7
8
9 #include <sgidefs.h>
10 __asm__(""
11     "   .text\n"
12     "   .globl  _start\n"
13     "   .ent    _start\n"
14     "   .type   _start,@function\n"
15     "   .hidden _start\n"
16     "_start:\n"
17     "   .set noreorder\n"
18     "   move    $25, $31\n"
19     "   bal     0f\n"
20     "   nop\n"
21     "0:\n"
22 #if _MIPS_SIM == _MIPS_SIM_ABI32
23     "   .cpload $31\n"
24 #else   /* N32 || N64 */
25     "   .cpsetup $31, $2, 0b\n"
26 #endif  /* N32 || N64 */
27     "   move    $31, $25\n"
28     "   .set reorder\n"
29 #if _MIPS_SIM == _MIPS_SIM_ABI64
30     "   dla     $4, _DYNAMIC\n"
31     "   sd      $4, -0x7ff0($28)\n"
32 #else   /* O32 || N32 */
33     "   la      $4, _DYNAMIC\n"
34     "   sw      $4, -0x7ff0($28)\n"
35 #endif  /* O32 || N32 */
36     "   move    $4, $29\n"
37 #if _MIPS_SIM == _MIPS_SIM_ABI32
38     "   subu    $29, 16\n"
39 #endif
40 #if _MIPS_SIM == _MIPS_SIM_ABI64
41     "   dla     $8, .coff\n"
42 #else   /* O32 || N32 */
43     "   la      $8, .coff\n"
44 #endif  /* O32 || N32 */
45     "   bltzal  $8, .coff\n"
46     ".coff:\n"
47 #if _MIPS_SIM == _MIPS_SIM_ABI64
48     "   dsubu   $8, $31, $8\n"
49     "   dla     $25, _dl_start\n"
50     "   daddu   $25, $8\n"
51 #else   /* O32 || N32 */
52     "   subu    $8, $31, $8\n"
53     "   la      $25, _dl_start\n"
54     "   addu    $25, $8\n"
55 #endif  /* O32 || N32 */
56     "   jalr    $25\n"
57 #if _MIPS_SIM == _MIPS_SIM_ABI32
58     "   addiu   $29, 16\n"
59 #endif
60     "   move    $16, $28\n"
61     "   move    $17, $2\n"
62 #if _MIPS_SIM == _MIPS_SIM_ABI64
63     "   ld      $2, _dl_skip_args\n"
64     "   beq     $2, $0, 1f\n"
65     "   ld      $4, 0($29)\n"
66     "   dsubu   $4, $2\n"
67     "   dsll    $2, 2\n"
68     "   daddu   $29, $2\n"
69     "   sd      $4, 0($29)\n"
70     "1:\n"
71     "   ld      $5, 0($29)\n"
72     "   dla     $6, 8 ($29)\n"
73     "   dsll    $7, $5, 2\n"
74     "   daddu   $7, $7, $6\n"
75     "   daddu   $7, $7, 4\n"
76     "   and     $2, $29, -4 * 4\n"
77     "   sd      $29, -8($2)\n"
78     "   dsubu   $29, $2, 32\n"
79     "   ld      $29, 24($29)\n"
80     "   dla     $2, _dl_fini\n"
81 #else   /* O32 || N32 */
82     "   lw      $2, _dl_skip_args\n"
83     "   beq     $2, $0, 1f\n"
84     "   lw      $4, 0($29)\n"
85     "   subu    $4, $2\n"
86     "   sll     $2, 2\n"
87     "   addu    $29, $2\n"
88     "   sw      $4, 0($29)\n"
89     "1:\n"
90     "   lw      $5, 0($29)\n"
91     "   la      $6, 4 ($29)\n"
92     "   sll     $7, $5, 2\n"
93     "   addu    $7, $7, $6\n"
94     "   addu    $7, $7, 4\n"
95     "   and     $2, $29, -2 * 4\n"
96     "   sw      $29, -4($2)\n"
97     "   subu    $29, $2, 32\n"
98 #if _MIPS_SIM == _MIPS_SIM_ABI32
99     "   .cprestore 16\n"
100 #endif
101     "   lw      $29, 28($29)\n"
102     "   la      $2, _dl_fini\n"
103 #endif  /* O32 || N32 */
104     "   move    $25, $17\n"
105     "   jr      $25\n"
106     ".end       _start\n"
107     ".size      _start, . -_start\n"
108     "\n\n"
109     "\n\n"
110     ".previous\n"
111 );
112
113 /*
114  * Get a pointer to the argv array.  On many platforms this can be just
115  * the address of the first argument, on other platforms we need to
116  * do something a little more subtle here.
117  */
118 #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1)
119
120
121 /* We can't call functions earlier in the dl startup process */
122 #define NO_FUNCS_BEFORE_BOOTSTRAP
123
124
125 /*
126  * Here is a macro to perform the GOT relocation. This is only
127  * used when bootstrapping the dynamic loader.
128  */
129 #define PERFORM_BOOTSTRAP_GOT(tpnt)                                             \
130 do {                                                                            \
131         ElfW(Sym) *sym;                                                         \
132         ElfW(Addr) i;                                                           \
133         register ElfW(Addr) gp __asm__ ("$28");                                 \
134         ElfW(Addr) *mipsgot = elf_mips_got_from_gpreg (gp);                     \
135                                                                                 \
136         /* Add load address displacement to all local GOT entries */            \
137         i = 2;                                                                  \
138         while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX])                 \
139                 mipsgot[i++] += tpnt->loadaddr;                                 \
140                                                                                 \
141         /* Handle global GOT entries */                                         \
142         mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];                 \
143         sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] +                     \
144                         tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];                 \
145         i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\
146                                                                                 \
147         while (i--) {                                                           \
148                 if (sym->st_shndx == SHN_UNDEF ||                               \
149                         sym->st_shndx == SHN_COMMON)                            \
150                         *mipsgot = tpnt->loadaddr + sym->st_value;              \
151                 else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&               \
152                         *mipsgot != sym->st_value)                              \
153                         *mipsgot += tpnt->loadaddr;                             \
154                 else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) {            \
155                         if (sym->st_other == 0)                                 \
156                                 *mipsgot += tpnt->loadaddr;                     \
157                 }                                                               \
158                 else                                                            \
159                         *mipsgot = tpnt->loadaddr + sym->st_value;              \
160                                                                                 \
161                 mipsgot++;                                                      \
162                 sym++;                                                          \
163         }                                                                       \
164 } while (0)
165
166 /*
167  * Here is a macro to perform a relocation.  This is only used when
168  * bootstrapping the dynamic loader.
169  */
170 #if _MIPS_SIM == _MIPS_SIM_ABI64        /* consult with glibc sysdeps/mips/dl-machine.h 1.69 */
171 #define R_MIPS_BOOTSTRAP_RELOC ((R_MIPS_64 << 8) | R_MIPS_REL32)
172 #else   /* N32 || O32 */
173 #define R_MIPS_BOOTSTRAP_RELOC R_MIPS_REL32
174 #endif
175 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB)                    \
176         switch(ELF_R_TYPE((RELP)->r_info)) {                                    \
177         case R_MIPS_BOOTSTRAP_RELOC:                                            \
178                 if (SYMTAB) {                                                   \
179                         if (symtab_index<tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])\
180                                 *REL += SYMBOL;                                 \
181                 }                                                               \
182                 else {                                                          \
183                         *REL += LOAD;                                           \
184                 }                                                               \
185                 break;                                                          \
186         case R_MIPS_NONE:                                                       \
187                 break;                                                          \
188         default:                                                                \
189                 SEND_STDERR("Aiieeee!");                                        \
190                 _dl_exit(1);                                                    \
191         }