reorganise twin-predication
[riscv-isa-sim.git] / riscv / insn_template_sv.cc
index 40d2a9b398a992e3c61c0a4c139ecec557c60a82..cab74d7c8f9ea254589f58183eec7050bb6b45e1 100644 (file)
@@ -19,12 +19,14 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
   // REGS_PATTERN is generated by id_regs.py (per opcode)
   unsigned int floatintmap = REGS_PATTERN;
   reg_t dest_pred = ~0x0;
+  int dest_offs = 0;
   bool zeroing = false;
 #ifdef INSN_CATEGORY_TWINPREDICATION
   reg_t src_pred = ~0x0;
+  int src_offs = 0;
   bool zeroingsrc = false;
 #endif
-  sv_insn_t insn(p, bits, floatintmap, PRED_ARGS);
+  sv_insn_t insn(p, bits, floatintmap, PRED_ARGS, OFFS_ARGS);
   if (vlen > 0)
   {
     fprintf(stderr, "pre-ex reg %s %x rd %ld rs1 %ld rs2 %ld vlen %d\n",
@@ -57,45 +59,55 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
   {
     insn.reset_vloop_check();
 #ifdef INSN_CATEGORY_TWINPREDICATION
-    int srcoffs = insn.rs_offs();
+    if (src_offs >= vlen) {
+        break;
+    }
+    if (dest_offs >= vlen) {
+        break;
+    }
+#ifdef INSN_C_MV
+        fprintf(stderr, "pre twin reg %s src %d dest %d pred %lx %lx\n",
+            xstr(INSN), src_offs, dest_offs, src_pred, dest_pred);
+#endif
     if (!zeroingsrc)
     {
-      while ((src_pred & (1<<srcoffs)) == 0) {
-          srcoffs = insn.rs_offs_inc();
-          if (srcoffs == vlen) {
+      while ((src_pred & (1<<src_offs)) == 0) {
+          src_offs += 1;
+          if (src_offs >= vlen) {
               break;
           }
       }
     }
-    int destoffs = insn.rd_offs();
     if (!zeroing)
     {
-      while ((dest_pred & (1<<destoffs)) == 0) {
-          destoffs = insn.rd_offs_inc();
-          if (destoffs == vlen) {
+      while ((dest_pred & (1<<dest_offs)) == 0) {
+          dest_offs += 1;
+          if (dest_offs >= vlen) {
               break;
           }
       }
     }
-    if (srcoffs == vlen || destoffs == vlen) {
+    if (src_offs >= vlen || dest_offs >= vlen) {
         break; // end vector loop if either src or dest pred reaches end
     }
     if (vlen > 1)
     {
         fprintf(stderr, "twin reg %s src %d dest %d pred %lx %lx\n",
-            xstr(INSN), srcoffs, destoffs, src_pred, dest_pred);
+            xstr(INSN), src_offs, dest_offs, src_pred, dest_pred);
     }
 #endif
 #ifdef INSN_C_MV
-    fprintf(stderr, "pre loop reg %s %x vloop %d " \
-                      "vlen %d stop %d pred %lx rd%lx rvc2%d\n",
-                xstr(INSN), INSNCODE, voffs, vlen, insn.stop_vloop(),
-                dest_pred & (1<<voffs), READ_REG(insn._rd()), insn.rvc_rs2());
+    fprintf(stderr, "pre loop reg %s %x vloop %d %d %d" \
+                      "vlen %d stop %d pred %lx rdv %lx rd %d rvc2 %d\n",
+                xstr(INSN), INSNCODE, voffs, src_offs, dest_offs,
+                vlen, insn.stop_vloop(),
+                dest_pred & (1<<voffs), READ_REG(insn._rd()),
+                insn._rd(), insn._rvc_rs2());
 #endif
       #include INCLUDEFILE
 #ifdef DEST_PREDINT
       // don't check inversion here as dest_pred has already been inverted
-      if (zeroing && ((dest_pred & (1<<insn.rd_offs())) == 0))
+      if (zeroing && ((dest_pred & (1<<dest_offs)) == 0))
       {
           // insn._rd() would be predicated: have to use insn._rd() here
           WRITE_REG(insn._DEST_REG(), 0);
@@ -103,7 +115,6 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
 #endif
       if (vlen > 1)
       {
-        insn.reset_caches(); // ready to increment offsets
 #if defined(USING_REG_RD)
         fprintf(stderr, "reg %s %x vloop %d vlen %d stop %d pred %lx rd%lx\n",
                 xstr(INSN), INSNCODE, voffs, vlen, insn.stop_vloop(),
@@ -120,6 +131,10 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
       {
         break;
       }
+#ifdef INSN_CATEGORY_TWINPREDICATION
+      src_offs += 1;
+#endif
+      dest_offs += 1;
   }
 #else
   insn_t insn(bits);