From 99b304bc4048a4d32d80de9134330c670cf4d0f7 Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Thu, 7 Jun 2018 19:00:23 +0530 Subject: [PATCH] arch-power: Add fixed-point doubleword rotate instructions This adds the following rotate instructions: * Rotate Left Doubleword Immediate then Clear Left (rldicl[.]) * Rotate Left Doubleword Immediate then Clear Right (rldicr[.]) * Rotate Left Doubleword Immediate then Clear (rldic[.]) * Rotate Left Doubleword then Clear Left (rldcl[.]) * Rotate Left Doubleword then Clear Right (rldcr[.]) * Rotate Left Doubleword Immediate then Mask Insert (rldimi[.]) Change-Id: I27520314e738e5bed92bf07c1150943c9f83e881 Signed-off-by: Sandipan Das --- src/arch/power/insts/integer.cc | 83 ++++++++++++++++++++++++++ src/arch/power/insts/integer.hh | 44 ++++++++++++++ src/arch/power/isa/decoder.isa | 78 ++++++++++++++++++++++++ src/arch/power/isa/formats/integer.isa | 29 +++++++++ 4 files changed, 234 insertions(+) diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index ce4ab463d..1a74b80f8 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -780,3 +780,86 @@ IntRotateOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const return ss.str(); } + +string +IntConcatRotateOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + stringstream ss; + bool printSecondSrc = false; + bool printShift = true; + bool printMaskBeg = true; + + // Generate the correct mnemonic + string myMnemonic(mnemonic); + + // Special cases + if (!myMnemonic.compare("rldicl")) { + if (maskBeg == 0) { + myMnemonic = "rotldi"; + printMaskBeg = false; + } else if (shift == 0) { + myMnemonic = "clrldi"; + printShift = false; + } + } else if (!myMnemonic.compare("rldcl")) { + if (maskBeg == 0) { + myMnemonic = "rotld"; + printMaskBeg = false; + } + printSecondSrc = true; + printShift = false; + } else if (!myMnemonic.compare("rldcr")) { + printSecondSrc = true; + printShift = false; + } + + // 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 amount + if (printShift) { + ss << ", " << shift; + } + + // Print the mask bound + if (printMaskBeg) { + ss << ", " << maskBeg; + } + + return ss.str(); +} diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 95d64b338..afcf928e8 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -679,6 +679,50 @@ class IntRotateOp : public IntShiftOp Addr pc, const SymbolTable *symtab) const override; }; + +/** + * Class for integer rotate operations with a shift amount obtained + * from a register or by concatenating immediate fields and the first + * and last bits of a mask obtained by concatenating immediate fields. + */ +class IntConcatRotateOp : public IntConcatShiftOp +{ + protected: + + uint32_t maskBeg; + uint32_t maskEnd; + + /// Constructor + IntConcatRotateOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : IntConcatShiftOp(mnem, _machInst, __opClass), + maskBeg(((uint32_t)machInst.mbn << 5) | machInst.mb), + maskEnd(((uint32_t)machInst.men << 5) | machInst.mb) + { + } + + inline uint64_t + rotate(uint64_t rs, uint32_t sh) const + { + sh = sh & 0x3f; + return (rs << sh) | (rs >> (64 - sh)); + } + + inline uint64_t + bitmask(uint32_t mb, uint32_t me) const + { + mb = mb & 0x3f; + me = me & 0x3f; + if (mb <= me) { + return mask(63 - mb, 63 - me); + } else { + return ~mask(63 - (me + 1), 63 - (mb - 1)); + } + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + } // namespace PowerISA #endif //__ARCH_POWER_INSTS_INTEGER_HH__ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 5933bca48..ef93bdfd3 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -984,6 +984,84 @@ decode PO default Unknown::unknown() { } } + // These instructions are of MD form and use bits 27 - 29 as XO. + 30: decode MD_XO { + format IntConcatRotateOp { + 0: rldicl({{ + uint64_t res; + if (shift != 0) { + res = rotate(Rs, shift); + } else { + res = Rs; + } + res = res & bitmask(maskBeg, 63); + Ra = res; + }}); + + 1: rldicr({{ + uint64_t res; + if (shift != 0) { + res = rotate(Rs, shift); + } else { + res = Rs; + } + res = res & bitmask(0, maskEnd); + Ra = res; + }}); + + 2: rldic({{ + uint64_t res; + if (shift != 0) { + res = rotate(Rs, shift); + } else { + res = Rs; + } + res = res & bitmask(maskBeg, ~shift); + Ra = res; + }}); + + 3: rldimi({{ + uint64_t res, mask; + mask = bitmask(maskBeg, ~shift); + if (shift != 0) { + res = rotate(Rs, shift); + } else { + res = Rs; + } + res = res & mask; + res = res | (Ra & ~mask); + Ra = res; + }}); + + // These instructions are of MDS form and use bits 27 - 30 as XO. + default: decode MDS_XO { + 8: rldcl({{ + uint64_t res; + uint32_t shift = Rb & 0x3f; + if (shift != 0) { + res = rotate(Rs, shift); + } else { + res = Rs; + } + res = res & bitmask(maskBeg, 63); + Ra = res; + }}); + + 9: rldcr({{ + uint64_t res; + uint32_t shift = Rb & 0x3f; + if (shift != 0) { + res = rotate(Rs, shift); + } else { + res = Rs; + } + res = res & bitmask(0, maskEnd); + Ra = res; + }}); + } + } + } + format LoadDispOp { 48: lfs({{ Ft_sf = Mem_sf; }}); 50: lfd({{ Ft = Mem_df; }}); diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa index 78f8062db..8f23084f1 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -551,3 +551,32 @@ def format IntRotateOp(code, inst_flags = []) {{ decoder_output += decoder_output_rc1 exec_output += exec_output_rc1 }}; + + +// Everything is same as above except that the immediates may need to be +// concatenated to get the final values for the mask bounds or the shift +// value. We need two versions for each instruction to deal with the Rc +// bit. +def format IntConcatRotateOp(code, inst_flags = []) {{ + + # The result is always in Ra + dict = {'result':'Ra'} + + # Code when Rc is set + code_rc1 = readXERCode + code + computeCR0Code % dict + + # Generate the first class + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntConcatRotateOp', code, inst_flags, + CheckRcDecode, BasicConstructor) + + # Generate the second class + (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ + GenAluOp(name, Name + 'RcSet', 'IntConcatRotateOp', 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 +}}; -- 2.30.2