fxlibc/src/libc/threads/atomic.S

96 lines
1.9 KiB
ArmAsm

.text
.global ___thread_atomic_start
.global ___thread_atomic_stop
.type ___thread_atomic_start, @function
.type ___thread_atomic_stop, @function
.align 2
/*
** extern uint32_t __thread_atomic_start(void)
** Save the current SR register and set the SR.BIT bit up to start an atomic
** context (interrupt is blocked).
** Return the saved SR register (only if the we enter into an atomic context),
** 0xffffffff otherwise.
*/
___thread_atomic_start:
! Check if the user is currently into an atomic operation
! and update atomic counter.
mov.l atomic_counter, r1
mov.l @r1, r2
tst r2, r2
add #1, r2
mov.l r2, @r1
bf.s atomic_start_exit
mov #-1, r0
! Block interrupt if needed.
stc sr, r1
mov r1, r0
mov.l bl_mask, r2
or r2, r1
ldc r1, sr
! Save "old" SR register.
mov.l sr_save, r1
mov.l r0, @r1
atomic_start_exit:
rts
nop
/*
** extern uint32_t __thread_atomic_stop(void)
** Decreate the internal "atomic context counter" and if the counter is 0,
** restore the saved SR register status.
** Return the restored SR register (if restored) or -1 otherwise.
*/
___thread_atomic_stop:
! Check if the device is currently into an atomic operation
! and update atomic counter and, if needed, restore the SR
! regsiter
mov.l atomic_counter, r1
mov.l @r1, r0
tst r0, r0
bt atomic_end_error
cmp/eq #1, r0
add #-1, r0
mov.l r0, @r1
bf atomic_end_error
! Restore saved SR register data.
mov.l sr_save, r1
mov.l @r1, r0
ldc r0, sr
bra atomic_end_exit
nop
atomic_end_error:
mov #-1, r0
atomic_end_exit:
rts
nop
.align 4
bl_mask: .long 0x100000f0
sr_save: .long ___thread_atomic_sr_save
atomic_counter: .long ___thread_atomic_counter
##---
## Global part.
##---
.data
.global ___thread_atomic_sr_save
.global ___thread_atomic_counter
.type ___thread_atomic_sr_save, @object
.type ___thread_atomic_counter, @object
.align 4
___thread_atomic_sr_save: .long 0x00000000
___thread_atomic_counter: .long 0x00000000