SX/B Word Subtraction Carry Error
Hello Terry;
I need to do some division with 32 bit Unix time, and have written a routine for that, using SX/B as much as I can (hence the earlier question regarding rotates vs shifts), employing the classical 'subtract, test addback and shift' method. However·I'm getting some errors, and find that the carry-out of a word subtraction will generate the wrong carry state for a certain range of numbers, specifically those where subtractor word is smaller than the subtrahend (while the upper byte of the subtractor is zero?). There may be other such situations... I have not studied it thoroughly.
The reason for the carry out error is that the word subtract instruction sequence·sort of "disconnects" the carry·between the first·and last instruction.
· ;__Wparam34 = __WParam34 - __WParam12
······ SUB __WPARAM34_LSB,__WPARAM12_LSB···················'carry OK here
······ SUBB __WPARAM34_MSB,/C····································· 'carry not affected
······ SUB __WPARAM34_MSB,__WPARAM12_MSB················· 'carry incorrect if result is negative
And so I can't use the SX/B word subtract operator in my division routine, or for that matter, anywhere I need to rely on the carry after a negative generating·subtraction.
So I'm wondering if you should replace the code generated by the SX/B assembler·for a word subtraction to be the same as you use for word subtraction in your division routine:
······· MOV W,__WPARAM12_LSB
······· SUB· __WPARAM34_LSB,W
······· MOV W,__WPARAM12_MSB
······· SC···························
······· MOV W,++__WPARAM12_MSB
······· SUB· __WPARAM34_MSB,W····································· 'carry stays "connected" with previous operation
As that is the same number of instructions, and does generate the correct carry-out.
Cheers,
Peter (pjv)
I need to do some division with 32 bit Unix time, and have written a routine for that, using SX/B as much as I can (hence the earlier question regarding rotates vs shifts), employing the classical 'subtract, test addback and shift' method. However·I'm getting some errors, and find that the carry-out of a word subtraction will generate the wrong carry state for a certain range of numbers, specifically those where subtractor word is smaller than the subtrahend (while the upper byte of the subtractor is zero?). There may be other such situations... I have not studied it thoroughly.
The reason for the carry out error is that the word subtract instruction sequence·sort of "disconnects" the carry·between the first·and last instruction.
· ;__Wparam34 = __WParam34 - __WParam12
······ SUB __WPARAM34_LSB,__WPARAM12_LSB···················'carry OK here
······ SUBB __WPARAM34_MSB,/C····································· 'carry not affected
······ SUB __WPARAM34_MSB,__WPARAM12_MSB················· 'carry incorrect if result is negative
And so I can't use the SX/B word subtract operator in my division routine, or for that matter, anywhere I need to rely on the carry after a negative generating·subtraction.
So I'm wondering if you should replace the code generated by the SX/B assembler·for a word subtraction to be the same as you use for word subtraction in your division routine:
······· MOV W,__WPARAM12_LSB
······· SUB· __WPARAM34_LSB,W
······· MOV W,__WPARAM12_MSB
······· SC···························
······· MOV W,++__WPARAM12_MSB
······· SUB· __WPARAM34_MSB,W····································· 'carry stays "connected" with previous operation
As that is the same number of instructions, and does generate the correct carry-out.
Cheers,
Peter (pjv)
Comments
· I had to put a "SZ" in before the last "SUB" in case the value +1 value was zero.
· Give this a try and let me know if it does what you need.
[noparse][[/noparse]EDIT] Posted beta version in lower post...
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
There is a fine line between arrogance and confidence. Make sure you don't cross it...
Post Edited (Bean (Hitt Consulting)) : 6/19/2009 6:14:19 PM GMT
http://forums.parallax.com/showthread.php?p=796397
regards peter
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
There is a fine line between arrogance and confidence. Make sure you don't cross it...
Post Edited (Bean (Hitt Consulting)) : 6/19/2009 7:17:31 PM GMT
I have my code running correctly, but I can't use SX/B to do it.
The word subtraction you are using in your own divide routine yields the correct result, and is an elegant answer.
Also I'm now having trouble with the carry-out from some number sets when using the word add SX/B instruction, and the similar approach as suggested by Peter Verkaik referenced in the above post will also fix that:
mov w,__Param1
add __Param3,w
mov w,__Param2
snc
mov w,++__Param2
add __Param4,w 'carry out is correct here
Is there a reason why the compiler could not be altered in the suggested manner to fix these? Seems pretty simple?
@Peter;
As I get older, I seem to forget more things.... heavens this was just discussed (but not fixed) only April of this year, and already I can't remember it !!!
In your referenced addition example, what is the purpose of the movsz w,++Value verses just mov w,++Value ? I don't get the SZ part.
Cheers,
Peter (pjv)
Now THAT's some kind of service.... live sotware upgrades! You fixed it while I was still posting.
Sorry to be such a whine, but there in a typo in the compiler in the word add instruction so it won't compile:
MOV W,++__PARRAM2 2 R's in __Param2
Also, I can't understand the purpose in the SZ instruction ?? What am I not seeing?
Cheers,
Peter (pjv)
First you would subtract the 1 from zero, and that would cause a underflow (carry clear).
Then W would get loaded with $FF +1 (zero), so the final SUB would NOT cause a underflow, but it should.
But having the SZ we skip the SUB leaving the carry clear to indicate the underflow and still get the right result.
I have fixed the typo. Try this version...
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
There is a fine line between arrogance and confidence. Make sure you don't cross it...
The movsz w,++ does not affect flags, wheras mov w,++ does.
If the·LSB add·gave overflow, C·gets set, and if ++MSB would be zero,·the following add
must be skipped as that would clear C. I think that is also
why Bean inserted an SZ before last addition.
regards peter
WOW, compilers fixed-while-U-wait. This is phenomenal.
Have downloaded, typo gone, will try in some detail.
@Peter;
Neither of the instructions affect the carry. I will try to wrap my head around Bean's explanation. Eventhough he does not use that SZ form in his own divide routine; just the MOV W,++VAR.
Thanks all for your help... much appreciated.
Cheers,
Peter (pjv)
I'll have to check the divide routine to see if it returns the currect results (0 or 1) when dividing by such large numbers.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
There is a fine line between arrogance and confidence. Make sure you don't cross it...
·
If you divide a small number by $FFxx you will get 1 instead of zero if xx is larger than the number you are dividing.
For example 1 / $FF02 will return "1", but 1 / $FF01 will return zero.
Bean
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
There is a fine line between arrogance and confidence. Make sure you don't cross it...
Post Edited (Bean (Hitt Consulting)) : 6/20/2009 7:07:59 PM GMT
I'll post this version in the official thread.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Money is not that important....In the grand scheme of things.
·
Since add is changed, is mutiply affected?
regards peter