:Title[LFaults]; * * Edit History * February 2, 1984 5:40 PM, JonL, set RBase before uCodeCheck at Fault0 * January 4, 1984 7:48 PM, JonL, CHECKPCXSUBR and FIXLEFT from LSTACK; * Let .intsoff in LispReschedule Call[FIXLEFT]; added more comments * 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: * "Called" only because there is no way to know T_ EMU, CoReturn; * the u-address of Fault0 at assembly time TOPLEVEL; Fault0: RBase_ RBase[FltPipe0], Call[RestoreALUFM]; * If interrupted from BITBLT ? PD_ (FaultInfo) AND (fi.numFaults); * Which kind of fault? Branch[.faultluz, alu#0], FaultMapVal_ NOT (Map'); T_ VAHi; T_ FltPipe0_ T AND (7777C); * Only want low bits FltPipe1_ Q_ VALo; FaultMapVal_ not (Pipe4'); * Ref bits in pipe FltTemp_ NOT (IFUMLH'); * Which emulator was running? 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]; .faultluz: RBase_ RBase[LTEMP0]; uCodeCheck[HWStackError]; *-------------------------------------------------------------------- * IFU traps from lisp emulator *-------------------------------------------------------------------- Set[LispTrapBase, Sub[300, LShift[LispInsSet, 6]]]; DontKnowRBase; TOPLEVEL; *-------------------------------------------------------------------- IFuNotReady: IFUJump[0], at[LispTrapBase, 34]; *-------------------------------------------------------------------- LispIFUFGparity: Branch[.], Breakpoint, at[LispTrapBase, 4]; *-------------------------------------------------------------------- LispIFURamPE: Branch[.], Breakpoint, at[LispTrapBase, 74]; *-------------------------------------------------------------------- *-------------------------------------------------------------------- LispIFUMapFault: *-------------------------------------------------------------------- MemBase_ ifuBR, at[LispTrapBase, 0]; CHECKPCX; PAGEFAULTOK; T_ not (PCX'); T_ T rsh 1; * PCX/2 = word address in code T_ (FETCH_ T) + 1; * segment addressed by ifuBR T_ MD, FETCH_ T; T_ MD; * Wait for fault to occur BogusIFUMapFault: Branch[.], Breakpoint; :if[Debugging]; *-------------------------------------------------------------------- SUBROUTINE; CHECKPCXSUBR: *-------------------------------------------------------------------- pd_ (PSTATE) and (PS.PCXBAD); branch[.+2, alu#0]; return; PSTATE_ Link; TOP LEVEL; UCodeCheck[PuntInCall]; :endif; (635)\f8 5430G *-------------------------------------------------------------------- LispReschedule: at[LispTrapBase, 14]; *-------------------------------------------------------------------- * cf AEmuReschedule in Start.mc rbase_ rbase[NWW]; PD_ NWW; branch[.+2, ALU>0]; NoReschedule, branch[.intsoff]; NWW_ (NWW) and not (BcplKeyMask); * Always turn off BCPL bit. If pd_ (NWW) and not (LispKeyMask); * other bits on, do old NWW punt branch[.checkWW, alu#0], pd_ NWW; * If LispInterrupt on, do KeyPunt NoReschedule, dblbranch[KEYPUNT, .intsoff, alu#0]; .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 rbase_ rbase[LTEMP0]; * other reschedule conditions. :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; ESP_ (ESP) + (Md), Call[FIXLEFT]; Branch[RestartIFU]; *-------------------------------------------------------------------- SUBROUTINE; FIXLEFT: *-------------------------------------------------------------------- T_ ESP; LEFT_ T - (TSP); FIXLEFT1: LEFT_ (LEFT) rsh 1; LEFT_ (LEFT) - (LEFTOffset), return; TOPLEVEL; \f8 3G70g47G70g1346G267g