Welcome to the Parallax Discussion Forums, sign-up to participate.

# P2 Instructions TESTB & TESTBN

• Posts: 16,673
I am not sure of a use for the instructions AND/OR/XOR of a [NOT]-BIT/PIN with the Z and/or C flag.
Still seems wrong to me but I guess since I cannot see a use, I can accept it being the wrong way around. It will catch people who use it tho'.

So now we have the MOV{C/Z}[N]{B/P} instructions...

So far, the use I have found for them have been to set the Z flag based on the bit/pin value. Here, I would like the Z flag to be set as it normally would ie Z=set=ZERO. How to solve this is easy with the compiler
I've just taken the MOVZxx instructions (from above) as the C is not at issue here.
```MOVZB   reg,bitindex  '  Bit --> Z    equiv    TESTNB  reg,bitindex WZ  ' Z if !Bit=0
MOVZNB  reg,bitindex  ' !Bit --> Z    equiv    TESTB   reg,bitindex WZ  ' Z if  Bit=0

MOVZP   pinindex      '  Pin --> Z    equiv    TESTNB  pinindex WZ      ' Z if !Pin=0
MOVZNP  pinindex      ' !Pin --> Z    equiv    TESTB   pinindex WZ      ' Z if  Pin=0

MOV  moves the bit/pin into the Z flag                         (ie Z=SET=1=zero-cond if bit/pin=1
TEST sets the Z flag according to the test result of bit/pin=0 (ie Z=SET=1=zero-cond if bit/pin=0)
```
So we have a pseudo code for testing the bit/pin which is equivalent to the inverse of moving the bit/pin.
• Posts: 16,673
TonyB_ wrote: »
CALLs that modify the flags write D[30] or S[30] to Z.
RCZL writes D[30] to Z.
RCZR writes D[0] to Z.

Z does not always mean zero.

I have just been looking thru the instruction set. There are more inconsistencies

