TITLE	RTSODT,<OCTAL DEBUGGING TOOL FOR RSTS V06)>,06,22-JUL-74,<TPH/MHB>

.SBTTL	COPYRIGHT 1972,1973
.SBTTL	BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. 01754
.SBTTL					
.SBTTL	DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY
.SBTTL	FOR THE USE OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT
.SBTTL	WHICH IS NOT SUPPLIED BY DEC.
.SBTTL					
	ORG	VE	;DEFINE VECTOR START

	ORG	ODT	;DEFINE ODT START

	ORG	ODTVE	;DEFINE ODT VECTOR START
	.SBTTL	USER STATE AREA AND DATA CONTROL

;SOME ODT TYPE DEFINITIONS (THESE ARE NOT PARAMETERS).

O.BKP	=16		;NUMBER OF BREAKPTS-1 X 2
O.RLR	=16		;NUMBER OF CORE RELOC. REGISTERS -1 X 2
O.TBT	=20		;T-BIT MASK, PROCESSOR STATUS

;SET UP THE REAL THING FINALLY

	ORG	ODT,40		;LEAVE SOME ODT STACK SPACE
ODTSTK:

;THE ORDER OF THESE ITEMS IS INTENTIONAL, SEE REGISTER MAPPING SCHEME

INTBEG	=.	;STARTING ADDRESS OF INTERNAL REGISTERS

O.UR0:	0	;USER R0			$0
	0	;     R1			$1
	0	;     R2			$2
	0	;     R3			$3
	0	;     R4			$3
	0	;     R5			$5
O.USP:	0	;USER SP			$6
O.UPC:	0	;USER PC			$7
O.UST:	0	;USER ST			$S
O.ARG:	0	;ARGUMENT REGISTER		$A
O.MSK:	-1	;MASK				$M
O.LOW:	0	;LOW LIMIT			$L
O.HI:	ODT	;HIGH LIMIT			$H
O.CNST:	O.ODT	;CONSTANT REGISTER		$C
O.QUAN:	0	;QUANTITY REGISTER		$Q
O.FORM:	0	;FORMAT REGISTER		$F
O.JOB:	0	;ODT OWNER JOB INDEX
	.SBTTL	BREAKPOINT AND RELOCATION TABLES

INTINX	=.		;STARTING ADDRESS OF INTERNAL TABLES

;BREAKPOINT CONTROL LISTS

O.ADR1:		;ADDRESS OF THE BREAKPOINT	($0B-$7B)
	.WORD	O.TRTC,O.TRTC,O.TRTC,O.TRTC,O.TRTC,O.TRTC,O.TRTC,O.TRTC,O.TRTC

O.CT:		;PROCEED COUNT	($0G-$7G)
	.WORD	0,0,0,0,0,0,0,0,0

O.UIN:		;USER INSTRUCTION SAVE LOCATION	($0I-$7I)
	.WORD	BPT,BPT,BPT,BPT,BPT,BPT,BPT,BPT,BPT

;RELOCATION REGISTERS

O.RELT:		;RELOCATION TABLES	($0R-$7R)
	.WORD	-1,-1,-1,-1,-1,-1,-1,-1
INTEND	=.-2	;END OF INTERNAL RESISTERS AND TABLES
	.SBTTL	INTERNAL DIRTY DATA AREA

;WORDS AND ORDERED BYTES, ITEMS MUST BE KEPT FROM COMMAND TO COMMAND

O.CAD:	.WORD	0	;ADDRESS OF CURRENTLY OPEN REGISTER
O.DOT:	.WORD	0	;ADDRESS OF LAST EXPLICITLY OPENED CELL
O.BW:	.WORD	0	;OPEN CELL TYPE, 0=NONE, 1=BYTE, 2=WORD
D.ARGS:	.WORD	0	;SEMI COLON PUSH WORD


;THE FOLLOWING ITEMS NEED NOT BE KEPT FROM COMMAND TO COMMAND
;THEIR ORDER IS INTENTIONAL SO KNOW THY MAKER!

O.OP:	.BYTE	0	;CURRENT ARITHMETIC OPERATOR
	.ODD		;FIRST BYTE GOTTA BE AT ODDS
O.ALFA:	.BYTE	0	;AREA FOR RADIX 50 CONVERSION, 3 BYTES!
O.EXP:	.WORD	0	;EXPRESSION BUCKET, LAST 2 BYTES OF O.ALFA!
O.SMFD:	.BYTE	0	;SEMI-COLON COUNTER

;THE FOLLOWING ITEMS MUST BE KEPT FROM COMMAND TO COMMAND.

O.T:	.BYTE	0	;T BIT IN USE FLAG
O.P:	.BYTE	-1	;PROCEED ALLOW FLAG
O.S:	.BYTE	0	;SINGLE INSTRUCTION MODE, 0=NORMAL, -1=ENABLE
O.FM:	.BYTE	2	;OUTPUT FORMAT MODE, BYTE, WORD, ANSII, RAD50
O.OBW:	.BYTE	2	;OPEN CELL TYPE, 1=BYTE, 2=WORD
O.SEQ:	.BYTE	0	;CHANGE SEQUENCE INDICATIOR


;RSTS STUFF
	.EVEN
O.IOST:	.WORD	0		;SAVED IOSTS
O.XRB:	.WORD	0,0,0,0,0,0	;SAVED RSTS XRB
O.BUF:	.WORD	0		;CHARACTER BUFFER
	.SBTTL	INTERNAL REGISTER NAME AND CONTROL TABLES

;NON-INDEXED REGISTER NAMES

NIXMAP:	.ASCII	/01234567/	;USER REGISTER NAMES FOR MAPPING

NIXREG:	.BYTE	'S	;O.UST	USER STATUS
	.BYTE	'A	;O.ARG	ARGUMENT
	.BYTE	'M	;O.MSK	MASK REGISTER
	.BYTE	'L	;O.LOW	LOW SCAN LIMIT
	.BYTE	'H	;O.HI	HIGH SCAN LIMIT
	.BYTE	'C	;O.CNST	CONSTANT
	.BYTE	'Q	;O.QUAN	QUANTITY
	.BYTE	'F	;O.FORM	FORMAT CONTROL
	.BYTE	'J	;O.JOB	JOB INDEX OF OWNER

	.BYTE	00	;END OF THIS LIST

;INDEXED REGISTER NAMES

INXREG:	.BYTE	'B	;O.ADR1	BKPT ADDRESSES
	.BYTE	'G	;O.CT	BKPT PROCEED COUNTS
	.BYTE	'I	;O.UIN	BKPT USER INSTRUCTIONS
	.BYTE	'R	;O.RELT	RELOCATION REGISTERS

	.BYTE	00	;END OF THIS LIST

;INDEXED REGISTER TABLE BASES

	.EVEN
INXTBL:	.WORD	O.ADR1		;BKPT ADDRESS TABLE
	.WORD	O.CT		;BKPT PROCEED COUNTS
	.WORD	O.UIN		;BKPT'D INSTRUCTION
	.WORD	O.RELT		;RELOCATION TABLES
	.WORD	INTEND+2	;END OF TABLE AREA FOR ADDRESS MAPPING

	.SBTTL	COMMAND NAME AND DISPATCH TABLES

COMTAB:		;ADDRESS OF THE CHARACTER TABLE

;OPEN REGISTER COMMANDS (ORDER AND POSITION CRITICAL)

	.BYTE	'\,'/,'','",'%

;CLOSE REGISTER COMMANDS

	.BYTE	015,012,'^,'_,'@,'>,'<

;SPECIAL FORMS

	.BYTE	'$,'=,'C,'Q,'.

;OPERATORS (ORDER OF -+* IS CRITCAL)

	.BYTE	';,'-,'+,'*,',

;COMMANDS

	.ASCII	/BEFGKLNOPRSW/

	.BYTE	00	;******* END OF THE LIST *******
;THE DISPATCH TABLE, ORDERED ON ABOVE TABLE

	.EVEN ;THIS CAN HAPPEN TO YOU!!!!

;OPEN REGISTER COMMANDS

COMDIS:	+	OCBYTE	;\	OPEN OCTAL BYTE
	+	OCWORD	;/	OPEN OCTAL WORD
	+	ANBYTE	;'	OPEN ANSII BYTE
	+	ANWORD	;"	OPEN ANSII WORD
	+	MODULO	;%	OPEN RADIX 50 WORD

;CLOSE REGISTER COMMANDS

	+	CLCRET	;<CR>	CLOSE, NO SUCESSIVE OPEN
	+	CLLNFD	;<LF>	CLOSE, OPEN NEXT
	+	CLUPAR	;^	CLOSE, OPEN PREVIOUS
	+	CLBACK	;_	CLOSE, OPEN PC RELATIVE MODE
	+	CLATSG	;@	CLOSE, OPEN INDIRECT
	+	CLGRTH	;>	CLOSE, OPEN PC OFFSET AS BRANCH
	+	CLLSTH	;<	CLOSE, OPEN OLD SEQUENCE

