//MXPRIN.BCPL	Procedures to print out microinstructions


external [
//OS
	Wss; Wns; Puts

//MIDAS
	GetField

//MSYM
	SearchBlocks

//MXPRASM
	F1tab; F2tab; BStab; BDtab; ALUtab; BCtab

//Defined here
	PrintIM; PrintARM
]


let PrinT(S,TplusX) be
[	let Str = TplusX+rv TplusX
	if Str!0 ne 0 then Wss(S,Str)
]


and PWss(S,Str,lvFlag) be
[	if lvFlag!0 then Wss(S,", ")
	Wss(S,Str)
	rv lvFlag = false
]


and CkPQLR(S,lvPrevC,lvMread,MemX,MemA,PS,Plow,Phigh,QS,Qval) be
[	let Enclose,PMid = false,(Phigh+Plow) rshift 1
	let AVec = vec 1; AVec!0 = 0
	if (PS le Phigh) & (PS ge Plow) do
	[ PWss(S,"P←",lvPrevC)
	  if PS ne PMid do [ Enclose = true; Puts(S,$( ) ]
	]
	if QS eq Qval do PWss(S,"Q←",lvPrevC)
	if ((PS le Phigh) & (PS ge Plow)) % (QS eq Qval) do
	[ AVec!1 = MemA; SearchBlocks(S,MemX,AVec)
	  rv lvMread = true; rv lvPrevC = true
	  if Enclose do
	  [ test PS > PMid
	    ifso [ Wss(S,") LSH ["); Wns(S,PS-PMid,0,8) ]
	    ifnot [ Wss(S,") RSH ["); Wns(S,PMid-PS,0,8) ]
	    Puts(S,$] )
	  ]
	]
]


and PrinPCY(S,PS) be
[	test PS ge 31B
	ifso
	[ Wss(S,"Q RCY ["); Wns(S,(not PS) & 77B,0,8) ]
	ifnot switchon PS into
	[
case 1:	Wss(S,"Q RCY [Y"); endcase
case 2:	Wss(S,"Q RCY [44-Y"); endcase
default: Wss(S,"Q LCY ["); Wns(S,PS-3,0,8); endcase
	]
	Puts(S,$] )
]

