:TITLE[LoadRAM];
%
Edit by Fiala 5 February 1982: Bummed 10b mi and improved speed 15 percent;
use yBuf-yBuf1 instead of xBuf-xBuf3 and xfTemp to overwrite less of
Initialize’s device table during CSLKeyboard overlay load; make
ExchStkP and SetStkP available as subroutines; fix bugs that caused
FFault to be left even when starting the code and odd when
restarting the emulator, irrespective of whether LoadRAM is called
by Mesa or Alto.
Edit by Johnsson, January 28, 1980 12:14 PM

NOTES:
1) The exit conditional which allows either a specified starting address,
a jump to the Alto emulator, or a jump to the Mesa emulator is unnecessary
and non-useful. Instead, simply eliminate the last 7 locations of RamLoaded
and IMReserve 2 locations there which the overlay can overwrite with
a LoadPage and a GoTo. Current uses all specify the starting address anyway
(?), and it is painful to have to put these octal numbers in .MLF files; it
would be far easier to assemble code that jumps to the starting addresses
into the overlays directly.
%
%Verify consistency of parameters among all implementations; only Initial
should contain this file directly--other programs should use LoadRAMOccupied.
GlobalDefs will normally define all entry locations.
%
IDF[LRJStart,IFE[LRJStart,300,,ER[Bad.value.for.LRJStart]],
Set[LRJStart,300]];
IDF[LRJContinue,IFE[LRJContinue,301,,ER[Bad.value.for.LRJContinue]]];

IDF[LRJGo,IFE[LRJGo,302,,ER[Bad.value.for.LRJGo]],Set[LRJGo,302]];
IDF[ExchStkPLoc,IFE[ExchStkPLoc,330,,ER[Bad.value.for.ExchStkPLoc]],
Set[ExchStkPLoc,330]];
IDF[SetStkPLoc,IFE[SetStkPLoc,331,,ER[Bad.value.for.SetStkPLoc]],
Set[SetStkPLoc,331]];

%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 1cs bits 0-15d
word 2bits 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.

If the starting address includes a task number .ne. 0, that task will be
given control by a Call, so that when that task blocks, LoadRAM will continue
and resume the emulator correctly. If the starting address is an emulator
program, however, it can return to LoadRAM to resume the emulator only if
RTemp and RTemp1 are still valid because StkP will be again restored from
RTemp and RTemp1 is checked to decide whether to resume the Alto or Mesa
emulators.

Entry conditions (at LRJBegin):
FFaulteven to crash on MC1 or stack errors which are illegal
during execution of LoadRAM.
LP/LPhibase register pointing at array in MakeLoaderFile form
xfTemp1even (must be 20*n) for inline refresh without tasking
odd for normal tasking
RTemp1even iff starting address is to be believed
RTemp1.ls. 0 to leave FFault even and resume Alto;
.ge. 0 to leave FFault odd and resume Mesa.

Reentry conditions to load next overlay (also at LRJBegin):
LP,,LPhi untouched
xfTemp1, RTemp1, FFault as above

Smashes yBuf, yBuf1, and yBuf2 (= RTemp).

For compatibility with old LoadRAM, alternate entries at LRJEnter are also
provided. At LRJEnter LP/LPhi points at array-1 rather than array; at
LRJEnter+1 (the reentry location), LP + xfTemp points at the next mi.
Until the overlay skipping code in Pilot, AMesa, etc. is fixed to count
in LP/LPhi rather than in xfTemp, this compatibility vestige will be needed.

Timing ~ 45 cycles/mi + [38 cycles if overlay started else 41 cycles]
+ 4 cycles/mi for inline refresh. Fastest possible loop would be about
26 cycles/mi with lots more code and RM registers.
%

*To avoid "APCTask&APC← illegal with return" error message...
Macro[LRJAPCTask&APC←,FF1@[7] FF2@[10] A←];

