//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()
]