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 */