:TITLE[LoadRAM];

*Edit by Fiala, 25 November 1980
*Edit by Johnsson, January 28, 1980  12:14 PM

%This code will load control store with mi from an array of items in the form:
	word 0	(addr lsh 4) or (cs bits 32d-35d)
	word 1	cs bits 0-15d
	word 2	bits 16d-31d
The last item has addr=7777b.  In the last item, word 1 is the start address
of the code just loaded and word 2 is a checksum.  The checksum should be
checked by other software since detection of errors after loading the control
store is of marginal interest.  The code below does not check checksums.

Memory refresh may be done inline by LRJ without tasking.

Entry conditions (At[LRJStart]):
	LP,,LPhi has base pointer to array in MakeLoaderFile form
	xfTemp1 = 0 for inline refresh without tasks
		= 1 for normal tasking
	RTemp1 is even iff start address is to be believed
	RTemp1 is <0 if resume Alto emulator, >=0 if resume Mesa

To continue loading after a jump (overlay), jump to LRJContinue.

Reentry conditions (At[LRJContinue]):
	LP,,LPhi untouched
	xfTemp untouched
	xfTemp1 untouched or as above
	RTemp1 is even iff start address is to be believed
	RTemp1 is <0 if resume Alto emulator, >=0 if resume Mesa
%
 
OnPage[LRJpage];

LRJenter:
	xfTemp ← 1C, At[LRJStart,0];
*following location is the place to restart for overlays
	T ← xfTemp, At[LRJContinue];	*wait for xfTemp write to avoid bypass problem
LRJloop:
	PFetch1[LP,xBuf2], Call[LRJIncCount], At[LRJStart,2];
	PFetch1[LP,xBuf], Call[LRJIncCount], At[LRJStart,3];
	PFetch1[LP,xBuf1], Call[LRJIncCount], At[LRJStart,4];
	LU ← (LdF[xfTemp1,14,3]) + 1, Goto[DoTask,R Odd], At[LRJStart,5];
	xfTemp1 ← (xfTemp1) + (2C), Skip[ALU#0], At[LRJStart,10];
	  Refresh[xfTemp1,0], At[LRJStart,6];
	T ← LdF[xBuf2,0,14], At[LRJStart,7];	*address
	xBuf3 ← T, At[LRJStart,13];
LRJloopx:
	LU ← (xBuf3) xnor (170000C), At[LRJStart,14]; *look for m-i address = 7777
	T ← xBuf2, Goto[RamLoaded,ALU=0], At[LRJStart,15];
	LU ← xBuf, At[LRJStart,17];
	APCTask&APC ← xBuf3, At[LRJStart,20];
	WriteCS0&2, At[LRJStart,21];
	LU ← xBuf1, At[LRJStart,22];
	APCTask&APC ← xBuf3, At[LRJStart,23];
	WriteCS1, At[LRJStart,24];
	T ← xfTemp, Goto[LRJloop], At[LRJStart,25];

LRJIncCount:
	T ← xfTemp ← (xfTemp) + 1, UseCTask, Goto[LRJRet], At[LRJStart,26];

RamLoaded:
	RTemp1, Skip[R Odd], At[LRJStart,16];	*odd if no jump
	  APCTask&APC ← xBuf1, Call[LRJRet], At[LRJStart,30];	*set TPC for return
	T ← (SStkP&NStkP) xor (377C), At[LRJStart,31];
	RTemp ← IP[FFault]C, At[LRJStart, 27];
	StkP ← RTemp, RTemp ← T, NoRegILockOK, At[LRJStart,32];
	Stack ← (Stack) or (1C), At[LRJStart,33];
	RTemp1, Goto[.+3,R>=0], At[LRJStart,37];
	  T ← PCB, LoadPageExternal[nePage], At[LRJStart,35];
*For LRJStart on page 0, there are no free 42b-word blocks, so we use the
*single available 40b-word block below TimerTable and two unused mi in
*TimerTable, which is why there is a gap between 37b and 70b in the
*assignments (ugh).
	  GotoExternal[JmpFinLoc], At[LRJStart,70];
	LoadPageExternal[opPage3], At[LRJStart,34];
	StkP ← RTemp, GotoExternal[P7TailLoc], At[LRJStart,71];

LRJRet:	Return, At[LRJStart,36];

DoTask:	T ← LdF[xBuf2,0,14], Call[LRJRet], At[LRJStart,11];
	xBuf3 ← T, Goto[LRJloopx], At[LRJStart,12];

:END[LoadRam];