//D0Prin1.bcpl Procedures to prettyprint IM, IMX
// Last edited: 20 October 1981
//The args to print routines are as follows:
// X MemX or RegX
// DVec The DataVec to be printed
// AVec An AddrVec which sometimes is relevant to what gets
// printed (e.g., branch fields in IM printout show
// ".+1", ".+2", etc. relative to the AddrVec)
// ExtRadix Extension in l.h. (always 0 for D0) and radix
// for printout in the r.h. (currently ignored since octal
// is used everywhere)
get "d0.d"
manifest [ get "d0regmem.d" ]
external
[
// MIDAS
MidasSwat
// MASM
GetField; PutsCSS; WssCS1; @WssCSS; @OddParity
// MSYM
SearchBlocks
// MCMD
CmdCommentStream; CmdCS1; WnsCSS; WnsCS1
// D0I0
DVx
// D0I1
BootTable; NBootInst; MIMtab
// D0ASM
stNotInVM
// D0VM
LookUpAA; LookUpVA; @VirtualP
// D0PRIN1ASM
F1tab; F17F2tab; ALUbettab; ALUposttab0; BCtab; MEMtypetab
// D0PRIN1A
CPrint; PrinC; PrinR; PrinVA
// Defined here
PrinIM
]
let C1Wss(Str,Val) be
[ WssCS1(Str); WnsCS1(Val)
]
and SelfRel(X) = X!0 eq 0 ? 0,X+X!0
//Print out microinstruction--ambiguous printout for BLOCK and RSTK
//based upon emulator/non-emulator. AddrVec is the address of the
//microinstruction, virtual or absolute for IM and IMX.
and PrinIM(X,DVec,AddrVec,ExtRadix) be
[ let CTASK = DVx>>srbus.ctask //Frequently correct
//PrintTag winds up true to print the location before the contents of
//the instruction, false if not printing it. Point is the location
//(virtual if VirtualP else absolute). BA is the absolute location.
let PrintTag,BA,Point = true,nil,AddrVec!1
switchon X into
[
case MIMx: if MIMtab+(3*AddrVec!1) ge BootTable+(NBootInst*3) then
[ WssCSS("never loaded"); return
]
X,Point,CTASK = IMXx,DVec!2 & #7777,#17
BA = Point; endcase
case MDATAx: Point = #170000 //Prevent .+n, .-n printout
PrintTag = false
case IMXx: BA = Point; endcase
case IMx: if (DVec+3)>>IMV.Undef ne 0 then
[ WssCSS(stNotInVM); return
]
BA = (DVec+3)>>IMV.Addr
endcase
default: MidasSwat(BadPrintIMMemX)
]
//Print the m-i symbolically on the first comment line;
//print the individual m-i fields on the second comment line.
//M-i in IM, IMX, MIM, and MDATA are printed the same except that the
//tag is not printed for MDATA and the tag and branch targets are
//printed symbolically for IM.
//Form of virtual printout is:
// TAG+3: GOTO[FOO+1,FOO+2,ALU=0], ...;
//Form of absolute printout is:
// 351: GOTO[64,ALU=0], ...;
let PrinRoutine = VirtualP ? PrinVA,WnsCSS
if PrintTag do
[ test VirtualP
ifso
[ test X eq IMXx
ifso PrinVA(BA,#100000)
ifnot SearchBlocks(CmdCommentStream,IMx,AddrVec)
]
ifnot WnsCSS(BA)
WssCSS(": ")
]
//These fields common to both types of m-i
let MEMINST = GetField(0,1,DVec)
let RSEL = #60 xor (GetField(2,4,DVec) lshift 2)+GetField(32,2,DVec)
let F2 = GetField(18,4,DVec)
let JC = GetField(22,3,DVec)
let JA = (GetField(34,2,DVec) lshift 6) + GetField(25,6,DVec)
let CSPar = OddParity(DVec!0 xor DVec!1,DVec!2 & #170000)
//Regular m-i only
let RMOD = GetField(1,1,DVec)
let ALUF = GetField(6,4,DVec)
let BSEL = GetField(10,2,DVec)
let F1 = GetField(12,4,DVec)
let LR = GetField(16,1,DVec)
let LT = GetField(17,1,DVec)
//Memory m-i only
let DF2,TYPE = RMOD,ALUF
let SRCDEST = GetField(10,8,DVec)
let Rshift,StackShift,BranchShift,LoadPage=false,false,false,false
//Destinations for ALUA and H2
let ADest1,ADest2,BDest1,BDest2 = 0,0,0,0
let F1clause,F2clause = 0,0
let NextInst,NextData = false,false
let rwcs = false
//R Source stuff
let RPred, Rsrc = 0,0
//ALUA correct unless RMOD is 1
let ALUA =
(((RSEL rshift 4) eq 0 ? CTASK,CTASK & #14) lshift 4) % RSEL
let ALUAvec = vec 1; ALUAvec!0 = 0
//**Is the (F1 rshift 2) ne 1 correct? Know that F1 eq 5 is LoadPage[F2]
//**and F1 eq 7 is Group B, so F2 not ok, but F1 eq 4 and F1 eq 6 are
//**noops--do these disable F2?
let f2ok = MEMINST ne 0 ? DF2 eq 0,
(BSEL eq 2) & ((F1 rshift 2) ne 1)
if f2ok then switchon F2 into
[
case 0: Rshift = true; endcase
case 1: ADest2 = "StkP←"; endcase
case 2: F2clause = "FreezeResult"; endcase
case 3: test CTASK eq 0
ifso StackShift = true
ifnot F2clause = "IOStrobe"
endcase
case 4: ADest2 = "CycleControl←"; endcase
case 5: ADest2 = "DB←"; endcase
case 6: ADest2 = "SB←"; endcase
case 7: F2clause = "SpareF2"
endcase
case 8: BranchShift = true; endcase
case 9: BDest2 = "SALUF←"; endcase
case 10: endcase
case 11: ADest2 = "MNBR←"; endcase
case 12: ADest2 = "PCF←"; endcase
case 13: F2clause = "ResetMemErrs"; endcase
case 14: F2clause = "UseCoutAsCin"; endcase
case 15: ADest2 = "Printer←"; endcase
]
//Separate handling of m-i according to MEMINST
C1Wss("MI=",MEMINST)
test MEMINST eq 0
ifso
[ let rx = RSEL & 3
let f1ok = BSEL eq 2
if f1ok do
[ F1clause = SelfRel(F1tab+F1)
switchon F1 into
[
case 1: BDest1 = "RS232←"; endcase
case 2: ADest1 = "Timer←"; endcase
case 3: ADest1 = "AddToTimer←"
case 5: LoadPage = true; endcase
case 14: NextInst = true; endcase
case 15: NextData = true; endcase
case 7: F1clause = SelfRel(F17F2tab+F2)
switchon F2 into
[
case 8: ADest1 = "APCTask&APC←"; endcase
case 12 to 15: rwcs = true
default: endcase
]
//**case 0 BBFA requires Rshift true, but not checked
deafult: endcase
]
]
if RMOD ne 0 do
[ test rx eq 3
ifso Rsrc = selecton RSEL rshift 2 into
[
case 0: "SStkP&NStkP"
case 1: "ALUResult&NSALUF"
case 2: "MemSyndrome"
case 3 to 4: "UndefF2"
case 5: Rshift ? "Printer","Cycle&PCXF"
case 6: Rshift ? "DB&SB","Timer"
case 7: Rshift ? "MNBR","RS232"
case 8: "APCTask&APC"
case 9: "CTask&NCIA"
case 10: "CSData"
case 11: "Page&Par&Boot"
case 12: StackShift ? "Stack&+2","Stack"
case 13: StackShift ? "Stack&+3","Stack&+1"
case 14: StackShift ? "Stack","Stack&-1"
case 15: StackShift ? "Stack&-3","Stack&-2"
]
ifnot
[ RPred = selecton rx into
[ case 0: "PCF["
case 1: "SB["
case 2: "DB["
]
//The contents of PCF, SB, or DB replace RSEL[4:5]
ALUA = ALUA & #374
if rx eq 0 do
[ test NextInst
ifso [ RPred = "NextInst["; F1clause = 0 ]
ifnot if NextData do
[ RPred = "NextData["; F1clause = 0 ]
]
]
]
//Stuff for BSEL source and destination
//BSEL and F Constants provide at most one source and destination, but
//sometimes F's or LR provide a second (or even 3rd) destination
let Bsrc = BSEL < 2 ? "C","T"
let FC = (F1 lshift 4)+F2
let fconst = BSEL < 2
let SFtype,POSmask,SIZEcount = 0,nil,nil
switchon BSEL into
[
case 1: FC = FC lshift 8
case 0:
case 2: endcase
case 3: //Short-field stuff
test FC < #207
ifso //LDF
[ SFtype = 1 //SIZEcount,POSmask = nbits,leftbit
test FC < #20
ifso [ SIZEcount,POSmask = 1,FC ]
ifnot test FC < #37
ifso [ SIZEcount,POSmask = 2,FC-#20 ]
ifnot test FC < #55
ifso [ SIZEcount,POSmask = 3,FC-#37 ]
ifnot test FC < #72
ifso [ SIZEcount,POSmask = 4,FC-#55 ]
ifnot test FC < #106
ifso [ SIZEcount,POSmask = 5,FC-#72 ]
ifnot test FC < #121
ifso [ SIZEcount,POSmask = 6,FC-#106 ]
ifnot test FC < #133
ifso [ SIZEcount,POSmask = 7,FC-#121 ]
ifnot test FC < #144
ifso [ SIZEcount,POSmask = 8,FC-#133 ]
ifnot test FC < #154
ifso [ SIZEcount,POSmask = 9,FC-#144 ]
ifnot test FC < #163
ifso [ SIZEcount,POSmask = 10,FC-#154 ]
ifnot test FC < #171
ifso [ SIZEcount,POSmask = 11,FC-#163 ]
ifnot test FC < #176
ifso [ SIZEcount,POSmask = 12,FC-#171 ]
ifnot test FC < #202
ifso [ SIZEcount,POSmask = 13,FC-#176 ]
ifnot test FC < #205
ifso [ SIZEcount,POSmask = 14,FC-#202 ]
ifnot [ SIZEcount,POSmask = 15,FC-#205 ]
test POSmask eq 0
ifso //Convert to RSH form
[ SFtype,SIZEcount = 2,16-SIZEcount
]
ifnot if (SIZEcount+POSmask eq 16) &
(SIZEcount eq 8) do //RHMask
[ SFtype = 11
]
]
ifnot test FC < #301
ifso //DISPATCH
[ SFtype = 3
test FC < #227
ifso [ SIZEcount,POSmask = 1,FC-#207 ]
ifnot test FC < #246
ifso [ SIZEcount,POSmask = 2,FC-#227 ]
ifnot test FC < #264
ifso [ SIZEcount,POSmask = 3,FC-#246 ]
ifnot [ SIZEcount,POSmask = 4,FC-#264 ]
]
ifnot test FC < #320
ifso //LSH
[ SFtype,SIZEcount = 4,FC-#300
]
ifnot test FC < #337
ifso //LCY
[ SFtype,SIZEcount = 5,FC-#317
]
ifnot test FC < #341
ifso test FC eq #337
ifso //LHMASK
[ SFtype = 10
]
ifnot //ZERO
[ SFtype = 7
]
ifnot test FC eq #341
ifso //FixVA
[ SFtype = 8
]
ifnot test FC < #347
ifso
[ SFtype = 12
POSmask = table [ #2; #4; #5; #6; #10 ] ! (FC-#342)
]
ifnot test FC < #356
ifso //RBsource & mask
[ SFtype = 6
POSmask = table [ #2; #3; #4; #5; #6; #7; #10 ] !(FC-#347)
]
ifnot test FC eq #356
ifso //Nib0Rsh8
[ SFtype = 9
]
ifnot //Noops
[
]
endcase
]
if ADest2 eq 0 do
[ ADest2 = ADest1; ADest1 = 0
]
if BDest2 eq 0 do
[ BDest2 = BDest1; BDest1 = 0
]
let RPrinted = false
//ALU clause printed first
//Destinations first:
ALUAvec!1 = ALUA
if LR eq 1 then
[ PrinR(RPred,Rsrc,ALUAvec); PutsCSS($←); RPrinted = true
]
test LT eq 1
ifso WssCSS("T←")
ifnot if LR eq 0 then WssCSS("LU←")
//Stuff for ALU printout:
//ALUtype: 0=no args, 1=A only, 2=B only, 3 = both
let ALUtype = table [
2; 1; 3; 3; 3; 3; 3; 3;
1; 3; 3; 1; 3; 3; 0; 3 ] !ALUF
//First char of ALU expression is "(" unless the ALU function is purely
//ALUA or purely H2.
if ALUF ge 2 then PutsCSS($()
if (ALUtype & 1) ne 0 do //Involves ALUA
[ CPrint(ADest2,ADest1)
PrinR(RPred,Rsrc,ALUAvec,SFtype,SIZEcount,POSmask)
]
if ALUtype > 1 do //Involves H2
[ CPrint(SelfRel(ALUbettab+ALUF))
CPrint(BDest2,BDest1)
if fconst then WnsCSS(FC)
WssCSS(Bsrc)
]
CPrint(SelfRel(ALUposttab0+ALUF))
//If the ALU clause does not involve ALUA, print the ALUA clause now; print
//nothing if there is no ALUA destination, and the RM source was already
//printed as the ALU destination or is not one of the R-bus sources and is
//not involved in an RM branch condition or shifter-masker expression.
if (ALUtype & 1) eq 0 do
[ PrinC(ADest2,ADest1)
unless ((ADest2 eq 0) & (SFtype eq 0) &
(RPrinted % ((Rsrc eq 0) & ((JC ne 2) % BranchShift))) &
((Rsrc eq 0) % ((rx eq 3) & ((RSEL rshift 2) ge 12)))) do
[ if ADest2 eq 0 then WssCSS(", A←")
PrinR(RPred,Rsrc,ALUAvec,SFtype,SIZEcount,POSmask)
]
]
//If the ALU clause does not involve H2, print H2 clause now unless
//there is no destination for H2 and the source is T.
if ALUtype le 1 do
[ PrinC(BDest2,BDest1)
unless (BDest2 eq 0) & (fconst eq 0) do
[ if BDest2 eq 0 then WssCSS(", H2←")
if fconst then WnsCSS(FC)
WssCSS(Bsrc)
]
]
//Print any standalone F1 clause
PrinC(F1clause)
if f1ok & (F1 eq 5) then [ WnsCSS(F2); PutsCSS($]) ]
C1Wss(",RMOD=",RMOD)
C1Wss(",RSEL=",RSEL)
C1Wss(",ALUF=",ALUF)
C1Wss(",BSEL=",BSEL)
C1Wss(",F1=",F1)
C1Wss(",LR=",LR)
C1Wss(",LT=",LT)
]
ifnot //MEMINST eq 1
[ let SDvec = vec 1; SDvec!0 = 0
SDvec!1 = SRCDEST eq 0 ? 0, SRCDEST % (CTASK lshift 4)
ALUAvec!1 = ALUA
test (TYPE ne #2) & (TYPE ne #7) & (TYPE ne #13)
ifso
[ if (ALUA & 1) ne 0 then WssCSS("Odd")
WssCSS(SelfRel(MEMtypetab+TYPE))
SearchBlocks(CmdCommentStream,RMx,ALUAvec) //Base reg.
]
//Input, Output, & ReadPipe print the base register last iff non-zero
ifnot WssCSS(SelfRel(MEMtypetab+TYPE))
switchon TYPE into
[
case 4 to 6:
case 8 to 10:
case 14: PutsCSS($,)
case 2:
case 11:
case 7: //Types that have R source or destination
test SDvec!1 eq 0
ifso WssCSS("Stack")
ifnot SearchBlocks(CmdCommentStream,RMx,SDvec)
if DF2 eq 1 then
[ PutsCSS($,); WnsCSS(F2)
]
//Input, Output, & ReadPipe print base reg arg third iff non-zero.
if ((TYPE eq #2) % (TYPE eq #7) % (TYPE eq #13)) &
((ALUA & #17) ne 0) do
[ if DF2 eq 0 then PutsCSS($,)
PutsCSS($,); SearchBlocks(CmdCommentStream,RMx,ALUAvec)
]
case 0: //Undef
case 3: //Refresh
endcase
case 1:
case 12 to 13:
case 15: //Types that have device source or destination
if DF2 eq 1 do
[ PutsCSS($,); WnsCSS(F2)
]
endcase
]
PutsCSS($])
C1Wss(",DF2=",DF2)
C1Wss(",RSEL=",RSEL)
C1Wss(",TYPE=",TYPE)
C1Wss(",SRCDEST=",SRCDEST)
]
C1Wss(",F2=",F2)
C1Wss(",JC=",JC)
C1Wss(",JA=",JA)
WssCS1(CSPar ? ",Par ok",",Par bad")
//Standalone F2 clause
PrinC(F2clause)
//Control clause
let NxtA = (BA & #7400) + JA
switchon JC into
[
case 0 to 3: NxtA = NxtA % 1
PrinC("DblGoTo["); endcase
case 6: unless rwcs do
[ PrinC(((JA & 1) ne 0 ? "NIRet","Return")); endcase
]
case 4: PrinC("GoTo["); endcase
case 5: PrinC("Call["); endcase
case 7: PrinC("Disp["); endcase
]
if (JC ne 6) % rwcs do
[ PrinRoutine(NxtA,Point)
if JC < 4 do
[ PutsCSS($,); PrinRoutine(NxtA & #177776,Point); PutsCSS($,)
WssCSS(SelfRel(BCtab+((BranchShift & #10)+
(JC lshift 1)+(JA & 1))))
]
PutsCSS($])
]
test (BA & #6003) eq #2001
ifso
[ PrinC("Opcode["); WnsCSS((BA rshift 2) & #377); PutsCSS($])
]
ifnot if VirtualP do
[ PrinC("At["); WnsCSS(BA); PutsCSS($])
]
]