arch-power: Introduce proper opcode fields
authorSandipan Das <sandipan@linux.vnet.ibm.com>
Wed, 6 Jun 2018 21:00:09 +0000 (02:30 +0530)
committerSandipan Das <sandipan@linux.vnet.ibm.com>
Wed, 6 Jun 2018 21:00:09 +0000 (02:30 +0530)
This introduces separate extended opcode fields for DS, X, XFL,
XFX, XL and XO form instructions and renames the primary opcode
field from OPCODE to PO as listed in the Power ISA manual.

Scenarios where multiple instructions of different forms share
the same primary opcode have also been addressed by using the
correct extended opcode fields for decoding.

Change-Id: I4a01820f6a6326ef79330221b717952c6b9cbba3
Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
src/arch/power/isa/bitfields.isa
src/arch/power/isa/decoder.isa
src/arch/power/isa/formats/unimp.isa
src/arch/power/isa/formats/unknown.isa

index 2997ea52ffed2c52467ad0d91c48c22350621337..fcf592f8a9cdfcdfb4bdfc44b3f8d41b3d72b776 100644 (file)
 // are reversed sometimes. Not sure of a fix to this though...
 
 // Opcode fields
-def bitfield OPCODE        <31:26>;
-def bitfield X_XO          <10:0>;
-def bitfield XO_XO         <10:1>;
+def bitfield PO            <31:26>;
 def bitfield A_XO          <5:1>;
+def bitfield DS_XO         <1:0>;
+def bitfield X_XO          <10:1>;
+def bitfield XFL_XO        <10:1>;
+def bitfield XFX_XO        <10:1>;
+def bitfield XL_XO         <10:1>;
+def bitfield XO_XO         <9:1>;
 
 // Register fields
 def bitfield RA            <20:16>;
index ff5d6015ed44e4a6b4b1eef5d3c23a8933daadab..bce9465577bc79fa9930550420c319a21fef76f6 100644 (file)
@@ -36,7 +36,7 @@
 // I've used the Power ISA Book I v2.06 for instruction formats,
 // opcode numbers, register names, etc.
 //
