{File name:  CedarMisc.mc
 Description: Miscellaneous Mesa opcodes, modified for Cedar
 Author: R. Garner,
 Created: April 3, 1980.
 Last edited:
 Fiala  5-Jun-86 18:23:56
 Fiala 23-Jul-86 17:01:40: Remove assumption that right-half of uIOPage contains
 	the bank number of the IOPage; use the constant cedarIOPageHigh instead.
 Fiala 18-Nov-86 15:52:32 Remove commented out old defn's of the old map opcodes.
 Fiala 20-Nov-86 17:22:26 Conditionally assemble of RCLK, SETMP, INPUT, and OUTPUT
 	only when Config # 7 (not Dicentra).
 Fiala 30-Jan-87 15:08:37 Removed obsolete defn's for ASSOC, GETF, and SETF.
 	Changed the displacement on SETMP from 41 to MaintenancePanelOffset for new IOP.
 Trow  26-Oct-87 17:11:03 Remove @INPUT, @OUTPUT.  Convert @RCLK, @SETMP, @SM, @SMF, @GMF.  Fix bank cross.  Add Daybreak ops.  Remove labels RR*.
 Trow  29-Oct-87 21:27:05 Fix PC in Daybreak MISC ops.
 Trow   3-Nov-87  1:17:41 Add @NOOP.  Fix interrupt enable/disable at WR1.
 bj     3-Nov-87  6:17:00 Fix @NOOP; Remove interrupt enable/disable at WR1.
 bj    16-Nov-87 20:57:49 Mess with interrupt enable/disable at WR1.
 jt     8-Mar-88 16:41:24 Move Daybreak misc ops to 5x.

 Copyright (c) 1980, 1981, 1985, 1986, 1987, 1988 by Xerox Corporation.  All rights reserved.
}
{
	MISC - Miscellaneous operations
}

