/* romarg.s -- AIS/3200 RAMless-Monitor main body
 * copyright(c) American Information Systems Corporation
 *  Dock Williams
 *  February, 1984	updated for system 5.2 July, 1984
 *
 *  original idea and code by Franco I.
 *
 *  the ramless monitor uses no ram to perform its functions
 *	only the CPU registers are used in the ramless monitor
 *
 * pattern of register usage:
 *
 * r0-r5:
 *	early in command line processing: input character fifo
 *	an input character is read into r5 as a byte
 *	if it is determined that it was a legal character
 *	the character is echoed and pushed onto the input
 *	character fifo queue, if it was illegal it is ignored.
 *	bytes are ordered in the fifo in the following way:
 *	in registers r5-r1 the most significant byte is
 *	the oldest byte and the least significant byte is
 *	the latest byte to be pushed forward from somewhere
 *	lower in the fifo, r0 is reversed so that the current
 *	byte in r0 is always the top of the fifo
 *	later, after the fifo has been interpreted:
 *	r0-r2 form up to three arguments that were
 *	converted from the input fifo registers that can
 *	be used as input parameters to a command.
 *	r3-r5 are used as temporaries and their use will
 *	change with almost every command, with r5 being
 *	primarily used for io
 *	
 * r6:	return address for single character io
 *	and as a temporary when not doing single
 *	character
 * r7:	general return address
 * fp:	remembered address for open command
 * mod:	remembered last open type
 */
	.file	"raml.s"

#include "promhdr.h"
#include "3200config.h"

	.set	BCKSPC,0x08
	.set	TAB,0x09
	.set	SPC,0x20	
	.set	BELL,0x07
	.set	CR,0x0D
	.set	LF,0x0A
	.set	ESC,0x1B
	.set	CTRL_Q,0x11
	.set	CTRL_S,0x13
	.set	SLASH,0x2f
	.set	BACKSLASH,0x5c
	.set	DEL,0x7F

	.globl	_ramless_monitor
	.globl	ramless_quiet
	.globl	epushc
	.globl	pushc	
	.globl	erase	

/*  */

#define PARENABLES (SBUS_TMOENABLE | SBUS_PARENABLE | HOST_TMOENABLE | HOST_PARENABLE)

_ramless_monitor:
	/* 
	 * turn off
	 *	host bus parity checking,
	 *	host bus timeout,
	 *	system bus parity checking,
	 *	system bus timeout,
	 *	and pick enable
	 */
	movb	$(PARENABLES | PICK_ENABLE), @(UART_PARENABLE + U_CLROUT)

	addr	_RMbootmsg,r5		/* print AIS/3200 Ramless Monitor */
	addr	lab1,r7			/* return address */
	br	printm
lab1:
	addr	_copyright,r5		/* print copyright (c) 1984 */
	addr	lab2,r7			/* return address */
	br	printm
lab2:
	addr	_corporation,r5		/* print American Infor... */
	addr	ramless_quiet,r7	/* return address */
	br	printm

break:
	bpt				/* for debugging with monitor */
	br	_ramless_monitor	/* otherwise this is deadly */


/*  */


ramless_quiet:				/* quiet entry point */

	/* turn off input DTR */
	movb	$DTR1,@(U_CLROUT+UART_MAPENABLE)

	/* disable parity/timeout NMIs */
	movb	$(PARENABLES | PICK_ENABLE), @(UART_PARENABLE + U_CLROUT)

	movqd	$0,r0
	lprw	mod,r0		/* clear, because we're not in open mode */

#ifdef MMU /********************** MMU Available ***********************/
	lmr	msr,r0		/* disable special mmu functions */
#endif /************************** MMU Available ***********************/

	addr	getinpl,r7	/* return address */
	br	crlf		/* print a cr/lf combination */
getinpl:
	bicpsrw	$(PSR_I | PSR_S | PSR_U) /* disable interrupts */
	addr	sprompt,r5
	addr	getv,r7
	br	printm
