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