@MISC:	Xbus ← ibHigh, XDisp,	c1, opcode[364'b];
	Rx ← ib, XDisp, push, DISP4[MiscHigh],	c2;
	STK ← TOS, pop, DISP4[Misc0n],		c3, at[0,10,MiscHigh];

{ The original Pilot 8.0 map opcodes, ASSOC, SETF, and GETF (Misc 0, 1, and 2), use
short arguments in which the VP is the first argument word and the RP and 4 map flags
are the second argument word; this results in a 32 megabyte VM limit and 2 megabyte
RM limit.  The equivalent SM, SMF, and GMF opcodes here use a 32-bit VP as the
first argument, 32-bit RP as the second argument, and 16-bit flags as the third
argument (protected, dirty, and referenced = bits 12 to 15), thereby permitting
larger VM and RM configurations.  However, the current implementation ignores the
high-order RM and VM words, so the only effect is that the RM page specification
increases from 12 bits to 16 bits (i.e., from 2 megabytes to 4 megabytes).

The DTiger can handle up to 8 megabytes of real memory, or up to 22-bit RM addresses.
The DLion limit of 20 bits of RM is partly due to the VM map design, which has 4 flag
bits and 12 bits of real page address.  The modification here extends the RM limit to
4 megabytes by converting 1 flag bit to an address bit.  Mesa PrincOps defines 6 map
flag states and reserves 2 more states, all encoded in 3 bits.  Extension to 8 megabytes
could be accomplished by putting some map flags in a separate storage table, as discussed
in DTigerManual.memo.

The map holds the 13-bit real page in bits [12..15] and [0..8] and the write protected,
dirty, and referenced flags in bits [9..11].  The flags are interpreted as follows
(see DLion Microcode Reference page 30):
    w  d  r	Interpretation		ReadOK	WriteOK
    0  0  0	untouched, unprotected	 no	 no
    0  0  1	unwritten, read		 yes	 no
    0  1  0	reserved for software	 --	 --
    0  1  1	written			 yes	 yes
    1  0  0	untouched, protected	 no	 no
    1  0  1	protected, read		 yes	 no
    1  1  0	vacant			 no	 no
    1  1  1	reserved for software	 --	 --
The ReadOk and WriteOK columns show whether or not read and write references can,
respectively, proceed without modification to the map entry.  The two "don't care"
states are filled in to allow ReadOK to be based upon a branch on the r bit (XRefBr)
and WriteOK to be based on a 4-way branch on the w and d bits (XwdDisp).
}

{db
{SM Set Map}
{The extra pops skip the high-order words of the real page and virtual page,
which are assumed to be 0.}
@SM:	TOS {map flags} ← TOS and 7, pop,		c1, at[08, 10, Misc6n];
	TT {real page} ← STK, pop,			c2;
{XRefBr tests bit 11, so this is testing bit 3 in the real page word,
the high-order bit of the real page.}
	TT ← TT LRot8, XRefBr, pop,			c3;

	T {virtual page} ← STK, pop, BRANCH[SMe, SMf], {Check ext. adr bit}	c1;
SMe:	TT ← TT and ~80, GOTO[SMg],			c2;
SMf:	TT ← TT or 80, {add ext adr bit}		c2;
{Now have the high-order address bit in bit 8.  Map flags will be formed in bits
9..11.  Bits 8..12 become 0..3 of the value written into the map.}
SMg:	rhT ← T ← T LRot8,				c3;

	PC ← PC + 1, fXpop, push,			c1;
	TOS ← TOS LRot4 {map flags},			c2;
	Noop,						c3;

	Noop,						c1;
	TT {real page} ← TT and ~70,			c2;
	TT ← TOS {map flags} or TT,			c3;
{Now have the real page in bits 12..15 and 0..8 of the map word and the
write protected, dirty, and referenced flags in bits 9..11.}

SMd:	Map ← [rhT, T],					c1;
	MDR ← TT, IBDisp, GOTO[SLTail],			c2;


{GMF Get Map Flags}
@GMF:	T {virtual page} ← STK, pop, L0 ← 1,		c1, at[09, 10, Misc6n];
	GOTO[SMFa],					c2;

GMFa:	STK ← 0, IBDisp, GOTO[SLTail],			c2;	


{SMF Set Map Flags.  Preserve old real page in the map unless new flags = vacant;
return old flags and real page as the result}
@SMF:	pop, L0 ← 0,					c1, at[0A, 10, Misc6n];
	T {virtual page} ← STK, pop,			c2;
SMFa:	rhT ← T ← T LRot8,				c3;

	TOS {new map flags} ← TOS and 7, fXpop, push,	c1;
	PC ← PC + 1,					c2;
	Noop,						c3;

	Map ← [rhT, T],					c1;
	TT {new map flags} ← TOS LRot4,			c2;
	TOS {old map entry} ← MD,			c3;

	Rx {old map flags} ← TOS LRot12, XDisp,		c1;
	TOS ← TOS and ~70, DISP4[SMFb, 8],		c2;
{Here, TT gets new map flags or'ed with old real page unless new flags = vacant.
If the map entry was vacant, it stays vacant, in spite of attempt to change the flags.}
SMFb:	TT ← TOS or TT, GOTO[SMFc],			c3, at[08, 10, SMFb];
	TT ← TOS or TT, GOTO[SMFc],			c3, at[09, 10, SMFb];
	TT ← TOS or TT, GOTO[SMFc],			c3, at[0A, 10, SMFb];
	TT ← TOS or TT, GOTO[SMFc],			c3, at[0B, 10, SMFb];
	TT ← TOS or TT, GOTO[SMFc],			c3, at[0C, 10, SMFb];
	TT ← TOS or TT, GOTO[SMFc],			c3, at[0D, 10, SMFb];
	TT ← TOS or 60, GOTO[SMFc], {vacant}		c3, at[0E, 10, SMFb];
	TT ← TOS or TT, GOTO[SMFc],			c3, at[0F, 10, SMFb];

{Now unscramble the real page.  The high-order bit in bit 8 must be moved
to bit 11 before rotating the whole real page into bits [3..15].}
SMFc:	[] ← TOS LRot0, XLDisp, {check ext adr bit}	c1;
	TOS ← TOS and ~80, BRANCH[SMFe, SMFf, 1],	c2;
SMFe:	GOTO[SMFg],					c3;
SMFf:	TOS ← TOS or 10 {add ext adr bit}, GOTO[SMFg],	c3;

SMFg:	Rx {old map flags} ← Rx and 7,			c1;
	TOS ← TOS LRot8 {real page}, push,		c2;
	STK ← Rx, push, L0Disp,				c3;

	STK ← TOS, push, BRANCH[SMFd, GMFa],		c1;
SMFd:	STK ← 0,					c2;
	GOTO[SMd],					c3;
db}




{db}
{The Daybreak map entries contain map flags in bits 8..10, high order real page address in bits 11..15, and lower order real page address in bits 0..7.  While @SM, @SMF, and @GMF expect flags to be in w,d,r order, internally they are in r,d,w order:

    r  d  w	Interpretation		ReadOK	WriteOK
    0  0  0	untouched, unprotected	 no	 no
    0  0  1	untouched, protected	 no	 no
    0  1  0	reserved for software	 --	 --
    0  1  1	vacant			 no	 no
    1  0  0	unwritten, read		 yes	 no
    1  0  1	protected, read		 yes	 no
    1  1  0	written			 yes	 yes
    1  1  1	reserved for software	 --	 --

The ReadOk and WriteOK columns show whether or not read and write references can,
respectively, proceed without modification to the map entry.  The two "don't care"
states are filled in to allow ReadOK to be based upon a branch on the r bit (XRefBr)
and WriteOK to be based on a 4-way branch on the d and w bits (XdwDisp).
}


{SM Set Map}
{The extra pops skip the high-order words of the real page and virtual page,
which are assumed to be 0.}
@SM:	TOS {map flags} ← TOS and 7, pop,		c1, at[08, 10, Misc6n];
	TT {real page} ← STK, pop, L0 ← 1,		c2;
	TT ← TT LRot8, pop,				c3;

	T {virtual page} ← STK, pop,			c1;
	rhT ← T ← T LRot8,				c2;
	PC ← PC + 1, fXpop, push,			c3;

	Xbus ← TOS LRot0, XDisp, TOS ← 0,		c1;
SMa:	TT ← TT and ~0E0, DISP4[SMb,8],			c2;
SMb:	TT ← TT or 0, L0Disp, GOTO[SMc],		c3, at[08,10,SMb];
	TT ← TT or 80, L0Disp, GOTO[SMc],		c3, at[09,10,SMb];
	TT ← TT or 40, L0Disp, GOTO[SMc],		c3, at[0A,10,SMb];
	TT ← TT or 0C0, L0Disp, GOTO[SMc],		c3, at[0B,10,SMb];
	TT ← TT or 20, L0Disp, GOTO[SMc],		c3, at[0C,10,SMb];
	TT ← TT or 0A0, L0Disp, GOTO[SMc],		c3, at[0D,10,SMb];
	TT ← TT or 60, GOTO[SMc],			c3, at[0E,10,SMb];
	TT ← TT or 0E0, L0Disp, GOTO[SMc],		c3, at[0F,10,SMb];

SMc:	Map ← [rhT, T], BRANCH[SMFe, SMd, 0E],		c1;
SMd:	MDR ← TT, IBDisp, GOTO[SLTail],			c2;

{SLTail:	TOS ← STK, pop, DISPNI[OpTable],	c3;}


{This code isn't needed till someone wants to try PC emulation in Cedar.

SMc:	Map ← [rhT,T], BRANCH[SMFe, SMd, 0E],				c1;
SMd:	MDR ← TT, TT ← UvL,						c2;
	rhTT ← UvMDS,							c3;

{This section was added for supporting PC emulation.  Pilot has the right to change the real page numbers of L, G, and PC at will, so every time a SM is done, we remap these quantities just in case the SM operation changed their real page number. - AEF}

SMe:	Rx ← ~0FF,							c1;
	T ← L and 0FF,							c2;
	Q ← G and 0FF,							c3;

	Map ← [rhTT, TT], TT ← UvG,					c1;
	rhTT ← UvGhigh,							c2;
	rhL ← MD, L ← MD and Rx,					c3;

	Map ← [rhTT, TT], TT ← UvPCpage,				c1;
	rhTT ← UvChigh,							c2;
	rhG ← MD, G ← MD and Rx,					c3;

	Map ← [rhTT, TT],						c1;
	TT ← PC and 0FF,						c2;
	rhPC ← MD, PC ← MD and Rx,					c3;

	PC ← PC or TT,							c1;
	L ← L or T, IBDisp,						c2;
	G ← G or Q, pop, DISPNI[OpTable],				c3;
}


{GMF Get Map Flags}
@GMF:	T {virtual page} ← STK, pop, L0 ← 1,		c1, at[09, 10, Misc6n];
	GOTO[SMFa],					c2;

GMFa:	STK ← 0,					c1;
	IBDisp, GOTO[SLTail],				c2;


{SMF Set Map Flags.  Preserve old real page in the map unless new flags = vacant;
return old flags and real page as the result}
@SMF:	pop, L0 ← 0,					c1, at[0A, 10, Misc6n];
	T {virtual page} ← STK, pop,			c2;
SMFa:	rhT ← T ← T LRot8,				c3;

	TOS {new map flags} ← TOS and 7, fXpop, push,	c1;
	PC ← PC + 1,					c2;
	Noop,						c3;

	Map ← [rhT, T],					c1;
	Noop,						c2;
	TT {old map entry} ← MD,			c3;

	Xbus ← TT LRot12, XDisp {disp old flags},	c1;
	TT ← TT and ~0E0, DISP4[SMFb,1],		c2;
SMFb:	Rx ← 0, push, GOTO[SMFc],			c3, at[01,10,SMFb];
	Rx ← 4, push, GOTO[SMFc],			c3, at[03,10,SMFb];
	Rx ← 2, push, GOTO[SMFc],			c3, at[05,10,SMFb];
	Rx ← 6, push, L0←1, GOTO[SMFc], {vacant}	c3, at[07,10,SMFb];
	Rx ← 1, push, GOTO[SMFc],			c3, at[09,10,SMFb];
	Rx ← 5, push, GOTO[SMFc],			c3, at[0B,10,SMFb];
	Rx ← 3, push, GOTO[SMFc],			c3, at[0D,10,SMFb];
	Rx ← 7, push, GOTO[SMFc],			c3, at[0F,10,SMFb];

SMFc:	STK ← Rx {old external map flags},		c1;
	Rx ← TT LRot8, push, L0Disp,			c2;
	STK ← Rx {real page}, push, BRANCH[SMFd, GMFa],	c3;

SMFd:	Xbus ← TOS LRot0, XDisp,			c1;
	STK ← 0, DISP4[SMb,8],				c2;

SMFe:	MDR ← TT, IBDisp, GOTO[SLTail],			c2;
{db}


	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0, 10, Misc0n]; {was ASSOC}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[1, 10, Misc0n]; {was SETF}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0E, 10, Misc0n]; {was GETF}

