musl/arch/arm/atomic_arch.h
Rich Felker 980f80f792 fix build failure on arm building C code in thumb1 mode
a fully thumb1 build is not supported because some asm files are
incompatible with thumb1, but apparently it works to compile the C
code as thumb1

commit 06fbefd100 caused this regression
but introducing use of the clz instruction, which is not supported in
arm mode prior to v5, and not supported in thumb prior to thumb2
(v6t2). commit 1b9406b03c fixed the
issue only for arm mode pre-v5 but left thumb1 broken.
2019-07-15 15:33:12 -04:00

108 lines
2.1 KiB
C

#include "libc.h"
#if __ARM_ARCH_4__ || __ARM_ARCH_4T__ || __ARM_ARCH == 4
#define BLX "mov lr,pc\n\tbx"
#else
#define BLX "blx"
#endif
extern hidden uintptr_t __a_cas_ptr, __a_barrier_ptr;
#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
|| __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
#define a_ll a_ll
static inline int a_ll(volatile int *p)
{
int v;
__asm__ __volatile__ ("ldrex %0, %1" : "=r"(v) : "Q"(*p));
return v;
}
#define a_sc a_sc
static inline int a_sc(volatile int *p, int v)
{
int r;
__asm__ __volatile__ ("strex %0,%2,%1" : "=&r"(r), "=Q"(*p) : "r"(v) : "memory");
return !r;
}
#if __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
#define a_barrier a_barrier
static inline void a_barrier()
{
__asm__ __volatile__ ("dmb ish" : : : "memory");
}
#endif
#define a_pre_llsc a_barrier
#define a_post_llsc a_barrier
#else
#define a_cas a_cas
static inline int a_cas(volatile int *p, int t, int s)
{
for (;;) {
register int r0 __asm__("r0") = t;
register int r1 __asm__("r1") = s;
register volatile int *r2 __asm__("r2") = p;
register uintptr_t r3 __asm__("r3") = __a_cas_ptr;
int old;
__asm__ __volatile__ (
BLX " r3"
: "+r"(r0), "+r"(r3) : "r"(r1), "r"(r2)
: "memory", "lr", "ip", "cc" );
if (!r0) return t;
if ((old=*p)!=t) return old;
}
}
#endif
#ifndef a_barrier
#define a_barrier a_barrier
static inline void a_barrier()
{
register uintptr_t ip __asm__("ip") = __a_barrier_ptr;
__asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
}
#endif
#define a_crash a_crash
static inline void a_crash()
{
__asm__ __volatile__(
#ifndef __thumb__
".word 0xe7f000f0"
#else
".short 0xdeff"
#endif
: : : "memory");
}
#if __ARM_ARCH >= 5 && (!__thumb__ || __thumb2__)
#define a_clz_32 a_clz_32
static inline int a_clz_32(uint32_t x)
{
__asm__ ("clz %0, %1" : "=r"(x) : "r"(x));
return x;
}
#if __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
#define a_ctz_32 a_ctz_32
static inline int a_ctz_32(uint32_t x)
{
uint32_t xr;
__asm__ ("rbit %0, %1" : "=r"(xr) : "r"(x));
return a_clz_32(xr);
}
#endif
#endif