Hi! CrossWorks(c) for ARM has problem with 64-bit integer division when one or both operands have value exceeds 32-bit capacity. This is code below to work around. Does somebody knows this is CrossWorks ARM library problem only or also GCC ARM library has it ??? Regards, John Doe <pre> /* C-wrapper */ long long y_64div(long long a,long long b) { y_div64(); return b; } /* GCC ASM code - derived from ARM(c) macros */ .text .code 32 .align 4 .global y_div64 y_div64: STMFD SP!,{R0,R1,R2,R3,R6-R11,R12,LR} ANDS R9, R3, #1<<31 // get sign of d BPL L_00 RSBS R2, R2, #0 // ensure d +ve RSC R3, R3, #0 L_00: EORS R9, R9, R1, ASR#32 // b31=result b30=sign of n BCC L_01 RSBS R0, R0, #0 // ensure n +ve RSC R1, R1, #0 L_01: BL y_divu64 MOVS R9, R9, LSL#1 // get out sign bits BCC L_02 RSBS R2, R2, #0 RSC R3, R3, #0 L_02: MOVS R9, R9, LSL#1 BCC L_03 L_03: MOV R4, R2 MOV R5, R3 LDMFD SP!,{R0,R1,R2,R3,R6-R11,R12,LR} BX LR //----------------------------------- y_divu64: STMDB SP!, {R4,R5,R6,R7,R8} MOV R4,#0 /* zero the quotient */ MOV R5,#0 MOV R7,R1 /* set the remainder to the current value */ MOV R6,R0 ORRS R8, R2, R3 BEQ LU_08 /* divide by 0 */ MOVS R8,#0 /* count number of shifts */ /* first loop gets $d as large as possible */ LU_00: ADDS R2, R2, R2 ADCS R3, R3, R3 /* double d */ BCS LU_01 /* overflowed */ CMP R3, R7 CMPEQ R2, R6 ADDLS R8, R8, #1 /* done an extra shift */ BLS LU_00 ADDS R8, R8, #0 /* clear carry */ LU_01: /* carry the overflow here */ MOVS R3, R3, RRX /* colour */ MOV R2, R2, RRX /* shift back down again */ LU_02: SUBS R0, R6, R2 SBCS R1, R7, R3 /* n = r - d and C set if r>=d */ MOVCS R7, R1 MOVCS R6, R0 /* r=r-d if this goes */ ADCS R4, R4, R4 ADC R5, R5, R5 /* shift next bit into the answer */ MOVS R3, R3, LSR#1 MOV R2, R2, RRX /* shift down d */ SUBS R8, R8, #1 BGE LU_02 /* do next loop (t+1) loops */ LU_08: MOV R2, R4 MOV R3, R5 MOV R0, R6 MOV R1, R7 LDMIA SP!, {R4,R5,R6,R7,R8} BX LR </pre --------------------------------- |
64-bit integer division problem in CrossWorks(r) for ARM
Started by ●March 10, 2005
Reply by ●March 10, 20052005-03-10
Hi, Which version of CrossWorks for ARM are you using? You can use "Help | About CrossStudio" to determine the version and build number. I can't reproduce the problem, so can you provide some source code that demonstrates the problem you are seeing? Regards, Jon Elliott Rowley Associates Ltd --- In , John Doe <ytremil@y...> wrote: > Hi! > CrossWorks(c) for ARM has problem with 64-bit integer division when > one or both operands have value exceeds 32-bit capacity. This is > code below to work around. > > Does somebody knows this is CrossWorks ARM library problem only > or also GCC ARM library has it ??? > > Regards, > John Doe > > <pre> > > /* C-wrapper */ > long long y_64div(long long a,long long b) > { > y_div64(); > return b; > } > /* GCC ASM code - derived from ARM(c) macros */ > .text > .code 32 > .align 4 > .global y_div64 > > y_div64: > STMFD SP!,{R0,R1,R2,R3,R6-R11,R12,LR} > ANDS R9, R3, #1<<31 // get sign of d > BPL L_00 > RSBS R2, R2, #0 // ensure d +ve > RSC R3, R3, #0 > L_00: > EORS R9, R9, R1, ASR#32 // b31=result b30=sign of n > BCC L_01 > RSBS R0, R0, #0 // ensure n +ve > RSC R1, R1, #0 > L_01: > BL y_divu64 > MOVS R9, R9, LSL#1 // get out sign bits > BCC L_02 > RSBS R2, R2, #0 > RSC R3, R3, #0 > L_02: > MOVS R9, R9, LSL#1 > BCC L_03 > L_03: > MOV R4, R2 > MOV R5, R3 > LDMFD SP!,{R0,R1,R2,R3,R6-R11,R12,LR} > BX LR > //----------------------------------- > y_divu64: > STMDB SP!, {R4,R5,R6,R7,R8} > MOV R4,#0 /* zero the quotient */ > MOV R5,#0 > MOV R7,R1 /* set the remainder to the current value */ > MOV R6,R0 > ORRS R8, R2, R3 > BEQ LU_08 /* divide by 0 */ > MOVS R8,#0 /* count number of shifts */ > /* first loop gets $d as large as possible */ > LU_00: > ADDS R2, R2, R2 > ADCS R3, R3, R3 /* double d */ > BCS LU_01 /* overflowed */ > CMP R3, R7 > CMPEQ R2, R6 > ADDLS R8, R8, #1 /* done an extra shift */ > BLS LU_00 > ADDS R8, R8, #0 /* clear carry */ > LU_01: /* carry the overflow here */ > MOVS R3, R3, RRX /* colour */ > MOV R2, R2, RRX /* shift back down again */ > LU_02: > SUBS R0, R6, R2 > SBCS R1, R7, R3 /* n = r - d and C set if r>=d */ > MOVCS R7, R1 > MOVCS R6, R0 /* r=r-d if this goes */ > ADCS R4, R4, R4 > ADC R5, R5, R5 /* shift next bit into the answer */ > MOVS R3, R3, LSR#1 > MOV R2, R2, RRX /* shift down d */ > SUBS R8, R8, #1 > BGE LU_02 /* do next loop (t+1) loops */ > LU_08: > MOV R2, R4 > MOV R3, R5 > MOV R0, R6 > MOV R1, R7 > LDMIA SP!, {R4,R5,R6,R7,R8} > BX LR > </pre > --------------------------------- > |
Reply by ●March 10, 20052005-03-10
--- In , "moruisg" <je@r...> wrote: > > Hi, > > Which version of CrossWorks for ARM are you using? You can use "Help | > About CrossStudio" to determine the version and build number. > > I can't reproduce the problem, so can you provide some source code > that demonstrates the problem you are seeing? > > Regards, > > Jon Elliott > Rowley Associates Ltd > Hi, This is a simple example: long long a = 1767040273612800LL; long long b = 2365440384LL; long long c; int main(void) { c = a/b; return 0; } After division, "c" has value 747009,but correct result - 747023. Another few numbers: 1767020750438400 / 2365439945 = 747015, but CrossWorks give 747008; 1767001050316800 / 2365438870 = 747007, but CrossWorks give 746528 (!) My CrossStudio(r) current version - 1.3 Build 5 (with ver. 1.2 - the same problem) In LPC2106,S3C44B0X,ARM Simulator - the same problem. Regards, Yuri Tiomkin, http://www.tnkernel.com |