	.TITLE	MICRO ASSEMBLER
	.SBTTL	YET TO BE IMPLEMENTED FEATURES

; REGISTER TYPE SYMBOL HANDLING IN EXPRESSIONS AND OPERANDS
; OPCODE CLASS MACROS
; MULTIPLE INPUT FILES
; FIX /N SWITCH FOR BITMAP
; GOOD ERRORS IF NO WCS AND /W
; LOCAL LABELS
; MULTIPLY
; DIVIDE
	.SBTTL	MACRO DEFINITIONS

	.MACRO	RETURN
RETURN=.
	RTS	PC
	.ENDM

	.MACRO	CALL SUB
	JSR	PC,SUB
	.ENDM

	.MACRO	BEAR	LOCS
V=0
.IRP	L,<LOCS>
B=1
.REPT	<L&7>
B=B+B
.ENDR
V=V!B
LC=L
.ENDR
$=.
.=BEARTP+<LC/10>
	.BYTE	V
.=$
	.ENDM	BEAR

	.MACRO	BYTES	COUNT, CHAR
	.REPT	COUNT
	.BYTE	CHAR
	.ENDR
	.ENDM

	.MACRO	ERROR CHAR, MESSG
	JSR	R5,ERROR
	.WORD	''CHAR
	.PSECT	ERRS
	FOO=.
	.ASCIZ	/MESSG/
	.PSECT
	.WORD	FOO
	.ENDM

	.MACRO	OP	NAME,CLASS,OPCODE
	.ASCII	/NAME/
	.BYTE	OPCODE/400&377,CLASS
	.ENDM

	.MACRO	SYMBOL	NAME, VALUE, BITS
	.ASCII	/NAME/
	.WORD	BITS
	.WORD	VALUE
	.ENDM

	.MCALL	.CSIGEN, .EXIT, .READW, .WRITW, .PRINT,	.CSISPC
	.MCALL	.SETTOP, .CLOSE, .WAIT,	.RCTRL,	.GTLIN,	.CHAIN
	.MCALL	.DATE,	.GTIM,	.GVAL,	.LOCK,	.UNLOC,	.ENTER

	.NLIST	BEX
	.ENABL	LC
	.SBTTL	BIT DEFINITIONS

; CHARACTERS USED
TAB=	11	;HORIZONTAL TAB
CR=	15	;CARR. RETURN
LF=	12	;LINE FEED
FF=	14	;FORM FEED

; SYMBOL TABLE ENTRY OFFSETS
SY.ID=	0	;SYMBOL NAME
SY.ADR=	6	;ADDRESS
SY.STS=	10	;SYMBOL STATUS (SEE BELOW)
SY.LCL=	12	;LOCAL BLOCK POINTER

; SYMBOL STATUS BITS
ST.DFN=	1	;DEFINED
ST.MDF=	2	;MULTIPLY DEFINED
ST.EQU=	4	;SYMBOL EQUATED
ST.REG=	10	;REGISTER SYMBOL
ST.TRN=	20	;TRANSLATION SYMBOL
ST.EXT=	40	;EXTENSION BITS SYMBOL

; LEXICAL TYPES
LX.SYM=	0	;A SYMBOL
LX.NUM=	1	;A NUMBER
LX.SPC=	-1	;A SPECIAL CHARACTER

; OPCODE TABLE OFFSETS
OP.SYM=	0	;SYMBOLIC INSTRUCTION NAME
OP.INS=	6	;OPCODE INSTRUCTION CODE
OP.CLS=	7	;INSTRUCTION CLASS

; OPCODE CLASSES
CL.JMP=	0	;JUMP (11 BIT ADDRESS)
CL.RFS=	1	;NO OPERANDS (RFS, ETC.)
CL.CJM=	2	;CONDITIONAL JUMPS (8 BIT PAGE ADDRESS)
CL.LIT=	3	;LITERAL (8 BIT AND REGISTER)
CL.BFL=	4	;B FIELD ONLY
CL.AFL=	5	;A FIELD ONLY
CL.REG=	6	;REGISTER-REGISTER (A AND B REGS)
CL.LOC=	7	;LOCATION COUNTER DEFINITION
CL.END=	10	;END STATEMENT
CL.RDF=	11	;REGISTER DEFINITIONS
CL.TRN=	12	;TRANSLATION PSEUDO OP
CL.IW=	13	;INPUT WORD OR BYTE OPERATION
CL.TTL=	14	;TITLE
CL.SBT=	15	;SUBTITLE
CL.PAG=	16	;PAGE OPCODE
CL.DUM=	17	;DUMMPY OPCODE, NO OPERANDS
CL.JSR=	20	;JSR OPCODE
CL.NXT=	21	;NXT OPCODE
CL.MOD=	22	;MODEE OPCODE

; WCS BUS ADDRESSES
WCSSTS=	177540	;WCS CONTROL & STATUS (ALSO ADRS)
	WCS$EN=	010000	;ENABLE BIT
WCSLOW=	177542	;WCS DATA, LOW 16 BITS
WCSHGH=	177544	;WCS DATA, HIGH 8 BITS
CONFIG=	300	;OFFSET TO RT-11 CONFIGURATION WORD
CLK50=	000040	;50-CYCLE CLOCK BIT IN CONFIG
EMTERR=	52	;RT-11 EMT ERROR BYTE
TGLBIT=	34	;WCS ADDRESS TOGGLE TO 2ND HALF OF MODE II
	.SBTTL	DATA AREAS

S::
OPL:	.WORD	0	;OPCODE FORMED HERE
OPH:	.WORD	0	;  (HIGH WORD)
OPCLS:	.WORD	0	;OPCODE CLASS
TRANPR:	.WORD	0	;TRANSLATION FIELD FOUND FLAG (<>0 IF FOUND)
OLDLOC:	.WORD	0	;PREVIOUS LOC ADDRESS
LOC:	.WORD	0	;LOCATION COUNTER
LINCNT:	.WORD	0	;LINES LEFT ON CURRENT PAGE
LINE:	.WORD	0	;CURRENT LINE NUMBER
PAGE:	.WORD	0	;CURRENT PAGE NUMBER
PASS:	.WORD	0	;ASSEMBLY PASS
SYTBGN:	.WORD	0	;STARTING ADDRESS OF SYMBOL TABLE
SYTEND:	.WORD	0	;SYMBOL TABLE END
STIME:	.BLKW	2	;TIME-OF-DAY
CHKSUM:	.WORD	0	;CHECKSUM FOR OBJ RECORD
TXTPTR:	.WORD	0	;OBJ DATA RECORD POINTER
OLDFMT:	.WORD	0	;SET IF TRANS FIELD BEFORE EXTEN BITS
EXTEN1:	.WORD	0	;ROUTINE ADDR TO HANDLE 1ST EXTEN FLD
EXTEN2:	.WORD	0	;ROUTINE ADDR TO HANDLE 2ND EXTEN FLD
MODE:	.WORD	0	;WCS ADDRESSING MODE
RAMADR:	.WORD	0	;PHYSYCAL WCS RAM ADDR FOR INST

OPNDFL:	.WORD	0	;SET IF OPERAND FOUND
LOCADR:	.WORD	0	;ADDRESS TO FILL IN LOC FIELD
ERRPNT:	.WORD	0	;POINTER TO CURRENT ERROR LOCATION
ERRCNT:	.WORD	0	;TOTAL ERROR COUNT FOR PROGRAM SO FAR
STMERC:	.WORD	0	;ERROR COUNT FOR THIS STATEMENT
REPEAT:	.WORD	0	;REPEAT THE LAST LEXICAL SCAN FLAG
RESULT:	.WORD	0	;EXPRESSION EVALUATION RESULT
MSGPTR:	.WORD	0	;TEXT ERROR BUFFER POINTER
LISTFL:	.WORD	0	;SET IF LISTING FILE
OBJFL:	.WORD	0	;SET IF OBJ FILE SPECIFIED
BITFL:	.WORD	0	;BITMAP DESIRED FLAG
CRFFL:	.WORD	0	;CROSS-REFERENCE DESIRED FLAG
TTYFL:	.WORD	0	;NARROW LISTING DESIRED FLAG
WCSFL:	.WORD	0	;SET IF LOAD INTO WCS DESIRED
EOF:	.WORD	0	;SET IF END OF FILE ON READ
SAVESP:	.WORD	0	;SAVEED COPY OF SP FOR EXPRESSIONS
PARLVL:	.WORD	0	;CURRENT PAREN LEVEL, STARTS AT 0
LINSIZ:	.WORD	0	;LINE SIZE FOR LISTING

ID:	.BLKB	6	;6 CHARACTER NAMES
	.BYTE	40	;STOPPER FOR ERROR MESSAGES INSERTING SYMBOL


; I/O LINE FORMAT
	.EVEN
OUTLN:	.BLKB	4	;SPACE FOR ERRORS
	.BLKB	1
OUTLIN:	.BLKB	5	;SPACE FOR LINE NUMBER
	.BLKB	1
OUTLC:	.BLKB	5	;OUTPUT LOCATION COUNTER
	.BLKB	1
OUTOPH:	.BLKB	3	;HIGH ORDER OPCODE FIELD
	.BLKB	1
OUTOPL:	.BLKB	6	;LOW ORDER OPCODE FIELD
	.BLKB	1
IN:	.BLKB	110.	;INPUT LINE BEING ASSEMBLED
LINEND:
	.EVEN

; I/O BUFFERS
CRFBLK:	.WORD	0	;CRF BLOCK NUMBER
CRFPTR:	.WORD	0	;CREF OUTPUT BUFFER POINTER
OBJBLK:	.WORD	0	;OBJ BLOCK NUMBER
OBJPTR:	.WORD	0	;OBJ BUFFER POINTER
INBLK:	.WORD	0	;INPUT BLOCK NUMBER
OUTBLK:	.WORD	0	;OUTPUT BLOCK NUMBER
INPTR:	.WORD	0	;INPUT BUFFER POINTER
OUTPTR:	.WORD	0	;OUTPUT BUFFER POINTER
TITLEN=	30.
	.BYTE	FF
TITLE:	.BLKB	TITLEN	;TITLE TEXT
	.EVEN
SBTLEN=	50
SBTTL:	.BLKB	SBTLEN	;SUBTITLE TEXT
INBUF:	.BLKW	256.	;INPUT SOURCE BUFFER
OUTBUF:	.BLKW	256.	;OUTPUT BUFFER
OBJBUF:	.BLKW	256.	;OBJ BUFFER
CRFBUF:	.BLKW	256.	;CREF BUFFER
CRFEND:

BITMAP:	.BLKB	2000/10	;USED MEMORY BITMAP
BEARTP:	.REPT	4000/10	;BITMAP OF PREDEFINED CTRL CHIP TRANSLATIONS
	.BYTE	0
	.ENDR
BUCKET:	.BLKW	28.	;SYMBOL TABLE BUCKET LIST (A-Z, ., $) 
BCKEND:			;END OF BUCKETS
BCKPTR:	.BLKW		;CURRENT BUCKET (PRTSYM)

AREA:	.BLKW	12	;EMT AREA BLOCK
TOP:	.WORD	0	;HIGHEST AVAILABLE MEMORY LOCATION
ERRBUF:	.BLKW	100	;ERROR MESSAGE BUFFER
	.SBTTL	ASSEMBLE ONE LINE

; ASM
; ASSEMBLE ONE LINE OF MICRO CODE.
	.ENABL	LSB
ASM:	INC	LINE		;NEXT LINE PLEASE
	CALL	READ		;READ A LINE
	MOV	LOC,LOCADR	;SAVE LC AT START OF LINE
	MOV	#IN,R5		;R5 -> INPUT LINE
	TST	EOF
	BEQ	15$		;IF NOT AT END OF FILE
	ERROR	E,<Missing or illegal END statement>
	MOV	#CL.END,R1	;DEFAULT TO END STATEMENT
	MOVB	#CR,(R5)+	;BUILD A NULL LINE
	MOVB	#LF,(R5)+
	CLRB	(R5)+
	BR	6$
15$:	CALL	LEX		;GET 1ST LEXEME
	CMP	R1,#LX.SYM
	BNE	4$		;IF NOT A SYMBOL, CANT BE A LABEL
	CALL	STNF		;SKIP TO DELIMITER
	CMPB	@R5,#'=
	BNE	12$		;IF NOT EQUATE
	INC	R5		;PASS EQUAL
	CALL	ENTERD		;LOOK UP SYMBOL IN TABLE
	BIT	#ST.DFN,SY.STS(R0) 
	BNE	13$		;IF SYMBOL PREVIOUSLY DEFINED
	MOV	R0,-(SP)	;EVALUATE THE EXPRESSION OPERAND
	CALL	EXPR
	MOV	(SP)+,R0	;R0->SYMBOL ON LEFT OF EQUATE
	MOV	R1,SY.ADR(R0)	;PUT IN EXPRESSION VALUE
	MOV	R1,LOCADR	;PRINT EQUATE RESULT FOR LC
	BIS	#ST.EQU,SY.STS(R0) ;MAKE IT EQUATED
	MOV	#-1,OPNDFL	;USE SAME LISTING MODE AS PSEUDO OPS
	BR	14$
12$:	CMPB	@R5,#':
	BNE	4$		;  CHECK FOR LABEL
	INC	R5		;SKIP OVER THE DELIMITER
	CALL	ENTERD		;ENTER THE SYMBOL IN THE TABLE
	BIT	#ST.DFN!ST.EQU,SY.STS(R0)
	BEQ	23$		;IF LABEL ISNT DEFINED YET...OK
	TST	PASS
	BNE	23$		;IF MULT DEFN ON PASS 2, SKIP IT
	BIS	#ST.MDF,SY.STS(R0) ;MAKE IT MULTIPLY DEFINED
23$:	BIT	#ST.MDF,SY.STS(R0)
	BEQ	2$		;IF NOT MULTIPLE DEFINITION
	ERROR	M, <Multiple definition of label "@">
	BR	3$
13$:	ERROR	M,<Symbol "@" previously defined as label>
	BR	7$
2$:	MOV	LOC,SY.ADR(R0)	;PUT LOCATION COUNTER IN AS VALUE
	BIS	#ST.DFN,SY.STS(R0) ;MAKE IT DEFINED
3$:	CALL	LEX		;GET THE OPCODE FIELD
4$:	CMP	R1,#LX.SYM
	BNE	8$		;IF NOT A SYMBOL, THEN NOT OPCODE
5$:	CALL	OPCODE		;PROCESS THE OPCODE
	BEQ	6$		;IF OPCODE IS IN TABLE
	ERROR	O,<Opcode "@" not found>
	MOV	#CL.RFS,R1	;DEFAULT CLASS FOR OPCODE
