aboutsummaryrefslogtreecommitdiff
path: root/sim/common/sim-alu.h
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>1997-08-27 07:56:27 +0000
committerAndrew Cagney <cagney@redhat.com>1997-08-27 07:56:27 +0000
commitd6fea803dc93be47864a8f9094bc2c1fa0c95b9b (patch)
tree6fbebb64bc72bfc3a37ff56ed3d805415ba439c9 /sim/common/sim-alu.h
parent750b7942964c37db092d613eef64eff6dd5de7f3 (diff)
downloadfsf-binutils-gdb-d6fea803dc93be47864a8f9094bc2c1fa0c95b9b.zip
fsf-binutils-gdb-d6fea803dc93be47864a8f9094bc2c1fa0c95b9b.tar.gz
fsf-binutils-gdb-d6fea803dc93be47864a8f9094bc2c1fa0c95b9b.tar.bz2
Add MSBIT* and LSBIT* macro's to sim-bits.h
Add more macro's for extracting sub word quantites to sim-endian.h
Diffstat (limited to 'sim/common/sim-alu.h')
-rw-r--r--sim/common/sim-alu.h348
1 files changed, 348 insertions, 0 deletions
diff --git a/sim/common/sim-alu.h b/sim/common/sim-alu.h
new file mode 100644
index 0000000..6bb35f0
--- /dev/null
+++ b/sim/common/sim-alu.h
@@ -0,0 +1,348 @@
+/* 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 "sim-xcat.h"
+
+/* 32bit target expressions:
+
+ Each calculation is performed three times using each of the
+ signed64, unsigned64 and long integer types. The macro ALU_END
+ (in _ALU_RESULT_VAL) then selects which of the three alternative
+ results will be used in the final assignment of the target
+ register. As this selection is determined at compile time by
+ fields in the instruction (OE, EA, Rc) the compiler has sufficient
+ information to firstly simplify the selection code into a single
+ case and then back anotate the equations and hence eliminate any
+ resulting dead code. That dead code being the calculations that,
+ as it turned out were not in the end needed.
+
+ 64bit arrithemetic is used firstly because it allows the use of
+ gcc's efficient long long operators (typically efficiently output
+ inline) and secondly because the resultant answer will contain in
+ the low 32bits the answer while in the high 32bits is either carry
+ or status information. */
+
+
+
+/* 16bit target expressions:
+
+ These are a simplified version of the 32bit target expressions */
+
+
+
+/* 64bit target expressions:
+
+ Unfortunatly 128bit arrithemetic isn't that common. Consequently
+ the 32/64 bit trick can not be used. Instead all calculations are
+ required to retain carry/overflow information in separate
+ variables. Even with this restriction it is still possible for the
+ trick of letting the compiler discard the calculation of unneeded
+ values */
+
+
+/* Macro's to type cast 32bit constants to 64bits */
+#define SIGNED64(val) ((signed64)(signed32)(val))
+#define UNSIGNED64(val) ((unsigned64)(unsigned32)(val))
+
+
+/* Start a section of ALU code */
+
+#define ALU16_BEGIN(VAL) \
+{ \
+ signed_word alu_carry_val; \
+ unsigned_word alu_overflow_val; \
+ ALU16_SET(VAL)
+
+#define ALU32_BEGIN(VAL) \
+{ \
+ natural_word alu_val; \
+ unsigned64 alu_carry_val; \
+ signed64 alu_overflow_val; \
+ ALU32_SET(VAL)
+
+#define ALU_BEGIN(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_BEGIN)(VAL)
+
+/* More basic alu operations */
+
+
+
+#define ALU16_SET(VAL) \
+do { \
+ alu_carry_val = (unsigned16)(VAL); \
+ alu_overflow_val = (signed16)(VAL); \
+} while (0)
+
+#define ALU32_SET(VAL) \
+do { \
+ alu_val = (unsigned32)(VAL); \
+ alu_carry_val = (unsigned32)(alu_val); \
+ alu_overflow_val = (signed32)(alu_val); \
+} while (0)
+
+#define ALU64_SET(VAL) \
+do { \
+ alu_val = (VAL); \
+ alu_carry_val = ((unsigned64)alu_val) >> 32; \
+ alu_overflow_val = ((signed64)alu_val) >> 32; \
+} while (0)
+
+#define ALU_SET(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET)(VAL)
+
+
+
+
+#define ALU16_ADD(VAL) \
+do { \
+ alu_carry_val += (unsigned16)(VAL); \
+ alu_overflow_val += (signed16)(VAL); \
+} while (0)
+
+#define ALU32_ADD(VAL) \
+do { \
+ alu_val += (VAL); \
+ alu_carry_val += (unsigned32)(VAL); \
+ alu_overflow_val += (signed32)(VAL); \
+} while (0)
+
+#define ALU64_ADD(VAL) \
+do { \
+ unsigned64 alu_lo = (UNSIGNED64(alu_val) \
+ + UNSIGNED64(VAL)); \
+ signed alu_carry = ((alu_lo & BIT(31)) != 0); \
+ alu_carry_val = (alu_carry_val \
+ + UNSIGNED64(EXTRACTED(val, 0, 31)) \
+ + alu_carry); \
+ alu_overflow_val = (alu_overflow_val \
+ + SIGNED64(EXTRACTED(val, 0, 31)) \
+ + alu_carry); \
+ alu_val = alu_val + val; \
+} while (0)
+
+#define ALU_ADD(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD)(VAL)
+
+
+
+
+#define ALU16_ADD_CA \
+do { \
+ signed carry = ALU_CARRY; \
+ ALU16_ADD(carry); \
+} while (0)
+
+#define ALU32_ADD_CA \
+do { \
+ signed carry = ALU_CARRY; \
+ ALU32_ADD(carry); \
+} while (0)
+
+#define ALU64_ADD_CA \
+do { \
+ signed carry = ALU_CARRY; \
+ ALU64_ADD(carry); \
+} while (0)
+
+#define ALU_ADD_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD_CA)
+
+
+
+
+#define ALU16_SUB(VAL) \
+do { \
+ alu_carry_val -= (unsigned16)(VAL); \
+ alu_overflow_val -= (signed16)(VAL); \
+} while (0)
+
+#define ALU32_SUB(VAL) \
+do { \
+ alu_val -= (VAL); \
+ alu_carry_val -= (unsigned32)(VAL); \
+ alu_overflow_val -= (signed32)(VAL); \
+} while (0)
+
+#define ALU64_SUB(VAL) \
+do { \
+ error("ALU_SUB64"); \
+} while (0)
+
+#define ALU_SUB(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)(VAL)
+
+
+
+
+#define ALU16_SUB_CA \
+do { \
+ signed carry = ALU_CARRY; \
+ ALU16_SUB(carry); \
+} while (0)
+
+#define ALU32_SUB_CA \
+do { \
+ signed carry = ALU_CARRY; \
+ ALU32_SUB(carry); \
+} while (0)
+
+#define ALU64_SUB_CA \
+do { \
+ signed carry = ALU_CARRY; \
+ ALU64_SUB(carry); \
+} while (0)
+
+#define ALU_SUB_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB_CA)
+
+
+
+
+#define ALU16_OR(VAL) \
+do { \
+ error("ALU16_OR"); \
+} while (0)
+
+#define ALU32_OR(VAL) \
+do { \
+ alu_val |= (VAL); \
+ alu_carry_val = (unsigned32)(alu_val); \
+ alu_overflow_val = (signed32)(alu_val); \
+} while (0)
+
+#define ALU64_OR(VAL) \
+do { \
+ error("ALU_OR64"); \
+} 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 { \
+ alu_val ^= (VAL); \
+ alu_carry_val = (unsigned32)(alu_val); \
+ alu_overflow_val = (signed32)(alu_val); \
+} while (0)
+
+#define ALU64_XOR(VAL) \
+do { \
+ error("ALU_XOR64"); \
+} while (0)
+
+#define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL)
+
+
+
+
+#define ALU16_NEGATE \
+do { \
+ error("ALU_NEGATE16"); \
+} while (0)
+
+#define ALU32_NEGATE \
+do { \
+ alu_val = -alu_val; \
+ alu_carry_val = -alu_carry_val; \
+ alu_overflow_val = -alu_overflow_val; \
+} while(0)
+
+#define ALU64_NEGATE \
+do { \
+ error("ALU_NEGATE64"); \
+} while (0)
+
+#define ALU_NEGATE XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGATE)
+
+
+
+
+#define ALU16_AND(VAL) \
+do { \
+ error("ALU_AND16"); \
+} while (0)
+
+#define ALU32_AND(VAL) \
+do { \
+ alu_val &= (VAL); \
+ alu_carry_val = (unsigned32)(alu_val); \
+ alu_overflow_val = (signed32)(alu_val); \
+} while (0)
+
+#define ALU64_AND(VAL) \
+do { \
+ error("ALU_AND64"); \
+} 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 { \
+ signed64 new_alu_val = ~alu_val; \
+ ALU_SET(new_alu_val); \
+} while (0)
+
+#define ALU64_NOT \
+do { \
+ error("ALU_NOT64"); \
+} while (0)
+
+#define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT)
+
+
+
+/* Make available various results */
+
+
+/* overflow occures if the sign bit differs from the carry bit */
+
+#define ALU16_HAD_OVERFLOW \
+ (!(alu_overflow_val & MSBIT32 (0)) != !(alu_overflow_val & MSBIT32 (16)))
+
+#define ALU32_HAD_OVERFLOW \
+ ((((unsigned64)(alu_overflow_val & BIT64(0))) >> 32) \
+ != (alu_overflow_val & MSBIT64(32)))
+
+#define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW)
+
+/* carry found in bit before sign */
+
+#define ALU16_HAD_CARRY \
+ (alu_carry_val & MSBIT32(16))
+
+#define ALU32_HAD_CARRY \
+ (alu_carry_val & MSBIT64(31))
+
+
+#endif