aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2017-04-05 20:37:01 -0700
committerAndrew Waterman <andrew@sifive.com>2017-04-05 20:39:24 -0700
commit1132fdf4f07dfbfba237af7b0cfac3cae543a79b (patch)
treee94bcf8bba579f661b78fbdcf1bc267c36f08ef4 /riscv
parentf2e8eb28cca2a5f49cea9f37774058718f795fdd (diff)
downloadspike-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.h30
-rw-r--r--riscv/riscv.ac5
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])
+])