114 lines
2.4 KiB
ArmAsm
114 lines
2.4 KiB
ArmAsm
/* See the end of this file for copyright, license, and warranty information. */
|
|
|
|
.include "asm.S"
|
|
|
|
.text
|
|
|
|
/* int _atom_add(volatile int *atom, int val) */
|
|
func_begin _atom_add
|
|
push {r4}
|
|
1: ldrex r2, [r0] /* int old = __ldrex(atom) */
|
|
add r3, r2, r1 /* int new = old + val */
|
|
strex r4, r3, [r0] /* int err = __strex(atom, new) */
|
|
teq r4, #0 /* if (err) */
|
|
bne 1b /* goto 1 */
|
|
dmb /* data memory barrier */
|
|
mov r0, r2 /* return old */
|
|
pop {r4}
|
|
bx lr
|
|
func_end _atom_add
|
|
|
|
/* these are the same as _atom_add except for the instruction
|
|
* in the LDREX/STREX pair, so i'm not gonna annotate them */
|
|
|
|
func_begin _atom_sub
|
|
push {r4}
|
|
1: ldrex r2, [r0]
|
|
sub r3, r2, r1
|
|
strex r4, r3, [r0]
|
|
teq r4, #0
|
|
bne 1b
|
|
dmb
|
|
mov r0, r2
|
|
pop {r4}
|
|
bx lr
|
|
func_end _atom_sub
|
|
|
|
func_begin _atom_and
|
|
push {r4}
|
|
1: ldrex r2, [r0]
|
|
and r3, r2, r1
|
|
strex r4, r3, [r0]
|
|
teq r4, #0
|
|
bne 1b
|
|
dmb
|
|
mov r0, r2
|
|
pop {r4}
|
|
bx lr
|
|
func_end _atom_and
|
|
|
|
func_begin _atom_or
|
|
push {r4}
|
|
1: ldrex r2, [r0]
|
|
orr r3, r2, r1
|
|
strex r4, r3, [r0]
|
|
teq r4, #0
|
|
bne 1b
|
|
dmb
|
|
mov r0, r2
|
|
pop {r4}
|
|
bx lr
|
|
func_end _atom_or
|
|
|
|
func_begin _atom_xor
|
|
push {r4}
|
|
1: ldrex r2, [r0]
|
|
eor r3, r2, r1
|
|
strex r4, r3, [r0]
|
|
teq r4, #0
|
|
bne 1b
|
|
dmb
|
|
mov r0, r2
|
|
pop {r4}
|
|
bx lr
|
|
func_end _atom_xor
|
|
|
|
/* int _atom_xchg(volatile int *atom, int val) */
|
|
func_begin _atom_xchg
|
|
ldrex r2, [r0] /* int old = __ldrex(atom) */
|
|
strex r3, r1, [r0] /* int err = __strex(atom, val) */
|
|
teq r3, #0 /* if (err) */
|
|
bne _atom_xchg /* goto _atom_xchg */
|
|
dmb /* data memory barrier */
|
|
mov r0, r2 /* return old */
|
|
bx lr
|
|
func_end _atom_xchg
|
|
|
|
/* int _atom_cmpxchg(volatile int *atom, int cmp, int val) */
|
|
func_begin _atom_cmpxchg
|
|
push {r4}
|
|
1: mov r4, #0 /* int err = 0 */
|
|
ldrex r3, [r0] /* int old = __ldrex(atom) */
|
|
teq r3, r1 /* if (old == cmp) */
|
|
it eq
|
|
strexeq r4, r1, [r0] /* err = __strex(atom, val) */
|
|
teq r4, #0 /* if (err) */
|
|
bne 1b /* goto 1b */
|
|
dmb /* data memory barrier */
|
|
mov r0, r3 /* return old */
|
|
pop {r4}
|
|
bx lr
|
|
func_end _atom_cmpxchg
|
|
|
|
/*
|
|
* This file is part of Ardix.
|
|
* Copyright (c) 2021 Felix Kopp <owo@fef.moe>.
|
|
*
|
|
* Ardix is non-violent software: you may only use, redistribute,
|
|
* and/or modify it under the terms of the CNPLv6+ as found in
|
|
* the LICENSE file in the source code root directory or at
|
|
* <https://git.pixie.town/thufie/CNPL>.
|
|
*
|
|
* Ardix comes with ABSOLUTELY NO WARRANTY, to the extent
|
|
* permitted by applicable law. See the CNPLv6+ for details.
|
|
*/
|