Shop OBEX P1 Docs P2 Docs Learn Events
C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX - Page 3 — Parallax Forums

C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX

1356

Comments

  • evanhevanh Posts: 15,629
    edited 2017-09-30 14:21
    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.
  • evanhevanh Posts: 15,629
    I'm off to bed. I'm not in any rush to duplicate that on the Prop1.
  • I think as long as large number (larger than 32bit) math can be done properly, that is the main thing that matters, right?

  • cgraceycgracey Posts: 14,134
    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.
  • 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.
  • cgraceycgracey Posts: 14,134
    There is an overflow C result for the SUMxx instructions.
  • TonyB_TonyB_ Posts: 2,159
    edited 2017-09-30 22:16
    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.
  • TonyB_TonyB_ Posts: 2,159
    edited 2017-09-30 23:50
    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.
    Chip, could you please confirm this is how your logic works?

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

    With the way it works now, C always holds the sign of the result, even during overflow.
  • evanhevanh Posts: 15,629
    edited 2017-10-01 00:52
    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
  • TonyB_TonyB_ Posts: 2,159
    edited 2017-10-01 00:24
    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!
  • evanhevanh Posts: 15,629
    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
    
  • evanhevanh Posts: 15,629
    PS: The SUBS is providing the equation result. SUB goes nowhere.
  • TonyB_TonyB_ Posts: 2,159
    edited 2017-10-01 12:44
    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
    

    For ADDS/ADDSX/SUBS/SUBSX:
    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
  • evanhevanh Posts: 15,629
    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.
  • cgraceycgracey Posts: 14,134
    edited 2017-10-01 06:37
    Maybe "extended sign" would be more apt. Or, just "sign". C = bit 32 of the sum/difference.
  • evanhevanh Posts: 15,629
    [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.
  • cgraceycgracey Posts: 14,134
    edited 2017-10-01 08:26
    They work like this:

    ADD:
    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]

    ADDS:
    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]
  • evanhevanh Posts: 15,629
    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.
  • cgraceycgracey Posts: 14,134
    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.
  • C for Carry (ADD/SUB/CMP)
    C for Correct sign (ADDS/SUBS/CMPS)
  • cgraceycgracey Posts: 14,134
    edited 2017-10-02 03:47
    TonyB_, I take it you are okay with the state of things, then?
  • TonyB_TonyB_ Posts: 2,159
    edited 2017-10-02 14:44
    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 ?
    
    

  • cgraceycgracey Posts: 14,134
    edited 2017-10-02 19:09
    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!
  • TonyB_TonyB_ Posts: 2,159
    edited 2017-10-04 22:30
    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! :)
  • cgraceycgracey Posts: 14,134
    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.
  • TonyB_ wrote: »
    ... I think. I just need to edit some posts now and re-write history! :)

    Nice!

    Mike
  • cgraceycgracey Posts: 14,134
    edited 2017-10-03 01:02
    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.
  • 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?
  • cgraceycgracey Posts: 14,134
    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!!!!
Sign In or Register to comment.