Is there such a thing as overflow when doing CMPS/CMPSX? Because you are just comparing, and not producing a 'difference', I think there's nothing that could be called overflow. Is that right? $8000_0000 compared to $0000_0001 is 'less than', so C=1. I'm a little punch drunk from all this signed stuff.
CMPS is just SUBS without the result being saved, so yes there is an overflow and it will be used to generate the correct sign. TESTB D,#31 XORC relies on D[31] being the msb of the result, which it won't be with CMPS/CMPSX but that matters not one jot.
We could call it "correct sign", but maybe just "sign" would suffice. On the other hand, "correct sign" doesn't get mentally dismissed as easily.
Plain "sign" would be interpreted as the sign bit of the result, I think. I like the name "correct sign" and what it is, the XOR combination of sign bit and overflow.
XOR is a beautiful logical operation because it's reversible and there's no carry. After writing xoroshiro+ code for the Z80, I'm really tuned into XOR and I found it easier to represent two variables as a and a XOR b instead of simply a and b.
Finally, Chip, could you please add TESTB D,#31 XORC somewhere in the docs, so that people know how to test for overflow? Thanks.
At the weekend Chip asked me if I could think of new branch instructions to go into the gap between TJNS and CALLPA, created when JP/JNP {#}D,{#}S were deleted.
EEEE 1011010 00I DDDDDDDDD SSSSSSSSS IJZ D,{#}S Inc D and jump to S** if D = 0
EEEE 1011010 01I DDDDDDDDD SSSSSSSSS IJNZ D,{#}S Inc D and jump to S** if D != 0
EEEE 1011010 10I DDDDDDDDD SSSSSSSSS IJS D,{#}S Inc D and jump to S** if D < 0
EEEE 1011010 11I DDDDDDDDD SSSSSSSSS IJNS D,{#}S Inc D and jump to S** if D >= 0
---------------------------------------------------
EEEE 1011011 00I DDDDDDDDD SSSSSSSSS DJZ D,{#}S Dec D and jump to S** if D = 0
EEEE 1011011 01I DDDDDDDDD SSSSSSSSS DJNZ D,{#}S Dec D and jump to S** if D != 0
EEEE 1011011 10I DDDDDDDDD SSSSSSSSS DJS D,{#}S Dec D and jump to S** if D < 0
EEEE 1011011 11I DDDDDDDDD SSSSSSSSS DJNS D,{#}S Dec D and jump to S** if D >= 0
---------------------------------------------------
EEEE 1011100 00I DDDDDDDDD SSSSSSSSS TJZ D,{#}S Test D and jump to S** if D = 0
EEEE 1011100 01I DDDDDDDDD SSSSSSSSS TJNZ D,{#}S Test D and jump to S** if D != 0
EEEE 1011100 10I DDDDDDDDD SSSSSSSSS TJS D,{#}S Test D and jump to S** if D < 0
EEEE 1011100 11I DDDDDDDDD SSSSSSSSS TJNS D,{#}S Test D and jump to S** if D >= 0
---------------------------------------------------
EEEE 1011101 00I DDDDDDDDD SSSSSSSSS <empty> D,{#}S ?
EEEE 1011101 01I DDDDDDDDD SSSSSSSSS <empty> D,{#}S ?
EEEE 1011101 10I DDDDDDDDD SSSSSSSSS <empty> D,{#}S ?
EEEE 1011101 11I DDDDDDDDD SSSSSSSSS <empty> D,{#}S ?
As IJx/DJx seem to be sufficient, it would be best if the empty slots had four more TJx instructions, for which the encoding is suited. I've come up with some simple instructions that require very little logic:
EEEE 1011101 00I DDDDDDDDD SSSSSSSSS TJO D,{#}S Test D and jump to S** if D odd
EEEE 1011101 01I DDDDDDDDD SSSSSSSSS TJE D,{#}S Test D and jump to S** if D even
EEEE 1011101 10I DDDDDDDDD SSSSSSSSS TJM D,{#}S Test D and jump to S** if D = $FFFF_FFFF (all bits are 1)
EEEE 1011101 11I DDDDDDDDD SSSSSSSSS TJV D,{#}S Test D and jump to S** if overflow
TJO & TJE
These test D[0] and TJS & TJNS test D[31], so that D could be rotated or shifted, right or left, followed (or preceded) by a conditional jump but without writing C. TJO & TJE allow a second bit in D to be tested individually by TJx apart from bit 31.
ADDS D,S WC 'C is correct sign
TESTB D,#31 XORC 'C is overflow
IF_C JMP #overflow
The problems with this code are the correct sign is overwritten, it takes two instructions to test for overflow and the first one is long-winded and not that easy to remember.
TJV jumps if D[31] XOR C = 1 and the above code can be simplified to:
ADDS D,S WC 'C is correct sign
TJV D,#overflow
SUMC/SUMNC/SUMZ/SUMNZ could be changed to write correct sign to C, making all the signed arithmetic consistent. TJV could be omitted when D and S are such that overflow is impossible.
Another application is testing whether two registers hold values with different signs:
In general TJV is a way of testing whether D[31] and C are different. As TJx leaves the flags untouched, it can provide a way of doing conditional jumps based on the current flags and previous values stored in a register:
RCZR oldcz 'oldcz[31] = C, oldcz[30] = Z
...
IF_Z TJV oldcz,#label 'Jump if Z and C != old C
I consider a TJNV instruction (test and jump if not overflow) to be unnecessary and a waste of a slot.
TJM
Tests whether all the bits in D are 1 and jumps if so. It is a jump logical not zero but I can't think of a single letter that describes this operation well hence the temporary ? and suggestions are welcome.
It is also a way of jumping conditionally using four flag conditions, C and Z and two stored flag values when both of the latter are set:
IF_NC_OR_NZ TJSO flags,#label 'Jump if (!C or !Z) and flags[31] and flags[0]
It would be helpful to have a single instruction that writes C to D[31], Z to D[0] and C to the other 30 bits. The operation is in effect as follows:
RCZL flags
SIGNX flags,#1
Multiple flag condition examples:
IF_NC_AND_NZ TJZ flags,#label 'Jump if !C and !Z and !flags[31] and !flags[0]
IF_C_AND_Z TJNZ flags,#label 'Jump if C and Z and (flags[31] or flags[0])
IF_NC_OR_Z TJS flags,#label 'Jump if (!C or Z) and flags[31]
IF_C_OR_NZ TJNS flags,#label 'Jump if (C or !Z) and !flags[31]
IF_NC_AND_Z TJO flags,#label 'Jump if !C and Z and flags[0]
IF_C_OR_Z TJE flags,#label 'Jump if (C or Z) and !flags[0]
IF_NC_OR_NZ TJM flags,#label 'Jump if (!C or !Z) and flags[31] and flags[0]
Jump summary for D[31] and D[0]:
Instr. Jump if ...
TJZ D[31] = 0 and D[0] = 0 and D[30...1] all same as D[31]
TJNZ D[31] = 1 or D[0] = 1 and D[30...1] all same as D[31]
TJS D[31] = 1 and D[0] = X
TJNS D[31] = 0 and D[0] = X
TJO D[31] = X and D[0] = 1
TJE D[31] = X and D[0] = 0
TJM D[31] = 1 and D[0] = 1 and D[30...1] all same as D[31]
TJV D[31] = 1 and C = 0
TJV D[31] = 0 and C = 1
TJZ / TJM makes subsequent TJNS and TJE / TJS and TJO more specific.
I have edited the previous post to replace TJSO that jumps if D[31] and D[0] set with TJ? that jumps if all the bits in D are set. Testing two bits was not good, it is better for TJx to test all or just one. TJ? needs a proper mnemonic. Any ideas?
As mentioned above, it would be handy to have a single instruction that writes C and Z to D as follows:
WRCZ D 'D = %CCCCCCCC_CCCCCCCC_CCCCCCCC_CCCCCCCZ
This copies C to D[31] and Z to D[0] so they can be tested directly by TJS/TJNS/TJO/TJE. As all the bits of D are either C or Z, the tests in TJNZ and TJ? are registered versions of IF_C_OR_Z and IF_C_AND_Z, respectively. D would hold -2, -1, 0 or +1.
Yes, TJM for maximum value perhaps is one of about only two choices that convey any sort of meaning. The other one is TJA for all bits (set), which is consistent with TJS for sign bit (set) and even TJZ for zero bits (set). Also A and Z are the first and last letters, while $0000_0000 and $FFFF_FFFF are the first and last values, albeit the wrong way round.
Here are both so you can see how they look:
EEEE 1011101 00I DDDDDDDDD SSSSSSSSS TJO D,{#}S Test D and jump to S** if D odd
EEEE 1011101 01I DDDDDDDDD SSSSSSSSS TJE D,{#}S Test D and jump to S** if D even
EEEE 1011101 10I DDDDDDDDD SSSSSSSSS TJM D,{#}S Test D and jump to S** if D = $FFFF_FFFF (Max value)
EEEE 1011101 11I DDDDDDDDD SSSSSSSSS TJV D,{#}S Test D and jump to S** if overflow
EEEE 1011101 00I DDDDDDDDD SSSSSSSSS TJO D,{#}S Test D and jump to S** if D odd
EEEE 1011101 01I DDDDDDDDD SSSSSSSSS TJE D,{#}S Test D and jump to S** if D even
EEEE 1011101 10I DDDDDDDDD SSSSSSSSS TJA D,{#}S Test D and jump to S** if D = $FFFF_FFFF (All bits set)
EEEE 1011101 11I DDDDDDDDD SSSSSSSSS TJV D,{#}S Test D and jump to S** if overflow
Chip, do you think we could have a WRCZ as I've described? Although there are six instructions that write C or Z or both to D, none is quite right for the new TJx. The method I've outlined of jumping based on three or even four flag values using a single instruction is optional but potentially powerful.
Well, I changed it to TJA and it didn't feel right, so I changed it back to TJM for 'maximum'. The reason is because every other TJx mnemonic relates numerical qualities (zero, signed, odd, even, overflowed), not bitfield qualities as 'all' would have.
I think these are all very nice now.
Your idea to make overflow testing generic, with even a branch, was very good. I've already changed the SUMxx instructions so they report back 'correct sign'. It all tests correctly.
Seems to me that all these extra specialised instructions are just a waste with no real purpose. Unless there is a very specific case where one of these special instructions is required where a two instruction equivalent just won't cut it, it's just a waste of silicon/power for no gain.
Personally, I would rather have a spare unused instruction slot(s) perhaps for a later P2 variant.
Seems to me that all these extra specialised instructions are just a waste with no real purpose. Unless there is a very specific case where one of these special instructions is required where a two instruction equivalent just won't cut it, it's just a waste of silicon/power for no gain.
Personally, I would rather have a spare unused instruction slot(s) perhaps for a later P2 variant.
Am I missing something???
You may be right. They are just freebies, but maybe we shouldn't spend the space. The TJO/TJE instructions are worth the least. The TJM is sometimes useful and TJV is definitely useful for handling overflow - and it's compatible with all the 'correct sign' instructions. Maybe we should get rid of TJO and TJE and thereby have a free slot that can be a '{#}D,{#}S' instruction or two 'D,{#}D' instructions.
Hate to say this, but an event linked to one of those slots would allow for virtual instructions, etc...
Sort of like 6502 BRK
I'm rearranging instructions between CALLD and SETPAT and I've opened up a whole '{#}D,{#}S' slot. This part of the encoding had always bugged me, so now it's getting cleaned up.
TJO/TJE/TJM are gone and I put in TJONE/TJMAX for 1/-1 detection.
I think this is about more than just replacing two instructions by one.
The point about TJx is that you can test D and have a conditional jump without needing to write either C or Z, both of which may be in use already. If D holds a previous copy of C or Z or both, then conditional jumps can be made using earlier flags without disturbing the current ones or jumps can be a combination of up to four flags, two current and two old. Is that useful?
TJO/TJE tell you whether D is odd/even but that's just for naming the mnemonics. What they do is test D[0], high or low, so that another bit apart from D[31] can be tested individually without writing to C or Z. Also right shifts and rotates followed by conditional jumps can be done without writing C, by testing bit 0 before the shift/rotate probably. Is that useful? You tell me.
How are WRC/WRNC/WRZ/WRNZ used? The flag or its inverse is copied to D[0] where it could be tested by TJO/TJE but TJZ/TJNZ could do the same thing.
By getting rid of one of the first three mentioned above, we got whole '{#}D,{#}S' instruction slot freed up. This was because JINT..JNQMT were also taking up twice the space they could have. These two consolidations made a nice gap.
So, maybe TJO is more useful that TJONE. What do you think about that? Maybe we should just have TJO/TJM/TJV.
D = 0 or 1 could be tested with TJZ and TJO. Right rotate/shift could be tested with TJO with jump if odd or continue if even. So yes TJO is more useful than TJONE.
There could be lots of these if they were all single operand instructions - remodifying the C/Z flags instead of branching to S. Make better use of conditional execution.
EDIT: DJNZ is probably the only double operand instruction of that group that is of real value. Although I'd also go for a IJNZ without the conditional NZ for plain increment and loop.
Evan, a bit more explanation please. Are you saying that storing CZ for later use in TJx without affecting CZ at that time could avoid branches? If so I agree or have I misunderstood?
I'm saying it's a waste of encoding space having any test and jump instructions. And most of the inc/dec + jump are also worthless. They all burn up the valuable double operand slots.
EDIT: In other words: Forget preservation of C/Z meanings and, instead, dump the jump portion and focus on having a bunch of flag altering instructions that can then be conditionally executed on.
I did misunderstand and I still don't really understand. TJx can save time and code and avoids writing to the flags. Look at how much better TJV is as an overflow test, for example. If there are going to be seven TJx, I think we might as well have eight.
If there is one TJx slot free, TJNV might not be a bad choice after all as it could be used to jump over code that handles the overflow. Also TJV & TJNV are not just for overflow.
Comments
CMPS is just SUBS without the result being saved, so yes there is an overflow and it will be used to generate the correct sign. TESTB D,#31 XORC relies on D[31] being the msb of the result, which it won't be with CMPS/CMPSX but that matters not one jot.
Plain "sign" would be interpreted as the sign bit of the result, I think. I like the name "correct sign" and what it is, the XOR combination of sign bit and overflow.
XOR is a beautiful logical operation because it's reversible and there's no carry. After writing xoroshiro+ code for the Z80, I'm really tuned into XOR and I found it easier to represent two variables as a and a XOR b instead of simply a and b.
Finally, Chip, could you please add TESTB D,#31 XORC somewhere in the docs, so that people know how to test for overflow? Thanks.
https://docs.google.com/spreadsheets/d/12LZ9KPEy5FEz8aVAG1DBVur36MB2eTVNT4QZ7wgpc-c/edit?usp=sharing
As IJx/DJx seem to be sufficient, it would be best if the empty slots had four more TJx instructions, for which the encoding is suited. I've come up with some simple instructions that require very little logic:
TJO & TJE
These test D[0] and TJS & TJNS test D[31], so that D could be rotated or shifted, right or left, followed (or preceded) by a conditional jump but without writing C. TJO & TJE allow a second bit in D to be tested individually by TJx apart from bit 31.
TJV
Intended originally for use after ADDS/ADDSX/SUBS/SUBSX. Previously I worked out how to get overflow from the correct sign in this post: http://forums.parallax.com/discussion/comment/1421463/#Comment_1421463
The problems with this code are the correct sign is overwritten, it takes two instructions to test for overflow and the first one is long-winded and not that easy to remember.
TJV jumps if D[31] XOR C = 1 and the above code can be simplified to:
SUMC/SUMNC/SUMZ/SUMNZ could be changed to write correct sign to C, making all the signed arithmetic consistent. TJV could be omitted when D and S are such that overflow is impossible.
Another application is testing whether two registers hold values with different signs:
In general TJV is a way of testing whether D[31] and C are different. As TJx leaves the flags untouched, it can provide a way of doing conditional jumps based on the current flags and previous values stored in a register:
I consider a TJNV instruction (test and jump if not overflow) to be unnecessary and a waste of a slot.
TJM
Tests whether all the bits in D are 1 and jumps if so. It is a jump logical not zero but I can't think of a single letter that describes this operation well hence the temporary ? and suggestions are welcome.
It is also a way of jumping conditionally using four flag conditions, C and Z and two stored flag values when both of the latter are set:
It would be helpful to have a single instruction that writes C to D[31], Z to D[0] and C to the other 30 bits. The operation is in effect as follows:
Multiple flag condition examples:
Jump summary for D[31] and D[0]:
TJZ / TJM makes subsequent TJNS and TJE / TJS and TJO more specific.
As mentioned above, it would be handy to have a single instruction that writes C and Z to D as follows:
This copies C to D[31] and Z to D[0] so they can be tested directly by TJS/TJNS/TJO/TJE. As all the bits of D are either C or Z, the tests in TJNZ and TJ? are registered versions of IF_C_OR_Z and IF_C_AND_Z, respectively. D would hold -2, -1, 0 or +1.
Maybe TJM for TJ?.
Here are both so you can see how they look:
Chip, do you think we could have a WRCZ as I've described? Although there are six instructions that write C or Z or both to D, none is quite right for the new TJx. The method I've outlined of jumping based on three or even four flag values using a single instruction is optional but potentially powerful.
I think these are all very nice now.
Your idea to make overflow testing generic, with even a branch, was very good. I've already changed the SUMxx instructions so they report back 'correct sign'. It all tests correctly.
I'm looking into WRCZ.
I think that is sufficient.
Personally, I would rather have a spare unused instruction slot(s) perhaps for a later P2 variant.
Am I missing something???
You may be right. They are just freebies, but maybe we shouldn't spend the space. The TJO/TJE instructions are worth the least. The TJM is sometimes useful and TJV is definitely useful for handling overflow - and it's compatible with all the 'correct sign' instructions. Maybe we should get rid of TJO and TJE and thereby have a free slot that can be a '{#}D,{#}S' instruction or two 'D,{#}D' instructions.
Sort of like 6502 BRK
I'm rearranging instructions between CALLD and SETPAT and I've opened up a whole '{#}D,{#}S' slot. This part of the encoding had always bugged me, so now it's getting cleaned up.
TJO/TJE/TJM are gone and I put in TJONE/TJMAX for 1/-1 detection.
The point about TJx is that you can test D and have a conditional jump without needing to write either C or Z, both of which may be in use already. If D holds a previous copy of C or Z or both, then conditional jumps can be made using earlier flags without disturbing the current ones or jumps can be a combination of up to four flags, two current and two old. Is that useful?
TJO/TJE tell you whether D is odd/even but that's just for naming the mnemonics. What they do is test D[0], high or low, so that another bit apart from D[31] can be tested individually without writing to C or Z. Also right shifts and rotates followed by conditional jumps can be done without writing C, by testing bit 0 before the shift/rotate probably. Is that useful? You tell me.
How are WRC/WRNC/WRZ/WRNZ used? The flag or its inverse is copied to D[0] where it could be tested by TJO/TJE but TJZ/TJNZ could do the same thing.
I got rid of TJO/TJE/TJM and made TJONE/TJMAX.
TJV is still there, as it's most useful.
By getting rid of one of the first three mentioned above, we got whole '{#}D,{#}S' instruction slot freed up. This was because JINT..JNQMT were also taking up twice the space they could have. These two consolidations made a nice gap.
So, maybe TJO is more useful that TJONE. What do you think about that? Maybe we should just have TJO/TJM/TJV.
I think we are just going to have TJO/TJE/TJV.
EDIT: DJNZ is probably the only double operand instruction of that group that is of real value. Although I'd also go for a IJNZ without the conditional NZ for plain increment and loop.
EDIT: In other words: Forget preservation of C/Z meanings and, instead, dump the jump portion and focus on having a bunch of flag altering instructions that can then be conditionally executed on.
The S operand disappears, which opens up encoding space for hundreds of test variations then.