*-----------------------------------------------------------
Title[MesaDefs.mc...November 23, 1982  1:31 PM...Taft];
* Global definitions for Mesa emulator and I/O microcode (Trinity Pilot version)
*-----------------------------------------------------------

*-----------------------------------------------------------
* R Register definitions
*-----------------------------------------------------------

* Note that in many cases, only the RMRegion name is declared here.
* Registers within the region are defined within the module in which
* they are used:
*	SetRMRegion[regionName];
*	RVN[regName0];
*	...

* Macro to define synonyms for RM locations: RME[newName, oldName];
M[RME, RM[#1, IP[#2]]];

*-----------------------------------------------------------
* Region 0 -- IFU-addressable
RMRegion[MesaRegsMain];		* Main Mesa emulator registers
*-----------------------------------------------------------

* PrincOps registers
	RVN[PSB];		* Process State Block pointer
	RVN[XTS];		* Xfer Trap State

* Constants
	RVSH[StdShC, 10, 10, 2, 10]; * ShC at start of opcode:
				* LCY[T, R, 10], LMask=10, RMask=10
	RV[IndexMask, 7774];	* Mask for PsbIndex in Queue (see Process.mc)

* Internal registers
	RVN[XferFlags];		* Xfer control and state flags
	  RME[Zero, XferFlags];	* = 0 when not inside Xfer
	RVN[TrapParam];		* Xfer trap parameter
	RVN[LFShadow];		* Shadow of LF base register
	RVN[GFShadow];		* Shadow of GF base register
	RVN[MDSHi];		* Shadow of high half of MDS base register

	RVN[RTemp0];		* General temporaries
	RVN[RTemp1];
	RVN[RTemp2];
	RVN[RTemp3];
	RVN[RTemp4];
	RVN[RTemp5];		* RVRel 16 and 17 must be temps, for
	RVN[RTemp6];		*  multiply and divide subroutines


*-----------------------------------------------------------
* Region 1 -- IFU-addressable
RMRegion[MesaRegsAlt]; 		* Additional Mesa emulator registers
*-----------------------------------------------------------

* PrincOps registers
	RVN[Break];		* Break byte (in left half)
	RVN[PTC];		* Process Timeout Counter (~50 ms ticks)
	RVN[WP];		* Wakeups Pending
	RVN[WDC];		* Wakeup disable counter
	RVN[MaintPanel];	* Maintenance Panel code (called MP in PrincOps)

* Internal registers
	RVN[TickCount];		* Divides down 17-ms interrupts to make ticks
	RVN[Sticky];		* Sticky flags for floating point

*-----------------------------------------------------------
* Special uses of the Mesa RM registers:
*-----------------------------------------------------------

* Temporary register assignments, used only inside Xfer and when calling Xfer.
	RME[DLink, RTemp5];	* Xfer destination link
	RME[SLink, RTemp6];	* Xfer source link

* Temporary register assignments, for passing parameters thru fault handler.
* FaultParam0 and FaultParam1 must be preserved across Requeue.
	RME[FaultParam0, TrapParam]; * First or low-order fault parameter
	RME[FaultParam1, RTemp3]; * Second or high-order fault parameter

* XferFlags bit assignments.
* Note: xf.invalidContext must have the appropriate value (usually 0) any
* time a fault or trap may occur.  Other flags are relevant only inside Xfer.
* The low 3 bits are dispatched upon inside Xfer, so be circumspect about
* reassigning them.  Also, Xfer depends on xf.free being the low-order bit.
	MC[xf.invalidContext, 100000]; * Current context is invalid
	MC[xf.lstf, 20];	* This Xfer is a LSTF
	MC[xf.storeTrapParam, 10]; * If xf.trap, store TrapParam in destination frame
	MC[xf.trap, 4];		* This Xfer is a trap
	MC[xf.push, 2];		* Push SLink and DLink onto stack
	MC[xf.free, 1];		* Free local frame

* 16 and 17 must be temporaries (for MulSub and DivSub)
	RM[DivTemp, Or[!MesaRegsMain, 16]];
	RM[MulDivArg, Or[!MesaRegsMain, 17]];

* Important invariants:
* LFShadow is the same as LF at the beginning of each instruction and whenever a trap
* may occur.  They diverge only inside Xfer.  If a page fault occurs while they are
* different, the fault handler treats LF as the truth and reloads LFShadow from it.
* GFShadow is the same as GF at the beginning of each instruction.  Traps and faults
* reset both registers to the correct value as determined by the local context.


*-----------------------------------------------------------
* Aliases for LoadRam.
*-----------------------------------------------------------

* Note that these must never change, even if the above
* registers are shuffled around, since the LoadRam microcode is blown into EPROMs.
* Furthermore, it is to the caller's benefit to arrange to overlay LoadRam's
* registers with its own temporaries.

SetRMRegion[MesaRegsAlt];
	Reserve[12];
	RVN[LRFlag];		* RM 32: flag word passed to LoadRam
	RVN[LRTemp0];		* RM 33: temporary
	RVN[LRTemp1];		* RM 34:
	RVN[LRItem];		* RM 35: ending address returned by LoadRam
	RVN[LRTemp2];		* RM 36:

*-----------------------------------------------------------
* Region 2
RMRegion[BBRegs];		* BitBlt registers
* Individual RM locations defined in BitBlt.mc.
* This region may be re-used by any other emulator-level microcode requiring
* an entire region of temporary storage and no permanent storage.
*-----------------------------------------------------------


*-----------------------------------------------------------
* Region 3
RMRegion[EIRegs];
*-----------------------------------------------------------
	Reserve[4];		* Ethernet input task registers

	RVN[FaultPointers];	* Information left by fault task: ← Pointers
	RVN[FaultErrors];	* ← NOT (Errors')
	RVN[FaultVal];		* ← DBuf
	RVN[FaultInfo];		* ← NOT (FaultInfo')
	RVN[FaultEmuPC];	* Emulator task PC at time of fault
	RVN[FaultTemp];		* One always needs a temp


*-----------------------------------------------------------
* Region 4
RMRegion[EORegs];
*-----------------------------------------------------------
	Reserve[7];		* Ethernet output task registers

	RVN[AUTPC];		* Request PC for Asynchronous Utility Task

	RVN[VirtualBanks];	* Size of virtual memory in units of 64K words
	RVN[RealPages];		* Size of real memory in pages

* Remaining registers are used as temps by InitMem.mc (only during initialization).


*-----------------------------------------------------------
* Region 5
RMRegion[DiskRegs];		* disk registers
* Individual RM locations defined in DiskDefs.mc
*-----------------------------------------------------------

*-----------------------------------------------------------
* The following 2 regions are for 7-wire terminal.
* Region 6
RMRegion[TWTRegion];		* Terminal word task registers
* Individual RM locations defined in DisplayDefs.mc
*-----------------------------------------------------------

*-----------------------------------------------------------
* Region 7
RMRegion[THTRegion];		* Terminal horizontal task registers
* Individual RM locations defined in DisplayDefs.mc
*-----------------------------------------------------------


*-----------------------------------------------------------
* The following 3 regions are for special displays, NOT for 7-wire terminal.
* Region 10
RMRegion[AChannelRegion];	* Display A-channel registers
* Individual RM locations defined in DisplayDefs.mc
*-----------------------------------------------------------
* AChannelRegion must be assigned an RBase value with zero in bit 2.
* BChannelRegion must equal AChannelRegion, but with one in bit 2.

*-----------------------------------------------------------
* Region 11
RMRegion[DHTRegion];		* Display horizontal task (DHT) registers
* Individual RM locations defined in DisplayDefs.mc
*-----------------------------------------------------------

*-----------------------------------------------------------
* Region 12
RMRegion[BChannelRegion];	* Display B-channel registers
* Individual RM locations defined in DisplayDefs.mc
*-----------------------------------------------------------


*-----------------------------------------------------------
* Region 13
RMRegion[Events];		* Junk task -- clock and event counters
*-----------------------------------------------------------

	RVN[ITLo];		* Interval Timer, low part (PrincOps)
	RVN[ITHi];		* Interval Timer, high part (PrincOps)
	RVN[ITDeltaLo];		* Constant delta for IT increment

	RVN[EventAHi0];		* Event counter shadow registers
	RVN[EventAHi1];
	RVN[EventALo];
	RVN[EventAPrev];
	RVN[EventBHi0];
	RVN[EventBHi1];
	RVN[EventBLo];
	RVN[EventBPrev];
	RVN[EventUpdateTimer];

	RVN[EventTemp0];	* Used only by emulator task
	RVN[EventTemp1];	* Used only by emulator task
	RVN[JunkTemp];		* Used only by junk task


*-----------------------------------------------------------
* Unused regions -- declare so that non-standard microcode can refer to them.
RMRegion[Region14];
RMRegion[Region15];
RMRegion[Region16];
RMRegion[Region17];
*-----------------------------------------------------------

*-----------------------------------------------------------
* Base registers
*-----------------------------------------------------------

* BRs 0-3 are addressable as MemBX-relative registers.
* Of these, 0 and 1 are used as MemBX-relative registers by Mesa,
* thereby consuming registers 4, 5, 10, 11, 14, 15 also.
* The other registers in [0..17] are used as ordinary registers
* and should not be addressed from the IFU.
	BRX[LF, 0];		* Local Frame (must be GF xor 1)
	BRX[GF, 1];		* Global Frame (must be LF xor 1)

	BR[PDA, 2];		* Process Data Area

* BRs 3, 6, 7, 12, 13, 16, 17 unused

* Display Word Task base registers.
* First 2 must be a pair differing only in MemBase.2
	BR[AChannelBR, 20];	* For A and B channels
	BR[BChannelBR, 24];
	BR[TChannelBR, 21];	* For 7-wire terminal

* The following 2 must be an even-odd pair.
	BR[BBDstBR, 22];	* BitBlt destination base register
	BR[BBSrcBR, 23];	* BitBlt source base register

	BR[PCHistBR, 25];	* Base of histogram for PC sampling

	BR[IOBR, 26];		* I/O region is first 64K

	BR[DiskBR, 27];		* Disk task base register

	BR[EIBR, 30];		* Ethernet Input base register
	BR[EOBR, 31];		* Ethernet Output base register

* BRs 32-33 unused

* BRs 34-37 are addressable from the IFU
	BR[BR34, 34];		* Temporary base registers, for emulator-level code
	BR[BR35, 35];		* requiring an IFU-addressable even-odd pair

	BR[LPtr, IP[BR34]];	* Temp for Long Pointer instructions

	BR[MDS, 36];		* Main Data Space (must be CB xor 1)
	BR[CB, 37];		* Code Base (must be 37 for IFU)

*-----------------------------------------------------------
* Task numbers
*-----------------------------------------------------------

	TaskN[AUT, 1];		* Asynchronous utility task
	TaskN[JNK, 2];		* Junk task
	TaskN[DHT, 3];		* Display horizontal task
	TaskN[AHT, 4];		* Terminal horizontal task
	TaskN[EOT, 6];		* Ether Output task
	TaskN[EIT, 7];		* Ether Input task
	TaskN[AWT, 11];		* Terminal word task
	TaskN[TSKSIM, 12];	* Task simulator task
	TaskN[DWT, 13];		* Display word task
	TaskN[DSK, 14];		* Disk task

*-----------------------------------------------------------
* IM placement constants
*-----------------------------------------------------------

* These addresses are public (e.g., known by BaseBoard or Bootstrap)
	Set[InitMapLoc, 1076];	* Emulator boot (2 or 3-button boot)
	Set[LoadRamPage, 76];	* Page reserved for LoadRam microcode
	Set[BootOrStartLoc, 1070]; * .eb file starting address

* These addresses are private
	Set[ESCTableLoc, 4000];	* 400-instruction block for ESC dispatch
				* (ESCTableLoc-1 is also used)


*-----------------------------------------------------------
* Miscellaneous macro definitions
*-----------------------------------------------------------

M[Nop, Branch[.+1]];

* These macros take an existing full-word integer (defined by SET),
* constant (defined by MC), or list of up to 9 integers and/or
* constants to be summed, extract the high or low byte, and return
* the result as a constant that may be used in an instruction without
* further qualification.
M[HighByte, And[177400, DPS[#1,#2,#3,#4,#5,#6,#7,#8,#9]]C];
M[LowByte, And[377, DPS[#1,#2,#3,#4,#5,#6,#7,#8,#9]]C];

* TrapWithParam[constant] takes a defined low-byte constant (generally an SD index)
* and produces a constant with TrapParamFlag set.
MC[TrapParamFlag, 177400];
M[TrapWithParam, Add[TrapParamFlag!, #1!]C];

*-----------------------------------------------------------
* PrincOps constants
*-----------------------------------------------------------

* Memory address constants
	MC[AV, 400];		* Allocation Vector
	MC[SD, 1000];		* System Dispatch table
	MC[ETT, 1400];		* ESC Trap Table
	MC[GFT, 2000];		* Global Frame Table
	MC[PDAHi, 1];		* PDA starts at VM 200000
	MC[initialMDSHi, 0];	* MDS is set to 0 at boot time

* SD indices known to microcode
	MC[sBreakTrap, 0];
	MC[sStackError, 1];
	MC[sBoot, 2];
	MC[sRescheduleError, 3];
	MC[sXferTrap, 4];
	MC[sOpcodeTrap, 5];
	MC[sControlTrap, 6];
	MC[sCodeTrap, 7];
	MC[sUnboundTrap, 11];
	MC[sDivZeroTrap, 12];
	MC[sDivCheckTrap, 13];
	MC[sInterruptError, 14];
	MC[sProcessTrap, 15];
	MC[sBoundsTrap, 16];
	MC[sPointerTrap, 17];
	MC[sFirstGermRequest, 320];

* Fault queue offsets (2 * corresponding PrincOps FaultQueueIndex)
	MC[qFrameFault, 0];
	MC[qPageFault, 2];
	MC[qWriteProtectFault, 4];

* Stack size (size of StateVector.stk array)
	Set[StackDepth, 16];

* Frame formats.  Note that these are negative offsets relative to
* the frame pointer, which points at local zero or global zero.

* GlobalOverhead: TYPE = MACHINE DEPENDENT RECORD [
MC[GF.word, -3];		* word (0): GlobalWord,
MC[GF.codebase, -2];		* codebase (1): LONG POINTER TO CodeSegment];

* GlobalWord: TYPE = MACHINE DEPENDENT RECORD [
MC[GW.gfi, 177700];		* gfi (0: 0..9): GFTIndex,
				* available (0: 10..13): [0..17B],
MC[GW.disablexfertraps, 2];	* disablexfertraps (0: 14..14): BOOLEAN,
MC[GW.codelinks, 1];		* codelinks (0: 15..15): BOOLEAN];

* LocalOverhead: TYPE = MACHINE DEPENDENT RECORD [
MC[LF.word, -4];		* word (0): LocalWord,
MC[LF.returnlink, -3];		* returnlink (1): ControlLink,
MC[LF.globallink, -2];		* globallink (2): GlobalFrameHandle,
MC[LF.pc, -1];			* pc (3): CARDINAL];

* LocalWord: TYPE = MACHINE DEPENDENT RECORD [
				* available (0: 0..7): BYTE,
MC[LW.fsi, 377];		* fsi (0: 8..15): FSIndex];

*-----------------------------------------------------------
* Mesa main opcode definitions
*-----------------------------------------------------------

* Main opcode table
* In addition to defining the opcode names, it also assembles all IFU dispatches
* for undefined opcodes.

Set[MesaInsSet, 0]; Set[nEntryPoints, 1];
InsSet[MesaInsSet, nEntryPoints];
Set[MesaTrapBase, Sub[300, LShift[MesaInsSet, 6]]];

Set[MOpcodeVal, 0];
M[MOp, (IfSE[#1, , UndefOp[MOpcodeVal], Set[MOp#1, MOpcodeVal]]
	Set[MOpcodeVal, Add[MOpcodeVal, 1]])];
M[MesaOps, (MOp[#1] MOp[#2] MOp[#3] MOp[#4] MOp[#5] MOp[#6] MOp[#7] MOp[#8])];
M[UndefOp, IFUPause[#1, 1, LF, 0, OpcodeTrap, 17, 0, 0]];

*       xx0    xx1    xx2    xx3    xx4    xx5    xx6    xx7

MesaOps[ ,     LL0,   LL1,   LL2,   LL3,   LL4,   LL5,   LL6];		* 00x
MesaOps[LL7,   LL8,   LL9,   LL10,  LL11,  LLB,   LLD0,  LLD1];		* 01x
MesaOps[LLD2,  LLD3,  LLD4,  LLD5,  LLD6,  LLD7,  LLD8,  LLD10];	* 02x
MesaOps[LLDB,  SL0,   SL1,   SL2,   SL3,   SL4,   SL5,   SL6];		* 03x
MesaOps[SL7,   SL8,   SL9,   SL10,  SLB,   SLD0,  SLD1,  SLD2];		* 04x
MesaOps[SLD3,  SLD4,  SLD5,  SLD6,  SLD8,  PL0,   PL1,   PL2];		* 05x
MesaOps[PL3,   PLB,   PLD0,  PLDB,  LG0,   LG1,   LG2,   LGB];		* 06x
MesaOps[LGD0,  LGD2,  LGDB,  SGB,   BNDCK, BRK,    ,      ];		* 07x

MesaOps[R0,    R1,    RB,    RL0,   RLB,   RD0,   RDB,   RDL0];		* 10x
MesaOps[RDLB,  W0,    WB,    PSB,   WLB,   PSLB,  WDB,   PSD0];		* 11x
MesaOps[PSDB,  WDLB,  PSDLB, RLI00, RLI01, RLI02, RLI03, RLIP];		* 12x
MesaOps[RLILP, RLDI00,RLDIP, RLDILP,RGIP,  RGILP, WLIP,  WLILP];	* 13x
MesaOps[WLDILP,RS,    RLS,   WS,    WLS,   R0F,   RF,    RL0F];		* 14x
MesaOps[RLF,   RLFS,  RLIPF, RLILPF,W0F,   WF,    PSF,   PS0F];		* 15x
MesaOps[WS0F,  WL0F,  WLF,   PSLF,  WLFS,  SLDB,  SGDB,  LLKB];		* 16x
MesaOps[RKIB,  RKDIB, LKB,   SHIFT, SHIFTSB, ,     ,      ];		* 17x

MesaOps[CATCH, J2,    J3,    J4,    J6,    J8,    JB,    JW];		* 20x
MesaOps[JEP,   JEB,   JEBB,  JNEP,  JNEB,  JNEBB, JLB,   JGEB];		* 21x
MesaOps[JGB,   JLEB,  JULB,  JUGEB, JUGB,  JULEB, JZ3,   JZ4];		* 22x
MesaOps[JZB,   JNZ3,  JNZ4,  JNZB,  JIB,   JIW,   REC,   REC2];		* 23x
MesaOps[DIS,   DIS2,  EXCH,  DEXCH, DUP,   DDUP,  EXDIS, NEG];		* 24x
MesaOps[INC,   DEC,   DINC,  DBL,   DDBL,  TRPL,  AND,   IOR];		* 25x
MesaOps[ADDSB, ADD,   SUB,   DADD,  DSUB,  ADC,   ACD,   AL0IB];	* 26x
MesaOps[MUL,   DCMP,  UDCMP, ESC,   ESCL,  LP,     ,      ];		* 27x

MesaOps[LI0,   LI1,   LI2,   LI3,   LI4,   LI5,   LI6,   LI7];		* 30x
MesaOps[LI8,   LI9,   LI10,  LIN1,  LINI,  LIB,   LIW,   LINB];		* 31x
MesaOps[LIHB,  LID0,  LA0,   LA1,   LA2,   LA3,   LA6,   LA8];		* 32x
MesaOps[LAB,   LAW,   GA0,   GAB,   GAW,   EFC0,  EFC1,  EFC2];		* 33x
MesaOps[EFC3,  EFC4,  EFC5,  EFC6,  EFC7,  EFC8,  EFC9,  EFC10];	* 34x
MesaOps[EFC11, EFC12, EFCB,  LFC1,  LFC2,  LFC3,  LFC4,  LFC5];		* 35x
MesaOps[LFCB,  SFC,   RET,   KFCB,  D0,    DB,    BLT,   BLTL];		* 36x
MesaOps[BLTC,  BLTCL,  ,      ,      ,      ,      ,      ];		* 37x

*-----------------------------------------------------------
* Main opcode IFU entry point macros
*-----------------------------------------------------------
* Call(s) should appear IMMEDIATELY BEFORE the entry vector.
* Each call defines a label "@opcode" at the current IM location, and
* forces the next nEntryPoints instructions to comprise an IFU entry vector.

* Note: due to MicroD symbol table overflow problems, a label "@opcode"
* is defined only for the first opcode in a group of consecutive declarations.

* IFUR[opcode, length, options];	Regular opcode
* IFUP[opcode, length, options];	Pause opcode
* IFUJ[opcode, length, options];	Jump opcode

* opcode = one of the opcode names defined above
* length = 1, 2, or 3
* memBase = defined IFU MemBase name (BRX[0..3] or BR[34..37])

* Options (zero or more, in any order):
* N[n]		n = 0 to 16; default is none (i.e., 17)
* SignExtend	default is false
* PackedAlpha	default is false
* MemBase[br]	IFU-addressable base register (BRX[0..3] or BR[34..37]); default is LF
* RBase[rBase]	rBase = MesaRegsMain or MesaRegsAlt; default is MesaRegsMain
* Disp[n]	n = -40 to 37 (displacement for 1-byte jumps)

M[IFUR, IOpLabel[#1] (IOp#3, IOp#4, IOp#5, IOp#6, IOp#7, IFUDeflt)
  IFUReg[MOp#1, #2, IValMemBase, RShift[CRB@, 4], ILC, IValN, IValSign, IValPA]];
M[IFUP, IOpLabel[#1] (IOp#3, IOp#4, IOp#5, IOp#6, IOp#7, IFUDeflt)
  IFUPause[MOp#1, #2, IValMemBase, RShift[CRB@, 4], ILC, IValN, IValSign, IValPA]];
M[IFUJ, IOpLabel[#1] (IOp#3, IOp#4, IOp#5, IOp#6, IOp#7, IFUDeflt)
  IFUJmp[MOp#1, #2, IValMemBase, RShift[CRB@, 4], ILC, IValSign]];

M[IOp, ];
M[IOpN, Set[IValN, #1]];
M[IOpSignExtend, Set[IValSign, 1]];
M[IOpPackedAlpha, Set[IValPA, 1]];
M[IOpMemBase, Equate[IValMemBase, #1]];
M[IOpDisp, Set[IValSign, #1]];
Equate[IOpRBase, KnowRBase];

M[IFUDeflt, TopLevel[] KnowRBase[MesaRegsMain]
  Set[IValN, 17] Set[IValSign, 0] Set[IValPA, 0] Equate[IValMemBase, LF]];

Set[LastILC, 177777];
M[IOpLabel, IfE[IP[ILC], LastILC, , @#1: Set[LastILC, IP[ILC]]]];

* OpcodeUnimpl[opcode] is used to declare a main opcode to be unimplemented,
* where opcode is either a defined main opcode name or an octal number.
M[OpcodeUnimpl, IfDef[MOp#1, UndefOp[MOp#1], UndefOp[#1]]];


*-----------------------------------------------------------
* Opcode exit macro
* Instruction forwarding not implemented at present
*-----------------------------------------------------------

M[NextOpcode, IFUJump[0]];	* Normal dispatch to next opcode
M[NextOpcodeCF, Branch[ExitCheckFault]]; * Check for fault before dispatching

*-----------------------------------------------------------
* Mesa ESC opcode table
*-----------------------------------------------------------

Set[MOpcodeVal, 0];
Set[ESCMax, 200];	* Highest opcode defined
M[ESCAddr, At[ESCTableLoc, And[Sub[#1, Add[ESCMax, 1]], 377]]];
M[EOp,
  IfG[MOpcodeVal, ESCMax,
    IfSE[#1, , , ER[Defined.ESC.opcode.above.ESCMax, x]],
    IfSE[#1, , ILC[(ESCAddr[MOpcodeVal], Branch[ESCUnimplTrap])],
      Set[EOp#1, MOpcodeVal]]]
  Set[MOpcodeVal, Add[MOpcodeVal, 1]]];
M[ESCOps, (EOp[#1] EOp[#2] EOp[#3] EOp[#4] EOp[#5] EOp[#6] EOp[#7] EOp[#8])];

*       xx0    xx1    xx2    xx3    xx4    xx5    xx6    xx7

ESCOps[ME,    MX,    MW,    MR,    NC,    BC,    REQ,   SM];		* 00x
ESCOps[SMF,   GMF,   AF,    FF,    PI,    PO,    POR,   SPP];		* 01x
ESCOps[DI,    EI,    XOR,   DAND,  DIOR,  DXOR,  ROTATE,DSHIFT];	* 02x
ESCOps[LINT,  JS,    RCFS,  RC,    LLOB,  ROB,   SLOB,  WOB];		* 03x
ESCOps[DSTK,  LSTE,  LSTF,  DBS,   UDIV,  LUDIV, NILCKL,BLTLR];		* 04x
ESCOps[BLEL,  BLECL, CKSUM, BITBLT,TXTBLT,BYTBLT,BYTBLTR,VERSION];	* 05x
ESCOps[DMUL,  SDIV,  SDDIV, UDDIV,  ,      ,      ,      ];		* 06x
ESCOps[ ,      ,      ,      ,      ,      ,      ,      ];		* 07x

ESCOps[FADD,  FSUB,  FMUL,  FDIV,  FCOMP, FIX,   FLOAT, FIXI];		* 10x
ESCOps[FIXC,  FSTICKY,FREM, ROUND, ROUNDI,ROUNDC,FSQRT, FSC];		* 11x
ESCOps[ ,      ,      ,      ,      ,      ,      ,      ];		* 12x
ESCOps[ ,      ,      ,      ,      ,      ,      ,      ];		* 13x
ESCOps[RECREF,ALTCNT,RESSTK,GCSET,  ,     ENUREC, ,     CREREF];	* 14x
ESCOps[ ,     REFTYP,CREFTYP,ALLOCQ,ALLOCH,FREEO,FREEQ, FREEP];		* 15x
ESCOps[WRPSB, WRMDS, WRWP,  WRWDC, WRPTC, WRIT,  WRXTS, WRMP];		* 16x
ESCOps[RRPSB, RRMDS, RRWP,  RRWDC, RRPTC, RRIT,  RRXTS,  ];		* 17x

ESCOps[RESETH, ,      ,      ,      ,      ,      ,      ];		* 20x

* If the table is extended or shortened, ESCMax (above) must be adjusted.
* 200-237 reserved for processor-dependent opcodes
* 240-377 unassigned

IM[ILC, 0];

*-----------------------------------------------------------
* ESC opcode entry definition
*-----------------------------------------------------------
* "NewOp; ESCEntry[opcodeName];" should appear immediately before the first
* instruction of the microcode implementing the specified opcode.  If the opcode
* finishes in one microinstruction, or the first instruction of the opcode does not
* use FF, then "ESCEntry[opcodeName]" may be followed by a comma instead of
* a semicolon (this saves one instruction).
* Each call defines a label "@opcode" at the current IM location.

M[NewOp, TopLevel[] KnowRBase[MesaRegsMain]];
M[ESCEntry, @#1: ESCAddr[EOp#1]];

* ESCOpcodeUnimpl[opcode] is used to declare an ESC opcode to be unimplemented,
* where opcode is either a defined ESC opcode name or an octal number.
M[ESCOpcodeUnimpl,
  (IfDef[EOp#1, ESCAddr[EOp#1], ESCAddr[#1]], Branch[ESCUnimplTrap])];