forked from Lephenixnoir/gint
88 lines
1.5 KiB
ArmAsm
88 lines
1.5 KiB
ArmAsm
/*
|
|
** gint:thread:atomic - Thread atomic helper
|
|
*/
|
|
|
|
.text
|
|
.align 2
|
|
|
|
.global _atomic_begin
|
|
.type _atomic_begin, @function
|
|
|
|
/* thread_atomic_begin(): Mask interrupts and exceptions */
|
|
_atomic_begin:
|
|
/* Check if the user is currently into an atomic state 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_begin_exit
|
|
mov #-1, r0
|
|
|
|
/* Block all interrupts by setting IMASK=15 */
|
|
mov #0xf, r1
|
|
shll2 r1
|
|
shll2 r1
|
|
stc sr, r0
|
|
or r0, r1
|
|
ldc r1, sr
|
|
|
|
/* Save "old" SR register. */
|
|
mov.l atomic_sr_save, r1
|
|
mov.l r0, @r1
|
|
|
|
atomic_begin_exit:
|
|
rts
|
|
nop
|
|
|
|
|
|
.global _atomic_end
|
|
.type _atomic_end, @function
|
|
|
|
/* atomic_end(): Unmask (if possible) interrupts / exceptions signals */
|
|
_atomic_end:
|
|
/* Check if the device is currently into an atomic operation, then
|
|
update the counter and, if needed, restore the SR register. */
|
|
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/s atomic_end_exit
|
|
mov #0, r0
|
|
|
|
/* Restore saved SR register data. */
|
|
mov.l atomic_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
|
|
atomic_counter: .long _atomic_counter
|
|
atomic_sr_save: .long _atomic_sr_save
|
|
|
|
|
|
|
|
/*
|
|
** Global symbols
|
|
*/
|
|
.global _atomic_sr_save
|
|
.type _atomic_sr_save, @object
|
|
.global _atomic_counter
|
|
.type _atomic_counter, @object
|
|
|
|
.align 4
|
|
_atomic_sr_save: .long 0x00000000
|
|
_atomic_counter: .long 0x00000000
|