2011-11-23 14:28:25 +04:00
# include <asm/unwind.h>
2011-01-16 21:02:17 +03:00
# if __LINUX_ARM_ARCH__ >= 6
2011-11-23 14:28:25 +04:00
. macro bitop , name , instr
ENTRY ( \ name )
UNWIND ( . fnstart )
2011-01-16 20:59:44 +03:00
ands ip , r1 , # 3
strneb r1 , [ ip ] @ assert word - aligned
2005-07-16 18:21:51 +04:00
mov r2 , # 1
2011-01-16 21:02:17 +03:00
and r3 , r0 , # 31 @ Get bit offset
mov r0 , r0 , lsr # 5
add r1 , r1 , r0 , lsl # 2 @ Get word offset
2005-07-16 18:21:51 +04:00
mov r3 , r2 , lsl r3
2011-01-16 21:02:17 +03:00
1 : ldrex r2 , [ r1 ]
2005-07-16 18:21:51 +04:00
\ instr r2 , r2 , r3
2011-01-16 21:02:17 +03:00
strex r0 , r2 , [ r1 ]
2005-07-28 23:36:26 +04:00
cmp r0 , # 0
2005-07-16 18:21:51 +04:00
bne 1 b
2011-02-08 14:09:52 +03:00
bx lr
2011-11-23 14:28:25 +04:00
UNWIND ( . fnend )
ENDPROC ( \ name )
2005-07-16 18:21:51 +04:00
. endm
2011-11-23 14:28:25 +04:00
. macro testop , name , instr , store
ENTRY ( \ name )
UNWIND ( . fnstart )
2011-01-16 20:59:44 +03:00
ands ip , r1 , # 3
strneb r1 , [ ip ] @ assert word - aligned
2005-07-16 18:21:51 +04:00
mov r2 , # 1
2011-01-16 21:02:17 +03:00
and r3 , r0 , # 31 @ Get bit offset
mov r0 , r0 , lsr # 5
add r1 , r1 , r0 , lsl # 2 @ Get word offset
2005-07-16 18:21:51 +04:00
mov r3 , r2 , lsl r3 @ create mask
2009-05-25 23:58:00 +04:00
smp_dmb
2011-01-16 21:02:17 +03:00
1 : ldrex r2 , [ r1 ]
2005-07-16 18:21:51 +04:00
ands r0 , r2 , r3 @ save old value of bit
2011-01-16 21:02:17 +03:00
\ instr r2 , r2 , r3 @ toggle bit
strex ip , r2 , [ r1 ]
2005-07-28 02:00:05 +04:00
cmp ip , # 0
2005-07-16 18:21:51 +04:00
bne 1 b
2009-05-25 23:58:00 +04:00
smp_dmb
2005-07-16 18:21:51 +04:00
cmp r0 , # 0
movne r0 , # 1
2011-02-08 14:09:52 +03:00
2 : bx lr
2011-11-23 14:28:25 +04:00
UNWIND ( . fnend )
ENDPROC ( \ name )
2005-07-16 18:21:51 +04:00
. endm
# else
2011-11-23 14:28:25 +04:00
. macro bitop , name , instr
ENTRY ( \ name )
UNWIND ( . fnstart )
2011-01-16 20:59:44 +03:00
ands ip , r1 , # 3
strneb r1 , [ ip ] @ assert word - aligned
2011-01-16 21:02:17 +03:00
and r2 , r0 , # 31
mov r0 , r0 , lsr # 5
2005-04-19 01:50:01 +04:00
mov r3 , # 1
mov r3 , r3 , lsl r2
2005-11-09 18:04:22 +03:00
save_and_disable_irqs ip
2011-01-16 21:02:17 +03:00
ldr r2 , [ r1 , r0 , lsl # 2 ]
2005-04-19 01:50:01 +04:00
\ instr r2 , r2 , r3
2011-01-16 21:02:17 +03:00
str r2 , [ r1 , r0 , lsl # 2 ]
2005-04-19 01:50:01 +04:00
restore_irqs ip
mov pc , lr
2011-11-23 14:28:25 +04:00
UNWIND ( . fnend )
ENDPROC ( \ name )
2005-04-19 01:50:01 +04:00
. endm
/**
* testop - implement a test_and_xxx_bit operation .
* @ instr : operational instruction
* @ store : store instruction
*
* Note : we can trivially conditionalise the store instruction
2007-05-11 23:40:30 +04:00
* to avoid dirtying the data cache .
2005-04-19 01:50:01 +04:00
*/
2011-11-23 14:28:25 +04:00
. macro testop , name , instr , store
ENTRY ( \ name )
UNWIND ( . fnstart )
2011-01-16 20:59:44 +03:00
ands ip , r1 , # 3
strneb r1 , [ ip ] @ assert word - aligned
2011-01-16 21:02:17 +03:00
and r3 , r0 , # 31
mov r0 , r0 , lsr # 5
2005-11-09 18:04:22 +03:00
save_and_disable_irqs ip
2011-01-16 21:02:17 +03:00
ldr r2 , [ r1 , r0 , lsl # 2 ] !
mov r0 , # 1
2005-04-19 01:50:01 +04:00
tst r2 , r0 , lsl r3
\ instr r2 , r2 , r0 , lsl r3
\ store r2 , [ r1 ]
moveq r0 , # 0
2009-08-13 22:38:17 +04:00
restore_irqs ip
2005-04-19 01:50:01 +04:00
mov pc , lr
2011-11-23 14:28:25 +04:00
UNWIND ( . fnend )
ENDPROC ( \ name )
2005-04-19 01:50:01 +04:00
. endm
2005-07-16 18:21:51 +04:00
# endif