sprompt:
	.byte	0x52		/* RM> */
	.byte	0x4d
	.byte	0x3e
	.byte	SPC
	.byte	0

getv:
	movqd	$0,r0		/* clear registers */
	movqd	$0,r1
	movqd	$0,r2
	movqd	$0,r3
	movqd	$0,r4
	movqd	$0,r5
	bispsrw	$PSR_S		/* switch to user stack */
	lprd	sp,r0		/* clear user stack pointer */
	bicpsrw	$PSR_S		/* switch back to interrupt stack */

	/* get an input character */
getc:
	addr	chkinc,r6
	br	inc

/*  */

	/* figure out what to do with it */
chkinc:
	cmpb	r5,$TAB
	beq	pushspc
	cmpb	r5,$BCKSPC
	beq	erase
	cmpb	r5,$DEL
	beq	erase
	cmpb	r5,$LF
	beq	openchk
	cmpb	r5,$CR
	beq	openchk
	cmpb	r5,SQ:^
	beq	openchk
	cmpb	r5,SQ:+
	beq	openchk
	cmpb	r5,SQ:-
	beq	openchk
	cmpb	r5,SQ:?
	beq	epushc
	cmpb	r5,SQ:@
	beq	openchk
	cmpb	r5,$SPC
	blt	getc		/* illegal character, ignore */
	beq	epushc
	cmpb	r5,SQ:`
	beq	reopen
	cmpb	r5,$BACKSLASH
	beq	reopen
	cmpb	r5,$SLASH
	beq	reopen
	cmpb	r5,SQ:0
	blt	getc		/* illegal character, ignore */
	cmpb	r5,SQ:9
	ble	epushc
	cmpb	r5,SQ:A
	blt	getc		/* illegal character, ignore */
	cmpb	r5,SQ:Z
	ble	epushc
	br	getc		/* illegal character, ignore */

/*  */

openchk:
	sprd	mod,r6
	cmpb	$SLASH,r6	/* have to be in open mode for ^+-@ to make sense */
	beq	savtype
	cmpb	$BACKSLASH,r6
	beq	savtype
	cmpb	SQ:`,r6
	beq	savtype
	cmpb	SQ:^,r5		/* if not in open mode ^+-@ are errors */
	beq	error
	cmpb	SQ:+,r5
	beq	error
	cmpb	SQ:-,r5
	beq	error
	cmpb	SQ:@,r5
	beq	error

	movd	r5,r6
	movqd	$0,r7		/* shifting amount */
	movqb	$0,r5		/* clear last character */
rechk:
	cmpb	r6,$CR		/* get rid of spaces,tabs, and cr that */
	beq	rshift6		/* may be part of a regular command */
	cmpb	r6,$SPC
	beq	rshift6
	cmpb	r6,$TAB
	beq	rshift6
	cmpqb	$0,r6
	beq	ramless_quiet
	lprd	mod,r6		/* store regular command */
	br	convertinput	/* convert input for regular command */
rshift6:
	lshd	$-8,r6
	addb	$-8,r7		/* icrement shift amount */
	lshd	r7,r5		/* shift out useless byte */
	movqb	$0,r5		/* overwrite it */
	negb	r7,r7		/* shift back to where it was */
	lshd	r7,r5
	negb	r7,r7		/* restore shift to correct sense */
	br	rechk

/*  */

savtype:
	rotd	$-8,r6		/* r6 has remembered current open type */
	movb	r5,r6		/* r5 is current command  */
	rotd	$8,r6
	lprw	mod,r6		/* save for use after conversion */
	cmpb	SQ:^,r5		/* echo this command character */
	beq	echocmd		/* all rest will get echoed later */
	cmpb	SQ:@,r5		/* echo this command character */
	bne	convertinput	/* all rest will get echoed later */
echocmd:
	addr	convertinput,r6	/* echo command character then convert input */
	br	outc

