1160814Ssimon/*
2160814Ssimon * Special support for eabi and SVR4
3160814Ssimon *
4160814Ssimon *   Copyright (C) 1995-2020 Free Software Foundation, Inc.
5160814Ssimon *   Written By Michael Meissner
6160814Ssimon *
7160814Ssimon * This file is free software; you can redistribute it and/or modify it
8160814Ssimon * under the terms of the GNU General Public License as published by the
9160814Ssimon * Free Software Foundation; either version 3, or (at your option) any
10296341Sdelphij * later version.
11160814Ssimon *
12160814Ssimon * This file is distributed in the hope that it will be useful, but
13160814Ssimon * WITHOUT ANY WARRANTY; without even the implied warranty of
14160814Ssimon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15160814Ssimon * General Public License for more details.
16160814Ssimon *
17160814Ssimon * Under Section 7 of GPL version 3, you are granted additional
18160814Ssimon * permissions described in the GCC Runtime Library Exception, version
19160814Ssimon * 3.1, as published by the Free Software Foundation.
20160814Ssimon *
21160814Ssimon * You should have received a copy of the GNU General Public License and
22160814Ssimon * a copy of the GCC Runtime Library Exception along with this program;
23160814Ssimon * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24160814Ssimon * <http://www.gnu.org/licenses/>.
25160814Ssimon */
26160814Ssimon
27160814Ssimon/* Do any initializations needed for the eabi environment */
28160814Ssimon
29160814Ssimon	.section ".text"
30160814Ssimon	#include "ppc-asm.h"
31160814Ssimon
32160814Ssimon#ifndef __powerpc64__
33160814Ssimon
34160814Ssimon	 .section ".got2","aw"
35160814Ssimon	.align	2
36160814Ssimon.LCTOC1 = . /* +32768 */
37160814Ssimon
38160814Ssimon/* Table of addresses */
39160814Ssimon.Ltable = .-.LCTOC1
40160814Ssimon	.long	.LCTOC1				/* address we are really at */
41160814Ssimon
42160814Ssimon.Lsda = .-.LCTOC1
43160814Ssimon	.long	_SDA_BASE_			/* address of the first small data area */
44160814Ssimon
45160814Ssimon.Lsdas = .-.LCTOC1
46160814Ssimon	.long	__SDATA_START__			/* start of .sdata/.sbss section */
47160814Ssimon
48160814Ssimon.Lsdae = .-.LCTOC1
49160814Ssimon	.long	__SBSS_END__			/* end of .sdata/.sbss section */
50160814Ssimon
51160814Ssimon.Lsda2 = .-.LCTOC1
52160814Ssimon	.long	_SDA2_BASE_			/* address of the second small data area */
53160814Ssimon
54160814Ssimon.Lsda2s = .-.LCTOC1
55160814Ssimon	.long	__SDATA2_START__		/* start of .sdata2/.sbss2 section */
56160814Ssimon
57160814Ssimon.Lsda2e = .-.LCTOC1
58160814Ssimon	.long	__SBSS2_END__			/* end of .sdata2/.sbss2 section */
59160814Ssimon
60160814Ssimon#ifdef _RELOCATABLE
61160814Ssimon.Lgots = .-.LCTOC1
62160814Ssimon	.long	__GOT_START__			/* Global offset table start */
63160814Ssimon
64160814Ssimon.Lgotm1 = .-.LCTOC1
65296341Sdelphij	.long	_GLOBAL_OFFSET_TABLE_-4		/* end of GOT ptrs before BLCL + 3 reserved words */
66160814Ssimon
67160814Ssimon.Lgotm2 = .-.LCTOC1
68160814Ssimon	.long	_GLOBAL_OFFSET_TABLE_+12	/* start of GOT ptrs after BLCL + 3 reserved words */
69160814Ssimon
70296341Sdelphij.Lgote = .-.LCTOC1
71160814Ssimon	.long	__GOT_END__			/* Global offset table end */
72296341Sdelphij
73296341Sdelphij.Lgot2s = .-.LCTOC1
74296341Sdelphij	.long	__GOT2_START__			/* -mrelocatable GOT pointers start */
75296341Sdelphij
76296341Sdelphij.Lgot2e = .-.LCTOC1
77160814Ssimon	.long	__GOT2_END__			/* -mrelocatable GOT pointers end */
78296341Sdelphij
79160814Ssimon.Lfixups = .-.LCTOC1
80160814Ssimon	.long	__FIXUP_START__			/* start of .fixup section */
81160814Ssimon
82160814Ssimon.Lfixupe = .-.LCTOC1
83296341Sdelphij	.long	__FIXUP_END__			/* end of .fixup section */
84296341Sdelphij
85160814Ssimon.Lctors = .-.LCTOC1
86160814Ssimon	.long	__CTOR_LIST__			/* start of .ctor section */
87296341Sdelphij
88296341Sdelphij.Lctore = .-.LCTOC1
89160814Ssimon	.long	__CTOR_END__			/* end of .ctor section */
90296341Sdelphij
91160814Ssimon.Ldtors = .-.LCTOC1
92296341Sdelphij	.long	__DTOR_LIST__			/* start of .dtor section */
93160814Ssimon
94296341Sdelphij.Ldtore = .-.LCTOC1
95296341Sdelphij	.long	__DTOR_END__			/* end of .dtor section */
96296341Sdelphij
97296341Sdelphij.Lexcepts = .-.LCTOC1
98296341Sdelphij	.long	__EXCEPT_START__		/* start of .gcc_except_table section */
99160814Ssimon
100160814Ssimon.Lexcepte = .-.LCTOC1
101296341Sdelphij	.long	__EXCEPT_END__			/* end of .gcc_except_table section */
102296341Sdelphij
103296341Sdelphij.Linit = .-.LCTOC1
104296341Sdelphij	.long	.Linit_p			/* address of variable to say we've been called */
105296341Sdelphij
106296341Sdelphij	.text
107296341Sdelphij	.align	2
108160814Ssimon.Lptr:
109296341Sdelphij	.long	.LCTOC1-.Laddr			/* PC relative pointer to .got2 */
110296341Sdelphij#endif
111296341Sdelphij
112296341Sdelphij	.data
113296341Sdelphij	.align	2
114296341Sdelphij.Linit_p:
115160814Ssimon	.long	0
116160814Ssimon
117296341Sdelphij	.text
118296341Sdelphij
119160814SsimonFUNC_START(__eabi)
120160814Ssimon
121296341Sdelphij/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can
122160814Ssimon   be assembled with other assemblers than GAS.  */
123296341Sdelphij
124296341Sdelphij#ifndef _RELOCATABLE
125160814Ssimon	addis	10,0,.Linit_p@ha		/* init flag */
126160814Ssimon	addis	11,0,.LCTOC1@ha			/* load address of .LCTOC1 */
127296341Sdelphij	lwz	9,.Linit_p@l(10)		/* init flag */
128296341Sdelphij	addi	11,11,.LCTOC1@l
129160814Ssimon	cmplwi	2,9,0				/* init flag != 0? */
130160814Ssimon	bnelr	2				/* return now, if we've been called already */
131160814Ssimon	stw	1,.Linit_p@l(10)		/* store a nonzero value in the done flag */
132160814Ssimon
133160814Ssimon#else /* -mrelocatable */
134160814Ssimon	mflr	0
135296341Sdelphij	bl	.Laddr				/* get current address */
136160814Ssimon.Laddr:
137160814Ssimon	mflr	12				/* real address of .Laddr */
138160814Ssimon	lwz	11,(.Lptr-.Laddr)(12)		/* linker generated address of .LCTOC1 */
139296341Sdelphij	add	11,11,12			/* correct to real pointer */
140160814Ssimon	lwz	12,.Ltable(11)			/* get linker's idea of where .Laddr is */
141160814Ssimon	lwz	10,.Linit(11)			/* address of init flag */
142296341Sdelphij	subf.	12,12,11			/* calculate difference */
143296341Sdelphij	lwzx	9,10,12				/* done flag */
144296341Sdelphij	cmplwi	2,9,0				/* init flag != 0? */
145296341Sdelphij	mtlr	0				/* restore in case branch was taken */
146296341Sdelphij	bnelr	2				/* return now, if we've been called already */
147296341Sdelphij	stwx	1,10,12				/* store a nonzero value in the done flag */
148160814Ssimon	beq+	0,.Lsdata			/* skip if we don't need to relocate */
149296341Sdelphij
150296341Sdelphij/* We need to relocate the .got2 pointers.  */
151296341Sdelphij
152296341Sdelphij	lwz	3,.Lgot2s(11)			/* GOT2 pointers start */
153296341Sdelphij	lwz	4,.Lgot2e(11)			/* GOT2 pointers end */
154296341Sdelphij	add	3,12,3				/* adjust pointers */
155160814Ssimon	add	4,12,4
156296341Sdelphij	bl	FUNC_NAME(__eabi_convert)	/* convert pointers in .got2 section */
157296341Sdelphij
158296341Sdelphij/* Fixup the .ctor section for static constructors */
159296341Sdelphij
160160814Ssimon	lwz	3,.Lctors(11)			/* constructors pointers start */
161296341Sdelphij	lwz	4,.Lctore(11)			/* constructors pointers end */
162296341Sdelphij	bl	FUNC_NAME(__eabi_convert)	/* convert constructors */
163296341Sdelphij
164296341Sdelphij/* Fixup the .dtor section for static destructors */
165296341Sdelphij
166296341Sdelphij	lwz	3,.Ldtors(11)			/* destructors pointers start */
167296341Sdelphij	lwz	4,.Ldtore(11)			/* destructors pointers end */
168296341Sdelphij	bl	FUNC_NAME(__eabi_convert)	/* convert destructors */
169296341Sdelphij
170296341Sdelphij/* Fixup the .gcc_except_table section for G++ exceptions */
171296341Sdelphij
172160814Ssimon	lwz	3,.Lexcepts(11)			/* exception table pointers start */
173296341Sdelphij	lwz	4,.Lexcepte(11)			/* exception table pointers end */
174160814Ssimon	bl	FUNC_NAME(__eabi_convert)	/* convert exceptions */
175160814Ssimon
176160814Ssimon/* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */
177296341Sdelphij
178160814Ssimon	lwz	3,.Lgots(11)			/* GOT table pointers start */
179296341Sdelphij	lwz	4,.Lgotm1(11)			/* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */
180296341Sdelphij	bl	FUNC_NAME(__eabi_convert)	/* convert lower GOT */
181296341Sdelphij
182296341Sdelphij/* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */
183296341Sdelphij
184296341Sdelphij	lwz	3,.Lgotm2(11)			/* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */
185296341Sdelphij	lwz	4,.Lgote(11)			/* GOT table pointers end */
186296341Sdelphij	bl	FUNC_NAME(__eabi_convert)	/* convert lower GOT */
187160814Ssimon
188296341Sdelphij/* Fixup any user initialized pointers now (the compiler drops pointers to */
189296341Sdelphij/* each of the relocs that it does in the .fixup section).  */
190296341Sdelphij
191296341Sdelphij.Lfix:
192296341Sdelphij	lwz	3,.Lfixups(11)			/* fixup pointers start */
193296341Sdelphij	lwz	4,.Lfixupe(11)			/* fixup pointers end */
194296341Sdelphij	bl	FUNC_NAME(__eabi_uconvert)	/* convert user initialized pointers */
195296341Sdelphij
196296341Sdelphij.Lsdata:
197296341Sdelphij	mtlr	0				/* restore link register */
198296341Sdelphij#endif /* _RELOCATABLE */
199296341Sdelphij
200296341Sdelphij/* Only load up register 13 if there is a .sdata and/or .sbss section */
201296341Sdelphij	lwz	3,.Lsdas(11)			/* start of .sdata/.sbss section */
202296341Sdelphij	lwz	4,.Lsdae(11)			/* end of .sdata/.sbss section */
203296341Sdelphij	cmpw	1,3,4				/* .sdata/.sbss section non-empty? */
204296341Sdelphij	beq-	1,.Lsda2l			/* skip loading r13 */
205296341Sdelphij
206160814Ssimon	lwz	13,.Lsda(11)			/* load r13 with _SDA_BASE_ address */
207296341Sdelphij
208296341Sdelphij/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
209296341Sdelphij
210296341Sdelphij.Lsda2l:
211296341Sdelphij	lwz	3,.Lsda2s(11)			/* start of .sdata/.sbss section */
212296341Sdelphij	lwz	4,.Lsda2e(11)			/* end of .sdata/.sbss section */
213296341Sdelphij	cmpw	1,3,4				/* .sdata/.sbss section non-empty? */
214296341Sdelphij	beq+	1,.Ldone			/* skip loading r2 */
215296341Sdelphij
216160814Ssimon	lwz	2,.Lsda2(11)			/* load r2 with _SDA2_BASE_ address */
217160814Ssimon
218296341Sdelphij/* Done adjusting pointers, return by way of doing the C++ global constructors.  */
219296341Sdelphij
220296341Sdelphij.Ldone:
221160814Ssimon	b	FUNC_NAME(__init)	/* do any C++ global constructors (which returns to caller) */
222160814SsimonFUNC_END(__eabi)
223296341Sdelphij
224160814Ssimon/* Special subroutine to convert a bunch of pointers directly.
225160814Ssimon   r0		has original link register
226296341Sdelphij   r3		has low pointer to convert
227160814Ssimon   r4		has high pointer to convert
228296341Sdelphij   r5 .. r10	are scratch registers
229296341Sdelphij   r11		has the address of .LCTOC1 in it.
230296341Sdelphij   r12		has the value to add to each pointer
231296341Sdelphij   r13 .. r31	are unchanged */
232296341Sdelphij#ifdef _RELOCATABLE
233296341SdelphijFUNC_START(__eabi_convert)
234296341Sdelphij        cmplw	1,3,4				/* any pointers to convert? */
235296341Sdelphij        subf	5,3,4				/* calculate number of words to convert */
236296341Sdelphij        bclr	4,4				/* return if no pointers */
237296341Sdelphij
238296341Sdelphij        srawi	5,5,2
239296341Sdelphij	addi	3,3,-4				/* start-4 for use with lwzu */
240296341Sdelphij        mtctr	5
241296341Sdelphij
242296341Sdelphij.Lcvt:
243296341Sdelphij	lwzu	6,4(3)				/* pointer to convert */
244296341Sdelphij	cmpwi	0,6,0
245296341Sdelphij	beq-	.Lcvt2				/* if pointer is null, don't convert */
246296341Sdelphij
247296341Sdelphij        add	6,6,12				/* convert pointer */
248296341Sdelphij        stw	6,0(3)
249160814Ssimon.Lcvt2:
250296341Sdelphij        bdnz+	.Lcvt
251160814Ssimon        blr
252296341Sdelphij
253296341SdelphijFUNC_END(__eabi_convert)
254296341Sdelphij
255296341Sdelphij/* Special subroutine to convert the pointers the user has initialized.  The
256296341Sdelphij   compiler has placed the address of the initialized pointer into the .fixup
257296341Sdelphij   section.
258296341Sdelphij
259296341Sdelphij   r0		has original link register
260296341Sdelphij   r3		has low pointer to convert
261296341Sdelphij   r4		has high pointer to convert
262160814Ssimon   r5 .. r10	are scratch registers
263160814Ssimon   r11		has the address of .LCTOC1 in it.
264296341Sdelphij   r12		has the value to add to each pointer
265296341Sdelphij   r13 .. r31	are unchanged */
266296341Sdelphij
267296341SdelphijFUNC_START(__eabi_uconvert)
268296341Sdelphij        cmplw	1,3,4				/* any pointers to convert? */
269296341Sdelphij        subf	5,3,4				/* calculate number of words to convert */
270296341Sdelphij        bclr	4,4				/* return if no pointers */
271296341Sdelphij
272296341Sdelphij        srawi	5,5,2
273160814Ssimon	addi	3,3,-4				/* start-4 for use with lwzu */
274160814Ssimon        mtctr	5
275296341Sdelphij
276296341Sdelphij.Lucvt:
277296341Sdelphij	lwzu	6,4(3)				/* next pointer to pointer to convert */
278296341Sdelphij	add	6,6,12				/* adjust pointer */
279296341Sdelphij	lwz	7,0(6)				/* get the pointer it points to */
280160814Ssimon	stw	6,0(3)				/* store adjusted pointer */
281160814Ssimon	add	7,7,12				/* adjust */
282296341Sdelphij	stw	7,0(6)
283296341Sdelphij        bdnz+	.Lucvt
284296341Sdelphij        blr
285296341Sdelphij
286296341SdelphijFUNC_END(__eabi_uconvert)
287160814Ssimon#endif
288296341Sdelphij#endif
289296341Sdelphij