aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.cc
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2016-09-02 12:37:38 -0700
committerTim Newsome <tim@sifive.com>2016-09-02 12:37:38 -0700
commit2b390a9dea7435c5e83c11433c05e136ad9b163a (patch)
tree1e61e6024ebce5290b99401c4d7d94f8d8b3a091 /riscv/mmu.cc
parente464ab8efb36fc089303f11ddf78e32a90530c43 (diff)
downloadspike-2b390a9dea7435c5e83c11433c05e136ad9b163a.zip
spike-2b390a9dea7435c5e83c11433c05e136ad9b163a.tar.gz
spike-2b390a9dea7435c5e83c11433c05e136ad9b163a.tar.bz2
Support triggers on TLB misses.
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r--riscv/mmu.cc42
1 files changed, 42 insertions, 0 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 0b60713..878d849 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -73,9 +73,36 @@ const uint16_t* mmu_t::fetch_slow_path(reg_t vaddr)
}
}
+reg_t reg_from_bytes(size_t len, const uint8_t* bytes)
+{
+ switch (len) {
+ case 1:
+ return bytes[0];
+ case 2:
+ return bytes[0] |
+ (((reg_t) bytes[1]) << 8);
+ case 4:
+ return bytes[0] |
+ (((reg_t) bytes[1]) << 8) |
+ (((reg_t) bytes[2]) << 16) |
+ (((reg_t) bytes[3]) << 24);
+ case 8:
+ return bytes[0] |
+ (((reg_t) bytes[1]) << 8) |
+ (((reg_t) bytes[2]) << 16) |
+ (((reg_t) bytes[3]) << 24) |
+ (((reg_t) bytes[4]) << 32) |
+ (((reg_t) bytes[5]) << 40) |
+ (((reg_t) bytes[6]) << 48) |
+ (((reg_t) bytes[7]) << 56);
+ }
+ abort();
+}
+
void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes)
{
reg_t paddr = translate(addr, LOAD);
+
if (sim->addr_is_mem(paddr)) {
memcpy(bytes, sim->addr_to_mem(paddr), len);
if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
@@ -85,11 +112,26 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes)
} else if (!sim->mmio_load(paddr, len, bytes)) {
throw trap_load_access_fault(addr);
}
+
+ if (!matched_trigger) {
+ reg_t data = reg_from_bytes(len, bytes);
+ matched_trigger = trigger_exception(OPERATION_LOAD, addr, data);
+ if (matched_trigger)
+ throw *matched_trigger;
+ }
}
void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes)
{
reg_t paddr = translate(addr, STORE);
+
+ if (!matched_trigger) {
+ reg_t data = reg_from_bytes(len, bytes);
+ matched_trigger = trigger_exception(OPERATION_STORE, addr, data);
+ if (matched_trigger)
+ throw *matched_trigger;
+ }
+
if (sim->addr_is_mem(paddr)) {
memcpy(sim->addr_to_mem(paddr), bytes, len);
if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))