|
|
|
@ -51,11 +51,33 @@ public: |
|
|
|
mmu_t(sim_t* sim, processor_t* proc); |
|
|
|
~mmu_t(); |
|
|
|
|
|
|
|
inline reg_t misaligned_load(reg_t addr, size_t size) |
|
|
|
{ |
|
|
|
#ifdef RISCV_ENABLE_MISALIGNED |
|
|
|
reg_t res = 0; |
|
|
|
for (size_t i = 0; i < size; i++) |
|
|
|
res += (reg_t)load_uint8(addr + i) << (i * 8); |
|
|
|
return res; |
|
|
|
#else |
|
|
|
throw trap_load_address_misaligned(addr); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
inline void misaligned_store(reg_t addr, reg_t data, size_t size) |
|
|
|
{ |
|
|
|
#ifdef RISCV_ENABLE_MISALIGNED |
|
|
|
for (size_t i = 0; i < size; i++) |
|
|
|
store_uint8(addr + i, data >> (i * 8)); |
|
|
|
#else |
|
|
|
throw trap_store_address_misaligned(addr); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// template for functions that load an aligned value from memory
|
|
|
|
#define load_func(type) \ |
|
|
|
inline type##_t load_##type(reg_t addr) { \ |
|
|
|
if (addr & (sizeof(type##_t)-1)) \ |
|
|
|
throw trap_load_address_misaligned(addr); \ |
|
|
|
if (unlikely(addr & (sizeof(type##_t)-1))) \ |
|
|
|
return misaligned_load(addr, sizeof(type##_t)); \ |
|
|
|
reg_t vpn = addr >> PGSHIFT; \ |
|
|
|
if (likely(tlb_load_tag[vpn % TLB_ENTRIES] == vpn)) \ |
|
|
|
return *(type##_t*)(tlb_data[vpn % TLB_ENTRIES] + addr); \ |
|
|
|
@ -88,8 +110,8 @@ public: |
|
|
|
// template for functions that store an aligned value to memory
|
|
|
|
#define store_func(type) \ |
|
|
|
void store_##type(reg_t addr, type##_t val) { \ |
|
|
|
if (addr & (sizeof(type##_t)-1)) \ |
|
|
|
throw trap_store_address_misaligned(addr); \ |
|
|
|
if (unlikely(addr & (sizeof(type##_t)-1))) \ |
|
|
|
return misaligned_store(addr, val, sizeof(type##_t)); \ |
|
|
|
reg_t vpn = addr >> PGSHIFT; \ |
|
|
|
if (likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) \ |
|
|
|
*(type##_t*)(tlb_data[vpn % TLB_ENTRIES] + addr) = val; \ |
|
|
|
|