aboutsummaryrefslogtreecommitdiff
path: root/sim/common/sim-alu.h
diff options
context:
space:
mode:
authorDoug Evans <dje@google.com>1998-02-23 18:21:14 +0000
committerDoug Evans <dje@google.com>1998-02-23 18:21:14 +0000
commit36dbc8bb7cfa9399b50cdd0e47e617c7be69a280 (patch)
tree158fc81083ea5f0b22544d07791c8dce4445a004 /sim/common/sim-alu.h
parent3aeca4624a9ccaaa084b3d7c619b60dcbcd915b7 (diff)
downloadgdb-36dbc8bb7cfa9399b50cdd0e47e617c7be69a280.zip
gdb-36dbc8bb7cfa9399b50cdd0e47e617c7be69a280.tar.gz
gdb-36dbc8bb7cfa9399b50cdd0e47e617c7be69a280.tar.bz2
* sim-xcat.h: Delete.
* cgen-mem.h: Delete inclusion of sim-xcat.h. * cgen-sim.h: Ditto. * sim-alu.h: Replace sim-xcat.h with symcat.h. * sim-n-bits.h: Ditto. * sim-n-core.h: Ditto. * sim-n-endian.h: Ditto.
Diffstat (limited to 'sim/common/sim-alu.h')
-rw-r--r--sim/common/sim-alu.h801
1 files changed, 649 insertions, 152 deletions
diff --git a/sim/common/sim-alu.h b/sim/common/sim-alu.h
index e556dce..8473680 100644
--- a/sim/common/sim-alu.h
+++ b/sim/common/sim-alu.h
@@ -23,48 +23,203 @@
#ifndef _SIM_ALU_H_
#define _SIM_ALU_H_
-#include "sim-xcat.h"
+#include "symcat.h"
-/* Binary addition, carry and overflow:
+/* INTEGER ALU MODULE:
+ This module provides an implementation of 2's complement arithmetic
+ including the recording of carry and overflow status bits.
- Overflow - method 1:
- Overflow occures when the sign of the two operands is identical but
- different to the sign of the result:
+ EXAMPLE:
- SIGN_BIT (~(a ^ b) & ((a + b) ^ b))
+ Code using this module includes it into sim-main.h and then, as a
+ convention, defines macro's ALU*_END that records the result of any
+ aritmetic performed. Ex:
- Note that, for subtraction, care must be taken with MIN_INTn.
+ #include "sim-alu.h"
+ #define ALU32_END(RES) \
+ (RES) = ALU32_OVERFLOW_RESULT; \
+ carry = ALU32_HAD_CARRY_BORROW; \
+ overflow = ALU32_HAD_OVERFLOW
+ The macro's are then used vis:
+
+ {
+ ALU32_BEGIN (GPR[i]);
+ ALU32_ADDC (GPR[j]);
+ ALU32_END (GPR[k]);
+ }
+
+
+ NOTES:
+
+ Macros exist for efficiently computing 8, 16, 32 and 64 bit
+ arithmetic - ALU8_*, ALU16_*, .... In addition, according to
+ TARGET_WORD_BITSIZE a set of short-hand macros are defined - ALU_*
+
+ Initialization:
+
+ ALU*_BEGIN(ACC): Declare initialize the ALU accumulator with ACC.
+
+ Results:
+
+ The calculation of the final result may be computed a number
+ of different ways. Three different overflow macro's are
+ defined, the most efficient one to use depends on which other
+ outputs from the alu are being used.
+
+ ALU*_RESULT: Generic ALU result output.
+
+ ALU*_HAD_OVERFLOW: Returns a nonzero value if signed overflow
+ occured.
+
+ ALU*_OVERFLOW_RESULT: If the macro ALU*_HAD_OVERFLOW is being
+ used this is the most efficient result available. Ex:
+
+ #define ALU16_END(RES) \
+ if (ALU16_HAD_OVERFLOW) \
+ sim_engine_halt (...); \
+ (RES) = ALU16_OVERFLOW_RESULT
+
+ ALU*_HAD_CARRY_BORROW: Returns a nonzero value if unsigned
+ overflow or underflow (also refered to as carry and borrow)
+ occured.
+
+ ALU*_CARRY_BORROW_RESULT: If the macro ALU*_HAD_CARRY_BORROW is being
+ used this is the most efficient result available. Ex:
+
+ #define ALU64_END(RES) \
+ State.carry = ALU64_HAD_CARRY_BORROW; \
+ (RES) = ALU64_CARRY_BORROW_RESULT
+
+
+ Addition:
+
+ ALU*_ADD(VAL): Add VAL to the ALU accumulator. Record any
+ overflow as well as the final result.
+
+ ALU*_ADDC(VAL): Add VAL to the ALU accumulator. Record any
+ carry-out or overflow as well as the final result.
+
+ ALU*_ADDC_C(VAL,CI): Add VAL and CI (carry-in). Record any
+ carry-out or overflow as well as the final result.
+
+ Subtraction:
+
+ ALU*_SUB(VAL): Subtract VAL from the ALU accumulator. Record
+ any underflow as well as the final result.
+
+ ALU*_SUBC(VAL): Subtract VAL from the ALU accumulator using
+ negated addition. Record any underflow or carry-out as well
+ as the final result.
+
+ ALU*_SUBB(VAL): Subtract VAL from the ALU accumulator using
+ direct subtraction (ACC+~VAL+1). Record any underflow or
+ borrow-out as well as the final result.
+
+ ALU*_SUBC_X(VAL,CI): Subtract VAL and CI (carry-in) from the
+ ALU accumulator using extended negated addition (ACC+~VAL+CI).
+ Record any underflow or carry-out as well as the final result.
+
+ ALU*_SUBB_B(VAL,BI): Subtract VAL and BI (borrow-in) from the
+ ALU accumulator using direct subtraction. Record any
+ underflow or borrow-out as well as the final result.
+
+
+ */
+
+
+
+/* Twos complement aritmetic - addition/subtraction - carry/borrow
+ (or you thought you knew the answer to 0-0)
+
+
+
+ Notation and Properties:
+
+
+ Xn denotes the value X stored in N bits.
+
+ MSBn (X): The most significant (sign) bit of X treated as an N bit
+ value.
+
+ SEXTn (X): The infinite sign extension of X treated as an N bit
+ value.
+
+ MAXn, MINn: The upper and lower bound of a signed, two's
+ complement N bit value.
+
+ UMAXn: The upper bound of an unsigned N bit value (the lower
+ bound is always zero).
+
+ Un: UMAXn + 1. Unsigned arrithmetic is computed `modulo (Un)'.
+
+ X[p]: Is bit P of X. X[0] denotes the least signifant bit.
+
+ ~X[p]: Is the inversion of bit X[p]. Also equal to 1-X[p],
+ (1+X[p])mod(2).
+
+
+
+ Addition - Overflow - Introduction:
+
+
+ Overflow/Overflow indicates an error in computation of signed
+ arrithmetic. i.e. given X,Y in [MINn..MAXn]; overflow
+ indicates that the result X+Y > MAXn or X+Y < MIN_INTx.
+
+ Hardware traditionally implements overflow by computing the XOR of
+ carry-in/carry-out of the most significant bit of the ALU. Here
+ other methods need to be found.
+
+
+
+ Addition - Overflow - method 1:
+
+
+ Overflow occures when the sign (most significant bit) of the two N
+ bit operands is identical but different to the sign of the result:
+
+ Rn = (Xn + Yn)
+ V = MSBn (~(Xn ^ Yn) & (Rn ^ Xn))
+
+
+
+ Addition - Overflow - method 2:
- Overflow - method 2:
The two N bit operands are sign extended to M>N bits and then
added. Overflow occures when SIGN_BIT<n> and SIGN_BIT<m> do not
match.
- SIGN_BIT (r >> (M-N) ^ r)
+ Rm = (SEXTn (Xn) + SEXTn (Yn))
+ V = MSBn ((Rm >> (M - N)) ^ Rm)
+
- Overflow - method 3:
+ Addition - Overflow - method 3:
+
The two N bit operands are sign extended to M>N bits and then
- added. Overflow occures when the result is outside of signextended
- MIN_INTn, MAX_INTn.
+ added. Overflow occures when the result is outside of the sign
+ extended range [MINn .. MAXn].
+
- Overflow - method 4:
+ Addition - Overflow - method 4:
- Given the carry bit, the overflow can be computed using the
- equation:
- SIGN_BIT (((A ^ B) ^ R) ^ C)
+ Given the Result and Carry-out bits, the oVerflow from the addition
+ of X, Y and carry-In can be computed using the equation:
+
+ Rn = (Xn + Yn)
+ V = (MSBn ((Xn ^ Yn) ^ Rn)) ^ C)
As shown in the table below:
- I A B R C | V | A^B ^R ^C
+ I X Y R C | V | X^Y ^R ^C
---------------+---+-------------
0 0 0 0 0 | 0 | 0 0 0
0 0 1 1 0 | 0 | 1 0 0
@@ -77,11 +232,17 @@
- Carry - method 1:
+ Addition - Carry - Introduction:
+
- Consider the truth table (carryIn, Result, Carryout, Result):
+ Carry (poorly named) indicates that an overflow occured for
+ unsigned N bit addition. i.e. given X, Y in [0..UMAXn] then
+ carry indicates X+Y > UMAXn or X+Y >= Un.
- I A B R | C
+ The following table lists the output for all given inputs into a
+ full-adder.
+
+ I X Y R | C
------------+---
0 0 0 0 | 0
0 0 1 1 | 0
@@ -92,9 +253,16 @@
1 1 0 0 | 1
1 1 1 1 | 1
- Looking at the terms A, B and R we want an equation for C.
+ (carry-In, X, Y, Result, Carry-out):
+
+
+
+ Addition - Carry - method 1:
+
+
+ Looking at the terms X, Y and R we want an equation for C.
- AB\R 0 1
+ XY\R 0 1
+-------
00 | 0 0
01 | 1 0
@@ -103,11 +271,11 @@
This giving us the sum-of-prod equation:
- SIGN_BIT ((A & B) | (A & ~R) | (B & ~R))
+ MSBn ((Xn & Yn) | (Xn & ~Rn) | (Yn & ~Rn))
Verifying:
- I A B R | C | A&B A&~R B&~R
+ I X Y R | C | X&Y X&~R Y&~R
------------+---+---------------
0 0 0 0 | 0 | 0 0 0
0 0 1 1 | 0 | 0 0 0
@@ -120,32 +288,136 @@
- Carry - method 2:
+ Addition - Carry - method 2:
+
Given two signed N bit numbers, a carry can be detected by treating
the numbers as N bit unsigned and adding them using M>N unsigned
arrithmetic. Carry is indicated by bit (1 << N) being set (result
>= 2**N).
- SIGN_BITm (r)
- Carry - method 3:
+ Addition - Carry - method 3:
+
- Given the overflow bit. The carry can be computed from:
+ Given the oVerflow bit. The carry can be computed from:
(~R&V) | (R&V)
- Carry - method 4:
- Add the two signed N bit numbers as unsigned N bit numbers, and then
- compare the result to either one of the inputs via unsigned compare.
- If the result is less than the inputs, carry occurred.
- C = ((unsigned)(a+b)) < (unsigned)a if adding
- (or)
- C = (unsigned)a < (unsigned)b if subtracting
- */
+ Addition - Carry - method 4:
+
+ Given two signed numbers. Treating them as unsigned we have:
+
+ 0 <= X < Un, 0 <= Y < Un
+ ==> X + Y < 2 Un
+
+ Consider Y when carry occures:
+
+ X + Y >= Un, Y < Un
+ ==> (Un - X) <= Y < Un # re-arange
+ ==> Un <= X + Y < Un + X < 2 Un # add Xn
+ ==> 0 <= (X + Y) mod Un < X mod Un
+
+ or when carry as occured:
+
+ (X + Y) mod Un < X mod Un
+
+ Consider Y when carry does not occure:
+
+ X + Y < Un
+ have X < Un, Y >= 0
+ ==> X <= X + Y < Un
+ ==> X mod Un <= (X + Y) mod Un
+
+ or when carry has not occured:
+
+ ! ( (X + Y) mod Un < X mod Un)
+
+
+
+ Subtraction - Introduction
+
+
+ There are two different ways of computing the signed two's
+ complement difference of two numbers. The first is based on
+ negative addition, the second on direct subtraction.
+
+
+
+ Subtraction - Carry - Introduction - Negated Addition
+
+
+ The equation X - Y can be computed using:
+
+ X + (-Y)
+ ==> X + ~Y + 1 # -Y = ~Y + 1
+
+ In addition to the result, the equation produces Carry-out. For
+ succeeding extended prrcision calculations, the more general
+ equation can be used:
+
+ C[p]:R[p] = X[p] + ~Y[p] + C[p-1]
+ where C[0]:R[0] = X[0] + ~Y[0] + 1
+
+
+
+ Subtraction - Borrow - Introduction - Direct Subtraction
+
+
+ The alternative to negative addition is direct subtraction where
+ `X-Y is computed directly. In addition to the result of the
+ calculation, a Borrow bit is produced. In general terms:
+
+ B[p]:R[p] = X[p] - Y[p] - B[p-1]
+ where B[0]:R[0] = X[0] - Y[0]
+
+ The Borrow bit is the complement of the Carry bit produced by
+ Negated Addition above. A dodgy proof follows:
+
+ Case 0:
+ C[0]:R[0] = X[0] + ~Y[0] + 1
+ ==> C[0]:R[0] = X[0] + 1 - Y[0] + 1 # ~Y[0] = (1 - Y[0])?
+ ==> C[0]:R[0] = 2 + X[0] - Y[0]
+ ==> C[0]:R[0] = 2 + B[0]:R[0]
+ ==> C[0]:R[0] = (1 + B[0]):R[0]
+ ==> C[0] = ~B[0] # (1 + B[0]) mod 2 = ~B[0]?
+
+ Case P:
+ C[p]:R[p] = X[p] + ~Y[p] + C[p-1]
+ ==> C[p]:R[p] = X[p] + 1 - Y[0] + 1 - B[p-1]
+ ==> C[p]:R[p] = 2 + X[p] - Y[0] - B[p-1]
+ ==> C[p]:R[p] = 2 + B[p]:R[p]
+ ==> C[p]:R[p] = (1 + B[p]):R[p]
+ ==> C[p] = ~B[p]
+
+ The table below lists all possible inputs/outputs for a
+ full-subtractor:
+
+ X Y I | R B
+ 0 0 0 | 0 0
+ 0 0 1 | 1 1
+ 0 1 0 | 1 1
+ 0 1 1 | 0 1
+ 1 0 0 | 1 0
+ 1 0 1 | 0 0
+ 1 1 0 | 0 0
+ 1 1 1 | 1 1
+
+
+
+ Subtraction - Method 1
+
+
+ Treating Xn and Yn as unsigned values then a borrow (unsigned
+ underflow) occures when:
+
+ B = Xn < Yn
+ ==> C = Xn >= Yn
+
+ */
@@ -155,26 +427,26 @@
overflow method 2 are used. */
#define ALU8_BEGIN(VAL) \
-signed alu8_cr = (unsigned8) (VAL); \
-unsigned alu8_vr = (signed8) (alu8_cr)
+unsigned alu8_cr = (unsigned8) (VAL); \
+signed alu8_vr = (signed8) (alu8_cr)
#define ALU8_SET(VAL) \
alu8_cr = (unsigned8) (VAL); \
alu8_vr = (signed8) (alu8_cr)
-#define ALU8_SET_CARRY(CARRY) \
+#define ALU8_SET_CARRY_BORROW(CARRY) \
do { \
if (CARRY) \
alu8_cr |= ((signed)-1) << 8; \
else \
alu8_cr &= 0xff; \
} while (0)
-
-#define ALU8_HAD_CARRY (alu8_cr & LSBIT32(8))
+
+#define ALU8_HAD_CARRY_BORROW (alu8_cr & LSBIT32(8))
#define ALU8_HAD_OVERFLOW (((alu8_vr >> 8) ^ alu8_vr) & LSBIT32 (8-1))
#define ALU8_RESULT ((unsigned8) alu8_cr)
-#define ALU8_CARRY_RESULT ((unsigned8) alu8_cr)
+#define ALU8_CARRY_BORROW_RESULT ((unsigned8) alu8_cr)
#define ALU8_OVERFLOW_RESULT ((unsigned8) alu8_vr)
/* #define ALU8_END ????? - target dependant */
@@ -194,7 +466,7 @@ unsigned alu16_vr = (signed16) (alu16_cr)
alu16_cr = (unsigned16) (VAL); \
alu16_vr = (signed16) (alu16_cr)
-#define ALU16_SET_CARRY(CARRY) \
+#define ALU16_SET_CARRY_BORROW(CARRY) \
do { \
if (CARRY) \
alu16_cr |= ((signed)-1) << 16; \
@@ -202,11 +474,11 @@ do { \
alu16_cr &= 0xffff; \
} while (0)
-#define ALU16_HAD_CARRY (alu16_cr & LSBIT32(16))
+#define ALU16_HAD_CARRY_BORROW (alu16_cr & LSBIT32(16))
#define ALU16_HAD_OVERFLOW (((alu16_vr >> 16) ^ alu16_vr) & LSBIT32 (16-1))
#define ALU16_RESULT ((unsigned16) alu16_cr)
-#define ALU16_CARRY_RESULT ((unsigned16) alu16_cr)
+#define ALU16_CARRY_BORROW_RESULT ((unsigned16) alu16_cr)
#define ALU16_OVERFLOW_RESULT ((unsigned16) alu16_vr)
/* #define ALU16_END ????? - target dependant */
@@ -216,10 +488,7 @@ do { \
/* 32 bit target expressions:
Since most hosts do not support 64 (> 32) bit arrithmetic, carry
- method 4 and overflow method 4 are used.
-
- FIXME: 64 bit hosts should use the same method as for the 16 bit
- ALU. */
+ method 4 and overflow method 4 are used. */
#define ALU32_BEGIN(VAL) \
unsigned32 alu32_r = (VAL); \
@@ -231,13 +500,13 @@ alu32_r = (VAL); \
alu32_c = 0; \
alu32_v = 0
-#define ALU32_SET_CARRY(CARRY) alu32_c = (CARRY)
+#define ALU32_SET_CARRY_BORROW(CARRY) alu32_c = (CARRY)
+#define ALU32_HAD_CARRY_BORROW (alu32_c)
#define ALU32_HAD_OVERFLOW (alu32_v)
-#define ALU32_HAD_CARRY (alu32_c)
#define ALU32_RESULT (alu32_r)
-#define ALU32_CARRY_RESULT (alu32_r)
+#define ALU32_CARRY_BORROW_RESULT (alu32_r)
#define ALU32_OVERFLOW_RESULT (alu32_r)
@@ -257,13 +526,13 @@ alu64_r = (VAL); \
alu64_c = 0; \
alu64_v = 0
-#define ALU64_SET_CARRY(CARRY) alu64_c = (CARRY)
+#define ALU64_SET_CARRY_BORROW(CARRY) alu64_c = (CARRY)
-#define ALU64_HAD_CARRY (alu64_c)
+#define ALU64_HAD_CARRY_BORROW (alu64_c)
#define ALU64_HAD_OVERFLOW (alu64_v)
#define ALU64_RESULT (alu64_r)
-#define ALU64_CARRY_RESULT (alu64_r)
+#define ALU64_CARRY_BORROW_RESULT (alu64_r)
#define ALU64_OVERFLOW_RESULT (alu64_r)
@@ -283,141 +552,402 @@ alu64_v = 0
-/* Basic operations */
-
+/* Basic operation - add (overflowing) */
#define ALU8_ADD(VAL) \
do { \
- unsigned8 alu8_tmp = (VAL); \
- alu8_cr += (unsigned8)(alu8_tmp); \
- alu8_vr += (signed8)(alu8_tmp); \
+ unsigned8 alu8add_val = (VAL); \
+ ALU8_ADDC (alu8add_val); \
} while (0)
#define ALU16_ADD(VAL) \
do { \
- unsigned16 alu16_tmp = (VAL); \
- alu16_cr += (unsigned16)(alu16_tmp); \
- alu16_vr += (signed16)(alu16_tmp); \
+ unsigned16 alu16add_val = (VAL); \
+ ALU16_ADDC (alu8add_val); \
} while (0)
#define ALU32_ADD(VAL) \
do { \
- unsigned32 alu32_tmp = (unsigned32) (VAL); \
- unsigned32 alu32_sign = alu32_tmp ^ alu32_r; \
- alu32_r += (alu32_tmp); \
- alu32_c = (alu32_r < alu32_tmp); \
- alu32_v = ((alu32_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \
+ unsigned32 alu32add_val = (VAL); \
+ ALU32_ADDC (alu32add_val); \
} while (0)
#define ALU64_ADD(VAL) \
do { \
- unsigned64 alu64_tmp = (unsigned64) (VAL); \
- unsigned64 alu64_sign = alu64_tmp ^ alu64_r; \
- alu64_r += (alu64_tmp); \
- alu64_c = (alu64_r < alu64_tmp); \
- alu64_v = ((alu64_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \
+ unsigned64 alu64add_val = (unsigned64) (VAL); \
+ ALU64_ADDC (alu64add_val); \
+} while (0)
+
+#define ALU_ADD XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD)
+
+
+
+/* Basic operation - add carrying (and overflowing) */
+
+#define ALU8_ADDC(VAL) \
+do { \
+ unsigned8 alu8addc_val = (VAL); \
+ alu8_cr += (unsigned8)(alu8addc_val); \
+ alu8_vr += (signed8)(alu8addc_val); \
+} while (0)
+
+#define ALU16_ADDC(VAL) \
+do { \
+ unsigned16 alu16addc_val = (VAL); \
+ alu16_cr += (unsigned16)(alu16addc_val); \
+ alu16_vr += (signed16)(alu16addc_val); \
} while (0)
-#define ALU_ADD(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD)(VAL)
+#define ALU32_ADDC(VAL) \
+do { \
+ unsigned32 alu32addc_val = (VAL); \
+ unsigned32 alu32addc_sign = alu32addc_val ^ alu32_r; \
+ alu32_r += (alu32addc_val); \
+ alu32_c = (alu32_r < alu32addc_val); \
+ alu32_v = ((alu32addc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \
+} while (0)
+
+#define ALU64_ADDC(VAL) \
+do { \
+ unsigned64 alu64addc_val = (unsigned64) (VAL); \
+ unsigned64 alu64addc_sign = alu64addc_val ^ alu64_r; \
+ alu64_r += (alu64addc_val); \
+ alu64_c = (alu64_r < alu64addc_val); \
+ alu64_v = ((alu64addc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \
+} while (0)
+
+#define ALU_ADDC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC)
-#define ALU8_ADD_CA(VAL) \
+/* Compound operation - add carrying (and overflowing) with carry-in */
+
+#define ALU8_ADDC_C(VAL,C) \
do { \
- unsigned8 alu8_ca_tmp = (VAL) + ALU8_HAD_CARRY; \
- ALU8_ADD(alu8_ca_tmp); \
+ unsigned8 alu8addcc_val = (VAL); \
+ unsigned8 alu8addcc_c = (C); \
+ alu8_cr += (unsigned)(unsigned8)alu8addcc_val + alu8addcc_c; \
+ alu8_vr += (signed)(signed8)(alu8addcc_val) + alu8addcc_c; \
} while (0)
-#define ALU16_ADD_CA(VAL) \
+#define ALU16_ADDC_C(VAL,C) \
do { \
- unsigned16 alu16_ca_tmp = (VAL) + ALU16_HAD_CARRY; \
- ALU16_ADD(alu16_ca_tmp); \
+ unsigned16 alu16addcc_val = (VAL); \
+ unsigned16 alu16addcc_c = (C); \
+ alu16_cr += (unsigned)(unsigned16)alu16addcc_val + alu16addcc_c; \
+ alu16_vr += (signed)(signed16)(alu16addcc_val) + alu16addcc_c; \
} while (0)
-#define ALU32_ADD_CA(VAL) \
+#define ALU32_ADDC_C(VAL,C) \
do { \
- unsigned32 alu32_ca_tmp = (VAL) + ALU32_HAD_CARRY; \
- ALU32_ADD(alu32_ca_tmp); \
+ unsigned32 alu32addcc_val = (VAL); \
+ unsigned32 alu32addcc_c = (C); \
+ unsigned32 alu32addcc_sign = (alu32addcc_val ^ alu32_r); \
+ alu32_r += (alu32addcc_val + alu32addcc_c); \
+ alu32_c = ((alu32_r < alu32addcc_val) \
+ || (alu32addcc_c && alu32_r == alu32addcc_val)); \
+ alu32_v = ((alu32addcc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31;\
} while (0)
-#define ALU64_ADD_CA(VAL) \
+#define ALU64_ADDC_C(VAL,C) \
do { \
- unsigned64 alu64_ca_tmp = (VAL) + ALU64_HAD_CARRY; \
- ALU64_ADD(alu64_ca_tmp); \
+ unsigned64 alu64addcc_val = (VAL); \
+ unsigned64 alu64addcc_c = (C); \
+ unsigned64 alu64addcc_sign = (alu64addcc_val ^ alu64_r); \
+ alu64_r += (alu64addcc_val + alu64addcc_c); \
+ alu64_c = ((alu64_r < alu64addcc_val) \
+ || (alu64addcc_c && alu64_r == alu64addcc_val)); \
+ alu64_v = ((alu64addcc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63;\
} while (0)
-#define ALU_ADD_CA(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD_CA)(VAL)
+#define ALU_ADDC_C XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC_C)
-/* Remember: Hardware implements subtract as an ADD with a carry in of
- 1 into the least significant bit */
+/* Basic operation - subtract (overflowing) */
#define ALU8_SUB(VAL) \
do { \
- signed alu8sub_val = ~(VAL); \
- ALU8_ADD (alu8sub_val); \
- ALU8_ADD (1); \
+ unsigned8 alu8sub_val = (VAL); \
+ ALU8_ADDC_C (~alu8sub_val, 1); \
} while (0)
#define ALU16_SUB(VAL) \
do { \
- signed alu16sub_val = ~(VAL); \
- ALU16_ADD (alu16sub_val); \
- ALU16_ADD (1); \
+ unsigned16 alu16sub_val = (VAL); \
+ ALU16_ADDC_C (~alu16sub_val, 1); \
} while (0)
#define ALU32_SUB(VAL) \
do { \
- unsigned32 alu32_tmp = (unsigned32) (VAL); \
- unsigned32 alu32_sign = alu32_tmp ^ alu32_r; \
- alu32_c = (alu32_r < alu32_tmp); \
- alu32_r -= (alu32_tmp); \
- alu32_v = ((alu32_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \
+ unsigned32 alu32sub_val = (VAL); \
+ ALU32_ADDC_C (~alu32sub_val, 1); \
} while (0)
#define ALU64_SUB(VAL) \
do { \
- unsigned64 alu64_tmp = (unsigned64) (VAL); \
- unsigned64 alu64_sign = alu64_tmp ^ alu64_r; \
- alu64_c = (alu64_r < alu64_tmp); \
- alu64_r -= (alu64_tmp); \
- alu64_v = ((alu64_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \
+ unsigned64 alu64sub_val = (VAL); \
+ ALU64_ADDC_C (~alu64sub_val, 1); \
+} while (0)
+
+#define ALU_SUB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)
+
+
+
+/* Basic operation - subtract carrying (and overflowing) */
+
+#define ALU8_SUBC(VAL) \
+do { \
+ unsigned8 alu8subc_val = (VAL); \
+ ALU8_ADDC_C (~alu8subc_val, 1); \
} while (0)
-#define ALU_SUB(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)(VAL)
+#define ALU16_SUBC(VAL) \
+do { \
+ unsigned16 alu16subc_val = (VAL); \
+ ALU16_ADDC_C (~alu16subc_val, 1); \
+} while (0)
+#define ALU32_SUBC(VAL) \
+do { \
+ unsigned32 alu32subc_val = (VAL); \
+ ALU32_ADDC_C (~alu32subc_val, 1); \
+} while (0)
+
+#define ALU64_SUBC(VAL) \
+do { \
+ unsigned64 alu64subc_val = (VAL); \
+ ALU64_ADDC_C (~alu64subc_val, 1); \
+} while (0)
+#define ALU_SUBC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC)
-#define ALU8_SUB_CA(VAL) \
+
+/* Compound operation - subtract carrying (and overflowing), extended */
+
+#define ALU8_SUBC_X(VAL,C) \
do { \
- unsigned8 alu8_ca_tmp = (VAL) + ALU8_HAD_CARRY; \
- ALU8_SUB(alu8_ca_tmp); \
+ unsigned8 alu8subcx_val = (VAL); \
+ unsigned8 alu8subcx_c = (C); \
+ ALU8_ADDC_C (~alu8subcx_val, alu8subcx_c); \
} while (0)
-#define ALU16_SUB_CA(VAL) \
+#define ALU16_SUBC_X(VAL,C) \
do { \
- unsigned16 alu16_ca_tmp = (VAL) + ALU16_HAD_CARRY; \
- ALU16_SUB(alu16_ca_tmp); \
+ unsigned16 alu16subcx_val = (VAL); \
+ unsigned16 alu16subcx_c = (C); \
+ ALU16_ADDC_C (~alu16subcx_val, alu16subcx_c); \
} while (0)
-#define ALU32_SUB_CA(VAL) \
+#define ALU32_SUBC_X(VAL,C) \
do { \
- unsigned32 alu32_ca_tmp = (VAL) + ALU32_HAD_CARRY; \
- ALU32_SUB(alu32_ca_tmp); \
+ unsigned32 alu32subcx_val = (VAL); \
+ unsigned32 alu32subcx_c = (C); \
+ ALU32_ADDC_C (~alu32subcx_val, alu32subcx_c); \
} while (0)
-#define ALU64_SUB_CA(VAL) \
+#define ALU64_SUBC_X(VAL,C) \
+do { \
+ unsigned64 alu64subcx_val = (VAL); \
+ unsigned64 alu64subcx_c = (C); \
+ ALU64_ADDC_C (~alu64subcx_val, alu64subcx_c); \
+} while (0)
+
+#define ALU_SUBC_X XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC_X)
+
+
+
+/* Basic operation - subtract borrowing (and overflowing) */
+
+#define ALU8_SUBB(VAL) \
+do { \
+ unsigned8 alu8subb_val = (VAL); \
+ alu8_cr -= (unsigned)(unsigned8)alu8subb_val; \
+ alu8_vr -= (signed)(signed8)alu8subb_val; \
+} while (0)
+
+#define ALU16_SUBB(VAL) \
+do { \
+ unsigned16 alu16subb_val = (VAL); \
+ alu16_cr -= (unsigned)(unsigned16)alu16subb_val; \
+ alu16_vr -= (signed)(signed16)alu16subb_val; \
+} while (0)
+
+#define ALU32_SUBB(VAL) \
+do { \
+ unsigned32 alu32subb_val = (VAL); \
+ unsigned32 alu32subb_sign = alu32subb_val ^ alu32_r; \
+ alu32_c = (alu32_r < alu32subb_val); \
+ alu32_r -= (alu32subb_val); \
+ alu32_v = ((alu32subb_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \
+} while (0)
+
+#define ALU64_SUBB(VAL) \
+do { \
+ unsigned64 alu64subb_val = (VAL); \
+ unsigned64 alu64subb_sign = alu64subb_val ^ alu64_r; \
+ alu64_c = (alu64_r < alu64subb_val); \
+ alu64_r -= (alu64subb_val); \
+ alu64_v = ((alu64subb_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 31; \
+} while (0)
+
+#define ALU_SUBB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB)
+
+
+
+/* Compound operation - subtract borrowing (and overflowing) with borrow-in */
+
+#define ALU8_SUBB_B(VAL,B) \
+do { \
+ unsigned8 alu8subbb_val = (VAL); \
+ unsigned8 alu8subbb_b = (B); \
+ alu8_cr -= (unsigned)(unsigned8)alu8subbb_val; \
+ alu8_cr -= (unsigned)(unsigned8)alu8subbb_b; \
+ alu8_vr -= (signed)(signed8)alu8subbb_val + alu8subbb_b; \
+} while (0)
+
+#define ALU16_SUBB_B(VAL,B) \
+do { \
+ unsigned16 alu16subbb_val = (VAL); \
+ unsigned16 alu16subbb_b = (B); \
+ alu16_cr -= (unsigned)(unsigned16)alu16subbb_val; \
+ alu16_cr -= (unsigned)(unsigned16)alu16subbb_b; \
+ alu16_vr -= (signed)(signed16)alu16subbb_val + alu16subbb_b; \
+} while (0)
+
+#define ALU32_SUBB_B(VAL,B) \
+do { \
+ unsigned32 alu32subbb_val = (VAL); \
+ unsigned32 alu32subbb_b = (B); \
+ ALU32_ADDC_C (~alu32subbb_val, !alu32subbb_b); \
+ alu32_c = !alu32_c; \
+} while (0)
+
+#define ALU64_SUBB_B(VAL,B) \
+do { \
+ unsigned64 alu64subbb_val = (VAL); \
+ unsigned64 alu64subbb_b = (B); \
+ ALU64_ADDC_C (~alu64subbb_val, !alu64subbb_b); \
+ alu64_c = !alu64_c; \
+} while (0)
+
+#define ALU_SUBB_B XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB_B)
+
+
+
+/* Basic operation - negate (overflowing) */
+
+#define ALU8_NEG() \
+do { \
+ signed alu8neg_val = (ALU8_RESULT); \
+ ALU8_SET (1); \
+ ALU8_ADDC (~alu8neg_val); \
+} while (0)
+
+#define ALU16_NEG() \
+do { \
+ signed alu16neg_val = (ALU16_RESULT); \
+ ALU16_SET (1); \
+ ALU16_ADDC (~alu16neg_val); \
+} while (0)
+
+#define ALU32_NEG() \
+do { \
+ unsigned32 alu32neg_val = (ALU32_RESULT); \
+ ALU32_SET (1); \
+ ALU32_ADDC (~alu32neg_val); \
+} while(0)
+
+#define ALU64_NEG() \
do { \
- unsigned64 alu64_ca_tmp = (VAL) + ALU64_HAD_CARRY; \
- ALU64_SUB(alu64_ca_tmp); \
+ unsigned64 alu64neg_val = (ALU64_RESULT); \
+ ALU64_SET (1); \
+ ALU64_ADDC (~alu64neg_val); \
} while (0)
-#define ALU_SUB_CA(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB_CA)(VAL)
+#define ALU_NEG XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEG)
+
+/* Basic operation - negate carrying (and overflowing) */
+
+#define ALU8_NEGC() \
+do { \
+ signed alu8negc_val = (ALU8_RESULT); \
+ ALU8_SET (1); \
+ ALU8_ADDC (~alu8negc_val); \
+} while (0)
+
+#define ALU16_NEGC() \
+do { \
+ signed alu16negc_val = (ALU16_RESULT); \
+ ALU16_SET (1); \
+ ALU16_ADDC (~alu16negc_val); \
+} while (0)
+
+#define ALU32_NEGC() \
+do { \
+ unsigned32 alu32negc_val = (ALU32_RESULT); \
+ ALU32_SET (1); \
+ ALU32_ADDC (~alu32negc_val); \
+} while(0)
+
+#define ALU64_NEGC() \
+do { \
+ unsigned64 alu64negc_val = (ALU64_RESULT); \
+ ALU64_SET (1); \
+ ALU64_ADDC (~alu64negc_val); \
+} while (0)
+
+#define ALU_NEGC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGC)
+
+
+
+
+/* Basic operation - negate borrowing (and overflowing) */
+
+#define ALU8_NEGB() \
+do { \
+ signed alu8negb_val = (ALU8_RESULT); \
+ ALU8_SET (0); \
+ ALU8_SUBB (alu8negb_val); \
+} while (0)
+
+#define ALU16_NEGB() \
+do { \
+ signed alu16negb_val = (ALU16_RESULT); \
+ ALU16_SET (0); \
+ ALU16_SUBB (alu16negb_val); \
+} while (0)
+
+#define ALU32_NEGB() \
+do { \
+ unsigned32 alu32negb_val = (ALU32_RESULT); \
+ ALU32_SET (0); \
+ ALU32_SUBB (alu32negb_val); \
+} while(0)
+
+#define ALU64_NEGB() \
+do { \
+ unsigned64 alu64negb_val = (ALU64_RESULT); \
+ ALU64_SET (0); \
+ ALU64_SUBB (alu64negb_val); \
+} while (0)
+
+#define ALU_NEGB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGB)
+
+
+
+
+/* Other */
+
+#define ALU8_OR(VAL) \
+do { \
+ error("ALU16_OR"); \
+} while (0)
+
#define ALU16_OR(VAL) \
do { \
error("ALU16_OR"); \
@@ -465,39 +995,6 @@ do { \
-#define ALU8_NEGATE() \
-do { \
- signed alu8neg_val = ~(ALU8_RESULT); \
- ALU8_SET (1); \
- ALU8_ADD (alu8neg_val); \
-} while (0)
-
-#define ALU16_NEGATE() \
-do { \
- signed alu16neg_val = ~(ALU16_RESULT); \
- ALU16_SET (1); \
- ALU16_ADD (alu16neg_val); \
-} while (0)
-
-#define ALU32_NEGATE() \
-do { \
- unsigned32 alu32_tmp_orig = alu32_r; \
- ALU32_SET (0); \
- ALU32_SUB (alu32_tmp_orig); \
-} while(0)
-
-#define ALU64_NEGATE() \
-do { \
- unsigned64 alu64_tmp_orig = alu64_r; \
- ALU64_SET (0); \
- ALU64_SUB (alu64_tmp_orig); \
-} while (0)
-
-#define ALU_NEGATE XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGATE)
-
-
-
-
#define ALU16_AND(VAL) \
do { \
error("ALU_AND16"); \