*-----------------------------------------------------------
Title[InitMem.mc...November 23, 1982  12:56 PM...Taft];
*** Pilot-only version ***
* Memory system initialization
*-----------------------------------------------------------

%
Entry point:

	InitMap		Cold start: map and main storage initialization
			(name is an historical artifact).

After initialization, InitMap branches to the external label StartEmulator.

InitMap code assumes that CacheA, CacheD, and the map automata have already
been put into a good state (by bootstrap initialization), but
assumes nothing about the contents of the map or main storage.
It zeroes all real storage in order to clear out any lurking bad parity.
It maps virtual addresses to real storage such that all real storage
is compacted in VM (usually at the bottom), and marks all other VM vacant.
As a side-effect, it computes VirtualBanks and RealPages, for the benefit of
emulators.  If no real storage is present, it breaks at NoStorage.

This version of the code assumes 256-word pages,
but can cope with any map and main storage configuration.
%

Set[logWordsPerPage, 10];

TopLevel;
Set[XTask, IP[EMU]];

* Register usage -- bank shared with Ethernet output registers
SetRMRegion[EORegs];
*	Reserve[xx];	* Registers defined in RegisterDefs.mc
*	RVN[VirtualBanks];
*	RVN[RealPages];
Reserve[Add[And[IP[RealPages], 17], 1]];

	RVN[PgsPerMod];	* Pages per storage module
	RVN[ModMask];	* Mask of modules present
	RVN[ITemp0];	* Temporaries
	RVN[ITemp1];
	RVN[ITemp2];

	Reserve[1];	* Ensure there is at least one register left
	RVRel[ITemp17, 17];

*-----------------------------------------------------------
* Cold start initialization.
* Initially started here by "Initial" (second-stage bootstrap).
* Restarted here by Baseboard on 2-button boot.
*-----------------------------------------------------------

InitMap: At[InitMapLoc],
	Call[TasksOff];			* Do an I/O Reset

	RBase← RBase[ITemp0];
	B← FaultInfo';			* clear faults
	T← mcr.noWake;			* disable fault task wakeups
	LoadMCR[T, T];
	Call[WaitForMapBuf];

* Set TestSyndrome register to normal state (error correction on)
	MemBase← IOBR, T← A0;
	BrHi← T;
	BrLo← T, Call[FetchGetsT];	* need to be sure store will hit
	T← MD, Store← T, DBuf← tsyn.ecOn; * DBuf← data
	LoadTestSyndrome;		* TestSyn← DBuf
	Call[WaitForMapBuf];
	TaskingOn;

*-----------------------------------------------------------
* Map pre-initialization for cold start.
* Set the map one-to-one with real storage (without regard to the
* real storage configuration), in preparation for flushing the cache.
*-----------------------------------------------------------
	Call[GetMemConfig];
	ITemp1← T← A0, Call[BeginEnumerateMap];
Map1to1Loop:
	ITemp0← A0, Call[IWriteMap];	* Dirty=0, WP=0, RP = VPage mod 2↑16
	SCall[NextMapEntry];
	 ITemp1← (ITemp1)+1, Branch[Map1to1Loop];

*-----------------------------------------------------------
* Cache flush and map clear.
* Data in the cache is flushed to memory arbitrarily.
* This may result in flushing into nonexistent storage, but no matter.
*-----------------------------------------------------------
CacheFlush:
	ITemp1← T← A0, Call[BeginEnumerateMap];