;SPECIAL FORMS

	+	O.REGT	;$	INTERNAL REGISTER REFERENCE
	+	EQUALS	;=	PRINT LEFT SIDE IN OCTAL
	+	CHRCEE	;C	CONSTANT REGISTER CONTENTS
	+	CHRQUE	;Q	QUANTITY REGISTER CONTENTS
	+	CHRDOT	;.	LAST OPENED LOCATION'S ADDRESS

;OPERATORS

	+	O.SEMI	;;	MULTIPLE ARGUMENT DELIMITER
	+	O.MINS	;-	SUBTRACTION
	+	O.PLUS	;+	ADDITION
	+	O.STAR	;*	MULTIPLY BY 50
	+	O.COMM	;,	RELOCATION COMPUTE

;COMMANDS

	+	O.SEBK	;B	SET / CLEAR BREAKPOINTS
	+	O.EFFA	;E	EFFECTIVE ADDRESS SEARCH
	+	O.FILL	;F	MEMORY FILL
	+	O.GOTO	;G	GO TO USER'S DATA
	+	O.KILO	;K	KOMPUTE AND TYPE RELOCATION DATA
	+	O.LIST	;L	LIST MEMORY ON SPECIFIED DEVICE
	+	O.NOTW	;N	NOT WORD SEARCH
	+	O.OFST	;O	TYPE PC RELATIVE OFFSETS
	+	O.PROC	;P	PROCEED FROM BREAKPOINT
	+	O.RELO	;R	SET / RESET RELOCATION REGISTERS
	+	O.SNGL	;S	SET / RESET SINGLE STEP MODE
	+	O.WSCH	;W	MEMORY WORD SEARCH
	.SBTTL	MAJOR ENTRY AND RE-ENTRY POINTS

; INITIALIZE ODT
;  USE O.ODT FOR A NORMAL ENTRY, COMPLETE CLEAN RE-START
;  USE O.ODT+2 TO RE-ENTER (I.E. - FAKE A BREAKPOINT)

O.ODT:	BR	O.STRT		;NORMAL ENTRY
	;BR	O.ENTR		;RE-ENTRY

;RE-ENTER AS IF BREAKPOINT, BAD ONE AT THAT

O.ENTR:	CLR	-(SP)		;SET PS AS IF INTERRUPT
	MOV	#O.ENTR-2,-(SP)	;SET PC, IT GETS BUMPED BY 2 ON BE'S
	CLRB	O.S		;FAST EXECUTION MOOD
	JMP	O.BREK		;IT IS A BREAK, RUN LIKE HELL

;START ODT FROM SCRATCH, CLEAN SLATE

O.TRTC:	BPT			;TRACE TRAP ENTRY AND PROTOTYPE

O.STRT:	CLR	O.UST		;SAVE STATUS AND RUN AT ENTRY STATUS
	JSR	R0,O.SVR	;SAVE REGISTERS (MAINLY SP)
	MOV	#ODTSTK,SP	;SET A STACK TO GO WITH
				;SAVE TTY STATUS
				;RESET CONSOLE TTY FOR FATAL
				;ERRORS
	JSR	PC,O.RUAL	;RESET RELOC AND UNIT
	CLRB	O.S		;DISABLE SINGLE INSTRUCTION FOR NOW
	MOVB	#-1,O.P		;DISALLOW PROCEED
;
;PUT CODE TO SET TRAP HERE
;
;
	JMP	O.RALL		;CLEAR BRK PT TABLES GOT TO DECODER
	.SBTTL	COMMAND PROCESSORS, SECTION ONE ( $ T B R K A Q . )

;"$,<ALT-MODE>" PROCESSOR - INTERNAL REGISTER MAPPER

;SYNTAX--
;$L		DELIVER INTERNAL ADDRESS OF L
;$NL		DELIVER INTERNAL ADDRESS OF L+2N
;$N		DELIVER INTERNAL ADDRESS OF USER REGISTER N

;SEE MAPPING TABLES, RANGE OF N IS 0-27

O.REGT:	JSR	PC,GETNUM	;GET AN OCTAL NUMBER
	JSR	PC,O.RTST	;CHECK FOR ERROR
	BCS	O.ERR0		;MPY R4 X 2
	TST	R2		;SEE IF ANYTHING TYPED
	BNE	O.RE10		;IF SO IS INDEXED OR USER REGISTER
	JSR	R5,LOOKUP	;SEE IF NON-INDEXED
	 +	NIXREG
	BCS	O.RE12		;NON-INDEXED TURNS INTO A COMMAND
	MOV	R1,R4		;PLACE IN LIST IS INTERNAL ORDER
	ADD	#O.UST,R4	;GET ADDRESS IN R4, GOTTA READ CHAR
	BR	O.RE88
O.RE10:	JSR	R5,LOOKUP	;SEE IF INDEXED
	 +	INXREG
	BCC	O.RE15		;WAS TRULY INDEXED
O.RE12:	CMP	#7+7,R4		;INTERNAL USER REGISTER RANGE CHECK
	BLO	O.ERR0
	ADD	#O.UR0,R4	;SET ACCESS TO R0-R7 OF THE USER
	BR	O.RE89		;AVOID READING OF COMMAND
O.RE15:	ADD	INXTBL(R1),R4	;COMPUTE ADDRESS TO INDEXED TABLE
O.RE88:	JSR	PC,O.GET	;GET THE ASSUMED TERMINATOR
O.RE89:	INC	R2		;SHOW THEM THAT R4 GOT VALID DATA
	JMP	O.CLGL		;RE-USE CHARACTER, R2 IS NON-ZERO

;"B" PROCESSOR - SET AND REMOVE BREAKPOINTS

;SYNTAX--
;B			CLEAR ALL BREAKPOINTS
;NB			CLEAR BKPT N
;A;B			SET BKPT AT A, USE FIRST FREE  BKPT
;A;NB			SET BKPT N AT A

;DEPENDS MIGHTILY UPON LOCATION "O.TRTC" CONTAINING A TRAP INST.
;AND THAT A FREE BKPT CONTAINS THE ADDRESS "O.TRTC".

O.SEBK:	ASL	R4		;MPY R4 X2, JUST IN CASE ALL IS GO
	MOV	#O.TRTC,R0	;SET MAGIC VALUE IN R0, JUST IN CASE
	TST	R3		;CHECK FOR THE REAL CASE
	BEQ	O.REMB		;REMOVAL CASES, CLEAR THEM UP
	BIT	#1,R5		;LOOK AT ADDRESS
	BNE	O.ERR		;THAT'S ODD ?
	TST	R2		;SEE IF I GET TO PICK IT OR NOT
	BNE	O.SE04		;OR NOT, DISAPPOINTMENT
O.SE02:	CMP	R0,O.ADR1(R4)	;LOOK FOR LOCATION WITH FREE ADDRESS
	BEQ	O.SE04		;A HIT
	TST	(R4)+		;KEEP AT FOR A LONG WHILE
	BR	O.SE02		;LOOOOOOOOP
O.SE04:	MOV	R5,R0		;R0 HAS ADDRESS OF BREAKPOINT
	BR	O.RE02		;GO TUCK IT IN

;REMOVE SOME BREAKPOINTS

O.REMB:	TST	R2		;SEE IF ONE OR ALL
	BEQ	O.RALL		;ALL
O.RE02:	JSR	PC,SETBRK	;SET THE ONE SET UP TO SET
	BCC	O.DCD		;IT HAPPENED
O.ERR0:	BR	O.ERR		;SOME THING WENT WRONG

;REMOVE ALL BREAKPOINTS  (N.B. CALLED BY THE INIT CODE)

O.RALL:	MOV	#O.TRTC,R0	;MAGIC IN R0
	CLR	R4		;R4 IS ZERO
O.RA01:	JSR	PC,SETBRK	;SET THEM TILL
	BCC	O.RA01		;THEY GET OUTTA
O.DCD0:	BR	O.DCD		;HAND!!!!
;"R" PROCESSOR -RELOCATION REGISTER PROCESSING

;DETERMINE IF CLEAR OR SET

O.RELO:	TSTB	O.SMFD		;SEMI-COLON ABSENT MEANS CLEAR
	BEQ	O.RCLR		;CLEAR DISPATCH, OR FALL TO SETTING

;FORMS HERE--
; A;NR			SET RELOC(N) TO A
;ABSENT A OR N DEFAULTS TO 0

	JSR	PC,O.RTST	;PROTECTION EDITING
	BCS	O.ERR		;ILLEGAL REGISTER NUMBER ?
	MOV	R5,O.RELT(R4)	;SET THE APPROPRIATE REGISTER
	BR	O.DCD		;GO GET NEXT COMMAND

;FORMS HERE--
;R			RESET ALL TO -1 FOR RELOC(0-7)
;NR			RESET ONLY RELOC(N)

O.RCLR:	TST	R2		;SEE IF NR OR JUST R
	BEQ	O.RC01		;CLEAR ALL
	JSR	PC,O.RUCL	;CLEAR THE ONE IN R4
	BCS	O.ERR		;ERROR, INVALID REGISTER ?
	BR	O.DCD		;NEXT COMMAND
O.RC01:	JSR	PC,O.RUAL	;DO THEM ALL
	BR	O.DCD		;OFF AND ON
