Browse Source

Merge pull request #1122 from riscv-software-src/more-mmu-simplification

Fix minor MMU bugs; clean up MMU some more
pull/1132/head
Andrew Waterman 3 years ago
committed by GitHub
parent
commit
5a50590f25
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      customext/dummy_rocc.cc
  2. 16
      riscv/debug_module.cc
  3. 2
      riscv/insns/amoadd_d.h
  4. 2
      riscv/insns/amoadd_w.h
  5. 2
      riscv/insns/amoand_d.h
  6. 2
      riscv/insns/amoand_w.h
  7. 2
      riscv/insns/amomax_d.h
  8. 2
      riscv/insns/amomax_w.h
  9. 2
      riscv/insns/amomaxu_d.h
  10. 2
      riscv/insns/amomaxu_w.h
  11. 2
      riscv/insns/amomin_d.h
  12. 2
      riscv/insns/amomin_w.h
  13. 2
      riscv/insns/amominu_d.h
  14. 2
      riscv/insns/amominu_w.h
  15. 2
      riscv/insns/amoor_d.h
  16. 2
      riscv/insns/amoor_w.h
  17. 2
      riscv/insns/amoswap_d.h
  18. 2
      riscv/insns/amoswap_w.h
  19. 2
      riscv/insns/amoxor_d.h
  20. 2
      riscv/insns/amoxor_w.h
  21. 2
      riscv/insns/c_fld.h
  22. 2
      riscv/insns/c_fldsp.h
  23. 4
      riscv/insns/c_flw.h
  24. 4
      riscv/insns/c_flwsp.h
  25. 2
      riscv/insns/c_fsd.h
  26. 2
      riscv/insns/c_fsdsp.h
  27. 4
      riscv/insns/c_fsw.h
  28. 4
      riscv/insns/c_fswsp.h
  29. 2
      riscv/insns/c_lw.h
  30. 2
      riscv/insns/c_lwsp.h
  31. 2
      riscv/insns/c_sw.h
  32. 2
      riscv/insns/c_swsp.h
  33. 2
      riscv/insns/fld.h
  34. 2
      riscv/insns/flh.h
  35. 2
      riscv/insns/flw.h
  36. 2
      riscv/insns/fsd.h
  37. 2
      riscv/insns/fsh.h
  38. 2
      riscv/insns/fsw.h
  39. 2
      riscv/insns/hlv_b.h
  40. 2
      riscv/insns/hlv_bu.h
  41. 2
      riscv/insns/hlv_d.h
  42. 2
      riscv/insns/hlv_h.h
  43. 2
      riscv/insns/hlv_hu.h
  44. 2
      riscv/insns/hlv_w.h
  45. 2
      riscv/insns/hlv_wu.h
  46. 2
      riscv/insns/hlvx_hu.h
  47. 2
      riscv/insns/hlvx_wu.h
  48. 2
      riscv/insns/hsv_b.h
  49. 2
      riscv/insns/hsv_d.h
  50. 2
      riscv/insns/hsv_h.h
  51. 2
      riscv/insns/hsv_w.h
  52. 2
      riscv/insns/lb.h
  53. 2
      riscv/insns/lbu.h
  54. 2
      riscv/insns/ld.h
  55. 2
      riscv/insns/lh.h
  56. 2
      riscv/insns/lhu.h
  57. 4
      riscv/insns/lr_d.h
  58. 4
      riscv/insns/lr_w.h
  59. 2
      riscv/insns/lw.h
  60. 2
      riscv/insns/lwu.h
  61. 2
      riscv/insns/sb.h
  62. 7
      riscv/insns/sc_d.h
  63. 7
      riscv/insns/sc_w.h
  64. 2
      riscv/insns/sd.h
  65. 2
      riscv/insns/sh.h
  66. 2
      riscv/insns/sw.h
  67. 10
      riscv/interactive.cc
  68. 10
      riscv/mmu.cc
  69. 183
      riscv/mmu.h
  70. 4
      riscv/sim.cc
  71. 34
      riscv/v_ext_macros.h

2
customext/dummy_rocc.cc

@ -22,7 +22,7 @@ class dummy_rocc_t : public rocc_t
case 1: // xd <- acc (the only real work is the return statement below)
break;
case 2: // acc[rs2] <- Mem[xs1]
acc[insn.rs2] = p->get_mmu()->load_uint64(xs1);
acc[insn.rs2] = p->get_mmu()->load<uint64_t>(xs1);
break;
case 3: // acc[rs2] <- accX + xs1
acc[insn.rs2] += xs1;

16
riscv/debug_module.cc

