SUBSX
Instruction: Subtract signed value plus C from another signed value.
SUBSX SValue1, < # > SValue2
Result: Difference of signed SValue1, and signed SValue2 plus C flag, is stored in SValue1.
- SValue1 (d-field) is the register containing the value to subtract SValue2 plus C from, and is the destination in which to write the result.
- SValue2 (s-field) is a register or a 9-bit literal whose value plus C is subtracted from SValue1.
Opcode Table:
–INSTR– ZCRI –CON– –DEST– –SRC– | Z Result | C Result | Result | Clocks |
110111 001i 1111 ddddddddd sssssssss | Z & (D–(S+C) = 0) | Signed Overflow | Written | 4 |
Concise Truth Table:
In | Out | ||||||
Destination | Source | Z | C | Effects | Destination | Z | C |
$0000_0001; 1 | $0000_0001; 1 | 0 | 0 | wz wc | $0000_0000; 0 | 0 | 0 |
$0000_0001; 1 | $0000_0001; 1 | 1 | 0 | wz wc | $0000_0000; 0 | 1 | 0 |
$0000_0001; 1 | $0000_0001; 1 | x | 1 | wz wc | $FFFF_FFFF; -1 | 0 | 0 |
$FFFF_FFFF; -1 | $FFFF_FFFF; -1 | 0 | 0 | wz wc | $0000_0000; 0 | 0 | 0 |
$FFFF_FFFF; -1 | $FFFF_FFFF; -1 | 1 | 0 | wz wc | $0000_0000; 0 | 1 | 0 |
$FFFF_FFFF; -1 | $FFFF_FFFF; -1 | x | 1 | wz wc | $FFFF_FFFF; -1 | 0 | 0 |
$8000_0001; -2,147,483,647 | $0000_0001; 1 | x | 0 | wz wc | $8000_0000; -2,147,483,648 | 0 | 0 |
$8000_0001; -2,147,483,647 | $0000_0001; 1 | x | 1 | wz wc | $7FFF_FFFF; 2,147,483,647 | 0 | 1 |
$7FFF_FFFF; 2,147,483,647 | $FFFF_FFFF; -1 | x | 0 | wz wc | $8000_0000; -2,147,483,648 | 0 | 1 |
$7FFF_FFFF; 2,147,483,647 | $FFFF_FFFF; -1 | x | 1 | wz wc | $7FFF_FFFF; 2,147,483,647 | 0 | 0 |
Explanation
SUBSX (Subtract Signed, Extended) subtracts the signed value of SValue2 plus C from SValue1, and stores the result into the SValue1 register. The SUBSX instruction is used to perform signed multi-long subtraction; 64-bit subtractions, for example.
In a signed multi-long operation, the first instruction is unsigned (ex: SUB), any middle instructions are unsigned, extended (ex: SUBX), and the last instruction is signed, extended (ex: SUBSX). Make sure to use the WC, and optionally WZ, effect on the leading SUB and SUBX instructions.
For example, a signed double-long (64-bit) subtraction may look like this:
sub XLow, YLow wc wz 'Subtract low longs; save C and Z subsx XHigh, YHigh 'Subtract high longs
After executing the above, the double-long (64-bit) result is in the long registers XHigh:XLow. If XHigh:XLow started out as $0000_0000:0000_0001 (1) and YHigh:YLow was $0000_0000:0000_0002 (2) the result in XHigh:XLow would be $FFFF_FFFF:FFFF_FFFF (-1). This is demonstrated below.
Hexadecimal Decimal (high) (low) (XHigh:XLow) $0000_0000:0000_0001 1 - (YHigh:YLow) - $0000_0000:0000_0002 - 2 ---------------------- --------------- = $FFFF_FFFF:FFFF_FFFF = -1
A signed triple-long (96-bit) subtraction would look similar but with a SUBX instruction inserted between the SUB and SUBSX instructions:
sub XLow, YLow wc wz 'Subtract low longs; save C and Z subx XMid, YMid wc wz 'Subtract middle longs; save C and Z subsx XHigh, YHigh 'Subtract high longs
Of course, it may be necessary to specify the WC and WZ effects on the final instruction, SUBSX, in order to watch for a result of zero or signed overflow condition. Note that during this multi-step operation the Z flag always indicates if the result is turning out to be zero, but the C flag indicates unsigned borrows until the final instruction, SUBSX, in which it indicates signed overflow.
For SUBSX, if the WZ effect is specified, the Z flag is set (1) if Z was previously set and SValue1 − (SValue2 + C) equals zero (use WC and WZ on preceding SUB and SUBX instructions). If the WC effect is specified, the C flag is set (1) if the subtraction resulted in a signed overflow. The result is written to SValue1 unless the NR effect is specified).
Unless otherwise noted, content on this site is licensed under the
Creative Commons Attribution-ShareAlike 4.0 International License.