CMPSUB: a rather odd duck (not so odd, after all -- sorry for the trouble)
Phil Pilgrim (PhiPi)
Posts: 23,514
The cmpsub assembly instruction can be very useful, but there are a couple gotchas that can trap the unwary:
1. Even though it's a subtract instruction, it defaults to nr. You have to specify wr for the subtraction to take place.
2. The sense of the carry flag is the opposite of all the other compare and subtract instructions, in that it's set iff D > S (rather than D < S, as the others do).
Unless there's just an error in the docs, these make cmpsub a bit of an anomaly. I don't want to second-guess Chip, since the instruction set as a whole is so elegant and logical; but it would be interesting to know what prompted these two design decisions.
One thing that #2 makes possible (assuming the docs are correct) is a sure-fire way to set the carry flag without any other side effects:
-Phil
Addendum: Apparently #1 is the result of an error in the manual. wr is the default. The carry flag behaves as specified. It's this way to keep the division routine as short as possible.
Post Edited (Phil Pilgrim (PhiPi)) : 4/2/2009 4:04:59 AM GMT
1. Even though it's a subtract instruction, it defaults to nr. You have to specify wr for the subtraction to take place.
2. The sense of the carry flag is the opposite of all the other compare and subtract instructions, in that it's set iff D > S (rather than D < S, as the others do).
Unless there's just an error in the docs, these make cmpsub a bit of an anomaly. I don't want to second-guess Chip, since the instruction set as a whole is so elegant and logical; but it would be interesting to know what prompted these two design decisions.
One thing that #2 makes possible (assuming the docs are correct) is a sure-fire way to set the carry flag without any other side effects:
cmpsub any_register,#0 wc
-Phil
Addendum: Apparently #1 is the result of an error in the manual. wr is the default. The carry flag behaves as specified. It's this way to keep the division routine as short as possible.
Post Edited (Phil Pilgrim (PhiPi)) : 4/2/2009 4:04:59 AM GMT
Comments
CMPSUB compares the unsigned values of Value1 and Value2, and if Value2 is equal to or
greater than Value1 then it is subtracted from Value1 (if the WR effect is specified)
So, it's only subtracting if source is smaller than destination. That's nice for calculations where the result should definitely not be negative.
Subtract ever increasing odd numbers, 1, 3, 5, 7... from your input number until you can't subtract any more without going negative. The number of subtractions performed is the square root of your input.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 4/1/2009 9:41:09 PM GMT
CMPSUB defaults to WR! C is set if Dest is LESS THAN Source (i.e. same as opposite from SUB).
CMPSUB is really cool for circular counters and division code.
Post Edited (ericball) : 4/12/2009 11:56:06 PM GMT
<lame_excuse>
····One reason I did not is that I found the same info in two independent sources. (Or maybe they weren't so indpendent after all.)
</lame_excuse>
Thanks for the correction!
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 4/2/2009 1:27:07 AM GMT
Here's the real dope: wr is, indeed, the default (as shown in the Errata), but carry is set if D > S (not the same as cmp and sub), as the manual correctly states. There's a very good reason for this, too, which I had momentarily forgotten. It helps to keep the divide routine more compact, viz (from "Propeller Guts"):
I really do hope this settles it and rather wish I could just delete the whole thread.
-Phil