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