6$:	MOV	R1,OPCLS	;HANG ONTO THE CLASS FOR LATER
	INC	LOC		;BUMP LOCATION COUNTER FOR OPCODES
	MOV	#1,OPNDFL	;SET TO PRINT DATA
	MOV	PASS,R0
	BISB	PSEUDO(R1),R0
	BEQ	7$		;IF PASS1 AND 1 WORD INST, DONT EVAL
				; OPERANDS SINCE THEY CANT EFFECT
				; ANYTHING AT THIS POINT.
16$:	TSTB	PSEUDO(R1)
	BEQ	19$		;IF NOT PSEUDO OP
	MOV	#-1,OPNDFL	;SET LISTING CONTROL
	DEC	LOC		;PSEUDO OPS DONT INCR LC
19$:	CMP	R1,#CL.RFS
	BNE	21$		;IF INSTUCTION HAS OPERANDS
	CALL	STNF
	CMP	R0,#CR
	BEQ	10$		;IF END OF LINE
	CMPB	R0,#';
	BEQ	10$		;IF END OF LINE
	BR	20$		;DON'T LOOK FOR COMMA BEFORE EXT FLD
21$:	ASL	R1
	CALL	@OPDISP(R1)	;BRANCH ON OPCODE CLASS
14$:	CALL	STNF		;CHECK FOR A HIGH ORDER WORD
	CMPB	R0,#',
	BNE	10$		;IF NOT COMMA, SKIP IT
	INC	R5		;PASS IT UP
20$:	TST	OPNDFL
	BGT	1$		;IF INSTRUCTION
	ERROR	H,<Illegal extension bits on pseudo-op>

; GET EXTENSION FIELD IN WHATEVER ORDER IT IS IN
1$:	CALL	STNF
	CMPB	R0,#',
	BEQ	22$		;IF SKIPPING THIS FIELD
	CALL	@EXTEN1		;GET THE 1ST EXTEN FIELD
	CALL	STNF
	CMPB	R0,#',
	BNE	10$		;IF NO 2ND FIELD
22$:	INC	R5		;PASS THE COMMA
	CALL	@EXTEN2		;GET THE 2ND EXTENSION FIELD
10$:	CALL	LEX		;GET NEXT TOKEN

8$:	CMP	R1,#LX.SPC
	BNE	9$		;IF NOT SPECIAL, THEN NOT EOL
	CMP	R0,#';
	BEQ	7$		;IF END OF LINE COMMENT
	CMP	R0,#LF
	BEQ	7$
	CMP	R0,#CR
	BEQ	7$		;IF CR EOL
9$:	ERROR	S,<Syntax error>
7$:	CALL	OUTWRD		;OUTPUT THE WORD IF NEEDED
	CALL	PRINT		;PRINT THE LINE IF CORRECT PASS
	RETURN
	.DSABL	LSB

; OPCODE DISPATCH TABLE
OPDISP:	.WORD	CLS0, CLS1, CLS2, CLS3, CLS4, CLS5, CLS6
	.WORD	CLS7, CLS8, CLS9, CLS10, CLS11, CLS12, CLS13
	.WORD	CLS14, CLS8, CLS15, CLS16, CLS17

; BYTE IN THIS TABLE S NONZERO IF CORRRESPONDING OPCODE IS A
; PSEUDO OP AND DOESNT GENERATE ANY CODE.  THESE OPCODES
; MUST BE COMPLETELY EVALUATED ON THE FIRST AND SECOND PASSES.
PSEUDO:	.BYTE	0,0,0,0,0,0,0
	.BYTE	1,1,1,1,0,1,1
	.BYTE	1,1,0,1,1
	.EVEN


; EVALUATE TRANSLATION FIELD
	.ENABL	LSB
TRNFLD:	MOV	R5,TRANPR	;SAVE PTR TO TRAN FIELD
	MOVB	@R5,R0		;GET 1ST CHARACTER OF TRANSLATION
	TSTB	CLASS(R0)
	BNE	17$		;IF NOT ALPHABETIC
	CALL	LEX		;COLLECT TRANSLATION NAME
	CMP 	R1,#LX.SYM
	BEQ	18$		;IF REALLY A SYMBOL NAME
	ERROR	T,<Illegal Translation name>
	BR	17$
18$:	CALL	ENTER		;ENTER TRANSLATION NAME IN SYMBOL TBL
	BIT	#ST.TRN,SY.STS(R0)
	BNE	17$		;IF IS DEFINED AS TRANSLATION
	ERROR	T,<Symbol "@" not defined as a Translation>
	BIS	#ST.TRN,SY.STS(R0) ;MAKE IT A TRANSLATION SYMBOL
17$:	SUB	R5,TRANPR	;SET FLAG <> 0 IF TRANSLATION PRESENT
	RETURN
	.DSABL	LSB


; GET EXTENSION BITS FIELD AND PUT THEM IN HIGH ORDER WORD
	.ENABL	LSB
EXTFLD:	CALL	EXPR		;EVALUATE USER BITS
	CMP	R1,#377
	BLOS	11$		;IF FITS IN A BYTE
	ERROR	H,<Extension field value exceeds 8 bits>
	MOV	RESULT,R1
	BIC	#^C<377>,R1
11$:	BIS	R1,OPH
	RETURN
	.DSABL	LSB
	.SBTTL	SPECIFIC OPCODE CLASS PROCESSING

; JUMPS
; 11 BIT JUMP ADDRESS IS THE ONLY OPERAND
CLS0:	CALL	EXPR		;EVALUATE THE AADDRERSS
	MOV	R1,R0
	BIC	#10000,R1	;GET RID OF MODE 2 BIT
	CMP	R1,#3777
	BHI	CLS0B		;IF ADDRESS TOO BIG
	ADD	LOCADR,R0
	BIT	#10000,R0
	BEQ	CLS0A		;IF NOT GOING ACROSS A PAGE (MODE II)
	BIS	#TGLBIT,OPH	;SET TO TOGGLE TO OTHER PAGE
	BIT	#1,OPH
	BEQ	CLS0A		;IF NOT A JSR AND TOGGLE
	ERROR	A,<Possible subroutine return linkage error>
CLS0A:	BIS	R1,OPL		;ADD THE OPERAND TO THE OPCODE
	RETURN
CLS0B:	ERROR	A,<Address out of range>
CLS8:
CLS1:	RETURN		;NO OPNDS AND END STMT MERGE HERE

; CONDITIONAL JUMPS
; TAKE THE ADDRESS AND CHECK IF ITS IN THE SAME PAGE
; AS THE CURRENT LC.  IF IT IS, THEN USE THE LOW ORDER
; BITS OF IT AS THE OPERAND
CLS2:	CALL	EXPR		;GET THE LABEL
	BIC	#377,R1		;ISOLATE THE PAGE BITS
	MOV	LOC,R2
	BIC	#377,R2		;ISOLATE PAGE BITS ON LOC
	CMP	R1,R2
	BNE	1$		;IF OFF PAGE REFERENCE
	MOV	RESULT,R1	;GET ADDRESS BACK
	BIC	#^C<377>,R1
	BR	CLS0A		;COMBINE PAGE ADDRESS WITH OPCODE

1$:	ERROR	P,<Conditional jump to off-page label>
	RETURN

; LITERAL INSTRUCTIONS
; THESE INSTRUCTIONS HAVE AN 8 BIT LITERAL AND A REGISTER
	.ENABL	LSB
CLS3:	CALL	EXPR		;GET THE LITERAL VALUE
	CMP	R1,#377
	BLOS	2$		;IF LITERAL <= 8 BITS AND POSITIVE
	ADD	#400,R1		;MAKE LEGAL NEG LITERALS POSITIVE
	BMI	1$		;IF NOT POS, THEN ILLEGAL HIGH BYTE
2$:	ASL	R1
	ASL	R1		;MOVE IN POSITION
	ASL	R1
	ASL	R1
	BIS	R1,OPL		;PUT LITERAL IN INSTRUCTION
	CALL	INPCOM		;GET COMMA SEPARATOR
	BR	CLS5		;ACCEPT A FIELD REGISTER

1$:	ERROR	L,<Literal value exceeds 8 bits>
	CLR	R1		;USE ZERO
	BR	2$
	.DSABL	LSB

; B FIELD ONLY
; ONLY ONE REGISTER IS USED, THE B REGISTER
CLS4:	CALL	REG		;GET REGISTER
	ASL	R1
	ASL	R1		;INTO B FIELD
	ASL	R1
	ASL	R1
	BR	CLS0A		;MERGE INTO OPCODE

; A FIELD ONLY
; ONLY THE A REGISTER FIELD IS REFERENCED
CLS5:	CALL	REG		;GET B REGISTER FIELD
	BR	CLS0A		;OR INTO OPERAND FIELD

; IW AND IB OPERATIONS
; THESE OPCODES HAVE AN OPTIONAL B FIELD.  IF IT IS LEFT OUT
; THEN A LEADING COMMA IS USED IN ITS PLACE.
CLS11:	CALL	STNF		;SKIP TO COMMA OR WHATEVER
	CMPB	R0,#',
	BEQ	CLS6A		;JUST EVALUATE 2ND OPERAND

; REGISTER TO REGISTER INSTRUCTIONS
; BOTH THE B AND THE A FIELD ARE THE OPERANDS IN THESE INSTRUCTIONS
CLS6:	CALL	CLS4		;GET B REGISTER
CLS6A:	CALL	INPCOM		;  THEN THE DELIMITER
	BR	CLS5		;THEN THE A FIELD

; LOC PSEUDO OP
; SET THE LOCATION COUNTER TO THE VALUE OF THE OPERAND
; SET UP OBJADR IN OBJ TEXT BLOCK ON LOCS
	.ENABL	LSB
CLS7:	CALL	STNF
	CMPB	R0,#CR
	BEQ	1$		;IF NO LOC ADDR THEN USE PREVIOUS
	CMPB	R0,#';
	BNE	2$		;IF LOC EXPR
1$:	MOV	OLDLOC,R1	;USE PREVIOUS LOC ADDRESS
	BR	3$

2$:	MOV	LOC,OLDLOC	;SAVE PREVIOUS LOCATION COUNTER
	CALL	EXPR		;GET THE NEW ORIGIN
	CALL	CHKMOD		;SEE IF LEGAL ADDRESS FOR WCS MODE

CLS7A:
3$:	MOV	R1,LOC		;SET UP NEW LOCATION COUNTER
	MOV	R1,LOCADR	;USE RESULT FOR LC FIELD
	TST	OBJFL
	BEQ	RETURN		;IF NO OBJ FILE
	TST	PASS
	BEQ	RETURN		;IF NOT OUTPUTTING ON THIS PASS
	MOV	R1,-(SP)
	CMP	TXTPTR,#OBJTXT
	BEQ	4$		;IF CURRENT OBJ RECORD IS EMPTY
	MOV	#TXTREC,R1
	MOV	BYTCNT,R3	;WRITE THIS RECORD
	CALL	OBJWRT
	MOV	#10,BYTCNT	;INIT BYTE COUNT FOR BLOCK
	MOV	#OBJTXT,TXTPTR	;RESET POINTER TO OBJ RECORD
4$:	ASL	@SP		;COMPUTE NEW LOC
	ASL	@SP
	ADD	#1000,@SP
	MOV	(SP)+,OBJADR	;USE IT FOR NEXT OBJ BLOCK
	RETURN
	.DSABL	LSB

; NXT2-NXT400 OPCODES
; INCREMENT THE LC TO THE NEXT ADDRESS WHICH IS THE POWER 
; OF 2 SPECIFIED IN THE INSTRUCTION.
CLS16:	CLR	R1
	BISB	OPL+1,R1	;R1 = NXT OPERAND - 1
	BIT	R1,LOC
	BEQ	RETURN		;IN NOTHING TO DO, ALREADY THERE
	BIS	LOC,R1		;PUT IN THE LOWER BITS
	INC	R1		;AND BUMP THE NEXT BIT OVER
	BR	CLS7A		;MERGE WITH LOC CODE

; REG PSEUDO OP
; DEFINE REGISTERS BY TAKING THE NAME AND NAME'L AND NAME'H
; AND DEFINING WITH THE APPROPRIATE OFFSETS
	.ENABL	LSB
CLS9:	CALL	LEX		;GET THE REGISTER NAME
	CMP	R1,#LX.SYM
	BEQ	1$		;IF A SYMBOL
	ERROR	R,<Illegal register name>
	RETURN
1$:	CALL	REGENT		;ENTER REGISTER NAME INTO SYT
	MOV	R0,-(SP)	;SAVE SYMBOL ADDRESS
	CALL	INPCOM
	CALL	REG		;GET THE REGISTER VALUE EXPRESSION
	BIT	#1,R1
	BEQ	2$		;IF EVEN ADDRESS
	ERROR	R,<Register expression made even>
	DEC	R1		;MAKE VALUE EVEN
2$:	MOV	R1,LOCADR	;SET UP TO PRINT REG VALUE
	MOV	@SP,R0		;R0 -> REGISTER SYT ADDRESS
	MOV	R1,SY.ADR(R0)	;PUT VALUE IN FOR REGISTER
	MOV	#ID,R2		;R2 -> NAME HOLDING AREA
	MOV	(R0)+,(R2)+	;MOVE NAME TO ID TO ENTER OTHER NAMES
	MOV	(R0)+,(R2)+
	MOV	(R0)+,(R2)+
	MOV	(SP)+,R0	;R0 -> SYMBOL TBL ENTRY AGAIN
3$:	CMPB	-(R2),#40	;LOOK FOR LAST CHARACTER OF NAME TO ADD
	BNE	4$		;  THE H AND L VERSIONS TO THE SYT
	CMP	R2,#ID
	BHI	3$		;IF MORE CHARACTERS
	ERROR	R,<Register name "@" greater than 5 characters>
	RETURN
4$:	INC	R2		;R2 -> 1ST BLANK IN NAME
	MOVB	#'L,@R2		;MAKE IT REG'L
	MOV	R1,-(SP)	;SAVE THE VALUE FOR LATER
	MOV	R2,-(SP)	;SAVE BLANK BYTE ADDRESS
	CALL	REGENT		;PUT LOW VERSION IN SYT
	MOV	2(SP),SY.ADR(R0) ;INSERT THE VALUE
	MOVB	#'H,@(SP)+	;MAKE HIGH VERSION
	CALL	REGENT
	INC	@SP		;HIGH ONE IS ODD
	MOV	(SP)+,SY.ADR(R0) ;PUT IN VALUE
	RETURN
	.DSABL	LSB
; TRAN PSEUDO OP
; DEFINE TRANSLATION SYMBOL FOR LATER CHECKING AGAINST
; INSTRUCTION TRANSLATION FIELDS.
	.ENABL	LSB
