#include <asm/asi.h>
.text
- .align 64
- .globl __bitops_begin
-__bitops_begin:
- .globl ___test_and_set_bit
-___test_and_set_bit: /* %o0=nr, %o1=addr */
+ /* On SMP we need to use memory barriers to ensure
+ * correct memory operation ordering, nop these out
+ * for uniprocessor.
+ */
+
+#ifdef CONFIG_SMP
+#define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad
+#define BITOP_POST_BARRIER \
+ ba,pt %xcc, 80b; \
+ membar #StoreLoad | #StoreStore
+
+80: retl
+ nop
+#else
+#define BITOP_PRE_BARRIER
+#define BITOP_POST_BARRIER
+#endif
+
+ .globl test_and_set_bit
+ .type test_and_set_bit,#function
+test_and_set_bit: /* %o0=nr, %o1=addr */
+ BITOP_PRE_BARRIER
srlx %o0, 6, %g1
- mov 1, %g5
+ mov 1, %o2
sllx %g1, 3, %g3
and %o0, 63, %g2
- sllx %g5, %g2, %g5
+ sllx %o2, %g2, %o2
add %o1, %g3, %o1
- ldx [%o1], %g7
-1: andcc %g7, %g5, %o0
- bne,pn %xcc, 2f
- xor %g7, %g5, %g1
+1: ldx [%o1], %g7
+ or %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,a,pn %xcc, 1b
- ldx [%o1], %g7
-2: retl
- membar #StoreLoad | #StoreStore
+ bne,pn %xcc, 1b
+ and %g7, %o2, %g2
+ clr %o0
+ movrne %g2, 1, %o0
+ BITOP_POST_BARRIER
+ retl
+ nop
+ .size test_and_set_bit, .-test_and_set_bit
- .globl ___test_and_clear_bit
-___test_and_clear_bit: /* %o0=nr, %o1=addr */
+ .globl test_and_clear_bit
+ .type test_and_clear_bit,#function
+test_and_clear_bit: /* %o0=nr, %o1=addr */
+ BITOP_PRE_BARRIER
srlx %o0, 6, %g1
- mov 1, %g5
+ mov 1, %o2
sllx %g1, 3, %g3
and %o0, 63, %g2
- sllx %g5, %g2, %g5
+ sllx %o2, %g2, %o2
add %o1, %g3, %o1
- ldx [%o1], %g7
-1: andcc %g7, %g5, %o0
- be,pn %xcc, 2f
- xor %g7, %g5, %g1
+1: ldx [%o1], %g7
+ andn %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,a,pn %xcc, 1b
- ldx [%o1], %g7
-2: retl
- membar #StoreLoad | #StoreStore
+ bne,pn %xcc, 1b
+ and %g7, %o2, %g2
+ clr %o0
+ movrne %g2, 1, %o0
+ BITOP_POST_BARRIER
+ retl
+ nop
+ .size test_and_clear_bit, .-test_and_clear_bit
- .globl ___test_and_change_bit
-___test_and_change_bit: /* %o0=nr, %o1=addr */
+ .globl test_and_change_bit
+ .type test_and_change_bit,#function
+test_and_change_bit: /* %o0=nr, %o1=addr */
+ BITOP_PRE_BARRIER
srlx %o0, 6, %g1
- mov 1, %g5
+ mov 1, %o2
sllx %g1, 3, %g3
and %o0, 63, %g2
- sllx %g5, %g2, %g5
+ sllx %o2, %g2, %o2
add %o1, %g3, %o1
- ldx [%o1], %g7
-1: and %g7, %g5, %o0
- xor %g7, %g5, %g1
+1: ldx [%o1], %g7
+ xor %g7, %o2, %g1
casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,a,pn %xcc, 1b
- ldx [%o1], %g7
-2: retl
- membar #StoreLoad | #StoreStore
- nop
+ bne,pn %xcc, 1b
+ and %g7, %o2, %g2
+ clr %o0
+ movrne %g2, 1, %o0
+ BITOP_POST_BARRIER
+ retl
+ nop
+ .size test_and_change_bit, .-test_and_change_bit
- .globl ___test_and_set_le_bit
-___test_and_set_le_bit: /* %o0=nr, %o1=addr */
- srlx %o0, 5, %g1
- mov 1, %g5
- sllx %g1, 2, %g3
- and %o0, 31, %g2
- sllx %g5, %g2, %g5
+ .globl set_bit
+ .type set_bit,#function
+set_bit: /* %o0=nr, %o1=addr */
+ srlx %o0, 6, %g1
+ mov 1, %o2
+ sllx %g1, 3, %g3
+ and %o0, 63, %g2
+ sllx %o2, %g2, %o2
add %o1, %g3, %o1
- lduwa [%o1] ASI_PL, %g7
-1: andcc %g7, %g5, %o0
- bne,pn %icc, 2f
- xor %g7, %g5, %g1
- casa [%o1] ASI_PL, %g7, %g1
+1: ldx [%o1], %g7
+ or %g7, %o2, %g1
+ casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,a,pn %icc, 1b
- lduwa [%o1] ASI_PL, %g7
-2: retl
- membar #StoreLoad | #StoreStore
+ bne,pn %xcc, 1b
+ nop
+ retl
+ nop
+ .size set_bit, .-set_bit
- .globl ___test_and_clear_le_bit
-___test_and_clear_le_bit: /* %o0=nr, %o1=addr */
- srlx %o0, 5, %g1
- mov 1, %g5
- sllx %g1, 2, %g3
- and %o0, 31, %g2
- sllx %g5, %g2, %g5
+ .globl clear_bit
+ .type clear_bit,#function
+clear_bit: /* %o0=nr, %o1=addr */
+ srlx %o0, 6, %g1
+ mov 1, %o2
+ sllx %g1, 3, %g3
+ and %o0, 63, %g2
+ sllx %o2, %g2, %o2
add %o1, %g3, %o1
- lduwa [%o1] ASI_PL, %g7
-1: andcc %g7, %g5, %o0
- be,pn %icc, 2f
- xor %g7, %g5, %g1
- casa [%o1] ASI_PL, %g7, %g1
+1: ldx [%o1], %g7
+ andn %g7, %o2, %g1
+ casx [%o1], %g7, %g1
cmp %g7, %g1
- bne,a,pn %icc, 1b
- lduwa [%o1] ASI_PL, %g7
-2: retl
- membar #StoreLoad | #StoreStore
+ bne,pn %xcc, 1b
+ nop
+ retl
+ nop
+ .size clear_bit, .-clear_bit
- .globl __bitops_end
-__bitops_end:
+ .globl change_bit
+ .type change_bit,#function
+change_bit: /* %o0=nr, %o1=addr */
+ srlx %o0, 6, %g1
+ mov 1, %o2
+ sllx %g1, 3, %g3
+ and %o0, 63, %g2
+ sllx %o2, %g2, %o2
+ add %o1, %g3, %o1
+1: ldx [%o1], %g7
+ xor %g7, %o2, %g1
+ casx [%o1], %g7, %g1
+ cmp %g7, %g1
+ bne,pn %xcc, 1b
+ nop
+ retl
+ nop
+ .size change_bit, .-change_bit