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
 |