AMOs should always return store faults, not load faults
[riscv-isa-sim.git] / riscv / mmu.h
index 1f8d34b3a9ad2f0bfcc5793640c74524e04f532b..105908e5b7de4baf4056c46ad43d484442e254c5 100644 (file)
@@ -105,12 +105,32 @@ public:
         store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&val); \
     }
 
+  // template for functions that perform an atomic memory operation
+  #define amo_func(type) \
+    template<typename op> \
+    type##_t amo_##type(reg_t addr, op f) { \
+      if (addr & (sizeof(type##_t)-1)) \
+        throw trap_store_address_misaligned(addr); \
+      try { \
+        auto lhs = load_##type(addr); \
+        store_##type(addr, f(lhs)); \
+        return lhs; \
+      } catch (trap_load_access_fault& t) { \
+        /* AMO faults should be reported as store faults */ \
+        throw trap_store_access_fault(t.get_badaddr()); \
+      } \
+    }
+
   // store value to memory at aligned address
   store_func(uint8)
   store_func(uint16)
   store_func(uint32)
   store_func(uint64)
 
+  // perform an atomic memory operation at an aligned address
+  amo_func(uint32)
+  amo_func(uint64)
+
   static const reg_t ICACHE_ENTRIES = 1024;
 
   inline size_t icache_index(reg_t addr)