{The Dicentra has a different implementation of interval timer, input, and output}
IfEqual[Config, 7,,SkipTo[DLionIO]];
	{Dicentra implements RCLK differently}
	{Dicentra implements SETMP differently}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[5, 10, Misc0n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[6, 10, Misc0n];
	SkipTo[AllConfigs1]; {******End of Dicentra specific IO******}

DLionIO!

{db
@RCLK:	{must read all three clock regs in single click}
	TOS ← uClockHigh, push,				c1, at[9,10,Misc0n];
	T ← RShift1 uClockBits, SE←0, push,		c2;
	TT ← uClockLow,					c3;

	TT ← TT + T, CarryBr, push, fZpop,		c1;
	STK ← TT, IBDisp, PC ← PC + 1, BRANCH[RCLKnc, RCLKc],	c2;
RCLKnc:	DISPNI[OpTable],				c3;
RCLKc:	TOS ← TOS + 1, DISPNI[OpTable],			c3;
db}


{db}
{timer addresses and commands}

Set[T1Count, 41];
Set[T2Count, 42];
Set[T012Control, 43];

Set[T12Latch, 0DC];

@RCLK:	{read interval timer}
	rhRio ← T012Control,					c1, at[9,10,Misc0n];
	Rx ← 0, push,						c2;
	STK ← TOS, push,					c3;

{ The two halves of the counter are synchronized by a latch command given to the 8254 control register.  The counts are correct and synchronized to the command, not to when the counters are read. }
  
ReadTimer:
	IO ← [rhRio, 0], {Control Register}			c1;
	MDR ← T12Latch, {Latching the counts}			c2;
	rhRio ← T2Count,					c3;

{ read timer two, higher 16 bits }

	IO ← [rhRio, 0], {Cnt 2 LSB}				c1;
	T ← 0FF,						c2;
	Q ← MD and T, {mask high byte}				c3;

	IO ← [rhRio, 0], {Cnt 2 MSB}				c1;
	rhRio ← T1Count,					c2;
	TOS ← MD and T, {mask high byte}			c3;

{ read timer one, lower 16 bits, and finish higher (interlaced instructions)}

	IO ← [rhRio, 0], {Cnt 1 LSB}				c1;
	TOS ← TOS LRot8 or Q, {combine timer 2 bytes}		c2;
	Q ← MD and T, {mask high byte}				c3;

	IO ← [rhRio, 0], {Cnt 1 MSB}				c1;
	TOS ← 0 - TOS, {down count},				c2;
	T ← MD and T, {mask high byte}				c3;

	T ← T LRot8 or Q, {combine timer 1 bytes}		c1;
	T ← 1 - T, {down count, carries at 1}			c2;
	[] ← T or Rx, NZeroBr, {timing glitch when T is 0}	c3;

	STK ← T, BRANCH[$,RRx], {in Misc.mc}			c1;
	Rx ← 1, {need only one repeat}				c2;
	rhRio ← T012Control, GOTO[ReadTimer],			c3;

RRx:	push, fZpop, IBDisp,					c2;
	PC ← PC + 1, DISPNI[OpTable],				c3;
{db}


{db
@SETMP:	PC ← PC + PC16,{+PC16 at SLns} fXpop, push,	c1, at[8,10,Misc0n];
	TT ← uIOPage,					c2;
	TT ← TT + MaintenancePanelOffset {was 41},	c3;

	rhTT ← cedarIOPageHigh,				c1;
	Noop,						c2;
	Noop,						c3;

	MAR ← [rhTT,TT+0], push{popped at SLns}, GOTO[SLns],	c1;
db}


{db}
@SETMP:	{write maintenance panel}
	TT ← uMaintPanel, {maint panel code}			c1, at[8,10,Misc0n];
	rhTT ← uIORgnHigh,					c2;
	TOS ← TOS LRot8, {must byteswap}			c3;

	MAR ← [rhTT, TT + 0],					c1;
	MDR ← TOS,						c2;
	TT ← TT + 1, {maint panel down-notify mask}		c3;

	MAR ← [rhTT, TT + 0],					c1;
	Noop,							c2;
	TOS ← MD, GOTO[@NOTIFYIOP],				c3;
	{PC ← PC + 1 in NOTIFYIOP}
{db}


{db}	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[5, 10, Misc0n];
{db}	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[6, 10, Misc0n];

{db
@INPUT:	PC ← PC + 1, Xbus ← TOS LRot0, XDisp,		c1, at[5,10,Misc0n];
	fXpop, push, Ybus ← 0, EtherDisp, DISP4[Input],	c2;
Input:	TOS ← EIData, CANCELBR[MiscDone,3],		c3, at[0,10,Input];
	TOS ← EStatus, CANCELBR[MiscDone,3],		c3, at[1,10,Input];
	TOS ← KIData, CANCELBR[MiscDone,3],		c3, at[2,10,Input];
	TOS ← KStatus, CANCELBR[MiscDone,3],		c3, at[3,10,Input];
	KStrobe, CANCELBR[MiscDone,3],			c3, at[4,10,Input];
	TOS ← MStatus, CANCELBR[MiscDone,3],		c3, at[5,10,Input];
	TOS ← KTest, CANCELBR[MiscDone,3],		c3, at[6,10,Input];
	TOS ← IOPIData, CANCELBR[MiscDone,3],		c3, at[8,10,Input];
	TOS ← IOPStatus, CANCELBR[MiscDone,3],		c3, at[9,10,Input];
	BRANCH[Ether, NoEther, 1],			c3, at[0A,10,Input];
Ether:	TOS ← 1, GOTO[IBDispOnly],			c1;
NoEther:	TOS ← 0, GOTO[IBDispOnly],		c1;

MiscDone:	GOTO[IBDispOnly],			c1;
@OUTPUT:	T ← STK, pop,				c1, at[6,10,Misc0n];
	PC ← PC + 1, Xbus ← TOS LRot0, XDisp,		c2;
	TOS ← STK, pop, DISP4[Output],			c3;

Output:	IOPOData ← T LRot0, GOTO[IBDispOnly],		c1, at[0,10,Output];
	IOPCtl ← T LRot0, GOTO[IBDispOnly],		c1, at[1,10,Output];
	KOData ← T LRot0, GOTO[IBDispOnly],		c1, at[2,10,Output];
	KCtl ← T LRot0, GOTO[IBDispOnly],		c1, at[3,10,Output];
	EOData ← T LRot0, GOTO[IBDispOnly],		c1, at[4,10,Output];
	EICtl ← T LRot0, GOTO[IBDispOnly],		c1, at[5,10,Output];
	DCtlFifo ← T, GOTO[IBDispOnly],			c1, at[6,10,Output];
	DCtl ← T LRot0, GOTO[IBDispOnly],		c1, at[7,10,Output];
	DBorder ← T, GOTO[IBDispOnly],			c1, at[8,10,Output];
	PCtl ← T LRot0, GOTO[IBDispOnly],		c1, at[9,10,Output];
	MCtl ← T, GOTO[IBDispOnly],			c1, at[0A,10,Output];
	EStrobe, GOTO[IBDispOnly],			c1, at[0B,10,Output];
	EOCtl ← T LRot0, GOTO[IBDispOnly],		c1, at[0C,10,Output];
	KCmd ← T LRot0, GOTO[IBDispOnly],		c1, at[0D,10,Output];
	POData ← T LRot0, GOTO[IBDispOnly],		c1, at[0F,10,Output];
db}

AllConfigs1! {******End of DLion specific IO******}

	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[2,10,Misc0n]; {ReadRam}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[3,10,Misc0n]; {LoadRam}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[4,10,Misc0n];


	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0A,10,Misc0n]; {RPRINTER}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0B,10,Misc0n]; {WPRINTER}
{IfEqual[Config, 1, SkipTo[BandBlt], ];	****Raven w/o BandBlt...(bj)****}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0C,10,Misc0n]; {BANDBLT}
{BandBlt!}

	{*****HES***** changed TextBlt here}
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0D,10,Misc0n]; {TEXTBLT}