%These mi are for compatibility with old LoadRAM, which has a reentry
address at LRJStart+1 with the first word at LP+1 and the next word at
xfTemp+LP--this new LoadRAM does not use xfTemp and has the start and
continue addresses both at LRJBegin; as soon as a microcode system has been
reassembled with both the continue and starting addresses equal to LRJGo and
has had all dependencies on xfTemp removed, it need not IMReserve these
locations.
%
LRJEnter:
T ← xfTemp ← 1C, Skip, At[LRJStart];
T ← xfTemp, At[LRJContinue];
LP ← (LP) + T, At[LRJStart,36];
xfTemp ← 0C, Skip[Carry’], At[LRJStart,37];
LPhi ← (LPhi) + (400C) + 1, At[LRJStart,35];
Nop, At[LRJStart,34];

*This is the new starting address
LRJBegin:
PFetch1[LP,yBuf,0], At[LRJGo];
PFetch1[LP,yBuf1,1], At[LRJGo,1];
PFetch1[LP,yBuf2,2], At[LRJGo,2];
LP ← (LP) + (3C), Call[LRJ1], At[LRJGo,3];
*LRJ1 returns here if tasking permitted, else jumps here.
LRJ2:
LU ← yBuf1, UseCTask, Call[LRJadr], At[LRJGo,4];
*Setup for WriteCS0&2 with T ← data bits 32:35; ALUA ← data bits 0:15;
*and APCTask&APC ← address.
WriteCS0&2, At[LRJGo,5];
LU ← yBuf2, UseCTask, Call[LRJadr], At[LRJGo,6];
*Setup for WriteCS1 with ALUA ← data bits 16:31; APCTask&APC ← address.
WriteCS1, GoTo[LRJBegin], At[LRJGo,7];

LRJ1:
T ← (yBuf) + (20C), Skip[Carry’], At[LRJGo,10];
LPhi ← (LPhi) + (400C) + 1, GoTo[.-1], At[LRJGo,13];
yBuf ← RSh[yBuf,4], GoTo[RamLoaded,Carry], At[LRJGo,12];
xfTemp1 ← (xfTemp1) + (20C), Skip[R Odd], At[LRJGo,14];
Refresh[xfTemp1], GoTo[LRJ2], At[LRJGo,20];
*It is ok to do APCTask&APC← with Return here because, if an io task runs
*next, it is not permitted to task (i.e., to have a Return) in its 1st mi;
*the emulator needs the APCTask&APC← for the calls here from LRJ2 and LRJ2+2.
*Other emulator routes to this mi are unaffected.
LRJadr:
LU ← LRJAPCTask&APC ← yBuf, Return, At[LRJGo,21];

RamLoaded:
RTemp ← IP[FFault]C, Call[ExchStkP], At[LRJGo,15];
RTemp1, Skip[R<0], At[LRJGo,16];
*Setting FFault odd causes MC1 and Stack errors to be handled by notifying
*the emulator rather than by crashing--required for Mesa, bad idea for Alto.
Stack ← (Stack) or (1C), At[LRJGo,22];
LU ← RTemp1, Skip[R Odd], At[LRJGo,23];*Odd if no jump
*Note that any task can be started.
LU ← APCTask&APC ← yBuf1, Call[SetStkP], At[LRJGo,24];
*Some started overlays may return here (NOTE that IP[RTemp] .eq. IP[yBuf2]).
RTemp1, GoTo[.+3,R>=0], At[LRJGo,25];
T ← PCB, LoadPageExternal[nePage], At[LRJGo,27];
StkP ← RTemp, GoToExternal[JmpFinLoc], At[LRJGo,17];
LoadPageExternal[opPage3], At[LRJGo,26];
StkP ← RTemp, GoToExternal[P7TailLoc], At[LRJGo,11];

*Useful subroutines
ExchStkP:
T ← (SStkP&NStkP) xor (377C), At[ExchStkPLoc];
SetStkP:
StkP ← RTemp, RTemp ← T, NoRegILockOK, Return, At[SetStkPLoc];

:END[LoadRam];