]>
Commit | Line | Data |
---|---|---|
7857f134 | 1 | @ libgcc routines for ARM cpu. |
bd28bf5a | 2 | @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) |
454e0249 | 3 | |
83ffe9cd | 4 | /* Copyright (C) 1995-2023 Free Software Foundation, Inc. |
454e0249 DE |
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 | |
748086b7 | 8 | Free Software Foundation; either version 3, or (at your option) any |
454e0249 DE |
9 | later version. |
10 | ||
454e0249 DE |
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 | ||
748086b7 JJ |
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/>. */ | |
978e411f | 24 | |
6b9ce2b4 RE |
25 | /* Everything in this file should now use unified syntax. */ |
26 | ||
27 | .syntax unified | |
28 | ||
978e411f CD |
29 | /* An executable stack is *not* required for these functions. */ |
30 | #if defined(__ELF__) && defined(__linux__) | |
31 | .section .note.GNU-stack,"",%progbits | |
32 | .previous | |
907dd0c7 RE |
33 | #endif /* __ELF__ and __linux__ */ |
34 | ||
35 | #ifdef __ARM_EABI__ | |
36 | /* Some attributes that are common to all routines in this file. */ | |
6f0668cf | 37 | /* Tag_ABI_align_needed: This code does not require 8-byte |
907dd0c7 RE |
38 | alignment from the caller. */ |
39 | /* .eabi_attribute 24, 0 -- default setting. */ | |
6f0668cf | 40 | /* Tag_ABI_align_preserved: This code preserves 8-byte |
907dd0c7 RE |
41 | alignment in any callee. */ |
42 | .eabi_attribute 25, 1 | |
43 | #endif /* __ARM_EABI__ */ | |
6dcd26ea | 44 | /* ------------------------------------------------------------------------ */ |
888e552f NC |
45 | |
46 | /* We need to know what prefix to add to function names. */ | |
47 | ||
2a5307b1 NC |
48 | #ifndef __USER_LABEL_PREFIX__ |
49 | #error __USER_LABEL_PREFIX__ not defined | |
50 | #endif | |
51 | ||
a1e27b76 NC |
52 | /* ANSI concatenation macros. */ |
53 | ||
54 | #define CONCAT1(a, b) CONCAT2(a, b) | |
55 | #define CONCAT2(a, b) a ## b | |
56 | ||
57 | /* Use the right prefix for global labels. */ | |
58 | ||
59 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) | |
60 | ||
140fa895 | 61 | #ifdef __ELF__ |
d5b7b3ae | 62 | #ifdef __thumb__ |
6dcd26ea | 63 | #define __PLT__ /* Not supported in Thumb assembler (for now). */ |
9403b7f7 RS |
64 | #elif defined __vxworks && !defined __PIC__ |
65 | #define __PLT__ /* Not supported by the kernel loader. */ | |
d5b7b3ae | 66 | #else |
b355a481 | 67 | #define __PLT__ (PLT) |
d5b7b3ae | 68 | #endif |
b355a481 NC |
69 | #define TYPE(x) .type SYM(x),function |
70 | #define SIZE(x) .size SYM(x), . - SYM(x) | |
ce250a20 | 71 | #define LSYM(x) .x |
b355a481 NC |
72 | #else |
73 | #define __PLT__ | |
74 | #define TYPE(x) | |
75 | #define SIZE(x) | |
ce250a20 | 76 | #define LSYM(x) x |
b355a481 NC |
77 | #endif |
78 | ||
61f0ccff | 79 | /* Function end macros. Variants for interworking. */ |
888e552f | 80 | |
8168ccc0 SH |
81 | /* There are times when we might prefer Thumb1 code even if ARM code is |
82 | permitted, for example, the code might be smaller, or there might be | |
83 | interworking problems with switching to ARM state if interworking is | |
84 | disabled. */ | |
85 | #if (defined(__thumb__) \ | |
86 | && !defined(__thumb2__) \ | |
87 | && (!defined(__THUMB_INTERWORK__) \ | |
88 | || defined (__OPTIMIZE_SIZE__) \ | |
6f493951 | 89 | || !__ARM_ARCH_ISA_ARM)) |
8168ccc0 SH |
90 | # define __prefer_thumb__ |
91 | #endif | |
92 | ||
6f493951 TP |
93 | #if !__ARM_ARCH_ISA_ARM && __ARM_ARCH_ISA_THUMB == 1 |
94 | #define NOT_ISA_TARGET_32BIT 1 | |
95 | #endif | |
96 | ||
496b84c8 RE |
97 | /* How to return from a function call depends on the architecture variant. */ |
98 | ||
9b2e34ef | 99 | #if (__ARM_ARCH > 4) || defined(__ARM_ARCH_4T__) |
496b84c8 RE |
100 | |
101 | # define RET bx lr | |
102 | # define RETc(x) bx##x lr | |
103 | ||
4c5f9898 | 104 | /* Special precautions for interworking on armv4t. */ |
9b2e34ef | 105 | # if (__ARM_ARCH == 4) |
4c5f9898 PB |
106 | |
107 | /* Always use bx, not ldr pc. */ | |
108 | # if (defined(__thumb__) || defined(__THUMB_INTERWORK__)) | |
109 | # define __INTERWORKING__ | |
110 | # endif /* __THUMB__ || __THUMB_INTERWORK__ */ | |
111 | ||
112 | /* Include thumb stub before arm mode code. */ | |
113 | # if defined(__thumb__) && !defined(__THUMB_INTERWORK__) | |
114 | # define __INTERWORKING_STUBS__ | |
115 | # endif /* __thumb__ && !__THUMB_INTERWORK__ */ | |
116 | ||
117 | #endif /* __ARM_ARCH == 4 */ | |
496b84c8 RE |
118 | |
119 | #else | |
120 | ||
121 | # define RET mov pc, lr | |
122 | # define RETc(x) mov##x pc, lr | |
123 | ||
124 | #endif | |
125 | ||
d0f11b16 DJ |
126 | .macro cfi_pop advance, reg, cfa_offset |
127 | #ifdef __ELF__ | |
128 | .pushsection .debug_frame | |
129 | .byte 0x4 /* DW_CFA_advance_loc4 */ | |
130 | .4byte \advance | |
131 | .byte (0xc0 | \reg) /* DW_CFA_restore */ | |
132 | .byte 0xe /* DW_CFA_def_cfa_offset */ | |
133 | .uleb128 \cfa_offset | |
134 | .popsection | |
135 | #endif | |
136 | .endm | |
137 | .macro cfi_push advance, reg, offset, cfa_offset | |
138 | #ifdef __ELF__ | |
139 | .pushsection .debug_frame | |
140 | .byte 0x4 /* DW_CFA_advance_loc4 */ | |
141 | .4byte \advance | |
142 | .byte (0x80 | \reg) /* DW_CFA_offset */ | |
143 | .uleb128 (\offset / -4) | |
144 | .byte 0xe /* DW_CFA_def_cfa_offset */ | |
145 | .uleb128 \cfa_offset | |
146 | .popsection | |
147 | #endif | |
148 | .endm | |
149 | .macro cfi_start start_label, end_label | |
150 | #ifdef __ELF__ | |
151 | .pushsection .debug_frame | |
152 | LSYM(Lstart_frame): | |
153 | .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE | |
154 | LSYM(Lstart_cie): | |
155 | .4byte 0xffffffff @ CIE Identifier Tag | |
156 | .byte 0x1 @ CIE Version | |
157 | .ascii "\0" @ CIE Augmentation | |
158 | .uleb128 0x1 @ CIE Code Alignment Factor | |
159 | .sleb128 -4 @ CIE Data Alignment Factor | |
160 | .byte 0xe @ CIE RA Column | |
161 | .byte 0xc @ DW_CFA_def_cfa | |
162 | .uleb128 0xd | |
163 | .uleb128 0x0 | |
164 | ||
165 | .align 2 | |
166 | LSYM(Lend_cie): | |
167 | .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length | |
168 | LSYM(Lstart_fde): | |
169 | .4byte LSYM(Lstart_frame) @ FDE CIE offset | |
170 | .4byte \start_label @ FDE initial location | |
171 | .4byte \end_label-\start_label @ FDE address range | |
172 | .popsection | |
173 | #endif | |
174 | .endm | |
175 | .macro cfi_end end_label | |
176 | #ifdef __ELF__ | |
177 | .pushsection .debug_frame | |
178 | .align 2 | |
179 | LSYM(Lend_fde): | |
180 | .popsection | |
181 | \end_label: | |
182 | #endif | |
183 | .endm | |
184 | ||
496b84c8 RE |
185 | /* Don't pass dirn, it's there just to get token pasting right. */ |
186 | ||
d0f11b16 | 187 | .macro RETLDM regs=, cond=, unwind=, dirn=ia |
61f0ccff | 188 | #if defined (__INTERWORKING__) |
496b84c8 | 189 | .ifc "\regs","" |
d0f11b16 | 190 | ldr\cond lr, [sp], #8 |
496b84c8 | 191 | .else |
5b3e6663 PB |
192 | # if defined(__thumb2__) |
193 | pop\cond {\regs, lr} | |
194 | # else | |
496b84c8 | 195 | ldm\cond\dirn sp!, {\regs, lr} |
5b3e6663 | 196 | # endif |
d0f11b16 DJ |
197 | .endif |
198 | .ifnc "\unwind", "" | |
199 | /* Mark LR as restored. */ | |
200 | 97: cfi_pop 97b - \unwind, 0xe, 0x0 | |
496b84c8 RE |
201 | .endif |
202 | bx\cond lr | |
203 | #else | |
5b3e6663 | 204 | /* Caller is responsible for providing IT instruction. */ |
496b84c8 | 205 | .ifc "\regs","" |
d0f11b16 | 206 | ldr\cond pc, [sp], #8 |
496b84c8 | 207 | .else |
5b3e6663 PB |
208 | # if defined(__thumb2__) |
209 | pop\cond {\regs, pc} | |
210 | # else | |
4531703e | 211 | ldm\cond\dirn sp!, {\regs, pc} |
5b3e6663 | 212 | # endif |
496b84c8 RE |
213 | .endif |
214 | #endif | |
215 | .endm | |
216 | ||
5b3e6663 PB |
217 | /* The Unified assembly syntax allows the same code to be assembled for both |
218 | ARM and Thumb-2. However this is only supported by recent gas, so define | |
219 | a set of macros to allow ARM code on older assemblers. */ | |
220 | #if defined(__thumb2__) | |
221 | .macro do_it cond, suffix="" | |
222 | it\suffix \cond | |
223 | .endm | |
224 | .macro shift1 op, arg0, arg1, arg2 | |
225 | \op \arg0, \arg1, \arg2 | |
226 | .endm | |
227 | #define do_push push | |
228 | #define do_pop pop | |
5b3e6663 PB |
229 | /* Perform an arithmetic operation with a variable shift operand. This |
230 | requires two instructions and a scratch register on Thumb-2. */ | |
231 | .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp | |
232 | \shiftop \tmp, \src2, \shiftreg | |
233 | \name \dest, \src1, \tmp | |
234 | .endm | |
235 | #else | |
236 | .macro do_it cond, suffix="" | |
237 | .endm | |
238 | .macro shift1 op, arg0, arg1, arg2 | |
239 | mov \arg0, \arg1, \op \arg2 | |
240 | .endm | |
241 | #define do_push stmfd sp!, | |
242 | #define do_pop ldmfd sp!, | |
5b3e6663 PB |
243 | .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp |
244 | \name \dest, \src1, \src2, \shiftop \shiftreg | |
245 | .endm | |
246 | #endif | |
496b84c8 | 247 | |
e519d644 RE |
248 | #define COND(op1, op2, cond) op1 ## op2 ## cond |
249 | ||
0c23e1be JB |
250 | #ifdef __ARM_EABI__ |
251 | .macro ARM_LDIV0 name signed | |
252 | cmp r0, #0 | |
253 | .ifc \signed, unsigned | |
254 | movne r0, #0xffffffff | |
255 | .else | |
256 | movgt r0, #0x7fffffff | |
257 | movlt r0, #0x80000000 | |
258 | .endif | |
259 | b SYM (__aeabi_idiv0) __PLT__ | |
260 | .endm | |
261 | #else | |
262 | .macro ARM_LDIV0 name signed | |
d0f11b16 DJ |
263 | str lr, [sp, #-8]! |
264 | 98: cfi_push 98b - __\name, 0xe, -0x8, 0x8 | |
6dcd26ea RE |
265 | bl SYM (__div0) __PLT__ |
266 | mov r0, #0 @ About as wrong as it could be. | |
d0f11b16 | 267 | RETLDM unwind=98b |
6dcd26ea | 268 | .endm |
0c23e1be | 269 | #endif |
496b84c8 RE |
270 | |
271 | ||
0c23e1be JB |
272 | #ifdef __ARM_EABI__ |
273 | .macro THUMB_LDIV0 name signed | |
6f493951 | 274 | #ifdef NOT_ISA_TARGET_32BIT |
82742404 HW |
275 | |
276 | push {r0, lr} | |
6b9ce2b4 | 277 | movs r0, #0 |
82742404 | 278 | bl SYM(__aeabi_idiv0) |
0c23e1be | 279 | @ We know we are not on armv4t, so pop pc is safe. |
82742404 HW |
280 | pop {r1, pc} |
281 | ||
0c23e1be JB |
282 | #elif defined(__thumb2__) |
283 | .syntax unified | |
284 | .ifc \signed, unsigned | |
285 | cbz r0, 1f | |
286 | mov r0, #0xffffffff | |
287 | 1: | |
288 | .else | |
289 | cmp r0, #0 | |
290 | do_it gt | |
291 | movgt r0, #0x7fffffff | |
292 | do_it lt | |
293 | movlt r0, #0x80000000 | |
294 | .endif | |
295 | b.w SYM(__aeabi_idiv0) __PLT__ | |
296 | #else | |
297 | .align 2 | |
298 | bx pc | |
299 | nop | |
300 | .arm | |
301 | cmp r0, #0 | |
302 | .ifc \signed, unsigned | |
303 | movne r0, #0xffffffff | |
304 | .else | |
305 | movgt r0, #0x7fffffff | |
306 | movlt r0, #0x80000000 | |
307 | .endif | |
308 | b SYM(__aeabi_idiv0) __PLT__ | |
309 | .thumb | |
310 | #endif | |
311 | .endm | |
312 | #else | |
313 | .macro THUMB_LDIV0 name signed | |
d0f11b16 DJ |
314 | push { r1, lr } |
315 | 98: cfi_push 98b - __\name, 0xe, -0x4, 0x8 | |
6dcd26ea | 316 | bl SYM (__div0) |
6b9ce2b4 | 317 | movs r0, #0 @ About as wrong as it could be. |
496b84c8 | 318 | #if defined (__INTERWORKING__) |
d0f11b16 DJ |
319 | pop { r1, r2 } |
320 | bx r2 | |
496b84c8 | 321 | #else |
d0f11b16 | 322 | pop { r1, pc } |
6dcd26ea | 323 | #endif |
496b84c8 | 324 | .endm |
0c23e1be | 325 | #endif |
6dcd26ea | 326 | |
888e552f | 327 | .macro FUNC_END name |
496b84c8 RE |
328 | SIZE (__\name) |
329 | .endm | |
330 | ||
0c23e1be | 331 | .macro DIV_FUNC_END name signed |
d0f11b16 | 332 | cfi_start __\name, LSYM(Lend_div0) |
ce250a20 | 333 | LSYM(Ldiv0): |
888e552f | 334 | #ifdef __thumb__ |
0c23e1be | 335 | THUMB_LDIV0 \name \signed |
888e552f | 336 | #else |
0c23e1be | 337 | ARM_LDIV0 \name \signed |
888e552f | 338 | #endif |
d0f11b16 | 339 | cfi_end LSYM(Lend_div0) |
496b84c8 | 340 | FUNC_END \name |
888e552f NC |
341 | .endm |
342 | ||
343 | .macro THUMB_FUNC_START name | |
344 | .globl SYM (\name) | |
345 | TYPE (\name) | |
346 | .thumb_func | |
347 | SYM (\name): | |
348 | .endm | |
349 | ||
350 | /* Function start macros. Variants for ARM and Thumb. */ | |
351 | ||
d5b7b3ae RE |
352 | #ifdef __thumb__ |
353 | #define THUMB_FUNC .thumb_func | |
354 | #define THUMB_CODE .force_thumb | |
5b3e6663 | 355 | # if defined(__thumb2__) |
6b9ce2b4 | 356 | #define THUMB_SYNTAX |
5b3e6663 PB |
357 | # else |
358 | #define THUMB_SYNTAX | |
359 | # endif | |
d5b7b3ae RE |
360 | #else |
361 | #define THUMB_FUNC | |
362 | #define THUMB_CODE | |
5b3e6663 | 363 | #define THUMB_SYNTAX |
d5b7b3ae | 364 | #endif |
5b3e6663 | 365 | |
72e3a529 | 366 | .macro FUNC_START name |
d5b7b3ae RE |
367 | .text |
368 | .globl SYM (__\name) | |
369 | TYPE (__\name) | |
370 | .align 0 | |
371 | THUMB_CODE | |
372 | THUMB_FUNC | |
5b3e6663 | 373 | THUMB_SYNTAX |
d5b7b3ae RE |
374 | SYM (__\name): |
375 | .endm | |
496b84c8 | 376 | |
1025cb6c TW |
377 | .macro ARM_SYM_START name |
378 | TYPE (\name) | |
379 | .align 0 | |
380 | SYM (\name): | |
381 | .endm | |
382 | ||
383 | .macro SYM_END name | |
384 | SIZE (\name) | |
385 | .endm | |
386 | ||
496b84c8 RE |
387 | /* Special function that will always be coded in ARM assembly, even if |
388 | in Thumb-only compilation. */ | |
389 | ||
5b3e6663 PB |
390 | #if defined(__thumb2__) |
391 | ||
392 | /* For Thumb-2 we build everything in thumb mode. */ | |
72e3a529 TP |
393 | .macro ARM_FUNC_START name |
394 | FUNC_START \name | |
5b3e6663 PB |
395 | .syntax unified |
396 | .endm | |
397 | #define EQUIV .thumb_set | |
398 | .macro ARM_CALL name | |
399 | bl __\name | |
400 | .endm | |
401 | ||
402 | #elif defined(__INTERWORKING_STUBS__) | |
403 | ||
496b84c8 RE |
404 | .macro ARM_FUNC_START name |
405 | FUNC_START \name | |
406 | bx pc | |
407 | nop | |
408 | .arm | |
db151e9d PB |
409 | /* A hook to tell gdb that we've switched to ARM mode. Also used to call |
410 | directly from other local arm routines. */ | |
411 | _L__\name: | |
496b84c8 | 412 | .endm |
46049cff | 413 | #define EQUIV .thumb_set |
db151e9d PB |
414 | /* Branch directly to a function declared with ARM_FUNC_START. |
415 | Must be called in arm mode. */ | |
b3f8d95d MM |
416 | .macro ARM_CALL name |
417 | bl _L__\name | |
418 | .endm | |
5b3e6663 PB |
419 | |
420 | #else /* !(__INTERWORKING_STUBS__ || __thumb2__) */ | |
421 | ||
6f493951 | 422 | #ifdef NOT_ISA_TARGET_32BIT |
bf98ec6c PB |
423 | #define EQUIV .thumb_set |
424 | #else | |
72e3a529 | 425 | .macro ARM_FUNC_START name |
46049cff RE |
426 | .text |
427 | .globl SYM (__\name) | |
428 | TYPE (__\name) | |
429 | .align 0 | |
430 | .arm | |
431 | SYM (__\name): | |
496b84c8 | 432 | .endm |
46049cff | 433 | #define EQUIV .set |
b3f8d95d MM |
434 | .macro ARM_CALL name |
435 | bl __\name | |
436 | .endm | |
bf98ec6c | 437 | #endif |
5b3e6663 | 438 | |
496b84c8 RE |
439 | #endif |
440 | ||
2155b886 RE |
441 | .macro FUNC_ALIAS new old |
442 | .globl SYM (__\new) | |
4c5f9898 PB |
443 | #if defined (__thumb__) |
444 | .thumb_set SYM (__\new), SYM (__\old) | |
445 | #else | |
446 | .set SYM (__\new), SYM (__\old) | |
447 | #endif | |
2155b886 RE |
448 | .endm |
449 | ||
6f493951 | 450 | #ifndef NOT_ISA_TARGET_32BIT |
46049cff RE |
451 | .macro ARM_FUNC_ALIAS new old |
452 | .globl SYM (__\new) | |
453 | EQUIV SYM (__\new), SYM (__\old) | |
4c5f9898 | 454 | #if defined(__INTERWORKING_STUBS__) |
db151e9d PB |
455 | .set SYM (_L__\new), SYM (_L__\old) |
456 | #endif | |
46049cff | 457 | .endm |
bf98ec6c | 458 | #endif |
46049cff | 459 | |
ef0a4b67 PB |
460 | #ifdef __ARMEB__ |
461 | #define xxh r0 | |
462 | #define xxl r1 | |
463 | #define yyh r2 | |
464 | #define yyl r3 | |
465 | #else | |
466 | #define xxh r1 | |
467 | #define xxl r0 | |
468 | #define yyh r3 | |
469 | #define yyl r2 | |
470 | #endif | |
471 | ||
0c23e1be JB |
472 | #ifdef __ARM_EABI__ |
473 | .macro WEAK name | |
474 | .weak SYM (__\name) | |
475 | .endm | |
476 | #endif | |
477 | ||
6a436e5e | 478 | #ifdef __thumb__ |
888e552f | 479 | /* Register aliases. */ |
454e0249 | 480 | |
888e552f | 481 | work .req r4 @ XXXX is this safe ? |
bd28bf5a RE |
482 | dividend .req r0 |
483 | divisor .req r1 | |
888e552f | 484 | overdone .req r2 |
bd28bf5a RE |
485 | result .req r2 |
486 | curbit .req r3 | |
6a436e5e | 487 | #endif |
5a9335ef | 488 | #if 0 |
bd28bf5a RE |
489 | ip .req r12 |
490 | sp .req r13 | |
491 | lr .req r14 | |
492 | pc .req r15 | |
5a9335ef | 493 | #endif |
6a436e5e | 494 | |
888e552f | 495 | /* ------------------------------------------------------------------------ */ |
9a9f7594 | 496 | /* Bodies of the division and modulo routines. */ |
e519d644 RE |
497 | /* ------------------------------------------------------------------------ */ |
498 | ||
6a436e5e NP |
499 | .macro ARM_DIV_BODY dividend, divisor, result, curbit |
500 | ||
9b2e34ef | 501 | #if defined (__ARM_FEATURE_CLZ) && ! defined (__OPTIMIZE_SIZE__) |
9b66ebb1 | 502 | |
f36d140e PB |
503 | #if defined (__thumb2__) |
504 | clz \curbit, \dividend | |
505 | clz \result, \divisor | |
506 | sub \curbit, \result, \curbit | |
507 | rsb \curbit, \curbit, #31 | |
508 | adr \result, 1f | |
509 | add \curbit, \result, \curbit, lsl #4 | |
510 | mov \result, #0 | |
511 | mov pc, \curbit | |
512 | .p2align 3 | |
513 | 1: | |
514 | .set shift, 32 | |
515 | .rept 32 | |
516 | .set shift, shift - 1 | |
517 | cmp.w \dividend, \divisor, lsl #shift | |
518 | nop.n | |
519 | adc.w \result, \result, \result | |
520 | it cs | |
521 | subcs.w \dividend, \dividend, \divisor, lsl #shift | |
522 | .endr | |
523 | #else | |
9b66ebb1 PB |
524 | clz \curbit, \dividend |
525 | clz \result, \divisor | |
526 | sub \curbit, \result, \curbit | |
527 | rsbs \curbit, \curbit, #31 | |
528 | addne \curbit, \curbit, \curbit, lsl #1 | |
529 | mov \result, #0 | |
530 | addne pc, pc, \curbit, lsl #2 | |
531 | nop | |
532 | .set shift, 32 | |
533 | .rept 32 | |
534 | .set shift, shift - 1 | |
535 | cmp \dividend, \divisor, lsl #shift | |
536 | adc \result, \result, \result | |
537 | subcs \dividend, \dividend, \divisor, lsl #shift | |
538 | .endr | |
f36d140e | 539 | #endif |
9b66ebb1 | 540 | |
9b2e34ef CL |
541 | #else /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ |
542 | #if defined (__ARM_FEATURE_CLZ) | |
6a436e5e NP |
543 | |
544 | clz \curbit, \divisor | |
545 | clz \result, \dividend | |
546 | sub \result, \curbit, \result | |
547 | mov \curbit, #1 | |
548 | mov \divisor, \divisor, lsl \result | |
549 | mov \curbit, \curbit, lsl \result | |
550 | mov \result, #0 | |
551 | ||
9b2e34ef | 552 | #else /* !defined (__ARM_FEATURE_CLZ) */ |
6a436e5e NP |
553 | |
554 | @ Initially shift the divisor left 3 bits if possible, | |
555 | @ set curbit accordingly. This allows for curbit to be located | |
a50aa827 | 556 | @ at the left end of each 4-bit nibbles in the division loop |
6a436e5e NP |
557 | @ to save one loop in most cases. |
558 | tst \divisor, #0xe0000000 | |
559 | moveq \divisor, \divisor, lsl #3 | |
560 | moveq \curbit, #8 | |
561 | movne \curbit, #1 | |
562 | ||
bd28bf5a RE |
563 | @ Unless the divisor is very big, shift it up in multiples of |
564 | @ four bits, since this is the amount of unwinding in the main | |
565 | @ division loop. Continue shifting until the divisor is | |
566 | @ larger than the dividend. | |
6a436e5e NP |
567 | 1: cmp \divisor, #0x10000000 |
568 | cmplo \divisor, \dividend | |
569 | movlo \divisor, \divisor, lsl #4 | |
570 | movlo \curbit, \curbit, lsl #4 | |
571 | blo 1b | |
bd28bf5a | 572 | |
bd28bf5a RE |
573 | @ For very big divisors, we must shift it a bit at a time, or |
574 | @ we will be in danger of overflowing. | |
6a436e5e NP |
575 | 1: cmp \divisor, #0x80000000 |
576 | cmplo \divisor, \dividend | |
577 | movlo \divisor, \divisor, lsl #1 | |
578 | movlo \curbit, \curbit, lsl #1 | |
579 | blo 1b | |
bd28bf5a | 580 | |
6a436e5e NP |
581 | mov \result, #0 |
582 | ||
9b2e34ef | 583 | #endif /* !defined (__ARM_FEATURE_CLZ) */ |
6a436e5e NP |
584 | |
585 | @ Division loop | |
586 | 1: cmp \dividend, \divisor | |
f36d140e | 587 | do_it hs, t |
6a436e5e NP |
588 | subhs \dividend, \dividend, \divisor |
589 | orrhs \result, \result, \curbit | |
590 | cmp \dividend, \divisor, lsr #1 | |
f36d140e | 591 | do_it hs, t |
6a436e5e NP |
592 | subhs \dividend, \dividend, \divisor, lsr #1 |
593 | orrhs \result, \result, \curbit, lsr #1 | |
594 | cmp \dividend, \divisor, lsr #2 | |
f36d140e | 595 | do_it hs, t |
6a436e5e NP |
596 | subhs \dividend, \dividend, \divisor, lsr #2 |
597 | orrhs \result, \result, \curbit, lsr #2 | |
598 | cmp \dividend, \divisor, lsr #3 | |
f36d140e | 599 | do_it hs, t |
6a436e5e NP |
600 | subhs \dividend, \dividend, \divisor, lsr #3 |
601 | orrhs \result, \result, \curbit, lsr #3 | |
602 | cmp \dividend, #0 @ Early termination? | |
ee102849 | 603 | do_it ne, t |
6a436e5e NP |
604 | movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? |
605 | movne \divisor, \divisor, lsr #4 | |
606 | bne 1b | |
607 | ||
9b2e34ef | 608 | #endif /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ |
9b66ebb1 | 609 | |
6a436e5e NP |
610 | .endm |
611 | /* ------------------------------------------------------------------------ */ | |
612 | .macro ARM_DIV2_ORDER divisor, order | |
613 | ||
9b2e34ef | 614 | #if defined (__ARM_FEATURE_CLZ) |
6a436e5e NP |
615 | |
616 | clz \order, \divisor | |
617 | rsb \order, \order, #31 | |
618 | ||
619 | #else | |
620 | ||
621 | cmp \divisor, #(1 << 16) | |
622 | movhs \divisor, \divisor, lsr #16 | |
623 | movhs \order, #16 | |
624 | movlo \order, #0 | |
625 | ||
626 | cmp \divisor, #(1 << 8) | |
627 | movhs \divisor, \divisor, lsr #8 | |
628 | addhs \order, \order, #8 | |
629 | ||
630 | cmp \divisor, #(1 << 4) | |
631 | movhs \divisor, \divisor, lsr #4 | |
632 | addhs \order, \order, #4 | |
633 | ||
634 | cmp \divisor, #(1 << 2) | |
635 | addhi \order, \order, #3 | |
636 | addls \order, \order, \divisor, lsr #1 | |
637 | ||
638 | #endif | |
639 | ||
640 | .endm | |
641 | /* ------------------------------------------------------------------------ */ | |
642 | .macro ARM_MOD_BODY dividend, divisor, order, spare | |
643 | ||
9b2e34ef | 644 | #if defined(__ARM_FEATURE_CLZ) && ! defined (__OPTIMIZE_SIZE__) |
9b66ebb1 PB |
645 | |
646 | clz \order, \divisor | |
647 | clz \spare, \dividend | |
648 | sub \order, \order, \spare | |
649 | rsbs \order, \order, #31 | |
650 | addne pc, pc, \order, lsl #3 | |
651 | nop | |
652 | .set shift, 32 | |
653 | .rept 32 | |
654 | .set shift, shift - 1 | |
655 | cmp \dividend, \divisor, lsl #shift | |
656 | subcs \dividend, \dividend, \divisor, lsl #shift | |
657 | .endr | |
658 | ||
9b2e34ef CL |
659 | #else /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ |
660 | #if defined (__ARM_FEATURE_CLZ) | |
6a436e5e NP |
661 | |
662 | clz \order, \divisor | |
663 | clz \spare, \dividend | |
664 | sub \order, \order, \spare | |
665 | mov \divisor, \divisor, lsl \order | |
888e552f | 666 | |
9b2e34ef | 667 | #else /* !defined (__ARM_FEATURE_CLZ) */ |
454e0249 | 668 | |
6a436e5e | 669 | mov \order, #0 |
454e0249 | 670 | |
6a436e5e NP |
671 | @ Unless the divisor is very big, shift it up in multiples of |
672 | @ four bits, since this is the amount of unwinding in the main | |
673 | @ division loop. Continue shifting until the divisor is | |
674 | @ larger than the dividend. | |
675 | 1: cmp \divisor, #0x10000000 | |
676 | cmplo \divisor, \dividend | |
677 | movlo \divisor, \divisor, lsl #4 | |
678 | addlo \order, \order, #4 | |
679 | blo 1b | |
b355a481 | 680 | |
6a436e5e NP |
681 | @ For very big divisors, we must shift it a bit at a time, or |
682 | @ we will be in danger of overflowing. | |
683 | 1: cmp \divisor, #0x80000000 | |
684 | cmplo \divisor, \dividend | |
685 | movlo \divisor, \divisor, lsl #1 | |
686 | addlo \order, \order, #1 | |
687 | blo 1b | |
688 | ||
9b2e34ef | 689 | #endif /* !defined (__ARM_FEATURE_CLZ) */ |
6a436e5e NP |
690 | |
691 | @ Perform all needed substractions to keep only the reminder. | |
692 | @ Do comparisons in batch of 4 first. | |
693 | subs \order, \order, #3 @ yes, 3 is intended here | |
694 | blt 2f | |
695 | ||
696 | 1: cmp \dividend, \divisor | |
697 | subhs \dividend, \dividend, \divisor | |
698 | cmp \dividend, \divisor, lsr #1 | |
699 | subhs \dividend, \dividend, \divisor, lsr #1 | |
700 | cmp \dividend, \divisor, lsr #2 | |
701 | subhs \dividend, \dividend, \divisor, lsr #2 | |
702 | cmp \dividend, \divisor, lsr #3 | |
703 | subhs \dividend, \dividend, \divisor, lsr #3 | |
704 | cmp \dividend, #1 | |
705 | mov \divisor, \divisor, lsr #4 | |
706 | subges \order, \order, #4 | |
707 | bge 1b | |
708 | ||
709 | tst \order, #3 | |
710 | teqne \dividend, #0 | |
711 | beq 5f | |
712 | ||
713 | @ Either 1, 2 or 3 comparison/substractions are left. | |
714 | 2: cmn \order, #2 | |
715 | blt 4f | |
716 | beq 3f | |
717 | cmp \dividend, \divisor | |
718 | subhs \dividend, \dividend, \divisor | |
719 | mov \divisor, \divisor, lsr #1 | |
720 | 3: cmp \dividend, \divisor | |
721 | subhs \dividend, \dividend, \divisor | |
722 | mov \divisor, \divisor, lsr #1 | |
723 | 4: cmp \dividend, \divisor | |
724 | subhs \dividend, \dividend, \divisor | |
725 | 5: | |
9b66ebb1 | 726 | |
9b2e34ef | 727 | #endif /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */ |
9b66ebb1 | 728 | |
888e552f | 729 | .endm |
6dcd26ea | 730 | /* ------------------------------------------------------------------------ */ |
888e552f NC |
731 | .macro THUMB_DIV_MOD_BODY modulo |
732 | @ Load the constant 0x10000000 into our work register. | |
6b9ce2b4 RE |
733 | movs work, #1 |
734 | lsls work, #28 | |
ce250a20 | 735 | LSYM(Loop1): |
d5b7b3ae RE |
736 | @ Unless the divisor is very big, shift it up in multiples of |
737 | @ four bits, since this is the amount of unwinding in the main | |
738 | @ division loop. Continue shifting until the divisor is | |
739 | @ larger than the dividend. | |
740 | cmp divisor, work | |
ce250a20 | 741 | bhs LSYM(Lbignum) |
d5b7b3ae | 742 | cmp divisor, dividend |
ce250a20 | 743 | bhs LSYM(Lbignum) |
6b9ce2b4 RE |
744 | lsls divisor, #4 |
745 | lsls curbit, #4 | |
ce250a20 RE |
746 | b LSYM(Loop1) |
747 | LSYM(Lbignum): | |
d5b7b3ae | 748 | @ Set work to 0x80000000 |
6b9ce2b4 | 749 | lsls work, #3 |
ce250a20 | 750 | LSYM(Loop2): |
d5b7b3ae RE |
751 | @ For very big divisors, we must shift it a bit at a time, or |
752 | @ we will be in danger of overflowing. | |
753 | cmp divisor, work | |
ce250a20 | 754 | bhs LSYM(Loop3) |
d5b7b3ae | 755 | cmp divisor, dividend |
ce250a20 | 756 | bhs LSYM(Loop3) |
6b9ce2b4 RE |
757 | lsls divisor, #1 |
758 | lsls curbit, #1 | |
ce250a20 RE |
759 | b LSYM(Loop2) |
760 | LSYM(Loop3): | |
888e552f NC |
761 | @ Test for possible subtractions ... |
762 | .if \modulo | |
763 | @ ... On the final pass, this may subtract too much from the dividend, | |
764 | @ so keep track of which subtractions are done, we can fix them up | |
765 | @ afterwards. | |
6b9ce2b4 | 766 | movs overdone, #0 |
d5b7b3ae | 767 | cmp dividend, divisor |
ce250a20 | 768 | blo LSYM(Lover1) |
6b9ce2b4 | 769 | subs dividend, dividend, divisor |
ce250a20 | 770 | LSYM(Lover1): |
6b9ce2b4 | 771 | lsrs work, divisor, #1 |
d5b7b3ae | 772 | cmp dividend, work |
ce250a20 | 773 | blo LSYM(Lover2) |
6b9ce2b4 | 774 | subs dividend, dividend, work |
d5b7b3ae | 775 | mov ip, curbit |
6b9ce2b4 RE |
776 | movs work, #1 |
777 | rors curbit, work | |
778 | orrs overdone, curbit | |
d5b7b3ae | 779 | mov curbit, ip |
ce250a20 | 780 | LSYM(Lover2): |
6b9ce2b4 | 781 | lsrs work, divisor, #2 |
d5b7b3ae | 782 | cmp dividend, work |
ce250a20 | 783 | blo LSYM(Lover3) |
6b9ce2b4 | 784 | subs dividend, dividend, work |
d5b7b3ae | 785 | mov ip, curbit |
6b9ce2b4 RE |
786 | movs work, #2 |
787 | rors curbit, work | |
788 | orrs overdone, curbit | |
d5b7b3ae | 789 | mov curbit, ip |
ce250a20 | 790 | LSYM(Lover3): |
6b9ce2b4 | 791 | lsrs work, divisor, #3 |
d5b7b3ae | 792 | cmp dividend, work |
ce250a20 | 793 | blo LSYM(Lover4) |
6b9ce2b4 | 794 | subs dividend, dividend, work |
d5b7b3ae | 795 | mov ip, curbit |
6b9ce2b4 RE |
796 | movs work, #3 |
797 | rors curbit, work | |
798 | orrs overdone, curbit | |
d5b7b3ae | 799 | mov curbit, ip |
ce250a20 | 800 | LSYM(Lover4): |
d5b7b3ae | 801 | mov ip, curbit |
888e552f NC |
802 | .else |
803 | @ ... and note which bits are done in the result. On the final pass, | |
804 | @ this may subtract too much from the dividend, but the result will be ok, | |
805 | @ since the "bit" will have been shifted out at the bottom. | |
806 | cmp dividend, divisor | |
ce250a20 | 807 | blo LSYM(Lover1) |
6b9ce2b4 RE |
808 | subs dividend, dividend, divisor |
809 | orrs result, result, curbit | |
ba2f4247 | 810 | LSYM(Lover1): |
6b9ce2b4 | 811 | lsrs work, divisor, #1 |
888e552f | 812 | cmp dividend, work |
ce250a20 | 813 | blo LSYM(Lover2) |
6b9ce2b4 RE |
814 | subs dividend, dividend, work |
815 | lsrs work, curbit, #1 | |
816 | orrs result, work | |
ce250a20 | 817 | LSYM(Lover2): |
6b9ce2b4 | 818 | lsrs work, divisor, #2 |
888e552f | 819 | cmp dividend, work |
ce250a20 | 820 | blo LSYM(Lover3) |
6b9ce2b4 RE |
821 | subs dividend, dividend, work |
822 | lsrs work, curbit, #2 | |
823 | orrs result, work | |
ce250a20 | 824 | LSYM(Lover3): |
6b9ce2b4 | 825 | lsrs work, divisor, #3 |
888e552f | 826 | cmp dividend, work |
ce250a20 | 827 | blo LSYM(Lover4) |
6b9ce2b4 RE |
828 | subs dividend, dividend, work |
829 | lsrs work, curbit, #3 | |
830 | orrs result, work | |
ce250a20 | 831 | LSYM(Lover4): |
888e552f NC |
832 | .endif |
833 | ||
d5b7b3ae | 834 | cmp dividend, #0 @ Early termination? |
ce250a20 | 835 | beq LSYM(Lover5) |
6b9ce2b4 | 836 | lsrs curbit, #4 @ No, any more bits to do? |
ce250a20 | 837 | beq LSYM(Lover5) |
6b9ce2b4 | 838 | lsrs divisor, #4 |
ce250a20 RE |
839 | b LSYM(Loop3) |
840 | LSYM(Lover5): | |
888e552f | 841 | .if \modulo |
d5b7b3ae RE |
842 | @ Any subtractions that we should not have done will be recorded in |
843 | @ the top three bits of "overdone". Exactly which were not needed | |
844 | @ are governed by the position of the bit, stored in ip. | |
6b9ce2b4 RE |
845 | movs work, #0xe |
846 | lsls work, #28 | |
847 | ands overdone, work | |
ce250a20 | 848 | beq LSYM(Lgot_result) |
7405dc37 NC |
849 | |
850 | @ If we terminated early, because dividend became zero, then the | |
851 | @ bit in ip will not be in the bottom nibble, and we should not | |
852 | @ perform the additions below. We must test for this though | |
853 | @ (rather relying upon the TSTs to prevent the additions) since | |
854 | @ the bit in ip could be in the top two bits which might then match | |
855 | @ with one of the smaller RORs. | |
856 | mov curbit, ip | |
6b9ce2b4 | 857 | movs work, #0x7 |
7405dc37 | 858 | tst curbit, work |
ce250a20 | 859 | beq LSYM(Lgot_result) |
7405dc37 | 860 | |
d5b7b3ae | 861 | mov curbit, ip |
6b9ce2b4 RE |
862 | movs work, #3 |
863 | rors curbit, work | |
d5b7b3ae | 864 | tst overdone, curbit |
ce250a20 | 865 | beq LSYM(Lover6) |
6b9ce2b4 RE |
866 | lsrs work, divisor, #3 |
867 | adds dividend, work | |
ce250a20 | 868 | LSYM(Lover6): |
d5b7b3ae | 869 | mov curbit, ip |
6b9ce2b4 RE |
870 | movs work, #2 |
871 | rors curbit, work | |
d5b7b3ae | 872 | tst overdone, curbit |
ce250a20 | 873 | beq LSYM(Lover7) |
6b9ce2b4 RE |
874 | lsrs work, divisor, #2 |
875 | adds dividend, work | |
ce250a20 | 876 | LSYM(Lover7): |
d5b7b3ae | 877 | mov curbit, ip |
6b9ce2b4 RE |
878 | movs work, #1 |
879 | rors curbit, work | |
d5b7b3ae | 880 | tst overdone, curbit |
ce250a20 | 881 | beq LSYM(Lgot_result) |
6b9ce2b4 RE |
882 | lsrs work, divisor, #1 |
883 | adds dividend, work | |
888e552f | 884 | .endif |
ce250a20 | 885 | LSYM(Lgot_result): |
82742404 HW |
886 | .endm |
887 | ||
888 | /* If performance is preferred, the following functions are provided. */ | |
889 | #if defined(__prefer_thumb__) && !defined(__OPTIMIZE_SIZE__) | |
890 | ||
891 | /* Branch to div(n), and jump to label if curbit is lo than divisior. */ | |
892 | .macro BranchToDiv n, label | |
6b9ce2b4 | 893 | lsrs curbit, dividend, \n |
82742404 HW |
894 | cmp curbit, divisor |
895 | blo \label | |
896 | .endm | |
897 | ||
898 | /* Body of div(n). Shift the divisor in n bits and compare the divisor | |
899 | and dividend. Update the dividend as the substruction result. */ | |
900 | .macro DoDiv n | |
6b9ce2b4 | 901 | lsrs curbit, dividend, \n |
82742404 HW |
902 | cmp curbit, divisor |
903 | bcc 1f | |
6b9ce2b4 RE |
904 | lsls curbit, divisor, \n |
905 | subs dividend, dividend, curbit | |
82742404 | 906 | |
6b9ce2b4 | 907 | 1: adcs result, result |
82742404 HW |
908 | .endm |
909 | ||
910 | /* The body of division with positive divisor. Unless the divisor is very | |
911 | big, shift it up in multiples of four bits, since this is the amount of | |
912 | unwinding in the main division loop. Continue shifting until the divisor | |
913 | is larger than the dividend. */ | |
914 | .macro THUMB1_Div_Positive | |
6b9ce2b4 | 915 | movs result, #0 |
82742404 HW |
916 | BranchToDiv #1, LSYM(Lthumb1_div1) |
917 | BranchToDiv #4, LSYM(Lthumb1_div4) | |
918 | BranchToDiv #8, LSYM(Lthumb1_div8) | |
919 | BranchToDiv #12, LSYM(Lthumb1_div12) | |
920 | BranchToDiv #16, LSYM(Lthumb1_div16) | |
921 | LSYM(Lthumb1_div_large_positive): | |
6b9ce2b4 RE |
922 | movs result, #0xff |
923 | lsls divisor, divisor, #8 | |
82742404 | 924 | rev result, result |
6b9ce2b4 | 925 | lsrs curbit, dividend, #16 |
82742404 HW |
926 | cmp curbit, divisor |
927 | blo 1f | |
6b9ce2b4 RE |
928 | asrs result, #8 |
929 | lsls divisor, divisor, #8 | |
82742404 HW |
930 | beq LSYM(Ldivbyzero_waypoint) |
931 | ||
6b9ce2b4 | 932 | 1: lsrs curbit, dividend, #12 |
82742404 HW |
933 | cmp curbit, divisor |
934 | blo LSYM(Lthumb1_div12) | |
935 | b LSYM(Lthumb1_div16) | |
936 | LSYM(Lthumb1_div_loop): | |
6b9ce2b4 | 937 | lsrs divisor, divisor, #8 |
82742404 HW |
938 | LSYM(Lthumb1_div16): |
939 | Dodiv #15 | |
940 | Dodiv #14 | |
941 | Dodiv #13 | |
942 | Dodiv #12 | |
943 | LSYM(Lthumb1_div12): | |
944 | Dodiv #11 | |
945 | Dodiv #10 | |
946 | Dodiv #9 | |
947 | Dodiv #8 | |
948 | bcs LSYM(Lthumb1_div_loop) | |
949 | LSYM(Lthumb1_div8): | |
950 | Dodiv #7 | |
951 | Dodiv #6 | |
952 | Dodiv #5 | |
953 | LSYM(Lthumb1_div5): | |
954 | Dodiv #4 | |
955 | LSYM(Lthumb1_div4): | |
956 | Dodiv #3 | |
957 | LSYM(Lthumb1_div3): | |
958 | Dodiv #2 | |
959 | LSYM(Lthumb1_div2): | |
960 | Dodiv #1 | |
961 | LSYM(Lthumb1_div1): | |
6b9ce2b4 | 962 | subs divisor, dividend, divisor |
82742404 HW |
963 | bcs 1f |
964 | cpy divisor, dividend | |
965 | ||
6b9ce2b4 | 966 | 1: adcs result, result |
82742404 HW |
967 | cpy dividend, result |
968 | RET | |
969 | ||
970 | LSYM(Ldivbyzero_waypoint): | |
971 | b LSYM(Ldiv0) | |
972 | .endm | |
973 | ||
974 | /* The body of division with negative divisor. Similar with | |
975 | THUMB1_Div_Positive except that the shift steps are in multiples | |
976 | of six bits. */ | |
977 | .macro THUMB1_Div_Negative | |
6b9ce2b4 | 978 | lsrs result, divisor, #31 |
82742404 | 979 | beq 1f |
6b9ce2b4 | 980 | negs divisor, divisor |
82742404 | 981 | |
6b9ce2b4 | 982 | 1: asrs curbit, dividend, #32 |
82742404 | 983 | bcc 2f |
6b9ce2b4 | 984 | negs dividend, dividend |
82742404 | 985 | |
6b9ce2b4 RE |
986 | 2: eors curbit, result |
987 | movs result, #0 | |
82742404 HW |
988 | cpy ip, curbit |
989 | BranchToDiv #4, LSYM(Lthumb1_div_negative4) | |
990 | BranchToDiv #8, LSYM(Lthumb1_div_negative8) | |
991 | LSYM(Lthumb1_div_large): | |
6b9ce2b4 RE |
992 | movs result, #0xfc |
993 | lsls divisor, divisor, #6 | |
82742404 | 994 | rev result, result |
6b9ce2b4 | 995 | lsrs curbit, dividend, #8 |
82742404 HW |
996 | cmp curbit, divisor |
997 | blo LSYM(Lthumb1_div_negative8) | |
998 | ||
6b9ce2b4 RE |
999 | lsls divisor, divisor, #6 |
1000 | asrs result, result, #6 | |
82742404 HW |
1001 | cmp curbit, divisor |
1002 | blo LSYM(Lthumb1_div_negative8) | |
1003 | ||
6b9ce2b4 RE |
1004 | lsls divisor, divisor, #6 |
1005 | asrs result, result, #6 | |
82742404 HW |
1006 | cmp curbit, divisor |
1007 | blo LSYM(Lthumb1_div_negative8) | |
1008 | ||
6b9ce2b4 | 1009 | lsls divisor, divisor, #6 |
82742404 | 1010 | beq LSYM(Ldivbyzero_negative) |
6b9ce2b4 | 1011 | asrs result, result, #6 |
82742404 HW |
1012 | b LSYM(Lthumb1_div_negative8) |
1013 | LSYM(Lthumb1_div_negative_loop): | |
6b9ce2b4 | 1014 | lsrs divisor, divisor, #6 |
82742404 HW |
1015 | LSYM(Lthumb1_div_negative8): |
1016 | DoDiv #7 | |
1017 | DoDiv #6 | |
1018 | DoDiv #5 | |
1019 | DoDiv #4 | |
1020 | LSYM(Lthumb1_div_negative4): | |
1021 | DoDiv #3 | |
1022 | DoDiv #2 | |
1023 | bcs LSYM(Lthumb1_div_negative_loop) | |
1024 | DoDiv #1 | |
6b9ce2b4 | 1025 | subs divisor, dividend, divisor |
82742404 HW |
1026 | bcs 1f |
1027 | cpy divisor, dividend | |
1028 | ||
1029 | 1: cpy curbit, ip | |
6b9ce2b4 RE |
1030 | adcs result, result |
1031 | asrs curbit, curbit, #1 | |
82742404 HW |
1032 | cpy dividend, result |
1033 | bcc 2f | |
6b9ce2b4 | 1034 | negs dividend, dividend |
82742404 HW |
1035 | cmp curbit, #0 |
1036 | ||
1037 | 2: bpl 3f | |
6b9ce2b4 | 1038 | negs divisor, divisor |
82742404 HW |
1039 | |
1040 | 3: RET | |
1041 | ||
1042 | LSYM(Ldivbyzero_negative): | |
1043 | cpy curbit, ip | |
6b9ce2b4 | 1044 | asrs curbit, curbit, #1 |
82742404 | 1045 | bcc LSYM(Ldiv0) |
6b9ce2b4 | 1046 | negs dividend, dividend |
82742404 HW |
1047 | .endm |
1048 | #endif /* ARM Thumb version. */ | |
1049 | ||
888e552f NC |
1050 | /* ------------------------------------------------------------------------ */ |
1051 | /* Start of the Real Functions */ | |
1052 | /* ------------------------------------------------------------------------ */ | |
1053 | #ifdef L_udivsi3 | |
1054 | ||
8168ccc0 | 1055 | #if defined(__prefer_thumb__) |
f36d140e | 1056 | |
888e552f | 1057 | FUNC_START udivsi3 |
9bd05108 | 1058 | FUNC_ALIAS aeabi_uidiv udivsi3 |
82742404 | 1059 | #if defined(__OPTIMIZE_SIZE__) |
888e552f | 1060 | |
888e552f | 1061 | cmp divisor, #0 |
ce250a20 | 1062 | beq LSYM(Ldiv0) |
0c23e1be | 1063 | LSYM(udivsi3_skip_div0_test): |
6b9ce2b4 RE |
1064 | movs curbit, #1 |
1065 | movs result, #0 | |
888e552f NC |
1066 | |
1067 | push { work } | |
1068 | cmp dividend, divisor | |
ce250a20 | 1069 | blo LSYM(Lgot_result) |
888e552f NC |
1070 | |
1071 | THUMB_DIV_MOD_BODY 0 | |
1072 | ||
6b9ce2b4 | 1073 | movs r0, result |
d5b7b3ae | 1074 | pop { work } |
ef42b1dd | 1075 | RET |
888e552f | 1076 | |
82742404 HW |
1077 | /* Implementation of aeabi_uidiv for ARMv6m. This version is only |
1078 | used in ARMv6-M when we need an efficient implementation. */ | |
1079 | #else | |
1080 | LSYM(udivsi3_skip_div0_test): | |
1081 | THUMB1_Div_Positive | |
1082 | ||
1083 | #endif /* __OPTIMIZE_SIZE__ */ | |
1084 | ||
425d737b MGD |
1085 | #elif defined(__ARM_ARCH_EXT_IDIV__) |
1086 | ||
1087 | ARM_FUNC_START udivsi3 | |
1088 | ARM_FUNC_ALIAS aeabi_uidiv udivsi3 | |
1089 | ||
1090 | cmp r1, #0 | |
1091 | beq LSYM(Ldiv0) | |
1092 | ||
1093 | udiv r0, r0, r1 | |
1094 | RET | |
1095 | ||
f36d140e PB |
1096 | #else /* ARM version/Thumb-2. */ |
1097 | ||
1098 | ARM_FUNC_START udivsi3 | |
1099 | ARM_FUNC_ALIAS aeabi_uidiv udivsi3 | |
6a436e5e | 1100 | |
0c23e1be JB |
1101 | /* Note: if called via udivsi3_skip_div0_test, this will unnecessarily |
1102 | check for division-by-zero a second time. */ | |
1103 | LSYM(udivsi3_skip_div0_test): | |
6a436e5e | 1104 | subs r2, r1, #1 |
f36d140e | 1105 | do_it eq |
6a436e5e NP |
1106 | RETc(eq) |
1107 | bcc LSYM(Ldiv0) | |
1108 | cmp r0, r1 | |
1109 | bls 11f | |
1110 | tst r1, r2 | |
1111 | beq 12f | |
d5b7b3ae | 1112 | |
6a436e5e | 1113 | ARM_DIV_BODY r0, r1, r2, r3 |
888e552f | 1114 | |
6a436e5e | 1115 | mov r0, r2 |
888e552f | 1116 | RET |
bd28bf5a | 1117 | |
f36d140e PB |
1118 | 11: do_it eq, e |
1119 | moveq r0, #1 | |
6a436e5e NP |
1120 | movne r0, #0 |
1121 | RET | |
1122 | ||
1123 | 12: ARM_DIV2_ORDER r1, r2 | |
1124 | ||
1125 | mov r0, r0, lsr r2 | |
1126 | RET | |
1127 | ||
888e552f | 1128 | #endif /* ARM version */ |
bd28bf5a | 1129 | |
0c23e1be | 1130 | DIV_FUNC_END udivsi3 unsigned |
888e552f | 1131 | |
8168ccc0 | 1132 | #if defined(__prefer_thumb__) |
db151e9d | 1133 | FUNC_START aeabi_uidivmod |
0c23e1be JB |
1134 | cmp r1, #0 |
1135 | beq LSYM(Ldiv0) | |
82742404 | 1136 | # if defined(__OPTIMIZE_SIZE__) |
db151e9d | 1137 | push {r0, r1, lr} |
0c23e1be | 1138 | bl LSYM(udivsi3_skip_div0_test) |
db151e9d | 1139 | POP {r1, r2, r3} |
e519d644 RE |
1140 | muls r2, r0 |
1141 | subs r1, r1, r2 | |
db151e9d | 1142 | bx r3 |
82742404 HW |
1143 | # else |
1144 | /* Both the quotient and remainder are calculated simultaneously | |
1145 | in THUMB1_Div_Positive. There is no need to calculate the | |
1146 | remainder again here. */ | |
1147 | b LSYM(udivsi3_skip_div0_test) | |
1148 | RET | |
1149 | # endif /* __OPTIMIZE_SIZE__ */ | |
1150 | ||
425d737b MGD |
1151 | #elif defined(__ARM_ARCH_EXT_IDIV__) |
1152 | ARM_FUNC_START aeabi_uidivmod | |
1153 | cmp r1, #0 | |
1154 | beq LSYM(Ldiv0) | |
e519d644 | 1155 | mov r2, r0 |
425d737b MGD |
1156 | udiv r0, r0, r1 |
1157 | mls r1, r0, r1, r2 | |
1158 | RET | |
db151e9d | 1159 | #else |
f36d140e | 1160 | ARM_FUNC_START aeabi_uidivmod |
0c23e1be JB |
1161 | cmp r1, #0 |
1162 | beq LSYM(Ldiv0) | |
b3f8d95d | 1163 | stmfd sp!, { r0, r1, lr } |
0c23e1be | 1164 | bl LSYM(udivsi3_skip_div0_test) |
b3f8d95d MM |
1165 | ldmfd sp!, { r1, r2, lr } |
1166 | mul r3, r2, r0 | |
1167 | sub r1, r1, r3 | |
1168 | RET | |
db151e9d | 1169 | #endif |
b3f8d95d MM |
1170 | FUNC_END aeabi_uidivmod |
1171 | ||
888e552f NC |
1172 | #endif /* L_udivsi3 */ |
1173 | /* ------------------------------------------------------------------------ */ | |
1174 | #ifdef L_umodsi3 | |
1175 | ||
6f493951 | 1176 | #if defined(__ARM_ARCH_EXT_IDIV__) && __ARM_ARCH_ISA_THUMB != 1 |
888e552f | 1177 | |
425d737b MGD |
1178 | ARM_FUNC_START umodsi3 |
1179 | ||
1180 | cmp r1, #0 | |
1181 | beq LSYM(Ldiv0) | |
1182 | udiv r2, r0, r1 | |
1183 | mls r0, r1, r2, r0 | |
1184 | RET | |
1185 | ||
1186 | #elif defined(__thumb__) | |
1187 | ||
1188 | FUNC_START umodsi3 | |
888e552f NC |
1189 | |
1190 | cmp divisor, #0 | |
ce250a20 | 1191 | beq LSYM(Ldiv0) |
6b9ce2b4 | 1192 | movs curbit, #1 |
bd28bf5a | 1193 | cmp dividend, divisor |
ce250a20 | 1194 | bhs LSYM(Lover10) |
888e552f | 1195 | RET |
bd28bf5a | 1196 | |
ce250a20 | 1197 | LSYM(Lover10): |
888e552f NC |
1198 | push { work } |
1199 | ||
1200 | THUMB_DIV_MOD_BODY 1 | |
1201 | ||
1202 | pop { work } | |
1203 | RET | |
1204 | ||
1205 | #else /* ARM version. */ | |
82742404 | 1206 | |
425d737b MGD |
1207 | FUNC_START umodsi3 |
1208 | ||
6a436e5e NP |
1209 | subs r2, r1, #1 @ compare divisor with 1 |
1210 | bcc LSYM(Ldiv0) | |
1211 | cmpne r0, r1 @ compare dividend with divisor | |
1212 | moveq r0, #0 | |
1213 | tsthi r1, r2 @ see if divisor is power of 2 | |
1214 | andeq r0, r0, r2 | |
1215 | RETc(ls) | |
1216 | ||
1217 | ARM_MOD_BODY r0, r1, r2, r3 | |
888e552f | 1218 | |
d5b7b3ae | 1219 | RET |
454e0249 | 1220 | |
7405dc37 | 1221 | #endif /* ARM version. */ |
d5b7b3ae | 1222 | |
0c23e1be | 1223 | DIV_FUNC_END umodsi3 unsigned |
b355a481 | 1224 | |
bd28bf5a | 1225 | #endif /* L_umodsi3 */ |
6dcd26ea | 1226 | /* ------------------------------------------------------------------------ */ |
bd28bf5a | 1227 | #ifdef L_divsi3 |
454e0249 | 1228 | |
8168ccc0 | 1229 | #if defined(__prefer_thumb__) |
f36d140e | 1230 | |
82742404 | 1231 | FUNC_START divsi3 |
9bd05108 | 1232 | FUNC_ALIAS aeabi_idiv divsi3 |
82742404 | 1233 | #if defined(__OPTIMIZE_SIZE__) |
d5b7b3ae | 1234 | |
d5b7b3ae | 1235 | cmp divisor, #0 |
ce250a20 | 1236 | beq LSYM(Ldiv0) |
0c23e1be | 1237 | LSYM(divsi3_skip_div0_test): |
d5b7b3ae | 1238 | push { work } |
e519d644 RE |
1239 | movs work, dividend |
1240 | eors work, divisor @ Save the sign of the result. | |
d5b7b3ae | 1241 | mov ip, work |
e519d644 RE |
1242 | movs curbit, #1 |
1243 | movs result, #0 | |
d5b7b3ae | 1244 | cmp divisor, #0 |
ce250a20 | 1245 | bpl LSYM(Lover10) |
e519d644 | 1246 | negs divisor, divisor @ Loops below use unsigned. |
ce250a20 | 1247 | LSYM(Lover10): |
d5b7b3ae | 1248 | cmp dividend, #0 |
ce250a20 | 1249 | bpl LSYM(Lover11) |
e519d644 | 1250 | negs dividend, dividend |
ce250a20 | 1251 | LSYM(Lover11): |
d5b7b3ae | 1252 | cmp dividend, divisor |
ce250a20 | 1253 | blo LSYM(Lgot_result) |
d5b7b3ae | 1254 | |
888e552f | 1255 | THUMB_DIV_MOD_BODY 0 |
82742404 | 1256 | |
e519d644 | 1257 | movs r0, result |
d5b7b3ae RE |
1258 | mov work, ip |
1259 | cmp work, #0 | |
ce250a20 | 1260 | bpl LSYM(Lover12) |
e519d644 | 1261 | negs r0, r0 |
ce250a20 | 1262 | LSYM(Lover12): |
d5b7b3ae | 1263 | pop { work } |
888e552f | 1264 | RET |
454e0249 | 1265 | |
82742404 HW |
1266 | /* Implementation of aeabi_idiv for ARMv6m. This version is only |
1267 | used in ARMv6-M when we need an efficient implementation. */ | |
1268 | #else | |
1269 | LSYM(divsi3_skip_div0_test): | |
1270 | cpy curbit, dividend | |
6b9ce2b4 | 1271 | orrs curbit, divisor |
82742404 HW |
1272 | bmi LSYM(Lthumb1_div_negative) |
1273 | ||
1274 | LSYM(Lthumb1_div_positive): | |
1275 | THUMB1_Div_Positive | |
1276 | ||
1277 | LSYM(Lthumb1_div_negative): | |
1278 | THUMB1_Div_Negative | |
1279 | ||
1280 | #endif /* __OPTIMIZE_SIZE__ */ | |
1281 | ||
425d737b MGD |
1282 | #elif defined(__ARM_ARCH_EXT_IDIV__) |
1283 | ||
1284 | ARM_FUNC_START divsi3 | |
1285 | ARM_FUNC_ALIAS aeabi_idiv divsi3 | |
1286 | ||
1287 | cmp r1, #0 | |
1288 | beq LSYM(Ldiv0) | |
1289 | sdiv r0, r0, r1 | |
1290 | RET | |
1291 | ||
f36d140e | 1292 | #else /* ARM/Thumb-2 version. */ |
82742404 HW |
1293 | |
1294 | ARM_FUNC_START divsi3 | |
f36d140e PB |
1295 | ARM_FUNC_ALIAS aeabi_idiv divsi3 |
1296 | ||
6a436e5e | 1297 | cmp r1, #0 |
ce250a20 | 1298 | beq LSYM(Ldiv0) |
0c23e1be JB |
1299 | LSYM(divsi3_skip_div0_test): |
1300 | eor ip, r0, r1 @ save the sign of the result. | |
f36d140e | 1301 | do_it mi |
6a436e5e NP |
1302 | rsbmi r1, r1, #0 @ loops below use unsigned. |
1303 | subs r2, r1, #1 @ division by 1 or -1 ? | |
1304 | beq 10f | |
1305 | movs r3, r0 | |
f36d140e | 1306 | do_it mi |
6a436e5e NP |
1307 | rsbmi r3, r0, #0 @ positive dividend value |
1308 | cmp r3, r1 | |
1309 | bls 11f | |
1310 | tst r1, r2 @ divisor is power of 2 ? | |
1311 | beq 12f | |
1312 | ||
1313 | ARM_DIV_BODY r3, r1, r0, r2 | |
888e552f | 1314 | |
bd28bf5a | 1315 | cmp ip, #0 |
f36d140e | 1316 | do_it mi |
02689e18 | 1317 | rsbmi r0, r0, #0 |
d5b7b3ae | 1318 | RET |
454e0249 | 1319 | |
6a436e5e | 1320 | 10: teq ip, r0 @ same sign ? |
f36d140e | 1321 | do_it mi |
6a436e5e NP |
1322 | rsbmi r0, r0, #0 |
1323 | RET | |
1324 | ||
f36d140e PB |
1325 | 11: do_it lo |
1326 | movlo r0, #0 | |
1327 | do_it eq,t | |
6a436e5e NP |
1328 | moveq r0, ip, asr #31 |
1329 | orreq r0, r0, #1 | |
1330 | RET | |
1331 | ||
1332 | 12: ARM_DIV2_ORDER r1, r2 | |
1333 | ||
1334 | cmp ip, #0 | |
1335 | mov r0, r3, lsr r2 | |
f36d140e | 1336 | do_it mi |
6a436e5e NP |
1337 | rsbmi r0, r0, #0 |
1338 | RET | |
1339 | ||
6dcd26ea | 1340 | #endif /* ARM version */ |
d5b7b3ae | 1341 | |
0c23e1be | 1342 | DIV_FUNC_END divsi3 signed |
b355a481 | 1343 | |
8168ccc0 | 1344 | #if defined(__prefer_thumb__) |
db151e9d | 1345 | FUNC_START aeabi_idivmod |
0c23e1be JB |
1346 | cmp r1, #0 |
1347 | beq LSYM(Ldiv0) | |
82742404 | 1348 | # if defined(__OPTIMIZE_SIZE__) |
db151e9d | 1349 | push {r0, r1, lr} |
0c23e1be | 1350 | bl LSYM(divsi3_skip_div0_test) |
db151e9d | 1351 | POP {r1, r2, r3} |
e519d644 RE |
1352 | muls r2, r0 |
1353 | subs r1, r1, r2 | |
db151e9d | 1354 | bx r3 |
82742404 HW |
1355 | # else |
1356 | /* Both the quotient and remainder are calculated simultaneously | |
1357 | in THUMB1_Div_Positive and THUMB1_Div_Negative. There is no | |
1358 | need to calculate the remainder again here. */ | |
1359 | b LSYM(divsi3_skip_div0_test) | |
1360 | RET | |
1361 | # endif /* __OPTIMIZE_SIZE__ */ | |
1362 | ||
425d737b MGD |
1363 | #elif defined(__ARM_ARCH_EXT_IDIV__) |
1364 | ARM_FUNC_START aeabi_idivmod | |
1365 | cmp r1, #0 | |
1366 | beq LSYM(Ldiv0) | |
1367 | mov r2, r0 | |
1368 | sdiv r0, r0, r1 | |
1369 | mls r1, r0, r1, r2 | |
1370 | RET | |
db151e9d | 1371 | #else |
f36d140e | 1372 | ARM_FUNC_START aeabi_idivmod |
0c23e1be JB |
1373 | cmp r1, #0 |
1374 | beq LSYM(Ldiv0) | |
b3f8d95d | 1375 | stmfd sp!, { r0, r1, lr } |
0c23e1be | 1376 | bl LSYM(divsi3_skip_div0_test) |
b3f8d95d MM |
1377 | ldmfd sp!, { r1, r2, lr } |
1378 | mul r3, r2, r0 | |
1379 | sub r1, r1, r3 | |
1380 | RET | |
db151e9d | 1381 | #endif |
b3f8d95d MM |
1382 | FUNC_END aeabi_idivmod |
1383 | ||
bd28bf5a | 1384 | #endif /* L_divsi3 */ |
6dcd26ea | 1385 | /* ------------------------------------------------------------------------ */ |
454e0249 DE |
1386 | #ifdef L_modsi3 |
1387 | ||
6f493951 | 1388 | #if defined(__ARM_ARCH_EXT_IDIV__) && __ARM_ARCH_ISA_THUMB != 1 |
d5b7b3ae | 1389 | |
425d737b MGD |
1390 | ARM_FUNC_START modsi3 |
1391 | ||
1392 | cmp r1, #0 | |
1393 | beq LSYM(Ldiv0) | |
1394 | ||
1395 | sdiv r2, r0, r1 | |
1396 | mls r0, r1, r2, r0 | |
1397 | RET | |
1398 | ||
1399 | #elif defined(__thumb__) | |
1400 | ||
1401 | FUNC_START modsi3 | |
454e0249 | 1402 | |
6b9ce2b4 | 1403 | movs curbit, #1 |
d5b7b3ae | 1404 | cmp divisor, #0 |
ce250a20 RE |
1405 | beq LSYM(Ldiv0) |
1406 | bpl LSYM(Lover10) | |
6b9ce2b4 | 1407 | negs divisor, divisor @ Loops below use unsigned. |
ce250a20 | 1408 | LSYM(Lover10): |
d5b7b3ae RE |
1409 | push { work } |
1410 | @ Need to save the sign of the dividend, unfortunately, we need | |
888e552f | 1411 | @ work later on. Must do this after saving the original value of |
d5b7b3ae RE |
1412 | @ the work register, because we will pop this value off first. |
1413 | push { dividend } | |
1414 | cmp dividend, #0 | |
ce250a20 | 1415 | bpl LSYM(Lover11) |
6b9ce2b4 | 1416 | negs dividend, dividend |
ce250a20 | 1417 | LSYM(Lover11): |
d5b7b3ae | 1418 | cmp dividend, divisor |
ce250a20 | 1419 | blo LSYM(Lgot_result) |
d5b7b3ae | 1420 | |
888e552f NC |
1421 | THUMB_DIV_MOD_BODY 1 |
1422 | ||
d5b7b3ae RE |
1423 | pop { work } |
1424 | cmp work, #0 | |
ce250a20 | 1425 | bpl LSYM(Lover12) |
6b9ce2b4 | 1426 | negs dividend, dividend |
ce250a20 | 1427 | LSYM(Lover12): |
d5b7b3ae RE |
1428 | pop { work } |
1429 | RET | |
7405dc37 | 1430 | |
6dcd26ea | 1431 | #else /* ARM version. */ |
d5b7b3ae | 1432 | |
425d737b MGD |
1433 | FUNC_START modsi3 |
1434 | ||
6a436e5e | 1435 | cmp r1, #0 |
ce250a20 | 1436 | beq LSYM(Ldiv0) |
6a436e5e NP |
1437 | rsbmi r1, r1, #0 @ loops below use unsigned. |
1438 | movs ip, r0 @ preserve sign of dividend | |
1439 | rsbmi r0, r0, #0 @ if negative make positive | |
1440 | subs r2, r1, #1 @ compare divisor with 1 | |
1441 | cmpne r0, r1 @ compare dividend with divisor | |
1442 | moveq r0, #0 | |
1443 | tsthi r1, r2 @ see if divisor is power of 2 | |
1444 | andeq r0, r0, r2 | |
1445 | bls 10f | |
1446 | ||
1447 | ARM_MOD_BODY r0, r1, r2, r3 | |
1448 | ||
1449 | 10: cmp ip, #0 | |
1450 | rsbmi r0, r0, #0 | |
d5b7b3ae | 1451 | RET |
7405dc37 | 1452 | |
6dcd26ea RE |
1453 | #endif /* ARM version */ |
1454 | ||
0c23e1be | 1455 | DIV_FUNC_END modsi3 signed |
b355a481 | 1456 | |
454e0249 | 1457 | #endif /* L_modsi3 */ |
6dcd26ea | 1458 | /* ------------------------------------------------------------------------ */ |
2ecc7cad | 1459 | #ifdef L_dvmd_tls |
454e0249 | 1460 | |
0c23e1be JB |
1461 | #ifdef __ARM_EABI__ |
1462 | WEAK aeabi_idiv0 | |
1463 | WEAK aeabi_ldiv0 | |
1464 | FUNC_START aeabi_idiv0 | |
1465 | FUNC_START aeabi_ldiv0 | |
7405dc37 | 1466 | RET |
b3f8d95d MM |
1467 | FUNC_END aeabi_ldiv0 |
1468 | FUNC_END aeabi_idiv0 | |
0c23e1be JB |
1469 | #else |
1470 | FUNC_START div0 | |
1471 | RET | |
496b84c8 | 1472 | FUNC_END div0 |
0c23e1be | 1473 | #endif |
b355a481 | 1474 | |
454e0249 | 1475 | #endif /* L_divmodsi_tools */ |
6dcd26ea | 1476 | /* ------------------------------------------------------------------------ */ |
75d3a15b NC |
1477 | #ifdef L_dvmd_lnx |
1478 | @ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls | |
1479 | ||
5d7c0add | 1480 | /* Constant taken from <asm/signal.h>. */ |
d71ebc32 | 1481 | #define SIGFPE 8 |
d71ebc32 | 1482 | |
0c23e1be | 1483 | #ifdef __ARM_EABI__ |
4fa0f9ea | 1484 | cfi_start __aeabi_ldiv0, LSYM(Lend_aeabi_ldiv0) |
0c23e1be JB |
1485 | WEAK aeabi_idiv0 |
1486 | WEAK aeabi_ldiv0 | |
1487 | ARM_FUNC_START aeabi_idiv0 | |
1488 | ARM_FUNC_START aeabi_ldiv0 | |
4fa0f9ea JL |
1489 | do_push {r1, lr} |
1490 | 98: cfi_push 98b - __aeabi_ldiv0, 0xe, -0x4, 0x8 | |
0c23e1be | 1491 | #else |
4fa0f9ea | 1492 | cfi_start __div0, LSYM(Lend_div0) |
3303be15 | 1493 | ARM_FUNC_START div0 |
4fa0f9ea JL |
1494 | do_push {r1, lr} |
1495 | 98: cfi_push 98b - __div0, 0xe, -0x4, 0x8 | |
0c23e1be | 1496 | #endif |
d5b7b3ae | 1497 | |
5d7c0add DJ |
1498 | mov r0, #SIGFPE |
1499 | bl SYM(raise) __PLT__ | |
4fa0f9ea | 1500 | RETLDM r1 unwind=98b |
7405dc37 | 1501 | |
0c23e1be | 1502 | #ifdef __ARM_EABI__ |
4fa0f9ea | 1503 | cfi_end LSYM(Lend_aeabi_ldiv0) |
0c23e1be JB |
1504 | FUNC_END aeabi_ldiv0 |
1505 | FUNC_END aeabi_idiv0 | |
1506 | #else | |
4fa0f9ea | 1507 | cfi_end LSYM(Lend_div0) |
496b84c8 | 1508 | FUNC_END div0 |
0c23e1be | 1509 | #endif |
b355a481 | 1510 | |
75d3a15b | 1511 | #endif /* L_dvmd_lnx */ |
8a66e987 JM |
1512 | #ifdef L_clear_cache |
1513 | #if defined __ARM_EABI__ && defined __linux__ | |
1514 | @ EABI GNU/Linux call to cacheflush syscall. | |
0244b03f PB |
1515 | ARM_FUNC_START clear_cache |
1516 | do_push {r7} | |
9b2e34ef | 1517 | #if __ARM_ARCH >= 7 || defined(__ARM_ARCH_6T2__) |
8a66e987 JM |
1518 | movw r7, #2 |
1519 | movt r7, #0xf | |
1520 | #else | |
1521 | mov r7, #0xf0000 | |
1522 | add r7, r7, #2 | |
1523 | #endif | |
1524 | mov r2, #0 | |
57d104ab | 1525 | svc 0 |
0244b03f | 1526 | do_pop {r7} |
8a66e987 JM |
1527 | RET |
1528 | FUNC_END clear_cache | |
1529 | #else | |
1530 | #error "This is only for ARM EABI GNU/Linux" | |
1531 | #endif | |
1532 | #endif /* L_clear_cache */ | |
ebdb6f23 RE |
1533 | |
1534 | #ifdef L_speculation_barrier | |
1535 | FUNC_START speculation_barrier | |
1536 | #if __ARM_ARCH >= 7 | |
1537 | isb | |
1538 | dsb sy | |
1539 | #elif defined __ARM_EABI__ && defined __linux__ | |
1540 | /* We don't have a speculation barrier directly for this | |
1541 | platform/architecture variant. But we can use a kernel | |
1542 | clear_cache service routine which will emit such instructions | |
1543 | if run on a later version of the architecture. We don't | |
1544 | really want to flush the cache, but we must give it a valid | |
1545 | address, so just clear pc..pc+1. */ | |
1546 | #if defined __thumb__ && !defined __thumb2__ | |
1547 | push {r7} | |
6b9ce2b4 RE |
1548 | movs r7, #0xf |
1549 | lsls r7, #16 | |
1550 | adds r7, #2 | |
ebdb6f23 | 1551 | adr r0, . + 4 |
6b9ce2b4 RE |
1552 | adds r1, r0, #1 |
1553 | movs r2, #0 | |
ebdb6f23 RE |
1554 | svc 0 |
1555 | pop {r7} | |
1556 | #else | |
1557 | do_push {r7} | |
1558 | #ifdef __ARM_ARCH_6T2__ | |
1559 | movw r7, #2 | |
1560 | movt r7, #0xf | |
1561 | #else | |
1562 | mov r7, #0xf0000 | |
1563 | add r7, r7, #2 | |
1564 | #endif | |
1565 | add r0, pc, #0 /* ADR. */ | |
1566 | add r1, r0, #1 | |
1567 | mov r2, #0 | |
1568 | svc 0 | |
1569 | do_pop {r7} | |
1570 | #endif /* Thumb1 only */ | |
1571 | #else | |
1572 | #warning "No speculation barrier defined for this platform" | |
1573 | #endif | |
1574 | RET | |
1575 | FUNC_END speculation_barrier | |
1576 | #endif | |
6dcd26ea | 1577 | /* ------------------------------------------------------------------------ */ |
dc491742 RE |
1578 | /* Dword shift operations. */ |
1579 | /* All the following Dword shift variants rely on the fact that | |
1580 | shft xxx, Reg | |
1581 | is in fact done as | |
1582 | shft xxx, (Reg & 255) | |
1583 | so for Reg value in (32...63) and (-1...-31) we will get zero (in the | |
1584 | case of logical shifts) or the sign (for asr). */ | |
1585 | ||
1586 | #ifdef __ARMEB__ | |
1587 | #define al r1 | |
1588 | #define ah r0 | |
1589 | #else | |
1590 | #define al r0 | |
1591 | #define ah r1 | |
1592 | #endif | |
1593 | ||
c0354bf4 PB |
1594 | /* Prevent __aeabi double-word shifts from being produced on SymbianOS. */ |
1595 | #ifndef __symbian__ | |
1596 | ||
dc491742 RE |
1597 | #ifdef L_lshrdi3 |
1598 | ||
1599 | FUNC_START lshrdi3 | |
2155b886 | 1600 | FUNC_ALIAS aeabi_llsr lshrdi3 |
b3f8d95d | 1601 | |
dc491742 | 1602 | #ifdef __thumb__ |
6b9ce2b4 RE |
1603 | lsrs al, r2 |
1604 | movs r3, ah | |
1605 | lsrs ah, r2 | |
dc491742 | 1606 | mov ip, r3 |
6b9ce2b4 RE |
1607 | subs r2, #32 |
1608 | lsrs r3, r2 | |
1609 | orrs al, r3 | |
1610 | negs r2, r2 | |
dc491742 | 1611 | mov r3, ip |
6b9ce2b4 RE |
1612 | lsls r3, r2 |
1613 | orrs al, r3 | |
dc491742 RE |
1614 | RET |
1615 | #else | |
1616 | subs r3, r2, #32 | |
1617 | rsb ip, r2, #32 | |
1618 | movmi al, al, lsr r2 | |
1619 | movpl al, ah, lsr r3 | |
1620 | orrmi al, al, ah, lsl ip | |
1621 | mov ah, ah, lsr r2 | |
1622 | RET | |
1623 | #endif | |
b3f8d95d | 1624 | FUNC_END aeabi_llsr |
dc491742 RE |
1625 | FUNC_END lshrdi3 |
1626 | ||
1627 | #endif | |
1628 | ||
1629 | #ifdef L_ashrdi3 | |
1630 | ||
1631 | FUNC_START ashrdi3 | |
2155b886 | 1632 | FUNC_ALIAS aeabi_lasr ashrdi3 |
b3f8d95d | 1633 | |
dc491742 | 1634 | #ifdef __thumb__ |
6b9ce2b4 RE |
1635 | lsrs al, r2 |
1636 | movs r3, ah | |
1637 | asrs ah, r2 | |
1638 | subs r2, #32 | |
dc491742 RE |
1639 | @ If r2 is negative at this point the following step would OR |
1640 | @ the sign bit into all of AL. That's not what we want... | |
1641 | bmi 1f | |
1642 | mov ip, r3 | |
6b9ce2b4 RE |
1643 | asrs r3, r2 |
1644 | orrs al, r3 | |
dc491742 RE |
1645 | mov r3, ip |
1646 | 1: | |
6b9ce2b4 RE |
1647 | negs r2, r2 |
1648 | lsls r3, r2 | |
1649 | orrs al, r3 | |
dc491742 RE |
1650 | RET |
1651 | #else | |
1652 | subs r3, r2, #32 | |
1653 | rsb ip, r2, #32 | |
1654 | movmi al, al, lsr r2 | |
1655 | movpl al, ah, asr r3 | |
1656 | orrmi al, al, ah, lsl ip | |
1657 | mov ah, ah, asr r2 | |
1658 | RET | |
1659 | #endif | |
1660 | ||
b3f8d95d | 1661 | FUNC_END aeabi_lasr |
dc491742 RE |
1662 | FUNC_END ashrdi3 |
1663 | ||
1664 | #endif | |
1665 | ||
1666 | #ifdef L_ashldi3 | |
1667 | ||
1668 | FUNC_START ashldi3 | |
2155b886 | 1669 | FUNC_ALIAS aeabi_llsl ashldi3 |
b3f8d95d | 1670 | |
dc491742 | 1671 | #ifdef __thumb__ |
6b9ce2b4 RE |
1672 | lsls ah, r2 |
1673 | movs r3, al | |
1674 | lsls al, r2 | |
dc491742 | 1675 | mov ip, r3 |
6b9ce2b4 RE |
1676 | subs r2, #32 |
1677 | lsls r3, r2 | |
1678 | orrs ah, r3 | |
1679 | negs r2, r2 | |
dc491742 | 1680 | mov r3, ip |
6b9ce2b4 RE |
1681 | lsrs r3, r2 |
1682 | orrs ah, r3 | |
dc491742 RE |
1683 | RET |
1684 | #else | |
1685 | subs r3, r2, #32 | |
1686 | rsb ip, r2, #32 | |
1687 | movmi ah, ah, lsl r2 | |
1688 | movpl ah, al, lsl r3 | |
1689 | orrmi ah, ah, al, lsr ip | |
1690 | mov al, al, lsl r2 | |
1691 | RET | |
1692 | #endif | |
b3f8d95d | 1693 | FUNC_END aeabi_llsl |
dc491742 RE |
1694 | FUNC_END ashldi3 |
1695 | ||
1696 | #endif | |
1697 | ||
c0354bf4 PB |
1698 | #endif /* __symbian__ */ |
1699 | ||
ef0a4b67 | 1700 | #ifdef L_clzsi2 |
6f493951 | 1701 | #ifdef NOT_ISA_TARGET_32BIT |
ef0a4b67 | 1702 | FUNC_START clzsi2 |
6b9ce2b4 RE |
1703 | movs r1, #28 |
1704 | movs r3, #1 | |
1705 | lsls r3, r3, #16 | |
ef0a4b67 PB |
1706 | cmp r0, r3 /* 0x10000 */ |
1707 | bcc 2f | |
6b9ce2b4 RE |
1708 | lsrs r0, r0, #16 |
1709 | subs r1, r1, #16 | |
1710 | 2: lsrs r3, r3, #8 | |
ef0a4b67 PB |
1711 | cmp r0, r3 /* #0x100 */ |
1712 | bcc 2f | |
6b9ce2b4 RE |
1713 | lsrs r0, r0, #8 |
1714 | subs r1, r1, #8 | |
1715 | 2: lsrs r3, r3, #4 | |
ef0a4b67 PB |
1716 | cmp r0, r3 /* #0x10 */ |
1717 | bcc 2f | |
6b9ce2b4 RE |
1718 | lsrs r0, r0, #4 |
1719 | subs r1, r1, #4 | |
ef0a4b67 PB |
1720 | 2: adr r2, 1f |
1721 | ldrb r0, [r2, r0] | |
6b9ce2b4 | 1722 | adds r0, r0, r1 |
ef0a4b67 PB |
1723 | bx lr |
1724 | .align 2 | |
1725 | 1: | |
1726 | .byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 | |
1727 | FUNC_END clzsi2 | |
1728 | #else | |
1729 | ARM_FUNC_START clzsi2 | |
9b2e34ef | 1730 | # if defined (__ARM_FEATURE_CLZ) |
ef0a4b67 PB |
1731 | clz r0, r0 |
1732 | RET | |
1733 | # else | |
1734 | mov r1, #28 | |
1735 | cmp r0, #0x10000 | |
1736 | do_it cs, t | |
1737 | movcs r0, r0, lsr #16 | |
1738 | subcs r1, r1, #16 | |
1739 | cmp r0, #0x100 | |
1740 | do_it cs, t | |
1741 | movcs r0, r0, lsr #8 | |
1742 | subcs r1, r1, #8 | |
1743 | cmp r0, #0x10 | |
1744 | do_it cs, t | |
1745 | movcs r0, r0, lsr #4 | |
1746 | subcs r1, r1, #4 | |
1747 | adr r2, 1f | |
1748 | ldrb r0, [r2, r0] | |
1749 | add r0, r0, r1 | |
007403f3 | 1750 | RET |
ef0a4b67 PB |
1751 | .align 2 |
1752 | 1: | |
1753 | .byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 | |
9b2e34ef | 1754 | # endif /* !defined (__ARM_FEATURE_CLZ) */ |
ef0a4b67 PB |
1755 | FUNC_END clzsi2 |
1756 | #endif | |
1757 | #endif /* L_clzsi2 */ | |
1758 | ||
1759 | #ifdef L_clzdi2 | |
9b2e34ef | 1760 | #if !defined (__ARM_FEATURE_CLZ) |
ef0a4b67 | 1761 | |
6f493951 | 1762 | # ifdef NOT_ISA_TARGET_32BIT |
ef0a4b67 PB |
1763 | FUNC_START clzdi2 |
1764 | push {r4, lr} | |
6b9ce2b4 RE |
1765 | cmp xxh, #0 |
1766 | bne 1f | |
1767 | # ifdef __ARMEB__ | |
1768 | movs r0, xxl | |
1769 | bl __clzsi2 | |
1770 | adds r0, r0, #32 | |
1771 | b 2f | |
1772 | 1: | |
1773 | bl __clzsi2 | |
1774 | # else | |
1775 | bl __clzsi2 | |
1776 | adds r0, r0, #32 | |
1777 | b 2f | |
1778 | 1: | |
1779 | movs r0, xxh | |
1780 | bl __clzsi2 | |
1781 | # endif | |
1782 | 2: | |
1783 | pop {r4, pc} | |
1784 | # else /* NOT_ISA_TARGET_32BIT */ | |
ef0a4b67 PB |
1785 | ARM_FUNC_START clzdi2 |
1786 | do_push {r4, lr} | |
ef0a4b67 PB |
1787 | cmp xxh, #0 |
1788 | bne 1f | |
6b9ce2b4 | 1789 | # ifdef __ARMEB__ |
ef0a4b67 PB |
1790 | mov r0, xxl |
1791 | bl __clzsi2 | |
1792 | add r0, r0, #32 | |
1793 | b 2f | |
1794 | 1: | |
1795 | bl __clzsi2 | |
6b9ce2b4 | 1796 | # else |
ef0a4b67 PB |
1797 | bl __clzsi2 |
1798 | add r0, r0, #32 | |
1799 | b 2f | |
1800 | 1: | |
1801 | mov r0, xxh | |
1802 | bl __clzsi2 | |
6b9ce2b4 | 1803 | # endif |
ef0a4b67 | 1804 | 2: |
ef0a4b67 | 1805 | RETLDM r4 |
ef0a4b67 | 1806 | FUNC_END clzdi2 |
6b9ce2b4 | 1807 | # endif /* NOT_ISA_TARGET_32BIT */ |
ef0a4b67 | 1808 | |
9b2e34ef | 1809 | #else /* defined (__ARM_FEATURE_CLZ) */ |
ef0a4b67 PB |
1810 | |
1811 | ARM_FUNC_START clzdi2 | |
1812 | cmp xxh, #0 | |
1813 | do_it eq, et | |
1814 | clzeq r0, xxl | |
1815 | clzne r0, xxh | |
1816 | addeq r0, r0, #32 | |
1817 | RET | |
1818 | FUNC_END clzdi2 | |
1819 | ||
1820 | #endif | |
1821 | #endif /* L_clzdi2 */ | |
1822 | ||
06ea7371 | 1823 | #ifdef L_ctzsi2 |
6f493951 | 1824 | #ifdef NOT_ISA_TARGET_32BIT |
06ea7371 | 1825 | FUNC_START ctzsi2 |
6b9ce2b4 RE |
1826 | negs r1, r0 |
1827 | ands r0, r0, r1 | |
1828 | movs r1, #28 | |
1829 | movs r3, #1 | |
1830 | lsls r3, r3, #16 | |
06ea7371 RE |
1831 | cmp r0, r3 /* 0x10000 */ |
1832 | bcc 2f | |
6b9ce2b4 RE |
1833 | lsrs r0, r0, #16 |
1834 | subs r1, r1, #16 | |
1835 | 2: lsrs r3, r3, #8 | |
06ea7371 RE |
1836 | cmp r0, r3 /* #0x100 */ |
1837 | bcc 2f | |
6b9ce2b4 RE |
1838 | lsrs r0, r0, #8 |
1839 | subs r1, r1, #8 | |
1840 | 2: lsrs r3, r3, #4 | |
06ea7371 RE |
1841 | cmp r0, r3 /* #0x10 */ |
1842 | bcc 2f | |
6b9ce2b4 RE |
1843 | lsrs r0, r0, #4 |
1844 | subs r1, r1, #4 | |
06ea7371 RE |
1845 | 2: adr r2, 1f |
1846 | ldrb r0, [r2, r0] | |
6b9ce2b4 | 1847 | subs r0, r0, r1 |
06ea7371 RE |
1848 | bx lr |
1849 | .align 2 | |
1850 | 1: | |
1851 | .byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31 | |
1852 | FUNC_END ctzsi2 | |
1853 | #else | |
1854 | ARM_FUNC_START ctzsi2 | |
1855 | rsb r1, r0, #0 | |
1856 | and r0, r0, r1 | |
9b2e34ef | 1857 | # if defined (__ARM_FEATURE_CLZ) |
06ea7371 RE |
1858 | clz r0, r0 |
1859 | rsb r0, r0, #31 | |
1860 | RET | |
1861 | # else | |
1862 | mov r1, #28 | |
1863 | cmp r0, #0x10000 | |
1864 | do_it cs, t | |
1865 | movcs r0, r0, lsr #16 | |
1866 | subcs r1, r1, #16 | |
1867 | cmp r0, #0x100 | |
1868 | do_it cs, t | |
1869 | movcs r0, r0, lsr #8 | |
1870 | subcs r1, r1, #8 | |
1871 | cmp r0, #0x10 | |
1872 | do_it cs, t | |
1873 | movcs r0, r0, lsr #4 | |
1874 | subcs r1, r1, #4 | |
1875 | adr r2, 1f | |
1876 | ldrb r0, [r2, r0] | |
1877 | sub r0, r0, r1 | |
1878 | RET | |
1879 | .align 2 | |
1880 | 1: | |
1881 | .byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31 | |
9b2e34ef | 1882 | # endif /* !defined (__ARM_FEATURE_CLZ) */ |
06ea7371 RE |
1883 | FUNC_END ctzsi2 |
1884 | #endif | |
1885 | #endif /* L_clzsi2 */ | |
1886 | ||
dc491742 | 1887 | /* ------------------------------------------------------------------------ */ |
75d3a15b NC |
1888 | /* These next two sections are here despite the fact that they contain Thumb |
1889 | assembler because their presence allows interworked code to be linked even | |
1890 | when the GCC library is this one. */ | |
1891 | ||
c84df4c5 NC |
1892 | /* Do not build the interworking functions when the target architecture does |
1893 | not support Thumb instructions. (This can be a multilib option). */ | |
e0d4a859 PB |
1894 | #if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\ |
1895 | || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \ | |
9b2e34ef | 1896 | || __ARM_ARCH >= 6 |
e0d4a859 PB |
1897 | |
1898 | #if defined L_call_via_rX | |
75d3a15b NC |
1899 | |
1900 | /* These labels & instructions are used by the Arm/Thumb interworking code. | |
1901 | The address of function to be called is loaded into a register and then | |
1902 | one of these labels is called via a BL instruction. This puts the | |
1903 | return address into the link register with the bottom bit set, and the | |
1904 | code here switches to the correct mode before executing the function. */ | |
1905 | ||
1906 | .text | |
1907 | .align 0 | |
ec8aac6f | 1908 | .force_thumb |
7405dc37 | 1909 | |
75d3a15b | 1910 | .macro call_via register |
6dcd26ea RE |
1911 | THUMB_FUNC_START _call_via_\register |
1912 | ||
75d3a15b NC |
1913 | bx \register |
1914 | nop | |
2a5307b1 NC |
1915 | |
1916 | SIZE (_call_via_\register) | |
75d3a15b NC |
1917 | .endm |
1918 | ||
1919 | call_via r0 | |
1920 | call_via r1 | |
1921 | call_via r2 | |
1922 | call_via r3 | |
1923 | call_via r4 | |
1924 | call_via r5 | |
1925 | call_via r6 | |
1926 | call_via r7 | |
1927 | call_via r8 | |
1928 | call_via r9 | |
1929 | call_via sl | |
1930 | call_via fp | |
1931 | call_via ip | |
1932 | call_via sp | |
1933 | call_via lr | |
1934 | ||
1935 | #endif /* L_call_via_rX */ | |
e0d4a859 | 1936 | |
5b3e6663 | 1937 | /* Don't bother with the old interworking routines for Thumb-2. */ |
bf98ec6c | 1938 | /* ??? Maybe only omit these on "m" variants. */ |
6f493951 | 1939 | #if !defined(__thumb2__) && __ARM_ARCH_ISA_ARM |
5b3e6663 | 1940 | |
e0d4a859 | 1941 | #if defined L_interwork_call_via_rX |
7405dc37 | 1942 | |
75d3a15b NC |
1943 | /* These labels & instructions are used by the Arm/Thumb interworking code, |
1944 | when the target address is in an unknown instruction set. The address | |
1945 | of function to be called is loaded into a register and then one of these | |
1946 | labels is called via a BL instruction. This puts the return address | |
1947 | into the link register with the bottom bit set, and the code here | |
1948 | switches to the correct mode before executing the function. Unfortunately | |
1949 | the target code cannot be relied upon to return via a BX instruction, so | |
1950 | instead we have to store the resturn address on the stack and allow the | |
1951 | called function to return here instead. Upon return we recover the real | |
a2503645 RS |
1952 | return address and use a BX to get back to Thumb mode. |
1953 | ||
1954 | There are three variations of this code. The first, | |
1955 | _interwork_call_via_rN(), will push the return address onto the | |
1956 | stack and pop it in _arm_return(). It should only be used if all | |
1957 | arguments are passed in registers. | |
1958 | ||
1959 | The second, _interwork_r7_call_via_rN(), instead stores the return | |
1960 | address at [r7, #-4]. It is the caller's responsibility to ensure | |
1961 | that this address is valid and contains no useful data. | |
1962 | ||
1963 | The third, _interwork_r11_call_via_rN(), works in the same way but | |
1964 | uses r11 instead of r7. It is useful if the caller does not really | |
1965 | need a frame pointer. */ | |
75d3a15b NC |
1966 | |
1967 | .text | |
1968 | .align 0 | |
1969 | ||
1970 | .code 32 | |
2a5307b1 | 1971 | .globl _arm_return |
d0f11b16 DJ |
1972 | LSYM(Lstart_arm_return): |
1973 | cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return) | |
1974 | cfi_push 0, 0xe, -0x8, 0x8 | |
1975 | nop @ This nop is for the benefit of debuggers, so that | |
1976 | @ backtraces will use the correct unwind information. | |
496b84c8 | 1977 | _arm_return: |
d0f11b16 DJ |
1978 | RETLDM unwind=LSYM(Lstart_arm_return) |
1979 | cfi_end LSYM(Lend_arm_return) | |
a2503645 RS |
1980 | |
1981 | .globl _arm_return_r7 | |
1982 | _arm_return_r7: | |
1983 | ldr lr, [r7, #-4] | |
1984 | bx lr | |
1985 | ||
1986 | .globl _arm_return_r11 | |
1987 | _arm_return_r11: | |
1988 | ldr lr, [r11, #-4] | |
1989 | bx lr | |
1990 | ||
1991 | .macro interwork_with_frame frame, register, name, return | |
1992 | .code 16 | |
1993 | ||
1994 | THUMB_FUNC_START \name | |
1995 | ||
1996 | bx pc | |
1997 | nop | |
1998 | ||
1999 | .code 32 | |
2000 | tst \register, #1 | |
2001 | streq lr, [\frame, #-4] | |
2002 | adreq lr, _arm_return_\frame | |
2003 | bx \register | |
2004 | ||
2005 | SIZE (\name) | |
2006 | .endm | |
75d3a15b | 2007 | |
496b84c8 RE |
2008 | .macro interwork register |
2009 | .code 16 | |
6dcd26ea RE |
2010 | |
2011 | THUMB_FUNC_START _interwork_call_via_\register | |
2012 | ||
496b84c8 | 2013 | bx pc |
75d3a15b | 2014 | nop |
496b84c8 RE |
2015 | |
2016 | .code 32 | |
2017 | .globl LSYM(Lchange_\register) | |
2018 | LSYM(Lchange_\register): | |
75d3a15b | 2019 | tst \register, #1 |
d0f11b16 | 2020 | streq lr, [sp, #-8]! |
75d3a15b NC |
2021 | adreq lr, _arm_return |
2022 | bx \register | |
2a5307b1 NC |
2023 | |
2024 | SIZE (_interwork_call_via_\register) | |
a2503645 RS |
2025 | |
2026 | interwork_with_frame r7,\register,_interwork_r7_call_via_\register | |
2027 | interwork_with_frame r11,\register,_interwork_r11_call_via_\register | |
75d3a15b NC |
2028 | .endm |
2029 | ||
2030 | interwork r0 | |
2031 | interwork r1 | |
2032 | interwork r2 | |
2033 | interwork r3 | |
2034 | interwork r4 | |
2035 | interwork r5 | |
2036 | interwork r6 | |
2037 | interwork r7 | |
2038 | interwork r8 | |
2039 | interwork r9 | |
2040 | interwork sl | |
2041 | interwork fp | |
2042 | interwork ip | |
2043 | interwork sp | |
2a5307b1 | 2044 | |
6dcd26ea | 2045 | /* The LR case has to be handled a little differently... */ |
2a5307b1 | 2046 | .code 16 |
6dcd26ea RE |
2047 | |
2048 | THUMB_FUNC_START _interwork_call_via_lr | |
2049 | ||
2a5307b1 NC |
2050 | bx pc |
2051 | nop | |
2052 | ||
2053 | .code 32 | |
2054 | .globl .Lchange_lr | |
2055 | .Lchange_lr: | |
2056 | tst lr, #1 | |
d0f11b16 | 2057 | stmeqdb r13!, {lr, pc} |
2a5307b1 NC |
2058 | mov ip, lr |
2059 | adreq lr, _arm_return | |
2060 | bx ip | |
2061 | ||
2062 | SIZE (_interwork_call_via_lr) | |
2063 | ||
75d3a15b | 2064 | #endif /* L_interwork_call_via_rX */ |
5b3e6663 | 2065 | #endif /* !__thumb2__ */ |
907dd0c7 RE |
2066 | |
2067 | /* Functions to support compact pic switch tables in thumb1 state. | |
2068 | All these routines take an index into the table in r0. The | |
2069 | table is at LR & ~1 (but this must be rounded up in the case | |
2070 | of 32-bit entires). They are only permitted to clobber r12 | |
2071 | and r14 and r0 must be preserved on exit. */ | |
2072 | #ifdef L_thumb1_case_sqi | |
2073 | ||
2074 | .text | |
2075 | .align 0 | |
2076 | .force_thumb | |
2077 | .syntax unified | |
2078 | THUMB_FUNC_START __gnu_thumb1_case_sqi | |
2079 | push {r1} | |
2080 | mov r1, lr | |
2081 | lsrs r1, r1, #1 | |
2082 | lsls r1, r1, #1 | |
2083 | ldrsb r1, [r1, r0] | |
2084 | lsls r1, r1, #1 | |
2085 | add lr, lr, r1 | |
2086 | pop {r1} | |
2087 | bx lr | |
2088 | SIZE (__gnu_thumb1_case_sqi) | |
2089 | #endif | |
2090 | ||
2091 | #ifdef L_thumb1_case_uqi | |
2092 | ||
2093 | .text | |
2094 | .align 0 | |
2095 | .force_thumb | |
2096 | .syntax unified | |
2097 | THUMB_FUNC_START __gnu_thumb1_case_uqi | |
2098 | push {r1} | |
2099 | mov r1, lr | |
2100 | lsrs r1, r1, #1 | |
2101 | lsls r1, r1, #1 | |
2102 | ldrb r1, [r1, r0] | |
2103 | lsls r1, r1, #1 | |
2104 | add lr, lr, r1 | |
2105 | pop {r1} | |
2106 | bx lr | |
2107 | SIZE (__gnu_thumb1_case_uqi) | |
2108 | #endif | |
2109 | ||
2110 | #ifdef L_thumb1_case_shi | |
2111 | ||
2112 | .text | |
2113 | .align 0 | |
2114 | .force_thumb | |
2115 | .syntax unified | |
2116 | THUMB_FUNC_START __gnu_thumb1_case_shi | |
2117 | push {r0, r1} | |
2118 | mov r1, lr | |
2119 | lsrs r1, r1, #1 | |
2120 | lsls r0, r0, #1 | |
2121 | lsls r1, r1, #1 | |
2122 | ldrsh r1, [r1, r0] | |
2123 | lsls r1, r1, #1 | |
2124 | add lr, lr, r1 | |
2125 | pop {r0, r1} | |
2126 | bx lr | |
2127 | SIZE (__gnu_thumb1_case_shi) | |
2128 | #endif | |
2129 | ||
2130 | #ifdef L_thumb1_case_uhi | |
2131 | ||
2132 | .text | |
2133 | .align 0 | |
2134 | .force_thumb | |
2135 | .syntax unified | |
2136 | THUMB_FUNC_START __gnu_thumb1_case_uhi | |
2137 | push {r0, r1} | |
2138 | mov r1, lr | |
2139 | lsrs r1, r1, #1 | |
2140 | lsls r0, r0, #1 | |
2141 | lsls r1, r1, #1 | |
2142 | ldrh r1, [r1, r0] | |
2143 | lsls r1, r1, #1 | |
2144 | add lr, lr, r1 | |
2145 | pop {r0, r1} | |
2146 | bx lr | |
2147 | SIZE (__gnu_thumb1_case_uhi) | |
2148 | #endif | |
2149 | ||
2150 | #ifdef L_thumb1_case_si | |
2151 | ||
2152 | .text | |
2153 | .align 0 | |
2154 | .force_thumb | |
2155 | .syntax unified | |
2156 | THUMB_FUNC_START __gnu_thumb1_case_si | |
2157 | push {r0, r1} | |
2158 | mov r1, lr | |
2159 | adds.n r1, r1, #2 /* Align to word. */ | |
2160 | lsrs r1, r1, #2 | |
2161 | lsls r0, r0, #2 | |
2162 | lsls r1, r1, #2 | |
2163 | ldr r0, [r1, r0] | |
2164 | adds r0, r0, r1 | |
2165 | mov lr, r0 | |
2166 | pop {r0, r1} | |
2167 | mov pc, lr /* We know we were called from thumb code. */ | |
2168 | SIZE (__gnu_thumb1_case_si) | |
2169 | #endif | |
2170 | ||
e0d4a859 | 2171 | #endif /* Arch supports thumb. */ |
4202ce82 | 2172 | |
ff935d0c MG |
2173 | .macro CFI_START_FUNCTION |
2174 | .cfi_startproc | |
2175 | .cfi_remember_state | |
2176 | .endm | |
2177 | ||
2178 | .macro CFI_END_FUNCTION | |
2179 | .cfi_restore_state | |
2180 | .cfi_endproc | |
2181 | .endm | |
2182 | ||
f9a02408 | 2183 | #ifndef __symbian__ |
72e3a529 TP |
2184 | /* The condition here must match the one in gcc/config/arm/elf.h and |
2185 | libgcc/config/arm/t-elf. */ | |
6f493951 | 2186 | #ifndef NOT_ISA_TARGET_32BIT |
4202ce82 | 2187 | #include "ieee754-df.S" |
4202ce82 | 2188 | #include "ieee754-sf.S" |
b3f8d95d | 2189 | #include "bpabi.S" |
6f493951 | 2190 | #else /* NOT_ISA_TARGET_32BIT */ |
bf98ec6c | 2191 | #include "bpabi-v6m.S" |
6f493951 | 2192 | #endif /* NOT_ISA_TARGET_32BIT */ |
bf98ec6c | 2193 | #endif /* !__symbian__ */ |