Files
pdp7-unix/src/sys/s1.s
T

216 lines
6.0 KiB
ArmAsm

" S1
.. = 0
t = 0
orig:
hlt " overwritten with interrupt return addr
jmp pibreak " dispatch to interrupt processing
. = orig+7 " real time (60Hz) clock
-1 " -1 will cause "clock overflow" on next tick
" Overflow is checked by "clsf" instr
" in PI service (pibreak) routine,
" reset to -1 after tick handling
" results in an interrupt every "jiffy"
. = orig+020 " syscall (CAL) and user "interrupt" processing
1f " addr for "CAL I": store return here on "CAL"
iof " here on CAL: 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 in user area
lacq
dac u.mq " save user MQ in user area
lac 8
dac u.rg " save user auto-index location 8 in uarea
lac 9
dac u.rg+1 " save auto-index location 9 in user area
jms copy; 10; u.rg+2; 6 " save auto-index locations 10-15 (using 8/9!)
lac 1b " load user PC
dac u.rg+8 " save in user area
-1 " load -1
dac .savblk " set "save" flag (cleared by disk I/O?)
dac .insys " set "in system" flag
lac uquant " load user quantum (tick) count
jms betwen; d0; maxquant " check if between 0 & maxquant (30 jiffies)
jms swap " no: quantum expired: swap process out
ion " interrupts on
-1
tad u.rg+8 " get address of system call
jms laci " load system call instruction
jms betwen; o20001; swn " range check (expects CAL I!)
jmp badcal " bad system call
tad swp " add "jmp syscall_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, return to user
jmp .save " yes: dump core
jms copy; u.rg+2; 10; 6 " restore auto-index locations 10-15 (use 8/9)
lac u.rg+1 " restore auto-index location 9
dac 9
lac u.rg " restore auto-index location 8
dac 8
lac u.mq " restore MQ register
lmq
lac u.ac " restore AC register
jmp u.rg+8 i " return to user
" scheduler / swapper / 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 (149.333ms)
dac maxquant
lac u.dspbuf
sza " using display?
"** 01-s1.pdf page 4
jms movdsp " yes. switch to user display bufferx
3:
dzm uquant " 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 " last system call number: "CAL I n"
" 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
" <already ".insys", no interrupt, or intflg set (ignore interrupt)>
" <found user interrupt: 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