1/*-
2 * Copyright (c) 2000, 2001 Benno Rice
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <machine/asm.h>
30
31	.text
32
33ASENTRY_NOPROF(atomic_set_8)
340:	lwarx	0, 0, 3		/* load old value */
35	slwi	4, 4, 24	/* shift the byte so it's in the right place */
36	or	0, 0, 4		/* generate new value */
37	stwcx.	0, 0, 3		/* attempt to store */
38	bne-	0		/* loop if failed */
39	eieio			/* synchronise */
40	sync
41	blr			/* return */
42
43ASENTRY_NOPROF(atomic_clear_8)
440:	lwarx 	0, 0, 3		/* load old value */
45	slwi	4, 4, 24	/* shift the byte so it's in the right place */
46	andc	0, 0, 4		/* generate new value */
47	stwcx.	0, 0, 3		/* attempt to store */
48	bne-	0		/* loop if failed */
49	eieio			/* synchronise */
50	sync
51	blr			/* return */
52
53ASENTRY_NOPROF(atomic_add_8)
540:	lwarx	9, 0, 3		/* load old value */
55	srwi	0, 9, 24	/* byte alignment */
56	add	0, 4, 0		/* calculate new value */
57	slwi	0, 9, 24	/* byte alignment */
58	clrlwi	9, 9, 8		/* clear the byte in the original word */
59	or	9, 9, 0		/* copy back in to the original word */
60	stwcx.	9, 0, 3		/* attempt to store */
61	bne-	0		/* loop if failed */
62	eieio			/* synchronise */
63	sync
64	blr			/* return */
65
66ASENTRY_NOPROF(atomic_subtract_8)
670:	lwarx	9, 0, 3		/* load old value */
68	srwi	0, 9, 24	/* byte alignment */
69	subf	0, 4, 0		/* calculate new value */
70	slwi	0, 9, 24	/* byte alignment */
71	clrlwi	9, 9, 8		/* clear the byte in the original word */
72	or	9, 9, 0		/* copy back in to the original word */
73	stwcx.	9, 0, 3		/* attempt to store */
74	bne-	0		/* loop if failed */
75	eieio			/* synchronise */
76	sync
77	blr			/* return */
78
79ASENTRY_NOPROF(atomic_set_16)
80	li	11, 3		/* mask to test for alignment */
81	andc.	11, 3, 11	/* force address to be word-aligned */
820:	lwarx	12, 0, 11	/* load old value */
83	bne	1f		/* no realignment needed if it's aligned */
84	slwi	4, 4, 16	/* realign operand */
851:	or	12, 12, 4	/* calculate new value */
86	stwcx.	12, 0, 11	/* attempt to store */
87	bne-	0b		/* loop if failed */
88	eieio			/* synchronise */
89	sync
90	blr			/* return */
91
92ASENTRY_NOPROF(atomic_clear_16)
93	li	11, 3		/* mask to test for alignment */
94	andc.	11, 3, 11	/* force address to be word-aligned */
950:	lwarx	12, 0, 11	/* load old value */
96	bne	1f		/* no realignment needed if it's aligned */
97	slwi	4, 4, 16	/* realign operand */
981:	andc	12, 12, 4	/* calculate new value */
99	stwcx.	12, 0, 11	/* attempt to store */
100	bne-	0b		/* loop if failed */
101	eieio			/* synchronise */
102	sync
103	blr			/* return */
104
105ASENTRY_NOPROF(atomic_add_16)
106	li	11, 3		/* mask to test for alignment */
107	andc.	11, 3, 11	/* force address to be word-aligned */
1080:	lwarx	12, 0, 11	/* load old value */
109	bne	1f		/* no realignment needed if it's aligned */
110	srwi	12, 9, 16	/* realign */
1111:	add	12, 4, 12	/* calculate new value */
112	bne	2f		/* no realignment needed if it's aligned */
113	slwi	12, 12, 16	/* realign */
1142:	clrlwi	9, 9, 16	/* clear old value */
115	or	9, 9, 12	/* copy in new value */
116	stwcx.	12, 0, 11	/* attempt to store */
117	bne-	0b		/* loop if failed */
118	eieio			/* synchronise */
119	sync
120	blr			/* return */
121
122ASENTRY_NOPROF(atomic_subtract_16)
123	li	11, 3		/* mask to test for alignment */
124	andc.	11, 3, 11	/* force address to be word-aligned */
1250:	lwarx	12, 0, 11	/* load old value */
126	bne	1f		/* no realignment needed if it's aligned */
127	srwi	12, 9, 16	/* realign */
1281:	subf	12, 4, 12	/* calculate new value */
129	bne	2f		/* no realignment needed if it's aligned */
130	slwi	12, 12, 16	/* realign */
1312:	clrlwi	9, 9, 16	/* clear old value */
132	or	9, 9, 12	/* copy in new value */
133	stwcx.	12, 0, 11	/* attempt to store */
134	bne-	0		/* loop if failed */
135	eieio			/* synchronise */
136	sync
137	blr			/* return */
138