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;
// 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