@@ -23,6 +23,7 @@
UNSPEC_COMPARE_AND_SWAP
UNSPEC_SYNC_OLD_OP
UNSPEC_SYNC_EXCHANGE
+ UNSPEC_ATOMIC_LOAD
UNSPEC_ATOMIC_STORE
UNSPEC_MEMORY_BARRIER
])
@@ -72,6 +73,46 @@
;; Atomic memory operations.
+(define_expand "atomic_load<mode>"
+ [(set (match_operand:ANYI 0 "register_operand" "=r")
+ (unspec_volatile:ANYI
+ [(match_operand:ANYI 1 "memory_operand" "A")
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ UNSPEC_ATOMIC_LOAD))]
+ ""
+ {
+ rtx target = operands[0];
+ rtx mem = operands[1];
+ enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+
+ if (is_mm_seq_cst (model))
+ emit_insn (gen_mem_fence (GEN_INT (MEMMODEL_SEQ_CST)));
+ emit_move_insn (target, mem);
+ if (is_mm_acquire (model) || is_mm_seq_cst (model))
+ emit_insn (gen_mem_fence (GEN_INT (MEMMODEL_ACQUIRE)));
+
+ DONE;
+})
+
+(define_expand "atomic_store<mode>"
+ [(set (match_operand:ANYI 0 "memory_operand" "=A")
+ (unspec_volatile:ANYI
+ [(match_operand:ANYI 1 "reg_or_0_operand" "rJ")
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ UNSPEC_ATOMIC_STORE))]
+ ""
+ {
+ rtx mem = operands[0];
+ rtx val = operands[1];
+ enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+
+ if (is_mm_release (model) || is_mm_seq_cst (model))
+ emit_insn (gen_mem_fence (GEN_INT (MEMMODEL_RELEASE)));
+ emit_move_insn (mem, val);
+
+ DONE;
+})
+
(define_insn "atomic_<atomic_optab><mode>"
[(set (match_operand:GPR 0 "memory_operand" "+A")
(unspec_volatile:GPR