Google
 

Trailing-Edge - PDP-10 Archives - bb-h138e-bm_tops20_v6_1_distr - 6-1-sources/ddtsim.mac
There are 16 other files named ddtsim.mac in the archive. Click here to see a list.
; COPYRIGHT (C) 1984 BY
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	TITLE DDTSIM DDT11 SIMULATOR AND UBA CONTROL

	SEARCH	DDTSYM,JOBDAT,MACTEN,UUOSYM,MONSYM

	SALL			;GET NICE LISTINGS FOR A CHANGE
	.HWFRMT			;AND SKIP THE FANCY BITS

ENTSIM (ENTRY)
ENT11 (EXTERN)
ENTGP (EXTERN)
ENTFIL (EXTERN)

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
	SETZM 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
	POPJ P,

;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
	POPJ P,

;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
	POPJ P,
SIM.U1:
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 IOLDP2	;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)
	POPJ P,

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
>

;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
	POPJ P,
;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
Z=Z+1	>>
ZZ=<VAL+<<-MASK>&177777>>/100-Z
IFG ZZ < REPEAT	ZZ,<EXP	.'NAME
Z=Z+1	>>>>


OPDSP0:
XLIST
	OPDSPA			;0000XX INSTRUCTIONS
	.JMP			;0001XX INSTRUCTIONS
	OPDSPB			;0002XX INSTRUCTIONS
Z=	3
	INSTRU
ZZ=	2000-Z
REPEAT	ZZ,<EXP ILLINS>

;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>>
ZZ=VAL+<<-MASK>&177777>-Z
IFG ZZ <REPEAT ZZ,<EXP	.'NAME	;DISPATCH FOR INSTRUCTION
Z=Z+1>>>>>

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

;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>>>>>

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

LIST

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		>
IFN <FLAG&SMF.SS>,<ANDI	T2,77
IFN <FLAG&SMF.BY>,<JSR @SBFTCH(T2)		>
IFE <FLAG&SMF.BY>,<JSR @SFETCH(T2)		>>
NAME'.	FLAG
IFN <FLAG&SMF.BR> <
	TRNE IR,200
	TROA IR,177400
	TRZ IR,177400
	LSH IR,1
	ADD PC,IR
	ANDI PC,177777	>
IFE ZZRET,<JRST SIM11		>>>>

	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

;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
XLIST>
LIST

;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) <
	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
>

;HERE TO DO A WORD LOAD FROM AN IO REGISTER
IOLDM1:	SKIPA T1,[EXP 1]	;SIMPLE SKIP RETURN FOR GETWRD
IOLOAD:	MOVEI T1,LODRET		;SO RETURN GOES RIGHT
	ADDM T1,(P)
IOLDP2:	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
		POPJ P,	]
	POP P,T1		;CLEAN OFF STACK
	JRST NXM...

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

;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 ?
	POPJ P,
	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) <
	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
	POPJ P,
	JRST IORERR		> ;ERROR !?!

;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
		POPJ P,
		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
		POPJ P,
		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
	HRLZS 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
	POPJ P,


;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
	POPJ P,

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

PS.BWR:	TRNE MA,1		;WRITING LH ?
	POPJ P,
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 ?
	POPJ P,			;ALL DONE
	LDB T2,P.PLVL		;GET CURRENT PS LEVEL
PSCHK3:	HRRZ MA+1,DV.LNK(MA+1)
	JUMPN MA+1,PSCHK1
	POPJ P,

;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
	POPJ P,

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
	POPJ P,

SW.BWR:	TXNE FLG,F..SIM		;ARE WE SIMULATING ?
	POPJ P,			;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]
	POPJ P,

;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
	POPJ P,

;HERE IF USER DOES A BYTE OPERATION TO READ A CTY REGISTER
CTYBLD:	SETZ T1,
	TRNE MA,1
	POPJ P,
				;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
	POPJ P,

;HERE IF USER DOES A BYTE WRITE TO A CTY REGISTER
CTYBWR:	TRNE MA,1		;WRITING LH ?
	POPJ P,			;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) <
