/*
 * romcmd.s -- AIS/3200 RAMless-Monitor commands
 * copyright(c) American Information Systems Corporation
 *  Dock Williams
 *  February, 1984	updated for System 5.2 July, 1984
 *
 * execute a command
 * the command character will be in the mode register
 * r0,r1,r2 arguments to command
 * r3 restored from mod to have command character
 */


	.globl	_loadmsg
	.globl	_badtxchk
	.globl	_badmemchk
	.globl	_loadaddrmsg
	.globl	_sizemsg

docommand:
	addr	cmddsp,r7
	br	crlf
cmddsp:		
	sprd	mod,r3		/* get command */
	cmpqd	0,r3		/* anything at all? */
	beq	getinpl		/* nope */
	cmpb	SQ:C,r3		/* compare command */
	beq	rmlcmp
	cmpb	SQ:D,r3		/* dump command */
	beq	rmldump
	cmpb	SQ:F,r3		/* fill command */
	beq	rmlfill
	cmpb	SQ:G,r3		/* go command */
	beq	rmlgo
	cmpb	SQ:M,r3		/* move command */
	beq	rmlmove
	cmpb	SQ:I,r3		/* load command */
	beq	rmlload
	cmpb	SQ:X,r3		/* write continuously */
	beq	wrlp
	cmpb	SQ:Y,r3		/* read continuously */
	beq	rdlp
	cmpb	SQ:Z,r3		/* write without reading */
	beq	zap
	cmpb	SQ:?,r3		/* help command */
	beq	rmlhelp
	br	getinpl


/*  */

	/* rmlgo */
	/* start execution at a new address */
	/* r0 new address */
rmlgo:
	jump	0(r0)


	/* rmlmove */
	/* move a block of memory */
	/* r0 source address */
	/* r1 destination address */
	/* r2 count */
rmlmove:
	movb	0(r0),0(r1)	/* move a block of memory */
	addqd	1,r0
	addqd	1,r1
	acbd	-1,r2,rmlmove
	br	getinpl


	/* rmlfill */
	/* write a byte constant to a block of memory */
	/* r0 start address */
	/* r1 count */
	/* r2 byte value constant */
rmlfill:
	movb	r2,0(r0)
	addqd	1,r0
	acbd	-1,r1,rmlfill
	br	getinpl


	/* zap */
	/* write a byte, word, or double without reading */
	/* needed for device registers that do unwanted things  */
	/* if read before written */
	/* r0 address to write  */
	/* r1 value */
	/* r2 size - hex b for byte, hex d for double, and 0 for word */
zap:
	cmpb	r3,0x0d		/* is it a double */
	beq	dwrt
	cmpb	r3,0x0b		/* is it byte */
	beq	bwrt
wwrt:				/* else word write */
	movw	r1,0(r0)
	br	getinpl
bwrt:
	movb	r1,0(r0)	/* byte write */
	br	getinpl
dwrt:
	movd	r1,0(r0)	/* double write */
	br	getinpl

/*  */

	/* rmlcmp */
	/* compare two blocks of memory display any differences */
	/* r0 address two */
	/* r1 address one */
	/* r2 count */
rmlcmp:
	cmpb	0(r0),0(r1)	/* compare a block of memory */
	beq	nbytcmp

	movd	r0,r5
	addr	val2eq,r7
	br	cvprtd
val2eq:
	movb	SQ:=,r5
	addr	valr2,r6
	br	outc
valr2:
	movb	0(r0),r5
	addr	spcout,r7
	br	cvprtb
spcout:
	movb	SPC,r5
	addr	adrr1,r6
	br	outc
adrr1:
	movd	r1,r5
	addr	val1eq,r7
	br	cvprtd
val1eq:
	movb	SQ:=,r5
	addr	valr1,r6
	br	outc
valr1:
	movb	0(r1),r5
	addr	docrlf,r7
	br	cvprtb
docrlf:
	addr	nbytcmp,r7
	br	crlf
nbytcmp:
	addqd	1,r0
	addqd	1,r1
	acbd	-1,r2,rmlcmp
	br	getinpl

/*  */

	/* rmldump */
	/* dump memory - print address and then sixteen bytes */
	/* continue for count bytes */
	/* r0 start address */
	/* r1 count */
rmldump:
	addr	datapr,r7		/* print address */
	movd	r0,r5
	br	cvprt3
datapr:	movd	16,r2			/* number of bytes to print per line */
spc0:	addr	pr3spc,r5		/* print colon, space, space */
	addr	spc1,r7
	br	printm
pr3spc: .byte	SPC,SPC,SPC,0
spc1:	movb	0(r0),r5		/* print a value */
	addr	spc2,r7
	br	cvprtb
spc2:	movb	SPC,r5			/* print a space */
	addr	incr1,r6
	br	outc
incr1:
	addqd	1,r0			/* next address */
	addqd	-1,r1			/* one less to dump */
	cmpqd	0,r1
	bge	ramless_quiet		/* finished yet? */
	acbd	-1,r2,spc1		/* decrement line count */
	addr	rmldump,r7		/* print crlf */
	br	crlf			/* end of current line */

/*  */

	/* rmlenable */
	/* enable and disable ram mapping */
	/* r0 = clear or don't clear value */
rmlenable:
	cmpqb	0,r0			/* if zero turn mapping off */
	beq	mapoff

	/* turn mapping on */
	movb	ROM_MAP,@(UART_MAPENABLE + U_SETOUT)
	br	getout
