summary refs log tree commit diff
path: root/arch/sparc/lib/atomic_32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/lib/atomic_32.S')
-rw-r--r--arch/sparc/lib/atomic_32.S99
1 files changed, 99 insertions, 0 deletions
diff --git a/arch/sparc/lib/atomic_32.S b/arch/sparc/lib/atomic_32.S
new file mode 100644
index 000000000000..178cbb8ae1b9
--- /dev/null
+++ b/arch/sparc/lib/atomic_32.S
@@ -0,0 +1,99 @@
+/* atomic.S: Move this stuff here for better ICACHE hit rates.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ */
+
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+
+	.text
+	.align	4
+
+	.globl  __atomic_begin
+__atomic_begin:
+
+#ifndef CONFIG_SMP
+	.globl	___xchg32_sun4c
+___xchg32_sun4c:
+	rd	%psr, %g3
+	andcc	%g3, PSR_PIL, %g0
+	bne	1f
+	 nop
+	wr	%g3, PSR_PIL, %psr
+	nop; nop; nop
+1:
+	andcc	%g3, PSR_PIL, %g0
+	ld	[%g1], %g7
+	bne	1f
+	 st	%g2, [%g1]
+	wr	%g3, 0x0, %psr
+	nop; nop; nop
+1:
+	mov	%g7, %g2
+	jmpl	%o7 + 8, %g0
+	 mov	%g4, %o7
+
+	.globl	___xchg32_sun4md
+___xchg32_sun4md:
+	swap	[%g1], %g2
+	jmpl	%o7 + 8, %g0
+	 mov	%g4, %o7
+#endif
+
+	/* Read asm-sparc/atomic.h carefully to understand how this works for SMP.
+	 * Really, some things here for SMP are overly clever, go read the header.
+	 */
+	.globl	___atomic24_add
+___atomic24_add:
+	rd	%psr, %g3		! Keep the code small, old way was stupid
+	nop; nop; nop;			! Let the bits set
+	or	%g3, PSR_PIL, %g7	! Disable interrupts
+	wr	%g7, 0x0, %psr		! Set %psr
+	nop; nop; nop;			! Let the bits set
+#ifdef CONFIG_SMP
+1:	ldstub	[%g1 + 3], %g7		! Spin on the byte lock for SMP.
+	orcc	%g7, 0x0, %g0		! Did we get it?
+	bne	1b			! Nope...
+	 ld	[%g1], %g7		! Load locked atomic24_t
+	sra	%g7, 8, %g7		! Get signed 24-bit integer
+	add	%g7, %g2, %g2		! Add in argument
+	sll	%g2, 8, %g7		! Transpose back to atomic24_t
+	st	%g7, [%g1]		! Clever: This releases the lock as well.
+#else
+	ld	[%g1], %g7		! Load locked atomic24_t
+	add	%g7, %g2, %g2		! Add in argument
+	st	%g2, [%g1]		! Store it back
+#endif
+	wr	%g3, 0x0, %psr		! Restore original PSR_PIL
+	nop; nop; nop;			! Let the bits set
+	jmpl	%o7, %g0		! NOTE: not + 8, see callers in atomic.h
+	 mov	%g4, %o7		! Restore %o7
+
+	.globl	___atomic24_sub
+___atomic24_sub:
+	rd	%psr, %g3		! Keep the code small, old way was stupid
+	nop; nop; nop;			! Let the bits set
+	or	%g3, PSR_PIL, %g7	! Disable interrupts
+	wr	%g7, 0x0, %psr		! Set %psr
+	nop; nop; nop;			! Let the bits set
+#ifdef CONFIG_SMP
+1:	ldstub	[%g1 + 3], %g7		! Spin on the byte lock for SMP.
+	orcc	%g7, 0x0, %g0		! Did we get it?
+	bne	1b			! Nope...
+	 ld	[%g1], %g7		! Load locked atomic24_t
+	sra	%g7, 8, %g7		! Get signed 24-bit integer
+	sub	%g7, %g2, %g2		! Subtract argument
+	sll	%g2, 8, %g7		! Transpose back to atomic24_t
+	st	%g7, [%g1]		! Clever: This releases the lock as well
+#else
+	ld	[%g1], %g7		! Load locked atomic24_t
+	sub	%g7, %g2, %g2		! Subtract argument
+	st	%g2, [%g1]		! Store it back
+#endif
+	wr	%g3, 0x0, %psr		! Restore original PSR_PIL
+	nop; nop; nop;			! Let the bits set
+	jmpl	%o7, %g0		! NOTE: not + 8, see callers in atomic.h
+	 mov	%g4, %o7		! Restore %o7
+
+	.globl  __atomic_end
+__atomic_end: