+ // 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_page_fault& t) { \
+ /* AMO faults should be reported as store faults */ \
+ throw trap_store_page_fault(t.get_tval()); \
+ } catch (trap_load_access_fault& t) { \
+ /* AMO faults should be reported as store faults */ \
+ throw trap_store_access_fault(t.get_tval()); \
+ } \
+ }
+
+ void store_float128(reg_t addr, float128_t val)
+ {
+#ifndef RISCV_ENABLE_MISALIGNED
+ if (unlikely(addr & (sizeof(float128_t)-1)))
+ throw trap_store_address_misaligned(addr);
+#endif
+ store_uint64(addr, val.v[0]);
+ store_uint64(addr + 8, val.v[1]);
+ }
+
+ float128_t load_float128(reg_t addr)
+ {
+#ifndef RISCV_ENABLE_MISALIGNED
+ if (unlikely(addr & (sizeof(float128_t)-1)))
+ throw trap_load_address_misaligned(addr);
+#endif
+ return (float128_t){load_uint64(addr), load_uint64(addr + 8)};
+ }
+