aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure16
-rw-r--r--riscv/mmu.h30
-rw-r--r--riscv/riscv.ac5
4 files changed, 50 insertions, 4 deletions
diff --git a/config.h.in b/config.h.in
index 15b5850..137f195 100644
--- a/config.h.in
+++ b/config.h.in
@@ -75,6 +75,9 @@
/* Enable PC histogram generation */
#undef RISCV_ENABLE_HISTOGRAM
+/* Enable hardware support for misaligned loads and stores */
+#undef RISCV_ENABLE_MISALIGNED
+
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
#undef SOFTFLOAT_ENABLED
diff --git a/configure b/configure
index eddc147..77bab30 100755
--- a/configure
+++ b/configure
@@ -706,6 +706,7 @@ with_fesvr
enable_commitlog
enable_histogram
enable_dirty
+enable_misaligned
'
ac_precious_vars='build_alias
host_alias
@@ -1352,6 +1353,8 @@ Optional Features:
--enable-histogram Enable PC histogram generation
--enable-dirty Enable hardware management of PTE accessed and dirty
bits
+ --enable-misaligned Enable hardware support for misaligned loads and
+ stores
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -4681,6 +4684,19 @@ $as_echo "#define RISCV_ENABLE_DIRTY /**/" >>confdefs.h
fi
+# Check whether --enable-misaligned was given.
+if test "${enable_misaligned+set}" = set; then :
+ enableval=$enable_misaligned;
+fi
+
+if test "x$enable_misaligned" = "xyes"; then :
+
+
+$as_echo "#define RISCV_ENABLE_MISALIGNED /**/" >>confdefs.h
+
+
+fi
+
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])
+])