;"K" PROCESSOR - COMPUTE AND PRINT RELOCATION

;SYNTAX--
;AK				TYPE RELOCATION DEAL FROM DOT TO A
;L;AK				TYPE RELOCATION DEAL FROM L TO A

;IF A IS NULL THE THE OLD BEST FIT RULE APPLIES
;TYPES	=N,DDDDDD	WHERE N IS THE RELOCATION REGISTER
;				AND D-D IS THE RELOCATION BIAS

O.KILO:	TST	R2		;SEE WHO PICKS THE REGISTER
	BNE	O.KI02
	JSR	PC,O.LOC	;WE PICK IT
	BMI	O.ERR		;CAN'T FIND ONE THATS GOOD
	MOV	R0,R4		;R4 HAS OUR PICK
O.KI02:	BIC	#177770,R4	;EDIT REGISTER
	MOV	#" =,R0		;TYPE CUE
	JSR	PC,O.TYPE
	MOVB	R4,R0		;TYPE REGISTER & A ,
	ADD	#"0,,R0
	JSR	PC,O.TYPE
	ASL	R4		;GO GET IT AS TABLE INDEX
	TST	R3		;SEE WHO TYPED THE ADDRESS
	BNE	O.KI04
	MOV	O.CAD,R5	;THAT CAD!
O.KI04:	SUB	O.RELT(R4),R5
	MOV	R5,R0		;BIAS COMPUTE
	JSR	PC,O.CADW	;PRINT AS WORD
	BR	O.DCD

;"A-Q-." PROCESSORS - SPECIAL VALUES

;MERELY SUBSTITUTE THE VALUE IN R4 WITH THE CONTENTS OF THE SPECIFIED
;REGISTER.

CHRQUE:	MOV	O.QUAN,R4	;LAST QUANTITY PRINTED
	BR	CHR001
CHRCEE:	MOV	O.CNST,R4	;CONSTANT REGISTER
	BR	CHR001
CHRDOT:	MOV	O.CAD,R4	;CURRENT LOCATION
	;BR	CHR001

CHR001:	INC	R2		;ALLOW AS R4 IS REAL
	JSR	PC,O.GET	;GET NEXT CHARACTER AND ASSUME
	BR	O.CLGL		;IT IS A TERMINATOR
	.SBTTL	COMMAND DE-CODER AND MAIN LOOP OF ODT

; COMMAND DECODER - ODT11X

;  ALL REGISTERS MAY BE USED (R0-R5),

;ERROR ENTRY, TYPE FLAG AND GO DO COMMAND

O.ERR:	MOV	#" ?,R0		;  ? TO BE TYPED
	JSR	PC,O.TYPE	; OUTPUT ?

;DECODE FROM THE TOP, CLOSE ALL AND DO CR/LF/_

O.DCD:	MOV	#ODTSTK,SP	;SET THE STACK FOR SANITY
	CLR	O.BW		;CLOSE ALL
	MOV	@#FIRQB,O.IOST	;SAVE IOSTATUS
	.TTRST			;CANCEL ^O
	MOV	O.IOST,@#FIRQB	;RESTORE STATUS
	JSR	PC,O.CRLF	;TYPE  <CR><LF>
	MOVB	#'+,R0		;_ TO GO NEXT
	JSR	PC,O.FTYP

;MAINTAIN OPENED LOCATION, RE-INIT INPUT

O.NEWC:	CLRB	O.SMFD		;CLEAR SEMI-COLON FLAG/COUNT
	CLR	R3		;ZERO SECONDARY ARGUMENT FLAG
	CLR	R5		;AND ARGUMENT

;NEW SUB-EXPRESSION ENTRY

O.NEWE:	CLRB	O.OP		;CLEAR OPERATOR FOUND
	CLR	O.EXP		;SET ZERO IN EXPRESSION SO FAR LOCATION

;GET NUMBER AND THEN SCAN FOR COMMAND

O.NEWN:	JSR	PC,GETNUM	;GET AN OCTAL NUMBER AND TERMINATOR

;NON-OCTAL CHAR TYPED WHAT ARE WE TO DO?

O.CLGL:	JSR	R5,LOOKUP	;GO SEE IF IT IS REAL
	 +	COMTAB		;THIS DEFINES REAL
	BCS	O.ERR		;EASY ENOUGH IF NOT REAL
	TST	R2		;IF NOTHING TYPE BOTHER NOT
	BEQ	O.CL01		;WITH THE EXPRESSION
	JSR	PC,EXPCOM	;COMPUTE EXPRESSION
O.CL01:	JMP	@COMDIS(R1)	;GO TO PROPER ROUTINE

;FOR THE BENEFIT ALL REGISTERS ARE AS FOLLOWS

;R0	LAST CHARACTER TYPED, THE COMMAND ITSELF!
;R1	TABLE INDEX TO COMMAND ADDRESSES, IT IS USED.
;R2,R4	FIRST ARGUMENT, IF R2<>0 THEN R4 IS DATA
;R3,R5	SECOND ARGUMENT, IF R3<>0 THEN R5 IS DATA
	.SBTTL	EXPRESSION SETUP COMMANDS ( ; + - * , )

;SEMI-COLON PROCESSOR

O.SEMI:	INCB	O.SMFD		;COUNT SEMI-COLON
	CMPB	#2,O.SMFD	;PUSH CONTENTS INTO MULTI
	BNE	O.SEM1		;SEMI COLON ARG LIST
	MOV	R5,D.ARGS
O.SEM1:	MOV	R2,R3		;PUSH R2 AND R4 INTO
	MOV	R4,R5		;R3 AND R5 (FLAG AND CONTENTS)
	BR	O.NEWE		;CONTINUE SCANNER

;ADDITION SETUP

O.PLUS:	CLRB	O.OP		;OP IS 0 FOR +
	BR	O.CO00

;SUBTRACT SET UP

O.MINS:	MOVB	#2,O.OP
	BR	O.CO00

;MULTIPLY BY 50 AND ADD

O.STAR:	MOVB	#-2,O.OP	;OP IS -2 FOR *
O.CO00:	CLR	R4		;R4 IS RESET
	BR	O.NEWN

;MEMORY RELOCATION CHECK

O.COMM:	ASL	R4		;ALL NEED IT X 2
	CMP	R4,#O.RLR	;SEE IF REGISTER IS OUT OF RANGE
	BGT	O.ERR
	MOV	O.RELT(R4),O.EXP	;COMPUTE REAL CORE ADDRESS
	BR	O.PLUS
	.SBTTL	OPEN AND CLOSE PROCESSORS

;"\-/-'-"-%-:" PROCESSOR - OPEN AND TYPE CONTENT COMMANDS

;SYNTAX--
;NC				OPEN LOC N IN MODE C, SET MODE FOR NEXT
;C				TYPE LAST OPENED LOC IN MODE C

OCWORD:		;OCTAL WORD -		R1=2
ANWORD:		;ANSII WORD -		R1=6
MODULO:		;RADIX 50 WORD -	R1=10

;OPEN WORD MODE ENTRY, R1 CONTAINS FORMAT INDEX

	MOV	#2,R0		;SET BYTE FLAG TO WORD FLAG
	BR	OPE004		;GO TO IT ACE HOLE

OCBYTE:		;OCTAL BYTE -		R1=0
ANBYTE:		;ANSII BYTE -		R1=4

OPE001:	MOV	#1,R0		;SET WORD FLAG TO BYTE FLAG

OPE004:	TST	R2		;IF NO VALUE TYPED NO MODE SET
	BEQ	OPE005
	MOV	R0,O.BW		;SET MODE AND FORMAT FLAGS
	MOVB	R0,O.OBW	;SET THE LATER USE MOOD
	MOVB	R1,O.FM		;SET THE MODE FLAG FOR SOOTH
	MOV	R4,O.CAD	;SET ADDRESS FOR EXPLICIT OPEN
	MOV	R4,O.DOT	;RESET RETURN PTR.
OPE005:	CMP	#1,R0		;CHECK ON BYTE MOOD
	BEQ	OPE010		;NOT BYTE MODE
	BIT	#1,O.CAD	;SEE IF ADDRESS IS ODD
	BEQ	OPE010		;ALL IS GOOD
	CLR	R1		;THEY GET BYTE MODE ONLY
	BR	OPE001
OPE010:	MOV	R1,-(SP)	;SAVE FORMAT MAINLY
	JSR	PC,GETCAD	;GET THE DATA
	MOV	(SP)+,R1	;GET FORMAT
	JSR	PC,@TYFORM(R1)	;PRINT DATA IN PROPER FORMAT
	BR	O.NEWC		;GO GETTA NEW COMMAND TO DO
;"<CR>-<LF>->-<-^-_-@" PROCESSOR - CLOSE AND OPEN REFERENCED REGISTERS

;CARRIAGE RETURN

CLCRET:	JSR	PC,PUTCAD	;CLOSE LOCATION
	BR	O.DCD		;RETURN TO DECODER

;LESS THAN, BACK TO MAIN STREAM

CLLSTH:	INCB	O.SEQ	;SET FLAG TO LATER RESTORE CAD

;LINE FEED, NEXT ONE DOWN