@ -318,13 +318,13 @@ void debug_module_t::sb_read()
reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
try {
if (sbcs.sbaccess == 0 && config.max_sba_data_width >= 8) {
sbdata[0] = sim->debug_mmu->load_uint8(address);
sbdata[0] = sim->debug_mmu->load<uint8_t>(address);
} else if (sbcs.sbaccess == 1 && config.max_sba_data_width >= 16) {
sbdata[0] = sim->debug_mmu->load_uint16(address);
sbdata[0] = sim->debug_mmu->load<uint16_t>(address);
} else if (sbcs.sbaccess == 2 && config.max_sba_data_width >= 32) {
sbdata[0] = sim->debug_mmu->load_uint32(address);
sbdata[0] = sim->debug_mmu->load<uint32_t>(address);
} else if (sbcs.sbaccess == 3 && config.max_sba_data_width >= 64) {
uint64_t value = sim->debug_mmu->load_uint64(address);
uint64_t value = sim->debug_mmu->load<uint64_t>(address);
sbdata[0] = value;
sbdata[1] = value >> 32;
} else {
@ -340,13 +340,13 @@ void debug_module_t::sb_write()
reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
D(fprintf(stderr, "sb_write() 0x%x @ 0x%lx\n", sbdata[0], address));
if (sbcs.sbaccess == 0 && config.max_sba_data_width >= 8) {
sim->debug_mmu->store_uint8(address, sbdata[0]);
sim->debug_mmu->store<uint8_t>(address, sbdata[0]);
} else if (sbcs.sbaccess == 1 && config.max_sba_data_width >= 16) {
sim->debug_mmu->store_uint16(address, sbdata[0]);
sim->debug_mmu->store<uint16_t>(address, sbdata[0]);
} else if (sbcs.sbaccess == 2 && config.max_sba_data_width >= 32) {
sim->debug_mmu->store_uint32(address, sbdata[0]);
sim->debug_mmu->store<uint32_t>(address, sbdata[0]);
} else if (sbcs.sbaccess == 3 && config.max_sba_data_width >= 64) {
sim->debug_mmu->store_uint64(address,
sim->debug_mmu->store<uint64_t>(address,
(((uint64_t) sbdata[1]) << 32) | sbdata[0]);
} else {
sbcs.error = 3;

2
riscv/insns/amoadd_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs + RS2; }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs + RS2; }));

2
riscv/insns/amoadd_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs + RS2; })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs + RS2; })));

2
riscv/insns/amoand_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs & RS2; }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs & RS2; }));

2
riscv/insns/amoand_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs & RS2; })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs & RS2; })));

2
riscv/insns/amomax_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](int64_t lhs) { return std::max(lhs, int64_t(RS2)); }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](int64_t lhs) { return std::max(lhs, int64_t(RS2)); }));

2
riscv/insns/amomax_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](int32_t lhs) { return std::max(lhs, int32_t(RS2)); })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](int32_t lhs) { return std::max(lhs, int32_t(RS2)); })));

2
riscv/insns/amomaxu_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return std::max(lhs, RS2); }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return std::max(lhs, RS2); }));

2
riscv/insns/amomaxu_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return std::max(lhs, uint32_t(RS2)); })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return std::max(lhs, uint32_t(RS2)); })));

2
riscv/insns/amomin_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](int64_t lhs) { return std::min(lhs, int64_t(RS2)); }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](int64_t lhs) { return std::min(lhs, int64_t(RS2)); }));

2
riscv/insns/amomin_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](int32_t lhs) { return std::min(lhs, int32_t(RS2)); })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](int32_t lhs) { return std::min(lhs, int32_t(RS2)); })));

2
riscv/insns/amominu_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return std::min(lhs, RS2); }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return std::min(lhs, RS2); }));

2
riscv/insns/amominu_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return std::min(lhs, uint32_t(RS2)); })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return std::min(lhs, uint32_t(RS2)); })));

2
riscv/insns/amoor_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs | RS2; }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs | RS2; }));

2
riscv/insns/amoor_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs | RS2; })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs | RS2; })));

2
riscv/insns/amoswap_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t UNUSED lhs) { return RS2; }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t UNUSED lhs) { return RS2; }));

2
riscv/insns/amoswap_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t UNUSED lhs) { return RS2; })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t UNUSED lhs) { return RS2; })));

2
riscv/insns/amoxor_d.h

@ -1,3 +1,3 @@
require_extension('A');
require_rv64;
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs ^ RS2; }));
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs ^ RS2; }));

2
riscv/insns/amoxor_w.h

@ -1,2 +1,2 @@
require_extension('A');
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs ^ RS2; })));
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs ^ RS2; })));

2
riscv/insns/c_fld.h

@ -1,4 +1,4 @@
require_extension('C');
require_extension('D');
require_fp;
WRITE_RVC_FRS2S(f64(MMU.load_uint64(RVC_RS1S + insn.rvc_ld_imm())));
WRITE_RVC_FRS2S(f64(MMU.load<uint64_t>(RVC_RS1S + insn.rvc_ld_imm())));

2
riscv/insns/c_fldsp.h

@ -1,4 +1,4 @@
require_extension('C');
require_extension('D');
require_fp;
WRITE_FRD(f64(MMU.load_uint64(RVC_SP + insn.rvc_ldsp_imm())));
WRITE_FRD(f64(MMU.load<uint64_t>(RVC_SP + insn.rvc_ldsp_imm())));

4
riscv/insns/c_flw.h

