[net.sources] Princeton FORTH v2.0 for the VAX part 6 of 8

wls@astrovax.UUCP (William L. Sebok) (06/26/84)

part 6 of 8
--------Cut here and extract with sh not csh------------
mkdir ./vaxforth
/bin/echo 'Extracting ./vaxforth/forth1.S'
sed 's/^X//' <<'//go.sysin dd *' >./vaxforth/forth1.S
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *									 *
 *	FORTH Compiler, Native Mode Kernel for VAX UNIX			 *
 *                                              W.L.Sebok  July 1982	 *
 *						rev March 11,1984	 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifdef BSD4_2
#include <syscall.h>
#endif
X/* 	Definition of Parameters */

X/*   Definition of User Area (Task Control Block) */

	.set	usiz,0

	.set	active,usiz	/* non-zero if coprocess is sleeping */
	.set	usiz,usiz+4
	.set	rsav,usiz	/* save area for return stack */
	.set	usiz,usiz+4
	.set	rbot,usiz	/*  bottom of return stack */
	.set	usiz,usiz+4
	.set	sbot,usiz	/*  bottom of parameter stack */
	.set	usiz,usiz+4
	.set	typer,usiz	/*  points to control block of terminal */
	.set	usiz,usiz+4
	.set	typer0,usiz	/*  points to default terminal */
	.set	usiz,usiz+4
	.set	reader,usiz	/*  input device */
	.set	usiz,usiz+4
	.set	reader0,usiz	/*  reset for reader device */
	.set	usiz,usiz+4
	.set	head,usiz	/*  latest vocabulary entry  */
	.set	usiz,usiz+4
	.set	darea,usiz	/*  area which describes disk buffers */
	.set	usiz,usiz+4
	.set	lcknt,usiz	/* # of protected disk buffer i/o operations */
	.set	usiz,usiz+4
	.set	floc,usiz	/* pointer to next location if UNIX type file.*/
	.set	usiz,usiz+4
	.set	dpl,usiz /*describes characteristics of last number converted 
 *			 1st byte is negative of decimal exponent
 *			 2nd byte contains flag bits
 *			 bit 0  on if negative (-0 is distinguished by this bit)
 *			 bit 1 on if floating point
 *			 bit 7 on if single precision integer */
	.set	usiz,usiz+4
	.set	scr,usiz	/* current block being edited. */
	.set	usiz,usiz+4
	.set	base,usiz	/* base used in number conversions */
	.set	usiz,usiz+4
	.set	context,usiz	/* vocabulary with which words are interpreted*/
	.set	usiz,usiz+4
	.set	current,usiz	/* vocabulary in which new words are compiled*/
	.set	usiz,usiz+4
	.set	state,usiz	/* 0 if execute, 100000 if compile */
	.set	usiz,usiz+4
	.set	in,usiz		/* char pointer in block being interpreted */
	.set	usiz,usiz+4
	.set	blk,usiz	/* block currently being loaded */
				/* (or 0 if terminal). */
	.set	usiz,usiz+4
	.set	msgbuf,usiz	/* message buffer for terminal input. */
	.set	usiz,usiz+4
	.set	msgbuf0,usiz	/* restore cell for memory management. */
	.set	usiz,usiz+4
	.set	dbparen,usiz	/* stores pointer in output number formation. */
	.set	usiz,usiz+4
	.set	ssbot,usiz	/* bottom of string stack. */
	.set	usiz,usiz+4
	.set	fsbot,usiz	/* bottom of floating point stack */
	.set	usiz,usiz+4
	.set	errno,usiz	/* Saved unix error number */
	.set	usiz,usiz+4
	.set	quitadd,usiz	/* routine to intercept a QUIT */
	.set	usiz,usiz+4

X/*  Dedicated Register Definitions */

	.set	u,7	/* user area pointer. */
	.set	h,8	/* dictionary pointer */
	.set	c,9	/* string stack pointer */
	.set	f,10	/* floating point stack pointer */
	.set	s,11	/* parameter stack pointer */
	.set	r,14	/* return stack pointer */

X/*   Terminal Status Options */

	.set	RAW,040
	.set	CRMOD,020
	.set	ECHO,010

X/*  Terminal ioctl functions */

#ifdef BSD4_2
	.set	TIOCGETP,0x4006<16|'t<8|8	/* get terminal options */
	.set	TIOCSETP,0x8006<16|'t<8|9	/* set terminal options */
#else
	.set	TIOCGETP,'t<8|8	/* get terminal options */
	.set	TIOCSETP,'t<8|9	/* set terminal options */
#endif

X/*   Dictionary Flags Values */

	.set	IM,01		/* immediate */
	.set	INL,02		/* compile code in-line */
	.set	NUL,04		/* to make entry unavailable */


X/*   Various System Parameters */

	.set	NBUF,4		/* number of buffers */
	.set	BUFLEN,1024	/* length of buffers in bytes. */
	.set	FSTKSZ,256	/* space allocated for floating point stack */
	.set	STRSTKSZ,1024	/* space allocated for string stack (in bytes)*/
	.set	RSTKSZ,300	/* space allocated for return stack (in bytes)*/
	.set	DESLEN,24	/* size of buffer descriptor */
	.set	PADOFF,30	/* PAD is offset PADOFF bytes from HERE */
	.set	FREESIZE,256	/* Size of Free Area after HERE */
	.set	TBUFSIZ,80	/* Characters read from terminal per line. */
	.set	MAXSTR,5	/* Largest string compiled in-line. */

X/*  Definition of Error Conditions */

	.set	E.UCOND,1	/* Uncompleted conditional. */
	.set	E.QUER,2	/* ? message */
	.set	E.SBOT,3	/* Stack Empty */
	.set	E.DFULL,4	/* Dictionary Full */
	.set	E.ROVER,5	/* Return Stack Overflow. */
	.set	E.LOCK,6	/* All Buffers Locked. */
	.set	E.BADBL,7	/* Undefined block number */
	.set	E.ADOVF,8	/* Attempted Dictionary Overflow. */
	.set	E.FENCE,9	/* Attempted FORGET below fence. */
	.set	E.SEMPT,10	/* String Stack Empty */
	.set	E.SBAD,11	/* Bad String on String stack */
	.set	E.SOVER,12	/* String Stack Overflow */
	.set	E.FEMPT,13	/* Floating point stack empty */
	.set	E.FOVER,14	/* Floating point stack overflow. */
	.set	E.EOL,15	/* Ran off of End-of Line */
	.set	U.ERR,16	/* Offset for Intercepted Unix Errors. */
	.set	E.FLT,49	/* Offset for Floating point messages. */
	.set	E.INSTR,54	/* Illegal Instruction */
	.set	E.BUS,55	/* Bus error */
	.set	E.ADDR,56	/* Illegal Address */
	.set	E.SARG,57	/* Bad System Call Arguments. */

X/*   Random Stuff */

	.set	BLANK,040
	.set	TAB,011
	.set	NL,012

X/* ====================================================================== */

X/*   Initialization of Dictionary Chains */

	.set	fdc0,0		;	.set	adc0,0
 	.set	fdc1,0		;	.set	adc1,0
	.set	fdc2,0		;	.set	adc2,0
	.set	fdc3,0		;	.set	adc3,0
	.set	fdc4,0		;	.set	adc4,0
	.set	fdc5,0		;	.set	adc5,0
	.set	fdc6,0		;	.set	adc6,0
	.set	fdc7,0		;	.set	adc7,0
	.set	fdc8,0		;	.set	adc8,0
	.set	fdc9,0		;	.set	adc9,0
	.set	fdca,0		;	.set	adca,0
	.set	fdcb,0		;	.set	adcb,0
	.set	fdcc,0		;	.set	adcc,0
	.set	fdcd,0		;	.set	adcd,0
	.set	fdce,0		;	.set	adce,0
	.set	fdcf,0		;	.set	adcf,0

X/* ========================================================================== */
X/*	Globals    */
	.globl	_errno
X/* ========================================================================== */
X/* ========================================================================== */

X/*  << Start of TEXT >> */
	.text
	.word	0
	pushal	strtup
	rsb			/* jmp to initialization code */
