//D1PEScan.bcpl -- machine-dependent part of PE-scan overlay // 9 May 1983 get "d1.d" manifest [ get "d1pe.d" ] manifest [ get "d1instrs.d" ] manifest [ get "d1regmem.d" ] external [ // OS DoubleAdd // MASM @OddParity; VUsc; @MADDRL // MMPRGN UpdateMPDValues // MPESCAN ReportPE // D1ACTIONS @LongOne // D1TABLES @MEMLEN; @MEMNAM // D1MEM GetMemData; @SaveT; @SaveMCR; TurnOffRefresh // D1ASM ReadDMux; GetErrs; @XctL16C; @Xct; @XctR16; @XctL16T @XctLFF; @SelectTask; @SetRSTK; LoadDAddr; LoadDMD; @D1In // D1CONFIG NoCacheAParity; log2rows // Defined here ScanForPE ] let ScanForPE(MemX,WaitP,NPETab) be [ let NPEX = NPETab!0 let AVec,AVec1,DVec = vec 1,vec 1,vec 3 AVec!0 = 0; AVec1!0 = 0 NPETab!(NPEX+1) = " in " NPETab!(NPEX+2) = MEMNAM!MemX NPETab!0 = NPEX+3 let Last = MEMLEN!(MemX+MemX+1)-1 let RowMask = (1 lshift log2rows)-1 //For CACHEA/D scans switchon MemX into [ case IMXx: NPETab!(NPEX+1) = " " NPETab!(NPEX+2) = "breakpoints" NPETab!(NPEX+4) = " in " NPETab!(NPEX+5) = "IM[0:17]" NPETab!(NPEX+7) = " in " NPETab!(NPEX+8) = "IM[20:37]" NPETab!0 = NPEX+9 for I = 0 to Last do [ AVec!1 = I //To check IM parity errors, sequence analogous to the START sequence //is used to get the addressed instruction into MIR XctL16C(LLINK,I); Xct(STARTX) switchon GetErrs() & (CIMlhPE+CIMrhPE) into [ case CIMlhPE+CIMrhPE: //Breakpoint--never wait ReportPE(NPETab,NPEX,DVec,MemX,AVec,0); loop case CIMlhPE: //PE in IM[0:17] GetMemData(IMXx,DVec,AVec) ReportPE(NPETab,NPEX+3,DVec,MemX,AVec,WaitP); loop case CIMrhPE: //PE in IM[20:37] GetMemData(IMXx,DVec,AVec) ReportPE(NPETab,NPEX+6,DVec,MemX,AVec,WaitP) case 0: loop ] ] endcase case RMx: for I = 0 to Last do [ AVec!1 = I; GetMemData(MemX,DVec,AVec) Xct(SetRSTK(RRM0,MADDRL)) if (GetErrs() & RAMPE) ne 0 then ReportPE(NPETab,NPEX,DVec,MemX,AVec,WaitP) ] endcase case STKx: for I = 0 to Last do [ AVec!1 = I; GetMemData(MemX,DVec,AVec); Xct(RSTACK) if (GetErrs() & RAMPE) ne 0 then ReportPE(NPETab,NPEX,DVec,MemX,AVec,WaitP) ] endcase case MAPx: AVec!1 = 0 AVec1 = MEMLEN+MemX+MemX while VUsc(AVec,AVec1,2) ne 0 do [ GetMemData(MemX,DVec,AVec) if (DVec!0 & #10) ne 0 do ReportPE(NPETab,NPEX,DVec,MemX,AVec,WaitP) DoubleAdd(AVec,LongOne) ] endcase case IFUMx: for I = 0 to Last do [ AVec!1 = I; GetMemData(MemX,DVec,AVec) if (DVec!1 & 70000B) ne 0 then ReportPE(NPETab,NPEX,DVec,MemX,AVec,WaitP) ] endcase case CACHEAx: if NoCacheAParity eq 0 do [ for I = 0 to Last do [ AVec!1 = I; GetMemData(MemX,DVec,AVec) if (DVec!0 & #50000) eq 0 do //Not BeingLoaded % Vacant [ XctL16T(NoWake+DisHold); Xct(MCRFT) //Address word 0 of the munch with BR 36 //Arrange for BRLO+T = DVec!1+((AVec!1 & RowMask) lshift 4) XctL16T(DVec!0); Xct(BRHIFT) XctL16T((DVec!1+((AVec!1 & RowMask) lshift 4)) rshift 1) Xct(BRLOFT) //Similar to RdCACHEA in D1MEM.BCPL, but ensure Hit. let CE = TurnOffRefresh() Xct(DUMMYFT); Xct(NOOP) LoadDAddr(#1072) //HitColVA.Par let Parity = (rv D1In) & #4000 // LoadDAddr(#1074) // let Hit = rv D1In LoadDMD(CE) // if (Hit & #4000) eq 0 do // MidasSwat("Didn't get hit in CACHEA PEscan") if OddParity(DVec!0 & #7777,DVec!1 xor Parity) do ReportPE(NPETab,NPEX,DVec,MemX,AVec,WaitP) ] ] ] endcase case CACHEDx: for I = 0 to MEMLEN!(CACHEAx+CACHEAx+1)-1 do [ AVec!1 = I; GetMemData(CACHEAx,DVec,AVec) //Only if not Vacant or beingloaded if (DVec!0 & #50000) eq 0 do [ XctL16T(NoWake+DisHold); Xct(MCRFT) //Address word 0 of the munch with BR 36 XctL16T(DVec!0); Xct(BRHIFT) XctL16T(DVec!1+((AVec!1 & RowMask) lshift 4)); Xct(BRLOFT) //Loop over words in munch for J = 0 to 17B do [ XctL16T(J); Xct(FETCHM); Xct(TFMD) Xct(RT); XctR16(RT,DVec) if (GetErrs() & MdPE) ne 0 then [ AVec1!1 = (AVec!1 lshift 4)+J ReportPE(NPETab,NPEX,DVec,MemX,AVec1,WaitP) ] ] ] ] endcase ] ReadDMux(); UpdateMPDValues() ]