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