;*			buffalo
;* "bit user's fast friendly aid to logical operation"
;*
;* rev 2.0 - 4/23/85	- added disassembler.
;*			- variables now ptrn and tmpn.
;* rev 2.1 - 4/29/85	- added byte erase to chgbyt routine.
;* rev 2.2 - 5/16/85	- added hooks for evb board - acia
;*			  drivers, init and host routines.
;*	     7/8/85 	- fixed dump wraparound problem.
;*	     7/10/85	- added evm board commands.
;*			- added fill instruction.
;*	     7/18/85	- added jump to eeprom.
;* rev 2.3 - 8/22/85 	- call targco to disconnect sci from host
;*			  in reset routine for evb board.
;*	     10/3/85	- modified load for download through terminal.
;* rev 2.4 - 7/1/86	- changed dflop address to fix conflicts with
;*			  eeprom.  (was at a000)
;* rev 2.5 - 9/8/86	- modified to provide additional protection from
;*			  program run-away on power down.  also fixed bugs
;*			  in mm and move.  changed to 1 stop bit from 2.
;*
;********************************************************
;*	although the information contained herein,	*
;*	as well as any information provided relative	*
;*	thereto, has been carefully reviewed and is	*
;*	believed accurate, motorola assumes no		*
;*	liability arising out of its application or	*
;*	use, neither does it convey any license under	*
;*	its patent rights nor the rights of others.	*
;********************************************************

	.area	BUF25	(ABS,OVR)

	.setdp

;************************
;*	equates		*
;************************

rambs	=	0x0000		; start of ram
regbs	=	0x1000		; start of registers
rombs	=	0xe000		; start of rom
porte	=	regbs+0x0a	; port e
tcnt	=	regbs+0x0e	; timer count
toc5	=	regbs+0x1e	; oc5 reg
tctl1	=	regbs+0x20	; timer control 1
tmsk1	=	regbs+0x22	; timer mask 1
tflg1	=	regbs+0x23	; timer flag 1
tmsk2	=	regbs+0x24	; timer mask 2
baud	=	regbs+0x2b	; sci baud reg
sccr1	=	regbs+0x2c	; sci control1 reg
sccr2	=	regbs+0x2d	; sci control2 reg
scsr	=	regbs+0x2e	; sci status reg
scdat	=	regbs+0x2f	; sci data reg
option	=	regbs+0x39	; option reg
coprst	=	regbs+0x3a	; cop reset reg
pprog	=	regbs+0x3b	; ee prog reg
hprio	=	regbs+0x3c	; hprio reg
config	=	regbs+0x3f	; config register
dflop	=	0x4000		; evb d flip flop
duart	=	0xd000		; duart address
porta	=	duart
portb	=	duart+8
acia	=	0x9800		; acia address
prompt	=	'>
bufflng	=	35
ctla	=	0x01		; exit host or assembler
ctlb	=	0x02		; send break to host
ctlw	=	0x17		; wait
ctlx	=	0x18		; abort
del	=	0x7f		; abort
eot	=	0x04		; end of text/table
swi	=	0x3f

;***************
;* 	ram 	*
;***************

	.org	0x36

;*** buffalo ram space ***

	.blkb	20	; user stack area
ustack:	.blkb	30	; monitor stack area
stack:	.blkb	1
inbuff:	.blkb	bufflng	; input buffer
endbuff	= .
combuff:
	.blkb	8	; command buffer
shftreg:
	.blkb	2	; input shift register
brktabl:
	.blkb	8	; breakpoint table
regs:	.blkb	9	; user's pc,y,x,a,b,c
sp:	.blkb	2	; user's sp
autolf:	.blkb	1	; auto lf flag for i/o
iodev:	.blkb	1	; 0=sci,  1=acia, 2=duarta, 3=duartb
extdev:	.blkb	1	; 0=none, 1=acia, 2=duart,
hostdev:
	.blkb	1	; 0=sci,  1=acia,	    3=duartb
count:	.blkb	1	; # characters read
ptrmem:	.blkb	2	; current memory location

;*** buffalo variables - used by: ***
ptr0:	.blkb	2	; main,readbuff,incbuff,as
ptr1:	.blkb	2	; main,br,du,mo,as
ptr2:	.blkb	2	; du,go,mo,as
ptr3:	.blkb	2	; ho,mo,as
ptr4:	.blkb	2	; go,as
ptr5:	.blkb	2	; as
ptr6:	.blkb	2	; go,as
ptr7:	.blkb	2	; go,as
tmp1:	.blkb	1	; main,hexbin,buffarg,termarg
tmp2:	.blkb	1	; go,ho,as
tmp3:	.blkb	1	; as
tmp4:	.blkb	1	; go,ho,me,as

;*** vector jump table ***
jsci:	.blkb	3
jspi:	.blkb	3
jpaie:	.blkb	3
jpao:	.blkb	3
jtof:	.blkb	3
jtoc5:	.blkb	3
jtoc4:	.blkb	3
jtoc3:	.blkb	3
jtoc2:	.blkb	3
jtoc1:	.blkb	3
jtic3:	.blkb	3
jtic2:	.blkb	3
jtic1:	.blkb	3
jrti:	.blkb	3
jirq:	.blkb	3
jxirq:	.blkb	3
jswi:	.blkb	3
jillop:	.blkb	3
jcop:	.blkb	3
jclm:	.blkb	3

;*****************
;*
;* rom starts here *
;*
;*****************

	.org	rombs

;*****************
;**	buffalo - this is where buffalo starts
;** out of reset.  all initialization is done
;** here including determination of where the
;** user terminal is (sci,acia, or duart).
;*****************

buffalo:
	ldx	#porte
	brclr 0,x,#0x01,bufisit	; if bit 0 of port e is 1
	jmp	0xb600		; then jump to the start of eeprom
bufisit:
	ldaa	#0x93
	staa	option		; adpu, dly, irqe, cop
	ldaa	#0x00
	staa	tmsk2		; timer pre = %1 for trace
	lds	#stack		; monitor stack pointer
	jsr	vecinit
	ldx	#ustack
	stx	*sp		; default user stack
	ldaa	#0xd0
	staa	*regs+8		; default user ccr
	ldd	#0x3f0d		; initial command is ?
	std	*inbuff
	jsr	bpclr		; clear breakpoints
	clr	*autolf
	inc	*autolf		; auto cr/lf = on

;* determine type of external comm device - none, or acia *

	clr	*extdev		; default is none
	ldaa	hprio
	anda	#0x20
	beq	buff2		; jump if single chip mode
	ldaa	#0x03		; see if external acia exists
	staa	acia		; master reset
	ldaa	acia
	anda	#0x7f		; mask irq bit from status register
	bne	buff1		; jump if status reg not 0
	ldaa	#0x12
	staa	acia		; turn on acia
	ldaa	acia
	anda	#0x02
	beq	buff1		; jump if tdre not set
	ldaa	#0x01
	staa	*extdev		; external device is acia
	bra	buff2

buff1	= .			; see if duart exists
	ldaa	duart+0x0c	; read irq vector register
	cmpa	#0x0f		; should be out of reset
	bne	buff2
	ldaa	#0xaa
	staa	duart+0x0c	; write irq vector register
	ldaa	duart+0x0c	; read irq vector register
	cmpa	#0xaa
	bne	buff2
	ldaa	#0x02
	staa	*extdev		; external device is duart a

;* find terminal port - sci or external. *

buff2:	clr	*iodev
	jsr	targco		; disconnect sci for evb board
	jsr	signon		; initialize sci
	ldaa	*extdev
	beq	buff3		; jump if no external device
	staa	*iodev
	jsr	signon		; initialize external device
buff3:	clr	*iodev
	jsr	input		; get input from sci port
	cmpa	#0x0d
	beq	buff4		; jump if cr - sci is terminal port
	ldaa	*extdev
	beq	buff3		; jump if no external device
	staa	*iodev
	jsr	input		; get input from external device
	cmpa	#0x0d
	beq	buff4		; jump if cr - terminal found ext
	bra	buff3

signon:	jsr	init		; initialize device
	ldx	#msg1		; buffalo message
	jsr	outstrg
	rts

;* determine where host port should be.

buff4:	clr	*hostdev		; default - host = sci port
	ldaa	*iodev
	cmpa	#0x01
	beq	buff5		; default host if term = acia
	ldaa	#0x03
	staa	*hostdev		; else host is duart port b
buff5	= .

;*****************
;**	main - this module reads the user's input into
;** a buffer called inbuff.  the first field (assumed
;** to be the command field) is then parsed into a
;** second buffer called combuff.  the command table
;** is then searched for the contents of combuff and
;** if found, the address of the corresponding task
;** routine is fetched from the command table.  the
;** task is then called as a subroutine so that
;** control returns back to here upon completion of
;** the task.  buffalo expects the following format
;** for commands:
;**	<cmd>[<wsp><arg><wsp><arg>...]<cr>
;** [] implies contents optional.
;** <wsp> means whitespace character (space,comma,tab).
;** <cmd> = command string of 1-8 characters.
;** <arg> = argument particular to the command.
;** <cr> = carriage return signifying end of input string.
;*****************
;* prompt user
;*do
;*	a=input();
;*	if(a==(cntlx or del)) continue;
;*	elseif(a==backspace)
;*	b--;
;*	if(b<0) b=0;
;*	else
;*	if(a==cr && buffer empty)
;*		repeat last command;
;*	else put a into buffer;
;*		check if buffer full;
;*while(a != (cr or /)

main:	lds	#stack		; initialize sp every time
	clr	*autolf
	inc	*autolf		; auto cr/lf = on
	jsr	outcrlf
	ldaa	#prompt		; prompt user
	jsr	output
	clrb
main1:	jsr	inchar		; read terminal
	ldx	#inbuff
	abx			; pointer into buffer
	cmpa	#ctlx
	beq	main		; jump if cntl x
	cmpa	#del
	beq	main		; jump if del
	cmpa	#0x08
	bne	main2		; jump if not bckspc
	decb
	blt	main		; jump if buffer empty
	bra	main1
main2:	cmpa	#0xd
	bne	main3		; jump if not cr
	tstb
	beq	comm0		; jump if buffer empty
	staa	,x		; put a in buffer
	bra	comm0
main3:	staa	,x		; put a in buffer
	incb
	cmpb	#bufflng
	ble	main4		; jump if not long
	ldx	#msg3		; "long"
	jsr	outstrg
	bra	main
main4:	cmpa	#'/
	bne	main1		; jump if not "/"
;*	*******************

;*****************
;*	parse out and evaluate the command field.
;*****************
;*initialize

comm0	= .
	clr	*tmp1		; enable "/" command
	clr	*shftreg
	clr	*shftreg+1
	clrb
	ldx	#inbuff		; ptrbuff[] = inbuff[]
	stx	*ptr0
	jsr	wskip		; find first char

;*while((a=readbuff) != (cr or wspace))
;*	upcase(a);
;*	buffptr[b] = a
;*	b++
;*	if (b > 8) error(too long);
;*	if(a == "/")
;*		if(enabled) mslash();
;*		else error(command?);
;*	else hexbin(a);

comm1	= .
	jsr	readbuff	; read from buffer
	ldx	#combuff
	abx
	jsr	upcase		; convert to upper case
	staa	,x		; put in command buffer
	cmpa	#0x0d
	beq	srch		; jump if cr
	jsr	wchek
	beq	srch		; jump if wspac
	jsr	incbuff		; move buffer pointer
	incb
	cmpb	#0x8
	ble	comm2
	ldx	#msg3		; "long"
	jsr	outstrg
	jmp	main

comm2	= .
	cmpa	#'/
	bne	comm4		; jump if not "/"
	tst	*tmp1
	bne	comm3		; jump if not enabled
	stab	*count
	ldx	#mslash
	jmp	exec		; execute "/"
comm3:	ldx	#msg8		; "command?"
	jsr	outstrg
	jmp	main
comm4	= .
	jsr	hexbin
	bra	comm1

;*****************
;*	search tables for command.	at this point,
;* combuff holds the command field to be executed,
;* and b =	# of characters in the command field.
;* the command table holds the whole command name
;* but only the first n characters of the command
;* must match what is in combuff where n is the
;* number of characters entered by the user.
;*****************
;*count = b;
;*ptr1 = comtabl;
;*while(ptr1[0] != end of table)
;*	ptr1 = next entry
;*	for(b=1; b=count; b++)
;*	if(ptr1[b] == combuff[b]) continue;
;*	else error(not found);
;*	execute task;
;*	return();
;*return(command not found);

srch:	stab	*count		; size of command entered
	ldx	#comtabl	; pointer to table
	stx	*ptr1		; pointer to next entry
srch1:	ldx	*ptr1
	ldy	#combuff	; pointer to command buffer
	ldab	0,x
	cmpb	#0xff
	bne	srch2
	ldx	#msg2		; "command not found"
	jsr	outstrg
	jmp	main
srch2:	pshx			; compute next table entry
	addb	#0x3
	abx
	stx	*ptr1
	pulx
	clrb
srchlp:	incb			; match characters loop
	ldaa	1,x		; read table
	cmpa	0,y		; compare to combuff
	bne	srch1		; try next entry
	inx			; move pointers
	iny
	cmpb	*count
	blt	srchlp		; loop countu1 times
	ldx	*ptr1
	dex
	dex
	ldx	0,x		; jump address from table
exec:	jsr	0,x		; call task as subroutine
	jmp	main
;*
;*****************
;*	utility subroutines - these routines
;* are called by any of the task routines.
;*****************
;*****************
;*	upcase(a) - if the contents of a is alpha,
;* returns a converted to uppercase.
;*****************
upcase:	cmpa	#'a
	blt	upcase1		; jump if < a
	cmpa	#'z
	bgt	upcase1		; jump if > z
	suba	#0x20		; convert
upcase1:
	rts

;*****************
;*	bpclr() - clear all entries in the
;* table of breakpoints.
;*****************
bpclr:	ldx	#brktabl
	ldab	#8
bpclr1:	clr	0,x
	inx
	decb
	bgt	bpclr1		; loop 8 times
	rts

;*****************
;*	rprnt1(x) - prints name and contents of a single
;* user register. on entry x points to name of register
;* in reglist.  on exit, a=register name.
;*****************
reglist:
	.ascii	'PYXABCS'	; names
	.byte	0,2,4,6,7,8,9	; offset
	.byte	1,1,1,0,0,0,1	; size

rprnt1:	ldaa	0,x
	psha
	pshx
	jsr	output		; name
	ldaa	#'-
	jsr	output		; dash
	ldab	7,x		; contents offset
	ldaa	14,x		; bytesize
	ldx	#regs		; address
	abx
	tsta
	beq	rprn2		; jump if 1 byte
	jsr	out1byt		; 2 bytes
rprn2:	jsr	out1bsp
	pulx
	pula
	rts

;*****************
;*	rprint() - print the name and contents
;* of all the user registers.
;*****************
rprint:	pshx
	ldx	#reglist
rpri1:	jsr	rprnt1		; print name
	inx
	cmpa	#'S		; s is last register
	bne	rpri1		; jump if not done
	pulx
	rts

;*****************
;*	hexbin(a) - convert the ascii character in a
;* to binary and shift into shftreg.  returns value
;* in tmp1 incremented if a is not hex.
;*****************
hexbin:	psha
	pshb
	pshx
	jsr	upcase		; convert to upper case
	cmpa	#'0
	blt	hexnot		; jump if a < 0x30
	cmpa	#'9
	ble	hexnmb		; jump if 0-9
	cmpa	#'A
	blt	hexnot		; jump if 0x39> a <0x41
	cmpa	#'F
	bgt	hexnot		; jump if a > 0x46
	adda	#0x9		; convert 0xa-0xf
hexnmb:	anda	#0x0f		; convert to binary
	ldx	#shftreg
	ldab	#4
hexshft:
	asl	1,x		; 2 byte shift through
	rol	0,x		; carry bit
	decb
	bgt	hexshft		; shift 4 times
	oraa	1,x
	staa	1,x
	bra	hexrts
hexnot:	inc	*tmp1		; indicate not hex
hexrts:	pulx
	pulb
	pula
	rts

;*****************
;*	buffarg() - build a hex argument from the
;* contents of the input buffer. characters are
;* converted to binary and shifted into shftreg
;* until a non-hex character is found.  on exit
;* shftreg holds the last four digits read, count
;* holds the number of digits read, ptrbuff points
;* to the first non-hex character read, and a holds
;* that first non-hex character.
;*****************
;*initialize
;*while((a=readbuff()) not hex)
;*	hexbin(a);
;*return();

buffarg:
	clr	*tmp1		; not hex indicator
	clr	*count		; # or digits
	clr	*shftreg
	clr	*shftreg+1
	jsr	wskip
bufflp:	jsr	readbuff	; read char
	jsr	hexbin
	tst	*tmp1
	bne	buffrts		; jump if not hex
	inc	*count
	jsr	incbuff		; move buffer pointer
	bra	bufflp
buffrts:
	rts

;*****************
;*	termarg() - build a hex argument from the
;* terminal.  characters are converted to binary
;* and shifted into shftreg until a non-hex character
;* is found.  on exit shftreg holds the last four
;* digits read, count holds the number of digits
;* read, and a holds the first non-hex character.
;*****************
;*initialize
;*while((a=inchar()) == hex)
;*	if(a = cntlx or del)
;*		abort;
;*	else
;*		hexbin(a); countu1++;
;*return();

termarg:
	clr	*count
	clr	*shftreg
	clr	*shftreg+1
term0:	jsr	inchar
	cmpa	#ctlx
	beq	term1		; jump if controlx
	cmpa	#del
	bne	term2		; jump if not delete
term1:	jmp	main		; abort
term2:	clr	*tmp1		; hex indicator
	jsr	hexbin
	tst	*tmp1
	bne	term3		; jump if not hex
	inc	*count
	bra	term0
term3:	rts

;*****************
;*	chgbyt() - if shftreg is not empty, put
;* contents of shftreg at address in x.	if x
;* is an address in eeprom then program it.
;*****************
;*if(count != 0)
;*	(x) = a;
;*	if(((x) != a) && (x == eeprom location))
;*	if((x) != 0xff) byte erase (x);
;*	if(a != 0xff) program(x) = a);
;*	if((x) != a) error(rom)
;*return;

