      C 7$     
?BOOT-U-No boot on volume

 ߋtv                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         SRT11A                   DECRT11A      rks references to RMON (from hidden code)
.IfF;	NE	MMg$t
;	SL, SLR, and SLX mark references to handler code
;	RMON and RMONX mark references to RMON
.EndC;	NE	MMg$t
;-
.If	NE	MMg$t

.Macro	$Rel	Loc	Value	Base
.....1	=	.
.	=	Loc
.If	IDN	<SL>	<Base>
SL.Cnt	=	SL.Cnt+1
.Irp	x	<\SL.Cnt>
SL.'x:	.Word	Value-SLBase
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<SL>	<Base>

.If	IDN	<RMON>	<Base>
RM.Cnt	=	RM.Cnt+1
.Irp	x	<\RM.Cnt>
RM.'x:	.Word	Value
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<RMON>	<Base>

.If	IDN	<SLX>	<Base>
SLX.Cnt	=	SLX.Cnt+1
.Irp	x	<\SLX.Cnt>
SX.'x:	.Word	Value-SLXBase+P1Addr
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<SLX>	<Base>

.If	IDN	<SLR>	<Base>
SLR.Cnt	=	SLR.Cnt+1
.Irp	x	<\SLR.Cnt>
SLR.'x:	.Word	Value-SLBase
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<SLR>	<Base>

.If	IDN	<RMONX>	<Base>
RMX.Cnt	=	RMX.Cnt+1
.Irp	x	<\RMX.Cnt>
RMX.'x:	.Word	Value
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<RMONX>	<Base>

.Error	; Unknown B A S E "Base";
.EndM	$Rel

.IfF;	NE	MMg$t
.Macro	$Rel	Loc	Value	Base
.....1	=	.
.	=	Loc

.If	IDN	<SL>	<Base>
SL.Cnt	=	SL.Cnt+1
.Irp	x	<\SL.Cnt>
SL.'x:	.Word	Value-SLBase
.EndR;	IDN	<SL>	<Base>
.	=	.....1
.MExit
.EndC

.If	IDN	<RMON>	<Base>
RM.Cnt	=	RM.Cnt+1
.Irp	x	<\RM.Cnt>
RM.'x:	.Word	Value
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<RMON>	<Base>

.If	IDN	<SLX>	<Base>
SL.Cnt	=	SL.Cnt+1
.Irp	x	<\SL.Cnt>
SL.'x:	.Word	Value-SLBase
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<SLX>	<Base>

.If	IDN	<SLR>	<Base>
SL.Cnt	=	SL.Cnt+1
.Irp	x	<\SL.Cnt>
SL.'x:	.Word	Value-SLBase
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<SLR>	<Base>

.If	IDN	<RMONX>	<Base>
RM.Cnt	=	RM.Cnt+1
.Irp	x	<\RM.Cnt>
RM.'x:	.Word	Value
.EndR
.	=	.....1
.MExit
.EndC;	IDN	<RMONX>	<Base>

.Error	; Unknown B A S E "Base";
.EndM	$Rel

.EndC;	NE	MMg$t
;+
;	BOFF
;
;	Used to define mnemonic branch after TST(B)/BIT(B)
;
;	Boff	Dst
;
;	Dst	-- location to branch to if bit/byte/word off (zero)
;-

.Macro	Boff	Dst
	Beq	Dst
.EndM	Boff

