{File name:  StartCedar0.mc
 Description: Cedar Emulator initialization,

 Last Edited:
  Sturgis: 16-Sep-83 10:47:37: add a patch to zero uStickyReg for Floating point,
	a Kludge added because rollBack dosn't do it.  Once rollback zeros the
	register, all is well and this patch can be removed.
  Fiala 11-Jun-86 15:40:48:  Prepare for Initial changes by inserting init for u200
	and uSDAddr; remove def'n for uStickyRegx.
  Fiala 23-Jul-86 15:36:19 Insert changes for alternate configurations from 12.0
   	product microcode; do not assume that uIOPage contains bank number in rh;
	SAx000 code gets new init of PCtl.
  Fiala 25-Jul-86  9:47:58 Removed uStickyReg and uSDAddr init to InitDLion.mc.
  Fiala 30-Jul-86 10:29:20 Cosmetic.
  Fiala  9-Sep-86 15:13:40 Move Display IOPage defn's to Dandelion.dfn.
  Fiala 18-Nov-86 14:01:33 Add assembly config switch for Dicentra.
  Fiala 30-Jan-87 17:35:57 Removed useless rhTT ←; cosmetic edits to make
  	keys up init like Pilot 12.2.
  Fiala  6-Mar-87 10:54:48 Move this module from Bank 1 to Bank 0 for new booting
  	procedure.  Move Kernel & multi-bank reserves here from CedarB0.mc.
	Changed multi-bank reserve to be [1, 7F] and [800, 801] instead of [1, 0FF].
	Changed exit to do bank cross to B1EFCHaveLink.  Put code to show 799 in
	MP in as a comment.
  Trow	20-Oct-87 22:09:46 Remove initialization of DCtl, PCtl, KCtl, IOPCtl.  Fix bank cross.
  Trow	22-Oct-87 23:13:05 Add Cedar Emulator register (constants) initialization.
  Trow	27-Oct-87 19:09:32 Convert to StartCedar.mc.
  Trow	28-Oct-87  1:06:47 Split into StartCedar0.mc and StartCedar1.mc.
  Trow	30-Oct-87 23:10:08 Change starting point.
  Trow	31-Oct-87  1:39:03 Remove Reserve clauses in favor of Extensions.dfn.
  Trow	 2-Nov-87 17:19:03 Combine SwapGerm.mc into StartCedar0.mc.
  Trow	 3-Nov-87 16:16:13 Add StartHere.
  bj	 4-Nov-87  2:11:57 Change to use boot slot 23.
  Trow	 9-Nov-87 20:27:24 Initialize uPSB.
  bj	 8-Mar-88  1:34:14 read the length of the Germ out of its own image.
}