CacheFlushLoop:
* Flush all munches in this page
	ITemp0← A0, Cnt← 17S;
	ITemp0← Flush← ITemp0, Carry20, Branch[., Cnt#0&-1];
* Set the map entry to vacant
	Nop;
	ITemp0← T-T-1, Call[IWriteMap];	* Dirty = 1, WP = 1, RP = 0
	SCall[NextMapEntry];
	 Branch[CacheFlushLoop];

*-----------------------------------------------------------
* Map and storage initialization.
* Map all existing real memory one-to-one into virtual memory, and zero it.
*-----------------------------------------------------------
	ITemp1← T← A0,			* Init real page #, virtual bank #
		Call[BeginEnumerateMap];

* Current module exhausted, find the next one.
FindModule:
	ModMask← (ModMask) LSH 1, Branch[MapModule, R<0];
	T← PgsPerMod, Branch[InitMemDone, ALU=0];
	ITemp1← (ITemp1)+T, Branch[FindModule]; * Skip nonexistent real pages

MapModule:
	T← (1S)-(PgsPerMod);		* Init page count in module
	ITemp2← T;

* Continue mapping virtual pages into the current module.
* ITemp1 = real page number
* ITemp2 = -(remaining pages in current module)-1
MapModuleCont:
	ITemp0← A0, Call[IWriteMap];	* Write map entry; WP and Dirty = 0
	T← 377C;
	T← ITemp0← A0, Cnt← T;		* Zero out the page
	ITemp0← (Store← ITemp0)+1, DBuf← T, Branch[., Cnt#0&-1];
	ITemp1← (ITemp1)+1,		* Increment real page number
		SCall[NextMapEntry];	* Increment virtual page number
	 ITemp2← (ITemp2)+1,		* +1 return; decrement (negative) page count
		DblBranch[MapModuleCont, FindModule, R<0];
	Nop;				* +2 return: ran out of virtual memory ??


*-----------------------------------------------------------
* Now enable fault reporting and go run the emulator!
* For now, do not enable fault reporting of Single Errors.
*-----------------------------------------------------------
InitMemDone:
	B← FaultInfo';			* Clear faults
	T← mcr.noReportSE;		* Normal MCR value
	LoadMCR[T, T];
	Call[WaitForMapBuf];
	Branch[StartEmulator];

*-----------------------------------------------------------
GetMemConfig: * Read the map and storage configuration, and set these registers:
*	VirtualBanks = size of virtual memory, in units of 64K words
*	RealPages = size of real memory, in pages
*	PgsPerMod = number of pages per module
*	ModMask = bit mask of modules present (B0=1 => module 0 present, etc.)
* Breakpoints at NoStorage if no storage modules are present.
* Clobbers T, ITemp0, ITemp1, ITemp17
*-----------------------------------------------------------
Subroutine;
	ITemp0← Link;
TopLevel;
	T← 1400C;
	T← ITemp1← T OR (112C);
	Call[SetDMuxAddress];		* Read DMux[1512] = MapIs256K
	ITemp17, Branch[MapIs256K, R<0];
	VirtualBanks← 400C;
	T← (ITemp1)-1, Call[SetDMuxAddress]; * Read DMux[1511] = MapIs64K
	ITemp17, Branch[GotMapConfig, R<0];
	VirtualBanks← 100C, Branch[GotMapConfig]; * Assume MapIs16K
MapIs256K:
	VirtualBanks← 2000C;
GotMapConfig:
	ModMask← NOT (Config');
	T← LDF[ModMask, 2, 2];		* Storage chip size = 2↑(12 + 2*T)
	T← DPF[T, 2, 11];		* ShC count ← 2*T
	RealPages← A0, ShC← T;
	ModMask← LSH[ModMask, 10];	* Left-justify the module-present bits
	ModMask← T← (ModMask) AND (170000C);
	ITemp1← T, Branch[NoStorage, ALU=0];
	PgsPerMod← 400C;		* 4K chips give 400B pages/module
	PgsPerMod← T← ShiftNoMask[PgsPerMod]; * LCY[R, R, 2*n]
	ITemp1← (ITemp1)+(ITemp1), Branch[.+2, R>=0]; * Count the modules
	RealPages← (RealPages)+T, FreezeBC;
	Link← ITemp0, Branch[.-2, ALU#0];
Subroutine;
	PD← ModMask, Return;

*-----------------------------------------------------------
* No storage modules are present.
*-----------------------------------------------------------
NoStorage:
	Branch[.], Breakpoint;

*-----------------------------------------------------------
* EnumerateMap:	Perform operation on every entry in the map
* Calling sequence:
*
*	T← <first virtual bank #, normally 0>, Call[BeginEnumerateMap];
* Loop:	<code to be executed for each entry>;
*	SCall[NextMapEntry];
*	 Branch[Loop];
*	<code reached when map is exhausted>;
*
* Enter: MemBase = BR to use for enumeration
*	VirtualBanks set up
* Exit:	BR addresses word 0 of page corresponding to map entry
*	T = 0
* Clobbers T, ITemp17
*-----------------------------------------------------------
Subroutine;

BeginEnumerateMap:
	ITemp17← A0, Branch[NextMap1];

NextMapEntry:
	T← LShift[1, logWordsPerPage]C;	* Let the memory system do the add!
	DummyRef← T, T← MD;
	ITemp17← VALo;
	T← VAHi;
NextMap1:
	BRLo← ITemp17;
	PD← (BRHi← T)-(VirtualBanks);
	T← A0, Return[ALU=0];


*-----------------------------------------------------------
IWriteMapFlags:	* Write map flags without disturbing real page
* Enter: ITemp0 = WP and Dirty bits
*	Current BR contains VA for map entry to be written
* Clobbers ITemp1, Q.
*-----------------------------------------------------------
Subroutine;
	ITemp1← A0, Q← Link;
TopLevel;
	RMap← ITemp1, Call[WaitForMapBuf]; * Read current map entry
	ITemp1← NOT (Map'), Branch[IWriteMap1];


*-----------------------------------------------------------
IWriteMap:	* Write map entry
* Enter: ITemp0 = WP and Dirty bits
*	ITemp1 = real page number
*	Current BR contains VA for map entry to be written
* Clobbers Q.
*-----------------------------------------------------------
Subroutine;
	Q← Link;
TopLevel;
IWriteMap1:
	TIOA← ITemp0, Call[WaitForMapBuf];
	Map← 0S, MapBuf← ITemp1;
	Link← Q, Branch[WaitForMapBuf];


*-----------------------------------------------------------
WaitForMapBuf:	* Wait for map operation to complete
* Clobbers nothing
*-----------------------------------------------------------
Subroutine;
	PD← T-T-1;
	PD← PRef, Branch[., ALU<0];	* MapBufBusy is sign bit
	Return;