***************************************************************** * * * UNIX First-level Interrupt Handler * * * * Perkin-Elmer 7/32, 8/32, 3220, 3240 * * * ***************************************************************** entry stkovflo extrn trap extrn kisa,uisa extrn runrun extrn u * PSW bit definitions ps.flm equ y'40000' floating-point masked (3200) ps.iip equ y'20000' interruptible instruction in progress (3200) 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 & 3200) 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 ***************************************************************** * * * call: interface to C interrupt handlers * * * * re-rf - old PSW * * rd - current (interrupt) PSW status * * rc - interrupt routine address * * rb - interrupt routine PSW status * * r3 - device status ( or SVC arg address ) * * r2 - device address ( or trap code ) * * * ***************************************************************** pure align 2 entry call call equ * ifnz PIC bal r6,rdpic get last pic timing 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 am r5,utime add new interval to user time endc l r1,kisa 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 current 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 relocation epsr r0,rd * if stack pointer is out of range, set it to top of u area and force a panic l sp,ksp get kernel stack pointer ci sp,u below bottom of u area? bl badsp c sp,maxsp above top of u area? bnp goodsp badsp l sp,maxsp set to top of u area la rc,stkovflo force a panic goodsp equ * ifnz M3200 * save microcode scratchpad registers if necessary (3200 only) ti re,ps.iip interruptible instruction in progress? bz nsiip no - skip shi sp,16*adc space on stack for scratchpad regs psf 5,0(sp) save scratchpad regs nsiip equ * endc * save psw & status on kernel stack 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 li r0,12 trap 12 is give up cpu st r0,0(sp) bal rf,trap call trap routine again nswtch equ * * restore status of interrupted process 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 ifnz M3200 * restore microcode scratchpad registers (3200 only) ti re,ps.iip interruptible instruction interrupted? bz noriip no - skip psf 6,0(sp) restore scratchpad regs ahi sp,16*adc pop stack noriip equ * endc * 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 relocation epsr r0,rd l r1,uisa 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 bal r6,rdpic get last pic timing interval am r5,sytim add interval to sys time endc lm r0,nr.regs restore all regs lpsw nr.psw back to previous mode * stack overflow panic - called instead of 'trap' or interrupt routine * to force a panic when kernel stack overflows stkovflo equ * ifnz M3200 dc y'88008800' breakpoint on 3200, ill instr on other only else b * hang in a loop endc impur align adc * Non-reentrant save area for use while switching register sets align adc nr.intp das 1 interrupt handler address save align adc*2 nr.psw das 2 psw save nr.regs das 16 register save * Kernel mode stack pointer save entry ksp,maxsp align adc ksp dc 0 save stack pointer during user mode execution maxsp dc 0 pointer to top of stack segment (initialized by start) ***************************************************************** * * * addrsw: Switch Address Space Mapping * * * * input: r1 = &(new segment table descriptor) * * r6 = return address * * * * Must be called with relocation & interrupts disabled * * * ***************************************************************** pure align 2 entry addrsw addrsw equ * ifnz M3200 psf 1,0(r1) lpstd process table descriptor psf 2,4(r1) lsstd shared table descriptor else extrn macregs l r1,0(r1) address of seg registers ni r1,y'fffff' address part lhi r4,15*adc start at last reg seglp equ * l r0,0(r1,r4) next seg value st r0,macregs(r4) store in mac reg sis r4,adc back up bnm seglp repeat for all seg regs endc br r6 ***************************************************************** * * * Floating-point Register Save / Restore * * * ***************************************************************** entry savfp,restfp * save floating point registers savfp equ * ifnz FPREGS!DPREGS l r1,0(sp) fp save area in u ifnz FPREGS stme r0,0(r1) save single-precision regs endc ifnz DPREGS stmd r0,8*adc(r1) save double-precision regs endc endc br rf * restore floating point registers restfp equ * ifnz FPREGS!DPREGS l r1,0(sp) fp save area in u ifnz FPREGS lme r0,0(r1) save single-precision regs endc ifnz DPREGS lmd r0,8*adc(r1) save double-precision regs endc endc br rf ifnz PIC ***************************************************************** * * * rdpic: Get length of last precision timing interval * * * * r5 - returned value * * r6 - return address * * r0-r1 - work regs * * * ***************************************************************** pure align 2 extrn clockaddr entry rdpic rdpic equ * lb r0,clockaddr address of pic rhr r0,r1 read interval l r5,pictim previous count sr r5,r1 real current clock interval bp ras1 positive? ai r5,1000 no - must have wrapped around ras1 st r1,pictim save current count br r6 return * PIC timing information impur align adc entry sytim pictim dac 1000 last PIC interval count sytim dac 0 accumulated system time | MUST BE utime dac 0 user time | KEPT itime dac 0 idle time | TOGETHER endc db c'@(#)call.s 3.4',0 pure align adc*2 impur align adc*2