From 424998b2c77f61b240ce6594cfe770d0782041b1 Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Thu, 7 Jun 2018 18:39:20 +0530 Subject: [PATCH] arch-power: Add fixed-point doubleword shift instructions This adds the following shift instructions: * Shift Left Doubleword (sld[.]) * Shift Right Doubleword (srd[.]) * Shift Right Algebraic Doubleword (srad[.]) * Shift Right Algebraic Doubleword Immediate (sradi[.]) * Extend-Sign Word and Shift Left Immediate (extswsli[.]) Change-Id: Icd1f3efda715c5b8a7c7bc648ba29a8749e74695 Signed-off-by: Sandipan Das --- src/arch/power/insts/integer.cc | 64 ++++++++++++++++++ src/arch/power/insts/integer.hh | 22 +++++++ src/arch/power/isa/decoder.isa | 91 +++++++++++++++++++++++--- src/arch/power/isa/formats/integer.isa | 35 ++++++++++ 4 files changed, 203 insertions(+), 9 deletions(-) diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index 40f45e9df..090ec4802 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -629,6 +629,70 @@ IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const } +string +IntConcatShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + stringstream ss; + bool printSecondSrc = true; + bool printShift = false; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("sradi") || + !myMnemonic.compare("extswsli")) { + 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) { + printReg(ss, _destRegIdx[0]); + } + + // Print the first source register + if (_numSrcRegs > 0) { + if (_numDestRegs > 0) { + 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 value + if (printShift) { + ss << ", " << shift; + } + + return ss.str(); +} + + string IntRotateOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 7015a2edb..15a2b9fc3 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -610,6 +610,28 @@ class IntShiftOp : public IntOp }; +/** + * Class for integer shift operations with a shift value obtained from + * a register or by concatenating immediates. + */ +class IntConcatShiftOp : public IntOp +{ + protected: + + uint32_t shift; + + /// Constructor + IntConcatShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntOp(mnem, _machInst, __opClass), + shift(((uint32_t)machInst.shn << 5) | machInst.sh) + { + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + + /** * Class for integer rotate operations. */ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index b21263f86..af710edbc 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -652,6 +652,52 @@ decode PO default Unknown::unknown() { true); } + format IntConcatShiftOp { + 27: sld({{ + int64_t shift = Rb_sd; + uint64_t res = Rs & ~((shift << 57) >> 63); + if (shift != 0) { + shift = shift & 0x3f; + res = res << shift; + } + Ra = res; + }}); + + 539: srd({{ + int64_t shift = Rb_sd; + uint64_t res = Rs & ~((shift << 57) >> 63); + if (shift != 0) { + shift = shift & 0x3f; + res = res >> shift; + } + Ra = res; + }}); + + 794: srad({{ + int64_t src = Rs_sd; + uint64_t shift = Rb; + int64_t res; + if ((shift & 0x40) != 0) { + res = src >> 63; + if (res != 0) { + setCA = true; + } + } else { + if (shift != 0) { + shift = shift & 0x3f; + res = src >> shift; + if (src < 0 && (src & mask(shift)) != 0) { + setCA = true; + } + } else { + res = src; + } + } + Ra = res; + }}, + true); + } + // Generic integer format instructions. format IntOp { 339: decode SPR { @@ -876,19 +922,46 @@ decode PO default Unknown::unknown() { true); } - default: decode XFX_XO { - format IntOp { - 144: mtcrf({{ - uint32_t mask = 0; - for (int i = 0; i < 8; ++i) { - if (((FXM >> i) & 0x1) == 0x1) { - mask |= 0xf << (4 * i); + // These instructions are of XS form and use bits 21 - 29 as XO. + default: decode XS_XO { + format IntConcatShiftOp { + 413: sradi({{ + int64_t src = Rs_sd; + if (shift != 0) { + Ra = src >> shift; + if (src < 0 && (src & mask(shift))) { + setCA = true; } + } else { + Ra = src; + } + }}, + true); + + 445: extswsli({{ + int64_t src = Rs_sw; + if (shift != 0) { + Ra = src << shift; + } else { + Ra = src; } - CR = (Rs & mask) | (CR & ~mask); }}); + } - 19: mfcr({{ Rt = CR; }}); + default: decode XFX_XO { + format IntOp { + 144: mtcrf({{ + uint32_t mask = 0; + for (int i = 0; i < 8; ++i) { + if (((FXM >> i) & 0x1) == 0x1) { + mask |= 0xf << (4 * i); + } + } + CR = (Rs & mask) | (CR & ~mask); + }}); + + 19: mfcr({{ Rt = CR; }}); + } } } } diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa index 42c888747..8f8c2bd41 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -488,6 +488,41 @@ def format IntArithCheckRcOp(code, computeOV = 0, inst_flags = []) {{ }}; +// Integer instructions that also perform shift operations. Everything +// is same as above except if the shift value is not obtained from a +// register, two immediates need to be concatenated to get the final +// shift value. +def format IntConcatShiftOp(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 = 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) = \ + GenAluOp(name, Name, 'IntConcatShiftOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntConcatShiftOp', code_rc1, + inst_flags, CheckRcDecode, IntRcConstructor) + + # Finally, add to the other outputs + header_output += header_output_rc1 + decoder_output += decoder_output_rc1 + exec_output += exec_output_rc1 +}}; + + // A special format for rotate instructions which use certain fields // from the instruction's binary encoding. We need two versions for each // instruction to deal with the Rc bit. -- 2.30.2