@ -2,7 +2,7 @@ require_extension('C');
if (xlen == 32) {
require_extension('F');
require_fp;
WRITE_RVC_FRS2S(f32(MMU.load_uint32(RVC_RS1S + insn.rvc_lw_imm())));
WRITE_RVC_FRS2S(f32(MMU.load<uint32_t>(RVC_RS1S + insn.rvc_lw_imm())));
} else { // c.ld
WRITE_RVC_RS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
WRITE_RVC_RS2S(MMU.load<int64_t>(RVC_RS1S + insn.rvc_ld_imm()));
}

4
riscv/insns/c_flwsp.h

@ -2,8 +2,8 @@ require_extension('C');
if (xlen == 32) {
require_extension('F');
require_fp;
WRITE_FRD(f32(MMU.load_uint32(RVC_SP + insn.rvc_lwsp_imm())));
WRITE_FRD(f32(MMU.load<uint32_t>(RVC_SP + insn.rvc_lwsp_imm())));
} else { // c.ldsp
require(insn.rvc_rd() != 0);
WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
WRITE_RD(MMU.load<int64_t>(RVC_SP + insn.rvc_ldsp_imm()));
}

2
riscv/insns/c_fsd.h

@ -1,4 +1,4 @@
require_extension('C');
require_extension('D');
require_fp;
MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v[0]);
MMU.store<uint64_t>(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v[0]);

2
riscv/insns/c_fsdsp.h

@ -1,4 +1,4 @@
require_extension('C');
require_extension('D');
require_fp;
MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v[0]);
MMU.store<uint64_t>(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v[0]);

4
riscv/insns/c_fsw.h

@ -2,7 +2,7 @@ require_extension('C');
if (xlen == 32) {
require_extension('F');
require_fp;
MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v[0]);
MMU.store<uint32_t>(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v[0]);
} else { // c.sd
MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
MMU.store<uint64_t>(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
}

4
riscv/insns/c_fswsp.h

@ -2,7 +2,7 @@ require_extension('C');
if (xlen == 32) {
require_extension('F');
require_fp;
MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v[0]);
MMU.store<uint32_t>(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v[0]);
} else { // c.sdsp
MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2);
MMU.store<uint64_t>(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2);
}

2
riscv/insns/c_lw.h

@ -1,2 +1,2 @@
require_extension('C');
WRITE_RVC_RS2S(MMU.load_int32(RVC_RS1S + insn.rvc_lw_imm()));
WRITE_RVC_RS2S(MMU.load<int32_t>(RVC_RS1S + insn.rvc_lw_imm()));

2
riscv/insns/c_lwsp.h

@ -1,3 +1,3 @@
require_extension('C');
require(insn.rvc_rd() != 0);
WRITE_RD(MMU.load_int32(RVC_SP + insn.rvc_lwsp_imm()));
WRITE_RD(MMU.load<int32_t>(RVC_SP + insn.rvc_lwsp_imm()));

2
riscv/insns/c_sw.h

@ -1,2 +1,2 @@
require_extension('C');
MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_RS2S);
MMU.store<uint32_t>(RVC_RS1S + insn.rvc_lw_imm(), RVC_RS2S);

2
riscv/insns/c_swsp.h

@ -1,2 +1,2 @@
require_extension('C');
MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_RS2);
MMU.store<uint32_t>(RVC_SP + insn.rvc_swsp_imm(), RVC_RS2);

2
riscv/insns/fld.h

@ -1,3 +1,3 @@
require_extension('D');
require_fp;
WRITE_FRD(f64(MMU.load_uint64(RS1 + insn.i_imm())));
WRITE_FRD(f64(MMU.load<uint64_t>(RS1 + insn.i_imm())));

2
riscv/insns/flh.h

@ -1,3 +1,3 @@
require_extension(EXT_ZFHMIN);
require_fp;
WRITE_FRD(f16(MMU.load_uint16(RS1 + insn.i_imm())));
WRITE_FRD(f16(MMU.load<uint16_t>(RS1 + insn.i_imm())));

2
riscv/insns/flw.h

@ -1,3 +1,3 @@
require_extension('F');
require_fp;
WRITE_FRD(f32(MMU.load_uint32(RS1 + insn.i_imm())));
WRITE_FRD(f32(MMU.load<uint32_t>(RS1 + insn.i_imm())));

2
riscv/insns/fsd.h

@ -1,3 +1,3 @@
require_extension('D');
require_fp;
MMU.store_uint64(RS1 + insn.s_imm(), FRS2.v[0]);
MMU.store<uint64_t>(RS1 + insn.s_imm(), FRS2.v[0]);

2
riscv/insns/fsh.h

@ -1,3 +1,3 @@
require_extension(EXT_ZFHMIN);
require_fp;
MMU.store_uint16(RS1 + insn.s_imm(), FRS2.v[0]);
MMU.store<uint16_t>(RS1 + insn.s_imm(), FRS2.v[0]);

2
riscv/insns/fsw.h

@ -1,3 +1,3 @@
require_extension('F');
require_fp;
MMU.store_uint32(RS1 + insn.s_imm(), FRS2.v[0]);
MMU.store<uint32_t>(RS1 + insn.s_imm(), FRS2.v[0]);

2
riscv/insns/hlv_b.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int8(RS1));
WRITE_RD(MMU.guest_load<int8_t>(RS1));

