Add --enable-misaligned option for misaligned ld/st support
[riscv-isa-sim.git] / riscv / mmu.h
index 66454bed09ebd8f5a010f5c80623eebd108f6701..a8d9675b402ad421eb8b7ab70528062e66250f4f 100644 (file)
@@ -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; \