CLLNFD:	JSR	PC,PUTCAD	;CLOSE PRESENT CELL
	TSTB	O.SEQ		;SHOULD CAD BE RESTORED?
	BEQ	O.OP5		;BRANCH IF NOT
	MOV	O.DOT,O.CAD	;RESTORE PREVIOUS SEQUENCE
	CLRB	O.SEQ		;RESET FLAG; NO LONGER NEEDED
O.OP5:	ADD	O.BW,O.CAD	;GENERATE NEW ADDRESS
	MOV	O.CAD,O.DOT	;RESTORE DOT
	BR	O.OP2B

O.OP2:	MOV	O.CAD,O.DOT	;INITIALIZE DOT
O.OP2A:	JSR	PC,O.CRLF	;<CR><LF>
O.OP2B:	MOV	O.CAD,R0	;NUMBER TO TYPE
	JSR	PC,O.RORA	; CHECK FORMAT
	MOVB	O.FM,R0		;SET FORMAT
	ASR	R0		;SPLIT R0 IN HALF
	MOVB	COMTAB(R0),R0	;SET SUFFIX CHARACTER
	JSR	PC,O.FTYP	;PRINT IT
	MOV	O.CAD,R4	;SET UP THE DATA
	INC	R2		;FLAG IT AS THERE
	CLRB	O.OP		;THIS IS BECUZE
	CLR	O.EXP
	JMP	O.CLGL		;R0 HAS TERMIN, R4- DATA, R2= FLAG

;UP ARROW, NEXT ONE UP

CLUPAR:	JSR	PC,PUTCAD
	SUB	O.BW,O.CAD	;GENERATE NEW ADDRESS
	BR	O.OP2		;GO DO THE REST

;BACK ARROW, PC RELATIVE COMPUTE

CLBACK:	JSR	PC,O.TCLS	;TEST WORD MODE AND CLOSE
	ADD	@R2,R2		;COMPUTE
	INC	R2
	INC	R2		;   NEW ADDRESS
O.PCS:	MOV	R2,O.CAD	;UPDATE CAD
	BR	O.OP2A		;GO FINISH UP

;AT SIGN, ABSOLUTE OR INDIRECT CHAIN

CLATSG:	JSR	PC,O.TCLS	;TEST WORD MODE AND CLOSE
	MOV	@R2,R2		;GET ABSOLUTE ADDRESS
	BR	O.PCS

;GREATER THAN, PC OFFSET BRANCH ADDRESS

CLGRTH:	JSR	PC,O.TCLS	;TEST AND CLOSE
	MOVB	@R2,R1		;COMPUTE NEW ADDRESS, EXTEND SIGN
	ASL	R1		;R2=2(@R2)
	INC	R1		;   +2
	INC	R1
	ADD	R1,R2		;   +PC
	BR	O.PCS

;HANDY DANDY TO DO SOME LEG WORK

O.TCLS:	JSR	PC,PUTCAD	;CLOSE CURRENT CELL
	CMP	#2,O.BW		;ONLY WORD MODE ALLOWED
	BNE	O.ERR1		;BRANCH IF ERROR
	MOV	O.CAD,R2	;CURRENT ADDRESS IN R2
	RTS	PC
	.SBTTL	COMMAND PROCESSORS, SECTION TWO ( O = G S P )

;"O" PROCESSOR - COMPUTE AND PRINT OFFSETS

;SYNTAX--
;AO				TYPE OFFSETS FROM . TO A
;L;AO				TYPE OFFSETS FROM L TO A

;TYPES	_PPPPPP >DDDDDD			WHERE P-P IS PC RELATIVE
;					AND D-D IS BRANCH OFFSET

O.OFST:	TST	R3		;HOW ABOUT A VALUE OTHER
	BNE	O.OF01		;THAN CAD
	MOV	O.CAD,R5	;RELUCTANTLY
O.OF01:	SUB	R5,R4
	SUB	#2,R4		;NO TRICKS, ODD AND NON-EXIST THINGS
	MOV	#" _,R0		;TYPE PC RELATIVE CUE
	JSR	PC,O.TYPE
	MOV	R4,R0
	MOV	R4,-(SP)	;GOOD IDEA TO SAVE THIS
	JSR	PC,O.CADW	;TYPE VALUE + BLANK
	MOVB	#'>,R0		;TYPE OFFSET BRANCH CUE
	JSR	PC,O.FTYP
	MOV	(SP)+,R0
	ASR	R0		;DIVIDE
O.OF09:	JSR	PC,O.CADW	;16 BITS SO YOU CAN SEE HOW FAR OFF
	JMP	O.DCD		;YOU ARE

;"=" PROCESSOR - PRINT LEFT SIDE EXPRESSION ON RIGHT SIDE

EQUALS:	MOV	R4,R0		;PROPER PRIOR PLANNING PREVENTS
	BR	O.OF09		;PSSS POOR PERFORMANCE

;JUST ANOTHER ERROR CALL

O.ERR1:	JMP	O.ERR
;"G" PROCESSOR - GO TO PROGRAM COMMAND

;SYNTAX--
;LG			START PROGRAM AT LOCATION L
;G			START PROGRAM AT CURRENT PC

O.GOTO:	TST	R2		;SEE IF SPECIFIC ADDRESS
	BNE	O.GO01		;NO
	MOV	O.UPC,R4	;USE PC AS IT IS
O.GO01:	ASR	R4		;SEE IF STRANGE
	BCS	O.ERR1		;THAT'S ODD ?
	ASL	R4
	MOV	R4,O.UPC	;SET THE PC
	CLRB	O.S		;NO SINGLE INSTRUCTIONS
	MOVB	#O.BKP+3,O.P	;GOTTA BREAK TO PROCEED
O.TBIT:	CLRB	O.T		;CLEAR T-BIT FLAGS
	BIS	#O.TBT,O.UST	;BOTH
	TSTB	O.S		;SEE IF WE NEED A T-BIT BIT
	BMI	O.GO2		;NO GO ON
	BIC	#O.TBT,O.UST	;SET THE TEE BIT
	JSR	PC,O.RSB	;RESTORE BREAKPOINTS
O.GO2:	JSR	R0,O.RSR	;RESTORE USER STATE
	MOV	O.UST,-(SP)	;	AND STATUS
	MOV	O.UPC,-(SP)	;	AND PC
	RTT
;"S" PROCESSOR - SINGLE STEP PROCEED COMMAND

;SYNTAX--
;NS				EXECUTE N INSTRUCTIONS AND THEN STOP
;S				EXECUTE ONE INSTRUCTION

O.SNGL:	MOVB	#-1,O.S		;SET THE MODE FOR S.I. MOOD
	MOVB	#O.BKP+2,R0	;FAKE THE BREAK
	BR	O.PR01		;FAKE A PROCEED IN S.I. MOOD

;"P" PROCESSOR - PROCEED FROM BREAKPOINT COMMAND

;SYNTAX--
;NP				PROCEED THRU THIS BREAKPOINT N TIMES
;P				ASSUME N=1

O.PROC:	CLRB	O.S		;SET FAST MODE
	MOVB	O.P,R0		;GET NUMBER OF BREAK
	BMI	O.ERR1		;THERE WASN'T ONE SO FAR ?
O.PR01:	TST	R2
	BEQ	O.C990		;NO R4 IS DEFAULT TO 1
	MOV	R4,O.CT(R0)	;SET USER'S COUNT
O.C990:	CMPB	O.P,#O.BKP	;SEE IF A REAL ONE OR A FAKE
	BGT	O.TBIT		;BRANCH IF FAKE
	TSTB	O.S		;SEE IF SINGLE INSTRUCTION MODE
	BMI	O.TBIT		;IF SO EXIT NOW
	INCB	O.T		;SET T-BIT FLAG
	BIS	#O.TBT,O.UST	;SET T-BIT
	BR	O.GO2
	.SBTTL	BREAKPOINT TRAP ENTRY ROUTINE

O.BREK:	MOV	(SP)+,O.UPC	;PRIORITY IS 7 UPON ENTRY
	MOV	(SP)+,O.UST	;SAVE STATUS AND PC
	MOVB	#O.BKP+3,O.P	;TELL ;P THAT WE CAN CONTINUE
	JSR	R0,O.SVR	;SAVE VARIOUS REGISTERS
	TSTB	O.T		;CHECK FOR T-BIT SET
	BNE	O.TBIT		;JUMP IF SET
	JSR	PC,O.REM	;REMOVE BREAKPOINTS
	MOV	O.UPC,R5	;GET PC, IT POINTS TO THE TRT
	TSTB	O.S		;SEE IF IT WAS SINGLE INSTRUCTION FUN
	BMI	O.B4		;IF SO HANDLE THERE
	TST	-(R5)
	MOV	R5,O.UPC
	MOV	#O.BKP,R4	;GET A COUNTER
