[ARM] update atomic ops to use the ldr/strex instructions on armv6+
diff --git a/arch/arm/ops.S b/arch/arm/ops.S
index c1d612c..a7cb5b2 100644
--- a/arch/arm/ops.S
+++ b/arch/arm/ops.S
@@ -45,6 +45,19 @@
/* int atomic_add(int *ptr, int val); */
FUNCTION(atomic_add)
+#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
+ /* use load/store exclusive */
+.L_loop_add:
+ ldrex r12, [r0]
+ add r2, r12, r1
+ strex r3, r2, [r0]
+ cmp r3, #0
+ bne .L_loop_add
+
+ /* save old value */
+ mov r0, r12
+ bx lr
+#else
/* disable interrupts, do the add, and reenable */
mrs r2, cpsr
mov r12, r2
@@ -62,9 +75,23 @@
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
+#endif
/* int atomic_and(int *ptr, int val); */
FUNCTION(atomic_and)
+#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
+ /* use load/store exclusive */
+.L_loop_and:
+ ldrex r12, [r0]
+ and r2, r12, r1
+ strex r3, r2, [r0]
+ cmp r3, #0
+ bne .L_loop_and
+
+ /* save old value */
+ mov r0, r12
+ bx lr
+#else
/* disable interrupts, do the and, and reenable */
mrs r2, cpsr
mov r12, r2
@@ -82,9 +109,23 @@
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
+#endif
/* int atomic_or(int *ptr, int val); */
FUNCTION(atomic_or)
+#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
+ /* use load/store exclusive */
+.L_loop_or:
+ ldrex r12, [r0]
+ orr r2, r12, r1
+ strex r3, r2, [r0]
+ cmp r3, #0
+ bne .L_loop_or
+
+ /* save old value */
+ mov r0, r12
+ bx lr
+#else
/* disable interrupts, do the or, and reenable */
mrs r2, cpsr
mov r12, r2
@@ -102,6 +143,7 @@
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
+#endif
/* void arch_idle(); */
FUNCTION(arch_idle)