CLS10:	CALL	LEX		;GET OPERAND
	BNE	1$		;IF NE, NUMERIC OR SPECIAL CHARACTER
	CALL	ENTERD		;ENTER SYMBOL
	BIT	#ST.DFN!ST.EQU,SY.STS(R0) ;WAS IT PREVIOUSLY DEFINED?
	BNE	2$		;IF NE YES
	BIS	#ST.TRN,SY.STS(R0) ;INDICATE TRANSLATION SYMBOL
	RETURN

1$:	ERROR	T,<Translation mnemonic "@" first character is not alphabetic>
	RETURN

2$:	ERROR	T,<Translation mnemonic "@" is used elsewhere as symbol>
	RETURN
	.DSABL	LSB


; TITLE AND .TITLE
; MOVE REMAINDER OF LINE TO TITLE AREA
CLS12:	MOV	#TITLE,R2	;R2 -> TITLE AREA
	MOV	#TITLEN,R1	;R1 = NO OF CHARS IN TITLE
	BR	CLS13A

; SBTTL AND .SBTTL DIRECTIVES
; MOVE THE TEXT INTO THE SUBTITLE BUFFER
	.ENABL	LSB
CLS13:	MOV	#SBTTL,R2	;SUBTITLE POINTER
	MOV	#SBTLEN,R1	;R1 = SUBTITLE LENGTH
CLS13A:	CALL	STNF		;SKIP TO TEXT
2$:	MOVB	(R5)+,R0	;GET A CHARACTER FROM THE SUBTITLE
	CMPB	R0,#CR
	BEQ	3$		;IF AT END OF LINE
	CMPB	R0,#';
	BEQ	3$		;IF AT END OF STATEMENT
	MOVB	R0,(R2)+	;PUT CHARACTER IN BUFFER
	DEC	R1
	BGT	2$		;IF MORE CHARACTERS
3$:	CLRB	(R2)+		;AND A STOPPER FOR MOVE
	DEC	R5		;POSITION BEFORE <CR>
1$:	CMPB	(R5)+,#CR	;SKIP CHARACTERS
	BNE	1$		; UNTIL
	DEC	R5		;  EOL IS REACHED
	RETURN
	.DSABL	LSB


; PAGE DIRECTIVE
; PAGE CAUSES A NEW LISTING PAGE TO BE STARTED
CLS14:	CMP	LINCNT,#2
	BLT	RETURN		;IF A NEW PAGE IS STARTING ANYWAY
	MOV	#1,LINCNT	;MAKE THIS THE LAST LINE ON THE PAGE
	RETURN


; JSR INSTRUCTION
; THIS IS A JUMP WITH THE LRR(1) EXTENSION BIT PRESET
CLS15:	MOV	#1,OPH		;SET THE LRR BIT
	JMP	CLS0		;THEN SAME AS A JUMP INST


; MODE PSEUDO OP
; EXPRESSION INDICATES WHAT MODE PROGRAM IS FOR.  IF NO MODE
; DIRECTIVE IS PRESENT, THEN ASSUME MODE 1
CLS17:	CALL	EXPR		;GET THE MODE
	CMP	R1,#4
	BHI	1$		;IF NOT BETWEEN 1-4
	MOV	R1,LOCADR	;MAKE IT PRINT ON LISTING
	BEQ	1$		;IF ZERO, ILLEGAL
	MOV	R1,MODE
	RETURN
1$:	ERROR	M,<Illegal WCS addressing mode>
	RETURN
	.SBTTL	CHECK IF ADDRRESS IS LEGAL FOR MODE

; IF THE ADDRESS IN R1 IS NOT IN THE CORRECT RANGE FOR THE MODE
; SPECIFIED, THEN GIVE AN ERROR.
	.ENABL	LSB
CHKMOD:	MOV	MODE,R0
	ASL	R0
	JMP	@10$-2(R0)
10$:	.WORD	1$,2$,3$,4$

; MODE 1 AND 3
; ADDRESSES ARE IN THE RANGE 2000-3777
1$:
3$:	CMP	R1,#2000
	BLO	9$		;IF ILLEGAL
	CMP	R1,#3777
	BLOS	RETURN

9$:	ERROR	A,<Illegal address for mode>
	RETURN

; MODE 2
; ADDRESS ARE IN THE RANGE 3000-3777 AND 13000-13777
2$:	CMP	R1,#3000
	BLO	9$		;IF OUT
	CMP	R1,#3777
	BLOS	RETURN
	CMP	R1,#13000
	BLO	9$		;OUT OF RANGE
	CMP	R1,#13777
	BHI	9$
	RETURN

; MODE 4
; ADDRESSES MAP 0-1777
4$:	CMP	R1,#1777
	BHI	9$
	RETURN
	.DSABL	LSB
	.SBTTL	OUTPUT A CROSS-REFERENCE RECORD

; CRFSYM
; WRITES A CROSS-REFERENCE RECORD TO THE CREF INTERMEDIATE FILE

CRFSYM:	TST	PASS		;IS THIS PASS 2?
	BEQ	RETURN		;IF EQ NO - NO OUTPUT
	TST	CRFFL		;WAS CREF SWITCH SET?
	BEQ	RETURN		;IF EQ NO
	MOV	#ID,R1		;R1 -> INPUT SYMBOL NAME
	MOV	#CRFREC+1,R2	;R2 -> SYMBOL AREA IN RECORD
	MOV	#6.,R3		;R3 = # OF CHARS TO COPY
1$:	MOVB	(R1)+,(R2)+	;COPY SYMBOL NAME
	DEC	R3		; TO PROTOTYPE
	BNE	1$		;  OUTPUT RECORD
	MOVB	LINE+1,CRFLIN+0	;INSERT HIGH BYTE OF LINE #
	MOVB	LINE+0,CRFLIN+1	; AND LOW BYTE
	MOV	#CRFREC,R1	;R1 -> OUTPUT RECORD
	MOV	#12.,R2		;R2 = # OF CHARS IN RECORD
	MOV	R0,-(SP)	;SAVE CALLER'S R0
	MOV	CRFPTR,R0	;R0 -> NEXT CHAR IN BLOCK BUFFER
2$:	CMP	R0,#CRFEND	;SPACE LEFT IN CURRENT BLOCK?
	BLO	3$		;IF LO YES
	.WRITW	#AREA,#2,#CRFBUF,#256.,CRFBLK
	BCS	4$		;IF CS ERROR
	MOV	#CRFBUF,R0	;RESTORE BUFFER POINTER
	INC	CRFBLK		;BUMP BLOCK COUNTER
3$:	MOVB	(R1)+,(R0)+	;COPY A CHAR TO THE OUTPUT BUFFER
	DEC	R2		;COUNT DOWN CHARS IN RECORD
	BNE	2$		;IF NE, STILL SOME LEFT
	MOV	R0,CRFPTR	;ELSE STORE POINTER FOR NEXT TIME
6$:	MOV	(SP)+,R0	;RESTORE CALLER'S R0
	RETURN			;AND RETURN

4$:	TSTB	@#EMTERR	;WHAT KIND OF ERROR OCCURRED?
	BNE	5$		;IF NE, HARDWARE ERROR
	.PRINT	#CRFSML		;ELSE INDICATE FILE TOO TINY
	CLR	CRFFL		;AND IGNORE CREFFING FROM NOW ON
	BR	6$		;EXIT THIS ROUTINE

5$:	.PRINT	#CRFIO		;SHOW HARDWARE ERROR OCCURRED
	.EXIT			;AND BAIL OUT

CRFREC:	.BYTE	'S&37
	.ASCII	/SYMBOL/
	.BYTE	377,377		;NO PAGE NUMBER DESIRED
CRFLIN:	.BYTE	000,000		;LINE NUMBER
CRFFLG:	.BYTE	040		;DEFN/REF FLAG

CRFSML:	.ASCIZ	/?MICRO-W-Insufficient temporary file space for cross-reference/
CRFIO:	.ASCIZ	/?MICRO-F-Output error on cross-reference file/
	.EVEN
	.SBTTL	CLOSE THE FILES

; CLOSE FILES BY FLUSHING THE OUTPUT BUFFER IF NECESSARY
CLOSE:	.SETTOP	SPACE+2		;MAKE ROOM FOR THE USR
	TST	LISTFL
	BEQ	2$		;IF NO LISTING, DONT CLEAR BUFFER
	MOV	OUTPTR,R4
	CMP	R4,#OUTBUF
	BEQ	2$		;IF AT START OF BUFFER
	BR	5$

1$:	CLRB	(R4)+
5$:	CMP	R4,#OUTBUF+512.
	BNE	1$		;FILL BUFFER WITH ZEROS UNTIL END
	.WRITW	#AREA,#1,#OUTBUF,#256.,OUTBLK
	INC	OUTBLK		;MAKE BLOK NUMBER CORRECT
2$:	TST	OBJFL
	BEQ	6$		;IF NO OOBJ FILE OPENED
	CMP	TXTPTR,#OBJTXT
	BEQ	8$		;IF NO TEXT IN THIS RECORD
	MOV	#TXTREC,R1	;WRITE THIS RECORD THEN EOM
	MOV	BYTCNT,R3
	CALL	OBJWRT
8$:	MOV	#EOMREC,R1	;WRITE EOM RECORD
	MOV	#7,R3
	CALL	OBJWRT		
	CMP	OBJPTR,#OBJBUF
	BEQ	7$		;IF AT THE START OF THE RECORD
	.WRITW	#AREA,#0,#OBJBUF,#256.,OBJBLK ;WRITE LAST BLOCK
7$:	.CLOSE	#0		;CLOSE THE FILE
6$:	.CLOSE	#3
	.RCTRLO
	MOV	#ERRCT,R4	;POINT TO ERROR COUNT IN MESSAGE
	MOV	ERRCNT,R0	;GET COUNT OF ERRORS ENCOUNTERED
	BEQ	3$		;IF EQ NONE
	CALL	DEC5		;ELSE CONVERT IT FOR OUTPUT
	CLRB	@R4		;TERMINATE LINE
	.PRINT	#ERRSUM		;PRINT SUMMARY ON CONSOLE
	TST	WCSFL		;REQUESTED WCS LOAD?
	BEQ	15$		;IF EQ NO
	.PRINT	#ERRWCS		;ELSE INDICATE NOT LOADED
	BR	15$

3$:	TST	WCSFL		;LOADING DIRECT TO WCS?
	BEQ	4$		;IF EQ NO
	BIS	#WCS$EN,@#WCSSTS ;ELSE ENABLE WCS NOW
4$:	.PRINT	#ERRNON		;ANNOUNCE NO ERRORS
	BR	15$

15$:	TST	CRFFL		;ANY CREF OUTPUT?
	BEQ	16$		;IF EQ NO
	MOV	CRFPTR,R0	;GET BUFFER POINTER
	CMP	R0,#CRFBUF	;ANYTHING IN BUFFER NOW?
	BEQ	11$		;NOPE
9$:	CMP	#CRFEND,R0	;WHAT ABOUT NOW?
	BEQ	10$		;IF EQ, DONE
	CLRB	(R0)+		;ELSE CLEAR BUFFER
	BR	9$		;AND LOOP

10$:	.WRITW	#AREA,#2,#CRFBUF,#256.,CRFBLK
	INC	CRFBLK
11$:	MOV	#CHAINP,R0	;R0 -> CHAIN PROTOTYPE
	MOV	#500,R1		;R1 -> CHAIN PARAMETER AREA
12$:	MOV	(R0)+,(R1)+	;COPY PROTOTYPE INFORMATION
	CMP	R1,#536		;COPIED ALL BUT TITLE?
	BLO	12$		;IF LO NO
	MOV	LSTSPC,@#512	;SET LISTING DEVICE
	MOV	OUTBLK,@#514	;AND LISTING BLOCK #
	MOV	CRFSPC,@#520	;SET CREF TEMP FILE DEVICE
	MOV	CRFBLK,@#522	;AND ITS BLOCK #
	BEQ	16$		;IF NO CREF OUTPUT, NO CREF!
	TST	TTYFL		;NARROW LISTING DESIRED?
	BEQ	13$		;IF EQ NO
	COM	@#524		;ELSE FLAG AS SUCH
13$:	MOV	#TITLE-1,R0	;COPY TITLE TO OUTPUT
22$:	MOVB	(R0)+,(R1)+
	BNE	22$
	DEC	R1		;BACK UP BEFORE NULL AT END
	MOV	#HEADER,R0	;R0 -> OUR TITLE LINE
14$:	MOVB	(R0)+,(R1)+	;COPY IT
	CMP	#PAGEST,R0	; UP TO PAGE HEADER
	BNE	14$
	CLRB	@R1		;END LINE WITH A NULL
	.CHAIN			;CHAIN AWAY TO CREF

16$:	.CLOSE	#1		;CLOSE LISTING
	RETURN

CHAINP:	.RAD50	/SY CREF  SAV/	;CHAIN PROTOTYPE
	.WORD	1		;LISTING OUTPUT CHANNEL
	.BLKW	2		;LISTING DEV, HIGH BLOCK
	.WORD	2		;CREF TEMP CHANNEL
	.BLKW	2		;CREF DEV, HIGH BLOCK
	.WORD	-1		;LISTING FORMAT (WIDE)
	.RAD50	/SY MICRO SAV/	;PROGRAM TO RETURN TO

ERRSUM:	.ASCII	/?MICRO-F-Errors detected: /
ERRCT:	.ASCII	/99999 /
ERRNON:	.ASCIZ	/MICRO-I-No errors detected/
ERRWCS:	.ASCIZ	/?MICRO-I-WCS has NOT been enabled/
	.EVEN

; END OF MODULE RECORD
EOMREC:	.WORD	1	;EOM RECORD
	.WORD	6	;RECORD TYPE EOM=6
	.WORD	6	;BYTE COUNT
	.BYTE	-<1+6+6> ;CHECKSUM
	.EVEN
	.SBTTL	DATE AND TIME CONVERSION

; DAYTIM
; FORMATS DATE AND TIME FOR LISTING HEADER

DAYTIM:	MOV	#DATE,R2	;POINT TO DATE OUTPUT AREA
	.DATE			;GET DATE INTO R0
	MOV	R0,R5		;COPY IT
	BEQ	3$		;IF NO DATE TYPED IN
	ASL	R0
	ASL	R0		;ISOLATE
	ASL	R0		; DAY
	SWAB	R0
	BIC	#^C<37>,R0	;AND MASK OFF OTHERS
	CALL	DEC2		;CONVERT TO DECIMAL
	MOV	R5,R0		;COPY DATE AGAIN
	SWAB	R0		;GET MONTH*4
	BIC	#^C<37*4>,R0
	ADD	#MONTHS-4,R0	;R0 -> ASCII MONTH NAME
	MOV	#5.,R1		;SET TO MOVE -MON-
1$:	MOVB	(R0)+,(R2)+	;COPY MONTH NAME
	DEC	R1
	BNE	1$
	MOV	R5,R0		;RESTORE DATE AGAIN
	BIC	#^C<37>,R0	;ISOLATE YEAR
	ADD	#72.,R0		;BASE IS 1972
	CALL	DEC2		;CONVERT YEAR
