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