1/*
2 * Special support for eabi and SVR4
3 *
4 *   Copyright (C) 1995-2022 Free Software Foundation, Inc.
5 *   Written By Michael Meissner
6 *
7 * This file is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 3, or (at your option) any
10 * later version.
11 *
12 * This file is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * Under Section 7 of GPL version 3, you are granted additional
18 * permissions described in the GCC Runtime Library Exception, version
19 * 3.1, as published by the Free Software Foundation.
20 *
21 * You should have received a copy of the GNU General Public License and
22 * a copy of the GCC Runtime Library Exception along with this program;
23 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 * <http://www.gnu.org/licenses/>.
25 */
26
27/* Do any initializations needed for the eabi environment */
28
29          .section ".text"
30          #include "ppc-asm.h"
31
32#ifndef __powerpc64__
33
34           .section ".got2","aw"
35          .align    2
36.LCTOC1 = . /* +32768 */
37
38/* Table of addresses */
39.Ltable = .-.LCTOC1
40          .long     .LCTOC1                                 /* address we are really at */
41
42.Lsda = .-.LCTOC1
43          .long     _SDA_BASE_                              /* address of the first small data area */
44
45.Lsdas = .-.LCTOC1
46          .long     __SDATA_START__                         /* start of .sdata/.sbss section */
47
48.Lsdae = .-.LCTOC1
49          .long     __SBSS_END__                            /* end of .sdata/.sbss section */
50
51.Lsda2 = .-.LCTOC1
52          .long     _SDA2_BASE_                             /* address of the second small data area */
53
54.Lsda2s = .-.LCTOC1
55          .long     __SDATA2_START__              /* start of .sdata2/.sbss2 section */
56
57.Lsda2e = .-.LCTOC1
58          .long     __SBSS2_END__                           /* end of .sdata2/.sbss2 section */
59
60#ifdef _RELOCATABLE
61.Lgots = .-.LCTOC1
62          .long     __GOT_START__                           /* Global offset table start */
63
64.Lgotm1 = .-.LCTOC1
65          .long     _GLOBAL_OFFSET_TABLE_-4                 /* end of GOT ptrs before BLCL + 3 reserved words */
66
67.Lgotm2 = .-.LCTOC1
68          .long     _GLOBAL_OFFSET_TABLE_+12      /* start of GOT ptrs after BLCL + 3 reserved words */
69
70.Lgote = .-.LCTOC1
71          .long     __GOT_END__                             /* Global offset table end */
72
73.Lgot2s = .-.LCTOC1
74          .long     __GOT2_START__                          /* -mrelocatable GOT pointers start */
75
76.Lgot2e = .-.LCTOC1
77          .long     __GOT2_END__                            /* -mrelocatable GOT pointers end */
78
79.Lfixups = .-.LCTOC1
80          .long     __FIXUP_START__                         /* start of .fixup section */
81
82.Lfixupe = .-.LCTOC1
83          .long     __FIXUP_END__                           /* end of .fixup section */
84
85.Lctors = .-.LCTOC1
86          .long     __CTOR_LIST__                           /* start of .ctor section */
87
88.Lctore = .-.LCTOC1
89          .long     __CTOR_END__                            /* end of .ctor section */
90
91.Ldtors = .-.LCTOC1
92          .long     __DTOR_LIST__                           /* start of .dtor section */
93
94.Ldtore = .-.LCTOC1
95          .long     __DTOR_END__                            /* end of .dtor section */
96
97.Lexcepts = .-.LCTOC1
98          .long     __EXCEPT_START__              /* start of .gcc_except_table section */
99
100.Lexcepte = .-.LCTOC1
101          .long     __EXCEPT_END__                          /* end of .gcc_except_table section */
102
103.Linit = .-.LCTOC1
104          .long     .Linit_p                      /* address of variable to say we've been called */
105
106          .text
107          .align    2
108.Lptr:
109          .long     .LCTOC1-.Laddr                          /* PC relative pointer to .got2 */
110#endif
111
112          .data
113          .align    2
114.Linit_p:
115          .long     0
116
117          .text
118
119FUNC_START(__eabi)
120
121/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can
122   be assembled with other assemblers than GAS.  */
123
124#ifndef _RELOCATABLE
125          addis     10,0,.Linit_p@ha              /* init flag */
126          addis     11,0,.LCTOC1@ha                         /* load address of .LCTOC1 */
127          lwz       9,.Linit_p@l(10)              /* init flag */
128          addi      11,11,.LCTOC1@l
129          cmplwi    2,9,0                                   /* init flag != 0? */
130          bnelr     2                                       /* return now, if we've been called already */
131          stw       1,.Linit_p@l(10)              /* store a nonzero value in the done flag */
132
133#else /* -mrelocatable */
134          mflr      0
135          bl        .Laddr                                  /* get current address */
136.Laddr:
137          mflr      12                                      /* real address of .Laddr */
138          lwz       11,(.Lptr-.Laddr)(12)                   /* linker generated address of .LCTOC1 */
139          add       11,11,12                      /* correct to real pointer */
140          lwz       12,.Ltable(11)                          /* get linker's idea of where .Laddr is */
141          lwz       10,.Linit(11)                           /* address of init flag */
142          subf.     12,12,11                      /* calculate difference */
143          lwzx      9,10,12                                 /* done flag */
144          cmplwi    2,9,0                                   /* init flag != 0? */
145          mtlr      0                                       /* restore in case branch was taken */
146          bnelr     2                                       /* return now, if we've been called already */
147          stwx      1,10,12                                 /* store a nonzero value in the done flag */
148          beq+      0,.Lsdata                     /* skip if we don't need to relocate */
149
150/* We need to relocate the .got2 pointers.  */
151
152          lwz       3,.Lgot2s(11)                           /* GOT2 pointers start */
153          lwz       4,.Lgot2e(11)                           /* GOT2 pointers end */
154          add       3,12,3                                  /* adjust pointers */
155          add       4,12,4
156          bl        FUNC_NAME(__eabi_convert)     /* convert pointers in .got2 section */
157
158/* Fixup the .ctor section for static constructors */
159
160          lwz       3,.Lctors(11)                           /* constructors pointers start */
161          lwz       4,.Lctore(11)                           /* constructors pointers end */
162          bl        FUNC_NAME(__eabi_convert)     /* convert constructors */
163
164/* Fixup the .dtor section for static destructors */
165
166          lwz       3,.Ldtors(11)                           /* destructors pointers start */
167          lwz       4,.Ldtore(11)                           /* destructors pointers end */
168          bl        FUNC_NAME(__eabi_convert)     /* convert destructors */
169
170/* Fixup the .gcc_except_table section for G++ exceptions */
171
172          lwz       3,.Lexcepts(11)                         /* exception table pointers start */
173          lwz       4,.Lexcepte(11)                         /* exception table pointers end */
174          bl        FUNC_NAME(__eabi_convert)     /* convert exceptions */
175
176/* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */
177
178          lwz       3,.Lgots(11)                            /* GOT table pointers start */
179          lwz       4,.Lgotm1(11)                           /* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */
180          bl        FUNC_NAME(__eabi_convert)     /* convert lower GOT */
181
182/* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */
183
184          lwz       3,.Lgotm2(11)                           /* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */
185          lwz       4,.Lgote(11)                            /* GOT table pointers end */
186          bl        FUNC_NAME(__eabi_convert)     /* convert lower GOT */
187
188/* Fixup any user initialized pointers now (the compiler drops pointers to */
189/* each of the relocs that it does in the .fixup section).  */
190
191.Lfix:
192          lwz       3,.Lfixups(11)                          /* fixup pointers start */
193          lwz       4,.Lfixupe(11)                          /* fixup pointers end */
194          bl        FUNC_NAME(__eabi_uconvert)    /* convert user initialized pointers */
195
196.Lsdata:
197          mtlr      0                                       /* restore link register */
198#endif /* _RELOCATABLE */
199
200/* Only load up register 13 if there is a .sdata and/or .sbss section */
201          lwz       3,.Lsdas(11)                            /* start of .sdata/.sbss section */
202          lwz       4,.Lsdae(11)                            /* end of .sdata/.sbss section */
203          cmpw      1,3,4                                   /* .sdata/.sbss section non-empty? */
204          beq-      1,.Lsda2l                     /* skip loading r13 */
205
206          lwz       13,.Lsda(11)                            /* load r13 with _SDA_BASE_ address */
207
208/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
209
210.Lsda2l:
211          lwz       3,.Lsda2s(11)                           /* start of .sdata/.sbss section */
212          lwz       4,.Lsda2e(11)                           /* end of .sdata/.sbss section */
213          cmpw      1,3,4                                   /* .sdata/.sbss section non-empty? */
214          beq+      1,.Ldone                      /* skip loading r2 */
215
216          lwz       2,.Lsda2(11)                            /* load r2 with _SDA2_BASE_ address */
217
218/* Done adjusting pointers, return by way of doing the C++ global constructors.  */
219
220.Ldone:
221          b         FUNC_NAME(__init)   /* do any C++ global constructors (which returns to caller) */
222FUNC_END(__eabi)
223
224/* Special subroutine to convert a bunch of pointers directly.
225   r0               has original link register
226   r3               has low pointer to convert
227   r4               has high pointer to convert
228   r5 .. r10        are scratch registers
229   r11              has the address of .LCTOC1 in it.
230   r12              has the value to add to each pointer
231   r13 .. r31       are unchanged */
232#ifdef _RELOCATABLE
233FUNC_START(__eabi_convert)
234        cmplw       1,3,4                                   /* any pointers to convert? */
235        subf        5,3,4                                   /* calculate number of words to convert */
236        bclr        4,4                                     /* return if no pointers */
237
238        srawi       5,5,2
239          addi      3,3,-4                                  /* start-4 for use with lwzu */
240        mtctr       5
241
242.Lcvt:
243          lwzu      6,4(3)                                  /* pointer to convert */
244          cmpwi     0,6,0
245          beq-      .Lcvt2                                  /* if pointer is null, don't convert */
246
247        add         6,6,12                                  /* convert pointer */
248        stw         6,0(3)
249.Lcvt2:
250        bdnz+       .Lcvt
251        blr
252
253FUNC_END(__eabi_convert)
254
255/* Special subroutine to convert the pointers the user has initialized.  The
256   compiler has placed the address of the initialized pointer into the .fixup
257   section.
258
259   r0               has original link register
260   r3               has low pointer to convert
261   r4               has high pointer to convert
262   r5 .. r10        are scratch registers
263   r11              has the address of .LCTOC1 in it.
264   r12              has the value to add to each pointer
265   r13 .. r31       are unchanged */
266
267FUNC_START(__eabi_uconvert)
268        cmplw       1,3,4                                   /* any pointers to convert? */
269        subf        5,3,4                                   /* calculate number of words to convert */
270        bclr        4,4                                     /* return if no pointers */
271
272        srawi       5,5,2
273          addi      3,3,-4                                  /* start-4 for use with lwzu */
274        mtctr       5
275
276.Lucvt:
277          lwzu      6,4(3)                                  /* next pointer to pointer to convert */
278          add       6,6,12                                  /* adjust pointer */
279          lwz       7,0(6)                                  /* get the pointer it points to */
280          stw       6,0(3)                                  /* store adjusted pointer */
281          add       7,7,12                                  /* adjust */
282          stw       7,0(6)
283        bdnz+       .Lucvt
284        blr
285
286FUNC_END(__eabi_uconvert)
287#endif
288#endif
289