Trailing-Edge
-
PDP-10 Archives
-
decuslib10-07
-
43,50433/paspsi.mac
There are 4 other files named paspsi.mac in the archive. Click here to see a list.
title PASPSI
;This here is a set of routines for using the PSI system in PASCAL.
;Each condition established is assigned an "index". Internally this
;is the index into various tables. As far as the user is concerned it
;is simply a small non-negative integer. The user is assumed to have
;read the writeup on PSI in the monitor calls manual.
;WARNING: The interrupt handler is not reentrant. This means that we
;are in big trouble if the user does a PSIADD specifying that interrupts
;remain enabled when at interrupt level. If you want to make it
;reentrant, consider:
; use some AC other than 17 in the dispatch process, so the stack is
; always valid
; see if the code around INTMOD is reentrant
; figure out a way to make the critical section stuff support multiple
; levels of interrupts. Probably they would have to be stacked.
; change code so no variables in low seg are used. Do everything on
; the stack
;edit history
;2 - make LH of saved procedure addr be zero, since use it for indirection
; From J Hammer at CSL
len==20 ;assembly parameter: maximum no. of conditions active
;(i.e. all values of index must be less than len)
search uuosym
a=1
b=2 ;first argument
c=3
d=4
e=5
f=6
p=17
entry psiadd,psirem,psiini,psion,psioff,psiclr
%i=0
vector: ;This is the main vector for the psi system
repeat len,<
disp+2*%i ;new PC - entry point for interrupt
0 ;old PC
1b2 ;indicates no more interrupts until debreak
0 ;status
%i=%i+1
>
dispt: block len ;pascal routine to call on interrupt
disp: ;This is the place where interrupt handling begins
repeat len,<
movem 17,apracs+17
jsp 17,intmod
>
pisys: block 3*len ;this contains argument blocks for PISYS.
apracs: block 20 ;place to store ac's
index: block 1 ;place to store index on entry
resume: block 1 ;stores addr of appropriate OLD PC word in vector when
;resuming a critical section
intmod: ;This is the main interrupt processor and dispatcher
movem 17,index ;tells us which place we came from (index*2)
skipge in.crt## ;in critical section?
jrst docrit ;yes - resume it
movei 17,apracs
blt 17,apracs+16
move 17,apracs+17 ;we need to use the pdl pointer!
hrrz b,index ;this is pointer into disp.
subi b,disp+2 ;this gives index into disp
lsh b,-1 ;divide by 2 arg1 = "index"
move f,b ;f will be index*4, pointer into vector
imuli f,4
move c,vector+.psvop(f) ;arg2 = "old PC"
hrrz d,vector+.psvfl(f) ;arg3 = "reason"
move e,vector+.psvis(f) ;arg4 = "status"
;The following assumes that we can start our stack above the
;main program's. This will work unless we have interrupted a
;call of a procedure with more than 5 words of parameters. In
;that case stuff is put above the top of stack pointer.
;I don't have a general solution, but for any given program
;you can easily find out the maximum offset it uses above the
;stack and use that in the following line instead of the 200.
;200 should be enough except if big arrays are being passed by
;value.
hrri p,200(p) ;give us some space, just for luck
caig 15,40(p)
jsp 1,corerr## ;get more core if needed
movei f,tty## ;save state of TTY system
push p,2(f)
push p,36(f)
push p,37(f)
push p,43(f)
movei f,ttyout##
push p,43(f)
push p,1(p) ;routine will garbage p-1
pushj p,@dispt(b) ;go to SAIL routine. note it can look at a,b,c
pop p,0(p)
movei e,ttyout##
pop p,43(e)
movei e,tty##
pop p,43(e)
pop p,37(e)
pop p,36(e)
pop p,2(e)
movem 15,apracs+15 ;use new value of 15 if it changed
hrlzi 17,apracs ;now restore the world
blt 17,17
debrk. ;will return to interrupted thing
halt .
halt .
;index = psiadd(type,reasonbits,proc,control)
; Adds a condition. Does not turn on PSI system. Also makes like INTMAP.
; type - code for type of interrupt
; reasonbits - condition for I/O interrupts, 0 otherwise
; proc - procedure to call for immediate interrupt
; control - for setting LH of word 3 of vector
; Returns index, or -1 if table full
psiadd: setz a, ;a will be index
;compute index for new entry
psia1: skipn dispt(a) ;is this entry in use?
jrst psia2 ;no - use it
caige a,len-1 ;yes - last one checked?
aoja a,psia2 ;no - try again
setom 1(p) ;table full - return -1
popj p,
;set up what will happen at interrupt
psia2: hrrzm 4,dispt(a);[2] dispatch addr
;set up block at vector
move d,a ;d = a*4, offset into vector
lsh d,2
hrlz 5,5 ;flag bits go in lh
movem 5,vector+.psvfl(d)
;set up block for pisys.
move e,a ;e = a*3, offset into pisys
imuli e,3
hrl c,d ;vector offset in LH - reason in RH
movem c,pisys+1(e)
movem 2,pisys(e);type
setzm pisys+2(e);must be zero
;do the pisys
movsi b,(ps.fac)
hrri b,pisys(e)
pisys. b,
halt .
movem a,1(p) ;return index
popj p,
;psirem(index)
; removes a condition set up by psiadd, and clears table entries
; index - return from psimap
psirem: move a,b ;save index
imuli b,3 ;index into pisys
movei b,pisys(b)
hrli b,(ps.frc) ;turn off condition
pisys. b,
halt .
setzm dispt(a) ;release the entry
popj p,
;psiclr(index)
; clears all pending interrupts for one condition
; index - return from psiadd for the condition
psiclr: imuli b,3 ;index into pisys
movei b,pisys(b)
hrli b,(ps.fcs) ;clebr bll interrupts
pisys. b,
halt .
popj p,
;psiini
; Must be done before any psion or psioff. Mainly does PIINI.
; no arguments
psiini: movei a,vector
piini. a,
halt .
setzm dispt ;clear old interrupts
move a,[dispt,,dispt+1]
blt a,dispt+len-1
popj p,
;psion
; Turns on PSI system
;psioff
; Turns off PSI system
psion: skipa a,[ps.fon]
psioff: movsi a,(ps.fof)
pisys. a,
halt .
popj p,
subttl Critical section code
entry enterc,leavec
;Here from INTMOD when interrupted in critical section - go back to user
docrit: hrrz 17,17 ;get addr only of place in dispt
subi 17,disp+2 ;compute index in vector
lsh 17,1 ;now have index * 4
movei 17,vector+.psvop(17) ;now get addr of OLD PC word
tlo 17,(Z @) ;make it indirect
movem 17,resume ;and save it for resuming code
sos in.crt ;make incrit be -2
move 17,apracs+17 ;now return to user
jrstf @resume
;Here from LEAVEC when leaving an critical section that was resumed by
;DOCRIT. Go back and handle the interrupt
conint: hrrzs resume ;clear indirect bit in RESUME
pop p,@resume ;put return PC into OLD PC word
setzm in.crt ;no longer in critical section
movem 17,apracs+17 ;now simulate interrupt dispatch
move 17,index
jrst intmod
;ENTERC - called by user to enter critical section
enterc: setom in.crt ;say in critical section
popj p,
;LEAVEC - called by user at end of critical section, to resume interrupts
leavec: aosge in.crt ;clear flag unless an interrupt happened
pushj p,conint ;interrupt happened, continue it
popj p,
end