diff --git a/riscv/mmu.h b/riscv/mmu.h index b3c38c230b..b4abc2e3d0 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -56,8 +56,25 @@ class mmu_t { #ifdef RISCV_ENABLE_MISALIGNED reg_t res = 0; - for (size_t i = 0; i < size; i++) - res += (reg_t)load_uint8(addr + (target_big_endian? size-1-i : i)) << (i * 8); + bool caught_fault = false; + trap_load_access_fault fault(false, 0, 0, 0); + for (size_t i = 0; i < size; i++) { + try { + res += (reg_t)load_uint8(addr + (target_big_endian? size-1-i : i)) << (i * 8); + } catch (trap_load_access_fault& f) { + if (!caught_fault) { + // Catch first fault seen on unaligned access and proceed with other bytes of the access. + fault = f; + caught_fault = true; + } + } + } + + if (caught_fault) { + // Throw a fault if we saw onw + throw fault; + } + return res; #else bool gva = ((proc) ? proc->state.v : false) || (RISCV_XLATE_VIRT & xlate_flags); @@ -68,8 +85,24 @@ class mmu_t inline void misaligned_store(reg_t addr, reg_t data, size_t size, uint32_t xlate_flags, bool actually_store=true) { #ifdef RISCV_ENABLE_MISALIGNED - for (size_t i = 0; i < size; i++) - store_uint8(addr + (target_big_endian? size-1-i : i), data >> (i * 8), actually_store); + bool caught_fault = false; + trap_store_access_fault fault(false, 0, 0, 0); + for (size_t i = 0; i < size; i++) { + try { + store_uint8(addr + (target_big_endian? size-1-i : i), data >> (i * 8), actually_store); + } catch (trap_store_access_fault& f) { + if (!caught_fault) { + // Catch first fault seen on unaligned access and proceed with other bytes of the access. + fault = f; + caught_fault = true; + } + } + } + + if (caught_fault) { + // Throw a fault if we saw onw + throw fault; + } #else bool gva = ((proc) ? proc->state.v : false) || (RISCV_XLATE_VIRT & xlate_flags); throw trap_store_address_misaligned(gva, addr, 0, 0);