h60970
s 00202/00000/00000
d D 1.1 82/08/03 08:49:13 cecily 1 0
e
u
U
t
T
I 1
	title	signal -- interface to c signal routines

.signal	equ	48

	entry	signal
r0	equ	0
r1	equ	1
r2	equ	2
r3	equ	3
r4	equ	4
r5	equ	5
sp	equ	7
rf	equ	15
*
* signal(sig, func)
*
* note: this routine is *not* strictly reentrant.  if signal() is 
*   interrupted by a signal routine which itself calls signal(),
*   the svc may be called incorrectly.
*
nsig	equ	16	* add to brtab if this constant changes *
EINVAL	equ	22
	pure
signal	equ	*
*
* save previous signal value
*
	l	r1,0(sp)	sig
	bnp	illsig		must be +ve
	chi	r1,nsig		check range
	bp	illsig		too high
	lr	r0,r1		save sig number
	slls	r1,2		offset in sig table
	l	r5,sigtab-adc(r1)	previous value
*
* if func is nonzero and even, it's a function address
*
	l	r2,adc(sp)	func
	st	r2,sigtab-adc(r1)	set into sig table
	bz	nofunc		zero - not an address
	lis	r3,1		check low bit
	nr	r3,r2
	bnz	nofunc		odd - not an address
*
* replace function by branch table address so regs can be saved
*
	lr	r3,r1		signo * 4
	slls	r3,2		offset in branch table
	la	r2,brtab-16(r3)	branch table address
nofunc	equ	*
*
* call signal svc
*
	st	r0,svc.no	set signal number
	st	r2,svc.fn	set function address
	svc	0,0		* signal *
	dc	a(svcsig)
	bc	sigerr		carry bit -- error
*
* return previous signal value
*
	lis	r3,1		check low bit
	nr	r3,r0
	bnzr	rf		odd - signal previously ignored
	lr	r0,r5		return actual func address
	br	rf
*
* error exits
*
illsig	equ	*
	lhi	r0,EINVAL	invalid argument
sigerr	equ	*
	st	r0,errno	set error number
	lcs	r0,1		error return
	br	rf
*
* branch table -- save regs & transfer to actual function address
* note: entries must be 16 bytes long!
*
*
	align	adc
brtab	equ	*	nsig entries
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,1*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,2*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,3*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,4*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,5*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,6*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,7*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,8*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,9*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,10*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,11*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,12*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,13*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,14*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,15*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,16*adc(0)
*
*
* call c function
*
callfunc equ	*
	l	r0,18*adc(sp)	previous sp value
	st	r0,sp*adc(sp)	save it
	l	r2,sigtab-adc(r1)	function address
	sis	sp,adc
	srls	r1,2		pass signal number
	st	r1,0(sp)	to catching routine
	bal	rf,0(r2)	call function
	ais	sp,adc
	l	r0,sp*adc(sp)	possibly changed sp value
	st	r0,18*adc(sp)	restore it
	st	sp,sp*adc(sp)
	lm	r0,0(sp)	restore regs
	ahi	sp,16*adc	pop stack
*
* return from interrupt
*
	svc	0,.signal		* signal 0 *
	dc	0
	impur
*
* signal svc
*
svcsig	equ	*
	svc	0,.signal		* signal *
svc.no	dc	0		signal number
svc.fn	dc	0		function address
*
* sig table - func value for each signal
*
sigtab	equ	*
	do	nsig
	dc	0

errno	comn
	das	1
	ends
	end
E 1