3$:	MOV	#TIME,R2	;NOW POINT TO TIME OUTPUT AREA
	MOV	#STIME,R5	;R5 -> STORAGE FOR SYSTEM TIME
	.GTIM	#AREA,R5	;GET SYSTEM TIME
	MOV	(R5)+,R4	;R4 = HIGH-ORDER TIME
	MOV	@R5,R5		;R5 = LOW-ORDER TIME
	.GVAL	#AREA,#CONFIG	;GET CONFIG WORD IN R0
	MOV	#50.,R3		;ASSUME 50-CYCLE CLOCK
	BIT	#CLK50,R0	;IS IT TRULY 50-CYCLE?
	BNE	2$		;IF NE YES
	MOV	#60.,R3		;ELSE 60 CYCLE
2$:	CALL	DIV		;REMOVE TICKS
	CALL	DIV60		;SET R0=SECONDS
	MOV	R0,-(SP)
	CALL	DIV60		;SET R0=MINUTES
	MOV	R0,-(SP)
	CALL	DIV60		;SET R0=HOURS
	CALL	DEC2		;FORMAT HOURS
	MOVB	#':,(R2)+	;INSTALL SEPARATOR
	MOV	(SP)+,R0	;RESTORE MINUTES
	CALL	DEC2		;FORMAT THEM
	MOVB	#':,(R2)+	;PUT IN ANOTHER SEPARATOR
	MOV	(SP)+,R0	;AND AT LAST, SECONDS
	CALL	DEC2		;FORMAT THEM
	RETURN

; DIVIDE SUBROUTINE, DIVIDES (R4,R5) BY R3, RETURNING
; REMAINDER IN R0 AND QUOTIENT IN (R4,R5)

DIV60:	MOV	#60.,R3		;SET DIVISOR=60
DIV:	CLR	R0
	MOV	#32.,R1
1$:	ASL	R5
	ROL	R4
	ROL	R0
	CMP	R0,R3
	BLO	2$
	SUB	R3,R0
	INC	R5
2$:	DEC	R1
	BNE	1$
	RETURN

MONTHS:	.ASCII	/-Jan-Feb-Mar-Apr-May-Jun-Jul-Aug-Sep-Oct-Nov-Dec-/
	.EVEN
	.SBTTL	DECIMAL NUMBER CONVERSION

DEC5:	MOV	R4,-(SP)	;SAVE FIRST OUTPUT ADRS
	MOV	#DECTAB,R2	;R2 -> DIVISOR TABLE
1$:	CLR	R1		;INIT QUOTIENT
2$:	INC	R1		;BUMP QUO
	SUB	@R2,R0		;AND SUB OFF DIVISOR
	BPL	2$		;WHILE STILL POSITIVE
	ADD	@R2,R0		;CORRECT OVERRUN
	DEC	R1		;AND CORRECT QUO
	BNE	3$		;IF NE, NOT ZERO
	CMP	R4,@SP		;ELSE, IS THIS LEADING ZERO?
	BEQ	4$		;IF EQ YES
3$:	ADD	#'0,R1		;ASCIIFY DIGIT
	MOVB	R1,(R4)+	;AND OUTPUT IT
4$:	TST	-(R2)		;BACK TO NEXT DIVISOR
	BNE	1$		;IF NE NOT DONE
	ADD	#'0,R0		;DO UNIT'S DIGIT
	MOVB	R0,(R4)+
	TST	(SP)+
	RETURN

	.WORD	0
	.WORD	10.
	.WORD	100.
	.WORD	1000.
DECTAB:	.WORD	10000.

DEC2:	SWAB	R0		;CONVERTS 0<=R0<=99.
1$:	ADD	#<-10.*400>+1,R0 ;TO TWO ASCII DIGITS
	BPL	1$		;PLACING RESULT
	ADD	#<10.*400>-1+"00,R0 ;AT (R2)+
	MOVB	R0,(R2)+
	SWAB	R0
	MOVB	R0,(R2)+
	RETURN
	.SBTTL	ENTER A SYMBOL IN THE TABLE
; ENTER
; ENTER A SYMBOL IN THE SYMBOL TABLE
; ON EXIT R0->SYMBOL TABLE
ENTERD:	MOVB	#'#,CRFFLG	;INDICATE DEFINITION OF SYMBOL
	BR	ENTCOM

ENTER:	MOVB	#' ,CRFFLG	;INDICATE JUST REFERENCE
ENTCOM:	MOVB	ID,R2		;GET 1ST CHARACTER AS BUCKET POINTER
	CMPB	R2,#'.
	BNE	1$		;IF NOT A .
	MOVB	#'A-1,R2	;. FILLS POSITION 1 LESS THAN A
1$:	CMPB	R2,#'$
	BNE	5$		;IF NOT DOLLAR
	MOVB	#'Z+1,R2
5$:	ASL	R2		;MAKE WORD INDEX
	ADD 	#BUCKET-200-SY.LCL,R2 ;R2 -> SY.LCL LESS THAN BUCK PTR
	BR	2$

3$:	MOV	R0,R2		;R2 ->THIS SYMBOL TABLE ENTRY
	MOV	#ID,R3		;R3 -> SYMBOL FROM SOURCE LINE
	CMP	(R0)+,(R3)+
	BLO	2$		;IF NO MATCH BUT MORE TO CHECK
	BHI	4$		;IF INSERT SHOULD BE HERE
	CMP	(R0)+,(R3)+
	BLO	2$		;IF NO MATCH BUT MORE TO CHECK
	BHI	4$		;IF INSERT SHOULD BE HERE
	CMP	(R0)+,(R3)+
	BLO	2$		;IF NO MATCH BUT MORE TO CHECK
	BHI	4$		;IF INSERT SHOULD BE HERE
	MOV	R2,R0		;R0 -> SYMBOL TABLE ENTRY
6$:	CALL	CRFSYM		;CREF THE SYMBOL
	RETURN

2$:	MOV	R2,R4		;SAVE ADRS OF LAST SYMBOL
	MOV	SY.LCL(R2),R0	;R0 -> NEXT ENTRY LINKED TO BUCKET
	BNE	3$		;IF IS ONE TO LOOK AT
4$:	MOV	SYTEND,R0	;IF NON IN TABLE, MAKE ONE
	MOV	#ID,R3
	MOV	SY.LCL(R4),-(SP) ;SAVE FORWARD LINK
	MOV	R0,SY.LCL(R4)	;LINK NEW ENTRY TO PREVIOUS
	MOV	(R3)+,(R0)+	;MOVE IN NAME
	MOV	(R3)+,(R0)+
	MOV	(R3)+,(R0)+
	CLR	(R0)+		;ADDRESS
	CLR	(R0)+		;STATUS BITS
	MOV	(SP)+,(R0)+	;LINK TO NEXT SYMBOL
	MOV	R0,SYTEND	;RESET NEW SYMBOL TABLE END
	SUB	#14,R0		;R0 -> START OF ENTRY
	CMP	R0,TOP	
	BLO	6$		;IF SOME SPACE LEFT
	.PRINT	#OVRCOR
	.EXIT

OVRCOR:	.ASCIZ	/?MICRO-F-Not enough memory/
	.EVEN
	RETURN
	.SBTTL	ERROR PROCESSING

; ERROR
; INSERT AN ERROR MESSAGE CHARACTER IN THE START OF THE LINE.  UP
; TO THREE ERRORS ARE ALLOWED THERE
ERROR:	MOV	R0,-(SP)	;SAVE REGISTERS
	MOV	R1,-(SP)
	MOV	R2,-(SP)
	MOV	R3,-(SP)
	MOV	(R5)+,R0	;GET THE ERROR CHARACTER
	DEC	STMERC		;BUMP THE STATEMENT ERROR COUNT
	BLE	1$		;IF ALREADY TOO MANY ERRORS
	MOVB	R0,@ERRPNT
	INC	ERRPNT		;BUMP THE ERROR POINTER
	MOV	@R5,R0		;R5 -> ERROR TEXT
	MOV	MSGPTR,R1	;R1 -> CURRENT SPOT IN ERROR BUFFER
	MOVB	#'*,(R1)+	;INSERT *** BEFORE MESSAGE
	MOVB	#'*,(R1)+
	MOVB	#'*,(R1)+
	MOVB	#TAB,(R1)+
2$:	MOVB	(R0)+,R2	;A CHARACTER OF THE ERROR
	CMPB	R2,#'@
	BNE	4$		;IF '@', THEN SUBST ID FOR NAME
	MOV	#ID,R3
3$:	CMPB	@R3,#40
	BEQ	2$		;LOOP UNTIL BLANK
	MOVB	(R3)+,(R1)+	;MOVE IN ID NAME
	BR	3$
4$:	MOVB	R2,(R1)+	;PUT IN ERROR MESSAGE CHARACTER
	BNE	2$		;LOOP UNTIL END OF MESSG
	DEC	R1		;BACK UP OVER NULL
	MOVB	#CR,(R1)+	;PUT IN CRLF
	MOVB	#LF,(R1)+
	CLRB	@R1		;NULL AS STOPPER
	MOV	R1,MSGPTR	;SAVE CURRENT POSITION
1$:	INC	ERRCNT		;ERROR COUNTER FOR PROGRAM
	TST	(R5)+		;PASS ERROR TEXT POINTER
	MOV	(SP)+,R3	;RESTORE REGISTERS
	MOV	(SP)+,R2
	MOV	(SP)+,R1
	MOV	(SP)+,R0
	RTS	R5
	.SBTTL	EXPRESSIONS

;ACCEPT AN EXPRESSION AND RETURN THE RESULT IN 'RESULT' AND R1
	.ENABL	LSB
EXPR:	MOV	SP,SAVESP	;SAVE STACK IN CASE OF ERRORS
	CLR	PARLVL		;DEFAULT TO TOP LEVEL OF PARENS
EXPR0:	CLR	RESULT		;INITIALIZE RESULT
	CALL	STNF
	CMPB	R0,#'-
	BNE	6$		;IF NOT UNARY MINUS
	INC	R5		;PASS THE MINUS
	CALL	EXOPND		;GET THE OPERAND
	NEG	R1		;DO THE NEGATE OPERATION
	BR	7$
6$:	CMPB	R0,#'^
	BNE	9$		;IF NOT COMPLIMENT (^C)
	CMPB	1(R5),#'C
	BNE	9$		;DEFINITLY NOT
	CMPB	(R5)+,(R5)+	;SKIP OVER ^C
	CALL	EXOPND		;GET SUBEXPRESSION ARGUMENT
	COM	R1		;DO THE COMPLIMENT
	BR	7$
9$:	CMPB	R0,#'+
	BNE	8$		;IF UNARY '+'
	INC	R5		;SKIP PAST PLUS OPERATOR
8$:	CALL	EXOPND		;GET AN OPERAND
7$:	MOV	R1,RESULT	;SET RESULT WITH INITIAL OPERAND
1$:	MOVB	(R5)+,R0	;GET DELIMITER CHARACTER
	MOV	#NOPS-1,R1
4$:	CMPB	OPER(R1),R0	
	BEQ	2$		;IF MATCHES CURRENT OPCODE
	DEC	R1
	BPL	4$		;IF MORE OPERATERS LEFT
	CMPB	R0,#CR
	BEQ	3$		;IF END OF LINE CONDITION
	CMPB	R0,#',
	BEQ	3$
	CMPB	R0,#';
	BEQ	3$
	CMPB	R0,#040
	BEQ	3$
	CMPB	R0,#TAB
	BEQ	3$
	CMPB	R0,#'>
	BEQ	50$		;IF END OF SUBEXPRESSION
	ERROR	S,<Illegal operator in expression>
	BR	EXPERR		;RESET EVERYTHNG ON ERROR

2$:	MOV	R1,-(SP)	;SAVE THE OPERATOR
	CALL	EXOPND		;GET 2ND OPERAND
	MOV	(SP)+,R0	;GET OPERATOR BACK
	ASL	R0
	JMP	@OPERTB(R0)
	BR	1$		;LOOP ON OPERAND,OPRATOR PAIRS

; IF AN ERROR OCCURS IN AN EXPRESSION, THE STACK MUST BE
; RESET AND A ZERO IS SUBSTITUTED FOR THE RESULT
EXPERR:	MOV	SAVESP,SP	;RESET SP
	CLR	RESULT		;RETURN 0 FOR ILLEGAL EXPRESSION
	BR	5$
3$:	DEC	R5		;BUMP BACK DELIMITER
	TST	PARLVL
	BEQ	5$		;IF NO OPEN PARENS LEFT
	ERROR	S,<Missing Close Paren>
	CLR	R1		;RESULT IS 0 IF ERROR
5$:	MOV	RESULT,R1
	RETURN

OPERTB:	.WORD	10$,20$,30$,40$
OPER:	.ASCII	/+-&!/
	.EVEN
NOPS=	4			;NUMPER OF OPERATORS

; ADDITION
10$:	ADD	R1,RESULT
	BR	1$

; SUBTRACTION
20$:	SUB	R1,RESULT
	BR	1$

; AND
30$:	COM	R1
	BIC	R1,RESULT
	BR	1$

; OR
40$:	BIS	R1,RESULT
	BR	1$


; CLOSE PAREN (>)
; OPEN PARENS ARE FOUND IN EXOPND AND THE PAREN LEVEL IS INCR AND
; EXPRESSION IS CALLED RECURSIVLY.  IF THE PAREN LEVEL IS > 0,
; THEN RESET EVERYTHING AND RETURN TO EXOPND.
50$:	DEC	PARLVL
	BGE	61$		;IF WE WERE IN PARENS
	ERROR	S,<Close paren without matching open paren>
	BR	EXPERR
61$:	MOV	RESULT,R1	;GET THIS RESULT
	RETURN
	.DSABL	LSB
; EXPRESSION OPERAND GETTER
	.ENABL	LSB
EXOPND:	CALL	LEX		;GET A ITEM
	BLT	3$		;IF SPECIAL CHAR
	BGT	2$		;IF NUMBER, VALUE IN R1

; SYMBOL - LOOK UP NAME IN SYMBOL TABLE
	CALL	ENTER		;CHECK FOR NAME
	BIT	#ST.DFN!ST.EQU,SY.STS(R0)
	BNE	1$		;IF SYMBOL WAS ALREDY DEFINED
	ERROR	U,<Symbol "@" is undefined>
	CLR	R1
	RETURN			;DONT LEAVE WITH JUNK IN R1
1$:	MOV	SY.ADR(R0),R1
	RETURN

; CONSTANT CODE MERGES HERE
2$:	MOV	R0,R1
	RETURN

3$:	CMPB	R0,#'<
	BEQ	4$		;IF OPEN PAREN
	ERROR	E,<Illegal element in expression>
	CLR	R1		;RETURN 0 FOR ILLEGAL OPND
	BR	EXPERR

