:TITLE[LoadRam];

%Edit by Fiala 21 April 1981: Replace FFaultAdd by IP[FFault]C.
Edit by Fiala, 28 April 1980
Edit by Johnsson, January 28, 1980  12:14 PM

This code will load control store with instructions taken 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 write of xfTemp 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[7], 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];