mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.1 KiB
107 lines
2.1 KiB
/* SPDX-License-Identifier: GPL-2.0 */ |
|
#include <asm/assembler.h> |
|
#include <asm/unwind.h> |
|
|
|
#if __LINUX_ARM_ARCH__ >= 6 |
|
.macro bitop, name, instr |
|
ENTRY( \name ) |
|
UNWIND( .fnstart ) |
|
ands ip, r1, #3 |
|
strbne r1, [ip] @ assert word-aligned |
|
mov r2, #1 |
|
and r3, r0, #31 @ Get bit offset |
|
mov r0, r0, lsr #5 |
|
add r1, r1, r0, lsl #2 @ Get word offset |
|
#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) |
|
.arch_extension mp |
|
ALT_SMP(W(pldw) [r1]) |
|
ALT_UP(W(nop)) |
|
#endif |
|
mov r3, r2, lsl r3 |
|
1: ldrex r2, [r1] |
|
\instr r2, r2, r3 |
|
strex r0, r2, [r1] |
|
cmp r0, #0 |
|
bne 1b |
|
bx lr |
|
UNWIND( .fnend ) |
|
ENDPROC(\name ) |
|
.endm |
|
|
|
.macro testop, name, instr, store |
|
ENTRY( \name ) |
|
UNWIND( .fnstart ) |
|
ands ip, r1, #3 |
|
strbne r1, [ip] @ assert word-aligned |
|
mov r2, #1 |
|
and r3, r0, #31 @ Get bit offset |
|
mov r0, r0, lsr #5 |
|
add r1, r1, r0, lsl #2 @ Get word offset |
|
mov r3, r2, lsl r3 @ create mask |
|
smp_dmb |
|
#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) |
|
.arch_extension mp |
|
ALT_SMP(W(pldw) [r1]) |
|
ALT_UP(W(nop)) |
|
#endif |
|
1: ldrex r2, [r1] |
|
ands r0, r2, r3 @ save old value of bit |
|
\instr r2, r2, r3 @ toggle bit |
|
strex ip, r2, [r1] |
|
cmp ip, #0 |
|
bne 1b |
|
smp_dmb |
|
cmp r0, #0 |
|
movne r0, #1 |
|
2: bx lr |
|
UNWIND( .fnend ) |
|
ENDPROC(\name ) |
|
.endm |
|
#else |
|
.macro bitop, name, instr |
|
ENTRY( \name ) |
|
UNWIND( .fnstart ) |
|
ands ip, r1, #3 |
|
strbne r1, [ip] @ assert word-aligned |
|
and r2, r0, #31 |
|
mov r0, r0, lsr #5 |
|
mov r3, #1 |
|
mov r3, r3, lsl r2 |
|
save_and_disable_irqs ip |
|
ldr r2, [r1, r0, lsl #2] |
|
\instr r2, r2, r3 |
|
str r2, [r1, r0, lsl #2] |
|
restore_irqs ip |
|
ret lr |
|
UNWIND( .fnend ) |
|
ENDPROC(\name ) |
|
.endm |
|
|
|
/** |
|
* testop - implement a test_and_xxx_bit operation. |
|
* @instr: operational instruction |
|
* @store: store instruction |
|
* |
|
* Note: we can trivially conditionalise the store instruction |
|
* to avoid dirtying the data cache. |
|
*/ |
|
.macro testop, name, instr, store |
|
ENTRY( \name ) |
|
UNWIND( .fnstart ) |
|
ands ip, r1, #3 |
|
strbne r1, [ip] @ assert word-aligned |
|
and r3, r0, #31 |
|
mov r0, r0, lsr #5 |
|
save_and_disable_irqs ip |
|
ldr r2, [r1, r0, lsl #2]! |
|
mov r0, #1 |
|
tst r2, r0, lsl r3 |
|
\instr r2, r2, r0, lsl r3 |
|
\store r2, [r1] |
|
moveq r0, #0 |
|
restore_irqs ip |
|
ret lr |
|
UNWIND( .fnend ) |
|
ENDPROC(\name ) |
|
.endm |
|
#endif
|
|
|