X/* ========================================================================== */
X/*  <<< OUTER INTERPRETER >>> */
newlin:	bsbw	query		/* read in new line from terminal */
goloop:	bsbw	find		/* look up word */
gloop2:	tstl	(%s)		/* found it? */
	beql	con		/* in not, try to handle as number */
	blbc	state(%u),ex	/* compile mode? execute if not */
	subl3	$10,(%s),r0	/* flags are 10 before parameter field */
	blbs	(r0),ex		/* Immediate mode? compile if not */
	bsbb	compil
	brw	check

ex:	subl3	$6,(%s)+,r0
	jsb	(r0)
	brw	check

con:	bsbw	strcon		/* is it a string constant? */
	tstl	(%s)+
	beql	num
	brw	check

num:	clrq	-(%s)
	movl	%h,-(%s)
	bsbw	convert		/* convert string to number */
	bsbw	cnmbr		/* compile or return number */
	brw	check

X/* ========================================================================== */

X/*  Words Used in Definitions */

X/*    Execute Word */

	.byte	8f-execut
9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	INL+012414254070	/* EXECUTE */
execut:	subl3	$6,(%s)+,r0
	jsb	(r0)
8:	rsb

X/*  Compile into dictionary */

compil:	subl2	$6,(%s)
	movl	(%s),r0
	bitl	$INL,-(r0)	/* In-line? */
	jeql	_jbsb		/* No, then compile jsb, bsbb, or bsbw to it. */
	tstw	-(r0)		/* short link? */
	bneq	1f		/* yes */
	tstl	-(r0)		/* no, then skip over long link */
1:	movzbl	-(r0),r0	/* get length of in-line code. */
	movc3	r0,*(%s)+,(%h)	/* and move it */
	movl	r3,%h
	rsb

X/*   End A Forth Definition. */

9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	IM+020202020310		/* ; (semicolon) */
semcol:	movl	current(%u),context(%u)
	clrl	state(%u)
	movl	head(%u),r0
	bicl2	$NUL,(r0)	/* make entry available */
	bitb	$INL,(r0)	/* in-line defitition? */
	beql	2f		/* no */
	subl3	r0,%h,r1
	subl2	$4,r1
	tstw	-(r0)		/* short link? */
	bneq	1f		/* yes */
	tstl	-(r0)		/* no, skip over long link. */
1:	movb	r1,-(r0)	/* install length of in-line code */
2:	movb	$5,(%h)+	/* compile rsb instruction */
	rsb

X/* End a CODE definition */

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	01664207000	/* END-CODE */
	brb	semcol		/* same as semicolon in this implementation */

9:	.word	9b-fdc9
9:	.set	fdc9,9b
	.long	020070741440	/* ICON  in-line constant */
	bsbb	icode		/* create dictionary entry */
	bsbw	lit		/* compile as literal */
	brb	semcol

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020024207440	/* CODE */
code:	moval	asmdic,context(%u)
code0:	bsbw	create
	subl2	$6,%h		/* backup to code region of defintion */
	bisl2	$NUL,*head(%u)	/* make entry unfindable */
	rsb

9:	.word	9b-fdc9
9:	.set	fdc9,9b
	.long	02420741450		/* ICODE  in-line CODE definition */
icode:	clrb	(%h)+			/* reserve length */
	bsbb	code
	bisl2	$INL,*head(%u)		/* set mode=IN-LINE */
	rsb

9:	.word	9b-fdca
9:	.set	fdca,9b
	.long	IM+020202020310		/* : (colon) */
colon:	movl	current(%u),context(%u)
	incl	state(%u)	/* set state=COMPILE */
	jbr	code0

9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	IM+02420741750		/* ;CODE */
	moval	asmdic,context(%u)
	clrl	state(%u)
	moval	semcod,-(%s)
	jbr	_jbsb			/* compile call to semcod */

does:	movl	(%r)+,r0
	movl	(%r)+,-(%s)
	jmp	(r0)

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	IM+037114247450		/* DOES> */
	moval	semcod,-(%s)
	bsbw	_jbsb
	moval	does,-(%s)
	bsbw	_jbsb
	rsb

semcod:	movl	head(%u),r0
	movl	(%r)+,6(r0)
	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	012114707400		/* CONSTANT */
constn:	bsbw	create
	movl	(%s)+,(%h)+
	bsbb	semcod
const:	movl	*(%r)+,-(%s)
	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020200707430		/* CON  (abbrev. for CONSTANT) */
	jbr	constn

9:	.word	9b-fdc6
9:	.set	fdc6,9b
	.long	0445100500		/* VARIABLE */
	bsbw	create
	clrl	(%h)+
	rsb

9:	.word	9b-fdc6
9:	.set	fdc6,9b
	.long	020201100530		/* VAR */
	bsbw	create
	movl	(%s)+,(%h)+
	rsb

variable:
	movl	(%r)+,-(%s)
	rsb

X/* Deposit item in Dictionary, advancing dictionary pointer */

	.byte	8f-0f
9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	INL+020202020210	/* , (comma) */
0:	movl	(%s)+,(%h)+
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	INL+020202026020	/* C, (comma) */
0:	cvtlb	(%s)+,(%h)+
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc9
9:	.set	fdc9,9b
	.long	INL+02024646410		/* IMMEDIATE */
0:	bisl2	$IM,*head(%u)		/* set precedence=IMMEDIATE */
8:	rsb

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	07044302430		/* DEFINITIONS */
	movl	context(%u),current(%u)	/* current=context */
	rsb

X/*    Create a dictionary entry */

enter:	movl	(%s)+,r1		/* get thread number */
	moval	*current(%u)[r1],r1	/* get addr of this thread */
	subl3	(r1),%h,r2	/* will short link reach? */
	bitl	$0xffff0000,r2
	beql	1f		/* yes */
	movl	(r1),(%h)+	/* no, compile long link */
	clrl	r2		/*  and make null short link */
1:	movw	r2,(%h)+		/* compile short link */
	movl	%h,head(%u)	/* we're at head, remember it */
	movl	%h,(r1)		/* and make vocab. remember it too */
	movl	(%s)+,(%h)+	/* enter packed definition name */
	movw	$0x9f16,(%h)+	/* preformat JSB *$variable */
	moval	variable,(%h)+
	rsb

X/*  construct a dictionary entry */

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	012004251060	/* CREATE  (make new entry in dictionary) */
create:	movl	$BLANK,-(%s)
	bsbw	word
	bsbw	packit
	bsbw	enter
	rsb

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	IM+INL+020202020110	/* [  (to execute mode) */
0:	clrl	state(%u)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	INL+020202020110	/* ]  (to compile mode) */
0:	incl	state(%u)
8:	rsb

9:	.word	9b-fdc8
9:	.set	fdc8,9b
	.long	IM+020202020210		/* (  comment operator */
paren:	movl	$0x29,-(%s)
	bsbw	word
	tstl	(%s)+
	rsb

X/*  Compiler Words Not in Standard ---------------- */

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020202035320	/* <: (from CODE to COMPILE mode) */
	movl	current(%u),context(%u)
	incl	state(%u)
	rsb

9:	.word	9b-fdca
9:	.set	fdca,9b
	.long	IM+020202037320	/* :> (from COMPILE to CODE mode) */
	moval	asmdic,context(%u)
	clrl	state(%u)
	rsb

X/* ======================================================================= */

X/*   Dictionary search */

search:	movl	(%s)+,r1	/* thread number */
	movl	(%s),r0		/* get packed name */
	movl	context(%u),r2	/* start at context */	
0:	movl	r2,r5		/* save it for reference */
1:	movl	(r2)[r1],r3	/* get pointer to this thread */
	beql	6f		/* quit if it points nowhere */
X/*    Main Loop    */
2:	bicl3	$3,(r3),r6	/* get rid of in-line and immediate flag bits */
	cmpl	r6,r0		/* compare dictionary header */
	bneq	3f		/* no go */
	addl3	$10,r3,(%s)	/* Success!  return parameter addr */
	rsb

3:	movzwl	-(r3),r4	/* get link */
	beql	4f		/* if null then look for long link */
	subl2	r4,r3		/* short link is a displacement */
	jneq	2b		/* try next entry */
	jbr	6f		/* link to location 0 marks end of chain */

4:	movl	-(r3),r3	/* long link is absolute */
5:	bneq	2b		/* null long link ends chain */