2
riscv/insns/hlv_bu.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_uint8(RS1));
WRITE_RD(MMU.guest_load<uint8_t>(RS1));

2
riscv/insns/hlv_d.h

@ -2,4 +2,4 @@ require_extension('H');
require_rv64;
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int64(RS1));
WRITE_RD(MMU.guest_load<int64_t>(RS1));

2
riscv/insns/hlv_h.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int16(RS1));
WRITE_RD(MMU.guest_load<int16_t>(RS1));

2
riscv/insns/hlv_hu.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_uint16(RS1));
WRITE_RD(MMU.guest_load<uint16_t>(RS1));

2
riscv/insns/hlv_w.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_int32(RS1));
WRITE_RD(MMU.guest_load<int32_t>(RS1));

2
riscv/insns/hlv_wu.h

@ -2,4 +2,4 @@ require_extension('H');
require_rv64;
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_uint32(RS1));
WRITE_RD(MMU.guest_load<uint32_t>(RS1));

2
riscv/insns/hlvx_hu.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(MMU.guest_load_x_uint16(RS1));
WRITE_RD(MMU.guest_load_x<uint16_t>(RS1));

2
riscv/insns/hlvx_wu.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
WRITE_RD(sext_xlen(MMU.guest_load_x_uint32(RS1)));
WRITE_RD(sext_xlen(MMU.guest_load_x<uint32_t>(RS1)));

2
riscv/insns/hsv_b.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint8(RS1, RS2);
MMU.guest_store<uint8_t>(RS1, RS2);

2
riscv/insns/hsv_d.h

@ -2,4 +2,4 @@ require_extension('H');
require_rv64;
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint64(RS1, RS2);
MMU.guest_store<uint64_t>(RS1, RS2);

2
riscv/insns/hsv_h.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint16(RS1, RS2);
MMU.guest_store<uint16_t>(RS1, RS2);

2
riscv/insns/hsv_w.h

@ -1,4 +1,4 @@
require_extension('H');
require_novirt();
require_privilege(get_field(STATE.hstatus->read(), HSTATUS_HU) ? PRV_U : PRV_S);
MMU.guest_store_uint32(RS1, RS2);
MMU.guest_store<uint32_t>(RS1, RS2);

2
riscv/insns/lb.h

