From c520e10954d5e47e05aa9af8fc501a5ade4cf83f Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Thu, 7 Jun 2018 18:16:46 +0530 Subject: [PATCH] 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 --- src/arch/power/insts/integer.cc | 41 ++++++++++- src/arch/power/insts/integer.hh | 7 +- src/arch/power/isa/decoder.isa | 99 +++++++++++--------------- src/arch/power/isa/formats/integer.isa | 21 ++++-- 4 files changed, 101 insertions(+), 67 deletions(-) diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index 6f190d331..40f45e9df 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -571,8 +571,21 @@ string 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 @@ IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 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 afbdc4341..7015a2edb 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -589,18 +589,19 @@ class IntImmLogicOp : public IntLogicOp /** - * 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 f98fe82fd..b21263f86 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -588,83 +588,68 @@ decode PO default Unknown::unknown() { } 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; - } - } else { - Ra = 0; - 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 { - Ra = s >> (Rb & 0x1f); - if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) { - shiftSetCA = true; + if (shift != 0) { + shift = shift & 0x1f; + res = src >> shift; + if (src < 0 && (src & mask(shift)) != 0) { + setCA = 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 7afaef068..42c888747 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -311,13 +311,26 @@ def format IntLogicOp(code, computeCR0 = 0, inst_flags = []) {{ }}; -// 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) = \ -- 2.30.2