{db *****
	Reserve[0F6F]; Reserve[0F78]; Reserve[0F7F,0FFF];	{Kernel/Bermuda}
	Reserve[1, 7F]; {ExtraBanksKernel & IOPBoot}
	Reserve[800, 801]; {Don't know why this is reserved}
***** db}


{** this stuff is specific to PrincOps version! **}

Set[mapRealAddrHigh,	4];
Set[mapRealAddrLow,	0];

Set[germPageHigh,	0];
Set[germPageLow,	0];

Set[cedarGermPageHigh,	3E];
Set[cedarGermPageLow,	2];

Set[globalFrameTableHigh,	2];
Set[globalFrameTableLow,	0];

Set[germPageCount,	40];	{should get this value from Opie}
Set[topPageHighByte,	1B];	{		"		}
Set[topPageLowByte,	80];	{		"		}

MacroDef[RtnBLT, at[#1,10,subrRet]];

Set[L0.gftExch,		0];
Set[L0.germExch,	1];
Set[L0.vswap,		2];

Set[device,		0F1];
Set[bootfile,		0F3];



{InitDaybreak is now an initialization routine which ends by looping at addrLinkage. The emulator resumes at this address in any cycle; the following code synchronizes the cycle and transfers control to boot Cedar.  Note that InitDaybreak has set up parameters and loaded the germ for booting Mesa/Pilot.}

Linkage:
	[] ← L {=0} + PC16, NZeroBr, BRANCH[Linkage, LinkageEntry],		c*, at[addrLinkage];
LinkageEntry:
	Xbus ← 0, XC2npcDisp, BRANCH[LinkageEntry, ReadGermLength, 5],	c*;


StartHere:
	[] ← 1, ZeroBr, GOTO[Linkage],						c1;



{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

	Well, We've got a problem here.

	PrincOps 3.0 expects the germ at .mv 3E0200 and
	PrincOps 4.0 expects the germ at .mv 100.

	We can move the germ in virtual space by moving map entries; we don't have
	to move anything in physical address space.

	transferCount contains the number of virtual pages we have to move
	from .map 1 to .map 3E02

	CoreInitial sets up map and leaves next available virtual page in topPage.

	Since everybody's been nice enough so far to move things around and play the
	game according the the PrincOps 4.0 rules (like Bermuda),
	how about if we just swap the approprite map entries
	and leave everything as it already is?

	Well, that leaves a funny hole in VM at .mv 100,
	
	So...

	So we do an even cuter swap
	put the germ where it belongs: .mv 3E0200 <==> .mv 100
	move some real pages back under .vm 100 to be *nice*
	.map topPage-transferCount <==> .map 1

	On top of that, MDS relief required moving one other page in the germ that we
	have to fix up to get the global frame table back in the right place.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
}


{
	Read the size of the Germ Image from the SD (last word of the first page)
}

ReadGermLength:
		rErh ← globalFrameTableHigh, CANCELBR[$, 0F],	c1;
		rE ← globalFrameTableLow,			c2;
		rE ← rE LRot8,					c3;

		Map ← [rErh, rE],				c1;
		Q ← 0FF,					c2;
		rErh ← rE ← MD,					c3;

		MAR ← [rErh, Q + 0],				c1;
		Noop,						c2;
		rB ← MD,					c3;

		Noop,						c1;
		rB ← rB, ZeroBr,				c2;
		BRANCH[setSwapConstants, guessSize],		c3;

guessSize:
		rB ← germPageCount,				c1;
		Noop,						c2;
		Noop,						c3;

setSwapConstants:
		{rB ← germPageCount,} CANCELBR[$, 0F],		c1;
		transferCount ← rB,	 			c2;
		rE ← topPageHighByte,				c3;

		rE ← rE LRot8,					c1;
		rE ← rE or topPageLowByte,			c2;
		topPage ← rE,					c3;

{
	Bermuda can break here to modify topPage or transferCount.
}

constantsOK:
		rC ← transferCount, {number of pages in germ}	c1;
		rErh ← mapRealAddrHigh,				c2;
		rBrh ← mapRealAddrHigh,				c3;

{
	Swap the gft (at .map 200) back where it belongs (.map 0)
}

swapGft:
		rB ← germPageHigh,				c1;
		rB ← rB LRot8,					c2;
		rB ← rB or germPageLow, {vp of 4.0 germ}	c3;

		rE ← globalFrameTableHigh,			c1;
		rE ← rE LRot8,					c2;
		rE ← rE or globalFrameTableLow,			c3;

		Noop,						c1;
		L0 ← L0.gftExch,				c2;
		CALL[memSwap],					c3;

		rE ← cedarGermPageHigh,				c1, RtnBLT[L0.gftExch];
		rE ← rE LRot8,					c2;
		rE ← rE or cedarGermPageLow, {vp of 3.0 germ}	c3;

{
	Swap map entries at .map 0 (Pilot germ location) with those vacant entries at .map 3E02 (Cedar germ location).
}

looper:
		Noop,						c1;
		L0 ← L0.germExch,				c2;
		CALL[memSwap],					c3;

		rB ← rB + 1,					c1, RtnBLT[L0.germExch];
		rC ← rC - 1, ZeroBr,				c2;
		rE ← rE + 1, BRANCH[looper, swipe],		c3;

{
	Now swap the map entries for the last physical memory pages *present* in vm
	with those at .map 0 to fill in the hole in vm.
}

swipe:
		rB ← germPageHigh,				c1;
		rB ← rB LRot8,					c2;
		rB ← rB or germPageLow, {vp of 4.0 germ}	c3;

		rC ← transferCount, {number of pages in germ}	c1;
		rE ← topPage,					c2;
		rE ← rE - rC, {vp of real memory block}		c3;

looper2:
		Noop,						c1; 
		L0 ← L0.vswap,					c2;
		CALL[memSwap],					c3;

		rB ← rB + 1,					c1, RtnBLT[L0.vswap];
		rC ← rC - 1, ZeroBr,				c2;
		rE ← rE + 1, BRANCH[looper2, setBootRequest],	c3;

setBootRequest:
		rBrh ← cedarGermPageHigh,			c1;
		rB ← cedarGermPageLow,				c2;
		rB ← rB LRot8,					c3;

		Map ← [rBrh, rB],				c1;
		Q ← device,					c2;
		rErh ← rE ← MD,					c3;

		MAR ← [rErh, Q + 0],				c1;
		MDR ← 5,					c2;
		Q ← bootfile,					c3;

		acR ← 0A,					c1;
		acR ← acR LRot8,				c2;
		acR ← acR or 83,				c3;

		MAR ← [rErh, Q + 0],				c1;
		MDR ← acR {A83}, {BasicCedarDLion23.pb}		c2;
		GOTO[Germ],					c3;


{
	Swaps two locations in memory, takes addresses in $rE and $rB, clobbers acR and rD.
}

memSwap:
		MAR ← [rErh, rE+0],				c1;
		Noop,						c2;
		acR ← MD,					c3;

		MAR ← [rBrh, rB+0],				c1;
		Noop,						c2;
		rD ← MD,					c3;

		MAR ← [rErh, rE+0],				c1;
		MDR ← rD,					c2;
		Noop,						c3;

		MAR ← [rBrh, rB+0],				c1;
		MDR ← acR, pRet0,				c2;
		RET[subrRet],					c3;




Germ:	TOS ← 3E, rhMDS ← 3E, CANCELBR[SetMDS,0F],		c1, at[0, 2, Germ];
Go:	TOS ← 2, rhMDS ← 2, CANCELBR[SetMDS,0F],		c1, at[1, 2, Germ];
SetMDS:	UvMDS ← TOS,						c2;
	Noop,							c3;

	uXTS ← stackP ← 0,					c1;
	UvG ← 0,						c2;
	UBrkByte ← 0,						c3;

	T ← 2,							c1;
	T {200} ← T LRot8,					c2;
	u200 {200} ← T, {uAVAddr = u200}			c3;

	T {240} ← T + 40,					c1;
	uSDAddr {240} ← T,					c2;
	Noop,							c3;

	T {1FF} ← LShift1 0FF, SE ← 1,				c1;
	T {3FF} ← LShift1 T, SE ← 1,				c2;
	T {7FF} ← T LShift1, SE ← 1,				c3;

	u7FF {7FF} ← T, T {FFF} ← T LShift1, SE ← 1,		c1;
	T {1FFF} ← T LShift1, SE ← 1,				c2;
	u1FFF {1FFF} ← T, T {3FFF} ← T LShift1, SE ← 1,		c3;

	u3FFF {3FFF} ← T,					c1;
	T {8000} ← RShift1 0, SE ← 1,				c2;
	u8000 {8000} ← T,					c3;

	T ← 0F,							c1;
	T {0F00} ← T LRot8,					c2;
	T {0FFC} ← T or 0FC,					c3;

	uPMask {0FFC} ← T,					c1;
	uPMask2 {0FFC} ← T,					c2;
	Noop,							c3;

	T ← 7,							c1;
	T {7000} ← T LRot12,					c2;
	uPPMask {7000} ← T,					c3;

	uPCCross ← 0,						c1;
	uPCValid ← 0,						c2;
	PC ← 1,							c3;

	uWDC ← PC, ClrIntErr,					c1;
	uWP ← 0,						c2;
	uStickyReg ← 0,						c3;

{ initialize uPSB so we can debug before we start ProcessImpl }

	T ← 10,							c1;
	uPSB ← T,						c2;
	Noop,							c3;

	Bank ← MSBank1,						c1;
	GOTOABS[BxMP799],					c2;
	GOTOABS[B1MP799],					c3, at[BxMP799];