*-----------------------------------------------------------
Title[BlockMiscDispAndOps.mc...October 23, 1987 6:11:39 pm PDT...Willie-Sue];
* Dispatch tables for all MISC opcodes, and definitions of undefined MISC opcodes.
*-----------------------------------------------------------

%
There are 400B MISC opcodes, divided into 20B groups of 20B each.

The entry point for each MISC opcode is declared by including the clause
 MiscTable[xxx]
in the first microinstruction of the code implementing opcode xxx.

Upon entry, T contains TOS (if there is one) and StkP has been advanced
in preparation for pushing a result. Routines that do not push a result
must decrement StkP. Exit is via the usual IFUNextN.

All unimplemented MISC opcodes cause a trap to occur. In Alto mode,
a KFCB[sUnimplemented] is executed. (Exception: floating point opcodes trap
by putting the offending opcode in OTPReg and executing a KFCB[137B].)

In PrincOps mode, a Cedar opcode trap is executed if an OpTrapTable has been
set up; otherwise a standard PrincOps TrapZero[sUnimplemented] is executed.
(See DMesaFaults.mc for more details.) The microcode implementing a MISC
opcode may conditionally trap (e.g., for illegal arguments) by branching
to OpcodeTrap.

Adding or removing MISC opcodes requires changing the dispatch tables.
This is why these tables are in a separate file, which may be renamed and
edited when non-standard MISC opcodes are introduced.

To add a new MISC opcode to an existing group, delete the statement
 MiscOpcodeUnimplemented[xxx];
below, and add the corresponding
 MiscTable[xxx]
in the appropriate source file.

To add a new group of MISC opcodes, change
 MiscGroupUnimplemented[xxx];
to: MiscGroupImplemented[xxx];
below, where xxx is the first opcode of the group (i.e., a multiple of 20B).
Then, for each opcode in the group NOT being defined, add the statement
 MiscOpcodeUnimplemented[xxx];

