76 lines
1.6 KiB
ArmAsm
76 lines
1.6 KiB
ArmAsm
|
.define .gto
|
||
|
.extern .gto
|
||
|
|
||
|
.gto:
|
||
|
! nonlocal goto
|
||
|
! the argument on the stack is a pointer to a GTO-descriptor containing:
|
||
|
! - the new local base
|
||
|
! - the new stackpointer
|
||
|
! - the new program counter
|
||
|
!
|
||
|
! The main task of the GTO instruction is to restore the registers
|
||
|
! used for local variables. It uses a word stored in each stackframe,
|
||
|
! indicating how many data -and address registers the procedure of
|
||
|
! that stackframe has.
|
||
|
|
||
|
move.l (sp)+,a0
|
||
|
add.l #8,a0 ! a0 now points to new local base entry
|
||
|
! of the descriptor
|
||
|
cmp.l (a0),a6 ! GTO within same procedure?
|
||
|
beq noregs
|
||
|
move.l d0,savd0 ! gto may not destroy the return area
|
||
|
move.l d1,savd1
|
||
|
1:
|
||
|
tst.l (a6)
|
||
|
beq err
|
||
|
unlk a6
|
||
|
move.w (sp)+,d0 ! word indicating which regs. were saved
|
||
|
jsr restr
|
||
|
cmp.l (a0),a6
|
||
|
bne 1b
|
||
|
move.l savd0,d0
|
||
|
move.l savd1,d1
|
||
|
noregs:
|
||
|
move.l -4(a0),sp
|
||
|
move.l -8(a0),a0 ! new program counter
|
||
|
jmp (a0)
|
||
|
err:
|
||
|
move.w #EBADGTO,-(sp)
|
||
|
jmp .fat
|
||
|
|
||
|
restr:
|
||
|
! restore the registers. Note that scratch register a0 may
|
||
|
! not be changed here. d0 contains (8*#addr.regs + #data regs.)
|
||
|
! note that registers are assigned in the order d7,d6 .. and
|
||
|
! a5,a4...
|
||
|
|
||
|
move.l (sp)+,d2 ! return address; can't use a0 here
|
||
|
move.w d0,d1
|
||
|
and.l #7,d0 ! #data registers
|
||
|
asl.l #1,d0 ! * 2
|
||
|
lea etabd,a1
|
||
|
sub.l d0,a1
|
||
|
jmp (a1)
|
||
|
move.l (sp)+,d3
|
||
|
move.l (sp)+,d4
|
||
|
move.l (sp)+,d5
|
||
|
move.l (sp)+,d6
|
||
|
move.l (sp)+,d7
|
||
|
etabd:
|
||
|
and.l #070,d1
|
||
|
asr.l #2,d1 ! # address registers
|
||
|
lea etaba,a1
|
||
|
sub.l d1,a1
|
||
|
jmp (a1)
|
||
|
move.l (sp)+,a2
|
||
|
move.l (sp)+,a3
|
||
|
move.l (sp)+,a4
|
||
|
move.l (sp)+,a5
|
||
|
etaba:
|
||
|
move.l d2,a1
|
||
|
jmp (a1) ! return
|
||
|
.data
|
||
|
savd0: .long 0
|
||
|
savd1: .long 0
|
||
|
.text
|