]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - include/asm-mips/bitops.h
[MIPS] Fix struct sigcontext for N32 userland
[linux-2.6-omap-h63xx.git] / include / asm-mips / bitops.h
index 06445de1324bd3c058a507d08d0c747d6ab571ae..89436b96ad66ea9953309aa5ef8ba4560b03584b 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1994 - 1997, 1999, 2000, 06  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (c) 1994 - 1997, 99, 2000, 06, 07  Ralf Baechle (ralf@linux-mips.org)
  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
  */
 #ifndef _ASM_BITOPS_H
 #define SZLONG_MASK 31UL
 #define __LL           "ll     "
 #define __SC           "sc     "
+#define __INS          "ins    "
+#define __EXT          "ext    "
 #elif (_MIPS_SZLONG == 64)
 #define SZLONG_LOG 6
 #define SZLONG_MASK 63UL
 #define __LL           "lld    "
 #define __SC           "scd    "
+#define __INS          "dins    "
+#define __EXT          "dext    "
 #endif
 
 /*
@@ -62,13 +66,29 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
+#ifdef CONFIG_CPU_MIPSR2
+       } else if (__builtin_constant_p(nr)) {
+               __asm__ __volatile__(
+               "1:     " __LL "%0, %1                  # set_bit       \n"
+               "       " __INS "%0, %4, %2, 1                          \n"
+               "       " __SC "%0, %1                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
+               : "=&r" (temp), "=m" (*m)
+               : "ir" (nr & SZLONG_MASK), "m" (*m), "r" (~0));
+#endif /* CONFIG_CPU_MIPSR2 */
        } else if (cpu_has_llsc) {
                __asm__ __volatile__(
                "       .set    mips3                                   \n"
                "1:     " __LL "%0, %1                  # set_bit       \n"
                "       or      %0, %2                                  \n"
                "       " __SC  "%0, %1                                 \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
@@ -110,13 +130,29 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
+#ifdef CONFIG_CPU_MIPSR2
+       } else if (__builtin_constant_p(nr)) {
+               __asm__ __volatile__(
+               "1:     " __LL "%0, %1                  # clear_bit     \n"
+               "       " __INS "%0, $0, %2, 1                          \n"
+               "       " __SC "%0, %1                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
+               : "=&r" (temp), "=m" (*m)
+               : "ir" (nr & SZLONG_MASK), "m" (*m));
+#endif /* CONFIG_CPU_MIPSR2 */
        } else if (cpu_has_llsc) {
                __asm__ __volatile__(
                "       .set    mips3                                   \n"
                "1:     " __LL "%0, %1                  # clear_bit     \n"
                "       and     %0, %2                                  \n"
                "       " __SC "%0, %1                                  \n"
-               "       beqz    %0, 1b                                  \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
                "       .set    mips0                                   \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
@@ -166,7 +202,10 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                "1:     " __LL "%0, %1          # change_bit    \n"
                "       xor     %0, %2                          \n"
                "       " __SC  "%0, %1                         \n"
-               "       beqz    %0, 1b                          \n"
+               "       beqz    %0, 2f                          \n"
+               "       .subsection 2                           \n"
+               "2:     b       1b                              \n"
+               "       .previous                               \n"
                "       .set    mips0                           \n"
                : "=&r" (temp), "=m" (*m)
                : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
@@ -222,8 +261,12 @@ static inline int test_and_set_bit(unsigned long nr,
                "1:     " __LL "%0, %1          # test_and_set_bit      \n"
                "       or      %2, %0, %3                              \n"
                "       " __SC  "%2, %1                                 \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        and    %2, %0, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
                : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -278,6 +321,26 @@ static inline int test_and_clear_bit(unsigned long nr,
                : "memory");
 
                return res != 0;
+#ifdef CONFIG_CPU_MIPSR2
+       } else if (__builtin_constant_p(nr)) {
+               unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
+               unsigned long temp, res;
+
+               __asm__ __volatile__(
+               "1:     " __LL  "%0, %1         # test_and_clear_bit    \n"
+               "       " __EXT "%2, %0, %3, 1                          \n"
+               "       " __INS "%0, $0, %3, 1                          \n"
+               "       " __SC  "%0, %1                                 \n"
+               "       beqz    %0, 2f                                  \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "       .previous                                       \n"
+               : "=&r" (temp), "=m" (*m), "=&r" (res)
+               : "ri" (nr & SZLONG_MASK), "m" (*m)
+               : "memory");
+
+               return res;
+#endif
        } else if (cpu_has_llsc) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp, res;
@@ -290,8 +353,12 @@ static inline int test_and_clear_bit(unsigned long nr,
                "       or      %2, %0, %3                              \n"
                "       xor     %2, %3                                  \n"
                "       " __SC  "%2, %1                                 \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        and    %2, %0, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
                : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -356,8 +423,12 @@ static inline int test_and_change_bit(unsigned long nr,
                "1:     " __LL  "%0, %1         # test_and_change_bit   \n"
                "       xor     %2, %0, %3                              \n"
                "       " __SC  "\t%2, %1                               \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        and    %2, %0, %3                              \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    pop                                     \n"
                : "=&r" (temp), "=m" (*m), "=&r" (res)
                : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)