arch-power: Fix disassembly for rotate instructions
authorSandipan Das <sandipan@linux.ibm.com>
Sat, 6 Feb 2021 11:52:03 +0000 (17:22 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Mon, 15 Feb 2021 08:32:38 +0000 (14:02 +0530)
This fixes disassembly generated for integer rotate
instructions based on special use cases for which the
Power ISA provides extended mnemonics.

Change-Id: I8c33e7c8128ad62d856ce050df8a91b2dfd52f4c
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
src/arch/power/insts/integer.cc

index d921b5d1b08c07135b7a53b1e07d22cd71df6a96..aaa79253ff9f7fedb0efa8c38cb6ca612a4f51d0 100644 (file)
@@ -712,8 +712,40 @@ IntRotateOp::generateDisassembly(
         Addr pc, const Loader::SymbolTable *symtab) const
 {
     std::stringstream ss;
+    bool printSecondSrc = true;
+    bool printShift = true;
+    bool printMaskBeg = true;
+    bool printMaskEnd = true;
 
-    ccprintf(ss, "%-10s ", mnemonic);
+    // Generate the correct mnemonic
+    std::string myMnemonic(mnemonic);
+
+    // Special cases
+    if (!myMnemonic.compare("rlwinm")) {
+        if (maskBeg == 0 && maskEnd == 31) {
+            myMnemonic = "rotlwi";
+            printMaskBeg = false;
+            printMaskEnd = false;
+        } else if (shift == 0 && maskEnd == 31) {
+            myMnemonic = "clrlwi";
+            printShift = false;
+            printMaskEnd = false;
+        }
+        printSecondSrc = false;
+    } else if (!myMnemonic.compare("rlwnm")) {
+        if (maskBeg == 0 && maskEnd == 31) {
+            myMnemonic = "rotlw";
+            printMaskBeg = false;
+            printMaskEnd = false;
+        }
+        printShift = false;
+    } else if (!myMnemonic.compare("rlwimi")) {
+        printSecondSrc = 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) {
@@ -726,10 +758,40 @@ IntRotateOp::generateDisassembly(
             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;
     }
 
-    // Print the shift, mask begin and mask end
-    ss << ", " << sh << ", " << maskBeg << ", " << maskEnd;
+    // Print the mask bounds
+    if (printMaskBeg) {
+        ss << ", " << maskBeg;
+    }
+    if (printMaskEnd) {
+        ss << ", " << maskEnd;
+    }
 
     return ss.str();
 }