1 @ libgcc routines for ARM cpu.
2 @ Division routines
, written by Richard Earnshaw
, (rearnsha
@armltd.co.uk
)
4 /* Copyright
1995, 1996, 1998, 1999, 2000, 2003, 2004
5 Free Software Foundation
, Inc.
7 This file is free software
; you can redistribute it and/or modify it
8 under the terms of the GNU General
Public License as published by the
9 Free Software Foundation
; either version 2, or (at your option) any
12 In addition to the permissions
in the GNU General
Public License
, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of
this file
into combinations with other programs
,
15 and to distribute those combinations without any restriction coming
16 from the use of
this file.
(The General
Public License restrictions
17 do apply
in other respects
; for example, they cover modification of
18 the file
, and distribution when
not linked
into a combine
21 This file is distributed
in the hope that it will be useful
, but
22 WITHOUT ANY WARRANTY
; without even the implied warranty of
23 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General
Public License for more details.
26 You should have received a copy of the GNU General
Public License
27 along with
this program
; see the file COPYING. If not, write to
28 the Free Software Foundation
, 59 Temple Place
- Suite
330,
29 Boston
, MA
02111-1307, USA.
*/
30 /* ------------------------------------------------------------------------ */
32 /* We need to know what prefix to
add to function names.
*/
34 #ifndef __USER_LABEL_PREFIX__
35 #error __USER_LABEL_PREFIX__
not defined
38 /* ANSI concatenation macros.
*/
40 #define CONCAT1
(a
, b
) CONCAT2
(a
, b
)
41 #define CONCAT2
(a
, b
) a ## b
43 /* Use the right prefix for
global labels.
*/
45 #define SYM
(x
) CONCAT1
(__USER_LABEL_PREFIX__
, x
)
49 #define __PLT__
/* Not supported
in Thumb assembler
(for now
).
*/
53 #define
TYPE(x
) .
type SYM
(x
),function
54 #define
SIZE(x
) .
size SYM
(x
), .
- SYM
(x
)
63 /* Function
end macros. Variants for interworking.
*/
65 @
This selects the minimum architecture level required.
66 #define __ARM_ARCH__
3
68 #if defined
(__ARM_ARCH_3M__
) || defined
(__ARM_ARCH_4__
) \
69 || defined
(__ARM_ARCH_4T__
)
70 /* We use __ARM_ARCH__ set to
4 here
, but
in reality it
's any processor with
71 long multiply instructions. That includes v3M. */
73 # define __ARM_ARCH__ 4
76 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
77 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
78 || defined(__ARM_ARCH_5TEJ__)
80 # define __ARM_ARCH__ 5
83 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
84 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
85 || defined(__ARM_ARCH_6ZK__)
87 # define __ARM_ARCH__ 6
90 /* How to return from a function call depends on the architecture variant. */
92 #if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
95 # define RETc(x) bx##x lr
97 # if (__ARM_ARCH__ == 4) \
98 && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
99 # define __INTERWORKING__
104 # define RET mov pc, lr
105 # define RETc(x) mov##x pc, lr
109 /* Don't pass dirn
, it
's there just to get token pasting right. */
111 .macro RETLDM regs=, cond=, dirn=ia
112 #if defined (__INTERWORKING__)
114 ldr\cond lr, [sp], #4
116 ldm\cond\dirn sp!, {\regs, lr}
121 ldr\cond pc, [sp], #4
123 ldm\cond\dirn sp!, {\regs, pc}
132 bl SYM (__div0) __PLT__
133 mov r0, #0 @ About as wrong as it could be.
142 mov r0, #0 @ About as wrong as it could be.
143 #if defined (__INTERWORKING__)
155 .macro DIV_FUNC_END name
165 .macro THUMB_FUNC_START name
172 /* Function start macros. Variants for ARM and Thumb. */
175 #define THUMB_FUNC .thumb_func
176 #define THUMB_CODE .force_thumb
182 .macro FUNC_START name
192 /* Special function that will always be coded in ARM assembly, even if
193 in Thumb-only compilation. */
195 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
196 .macro ARM_FUNC_START name
201 /* A hook to tell gdb that we've switched to ARM mode. Also used to
call
202 directly from other
local arm routines.
*/
205 #define EQUIV .thumb_set
206 /* Branch directly to a function declared with ARM_FUNC_START.
207 Must be called
in arm mode.
*/
212 .
macro ARM_FUNC_START
name
226 .
macro ARM_FUNC_ALIAS new old
228 EQUIV SYM
(__
\new
), SYM
(__\old
)
230 .set SYM
(_L__
\new
), SYM
(_L__\old
)
235 /* Register aliases.
*/
237 work .req r4 @ XXXX is
this safe
?
251 /* ------------------------------------------------------------------------ */
252 /* Bodies of the division
and modulo routines.
*/
253 /* ------------------------------------------------------------------------ */
254 .
macro ARM_DIV_BODY dividend
, divisor
, result
, curbit
256 #if __ARM_ARCH__
>= 5 && ! defined
(__OPTIMIZE_SIZE__
)
258 clz \curbit
, \dividend
259 clz
\result
, \divisor
260 sub \curbit
, \result
, \curbit
261 rsbs \curbit
, \curbit
, #
31
262 addne \curbit
, \curbit
, \curbit
, lsl #
1
264 addne pc
, pc
, \curbit
, lsl #
2
268 .set shift
, shift
- 1
269 cmp \dividend
, \divisor
, lsl #shift
270 adc \result
, \result
, \result
271 subcs \dividend
, \dividend
, \divisor
, lsl #shift
274 #else
/* __ARM_ARCH__
< 5 || defined
(__OPTIMIZE_SIZE__
) */
275 #if __ARM_ARCH__
>= 5
277 clz \curbit
, \divisor
278 clz
\result
, \dividend
279 sub \result
, \curbit
, \result
281 mov \divisor
, \divisor
, lsl \result
282 mov \curbit
, \curbit
, lsl \result
285 #else
/* __ARM_ARCH__
< 5 */
287 @ Initially shift the divisor left
3 bits if possible
,
288 @ set curbit accordingly.
This allows for curbit to be located
289 @ at the left
end of each
4 bit nibbles
in the division
loop
290 @ to save one
loop in most cases.
291 tst \divisor
, #
0xe0000000
292 moveq \divisor
, \divisor
, lsl #
3
296 @ Unless the divisor is very big
, shift it up
in multiples of
297 @ four bits
, since
this is the amount of unwinding
in the main
298 @ division
loop. Continue shifting until the divisor is
299 @ larger than the dividend.
300 1: cmp \divisor
, #
0x10000000
301 cmplo \divisor
, \dividend
302 movlo \divisor
, \divisor
, lsl #
4
303 movlo \curbit
, \curbit
, lsl #
4
306 @ For very big divisors
, we must shift it a bit at a time
, or
307 @ we will be
in danger of overflowing.
308 1: cmp \divisor
, #
0x80000000
309 cmplo \divisor
, \dividend
310 movlo \divisor
, \divisor
, lsl #
1
311 movlo \curbit
, \curbit
, lsl #
1
316 #endif
/* __ARM_ARCH__
< 5 */
319 1: cmp \dividend
, \divisor
320 subhs \dividend
, \dividend
, \divisor
321 orrhs
\result
, \result
, \curbit
322 cmp \dividend
, \divisor
, lsr #
1
323 subhs \dividend
, \dividend
, \divisor
, lsr #
1
324 orrhs
\result
, \result
, \curbit
, lsr #
1
325 cmp \dividend
, \divisor
, lsr #
2
326 subhs \dividend
, \dividend
, \divisor
, lsr #
2
327 orrhs
\result
, \result
, \curbit
, lsr #
2
328 cmp \dividend
, \divisor
, lsr #
3
329 subhs \dividend
, \dividend
, \divisor
, lsr #
3
330 orrhs
\result
, \result
, \curbit
, lsr #
3
331 cmp \dividend
, #
0 @ Early termination
?
332 movnes \curbit
, \curbit
, lsr #
4 @ No
, any more bits to do
?
333 movne \divisor
, \divisor
, lsr #
4
336 #endif
/* __ARM_ARCH__
< 5 || defined
(__OPTIMIZE_SIZE__
) */
339 /* ------------------------------------------------------------------------ */
340 .
macro ARM_DIV2_ORDER divisor
, order
342 #if __ARM_ARCH__
>= 5
345 rsb \order
, \order
, #
31
349 cmp \divisor
, #
(1 << 16)
350 movhs \divisor
, \divisor
, lsr #
16
354 cmp \divisor
, #
(1 << 8)
355 movhs \divisor
, \divisor
, lsr #
8
356 addhs \order
, \order
, #
8
358 cmp \divisor
, #
(1 << 4)
359 movhs \divisor
, \divisor
, lsr #
4
360 addhs \order
, \order
, #
4
362 cmp \divisor
, #
(1 << 2)
363 addhi \order
, \order
, #
3
364 addls \order
, \order
, \divisor
, lsr #
1
369 /* ------------------------------------------------------------------------ */
370 .
macro ARM_MOD_BODY dividend
, divisor
, order
, spare
372 #if __ARM_ARCH__
>= 5 && ! defined
(__OPTIMIZE_SIZE__
)
375 clz \spare
, \dividend
376 sub \order
, \order
, \spare
377 rsbs \order
, \order
, #
31
378 addne pc
, pc
, \order
, lsl #
3
382 .set shift
, shift
- 1
383 cmp \dividend
, \divisor
, lsl #shift
384 subcs \dividend
, \dividend
, \divisor
, lsl #shift
387 #else
/* __ARM_ARCH__
< 5 || defined
(__OPTIMIZE_SIZE__
) */
388 #if __ARM_ARCH__
>= 5
391 clz \spare
, \dividend
392 sub \order
, \order
, \spare
393 mov \divisor
, \divisor
, lsl \order
395 #else
/* __ARM_ARCH__
< 5 */
399 @ Unless the divisor is very big
, shift it up
in multiples of
400 @ four bits
, since
this is the amount of unwinding
in the main
401 @ division
loop. Continue shifting until the divisor is
402 @ larger than the dividend.
403 1: cmp \divisor
, #
0x10000000
404 cmplo \divisor
, \dividend
405 movlo \divisor
, \divisor
, lsl #
4
406 addlo \order
, \order
, #
4
409 @ For very big divisors
, we must shift it a bit at a time
, or
410 @ we will be
in danger of overflowing.
411 1: cmp \divisor
, #
0x80000000
412 cmplo \divisor
, \dividend
413 movlo \divisor
, \divisor
, lsl #
1
414 addlo \order
, \order
, #
1
417 #endif
/* __ARM_ARCH__
< 5 */
419 @ Perform all needed substractions to keep only the reminder.
420 @ Do comparisons
in batch of
4 first.
421 subs \order
, \order
, #
3 @ yes
, 3 is intended here
424 1: cmp \dividend
, \divisor
425 subhs \dividend
, \dividend
, \divisor
426 cmp \dividend
, \divisor
, lsr #
1
427 subhs \dividend
, \dividend
, \divisor
, lsr #
1
428 cmp \dividend
, \divisor
, lsr #
2
429 subhs \dividend
, \dividend
, \divisor
, lsr #
2
430 cmp \dividend
, \divisor
, lsr #
3
431 subhs \dividend
, \dividend
, \divisor
, lsr #
3
433 mov \divisor
, \divisor
, lsr #
4
434 subges \order
, \order
, #
4
441 @ Either
1, 2 or 3 comparison
/substractions are left.
445 cmp \dividend
, \divisor
446 subhs \dividend
, \dividend
, \divisor
447 mov \divisor
, \divisor
, lsr #
1
448 3: cmp \dividend
, \divisor
449 subhs \dividend
, \dividend
, \divisor
450 mov \divisor
, \divisor
, lsr #
1
451 4: cmp \dividend
, \divisor
452 subhs \dividend
, \dividend
, \divisor
455 #endif
/* __ARM_ARCH__
< 5 || defined
(__OPTIMIZE_SIZE__
) */
458 /* ------------------------------------------------------------------------ */
459 .
macro THUMB_DIV_MOD_BODY modulo
460 @ Load the constant
0x10000000 into our work register.
464 @ Unless the divisor is very big
, shift it up
in multiples of
465 @ four bits
, since
this is the amount of unwinding
in the main
466 @ division
loop. Continue shifting until the divisor is
467 @ larger than the dividend.
470 cmp divisor
, dividend
476 @ Set work to
0x80000000
479 @ For very big divisors
, we must shift it a bit at a time
, or
480 @ we will be
in danger of overflowing.
483 cmp divisor
, dividend
489 @
Test for possible subtractions ...
491 @ ... On the final pass
, this may subtract too much from the dividend
,
492 @ so keep track of which subtractions are done
, we can fix them up
495 cmp dividend
, divisor
497 sub dividend
, dividend
, divisor
499 lsr work
, divisor
, #
1
502 sub dividend
, dividend
, work
509 lsr work
, divisor
, #
2
512 sub dividend
, dividend
, work
519 lsr work
, divisor
, #
3
522 sub dividend
, dividend
, work
531 @ ...
and note which bits are done
in the result. On the final pass
,
532 @
this may subtract too much from the dividend
, but the result will be ok
,
533 @ since the
"bit" will have been shifted
out at the bottom.
534 cmp dividend
, divisor
536 sub dividend
, dividend
, divisor
537 orr result
, result
, curbit
539 lsr work
, divisor
, #
1
542 sub dividend
, dividend
, work
546 lsr work
, divisor
, #
2
549 sub dividend
, dividend
, work
553 lsr work
, divisor
, #
3
556 sub dividend
, dividend
, work
562 cmp dividend
, #
0 @ Early termination
?
564 lsr curbit
, #
4 @ No
, any more bits to do
?
570 @ Any subtractions that we should
not have done will be recorded
in
571 @ the top three bits of
"overdone". Exactly which were
not needed
572 @ are governed by the position of the bit
, stored
in ip.
576 beq LSYM
(Lgot_result
)
578 @ If we terminated early
, because dividend became zero
, then the
579 @ bit
in ip will
not be
in the bottom nibble
, and we should
not
580 @ perform the additions below. We must
test for
this though
581 @
(rather relying upon the TSTs to prevent the additions
) since
582 @ the bit
in ip could be
in the top two bits which might then match
583 @ with one of the smaller RORs.
587 beq LSYM
(Lgot_result
)
594 lsr work
, divisor
, #
3
602 lsr work
, divisor
, #
2
609 beq LSYM
(Lgot_result
)
610 lsr work
, divisor
, #
1
615 /* ------------------------------------------------------------------------ */
616 /* Start of the Real Functions
*/
617 /* ------------------------------------------------------------------------ */
630 cmp dividend
, divisor
631 blo LSYM
(Lgot_result
)
639 #else
/* ARM version.
*/
649 ARM_DIV_BODY r0
, r1
, r2
, r3
658 12: ARM_DIV2_ORDER r1
, r2
663 #endif
/* ARM version
*/
667 FUNC_START aeabi_uidivmod
676 stmfd
sp!, { r0, r1, lr }
678 ldmfd
sp!, { r1, r2, lr }
683 FUNC_END aeabi_uidivmod
685 #endif
/* L_udivsi3
*/
686 /* ------------------------------------------------------------------------ */
696 cmp dividend
, divisor
708 #else
/* ARM version.
*/
710 subs r2
, r1
, #
1 @ compare divisor with
1
712 cmpne r0
, r1 @ compare dividend with divisor
714 tsthi r1
, r2 @ see if divisor is power of
2
718 ARM_MOD_BODY r0
, r1
, r2
, r3
722 #endif
/* ARM version.
*/
726 #endif
/* L_umodsi3
*/
727 /* ------------------------------------------------------------------------ */
738 eor work
, divisor @ Save the sign of the result.
744 neg divisor
, divisor @ Loops below use unsigned.
748 neg dividend
, dividend
750 cmp dividend
, divisor
751 blo LSYM
(Lgot_result
)
764 #else
/* ARM version.
*/
767 eor ip
, r0
, r1 @ save the sign of the result.
769 rsbmi r1
, r1
, #
0 @ loops below use unsigned.
770 subs r2
, r1
, #
1 @ division by
1 or -1 ?
773 rsbmi r3
, r0
, #
0 @ positive dividend value
776 tst r1
, r2 @ divisor is power of
2 ?
779 ARM_DIV_BODY r3
, r1
, r0
, r2
785 10: teq ip
, r0 @ same sign
?
790 moveq r0
, ip
, asr #
31
794 12: ARM_DIV2_ORDER r1
, r2
801 #endif
/* ARM version
*/
805 FUNC_START aeabi_idivmod
814 stmfd
sp!, { r0, r1, lr }
816 ldmfd
sp!, { r1, r2, lr }
821 FUNC_END aeabi_idivmod
823 #endif
/* L_divsi3
*/
824 /* ------------------------------------------------------------------------ */
835 neg divisor
, divisor @ Loops below use unsigned.
838 @ Need to save the sign of the dividend
, unfortunately
, we need
839 @ work later on. Must do
this after saving the original value of
840 @ the work register
, because we will
pop this value off first.
844 neg dividend
, dividend
846 cmp dividend
, divisor
847 blo LSYM
(Lgot_result
)
854 neg dividend
, dividend
859 #else
/* ARM version.
*/
863 rsbmi r1
, r1
, #
0 @ loops below use unsigned.
864 movs ip
, r0 @ preserve sign of dividend
865 rsbmi r0
, r0
, #
0 @ if negative make positive
866 subs r2
, r1
, #
1 @ compare divisor with
1
867 cmpne r0
, r1 @ compare dividend with divisor
869 tsthi r1
, r2 @ see if divisor is power of
2
873 ARM_MOD_BODY r0
, r1
, r2
, r3
879 #endif
/* ARM version
*/
883 #endif
/* L_modsi3
*/
884 /* ------------------------------------------------------------------------ */
888 ARM_FUNC_ALIAS aeabi_idiv0 div0
889 ARM_FUNC_ALIAS aeabi_ldiv0 div0
897 #endif
/* L_divmodsi_tools
*/
898 /* ------------------------------------------------------------------------ */
900 @ GNU
/Linux division
-by zero handler. Used
in place of L_dvmd_tls
902 /* Constants taken from
<asm
/unistd.h
> and <asm
/signal.h
> */
904 #define __NR_SYSCALL_BASE
0x900000
905 #define __NR_getpid
(__NR_SYSCALL_BASE
+ 20)
906 #define __NR_kill
(__NR_SYSCALL_BASE
+ 37)
921 #endif
/* L_dvmd_lnx
*/
922 /* ------------------------------------------------------------------------ */
923 /* Dword shift operations.
*/
924 /* All the following
Dword shift variants rely on the fact that
927 shft xxx
, (Reg
& 255)
928 so for Reg value
in (32..
.63) and (-1...
-31) we will get zero
(in the
929 case of logical shifts
) or the sign
(for asr
).
*/
942 ARM_FUNC_ALIAS aeabi_llsr lshrdi3
962 orrmi
al, al, ah, lsl ip
974 ARM_FUNC_ALIAS aeabi_lasr ashrdi3
981 @ If r2 is negative at
this point the following step would
OR
982 @ the sign bit
into all of
AL. That
's not what we want...
998 orrmi al, al, ah, lsl ip
1011 ARM_FUNC_ALIAS aeabi_llsl ashldi3
1029 movmi ah, ah, lsl r2
1030 movpl ah, al, lsl r3
1031 orrmi ah, ah, al, lsr ip
1040 /* ------------------------------------------------------------------------ */
1041 /* These next two sections are here despite the fact that they contain Thumb
1042 assembler because their presence allows interworked code to be linked even
1043 when the GCC library is this one. */
1045 /* Do not build the interworking functions when the target architecture does
1046 not support Thumb instructions. (This can be a multilib option). */
1047 #if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
1048 || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
1049 || __ARM_ARCH__ >= 6
1051 #if defined L_call_via_rX
1053 /* These labels & instructions are used by the Arm/Thumb interworking code.
1054 The address of function to be called is loaded into a register and then
1055 one of these labels is called via a BL instruction. This puts the
1056 return address into the link register with the bottom bit set, and the
1057 code here switches to the correct mode before executing the function. */
1063 .macro call_via register
1064 THUMB_FUNC_START _call_via_\register
1069 SIZE (_call_via_\register)
1088 #endif /* L_call_via_rX */
1090 #if defined L_interwork_call_via_rX
1092 /* These labels & instructions are used by the Arm/Thumb interworking code,
1093 when the target address is in an unknown instruction set. The address
1094 of function to be called is loaded into a register and then one of these
1095 labels is called via a BL instruction. This puts the return address
1096 into the link register with the bottom bit set, and the code here
1097 switches to the correct mode before executing the function. Unfortunately
1098 the target code cannot be relied upon to return via a BX instruction, so
1099 instead we have to store the resturn address on the stack and allow the
1100 called function to return here instead. Upon return we recover the real
1101 return address and use a BX to get back to Thumb mode. */
1112 .macro interwork register
1115 THUMB_FUNC_START _interwork_call_via_\register
1121 .globl LSYM(Lchange_\register)
1122 LSYM(Lchange_\register):
1124 streq lr, [sp, #-4]!
1125 adreq lr, _arm_return
1128 SIZE (_interwork_call_via_\register)
1146 /* The LR case has to be handled a little differently... */
1149 THUMB_FUNC_START _interwork_call_via_lr
1160 adreq lr, _arm_return
1163 SIZE (_interwork_call_via_lr)
1165 #endif /* L_interwork_call_via_rX */
1166 #endif /* Arch supports thumb. */
1169 #include "ieee754-df.S"
1170 #include "ieee754-sf.S"
1172 #endif /* __symbian__ */