diff options
Diffstat (limited to 'contrib/gcc/config/arm/lib1funcs.asm')
-rw-r--r-- | contrib/gcc/config/arm/lib1funcs.asm | 668 |
1 files changed, 423 insertions, 245 deletions
diff --git a/contrib/gcc/config/arm/lib1funcs.asm b/contrib/gcc/config/arm/lib1funcs.asm index ec706ec..e72af6c 100644 --- a/contrib/gcc/config/arm/lib1funcs.asm +++ b/contrib/gcc/config/arm/lib1funcs.asm @@ -1,7 +1,8 @@ @ libgcc routines for ARM cpu. @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) -/* Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc. +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004 + Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -51,74 +52,117 @@ Boston, MA 02111-1307, USA. */ #endif #define TYPE(x) .type SYM(x),function #define SIZE(x) .size SYM(x), . - SYM(x) +#define LSYM(x) .x #else #define __PLT__ #define TYPE(x) #define SIZE(x) +#define LSYM(x) x #endif /* Function end macros. Variants for 26 bit APCS and interworking. */ +@ This selects the minimum architecture level required. +#define __ARM_ARCH__ 3 + +#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \ + || defined(__ARM_ARCH_4T__) +/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with + long multiply instructions. That includes v3M. */ +# undef __ARM_ARCH__ +# define __ARM_ARCH__ 4 +#endif + +#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5TE__) +# undef __ARM_ARCH__ +# define __ARM_ARCH__ 5 +#endif + +/* How to return from a function call depends on the architecture variant. */ + #ifdef __APCS_26__ + # define RET movs pc, lr # define RETc(x) mov##x##s pc, lr -# define RETCOND ^ + +#elif (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__) + +# define RET bx lr +# define RETc(x) bx##x lr + +# if (__ARM_ARCH__ == 4) \ + && (defined(__thumb__) || defined(__THUMB_INTERWORK__)) +# define __INTERWORKING__ +# endif + +#else + +# define RET mov pc, lr +# define RETc(x) mov##x pc, lr + +#endif + +/* Don't pass dirn, it's there just to get token pasting right. */ + +.macro RETLDM regs=, cond=, dirn=ia +#ifdef __APCS_26__ + .ifc "\regs","" + ldm\cond\dirn sp!, {pc}^ + .else + ldm\cond\dirn sp!, {\regs, pc}^ + .endif +#elif defined (__INTERWORKING__) + .ifc "\regs","" + ldr\cond lr, [sp], #4 + .else + ldm\cond\dirn sp!, {\regs, lr} + .endif + bx\cond lr +#else + .ifc "\regs","" + ldr\cond pc, [sp], #4 + .else + ldm\cond\dirn sp!, {\regs, pc} + .endif +#endif +.endm + + .macro ARM_LDIV0 -Ldiv0: +LSYM(Ldiv0): str lr, [sp, #-4]! bl SYM (__div0) __PLT__ mov r0, #0 @ About as wrong as it could be. - ldmia sp!, {pc}^ + RETLDM .endm -#else -# ifdef __THUMB_INTERWORK__ -# define RET bx lr -# define RETc(x) bx##x lr + + .macro THUMB_LDIV0 -Ldiv0: +LSYM(Ldiv0): push { lr } bl SYM (__div0) mov r0, #0 @ About as wrong as it could be. +#if defined (__INTERWORKING__) pop { r1 } bx r1 -.endm -.macro ARM_LDIV0 -Ldiv0: - str lr, [sp, #-4]! - bl SYM (__div0) __PLT__ - mov r0, #0 @ About as wrong as it could be. - ldr lr, [sp], #4 - bx lr -.endm -# else -# define RET mov pc, lr -# define RETc(x) mov##x pc, lr -.macro THUMB_LDIV0 -Ldiv0: - push { lr } - bl SYM (__div0) - mov r0, #0 @ About as wrong as it could be. +#else pop { pc } -.endm -.macro ARM_LDIV0 -Ldiv0: - str lr, [sp, #-4]! - bl SYM (__div0) __PLT__ - mov r0, #0 @ About as wrong as it could be. - ldmia sp!, {pc} -.endm -# endif -# define RETCOND #endif +.endm .macro FUNC_END name -Ldiv0: + SIZE (__\name) +.endm + +.macro DIV_FUNC_END name +LSYM(Ldiv0): #ifdef __thumb__ THUMB_LDIV0 #else ARM_LDIV0 #endif - SIZE (__\name) + FUNC_END \name .endm .macro THUMB_FUNC_START name @@ -147,7 +191,37 @@ SYM (\name): THUMB_FUNC SYM (__\name): .endm - + +/* Special function that will always be coded in ARM assembly, even if + in Thumb-only compilation. */ + +#if defined(__thumb__) && !defined(__THUMB_INTERWORK__) +.macro ARM_FUNC_START name + FUNC_START \name + bx pc + nop + .arm +_L__\name: /* A hook to tell gdb that we've switched to ARM */ +.endm +#define EQUIV .thumb_set +#else +.macro ARM_FUNC_START name + .text + .globl SYM (__\name) + TYPE (__\name) + .align 0 + .arm +SYM (__\name): +.endm +#define EQUIV .set +#endif + +.macro ARM_FUNC_ALIAS new old + .globl SYM (__\new) + EQUIV SYM (__\new), SYM (__\old) +.endm + +#ifdef __thumb__ /* Register aliases. */ work .req r4 @ XXXX is this safe ? @@ -156,133 +230,212 @@ divisor .req r1 overdone .req r2 result .req r2 curbit .req r3 +#endif +#if 0 ip .req r12 sp .req r13 lr .req r14 pc .req r15 +#endif /* ------------------------------------------------------------------------ */ -/* Bodies of the divsion and modulo routines. */ +/* Bodies of the division and modulo routines. */ /* ------------------------------------------------------------------------ */ -.macro ARM_DIV_MOD_BODY modulo -Loop1: +.macro ARM_DIV_BODY dividend, divisor, result, curbit + +#if __ARM_ARCH__ >= 5 + + clz \curbit, \divisor + clz \result, \dividend + sub \result, \curbit, \result + mov \curbit, #1 + mov \divisor, \divisor, lsl \result + mov \curbit, \curbit, lsl \result + mov \result, #0 + +#else + + @ Initially shift the divisor left 3 bits if possible, + @ set curbit accordingly. This allows for curbit to be located + @ at the left end of each 4 bit nibbles in the division loop + @ to save one loop in most cases. + tst \divisor, #0xe0000000 + moveq \divisor, \divisor, lsl #3 + moveq \curbit, #8 + movne \curbit, #1 + @ Unless the divisor is very big, shift it up in multiples of @ four bits, since this is the amount of unwinding in the main @ division loop. Continue shifting until the divisor is @ larger than the dividend. - cmp divisor, #0x10000000 - cmplo divisor, dividend - movlo divisor, divisor, lsl #4 - movlo curbit, curbit, lsl #4 - blo Loop1 +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + movlo \curbit, \curbit, lsl #4 + blo 1b -Lbignum: @ For very big divisors, we must shift it a bit at a time, or @ we will be in danger of overflowing. - cmp divisor, #0x80000000 - cmplo divisor, dividend - movlo divisor, divisor, lsl #1 - movlo curbit, curbit, lsl #1 - blo Lbignum +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + movlo \curbit, \curbit, lsl #1 + blo 1b + + mov \result, #0 + +#endif + + @ Division loop +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + orrhs \result, \result, \curbit + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + orrhs \result, \result, \curbit, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + orrhs \result, \result, \curbit, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + orrhs \result, \result, \curbit, lsr #3 + cmp \dividend, #0 @ Early termination? + movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? + movne \divisor, \divisor, lsr #4 + bne 1b + +.endm +/* ------------------------------------------------------------------------ */ +.macro ARM_DIV2_ORDER divisor, order + +#if __ARM_ARCH__ >= 5 + + clz \order, \divisor + rsb \order, \order, #31 + +#else -Loop3: - @ Test for possible subtractions. On the final pass, this may - @ subtract too much from the dividend ... + cmp \divisor, #(1 << 16) + movhs \divisor, \divisor, lsr #16 + movhs \order, #16 + movlo \order, #0 + + cmp \divisor, #(1 << 8) + movhs \divisor, \divisor, lsr #8 + addhs \order, \order, #8 + + cmp \divisor, #(1 << 4) + movhs \divisor, \divisor, lsr #4 + addhs \order, \order, #4 + + cmp \divisor, #(1 << 2) + addhi \order, \order, #3 + addls \order, \order, \divisor, lsr #1 + +#endif + +.endm +/* ------------------------------------------------------------------------ */ +.macro ARM_MOD_BODY dividend, divisor, order, spare + +#if __ARM_ARCH__ >= 5 + + clz \order, \divisor + clz \spare, \dividend + sub \order, \order, \spare + mov \divisor, \divisor, lsl \order - .if \modulo - @ ... so keep track of which subtractions are done in OVERDONE. - @ We can fix them up afterwards. - mov overdone, #0 - cmp dividend, divisor - subhs dividend, dividend, divisor - cmp dividend, divisor, lsr #1 - subhs dividend, dividend, divisor, lsr #1 - orrhs overdone, overdone, curbit, ror #1 - cmp dividend, divisor, lsr #2 - subhs dividend, dividend, divisor, lsr #2 - orrhs overdone, overdone, curbit, ror #2 - cmp dividend, divisor, lsr #3 - subhs dividend, dividend, divisor, lsr #3 - orrhs overdone, overdone, curbit, ror #3 - mov ip, curbit - .else - @ ... so keep track of which subtractions are done in RESULT. - @ The result will be ok, since the "bit" will have been - @ shifted out at the bottom. - cmp dividend, divisor - subhs dividend, dividend, divisor - orrhs result, result, curbit - cmp dividend, divisor, lsr #1 - subhs dividend, dividend, divisor, lsr #1 - orrhs result, result, curbit, lsr #1 - cmp dividend, divisor, lsr #2 - subhs dividend, dividend, divisor, lsr #2 - orrhs result, result, curbit, lsr #2 - cmp dividend, divisor, lsr #3 - subhs dividend, dividend, divisor, lsr #3 - orrhs result, result, curbit, lsr #3 - .endif +#else - cmp dividend, #0 @ Early termination? - movnes curbit, curbit, lsr #4 @ No, any more bits to do? - movne divisor, divisor, lsr #4 - bne Loop3 + mov \order, #0 - .if \modulo -Lfixup_dividend: - @ Any subtractions that we should not have done will be recorded in - @ the top three bits of OVERDONE. Exactly which were not needed - @ are governed by the position of the bit, stored in IP. - ands overdone, overdone, #0xe0000000 - @ If we terminated early, because dividend became zero, then the - @ bit in ip will not be in the bottom nibble, and we should not - @ perform the additions below. We must test for this though - @ (rather relying upon the TSTs to prevent the additions) since - @ the bit in ip could be in the top two bits which might then match - @ with one of the smaller RORs. - tstne ip, #0x7 - beq Lgot_result - tst overdone, ip, ror #3 - addne dividend, dividend, divisor, lsr #3 - tst overdone, ip, ror #2 - addne dividend, dividend, divisor, lsr #2 - tst overdone, ip, ror #1 - addne dividend, dividend, divisor, lsr #1 - .endif + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + addlo \order, \order, #4 + blo 1b -Lgot_result: + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + addlo \order, \order, #1 + blo 1b + +#endif + + @ Perform all needed substractions to keep only the reminder. + @ Do comparisons in batch of 4 first. + subs \order, \order, #3 @ yes, 3 is intended here + blt 2f + +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + cmp \dividend, #1 + mov \divisor, \divisor, lsr #4 + subges \order, \order, #4 + bge 1b + + tst \order, #3 + teqne \dividend, #0 + beq 5f + + @ Either 1, 2 or 3 comparison/substractions are left. +2: cmn \order, #2 + blt 4f + beq 3f + cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +3: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +4: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor +5: .endm /* ------------------------------------------------------------------------ */ .macro THUMB_DIV_MOD_BODY modulo @ Load the constant 0x10000000 into our work register. mov work, #1 lsl work, #28 -Loop1: +LSYM(Loop1): @ Unless the divisor is very big, shift it up in multiples of @ four bits, since this is the amount of unwinding in the main @ division loop. Continue shifting until the divisor is @ larger than the dividend. cmp divisor, work - bhs Lbignum + bhs LSYM(Lbignum) cmp divisor, dividend - bhs Lbignum + bhs LSYM(Lbignum) lsl divisor, #4 lsl curbit, #4 - b Loop1 -Lbignum: + b LSYM(Loop1) +LSYM(Lbignum): @ Set work to 0x80000000 lsl work, #3 -Loop2: +LSYM(Loop2): @ For very big divisors, we must shift it a bit at a time, or @ we will be in danger of overflowing. cmp divisor, work - bhs Loop3 + bhs LSYM(Loop3) cmp divisor, dividend - bhs Loop3 + bhs LSYM(Loop3) lsl divisor, #1 lsl curbit, #1 - b Loop2 -Loop3: + b LSYM(Loop2) +LSYM(Loop3): @ Test for possible subtractions ... .if \modulo @ ... On the final pass, this may subtract too much from the dividend, @@ -290,79 +443,79 @@ Loop3: @ afterwards. mov overdone, #0 cmp dividend, divisor - blo Lover1 + blo LSYM(Lover1) sub dividend, dividend, divisor -Lover1: +LSYM(Lover1): lsr work, divisor, #1 cmp dividend, work - blo Lover2 + blo LSYM(Lover2) sub dividend, dividend, work mov ip, curbit mov work, #1 ror curbit, work orr overdone, curbit mov curbit, ip -Lover2: +LSYM(Lover2): lsr work, divisor, #2 cmp dividend, work - blo Lover3 + blo LSYM(Lover3) sub dividend, dividend, work mov ip, curbit mov work, #2 ror curbit, work orr overdone, curbit mov curbit, ip -Lover3: +LSYM(Lover3): lsr work, divisor, #3 cmp dividend, work - blo Lover4 + blo LSYM(Lover4) sub dividend, dividend, work mov ip, curbit mov work, #3 ror curbit, work orr overdone, curbit mov curbit, ip -Lover4: +LSYM(Lover4): mov ip, curbit .else @ ... and note which bits are done in the result. On the final pass, @ this may subtract too much from the dividend, but the result will be ok, @ since the "bit" will have been shifted out at the bottom. cmp dividend, divisor - blo Lover1 + blo LSYM(Lover1) sub dividend, dividend, divisor orr result, result, curbit -Lover1: +LSYM(Lover1): lsr work, divisor, #1 cmp dividend, work - blo Lover2 + blo LSYM(Lover2) sub dividend, dividend, work lsr work, curbit, #1 orr result, work -Lover2: +LSYM(Lover2): lsr work, divisor, #2 cmp dividend, work - blo Lover3 + blo LSYM(Lover3) sub dividend, dividend, work lsr work, curbit, #2 orr result, work -Lover3: +LSYM(Lover3): lsr work, divisor, #3 cmp dividend, work - blo Lover4 + blo LSYM(Lover4) sub dividend, dividend, work lsr work, curbit, #3 orr result, work -Lover4: +LSYM(Lover4): .endif cmp dividend, #0 @ Early termination? - beq Lover5 + beq LSYM(Lover5) lsr curbit, #4 @ No, any more bits to do? - beq Lover5 + beq LSYM(Lover5) lsr divisor, #4 - b Loop3 -Lover5: + b LSYM(Loop3) +LSYM(Lover5): .if \modulo @ Any subtractions that we should not have done will be recorded in @ the top three bits of "overdone". Exactly which were not needed @@ -370,7 +523,7 @@ Lover5: mov work, #0xe lsl work, #28 and overdone, work - beq Lgot_result + beq LSYM(Lgot_result) @ If we terminated early, because dividend became zero, then the @ bit in ip will not be in the bottom nibble, and we should not @@ -381,33 +534,33 @@ Lover5: mov curbit, ip mov work, #0x7 tst curbit, work - beq Lgot_result + beq LSYM(Lgot_result) mov curbit, ip mov work, #3 ror curbit, work tst overdone, curbit - beq Lover6 + beq LSYM(Lover6) lsr work, divisor, #3 add dividend, work -Lover6: +LSYM(Lover6): mov curbit, ip mov work, #2 ror curbit, work tst overdone, curbit - beq Lover7 + beq LSYM(Lover7) lsr work, divisor, #2 add dividend, work -Lover7: +LSYM(Lover7): mov curbit, ip mov work, #1 ror curbit, work tst overdone, curbit - beq Lgot_result + beq LSYM(Lgot_result) lsr work, divisor, #1 add dividend, work .endif -Lgot_result: +LSYM(Lgot_result): .endm /* ------------------------------------------------------------------------ */ /* Start of the Real Functions */ @@ -419,13 +572,13 @@ Lgot_result: #ifdef __thumb__ cmp divisor, #0 - beq Ldiv0 + beq LSYM(Ldiv0) mov curbit, #1 mov result, #0 push { work } cmp dividend, divisor - blo Lgot_result + blo LSYM(Lgot_result) THUMB_DIV_MOD_BODY 0 @@ -434,22 +587,32 @@ Lgot_result: RET #else /* ARM version. */ + + subs r2, r1, #1 + RETc(eq) + bcc LSYM(Ldiv0) + cmp r0, r1 + bls 11f + tst r1, r2 + beq 12f - cmp divisor, #0 - beq Ldiv0 - mov curbit, #1 - mov result, #0 - cmp dividend, divisor - blo Lgot_result - - ARM_DIV_MOD_BODY 0 + ARM_DIV_BODY r0, r1, r2, r3 - mov r0, result + mov r0, r2 RET +11: moveq r0, #1 + movne r0, #0 + RET + +12: ARM_DIV2_ORDER r1, r2 + + mov r0, r0, lsr r2 + RET + #endif /* ARM version */ - FUNC_END udivsi3 + DIV_FUNC_END udivsi3 #endif /* L_udivsi3 */ /* ------------------------------------------------------------------------ */ @@ -460,13 +623,13 @@ Lgot_result: #ifdef __thumb__ cmp divisor, #0 - beq Ldiv0 + beq LSYM(Ldiv0) mov curbit, #1 cmp dividend, divisor - bhs Lover10 + bhs LSYM(Lover10) RET -Lover10: +LSYM(Lover10): push { work } THUMB_DIV_MOD_BODY 1 @@ -476,21 +639,21 @@ Lover10: #else /* ARM version. */ - cmp divisor, #0 - beq Ldiv0 - cmp divisor, #1 - cmpne dividend, divisor - moveq dividend, #0 - RETc(lo) - mov curbit, #1 + subs r2, r1, #1 @ compare divisor with 1 + bcc LSYM(Ldiv0) + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + RETc(ls) - ARM_DIV_MOD_BODY 1 + ARM_MOD_BODY r0, r1, r2, r3 RET #endif /* ARM version. */ - FUNC_END umodsi3 + DIV_FUNC_END umodsi3 #endif /* L_umodsi3 */ /* ------------------------------------------------------------------------ */ @@ -500,7 +663,7 @@ Lover10: #ifdef __thumb__ cmp divisor, #0 - beq Ldiv0 + beq LSYM(Ldiv0) push { work } mov work, dividend @@ -509,50 +672,67 @@ Lover10: mov curbit, #1 mov result, #0 cmp divisor, #0 - bpl Lover10 + bpl LSYM(Lover10) neg divisor, divisor @ Loops below use unsigned. -Lover10: +LSYM(Lover10): cmp dividend, #0 - bpl Lover11 + bpl LSYM(Lover11) neg dividend, dividend -Lover11: +LSYM(Lover11): cmp dividend, divisor - blo Lgot_result + blo LSYM(Lgot_result) THUMB_DIV_MOD_BODY 0 mov r0, result mov work, ip cmp work, #0 - bpl Lover12 + bpl LSYM(Lover12) neg r0, r0 -Lover12: +LSYM(Lover12): pop { work } RET #else /* ARM version. */ - eor ip, dividend, divisor @ Save the sign of the result. - mov curbit, #1 - mov result, #0 - cmp divisor, #0 - rsbmi divisor, divisor, #0 @ Loops below use unsigned. - beq Ldiv0 - cmp dividend, #0 - rsbmi dividend, dividend, #0 - cmp dividend, divisor - blo Lgot_result - - ARM_DIV_MOD_BODY 0 + cmp r1, #0 + eor ip, r0, r1 @ save the sign of the result. + beq LSYM(Ldiv0) + rsbmi r1, r1, #0 @ loops below use unsigned. + subs r2, r1, #1 @ division by 1 or -1 ? + beq 10f + movs r3, r0 + rsbmi r3, r0, #0 @ positive dividend value + cmp r3, r1 + bls 11f + tst r1, r2 @ divisor is power of 2 ? + beq 12f + + ARM_DIV_BODY r3, r1, r0, r2 - mov r0, result cmp ip, #0 rsbmi r0, r0, #0 RET +10: teq ip, r0 @ same sign ? + rsbmi r0, r0, #0 + RET + +11: movlo r0, #0 + moveq r0, ip, asr #31 + orreq r0, r0, #1 + RET + +12: ARM_DIV2_ORDER r1, r2 + + cmp ip, #0 + mov r0, r3, lsr r2 + rsbmi r0, r0, #0 + RET + #endif /* ARM version */ - FUNC_END divsi3 + DIV_FUNC_END divsi3 #endif /* L_divsi3 */ /* ------------------------------------------------------------------------ */ @@ -564,56 +744,55 @@ Lover12: mov curbit, #1 cmp divisor, #0 - beq Ldiv0 - bpl Lover10 + beq LSYM(Ldiv0) + bpl LSYM(Lover10) neg divisor, divisor @ Loops below use unsigned. -Lover10: +LSYM(Lover10): push { work } @ Need to save the sign of the dividend, unfortunately, we need @ work later on. Must do this after saving the original value of @ the work register, because we will pop this value off first. push { dividend } cmp dividend, #0 - bpl Lover11 + bpl LSYM(Lover11) neg dividend, dividend -Lover11: +LSYM(Lover11): cmp dividend, divisor - blo Lgot_result + blo LSYM(Lgot_result) THUMB_DIV_MOD_BODY 1 pop { work } cmp work, #0 - bpl Lover12 + bpl LSYM(Lover12) neg dividend, dividend -Lover12: +LSYM(Lover12): pop { work } RET #else /* ARM version. */ - cmp divisor, #0 - rsbmi divisor, divisor, #0 @ Loops below use unsigned. - beq Ldiv0 - @ Need to save the sign of the dividend, unfortunately, we need - @ ip later on; this is faster than pushing lr and using that. - str dividend, [sp, #-4]! - cmp dividend, #0 @ Test dividend against zero - rsbmi dividend, dividend, #0 @ If negative make positive - cmp dividend, divisor @ else if zero return zero - blo Lgot_result @ if smaller return dividend - mov curbit, #1 - - ARM_DIV_MOD_BODY 1 - - ldr ip, [sp], #4 - cmp ip, #0 - rsbmi dividend, dividend, #0 + cmp r1, #0 + beq LSYM(Ldiv0) + rsbmi r1, r1, #0 @ loops below use unsigned. + movs ip, r0 @ preserve sign of dividend + rsbmi r0, r0, #0 @ if negative make positive + subs r2, r1, #1 @ compare divisor with 1 + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + bls 10f + + ARM_MOD_BODY r0, r1, r2, r3 + +10: cmp ip, #0 + rsbmi r0, r0, #0 RET #endif /* ARM version */ - FUNC_END modsi3 + DIV_FUNC_END modsi3 #endif /* L_modsi3 */ /* ------------------------------------------------------------------------ */ @@ -623,7 +802,7 @@ Lover12: RET - SIZE (__div0) + FUNC_END div0 #endif /* L_divmodsi_tools */ /* ------------------------------------------------------------------------ */ @@ -636,22 +815,18 @@ Lover12: #define __NR_getpid (__NR_SYSCALL_BASE+ 20) #define __NR_kill (__NR_SYSCALL_BASE+ 37) + .code 32 FUNC_START div0 stmfd sp!, {r1, lr} swi __NR_getpid cmn r0, #1000 - ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do + RETLDM r1 hs mov r1, #SIGFPE swi __NR_kill -#ifdef __THUMB_INTERWORK__ - ldmfd sp!, {r1, lr} - bx lr -#else - ldmfd sp!, {r1, pc}RETCOND -#endif + RETLDM r1 - SIZE (__div0) + FUNC_END div0 #endif /* L_dvmd_lnx */ /* ------------------------------------------------------------------------ */ @@ -720,24 +895,23 @@ Lover12: .code 32 .globl _arm_return -_arm_return: - ldmia r13!, {r12} - bx r12 +_arm_return: + RETLDM .code 16 -.macro interwork register - .code 16 +.macro interwork register + .code 16 THUMB_FUNC_START _interwork_call_via_\register - bx pc + bx pc nop - - .code 32 - .globl .Lchange_\register -.Lchange_\register: + + .code 32 + .globl LSYM(Lchange_\register) +LSYM(Lchange_\register): tst \register, #1 - stmeqdb r13!, {lr} + streq lr, [sp, #-4]! adreq lr, _arm_return bx \register @@ -779,3 +953,7 @@ _arm_return: SIZE (_interwork_call_via_lr) #endif /* L_interwork_call_via_rX */ + +#include "ieee754-df.S" +#include "ieee754-sf.S" + |