reopen:
	addr	openecho,r6	/* echo open command character */
	br	outc		/* r5 has open command character */
openecho:
	lprd	mod,r5
	rotd	$-8,r5
	cmpqb	$0,r5
	beq	open
	rotd	$8,r5
	br	convertinput	/* must have got an address */

/*  */

	/* for wierd characters */
	/* instead of throwing them away just echo a space */
	/* and push a space onto the input queue */
pushspc:
	movb	$SPC,r5
	br	epushc

	#echo and then push onto the input queue
epushc:
	addr	chkqueue,r6
	br 	boutc
chkqueue: 			/* if next byte to be shifted out */
	cmpqb	$0,r0		/* is zero we have room for one character */
	bne	fifovflow

	/* after pushing this input character go get another */
	addr	getc,r7

	/* push a character onto the input queue */
pushc:	
	rotd	$8,r1
	movb	r1,r0
	rotd	$-8,r0
	rotd	$8,r2
	movb	r2,r1
	rotd	$8,r3
	movb	r3,r2
	rotd	$8,r4
	movb	r4,r3
	rotd	$8,r5
	movb	r5,r4
	jump	0(r7)

/*  */

	/* erase a character from the input queue */
erase:	
	rotd	$-8,r5
	cmpqb	$0,r5		/* check if any characters in fifo */
	rotd	$8,r5
	beq	getc		/* if none, just return */
	
	movb	$BCKSPC,r5	/* print backspace, space, backspace */
	addr	erase1,r6
	br	boutc
erase1:
	movb	$SPC,r5
	addr	backspace,r6
	br	boutc
backspace:
	movb	$BCKSPC,r5
	addr	popc,r6
boutc:	br	outc

popc:				/* remove the last pushed character */
	movb	r4,r5
	rotd	$-8,r5
	movb	r3,r4
	rotd	$-8,r4
	movb	r2,r3
	rotd	$-8,r3
	movb	r1,r2
	rotd	$-8,r2
	movb	r0,r1
	rotd	$-8,r1
	movqb	$0,r0
	rotd	$8,r0
	br	getc

/*  */

	/* get the first argument out of the fifo and put it into r4 */
	/* after fisrt forming it in r6 */

convertinput:
	movqd	$0,r6

	/* move argument characters to head of fifo */
head5:
	cmpqb	$0,r0		/* is top of fifo zero */
	beq	pump5		/* yes, then throw it away */
	cmpb	$SPC,r0
	bne	conv5
pump5:
	movqb	$0,r5

	/* check if the input fifo registers have any characters */
	cmpqd	$0,r0
	bne	gotsome
	cmpqd	$0,r1
	bne	gotsome
	cmpqd	$0,r2
	bne	gotsome
	cmpqd	$0,r3
	bne	gotsome
	cmpqd	$0,r4
	bne	gotsome
	cmpqd	$0,r5
	beq	svinr2		/* no more input */
gotsome:
	addr	head5,r7
	br	pushc
		
conv5:
	movb	r0,r5

	cmpb	r5,SQ:0
	blt	svinr4
	cmpb	r5,SQ:9
	ble	digitcv5
	cmpb	r5,SQ:A
	blt	svinr4
	cmpb	r5,SQ:F
	ble	atoxcv5
	br	svinr4
digitcv5:
	subb	$0x30,r5
	br	shiftd5
atoxcv5:
	subb	$0x37,r5
shiftd5:
	lshd	$4,r6
	orb	r5,r6
	movqb	$0,r5

	/* signify received valid hex char */
	bispsrw	$PSR_S		/* switch to user stack */
	adjspb	$-1		/* increment user stack pointer */
	bicpsrw	$PSR_S		/* switch back to interrupt stack */

	addr	conv5,r7
	br	pushc

/*  */

	/* save first argument in r4 temporarily */
svinr4:
	movd	r6,r4
	movqd	$0,r6

	/* get next arguments characters to head of the fifo */
head4:
	cmpb	$SPC,r0
	bne	conv4
