• Posts: 1,708
edited 2017-10-11 12:38
We've probably all had enough of signed arithmetic, so I'll try to make this my final thoughts on the matter.
cgracey wrote: »
Thanks for all the work you did on this, TonyB_.

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.
cgracey wrote: »
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.
• Posts: 13,587
• Posts: 1,708
edited 2017-12-14 00:31
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.

TJV
```		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:
```		MOV	reg1,reg1	WC	'C = reg1[31]
TJV	reg2,#diff_sign
```
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.
• Posts: 1,708
edited 2017-12-13 14:17
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.
• Posts: 13,587
TonyB_, these look good.

Maybe TJM for TJ?.
• Posts: 1,708
edited 2017-12-13 18:56
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.
• Posts: 13,587
I like TJA better than TJM. I've already implemented these four TJx instructions, but I'll change that name.
• Posts: 13,587
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.

I'm looking into WRCZ.
• Posts: 13,587
I don't have any convenient opcode space for WRCZ. Its function could be achieved by:
```NEGC    D,#1
MUXZ    D,#1
```

I think that is sufficient.

• Posts: 17,711
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???
• Posts: 13,587
Cluso99 wrote: »
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.
• Posts: 10,179
edited 2017-12-13 23:23
Hate to say this, but an event linked to one of those slots would allow for virtual instructions, etc...

Sort of like 6502 BRK
• Posts: 13,587
edited 2017-12-14 00:14
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.
• Posts: 1,708
edited 2017-12-14 01:17
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.
• Posts: 1,708
TJ? changed to TJM in earlier post.
• Posts: 1,708
I wrote my last two posts before I saw Chip's latest one. Does that mean one TJx is free now?
• Posts: 13,587
TonyB_,

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.
• Posts: 1,708
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.
• Posts: 1,708
edited 2017-12-14 01:05
D = 0 or 1 could be tested with TJZ and TJNZ of course.
• Posts: 13,587

I think we are just going to have TJO/TJE/TJV.
• Posts: 1,708
How does getting rid of one of the four new TJx, say TJM, help create a new {#}D,{#}S instruction?
• Posts: 10,929
edited 2017-12-14 01:44
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.
• Posts: 1,708
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?
• Posts: 10,929
edited 2017-12-14 02:06
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.
• Posts: 1,708
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.
• Posts: 10,929
Sure, still do the test. But set, say, the Z flag instead of doing a branch.

The S operand disappears, which opens up encoding space for hundreds of test variations then.

• Posts: 1,708
edited 2017-12-14 03:17
But then you wouldn't know if result is zero or non-zero.
```	ADDS    D,S		WCZ	'C is correct sign, Z if D = 0
TJV	D,#overflow
```
• Posts: 10,929
Obviously, if zero is of interest then don't insert the Txx instruction in that part of the program.
• Posts: 10,929
Could have WZ and WC versions of each Txx instruction to allow for setting of either flag.
• Posts: 1,708
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.