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

• Posts: 9,702
edited 2017-09-30 - 14:21:54
I'm completely zombied right now but my earlier effort at least tells me I would expect SUBS and CMPS to set the flags identically. EDIT: Which makes v21 look like an improvement.
• Posts: 9,702
I'm off to bed. I'm not in any rush to duplicate that on the Prop1.
• Posts: 2,877
I think as long as large number (larger than 32bit) math can be done properly, that is the main thing that matters, right?

• Posts: 12,877
Roy Eltham wrote: »
I think as long as large number (larger than 32bit) math can be done properly, that is the main thing that matters, right?

That is how I see it. Also, it is important to know after a subtract or a compare if D was less than S. This test is different for signed and unsigned cases. I think that is more important than overflow. Overflow is an error condition that should be designed around, not detected and then dealt with.
• Posts: 2,877
I agree about needing to know on compare if D < S, and that is indeed different for signed vs unsigned. I since compare is just subtract with NR, that is why they work the same for flags.

An overflow flag would be nice, but not in some hacky weird way, a proper separate flag. That would require complete reworking of instructions and should absolutely not happen for P2.
• Posts: 12,877
There is an overflow C result for the SUMxx instructions.
• Posts: 1,493
edited 2017-09-30 - 22:16:32
evanh wrote: »
I'm off to bed. I'm not in any rush to duplicate that on the Prop1.

Many thanks for the test results, Evan. No need to do them on a P1.
evanh wrote: »
I've just been trying to work out how a signed multi-word addition should be managed. I've realised that only the most significant word of the number is actually signed. All lesser significant words of the number are inherently unsigned.

Correct.
evanh wrote: »
Meaning that an overflow can only be valid if there is no further carrying up through the number.

An overflow can occur without a carry from the lower words, e.g. \$8000_0000_0000_0000 + \$8000_0000_0000_0000.
evanh wrote: »
So, there is no such thing as a "signed carry".

Right again. Once you get to the most significant word you cannot go any higher, which is why using "carry" for signed arithmetic is confusing and wrong. There is nowhere else for a "carry" to go. If the result can't fit, that's an overflow.
• Posts: 1,493
edited 2017-09-30 - 23:50:32
cgracey wrote: »
evanh wrote: »
So, there is no such thing as a "signed carry".

Well, what do you call C after:

CMPS D,S WC

...when it indicates that signed D was less than signed S?

It is a signed version of what:

CMP D,S WC

...would return in C, indicating that unsigned D was less than unsigned S.

C after CMPS is what I'd call the "corrected sign" or "correct sign". It is, or should be, the correct sign for the D-S operation, whether or not there has been overflow.

If no overflow, C is the sign bit of the result.
If overflow, C is the negated sign bit of the result.

The add/subtract logic is the same for unsigned and signed values. Only the C flag is different.
• Posts: 12,877
TonyB_,

With the way it works now, C always holds the sign of the result, even during overflow.
• Posts: 9,702
edited 2017-10-01 - 00:52:14
Here's some Prop2 v21b testing:
```80000000(reg1) - 80000000(reg2) = 00000000
Collected flags = 00000055
CMP  reg1,reg2:  C = 0,  Z = 1
SUB  reg1,reg2:  C = 0,  Z = 1
CMPS reg1,reg2:  C = 0,  Z = 1
SUBS reg1,reg2:  C = 0,  Z = 1

7fffffff(reg1) - ffffffff(reg2) = 80000000
Collected flags = 000000a0
CMP  reg1,reg2:  C = 1,  Z = 0
SUB  reg1,reg2:  C = 1,  Z = 0
CMPS reg1,reg2:  C = 0,  Z = 0
SUBS reg1,reg2:  C = 0,  Z = 0

ffffffff(reg1) - 7fffffff(reg2) = 80000000
Collected flags = 0000000a
CMP  reg1,reg2:  C = 0,  Z = 0
SUB  reg1,reg2:  C = 0,  Z = 0
CMPS reg1,reg2:  C = 1,  Z = 0
SUBS reg1,reg2:  C = 1,  Z = 0

00000004(reg1) - 00000005(reg2) = ffffffff
Collected flags = 000000aa
CMP  reg1,reg2:  C = 1,  Z = 0
SUB  reg1,reg2:  C = 1,  Z = 0
CMPS reg1,reg2:  C = 1,  Z = 0
SUBS reg1,reg2:  C = 1,  Z = 0

00000005(reg1) - 00000004(reg2) = 00000001
Collected flags = 00000000
CMP  reg1,reg2:  C = 0,  Z = 0
SUB  reg1,reg2:  C = 0,  Z = 0
CMPS reg1,reg2:  C = 0,  Z = 0
SUBS reg1,reg2:  C = 0,  Z = 0
```

