*----------------------------------------------------------- Title[XMFaultTask.mc...September 3, 1980 1:01 PM...Taft]; *----------------------------------------------------------- % Simple Alto Emulator fault task. This version does a partial emulation of an Extended Memory Alto. Specifically, it supports changing the emulator task's alternate bank register (for XMLDA, XMSTA, and BITBLT) and the display task's normal bank register (to move the display into XM). It does NOT support emulating Alto instructions in XM. If a fault occurs as a result of storing into write-protected page 377, and the emulator's or Alto display task's bank register is the word addressed, allow the store to proceed and also update the high part of the appropriate base register. If any other word in page 377 was addressed, ignore the store. 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) StackError Stack error from Alto emulator MapFault Map fault from Alto emulator 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_ % * Alto XM bank register addresses MC[ADispWordTaskReg, 177751]; MC[Task0XMReg, 177740]; MC[XMBankRegArea, 177740]; *----------------------------------------------------------- * 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[EmuBRHiReg]; Q_ EmuBRHiReg; RBase_ RBase[FltPipe0]; PD_ (FaultInfo) AND (fi.numFaults); * Which kind of fault? FaultMapVal_ NOT (Map'), Branch[StackError, ALU#0]; T_ VAHi; FltPipe0_ T AND (7777C); * only want low bits FltPipe1_ VALo; T_ (FltPipe1) AND (177400C); * See if VA = page 377 in MDS T_ T XOR (177400C); T_ T XOR (FltPipe0); T_ T XOR Q; * Q = EmuBRHiReg T_ (FltPipe1) AND (XMBankRegArea), Branch[MapFault, ALU#0]; * check if storing into an XM bank register PD_ T XOR (XMBankRegArea); PD_ (FltPipe1) XOR (Task0XMReg), Branch[IgnoreStore, ALU#0]; PD_ (FltPipe1) XOR (ADispWordTaskReg), Branch[Task0XM, ALU=0]; DblBranch[DispXM, XMBStoreOnly, ALU=0]; * Set alternate bank for emulator task Task0XM: T_ (FaultVal) AND (3C); * [14:15] alternate bank bits EmuXMBRHiReg_ T, Branch[XMBStoreOnly]; * Set normal bank for display task DispXM: T_ LDF[FaultVal, 2, 2]; * [12:13] normal bank bits T_ T+Q, Call[SetDisplayBRHi]; * Q = EmuBRHiReg * Momentarily write-enable page 377 and store the value into the bank register XMBStoreOnly: MemBase_ MDS; Flush_ FltPipe1; * invalidate possible cache entry FltTemp_ MD, T_ TIOAusedMapEntry; T_ FltPipe1, TIOA_ T; Map_ T, MapBuf_ FaultMapVal; * turn off write protect T_ FltPipe1, Call[WaitForMapBuf]; Store_ T, DBuf_ FaultVal; * do the actual store FltTemp_ MD, T_ TIOAwProtect; * wait for store Flush_ FltPipe1; * clear entry from cache FltPipe1_ MD, T_ FltPipe1, TIOA_ T; * wait for flush Map_ T, MapBuf_ FaultMapVal; * restore wProtect Call[WaitForMapBuf]; *----------------------------------------------------------- * Restart the current instruction -- the instruction following the * one that caused the fault. All instructions must wait for faults before * changing any permanent state, and instructions that can cause faults * (presumably only STA) must do so as their last microinstruction, so * it is guaranteed that a new instruction will have begun by the time * the fault occurs. *----------------------------------------------------------- IgnoreStore: T_ A0, RBase_ RBase[AEmRegs]; TIOA_ T; Branch[AEmuReschedule]; * whew!!! *----------------------------------------------------------- * Faults that can't be handled. *----------------------------------------------------------- StackError: Branch[.], Breakpoint; MapFault: Branch[.], Breakpoint; (1552)