6:	movl	-(r2),r2	/* Is this vocab linked to another? */
	bneq	1b		/* if so then try it */
	cmpl	r5,current(%u)	/* have we tried current yet? */
	beql	fail		/* if so then we'll never find it */
	movl	current(%u),r2	/* try current */
	brb	0b
fail:	clrl	(%s)		/* return null for failure */
	rsb
X/*
 * Packing Format
 *	5 5 5 5 5 5 4 4 4 4 4 4 3 3 3 3 3 3 2 2 2 2 2 2 1 1 L L L H N I
 *	1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 * H = makes entry unavailable
 * N = compile code in-line (rather than JSB to it)
 * I = execute immediately (compiler directive)
 */

X/*   Pack Bits In Dictionary Header */

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	04454140560		/* PACKIT */
packit:	movl	(%s),r0		/* get address */
	movzbl	(r0)+,r1	/* get byte length of string */
	extzv	$0,$4,(r0),r5	/* extract thread */
	movl	r1,r4		/* save length */
	movl	$2,r2		/* initialize bit offset pointer */
1:	decl	r1
	bgeq	2f
	movl	$BLANK,r3	/* if off length of string - substitute blank */
	brb	3f
2:	movzbl	(r0)+,r3	/* get character */
	cmpl	r3,$96		/* is it a small letter? */
	blss	3f
	subl2	$32,r3		/* convert to uppercase */
3:	insv	r3,r2,$6,(%s)	/* emplace 6 bit characters */
	acbl	$26,$6,r2,1b	/* loop */
	insv	r4,$3,$3,(%s)	/* emplace length */
	bicl2	$7,(%s)		/* make sure flag bits are clear */
	movl	r5,-(%s)	/* return thread number */
	rsb

prompter:
	.ascii	"OK\n"

X/* Add code here for end-of-line "Signal" Stack */
prompt:	moval	prompter,-(%s)
	movl	$3,-(%s)
	bsbw	type0
	jbr	quit

X/*   detect and handle end-of-line condition 
 *    called from "find"	str  ---  str	(if len(str) != 0)
 *				str  ---	(if len(str) == 0)
 *  str points to a string with length in the first byte
 *
 *  if (length != 0) { continue whatever you where doing }
 *  if (find not called from goloop) abort with message. }
 *  if from keyboard  { type OK and QUIT }
 *  else {  execute ;S routine }
 */  

endline:
	tstb	*0(%s)		/* zero length string? */
	beql	1f
	rsb			/* no, continue. */

1:	cmpl	(%s)+,(%r)+	/* yes, pop stacks. */

	cmpl	(%r),$gloop2	/* `find' called from go loop? */
	beql	2f

	movl	$E.EOL,r0
	jbr	abort		/* Abort with "Ran off End of Line" */

2:	tstl	blk(%u)		/* interpreting a block? */
	beql	prompt		/* No. */

	moval	goloop,(%r)	/* back it up */
	jbr	semies		/* Yes, do ;S */

9:	.word	9b-fdc6
9:	.set	fdc6,9b
	.long	020020704440	/* FIND */
find:	movl	$BLANK,-(%s)
	bsbw	word
	bsbb	endline
	bsbw	packit
	bsbw	search
	rsb

9:	.word	9b-fdc7
9:	.set	fdc7,9b
	.long	IM+020202020210		/*  ' (tick) */
tick:	bsbb	find
	tstl	(%s)
	beql	ques
	jlbs	state(%u),lit
	rsb

ques:	movl	$E.QUER,r0
	jbr	abort

9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	IM+010064741510		/* [COMPILE]  (make next token in  */
	bsbb	find			/*  input stream be compiled, even */
	tstl	(%s)			/*  if Immediate) */
	beql	ques
	brw	compil

comp:	movl	(%r),r0
	movl	(r0)+,-(%s)
	movl	r0,(%r)
	brw	compil

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	IM+04500647470		/* COMPILE  (make next token be */
	moval	comp,-(%s)		/*  compiled when the definition now */
	bsbw	_jbsb			/*  under construction is executed) */
	bsbb	find
	tstl	(%s)
	beql	ques
	movl	(%s)+,(%h)+
	rsb

X/* ===================================================================== */

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	020200254430	/* BYE  exit back to system */
bye:
#ifdef	FPROMPT
	bsbw	treset
#endif
	bsbw	flush
	clrl	-(%s)
	brw	s_exit

X/* ===================================================================== */

X/*   Unix Terminal Interface */

	.set	is.arg,-18
	.set	is.mode,-14
	.set	s.arg,-12
	.set	s.mode,-8
	.set	rchan,-6
	.set	mung,-5

unxout:	movl	(r0),-(%s)	/* get file descriptor */
	bsbw	s_write
	tstl	(%s)+
#ifdef	COPROCESS
	jbr	c_wait
#else
	rsb
#endif

unxin:	blbc	mung(r0),1f	/* does terminal need reset? */
	pushl	r0		/* put control block in safer place */
	bsbw	ekey		/* yes, reset it */
	movl	(%r)+,r0	/* recall control block */
1:	tstl	(%s)		/* check count */
	bgtr	2f		/* count <= 0? */
	addl2	$8,%s		/* yes, quit */
	rsb
2:	movl	4(%s),r4
	clrb	(r4)		/* in case it returns prematurely */
	movzbl	rchan(r0),-(%s)	/* get file descriptor */
	bsbw	s_read
	movl	(%s)+,r0	/* get number of bytes read, EOF? */
	jeql	bye		/* yes, then quit */
	blss	3f		/* handle errors */
	clrb	-(r4)[r0]	/* place null at end of buffer. */
#ifdef	COPROCESS
	jbr	c_wait
#else
	rsb
#endif
X/*
 * Terminal error handling here badly needs to be cleaned up. In particular,
 * if it is reading from file descriptor 0 and gets an error it could try to
 * reopen descriptor 0 as /dev/tty.  It is now possible to hang FORTH by closing
 * file descriptor 0.
 */
3:	clrl	r0
	jbr	abort

9:	.word	9b-fdc4
9:	.set	fdc4,9b
#ifdef	FPROMPT
	.long	02514251160		/* TRESET  reset terminal modes */
treset:	movl	reader(%u),r2
	bicw2	$FPROMPT,s.mode(r2)
	incb	mung(r2)
	jbr	setty
#else
	.long	IM+02514251160		/* TRESET  is dummy without FPROMPT */
	rsb
#endif

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020144245740		/* <KEY (put terminal in Raw MOde) */
skey:	movl	reader(%u),r0
	incb	mung(r0)
	bisw2	$RAW,s.mode(r0)		/* set RAW mode into terminal status */
	bicw2	$(ECHO|CRMOD),s.mode(r0)	/* turn off ECHOing */
	jbr	setty

9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	020371442440
ekey:	movl	reader(%u),r2
	clrb	mung(r2)
	movc3	$6,is.arg(r2),s.arg(r2)	/* reset arguments */

setty:	movl	reader(%u),r2
	moval	s.arg(r2),-(%s)
	movl	$TIOCSETP,-(%s)
	movzbl	rchan(r2),-(%s)
	bsbw	s_ioctl
	tstl	(%s)+
	rsb

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020144245740	/* 0KEY  (read 1 char onto stack) */
key0:	movl	reader(%u),r2
	clrq	-(%s)		/* reserve a word */
	moval	4(%s),(%s)	/* point to this word */
	movl	$1,-(%s)	/* read 1 word */
	movzbl	rchan(r2),-(%s)	/* get file descriptor */
	bsbw	s_read
	tstl	(%s)+
	jlss	unxerr
	rsb

X/* ========================================================================
 *
 *    UNIX disk handler interface
 *
 *    format of buffer descriptor
 *
 * 	offset from		function
 * 	buffer start
 *
 * 	02000	reserved for null character at end of block. 
 *	02001	update flag
 * 	02002	lock flag 
 * 	02004	ownership mark 
 * 	02010	block number of this block (-1 if empty) 
 * 	02014	link 
 * 	02020	link back (to previous buffer in chain) 
 *	02024	raw link (this link is not touched once created)
 */

	.set	updat,-11
	.set	lock,-10
	.set	own,-8
	.set	locat,-4
	.set	link1,02014
	.set	link2,4
	.set	link0,8

	.set	L.blktab,10		/* Size of Disk block table */
	.set	CHANBOT,0xffffff00	/* Dscrpt 0 maps into this Block numb */

