diff mon2.asm @ 0:9a224bd9b45f

os9 emulation
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 02 Jul 2018 02:12:31 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mon2.asm	Mon Jul 02 02:12:31 2018 +0900
@@ -0,0 +1,3080 @@
+	;Buggy machine language monitor and rudimentary O.S. version 1.0
+
+* Memory map of SBC
+* $0-$40 Zero page variables reserved by monitor and O.S.
+* $40-$FF Zero page portion for user programs.
+* $100-$17F Xmodem buffer 0, terminal input buffer,
+* $180-$1FF Xmodem buffer 1, terminal output buffer.
+* $200-$27F Terminal input line.
+* $280-$2FF Variables reserved by monitor and O.S.
+* $300-$400 System stack.
+* $400-$7FFF RAM for user programs and data.
+* $8000-$DFFF PROM for user programs.
+* $E000-$E1FF I/O addresses.
+* $E200-$E3FF Reserved.
+* $E400-$FFFF Monitor ROM
+
+* Reserved Zero page addresses
+		org $0000
+* First the I/O routine vectors.
+getchar		rmb 3		;Jump to getchar routine.
+putchar		rmb 3		;Jump to putchar routine.
+getline		rmb 3		;Jump to getline routine.
+putline		rmb 3		;Jump to putline routine.
+putcr		rmb 3		;Jump to putcr routine.
+getpoll         rmb 3           ;Jump to getpoll routine.
+xopenin		rmb 3		;Jump to xopenin routine.
+xopenout	rmb 3		;Jump to xopenout routine.
+xabortin	rmb 3           ;Jump to xabortin routine.
+xclosein	rmb 3		;Jump to xclosein routine.
+xcloseout	rmb 3		;Jump to xcloseout routine.
+delay		rmb 3		;Jump to delay routine.
+
+*Next the system variables in the zero page.
+temp		rmb 2            ;hex scanning/disasm
+temp2		rmb 2            ;Hex scanning/disasm
+temp3 		rmb 2            ;Used in Srecords, H command
+timer		rmb 3            ;3 byte timer, incremented every 20ms
+xpacknum	rmb 1            ;Packet number for XMODEM block,
+xsum		rmb 1		 ;XMODEM checksum
+lastok		rmb 1            ;flag to indicate last block was OK
+xcount		rmb 1		 ;Count of characters in buffer.
+xmode 		rmb 1		 ;XMODEM mode, 0 none, 1 out, 2 in.
+disflg		rmb 1
+
+* I/O buffers.
+buflen		equ 128		;Length of input line buffer.
+		org $100
+buf0		rmb 128		;Xmodem buffer 0, serial input buffer.
+buf1		rmb 128		;Xmodem buffer 1, serial output buffer.
+linebuf		rmb buflen	;Input line buffer.
+
+
+* Interrupt vectors (start at $280)
+* All interrupts except RESET are vectored through jumps.
+* FIRQ is timer interrupt, IRQ is ACIA interrupt.
+swi3vec		rmb 3
+swi2vec		rmb 3
+firqvec		rmb 3
+irqvec		rmb 3
+swivec 		rmb 3
+nmivec		rmb 3
+xerrvec		rmb 3           ;Error handler for XMODEM error.
+exprvec		rmb 3		;Expression evaluator in assembler.
+asmerrvec	rmb 3		;Error handler for assembler errors.
+pseudovec	rmb 3		;Vector for asm pseudo instructions.
+
+* Next the non zero page system variables.
+oldpc		rmb 2		;Saved pc value for J command.
+addr		rmb 2		;Address parameter.
+length		rmb 2		;Length parameter.
+
+brkpoints 	equ 8		;Number of settable breakpoints. 
+bpaddr		rmb brkpoints*3 ;Address and byte for each break point.
+stepbp		rmb 3		;Address of P command break point.
+
+sorg		rmb 2		;Origin address of S record entry.
+soffs		rmb 2		;Offset load adrr-addr in record
+
+oldgetc		rmb 2		;Old getchar address.
+oldputc		rmb 2		;Old putchar address.
+oldputcr	rmb 2		;Old putcr address.
+lastterm	rmb 1		;Last terminating character.
+filler		rmb 1		;Filler at end of XMODEM file.
+xmcr		rmb 1		;end-of-line characters for XMODEM send.
+savesp		rmb 2		;Save sp to restore it on error.
+nxtadd		rmb 2
+
+* Following variables are used by assembler/disassembler.
+prebyte		rmb 1
+opc1		rmb 1
+opcode 		rmb 1
+postbyte	rmb 1
+amode		rmb 1
+operand		rmb 2		
+mnembuf		rmb 5		;Buffer to store capitalized mnemonic.
+opsize		rmb 1		;SIze (in bytes) of extra oeprand (0--2)
+uncert		rmb 1		;Flag to indicate that op is unknown.
+dpsetting	rmb 2
+
+endvars		equ *
+
+ramstart	equ $400	;first free RAM address.
+
+ramtop  	equ $8000       ;top of RAM.
+
+* I/O port addresses
+aciactl		equ $e000	;Control port of ACIA
+aciasta		equ $e000	;Status port of ACIA
+aciadat		equ $e001	;Data port of ACIA
+
+* ASCII control characters.
+SOH		equ 1
+EOT		equ 4
+ACK		equ 6
+BS		equ 8
+TAB		equ 9
+LF		equ 10
+CR		equ 13
+NAK		equ 21
+CAN		equ 24
+DEL		equ 127
+
+CASEMASK	equ $DF		;Mask to make lowercase into uppercase.
+
+* Monitor ROM starts here.
+		org $E400
+
+reset		orcc #$FF	;Disable interrupts.
+		clra		
+		tfr a,dp	;Set direct page register to 0.
+		clr disflg
+		lds #ramstart
+		ldx #intvectbl
+		ldu #swi3vec
+		ldb #osvectbl-intvectbl
+		bsr blockmove   ;Initialize interrupt vectors from ROM.
+		ldx #osvectbl
+		ldu #0
+		ldb #endvecs-osvectbl
+		bsr blockmove	;Initialize I/O vectors from ROM.
+		bsr initacia	;Initialize serial port.
+		andcc #$0	;Enable interrupts
+* Put the 'saved' registers of the program being monitored on top of the
+* stack. There are 12 bytes on the stack for cc,b,a,dp,x,y,u and pc
+* pc is initialized to $400, the rest to zero.
+		ldx #0          
+		tfr x,y
+		ldu #ramstart
+		pshs x,u
+		pshs x,y
+		pshs x,y  
+		ldx #oldpc
+		ldb #endvars-oldpc
+clvar		clr ,x+
+		decb
+		bne clvar	;Clear the variable area.	
+		ldd #$1A03	
+		std filler	;Set XMODEM filler and end-of-line.
+		ldx #welcome
+		jsr outcount
+		jsr putcr	;Print a welcome message.      
+		jmp cmdline
+* Block move routine, from X to U length B. Modifies them all and A. 
+blockmove	lda ,x+
+		sta ,u+
+		decb
+		bne blockmove
+		rts
+
+* Initialize serial communications port, buffers, interrupts.
+initacia	ldb #$03
+		stb aciactl
+		ldb #%00110101
+		rts
+
+* O.S. routine to read a character into B register.
+osgetc		ldb aciasta
+		bitb #$01
+		beq osgetc
+		ldb aciadat
+		rts
+
+;O.S. rotuine to check if there is a character ready to be read.
+osgetpoll       ldb aciasta
+		bitb #$01
+		bne poltrue
+		clrb
+		rts
+poltrue		ldb #$ff
+		rts
+
+* O.S. routine to write the character in the B register.
+osputc		pshs a
+putcloop	lda aciasta
+		bita #$02
+		beq putcloop
+		stb aciadat
+		puls a
+		rts
+
+* O.S. routine to read a line into memory at address X, at most B chars
+* long, return actual length in B. Permit backspace editing.
+osgetl		pshs a,x
+		stb temp
+		clra
+osgetl1		jsr getchar
+		andb #$7F      		
+		cmpb #BS
+		beq backsp
+		cmpb #DEL
+		bne osgetl2       
+backsp		tsta                  ;Recognize BS and DEL as backspace key.
+		beq osgetl1	      ;ignore if line already zero length.
+		ldb #BS
+		jsr putchar
+		ldb #' '
+		jsr putchar
+		ldb #BS		      ;Send BS,space,BS. This erases last
+		jsr putchar           ;character on most terminals.
+		leax -1,x	      ;Decrement address.
+		deca
+		bra osgetl1
+osgetl2		cmpb #CR
+		beq newline
+		cmpb #LF
+		bne osgetl3           ;CR or LF character ends line.
+		ldb lastterm
+		cmpb #CR
+		beq osgetl1	      ;Ignore LF if it comes after CR
+		ldb #LF		      
+newline         stb lastterm
+		jsr putcr             
+		tfr a,b               ;Move length to B
+		puls a,x              ;restore registers.
+		rts                   ;<--- Here is the exit point.
+osgetl3         cmpb #TAB
+		beq dotab		
+		cmpb #' '
+		blo osgetl1	      ;Ignore control characters.
+		cmpa temp
+		beq osgetl1	      ;Ignore char if line full.
+		jsr putchar           ;Echo the character.
+		stb ,x+               ;Store it in memory.
+		inca
+		bra osgetl1
+dotab		ldb #' '
+		cmpa temp
+		beq osgetl1
+		jsr putchar
+		stb ,x+
+		inca
+		bita #7		       ;Insert spaces until length mod 8=0
+		bne dotab
+		bra osgetl1 
+
+* O.S. routine to write a line starting at address X, B chars long.
+osputl		pshs a,b,x
+		tfr b,a
+		tsta
+		beq osputl1
+osputl2		ldb ,x+
+		jsr putchar
+		deca
+		bne osputl2
+osputl1		puls a,b,x
+		rts
+
+* O.S. routine to terminate a line.
+oscr		pshs b
+		ldb #CR
+		jsr putchar
+		ldb #LF
+		jsr putchar     ;Send the CR and LF characters.
+		puls b
+		rts
+
+* Output a counted string at addr X
+outcount	pshs x,b
+		ldb ,x+
+		jsr putline
+		puls x,b
+		rts
+
+timerirq	inc timer+2
+		bne endirq
+		inc timer+1
+		bne endirq
+		inc timer
+		rti
+aciairq		nop
+endirq		rti
+
+* Wait D times 20ms.
+osdly		addd timer+1
+dlyloop		cmpd timer+1
+		bne dlyloop
+		rts		
+
+* This table will be copied to the interrupt vector area in RAM.
+intvectbl	jmp endirq
+		jmp endirq
+		jmp timerirq
+		jmp aciairq
+		jmp unlaunch
+		jmp endirq
+		jmp xerrhand
+		jmp expr
+		jmp asmerrvec
+		jmp pseudo
+* And this one to the I/O vector table.
+osvectbl	jmp osgetc
+		jmp osputc
+		jmp osgetl
+		jmp osputl
+		jmp oscr		
+		jmp osgetpoll
+		jmp xopin
+		jmp xopout
+		jmp xabtin
+		jmp xclsin
+		jmp xclsout
+		jmp osdly
+endvecs 	equ *		
+		
+* The J command returns here.
+stakregs        pshs x		     ;Stack something where the pc comes
+		pshs ccr,b,a,dp,x,y,u ;Stack the normal registers.
+		ldx oldpc	
+		stx 10,s	     ;Stack the old pc value.
+		bra unlaunch1
+* The G and P commands return here through a breakpoint.
+* Registers are already stacked.
+unlaunch	ldd 10,s
+		subd #1
+		std 10,s	     ;Decrement pc before breakpoint
+unlaunch1	andcc #$0	     ;reenable the interrupts.
+		jsr disarm	     ;Disarm the breakpoints.
+		jsr dispregs 	     
+cmdline		jsr xcloseout
+		sts savesp
+		ldb #'.'
+		jsr putchar
+		ldx #linebuf
+		ldb #buflen
+                jsr getline
+		tstb
+		beq cmdline          ;Ignore line if it is empty
+		abx
+		clr ,x		     ;Make location after line zero.
+		ldx #linebuf
+		ldb ,x+
+		andb #CASEMASK	     ;Make 1st char uppercase.
+		subb #'A'            
+		bcs unk
+		cmpb #26
+		bcc unk		     ;Unknown cmd if it is not a letter.
+		ldx #cmdtab
+		aslb		      ;Index into command table.
+		jmp [b,x]
+
+cmdtab 		fdb asm,break,calc,dump
+		fdb enter,find,go,help
+		fdb inp,jump,unk,unk
+		fdb move,unk,unk,prog
+		fdb unk,regs,srec,trace
+		fdb unasm,unk,unk,xmodem
+		fdb unk,unk
+
+* Unknown command handling routine.
+unk		jsr xabortin
+		ldx #unknown
+		jsr outcount
+		jsr putcr
+		jmp cmdline
+
+help		ldx #mhelp   	;Print a help message.
+help1		ldb ,x+
+		beq endhlp
+		lbsr osputc
+		bra help1		
+endhlp		jmp cmdline
+mhelp		fcb	CR,LF
+		fcc	'Commands list'
+		fcb	CR,LF
+
+		fcc	'-------------'
+		fcb	CR,LF
+
+	        fcc 	'Asm    '
+		fcc	'{Aaddr}'
+		fcb	CR,LF
+
+		fcc	'Unasm  '
+		fcc	'{U or Uaddr or Uaddr,length}'
+		fcb	CR,LF
+
+		fcc	'Dump   '
+		fcc	'{D or D<addr> or D<addr>,<length>}'
+		fcb	CR,LF
+
+		fcc	'Enter  '
+		fcc	'{E or E<addr> or E<addr> <bytes> or E<addr>string}'
+		fcb	CR,LF
+
+		fcc	'Break  '
+		fcc	'{B or B<addr>. B displays, B<addr> sets or clears breakpoint}'
+		fcb	CR,LF
+
+		fcc	'Find   '
+		fcb	"{Faddr bytes or Faddr",34,"ascii",34,"}"
+		fcb	CR,LF
+
+		fcc	'Go     '
+		fcc	'{G or G<addr>}'
+		fcb	CR,LF
+
+		fcc	'Calc   '
+		fcc	'{Chexnum{+|-hexnum}}'
+		fcb	CR,LF
+
+		fcc	'Inp    '
+		fcc	'{Iaddr}'
+		fcb	CR,LF
+
+		fcc	'Jump   '
+		fcc	'{J<addr>}'
+		fcb	CR,LF
+
+		fcc	'Move   '
+		fcc	'{M<addr1>,<addr2>,<lenght>}'
+		fcb	CR,LF
+
+		fcc	'Prog   '
+		fcc	'{P}'
+		fcb	CR,LF
+
+		fcc	'Regs   '
+		fcc	'{R or R<letter><hex>}'
+		fcb	CR,LF
+
+		fcc	'Srec   '
+		fcc	'{SO<addr> or SS<addr>,<len> or S1<bytes> or S9<bytes>}'
+		fcb	CR,LF
+
+		fcc	'Trace  '
+		fcc	'{T}'
+		fcb	CR,LF
+
+		fcc	'Xmodem '
+		fcc	'{XSaddr,len XLaddr,len XX XOcrlf,filler, XSSaddr,len}'
+		fcb	CR,LF
+
+		fcc	'Help   '
+		fcc	'{H}'
+		fcb	CR,LF,0
+
+
+
+* Here are some useful messages.
+welcome		fcb unknown-welcome-1
+		fcc "Welcome to BUGGY version 1.0"
+unknown		fcb brkmsg-unknown-1
+		fcc "Unknown command"
+brkmsg		fcb clrmsg-brkmsg-1
+		fcc "Breakpoint set"
+clrmsg		fcb fullmsg-clrmsg-1
+		fcc "Breakpoint cleared"
+fullmsg		fcb smsg-fullmsg-1
+		fcc "Breakpoints full"
+smsg		fcb lastrec-smsg-1
+		fcc "Error in S record"
+lastrec		fcb xsmsg-lastrec-1
+		fcc "S9030000FC"
+xsmsg		fcb xrmsg-xsmsg-1
+		fcc "Start XMODEM Send"
+xrmsg		fcb xamsg-xrmsg-1
+		fcc "Start XMODEM Receive"
+xamsg		fcb invmmsg-xamsg-1
+		fcc "XMODEM transfer aborted"
+invmmsg		fcb exprmsg-invmmsg-1
+		fcc "Invalid mnemonic"
+exprmsg		fcb modemsg-exprmsg-1
+		fcc "Expression error"
+modemsg		fcb brmsg-modemsg-1
+		fcc "Addressing mode error"		
+brmsg		fcb endmsg-brmsg-1
+		fcc "Branch too long"
+endmsg		equ *
+
+* Output hex digit contained in A
+hexdigit 	adda #$90
+		daa
+		adca #$40
+		daa		;It's the standard conversion trick ascii
+		tfr a,b		;to hex without branching.
+		jsr putchar
+		rts
+
+* Output contents of A as two hex digits 
+outbyte		pshs a		
+		lsra
+		lsra
+		lsra
+		lsra
+		bsr hexdigit
+		puls a
+		anda #$0f
+		bra hexdigit
+
+* Output contents of d as four hex digits 
+outd		pshs b   
+		bsr outbyte
+		puls a
+		bsr outbyte
+		rts
+
+* Skip X past spaces, B is first non-space character.
+skipspace	ldb ,x+
+		cmpb #' '
+		beq skipspace
+		rts
+
+* Convert ascii hex digit in B register to binary Z flag set if no hex digit. 
+convb		subb #'0'
+		blo convexit
+		cmpb #9
+		bls cb2
+		andb #CASEMASK ;Make uppercase.
+		subb #7		;If higher than digit 9 it must be a letter.
+		cmpb #9
+		bls convexit
+		cmpb #15
+		bhi convexit
+cb2		andcc #$FB      ;clear zero	
+		rts
+convexit	orcc #$04
+		rts
+
+scanexit  	ldd temp
+		leax -1,x
+		tst temp2
+		rts		<-- exit point of scanhex
+
+* Scan for hexadecimal number at address X return in D, Z flag is set it no
+* number found.
+scanhex		clr temp    
+		clr temp+1
+		clr temp2
+		bsr skipspace
+scloop		jsr convb
+		beq scanexit
+		pshs b
+		ldd temp
+		aslb
+		rola
+		aslb
+		rola
+		aslb
+		rola
+		aslb
+		rola
+		addb ,s+
+		std temp
+		inc temp2
+		ldb ,x+
+		bra scloop
+
+scan2parms	std length
+		bsr scanhex
+		beq sp2
+		std addr
+		bsr skipspace
+		cmpb #','
+		bne sp2
+		bsr scanhex
+		beq sp2
+		std length				
+sp2 		rts
+
+* Scan two hexdigits at in and convert to byte into A, Z flag if error.
+scanbyte	bsr skipspace
+		bsr convb
+		beq sb1
+		tfr b,a
+		ldb ,x+
+		bsr convb
+		beq sb1
+		asla
+		asla
+		asla
+		asla
+		stb temp
+		adda temp
+		andcc #$fb	;Clear zero flag
+sb1		rts
+
+
+* This is the code for the D command, hex/ascii dump of memory
+* Syntax: D or D<addr> or D<addr>,<length>	
+dump	    	ldx #linebuf+1
+		ldd #$40	
+	        jsr scan2parms ;Scan address and length, default length=64
+		ldy addr
+dh1		lda #16
+		sta temp+1	
+		tfr y,d
+		jsr outd
+		ldb #' '
+		jsr putchar
+dh2		lda ,y+		;display row of 16 mem locations as hex
+		jsr outbyte
+		ldb #' '
+		lda temp+1
+		cmpa #9
+		bne dh6
+		ldb #'-'	;Do a - after the eighth byte.
+dh6		jsr putchar
+		dec temp+1
+		bne dh2
+		leay -16,y	;And now for the ascii dump.
+		lda #16
+dh3		ldb ,y+
+		cmpb #' '
+		bhs dh4
+		ldb #'.'            
+dh4		cmpb #DEL
+		blo dh5
+		ldb #'.'	;Convert all nonprintables to .
+dh5		jsr putchar
+		deca
+		bne dh3
+		jsr putcr
+		ldd length
+		subd #16
+		std length
+		bhi dh1
+		sty addr
+		jmp cmdline
+
+* This is the code for the E command, enter hex bytes or ascii string.
+* Syntax E or E<addr> or E<addr> <bytes> or E<addr>"string"
+enter		ldx #linebuf+1
+		jsr scanhex
+		beq ent1
+		std addr
+ent1		bsr entline
+		lbne cmdline	;No bytes, then enter interactively.		
+ent2		ldb #'E'
+		jsr putchar
+		ldd addr 
+		jsr outd
+		ldb #' '
+		jsr putchar	;Display Eaddr + space
+		lda [addr]
+		jsr outbyte
+		ldb #' '
+		jsr putchar
+                ldx #linebuf
+		ldb #buflen
+		jsr getline     ;Get the line.
+		tstb
+		beq skipbyte
+		abx
+		clr ,x
+		ldx #linebuf
+		bsr entline
+		bne ent2
+		jmp cmdline 
+skipbyte	ldd addr
+		addd #1
+		std addr
+		bra ent2
+
+* Enter a line of hex bytes or ascci string at address X, Z if empty.
+entline		jsr skipspace
+		tstb
+		beq entexit
+		cmpb #'.'
+		beq entexit
+		cmpb #'"'
+		beq entasc 
+		leax -1,x
+		ldy addr
+entl2		jsr scanbyte  ;Enter hex digits.
+		beq entdone
+		sta ,y+
+		bra entl2
+entasc		ldy addr
+entl3		lda ,x+
+		tsta
+		beq entdone
+		cmpa #'"'
+		beq entdone
+		sta ,y+
+		bra entl3
+entdone		sty addr
+		andcc #$fb
+		rts
+entexit		orcc #$04
+		rts
+
+*This is the code for the I command, display the contents of an address
+* Syntax: Iaddr
+inp		ldx #linebuf+1
+		jsr scanhex
+		tfr d,x
+		lda ,x		;Read the byte from memory.
+		jsr outbyte	;Display itin hex.
+		jsr putcr
+		jmp cmdline		 
+
+*This is the code for the H command, display result of simple hex expression
+*Syntax Hhexnum{+|-hexnum}
+calc		ldx #linebuf+1
+		jsr scanhex
+		std temp3
+hexloop		jsr skipspace
+		cmpb #'+'
+		bne hex1
+		jsr scanhex
+		addd temp3
+		std temp3
+		bra hexloop
+hex1		cmpb #'-'
+		bne hexend
+		jsr scanhex
+		comb
+		coma
+		addd #1
+		addd temp3
+		std temp3
+		bra hexloop
+hexend		ldd temp3
+		jsr outd
+		jsr putcr
+		jmp cmdline		
+
+* This is the code for the G command, jump to the program
+* Syntax G or G<addr>
+go		ldx #linebuf+1
+		jsr scanhex
+		beq launch		
+		std 10,s	;Store parameter in pc location.
+launch		jsr arm         ;Arm the breakpoints.  
+		puls ccr,b,a,dp,x,y,u,pc
+
+* This is the code for the J command, run a subroutine.
+* Syntax J<addr>
+jump		ldx #linebuf+1
+		ldd 10,s	        
+		std oldpc	;Save old pc
+		jsr scanhex
+		std 10,s	;Store parameter in PC location
+		tfr s,x
+		leas -2,s
+		tfr s,u
+		ldb #12		;Move the saved register set 2 addresses
+		jsr blockmove   ;down on the stack.
+		ldd #stakregs
+		std 12,s	;Prepare subroutine return address.
+		bra launch	;Jump to the routine.
+
+
+* This is the code for the P command, run instruction followed by breakpoint
+* Syntax P
+prog		ldy 10,s	;Get program counter value.
+		jsr disdecode	;Find out location past current insn.
+		sty stepbp
+		bra launch
+
+* This is the code for the T command, single step trace an instruction.
+* Syntax T
+trace		jsr traceone
+		jsr dispregs
+		jmp cmdline
+
+traceone	orcc #$50	;Disable the interrupts.
+		ldd ,s++	
+		std oldpc	;Remove saved pc from stack.
+		ldd #traceret
+		std firqvec+1   ;Adjust timer IRQ vector.
+		sync		;Synchronize on the next timer interrupt.
+				;1 cycle
+		ldx #4441	;3 cycles
+traceloop	leax -1,x       ;6 cycles\x4441= 39969 cycles.
+		bne traceloop	;3 cycles/
+		nop		;2 cycles.
+		nop		;2 cycles.
+		nop		;2 cycles.
+		brn traceret	;3 cycles.
+		puls x,y,u,a,b,dp,cc,pc ;17 cycles, total=39999 20ms @ 2MHz
+					;Pull all registers and execute.
+					;Is timed such that next timer IRQ
+					;occurs right after it.
+traceret	puls cc
+		pshs x,y,u,a,b,dp,cc;Store full register set instead of cc.
+		ldd #timerirq
+		std firqvec+1	;Restore timer IRQ vector.
+		jmp [oldpc]
+				
+
+* Display the contents of 8 bit register, name in B, contents in A
+disp8		jsr putchar
+		ldb #'='
+		jsr putchar
+		jsr outbyte
+		ldb #' '
+		jsr putchar
+		rts
+
+* Display the contents of 16 bit register, name in B, contents in Y
+disp16		jsr putchar
+		ldb #'='
+		jsr putchar
+		tfr y,d
+		jsr outd
+		ldb #' '
+		jsr putchar
+		rts
+
+* Display the contents of the registers and disassemble instruction at
+* PC location.
+dispregs	ldb #'X'
+		ldy 6,s		;Note that there's one return address on
+		bsr disp16	;stack so saved register offsets are 
+		ldb #'Y'	;inremented by 2.
+		ldy 8,s
+		bsr disp16
+		ldb #'U'
+		ldy 10,s
+		bsr disp16
+		ldb #'S'
+		tfr s,y
+		leay 14,y	;S of the running program is 12 higher,
+				;because regs are not stacked when running.
+		bsr disp16
+		ldb #'A'
+		lda 3,s
+		bsr disp8
+		ldb #'B'
+		lda 4,s
+		bsr disp8
+		ldb #'D'
+		lda 5,s
+		bsr disp8
+		ldb #'C'
+		lda 2,s
+		bsr disp8
+		jsr putcr
+		ldb #'P'
+		ldy 12,s
+		bsr disp16
+		jsr disdecode
+		jsr disdisp       ;Disassemble instruction at PC
+		jsr putcr
+		rts
+
+
+* This is the code for the R command, display or alter the registers.
+* Syntax R or R<letter><hex>	
+regs		ldx #linebuf+1
+		jsr skipspace
+		tstb
+		bne setreg		
+		bsr dispregs	;Display regs ifnothing follows.
+		jmp cmdline
+setreg		ldy #regtab	
+		clra
+		andb #CASEMASK	;Make letter uppercase.
+sr1		tst ,y
+		lbeq unk	;At end of register tab, unknown reg
+		cmpb ,y+
+		beq sr2		;Found the register?
+		inca
+		bra sr1		
+sr2		pshs a
+		jsr scanhex	;Convert the hex argument.
+		pshs d
+		lda 2,s		;Get register number.
+		cmpa #4
+		bcc sr3		
+		ldb 1,s		;It's 8 bit. 		
+		leas 3,s	;Remove temp stuff from stack.
+		stb a,s		;Store it in the reg on stack.
+		jmp cmdline
+sr3		cmpa #8
+		bcc sr4		
+		puls x		;It's 16 bit.
+		leas 1,s
+		lsla
+		suba #4		;Convert reg no to stack offset.
+		stx a,s
+		jmp cmdline
+sr4		puls u		;It's the stack pointer.
+		leas 1,s
+		leau -12,u      
+		tfr s,x
+		tfr u,s		;Set new stack pointer.
+		ldb #12
+		jsr blockmove	;Move register set to new stack location.
+		jmp cmdline				
+		
+regtab 		FCC "CABDXYUPS "
+
+* Disarm the breakpoints, this is replace the SWI instructions with the
+* original byte.
+disarm		ldx #bpaddr
+		lda #brkpoints+1
+disarm1		ldu ,x++        
+		ldb ,x+		;Get address in u, byte in b
+		cmpu #0
+		beq disarm2
+		stb ,u
+disarm2		deca
+		bne disarm1
+		ldu #0
+		stu -3,x	;Clear the step breakpoint.
+		rts
+
+* Arm the breakponts, this is replace the byte at the breakpoint address
+* with an SWI instruction.
+arm		ldx #bpaddr+brkpoints*3
+		lda #brkpoints+1  ;Arm them in reverse order of disarming.
+arm1		ldu ,x       ;Get address in u.
+		beq arm2
+		ldb ,u
+		stb 2,x
+		cmpu 12,s      ;Compare to program counter location
+		beq arm2
+		ldb #$3F
+		stb ,u	       ;Store SWI instruction if not equal.
+arm2		leax -3,x
+		deca
+		bne arm1		
+		rts
+
+* This is the code for the break command, set, clear display breakpoints.
+* Syntax B or B<addr>. B displays, B<addr> sets or clears breakpoint.
+break		lda #brkpoints
+		sta temp2+1     ;Store number of breakpoints to visit.
+		ldx #linebuf+1
+		jsr scanhex
+		beq dispbp	;No number then display breakpoints
+		ldx #bpaddr
+		ldu #0
+		tfr u,y
+bp1		cmpd ,x
+		beq clearit	;Found the breakpoint, so clear it,
+		cmpu ,x		;Is location zero
+		bne bp2
+		tfr x,y		;Set free address to y
+bp2		leax 3,x
+		dec temp2+1
+		bne bp1
+		cmpy #0		;Address not found in list of breakpoints
+		beq bpfull	;Was free address found.
+		std ,y		;If so, store breakpoint there.
+		ldx #brkmsg	
+bpexit		jsr outcount
+		jsr putcr
+		jmp cmdline
+clearit		clra
+		clrb
+		std ,x
+		ldx #clrmsg
+		bra bpexit
+bpfull		ldx #fullmsg
+		bra bpexit		
+
+dispbp 		ldx #bpaddr
+dbp1		ldd ,x
+		beq dbp2
+		jsr outd
+		ldb #' '
+		jsr putchar
+dbp2		leax 3,x
+		dec temp2+1
+		bne dbp1
+		jsr putcr
+		jmp cmdline
+
+* Scan hex byte into a and add it to check sum in temp2+1
+addchk		jsr scanbyte
+		lbeq srecerr
+		tfr a,b
+		addb temp2+1
+		stb temp2+1
+		rts
+
+* This tis the code for the S command, the Motorola S records entry.
+* Syntax SO<addr> or SS<addr>,<len> or S1<bytes> or S9<bytes>
+srec		ldx #linebuf+1
+		ldb ,x+
+		andb #CASEMASK
+		cmpb #'O'
+		beq setsorg
+		cmpb #'S'
+		beq sendrec
+		ldb -1,x
+		clr temp3
+		cmpb #'1'
+		beq readrec
+		cmpb #'9'
+		bne srecerr
+		inc temp3		
+readrec		clr temp2+1	;clear checksum.
+		bsr addchk
+		suba #2		;discount the address bytes from the count.
+		sta temp3+1	;Read length byte.
+		bsr addchk
+		pshs a
+		bsr addchk
+		puls b
+		exg a,b		;Read address into d.
+		ldu sorg
+		beq rr1		
+		ldu soffs
+		bne rr1
+		pshs d		;Sorg is nonzero and soffs is zero, now
+		subd sorg	;set soffs
+		std soffs
+		puls d
+rr1		subd soffs	;Subtract the address offset.
+		tfr d,y
+rr2		bsr addchk	
+		dec temp3+1
+		beq endrec
+		sta ,y+
+		bra rr2
+endrec		inc temp2+1	;Check checksum.
+		bne srecerr
+		tst temp3
+		lbeq cmdline	;Was it no S9 record?
+		cmpy #0
+		beq endrec1 
+		sty 10,s	;Store address into program counter.
+endrec1		clra
+		clrb
+		std sorg	;Reset sorg, next S loads will be normal.
+		std soffs
+		jmp cmdline	
+srecerr		jsr xabortin
+		ldx #smsg	;Error in srecord, display message.
+		jsr outcount
+		jsr putcr
+		jmp cmdline
+setsorg		jsr scanhex	;Set S record origin.
+		std sorg
+		clra 
+		clrb
+		std soffs
+		jmp cmdline
+* Send a memory region as S-records.
+sendrec		ldd #$100	;Scan address and length parameter.
+		jsr scan2parms				
+		ldd sorg
+		beq ss1
+		ldd addr
+		subd sorg
+		std soffs	;Compute offset for origin.
+ss1		ldd length	
+		beq endss	;All bytes sent?
+		cmpd #16
+		blo ss2         
+		ldb #16		;If more than 16 left, then send 16.
+ss2		stb temp
+		negb
+		ldu length
+		leau b,u
+		stu length	;Discount line length from length.
+		ldb #'S'
+		jsr putchar
+		ldb #'1'
+		jsr putchar
+		clr temp+1	;Clear check sum
+		ldb temp
+		addb #3
+		bsr checkout	;Output byte b as hex and add to check sum.
+		ldd addr
+		tfr d,y
+		subd soffs
+		exg a,b
+		bsr checkout
+		exg a,b
+		bsr checkout	;Output address (add into check sum)
+ss3		ldb ,y+
+		bsr checkout
+		dec temp
+		bne ss3
+		sty addr
+		ldb temp+1
+		comb
+		bsr checkout	;Output checksum byte.
+		jsr putcr
+		bra ss1
+endss		ldx #lastrec
+		jsr outcount
+		jsr putcr
+		jmp cmdline
+* Output byte in register B and add it into check sum at temp+1
+checkout	pshs a
+		tfr b,a
+		addb temp+1
+		stb temp+1
+		jsr outbyte
+		puls a
+		rts
+
+* This is the code for the M command, move memory region.
+* Syntax: Maddr1,addr2,length
+move		ldx #linebuf+1
+		jsr scanhex
+		lbeq unk
+		std temp3
+		jsr skipspace
+		cmpb #','
+		lbne unk
+		jsr scanhex
+		lbeq unk
+		tfr d,u
+		jsr skipspace
+		cmpb #','
+		lbne unk
+		jsr scanhex
+		lbeq unk
+		tfr d,y		;Read the argument separated by commas
+		ldx temp3	;src addr to x, dest addr to u, length to y
+			        ;Don't tolerate syntax deviations.
+mvloop		lda ,x+
+		sta ,u+
+		leay -1,y
+		bne mvloop	;Perform the block move.
+		jmp cmdline
+		
+
+* This is the code for the F command, find byte/ascii string in memory.
+* Syntax: Faddr bytes or Faddr "ascii"
+find		ldx #linebuf+1
+		jsr scanhex
+		tfr d,y		;Scan the start address.
+		jsr skipspace
+		cmpb #'"'
+		bne findhex
+		ldu #linebuf	;Quote found, so scan for quoted string.
+		clra
+fstrloop	ldb ,x+
+		beq startsrch	;End of line without final quote.
+		cmpb #'"'
+		beq startsrch   ;End quote found
+		stb ,u+
+		inca
+		bra fstrloop		 		
+findhex		ldu #linebuf	;Convert string of hex bytes.
+		leax -1,x	;String will be stored at start of line
+		clra		;buffer and may overwrite part of the
+fhexloop	pshs a		;already converted string.
+		jsr scanbyte
+		tfr a,b
+		puls a
+		beq startsrch	
+		stb ,u+
+		inca
+		bra fhexloop				
+startsrch	tsta		;Start searching, start addr in Y, 
+		                ;string starts at linebuf, length A
+		lbeq cmdline	;Quit with zero length string.
+		clr temp3
+		sta temp3+1
+srchloop	tfr y,x
+		lda temp3+1
+		cmpx #$e100
+		bcc srch1
+		leax a,x
+		cmpx #$e000	;Stop at I/O addresses.
+		lbcc cmdline
+srch1		tfr y,x
+		ldu #linebuf
+srch2		ldb ,x+
+		cmpb ,u+
+		bne srch3       ;Not equal, try next address.
+		deca 
+		bne srch2
+		tfr y,d
+		jsr outd	;String found
+		jsr putcr
+		inc temp3
+		lda temp3
+		cmpa #$10
+		lbeq cmdline	;If 10 matches found, just stop.
+srch3		leay 1,y
+		bra srchloop
+
+* Send the contents of the xmodem buffer and get it acknowledged, zero flag
+* is set if transfer aborted.
+xsendbuf	ldb #SOH		
+		jsr osputc	;Send SOH
+		ldb xpacknum
+		jsr osputc	;Send block number.
+		comb
+		jsr osputc      ;and its complement.
+		clr xsum
+		lda #128
+		ldx #buf0
+xsloop		ldb ,x
+	        addb xsum
+		stb xsum	
+		ldb ,x+
+		jsr osputc
+		deca
+		bne xsloop      ;Send the buffer contents.
+		ldb xsum
+		jsr osputc	;Send the check sum
+waitack		jsr osgetc
+		cmpb #CAN
+		beq xsabt	;^X for abort.
+		cmpb #NAK        
+		beq xsendbuf	;Send again if NAK
+		cmpb #ACK
+		bne waitack
+		inc xpacknum
+xsok		andcc #$fb	;Clear zero flag after ACK		
+xsabt		rts
+		
+* Start an XMODEM send session.
+xsendinit	ldb #1
+		stb xpacknum	;Initialize block number.
+waitnak		jsr osgetc
+		cmpb #CAN
+		beq xsabt      ;If ^X exit with zero flag.
+		cmpb #NAK
+		beq xsok        
+		bra waitnak    ;Wait until NAK received.
+
+* Send ETX and wait for ack.
+xsendeot	ldb #EOT
+		jsr osputc
+waitack2	jsr osgetc
+		cmpb #CAN
+		beq xsabt
+		cmpb #NAK
+		beq xsendeot
+		cmpb #ACK
+		beq xsok
+		bra waitack2
+
+* Read character into B with a timeout of A seconds,  Carry set if timeout.
+gettimeout	asla
+		ldb #50
+		mul
+		tfr b,a
+		adda timer+2
+gt1		jsr osgetpoll
+		tstb
+		bne gtexit
+		cmpa timer+2
+		bne gt1		
+		orcc #$1
+		rts
+gtexit		jsr osgetc
+		andcc #$fe
+		rts
+
+* Wait until line becomes quiet.
+purge		lda #3
+		jsr gettimeout
+		bcc purge
+		rts
+
+* Receive an XMODEM block and wait till it is OK, Z set if etx.				
+xrcvbuf		lda #3
+		tst lastok				
+		beq sendnak
+		ldb #ACK
+		jsr osputc	;Send an ack.
+		lda #5         
+		bra startblock
+sendnak		ldb #NAK
+		jsr osputc	;Send a NAK
+startblock	clr lastok
+		bsr gettimeout   
+		lda #3
+		bcs sendnak	;Keep sending NAKs when timed out.
+		cmpb #EOT		
+		beq xrcveot	;End of file reached, acknowledge EOT.
+		cmpb #SOH
+		bne purgeit	;Not, SOH, bad block.
+		lda #1
+		bsr gettimeout	
+		bcs purgeit				
+		cmpb xpacknum	;Is it the right block?
+		beq xr1
+		incb
+		cmpb xpacknum   ;Was it the previous block.
+		bne purgeit	
+		inc lastok
+xr1		stb xsum
+		lda #1
+		bsr gettimeout
+		bcs purgeit
+		comb
+		cmpb xsum       ;Is the complement of the block number OK
+		bne purgeit		
+		ldx #buf0
+		clr xsum
+xrloop		lda #1
+		bsr gettimeout  
+		bcs purgeit
+		stb ,x+
+		addb xsum
+		stb xsum
+		cmpx #buf0+128
+		bne xrloop       ;Get the data bytes.		
+		lda #1
+		bsr gettimeout
+		bcs purgeit
+		cmpb xsum
+		bne purgeit	;Check the check sum.
+		tst lastok
+		bne xrcvbuf	;Block was the previous block, get next one
+		inc lastok
+		inc xpacknum
+		andcc #$fb
+		rts
+purgeit		jsr purge
+		bra sendnak		
+xrcveot		lda #3		;EOT was received.
+		ldb #ACK
+ackloop		jsr osputc
+		deca
+		bne ackloop     ;Send 3 acks in a row.
+		rts
+
+
+savevecs	ldx getchar+1
+		stx oldgetc
+		ldx putchar+1
+		stx oldputc
+		ldx putcr+1
+		stx oldputcr
+		clr lastterm
+		rts
+
+rstvecs		ldx oldgetc
+		stx getchar+1
+		ldx oldputc
+		stx putchar+1
+		ldx oldputcr
+		stx putcr+1
+		clr lastterm
+		rts	
+
+* O.S. routine to open input through XMODEM transfer.
+xopin		pshs x,a,b
+		ldx #xsmsg
+		jsr outcount
+		jsr putcr	;Display message to start XMODEM send.
+		bsr savevecs
+		ldx #noop
+		stx putchar+1	;Disable character output.
+		ldx #xgetc
+		stx getchar+1	;
+		clr lastok
+		clr xcount
+		lda #1
+		sta xpacknum
+		inca
+		sta xmode	;set xmode to 2.
+		puls x,a,b,pc
+
+* O.S. routine to open output through XMODEM transfer.
+xopout		pshs x,a,b
+		bsr savevecs
+		ldx #xrmsg
+		jsr outcount	;Display message to start XMODEM receive
+		jsr putcr
+		ldx #xputc
+		stx putchar+1
+		ldx #xputcr
+		stx putcr+1
+		jsr xsendinit
+		lbeq xerror
+		clr xcount
+		lda #1
+		sta xmode
+		puls x,a,b,pc
+		
+
+* O.S. routine to abort input through XMODEM transfer.
+xabtin		lda xmode
+		cmpa #2
+		bne xclsend
+		jsr purge
+		ldb #CAN
+		lda #8
+xabtloop	jsr osputc
+		deca
+		bne xabtloop	;Send 8 CAN characters to kill transfer.
+		bsr rstvecs
+		clr xmode
+		ldx #xamsg
+		jsr outcount
+		jsr putcr	;Send diagnostic message.
+		rts		
+
+* O.S. routine to close output through XMODEM transfer.
+xclsout		lda xmode 
+		cmpa #1
+		bne xclsend
+		tst xcount
+		beq xclsdone
+		lda #128
+		suba xcount
+xclsloop	ldb filler
+		bsr xputc   
+		deca
+		bne xclsloop	;Transfer filler chars to force block out.
+xclsdone	jsr xsendeot	;Send EOT
+		lbeq xerror
+		jsr rstvecs
+		clr xmode						
+xclsend		rts	
+
+* O.S. routine to close input through XMODEM, by gobbling up the remaining
+* bytes.
+xclsin		ldb xmode
+		cmpb #2
+		bne xclsend
+		jsr putchar
+		bra xclsin
+
+* putchar routine for XMODEM 
+xputc		pshs x,a,b
+		lda xcount
+		inc xcount
+		ldx #buf0
+		stb a,x		;Store character in XMODEM buffer.
+		cmpa #127
+		bne xputc1	;is buffer full?
+		clr xcount
+		pshs y,u
+		jsr xsendbuf	
+		lbeq xerror
+		puls y,u
+xputc1		puls x,a,b,pc			
+
+* putcr routine for XMODEM
+xputcr		pshs b
+		ldb xmcr
+		bitb #2
+		beq xputcr1
+		ldb #CR
+		bsr xputc
+xputcr1		ldb xmcr
+		bitb #1
+		beq xputcr2
+		ldb #LF
+		bsr xputc		
+xputcr2		puls b
+		rts
+
+* getchar routine for XMODEM
+xgetc		pshs x,a
+		tst xcount	;No characters left?
+		bne xgetc1
+		pshs y,u
+		jsr xrcvbuf	;Receive new block.
+		puls y,u
+		beq xgetcterm	;End of input?		
+		lda #128
+		sta xcount
+xgetc1		lda xcount
+		nega
+		ldx #buf0+128
+		ldb a,x		;Get character from buffer
+		dec xcount
+		puls x,a,pc		
+xgetcterm	jsr rstvecs
+		clr xmode
+		ldb filler
+		puls x,a,pc
+		
+xerror		jsr rstvecs	;Restore I/O vectors
+		clr xmode
+		ldx #xamsg
+		jsr outcount
+		jsr putcr
+		jmp xerrvec
+	
+xerrhand	lds savesp
+		jmp cmdline
+
+* This is the code for the X command, various XMODEM related commands.
+* Syntax: XSaddr,len XLaddr,len XX XOcrlf,filler, XSSaddr,len
+xmodem		ldx #linebuf+1
+		lda ,x+
+		anda #CASEMASK	;Convert to uppercase.
+		cmpa #'X'
+		beq xeq	
+		cmpa #'L'
+		beq xload
+		cmpa #'O'
+		beq xopts
+		cmpa #'S'
+		lbne unk
+		lda ,x
+		anda #CASEMASK
+		cmpa #'S'
+		beq xss
+		ldd #$100            ;XSaddr,len command.
+		jsr scan2parms       ;Send binary through XMODEM
+		jsr xopenout
+		ldu addr
+		ldy length
+xsbinloop	ldb ,u+
+		jsr putchar		
+		leay -1,y
+		bne xsbinloop 	     ;Send all the bytes through XMODEM.
+		jmp cmdline
+xss		leax 1,x	     ;XSSaddr,len command.
+		jsr xopenout	     ;Send Srecords through XMODEM
+		jmp sendrec		
+xload		jsr scanhex	     ;XLaddr command
+		tfr d,y		     ;Load binary through XMODEM
+		jsr xopenin
+xlodloop	jsr getchar
+		tst xmode	     ;File ended? then done
+		lbeq cmdline					
+		stb ,y+
+		bra xlodloop
+xeq		jsr xopenin	     ;XX command
+		jmp cmdline	     ;Execute commands received from XMODEM
+xopts		ldd #$1a
+		jsr scan2parms
+		lda addr+1
+		sta xmcr
+		lda length+1
+		sta filler
+		jmp cmdline
+	
+* mnemonics table, ordered alphabetically.
+* 5 bytes name, 1 byte category, 2 bytes opcode, 8 bytes total.
+mnemtab         fcc "ABX  "
+                fcb 0
+                fdb $3a
+                fcc "ADCA "
+                fcb 7
+                fdb $89
+                fcc "ADCB "
+                fcb 7
+                fdb $c9
+                fcc "ADDA "
+                fcb 7
+		fdb $8b
+                fcc "ADDB "
+                fcb 7
+                fdb $cb 
+                fcc "ADDD "
+		fcb 8
+		fdb $c3
+                fcc "ANDA "
+                fcb 7
+                fdb $84
+                fcc "ANDB "
+                fcb 7
+                fdb $c4
+                fcc "ANDCC"
+ 		fcb 2
+		fdb $1c
+                fcc "ASL  "
+		fcb 10
+		fdb $08
+                fcc "ASLA "
+		fcb 0
+		fdb $48
+		fcc "ASLB "
+		fcb 0
+		fdb $58
+                fcc "ASR  "
+                fcb 10
+                fdb $07
+                fcc "ASRA "
+		fcb 0
+		fdb $47
+                fcc "ASRB "
+		fcb 0
+		fdb $57
+                fcc "BCC  "
+		fcb 4
+		fdb $24
+                fcc "BCS  "
+		fcb 4 
+		fdb $25
+                fcc "BEQ  "
+		fcb 4
+		fdb $27
+                fcc "BGE  "
+		fcb 4
+		fdb $2c
+                fcc "BGT  "
+		fcb 4
+		fdb $2e
+                fcc "BHI  "
+		fcb 4
+		fdb $22
+                fcc "BHS  "
+		fcb 4
+		fdb $24
+                fcc "BITA "
+		fcb 7
+		fdb $85
+                fcc "BITB "
+		fcb 7
+		fdb $c5
+                fcc "BLE  "
+		fcb 4
+		fdb $2f
+                fcc "BLO  "
+		fcb 4
+		fdb $25
+                fcc "BLS  "
+		fcb 4
+		fdb $23
+                fcc "BLT  "
+		fcb 4
+		fdb $2d
+                fcc "BMI  "
+		fcb 4
+		fdb $2b
+                fcc "BNE  "
+		fcb 4
+		fdb $26
+                fcc "BPL  "
+		fcb 4
+		fdb $2a
+                fcc "BRA  "
+		fcb 4
+		fdb $20 
+                fcc "BRN  "
+		fcb 4
+		fdb $21
+mnembsr         fcc "BSR  "
+		fcb 4
+		fdb $8d
+                fcc "BVC  "
+		fcb 4
+		fdb $28
+                fcc "BVS  "
+		fcb 4
+		fdb $29
+                fcc "CLR  "
+		fcb 10
+		fdb $0f
+                fcc "CLRA "
+		fcb 0
+		fdb $4f
+                fcc "CLRB "
+		fcb 0
+		fdb $5f
+                fcc "CMPA "
+		fcb 7
+		fdb $81
+                fcc "CMPB "
+		fcb 7
+		fdb $c1
+                fcc "CMPD "
+		fcb 9
+		fdb $1083
+                fcc "CMPS "
+		fcb 9
+		fdb $118c
+                fcc "CMPU "
+		fcb 9
+		fdb $1183
+                fcc "CMPX "
+		fcb 8
+		fdb $8c
+                fcc "CMPY "
+		fcb 9
+		fdb $108c
+                fcc "COM  "
+		fcb 10
+		fdb $03
+                fcc "COMA "
+		fcb 0
+		fdb $43
+                fcc "COMB "
+		fcb 0
+		fdb $53
+                fcc "CWAI "
+		fcb 2
+		fdb $3c
+                fcc "DAA  "
+		fcb 0
+		fdb $19
+                fcc "DEC  "
+		fcb 10
+		fdb $0a
+                fcc "DECA "
+		fcb 0
+		fdb $4a
+                fcc "DECB "
+		fcb 0
+		fdb $5a
+                fcc "EORA "
+		fcb 7
+		fdb $88
+                fcc "EORB "
+		fcb 7
+		fdb $c8
+                fcc "EQU  "
+		fcb 13
+		fdb 0
+                fcc "EXG  "
+		fcb 11
+		fdb $1e
+mnemfcb         fcc "FCB  "
+		fcb 13
+		fdb 1
+                fcc "FCC  "
+		fcb 13
+		fdb 2
+                fcc "FDB  "
+		fcb 13
+		fdb 3
+                fcc "INC  "
+		fcb 10
+		fdb $0c
+                fcc "INCA "
+		fcb 0
+		fdb $4c
+                fcc "INCB "
+		fcb 0
+		fdb $5c
+                fcc "JMP  "
+		fcb 10
+		fdb $0e
+mnemjsr         fcc "JSR  "
+		fcb 8
+		fdb $8d
+                fcc "LBCC "
+		fcb 5
+		fdb $1024
+                fcc "LBCS "
+		fcb 5
+		fdb $1025
+                fcc "LBEQ "
+		fcb 5
+		fdb $1027
+                fcc "LBGE "
+		fcb 5
+		fdb $102c
+                fcc "LBGT "
+		fcb 5
+		fdb $102e
+                fcc "LBHI "
+		fcb 5
+		fdb $1022
+                fcc "LBHS "
+		fcb 5
+		fdb $1024
+                fcc "LBLE "
+		fcb 5
+		fdb $102f
+                fcc "LBLO "
+		fcb 5
+		fdb $1025
+                fcc "LBLS "
+		fcb 5
+		fdb $1023
+                fcc "LBLT "
+		fcb 5
+		fdb $102d
+                fcc "LBMI "
+		fcb 5
+		fdb $102b
+                fcc "LBNE "
+		fcb 5
+		fdb $1026
+                fcc "LBPL "
+		fcb 5
+		fdb $102a
+                fcc "LBRA "
+		fcb 6
+		fdb $16
+                fcc "LBRN "
+		fcb 5
+		fdb $1021
+                fcc "LBSR "
+		fcb 6
+		fdb $17
+                fcc "LBVC "
+		fcb 5
+		fdb $1028
+                fcc "LBVS "
+		fcb 5
+		fdb $1029
+                fcc "LDA  "
+		fcb 7
+		fdb $86
+                fcc "LDB  "
+		fcb 7
+		fdb $c6
+                fcc "LDD  "
+		fcb 8
+		fdb $cc
+                fcc "LDS  "
+		fcb 9
+		fdb $10ce
+                fcc "LDU  "
+		fcb 8
+		fdb $ce
+                fcc "LDX  "
+		fcb 8
+		fdb $8e
+                fcc "LDY  "
+		fcb 9
+		fdb $108e
+                fcc "LEAS "
+		fcb 3
+		fdb $32
+                fcc "LEAU "
+		fcb 3
+		fdb $33
+                fcc "LEAX "
+		fcb 3
+		fdb $30
+                fcc "LEAY "
+		fcb 3
+		fdb $31
+                fcc "LSL  "
+		fcb 10
+		fdb $08
+                fcc "LSLA "
+		fcb 0
+		fdb $48
+                fcc "LSLB "
+		fcb 0
+		fdb $58
+                fcc "LSR  "
+		fcb 10
+		fdb $04
+                fcc "LSRA "
+		fcb 0
+		fdb $44
+                fcc "LSRB "
+		fcb 0
+		fdb $54
+                fcc "MUL  "
+		fcb 0
+		fdb $3d
+                fcc "NEG  "
+		fcb 10
+		fdb $00
+                fcc "NEGA "
+		fcb 0
+		fdb $40
+                fcc "NEGB "
+		fcb 0
+		fdb $50
+                fcc "NOP  "
+		fcb 0
+		fdb $12
+                fcc "ORA  "
+		fcb 7
+		fdb $8a
+                fcc "ORB  "
+		fcb 7
+		fdb $ca
+                fcc "ORCC "
+		fcb 2
+		fdb $1a
+                fcc "ORG  "
+		fcb 13
+		fdb 4
+                fcc "PSHS "
+		fcb 12
+		fdb $34
+                fcc "PSHU "
+		fcb 12
+		fdb $36
+                fcc "PULS "
+		fcb 12
+		fdb $35
+                fcc "PULU "
+		fcb 12
+		fdb $37
+                fcc "RMB  "
+		fcb 13
+		fdb 5
+                fcc "ROL  "
+		fcb 10
+		fdb $09
+                fcc "ROLA "
+		fcb 0
+		fdb $49
+                fcc "ROLB "
+		fcb 0
+		fdb $59
+                fcc "ROR  "
+		fcb 10
+		fdb $06
+                fcc "RORA "
+		fcb 0
+		fdb $46
+                fcc "RORB "
+		fcb 0
+		fdb $56
+                fcc "RTI  "
+		fcb 0
+		fdb $3b
+                fcc "RTS  "
+		fcb 0
+		fdb $39
+                fcc "SBCA "
+		fcb 7
+		fdb $82
+                fcc "SBCB "
+		fcb 7
+		fdb $c2
+                fcc "SET  "
+		fcb 13
+		fdb 6
+                fcc "SETDP"
+		fcb 13
+		fdb 7
+                fcc "SEX  "
+		fcb 0
+		fdb $1d
+                fcc "STA  "
+		fcb 7
+		fdb $87
+                fcc "STB  "
+		fcb 7
+		fdb $c7
+                fcc "STD  "
+		fcb 8
+		fdb $cd
+                fcc "STS  "
+		fcb 9
+		fdb $10cf
+                fcc "STU  "
+		fcb 8
+		fdb $cf
+                fcc "STX  "
+		fcb 8
+		fdb $8f
+                fcc "STY  "
+		fcb 9
+		fdb $108f
+                fcc "SUBA "
+		fcb 7
+		fdb $80
+                fcc "SUBB "
+		fcb 7
+		fdb $c0 
+                fcc "SUBD "
+		fcb 8
+		fdb $83
+                fcc "SWI  "
+		fcb 0
+		fdb $3f
+                fcb "SWI2 "
+		fcb 1
+		fdb $103f
+                fcb "SWI3 "
+		fcb 1
+		fdb $113f
+                fcc "SYNC "
+		fcb 0
+		fdb $13
+                fcc "TFR  "
+		fcb 11
+		fdb $1f
+                fcc "TST  "
+		fcb 10
+		fdb $0d
+                fcc "TSTA "
+		fcb 0
+		fdb $4d
+                fcc "TSTB "
+		fcb 0
+		fdb $5d
+
+mnemsize	equ (*-mnemtab)/8
+
+* Register table for PUSH/PULL and TFR/EXG instructions.
+* 3 bytes for name, 1 for tfr/exg, 1 for push/pull, 5 total 
+asmregtab     	fcc "X  "
+		fcb $01,$10
+		fcc "Y  "
+		fcb $02,$20
+aregu           fcc "U  "
+		fcb $03,$40
+aregs		fcc "S  "
+		fcb $04,$40
+		fcc "PC "
+		fcb $05,$80
+                fcc "A  "
+		fcb $08,$02
+		fcc "B  "
+		fcb $09,$04
+		fcc "D  "
+		fcb $00,$06
+		fcc "CC "
+		fcb $0a,$01
+		fcc "CCR"
+		fcb $0a,$01
+		fcc "DP "
+		fcb $0b,$08
+		fcc "DPR"
+		fcb $0b,$08
+reginval	fcc "?  "
+
+ixregs		fcc "XYUS"
+
+* opcode offsets to basic opcode, depends on first nibble. 
+opcoffs		fcb 0,0,0,0,0,0,-$60,-$70
+		fcb 0,-$10,-$20,-$30,0,-$10,-$20,-$30
+* mode depending on first nibble of opcode.
+modetab		fcb 3,0,0,0,0,0,5,4,1,3,5,4,1,3,5,4
+* mode depending on category code stored in mnemtab
+modetab2	fcb 0,0,1,5,6,7,7,1,2,2,0,8,9
+* modes in this context: 0 no operands, 1 8-bit immediate, 2 16 bit imm,
+* 3, 8-bit address, 4 16 bit address, 5 indexed with postbyte, 6 short
+* relative, 7 long relative, 8 pushpul, 9 tftetx
+
+* Decode instruction pointed to by Y for disassembly (and to find out
+* how long it is). On return, U points to appropriate mnemonic table entry,
+* Y points past instruction. 
+* It's rather clumsy code, but we do want to reuse the same table
+* as used with assembling.
+disdecode	clr prebyte
+		clr amode
+		lda ,y+
+		cmpa #$10
+		beq ddec1
+		cmpa #$11
+		bne ddec2
+ddec1		sta prebyte         ;Store $10 or $11 prebyte.
+		lda ,y+             ;Get new opcode.
+ddec2		sta opcode
+		lsra
+		lsra
+		lsra
+		lsra		    ;Get high nibble.
+		ldx #modetab
+		ldb a,x
+		stb amode
+		ldx #opcoffs
+		lda a,x
+		adda opcode         ;Add opcode offset to opcode. 		
+ddec4		sta opc1            ;Store the 'basis' opcode.
+		ldu #mnemtab
+		ldx #mnemsize
+ddecloop	ldb #13
+		cmpb 5,u            ;Compare category code with 13
+		beq ddec3	    ;13=pseudo op, no valid opcode
+		ldd prebyte
+		cmpd 6,u
+		beq ddecfound	    ;Opcode&prebyte agree, operation found.
+ddec3		leau 8,u            ;point to next mnemonic
+		leax -1,x
+		bne ddecloop        
+		ldu #mnemfcb        ;mnemonic not found, use FCB byte.
+		lda #3
+		sta amode	    ;Store mode 3, 8 bit address.
+		lda opcode
+		tst prebyte
+		beq ddec5
+		lda prebyte 	    ;if it was the combination prebyte
+		clr prebyte         ;and opcode that was not found,
+         	leay -1,y 	    ;FCB just the prebyte
+ddec5	        sta operand+1       ;The byte must be stored as operand.	
+		rts
+ddecfound       cmpu #mnembsr
+		bne ddec6
+		lda #$8d	    ;Is it really the BSR opcode?
+		cmpa opcode
+		beq ddec6
+		ldu #mnemjsr        ;We mistakenly found BSR instead of JSR
+ddec6           lda amode
+		anda #$FE
+		bne ddec7
+		lda 5,u             ;nibble-dependent mode was 0 or 1,
+		ldx #modetab2       ;use category dependent mode instead.
+		lda a,x
+		sta amode
+ddec7           lda amode
+		asla
+		ldx #disdectab
+		jmp [a,x]           ;jump dependent on definitive mode.
+disdectab	fdb noop,opdec1,opdec2,opdec1,opdec2,opdecidx
+		fdb opdec1,opdec2,opdecpb,opdecpb
+disdectab1	fdb noop,noop,noop,noop,noop,noop,noop,noop
+		fdb opdec1,opdec2,noop,noop,opdec1,opdec2,noop,opdec2
+opdec1		ldb ,y+
+		sex
+od1a		std operand
+noop		rts 
+opdec2		ldd ,y++
+		bra od1a
+opdecpb		ldb ,y+
+odpa		stb postbyte
+		rts
+opdecidx	ldb ,y+
+		bpl odpa	;postbytes <$80 have no extra operands.
+		stb postbyte    
+		andb #$0f
+		aslb
+		ldx #disdectab1
+		jmp [b,x]
+
+* Display disassembled instruction after the invocation of disdecode.
+* U points to mnemonic table entry.
+disdisp		tfr u,x
+		ldb #5
+		jsr putline      ;Display the mnemonic.
+		ldb #' '
+		jsr putchar
+		lda amode
+		asla
+		ldx #disdisptab
+		jmp [a,x]        ;Perform action dependent on mode.
+disdisptab	fdb noop,disim8,disim16,disadr8,disadr16
+		fdb disidx,disrel8,disrel16,distfr,dispush
+disim8		bsr puthash
+		bra disadr8
+disim16		bsr puthash
+disadr16	bsr putdol
+		ldd operand
+		jmp outd
+disadr8		bsr putdol
+		lda operand+1
+		jmp outbyte
+disrel8		bsr putdol
+		ldb operand+1
+		sex
+dr8a		sty temp
+		addd temp
+		jmp outd
+disrel16	bsr putdol
+		ldd operand
+		bra dr8a
+		
+puthash		ldb #'#'
+		jmp putchar
+putdol		ldb #'$'
+		jmp putchar						    
+putcomma	ldb #','
+		jmp putchar
+putspace	ldb #' '
+		jmp putchar
+
+dispush		ldb #12
+		ldx #asmregtab	;Walk through the register table.
+		clr temp
+regloop		lda postbyte
+		anda 4,x                
+		beq dispush1	;Is bit corresponding to reg set in postbyte
+		cmpx #aregu
+		bne dispush3
+		sta temp+1
+		lda opcode
+		anda #2
+		bne dispush1    ;no u register in pshu pulu.
+		lda temp+1		
+dispush3	cmpx #aregs
+		bne dispush4
+		sta temp+1
+		lda opcode
+		anda #2
+		beq dispush1   ;no s register in pshs puls.
+		lda temp+1
+dispush4	coma
+		anda postbyte   ;remove the bits from postbyte.
+		sta postbyte
+		pshs b          
+		tst temp
+		beq dispush2
+		bsr putcomma	;print comma after first register.
+dispush2	bsr disregname
+		inc temp
+		puls b
+dispush1	leax 5,x
+		decb
+		bne regloop		
+		rts
+
+distfr 		lda postbyte
+		lsra
+		lsra
+		lsra
+		lsra
+		bsr distfrsub
+		bsr putcomma
+		lda postbyte
+		anda #$0f
+distfrsub	ldb #12
+		ldx #asmregtab
+distfrloop	cmpa 3,x
+		beq distfrend
+		leax 5,x
+		decb
+		bne distfrloop
+distfrend	bsr disregname
+		rts
+
+disregname	lda #3
+		tfr x,u
+drnloop		ldb ,u+
+		cmpb #' '
+		beq drnend
+		jsr putchar
+		deca
+		bne drnloop
+drnend		rts
+
+disidxreg	lda postbyte
+		lsra
+		lsra
+		lsra
+		lsra
+		lsra
+		anda #3
+		ldx #ixregs
+		ldb a,x
+		jmp putchar
+
+disidx		clr temp
+		lda postbyte
+		bmi disidx1
+		anda #$1f
+		bita #$10
+		bne negoffs
+		jsr outdecbyte
+		bra discomma
+negoffs		ldb #'-'
+		jsr putchar
+		ora #$f0
+		nega
+		jsr outdecbyte
+discomma	jsr putcomma         ;Display ,Xreg and terminating ]
+disindex	bsr disidxreg
+disindir	tst temp             ;Display ] if indirect.
+		beq disidxend      
+		ldb #']'       
+		jsr putchar
+disidxend	rts
+disidx1		bita #$10			
+		beq disidx2
+		ldb #'['
+		jsr putchar
+		inc temp
+disidx2		lda postbyte
+		anda #$0f
+		asla
+		ldx #disidxtab
+		jmp [a,x]	     ;Jump to routine for indexed mode
+disadec2	lda #2
+		bra disadeca
+disadec1 	lda #1		
+disadeca	jsr putcomma
+disadloop	ldb #'-'
+		jsr putchar
+		deca
+		bne disadloop
+		bra disindex
+disainc2	lda #2
+		bra disainca
+disainc1	lda #1
+disainca	sta temp+1
+		jsr putcomma
+		jsr disidxreg		
+		lda temp+1
+disailoop	ldb #'+'
+		jsr putchar
+		deca
+		bne disailoop
+		jmp disindir
+disax		ldb #'A'
+		jsr putchar
+		jmp discomma
+disbx		ldb #'B'
+		jsr putchar
+		jmp discomma
+disdx		ldb #'D'
+		jsr putchar
+		jmp discomma
+disinval	ldb #'?'
+		jsr putchar
+		jmp disindir
+disnx		lda operand+1
+		bmi disnxneg
+disnx1		jsr putdol
+		jsr outbyte
+		jmp discomma
+disnxneg	ldb #'-'
+		jsr putchar
+		nega
+		bra disnx1
+disnnx		jsr putdol
+		ldd operand
+		jsr outd
+		jmp discomma
+disnpc		jsr putdol
+		ldb operand+1
+		sex
+disnpca		sty temp2
+		addd temp2
+		jsr outd
+		ldx #commapc
+		ldb #4
+		jsr putline
+		jmp disindir
+disnnpc		jsr putdol
+		ldd operand
+		bra disnpca
+disdirect	jsr putdol
+		ldd operand
+		jsr outd		
+		jmp disindir
+
+commapc		fcc ",PCR"
+
+disidxtab	fdb disainc1,disainc2,disadec1,disadec2
+		fdb discomma,disbx,disax,disinval
+		fdb disnx,disnnx,disinval,disdx
+		fdb disnpc,disnnpc,disinval,disdirect		
+
+* Display byte A in decimal (0<=A<20)
+outdecbyte	cmpa #10
+		blo odb1
+		suba #10
+		ldb #'1'
+		jsr putchar
+odb1		adda #'0'
+		tfr a,b
+		jmp putchar
+		
+* This is the code for the U command, unassemble instructions in memory.
+* Syntax: U or Uaddr or Uaddr,length
+unasm		bsr disasm		
+		jmp cmdline
+disasm		ldx #linebuf+1
+		ldd #20
+		jsr scan2parms  ;Scan address,length parameters.
+dis1		ldd addr
+		addd length
+		std length
+		ldy addr
+unasmloop	tfr y,d
+		jsr outd        ;Display instruction address
+		jsr putspace
+		pshs y
+		jsr disdecode
+		puls x
+		sty temp
+		clr temp2
+unadishex	lda ,x+
+		jsr outbyte
+		inc temp2
+		inc temp2
+		cmpx temp
+		bne unadishex  ;Display instruction bytes as hex.
+unadisspc	ldb #' '
+		jsr putchar
+		inc temp2
+		lda #11
+		cmpa temp2     ;Fill out with spaces to width 11.
+		bne unadisspc
+		bne unadishex
+		jsr disdisp    ;Display disassembled instruction.
+		tst disflg
+		bne skipcr		
+		jsr putcr
+skipcr		cmpy length
+		bls unasmloop
+		sty addr
+		rts
+
+* Simple 'expression evaluator' for assembler.
+expr		ldb ,x
+		cmpb #'-'
+		bne pos
+		clrb
+		leax 1,x
+pos		pshs b
+		bsr scanfact
+		beq exprend1
+		tst ,s+
+		bne exprend 	;Was the minus sign there.
+		coma
+		comb
+		addd #1
+		andcc #$fb	;Clear Z flag for valid result.
+exprend		rts		
+exprend1	puls b
+		rts
+
+scanfact	ldb ,x+
+		cmpb #'$'
+		lbeq scanhex   ;Hex number if starting with dollar.
+		cmpb #'''
+		bne scandec    ;char if starting with ' else decimal
+		ldb ,x+
+		lda ,x
+		cmpa #'''
+		bne scanchar2
+		leax 1,x       ;Increment past final quote if it's there.
+scanchar2	clra
+		andcc #$fb     ;Clear zero flag.
+		rts
+scandec		cmpb #'0'
+		blo noexpr
+		cmpb #'9'
+		bhi noexpr
+		clr temp
+		clr temp+1
+scandloop	subb #'0'
+		bcs sdexit				
+		cmpb #10
+		bcc sdexit
+		pshs b
+		ldd temp
+		aslb
+		rola
+		pshs d
+		aslb
+		rola
+		aslb
+		rola
+		addd ,s++     ;Multiply number by 10.
+		addb ,s+
+		adca #0	      ;Add digit to 10.
+		std temp	
+		ldb ,x+	      ;Get next character.
+		bra scandloop
+sdexit		ldd temp
+		leax -1,x
+		andcc #$fb	
+		rts			
+noexpr		orcc #$04
+		rts	
+
+* Assemble the instruction pointed to by X.
+* Fisrt stage: copy mnemonic to mnemonic buffer.
+asminstr 	lda #5
+		ldu #mnembuf
+mncploop	ldb ,x+		
+		beq mncpexit
+		cmpb #' '
+		beq mncpexit	;Mnemonic ends at first space or null
+		andb #CASEMASK
+		cmpb #'A'
+		blo nolet
+		cmpb #'Z'
+		bls mnemcp1	;Capitalize letters, but only letters.
+nolet		ldb -1,x
+mnemcp1		stb ,u+		;Copy to mnemonic buffer.
+		deca
+		bne mncploop
+mncpexit	tsta
+		beq mncpdone
+		ldb #' '
+mnfilloop	stb ,u+
+		deca
+		bne mnfilloop	;Fill the rest of mnem buffer with spaces.
+* Second stage: look mnemonic up using binary search.
+mncpdone	stx temp3
+		clr temp	;Low index=0
+		lda #mnemsize
+		sta temp+1      ;High index=mnemsize.
+bsrchloop	ldb temp+1
+		cmpb #$ff
+		beq invmnem	;lower limit -1?
+		cmpb temp
+		blo invmnem     ;hi index lower than low index?
+		clra
+		addb temp	;Add indexes.
+		adca #0 	
+		lsra
+		rorb		;Divide by 2 to get average
+		stb temp2
+		aslb
+		rola
+		aslb		
+		rola		
+		aslb
+		rola		;Multiply by 8 to get offset.
+		ldu #mnemtab
+		leau d,u	;Add offset to table base
+		tfr u,y
+		lda #5
+		ldx #mnembuf
+bscmploop	ldb ,x+
+		cmpb ,y+
+		bne bscmpexit	;Characters don't match?
+		deca
+		bne bscmploop
+		jmp mnemfound	;We found the mnemonic.
+bscmpexit	ldb temp2
+		bcc bscmplower
+		decb
+		stb temp+1	;mnembuf<table, adjust high limit.
+		bra bsrchloop
+bscmplower	incb
+		stb temp	;mnembuf>table, adjust low limit.
+		bra bsrchloop
+invmnem		ldx #invmmsg	
+		jmp asmerrvec
+* Stage 3: Perform routine depending on category code.
+mnemfound	clr uncert
+		ldy addr
+		lda 5,u
+		asla
+		ldx #asmtab
+		jsr [a,x]
+		sty addr
+		rts
+asmtab		fdb onebyte,twobyte,immbyte,lea
+		fdb sbranch,lbranch,lbra,acc8
+		fdb dreg1,dreg2,oneaddr,tfrexg
+		fdb pushpul,pseudovec
+
+putbyte		stb ,y+
+		rts
+putword		std ,y++
+		rts
+
+onebyte		ldb 7,u		;Cat 0, one byte opcode w/o operands RTS
+		bra putbyte
+twobyte		ldd 6,u		;Cat 1, two byte opcode w/o operands SWI2
+		bra putword
+immbyte		ldb 7,u		;Cat 2, opcode w/ immdiate operand ANDCC
+		bsr putbyte
+		jsr scanops
+		ldb amode
+		cmpb #1
+		lbne moderr
+		ldb operand+1
+		bra putbyte
+lea		ldb 7,u		;Cat 3, LEA
+		bsr putbyte
+		jsr scanops
+		lda amode
+		cmpa #1
+		lbeq moderr	;No immediate w/ lea
+		cmpa #3
+		lbhs doaddr	
+		jsr set3
+		lda #$8f
+		sta postbyte
+		lda #2
+		sta opsize	;Use 8F nn nn for direct mode.	
+		jmp doaddr
+sbranch		ldb 7,u		;Cat 4, short branch instructions
+		bsr putbyte
+		jsr startop
+		leax -1,x
+		jsr exprvec
+		lbeq exprerr
+		jmp shortrel
+lbranch		ldd 6,u		;Cat 5, long brach w/ two byte opcode
+		bsr putword
+lbra1		jsr startop
+		leax -1,x
+		jsr exprvec
+		lbeq exprerr
+		jmp longrel		
+lbra		ldb 7,u		;Cat 6, long branch w/ one byte opcode.
+		jsr putbyte
+		bra lbra1
+acc8		lda #1		;Cat 7, 8-bit two operand instructions ADDA
+		sta opsize
+		jsr scanops
+		jsr adjopc
+		jsr putbyte
+		jmp doaddr
+dreg1		lda #2		;Cat 8, 16-bit 2operand insns 1byte opc LDX
+		sta opsize
+		jsr scanops
+		jsr adjopc
+		jsr putbyte
+		jmp doaddr
+dreg2		lda #2		;Cat 9, 16-bit 2operand insns 2byte opc LDY
+		sta opsize
+		jsr scanops
+		jsr adjopc
+		lda 6,u
+		jsr putword
+		jmp doaddr
+oneaddr		jsr scanops	;Cat 10, one-operand insns NEG..CLR
+		ldb 7,u
+		lda amode
+		cmpa #1
+		lbeq moderr	;No immediate mode
+		cmpa #3
+		bhs oaind	;indexed etc
+		lda opsize
+		deca
+		beq oadir
+		addb #$10	;Add $70 for extended direct.
+oaind		addb #$60	;And $60 for indexed etc.
+oadir		jsr putbyte	;And nothing for direct8.
+		jmp doaddr
+tfrexg		jsr startop	;Cat 11, TFR and EXG
+		leax -1,x
+		ldb 7,u
+		jsr putbyte
+		jsr findreg
+		ldb ,u
+		aslb 
+		aslb
+		aslb
+		aslb
+		stb postbyte
+		ldb ,x+
+		cmpb #','
+		lbne moderr
+		jsr findreg
+		ldb ,u
+		orb postbyte
+		jmp putbyte		
+pushpul		jsr startop	;Cat 12, PSH and PUL
+		leax -1,x
+		ldb 7,u
+		jsr putbyte
+		clr postbyte
+pploop		jsr findreg
+		ldb 1,u
+		orb postbyte
+		stb postbyte
+		ldb ,x+
+		cmpb #','
+		beq pploop
+		leax -1,x
+		ldb postbyte
+		jmp putbyte		
+pseudo		ldb 7,u		;Cat 13, pseudo oeprations
+		aslb
+		ldx #pseudotab
+		jmp [b,x]
+pseudotab	fdb pseudoend,dofcb,dofcc,dofdb
+		fdb doorg,dormb,pseudoend,pseudoend
+dofcb		jsr startop
+		leax -1,x
+fcbloop		jsr exprvec
+		lbeq exprerr
+		jsr putbyte
+		ldb ,x+
+		cmpb #','
+		beq fcbloop
+pseudoend	rts
+dofcc		jsr startop
+		tfr b,a ;Save delimiter.
+fccloop		ldb ,x+	
+		beq pseudoend
+		pshs a
+		cmpb ,s+
+		beq pseudoend
+		jsr putbyte
+		bra fccloop	
+dofdb		jsr startop
+		leax -1,x
+fdbloop		jsr exprvec
+		lbeq exprerr
+		jsr putword
+		ldb ,x+
+		cmpb #','
+		beq fdbloop
+		rts
+doorg		jsr startop
+		leax -1,x
+		jsr exprvec
+		lbeq exprerr
+		tfr d,y
+		rts
+dormb		jsr startop
+		leax -1,x
+		jsr exprvec
+		lbeq exprerr
+		leay d,y
+		rts
+
+
+* Adjust opcdoe depending on mode (in $80-$FF range)
+adjopc		ldb 7,u
+		lda amode
+		cmpa #2
+		beq adjdir	;Is it direct?
+		cmpa #3
+		bhs adjind	;Indexed etc?
+		rts		;Not, then immediate, no adjust.
+adjind		addb #$20	;Add $20 to opcode for indexed etc modes.
+		rts
+adjdir		addb #$10	;Add $10 to opcode for direct8
+		lda opsize
+		deca
+		bne adjind	;If opsize=2, add another $20 for extended16	
+		rts
+
+* Start scanning of operands.
+startop		ldx temp3
+		clr amode
+		jmp skipspace
+
+* amode settings in assembler: 1=immediate, 2=direct/extended, 3=indexed
+* etc. 4=pc relative, 5=indirect, 6=pcrelative and indirect.
+
+* This subroutine scans the assembler operands.
+scanops		bsr startop
+		cmpb #'['
+		bne noindir
+		lda #5		;operand starts with [, then indirect.
+		sta amode	
+		ldb ,x+
+noindir		cmpb #'#'
+		lbeq doimm
+		cmpb #','
+		lbeq dospecial
+		andb #CASEMASK    ;Convert to uppercase.
+		lda #$86
+		cmpb #'A'
+		beq scanacidx
+		lda #$85
+		cmpb #'B'
+		beq scanacidx
+		lda #$8B
+		cmpb #'D'
+		bne scanlab
+scanacidx	ldb ,x+		;Could it be A,X B,X or D,X
+		cmpb #','
+		bne nocomma
+		sta postbyte
+		clr opsize
+		jsr set3
+		jsr scanixreg
+		bra scanend
+nocomma		leax -1,x		
+scanlab		leax -1,x	;Point to the start of the operand
+		jsr exprvec
+		lbeq exprerr    
+		std operand
+		tst uncert
+		bne opsz2	;Go for extended if operand unknown.
+		subd dpsetting  
+		tsta		;Can we use 8-bit operand?
+		bne opsz2
+		inca		
+		bra opsz1
+opsz2		lda #2
+opsz1		sta opsize	;Set opsize depending on magnitude of op.
+		lda amode
+		cmpa #5
+		bne opsz3	;Or was it indirect.
+		lda #2		;Then we have postbyte and opsize=2
+		sta opsize
+		lda #$8F
+		sta postbyte	
+		bra opsz4
+opsz3		lda #2
+		sta amode	;Assume direct or absolute addressing 
+opsz4		ldb ,x+		
+		cmpb #','
+		lbeq doindex	;If followed by, then indexed.
+scanend		lda amode
+		cmpa #5
+		blo scanend2	;Was it an indirect mode?
+		lda postbyte
+		ora #$10	;Set indirect bit.
+		sta postbyte
+		ldb ,x+		
+		cmpb #']'	;Check for the other ]
+		lbeq moderr
+scanend2	rts
+doimm		jsr exprvec	;Immediate addressing.	
+		lbeq exprerr
+		std operand
+		lda amode
+		cmpa #5
+		lbeq moderr	;Inirect mode w/ imm is illegal.
+		lda #$01
+		sta amode
+		rts
+dospecial	jsr set3
+		clr opsize
+		clra
+adecloop	ldb ,x+
+		cmpb #'-'
+		bne adecend
+		inca		;Count the - signs for autodecrement.
+		bra adecloop
+adecend		leax -1,x
+		cmpa #2				
+		lbhi moderr
+		tsta
+		bne autodec
+		clr postbyte
+		jsr scanixreg
+		clra
+aincloop	ldb ,x+
+		cmpb #'+'
+		bne aincend
+		inca
+		bra aincloop	;Count the + signs for autoincrement.			
+aincend		leax -1,x
+		cmpa #2
+		lbhi moderr
+		tsta
+		bne autoinc
+		lda #$84
+		ora postbyte
+		sta postbyte
+		bra scanend
+autoinc		adda #$7f
+		ora postbyte
+		sta postbyte		
+		bra scanend
+autodec		adda #$81
+		sta postbyte
+		jsr scanixreg
+		lbra scanend
+doindex		clr postbyte
+		jsr set3
+		ldb ,x+
+		andb #CASEMASK	;Convert to uppercase.
+		cmpb #'P'
+		lbeq dopcrel	;Check for PC relative.
+		leax -1,x
+		clr opsize
+		bsr scanixreg
+		ldd operand
+		tst uncert
+		bne longindex	;Go for long index if operand unknown.
+		cmpd #-16
+		blt shortindex
+		cmpd #15
+		bgt shortindex
+		lda amode
+		cmpa #5		
+		beq shortind1	;Indirect may not be 5-bit index	
+				;It's a five-bit index.
+		andb #$1f
+		orb postbyte
+		stb postbyte
+		lbra scanend
+shortindex	cmpd #-128
+		blt longindex
+		cmpd #127
+		bgt longindex
+shortind1	inc opsize
+		ldb #$88
+		orb postbyte
+		stb postbyte
+		lbra scanend
+longindex	lda #$2
+		sta opsize
+		ldb #$89
+		orb postbyte
+		stb postbyte
+		lbra scanend
+dopcrel		ldb ,x+
+		andb #CASEMASK	;Convert to uppercase
+		cmpb #'C'
+		blo pcrelend
+		cmpb #'R'
+		bhi pcrelend
+		bra dopcrel	;Scan past the ,PCR 
+pcrelend	leax -1,x
+		ldb #$8C
+		orb postbyte	;Set postbyte
+		stb postbyte	
+		inc amode	;Set addr mode to PCR
+		lbra scanend
+
+* Scan for one of the 4 index registers and adjust postbyte. 
+scanixreg	ldb ,x+
+		andb #CASEMASK	;Convert to uppercase.
+		pshs x
+		ldx #ixregs
+		clra
+scidxloop	cmpb ,x+
+		beq ixfound
+		adda #$20
+		bpl scidxloop
+		jmp moderr	;Index register not found where expected.
+ixfound		ora postbyte
+		sta postbyte	;Set index reg bits in postbyte.
+		puls x
+		rts		
+				
+* This routine sets amode to 3, if it was less.
+set3		lda amode
+		cmpa #3
+		bhs set3a
+		lda #3
+		sta amode
+set3a		rts
+
+* This subroutine lays down the address.
+doaddr		lda amode
+		cmpa #3
+		blo doa1
+		ldb postbyte
+		jsr putbyte
+		lda amode 
+		anda #1
+		beq doapcrel	;pc rel modes.
+doa1		lda opsize
+		tsta
+		beq set3a
+		deca
+		beq doa2
+		ldd operand
+		jmp putword
+doa2		ldb operand+1
+		jmp putbyte		
+doapcrel	sty addr
+		ldd operand
+		subd addr
+		subd #1
+		tst uncert
+		bne pcrlong
+		cmpd #-128
+		blt pcrlong
+		cmpd #-127
+		bgt pcrlong
+		lda #1
+		sta opsize
+		jmp putbyte
+pcrlong		subd #1
+		leay -1,y
+		inc postbyte
+		pshs d
+		ldb postbyte
+		jsr putbyte
+		lda #2
+		sta opsize
+		puls d
+		jmp putword
+
+* This routine checks and lays down short relative address.
+shortrel	sty addr
+		subd addr
+		subd #1
+		cmpd #-128
+		blt brerr
+		cmpd #127
+		bgt brerr
+		jsr putbyte
+		lda #4
+		sta amode
+		lda #1
+		sta opsize
+		rts
+* This routine lays down long relative address.
+longrel		sty addr
+		subd addr
+		subd #2
+		jsr putword
+		lda #4
+		sta amode
+		lda #2
+		sta opsize
+		rts
+
+brerr		ldx #brmsg
+		jmp asmerrvec 
+exprerr		ldx #exprmsg
+		jmp asmerrvec
+moderr		ldx #modemsg
+		jmp asmerrvec
+asmerr		pshs x
+		jsr xabortin
+		puls x
+		jsr outcount
+		jsr putcr
+		lds savesp
+		jmp cmdline
+
+* Find register for TFR and PSH instruction
+findreg		ldb #12
+		pshs y,b
+		ldu #asmregtab
+findregloop	tfr x,y
+		lda #3
+frcmps		ldb ,u
+		cmpb #' '
+		bne frcmps1
+		ldb ,y
+		cmpb #'A'
+		blt frfound
+frcmps1		ldb ,y+
+		andb #CASEMASK
+		cmpb ,u+
+		bne frnextreg
+		deca
+		bne frcmps
+		inca
+		bra frfound
+frnextreg	inca
+		leau a,u
+		dec ,s
+		bne findregloop
+		lbra moderr
+frfound		leau a,u
+		tfr y,x
+		puls y,b
+		rts
+
+* This is the code for the A command, assemble instructions.
+* Syntax: Aaddr
+asm             ldx #linebuf+1
+		jsr scanhex
+		std addr
+		inc disflg	
+
+
+asmloop		ldy #0
+		sty length
+		ldd addr
+		pshs d
+		jsr dis1        ;display unassembled line
+		ldd addr
+		std nxtadd
+
+		puls d
+		std addr
+
+*		ldd addr
+*		jsr outd
+
+		ldb #TAB
+		jsr putchar     ;Print TAB
+		ldx #linebuf
+		ldb #128
+		jsr getline     ;Get new line
+		tstb    
+		beq next
+
+***		beq asmend      ;Exit on empty line.
+		abx 
+		clr ,x          ;Make line zero terminated.
+		ldx #linebuf
+		lda ,x
+		cmpa #'.'
+		beq asmend
+		jsr asminstr
+		bra asmloop
+
+next		ldd nxtadd
+		std addr
+		bra asmloop
+
+asmend		clr disflg
+		jmp cmdline			
+
+
+* Jump table for monitor routines that are usable by other programs.
+		org $ffc0
+		jmp outbyte
+		jmp outd
+		jmp scanbyte
+		jmp scanhex
+		jmp scanfact
+		jmp asminstr
+		
+								
+* Interrupt vector addresses at top of ROM. Most are vectored through jumps
+* in RAM.
+		org $fff2
+		fdb swi3vec
+		fdb swi2vec
+		fdb firqvec
+		fdb irqvec
+		fdb swivec
+		fdb nmivec
+		fdb reset
+
+		end