aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.h
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/mmu.h')
-rw-r--r--riscv/mmu.h20
1 files changed, 20 insertions, 0 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 1f8d34b..105908e 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -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)