80 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| .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
 |