1/*
2 * Special support for eabi and SVR4
3 *
4 *   Copyright (C) 1995-2020 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