Sandipan Das has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/16633
Change subject: arch-power: Fix fixed-point word shift instructions
......................................................................
arch-power: Fix fixed-point word shift instructions
This fixes the following shift instructions:
* Shift Left Word (slw[.])
* Shift Right Word (srw[.])
* Shift Right Algebraic Word (sraw[.])
* Shift Right Algebraic Word Immediate (srawi[.])
For 64-bit execution, these instructions should perform
shift operations on only the lower order 32 bits of the
source register instead of all 64 bits.
This also fixes disassembly generation for all of the above.
Change-Id: I18871486d74969244d474eaf0f9d810f06faf50a
Signed-off-by: Sandipan Das <[email protected]>
---
M src/arch/power/insts/integer.cc
M src/arch/power/insts/integer.hh
M src/arch/power/isa/decoder.isa
M src/arch/power/isa/formats/integer.isa
4 files changed, 102 insertions(+), 68 deletions(-)
diff --git a/src/arch/power/insts/integer.cc
b/src/arch/power/insts/integer.cc
index 6f190d3..40f45e9 100644
--- a/src/arch/power/insts/integer.cc
+++ b/src/arch/power/insts/integer.cc
@@ -571,8 +571,21 @@
IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
stringstream ss;
+ bool printSecondSrc = true;
+ bool printShift = false;
- ccprintf(ss, "%-10s ", mnemonic);
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("srawi")) {
+ printSecondSrc = false;
+ printShift = true;
+ }
+
+ // Additional characters depending on isa bits being set
+ if (rcSet) myMnemonic = myMnemonic + ".";
+ ccprintf(ss, "%-10s ", myMnemonic);
// Print the first destination only
if (_numDestRegs > 0) {
@@ -585,10 +598,32 @@
ss << ", ";
}
printReg(ss, _srcRegIdx[0]);
+
+ // Print the second source register
+ if (printSecondSrc) {
+
+ // If the instruction updates the CR, the destination register
+ // Ra is read and thus, it becomes the second source register
+ // due to its higher precedence over Rb. In this case, it must
+ // be skipped.
+ if (rcSet) {
+ if (_numSrcRegs > 2) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[2]);
+ }
+ } else {
+ if (_numSrcRegs > 1) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[1]);
+ }
+ }
+ }
}
- // Print the shift
- ss << ", " << sh;
+ // Print the shift value
+ if (printShift) {
+ ss << ", " << shift;
+ }
return ss.str();
}
diff --git a/src/arch/power/insts/integer.hh
b/src/arch/power/insts/integer.hh
index d8c7507..bcf4f5c 100644
--- a/src/arch/power/insts/integer.hh
+++ b/src/arch/power/insts/integer.hh
@@ -601,18 +601,19 @@
/**
- * Class for integer operations with a shift.
+ * Class for integer operations with a shift value obtained from
+ * a register or an instruction field.
*/
class IntShiftOp : public IntOp
{
protected:
- uint32_t sh;
+ uint32_t shift;
/// Constructor
IntShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: IntOp(mnem, _machInst, __opClass),
- sh(machInst.sh)
+ shift(machInst.sh)
{
}
diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa
index e267c63..cbe589d 100644
--- a/src/arch/power/isa/decoder.isa
+++ b/src/arch/power/isa/decoder.isa
@@ -601,83 +601,68 @@
}
Ra = res;
}});
+ }
+ // Integer instructions with a shift value.
+ format IntShiftOp {
24: slw({{
- if (Rb & 0x20) {
- Ra = 0;
- } else {
- Ra = Rs << (Rb & 0x1f);
+ int32_t shift = Rb_sw;
+ uint32_t res = Rs_uw & ~((shift << 26) >> 31);
+ if (shift != 0) {
+ shift = shift & 0x1f;
+ res = res << shift;
}
+ Ra = res;
}});
536: srw({{
- if (Rb & 0x20) {
- Ra = 0;
- } else {
- Ra = Rs >> (Rb & 0x1f);
+ int32_t shift = Rb_sw;
+ uint32_t res = Rs_uw & ~((shift << 26) >> 31);
+ if (shift != 0) {
+ shift = shift & 0x1f;
+ res = res >> shift;
}
+ Ra = res;
}});
792: sraw({{
- bool shiftSetCA = false;
- int32_t s = Rs;
- if (Rb == 0) {
- Ra = Rs;
- shiftSetCA = true;
- } else if (Rb & 0x20) {
- if (s < 0) {
- Ra = (uint32_t)-1;
- if (s & 0x7fffffff) {
- shiftSetCA = true;
- } else {
- shiftSetCA = false;
+ int32_t src = Rs_sw;
+ uint32_t shift = Rb_uw;
+ int64_t res;
+ if ((shift & 0x20) != 0) {
+ res = src >> 31;
+ if (res != 0) {
+ setCA = true;
+ }
+ } else {
+ if (shift != 0) {
+ shift = shift & 0x1f;
+ res = src >> shift;
+ if (src < 0 && (src & mask(shift)) != 0) {
+ setCA = true;
}
} else {
- Ra = 0;
- shiftSetCA = false;
- }
- } else {
- Ra = s >> (Rb & 0x1f);
- if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) {
- shiftSetCA = true;
- } else {
- shiftSetCA = false;
+ res = src;
}
}
- Xer xer1 = XER;
- if (shiftSetCA) {
- xer1.ca = 1;
- } else {
- xer1.ca = 0;
- }
- XER = xer1;
- }});
- }
+ Ra = res;
+ }},
+ true);
- // Integer logic instructions with a shift value.
- format IntShiftOp {
824: srawi({{
- bool shiftSetCA = false;
- if (sh == 0) {
- Ra = Rs;
- shiftSetCA = false;
- } else {
- int32_t s = Rs;
- Ra = s >> sh;
- if (s < 0 && (s << (32 - sh)) != 0) {
- shiftSetCA = true;
- } else {
- shiftSetCA = false;
+ int32_t src = Rs_sw;
+ int64_t res;
+ if (shift != 0) {
+ res = src >> shift;
+ if (src < 0 && (src & mask(shift)) != 0) {
+ setCA = true;
}
- }
- Xer xer1 = XER;
- if (shiftSetCA) {
- xer1.ca = 1;
} else {
- xer1.ca = 0;
+ res = src;
}
- XER = xer1;
- }});
+ Ra = res;
+ }},
+ true);
}
// Generic integer format instructions.
diff --git a/src/arch/power/isa/formats/integer.isa
b/src/arch/power/isa/formats/integer.isa
index 7afaef0..42c8887 100644
--- a/src/arch/power/isa/formats/integer.isa
+++ b/src/arch/power/isa/formats/integer.isa
@@ -311,13 +311,26 @@
}};
-// Integer instructions with a shift amount. As above, except inheriting
-// from the IntShiftOp class.
-def format IntShiftOp(code, inst_flags = []) {{
+// Integer instructions that perform shift operations. All of these
+// instructions write to Ra and use Rs as a source register. The shift
+// value is obtained from an register or an instruction field. If it
+// from a register, Rb is also used as a source register. In certain
+// situations, the carry bits have to be set and this is dealt with
+// using the 'setCA' boolean in decoder.isa. We need two versions for
+// each instruction to deal with the Rc bit.
+def format IntShiftOp(code, computeCA = 0, inst_flags = []) {{
dict = {'result':'Ra'}
+ # Add code to setup variables and access XER if necessary
+ code = 'bool setCA M5_VAR_USED = false;\n' + code
+
# Code when Rc is set
- code_rc1 = code + readXERCode + computeCR0Code % dict
+ code_rc1 = readXERCode + code + computeCR0Code % dict
+
+ # Add code for calculating the carry, if needed
+ if computeCA:
+ code = readXERCode + code + setCACode + setXERCode
+ code_rc1 += setCACode + setXERCode
# Generate the first class
(header_output, decoder_output, decode_block, exec_output) = \
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16633
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I18871486d74969244d474eaf0f9d810f06faf50a
Gerrit-Change-Number: 16633
Gerrit-PatchSet: 1
Gerrit-Owner: Sandipan Das <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev