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

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

cgraceycgracey Posts: 14,134
edited 2017-09-08 22:57 in Propeller 2
I just realized something that maybe could be improved.

The instructions CMPS and CMPSX actually report a 'signed carry' into C (the spreadsheet wrongly said 'overflow'). However ADDS/ADDSX/SUBS/SUBSX do report 'overflow' into C.

I'm thinking that for consistency, CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX should all report a 'signed carry'.

An 'overflow' report only makes sense for SUMC/SUMNC/SUMZ/SUMNZ, I think.

Any agreement or disagreement?
«13456

Comments

  • cgraceycgracey Posts: 14,134
    I ran into this discrepancy when coding the LOOKUP/LOOKDOWN-by-range snippets for the Spin2 interpreter.
  • cgraceycgracey Posts: 14,134
    edited 2017-09-08 23:13
    I don't know why I made ADDS/ADDSX/SUBS/SUBSX report 'overflow'. That made little sense and rendered them useless for normal carry applications. I think they should report 'signed carry', like CMPS/CMPSX do. I think these instructions are not used very often, so nobody bumped into this issue.
  • cgraceycgracey Posts: 14,134
    edited 2017-09-09 00:27
    I just changed ADDS/ADDSX/SUBS/SUBSX to report 'signed' carry. I like this way better.

    For ADDS/ADDSX/SUBS/SUBSX, the C output is bit 32 of the signed result, as it should be. The universe makes more sense now.

    This will be in the next release and what is headed for synthesis.
  • evanhevanh Posts: 15,848
    I thought overflow is the name given to the signed version of carry. I've never tried to use it though.
  • jmgjmg Posts: 15,171
    cgracey wrote: »
    I don't know why I made ADDS/ADDSX/SUBS/SUBSX report 'overflow'. That made little sense and rendered them useless for normal carry applications. I think they should report 'signed carry', like CMPS/CMPSX do. I think these instructions are not used very often, so nobody bumped into this issue.

    The main use I know of for carry-out is for higher precision maths, like 64b or 128b adds, by simple chaining of ADD/SUB.

    Does this new form better support that ?

    Makes sense to have carry-out consistent.
  • cgraceycgracey Posts: 14,134
    edited 2017-09-09 00:29
    evanh wrote: »
    I thought overflow is the name given to the signed version of carry. I've never tried to use it though.

    Overflow in Prop2 means that the result overflowed 32 bits, whether from an add or subtract. We also have signed carry, which might be what others call 'overflow'.

    Still trying to get my head around ADDS/ADDSX behavior regarding C. I'm not understanding something here. Signed carry does make sense for subtracts, by maybe not additions? No problem, I was testing with ADD when I should have been using ADDS. Everything looks fine with this new scheme.
  • RaymanRayman Posts: 14,557
    Need CS major for that one...

    Guess key is that ADDSX and SUBSX work as expected, right?
  • A late-night question literally at first glance: is a 9-bit immediate S always zero-extended first for these signed instructions [and all others] and if so should it be sign-extended?
  • cgraceycgracey Posts: 14,134
    TonyB_ wrote: »
    A late-night question literally at first glance: is a 9-bit immediate S always zero-extended first for these signed instructions [and all others] and if so should it be sign-extended?

    9-bit S immediates are always zero-extended. Sign doesn't come into play until you do some signed instruction.
  • cgraceycgracey Posts: 14,134
    Rayman wrote: »
    Need CS major for that one...

    Guess key is that ADDSX and SUBSX work as expected, right?

    Huh?
  • I guess your distinction between normal carry operation and overflow goes sort of over my head.

    isn't carry a overflow condition? I am sort of confused here

    After about 10 years programming the P1 I finally wrote a program USING addx and subx for longer integer math.

    Just because you put them instructions in the P1 and I stumbled again and again over them in the Propeller Manual. I started a thread about what to do with BigInts and funnily no one has much need for longer ints.

    in my BigInt project I allow for different long sized variables and decided to zero-extend for all non-signed operation and sign-extend for signed operations like CMPS, ADDS SUBS (and MULS, DIVS)

    That did make the most sense to me.

    If a programmer uses signed commands he could expect signed constants also. a 9-bit immediate could be looked at as +0 to +511 or -255 to +255?

    Mike
  • TonyB_TonyB_ Posts: 2,178
    edited 2017-10-04 22:40
    cgracey wrote: »
    I just realized something that maybe could be improved.

    The instructions CMPS and CMPSX actually report a 'signed carry' into C (the spreadsheet wrongly said 'overflow'). However ADDS/ADDSX/SUBS/SUBSX do report 'overflow' into C.

    I'm thinking that for consistency, CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX should all report a 'signed carry'.

    An 'overflow' report only makes sense for SUMC/SUMNC/SUMZ/SUMNZ, I think.

    Any agreement or disagreement?

    For me, there are two issues here:

    1. What the carry flag signifies in ADDS/ADDSX/SUBS/SUBSX.
    2. How to extend 9-bit immediates in CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX.

    Let's concentrate on the first point only for now. There was nothing wrong with how things were and the proposed change is a mistake. The flags must indicate when an overflow has occurred in signed addition or subtraction, i.e. when the sign bit has changed wrongly after

    * adding large positive numbers
    * adding large negative numbers
    * subtracting a large positive number from a large negative number
    * subtracting a large negative number from a large positive number
  • RaymanRayman Posts: 14,557
    edited 2017-09-09 17:48
    Isn't the carry flag often used when doing, say, 64-bit arithmetic with a 32-bit machine?

    You might want to ADDS the lower ints and then ADDSX the upper ints. Right?


    Wait, that was dumb... Guess you just want to capture overflow or underflow...
  • TonyB_TonyB_ Posts: 2,178
    edited 2017-09-09 17:59
    To keep things simple, I suggest using overflow for overflow and underflow, in the same way as carry for carry and borrow.
  • RaymanRayman Posts: 14,557
    Seems like carry for all these signed math operations should work the same way.
    Otherwise, we'll always have to remember that some are different...
  • RaymanRayman Posts: 14,557
    edited 2017-09-09 20:55
    Had to remind myself that "underflow" only applies to floating point, when number gets too small...
    I guess for this case, both too big and to small are both overflow...

    This page says "carry" in signed arithmetic tells you nothing, and to only watch "overflow" flag...
    http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt

  • After playing around with extended integers, I have the feeling that the P1 just does what needs to be done.

    if you add something to a unsigned value and exceed 32bit you get a Carry which you can handle with addx later on.
    if you subtract something from a unsigned value you get a carry if below zero and can handle this with subx later
    when doing the same for signed 32bit values you get no carry when crossing zero, but on both ends and can handle it with addsx abd subsx later.
    I guess this is what chip is meaning with overflow or is it signed carry? I still do not get the difference here.
    The same seems to work for cmp/cmpx and cmps/cmpsx.

    So what I am missing here?

    Mike
  • Cluso99Cluso99 Posts: 18,069
    Do we really need these extra instructions ???
  • TonyB_TonyB_ Posts: 2,178
    edited 2017-09-10 12:30
    msrobots, did you read the text file that Rayman linked to?
  • TonyB_TonyB_ Posts: 2,178
    edited 2017-09-29 00:25
    Cluso99 wrote: »
    Do we really need these extra instructions ???

    The only difference between ADD and ADDS, for example, is the C flag, carry and overflow respectively.

    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.

    C as sign bit could also apply to ADDS/ADDSX/SUBS/SUBSX and SUMC/SUMNC/SUMZ/SUMNZ for consistency and it would save an instruction to test whether the result is negative. Overflow could be signified by C and Z. Four states are possible with two flags as follows:

    NC & NZ - positive result
    NC & Z - zero result (if Z beforehand for ADDS/ADDSX/SUBS/SUBSX)
    C & NZ - negative result
    C & Z - overflow (result cannot be negative and zero at same time)

    The two flags could be tested independently if the range of signed numbers is such that overflow is impossible.
  • evanhevanh Posts: 15,848
    edited 2017-09-11 10:32
    Tony,
    That seems awfully sensible logic.

    Of course that means, for example, testing for the Z flag by itself would have to be banned. To the extent of removing the capability. It's not like the flags are fully accessible now anyway.

    The upside of such an approach is the EEEE instruction encodings will drop to a mere two bits (EE) ... Giving an immediate increase to 22-bit (4 MB) code space. MRAM could really be pushed to its limit then :D

    EDIT: Corrected CCCC to the newer EEEE reference.
  • TonyB_TonyB_ Posts: 2,178
    edited 2017-09-11 19:59
    Thanks, Evan. Using both flags for positive/zero/negative/overflow appears to work very well, however it applies only to signed arithmetic instructions. The C and Z interdependency if overflow possible is a downside but a small one.

    I've edited my previous post to include SUMC/SUMNC/SUMZ/SUMNZ. There are other instructions that can write the sign bit to C, e.g. MOV/NOT/ABS/NEGxx, and one that cannot but could if tweaked a little (see below for details).
  • evanhevanh Posts: 15,848
    edited 2017-09-11 14:09
    Oh, yeah, I wasn't thinking too much about unsigned. It still needs C and Z as separate tests. And so does many other instructions for special uses.

    I suppose it's just a case of the signed instructions having their own special use of the flags.

    EDIT: That's shot down the dream of freeing up a couple of encoding bits. :cry:
  • TonyB_TonyB_ Posts: 2,178
    edited 2017-12-08 20:17
    Related topic:

    Being able to sign-extend from any bit position using SIGNX is excellent but sadly it doesn't tell you what the sign bit actually is and it can't because of the way the instruction is encoded.

    However, if SIGNX were moved to an empty slot in the opcode map, it could do so by writing the sign to C (and setting Z if zero) and I think that would be a worthwhile change.

    Selected existing opcodes (aliases omitted):
    ...
    EEEE 0111110 CZI DDDDDDDDD SSSSSSSSS ANYB    D,{#}S   {WC/WZ/WCZ}
    EEEE 0111111 CZI DDDDDDDDD SSSSSSSSS <empty> D,{#}S   {WC/WZ/WCZ}
    ...
    EEEE 1001110 10I DDDDDDDDD SSSSSSSSS ZEROX   D,{#}S
    EEEE 1001110 11I DDDDDDDDD SSSSSSSSS SIGNX   D,{#}S
    ...
    

    Note there are no opcode bits available in ZEROX and SIGNX for writing either C or Z.

    Proposed change:

    Move SIGNX to empty slot after ANYB.
    Old SIGNX slot used to write Z in ZEROX.
    ...
    EEEE 0111110 CZI DDDDDDDDD SSSSSSSSS ANYB    D,{#}S   {WC/WZ/WCZ}
    EEEE 0111111 CZI DDDDDDDDD SSSSSSSSS SIGNX   D,{#}S   {WC/WZ/WCZ} *changed*
    ...
    EEEE 1001110 1ZI DDDDDDDDD SSSSSSSSS ZEROX   D,{#}S   {WZ}	  *changed*
    ...
    

    ZEROX cannot write C but no point saving sign bit even it were possible as it is always 0. What I'm suggesting here is enhancing a couple of existing instructions by filling an instruction slot that has been empty for some time and otherwise would end up unused.
  • The most common instruction MOV already uses a subset of the four states possible with signed values:

    NC & NZ - positive result
    NC & Z - zero result
    C & NZ - negative result
    C & Z - invalid (overflow impossible)

    All the above discussion really changes in the P2 is C & Z for overflow, not C only.

    Opposing it would be like opposing breathing! :)
  • cgraceycgracey Posts: 14,134
    TonyB_ wrote: »
    The most common instruction MOV already uses a subset of the four states possible with signed values:

    NC & NZ - positive result
    NC & Z - zero result
    C & NZ - negative result
    C & Z - invalid (overflow impossible)

    All the above discussion really changes in the P2 is C & Z for overflow, not C only.

    Opposing it would be like opposing breathing! :)

    TonyB,

    This is a great idea. I never thought of using the flags in combination like that. I need to absorb this a little, though. I'm kind of loathe to change more instruction encodings, at this point. I'm trying to get the Verilog into OnSemi's hands so they can get started on the synthesis work. Let me think about this, though. It's a neat idea.
  • evanhevanh Posts: 15,848
    TonyB_ wrote: »
    NC & NZ - positive result
    NC & Z - zero result
    C & NZ - negative result
    C & Z - invalid (overflow impossible)
    Ah, and with WC/WZ control one can remove WC when used amongst unsigned operations so then it won't go thinking a carry has occurred. Works for me.
  • Perhaps to go with that a new condition alias such as
    	if_ov	jmp	#handle_overflow
    
  • @TonyB

    finally I got it. I read the document, pointed to by @Rayman, but still struggled with the idea. Hmm English is my third language, I am quite bad at it.

    Yes, I like it and if I find some more longs in BigInt-Pasm I will use it. Having different sized Operants is part of BigInts and I was looking for some way to notify when out of bounds.

    I still think that distinguishing signed and not signed operations should be enough to zero or sign extend values. I do not see the need for extra instructions to do this.

    maybe I am wrong there too, so please correct me if you have time...

    Mike
  • Needing both flags to define a state is not new, of course, as positive is NC & NZ.

    The other issue here is how to treat 9-bit immediates in signed arithmetic instructions. Currently they are zero-extended and therefore always positive or zero. Would it be better if they were sign-extended, so that an extra long could be avoided for small negative values?

    If they are true constants at assembly time then there are workarounds, e.g. NOT instead of MOV and SUB instead of ADD. Is that sufficient or would self-modifying code ever create a 9-bit immediate with unpredictable sign?
Sign In or Register to comment.