pump4:
	addr	head4,r7
push4c:
	rotd	$8,r1
	movb	r1,r0
	rotd	$-8,r0
	rotd	$8,r2
	movb	r2,r1
	rotd	$8,r3
	movb	r3,r2
	movqb	$0,r3
	jump	0(r7)
conv4:
	movb	r0,r5
	cmpb	r5,SQ:0
	blt	svinr3
	cmpb	r5,SQ:9
	ble	digitcv4
	cmpb	r5,SQ:A
	blt	svinr3
	cmpb	r5,SQ:F
	ble	atoxcv4
	br	svinr3
digitcv4:
	subb	$0x30,r5
	br	shiftd4
atoxcv4:
	subb	$0x37,r5
shiftd4:
	lshd	$4,r6
	orb	r5,r6
	movqb	$0,r5

	addr	conv4,r7
	br	push4c

/*  */

	/* save second argument, convert third */
svinr3:
	movd	r6,r3
	movqd	$0,r6

head3:
	cmpb	$SPC,r0
	bne	conv3
pump3:
	addr	head3,r7
push3c:
	rotd	$8,r1
	movb	r1,r0
	rotd	$-8,r0
	rotd	$8,r2
	movb	r2,r1
	movqb	$0,r2
	jump	0(r7)

conv3:
	movb	r0,r5

	cmpb	r5,SQ:0
	blt	svinr2
	cmpb	r5,SQ:9
	ble	digitcv3
	cmpb	r5,SQ:A
	blt	svinr2
	cmpb	r5,SQ:F
	ble	atoxcv3
	br	svinr2
digitcv3:
	subb	$0x30,r5
	br	shiftd3
atoxcv3:
	subb	$0x37,r5
shiftd3:
	lshd	$4,r6
	orb	r5,r6

	addr	conv3,r7
	br	push3c

/*  */

/* save third argument in r2 and move the arguments from their temporary */
/* places to r0 and r1 respectively to get ready for command execution */
svinr2:
	movd	r6,r2		/* arguemnt 3 */
	movd	r3,r1		/* argument 2 */
	movd	r4,r0		/* argument 1 */

	sprd	mod,r6
	cmpb	$SLASH,r6
	beq	opchk
	cmpb	$BACKSLASH,r6
	beq	opchk
	cmpb	SQ:`,r6
	bne	docommand
opchk:
	rotd	$-8,r6
	cmpb	SQ:+,r6
	beq	forward
	cmpb	SQ:-,r6
	beq	backward
	cmpb	$CR,r6
	beq	wrt
	cmpb	$LF,r6
	beq	nxtwrt
	cmpb	SQ:^,r6
	beq	prevwrt
	cmpb	SQ:@,r6
	beq	movtoloc
	lprd	fp,r0
	br	open

/*  */

	/* move the current location forward by the given input amount */
	/* else just use the default for the current size and move forward */
	/* that amount */
forward:
	movb	r6,r5
	addr	echoforw,r6
	br	outc
echoforw:
	cmpqb	$0,r0
	beq	plusdef
	addr	0(fp),r6
	addd	r0,r6
	lprd	fp,r6
	br	opcrlf

plusdef:
	sprw	mod,r6
	cmpb	$SLASH,r6
	beq	plus4
	cmpb	$BACKSLASH,r6
	beq	plus2
	cmpb	SQ:`,r6
	bne	error
plus1:
	addr	1(fp),r6
	lprd	fp,r6
	br	opcrlf
plus2:
	addr	2(fp),r6
	lprd	fp,r6
	br	opcrlf
plus4:
	addr	4(fp),r6
	lprd	fp,r6
	br	opcrlf

opcrlf:
	addr	open,r7		/* print carriage return - line feed */
	br	crlf		/* and jump to open */

/*  */

	/* move the current location back by the given input amount */
	/* else just backup the default current size  */
backward:
	movb	r6,r5
	addr	echoback,r6
	br	outc
