#ifdef INSN_TYPE_BRANCH
#define set_pc(x) insn.setpc(xlen, vlen, npc, x, \
- *dest_offs, target_reg);
+ *dest_offs, target_reg, zeroingtarg, invtarg);
#else
#define set_pc _set_pc
#endif
// ok, at the end of the loop, if the predicates are equal,
// we're good to branch. use the saved address (to avoid
// calculating the BRANCH_TARGET macro again)
- uint64_t mask = (1<<vlen) - 1;
- if (insn.get_if_one_reg_vectorised() &&
- (insn.get_saved_branch_rd() & mask) == (target_pred & mask))
+ if (r->active) // only when predication is set
{
- fprintf(stderr, "vector branch ACTIVE\n");
- _set_pc(insn.get_saved_branch_addr());
+ uint64_t mask = (1<<vlen) - 1;
+ if (insn.get_if_one_reg_vectorised() &&
+ (insn.get_saved_branch_rd() & mask) == (target_pred & mask))
+ {
+ fprintf(stderr, "vector branch ACTIVE\n");
+ _set_pc(insn.get_saved_branch_addr());
+ }
}
#endif
// ok at the **END** of the looping we set the (ref'd) dest_offs and
*/
reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing)
{
- bool inv = false;
- return predicate(reg, intreg, zeroing, inv);
+ sv_reg_entry *pr = get_regentry(reg, intreg);
+ if (!pr->active)
+ {
+ return ~0x0; // *REGISTER* not active: return all-1s (unconditional "on")
+ }
+ sv_pred_entry *r = get_predentry(reg, intreg);
+ if (!r->active)
+ {
+ return ~0x0; // *PREDICATION* not active: return all-1s (unconditional "on")
+ }
+ zeroing = r->zero;
+ fprintf(stderr, "predicate read %ld -> %ld\n", reg, r->regidx);
+ reg = r->regidx;
+ reg_spec_t rs = {reg, NULL};
+ reg_t pred = p->s.READ_REG(rs); // macros go through processor_t state
+ if (r->inv)
+ {
+ return ~pred;
+ }
+ return pred;
}
+
+// XXX WARNING: this fn does NOT invert the predicate (if r->inv return ~pred)
reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing, bool &inv)
{
sv_reg_entry *pr = get_regentry(reg, intreg);
return ~0x0; // *PREDICATION* not active: return all-1s (unconditional "on")
}
zeroing = r->zero;
+ inv = r->inv;
fprintf(stderr, "predicate read %ld -> %ld\n", reg, r->regidx);
reg = r->regidx;
reg_spec_t rs = {reg, NULL};
reg_t predicate = p->s.READ_REG(rs); // macros go through processor_t state
- if (r->inv)
- {
- return ~predicate;
- }
return predicate;
}
}
void sv_insn_t::setpc(int xlen, int vlen, reg_t &npc, reg_t addr, uint64_t offs,
- reg_t *target_reg)
+ reg_t *target_reg, bool zeroing, bool inv)
{
save_branch_addr = addr;
- if (not at_least_one_reg_vectorised)
+ if (not at_least_one_reg_vectorised) // scalar-scalar: make the branch
{
_set_pc(addr);
return;
if ((1<<offs) & prs1)
{
if (target_reg) {
- save_branch_rd = rd_bitset(*target_reg, offs, true);
+ save_branch_rd = rd_bitset(*target_reg, offs, !zeroing);
} else {
- save_branch_rd |= (1<<offs);
+ if (zeroing)
+ save_branch_rd &= ~(1UL<<offs);
+ else
+ save_branch_rd |= (1UL<<offs);
}
}
+ else if (inv) // target pred, meaning of inv bit is overloaded
+ {
+ vloop_continue = false;
+ }
fprintf(stderr, "setpc %lx offs %ld predicate %lx rs1 %ld rs2 %ld\n",
save_branch_rd, offs, prs1,
p->s.READ_REG(rs1()), p->s.READ_REG(rs2()));
use_offs ? offs_sp : NULL); }
void setpc(int xlen, int vlen, reg_t &npc, reg_t addr, uint64_t offs,
- reg_t *target_reg);
+ reg_t *target_reg, bool zeroing, bool inv);
// used for predicated branches. sets bit N if val=true; clears bit N if false
uint64_t rd_bitset(reg_t reg, int bit, bool val);