:Title[LFaults.dmc, December 6, 1982 1:28 PM, Masinter]; % Lisp fault handler. If the fault was an emulator map fault or a stack error, and the emulator running at the time was Lisp, then calls the appropriate trap procedure. For any other fault, halts at one of the following breakpoints: (In fault task, not having reset FaultInfo) ManyFaults More than one fault NotEmuFault Fault in non-emulator task NotMapFault Memory system fault other than map fault UnknownFault Fault of unknown origin (In emulator task, having reset FaultInfo) AEmuStackError Stack error from Alto emulator AEmuMapFault Map fault from Alto emulator (In emulator task, the fault task never having been awakened) LispIFUMapFault Map fault caused by IFU reference LispIFUFGParity FG parity error LispIFURamPE IFU decoding Ram parity error BogusIFUMapFault IFU gave a map fault, but the page referenced by PCX is not vacant and shouldn't have faulted. In the case of faults passed to the emulator task, interesting information is left in R-registers, as follows: FltErrors NOT (Errors') FaultInfo NOT (Pipe2') FltEmuPC Emulator TPC at time of fault FaultVal DBuf -- value being stored if faulted on Store← % *----------------------------------------------------------- * Fault Task *----------------------------------------------------------- Set[XTask, IP[FLT]]; Subroutine; FLTInitPC: T← FLT, CoReturn; TopLevel; T← A0, RBase← RBase[FaultInfo]; TIOA← T, Block; FaultTask: FltErrors← NOT (Errors'); * Read this always FaultInfo← NOT (Pipe2'); * Doesn't clear FaultInfo * Test for memory system fault T← (FaultInfo) AND (fi.numfaults); PD← T XOR (fi.numFaults); * See if we have all bits set; T← Pointers, Branch[CheckStackErr, ALU=0]; * All ones => no fault * Memory system fault, see what kind PD← (FaultInfo) AND (fi.numFaults); * All zeroes => one fault PD← (FaultInfo) AND (fi.emuFault), Branch[ManyFaults, ALU#0]; PD← (FltErrors) AND (pipe4.notMapTrouble), Branch[NotEmuFault, ALU=0]; Branch[NotMapFault, ALU#0]; * Emulator map fault. Clear it and pass fault to emulator. B← FaultInfo', Branch[EmuFault]; * Not memory system fault, check for stack overflow or underflow CheckStackErr: PD← T AND (300c); * 200 = stack overflow, 100 = stack underflow Branch[UnknownFault, ALU=0]; * Emulator map fault or stack error. * Save emulator's state and restart emulator at Fault0. EmuFault: FaultVal← DBuf; RdTPC← EMU; FltEmuPC← NOT (Link); * TPC data is complemented Call[GetEmuFaultPC]; LdTPC← T; Block, Branch[FaultTask]; * Fault conditions that we can't handle: ManyFaults: Branch[.], Breakpoint; * More than 1 fault NotEmuFault: Branch[.], Breakpoint; * Not Emulator fault NotMapFault: Branch[.], Breakpoint; * Not map fault UnknownFault: Branch[.], Breakpoint; * Don't know what fault occurred *-------------------------------------------------------------------- * Emulator Task * The emulator is restarted here by the fault task after an emulator * map fault or stack error. *----------------------------------------------------------- Set[XTask, IP[EMU]]; Subroutine; GetEmuFaultPC: T← EMU, CoReturn; TopLevel; Fault0: RBase← RBase[FltPipe0], Call[RestoreALUFM]; * In case interrupted from BITBLT PD← (FaultInfo) AND (fi.numFaults); * Which kind of fault? FaultMapVal← NOT (Map'), Branch[StackError, ALU#0]; T← VAHi; T← FltPipe0← T AND (7777C); * only want low bits FltPipe1← Q← VALo; FaultMapVal← not (Pipe4'); * ref bits in pipe * Which emulator was running at the time? FltTemp← NOT (IFUMLH'); PD← (FltTemp) AND (14000C); * Test InsSet (Alto=0) branch[.+2, alu=0], rbase← rbase[spAC0]; branch[PAGEFAULTPUNT]; * Page fault from alto emulator: continue in next instruction * with faulting address in AC0, 1 StkP← spAC0; Stack&+1 ← T; Stack&-1 ← Q, branch[EmuNext]; *-------------------------------------------------------------------- * IFU traps from lisp emulator Set[LispTrapBase, Sub[300, LShift[LispInsSet, 6]]]; DontKnowRBase; TopLevel; *-------------------------------------------------------------------- IFuNotReady: IFUJump[0], at[LispTrapBase, 34]; *-------------------------------------------------------------------- LispReschedule: * cf AEmuReschedule in Start.mc rbase← rbase[NWW], at[LispTrapBase, 14]; PD← NWW; branch[.+2, ALU>0]; NoReschedule, branch[.intsoff]; NWW← (NWW) and not (BcplKeyMask); * always turn off BCPL bit pd← (NWW) and not (LispKeyMask); * if other bits on, do old NWW punt branch[.checkWW, alu#0], pd← NWW; * if LispInterrupt on, do KeyPunt dblbranch[KEYPUNT, .intsoff, alu#0], NoReschedule; .checkWW: MemBase← MDS; T← (R400)+(52C); T← (fetch← T) + 1; * WW (= 452B) T← MD, ETemp← (Fetch← T) - 1; * ACTIVE (= 453B) NWW← (NWW) OR T, T← MD; * WW OR NWW NWW← T← T AND (Q← NWW); * (WW OR NWW) AND ACTIVE branch[.+2, ALU=0]; branch[NWWPUNT]; * no pending channel is turned on. * Save turned-off interrupts in WW, flush them from NWW, and resume execution. Store← ETemp, DBuf← Q; NoReschedule, branch[RestartIFU]; .intsoff: * no interrupt enabled; check for other Reschedule conditions: rbase← rbase[LTEMP0]; :if[FNStats]; pd← (FnStatsPtr) - (StatsBufferBoundary); branch[STATSPUNT, alu>=0]; :endif; branch[.+2, R<0], LEFT; * is LEFT negative? branch[RestartIFU]; memBase← StackBR; ESP← (fetch← ESP) + 1; * fetch flagword LTEMP2← Md, fetch← ESP; pd← (LTEMP2) xor (FreeStackBlock); * is it a free block? branch[STKOVPUNT, alu#0], ESP← (ESP) - 1; T← ESP← (ESP) + (Md); LEFT← T - (TSP); * recompute Left LEFT← (LEFT) rsh 1; LEFT← (LEFT) - (LeftOffset), branch[RestartIFU]; *-------------------------------------------------------------------- LispIFUFGparity: At[LispTrapBase, 4], Branch[.], Breakpoint; *-------------------------------------------------------------------- LispIFURamPE: At[LispTrapBase, 74], Branch[.], Breakpoint; *-------------------------------------------------------------------- LispIFUMapFault: At[LispTrapBase, 0], MemBase← ifuBR; CHECKPCX; PAGEFAULTOK; T← NOT (PCX'); T← T RSH 1; * PCX/2 = word address in code segment T← (FETCH← T) + 1; T← MD, FETCH← T; T← MD; * Wait for fault to occur BogusIFUMapFault: Branch[.], Breakpoint; *----------------------------------------------------------- StackError: uCodeCheck[HWStackError];