arch-power: Fix extended opcode based decoding
authorSandipan Das <sandipan@linux.ibm.com>
Sat, 6 Feb 2021 11:46:35 +0000 (17:16 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Mon, 15 Feb 2021 08:32:37 +0000 (14:02 +0530)
When multiple instructions share the same primary opcode,
they are distinguished by the decoder by looking at the
extended opcode. However, the length and position of the
extended opcode field can vary based on instruction form.

This ensures that the correct extended opcode fields are
used for decoding such instructions.

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

index fa6c9cb47f834885e1f77c70cba1235936c80b20..478b2546de3894e615cb82ee6e983736bfa086bd 100644 (file)
@@ -62,7 +62,7 @@ decode PO default Unknown::unknown() {
         }
     }
 
-    19: decode XO_XO {
+    19: decode XL_XO {
 
         // Conditionally branch to address in LR based on CR and CTR.
         format BranchLrCondCtr {
@@ -144,9 +144,14 @@ decode PO 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 {
@@ -224,12 +229,18 @@ decode PO 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
@@ -285,94 +296,6 @@ decode PO 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;
@@ -489,34 +412,6 @@ decode PO 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; }});
-                0x120: mfctr({{ Rt = CTR; }});
-            }
-            467: decode SPR {
-                0x20: mtxer({{ XER = Rs; }});
-                0x100: mtlr({{ LR = Rs; }});
-                0x120: mtctr({{ CTR = Rs; }});
-            }
-            512: mcrxr({{
-                CR = insertCRField(CR, BF, XER<31:28>);
-                XER = XER<27:0>;
-                }});
-        }
-
         format StoreIndexOp {
             663: stfsx({{ Mem_sf = Fs_sf; }});
             727: stfdx({{ Mem_df = Fs; }});
@@ -535,6 +430,137 @@ decode PO default Unknown::unknown() {
             598: sync({{ }}, [ IsReadBarrier, IsWriteBarrier ]);
             854: eieio({{ }}, [ IsReadBarrier, IsWriteBarrier ]);
         }
+
+        // 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 {
+                    339: decode SPR {
+                        0x20: mfxer({{ Rt = XER; }});
+                        0x100: mflr({{ Rt = LR; }});
+                        0x120: mfctr({{ Rt = CTR; }});
+                    }
+
+                    467: decode SPR {
+                        0x20: mtxer({{ XER = Rs; }});
+                        0x100: mtlr({{ LR = Rs; }});
+                        0x120: mtctr({{ CTR = Rs; }});
+                    }
+
+                    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; }});
+
+                    512: mcrxr({{
+                        CR = insertCRField(CR, BF, XER<31:28>);
+                        XER = XER<27:0>;
+                    }});
+                }
+            }
+        }
     }
 
     format LoadDispOp {
@@ -582,7 +608,7 @@ decode PO 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({{
@@ -619,20 +645,23 @@ decode PO 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));
+                                }
+                            }
+                        }
+                    }});
+                }
             }
         }
     }