eabi.asm revision 117395
1180740Sdes/*
2180740Sdes * Special support for eabi and SVR4
3226046Sdes *
4226046Sdes *   Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
5226046Sdes *   Written By Michael Meissner
6180740Sdes * 
7180740Sdes * This file is free software; you can redistribute it and/or modify it
8180740Sdes * under the terms of the GNU General Public License as published by the
9180740Sdes * Free Software Foundation; either version 2, or (at your option) any
10180740Sdes * later version.
11180740Sdes * 
12180740Sdes * In addition to the permissions in the GNU General Public License, the
13180746Sdes * Free Software Foundation gives you unlimited permission to link the
14180746Sdes * compiled version of this file with other programs, and to distribute
15180746Sdes * those programs without any restriction coming from the use of this
16180740Sdes * file.  (The General Public License restrictions do apply in other
17180740Sdes * respects; for example, they cover modification of the file, and
18180740Sdes * distribution when not linked into another program.)
19240075Sdes * 
20240075Sdes * This file is distributed in the hope that it will be useful, but
21240075Sdes * WITHOUT ANY WARRANTY; without even the implied warranty of
22180740Sdes * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23180740Sdes * General Public License for more details.
24180740Sdes * 
25180740Sdes * You should have received a copy of the GNU General Public License
26180740Sdes * along with this program; see the file COPYING.  If not, write to
27180740Sdes * the Free Software Foundation, 59 Temple Place - Suite 330,
28180740Sdes * Boston, MA 02111-1307, USA.
29180740Sdes * 
30180740Sdes *    As a special exception, if you link this library with files
31180746Sdes *    compiled with GCC to produce an executable, this does not cause
32180746Sdes *    the resulting executable to be covered by the GNU General Public License.
33180746Sdes *    This exception does not however invalidate any other reasons why
34180740Sdes *    the executable file might be covered by the GNU General Public License.
35180740Sdes */ 
36180740Sdes
37180740Sdes/* Do any initializations needed for the eabi environment */
38180740Sdes
39180740Sdes	.file	"eabi.asm"
40180740Sdes	.section ".text"
41180740Sdes	#include "ppc-asm.h"
42180740Sdes
43180740Sdes#ifndef __powerpc64__
44180740Sdes
45180740Sdes	 .section ".got2","aw"
46180740Sdes	.align	2
47180750Sdes.LCTOC1 = . /* +32768 */
48180750Sdes
49180750Sdes/* Table of addresses */
50262566Sdes.Ltable = .-.LCTOC1
51262566Sdes	.long	.LCTOC1				/* address we are really at */
52262566Sdes
53262566Sdes.Lsda = .-.LCTOC1
54180740Sdes	.long	_SDA_BASE_			/* address of the first small data area */
55180740Sdes
56180740Sdes.Lsdas = .-.LCTOC1
57180740Sdes	.long	__SDATA_START__			/* start of .sdata/.sbss section */
58180740Sdes
59180740Sdes.Lsdae = .-.LCTOC1
60180740Sdes	.long	__SBSS_END__			/* end of .sdata/.sbss section */
61180740Sdes
62180740Sdes.Lsda2 = .-.LCTOC1
63180740Sdes	.long	_SDA2_BASE_			/* address of the second small data area */
64180740Sdes
65180740Sdes.Lsda2s = .-.LCTOC1
66180740Sdes	.long	__SDATA2_START__		/* start of .sdata2/.sbss2 section */
67180740Sdes
68180740Sdes.Lsda2e = .-.LCTOC1
69180740Sdes	.long	__SBSS2_END__			/* end of .sdata2/.sbss2 section */
70180740Sdes
71180740Sdes#ifdef _RELOCATABLE
72180740Sdes.Lgots = .-.LCTOC1
73180740Sdes	.long	__GOT_START__			/* Global offset table start */
74180740Sdes
75180746Sdes.Lgotm1 = .-.LCTOC1
76180746Sdes	.long	_GLOBAL_OFFSET_TABLE_-4		/* end of GOT ptrs before BLCL + 3 reserved words */
77180746Sdes
78180740Sdes.Lgotm2 = .-.LCTOC1
79180740Sdes	.long	_GLOBAL_OFFSET_TABLE_+12	/* start of GOT ptrs after BLCL + 3 reserved words */
80180740Sdes
81262566Sdes.Lgote = .-.LCTOC1
82248619Sdes	.long	__GOT_END__			/* Global offset table end */
83248619Sdes
84197679Sdes.Lgot2s = .-.LCTOC1
85197679Sdes	.long	__GOT2_START__			/* -mrelocatable GOT pointers start */
86197679Sdes
87180740Sdes.Lgot2e = .-.LCTOC1
88180740Sdes	.long	__GOT2_END__			/* -mrelocatable GOT pointers end */
89180740Sdes
90180740Sdes.Lfixups = .-.LCTOC1
91180740Sdes	.long	__FIXUP_START__			/* start of .fixup section */
92180740Sdes
93180740Sdes.Lfixupe = .-.LCTOC1
94180740Sdes	.long	__FIXUP_END__			/* end of .fixup section */
95180740Sdes
96180740Sdes.Lctors = .-.LCTOC1
97180740Sdes	.long	__CTOR_LIST__			/* start of .ctor section */
98180740Sdes
99180740Sdes.Lctore = .-.LCTOC1
100180740Sdes	.long	__CTOR_END__			/* end of .ctor section */
101180740Sdes
102180740Sdes.Ldtors = .-.LCTOC1
103180740Sdes	.long	__DTOR_LIST__			/* start of .dtor section */
104180740Sdes
105180740Sdes.Ldtore = .-.LCTOC1
106180740Sdes	.long	__DTOR_END__			/* end of .dtor section */
107180740Sdes
108180740Sdes.Lexcepts = .-.LCTOC1
109180740Sdes	.long	__EXCEPT_START__		/* start of .gcc_except_table section */
110180740Sdes
111180740Sdes.Lexcepte = .-.LCTOC1
112180740Sdes	.long	__EXCEPT_END__			/* end of .gcc_except_table section */
113180740Sdes
114180740Sdes.Linit = .-.LCTOC1
115180740Sdes	.long	.Linit_p			/* address of variable to say we've been called */
116180740Sdes
117180740Sdes	.text
118180740Sdes	.align	2
119180740Sdes.Lptr:
120180740Sdes	.long	.LCTOC1-.Laddr			/* PC relative pointer to .got2 */
121180740Sdes#endif
122180740Sdes
123180740Sdes	.data
124180740Sdes	.align	2
125180740Sdes.Linit_p:
126180740Sdes	.long	0
127180740Sdes
128180740Sdes	.text
129180740Sdes
130180740SdesFUNC_START(__eabi)
131180740Sdes
132180740Sdes/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can
133180740Sdes   be assembled with other assemblers than GAS.  */
134180740Sdes
135204917Sdes#ifndef _RELOCATABLE
136204917Sdes	addis	10,0,.Linit_p@ha		/* init flag */
137204917Sdes	addis	11,0,.LCTOC1@ha			/* load address of .LCTOC1 */
138221420Sdes	lwz	9,.Linit_p@l(10)		/* init flag */
139221420Sdes	addi	11,11,.LCTOC1@l
140221420Sdes	cmplwi	2,9,0				/* init flag != 0? */
141197679Sdes	bnelr	2				/* return now, if we've been called already */
142180750Sdes	stw	1,.Linit_p@l(10)		/* store a nonzero value in the done flag */
143180750Sdes
144197679Sdes#else /* -mrelocatable */
145197679Sdes	mflr	0
146197679Sdes	bl	.Laddr				/* get current address */
147180740Sdes.Laddr:
148180740Sdes	mflr	12				/* real address of .Laddr */
149180740Sdes	lwz	11,(.Lptr-.Laddr)(12)		/* linker generated address of .LCTOC1 */
150180740Sdes	add	11,11,12			/* correct to real pointer */
151180740Sdes	lwz	12,.Ltable(11)			/* get linker's idea of where .Laddr is */
152180740Sdes	lwz	10,.Linit(11)			/* address of init flag */
153180740Sdes	subf.	12,12,11			/* calculate difference */
154180740Sdes	lwzx	9,10,12				/* done flag */
155180740Sdes	cmplwi	2,9,0				/* init flag != 0? */
156180740Sdes	mtlr	0				/* restore in case branch was taken */
157180740Sdes	bnelr	2				/* return now, if we've been called already */
158180740Sdes	stwx	1,10,12				/* store a nonzero value in the done flag */
159221420Sdes	beq+	0,.Lsdata			/* skip if we don't need to relocate */
160221420Sdes
161221420Sdes/* We need to relocate the .got2 pointers.  */
162180740Sdes
163180740Sdes	lwz	3,.Lgot2s(11)			/* GOT2 pointers start */
164180740Sdes	lwz	4,.Lgot2e(11)			/* GOT2 pointers end */
165180740Sdes	add	3,12,3				/* adjust pointers */
166180740Sdes	add	4,12,4
167180740Sdes	bl	FUNC_NAME(__eabi_convert)	/* convert pointers in .got2 section */
168180740Sdes
169180740Sdes/* Fixup the .ctor section for static constructors */
170180740Sdes
171180740Sdes	lwz	3,.Lctors(11)			/* constructors pointers start */
172180740Sdes	lwz	4,.Lctore(11)			/* constructors pointers end */
173180740Sdes	bl	FUNC_NAME(__eabi_convert)	/* convert constructors */
174180740Sdes
175180740Sdes/* Fixup the .dtor section for static destructors */
176180740Sdes
177180740Sdes	lwz	3,.Ldtors(11)			/* destructors pointers start */
178180740Sdes	lwz	4,.Ldtore(11)			/* destructors pointers end */
179180740Sdes	bl	FUNC_NAME(__eabi_convert)	/* convert destructors */
180180740Sdes
181180740Sdes/* Fixup the .gcc_except_table section for G++ exceptions */
182180740Sdes
183180740Sdes	lwz	3,.Lexcepts(11)			/* exception table pointers start */
184180740Sdes	lwz	4,.Lexcepte(11)			/* exception table pointers end */
185180740Sdes	bl	FUNC_NAME(__eabi_convert)	/* convert exceptions */
186180750Sdes
187180750Sdes/* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */
188180750Sdes
189262566Sdes	lwz	3,.Lgots(11)			/* GOT table pointers start */
190262566Sdes	lwz	4,.Lgotm1(11)			/* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */
191262566Sdes	bl	FUNC_NAME(__eabi_convert)	/* convert lower GOT */
192180750Sdes
193180750Sdes/* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */
194180750Sdes
195180740Sdes	lwz	3,.Lgotm2(11)			/* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */
196180740Sdes	lwz	4,.Lgote(11)			/* GOT table pointers end */
197180740Sdes	bl	FUNC_NAME(__eabi_convert)	/* convert lower GOT */
198180740Sdes
199180740Sdes/* Fixup any user initialized pointers now (the compiler drops pointers to */
200180740Sdes/* each of the relocs that it does in the .fixup section).  */
201180744Sdes
202180744Sdes.Lfix:
203180744Sdes	lwz	3,.Lfixups(11)			/* fixup pointers start */
204180740Sdes	lwz	4,.Lfixupe(11)			/* fixup pointers end */
205180740Sdes	bl	FUNC_NAME(__eabi_uconvert)	/* convert user initialized pointers */
206180740Sdes
207180746Sdes.Lsdata:
208180746Sdes	mtlr	0				/* restore link register */
209180746Sdes#endif /* _RELOCATABLE */
210180740Sdes
211180740Sdes/* Only load up register 13 if there is a .sdata and/or .sbss section */
212180740Sdes	lwz	3,.Lsdas(11)			/* start of .sdata/.sbss section */
213180740Sdes	lwz	4,.Lsdae(11)			/* end of .sdata/.sbss section */
214180740Sdes	cmpw	1,3,4				/* .sdata/.sbss section non-empty? */
215180740Sdes	beq-	1,.Lsda2l			/* skip loading r13 */
216180740Sdes
217180740Sdes	lwz	13,.Lsda(11)			/* load r13 with _SDA_BASE_ address */
218180740Sdes
219180740Sdes/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
220180740Sdes
221180740Sdes.Lsda2l:	
222262566Sdes	lwz	3,.Lsda2s(11)			/* start of .sdata/.sbss section */
223262566Sdes	lwz	4,.Lsda2e(11)			/* end of .sdata/.sbss section */
224262566Sdes	cmpw	1,3,4				/* .sdata/.sbss section non-empty? */
225180740Sdes	beq+	1,.Ldone			/* skip loading r2 */
226180740Sdes
227180740Sdes	lwz	2,.Lsda2(11)			/* load r2 with _SDA2_BASE_ address */
228262566Sdes
229262566Sdes/* Done adjusting pointers, return by way of doing the C++ global constructors.  */
230262566Sdes
231262566Sdes.Ldone:
232262566Sdes	b	FUNC_NAME(__init)	/* do any C++ global constructors (which returns to caller) */
233262566SdesFUNC_END(__eabi)
234262566Sdes
235262566Sdes/* Special subroutine to convert a bunch of pointers directly.
236262566Sdes   r0		has original link register
237262566Sdes   r3		has low pointer to convert
238262566Sdes   r4		has high pointer to convert
239262566Sdes   r5 .. r10	are scratch registers
240262566Sdes   r11		has the address of .LCTOC1 in it.
241262566Sdes   r12		has the value to add to each pointer
242262566Sdes   r13 .. r31	are unchanged */
243262566Sdes	
244262566SdesFUNC_START(__eabi_convert)
245262566Sdes        cmplw	1,3,4				/* any pointers to convert? */
246221420Sdes        subf	5,3,4				/* calculate number of words to convert */
247221420Sdes        bclr	4,4				/* return if no pointers */
248221420Sdes
249248619Sdes        srawi	5,5,2
250248619Sdes	addi	3,3,-4				/* start-4 for use with lwzu */
251248619Sdes        mtctr	5
252180740Sdes
253180740Sdes.Lcvt:
254180740Sdes	lwzu	6,4(3)				/* pointer to convert */
255180740Sdes	cmpi	0,6,0
256180740Sdes	beq-	.Lcvt2				/* if pointer is null, don't convert */
257180740Sdes
258262566Sdes        add	6,6,12				/* convert pointer */
259262566Sdes        stw	6,0(3)
260262566Sdes.Lcvt2:
261180740Sdes        bdnz+	.Lcvt
262180740Sdes        blr
263180740Sdes
264255767SdesFUNC_END(__eabi_convert)
265255767Sdes
266255767Sdes/* Special subroutine to convert the pointers the user has initialized.  The
267180740Sdes   compiler has placed the address of the initialized pointer into the .fixup
268180740Sdes   section.
269180740Sdes
270180740Sdes   r0		has original link register
271180740Sdes   r3		has low pointer to convert
272180740Sdes   r4		has high pointer to convert
273180740Sdes   r5 .. r10	are scratch registers
274180740Sdes   r11		has the address of .LCTOC1 in it.
275180740Sdes   r12		has the value to add to each pointer
276180740Sdes   r13 .. r31	are unchanged */
277180740Sdes	
278180740SdesFUNC_START(__eabi_uconvert)
279255767Sdes        cmplw	1,3,4				/* any pointers to convert? */
280255767Sdes        subf	5,3,4				/* calculate number of words to convert */
281255767Sdes        bclr	4,4				/* return if no pointers */
282180740Sdes
283180740Sdes        srawi	5,5,2
284180740Sdes	addi	3,3,-4				/* start-4 for use with lwzu */
285180740Sdes        mtctr	5
286180740Sdes
287180740Sdes.Lucvt:
288180740Sdes	lwzu	6,4(3)				/* next pointer to pointer to convert */
289180740Sdes	add	6,6,12				/* adjust pointer */
290180740Sdes	lwz	7,0(6)				/* get the pointer it points to */
291180740Sdes	stw	6,0(3)				/* store adjusted pointer */
292180740Sdes	add	7,7,12				/* adjust */
293180740Sdes	stw	7,0(6)
294180740Sdes        bdnz+	.Lucvt
295180740Sdes        blr
296180740Sdes
297180740SdesFUNC_END(__eabi_uconvert)
298180740Sdes
299180740Sdes#endif
300180740Sdes