match: Improve handling of double convert [PR117776]
[gcc.git] / libgcc / config / rs6000 / eabi.S
blob02a02f59c10615968101bc42370f7ad0e8363749
1 /*
2  * Special support for eabi and SVR4
3  *
4  *   Copyright (C) 1995-2024 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  */ 
27 /* Do any initializations needed for the eabi environment */
29         .section ".text"
30         #include "ppc-asm.h"
32 #ifndef __powerpc64__
34          .section ".got2","aw"
35         .align  2
36 .LCTOC1 = . /* +32768 */
38 /* Table of addresses */
39 .Ltable = .-.LCTOC1
40         .long   .LCTOC1                         /* address we are really at */
42 .Lsda = .-.LCTOC1
43         .long   _SDA_BASE_                      /* address of the first small data area */
45 .Lsdas = .-.LCTOC1
46         .long   __SDATA_START__                 /* start of .sdata/.sbss section */
48 .Lsdae = .-.LCTOC1
49         .long   __SBSS_END__                    /* end of .sdata/.sbss section */
51 .Lsda2 = .-.LCTOC1
52         .long   _SDA2_BASE_                     /* address of the second small data area */
54 .Lsda2s = .-.LCTOC1
55         .long   __SDATA2_START__                /* start of .sdata2/.sbss2 section */
57 .Lsda2e = .-.LCTOC1
58         .long   __SBSS2_END__                   /* end of .sdata2/.sbss2 section */
60 #ifdef _RELOCATABLE
61 .Lgots = .-.LCTOC1
62         .long   __GOT_START__                   /* Global offset table start */
64 .Lgotm1 = .-.LCTOC1
65         .long   _GLOBAL_OFFSET_TABLE_-4         /* end of GOT ptrs before BLCL + 3 reserved words */
67 .Lgotm2 = .-.LCTOC1
68         .long   _GLOBAL_OFFSET_TABLE_+12        /* start of GOT ptrs after BLCL + 3 reserved words */
70 .Lgote = .-.LCTOC1
71         .long   __GOT_END__                     /* Global offset table end */
73 .Lgot2s = .-.LCTOC1
74         .long   __GOT2_START__                  /* -mrelocatable GOT pointers start */
76 .Lgot2e = .-.LCTOC1
77         .long   __GOT2_END__                    /* -mrelocatable GOT pointers end */
79 .Lfixups = .-.LCTOC1
80         .long   __FIXUP_START__                 /* start of .fixup section */
82 .Lfixupe = .-.LCTOC1
83         .long   __FIXUP_END__                   /* end of .fixup section */
85 .Lctors = .-.LCTOC1
86         .long   __CTOR_LIST__                   /* start of .ctor section */
88 .Lctore = .-.LCTOC1
89         .long   __CTOR_END__                    /* end of .ctor section */
91 .Ldtors = .-.LCTOC1
92         .long   __DTOR_LIST__                   /* start of .dtor section */
94 .Ldtore = .-.LCTOC1
95         .long   __DTOR_END__                    /* end of .dtor section */
97 .Lexcepts = .-.LCTOC1
98         .long   __EXCEPT_START__                /* start of .gcc_except_table section */
100 .Lexcepte = .-.LCTOC1
101         .long   __EXCEPT_END__                  /* end of .gcc_except_table section */
103 .Linit = .-.LCTOC1
104         .long   .Linit_p                        /* address of variable to say we've been called */
106         .text
107         .align  2
108 .Lptr:
109         .long   .LCTOC1-.Laddr                  /* PC relative pointer to .got2 */
110 #endif
112         .data
113         .align  2
114 .Linit_p:
115         .long   0
117         .text
119 FUNC_START(__eabi)
121 /* Eliminate -mrelocatable code if not -mrelocatable, so that this file can
122    be assembled with other assemblers than GAS.  */
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 */
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 */
150 /* We need to relocate the .got2 pointers.  */
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 */
158 /* Fixup the .ctor section for static constructors */
160         lwz     3,.Lctors(11)                   /* constructors pointers start */
161         lwz     4,.Lctore(11)                   /* constructors pointers end */
162         bl      FUNC_NAME(__eabi_convert)       /* convert constructors */
164 /* Fixup the .dtor section for static destructors */
166         lwz     3,.Ldtors(11)                   /* destructors pointers start */
167         lwz     4,.Ldtore(11)                   /* destructors pointers end */
168         bl      FUNC_NAME(__eabi_convert)       /* convert destructors */
170 /* Fixup the .gcc_except_table section for G++ exceptions */
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 */
176 /* Fixup the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */
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 */
182 /* Fixup the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */
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 */
188 /* Fixup any user initialized pointers now (the compiler drops pointers to */
189 /* each of the relocs that it does in the .fixup section).  */
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 */
196 .Lsdata:
197         mtlr    0                               /* restore link register */
198 #endif /* _RELOCATABLE */
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 */
206         lwz     13,.Lsda(11)                    /* load r13 with _SDA_BASE_ address */
208 /* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
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 */
216         lwz     2,.Lsda2(11)                    /* load r2 with _SDA2_BASE_ address */
218 /* Done adjusting pointers, return by way of doing the C++ global constructors.  */
220 .Ldone:
221         b       FUNC_NAME(__init)       /* do any C++ global constructors (which returns to caller) */
222 FUNC_END(__eabi)
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
233 FUNC_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 */
238         srawi   5,5,2
239         addi    3,3,-4                          /* start-4 for use with lwzu */
240         mtctr   5
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 */
247         add     6,6,12                          /* convert pointer */
248         stw     6,0(3)
249 .Lcvt2:
250         bdnz+   .Lcvt
251         blr
253 FUNC_END(__eabi_convert)
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.
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         
267 FUNC_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 */
272         srawi   5,5,2
273         addi    3,3,-4                          /* start-4 for use with lwzu */
274         mtctr   5
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
286 FUNC_END(__eabi_uconvert)
287 #endif
288 #endif