4$:	INC	PARLVL		;INDICATE IN PARENS
	MOV	RESULT,-(SP)	;SAVE PREVIOUS RESULT
	CALL	EXPR0		;EVALUATE INSIDE PARENS
	MOV	(SP)+,RESULT	;PUT THE PREVIOUS RESULT IN RESULT
	RETURN			;THE SUBEXPRESSION RESULT IS IN R1
	.DSABL	LSB



	.SBTTL	CHARACTER ACCEPTERS

; COMMA
INPCOM:	CALL	LEX		;GET THE ELEMENT
	CMP	R1,#LX.SPC
	BNE	1$		;IF NOT SPECIAL CHARACTER
	CMPB	R0,#',
	BEQ	RETURN		;IF IS A COMMA
1$:	ERROR	S,<Missing comma after operand>
	.SBTTL	LEXICAL ANALYZER

; LEX
; GET THE NEXT SYNTATIC ELEMENT
LEX:	MOV	REPEAT,R1
	BNE	RETURN		;IF REPEATING THE LAST REPORT
	CALL	STNF		;SKIP TO THE NEXT FIELD
	CLR	R2		;DEFAULT TO RADIX 8
	MOVB	(R5)+,R0	;R0=1ST CHARACTER
	BIC	#^C<177>,R0
	MOVB	CLASS(R0),R1	;DISPATCH ON THE CHARACTER CLASS
	JMP	@LEX1(R1)

LEX1:	.WORD	LEXALP,LEXNUM,LEXSPC

; ALPHABETIC CHARACTER FIRST
LEXALP:	MOV	#ID+4,R2	;MOVE NAME INTO ID
	MOV	#"  ,R3
	MOV	R3,@R2
	MOV	R3,-(R2)	;INIT IT TO BLANKS
	MOV	R3,-(R2)
	MOV	#6,R3		;UP TO 6 CHARACTERS
1$:	DEC	R3
	BLT	2$		;IF PAST THE END OF THE NAME
	MOVB	R0,(R2)+	;PUT A CHARACTER IN BUFFER
2$:	MOVB	(R5)+,R0	;GET THE NEXT CHARACTER
	BIC	#^C<177>,R0
	CMPB	CLASS(R0),#2
	BLE	1$		;IF ALPHA-NUMERIC
	DEC	R5		;BACKUP OVER DELIMITER
	CMP	ID,#". 
	BNE	3$		;IF NOT SYMBOL ". "
	MOV	LOCADR,R0		;USE LOC FOR CONSTANT VALUE
	MOV	#LX.NUM,R1	;  AND NUMBER AS ITEM TYPE
	RETURN
3$:	MOV	#LX.SYM,R1	;RETURN SYMBOL
	RETURN
; GET A NUMBER
	.ENABL	LSB
LEXNUM:	CLR	R1		;INITIALIZE RESULT
1$:	CMPB	R0,MAXDIG(R2)
	BGT	2$		;IF NOT DIGIT OF RADIX
	JMP	@4$(R2)		;DISPATCH ON MULTIPLY BY RADIX
4$:	.WORD	5$,6$,7$
5$:	ASL	R1		;SHIFT PREVIOUS RESULT
	ASL	R1
6$:	ASL	R1
	BR	8$
7$:	MOV	R1,-(SP)	;MULTIPLY BY 10
	ASL	R1
	ASL	R1
	ADD	(SP)+,R1
	ASL	R1
8$:	SUB	#'0,R0		;MAKE DIGIT A NUMBER
	ADD	R0,R1		;ADD INTO RUNNING TOTAL
	MOVB	(R5)+,R0	;GET NEXT CHARACTER
	BIC	#^C<177>,R0
	CMPB	CLASS(R0),#C.NMBR
	BEQ	1$		;LOOP ON DIGITS
	MOV	R1,R0		;RETURN NUMBER IN R0
	DEC	R5		;BACK OVER DELIMITER
	BR	3$
2$:	ERROR	N,<Error in numeric constant>
	CLR	R0
3$:	MOV	#LX.NUM,R1	;RETURN A NUMBER OF ZERO
	RETURN
	.DSABL	LSB


; SPECIAL CHARACTER
	.ENABL	LSB
LEXSPC:	MOVB	#LX.SPC,R1	;RETURN SPECIAL CHAR CODE
	CMPB	R0,#''
	BNE	4$		;IF NOT ASCII CHARACTER
	MOVB	(R5)+,R0
	BIC	#^C<177>,R0
	CMPB	R0,#40
	BGE	2$		;MAKE R0 THE CONSTANT
	ERROR	C,<Illegal ASCII character>
	BR	5$

4$:	CMPB	R0,#';
	BNE	6$		;IF NOT COMMENT
	DEC	R5		;SKIP OVER SEMI-COLON
	RETURN
6$:	CMPB	R0,#'^
	BNE	RETURN		;IF NOT ^RADIX CHARACTER
	MOVB	(R5)+,R0
	MOV	#RDXTBL,R1	;SEE WHAT RADIXHE WANTS
1$:	MOV	(R1)+,R2
	BEQ	2$		;IF ILLEGAL RADIX
	CMPB	R2,R0
	BNE	1$		;IF NOT THIS RADIX
	CLRB	R2
	SWAB	R2		;GET RADIX NUMBER
				; OCTAL = 0
				; DECIMAL = 4
				; BINARY = 2
	MOVB	(R5)+,R0	;GET DIGIT
	BIC	#^C<177>,R0
	CMPB	CLASS(R0),#C.NMBR
	BEQ	LEXNUM
2$:	ERROR	N,<Illegal number radix>
5$:	CLR	R0		;SET ERROR
3$:	MOV	#LX.NUM,R1
	RETURN
	.DSABL	LSB

RDXTBL:	.BYTE	'O,0
	.BYTE	'B,2
	.BYTE	'D,4
	.BYTE	0,0


; MAX DIGIT IN RADIX TABLE
MAXDIG:	.WORD	'7, '1, '9
	RETURN
	.SBTTL	MICRO ASSEMBLER MAIN PROGRAM

; MICRO ASSEMBLER
MICASM::CLR	PASS		;START IN PASS 1
	CALL	DAYTIM		;FORMAT DATE AND TIME FOR OUTPUT
	CALL	OPEN		;OPEN THE FILES
	CALL	ONEPAS		;DO BOTH PASSES
	CLRB	TITLE		;START WITH NO TITLE
	CLRB	SBTTL		;START WITH NO SUBTITLE
	CALL	ONEPAS
	CALL	PRTSYM		;PRINT SYMBOL TABLE
	CALL	PRBTMP		;PRINT BIT MAP ALA OS/8
	CALL	CLOSE		;CLOSE THE FILES
	.EXIT			;THATS ALL
	.SBTTL	OCTAL NUMBER CONVERSION

; CONVERT BINARY NUMBERS TO OCTAL
; DIFFERENT ENTRY POINTS FOR DIFFERENT NUMBERS OF BITS TO CONVERT
OCT12:	MOV	#40,R2		;DEFALUT TO BLANK UNLESS 1
	BIT	#10000,R0
	BEQ	1$		;IF NOT 10000 BIT SET
	MOV	#'1,R2
1$:	MOVB	R2,(R4)+	;PUT IN THE DIGIT

OCT11:	.ENABLE	LSB
	MOV	#4,R2		;DO 11 BITS (4 DIGITS)
	CLC
	SWAB	R0
	RORB	R0		;11 BITS TO TOP OF WORD
	BR	3$

; DO A BYTE (3 DIGITS, 8 BITS)
OCTBYT:	MOV	#3,R2		;3 DIGITS
	CLC
	SWAB	R0
	BR	4$

; OUTPUT 16 BITS WORTH 
OCTOUT:	MOV	#6,R2		;6 DIGITS
	CLR	R1
	ROL	R0
	ROL	R1		;ROTATE IN BIT
	CLC
	BR	2$
1$:	ROL	R0		;POSITION DIGIT AT LOW ORDER 3 BITS
4$:	ROL	R0
	ROL	R0
	ROL	R0
3$:	MOV	R0,R1		;GET WORD IN SAFE PLACE
	ROR	R0		;SHIFT BACK CARRY SO IT DOESNT GET LOST
2$:	BIC	#^C<7>,R1	;ONLY 3 BITS
	ADD	#'0,R1
	MOVB	R1,(R4)+	;PUT IN OUTPUT LINE
	DEC	R2
	BNE	1$		;IF MORE DIGITS
	RETURN
	.DSABLE	LSB
	.SBTTL	DO AN ASSEMBLY PASS

; DO A PASS
; ASSEMBLE LINES UNTIL THE END STATEMENT IS FOUND
ONEPAS:	CLR	OPNDFL		;INITIAL COMMENT STATEMENT
	CLR	ERRCNT		;CLEAR PROGRAM ERROR COUNT
	CLR	LOC		;INITIAL LOCATION COUNTER
	CLR	LINE		;CLEAR CURRENT LINE
	CLR	PAGE		;CLEAR CURRENT PAGE
	CLR	LINCNT		;AND START FRESH PAGE
	CLR	INBLK		;I/O BUFFER ADDRESS
	CLR	OUTBLK
	CLR	CRFBLK		;INIT CREF FILE OUTPUT BLOCK
	MOV	#CRFBUF,CRFPTR	;AND BUFFER POINTER
	MOV	#OBJTXT,TXTPTR	;INIT TEXT RECORD POINTER
	MOV	#10,BYTCNT	;INITIALIZE OBJ RECORD SIZE
	CLR	OBJBLK		;START AT OBJ BLOCK 0
	MOV	#1000,OBJADR	;START AT LOCATION 0 IN OBJ FILE
	MOV	#-1,OPCLS	;MAKE SURE CLASS OK
	MOV	#INBUF+513.,INPTR ;SET UP I/O POINTERS
	MOV	#OUTBUF,OUTPTR
	MOV	#OBJBUF,OBJPTR	;INITIALIZE OUTPUT POINTER FOR OBJ
1$:	MOV	#3,STMERC	;NUMBER OF ALLOWABLE ERRORS
	MOV	#ERRBUF,MSGPTR	;INIT ERROR MESSAGE BUFFER POINTER
	MOV	#OUTLN,ERRPNT	;SET UP ERROR POINTER
	CALL	ASM		;ASSEMBLE A LINE
	CMP	OPCLS,#CL.END
	BNE	1$		;LOOP UNTIL END
	INC	PASS
	RETURN
	.SBTTL	LOOKUP OPCODES IN OPCODE TABLE

; OPCODE
; CHECK IF THE OPCODE IS IN THE TABLE AND PULL OUT THE BASE
; OPCODE NUMBER FROM THE TABLE.  
OPCODE:	MOV	#OPTBL,R1	;R1 -> START OF TABLE
	MOV	R1,-(SP)
	BIC	#^C<7>,@SP	;@SP->TABLE ADDR LOW BITS TO OR IN
	MOV	#OPTBLE-10,R2	;R2 -> CURRENT HIGH ENTRY
	MOV	R1,R0
1$:	MOV	R0,R1		;CLACULATE PROBE INTO TABLE
	ADD	R2,R1
	ROR	R1
	BIC	#7,R1		;KILL LOW BITS
	BIS	@SP,R1		;AND USE TABLE OFFSET FM XXX0
	MOV	#6,R3		;R3 = BYTE COUNT
	MOV	#ID,R4		;R4 -> SOURCE FROM MICRO STMT
	MOV	R1,-(SP)	;SAVE ENTRY POINTER
15$:	CMPB	(R1)+,(R4)+
	BNE	10$		;IF FAILURE
	DEC	R3
	BNE	15$		;IF MORE BYTES TO COMPARE
	CLR	OPL		;LOW ORDER BITS ARE ZERO
	MOVB	(R1)+,OPL+1	;SET HIGH BITS
	MOVB	(R1)+,R1
	CMP	(SP)+,(SP)+
	CLR	OPH		;CLEAR HIGH MICRO WORD AND RETURN Z BIT
	RETURN

10$:	BHI	3$		;IF GREATER CASE
	MOV	(SP)+,R0	;LOW POINTER UPDATED
	ADD	#10,R0
	BR	5$
3$:	MOV	(SP)+,R2	;HIGH POINTER UPDATED
	SUB	#10,R2
5$:	CMP	R0,R2
	BLOS	1$		;IF NOT DONE
	MOV	PC,(SP)+	;FAIL - RETURN Z CLEAR
	RETURN
	.SBTTL	OPEN FILES AND SET UP

; OPEN
; DO A CSI CALL TO OPEN THE FILES AND LOAD HANDLERS
OPEN:	MOV	#SWTTBL,R0	;R0 -> SWITCH TABLE
1$:	TST	(R0)+		;AT END YET?
	BEQ	2$		;IF EQ YES
	CLR	@(R0)+		;ELSE INIT VALUE
	BR	1$

2$:	MOV	SP,R5		;SAVE STACK POINTER FOR ERRORS
	MOV	#-1*2,R1	;GET ERROR INDEX FOR ID MSG
	.LOCK			;LOCK THE USR
	.GTLIN	#LINBUF,#PROMPT	;READ A LINE OF SPECS
	TSTB	LINBUF		;ANYTHING MORE THAN <CR>?
	BEQ	3$		;IF EQ NO
	.CSISPC	#OUTSPC,#DEXT,#LINBUF ;GET RAD50 FOR CREF
	MOV	R5,SP		;RESTORE STACK
	.CSIGEN	SPACE+2,#DEXT,#LINBUF ;NOW OPEN AND GET HANDLERS
	BCC	4$		;IF CC NO ERRORS
	MOVB	@#EMTERR,R1	;ELSE GET ERROR INDEX
	ASL	R1		;MAKE WORD INDEX
3$:	.UNLOCK			;BANISH USR
	.PRINT	OPNERR(R1)	;PRINT APPROPRIATE MSG
	MOV	R5,SP		;RESTORE STACK
	BR	2$		;AND GET A VALID LINE

4$:	MOV	R0,SYTBGN	;SET LOW LIMITS
	MOV	R0,SYTEND

; POP SWITCHES OFF STACK AND SET FLAGS
	MOV	(SP)+,R1	;R1 = # OF SWITCHES
	BEQ	9$		;IF EQ, NONE
8$:	MOV	#SWTTBL,R2	;R2 -> TABLE OF VALID SWITCHES
5$:	CMPB	@SP,@R2		;SWITCH NAME MATCH?
	BEQ	6$		;IF EQ YES
	CMP	(R2)+,(R2)+	;ELSE SKIP THIS ENTRY
	TST	@R2		;AT END OF TABLE?
	BNE	5$		;IF NE NO
	MOV	#-2*2,R1	;SET UNKNOWN SWITCH MSG
	MOVB	@SP,SWTNAM	;AND ITS NAME
	BR	3$

