]> granicus.if.org Git - libatomic_ops/commitdiff
Fix unsupported instruction use in char/short_fetch_and_add for ARMv6
authorIvan Maidanski <ivmai@mail.ru>
Sat, 2 Feb 2013 16:46:10 +0000 (20:46 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 2 Feb 2013 16:46:10 +0000 (20:46 +0400)
* src/atomic_ops/sysdeps/gcc/arm.h (AO_ARM_HAVE_LDREXBH): Define new
macro for ARMv6K/Z+ (excluding ARMv6, ARMv6J, ARMv6T2).
* src/atomic_ops/sysdeps/gcc/arm.h (AO_char_store, AO_short_store,
AO_char_fetch_and_add, AO_short_fetch_and_add): Define (together with
the corresponding AO_HAVE_x macros) only if AO_ARM_HAVE_LDREXBH (since
otherwise LDREXB/STREXB, LDREXH/STREXH are not supported by the target
processor).
* src/atomic_ops/sysdeps/gcc/arm.h: Include char_atomic_store.h and
short_atomic_store.h only if AO_HAVE_char_store is not defined (by
gcc/arm.h itself).

src/atomic_ops/sysdeps/gcc/arm.h

index 28bb94ad0510477ffc59095e2aa4637d696d8d57..746f11bfbe1c86f0565635d94f700f2730ba9192 100644 (file)
          && !defined(__ARM_ARCH_5TEJ__) && !defined(__ARM_ARCH_6M__)) \
         || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__))
 # define AO_ARM_HAVE_LDREX
+# if !defined(__ARM_ARCH_6__) && !defined(__ARM_ARCH_6J__) \
+     && !defined(__ARM_ARCH_6T2__)
+    /* LDREXB/STREXB and LDREXH/STREXH are present in ARMv6K/Z+.        */
+#   define AO_ARM_HAVE_LDREXBH
+# endif
 # if !defined(__ARM_ARCH_6__) && !defined(__ARM_ARCH_6J__) \
      && !defined(__ARM_ARCH_6T2__) && !defined(__ARM_ARCH_6Z__) \
      && !defined(__ARM_ARCH_6ZT2__)
     }
 #   define AO_HAVE_store
 
-    AO_INLINE void AO_char_store(volatile unsigned char *addr,
-                                 unsigned char value)
-    {
-      int flag;
+#   ifdef AO_ARM_HAVE_LDREXBH
+      AO_INLINE void AO_char_store(volatile unsigned char *addr,
+                                   unsigned char value)
+      {
+        int flag;
 
-      __asm__ __volatile__("@AO_char_store\n"
-        AO_THUMB_GO_ARM
-        "1:     ldrexb %0, [%2]\n"
-        "       strexb %0, %3, [%2]\n"
-        "       teq    %0, #0\n"
-        "       bne 1b\n"
-        AO_THUMB_RESTORE_MODE
-        : "=&r" (flag), "+m" (*addr)
-        : "r" (addr), "r" (value)
-        : AO_THUMB_SWITCH_CLOBBERS "cc");
-    }
-#   define AO_HAVE_char_store
-
-    AO_INLINE void AO_short_store(volatile unsigned short *addr,
-                                  unsigned short value)
-    {
-      int flag;
-
-      __asm__ __volatile__("@AO_short_store\n"
-        AO_THUMB_GO_ARM
-        "1:     ldrexh %0, [%2]\n"
-        "       strexh %0, %3, [%2]\n"
-        "       teq    %0, #0\n"
-        "       bne 1b\n"
-        AO_THUMB_RESTORE_MODE
-        : "=&r" (flag), "+m" (*addr)
-        : "r" (addr), "r" (value)
-        : AO_THUMB_SWITCH_CLOBBERS "cc");
-    }
-#   define AO_HAVE_short_store
+        __asm__ __volatile__("@AO_char_store\n"
+          AO_THUMB_GO_ARM
+          "1:     ldrexb %0, [%2]\n"
+          "       strexb %0, %3, [%2]\n"
+          "       teq    %0, #0\n"
+          "       bne 1b\n"
+          AO_THUMB_RESTORE_MODE
+          : "=&r" (flag), "+m" (*addr)
+          : "r" (addr), "r" (value)
+          : AO_THUMB_SWITCH_CLOBBERS "cc");
+      }
+#     define AO_HAVE_char_store
+
+      AO_INLINE void AO_short_store(volatile unsigned short *addr,
+                                    unsigned short value)
+      {
+        int flag;
+
+        __asm__ __volatile__("@AO_short_store\n"
+          AO_THUMB_GO_ARM
+          "1:     ldrexh %0, [%2]\n"
+          "       strexh %0, %3, [%2]\n"
+          "       teq    %0, #0\n"
+          "       bne 1b\n"
+          AO_THUMB_RESTORE_MODE
+          : "=&r" (flag), "+m" (*addr)
+          : "r" (addr), "r" (value)
+          : AO_THUMB_SWITCH_CLOBBERS "cc");
+      }
+#     define AO_HAVE_short_store
+#   endif /* AO_ARM_HAVE_LDREXBH */
 
 # else
 #   include "../loadstore/atomic_store.h"
