Google
 

Trailing-Edge - PDP-10 Archives - BB-M836A-BM - tools/ddt11/ddtsim.mac
There are 16 other files named ddtsim.mac in the archive. Click here to see a list.
	TITLE DDTSIM DDT11 SIMULATOR AND UBA CONTROL

	SUBTTL	LISTING CONTROL, AND OTHER USEFUL STUFF

	SEARCH	DDTSYM,JOBDAT,MACTEN,UUOSYM,MONSYM,MACSYM

	SALL			;GET NICE LISTINGS FOR A CHANGE
	.HWFRMT			;AND SKIP THE FANCY BITS
	.DIRECTIVE LITLST,FLBLST

EXTERNAL EXPRES,GOTO,MEMORY,MEMLIM,MEMUSE,SAVE24,CRLTYP,COMLF1,PDECTY
EXTERNAL OCTYPE,TYPSTR,ADRTYP,POSYMT,MOVMUS,SYMEND,DDT11,SAVE4,SYMBEG
EXTERNAL TYPCHR

ENTRY UBACTL,SIMXCT,MAPCOR,UPTIME,INSRUN,WAITIM,SIMREG,SETUPC,SIMREL
ENTRY IOBSTO,IOLOAD,IOSTOR
	SUBTTL	SIMULATION

RLMSIZ==0			; MUST BE DEFINED HERE

;HERE TO EXECUTE THE NEXT INSTRUCTION
; CALL	WITH F.RUNF CLEAR TO SINGLE INSTRUCTION
;	WITH F.RUNF SET TO RUN
;	CALL	SIMXCT
;	RETURN			;WHEN MACHINE HALTED
;				; AC1 WILL CONTAIN THE STARTING PC
SIMXCT:	TXZ	FLG,F.SVIO!F.HALT
	TXNN	PS,20		;IS T BIT SET ?
	SETZM	INTDLY
	SETZM	INTDLY+1
	TXON	FLG,F.TOPN	;HAS CTY BEEN OPENED ?
	CALL	SIMOPN		;DO OPEN FOR TTY
	CALL SIMSAC		;SETUP THE AC'S
	SETSTS	17,200		;SET NO ECHO
	TRNN	PC,1		;GET A BUM PC ?
	JRST	SIMCYC		;EXECUTE AN INSTRUCTION
	JRST	NXM...		;TAKE A BUS TRAP

SIMSAC:	EXCH	0,SIMREG
	EXCH	1,SIMREG+1
	EXCH	2,SIMREG+2
	EXCH	3,SIMREG+3
	EXCH	4,SIMREG+4
	EXCH	5,SIMREG+5
	EXCH	6,SIMREG+6
	EXCH	7,SIMREG+7
	TXC	FLG,F..SIM
	RET
;HERE TO SETUP THE PC TO EXECUTE
SETUPC:	SKIPN	AC1,EXPRESS	;DID USER GIVE A PC ?
	SKIPE	AC1,SIMREG+PC	;OR DID WE ALREADY HAVE A PC ?
	JRST	SETPC2
	SKIPE	INSRUN		;HAVE WE RUN YET ?
	JRST	SETPC2		;YES SO MUST BE WE MEANT 0 PC
	SKIPN	AC1,GOTO	;TAKE STARTING ADDRESS FOR PROGRAM
	HRRZ	AC1,DOT		;OH WELL USE CURRENT LOCATION
SETPC2:	HRRZM	AC1,SIMREG+PC
	RET

;HERE TO OPEN THE TTY FOR THE SIMULATOR
SIMOPN:	CALL	SIMREL		;RELOCATE STUFF
SIMOP1:	INIT	17,200		;SUPRESS ECHO
	SIXBIT	\TTY\
	Z
	EXIT
	CALL	R.SET		;RESET THE WORLD
	CALL	PS.CHK		;BE SURE LEVELS SET UP RIGHT
	RET
SIM.U1:
;MAIN LOOP FOR SIMULATION

SIM11:	TRNE	PS,PS...T	;CHECK T BIT
	JRST	TB.INT
SIM11A:
	SOSG	T1,INTDLY	;TIME TO CHECK FOR INTERRUPTS ?
	JRST	INTCHK		;CHECK TO SEE IF THERE IS AN INTERRUPT PENDING

SIMCYC:	HRRZ	MA,PC		;COPY PC
		MEMREL	MEMLIM
	CAIL	MA,0
	JRST	[CALL	IOLOAD+2	;GET INFORMATION
		MOVE	IR,T1		;PUT INSTRUCTION IN RIGHT REGISTER
		JRST	SIMCY1]
	ROT	MA,-2
	SKIPGE	MA
		MEMREL	MEMORY
	SKIPA	IR,(MA)
		MEMREL	MEMORY
	MOVS	IR,(MA)
SIMCY1:	ADDI	PC,2		;ADVANCE PC
	HRRZ	T2,IR		;COPY INSTRUCTION
	LSH	T2,-6		;POSITION FOR DISPATCH
	JRST	@OPDSP0(T2)	;DISPATCH ON OPCODE
;HERE IF OPCODE IN RANGE 000000 THRU 000077
OPDSPA:	JRST	@OPDSP1(IR)

;HERE IF OPCODE IN RANGE 000200 THRU 000277
OPDSPB:	JRST	@OPDSP2-200(IR)

;HERE FOR A TBIT TRAP
TB.INT:	INTSAV	14
	HRROS	INTDLY		;COME BACK THROUGH AGAIN
	JRST	SIM11A
;HERE BECAUSE TIMER WENT OFF - CHECK FOR INTERRUPTS ETC.

INTCHK:
	HRRE	T1,INTDLY	;CURRENT COUNT
	HRRE	T2,INTDLY+1	;ORIGINAL COUNT
	SUB	T2,T1
	ADDB	T2,INSRUN	;MAKE CURRENT NUMBER OF INSTRUCTIONS EXECUTED
	MOVE	T1,CTISPD	;PROBABLE MAXIMUM FOR INTDLY
	MOVEM	T1,INTDLY
	MOVEM	T1,INTDLY+1

;NOW SEE IF LAST INSTRUCTION HAD A STACK VIOLATION
INTCK0:	TXZN	FLG,F.SVIO	;HIT A STACK VIOLATION ?
	JRST	INTCK1		;NO
	INTSAV	4
	TXZ	FLG,F.SVIO

INTCK1:	TXNN	FLG,F.EXEC	;RUNNING IN EXEC MODE ?
	JRST	INTCK6		;NO SO DON'T TOUCH HDW
	SKIPE	T1,BR7PND	;ANY INTERRUPTS PENDING ON BR7 ?
	JRST	[SETZM	BR7PND		;FORGET OLD INTERRUPT
		JRST	INTCK3 ]	;GO TAKE THE INTERRUPT
	SKIPN	T1,BR5PND	;ANY BR5 INTERRUPTS PENDING ?
	JRST	INTCK6		;NO
	SETZM	BR5PND
INTCK3:	INTSAV	<(T1)>		;TAKE AN INTERRUPT
	HRROS	INTDLY		;CHECK FOR OTHER INTERRUPTS
	JRST	SIM11A		;IN CASE THAT LOWERED THE LEVEL

INTCK6:	CALL	TIMCHK		;CHECK FOR DEVICES THAT WANT TO INTERRUPT
	NOP

	TXNE	FLG,F.RUNF	;STILL RUNNING ?
	JRST	SIMCYC		;YES GO DO NEXT INSTRUCTION
	SETSTS	17,0		;PUT ECHO BACK ON
	JRST	SIMSAC		;SAVE SIMULATED REGS AND RET
;HERE TO CHECK FOR DEVICES WHICH MAY EXPIRED TIMERS

TIMCHK:	TXZ	FLG,F.FLOP

;HERE TO SEE IF ANY DEVICES WANT TIMER SERVICE

	HRRZ	T5,FIRDDB	;POINT TO FIRST DEVICE(LOWEST ADR)
TIMCK2:	SKIPN	DV.TIM+1(T5)	;IS THIS DEVICE TIMING ?
	JRST	TIMCK4		;NO SO DONE WITH IT
	MOVE	T2,INSRUN
	CAMGE	T2,DV.TIM+1(T5)	;HAS TIMER EXPIRED ?
	JRST	TIMCK3		;NOT TIME FOR AN INTERRUPT
	SETZM	DV.TIM+1(T5)
	CALL	@DV.TIM(T5)
TIMCK3:	SKIPN	T1,DV.TIM+1(T5)	;IS THERE A TIMER ?
	JRST	TIMCK4		;NO TIMER NOW
	SUB	T1,INSRUN	;MAKE RELATIVE TIME
	CAML	T1,INTDLY+1	;LOWER THAN OTHERS ?
	JRST	TIMCK4		;NO
	MOVEM	T1,INTDLY	;RESET TIMER
	MOVEM	T1,INTDLY+1
TIMCK4:	HRRZ	T5,DV.LNK(T5)	;GET ADR OF NEXT DEVICE
	JUMPN	T5,TIMCK2
	TXNE	FLG,F.FLOP
	AOS	(P)
	RET
INTDLY:	Z			;FLAG TO KEEP TRACK OF TIMING ETC.
		; TO REQUEST A CHECK FOR INTERRUPTS DO A HRROS INTDLY
	Z			;ORIGINAL COUNT IN INTDLY

INSRUN:	Z			;COUNTER TICKED ONCE PER INSTRUCTION
WAITIM:	Z			;TIME SPENT WAITING

	DEFINE	TADJUS <
	HRRE	T1,INTDLY	;CURRENT COUNT
	HRRE	T2,INTDLY+1	;ORIGINAL COUNT
	SUB	T2,T1		;COUNTS TAKEN SO FAR
	ADDM	T2,INSRUN	;UPDATE NUMBER OF INSTRUCTIONS EXECUTED
	MOVNS	T2
	ADDB	T2,INTDLY+1	;MAKES NEW INTERVAL
	HRRM	T2,INTDLY
>;DEFINE TADJUS
;HERE ON A RESET INSTRUCTION OR WHEN FIRST START
R.SET:
	HLLZ	MA,UBACTL	;GET UNIBUS CONTROLLER NUMBER
	TXNN	FLG,F.EXEC
	JRST	R.SET1		;DON'T RESET UNIBUS
	MOVEI	T1,1B29		;BIT TO DO UNIBUS RESET
	WRIO	T1,UBA.SR(MA)	;RESET THE UNIBUS
	CAIA
	HALT	R.SET		;IN CASE OF PAGE FAIL
	WRIO	T1,UBA.SR(MA)	;RESET THE UNIBUS
	CAIA
	HALT	R.SET		;IN CASE OF PAGE FAIL
	MOVEI	T1,1B18!1B19!1B20!1B21	;TO RESET TIMEOUT & MEMORY ERRORS
	WRIO	T1,UBA.SR(MA)
	CAIA
	HALT	R.SET
	RDIO	T1,UBA.SR(MA)
	TRNE	T1,740000	;ANY ERRORS LEFT ?
	HALT	R.SET
	MOVEI	T1,1B28		;STOP ON MEMORY ERRORS
	WRIO	T1,UBA.SR(MA)	;ASSIGN PI LVLS
	CAIA
	HALT	.+1		;IN CASE OF PAGE FAIL

