// MDlist0.bcpl -- common listing routines for MicroD
// last edited February 2, 1981  2:57 PM

	get "mddecl.d"

external	// defined here
[	CountUsed	// (ubits, used, reserved)
	ListRM	// (S)
	ListMem	// (S, header, membits, memx, memsize, proc, blocksize)
	ListSym	// (S, ptr)
	ListASym	// (str, ptr[, flag])
]

external	// used
[		// MDmain
	@IP
	@DMachine
	@NInstructions
	@IMlocked
	@RM; @RMbits
		// MDerr
	PutName
		// MDload
	@mSymMax
		// MDdump
	@mSymPtrs
		// MDscan
	@nPages; @PageSize
		// MDasm
	CountBits
	Get1Bit; Set1Bit
		// Template
	PutTemplate
		// OS
	Puts; Wss
	Zero
]


let CountUsed(ubits, used, reserved) be
// let ubits, used, reserved = vec IMsize/16, vec maxnPages, vec maxnPages
[	Zero(ubits, IMsize/16)
	for i = 0 to NInstructions-1 do
	[ let ip = IP(i)
	  if ip>>IM.placed then	// Skip instrs not placed (if assignment pass failed)
	    Set1Bit(ubits, ip>>IM.W0, 1)
	]
	Zero(used, nPages)
	Zero(reserved, nPages)
	let up, rp, wpp = ubits, IMlocked, PageSize/16
	for i = 0 to nPages-1 do
	[ let u, r = 0, 0
	  for j = 1 to wpp do
	  [ u = CountBits(@up)+u
	    r = CountBits(@rp)+r
	    up, rp = up+1, rp+1
	  ]
	  used!i, reserved!i = u, r
	]
]

and ListRM(S) be
[	let ListRMword(S, i, used) be
	[ test used eq 0
	   ifso Wss(S, "        ")	// location and symbol only
	   ifnot PutTemplate(S, "$8UO", RM!i)
	]
	ListMem(S, "RM", RMbits, RMmemx, RMsize, ListRMword, (DMachine eq 0? D0RMBlockSize, D1RMBlockSize))
]

and ListMem(S, header, membits, memx, memsize, proc, blocksize) be
[	let first = true
	let syms, symax  = mSymPtrs!memx, mSymMax!memx
	let lastblock, mask = -1, -blocksize
	for i = 0 to memsize-1 do
	[ let sym = (i gr symax? 0, syms!i)
	  let used = (membits eq 0? 0, Get1Bit(membits, i))
	  if (sym ne 0) % (used ne 0) then
	  [ if first then
	    [ PutTemplate(S, (header>>BS.char↑1 eq $*N? "$S", "*N$S:*N"), header)
	      first = false
	    ]
	    let block = i & mask
	    if block ne lastblock then
	    [ Puts(S, $*N)
	      lastblock = block
	    ]
	    PutTemplate(S, "$6O", i)
	    proc(S, i, used)
	    if (sym ne 0) then ListSym(S, sym)
	    Puts(S, $*N)
	  ]
	]
]

and ListSym(S, ptr) be
if ptr ne 0 then
[	Wss(S, "  ")
	ListASym(S, ptr, true)
]

and ListASym(s, ptr, flag; numargs na) be
[	if na ls 3 then flag = false
	test @ptr ne 0
	 ifso	// chained
	[ ListASym(s, @ptr, flag)
	  test flag
	   ifso [ Puts(s, $*S); PutName(s, ptr+1) ]
	   ifnot [ Wss(s, "(="); PutName(s, ptr+1); Puts(s, $)) ]
	]
	 ifnot
	PutName(s, ptr+1)
]