summaryrefslogtreecommitdiff
path: root/arch/mips/include/asm/bitops.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/include/asm/bitops.h')
-rw-r--r--arch/mips/include/asm/bitops.h58
1 files changed, 39 insertions, 19 deletions
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index dc2a6234dd3c..42f88452c920 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -16,14 +16,12 @@
#include <linux/bits.h>
#include <linux/compiler.h>
#include <linux/types.h>
+#include <asm/asm.h>
#include <asm/barrier.h>
#include <asm/byteorder.h> /* sigh ... */
#include <asm/compiler.h>
#include <asm/cpu-features.h>
-#include <asm/isa-rev.h>
-#include <asm/llsc.h>
#include <asm/sgidefs.h>
-#include <asm/war.h>
#define __bit_op(mem, insn, inputs...) do { \
unsigned long __temp; \
@@ -32,10 +30,10 @@
" .set push \n" \
" .set " MIPS_ISA_LEVEL " \n" \
" " __SYNC(full, loongson3_war) " \n" \
- "1: " __LL "%0, %1 \n" \
+ "1: " __stringify(LONG_LL) " %0, %1 \n" \
" " insn " \n" \
- " " __SC "%0, %1 \n" \
- " " __SC_BEQZ "%0, 1b \n" \
+ " " __stringify(LONG_SC) " %0, %1 \n" \
+ " " __stringify(SC_BEQZ) " %0, 1b \n" \
" .set pop \n" \
: "=&r"(__temp), "+" GCC_OFF_SMALL_ASM()(mem) \
: inputs \
@@ -49,10 +47,10 @@
" .set push \n" \
" .set " MIPS_ISA_LEVEL " \n" \
" " __SYNC(full, loongson3_war) " \n" \
- "1: " __LL ll_dst ", %2 \n" \
+ "1: " __stringify(LONG_LL) " " ll_dst ", %2\n" \
" " insn " \n" \
- " " __SC "%1, %2 \n" \
- " " __SC_BEQZ "%1, 1b \n" \
+ " " __stringify(LONG_SC) " %1, %2 \n" \
+ " " __stringify(SC_BEQZ) " %1, 1b \n" \
" .set pop \n" \
: "=&r"(__orig), "=&r"(__temp), \
"+" GCC_OFF_SMALL_ASM()(mem) \
@@ -75,7 +73,8 @@ int __mips_test_and_clear_bit(unsigned long nr,
volatile unsigned long *addr);
int __mips_test_and_change_bit(unsigned long nr,
volatile unsigned long *addr);
-
+bool __mips_xor_is_negative_byte(unsigned long mask,
+ volatile unsigned long *addr);
/*
* set_bit - Atomically set a bit in memory
@@ -98,7 +97,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
}
if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(bit) && (bit >= 16)) {
- __bit_op(*m, __INS "%0, %3, %2, 1", "i"(bit), "r"(~0));
+ __bit_op(*m, __stringify(LONG_INS) " %0, %3, %2, 1", "i"(bit), "r"(~0));
return;
}
@@ -126,7 +125,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
}
if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(bit)) {
- __bit_op(*m, __INS "%0, $0, %2, 1", "i"(bit));
+ __bit_op(*m, __stringify(LONG_INS) " %0, $0, %2, 1", "i"(bit));
return;
}
@@ -234,8 +233,8 @@ static inline int test_and_clear_bit(unsigned long nr,
res = __mips_test_and_clear_bit(nr, addr);
} else if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(nr)) {
res = __test_bit_op(*m, "%1",
- __EXT "%0, %1, %3, 1;"
- __INS "%1, $0, %3, 1",
+ __stringify(LONG_EXT) " %0, %1, %3, 1;"
+ __stringify(LONG_INS) " %1, $0, %3, 1",
"i"(bit));
} else {
orig = __test_bit_op(*m, "%0",
@@ -281,6 +280,28 @@ static inline int test_and_change_bit(unsigned long nr,
return res;
}
+static inline bool xor_unlock_is_negative_byte(unsigned long mask,
+ volatile unsigned long *p)
+{
+ unsigned long orig;
+ bool res;
+
+ smp_mb__before_atomic();
+
+ if (!kernel_uses_llsc) {
+ res = __mips_xor_is_negative_byte(mask, p);
+ } else {
+ orig = __test_bit_op(*p, "%0",
+ "xor\t%1, %0, %3",
+ "ir"(mask));
+ res = (orig & BIT(7)) != 0;
+ }
+
+ smp_llsc_mb();
+
+ return res;
+}
+
#undef __bit_op
#undef __test_bit_op
@@ -306,7 +327,7 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *
* Return the bit position (0..63) of the most significant 1 bit in a word
* Returns -1 if no 1 bit exists
*/
-static __always_inline unsigned long __fls(unsigned long word)
+static __always_inline __attribute_const__ unsigned long __fls(unsigned long word)
{
int num;
@@ -372,7 +393,7 @@ static __always_inline unsigned long __fls(unsigned long word)
* Returns 0..SZLONG-1
* Undefined if no bit exists, so code should check against 0 first.
*/
-static __always_inline unsigned long __ffs(unsigned long word)
+static __always_inline __attribute_const__ unsigned long __ffs(unsigned long word)
{
return __fls(word & -word);
}
@@ -384,7 +405,7 @@ static __always_inline unsigned long __ffs(unsigned long word)
* This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-static inline int fls(unsigned int x)
+static inline __attribute_const__ int fls(unsigned int x)
{
int r;
@@ -437,7 +458,7 @@ static inline int fls(unsigned int x)
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the below ffz (man ffs).
*/
-static inline int ffs(int word)
+static inline __attribute_const__ int ffs(int word)
{
if (!word)
return 0;
@@ -446,7 +467,6 @@ static inline int ffs(int word)
}
#include <asm-generic/bitops/ffz.h>
-#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__