OSDN Git Service

PR bootstrap/45177
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / bpabi-v6m.S
1 /* Miscellaneous BPABI functions.  ARMv6M implementation
2
3    Copyright (C) 2006, 2008, 2009  Free Software Foundation, Inc.
4    Contributed by CodeSourcery.
5
6    This file is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 3, or (at your option) any
9    later version.
10
11    This file is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15
16    Under Section 7 of GPL version 3, you are granted additional
17    permissions described in the GCC Runtime Library Exception, version
18    3.1, as published by the Free Software Foundation.
19
20    You should have received a copy of the GNU General Public License and
21    a copy of the GCC Runtime Library Exception along with this program;
22    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23    <http://www.gnu.org/licenses/>.  */
24
25 #ifdef __ARM_EABI__
26 /* Some attributes that are common to all routines in this file.  */
27         /* Tag_ABI_align_needed: This code does not require 8-byte
28            alignment from the caller.  */
29         /* .eabi_attribute 24, 0  -- default setting.  */
30         /* Tag_ABI_align_preserved: This code preserves 8-byte
31            alignment in any callee.  */
32         .eabi_attribute 25, 1
33 #endif /* __ARM_EABI__ */
34
35 #ifdef L_aeabi_lcmp
36
37 FUNC_START aeabi_lcmp
38         cmp     xxh, yyh
39         beq     1f
40         bgt     2f
41         mov     r0, #1
42         neg     r0, r0
43         RET
44 2:
45         mov     r0, #1
46         RET
47 1:
48         sub     r0, xxl, yyl
49         beq     1f
50         bhi     2f
51         mov     r0, #1
52         neg     r0, r0
53         RET
54 2:
55         mov     r0, #1
56 1:
57         RET
58         FUNC_END aeabi_lcmp
59
60 #endif /* L_aeabi_lcmp */
61         
62 #ifdef L_aeabi_ulcmp
63
64 FUNC_START aeabi_ulcmp
65         cmp     xxh, yyh
66         bne     1f
67         sub     r0, xxl, yyl
68         beq     2f
69 1:
70         bcs     1f
71         mov     r0, #1
72         neg     r0, r0
73         RET
74 1:
75         mov     r0, #1
76 2:
77         RET
78         FUNC_END aeabi_ulcmp
79
80 #endif /* L_aeabi_ulcmp */
81
82 .macro test_div_by_zero signed
83         cmp     yyh, #0
84         bne     7f
85         cmp     yyl, #0
86         bne     7f
87         cmp     xxh, #0
88         bne     2f
89         cmp     xxl, #0
90 2:
91         .ifc    \signed, unsigned
92         beq     3f
93         mov     xxh, #0
94         mvn     xxh, xxh                @ 0xffffffff
95         mov     xxl, xxh
96 3:
97         .else
98         beq     5f
99         blt     6f
100         mov     xxl, #0
101         mvn     xxl, xxl                @ 0xffffffff
102         lsr     xxh, xxl, #1            @ 0x7fffffff
103         b       5f
104 6:      mov     xxh, #0x80
105         lsl     xxh, xxh, #24           @ 0x80000000
106         mov     xxl, #0
107 5:
108         .endif
109         @ tailcalls are tricky on v6-m.
110         push    {r0, r1, r2}
111         ldr     r0, 1f
112         adr     r1, 1f
113         add     r0, r1
114         str     r0, [sp, #8]
115         @ We know we are not on armv4t, so pop pc is safe.
116         pop     {r0, r1, pc}
117         .align  2
118 1:
119         .word   __aeabi_ldiv0 - 1b
120 7:
121 .endm
122
123 #ifdef L_aeabi_ldivmod
124
125 FUNC_START aeabi_ldivmod
126         test_div_by_zero signed
127
128         push {r0, r1}
129         mov r0, sp
130         push {r0, lr}
131         ldr r0, [sp, #8]
132         bl SYM(__gnu_ldivmod_helper)
133         ldr r3, [sp, #4]
134         mov lr, r3
135         add sp, sp, #8
136         pop {r2, r3}
137         RET
138         FUNC_END aeabi_ldivmod
139
140 #endif /* L_aeabi_ldivmod */
141
142 #ifdef L_aeabi_uldivmod
143
144 FUNC_START aeabi_uldivmod
145         test_div_by_zero unsigned
146
147         push {r0, r1}
148         mov r0, sp
149         push {r0, lr}
150         ldr r0, [sp, #8]
151         bl SYM(__gnu_uldivmod_helper)
152         ldr r3, [sp, #4]
153         mov lr, r3
154         add sp, sp, #8
155         pop {r2, r3}
156         RET
157         FUNC_END aeabi_uldivmod
158         
159 #endif /* L_aeabi_uldivmod */
160
161 #ifdef L_arm_addsubsf3
162
163 FUNC_START aeabi_frsub
164
165       push      {r4, lr}
166       mov       r4, #1
167       lsl       r4, #31
168       eor       r0, r0, r4
169       bl        __aeabi_fadd
170       pop       {r4, pc}
171
172       FUNC_END aeabi_frsub
173
174 #endif /* L_arm_addsubsf3 */
175
176 #ifdef L_arm_cmpsf2
177
178 FUNC_START aeabi_cfrcmple
179
180         mov     ip, r0
181         mov     r0, r1
182         mov     r1, ip
183         b       6f
184
185 FUNC_START aeabi_cfcmpeq
186 FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
187
188         @ The status-returning routines are required to preserve all
189         @ registers except ip, lr, and cpsr.
190 6:      push    {r0, r1, r2, r3, r4, lr}
191         bl      __lesf2
192         @ Set the Z flag correctly, and the C flag unconditionally.
193         cmp     r0, #0
194         @ Clear the C flag if the return value was -1, indicating
195         @ that the first operand was smaller than the second.
196         bmi 1f
197         mov     r1, #0
198         cmn     r0, r1
199 1:
200         pop     {r0, r1, r2, r3, r4, pc}
201
202         FUNC_END aeabi_cfcmple
203         FUNC_END aeabi_cfcmpeq
204         FUNC_END aeabi_cfrcmple
205
206 FUNC_START      aeabi_fcmpeq
207
208         push    {r4, lr}
209         bl      __eqsf2
210         neg     r0, r0
211         add     r0, r0, #1
212         pop     {r4, pc}
213
214         FUNC_END aeabi_fcmpeq
215
216 .macro COMPARISON cond, helper, mode=sf2
217 FUNC_START      aeabi_fcmp\cond
218
219         push    {r4, lr}
220         bl      __\helper\mode
221         cmp     r0, #0
222         b\cond  1f
223         mov     r0, #0
224         pop     {r4, pc}
225 1:
226         mov     r0, #1
227         pop     {r4, pc}
228
229         FUNC_END aeabi_fcmp\cond
230 .endm
231
232 COMPARISON lt, le
233 COMPARISON le, le
234 COMPARISON gt, ge
235 COMPARISON ge, ge
236
237 #endif /* L_arm_cmpsf2 */
238
239 #ifdef L_arm_addsubdf3
240
241 FUNC_START aeabi_drsub
242
243       push      {r4, lr}
244       mov       r4, #1
245       lsl       r4, #31
246       eor       xxh, xxh, r4
247       bl        __aeabi_dadd
248       pop       {r4, pc}
249
250       FUNC_END aeabi_drsub
251
252 #endif /* L_arm_addsubdf3 */
253
254 #ifdef L_arm_cmpdf2
255
256 FUNC_START aeabi_cdrcmple
257
258         mov     ip, r0
259         mov     r0, r2
260         mov     r2, ip
261         mov     ip, r1
262         mov     r1, r3
263         mov     r3, ip
264         b       6f
265
266 FUNC_START aeabi_cdcmpeq
267 FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
268
269         @ The status-returning routines are required to preserve all
270         @ registers except ip, lr, and cpsr.
271 6:      push    {r0, r1, r2, r3, r4, lr}
272         bl      __ledf2
273         @ Set the Z flag correctly, and the C flag unconditionally.
274         cmp     r0, #0
275         @ Clear the C flag if the return value was -1, indicating
276         @ that the first operand was smaller than the second.
277         bmi 1f
278         mov     r1, #0
279         cmn     r0, r1
280 1:
281         pop     {r0, r1, r2, r3, r4, pc}
282
283         FUNC_END aeabi_cdcmple
284         FUNC_END aeabi_cdcmpeq
285         FUNC_END aeabi_cdrcmple
286
287 FUNC_START      aeabi_dcmpeq
288
289         push    {r4, lr}
290         bl      __eqdf2
291         neg     r0, r0
292         add     r0, r0, #1
293         pop     {r4, pc}
294
295         FUNC_END aeabi_dcmpeq
296
297 .macro COMPARISON cond, helper, mode=df2
298 FUNC_START      aeabi_dcmp\cond
299
300         push    {r4, lr}
301         bl      __\helper\mode
302         cmp     r0, #0
303         b\cond  1f
304         mov     r0, #0
305         pop     {r4, pc}
306 1:
307         mov     r0, #1
308         pop     {r4, pc}
309
310         FUNC_END aeabi_dcmp\cond
311 .endm
312
313 COMPARISON lt, le
314 COMPARISON le, le
315 COMPARISON gt, ge
316 COMPARISON ge, ge
317
318 #endif /* L_arm_cmpdf2 */