From: Sandipan Das Date: Thu, 7 Jun 2018 12:46:46 +0000 (+0530) Subject: arch-power: Fix fixed-point word shift instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5fbdc1c8b09d2856bf5a0cef04b080467901a7ab;p=gem5.git 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 --- diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index 2f7e15909..66e50e2bf 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -577,8 +577,21 @@ IntShiftOp::generateDisassembly( Addr pc, const Loader::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) { @@ -591,10 +604,32 @@ IntShiftOp::generateDisassembly( 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 4129a3482..a2b65af6e 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -587,18 +587,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 928cfd856..cf440e048 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -586,83 +586,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 057277ffb..4a9630790 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -309,13 +309,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) = \