Note: the MiscOpcodeUnimplemented[xxx] statments may appear either below or in
another source file. They appear below when the unimplemented opcodes in
a group are unrelated, but in a separate source file when they are related to
other opcodes that are implemented in that source file.
%
TopLevel;
Set[XTask, IP[EMU]];
*-----------------------------------------------------------
* First-level (group) dispatch table:
*-----------------------------------------------------------
M[MiscGroupImplemented,
(T← StackNoUfl&+1, BranchExternal[Or[
Select[RShift[#1, 6], MT0Loc, MT1Loc, MT2Loc, MT3Loc],
1]])];
M[MiscGroupUnimplemented, (Branch[Misc377])];

MiscDispatch: DispTable[20],
 MiscGroupImplemented[000];  * Miscellaneous operations
 MiscGroupImplemented[020];  * Floating point
 MiscGroupUnimplemented[040];
 MiscGroupImplemented[060];  * Cedar allocator/GC
 MiscGroupImplemented[100];  * More miscellaneous operations
 MiscGroupUnimplemented[120];
 MiscGroupImplemented[140];  * Cedar 5.0 reference-counting opcodes
 MiscGroupUnimplemented[160];
 MiscGroupUnimplemented[200];
 MiscGroupUnimplemented[220];
 MiscGroupImplemented[240];  * Dorado-only operations
 MiscGroupUnimplemented[260];
 MiscGroupUnimplemented[300];
 MiscGroupUnimplemented[320];
 MiscGroupUnimplemented[340];
 MiscGroupUnimplemented[360];
*-----------------------------------------------------------
* Unimplemented MISC opcodes:
*-----------------------------------------------------------

 MiscOpcodeUnimplemented[002]; * Read RAM
 MiscOpcodeUnimplemented[004]; * IO reset
 MiscOpcodeUnimplemented[014]; * XferL
 MiscOpcodeUnimplemented[015]; * TextBlt
 MiscOpcodeUnimplemented[017]; * Set default partition

 * MiscOpcodeUnimplemented[244]; * TblLookup
 * MiscOpcodeUnimplemented[245]; * OpBlt
 MiscOpcodeUnimplemented[250]; * used by PilotMesa10MBMiscDisp

 MiscOpcodeUnimplemented[101];
 MiscOpcodeUnimplemented[103];
 MiscOpcodeUnimplemented[105];
 MiscOpcodeUnimplemented[106];
 MiscOpcodeUnimplemented[107];
 MiscOpcodeUnimplemented[110];
 MiscOpcodeUnimplemented[111];
 MiscOpcodeUnimplemented[112];
 MiscOpcodeUnimplemented[113];
 MiscOpcodeUnimplemented[114];
 MiscOpcodeUnimplemented[115];
 MiscOpcodeUnimplemented[116];
 MiscOpcodeUnimplemented[117];


* Special entry to squash pending dispatch when an entire
* group is unimplemented.
Misc377:
 MiscOpcodeUnimplemented[377];

*-----------------------------------------------------------
* TArgs: TYPE = MDR[src, dst, table: LONG POINTER, srcSkip, dstSkip, count: CARDINAL]
MSC[TArgs.srcLo, 0];
MSC[TArgs.dstLo, 2];
MSC[TArgs.tableLo, 4];
MSC[TArgs.srcSkip, 6];
SetRMRegion[RMforIFU];
RME[SrcPtr, RTemp0];
RME[DstPtr, RTemp1];
RME[SrcSkip, RTemp2];
RME[DstSkip, RTemp3];
BR[TblBR, 26];  * share with NSIBR
BR[TblSrcBR, 27];  * share with NSOBR
*-----------------------------------------------------------
TblLookup: MiscTable[244],
* TableLookup: PROC [tArgs: TArgs]
* FOR k: CARDINAL IN [0..count) DO
* tArgs.dst[k*tArgs.dstSkip] ← tArgs.table[tArgs.src[k*tArgs.srcSkip]];
* ENDLOOP;
*-----------------------------------------------------------
 KnowRbase[RTemp0];
MemBase ← LPtr, RTemp0 ← A0;
BrHi ← T, StkP-2;
BrLo ← Stack&-1;
T ← (Fetch ← RTemp0) + 1;
T ← MD, Fetch ← T;
Membase ← TblSrcBR; * for src
BrLo ← T, T ← MD;
BrHi ← T;
Membase ← LPtr;
T ← (Fetch ← TArgs.dstLo) + 1;
T ← MD, Fetch ← T;
Membase ← ScratchBR; * for dst
BrLo ← T, T ← MD;
BrHi ← T;
Membase ← LPtr, DstPtr ← A0;
T ← (Fetch ← TArgs.tableLo) + 1;
T ← MD, Fetch ← T;
Membase ← TblBR, SrcPtr ← A0;
BrLo ← T, T ← MD;
BrHi ← T;
Membase ← LPtr;
T ← (Fetch ← TArgs.srcSkip) + 1;
SrcSkip ← MD;
T ← (Fetch ← T) + 1;
DstSkip ← MD;
Fetch ← T;
Cnt ← MD;
TblLoop:
Membase ← TblBR, Branch[TblDone, Cnt=0&-1];
T ← (Fetch ← TblPtr), FlipMembase;
TblPtr ← (SrcSkip) + T;
Fetch ← MD;
Membase ← ScratchBR;
T ← (Store ← DstPtr), DBuf ← MD;
DstPtr ← (DstSkip) + T, Branch[TblLoop];
TblLoop:
Membase ← TblSrcBR, Branch[TblDone, Cnt=0&-1];
T ← (Fetch ← SrcPtr), FlipMembase;
SrcPtr ← (SrcSkip) + T;
Fetch ← MD, Branch[Tbl1, Carry'];
FlipMembase, T ← A0;
DummyRef ← T;
T ← VaHi;
T ← T + 1;
BrHi ← T;
Tbl1:
Membase ← ScratchBR;
T ← (Store ← DstPtr), DBuf ← MD;
DstPtr ← (DstSkip) + T;
Branch[TblLoop, Carry'], T ← A0;
DummyRef ← T;
T ← VaHi;
T ← T + 1;
BrHi ← T, Branch[TblLoop];
TblDone: IFUNext0;
*-----------------------------------------------------------
* BltOp: TYPE = MDR[logAdd(0), logSubtract(1), and(2), or(3), xor(4)]
* OArgs: TYPE = MDR[srcA, srcB, dst: LONG POINTER, count, delta: CARDINAL, op: BltOp]
MSC[OArgs.srcALo, 0];
MSC[OArgs.srcBLo, 2];
MSC[OArgs.dstLo, 4];
MSC[OArgs.count, 6];
MSC[OArgs.delta, 7];
MSC[OArgs.op, 8];
SetRMRegion[RMforIFU];
RME[SrcAPtr, RTemp0];
RME[SrcBPtr, RTemp1];
RME[OpDstPtr, RTemp2];
RME[delta, RTemp3];
RME[op, RTemp4];
BR[SrcABR, 26];  * share with NSIBR
BR[SrcBBR, 27];  * share with NSOBR
OpBlt: MiscTable[245],
* OpBlt: PROC [oArgs: OArgs]
* FOR k: CARDINAL IN [0..oArgs.count) DO
* dst[k*oArgs.delta] ← oArgs.op[a: oArgs.srcA[k*oArgs.delta], b: oArgs.srcB[k*oArgs.delta]];
* ENDLOOP;
*-----------------------------------------------------------
KnowRbase[RTemp0];
MemBase ← LPtr, RTemp0 ← A0;
BrHi ← T, StkP-2;
BrLo ← Stack&-1;
T ← (Fetch ← RTemp0) + 1;
T ← MD, Fetch ← T;
Membase ← SrcABR; * for srcA
BrLo ← T, T ← MD;
BrHi ← T;
Membase ← LPtr;
T ← (Fetch ← OArgs.srcBLo) + 1;
T ← MD, Fetch ← T;
Membase ← srcBBR; * for srcB
BrLo ← T, T ← MD;
BrHi ← T;
Membase ← LPtr, SrcAPtr ← A0;
T ← (Fetch ← OArgs.dstLo) + 1;
T ← MD, Fetch ← T;
Membase ← ScratchBR, SrcBPtr ← A0; * dst
BrLo ← T, T ← MD;
BrHi ← T;
Membase ← LPtr, OpDstPtr ← A0;
T ← (Fetch ← OArgs.count) + 1;
Cnt ← MD;
T ← (Fetch ← T) + 1;
Delta ← MD;
Fetch ← T;
op ← MD;
OpBltLoop:
Membase ← SrcABR, Branch[OpBltDone, Cnt=0&-1];
T ← (Fetch ← SrcAPtr), FlipMembase;
SrcAPtr ← (delta) + T;
RTemp5 ← MD, Branch[DoSrcB, Carry'];
FlipMembase, T ← A0;
DummyRef ← T;
T ← VaHi;
T ← T + 1;
BrHi ← T;
DoSrcB:
Membase ← SrcBBR;
T ← (Fetch ← SrcBPtr);
SrcBPtr ← (delta) + T;
Branch[DoOpNow, Carry'], T ← A0;
DummyRef ← T;
T ← VaHi;
T ← T + 1;
BrHi ← T;
DoOpNow:  * values are in RTemp5 and MD
BDispatch ← op;
Membase ← ScratchBR, branch[opDisp];
opDisp: DispTable[8],
T ← (RTemp5) + (MD), Branch[finOpDisp];
T ← (RTemp5) - (MD), Branch[finOpDisp];
T ← (RTemp5) AND (MD), Branch[finOpDisp];
T ← (RTemp5) OR (MD), Branch[finOpDisp];
T ← (RTemp5) XOR (MD), Branch[finOpDisp];
T ← (RTemp5), Branch[finOpDisp];
T ← (RTemp5), Branch[finOpDisp];
T ← (RTemp5), Branch[finOpDisp];
finOpDisp:
T ← (Store ← OpDstPtr), DBuf ← T;
OpDstPtr ← (delta) + T;
Branch[OpBltLoop, Carry'], T ← A0;
DummyRef ← T;
T ← VaHi;
T ← T + 1;
BrHi ← T, Branch[OpBltLoop];
OpBltDone: IFUNext0;