echoback:
	cmpb	$0,r0
	beq	minusdef
	addr	0(fp),r6
	subd	r0,r6
	lprd	fp,r6
	br	opcrlf
minusdef:
	sprw	mod,r6
	cmpb	$SLASH,r6
	beq	minus4
	cmpb	$BACKSLASH,r6
	beq	minus2
	cmpb	SQ:`,r6
	bne	error
minus1:
	addr	-1(fp),r6
	lprd	fp,r6
	br	opcrlf
minus2:
	addr	-2(fp),r6
	lprd	fp,r6
	br	opcrlf
minus4:
	addr	-4(fp),r6
	lprd	fp,r6
	br	opcrlf

/*  */

	/* received a '^', write the current location if received input */
	/* in any case, advance to the previous location by the current size */
prevwrt:
	bispsrw	$PSR_S		/* switch to user stack pointer */
	sprd	sp,r6
	bicpsrw	$PSR_S		/* switch back to interrupt stack pointer */
	cmpqd	$0,r6
	beq	minusdef
	addr	minusdef,r7
	br	wrtaloc

	/* received a LF, write the current location if received input */
	/* in any case, advance to the next location by the current size */
nxtwrt:
	bispsrw	$PSR_S		/* switch to user stack pointer */
	sprd	sp,r6
	bicpsrw	$PSR_S		/* switch back to interrupt stack pointer */
	cmpqd	$0,r6
	beq	plusdef		/* write nothing, just advance pointer */
	addr	plusdef,r7	/* write and advance pointer */
	br	wrtaloc

	/* received a CR, write the location if recieved input */
	/* else just return to top level monitor */
wrt:
	bispsrw	$PSR_S		/* switch to user stack pointer */
	sprd	sp,r6
	bicpsrw	$PSR_S		/* switch back to interrupt stack pointer */
	cmpqd	$0,r6
	beq	ramless_quiet
	addr	ramless_quiet,r7
	br	wrtaloc

/*  */

	/* write a location in memory using the correct current size */
wrtaloc:
	sprd	mod,r6		/* get current open type */
	cmpb	$SLASH,r6
	beq	wrtdouble
	cmpb	$BACKSLASH,r6
	beq	wrtword
	cmpb	SQ:`,r6
	bne	error
wrtbyte:
	movb	r0,0(fp)
	br	r7ret
wrtword:
	movw	r0,0(fp)
	br	r7ret
wrtdouble:
	movd	r0,0(fp)
r7ret:
	jump	0(r7)

/* move the current open location to the contents at the current address */
/* implements the '@' option of open */
movtoloc:
	movd	0(fp),r6
	lprd	fp,r6
	br	opcrlf

/*  */

error:
	addr	errmsg,r5
	addr	getinpl,r7
	br	printm

errmsg:	.byte	CR		/* carriage return */
	.byte	LF		/* line feed */
	.byte	0x3f		/* ? */
	.byte	0x3f		/* ? */
	.byte	0

fifovflow:
	addr	_fifomsg,r5
	addr	ramless_quiet,r7
	br	printm
/*
 * romcmd.s -- AIS/3200 RAMless-Monitor commands
 * copyright(c) American Information Systems Corporation
 *  Dock Williams
 *  February, 1984	updated for System 5.2 July, 1984
 *
 *  added Diagnostic Monitor support
 *	December, 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
	.globl	cmddsp

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
				/* AIS/Diagnostic-Monitor commands: */

	cmpb	SQ:R,r3		/* RAM diagnostics */
	beq	ramdiag
	cmpb	SQ:?,r3		/* help command */
	beq	rmlhelp
	br	getinpl


/*  */

	/* ramdiag */
	/* RAM diagnostics */
	/* r0 start address */
	/* r1 length */
	/* r2 test flag */
ramdiag:
	jump	ram_DIAG


	/* 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
	.byte	SPC
	.byte	SPC
	.byte	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:
				/* Sync characters for UART Loader */
	.byte	0x4c		/* L */
	.byte	0x53		/* S */
	.byte	0x49		/* I */
	.byte	0x41		/* A */
