summaryrefslogtreecommitdiff
path: root/arch/sparc/lib/bitops.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/lib/bitops.S')
-rw-r--r--arch/sparc/lib/bitops.S110
1 files changed, 110 insertions, 0 deletions
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S
new file mode 100644
index 000000000000..3e9399769075
--- /dev/null
+++ b/arch/sparc/lib/bitops.S
@@ -0,0 +1,110 @@
+/* bitops.S: Low level assembler bit operations.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/config.h>
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+
+ .text
+ .align 4
+
+ .globl __bitops_begin
+__bitops_begin:
+
+ /* Take bits in %g2 and set them in word at %g1,
+ * return whether bits were set in original value
+ * in %g2. %g4 holds value to restore into %o7
+ * in delay slot of jmpl return, %g3 + %g5 + %g7 can be
+ * used as temporaries and thus is considered clobbered
+ * by all callers.
+ */
+ .globl ___set_bit
+___set_bit:
+ rd %psr, %g3
+ nop; nop; nop;
+ or %g3, PSR_PIL, %g5
+ wr %g5, 0x0, %psr
+ nop; nop; nop
+#ifdef CONFIG_SMP
+ set bitops_spinlock, %g5
+2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
+ orcc %g7, 0x0, %g0 ! Did we get it?
+ bne 2b ! Nope...
+#endif
+ ld [%g1], %g7
+ or %g7, %g2, %g5
+ and %g7, %g2, %g2
+#ifdef CONFIG_SMP
+ st %g5, [%g1]
+ set bitops_spinlock, %g5
+ stb %g0, [%g5]
+#else
+ st %g5, [%g1]
+#endif
+ wr %g3, 0x0, %psr
+ nop; nop; nop
+ jmpl %o7, %g0
+ mov %g4, %o7
+
+ /* Same as above, but clears the bits from %g2 instead. */
+ .globl ___clear_bit
+___clear_bit:
+ rd %psr, %g3
+ nop; nop; nop
+ or %g3, PSR_PIL, %g5
+ wr %g5, 0x0, %psr
+ nop; nop; nop
+#ifdef CONFIG_SMP
+ set bitops_spinlock, %g5
+2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
+ orcc %g7, 0x0, %g0 ! Did we get it?
+ bne 2b ! Nope...
+#endif
+ ld [%g1], %g7
+ andn %g7, %g2, %g5
+ and %g7, %g2, %g2
+#ifdef CONFIG_SMP
+ st %g5, [%g1]
+ set bitops_spinlock, %g5
+ stb %g0, [%g5]
+#else
+ st %g5, [%g1]
+#endif
+ wr %g3, 0x0, %psr
+ nop; nop; nop
+ jmpl %o7, %g0
+ mov %g4, %o7
+
+ /* Same thing again, but this time toggles the bits from %g2. */
+ .globl ___change_bit
+___change_bit:
+ rd %psr, %g3
+ nop; nop; nop
+ or %g3, PSR_PIL, %g5
+ wr %g5, 0x0, %psr
+ nop; nop; nop
+#ifdef CONFIG_SMP
+ set bitops_spinlock, %g5
+2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
+ orcc %g7, 0x0, %g0 ! Did we get it?
+ bne 2b ! Nope...
+#endif
+ ld [%g1], %g7
+ xor %g7, %g2, %g5
+ and %g7, %g2, %g2
+#ifdef CONFIG_SMP
+ st %g5, [%g1]
+ set bitops_spinlock, %g5
+ stb %g0, [%g5]
+#else
+ st %g5, [%g1]
+#endif
+ wr %g3, 0x0, %psr
+ nop; nop; nop
+ jmpl %o7, %g0
+ mov %g4, %o7
+
+ .globl __bitops_end
+__bitops_end: