arch-power: Add fixed-point doubleword shift instructions
authorSandipan Das <sandipan@linux.vnet.ibm.com>
Thu, 7 Jun 2018 13:09:20 +0000 (18:39 +0530)
committerSandipan Das <sandipan@linux.vnet.ibm.com>
Thu, 7 Jun 2018 13:14:21 +0000 (18:44 +0530)
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 <sandipan@linux.vnet.ibm.com>
src/arch/power/insts/integer.cc
src/arch/power/insts/integer.hh
src/arch/power/isa/decoder.isa
src/arch/power/isa/formats/integer.isa

index 40f45e9dfe636b33405a38996ab5f772ceb3d589..090ec480274910139618e1fe4df76b6e8bbedb72 100644 (file)
@@ -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
 {
index 7015a2edb059cd1a6782b5533b4a9308f5132919..15a2b9fc3540759cf2ce036f1f1ba24e4539eaba 100644 (file)
@@ -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.
  */
index b21263f863aa78aea162ec9ad3318eff09b7d678..af710edbcbb331257fd21c22fc4fd5a52d5754e2 100644 (file)
@@ -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; }});
+                    }
                 }
             }
         }
index 42c88874714c0dbd4eec7bf4f2e16b42d2fb2aab..8f8c2bd41ccf5cf4883c3889a0f55400f54d9026 100644 (file)
@@ -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.