IMPORTS
Basics, BasicTime, Commander, CommandTool, IO, PrincOpsUtils, Rope, VM,
MDGlobalVars, MDOps, MDUtils
StartMicroD:
ENTRY Commander.CommandProc = {
ENABLE UNWIND => NULL;
wDir: ROPE ← CommandTool.CurrentWorkingDirectory[];
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd];
cmdLine: ROPE = Rope.Concat["MicroD", cmd.commandLine];
ok: BOOL;
startTime: BasicTime.GMT = BasicTime.Now[];
nIMWords: INT ← IMsize* SIZE[IMRecord];
nIFUMWords: INT = IFUMsize* SIZE[IFUMRecord];
nIMWords: INT ← SIZE[IMRecord];
nIMWords ← nIMWords * IMsize;
[srcFileList, ok] ← MDOps.InitMicroDVars[cmdLine, wDir, argv];
IF ~ok THEN RETURN;
allocate space for data structures
IF ifumArrayHead =
NIL
THEN
TRUSTED {
buf:
LONG
POINTER ←
VM.AddressForPageNumber[VM.SimpleAllocate[VM.PagesForWords[nIFUMWords]].page];
ifumArrayHead ← LOOPHOLE[buf];
buf ← VM.AddressForPageNumber[VM.SimpleAllocate[VM.PagesForWords[nIMWords]].page];
imArrayHead ← LOOPHOLE[buf];
buf ←
VM.AddressForPageNumber[VM.SimpleAllocate[VM.PagesForWords[ALUFMsize]].page];
alufmArrayHead ← LOOPHOLE[buf];
buf ← VM.AddressForPageNumber[VM.SimpleAllocate[VM.PagesForWords[RMsize]].page];
rmArrayHead ← LOOPHOLE[buf];
};
now to initialize
imLocked ← ALL[FALSE];
rmBits ← ALL[FALSE];
alufmBits ← ALL[FALSE];
ifumBits ← ALL[FALSE];
BEGIN
ENABLE
ABORTED => {
MDOps.Report[infoOnly, "\n* * * Aborted\n"];
IF outFile.strm # NIL THEN outFile.strm.Close[ ! IO.Error => CONTINUE];
outFile.strm ← NIL;
IF listingFile.strm # NIL THEN listingFile.strm.Close[ ! IO.Error => CONTINUE];
listingFile.strm ← NIL;
};
TRUSTED {
ifumPtr: MDDefs.IFUMRecordPtr ← ifumArrayHead;
PrincOpsUtils.LongZero[ifumArrayHead, nIFUMWords];
PrincOpsUtils.LongZero[imArrayHead, nIMWords];
PrincOpsUtils.LongZero[alufmArrayHead, ALUFMsize];
PrincOpsUtils.LongZero[rmArrayHead, RMsize];
FOR i: IFUMIndex
IN [0..IFUMsize)
DO
MDUtils.IFUMPtr[i].ifumWord0.ifad ← WNull;
ENDLOOP;
};
IF ~MDOps.LoadBinaryFiles[srcFileList]
-- this closes any open source files
THEN { Finish[startTime]; RETURN};
IF ~MDOps.InitialScan[]
-- Mark IFU entries, check common errors
THEN { Finish[startTime]; RETURN};
IF ~MDOps.SetupLinks[]
-- Setup branch linkages
THEN { Finish[startTime]; RETURN};
IF ~MDOps.BuildALists[]
-- Form allocation lists
THEN { Finish[startTime]; RETURN};
IF ~MDOps.DoAssignments[] THEN { Finish[startTime]; RETURN};
IF fatalErrors
THEN {
-- Still want storage map
MDOps.ListIMUsed[listingFile];
IF mapFile # NIL THEN MDOps.DoMapIM[mapFile];
Finish[startTime];
RETURN
};
IF ~DoCheckPass[] THEN { Finish[startTime]; RETURN};
IF ~MDOps.FixupJCN[] THEN { Finish[startTime]; RETURN};
MDOps.DumpImage[outFile];
MDOps.DumpSyms[outFile];
MDOps.PutEndMarker[outFile];
outFile.strm.Close[];
outFile.strm ← NIL;
MDOps.ListIM[listingFile, srcFileList];
MDOps.ListIMUsed[listingFile];
MDOps.ListNonIM[listingFile, listingLevel];
IF listSymbols
THEN {
IF listingLevel < 0 THEN MDOps.ListRM[listingFile];
MDOps.ListOtherSyms[listingFile];
};
IF absFile # NIL THEN MDOps.DoListAbs[absFile];
IF mapFile # NIL THEN MDOps.DoMapIM[mapFile];
IF occupiedFile # NIL THEN MDOps.DoMapOccupied[occupiedFile];
IF chartFile # NIL THEN MDOps.DoMapChart[chartFile];
IF regsFile # NIL THEN MDOps.DoMapRM[regsFile];
Finish[startTime];
listingFile.strm.Close[];
listingFile.strm ← NIL;
END;
};
Finish:
PROC[startTime: BasicTime.
GMT] = {
now: BasicTime.GMT = BasicTime.Now[];
secs: INT = BasicTime.Period[startTime, now];
MDOps.Report[infoOnly, "\nFinished at %g, (%g seconds)\n", IO.time[now], IO.int[secs]];
};
DoCheckPass:
PROC
RETURNS[ok:
BOOL] =
TRUSTED {
Check all addressability constraints
we checked for duplicate assignment as we went along
OPEN Basics;
ok ← TRUE;
the following loop is equivalent to bcpl's reloadIM - NOT TRUE!!!
FOR i:
CARDINAL
IN [0..nInstructions)
DO
imPtr: IMRecordPtr = MDUtils.IMPtr[i];
imPtr.wx0.W0Addr ← imPtr.word0.W0Addr;
ENDLOOP;
MDOps.Report[infoOnly, "Checking assignment...\n"];
FOR i:
CARDINAL
IN [0..nInstructions)
DO
imPtr: IMRecordPtr = MDUtils.IMPtr[i];
a0: CARDINAL = imPtr.wx0.W0Addr;
i1: CARDINAL = imPtr.wx1.W1AddrAndGroupLink;
a1: CARDINAL;
ip1: IMRecordPtr;
a1Bit: WORD;
IF (imPtr.wx0.globalAndIFUSeq # 0)
AND
(MDUtils.CardAnd[a0, globalZero] # 0) THEN {
ok ← FALSE;
MDOps.Report[infoOnly, "******%bb....bad assignment for global\n", IO.card[i]];
};
IF i1 = WExt THEN LOOP;
ip1 ← MDUtils.IMPtr[i1];
a1 ← ip1.wx0.W0Addr;
a1Bit ← BITSHIFT[100000B, -BITAND[LOOPHOLE[a1], 17B]]; -- oneBits!(a1&17B)
IF (imPtr.wx2.iscond # 0)
AND (imPtr.wx1.returns = 0)
THEN {
i2: CARDINAL = imPtr.wx2.W2AddrAndbLink;
a2: CARDINAL = MDUtils.IMPtr[i2].wx0.W0Addr;
IF IsOdd[a1]
OR (a2 # a1+1)
OR
( (imPtr.wx1.jbc # 0) AND
( (
BITAND[a1Bit, jbctMask] = 0)
OR
(BITAND[a1, PageMask] # BITAND[a0, PageMask])) ) THEN {
ok ← FALSE;
MDOps.Report[infoOnly,
"******%bb (%bb) -> %bb (%bb), %bb....bad assignment for conditional\n",
IO.card[i], IO.card[a0], IO.card[i1], IO.card[a1] ];
MDOps.Report[infoOnly,
" %bb (%bb)....bad assignment for conditional\n", IO.card[i2], IO.card[a2] ];
};
};
IF ((imPtr.wx2.goes # 0)
AND (
BITAND[a1Bit, goedtoMask] = 0))
OR
(( imPtr.wx1.calls # 0)
AND (imPtr.wx1.returns = 0)
AND
(BITAND[a1Bit, calledMask] = 0) ) THEN {
ok ← FALSE;
MDOps.Report[infoOnly,
"******%bb (%bb) -> %bb (%bb)....bad assignment for GOTO or CALL\n",
IO.card[i], IO.card[a0], IO.card[i1], IO.card[a1] ];
};
the following means no constraint on successor
IF imPtr.wx1.usesFN = 0 OR imPtr.wx1.returns # 0 THEN LOOP;
IF (MDUtils.CardAnd[a1, PageMask] # MDUtils.CardAnd[a0, PageMask])
AND
(MDUtils.CardAnd[a1, globalZero] # 0) THEN {
ok ← FALSE;
MDOps.Report[infoOnly, "*******"];
MDUtils.PutAData[i];
MDOps.Report[infoOnly, " -> "];
MDUtils.PutAData[i1];
MDOps.Report[infoOnly, "....bad assignment -- can't get there\n"];
};
ENDLOOP;
};