*-----------------------------------------------------------
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):
*
42Start.mc -- interrupts, traps, and subroutines
*
93M-Group.mc -- M and J-group instructions
*
105A-Group.mc
*
187S-Group.mc
*
32ATraps.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;