And the new collector code:
```		mov     temp1, reg1
cmp     reg1, reg2       wcz
rczl    flags
sub     reg1, reg2       wcz
rczl    flags

mov     reg1, temp1
cmps    reg1, reg2       wcz
rczl    flags
subs    reg1, reg2       wcz
rczl    flags

mov     parm, reg1
call    #itoa
call    #putnl
```

EDIT: included code showing equation result at tail of collector code
• Posts: 1,493
edited 2017-10-01 - 00:24:11
Evan, two pairs of negative numbers would complete the set!

reg1 = \$8000_0000, reg2 = \$8000_0001
reg1 = \$8000_0001, reg2 = \$8000_0000

EDIT:
Numbers changed!
• Posts: 9,702
Exactly the same as the two positive tests:
```80000000(reg1) - 80000001(reg2) = ffffffff
Collected flags = 000000aa
CMP  reg1,reg2:  C = 1,  Z = 0
SUB  reg1,reg2:  C = 1,  Z = 0
CMPS reg1,reg2:  C = 1,  Z = 0
SUBS reg1,reg2:  C = 1,  Z = 0

80000001(reg1) - 80000000(reg2) = 00000001
Collected flags = 00000000
CMP  reg1,reg2:  C = 0,  Z = 0
SUB  reg1,reg2:  C = 0,  Z = 0
CMPS reg1,reg2:  C = 0,  Z = 0
SUBS reg1,reg2:  C = 0,  Z = 0
```
• Posts: 9,702
PS: The SUBS is providing the equation result. SUB goes nowhere.
• Posts: 1,493
edited 2017-10-01 - 12:44:52
After further thought, the overflow flag is still there in v21, it's just hidden.
```		MOV     D,##\$7FFF_FFFF		'+2147483647
MOV     S,##\$FFFF_FFFF		'-1
SUBS    D,S		WCZ	'C is correct sign flag

'D = \$8000_0000, C = 0, Z = 0 (NC,NZ)
```

D[31] = 1, indicating that +2147483647 is less than -1 due to overflow
C = 0, indicating that +2147483647 is not less than -1

C has been corrected to give the right sign for this subtraction, as follows:
C = !D[31] if overflow, else C = D[31]

Let V = 0 if no overflow, V = 1 if overflow, then

C = D[31] XOR V
V = D[31] XOR C

Converting C into V requires one more instruction:
```		MOV     D,##\$7FFF_FFFF		'+2147483647
MOV     S,##\$FFFF_FFFF		'-1
SUBS    D,S		WCZ	'C is correct sign flag
TESTB	D,#31		XORC	'C is overflow flag
```

An assembler alias would be handy:
```		MOV     D,##\$7FFF_FFFF		'+2147483647
MOV     S,##\$FFFF_FFFF		'-1
SUBS    D,S		WCZ	'C is correct sign flag
TESTV	D		WC	'C is overflow flag
```

P1 and P2 v20 and earlier have overflow and extra instruction needed to get sign
P2 v21 has (corrected) sign and extra instruction needed to get overflow
• Posts: 9,702
Thanks Tony, I've stepped that through in my head and worked out why Chip has changed it from the Prop1. I'm good with what Chip has logically done in v21. It works cleanly/directly with compares while still having normal unsigned carry from SUB/ADD for extending the numbers.

