{
 File name:  GermSwap.mc
 Description: Code we can drive from Bermuda to move the germ!
}


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

Set[MapRealAddrHigh, 4];
Set[MapRealAddrLow, 0];

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

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

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

Set[L0.vswap,		0E];
Set[L0.germExch,	0F];

{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	Well, We've got a problem here.
	
	PrincOps 3.0 expects the germ at .mv [3E, 0200] and
	PrincOps 4.0 expects the germ at .mv [00, 0100].
	
	transferCount contains the # of pages we have to move
	and we have to move them from Map[0001] to Map[3E02]
	
	CoreInitial sets up map and leaves next available page (virtual) 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 Burdock),
	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 [00, 0100],
	
	So...
	
	So we do an even cuter swap
	put the germ where it belongs: [01, 3E02] <==> [01, 0001]
	move some pages back under .vm 0100 to be *nice*
	[01, (topPage-1)-transferCount] <==> [01, 0001]
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
}

mapGerm:	rB ← germPageHigh  				,c1;
		rB ← rB LRot8	 				,c2;
		rB ← rB or germPageLow				,c3; {Map entry for 4.0 germ}
		
		rE ← cedarGermPageHigh				,c1;
		rE ← rE LRot8					,c2;
		rE ← rE or cedarGermPageLow			,c3; {Map entry for 3.0 germ}
		
		rC ← transferCount				,c1; {number pages in germ}
		rErh ← MapRealAddrHigh {1},			c2;
		rBrh ← MapRealAddrHigh {1},			c3;
		
looper:		{Noop}						,c1;
		L0 ← L0.germExch				,c2;
		CALL[memSwap]					,c3;
		
germExch:	rB ← rB + 1					,c1, RtnBLT[L0.germExch]; {make pages vacant}
		rC ← rC - 1, ZeroBr				,c2;
		rE ← rE + 1, BRANCH[looper, swipe]		,c3;
{
	Now move a swatch of physical memory *present* in top vm
	to sit under where .vm 0100 used to be!
}

swipe:		rB ← germPageHigh  				,c1;
		rB ← rB LRot8	 				,c2;
		rB ← rB or germPageLow				,c3; {Map entry for 4.0 germ}
		
		rC ← transferCount				,c1; {number pages in germ}
		rE ← topPage					,c2;
		rE ← rE - rC					,c3; {Map entry for 3.0 germ}
		
looper2:	Noop						,c1; 
		L0 ← L0.vswap					,c2;
		CALL[memSwap]					,c3;
		
vswap:		rB ← rB + 1					,c1, RtnBLT[L0.vswap]; {make pages vacant}
		rC ← rC - 1, ZeroBr				,c2;
		rE ← rE + 1, BRANCH[looper2, vswapdone]		,c3;

vswapdone:	Noop						,c1;

{
	swaps two locations in memory, takes address in rE and rB, clobbers acR & rD
}

memSwap2:	Noop						,c2;
memSwap3:	Noop						,c3;

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

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


{the end...}