*----------------------------------------------------------- Title[Start.mc...February 4, 1982 10:21 AM...Taft]; *----------------------------------------------------------- * EmIFUReg[opcode, IMaddress, Sign, N] M[EmIFUReg, IFUReg[#1, 2, MDS, rbAemRegs, #2, #4, #3, 0]]; * EmIFUArith[opcode, IMaddress, N] M[EmIFUArith, IFUReg[#1, 2, MDS, rbAemRegs, #2, #3, 0, 1]]; * EmIFUPause[opcode, IMaddress, MemBase, Sign] M[EmIFUPause, IFUPause[#1, 2, #3, rbAemRegs, #2, 17, #4, 0]]; * ALUFM[17] must be "2A" * Page-zero and ALU-class instructions instructions have sign = 0. * All other memory-reference instructions have sign = 1 (sign-extend). * Base registers must be in the range 34-37 so the IFU can set them. * I am assuming that Mesa will use the ones addressed by MemBX. * Accumulators AC0-AC3 are kept in Stack[1] through Stack[4]. * The XMFaultTask may restart an opcode at the beginning if the previous * opcode was a store into write-protected page 377. Therefore, all * opcodes must wait for previous memory activity to complete (by doing * a Fetch_, Store_, or _MD) before changing any permanent state. * Micoinstruction counts (as of last time I checked): * 42 Start.mc -- interrupts, traps, and subroutines * 93 M-Group.mc -- M and J-group instructions * 105 A-Group.mc * 187 S-Group.mc * 32 ATraps.mc * Timings include unavoidable memory wait and IFU not-ready wait after PCF_, * but do not include other forms of waiting (cache misses, IFU/processor * interference, etc.) * Instruction set number for Alto emulator * Set[AEmuInsSet, ?]; * Defined in ADefs.mc. Must be 0 or 1 Set[AEmuTrapBase, Sub[300, LShift[AEmuInsSet, 6]]]; InsSet[AEmuInsSet, 1]; DontKnowRBase; TopLevel; *----------------------------------------------------------- Start: Global, * Cold-start the Alto emulator at PC given in T. * RBase and MemBase undefined. *----------------------------------------------------------- RBase_ RBase[AEmRegs]; ETemp_ Add[100000, LShift[AEmuInsSet, 10]]C; InsSetOrEvent_ ETemp; RCODE_ T, MemBase_ CODE; * Load IFU's base register BrHi_ EmuBrHiReg; T_ A0, BrLo_ RCODE; StartIFU: PCF_ T, Call[RestoreALUFM]; * Restore ALUFM variables IFUJump[0]; *----------------------------------------------------------- * Trap handlers for Alto emulator *----------------------------------------------------------- AEmuNotReady: IFUJump[0], At[AEmuTrapBase, 34]; * Not-ready trap AEmuIFURamPE: Branch[.], Breakpoint, At[AEmuTrapBase, 74]; * IFUM parity error AEmuIFUFGParity: Branch[.], Breakpoint, At[AEmuTrapBase, 4]; * Data parity error AEmuIFUMapFault: Branch[.], Breakpoint, At[AEmuTrapBase, 0]; * Map fault *----------------------------------------------------------- * Reschedule trap. * Can also branch here directly when an explicit Reschedule test * indicates that an interrupt is pending. * (Any instruction that branches here should leave FF free.) *----------------------------------------------------------- AEmuReschedule: RBase_ RBase[NWW], At[AEmuTrapBase, 14]; PD_ NWW, NoReschedule; Branch[.+3, ALU>0]; RestartIFU: T_ NOT (PCX'); * False alarm, resume execution Branch[StartIFU]; * Leave FF free for placement * Have at least one pending interrupt. * Update WW and see whether any pending channels are turned on. 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 ETemp2_ 1C, Branch[.+2, ALU#0]; * No pending channel is turned on. * Save turned-off interrupts in WW, flush them from NWW, and resume execution. Store_ ETemp, DBuf_ Q, Branch[RestartIFU]; * WW (=452B) * T has the channels that are both pending and turned on. NWW_ (NWW) OR Q; * Restore all pending interrupts ETemp2_ T, Q_ ETemp2, Call[GetPC]; ETemp_ (ETemp)+(26C); * Store PC at PCLOC (=500B) T_ Store_ ETemp, DBuf_ T; ETemp_ (ETemp)-(26C); * Find the highest-priority interrupt waiting in ETemp2. * T will end up with INTVEC (=501B) + channel number. PD_ (ETemp2) AND Q, Q LSH 1; T_ T+1, Branch[.-1, ALU=0]; * Disable interrupt system and initiate the interrupt. Q RSH 1; * Undo last LSH 1 NWW_ (NWW) AND NOT Q; * Turn off interrupt being initiated Fetch_ T, T_ 100000C; * Fetch new PC from INTVEC NWW_ T, Q_ NWW; * Save and disable interrupts Store_ ETemp, DBuf_ Q, T_ MD, Branch[Start]; *----------------------------------------------------------- * Skip and no-skip exits for opcodes *----------------------------------------------------------- NoSkip: IFUJump[0]; DoSkip: T_ (RR3)-(PCX'); * T_ PCX+4 PCF_ T; Branch[NoSkip]; * This Nop is required *----------------------------------------------------------- AEmuNext: * Restart IFU at next opcode (i.e., PCX+2) *----------------------------------------------------------- RBase_ RBase[AEmRegs], Call[GetPC]; T_ T+1, Branch[Start]; *----------------------------------------------------------- StartMB: * Restart IFU at pc from loc 0 (midas loaded boot file) *----------------------------------------------------------- MemBase_ MDS; Fetch_ 0S; T_ MD, Branch[Start]; *----------------------------------------------------------- EffAdrPCRel: * Given PC-relative offset in ID, returns effective address in T. * Computes T_ RCODE + PCX/2 + ID (ID must be sign-extended by IFU). *----------------------------------------------------------- Subroutine; T_ 2(ID), Q_ PCX'; T_ (T-Q-1) ARSH 1; T_ (RCODE)+T, Return; * Enter here having already done first instruction EffAdrPCRel1: T_ (T-Q-1) ARSH 1, Branch[.-1]; *----------------------------------------------------------- GetPC: * Returns the current PC in T *----------------------------------------------------------- Subroutine; T_ PCX'; T_ (NOT T) RSH 1; T_ (RCODE)+T, Return; *----------------------------------------------------------- RestoreALUFM: * Restores the ALUFM variables to their standard values. * Clobbers T *----------------------------------------------------------- Subroutine; T_ AFM15; ALUFMRW_ T, ALUF[15]; T_ AFM17; ALUFMRW_ T, ALUF[17], Return; TopLevel;(1552)