arch-power: Fix disassembly for compare instructions
authorSandipan Das <sandipan@linux.ibm.com>
Sat, 6 Feb 2021 11:50:56 +0000 (17:20 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Mon, 15 Feb 2021 08:32:38 +0000 (14:02 +0530)
This fixes disassembly generated for integer compare
instructions based on the type of operands, the type of
comparison to be made and the special use cases for which
the Power ISA provides extended mnemonics.

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

index da7f392eac925fc1cf677377d9fbc5abe14db1b3..4a03f8fa39a5978bad8e5515ab9115d5d9369ae1 100644 (file)
@@ -49,7 +49,6 @@ IntOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const
                !myMnemonic.compare("mtxer") ||
                !myMnemonic.compare("mtlr")  ||
                !myMnemonic.compare("mtctr") ||
-               !myMnemonic.compare("cmpi")  ||
                !myMnemonic.compare("mttar")) {
         printDest = false;
     } else if (!myMnemonic.compare("mfcr")  ||
@@ -286,6 +285,185 @@ IntDispArithOp::generateDisassembly(
 }
 
 
+std::string
+IntCompOp::generateDisassembly(
+        Addr pc, const Loader::SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    bool printFieldPrefix = false;
+    bool printLength = true;
+
+    // Generate the correct mnemonic
+    std::string myMnemonic(mnemonic);
+
+    // Special cases
+    if (!myMnemonic.compare("cmp")) {
+        if (length) {
+            myMnemonic = "cmpd";
+        } else {
+            myMnemonic = "cmpw";
+        }
+        printFieldPrefix = true;
+        printLength = false;
+    } else if (!myMnemonic.compare("cmpl")) {
+        if (length) {
+            myMnemonic = "cmpld";
+        } else {
+            myMnemonic = "cmplw";
+        }
+        printFieldPrefix = true;
+        printLength = false;
+    }
+
+    ccprintf(ss, "%-10s ", myMnemonic);
+
+    // Print the first destination only
+    if (printFieldPrefix) {
+        if (field > 0) {
+            ss << "cr" << field;
+        }
+    } else {
+        ss << field;
+    }
+
+    // Print the length
+    if (printLength) {
+        if (!printFieldPrefix || field > 0) {
+            ss << ", ";
+        }
+        ss << length;
+    }
+
+    // Print the first source register
+    if (_numSrcRegs > 0) {
+        if (!printFieldPrefix || field > 0 || printLength) {
+            ss << ", ";
+        }
+        printReg(ss, srcRegIdx(0));
+
+        // Print the second source register
+        if (_numSrcRegs > 1) {
+            ss << ", ";
+            printReg(ss, srcRegIdx(1));
+        }
+    }
+
+    return ss.str();
+}
+
+
+std::string
+IntImmCompOp::generateDisassembly(
+        Addr pc, const Loader::SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    bool printFieldPrefix = false;
+    bool printLength = true;
+
+    // Generate the correct mnemonic
+    std::string myMnemonic(mnemonic);
+
+    // Special cases
+    if (!myMnemonic.compare("cmpi")) {
+        if (length) {
+            myMnemonic = "cmpdi";
+        } else {
+            myMnemonic = "cmpwi";
+        }
+        printFieldPrefix = true;
+        printLength = false;
+    }
+
+    ccprintf(ss, "%-10s ", myMnemonic);
+
+    // Print the first destination only
+    if (printFieldPrefix) {
+        if (field > 0) {
+            ss << "cr" << field;
+        }
+    } else {
+        ss << field;
+    }
+
+    // Print the length
+    if (printLength) {
+        if (!printFieldPrefix || field > 0) {
+            ss << ", ";
+        }
+        ss << length;
+    }
+
+    // Print the first source register
+    if (_numSrcRegs > 0) {
+        if (!printFieldPrefix || field > 0 || printLength) {
+            ss << ", ";
+        }
+        printReg(ss, srcRegIdx(0));
+    }
+
+    // Print the immediate value
+    ss << ", " << simm;
+
+    return ss.str();
+}
+
+
+std::string
+IntImmCompLogicOp::generateDisassembly(
+        Addr pc, const Loader::SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    bool printFieldPrefix = false;
+    bool printLength = true;
+
+    // Generate the correct mnemonic
+    std::string myMnemonic(mnemonic);
+
+    // Special cases
+    if (!myMnemonic.compare("cmpli")) {
+        if (length) {
+            myMnemonic = "cmpldi";
+        } else {
+            myMnemonic = "cmplwi";
+        }
+        printFieldPrefix = true;
+        printLength = false;
+    }
+
+    ccprintf(ss, "%-10s ", myMnemonic);
+
+    // Print the first destination only
+    if (printFieldPrefix) {
+        if (field > 0) {
+            ss << "cr" << field;
+        }
+    } else {
+        ss << field;
+    }
+
+    // Print the mode
+    if (printLength) {
+        if (!printFieldPrefix || field > 0) {
+            ss << ", ";
+        }
+        ss << length;
+    }
+
+    // Print the first source register
+    if (_numSrcRegs > 0) {
+        if (!printFieldPrefix || field > 0 || printLength) {
+            ss << ", ";
+        }
+        printReg(ss, srcRegIdx(0));
+    }
+
+    // Print the immediate value
+    ss << ", " << uimm;
+
+    return ss.str();
+}
+
+
 std::string
 IntShiftOp::generateDisassembly(
         Addr pc, const Loader::SymbolTable *symtab) const
index 75d4543e24c52c61e8959c3987f1c954da5b937e..2cf35ab9ca29956e126ea02a9b3f5de00ff7ba03 100644 (file)
@@ -443,6 +443,9 @@ class IntCompOp : public IntOp
         field(machInst.bf)
     {
     }
+
+    std::string generateDisassembly(
+            Addr pc, const Loader::SymbolTable *symtab) const override;
 };
 
 
@@ -461,6 +464,9 @@ class IntImmCompOp : public IntCompOp
         simm((int16_t)machInst.si)
     {
     }
+
+    std::string generateDisassembly(
+            Addr pc, const Loader::SymbolTable *symtab) const override;
 };
 
 
@@ -479,6 +485,9 @@ class IntImmCompLogicOp : public IntCompOp
         uimm(machInst.ui)
     {
     }
+
+    std::string generateDisassembly(
+            Addr pc, const Loader::SymbolTable *symtab) const override;
 };