I don't see how these can be changed without multiplying the confusion. That none of you guys complaining have bothered to address this tells me that you don't have any solution, either.
The problem here is that we've transcended traditional Z-flag simplicity and there's no going back.
The Z flag is set if the result is zero, and reset (ie NZ) if the result is not zero (1 or anything else), as it is with other instructions.
That includes AND, OR, TEST, TESTN, MOV, etc.
Saying that TESTB/TESTBN/TESTP/TESTPN moves the bit into Z is the confusing part. It should be described as testing the bit/pin and Z is set accordingly where Z means ZERO and NZ means NOT-ZERO. Then all following IF_xxx conditions work as expected too.
IIRC MOVCZ falls into this problem setting Z too ??? (cannot check ATM)
Chip, until I actually used the TESTB instruction, I had not realised it was not as expected, and my code was not working as expected. I seem to recall being caught before. But really, isn't this what we are supposed to be doing, finding gremlins in the engineering sample chips, where at least they can be fixed.
Chip, I do hope you are not taking this personally! It's a fantastic P2. I just want it to be the best that it can be.
Chip,
Can you explain the purpose of the MODCZ instruction please? I follow the straight resetting/setting of the C & Z flags, but what I don't follow is the reason (ie use) for using 4 bits for setting each of C & Z.
Chip,
My answer applies to ALL instructions that set/clear the C/Z flags based on ALU operations. The only exception should be instructions that are intended to manipulate the C/Z flags in an explicit way (like one that restores those flags from a saved store).
Those special ANDZ/ORZ/XORZ things are weird, and don't really belong in the same place as WZ/WC/WCZ. I'm not even sure why they exist, and what they are good for... I assume the operation is for them is to do the TESTB/TESTBN parts and then the result is AND/OR/XOR'd with whatever is in the Z flag already (from the previous instruction(s)). So it's a three operand operation. The "consistent" way to set the flag afterwards, is to set it based on the result of the whole operation. If you want the "result" out then it should go into the D register someplace.
Chip,
Can you explain the purpose of the MODCZ instruction please? I follow the straight resetting/setting of the C & Z flags, but what I don't follow is the reason (ie use) for using 4 bits for setting each of C & Z.
Chip,
My answer applies to ALL instructions that set/clear the C/Z flags based on ALU operations. The only exception should be instructions that are intended to manipulate the C/Z flags in an explicit way (like one that restores those flags from a saved store).
Those special ANDZ/ORZ/XORZ things are weird, and don't really belong in the same place as WZ/WC/WCZ. I'm not even sure why they exist, and what they are good for... I assume the operation is for them is to do the TESTB/TESTBN parts and then the result is AND/OR/XOR'd with whatever is in the Z flag already (from the previous instruction(s)). So it's a three operand operation. The "consistent" way to set the flag afterwards, is to set it based on the result of the whole operation. If you want the "result" out then it should go into the D register someplace.
I don't see how these can be changed without multiplying the confusion. That none of you guys complaining have bothered to address this tells me that you don't have any solution, either.
The problem here is that we've transcended traditional Z-flag simplicity and there's no going back.
Yes and it would be far more confusing for Z to be the opposite of C in TESTBx/TESTPx. I think the mnemonics are the only truly confusing thing now and MOVBx/MOVPx would be better.
The Z flag used in the AND/OR/XOR is what the Z flag was at the start of the instruction. So the flag that was there influences the result, but the result is not written to the flag. The flag is just set if the result is zero, and cleared if it is not zero.
It's a different instruction really, and would require a S, D slot if you wanted the result written someplace.
These instructions are intending to be operations with/on the Z or C flags, and are oddball. Normally, the ONLY way to manipulate the Z or C flags is by having a result of an operation set them accordingly, but by directly doing logic operations on them. You are doing something non-standard.
I think the only solution that keeps the functionality you want is to name the instructions differently, so that they are explicitly operations on the flags. Calling them TESTB and TESTBN implies that they will set the flags like any other TEST would.
Perhaps this?
The WZ/WC should be absent in the syntax (but it will still write to the Z or C flag).
This way it's explicit what it's doing.
The TESTB reg,bitindex WC 'C = bit should be SETC reg,bitindex, and then the Z variant could be SETZ reg,bitindex (and be the same as SETC, instead of inverted). Again the WZ/WC should be absent in the syntax.
This will make it more clear what the operations actually are. and I think that makes it less confusing with respect to how the Z/C flags end up being set/cleared.
Chip,
My answer applies to ALL instructions that set/clear the C/Z flags based on ALU operations. The only exception should be instructions that are intended to manipulate the C/Z flags in an explicit way (like one that restores those flags from a saved store).
Those special ANDZ/ORZ/XORZ things are weird, and don't really belong in the same place as WZ/WC/WCZ. I'm not even sure why they exist, and what they are good for... I assume the operation is for them is to do the TESTB/TESTBN parts and then the result is AND/OR/XOR'd with whatever is in the Z flag already (from the previous instruction(s)). So it's a three operand operation. The "consistent" way to set the flag afterwards, is to set it based on the result of the whole operation. If you want the "result" out then it should go into the D register someplace.
So, here is what would seem right, maybe:
TESTB reg,bitindex WZ 'Z=!bit
TESTBN reg,bitindex WZ 'Z=bit
NO! Change the name but keep the operation as it is. Rev A is done and it's too late to complain now.
Well, what was mildly confusing to me has just become terribly confusing
From a syntax standpoint, I didn't have any problem knowing what to do because to me the "B" and "P" signified singular, so the bit:flag or pin:flag TEST relationship made sense. You just temporarily interpret Z the same as C and you can use the instruction prefix to clarify what's going on:
testb urx, #J_IDLEB wc ' Wait for rise of J or K, mutually exclusive
testb urx, #K_RESUMEB wz
if_00 jmp #disconnected ' J and K still low, so keep waiting for connect
if_10 jmp #.connect_test ' J high is FS connect state and K high is LS
if_01 jmp #.connect_test
.se1_test
waitx ##_1ms * 100 ' J and K high is the illegal SE1 state, so wait and retest
AFAIK, TESTP[N] and TESTB[N] are the only two instruction groups that break the "Z" mold? As was stated earlier, the C flag interpretation means something other than carry depending on instruction context, so why must Z be sacrosanct?
Well, what was mildly confusing to me has just become terribly confusing
From a syntax standpoint, I didn't have any problem knowing what to do because to me the "B" and "P" signified singular, so the bit:flag or pin:flag TEST relationship made sense. You just temporarily interpret Z the same as C and you can use the instruction prefix to clarify what's going on:
testb urx, #J_IDLEB wc ' Wait for rise of J or K, mutually exclusive
testb urx, #K_RESUMEB wz
if_00 jmp #disconnected ' J and K still low, so keep waiting for connect
if_10 jmp #.connect_test ' J high is FS connect state and K high is LS
if_01 jmp #.connect_test
.se1_test
waitx ##_1ms * 100 ' J and K high is the illegal SE1 state, so wait and retest
AFAIK, TESTP[N] and TESTB[N] are the only two instruction groups that break the "Z" mold? As was stated earlier, the C flag interpretation means something other than carry depending on instruction context, so why must Z be sacrosanct?
I don't think changing the actual instruction coding makes sense since Rev A exists now, but if there is a clearer set of mnemonics that can be used for the instructions, that might make sense to assist assembly language programmers.
Personally I'd fall on the size of consistency in how Z is treated, it's just want people coming from other assembly languages will expect.
I didn't mean to be so blunt earlier. Cluso has a genuine concern about how an instruction called TEST should work, but a name change could take care of that, I think. The bottom line is that people have written code based on how the instructions work now. I've used wc, wz, andc, orc, xorc, xorz. None of it tested yet because I don't have a P2. Quite often in this context the flag to choose will be the one not already in use, so consistency is important vital.
Chip,
I think having the suffix WC/WZ carries the implication that those flags will be set according to the result.
I also think that having the flag name in the instruction suffices for knowing the flag will be changed by the instruction.
Here's what I think makes everything clear:
SETZB reg,bitindex ' Z = Bit
SETZNB reg,bitindex ' Z = !Bit
SETCB reg,bitindex ' C = Bit
SETCNB reg,bitindex ' C = !Bit
ANDZB reg,bitindex ' Z = Z & Bit
ANDZNB reg,bitindex ' Z = Z & !Bit
ANDCB reg,bitindex ' C = C & Bit
ANDCNB reg,bitindex ' C = C & !Bit
ORZB reg,bitindex ' Z = Z | Bit
ORZNB reg,bitindex ' Z = Z | !Bit
ORCB reg,bitindex ' C = C | Bit
ORCNB reg,bitindex ' C = C | !Bit
XORZB reg,bitindex ' Z = Z ^ Bit
XORZNB reg,bitindex ' Z = Z ^ !Bit
XORCB reg,bitindex ' C = C ^ Bit
XORCNB reg,bitindex ' C = C ^ !Bit
SETZP pinindex ' Z = Pin
SETZNP pinindex ' Z = !Pin
SETCP pinindex ' C = Pin
SETCNP pinindex ' C = !Pin
ANDZP pinindex ' Z = Z & Pin
ANDZNP pinindex ' Z = Z & !Pin
ANDCP pinindex ' C = C & Pin
ANDCNP pinindex ' C = C & !Pin
ORZP pinindex ' Z = Z | Pin
ORZNP pinindex ' Z = Z | !Pin
ORCP pinindex ' C = C | Pin
ORCNP pinindex ' C = C | !Pin
XORZP pinindex ' Z = Z ^ Pin
XORZNP pinindex ' Z = Z ^ !Pin
XORCP pinindex ' C = C ^ Pin
XORCNP pinindex ' C = C ^ !Pin
These all fit in the same space as the existing TESTB/BN and TESTP/PN space. Just without the WZ/WC/ANDZ/ANDC/ORZ/ORC/XORZ/XORC suffixes (they are indicated by the instruction name instead.
How about getting super-simple and create the aliases WA, WB and WAB to use for these outlier instructions and let the doc explain how to interpret them A and B?
To be clear, I am saying change the names (compiler/assembler side), not the actual encoding or functionality.
I think it's vitally important that the suffix WC/WZ not be on these, because that is what implies that the flags will be set according to the value of the result (like the normal logic and test operations).
Chip,
I think having the suffix WC/WZ carries the implication that those flags will be set according to the result.
I also think that having the flag name in the instruction suffices for knowing the flag will be changed by the instruction.
Here's what I think makes everything clear:
SETZB reg,bitindex ' Z = Bit
SETZNB reg,bitindex ' Z = !Bit
SETCB reg,bitindex ' C = Bit
SETCNB reg,bitindex ' C = !Bit
ANDZB reg,bitindex ' Z = Z & Bit
ANDZNB reg,bitindex ' Z = Z & !Bit
ANDCB reg,bitindex ' C = C & Bit
ANDCNB reg,bitindex ' C = C & !Bit
ORZB reg,bitindex ' Z = Z | Bit
ORZNB reg,bitindex ' Z = Z | !Bit
ORCB reg,bitindex ' C = C | Bit
ORCNB reg,bitindex ' C = C | !Bit
XORZB reg,bitindex ' Z = Z ^ Bit
XORZNB reg,bitindex ' Z = Z ^ !Bit
XORCB reg,bitindex ' C = C ^ Bit
XORCNB reg,bitindex ' C = C ^ !Bit
SETZP pinindex ' Z = Pin
SETZNP pinindex ' Z = !Pin
SETCP pinindex ' C = Pin
SETCNP pinindex ' C = !Pin
ANDZP pinindex ' Z = Z & Pin
ANDZNP pinindex ' Z = Z & !Pin
ANDCP pinindex ' C = C & Pin
ANDCNP pinindex ' C = C & !Pin
ORZP pinindex ' Z = Z | Pin
ORZNP pinindex ' Z = Z | !Pin
ORCP pinindex ' C = C | Pin
ORCNP pinindex ' C = C | !Pin
XORZP pinindex ' Z = Z ^ Pin
XORZNP pinindex ' Z = Z ^ !Pin
XORCP pinindex ' C = C ^ Pin
XORCNP pinindex ' C = C ^ !Pin
These all fit in the same space as the existing TESTB/BN and TESTP/PN space. Just without the WZ/WC/ANDZ/ANDC/ORZ/ORC/XORZ/XORC suffixes (they are indicated by the instruction name instead.
Change all of those SETs to MOVs and it'll work. If you are going to insist on the semantics of WZ then I'll have to insist on something even more fundamental:
SET means make 1 and CLEAR means make 0.
The basics of the problem to me, is that Z should be set if the result is ZERO, and C is set if the result is NON-ZERO/PARITY.
Fundamentally, the Z flag is set to mean a ZERO result, and the C flag is opposite where the C flag is set basically for a NON-ZERO result.
This is the same for any micro with a Z flag.
The problem is being driven by thinking that the result is being shifted into the Z flag, instead of the "normal" usage where the Z flag is set as a test of the result. The underlying subtlety is grasping that Z set means ZERO.
C doesn't have this problem because whether you test the result, or shift it in to the flag, the result is the same.
C has a RCL/RCR instruction. Fortunately there is no RZL/RZR instruction to confuse things.
So, to me, Roy's solution does not fix the fundamental issue that Z is opposite to C, and Z always represents a ZERO result.
Agreed, the ultimate fix can be achieved by swapping/changing the source instruction codes.
Here is my preference, which is a combo of Roy's suggestion...
TESTB[N] reg,bitno [WC/WZ/WCZ]
TESTP[N] pinno [WC/WZ/WCZ]
AND/OR/XORB[N] reg,bitno [WC/WZ/WCZ]
AND/OR/XORP[N] pinno [WC/WZ/WCZ]
where Z is set if the result is ZERO, C is set if the result is NON-ZERO
And Z is reset if the result is NON-ZERO, C is reset if the result ZERO.
Cluso if it helps you, just think of all these new instructions as being in a different category being those that manipulate the flag bits directly. In contrast all/most of the other ones that use WZ, WC set the flag bits based on the just computed Result. And of course for any ALU type operations if the result is zero, Z=1. However for this new category of instructions which manipulate flag states themselves, Z is set/clear by basic boolean operations that work on the flag bits and other inputs. It helped me deal with it thinking that way. Removing the WZ from TESTB also helps with this concept a lot.
I think Roy's names are pretty good with MOV instead of SET.
It's all good and well until we start writing some real assembly code as garryj did and then we will see where it can be confusing or awkward. Maybe I might have a problem but then I think I will anyway, the P2 is radically different even from the P1.
Here is Roy's suggestion tidied up using mov instead of set.
MOVZB reg,bitindex ' Z = Bit
MOVZNB reg,bitindex ' Z = !Bit
MOVCB reg,bitindex ' C = Bit
MOVCNB reg,bitindex ' C = !Bit
ANDZB reg,bitindex ' Z = Z & Bit
ANDZNB reg,bitindex ' Z = Z & !Bit
ANDCB reg,bitindex ' C = C & Bit
ANDCNB reg,bitindex ' C = C & !Bit
ORZB reg,bitindex ' Z = Z | Bit
ORZNB reg,bitindex ' Z = Z | !Bit
ORCB reg,bitindex ' C = C | Bit
ORCNB reg,bitindex ' C = C | !Bit
XORZB reg,bitindex ' Z = Z ^ Bit
XORZNB reg,bitindex ' Z = Z ^ !Bit
XORCB reg,bitindex ' C = C ^ Bit
XORCNB reg,bitindex ' C = C ^ !Bit
MOVZP pinindex ' Z = Pin
MOVZNP pinindex ' Z = !Pin
MOVCP pinindex ' C = Pin
MOVCNP pinindex ' C = !Pin
ANDZP pinindex ' Z = Z & Pin
ANDZNP pinindex ' Z = Z & !Pin
ANDCP pinindex ' C = C & Pin
ANDCNP pinindex ' C = C & !Pin
ORZP pinindex ' Z = Z | Pin
ORZNP pinindex ' Z = Z | !Pin
ORCP pinindex ' C = C | Pin
ORCNP pinindex ' C = C | !Pin
XORZP pinindex ' Z = Z ^ Pin
XORZNP pinindex ' Z = Z ^ !Pin
XORCP pinindex ' C = C ^ Pin
XORCNP pinindex ' C = C ^ !Pin
Cluso,
I was with you, and still would be if they leave them called TESTB/TESTNB/etc.
However, these instructions are meant to manipulate the C and Z flags in an explicit way using source bit or pin. I think with the instruction names changed it becomes clear what's happening and the actual functionality doesn't need to change.
If they were changed to work like you want, then they can't do what they are intended to do, because the whole point of them is to manipulate the C/Z flags directly.
Comments
That includes AND, OR, TEST, TESTN, MOV, etc.
Saying that TESTB/TESTBN/TESTP/TESTPN moves the bit into Z is the confusing part. It should be described as testing the bit/pin and Z is set accordingly where Z means ZERO and NZ means NOT-ZERO. Then all following IF_xxx conditions work as expected too.
IIRC MOVCZ falls into this problem setting Z too ??? (cannot check ATM)
Chip, until I actually used the TESTB instruction, I had not realised it was not as expected, and my code was not working as expected. I seem to recall being caught before. But really, isn't this what we are supposed to be doing, finding gremlins in the engineering sample chips, where at least they can be fixed.
Chip, I do hope you are not taking this personally! It's a fantastic P2. I just want it to be the best that it can be.
Can you explain the purpose of the MODCZ instruction please? I follow the straight resetting/setting of the C & Z flags, but what I don't follow is the reason (ie use) for using 4 bits for setting each of C & Z.
My answer applies to ALL instructions that set/clear the C/Z flags based on ALU operations. The only exception should be instructions that are intended to manipulate the C/Z flags in an explicit way (like one that restores those flags from a saved store).
Those special ANDZ/ORZ/XORZ things are weird, and don't really belong in the same place as WZ/WC/WCZ. I'm not even sure why they exist, and what they are good for... I assume the operation is for them is to do the TESTB/TESTBN parts and then the result is AND/OR/XOR'd with whatever is in the Z flag already (from the previous instruction(s)). So it's a three operand operation. The "consistent" way to set the flag afterwards, is to set it based on the result of the whole operation. If you want the "result" out then it should go into the D register someplace.
See here
http://forums.parallax.com/discussion/comment/1437740/#Comment_1437740
Thanks for that Brian.
So, here is what would seem right, maybe:
TESTB reg,bitindex WZ 'Z=!bit
TESTB reg,bitindex WC 'C=bit
TESTBN reg,bitindex WZ 'Z=bit
TESTBN reg,bitindex WC 'C=!bit
TESTB reg,bitindex ANDZ 'Z &= bit
TESTB reg,bitindex ANDC 'C &= bit
TESTBN reg,bitindex ANDZ 'Z &= !bit
TESTBN reg,bitindex ANDC 'C &= !bit
Yes and it would be far more confusing for Z to be the opposite of C in TESTBx/TESTPx. I think the mnemonics are the only truly confusing thing now and MOVBx/MOVPx would be better.
I don't think so.
The Z flag used in the AND/OR/XOR is what the Z flag was at the start of the instruction. So the flag that was there influences the result, but the result is not written to the flag. The flag is just set if the result is zero, and cleared if it is not zero.
It's a different instruction really, and would require a S, D slot if you wanted the result written someplace.
These instructions are intending to be operations with/on the Z or C flags, and are oddball. Normally, the ONLY way to manipulate the Z or C flags is by having a result of an operation set them accordingly, but by directly doing logic operations on them. You are doing something non-standard.
I think the only solution that keeps the functionality you want is to name the instructions differently, so that they are explicitly operations on the flags. Calling them TESTB and TESTBN implies that they will set the flags like any other TEST would.
Perhaps this?
ANDZ reg, bitindex 'Z &= bit
ANDZN reg, bitindex 'Z &= !bit
ANDC reg, bitindex 'C &= bit
ANDCN reg, bitindex 'C &= !bit
The WZ/WC should be absent in the syntax (but it will still write to the Z or C flag).
This way it's explicit what it's doing.
The TESTB reg,bitindex WC 'C = bit should be SETC reg,bitindex, and then the Z variant could be SETZ reg,bitindex (and be the same as SETC, instead of inverted). Again the WZ/WC should be absent in the syntax.
This will make it more clear what the operations actually are. and I think that makes it less confusing with respect to how the Z/C flags end up being set/cleared.
NO! Change the name but keep the operation as it is. Rev A is done and it's too late to complain now.
ANDZ reg,bit WZ
...would be okay, but what about the version that uses what is now TESTBN? How does that get called out?
t's important to have a suffix showing that a flag is being affected, in any case.
BMOVZ
BANDZ
BORZ
BXORZ
BNMOVZ
BNANDZ
BNORZ
BNXORZ
PMOVZ
PANDZ
PORZ
PXORZ
PNMOVZ
PNANDZ
PNORZ
PNXORZ
EDIT: So even PNANDCZ fits the 7 character limit. It also means the WCZ part is implicit and shouldn't be an added parameter.
EDIT2: Or, since that is a huge number of aliases in total, maybe it should be like PNAND reg,bit WCZ
EDIT3: Hehe, of course your common syntax is ANDN, so that means PANDN reg,bit WCZ
EDIT4: Oops, I see CZ combo is not an option. It's either C or Z.
BAND reg,bit WC/WZ
BOR reg,bit WC/WZ
BXOR reg,bit WC/WZ
BNOT reg,bit WC/WZ
BANDN reg,bit WC/WZ
BORN reg,bit WC/WZ
BXORN reg,bit WC/WZ
PMOV reg,bit WC/WZ
PAND reg,bit WC/WZ
POR reg,bit WC/WZ
PXOR reg,bit WC/WZ
PNOT reg,bit WC/WZ
PANDN reg,bit WC/WZ
PORN reg,bit WC/WZ
PXORN reg,bit WC/WZ
How about:
CANDB reg,bit
ZANDB reg,bit
CANDNB reg,bit
ZANDNB reg,bit
CANDP reg,bit
ZANDP reg,bit
CANDNP reg,bit
ZANDNP reg,bit
From a syntax standpoint, I didn't have any problem knowing what to do because to me the "B" and "P" signified singular, so the bit:flag or pin:flag TEST relationship made sense. You just temporarily interpret Z the same as C and you can use the instruction prefix to clarify what's going on: AFAIK, TESTP[N] and TESTB[N] are the only two instruction groups that break the "Z" mold? As was stated earlier, the C flag interpretation means something other than carry depending on instruction context, so why must Z be sacrosanct?
I agree with Garry on this.
Personally I'd fall on the size of consistency in how Z is treated, it's just want people coming from other assembly languages will expect.
I think having the suffix WC/WZ carries the implication that those flags will be set according to the result.
I also think that having the flag name in the instruction suffices for knowing the flag will be changed by the instruction.
Here's what I think makes everything clear:
These all fit in the same space as the existing TESTB/BN and TESTP/PN space. Just without the WZ/WC/ANDZ/ANDC/ORZ/ORC/XORZ/XORC suffixes (they are indicated by the instruction name instead.
Edit: Roy's suggestion looks good.
I think it's vitally important that the suffix WC/WZ not be on these, because that is what implies that the flags will be set according to the value of the result (like the normal logic and test operations).
Change all of those SETs to MOVs and it'll work. If you are going to insist on the semantics of WZ then I'll have to insist on something even more fundamental:
SET means make 1 and CLEAR means make 0.
Fundamentally, the Z flag is set to mean a ZERO result, and the C flag is opposite where the C flag is set basically for a NON-ZERO result.
This is the same for any micro with a Z flag.
The problem is being driven by thinking that the result is being shifted into the Z flag, instead of the "normal" usage where the Z flag is set as a test of the result. The underlying subtlety is grasping that Z set means ZERO.
C doesn't have this problem because whether you test the result, or shift it in to the flag, the result is the same.
C has a RCL/RCR instruction. Fortunately there is no RZL/RZR instruction to confuse things.
So, to me, Roy's solution does not fix the fundamental issue that Z is opposite to C, and Z always represents a ZERO result.
Agreed, the ultimate fix can be achieved by swapping/changing the source instruction codes.
Here is my preference, which is a combo of Roy's suggestion...
RCZL writes D[30] to Z.
RCZR writes D[0] to Z.
Z does not always mean zero.
I think Roy's names are pretty good with MOV instead of SET.
Here is Roy's suggestion tidied up using mov instead of set.
I was with you, and still would be if they leave them called TESTB/TESTNB/etc.
However, these instructions are meant to manipulate the C and Z flags in an explicit way using source bit or pin. I think with the instruction names changed it becomes clear what's happening and the actual functionality doesn't need to change.
If they were changed to work like you want, then they can't do what they are intended to do, because the whole point of them is to manipulate the C/Z flags directly.