; IfsInterrupt.Asm -- IFS version of interrupt handler ; CauseInterrupt, DestroyInterrupt, (+ interrupt handler) ; Copyright Xerox Corporation 1980 ; last modified March 18, 1980 7:28 PM by Taft ; - save and restore interruptXJmp and interruptXPC for Extended Emulator ; Based on Interrupt.Asm, from Interrupt package, ; last modified September 4, 1979 2:30 PM by Taft .ent CauseInterrupt .ent DestroyInterrupt .ent interruptPrologue .ent interruptsActive .ent interruptFinish .ent savedUserFinishProc .bext lvUserFinishProc .srel CauseInterrupt: .Cause DestroyInterrupt: .Destroy interruptPrologue: .Prologue interruptsActive: 0 ; Bits that I have turned on! interruptFinish: .IntFin savedUserFinishProc: -1 ; -1 means nothing yet saved .zrel InterruptEntry: .IntEnt .nrel 0 ; Sacrifice to Bldr ; Offsets of things in IST (Interrupt Stack); same as in InterruptInit.Bcpl ; Prologue is in 0, 1 R=2 ; Point where AC3 will point .AC0=2 ; Machine state.... .AC1=3 .AC2=4 .AC3=5 .PC=6 .XJmp=7 .XPC=8. .StkMin=9. ; Old stack min .ACT=10. ; Active lshift 1 + carry ; Context to run the guy in: .NMask=11. ; New interrupt mask .NStack=12. .NStkMin=13. .InitPC=14. ; Procedure to call .StkBot=15. ; Bottom of stack -- place 335 will point to. ; Bcpl runtime location StkMin=335 ; page one addresses base = 600 ; base for page 1 addressing wakeupsWaiting = 452 activeInterrupts = 453 interruptPC = 500 interruptXJmp = 627 ; XJMP b -- interruptPC (500B) points here interruptXPC = 630 ; real PC ; The following 2 prologue words are recorded in the IST. ; When an interrupt fires, control transfers to the IST, which ; saves AC3 and jsr's to common code for saving the remainder ; of the state .Prologue: sta 3,.Prologue+.AC3 ; State-saving prologue in each IST jsr @InterruptEntry ;----------------------------------------------------------------- .IntEnt: ;----------------------------------------------------------------- sta 2 .AC2-R 3 ; Common code to save state sta 1 .AC1-R 3 sta 0 .AC0-R 3 lda 2 .base lda 0 interruptPC-base 2 sta 0 .PC-R 3 lda 0 StkMin sta 0 .StkMin-R 3 lda 0 interruptXJmp-base 2 sta 0 .XJmp-R 3 lda 0 interruptXPC-base 2 sta 0 .XPC-R 3 lda 0 activeInterrupts-base 2 ; Save current active interrupts movl 0 1 ; Save carry (bit 0 of active unused) sta 1 .ACT-R 3 lda 1 .NMask-R 3 ; Interrupts to leave on. and 1 0 ; Compute new active sta 0 activeInterrupts-base 2 ; And put it down. eir ; Now can proceed. ; Set up new context, and call the specified procedure. ; Interrupt will be dismissed when procedure returns. lda 2 .NStkMin-R 3 sta 2 StkMin lda 2 .NStack-R 3 jsr @.InitPC-R 3 ; Call procedure 0 ; With no arguments. ; Restore state that was saved in the IST, and dismiss interrupt. lda 3 0 2 ; Recover IST pointer dir ; Prepare to restore state lda 1 .ACT-R 3 movzr 1 1 ; Restore carry lda 2 .base sta 1 activeInterrupts-base 2 ; Restore active lda 1 .XJmp-R 3 sta 1 interruptXJmp-base 2 lda 1 .XPC-R 3 sta 1 interruptXPC-base 2 lda 1 .StkMin-R 3 sta 1 StkMin lda 1 .PC-R 3 sta 1 interruptPC-base 2 lda 0 .AC0-R 3 lda 1 .AC1-R 3 lda 2 .AC2-R 3 lda 3 .AC3-R 3 bri ; Off to see the world .base: base ;----------------------------------------------------------------- .IntFin: ;----------------------------------------------------------------- ; called on Finish or Abort to disable any interrupts that ; we may have turned on. sta 3 1 2 lda 0,@.IntAct ; Turn off interrupts that are on. jsr .Destroy 1 lda 0,@.savedUserFinishProc ; Restore old finish routine lda 3,@.lvUserFinishProc sta 0,0,3 lda 3 1 2 jmp 1 3 .IntAct: interruptsActive .savedUserFinishProc: savedUserFinishProc .lvUserFinishProc: lvUserFinishProc ;----------------------------------------------------------------- .Destroy: ;----------------------------------------------------------------- ; DestroyInterrupt(mask) ; Turn off interrupt channel(s) designated by mask com 0,0 ; Prepare to "and" with active dir lda 1,@.Active and 0,1 sta 1,@.Active ; All gone! eir lda 1 @.IntAct ; Update our record and 0 1 sta 1 @.IntAct jmp 1,3 ; Return ;----------------------------------------------------------------- .Cause: ;----------------------------------------------------------------- ; CauseInterrupt(mask) ; Initiate interrupt on channel(s) designated by mask com 0,0 ; Prepare to "or" with wakeups waiting dir lda 1,@.Wakeups and 0,1 adc 0,1 sta 1,@.Wakeups eir jmp 1,3 .Wakeups: wakeupsWaiting .Active: activeInterrupts .end