rmlload:
	addr	_loadmsg,r5
	addr    gsync,r7
	br	printm
gsync:
	movb	$DTR1,@(U_SETOUT+UART_MAPENABLE)	/* turn on DTR */

	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	$SLASH,r2
	beq	dvpr		/* print a double value */
	cmpb	$BACKSLASH,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 */

/*  */
/*
 * romsub.s -- Subroutines for the RAMless-Monitor
 * copyright (c) American Information Systems Corporation
 *	Dock Williams
 *	February, 1984		updated for system 5.2 July, 1984
 *
 * chkesc -- Check for ESCAPE on UART-0
 *	in:	r7	return address
 *	Jumps to ramless_quiet of <ESC> typed
 *	Uses R6
 */
	.globl	chkesc
chkesc:
#ifdef REV_1A /****************** CPU REVISION-1A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT) /*  incoming char on UART-0? */
	bfc	noescape		/*  no....there is no escape */
	movb	@(UART0+U_IDATA),r6	/* yes...read it from UART-0 */
#endif /************************* CPU REVISION-1A **********************/

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT)	/*  incoming char on UART-0? */
	bfc	noescape		/*  no....there is no escape */
	movb	@(UART0+U_IDATA),r6	/*  yes...read it from UART-0 */
#endif /************************* CPU REVISION-2A **********************/

	andb	$0x7F,r6		/* clear extra bits */
	cmpb	r6,$ESC			/* ESCAPE? */
	beq	ramless_quiet		/* yes...quit waiting for UART-1 */
noescape:
	jump	0(r7)			/* use return address */

/*  */

/*
 * cvprtb - cvprtw - cvprt3 - cvprtd -- Print hex values
 *	in:	R5	Value to print
 *	in:	R7	Return address
 *	R4	copy of value to print
 *	R3	shift to get significant byte into low byte of register
 *	Prints the hex value (byte, word, or double)
 *	in R5 on the console terminal, and returns thru R7.
 *	Uses R3-R6 for the conversion algorithm.
 */

	/* convert the double word value in r5 to hex and print it */
cvprtd: movd	r5,r4
	movxbd	$-28,r3		/* shift distance */
	br	conv

	/* convert the 3 byte value in r5 to hex and print it */
cvprt3: movd	r5,r4
	movxbd	$-20,r3		/* shift distance */
	br	conv

	/* convert the word value in r5 to hex and print it */
cvprtw: movd	r5,r4
	movxbd	$-12,r3		/* shift distance */
	br	conv

	/* convert the byte value in r5 to hex and print it */
cvprtb: movd	r5,r4
	movqd	$-4,r3		/* shift distance */
conv:
	lshd	r3,r5		/* get nibble in lower byte */
	andb	$0x0f,r5	/* mask off the rest */
	cmpb	r5,$0x0a	/* is it a digit */
	bge	pralph		/* no, print the alpha character */
	addb	$0x30,r5	/* yes convert to digit hex */
prout:
	addr	nxt4,r6
	br	outc		/* print the converted nibble */
pralph:	
	addb	$0x37,r5	/* convert to alpha hex */
	br	prout
nxt4:
	movd	r4,r5		/* restore r5 */
	addqd	$4,r3		/* rotate more */
	cmpqb	$4,r3		/* check if done */
	ble	cvret
	br	conv		/* convert another digit */
cvret:	jump	0(r7)		/* return */

/*  */


	/* crlf -- output a carriage return and line feed */
	/* 	in:	R7	return address */
crlf:
	movb	$CR,r5		/* output carriage return */
	addr	plf,r6
	br	outc
plf:
	movb	$LF,r5		/* output line feed */
	movd	r7,r6
	br	outc

/*  */

