C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX
cgracey
Posts: 14,152
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?
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?
Comments
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.
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.
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.
Guess key is that ADDSX and SUBSX work as expected, right?
9-bit S immediates are always zero-extended. Sign doesn't come into play until you do some signed instruction.
Huh?
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
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
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...
Otherwise, we'll always have to remember that some are different...
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
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
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.
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
EDIT: Corrected CCCC to the newer EEEE reference.
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).
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.
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):
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.
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.
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.
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
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?