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