;+
;	BON
;
;	Used to define mn        {vkQi   + {vԀ   + {v^   _ {vv7   _  9g&   +  if bit/byte/word on (non-zero)
;-

.Macro	Bon	Dst
	Bne	Dst
.EndM	Bon

;+
;	......
;
;	indicate unconditional "branching"
;
;	......
;-

.Macro	......
.EndM	......

;+
;	.DISABLE
;
;	Allow .Disable to be used in place of .dsabl
;
;	.Disable opt opt opt
;-

.Macro	.Disable a b c d e f
	.Dsabl	a b c d e f
.EndM	.Disable
;+
;	CALLXR
;
;	Provide multiple calling function (threaded code)
;	Saves space in coding
;
;	CallXR	a,b,c,d,e,f
;-

.Macro	CallXR	A,B,C,D,E,F
	Jsr	R0,CallXR
...Cnt = 0
.Irp	Dest, <F,E,D,C,B,A>
...Cnt = ...Cnt+1
.If	NB	<Dest>
 .If	NE	...Cnt-6
	.Word	Dest-.-2
 .IfF;	NE	...Cnt-6
	.Word	Dest+1-.-2
 .EndC;	NE	...Cnt-6
.EndC;	NB	<Dest>
.EndR
.EndM	CallXR
;+
;	Push
;
;	Place a word on the stack
;-

.Macro	Push	Value
.If	IDN	<Value>	<#0>
	Clr	-(SP)
.Iff;	IDN	<Value>	<#0>
	Mov	Value,-(SP)
.EndC;	IDN	<Value>	<#0>
.EndM	Push

;+
;	PushB
;
;	Place a byte o	.title	Disassembler
	.enabl	lc
;++
;
; Saved image (.SAV) disassembler.
;
; By John Wilson <wilson@dbit.com>.
;
; Copyright (C) 1998 by D Bit.  All rights reserved.
; Distribution, modification, and use for any purpose is allowed as long as
; source code is available which includes this notice.
;
; For RSTS/E V7.0-07 and later, or RT-11 V4.0 and later (probably V3C too).
;
; Makes two passes over the binary file, attempting to trace out the possible
; execution paths of the program, to help differentiate between code and data,
; and to put labels only on locations which are referenced elsewhere.
;
; 06/1984	JMBW	Disassembler created (as part of RAID, DECUS #11-772).
; 08/1985	JMBW	Converted to stand-alone disassembler with execution
;			trace.  V1.0.
; 07/10/1998	JMBW	Added support for re-reading .MAC files from previous
;			runs, to eliminate most of the manual cut/past work
;			needed.  /B switch for use on overlays.  Cleaned up to
;			run on all PDP-11 models (no EIS or SOB).  V1.1.
; 10/17/1998	JMBW	Added CIS, DCJ11, 11/60 instructions.  /U switch for
;			upper case output.  V1.2.
;
; Command line:
; *outfile.MAC=infile.SAV[,infile.mac][/switches]
;
; Switches:
; /S:start	Starting virtual addr of range to disassemble
; /E:end	Ending virtual addr of range to disassemble
; /T:transfer	Transfer address (beginning of an execution thread)
; /B:blk[:offset]  Set base address (within .SAV file) of code to disassemble;
;		virtual address 000000 is at the specified offset (default=0)
;		of block "blk".
; /I		Insert block of disassembled code here
;		(used with /S and /E in .MAC input file)
; /U		Upper case source output (default is lower case).
;
; The basic idea is, on the first run you use the command line to specify the
; range of the .SAV file to disassemble.  Then you go into the resulting .MAC
; file with an editor, add comments and figure out the stuff that's too
; complicated for DISSAV to get on its own (like computed jumps and dispatch
; tables).  You will probably find blocks of code to which DISSAV could find
; no execution path so it left them as .WORD statements.  Once you figure out
; that a block of data is really code, chop it out with the editor and then
; put in a line starting with an asterisk, that looks like the above command
; line but contains only switches (no filenames).  Re-running DISSAV with no
; switches (but with the existing .MAC file specified as the second input
; file) causes it to copy all lines of the file that don't start with "*"
; through to the output file verbatim, and lines that start with "*" are
; treated as command lines, similar to the CSI command line.  For example,
; this could appear in the .MAC input file:
;
; ; insert disassembled code after the next line
; */s:1400/e:1477/t:1400/i
;
; The /I switch means that the block of code should be disassembled and
; <I>nserted after the line starting with "*".  The /S and /E switches are
; required when /I is used, and give the start and end address of the block
; to insert.  /T may optionally be used to specify a transfer address within
; the block, in cases where DISSAV has found no execution route to the block
; on its own.
;
; DISSAV always copies "*" lines containing /T through to the output file
; (after removing /S, /E, and /I switches since they cause a one-time action),
; so that all the information about execution routes will be preserved for
; future runs.  If the line contains /I (i.e. it's a line added by the user to
; force the insertion of a block of disassembled code), DISSAV encloses it in 
; a .REM comment block in the output file, on the assumption that the user
; added that line by hand.  Any other "*" line is assumed to already be inside
; a .REM block since it is assumed to have been generated by a previous DISSAV
; run, so it's copied without adding more .REM statements.
;
; "*" lines containing /B switches may be inserted anywhere in the .MAC file
; to change the base/offset used for reading data out of the .SAV file.
;
; "*" lines containing /T switches may also appear anywhere in the .MAC file;
; only one /T switch is recognized per line.  This allows the user to tell
; DISSAV about JMP/JSR/BR targets that it was unable to find on its own, so
; that the execution trace performed on each successive run includes all
; previously found code blocks.  As noted above, /T switches that appear on
; /I/S/E lines (that insert a block of disassembled code) are automatically
; passed through to the output file, so there's no need to specify /T twice
; for the same transfer address.
;
; Note:  the parameters for the very first disassembly of the entire .SAV file
; are preserved in a .REM block at the beginning of the .MAC file.  DISSAV
; will use this line to set the /B/E/S/T/U parameters for all future runs
; (rather than requiring the user to type the same switches again and again),
; so this automatically generated "*" line must be the first one in the file
; so that DISSAV can find it on the next run.
;
;--
rsts=	0	;set to 0 for real RT-11
		;non-zero for RSTS-style version ID banner (needs .ERRPRT)
;
	.mcall	.close,.csigen,.csispc,.print,.purge,.rctrlo,.wait
;
macin=	2048.	;size of each of two .MAC input buffers (mult of 512.)
macout=	2048.	;size of each of two .MAC output buffers (mult of 512.)
;
.read=	emt!375	;SYSMAC forms of these expect to build EMT area for me
.readw=	emt!375
.write=	emt!375
.writw=	emt!375
;
.errprt=emt!364	;RSTS RT11.RTS call to display err msg for err # in R0
		;(used only if RSTS symbol set NZ)
;
op0=	0	;0-operand instruction
;
ht=	11	;ASCII values
lf=	12
ff=	14
cr=	15
;
jsw=	44	;job status word
;
; Define instruction (with no byte form):
	.macro	instr	mask,result,name,oprnds
	.word	mask,result
	.rad50	/name/
	.word	oprnds
	.endm
;
; Define instruction (add "b" to mnemonic if byte form):
	.macro	instrb	mask,result,name,oprnds
	.word	mask,result
	.rad50	/name/
	.word	oprnds!1	;odd => add "b" if opcode<15> set
	.endm
;
	.macro	.out	ptr	;write .ASCIZ string to output file
	mov	#'ptr,r0
	call	out
	.endm
;
; Start of program.
;
dissav:	call	progid		;print program ID
	.print	#forhlp		;tell them how to get help
;
csi:	; prompt for next command
	mov	@#42,sp		;restore stack
	bis	#40000,@#jsw	;enable LC input
	.rctrlo			;make sure RMON notices
	.csigen	#devhnd,#defext,#0,#rbuf ;call CSI, save line
	mov	#rbuf,r1	;point at string
10$:	movb	(r1)+,r0	;get a char
	beq	20$		;end of string, null command
	cmpb	r0,#40		;space or ctrl char?
	blos	10$		;yes, loop
	br	30$		;no, significant char, cont
20$:	tst	(sp)+		;purge stack
	call	progid		;print program ID
	br	csi		;reprompt
30$:	clr	gstart		;for now, so PEEK can read .SAV header
	mov	#177777,gend	;(same as above)
	clr	base		;reading root, file addr = memory addr
	clr	offset
	mov	#40,r5		;get starting addr
	call	peek
	mov	r0,ppc		;point at starting loc
	mov	r0,xfer		;(label='START:')
	mov	#50,r5		;get high limit
	call	peek
	mov	r0,end		;end at end
	mov	#1000,start	;start at begn
	call	switch		;handle switches parsed by CSI
	tstb	eflg		;get /E value
	beq	40$
	 mov	eval,end
40$:	tstb	sflg		;get /S value
	beq	50$
	 mov	sval,start
50$:	tstb	tflg		;get /T value
	beq	60$
	 mov	tval,ppc
60$:	mov	#symtab,r0	;point at symbol table bitmap
	mov	#14000,r1	;length of SYMTAB+BITMAP+INSBND
70$:	clr	(r0)+		;clear a word
	dec	r1		;loop
	bne	70$
	bic	#1,start	;start on an even address
	bic	#1,xfer		;same for transfer address
	bic	#1,ppc		;and pseudo-PC
	mov	start,gstart	;save global file start/end
	mov	end,gend
	; init output file
	mov	#wmbuf+macout,wmba ;init buffer addr
	mov	#wmbuf,wmoth	;init "other" buffer
	mov	#wmbuf,wptr	;init output ptr/ctr
	mov	#macout,wcnt
	clr	wmblk		;init blk #
	.wait	#0		;is channel #0 even open?
	mov	#1,r0		;[assume so]
	sbc	r0		;0 if not
	movb	r0,wmflg	;NZ if open
;+
;
; Okay, that takes care of initialization.  What we's a gonna do, is:  make
; two passes through the input file;  on pass 1, do a recursive test
; disassembly to find out what gets executed and what doesn't (so we know
; what's data and what isn't).  This will, of course, completely fuck up if
; the program is overlaid (although we will probably get some useful
; information), and if there are any JMPs or JSRs through registers or
; dispatch tables, we aren't going to be able to chase them down (well, I
; suppose we could if we actually single-stepped through the entire program,
; but I'm too lazy to do that and besides the program might be doing something
; nasty).  Okay, so we'll start disassembling at the transfer address
; (contents of location 40 or value specified with /T switch), and each time
; we come to a conditional branch or a subroutine call, we'll try both
; branches (that's how this is recursive).  Each time we read a word to
; disassemble with PEEK, a bit gets set in BITMAP to remember that this word
; gets executed.  We will stop pursuing a branch if we reach either 1. a HALT
; (!) or EMT 350 instruction, [2. any undefined instruction,] 3. an RTS
; instruction, 4. a JMP or JSR which uses something other than relative or
; absolute mode, 5. anything outside of the range [START,END], or 6. any place
; we've been before, according to BITMAP (otherwise we'd hang on the first
; loop we came across).  On the trace pass, a bit is set in INSBND for the
; first word of each instruction, so we know where labels are possible (not
; between words in a multi-word instruction).
;
;-
	call	rewmac		;see if .MAC input file exists
	tstb	rmflg		;does it?
	bne	macinp		;yes, use it
	; use supplied switches (or defaults) to do whole .SAV file
	mov	xfer,tval	;set up /T switch if not already done
	movb	#1,tflg
	clrb	trash		;really write it
	movb	#1,sflg		;always specify /S and /E
	movb	#1,eflg
	mov	start,sval	;copy values in case defaulted
	mov	end,eval
	call	comswt		;write cmd line switch(es) in a comment blk
	comb	trash		;no output on first pass
	mov	xfer,r5		;point at transfer addr
	call	bitnum		;get corresponding bit
	bis	r0,symtab(r5)	;this gets a symbol (START)
	mov	ppc,r5		;get starting address
	call	trace		;call recursive routine
	call	disasm		;disassemble range
	.out	t$end		;".end<tab>start"
done:	; finished with disassembly
	call	wrmac		;flush last buffer to .MAC output file
	.close	#0		;.CSIGEN bug, no longer closes files in V5.X
				;(in spite of V4.0 documentation)
	jmp	csi		;reprompt
;+
;
; If a .MAC input file was specified, things are different.  Instead of
; disassembling the whole input file, we copy the .MAC file through to the
; output and only disassemble when we find a line starting with *, which
; contains another CSI command line with a similar syntax to our .CSIGEN line
; but no filenames.
;
; */T:transfer/S:start/E:end/B:base[:offset]/I/U
;
; /S and /E are only useful with /I, which means to insert a disassembled
; block of code in the output file in place of the '*' line.
;
;-
macinp:	mov	base,-(sp)	;save initial base/offset values
	mov	offset,-(sp)
	movb	#377,trash	;no output on first pass
	call	rdline		;find first "*" line, parse switches
	bcs	60$		;haven't they heard of PIP?!
	tstb	sflg		;this sets global start/end values
	beq	10$
	 mov	sval,gstart
10$:	tstb	eflg
	beq	20$
	 mov	eval,gend
20$:	mov	gstart,xfer	;assume we know nothing
	tstb	tflg		;transfer addr specified?
	beq	30$
	 mov	tval,xfer	;yes
30$:	br	50$		;go process, and pass the line through
40$:	; first pass, find and search all addresses specified with /T
	call	rdline		;copy lines through until we find a "*" line
	bcs	60$		;EOF
50$:	tstb	tflg		;/T flag given?
	beq	40$		;no
	mov	tval,r5		;get starting address
	call	bitnum		;get corresponding bit
	bis	r0,symtab(r5)	;this gets a symbol
	mov	tval,r5		;get starting address again
	call	trace		;trace range
	br	40$
60$:	call	rewmac		;rewind .MAC file again
	clrb	trash		;now write output for real
	mov	(sp)+,offset	;restore initial base/offset values
	mov	(sp)+,base
70$:	; second pass, copy input .MAC file, inserting disassembled blocks as
	; required
	call	rdline		;copy lines through until we find a "*" line
	bcs	done		;done
	tstb	iflg		;/I flag given?
	beq	80$		;no, perhaps new base/offset, pass through
	tstb	sflg		;they should have given both /S and /E
	beq	90$
	tstb	eflg
	beq	90$
	mov	sval,start	;fetch start/end values
	mov	eval,end
	clrb	sflg		;don't preserve /S/E
	clrb	eflg
	call	comswt		;pass switch(es) through, if any to save
	call	disasm		;include block
	br	70$		;around for more
80$:	call	outswt		;no /I, assume already in a comment block
	br	70$		;around for more
90$:	mov	#ireqse,r0	;/I requires /S and /E
asterr:	; error with line starting with asterisk, R0=.ASCIZ message
	.print			;print message
;; really ought to give line number
	.purge	#0		;flush output file
	jmp	csi		;outta here (purge I/O, reset stack)
;+
;
; Tracer.  See discussion above.
;
; r5	starting virtual address
;
;-
trace:	mov	r5,r4		;save R5
	call	bitnum		;get bit pattern
	bit	r0,bitmap(r5)	;have we been here before?
	bne	20$		;yes, don't loop
	bis	r0,insbnd(r5)	;start of an instruction
	mov	r4,r5		;no, restore R5
	call	peek		;get an opcode
	bcs	20$		;error, return
	tst	r0		;HALT instruction?
	beq	20$		;yes, return
	cmp	r0,#emt!350	;.EXIT (RT-11)?
	beq	20$		;yes, return
; This, of course, depends on the RTS (or OS) which the file is to run on, but
; it's a .SAV file, so it would be pretty useless anywhere but on RT-11.
	call	dis1		;disassemble the instruction
	tstb	jmpflg		;is it a branch of some kind?
	beq	trace		;no, get next instruction
	bmi	10$		;unconditional, follow only one branch
	tstb	adrflg		;where was it to?
	beq	trace		;dunno, follow only other branch
	mov	r5,-(sp)	;save r5
	mov	addr,r5		;get destination
	call	trace		;scope it out (recurse)
	mov	(sp)+,r5	;restore PC
	br	trace		;loop
10$:	mov	addr,r5		;get address to go to
	tstb	adrflg		;is it valid?
	bne	trace		;yes, loop
20$:	rts	pc		;no, return
;+
;
; Disassemble the range from START to END and add it to the output file.
;
; BITMAP/SYMTAB assumed set up by TRACE.
;
;-
disasm:	mov	start,r5	;start at begn of range
	clrb	trash		;for real this time
	mov	r5,ppc		;save location counter
10$:	call	bitnum		;get corresponding bit
	bit	r0,symtab(r5)	;does it get a symbol?
	beq	20$		;no, skip
	mov	ppc,r0		;get addr
	call	prlab		;print label
	.out	colon		;print ":"
20$:	.out	tab		;print tab
	mov	ppc,r5		;restore ptr
	call	bitnum		;get bit
	bit	r0,bitmap(r5)	;is it ever executed?
	bne	30$		;yes, skip
	.out	t$word		;print ".word"<tab>
	mov	ppc,r5		;restore ptr
	call	peek		;read a word
	call	huh		;print its value
	br	40$		;skip
30$:	mov	ppc,r5		;restore ptr
	call	dis		;do an instruction
40$:	mov	r5,ppc		;save
	cmp	r5,end		;off end of range?
	blos	10$		;no, loop
	rts	pc
;
dis:	; disassemble instruction at (R5)
	call	peek		;get opcode
dis1:	clr	jmpflg		;clear ADRFLG and JMPFLG
	mov	r0,-(sp)	;save
	mov	#inslst,r2	;point at instruction list
10$:	mov	(sp),r1		;get opcode back
	bic	(r2)+,r1	;clear operand bits
	cmp	r1,(r2)+	;compare to expected result
	beq	20$		;this is it -- go print
	add	#4+2,r2		;skip name, CALL addr
	br	10$		;loop until found (always finds .WORD)
20$:	mov	r1,-(sp)	;save
	mov	r5,-(sp)
	mov	#numbuf,r5	;point at buf
	mov	(r2)+,r0	;get first half of string
	mov	r2,-(sp)	;save
	call	rad$		;convert first half
	mov	(sp)+,r2	;restore
	mov	(r2)+,r0	;get second half of string
	mov	r2,-(sp)	;save again
	call	rad$		;convert second half
	clrb	(r5)		;mark end
	.out	numbuf		;write the string
	mov	(sp)+,r2	;restore
	mov	(sp)+,r5
	mov	(sp)+,r1
	bit	#1,(r2)		;byte flag set?
	beq	30$		;no byte version of instr, skip
	tst	(sp)		;byte bit set?
	bpl	30$		;no, word
	.out	b		;print 'b'
	bic	#100000,(sp)	;chop off high bit
30$:	mov	(r2),r2		;get operand types (addr of routine)
	bic	#1,r2		;clear low bit
	bne	40$		;go print them
	tst	(sp)+		;no operands, clear stack
	jmp	crlf		;print <CRLF> and return
40$:	cmp	r2,#chgflg	;SEx or CLx?
	beq	50$		;yes, don't print tab
	.out	tab		;print '	'
50$:	mov	(sp)+,r0	;get opcode back
	jmp	(r2)		;jump to the appropriate routine
;
op0.5:	; half operand (one register)
	cmp	r1,#200		;RTS instruction?
	bne	10$		;no
	comb	jmpflg		;yes, unconditional jump, no valid ADDR
10$:	call	prreg		;print the register
	jmp	crlf		;print <CRLF> and return
;
op1:	; single operand
	cmp	r1,#100		;JMP instruction?
	bne	10$		;no
	comb	jmpflg		;yes, unconditional jump
	incb	adrflg		;valid address
10$:	cmp	r1,#4700	;JSR PC ("CALL") instruction?
	bne	20$		;no
	incb	jmpflg		;yes, conditional jump (we'll be back later)
	incb	adrflg		;valid address
20$:	call	proper		;print the operand
	jmp	crlf		;print <CRLF> and return
;
op1.5:	; 1-1/2 operand (reg,operand)
	cmp	r1,#4000	;JSR?
	bne	10$		;no
	incb	jmpflg		;yes, conditional jump (we'll be back later)
	incb	adrflg		;valid address
10$:	mov	r0,-(sp)	;save opcode
	asl	r0		;left 2
	asl	r0
	swab	r0		;and right 8, get register field into <2:0>
	call	prreg		;print it
	.out	comma		;print ","
	mov	(sp)+,r0	;get opcode back
	call	proper		;print the operand
	jmp	crlf		;print <CRLF> and return
;
op2:	; two operand
	mov	r0,-(sp)	;save opcode
	asl	r0		;left 2
	asl	r0
	swab	r0		;and right 8, get source into <5:0>
	call	proper		;print it
	.out	comma		;print ","
	mov	(sp)+,r0	;get other operand
	call	proper		;print it
	jmp	crlf		;print <CRLF> and return
;
branch:	; BRanch instruction
	cmp	r1,#400		;just BR (unconditional)?
	bne	10$		;no, skip
	comb	jmpflg		;remember this
	br	20$		;skip
10$:	incb	jmpflg		;conditional branch
20$:	movb	r0,r0		;sign extend
	asl	r0		;multiply by 2 (word)
	add	r5,r0		;add in current PC (instr addr +2)
	call	prlab		;print resulting address
	incb	adrflg		;valid address
	jmp	crlf		;print <CRLF> and return
;
muldiv:	; multiply or divide (or ASH[C])
	mov	r0,-(sp)	;save opcode
	call	proper		;print source
	.out	comma		;print ","
	mov	(sp)+,r0	;get opcode back
	asl	r0		;left 2
	asl	r0
	swab	r0		;and right 8 to get register into <2:0>
	call	prreg		;print destination
	jmp	crlf		;print <CRLF> and return
;
trpemt:	; TRAP or EMT
	bic	#^C377,r0	;isolate low 8
	call	prbyte		;print the low byte
	jmp	crlf		;print <CRLF> and return
;
decbra:	; SOB instruction
	mov	r0,-(sp)	;save R0
	asl	r0		;left 2
	asl	r0
	swab	r0		;and right 8 to get reg into <2:0>
	call	prreg		;print it
	.out	comma		;print ","
	mov	(sp)+,r1	;restore
	bic	#^C77,r1	;isolate
	asl	r1		;*2
	mov	r5,r0		;copy location counter
	sub	r1,r0		;calculate destination address
	call	prlab		;print it
	incb	adrflg		;valid address
	incb	jmpflg		;conditional branch
	jmp	crlf		;<CRLF> and return
;
fop1:	; fdst
	call	pfoper		;print the operand
	jmp	crlf		;<CRLF> and return
;
fop2a:	; fsrc,AC
	mov	r0,-(sp)	;save
	call	pfoper		;print source
	.out	comma		;","
	mov	(sp)+,r0	;restore
	call	prac		;print AC
	jmp	crlf		;<CRLF>, return
;
fop2b:	; AC,fdst
	mov	r0,-(sp)	;save
	call	prac		;print AC
	.out	comma		;","
	mov	(sp)+,r0	;restore
	call	pfoper		;fdst
	jmp	crlf		;<CRLF>, return
;
fop2c:	; src,AC
	mov	r0,-(sp)	;save
	call	proper		;src
	.out	comma		;","
	mov	(sp)+,r0	;restore
	call	prac		;AC
	jmp	crlf		;<CRLF>, return
;
fop2d:	; AC,dst
	mov	r0,-(sp)	;save
	call	prac		;AC
	.out	comma		;","
	mov	(sp)+,r0	;restore
	call	proper		;dst
	jmp	crlf		;<CRLF>, return
;
setpri:	; SPL instruction (which Digby doesn't have).  oh well.
	bic	#^C7,r0		;isolate prio level
	add	#'0,r0		;convert to ASCII
	mov	r0,-(sp)	;save on stack
	mov	sp,r0		;pt at it
	call	out		;print it (check TRASH)
	tst	(sp)+		;clear stack
	jmp	crlf		;<CRLF>, return
;
chgflg:	; SEx, CLx
	mov	#flgnam,r1	;point at flags' names
	mov	#4,r2		;number of flags
	mov	r3,-(sp)	;save R3
	mov	r5,-(sp)	;and R5
	clr	r3		;nothing printed yet
	mov	r0,r5		;copy opcode into R5
10$:	ror	r5		;rotate a bit into C
	bcc	30$		;clear, continue
	tst	r3		;comma needed?
	beq	20$		;no
	.out	comma		;yes, print it
20$:	movb	(r1),r0		;get flag name
	mov	r0,-(sp)	;put on stack
	mov	sp,r0		;point at it
	call	out		;print it
	tst	(sp)+		;clear stack
	inc	r3		;set comma flag
30$:	inc	r1		;inc ptr
	dec	r2		;checked all flags?
	bne	10$		;no
	mov	(sp)+,r5	;[restore R5]
	mov	(sp)+,r3	;[and R3]
	jmp	crlf		;yes, <CRLF>, return
;
; Inline forms of CIS instructions:
;
cis1.5:	; one descriptor, one immediate value
	call	crlf		;EOL
	br	cis2a
;
cis2:	; two descriptors
	call	crlf		;EOL
	br	cis3a
;
cis2.5:	; two descriptors, one immediate value
	call	crlf		;EOL
	call	cisd		;descriptor
cis2a:	call	cisd		;descriptor
	br	cisi		;immed value, return
;
cis3:	; three descriptors
	call	crlf		;EOL
	call	cisd		;descriptor
cis3a:	call	cisd		;descriptor
	br	cisd		;descriptor, return
;
cis4:	; MOVTCI
	; two descriptors, immed value, table address
	call	cis2.5		;start it off
	;br	cisd		;treat table addr as descriptor, return
;
cisd:	; display descriptor pointer
	mov	r5,-(sp)	;save
	call	bitnum		;get corresponding bit
	bit	r0,symtab(r5)	;does it get a symbol?
	beq	10$		;no, skip
	mov	ppc,r0		;get addr
	call	prlab		;print label
	.out	colon		;print ":"
10$:	.out	tab		;print tab
	.out	space		;indent
	.out	t$word		;print ".word"<tab>
	mov	(sp)+,r5	;restore
	call	peek		;read a word
	call	prlab		;print its value as a label
	jmp	crlf		;CRLF, return
;
cisi:	; display immediate value (fill char, etc.)
	mov	r5,-(sp)	;save
	call	bitnum		;get corresponding bit
	bit	r0,symtab(r5)	;does it get a symbol?
	beq	10$		;no, skip
	mov	ppc,r0		;get addr
	call	prlab		;print label
	.out	colon		;print ":"
10$:	.out	tab		;print tab
	.out	space		;indent
	.out	t$word		;print ".word"<tab>
	mov	(sp)+,r5	;restore
	call	peek		;read a word
	;br	huh		;print as immed value, return
;
huh:	; ??? undefined instruction
	call	prnum		;".word nnnnnn"
	mov	r0,-(sp)	;save value
	.out	cmnt		;"	;"
	mov	(sp),r0		;get value
	clr	r1		;no quotes yet
	call	huh1		;do low byte
	mov	(sp)+,r0	;get again
	swab	r0		;byte swap
	call	huh1		;do high byte
	clr	r2		;not in quotes anymore
	call	huh2		;print closing quote
	jmp	crlf		;see you around
;
huh1:	; do a char
	movb	r0,r0		;SXT
	mov	r0,-(sp)	;save
	cmp	r0,#40		;ctrl char?
	blo	10$		;yes
	cmp	r0,#176		;no, rubout or negative?
	bhi	10$		;yes
	cmp	r0,#140		;grave accent?
	beq	10$		;yes, MACRO is afraid of them
	mov	#1,r2		;make sure we're between quotes
	call	huh2		;(print one if nessa)
	mov	(sp)+,r0	;restore
	movb	r0,char		;no, put in buffer
	mov	#char,r0	;point at it
	jmp	out		;print, return
10$:	clr	r2		;make sure we aren't between quotes
	call	huh2		;(print a closing one)
	.out	lt		;"<"
	mov	(sp)+,r0	;restore
	call	prbyte		;print value
	mov	#gt,r0		;">"
	jmp	out		;print it, return
;
huh2:	; print a quote if R1<>R2
	cmp	r1,r2		;equal?
	beq	10$		;yes
	.out	quote		;no, print a quote
	mov	r2,r1		;update flag
10$:	rts	pc
;
proper:	; print operand in R0 <5:0>
	bic	#^C77,r0	;isolate
	mov	r0,-(sp)	;save R0
	bic	#70,r0		;mask out <5:3>
	cmp	r0,#7		;reg=PC?
	beq	pcoper		;PC gets special treatment
	mov	(sp),r0		;get back operand
	bic	#7,r0		;mask out register
prop1:	tst	r0		;mode 0?
	bne	10$		;no, continue
	mov	(sp)+,r0	;get register number
	jmp	prreg		;print register and return
10$:	cmp	r0,#10		;mode 1?
	bne	20$		;no, continue
	mov	(sp)+,r0	;get reg number
	jmp	prrgp		;print "(reg)"
20$:	cmp	r0,#20		;mode 2?
	bne	40$		;no, continue
30$:	mov	(sp)+,r0	;get reg number
	call	prrgp		;print "(reg)"
	mov	#plus,r0	;print "+"
	jmp	out		;and return
40$:	cmp	r0,#30		;mode 3?
	bne	50$		;no, continue
	.out	at		;print "@"
	br	30$		;continue as if mode=2
50$:	cmp	r0,#40		;mode 4?
	bne	70$		;no, continue
60$:	.out	minus		;print "-"
	mov	(sp)+,r0	;get reg number
	jmp	prrgp		;print "(reg)" and return
70$:	cmp	r0,#50		;mode 5?
	bne	80$		;no, continue
	.out	at		;print "@"
	br	60$		;continue as if mode=4
80$:	cmp	r0,#60		;mode 6?
	bne	100$		;no, must be mode 7
90$:	call	peek		;get index address
	call	prlab		;print it
	mov	(sp)+,r0	;get reg number
	jmp	prrgp		;print "(reg)" and return
100$:	.out	at		;print "@"
	br	90$		;print "######(reg)"
;
pcoper:	; handle special interpretations of modes 27, 37, 67, and 77
	mov	(sp),r0		;get opcode
	bic	#^C70,r0	;isolate mode
	cmp	r0,#20		;immediate?
	bne	20$		;no, continue
10$:	tst	(sp)+		;clear stack
	.out	number		;print "#"
	call	peek		;get operand
	jmp	prlab		;print label, return
20$:	cmp	r0,#30		;absolute?
	bne	30$		;no, continue
	tst	(sp)+		;clear stack
	movb	r0,adrflg	;set flag in case of JMP or JSR
	.out	at		;print "@#"
	.out	number
	call	peek		;get operand
	jmp	prlab		;print it
30$:	cmp	r0,#60		;relative?
	bne	50$		;no, continue
	movb	r0,adrflg	;set flag in case of JMP or JSR
40$:	tst	(sp)+		;clear stack
	call	peek		;get index
	add	r5,r0		;add on value of PC
	jmp	prlab		;print resulting address and return
50$:	cmp	r0,#70		;relative deferred?
	bne	60$		;no, go treat it normally
	.out	at		;print "@"
	br	40$		;print index
60$:	jmp	prop1		;go treat it like a normal register
;
pfoper:	; print FP operand in R0 <5:0>
	bic	#^C77,r0	;isolate
	bit	#70,r0		;mode 0?
	beq	prfpac		;yes, print "Fn"
	jmp	proper		;no, print normal operand
;
prrgp:	; print reg in R0 with parenthesis around it
	mov	r0,-(sp)	;save R0
	.out	leftp		;print "("
	mov	(sp)+,r0	;get number back
	call	prreg		;print reg name
	.out	rightp		;print ")"
	rts	pc		;return
;
prreg:	; print reg whose number is in R0
	bic	#^C7,r0		;isolate
	cmp	r0,#6		;pc or sp?
	blo	20$		;no, go print "r#"
	bne	10$		;go print "pc"
	mov	#sptext,r0	;print "sp"
	jmp	out		;and return
10$:	mov	#pctext,r0	;print "pc"
	jmp	out		;and return
20$:	add	#'0,r0		;convert to ASCII
	movb	r0,rtext+1	;put in buffer
	mov	#rtext,r0	;print "r#"
	jmp	out		;and return
;
prfpac:	; print FP accumulator whose # is in R0 <2:0>
	bic	#^C7,r0		;isolate
prac1:	add	#'0,r0		;cvt to ASCII
	movb	r0,actxt+1	;put in buffer
	mov	#actxt,r0	;print
	jmp	out		;and return
;
prac:	; print FP accumulator whose # is in R0 <7:6>
	asl	r0		;left 2
	asl	r0
	swab	r0		;and right 8 = net right 6 (get into <1:0>)
	bic	#^C3,r0		;isolate
	br	prac1		;jump into PRFPAC
;+
;
; Print <CRLF>.
;
;-
crlf:	mov	#crlf$,r0	;print <CRLF>
	;br	out		;do it, return
;+
;
; Write .ASCIZ string at (R0) to the output file if TRASH is not zero.
;
; R0 trashed, others preserved.
;
;-
out:	tstb	trash		;are we trashing output?
	bne	40$		;yes, return
	mov	r1,-(sp)	;save regs
	mov	r2,-(sp)
10$:	mov	wptr,r1		;get ptr
	mov	wcnt,r2		;space remaining
20$:	movb	(r0)+,(r1)+	;copy
	beq	30$		;end of string
	dec	r2		;buffer full?
	bne	20$		;loop if not
	mov	r0,-(sp)	;save R0
	mov	r1,wptr		;update ptr
	call	wrmac		;flush output buffer
	mov	(sp)+,r0	;restore
	br	10$		;around for more
30$:	dec	r1		;correct ptr
	mov	r1,wptr		;update
	mov	r2,wcnt
	mov	(sp)+,r2	;restore regs
	mov	(sp)+,r1
40$:	rts	pc
;
prlab:	; print R0 as a label, if its bit is set in INSBND;
	; otherwise print in octal
	mov	r0,addr		;save in case it's important
	mov	r5,-(sp)	;save regs
	mov	r0,-(sp)
	cmp	r0,start	;in range?
	blo	30$		;no
	cmp	r0,end		;hm?
	bhi	30$		;no
	mov	r0,r5		;yes, copy
	call	bitnum		;get bit #
	tstb	trash		;pass one?
	bne	10$		;yes, set SYMTAB bit
	bit	r0,bitmap(r5)	;is it an instruction?
	beq	10$		;no, give it a label
	bit	r0,insbnd(r5)	;yes, is it the begn of one?
	beq	30$		;no, print it in octal
10$:	bis	r0,symtab(r5)	;make mark in table
	mov	(sp)+,r0	;restore R0
	cmp	r0,xfer		;START?
	beq	20$		;yes, never mind
	mov	#'L,r5		;use L or M for high bit
	br	prnum2		;print the number, return
20$:	.out	strt		;print "START"
	mov	(sp)+,r5	;restore
	rts	pc
30$:	mov	(sp)+,r0	;restore
	br	prnum1		;print in octal
;
prnum:	; print R0 in octal
	mov	r5,-(sp)	;save R5
prnum1:	mov	#'0,r5		;octal, not symbolic
prnum2:	call	proct		;print it
	mov	(sp)+,r5	;restore
	rts	pc
;
proct:	; print R0 in octal, using char in R5 as char for high bit
	mov	r0,addr		;save in case it's important
	mov	r0,-(sp)	;save regs
	mov	r1,-(sp)
	mov	r2,-(sp)
	mov	r3,-(sp)
	mov	#numbuf+6,r1	;point at end of buffer
	mov	#5,r3		;loop counter
10$:	mov	r0,r2		;put # in R2
	bic	#^C7,r2		;isolate low 3
	bis	#'0,r2		;convert to ASCII
	movb	r2,-(r1)	;put in buffer
	asr	r0		;right 3
	asr	r0
	asr	r0
	dec	r3		;done all digits?
	bne	10$		;loop if not
	asr	r0		;shift highest bit into C
	adc	r5		;R5+1 if 1
	movb	r5,-(r1)	;put in buffer
	.out	numbuf		;print number
	mov	(sp)+,r3	;restore regs
	mov	(sp)+,r2
	mov	(sp)+,r1
	mov	(sp)+,r0
	rts	pc		;return
;
prbyte:	; print lower byte of R0 in octal
	mov	r0,-(sp)	;save regs
	mov	r1,-(sp)
	mov	r2,-(sp)
	mov	r0,r1		;copy out of the way
	mov	#numbuf+6,r0	;point at end of buffer
10$:	mov	r1,r2		;copy
	bic	#^C7,r2		;isolate
	bis	#'0,r2		;convert to ASCII, C=0
	movb	r2,-(r0)	;[save in buf]
	rorb	r1		;right a bit (C=0 from BIS above)
	rorb	r1
	rorb	r1
	cmp	r0,#numbuf+3	;done 3 digits?
	bhi	10$		;loop if not
	call	out		;print it
	mov	(sp)+,r2	;restore regs
	mov	(sp)+,r1
	mov	(sp)+,r0
	rts	pc		;return
;+
;
; Routine to convert a word from .RAD50 to .ASCII using a variation of the BCD
; method used by the TSS/8 System Interpreter to convert decimal numbers on
; the PDP-8 (with no DIV instruction).
;
; r0	number
; r5	buffer (updated on return)
;
;-
rad$:	mov	#r50bit,r3	;pt at table
	br	40$		;jump into loop
10$:	; next digit
	clr	r4		;clear it
	mov	#6,r2		;bit count (each .RAD50 dig is 5.625 bits)
20$:	asl	r4		;*2
	cmp	r1,r0		;OK?
	bhi	30$		;no (C=0)
	sub	r1,r0		;remove the bit (C=0)
	inc	r4		;[count it]
30$:	ror	r1		;/2 (C=0 either way above)
	dec	r2		;done all bits?
	bne	20$		;loop if not
	movb	r50(r4),r4	;convert
	beq	40$		;blank, ignore
	 movb	r4,(r5)+	;save
40$:	mov	(r3)+,r1	;get next value
	bne	10$		;loop if non-zero
	movb	r50(r0),r4	;convert last
	beq	50$		;blank, ignore
	 movb	r4,(r5)+	;save
50$:	rts	pc
;+
;
; Routine to return word at virtual address in R5.  Result in R0, R5 is
; incremented by 2.  Returns with C set on error.
;
;-
peek:	mov	r1,-(sp)	;save
	mov	r2,-(sp)
	cmp	r5,gstart	;before START?
	blo	60$		;yes, error
	cmp	r5,gend		;after end?
	bhi	60$		;yes, error
	mov	r5,r1		;copy addr
	tstb	trash		;on pass 2?
	beq	10$		;yes, don't set bit
	call	bitnum		;find bit in BITMAP
	bis	r0,bitmap(r5)	;set it
	mov	r1,r5		;restore R5
10$:	mov	r1,r2		;copy
	asr	r2		;right 9 bits
	swab	r2
	bic	#^C177,r2	;isolate block
	bic	#^C777,r1	;isolate offset within block
	add	base,r2		;add base block of memory image
	add	offset,r1	;and offset
	bit	#^C777,r1	;carry?
	beq	20$
	inc	r2		;yes
	bic	#^C777,r1	;trim again
20$:	cmp	r2,rblk		;is this block already loaded?
	beq	30$		;yes, great
	mov	r2,rblk		;it will be in a second
	mov	#rarea,r0	;point at EMT arg blk
	.readw			;read a block
	bcs	50$		;error, gack
30$:	mov	rbuf(r1),r0	;get the word
	add	#2,r5		;inc ptr
	clc			;in case R5 was 177776
40$:	mov	(sp)+,r2	;[restore]
	mov	(sp)+,r1
	rts	pc
50$:	mov	#-1,rblk	;[don't get any ideas]
	br	40$		;return, C is already set
60$:	sec			;error, out range
	br	40$		;return
;+
;
; Find the bit in either bit map which corresponds to the address in R5.
;
; On return:
; r0	has the proper bit set
; r5	offset into bitmap of word to BIS/BIT
; Others preserved.
;
;-
bitnum:	mov	r5,r0		;copy byte addr
	asr	r5		;find word address
	asr	r5		;/16., *2 to get offset into table
	asr	r5
	asr	r5
	bic	#^C7776,r5	;isolate
	bic	#^C<17*2>,r0	;find bit number *2
	mov	bits(r0),r0	;look up bit
	rts	pc
;+
;
; Interpret switches parsed by CSI.
;
; Stack:
;	(stuff pushed by CSI)
; SP =>	return addr
;
; Saves values of /S/E/T/B switches in *VAL variables (BVAL is 2 words since
; /B can take two values), *FLG variables are set NZ if switch given.
;
;-
switch:	mov	(sp)+,r5	;catch return addr
	clrb	bflg		;no switches yet
	clrb	eflg
	clrb	iflg
	clrb	sflg
	clrb	tflg
	clrb	uflg
	mov	(sp)+,r4	;get switch count
	beq	110$		;no switches, use defaults
10$:	mov	(sp)+,r0	;get a switch
	bpl	20$		;no value given
	 mov	(sp)+,r1	;get value
20$:	cmpb	r0,#'?		;/? ?
	beq	50$		;help
	bicb	#40,r0		;convert to UC if LC
	cmpb	r0,#'B		;/B:block[:offset] ?
	beq	30$		;set base block # (or offset) in file
	cmpb	r0,#'E		;/E:addr ?
	beq	40$		;set end of range
	cmpb	r0,#'H		;/H ?
	beq	50$		;help
	cmpb	r0,#'I		;/I ?
	beq	60$		;insert disassembled block
	cmpb	r0,#'S		;/S:addr ?
	beq	70$		;set start of range
	cmpb	r0,#'T		;/T:addr ?
	beq	80$		;set transfer addr
	cmpb	r0,#'U		;/U ?
	beq	90$		;upper case output
	.print	#badsw		;none of the above, print message
	.purge	#0		;flush output file
	jmp	csi		;outta here (purge I/O, reset stack)
30$:	; /B:block[:offset]
	tst	r0		;value given?
	bpl	100$		;no
	mov	bval,bval+2	;any previous value was offset (/B:blk:offs)
	bic	#1,bval+2	;(must be even)
	mov	r1,bval		;set starting block #
	movb	#1,bflg		;remember that switch was given
	br	100$
40$:	; /E:endaddr
	tst	r0		;value given?
	bpl	100$		;no
	mov	r1,eval		;set ending addr
	movb	#1,eflg		;remember that switch was given
	br	100$		;skip
50$:	; /Help
	call	progid		;print program ID
	.print	#help		;print msg (will seem odd if in .MAC file!)
	br	100$		;skip
60$:	; /Insert (intended for use in input .MAC file only)
	movb	#1,iflg		;remember that switch was given
	br	100$		;skip
70$:	; /S:startaddr
	tst	r0		;value given?
	bpl	100$		;no
	bic	#1,r1		;force even
	mov	r1,sval		;set starting addr
	movb	#1,sflg		;remember that switch was given
	br	100$		;skip
80$:	; /T:xfraddr
	tst	r0		;value given?
	bpl	100$		;no
	bic	#1,r1		;force even
	mov	r1,tval		;set address to start bitmap at
	movb	#1,tflg		;remember that switch was given
	br	100$		;skip
90$:	; /Uppercase
	movb	#1,uflg		;remember that switch was given
100$:	dec	r4		;loop through all switches
	bne	10$
110$:	; update base/offset if /B was given
	tstb	bflg		;/B specified?
	beq	120$
	mov	bval,base	;get values
	mov	bval+2,offset
120$:	; output source in upper case if /U was given
	tstb	uflg		 ;/U specified?
	beq	150$
	mov	#ucbeg,r1	;point at begn of range
130$:	movb	(r1)+,r0	;get a char
	cmp	r0,#'a		;lower case?
	blo	140$
	cmp	r0,#'z
	bhi	140$
	bicb	#40,-1(r1)	;yes, convert to upper
140$:	cmp	r1,#ucend	;done all?
	blo	130$		;loop if not
150$:	jmp	(r5)		;return
;
; Write out the current set of switches, inside a comment block.
;
;-
comswt:	movb	bflg,r0		;see if anything specified
	bisb	eflg,r0
	bisb	sflg,r0
	bisb	tflg,r0
	bisb	uflg,r0
	beq	10$		;no
	.out	rem		;start off
	call	outswt		;write switches
	.out	remend		;end of string
10$:	rts	pc
;+
;
; Write out the current set of switches (/B and/or /T).
;
; /S, /E, and /I are not passed through since we don't want to insert the same
; block next time through.
;
;-
outswt:	movb	bflg,r0		;see if anything specified
	bisb	eflg,r0
	bisb	sflg,r0
	bisb	tflg,r0
	bisb	uflg,r0
	beq	60$		;no
	.out	astrsk		;start off
	tstb	bflg		;/B given?
	beq	10$		;no
	.out	slab		;/B:
	mov	base,r0		;get block #
	call	prnum
	.out	colon		;:
	mov	offset,r0	;get offset within block
	call	prnum
10$:	tstb	sflg		;/S given?
	beq	20$		;no
	.out	slas		;/S:
	mov	sval,r0		;get starting addr
	call	prnum
20$:	tstb	eflg		;/E given?
	beq	30$		;no
	.out	slae		;/E:
	mov	eval,r0		;get ending addr
	call	prnum
30$:	tstb	tflg		;/T given?
	beq	40$		;no
	.out	slat		;/T:
	mov	tval,r0		;get transfer address
	call	prnum
40$:	tstb	uflg		;/U given?
	beq	50$		;no
	.out	slau		;/U
50$:	call	crlf		;<CRLF>
60$:	rts	pc
;+
;
; Print program ID.
;
; R0 destroyed, others preserved.
;
;-
progid:	.print	#header		;print prog ID
.if nz rsts
	; display system ID as part of version banner (RSTS style)
	clr	r0		;print system ID
	.errprt
	.print	#terpri		;<CRLF>
.endc
	rts	pc
;+
;
; Rewind .MAC input file (if any) (start first read).
;
;-
rewmac:	clrb	rmflg		;assume no .MAC file to read
	clrb	rdeof		;no EOF yet
	clr	line		;init line #
	.wait	#4		;make sure it exists
	bcs	10$		;no
	clr	rmblk		;init block #
	mov	#rmbuf,rmba	;init buffer
	mov	#rmbuf+macin,rmoth ;init "other" buffer
	mov	#macin/2,rmwc	;word count
	mov	#rmarea,r0	;point at EMT area
	.read			;start first read
	bcs	20$		;failed
	mov	r0,rmewc	;save expected WC
	comb	rmflg		;.MAC input file exists
10$:	rts	pc
20$:	tst	r0		;EOF?
	bne	rmerr
	incb	rdeof		;yes, easy
	sec
	rts	pc
rmerr:	.print	#rerr		;error msg
	.purge	#0		;flush output file
	jmp	csi		;bomb
;+
;
; Read next buffer from .MAC input file.
;
; C=1 on EOF, otherwise:
; r5	addr of buffer
; r4	# bytes in buffer
;
;-
rdmac:	tstb	rdeof		;EOF last time?
	bne	20$
	.wait	#4		;wait for previous read to finish
	bcs	rmerr		;error
	mov	rmba,r5		;get buf addr
	mov	rmewc,r4	;get expected word count
	asl	r4		;*2 => byte count
	add	#macin/512.,rmblk ;update blk # for next read
	mov	rmoth,rmba	;switch buffers
	mov	r5,rmoth
	mov	r5,rptr		;save
	mov	r4,rcnt
	mov	#rmarea,r0	;point at EMT area
	.read			;read next bufferload
	bcs	10$		;error
	mov	r0,rmewc	;[save expected WC for next time]
	rts	pc		;C=0
10$:	tst	r0		;EOF?
	bne	rmerr		;no, print msg
	incb	rdeof		;report it next time
	rts	pc		;C=0 from TST
20$:	sec			;EOF
	rts	pc
;+
;
; Read next line from .MAC input file, copy to output if TRASH=0 and doesn't
; start with '*'.  If the line *does* start with '*', parse it with .CSISPC
; and call SWITCH.
;
; On return, C=1 if reached EOF, otherwise SWITCH's variables are set up.
;
;-
rdline:	tst	rcnt		;anything in buf?
	bne	10$		;yes, skip
	call	rdmac		;refill buf
	bcc	rdline		;loop
	rts	pc		;EOF
10$:	inc	line		;bump to new line #
	cmpb	@rptr,#'*	;starts with '*'?
	beq	70$		;yes
	; doesn't start with '*', copy to output if TRASH=0
	tstb	trash		;well?
	bne	60$		;just ignore the line
20$:	; copy input line directly to output
	movb	@rptr,r0	;get char
	beq	40$		;NUL, ignore
	movb	r0,@wptr	;save
	inc	wptr		;count it
	dec	wcnt
	bne	30$
	call	wrmac		;flush output buffer
	movb	@rptr,r0	;restore R0=char
30$:	cmp	r0,#lf		;EOL?  (CR already copied if so)
	beq	50$		;yes, skip
	cmp	r0,#ff		;(FF works too)
	beq	50$
40$:	inc	rptr		;eat the char
	dec	rcnt
	bne	20$		;loop
	call	rdmac		;read more
	bcc	20$		;loop on success
	rts	pc		;EOF, C=1
50$:	inc	rptr		;eat the LF
	dec	rcnt
	br	rdline		;get next line
60$:	; skip rest of input line
	cmpb	@rptr,#lf	;EOL?
	beq	50$
	cmpb	@rptr,#ff
	beq	50$
	inc	rptr		;eat the char if not
	dec	rcnt
	bne	60$
	call	rdmac		;read more
	bcc	60$		;loop on success
	rts	pc		;EOF, C=1
70$:	; line starts with '*', copy to LBUF
	mov	#lbuf,r5	;point at it
	br	90$		;eat the '*', copy line
80$:	movb	@rptr,r0	;get a char
	cmp	r0,#lf		;EOL?
	beq	100$
	cmp	r0,#ff
	beq	100$
	cmp	r0,#40		;space or ctrl char?
	blos	90$		;yes, ignore
	cmp	r5,#lbuf+80.	;buf full?
	beq	90$
	 movb	r0,(r5)+	;store char if not
90$:	inc	rptr		;eat the char
	dec	rcnt
	bne	80$		;loop
	mov	r5,-(sp)	;save ptr
	call	rdmac		;read more
	mov	(sp)+,r5	;[restore]
	bcc	80$		;loop
	br	110$		;skip
100$:	inc	rptr		;eat the LF
	dec	rcnt
110$:	clrb	(r5)		;mark EOL
	.csispc	#sbuf,#defext,#lbuf ;parse switches (ignore any filenames)
	bcs	120$		;error
	call	switch		;parse switches (use CALL/RTS not CALLR, stack
	clc			;is set up from CSI)
	rts	pc
120$:	mov	#synerr,r0	;error msg
	jmp	asterr
;+
;
; Write next buffer to .MAC output file.
;
; WPTR	char after last char written in current output buf
;
; R0, R1 destroyed, others preserved.
;
;-
wrmac:	tstb	wmflg		;is file open?
	beq	20$		;no, ignore output
	.wait	#0		;wait for previous write to finish
	bcs	wmerr		;error
	mov	wptr,r1		;get curr addr
	bit	#1,r1		;odd?
	beq	10$
	 clrb	(r1)+		;yes, pad with NUL (last buffer only)
10$:	mov	wmoth,r0	;get the buf we were using
	mov	wmba,wmoth	;switch buffers
	mov	r0,wmba
	sub	r0,r1		;find # bytes used
	beq	20$		;whoops, nothing to do
	ror	r1		;/2 to get WC (C=0 from SUB)
	mov	r1,wmwc		;set word count
	mov	#wmarea,r0	;point at EMT area
	.write			;start next write
	bcs	wmerr		;failed
	clrb	r1		;(clear low order)
	swab	r1		;convert to block count
	add	r1,wmblk	;update starting blk for next time
20$:	mov	wmoth,wptr	;reinit ptr/ctr
	mov	#macout,wcnt
	rts	pc
wmerr:	.print	#werr		;error msg
	.purge	#0		;flush output file
	jmp	csi		;bomb
;
	.sbttl	pure data
;
defext:	.rad50	/SAVMACMACMAC/	;3rd output file not used
;
header:	.ascii	/DISSAV/	;RSTS programs use a tab here
.if nz rsts
	.ascii	<ht>		;RSTS programs use a tab here
.iff
	.ascii	/ /		;but RT-11 programs use a blank
.endc
	.ascii	/V1.2/		;version #
.iif nz rsts,	.byte	ht,200	;tab, end of string
terpri:	.byte	0		;must follow header
;
forhlp:	.asciz	'Type /H or /? for help'
;
crlf$:	.byte	15,12,0
synerr:	.asciz	/?Syntax error/
ireqse:	.asciz	'?/I requires /S and /E too'
badsw:	.asciz	/?Bad switch/
werr:	.asciz	/?File write error/
rerr:	.asciz	/?File read error/
;
help:	.ascii	"By John Wilson <wilson@dbit.com>"<cr><lf>
	.ascii	"Copyright (C) 1998 by D Bit.  All rights reserved."<cr><lf>
	.ascii	"Distribution, modification, and use for any purpose is"
	.ascii	" allowed as long as"<cr><lf>
	.ascii	"source code is available which includes this notice."<cr><lf>
	.ascii	<cr><lf>
	.ascii	"Usage:"<cr><lf>
	.ascii	"*newsource[.MAC]=binary[.SAV][,oldsource.MAC]/switches"
	.ascii	<cr><lf>
	.ascii	<cr><lf>
	.ascii	"Switches:"<cr><lf>
	.ascii	"/S:start          Set starting virtual addr"<cr><lf>
	.ascii	"/E:end            Set ending virtual addr"<cr><lf>
	.ascii	"/T:transfer       Set virtual transfer addr"<cr><lf>
	.ascii	"/B:base[:offset]  Set starting file address of memory image"
	.ascii	<cr><lf>
	.ascii	"                  (BASE=starting block, OFFSET=offset in"
	.ascii	" that block"<cr><lf>
	.ascii	"/I                Insert block of code here (requires /S/E),"
	.ascii	" useful only"<cr><lf>
	.ascii	"                  within oldsource.MAC"<cr><lf>
	.ascii	"/U                Write source code in upper case"<cr><lf>
	.ascii	<cr><lf>
	.ascii	"output file:      Disassembled MACRO source"<cr><lf>
	.ascii	"input file #1:    Binary .SAV file"<cr><lf>
	.ascii	"input file #2:    MACRO source (N.B. default ext=.SAV) from"
	.ascii	" previous run,"<cr><lf>
	.ascii	"                  lines starting with '*' are more switches"
	.byte	0
;
	.even
bits:	; table of bits (saves an ASH in BITNUM)
	.word	000001,000002,000004,000010,000020,000040,000100,000200
	.word	000400,001000,002000,004000,010000,020000,040000,100000
;
r50bit:	.word	40*50*50,40*50,0 ;bits for probing number in RAD$
;
inslst:	; instruction list
	instr	000000,000000,<HALT  >,op0
	instr	000000,000001,<WAIT  >,op0
	instr	000000,000002,<RTI   >,op0
	instr	000000,000003,<BPT   >,op0
	instr	000000,000004,<IOT   >,op0
	instr	000000,000005,<RESET >,op0
	instr	000000,000006,<RTT   >,op0
	instr	000000,000007,<MFPT  >,op0
	instr	000077,000100,<JMP   >,op1
	instr	000007,000200,<RTS   >,op0.5
	instr	000007,000230,<SPL   >,setpri
	instr	000000,000240,<NOP   >,op0
	instr	000000,000257,<CCC   >,op0
	instr	000017,000240,<CL    >,chgflg
	instr	000000,000277,<SCC   >,op0
	instr	000017,000260,<SE    >,chgflg
	instr	000077,000300,<SWAB  >,op1
	instr	000377,000400,<BR    >,branch
	instr	000377,001000,<BNE   >,branch
	instr	000377,001400,<BEQ   >,branch
	instr	000377,002000,<BGE   >,branch
	instr	000377,002400,<BLT   >,branch
	instr	000377,003000,<BGT   >,branch
	instr	000377,003400,<BLE   >,branch
	instr	000077,004700,<CALL  >,op1
	instr	000777,004000,<JSR   >,op1.5
	instrb	100077,005000,<CLR   >,op1
	instrb	100077,005100,<COM   >,op1
	instrb	100077,005200,<INC   >,op1
	instrb	100077,005300,<DEC   >,op1
	instrb	100077,005400,<NEG   >,op1
	instrb	100077,005500,<ADC   >,op1
	instrb	100077,005600,<SBC   >,op1
	instrb	100077,005700,<TST   >,op1
	instrb	100077,006000,<ROR   >,op1
	instrb	100077,006100,<ROL   >,op1
	instrb	100077,006200,<ASR   >,op1
	instrb	100077,006300,<ASL   >,op1
	instr	000077,006400,<MARK  >,op1
	instr	000077,006500,<MFPI  >,op1
	instr	000077,006600,<MTPI  >,op1
	instr	000077,006700,<SXT   >,op1
	instr	000077,007000,<CSM   >,op1
	instr	000077,007200,<TSTSET>,op1
	instr	000077,007300,<WRTLCK>,op1
	instrb	107777,010000,<MOV   >,op2
	instrb	107777,020000,<CMP   >,op2
	instrb	107777,030000,<BIT   >,op2
	instrb	107777,040000,<BIC   >,op2
	instrb	107777,050000,<BIS   >,op2
	instr	007777,060000,<ADD   >,op2
	instr	000777,070000,<MUL   >,muldiv
	instr	000777,071000,<DIV   >,muldiv
	instr	000777,072000,<ASH   >,muldiv
	instr	000777,073000,<ASHC  >,muldiv
	instr	000777,074000,<XOR   >,op1.5
	; FIS
	instr	000007,075000,<FADD  >,op0.5
	instr	000007,075010,<FSUB  >,op0.5
	instr	000007,075020,<FMUL  >,op0.5
	instr	000007,075030,<FDIV  >,op0.5
	; CIS
	instr	000000,076020,<L2D0  >,op0
	instr	000000,076021,<L2D1  >,op0
	instr	000000,076022,<L2D2  >,op0
	instr	000000,076023,<L2D3  >,op0
	instr	000000,076024,<L2D4  >,op0
	instr	000000,076025,<L2D5  >,op0
	instr	000000,076026,<L2D6  >,op0
	instr	000000,076027,<L2D7  >,cis2
	instr	000000,076030,<MOVC  >,op0
	instr	000000,076031,<MOVRC >,op0
	instr	000000,076032,<MOVTC >,op0
	instr	000000,076040,<LOCC  >,op0
	instr	000000,076041,<SKPC  >,op0
	instr	000000,076042,<SCANC >,op0
	instr	000000,076043,<SPANC >,op0
	instr	000000,076044,<CMPC  >,op0
	instr	000000,076045,<MATC  >,op0
	instr	000000,076050,<ADDN  >,op0
	instr	000000,076051,<SUBN  >,op0
	instr	000000,076052,<CMPN  >,op0
	instr	000000,076053,<CVTNL >,op0
	instr	000000,076054,<CVTPN >,op0
	instr	000000,076055,<CVTNP >,op0
	instr	000000,076056,<ASHN  >,op0
	instr	000000,076057,<CVTLN >,op0
	instr	000000,076060,<L3D0  >,op0
	instr	000000,076061,<L3D1  >,op0
	instr	000000,076062,<L3D2  >,op0
	instr	000000,076063,<L3D3  >,op0
	instr	000000,076064,<L3D4  >,op0
	instr	000000,076065,<L3D5  >,op0
	instr	000000,076066,<L3D6  >,op0
	instr	000000,076067,<L3D7  >,cis3
	instr	000000,076070,<ADDP  >,op0
	instr	000000,076071,<SUBP  >,op0
	instr	000000,076072,<CMPP  >,op0
	instr	000000,076073,<CVTPL >,op0
	instr	000000,076074,<MULP  >,op0
	instr	000000,076075,<DIVP  >,op0
	instr	000000,076076,<ASHP  >,op0
	instr	000000,076077,<CVTLP >,op0
	instr	000000,076130,<MOVCI >,cis2.5
	instr	000000,076131,<MOVRCI>,cis2.5
	instr	000000,076132,<MOVTCI>,cis4
	instr	000000,076140,<LOCCI >,cis1.5
	instr	000000,076141,<SKPCI >,cis1.5
	instr	000000,076142,<SCANCI>,cis2
	instr	000000,076143,<SPANCI>,cis2
	instr	000000,076144,<CMPCI >,cis2.5
	instr	000000,076145,<MATCI >,cis2
	instr	000000,076150,<ADDNI >,cis3
	instr	000000,076151,<SUBNI >,cis3
	instr	000000,076152,<CMPNI >,cis2
	instr	000000,076153,<CVTNLI>,cis2
	instr	000000,076154,<CVTPNI>,cis2
	instr	000000,076155,<CVTNPI>,cis2
	instr	000000,076156,<ASHNI >,cis2.5
	instr	000000,076157,<CVTLNI>,cis2
	instr	000000,076170,<ADDPI >,cis3
	instr	000000,076171,<SUBPI >,cis3
	instr	000000,076172,<CMPPI >,cis2
	instr	000000,076173,<CVTPLI>,cis2
	instr	000000,076174,<MULPI >,cis3
	instr	000000,076175,<DIVPI >,cis3
	instr	000000,076176,<ASHPI >,cis2.5
	instr	000000,076177,<CVTLPI>,cis2
	; back to regular instructions
	instr	000000,076600,<MED   >,op0	;11/60 -- maint exam/depos
	instr	000077,076700,<XFC   >,op1	;11/60 -- ext func code (WCS)
	instr	000777,077000,<SOB   >,decbra
	instr	000377,100000,<BPL   >,branch
	instr	000377,100400,<BMI   >,branch
	instr	000377,101000,<BHI   >,branch
	instr	000377,101400,<BLOS  >,branch
	instr	000377,102000,<BVC   >,branch
	instr	000377,102400,<BVS   >,branch
	instr	000377,103000,<BCC   >,branch
	instr	000377,103400,<BCS   >,branch
	instr	000377,104000,<EMT   >,trpemt
	instr	000377,104400,<TRAP  >,trpemt
	instr	000077,106400,<MTPS  >,op1
	instr	000077,106500,<MFPD  >,op1
	instr	000077,106600,<MTPD  >,op1
	instr	000077,106700,<MFPS  >,op1
	instr	007777,160000,<SUB   >,op2
	; FP11 floating point
	instr	000000,170000,<CFCC  >,op0
	instr	000000,170001,<SETF  >,op0
	instr	000000,170002,<SETI  >,op0
	instr	000000,170003,<LDUB  >,op0	;11/60 -- load ubreak reg
	instr	000000,170004,<MNS   >,op0	;11/60 -- maint norm shift
	instr	000000,170005,<MPP   >,op0	;11/60 -- maint partial prod
	instr	000000,170011,<SETD  >,op0
	instr	000000,170012,<SETL  >,op0
	instr	000077,170100,<LDFPS >,op1
	instr	000077,170200,<STFPS >,op1
	instr	000077,170300,<STST  >,op1
	instr	000077,170400,<CLRF  >,fop1
	instr	000077,170500,<TSTF  >,fop1
	instr	000077,170600,<ABSF  >,fop1
	instr	000077,170700,<NEGF  >,fop1
	instr	000377,171000,<MULF  >,fop2a
	instr	000377,171400,<MODF  >,fop2a
	instr	000377,172000,<ADDF  >,fop2a
	instr	000377,172400,<LDF   >,fop2a
	instr	000377,173000,<SUBF  >,fop2a
	instr	000377,173400,<CMPF  >,fop2a
	instr	000377,174000,<STF   >,fop2b
	instr	000377,174400,<DIVF  >,fop2a
	instr	000377,175000,<STEXP >,fop2d
	instr	000377,175400,<STCFI >,fop2d
	instr	000377,176000,<STCFD >,fop2b
	instr	000377,176400,<LDEXP >,fop2c
	instr	000377,177000,<LDCIF >,fop2c
	instr	000377,177400,<LDCDF >,fop2a
	instr	177777,000000,<.WORD >,huh
;
astrsk:	.asciz	/*/		;start of CSI line
slab:	.asciz	'/B:'		;switches
slae:	.asciz	'/E:'
slas:	.asciz	'/S:'
slat:	.asciz	'/T:'
slau:	.asciz	'/U'
;
tab:	.asciz	<ht>
space:	.asciz	/ /
comma:	.asciz	/,/
leftp:	.asciz	/(/
rightp:	.asciz	/)/
at:	.asciz	/@/
plus:	.asciz	/+/
minus:	.asciz	/-/
colon:	.asciz	/:/
cmnt:	.asciz	<ht>/;/
char:	.asciz	/ /
quote:	.asciz	/'/
lt:	.asciz	/</
gt:	.asciz	/>/
;
	.sbttl	impure data (initialized but will change)
;
ucbeg:	; beginning of data to convert to upper case on /U
;
;;	.dsabl	lc		;uncomment this to make /U the default
;
t$word:	.asciz	/.word/<ht>	;undefined or unexecuted instructions
;
r50:	.ascii	<0>/abcdefghijklmnopqrstuvwxyz$.%0123456789/ ;lower case RAD50
;
rem:	.ascii	<ht>/.rem/<ht>	;beginning of comment block
				;(to hide CSI line from assembler)
remend:	.asciz	/!/<cr><lf>	;(also end of comment block)
;
t$end:	.asciz	<ht>/.end/<ht>/start/<cr><lf> ;start at initial entry point
b:	.asciz	/b/		;suffix for byte instructions
sptext:	.asciz	/sp/
pctext:	.asciz	/pc/
strt:	.asciz	/start/
flgnam:	.ascii	/cvzn/		;names of flags
;
rtext:	.asciz	/r /		;general register names
actxt:	.asciz	/f /		;FP-11A registers
;
ucend:	; end of data to convert to upper case on /U
	.enabl	lc		;in case there was a .DSABL LC above
;
	.even
rarea:	.byte	3,10	;.READW, channel 3
rblk:	.word	-1	;block number
	.word	rbuf	;buffer address
	.word	400	;word count
	.word	0	;no crtn;  implicit .WAIT
;
rmarea:	.byte	4,10	;.READ, channel 4
rmblk:	.word		;block number
rmba:	.word		;buffer address
rmwc:	.word		;word count
	.word	1	;no crtn;  .WAIT for completion
;
wmarea:	.byte	0,11	;.WRITE, channel 0
wmblk:	.word		;block number
wmba:	.word		;buffer address
wmwc:	.word		;word count
	.word	1	;no crtn;  .WAIT for completion
;
number:	.asciz	/#/
numbuf:	.asciz	/######/	;buffer for numbers and .RAD50 symbols
;
	.sbttl	pure storage
;
	.even
;
start:	.blkw		;start of range to disassemble
end:	.blkw		;end of range to disassemble
xfer:	.blkw		;STARTing address
ppc:	.blkw		;current pseudo program counter
base:	.blkw		;base block # in file (this blk contains addr 000000)
offset:	.blkw		;offset within block # BASE of addr 000000
;
gstart:	.blkw		;global start of valid range of file
gend:	.blkw		;global end of valid range of file
;
rcnt:	.blkw		;count of unread bytes in current half of RMBUF
rptr:	.blkw		;current ptr into RMBUF
;
wcnt:	.blkw		;count of bytes free in current half of WMBUF
wptr:	.blkw		;current ptr into WMBUF
;
	.even
jmpflg:	.blkb		;non-zero if last instruction transferred
			;control somewhere;
			;negative if the transfer was unconditional
adrflg:	.blkb		;non-zero if last operand decoded was
			;REL or ABS
			;ADRFLG *must* follow JMPFLG (both CLRed at once)
;
rmflg:	.blkb		;NZ => .MAC input file is open
wmflg:	.blkb		;NZ => .MAC output file is open
rdeof:	.blkb		;NZ => reached EOF reading .MAC input file
bflg:	.blkb		;NZ => /B given
eflg:	.blkb		;NZ => /E given
iflg:	.blkb		;NZ => /I given
sflg:	.blkb		;NZ => /S given
tflg:	.blkb		;NZ => /T given
uflg:	.blkb		;NZ => /U given
trash:	.blkb		;OUT trashes output if this is non-zero
;
lbuf:	.blkb	81.	;line buffer for .CSISPC
;
	.even
addr:	.blkw		;target address if ADRFLG is set
;
bval:	.blkw	2	;base, offset values
eval:	.blkw		;ending addr
sval:	.blkw		;starting addr
tval:	.blkw		;transfer addr
;
sbuf:	.blkw	39.	;scratch buf for .CSISPC
;
line:	.blkw		;current line # in .MAC input file
rmewc:	.blkw		;expected word count from outstanding .MAC input .READ
rmoth:	.blkw		;other buffer (besides the one in RMBA)
wmoth:	.blkw		;other buffer (besides the one in WMBA)
;
rbuf:	.blkw	400	;.SAV read buf
rmbuf:	.blkb	macin*2	;.MAC read buf
wmbuf:	.blkb	macout*2 ;.MAC write buf
;
symtab:	.blkw	4000	;1 bit for each word that's a JMP/JSR/BR target
bitmap:	.blkw	4000	;1 bit for each word executed
insbnd:	.blkw	4000	;1 bit for each instruction's first word
;; INSBND isn't *that* useful, might be better to use the space for
;; bigger I/O buffers?
;
devhnd=	.	; device handlers go here
	.end	dissav
                                     DISSAV.TXT					John Wilson  10-Oct-1997

DISSAV.SAV is a two-pass PDP-11 disassembler by John Wilson (this one is
anyway, it's an obvious filename so there are probably other DISASMs by other
authors).  I wrote it ages ago when I was even more clueless than now so I'm
too embarrassed to even look at the source, I'm sure it's a mess.  Anyway it
goes like this:

.RUN DISSAV
DISASM	V1.0	<system ID string if RSTS>
*out[.MAC]=in[.SAV]/switches

Possible switches:
/S:oooooo	starting octal addr (in .SAV file) to disassemble
/E:oooooo	ending octal addr (in .SAV file) to disassemble
/T:oooooo	transfer address to begin execution trace
		(default is .SAV transfer address from loc 000040)

The disassembler makes two passes.  The first pass detects (or tries to detect)
the difference between code and data, and figures out what addresses are branch
targets (and thus require labels).  It does this by building a bitmap of all
words of the file and doing a "dry" disassembly (i.e. no source output) of each
word of the file.  As an instruction is traced it is entered into the bitmap as
code (rather than data).  If the instruction ends a thread (RTS, HALT etc., or
a computed JMP) then tracing stops.  If it's an unconditional branch (BR or
JMP) then tracing continues at the target address.  If it's a JSR or
conditional branch, then each path is searched recursively.

On the second pass the .SAV file is disassembled linearly, with labels
generated as appropriate and code/data generated according to the bitmap.  All
non-trivial programs will contain some type of jump or dispatch tables and/or
some other kind of computed JMP, which the disassembler will not be able to
find (and could not even guess at without some very sophisticated heuristics to
figure out the bounds on the possible values in each register during a real
run).  So there will be dead code shown as data that actually should have been
disassembled as instructions.  In this case you can make successive runs of the
disassembler, telling it what code to disassemble using the /S, /E, and /T
switches, and then edit the resulting file in with the main disassembled file
by hand.  Yes I know it's cumbersome.  Ideally this could be done using a file
to hold a long list of transfer and data addresses (my DASM.COM 8080/Z80/8086
disassembler for DOS does this, it's also available from FTP.DBIT.COM), so that
you could produce a fresh source file each time you find a new transfer address
to add, w/o having to do any hand editing.  Actually my plan for DISASM.SAV was
to do this using simple directives that could be embedded in a .MAC file
produced in a previous disassembly, that way you wouldn't destroy any previous
work in commenting the disassembled code, the disassembler would just insert
the new source code into your edited source file.  But I never got around to
it.  Some day...

I had planned to write a version of this that used the extra information
available in a .OBJ file, but it would be pretty hard work to combine that with
the execution trace.  I got as far as writing a program that understands the
record format in a .OBJ file and dumps out all the records in text form, but
that's not much help.  Anyway I gather this is familiar territory to the other
PDP-11 disassemblers out there, I wish I'd heard of them when I wrote my stuff.

DISASM.MAC contains a conditional assembly flag named "RSTS" which decides
whether DISASM.SAV will display a RSTS version banner on startup (since I wrote
the program on a RSTS V7.0-07 system), in practice it seems that this can be
left on in real RT-11 (I haven't looked up what EMT 364 in does in real RT-11
but the program doesn't bomb for what that's worth).

Happy hacking,

John Wilson
D Bit
                                                                                                                                                                                                                                                                                                                &  {K	    D       k    (                    	0<" U @$ k(&
@  	
7
7
7
  	z77( 	j7 	   
< k$(,   | xr; 

E XE VE RHRDN3*+
+D <7
 
 71	H
(   $;P3V+\+    / !7  h`	H	w	5P;	 	"	P	| w  	v
'   @;Ps   t t	D
	5P;	^ 	~	7gJD	
QLD7 
  >;   47.	t	f 	d w D	(50K 5P[	 	 
f,	  7   d2K8[   lw	50;	Pq	a	v	50K~	`	"	R	 wJw!Bԃ 	7
L&DR e fw   ;q$a4K:~nB   f			5 	xE E w b a	XJ W  w	w >W @ w    8RXa   dW 		w W  & 	e		w & 	pe		bw W  wNH @a	X   8eVec   ;w &	6e	 	Hw E 	bw & 	,e	tE@@	w T	w L&	e	B	   eDeve   \,w 4&	"e	*	w &	e		w &	e		~w Ee0 &	w  f
v   e*eBej   e	@&	


w 				 	 *	|	
 	 	f	50;	q	Va	Nc	FV   e\;jqrazc   T~	>	p	lw ,f	50;	Tq	a	c	~		.	x&s	
	  	
 
	L w  & "  ~";0q8a@cH~\s       ~  `  	* 7vw 
	 z		d|w B x	z E&E8   AE w   a   &v4zB|Nx   Lw    	 mw 6  k	(   o	w   ( k	 0 	0	,w  k	 E  	   m$k4oHkfk~   	 	w    7?k	 	 	w   0 7	@aw   8 k	~ w E58 %w &g	` 	
 i    k&Rkpg~i>   D	R  E  	w < w 4 e0 7jw $ Ee0 7Yw   ESftn	
&wb	     0DXS   
wTN 7f&7 (7 $	X950K50[5P;7 L 	 f0 	  7J&fa   8K>[D;Vq   < EU0 
Ea	4 &fBEU0  	 z
 @ @
   (BXjz   
 fw!82w!4/AA	V 5PKEB EE mm5 
E  @e     
<KnvL   4	  @EE Z 777777^? 5  B E %H *I -S .T 5& 
  (Z]   	U < w F5E w E)'w 6!	@ #E wt E wb    
JP   ,
 
>:~@ a  z   W M ݮݬݩݦ
		
 	 ݂݀   (~@^j   
}zAL	gN	D	Rq	6	BDV		,,R	|	Z	j	    LN,qBVXRnZ   $^	l	d 0鈇 777
 7
#z 7fw    w v!    ^06<#HfB   F.e 8$4wwX7R7 H   2	 
ׯ"* 6+"?

	  
  *    
   	

	^䆇 

ׯ
 ׯ 

	2 * 
      W!z

f	n   P*lzY   
t
n(*	  Vw @S 
!B5 7w w`    ( *0Vhj     w vkQkQkQDISSAV V1.2 Type /H or /? for help 
 ?Syntax error ?/I requires /S and /E too ?Bad switch ?File 
  
N    write error ?File read error By John Wilson <wilson@dbit.com>
Copyright (C) 1998 by D Bit.  All rights reserved.
Distribu   tion, modification, and use for any purpose is allowed as long as
source code is available which includes this notice.

U   sage:
*newsource[.MAC]=binary[.SAV][,oldsource.MAC]/switches

Switches:
/S:start          Set starting virtual addr
/E:   end            Set ending virtual addr
/T:transfer       Set virtual transfer addr
/B:base[:offset]  Set starting file add   ress of memory image
                  (BASE=starting block, OFFSET=offset in that block
/I                Insert block of    code here (requires /S/E), useful only
                  within oldsource.MAC
/U                Write source code in uppey   xr case

output file:      Disassembled MACRO source
input file #1:    Binary .SAV file
input file #2:    MACRO source (N   .B. default ext=.SAV) from previous run,
                  lines starting with '*' are more switches        @        p     @         42 }      }     s              :       [q`"     s       @R }  ? @ @  X  s  F  Ly     lXvFe      Y       ;           ;w      w  ?  YzX  P        Y        t        .  "6@XJT^hr|   h e  ? 	 KX A  |? 
    ?@
%    ?
s:    ?
    ? OX    ?@    ?w    ?    ? r    ?@r u  
X|(X 
2X 
<X 
FX 
PX 
ZX 
dX 
nX 
xX 
a       ?J	    ?D	    ?  zQDX? @@R@8X? pT@8X? z  X?    X? wX? KX S           0     d  X 
X 
X 
$X.X8XBXLXVX`Xj 
t 
~ 
'   ` @     P     `   pT   r~   t@	   v@	 xj  |  z% F z(F z' KF z)&F  | D   
 
 *4>HR|\FfFpFzF   P    |P    |P     |P@    |P    |P    |P     |P@  |S    |Sp    |Sx}     |[M    !|x 
  N   X    "|9wW    #|AyW    $|    %||Q    (|W    )|
zW    *|W    +|D`Y    ,|D0f    -|D Z    .|@	W    /|D0M    `   0|,P    1|,P    2|,P     3|,P@    4|,P    5|,P    6|,P     7|,P@  8| d    9|
z d    :| d    ;|De    <|T 
  P   P d    =|~ d    >|@	 d    ?|DM    X|S(  Y|Sq  Z|S}$  `|[M(  a|x(  b|9wX  c|AyX  d|(  e||Q(z *  .8B$LV`jt~]     h|X  i|
zX  j|X  k|DiY  l|D9f  m|D	Z  n|@	X  o|D9M  x|he  y|
zhe  z|he  {|De  ||% 6   *4>HR\fpz   HThe  }|~he  ~|@	he  |DM  }R    ? }  X ~y                ov        R 2  &:XDNXblvR             \!     d?  pTvX? @@R X? pT X? @RvX 
z         w%    w@8     .  ",6X@XJXTX^S   @K    S      S      	w     
w K  ? @KfX? yfX? y }X?  %B? @%B? %B? OX%B  T "  <XFXPXZBdBnBxB3   %J  S%J  %J  K  J  
z%J  %J  y  b  ~%J  y  y&  y &b  Kz  K09z :  JJJ$J.J8JBbLJV`jbtz~zD   8  KJ   q* /B: /E: /S: /T: /U 	   , ( ) @ + - : 	;   ' < > .word	  abcdefghijklmnopqrstuvwxyz$.%0123456789	.rem	!   J 1  
 	.end	start
 b sp pc start cvznr  f   
    /             	       # ######  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   m                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    	0<" U @$ m(&
@  	
7
7
7
  	z77( 	j7 	xr= 

E XE VE RHRDN5*-
-D <7
 
 71	H
(/ !7  h`	H	w	5P=	 	"	P	| w  	v
' t	D
	5P=	^ 	~	7gJD	
QLD747.	t	f 	d w D	(50M 5P]	 	 
f,	  7w	50=	Pq	a	v	50M~	`	"	R	 wJw!Bԃ 	7
L&DR e ff			5 	xE E w b a	XJ W  w	w >W @ wW 		w W  & 	e		w & 	pe		bw W  wNH @a	;w &	6e	 	Hw E 	bw & 	,e	tE@@	w T	w L&	e	B	,w 4&	"e	*	w &	e		w &	e		~w Ee0 &	w  f
e	@&	


w 				 	 *	|	
 	 	f	50=	q	Va	Nc	F~	>	p	lw ,f	50=	Tq	a	c	~		.	x&s	
	  	
 
	L w  &    ~  `  	* 7vw 
	 z		d|w B x	z E&E8   AE w   w    	 mw 6  k	(   o	w   ( k	 0 	0	,w  k	 E  		 	w    7?k	 	 	w   0 7	@aw   8 k	~ w E58 %w &g	` 	
 i	R  E  	w < w 4 e0 7jw $ Ee0 7Yw   ESftn	
&wb	
wTN 7f&7 (7 $	X950M50]5P=7 L 	 f0 	  7J&f EU0 
Ea	4 &fBEU0  	 z
 @ @

 fw!82w!4/AA	V 5PMEB EE mm5 
E  @e    @EE Z 777777^? 5  B E %H *I -S .T 5U < w F5E w E)'w 6!	@ #E wt E wb  
>:~@ a  z   W M ݮݬݩݦ
		
 	 ݂݀}zAL	gN	D	Rq	6	BDV		,,R	|	Z	j	 ^	l	d 0鈇 777
 7
%z 7fw    w v! F.e 8$4wwX7R7 H   2	 
ׯ"* 6+"?

	  
   	

	^䆇 

ׯ
 ׯ 

	2 * 
      W!z

f	
t
n(*	  Vw @S 
!B5 7w w`   w vkQkQkQDISSAV V1.2 Type /H or /? for help 
 ?Syntax error ?/I requires /S and /E too ?Bad switch ?File write error ?File read error By John Wilson <wilson@dbit.com>
Copyright (C) 1998 by D Bit.  All rights reserved.
Distribution, modification, and use for any purpose is allowed as long as
source code is available which includes this notice.

Usage:
*newsource[.MAC]=binary[.SAV][,oldsource.MAC]/switches

Switches:
/S:start          Set starting virtual addr
/E:end            Set ending virtual addr
/T:transfer       Set virtual transfer addr
/B:base[:offset]  Set starting file address of memory image
                  (BASE=starting block, OFFSET=offset in that block
/I                Insert block of code here (requires /S/E), useful only
                  within oldsource.MAC
/U                Write source code in upper case

output file:      Disassembled MACRO source
input file #1:    Binary .SAV file
input file #2:    MACRO source (N.B. default ext=.SAV) from previous run,
                  lines starting with '*' are more switches        @          @         42 }      }     s              :       [q`"     s       @R }  ? @ @  X  s  F  Ly     Y       ;           ;w      w  ?  YzX  P        Y        t        e  ? 	 KX A  |? 
  Y?@
%  Y?
s:  Y?
  Y? OX  Y?@  Y?w  Y?  Y? r  Y?@r  Y?J	  Y?D	  Y?  zQDX? @@R@8X? pT@8X? z  X?    X? wX? KX S       0   @   P   `   pT   r~   t@	   v@	 xj  |  z% F z(F z' KF z)&F  |P    |P    |P     |P@    |P    |P    |P     |P@  |S    |Sp    |Sx}     |[M    !|x    "|9wW    #|AyW    $|    %||Q    (|W    )|
zW    *|W    +|D`Y    ,|D0f    -|D Z    .|@	W    /|D0M    0|,P    1|,P    2|,P     3|,P@    4|,P    5|,P    6|,P     7|,P@  8| d    9|
z d    :| d    ;|De    <|T d    =|~ d    >|@	 d    ?|DM    X|S(  Y|Sq  Z|S}$  `|[M(  a|x(  b|9wX  c|AyX  d|(  e||Q(  h|X  i|
zX  j|X  k|DiY  l|D9f  m|D	Z  n|@	X  o|D9M  x|he  y|
zhe  z|he  {|De  ||The  }|~he  ~|@	he  |DM  }R    ? }  X ~y                ov                  \!     d?  pTvX? @@R X? pT X? @RvX 
z         w%    w@8    K    S      S      	w     
w K  ? @KfX? yfX? y }X?  %B? @%B? %B? OX%B  T%J  S%J  %J  K  J  
z%J  %J  y  b  ~%J  y  y&  y &b  Kz  K09z  KJ   q* /B: /E: /S: /T: /U 	   , ( ) @ + - : 	;   ' < > .word	  abcdefghijklmnopqrstuvwxyz$.%0123456789	.rem	!
 	.end	start
 b sp pc start cvznr  f              	       # ######                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            t word.

MvWLft:
	tst	(r5)			; at BOL already?
	beq	BOLErr
	mov	r3,r0			; Put cursor location in R0
	call	FindWR			; Find word in reverse
	neg	r2			; make count negative
	br	8$

	.Disable LSB
.EndC;	NE	SL$KED
.SbTtl	DATA -- insert data
;+
;	DATA
;
;	Put data char into buffer if there is room.
;-
.Enable	LSB
Data:
	Mov	R0,Temp(R5)		; build a 1 char len string
.If NE Let$
	TstB	@#dLet			; doing Let substitution?
$Rel	.-2	dLet	SLR
	Boff	50$			; no, skip it

; Is the entered character in the LET symbol table?

	Mov	#LetSym,R1		; point to symbol names
$Rel	.-2	LetSym	SLR
	Mov	#LetVal,R4		; point to symbol value base
$Rel	.-2	LetVal	SLR
	Mov	#LetNo$,R2		; and load count too
 10$:
	 CmpB	(R1)+,R0		; is this the symbol?
	 Beq	20$			; yes
	 Add	#LetSz$+1,R4		; point to next value
	 Sob	R2,10$			; try all of them
	Br	50$			; not found
	...........

; It's a LET symbol.  Is it preceded by the LET QUOTE symbol?

20$:
					.Assume CurOfs EQ 0
	Tst	@R5			; at the beginning at line?
	Beq	30$			; then there is no "quote"
	CmpB	-1(R3),#<LQuote>	; is the prev char "quote"
	Bne	30$			; no
	Push	R0			; save "quoted" char
	Call	DelCL			; and delete the "quote"
	Pop	Temp(R5)		; now insert "quoted" char
					; (DelCL crushes Temp)
	Br	50$			; and just insert it
	...........

30$:
	Mov	R4,R0			; transfer the value pointer to R0
	Br	60$			; and insert it
	...........
50$:
.EndC;	NE	Let$

; Insert the typed character.  It's located in TEMP(R5).  Point
; to that location and drop through to insert.

	Mov	R5,R0			; point to it
	Add	#Temp,R0		; ...

; R0 points to a string to insert

.If	NE	Let$
LetIns:			; Come here from FunKyL
60$:
.EndC;	NE	Let$
	TstB	IRMode			; INSERT or REPLACE mode?
	Bmi	70$			; Branch if INSERT
65$:	TstB	@R3			; Sitting at end now?
	Beq	70$			; If so, treat as insert.
	Mov	R0,R1			; Let R1 point to character
	TSTB	@R0			; End of string?
	BEQ	75$			; return if so.
	Call	LUCase			;  so that LUCase can see it.
	MovB	(R0)+,@R3		; REPLACE... get the character,
	MOV	R0,-(SP)
	MOVB	(R3)+,R0
	Call	V.R0			; Print the character
	MOV	(SP)+,R0
	Inc	@R5			; Bump cursor position
	Br	65$			; any more?

70$:	Call	Insert			; insert the data char(s)
75$:	Bcc	Ret1			; done
InsErr:
	Call	DoBEL			; and do it
	.Word	InsCod			; do error
	.............

.Disable LSB
.SbTtl	*****************************************
.SbTtl	*	Command service routines	*
.SbTtl	*****************************************
.SbTtl	Error routines
.SbTtl	OldErr -- no old line to get
;OldErr:
;	Call	DoBel
;	.Word	OldCod
;	..............

.SbTtl	EolErr -- at EOL, can't to operation to the right
EolErr:
	Call	DoBel
	.Word	EolCod
	..............

.SbTtl	BOLERR -- at BOL, can't do operation to the left
BolErr:
	Call	DoBel
	.Word	BolCod
	..............
.SbTtl	GetChr	- get next input char
;+
;	GETCHR
;
;	Get next char from terminal, if a NULL try again.
;
;	Call GetChr
;or
;	Call @InTty(R5)		; vectored thru impure area
;
;	On Return:
;	R0 = char (high byte cleared)
;	Carry cleared
;
;	Other registers preserved
;-
.Enable	LSB
GetChr:
10$:
	.TtInR				; Get a char
	Mov	SP,SP			; indicate request from SL
	Bcs	10$			; no char available
;NOTE: the .TtTnR is used because .TtyIn has a Bcs following the EMT
; which breaks the Mov R5,R5 test
	Bic	#^c177,R0		; ignore 8th bit (for now)
	Beq	10$			; EAT NULs (unlikely, but ...)
Ret1:	Return
	......
.Disable LSB
.SbTtl	Range	- match a char within a range / dispatch if found
;+
;	RANGE
;
;	try