I like "corrected sign" too. Is a distinct term that won't be confused.
• Posts: 12,877
edited 2017-10-01 - 06:37:03
Maybe "extended sign" would be more apt. Or, just "sign". C = bit 32 of the sum/difference.
• Posts: 9,702
[shrug] Tony will have a better grasp. I'd like to see an equation that generates C from both ADD and ADDS. Something like:

ADD: C = Sm . Dm + Dm . !Rm + Sm . !Rm

+ is OR
. is AND
! is NOT
C is carry flag.
m is most significant bit of the register.
S, D, R are Source, Destination and Result respectively.

That's pretty much verbatim copied from the 68k manual.
• Posts: 12,877
edited 2017-10-01 - 08:26:58
They work like this:

sum[32:0] = d[31:0] + s[31:0]
c = sum[32]

SUB/CMP:
sum[32:0] = d[31:0] - s[31:0]
c = !sum[32]

sum[32:0] = d[31:0] + s[31:0]
c = sum[32] XOR d[31] XOR s[31]

SUBS/CMPS:
sum[32:0] = d[31:0] - s[31:0]
c = sum[32] XOR d[31] XOR !s[31]
• Posts: 9,702
Hmm, right. All pretty clean. I can only assume my above equation is equivalent to the 33rd bit of the result.

So then you're thinking those XORs change the carry into a valid extended sign bit.
• Posts: 12,877
evanh wrote: »
Hmm, right. All pretty clean. I can only assume my above equation is equivalent to the 33rd bit of the result.

So then you're thinking those XORs change the carry into a valid extended sign bit.

They certainly seem to.

I remember writing down all the cases for 4-bit values, then I saw the pattern.
• Posts: 1,493
• Posts: 12,877
edited 2017-10-02 - 03:47:22
TonyB_, I take it you are okay with the state of things, then?
• Posts: 1,493
edited 2017-10-02 - 14:44:49
cgracey wrote: »
TonyB_, I take it you are okay with the state of things, then?

I think so, Chip. It would be good to have confirmation that TESTB D,#31 XORC does convert C from correct sign to overflow successfully. On September 10th, I wrote:
TonyB_ wrote: »
CMPS/CMPSX is SUBS/SUBSX with the result discarded, so in the former it is safe for C to be something other than overflow. After some study, I think C is simply the sign bit of the result, corrected if there is overflow: C = Sign XOR Overflow.

so I knew then that correct sign should be a function of overflow. Afterwards I did get a bit worked up about what I thought was the total loss of the overflow flag, as I think users should have the ability to test for overflow and I wasn't sure what "signed carry" meant.

Could somebody please try the following? I don't have anything P2, sorry.
```'All of the following tests should overflow and set C

MOV	FLAGS,#0
'Test 1
MOV     D,##\$7FFF_FFFF
MOV     S,#1
ADDS    D,S		WCZ	'C is correct sign
TESTB	D,#31		XORC	'C is overflow ?
RCZL	FLAGS
'is same as
MOV     D,##\$7FFF_FFFF
MOV     S,#1
CMP	D,S		WZ	'NZ for SUMZ D+S
SUMZ	D,S		WCZ	'C is overflow
RCZL	FLAGS

'Test 2
MOV     D,##\$8000_0000
MOV     S,##\$FFFF_FFFF
ADDS    D,S		WCZ	'C is correct sign
TESTB	D,#31		XORC	'C is overflow ?
RCZL	FLAGS
'is same as
MOV     D,##\$8000_0000
MOV     S,##\$FFFF_FFFF
CMP	D,S		WZ	'NZ for SUMZ D+S
SUMZ	D,S		WCZ	'C is overflow
RCZL	FLAGS

'Test 3
MOV     D,##\$8000_0000
MOV     S,#1
SUBS    D,S		WCZ	'C is correct sign
TESTB	D,#31		XORC	'C is overflow ?
RCZL	FLAGS
'is same as
MOV     D,##\$8000_0000
MOV     S,#1
CMP	D,S		WZ	'NZ for SUMNZ D-S
SUMNZ	D,S		WCZ	'C is overflow
RCZL	FLAGS

'Test 4
MOV     D,##\$7FFF_FFFF
MOV     S,##\$FFFF_FFFF
SUBS    D,S		WCZ	'C is correct sign
TESTB	D,#31		XORC	'C is overflow ?
RCZL	FLAGS
'is same as
MOV     D,##\$7FFF_FFFF
MOV     S,##\$FFFF_FFFF
CMP	D,S		WZ	'NZ for SUMNZ D-S
SUMNZ	D,S		WCZ	'C is overflow
RCZL	FLAGS

'FLAGS = %10_10_10_10_10_10_10_10 = \$AAAA ?

```