/*
 * nromio.S -- Character i/o subroutines for the RAMless-Monitor
 * copyright (c) American Information Systems Corporation
 *	Dock Williams
 *	February, 1984		updated for system 5.2 July, 1984
 *
 *
 * printm -- print the null terminated message at the address in r3
 *	in:	r5	string address
 *	in:	r7	return address for when finished printing string
 * uses:
 *	r5 next character to output, low byte
 *	r5 pointer to string, upper three bytes
 *	r6 gets return address for outc
 *	r7 return address, hi level, when finished printing string
 */
	.globl	printm
	.globl	inc
	.globl	inc1
	.globl	outc

printm:
	movb	0(r5),r6	/* get character to print */
	addqd	$1,r5		/* increment string pointer */
	cmpqb	$0,r6		/* check for null */
	beq	prtret		/* are we finished yet */
	rotd	$8,r5		/* store pointer in upper bytes */
	movb	r6,r5		/* byte to output */
	addr	outret,r6	/* return address for outc */
	br	outc		/* go print the character */
outret:
	rotd	$-8,r5
	br	printm
prtret:


	jump	0(r7)		/* message out use return address */

/*  */


	/* outc -- print out the charcter in r5 to the console
	 *	in:	R5	character to print
	 *	in:	R6	return address for outc
	 *	in:	R7	return address for high level
	 * uses R4, MOD, and SP registers
	 */

outc:

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT)	/* characters to read */
	bfs	rxc
	tbitb	$U_B_TXRDY,@(UART0+U_STAT)	/* wait til ok to write more */
	bfc	outc
	movb	r5,@(UART0+U_ODATA)		/* write out character */

outcret:
	tbitb	$U_B_TXEMPTY,@(UART0+U_STAT)	/* wait for transmitter empty */
	bfc	outcret				/* before returning */
#endif /************************* CPU REVISION-2A **********************/
	jump	0(r6)			/* use return address */
rxc:
	lprw	mod,r5			/* save the output character */
	lprd	fp,r6			/* and return address */

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	movb	@(UART0+U_IDATA),r5	/* read the pending character */
#endif /************************* CPU REVISION-2A **********************/

	addr	rxlp,r6		/* set a dummy return address */
	cmpb	r5,$CTRL_S	/* stop output? */
	beq	inc		/* yes...go wait for an input */
	cmpb	r5,$ESC		/* cancel output? */
	beq	ramless_quiet	/* yes...jump to monitor entry */
	br	outc		/* otherwise, throw it away */
rxlp:
	cmpb	r5,$ESC		/* got an input character after CTRL_S */
	beq	ramless_quiet	/* jump back quietly */
	cmpb	r5,$CTRL_Q	/* enable output? */
	bne	inc		/* no....keep reading */
dooutc:
	sprd	mod,r5		/* CTRL_Q arrived so restore print state */
	sprd	fp,r6		/* and return address */
	br	outc		/* and retry character output */

/*  */

	/* inc */
	/* read a character from the console port */
	/* r5 character read in */
	/* r6 return address */
inc:	

#ifdef REV_1A /****************** CPU REVISION-1A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT)	/* incoming character ready? */
	bfc	inc			/* no....wait forever */
	movb	@(UART0+U_IDATA),r5		/* yes...get the character */
#endif /************************* CPU REVISION-1A **********************/

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT)	/* incoming character ready? */
	bfc	inc			/* no....wait forever */
	movb	@(UART0+U_IDATA),r5		/* yes...get the character */
#endif /************************* CPU REVISION-2A **********************/

	andb	$0x7f,r5	/* only look at seven bits */
	cmpb	r5,$0x61	/* map to upper case */
	blo	uprcas
	cmpb	r5,$0x7a
	bhi	uprcas
	subb	$0x20,r5
uprcas:				/* check for escape */
	cmpb	$ESC,r5
	beq	ramless_quiet
r6ret:	jump	0(r6)		/* return to caller */

/*  */

	/* inc1 */
	/* read a character from the alternate port */
	/* abort if ESC from console port */
	/* r5 character read in */
	/* r6 return address */
