1 @ libgcc1 routines for ARM cpu.
2 @ Division routines
, written by Richard Earnshaw
, (rearnsha
@armltd.co.uk
)
4 /* Copyright
(C
) 1995, 1996, 1998 Free Software Foundation
, Inc.
6 This file is free software
; you can redistribute it and/or modify it
7 under the terms of the GNU General
Public License as published by the
8 Free Software Foundation
; either version 2, or (at your option) any
11 In addition to the permissions
in the GNU General
Public License
, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of
this file with other programs
, and to distribute
14 those programs without any restriction coming from the use of
this
15 file.
(The General
Public License restrictions do apply
in other
16 respects
; for example, they cover modification of the file, and
17 distribution when
not linked
into another program.
)
19 This file is distributed
in the hope that it will be useful
, but
20 WITHOUT ANY WARRANTY
; without even the implied warranty of
21 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General
Public License for more details.
24 You should have received a copy of the GNU General
Public License
25 along with
this program
; see the file COPYING. If not, write to
26 the Free Software Foundation
, 59 Temple Place
- Suite
330,
27 Boston
, MA
02111-1307, USA.
*/
29 /* As a special exception
, if you link
this library with other files
,
30 some of which are compiled with GCC
, to produce an executable
,
31 this library does
not by itself cause the resulting executable
32 to be covered by the GNU General
Public License.
33 This exception does
not however invalidate any other reasons why
34 the executable file might be covered by the GNU General
Public License.
*/
38 #ifndef __USER_LABEL_PREFIX__
39 #error __USER_LABEL_PREFIX__
not defined
44 #define
TYPE(x
) .
type SYM
(x
),function
45 #define
SIZE(x
) .
size SYM
(x
), .
- SYM
(x
)
52 #define
RET mov pc
, lr
54 /* ANSI concatenation macros.
*/
56 #define CONCAT1
(a
, b
) CONCAT2
(a
, b
)
57 #define CONCAT2
(a
, b
) a ## b
59 /* Use the right prefix for
global labels.
*/
61 #define SYM
(x
) CONCAT1
(__USER_LABEL_PREFIX__
, x
)
63 work .req r4 @ XXXX is
this safe
?
77 .globl SYM
(__udivsi3
)
91 @ Load the constant
0x10000000 into our work register
95 @ Unless the divisor is very big
, shift it up
in multiples of
96 @ four bits
, since
this is the amount of unwinding
in the main
97 @ division
loop. Continue shifting until the divisor is
98 @ larger than the dividend.
101 cmp divisor
, dividend
108 @ Set work to
0x80000000
111 @ For very big divisors
, we must shift it a bit at a time
, or
112 @ we will be
in danger of overflowing.
115 cmp divisor
, dividend
122 @
Test for possible subtractions
, and note which bits
123 @ are done
in the result. On the final pass
, this may subtract
124 @ too much from the dividend
, but the result will be ok
, since the
125 @
"bit" will have been shifted
out at the bottom.
126 cmp dividend
, divisor
128 sub dividend
, dividend
, divisor
129 orr result
, result
, curbit
131 lsr work
, divisor
, #
1
134 sub dividend
, dividend
, work
138 lsr work
, divisor
, #
2
141 sub dividend
, dividend
, work
145 lsr work
, divisor
, #
3
148 sub dividend
, dividend
, work
152 cmp dividend
, #
0 @ Early termination
?
154 lsr curbit
, #
4 @ No
, any more bits to do
?
165 bl SYM
(__div0
) __PLT__
166 mov r0
, #
0 @ about as wrong as it could be
171 #endif
/* L_udivsi3
*/
185 .globl SYM
(__umodsi3
)
193 cmp dividend
, divisor
198 @ Load the constant
0x10000000 into our work register
203 @ Unless the divisor is very big
, shift it up
in multiples of
204 @ four bits
, since
this is the amount of unwinding
in the main
205 @ division
loop. Continue shifting until the divisor is
206 @ larger than the dividend.
209 cmp divisor
, dividend
216 @ Set work to
0x80000000
219 @ For very big divisors
, we must shift it a bit at a time
, or
220 @ we will be
in danger of overflowing.
223 cmp divisor
, dividend
230 @
Test for possible subtractions. On the final pass
, this may
231 @ subtract too much from the dividend
, so keep track of which
232 @ subtractions are done
, we can fix them up afterwards...
234 cmp dividend
, divisor
236 sub dividend
, dividend
, divisor
238 lsr work
, divisor
, #
1
241 sub dividend
, dividend
, work
248 lsr work
, divisor
, #
2
251 sub dividend
, dividend
, work
258 lsr work
, divisor
, #
3
261 sub dividend
, dividend
, work
269 cmp dividend
, #
0 @ Early termination
?
271 lsr curbit
, #
4 @ No
, any more bits to do
?
277 @ Any subtractions that we should
not have done will be recorded
in
278 @ the top three bits of
"overdone". Exactly which were
not needed
279 @ are governed by the position of the bit
, stored
in ip.
280 @ If we terminated early
, because dividend became zero
,
281 @ then none of the below will match
, since the bit
in ip will
not be
282 @
in the bottom nibble.
289 RET @ No fixups needed
296 lsr work
, divisor
, #
3
297 add dividend
, dividend
, work
304 lsr work
, divisor
, #
2
305 add dividend
, dividend
, work
312 lsr work
, divisor
, #
1
313 add dividend
, dividend
, work
320 bl SYM
(__div0
) __PLT__
321 mov r0
, #
0 @ about as wrong as it could be
326 #endif
/* L_umodsi3
*/
340 .globl SYM
(__divsi3
)
350 eor work
, divisor @ Save the sign of the result.
356 neg divisor
, divisor @ Loops below use unsigned.
360 neg dividend
, dividend
362 cmp dividend
, divisor
368 @ Unless the divisor is very big
, shift it up
in multiples of
369 @ four bits
, since
this is the amount of unwinding
in the main
370 @ division
loop. Continue shifting until the divisor is
371 @ larger than the dividend.
374 cmp divisor
, dividend
381 @ For very big divisors
, we must shift it a bit at a time
, or
382 @ we will be
in danger of overflowing.
387 cmp divisor
, dividend
394 @
Test for possible subtractions
, and note which bits
395 @ are done
in the result. On the final pass
, this may subtract
396 @ too much from the dividend
, but the result will be ok
, since the
397 @
"bit" will have been shifted
out at the bottom.
398 cmp dividend
, divisor
400 sub dividend
, dividend
, divisor
401 orr result
, result
, curbit
403 lsr work
, divisor
, #
1
406 sub dividend
, dividend
, work
410 lsr work
, divisor
, #
2
413 sub dividend
, dividend
, work
415 orr result
, result
, work
417 lsr work
, divisor
, #
3
420 sub dividend
, dividend
, work
422 orr result
, result
, work
424 cmp dividend
, #
0 @ Early termination
?
426 lsr curbit
, #
4 @ No
, any more bits to do
?
443 bl SYM
(__div0
) __PLT__
444 mov r0
, #
0 @ about as wrong as it could be
449 #endif
/* L_divsi3
*/
463 .globl SYM
(__modsi3
)
472 neg divisor
, divisor @ Loops below use unsigned.
475 @ Need to save the sign of the dividend
, unfortunately
, we need
476 @ ip later on. Must do
this after saving the original value of
477 @ the work register
, because we will
pop this value off first.
481 neg dividend
, dividend
483 cmp dividend
, divisor
488 @ Unless the divisor is very big
, shift it up
in multiples of
489 @ four bits
, since
this is the amount of unwinding
in the main
490 @ division
loop. Continue shifting until the divisor is
491 @ larger than the dividend.
494 cmp divisor
, dividend
501 @ Set work to
0x80000000
504 @ For very big divisors
, we must shift it a bit at a time
, or
505 @ we will be
in danger of overflowing.
508 cmp divisor
, dividend
515 @
Test for possible subtractions. On the final pass
, this may
516 @ subtract too much from the dividend
, so keep track of which
517 @ subtractions are done
, we can fix them up afterwards...
519 cmp dividend
, divisor
521 sub dividend
, dividend
, divisor
523 lsr work
, divisor
, #
1
526 sub dividend
, dividend
, work
533 lsr work
, divisor
, #
2
536 sub dividend
, dividend
, work
543 lsr work
, divisor
, #
3
546 sub dividend
, dividend
, work
554 cmp dividend
, #
0 @ Early termination
?
556 lsr curbit
, #
4 @ No
, any more bits to do
?
562 @ Any subtractions that we should
not have done will be recorded
in
563 @ the top three bits of
"overdone". Exactly which were
not needed
564 @ are governed by the position of the bit
, stored
in ip.
565 @ If we terminated early
, because dividend became zero
,
566 @ then none of the below will match
, since the bit
in ip will
not be
567 @
in the bottom nibble.
578 lsr work
, divisor
, #
3
579 add dividend
, dividend
, work
586 lsr work
, divisor
, #
2
587 add dividend
, dividend
, work
594 lsr work
, divisor
, #
1
595 add dividend
, dividend
, work
600 neg dividend
, dividend
607 bl SYM
(__div0
) __PLT__
608 mov r0
, #
0 @ about as wrong as it could be
613 #endif
/* L_modsi3
*/
626 #endif
/* L_divmodsi_tools
*/
631 /* These labels
& instructions are used by the Arm
/Thumb interworking code.
632 The address of function to be called is loaded
into a register
and then
633 one of these labels is called via a
BL instruction.
This puts the
634 return address
into the link register with the bottom bit set
, and the
635 code here switches to the correct mode before executing the function.
*/
640 .
macro call_via register
641 .globl SYM
(_call_via_
\register
)
642 TYPE (_call_via_
\register
)
644 SYM
(_call_via_
\register
):
648 SIZE (_call_via_
\register
)
667 #endif
/* L_call_via_rX
*/
669 #ifdef L_interwork_call_via_rX
671 /* These labels
& instructions are used by the Arm
/Thumb interworking code
,
672 when the target address is
in an unknown instruction set. The address
673 of function to be called is loaded
into a register
and then one of these
674 labels is called via a
BL instruction.
This puts the return address
675 into the link register with the bottom bit set
, and the code here
676 switches to the correct mode before executing the function. Unfortunately
677 the target code cannot be relied upon to return via a
BX instruction
, so
678 instead we have to store the resturn address on the stack
and allow the
679 called function to return here instead. Upon return we recover the real
680 return address
and use a
BX to get back to Thumb mode.
*/
691 .
macro interwork register
694 .globl SYM
(_interwork_call_via_
\register
)
695 TYPE (_interwork_call_via_
\register
)
697 SYM
(_interwork_call_via_
\register
):
702 .globl .Lchange_
\register
706 adreq lr
, _arm_return
709 SIZE (_interwork_call_via_
\register
)
727 /* The lr case has to be handled a little differently...
*/
729 .globl SYM
(_interwork_call_via_lr
)
730 TYPE (_interwork_call_via_lr
)
732 SYM
(_interwork_call_via_lr
):
742 adreq lr
, _arm_return
745 SIZE (_interwork_call_via_lr
)
747 #endif
/* L_interwork_call_via_rX
*/