Interdata_v6/usr/sys/low.s
title Interdata unix low-core initialization
* conditional assembly switches
FPREGS equ 0 if 1, floating-point regs must be saved
DPREGS equ 0 if 1, double-precision regs must be saved
PIC equ 0 if 1, include precision interrupt clock timing
* (must also be defined in start.s)
entry kisa0,uisa0,ka6
entry kisa,uisa
entry addrsw,ksp
entry consaddr,conscmd2
entry trmask
entry memtop,consdev,rootdev,swapdev,swplo,nswap
entry savfp
ifnz PIC
entry sytim,utime,itime
entry stclk.a,stclk.b
endc
extrn start,dump
extrn dispint,trap,clock
extrn selchint,cntlintr,dskintr
extrn mtintr
extrn vdurint,vduxint
extrn lpint
extrn msmcintr,msmintr
extrn swtch,runrun
extrn proc
extrn u
* psw bit definitions
ps.wait equ x'8000' wait state
ps.io equ x'4000' immediate interrupt mask
ps.mm equ x'2000' machine malfunction interrupt mask
ps.af equ x'1000' arith fault interrupt mask
ps.il equ x'0800' multi level interrupts (8/32)
ps.rp equ x'0400' memory relocation / protection
ps.sq equ x'0200' system queue service mask
ps.prot equ x'0100' protect mode
ps.ureg equ x'00f0' user register set
* psw definitions
ps.user equ ps.io+ps.mm+ps.af+ps.rp+ps.prot+ps.ureg
ps.idle equ ps.wait+ps.io+ps.mm+ps.af+ps.rp+ps.ureg
ps.kern equ ps.io+ps.mm+ps.af+ps.rp+ps.ureg
ps.disb equ ps.mm+ps.af+ps.rp+ps.ureg
ps.trap equ ps.mm+ps.af
* register definitions
r0 equ 0
r1 equ 1
r2 equ 2
r3 equ 3
r4 equ 4
r5 equ 5
r6 equ 6
r7 equ 7
r8 equ 8
r9 equ 9
ra equ 10
rb equ 11
rc equ 12
rd equ 13
re equ 14
rf equ 15
sp equ r7
title low-core reserved locations
* Note: This code should be absolute, since it is loaded into
* physical low core. Unfortunately the assembler doesn't handle absolute
* code, so it must be faked as pure.
* org 0 start at physical low core
pure (not really -- see note above)
low equ *
* reserved memory location definitions
isp equ low+x'd0' interrupt-service pointer table
mac.r0 equ low+x'300' memory-access controller seg regs
mac.rs equ low+x'340' memory-access controller status reg
fsav equ 2*adc offset of f.p. reg save area (u_fsav)
dsav equ 8*4+fsav offset of d.p. reg save area (u_fsav[8])
fsaved equ 8*8+dsav offset of 'f.p. regs saved' flag (u_fsav[24])
* trap psw's and pointers
fpregs ds 8*4 floating-point regs
psw.mmo ds 8 machine malfunction old psw
dc 0,0 -
psw.ii dc ps.trap illegal instruction new psw
dc trap.ii
psw.mm dc 0 machine malfunction new psw
dc trap.mm
dc 0,0 -
psw.af dc ps.trap arith fault new psw
dc trap.af
* '50' sequence for magtape load
org low+x'50'
al x'300'
b x'80'
org low+x'60'
b start lsu start address
b dump dump start address
org low+x'78' LSU addresses
consaddr db y'10' device address of 'system console'
conscmd2 db x'38' pals command 2 for 'system console'
org low+x'80'
dc sq &(system queue)
dc z(pf.psw) &(power-fail psw save area)
dc z(pf.regs) &(power-fail reg save area)
psw.sqs dc ps.trap system queue service new psw
dc trap.sq
psw.mf dc ps.trap memory fault new psw
dc trap.mf
* svc table
psw.svc dc ps.trap svc new psw status
dc z(trap.isv) svc 0
dc z(trap.isv) svc 1
dc z(trap.isv) svc 2
dc z(trap.isv) svc 3
dc z(trap.isv) svc 4
dc z(trap.isv) svc 5
dc z(trap.isv) svc 6
dc z(trap.isv) svc 7
dc z(trap.isv) svc 8
dc z(trap.isv) svc 9
dc z(trap.isv) svc 10
dc z(trap.isv) svc 11
dc z(trap.isv) svc 12
dc z(trap.isv) svc 13
dc z(trap.svc) svc 14 - system call
ifnz PIC
dc z(trap.tim) svc 15
else
dc z(trap.isv) svc 15
endc
dc 0,0,0,0,0
* interrupt service pointer table
org isp initialize unused entries to ignore interrupts
nlist
do 256
dc z(int.null)
list
* do 256
* dc z(int.null) listing suppressed
* display console interrupt
org 2*x'01'+isp address 01
dc z(int.disp)
* line printer interrupt
org 2*x'62'+isp
dc z(int.lp)
* clock interrupts
org 2*x'6d'+isp line frequency clock
dc z(int.lfc)
* selector channel interrupt
org 2*x'f0'+isp ** selch
dc z(int.sch)
* disk controller interrupt
org 2*x'b6'+isp disk controller
dc z(int.dcnt)
* disk interrupts
org 2*x'c6'+isp removable disk
dc z(int.dsk)
org 2*x'c7'+isp fixed disk
dc z(int.dsk)
* msm disc interrupts
org 2*x'fb'+isp controller
dc z(int.mcnt)
org 2*x'fc'+isp drive 0
dc z(int.mdsk)
org 2*x'fd'+isp drive 1
dc z(int.mdsk)
* magtape interrupts
org 2*x'c5'+isp tape transport 1
dc z(int.mt)
* pals interrupts
org 2*x'10'+isp local vdu's
dc z(int.vdur),z(int.vdux) tty0
dc z(int.vdur),z(int.vdux) tty1
dc z(int.vdur),z(int.vdux) tty2
dc z(int.vdur),z(int.vdux) tty3
dc z(int.vdur),z(int.vdux) tty4
dc z(int.vdur),z(int.vdux) tty5
dc z(int.vdur),z(int.vdux) tty6
dc z(int.vdur),z(int.vdux) tty7
dc z(int.vdur),z(int.vdux) ttya
dc z(int.vdur),z(int.vdux) ttyb
dc z(int.vdur),z(int.vdux) ttyc
dc z(int.vdur),z(int.vdux) ttyd
dc z(int.vdur),z(int.vdux) ttye
dc z(int.vdur),z(int.vdux) ttyf
dc z(int.vdur),z(int.vdux) ttyg
dc z(int.vdur),z(int.vdux) ttyh
title low-core data areas
* fixed area - should not be moved
* used for emergency patching and 'ps' command
org mac.r0+x'100' skip mac area
dc a(proc) address of proc table for 'ps' command
trmask dc 0 mask for execution trace
memtop dc 256*1024 max possible memory (changed to actual amount of
* memory by start.s)
consdev dc 0 console device number (major/minor)
rootdev dc y'0200' root filesystem device number
swapdev dc y'0200' swap area device number
swplo dc 8000 first block in swap area (must be >0)
nswap dc 1600 number of blocks in swap area
* hardware-dependent area
pf.psw ds 8 power-fail psw save area
pf.regs ds 32*4 power-fail reg save area
sq dc 0,0 system queue (unused)
* mac segmentation registers
kisa0 equ * kernel mode seg regs
dc 0,0,0,0,0,0,0,0
dc 0,0,0,0,0,0,0,0
kisae equ *-8 seg e
uisa0 equ * user mode seg regs
dc 0,0,0,0,0,0,0,0
dc 0,0,0,0,0,0,0,0
kisa dc a(kisa0) ptr to kernel seg regs
uisa dc a(uisa0) ptr to user seg regs
ka6 dc a(kisae) ptr to per-process segment
* non-reentrant save area for address-space switching
align 4
ksp ds 4 kernel mode stack pointer save
nr.intp ds 4 interrupt handler address save
nr.psw ds 8 psw save
nr.regs ds 16*4 register save
title trap transfer vector
trap.mm equ * machine malfunction
btc 6,trap.mp
lm re,psw.mmo get saved old psw
bal r6,trapx
dc h'4'
trap.mp equ * memory parity error
lm re,psw.mmo get saved old psw
b trap.mf
trap.af equ * arithmetic fault
bal r6,trapx
dc h'8'
trap.mf equ * memory fault
lis r0,0
st r0,mac.rs clear mac status register
bal r6,trapx
dc h'0'
trap.ii equ * protect mode / illegal instruction
bal r6,trapx
dc h'1'
trap.isv equ * illegal supervisor call
bal r6,trapx
dc h'10'
trap.svc equ * supervisor call
lr r3,rd 'stat' is effective svc arg address
bal r6,trapx
dc h'6'
trap.sq equ * system queue service
bal r6,trapx
dc h'4'
ifnz PIC
trap.tim equ * svc 15 request 10us clock
* return in users r0 the current value of
* sytim , utime , or itime
* user must supply in r1 one of 0,4,8 to get
* the corresponding value of the above
stm re,nr.psw save old psw for quick return
epsr rc,rc current ps
ohi rc,ps.ureg switch to user regs
epsr r0,rc
ni r1,x'c' make sure offset is legal
l r0,sytim(r1) load requested time value
lpsw nr.psw exit quickly without telling anyone
endc
* common trap routine
trapx equ *
lh r2,0(r6) get trap code
epsr rd,rd current psw
li rb,ps.kern new psw: kernel mode, enabled
la rc,trap
b call go call c trap handler
title interrupt transfer vector
int.null equ * unknown device
lpswr r0 ignore interrupt
int.disp equ * display console
la rc,dispint
b int
int.lp equ * line printer interrupt
la rc,lpint
b int
int.lfc equ * line frequency clock
la rc,clock
b int
int.sch equ * selector channel
la rc,selchint
b int
int.dcnt equ * disk controller
la rc,cntlintr
b int
int.dsk equ * disk file
la rc,dskintr
b int
int.mcnt equ * msm disk controller
la rc,msmcintr
b int
int.mdsk equ * msm disk drive
la rc,msmintr
b int
int.mt equ * mag tape
la rc,mtintr
b int
int.vdur equ * local vdu input
la rc,vdurint
b int
int.vdux equ * local vdu output
la rc,vduxint
b int
* common interrupt routine
int equ *
lr re,r0 move psw to correct regs
lr rf,r1
epsr rd,rd current psw
nhi rd,x'ffff'-ps.il all interrupt levels off (8/32)
epsr r0,rd
li rb,ps.disb new psw: kernel mode, disabled
b call go call c interrupt-handler
title call -- interface to c trap / interrupt handlers
* input: re-rf - old psw & loc
* rd - current (interrupt) psw status
* rc - interrupt routine address
* rb - interrupt routine psw status
* r2 - device address ( or trap code )
* r3 - device status ( or svc arg address )
call equ *
ifnz PIC
* read and restart the pic (precision interrupt clock)
lhi r0,x'6c' addr of pic
rhr r0,r1 read current interval
sc1 wh r0,stclk.a restart clock
ssr r0,r4
btc 8,sc1
oc r0,stclk.b
lhi r5,x'fff' max interval
sr r5,r1 current clock interval
endc
* if trap from user mode, switch to kernel address space
thi re,ps.prot user mode?
bz kernel no - kernel already
ifnz PIC
* add new interval to user time
am r5,utime increment user time
endc
la r1,kisa0 kernel seg regs
bal r6,addrsw switch address space
b nkernel
* else trap from kernel mode -- get stack pointer from register set f
kernel equ *
ifnz PIC
thi re,ps.wait
bz kernel2 not in wait
am r5,itime if wait add currnt interval to idle time
b kernel3
kernel2 am r5,sytim if kernel and not wait increment sys time
kernel3 equ *
endc
st rd,nr.psw set up resume psw
la r1,nkernel
st r1,nr.psw+adc
lr r1,rd current psw
ohi r1,ps.ureg switch to reg set f
epsr r0,r1
st sp,ksp save stack pointer
lpsw nr.psw back to reg set 0
nkernel equ *
* enable memory relocation / protection
ohi rd,ps.rp enable mac
epsr r0,rd
* save psw & status on kernel stack
l sp,ksp get kernel stack pointer
shi sp,14*adc space for 14 words
stm re,11*adc(sp) save old psw
st rb,13*adc(sp) save new psw
st r2,0(sp) save dev code
st r3,adc(sp) save status
* switch to user register set, and save regs
st rc,nr.intp save routine address
st sp,ksp save stack pointer
ohi rd,ps.ureg switch to user regs
epsr r0,rd
stm r0,nr.regs save all regs
l sp,ksp restore stack pointer
lm r8,nr.regs stack regs r0-sp
stm r8,2*adc(sp)
* reload user high regs ( to be saved by standard c linkage )
* and call c trap handler
lm r8,8*adc+nr.regs restore regs r8-rf
st rf,10*adc(sp) stack link reg
l r1,nr.intp trap routine address
l r0,13*adc(sp) new psw
epsr r2,r0
balr rf,r1 call trap routine
* on return from trap routine, check whether higher-priority process
* is now ready to run
l r1,11*adc(sp) old psw
thi r1,ps.prot user mode ?
bz noswtch no - don't switch kernel process
switch equ *
li r0,ps.disb disable interrupts
epsr r1,r0
lb r1,runrun higher-priority process waiting?
lr r1,r1
bz nswtch no - restore interrupted process
li r0,ps.kern enable interrupts
epsr r1,r0
ifnz FPREGS!DPREGS
bal rf,savfp save floating-point regs
endc
bal rf,swtch reschedule cpu to new process
b switch check again
nswtch equ *
* restore status of interrupted process
ifnz FPREGS!DPREGS
l r0,u+fsaved f.p. registers saved?
bz nofp
lis r0,0
st r0,u+fsaved
ifnz FPREGS
lme r0,u+fsav restore floating-point regs
endc
ifnz DPREGS
lmd r0,u+dsav restore double floating-point regs
endc
nofp equ *
endc
noswtch equ *
li r0,ps.disb disable interrupts
epsr r1,r0
l rf,10*adc(sp) restore link reg
stm r8,8*adc+nr.regs save r8-rf
lm r8,2*adc(sp) save r0-sp
stm r8,nr.regs
lm re,11*adc(sp) old psw
ahi sp,14*adc pop stack
* if previous mode was user, switch back to user address space
thi re,ps.prot user mode?
bz kernel1 no - stay in kernel mode
epsr rd,rd current psw
nhi rd,x'ffff'-ps.rp disable memory access controller
epsr r0,rd
la r1,uisa0 user seg regs
bal r6,addrsw
kernel1 equ *
* return to previous status
st sp,ksp save kernel stack pointer
ni re,y'ffffffff'-ps.wait turn off 'wait' bit
stm re,nr.psw save return psw
ifnz PIC
* read the pic and restart
* update sys time
lhi r0,x'6c' pic addr
rhr r0,r1 read current interval
sc2 wh r0,stclk.a restart
ssr r0,r4
btc 8,sc2
oc r0,stclk.b
lhi r5,x'fff' max interval
sr r5,r1
am r5,sytim add real interval to sys time
endc
lm r0,nr.regs restore all regs
lpsw nr.psw back to previous mode
* save floating point registers (also called from trap.c)
savfp equ *
ifnz FPREGS!DPREGS
l r0,u+fsaved f.p. regs saved?
bnzr rf
lis r0,1
st r0,u+fsaved
ifnz FPREGS
stme r0,u+fsav save single-precision regs
endc
ifnz DPREGS
stmd r0,u+dsav save double-precision regs
endc
endc
br rf
title addrsw -- switch address space
* input: r1 = &(new segmentation register values)
* r6 = return address
* must be called with mac & interrupts disabled
addrsw equ *
lhi r4,15*adc start at last reg
seglp equ *
l r0,0(r1,r4) next seg value
st r0,mac.r0(r4) store in mac reg
sis r4,adc back up
bnm seglp repeat for all seg regs
br r6
ifnz PIC
title strclk and stpclk -- start and stop pic
stclk.a dc x'2fff' 10us precision and max interval (.04 sec)
stclk.b dc x'e000' disarm pic interrupts and start
sytim dac y'0' accumulated system time
utime dac y'0' user time
itime dac y'0' idle time
endc
end