ASM 32bit divide help!
So I want to divide·long (32bit)·numbers, i.e. 30_000_000 / 4000, or 757_002 / 80, etc so I wrote this as a quick divide routine:
It appears to work in my test case (110 / 10 = 11) - but when I start using it for real math it seems to "glitch" - i.e. suddenly from data where I should get 2,300 I get lumps of 4,700 or whatever.· I've confirmed its this code, if I let SPIN do the math it works perfectly.
Any ideas?· Its so simple I can't see how it can't not work.
Interestingly de-siliva's example has the WZ specified - but can't see how that would work either, as you'd want to still sub if X=Y?
Cheers,
James
asmLongDivide ' takes X / Y = R
mov r,#0
:loop cmpsub x, y wc
if_c add r,#1
if_c jmp #:loop
asmLongDivide_ret ret
It appears to work in my test case (110 / 10 = 11) - but when I start using it for real math it seems to "glitch" - i.e. suddenly from data where I should get 2,300 I get lumps of 4,700 or whatever.· I've confirmed its this code, if I let SPIN do the math it works perfectly.
Any ideas?· Its so simple I can't see how it can't not work.
Interestingly de-siliva's example has the WZ specified - but can't see how that would work either, as you'd want to still sub if X=Y?
asmLongDivide ' takes X / Y = R
mov r,#0
:loop cmpsub x, y wc, wz
if_c add r,#1
if_c_and_nz jmp #:loop
asmLongDivide_ret ret
Cheers,
James

Comments
As for wz, if x == y you have C (and Z) set and the sub is done already. Not looking at Z makes you go around the loop one more time for nothing (x < y || x == 0). Call it an early exit if you want.
Its called like this:
mov x, rawvalue ' convert to MS (X / 80_000) mov y, eighty_thousand call #asmLongDivide mov pulseMS, rfor example.
>Works for me (your example that is).
hmmmm.· Interesting.··OK will have to dig yet more.
Cheers!
James
Are you trying to divide signed integers with that routine?
James
I am sampling the pulse length of a pin in ASM - high-low-high time like this:
readPulseLength waitpeq RPMPULSEPIN,RPMPULSEPIN ' Wait until pin goes HIGH mov starttime,cnt ' waitpeq zero,RPMPULSEPIN ' Wait until pin goes LOW waitpeq RPMPULSEPIN,RPMPULSEPIN ' Wait until pin goes HIGH mov stoptime,cnt ' sub stoptime,starttime ' mov rawvalue, stoptime ' leave the value in rawvalue readPulseLength_ret retthe problem seems to be when the pulse length is ~ 2ms then the rawvalue times jump arround.· I know that that spin executes instructions at ~50us so I would imagine that ASM can see a 2ms pulse without breaking sweat!
I thought about using the counters, but then I still have to waitpeq/waitpne for signal edges, so why would that improve the timing? (apart from avoiding cnt roleover issues)
Am I making a mistake here?· Is there a better way to do this, preferably non-blocking so I can include other functions in the cog too?
Thanks again,
James
Post Edited (Javalin) : 6/27/2010 2:50:52 PM GMT
Ah, I gettit. I'll check it out.
thanks,
James
readPulseLength [i]waitpeq zero,RPMPULSEPIN[/i] ' Wait until pin goes LOW waitpeq RPMPULSEPIN,RPMPULSEPIN ' Wait until pin goes HIGH mov starttime,cnt ' waitpeq zero,RPMPULSEPIN ' Wait until pin goes LOW waitpeq RPMPULSEPIN,RPMPULSEPIN ' Wait until pin goes HIGH mov stoptime,cnt ' sub stoptime,starttime ' mov rawvalue, stoptime ' leave the value in rawvalue readPulseLength_ret retNow it waits for a complete cycle and is still accurate.
Cheers all,
James
Post Edited (Javalin) : 6/28/2010 7:36:09 PM GMT