O.B1:	CMP	R5,O.ADR1(R4)	;COMPARE WITH LIST
	BEQ	O.B2		;JUMP IF FOUND
	DEC	R4
	DEC	R4
	BGE	O.B1		;RE-LOOP UNTIL FOUND
	JSR	PC,O.CRLF
	MOV	#"BE,R0
	JSR	PC,O.TYPE	;OUTPUT "BE" FOR BAD ENTRY
	MOV	R5,R0
	ADD	#2,O.UPC	;POP OVER THE ADJUSTMENT ABOVE
	BR	O.B3		; OR CONTINUE
O.B4:	MOVB	#O.BKP+2,R4	;SET BREAK POINT HIGH + 1
	MOV	R5,O.ADR1(R4)	;STORE NEXT PC VALUE FOR TYPE OUT
O.B2:	MOVB	R4,O.P		;ALLOW PROCEED
	DEC	O.CT(R4)
	BGT	O.C990		;JUMP IF REPEAT
	MOV	#1,O.CT(R4)	;RESET COUNT TO 1
	JSR	PC,O.CRLF
	MOVB	R4,R0		;SET UP TO TYPE B PLUS N
	ASR	R0		;JUST AS A TOKEN GESTURE
	ADD	#"0B,R0		;SEE WHAT I MEAN
	JSR	PC,O.TYPE	;TYPE
	MOV	#':,R0
	JSR	PC,O.FTYP	; TYPE 
	MOV	O.ADR1(R4),R0	;GET ADDRESS OF BREAK
O.B3:	JSR	PC,O.RORA	; CHECK FORMAT
	JMP	O.DCD		;GO TO DECODER
	.SBTTL	COMMAND PROCESSORS, SECTION THREE ( L W N E F )

;"L" PROCESSOR - LIST MEMORY ON THE SPECIFIED DEVICE

;SYNTAX--
; D;S;FL		WHERE	D IS DEVICE, NULL OR 0 = CONSOLE
;				S IS START ADDRESS, SETS $L IF THERE
;				F IS STOP ADDRESS, SETS $H IF THERE

O.LIST:	TST	R2		;SET UPPER AND LOWER LIMITS
	BEQ	O.LI02		;IF SPECIFIED TO DO SO
	MOV	R4,O.HI
O.LI02:	TST	R3		;DO THE LOW ONE
	BEQ	O.LI10
	MOV	R5,O.LOW
O.LI10:	JSR	PC,SARSET	;SET UP THE LIMITS TO START
	TST	-(SP)		;MAKE A HOLE IN THE STACK
O.LI30:	CLR	(SP)		;NEW LINE UP
	JSR	PC,SNAGIT	;ACCESS DEVICE FOR DATA
	JSR	PC,SPRINT	;PRINT ADDRESS AND FIRST ITEM
O.LI35:	JSR	PC,SNAGIT	;GET MORE DATA
	JSR	PC,DPRINT	;JUST PRINT THE DATA
	INC	(SP)		;COUNT THE DATA
	CMP	#7,(SP)		;CHECK THE COUNT
	BNE	O.LI35		;JUST LIKE THEY TOLD YOU AT THE
	BR	O.LI30		;FAMOUS PROGRAMMERS SCHOOL
;"W" PROCESSOR - MASKED EQUAL WORD SEARCH

;SYNTAX--
;M;AW				SET $M TO M, SET $A TO A, DO SEARCH
;AW				SET $A TO A, DO SEARCH
;W				USE $L, $H, $M, $A TO SEARCH. PRINT HITS

O.WSCH:	JSR	PC,SARGUS	;SET UP $A, $M AND R5
O.WS02:	JSR	PC,SNAGIT	;R5 IS MEMORY INDEX, CHECK FOR IT
	BNE	O.WS02		;NOT EQUAL IS NOT THE OBJECTIVE
	JSR	PC,SPRINT	;PRINT LOCATION AND VALUE
	BR	O.WS02		;MOVE ON

;"N" PROCESSOR - MASKED NOT EQUAL WORD SEARCH

;SYNTAX--
;N				COMMAND IS "N", FORMS AS ARE FOR "W"

O.NOTW:	JSR	PC,SARGUS
O.NO02:	JSR	PC,SNAGIT
	BEQ	O.NO02		;THE ONLY DIFFERENCE
	JSR	PC,SPRINT
	BR	O.NO02

;"E" PROCESSOR - MASKED EFFECTIVE ADDRESS

;SYNTAX--
;E		COMMAND IS "E", FORMS ARE AS ABOVE IN "W" AND "N"

O.EFFA:	JSR	PC,SARGUS	;SET IT ALL UP PLEASE
O.EF02:	JSR	PC,SNAGIT	;GET THE DATA VIA R5
	BEQ	O.EF10		;SAME ABSOLUTE ADDRESS FOUND
	MOV	R5,R0		;DO THE PC REL
	JSR	PC,SRCHEF	;GO SEE IF MASKED SAME
	BEQ	O.EF10		;SAME PC RELATIVE ADDRESS
	MOVB	R5,R0		;DISPLACEMENT INTO R1, SIGN EXTEND
	ASL	R0		;CARRY IS CLEAR
	JSR	PC,SRCHEF	;CHECK IT
	BNE	O.EF02		;SAME BRANCH DISPLACE IN FALL THRU
O.EF10:	JSR	PC,SPRINT
	BR	O.EF02

;"F" COMMAND - FILL MEMORY WORDS

;AF			SET ARG REGISTER, FILL WITH $A FROM $L TO $H

O.FILL:	CLR	R3		;NO MASK IS TO BE SET
	JSR	PC,SARGUS	;SET UP ARG AND R5
O.FI02:	JSR	PC,SNAGIT	;GET LOC IN R5
	MOV	SP,R2		;PRETEND DATA IS HERE
	MOV	O.ARG,R4	;THIS IS WHY
	MOVB	O.OBW,O.BW	;OPEN THE ITEM
	JSR	PC,PUTCAD	;PUT THE DATA
	BR	O.FI02		;GO TILL BROKEN
	.SBTTL	UTILITIES - SAVE AND RESTORE USER DATA.

;SAVE REGISTERS R0-R6, SET ODT'S STACK UP	JSR R0,O.SVR

O.SVR:	MOV	(SP)+,O.UR0	;PICK R0 FROM STACK AND SAVE
	MOV	SP,O.USP	;SAVE USER STACK ADDRESS
	MOV	#O.USP,SP	;SET TO INTERNAL STACK
	MOV	R5,-(SP)	;SAVE
	MOV	R4,-(SP)	; REGISTERS
	MOV	R3,-(SP)	;5
	MOV	R2,-(SP)	; THRU
	MOV	R1,-(SP)	;     1
	CMP	-(SP),-(SP)	;SET UP ODT'S STACK AND COVER R0 SAVE
	RTS	R0

;RESTORE REGISTERS R0-R6			JSR R0,O.RSR

O.RSR:	CMP	(SP)+,(SP)+	;POP THE EXTRA CELLS
	MOV	(SP)+,R1	;RESTORE
	MOV	(SP)+,R2	; REGISTERS
	MOV	(SP)+,R3	;  1
	MOV	(SP)+,R4	;  THRU
	MOV	(SP)+,R5	;    5
	MOV	O.USP,SP	;RESTORE USER STACK
	MOV	O.UR0,-(SP)	;PUT R0 ON USER STACK
	RTS	R0

;RESTORE BREAKPOINTS 7-0			JSR PC,O.RSB

O.RSB:	MOV	#O.BKP,R4	;RESTORE ALL BREAKPOINTS
O.RS1:	MOV	@O.ADR1(R4),O.UIN(R4)	;SAVE CONTENTS
	MOV	O.TRTC,@O.ADR1(R4)	;REPLACE WITH TRAP
	DEC	R4
	DEC	R4
	BGE	O.RS1		;RE-LOOP UNTIL DONE
	RTS	PC		;  THEN QUIT

;REMOVE BREAKPOINTS 0-7, OPPOSITE ORDER!!	JSR PC,O.REM

O.REM:	TSTB	O.S		;IGNOGE IT IF S.I MOOD
	BNE	O.R2		;SEE ABOVE
	CLR	R4		;REMOVE ALL START WITH 0
O.R1:	MOV	O.UIN(R4),@O.ADR1(R4)	;INSTR BACK TO PROGRAM
	TST	(R4)+		;BUMP BUMP
	CMP	#O.BKP,R4
	BHIS	O.R1		;LOOP
O.R2:	RTS	PC		;THEN SPLIT
	.SBTTL	UTILITIES - COMMAND SUPPORT ROUTINES

;TEST FOR VALID RELOCATION REGISTER IN R4

O.RTST:	TST	R4
	BMI	O.RTS9		;LOW IS NO GOOD
	CMP	#O.RLR,R4
	BLOS	O.RTS9		;HIGH IS NO GOOD HERE
	ASL	R4
O.RTS8:	CLC
	RTS	PC
O.RTS9:	SEC
	RTS	PC

;RESET RELOCATION BASE AND UNIT REGISTER

O.RUCL:	JSR	PC,O.RTST	;TEST REGISTER TYPE
	BCS	O.RU99		;BAD REGISTER, JUST GO
	MOV	#-1,O.RELT(R4)	;R4 IS INTEGER X2
	ASR	R4		;R4 BACK TO ST INTEGER
O.RU99:	RTS	PC

;CLEAR ALL RELOC AND UNIT REGISTERS

