diff options
author | Andrew Waterman <andrew@sifive.com> | 2017-04-05 20:37:01 -0700 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2017-04-05 20:39:24 -0700 |
commit | 1132fdf4f07dfbfba237af7b0cfac3cae543a79b (patch) | |
tree | e94bcf8bba579f661b78fbdcf1bc267c36f08ef4 /riscv | |
parent | f2e8eb28cca2a5f49cea9f37774058718f795fdd (diff) | |
download | spike-1132fdf4f07dfbfba237af7b0cfac3cae543a79b.zip spike-1132fdf4f07dfbfba237af7b0cfac3cae543a79b.tar.gz spike-1132fdf4f07dfbfba237af7b0cfac3cae543a79b.tar.bz2 |
Add --enable-misaligned option for misaligned ld/st support
Resolves #93
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/mmu.h | 30 | ||||
-rw-r--r-- | riscv/riscv.ac | 5 |
2 files changed, 31 insertions, 4 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h index 66454be..a8d9675 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -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; \ diff --git a/riscv/riscv.ac b/riscv/riscv.ac index a099269..68bcdb5 100644 --- a/riscv/riscv.ac +++ b/riscv/riscv.ac @@ -37,3 +37,8 @@ AC_ARG_ENABLE([dirty], AS_HELP_STRING([--enable-dirty], [Enable hardware managem AS_IF([test "x$enable_dirty" = "xyes"], [ AC_DEFINE([RISCV_ENABLE_DIRTY],,[Enable hardware management of PTE accessed and dirty bits]) ]) + +AC_ARG_ENABLE([misaligned], AS_HELP_STRING([--enable-misaligned], [Enable hardware support for misaligned loads and stores])) +AS_IF([test "x$enable_misaligned" = "xyes"], [ + AC_DEFINE([RISCV_ENABLE_MISALIGNED],,[Enable hardware support for misaligned loads and stores]) +]) |