1 @ libgcc routines for ARM cpu.
2 @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
4 /* Copyright 1995, 1996, 1998, 1999, 2000 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 into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
20 This file is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; see the file COPYING. If not, write to
27 the Free Software Foundation, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. */
29 /* ------------------------------------------------------------------------ */
31 /* We need to know what prefix to add to function names. */
33 #ifndef __USER_LABEL_PREFIX__
34 #error __USER_LABEL_PREFIX__ not defined
37 /* ANSI concatenation macros. */
39 #define CONCAT1(a, b) CONCAT2(a, b)
40 #define CONCAT2(a, b) a ## b
42 /* Use the right prefix for global labels. */
44 #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
48 #define __PLT__ /* Not supported in Thumb assembler (for now). */
52 #define TYPE(x) .type SYM(x),function
53 #define SIZE(x) .size SYM(x), . - SYM(x)
62 /* Function end macros. Variants for 26 bit APCS and interworking. */
65 # define RET movs pc, lr
66 # define RETc(x) mov##x##s pc, lr
71 bl SYM (__div0) __PLT__
72 mov r0, #0 @ About as wrong as it could be.
76 # ifdef __THUMB_INTERWORK__
78 # define RETc(x) bx##x lr
83 mov r0, #0 @ About as wrong as it could be.
90 bl SYM (__div0) __PLT__
91 mov r0, #0 @ About as wrong as it could be.
96 # define RET mov pc, lr
97 # define RETc(x) mov##x pc, lr
102 mov r0, #0 @ About as wrong as it could be.
108 bl SYM (__div0) __PLT__
109 mov r0, #0 @ About as wrong as it could be.
126 .macro THUMB_FUNC_START name
133 /* Function start macros. Variants for ARM and Thumb. */
136 #define THUMB_FUNC .thumb_func
137 #define THUMB_CODE .force_thumb
143 .macro FUNC_START name
153 /* Register aliases. */
155 work .req r4 @ XXXX is this safe ?
166 /* ------------------------------------------------------------------------ */
167 /* Bodies of the divsion and modulo routines. */
168 /* ------------------------------------------------------------------------ */
169 .macro ARM_DIV_MOD_BODY modulo
171 @ Unless the divisor is very big, shift it up in multiples of
172 @ four bits, since this is the amount of unwinding in the main
173 @ division loop. Continue shifting until the divisor is
174 @ larger than the dividend.
175 cmp divisor, #0x10000000
176 cmplo divisor, dividend
177 movlo divisor, divisor, lsl #4
178 movlo curbit, curbit, lsl #4
182 @ For very big divisors, we must shift it a bit at a time, or
183 @ we will be in danger of overflowing.
184 cmp divisor, #0x80000000
185 cmplo divisor, dividend
186 movlo divisor, divisor, lsl #1
187 movlo curbit, curbit, lsl #1
191 @ Test for possible subtractions. On the final pass, this may
192 @ subtract too much from the dividend ...
195 @ ... so keep track of which subtractions are done in OVERDONE.
196 @ We can fix them up afterwards.
198 cmp dividend, divisor
199 subhs dividend, dividend, divisor
200 cmp dividend, divisor, lsr #1
201 subhs dividend, dividend, divisor, lsr #1
202 orrhs overdone, overdone, curbit, ror #1
203 cmp dividend, divisor, lsr #2
204 subhs dividend, dividend, divisor, lsr #2
205 orrhs overdone, overdone, curbit, ror #2
206 cmp dividend, divisor, lsr #3
207 subhs dividend, dividend, divisor, lsr #3
208 orrhs overdone, overdone, curbit, ror #3
211 @ ... so keep track of which subtractions are done in RESULT.
212 @ The result will be ok, since the "bit" will have been
213 @ shifted out at the bottom.
214 cmp dividend, divisor
215 subhs dividend, dividend, divisor
216 orrhs result, result, curbit
217 cmp dividend, divisor, lsr #1
218 subhs dividend, dividend, divisor, lsr #1
219 orrhs result, result, curbit, lsr #1
220 cmp dividend, divisor, lsr #2
221 subhs dividend, dividend, divisor, lsr #2
222 orrhs result, result, curbit, lsr #2
223 cmp dividend, divisor, lsr #3
224 subhs dividend, dividend, divisor, lsr #3
225 orrhs result, result, curbit, lsr #3
228 cmp dividend, #0 @ Early termination?
229 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
230 movne divisor, divisor, lsr #4
234 LSYM(Lfixup_dividend):
235 @ Any subtractions that we should not have done will be recorded in
236 @ the top three bits of OVERDONE. Exactly which were not needed
237 @ are governed by the position of the bit, stored in IP.
238 ands overdone, overdone, #0xe0000000
239 @ If we terminated early, because dividend became zero, then the
240 @ bit in ip will not be in the bottom nibble, and we should not
241 @ perform the additions below. We must test for this though
242 @ (rather relying upon the TSTs to prevent the additions) since
243 @ the bit in ip could be in the top two bits which might then match
244 @ with one of the smaller RORs.
246 beq LSYM(Lgot_result)
247 tst overdone, ip, ror #3
248 addne dividend, dividend, divisor, lsr #3
249 tst overdone, ip, ror #2
250 addne dividend, dividend, divisor, lsr #2
251 tst overdone, ip, ror #1
252 addne dividend, dividend, divisor, lsr #1
257 /* ------------------------------------------------------------------------ */
258 .macro THUMB_DIV_MOD_BODY modulo
259 @ Load the constant 0x10000000 into our work register.
263 @ Unless the divisor is very big, shift it up in multiples of
264 @ four bits, since this is the amount of unwinding in the main
265 @ division loop. Continue shifting until the divisor is
266 @ larger than the dividend.
269 cmp divisor, dividend
275 @ Set work to 0x80000000
278 @ For very big divisors, we must shift it a bit at a time, or
279 @ we will be in danger of overflowing.
282 cmp divisor, dividend
288 @ Test for possible subtractions ...
290 @ ... On the final pass, this may subtract too much from the dividend,
291 @ so keep track of which subtractions are done, we can fix them up
294 cmp dividend, divisor
296 sub dividend, dividend, divisor
298 lsr work, divisor, #1
301 sub dividend, dividend, work
308 lsr work, divisor, #2
311 sub dividend, dividend, work
318 lsr work, divisor, #3
321 sub dividend, dividend, work
330 @ ... and note which bits are done in the result. On the final pass,
331 @ this may subtract too much from the dividend, but the result will be ok,
332 @ since the "bit" will have been shifted out at the bottom.
333 cmp dividend, divisor
335 sub dividend, dividend, divisor
336 orr result, result, curbit
338 lsr work, divisor, #1
341 sub dividend, dividend, work
345 lsr work, divisor, #2
348 sub dividend, dividend, work
352 lsr work, divisor, #3
355 sub dividend, dividend, work
361 cmp dividend, #0 @ Early termination?
363 lsr curbit, #4 @ No, any more bits to do?
369 @ Any subtractions that we should not have done will be recorded in
370 @ the top three bits of "overdone". Exactly which were not needed
371 @ are governed by the position of the bit, stored in ip.
375 beq LSYM(Lgot_result)
377 @ If we terminated early, because dividend became zero, then the
378 @ bit in ip will not be in the bottom nibble, and we should not
379 @ perform the additions below. We must test for this though
380 @ (rather relying upon the TSTs to prevent the additions) since
381 @ the bit in ip could be in the top two bits which might then match
382 @ with one of the smaller RORs.
386 beq LSYM(Lgot_result)
393 lsr work, divisor, #3
401 lsr work, divisor, #2
408 beq LSYM(Lgot_result)
409 lsr work, divisor, #1
414 /* ------------------------------------------------------------------------ */
415 /* Start of the Real Functions */
416 /* ------------------------------------------------------------------------ */
429 cmp dividend, divisor
430 blo LSYM(Lgot_result)
438 #else /* ARM version. */
444 cmp dividend, divisor
445 blo LSYM(Lgot_result)
452 #endif /* ARM version */
456 #endif /* L_udivsi3 */
457 /* ------------------------------------------------------------------------ */
467 cmp dividend, divisor
479 #else /* ARM version. */
484 cmpne dividend, divisor
493 #endif /* ARM version. */
497 #endif /* L_umodsi3 */
498 /* ------------------------------------------------------------------------ */
509 eor work, divisor @ Save the sign of the result.
515 neg divisor, divisor @ Loops below use unsigned.
519 neg dividend, dividend
521 cmp dividend, divisor
522 blo LSYM(Lgot_result)
535 #else /* ARM version. */
537 eor ip, dividend, divisor @ Save the sign of the result.
541 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
544 rsbmi dividend, dividend, #0
545 cmp dividend, divisor
546 blo LSYM(Lgot_result)
555 #endif /* ARM version */
559 #endif /* L_divsi3 */
560 /* ------------------------------------------------------------------------ */
571 neg divisor, divisor @ Loops below use unsigned.
574 @ Need to save the sign of the dividend, unfortunately, we need
575 @ work later on. Must do this after saving the original value of
576 @ the work register, because we will pop this value off first.
580 neg dividend, dividend
582 cmp dividend, divisor
583 blo LSYM(Lgot_result)
590 neg dividend, dividend
595 #else /* ARM version. */
598 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
600 @ Need to save the sign of the dividend, unfortunately, we need
601 @ ip later on; this is faster than pushing lr and using that.
602 str dividend, [sp, #-4]!
603 cmp dividend, #0 @ Test dividend against zero
604 rsbmi dividend, dividend, #0 @ If negative make positive
605 cmp dividend, divisor @ else if zero return zero
606 blo LSYM(Lgot_result) @ if smaller return dividend
613 rsbmi dividend, dividend, #0
616 #endif /* ARM version */
620 #endif /* L_modsi3 */
621 /* ------------------------------------------------------------------------ */
630 #endif /* L_divmodsi_tools */
631 /* ------------------------------------------------------------------------ */
633 @ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
635 /* Constants taken from <asm/unistd.h> and <asm/signal.h> */
637 #define __NR_SYSCALL_BASE 0x900000
638 #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
639 #define __NR_kill (__NR_SYSCALL_BASE+ 37)
646 ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
649 #ifdef __THUMB_INTERWORK__
653 ldmfd sp!, {r1, pc}RETCOND
658 #endif /* L_dvmd_lnx */
659 /* ------------------------------------------------------------------------ */
660 /* These next two sections are here despite the fact that they contain Thumb
661 assembler because their presence allows interworked code to be linked even
662 when the GCC library is this one. */
664 /* Do not build the interworking functions when the target architecture does
665 not support Thumb instructions. (This can be a multilib option). */
666 #if defined L_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
668 /* These labels & instructions are used by the Arm/Thumb interworking code.
669 The address of function to be called is loaded into a register and then
670 one of these labels is called via a BL instruction. This puts the
671 return address into the link register with the bottom bit set, and the
672 code here switches to the correct mode before executing the function. */
678 .macro call_via register
679 THUMB_FUNC_START _call_via_\register
684 SIZE (_call_via_\register)
703 #endif /* L_call_via_rX */
704 /* ------------------------------------------------------------------------ */
705 /* Do not build the interworking functions when the target architecture does
706 not support Thumb instructions. (This can be a multilib option). */
707 #if defined L_interwork_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
709 /* These labels & instructions are used by the Arm/Thumb interworking code,
710 when the target address is in an unknown instruction set. The address
711 of function to be called is loaded into a register and then one of these
712 labels is called via a BL instruction. This puts the return address
713 into the link register with the bottom bit set, and the code here
714 switches to the correct mode before executing the function. Unfortunately
715 the target code cannot be relied upon to return via a BX instruction, so
716 instead we have to store the resturn address on the stack and allow the
717 called function to return here instead. Upon return we recover the real
718 return address and use a BX to get back to Thumb mode. */
730 .macro interwork register
733 THUMB_FUNC_START _interwork_call_via_\register
739 .globl .Lchange_\register
743 adreq lr, _arm_return
746 SIZE (_interwork_call_via_\register)
764 /* The LR case has to be handled a little differently... */
767 THUMB_FUNC_START _interwork_call_via_lr
778 adreq lr, _arm_return
781 SIZE (_interwork_call_via_lr)
783 #endif /* L_interwork_call_via_rX */