O.RUAL:	CLR	R4		;START WITH 0
O.RUA1:	JSR	PC,O.RUCL	;DO THIS ONE ONLY AT A TIME
	BCS	O.RU99		;SAME AS RTS PC
	INC	R4		;NEXT ONE AT A TIME
	BR	O.RUA1

;RESET BREAKPOINT VIA VALUE IN R4 AND R0

SETBRK:	CMP	#O.BKP,R4	;SEE IF LEGAL REFERENCE
	BLO	O.RTS9		;NO GO SIGNAL ON SPLIT
	MOV	R0,O.ADR1(R4)	;SET THE ADDRESS
	MOV	(R0),O.UIN(R4)	;SET THE INSTRUCTION/ OR TRAP
	CLR	O.CT(R4)	;ZERO PROCEED COUNT
	TST	(R4)+		;A TOUCH
	BR	O.RTS8		;GOOD SPLIT
;SNAG MEMORY LOCATION AND CHECK FOR =	JSR PC,SNAGIT

;NEEDS--
;O.CAD		POINTS TO MEMORY WORD (APPROXIMATELY THAT IS)
;R0,R5		CONTAINS REAL WORD UPON EXIT TO "SRCHEK"

;FALLS THRU TO "SRCHEK" FOR THE NITTY GRITTY

SNA000:	JMP	O.DCD		;GO RESET STACK AND DO NEXT TASK
SNAGIT:	MOVB	O.OBW,R0	;SET THE INCREMENT
	ADD	R0,O.CAD	;INCREMENT AND NOW
	CMP	O.CAD,O.HI	;SEE IF MORE TO DO
	BHI	SNA000		;IF NOT DO NOT
	JSR	PC,GETCAD	;ACCESS METHOD
	MOV	R0,R5		;MAKE A COPY FOR LATER

;MASKED SEARCH CHECKER				JSR PC,SRCHEK

;NEEDS--
;R0		HAS OBJECT UNDER TEST
;SEES IF R0 UNDER MASK IS SAME AS ARGUMENT UNDER MASK

;RETURNS--
;CODES SET FOR	BEQ GOOD FOR SAME, R0=0
;		BNE GOOD FOR NOT SAME, R0<>0

SRCHEK:	MOV	R0,R2		;MAKA COPY
	MOV	O.ARG,R1	;DE ARGUMENT TO COMPARE AGAINST
	BIC	R1,R0		; (NOT A) AND O = X
	BIC	R2,R1		; (NOT O) AND A = Y
	BIS	R0,R1		; X IOR Y = Z
	MOV	O.MSK,R0
	COM	R0
	BIC	R0,R1		;(NOT (NOT M)) AND Z = R1
	RTS	PC		;BACK TO NEXT ONE

;FINISH EFFECTIVE ADDRESS COMPUTE AND CHECK IT, R0 HAS THE ADDRESS

SRCHEF:	ADD	#2,R0		;TWO CAUSE THE PC GETS TWO TOO
	ADD	O.CAD,R0	;RELOCATION PLEASE
	BR	SRCHEK		;DO THE LOGICAL COMPARE

;SET UP SEARCH ARGUMENTS			JSR PC,SARGUS
;JUST SET UP LIMIT				JSR PC,SARSET

;SETS UP--
;O.ARG IF R4 IS VALID
;O.MSK IF R5 IS VALID
;O.CAD,O.OBW	USED TO GET THE ADDRESS TO START OUT WITH

SARGUS:	TST	R2
	BEQ	SAR002
	MOV	R4,O.ARG	;SET THE SEARCH ARGUMENT
SAR002:	TST	R3
	BEQ	SARSET
	MOV	R5,O.MSK
SARSET:	MOV	O.LOW,R5	;SET THE START OF START
	MOVB	O.OBW,R0	;NO SUCHA THING AS A "SUBB"
	SUB	R0,R5
	MOV	R5,O.CAD
	RTS	PC

;SEARCH HIT PRINT			JSR PC,SPRINT

;O.CAD POINTS TO THE LOC TO BE PRINTED
;R5 CONTAINS THE CONTENTS OF THE LOCATION TO BE PRINTED

SPRINT:	JSR	PC,O.CRLF
	MOV	O.CAD,R0	;THE LOCATION
	JSR	PC,O.RORA	;THE MODE
	MOVB	O.FM,R0		;PICK UP OLD CURENT MODE
	ASR	R0		;HALVES
	MOVB	COMTAB(R0),R0	;AH HA
	JSR	PC,O.FTYP	;TYPE THE MODE DESIGNATOR

;DATA PRINT ROUTINE			JSR PC,DPRINT

;PRINTS DATA IN R5 IN CURRENT MODE

DPRINT:	MOVB	O.FM,R1		;SET THE MODE
	MOV	R5,R0		;THIS IS THE POOR DATA
	MOV	R5,-(SP)	;SAVE THE DATA
	JSR	PC,@TYFORM(R1)	;DO THAT __ TO THE POOR DATA
	MOV	(SP)+,R5	;RESTORE THE DATA
	RTS	PC		;RESTORE THE PC
;EXPRESSION COMPUTATION ROUTINE		JSR PC,EXPCOM

;NEEDS--
;O.OP			THE OPERATION (-2=*, 0=+, *=2)
;O.EXP			THE LEFT SIDE
;R4			THE RIGHT SIDE

;SETS UP--
;O.OP			BACK TO 0 FOR ADD
;O.EXP,R4		ALL SO FAR

EXPCOM:	TSTB	O.OP		;SEE WHAT'S UP CHUCK
	BMI	EXP040
	BEQ	EXP020
	NEG	R4		;MINUS, OP=2
EXP020:	ADD	O.EXP,R4	;PLUS, OP=0
EXP025:	MOV	R4,O.EXP	;COMMON OUT, SET EXP TO WHATEVER
	CLRB	O.OP		;IS IN R4 TOO
	INC	R2		;SET R2 SO THAT R4 IS, OP=0
	RTS	PC
EXP040:	MOV	R4,-(SP)	;MULTIPLY X 50, OP=4  SAVE OLD R4
	CLR	R4		;12 BITS IN A PDP-8, MORE HERE
	MOV	#50,R2		;MULTIPLY!!!
EXP042:	ADD	O.EXP,R4
	DEC	R2
	BNE	EXP042		;NOT OPTIMIZED
	ADD	(SP)+,R4	;RECOVER R4 AND JUST RECOVER, INCOVER
	BR	EXP025
;BUILD AN OCTAL NUMBER		JSR PC,GETNUM

;NEEDS AND RETURNS--
;R0	NON-OCTAL TERMINATING CHARACTER
;R2	OCTAL CHARACTER COUNT
;R4	OCTAL NUMBER THAT I GOT, YOU GET

GETNUM:	CLR	R2		;NEW R2 AND R4
	CLR	R4
GET010:	JSR	PC,O.GET	;GET 1 CHARACTER
	CMPB	#'0,R0		;NON-OCTAL, LESS THAN "0"
	BHI	GETC99
	CMPB	#'7,R0		;NON-OCTAL, LESS THAN "7"
	BLO	GETC99
	BIC	#177770,R0	;MAKE INTO ACCEPTABLE RANGE
	ASL	R4
	ASL	R4
	ASL	R4		;MPY BY 10 TO MAKE ROOM
	ADD	R0,R4		;PLANT LO PLACE
	INC	R2		;ACCOUNT FOR NEW ONE
	BR	GET010		;NEXT ONE OR OTHER

;SCAN A LIST OF CHARACTERS	JSR R5,LOOKUP

;CALL--
;		R0	HAS THE CHARACTER
;	JSR	R5,LOOKUP	;THAT IS IT
;	 +	LIST TO USE, 00 BYTE IS END OF LIST

;RETURNS AT CALL + 2 WITH--
;R0	STILL HAS CHARACTER
;R1	HAS INDEX X2 OF FOUND CHARACTER IF C=0
;C=1	CHARACTER WAS NOT FOUND

LOOKUP:	MOV	(R5),R1		;GET LIST START
LOOK10:	CMPB	R0,(R1)		;IS THIS THE ONE
	BNE	LOOK20		;RIGHT IT WASN'T
	SUB	(R5)+,R1	;COMPUTE INDEX AND RETURN
	ASL	R1		;DO THIS FOR EVERBODY, C=0
	BR	LOOK99
LOOK20:	TSTB	(R1)+		;CHECK FOR END OF LIST
	BNE	LOOK10		;IF NOT LOOK AT NEXT ITEM
	TST	(R5)+		;END, AVOID ILLEGAL INSTRUCTION
	SEC			;SECURITY EXCHANGE COMMISION
LOOK99:	RTS	R5		;SECURITY ELSEWHERE
;GET CONTENTS OF ADDRESS IN THE MODE		JSR PC,GETCAD

;NEEDS--
;R0		THE MODE 1=BYTE, 2=WORD
;O.CAD		THE ADDRESS
;O.DEVI		THE DEVICE CODE

;RETURNS--
;R0		HAS THE DATA YOU ASKED FOR

