xref: /openbmc/linux/arch/sparc/lib/atomic_64.S (revision 7dd65feb)
1/* atomic.S: These things are too big to do inline.
2 *
3 * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#include <asm/asi.h>
7#include <asm/backoff.h>
8
9	.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 */
19	BACKOFF_SETUP(%o2)
201:	lduw	[%o1], %g1
21	add	%g1, %o0, %g7
22	cas	[%o1], %g1, %g7
23	cmp	%g1, %g7
24	bne,pn	%icc, 2f
25	 nop
26	retl
27	 nop
282:	BACKOFF_SPIN(%o2, %o3, 1b)
29	.size	atomic_add, .-atomic_add
30
31	.globl	atomic_sub
32	.type	atomic_sub,#function
33atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
34	BACKOFF_SETUP(%o2)
351:	lduw	[%o1], %g1
36	sub	%g1, %o0, %g7
37	cas	[%o1], %g1, %g7
38	cmp	%g1, %g7
39	bne,pn	%icc, 2f
40	 nop
41	retl
42	 nop
432:	BACKOFF_SPIN(%o2, %o3, 1b)
44	.size	atomic_sub, .-atomic_sub
45
46	.globl	atomic_add_ret
47	.type	atomic_add_ret,#function
48atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
49	BACKOFF_SETUP(%o2)
501:	lduw	[%o1], %g1
51	add	%g1, %o0, %g7
52	cas	[%o1], %g1, %g7
53	cmp	%g1, %g7
54	bne,pn	%icc, 2f
55	 add	%g7, %o0, %g7
56	sra	%g7, 0, %o0
57	retl
58	 nop
592:	BACKOFF_SPIN(%o2, %o3, 1b)
60	.size	atomic_add_ret, .-atomic_add_ret
61
62	.globl	atomic_sub_ret
63	.type	atomic_sub_ret,#function
64atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
65	BACKOFF_SETUP(%o2)
661:	lduw	[%o1], %g1
67	sub	%g1, %o0, %g7
68	cas	[%o1], %g1, %g7
69	cmp	%g1, %g7
70	bne,pn	%icc, 2f
71	 sub	%g7, %o0, %g7
72	sra	%g7, 0, %o0
73	retl
74	 nop
752:	BACKOFF_SPIN(%o2, %o3, 1b)
76	.size	atomic_sub_ret, .-atomic_sub_ret
77
78	.globl	atomic64_add
79	.type	atomic64_add,#function
80atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
81	BACKOFF_SETUP(%o2)
821:	ldx	[%o1], %g1
83	add	%g1, %o0, %g7
84	casx	[%o1], %g1, %g7
85	cmp	%g1, %g7
86	bne,pn	%xcc, 2f
87	 nop
88	retl
89	 nop
902:	BACKOFF_SPIN(%o2, %o3, 1b)
91	.size	atomic64_add, .-atomic64_add
92
93	.globl	atomic64_sub
94	.type	atomic64_sub,#function
95atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
96	BACKOFF_SETUP(%o2)
971:	ldx	[%o1], %g1
98	sub	%g1, %o0, %g7
99	casx	[%o1], %g1, %g7
100	cmp	%g1, %g7
101	bne,pn	%xcc, 2f
102	 nop
103	retl
104	 nop
1052:	BACKOFF_SPIN(%o2, %o3, 1b)
106	.size	atomic64_sub, .-atomic64_sub
107
108	.globl	atomic64_add_ret
109	.type	atomic64_add_ret,#function
110atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
111	BACKOFF_SETUP(%o2)
1121:	ldx	[%o1], %g1
113	add	%g1, %o0, %g7
114	casx	[%o1], %g1, %g7
115	cmp	%g1, %g7
116	bne,pn	%xcc, 2f
117	 add	%g7, %o0, %g7
118	mov	%g7, %o0
119	retl
120	 nop
1212:	BACKOFF_SPIN(%o2, %o3, 1b)
122	.size	atomic64_add_ret, .-atomic64_add_ret
123
124	.globl	atomic64_sub_ret
125	.type	atomic64_sub_ret,#function
126atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
127	BACKOFF_SETUP(%o2)
1281:	ldx	[%o1], %g1
129	sub	%g1, %o0, %g7
130	casx	[%o1], %g1, %g7
131	cmp	%g1, %g7
132	bne,pn	%xcc, 2f
133	 sub	%g7, %o0, %g7
134	mov	%g7, %o0
135	retl
136	 nop
1372:	BACKOFF_SPIN(%o2, %o3, 1b)
138	.size	atomic64_sub_ret, .-atomic64_sub_ret
139