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