{File name: CoreInitial11.mc
Description: 2MB Purcell Core of the initial microcode booting sequence,
Last Edited: Lichtenberg 19-Jul-84 0:21:27 4mb mem stuff for Mesa 11
Last Edited: Purcell 2-Jul-84 2:38:37 Mesa 11 upgrades to 27-Sep-83
Last Edited: Purcell 2-Mar-84 5:16:02 remove Bank ← 4
Last Edited: Purcell 15-Feb-84 1:29:59 recognize 4mb
Last Edited: Purcell February 6, 1984 12:29 PM MCtl ← 8002h or xx
Last Edited: Purcell January 19, 1984 7:25 PM Mesa ignore xtra mem
Last Edited: Purcell January 16, 1984 6:35 PM test for 4MB
Last Edited: Purcell January 4, 1984 6:46 PM Bank ← 4{21 bit real mem}
Last Edited: Purcell December 30, 1983 11:17 AM MCtl ← 2.
Last Edited: Purcell December 29, 1983 5:00 PM 3-8MB mem.
Last Edited: Purcell December 27, 1983 9:14 PM 2MB mem.
Last Edited: Neely, April 2, 1982 6:28 PM @ TridentInit elim use of U0400.
Last Edited: Neely, December 11, 1981 9:59 AM Eliminated mapZap subr.
Last Edited: Neely, November 13, 1981 3:47 PM Added Trident Switch.
Last Edited: Jarvis, March 21, 1981 8:39 AM
Created: Jarvis, November 12, 1980}

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

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

RegDef[IOPageLow,U,4];

{Set[realBankCnt, 0C];{1.5}
Set[realBankCnt, 10];{2.0}
Set[realBankCnt, 0A0];
Set[realBankCnt, 08F];
}
Set[realBankCnt, 090];

Set[realBankCntM1, Sub[realBankCnt, 1]];
SetTask[0], StartAddress[go];

go:
{MCtl ←} rB{← 8002h} ← RRot1 5, CANCELBR[$, 0F],c1;
IOPCtl← 0,c2;
IfGreater[Config,1,SkipTo[TridentInit],];

KCtl← 0,c3; {SAx000}
SkipTo[NoTridentInit];

TridentInit!
RCnt ← 0F,c3; {Trident}
KCtl ← RCnt LRot12,c1; {Trident}
acR ← 4,c2; {Trident}
KCmd ← acR LRot8,c3; {Trident}

NoTridentInit!

DCtl← 3,c1; {display black, enable task}
PCtl← 0,c2;
EICtl← 0,c3;
EOCtl← 0,c1;
acR← 0,c2;
acR← acR LRot8,c3;
IOPageLow← acR,c1;
MCtl{← 8002h} ← rB, rB ← 4{21 bit real mem},c2;
Noop{Bank ← rB}, {GOTO[mapInit],}c3;

{*}
acR← uDiagnostic,c1;
{*}
[]← acR{uDiagnostic} - 1, ZeroBr,c2;
Q ← 55{Mesa}, BRANCH[qMBoot, qLBoot],c3;

qLBoot:
[]← Q xor uLispBootMsg, ZeroBr,c1;
Noop, BRANCH[rLBoot, rMBoot],c2;
rMBoot:
uDiagnostic← 0, GOTO[qMBoot],c3;
rLBoot:
Noop,c3;

qMBoot:
rB ← 0AA{Lisp},c1;
uLispBootMsg ← rB,c2;
Noop, 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;

trapIt:
Noop, GOTO[trapIt],c*;

{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;
}
rErh ← IOPageHigh,c2;