MiscF:	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],		c1, at[0F,10,Misc0n];

	{STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[1,10,MiscHigh];} { 20'b to  37'b => CedarFpt.mc}
{Unimplemented Misc Groups}
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[2,10,MiscHigh];  { 40'b to  57'b}
	{STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[3,10,MiscHigh];} { 60'b to  77'b => CedarB1.mc}
	{STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[4,10,MiscHigh];} {100'b to 117'b => CedarB1.mc}
{db	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[5,10,MiscHigh];} {120'b to 137'b => Cedar/Daybreak}
	{STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[6,10,MiscHigh];} {140'b to 157'b => CedarB1.mc}
IfEqual[Config, 7, SkipTo[AllConfigs2], ];
	{Special Dicentra IO operations}
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[7,10,MiscHigh]; {160'b to 177'b => MiscDicentraB1.mc}
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[8,10,MiscHigh]; {200'b to 217'b}
AllConfigs2!
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[9,10,MiscHigh];
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[0A,10,MiscHigh];
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[0B,10,MiscHigh];
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[0C,10,MiscHigh];
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[0D,10,MiscHigh];
	STK ← TOS, pop, CANCELBR[MiscF, 0F],		c3, at[0F,10,MiscHigh];

{
	WR - Write Register
}
{Timing - 2 clicks}
@WR:	Xbus←ib, PC ← PC + 1, push, XDisp,		c1, opcode[374'b];
	STK ← TOS, T ← 0FF, pop, DISP4[WR1],		c2;

WR0:	uPSB ← TOS, GOTO[WRTail],			c3, at[0,10,WR1];

WR1:
{db	uWDC ← TOS and T, GOTO[WRTail],			c3, at[1,10,WR1]; }
{db}	Noop,							c3, at[1,10,WR1];

{db}	uWDC ← TOS and T, ZeroBr,				c1;
{db}	TOS ← STK, pop, IBDisp, BRANCH[DisableInts,EnableInts],	c2;
DisableInts:
{db}	{ClrIE}, DISPNI[OpTable],				c3;
EnableInts:
{db}	{SetIE}, DISPNI[OpTable],				c3;

WR2:	uXTS ← TOS, GOTO[WRTail],			c3, at[2,10,WR1];
WR3:	UvMDS ← TOS,					c3, at[3,10,WR1];

	rhMDS ← UvMDS,					c1;
	L ← UvL,					c2;
	G ← UvG,					c3;

	Map ← Q ← [rhMDS, L],				c1;
	T ← Q and 0FF,					c2;
	L ← rhL ← MD,					c3;

	Map ← Q ← [rhMDS, G],				c1;
	L ← L and ~0FF,					c2;
	G ← rhG ← MD,					c3;

	MAR ← G ← [rhG, Q+0],				c1;
	L ← L or T, IBDisp, GOTO[SLTail],		c2;

WR8:	uPTC ← TOS, GOTO[WRTail],			c3, at[8,10,WR1];

WRTail:	TOS ← STK, pop, GOTO[IBDispOnly],		c1;

{
	RR - Read Register
}
{Timing - 1 click}
@RR:	T←ib, push, XDisp,				c1, opcode[375'b];
	STK ← TOS, PC ← PC+1, IBDisp, push, fZpop, DISP4[RR1],	c2;

	TOS ← uPSB, DISPNI[OpTable],			c3, at[0,10,RR1];
	TOS ← uWDC, DISPNI[OpTable],			c3, at[1,10,RR1];
	TOS ← uXTS, DISPNI[OpTable],			c3, at[2,10,RR1];
	TOS ← UTrapParm{XTP}, DISPNI[OpTable],		c3, at[3,10,RR1];
	TOS ← UvMDS, DISPNI[OpTable],			c3, at[6,10,RR1];
	TOS ← uPTC{PTC}, DISPNI[OpTable],		c3, at[8,10,RR1];



{********************************************************************
	Daybreak specific opcodes
********************************************************************}

	STK ← TOS, pop, DISP4[Misc5n],				c3, at[05,10,MiscHigh];

@BYTESWAP:
	TOS ← TOS LRot8, pop,					c1, at[00,10,Misc5n];
	PC ← PC + 1, push, IBDisp, GOTO[DISPNIonly],		c2;

{-------------------------------------------------------------------------}

{@LOCKMEM: [operation, offset, value, mask] RETURNS [result]}
{TOS contains lock mask}
{T is loaded with value for operation}
{TT is loaded with offset into IORegion, whose base address is in [uIORgnHigh, rIORgn]}
{rhT is loaded with operation code}

@LOCKMEM:
	T ← STK, pop,						c1, at[01,10,Misc5n];
	TT ← STK, pop, L4 ← SoftwareLockRets.LOCKMEM,		c2;
	rhT ← STK, pop,						c3;

	MAR ← [rhIORgn, rIORgn + iopRequestsLock],		c1;
	TT ← TT + rIORgn, CANCELBR[SoftwareLockSideDoor,0],	c2;

	MDR ← 0, IBDisp, push, CANCELBR[$,0],			c2, at[SoftwareLockRets.LOCKMEM,10,SoftwareLockRets];
	PC ← PC + 1, STK ← TOS, fXpop, fZpop, DISPNI[OpTable],	c3;

{-------------------------------------------------------------------------}

@NOTIFYIOP: {TOS contains notify mask: byte-mask in high byte, byte offset in low}
	T ← uMesaProc,						c1, at[02,10,Misc5n];
	rhT ← uIORgnHigh,					c2;
	TT ← LShift1 (T + downNotifyBits), LOOPHOLE[niblTiming], c3;

	MAR ← [rhT, T + notifiersLockMask],			c1;
	STK ← TOS, T ← TOS and ~0FF, CANCELBR[$,0],		c2;
	TOS ← MD, L4 ← SoftwareLockRets.NOTIFYIOP,		c3;

	rhTT ← STK, pop, XLDisp,				c1;
{the following branch is reversal of Mesa byte order to do byte-swapping for IOP}
	TT ← RShift1 (TT + rhTT), LOOPHOLE[niblTiming], BRANCH[MaskInLowByte,$,2], c2;
	rhT ← lock.or, SetMPIntIOP, CALL[SoftwareLock],		c3;
MaskInLowByte:
	rhT ← lock.or, SetMPIntIOP,				c3;

	MAR ← [rhIORgn, rIORgn + iopRequestsLock],		c1;
	T ← T LRot8, CANCELBR[SoftwareLockSideDoor,0],		c2;

	MDR ← 0, IBDisp, CANCELBR[$,0],				c2, at[SoftwareLockRets.NOTIFYIOP,10,SoftwareLockRets];
	PC ← PC + 1, ClrMPIntIOP, DISPNI[OpTable],		c3;

{-------------------------------------------------------------------------}

@SetWakeupBits:
	T ← TOS, push, MesaIntRq,				c1, at[03,10,Misc5n];
	STK ← TOS, pop,						c2;
	TOS ← STK, pop,						c3;

	T ← T or uWP,						c1;
	PC ← PC + 1, uWP ← T, IBDisp, GOTO[DISPNIonly],		c2;


{-------------------------------------------------------------------------}

{	Useful for setting breakpoints while debugging Cedar.	}

@NOOP:
	Noop,							c1, at[04,10,Misc5n];
	PC ← PC + 1, IBDisp, GOTO[DISPNIonly],			c2;


{-------------------------------------------------------------------------}

{	

@PEEK:
	Noop,							c1, at[05,10,Misc5n];
	PC ← PC + 1, IBDisp, GOTO[DISPNIonly],			c2;			}


{-------------------------------------------------------------------------}

{	

@POKE:
	Noop,							c1, at[06,10,Misc5n];
	PC ← PC + 1, IBDisp, GOTO[DISPNIonly],			c2;			}


{	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[00,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[01,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[02,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[03,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[04,10,Misc5n];	}

	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[05,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[06,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[07,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[08,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[09,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[0A,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[0B,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[0C,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[0D,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[0E,10,Misc5n];
	T ← Rx + 377'b + 1, GOTO[UnimpOpcode],			c1, at[0F,10,Misc5n];

{-------------------------------------------------------------------------}

{SoftwareLock subroutine
L4 contains return branch
TOS contains mask
T contains value
TT contains low real address of word on which locked op is done
rhT contains operation code in lower three bits
on return, TOS contains result}

SoftwareLock:
	MAR ← [rhIORgn, rIORgn + iopRequestsLock],			c1;
	CANCELBR[$,0],							c2;
SoftwareLockSideDoor:
	Rx ← MD,							c3;

	Rx ← TOS and Rx,						c1;
	[] ← Rx, ZeroBr, {zero iff lock available}			c2;
	BRANCH[SoftwareLock,$],						c3;

	MAR ← [rhIORgn, rIORgn + mesaHasLock],				c1;
	MDR ← TOS, CANCELBR[$,0],					c2;
	rhTT ← uIORgnHigh,						c3;

LockAcquired:
	MAR ← [rhTT, TT + 0],						c1;
	Xbus ← rhT, XDisp,						c2;
	TOS ← MD, DISP4[LockedOp,08],					c3;

LockedAdd:
	MAR ← [rhTT, TT + 0],						c1, at[lock.add,10,LockedOp];
	MDR ← TOS ← T + TOS, GOTO[ClearLock],				c2;

LockedAnd:
	MAR ← [rhTT, TT + 0],						c1, at[lock.and,10,LockedOp];
	MDR ← TOS ← T and TOS, GOTO[ClearLock],				c2;

LockedOr:
	MAR ← [rhTT, TT + 0],						c1, at[lock.or,10,LockedOp];
	MDR ← TOS ← T or TOS, GOTO[ClearLock],				c2;

LockedXchg:
	MAR ← [rhTT, TT + 0],						c1, at[lock.xchg,10,LockedOp];
	MDR ← T, GOTO[ClearLock],					c2;

LockedWrIfNil:
	[] ← TOS, ZeroBr,						c1, at[lock.wrIfNil,10,LockedOp];
	BRANCH[ClearLock,$],						c2;
	GOTO[LockedOr] {same as write, since TOS = 0},			c3;

ClearLock:
	L4Disp,								c3;

	MAR ← [rhIORgn, rIORgn + mesaHasLock], DISP4[SoftwareLockRets],	c1;




{
	Unimplemented Opcodes
}
Unimplemented:
	T ← 75'b, GOTO[UnimpOpcode],			c1, opcode[75'b];
	T ← 174'b, GOTO[UnimpOpcode],			c1, opcode[174'b];
	T ← 175'b, GOTO[UnimpOpcode],			c1, opcode[175'b];
	T ← 176'b, GOTO[UnimpOpcode],			c1, opcode[176'b];
	T ← 177'b, GOTO[UnimpOpcode],			c1, opcode[177'b];
	T ← 271'b, GOTO[UnimpOpcode],			c1, opcode[271'b];
	T ← 272'b, GOTO[UnimpOpcode],			c1, opcode[272'b];
	T ← 273'b, GOTO[UnimpOpcode],			c1, opcode[273'b];
	T ← 274'b, GOTO[UnimpOpcode],			c1, opcode[274'b];
	T ← 275'b, GOTO[UnimpOpcode],			c1, opcode[275'b];
	T ← 276'b, GOTO[UnimpOpcode],			c1, opcode[276'b];
	T ← 277'b, GOTO[UnimpOpcode],			c1, opcode[277'b];
	T ← 355'b, GOTO[UnimpOpcode],			c1, opcode[355'b];
@STOP: 	T ← 362'b, GOTO[UnimpOpcode],			c1, opcode[362'b]; {STOP}
	T ← 366'b, GOTO[UnimpOpcode],			c1, opcode[366'b]; {STARTIO}
	T ← 367'b, GOTO[UnimpOpcode],			c1, opcode[367'b]; {JRAM}
	T ← 373'b, GOTO[UnimpOpcode],			c1, opcode[373'b];
	T ← 377'b, GOTO[UnimpOpcode],			c1, opcode[377'b];