chgbyt:	tst	*count
	beq	chgbyt4		; jump if shftreg empty
	ldaa	*shftreg+1
	staa	0,x		; attempt to write
	ldaa	0,x
	cmpa	*shftreg+1
	beq	chgbyt3		; jump if it worked
	cpx	#config
	beq	chgbyt1		; jump if config reg
	cpx	#0xb600
	blo	chgbyt3		; jump if not ee
	cpx	#0xb7ff
	bhi	chgbyt3		; jump if not ee
chgbyt1	= .
	ldaa	0,x
	cmpa	#0xff
	beq	chgbyt2		; jump if already erased
	ldaa	#0x16		; do byte erase
	staa	pprog
	ldaa	#0xff
	staa	0,x
	ldaa	#0x17
	bne	acl1
	clra			; fail safe
acl1:	staa	pprog
	bsr	chgwait
	ldaa	#0x00
	staa	pprog		; end of byte erase
chgbyt2	= .
	ldaa	*shftreg+1
	cmpa	#0xff
	beq	chgbyt3		; jump if no need to program
	ldaa	#0x02		; do byte program
	staa	pprog
	ldaa	*shftreg+1
	staa	0,x
	ldaa	#0x03
	bne	acl2
	clra			; fail safe
acl2:	staa	pprog
	bsr	chgwait
	ldaa	#0x00
	staa	pprog		; end of byte program
chgbyt3	= .
	ldaa	,x
	cmpa	*shftreg+1
	beq	chgbyt4
	pshx
	ldx	#msg6		; "rom"
	jsr	outstrg
	jsr	outcrlf
	pulx
chgbyt4	= .
	rts

chgwait	= . 		; delay 10 ms at E = 2mhz
	pshx
	ldx	#0x0d06
chgwait1:
	dex
	bne	chgwait1
	pulx
	rts

;*****************
;*	readbuff() -  read the character in inbuff
;* pointed at by ptrbuff into a.  returns ptrbuff
;* unchanged.
;*****************
readbuff:
	pshx
	ldx	*ptr0
	ldaa	0,x
	pulx
	rts

;*****************
;*	incbuff(), decbuff() - increment or decrement
;* ptrbuff.
;*****************
incbuff:
	pshx
	ldx	*ptr0
	inx
	bra	incdec
decbuff:
	pshx
	ldx	*ptr0
	dex
incdec:	stx	*ptr0
	pulx
	rts

;*****************
;*	wskip() - read from the inbuff until a
;* non whitespace (space, comma, tab) character
;* is found.  returns ptrbuff pointing to the
;* first non-whitespace character and a holds
;* that character.
;*****************
wskip:	jsr	readbuff	; read character
	jsr	wchek
	bne	wskip1		; jump if not wspc
	jsr	incbuff		; move pointer
	bra	wskip		; loop
wskip1:	rts

;*****************
;*	wchek(a) - returns z=1 if a holds a
;* whitespace character, else z=0.
;*****************
wchek:	cmpa	#0x2c		; comma
	beq	wchek1
	cmpa	#0x20		; space
	beq	wchek1
	cmpa	#0x09		; tab
wchek1:	rts

;*****************
;*	dchek(a) - returns z=1 if a = whitespace
;* or carriage return.	else returns z=0.
;*****************
dchek:	jsr	wchek
	beq	dchek1		; jump if whitespace
	cmpa	#0x0d
dchek1:	rts

;*****************
;*	chkabrt() - checks for a control x or delete
;* from the terminal.  if found, the stack is
;* reset and the control is transferred to main.
;* note that this is an abnormal termination.
;*	if the input from the terminal is a control w
;* then this routine keeps waiting until any other
;* character is read.
;*****************
;*a=input();
;*if(a=cntl w) wait until any other key;
;*if(a = cntl x or del) abort;

chkabrt:
	jsr	input
	beq	chk4		; jump if no input
	cmpa	#ctlw
	bne	chk2		; jump in not cntlw
chkabrt1:
	jsr	input
	beq	chkabrt1	; jump if no input
chk2:	cmpa	#del
	beq	chk3		; jump if delete
	cmpa	#ctlx
	beq	chk3		; jump if control x
	cmpa	#ctla
	bne	chk4		; jump not control a
chk3:	jmp	main		; abort
chk4:	rts			; return

;***********************
;*	hostco - connect sci to host for evb board.
;*	targco - connect sci to target for evb board.
;***********************
hostco:	psha
	ldaa	#0x01
	staa	dflop		; send 1 to d-flop
	pula
	rts

targco:	psha
	ldaa	#0x00
	staa	dflop		; send 0 to d-flop
	pula
	rts

;*
;**********
;*
;*	vecinit - this routine checks for
;*	vectors in the ram table.	all
;*	uninitialized vectors are programmed
;*	to jmp stopit
;*
;**********
;*
vecinit:
	ldx	#jsci		; point to first ram vector
	ldy	#stopit		; pointer to stopit routine
	ldd	#0x7e03		; a=jmp opcode; b=offset
vecloop:
	cmpa	0,x
	beq	vecnext		; if vector already in
	staa	0,x		; install jmp
	sty	1,x		; to stopit routine
vecnext:
	abx			; add 3 to point at next vector
	cpx	#jclm+3		; done?
	bne	vecloop		; if not, continue loop
	rts
;*
stopit:	ldaa	#0x50		; stop-enable; irq, xirq-off
	tap
	stop			; you are lost!	shut down
	jmp	stopit		; in case continue by xirq

;**********
;*
;*	i/o module
;*	communications with the outside world.
;* 3 i/o routines (init, input, and output) call
;* drivers specified by iodev (0=sci, 1=acia,
;* 2=duarta, 3=duartb).
;*
;**********
;*	init() - initialize device specified by iodev.
;*********
;*
init	= .
	psha			; save registers
	pshx
	ldaa	*iodev
	cmpa	#0x00
	bne	init1		; jump not sci
	jsr	onsci		; initialize sci
	bra	init4
init1:	cmpa	#0x01
	bne	init2		; jump not acia
	jsr	onacia		; initialize acia
	bra	init4
init2:	ldx	#porta
	cmpa	#0x02
	beq	init3		; jump duart a
	ldx	#portb
init3:	jsr	onuart		; initialize duart
init4:	pulx			; restore registers
	pula
	rts

;**********
;*	input() - read device. returns a=char or 0.
;*	this routine also disarms the cop.
;**********
input	= .
	pshx
	ldaa	#0x55		; reset cop
	staa	coprst
	ldaa	#0xaa
	staa	coprst
	ldaa	*iodev
	bne	input1		; jump not sci
	jsr	insci		; read sci
	bra	input4
input1:	cmpa	#0x01
	bne	input2		; jump not acia
	jsr	inacia		; read acia
	bra	input4
input2:	ldx	#porta
	cmpa	#0x02
	beq	input3		; jump if duart a
	ldx	#portb
input3:	jsr	inuart		; read uart
input4:	pulx
	rts

;**********
;*	output() - output character in a.
;**********

output	= .
	psha			; save registers
	pshb
	pshx
	ldab	*iodev
	bne	output1		; jump not sci
	jsr	outsci		; write sci
	bra	output4
output1:
	cmpb	#0x01
	bne	output4		; jump not acia
	jsr	outacia		; write acia
	bra	output4
output2:
	ldx	#porta
	cmpb	#0x02
	beq	output3		; jump if duart a
	ldx	#portb
output3:
	jsr	outuart		; write uart
output4:
	pulx
	pulb
	pula
	rts

;**********
;*	onuart(port) - initialize a duart port.
;* sets duart to internal clock, divide by 16,
;* 8 data + 1 stop bits.
;**********

onuart:	ldaa	#0x22
	staa	2,x		; reset receiver
	ldaa	#0x38
	staa	2,x		; reset transmitter
	ldaa	#0x40
	staa	2,x		; reset error status
	ldaa	#0x10
	staa	2,x		; reset pointer
	ldaa	#0x00
	staa	duart+4		; clock source
	ldaa	#0x00
	staa	duart+5		; interrupt mask
	ldaa	#0x13
	staa	0,x		; 8 data, no parity
	ldaa	#0x07
	staa	0,x		; 1 stop bits
	ldaa	#0xbb		; baud rate (9600)
	staa	1,x		; tx and rcv baud rate
	ldaa	#0x05
	staa	2,x		; enable tx and rcv
	rts

;**********
;*	inuart(port) - check duart for any input.
;**********

inuart:	ldaa	1,x		; read status
	anda	#0x01		; check rdrf
	beq	inuart1		; jump if no data
	ldaa	3,x		; read data
	anda	#0x7f		; to mask parity
inuart1:
	rts

;**********
;*	outuart(port) - output the character in a.
;*	if autolf=1, transmits cr or lf as crlf.
;**********
outuart:
	tst	*autolf
	beq	outuart2	; jump if no autolf
	bsr	outuart2
	cmpa	#0x0d
	bne	outuart1
	ldaa	#0x0a		; if cr, output lf
	bra	outuart2
outuart1:
	cmpa	#0x0a
	bne	outuart3
	ldaa	#0x0d		; if lf, output cr
outuart2:
	 ldab	1,x		; check status
	andb	#0x4
	beq	outuart2	; loop until tdre=1
	anda	#0x7f		; mask parity
	staa	3,x		; send character
outuart3:
	rts

;**********
;*	onsci() - initialize the sci for 9600
;*			baud at 8 mhz extal.
;**********
onsci:	ldaa	#0x30
	staa	baud		; baud register
	ldaa	#0x00
	staa	sccr1
	ldaa	#0x0c
	staa	sccr2		; enable
	rts

;**********
;*	insci() - read from sci.	return a=char or 0.
;**********
insci:	ldaa	scsr		; read status reg
	anda	#0x20
	beq	insci1		; jump if rdrf=0
	ldaa	scdat		; read data register
	anda	#0x7f		; mask parity
insci1:	rts

;**********
;*	outsci() - output a to sci. if autolf = 1,
;*		cr and lf sent as crlf.
;**********
outsci:	tst	*autolf
	beq	outsci2		; jump if autolf=0
	bsr	outsci2
	cmpa	#0x0d
	bne	outsci1
	ldaa	#0x0a		; if cr, send lf
	bra	outsci2
outsci1:
	cmpa	#0x0a
	bne	outsci3
	ldaa	#0x0d		; if lf, send cr
outsci2:
	ldab	scsr		; read status
	bitb	#0x80
	beq	outsci2		; loop until tdre=1
	anda	#0x7f		; mask parity
	staa	scdat		; send character
outsci3:
	rts

;**********
;*	onacia - initialize the acia for
;* 8 data bits, 1 stop bit, divide by 64 clock.
;**********
onacia:	ldx	#acia
	ldaa	#0x03
	staa	0,x		; master reset
	ldaa	#0x16
	staa	0,x		; setup
	rts

;**********
;*	inacia - read from the acia, return a=char or 0.
;**********
inacia:	ldx	#acia
	ldaa	0,x		; status
	psha
	anda	#0x70		; check pe, ov, fe
	pula
	beq	inacia1		; jump - no error
	bsr	onacia		; reinitialize and try again
	bra	inacia
inacia1:
	lsra			; check rdrf
	bcs	inacia2		; jump if data
	clra			; return(no data)
	rts
inacia2:
	ldaa	1,x		; read data
	anda	#0x7f		; mask parity
	rts

;**********
;*	outacia - output a to acia. if autolf = 1,
;*		cr or lf sent as crlf.
;**********
outacia:
	bsr	outacia3	; output char
	tst	*autolf
	beq	outacia2	; jump no autolf
	cmpa	#0x0d
	bne	outacia1
	ldaa	#0x0a
	bsr	outacia3	; if cr, output lf
	bra	outacia2
outacia1:
	cmpa	#0x0a
	bne	outacia2
	ldaa	#0x0d
	bsr	outacia3	; if lf, output cr
outacia2:
	rts

outacia3:
	ldx	#acia
	ldab	0,x
	bitb	#0x2
	beq	outacia3	; loop until tdre
	anda	#0x7f		; mask parity
	staa	1,x		; output
	rts
;*
;*	space for modifying outacia routine
;*
	.word	0xffff,0xffff,0xffff,0xffff
;*******************************
;*** i/o utility subroutines ***
;***these subroutines perform the neccesary
;* data i/o operations.
;* outlhlf-convert left 4 bits of a from binary
;*		to ascii and output.
;* outrhlf-convert right 4 bits of a from binary
;*		to ascii and output.
;* out1byt-convert byte addresed by x from binary
;*		to ascii and output.
;* out1bsp-convert byte addressed by x from binary
;*		to ascii and output followed by a space.
;* out2bsp-convert 2 bytes addressed by x from binary
;*		to ascii and  output followed by a space.
;* outspac-output a space.
;*
;* outcrlf-output a line feed and carriage return.
;*
;* outstrg-output the string of ascii bytes addressed
;*		by x until 0x04.
;* outa-output the ascii character in a.
;*
;* inchar-input to a and echo one character.  loops
;*		until character read.
;********************

;**********
;*	outrhlf(), outlhlf(), outa()
;*convert a from binary to ascii and output.
;*contents of a are destroyed..
;**********
outlhlf:
	lsra			; shift data to right
	lsra
	lsra
	lsra
outrhlf:
	anda	#0x0f		; mask top half
	adda	#0x30		; convert to ascii
	cmpa	#0x39
	ble	outa		; jump if 0-9
	adda	#0x07		; convert to hex a-f
outa:	jsr	output		; output character
	rts

;**********
;*	out1byt(x) - convert the byte at x to two
;* ascii characters and output. return x pointing
;* to next byte.
;**********
out1byt:
	psha
	ldaa	0,x		; get data in a
	psha			; save copy
	bsr	outlhlf		; output left half
	pula			; retrieve copy
	bsr	outrhlf		; output right half
	pula
	inx
	rts

;**********
;*	out1bsp(x), out2bsp(x) - output 1 or 2 bytes
;* at x followed by a space.  returns x pointing to
;* next byte.
;**********
out2bsp:
	jsr	out1byt		; do first byte
out1bsp:
	jsr	out1byt		; do next byte
outspac:
	ldaa	#0x20		; output a space
	jsr	output
	rts

;**********
;*	outcrlf() - output a carriage return and
;* a line feed.	returns a = cr.
;**********
outcrlf:
	ldaa	#0x0d		; cr
	jsr	output		; output a
	ldaa	#0x00
	jsr	output		; output padding
	ldaa	#0x0d
	rts

;**********
;*	outstrg(x) - output string of ascii bytes
;* starting at x until end of text (0x04).	can
;* be paused by control w (any char restarts).
;**********
outstrg:
	jsr	outcrlf
outstrg0:
	psha
outstrg1:
	ldaa	0,x		; read char into a
	cmpa	#eot
	beq	outstrg3	; jump if eot
	jsr	output		; output character
	inx
	jsr	input
	beq	outstrg1	; jump if no input
	cmpa	#ctlw
	bne	outstrg1	; jump if not cntlw
outstrg2:
	jsr	input
	beq	outstrg2	; jump if any input
	bra	outstrg1
outstrg3:
	pula
	rts

;**********
;*	inchar() - reads input until character sent.
;*	echoes char and returns with a = char.
inchar:	jsr	input
	tsta
	beq	inchar		; jump if no input
	jsr	output		; echo
	rts