{make sure the display is off when the germ starts}
DPYOff:
acR← RShift1 0, SE← 1,c3; {acR← 8000}
rE← uIOPage,c1; {IOPage real address}
rB← 0,c2;
rBrh← 0,c3;
MAR← [rErh, IOPage.DSCB.syncCmd+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{C}, {start in bank 90{B}}c1;
rB{0}← 0,c2; {address within bank}
passTraps← acR xor ~acR,c3; {catch faults}
acR← realBankCnt,{start in bank 90{0F}{B}}c1;
acR← acR LRot8, GOTO[mark1],c2; {page counter}

{mark the first word of each page with its page number}
markPages:
MAR← [rBrh, rB+0],c1;
MDR← acR, ZeroBr,c2;
mark1:
acR← acR-1, {NegBr,} BRANCH[$, mapBuild1],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;
mapBuild1:
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;

{Mesa 10:
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 pa
ge number in the first location}
mapLoop2:
Noop,c2;
mapLoop:
Noop,c3;
mapLoop1:
MAR← [rBrh, rB+0], CANCELBR[$,1],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;
rB← rB+rC, CarryBr,c2;
Q← rBrh, BRANCH[$, nextBank],c3;
Noop, GOTO[mapLoop2],c1;

nextBank:
rC← Q+1, PgCarryBr, c1;
rBrh← rC LRot0, BRANCH[$, clearMem3],c2;
Noop,c3;

Q← uDiagnostic,c1;
[]← Q{uDiagnostic} - 1, ZeroBr{uD=1},c2;
[]← rC xor 0C, ZeroBr, BRANCH[$, mapLoop1],c3;
Noop, BRANCH[mapLoop2, clearMem2],c1;
end Mesa 10}
{Mesa 11:}
{Set up the rE pair with the real address of the virtual memory map and the rB pair with the real address of the first location to be mapped. acR must contain the page number of the first real page to be mapped.}

rErh ← MapRealAddrHigh,c1, at[0A, 10, subrRet];
rE ← MapRealAddrLow,c2;
rBrh ← rB ← FirstRealPageToMapHigh, c3;

acR ← rB LRot8, {construct page number in acR}c1;
rC ← FirstRealPageToMap, c2;
rB ← rC LRot8,c3;

Q ← uDiagnostic, c1;
[] ← Q - 1, ZeroBr, {uD=1/Lisp} c2;
rD ← 0C{smallMem}, BRANCH[Smallmem,Bigmem], c3;

Smallmem:acR ← acR or rC,
c1;
GOTO[mapLoop3],c2;

Bigmem: acR ← acR or rC, c1;
rD ← realBankCnt,GOTO[mapLoop3], c2;

{Check if the page has its own page number in the first location of the page.}
mapLoop3:
Noop,c3;

mapLoop1:
MAR← [rBrh, rB+0],c1;
Noop,c2;
rC ← MD, {double bit error possible here}c3;

[] ← rC xor acR, ZeroBr,c1;
rC ← IOPageHigh, BRANCH[nextReal3, $],c2;

{Check if this is the page number of the IOPage. If so, then do not map this real page yet. Go on to the next real page.}

rC ← rC LRot8,c3;

rC ← rC or IOPage,c1;
[] ← rC xor acR, ZeroBr,c2;
rC ← IOPageVirtual, BRANCH[NotIOPageReal, IsIOPageReal],c3;

IsIOPageReal:
Noop,c1;
GOTO[nextReal3],c2;

{Check if this is the virtual map entry for the IOPage. If so, map the IOPage to this map entry. Do not increment the real page number.}

NotIOPageReal:
[] ← rC xor rE, NZeroBr,c1;
Noop, BRANCH[$, NotIOPageVirt],c2;

MapIOPage:
rC ← IOPage,c3;

rC ← IOPage,c1;
rC ← rC LRot8,c2;
rC ← rC or IOPageHigh,c3;

MAR← [rErh, rE + 0],c1;
MDR← rC or present,c2;
rE ← rE + 1, GOTO[mapLoop1],c3;

{Map this page in.}
NotIOPageVirt:
topPage← rB,c3;

rB← rB or rBrh,c1;
rC← rB,c2;
rB← topPage,c3;

MAR← [rErh, rE + 0],c1;
MDR← rC or present,c2;
rE ← rE + 1, GOTO[nextReal1],c3;

nextReal3:
Noop,c3;
nextReal1:
acR ← acR + 1, GOTO[IncReal],c1;
nextReal:
Noop,c1;
IncReal:
rC ← 0FF + 1,c2;
rC← rB+rC, CarryBr,c3;

rB← rBrh, BRANCH[$, nextBank],c1;
rB← rC, GOTO[mapLoop3],c2;

nextBank:
rB← rB+1,c2;
[]← rB xor rD{maxbanktocheck}, ZeroBr,c3;

rBrh← rB LRot0, BRANCH[$, clearMem2],c1;
rB← rC, GOTO[mapLoop3],c2;

{clear all mapped pages}
clearMem2:
Noop,c2;
clearMem3:
Noop,c3;
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];

{*** 32MB: The following line was moved to NewInit for big vm test}
{
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;

{******* Not used anymore
{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;