GETCAD:	MOV	O.CAD,R3	;GET CORE ADDRESS
	ASR	R0		;PUSH BW FLAG INTO CARRY BIT
	BCC	GETC95		;2 WON'T FIT SO IS WORD
	MOVB	(R3),R0		;ACCESS BYTE
	BR	GETC99
GETC95:	MOV	(R3),R0		;ACCESS WORD
GETC99:	RTS	PC		;STACK ACCESS

;PUT R4 INTO ADDRESS IN THE MODE		JSR PC,PUTCAD

;NEEDS--
;R2		CONTENT FLAG, 0 FOR NONE, ELSE R4 IS GOLD
;R4		THE DATA
;O.BW		THE MODE FLAG, IF 0 THEN NO LOCATION OPEN

PUTCAD:	TST	R2		;CHECK FOR TYPED VALUE
	BEQ	PUTC12		;NO DATA NO DODO
	MOV	O.BW,R0		;PICK UP MODE AN CC'S
	BEQ	PUTC12		;NOT OPEN NOT STORED
	MOV	O.CAD,R3	;GET THE CORE ADDRESS
	BIT	#177776,R0	;CHECK MODE
	BNE	PUTC10		;WORD MODE
	MOVB	R4,(R3)		;BYTE MODE
	BR	PUTC12		;BRANCH MODE
PUTC10:	MOV	R4,(R3)		;WORD MODE
PUTC12:	RTS	PC
	.SBTTL	UTILITIES - TELETYPE I/O ROUTINES

;TYPE CARRIAGE RETURN LINE FEED			JSR PC,O.CRLF

O.CRLF:	MOV	(PC)+,R0
	.BYTE	015,012

;TYPE TWO CHARS IN R0 PLEASE			JSR PC,O.TYPE

O.TYPE:	JSR	PC,O.FTYP	;DO ONE
	SWAB	R0

;TYPE ONLY ONE CHARACTER IN R0			JSR PC,O.FTYP

O.FTYP:	MOVB	R0,O.BUF	;PUT CHAR IN BUFFER
	MOV	R0,-(SP)	;BREATHING ROOM
	JSR	PC,O.IO		;CALL SETUP
	INC	XRB+XRBC	;ONE BYTE TRANSFER
	.WRITE			;OUT IT GOES
	JSR	PC,@(SP)+	;RESTORE XRB
	MOV	(SP)+,R0	;GET IT BACK
	RTS	PC

O.IO:	MOV	@#FIRQB,O.IOST	;SAVE IOSTS
	MOV	#6.*2,R0	;BYTES IN XRB
1$:	MOVB	XRB-1(R0),O.XRB-1(R0)	;SAVE A BYTE
	SOB	R0,1$		;ALL PLEASE
	MOV	#XRB,R0		;ACCESS PTR
	MOV	#2,(R0)+	;XRLEN
	CLR	(R0)+		;XRBC
	MOV	#O.BUF,(R0)+	;XRLOC
	CLR	(R0)+		;XRCI (TTY)
	CLR	(R0)+		;XRBLK
	CLR	(R0)+		;XRTIME
	JSR	PC,@(SP)+	;PERFORM OPERATION
	MOV	#6*2,R0		;BYTES TO RESTORE
2$:	MOVB	O.XRB-1(R0),XRB-1(R0)	;RESTORE A BYTE
	SOB	R0,2$		;ALL OF THEM
	MOV	O.IOST,@#FIRQB	;RESTORE IOSTS
	RTS	PC		;DONE

O.GET:	TSTB	O.BUF	;<>0 MEANS SAVED CHARACTER
	BNE	2$
	JSR	PC,O.IO		;CALL SERVICE ROUTINE
	.TTDDT			;ANY ONE WILL DO
	.READ			;GET IT
	JSR	PC,@(SP)+	;RESTORE
2$:	MOVB	O.BUF,R0		;HERE IT IS
	CLRB	O.BUF	;USED UP
	SWAB	O.BUF	;POSITION FOR NEXT
	CMPB	#33,R0		;IS IT ALT MODE?
	BNE	1$		;NO
	MOVB	#'$,R0		;YES, USE $
1$:	CMPB	#' ,R0		;CVT BLANK
	BNE	O.GET1
	MOVB	#'+,R0		;INTO +
O.GET1:	RTS	PC
	.SBTTL	UTILITIES - PRETTY PRINTERS

;PRINT ADDRESS- RELOC, SYMBOLIC, OR ABSL	JSR PC.O.RORA

;R0	ADDRESS TO BE PRINTED
;O.FORM	CORE ADDRESS FORMAT (0-RELOC  1-ABSOL)

;REGISTER	'$R ' OR '$DR '
;CORE		'D,XXXXXX ' OR 'XXXXXX '

O.RORA:	MOV	R0,-(SP)	;CALLING VALUE ONA TOPPA SATCK
	CMP	#INTBEG,(SP)
	BHI	O.RO50		;BELOW FIRST NON-INDEXED
	CMP	#INTEND,(SP)
	BLO	O.RO50		;ABOVE LAST NON-INDEXED
	MOV	#'$,R0		;ANNOUNCE INTENTIONS
	JSR	PC,O.FTYP
	CMP	#INTINX,(SP)
	BLOS	O.RO20		;GO TO DO INDEXED
	MOV	(SP)+,R0	;NON-INDEXED REGISTER ----- "$R "
	SUB	#INTBEG,R0	;CLEANED UP STACK, GET OFFSET
	ASR	R0		;BYTE THAT WORD, WORD THAT BYTE
	MOVB	NIXMAP(R0),R0	;MAGIC CHARACTER FROM TABLE
O.RO15:	BIS	(PC)+,R0
	.BYTE	000,' 		;CHARACTER PLUSSA BLANK
	BR	O.TYPE		;NAME PLUS BLANK AND SPLIT
O.RO20:	CLR	R1		;SEE WHICH SET OF TABLES WE GOT
O.RO22:	CMP	INXTBL+2(R1),(SP)	;LOOK ON AHEAD TO FIND BEHIND
	BHI	O.RO24		;R1 POINTS TO BASE OF SET
	TST	(R1)+		;THINK ABOUT THOSE DUMMY ENTRIES DUMMY
	BR	O.RO22
O.RO24:	MOV	(SP)+,R0		;INDEXED REGISTER ---- "$DR "
	SUB	INXTBL(R1),R0	;GET ADDRESS AND COMPUTE OFFSET IN WORDS
	ASR	R0		;AND FINALLY IN PLAIN TALK
	ADD	#'0,R0		;CONVERT TO ASCII
	JSR	PC,O.FTYP	;TYPE OUT REGISTER NUMBER
	ASR	R1
	MOVB	INXREG(R1),R0	;PICK UP THE REAL CHARACTER
	BR	O.RO15		;GO PRINT REST OF IT
O.RO50:	TST	O.FORM		;CORE ADDRESS SEE WHAT USER WANTS
	BNE	O.RO90		;TYPE AS ABSOLUTE.
	MOV	(SP),R4		;RELOCATE ---- "R,XXXXXX "
	JSR	PC,O.LOCA	;WE ALWAYS PICK, ODT KNOWS BEST
	BMI	O.RO90		;BUT NOT ALL THE TIME
	MOV	R1,(SP)		;SET THE DISPLACEMENT
O.RO80:	ADD	#"0,,R0		;PRINT REGISTER AND COMMA
	JSR	PC,O.TYPE	;DISK AND CORE
O.RO90:	MOV	(SP)+,R0	;PRINT R0 AS A WORD
	;JSR	PC,O.CADW
	;RTS	PC
;TYPE R0 AS BYTE OR WORD, TWO ENTRIES
;	FOR A WORD				JSR PC,O.CADW
;	FOR A BITE				JSR PC,O.CADB

O.CADW:	MOV	R0,O.QUAN	;SET THE FAMOUS QUANTITY VALUE
	MOV	#6,R3		;# OF DIGITS
	MOV	#-2,R4		;# OF BITS FIRST-3
	BR	O.CA01		;DO THE COMMON THING
O.CADB:	CLR	O.QUAN		;SET FOR ALL OF QUAN A BYTE
	MOVB	R0,O.QUAN	;SET THE QUANTITY THING AGAIN
	MOV	#3,R3		;THERE ARE THREE DIGITS
	MOV	#-1,R4		;AND ONLY TWO BITS
	SWAB	R0		;SWITCH ENDS
O.CA01:	MOV	R0,-(SP)	;SAVE R0
O.CA03:	ADD	#3,R4		;COMPUTE THE NUMBER OF BITS TO DO
	CLR	R0
O.CA05:	ROL	(SP)		;GET A BIT
	ROL	R0		;STORE IT AWAY
	DEC	R4		;DECREMENT COUNTER
	BGT	O.CA05		;LOOP IF MORE BITS NEEDED
	ADD	#'0,R0		;CONVERT TO ASCII
	JSR	PC,O.FTYP	;TYPE IT
	DEC	R3		;SEE IF MORE DIGITS TO DO
	BGT	O.CA03		;LOOP IF SO
	MOVB	#' ,R0		;SET UP FOR TRAILING SPACE
	TST	(SP)+		;GET RID OF JUNK 
