// MDscan -- mark IFU entries, compute parameters, scan for errors // last edited July 15, 1980 7:38 PM get "mddecl.d" external // defined here [ Scan // () // Statics @PageSize; @nPages; @PageMask; @WordMask @globalZero; @nGlobalPages @ifuZero; @nIfuPages; @pageIfuMax; @ifuMask @calledMask; @goedtoMask; @jbctMask @evenCall; @callerMask; @slowJump; @jbcSubpage ] external [ // MDinit Kludge // MDmain @IP @NInstructions @IFUM; @NIFUM @DMachine IgnoreOnPage Version // MDerr Err PutAddress ] static // Might as well initialize for one configuration [ PageSize = D1PageSize nPages PageMask WordMask globalZero = globalZero0 nGlobalPages ifuZero = ifuZero0 nIfuPages pageIfuMax = pageIfuMax0 ifuMask = ifuMask0 calledMask = calledMask0 goedtoMask = goedtoMask0 jbctMask = jbctMask0 evenCall = false callerMask = -1 slowJump = false jbcSubpage = false ] let Scan() be [ Err(PassMessage, "Checking for errors...") PreScan() RealScan() ] and PreScan() be [ // Compute parameters switchon DMachine into [ case 0: // D0 PageSize = D0PageSize calledMask, goedtoMask = -1, -1 evenCall = Version ls 1 callerMask = (evenCall? evenMask, -1) slowJump = Version ls 2 // other parameters not relevant endcase case 1: // Dorado model 0 jbcSubpage = true endcase case 2: // Dorado model 1 globalZero = globalZero1 ifuZero, pageIfuMax, ifuMask = ifuZero1, pageIfuMax1, ifuMask1 calledMask, goedtoMask, jbctMask = calledMask1, goedtoMask1, jbctMask1 endcase ] nPages, PageMask, WordMask = IMsize/PageSize, IMsize-PageSize, PageSize-1 nGlobalPages = (IMsize-1-globalZero)/PageSize+1 nIfuPages = (IMsize-1-ifuZero)/PageSize+1 // Miscellaneous checking and cleanup: // Remove onPage if appropriate // Remove calls if oddcall set (since call does not return) // If callerMask=-1, remove oddcall as well (i.e. RCALL=GOTO) // Remove iscond if returns set (for "conditional" IFU jumps) // Prohibit conditional and FF-busy branches to external symbols // Reset IFUE bit for IFU entry loop for i = 0 to NInstructions-1 do [ let ip = IP(i) if IgnoreOnPage then ip>>IM.onPage = 0 if DMachine eq 0 then if ip>>IM.oddcall then [ ip>>IM.calls = 0 if callerMask eq -1 then ip>>IM.oddcall = 0 ] if (ip>>IM.W1 eq WExt) % (ip>>IM.W2 eq WExt) then test ip>>IM.iscond ifso Err(PassFatal, "$P....Conditional branch to external symbol", PutAddress, i) ifnot if ip>>IM.usesFN then Err(PassFatal, "$P....Branches to external symbol, but FF is busy", PutAddress, i) if ip>>IM.returns then ip>>IM.iscond = 0 ip>>IM.IFUE = 0 ] // Indicate IFU entries let nIFUE = 0 let ifuerr(j) be Err(PassFatal, "$P....Overlapping IFU entry sequences", PutAddress, j) for k = 0 to NIFUM-1 do [ let i = (IFUM+k*lIFUM)>>IFUM.IFAD if i eq 7777b loop let ip = IP(i) test ip>>IM.IFUE eq 0 ifso [ nIFUE = nIFUE+1 let i1 = i+(IFUM+k*lIFUM)>>IFUM.NENT for j = i to i1 do [ ip = IP(j) if ip>>IM.IFUE ne 0 then ifuerr(j) if ip>>IM.IFUseq ne 0 then // *** IFUseq=global Err(PassFatal, "$P....Both IFU entry and global", PutAddress, j) ip>>IM.IFUE = 1 if j ne i then ip>>IM.IFUseq = 1 ] ] ifnot if ip>>IM.IFUseq ne 0 then ifuerr(i) ] let maxIFUE = pageIfuMax*nIfuPages if nIFUE gr maxIFUE then Err(PassFatal, "Too many IFU entries (>$D)", maxIFUE) ] and RealScan() be [ // Check constraints: // For D0, check LOADPAGE/RETURN constraints // For both D0 and Dorado, forbid branches beyond end of program for i = 0 to NInstructions-1 do [ let ip = IP(i) let i1, i2 = ip>>IM.W1, ip>>IM.W2 // Check for branch beyond end if (i1 ge NInstructions) & usesW1(ip) then unless (ip>>IM.returns ne 0) & (ip>>IM.calls eq 0) do Err(PassFatal, "$P....successor is beyond end of program", PutAddress, i) if (i2 ge NInstructions) & usesW2(ip) then test ip>>IM.iscond ifso Err(PassFatal, "$P....one successor is beyond end of program", PutAddress, i) ifnot Err(PassFatal, "$P....successor is beyond end of program", PutAddress, i) // Check local constraints (LOADPAGE) if DMachine eq 0 then [ if ip>>IM.swpage then swpcheck(i, i1) ] ] ] and swpcheck(i, i1) be [ let ip = IP(i) test ip>>IM.returns ifso Err(PassFatal, "$P....has both LOADPAGE[n] and RETURN", PutAddress, i) ifnot [ let newpage = ip>>IM.newpage let ip1 = IP(i1) unless Kludge do // *** Kludge so RETURN can be used for abs goto test slowJump ifso // LOADPAGE effect is deferred for 1 instruction test ip1>>IM.returns ifso Err(PassFatal, "$P....has RETURN with LOADPAGE[n] in predecessor $P", PutAddress, i1, PutAddress, i) ifnot [ let i2 = ip1>>IM.W1 if i2 eq WExt return let ip2 = IP(i2) if (ip2>>IM.onPage ne 0) & (ip2>>IM.W0/PageSize ne newpage) then Err(PassFatal, "$P....on page $O, conflicts with LOADPAGE[$O] at $P (reached via $P)", PutAddress, i2, ip2>>IM.W0/PageSize, ip>>IM.newpage, PutAddress, i, PutAddress, i1) ] ifnot // LOADPAGE takes effect immediately [ if i1 eq WExt return if (ip1>>IM.onPage ne 0) & (ip1>>IM.W0/PageSize ne newpage) then Err(PassFatal, "$P....on page $O, conflicts with LOADPAGE[$O] at $P", PutAddress, i1, ip1>>IM.W0/PageSize, ip>>IM.newpage, PutAddress, i1) ] ] ] and usesW1(ip) = ((ip>>IM.returns eq 0) % (ip>>IM.calls ne 0)) & (ip>>IM.W1 ne WExt) and usesW2(ip) = ((ip>>IM.iscond ne 0) % (ip>>IM.calls ne 0)) & (ip>>IM.W1 ne WExt)