// REGS_PATTERN is generated by id_regs.py (per opcode)
unsigned int floatintmap = REGS_PATTERN;
reg_t dest_pred = ~0x0;
- int dest_offs = 0;
+ int *dest_offs = &(p->get_state()->destoffs);
bool zeroing = false;
#ifdef INSN_CATEGORY_TWINPREDICATION
reg_t src_pred = ~0x0;
- int src_offs = 0;
+ int *src_offs = &(p->get_state()->srcoffs);
bool zeroingsrc = false;
#endif
sv_insn_t insn(p, bits, floatintmap, PRED_ARGS, OFFS_ARGS);
{
insn.reset_vloop_check();
#ifdef INSN_CATEGORY_TWINPREDICATION
- if (src_offs >= vlen) {
+ if (*src_offs >= vlen) {
break;
}
- if (dest_offs >= vlen) {
+ 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);
+ xstr(INSN), *src_offs, *dest_offs, src_pred, dest_pred);
#endif
if (!zeroingsrc)
{
- while ((src_pred & (1<<src_offs)) == 0) {
- src_offs += 1;
- if (src_offs >= vlen) {
+ while ((src_pred & (1<<*src_offs)) == 0) {
+ *src_offs += 1;
+ if (*src_offs >= vlen) {
break;
}
}
}
if (!zeroing)
{
- while ((dest_pred & (1<<dest_offs)) == 0) {
- dest_offs += 1;
- if (dest_offs >= vlen) {
+ while ((dest_pred & (1<<*dest_offs)) == 0) {
+ *dest_offs += 1;
+ if (*dest_offs >= vlen) {
break;
}
}
}
- if (src_offs >= vlen || dest_offs >= 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), src_offs, dest_offs, 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 %d %d" \
"vlen %d stop %d pred %lx rdv %lx rd %d rvc2 %d\n",
- xstr(INSN), INSNCODE, voffs, src_offs, dest_offs,
+ 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());
#include INCLUDEFILE
#ifdef DEST_PREDINT
// don't check inversion here as dest_pred has already been inverted
- if (zeroing && ((dest_pred & (1<<dest_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);
break;
}
#ifdef INSN_CATEGORY_TWINPREDICATION
- src_offs += 1;
+ *src_offs += 1;
#endif
- dest_offs += 1;
+ *dest_offs += 1;
}
+ // ok at the **END** of the looping we set the (ref'd) dest_offs and
+ // src_offs to zero. this allows any exceptions that are thrown
+ // to leave dest_offs and src_offs as they are, such that when
+ // the instruction is re-run it continues from where things left off.
+ *dest_offs = 0;
+#ifdef INSN_CATEGORY_TWINPREDICATION
+ *src_offs = 0;
+#endif
#else
insn_t insn(bits);
#include INCLUDEFILE
#ifdef SPIKE_SIMPLEV
uint64_t vl;
uint64_t mvl;
- uint64_t destoffs; // destination loop element offset
- uint64_t srcoffs; // source loop element offset (used in twin-predication)
+ int destoffs; // destination loop element offset
+ int srcoffs; // source loop element offset (used in twin-predication)
sv_reg_csr_entry sv_csrs[SV_CSR_SZ];
sv_reg_entry sv_int_tb[NXPR];
sv_reg_entry sv_fp_tb[NFPR];
* of SV. it's "supposed" to "just" be a vectorisation API. it isn't:
* it's quite a bit more.
*/
-uint64_t sv_insn_t::remap(uint64_t reg, bool intreg, int &voffs)
+uint64_t sv_insn_t::remap(uint64_t reg, bool intreg, int voffs)
{
// okaay so first determine which map to use. intreg is passed
// in (ultimately) from id_regs.py's examination of the use of
public:
sv_insn_t(processor_t *pr, insn_bits_t bits, unsigned int f,
uint64_t &p_rd, uint64_t &p_rs1, uint64_t &p_rs2, uint64_t &p_rs3,
- int &o_rd, int &o_rs1, int &o_rs2, int &o_rs3) :
+ int *o_rd, int *o_rs1, int *o_rs2, int *o_rs3) :
insn_t(bits), p(pr), vloop_continue(false), fimap(f),
offs_rd(o_rd), offs_rs1(o_rs1), offs_rs2(o_rs2), offs_rs3(o_rs3),
prd(p_rd), prs1(p_rs1), prs2(p_rs2), prs3(p_rs3) {}
- uint64_t rd () { return predicated(_rd (), offs_rd, prd); }
- uint64_t rs1() { return predicated(_rs1(), offs_rs1, prs1); }
- uint64_t rs2() { return predicated(_rs2(), offs_rs2, prs2); }
- uint64_t rs3() { return predicated(_rs3(), offs_rs3, prs3); }
- uint64_t rvc_rs1 () { return predicated(_rvc_rs1 (), offs_rs1, prs1); }
- uint64_t rvc_rs1s() { return predicated(_rvc_rs1s(), offs_rs1, prs1); }
- uint64_t rvc_rs2 () { return predicated(_rvc_rs2 (), offs_rs2, prs2); }
- uint64_t rvc_rs2s() { return predicated(_rvc_rs2s(), offs_rs2, prs2); }
+ uint64_t rd () { return predicated(_rd (), *offs_rd, prd); }
+ uint64_t rs1() { return predicated(_rs1(), *offs_rs1, prs1); }
+ uint64_t rs2() { return predicated(_rs2(), *offs_rs2, prs2); }
+ uint64_t rs3() { return predicated(_rs3(), *offs_rs3, prs3); }
+ uint64_t rvc_rs1 () { return predicated(_rvc_rs1 (), *offs_rs1, prs1); }
+ uint64_t rvc_rs1s() { return predicated(_rvc_rs1s(), *offs_rs1, prs1); }
+ uint64_t rvc_rs2 () { return predicated(_rvc_rs2 (), *offs_rs2, prs2); }
+ uint64_t rvc_rs2s() { return predicated(_rvc_rs2s(), *offs_rs2, prs2); }
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); }
private:
bool vloop_continue;
unsigned int fimap;
- int &offs_rd;
- int &offs_rs1;
- int &offs_rs2;
- int &offs_rs3;
+ int *offs_rd;
+ int *offs_rs1;
+ int *offs_rs2;
+ int *offs_rs3;
uint64_t &prd;
uint64_t &prs1;
uint64_t &prs2;
// 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);
+ 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 _remap(uint64_t reg, bool isint, int *offs)
{
if (sv_check_reg(isint, reg))
{
vloop_continue = true;
}
- return remap(reg, isint, offs);
+ return remap(reg, isint, *offs);
}
uint64_t predicated(uint64_t reg, int offs, uint64_t pred);