6$:	COM	@2(R2)		;ELSE FLAG LISTED SWITCH
	TST	(SP)+		;DUMP SWITCH NAME
	BPL	7$		;IF PL, NO VALUE GIVEN
	MOV	(SP)+,@2(R2)	;PUT VALUE IN SWITCH
7$:	DEC	R1		;COUNT DOWN # OF SWITCHES
	BNE	8$		;IF NE , SOME LEFT
9$:	MOV	MODE,R0		;CHECK WHAT MODE THIS SHOULD BE
	BEQ	12$		;IF NONE SPECIFIED, THEN MODE 1
	CMP	R0,#1
	BLT	14$		;IF ILLEGAL MODE
	CMP	R0,#4
	BLE	13$		;IF LEGAL MODE
14$:	.PRINT 	#MODERR		;ILLEGAL MODE
	.EXIT
12$:	INC	R0		;IF NO MODE SPECIFIED, USE 1
13$:	MOV	R0,MODE		;STORE MODE
	TST	CRFFL		;CREF REQUESTED?
	BEQ	10$		;IF EQ NO
	.WAIT	#2		;WAS A FILE SPECIFIED?
	BCC	10$		;IF CC YES
	MOV	#^RSY ,CRFSPC	;ELSE SET CREF DEVICE=SY:
	.ENTER	#AREA,#2,#CRFSYS,#-1 ;AND ENTER A CREF TEMP FILE
	BCC	10$		;IF CC OKAY
	MOV	#-3*2,R1	;INDICATE NO CREF FILE ROOM
	BR	3$

10$:	.UNLOCK			;FREE USR NOW
	.SETTOP	#-2		;GET ALL FREE SPACE AVAILABLE
	SUB	#40,R0		;LEAVE SOME BUFFER
	MOV	R0,TOP		;REMEMBER TOP LOC
	TST	WCSFL		;WCS LOAD REQUESTED?
	BEQ	OPNPRE		;IF EQ NO
	CLR	@#WCSSTS	;ELSE DISABLE WCS MIB RESPONSE
	CLR	@#WCSSTS

; ENTER PREDEFINED SYMBOLS INTO THE SYMBOL TABLE
OPNPRE:	MOV	#BUCKET,R5	;CLEAR THE BUCKET POINTERS
	MOV	#27.,R4
1$:	CLR	(R5)+
	DEC	R4
	BNE	1$
	MOV	#PREDF,R5	;ENTER PREDEFINED SYMBOLS BY
6$:	MOV	#ID,R4		; MOVING THEM IN VIA ENTER
	MOV	(R5)+,(R4)+
	BEQ	4$		;IF DONE ENTERNG
	MOV	(R5)+,(R4)+
	MOV	(R5)+,(R4)+
	CALL	ENTERD		;PUT IT IN
	MOV	(R5)+,SY.STS(R0) ;PUT IN STATUS BITS
	MOV	(R5)+,SY.ADR(R0) ;PUT IN VALUE
	BR	6$		;DO NEXT SYMBOL

; CLEAR THE MEMORY BITMAP
4$:	MOV	#BITMAP,R0
	MOV	#4000/10,R1
5$:	CLRB	(R0)+
	DEC	R1
	BNE	5$

; SET UP ORDER FOR EXTENSION BITS  FIELD AND TRAN FIELD
	MOV	#EXTFLD,EXTEN1	;ASSUME THE NEW WAY (TRAN LAST)
	MOV	#TRNFLD,EXTEN2
	TST	OLDFMT
	BEQ	11$		;IF NOT OLD WAY
	MOV	#TRNFLD,EXTEN1	;SET UP TWO FIELD ADDRESSES
	MOV	#EXTFLD,EXTEN2

; CHECK FOR OBJ AND LIST FILES IN CSI LINE
11$:	CLR	OBJFL		;INIT OBJ AND LIST FLAGS
	CLR	LISTFL
	.WAIT	#0		;CHECK IF OBJ FILE OPENED
	BCS	3$
	INC	OBJFL		;SET OBJ FLAG
3$:	MOV	#131.-29.,LINSIZ	;DEFAULT TO LINE PRINTER
	.WAIT	#1
	BCS	7$		;IF NO LIST FILE
	INC	LISTFL
	TST	TTYFL
	BEQ	7$		;IF NOT NARROW
	MOV	#71.-18.,LINSIZ
7$:	RETURN

2$:	.PRINT	#STFAIL
	.EXIT

STFAIL:	.ASCIZ	/?MICRO-F-Not enough memory for symbol table/
	.EVEN

ILC:	.PRINT	#ILCM		;ILLEGAL COMMAND
	.EXIT

ILCM:	.ASCIZ	/?MICRO-F-Illegal command line/
	.EVEN

; DEFAULT EXTENSION TABLE
DEXT:	.RAD50	/MIC/		;INPUT FILES
	.RAD50	/OBJ/		;OUTPUT FILES
	.RAD50	/LST/		;LISTING

SPACE:	.LIMIT			;CORE LIMIT IN 2ND WORD

SWTTBL:	.WORD	'B,BITFL
	.WORD	'C,CRFFL
	.WORD	'M,MODE
	.WORD	'N,TTYFL
	.WORD	'O,OLDFMT
	.WORD	'W,WCSFL
	.WORD	0

OUTSPC:	.BLKW	5
LSTSPC:	.BLKW	5
CRFSPC:	.BLKW	5
	.BLKW	24.

CRFSYS:	.RAD50	/SY CREF  TMP/
PROMPT:	.BYTE	'*,200

	.WORD	CRFERR
	.WORD	SWTMSG
	.WORD	VERMSG
OPNERR:	.WORD	ILLCMD
	.WORD	ILLDEV
	.WORD	0
	.WORD	DEVFUL
	.WORD	FNFMSG

CRFERR:	.ASCIZ	/?MICRO-F-Insufficient space for cross-reference temporary file/
SWTMSG:.ASCII	%?MICRO-F-Undefined switch "/%
SWTNAM:	.ASCIZ	/ "/
VERMSG:	.ASCIZ	/MICRO	V01.01/
ILLCMD:	.ASCIZ	/?MICRO-F-Illegal command format/
ILLDEV:	.ASCIZ	/?MICRO-F-Illegal device specification/
DEVFUL:	.ASCIZ	/?MICRO-F-Output device full/
FNFMSG:	.ASCIZ	/?MICRO-F-Input file not found/
MODERR:	.ASCIZ	/?MICRO-F-Illegal MODE switch value/

LINBUF:	.BLKB	82.
	.EVEN
	.SBTTL	OBJ OUTPUT ROUTINES

; WRITE AN OBJ RECORD AND COMPUTE CHECKSUM
; 	R1 -> OBJ RECORD TO BE WRITTEN
;	R3 = BYTE COUNT
OBJWRT:	MOV	OBJPTR,R0	;R0 -> OBJBUF CURRENT POSITION
	CLR	CHKSUM
1$:	CMP	R0,#OBJBUF+512.
	BLO	3$		;IF MORE ROOM LEFT
	.WRITW	#AREA,#0,#OBJBUF,#256.,OBJBLK ;WRITE LAST BLOCK
	BCC	2$		;IF NO ERRORS
	.PRINT	#OBJERR
	.EXIT

2$:	MOV	#OBJBUF,R0	;RESET BUFFER POINTER
	INC	OBJBLK
3$:	CLR	R2		;GET AN OBJ BYTE TO WRITE
	BISB	(R1)+,R2
	MOVB	R2,(R0)+	;PUT IN OBJ BUFFER
	ADD	R2,CHKSUM	;ADD BYTE TO CHECKSUM
	DEC	R3
	BGT	1$		;IF MORE BYTES TO WRITE
	BLT	4$		;IF REALLY DONE WITH EVERYTHING
	MOV	#CHKSUM,R1	;WRITE THE CHECKSUM
	NEG	@R1
	BR	1$		;WRITE ONE MORE BYTE
4$:	MOV	R0,OBJPTR	;KEEP OBJ POINTER
	RETURN

OBJERR:	.ASCIZ	/?MICRO-F-Error writing OBJ file/

; WRITE SOME WORDS TO THE DATA RECORD AND WRITE IT IF NECESSARY
OUTDAT:	CMP	TXTPTR,#OBJEND
	BLO	1$		;IF ROOM IN CURRENT RECORD
	MOV	#TXTREC,R1
	MOV	BYTCNT,R3
	CALL	OBJWRT		;NO ROOM, WRITE THIS RECORD
	MOV	#10,BYTCNT	;START A NEW RECORD
	MOV	#OBJTXT,TXTPTR
	MOV	LOC,R0		;SET NEW LOCATION COUNTER
	ASL	R0
	ASL	R0
	ADD	#1000,R0	;OBJ ADDR = LOC*4+10000
	MOV	R0,OBJADR
1$:	MOV	(R5)+,R0	;GET ADDRESS OF BYTE TO MOVE
	BEQ	2$		;IF NO MORE BYTES
	MOVB	@R0,@TXTPTR	;MOVE A BYTE
	INC	BYTCNT		;COUNT THE DATA BYTE
	INC	TXTPTR
	BR	OUTDAT		;DO NEXT BYTE
2$:	RTS	R5


; OBJ TEXT RECORD
TXTREC:	.WORD	1	;TEXT RECORD
BYTCNT:	.WORD	0	;BYTE COUNT FOR RECORD
	.WORD	3	;RECORD TYPE 3=TXT REC
OBJADR:	.WORD	0	;LOAD ADDRESS
OBJTXT:	.BLKW	40.	;THE TEXT ITSELF
OBJEND:	
	.SBTTL	OUTPUT A MICRO WORD TO THE OUTPUT

; OUTPUT A MICRO WORD
; CHECK THAT IT IS NOT OVERLAYING A PREVIOUSLY ASSEMBLED LOCATION
	.ENABLE	LSB
OUTWRD:	TST	PASS
	BEQ	RETURN		;DONT DO ANYTHING ON PASS 1
	TST	OPNDFL
	BLE	RETURN		;IF NO OPRAND AT THIS LOC
	MOV	LOCADR,R0
	CMP	MODE,#2
	BNE	5$		;ALL MODES ARE EASY EXCEPT 2
	SUB	#10000,R0	;IF IN THE HIGH RANGE
	BGE	5$		; THEN ADDRESS IS NORMALIZED
	ADD	#10000-3000,R0	;OTHERWISE, DO LOW ADDRESSES
5$:	BIC	#^C<1777>,R0	;MAKE ADDRESS IN RANGE FOR RAM
	MOV	R0,RAMADR
	MOV	R0,R1		;R0,R1=MICRO PC
	ASR	R0
	ASR	R0
	ASR	R0		;R0=BYTE OFFSET INTO BITMAP
	BIC	#^C<7>,R1	;R1=BIT NUMBER TO USE
	BITB	BITS(R1),BITMAP(R0)
	BEQ	1$		;IF LOCATION IS UNUSED SO FAR
	ERROR	O,<Attempt to redefine previously-used location>
1$:	BISB	BITS(R1),BITMAP(R0)
	BITB	BITS(R1),BEARTP(R0) ;DEFINED TRANSLATION FOR THIS LOC?
	BEQ	2$		;IF EQ NO
	TST	TRANPR		;WAS A TRANSLATION PRESENT IN THE CODE?
	BNE	2$		;IF NE YES
	CMP	OPCLS,#CL.JMP	;UNCONDITIONAL JMP AT THIS ADRS?
	BEQ	2$		;IF EQ YES
	CMP	OPCLS,#CL.CJM	;OR CONDITIONAL TYPE?
	BEQ	2$		;IF EQ YES
	CMP	OPCLS,#CL.JSR
	BEQ	2$		;JSR IS A JUMP
	CMP	OPCLS,#CL.RFS
	BEQ	2$		;RFS CHANGES PC ON TRANS ALSO
	ERROR	T,<Predefined PLA translation at this microlocation>
2$:	TST	WCSFL		;ASSEMBLING TO WCS?
	BEQ	3$		;IF EQ NO
	MOV	RAMADR,@#WCSSTS	;ELSE LOAD ADRS
	MOV	OPL,@#WCSLOW	;AND LOW DATA
	MOV	OPH,@#WCSHGH	;AND HIGH DATA
3$:	TST	OBJFL
	BEQ	4$		;IF NO OBJ FILE
	JSR	R5,OUTDAT	;WRITE THE 4 BYTES IN THE OBJ
	.WORD	OPL,OPL+1,OPH,OPH+1,0
4$:	RETURN
	.DSABL	LSB

BITS:	.BYTE	1,2,4,10,20,40,100,200
	.SBTTL	BEARTRAP LOCATION DEFINITIONS

; BEARTRAP LOCATIONS IN THE EIS/FIS REGION:
BEAR	<2033>	;EII
BEAR	<2072>	;EII
BEAR	<2123>	;PSW
BEAR	<2172>	;PSW
BEAR	<2220>	;FII
BEAR	<2254>	;FII
BEAR	<2274>	;FII
BEAR	<2320>	;FII
BEAR	<2406>	;FII
BEAR	<2447>	;EII
BEAR	<2500>	;EII
BEAR	<2516>	;PSW
BEAR	<2540>	;EII
BEAR	<2571>	;DMW
BEAR	<2604>	;EII
BEAR	<2614>	;EII
BEAR	<2622>	;PSW
BEAR	<2630>	;PSW
BEAR	<2644>	;EII
BEAR	<2654>	;EII
BEAR	<2700>	;EII
BEAR	<2710,2714,2717>	;EII,PSW,PSW
BEAR	<2740>	;EII
BEAR	<2750,2754>	;EII,PSW
BEAR	<2550,2551,2552,2553>	;RET,RET,RET,RET
	.SBTTL	PRINT OS/8 STYLE BIT MAP ON LISTING FILE

PRBTMP:	TST	LISTFL
	BEQ	RETURN		;NOT IF NO OUTPUT FILES
	TST	BITFL		;IS BITMAP SWITCH SET?
	BEQ	RETURN		;IF EQ NO
	CLR	LINCNT		;FORCE TOP OF PAGE
	MOV	#MEMBIT,R0
	MOV	#SBTTL,R1	;PUT TITLE ON BITMAP
7$:	MOVB	(R0)+,(R1)+
	BNE	7$
	MOV	#BITM1,R2	;OUTPUT HEADER LINE 1
	CALL	PRNTR2
	MOV	#BITM2,R2	;OUTPUT HEADER LINE 2
	CALL	PRNTR2
	MOV	#BITBL,R2	;AND A BLANK LINE
	CALL	PRNTR2
	MOV	#BITMAP,R3	;R3 -> BITMAP BYTE TABLE
	CLR	R5		;R5 = LOCATION CURRENTLY MAPPED
1$:	MOV	#OUTLN,R4	;R4 -> OUTPUT LINE
	MOV	R5,R0
	MOV	MODE,R2		;RECONVERT ADDRESS BASED ON MODE
	ASL	R2
	JMP	@10$-2(R2)