-#   include "../loadstore/char_atomic_store.h"
-#   include "../loadstore/short_atomic_store.h"
     /* AO_int_store is defined in ao_t_is_int.h.    */
 # endif /* !AO_BROKEN_TASKSWITCH_CLREX */
 
+# ifndef AO_HAVE_char_store
+#   include "../loadstore/char_atomic_store.h"
+#   include "../loadstore/short_atomic_store.h"
+# endif
+
 /* NEC LE-IT: replace the SWAP as recommended by ARM:
    "Applies to: ARM11 Cores
       Though the SWP instruction will still work with ARM V6 cores, it is
@@ -313,47 +323,49 @@ AO_fetch_and_sub1(volatile AO_t *p)
 #define AO_HAVE_fetch_and_sub1
 #endif /* !AO_PREFER_GENERALIZED */
 
-AO_INLINE unsigned char
-AO_char_fetch_and_add(volatile unsigned char *p, unsigned char incr)
-{
-  unsigned char result, tmp;
-  int flag;
+#ifdef AO_ARM_HAVE_LDREXBH
+  AO_INLINE unsigned char
+  AO_char_fetch_and_add(volatile unsigned char *p, unsigned char incr)
+  {
+    unsigned char result, tmp;
+    int flag;
 
-  __asm__ __volatile__("@AO_char_fetch_and_add\n"
-    AO_THUMB_GO_ARM
-    "1:     ldrexb  %0, [%5]\n"
-    "       add     %2, %0, %4\n"
-    "       strexb  %1, %2, [%5]\n"
-    "       teq     %1, #0\n"
-    "       bne     1b\n"
-    AO_THUMB_RESTORE_MODE
-    : "=&r" (result), "=&r" (flag), "=&r" (tmp), "+m" (*p)
-    : "r" (incr), "r" (p)
-    : AO_THUMB_SWITCH_CLOBBERS "cc");
-  return result;
-}
-#define AO_HAVE_char_fetch_and_add
+    __asm__ __volatile__("@AO_char_fetch_and_add\n"
+      AO_THUMB_GO_ARM
+      "1:     ldrexb  %0, [%5]\n"
+      "       add     %2, %0, %4\n"
+      "       strexb  %1, %2, [%5]\n"
+      "       teq     %1, #0\n"
+      "       bne     1b\n"
+      AO_THUMB_RESTORE_MODE
+      : "=&r" (result), "=&r" (flag), "=&r" (tmp), "+m" (*p)
+      : "r" (incr), "r" (p)
+      : AO_THUMB_SWITCH_CLOBBERS "cc");
+    return result;
+  }
+# define AO_HAVE_char_fetch_and_add
 
-AO_INLINE unsigned short
-AO_short_fetch_and_add(volatile unsigned short *p, unsigned short incr)
-{
-  unsigned short result, tmp;
-  int flag;
+  AO_INLINE unsigned short
+  AO_short_fetch_and_add(volatile unsigned short *p, unsigned short incr)
+  {
+    unsigned short result, tmp;
+    int flag;
 
-  __asm__ __volatile__("@AO_short_fetch_and_add\n"
-    AO_THUMB_GO_ARM
-    "1:     ldrexh  %0, [%5]\n"
-    "       add     %2, %0, %4\n"
-    "       strexh  %1, %2, [%5]\n"
-    "       teq     %1, #0\n"
-    "       bne     1b\n"
-    AO_THUMB_RESTORE_MODE
-    : "=&r" (result), "=&r" (flag), "=&r" (tmp), "+m" (*p)
-    : "r" (incr), "r" (p)
-    : AO_THUMB_SWITCH_CLOBBERS "cc");
-  return result;
-}
-#define AO_HAVE_short_fetch_and_add
+    __asm__ __volatile__("@AO_short_fetch_and_add\n"
+      AO_THUMB_GO_ARM
+      "1:     ldrexh  %0, [%5]\n"
+      "       add     %2, %0, %4\n"
+      "       strexh  %1, %2, [%5]\n"
+      "       teq     %1, #0\n"
+      "       bne     1b\n"
+      AO_THUMB_RESTORE_MODE
+      : "=&r" (result), "=&r" (flag), "=&r" (tmp), "+m" (*p)
+      : "r" (incr), "r" (p)
+      : AO_THUMB_SWITCH_CLOBBERS "cc");
+    return result;
+  }
+# define AO_HAVE_short_fetch_and_add
+#endif /* AO_ARM_HAVE_LDREXBH */
 
 #ifndef AO_GENERALIZE_ASM_BOOL_CAS
   /* Returns nonzero if the comparison succeeded.       */