PDP7-Unix/sys/s1.s
" S1
.. = 0
t = 0
orig:
hlt " overwritten with interrupt return addr
jmp pibreak " dispatch to interrupt processing
. = orig+7
-1 " only ever set (to -1): never read?!
. = orig+020 " syscall (CAL) and user "interrupt" processing
1f " addr for "CAL I": store return here on "CAL"
iof " interrupts off
dac u.ac " save user AC
lac 020 " save user return addr
dac 1f " save as if "CAL I"
lac 1f-1
dac 020 " restore location 20
lac u.ac " restore user AC
jmp 1f+1 " join "CAL I" processing
1f " literal to restore location 20
1: 0 " "CAL I" PC stored here
iof " interrupts off
dac u.ac " save user AC
lacq
dac u.mq " save user MQ
lac 8
dac u.rq " save user auto-index location 8
lac 9
dac u.rq+1 " save user auto-index location 9
jms copy; 10; u.rq+2; 6 " save user auto-index locations 10-15
lac 1b " load user PC after system call
dac u.rq+8 " save user PC
-1 " load -1
dac .savblk " set "save" flag (cleared by disk I/O?)
dac .insys " set "in system" flag
lac uquant " load user quantum count
jms betwen; d0; maxquant " check if between 0 & maxquant??
jms swap " no: swap processes
ion " interrupts on
-1
tad u.rq+8 " get address of system call
jms laci " load AC indirect??
jms betwen; o20001; swn " range check
jmp badcal " bad system call
tad swp " add system call table base
dac .+1 " save as next instruction
jmp .. i " dispatch system call
. = orig+0100
jmp coldentry " here to start kernel
jms halt
okexit:
dzm u.ac " 'OK' system call exit: clear user AC
sysexit: " common system call exit code
ion " enable interrupts
lac .savblk " load "save" flag
sza " is zero (cleared by disk I/O)?
jmp 1f " no: no disk I/O done?
jms copy; sysdata; dskbuf; 64 " copy system data to disk buffer
cla
jms dskio; 07000 " save to disk?
1:
dzm .insys " clear "in system call" flag
jms chkint " pending user interrupt?
skp " no
jmp .save " yes: dump core
jms copy; u.rq+2; 10; 6 " restore auto-index locations 10-15
lac u.rq+1 " restore auto-index location 9
dac 9
lac u.rq " restore auto-index location 8
dac 8
lac u.mq " restore MQ register
lmq
lac u.ac " restore AC register
jmp u.rq+8 i " return to user
" scheduler / idle loop
swap: 0
ion
1:
jms lookfor; 3 " out/ready
jmp 1f
jms lookfor; 1 " in/ready
skp
jmp 1b " loop until a process becomes ready
dzm maxquant " in/ready (self?): come back next tick!
jmp 3f
1: " here with out/ready process
dac 9f+t " save process pointer (swapped out) in t0
jms lookfor; 2 " in/notready " find a swapped in process to swap out?
jmp 1f
jms lookfor; 1 " in/ready
jmp 1f
jmp 2f
1:
lac swap
dac u.swapret " return to caller when swapped back
iof
lac o200000 " change status to swapped out
tad u.ulistp i
dac u.ulistp i
ion
jms dskswap; 07000 " swap process out
lac u.dspbuf
sna " process using display??
jmp 2f " no
law dspbuf " reset to default display buffer
jms movdsp
2:
iof " disable interrupts
lac o600000 " change status (1->7?????)
tad 9f+t i
dac 9f+t i
ion " enable interrupts
jms dskswap; 06000 " read process in?
lac u.swapret " set our return addr
dac swap " to saved return addr
lac o20 " reset maxquant to 16 ticks
dac maxquant
lac u.dspbuf
sza " using display?
"** 01-s1.pdf page 4
jms movdsp " yes. switch to user display bufferx
3:
dzm uquant " no. reset process tick count
iof
jmp swap i " return
t = t+1
swp: " system call dispatch table
jmp . " base instruction
.save; .getuid; .open; .read; .write; .creat; .seek; .tell
.close; .link; .unlink; .setuid; .rename; .exit; .time; .intrp
.chdir; .chmod; .chown; badcal; .sysloc; badcal; .capt; .rele
.status; badcal; .smes; .rmes; .fork
swn:
.-swp-1 i " count of system calls, plus indirect!
" AC/ new value for intflg (non-zero to ignore interrupt char)
" sys intrp
.intrp:
lac u.ac
dac u.intflg
jmp okexit
" syscall to retrieve system addresses (data & routines!!)
" AC/ index (1..17)
" sys sysloc
" AC/ address (or -1 on bad index)
.sysloc:
lac u.ac
and o17777
jms betwen; d1; locn
jms error
tad locsw
dac .+1
lac ..
dac u.ac
jmp sysexit
locsw: " table of system addresses for sysloc
lac .
iget; inode; userdata; sysdata; copy; copyz; betwen; dskrd
dskwr; dskbuf; dpdata; namei; pbsflgs; alloc; free; dspdata
crdata
locn:
.-locsw-1
" check if "interrupt" for current process
" checks .int1 and .int2 (contain i-number of interrupt source)
" compared against process stdin
"
" call:
" .insys/ 0
" jms chkint
" no: no interrupt, or intflg set (discards interrupt)
" yes: PI off, .insys set
chkint: 0
lac .insys
sza " in system?
jmp chkint i " yes: return
lac .int1 " get inumber of interrupt1 source?
sna " zero?
jmp 1f " yes: skip stdin check
sad u.ofiles+2 " non-zero: compare to stdin inumber
jmp 2f " same
1:
lac .int2 " get inum of interrupt 2 source?
sna " zero?
jmp chkint i " yes: return
sad u.ofiles+2 " non-zero: compare to stdin inumber
skp " match!
jmp chkint i " no match: return
dzm .int2 " clear int2 source
jmp 1f
2:
dzm .int1 " clear int1 source
1:
"** 01-s1.pdf page 5
lac u.intflg " get user intflg
sza " zero?
jmp chkint i " no: ignore
-1
dac .insys " set "in system" flag
ion " enable interrupts
isz chkint " give skip return
jmp chkint i