I expect that the following are not what would normally be expected either (not tested)...
DRVZ {#}D {WCZ}
DRVNZ {#}D {WCZ}
My assumption would have been that if Z is set (ie means zero) that the pin would be set LOW. Is it set HIGH ???

Same applies to these ???
WRZ D
WRNZ D

And of course CALL and its variants are likely saving Z as "1" and not "0" as I would have previously expected. It's only a problem if you test these bits. It's fine for the RET instruction as a negative-negative will result in a positive.
• Posts: 9,982
The existing listed TESTxx instruction encodings have a hole in the CZ bit encodings of each one.

Assuming Chip likes the idea of absorbing C/Z into the mnemonics, I'm guessing Chip will remove the existing TESTxx mnemonics and issue a new, more verbose set as per Roys/Peters examples. ie: It won't be aliases.

• Posts: 16,673
evanh wrote: »
The existing listed TESTxx instruction encodings have a hole in the CZ bit encodings of each one.

Assuming Chip likes the idea of absorbing C/Z into the mnemonics, I'm guessing Chip will remove the existing TESTxx mnemonics and issue a new, more verbose set as per Roys/Peters examples. ie: It won't be aliases.

The aliases will allow those (including myself) who want to test the bit/pin using the sensible and consistent settings of the Z flag.
• Posts: 1,072
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
```

This makes perfectly sense and I think it is not confusing, even to a hardcore assembly programmer. Remember SEC and CLC instructions on the 6502? While there was no SEZ and CLZ, I think most assembly programmers are very familier with the concept of setting the status flags in other ways than by arithmetical results.
• Posts: 2,715
Cluso99 wrote: »
I am not sure of a use for the instructions AND/OR/XOR of a [NOT]-BIT/PIN with the Z and/or C flag.
Still seems wrong to me but I guess since I cannot see a use, I can accept it being the wrong way around. It will catch people who use it tho'.
Here's an example of a CRC calc.
```	rep	#4,#8
shr	data,#1 wc
testb	crc16,#0 xorc
shr	crc16,#1
if_c	xor	crc16,poly
```
• Posts: 2,715
Cluso99 wrote: »
DRVZ {#}D {WCZ}
DRVNZ {#}D {WCZ}
My assumption would have been that if Z is set (ie means zero) that the pin would be set LOW. Is it set HIGH ???

DRVZ will drive the pin high if the result was zero.(z=1)
• Posts: 13,079
Cluso99 wrote: »
TonyB_ wrote: »
CALLs that modify the flags write D[30] or S[30] to Z.
RCZL writes D[30] to Z.
RCZR writes D[0] to Z.

Z does not always mean zero.

I have just been looking thru the instruction set. There are more inconsistencies

I expect that the following are not what would normally be expected either (not tested)...
DRVZ {#}D {WCZ}
DRVNZ {#}D {WCZ}
My assumption would have been that if Z is set (ie means zero) that the pin would be set LOW. Is it set HIGH ???

Same applies to these ???
WRZ D
WRNZ D

And of course CALL and its variants are likely saving Z as "1" and not "0" as I would have previously expected. It's only a problem if you test these bits. It's fine for the RET instruction as a negative-negative will result in a positive.

Maybe we should rename the Z flag into something that means "not zero", but in the positive, like "S" for "something", as opposed to nothing. Then, all this madness could go away.
• Posts: 16,673
cgracey wrote: »
Cluso99 wrote: »
TonyB_ wrote: »
CALLs that modify the flags write D[30] or S[30] to Z.
RCZL writes D[30] to Z.
RCZR writes D[0] to Z.

Z does not always mean zero.

I have just been looking thru the instruction set. There are more inconsistencies

I expect that the following are not what would normally be expected either (not tested)...
DRVZ {#}D {WCZ}
DRVNZ {#}D {WCZ}
My assumption would have been that if Z is set (ie means zero) that the pin would be set LOW. Is it set HIGH ???

Same applies to these ???
WRZ D
WRNZ D

And of course CALL and its variants are likely saving Z as "1" and not "0" as I would have previously expected. It's only a problem if you test these bits. It's fine for the RET instruction as a negative-negative will result in a positive.

Maybe we should rename the Z flag into something that means "not zero", but in the positive, like "S" for "something", as opposed to nothing. Then, all this madness could go away.
Z has always been at odds with C.
Perhaps it could be called "N" for Non-zero. Of course we already use "N" to be NOT although in that context it might be ok.

I really don't follow why we introduced the notion of shifting into Z rather than the standard way of Z being set in the result. RCZL/RCZR is the only place where the shifting notion has real meaning, and it could be covered here as being the same as Z is set if the shift result is Zero.

Currently, it does not matter how you cut it, Z is not consistent. Sometimes it means Zero, sometimes it means Non-Zero.
• Posts: 9,982
And sometimes C means Carry, sometimes it doesn't. That's why there is so many ways of labelling the if_ conditions.

There is only the two flags. The Prop doesn't have a whole register full of condition codes bits, so the Z and C get repurposed.

• Posts: 2,371
Cluso99 wrote: »
...
Currently, it does not matter how you cut it, Z is not consistent. Sometimes it means Zero, sometimes it means Non-Zero.

It's not sometimes, it's well defined:
For ALU operations the Z flag indicates if the resulting value is zero, that is: all bits are zero, not just a single bit. ALU operations work 32bit wide and all bits count, that is totally different from single bit operations.

For single bit operations it makes much more sense to use the true state of the bits for the universal C and Z flags. So they behave the same and are interchangeable.

Why is this such a problem for you with the Z flag, but not with the C flag? C is even more inconsistent, and should be always cleared for logical operations, because there is no overflow, and therefore no carry to indicate. For sure this would make it unusable.

Andy
• Posts: 10,117
I have the same question. The sorting Roy did makes a lot of sense!

For what it's worth, didn't we add the flag ops in response to a discussion about saving variable space some time back? That's where all this came from. Rather than maintain an entire long, and read / write to it, use the flags for more complex state information.

That also means we can ignore these instructions in most cases, just doing things in the usual way, does it not?

• Posts: 2,920
Chip,
Please don't change the Z flag. That's impacting almost all of the instructions/modifiers for an issue with just a small number of them. It will have ramifications across the board, including making porting from P1 harder.
Just rename the instructions, like I suggested and Peter revised.
• Posts: 10,117
Seconded. I would rather see the conflicting instructions removed before changing the Z flag.
• Posts: 13,079
edited 2018-12-10 - 19:36:46
Seconded. I would rather see the conflicting instructions removed before changing the Z flag.

I don't want to change the Z flag, believe me. That is opening a big can of worms.

We could rename those instructions, however. I would like to require WZ or WC after the operands, so that a quick look at the code will tell you a flag is being modified.

Can someone make a list of the proposed instructions, substituting the letter F for the letter C or Z? That would cut the mnemonics in half and give need for WZ/WC.
• Posts: 1,524
edited 2018-12-10 - 20:32:16
No need for F in my view.
```MOVB	D,{#},S		WC/WZ
MOVBN	D,{#},S		WC/WZ
ANDB	D,{#},S		WC/WZ
ANDBN	D,{#},S		WC/WZ
ORB	D,{#},S		WC/WZ
ORBN	D,{#},S		WC/WZ
XORB	D,{#},S		WC/WZ
XORBN	D,{#},S		WC/WZ

MOVP	D,{#},S		WC/WZ
MOVPN	D,{#},S		WC/WZ
ANDP	D,{#},S		WC/WZ
ANDPN	D,{#},S		WC/WZ
ORP	D,{#},S		WC/WZ
ORPN	D,{#},S		WC/WZ
XORP	D,{#},S		WC/WZ
XORPN	D,{#},S		WC/WZ
```

• Posts: 2,920
I really think it's better if you DO NOT put the WC/WZ on the end. That is part of the confusion. With WZ on there it should mean that the Z flag is set based on the result of the operation and not just part of the operation like it is in these instructions.

Having the flag name in the instruction should be enough to know that it's going to manipulate the flag.

If you insist on having something on the end to indicate it, then it should be a unique identifier that is not WZ/WC/WCZ. Perhaps WF? And keep the flag name in the instruction.
• Posts: 13,079
TonyB_ wrote: »
No need for F in my view.
```MOVB	D,{#},S		WC/WZ
MOVBN	D,{#},S		WC/WZ
ANDB	D,{#},S		WC/WZ
ANDBN	D,{#},S		WC/WZ
ORB	D,{#},S		WC/WZ
ORBN	D,{#},S		WC/WZ
XORB	D,{#},S		WC/WZ
XORBN	D,{#},S		WC/WZ

MOVP	D,{#},S		WC/WZ
MOVPN	D,{#},S		WC/WZ
ANDP	D,{#},S		WC/WZ
ANDPN	D,{#},S		WC/WZ
ORP	D,{#},S		WC/WZ
ORPN	D,{#},S		WC/WZ
XORP	D,{#},S		WC/WZ
XORPN	D,{#},S		WC/WZ
```

I see MOVB and think a bit is being moved, but from where to where?

Maybe this is better:
```GETB	D,{#},S		WC/WZ
GETBN	D,{#},S		WC/WZ
GETB	D,{#},S		ANDC/ANDZ
GETBN	D,{#},S		ANDC/ANDZ
GETB	D,{#},S		ORC/ORZ
GETBN	D,{#},S		ORC/ORZ
GETB	D,{#},S		XORC/XORZ
GETBN	D,{#},S		XORC/XORZ

GETP	D,{#},S		WC/WZ
GETPN	D,{#},S		WC/WZ
GETP	D,{#},S		ANDC/ANDZ
GETPN	D,{#},S		ANDC/ANDZ
GETP	D,{#},S		ORC/ORZ
GETPN	D,{#},S		ORC/ORZ
GETP	D,{#},S		XORC/XORZ
GETPN	D,{#},S		XORC/XORZ
```

• Posts: 2,920
edited 2018-12-10 - 21:18:51
Ugh, I give up, are you even reading my posts?

MOVBZ <-- move B to Z
MOVPZ <--- move P to Z

Having the flag in the instruction name MAKES it more clear.
• Posts: 13,079
edited 2018-12-10 - 21:44:20
Roy Eltham wrote: »
Ugh, I give up, are you even reading my posts?

MOVBZ <-- move B to Z
MOVPZ <--- move P to Z

Having the flag in the instruction name MAKES it more clear.

As I've said, I would like to keep some flag suffix, so that it's obvious a flag is being affected.

I like MOVBZ/MOVPZ, except for their lack of flag suffix.

I agree that TESTB(N)/TESTP(N) is a little confusing because of the TEST(N) precedent.

These instructions are really 'getting' a bit and affecting a flag with it. I think GETB(N)/GETP(N) are most accurate and preserve the flag suffix.
• Posts: 2,920
edited 2018-12-10 - 21:47:21
My recent post suggested a new suffix for these. Is that acceptable?
As I said, the problem is that having WZ on the suffix implies that the Z flag will be set according to the result (as in set when the result is 0) and not what will actually happen with these instructions.
That, to me, is the crux of the problem. So it needs to be something else that indicates it.

Also, I don't like GET* at all.
• Posts: 13,079
Roy Eltham wrote: »
My recent post suggested a new suffix for these. Is that acceptable?
As I said, the problem is that having WZ on the suffix implies that the Z flag will be set according to the result (as in set when the result is 0) and not what will actually happen with these instructions.
That, to me, is the crux of the problem. So it needs to be something else that indicates it.

Also, I don't like GET* at all.

If people insist on thinking "GETB reg,bit WZ" is going to make Z = !bit, I can't help that.

"WF" as a suffix doesn't tell what flag is being affected.

GET seems most accurate for what is going on.
• Posts: 22,756
edited 2018-12-10 - 22:01:59
'Too bad it couldn't have been an NZ flag. Then we wouldn't be having this discussion.

-Phil
• Posts: 347
edited 2018-12-10 - 22:03:06
Roy Eltham wrote: »
My recent post suggested a new suffix for these. Is that acceptable?
As I said, the problem is that having WZ on the suffix implies that the Z flag will be set according to the result (as in set when the result is 0) and not what will actually happen with these instructions.
That, to me, is the crux of the problem. So it needs to be something else that indicates it.

Also, I don't like GET* at all.

To me (and I think it's safe to say, Chip), all the WC and WZ suffices indicate is that the particular flag is affected (may change). I humbly submit that the "set according to the result (as in set when the result is 0)" is an inference, not an implication.

To me, the crux of the problem is whether one can accept the idea of flag states being directly controlled, or being restricted to the ALU state output only. It seems obvious to me that we have some who can and some who can't (or won't), but only for the Z flag; Direct control of the C flag is accepted without question.
I find this inconsistency quite puzzling.

• Posts: 2,920
I think as a compromise, that the instruction should have the flag name in it also.

In your example: GETB reg,bit WZ ' Where is B being put? You seem to think the WZ explains that, but it doesn't. On every other ALU instruction WZ is not the destination, it's indicating that the Z flag will be written based on the result.

GETBZ reg, bit WZ ' this is better, in my opinion, because it's more clear. It's not ideal, but since you insist on having the WZ, this compromise is acceptable.

Also, I still think MOVBZ is more clear than GETBZ, but whatever, it's not as big a deal as the main issue.
• Posts: 2,371
I like the GETxx syntax.

WZ and WC just mean that the corresponding flag gets written. What kind of operation is used to generate the C and Z flag depends on the instruction.
```GETB  D,#S  WZ     'Get Bit from D and write it into Z.
GETP  D,#S  XORC   'Get Pin from Port and xor it with C.
```

maybe GETNB instead of GETBN describes better what happens.
• Posts: 13,079
edited 2018-12-10 - 22:17:23
Roy Eltham wrote: »
I think as a compromise, that the instruction should have the flag name in it also.

In your example: GETB reg,bit WZ ' Where is B being put? You seem to think the WZ explains that, but it doesn't. On every other ALU instruction WZ is not the destination, it's indicating that the Z flag will be written based on the result.

GETBZ reg, bit WZ ' this is better, in my opinion, because it's more clear. It's not ideal, but since you insist on having the WZ, this compromise is acceptable.

Also, I still think MOVBZ is more clear than GETBZ, but whatever, it's not as big a deal as the main issue.

I kind of agree, but when it comes to the logical operations AND/OR/XOR, things get really hard to infer, since it seems most likely that the bit would be getting affected. That's why I like GET - it's very passive in regards to the bit.
• Posts: 13,079
'Too bad it couldn't have been an NZ flag. Then we wouldn't be having this discussion.

-Phil

Our problem is that in English and math parlance, we don't have a word that means NOT ZERO, so we can only express the function as ZERO in the negative.
• Posts: 4,098
edited 2018-12-10 - 22:35:56
Since ZIP can mean zero, how about a flag UNZIP ?

I'm not yet persuaded we need to rake over things like this. Its not like P2 is a processor without quirks

I'm not so worried about what gets decided here, as I am about the precedent it sets for revisiting so many decisions from past years. Those decisions made some kind of marginal sense at the time, but its hard to respool the surrounding context that led to those decisions
• Posts: 2,715
GET works for me.