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