• Posts: 12,877
edited 2017-10-02 - 19:09:48
TonyB_,

Good work!

The result in flags is %10_10_10_10_10_10_10_10, which is what you'd want.

I changed all the \$7FFF_FFFF's to \$7FFF_FFFE and all the \$8000_0000's to \$8000_0001 and the result became %00_00_00_00_00_00_00_00, which is also correct.

It never occurred to me use those blasted flag operators to get an overflow indicator. Good thinking!
• Posts: 1,493
edited 2017-10-04 - 22:30:23
Thanks for doing the tests, Chip, which prove that we can test for overflow after ADDS/SUBS and without involving Z. One of my posts a bit higher up shows how I worked this out: http://forums.parallax.com/discussion/comment/1421463/#Comment_1421463

I was looking for a single instruction to do D[31] XOR C and TESTB almost chose itself. TESTB D,#31 XORC is a bit long-winded, mind you, and the XORC suffix is unfamiliar, which is why I mentioned an alias. TESTB is a great instruction, blessed rather than blasted!

I complained about losing the overflow flag, others said it is not that important and none of us realised that it had not gone away at all. Many thanks for considering my C & Z overflow idea. You politely declined it, which was the right thing to do as your change to ADDS/ADDSX/SUBS/SUBSX is definitely better.

Could "C = correct sign" be adopted officially? It is what it says. No other CPU I know corrects the sign after overflow. It's interesting that detecting overflow after CMPS/CMPSX is impossible, but the only thing that matters here is that the correct sign is reported. This lack of redundancy tells me that v21 is the way the P2 should be.

We've given signed arithmetic a really good examination and all's well that ends well, I think. I just need to edit some posts now and re-write history!
• Posts: 12,877
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.

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.
• Posts: 3,191
TonyB_ wrote: »
... I think. I just need to edit some posts now and re-write history!

Nice!

Mike
• Posts: 12,877
edited 2017-10-03 - 01:02:39
TonyB_ wrote: »
...TESTB D,#31 XORC is a bit long-winded, mind you...

Agreed. I need to look into shortening those instructions by doing something like this with them:
```GETC	reg,{#}bit
GETZ	reg,{#}bit
GETCN	reg,{#}bit
GETZN	reg,{#}bit

ANDC	reg,{#}bit
ANDZ	reg,{#}bit
ANDCN	reg,{#}bit
ANDZN	reg,{#}bit

ORC	reg,{#}bit
ORZ	reg,{#}bit
ORCN	reg,{#}bit
ORZN	reg,{#}bit

XORC	reg,{#}bit
XORZ	reg,{#}bit
XORCN	reg,{#}bit
XORZN	reg,{#}bit
```

WAIT.... Never mind. Both C and Z can be recipients of the operation, so it needs to stay as it is.
• Posts: 1,493
I was thinking of a very specific alias for TESTB D,#31 XORC
```		ADDS    D,S		WC	'C is correct sign
TESTB	D,#31		XORC	'C is overflow

'with alias?
ADDS    D,S		WC	'C is correct sign
TESTV	D		WC	'C is overflow
```

but perhaps a macro could be used?
• Posts: 12,877
TonyB_ wrote: »
I was thinking of a very specific alias for TESTB D,#31 XORC
```		ADDS    D,S		WC	'C is correct sign
TESTB	D,#31		XORC	'C is overflow

'with alias?
ADDS    D,S		WC	'C is correct sign
TESTV	D		WC	'C is overflow
```

but perhaps a macro could be used?

Good idea!!!!