<> <> <> <> DIRECTORY IO, Rope, MDDefs, MDGlobalVars, MDOps, MDUtils; MDScanImpl: CEDAR PROGRAM IMPORTS IO, MDGlobalVars, MDOps, MDUtils EXPORTS MDOps, MDUtils = BEGIN OPEN MDDefs, MDGlobalVars; -- Mark IFU entries, check common errors InitialScan: PUBLIC PROC RETURNS[ok: BOOL] = { MDOps.Report[infoOnly, " Checking for errors...\n"]; IF ~PreScan[] THEN RETURN[FALSE]; RETURN[RealScan[]]; }; PreScan: PROC RETURNS[ok: BOOL] = TRUSTED { <> <> <> <> <> <> <> nIFUE: INTEGER _ 0; FOR i: CARDINAL IN [0..nInstructions) DO imPtr: MDDefs.IMRecordPtr = MDUtils.IMPtr[i]; IF ignoreOnPage THEN imPtr.word0.onPageAndPlaced _ 0; IF imPtr.word1.W1AddrAndGroupLink = WExt OR imPtr.word2.W2AddrAndbLink = WExt THEN { IF imPtr.word2.iscond = 1 THEN { MDOps.Report[infoOnly, "%g ....Conditional branch to external symbol\n", IO.int[i] ]; RETURN[FALSE]; } ELSE IF imPtr.word1.usesFN = 1 THEN { MDOps.Report[infoOnly, "%g ....Branches to external symbol, but FF is busy\n", IO.int[i] ]; RETURN[FALSE]; }; }; IF imPtr.word1.returns = 1 THEN imPtr.word2.iscond _ 0; imPtr.word0.brkPAndIFUE _ 0; ENDLOOP; <<>> <> FOR k: CARDINAL IN [0..nIFUInstructions) DO ifumPtr: IFUMRecordPtr = MDUtils.IFUMPtr[k]; imPtr: IMRecordPtr; iAddr: CARDINAL = ifumPtr.ifumWord0.ifad; IF iAddr = 7777B THEN LOOP; imPtr _ MDUtils.IMPtr[iAddr]; IF imPtr.word0.brkPAndIFUE = 0 THEN { iAddrLast: CARDINAL; nIFUE _ nIFUE + 1; iAddrLast _ iAddr + ifumPtr.ifumWord0.nEnt; FOR j: CARDINAL IN [iAddr .. iAddrLast] DO -- checking multiple entry points imP: MDDefs.IMRecordPtr = IMPtr[j]; IF imP.word0.brkPAndIFUE = 1 THEN RETURN[IFUErr[j]]; -- return[false] IF imP.word0.globalAndIFUSeq = 1 THEN { MDOps.Report[infoOnly, "%g ....Both IFU entry and global\n", IO.int[j]]; RETURN[FALSE]; }; imP.word0.brkPAndIFUE _ 1; IF j # iAddr THEN imP.word0.globalAndIFUSeq _ 1; ENDLOOP; } ELSE IF imPtr.word0.globalAndIFUSeq = 1 THEN RETURN[IFUErr[iAddr]]; ENDLOOP; IF nIFUE > IFUMsize THEN { MDOps.Report[infoOnly, "Too many (%g) IFU entries - max is %g\n", IO.int[nIFUE], IO.int[IFUMsize]]; RETURN[FALSE]; }; <> FOR i: CARDINAL IN [0 .. nInstructions) DO imPtr: IMRecordPtr = IMPtr[i]; IF imPtr.word1.W1AddrAndGroupLink = WNext THEN imPtr.word1.W1AddrAndGroupLink _ i+1; IF imPtr.word2.W2AddrAndbLink = WNext THEN imPtr.word2.W2AddrAndbLink _ i+1; ENDLOOP; RETURN[TRUE]; }; RealScan: PROC RETURNS[ok: BOOL] = TRUSTED { <> <> FOR i: CARDINAL IN [0 .. nInstructions) DO imPtr: IMRecordPtr _ IMPtr[i]; addr1, addr2: CARDINAL; addr1 _ imPtr.word1.W1AddrAndGroupLink; IF addr1 > nInstructions AND UsesW1[imPtr] THEN IF NOT (imPtr.word1.returns # 0 AND imPtr.word1.calls = 0) THEN { MDOps.Report[infoOnly, "%g....successor (%g) is beyond end of program\n", IO.card[i], IO.card[addr1] ]; RETURN[FALSE]; }; IF (addr2 _ imPtr.word2.W2AddrAndbLink) > nInstructions AND UsesW2[imPtr] THEN { IF imPtr.word2.iscond = 1 THEN MDOps.Report[infoOnly, "%g....one successor (%g) is beyond end of program\n", IO.card[i], IO.card[addr2] ] ELSE MDOps.Report[infoOnly, "%g....successor (%g) is beyond end of program\n", IO.card[i], IO.card[addr2] ]; RETURN[FALSE]; }; ENDLOOP; RETURN[TRUE]; }; IFUErr: PROC[addr: CARDINAL] RETURNS[BOOL] = { MDOps.Report[infoOnly, "%g ....Overlapping IFU entry sequences\n", IO.card[addr]]; RETURN[FALSE]; }; IMPtr: PUBLIC PROC[offset: CARDINAL] RETURNS[IMRecordPtr] = { RETURN[LOOPHOLE[imArrayHead + offset*SIZE[IMRecord]]] }; UsesW1: PROC[imPtr: MDDefs.IMRecordPtr] RETURNS[BOOL] = TRUSTED { RETURN[ ((imPtr.word1.returns = 0) OR (imPtr.word1.calls # 0)) AND (imPtr.word1.W1AddrAndGroupLink # WExt)] }; UsesW2: PROC[imPtr: MDDefs.IMRecordPtr] RETURNS[BOOL] = TRUSTED { RETURN[ ((imPtr.word2.iscond # 0) OR (imPtr.word1.calls # 0)) AND (imPtr.word1.W1AddrAndGroupLink # WExt)] }; END.