UnimpOpcode:
	uNcTrapOffset ← T,				c2;
	T ← NcUnImplementedTrap,			c3;
	
	UTrapParm ← T,					c1;
	{noop}						c2;
	T ← sNcCedarTrapTable, GOTO[TrapContinue],	c3;


{********************************************************************
Transfer locations in bank1 for assorted exits from Cedar code
********************************************************************}
{db}	T ← sNcCedarTrapTable, GOTOABS[B1TrapContinue],	c3, at[BxTrapContinue];

TrapContinue: {first part executed in Bank0}
{CedarFptAll.UnImplementedFP, CommonSubs.Trapc2}
	L2 ← L2.NcCedarOpCodeTrap2,			c1, at[B1TrapContinue];
	TT ← UvPCpage, L1 ← 0, GOTO[StashPC0],		c2;

	{FixedXfer.TrapGo}
	uPCValid ← 0, BRANCH[$, NcXferFaultStandIn],	c3, at[L2.NcCedarOpCodeTrap2, 10, StashRets];

	rhT ← xtTrap,					c1;
	{FixedXfer.SDFetch}
	TT ← uSDAddr, L2 ← L2.NcCedarOpCodeTrap3,	c2;
	TT ← TT + T,					c3;

	Map ← Q ← [rhMDS, TT], CALL[XMDSRead] {this read does not fault},	c1;

	[] ← T, ZeroBr, CANCELBR[$, 0F],		c1, at[L2.NcCedarOpCodeTrap3, 10, XMDSReadRets];
	TT ← uNcTrapOffset, L2 ← L2.EFCHaveLink, BRANCH[NcSDFetchxStandIn, $], c2;