;*********************
;*** command table ***
comtabl	= .
	.byte	5
	.ascii	'ASSEM'
	.word	#assem
	.byte	5
	.ascii	'BREAK'
	.word	#break
	.byte	4
	.ascii	'BULK'
	.word	#bulk
	.byte	7
	.ascii	'BULKALL'
	.word	#bulkall
	.byte	4
	.ascii	'CALL'
	.word	#call
	.byte	4
	.ascii	'DUMP'
	.word	#dump
	.byte	4
	.ascii	'FILL'
	.word	#fill
	.byte	2
	.ascii	'GO'
	.word	#go
	.byte	4
	.ascii	'HELP'
	.word	#help
	.byte	4
	.ascii	'HOST'
	.word	#host
	.byte	4
	.ascii	'LOAD'
	.word	#load
	.byte	6 		; length of command
	.ascii	'MEMORY'	; ascii command
	.word	#memory		; command address
	.byte	4
	.ascii	'MOVE'
	.word	#move
	.byte	7
	.ascii	'PROCEED'
	.word	#proceed
	.byte	8
	.ascii	'REGISTER'
	.word	#register
	.byte	5
	.ascii	'TRACE'
	.word	#trace
	.byte	6
	.ascii	'VERIFY'
	.word	#verify
	.byte	1
	.ascii	'?'		; initial command
	.word	#help
	.byte	5
	.ascii	'XBOOT'
	.word	#boot
;*
;*** command names for evm compatability ***
;*
	.byte	3
	.ascii	'ASM'
	.word	#assem
	.byte	2
	.ascii	'BF'
	.word	#fill
	.byte	4
	.ascii	'COPY'
	.word	#move
	.byte	5
	.ascii	'ERASE'
	.word	#bulk
	.byte	2
	.ascii	'MD'
	.word	#dump
	.byte	2
	.ascii	'MM'
	.word	#memory
	.byte	2
	.ascii	'RD'
	.word	#register
	.byte	2
	.ascii	'RM'
	.word	#register
	.byte	4
	.ascii	'READ'
	.word	#move
	.byte	2
	.ascii	'TM'
	.word	#host
	.byte	4
	.ascii	'TEST'
	.word	#evbtest
	.byte	-1

;*******************
;*** text tables ***

msg1:	.ascii	'BUFFALO 2.5 (ext) - '
	.ascii	'Bit User Fast Friendly Aid to Logical Operation'
	.byte	eot
msg2:	.ascii	'What?'
	.byte	eot
msg3:	.ascii	'Too Long'
	.byte	eot
msg4:	.ascii	'Full'
	.byte	eot
msg5:	.ascii	'Op- '
	.byte	eot
msg6:	.ascii	'rom-'
	.byte	eot
msg8:	.ascii	'Command?'
	.byte	eot
msg9:	.ascii	'Bad argument'
	.byte	eot
msg10:	.ascii	'No host port available'
	.byte	eot
msg11:	.ascii	'done'
	.byte	eot
msg12:	.ascii	'checksum error'
	.byte	eot
msg13:	.ascii	'error addr '
	.byte	eot

;**********
;*	break [-][<addr>] . . .
;* modifies the breakpoint table.  more than
;* one argument can be entered on the command
;* line but the table will hold only 4 entries.
;* 4 types of arguments are implied above:
;* break 		prints table contents.
;* break <addr>		inserts <addr>.
;* break -<addr>	deletes <addr>.
;* break -		clears all entries.
;**********
;* while 1
;*	a = wskip();
;*	switch(a)
;*		case(cr):
;*		bprint(); return;

break:	jsr	wskip
	cmpa	#0x0d
	bne	brkdel		; jump if not cr
	jsr	bprint		; print table
	rts

;*		case("-"):
;*		incbuff(); readbuff();
;*		if(dchek(a))		/* look for wspac or cr */
;*			bpclr();
;*			breaksw;
;*		a = buffarg();
;*		if( !dchek(a) ) return(bad argument);
;*		b = bpsrch();
;*		if(b >= 0)
;*			brktabl[b] = 0;
;*		breaksw;

brkdel:	cmpa	#'-
	bne	brkdef		; jump if not -
	jsr	incbuff
	jsr	readbuff
	jsr	dchek
	bne	brkdel1		; jump if not delimeter
	jsr	bpclr		; clear table
	jmp	break		; do next argument
brkdel1:
	jsr	buffarg		; get address to delete
	jsr	dchek
	beq	brkdel2		; jump if delimeter
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
brkdel2:
	jsr	bpsrch		; look for addr in table
	tstb
	bmi	brkdel3		; jump if not found
	ldx	#brktabl
	abx
	clr	0,x		; clear entry
	clr	1,x
brkdel3:
	jmp	break		; do next argument

;*		default:
;*		a = buffarg();
;*		if( !dchek(a) ) return(bad argument);
;*		b = bpsrch();
;*		if(b < 0)		/* not already in table */
;*			x = shftreg;
;*			shftreg = 0;
;*			a = x[0]; x[0] = 0x3f
;*			b = x[0]; x[0] = a;
;*			if(b != 0x3f) return(rom);
;*			b = bpsrch();	/* look for hole */
;*			if(b >= 0) return(table full);
;*			brktabl[b] = x;
;*		breaksw;

brkdef:	jsr	buffarg		; get argument
	jsr	dchek
	beq	brkdef1		; jump if delimiter
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
brkdef1:
	jsr	bpsrch		; look for entry in table
	tstb
	bge	break		; jump if already in table
	ldx	*shftreg	; x = new entry
	ldaa	0,x
	ldab	#swi
	stab	0,x
	ldab	0,x
	staa	0,x
	cmpb	#swi
	beq	brkdef2		; jump if writes ok
	stx	*ptr1		; save address
	ldx	#msg6		; "rom-"
	jsr	outstrg
	ldx	#ptr1
	jsr	out2bsp		; print address
	jsr	bprint
	rts
brkdef2:
	clr	*shftreg
	clr	*shftreg+1
	pshx
	jsr	bpsrch		; look for 0 entry
	pulx
	tstb
	bpl	brkdef3		; jump if table not full
	ldx	#msg4		; "full"
	jsr	outstrg
	jsr	bprint
	rts
brkdef3:

	ldy	#brktabl
	aby
	stx	0,y		; put new entry in
	jmp	break		; do next argument

;**********
;*	bprint() - print the contents of the table.
;**********
bprint:	jsr	outcrlf
	ldx	#brktabl
	ldab	#4
bprint1:
	jsr	out2bsp
	decb
	bgt	bprint1		; loop 4 times
	rts

;**********
;*	bpsrch() - search table for address in
;* shftreg. returns b = index to entry or
;* b = -1 if not found.
;**********
;*for(b=0; b=6; b=+2)
;*	x[] = brktabl + b;
;*	if(x[0] = shftreg)
;*		return(b);
;*return(-1);

bpsrch:	clrb
bpsrch1:
	ldx	#brktabl
	abx
	ldx	0,x		; get table entry
	cpx	*shftreg
	bne	bpsrch2		; jump if no match
	rts
bpsrch2:
	incb
	incb
	cmpb	#0x6
	ble	bpsrch1		; loop 4 times
	ldab	#0xff
	rts


;**********
;*	bulk - bulk erase the eeprom except the
;* config register.
;**********
bulk:
	clr	*tmp2
	bra	bulk1

;**********
;*	bulkall - bulk erase the eeprom and the
;* config register.
;**********
bulkall:
	clr	*tmp2
	inc	*tmp2

;*set up pprog register for erase
bulk1:	psha
	ldaa	#0x06
	staa	pprog		; set eelat, erase bits

;*if (ee only) write to 0xb600
;*else write to config register
	ldaa	#0xff
	tst	*tmp2
	bne	bulk2		; jump if config
	staa	0xb600		; write to 0xb600
	bra	bulk3
bulk2:	staa	config
bulk3	= .

;*start erasing
	ldaa	#0x07
	bne	acl3
	clra			; fail safe
acl3:	staa	pprog

;*delay for 10 ms at E = 2 mhz
	pshx
	ldx	#0x0d06		; 6~ * 3334 = 20,004 * 0.5 mhz
bulkdly:
	dex			; 2~
	bne	bulkdly		; 3~
	pulx

;*stop programming
	clr	pprog
	pula
	rts

;**********
;*	dump [<addr1> [<addr2>]]  - dump memory
;* in 16 byte lines from <addr1> to <addr2>.
;*	default starting address is "current
;* location" and default number of lines is 8.
;**********
;*ptr1 = ptrmem;	/* default start address */
;*ptr2 = ptr1 + 0x80;	/* default end address */
;*a = wskip();
;*if(a != cr)
;*	a = buffarg();
;*	if(countu1 = 0) return(bad argument);
;*	if( !dchek(a) ) return(bad argument);
;*	ptr1 = shftreg;
;*	ptr2 = ptr1 + 0x80;	/* default end address */
;*	a = wskip();
;*	if(a != cr)
;*		a = buffarg();
;*		if(countu1 = 0) return(bad argument);
;*		a = wskip();
;*		if(a != cr) return(bad argument);
;*		ptr2 = shftreg;

dump:	ldx	*ptrmem		; current location
	stx	*ptr1		; default start
	ldab	#0x80
	abx
	stx	*ptr2		; default end
	jsr	wskip
	cmpa	#0xd
	beq	dump1		; jump - no arguments
	jsr	buffarg		; read argument
	tst	*count
	beq	dumperr		; jump if no argument
	jsr	dchek
	bne	dumperr		; jump if delimiter
	ldx	*shftreg
	stx	*ptr1
	ldab	#0x80
	abx
	stx	*ptr2		; default end address
	jsr	wskip
	cmpa	#0xd
	beq	dump1		; jump - 1 argument
	jsr	buffarg		; read argument
	tst	*count
	beq	dumperr		; jump if no argument
	jsr	wskip
	cmpa	#0x0d
	bne	dumperr		; jump if not cr
	ldx	*shftreg
	stx	*ptr2
	bra	dump1		; jump - 2 arguments
dumperr:
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts

;*ptrmem = ptr1;
;*ptr1 = ptr1 & 0xfff0;

dump1:	ldd	*ptr1
	std	*ptrmem		; new current location
	andb	#0xf0
	std	*ptr1		; start dump at 16 byte boundary

;*** dump loop starts here ***
;*do:
;*	output address of first byte;

dumplp:	jsr	outcrlf
	ldx	#ptr1
	jsr	out2bsp		; first address

;*	x = ptr1;
;*	for(b=0; b=16; b++)
;*		output contents;

	ldx	*ptr1		; base address
	clrb			; loop counter
dumpdat:
	jsr	out1bsp		; hex value loop
	incb
	cmpb	#0x10
	blt	dumpdat		; loop 16 times

;*	x = ptr1;
;*	for(b=0; b=16; b++)
;*		a = x[b];
;*		if(0x7a < a < 0x20)  a = 0x20;
;*		output ascii contents;

	clrb			; loop counter
dumpasc:
	ldx	*ptr1		; base address
	abx
	ldaa	,x		; ascii value loop
	cmpa	#0x20
	blo	dump3		; jump if non printable
	cmpa	#0x7a
	bls	dump4		; jump if printable
dump3:	ldaa	#0x20		; space for non printables
dump4:	jsr	output		; output ascii value
	incb
	cmpb	#0x10
	blt	dumpasc		; loop 16 times

;*	chkabrt();
;*	ptr1 = ptr1 + 0x10;
;*while(ptr1 <= ptr2);
;*return;

	jsr	chkabrt		; check abort or wait
	ldd	*ptr1
	addd	#0x10		; point to next 16 byte bound
	std	*ptr1		; update ptr1
	cpd	*ptr2
	bhi	dump5		; quit if ptr1 > ptr2
	cpd	#0x00		; check wraparound at 0xffff
	bne	dumplp		; jump - no wraparound
	ldd	*ptr2
	cpd	#0xfff0
	blo	dumplp		; upper bound not at top
dump5:	rts			; quit

;**********
;*	fill <addr1> <addr2> [<data>]  - block fill
;*memory from addr1 to addr2 with data.	data
;*defaults to 0xff.
;**********
;*get addr1 and addr2

fill	= .
	jsr	wskip
	jsr	buffarg
	tst	*count
	beq	fillerr		; jump if no argument
	jsr	wchek
	bne	fillerr		; jump if bad argument
	ldx	*shftreg
	stx	*ptr1		; address1
	jsr	wskip
	jsr	buffarg
	tst	*count
	beq	fillerr		; jump if no argument
	jsr	dchek
	bne	fillerr		; jump if bad argument
	ldx	*shftreg
	stx	*ptr2		; address2

;*get data if it exists
	ldaa	#0xff
	staa	*tmp2		; default data
	jsr	wskip
	cmpa	#0x0d
	beq	fill1		; jump if default data
	jsr	buffarg
	tst	*count
	beq	fillerr		; jump if no argument
	jsr	wskip
	cmpa	#0x0d
	bne	fillerr		; jump if bad argument
	ldaa	*shftreg+1
	staa	*tmp2

;*while(ptr1 <= ptr2)
;*	*ptr1 = data
;*	if(*ptr1 != data) abort

fill1	= .
	jsr	chkabrt		; check for abort
	ldx	*ptr1		; starting address
	ldaa	*tmp2		; data
	staa	0,x
	cmpa	0,x
	bne	fillbad		; jump if no write
	cpx	*ptr2
	beq	fill2		; quit yet?
	inx
	stx	*ptr1
	bra	fill1		; loop
fill2:	rts

fillerr:
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts

fillbad:
	ldx	#msg6		; "rom -"
	jsr	outstrg
	ldx	#ptr1
	jsr	out2bsp
	rts

;**********
;*	call [<addr>] - execute a jsr to addr or
;*user's pc value.  return to monitor by rts
;*or breakpoint.
;**********
;*a = wskip();
;*if(a != cr)
;*	a = buffarg();
;*	a = wskip();
;*	if(a != cr) return(bad argument)
;*	pc = shftreg;

call:	jsr	wskip
	cmpa	#0xd
	beq	call3		; jump if no arg
	jsr	buffarg
	jsr	wskip
	cmpa	#0xd
	beq	call2		; jump if cr
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
call2:	ldx	*shftreg
	stx	*regs		; pc = <addr>

;*user_stack[0] = return_to_monitor;
;*setbps();
;*restack();	/* restack and go*/

call3:	ldx	*sp
	dex			; user stack pointer
	ldd	#return		; return address
	std	0,x
	dex
	stx	*sp		; new user stack pointer
	jsr	setbps
	clr	*tmp2		; flag for breakpoints
	jmp	restack		; executes an rti

;**********
;*	return() - return here from rts after
;*call command.
;**********
return:	psha			; save a register
	tpa
	staa	*regs+8		; cc register
	pula
	std	*regs+6		; a and b registers
	stx	*regs+4		; x register
	sty	*regs+2		; y register
	sts	*sp		; user stack pointer
	lds	#stack		; monitor stack pointer
	jsr	rembps		; remove breakpoints
	jsr	outcrlf
	jsr	rprint		; print user registers
	jmp	main

;**********
;*	go [<addr>] - execute starting at <addr> or
;*user's pc value.  executes an rti to user code.
;*returns to monitor via an swi through swiin.
;**********
;*a = wskip();
;*if(a != cr)
;*	a = buffarg();
;*	a = wskip();
;*	if(a != cr) return(bad argument)
;*	pc = shftreg;
;*setbps();
;*restack();	/* restack and go*/

go:	jsr	wskip
	cmpa	#0x0d
	beq	go2		; jump if no arg
	jsr	buffarg
	jsr	wskip
	cmpa	#0x0d
	beq	go1		; jump if cr
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
go1:	ldx	*shftreg
	stx	*regs		; pc = <addr>
go2:	clr	*tmp2		; flag for breakpoints
	inc	*tmp2		; (1=go, 0=call)
	jsr	setbps
	jmp	restack		; execute an rti

;**********
;*	swiin() - return from swi.	set up
;*stack pointers, save user registers, and
;*return to main.
;**********
swiin:	tsx			; swi entry point
	lds	#stack
	jsr	savstack	; save user regs
	ldx	*regs
	dex
	stx	*regs		; save user pc
	ldx	*ptr4		; restore user swi vector
	stx	*jswi+1

;*if(flagt1 = 0) remove return addr from stack;

	tst	*tmp2		; 0=call, 1=go
	bne	go3		; jump if go command
	ldx	*sp		; remove return address
	inx
	inx
	stx	*sp
go3:	jsr	outcrlf		; print register values
	jsr	rprint
	jsr	rembps
	jmp	main		; return to monitor
;*				; (sp destroyed above)

;**********
;*	proceed - same as go except it ignores
;*a breakpoint at the first opcode.  calls
;*trace once and the go.
;**********
proceed:
	clr	*tmp2		; flag for breakpoints
	inc	*tmp2		; 0=trace, 1=proceed
	jmp	trace3

;**********
;*	trace <n> - trace n instructions starting
;*at user's pc value. n is a hex number less than
;*0xff (defaults to 1).
;**********
;*countt1 = 1
;*a = wskip();
;*if(a != cr)
;*	a = buffarg(); a = wskip();
;*	if(a != cr) return(bad argument);
;*	countt1 = n

trace:	clr	*tmp4
	inc	*tmp4		; default countt1 = 1
	clr	*tmp2		; 0 = trace
	jsr	wskip
	cmpa	#0x0d
	beq	trace2		; jump if cr
	jsr	buffarg
	jsr	wskip
	cmpa	#0x0d
	beq	trace1		; jump if cr
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
trace1:	ldaa	*shftreg+1	; n
	staa	*tmp4

