1/* atomic.S: These things are too big to do inline. 2 * 3 * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net) 4 */ 5 6#include <linux/linkage.h> 7#include <asm/asi.h> 8#include <asm/backoff.h> 9 10 .text 11 12 /* Two versions of the atomic routines, one that 13 * does not return a value and does not perform 14 * memory barriers, and a second which returns 15 * a value and does the barriers. 16 */ 17 18#define ATOMIC_OP(op) \ 19ENTRY(atomic_##op) /* %o0 = increment, %o1 = atomic_ptr */ \ 20 BACKOFF_SETUP(%o2); \ 211: lduw [%o1], %g1; \ 22 op %g1, %o0, %g7; \ 23 cas [%o1], %g1, %g7; \ 24 cmp %g1, %g7; \ 25 bne,pn %icc, BACKOFF_LABEL(2f, 1b); \ 26 nop; \ 27 retl; \ 28 nop; \ 292: BACKOFF_SPIN(%o2, %o3, 1b); \ 30ENDPROC(atomic_##op); \ 31 32#define ATOMIC_OP_RETURN(op) \ 33ENTRY(atomic_##op##_return) /* %o0 = increment, %o1 = atomic_ptr */ \ 34 BACKOFF_SETUP(%o2); \ 351: lduw [%o1], %g1; \ 36 op %g1, %o0, %g7; \ 37 cas [%o1], %g1, %g7; \ 38 cmp %g1, %g7; \ 39 bne,pn %icc, BACKOFF_LABEL(2f, 1b); \ 40 op %g1, %o0, %g1; \ 41 retl; \ 42 sra %g1, 0, %o0; \ 432: BACKOFF_SPIN(%o2, %o3, 1b); \ 44ENDPROC(atomic_##op##_return); 45 46#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) 47 48ATOMIC_OPS(add) 49ATOMIC_OPS(sub) 50 51#undef ATOMIC_OPS 52#undef ATOMIC_OP_RETURN 53#undef ATOMIC_OP 54 55#define ATOMIC64_OP(op) \ 56ENTRY(atomic64_##op) /* %o0 = increment, %o1 = atomic_ptr */ \ 57 BACKOFF_SETUP(%o2); \ 581: ldx [%o1], %g1; \ 59 op %g1, %o0, %g7; \ 60 casx [%o1], %g1, %g7; \ 61 cmp %g1, %g7; \ 62 bne,pn %xcc, BACKOFF_LABEL(2f, 1b); \ 63 nop; \ 64 retl; \ 65 nop; \ 662: BACKOFF_SPIN(%o2, %o3, 1b); \ 67ENDPROC(atomic64_##op); \ 68 69#define ATOMIC64_OP_RETURN(op) \ 70ENTRY(atomic64_##op##_return) /* %o0 = increment, %o1 = atomic_ptr */ \ 71 BACKOFF_SETUP(%o2); \ 721: ldx [%o1], %g1; \ 73 op %g1, %o0, %g7; \ 74 casx [%o1], %g1, %g7; \ 75 cmp %g1, %g7; \ 76 bne,pn %xcc, BACKOFF_LABEL(2f, 1b); \ 77 nop; \ 78 retl; \ 79 op %g1, %o0, %o0; \ 802: BACKOFF_SPIN(%o2, %o3, 1b); \ 81ENDPROC(atomic64_##op##_return); 82 83#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op) 84 85ATOMIC64_OPS(add) 86ATOMIC64_OPS(sub) 87 88#undef ATOMIC64_OPS 89#undef ATOMIC64_OP_RETURN 90#undef ATOMIC64_OP 91 92ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */ 93 BACKOFF_SETUP(%o2) 941: ldx [%o0], %g1 95 brlez,pn %g1, 3f 96 sub %g1, 1, %g7 97 casx [%o0], %g1, %g7 98 cmp %g1, %g7 99 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) 100 nop 1013: retl 102 sub %g1, 1, %o0 1032: BACKOFF_SPIN(%o2, %o3, 1b) 104ENDPROC(atomic64_dec_if_positive) 105