arch-power: Fix fixed-point word shift instructions
authorSandipan Das <sandipan@linux.vnet.ibm.com>
Thu, 7 Jun 2018 12:46:46 +0000 (18:16 +0530)
committerSandipan Das <sandipan@linux.vnet.ibm.com>
Thu, 7 Jun 2018 12:46:46 +0000 (18:16 +0530)
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 <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 6f190d331d8f1a0b91dc69e8b9ca3921fb79e111..40f45e9dfe636b33405a38996ab5f772ceb3d589 100644 (file)
@@ -571,8 +571,21 @@ string
 IntShiftOp::generateDisassembly(Addr pc, const 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) {
@@ -585,10 +598,32 @@ IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
             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();
 }
index afbdc4341f507fb315a75397a784296c270589b8..7015a2edb059cd1a6782b5533b4a9308f5132919 100644 (file)
@@ -589,18 +589,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)
     {
     }
 
index f98fe82fd08c330171bc83a4823ca757528015b3..b21263f863aa78aea162ec9ad3318eff09b7d678 100644 (file)
@@ -588,83 +588,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.
index 7afaef06892ef1e08a5b92dce1de7fc5ccc8b9b5..42c88874714c0dbd4eec7bf4f2e16b42d2fb2aab 100644 (file)
@@ -311,13 +311,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) = \