10$:	.WORD	11$,12$,13$,14$

; MODE 1 AND 3
11$:
13$:	ADD	#2000,R0
	BR	14$		;EASY MODE

; MODE 2
12$:	ADD	#3000,R0
	CMP	R0,#4000
	BLO	14$		;IF IN 1ST HALF OF RAM
	ADD	#10000-1000,R0	;MAKE 2ND HALF ADDRESS

; MODE 4 MERGES HERE
14$:	CALL	OCT12		;CONVERT LOCATION
	MOVB	#' ,(R4)+	
	CLR	R2		;LOOK FOR EMPTY ROW
2$:	MOVB	#' ,(R4)+
	MOVB	(R3)+,R0	;R0 = BYTE TO OUTPUT
	BIS	R0,R2		;OR ALL BITS FROM ROW
	SEC
3$:	MOV	#'0,R1		;ASSUME A ZERO
	RORB	R0
	BEQ	4$		;IF AT END OF BYTE
	ADC	R1		;ADD IN ACTUAL BIT
	MOVB	R1,(R4)+	;PUT BIT IN OUTPUT LINE
	BR	3$

4$:	ADD	#10,R5		;SKIP TO NEXT BLOCK OF 8 WORDS
	BIT	#77,R5
	BNE	2$		;IF NOT AT END OF LINE
	TST	R2
	BNE	6$		;IF AT LEAST ONE BIT ON ROW
	MOV	#OUTLN+5,R4	;IF NO BITS, ONLY PRINT ADDR
6$:	MOVB	#CR,(R4)+
	MOVB	#LF,(R4)+
	BIT	#777,R5
	BNE	5$		;IF NOT END OF BLOCK
	DEC	LINCNT		;THIS IS EXTRA LINE
	MOVB	#CR,(R4)+	;PUT OUT EXTRA BLANK LINE
	MOVB	#LF,(R4)+
5$:	CLRB	(R4)+		;INDICATE END OF LINE
	CALL	PRTLN		;PRINT THE LINE
	CMP	R5,#2000
	BLO	1$		;IF MORE BITS TO DO
	RETURN

BITM1:	.ASCII	/Micro    00       10       20       30       40    /
	.ASCIZ	/   50       60       70   /<CR><LF>
BITM2:	.ASCII	/Adrs+ 01234567 01234567 01234567 01234567 01234567 /
	.ASCII	/01234567 01234567 01234567/
BITBL:	.ASCIZ	<CR><LF>
MEMBIT:	.ASCIZ	/Bitmap of Microlocations Used/
	.EVEN
	.SBTTL	PRINT A LINE BY MOVING IT TO THE OUTPUT BUFFER

; PRINT
; MOVE THE LINE TO THE OUTPUT BUFFER AND SEND THE BUFFER IF NECESSARY
	.ENABL	LSB
PRINT:	TST	PASS
	BEQ	RETURN		;NO LISTING ON PASS 1
	TST	LISTFL
	BNE	6$		;IF GETTING  LISTING
	CMP	#ERRBUF,MSGPTR
	BEQ	9$		;IF NO ERRORS ON LINE
6$:	MOV	#OUTLIN,R4
	MOV	LINE,R0
	CALL	DEC5		;CONVERT LINE # FOR OUTPUT
	TST	OPNDFL
	BEQ	PRTLN		;IF ONLY COMMENT LINE
	MOV	#OUTLC,R4	;PRINT LOCATION COUNTER
	MOV	LOCADR,R0
	CALL	OCT12		;12 BITS
	TST	TTYFL
	BEQ	4$		;IF WIDE DEFAULT LISTING
	MOV	#IN-1,R0	;MOVE INPUT LINE DOWN AFTER LOC CTR
12$:	MOVB	(R0)+,(R4)+	;MOVE A BYTE
	BNE	12$		;IF NOT AT END
	BR	PRTLN		;PRINT SHORTEND LINE
4$:	TST	OPNDFL
	BLE	PRTLN		;IF NO OPERAND TO PRINT
	MOV	OPH,R0
	INC	R4		;PASS SPACE
	CALL	OCTBYT		;HIGH ORDER WORD
	INC	R4
	MOV	OPL,R0		;LOW ORDER WORD (INSTRUCTION)
	CALL	OCTOUT		;ALL 16 BITS
PRTLN:	MOV	#OUTLN,R2	;R2 -> LINE TO BE PRINTED
PRNTR2:	MOV	OUTPTR,R0	;R0 -> NEXT FREE CHARACTER IN BUFFER
8$:	TST	LISTFL
	BNE	10$		;IF LISTING
	MOV	R2,R0
	.PRINT			;PRINT ERROR ON TTY
	BR	7$
10$:	DEC	LINCNT		;ANY LINES LEFT ON CURRENT PAGE?
	BPL	11$		;IF PL YES
	MOV	R2,-(SP)	;SAVE VOLATILE REGS
	MOV	R0,-(SP)
	MOV	#PAGENM,R4
	INC	PAGE
	MOV	PAGE,R0
	CALL	DEC5		;FORMAT PAGE #
	MOV	(SP)+,R0	;RESTORE OUTPUT POINTER
	MOV	#TITLE-1,R2
	CALL	1$		;PRINT THE TITLE
	MOV	#HEADER,R2	;POINT TO LISTING HEADER
	CALL	1$		;AND OUTPUT IT
	MOV	#SBTTL,R2	;POINT TO SUBTITLE LINE
	CALL	1$		;AND OUTPUT IT
	MOV	#CRLF,R2	;TERMINATE SUBTITLE AND
	CALL	1$		;LEAVE A BLANK LINE
	MOV	(SP)+,R2
	MOV	#55.,LINCNT	;SET LINES LEFT
11$:	CALL	1$		;OUTPUT LINE
7$:	MOV	#ERRBUF,R2	;MOVE ERROR MESSAGES IN AFTER LINE
	CMP	R2,MSGPTR
	BEQ	5$		;IF NO ERRORS ON THIS LINE
	MOV	R2,MSGPTR
	BR	8$		;NOW MOVE IN ERROR TEXT
5$:	MOV	R0,OUTPTR
9$:	CLR	OPNDFL		;RESET FLAG FOR NEXT TIME
	RETURN

1$:	CMP	R0,#OUTBUF+512.
	BLO	3$		;IF MORE ROOM FOR THIS CHARACTER
	.WRITW	#AREA,#1,#OUTBUF,#256.,OUTBLK
	BCC	2$		;IF OUTPUT WENT OK
	.PRINT	#WRERR		;GOT AN ERROR
	.EXIT
2$:	MOV	#OUTBUF,R0	;R0 -> START OF OUTPUT BUFFER
	INC	OUTBLK		;NEXT BLOCK
3$:	MOVB	(R2)+,(R0)+
	BNE	1$		;LOOP MOVING CHARACTERS
	DEC	R0		;DISCARD NULL
	RETURN

	.DSABL	LSB

WRERR:	.ASCIZ	/?MICRO-F-Output error on listing file/
HEADER:	.ASCII	/ MICRO V01.01  /
DATE:	.ASCII	/99-XXX-99 /
TIME:	.ASCII	/99:99:99/
PAGEST:	.ASCII	/ PAGE /
PAGENM:	.ASCIZ	/     /<CR><LF>
CRLF:	.ASCIZ	<CR><LF><CR><LF>
	.EVEN
	.SBTTL	PRINT SYMBOL TABLE IN LISTING

; PRTSYM
; PRINTS SYMBOL TABLE INTO LISTING FILE

PRTSYM:	TST	LISTFL		;LISTING REQUESTED?
	BEQ	RETURN		;IF EQ NO
	CLR	LINCNT		;GET NEW PAGE
	MOV	#SYMSBT,R0	;POINT TO OUR SUBTITLE LINE
	MOV	#SBTTL,R1	;AND THE SUBTITLE BUFFER
1$:	MOVB	(R0)+,(R1)+	;COPY SUBTITLE
	BNE	1$
	MOV	#BUCKET,R5	;INIT POINTER FOR PRTNXT
	MOV	R5,BCKPTR
2$:	MOV	#5.,R3		;R3 = # OF COLUMNS TO PRINT
	MOV	#OUTLN,R4	;R4 -> OUTPUT LINE BUFFER
3$:	CALL	PRTNXT		;SET R5 -> NEXT SYMBOL TO OUTPUT
	BCS	9$		;IF CS, NONE LEFT
	MOVB	(R5)+,(R4)+	;COPY SYMBOL TO OUTPUT LINE
	MOVB	(R5)+,(R4)+
	MOVB	(R5)+,(R4)+
	MOVB	(R5)+,(R4)+
	MOVB	(R5)+,(R4)+
	MOVB	(R5)+,(R4)+
	MOV	(R5)+,R0	;R0 = ADRS FOR SYMBOL
	MOVB	#40,(R4)+	;ASSUME BLANK, NOT EQUATED
	BIT	#ST.EQU,@R5	;WAS EQUATE DONE?
	BEQ	4$		;IF EQ NO
	MOVB	#'=,-1(R4)	;MAKE IT EQUATED
4$:	MOVB	#'*,@R4		;ASSUME NO VALUE, ****
	MOVB	(R4)+,@R4
	MOVB	(R4)+,@R4
	MOVB	(R4)+,(R4)+
	MOVB	#40,(R4)+	;BLANK AT END
	BIT	#ST.DFN!ST.EQU,@R5 ;DOES SYMBOL HAVE A VALUE?
	BEQ	5$		;IF EQ NO
	SUB	#5,R4		;BACK UP TO ADDR OF VALUE IN LINE
	CALL	OCT12		;CONVERT TO 5 OCTAL DIGITS
5$:	MOV	R4,R0		;REMEMBER OUTPUT LOCATION
	MOV	(R5)+,R1	;PICK UP STATUS FLAGS
	MOVB	#40,@R4		;PRE-BLANK STATUS AREA (4 BYTES)
	MOVB	(R4)+,@R4
	MOVB	(R4)+,@R4
	MOVB	(R4)+,(R4)+
	BIT	#ST.REG,R1	;DEFINED AS REGISTER?
	BEQ	6$		;IF EQ NO
	MOVB	#'R,(R0)+	;ELSE OUTPUT "R" FLAG
6$:	BIT	#ST.TRN,R1	;IS THIS A TRANSLATION SYMBOL?
	BEQ	7$		;IF EQ NO
	MOVB	#'T,(R0)+	;ELSE FLAG AS SUCH
7$:	BIT	#ST.EXT,R1	;SYMBOL DEFINES EXTENSION BITS?
	BEQ	8$		;IF EQ NO
	MOVB	#'X,(R0)+	;ELSE FLAG
8$:	DEC	R3		;COUNT DOWN NUMBER OF OUTPUT COLUMNS
	BNE	3$		;IF NE, MORE TO DO ON THIS LINE
	CALL	9$		;ELSE OUTPUT LINE
	BR	2$		;AND CONTINUE

9$:	CMP	R4,#OUTLN	;ANYTHING ON THIS LINE?
	BEQ	10$		;IF EQ NO
	MOVB	#CR,(R4)+	;INSTALL LINE
	MOVB	#LF,(R4)+	; TERMINATORS
	CLRB	@R4		;MAKE IT ASCIZ
	MOV	#OUTLN,R2	;GET ADDRESS
	CALL	PRNTR2		;AND PRINT THE LINE
10$:	RETURN

PRTNXT:	MOV	@R5,R5		;LINK TO NEXT SYMTAB ENTRY
	BNE	1$		;IF NE, SOME LEFT ON THIS BUCKET
	ADD	#2,BCKPTR	;ELSE BUMP BUCKET POINTER
	MOV	BCKPTR,R5	;AND GET THE NEXT BUCKET
	CMP	R5,#BCKEND	;FINISHED ALL BUCKETS?
	BLO	PRTNXT		;IF LO NO
	BR	2$		;ELSE RETURN ERROR

1$:	TST	(PC)+		;CLEAR CARRY (NO ERROR)
2$:	SEC			;INDICATE NO SYMBOLS LEFT
	RETURN

SYMSBT:	.ASCIZ	/Symbol Table/
	.EVEN
	.SBTTL	READ A LINE FROM THE INPUT FILE

; READ
; GET THE NEXT LINE FROM THE INPUT FILE
READ:	CLR	EOF		;DEFAULT NOT AT EOF
	MOV	#LINEND,R2
3$:	MOVB	#' ,-(R2)	;MOVE IN BLANKS
	CMP	R2,#OUTLN
	BNE	3$
	MOV	#IN-1,R2	;R2 -> INPUT LINE
	MOVB	#40,(R2)+	;START AT GOOD SPOT
	MOV	INPTR,R0	;R0 -> INPUT BUFFER POINTER
	CLR	R3		;COLUMN COUNTER INIT 0
2$:	CMP	R0,#INBUF+512.
	BLO	1$		;IF A CHARACTER IN BUFFER
	.READW	#AREA,#3,#INBUF,#256.,INBLK
	BCC	4$		;IF NO ERRORS
	INC	EOF		;IF END OF FILE
	RETURN			;ASSUME EOF ON ERRORS
4$:	MOV	#INBUF,R0	;NEW BUFFER POINTER
	INC	INBLK		;BUMP BLOCK NUMBER

1$:	MOVB	(R0)+,R1	;GET A CHARACTER
	BEQ	2$		;SKIP OVER NULLS
	CMPB	R1,#FF		;FORM FEED EMBEDDED?
	BNE	5$		;IF NE NO
	CLR	LINCNT		;ELSE FORCE NEW OUTPUT PAGE
	BR	2$		;AND IGNORE CHARACTER

5$:	INC	R3		;GO TO NEXT COLUMN
	CMP	R3,LINSIZ
	BGE	7$		;IF AT THE END OF THE LINE
	CMPB	R1,#TAB
	BNE	8$		;IF NOT A TAB TO EXPAND
	MOVB	#40,(R2)+	;REPLACE TAB WITH AT LEAST ONE BLANK
	BIT	#7,R3
	BNE	5$		;IF MORE SPACES TO NEXT TAB STOP
	BR	2$		;IF ALREADY THERE, DO NEXT CHARACTER
8$:	MOVB	R1,(R2)+	;PUT IT IN THE LINE BUFFER
7$:	CMPB	R1,#LF
	BNE	2$		;IF NOT THE END OF LINE
	MOV	R0,INPTR	;NEW INPUT POINTER
	CMPB	-1(R2),#LF
	BEQ	6$		;IF LINE REALLY ENDED IN LF
	MOVB	#LF,-1(R2)	; OTHERWISE PUT IN CR AND LF SO IT
	MOVB	#CR,-2(R2)	;  WILL PRINT CORRECTLY
6$:	CLRB	(R2)+
	RETURN