and PrEnclose(S,Flag,lvFirst) be
[	if Flag then test rv lvFirst
	ifso Puts(S,$()
	ifnot Wss(S,") U (")
	rv lvFirst = false
]


and PrintIM(S,X,DVec,AddrVec) be
[	let AVec = vec 1; AVec!0 = 0
	let PrevClause = false
	let BA = GetField(0,14B,DVec)
	let LA = GetField(14B,5,DVec)
	let BT = GetField(21B,2,DVec)
	let BC = GetField(23B,5,DVec)
	let RA = GetField(30B,5,DVec)
	let ALUF = GetField(35B,5,DVec)
	let BS = GetField(42B,5,DVec)
	let PS = GetField(47B,6,DVec)
	let QS = GetField(55B,3,DVec)
	let BRKP = GetField(60B,1,DVec)
	let BD = GetField(61B,5,DVec)
	let F1 = GetField(66B,6,DVec)
	let F2 = GetField(74B,4,DVec)
	let SMA = GetField(100B,10B,DVec)

	if BC ne 0 do		//Have a branch clause?
	[ Wss(S,selecton BT into
	  [ case 0:	"CALL"
	    case 1:	"GOTO"
	    case 2:	"RETURN"
	    case 3:	"DGOTO"
	  ] )
	  PrevClause = true
	  test BT ne 2
	  ifso
	  [ Puts(S,$[ ); AVec!1 = BA; SearchBlocks(S,2,AVec,AddrVec!1)
	    if BC ne 20B do [ Puts(S,$, ); PrinT(S,BCtab+BC) ]
	    Puts(S,$] )
	  ]
	  ifnot if BC ne 20B do
	  [ Puts(S,$[ ); PrinT(S,BCtab+BC); Puts(S,$] ) ]
	]

	let LMread,RMread,DoneALU = LA eq 4,RA eq 4,0
	let DoneF1 = (F1 eq 50B) % (F1 eq 6B)
	let DoneF2 = (F2 eq 12B) % (F2 eq 15B)

//Check P←Q←LM and P←Q←RM
	CkPQLR(S,lv PrevClause,lv LMread,8,LA,PS,16B,24B,QS,0)
	CkPQLR(S,lv PrevClause,lv RMread,7,RA,PS,7B,15B,QS,4)

//Q←RB RSH 1 or Q←RB RCY 1
	if QS eq 6 do
	[ PWss(S,"Q←(",lv PrevClause)
	  AVec!1 = RA; SearchBlocks(S,7,AVec)
	  Wss(S, ((DoneF1 % DoneF2) ? ") RCY 1", ") RSH 1"))
	  PrevClause,RMread = true,true
	]

//Other Q except bus and ALU
	if QS eq 3 % QS eq 1 do
	[ PWss(S,(QS eq 3 ? "Q R","Q L"),lv PrevClause)
	  Wss(S,((DoneF1 % DoneF2) ? "CY 1","SH 1"))
	  PrevClause = true
	]

//Other P except bus and ALU
	if PS eq 27B do
	[ PWss(S,"P←P1",lv PrevClause); PrevClause = true ]

	if (F1 ne 7) & ((PS ge 31B) % (PS le 6B)) do
//NOT(ALU)Q RCY postponed until later
	[ PWss(S,"",lv PrevClause)
	  test PS eq 0
	  ifso Wss(S,"PSEL[0]")
	  ifnot
	  [ Puts(S, (((F1 eq 50B) % (F2 eq 15B)) ? $Q,
		((F1 eq 6) % (F2 eq 12B)) ? $0,$P))
	    PrinPCY(S,PS)
	  ]
	  PrevClause = true
	]

//Now do bus destinations
	let HaveDestination = false
	if PS eq 30B do	//P←bus?
	[ PWss(S,"P←",lv PrevClause)
	  HaveDestination = true
	]
	if QS eq 7B do		//Q←bus?
	[ PWss(S,"Q←",lv PrevClause)
	  HaveDestination = true
	]
	if (F1 eq 61B) % (F2 eq 6B) % (BD eq 6B) do	//SM←bus?
	[ if PrevClause then Wss(S,", ")
	  AVec!1 = SMA; SearchBlocks(S,3,AVec)
	  Puts(S,$←); HaveDestination = true
	  if F1 eq 61B then DoneF1 = true
	  if F2 eq 6B then DoneF2 = true
	]
	if (F1 eq 43B) %	//KMDRL←
	  (F1 eq 62B) %	//ARM←
	  (F1 eq 2B) %		//YKPTR←
	  (F1 eq 41B) do	//MDRL←
	[ PWss(S,"",lv PrevClause); PrinT(S,F1tab+F1); DoneF1 = true
	  HaveDestination = true
	]

	let Enclose = ((BS ne 37B) & (BS ne 0)) ? 1,0
	if (F1 eq 22B) % (F1 eq 45B) % (F1 eq 46B) % (F1 eq 60B) %
		(F1 eq 27B) % (F1 eq 53B) do
	[ DoneF1 = true;  Enclose = Enclose+1 ]
	if F2 eq 5 then [ DoneF2 = true; Enclose = Enclose+1 ]
	if ((BD ne 0) % (Enclose ne 0)) & (BD ne 6B) do
	[ PWss(S,"",lv PrevClause); PrinT(S,BDtab+BD)
	  HaveDestination = true
	]
//Now do bus sources
	AVec!1 = SMA
	test Enclose eq 0
	ifso if HaveDestination then [ PrevClause = true; Wss(S,"NULL") ]
	ifnot
	[ Enclose = Enclose > 1 ? true,false
	  PrevClause = true; let FirstClause = true
//High SM as source?
	  if (F1 eq 27B) % (BS eq 17B) then SMA = SMA+400B
//SM as source?
	  if (F1 eq 22B) % (F2 eq 5) % (BS eq 6) %
		(F1 eq 27B) % (BS eq 17B) do
	  [ PrEnclose(S,Enclose,lv FirstClause); SearchBlocks(S,3,AVec)
	  ]
//F1 sources (KRDATA, KWDATA)?
	  if (F1 eq 45B) % (F1 eq 46B) do
	  [ PrEnclose(S,Enclose,lv FirstClause); PrinT(S,F1tab+F1) ]
//BA as source?
	  if (F1 eq 60B) % (BS eq 36B) do
	  [ PrEnclose(S,Enclose,lv FirstClause); Wns(S,BA,0,8); Wss(S,"IB")
	  ]  
//ALU as source?
	  if (F1 eq 53B) % (BS eq 25B) do
	  [ PrEnclose(S,Enclose,lv FirstClause)
	    PrinALU(S,PS,QS,ALUF,LA,RA,LMread,RMread,F1,F2)
	    DoneALU = true
	  ]
//BS as source & not used above?
	  if (BS ne 0) & (BS ne 36B) & (BS ne 6) &
		(BS ne 17B) & (BS ne 25B) do
	  [ PrEnclose(S,Enclose,lv FirstClause); PrinT(S,BStab+BS)
	  ]
	  if Enclose then Puts(S,$))
	]

	if BS eq 37B do	//BAX source?
	[ Wss(S,", "); PrinT(S,BStab+BS); PrinMask(S,(not BA) & 7777B)
	]
//Now do the ALU if not used above
	if not DoneALU do
	[ if PrevClause then Wss(S,", ")
	  PrinALU(S,PS,QS,ALUF,LA,RA,LMread,RMread,F1,F2)
	]

//Standalone F1's
	if (not DoneF1) & (F1 ne 0) & (F1 ne 20B) & (F1 ne 21B) do
	[ Wss(S,", "); PrinT(S,F1tab+F1)
//Special for mask, x-loading, SETF functions
	  switchon F1 into
	  [
case 1B:  PrinSAF(S,AVec); endcase		//SETSF
case 34B: PrinSAF(S,AVec); endcase		//SETF
case 35B: PrinSAFC(S,AVec,BC); endcase	//SETFC
case 36B: PrinSAF(S,AVec); endcase		//CLEARF
case 37B: PrinSAFC(S,AVec,BC); endcase	//CLEARFC
case 54B: PrinMask(S,BA); endcase		//BAMASK
case 55B: PrinMask(S,(not SMA) & 77B); endcase	//SAMASK
case 57B: PrinMask(S,ALUF); endcase		//AMASK
case 70B: PrinMask(S,(not BA) & 7777B); endcase	//BAX
case 71B: PrinMask(S,SMA); endcase		//SAX
case 73B: PrinMask(S,(not ALUF) & 37B); endcase	//AX
	  ]
	]

//Standalone F2's
	if (not DoneF2) & (F2 ne 10B) do
	[ Wss(S,", "); PrinT(S,F2tab+F2)
	  if F2 eq 11B do PrinSAF(S,AVec)
	]

//Finally, BRKP
	if BRKP ne 0 then Wss(S,", BRKP[1]")
]


