diff options
Diffstat (limited to 'arch/sparc/lib/bitops.S')
-rw-r--r-- | arch/sparc/lib/bitops.S | 110 |
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 00000000000..3e939976907 --- /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: |