1#include <asm/assembler.h>
2#include <asm/unwind.h>
3
4#if __LINUX_ARM_ARCH__ >= 6
5	.macro	bitop, name, instr
6ENTRY(	\name		)
7UNWIND(	.fnstart	)
8	ands	ip, r1, #3
9	strneb	r1, [ip]		@ assert word-aligned
10	mov	r2, #1
11	and	r3, r0, #31		@ Get bit offset
12	mov	r0, r0, lsr #5
13	add	r1, r1, r0, lsl #2	@ Get word offset
14#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
15	.arch_extension	mp
16	ALT_SMP(W(pldw)	[r1])
17	ALT_UP(W(nop))
18#endif
19	mov	r3, r2, lsl r3
201:	ldrex	r2, [r1]
21	\instr	r2, r2, r3
22	strex	r0, r2, [r1]
23	cmp	r0, #0
24	bne	1b
25	bx	lr
26UNWIND(	.fnend		)
27ENDPROC(\name		)
28	.endm
29
30	.macro	testop, name, instr, store
31ENTRY(	\name		)
32UNWIND(	.fnstart	)
33	ands	ip, r1, #3
34	strneb	r1, [ip]		@ assert word-aligned
35	mov	r2, #1
36	and	r3, r0, #31		@ Get bit offset
37	mov	r0, r0, lsr #5
38	add	r1, r1, r0, lsl #2	@ Get word offset
39	mov	r3, r2, lsl r3		@ create mask
40	smp_dmb
41#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
42	.arch_extension	mp
43	ALT_SMP(W(pldw)	[r1])
44	ALT_UP(W(nop))
45#endif
461:	ldrex	r2, [r1]
47	ands	r0, r2, r3		@ save old value of bit
48	\instr	r2, r2, r3		@ toggle bit
49	strex	ip, r2, [r1]
50	cmp	ip, #0
51	bne	1b
52	smp_dmb
53	cmp	r0, #0
54	movne	r0, #1
552:	bx	lr
56UNWIND(	.fnend		)
57ENDPROC(\name		)
58	.endm
59#else
60	.macro	bitop, name, instr
61ENTRY(	\name		)
62UNWIND(	.fnstart	)
63	ands	ip, r1, #3
64	strneb	r1, [ip]		@ assert word-aligned
65	and	r2, r0, #31
66	mov	r0, r0, lsr #5
67	mov	r3, #1
68	mov	r3, r3, lsl r2
69	save_and_disable_irqs ip
70	ldr	r2, [r1, r0, lsl #2]
71	\instr	r2, r2, r3
72	str	r2, [r1, r0, lsl #2]
73	restore_irqs ip
74	ret	lr
75UNWIND(	.fnend		)
76ENDPROC(\name		)
77	.endm
78
79/**
80 * testop - implement a test_and_xxx_bit operation.
81 * @instr: operational instruction
82 * @store: store instruction
83 *
84 * Note: we can trivially conditionalise the store instruction
85 * to avoid dirtying the data cache.
86 */
87	.macro	testop, name, instr, store
88ENTRY(	\name		)
89UNWIND(	.fnstart	)
90	ands	ip, r1, #3
91	strneb	r1, [ip]		@ assert word-aligned
92	and	r3, r0, #31
93	mov	r0, r0, lsr #5
94	save_and_disable_irqs ip
95	ldr	r2, [r1, r0, lsl #2]!
96	mov	r0, #1
97	tst	r2, r0, lsl r3
98	\instr	r2, r2, r0, lsl r3
99	\store	r2, [r1]
100	moveq	r0, #0
101	restore_irqs ip
102	ret	lr
103UNWIND(	.fnend		)
104ENDPROC(\name		)
105	.endm
106#endif
107