CT'Q'WRS:
	TDZ T1,CT'Q'STS+1	;CLEAR BITS WHICH WERE ALREADY SET
	TRNN T1,100		;WAS ENABLE SET ?
	POPJ P,			;WAS ALREADY SET
	SETOM CT'Q'FLG		;CAN INTERRUPT AGAIN
	JRST CTYCHK		;CHECK FOR INTERRUPTS
>

;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
	POPJ P,

;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 ?
	POPJ P,			;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 ?
	POPJ P,
	SKIPN CTOFLG		;WANT TO INTERRUPT ?
	POPJ P,			;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
	POPJ P,

;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

;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	^D5000		;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
	POPJ P,

;HERE TO READ THE CLOCK
CLKLOD:	HRRZ T1,CLKSTS		;GET THE STATUS REGISTER
	POPJ P,			;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
	POPJ P,

;HERE FOR A BYTE WRITE TO THE KW11L
CLKBWR:	TRNE MA,1		;WRITING RH OR LH ?
	POPJ P,			;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 ?
	POPJ P,			;NOT NOW

;HERE TO SEE IF CLOCK WANTS TO INTERRUPT

CLKINT:	SKIPN CLKFLG		;CAN WE INTERRUPT ?
	POPJ P,			;NO
	HRRZ T1,CLKSTS		;GET THE STATUS REGISTER
	TRNE T1,100		;IS ENABLE SET ?
	TRNN T1,200		;IS FLAG SET ?
	POPJ P,			;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
	POPJ P,

	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
	POPJ P,

KG.BWR:
KG.TIM:
>

;HERE FOR REFERENCES TO UNIBUS ADAPTER

	DDBGEN	UBX,41

	DEFINE	X (Q) <
	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
>

;HERE TO DO A LOAD FROM A UBX REGISTER
UBXLOD:	X NXMRET
	RDIO T1,600000(MA)	;GET DATA FROM UNIBUS
	POPJ P,			;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
	POPJ P,			;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
	POPJ P,
	JRST STONXM

;HERE TO DO A BYTE WRITE TO THE UBX REGISTER
UBXBWR:	X STONXM
	WRIOB T1,600000(MA)	;GIVE DATA TO UNIBUS
	POPJ P,
	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 ?
	POPJ P,			;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:	POPJ P,

;HERE TO SETUP EPT AND UNIBUS MAPPING

MAPCOR:	TXNN FLG,F.EXEC		;RUNNING IN EXEC MODE ?
	POPJ P,			;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
	POPJ P,

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 ?
	PUSHJ P,[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 T2,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
		ANDI T2,377
		CAIE T2,217	; ODD PARITY
		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
	POPJ P,

;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
	POPJ P,

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,,RSKP		;(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
	AOS (P)
	POPJ P,

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

;SLEEP - CALLI 31
USLEEP:	POPJ P,

;GETTAB - CALLI 41
UGTTAB:	POPJ P,

;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
	POPJ P,

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

;INCHRS
TTCLL2:	CALL CHKCHR		;TRY TO GET A CHARACTER
	POPJ P,			;TRY LATER
	MOVEM T1,(AC2)		;GIVE THE USER THE CHARACTER
	AOS (P)
	POPJ P,

;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)
	POPJ P,

;SETLCH
TTCLL7:	POPJ P,

;RESCAN
TTCL10:	POPJ P,

;CLRBFI
TTCL11:	POPJ P,

;CLRBFO
TTCL12:	POPJ P,

;SKPINC
TTCL13:	CALL CHKCHR		;IS ANYTHING READY ?
	POPJ P,			;NO
	MOVEM T1,(AC2)		;GIVER USER CHARACTER
	AOS (P)
	POPJ P,

;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 ?
	POPJ P,
	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
	POPJ P,
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
	POPJ P,
	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
	AOS (P)
	POPJ P,

;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

;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
	POPJ P,			; *** FOR NOW, DUE TO SOME BUGS ***
	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
		POPJ P,	]
	POPJ P,

OPNTTY:	MOVEM T1,TTYDDB		;SAVE DEVICE STATUS
	AOS (P)
	POPJ P,

;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
	POPJ P,
	HRRM T1,0(AC4)
	POPJ P,

;HERE ON A CLOSE UUO
UCLOSE:	POPJ P,

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

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
	POPJ P,

;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
	POPJ P,
;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 ?
	POPJ P,			;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
	POPJ P,			;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