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