inc1:	

#ifdef REV_1A /****************** CPU REVISION-1A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT)	/* incoming char on UART-0? */
	bfc	inc1chk			/* no....check UART-1 */
	movb	@(UART0+U_IDATA),r5	/* yes...read it from UART-0 */
	andb	$0x7F,r5		/* clear extra bits */
	cmpb	r5,$ESC			/* ESCAPE? */
	beq	ramless_quiet		/* yes...quit waiting for UART-1 */
inc1chk:
	tbitb	$U_B_RXRDY,@(UART1+U_STAT)	/* incoming char ready? */
	bfc	inc1			/* no....try again */
	movb	@(UART1+U_IDATA),r5	/* yes...get the character */
#endif /************************* CPU REVISION-1A **********************/

#ifdef REV_2A /****************** CPU REVISION-2A **********************/
	tbitb	$U_B_RXRDY,@(UART0+U_STAT)	/* incoming char on UART-0? */
	bfc	inc1chk			/* no....check UART-1 */
	movb	@(UART0+U_IDATA),r5	/* yes...read it from UART-0 */
	andb	$0x7F,r5			/* clear extra bits */
	cmpb	r5,$ESC			/* ESCAPE? */
	beq	ramless_quiet		/* yes...quit waiting for UART-1 */
inc1chk:
	tbitb	$U_B_RXRDY,@(UART1+U_STAT)	/* incoming char ready? */
	bfc	inc1			/* no....try again */
	movb	@(UART1+U_IDATA),r5	/* yes...get the character */
#endif /************************* CPU REVISION-2A **********************/

	br	r6ret			/* use return address */


/*
 * romhelp.s -- AIS/3200 RAMless-Monitor help
 * copyright(c) American Information Systems Corporation
 *  Dock Williams
 *  June, 1984		updated for System 5.2 July, 1984
 *
 * print a synopsis of each ROM-monitor command
 * in a manner similar to the RAM-monitor
 */

	.globl _cmdc
	.globl _cmdcsyn
	.globl _cmdd
	.globl _cmddsyn
	.globl _cmdf
	.globl _cmdfsyn
	.globl _cmdg
	.globl _cmdgsyn
	.globl _cmdh
	.globl _cmdhsyn
	.globl _cmdi
	.globl _cmdisyn
	.globl _cmdm
	.globl _cmdmsyn
	.globl _cmdo
	.globl _cmdosyn
	.globl _cmdz
	.globl _cmdzsyn
	.globl _cmdr
	.globl _cmdrsyn

msgarray:	
	.double _cmdh
	.double _cmdhsyn
	.double _cmdc
	.double _cmdcsyn
	.double _cmdd
	.double _cmddsyn
	.double _cmdf
	.double _cmdfsyn
	.double _cmdg
	.double _cmdgsyn
	.double _cmdi
	.double _cmdisyn
	.double _cmdm
	.double _cmdmsyn
	.double _cmdo
	.double _cmdosyn
	.double _cmdz
	.double _cmdzsyn
	.double _cmdr
	.double _cmdrsyn
	.double 0,0
dashstr:
	.byte	0x20,0x2d,0x20,0	/* the string: " - " */

rmlhelp:
	addr	msgarray,r0
sprloop:
	movd	0(r0),r5		/* print commmand name */
	addr	sprdash,r7
	br	printm
sprdash:
	addr	dashstr,r5		/* print space, dash, space */
	addr	sprsyn,r7
	br	printm
sprsyn:	
	addqd	$4,r0			/* print synopsis */
	movd	0(r0),r5
	addr	sprret,r7
	br	printm
sprret:
	addr	sprchk,r7		/* print carriage return, line feed */
	br	crlf
sprchk:
	addqd	$4,r0
	cmpqd	$0,0(r0)			/* finished yet? */
	bne	sprloop			/* keep on printing till done */
	br	getinpl			/* finished. On to next command */

