]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/arm/lib1funcs.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / arm / lib1funcs.S
CommitLineData
7857f134 1@ libgcc routines for ARM cpu.
bd28bf5a 2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
454e0249 3
99dee823 4/* Copyright (C) 1995-2021 Free Software Foundation, Inc.
454e0249
DE
5
6This file is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
748086b7 8Free Software Foundation; either version 3, or (at your option) any
454e0249
DE
9later version.
10
454e0249
DE
11This file is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
748086b7
JJ
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see 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
152LSYM(Lstart_frame):
153 .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
154LSYM(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
166LSYM(Lend_cie):
167 .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
168LSYM(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
179LSYM(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. */
20097: 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]!
26498: 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
2871:
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 }
31598: 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 333LSYM(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
347SYM (\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
374SYM (__\name):
375.endm
496b84c8 376
1025cb6c
TW
377.macro ARM_SYM_START name
378 TYPE (\name)
379 .align 0
380SYM (\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
431SYM (__\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 481work .req r4 @ XXXX is this safe ?
bd28bf5a
RE
482dividend .req r0
483divisor .req r1
888e552f 484overdone .req r2
bd28bf5a
RE
485result .req r2
486curbit .req r3
6a436e5e 487#endif
5a9335ef 488#if 0
bd28bf5a
RE
489ip .req r12
490sp .req r13
491lr .req r14
492pc .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
5131:
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
5671: 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
5751: 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
5861: 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.
6751: 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.
6831: 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
6961: 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.
7142: cmn \order, #2
715 blt 4f
716 beq 3f
717 cmp \dividend, \divisor
718 subhs \dividend, \dividend, \divisor
719 mov \divisor, \divisor, lsr #1
7203: cmp \dividend, \divisor
721 subhs \dividend, \dividend, \divisor
722 mov \divisor, \divisor, lsr #1
7234: cmp \dividend, \divisor
724 subhs \dividend, \dividend, \divisor
7255:
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 735LSYM(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)
747LSYM(Lbignum):
d5b7b3ae 748 @ Set work to 0x80000000
6b9ce2b4 749 lsls work, #3
ce250a20 750LSYM(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)
760LSYM(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 770LSYM(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 780LSYM(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 790LSYM(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 800LSYM(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 810LSYM(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 817LSYM(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 824LSYM(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 831LSYM(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)
840LSYM(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 868LSYM(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 876LSYM(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 885LSYM(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 9071: 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)
921LSYM(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 9321: lsrs curbit, dividend, #12
82742404
HW
933 cmp curbit, divisor
934 blo LSYM(Lthumb1_div12)
935 b LSYM(Lthumb1_div16)
936LSYM(Lthumb1_div_loop):
6b9ce2b4 937 lsrs divisor, divisor, #8
82742404
HW
938LSYM(Lthumb1_div16):
939 Dodiv #15
940 Dodiv #14
941 Dodiv #13
942 Dodiv #12
943LSYM(Lthumb1_div12):
944 Dodiv #11
945 Dodiv #10
946 Dodiv #9
947 Dodiv #8
948 bcs LSYM(Lthumb1_div_loop)
949LSYM(Lthumb1_div8):
950 Dodiv #7
951 Dodiv #6
952 Dodiv #5
953LSYM(Lthumb1_div5):
954 Dodiv #4
955LSYM(Lthumb1_div4):
956 Dodiv #3
957LSYM(Lthumb1_div3):
958 Dodiv #2
959LSYM(Lthumb1_div2):
960 Dodiv #1
961LSYM(Lthumb1_div1):
6b9ce2b4 962 subs divisor, dividend, divisor
82742404
HW
963 bcs 1f
964 cpy divisor, dividend
965
6b9ce2b4 9661: adcs result, result
82742404
HW
967 cpy dividend, result
968 RET
969
970LSYM(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 9821: asrs curbit, dividend, #32
82742404 983 bcc 2f
6b9ce2b4 984 negs dividend, dividend
82742404 985
6b9ce2b4
RE
9862: 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)
991LSYM(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)
1013LSYM(Lthumb1_div_negative_loop):
6b9ce2b4 1014 lsrs divisor, divisor, #6
82742404
HW
1015LSYM(Lthumb1_div_negative8):
1016 DoDiv #7
1017 DoDiv #6
1018 DoDiv #5
1019 DoDiv #4
1020LSYM(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
10291: 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
10372: bpl 3f
6b9ce2b4 1038 negs divisor, divisor
82742404
HW
1039
10403: RET
1041
1042LSYM(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 1063LSYM(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
1080LSYM(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. */
1103LSYM(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
111811: do_it eq, e
1119 moveq r0, #1
6a436e5e
NP
1120 movne r0, #0
1121 RET
1122
112312: 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 1133FUNC_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__)
1152ARM_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 1160ARM_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 1197LSYM(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 1237LSYM(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 1247LSYM(Lover10):
d5b7b3ae 1248 cmp dividend, #0
ce250a20 1249 bpl LSYM(Lover11)
e519d644 1250 negs dividend, dividend
ce250a20 1251LSYM(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 1262LSYM(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
1269LSYM(divsi3_skip_div0_test):
1270 cpy curbit, dividend
6b9ce2b4 1271 orrs curbit, divisor
82742404
HW
1272 bmi LSYM(Lthumb1_div_negative)
1273
1274LSYM(Lthumb1_div_positive):
1275 THUMB1_Div_Positive
1276
1277LSYM(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
1299LSYM(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 132010: teq ip, r0 @ same sign ?
f36d140e 1321 do_it mi
6a436e5e
NP
1322 rsbmi r0, r0, #0
1323 RET
1324
f36d140e
PB
132511: 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
133212: 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 1345FUNC_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__)
1364ARM_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 1372ARM_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 1408LSYM(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 1417LSYM(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 1427LSYM(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
144910: 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}
149098: 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}
149598: 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
1525 swi 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
16461:
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 1702FUNC_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
17102: 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
17152: 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
17202: adr r2, 1f
1721 ldrb r0, [r2, r0]
6b9ce2b4 1722 adds r0, r0, r1
ef0a4b67
PB
1723 bx lr
1724.align 2
17251:
1726.byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
1727 FUNC_END clzsi2
1728#else
1729ARM_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
17521:
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
1763FUNC_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
17721:
1773 bl __clzsi2
1774# else
1775 bl __clzsi2
1776 adds r0, r0, #32
1777 b 2f
17781:
1779 movs r0, xxh
1780 bl __clzsi2
1781# endif
17822:
1783 pop {r4, pc}
1784# else /* NOT_ISA_TARGET_32BIT */
ef0a4b67
PB
1785ARM_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
17941:
1795 bl __clzsi2
6b9ce2b4 1796# else
ef0a4b67
PB
1797 bl __clzsi2
1798 add r0, r0, #32
1799 b 2f
18001:
1801 mov r0, xxh
1802 bl __clzsi2
6b9ce2b4 1803# endif
ef0a4b67 18042:
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
1811ARM_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 1825FUNC_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
18352: 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
18402: 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
18452: adr r2, 1f
1846 ldrb r0, [r2, r0]
6b9ce2b4 1847 subs r0, r0, r1
06ea7371
RE
1848 bx lr
1849.align 2
18501:
1851.byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31
1852 FUNC_END ctzsi2
1853#else
1854ARM_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
18801:
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
1972LSYM(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)
2018LSYM(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__ */