diff options
author | Tim Newsome <tim@sifive.com> | 2016-09-02 12:37:38 -0700 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2016-09-02 12:37:38 -0700 |
commit | 2b390a9dea7435c5e83c11433c05e136ad9b163a (patch) | |
tree | 1e61e6024ebce5290b99401c4d7d94f8d8b3a091 /riscv/mmu.cc | |
parent | e464ab8efb36fc089303f11ddf78e32a90530c43 (diff) | |
download | spike-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.cc | 42 |
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)) |