blob: 70ac4186f62b7afc4af36eeb5472d6db868688d8 [file] [log] [blame]
David S. Miller24f287e2007-10-15 16:41:44 -07001/* atomic.S: These things are too big to do inline.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
David S. Miller24f287e2007-10-15 16:41:44 -07003 * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 */
5
Linus Torvalds1da177e2005-04-16 15:20:36 -07006#include <asm/asi.h>
David S. Miller24f287e2007-10-15 16:41:44 -07007#include <asm/backoff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 .text
10
11 /* Two versions of the atomic routines, one that
12 * does not return a value and does not perform
13 * memory barriers, and a second which returns
14 * a value and does the barriers.
15 */
16 .globl atomic_add
17 .type atomic_add,#function
18atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -070019 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201: lduw [%o1], %g1
21 add %g1, %o0, %g7
22 cas [%o1], %g1, %g7
23 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -070024 bne,pn %icc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 nop
26 retl
27 nop
David S. Miller24f287e2007-10-15 16:41:44 -0700282: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 .size atomic_add, .-atomic_add
30
31 .globl atomic_sub
32 .type atomic_sub,#function
33atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -070034 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351: lduw [%o1], %g1
36 sub %g1, %o0, %g7
37 cas [%o1], %g1, %g7
38 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -070039 bne,pn %icc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 nop
41 retl
42 nop
David S. Miller24f287e2007-10-15 16:41:44 -0700432: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 .size atomic_sub, .-atomic_sub
45
David S. Millerb445e262005-06-27 15:42:04 -070046 /* On SMP we need to use memory barriers to ensure
47 * correct memory operation ordering, nop these out
48 * for uniprocessor.
49 */
50#ifdef CONFIG_SMP
51
52#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad;
53#define ATOMIC_POST_BARRIER \
54 ba,pt %xcc, 80b; \
55 membar #StoreLoad | #StoreStore
56
5780: retl
58 nop
59#else
60#define ATOMIC_PRE_BARRIER
61#define ATOMIC_POST_BARRIER
62#endif
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 .globl atomic_add_ret
65 .type atomic_add_ret,#function
66atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -070067 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 ATOMIC_PRE_BARRIER
691: lduw [%o1], %g1
70 add %g1, %o0, %g7
71 cas [%o1], %g1, %g7
72 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -070073 bne,pn %icc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 add %g7, %o0, %g7
David S. Millerb445e262005-06-27 15:42:04 -070075 sra %g7, 0, %o0
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 ATOMIC_POST_BARRIER
77 retl
David S. Millerb445e262005-06-27 15:42:04 -070078 nop
David S. Miller24f287e2007-10-15 16:41:44 -0700792: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 .size atomic_add_ret, .-atomic_add_ret
81
82 .globl atomic_sub_ret
83 .type atomic_sub_ret,#function
84atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -070085 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 ATOMIC_PRE_BARRIER
871: lduw [%o1], %g1
88 sub %g1, %o0, %g7
89 cas [%o1], %g1, %g7
90 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -070091 bne,pn %icc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 sub %g7, %o0, %g7
David S. Millerb445e262005-06-27 15:42:04 -070093 sra %g7, 0, %o0
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 ATOMIC_POST_BARRIER
95 retl
David S. Millerb445e262005-06-27 15:42:04 -070096 nop
David S. Miller24f287e2007-10-15 16:41:44 -0700972: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 .size atomic_sub_ret, .-atomic_sub_ret
99
100 .globl atomic64_add
101 .type atomic64_add,#function
102atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -0700103 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041: ldx [%o1], %g1
105 add %g1, %o0, %g7
106 casx [%o1], %g1, %g7
107 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -0700108 bne,pn %xcc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 nop
110 retl
111 nop
David S. Miller24f287e2007-10-15 16:41:44 -07001122: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 .size atomic64_add, .-atomic64_add
114
115 .globl atomic64_sub
116 .type atomic64_sub,#function
117atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -0700118 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191: ldx [%o1], %g1
120 sub %g1, %o0, %g7
121 casx [%o1], %g1, %g7
122 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -0700123 bne,pn %xcc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 nop
125 retl
126 nop
David S. Miller24f287e2007-10-15 16:41:44 -07001272: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 .size atomic64_sub, .-atomic64_sub
129
130 .globl atomic64_add_ret
131 .type atomic64_add_ret,#function
132atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -0700133 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 ATOMIC_PRE_BARRIER
1351: ldx [%o1], %g1
136 add %g1, %o0, %g7
137 casx [%o1], %g1, %g7
138 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -0700139 bne,pn %xcc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 add %g7, %o0, %g7
David S. Millerb445e262005-06-27 15:42:04 -0700141 mov %g7, %o0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 ATOMIC_POST_BARRIER
143 retl
David S. Millerb445e262005-06-27 15:42:04 -0700144 nop
David S. Miller24f287e2007-10-15 16:41:44 -07001452: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 .size atomic64_add_ret, .-atomic64_add_ret
147
148 .globl atomic64_sub_ret
149 .type atomic64_sub_ret,#function
150atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
David S. Miller24f287e2007-10-15 16:41:44 -0700151 BACKOFF_SETUP(%o2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 ATOMIC_PRE_BARRIER
1531: ldx [%o1], %g1
154 sub %g1, %o0, %g7
155 casx [%o1], %g1, %g7
156 cmp %g1, %g7
David S. Miller24f287e2007-10-15 16:41:44 -0700157 bne,pn %xcc, 2f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 sub %g7, %o0, %g7
David S. Millerb445e262005-06-27 15:42:04 -0700159 mov %g7, %o0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 ATOMIC_POST_BARRIER
161 retl
David S. Millerb445e262005-06-27 15:42:04 -0700162 nop
David S. Miller24f287e2007-10-15 16:41:44 -07001632: BACKOFF_SPIN(%o2, %o3, 1b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 .size atomic64_sub_ret, .-atomic64_sub_ret