O.FT01:	JMP	O.FTYP

;TYPE CONTENTS OF WORD IN FORMAT	JSR PC,@TYFORM(R1)

;R0		WORD OR BYTE TO BE TYPED, RHJ
;R1		FORMAT CODE,	-0 BYTE OCTAL
;				-2 WORD OCTAL
;				-4 BYTE ANSII
;				-6 WORD ANSII
;				-10 RADIX 50 / MODULO 40

TYFORM:	+	O.CADB	;BYTE OCTAL
	+	O.CADW	;WORD OCTAL
	+	TYF040	;BYTE ANSII
	+	TYF060	;WORD ANSII
	+	TYF100	;RADIX 50

;MODULO 40, RADIX 50

TYF100:	MOV	#O.ALFA,R1	;SET OUTPUT DATA ADDRESS
	JSR	PC,UNPA00	;R0 TO RADIX 50
	MOV	#O.ALFA,R1
	MOVB	(R1)+,R0	;GET A CHARACTER, #1
	JSR	PC,O.FTYP
	MOV	(R1),R0		;GET CHARS #2 AND #3

;WORD ANSII

TYF060:	JSR	PC,O.FTYP	;TYPE BYTE IN R0
	SWAB	R0		;SWAP EM AND TYPE IT

;BYTE ANSII

TYF040:	JSR	PC,O.FTYP	;TYPE OF BYTE IN R0
	MOVB	#' ,R0		;SAVE SPACE
	BR	O.FT01		;ALSO SAVE SPACE
;SELECT RELOCATION REGISTER			JSR PC,O.LOC

;O.CAD		ADDRESS TO USE IN SELECTION

;RETURNS--
;R0				REGISTER NUMBER FOUND, -1 IF NONE FOUND
;R1				DISTANCE, RELOCATION FACTOR

;SUBROUTINE TO LOCATE RELOCATION REGISTER NEAREST BUT STILL 
;BELOW THE ADDRESS IN O.CAD.  RETURNS WITH THE REGISTER 
;NUMBER IN R0, AND WITH THE DISTANCE BETWEEN THE REGISTER 
;AND (O.CAD) IN R1
;IF NO GOOD RELOC. REG. FOUND, R0 WILL = -1

O.LOC:	MOV	O.CAD,R4	;SET UP CAD DATA
O.LOCA:	CLR	R0
	MOV	#-1,-(SP)	;INITIALIZE RELOC. REG. INDEX
	MOV	(SP),R1		;INITIALIZE DISTANCE TO A HIGH VALUE
O.LOC4:	CMP	R0,#O.RLR	;ARE WE DONE COMPARING?
	BHI	O.LOC1		;BRANCH IF DONE
	CMP	O.RELT(R0),R4	;IS CURR. RELOC. BIAS > (R4)?
	BHI	O.LOC2		;IF SO, BRANCH -- DON'T SUBTRACT, GET NEXT
	MOV	R4,R2		;OTHERWISE TAKE THE DIFFERENCE
	SUB	O.RELT(R0),R2	;OF CURR. RELOC. REG. AND O.CAD
	CMP	R1,R2		;IS THE RESULT THE SMALLEST SO FAR?
	BHI	O.LOC3		;BRANCH IF YES (UNSIGNED CONDITIONAL)
O.LOC2:	TST	(R0)+		;OTHERWISE, BUMP R0 FOR NEXT RELOC. REG.
	BR	O.LOC4		;LOOP BACK FOR NEXT COMPARISON
O.LOC1:	MOV	(SP)+,R0	;PUT REG.# IN R0
	RTS	PC		;JOB OVER, RETURN
O.LOC3:	MOV	R2,R1		;REMEMBER SMALLEST DIFFERENCE IN O.XXY
	ASR	R0		;AND ASSOCIATED REGISTER NUMBER
	MOV	R0,(SP)		; IN (SP)
	ASL	R0		;RESTORE R0 TO ORIGINAL VALUE
	BR	O.LOC2		;GO FO NEXT COMPARISON.
;	MOD40 UNPACK - ENTERED VIA JSR PC,UNPA00
;
;	INPUT:	R0= MOD40 NUMBER (1 WORD)
;		R1=ADR OF ASCII STRING (3 BYTES)
;
;	OUTPUT:	R1 POINTS ONE PAST LAST GENERATED CHARACTER
;
;	IF N IS THE MOD40 NUMBER, THEN
;		N=C1*50 ^ 2+C2*50+C3
;	THUS, N/50^2 IS C1 AND THE REMAINDER IS C2*50+C3
;	THE REMAINDER IS DIVIDED BY 50 TO GET C2 ETC.
;
UNPA00:	MOV	#-3,R5		;MINOR LOOP COUNT
	MOV	#COEFF,R2	;PTR TO COEFFICIENT TABLE
UNPA06:	CLR	R3		;0 QUOTIENT
;	DIVIDE BY COEFFICIENTS
UNPA02:	CMP	R0,(R2)		;DONE WITH DIVIDE?
	BLO	UNPA01	;YES
	SUB	(R2),R0		;NO-SUBTRACT COEFF.
	INC	R3		;ADD 1 TO QUOTIENT
	BR	UNPA02
;	DIVIDE DONE.  QUOT IN R3, REMAINDER IN R0
;	CONVERT TO AN ASCII CHARACTER
UNPA01:	TSTB	R3
	BEQ	UNPA03		;"BLANK"
	CMPB	R3,#33
	BEQ	UNPA05		;"$"
	BGT	UNPA04		;"." OR "0-9"
	ADD	#40,R3		;"A-Z"
UNPA03:	ADD	#16,R3
UNPA04:	ADD	#11,R3
UNPA05:	ADD	#11,R3
	MOVB	R3,(R1)+	;STORE CHARACTER
	TST	(R2)+		;ADVANCE TO NEXT COEFF.
	INC	R5		;DONE 3 CHARS?
	BLT	UNPA06		;NO-DO MORE
	RTS	PC

;COEFFICIENT TABLE

COEFF:	.WORD	+1600.,+40.,+1.		;40.^2,40.^1,40.^0

O.FIS:	BPT
	JMP	@VE+P.FIS-P.OFF
O.CRAS:	BPT
	JMP	@VE+P.CRAS-P.OFF
O.STR:	BPT
	JMP	@VE+P.STRT-P.OFF
O.NEW:	BPT
	JMP	@VE+P.NEW-P.OFF
O.RUN:	BPT
	JMP	@VE+P.RUN-P.OFF
O.BAD:	BPT
	CMP	(SP),#O.BRK1	;ERROR TRYING TO OWN ODT?
	BEQ	1$		;YES, SO FORGET IT ALOTGETHER
	JMP	@VE+P.BAD-P.OFF	;NO, SO CALL IT A REAL ERROR

1$:	CMP	(SP)+,(SP)+	;DUMP PC & PS FROM BAD TYPE TRAP
	MOV	(SP)+,FIRQB	;RESTORE ORIGINAL IO STATUS
O.BRK0:	RTI			;AND JUST EXIT

O.BRK:	TSTB	O.JOB		;ODT OWNED?
	BEQ	1$		;NO, SO OWN IT
	CMPB	O.JOB,FIRQB+FQJOB;YES, BY WHO?
	BNE	O.BRK0		;OTHERS, SO FORGET IT
1$:	MOV	FIRQB,-(SP)	;SAVE CURRENT IO STATUS
	MOVB	FIRQB+FQJOB,O.JOB;AND TRY TO OWN ODT
O.BRK1:	MOV	(SP)+,FIRQB	;RESTORE IO STATUS IF SUCCESSFUL
	JMP	O.BREK		;AND ENTER ODT FOR REAL
O.IOT:	BPT
	JMP	@VE+P.IOT-P.OFF
O.EMT:	BPT
	JMP	@VE+P.EMT-P.OFF
O.TRAP:	BPT
	JMP	@VE+P.TRAP-P.OFF
O.FPP:	BPT
	JMP	@VE+P.FPP-P.OFF
O.CC:	BPT
	JMP	@VE+P.CC-P.OFF
O.2CC:	BPT
	JMP	@VE+P.2CC-P.OFF
.MACRO	VECTOR	AT,TO
	ORG	ODTVE,AT-P.OFF
	TO
.ENDM	VECTOR

	VECTOR	P.ISIZ,2.
	VECTOR	P.MSIZ,2.
	VECTOR	P.FIS,O.FIS
	VECTOR	P.CRAS,O.CRAS
	VECTOR	P.STRT,O.STR
	VECTOR	P.NEW,O.NEW
	VECTOR	P.RUN,O.RUN
	VECTOR	P.BAD,O.BAD
	VECTOR	P.BPT,O.BRK
	VECTOR	P.IOT,O.IOT
	VECTOR	P.EMT,O.EMT
	VECTOR	P.TRAP,O.TRAP
	VECTOR	P.FPP,O.FPP
	VECTOR	P.CC,O.CC
	VECTOR	P.2CC,O.2CC
	VECTOR	P.SIZE,16.
	ORG	ODT

SIZODT	=	.-ODT	;SIZE OF ODT CODE AND DATA IN BYTES

	.END

