arch-power: Fix fixed-point logical instructions
authorSandipan Das <sandipan@linux.vnet.ibm.com>
Thu, 7 Jun 2018 09:19:41 +0000 (14:49 +0530)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 24 Jan 2021 03:25:58 +0000 (03:25 +0000)
This fixes the following logical instructions:
  * Extend Sign Byte (extsb[.])
  * Extend Sign Halfword (extsh[.])
  * Count Leading Zeros Word (cntlzw[.])
  * Compare Bytes (cmpb)

This also fixes disassembly generation for all of the above.

Change-Id: I98873edf24db606d8de481aa18bcb809ad38d296
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 b55f75ccd61c278c4c977deda0c53ee601af4282..4f2804f9c6bdf33573f976c44bb3bd40abff8375 100644 (file)
@@ -278,6 +278,117 @@ IntDispArithOp::generateDisassembly(
 }
 
 
+string
+IntLogicOp::generateDisassembly(
+        Addr pc, const Loader::SymbolTable *symtab) const
+{
+    stringstream ss;
+    bool printSecondSrc = true;
+
+    // Generate the correct mnemonic
+    string myMnemonic(mnemonic);
+
+    // Special cases
+    if (!myMnemonic.compare("or") && _srcRegIdx[0] == _srcRegIdx[1]) {
+        myMnemonic = "mr";
+        printSecondSrc = false;
+    } else if (!myMnemonic.compare("extsb") ||
+               !myMnemonic.compare("extsh") ||
+               !myMnemonic.compare("cntlzw")) {
+        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) {
+        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]);
+                }
+            }
+        }
+    }
+
+    return ss.str();
+}
+
+
+string
+IntImmLogicOp::generateDisassembly(
+        Addr pc, const Loader::SymbolTable *symtab) const
+{
+    stringstream ss;
+    bool printRegs = true;
+
+    // Generate the correct mnemonic
+    string myMnemonic(mnemonic);
+
+    // Special cases
+    if (!myMnemonic.compare("ori") &&
+        _destRegIdx[0].index() == 0 && _srcRegIdx[0].index() == 0) {
+        myMnemonic = "nop";
+        printRegs = false;
+    } else if (!myMnemonic.compare("xori") &&
+               _destRegIdx[0].index() == 0 && _srcRegIdx[0].index() == 0) {
+        myMnemonic = "xnop";
+        printRegs = false;
+    } else if (!myMnemonic.compare("andi_")) {
+        myMnemonic = "andi.";
+    } else if (!myMnemonic.compare("andis_")) {
+        myMnemonic = "andis.";
+    }
+
+    ccprintf(ss, "%-10s ", myMnemonic);
+
+    if (printRegs) {
+
+        // Print the first destination only
+        if (_numDestRegs > 0) {
+            printReg(ss, _destRegIdx[0]);
+        }
+
+        // Print the source register
+        if (_numSrcRegs > 0) {
+            if (_numDestRegs > 0) {
+                ss << ", ";
+            }
+            printReg(ss, _srcRegIdx[0]);
+        }
+
+        // Print the immediate value
+        ss << ", " << uimm;
+    }
+
+     return ss.str();
+}
+
+
 string
 IntCompOp::generateDisassembly(
         Addr pc, const Loader::SymbolTable *symtab) const
index c691ad39b1f48efaaeed150b1a144f81f2e39b82..0cdd2b4570a161d8c0122e9c7e26c515b1f06441 100644 (file)
@@ -479,6 +479,60 @@ class IntImmCompLogicOp : public IntCompOp
 };
 
 
+/**
+ * Class for integer logical operations.
+ */
+class IntLogicOp : public IntOp
+{
+  protected:
+
+    /// Constructor
+    IntLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+      : IntOp(mnem, _machInst, __opClass)
+    {
+    }
+
+    inline int
+    findLeadingZeros(uint32_t rs) const
+    {
+        if (rs) {
+    #if defined(__GNUC__) || (defined(__clang__) && \
+                              __has_builtin(__builtin_clz))
+            return __builtin_clz(rs);
+    #else
+            return 31 - findMsbSet(rs);
+    #endif
+        } else {
+            return 32;
+        }
+    }
+
+    std::string generateDisassembly(
+            Addr pc, const SymbolTable *symtab) const override;
+};
+
+
+/**
+ * Class for integer immediate logical operations.
+ */
+class IntImmLogicOp : public IntLogicOp
+{
+  protected:
+
+    uint32_t uimm;
+
+    /// Constructor
+    IntImmLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+      : IntLogicOp(mnem, _machInst, __opClass),
+        uimm(machInst.si)
+    {
+    }
+
+    std::string generateDisassembly(
+            Addr pc, const SymbolTable *symtab) const override;
+};
+
+
 /**
  * Class for integer operations with a shift.
  */
