}
}
-reg_t processor_t::set_csr(int which, reg_t val, bool csrrwi)
+reg_t processor_t::set_csr(int which, reg_t val, bool imm_mode)
{
reg_t old_val = get_csr(which);
val = _zext_xlen(val);
int end = 0;
state.get_csr_start_end(start, end);
uint64_t res_old = 0;
+ int num_entries = val & 0xf;
+ int max_xlen_entries = (xlen == 64) ? 4 : 2;
+ if (!imm_mode) {
+ num_entries = max_xlen_entries;
+ }
// read 2 16-bit entries for RV32, 4 16-bit entries for RV64
- for (int i = 0; i < ((xlen == 64) ? 4 : 2); i++) {
- uint64_t mask = 0xffffUL << (i*16UL);
- uint64_t svcfg = get_field(v, mask);
- fprintf(stderr, "SVREG mask %lx cfg %lx\n", mask, svcfg);
- if (!svcfg && i > 0) {
- break;
+ int popidx = 0;
+ for (int i = 0; i < num_entries; i++) {
+ uint64_t svcfg = 0;
+ if (!imm_mode) {
+ uint64_t mask = 0xffffUL << (i*16UL);
+ svcfg = get_field(v, mask);
+ fprintf(stderr, "SVREG mask %lx cfg %lx\n", mask, svcfg);
+ if (!svcfg && i > 0) {
+ break;
+ }
}
// see regpush on how this works.
uint64_t res = state.sv().regpush(svcfg, end, top);
- res_old |= res << (i * 16UL);
+ if (res != 0) {
+ res_old |= res << (popidx * 16UL);
+ popidx += 1;
+ if (popidx == max_xlen_entries) {
+ break;
+ }
+ }
}
+ old_val = res_old;
state.sv_csr_reg_unpack();
break;
}