1/* $Id: bitops.S,v 1.3 2001/11/18 00:12:56 davem Exp $
2 * bitops.S: Sparc64 atomic bit operations.
3 *
4 * Copyright (C) 2000 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 BITOP_PRE_BARRIER	membar #StoreLoad | #LoadLoad
16#define BITOP_POST_BARRIER	membar #StoreLoad | #StoreStore
17#else
18#define BITOP_PRE_BARRIER	nop
19#define BITOP_POST_BARRIER	nop
20#endif
21
22	.text
23
24	.globl	__bitops_begin
25__bitops_begin:
26
27
28	.globl	test_and_set_bit
29	.type	test_and_set_bit,#function
30test_and_set_bit:	/* %o0=nr, %o1=addr */
31	BITOP_PRE_BARRIER
32	srlx	%o0, 6, %g1
33	mov	1, %g5
34	sllx	%g1, 3, %g3
35	and	%o0, 63, %g2
36	sllx	%g5, %g2, %g5
37	add	%o1, %g3, %o1
381:	ldx	[%o1], %g7
39	or	%g7, %g5, %g1
40	casx	[%o1], %g7, %g1
41	cmp	%g7, %g1
42	bne,pn	%xcc, 1b
43	 and	%g7, %g5, %g2
44	BITOP_POST_BARRIER
45	clr	%o0
46	retl
47	 movrne	%g2, 1, %o0
48	.size	test_and_set_bit, .-test_and_set_bit
49
50	.globl	test_and_clear_bit
51	.type	test_and_clear_bit,#function
52test_and_clear_bit:	/* %o0=nr, %o1=addr */
53	BITOP_PRE_BARRIER
54	srlx	%o0, 6, %g1
55	mov	1, %g5
56	sllx	%g1, 3, %g3
57	and	%o0, 63, %g2
58	sllx	%g5, %g2, %g5
59	add	%o1, %g3, %o1
601:	ldx	[%o1], %g7
61	andn	%g7, %g5, %g1
62	casx	[%o1], %g7, %g1
63	cmp	%g7, %g1
64	bne,pn	%xcc, 1b
65	 and	%g7, %g5, %g2
66	BITOP_POST_BARRIER
67	clr	%o0
68	retl
69	 movrne	%g2, 1, %o0
70	.size	test_and_clear_bit, .-test_and_clear_bit
71
72	.globl	test_and_change_bit
73	.type	test_and_change_bit,#function
74test_and_change_bit:	/* %o0=nr, %o1=addr */
75	BITOP_PRE_BARRIER
76	srlx	%o0, 6, %g1
77	mov	1, %g5
78	sllx	%g1, 3, %g3
79	and	%o0, 63, %g2
80	sllx	%g5, %g2, %g5
81	add	%o1, %g3, %o1
821:	ldx	[%o1], %g7
83	xor	%g7, %g5, %g1
84	casx	[%o1], %g7, %g1
85	cmp	%g7, %g1
86	bne,pn	%xcc, 1b
87	 and	%g7, %g5, %g2
88	BITOP_POST_BARRIER
89	clr	%o0
90	retl
91	 movrne	%g2, 1, %o0
92	.size	test_and_change_bit, .-test_and_change_bit
93
94	.globl	set_bit
95	.type	set_bit,#function
96set_bit:		/* %o0=nr, %o1=addr */
97	srlx	%o0, 6, %g1
98	mov	1, %g5
99	sllx	%g1, 3, %g3
100	and	%o0, 63, %g2
101	sllx	%g5, %g2, %g5
102	add	%o1, %g3, %o1
1031:	ldx	[%o1], %g7
104	or	%g7, %g5, %g1
105	casx	[%o1], %g7, %g1
106	cmp	%g7, %g1
107	bne,pn	%xcc, 1b
108	 nop
109	retl
110	 nop
111	.size	set_bit, .-set_bit
112
113	.globl	clear_bit
114	.type	clear_bit,#function
115clear_bit:		/* %o0=nr, %o1=addr */
116	srlx	%o0, 6, %g1
117	mov	1, %g5
118	sllx	%g1, 3, %g3
119	and	%o0, 63, %g2
120	sllx	%g5, %g2, %g5
121	add	%o1, %g3, %o1
1221:	ldx	[%o1], %g7
123	andn	%g7, %g5, %g1
124	casx	[%o1], %g7, %g1
125	cmp	%g7, %g1
126	bne,pn	%xcc, 1b
127	 nop
128	retl
129	 nop
130	.size	clear_bit, .-clear_bit
131
132	.globl	change_bit
133	.type	change_bit,#function
134change_bit:		/* %o0=nr, %o1=addr */
135	srlx	%o0, 6, %g1
136	mov	1, %g5
137	sllx	%g1, 3, %g3
138	and	%o0, 63, %g2
139	sllx	%g5, %g2, %g5
140	add	%o1, %g3, %o1
1411:	ldx	[%o1], %g7
142	xor	%g7, %g5, %g1
143	casx	[%o1], %g7, %g1
144	cmp	%g7, %g1
145	bne,pn	%xcc, 1b
146	 nop
147	retl
148	 nop
149	.size	change_bit, .-change_bit
150
151	.globl	__bitops_end
152__bitops_end:
153