| /* bitops.S: Low level assembler bit operations. | 
 |  * | 
 |  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) | 
 |  */ | 
 |  | 
 | #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: |