*----------------------------------------------------------- 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])];