;INITIALIZE THE CTY
	SETZM	COLUMN		;BACK TO THE LH MARGIN
R.SET1:	SETZM	BR7PND		;CLEAN OUT PENDING INTERRUPTS
	SETZM	BR5PND		; DITTO
	HRRZ	T5,FIRDDB	;POINT TO THE FIRST DEVICE
R.SET2:	SETZM	DV.TIM+1(T5)	;CLEAR TIMER FOR DEVICE
	CALL	@DV.RST(T5)	;RESET THIS DEVICE
	HRRZ	T5,DV.LNK(T5)	;GET NEXT DEVICE ADR
	JUMPN	T5,R.SET2	;LOOPBACK FOR REST OF DEVICES
	RET
;DISPATCH TABLE FOR INSTRUCTIONS

	DEFINE	X (VAL,MASK,NAME,FLAG) <
IFE	<<FLAG&<SMF.11!SMF.IN>>-<SMF.11!SMF.IN>> <
ZZ=<VAL/100>-Z
IFG	ZZ < REPEAT	ZZ,<
	EXP	ILLINS		;ILLEGAL INSTRUCTION DISPATCH
Z=Z+1	>>;IFG ZZ
ZZ=<VAL+<<-MASK>&177777>>/100-Z
IFG	ZZ < REPEAT	ZZ,<
	EXP	.'NAME		;DISPATCH FOR INSTRUCTION
Z=Z+1	>>;IFG ZZ
	>;IFE <<FLAG&<SMF.11!SMF.IN>>-<SMF.11!SMF.IN>>
>;DEFINE X

OPDSP0:	OPDSPA			;0000XX INSTRUCTIONS
	.JMP		;0001XX INSTRUCTIONS
	OPDSPB			;0002XX INSTRUCTIONS
Z=	3
	INSTRU
ZZ=	2000-Z

REPEAT	ZZ,<
	EXP	ILLINS
	XLIST
	>
	LIST
;DISPATCH TABLE FOR OPCODES 000000 THRU 000077

	DEFINE	X (VAL,MASK,NAME,FLAG) <
IFE	<<FLAG&<SMF.11!SMF.IN>>-<SMF.11!SMF.IN>> <
IFL	<VAL-100> <
ZZ=VAL-Z
IFG	ZZ <REPEAT ZZ,<
	EXP	ILLINS		;ILLEGAL INSTRUCTION DISPATCH
Z=Z+1
	>>;IFG ZZ
ZZ=VAL+<<-MASK>&177777>-Z
IFG	ZZ <REPEAT ZZ,<
	EXP	.'NAME		;DISPATCH FOR INSTRUCTION
Z=Z+1
	>>>>
>;DEFINE X (VAL,MASK,NAME,FLAG)

Z=0
OPDSP1:	INSTRU			;DO DISPATCHS FOR 000000-000077
REPEAT	<100-Z>,<
	EXP	ILLINS
	XLIST
	>
	LIST

;DISPATCH TABLE FOR OPCODES 000200 THRU 000277

	DEFINE	X (VAL,MASK,NAME,FLAG) <
IFE	<<FLAG&<SMF.11!SMF.IN>>-<SMF.11!SMF.IN>> <
IFL	<VAL-240> <
ZZ=VAL-Z
IFG ZZ <REPEAT	ZZ,<
	EXP	ILLINS		;ILLEGAL INSTRUCTION DISPATCH
Z=Z+1
	>>
ZZ=VAL+<<-MASK>&177777>-Z
IFG ZZ <REPEAT	ZZ,<
	EXP	.'NAME		;DISPATCH FOR INSTRUCTION
Z=Z+1
	>>>>
>;DEFINE X (VAL,MASK,NAME,FLAG)

Z=200
OPDSP2:	INSTRU			;DO DISPATCHS FOR 000200-000227
REPEAT	<240-Z>,<
	EXP	ILLINS
	XLIST
	>
	LIST
	EXP	SIM11		;THIS IS A NOP
REPEAT	17,<
	EXP	.CCCLR		;CLEAR CONDITION CODES
	XLIST
	>
	LIST
	EXP	SIM11		;THIS IS A NOP
REPEAT	17,<
	EXP	.CCSET		;SET CONDITION CODES
	XLIST
	>
	LIST
	SUBTTL	OPCODE SIMULATION

	DEFINE	X (VAL,MASK,NAME,FLAG) <
IFE	<<FLAG&<SMF.11!SMF.IN>>-<SMF.11!SMF.IN>> <
IFN	<<VAL&177740>-240> <
	.'NAME:		ZZRET==0
IFN	<FLAG&<SMF.SS!SMF.DD!SMF.EI>>,<ANDI IR,77>	;LEAVE ONLY DD
IFN	<FLAG&SMF.SS>,<
	ANDI	T2,77		;LEAVE ONLY SS
IFN	<FLAG&SMF.BY>,<JSR @SBFTCH(T2)>	;GET BYTE SOURCE OPERAND
IFE	<FLAG&SMF.BY>,<JSR @SFETCH(T2)>	;GET SOURCE OPERAND
	>
	NAME'.	FLAG		;MACRO FOR UNIQUE CODE
IFN	<FLAG&SMF.BR> <
	TRNE	IR,200		;POSITIVIE OR NEGATIVE OFFSET
	TROA	IR,177400	;NEGATIVE SO EXTEND SIGN
	TRZ	IR,177400	;POSITIVE SO EXTEND SIGN
	LSH	IR,1		;MAKE OFFSET * 2
	ADD	PC,IR
	ANDI	PC,177777	;IN CASE PC SPILLED OUT OF 16 BITS
	>
IFE	ZZRET,<JRST SIM11>
	>>
>;DEFINE X

	INSTRU
;HERE WHEN INSTRUCTION TRIES TO JMP TO REG
JMPREG:	Z			;CAME WITH A JSR
	JRST	NXM...		;DIE

;HERE IF @STUFF (OR @BSTUFF) GIVES BUS TRAP
STFNXM:	HRR PS,PS.REG+1		;RESTORE OLD PS
	JRST	NXM...

;HERE FOR ILLEGAL MEMORY REFERENCES
NXM...:	INTSAV	4
	JRST	SIM11

;HERE FOR ILLEGAL INSTRUCTION
ILLINS:	INTSAV	10
	JRST	SIM11

;HERE FOR A CONDITION CODE CLEAR
.CCCLR:	ANDI	IR,17		;STRIP EXTRA BITS
	TRZ	PS,(IR)		;CLEAR BITS
	JRST	SIM11

;HERE FOR A CONDITION CODE SET
.CCSET:	ANDI	IR,17		;STRIP EXTRA BITS
	TRO	PS,(IR)		;SET BITS
	JRST	SIM11

;HERE FOR A STACK VIOLATION & RESTORE PS IF RED STACK & PDP11/40
STCKVP:	Z			;HERE WITH A JSR
	TXO	FLG,F.SVIO	;REMEMBER WE HAD VIOLATION
	HRROS	INTDLY		;SO WE FIND IT QUICK
	CAIL	MA,400-40	;DO WE NEED TO FORCE A RED ?
	JRST	@STCKVP		;JUST YELLOW SO RETURN
	HRR	PS,PS.REG+1	;RESTORE PS
	JRST	RSTACK		;AND TAKE A RED STACK

;HERE FOR A STACK VIOLATION
STACKV:	Z			;HERE WITH A JSR
	TXO	FLG,F.SVIO	;REMEMBER WE HAD VIOLATION
	HRROS	INTDLY		;SO WE FIND IT QUICK
	CAIL	MA,400-40	;DO WE NEED TO FORCE A RED ?
	JRST	@STACKV		;JUST YELLOW SO RETURN

;HERE FOR A RED STACK VIOLATION
RSTACK:	TXZ	FLG,F.SVIO	;WE DID IT
	MOVEI	MA,2		;PUT PS AT 2
	STORE	MA,PS		;SAVE THE PS
	SETZB	SP,MA
	STORE	MA,PC		;SAVE THE PC IN 0
	MOVEI	MA,4		;ADR OF NEW PC
	LOAD	MA,T1		;GET THE NEW PC
	MOVEI	MA,6		;GET THE NEW PS
	LOAD	MA,T2		;GET THE NEW PS
	ANDI	T2,377		;STRIP EXTRA BITS
	MOVE	PC,T1		;SET THE NEW PC
	MOVE	PS,T2		;SET THE NEW PS
	TRNE	PC,1		;BAD PC ?
	TXZ	FLG,F.RUNF	;STOP THE MACHINE
	JRST	SIM11
	SUBTTL	ADDRESSING MODE CALCULATIONS

;DISPATCH TO FECTH SOURCE OPERAND (WORD MODE)
SFETCH:	TAGDSP SGET

;DISPATCH TO FETCH OPERAND (WORD MODE)
FETCH:	TAGDSP	GET

;DISPATCH TO FETCH OPERAND (WORD MODE) AND SET UP MA FOR RSTORE
RFETCH:	TAGDSP	RGET

;DISPATCH TO FETCH SOURCE OPERAND (BYTE MODE)
SBFTCH:	TAGDSP SBGT

;DISPATCH TO FETCH OPERAND (BYTE MODE)
BFETCH:	TAGDSP	BGET

;DISPATCH TO FETCH OPERAND (BYTE MODE) AND SET UP MA FOR RSTORE
BRFTCH:	TAGDSP	BRGT

;DISPATCH TO DO ADDRESS CALCULATION FOR JMP OR JSR
JMPCLC:	TAGDSP	JMP

;DISPATCH TO STORE OPERAND (WORD MODE)
; RH OF OPERAND MUST ALREADY BE MASKED TO 16 BITS (LH MAY BE NONZERO)
STUFF:	TAGDSP	PUT

;DISPATCH TO STORE OPERAND (BYTE MODE)
; RH OF OPERAND MUST ALREADY BE MASKED TO 8 BITS (LH MAY BE NONZERO)
BSTUFF:	TAGDSP	BPUT


;EXPAND MACRO FOR GET, RGET AND PUT

QQ=	0
	REPEAT	10,<
	MODES	\QQ
QQ=	QQ+1
	>;REPEAT 10
	SUBTTL	IO SIMULATION

