Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #include <asm/assembler.h>
0003 #include <asm/unwind.h>
0004 
0005 #if __LINUX_ARM_ARCH__ >= 6
0006     .macro  bitop, name, instr
0007 ENTRY(  \name       )
0008 UNWIND( .fnstart    )
0009     ands    ip, r1, #3
0010     strbne  r1, [ip]        @ assert word-aligned
0011     mov r2, #1
0012     and r3, r0, #31     @ Get bit offset
0013     mov r0, r0, lsr #5
0014     add r1, r1, r0, lsl #2  @ Get word offset
0015 #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
0016     .arch_extension mp
0017     ALT_SMP(W(pldw) [r1])
0018     ALT_UP(W(nop))
0019 #endif
0020     mov r3, r2, lsl r3
0021 1:  ldrex   r2, [r1]
0022     \instr  r2, r2, r3
0023     strex   r0, r2, [r1]
0024     cmp r0, #0
0025     bne 1b
0026     bx  lr
0027 UNWIND( .fnend      )
0028 ENDPROC(\name       )
0029     .endm
0030 
0031     .macro  testop, name, instr, store
0032 ENTRY(  \name       )
0033 UNWIND( .fnstart    )
0034     ands    ip, r1, #3
0035     strbne  r1, [ip]        @ assert word-aligned
0036     mov r2, #1
0037     and r3, r0, #31     @ Get bit offset
0038     mov r0, r0, lsr #5
0039     add r1, r1, r0, lsl #2  @ Get word offset
0040     mov r3, r2, lsl r3      @ create mask
0041     smp_dmb
0042 #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
0043     .arch_extension mp
0044     ALT_SMP(W(pldw) [r1])
0045     ALT_UP(W(nop))
0046 #endif
0047 1:  ldrex   r2, [r1]
0048     ands    r0, r2, r3      @ save old value of bit
0049     \instr  r2, r2, r3      @ toggle bit
0050     strex   ip, r2, [r1]
0051     cmp ip, #0
0052     bne 1b
0053     smp_dmb
0054     cmp r0, #0
0055     movne   r0, #1
0056 2:  bx  lr
0057 UNWIND( .fnend      )
0058 ENDPROC(\name       )
0059     .endm
0060 #else
0061     .macro  bitop, name, instr
0062 ENTRY(  \name       )
0063 UNWIND( .fnstart    )
0064     ands    ip, r1, #3
0065     strbne  r1, [ip]        @ assert word-aligned
0066     and r2, r0, #31
0067     mov r0, r0, lsr #5
0068     mov r3, #1
0069     mov r3, r3, lsl r2
0070     save_and_disable_irqs ip
0071     ldr r2, [r1, r0, lsl #2]
0072     \instr  r2, r2, r3
0073     str r2, [r1, r0, lsl #2]
0074     restore_irqs ip
0075     ret lr
0076 UNWIND( .fnend      )
0077 ENDPROC(\name       )
0078     .endm
0079 
0080 /**
0081  * testop - implement a test_and_xxx_bit operation.
0082  * @instr: operational instruction
0083  * @store: store instruction
0084  *
0085  * Note: we can trivially conditionalise the store instruction
0086  * to avoid dirtying the data cache.
0087  */
0088     .macro  testop, name, instr, store
0089 ENTRY(  \name       )
0090 UNWIND( .fnstart    )
0091     ands    ip, r1, #3
0092     strbne  r1, [ip]        @ assert word-aligned
0093     and r3, r0, #31
0094     mov r0, r0, lsr #5
0095     save_and_disable_irqs ip
0096     ldr r2, [r1, r0, lsl #2]!
0097     mov r0, #1
0098     tst r2, r0, lsl r3
0099     \instr  r2, r2, r0, lsl r3
0100     \store  r2, [r1]
0101     moveq   r0, #0
0102     restore_irqs ip
0103     ret lr
0104 UNWIND( .fnend      )
0105 ENDPROC(\name       )
0106     .endm
0107 #endif