@ -1 +1 @@
WRITE_RD(MMU.load_int8(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<int8_t>(RS1 + insn.i_imm()));

2
riscv/insns/lbu.h

@ -1 +1 @@
WRITE_RD(MMU.load_uint8(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<uint8_t>(RS1 + insn.i_imm()));

2
riscv/insns/ld.h

@ -1,2 +1,2 @@
require_rv64;
WRITE_RD(MMU.load_int64(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<int64_t>(RS1 + insn.i_imm()));

2
riscv/insns/lh.h

@ -1 +1 @@
WRITE_RD(MMU.load_int16(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<int16_t>(RS1 + insn.i_imm()));

2
riscv/insns/lhu.h

@ -1 +1 @@
WRITE_RD(MMU.load_uint16(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<uint16_t>(RS1 + insn.i_imm()));

4
riscv/insns/lr_d.h

@ -1,5 +1,3 @@
require_extension('A');
require_rv64;
auto res = MMU.load_int64(RS1, true);
MMU.acquire_load_reservation(RS1);
WRITE_RD(res);
WRITE_RD(MMU.load_reserved<int64_t>(RS1));

4
riscv/insns/lr_w.h

@ -1,4 +1,2 @@
require_extension('A');
auto res = MMU.load_int32(RS1, true);
MMU.acquire_load_reservation(RS1);
WRITE_RD(res);
WRITE_RD(MMU.load_reserved<int32_t>(RS1));

2
riscv/insns/lw.h

@ -1 +1 @@
WRITE_RD(MMU.load_int32(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<int32_t>(RS1 + insn.i_imm()));

2
riscv/insns/lwu.h

@ -1,2 +1,2 @@
require_rv64;
WRITE_RD(MMU.load_uint32(RS1 + insn.i_imm()));
WRITE_RD(MMU.load<uint32_t>(RS1 + insn.i_imm()));

2
riscv/insns/sb.h

@ -1 +1 @@
MMU.store_uint8(RS1 + insn.s_imm(), RS2);
MMU.store<uint8_t>(RS1 + insn.s_imm(), RS2);

7
riscv/insns/sc_d.h

@ -1,11 +1,6 @@
require_extension('A');
require_rv64;
bool have_reservation = MMU.check_load_reservation(RS1, 8);
if (have_reservation)
MMU.store_uint64(RS1, RS2);
MMU.yield_load_reservation();
bool have_reservation = MMU.store_conditional<uint64_t>(RS1, RS2);
WRITE_RD(!have_reservation);

7
riscv/insns/sc_w.h

@ -1,10 +1,5 @@
require_extension('A');
bool have_reservation = MMU.check_load_reservation(RS1, 4);
if (have_reservation)
MMU.store_uint32(RS1, RS2);
MMU.yield_load_reservation();
bool have_reservation = MMU.store_conditional<uint32_t>(RS1, RS2);
WRITE_RD(!have_reservation);

2
riscv/insns/sd.h

@ -1,2 +1,2 @@
require_rv64;
MMU.store_uint64(RS1 + insn.s_imm(), RS2);
MMU.store<uint64_t>(RS1 + insn.s_imm(), RS2);

2
riscv/insns/sh.h

@ -1 +1 @@
MMU.store_uint16(RS1 + insn.s_imm(), RS2);
MMU.store<uint16_t>(RS1 + insn.s_imm(), RS2);

2
riscv/insns/sw.h

@ -1 +1 @@
MMU.store_uint32(RS1 + insn.s_imm(), RS2);
MMU.store<uint32_t>(RS1 + insn.s_imm(), RS2);

10
riscv/interactive.cc

@ -678,17 +678,17 @@ reg_t sim_t::get_mem(const std::vector<std::string>& args)
switch (addr % 8)
{
case 0:
val = mmu->load_uint64(addr);
val = mmu->load<uint64_t>(addr);
break;
case 4:
val = mmu->load_uint32(addr);
val = mmu->load<uint32_t>(addr);
break;
case 2:
case 6:
val = mmu->load_uint16(addr);
val = mmu->load<uint16_t>(addr);
break;
default:
val = mmu->load_uint8(addr);
val = mmu->load<uint8_t>(addr);
break;
}
return val;
@ -722,7 +722,7 @@ void sim_t::interactive_str(const std::string& cmd, const std::vector<std::strin
std::ostream out(sout_.rdbuf());
char ch;
while ((ch = mmu->load_uint8(addr++)))
while ((ch = mmu->load<uint8_t>(addr++)))
out << ch;
out << std::endl;

10
riscv/mmu.cc

@ -190,12 +190,16 @@ void mmu_t::load_slow_path_intrapage(reg_t addr, reg_t len, uint8_t* bytes, uint
tracer.trace(paddr, len, LOAD);
else if (xlate_flags == 0)
refill_tlb(addr, paddr, host_addr, LOAD);
} else if (!mmio_load(paddr, len, bytes)) {
if (xlate_flags & RISCV_XLATE_LR) {
load_reservation_address = paddr;
}
} else if ((xlate_flags & RISCV_XLATE_LR) || !mmio_load(paddr, len, bytes)) {
throw trap_load_access_fault((proc) ? proc->state.v : false, addr, 0, 0);
}
}
void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags, bool UNUSED require_alignment)
void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags)
{
check_triggers(triggers::OPERATION_LOAD, addr);
@ -206,7 +210,7 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate
#ifndef RISCV_ENABLE_MISALIGNED
throw trap_load_address_misaligned(gva, addr, 0, 0);
#else
if (require_alignment)
if (xlate_flags & RISCV_XLATE_LR)
throw trap_load_access_fault(gva, addr, 0, 0);
reg_t len_page0 = std::min(len, PGSIZE - addr % PGSIZE);

183
riscv/mmu.h

@ -49,8 +49,9 @@ public:
mmu_t(simif_t* sim, processor_t* proc);
~mmu_t();
#define RISCV_XLATE_VIRT (1U << 0)
#define RISCV_XLATE_VIRT (1U << 0)
#define RISCV_XLATE_VIRT_HLVX (1U << 1)
#define RISCV_XLATE_LR (1U << 2)
#ifndef RISCV_ENABLE_COMMITLOG
# define READ_MEM(addr, size) ((void)(addr), (void)(size))
@ -59,49 +60,39 @@ public:
proc->state.log_mem_read.push_back(std::make_tuple(addr, 0, size));
#endif
// template for functions that load an aligned value from memory
#define load_func(type, prefix, xlate_flags) \
type##_t ALWAYS_INLINE prefix##_##type(reg_t addr, bool require_alignment = false) { \
reg_t vpn = addr >> PGSHIFT; \
size_t size = sizeof(type##_t); \
bool aligned = (addr & (size - 1)) == 0; \
bool tlb_hit = tlb_load_tag[vpn % TLB_ENTRIES] == vpn; \
if (likely((xlate_flags) == 0 && aligned && tlb_hit)) { \
if (proc) READ_MEM(addr, size); \
return from_target(*(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr)); \
} else { \
target_endian<type##_t> res; \
load_slow_path(addr, sizeof(type##_t), (uint8_t*)&res, (xlate_flags), require_alignment); \
if (proc) READ_MEM(addr, size); \
return from_target(res); \
} \
template<typename T>
T ALWAYS_INLINE load(reg_t addr, uint32_t xlate_flags = 0) {
target_endian<T> res;
reg_t vpn = addr >> PGSHIFT;
bool aligned = (addr & (sizeof(T) - 1)) == 0;
bool tlb_hit = tlb_load_tag[vpn % TLB_ENTRIES] == vpn;
if (likely(xlate_flags == 0 && aligned && tlb_hit)) {
res = *(target_endian<T>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr);
} else {
load_slow_path(addr, sizeof(T), (uint8_t*)&res, xlate_flags);
}
// load value from memory at aligned address; zero extend to register width
load_func(uint8, load, 0)
load_func(uint16, load, 0)
load_func(uint32, load, 0)
load_func(uint64, load, 0)
// load value from guest memory at aligned address; zero extend to register width
load_func(uint8, guest_load, RISCV_XLATE_VIRT)
load_func(uint16, guest_load, RISCV_XLATE_VIRT)
load_func(uint32, guest_load, RISCV_XLATE_VIRT)
load_func(uint64, guest_load, RISCV_XLATE_VIRT)
load_func(uint16, guest_load_x, RISCV_XLATE_VIRT|RISCV_XLATE_VIRT_HLVX)
load_func(uint32, guest_load_x, RISCV_XLATE_VIRT|RISCV_XLATE_VIRT_HLVX)
// load value from memory at aligned address; sign extend to register width
load_func(int8, load, 0)
load_func(int16, load, 0)
load_func(int32, load, 0)
load_func(int64, load, 0)
// load value from guest memory at aligned address; sign extend to register width
load_func(int8, guest_load, RISCV_XLATE_VIRT)
load_func(int16, guest_load, RISCV_XLATE_VIRT)
load_func(int32, guest_load, RISCV_XLATE_VIRT)
load_func(int64, guest_load, RISCV_XLATE_VIRT)
if (proc)
READ_MEM(addr, sizeof(T));
return from_target(res);
}
template<typename T>
T load_reserved(reg_t addr) {
return load<T>(addr, RISCV_XLATE_LR);
}
template<typename T>
T guest_load(reg_t addr) {
return load<T>(addr, RISCV_XLATE_VIRT);
}
template<typename T>
T guest_load_x(reg_t addr) {
return load<T>(addr, RISCV_XLATE_VIRT|RISCV_XLATE_VIRT_HLVX);
}
#ifndef RISCV_ENABLE_COMMITLOG
# define WRITE_MEM(addr, value, size) ((void)(addr), (void)(value), (void)(size))
@ -110,23 +101,26 @@ public:
proc->state.log_mem_write.push_back(std::make_tuple(addr, val, size));
#endif
// template for functions that store an aligned value to memory
#define store_func(type, prefix, xlate_flags) \
void ALWAYS_INLINE prefix##_##type(reg_t addr, type##_t val, bool actually_store=true, bool require_alignment=false) { \
reg_t vpn = addr >> PGSHIFT; \
size_t size = sizeof(type##_t); \
bool aligned = (addr & (size - 1)) == 0; \
bool tlb_hit = tlb_store_tag[vpn % TLB_ENTRIES] == vpn; \
if ((xlate_flags) == 0 && likely(aligned && tlb_hit)) { \
if (actually_store) { \
if (proc) WRITE_MEM(addr, val, size); \
*(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); \
} \
} else { \
target_endian<type##_t> target_val = to_target(val); \
store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&target_val, (xlate_flags), actually_store, require_alignment); \
if (actually_store && proc) WRITE_MEM(addr, val, size); \
} \
template<typename T>
void ALWAYS_INLINE store(reg_t addr, T val, uint32_t xlate_flags = 0) {
reg_t vpn = addr >> PGSHIFT;
bool aligned = (addr & (sizeof(T) - 1)) == 0;
bool tlb_hit = tlb_store_tag[vpn % TLB_ENTRIES] == vpn;
if (xlate_flags == 0 && likely(aligned && tlb_hit)) {
*(target_endian<T>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val);
} else {
target_endian<T> target_val = to_target(val);
store_slow_path(addr, sizeof(T), (const uint8_t*)&target_val, xlate_flags, true, false);
}
if (proc)
WRITE_MEM(addr, val, sizeof(T));
}
template<typename T>
void guest_store(reg_t addr, T val) {
store(addr, val, RISCV_XLATE_VIRT);
}
// AMO/Zicbom faults should be reported as store faults
@ -145,16 +139,15 @@ public:
}
// template for functions that perform an atomic memory operation
#define amo_func(type) \
template<typename op> \
type##_t amo_##type(reg_t addr, op f) { \
convert_load_traps_to_store_traps({ \
store_##type(addr, 0, false, true); \
auto lhs = load_##type(addr, true); \
store_##type(addr, f(lhs)); \
return lhs; \
}) \
}
template<typename T, typename op>
T amo(reg_t addr, op f) {
convert_load_traps_to_store_traps({
store_slow_path(addr, sizeof(T), nullptr, 0, false, true);
auto lhs = load<T>(addr);
store<T>(addr, f(lhs));
return lhs;
})
}
void store_float128(reg_t addr, float128_t val)
{
@ -162,8 +155,8 @@ public:
if (unlikely(addr & (sizeof(float128_t)-1)))
throw trap_store_address_misaligned((proc) ? proc->state.v : false, addr, 0, 0);
#endif
store_uint64(addr, val.v[0]);
store_uint64(addr + 8, val.v[1]);
store<uint64_t>(addr, val.v[0]);
store<uint64_t>(addr + 8, val.v[1]);
}
float128_t load_float128(reg_t addr)
@ -172,29 +165,13 @@ public:
if (unlikely(addr & (sizeof(float128_t)-1)))
throw trap_load_address_misaligned((proc) ? proc->state.v : false, addr, 0, 0);
#endif
return (float128_t){load_uint64(addr), load_uint64(addr + 8)};
return (float128_t){load<uint64_t>(addr), load<uint64_t>(addr + 8)};
}
// store value to memory at aligned address
store_func(uint8, store, 0)
store_func(uint16, store, 0)
store_func(uint32, store, 0)
store_func(uint64, store, 0)
// store value to guest memory at aligned address
store_func(uint8, guest_store, RISCV_XLATE_VIRT)
store_func(uint16, guest_store, RISCV_XLATE_VIRT)
store_func(uint32, guest_store, RISCV_XLATE_VIRT)
store_func(uint64, guest_store, RISCV_XLATE_VIRT)
// perform an atomic memory operation at an aligned address
amo_func(uint32)
amo_func(uint64)
void cbo_zero(reg_t addr) {
auto base = addr & ~(blocksz - 1);
for (size_t offset = 0; offset < blocksz; offset += 1)
store_uint8(base + offset, 0);
store<uint8_t>(base + offset, 0);
}
void clean_inval(reg_t addr, bool clean, bool inval) {
@ -214,15 +191,6 @@ public:
load_reservation_address = (reg_t)-1;
}
inline void acquire_load_reservation(reg_t vaddr)
{
reg_t paddr = translate(vaddr, 1, LOAD, 0);
if (auto host_addr = sim->addr_to_mem(paddr))
load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr;
else
throw trap_load_access_fault((proc) ? proc->state.v : false, vaddr, 0, 0); // disallow LR to I/O space
}
inline bool check_load_reservation(reg_t vaddr, size_t size)
{
if (vaddr & (size-1)) {
@ -231,12 +199,25 @@ public:
}
reg_t paddr = translate(vaddr, 1, STORE, 0);
if (auto host_addr = sim->addr_to_mem(paddr))
return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr;
if (sim->addr_to_mem(paddr))
return load_reservation_address == paddr;
else
throw trap_store_access_fault((proc) ? proc->state.v : false, vaddr, 0, 0); // disallow SC to I/O space
}
template<typename T>
bool store_conditional(reg_t addr, T val)
{
bool have_reservation = check_load_reservation(addr, sizeof(T));
if (have_reservation)
store(addr, val);
yield_load_reservation();
return have_reservation;
}
static const reg_t ICACHE_ENTRIES = 1024;
inline size_t icache_index(reg_t addr)
@ -379,7 +360,7 @@ private:
// handle uncommon cases: TLB misses, page faults, MMIO
tlb_entry_t fetch_slow_path(reg_t addr);
void load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags, bool require_alignment);
void load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags);
void load_slow_path_intrapage(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags);
void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags, bool actually_store, bool require_alignment);
void store_slow_path_intrapage(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags, bool actually_store);

4
riscv/sim.cc

@ -420,7 +420,7 @@ void sim_t::idle()
void sim_t::read_chunk(addr_t taddr, size_t len, void* dst)
{
assert(len == 8);
auto data = debug_mmu->to_target(debug_mmu->load_uint64(taddr));
auto data = debug_mmu->to_target(debug_mmu->load<uint64_t>(taddr));
memcpy(dst, &data, sizeof data);
}
@ -429,7 +429,7 @@ void sim_t::write_chunk(addr_t taddr, size_t len, const void* src)
assert(len == 8);
target_endian<uint64_t> data;
memcpy(&data, src, sizeof data);
debug_mmu->store_uint64(taddr, debug_mmu->from_target(data));
debug_mmu->store<uint64_t>(taddr, debug_mmu->from_target(data));
}
void sim_t::set_target_endianness(memif_endianness_t endianness)

34
riscv/v_ext_macros.h

@ -1183,7 +1183,7 @@ reg_t index[P.VU.vlmax]; \
VI_STRIP(i); \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
elt_width##_t val = MMU.load_##elt_width( \
elt_width##_t val = MMU.load<elt_width##_t>( \
baseAddr + (stride) + (offset) * sizeof(elt_width##_t)); \
P.VU.elt<elt_width##_t>(vd + fn * emul, vreg_inx, true) = val; \
} \
@ -1207,19 +1207,19 @@ reg_t index[P.VU.vlmax]; \
switch (P.VU.vsew) { \
case e8: \
P.VU.elt<uint8_t>(vd + fn * flmul, vreg_inx, true) = \
MMU.load_uint8(baseAddr + index[i] + fn * 1); \
MMU.load<uint8_t>(baseAddr + index[i] + fn * 1); \
break; \
case e16: \
P.VU.elt<uint16_t>(vd + fn * flmul, vreg_inx, true) = \
MMU.load_uint16(baseAddr + index[i] + fn * 2); \
MMU.load<uint16_t>(baseAddr + index[i] + fn * 2); \
break; \
case e32: \
P.VU.elt<uint32_t>(vd + fn * flmul, vreg_inx, true) = \
MMU.load_uint32(baseAddr + index[i] + fn * 4); \
MMU.load<uint32_t>(baseAddr + index[i] + fn * 4); \
break; \
default: \
P.VU.elt<uint64_t>(vd + fn * flmul, vreg_inx, true) = \
MMU.load_uint64(baseAddr + index[i] + fn * 8); \
MMU.load<uint64_t>(baseAddr + index[i] + fn * 8); \
break; \
} \
} \
@ -1238,7 +1238,7 @@ reg_t index[P.VU.vlmax]; \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
elt_width##_t val = P.VU.elt<elt_width##_t>(vs3 + fn * emul, vreg_inx); \
MMU.store_##elt_width( \
MMU.store<elt_width##_t>( \
baseAddr + (stride) + (offset) * sizeof(elt_width##_t), val); \
} \
} \
@ -1260,19 +1260,19 @@ reg_t index[P.VU.vlmax]; \
for (reg_t fn = 0; fn < nf; ++fn) { \
switch (P.VU.vsew) { \
case e8: \
MMU.store_uint8(baseAddr + index[i] + fn * 1, \
MMU.store<uint8_t>(baseAddr + index[i] + fn * 1, \
P.VU.elt<uint8_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
case e16: \
MMU.store_uint16(baseAddr + index[i] + fn * 2, \
MMU.store<uint16_t>(baseAddr + index[i] + fn * 2, \
P.VU.elt<uint16_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
case e32: \
MMU.store_uint32(baseAddr + index[i] + fn * 4, \
MMU.store<uint32_t>(baseAddr + index[i] + fn * 4, \
P.VU.elt<uint32_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
default: \
MMU.store_uint64(baseAddr + index[i] + fn * 8, \
MMU.store<uint64_t>(baseAddr + index[i] + fn * 8, \
P.VU.elt<uint64_t>(vs3 + fn * flmul, vreg_inx)); \
break; \
} \
@ -1294,7 +1294,7 @@ reg_t index[P.VU.vlmax]; \
for (reg_t fn = 0; fn < nf; ++fn) { \
uint64_t val; \
try { \
val = MMU.load_##elt_width( \
val = MMU.load<elt_width##_t>( \
baseAddr + (i * nf + fn) * sizeof(elt_width##_t)); \
} catch (trap_t& t) { \
if (i == 0) \
@ -1327,7 +1327,7 @@ reg_t index[P.VU.vlmax]; \
reg_t off = P.VU.vstart->read() % elt_per_reg; \
if (off) { \
for (reg_t pos = off; pos < elt_per_reg; ++pos) { \
auto val = MMU.load_## elt_width(baseAddr + \
auto val = MMU.load<elt_width##_t>(baseAddr + \
P.VU.vstart->read() * sizeof(elt_width ## _t)); \
P.VU.elt<elt_width ## _t>(vd + i, pos, true) = val; \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
@ -1336,7 +1336,7 @@ reg_t index[P.VU.vlmax]; \
} \
for (; i < len; ++i) { \
for (reg_t pos = 0; pos < elt_per_reg; ++pos) { \
auto val = MMU.load_## elt_width(baseAddr + \
auto val = MMU.load<elt_width##_t>(baseAddr + \
P.VU.vstart->read() * sizeof(elt_width ## _t)); \
P.VU.elt<elt_width ## _t>(vd + i, pos, true) = val; \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
@ -1359,7 +1359,7 @@ reg_t index[P.VU.vlmax]; \
if (off) { \
for (reg_t pos = off; pos < P.VU.vlenb; ++pos) { \
auto val = P.VU.elt<uint8_t>(vs3 + i, pos); \
MMU.store_uint8(baseAddr + P.VU.vstart->read(), val); \
MMU.store<uint8_t>(baseAddr + P.VU.vstart->read(), val); \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
} \
i++; \
@ -1367,7 +1367,7 @@ reg_t index[P.VU.vlmax]; \
for (; i < len; ++i) { \
for (reg_t pos = 0; pos < P.VU.vlenb; ++pos) { \
auto val = P.VU.elt<uint8_t>(vs3 + i, pos); \
MMU.store_uint8(baseAddr + P.VU.vstart->read(), val); \
MMU.store<uint8_t>(baseAddr + P.VU.vstart->read(), val); \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
} \
} \
@ -1409,14 +1409,14 @@ reg_t index[P.VU.vlmax]; \
switch (P.VU.vsew) { \
case e32: { \
auto vs3 = P.VU.elt< type ## 32_t>(vd, vreg_inx); \
auto val = MMU.amo_uint32(baseAddr + index[i], [&](type ## 32_t UNUSED lhs) { op }); \
auto val = MMU.amo<uint32_t>(baseAddr + index[i], [&](type ## 32_t UNUSED lhs) { op }); \
if (insn.v_wd()) \
P.VU.elt< type ## 32_t>(vd, vreg_inx, true) = val; \
} \
break; \
case e64: { \
auto vs3 = P.VU.elt< type ## 64_t>(vd, vreg_inx); \
auto val = MMU.amo_uint64(baseAddr + index[i], [&](type ## 64_t UNUSED lhs) { op }); \
auto val = MMU.amo<uint64_t>(baseAddr + index[i], [&](type ## 64_t UNUSED lhs) { op }); \
if (insn.v_wd()) \
P.VU.elt< type ## 64_t>(vd, vreg_inx, true) = val; \
} \

Loading…
Cancel
Save