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