and PrinSAF(S,AVec) be
[	Puts(S,$[); SearchBlocks(S,3,AVec); Puts(S,$])
]


and PrinSAFC(S,AVec,BC) be
[	Puts(S,$[); SearchBlocks(S,3,AVec); Puts(S,$,)
	PrinT(S,BCtab+BC); Puts(S,$])
]


and PrinMask(S,Val) be
[	Puts(S,$[); Wns(S,Val,0,8); Puts(S,$])
]


and PrinALU(S,PS,QS,ALUF,LA,RA,LMread,RMread,F1,F2) be
[	let Enclose = ((F1 eq 7) & ((PS ge 31B) % (PS le 77B)
		% (PS le 6B))) % (PS eq 25B)
	test Enclose
	ifso Wss(S,(PS eq 25B ? "P←(","NOT("))
	ifnot if PS eq 26B then Wss(S,"P←")
	let AVec = vec 1; AVec!0 = 0
	if not LMread do
	[ AVec!1 = LA; SearchBlocks(S,8,AVec); Puts(S,$←)
	]
	if not RMread do
	[ AVec!1 = RA; SearchBlocks(S,7,AVec); Puts(S,$←)
	]
	if QS eq 2 then Wss(S,"Q←")
	test ALUF ge 20B
	ifso PrinT(S,ALUtab+ALUF-20B)
	ifnot
	[ let Carry = (F1 eq 20B) % (F2 eq 13B)
	  let CarryJ = F1 eq 21B
	  switchon ALUF into
	  [
default: Wss(S,"ALUF["); Wns(S,ALUF,0,8); Wpj(S,"]",Carry,CarryJ); endcase
case 0:	  Wnj(S,"P",Carry,CarryJ); endcase
case 3:	  Wpj(S,"2P",Carry,CarryJ); endcase
case 4:	  Wnj(S,"P AND NOT Q",Carry,CarryJ); endcase
case 6:	  Wnj(S,"P-Q",Carry,CarryJ); endcase
case 10B: Wnj(S,"P AND Q",Carry,CarryJ); endcase
case 11B: Wpj(S,"P+Q",Carry,CarryJ); endcase
case 13B: Wpj(S,"P AND Q+P",Carry,CarryJ); endcase
case 17B: Wpj(S,"P",Carry,CarryJ); endcase
	  ]
	]
	if Enclose then test PS eq 25B
	  ifso Wss(S,") ARSHC 1")
	  ifnot [ Puts(S,$) ); PrinPCY(S,PS) ]
]