{cedar opcode trap table not defined, so treat as unimplemented op}
	T ← sUnimplemented,				c3;

	GOTO[SDFetch],					c1;

{FixedXfer.XferFault}
NcXferFaultStandIn:
	Rx ← pFault, GOTO[SaveRegs],			c1;

{FixedXfer.SDFetchx} {avoids a conflict when assembled with Cedar 4.4 version of the microcode}
NcSDFetchxStandIn:
	TT ← TT + T,					c3;

	Map ← Q ← [rhMDS,TT],				c1;
	L ← UvL, L0←L0.XMStartRead, CALL[XMDSReadx],	c2;


{db}	TOS ← STK, GOTOABS[B1CedarFault],		c3, at[BxCedarFault];

CedarFault:
	Noop,						c1, at[B1CedarFault];
	GOTO[Faultc3] {In CommonSubs.mc},		c2;

{Arrive here via GOTOABS from Bank 0 LongBlkZ, WriteMBus, ReadMBus, WritePCBus,
ReadPCBus, and Checksum in BlockB0.mc.}
{db}	STK ← TOS, pop, GOTOABS[B1IntContinue],			c3, at[BxIntContinue1];

{db}	TOS ← STK ← Q, pop, GOTOABS[B1IntContinue],		c3, at[BxIntContinue2];

