.define .gto .sect .text .sect .rom .sect .data .sect .bss .extern .gto .sect .text .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 .sect .data savd0: .data4 0 savd1: .data4 0 .sect .text