arch-power: Refactor shift instructions
authorSandipan Das <sandipan@linux.ibm.com>
Sat, 6 Feb 2021 11:51:37 +0000 (17:21 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Mon, 15 Feb 2021 08:32:38 +0000 (14:02 +0530)
This changes the format for integer shift instructions
such that the computation of the carry bit is implicitly
handled rather than including it in the definition of an
instruction.

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

index 1e4ce368b563ea80bb21508081cacf904a3a8c9e..14b6daca5468dbc760e17eabca667f244dced971 100644 (file)
@@ -599,18 +599,19 @@ class IntImmLogicOp : public IntLogicOp
 
 
 /**
- * Class for integer operations with a shift.
+ * Class for integer operations with a shift value obtained from
+ * a register or an instruction field.
  */
 class IntShiftOp : public IntOp
 {
   protected:
 
-    uint32_t sh;
+    uint32_t shift;
 
     /// Constructor
     IntShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass)
       : IntOp(mnem, _machInst, __opClass),
-        sh(machInst.sh)
+        shift(machInst.sh)
     {
     }
 
index 908ba3c26cf38fb5ada7ba0badd3c2ae824f89f3..80886de93171a109039581b438aef27b9b7de425 100644 (file)
@@ -583,7 +583,10 @@ decode PO default Unknown::unknown() {
                 }
                 Ra = res;
             }});
+        }
 
+        // Integer instructions with a shift value.
+        format IntShiftOp {
             24: slw({{
                 if (Rb & 0x20) {
                     Ra = 0;
@@ -601,65 +604,46 @@ decode PO default Unknown::unknown() {
             }});
 
             792: sraw({{
-                bool shiftSetCA = false;
                 int32_t s = Rs;
                 if (Rb == 0) {
                     Ra = Rs;
-                    shiftSetCA = true;
+                    setCA = true;
                 } else if (Rb & 0x20) {
                     if (s < 0) {
                         Ra = (uint32_t)-1;
                         if (s & 0x7fffffff) {
-                            shiftSetCA = true;
+                            setCA = true;
                         } else {
-                            shiftSetCA = false;
+                            setCA = false;
                         }
                     } else {
                         Ra = 0;
-                        shiftSetCA = false;
+                        setCA = false;
                     }
                 } else {
                     Ra = s >> (Rb & 0x1f);
                     if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) {
-                        shiftSetCA = true;
+                        setCA = true;
                     } else {
-                        shiftSetCA = false;
+                        setCA = false;
                     }
                 }
-                Xer xer1 = XER;
-                if (shiftSetCA) {
-                    xer1.ca = 1;
-                } else {
-                    xer1.ca = 0;
-                }
-                XER = xer1;
-            }});
-        }
+            }}, true);
 
-        // Integer logic instructions with a shift value.
-        format IntShiftOp {
             824: srawi({{
-                bool shiftSetCA = false;
                 if (sh == 0) {
                     Ra = Rs;
-                    shiftSetCA = false;
+                    setCA = false;
                 } else {
                     int32_t s = Rs;
                     Ra = s >> sh;
                     if (s < 0 && (s << (32 - sh)) != 0) {
-                        shiftSetCA = true;
+                        setCA = true;
                     } else {
-                        shiftSetCA = false;
+                        setCA = false;
                     }
                 }
-                Xer xer1 = XER;
-                if (shiftSetCA) {
-                    xer1.ca = 1;
-                } else {
-                    xer1.ca = 0;
-                }
-                XER = xer1;
-            }});
+            }}, true);
         }
 
         format StoreIndexOp {
index 286c1cf98e3f0c4a3380c4197d6dbda4e5e05af8..4fa21349dbb1fa8a8998a5acf296e5fdf25bd1e1 100644 (file)
@@ -110,6 +110,16 @@ computeOVCode = '''
     }
 '''
 
+setCACode = '''
+    if (setCA) {
+        xer.ca = 1;
+        xer.ca32 = 1;
+    } else {
+        xer.ca = 0;
+        xer.ca32 = 0;
+    }
+'''
+
 setOVCode = '''
     if (setOV) {
         xer.ov = 1;
@@ -305,13 +315,26 @@ def format IntLogicOp(code, computeCR0 = 0, inst_flags = []) {{
 }};
 
 
-// Integer instructions with a shift amount. As above, except inheriting
-// from the IntShiftOp class.
-def format IntShiftOp(code, inst_flags = []) {{
+// Integer instructions that perform shift operations. All of these
+// instructions write to Ra and use Rs as a source register. The shift
+// value is obtained from an register or an instruction field. If it
+// from a register, Rb is also used as a source register. In certain
+// situations, the carry bits have to be set and this is dealt with
+// using the 'setCA' boolean in decoder.isa. We need two versions for
+// each instruction to deal with the Rc bit.
+def format IntShiftOp(code, computeCA = 0, inst_flags = []) {{
     dict = {'result':'Ra'}
 
+    # Add code to setup variables and access XER if necessary
+    code  = 'M5_VAR_USED bool setCA = false;\n' + code
+
     # Code when Rc is set
-    code_rc1 = code + readXERCode + computeCR0Code % dict
+    code_rc1 = readXERCode + code + computeCR0Code % dict
+
+    # Add code for calculating the carry, if needed
+    if computeCA:
+        code = readXERCode + code + setCACode + setXERCode
+        code_rc1 += setCACode + setXERCode
 
     # Generate the first class
     (header_output, decoder_output, decode_block, exec_output) = \