-decode OPCODE default Unknown::unknown() {
+decode PO default Unknown::unknown() {
 
     18: decode AA {
 
@@ -64,7 +64,7 @@ decode OPCODE default Unknown::unknown() {
         }
     }
 
-    19: decode XO_XO {
+    19: decode XL_XO {
 
         // Conditionally branch to address in LR based on CR and CTR.
         format BranchLrCondCtr {
@@ -147,9 +147,14 @@ decode OPCODE default Unknown::unknown() {
         40: lhz({{ Rt = Mem_uh; }});
         42: lha({{ Rt = Mem_sh; }});
         32: lwz({{ Rt = Mem; }});
-        58: lwa({{ Rt = Mem_sw; }},
-                {{ EA = Ra + (disp & 0xfffffffc); }},
-                {{ EA = disp & 0xfffffffc; }});
+    }
+
+    58: decode DS_XO {
+        format LoadDispOp {
+            2: lwa({{ Rt = Mem_sw; }},
+                   {{ EA = Ra + (disp & 0xfffffffc); }},
+                   {{ EA = disp & 0xfffffffc; }});
+        }
     }
 
     format LoadDispUpdateOp {
@@ -227,12 +232,18 @@ decode OPCODE default Unknown::unknown() {
                            (Ra & ~fullMask); }});
     }
 
-    // Some instructions use bits 21 - 30, others 22 - 30. We have to use
-    // the larger size to account for all opcodes. For those that use the
-    // smaller value, the OE bit is bit 21. Therefore, we have two versions
-    // of each instruction: 1 with OE set, the other without. For an
-    // example see 'add' and 'addo'.
-    31: decode XO_XO {
+    // There are a large number of instructions that have the same primary
+    // opcode (PO) of 31. In this case, the instructions are of different
+    // forms. For every form, the XO fields may vary in position and width.
+    // The X, XFL, XFX and XL form instructions use bits 21 - 30 and the
+    // XO form instructions use bits 22 - 30 as extended opcode (XO). To
+    // avoid conflicts, instructions of each form have to be defined under
+    // separate decode blocks. However, only a single decode block can be
+    // associated with a particular PO and it will recognize only one type
+    // of XO field. A solution for associating decode blocks for the other
+    // types of XO fields with the same PO is to have the other blocks as
+    // nested default cases.
+    31: decode X_XO {
 
         // All loads with an index register. The non-update versions
         // all use the value 0 if Ra == R0, not the value contained in
@@ -288,94 +299,6 @@ decode OPCODE default Unknown::unknown() {
             183: stwux({{ Mem = Rs; }});
         }
 
-        // These instructions can all be reduced to the form
-        // Rt = src1 + src2 [+ CA], therefore we just give src1 and src2
-        // (and, if necessary, CA) definitions and let the python script
-        // deal with setting things up correctly. We also give flags to
-        // say which control registers to set.
-        format IntSumOp {
-            266: add({{ Ra }}, {{ Rb }});
-            40: subf({{ ~Ra }}, {{ Rb }}, {{ 1 }});
-            10: addc({{ Ra }}, {{ Rb }},
-                     computeCA = true);
-            8: subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }},
-                     true);
-            104: neg({{ ~Ra }}, {{ 1 }});
-            138: adde({{ Ra }}, {{ Rb }}, {{ xer.ca }},
-                      true);
-            234: addme({{ Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
-                       true);
-            136: subfe({{ ~Ra }}, {{ Rb }}, {{ xer.ca }},
-                       true);
-            232: subfme({{ ~Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
-                        true);
-            202: addze({{ Ra }}, {{ xer.ca }},
-                       computeCA = true);
-            200: subfze({{ ~Ra }}, {{ xer.ca }},
-                        computeCA = true);
-        }
-
-        // Arithmetic instructions all use source registers Ra and Rb,
-        // with destination register Rt.
-        format IntArithOp {
-            75: mulhw({{ int64_t prod = Ra_sd * Rb_sd; Rt = prod >> 32; }});
-            11: mulhwu({{ uint64_t prod = Ra_ud * Rb_ud; Rt = prod >> 32; }});
-            235: mullw({{ int64_t prod = Ra_sd * Rb_sd; Rt = prod; }});
-            747: mullwo({{
-                int64_t src1 = Ra_sd;
-                int64_t src2 = Rb;
-                int64_t prod = src1 * src2;
-                Rt = prod;
-            }},
-            true);
-
-            491: divw({{
-                int32_t src1 = Ra_sw;
-                int32_t src2 = Rb_sw;
-                if ((src1 != 0x80000000 || src2 != 0xffffffff)
-                    && src2 != 0) {
-                    Rt = src1 / src2;
-                } else {
-                    Rt = 0;
-                }
-            }});
-
-            1003: divwo({{
-                int32_t src1 = Ra_sw;
-                int32_t src2 = Rb_sw;
-                if ((src1 != 0x80000000 || src2 != 0xffffffff)
-                    && src2 != 0) {
-                    Rt = src1 / src2;
-                } else {
-                    Rt = 0;
-                    divSetOV = true;
-                }
-            }},
-            true);
-
-            459: divwu({{
-                uint32_t src1 = Ra_sw;
-                uint32_t src2 = Rb_sw;
-                if (src2 != 0) {
-                    Rt = src1 / src2;
-                } else {
-                    Rt = 0;
-                }
-            }});
-
-            971: divwuo({{
-              uint32_t src1 = Ra_sw;
-              uint32_t src2 = Rb_sw;
-              if (src2 != 0) {
-                  Rt = src1 / src2;
-              } else {
-                  Rt = 0;
-                  divSetOV = true;
-              }
-            }},
-            true);
-        }
-
         format IntOp {
             0: cmp({{
                 Xer xer = XER;
@@ -494,16 +417,6 @@ decode OPCODE default Unknown::unknown() {
 
         // Generic integer format instructions.
         format IntOp {
-            144: mtcrf({{
-                uint32_t mask = 0;
-                for (int i = 0; i < 8; ++i) {
-                    if (((FXM >> i) & 0x1) == 0x1) {
-                        mask |= 0xf << (4 * i);
-                    }
-                }
-                CR = (Rs & mask) | (CR & ~mask);
-                }});
-            19: mfcr({{ Rt = CR; }});
             339: decode SPR {
                 0x20: mfxer({{ Rt = XER; }});
                 0x100: mflr({{ Rt = LR; }});
@@ -534,6 +447,120 @@ decode OPCODE default Unknown::unknown() {
             598: sync({{ }}, [ IsMemBarrier ]);
             854: eieio({{ }}, [ IsMemBarrier ]);
         }
+
+        // These instructions are of XO form with bit 21 as the OE bit.
+        default: decode XO_XO {
+
+            // These instructions can all be reduced to the form
+            // Rt = src1 + src2 [+ CA], therefore we just give src1 and src2
+            // (and, if necessary, CA) definitions and let the python script
+            // deal with setting things up correctly. We also give flags to
+            // say which control registers to set.
+            format IntSumOp {
+                266: add({{ Ra }}, {{ Rb }});
+                40: subf({{ ~Ra }}, {{ Rb }}, {{ 1 }});
+                10: addc({{ Ra }}, {{ Rb }},
+                         computeCA = true);
+                8: subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }},
+                         true);
+                104: neg({{ ~Ra }}, {{ 1 }});
+                138: adde({{ Ra }}, {{ Rb }}, {{ xer.ca }},
+                          true);
+                234: addme({{ Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
+                           true);
+                136: subfe({{ ~Ra }}, {{ Rb }}, {{ xer.ca }},
+                           true);
+                232: subfme({{ ~Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
+                            true);
+                202: addze({{ Ra }}, {{ xer.ca }},
+                           computeCA = true);
+                200: subfze({{ ~Ra }}, {{ xer.ca }},
+                            computeCA = true);
+            }
+
+            // Arithmetic instructions all use source registers Ra and Rb,
+            // with destination register Rt.
+            format IntArithOp {
+                75: mulhw({{
+                    int64_t prod = Ra_sd * Rb_sd;
+                    Rt = prod >> 32;
+                }});
+                11: mulhwu({{
+                    uint64_t prod = Ra_ud * Rb_ud;
+                    Rt = prod >> 32;
+                }});
+                235: mullw({{ int64_t prod = Ra_sd * Rb_sd; Rt = prod; }});
+                747: mullwo({{
+                    int64_t src1 = Ra_sd;
+                    int64_t src2 = Rb;
+                    int64_t prod = src1 * src2;
+                    Rt = prod;
+                }},
+                true);
+
+                491: divw({{
+                    int32_t src1 = Ra_sw;
+                    int32_t src2 = Rb_sw;
+                    if ((src1 != 0x80000000 || src2 != 0xffffffff)
+                        && src2 != 0) {
+                        Rt = src1 / src2;
+                    } else {
+                        Rt = 0;
+                    }
+                }});
+
+                1003: divwo({{
+                    int32_t src1 = Ra_sw;
+                    int32_t src2 = Rb_sw;
+                    if ((src1 != 0x80000000 || src2 != 0xffffffff)
+                        && src2 != 0) {
+                        Rt = src1 / src2;
+                    } else {
+                        Rt = 0;
+                        divSetOV = true;
+                    }
+                }},
+                true);
+
+                459: divwu({{
+                    uint32_t src1 = Ra_sw;
+                    uint32_t src2 = Rb_sw;
+                    if (src2 != 0) {
+                        Rt = src1 / src2;
+                    } else {
+                        Rt = 0;
+                    }
+                }});
+
+                971: divwuo({{
+                  uint32_t src1 = Ra_sw;
+                  uint32_t src2 = Rb_sw;
+                  if (src2 != 0) {
+                      Rt = src1 / src2;
+                  } else {
+                      Rt = 0;
+                      divSetOV = true;
+                  }
+                }},
+                true);
+            }
+
+            default: decode XFX_XO {
+                format IntOp {
+                    144: mtcrf({{
+                        uint32_t mask = 0;
+                        for (int i = 0; i < 8; ++i) {
+                            if (((FXM >> i) & 0x1) == 0x1) {
+                                mask |= 0xf << (4 * i);
+                            }
+                        }
+                        CR = (Rs & mask) | (CR & ~mask);
+                    }});
+
+                    19: mfcr({{ Rt = CR; }});
+                }
+            }
+        }
     }
 
     format LoadDispOp {
@@ -581,7 +608,7 @@ decode OPCODE default Unknown::unknown() {
             30: fnmsub({{ Ft = -((Fa * Fc) - Fb); }});
         }
 
-        default: decode XO_XO {
+        default: decode X_XO {
             format FloatRCCheckOp {
                 72: fmr({{ Ft = Fb; }});
                 264: fabs({{
@@ -618,20 +645,23 @@ decode OPCODE default Unknown::unknown() {
                     FPSCR = insertCRField(FPSCR, BF + (8 * (1 - W_FIELD)),
                                           U_FIELD);
                 }});
-                711: mtfsf({{
-                    if (L_FIELD == 1) { FPSCR = Fb_ud; }
-                    else {
-                        for (int i = 0; i < 8; ++i) {
-                            if (bits(FLM, i) == 1) {
-                                int k = 4 * (i + (8 * (1 - W_FIELD)));
-                                FPSCR = insertBits(FPSCR, k + 3, k,
-                                                   bits(Fb_ud, k + 3, k));
-                            }
-                        }
-                    }
-                }});
                 70: mtfsb0({{ FPSCR = insertBits(FPSCR, 31 - BT, 0); }});
                 38: mtfsb1({{ FPSCR = insertBits(FPSCR, 31 - BT, 1); }});
+
+                default: decode XFL_XO {
+                    711: mtfsf({{
+                        if (L_FIELD == 1) { FPSCR = Fb_ud; }
+                        else {
+                            for (int i = 0; i < 8; ++i) {
+                                if (bits(FLM, i) == 1) {
+                                    int k = 4 * (i + (8 * (1 - W_FIELD)));
+                                    FPSCR = insertBits(FPSCR, k + 3, k,
+                                                       bits(Fb_ud, k + 3, k));
+                                }
+                            }
+                        }
+                    }});
+                }
             }
         }
     }
index 4c49ffac73a5262fd41f6765987bd2446e11c4c5..5a6a53d7f7800971895137753a86290cd05c2a07 100644 (file)
@@ -115,7 +115,7 @@ output exec {{
                                Trace::InstRecord *traceData) const
     {
         panic("attempt to execute unimplemented instruction '%s' "
-              "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
+              "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, PO,
               inst2string(machInst));
         return std::make_shared<UnimplementedOpcodeFault>();
     }
@@ -143,4 +143,3 @@ def format WarnUnimpl() {{
     iop = InstObjParams(name, 'WarnUnimplemented')
     decode_block = BasicDecodeWithMnemonic.subst(iop)
 }};
-
index ee4bc2a529cca76ec48a6d9ff543ead94a0990cd..1d420f3a071c2fb0e976cac138d09c0abd6d511c 100644 (file)
@@ -65,7 +65,7 @@ output decoder {{
     Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
     {
         return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)",
-                        "unknown", machInst, OPCODE, inst2string(machInst));
+                        "unknown", machInst, PO, inst2string(machInst));
     }
 }};
 
@@ -75,7 +75,7 @@ output exec {{
     {
         panic("attempt to execute unknown instruction at %#x"
               "(inst 0x%08x, opcode 0x%x, binary: %s)",
-              xc->pcState().pc(), machInst, OPCODE, inst2string(machInst));
+              xc->pcState().pc(), machInst, PO, inst2string(machInst));
         return std::make_shared<UnimplementedOpcodeFault>();
     }
 }};