aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianluca Guida <gianluca@rivosinc.com>2023-05-25 13:27:45 +0100
committerGianluca Guida <gianluca@rivosinc.com>2023-06-19 19:16:15 +0100
commit4ac7e03dfb7a45d2732fadfe29e1af30ef25bcac (patch)
tree01d2db9dbe050ec9c0a077d511784a6f95310bfe
parent07e7626e5692ae6bb5773ddb5493ba838debca86 (diff)
downloadriscv-isa-sim-4ac7e03dfb7a45d2732fadfe29e1af30ef25bcac.zip
riscv-isa-sim-4ac7e03dfb7a45d2732fadfe29e1af30ef25bcac.tar.gz
riscv-isa-sim-4ac7e03dfb7a45d2732fadfe29e1af30ef25bcac.tar.bz2
mmu: support load/store longer than 64-bits.
-rw-r--r--riscv/mmu.cc17
1 files changed, 15 insertions, 2 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 358ccd3..3f90060 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -242,6 +242,11 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t
load_slow_path_intrapage(len - len_page0, bytes + len_page0, access_info.split_misaligned_access(len_page0));
}
+ while (len > sizeof(reg_t)) {
+ check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), bytes));
+ len -= sizeof(reg_t);
+ bytes += sizeof(reg_t);
+ }
check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(len, bytes));
}
@@ -275,8 +280,16 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces
void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment)
{
auto access_info = generate_access_info(addr, STORE, xlate_flags);
- if (actually_store)
- check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(len, bytes));
+ if (actually_store) {
+ reg_t trig_len = len;
+ const uint8_t* trig_bytes = bytes;
+ while (trig_len > sizeof(reg_t)) {
+ check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), trig_bytes));
+ trig_len -= sizeof(reg_t);
+ trig_bytes += sizeof(reg_t);
+ }
+ check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(trig_len, trig_bytes));
+ }
if (addr & (len - 1)) {
bool gva = access_info.effective_virt;