1139825Simp/*-
270741Sbenno * Copyright (c) 2000, 2001 Benno Rice
370741Sbenno * All rights reserved.
470741Sbenno *
570741Sbenno * Redistribution and use in source and binary forms, with or without
670741Sbenno * modification, are permitted provided that the following conditions
770741Sbenno * are met:
870741Sbenno * 1. Redistributions of source code must retain the above copyright
970741Sbenno *    notice, this list of conditions and the following disclaimer.
1070741Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1170741Sbenno *    notice, this list of conditions and the following disclaimer in the
1270741Sbenno *    documentation and/or other materials provided with the distribution.
1370741Sbenno *
1470741Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1570741Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1670741Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1770741Sbenno * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1870741Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1970741Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2070741Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2170741Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2270741Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2370741Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2470741Sbenno * SUCH DAMAGE.
2570741Sbenno *
2670741Sbenno * $FreeBSD$
2770741Sbenno */
2870741Sbenno
2970741Sbenno#include <machine/asm.h>
3070741Sbenno
3170741Sbenno	.text
3270741Sbenno
33231907SandreastASENTRY_NOPROF(atomic_set_8)
3470741Sbenno0:	lwarx	0, 0, 3		/* load old value */
3570741Sbenno	slwi	4, 4, 24	/* shift the byte so it's in the right place */
3670741Sbenno	or	0, 0, 4		/* generate new value */
3770741Sbenno	stwcx.	0, 0, 3		/* attempt to store */
3870741Sbenno	bne-	0		/* loop if failed */
3970741Sbenno	eieio			/* synchronise */
4070741Sbenno	sync
4170741Sbenno	blr			/* return */
4270741Sbenno
43231907SandreastASENTRY_NOPROF(atomic_clear_8)
4470741Sbenno0:	lwarx 	0, 0, 3		/* load old value */
4570741Sbenno	slwi	4, 4, 24	/* shift the byte so it's in the right place */
4670741Sbenno	andc	0, 0, 4		/* generate new value */
4770741Sbenno	stwcx.	0, 0, 3		/* attempt to store */
4870741Sbenno	bne-	0		/* loop if failed */
4970741Sbenno	eieio			/* synchronise */
5070741Sbenno	sync
5170741Sbenno	blr			/* return */
5270741Sbenno
53231907SandreastASENTRY_NOPROF(atomic_add_8)
5470741Sbenno0:	lwarx	9, 0, 3		/* load old value */
5570741Sbenno	srwi	0, 9, 24	/* byte alignment */
5670741Sbenno	add	0, 4, 0		/* calculate new value */
5770741Sbenno	slwi	0, 9, 24	/* byte alignment */
5870741Sbenno	clrlwi	9, 9, 8		/* clear the byte in the original word */
5970741Sbenno	or	9, 9, 0		/* copy back in to the original word */
6070741Sbenno	stwcx.	9, 0, 3		/* attempt to store */
6170741Sbenno	bne-	0		/* loop if failed */
6270741Sbenno	eieio			/* synchronise */
6370741Sbenno	sync
6470741Sbenno	blr			/* return */
6570741Sbenno
66231907SandreastASENTRY_NOPROF(atomic_subtract_8)
6770741Sbenno0:	lwarx	9, 0, 3		/* load old value */
6870741Sbenno	srwi	0, 9, 24	/* byte alignment */
6970741Sbenno	subf	0, 4, 0		/* calculate new value */
7070741Sbenno	slwi	0, 9, 24	/* byte alignment */
7170741Sbenno	clrlwi	9, 9, 8		/* clear the byte in the original word */
7270741Sbenno	or	9, 9, 0		/* copy back in to the original word */
7370741Sbenno	stwcx.	9, 0, 3		/* attempt to store */
7470741Sbenno	bne-	0		/* loop if failed */
7570741Sbenno	eieio			/* synchronise */
7670741Sbenno	sync
7770741Sbenno	blr			/* return */
7870741Sbenno
79231907SandreastASENTRY_NOPROF(atomic_set_16)
8078342Sbenno	li	11, 3		/* mask to test for alignment */
8178342Sbenno	andc.	11, 3, 11	/* force address to be word-aligned */
8278342Sbenno0:	lwarx	12, 0, 11	/* load old value */
8378342Sbenno	bne	1f		/* no realignment needed if it's aligned */
8470741Sbenno	slwi	4, 4, 16	/* realign operand */
8578342Sbenno1:	or	12, 12, 4	/* calculate new value */
8678342Sbenno	stwcx.	12, 0, 11	/* attempt to store */
8778342Sbenno	bne-	0b		/* loop if failed */
8870741Sbenno	eieio			/* synchronise */
8970741Sbenno	sync
9070741Sbenno	blr			/* return */
9170741Sbenno
92231907SandreastASENTRY_NOPROF(atomic_clear_16)
9378342Sbenno	li	11, 3		/* mask to test for alignment */
9478342Sbenno	andc.	11, 3, 11	/* force address to be word-aligned */
9578342Sbenno0:	lwarx	12, 0, 11	/* load old value */
9678342Sbenno	bne	1f		/* no realignment needed if it's aligned */
9770741Sbenno	slwi	4, 4, 16	/* realign operand */
9878342Sbenno1:	andc	12, 12, 4	/* calculate new value */
9978342Sbenno	stwcx.	12, 0, 11	/* attempt to store */
10078342Sbenno	bne-	0b		/* loop if failed */
10170741Sbenno	eieio			/* synchronise */
10270741Sbenno	sync
10370741Sbenno	blr			/* return */
10470741Sbenno
105231907SandreastASENTRY_NOPROF(atomic_add_16)
10678342Sbenno	li	11, 3		/* mask to test for alignment */
10778342Sbenno	andc.	11, 3, 11	/* force address to be word-aligned */
10878342Sbenno0:	lwarx	12, 0, 11	/* load old value */
10978342Sbenno	bne	1f		/* no realignment needed if it's aligned */
11078342Sbenno	srwi	12, 9, 16	/* realign */
11178342Sbenno1:	add	12, 4, 12	/* calculate new value */
11278342Sbenno	bne	2f		/* no realignment needed if it's aligned */
11378342Sbenno	slwi	12, 12, 16	/* realign */
11478342Sbenno2:	clrlwi	9, 9, 16	/* clear old value */
11578342Sbenno	or	9, 9, 12	/* copy in new value */
11678342Sbenno	stwcx.	12, 0, 11	/* attempt to store */
11778342Sbenno	bne-	0b		/* loop if failed */
11870741Sbenno	eieio			/* synchronise */
11970741Sbenno	sync
12070741Sbenno	blr			/* return */
12170741Sbenno
122231907SandreastASENTRY_NOPROF(atomic_subtract_16)
12378342Sbenno	li	11, 3		/* mask to test for alignment */
12478342Sbenno	andc.	11, 3, 11	/* force address to be word-aligned */
12578342Sbenno0:	lwarx	12, 0, 11	/* load old value */
12678342Sbenno	bne	1f		/* no realignment needed if it's aligned */
12778342Sbenno	srwi	12, 9, 16	/* realign */
12878342Sbenno1:	subf	12, 4, 12	/* calculate new value */
12978342Sbenno	bne	2f		/* no realignment needed if it's aligned */
13078342Sbenno	slwi	12, 12, 16	/* realign */
13178342Sbenno2:	clrlwi	9, 9, 16	/* clear old value */
13278342Sbenno	or	9, 9, 12	/* copy in new value */
13378342Sbenno	stwcx.	12, 0, 11	/* attempt to store */
13470741Sbenno	bne-	0		/* loop if failed */
13570741Sbenno	eieio			/* synchronise */
13670741Sbenno	sync
13770741Sbenno	blr			/* return */
138