X/* define disk buffer descriptor control block */

	.set	bufs,12
	.set	n.blktab,bufs+4
	.set	b.blktab,n.blktab+4
	.set	e.blktab,b.blktab+(4*L.blktab)
	.set	f.blktab,e.blktab+(4*L.blktab)
	.set	Blktab,f.blktab+L.blktab

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	01070044070	/* CHANBOT */
	movl	$CHANBOT,-(%s)
	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	020114312440	/* BUFS */
	addl3	darea(%u),$bufs,-(%s)
	rsb

9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	05460127000	/* N.BLKTAB */
	addl3	darea(%u),$n.blktab,-(%s)
	rsb

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	05460127000	/* L.BLKTAB */
	movl	$L.blktab,-(%s)
	rsb

9:	.word	9b-fdc6
9:	.set	fdc6,9b
	.long	05460127000	/* F.BLKTAB */
	addl3	darea(%u),$f.blktab,-(%s)
	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	05460127000	/* B.BLKTAB */
	addl3	darea(%u),$b.blktab,-(%s)
	rsb

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	05460127000	/* E.BLKTAB */
	addl3	darea(%u),$e.blktab,-(%s)
	rsb

X/*   UNIX disk interface */

X/*   buff count block rwtflag endaction DRWT */

drwt:	tstl	(%s)+		/* ignore unused end-action Flag */
	movl	(%s)+,r3	/* get read/write flag */
	movl	(%s)+,r1	/* get block number */
	mcoml	r1,r0		/* null block? */
	bneq	1f		/* no */
	addl2	$8,%s		/* yes, then do nothing */
	rsb

1:	subl3	$CHANBOT,r1,r2	/* is block number a channel number? */
	bgequ	unxfil		/* yes */

X/*    regular block style format file */

	movl	darea(%u),r4	/* get pointer to disk area */
	movl	n.blktab(r4),r2	/* get number of intems in mapping table */
	moval	b.blktab(r4)[r2],r0	/* get address of table */
1:	decl	r2
	blss	2f		/* loop and exit */
	cmpl	r1,-(r0)	/* after beginning of item? */
	blssu	1b		/* no */
	cmpl	r1,e.blktab(r4)[r2]	/* before end of item? */
	bgtru	1b		/* no, try next entry */
	brb	3f		/* Yes, got it!!! */

2:	movl	$E.BADBL,r0	/* undefined block number */
	jbr	abort

3:	cvtbl	f.blktab(r4)[r2],r2	/* get channel number */
	subl2	(r0),r1		/* get file offset */
	ashl	$10,r1,r1	/* convert block offset to byte offset */
	brb	rw

unxfil:	movl	floc(%u),r1	/* get file offset */

	/* at this point the file offset is in r1 */
rw:	movl	r2,-(%s)	/* push file descriptor for read/write call */
	movl	r1,-(%s)	/* file location for seek */
	clrl	-(%s)		/* offset from file beginning */
	movl	r2,-(%s)	/* file descriptor for seek */
	bsbw	s_seek
	movl	(%s)+,r0
	jlss	unxerr

	blbs	r3,2f		/* test read/write flag */

	movl	4(%s),r4	/* save buffer address */
	movl	8(%s),r2	/* save count */
	bsbw	s_read		/* assumed that s_read doesn't touch r2,r4 */
	movl	(%s)+,r0
	jlss	unxerr

	cmpl	r0,r4		/* full extent read in? */
	bgeq	1f
	clrb	(r2)[r0]	/* no, place null byte at end of record */
	rsb
1:	movb	$NL,(r2)[r0]	/* Yes, place new-line at end */
	rsb

2:	bsbw	s_write
	tstl	(%s)+
	jlss	unxerr
	rsb

X/* ----------------------------------------------------------------- */

X/*  Block Buffer Processing (Locking and Unlocking Version) */

X/*    See if block is in core */

core:	movl	darea(%u),r2
	movl	(r2),r0		/* most recently referenced buffer */
	movl	bufs(r2),r1	/* get buffer count */

1:	cmpl	locat(r0),(%s)	/* is this the one? */
	beql	2f		/* yes */
	movl	(r0),r0		/* no check all other buffers */
	sobgtr	r1,1b		/* check all buffers */
#ifdef	COPROCESS
	brb	3f		/* can't find it */
#else
	rsb
#endif
2:	remque	(r0),r1		/* unlink buffer */
	insque	(r0),(r2)	/* and move it to beginning of search queue */
	subl3	$link1,r0,(%s)	/* save buffer */
	tstl	(%r)+		/* and skip extraneous games */

#ifdef COPROCESS
X/*
 *  Strategy here is to decrement the lock count on all other buffers whenever
 *  the referenced block changes
 */
	cmpb	lock(r0),lckcnt(%u)	/* lock count already highest? */
	bgequ	5f			/* yes */
	movb	lcknt(%u),lock(r0)	/* claim it */
	movl	%u,own(r0)
	movl	bufs(r2),r1		/* get number of bufs */
	brb	4f
3:	cmpl	%u,own(r0)		/* ours? */
	bneq	4f			/* no */
	tstb	lock(r0)		/* already zero? */
	beql	4f			/* no */
	decb	lock(r0)		/* decrement lock count */
	bneq	4f
	clrl	own(r0)
4:	movl	(r0),r0
	sobgtr	r1,3b
#endif
5:	rsb

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020054147440	/* LOCK lock buffer in place */
	movl	*darea(%u),r0	/* get block addr */
	movl	%u,own(r0)	/* claim it */
	clrb	lock(r0)	/* disable auto-unlocking */
	rsb


9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	01474607160	/* UNLOCK */
unlock:	addl3	$link1,(%s),r0	/* get buffer addr */
#ifdef	COPROCESS
	cmpl	%u,own(r0)	/* one of our's */
	beql	1f
	tstl	own(r0)
	bneq	2f
#endif
1:	movl	locat(r0),r1	/* get blk num */
	mnegl	$1,locat(r0)	/* mark buffer free */
	movl	darea(%u),r2
	remque	(r0),r3
	insque	(r0),*4(r2)	/* move to end of buffer queue */
	clrl	own(r0)		/* unlock */
	clrb	lock(r0)
	blbs	updat(r0),wwrite	/* update? */
2:	tstl	(%s)+		/* no */
	rsb

wwrite:	clrb	updat(r0)	/* clr updat flag (& busy) */
	cvtwl	$BUFLEN,-(%s)	/* bytes to read */
	movl	r1,-(%s)	/* block number */
	movl	$1,-(%s)	/* flag write (synchronous) */
	clrl	-(%s)		/* asynchronous flag (not used in UNIX) */
	jbr	drwt		/* do it. */

X/*   Prepare to Read */

rread:	movl	(%s),r0		/* get buffer */
	movl	r0,-(%s)	/* copy of buffer for read */
	cvtwl	$BUFLEN,-(%s)	/* bytes to read */
	movl	(locat+link1)(r0),-(%s)	/* copy of block number for read */
	clrl	-(%s)		/* flag a read */
	clrl	-(%s)		/* asynchronous flag for non-UNIX systems */
	jbr	drwt		/* do it */


X/*   Get a New Buffer */

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	02430312460	/* BUFFER  get (but don't read in) buffer */
buffer:	movl	darea(%u),r2	/* get disk area pointer */
	movl	bufs(r2),r1	/* get buffer count */
1:	movl	4(r2),r0	/* get buffer from end of queue */
	tstl	own(r0)		/* is it free? */
	beql	2f		/* yes, got it */
	sobgtr	r1,1b		/* try again */

	movl	$E.LOCK,r0	/* error, no free buffers */
	jbr	abort

2:
#ifdef	COPROCESS
	movl	%u,own(r0)	/* claim it */
	movb	lcknt(%u),lock(r0)
#endif
	remque	(r0),r0
	insque	(r0),(r2)	/* place at head of queue */
	movl	locat(r0),r1
	movl	(%s),locat(r0)
	subl3	$link1,r0,(%s)	/* return buffer addr */
	blbs	updat(r0),4f	/* update? */
	rsb

4:	subl3	$link1,r0,-(%s)
	jbr	wwrite

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	012004210160		/* UPDATE  mark a block for output */
update:	movl	*darea(%u),r0
	bisb2	$1,updat(r0)
	rsb

