gint-with-thread/src/std/setjmp.S

92 lines
1.6 KiB
ArmAsm

/*
** gint:std:setjmp - performing a nonlocal goto
*/
.section .gint.mapped, "ax"
.align 4
.global _setjmp
.type _setjmp, @function
/* setjmp(): saves various information about the calling environment */
_setjmp:
/* block interrupts / exceptions (this part should b exception-safe) */
stc sr, r1
mov r1, r3
mov #0x10, r2
shll8 r2
shll16 r2
or r2, r1
ldc r1, sr
/* save current environment */
add #52, r4
sts.l pr, @-r4
sts.l mach, @-r4
sts.l macl, @-r4
stc.l gbr, @-r4
mov.l r15, @-r4
mov.l r14, @-r4
mov.l r13, @-r4
mov.l r12, @-r4
mov.l r11, @-r4
mov.l r10, @-r4
mov.l r9, @-r4
mov.l r8, @-r4
mov.l r3, @-r4 ! previous SR register status
/* restore sr then exit */
ldc r3, sr
rts
mov #0, r0
.global _longjmp
.type _longjmp, @function
/* longjmp(): restore the saved environment */
_longjmp:
/* block interrupt */
stc sr, r1
mov #0x10, r2
shll8 r2
shll16 r2
or r2, r1
ldc r1, sr
/* check arg validity and save it into unbankable register to avoid
error when the "old" SR register is restored */
tst r5, r5
mov r4, r8
bf/s env_switch
mov r5, r9
mov #1, r9
env_switch:
/* load the old SR regsiter first to force register bank switch (if
occur) then move the context and the returned value into non-saved
(by the setjmp context) registers. */
ldc.l @r8+, sr
mov r8, r4
mov r9, r0
/* restore all old registers */
mov.l @r4+, r8
mov.l @r4+, r9
mov.l @r4+, r10
mov.l @r4+, r11
mov.l @r4+, r12
mov.l @r4+, r13
mov.l @r4+, r14
mov.l @r4+, r15
ldc.l @r4+, gbr
lds.l @r4+, macl
lds.l @r4+, mach
lds.l @r4+, pr
rts
nop