diff options
author | Nick Clifton <nickc@redhat.com> | 2000-08-22 19:50:12 +0000 |
---|---|---|
committer | Nick Clifton <nickc@gcc.gnu.org> | 2000-08-22 19:50:12 +0000 |
commit | 888e552fda3782604fff70acc32285b09e5c4246 (patch) | |
tree | 6c8575bbd09f3c6cac2c5355649b255fbc678fdb /gcc/config/arm/lib1funcs.asm | |
parent | 89e43e33153195963cf124b257a322f0b7f9c2df (diff) | |
download | gcc-888e552fda3782604fff70acc32285b09e5c4246.zip gcc-888e552fda3782604fff70acc32285b09e5c4246.tar.gz gcc-888e552fda3782604fff70acc32285b09e5c4246.tar.bz2 |
Use macros to replace duplicated bodies of assembler code.
From-SVN: r35890
Diffstat (limited to 'gcc/config/arm/lib1funcs.asm')
-rw-r--r-- | gcc/config/arm/lib1funcs.asm | 887 |
1 files changed, 280 insertions, 607 deletions
diff --git a/gcc/config/arm/lib1funcs.asm b/gcc/config/arm/lib1funcs.asm index 619a480..08fa589 100644 --- a/gcc/config/arm/lib1funcs.asm +++ b/gcc/config/arm/lib1funcs.asm @@ -27,6 +27,9 @@ along with this program; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ------------------------------------------------------------------------ */ + +/* We need to know what prefix to add to function names. */ + #ifndef __USER_LABEL_PREFIX__ #error __USER_LABEL_PREFIX__ not defined #endif @@ -55,6 +58,7 @@ Boston, MA 02111-1307, USA. */ #endif /* Function end macros. Variants for 26 bit APCS and interworking. */ + #ifdef __APCS_26__ # define RET movs pc, lr # define RETc(x) mov##x##s pc, lr @@ -71,6 +75,7 @@ Ldiv0: # define RET bx lr # define RETc(x) bx##x lr .macro THUMB_LDIV0 +Ldiv0: push { lr } bl SYM (__div0) mov r0, #0 @ About as wrong as it could be. @@ -78,6 +83,7 @@ Ldiv0: 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. @@ -88,12 +94,14 @@ Ldiv0: # 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. 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. @@ -103,6 +111,25 @@ Ldiv0: # define RETCOND #endif +.macro FUNC_END name +Ldiv0: +#ifdef __thumb__ + THUMB_LDIV0 +#else + ARM_LDIV0 +#endif + SIZE (__\name) +.endm + +.macro THUMB_FUNC_START name + .globl SYM (\name) + TYPE (\name) + .thumb_func +SYM (\name): +.endm + +/* Function start macros. Variants for ARM and Thumb. */ + #ifdef __thumb__ #define THUMB_FUNC .thumb_func #define THUMB_CODE .force_thumb @@ -111,7 +138,6 @@ Ldiv0: #define THUMB_CODE #endif - .macro FUNC_START name .text .globl SYM (__\name) @@ -121,208 +147,114 @@ Ldiv0: THUMB_FUNC SYM (__\name): .endm - -.macro FUNC_END name -Ldiv0: -#ifdef __thumb__ - THUMB_LDIV0 -#else - ARM_LDIV0 -#endif - SIZE (__\name) -.endm - -.macro THUMB_FUNC_START name - .globl SYM (\name) - TYPE (\name) - .thumb_func -SYM (\name): -.endm -/* Used for Thumb code. */ -work .req r4 @ XXXX is this safe ? - -/* ------------------------------------------------------------------------ */ -#ifdef L_udivsi3 +/* Register aliases. */ +work .req r4 @ XXXX is this safe ? dividend .req r0 divisor .req r1 +overdone .req r2 result .req r2 curbit .req r3 ip .req r12 sp .req r13 lr .req r14 pc .req r15 - - FUNC_START udivsi3 - -#ifdef __thumb__ - cmp divisor, #0 - beq Ldiv0 - mov curbit, #1 - mov result, #0 - - push { work } - cmp dividend, divisor - bcc Lgot_result - - @ Load the constant 0x10000000 into our work register - mov work, #1 - lsl work, #28 -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 - bcs Lbignum - cmp divisor, dividend - bcs Lbignum - lsl divisor, #4 - lsl curbit, #4 - b Loop1 - -Lbignum: - @ Set work to 0x80000000 - lsl work, #3 -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 - bcs Loop3 - cmp divisor, dividend - bcs Loop3 - lsl divisor, #1 - lsl curbit, #1 - b Loop2 - -Loop3: - @ Test for possible subtractions, 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 - bcc Over1 - sub dividend, dividend, divisor - orr result, result, curbit -Over1: - lsr work, divisor, #1 - cmp dividend, work - bcc Over2 - sub dividend, dividend, work - lsr work, curbit, #1 - orr result, work -Over2: - lsr work, divisor, #2 - cmp dividend, work - bcc Over3 - sub dividend, dividend, work - lsr work, curbit, #2 - orr result, work -Over3: - lsr work, divisor, #3 - cmp dividend, work - bcc Over4 - sub dividend, dividend, work - lsr work, curbit, #3 - orr result, work -Over4: - cmp dividend, #0 @ Early termination? - beq Lgot_result - lsr curbit, #4 @ No, any more bits to do? - beq Lgot_result - lsr divisor, #4 - b Loop3 -Lgot_result: - mov r0, result - pop { work } - RET - -#else /* ARM version. */ - - cmp divisor, #0 - beq Ldiv0 - mov curbit, #1 - mov result, #0 - cmp dividend, divisor - bcc Lgot_result +/* ------------------------------------------------------------------------ */ +/* Bodies of the divsion and modulo routines. */ +/* ------------------------------------------------------------------------ */ +.macro ARM_DIV_MOD_BODY modulo 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, #0x10000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #4 - movcc curbit, curbit, lsl #4 - bcc Loop1 + cmpLO divisor, dividend + movLO divisor, divisor, lsl #4 + movLO curbit, curbit, lsl #4 + bLO Loop1 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 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #1 - movcc curbit, curbit, lsl #1 - bcc Lbignum + cmpLO divisor, dividend + movLO divisor, divisor, lsl #1 + movLO curbit, curbit, lsl #1 + bLO Lbignum Loop3: - @ Test for possible subtractions, 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. + @ Test for possible subtractions. On the final pass, this may + @ subtract too much from the dividend ... + + .if \modulo + @ ... so keep track of which subtractions are done in OVERDONE. + @ We can fix them up afterwards. + mov overdone, #0 cmp dividend, divisor - subcs dividend, dividend, divisor - orrcs result, result, curbit - cmp dividend, divisor, lsr #1 - subcs dividend, dividend, divisor, lsr #1 - orrcs result, result, curbit, lsr #1 - cmp dividend, divisor, lsr #2 - subcs dividend, dividend, divisor, lsr #2 - orrcs result, result, curbit, lsr #2 - cmp dividend, divisor, lsr #3 - subcs dividend, dividend, divisor, lsr #3 - orrcs 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 Loop3 -Lgot_result: - mov r0, result - RET + 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 -#endif /* ARM version */ + cmp dividend, #0 @ Early termination? + movNEs curbit, curbit, lsr #4 @ No, any more bits to do? + movNE divisor, divisor, lsr #4 + bNE Loop3 - FUNC_END udivsi3 + .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 -#endif /* L_udivsi3 */ +Lgot_result: +.endm /* ------------------------------------------------------------------------ */ -#ifdef L_umodsi3 - -dividend .req r0 -divisor .req r1 -overdone .req r2 -curbit .req r3 -ip .req r12 -sp .req r13 -lr .req r14 -pc .req r15 - - FUNC_START umodsi3 - -#ifdef __thumb__ - - cmp divisor, #0 - beq Ldiv0 - mov curbit, #1 - cmp dividend, divisor - bcs Over1 - RET - -Over1: - @ Load the constant 0x10000000 into our work register - push { work } +.macro THUMB_DIV_MOD_BODY modulo + @ Load the constant 0x10000000 into our work register. mov work, #1 lsl work, #28 Loop1: @@ -331,11 +263,11 @@ Loop1: @ division loop. Continue shifting until the divisor is @ larger than the dividend. cmp divisor, work - bcs Lbignum + bHS Lbignum cmp divisor, dividend - bcs Lbignum + bHS Lbignum lsl divisor, #4 - lsl curbit, #4 + lsl curbit, #4 b Loop1 Lbignum: @ Set work to 0x80000000 @@ -344,68 +276,101 @@ 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 - bcs Loop3 + bHS Loop3 cmp divisor, dividend - bcs Loop3 + bHS Loop3 lsl divisor, #1 - lsl curbit, #1 + lsl curbit, #1 b Loop2 Loop3: - @ Test for possible subtractions. On the final pass, this may - @ subtract too much from the dividend, so keep track of which - @ subtractions are done, we can fix them up afterwards... + @ Test for possible subtractions ... + .if \modulo + @ ... On the final pass, this may subtract too much from the dividend, + @ so keep track of which subtractions are done, we can fix them up + @ afterwards. mov overdone, #0 cmp dividend, divisor - bcc Over2 + bLO Lover1 sub dividend, dividend, divisor -Over2: +Lover1: lsr work, divisor, #1 cmp dividend, work - bcc Over3 + bLO Lover2 sub dividend, dividend, work mov ip, curbit mov work, #1 ror curbit, work orr overdone, curbit mov curbit, ip -Over3: +Lover2: lsr work, divisor, #2 cmp dividend, work - bcc Over4 + bLO Lover3 sub dividend, dividend, work mov ip, curbit mov work, #2 ror curbit, work orr overdone, curbit mov curbit, ip -Over4: +Lover3: lsr work, divisor, #3 cmp dividend, work - bcc Over5 + bLO Lover4 sub dividend, dividend, work mov ip, curbit mov work, #3 ror curbit, work orr overdone, curbit mov curbit, ip -Over5: +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 + sub dividend, dividend, divisor + orr result, result, curbit +Lover1: + lsr work, divisor, #1 + cmp dividend, work + bLO Lover2 + sub dividend, dividend, work + lsr work, curbit, #1 + orr result, work +Lover2: + lsr work, divisor, #2 + cmp dividend, work + bLO Lover3 + sub dividend, dividend, work + lsr work, curbit, #2 + orr result, work +Lover3: + lsr work, divisor, #3 + cmp dividend, work + bLO Lover4 + sub dividend, dividend, work + lsr work, curbit, #3 + orr result, work +Lover4: + .endif + cmp dividend, #0 @ Early termination? - beq Over6 - lsr curbit, #4 @ No, any more bits to do? - beq Over6 + bEQ Lover5 + lsr curbit, #4 @ No, any more bits to do? + bEQ Lover5 lsr divisor, #4 b Loop3 -Over6: +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 @ are governed by the position of the bit, stored in ip. mov work, #0xe - lsl work, #28 + lsl work, #28 and overdone, work - bne Over7 - pop { work } - RET @ No fixups needed + bEQ 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 @@ -416,103 +381,111 @@ Over6: mov curbit, ip mov work, #0x7 tst curbit, work - beq Over10 + bEQ Lgot_result -Over7: mov curbit, ip mov work, #3 ror curbit, work tst overdone, curbit - beq Over8 + bEQ Lover6 lsr work, divisor, #3 - add dividend, dividend, work -Over8: + add dividend, work +Lover6: mov curbit, ip mov work, #2 ror curbit, work tst overdone, curbit - beq Over9 + bEQ Lover7 lsr work, divisor, #2 - add dividend, dividend, work -Over9: + add dividend, work +Lover7: mov curbit, ip mov work, #1 ror curbit, work tst overdone, curbit - beq Over10 + bEQ Lgot_result lsr work, divisor, #1 - add dividend, dividend, work -Over10: + add dividend, work + .endif +Lgot_result: +.endm +/* ------------------------------------------------------------------------ */ +/* Start of the Real Functions */ +/* ------------------------------------------------------------------------ */ +#ifdef L_udivsi3 + + FUNC_START udivsi3 + +#ifdef __thumb__ + + cmp divisor, #0 + bEQ Ldiv0 + mov curbit, #1 + mov result, #0 + + push { work } + cmp dividend, divisor + bLO Lgot_result + + THUMB_DIV_MOD_BODY 0 + + mov r0, result pop { work } RET - -#else /* ARM version. */ + +#else /* ARM version. */ cmp divisor, #0 - beq Ldiv0 + bEQ Ldiv0 mov curbit, #1 + mov result, #0 cmp dividend, divisor - RETc(cc) -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, #0x10000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #4 - movcc curbit, curbit, lsl #4 - bcc Loop1 + bLO Lgot_result + + ARM_DIV_MOD_BODY 0 + + mov r0, result + RET -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 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #1 - movcc curbit, curbit, lsl #1 - bcc Lbignum +#endif /* ARM version */ -Loop3: - @ Test for possible subtractions. On the final pass, this may - @ subtract too much from the dividend, so keep track of which - @ subtractions are done, we can fix them up afterwards... - mov overdone, #0 + FUNC_END udivsi3 + +#endif /* L_udivsi3 */ +/* ------------------------------------------------------------------------ */ +#ifdef L_umodsi3 + + FUNC_START umodsi3 + +#ifdef __thumb__ + + cmp divisor, #0 + bEQ Ldiv0 + mov curbit, #1 cmp dividend, divisor - subcs dividend, dividend, divisor - cmp dividend, divisor, lsr #1 - subcs dividend, dividend, divisor, lsr #1 - orrcs overdone, overdone, curbit, ror #1 - cmp dividend, divisor, lsr #2 - subcs dividend, dividend, divisor, lsr #2 - orrcs overdone, overdone, curbit, ror #2 - cmp dividend, divisor, lsr #3 - subcs dividend, dividend, divisor, lsr #3 - orrcs overdone, overdone, curbit, ror #3 - mov ip, curbit - cmp dividend, #0 @ Early termination? - movnes curbit, curbit, lsr #4 @ No, any more bits to do? - movne divisor, divisor, lsr #4 - bne Loop3 + bHS Lover10 + RET - @ 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 - RETc(eq) @ No fixups needed - 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 +Lover10: + push { work } + + THUMB_DIV_MOD_BODY 1 + + pop { work } + RET + +#else /* ARM version. */ + + cmp divisor, #0 + bEQ Ldiv0 + cmp divisor, #1 + cmpNE dividend, divisor + movEQ dividend, #0 + RETc(LO) + mov curbit, #1 + + ARM_DIV_MOD_BODY 1 + RET #endif /* ARM version. */ @@ -523,20 +496,11 @@ Loop3: /* ------------------------------------------------------------------------ */ #ifdef L_divsi3 -dividend .req r0 -divisor .req r1 -result .req r2 -curbit .req r3 -ip .req r12 -sp .req r13 -lr .req r14 -pc .req r15 - FUNC_START divsi3 #ifdef __thumb__ cmp divisor, #0 - beq Ldiv0 + bEQ Ldiv0 push { work } mov work, dividend @@ -545,91 +509,26 @@ pc .req r15 mov curbit, #1 mov result, #0 cmp divisor, #0 - bpl Over1 + bPL Lover10 neg divisor, divisor @ Loops below use unsigned. -Over1: +Lover10: cmp dividend, #0 - bpl Over2 + bPL Lover11 neg dividend, dividend -Over2: +Lover11: cmp dividend, divisor - bcc Lgot_result - - mov work, #1 - lsl work, #28 -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 - Bcs Lbignum - cmp divisor, dividend - Bcs Lbignum - lsl divisor, #4 - lsl curbit, #4 - b Loop1 - -Lbignum: - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. - lsl work, #3 -Loop2: - cmp divisor, work - Bcs Loop3 - cmp divisor, dividend - Bcs Loop3 - lsl divisor, #1 - lsl curbit, #1 - b Loop2 + bLO Lgot_result -Loop3: - @ Test for possible subtractions, 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 - Bcc Over3 - sub dividend, dividend, divisor - orr result, result, curbit -Over3: - lsr work, divisor, #1 - cmp dividend, work - Bcc Over4 - sub dividend, dividend, work - lsr work, curbit, #1 - orr result, work -Over4: - lsr work, divisor, #2 - cmp dividend, work - Bcc Over5 - sub dividend, dividend, work - lsr work, curbit, #2 - orr result, result, work -Over5: - lsr work, divisor, #3 - cmp dividend, work - Bcc Over6 - sub dividend, dividend, work - lsr work, curbit, #3 - orr result, result, work -Over6: - cmp dividend, #0 @ Early termination? - Beq Lgot_result - lsr curbit, #4 @ No, any more bits to do? - Beq Lgot_result - lsr divisor, #4 - b Loop3 + THUMB_DIV_MOD_BODY 0 -Lgot_result: mov r0, result mov work, ip cmp work, #0 - Bpl Over7 + bPL Lover12 neg r0, r0 -Over7: +Lover12: pop { work } - RET + RET #else /* ARM version. */ @@ -637,58 +536,18 @@ Over7: mov curbit, #1 mov result, #0 cmp divisor, #0 - rsbmi divisor, divisor, #0 @ Loops below use unsigned. - beq Ldiv0 + rsbMI divisor, divisor, #0 @ Loops below use unsigned. + bEQ Ldiv0 cmp dividend, #0 - rsbmi dividend, dividend, #0 + rsbMI dividend, dividend, #0 cmp dividend, divisor - bcc Lgot_result - -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, #0x10000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #4 - movcc curbit, curbit, lsl #4 - bcc Loop1 - -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 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #1 - movcc curbit, curbit, lsl #1 - bcc Lbignum + bLO Lgot_result -Loop3: - @ Test for possible subtractions, 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 - subcs dividend, dividend, divisor - orrcs result, result, curbit - cmp dividend, divisor, lsr #1 - subcs dividend, dividend, divisor, lsr #1 - orrcs result, result, curbit, lsr #1 - cmp dividend, divisor, lsr #2 - subcs dividend, dividend, divisor, lsr #2 - orrcs result, result, curbit, lsr #2 - cmp dividend, divisor, lsr #3 - subcs dividend, dividend, divisor, lsr #3 - orrcs 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 Loop3 -Lgot_result: + ARM_DIV_MOD_BODY 0 + mov r0, result cmp ip, #0 - rsbmi r0, r0, #0 + rsbMI r0, r0, #0 RET #endif /* ARM version */ @@ -699,242 +558,57 @@ Lgot_result: /* ------------------------------------------------------------------------ */ #ifdef L_modsi3 -dividend .req r0 -divisor .req r1 -overdone .req r2 -curbit .req r3 -ip .req r12 -sp .req r13 -lr .req r14 -pc .req r15 - FUNC_START modsi3 #ifdef __thumb__ mov curbit, #1 cmp divisor, #0 - beq Ldiv0 - Bpl Over1 + bEQ Ldiv0 + bPL Lover10 neg divisor, divisor @ Loops below use unsigned. -Over1: +Lover10: push { work } @ Need to save the sign of the dividend, unfortunately, we need - @ ip later on. Must do this after saving the original value of + @ 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 Over2 + bPL Lover11 neg dividend, dividend -Over2: - cmp dividend, divisor - bcc Lgot_result - mov work, #1 - lsl work, #28 -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 - bcs Lbignum - cmp divisor, dividend - bcs Lbignum - lsl divisor, #4 - lsl curbit, #4 - b Loop1 - -Lbignum: - @ Set work to 0x80000000 - lsl work, #3 -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 - bcs Loop3 - cmp divisor, dividend - bcs Loop3 - lsl divisor, #1 - lsl curbit, #1 - b Loop2 - -Loop3: - @ Test for possible subtractions. On the final pass, this may - @ subtract too much from the dividend, so keep track of which - @ subtractions are done, we can fix them up afterwards... - mov overdone, #0 +Lover11: cmp dividend, divisor - bcc Over3 - sub dividend, dividend, divisor -Over3: - lsr work, divisor, #1 - cmp dividend, work - bcc Over4 - sub dividend, dividend, work - mov ip, curbit - mov work, #1 - ror curbit, work - orr overdone, curbit - mov curbit, ip -Over4: - lsr work, divisor, #2 - cmp dividend, work - bcc Over5 - sub dividend, dividend, work - mov ip, curbit - mov work, #2 - ror curbit, work - orr overdone, curbit - mov curbit, ip -Over5: - lsr work, divisor, #3 - cmp dividend, work - bcc Over6 - sub dividend, dividend, work - mov ip, curbit - mov work, #3 - ror curbit, work - orr overdone, curbit - mov curbit, ip -Over6: - mov ip, curbit - cmp dividend, #0 @ Early termination? - beq Over7 - lsr curbit, #4 @ No, any more bits to do? - beq Over7 - lsr divisor, #4 - b Loop3 + bLO Lgot_result -Over7: - @ 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. - mov work, #0xe - lsl work, #28 - and overdone, work - beq 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 - @ 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. - mov curbit, ip - mov work, #0x7 - tst curbit, work - beq Lgot_result - - mov curbit, ip - mov work, #3 - ror curbit, work - tst overdone, curbit - beq Over8 - lsr work, divisor, #3 - add dividend, dividend, work -Over8: - mov curbit, ip - mov work, #2 - ror curbit, work - tst overdone, curbit - beq Over9 - lsr work, divisor, #2 - add dividend, dividend, work -Over9: - mov curbit, ip - mov work, #1 - ror curbit, work - tst overdone, curbit - beq Lgot_result - lsr work, divisor, #1 - add dividend, dividend, work -Lgot_result: + THUMB_DIV_MOD_BODY 1 + pop { work } cmp work, #0 - bpl Over10 + bPL Lover12 neg dividend, dividend -Over10: +Lover12: pop { work } RET #else /* ARM version. */ - mov curbit, #1 cmp divisor, #0 - rsbmi divisor, divisor, #0 @ Loops below use unsigned. - beq Ldiv0 + 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 - rsbmi dividend, dividend, #0 - cmp dividend, divisor - bcc Lgot_result - -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, #0x10000000 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #4 - movcc curbit, curbit, lsl #4 - bcc Loop1 + 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 -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 - cmpcc divisor, dividend - movcc divisor, divisor, lsl #1 - movcc curbit, curbit, lsl #1 - bcc Lbignum + ARM_DIV_MOD_BODY 1 -Loop3: - @ Test for possible subtractions. On the final pass, this may - @ subtract too much from the dividend, so keep track of which - @ subtractions are done, we can fix them up afterwards... - mov overdone, #0 - cmp dividend, divisor - subcs dividend, dividend, divisor - cmp dividend, divisor, lsr #1 - subcs dividend, dividend, divisor, lsr #1 - orrcs overdone, overdone, curbit, ror #1 - cmp dividend, divisor, lsr #2 - subcs dividend, dividend, divisor, lsr #2 - orrcs overdone, overdone, curbit, ror #2 - cmp dividend, divisor, lsr #3 - subcs dividend, dividend, divisor, lsr #3 - orrcs overdone, overdone, curbit, ror #3 - mov ip, curbit - cmp dividend, #0 @ Early termination? - movnes curbit, curbit, lsr #4 @ No, any more bits to do? - movne divisor, divisor, lsr #4 - bne Loop3 - - @ 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 -Lgot_result: ldr ip, [sp], #4 cmp ip, #0 - rsbmi dividend, dividend, #0 + rsbMI dividend, dividend, #0 RET #endif /* ARM version */ @@ -1105,4 +779,3 @@ _arm_return: SIZE (_interwork_call_via_lr) #endif /* L_interwork_call_via_rX */ - |