X/*   General Block handler */
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	05414746050		/* BLOCK */
block:	bsbw	core
	bsbb	buffer
	bsbw	rread
	rsb

X/* ------------------------------------------------------------------------ */

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020020047440	/* LOAD  divert input to block from terminal */
load:	pushl	floc(%u)	/* save file location pointer */
	pushl	blk(%u)		/* save which block to interpret */
	pushl	in(%u)		/* save byte pointer */
	clrl	floc(%u)	/* save offset in file */
	movl	(%s)+,blk(%u)	/* get new block to interpret */
	clrl	in(%u)		/* reset block pointer for new block */
	jbr	goloop		/* interpret it */

9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	020202011720	/* ;S */ 
semies:	tstl	(%r)+		/* do not return to caller */
	movl	(%r)+,in(%u)	/* restore in */
	movl	blk(%u),r0	/* save old blk for reference */
	movl	(%r)+,blk(%u)	/* restore blk */
	movl	(%r)+,floc(%u)	/* restore file offset */
	subl2	$CHANBOT,r0	/* is old blk a non-Block type file? */
	blssu	1f		/* no */
	movl	r0,-(%s)
	bsbw	s_close
1:	rsb

9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	IM+020203726630		/* -->  (continue on next screen) */
	cmpl	blk(%u),$CHANBOT
	blssu	1f
	bisl2	$(BUFLEN-1),floc(%u)	/* "File Descriptor" file */
	incl	floc(%u)		/* move floc to even screen boundary */
	movl	*darea(%u),r0		/* mark buffer stale */
	mnegl	$1,locat(r0)
	brb	2f
1:	incl	blk(%u)			/* regular screen number */
2:	clrl	in(%u)
	rsb

9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	020054146240		/* !LCK  (store buffer lock count) */
	movl	(%s)+,lcknt(%u)
	rsb


9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	014521006450		/* EMPTY-BUFFERS  (or EMPTY) */
	movl	darea(%u),r0
	brb	2f
1:	mnegl	$1,locat(r0)	/* mark buffer as nothing */
	clrl	own(r0)		/* clear lock and ownership */
	clrb	lock(r0)
2:	movl	link0(r0),r0	/* get hard link */
	bneq	1b		/* process it if anything there */
	rsb


9:	.word	9b-fdc6
9:	.set	fdc6,9b
	.long	04115246050		/* FLUSH  (write out buffers) */
	brb	flush


9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	026425300540		/* SAVE-BUFFERS */
X/* NOTE: this routine also gathers stray blocks */
flush:	movl	darea(%u),r6
	brb	2f
1:	subl3	$link1,r6,-(%s)
	bsbw	unlock
2:	movl	link0(r6),r6		/* use raw link */
	bneq	1b
	rsb

X/* ======================================================================= */


X/* 	Basic Utility Words */

X/*   Stack Manipulation ------------------------------------------------- */

	.byte	8f-0f
