xtensa: add s32c1i-based bitops implementations
authorMax Filippov <jcmvbkbc@gmail.com>
Sun, 11 Nov 2012 01:47:25 +0000 (05:47 +0400)
committerChris Zankel <chris@zankel.net>
Wed, 19 Dec 2012 05:10:22 +0000 (21:10 -0800)
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
arch/xtensa/include/asm/bitops.h

index 5270197ddd369bd76771ab1f05a2c5bbb24563cb..84afe58d5d374bc7cc19f8d02dbcc279b3b0014a 100644 (file)
@@ -29,7 +29,6 @@
 #define smp_mb__before_clear_bit()     barrier()
 #define smp_mb__after_clear_bit()      barrier()
 
-#include <asm-generic/bitops/atomic.h>
 #include <asm-generic/bitops/non-atomic.h>
 
 #if XCHAL_HAVE_NSA
@@ -104,6 +103,132 @@ static inline unsigned long __fls(unsigned long word)
 #endif
 
 #include <asm-generic/bitops/fls64.h>
+
+#if XCHAL_HAVE_S32C1I
+
+static inline void set_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long tmp, value;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       __asm__ __volatile__(
+                       "1:     l32i    %1, %3, 0\n"
+                       "       wsr     %1, scompare1\n"
+                       "       or      %0, %1, %2\n"
+                       "       s32c1i  %0, %3, 0\n"
+                       "       bne     %0, %1, 1b\n"
+                       : "=&a" (tmp), "=&a" (value)
+                       : "a" (mask), "a" (p)
+                       : "memory");
+}
+
+static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long tmp, value;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       __asm__ __volatile__(
+                       "1:     l32i    %1, %3, 0\n"
+                       "       wsr     %1, scompare1\n"
+                       "       and     %0, %1, %2\n"
+                       "       s32c1i  %0, %3, 0\n"
+                       "       bne     %0, %1, 1b\n"
+                       : "=&a" (tmp), "=&a" (value)
+                       : "a" (~mask), "a" (p)
+                       : "memory");
+}
+
+static inline void change_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long tmp, value;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       __asm__ __volatile__(
+                       "1:     l32i    %1, %3, 0\n"
+                       "       wsr     %1, scompare1\n"
+                       "       xor     %0, %1, %2\n"
+                       "       s32c1i  %0, %3, 0\n"
+                       "       bne     %0, %1, 1b\n"
+                       : "=&a" (tmp), "=&a" (value)
+                       : "a" (mask), "a" (p)
+                       : "memory");
+}
+
+static inline int
+test_and_set_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long tmp, value;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       __asm__ __volatile__(
+                       "1:     l32i    %1, %3, 0\n"
+                       "       wsr     %1, scompare1\n"
+                       "       or      %0, %1, %2\n"
+                       "       s32c1i  %0, %3, 0\n"
+                       "       bne     %0, %1, 1b\n"
+                       : "=&a" (tmp), "=&a" (value)
+                       : "a" (mask), "a" (p)
+                       : "memory");
+
+       return tmp & mask;
+}
+
+static inline int
+test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long tmp, value;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       __asm__ __volatile__(
+                       "1:     l32i    %1, %3, 0\n"
+                       "       wsr     %1, scompare1\n"
+                       "       and     %0, %1, %2\n"
+                       "       s32c1i  %0, %3, 0\n"
+                       "       bne     %0, %1, 1b\n"
+                       : "=&a" (tmp), "=&a" (value)
+                       : "a" (~mask), "a" (p)
+                       : "memory");
+
+       return tmp & mask;
+}
+
+static inline int
+test_and_change_bit(unsigned int bit, volatile unsigned long *p)
+{
+       unsigned long tmp, value;
+       unsigned long mask = 1UL << (bit & 31);
+
+       p += bit >> 5;
+
+       __asm__ __volatile__(
+                       "1:     l32i    %1, %3, 0\n"
+                       "       wsr     %1, scompare1\n"
+                       "       xor     %0, %1, %2\n"
+                       "       s32c1i  %0, %3, 0\n"
+                       "       bne     %0, %1, 1b\n"
+                       : "=&a" (tmp), "=&a" (value)
+                       : "a" (mask), "a" (p)
+                       : "memory");
+
+       return tmp & mask;
+}
+
+#else
+
+#include <asm-generic/bitops/atomic.h>
+
+#endif /* XCHAL_HAVE_S32C1I */
+
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/le.h>