Sandipan Das has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/40933 )

Change subject: arch-power: Add doubleword rotate instructions
......................................................................

arch-power: Add doubleword rotate instructions

This introduces a new class and a new format for MD and
MDS form instructions where the shift amount, mask begin
and mask end are specified by two fields that must be
concatenated and adds the following 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: Id7f1f24032242ccfdfda2f1aefd6fe9f0331f610
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, 234 insertions(+), 0 deletions(-)



diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc
index aaa7925..0631749 100644
--- a/src/arch/power/insts/integer.cc
+++ b/src/arch/power/insts/integer.cc
@@ -795,3 +795,86 @@

     return ss.str();
 }
+
+std::string
+IntConcatRotateOp::generateDisassembly(
+        Addr pc, const Loader::SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    bool printSecondSrc = false;
+    bool printShift = true;
+    bool printMaskBeg = true;
+
+    // Generate the correct mnemonic
+    std::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 6d39a5f..59566e8 100644
--- a/src/arch/power/insts/integer.hh
+++ b/src/arch/power/insts/integer.hh
@@ -689,6 +689,50 @@
             Addr pc, const Loader::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 Loader::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 1c67d3a..73b0973 100644
--- a/src/arch/power/isa/decoder.isa
+++ b/src/arch/power/isa/decoder.isa
@@ -984,6 +984,84 @@
         }
     }

+    // 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 bc52340..6f8d038 100644
--- a/src/arch/power/isa/formats/integer.isa
+++ b/src/arch/power/isa/formats/integer.isa
@@ -554,3 +554,32 @@
     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
+}};

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/40933
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Id7f1f24032242ccfdfda2f1aefd6fe9f0331f610
Gerrit-Change-Number: 40933
Gerrit-PatchSet: 1
Gerrit-Owner: Sandipan Das <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to