;*print opcode
trace2:	jsr	outcrlf
	ldx	#msg5		; "op-"
	jsr	outstrg
	ldx	*regs
	jsr	out1bsp		; opcode

;*save user oc5 regs, setup monitor oc5 regs
trace3:	ldaa	tctl1
	staa	*ptr2		; save user mode/level
	anda	#0xfc
	staa	tctl1		; disable oc5 output
	ldaa	tmsk1
	staa	*ptr2+1		; save user int masks
	clr	tmsk2		; disable tof and pac ints

;*put monitor toc5 vector into jump table
	ldx	*jtoc5+1
	stx	*ptr4		; save user's vector
	ldaa	#0x7e		; jmp opcode
	staa	*jtoc5
	ldx	#tracein
	stx	*jtoc5+1	; monitor toc5 vector

;*unmask i bit in user ccr
	ldaa	*regs+8		; user ccr
	anda	#0xef		; clear i bit
	staa	*regs+8

;*arm oc5 interrupt
	ldab	#87		; cycles to end of rti
	ldx	tcnt		; timer count value
	abx			; 			3~ )
	stx	toc5		; oc5 match register	5~  )
	ldaa	#0x08		; 			2~	)
	staa	tflg1		; clear oc5 int flag	4~	) 86~
	staa	tmsk1		; enable oc5 interrupt	4~	)
	cli			; 			2~  )
	jmp	restack		; execute an rti 	66~ )

;**********
;*	tracein - return from toc5 interrupt.
;**********
;*disable toc5 interrupt
;*replace user's toc5 vector
tracein:
	sei
	clr	tmsk1		; disable timer ints
	tsx
	lds	#stack
	jsr	savstack	; save user regs
	ldx	*ptr4
	stx	*jtoc5+1
	jsr	chkabrt		; check for abort

;*if(flagt1 = 1) jump to go command ( proceed )
	tst	*tmp2
	beq	trace9		; jump if trace command
	jmp	go2

;*rprint();
;*while(countt1 >= 0) continue trace;

trace9:	jsr	outcrlf		; print registers for
	jsr	rprint		; trace only.
	dec	*tmp4
	bhi	trace2		; jump if countt1 >= 0
	jmp	main		; return to monitor
;*				; (sp destroyed above)

;**********
;*	setbps - replace user code with swi's at
;*breakpoint addresses.
;**********
;*for(b=0; b=6; b =+ 2)
;*	x = brktabl[b];
;*	if(x != 0)
;*		optabl[b] = x[0];
;*		x[0] = 0x3f;

setbps:	clrb
setbps1:
	ldx	#brktabl
	ldy	#ptr6
	abx
	aby
	ldx	0,x		; breakpoint table entry
	beq	setbps2		; jump if 0
	ldaa	0,x		; save user opcode
	staa	0,y
	ldaa	#swi		; insert swi into code
	staa	0,x
setbps2:
	addb	#0x2
	cmpb	#0x6
	ble	setbps1		; loop 4 times

;*put monitor swi vector into jump table
	ldx	*jswi+1
	stx	*ptr4		; save user swi vector
	ldaa	#0x7e		; jmp opcode
	staa	*jswi
	ldx	#swiin
	stx	*jswi+1		; monitor swi vector
	rts

;**********
;*	rembps - remove breakpoints from user code.
;**********
;*for(b=0; b=6; b =+ 2)
;*	x = brktabl[b];
;*	if(x != 0)
;*		x[0] = optabl[b];

rembps:	clrb
rembps1:
	ldx	#brktabl
	ldy	#ptr6
	abx
	aby
	ldx	0,x		; breakpoint table entry
	beq	rembps2		; jump if 0
	ldaa	0,y		; restore user's opcode
	staa	0,x
rembps2:
	addb	#0x2
	cmpb	#0x6
	ble	rembps1		; loop 4 times

;*replace user's swi vector
	ldx	*ptr4
	stx	*jswi+1
	rts

;**********
;*	restack() - restore user stack and
;*execute an rti. extended addressing forced
;*to ensure count value for trace.
;**********
restack:
	lds	sp		; stack pointer
	ldx	regs
	pshx			; pc
	ldx	regs+2
	pshx			; y
	ldx	regs+4
	pshx			; x
	ldd	regs+6
	psha			; a
	pshb			; b
	ldaa	regs+8
	psha			; ccr
restack1:
	rti

;**********
;*	savstack() -	save user's registers.
;**********
savstack:
	ldaa	0,x
	staa	*regs+8		; ccr
	ldd	1,x
	staa	*regs+7		; b
	stab	*regs+6		; a
	ldd	3,x
	std	*regs+4		; x
	ldd	5,x
	std	*regs+2		; y
	ldd	7,x
	std	*regs		; pc
	ldab	#8
	abx
	stx	*sp		; stack pointer
	rts

;**********
;*	help  -  list buffalo commands to terminal.
;**********
help	= .
	ldx	#helpmsg1
	jsr	outstrg		; print help screen
	rts

helpmsg1	= .
	.ascii	'ASM [<addr>]  Line assembler/disassembler.'
	.byte	0x0d
	.ascii	'    /        Do same address.'
	.ascii	'           ^        Do previous address.'
	.byte	0x0d
	.ascii	'    CTRL-J   Do next address.'
	.ascii	'           RETURN   Do next opcode.'
	.byte	0x0d
	.ascii	'    CTRL-A   Quit.'
	.byte	0x0d
	.ascii	'BF <addr1> <addr2> [<data>]  Block fill.'
	.byte	0x0d
	.ascii	'BR [-][<addr>]  Set up breakpoint table.'
	.byte	0x0d
	.ascii	'BULK  Erase the EEPROM.'
	.ascii	'                   BULKALL  Erase EEPROM and CONFIG.'
	.byte	0x0d
	.ascii	'CALL [<addr>]  Call user subroutine.'
	.ascii	'      G [<addr>]  Execute user code.'
	.byte	0x0d
	.ascii	'LOAD, VERIFY [T] <host download command>'
	.ascii	'  Load or verify S-records.'
	.byte	0x0d
	.ascii	'MD [<addr1> [<addr2>]]  Memory dump.'
	.byte	0x0d
	.ascii	'MM [<addr>]  Memory modify.'
	.byte	0x0d
	.ascii	'    /        Open same address.         CTRL-H'
	.ascii	' or ^   Open previous address.'
	.byte	0x0d
	.ascii	'    CTRL-J   Open next address.         SPACE'
	.ascii	'         Open next address.'
	.byte	0x0d
	.ascii	'    RETURN   Quit.                      <addr>O'
	.ascii	'       Compute offset to <addr>.'
	.byte	0x0d
	.ascii	'MOVE <s1> <s2> [<d>]  Block move.'
	.byte	0x0d
	.ascii	'P  Proceed/continue execution.'
	.byte	0x0d
	.ascii	'RM [P, Y, X, A, B, C, or S]  Register modify.'
	.byte	0x0d
	.ascii	'T [<n>]  Trace n instructions.'
	.byte	0x0d
	.ascii	'TM  Transparent mode (CTRL-A = exit, CTRL-B = send break).'
	.byte	0x0d
	.ascii	'CTRL-H  Backspace.'
	.ascii	'                      CTRL-W  Wait for any key.'
	.byte	0x0d
	.ascii	'CTRL-X or DELETE  Abort/cancel command.'
	.byte	0x0d
	.ascii	'RETURN  Repeat last command.'
	.byte	4

;**********
;*	host() - establishes transparent link between
;*	terminal and host.  port used for host is
;*	determined in the reset initialization routine
;*	and stored in hostdev.
;*		to exit type control a.
;*		to send break to host type control b.
;*if(no external device) return;
;*initialize host port;
;*while( !(control a))
;*	input(terminal); output(host);
;*	input(host); output(terminal);

host:	ldaa	*extdev
	bne	host0		; jump if host port avail.
	ldx	#msg10		; "no host port avail"
	jsr	outstrg
	rts
host0:	clr	*autolf		; turn off autolf
	jsr	hostco		; connect sci (evb board)
	jsr	hostinit	; initialize host port
host1:	jsr	input		; read terminal
	tsta
	beq	host3		; jump if no char
	cmpa	#ctla
	beq	hostend		; jump if control a
	cmpa	#ctlb
	bne	host2		; jump if not control b
	jsr	txbreak		; send break to host
	bra	host3
host2:	jsr	hostout		; echo to host
host3:	jsr	hostin		; read host
	tsta
	beq	host1		; jump if no char
	jsr	output		; echo to terminal
	bra	host1
hostend:
	inc	*autolf		; turn on autolf
	jsr	targco		; disconnect sci (evb board)
	rts			; return

;**********
;* txbreak() - transmit break to host port.
;* the duration of the transmitted break is
;* approximately 200,000 e-clock cycles, or
;* 100ms at 2.0 mhz.
;***********
txbreak	= .
	ldaa	*hostdev
	cmpa	#0x03
	beq	txbdu		; jump if duartb is host

txbsci:	ldx	#sccr2		; sci is host
	bset	0,x ,#0x01	; set send break bit
	bsr	txbwait
	bclr	0,x ,#0x01	; clear send break bit
	bra txb1

txbdu:	ldx	#portb		; duart host port
	ldaa	#0x60		; start break cmd
	staa	2,x		; port b command register
	bsr	txbwait
	ldaa	#0x70		; stop break cmd
	staa	2,x		; port b command register

txb1:	ldaa	#0x0d
	jsr	hostout		; send carriage return
	ldaa	#0x0a
	jsr	hostout		; send linefeed
	rts

txbwait:
	ldy	#0x6f9b		; loop count = 28571
txbwait1:
	dey			; 7 cycle loop
	bne	txbwait1
	rts


;**********
;*	hostinit(), hostin(), hostout() - host i/o
;*routines.  restores original terminal device.
;**********
hostinit:
	ldab	*iodev		; save terminal
	pshb
	ldab	*hostdev
	stab	*iodev		; point to host
	jsr	init		; initialize host
	bra	termres		; restore terminal
hostin:	ldab	*iodev		; save terminal
	pshb
	ldab	*hostdev
	stab	*iodev		; point to host
	jsr	input		; read host
	bra	termres		; restore terminal
hostout:
	ldab	*iodev		; save terminal
	pshb
	ldab	*hostdev
	stab	*iodev		; point to host
	jsr	output		; write to host
termres:
	pulb			; restore terminal device
	stab	*iodev
	rts


;**********
;*	load(ptrbuff[]) - load s1/s9 records from
;*host to memory.  ptrbuff[] points to string in
;*input buffer which is a command to output s1/s9
;*records from the host ("cat filename" for unix).
;*	returns error and address if it can't write
;*to a particular location.
;**********
;*	verify(ptrbuff[]) - verify memory from load
;*command.  ptrbuff[] is same as for load.
;**********
verify:	clr	*tmp2
	inc	*tmp2		; flagt1 = 1 = verify
	bra	load1
load:	clr	*tmp2		; flagt1 = 0 = load


;*a=wskip();
;*if(a = cr) goto transparent mode;
;*if(t option) hostdev = iodev;

load1:	jsr	wskip
	cmpa	#0x0d
	bne	load1a
	jmp	host		; go to host if no args
load1a:	jsr	upcase
	cmpa	#'T		; look for t option
	bne	load1b		; jump not t option
	jsr	incbuff
	jsr	readbuff	; get next character
	jsr	decbuff
	cmpa	#0x0d
	bne	load1b		; jump if not t option
	clr	*autolf
	ldaa	*iodev
	staa	*hostdev		; set host port = terminal
	bra	load6		; go wait for s1 records

;*else while(not cr)
;*	read character from input buffer;
;*	send character to host;

load1b:	clr	*autolf
	jsr	hostco		; connect sci (evb board)
	jsr	hostinit	; initialize host port
load2:	jsr	readbuff	; get next char
	jsr	incbuff
	psha			; save char
	jsr	hostout		; output to host
	jsr	output		; echo to terminal
	pula
	cmpa	#0x0d
	bne	load2		; jump if not cr

;*repeat:
;*	if(hostdev != iodev) check abort;
;*	a = hostin();
;*	if(a = 's')
;*		a = hostin;
;*		if(a = '9')
;*		read rest of record;
;*		return(done);
;*		if(a = '1')
;*		checksum = 0;
;*		byte(); b = shftreg+1;	/* byte count */
;*		byte(); byte(); x = shftreg; /* base addr*/
;*		do
;*			byte();
;*			if(flagt1 = 0)
;*			x[0] = shftreg+1
;*			if(x[0] != shftreg+1)
;*				return("rom-(x)");
;*			x++; b--;
;*		until(b = 0)

load6	= .
	ldaa	*hostdev
	cmpa	*iodev
	beq	load65		; jump if hostdev=iodev
	jsr	chkabrt		; check for abort
load65:	jsr	hostin		; read host
	tsta
	beq	load6		; jump if no input
	cmpa	#'S
	bne	load6		; jump if not s
load7:	jsr	hostin		; read host
	tsta
	beq	load7		; jump if no input
	cmpa	#'9
	bne	load8		; jump if not s9
	jsr	byte
	ldab	*shftreg+1	; b = byte count
load75:	jsr	byte
	decb
	bne	load75		; loop until end of record
	inc	*autolf		; turn on autolf
	jsr	targco		; disconnect sci (evb)
	ldx	#msg11		; "done"
	jsr	outstrg
	rts
load8:	cmpa	#'1
	bne	load6		; jump if not s1
	clr	*tmp4		; clear checksum
	jsr	byte
	ldab	*shftreg+1
	subb	#0x2		; b = byte count
	jsr	byte
	jsr	byte
	ldx	*shftreg	; x = base address
	dex
load10:	jsr	byte		; get next byte
	inx
	decb			; check byte count
	beq	load12		; if 0, go do checksum
	ldaa	*shftreg+1
	tst	*tmp2
	bne	load11		; jump if verify
	staa	0,x		; load only
load11:	cmpa	0,x		; verify ram location
	beq	load10		; jump if ram ok
	stx	*ptr3		; save error address
	inc	*autolf		; turn on autolf
	jsr	targco		; disconnect sci(evb)
	jsr	outcrlf
	ldx	#msg13		; "error addr"
	jsr	outstrg
	ldx	#ptr3
	jsr	out2bsp		; address
	rts
load12:	ldaa	*tmp4
	inca			; do checksum
	bne	load13		; jump if s1 record okay
	jmp	load6
load13:	inc	*autolf
	jsr	targco		; disconnect sci(evb)
	jsr	outcrlf
	ldx	#msg12		; "checksum error"
	jsr	outstrg
	rts

;**********
;*	byte() -  read 2 ascii bytes from host and
;*convert to one hex byte.  returns byte
;*shifted into shftreg and added to tmp4.
;**********
byte:	pshb
	pshx
byte0:	jsr	hostin		; read host (1st byte)
	tsta
	beq	byte0		; loop until input
	jsr	hexbin
byte1:	jsr	hostin		; read host (2nd byte)
	tsta
	beq	byte1		; loop until input
	jsr	hexbin
	ldaa	*shftreg+1
	adda	*tmp4
	staa	*tmp4		; add to checksum
	pulx
	pulb
	rts


;*******************************************
;*	memory [<addr>]
;*	[<addr>]/
;* opens memory and allows user to modify the
;*contents at <addr> or the last opened location.
;*	subcommands:
;* [<data>]<cr> - close current location and exit.
;* [<data>]<lf> - close current and open next.
;* [<data>]<^> - close current and open previous.
;* [<data>]<sp> - close current and open next.
;* [<data>]/ - reopen current location.
;*	the contents of the current location is only
;*	changed if valid data is entered before each
;*  subcommand.
;* [<addr>]o - compute relative offset from current
;*	location to <addr>.  the current location must
;*	be the address of the offset byte.
;**********
;*a = wskip();
;*if(a != cr)
;*	a = buffarg();
;*	if(a != cr) return(bad argument);
;*	if(countu1 != 0) ptrmem[] = shftreg;

memory:	jsr	wskip
	cmpa	#0xd
	beq	mem1		; jump if cr
	jsr	buffarg
	jsr	wskip
	cmpa	#0xd
	beq	mslash		; jump if cr
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
mslash:	tst	*count
	beq	mem1		; jump if no argument
	ldx	*shftreg
	stx	*ptrmem		; update "current location"

;**********
;* subcommands
;**********
;*outcrlf();
;*out2bsp(ptrmem[]);
;*out1bsp(ptrmem[0]);

mem1:	jsr	outcrlf
mem2:	ldx	#ptrmem
	jsr	out2bsp		; output address
mem3:	ldx	*ptrmem
	jsr	out1bsp		; output contents
	clr	*shftreg
	clr	*shftreg+1