RDERR:	.ASCIZ	/?MICRO-F-Error reading input file/
	.EVEN
	.SBTTL	PROCESS REGISTER OPERANDS

; REG
; GET REGISTER AS ANY EXPRESSION
REG:	CALL	EXPR		;GET EXPRESSION
	CMP	R1,#17
	BLOS	RETURN		;IF IN RANGE
	ERROR	R,<Illegal register value>
	CLR	R1		;SET GL AS VALUE
	RETURN



; ENTER REGISTER NAME IN SYMBOL TABLE AND SET ATTRIBUTES
	.ENABL	LSB
REGENT:	CALL	ENTERD		;ENTER SYMBOL
	BIT	#ST.DFN,SY.STS(R0)
	BEQ	1$		;IF NOT PREVIOUSLY A LABEL
	ERROR	R,<Register "@" previously declared as a label>
	RETURN
1$:	BIS	#ST.EQU!ST.REG,SY.STS(R0) ;MAKE IT A REGISTER IN TBL
	RETURN
	.DSABL	LSB




	.SBTTL	SKIP TO NEXT FIELD

; STNF
; SKIP TO NEXT FIELD
STNF:	MOVB	(R5)+,R0	;GET CURRENT CHARACTER
	CMPB	R0,#40
	BEQ	STNF		;IF A BLANK
	CMPB	R0,#TAB
	BEQ	STNF		;IF A TAB
	DEC	R5		;SET TO REPEAT NEXT CHARACTER
	RETURN
	.SBTTL	OPCODE TABLES

; OPCODE TABLES DRIVE THE ASSEMBLE PROCESS
; THE TABLES CONTAIN THE OPCODE, THE NAME, AND THE CLASS OF
; OPERATION TO ALLOW CORRECT OPERAND PROCESSING.

OPTBL:
OP	<.END  >,CL.END,0
OP	<.PAGE >,CL.PAG,0
OP	<.SBTTL>,CL.SBT,0
OP	<.TITLE>,CL.TTL,0
OP	<AB    >,CL.REG,120000
OP	<ABC   >,CL.REG,124000
OP	<ABCF  >,CL.REG,124400
OP	<ABF   >,CL.REG,120400
OP	<AL    >,CL.LIT,20000
OP	<AW    >,CL.REG,121000
OP	<AWC   >,CL.REG,125000
OP	<AWCF  >,CL.REG,125400
OP	<AWF   >,CL.REG,121400
OP	<CAB   >,CL.REG,122000
OP	<CABF  >,CL.REG,122400
OP	<CAD   >,CL.REG,126000
OP	<CAI   >,CL.REG,127000
OP	<CAIF  >,CL.REG,127400
OP	<CAW   >,CL.REG,123000
OP	<CAWF  >,CL.REG,123400
OP	<CB    >,CL.REG,132000
OP	<CBF   >,CL.REG,132400
OP	<CCF   >,CL.AFL,71000
OP	<CDB   >,CL.AFL,73400
OP	<CIB   >,CL.AFL,73000
OP	<CL    >,CL.LIT,30000
OP	<CMB   >,CL.REG,102000
OP	<CMBF  >,CL.REG,102400
OP	<CMW   >,CL.REG,103000
OP	<CMWF  >,CL.REG,103400
OP	<CW    >,CL.REG,133000
OP	<CWF   >,CL.REG,133400
OP	<DB1   >,CL.REG,136000
OP	<DB1F  >,CL.REG,136400
OP	<DW1   >,CL.REG,137000
OP	<DW1F  >,CL.REG,137400
OP	<EMPTY2>,CL.DUM,0
OP	<EMPTY3>,CL.DUM,0
OP	<END   >,CL.END,0
OP	<IB    >,CL.IW,160000
OP	<IBF   >,CL.IW,160400
OP	<ICB1  >,CL.REG,110000
OP	<ICB1F >,CL.REG,110400
OP	<ICB2  >,CL.REG,112000
OP	<ICB2F >,CL.REG,112400
OP	<ICW1  >,CL.REG,111000
OP	<ICW1F >,CL.REG,111400
OP	<ICW2  >,CL.REG,113000
OP	<ICW2F >,CL.REG,113400
OP	<ISB   >,CL.IW,162000
OP	<ISBF  >,CL.IW,162400
OP	<ISW   >,CL.REG,163000
OP	<ISWF  >,CL.REG,163400
OP	<IW    >,CL.IW,161000
OP	<IWF   >,CL.IW,161400
OP	<JC8F  >,CL.CJM,11000
OP	<JC8T  >,CL.CJM,11400
OP	<JCF   >,CL.CJM,15000
OP	<JCT   >,CL.CJM,15400
OP	<JIF   >,CL.CJM,12000
OP	<JIT   >,CL.CJM,12400
OP	<JMP   >,CL.JMP,0
OP	<JNBF  >,CL.CJM,13000
OP	<JNBT  >,CL.CJM,13400
OP	<JNF   >,CL.CJM,17000
OP	<JNT   >,CL.CJM,17400
OP	<JSR   >,CL.JSR,0
OP	<JVF   >,CL.CJM,16000
OP	<JVT   >,CL.CJM,16400
OP	<JZBF  >,CL.CJM,10000
OP	<JZBT  >,CL.CJM,10400
OP	<JZF   >,CL.CJM,14000
OP	<JZT   >,CL.CJM,14400
OP	<LCF   >,CL.REG,71400
OP	<LGL   >,CL.AFL,72400
OP	<LL    >,CL.LIT,60000
OP	<LOC   >,CL.LOC,0
OP	<LTR   >,CL.REG,167000
OP	<MB    >,CL.REG,100000
OP	<MBF   >,CL.REG,100400
OP	<MI    >,CL.REG,166000
OP	<MODE  >,CL.MOD,0
OP	<MW    >,CL.REG,101000
OP	<MWF   >,CL.REG,101400
OP	<NB    >,CL.REG,140000
OP	<NBF   >,CL.REG,140400
OP	<NCB   >,CL.REG,150000
OP	<NCBF  >,CL.REG,150400
OP	<NCW   >,CL.REG,151000
OP	<NCWF  >,CL.REG,151400
OP	<NL    >,CL.LIT,40000
OP	<NOP   >,CL.RFS,177400
OP	<NW    >,CL.REG,141000
OP	<NWF   >,CL.REG,141400
OP	<NXT10 >,CL.NXT,10-1*400
OP	<NXT100>,CL.NXT,100-1*400
OP	<NXT2  >,CL.NXT,2-1*400
OP	<NXT20 >,CL.NXT,20-1*400
OP	<NXT200>,CL.NXT,200-1*400
OP	<NXT4  >,CL.NXT,4-1*400
OP	<NXT40 >,CL.NXT,40-1*400
OP	<NXT400>,CL.NXT,400-1*400
OP	<OB    >,CL.REG,176000
OP	<OCB   >,CL.REG,116000
OP	<OCBF  >,CL.REG,116400
OP	<OCW   >,CL.REG,117000
OP	<OCWF  >,CL.REG,117400
OP	<ORB   >,CL.REG,144000
OP	<ORBF  >,CL.REG,144400
OP	<ORW   >,CL.REG,145000
OP	<ORWF  >,CL.REG,145400
OP	<OS    >,CL.REG,177000
OP	<OW    >,CL.REG,176400
OP	<PAGE  >,CL.PAG,0
OP	<R     >,CL.REG,174000
OP	<RA    >,CL.REG,175000
OP	<REG   >,CL.RDF,0
OP	<RF    >,CL.BFL,70000
OP	<RFS   >,CL.RFS,4000
OP	<RI    >,CL.BFL,70000
OP	<RIB1  >,CL.REG,170000
OP	<RIB2  >,CL.REG,172000
OP	<RIW1  >,CL.REG,171000
OP	<RIW2  >,CL.REG,173000
OP	<RTSR  >,CL.RFS,72000
OP	<SB    >,CL.REG,130000
OP	<SBC   >,CL.REG,134000
OP	<SBCF  >,CL.REG,134400
OP	<SBF   >,CL.REG,130400
OP	<SBTTL >,CL.SBT,0
OP	<SF    >,CL.BFL,70400
OP	<SI    >,CL.BFL,70400
OP	<SLB   >,CL.REG,106000
OP	<SLBC  >,CL.REG,104000
OP	<SLBCF >,CL.REG,104400
OP	<SLBF  >,CL.REG,106400
OP	<SLW   >,CL.REG,107000
OP	<SLWC  >,CL.REG,105000
OP	<SLWCF >,CL.REG,105400
OP	<SLWF  >,CL.REG,107400
OP	<SRB   >,CL.REG,156000
OP	<SRBC  >,CL.REG,154000
OP	<SRBCF >,CL.REG,154400
OP	<SRBF  >,CL.REG,156400
OP	<SRW   >,CL.REG,157000
OP	<SRWC  >,CL.REG,155000
OP	<SRWCF >,CL.REG,155400
OP	<SRWF  >,CL.REG,157400
OP	<SW    >,CL.REG,131000
OP	<SWC   >,CL.REG,135000
OP	<SWCF  >,CL.REG,135400
OP	<SWF   >,CL.REG,131400
OP	<TB    >,CL.REG,142000
OP	<TBF   >,CL.REG,142400
OP	<TCB   >,CL.REG,114000
OP	<TCBF  >,CL.REG,114400
OP	<TCW   >,CL.REG,115000
OP	<TCWF  >,CL.REG,115400
OP	<TITLE >,CL.TTL,0
OP	<TL    >,CL.LIT,50000
OP	<TRAN  >,CL.TRN,0
OP	<TW    >,CL.REG,143000
OP	<TWF   >,CL.REG,143400
OP	<W     >,CL.REG,174400
OP	<WA    >,CL.REG,175400
OP	<WIB1  >,CL.REG,170400
OP	<WIB2  >,CL.REG,172400
OP	<WIW1  >,CL.REG,171400
OP	<WIW2  >,CL.REG,173400
OP	<XB    >,CL.REG,146000
OP	<XBF   >,CL.REG,146400
OP	<XW    >,CL.REG,147000
OP	<XWF   >,CL.REG,147400
OPTBLE:	.WORD	0,0,0
	.SBTTL	PREDEFINED SYMBOLS

; THE FOLLOWING SYMBOLS ARE ENTERED INTO THE SYMBOL TABLE BY
; OPEN AT THE START OF AN ASSEMBLY.  THIS ASSURES THE REGISTERS
; ETC. TO BE DEFINED.
PREDF:	SYMBOL	<G     >,0,	ST.EQU!ST.REG
	SYMBOL	<GL    >,0,	ST.EQU!ST.REG
	SYMBOL	<GH    >,1,	ST.EQU!ST.REG
	SYMBOL	<RBA   >,2,	ST.EQU!ST.REG
	SYMBOL	<RBAL  >,2,	ST.EQU!ST.REG
	SYMBOL	<RBAH  >,3,	ST.EQU!ST.REG
	SYMBOL	<RSRC  >,4,	ST.EQU!ST.REG
	SYMBOL	<RSRCL >,4,	ST.EQU!ST.REG
	SYMBOL	<RSRCH >,5,	ST.EQU!ST.REG
	SYMBOL	<RDST  >,6,	ST.EQU!ST.REG
	SYMBOL	<RDSTL >,6,	ST.EQU!ST.REG
	SYMBOL	<RDSTH >,7,	ST.EQU!ST.REG
	SYMBOL	<RIR   >,10,	ST.EQU!ST.REG
	SYMBOL	<RIRL  >,10,	ST.EQU!ST.REG
	SYMBOL	<RIRH  >,11,	ST.EQU!ST.REG
	SYMBOL	<RPSW  >,12,	ST.EQU!ST.REG
	SYMBOL	<RPSWL >,12,	ST.EQU!ST.REG
	SYMBOL	<RPSWH >,13,	ST.EQU!ST.REG
	SYMBOL	<SP    >,14,	ST.EQU!ST.REG
	SYMBOL	<SPL   >,14,	ST.EQU!ST.REG
	SYMBOL	<SPH   >,15,	ST.EQU!ST.REG
	SYMBOL	<PC    >,16,	ST.EQU!ST.REG
	SYMBOL	<PCL   >,16,	ST.EQU!ST.REG
	SYMBOL	<PCH   >,17,	ST.EQU!ST.REG
	SYMBOL	<I4    >,1,	ST.EQU
	SYMBOL	<I5    >,2,	ST.EQU
	SYMBOL	<I6    >,4,	ST.EQU
	SYMBOL	<C     >,1,	ST.EQU
	SYMBOL	<V     >,2,	ST.EQU
	SYMBOL	<Z     >,4,	ST.EQU
	SYMBOL	<N     >,10,	ST.EQU
	SYMBOL	<C8    >,20,	ST.EQU
	SYMBOL	<C4    >,40,	ST.EQU
	SYMBOL	<ZB    >,100,	ST.EQU
	SYMBOL	<NB    >,200,	ST.EQU
	SYMBOL	<UB    >,0,	ST.EQU
	SYMBOL	<LB    >,1,	ST.EQU
	SYMBOL	<UBC   >,2,	ST.EQU
	SYMBOL	<LBC   >,3,	ST.EQU
	SYMBOL	<RMW   >,4,	ST.EQU
	SYMBOL	<TG6   >,1,	ST.EQU
	SYMBOL	<TG8   >,2,	ST.EQU
	SYMBOL	<LRR   >,1,	ST.EQU!ST.EXT
	SYMBOL	<RSVC  >,2,	ST.EQU!ST.EXT
	SYMBOL	<TROFF >,200,	ST.EQU!ST.EXT
	SYMBOL	<TGL   >,34,	ST.EQU!ST.EXT
	.WORD	0,0,0
	.SBTTL	CHARACTER CLASS TABLE

; CLASS
; EACH CHARACTER FROM 0-177 HAS A SPECIAL CLASS
; THE CHOICES ARE:
C.ALPH=	0	;ALPHABETIC
C.NMBR=	2	;NUMERIC
C.SPCL=	4	;SPECIAL CHARACTER

CLASS:	BYTES	10,C.SPCL	;0-7
	BYTES	10,C.SPCL	;10-17
	BYTES	10,C.SPCL	;20-27
	BYTES	10,C.SPCL	;30-37
	BYTES	4,C.SPCL	;40-43
	BYTES	1,C.ALPH	;44 (DOLLAR)
	BYTES	3,C.SPCL	;45-47
	BYTES	6,C.SPCL	;50-55
	BYTES	1,C.ALPH	;56 (DOT)
	BYTES	1,C.SPCL
	BYTES	10,C.NMBR	;60-67 (0-7)
	BYTES	2,C.NMBR	;70-71 (8-9)
	BYTES	6,C.SPCL	;72-77
	BYTES	1,C.SPCL	;100
	BYTES	26.,C.ALPH	;101-132 (A-Z)
	BYTES	45,C.SPCL	;133-177

	.END	MICASM
