From 4c7df2c778c8bf1e13ae2f1456425eb99c75d866 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sat, 2 Feb 2013 20:46:10 +0400 Subject: [PATCH] Fix unsupported instruction use in char/short_fetch_and_add for ARMv6 * 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 | 160 +++++++++++++++++-------------- 1 file changed, 86 insertions(+), 74 deletions(-) diff --git a/src/atomic_ops/sysdeps/gcc/arm.h b/src/atomic_ops/sysdeps/gcc/arm.h index 28bb94a..746f11b 100644 --- a/src/atomic_ops/sysdeps/gcc/arm.h +++ b/src/atomic_ops/sysdeps/gcc/arm.h @@ -49,6 +49,11 @@ && !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__) @@ -167,49 +172,54 @@ } # 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. */ -- 2.40.0