diff options
Diffstat (limited to 'sim/common/sim-alu.h')
-rw-r--r-- | sim/common/sim-alu.h | 1047 |
1 files changed, 1047 insertions, 0 deletions
diff --git a/sim/common/sim-alu.h b/sim/common/sim-alu.h new file mode 100644 index 0000000..49d1018 --- /dev/null +++ b/sim/common/sim-alu.h @@ -0,0 +1,1047 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_ALU_H_ +#define _SIM_ALU_H_ + +#include "symcat.h" + + +/* INTEGER ALU MODULE: + + This module provides an implementation of 2's complement arithmetic + including the recording of carry and overflow status bits. + + + EXAMPLE: + + 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: + + #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: + + + 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. + + Rm = (SEXTn (Xn) + SEXTn (Yn)) + V = MSBn ((Rm >> (M - N)) ^ Rm) + + + + 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 the sign + extended range [MINn .. MAXn]. + + + + Addition - Overflow - method 4: + + + 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 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 + 0 1 0 1 0 | 0 | 1 0 0 + 0 1 1 0 1 | 1 | 0 0 1 + 1 0 0 1 0 | 1 | 0 1 1 + 1 0 1 0 1 | 0 | 1 1 0 + 1 1 0 0 1 | 0 | 1 1 0 + 1 1 1 1 1 | 0 | 0 1 0 + + + + Addition - Carry - Introduction: + + + 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. + + 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 + 0 1 0 1 | 0 + 0 1 1 0 | 1 + 1 0 0 1 | 0 + 1 0 1 0 | 1 + 1 1 0 0 | 1 + 1 1 1 1 | 1 + + (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. + + XY\R 0 1 + +------- + 00 | 0 0 + 01 | 1 0 + 11 | 1 1 + 10 | 1 0 + + This giving us the sum-of-prod equation: + + MSBn ((Xn & Yn) | (Xn & ~Rn) | (Yn & ~Rn)) + + Verifying: + + 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 + 0 1 0 1 | 0 | 0 0 0 + 0 1 1 0 | 1 | 1 1 1 + 1 0 0 1 | 0 | 0 0 0 + 1 0 1 0 | 1 | 0 0 1 + 1 1 0 0 | 1 | 0 1 0 + 1 1 1 1 | 1 | 1 0 0 + + + + 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). + + + + Addition - Carry - method 3: + + + Given the oVerflow bit. The carry can be computed from: + + (~R&V) | (R&V) + + + + 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) + + hence we get carry by computing in N bit unsigned arrithmetic. + + carry <- (Xn + Yn) < Xn + + + + 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 + + */ + + + +/* 8 bit target expressions: + + Since the host's natural bitsize > 8 bits, carry method 2 and + overflow method 2 are used. */ + +#define ALU8_BEGIN(VAL) \ +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_BORROW(CARRY) \ +do { \ + if (CARRY) \ + alu8_cr |= ((signed)-1) << 8; \ + else \ + alu8_cr &= 0xff; \ +} while (0) + +#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_BORROW_RESULT ((unsigned8) alu8_cr) +#define ALU8_OVERFLOW_RESULT ((unsigned8) alu8_vr) + +/* #define ALU8_END ????? - target dependant */ + + + +/* 16 bit target expressions: + + Since the host's natural bitsize > 16 bits, carry method 2 and + overflow method 2 are used. */ + +#define ALU16_BEGIN(VAL) \ +signed alu16_cr = (unsigned16) (VAL); \ +unsigned alu16_vr = (signed16) (alu16_cr) + +#define ALU16_SET(VAL) \ +alu16_cr = (unsigned16) (VAL); \ +alu16_vr = (signed16) (alu16_cr) + +#define ALU16_SET_CARRY_BORROW(CARRY) \ +do { \ + if (CARRY) \ + alu16_cr |= ((signed)-1) << 16; \ + else \ + alu16_cr &= 0xffff; \ +} while (0) + +#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_BORROW_RESULT ((unsigned16) alu16_cr) +#define ALU16_OVERFLOW_RESULT ((unsigned16) alu16_vr) + +/* #define ALU16_END ????? - target dependant */ + + + +/* 32 bit target expressions: + + Since most hosts do not support 64 (> 32) bit arrithmetic, carry + method 4 and overflow method 4 are used. */ + +#define ALU32_BEGIN(VAL) \ +unsigned32 alu32_r = (VAL); \ +int alu32_c = 0; \ +int alu32_v = 0 + +#define ALU32_SET(VAL) \ +alu32_r = (VAL); \ +alu32_c = 0; \ +alu32_v = 0 + +#define ALU32_SET_CARRY_BORROW(CARRY) alu32_c = (CARRY) + +#define ALU32_HAD_CARRY_BORROW (alu32_c) +#define ALU32_HAD_OVERFLOW (alu32_v) + +#define ALU32_RESULT (alu32_r) +#define ALU32_CARRY_BORROW_RESULT (alu32_r) +#define ALU32_OVERFLOW_RESULT (alu32_r) + + + +/* 64 bit target expressions: + + Even though the host typically doesn't support native 64 bit + arrithmetic, it is still used. */ + +#define ALU64_BEGIN(VAL) \ +unsigned64 alu64_r = (VAL); \ +int alu64_c = 0; \ +int alu64_v = 0 + +#define ALU64_SET(VAL) \ +alu64_r = (VAL); \ +alu64_c = 0; \ +alu64_v = 0 + +#define ALU64_SET_CARRY_BORROW(CARRY) alu64_c = (CARRY) + +#define ALU64_HAD_CARRY_BORROW (alu64_c) +#define ALU64_HAD_OVERFLOW (alu64_v) + +#define ALU64_RESULT (alu64_r) +#define ALU64_CARRY_BORROW_RESULT (alu64_r) +#define ALU64_OVERFLOW_RESULT (alu64_r) + + + +/* Generic versions of above macros */ + +#define ALU_BEGIN XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_BEGIN) +#define ALU_SET XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET) +#define ALU_SET_CARRY XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET_CARRY) + +#define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW) +#define ALU_HAD_CARRY XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_CARRY) + +#define ALU_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_RESULT) +#define ALU_OVERFLOW_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OVERFLOW_RESULT) +#define ALU_CARRY_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_CARRY_RESULT) + + + +/* Basic operation - add (overflowing) */ + +#define ALU8_ADD(VAL) \ +do { \ + unsigned8 alu8add_val = (VAL); \ + ALU8_ADDC (alu8add_val); \ +} while (0) + +#define ALU16_ADD(VAL) \ +do { \ + unsigned16 alu16add_val = (VAL); \ + ALU16_ADDC (alu8add_val); \ +} while (0) + +#define ALU32_ADD(VAL) \ +do { \ + unsigned32 alu32add_val = (VAL); \ + ALU32_ADDC (alu32add_val); \ +} while (0) + +#define ALU64_ADD(VAL) \ +do { \ + 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 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) + + + +/* Compound operation - add carrying (and overflowing) with carry-in */ + +#define ALU8_ADDC_C(VAL,C) \ +do { \ + 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_ADDC_C(VAL,C) \ +do { \ + 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_ADDC_C(VAL,C) \ +do { \ + 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_ADDC_C(VAL,C) \ +do { \ + 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_ADDC_C XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC_C) + + + +/* Basic operation - subtract (overflowing) */ + +#define ALU8_SUB(VAL) \ +do { \ + unsigned8 alu8sub_val = (VAL); \ + ALU8_ADDC_C (~alu8sub_val, 1); \ +} while (0) + +#define ALU16_SUB(VAL) \ +do { \ + unsigned16 alu16sub_val = (VAL); \ + ALU16_ADDC_C (~alu16sub_val, 1); \ +} while (0) + +#define ALU32_SUB(VAL) \ +do { \ + unsigned32 alu32sub_val = (VAL); \ + ALU32_ADDC_C (~alu32sub_val, 1); \ +} while (0) + +#define ALU64_SUB(VAL) \ +do { \ + 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 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) + + + +/* Compound operation - subtract carrying (and overflowing), extended */ + +#define ALU8_SUBC_X(VAL,C) \ +do { \ + unsigned8 alu8subcx_val = (VAL); \ + unsigned8 alu8subcx_c = (C); \ + ALU8_ADDC_C (~alu8subcx_val, alu8subcx_c); \ +} while (0) + +#define ALU16_SUBC_X(VAL,C) \ +do { \ + unsigned16 alu16subcx_val = (VAL); \ + unsigned16 alu16subcx_c = (C); \ + ALU16_ADDC_C (~alu16subcx_val, alu16subcx_c); \ +} while (0) + +#define ALU32_SUBC_X(VAL,C) \ +do { \ + unsigned32 alu32subcx_val = (VAL); \ + unsigned32 alu32subcx_c = (C); \ + ALU32_ADDC_C (~alu32subcx_val, alu32subcx_c); \ +} while (0) + +#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 alu64neg_val = (ALU64_RESULT); \ + ALU64_SET (1); \ + ALU64_ADDC (~alu64neg_val); \ +} while (0) + +#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"); \ +} while (0) + +#define ALU32_OR(VAL) \ +do { \ + alu32_r |= (VAL); \ + alu32_c = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_OR(VAL) \ +do { \ + alu64_r |= (VAL); \ + alu64_c = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_OR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OR)(VAL) + + + +#define ALU16_XOR(VAL) \ +do { \ + error("ALU16_XOR"); \ +} while (0) + +#define ALU32_XOR(VAL) \ +do { \ + alu32_r ^= (VAL); \ + alu32_c = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_XOR(VAL) \ +do { \ + alu64_r ^= (VAL); \ + alu64_c = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL) + + + + +#define ALU16_AND(VAL) \ +do { \ + error("ALU_AND16"); \ +} while (0) + +#define ALU32_AND(VAL) \ +do { \ + alu32_r &= (VAL); \ + alu32_r = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_AND(VAL) \ +do { \ + alu64_r &= (VAL); \ + alu64_r = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_AND(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_AND)(VAL) + + + + +#define ALU16_NOT(VAL) \ +do { \ + error("ALU_NOT16"); \ +} while (0) + +#define ALU32_NOT \ +do { \ + alu32_r = ~alu32_r; \ + alu32_c = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_NOT \ +do { \ + alu64_r = ~alu64_r; \ + alu64_c = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT) + +#endif |