;*while 1
;*a = termarg();
;*	switch(a)
;*		case(space):
;*		chgbyt();
;*		ptrmem[]++;
;*		case(linefeed):
;*		chgbyt();
;*		ptrmem[]++;
;*		case(up arrow):
;*		case(backspace):
;*		chgbyt();
;*		ptrmem[]--;
;*		case("/"):
;*		chgbyt();
;*		outcrlf();
;*		case(o):
;*		d = ptrmem[0] - (shftreg);
;*		if(0x80 < d < 0xff81)
;*			print(out of range);
;*		countt1 = d-1;
;*		out1bsp(countt1);
;*		case(carriage return):
;*		chgbyt();
;*		return;
;*		default: return(command?)

mem4:	jsr	termarg
	jsr	upcase
	ldx	*ptrmem
	cmpa	#0x20
	beq	memsp		; jump if space
	cmpa	#0x0a
	beq	memlf		; jump if linefeed
	cmpa	#0x5e
	beq	memua		; jump if up arrow
	cmpa	#0x08
	beq	membs		; jump if backspace
	cmpa	#'/
	beq	memsl		; jump if /
	cmpa	#'O
	beq	memoff		; jump if o
	cmpa	#0x0d
	beq	memcr		; jump if carriage ret
	ldx	#msg8		; "command?"
	jsr	outstrg
	jmp	mem1
memsp:	jsr	chgbyt
	inx
	stx	*ptrmem
	jmp	mem3		; output contents
memlf:	jsr	chgbyt
	inx
	stx	*ptrmem
	jmp	mem2		; output addr, contents
memua	= .
membs:	jsr	chgbyt
	dex
	stx	*ptrmem
	jmp	mem1		; output cr, addr, contents
memsl:	jsr	chgbyt
	jmp	mem1		; output cr, addr, contents
memoff:	ldd	*shftreg	; destination addr
	subd	*ptrmem
	cmpa	#0x0
	bne	memoff1		; jump if not 0
	cmpb	#0x80
	bls	memoff3		; jump if in range
	bra	memoff2		; out of range
memoff1:
	cmpa	#0xff
	bne	memoff2		; out of range
	cmpb	#0x81
	bhs	memoff3		; in range
memoff2:
	ldx	#msg3		; "too long"
	jsr	outstrg
	jmp	mem1		; output cr, addr, contents
memoff3:
	subd	#0x1		; b now has offset
	stab	*tmp4
	jsr	outspac
	ldx	#tmp4
	jsr	out1bsp		; output offset
	jmp	mem1		; output cr, addr, contents
memcr:	jsr	chgbyt
	rts			; exit task


;**********
;*	move <src1> <src2> [<dest>]	- move
;*block at <src1> to <src2> to <dest>.
;*	moves block 1 byte up if no <dest>.
;**********
;*a = buffarg();
;*if(countu1 = 0) return(bad argument);
;*if( !wchek(a) ) return(bad argument);
;*ptr1 = shftreg;	/* src1 */

move	= .
	jsr	buffarg
	tst	*count
	beq	moverr		; jump if no arg
	jsr	wchek
	bne	moverr		; jump if no delim
	ldx	*shftreg	; src1
	stx	*ptr1

;*a = buffarg();
;*if(countu1 = 0) return(bad argument);
;*if( !dchek(a) ) return(bad argument);
;*ptr2 = shftreg;	/* src2 */

	jsr	buffarg
	tst	*count
	beq	moverr		; jump if no arg
	jsr	dchek
	bne	moverr		; jump if no delim
	ldx	*shftreg	; src2
	stx	*ptr2

;*a = buffarg();
;*a = wskip();
;*if(a != cr) return(bad argument);
;*if(countu1 != 0) tmp2 = shftreg;  /* dest */
;*else tmp2 = ptr1 + 1;

	jsr	buffarg
	jsr	wskip
	cmpa	#0x0d
	bne	moverr		; jump if not cr
	tst	*count
	beq	move1		; jump if no arg
	ldx	*shftreg	; dest
	bra	move2
moverr:	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
move1:	ldx	*ptr1
	inx			; default dest
move2:	stx	*ptr3

;*if(src1 < dest <= src2)
;*	dest = dest+(src2-src1);
;*	for(x = src2; x = src1; x--)
;*		dest[0]-- = x[0]--;

	ldx	*ptr3		; dest
	cpx	*ptr1		; src1
	bls	move3		; jump if dest =< src1
	cpx	*ptr2		; src2
	bhi	move3		; jump if dest > src2
	ldd	*ptr2
	subd	*ptr1
	addd	*ptr3
	std	*ptr3		; dest = dest+(src2-src1)
	ldx	*ptr2
movelp1:
	jsr	chkabrt		; check for abort
	ldaa	,x		; char at src2
	pshx
	ldx	*ptr3
	cpx	#0xb600		; jump if not eeprom
	blo	movea
	cpx	#0xb7ff		; jump if not eeprom
	bhi	movea
	jsr	movprog		; program eeprom
movea:	staa	,x		; dest
	dex
	stx	*ptr3
	pulx
	cpx	*ptr1
	beq	movrts
	dex
	bra	movelp1		; loop src2 - src1 times
;*
;* else
;*	for(x=src1; x=src2; x++)
;*		dest[0]++ = x[0]++;


move3:	ldx	*ptr1		; srce1
movelp2:
	jsr	chkabrt		; check for abort
	ldaa	,x
	pshx
	ldx	*ptr3		; dest
	cpx	#0xb600		; jump if not eeprom
	blo	moveb
	cpx	#0xb7ff		; jump if not eeprom
	bhi	moveb
	jsr	movprog		; program eeprom
moveb:	staa	,x
	inx
	stx	*ptr3
	pulx
	cpx	*ptr2
	beq	movrts
	inx
	bra	movelp2		; loop src2-src1 times
movrts:	rts

;*************
;*	movprog - program eeprom location in x with
;*	data in a.
;*************
movprog:
	pshb
	pshx
	ldab	#0x02
	stab	pprog		; set eelat
	staa	,x
	ldab	#0x03
	bne	acl4
	clrb			; fail safe
acl4:	stab	pprog		; set pgm
	ldx	#0x0d06
movedly:
	dex
	bne	movedly		; delay 10 ms at E = 2 mhz
	ldab	#0x00
	stab	pprog
	pulx
	pulb
	rts


;**********
;*	register [<name>]	- prints the user regs
;*and opens them for modification.	<name> is
;*the first register opened (default = p).
;*	subcommands:
;* [<nn>]<space>	opens the next register.
;* [<nn>]<cr>	return.
;*	the register value is only changed if
;*	<nn> is entered before the subcommand.
;**********
;*x[] = reglist
;*a = wskip(); a = upcase(a);
;*if(a != cr)
;*	while( a != x[0] )
;*		if( x[0] = "s") return(bad argument);
;*		x[]++;
;*	incbuff(); a = wskip();
;*	if(a != cr) return(bad argument);

register:
	ldx	#reglist
	jsr	wskip		; a = first char of arg
	jsr	upcase		; convert to upper case
	cmpa	#0xd
	beq	reg4		; jump if no argument
reg1:	cmpa	0,x
	beq	reg3
	ldab	0,x
	inx
	cmpb	#'S
	bne	reg1		; jump if not "s"
reg2:	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
reg3:	pshx
	jsr	incbuff
	jsr	wskip		; next char after arg
	cmpa	#0xd
	pulx
	bne	reg2		; jump if not cr

