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)
60 /* Function end macros. Variants for 26 bit APCS and interworking. */
63 # define RET movs pc, lr
64 # define RETc(x) mov##x##s pc, lr
69 bl SYM (__div0) __PLT__
70 mov r0, #0 @ About as wrong as it could be.
74 # ifdef __THUMB_INTERWORK__
76 # define RETc(x) bx##x lr
81 mov r0, #0 @ About as wrong as it could be.
88 bl SYM (__div0) __PLT__
89 mov r0, #0 @ About as wrong as it could be.
94 # define RET mov pc, lr
95 # define RETc(x) mov##x pc, lr
100 mov r0, #0 @ About as wrong as it could be.
106 bl SYM (__div0) __PLT__
107 mov r0, #0 @ About as wrong as it could be.
124 .macro THUMB_FUNC_START name
131 /* Function start macros. Variants for ARM and Thumb. */
134 #define THUMB_FUNC .thumb_func
135 #define THUMB_CODE .force_thumb
141 .macro FUNC_START name
151 /* Register aliases. */
153 work .req r4 @ XXXX is this safe ?
164 /* ------------------------------------------------------------------------ */
165 /* Bodies of the divsion and modulo routines. */
166 /* ------------------------------------------------------------------------ */
167 .macro ARM_DIV_MOD_BODY modulo
169 @ Unless the divisor is very big, shift it up in multiples of
170 @ four bits, since this is the amount of unwinding in the main
171 @ division loop. Continue shifting until the divisor is
172 @ larger than the dividend.
173 cmp divisor, #0x10000000
174 cmplo divisor, dividend
175 movlo divisor, divisor, lsl #4
176 movlo curbit, curbit, lsl #4
180 @ For very big divisors, we must shift it a bit at a time, or
181 @ we will be in danger of overflowing.
182 cmp divisor, #0x80000000
183 cmplo divisor, dividend
184 movlo divisor, divisor, lsl #1
185 movlo curbit, curbit, lsl #1
189 @ Test for possible subtractions. On the final pass, this may
190 @ subtract too much from the dividend ...
193 @ ... so keep track of which subtractions are done in OVERDONE.
194 @ We can fix them up afterwards.
196 cmp dividend, divisor
197 subhs dividend, dividend, divisor
198 cmp dividend, divisor, lsr #1
199 subhs dividend, dividend, divisor, lsr #1
200 orrhs overdone, overdone, curbit, ror #1
201 cmp dividend, divisor, lsr #2
202 subhs dividend, dividend, divisor, lsr #2
203 orrhs overdone, overdone, curbit, ror #2
204 cmp dividend, divisor, lsr #3
205 subhs dividend, dividend, divisor, lsr #3
206 orrhs overdone, overdone, curbit, ror #3
209 @ ... so keep track of which subtractions are done in RESULT.
210 @ The result will be ok, since the "bit" will have been
211 @ shifted out at the bottom.
212 cmp dividend, divisor
213 subhs dividend, dividend, divisor
214 orrhs result, result, curbit
215 cmp dividend, divisor, lsr #1
216 subhs dividend, dividend, divisor, lsr #1
217 orrhs result, result, curbit, lsr #1
218 cmp dividend, divisor, lsr #2
219 subhs dividend, dividend, divisor, lsr #2
220 orrhs result, result, curbit, lsr #2
221 cmp dividend, divisor, lsr #3
222 subhs dividend, dividend, divisor, lsr #3
223 orrhs result, result, curbit, lsr #3
226 cmp dividend, #0 @ Early termination?
227 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
228 movne divisor, divisor, lsr #4
233 @ Any subtractions that we should not have done will be recorded in
234 @ the top three bits of OVERDONE. Exactly which were not needed
235 @ are governed by the position of the bit, stored in IP.
236 ands overdone, overdone, #0xe0000000
237 @ If we terminated early, because dividend became zero, then the
238 @ bit in ip will not be in the bottom nibble, and we should not
239 @ perform the additions below. We must test for this though
240 @ (rather relying upon the TSTs to prevent the additions) since
241 @ the bit in ip could be in the top two bits which might then match
242 @ with one of the smaller RORs.
245 tst overdone, ip, ror #3
246 addne dividend, dividend, divisor, lsr #3
247 tst overdone, ip, ror #2
248 addne dividend, dividend, divisor, lsr #2
249 tst overdone, ip, ror #1
250 addne dividend, dividend, divisor, lsr #1
255 /* ------------------------------------------------------------------------ */
256 .macro THUMB_DIV_MOD_BODY modulo
257 @ Load the constant 0x10000000 into our work register.
261 @ Unless the divisor is very big, shift it up in multiples of
262 @ four bits, since this is the amount of unwinding in the main
263 @ division loop. Continue shifting until the divisor is
264 @ larger than the dividend.
267 cmp divisor, dividend
273 @ Set work to 0x80000000
276 @ For very big divisors, we must shift it a bit at a time, or
277 @ we will be in danger of overflowing.
280 cmp divisor, dividend
286 @ Test for possible subtractions ...
288 @ ... On the final pass, this may subtract too much from the dividend,
289 @ so keep track of which subtractions are done, we can fix them up
292 cmp dividend, divisor
294 sub dividend, dividend, divisor
296 lsr work, divisor, #1
299 sub dividend, dividend, work
306 lsr work, divisor, #2
309 sub dividend, dividend, work
316 lsr work, divisor, #3
319 sub dividend, dividend, work
328 @ ... and note which bits are done in the result. On the final pass,
329 @ this may subtract too much from the dividend, but the result will be ok,
330 @ since the "bit" will have been shifted out at the bottom.
331 cmp dividend, divisor
333 sub dividend, dividend, divisor
334 orr result, result, curbit
336 lsr work, divisor, #1
339 sub dividend, dividend, work
343 lsr work, divisor, #2
346 sub dividend, dividend, work
350 lsr work, divisor, #3
353 sub dividend, dividend, work
359 cmp dividend, #0 @ Early termination?
361 lsr curbit, #4 @ No, any more bits to do?
367 @ Any subtractions that we should not have done will be recorded in
368 @ the top three bits of "overdone". Exactly which were not needed
369 @ are governed by the position of the bit, stored in ip.
375 @ If we terminated early, because dividend became zero, then the
376 @ bit in ip will not be in the bottom nibble, and we should not
377 @ perform the additions below. We must test for this though
378 @ (rather relying upon the TSTs to prevent the additions) since
379 @ the bit in ip could be in the top two bits which might then match
380 @ with one of the smaller RORs.
391 lsr work, divisor, #3
399 lsr work, divisor, #2
407 lsr work, divisor, #1
412 /* ------------------------------------------------------------------------ */
413 /* Start of the Real Functions */
414 /* ------------------------------------------------------------------------ */
427 cmp dividend, divisor
436 #else /* ARM version. */
442 cmp dividend, divisor
450 #endif /* ARM version */
454 #endif /* L_udivsi3 */
455 /* ------------------------------------------------------------------------ */
465 cmp dividend, divisor
477 #else /* ARM version. */
482 cmpne dividend, divisor
491 #endif /* ARM version. */
495 #endif /* L_umodsi3 */
496 /* ------------------------------------------------------------------------ */
507 eor work, divisor @ Save the sign of the result.
513 neg divisor, divisor @ Loops below use unsigned.
517 neg dividend, dividend
519 cmp dividend, divisor
533 #else /* ARM version. */
535 eor ip, dividend, divisor @ Save the sign of the result.
539 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
542 rsbmi dividend, dividend, #0
543 cmp dividend, divisor
553 #endif /* ARM version */
557 #endif /* L_divsi3 */
558 /* ------------------------------------------------------------------------ */
569 neg divisor, divisor @ Loops below use unsigned.
572 @ Need to save the sign of the dividend, unfortunately, we need
573 @ work later on. Must do this after saving the original value of
574 @ the work register, because we will pop this value off first.
578 neg dividend, dividend
580 cmp dividend, divisor
588 neg dividend, dividend
593 #else /* ARM version. */
596 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
598 @ Need to save the sign of the dividend, unfortunately, we need
599 @ ip later on; this is faster than pushing lr and using that.
600 str dividend, [sp, #-4]!
601 cmp dividend, #0 @ Test dividend against zero
602 rsbmi dividend, dividend, #0 @ If negative make positive
603 cmp dividend, divisor @ else if zero return zero
604 blo Lgot_result @ if smaller return dividend
611 rsbmi dividend, dividend, #0
614 #endif /* ARM version */
618 #endif /* L_modsi3 */
619 /* ------------------------------------------------------------------------ */
628 #endif /* L_divmodsi_tools */
629 /* ------------------------------------------------------------------------ */
631 @ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
633 #include <asm/unistd.h>
635 #define SIGFPE 8 @ cant use <asm/signal.h> as it
636 @ contains too much C rubbish
642 ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
645 #ifdef __THUMB_INTERWORK__
649 ldmfd sp!, {r1, pc}RETCOND
654 #endif /* L_dvmd_lnx */
655 /* ------------------------------------------------------------------------ */
656 /* These next two sections are here despite the fact that they contain Thumb
657 assembler because their presence allows interworked code to be linked even
658 when the GCC library is this one. */
660 /* Do not build the interworking functions when the target architecture does
661 not support Thumb instructions. (This can be a multilib option). */
662 #if defined L_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
664 /* These labels & instructions are used by the Arm/Thumb interworking code.
665 The address of function to be called is loaded into a register and then
666 one of these labels is called via a BL instruction. This puts the
667 return address into the link register with the bottom bit set, and the
668 code here switches to the correct mode before executing the function. */
674 .macro call_via register
675 THUMB_FUNC_START _call_via_\register
680 SIZE (_call_via_\register)
699 #endif /* L_call_via_rX */
700 /* ------------------------------------------------------------------------ */
701 /* Do not build the interworking functions when the target architecture does
702 not support Thumb instructions. (This can be a multilib option). */
703 #if defined L_interwork_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
705 /* These labels & instructions are used by the Arm/Thumb interworking code,
706 when the target address is in an unknown instruction set. The address
707 of function to be called is loaded into a register and then one of these
708 labels is called via a BL instruction. This puts the return address
709 into the link register with the bottom bit set, and the code here
710 switches to the correct mode before executing the function. Unfortunately
711 the target code cannot be relied upon to return via a BX instruction, so
712 instead we have to store the resturn address on the stack and allow the
713 called function to return here instead. Upon return we recover the real
714 return address and use a BX to get back to Thumb mode. */
726 .macro interwork register
729 THUMB_FUNC_START _interwork_call_via_\register
735 .globl .Lchange_\register
739 adreq lr, _arm_return
742 SIZE (_interwork_call_via_\register)
760 /* The LR case has to be handled a little differently... */
763 THUMB_FUNC_START _interwork_call_via_lr
774 adreq lr, _arm_return
777 SIZE (_interwork_call_via_lr)
779 #endif /* L_interwork_call_via_rX */