1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* atomic.S: These things are too big to do inline.
7 #include <linux/linkage.h>
9 #include <asm/backoff.h>
10 #include <asm/export.h>
14 /* Three versions of the atomic routines, one that
15 * does not return a value and does not perform
16 * memory barriers, and a two which return
17 * a value, the new and old value resp. and does the
21 #define ATOMIC_OP(op) \
22 ENTRY(atomic_##op) /* %o0 = increment, %o1 = atomic_ptr */ \
26 cas [%o1], %g1, %g7; \
28 bne,pn %icc, BACKOFF_LABEL(2f, 1b); \
32 2: BACKOFF_SPIN(%o2, %o3, 1b); \
33 ENDPROC(atomic_##op); \
34 EXPORT_SYMBOL(atomic_##op);
36 #define ATOMIC_OP_RETURN(op) \
37 ENTRY(atomic_##op##_return) /* %o0 = increment, %o1 = atomic_ptr */ \
41 cas [%o1], %g1, %g7; \
43 bne,pn %icc, BACKOFF_LABEL(2f, 1b); \
47 2: BACKOFF_SPIN(%o2, %o3, 1b); \
48 ENDPROC(atomic_##op##_return); \
49 EXPORT_SYMBOL(atomic_##op##_return);
51 #define ATOMIC_FETCH_OP(op) \
52 ENTRY(atomic_fetch_##op) /* %o0 = increment, %o1 = atomic_ptr */ \
56 cas [%o1], %g1, %g7; \
58 bne,pn %icc, BACKOFF_LABEL(2f, 1b); \
62 2: BACKOFF_SPIN(%o2, %o3, 1b); \
63 ENDPROC(atomic_fetch_##op); \
64 EXPORT_SYMBOL(atomic_fetch_##op);
83 #undef ATOMIC_FETCH_OP
84 #undef ATOMIC_OP_RETURN
87 #define ATOMIC64_OP(op) \
88 ENTRY(atomic64_##op) /* %o0 = increment, %o1 = atomic_ptr */ \
92 casx [%o1], %g1, %g7; \
94 bne,pn %xcc, BACKOFF_LABEL(2f, 1b); \
98 2: BACKOFF_SPIN(%o2, %o3, 1b); \
99 ENDPROC(atomic64_##op); \
100 EXPORT_SYMBOL(atomic64_##op);
102 #define ATOMIC64_OP_RETURN(op) \
103 ENTRY(atomic64_##op##_return) /* %o0 = increment, %o1 = atomic_ptr */ \
104 BACKOFF_SETUP(%o2); \
107 casx [%o1], %g1, %g7; \
109 bne,pn %xcc, BACKOFF_LABEL(2f, 1b); \
113 2: BACKOFF_SPIN(%o2, %o3, 1b); \
114 ENDPROC(atomic64_##op##_return); \
115 EXPORT_SYMBOL(atomic64_##op##_return);
117 #define ATOMIC64_FETCH_OP(op) \
118 ENTRY(atomic64_fetch_##op) /* %o0 = increment, %o1 = atomic_ptr */ \
119 BACKOFF_SETUP(%o2); \
122 casx [%o1], %g1, %g7; \
124 bne,pn %xcc, BACKOFF_LABEL(2f, 1b); \
128 2: BACKOFF_SPIN(%o2, %o3, 1b); \
129 ENDPROC(atomic64_fetch_##op); \
130 EXPORT_SYMBOL(atomic64_fetch_##op);
133 ATOMIC64_OP_RETURN(add)
134 ATOMIC64_FETCH_OP(add)
137 ATOMIC64_OP_RETURN(sub)
138 ATOMIC64_FETCH_OP(sub)
141 ATOMIC64_FETCH_OP(and)
144 ATOMIC64_FETCH_OP(or)
147 ATOMIC64_FETCH_OP(xor)
149 #undef ATOMIC64_FETCH_OP
150 #undef ATOMIC64_OP_RETURN
153 ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */
160 bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
164 2: BACKOFF_SPIN(%o2, %o3, 1b)
165 ENDPROC(atomic64_dec_if_positive)
166 EXPORT_SYMBOL(atomic64_dec_if_positive)