change SV_REGCSR csrrwi to different meaning: 5-bit is num CSR entries to pop
[riscv-isa-sim.git] / riscv / processor.cc
index b3ea542dbf17cf82fc7f22df39675dad3715dbb7..773fab85c0d5efde829469657cb998b46c4c143a 100644 (file)
@@ -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;
     }