index 2154de279c211ec84fab5cb479109c17552b380c..77ce3c04c3cbb828db5ff08c7658922aa1fbe81b 100644 (file)
@@ -501,25 +501,28 @@ decode PO default Unknown::unknown() {
         // Integer logic instructions use source registers Rs and Rb,
         // with destination register Ra.
         format IntLogicOp {
-            28: and({{ Ra = Rs & Rb; }});
-            316: xor({{ Ra = Rs ^ Rb; }});
-            476: nand({{ Ra = ~(Rs & Rb); }});
-            444: or({{ Ra = Rs | Rb; }});
-            124: nor({{ Ra = ~(Rs | Rb); }});
-            60: andc({{ Ra = Rs & ~Rb; }});
-            954: extsb({{ Ra = sext<8>(Rs); }});
-            284: eqv({{ Ra = ~(Rs ^ Rb); }});
-            412: orc({{ Ra = Rs | ~Rb; }});
-            922: extsh({{ Ra = sext<16>(Rs); }});
-            26: cntlzw({{ Ra = Rs == 0 ? 32 : 31 - findMsbSet(Rs); }});
+            28: and({{ Ra = Rs & Rb; }}, true);
+            316: xor({{ Ra = Rs ^ Rb; }}, true);
+            476: nand({{ Ra = ~(Rs & Rb); }}, true);
+            444: or({{ Ra = Rs | Rb; }}, true);
+            124: nor({{ Ra = ~(Rs | Rb); }}, true);
+            60: andc({{ Ra = Rs & ~Rb; }}, true);
+            284: eqv({{ Ra = ~(Rs ^ Rb); }}, true);
+            412: orc({{ Ra = Rs | ~Rb; }}, true);
+            954: extsb({{ Ra = Rs_sb; }}, true);
+            922: extsh({{ Ra = Rs_sh; }}, true);
+            26: cntlzw({{ Ra = findLeadingZeros(Rs_uw); }}, true);
+
             508: cmpb({{
-                uint32_t val = 0;
-                for (int n = 0; n < 32; n += 8) {
-                    if(bits(Rs, n+7, n) == bits(Rb, n+7, n)) {
-                        val = insertBits(val, n+7, n, 0xff);
+                uint64_t mask = 0xff;
+                uint64_t res = 0;
+                for (int i = 0; i < 8; ++i) {
+                    if ((Rs & mask) == (Rb & mask)) {
+                        res |= mask;
                     }
+                    mask <<= 8;
                 }
-                Ra = val;
+                Ra = res;
             }});
 
             24: slw({{
index a22e4fd95015dd4bc1c65568ec478ebc3fb7cf80..057277ffb96c4bcb1669d906434d4d1656304de2 100644 (file)
@@ -200,12 +200,14 @@ def format IntImmLogicOp(code, computeCR0 = 0, inst_flags = []) {{
 
     # Set up the dictionary and deal with computing CR0
     dict = {'result':'Ra'}
+
+    # Code when Rc is set
     if computeCR0:
         code += readXERCode + computeCR0Code % dict
 
     # Generate the class
     (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode,
+        GenAluOp(name, Name, 'IntImmLogicOp', code, inst_flags, BasicDecode,
                  BasicConstructor)
 }};
 
@@ -273,29 +275,37 @@ def format IntImmCompLogicOp(code, inst_flags = []) {{
 
 
 // Integer instructions that perform logic operations. The result is
-// always written into Ra. All instructions have 2 versions depending on
+// always written into Ra. Some instructions have 2 versions depending on
 // whether the Rc bit is set to compute the CR0 code. This is determined
 // at decode as before.
-def format IntLogicOp(code, inst_flags = []) {{
+def format IntLogicOp(code, computeCR0 = 0, inst_flags = []) {{
     dict = {'result':'Ra'}
 
-    # Code when Rc is set
-    code_rc1 = code + readXERCode + computeCR0Code % dict
+    # Deal with computing CR0
+    if computeCR0:
+        # Setup the 2 code versions and add code to access XER if necessary
+        code_rc1 = code + readXERCode + computeCR0Code % dict
 
-    # Generate the first class
-    (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'IntOp', code, inst_flags,
-                 CheckRcDecode, BasicConstructor)
+        # Generate the first class
+        (header_output, decoder_output, decode_block, exec_output) = \
+            GenAluOp(name, Name, 'IntLogicOp', code, inst_flags,
+                    CheckRcDecode, BasicConstructor)
 
-    # Generate the second class
-    (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
-        GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
-                 CheckRcDecode, IntRcConstructor)
+        # Generate the second class
+        (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+            GenAluOp(name, Name + 'RcSet', 'IntLogicOp', 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
+        # Finally, add to the other outputs
+        header_output += header_output_rc1
+        decoder_output += decoder_output_rc1
+        exec_output += exec_output_rc1
+
+    else:
+        # Generate the class
+        (header_output, decoder_output, decode_block, exec_output) = \
+            GenAluOp(name, Name, 'IntLogicOp', code, inst_flags,
+                     BasicDecode, BasicConstructor)
 }};