453 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			453 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| ;@(#)signal.s	2.15 90/10/14 21:57:55, AMD
 | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | |
| ; Copyright 1990 Advanced Micro Devices, Inc.
 | |
| ;
 | |
| ; This software is the property of Advanced Micro Devices, Inc  (AMD)  which
 | |
| ; specifically  grants the user the right to modify, use and distribute this
 | |
| ; software provided this notice is not removed or altered.  All other rights
 | |
| ; are reserved by AMD.
 | |
| ;
 | |
| ; AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
 | |
| ; SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
 | |
| ; DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
 | |
| ; USE OF THIS SOFTWARE.
 | |
| ;
 | |
| ; So that all may benefit from your experience, please report  any  problems
 | |
| ; or  suggestions about this software to the 29K Technical Support Center at
 | |
| ; 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131  in  the  UK,  or
 | |
| ; 0031-11-1129 in Japan, toll free.  The direct dial number is 512-462-4118.
 | |
| ;
 | |
| ; Advanced Micro Devices, Inc.
 | |
| ; 29K Support Products
 | |
| ; Mail Stop 573
 | |
| ; 5900 E. Ben White Blvd.
 | |
| ; Austin, TX 78741
 | |
| ; 800-292-9263
 | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | |
| 	.file	"signal.s"
 | |
| 
 | |
| ; SigEntry is the address of an array of C-level user code signal handlers.
 | |
| ; They must return to the top-level before doing a sigret() return function.
 | |
| ; Nested signals are supported.
 | |
| 
 | |
| 	.extern	V_SPILL, V_FILL
 | |
| 	.extern fill		; In crt0.s
 | |
| 
 | |
| 	.align	4
 | |
| 	.comm	WindowSize, 4
 | |
| 	.data
 | |
| SigEntry:
 | |
| 	.word	0		; reserved
 | |
| 	.word	0		; adds. of #2 SIGINT handler
 | |
| 	.word	0		; reserved
 | |
| 	.word	0		; reserved
 | |
| 	.word	0		; reserved
 | |
| 	.word	0		; reserved
 | |
| 	.word	0		; reserved
 | |
| 	.word	0		; adds. of #8 SIGFPE handler
 | |
| 
 | |
| 	.text
 | |
| 
 | |
| 	.reg	v0,	gr96
 | |
| 	.reg	v1,	gr97
 | |
| 	.reg	v2,	gr98
 | |
| 	.reg	v3,	gr99
 | |
| 
 | |
| 	.reg	tav,	gr121
 | |
| 	.reg	tpc,	gr122
 | |
| 	.reg	lrp,	gr123
 | |
| 	.reg	slp,	gr124
 | |
| 	.reg	msp,	gr125
 | |
| 	.reg	rab,	gr126
 | |
| 	.reg	rfb,	gr127
 | |
| 
 | |
| ;=================================================================== setjmp()
 | |
| ; int
 | |
| ; setjmp(label_t jmpbuf)
 | |
| ; {
 | |
| ;	*jmpbuf = {gr1, msp, lr0, lr1};
 | |
| ;	return 0;
 | |
| ; }
 | |
| ;
 | |
| 	.global	_setjmp
 | |
| _setjmp:
 | |
| 	store	0, 0, gr1, lr2
 | |
| 	add	lr2, lr2, 4
 | |
| 	store	0, 0, msp, lr2
 | |
| 	add	lr2, lr2, 4
 | |
| 	store	0, 0, lr0, lr2
 | |
| 	add	lr2, lr2, 4
 | |
| 	store	0, 0, lr1, lr2
 | |
| 	jmpi	lr0
 | |
| 	 const	v0, 0
 | |
| ;
 | |
| ;==================================================================== longjmp()
 | |
| ; int
 | |
| ; longjmp(label_t jmpbuf, int value)
 | |
| ; {
 | |
| ;	/* BUG: check for this
 | |
| ;	  if (msp > jmpbuf->msp || gr1 > jmpbuf->gr1)
 | |
| ;		longjmperror();
 | |
| ;	 */
 | |
| ;
 | |
| ;	gr1 = jmpbuf->gr1;
 | |
| ;	lr2addr = jmpbuf->gr1 + 8;
 | |
| ;	msp = jmpbuf->msp;
 | |
| ;
 | |
| ;	/* saved lr1 is invalid if saved lr2addr > rfb */
 | |
| ;	if (lr2addr > rfb) {
 | |
| ;		/*
 | |
| ;		 * None of the registers are useful.
 | |
| ;		 * Set rfb to lr2addr - 512 & rab to rfb - 512.
 | |
| ;		 * the FILL assert will take care of filling
 | |
| ;		 */
 | |
| ;		lr1 = jmpbuf->lr1;
 | |
| ;		rab = lr2addr - windowsize;
 | |
| ;		rfb = lr2addr;
 | |
| ;	}
 | |
| ;
 | |
| ;	lr0 = jmpbuf->lr0;
 | |
| ;	if (rfb < lr1)
 | |
| ;		raise V_FILL;
 | |
| ;	return value;
 | |
| ; }
 | |
| ;
 | |
| 	.global	_longjmp
 | |
| _longjmp:
 | |
| 	load	0, 0, tav, lr2		; copy in gr1
 | |
| 	add	v1, lr2, 4		; v1 points to msp
 | |
| 	; make sure we return a non-zero value
 | |
| 	cpeq	v0, lr3, 0
 | |
| 	srl	v0, v0, 31
 | |
| 	or	v0, lr3, v0
 | |
| 
 | |
| 	add	gr1, tav, 0		; now update gr1
 | |
| 	add	tav, tav, 8		; calculate lr2addr
 | |
| 	load	0, 0, msp, v1		; update msp from jmpbuf
 | |
| 	cpleu	v3, tav, rfb		; if (lr2addr > rfb)
 | |
| 	jmpt	v3, $1			; {
 | |
| 	 add	v1, v1, 4		; v1 points to lr0
 | |
| 	add	v2, v1, 4		;	v2 points to lr1
 | |
| 	load	0, 0, lr1, v2		;	lr1 = value from jmpbuf
 | |
| 	sub	v3, rfb, rab		;
 | |
| 	sub	rab, tav, v3		;	rab = lr2addr - windowsize
 | |
| 	add	rfb, tav, 0		;	rfb = lr2addr
 | |
| $1:	; }
 | |
| 	load	0, 0, lr0, v1
 | |
| 	jmpi	lr0
 | |
| 	 asgeu	 V_FILL, rfb, lr1	; may fill from rfb to lr1
 | |
| ;
 | |
| ;================================================================== sigcode
 | |
| ; About to deliver a signal to a user mode signal handler.
 | |
| ;	msp+(15*4) = signal_number
 | |
| ;	msp+(14*4) = gr1
 | |
| ;	msp+(13*4) = rab
 | |
| ;	msp+(12*4) = PC0
 | |
| ;	msp+(11*4) = PC1
 | |
| ;	msp+(10*4) = PC2
 | |
| ;	msp+( 9*4) = CHA
 | |
| ;	msp+( 8*4) = CHD
 | |
| ;	msp+( 7*4) = CHC
 | |
| ;	msp+( 6*4) = ALU
 | |
| ;	msp+( 5*4) = OPS
 | |
| ;	msp+( 4*4) = gr121
 | |
| ;	msp+( 3*4) = gr99
 | |
| ;	msp+( 2*4) = gr98
 | |
| ;	msp+( 1*4) = gr97
 | |
| ;	msp        = gr96
 | |
| ; The state of all the registers (except for msp, chc and rab)
 | |
| ; is the same as when the process was interrupted.
 | |
| ;
 | |
| ; We must make the stack and window consistent before calling the handler
 | |
| ; The orignal rab value is on the stack. The interrupt handler placed
 | |
| ; rfb-Windowsize in rab. This is required to support nested interrupts.
 | |
| ;
 | |
| ; Note that the window becomes incosistent only during certain
 | |
| ; critical sections in spill, fill, longjmp and sigcode.
 | |
| ;	rfb - rab > windowsize => we are in spill
 | |
| ;	rfb - rab < windowsize => we are in fill
 | |
| ;	gr1 + 8   > rfb        => we are in long-longjmp case
 | |
| ; In case of spill, fill and lonjmp; rab is modified first,
 | |
| ; so if we are in one of these critical sections,
 | |
| ; we set rab to rfb - WINDOWSIZE.
 | |
| ;
 | |
| 	.equ	SIGCTX_SIZE,		(16)*4
 | |
| 	.equ	SIGCTX_SIGNUMB,		(15)*4
 | |
| 	.equ	SIGCTX_GR1_OFFSET,	(14)*4
 | |
| 	.equ	SIGCTX_RAB_OFFSET,	(13)*4
 | |
| 	.equ	SIGCTX_PC0_OFFSET,	(12)*4
 | |
| 	.equ	SIGCTX_PC1_OFFSET,	(11)*4
 | |
| 	.equ	SIGCTX_PC2_OFFSET,	(10)*4
 | |
| 	.equ	SIGCTX_CHC_OFFSET,	(7)*4
 | |
| 	.equ	SIGCTX_OPS_OFFSET,	(5)*4
 | |
| 	.equ	SIGCTX_TAV_OFFSET,	(4)*4
 | |
| 	.global	sigcode
 | |
| sigcode:
 | |
| ; --------------------------------------------------------  R-Stack fixup
 | |
| 	const	v0, WindowSize		; get register cache size
 | |
| 	consth	v0, WindowSize
 | |
| 	load	0, 0, v0, v0
 | |
| 	add	v2, msp, SIGCTX_RAB_OFFSET
 | |
| 	load	0, 0, v2, v2		; get interrupted rab value
 | |
| 	sub	v1, rfb, v2		; determine if  rfb-rab <= WINDOW_SIZE
 | |
| 	cpgeu	v1, v1, v0		;
 | |
| 	jmpt	v1, nfill		; jmp if spill or 'normal' interrupt
 | |
| 	add	v1, gr1, 8
 | |
| 	 cpgt	v1, v1, rfb		; interrupted longjmp can look like fill
 | |
| 	jmpf	v1, nfill		; test for long-longjmp interruption
 | |
| 	 nop				; jmp if gr1+8 <= rfb
 | |
| ; Fixup signal stack to re-start interrupted fill
 | |
| ; backup pc1 -- this is needed for the partial fill case.
 | |
| ; Clear chc so an interrupted load/store does not restart.
 | |
| ; Reset rab to a window distance below rfb, rab shall be
 | |
| ; decremented again on re-starting the interrupted fill.
 | |
| ; The interrupt handler set rab=rfb-WindowSize.
 | |
| ;
 | |
| 	add	v0, msp, SIGCTX_RAB_OFFSET
 | |
| 	store	0, 0, rab, v0		; re-store (rfb-WindowSize) for rab
 | |
| 	const	v2, fill
 | |
| 	consth	v2, fill
 | |
| 	add	v0, msp, SIGCTX_PC1_OFFSET
 | |
| 	store	0, 0, v2, v0
 | |
| 	sub	v2, v2, 4		; determine pc0
 | |
| 	add	v0, msp, SIGCTX_PC0_OFFSET
 | |
| 	store	0, 0, v2, v0
 | |
| 	const	v2, 0			; clear chc
 | |
| 	add	v0, msp, SIGCTX_CHC_OFFSET
 | |
| 	store	0, 0, v2, v0
 | |
| 
 | |
| nfill:
 | |
| 	cpgt	v0, gr1, rfb		; if gr1 > rfb then gr1 = rfb
 | |
| 	jmpt	v0, lower
 | |
| 	 cplt	v0, gr1, rab		; if gr1 < rab then gr1 = rab
 | |
| 	jmpt	v0, raise
 | |
| 	 nop
 | |
| ; -------------------------------------------------------- save_regs
 | |
| sig1:	sub	msp, msp, (4+2+25)*4	; reserve space for regs
 | |
| 	mfsr	gr96, ipc
 | |
| 	mfsr	gr97, ipa
 | |
| 	mfsr	gr98, ipb
 | |
| 	mfsr	gr99, q
 | |
| 	mtsrim	cr, 4-1
 | |
| 	storem  0, 0, gr96, msp
 | |
| ;					 "push" registers stack support
 | |
| 	add	gr96, lr1, 0
 | |
| 	add	gr97, rfb, 0
 | |
| 	mtsrim	cr, 2-1
 | |
| 	add	gr99, msp, 2*4
 | |
| 	storem  0, 0, gr96, gr99
 | |
| ;					  "push" remaining global registers
 | |
| 	mtsrim	cr, 25-1		; gr100-gr124
 | |
| 	add	gr96, msp, (4+2)*4
 | |
| 	storem  0, 0, gr100, gr96
 | |
| ;
 | |
| ; -------------------------------------------------------- Dummy Call
 | |
| 	.equ	RALLOC, 4*4		; make space for function calls
 | |
| 	add	v0, rfb, 0		; store original rfb
 | |
| 	sub	gr1, gr1, RALLOC
 | |
| 	asgeu	V_SPILL, gr1, rab
 | |
| 	add	lr1, v0, 0		; set lr1 = original rfb
 | |
| 	add	v1, msp, (4+2+25)*4 + SIGCTX_SIGNUMB
 | |
| 	load	0, 0, lr2, v1		; restore signal number
 | |
| 	sub	v1, lr2, 1		; get handler index
 | |
| 	sll	v1, v1, 2		; point to addresses
 | |
| ;
 | |
| ; -------------------------------------------------------- call C-level
 | |
| ; Handler must not use HIF services other than the _sigret() type.
 | |
| 	const	v0, SigEntry
 | |
| 	consth	v0, SigEntry
 | |
| 	add	v0, v0, v1
 | |
| 	load	0, 0, v0, v0		; determine if handler registered
 | |
| 	cpeq	v1, v0, 0
 | |
| 	jmpt	v1, NoHandler
 | |
| 	 nop
 | |
| 	calli	lr0, v0			; call C-level signal handler
 | |
| 	 nop
 | |
| ;
 | |
| ; -------------------------------------------------------- default return
 | |
| NoHandler:
 | |
| 	jmp	__sigdfl
 | |
| 	 nop
 | |
| 
 | |
| ; -------------------------------------------------------- support bits
 | |
| lower:	sll	gr1, rfb, 0
 | |
| 	jmp	sig1
 | |
| 	 nop
 | |
| raise:	sll	gr1, rab, 0
 | |
| 	jmp	sig1
 | |
| 	 nop
 | |
| /*
 | |
| ; -------------------------------------------------------- repair_regs
 | |
| 	mtsrim	cr, 4-1
 | |
| 	loadm	0, 0, gr96, msp
 | |
| 	mtsr	ipc, gr96
 | |
| 	mtsr	ipa, gr97
 | |
| 	mtsr	ipb, gr98
 | |
| 	mtsr	Q, gr99
 | |
| ;					 "pop" registers stack support
 | |
| 	mtsrim	cr, 2-1
 | |
| 	add	gr99, msp, 2*4
 | |
| 	loadm	0, 0, gr96, gr99
 | |
| 	add	lr1, gr96, 0
 | |
| 	add	rfb, gr97, 0
 | |
| ;					  "pop" remaining global registers
 | |
| 	mtsrim	cr, 25-1		; gr100-gr124
 | |
| 	add	gr96, msp, (4+2)*4
 | |
| 	loadm	0, 0, gr100, gr96
 | |
| 	add	msp, msp, (4+2+25)*4	; repair msp to save_regs entry value
 | |
| ; -------------------------------------------------------- end repair
 | |
| */
 | |
| 
 | |
| ; ======================================================== _sigret()
 | |
| 	.global	__sigret
 | |
| __sigret:
 | |
| ;	repair_regs
 | |
| ; -------------------------------------------------------- repair_regs
 | |
| 	mtsrim	cr, 4-1
 | |
| 	loadm	0, 0, gr96, msp
 | |
| 	mtsr	ipc, gr96
 | |
| 	mtsr	ipa, gr97
 | |
| 	mtsr	ipb, gr98
 | |
| 	mtsr	q, gr99
 | |
| ;					 "pop" registers stack support
 | |
| 	mtsrim	cr, 2-1
 | |
| 	add	gr99, msp, 2*4
 | |
| 	loadm	0, 0, gr96, gr99
 | |
| 	add	lr1, gr96, 0
 | |
| 	add	rfb, gr97, 0
 | |
| ;					  "pop" remaining global registers
 | |
| 	mtsrim	cr, 25-1		; gr100-gr124
 | |
| 	add	gr96, msp, (4+2)*4
 | |
| 	loadm	0, 0, gr100, gr96
 | |
| 	add	msp, msp, (4+2+25)*4	; repair msp to save_regs entry value
 | |
| ; -------------------------------------------------------- end repair
 | |
| 	const	tav, 323		; HIF _sigret
 | |
| 	asneq	69, gr1,gr1
 | |
| 	halt				; commit suicide if returns
 | |
| 
 | |
| ; ======================================================== _sigdfl()
 | |
| 	.global	__sigdfl
 | |
| __sigdfl:
 | |
| ;	repair_regs
 | |
| ; -------------------------------------------------------- repair_regs
 | |
| 	mtsrim	cr, 4-1
 | |
| 	loadm	0, 0, gr96, msp
 | |
| 	mtsr	ipc, gr96
 | |
| 	mtsr	ipa, gr97
 | |
| 	mtsr	ipb, gr98
 | |
| 	mtsr	q, gr99
 | |
| ;					 "pop" registers stack support
 | |
| 	mtsrim	cr, 2-1
 | |
| 	add	gr99, msp, 2*4
 | |
| 	loadm	0, 0, gr96, gr99
 | |
| 	add	lr1, gr96, 0
 | |
| 	add	rfb, gr97, 0
 | |
| ;					  "pop" remaining global registers
 | |
| 	mtsrim	cr, 25-1		; gr100-gr124
 | |
| 	add	gr96, msp, (4+2)*4
 | |
| 	loadm	0, 0, gr100, gr96
 | |
| 	add	msp, msp, (4+2+25)*4	; repair msp to save_regs entry value
 | |
| ; -------------------------------------------------------- end repair
 | |
| 	const	tav, 322		; HIF _sigdfl
 | |
| 	asneq	69, gr1,gr1
 | |
| 	halt				; commit suicide if returns
 | |
| 
 | |
| ; ======================================================== _sigrep()
 | |
| __sigrep:
 | |
| 	.global	__sigrep
 | |
| ;	repair_regs
 | |
| ; -------------------------------------------------------- repair_regs
 | |
| 	mtsrim	cr, 4-1
 | |
| 	loadm	0, 0, gr96, msp
 | |
| 	mtsr	ipc, gr96
 | |
| 	mtsr	ipa, gr97
 | |
| 	mtsr	ipb, gr98
 | |
| 	mtsr	q, gr99
 | |
| ;					 "pop" registers stack support
 | |
| 	mtsrim	cr, 2-1
 | |
| 	add	gr99, msp, 2*4
 | |
| 	loadm	0, 0, gr96, gr99
 | |
| 	add	lr1, gr96, 0
 | |
| 	add	rfb, gr97, 0
 | |
| ;					  "pop" remaining global registers
 | |
| 	mtsrim	cr, 25-1		; gr100-gr124
 | |
| 	add	gr96, msp, (4+2)*4
 | |
| 	loadm	0, 0, gr100, gr96
 | |
| 	add	msp, msp, (4+2+25)*4	; repair msp to save_regs entry value
 | |
| ; -------------------------------------------------------- end repair
 | |
| 	const	tav, 324		; HIF _sigrep
 | |
| 	asneq	69, gr1,gr1
 | |
| 	halt				; commit suicide if returns
 | |
| 
 | |
| ; ======================================================== _sigskp()
 | |
| 	.global	__sigskp
 | |
| __sigskp:
 | |
| ;	repair_regs
 | |
| ; -------------------------------------------------------- repair_regs
 | |
| 	mtsrim	cr, 4-1
 | |
| 	loadm	0, 0, gr96, msp
 | |
| 	mtsr	ipc, gr96
 | |
| 	mtsr	ipa, gr97
 | |
| 	mtsr	ipb, gr98
 | |
| 	mtsr	q, gr99
 | |
| ;					 "pop" registers stack support
 | |
| 	mtsrim	cr, 2-1
 | |
| 	add	gr99, msp, 2*4
 | |
| 	loadm	0, 0, gr96, gr99
 | |
| 	add	lr1, gr96, 0
 | |
| 	add	rfb, gr97, 0
 | |
| ;					  "pop" remaining global registers
 | |
| 	mtsrim	cr, 25-1		; gr100-gr124
 | |
| 	add	gr96, msp, (4+2)*4
 | |
| 	loadm	0, 0, gr100, gr96
 | |
| 	add	msp, msp, (4+2+25)*4	; repair msp to save_regs entry value
 | |
| ; -------------------------------------------------------- end repair
 | |
| 	const	tav, 325		; HIF _sigskp
 | |
| 	asneq	69, gr1,gr1
 | |
| 	halt				; commit suicide if returns
 | |
| 
 | |
| ; ======================================================== _sendsig()
 | |
| ; lr2 = signal number
 | |
| 	.global _raise
 | |
| 	.global	__sendsig
 | |
| _raise:
 | |
| __sendsig:
 | |
| 	const	tav, 326		; HIF sendsig
 | |
| 	asneq	69, gr1,gr1
 | |
| 	jmpi	lr0
 | |
| 	 nop
 | |
| 
 | |
| ;
 | |
| ; ======================================================== signal()
 | |
| ;	lr2 = signal number
 | |
| ;	lr3 = handler address
 | |
| 	.global	_signal
 | |
| _signal:
 | |
| ; the memory variable WindowSize must be initalised at the
 | |
| ; start when rfb and rab are a window size apart.
 | |
| 	const	v0, WindowSize		; get register cache size
 | |
| 	consth	v0, WindowSize
 | |
| 	load	0, 0, v1, v0
 | |
| 	cpeq	v1, v1, 0
 | |
| 	jmpf	v1, WindowSizeOK
 | |
| 	 sub	v1, rfb, rab		; rfb-rab = WINDOW_SIZE
 | |
| 	store	0, 0, v1, v0
 | |
| WindowSizeOK:
 | |
| 	const	v1, SigEntry
 | |
| 	consth	v1, SigEntry
 | |
| 	sub	v3, lr2, 1		; get handler index
 | |
| 	sll	v3, v3, 2		; pointer to addresses
 | |
| 	add	v1, v1, v3
 | |
| 	store	0,0, lr3, v1		; save new handler
 | |
| 
 | |
| 	const	lr2, sigcode
 | |
| 	consth	lr2, sigcode
 | |
| 	;Fall through to __signal
 | |
| ; ======================================================== _signal()
 | |
| 	.global	__signal
 | |
| __signal:
 | |
| 	const	tav, 321		; HIF signal
 | |
| 	asneq	69, gr1,gr1
 | |
| 	jmpi	lr0
 | |
| 	 nop
 |