IntContinue:
	Rx ← pInt {for a YDisp}, GOTO[SaveRegs {Process}],	c1, at[B1IntContinue];


{edit log

Early changes to remove TextBlt and to move floating point to CeddarFpt.

Sandman, April 23, 1981 8:46 AM: Fix Stack on Misc ~IN[0..15].
Frandeen, March 16, 1981 11:51 AM: Allow Block to catch Checksum Misc
Sturgis 18-Jul-83  9:58:03: add Input[6] case (TOS ← KTest).
Fiala 12-Jul-85 17:23:07: restore trap mi for 300'b to 317'b; restore trap for opcodes
	271'b and 272'b (formerly test versions of AssignRef and AssignRefNew); change
	name from NewCedarMisc.mc to CedarMisc.mc.
Fiala 18-Jul-85 10:58:53: Make all unimplemented opcodes use the Cedar trap table.
Fiala  7-Aug-85 17:25:27: Absorb Bank 0 reentries from CedarB1.
Fiala 17-Apr-86 10:22:44 Make Checksum opcode jump to code in Bank 0 (in CedarB0.mc).
Fiala 22-Apr-86 13:08:18: Replace jaw-breaking long names for Cedar interrupt and trap entries.
Fiala 30-Apr-86 17:19:29: Moved Checksum entry to CedarB1.mc
BJackson 17-Nov-85 20:03:42: Turned off BandBlt for Raven version (Config = 1).
Fiala 20-May-86 14:52:08: Added long format map opcodes and revised existing short format map
	opcodes to use new format.
}