blob: e528b8d1a3e69fc8d57128df8f8d7654a1ef8ab6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $Id: atomic.S,v 1.4 2001/11/18 00:12:56 davem Exp $
2 * atomic.S: These things are too big to do inline.
3 *
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
5 */
6
7#include <linux/config.h>
8#include <asm/asi.h>
9
10 /* On SMP we need to use memory barriers to ensure
11 * correct memory operation ordering, nop these out
12 * for uniprocessor.
13 */
14#ifdef CONFIG_SMP
15#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad
16#define ATOMIC_POST_BARRIER membar #StoreLoad | #StoreStore
17#else
18#define ATOMIC_PRE_BARRIER nop
19#define ATOMIC_POST_BARRIER nop
20#endif
21
22 .text
23
24 /* Two versions of the atomic routines, one that
25 * does not return a value and does not perform
26 * memory barriers, and a second which returns
27 * a value and does the barriers.
28 */
29 .globl atomic_add
30 .type atomic_add,#function
31atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
321: lduw [%o1], %g1
33 add %g1, %o0, %g7
34 cas [%o1], %g1, %g7
35 cmp %g1, %g7
36 bne,pn %icc, 1b
37 nop
38 retl
39 nop
40 .size atomic_add, .-atomic_add
41
42 .globl atomic_sub
43 .type atomic_sub,#function
44atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
451: lduw [%o1], %g1
46 sub %g1, %o0, %g7
47 cas [%o1], %g1, %g7
48 cmp %g1, %g7
49 bne,pn %icc, 1b
50 nop
51 retl
52 nop
53 .size atomic_sub, .-atomic_sub
54
55 .globl atomic_add_ret
56 .type atomic_add_ret,#function
57atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
58 ATOMIC_PRE_BARRIER
591: lduw [%o1], %g1
60 add %g1, %o0, %g7
61 cas [%o1], %g1, %g7
62 cmp %g1, %g7
63 bne,pn %icc, 1b
64 add %g7, %o0, %g7
65 ATOMIC_POST_BARRIER
66 retl
67 sra %g7, 0, %o0
68 .size atomic_add_ret, .-atomic_add_ret
69
70 .globl atomic_sub_ret
71 .type atomic_sub_ret,#function
72atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
73 ATOMIC_PRE_BARRIER
741: lduw [%o1], %g1
75 sub %g1, %o0, %g7
76 cas [%o1], %g1, %g7
77 cmp %g1, %g7
78 bne,pn %icc, 1b
79 sub %g7, %o0, %g7
80 ATOMIC_POST_BARRIER
81 retl
82 sra %g7, 0, %o0
83 .size atomic_sub_ret, .-atomic_sub_ret
84
85 .globl atomic64_add
86 .type atomic64_add,#function
87atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
881: ldx [%o1], %g1
89 add %g1, %o0, %g7
90 casx [%o1], %g1, %g7
91 cmp %g1, %g7
92 bne,pn %xcc, 1b
93 nop
94 retl
95 nop
96 .size atomic64_add, .-atomic64_add
97
98 .globl atomic64_sub
99 .type atomic64_sub,#function
100atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
1011: ldx [%o1], %g1
102 sub %g1, %o0, %g7
103 casx [%o1], %g1, %g7
104 cmp %g1, %g7
105 bne,pn %xcc, 1b
106 nop
107 retl
108 nop
109 .size atomic64_sub, .-atomic64_sub
110
111 .globl atomic64_add_ret
112 .type atomic64_add_ret,#function
113atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
114 ATOMIC_PRE_BARRIER
1151: ldx [%o1], %g1
116 add %g1, %o0, %g7
117 casx [%o1], %g1, %g7
118 cmp %g1, %g7
119 bne,pn %xcc, 1b
120 add %g7, %o0, %g7
121 ATOMIC_POST_BARRIER
122 retl
123 mov %g7, %o0
124 .size atomic64_add_ret, .-atomic64_add_ret
125
126 .globl atomic64_sub_ret
127 .type atomic64_sub_ret,#function
128atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
129 ATOMIC_PRE_BARRIER
1301: ldx [%o1], %g1
131 sub %g1, %o0, %g7
132 casx [%o1], %g1, %g7
133 cmp %g1, %g7
134 bne,pn %xcc, 1b
135 sub %g7, %o0, %g7
136 ATOMIC_POST_BARRIER
137 retl
138 mov %g7, %o0
139 .size atomic64_sub_ret, .-atomic64_sub_ret