;ROUTINE TO READ AND WRITE IN THE IO AREA
; NOTE THAT REFERENCES ARE NOT CHECKED TO BE SURE IN IO AREA (160000-177777)
; THIS DOESN'T MATTER BECAUSE THEY WILL REFERENCE 600000+MEMLIM TO 7600000
; WHICH SHOULD PAGE FAIL (UNLESS MEMORY IS ON UNIBUS)

	DEFINE	X (Q,QQ) <
	XLIST
	HRRZ	MA+1,FIRDDB
	CAMG	MA,1(MA+1)
	JRST	[CAMGE	MA,(MA+1)
		JRST	.+3
		TLO	MA,MA..IO	;REMEMBER IS AN IO DEVICE
		JRST	@DV.'Q(MA+1) ]
	HRRZ	MA+1,DV.LNK(MA+1)	;GET NEXT DEVICE ADR
	JUMPN	MA+1,.-3
	TXNN	FLG,F.EXEC
	JRST	QQ		;CAN'T HELP THIS GUY
	HLL	MA,UBACTL	;ADD UBA UNIT NUMBER
	LIST
>;DEFINE X (OFFSET)
;HERE TO DO A WORD LOAD FROM AN IO REGISTER
	SKIPA	T1,[EXP 1]	;SIMPLE SKIP RETURN FOR GETWRD
IOLOAD:	MOVEI	T1,LODRET	;SO RETURN GOES RIGHT
	ADDM	T1,(P)
	X	LOD,NXMRET
	TXNN FLG,F.EXEC
	JRST NXMRET
	RDIO	T1,600000(MA)	;GET DATA FROM UNIBUS
	JRST	IORET		;DONE

;HERE FOR A NXM (AFTER POPING RETURN OFF STACK)
NXMRET:	TXNN	FLG,F.EXEC	;RUNNING IN EXEC MODE ?
	JRST	NXMRT3		;NO
	MOVEI	T2,1B18+1B21+1B28
	LDB	T1,P.PLVL	;GET PROCESSOR LEVEL
	CAIGE	T1,7		;ALLOW BR7 ?
	MOVEI	T2,1B18+1B21!UBA.B7
	CAIGE	T1,5		;ALLOW BR7 ?
	MOVEI	T2,1B18+1B21!UBA.B5!UBA.B7
	HLLZ	T1,UBACTL	;POINT TO RIGHT UNIBUS
	WRIO	T2,UBA.SR(T1)	;CLEAR FLAG
NXMRT3:	TXNN	FLG,F..SIM	;ARE WE SIMULATING ?
	JRST	[SOS	(P)		;UNSKIP THE RETURN
		RET	]
	POP	P,T1		;CLEAN OFF STACK
	JRST	NXM...

IORET:	HRLI	MA,MA..UN!MA..IO	;MUST BE A UNIBUS DEVICE
	RET

;HERE TO DO A BYTE LOAD FROM AN IO REGISTER
	SKIPA	T1,[EXP 1]	;SIMPLE SKIP RETURN
IOBLOD:	MOVEI	T1,BLDRET	;NUMBER OF INSTRUCTIONS TO SKIP
	ADDM	T1,(P)		;SKIP RETURN
	X	BLD,NXMRET
	TXNN FLG,F.EXEC
	JRST NXMRET
	RDIOB	T1,600000(MA)	;GET DATA FROM UNIBUS
	JRST	IORET		;WILL SKIP IF FAILED
;HERE TO STORE A WORD IN THE IO AREA
IOSTOR:
	X	WRT,STONXM
	TXNN FLG,F.EXEC
	JRST STONX3
	WRIO	T1,600000(MA)	;GIVE DATA TO UNIBUS
	JRST	IORET
STONXM:	TXNN	FLG,F.EXEC	;RUNNING IN EXEC MODE ?
	JRST	STONX3		;NO
	MOVEI	T2,1B18+1B21+1B28
	LDB	T1,P.PLVL	;GET PROCESSOR LEVEL
	CAIGE	T1,7		;ALLOW BR7 ?
	MOVEI	T2,1B18+1B21!UBA.B7
	CAIGE	T1,5		;ALLOW BR7 ?
	MOVEI	T2,1B18+1B21!UBA.B5!UBA.B7
	HLLZ	T1,UBACTL	;POINT TO RIGHT UNIBUS
	WRIO	T2,UBA.SR(T1)	;CLEAR FLAG
STONX3:	TXNN	FLG,F..SIM	;ARE WE SIMULATING ?
	RET
	POP	P,T1		;CLEAN OFF STACK
	JRST	STFNXM		;GIVE BUS TRAP

;HERE TO STORE A BYTE IN THE IO AREA
IOBSTO:
	X	BWR,STONXM
	TXNN FLG,F.EXEC
	JRST STONXM
	WRIOB	T1,600000(MA)	;GET DATA FROM UNIBUS
	JRST	IORET		;WON
	DEFINE	X (Q,QQ) <
	XLIST
	TLNN	MA,MA..UN	;IS THIS A UNIBUS DEVICE ?
	JRST	Q		;SAME AS PLAIN TYPE
	HLL	MA,UBACTL	;ADD UNIBUS UNIT
	QQ	T2,600000(MA)	;DO THE WRITE
	RET
	JRST	IORERR		;ERROR !?!
	LIST
>;DEFINE X

;HERE TO RESTORE (CLEARING BITS) A WORD TO THE IO AREA
IOR.C:	X	IOR.,BCIO

;HERE TO RESTORE (SETTING BITS) A WORD TO THE IO AREA
IOR.S:	X	IOR.,BSIO

;HERE TO RESTORE A WORD TO THE IO AREA
IOR.:	TLNE	MA,MA..UN	;IS THIS A UNIBUS DEVICE ?
	JRST	[HLL	MA,UBACTL	;ADD UNIBUS UNIT
		WRIO	T1,600000(MA)	;WRITE THE DATA
		RET
		JRST	IORERR ]	;ERROR !?!
	ANDI	MA,177777
	JRST	@DV.WRT(MA+1)	;STORE DATA

;HERE TO RESTORE (CLEARING BITS) A BYTE TO THE IO AREA
IOBR.C:	X	IOBR.,BCIOB

;HERE TO RESTORE (SETTING BITS) A BYTE TO THE IO AREA
IOBR.S:	X	IOBR.,BSIOB

;HERE TO RESTORE A BYTE TO THE IO AREA
IOBR.:	TLNE	MA,MA..UN	;IS THIS A UNIBUS DEVICE ?
	JRST	[HLL	MA,UBACTL	;ADD UNIBUS NUMBER
		WRIOB	T1,600000(MA)	;WRITE THE DATA
		RET
		JRST	IORERR ]	;ERROR !?!
	ANDI	MA,177777	;STRIP EXTRA BITS
	JRST	@DV.BWR(MA+1)	;STORE DATA

;HERE IF ERROR RESTORING DATA
IORERR:	HALT	.

DDBADR==200000

DDBLNK==0
;HERE TO WRITE A SIMULATED DEVICE REGISTER
; CALL	MOVE	T1,<WANT TO WRITE>
;	CALL	DEVWRT
;	RETURN	WITH NEW REGISTER IN T1
DEVWRT:	ANDI	MA,177777	;STRIP EXTRA BITS
	HRRZ	T2,MA		;COPY DEVICE ADDRESS
	SUB	T2,(MA+1)	;MAKE RELATIVE ADR
	ADDI	T2,DV.SIZ(MA+1)	;POINT TO DEVICE REGISTERS
	PUSH	P,T1		;SAVE DATA TO WRITE
	MOVE	T1,(T2)		;GET ORIGINAL REGISTER
	HRRM	T1,1(T2)	;SAVE ORIGINAL REGISTER
	HLRZS	T1		;BITS PROGRAM CAN WRITE
	TXNN	FLG,F..SIM	;IS SIMULATION RUNNING
	HLRZ	T1,1(T2)	;NO SO HAVE DIFFERENT ENABLES
	ANDCAM	T1,(T2)		;CLEAR BITS IN SIMULATED REGISTER
	AND	T1,(P)		;BITS TO SET
	IORB	T1,(T2)		;SET NEW BITS
	POP	P,T2		;CLEAN UP STACK
	RET
	SUBTTL	IO SIMULATION - PS

;HERE FOR PDP11 REFERENCES TO THE PS

	DDBGEN	PS.,1

PS.REG:
	000357,,0	;PS REGISTER FOR DEVWRT, ETC.
	000377,,0	;LET OPERATOR SET ALL BITS

PS.LOD:	HRRZ	T1,PS		;JUST A LOAD
	RET

PS.BLD:	HRRZ	T1,PS		;LOAD THE PS
	TRNE	MA,1		;WANT LEFT HALF ?
	LSH	T1,-^D8
	ANDI	T1,377
	RET

PS.BWR:	TRNE	MA,1		;WRITING LH ?
	RET
PS.WRT:	HRRM	PS,PS.REG	;COPY CURRENT PS
	CALL	DEVWRT		;SET NEW PS
	HRRZ	PS,PS.REG	;SETUP NEW PS
;HERE TO SEE IF NEW PS IS LOWER PRIORITY THAN OLD PS AND IF SO CHECK FOR INTERRUPTS
PS.CHK:	LDB	T2,P.PLVL	;GET CURRENT PS LEVEL
	TXNN	FLG,F.EXEC	;RUNNING IN EXEC MODE ?
	JRST	PSCHK0		;NO SO DON'T CHANGE ANYTHING
	MOVEI	T1,1B28		;ASSUME CAN'T TAKE INTERRUPTS
	CAIGE	T2,7		;CAN WE TAKE BR7'S NOW ?
	HRRZI	T1,UBA.B7	;ENABLE CHANNEL FOR BR7
	CAIGE	T2,5		;CAN WE TAKE BR5'S NOW ?
	HRRZI	T1,UBA.B5!UBA.B7;ENABLE FOR BR5 & BR7
	HLLZ	T2,UBACTL	;POINT TO UNIBUS
	WRIO	T1,UBA.SR(T2)	;ENABLE TO TAKE INTERRUPTS
PSCHK0:	HRRZ	MA+1,FIRDDB
PSCHK1:	CAML	T2,DV.LVL(MA+1)
	JRST	PSCHK3
	TXZ	FLG,F.FLOP
	CALL	@DV.INT(MA+1)
	TXNE	FLG,F.FLOP	;DID THAT ONE TAKE AN INTERRUPT ?
	RET			;ALL DONE
	LDB	T2,P.PLVL	;GET CURRENT PS LEVEL
PSCHK3:	HRRZ	MA+1,DV.LNK(MA+1)
	JUMPN	MA+1,PSCHK1
	RET
	SUBTTL	IO SIMULATION - SWITCHES

;HERE FOR PDP11 REFERENCES TO THE SWITCH REGISTER

SW.WRT==DEVWRT				;PLAIN DEVICE WRITE
	DDBGEN	SW.,1

SW.REG:	0,,0				;THIS IS THE SWITCH REGISTER
	177777,,0			;LH IS WRITEABLE BY OPER BITS

SW.LOD:	MOVE	T1,SW.REG		;LOAD THE SWITCHES
	RET

SW.BLD:	MOVE	T1,SW.REG		;LOAD THE SWITCHES
	TRNE	T1,1			;WANT LH BYTE ?
	LSH	T1,-10			;WANT LH
	ANDI	T1,377			;ONLY 8 BITS
	RET

SW.BWR:	TXNE	FLG,F..SIM		;ARE WE SIMULATING ?
	RET				;YES SO DON'T WRITE IT
	TRNN	MA,1			;WRITING RH ?
	DPB	T1,[POINT 8,SW.REG,35]	;YES
	TRNE	MA,1			;WRITING LH ?
	DPB	T1,[POINT 8,SW.REG,27]
	RET
	SUBTTL	IO SIMULATION - CTY

;HERE TO READ OR WRITE THE SIMULATED CTY REGS

	DDBGEN	CTY,4

;SIMULATED DEVICE REGISTERS FOR CTY
; LH IS MASK FOR BITS WHICH USER CAN WRITE
; RH IS SIMULATED REGISTER
; 2ND WORD IS COPY BEFORE WRITE
CTISTS:	100,,200
	300,,0
CTIDAT:	377,,0
	377,,0
CTOSTS:	104,,200	;200=RDY,100=ENAB,4=MAINT
	304,,0
CTODAT:	377,,0
	377,,0
CTOFLG:	-1		;WHEN -1 CTY OUTPUT WANTS TO INTERRUPT
CTIFLG:	-1		;WHEN -1 CTY INPUT WANTS TO INTERRUPT

CTITIM:	Z			;TIME TO CHECK CTY FOR INPUT
CTISPD:	EXP	010000		;NUMBER OF INSTRUCTIONS BETWEEN INPUTTING CHARS
CTOTIM:	Z			;TIME FOR CTY OUTPUT TO BE DONE OR 0
CTOSPD:	EXP	001000		;NUMBER OF INSTRUCTIONS BETWEEN PRINTING CHARS
;HERE ON A RESET
CTYRST:	MOVE	T1,CTISPD	;START TIMING AGAIN
	ADD	T1,INSRUN	;MAKE ABSOLUTE
	MOVEM	T1,CTITIM	;TIME TO CHECK KEYBOARD AGAIN
	MOVEM	T1,DV.TIM+1+CTYDDB	;TIME TO CHECK KEYBOARD
	SETZM	CTOTIM		;DON'T NEED TIMER FOR PRINTER
	HLLZS	CTISTS		;CLEAR KEYBOARD REGISTER
				;CTIDAT UNAFFECTED
	SETZM	CTIFLG		;DON'T WANT TO INTERRUPT
	MOVEI	T1,200		;DONE FLAG
	HRRM	T1,CTOSTS	;FOR TELEPRINTER
	HLLZS	CTODAT		;CLEAR OUTPUT DATA REGISTER
	SETOM	CTOFLG		;WANT TO INTERRUPT
	RET

;HERE IF USER DOES A BYTE OPERATION TO READ A CTY REGISTER
CTYBLD:	SETZ	T1,
	TRNE	MA,1
	RET
	;FALL INTO WORD OPERATION

;HERE IF USER DOES A WORD OPERATION TO READ A CTY REGISTER
CTYLOD:	SETCMI	T1,200		;MASK FOR CTISTS
	TXNN	FLG,F..SIM	;ARE WE SIMULATING ?
	SETZ	T1,		;NO - DON'T ZERO ANYTHING
	CAMN	MA,[MA..IO,,CTYADR+2]	;READING DATA ?
	ANDM	T1,CTISTS	;CLEAR DONE FLOP
	HRRZ	T1,CTISTS-CTYADR(MA)	;GET REGISTER FOR HIM
	RET

;HERE IF USER DOES A BYTE WRITE TO A CTY REGISTER
CTYBWR:	TRNE	MA,1		;WRITING LH ?
	RET			;NO BITS THERE TO CHANGE
	;FALL INTO WORD OPERATION

;HERE IF USER DOES A WORD WRITE TO A CTY REGISTER
CTYWRT:	CALL	DEVWRT		;PERFORM THE WRITE
	JRST	@.+1-CTYADR(MA)
	CTIWRS			;WRITE CTY KEYBOARD STATUS REGISTER
	HALT	.
	R			;WRITE KEYBOARD DATA REGISTER
	HALT	.
	CTOWRS			;WRITE CTY PRINTER STATUS REGISTER
	HALT	.
	CTOWDT			;WRITE CTY PRINTER DATA
	HALT	.
	DEFINE	X (Q,VEC) <
	XLIST
	CT'Q'WRS:	TDZ	T1,CT'Q'STS+1	;CLEAR BITS WHICH WERE ALREADY SET
	TRNN	T1,100		;WAS ENABLE SET ?
	RET			;WAS ALREADY SET
	SETOM	CT'Q'FLG	;CAN INTERRUPT AGAIN
	JRST	CTYCHK		;CHECK FOR INTERRUPTS
	LIST
>;DEFINE X

;HERE BECAUSE WRITING CTY KEYBOARD STATUS REGISTER
	X	I,60

;HERE BECAUSE WRITING CTY PRINTER STATUS REGISTER
	X	O,64

;HERE BECAUSE WRITING CTY PRINTER DATA REGISTER
CTOWDT:	MOVEI	T1,200		;READY FLOP
	ANDCAM	T1,CTOSTS
	SETZM	CTOFLG		;DON'T WANT TO INTERRUPT
	TADJUS			;BE SURE INSRUN IS CURRENT
	MOVE	T1,CTOSPD	;TIME TILL ALL PRINTED
	CAML	T1,INTDLY+1	;BEFORE WE STOP TO CHECK ?
	JRST	CTOWD1		;YES
	HRRM	T1,INTDLY	;SET NEW TIME TO STOP
	HRRM	T1,INTDLY+1
CTOWD1:	ADD	T1,INSRUN	;ABSOLUTE TIME TO FINISH PRINT
	MOVEM	T1,CTOTIM	;REMEMBER WHEN DONE
	CAMGE	T1,DV.TIM+1+CTYDDB	;SOONER THAN KEYBOARD ?
	MOVEM	T1,DV.TIM+1+CTYDDB	;SOONER SO USE THIS VALUE
	RET
;HERE IF TIMER FOR CTY GOES OFF
CTYTIM:	MOVE	T1,INSRUN	;GET NUMBER OF INSTRUCTIONS EXECUTED SO FAR
	CAMGE	T1,CTITIM	;TIME TO CHECK FOR CTY INPUT ?
	JRST	CHKCTO
	ADD	T1,CTISPD
	MOVEM	T1,CTITIM	;RESET CTY TIMER
	INCHRS	T1		;HAS USER TYPED ?
	JRST	CHKCTO		;NOT YET
	ANDI	T1,177		;STRIP PARITY (SHOULDN'T HAVE BEEN SET)
	CAIN	T1,15		;WAS THAT A CARRIAGE RETURN ?
	JRST	[INCHRS	T2		;GET THE LF THAT FOLLOWES
		NOP			;FOOBAZ !!!!
		JRST	.+1 ]
	CAIN	T1,5		;WAS THAT A <^E>
	JRST	[TYPE	<
^E
>
		CALL	TYPSTR
		HRROS	INTDLY		;STOP THE SIMULATION
		TXZ	FLG,F.RUNF	;STOP THE SIMULATION
		JRST	CHKCTO ]
	CAIN	T1,24		;WAS THAT A ^T ?
	JRST	CNTRLT		;DISPLAY STATUS FOR CONTROL T
	HRRM	T1,CTIDAT	;SAVE CHAR FOR PROGRAM
	MOVEI	T1,200		;DONE FLAG
	IORB	T1,CTISTS	;SET FLAG
	SETOM	CTIFLG		;SO WE INTERRUPT
CHKCTO:	SKIPE	T1,CTOTIM	;ARE WE TIMING TRANSMITTER ?
	CAMLE	T1,INSRUN	;AND HAS ITS TIME COME ?
	JRST	CTTIM8		;NO
	HRRZ	T1,CTODAT	;GET CHARACTER TO PRINT
	CALL	TYPCHR		;TYPE THE CHARACTER
	SETZM	CTOTIM		;CLEAR TIMER
	MOVEI	T1,200		;DONE FLAG
	IORB	T1,CTOSTS	;FLAG ITS DONE
	SETOM	CTOFLG		;WANT TO INTERRUPT
CTTIM8:	SKIPE	T1,CTOTIM	;ARE WE TIMING TRANSMITTER ?
	CAMLE	T1,CTITIM	;WILL TRANSMITTER BE FIRST ?
	MOVE	T1,CTITIM	;USE KEYBOARD TIME
	MOVEM	T1,CTYDDB+DV.TIM+1	;SET TIMER
CTYCHK:	LDB	T1,P.PLVL	;GET PROCESSOR LEVEL
	CAML	T1,CTYDDB+DV.LVL	;CAN WE TAKE INTERRUPTS NOW ?
	RET			;NOT NOW
;HERE CAUSE PS WENT BELOW OUR LVL
CTYINT:	MOVE	T1,CTISTS	;GET RECEIVER STATUS
	TRNE	T1,200		;IN INTERRUPT FLAG UP
	TRNN	T1,100		;AND IS ENABLE SET ?
	JRST	CTOINT		;CHECK TRANSMITTER
	SKIPN	CTIFLG		;MAY WE INTERRUPT ?
	JRST	CTOINT		;NO SO CHECK TRANSMITTER
	SETZM	CTIFLG		;DON'T INTERRUPT AGAIN
	INTSAV	60		;TAKE INPUT INTERRUPT
	TXO	FLG,F.FLOP	;FLAG WE TOOK AN INTERRUPT
CTOINT:	MOVE	T1,CTOSTS	;GET TRANSMITTER STATUS
	TRNE	T1,200		;IS FLAG SET ?
	TRNN	T1,100		;AND IS ENABLE SET ?
	RET
	SKIPN	CTOFLG		;WANT TO INTERRUPT ?
	RET			;CAN'T INTERRUPT AGAIN
	SETZM	CTOFLG		;DON'T WANT ANOTHER
	INTSAV	64		;TAKE A TRANSMITTER INTERRUPT
	TXO	FLG,F.FLOP	;FLAG WE TOOK AN INTERRUPT
	RET
;HERE WHEN READ A CONTROL T FROM CTY WHILE SIMULATING

CNTRLT:	CALL	SIMSAC		;SAVE REG'S
	TYPE	< PC = >
	MOVE	T1,SIMREG+PC
	CALL	ADRTYP
	TYPE	< PS = >
	MOVE	T1,PS
	CALL	OCTYPE
	TYPE	< after >
	MOVE	T1,INSRUN
	CALL	PDECTY
	TYPE	< instructions >
	TXNN	FLG,F.LOPN	;WAS A LOCATION OPEN ?
	JRST	CNTLT6		;NO SO DON'T DISPLAY
	PUSH	P,T5		;SAVE DDB POINTER
	CALL	COMLF1		;DISPLAY LOCATION
	POP	P,T5		;RESTORE DDB POINTER
CNTLT6:	CALL	SIMSAC		;RESTORE AC'S
	CALL	CRLTYP
	JRST	CHKCTO
	SUBTTL	IO SIMULATION - KW11L CLOCK

;HERE FOR REFERENCES TO KW11 CLOCK

	DDBGEN	CLK,1

CLKSTS:	000300,,0	;SIMULATED CLOCK STATUS REGISTER
	000300,,0	; 200=INT,100=ENAB
CLKFLG:	Z			;WHEN NONZERO CLOCK CAN INTERRUPT
CLKSPD:	EXP	^D1000		;INSTRUCTIONS/CLOCK TICK
			; THIS IS SLOWER THAN REAL 11/40 BUT
			; FASTER THAN SIMULATED 11/40
CLKTCK:	Z			;COUNTED DOWN ONCE/MILASECOND

;HERE FOR THE KW11L ON A RESET
CLKRST:	MOVEI	T1,200
	HRRM	T1,CLKSTS
	SETOM	CLKFLG		;CAN TAKE AN INTERRUPT
	TXNN FLG,F.EXEC
	JRST CLKRS1
	MOVEI	T1,^D20		;NUMBER OF MILLASECONDS TILL NEXT TICK
	MOVEM	T1,CLKTCK
CLKRS1:	TADJUS			;MAKE TIMER CURRENT
	MOVE	T1,CLKSPD	;TIME TILL NEXT TICK
	CAML	T1,INTDLY+1	;LESS THAN ANY OTHER ?
	JRST	CLKRS2
	HRRM	T1,INTDLY+1
	HRRM	T1,INTDLY
CLKRS2:	ADD	T1,INSRUN	;TIME TILL NEXT TICK
	MOVEM	T1,CLKDDB+DV.TIM+1
	RET
;HERE TO READ THE CLOCK
CLKLOD:	HRRZ	T1,CLKSTS	;GET THE STATUS REGISTER
	RET			;RETURN

;HERE TO READ THE CLOCK WITH A BYTE INSTRUCTION
CLKBLD:	TRNE	MA,1		;WANT RH OR LH ?
	TDZA	T1,T1		;WANTED LEFT HALF
	HRRZ	T1,CLKSTS	;WANTED RH
	RET

;HERE FOR A BYTE WRITE TO THE KW11L
CLKBWR:	TRNE	MA,1		;WRITING RH OR LH ?
	RET			;DON'T WRITE LH

;HERE TO WRITE THE KW11L
CLKWRT:	CALL	DEVWRT		;PERFORM THE WRITE
	TDZ	T1,CLKSTS+1	;CLEAR BITS ALREADY SET
	TRNE	T1,100		;DID THAT SET ENABLE ?
	SETOM	CLKFLG		;CAN INTERRUPT AGAIN
	JRST	CLKWR3		;CHECK FOR POSSIBLE INTERRUPT

;HERE WHEN TIMER GOES OFF FOR THE CLOCK
CLKTIM:	TADJUS			;BE SURE TIMER CURRENT
	MOVE	T1,CLKSPD	;TIME TILL NEXT CLOCK TICK
	CAML	T1,INTDLY+1	;WILL THIS BE NEXT DEVICE TO TICK ?
	JRST	CLKTI1
	HRRM	T1,INTDLY
	HRRM	T1,INTDLY+1
CLKTI1:	ADD	T1,INSRUN	;MAKES TIME FOR NEXT TICK
	MOVEM	T1,CLKDDB+DV.TIM+1	;TIME FOR NEXT TICK
	MOVEI	T1,200		;DONE FLAG
	IORM	T1,CLKSTS
	SETOM	CLKFLG		;CAN INTERRUPT AGAIN
	TXNN FLG,F.EXEC
	JRST CLKWR3
	MOVEI	T1,^D20		;NUMBER OF MILLASECONDS TILL NEXT TICK
	MOVEM	T1,CLKTCK
CLKWR3:	LDB	T1,P.PLVL	;GET PROCESSOR LEVEL
	CAML	T1,CLKDDB+DV.LVL	;CAN WE INTERRUPT ?
	RET			;NOT NOW
;HERE TO SEE IF CLOCK WANTS TO INTERRUPT

CLKINT:	SKIPN	CLKFLG		;CAN WE INTERRUPT ?
	RET			;NO
	HRRZ	T1,CLKSTS	;GET THE STATUS REGISTER
	TRNE	T1,100		;IS ENABLE SET ?
	TRNN	T1,200		;IS FLAG SET ?
	RET			;DON'T WANT TO INTERRUPT NOW
	SETZM	CLKFLG		;HAVE TAKEN OUR INTERRUPT NOW
	INTSAV	100		;TAKE AN INTERRUPT
	TXO	FLG,F.FLOP	;FLAG WE TOOK AN INTERRUPT
	RET
	SUBTTL	IO SIMULATION - KG11

	REPEAT	0,<
;HERE FOR REFERENCES TO KG11

	DDBGEN	KG.,3

KG.STS:	000117,,0
	000777,,0
KG.BCC:	000000,,0	;BCC REGISTER - READ ONLY FOR PDP11
	177777,,0	; BUT OPERATOR CAN WRITE IT
KG.DAT:	177777,,0	;DATA REGISTER - WRITE ONLY
	177777,,0

KG.RST:
KG.LOD:
KG.BLD:

;HERE FOR WRITES TO KG11
KG.WRT:	CALL	DEVWRT		;WRITE THE REGISTER
	RET

KG.BWR:
KG.TIM:
>
	SUBTTL	IO SIMULATION - UBX

;HERE FOR REFERENCES TO UNIBUS ADAPTER

	DDBGEN	UBX,41

	DEFINE	X (Q) <
	XLIST
	TXNE	FLG,F..SIM	;ARE WE SIMULATING ?
	JRST	Q		;LOSE
	TXNN	FLG,F.EXEC	;ARE WE IN EXEC MODE ?
	JRST	Q		;LOSE
	HLL	MA,UBACTL	;ADD UNIBUS NUMBER
	LIST
>;DEFINE X

;HERE TO DO A LOAD FROM A UBX REGISTER
UBXLOD:	X	NXMRET
	RDIO	T1,600000(MA)	;GET DATA FROM UNIBUS
	RET			;WILL SKIP IF FAILED
	JRST	NXMRET

;HERE TO DO A BYTE LOAD FROM A UBX REGISTER
UBXBLD:	X	NXMRET
	RDIOB	T1,600000(MA)	;GET BYTE FROM UNIBUS
	RET			;WILL SKIP IF FAILED
	JRST	NXMRET

;HERE TO DO A WRITE TO A UBX REGISTER
UBXWRT:	X	STONXM
	WRIO	T1,600000(MA)	;GIVE DATA TO UNIBUS
	RET
	JRST	STONXM

;HERE TO DO A BYTE WRITE TO THE UBX REGISTER
UBXBWR:	X	STONXM
	WRIOB	T1,600000(MA)	;GIVE DATA TO UNIBUS
	RET
	JRST	STONXM
;POINTER TO FIRST DDB
; RH LINK IS FOR USE WHILE RUNNING - DEVICES MAY BE REMOVED BY REMOVING LINKS
; LH LINK IS SO DELETED DEVICES CAN BE REINSTALLED
FIRDDB:	DDBLNK,,DDBLNK		;POINTER TO FIRST DDB

;BYTE POINTERS TO THE SIMULATED MEMORY
SIMPTR:	MEMREL	MEMORY
	POINT	8,0(MA),17
		MEMREL	MEMORY
	POINT	8,0(MA),9
		MEMREL	MEMORY
	POINT	8,0(MA),35
		MEMREL	MEMORY
	POINT	8,0(MA),27

;TABLE OF INSTRUCTIONS WHICH MUST BE RELOCATED
RLMTAB:	BLOCK	RLMSIZ
;HERE TO RELOCATE MEMORY REFERENCES

SIMREL:	MOVE	T3,[-RLMSIZ,,RLMTAB]
	SKIPN	T1,MEMORY	;GET ADDRESS OF SIMULATED MEMORY
	HALT
SIMRL2:	MOVE	T2,(T3)
	HLRZ	T1,T2		;GET WHAT TO RELOCATE WITH
	MOVE	T1,(T1)
	HRRM	T1,(T2)
	AOBJN	T3,SIMRL2

;RECONSTRUCT VIRGIN DEVICE CHAIN
	MOVEI	T1,FIRDDB-DV.LNK
	HLRS	T1,DV.LNK(T1)
	JUMPN	T1,.-1

;TO SPEED UP USER MODE RUNS REMOVE DDB FOR UNIBUS ADAPTER
	TXNE	FLG,F.EXEC	;RUNNING IN EXEC MODE ?
	RET			;NO, SKIP THIS
	PUSH	P,IR		;SAVE REGISTER
	MOVEI	IR,FIRDDB-DV.LNK
SIMRL4:	HRRZ	T1,DV.LNK(IR)	;POINT TO NEXT DEVICE
	CAIN	T1,UBXDDB
	HRRZ	T1,DV.LNK(T1)	;SKIP POINTER TO UBA
	HRRM	T1,DV.LNK(IR)
	SKIPE	IR,T1
	JRST	SIMRL4
	POP	P,IR
SIMRL5:	RET
;HERE TO SETUP EPT AND UNIBUS MAPPING

MAPCOR:	TXNN	FLG,F.EXEC	;RUNNING IN EXEC MODE ?
	RET			;NO SO DON'T DIDDLE ADAPTER MAPPING
	SKIPE	T4,EPTBLK	;HAVE WE CHOSEN A SLOT FOR AN EPT YET ?
	JRST	MAPCR3		;ALREADY HAVE AN EPT

;MOVE SYMBOL TABLE AND PDP11 MEMORY UP TO ALLOW FOR EPT
	CALL	POSYMT		;BE SURE SYMBOL TABLE IS AT END OF CORE
	SKIPN	T1,MEMUSE	;FIRST TABLE TO MOVE UP
	HRRZ	T1,SYMBEG	;IF NO MEMORY THAN JUST MOVING SYMBOL TABLE
	HRRZM	T1,T2		;SAVE FIRST ADR IN OLD TABLES
	ADDI	T1,777		;WE WILL ROUND TO NEXT PAGE
	ANDI	T1,777000	;MAKE PAGE ADR
	MOVEM	T1,EPTBLK	;SAVE ADR OF EPT
	ADDI	T1,EBLKSZ	;TO GET TO FIRST TABLE
	SUB	T1,T2		;HOW MUCH TO MOVE TABLE
	MOVE	T3,SYMEND	;LAST ADR IN SYMBOL TABLE
	ADDI	T3,-1(T1)	;NEW LAST ADR IN SYMBOL TABLE
	CALL	MOVMUS		;MOVE THE TABLES
MAPCR1:	MOVE	T4,EPTBLK	;GET EPT ADR AGAIN
	HRLI	T1,INTBLK	;COPY UUO AND INTERRUPT VECTORS
	HRRI	T1,EPTINT(T4)
	BLT	T1,EPTINT+15(T4)
	MOVEI	T1,VECTAB(T4)	;ADR OF VECTOR TABLE FOR UBA
	MOVEI	T2,EPTVEC(T4)	;WHERE VECTORS GO
	HRLI	T2,-10		;POSSIBLE NUMBER OF UBA'S
	MOVEM	T1,(T2)
	AOBJN	T2,.-1
	MOVSI	T1,(NOP)
	MOVEM	T1,EPTAOV(T4)	;IN CASE OF ARITHMITIC OVERFLOW
	MOVE	T1,[JSR EPDLOV]	;TELL USER ABOUT PROBLEM
	MOVEM	T1,EPTPDO	;IN CASE OF PUSHDOWN LIST OVERFLOW
	LDB	T1,[POINT 9,T4,26]	;PICK UP PAGE NUMBER OF EPT
	ADD	T1,[124000,,2]	;IMMEDIATE; KERNEL; WRITABLE; CACHE
				; ,, SECT 0 PAGE TABLE
	MOVEM	T1,EPTSTP(T4)	;POINTER TO SECTION 0 PAGE TABLE
	MOVEI	T1,UUO0		;WHERE TO GO ON A MUUO
	MOVEM	T1,1430(T4)
	HRLI	T1,1430(T4)
	HRRI	T1,1431(T4)
	BLT	T1,1437(T4)
	MOVEI	T1,PGFAIL	;WHERE TO GO ON A PAGE FAIL
	MOVEM	T1,UPTPFN(T4)
	MOVSI	T1,400000	;CST ENTRY
	MOVEM	T1,CST...(T4)	;FIRST ENTRY IN THE TABLE
	HRLI	T1,CST...(T4)	;BEGINING OF CST TABLE
	HRRI	T1,CST...+1(T4)
	BLT	T1,CST...+777(T4)	;FILL TABLE
;FILL UP VECTOR TABLE AND SPACE
	MOVEI	T3,VECTAB(T4)
MAPCR2:	MOVE	T1,T3
	SUBI	T1,VECTAB(T4)
	IMULI	T1,5
	ADDI	T1,VECTAB+400(T4)
	HRLI	T1,(JSR)
	MOVEM	T1,(T3)		;JSR VEC#
	SETZM	(T1)		;VEC#: 0
	HRLI	T1,(PUSH P,)
	MOVEM	T1,1(T1)	;PUSH P,VEC#
	MOVE	T2,[PUSH P,T1]
	MOVEM	T2,2(T1)	;PUSH P,T1
	MOVE	T2,T3
	SUBI	T2,VECTAB(T4)
	LSH	T2,2
	HRLI	T2,(MOVEI T1,)
	MOVEM	T2,3(T1)	;MOVEI T1,#
	MOVE	T2,[JRST VECXX]
	MOVEM	T2,4(T1)	;JRST VECXX
	CAIE	T3,VECTAB+377(T4)
	AOJA	T3,MAPCR2

;SETUP THE PAGE MAP FOR LOW CORE
MAPCR3:	MOVSI	T1,124000	;FIRST ENTRY FOR SECTION 0 PAGE TABLE
	MOVEI	T3,STB...(T4)	;ADR OF SECTION 0 PAGE TABLE
	HRLI	T3,-400		;ONLY FILL IN FIRST 256 PAGES
MAPCR4:	HRRZ	T2,T1
	LSH	T2,^D9
	CAML	T2,MEMORY	;CACHE ONLY UP TO PDP11 MEMORY
	TLZ	T1,004000	;UNCACHE PDP11 MEMORY
	MOVEM	T1,(T3)
	AOS	T1
	AOBJN	T3,MAPCR4
	MOVSI	T1,4000		;MASK FOR CACHE BIT
	ANDCAM	T1,STB...(T4)	;UNCACHE FIRST PAGE (8080 WORDS)
;SETUP THE UNIBUS MAPPING REGISTERS
	SETZM	T2
	MOVE	T1,MEMORY	;GET STARTING ADDRESS OF MEMORY
	LSH	T1,-^D9		;CONVERT TO PAGE NUMBER
	TXO	T1,UB.VLD!UB.16B!UB.RPW	;SET READ/PAUSE WRITE, 16BIT, & VALID
MAPCR5:	HLL	T2,UBACTL	;POINT TO RIGHT UNIBUS
	WRIO	T1,UBAMAP(T2)	;WRITE MAPPING REGISTER
	TLZA	T2,-1		;CLEAR UNIBUS NUMBER
	HALT	.+1		;IF GET PAGE FAIL
	AOS	T2
	LSH	T2,^D11
	CAML	T2,MEMLIM	;STILL IN RANGE ?
	TXZ	T1,UB.VLD	;CLEAR VALID BIT
	LSH	T2,-^D11
	CAIE	T2,^D64
	AOJA	T1,MAPCR5
	SETO	T1,
	WRCSTM	T1		;WRITE CST MASK REGISTER
	SETZ	T1,
	WRPUR	T1		;WRITE PROCESS USE REGISTER
	MOVEI	T1,CST...(T4)	;ADR OF CST
	WRCSB	T1		;WRITE CORE STATUS TABLE BASE REGISTER
	MOVE	T1,EPTBLK	;GET ADR OF EXECUTIVE PROCESS TABLE
	LSH	T1,-^D9
	IORI	T1,1B21!1B22	;TOPS-20 PAGING, ENABLE TRAP AND PAGING
	WREBR	(T1)		;SET UP EBR FOR EPT
	TRZ	T1,1B22
	ADD	T1,[1B0!1B2!1]	;LOAD AC BLOCK AND UBR
	WRUBR	T1		;SETUP UBR FOR UPT
	RET
	SUBTTL	MONITOR FOR EXEC MODE USE

INTBLK:	JSR	CH1
	HALT	42
	JSR	CH2
	HALT	44
	JSR	CH3
	HALT	46
	JSR	CH4
	HALT	50
	JSR	CH5
	HALT	52
	JSR	CH6
	HALT	54
	JSR	CH7
	HALT	56

CH1:	Z
	HALT	.+1
	JEN	@CH1

CH2:	Z
	PUSH	P,T1		;SAVE REGISTER
	PUSH	P,T2		;SAVE ANOTHER REGISTER
	RDAPR	T1		;GET PROCESSOR STATUS
	TRNE	T1,7B28		;SERIOUS PROBLEM ?
	CALL	[CALL	SAVE24		;SAVE REGISTER
		PUSH	P,T1
		CALL INLMES
		ASCIZ	\
	APR	error \
		POP	P,T1
		CALL	OCTYPE
		WRAPR	1B22!7B28!APRLVL	;CLEAR ERROR FLAG
		HALT	R ]
	TRNN	T1,1B30		;DID CLOCK GO OFF ?
	JRST	CH2CK5
	AOS	UPTIME		;WE HAVE BEEN UP FOR ANOTHER MILLASECOND
	WRAPR	1B22!1B30!APRLVL	;CLEAR THE CLOCK FLAG
	SOSG	CLKTCK		;TIME FOR KW11 TO TICK ?
	JRST	[MOVEI	T2,^D20		;NUMBER OF MILASECONDS TILL NEXT TICK
		MOVEM	T2,CLKTCK
		TXNN	FLG,F.RUNF	;ARE WE SIMULATING
		JRST	CH2CK5		;NO
		MOVEM	T2,CLKDDB+DV.TIM+1	;KW11 WANTS TIMER SERVICE NOW
		HRROS	INTDLY		;CHECK KW11 SOON
		JRST	CH2CK5]
CH2CK5:	TRNE	T1,1B31		;DID THE 8080 INTERRUPT
	JRST	[MOVE	T2,FEWINP	;GET DATA
		WRAPR	1B22!1B31!APRLVL	;CLEAR FLAG
		JUMPE	T1,CH2CK9	;IF NOTHING WE'RE DONE
		SETZM	FEWINP		;FLAG WE SAW IT
		HRRZ	T1,T2		;COPY DATA
		LSH	T1,-^D8		;LEAVE ONLY THE CODE
		CAIE	T1,1		;IS THIS A CTY CHAR ?
		JRST	CH2CK9		;NO
		CAIN	T2,17		;IS THIS A CONTROL O ?
		JRST	[SETCMM	CNTLOF		;COMPLEMENT CONTROL O FLAG
			JRST	CH2CK9]
		MOVE	T1,RCVPTR	;GET RECEIVE CHAR PUTTER
		IDPB	T2,T1		;PUT CHAR IN BUFFER
		CAMN	T1,[POINT 8,RCVBUF+7,31]
		MOVE	T1,[POINT 8,RCVBUF]	;WRAP BUFFER AROUND
		MOVEM	T1,RCVPTR
		JRST	CH2CK9 ]
CH2CK9:	POP	P,T2		;RESTORE REGISTER
	POP	P,T1		;RESTORE REGISTER
	JEN	@CH2

UPTIME:	Z			;COUNTED ONCE PER MILLASECOND

CH3:	Z
	HALT	.+1
	JEN	@CH3

CH4:	Z
	HALT	.+1
	JEN	@CH4

CH5:	Z
	HALT	.+1
	JEN	@CH5

CH6:	Z
	HALT	.+1
	JEN	@CH6

CH7:	Z
	HALT	.+1
	JEN	@CH7
;HERE AFTER AFTER TAKING A VECTORED INTERRUPT
; INTERRUPTED PC IS PUSHED ON STACK FOLLOWED BY T1
VECXX:	HRROS	INTDLY
	PUSH	P,T2		;SAVE ANOTHER REG
	RDPI	T2		;GET PI STATUS
	TRNE	T2,BR7INT	;WAS THIS A BR7(BR6) INTERRUPT ?
	JRST	VECX7
	TRNN	T2,BR5INT	;WAS THIS A BR5(BR4) INTERRUPT
	HALT	.+1
	MOVEM	T1,BR5PND#	;SAVE VECTOR FOR PENDING INTERRUPT
	MOVEI	T1,1B28
	HLLZ	T2,UBACTL	;GET UNIBUS NUMBER
	WRIO	T1,UBA.SR(T2)
	POP	P,T2
	POP	P,T1
	POP	P,BR5TRP#
	JEN	@BR5TRP#	;DISMISS THE INTERRUPT

VECX7:	MOVEM	T1,BR7PND#	;SAVE VECTOR FOR PENDING INTERRUPT
	MOVEI	T1,1B28
	HLLZ	T2,UBACTL	;GET UNIBUS NUMBER
	WRIO	T1,UBA.SR(T2)
	POP	P,T2
	POP	P,T1
	POP	P,BR7TRP#	;GET WHERE WE INTERRUPTED FROM
	JEN	@BR7TRP#


;HERE IN CASE OF PUSHDOWN LIST OVERFLOW

EPDLOV:	HALT	.
;HERE ON A PAGE FAIL

PGFAIL:	MOVEM	T4,PGFSAV#	;SAVE A REG
	MOVE	T4,EPTBLK	;POINT TO PAGE TABLES
	PUSH	P,UPTPFO(T4)	;SAVE ADR WE CAME FROM
	AOS	(P)		;ADVANCE OVER FAILING INSTRUCTION
	MOVE	T4,PGFSAV#	;RESTORE REG
	CALL	SAVE4		;SAVE T1-T4
	MOVE	T4,EPTBLK	;POINT TO PAGE TABLES
	LDB	T1,[POINT 6,UPTPFW(T4),5]	;GET PAGE FAIL CODE
	CAIN	T1,20		;IS THIS AN IO FAILURE ?
	JRST	RSKP		;RETURN MAKING FAILING INSTRUCTION SKIP
	CALL INLMES
	ASCIZ	\
	Page Fail @pc = \
	MOVE	T4,EPTBLK	;POINT TO PAGE TABLES AGAIN
	MOVE	T1,UPTPFO(T4)	;GET FAILING PC
	CALL	OCTYPE		;DISPLAY THE PC
	CALL INLMES
	ASCIZ	\ ... Page fail word \
	MOVE	T4,EPTBLK	;CUZ INLMES WIPES T4
	MOVE	T1,UPTPFW(T4)
	CALL	OCTYPE
	HALT	.+1
	RET
;HERE ON A UUO
UUO0:	MOVEM	16,UUOACS+16
	MOVEI	16,UUOACS
	BLT	16,UUOACS+15
	MOVE	AC1,EPTBLK	;ADDRESS OF EXECUTIVE PROCESS TABLE
	PUSH	P,.UPMUP(AC1)	;SAVE RETURN ADR ON STACK
	MOVE	AC2,.UPMUO+2(AC1)	;GET UUO EFFECTIVE ADR
	LDB	AC3,[POINT 4,.UPMUO(AC1),30]	;GET REG ARGUMENT
	LDB	T1,[POINT 9,.UPMUO(AC1),26]	;GET OP CODE
	CAIL	T1,40
	CAIL	T1,100
	CALL ILLUUO
	ROT	T1,-1
	TLNE	T1,400000
	SKIPA	T1,UUODSP-20(T1)
	HLRZ	T1,UUODSP-20(T1)
	CALL (T1)
UUORET:	CAIA
	AOS	(P)
	MOVSI	16,UUOACS
	BLT	16,16		;RESTORE ACS
	RET

UUOACS:	BLOCK	^D16		;COPY AC'S HERE WHILE DOING A UUO

UUODSP:	ILLUUO,,UUINIT	;CALL(40),,INIT(41)
	ILLUUO,,ILLUUO	;(42),,(43)
	ILLUUO,,ILLUUO	;(44),,(45)
	ILLUUO,,UCALLI	;(46),,CALLI(47)
	UUOPEN,,UTTCAL	;OPEN(50),,TTCALL(51)
	ILLUUO,,ILLUUO	;(52),,(53)
	ILLUUO,,ILLUUO	;(54),,RENAME(55)
	ILLUUO,,ILLUUO	;IN(56),,OUT(57)
	USTSTS,,ILLUUO	;SETSTS(60),,STATO(61)
	ILLUUO,,ILLUUO	;STATUS(62),,GETSTS(63)
	ILLUUO,,ILLUUO	;STATZ(64),,INBUF(65)
	ILLUUO,,ILLUUO	;INPUT(66),,OUTPUT(67)
	UCLOSE,,URLEAS	;CLOSE(70),,RELEAS(71)
	ILLUUO,,ILLUUO	;MTAPE(72),,UGETF(73)
	ILLUUO,,ILLUUO	;USETI(74),,USETO(75)
	ILLUUO,,ILLUUO	;LOOKUP(76),,ENTER(77)

ILLUUO:	CALL	INLMES
	ASCIZ	\
Illegal UUO \
	PUSH	P,.UPMUP(AC1)	;SAVE PC
	HRLZ	T1,.UPMUO(AC1)	;GET THE UUO
	HRR	T1,.UPMUO+2(AC1)	;PICKUP EFFECTIVE ADR
	CALL	OCTYPE		;DISPLAY OCTAL CODE
	CALL	INLMES
	ASCIZ	\ @PC=\
	POP	P,T1		;GET PC
	ANDI	T1,-1		;STRIP OFF THE FLAGS
	SOS	T1		;BACK UP TO UUO
	CALL	OCTYPE
	HALT	.+1
	POP	P,T1		;CLEAN OFF THE STACK
	JRST	UUORET		;THEN EXIT UUO
;HERE FOR A CALLI UUO
UCALLI:	MOVE	T1,UUOACS(AC3)	;GET ARGUMENT FROM REGISTER
	HRRZ	T2,AC2		;GET CALLI INDEX
	CAIL	T2,126
	JRST	ILLUUO
	ROT	T2,-1
	TLNE	T2,400000
	SKIPA	T2,CALDSP(T2)
	HLRZ	T2,CALDSP(T2)
	JRST	(T2)

CALDSP:	CALLI0,,ILLUUO	;RESET(0),,(1)
	ILLUUO,,ILLUUO	;SETDDT(2),,(3)
	ILLUUO,,ILLUUO	;DEVCHR(4),,(5)
	ILLUUO,,ILLUUO	;GETCHR(6),,(7)
	ILLUUO,,UCORE	;WAIT(10),,CORE(11)
	ILLUUO,,ILLUUO	;EXIT(12),,(13)
	ILLUUO,,ILLUUO	;DATE(14),,LOGIN(15)
	ILLUUO,,ILLUUO	;APRENB(16),,LOGOUT(17)
	ILLUUO,,ILLUUO	;SWITCH(20),,REASSIGN(21)
	ILLUUO,,ILLUUO	;TIMER(22),,MSTIME(23)
	ILLUUO,,ILLUUO	;GETPPN(24),,TRPSET(25)
	ILLUUO,,URUNTM	;(26),,RUNTIM(27)
	ILLUUO,,USLEEP	;PJOB(30),,SLEEP(31)
	ILLUUO,,ILLUUO	;(32),,PEEK(33)
	ILLUUO,,ILLUUO	;GETLIN(34),,RUN(35)
	ILLUUO,,ILLUUO	;SETUWP(36),,REMAP(37)
	ILLUUO,,UGTTAB	;GETSEG(40),,GETTAB(41)
	ILLUUO,,ILLUUO	;SPY(42),,SETNAM(43)
	ILLUUO,,ILLUUO	;TMPCOR(44),,DSKCHR(45)
	ILLUUO,,ILLUUO	;SYSSTR(46),,JOBSTR(47)
	ILLUUO,,ILLUUO	;STRUUO(50),,SYSPHY(51)
	ILLUUO,,ILLUUO	;(52),,DEVTYP(53)
	ILLUUO,,ILLUUO	;DEVSTS(54),,DEVPPN(55)
	ILLUUO,,ILLUUO	;SEEK(56),,RTTRP(57)
	RSKP,,ILLUUO	;LOCK(60),,JOBSTS(61)
	ILLUUO,,ILLUUO	;LOCATE(62),,WHERE(63)
	ILLUUO,,ILLUUO	;DEVNAM(64),,CTLJOB(65)
	ILLUUO,,ILLUUO	;GOBSTR(66),,(67)
	ILLUUO,,ILLUUO	;(70),,HPQ(71)
	ILLUUO,,ILLUUO	;HIBER(72),,WAKE(73)
	ILLUUO,,ILLUUO	;CHGPPN(74),,SETUUO(75)
	ILLUUO,,ILLUUO	;(76),,OTHUSR(77)
	ILLUUO,,ILLUUO	;CHKACC(100),,DEVSIZ(101)
	ILLUUO,,ILLUUO	;DAEMON(102),,JOBPEK(103)
	ILLUUO,,ILLUUO	;ATTACH(104),,DAEFIN(105)
	ILLUUO,,ILLUUO	;FRCUUO(106),,DEVLNM(107)
	ILLUUO,,ILLUUO	;PATH(110),,METER.(111)
	ILLUUO,,ILLUUO	;MTCHR.(112),,JBSET.(113)
	ILLUUO,,ILLUUO	;POKE.(114),,TRMNO.(115)
	ILLUUO,,ILLUUO	;TRMOP.(116),,RESDV.(117)
	RSKP,,ILLUUO	;UNLOK.(120),,DISK(121)
	ILLUUO,,ILLUUO	;DVRST.(122),,DVURS.(123)
	ILLUUO,,ILLUUO	;(124),,CAL11.(125)
;RESET
CALLI0:	WRAPR	1B19!1B22!37B30	;IO RESET
	CALL	R.SET		;DO A UNIBUS RESET
	WRPI	12377	;RESET PI SYSTEM & TURN IT ON
	MOVEI	T1,^D4096
	WRINT	T1		;SET INTERVAL FOR TIMER
	SETZM	FEWSTS		;CLEAR FRONT END STATUS WORD
	SETZM	FEWINP		;CLEAR INPUT WORD
	SETZM	FEWOUT		;CLEAR OUTPUT WORD
	MOVE	T1,[POINT 8,RCVBUF]
	MOVEM	T1,RCVPTR	;INITIALIZE RECEIVE CHAR PUTTER
	MOVEM	T1,RCVTKR	;INITIALIZE RECEIVE CHAR TAKER
	SETZM	CNTLOF		;CLEAR CONTROL O FLAG
	WRAPR	1B20!73B31!APRLVL	;ENABLE INTERRUPTS
	MOVSI	T1,400000
	LSH	T1,-1
	JUMPG	T1,R
	TYPE	<LSH extends sign>
	HALT	CALLI0

;CORE - CALLI 11
UCORE:	IORI	T1,777
	HRRM	T1,.JBREL	;SET NEW JOBREL
	MOVEI	T1,140
	MOVEM	T1,UUOACS(AC3)	;RESULT
	RETSKP FAST

;HERE FOR A RUNTIM UUO
URUNTM:	MOVE	T1,UPTIME	;GET UPTIME (WE USE ALL THE TIME)
	MOVEM	T1,UUOACS(AC3)	;RESULT
	RET

;SLEEP - CALLI 31
USLEEP:	RET

;GETTAB - CALLI 41
UGTTAB:	RET
;HERE FOR A TTCALL UUO
UTTCAL:	CAIG	AC2,16
	ADDI	AC2,UUOACS	;POINT TO RIGHT ARGUMENT
	ROT	AC3,-1
	TLNE	AC3,400000
	SKIPA	T2,TTCDSP(AC3)
	HLRZ	T2,TTCDSP(AC3)
	JRST	(T2)
TTCDSP:	TTCLL0,,TTCLL1	;INCHRW(0),,OUTCHR(1)
	TTCLL2,,TTCLL3	;INCHRS(2),,OUTSTR(3)
	TTCLL4,,TTCLL5	;INCHWL(4),,INCHSL(5)
	TTCLL6,,TTCLL7	;GETLCH(6),,SETLCH(7)
	TTCL10,,TTCL11	;RESCAN(10),,CLRBFI(11)
	TTCL12,,TTCL13	;CLRBFO(12),,SKPINC(13)
	TTCL14,,TTCL15	;SKPINL(14),,IONEOU(15)
	ILLUUO,,ILLUUO	;(16),,(17)

;INCHRW
TTCLL0:	CALL	CHKCHR		;SEE IF THERE IS A CHARACTER READY
	JRST	TTCLL0		;TRY AGAIN
	MOVEM	T1,(AC2)	;GIVE USER THE DATA
	RET

;OUTCHR
TTCLL1:	MOVE	T1,(AC2)	;GET THE CHARACTER TO WRITE
	JRST	SCNTYP		;TYPE THE CHARACTER

;INCHRS
TTCLL2:	CALL	CHKCHR		;TRY TO GET A CHARACTER
	RET			;TRY LATER
	MOVEM	T1,(AC2)	;GIVE THE USER THE CHARACTER
	RETSKP FAST

;OUTSTR
TTCLL3:	HRLI	AC2,(POINT 7,0)
TTCL31:	ILDB	T1,AC2
	JUMPE	T1,R		;IF NULL WE ARE DONE
	CALL	SCNTYP		;TYPE THE CHARACTER
	JRST	TTCL31

;INCHWL
TTCLL4:	JRST	TTCLL0

;INCHSL
TTCLL5:	JRST	TTCLL2

;GETLCH
TTCLL6:	SETZM	(AC2)
	RET

;SETLCH
TTCLL7:	RET

;RESCAN
TTCL10:	RET

;CLRBFI
TTCL11:	RET

;CLRBFO
TTCL12:	RET

;SKPINC
TTCL13:	CALL	CHKCHR		;IS ANYTHING READY ?
	RET			;NO
	MOVEM	T1,(AC2)	;GIVER USER CHARACTER
	RETSKP FAST

;SKPINL
TTCL14:	JRST	TTCL13

;IONEOU
TTCL15:	MOVE	T1,(AC2)
	JRST	SCNTYP
;HERE TO TYPE AN INLINE MESSAGE
INLMES:	HRLI	T1,(POINT 7,0)
	HLLM	T1,(P)		;MAKE A BYTE POINTER
INLMS3:	ILDB	T1,(P)
	JUMPE	T1,RSKP		;SKIP NULL CHAR AND DONE
	CALL SCNTYP
	JRST	INLMS3		;FINISH REST OF MESSAGE
;HERE TO TYPE A CHARACTER
SCNTYP:	SKIPE	CNTLOF		;DID USER FLUSH OUTPUT ?
	RET
	ANDI	T1,177		;STRIP PARITY BIT
	CAIN	T1,15		;WAS THAT A CARRIAGE RETURN ?
	SETZM	COLUMN		;BACK TO LH MARGIN
	AOS	T2,COLUMN	;ADVANCE COLUMN POINTER
	CAIE	T1,177		;RUBOUTS DON'T PRINT
	CAIGE	T1,40		;IS THIS A PRINTING CHARACTER ?
	SOS	T2,COLUMN	;NOT PRINTING SO BACKUP SOLUMN COUNTER
	CAIN	T1,11		;WAS THAT A HT ?
	JRST	[ADDI	T2,^D8
		ANDI	T2,-10
		MOVEM	T2,COLUMN
		JRST	.+1 ]
	CAMLE	T2,WIDTH	;IS THAT IN RANGE ?
	JRST	[PUSH	P,T1		;SAVE CHAR TO TYPE
		CALL	INLMES
		BYTE	(7)15,12,0
		POP	P,T1
		JRST	SCNTYP ]
	CAIGE	T1,40		;SHOULD WE PAD THIS CHARACTER ?
	JRST	[CALL .+1		;PRINT THE CHARACTER THEN RETURN HERE
		MOVEI	T1,377		;PAD CHAR
		JRST	.+1 ]
	SKIPE	FEWOUT		;CAN WE TYPE NEXT CHAR ?
	JRST	.-1		;WAIT UNTIL WE CAN
	ANDI	T1,377		;STRIP EXTRA BITS
	IORI	T1,1B27		;FLAG THIS IS A CTY CHAR
	MOVEM	T1,FEWOUT	;PUT IT FOR 8080 TO FIND
	WRAPR	1B23!1B25!APRLVL	;INTERRUPT THE 8080
	RET
CNTLOF:	Z			;CONTROL O FLAG
RCVTKR:	Z			;TAKER FOR RECEIVE CHARACTERS
RCVPTR:	Z			;PUTTER FOR RECEIVE CHARACTERS
RCVBUF:	BLOCK	10		;BUFFER FOR RECEIVE CHARACTERS

COLUMN:	Z			;COLUMN WE ARE ON
WIDTH:	^D80		;MAXIMUM NUMBER OF COLUMNS FOR OUTPUT
;HERE TO TRY TO GET A CHARACTER FROM THE CTY
CHKCHR:	SETZM	CNTLOF		;CLEAR CONTROL O FLAG
	SETZ	T1,
	EXCH	T1,SAVCHR#	;GET SAVED CHAR
	JUMPN	T1,CKCHR5
	MOVE	T2,RCVTKR	;GET RECEIVE CHAR TAKER
	CAMN	T2,RCVPTR	;ANY CHARACTERS
	RET
	ILDB	T1,T2		;GET NEXT CHARACTER
	CAMN	T2,[POINT 8,RCVBUF+7,31]	;WAS THAT LAST IN BUFFER ?
	MOVE	T2,[POINT 8,RCVBUF]	;TIME TO WRAP BUFFER AROUND
	MOVEM	T2,RCVTKR
CKCHR5:	ANDI	T1,377		;STRIP EXTRA BITS
	MOVE	T2,T1		;COPY CHAR
	ANDI	T2,177		;STRIP PARITY BIT
	TXNN	FLG,F.RUNF	;RUNNING SIMULATION ?
	CAIE	T2,3		;WAS THAT A CONTROL C ?
	CAIA
	JRST	DDT11		;YES SO BEGIN AGAIN
	PUSH	P,T2		;SAVE CHARACTER FOR RETURN
	CAIN	T2,15		;WAS THAT A CR ?
	JRST	[MOVEI	T2,12		;LF
		MOVEM	T2,SAVCHR#
		JRST	.+1]
	CAIN	T2,33		;WAS THAT AN ALTMODE ?
	MOVEI	T1,"$"		;ECHO AS THIS
	TXNN	FLG,F.RUNF	;IF SIMULATING DON'T ECHO
	CALL	SCNTYP		;ECHO THE CHARACTER
	POP	P,T1		;GET CHAR OFF STACK
	RETSKP FAST
;HERE ON AN INIT UUO
UUINIT:	HRRZ	AC2,-1(P)	;GET RETURN ADDRESS
	SOS	AC2
	MOVEI	T1,2
	ADDM	T1,-1(P)	;SO RETURN WORKS
	;JRST	UUOPEN
;HERE ON AN OPEN UUO
UUOPEN:	CAIG	AC2,16		;WAS ARGUMENT IN REGISTERS ?
	ADDI	AC2,UUOACS	;YES SO RELOCATE
	HRRZ	T1,AC3		;GET REGISTER ARGUMENT = CHNL
	LSH	T1,^D23		;POSITION IN LH
	TLO	T1,20		;FLAG DEVICE OPENED
	HRR	T1,(AC2)	;GET STATUS
	MOVS	T2,1(AC2)	;GET DEVICE NAME TO OPEN
	CAIN	T2,'TTY'
	JRST	OPNTTY
	MOVEM	T1,DSKDDB	;SAVE STATUS
	MOVSM	T2,DSKSTR	;SAVE NAME OF DISK STRUCTURE
	SETZM	RJUNIT		;LOOK AT FIRST UNIT FOR STRUCTURE NAME
	SETZM	RJBLCK		;BLOCK TO READ
DSKOP2:	CALL	RJREAD		;TRY TO READ THE BLOCK
	JRST	[AOS	T1,RJUNIT
		CAIE	T1,^D8		;TOO LARGE ?
		JRST	DSKOP2
		RET	]
	RET

OPNTTY:	MOVEM	T1,TTYDDB	;SAVE DEVICE STATUS
	RETSKP FAST

;DEVICE BLOCKS
TTYDDB:	Z			;CHNL,,DEVICE STATUS SET BY USER
	EXP	DSKDDB

DSKDDB:	Z			;CHNL,,DEVICE STATUS SET BY USER
	Z
DSKSTR:	Z			;STRUCTURE
DSKFIL:	Z			;FILE NAME
DSKEXT:	Z			;FILE EXT
;HERE ON A SETSTS UUO
USTSTS:	CALL	UFNDDB
	RET
	HRRM	T1,0(AC4)
	RET

;HERE ON A CLOSE UUO
UCLOSE:	RET

;HERE ON A RELEASE UUO
URLEAS:	CALL	UFNDDB		;FIND WHICH DDB
	RET
	SETZM	0(AC4)
	RET

UFNDDB:	MOVEI	AC4,TTYDDB
UFNDD0:	SKIPN	T1,0(AC4)	;GET STATUS
	JRST	UFNDD7
	LDB	T1,[POINT 4,0(AC4),12]
	CAMN	T1,AC3
	JRST	RSKP
UFNDD7:	SKIPE	AC4,1(AC4)	;GET NEXT DDB ADR
	JRST	UFNDD0
	RET
;HERE TO HANDLE AN RJPO4

;HERE TO READ A BLOCK FROM AN RJP04
; CALL	SETUP RJUNIT WITH UNIT NUMBER
;	SETUP RJBLCK TO BE BLOCK NUMBER TO READ
;	CALL RJREAD
;	ERROR RETURN
;	WIN RETURN
RJREAD:	HLLZ	MA,UBACTL	;ADD UNIBUS UNIT
	RDIO	T1,UBAMAP+77(MA)	;GET CURRENT MAP FOR PAGE
	PUSH	P,T1		;SAVE STATUS
	HRRZ	T1,EPTBLK	;GET ADR OF EPT
	MOVEI	T1,DSKPAG(T1)	;MAKE ADR OF DISK PAGE
	LSH	T1,-^D9		;MAKE PAGE NUMBER
	TRO	T1,UB.VLD!UB.FST	;STATUS
	WRIO	T1,UBAMAP+77(MA)	;MAP THE DISK PAGE
	MOVEI	T1,000040	;RESET
	WRIO	T1,RPCS2(MA)	;CLEAR OUT THE CONTROLLER
	MOVE	T1,RJUNIT	;UNIT TO READ FROM
	WRIO	T1,RPCS2(MA)	;SELECT UNIT
	MOVEI	T1,21		;PRESELECT
	WRIO	T1,RPCS1(MA)	;SELECT OUR UNIT
	MOVEI	T1,174000	;ADR TO TRANSFER TO
	WRIO	T1,RPBA(MA)	;SET ADDRESS
	MOVEI	T1,-2000	;NUMBER OF PDP11 WORDS TO TRANSFER
	WRIO	T1,RPWC(MA)
	MOVEI	T1,471		;READ DATA AND MEMORY EXTENSION
	WRIO	T1,RPCS1(MA)	;START THE TRANSFER
	CALL	RJRDWT		;WAIT FOR TRANSFER TO COMPLETE
	JRST	RJRD.9
RJRD.9:	POP	P,T2		;GET OLD UBAMAP STATUS
	LDB	T1,[POINT 11,T2,26]	;GET PAGE NUMBER
	LDB	T2,[POINT 4,T2,8]	;GET STATUS BITS
	DPB	T2,[POINT 4,T1,21]	;PUT INTO WORD
	WRIO	T1,UBAMAP+77(MA)	;RESTORE MAP FOR THAT PAGE
	RET
;HERE TO WAIT FOR DISK OPERATION TO COMPLETE
RJRDWT:	MOVE	T4,UPTIME	;HOW LOG WE HAVE BEEN UP
	ADDI	T4,^D1000	;ADD A SECOND
RJRDW4:	CAMG	T4,UPTIME	;HAVE WE WAITED TOO LONG ?
	RET			;MUST BE DEAD
RJRD.5:	RDIO	T1,RPCS1(MA)	;GET DRIVE STATUS
	TRNN	T1,160200	;FLAG COME UP ?
	JRST	RJRDW4		;NOT YET
	TRNN	T1,060000	;ERROR FLAG UP ?
	AOS (P)			;NO, SKIP RETURN
	RET			;YES LOSE


RJUNIT:	Z			;UNIT TO READ
RJBLCK:	Z			;BLOCK TO READ

P.PLVL:	POINT	3,PS,30		;BYTE POINTER TO GET PROCESSOR LEVEL

;FOLLOWING ARE SIMULATOR REGISTERS WHEN NOT SIMULATING
SIMREG:	EXP	0		;R0
	EXP	0		;R1
	EXP	0		;R2
	EXP	0		;R3
	EXP	0		;R4
	EXP	0		;R5
	EXP	0		;R6
	EXP	0		;R7

EPTBLK:	Z		;ADR OF EXEC STORAGE

UBACTL:	1,,0		;UBA CONTROLLER NUMBER

	END