From: Luke Kenneth Casson Leighton Date: Tue, 13 Nov 2018 23:17:24 +0000 (+0000) Subject: change SV_REGCSR csrrwi to different meaning: 5-bit is num CSR entries to pop X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cae90f513a497d8c92fa9c9ad6a2ba122d913778;p=riscv-isa-sim.git change SV_REGCSR csrrwi to different meaning: 5-bit is num CSR entries to pop however, it has to be limited to what will fit into the return result. so stops at 4 non-zero entries on RV64 and 2 on RV32. perhaps use notification of use of x0 to remove all items requested? can do a complate stack-wipe with one csrrwi instruction, then --- diff --git a/riscv/processor.cc b/riscv/processor.cc index b3ea542..773fab8 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -485,7 +485,7 @@ void state_t::sv_csr_pred_unpack() } } -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); @@ -548,18 +548,34 @@ reg_t processor_t::set_csr(int which, reg_t val, bool csrrwi) 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; }