9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	INL+020201012430	/* DUP */
0:	movl	(%s),-(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	INL+020100751040	/* DROP */
0:	tstl	(%s)+			/* pop one item from stack */
8:	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020100053540		/* SWAP */
swap:	movl	(%s)+,r0
	movl	(%s),-(%s)
	movl	r0,4(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdcf
9:	.set	fdcf,9b
	.long	INL+020110253040	/* OVER */
0:	movl	4(%s),-(%s)
8:	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	020201207530		/* ROT */
rot:	movl	8(%s),-4(%s)
	movc3	$12,-4(%s),(%s)
	rsb

9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	020120751240		/* -ROT (not in Standard) */
mrot:	movc3	$12,(%s),-4(%s)
	movl	-4(%s),8(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	INL+020054144540	/* PICK */
0:	movl	(%s),r0
	movl	(%s)[r0],(%s)
8:	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	020060607540		/* ROLL */
roll:	movl	(%s),r1
	movl	(%s)[r1],(%s)+
	ashl	$2,r1,r1
	movc3	r1,-4(%s),(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdcf
9:	.set	fdcf,9b
	.long	020101242340		/* ?DUP */
0:	tstl	(%s)
	beql	8f
	movl	(%s),-(%s)
8:	rsb

rto:	movl	(%r)+,r0
	pushl	(%s)+
	jmp	(r0)

7:	movl	(%s)+,-(%r)
8:

9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	IM+020202011320		/* >R */
	tstl	state(%u)
	beql	rto
	movc3	$(8b-7b),7b,(%h)
	movl	r3,%h
	rsb


rfrom:	movl	(%r)+,r0
	movl	(%r)+,-(%s)
	jmp	(r0)

7:	movl	(%r)+,-(%s)
8:

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	IM+020202037120		/* R> */
	tstl	state(%u)
	beql	rfrom
	movc3	$(8b-7b),7b,(%h)
	movl	r3,%h
	rsb

r_at:	movl	4(%r),-(%s)
	rsb

7:	movl	(%r),-(%s)
8:

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	IM+020202000120		/* R@ */
	tstl	state(%u)
	beql	r_at
	movc3	$(8b-7b),7b,(%h)
	movl	r3,%h
	rsb

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	04121002450		/* DEPTH */
	subl3	%s,sbot(%u),r0
	ashl	$-2,r0,-(%s)
	rsb

X/* Stack Manipulation operators not in standard */

	.byte	8f-0f
9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	INL+010075102250	/* -DROP  (drop item 1 deep) */
0:	movl	(%s)+,(%s)
8:	rsb


X/*   Comparison ================================================== */

X/*                                  Standard comparison Operators */

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020202020310	/* < */
less:	cmpl	(%s)+,(%s)+
	jgtr	true
	jbr	false

9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	020202020310	/* = */
equals:	cmpl	(%s)+,(%s)+
	jeql	true
	jbr	false

9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	020202020310	/* > */
greater:
	cmpl	(%s)+,(%s)+
	jlss	true
	jbr	false

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020202036320	/* 0< */
zless:	tstl	(%s)+
	jlss	true
	jbr	false

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020202036720	/* 0= */
_zeq:	tstl	(%s)+
	jeql	true
	jbr	false

9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	020201207430	/* NOT */
	brb	_zeq

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020202037320	/* 0> */
	tstl	(%s)+
	jgtr	true
	jbr	false

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	020202036120	/* U< */
	cmpl	(%s)+,(%s)+
	jgtru	true
	jbr	false

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	020202036020	/* D< */
d.less:	movl	%s,r1
	addl2	$8,%s
	movl	%s,r0
	addl2	$8,%s
	cmpl	(r0)+,(r1)+	/*  compare high words */
	beql	1f		/*  if equal inspect low words */
	blss	true
	jbr	false

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	020203612430	/* DU<  (unsigned double compare) */
	movl	%s,r1
	addl2	$8,%s
	movl	%s,r0
	addl2	$8,%s
	cmpl	(r0)+,(r1)+
	bneq	2f
1:	cmpl	(r0),(r1)
2:	blssu	true
	jbr	false

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	020203670030	/* D0= */
dzeq:	bisl2	(%s)+,(%s)+
	beql	true
	jbr	false

true:	movl	$1,-(%s)
	rsb

false:	clrl	-(%s)
	rsb

X/*                          Comparison Operators not in Standard */

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020203736330	/* 0<> */
	tstl	(%s)+
	jneq	true
	jbr	false

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020203676330	/* 0<= */
	tstl	(%s)+
	jleq	true
	jbr	false

9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	020203677330	/* 0>= */
	tstl	(%s)+
	jgeq	true
	jbr	false

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020202037320	/* <> */
	cmpl	(%s)+,(%s)+
	bneq	true
	jbr	false

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	020202036720	/* <= */
	cmpl	(%s)+,(%s)+
	bgeq	true
	jbr	false

9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	020202036720	/* >= */
	cmpl	(%s)+,(%s)+
	bleq	true
	jbr	false

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	020202037120	/* U> */
	cmpl	(%s)+,(%s)+
	jlssu	true
	jbr	false


X/* Arithmetic  And Logical ---------------------------------------- */

X/*           Operators in Standard */

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202025720	/* 1+ */
0:	incl	(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202026720	/* 1- */
0:	decl	(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdca
9:	.set	fdca,9b
	.long	INL+020202020210	/* * */
0:	mull2	(%s)+,(%s)
8:	rsb

9:	.word	9b-fdcf
9:	.set	fdcf,9b
	.long	020020746640		/* /MOD */
divmod:	movl	(%s)+,r2
	clrl	r1
	movl	(%s),r0
	bgeq	1f
	decl	r1
1:	ediv	r2,r0,-(%s),4(%s)
	rsb

9:	.word	9b-fdca
9:	.set	fdca,9b
	.long	02074667650		# */MOD
tmdvmod:
	emul	4(%s),8(%s),$0,r0
	ediv	(%s)+,r0,(%s),4(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdcf
9:	.set	fdcf,9b
	.long	INL+020202020210	/* /  (divide) */
0:	divl2	(%s)+,(%s)
8:	rsb

9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	020200207430		/* MOD */
	bsbb	divmod
	tstl	(%s)+
	rsb

9:	.word	9b-fdca
9:	.set	fdca,9b
	.long	020202027620		#  */ (multiply, then divide)
	bsbb	tmdvmod
	movl	(%s)+,(%s)
	rsb

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	020202025120		/* U* */
	movl	(%s)+,r2
	emul	r2,(%s),$0,r0
	tstl	(%s)
	bgeq	1f
	addl2	r2,r1
1:	tstl	r2
	bgeq	2f
	addl2	(%s),r1
2:	movl	r0,(%s)
	movl	r1,-(%s)
	rsb

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	02074667550		/* U/MOD */
X/* This is devilishly hard to do properly. Because the basic precision of vax */
X/* integers is more than the `standard' unsigned 16 bit integer, I am not     */
X/* bothering to do unsigned arithemetic. */
	movl	(%s)+,r2
	movl	(%s)+,r1
	movl	(%s),r0
	ediv	r2,r0,-(%s),4(%s)
	rsb

9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	020201400430		/* MAX */
max:	cmpl	(%s)+,(%s)
	bleq	1f
	movl	-4(%s),(%s)
1:	rsb


9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	020200704430		/* MIN */
min:	cmpl	(%s)+,(%s)
	bgeq	1f
	movl	-4(%s),(%s)
1:	rsb


9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	020201141030
abs:	tstl	(%s)			/* ABS */
	bgeq	1f
	mnegl	(%s),(%s)
1:	rsb


	.byte	8f-0f
9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	INL+012004342460	/* NEGATE */
0:	mnegl	(%s),(%s)
8:	rsb

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	0434247070		/* DNEGATE */
dnegate:
	mnegl	(%s),(%s)+
	mnegl	(%s),(%s)
	sbwc	$0,-(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020200207030	/* AND */
0:	mcoml	(%s)+,r0
	bicl2	r0,(%s)
8:	rsb


	.byte	8f-0f
9:	.word	9b-fdcf
9:	.set	fdcf,9b
	.long	INL+020202011020	/* OR */
0:	bisl2	(%s)+,(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc8
9:	.set	fdc8,9b
	.long	INL+020201107530	/* XOR */
0:	xorl2	(%s)+,(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	INL+020202020210	/* + */
0:	addl2	(%s)+,(%s)
8:	rsb

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	020202025420		/* D+ */
d.plus:	movq	(%s)+,r0
	addl2	r1,4(%s)
	adwc	r0,(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	INL+020202020210	/* - */
0:	subl2	(%s)+,(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020202025720	/* 2+ */
0:	addl2	$2,(%s)
8:	rsb


	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020202026720	/* 2- */
0:	subl2	$2,(%s)
8:	rsb


X/*         Operators not in Standard ------------------------ */

	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020202025320	/* 2* */
0:	addl2	(%s),(%s)
8:	rsb


	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020202027720	/* 2/ */
0:	divl2	$2,(%s)
8:	rsb

X/*                 Machine independent (hopefully) address arithmetic */

	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020025214440	/* BYTE == 4* */
0:	ashl	$2,(%s),(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc7
9:	.set	fdc7,9b
	.long	INL+020200211130	/* WRD == 4/ */
0:	ashl	$-2,(%s),(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	INL+020202025620	/* ++ (increment addr 1 word) */
0:	addl2	$4,(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	INL+020202026620	/* --  (decrement addr 1 word) */
0:	subl2	$4,(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202025420	/* A+  (add const to addr) */
0:	movl	(%s)+,r0
	moval	*(%s)+[r0],-(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	INL+020202000620	/* +A  (add addr to const) */
0:	movl	4(%s),r0
	moval	*(%s)+[r0],(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202026420	/* A-  (subtract constant form addr) */
0:	mnegl	(%s)+,r0
	moval	*(%s)+[r0],-(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202065730	/* 1+! */
0:	incl	*(%s)+
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202066730	/* 1-! */
0:	decl	*(%s)+
8:	rsb


	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020202065730	/* 2+! */
0:	addl2	$2,*(%s)+
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	INL+020202066730	/* 2-! */
0:	subl2	$2,*(%s)+
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	INL+020202065630	/* ++! (increment addr to next word) */
0:	addl2	$4,*(%s)+
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	INL+020202066630	/* --! (decrement addr to prev word) */
0:	subl2	$4,*(%s)+
8:	rsb

X/*   Memory Operators ---------------------------------------------- */

	.byte	8f-0f
9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	INL+020202020010	/* @  (retrieve value from address) */
0:	movl	*(%s)+,-(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	INL+020202020210	/* ! (store value at address) */
0:	movl	(%s)+,r0
	movl	(%s)+,(r0)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	INL+020202000020	/* C@  (retrieve byte) */
0:	movzbl	*(%s)+,-(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	INL+020202020420	/* C!  (store byte) */
0:	movl	(%s)+,r0
	cvtlb	(%s)+,(r0)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	INL+020202020620	/* +!  (sum into address) */
0:	addl3	*(%s)+,(%s)+,*(-8)(%s)
8:	rsb


9:	.word	9b-fdcd
9:	.set	fdcd,9b
	.long	020025307440	/* MOVE  (move a string of words) */
move:	ashl	$2,(%s)+,r0
	movl	(%s)+,r1
	movc3	r0,*(%s)+,(r1)
	rsb

	.byte	8f-cmove
9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	INL+02530746450		/* CMOVE  (move string of bytes) */
cmove:	movl	(%s)+,r0
	movl	(%s)+,r1
	movc3	r0,*(%s)+,(r1)
8:	rsb

	.byte	8f-fill
9:	.word	9b-fdc6
9:	.set	fdc6,9b
	.long	INL+020060604440	/* FILL (fill with bytes) */
fill:	movl	(%s)+,r1
	movl	(%s)+,r0
	movc5	$0,(%h),r1,r0,*(%s)+
8:	rsb

X/*   Control Structures =========================================== */

X/*   Basic Conditional Branch */

0:	tstl	(%s)+
	bneq	1f
	brw	1f
1:

9:	.word	9b-fdc9
9:	.set	fdc9,9b
	.long	IM+020202003020		/* IF */
if:	movc3	$7,0b,(%h)		/* tstl (s)+ ; bneq .+4 ; brw xxx ; */
	movl	r3,%h
	movl	%h,-(%s)
	rsb

9:	.word	9b-fdc7
9:	.set	fdc7,9b
	.long	IM+02460444150		/* WHILE */
	brb	if			/* while requires same action as if */

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	IM+020070244140		/* THEN */
then:	movl	(%s)+,r0
	subl3	r0,%h,r1
	movw	r1,-(r0)
	rsb

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	IM+020025146040		/* ELSE */
	movb	$0x31,(%h)+		/* compile brw opcode */
	clrw	(%h)+			/* reserve space for offset */
	bsbb	then
	movl	%h,-(%s)
	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	IM+0425002560		/* REPEAT */
	bsbw	swap
	bsbw	_br
	bsbw	then
	rsb

1:	tstl	(%s)+

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	IM+06045207150		/* UNTIL */
	movw	1b,(%h)+		/* compile tstl (%s)+ */
	movl	$0x12,-(%s)		/* compile assembler 0<> opcode */
	brw	auntil			/* go to assembler `UNTIL' */

	.byte	8f-here
9:	.word	9b-fdc8
9:	.set	fdc8,9b
	.long	INL+020025102440	/* HERE  push h on stack */
here:	movl	%h,-(%s)
8:	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	IM+07044342450		/* BEGIN */
	brb	here

do:	movl	(%r)+,r1	/* get linkage out of way */
	movl	(%s)+,r0	/* get initial value of counter */
	cmpl	r0,(%s)		/* less than limit (counting upward)? */
	bgeq	1f		/* no */
	decl	(%s)		/* yes, adjust limit downwards */
1:	pushl	(%s)+		/* push limit */
	pushl	r0		/* push counter */
	jmp	(r1)		/* return */

9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	IM+020202007420		/* DO */
	moval	do,-(%s)
	bsbw	_jbsb		/* compile `do' */
	movl	%h,-(%s)
	rsb

1:	addl2	$8,%r			/* pop loop arguments */

popal:	movc3	$3,1b,(%h)
	movl	r3,%h
	rsb

9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	IM+020100747440		/* LOOP */
	subl3	(%s),%h,r0
	addl2	$5,r0
	cvtbl	r0,r1
	movzbl	$(0x60+r),-(%s)		/* r ) */
	movl	$4,-(%s)
	movzbl	$(0xa0+r),-(%s)		/* 4 r )) */
	cmpl	r0,r1
	bneq	1f
	bsbw	_aobleq			/* compile aobleq 4(%r),(%r),xxx */
	brb	popal
1:	movl	$1,-(%s)
	movzbl	$0x8f,-(%s)
	bsbw	d.swap
	bsbw	_acbl			/* compile acbl 4(%r),$1,(%r),xxx */
	brb	popal

9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	IM+010074746250		/* +LOOP */
	movzbl	$(0x60+r),-(%s)		/* r ) */
	movzbl	$(0x80+s),-(%s)		/* s )+ */
	movl	$4,-(%s)
	movzbl	$(0xa0+r),-(%s)		/* 4 r )) */
	bsbw	_acbl			/* compile acbl 4(%r),(%s)+,(%r),xxx */
	brb	popal

X/* In this implementation, the following words MUST be called from compile
 * mode */

	.byte	8f-0f
9:	.word	9b-fdc9
9:	.set	fdc9,9b
	.long	INL+020202020010	/* I  (get inner loop index) */
0:	movl	(%r),-(%s)
8:

	.byte	8f-0f
9:	.word	9b-fdca
9:	.set	fdca,9b
	.long	INL+020202020010	/* J  (get loop index 1 level out) */
0:	movl	8(%r),-(%s)
8:

	.byte	8f-0f
9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	INL+020202020010	/* K (get loop index 2 levels out) */
0:	movl	16(%r),-(%s)		/*   not in Standards */
8:

	.byte	8f-0f
9:	.word	9b-fdcc
9:	.set	fdcc,9b
	.long	INL+02530042450		/* LEAVE  leave do loop */
0:	movl	(%r),4(%r)
8:
	.byte	1
9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	INL+020120454040	/* EXIT */
	rsb

X/*   Control structure not in 79 standards --------------- */

1:	cmpl	(%s)+,(%s)+
	beql	2f
	tstl	-(%s)
	brw	2f
2:
9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	IM+020025140440		/* CASE */
	movc3	$(2b-1b),1b,(%h)
	movl	r3,%h
	movl	%h,-(%s)
	rsb

X/* ============================================================== */

X/*   Terminal I/O */


	.byte	8f-type0
9:	.word	9b-fdc0
9:	.set	fdc0,9b
	.long	INL+02501452350		/* 0TYPE */
type0:	movl	typer0(%u),r0
	jsb	*(r0)+
8:	rsb

	.byte	8f-type
9:	.word	9b-fdc4
9:	.set	fdc4,9b
	.long	INL+020025014540	/* TYPE */
type:	movl	typer(%u),r0
	jsb	*(r0)+
8:	rsb

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	01425014060		/* EXPECT */
expect:	movl	reader(%u),r0
	movl	-4(r0),r1
	jmp	(r1)


9:	.word	9b-fdc1
9:	.set	fdc1,9b
	.long	014510252550		/* QUERY  (read 80 char) */
query:	movl	msgbuf(%u),-(%s)
	movzbl	$TBUFSIZ,-(%s)
	brb	expect


9:	.word	9b-fdcb
9:	.set	fdcb,9b
	.long	020201442430		/* KEY (read 1 char RAW NOECHO) */
	bsbw	skey
	bsbw	key0
	bsbw	ekey
	rsb

9:	.word	9b-fdc5
9:	.set	fdc5,9b
	.long	020120446440		/* EMIT  (type 1 char from stack) */
	movb	(%s),(%h)
	movl	%h,(%s)
	movl	$1,-(%s)
	jbr	type

X/* ========================================================================= 
 *
 *  Character string handling.
 *
 *      Character strings are stored in-line if 5 chars or less 
 *        otherwise they reside in a temporary file (usually file descriptor 4) 
 *
 *   handle escaped sequences
 *	chars preceded by a backslash are interpreted as control characters
 *	\b	=	backspace
 *	\e	=	escape char (octal 033)
 *	\f	=	form feed
 *	\n	=	new line (line-feed)
 *	\r	=	carriage return
 *	\t	=	tab
 *	\?	=	rubout character (octal 0177)
 *	\\	=	backslash character
 *	\nnn	=	nnn is up to 3 digit octal number.
 *	\X	=	X is a capital letter. Value of X with most significant
 *			3 bits removed,  (i.e. \C = "control C")
 *
 *	all  other characters following a backslash yield an undefined result.
 *	
 * r0  string in		r1  string out
 * r2  end of string		r3  working char
 * r4  number accumulator	r5  digit & table counter
 */
	.set	NESCTB,8
esctb1:	.byte	'?,0x5c,'b,'e,'f,'n,'r,'t
esctb2:	.byte	0177,0x5c,010,033,014,012,015,011

X/*
 *	addr  --- 
 *	addr = address of string (length in 1st byte)
 */

escap:	movl	(%s)+,r0
	movzbl	(r0)+,r2
	beql	escqit
	addl2	r0,r2
	movl	r0,r1
esclup:	movzbl	(r0)+,r3
	cmpb	r3,$0x5c	/* escaped? */
	bneq	escelp
	movzbl	(r0)+,r3
	cmpb	r3,$'0
	blssu	escndg
	cmpb	r3,$'7
	bgtru	escndg

	clrl	r4
	movl	$3,r5
escdig:	mulb2	$8,r4		/* Convert up to 3 digit octal sequence */
	subb2	$'0,r3
	addb2	r3,r4
	movzbl	(r0)+,r3
	cmpb	r3,$'0
	blssu	escedg
	cmpb	r3,$'7
	bgtru	escedg
	sobgtr	r5,escdig

escedg:	decl	r0
	movl	r4,r3
	brb	escelp

escndg:	movl	$(NESCTB-1),r5
escklp:	cmpb	r3,esctb1[r5]
	beql	esckch
	sobgeq	r5,escklp

	bicb2	$0xe0,r3		/* remove top bits */
	brb	escelp
	
esckch:	movb	esctb2[r5],r3
escelp:	movb	r3,(r1)+
	cmpl	r0,r2
	blssu	esclup

	subl2	-4(%s),r1		/* compute string length */
	decl	r1
	movb	r1,*-4(%s)
escqit:	rsb

X/*
 * This is the check for a string constant in the goloop
 *	string constants begin with an (otherwise ignored) backslash
 *	string to test initially at (%h)
 *
 *	dummy --- flag
 * 		flag = 0 if not string = addr of string if string
 */
strcon:	clrl	(%s)
	tstb	(%h)		/* special test for null string */
	beql	1f
	cmpb	1(%h),$0x5c	/* begins with backslash? */
	bneq	1f
	moval	1(%h),r0	/* skip over backslash */
	subb3	$1,(%h),(r0)	/* decrement and move length byte */
	movl	r0,(%s)
	movl	r0,-(%s)
	movl	r0,-(%s)
	bsbw	escap
	bsbw	spush
	tstl	state(%u)
	beql	1f
	bsbw	sliter
1:	rsb

X/*  Fetch String */

str:	bsbw	count
	tstb	(%s)		/* in-line string? */
	blss	1f		/* no, retrieve from disk? */
	movq	(%s),-(%s)	/* 2dup */
	bsbw	s.at		/* reserve space on string stack */
	addl2	(%s)+,(%s)	/* return addr of end of string */
	rsb

1:	bicb2	$0x80,(%s)	/* clear flag bit */
	movq	(%s),-(%s)	/* 2dup */
	bsbw	s.at		/* reserve space on string stack */
	pushl	(%s)+		/* save count for read call */
	movl	(%s),r2		/* recall in-line address */
	addl2	$4,(%s)		/* return location after offset */
	movl	(r2)+,-(%s)	/* location in file for seek call */
	clrl	-(%s)
	movl	msgfil,-(%s)
	bsbw	s_seek		/* position file to beginning of message */
	tstl	(%s)+
	jlss	unxerr
	moval	1(%c),-(%s)	/* get address  for read call */
	movl	(%r)+,-(%s)	/* get saved count */
	movl	msgfil,-(%s)	/* file descriptor */
	bsbw	s_read
	tstl	(%s)+
	jlss	unxerr
	rsb

X/* Compile a Character string */

slit:	movl	%c,-(%s)	/* save string stack top */
	bsbw	sdrop		/* remove knowledge of string */
	movl	(%s)+,r2	/* recall string */
	movzbl	(r2),r3		/* get length */
	cmpb	r3,$MAXSTR	/* less than max in-line characters? */
	bgtru	1f		/* no, store on `message' file */
	incl	r3		/* include len byte itself */
	movc3	r3,(r2),(%h)	/* copy string to dictionary */
	movl	r3,%h
	rsb

1:	bisb3	$0x80,(r2)+,(%h)+	/* len has flag that str is disk resid*/
	clrl	-(%s)
	movl	$2,-(%s)
	movl	msgfil,-(%s)
	bsbw	s_seek
	movl	(%s)+,(%h)+
	jlss	unxerr

	movl	r2,-(%s)	/* set up addr for write call */
	movl	r3,-(%s)	/* set up length of string for write call */
	movl	msgfil,-(%s)
	bsbw	s_write		/* write out message */
	tstl	(%s)+
	jlss	unxerr
	rsb

X/* A Reference to this code fragment is compiled into a sliteral */
stri:	movl	(%r)+,-(%s)
	bsbw	str
	jmp	*(%s)+

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	IM+02520446100		/* SLITERAL */
sliter:	moval	stri,-(%s)
	bsbw	_jbsb
	bsbw	slit
	rsb
X/*
 * 	Compile a string-storing word
 *
 *	  Format of String Reference:
 *
 *	   <len><string>  in-line reference (parity bit set in 1st char)
 *   or	   <len><offset>  disk reference  (offset is 4 bytes long)
 *
 *	FORTH call to string defining word
 *
 *	: def  ...  char CDOES> ...... ;
 *		when `def string' appears in a definition a reference to
 *		`string' is compiled such that when that word is executed the
 *		stuff after CDOES> is executed with `string' on the string
 *		stack.  `def string' can also be executed directly, rather than
 *		appearing in a definition.  The execution of the stuff after
 *		CDOES> with `string' on the string stack will then take place
 *		immediately.
 *
 *	Code generated by string reference compiling word CDOES>
 *		jbsb	csav
 *		brb	1f
 *		jbsb	cget
 *	1:	  words to be executed to process the string ...
 */

cget:	movl	4(%r),-(%s)	/* get string location */
	bsbw	str		/* retrieve string location */
	movl	(%s)+,4(%r)	/* grandfather def. returns past string end */
	rsb

csav:	bsbw	word
	bsbw	escap		/* check for escaped characters */
	movl	%h,-(%s)
	bsbw	spush		/* push string on string stack */
	blbc	state(%u),1f	/* if no compile mode, exit code that follows */
	addl3	$2,(%r)+,-(%s)	/* compile call to past brb instruction */
	bsbw	_jbsb
	bsbw	slit		/* compile string */
1:	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	IM+011424742060	/* CDOES>  (compile string reference word) */
cdoes:	moval	csav,-(%s)
	bsbw	_jbsb		/* compile call to csav */
	movw	$0x11,(%h)+	/* compile brb instruction */
	pushl	%h
	moval	cget,-(%s)	/* compile call to cget */
	bsbw	_jbsb
	movl	(%r)+,r0	/* recall saved position */
	subb3	r0,%h,-(r0)	/* calculate displacement */
	rsb

9:	.word	9b-fdc2
9:	.set	fdc2,9b
	.long	IM+020202020210	/*  "  (push literal string on string stack) */
dqot:	movl	$042,-(%s)
	bsbw	csav
	brb	1f
	bsbb	cget
1:	rsb

stovf:	movl	$E.SOVER,r0
	jbr	abort

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	04115250150	/* SPUSH  push string onto string stack */
spush:	movl	(%s)+,r0
	movzbl	(r0),r1		/* get length */
	subl3	r1,%c,r2	/* get beginning of string */
	tstw	-(r2)
	cmpl	r2,fsbot(%u)	/* overflowed into flt stack area (or beyond)?*/
	blequ	stovf
	movl	r2,%c
	incl	r1		/* include length byte */
	movc3	r1,(r0),(r2)	/* move string on to stack */
	clrb	(r3)		/* add final null byte */
	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020202000120	/* S@   addr len S@ */
s.at:	movl	(%s)+,r1
	bgeq	1f
	tstl	(%s)+
	rsb
1:	cmpl	r1,$0xff
	bleq	2f
	movzbl	$0xff,r1
2:	subl3	r1,%c,r2	/* get beginning of string */
	tstw	-(r2)
	cmpl	r2,fsbot(%u)	/* overflowed into flt stack area (or beyond)?*/
	blequ	stovf
	movl	r2,%c
	movb	r1,(r2)+	/* put length byte in place */
	movc3	r1,*(%s)+,(r2)	/* move string on to stack */
	clrb	(r3)		/* add final null byte */
	rsb

X/*  Probe downward in string stack. */

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	07134742150	/* SDOWN  probe downward in string stack */
sdown:	movl	(%s)+,r0	/* get arg */
	movzbl	(r0)+,r1	/* get len */
	addl2	r1,r0
	incl	r0		/* skip over null byte */
	cmpl	r0,ssbot(%u)	/* end of string below stack bottom? */
	blequ 	2f		/* no */
	movl	$E.SBAD,r0
	cmpl	%c,ssbot(%u)	/* string stack at bottom? */
	bneq	0f
	movl	$E.SEMPT,r0	/* yes, stack string stack Empty. */
0:	jbr	abort
2:	movl	r0,-(%s)
	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	010075102150		/* SDROP  drop item from string stack */
sdrop:	movl	%c,-(%s)
	bsbb	sdown
	movl	(%s)+,%c
	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020202020520		/* S!  pop from c and store in array */
s.stor:	pushl	%c
	bsbb	sdrop
	movl	(%r)+,r0
	movzbl	(r0)+,r1
	movl	(%s)+,r2
	movc5	r1,(r0),$BLANK,r2,*(%s)+
	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	012071247450		/* COUNT  return len and addr */
count:	movzbl	*(%s)+,r0
	incl	-(%s)
	movl	r0,-(%s)
	rsb

	.byte	8f-0f
9:	.word	9b-fdc7
9:	.set	fdc7,9b
	.long	INL+020201151630	/* 'SS  addr of strin stack top */
0:	movl	%c,-(%s)
8:	rsb

	.byte	8f-0f
9:	.word	9b-fdc7
9:	.set	fdc7,9b
	.long	INL+020205151640	/* 'SS!  change string stack top */
0:	movl	(%s)+,%c
8:	rsb

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020101242140		/* SDUP */
sdup:	movl	%c,-(%s)
	jbr	spush

9:	.word	9b-fdc3
9:	.set	fdc3,9b
	.long	020202027120		/* S.  print top item on str stack */
sdot:	movl	%c,-(%s)
	bsbw	sdrop
	bsbb	count
	jbr	type

9:	.word	9b-fdce
9:	.set	fdce,9b
	.long	IM+020202021220		/* ."  print a message */
	movl	$042,-(%s)
	bsbw	csav
	brb	1f
	bsbw	cget
1:	bsbb	sdot
	rsb

//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./vaxforth/forth1.S
	/bin/echo -n '	'; /bin/ls -ld ./vaxforth/forth1.S
fi
exit
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls