about summary refs log tree commit diff
path: root/arch/arm/atomic_arch.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/atomic_arch.h')
-rw-r--r--arch/arm/atomic_arch.h21
1 files changed, 14 insertions, 7 deletions
diff --git a/arch/arm/atomic_arch.h b/arch/arm/atomic_arch.h
index 706fa1f2..d6af84d0 100644
--- a/arch/arm/atomic_arch.h
+++ b/arch/arm/atomic_arch.h
@@ -1,5 +1,11 @@
-__attribute__((__visibility__("hidden")))
-extern const void *__arm_atomics[3]; /* gettp, cas, barrier */
+#if __ARM_ARCH_4__ || __ARM_ARCH_4T__ || __ARM_ARCH == 4
+#define BLX "mov lr,pc\n\tbx"
+#else
+#define BLX "blx"
+#endif
+
+extern uintptr_t __attribute__((__visibility__("hidden")))
+	__a_cas_ptr, __a_barrier_ptr;
 
 #if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \
  || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ ||  __ARM_ARCH >= 7
@@ -42,11 +48,12 @@ static inline int a_cas(volatile int *p, int t, int s)
 		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__ (
-			"bl __a_cas"
-			: "+r"(r0) : "r"(r1), "r"(r2)
-			: "memory", "r3", "lr", "ip", "cc" );
+			BLX " r3"
+			: "+r"(r0), "+r"(r3) : "r"(r1), "r"(r2)
+			: "memory", "lr", "ip", "cc" );
 		if (!r0) return t;
 		if ((old=*p)!=t) return old;
 	}
@@ -58,8 +65,8 @@ static inline int a_cas(volatile int *p, int t, int s)
 #define a_barrier a_barrier
 static inline void a_barrier()
 {
-	__asm__ __volatile__("bl __a_barrier"
-		: : : "memory", "cc", "ip", "lr" );
+	register uintptr_t ip __asm__("ip") = __a_barrier_ptr;
+	__asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
 }
 #endif