arch-power: Fix rotate instructions
authorSandipan Das <sandipan@linux.ibm.com>
Sat, 6 Feb 2021 11:52:00 +0000 (17:22 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Mon, 15 Feb 2021 08:32:38 +0000 (14:02 +0530)
Now that 64-bit registers are being used, the rotation
operation changes for words. Instead of just rotating
the lower word of the operand, the lower word is first
duplicated in the upper word and then rotated. This
fixes the following instructions.
  * Rotate Left Word Immediate then And with Mask (rlwinm[.])
  * Rotate Left Word then And with Mask (rlwnm[.])
  * Rotate Left Word Immediate then Mask Insert (rlwimi[.])

Change-Id: Ic743bceb8bafff461276984ecc999dedc1f94e9f
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
src/arch/power/insts/integer.hh
src/arch/power/isa/decoder.isa

index d96936291aebd1df6c51a0195e121e4974176517..6d39a5fed3df35c9fbc408e1ffa48029ef004a9e 100644 (file)
@@ -651,7 +651,6 @@ class IntRotateOp : public IntShiftOp
 {
   protected:
 
-    uint32_t fullMask;
     uint32_t maskBeg;
     uint32_t maskEnd;
 
@@ -661,18 +660,29 @@ class IntRotateOp : public IntShiftOp
         maskBeg(machInst.mb),
         maskEnd(machInst.me)
     {
-        if (maskEnd >= maskBeg) {
-            fullMask = mask(31 - maskBeg, 31 - maskEnd);
-        } else {
-            fullMask = ~mask(31 - (maskEnd + 1), 31 - (maskBeg - 1));
-        }
     }
 
-    inline uint32_t
+    inline uint64_t
     rotate(uint32_t rs, uint32_t sh) const
     {
-        uint32_t n = shift & 31;
-        return (rs << n) | (rs >> (32 - n));
+        uint64_t res;
+        sh = sh & 0x1f;
+        res = rs;
+        res = (res << 32) | res;
+        res = (res << sh) | (res >> (32 - sh));
+        return res;
+    }
+
+    inline uint64_t
+    bitmask(uint32_t mb, uint32_t me) const
+    {
+        mb = mb & 0x1f;
+        me = me & 0x1f;
+        if (mb <= me) {
+            return mask(31 - mb, 31 - me);
+        } else {
+            return ~mask(31 - (me + 1), 31 - (mb - 1));
+        }
     }
 
     std::string generateDisassembly(
index ef66ac95ddf98743842209df3bf430b757e30728..1c67d3aaa98a5b813d2e108ff4bdb517ca4e60c5 100644 (file)
@@ -266,10 +266,27 @@ decode PO default Unknown::unknown() {
     }
 
     format IntRotateOp {
-        21: rlwinm({{ Ra = rotate(Rs, sh) & fullMask; }});
-        23: rlwnm({{ Ra = rotate(Rs, Rb) & fullMask; }});
-        20: rlwimi({{ Ra = (rotate(Rs, sh) & fullMask) |
-                           (Ra & ~fullMask); }});
+        21: rlwinm({{
+            uint64_t res;
+            res = rotate(Rs, shift);
+            res = res & bitmask(maskBeg, maskEnd);
+            Ra = res;
+        }});
+
+        23: rlwnm({{
+            uint64_t res;
+            res = rotate(Rs, Rb);
+            res = res & bitmask(maskBeg, maskEnd);
+            Ra = res;
+        }});
+
+        20: rlwimi({{
+            uint64_t res, mask;
+            mask = bitmask(maskBeg, maskEnd);
+            res = rotate(Rs, shift);
+            res = (res & mask) | (Ra & ~mask);
+            Ra = res;
+        }});
     }
 
     // There are a large number of instructions that have the same primary