aboutsummaryrefslogtreecommitdiff
path: root/sys/linux/arm/arch/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/linux/arm/arch/atomic.h')
-rw-r--r--sys/linux/arm/arch/atomic.h107
1 files changed, 107 insertions, 0 deletions
diff --git a/sys/linux/arm/arch/atomic.h b/sys/linux/arm/arch/atomic.h
new file mode 100644
index 0000000..abb8a7b
--- /dev/null
+++ b/sys/linux/arm/arch/atomic.h
@@ -0,0 +1,107 @@
+#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 __atomic·casptr, __atomic·barrierptr;
+
+#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
+
+static inline int
+atomic·ll(volatile int *p)
+{
+ int v;
+ __asm__ __volatile__ ("ldrex %0, %1" : "=r"(v) : "Q"(*p));
+ return v;
+}
+
+static inline int
+atomic·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
+
+static inline void
+atomic·barrier()
+{
+ __asm__ __volatile__ ("dmb ish" : : : "memory");
+}
+
+#endif
+
+#define atomic·prellsc atomic·barrier
+#define atomic·postllsc atomic·barrier
+
+#else
+
+static inline int
+atomic·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 r3 __asm__("r3") = __atomic·casptr;
+ 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 atomic·barrier
+static inline void
+atomic·barrier()
+{
+ register uintptr ip __asm__("ip") = __atomic·barrierptr;
+ __asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
+}
+#endif
+
+static inline void
+atomic·crash()
+{
+ __asm__ __volatile__(
+#ifndef __thumb__
+ ".word 0xe7f000f0"
+#else
+ ".short 0xdeff"
+#endif
+ : : : "memory");
+}
+
+#if __ARM_ARCH >= 5 && (!__thumb__ || __thumb2__)
+
+static inline int
+atomic·clz32(uint32 x)
+{
+ __asm__ ("clz %0, %1" : "=r"(x) : "r"(x));
+ return x;
+}
+
+#if __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+static inline int
+atomic·ctz32(uint32 x)
+{
+ uint32 xr;
+ __asm__ ("rbit %0, %1" : "=r"(xr) : "r"(x));
+ return atomic·clz32(xr);
+}
+
+#endif
+
+#endif