{File name:  CoreInitial.mc
 Description: Core of the initial microcode booting sequence,
 Author: Jarvis,
 Created: November 12, 1980,
 Last Edited: bj, 25-Jul-85  1:28:42	Added realBankCnt to identify memory size}

Reserve[ProtectStart, ProtectFence], Reserve[0FE0, 0FFF];	{save room for boot kernel}

{IO page offsets}	Set[DPYCtlWord, 0EC];	{8000=> turn display off}

{
	Set[realBankCnt,  0C];	{ 0C00'h =  3072 =   6000B = 1.5MB }
	Set[realBankCnt,  10];	{ 1000'h =  4096 =  10000B = 2.0MB }
	Set[realBankCnt, 08F];	{ 8F00'h = 36608 = 107400B = ???MB }
	Set[realBankCnt, 090];	{ 9000'h = 36864 = 110000B = ???MB }
	Set[realBankCnt, 0A0];	{ A000'h = 40960 = 120000B = ???MB }
}

Set[realBankCnt,  10];	{ 1000'h =  4096 =  10000B = 2.0MB }

SetTask[0], StartAddress[go];

go:	MCtl ← 0, CANCELBR[$, 0F],	c1;
	IOPCtl ← 0,	c2;
	KCtl ← 0,	c3;
	DCtl ← 3,	c1; {display black, enable task}
	PCtl ← 0,	c2;
	EICtl ← 0,	c3;
	EOCtl ← 0,	c1;
	acR ← 40,	c2;
	acR ← acR LRot8,	c3;
	IOPageLow ← acR,	c1;
	Noop,	c2;
	GOTO[mapInit],	c3;

{map initialization goes on during this interval}

mapRet:
{clear all but the first two pages of bank 0}
	acR ← 0,	c2;
	passTraps ← acR,	c3;
	rD ← 2,	c1;
	rD ← rD LRot8,	c2;
	rDrh ← 0,	c3;

clear:	MAR ← [rDrh, rD+0],	c1;
	MDR ← acR, rD ← rD+1, ZeroBr,	c2;
	BRANCH[clear, $],	c3;

	Noop,	c1;
	acR ← 0FF+1,	c2;
	uBootStart ← acR, GOTO[OnceOnlyInit],	c3;

{OnceOnlyInit transfers control to DoneOnceOnlyInit.  DoneOnceOnlyInit lives in the device specific initial microcode.  When that finishes, control passes to exitToEmulator.}

exitToEmulator:

{swap entries for IO page and 0}
mapIO:	rE ← 0,	c1;
	rErh ← 1,	c2;
	rB ← virtualIOPage, L0 ← 0F,	c3;
	rBrh ← 1, CALL[memSwap2],	c1;

	Noop,	c1, at[0F, 10, subrRet];
	Noop,	c2;

{make sure the display is off when the germ starts}
DPYOff:	acR ← RShift1 0, SE ← 1,	c3; {acR ← 8000}
	rE ← IOPageLow,	c1; {IOPage real address}
	rB ← 0,	c2;
	rBrh ← 0,	c3;
	MAR ← [rErh, DPYCtlWord+0],	c1;
	MDR ← acR,	c2;


enableIOP:	Noop,	c3;
	MAR ← [rBrh, 0+0],	c1;
	MDR ← 0FF,	c2;
	Noop,	c3;
	MAR ← [rBrh, 0+1],	c1;
	MDR ← uBootStart, CANCELBR[$, 0],	c2;
	IOPCtl ← IOPInMode, GOTOABS[IdleLoc],	c3;

{subroutines and end matter}

{Map initialization -- Sets up map and leaves next available page in topPage.  Start looking for pages before 768K, i.e., below bank 0C.  Does not map any pages in bank 0.

Beware -- clobbers the first word of each page in bank 0 even though you don't mean it!!!!!!!!!!!!!!!!!!!!!!!!

Write page number in the first word of each page.  Go through memory top down to give lower addresses precedence

Register usage
acR	page number
rB	memory address register
rC	temporary
rD	temporary
rE	next available page}	

mapInit:	rBrh ← realBankCnt, {start in bank 0B}	c1; {0C=1.5MB, 10=2.0MB}
	rB ← 0,	c2; {address within bank}
	acR ← rB-1,	c3;
	passTraps ← acR,	c1; {catch faults}
	acR ← realBankCnt,	c2;
	acR ← acR LRot8,	c3; {page counter}
	Noop,	c1;
	GOTO[mark1],	c2;

{mark the first word of each page with its page number}
markPages:	MAR ← [rBrh, rB+0],	c1;
	MDR ← acR,	c2;
mark1:	acR ← acR-1, NegBr,	c3; {written all pages?}
	rC ← 0FF+1, BRANCH[$, mapBuild],	c1;
	rC ← rB-rC, CarryBr,	c2;
	rB ← rC, BRANCH[$, markPages],	c3;
	rB ← rBrh,	c1;
	rB ← rB-1,	c2;
	rBrh ← rB LRot0,	c3;
	rB ← rC,	c1;
	Noop,	c2;
	GOTO[markPages],	c3;

mapBuild:	Noop,	c2;
	Noop,	c3;
	rBrh ← 1,	c1;
	rC ← rCrh ← 1,	c2;
	rB ← 0,	c3;

{make all pages vacant}
	MAR ← [rBrh, rB+0],	c1;
	MDR ← vacant,	c2;
	acR ← mapPages,	c3;
	acR ← acR LRot8, L0 ← 0A,	c1;
	acR ← acR-1, CALL[BLT3],	c2;

	Noop,	c1, at[0A, 10, subrRet];
	rE ← 0, {start at virtual 0}	c2;
	rErh ← 1,	c3; {map in bank 1}
	rBrh ← 1,	c1; {so is the IO page}
	rB ← IOPageLow,	c2;
	acR ← rB LRot8,	c3; {start mapping pages . . . }
	acR ← acR+0FF+1,	c1; {IO page is in bank 1}

{page should have its own page number in the first location}
mapLoop2:	Noop,	c2;
mapLoop:	Noop,	c3;
mapLoop1:	MAR ← [rBrh, rB+0],	c1;
	Noop,	c2;
	rC ← MD, {double  error bit error possible here}	c3;
	Noop,	c1;
	[] ← rC xor acR, ZeroBr,	c2;
	acR ← acR+1, BRANCH[nextReal, $],	c3;

{map this page in}
	topPage ← rB,	c1;
	Noop,	c2;
	Noop,	c3;
	rB ← rB or rBrh,	c1; {map entry for this page}
	rC ← rB,	c2;
	rB ← topPage,	c3;
	MAR ← [rErh, rE+0],	c1;
	MDR ← rC or present,	c2;
	rE ← rE+1,	c3;
nextReal:	rC ← 0FF+1,	c1;
	rC ← rB+rC, CarryBr,	c2;
	rB ← rBrh, BRANCH[$, nextBank],	c3;
	rB ← rC, GOTO[mapLoop2],	c1;
nextBank:	rB ← rB+1,	c1;
	[] ← rB xor 0C, ZeroBr,	c2;
	rBrh ← rB LRot0, BRANCH[$, clearMem],	c3;
	rB ← rC, GOTO[mapLoop2],	c1;

{clear all mapped pages}
clearMem:	topPage ← rE,	c1; {save away}
	rE ← 0,	c2; {word offset}
	rD ← 0,	c3; {source of zero}
	passTraps ← rD, {die on double bit errors}	c1;
	Noop,	c2;
	Noop,	c3;

clearLoop:	MAR ← [rErh, rE+0],	c1; {read the map}
	rC ← 0,	c2;
	acR ← MD,	c3;

	rB ← acR and 0F,	c1;
	rBrh ← rB LRot0,	c2;
	rB ← acR and ~0FF,	c3;

{write into every word of the page}
clearPage:	MAR ← [rBrh, rC+0],	c1;
	MDR ← rD, rC ← rC+1, PgCarryBr,	c2;
	acR ← topPage, BRANCH[clearPage, $],	c3;

	rE ← rE+1,	c1;
	[] ← rE xor acR, ZeroBr,	c2; {compare to topPage}
	BRANCH[clearLoop, $],	c3;

	GOTO[mapRet],	c1;

{trap catcher, gets here with rC ← RRot1 ErrnIBnStkp}
error:	Xbus ← rC LRot0, XwdDisp,	c2, at[ErrorHandlerLoc];
	DISP2[errorType],	c3;

	GOTO[death], {control store parity error}	c1, at[0, 4, errorType];
	Xbus ← MStatus, XLDisp, GOTO[memFault],	c1, at[1, 4, errorType];
	GOTO[death], {stack error}	c1, at[2, 4, errorType];
	GOTO[death], {instruction buffer empty}	c1, at[3, 4, errorType];
death:	GOTO[death],	c*;

memFault:	BRANCH[death, $, 1],	c2; {map out of bound?}
	GOTO[nextReal],	c3; {no, double bit error}

{block transfer, takes count in acR, from in rB, and to in rC, returns first word past from block in rE}
BLT2:	Noop,	c2;
BLT3:	Noop,	c3;
BLT:	MAR ← [rBrh, rB+0],	c1;
	[] ← acR, ZeroBr,	c2;
	rE ← MD, BRANCH[$, endBLT],	c3;
	MAR ← [rCrh, rC+0],	c1;
	MDR ← rE,	c2;
	acR ← acR-1,	c3;
	rB ← rB+1,	c1;
	rC ← rC+1,	c2;
	GOTO[BLT],	c3;
endBLT:	Noop,	c1;
endBLT1:	pRet0,	c2;
endBLT2:	RET[subrRet],	c3;

{takes count in acR, virtual page number in rE, and map entry in rC.  Beware, rErh better have a 1 !!!!}
mapZap3:	Noop,	c3;
mapZap:	MAR ← [rErh, rE+0],	c1;
	MDR ← rC or present,	c2; {referenced and present}
	rC ← rC+0FF+1,	c3;
	rE ← rE+1,	c1;
	acR ← acR-1, ZeroBr,	c2;
	BRANCH[mapZap, $],	c3;
	Noop,	c1;
endMisc1:	pRet0,	c2;
endMisc2:	RET[miscRet],	c3;

{swaps two locations in memory, takes address in rE and rB, clobbers acR}
memSwap2:	Noop,	c2;
memSwap3:	Noop,	c3;
memSwap:	MAR ← [rErh, rE+0],	c1;
	Noop,	c2;
	acR ← MD,	c3;
	MAR ← [rBrh, rB+0],	c1;
	MDR ← acR,	c2;
	acR ← MD,	c3;
	MAR ← [rErh, rE+0],	c1;
	MDR ← acR, pRet0,	c2;
	RET[subrRet],	c3;