forked from Lephenixnoir/gint
92 lines
1.6 KiB
ArmAsm
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
|
|
mov.l r3, @-r4 ! previous SR register status
|
|
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
|
|
|
|
/* 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 and save arg validity into unbankable register to avoid
|
|
error when the "old" SR register will be 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
|