cache the sv redirected register values on each loop
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 26 Sep 2018 15:21:19 +0000 (16:21 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 26 Sep 2018 15:21:19 +0000 (16:21 +0100)
if an emulated opcode ever calls insn.rd() or rs1-3 more than once
sv_inst_t::remap would accidentally increment the loop offset before
it was time to do so.

therefore put in a cacheing system and clear it only at the end
of each loop

riscv/insn_template_sv.cc
riscv/sv_decode.h

index b8bad7aa92a5e6f683961663da4fb5539600800d..de09f50d3ea9c76bc4eff6744c3d28af16fcb726 100644 (file)
@@ -56,6 +56,7 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
   for (int voffs=0; voffs < vlen; voffs++)
   {
       #include INCLUDEFILE
+      insn.reset_caches(); // ready to increment offsets in next iteration
   }
 #else
   insn_t insn(bits);
index 49a16784c58cecd0cc311136f6d7bf3836b3c68d..eca0e777d022a35911e8b1e5d66de680a09a99c5 100644 (file)
@@ -16,14 +16,32 @@ class sv_insn_t: public insn_t
 public:
   sv_insn_t(insn_bits_t bits, unsigned int f) :
             insn_t(bits), fimap(f),
+            cached_rd(0xff), cached_rs1(0xff),
+            cached_rs2(0xff), cached_rs3(0xff),
             offs_rd(0), offs_rs1(0),
             offs_rs2(0), offs_rs3(0) {}
-  uint64_t rd () { return remap(insn_t::rd (), fimap & REG_RD , offs_rd); }
-  uint64_t rs1() { return remap(insn_t::rs1(), fimap & REG_RS1, offs_rs1); }
-  uint64_t rs2() { return remap(insn_t::rs2(), fimap & REG_RS2, offs_rs2); }
-  uint64_t rs3() { return remap(insn_t::rs3(), fimap & REG_RS3, offs_rs3); }
+  uint64_t rd ()
+    { return _remap(insn_t::rd (), fimap & REG_RD , offs_rd , cached_rd); }
+  uint64_t rs1()
+    { return _remap(insn_t::rs1(), fimap & REG_RS1, offs_rs1, cached_rs1); }
+  uint64_t rs2()
+    { return _remap(insn_t::rs2(), fimap & REG_RS2, offs_rs2, cached_rs2); }
+  uint64_t rs3()
+    { return _remap(insn_t::rs3(), fimap & REG_RS3, offs_rs3, cached_rs3); }
+
+  void reset_caches(void)
+  {
+    cached_rd = 0xff;
+    cached_rs1 = 0xff;
+    cached_rs2 = 0xff;
+    cached_rs3 = 0xff;
+  }
 private:
   unsigned int fimap;
+  uint64_t cached_rd;
+  uint64_t cached_rs1;
+  uint64_t cached_rs2;
+  uint64_t cached_rs3;
   int offs_rd;
   int offs_rs1;
   int offs_rs2;
@@ -31,6 +49,18 @@ private:
   // remaps the register through the lookup table.
   // will need to take the current loop index/offset somehow
   uint64_t remap(uint64_t reg, bool isint, int &offs);
+
+  // cached version of remap: if remap is called multiple times
+  // by an emulated instruction it would increment the loop offset
+  // before it's supposed to.
+  uint64_t _remap(uint64_t reg, bool isint, int &offs, uint64_t &cached)
+  {
+    if (cached == 0xff)
+    {
+        cached = remap(reg, isint, offs);
+    }
+    return cached;
+  }
 };
 
 #endif