: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];