mapoff:
	/* turn mapping off */
	movb	ROM_MAP,@(UART_MAPENABLE + U_CLROUT)
getout:	br	ramless_quiet


/*  */

	/* rmload */
	/* load data into memory from alternate serial port */
LSYNC:
	.byte	SQ:L,SQ:S,SQ:I,SQ:A	/* Sync characters for UART Loader */
rmlload:
	addr	_loadmsg,r5
	addr    gsync,r7
	br	printm
gsync:
	addr	sychk,r6	/* get sync characters */
	br	inc1
sychk:	movb	r5,r4
	cmpd	LSYNC,r4
	lshd	8,r4
	bne	gsync

	movqd	4,r3		/* get load address */
ldadrlp:
	addr	ldadr,r6
	br	inc1
ldadr:	rotd	8,r0
	movb	r5,r0
	acbd	-1,r3,ldadrlp
	lprd	sb,r0

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	movb	SQ:.,@(UART0+U_ODATA)
#endif /************************* CPU REVISION-2A **********************/

	movqd	4,r3		/* get number of bytes */
numbylp:
	addr	numby,r6
	br	inc1
numby:	rotd	8,r1
	movb	r5,r1
	acbd	-1,r3,numbylp
	lprd	sp,r1

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	movb	SQ:.,@(UART0+U_ODATA)
#endif /************************* CPU REVISION-2A **********************/

	movqd	4,r3		/* get chksum */
chksmlp:
	addr	chksm,r6
	br	inc1
chksm:	rotd	8,r2
	movb	r5,r2
	acbd	-1,r3,chksmlp

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	movb	SQ:.,@(UART0+U_ODATA)
#endif /************************* CPU REVISION-2A **********************/

	movqd	0,r4		/* initialize checksum */
readdat:
	addr	calcu,r6
	br	inc1		/* read data from port 1 */
calcu:
	movzbd	r5,r5		/* only want a byte */
	addd	r5,r4		/* compute checksum */
	movb	r5,0(r0)	/* write data into memory */
	addqd	1,r0		/* next address to write to */
	acbd	-1,r1,readdat	/* decrement number of bytes */

	cmpd	r2,r4		/* verify checksum */
	beq	goodtc		/* good transmission checksum */
badtchk:
	addr	_badtxchk,r5	/* bad checksum */
badchk:
	addr	ramless_quiet,r7	/* restart, after printing message */
	br	printm

badmchk:
	addr	_badmemchk,r5
	br	badchk

goodtc:				/* now checksum data as it is in memory */
	movqd	0,r4		/* initialize checksum */
	sprd	sb,r0		/* start of image */
	sprd	sp,r1		/* size */
mchklp:
	movzbd	0(r0),r5	/* only want a byte */
	addd	r5,r4		/* compute checksum */
	addqd	1,r0		/* next address to check */
	acbd	-1,r1,mchklp	/* decrement number of bytes */
	
	cmpd	r2,r4
	bne	badmchk			/* got a bad checksum */
goodmc:
	addr	_loadaddrmsg,r5		/* print load address message */
	addr	prtaddr,r7
	br	printm
prtaddr:
	sprd	sb,r5			/* print load address value */
	addr	printsize,r7
	br	cvprt3
printsize:
	addr	_sizemsg,r5		/* print size message */
	addr	prtsize,r7
	br	printm
prtsize:
	sprd	sp,r5			/* print size value */
	addr	ramless_quiet,r7	/* return to top level RM */
	br	cvprt3

/*  */

	/* open */
	/* mod,r2 current command type */
	/* fp,r5 current address */
open:
	sprd	mod,r2		/* get open type */
	sprd	fp,r5		/* current address */
	addr	pr1sp,r7
	br	cvprt3		/* print address */
pr1sp:
	movb	SPC,r5		/* print space */
	addr	sizsel,r6
	br	outc
sizsel:
	cmpb	SQ:/,r2
	beq	dvpr		/* print a double value */
	cmpb	SQ:\,r2
	beq	wvpr		/* print a word value */
	cmpb	SQ:`,r2
	beq	bvpr		/* print a byte value */

	/* open double sized location(32-bits), print its value, and */
	/* wait for new contents */
dvpr:
	movd	0(fp),r5	/* get data at current address */
	addr	getdv,r7
	br	cvprtd
getdv:
	movb	SPC,r5
	addr	getv,r6
	br	outc		/* get another value */

	/* open word size locatin(16-bits), print its value, and */
	/* wait for new contents */
wvpr:
	movw	0(fp),r5	/* get data at current address */
	addr	getwv,r7
	br	cvprtw
getwv:
	movb	SPC,r5
	addr	getv,r6
	br	outc		/* get another value */

	/* open byte size locatin(8-bits), print its value, and */
	/* wait for new contents */
bvpr:
	movb	0(fp),r5	/* get data at current address */
	addr	getbv,r7
	br	cvprtb
getbv:
	movb	SPC,r5
	addr	getv,r6
	br	outc		/* get another value */

/*  */

	/* continuously write a location */
wrlp:	addr	wrlp,r7		/* set permanent return location */
	movb	r1,0(r0)
	br	chkesc		/* loop until <ESCAPE> */

	/* continuously read a location */
rdlp:	addr	rdlp,r7		/* set return loop address */
	movb	0(r0),r1
	br	chkesc		/* loop */

	/* continuously write and read a location */
wrrdlp:	addr	wrrdlp,r7	/* set return address */
	movb	r1,0(r0)
	movb	0(r0),r2
				/* fall thru to chkesc */

/*  */