and Wnj(S,Str,Carry,CarryJ) be
[	Wss(S,Str); if not Carry then
		Wss(S,(CarryJ ? "-NJ","-1"))
]


and Wpj(S,Str,Carry,CarryJ) be
[	Wss(S,Str); test Carry
	ifso Wss(S,"+1")
	ifnot if CarryJ then Wss(S,"+J")
]


and PrintARM(S,X,DVec) be
[	let Enabled = (DVec!1 lshift 4)+(DVec!2 rshift 12)
	if Enabled ne 0 do
	[ Wss(S,"Ch ")
	  for I = 0 to 15 do
	  [ if Enabled < 0 then Wns(S,I,0,8); Puts(S,$ )
	    Enabled = Enabled lshift 1
	  ]
	  Wss(S," enabled, ")
	]
	Enabled = DVec!0
	if Enabled < 0 do
	[ Wss(S,"int on ch "); Wns(S,(not (Enabled rshift 11)) & 17B,0,8)
	  Wss(S,", ")
	]
	if (Enabled & 8) ne 0 then Wss(S,"IM ")
	if (Enabled & 4) ne 0 then Wss(S,"SM ")
	if (Enabled & 2) ne 0 then Wss(S,"& MP ")
	if (Enabled & 16B) ne 0 then Wss(S,"PE enabled, ")
	if (Enabled & 3760B) ne 0 do
	[ Wss(S,"PE's in ")
	  if (Enabled & 2000B) ne 0 then Wss(S,"IM0-17 ")
	  if (Enabled & 1000B) ne 0 then Wss(S,"IM18-35 ")
	  if (Enabled & 400B) ne 0 then Wss(S,"IM36-53 ")
	  if (Enabled & 200B) ne 0 then Wss(S,"IM54-71 ")
	  if (Enabled & 100B) ne 0 then Wss(S,"SM0-17 ")
	  if (Enabled & 40B) ne 0 then Wss(S,"SM18-35 ")
	  if (Enabled & 20B) ne 0 then Wss(S,"MP ")
	]
]