;*rprint();
;*	while(x[0] != "s")
;*		rprnt1(x);
;*		a = termarg();	/* read from terminal */
;*		if( ! dchek(a) ) return(bad argument);
;*		if(countu1 != 0)
;*		if(x[14] = 1)
;*			regs[x[7]++ = shftreg;
;*		regs[x[7]] = shftreg+1;
;*		if(a = cr) break;
;*return;

reg4:	jsr	rprint		; print all registers
reg5:	jsr	outcrlf
	jsr	rprnt1		; print reg name
	clr	*shftreg
	clr	*shftreg+1
	jsr	termarg		; read subcommand
	jsr	dchek
	beq	reg6		; jump if delimeter
	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts
reg6:	psha
	pshx
	tst	*count
	beq	reg8		; jump if no input
	ldab	7,x		; get reg offset
	ldaa	14,x		; byte size
	ldx	#regs		; user registers
	abx
	tsta
	beq	reg7		; jump if 1 byte reg
	ldaa	*shftreg
	staa	0,x		; put in top byte
	inx
reg7:	ldaa	*shftreg+1
	staa	0,x		; put in bottom byte
reg8:	pulx
	pula
	ldab	0,x		; check for register s
	cmpb	#'S
	beq	reg9		; jump if "s"
	inx			; point to next register
	cmpa	#0xd
	bne	reg5		; jump if not cr
reg9:	rts

page1	=	0x00		; values for page opcodes
page2	=	0x18
page3	=	0x1a
page4	=	0xcd
immed	=	0x0		; addressing modes
indx	=	0x1
indy	=	0x2
limmed	=	0x3		; (long immediate)
other	=	0x4

;*** rename variables for assem/disassem ***
amode	=	tmp2		; addressing mode
yflag	=	tmp3
pnorm	=	tmp4		; page for normal opcode
oldpc	=	ptrmem
pc	=	ptr1		; program counter
px	=	ptr2		; page for x indexed
py	=	ptr2+1		; page for y indexed
baseop	=	ptr3		; base opcode
class	=	ptr3+1		; class
dispc	=	ptr4		; pc for disassembler
braddr	=	ptr5		; relative branch offset
mneptr	=	ptr6		; pointer to table for dis
asscomm	=	ptr7		; subcommand for assembler

;*** error messages for assembler ***
msgdir:	.word	#msga1		; message table index
	.word	#msga2
	.word	#msga3
	.word	#msga4
	.word	#msga5
	.word	#msga6
	.word	#msga7
	.word	#msga8
	.word	#msga9
msga1:	.ascii	'Immediate mode illegal'
	.byte	eot
msga2:	.ascii	'Error in mnemonic table'
	.byte	eot
msga3:	.ascii	'Illegal bit op'
	.byte	eot
msga4:	.ascii	'Bad argument'
	.byte	eot
msga5:	.ascii	'Mnemonic not found'
	.byte	eot
msga6:	.ascii	'Unknown addressing mode'
	.byte	eot
msga7:	.ascii	'Indexed addressing assumed'
	.byte	eot
msga8:	.ascii	'Syntax error'
	.byte	eot
msga9:	.ascii	'Branch out of range'
	.byte	eot

;****************
;*	assem(addr) -68hc11 line assembler/disassembler.
;*	this routine will disassemble the opcode at
;*<addr> and then allow the user to enter a line for
;*assembly. rules for assembly are as follows:
;* -a '#' sign indicates immediate addressing.
;* -a ',' (comma) indicates indexed addressing
;*	and the next character must be x or y.
;* -all arguments are assumed to be hex and the
;*	'$' sign shouldn't be used.
;* -arguments should be separated by 1 or more
;*	spaces or tabs.
;* -any input after the required number of
;*	arguments is ignored.
;* -upper or lower case makes no difference.
;*
;*	to signify end of input line, the following
;*commands are available and have the indicated action:
;*	<cr>  -carriage return finds the next opcode for
;*		assembly.  if there was no assembly input,
;*		the next opcode disassembled is retrieved
;*		from the disassembler.
;*	<lf>  -linefeed works the same as carriage return
;*		except if there was no assembly input, the
;*		<addr> is incremented and the next <addr> is
;*		disassembled.
;*	'^'  -up arrow decrements <addr> and the previous
;*		address is then disassembled.
;*	'/'  -slash redisassembles the current address.
;*
;*	to exit the assembler use control a.  of course
;*control x and del will also allow you to abort.
;**********
;*oldpc = rambase;
;*a = wskip();
;*if (a != cr)
;*	buffarg()
;*	a = wskip();
;*	if ( a != cr ) return(error);
;*	oldpc = a;

assem	= .
	ldx	#rambs
	stx	*oldpc
	jsr	wskip
	cmpa	#0x0d
	beq	assloop 	; jump if no argument
	jsr	buffarg
	jsr	wskip
	cmpa	#0x0d
	beq	assem1		; jump if argument ok
	ldx	#msga4		; "bad argument"
	jsr	outstrg
	rts
assem1:	ldx	*shftreg
	stx	*oldpc

;*repeat
;*	pc = oldpc;
;*	out2bsp(pc);
;*	disassem();
;*	a=readln();
;*	asscomm = a;	/* save command */
;*	if(a == ('^' or '/')) outcrlf;
;*	if(a == 0) return(error);

assloop:
	ldx	*oldpc
	stx	*pc
	jsr	outcrlf
	ldx	#pc
	jsr	out2bsp		; output the address
	jsr	disassm		; disassemble opcode
	jsr	outcrlf
	jsr	outspac
	jsr	outspac
	jsr	outspac
	jsr	outspac
	ldaa	#prompt		; prompt user
	jsr	outa		; output prompt character
	jsr	readln		; read input for assembly
	staa	*asscomm
	cmpa	#'^
	beq	asslp0		; jump if up arrow
	cmpa	#'/
	beq	asslp0		; jump if slash
	cmpa	#0x00
	bne	asslp1		; jump if none of above
	rts			; return if bad input
asslp0:	jsr	outcrlf
asslp1	= .
	jsr	outspac
	jsr	outspac
	jsr	outspac
	jsr	outspac
	jsr	outspac

;*	b = parse(input); /* get mnemonic */
;*	if(b > 5) print("not found"); asscomm='/';
;*	elseif(b >= 1)
;*	msrch();
;*	if(class==0xff)
;*	print("not found"); asscomm='/';
;*	else
;*	a = doop(opcode,class);
;*	if(a == 0) dispc=0;
;*	else process error; asscomm='/';

	jsr	parse
	cmpb	#0x5
	ble	asslp2		; jump if mnemonic <= 5 chars
	ldx	#msga5		; "mnemonic not found"
	jsr	outstrg
	bra	asslp5
asslp2	= .
	cmpb	#0x0
	beq	asslp10 	; jump if no input
	jsr	msrch
	ldaa	*class
	cmpa	#0xff
	bne	asslp3
	ldx	#msga5		; "mnemonic not found"
	jsr	outstrg
	bra	asslp5
asslp3:	jsr	doop
	cmpa	#0x00
	bne	asslp4		; jump if doop error
	ldx	#0x00
	stx	*dispc		; indicate good assembly
	bra	asslp10
asslp4:	deca			; a = error message index
	tab
	ldx	#msgdir
	abx
	abx
	ldx	0,x
	jsr	outstrg 	; output error message
asslp5:	clr	*asscomm 	; error command

;*	/* compute next address - asscomm holds subcommand
;*	and dispc indicates if valid assembly occured. */
;*  if(asscomm=='^') oldpc -= 1;
;*  if(asscomm==(lf or cr)
;*	if(dispc==0) oldpc=pc;
;*	else
;*	if(asscomm==lf) dispc=oldpc+1;
;*	oldpc=dispc;
;*until(eot)


asslp10	= .
	ldaa	*asscomm
	cmpa	#'^
	bne	asslp11		; jump if not up arrow
	ldx	*oldpc
	dex
	stx	*oldpc		; back up
	bra	asslp15
asslp11:
	cmpa	#0x0a
	beq	asslp12		; jump if linefeed
	cmpa	#0x0d
	bne	asslp15		; jump if not cr
asslp12:
	ldx	*dispc
	bne	asslp13		; jump if dispc != 0
	ldx	*pc
	stx	*oldpc
	bra	asslp15
asslp13:
	cmpa	#0x0a
	bne	asslp14		; jump if not linefeed
	ldx	*oldpc
	inx
	stx	*dispc
asslp14:
	ldx	*dispc
	stx	*oldpc
asslp15:
	jmp	assloop

;****************
;*	readln() --- read input from terminal into buffer
;* until a command character is read (cr,lf,/,^).
;* if more chars are typed than the buffer will hold,
;* the extra characters are overwritten on the end.
;*  on exit: b=number of chars read, a=0 if quit,
;* else a=next command.
;****************
;*for(b==0;b<=bufflng;b++) inbuff[b] = cr;

readln:	clrb
	ldaa	#0x0d		; carriage ret
rln0:	ldx	#inbuff
	abx
	staa	0,x		; initialize input buffer
	incb
	cmpb	#bufflng
	blt	rln0
;*b=0;
;*repeat
;*	if(a == (ctla, cntlc, cntld, cntlx, del))
;*	return(a=0);
;*  if(a == backspace)
;*	if(b > 0) b--;
;*	else b=0;
;*  else  inbuff[b] = upcase(a);
;*  if(b < bufflng) b++;
;*until (a == (cr,lf,^,/))
;*return(a);

	clrb
rln1:	jsr	inchar
	cmpa	#del		; delete
	beq	rlnquit
	cmpa	#ctlx		; control x
	beq	rlnquit
	cmpa	#ctla		; control a
	beq	rlnquit
	cmpa	#0x03		; control c
	beq	rlnquit
	cmpa	#0x04		; control d
	beq	rlnquit
	cmpa	#0x08		; backspace
	bne	rln2
	decb
	bgt	rln1
	bra	readln		; start over
rln2:	ldx	#inbuff
	abx
	jsr	upcase
	staa	0,x		; put char in buffer
	cmpb	#bufflng	; max buffer length
	bge	rln3		; jump if buffer full
	incb			; move buffer pointer
rln3:	jsr	asschek 	; check for subcommand
	bne	rln1
	rts
rlnquit:
	clra			; quit
	rts			; return


;**********
;*	parse() -parse out the mnemonic from inbuff
;* to combuff. on exit: b=number of chars parsed.
;**********
;*combuff[3] = <space>;	initialize 4th character to space.
;*ptrbuff[] = inbuff[];
;*a=wskip();
;*for (b = 0; b = 5; b++)
;*	a=readbuff(); incbuff();
;*	if (a = (cr,lf,^,/,wspace)) return(b);
;*	combuff[b] = upcase(a);
;*return(b);

parse:	ldaa	#0x20
	staa	*combuff+3
	ldx	#inbuff		; initialize buffer ptr
	stx	*ptr0
	jsr	wskip		; find first character
	clrb
parslp:	jsr	readbuff	; read character
	jsr	incbuff
	jsr	wchek
	beq	parsrt		; jump if whitespace
	jsr	asschek
	beq	parsrt		; jump if end of line
	jsr	upcase		; convert to upper case
	ldx	#combuff
	abx
	staa	0,x		; store in combuff
	incb
	cmpb	#0x5
	ble	parslp		; loop 6 times
parsrt:	rts


;****************
;*	asschek() -perform compares for
;* cr, lf, ^, /
;****************
asschek:
	cmpa	#0x0a		; linefeed
	beq	asschk1
	cmpa	#0x0d		; carriage ret
	beq	asschk1
	cmpa	#'^		; up arrow
	beq	asschk1
	cmpa	#'/		; slash
asschk1:
	rts


;*********
;*	msrch() --- search mnetabl for mnemonic in combuff.
;*stores base opcode at baseop and class at class.
;*  class = ff if not found.
;**********
;*while ( != eof )
;*	if (combuff[0-3] = mnetabl[0-3])
;*	return(mnetabl[4],mnetabl[5]);
;*	else *mnetabl =+ 6

msrch:	ldx	#mnetabl	; pointer to mnemonic table
	ldy	#combuff	; pointer to string
	bra	msrch1
msnext	= .
	ldab	#6
	abx			; point to next table entry
msrch1:	ldaa	0,x		; read table
	cmpa	#eot
	bne	msrch2		; jump if not end of table
	ldaa	#0xff
	staa	*class		; ff = not in table
	rts
msrch2:	cmpa	0,y		; op[0] = tabl[0] ?
	bne	msnext
	ldaa	1,x
	cmpa	1,y		; op[1] = tabl[1] ?
	bne	msnext
	ldaa	2,x
	cmpa	2,y		; op[2] = tabl[2] ?
	bne	msnext
	ldaa	3,x
	cmpa	3,y		; op[2] = tabl[2] ?
	bne	msnext
	ldd	4,x		; opcode, class
	staa	*baseop
	stab	*class
	rts

;**********
;**	doop(baseop,class) --- process mnemonic.
;**	on exit: a=error code corresponding to error
;**					messages.
;**********
;*amode = other; /* addressing mode */
;*yflag = 0;	/* ynoimm, nlimm, and cpd flag */
;*x[] = ptrbuff[]

doop	= .
	ldaa	#other
	staa	*amode		; mode
	clr	*yflag
	ldx	*ptr0

;*while (*x != end of buffer)
;*	if (x[0]++ == ',')
;*	if (x[0] == 'y') amode = indy;
;*	else amod = indx;
;*	break;
;*a = wskip()
;*if( a == '#' ) amode = immed;

doplp1:	cpx	#endbuff	; (end of buffer)
	beq	doop1		; jump if end of buffer
	ldd	0,x		; read 2 chars from buffer
	inx			; move pointer
	cmpa	#',
	bne	doplp1
	cmpb	#'Y		; look for ",y"
	bne	doplp2
	ldaa	#indy
	staa	*amode
	bra	doop1
doplp2:	cmpb	#'X		; look for ",x"
	bne	doop1		; jump if not x
	ldaa	#indx
	staa	*amode
	bra	doop1
doop1:	jsr	wskip
	cmpa	#'#		; look for immediate mode
	bne	doop2
	jsr	incbuff 	; point at argument
	ldaa	#immed
	staa	*amode
doop2	= .

;*switch(class)
	ldab	*class
	cmpb	#p2inh
	bne	dosw1
	jmp	dop2i
dosw1:	cmpb	#inh
	bne	dosw2
	jmp	doinh
dosw2:	cmpb	#rel
	bne	dosw3
	jmp	dorel
dosw3:	cmpb	#limm
	bne	dosw4
	jmp	dolim
dosw4:	cmpb	#nimm
	bne	dosw5
	jmp	donoi
dosw5:	cmpb	#gen
	bne	dosw6
	jmp	dogene
dosw6:	cmpb	#grp2
	bne	dosw7
	jmp	dogrp
dosw7:	cmpb	#cpd
	bne	dosw8
	jmp	docpd
dosw8:	cmpb	#xnimm
	bne	dosw9
	jmp	doxnoi
dosw9:	cmpb	#xlimm
	bne	dosw10
	jmp	doxli
dosw10:	cmpb	#ynimm
	bne	dosw11
	jmp	doynoi
dosw11:	cmpb	#ylimm
	bne	dosw12
	jmp	doyli
dosw12:	cmpb	#btb
	bne	dosw13
	jmp	dobtb
dosw13:	cmpb	#setclr
	bne	dodef
	jmp	doset

;*	default: return("error in mnemonic table");

dodef:	ldaa	#0x2
	rts

;*  case p2inh: emit(page2)

dop2i:	ldaa	#page2
	jsr	emit

;*  case inh: emit(baseop);
;*	return(0);

doinh:	ldaa	*baseop
	jsr	emit
	clra
	rts

;*  case rel: a = assarg();
;*		if(a=4) return(a);
;*		d = address - pc + 2;
;*		if (0x7f >= d >= 0xff82)
;*		return (out of range);
;*		emit(opcode);
;*		emit(offset);
;*		return(0);

dorel:	jsr	assarg
	cmpa	#0x04
	bne	dorel1		; jump if arg ok
	rts
dorel1:	ldd	*shftreg 	; get branch address
	ldx	*pc		; get program counter
	inx
	inx			; point to end of opcode
	stx	*braddr
	subd	*braddr		; calculate offset
	std	*braddr		; save result
	cmpd	#0x7f		; in range ?
	bls	dorel2		; jump if in range
	cmpd	#0xff80
	bhs	dorel2		; jump if in range
	ldaa	#0x09		; 'out of range'
	rts
dorel2:	ldaa	*baseop
	jsr	emit		; emit opcode
	ldaa	*braddr+1
	jsr	emit		; emit offset
	clra			; normal return
	rts

;*	case limm: if (amode == immed) amode = limmed;

dolim:	ldaa	*amode
	cmpa	#immed
	bne	donoi
	ldaa	#limmed
	staa	*amode

;*	case nimm: if (amode == immed)
;*		return("immediate mode illegal");

donoi:	ldaa	*amode
	cmpa	#immed
	bne	dogene		; jump if not immediate
	ldaa	#0x1		; "immediate mode illegal"
	rts

;*  case gen: dogen(baseop,amode,page1,page1,page2);
;*		return;

dogene:	ldaa	#page1
	staa	*pnorm
	staa	*px
	ldaa	#page2
	staa	*py
	jsr	dogen
	rts

;*  case grp2: if (amode == indy)
;*		emit(page2);
;*		amode = indx;
;*		if( amode == indx )
;*		doindx(baseop);
;*		else a = assarg();
;*		if(a=4) return(a);
;*		emit(opcode+0x10);
;*		emit(extended address);
;*		return;

dogrp:	ldaa	*amode
	cmpa	#indy
	bne	dogrp1
	ldaa	#page2
	jsr	emit
	ldaa	#indx
	staa	*amode
dogrp1	= .
	ldaa	*amode
	cmpa	#indx
	bne	dogrp2
	jsr	doindex
	rts
dogrp2	= .
	ldaa	*baseop
	adda	#0x10
	jsr	emit
	jsr	assarg
	cmpa	#0x04
	beq	dogrprt 	; jump if bad arg
	ldd	*shftreg 	; extended address
	jsr	emit
	tba
	jsr	emit
	clra
dogrprt:
	rts

;*  case cpd: if (amode == immed)
;*		amode = limmed; /* cpd */
;*		if( amode == indy ) yflag = 1;
;*		dogen(baseop,amode,page3,page3,page4);
;*		return;

docpd:	ldaa	*amode
	cmpa	#immed
	bne	docpd1
	ldaa	#limmed
	staa	*amode
docpd1:	ldaa	*amode
	cmpa	#indy
	bne	docpd2
	inc	*yflag
docpd2:	ldaa	#page3
	staa	*pnorm
	staa	*px
	ldaa	#page4
	staa	*py
	jsr	dogen
	rts

;*	case xnimm: if (amode == immed)	/* stx */
;*			return("immediate mode illegal");

doxnoi:	ldaa	*amode
	cmpa	#immed
	bne	doxli
	ldaa	#0x1		; "immediate mode illegal"
	rts

;*	case xlimm: if (amode == immed)	/* cpx, ldx */
;*			amode = limmed;
;*		dogen(baseop,amode,page1,page1,page4);
;*		return;

doxli:	ldaa	*amode
	cmpa	#immed
	bne	doxli1
	ldaa	#limmed
	staa	*amode
doxli1:	ldaa	#page1
	staa	*pnorm
	staa	*px
	ldaa	#page4
	staa	*py
	jsr	dogen
	rts

;*	case ynimm: if (amode == immed)	/* sty */
;*			return("immediate mode illegal");

doynoi:	ldaa	*amode
	cmpa	#immed
	bne	doyli
	ldaa	#0x1		; "immediate mode illegal"
	rts

;*	case ylimm: if (amode == indy) yflag = 1;/* cpy, ldy */
;*		if(amode == immed) amode = limmed;
;*		dogen(opcode,amode,page2,page3,page2);
;*		return;

doyli:	ldaa	*amode
	cmpa	#indy
	bne	doyli1
	inc	*yflag
doyli1:	cmpa	#immed
	bne	doyli2
	ldaa	#limmed
	staa	*amode
doyli2:	ldaa	#page2
	staa	*pnorm
	staa	*py
	ldaa	#page3
	staa	*px
	jsr	dogen
	rts

;*	case btb:		/* bset, bclr */
;*	case setclr: a = bitop(baseop,amode,class);
;*		if(a=0) return(a = 3);
;*		if( amode == indy )
;*			emit(page2);
;*			amode = indx;

dobtb	= .
doset:	jsr	bitop
	cmpa	#0x00
	bne	doset1
	ldaa	#0x3		; "illegal bit op"
	rts
doset1:	ldaa	*amode
	cmpa	#indy
	bne	doset2
	ldaa	#page2
	jsr	emit
	ldaa	#indx
	staa	*amode
doset2	= .

;*		emit(baseop);
;*		a = assarg();
;*		if(a = 4) return(a);
;*		emit(index offset);
;*		if( amode == indx )
;*			buffptr += 2;	/* skip ,x or ,y */

	ldaa	*baseop
	jsr	emit
	jsr	assarg
	cmpa	#0x04
	bne	doset22		; jump if arg ok
	rts
doset22:
	ldaa	*shftreg+1	; index offset
	jsr	emit
	ldaa	*amode
	cmpa	#indx
	bne	doset3
	jsr	incbuff
	jsr	incbuff
doset3	= .

;*		a = assarg();
;*		if(a = 4) return(a);
;*		emit(mask);	/* mask */
;*		if( class == setclr )
;*			return;

	jsr	assarg
	cmpa	#0x04
	bne	doset33		; jump if arg ok
	rts
doset33:
	ldaa	*shftreg+1	; mask
	jsr	emit
	ldaa	*class
	cmpa	#setclr
	bne	doset4
	clra
	rts
doset4	= .

;*		a = assarg();
;*		if(a = 4) return(a);
;*		d = (pc+1) - shftreg;
;*		if (0x7f >= d >= 0xff82)
;*			return (out of range);
;*		emit(branch offset);
;*		return(0);

	jsr	assarg
	cmpa	#0x04
	bne	doset5		; jump if arg ok
	rts
doset5:	ldx	*pc 		; program counter
	inx			; point to next inst
	stx	*braddr		; save pc value
	ldd	*shftreg		; get branch address
	subd	*braddr		; calculate offset
	cmpd	#0x7f
	bls	doset6		; jump if in range
	cmpd	#0xff80
	bhs	doset6		; jump if in range
	clra
	jsr	emit
	ldaa	#0x09		; 'out of range'
	rts
doset6:	tba			; offset
	jsr	emit
	clra
	rts


;**********
;**	bitop(baseop,amode,class) --- adjust opcode on bit
;**	manipulation instructions.  returns opcode in a
;**	or a = 0 if error
;**********
;*if( amode == indx || amode == indy ) return(op);
;*if( class == setclr ) return(op-8);
;*else if(class==btb) return(op-12);
;*else fatal("bitop");

bitop	= .
	ldaa	*amode
	ldab	*class
	cmpa	#indx
	bne	bitop1
	rts
bitop1:	cmpa	#indy
	bne	bitop2		; jump not indexed
	rts
bitop2:	cmpb	#setclr
	bne	bitop3		; jump not bset,bclr
	ldaa	*baseop		; get opcode
	suba	#8
	staa	*baseop
	rts
bitop3:	cmpb	#btb
	bne	bitop4		; jump not bit branch
	ldaa	*baseop		; get opcode
	suba	#12
	staa	*baseop
	rts
bitop4:	clra			; 0 = fatal bitop
	rts

;**********
;**	dogen(baseop,mode,pnorm,px,py) - process
;** general addressing modes. returns a = error	#.
;**********
;*pnorm = page for normal addressing modes: imm,dir,ext
;*px = page for indx addressing
;*py = page for indy addressing
;*switch(amode)
dogen:	ldaa	*amode
	cmpa	#limmed
	beq	doglim
	cmpa	#immed
	beq	dogimm
	cmpa	#indy
	beq	dogindy
	cmpa	#indx
	beq	dogindx
	cmpa	#other
	beq	dogoth

;*default: error("unknown addressing mode");

dogdef:	ldaa	#0x06		; unknown addre...
	rts

;*case limmed: epage(pnorm);
;*		emit(baseop);
;*		a = assarg();
;*		if(a = 4) return(a);
;*		emit(2 bytes);
;*		return(0);

doglim:	ldaa	*pnorm
	jsr	epage
doglim1:
	ldaa	*baseop
	jsr	emit
	jsr	assarg		; get next argument
	cmpa	#0x04
	bne	doglim2		; jump if arg ok
	rts
doglim2:
	ldd	*shftreg
	jsr	emit
	tba
	jsr	emit
	clra
	rts

;*case immed: epage(pnorm);
;*		emit(baseop);
;*		a = assarg();
;*		if(a = 4) return(a);
;*		emit(lobyte);
;*		return(0);

dogimm:	ldaa	*pnorm
	jsr	epage
	ldaa	*baseop
	jsr	emit
	jsr	assarg
	cmpa	#0x04
	bne	dogimm1		; jump if arg ok
	rts
dogimm1:
	ldaa	*shftreg+1
	jsr	emit
	clra
	rts

;*case indy: epage(py);
;*		a=doindex(op+0x20);
;*		return(a);

dogindy:
	ldaa	*py
	jsr	epage
	ldaa	*baseop
	adda	#0x20
	staa	*baseop
	jsr	doindex
	rts

;*case indx: epage(px);
;*		a=doindex(op+0x20);
;*		return(a);

dogindx:
	ldaa	*px
	jsr	epage
	ldaa	*baseop
	adda	#0x20
	staa	*baseop
	jsr	doindex
	rts

;*case other: a = assarg();
;*		if(a = 4) return(a);
;*		epage(pnorm);
;*		if(countu1 <= 2 digits)	/* direct */
;*		emit(op+0x10);
;*		emit(lobyte(result));
;*		return(0);
;*		else	emit(op+0x30);	/* extended */
;*		eword(result);
;*		return(0)

dogoth:	jsr	assarg
	cmpa	#0x04
	bne	dogoth0		; jump if arg ok
	rts
dogoth0:
	ldaa	*pnorm
	jsr	epage
	ldaa	*count
	cmpa	#0x2
	bgt	dogoth1
	ldaa	*baseop
	adda	#0x10		; direct mode opcode
	jsr	emit
	ldaa	*shftreg+1
	jsr	emit
	clra
	rts
dogoth1:
	ldaa	*baseop
	adda	#0x30		; extended mode opcode
	jsr	emit
	ldd	*shftreg
	jsr	emit
	tba
	jsr	emit
	clra
	rts

;**********
;**	doindex(op) --- handle all wierd stuff for
;**	indexed addressing. returns a = error number.
;**********
;*emit(baseop);
;*a=assarg();
;*if(a = 4) return(a);
;*if( a != ',' ) return("syntax");
;*buffptr++
;*a=readbuff()
;*if( a != 'x' && != 'y') warn("ind addr assumed");
;*emit(lobyte);
;*return(0);

doindex:
	ldaa	*baseop
	jsr	emit
	jsr	assarg
	cmpa	#0x04
	bne	doindx0		; jump if arg ok
	rts
doindx0:
	cmpa	#',
	beq	doindx1
	ldaa	#0x08		; "syntax error"
	rts
doindx1:
	jsr	incbuff
	jsr	readbuff
	cmpa	#'Y
	beq	doindx2
	cmpa	#'X
	beq	doindx2
	ldx	msga7		; "index addr assumed"
	jsr	outstrg
doindx2:
	ldaa	*shftreg+1
	jsr	emit
	clra
	rts

;**********
;**	assarg(); - get argument.	returns a = 4 if bad
;** argument, else a = first non hex char.
;**********
;*a = buffarg()
;*if(asschk(aa) && countu1 != 0) return(a);
;*return(bad argument);

assarg:	jsr	buffarg
	jsr	asschek		; check for command
	beq	assarg1		; jump if ok
	jsr	wchek		; check for whitespace
	bne	assarg2		; jump if not ok
assarg1:
	tst	*count
	beq	assarg2		; jump if no argument
	rts
assarg2:
	ldaa	#0x04		; bad argument
	rts

;**********
;**  epage(a) --- emit page prebyte
;**********
;*if( a != page1 ) emit(a);

epage:	cmpa	#page1
	beq	epagrt		; jump if page 1
	jsr	emit
epagrt:	rts

;**********
;*	emit(a) --- emit contents of a
;**********
emit:	ldx	*pc
	staa	0,x
	jsr	out1bsp
	stx	*pc
	rts

;*mnemonic table for hc11 line assembler
null	=	0x0		; nothing
inh	=	0x1		; inherent
p2inh	=	0x2		; page 2 inherent
gen	=	0x3		; general addressing
grp2	=	0x4		; group 2
rel	=	0x5		; relative
imm	=	0x6		; immediate
nimm	=	0x7		; general except for immediate
limm	=	0x8		; 2 byte immediate
xlimm	=	0x9		; longimm for x
xnimm	=	0x10		; no immediate for x
ylimm	=	0x11		; longimm for y
ynimm	=	0x12		; no immediate for y
btb	=	0x13		; bit test and branch
setclr	=	0x14		; bit set or clear
cpd	=	0x15		; compare d
btbd	=	0x16		; bit test and branch direct
setclrd	=	0x17		; bit set or clear direct

;**********
;*	mnetabl - includes all '11 mnemonics, base opcodes,
;* and type of instruction.  the assembler search routine
;*depends on 4 characters for each mnemonic so that 3 char
;*mnemonics are extended with a space and 5 char mnemonics
;*are truncated.
;**********

mnetabl	= .
	.ascii	'ABA '		; mnemonic
	.byte	0x1b		; base opcode
	.byte	inh		; class
	.ascii	'ABX '
	.byte	0x3a
	.byte	inh
	.ascii	'ABY '
	.byte	0x3a
	.byte	p2inh
	.ascii	'ADCA'
	.byte	0x89
	.byte	gen
	.ascii	'ADCB'
	.byte	0xc9
	.byte	gen
	.ascii	'ADDA'
	.byte	0x8b
	.byte	gen
	.ascii	'ADDB'
	.byte	0xcb
	.byte	gen
	.ascii	'ADDD'
	.byte	0xc3
	.byte	limm
	.ascii	'ANDA'
	.byte	0x84
	.byte	gen
	.ascii	'ANDB'
	.byte	0xc4
	.byte	gen
	.ascii	'ASL '
	.byte	0x68
	.byte	grp2
	.ascii	'ASLA'
	.byte	0x48
	.byte	inh
	.ascii	'ASLB'
	.byte	0x58
	.byte	inh
	.ascii	'ASLD'
	.byte	0x05
	.byte	inh
	.ascii	'ASR '
	.byte	0x67
	.byte	grp2
	.ascii	'ASRA'
	.byte	0x47
	.byte	inh
	.ascii	'ASRB'
	.byte	0x57
	.byte	inh
	.ascii	'BCC '
	.byte	0x24
	.byte	rel
	.ascii	'BCLR'
	.byte	0x1d
	.byte	setclr
	.ascii	'BCS '
	.byte	0x25
	.byte	rel
	.ascii	'BEQ '
	.byte	0x27
	.byte	rel
	.ascii	'BGE '
	.byte	0x2c
	.byte	rel
	.ascii	'BGT '
	.byte	0x2e
	.byte	rel
	.ascii	'BHI '
	.byte	0x22
	.byte	rel
	.ascii	'BHS '
	.byte	0x24
	.byte	rel
	.ascii	'BITA'
	.byte	0x85
	.byte	gen
	.ascii	'BITB'
	.byte	0xc5
	.byte	gen
	.ascii	'BLE '
	.byte	0x2f
	.byte	rel
	.ascii	'BLO '
	.byte	0x25
	.byte	rel
	.ascii	'BLS '
	.byte	0x23
	.byte	rel
	.ascii	'BLT '
	.byte	0x2d
	.byte	rel
	.ascii	'BMI '
	.byte	0x2b
	.byte	rel
	.ascii	'BNE '
	.byte	0x26
	.byte	rel
	.ascii	'BPL '
	.byte	0x2a
	.byte	rel
	.ascii	'BRA '
	.byte	0x20
	.byte	rel
	.ascii	'BRCL'		; (brclr)
	.byte	0x1f
	.byte	btb
	.ascii	'BRN '
	.byte	0x21
	.byte	rel
	.ascii	'BRSE'		; (brset)
	.byte	0x1e
	.byte	btb
	.ascii	'BSET'
	.byte	0x1c
	.byte	setclr
	.ascii	'BSR '
	.byte	0x8d
	.byte	rel
	.ascii	'BVC '
	.byte	0x28
	.byte	rel
	.ascii	'BVS '
	.byte	0x29
	.byte	rel
	.ascii	'CBA '
	.byte	0x11
	.byte	inh
	.ascii	'CLC '
	.byte	0x0c
	.byte	inh
	.ascii	'CLI '
	.byte	0x0e
	.byte	inh
	.ascii	'CLR '
	.byte	0x6f
	.byte	grp2
	.ascii	'CLRA'
	.byte	0x4f
	.byte	inh
	.ascii	'CLRB'
	.byte	0x5f
	.byte	inh
	.ascii	'CLV '
	.byte	0x0a
	.byte	inh
	.ascii	'CMPA'
	.byte	0x81
	.byte	gen
	.ascii	'CMPB'
	.byte	0xc1
	.byte	gen
	.ascii	'COM '
	.byte	0x63
	.byte	grp2
	.ascii	'COMA'
	.byte	0x43
	.byte	inh
	.ascii	'COMB'
	.byte	0x53
	.byte	inh
	.ascii	'CPD '
	.byte	0x83
	.byte	cpd
	.ascii	'CPX '
	.byte	0x8c
	.byte	xlimm
	.ascii	'CPY '
	.byte	0x8c
	.byte	ylimm
	.ascii	'DAA '
	.byte	0x19
	.byte	inh
	.ascii	'DEC '
	.byte	0x6a
	.byte	grp2
	.ascii	'DECA'
	.byte	0x4a
	.byte	inh
	.ascii	'DECB'
	.byte	0x5a
	.byte	inh
	.ascii	'DES '
	.byte	0x34
	.byte	inh
	.ascii	'DEX '
	.byte	0x09
	.byte	inh
	.ascii	'DEY '
	.byte	0x09
	.byte	p2inh
	.ascii	'EORA'
	.byte	0x88
	.byte	gen
	.ascii	'EORB'
	.byte	0xc8
	.byte	gen
	.ascii	'FDIV'
	.byte	0x03
	.byte	inh
	.ascii	'IDIV'
	.byte	0x02
	.byte	inh
	.ascii	'INC '
	.byte	0x6c
	.byte	grp2
	.ascii	'INCA'
	.byte	0x4c
	.byte	inh
	.ascii	'INCB'
	.byte	0x5c
	.byte	inh
	.ascii	'INS '
	.byte	0x31
	.byte	inh
	.ascii	'INX '
	.byte	0x08
	.byte	inh
	.ascii	'INY '
	.byte	0x08
	.byte	p2inh
	.ascii	'JMP '
	.byte	0x6e
	.byte	grp2
	.ascii	'JSR '
	.byte	0x8d
	.byte	nimm
	.ascii	'LDAA'
	.byte	0x86
	.byte	gen
	.ascii	'LDAB'
	.byte	0xc6
	.byte	gen
	.ascii	'LDD '
	.byte	0xcc
	.byte	limm
	.ascii	'LDS '
	.byte	0x8e
	.byte	limm
	.ascii	'LDX '
	.byte	0xce
	.byte	xlimm
	.ascii	'LDY '
	.byte	0xce
	.byte	ylimm
	.ascii	'LSL '
	.byte	0x68
	.byte	grp2
	.ascii	'LSLA'
	.byte	0x48
	.byte	inh
	.ascii	'LSLB'
	.byte	0x58
	.byte	inh
	.ascii	'LSLD'
	.byte	0x05
	.byte	inh
	.ascii	'LSR '
	.byte	0x64
	.byte	grp2
	.ascii	'LSRA'
	.byte	0x44
	.byte	inh
	.ascii	'LSRB'
	.byte	0x54
	.byte	inh
	.ascii	'LSRD'
	.byte	0x04
	.byte	inh
	.ascii	'MUL '
	.byte	0x3d
	.byte	inh
	.ascii	'NEG '
	.byte	0x60
	.byte	grp2
	.ascii	'NEGA'
	.byte	0x40
	.byte	inh
	.ascii	'NEGB'
	.byte	0x50
	.byte	inh
	.ascii	'NOP '
	.byte	0x01
	.byte	inh
	.ascii	'ORAA'
	.byte	0x8a
	.byte	gen
	.ascii	'ORAB'
	.byte	0xca
	.byte	gen
	.ascii	'PSHA'
	.byte	0x36
	.byte	inh
	.ascii	'PSHB'
	.byte	0x37
	.byte	inh
	.ascii	'PSHX'
	.byte	0x3c
	.byte	inh
	.ascii	'PSHY'
	.byte	0x3c
	.byte	p2inh
	.ascii	'PULA'
	.byte	0x32
	.byte	inh
	.ascii	'PULB'
	.byte	0x33
	.byte	inh
	.ascii	'PULX'
	.byte	0x38
	.byte	inh
	.ascii	'PULY'
	.byte	0x38
	.byte	p2inh
	.ascii	'ROL '
	.byte	0x69
	.byte	grp2
	.ascii	'ROLA'
	.byte	0x49
	.byte	inh
	.ascii	'ROLB'
	.byte	0x59
	.byte	inh
	.ascii	'ROR '
	.byte	0x66
	.byte	grp2
	.ascii	'RORA'
	.byte	0x46
	.byte	inh
	.ascii	'RORB'
	.byte	0x56
	.byte	inh
	.ascii	'RTI '
	.byte	0x3b
	.byte	inh
	.ascii	'RTS '
	.byte	0x39
	.byte	inh
	.ascii	'SBA '
	.byte	0x10
	.byte	inh
	.ascii	'SBCA'
	.byte	0x82
	.byte	gen
	.ascii	'SBCB'
	.byte	0xc2
	.byte	gen
	.ascii	'SEC '
	.byte	0x0d
	.byte	inh
	.ascii	'SEI '
	.byte	0x0f
	.byte	inh
	.ascii	'SEV '
	.byte	0x0b
	.byte	inh
	.ascii	'STAA'
	.byte	0x87
	.byte	nimm
	.ascii	'STAB'
	.byte	0xc7
	.byte	nimm
	.ascii	'STD '
	.byte	0xcd
	.byte	nimm
	.ascii	'STOP'
	.byte	0xcf
	.byte	inh
	.ascii	'STS '
	.byte	0x8f
	.byte	nimm
	.ascii	'STX '
	.byte	0xcf
	.byte	xnimm
	.ascii	'STY '
	.byte	0xcf
	.byte	ynimm
	.ascii	'SUBA'
	.byte	0x80
	.byte	gen
	.ascii	'SUBB'
	.byte	0xc0
	.byte	gen
	.ascii	'SUBD'
	.byte	0x83
	.byte	limm
	.ascii	'SWI '
	.byte	0x3f
	.byte	inh
	.ascii	'TAB '
	.byte	0x16
	.byte	inh
	.ascii	'TAP '
	.byte	0x06
	.byte	inh
	.ascii	'TBA '
	.byte	0x17
	.byte	inh
	.ascii	'TPA '
	.byte	0x07
	.byte	inh
	.ascii	'TEST'
	.byte	0x00
	.byte	inh
	.ascii	'TST '
	.byte	0x6d
	.byte	grp2
	.ascii	'TSTA'
	.byte	0x4d
	.byte	inh
	.ascii	'TSTB'
	.byte	0x5d
	.byte	inh
	.ascii	'TSX '
	.byte	0x30
	.byte	inh
	.ascii	'TSY '
	.byte	0x30
	.byte	p2inh
	.ascii	'TXS '
	.byte	0x35
	.byte	inh
	.ascii	'TYS '
	.byte	0x35
	.byte	p2inh
	.ascii	'WAI '
	.byte	0x3e
	.byte	inh
	.ascii	'XGDX'
	.byte	0x8f
	.byte	inh
	.ascii	'XGDY'
	.byte	0x8f
	.byte	p2inh
	.ascii	'BRSE'		; bit direct modes for
	.byte	0x12		; disassembler.
	.byte	btbd
	.ascii	'BRCL'
	.byte	0x13
	.byte	btbd
	.ascii	'BSET'
	.byte	0x14
	.byte	setclrd
	.ascii	'BCLR'
	.byte	0x15
	.byte	setclrd
	.byte	eot		; end of table

;**********************************************
pg1	=	0x0
pg2	=	0x1
pg3	=	0x2
pg4	=	0x3

;******************
;*disassem() - disassemble the opcode.
;******************
;*(check for page prebyte)
;*baseop=pc[0];
;*pnorm=pg1;
;*if(baseop==0x18) pnorm=pg2;
;*if(baseop==0x1a) pnorm=pg3;
;*if(baseop==0xcd) pnorm=pg4;
;*if(pnorm != pg1) dispc=pc+1;
;*else dispc=pc; (dispc points to next byte)

disassm	= .
	ldx	*pc 		; address
	ldaa	0,x		; opcode
	ldab	#pg1
	cmpa	#0x18
	beq	disp2		; jump if page2
	cmpa	#0x1a
	beq	disp3		; jump if page3
	cmpa	#0xcd
	bne	disp1		; jump if not page4
disp4:	incb			; set up page value
disp3:	incb
disp2:	incb
	inx
disp1:	stx	*dispc		; point to opcode
	stab	*pnorm		; save page

;*if(opcode == (0x00-0x5f or 0x8d or 0x8f or 0xcf))
;*	if(pnorm == (pg3 or pg4))
;*	disillop(); return();
;*  b=disrch(opcode,null);
;*  if(b==0) disillop(); return();

	ldaa	0,x		; get current opcode
	staa	*baseop
	inx
	stx	*dispc		; point to next byte
	cmpa	#0x5f
	bls	dis1		; jump if in range
	cmpa	#0x8d
	beq	dis1		; jump if bsr
	cmpa	#0x8f
	beq	dis1		; jump if xgdx
	cmpa	#0xcf
	beq	dis1		; jump if stop
	jmp	disgrp		; try next part of map
dis1:	ldab	*pnorm
	cmpb	#pg3
	blo	dis2		; jump if page 1 or 2
	jsr	disillop	; "illegal opcode"
	rts
dis2:	ldab	*baseop		; opcode
	clrb			; class=null
	jsr	disrch
	tstb
	bne	dispec		; jump if opcode found
	jsr	disillop	; "illegal opcode"
	rts

;*	if(opcode==0x8d) dissrch(opcode,rel);
;*	if(opcode==(0x8f or 0xcf)) disrch(opcode,inh);

dispec:	ldaa	*baseop
	cmpa	#0x8d
	bne	dispec1
	ldab	#rel
	bra	dispec3		; look for bsr opcode
dispec1:
	cmpa	#0x8f
	beq	dispec2		; jump if xgdx opcode
	cmpa	#0xcf
	bne	disinh		; jump not stop opcode
dispec2:
	ldab	#inh
dispec3:
	jsr	disrch		; find other entry in table

;*	if(class==inh)		/* inh */
;*	if(pnorm==pg2)
;*	b=disrch(baseop,p2inh);
;*	if(b==0) disillop(); return();
;*	prntmne();
;*	return();

disinh	= .
	ldab	*class
	cmpb	#inh
	bne	disrel		; jump if not inherent
	ldab	*pnorm
	cmpb	#pg1
	beq	disinh1		; jump if page1
	ldaa	*baseop		; get opcode
	ldab	#p2inh		; class=p2inh
	jsr	disrch
	tstb
	bne	disinh1		; jump if found
	jsr	disillop	; "illegal opcode"
	rts
disinh1:
	jsr	prntmne
	rts

;*	elseif(class=rel)		/* rel */
;*	if(pnorm != pg1)
;*	disillop(); return();
;*	prntmne();
;*	disrelad();
;*	return();

disrel	= .
	ldab	*class
	cmpb	#rel
	bne	disbtd
	tst	*pnorm
	beq	disrel1		; jump if page1
	jsr	disillop	; "illegal opcode"
	rts
disrel1:
	jsr	prntmne		; output mnemonic
	jsr	disrelad	; compute relative address
	rts

;*	else		/* setclr,setclrd,btb,btbd */
;*	if(class == (setclrd or btbd))
;*		if(pnorm != pg1)
;*		disillop(); return();	/* illop */
;*		prntmne();		/* direct */
;*		disdir();		/* output 0xbyte */
;*	else (class == (setclr or btb))
;*		prntmne();		/* indexed */
;*		disindx();
;*	outspac();
;*	disdir();
;*	outspac();
;*	if(class == (btb or btbd))
;*		disrelad();
;*	return();

disbtd	= .
	ldab	*class
	cmpb	#setclrd
	beq	disbtd1
	cmpb	#btbd
	bne	disbit		; jump not direct bitop
disbtd1:
	tst	*pnorm
	beq	disbtd2		; jump if page 1
	jsr	disillop
	rts
disbtd2:
	jsr	prntmne
	jsr	disdir		; operand(direct)
	bra	disbit1
disbit	= .
	jsr	prntmne
	jsr	disindx		; operand(indexed)
disbit1:
	jsr	outspac
	jsr	disdir		; mask
	ldab	*class
	cmpb	#btb
	beq	disbit2		; jump if btb
	cmpb	#btbd
	bne	disbit3		; jump if not bit branch
disbit2:
	jsr	disrelad	; relative address
disbit3:
	rts


;*elseif(0x60 <= opcode <= 0x7f)  /*  grp2 */
;*	if(pnorm == (pg3 or pg4))
;*	disillop(); return();
;*	if((pnorm==pg2) and (opcode != 0x6x))
;*	disillop(); return();
;*	b=disrch(baseop & 0x6f,null);
;*	if(b==0) disillop(); return();
;*	prntmne();
;*	if(opcode == 0x6x)
;*	disindx();
;*	else
;*	disext();
;*	return();

disgrp	= .
	cmpa	#0x7f		; a=opcode
	bhi	disnext		; try next part of map
	ldab	*pnorm
	cmpb	#pg3
	blo	disgrp2		; jump if page 1 or 2
	jsr	disillop	; "illegal opcode"
	rts
disgrp2:
	anda	#0x6f		; mask bit 4
	clrb			; class=null
	jsr	disrch
	tstb
	bne	disgrp3		; jump if found
	jsr	disillop	; "illegal opcode"
	rts
disgrp3:
	jsr	prntmne
	ldaa	*baseop		; get opcode
	anda	#0xf0
	cmpa	#0x60
	bne	disgrp4		; jump if not 6x
	jsr	disindx		; operand(indexed)
	rts
disgrp4:
	jsr	disext		; operand(extended)
	rts

;*else	(0x80 <= opcode <= 0xff)
;*	if(opcode == (0x87 or 0xc7))
;*	disillop(); return();
;*	b=disrch(opcode&0xcf,null);
;*	if(b==0) disillop(); return();

disnext	= .
	cmpa	#0x87		; a=opcode
	beq	disnex1
	cmpa	#0xc7
	bne	disnex2
disnex1:
	jsr	disillop	; "illegal opcode"
	rts
disnex2:
	anda	#0xcf
	clrb			; class=null
	jsr	disrch
	tstb
	bne	disnew		; jump if mne found
	jsr	disillop	; "illegal opcode"
	rts

;*	if(opcode&0xcf==0x8d) disrch(baseop,nimm; (jsr)
;*	if(opcode&0xcf==0x8f) disrch(baseop,nimm; (sts)
;*	if(opcode&0xcf==0xcf) disrch(baseop,xnimm; (stx)
;*	if(opcode&0xcf==0x83) disrch(baseop,limm); (subd)

disnew:	ldaa	*baseop
	anda	#0xcf
	cmpa	#0x8d
	bne	disnew1		; jump not jsr
	ldab	#nimm
	bra	disnew4
disnew1:
	cmpa	#0x8f
	bne	disnew2		; jump not sts
	ldab	#nimm
	bra	disnew4
disnew2:
	cmpa	#0xcf
	bne	disnew3		; jump not stx
	ldab	#xnimm
	bra	disnew4
disnew3:
	cmpa	#0x83
	bne	disgen		; jump not subd
	ldab	#limm
disnew4:
	jsr	disrch
	tstb
	bne	disgen		; jump if found
	jsr	disillop	; "illegal opcode"
	rts

;*	if(class == (gen or nimm or limm	))	/* gen,nimm,limm,cpd */
;*	if(opcode&0xcf==0x83)
;*		if(pnorm==(pg3 or pg4)) disrch(opcode#0xcf,cpd)
;*		class=limm;
;*	if((pnorm == (pg2 or pg4) and (opcode != (0xax or 0xex)))
;*		disillop(); return();
;*	disgenrl();
;*	return();

disgen:	ldab	*class		; get class
	cmpb	#gen
	beq	disgen1
	cmpb	#nimm
	beq	disgen1
	cmpb	#limm
	bne	disxln		; jump if other class
disgen1:
	ldaa	*baseop
	anda	#0xcf
	cmpa	#0x83
	bne	disgen3		; jump if not	#0x83
	ldab	*pnorm
	cmpb	#pg3
	blo	disgen3		; jump not pg3 or 4
	ldab	#cpd
	jsr	disrch		; look for cpd mne
	ldab	#limm
	stab	*class		; set class to limm
disgen3:
	ldab	*pnorm
	cmpb	#pg2
	beq	disgen4		; jump if page 2
	cmpb	#pg4
	bne	#disgen5	; jump not page 2 or 4
disgen4:
	ldaa	*baseop
	anda	#0xb0		; mask bits 6,3-0
	cmpa	#0xa0
	beq	disgen5		; jump if 0xax or 0xex
	jsr	disillop	; "illegal opcode"
	rts
disgen5:
	jsr	disgenrl	; process general class
	rts

;*	else	/* xlimm,xnimm,ylimm,ynimm */
;*	if(pnorm==(pg2 or pg3))
;*	if(class==xlimm) disrch(opcode&0xcf,ylimm);
;*	else disrch(opcode&0xcf,ynimm);
;*	if((pnorm == (pg3 or pg4))
;*	if(opcode != (0xax or 0xex))
;*		disillop(); return();
;*	class=limm;
;*	disgen();
;*	return();

disxln:	ldab	*pnorm
	cmpb	#pg2
	beq	disxln1		; jump if page2
	cmpb	#pg3
	bne	disxln4		; jump not page3
disxln1:
	ldaa	*baseop
	anda	#0xcf
	ldab	*class
	cmpb	#xlimm
	bne	disxln2
	ldab	#ylimm
	bra	disxln3		; look for ylimm
disxln2:
	ldab	#ynimm		; look for ynimm
disxln3:
	jsr	disrch
disxln4:
	ldab	*pnorm
	cmpb	#pg3
	blo	disxln5		; jump if page 1 or 2
	ldaa	*baseop		; get opcode
	anda	#0xb0		; mask bits 6,3-0
	cmpa	#0xa0
	beq	disxln5		; jump opcode = 0xax or 0xex
	jsr	disillop	; "illegal opcode"
	rts
disxln5:
	ldab	#limm
	stab	*class
	jsr	disgenrl	; process general class
	rts


;******************
;*disrch(a=opcode,b=class)
;*return b=0 if not found
;*	else mneptr=points to mnemonic
;*	class=class of opcode
;******************
;*x=#mnetabl
;*while(x[0] != eot)
;*	if((opcode==x[4]) && ((class=null) || (class=x[5])))
;*	mneptr=x;
;*	class=x[5];
;*	return(1);
;*	x += 6;
;*return(0);	/* not found */

disrch	= .
	ldx	#mnetabl	; point to top of table
disrch1:
	cmpa	4,x		; test opcode
	bne	disrch3		; jump not this entry
	tstb
	beq	disrch2		; jump if class=null
	cmpb	5,x		; test class
	bne	disrch3		; jump not this entry
disrch2:
	ldab	5,x
	stab	*class
	stx	*mneptr		; return ptr to mnemonic
	incb
	rts			; return found
disrch3:
	pshb			; save class
	ldab	#6
	abx
	ldab	0,x
	cmpb	#eot		; test end of table
	pulb
	bne	disrch1
	clrb
	rts			; return not found

;******************
;*prntmne() - output the mnemonic pointed
;*at by mneptr.
;******************
;*outa(mneptr[0-3]);
;*outspac;
;*return();

prntmne	= .
	ldx	*mneptr
	ldaa	0,x
	jsr	outa		; output char1
	ldaa	1,x
	jsr	outa		; output char2
	ldaa	2,x
	jsr	outa		; output char3
	ldaa	3,x
	jsr	outa		; output char4
	jsr	outspac
	rts

;******************
;*disindx() - process indexed mode
;******************
;*disdir();
;*outa(',');
;*if(pnorm == (pg2 or pg4)) outa('y');
;*else outa('x');
;*return();

disindx	= .
	jsr	disdir		; output 0xbyte
	ldaa	#',
	jsr	outa		; output ,
	ldab	*pnorm
	cmpb	#pg2
	beq	disind1		; jump if page2
	cmpb	#pg4
	bne	disind2		; jump if not page4
disind1:
	ldaa	#'Y
	bra disind3
disind2:
	ldaa	#'X
disind3:
	jsr	outa		; output x or y
	rts

;******************
;*disrelad() - compute and output relative address.
;******************
;* braddr = dispc[0] + (dispc++);( 2's comp arith)
;*outa('$');
;*out2bsp(braddr);
;*return();

disrelad	= .
	ldx	*dispc
	ldab	0,x		; get relative offset
	inx
	stx	*dispc
	tstb
	bmi	disrld1		; jump if negative
	abx
	bra	disrld2
disrld1:
	dex
	incb
	bne	disrld1		; subtract
disrld2:
	stx	*braddr		; save address
	jsr	outspac
	ldaa	#'$
	jsr	outa
	ldx	#braddr
	jsr	out2bsp		; output address
	rts


;******************
;*disgenrl() - output data for the general cases which
;*includes immediate, direct, indexed, and extended modes.
;******************
;*prntmne();
;*if(baseop == (0x8x or 0xcx))	/* immediate */
;*	outa('#');
;*	disdir();
;*	if(class == limm)
;*	out1byt(dispc++);
;*elseif(baseop == (0x9x or 0xdx))	/* direct */
;*	disdir();
;*elseif(baseop == (0xax or 0xex)) /* indexed */
;*	disindx();
;*else	(baseop == (0xbx or 0xfx)) /* extended */
;*	disext();
;*return();

disgenrl	= .
	jsr	prntmne		; print mnemonic
	ldaa	*baseop		; get opcode
	anda	#0xb0		; mask bits 6,3-0
	cmpa	#0x80
	bne	disgrl2		; jump if not immed
	ldaa	#'#		; do immediate
	jsr	outa
	jsr	disdir
	ldab	*class
	cmpb	#limm
	beq	disgrl1		; jump class = limm
	rts
disgrl1:
	ldx	*dispc
	jsr	out1byt
	stx	*dispc
	rts
disgrl2:
	cmpa	#0x90
	bne	disgrl3		; jump not direct
	jsr	disdir		; do direct
	rts
disgrl3:
	cmpa	#0xa0
	bne	disgrl4		; jump not indexed
	jsr	disindx		; do extended
	rts
disgrl4:
	jsr	disext		; do extended
	rts

;*****************
;*disdir() - output "$ next byte"
;*****************
disdir	= .
	ldaa	#'$
	jsr	outa
	ldx	*dispc
	jsr	out1byt
	stx	*dispc
	rts

;*****************
;*disext() - output "$ next 2 bytes"
;*****************
disext	= .
	ldaa	#'$
	jsr	outa
	ldx	*dispc
	jsr	out2bsp
	stx	*dispc
	rts


;*****************
;*disillop() - output "illegal opcode"
;*****************
dismsg1:
	.ascii	'ILLOP'
	.byte	eot
disillop	= .
	pshx
	ldx	#dismsg1
	jsr	outstrg0	; no cr
	pulx
	rts

;* equates
jportd	=	0x08
jddrd	=	0x09
jbaud	=	0x2b
jsccr1	=	0x2c
jsccr2	=	0x2d
jscsr	=	0x2e
jscdat	=	0x2f
;*

;************
;*	boot [<addr>] - use sci to talk to an 'hc11 in
;* boot mode.  downloads 256 bytes starting at addr.
;* default addr = 0x2000.
;************

;*get arguments
;*if no args, default 0x2000
boot:	jsr	wskip
	cmpa	#0x0d
	bne	bot1		; jump if arguments
	ldy	#0x2000
	bra	bot2		; go - use default address

;*else get arguments
bot1:	jsr	buffarg
	tst	*count
	beq	boterr		; jump if no address
	jsr	wskip
	ldy	*shftreg	; start address
	cmpa	#0xd
	beq	bot2		; go - use arguments
boterr:	ldx	#msg9		; "bad argument"
	jsr	outstrg
	rts

;*boot routine
bot2:	ldab	#0xff		; control character (0xff -> download)
	jsr	btsub		; set up sci and send control char

;*download 256 byte block
	clrb			; counter
blop:	ldaa	0,y
	staa	jscdat,x	; write to transmitter
	iny
	brclr jscsr,x ,#0x80, .	; wait for tdre
	decb
	bne	blop
	rts

;************************************************
;*subroutine
;*	btsub	- sets up sci and outputs control character
;* on entry, b = control character
;* on exit,  x = 0x1000
;*		a = 0x0c
;***************************

btsub	= .
	ldx	#0x1000		; to use indexed addressing
	ldaa	#0x02
	staa	jportd,x	; drive transmitter line
	staa	jddrd,x		; high
	clr	jsccr2,x	; turn off xmtr and rcvr
	ldaa	#0x22		; baud = /16
	staa	jbaud,x
	ldaa	#0x0c		; turn on xmtr & rcvr
	staa	jsccr2,x
	stab	jscdat,x
	brclr jscsr,x ,#0x80, .	; wait for tdre
	rts

;******************
;*
;*	evbtest - this routine makes it a little easier
;*	on us to test this board.
;*
;******************

evbtest:
	ldaa	#0xff

	staa	0x1000		; write ones to port a

	clr	*autolf		; turn off auto lf
	jsr	hostco		; connect host
	jsr	hostinit	; initialize host

	ldaa	#0x7f
	jsr	hostout		; send delete to altos
	ldaa	#0x0d
	jsr	hostout		; send <cr>
	inc	*autolf		; turn on auto lf
	ldx	#inbuff+5	; point at load message
	stx	*ptr0		; set pointer for load command
	ldy	#msgevb		; point at cat line
loop:	ldaa	0,y		; loop to xfer command line
	cmpa	#04		; into buffalo line buffer
	beq	done		; quit on 0x04
	staa	0,x
	inx			; next character
	iny
	bra	loop
done:	clr	*tmp2		; set load vs. verify
	jsr	load1b		; jmp into middle of load
	lds	#stack		; reset stack
	jmp	0xc0b3		; jump to downloaded code

msgevb:	.ascii	/cat evbtest.out/
	.byte	0x0d
	.byte	0x04

	.org	rombs+0x1fa0
;*** jump table ***
.upcase:jmp	upcase
.wchek:	jmp	wchek
.dchek:	jmp	dchek
.init:	jmp	init
.input:	jmp	input
.output:jmp	output
.outlhl:jmp	outlhlf
.outrhl:jmp	outrhlf
.outa:	jmp	outa
.out1by:jmp	out1byt
.out1bs:jmp	out1bsp
.out2bs:jmp	out2bsp
.outcrl:jmp	outcrlf
.outstr:jmp	outstrg
.outst0:jmp	outstrg0
.inchar:jmp	inchar
.vecint:jmp	vecinit

	.org	rombs+0x1fd6
;*** vectors ***
vsci:	.word	jsci
vspi:	.word	jspi
vpaie:	.word	jpaie
vpao:	.word	jpao
vtof:	.word	jtof
vtoc5:	.word	jtoc5
vtoc4:	.word	jtoc4
vtoc3:	.word	jtoc3
vtoc2:	.word	jtoc2
vtoc1:	.word	jtoc1
vtic3:	.word	jtic3
vtic2:	.word	jtic2
vtic1:	.word	jtic1
vrti:	.word	jrti
virq:	.word	jirq
vxirq:	.word	jxirq
vswi:	.word	jswi
villop:	.word	jillop
vcop:	.word	jcop
vclm:	.word	jclm
vrst:	.word	buffalo

