Reverting merge from trunk
[official-gcc.git] / libgcc / config / arm / bpabi-v6m.S
blob2ad8f03748289461f123173a97d14e0f8cfb1af6
1 /* Miscellaneous BPABI functions.  ARMv6M implementation
3    Copyright (C) 2006-2013 Free Software Foundation, Inc.
4    Contributed by CodeSourcery.
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.
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.
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.
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/>.  */
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__ */
35 #ifdef L_aeabi_lcmp
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
45         mov     r0, #1
46         RET
48         sub     r0, xxl, yyl
49         beq     1f
50         bhi     2f
51         mov     r0, #1
52         neg     r0, r0
53         RET
55         mov     r0, #1
57         RET
58         FUNC_END aeabi_lcmp
60 #endif /* L_aeabi_lcmp */
61         
62 #ifdef L_aeabi_ulcmp
64 FUNC_START aeabi_ulcmp
65         cmp     xxh, yyh
66         bne     1f
67         sub     r0, xxl, yyl
68         beq     2f
70         bcs     1f
71         mov     r0, #1
72         neg     r0, r0
73         RET
75         mov     r0, #1
77         RET
78         FUNC_END aeabi_ulcmp
80 #endif /* L_aeabi_ulcmp */
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
91         .ifc    \signed, unsigned
92         beq     3f
93         mov     xxh, #0
94         mvn     xxh, xxh                @ 0xffffffff
95         mov     xxl, xxh
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
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
119         .word   __aeabi_ldiv0 - 1b
121 .endm
123 #ifdef L_aeabi_ldivmod
125 FUNC_START aeabi_ldivmod
126         test_div_by_zero signed
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
140 #endif /* L_aeabi_ldivmod */
142 #ifdef L_aeabi_uldivmod
144 FUNC_START aeabi_uldivmod
145         test_div_by_zero unsigned
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 */
161 #ifdef L_arm_addsubsf3
163 FUNC_START aeabi_frsub
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}
172       FUNC_END aeabi_frsub
174 #endif /* L_arm_addsubsf3 */
176 #ifdef L_arm_cmpsf2
178 FUNC_START aeabi_cfrcmple
180         mov     ip, r0
181         mov     r0, r1
182         mov     r1, ip
183         b       6f
185 FUNC_START aeabi_cfcmpeq
186 FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
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
200         pop     {r0, r1, r2, r3, r4, pc}
202         FUNC_END aeabi_cfcmple
203         FUNC_END aeabi_cfcmpeq
204         FUNC_END aeabi_cfrcmple
206 FUNC_START      aeabi_fcmpeq
208         push    {r4, lr}
209         bl      __eqsf2
210         neg     r0, r0
211         add     r0, r0, #1
212         pop     {r4, pc}
214         FUNC_END aeabi_fcmpeq
216 .macro COMPARISON cond, helper, mode=sf2
217 FUNC_START      aeabi_fcmp\cond
219         push    {r4, lr}
220         bl      __\helper\mode
221         cmp     r0, #0
222         b\cond  1f
223         mov     r0, #0
224         pop     {r4, pc}
226         mov     r0, #1
227         pop     {r4, pc}
229         FUNC_END aeabi_fcmp\cond
230 .endm
232 COMPARISON lt, le
233 COMPARISON le, le
234 COMPARISON gt, ge
235 COMPARISON ge, ge
237 #endif /* L_arm_cmpsf2 */
239 #ifdef L_arm_addsubdf3
241 FUNC_START aeabi_drsub
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}
250       FUNC_END aeabi_drsub
252 #endif /* L_arm_addsubdf3 */
254 #ifdef L_arm_cmpdf2
256 FUNC_START aeabi_cdrcmple
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
266 FUNC_START aeabi_cdcmpeq
267 FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
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
281         pop     {r0, r1, r2, r3, r4, pc}
283         FUNC_END aeabi_cdcmple
284         FUNC_END aeabi_cdcmpeq
285         FUNC_END aeabi_cdrcmple
287 FUNC_START      aeabi_dcmpeq
289         push    {r4, lr}
290         bl      __eqdf2
291         neg     r0, r0
292         add     r0, r0, #1
293         pop     {r4, pc}
295         FUNC_END aeabi_dcmpeq
297 .macro COMPARISON cond, helper, mode=df2
298 FUNC_START      aeabi_dcmp\cond
300         push    {r4, lr}
301         bl      __\helper\mode
302         cmp     r0, #0
303         b\cond  1f
304         mov     r0, #0
305         pop     {r4, pc}
307         mov     r0, #1
308         pop     {r4, pc}
310         FUNC_END aeabi_dcmp\cond
311 .endm
313 COMPARISON lt, le
314 COMPARISON le, le
315 COMPARISON gt, ge
316 COMPARISON ge, ge
318 #endif /* L_arm_cmpdf2 */