Google
 

Trailing-Edge - PDP-10 Archives - BB-AS80B-SM_1985 - sources/io.mic
There are 5 other files named io.mic in the archive. Click here to see a list.
.TOC	"I/O INSTRUCTIONS"

; BITS 10-12 OF INSTRUCTION GET MAPPED TO IR 7-9 FOR I/O INSTRUCTIONS
; THE DEVICE ADDRESS IS BROKEN DOWN AS ONE OF THE FIRST 7, OR ALL OTHERS
	.DCODE

;DEVICE 000 (APR)

700:	W,		J/APRBI	;APRID (BLKI APR,)	OPTIONS, SERIAL #
	W,	DATAI,	J/APRDI	;DATAI APR,		ADDRESS COMPARE
	I,		J/APRBO	;WRFIL (BLKO APR,)	REFILL RAM
	R,	DATAO,	J/APRDO	;DATAO APR,		ADDRESS COMPARE
	I,	CONO,	J/APRCO	;CONO APR,		APR FLAGS
	I,	CONI,	J/APRCI	;CONI APR,
	I,	CONSZ,	J/APRCI	;CONSZ APR,
	I,	CONSO,	J/APRCI	;CONSO APR,

;DEVICE 004 (PI)

710:	W,	M,	J/PIBI	;RDERA (BLKI PI,)	READ ERA
	W,	B/3,	J/PIDI	;DATAI PI,		Stats, or not used
	R,		J/PIBO	;SBDIAG (BLKO PI,)	SBUS DIAGNOSTIC
	R,	B/0,	J/PIDO	;DATAO PI,		More statistics
	I,	CONO,	J/PICO	;CONO PI,		PI SYSTEM CONTROL
	I,	CONI,	J/PICI	;CONI PI,		IN PROGRESS, ENABLE
	I,	CONSZ,	J/PICI
	I,	CONSO,	J/PICI

;DEVICE 010 (PAG)

720:	RW,	BLKI,	J/PAGBI	;BLKI PAG,		UNASSIGNED
	W,	DATAI,	J/PAGDI	;DATAI PAG,		USER CONTEXT
	I,		J/PAGBO	;CLRPT (BLKO PAG,)	INVAL PAGE TABLE
	R,	DATAO,	J/PAGDO	;DATAO PAG,		USER CONTEXT
	I,	CONO,	J/PAGCO	;CONO PAG,		EXEC CONTEXT
	I,	CONI,	J/PAGCI	;CONI PAG,
	I,	CONSZ,	J/PAGCI
	I,	CONSO,	J/PAGCI

;DEVICE 014 (CCA)

730:	I,	J/SWEEP	;BLKI CCA,	8 FUNCTIONS TO SWEEP THE CACHE
	I,	J/SWEEP	;SWPIA (DATAI CCA,)INVALIDATE CACHE, NO CORE UPDATE
	I,	J/SWEEP	;SWPVA (BLKO CCA,)VALIDATE CORE, LEAVE CACHE VALID
	I,	J/SWEEP	;SWPUA (DATAO CCA,)UNLOAD CACHE TO CORE, CLEAR CACHE
	I,	J/SWEEP	;CONO CCA,
	I,	J/SWEEP	;SWPIO (CONI CCA,)INVALIDATE ONE PAGE
	I,	J/SWEEP	;SWPVO (CONSZ CCA,)VALIDATE ONE PAGE
	I,	J/SWEEP	;SWPUO (CONSO CCA,)UNLOAD ONE PAGE
;I/O CONT'D

;DEVICE 020 (TIM)

740:	W,	B/1,	J/RDMTR	;RDPERF (BLKI TIM,)	PERF CNT
	W,	B/0,	J/RDMTR	;RDTIME (DATAI TIM,)	TIME BASE
	R,	DATAO,	J/TIMBO	;WRPAE (BLKO TIM,)	PA ENABLES
	R,	DATAO,	J/TIMDO	;DATAO TIM,		UNDEFINED
	I,	CONO,	J/TIMCO	;CONO TIM,		SETUP INTERVAL TIMER
	I,	CONI,	J/TIMCI	;CONI TIM,		RD INTERVAL & PERIOD
	I,	CONSZ,	J/TIMCI
	I,	CONSO,	J/TIMCI

;DEVICE 024 (MTR)


750:	W,	B/3,	J/RDMTR	;RDMACT (BLKI MTR,)	CACHE CNT
	W,	B/2,	J/RDMTR	;RDEACT (DATAI MTR,)	EBOX CNT
	I,		J/UUO	;BLKO MTR,		UNDEFINED
	I,		J/UUO	;DATAO MTR,		UNDEFINED
	I,	CONO,	J/MTRCO	;WRTIME (CONO MTR,)	ACCT & TB CTL
	I,	CONI,	J/MTRCI	;CONI MTR,		SAME
	I,	CONSZ,	J/MTRCI
	I,	CONSO,	J/MTRCI

;DEVICE 030

760:	RW,	BLKI,	J/BLKIO
	W,	DATAI,	J/IO
	RW,	BLKO,	J/BLKIO
	R,	DATAO,	J/IO
	I,	CONO,	J/CONO
	W,	CONI,	J/IO
	I,	CONSZ,	J/CONS
	I,	CONSO,	J/CONS

;DEVICES 034-774 (ALL OTHERS)

770:	RW,	BLKI,	J/BLKIO
	W,	DATAI,	J/IO
	RW,	BLKO,	J/BLKIO
	R,	DATAO,	J/IO
	I,	CONO,	J/CONO
	W,	CONI,	J/IO
	I,	CONSZ,	J/CONS
	I,	CONSO,	J/CONS

	.UCODE
.TOC	"EXTERNAL DEVICE I/O INSTRUCTIONS"

=0****00*000
BLKIO:	SKP IO LEGAL,CALL,J/IOCHK	;FIRST VERIFY INSTR VALIDITY
	BYTE DISP,J/BLK1		;TEST FPD
CONS:					;HERE FOR CONSO, CONSZ TO LOAD
					; BR IN CASE OF UUO
CONO:	BR/AR,ARL_ARR,ARR_ARR		;CONDITIONS TO BOTH HALVES
=10
IO:	AR_MEM,SKP IO LEGAL,CALL,J/GTEBUS;WAIT FOR MBOX IF BLKI/O
RELEEB:	REL ECL EBUS,B WRITE		;XFER DONE, WHAT TO DO?
=
=1*010
IOTEND:	FIN STORE,MB WAIT,J/BLK4	;BLKI/BLKO
	TEST AR.BR,TEST FETCH,J/NOP	;CONSZ
	MEM_AR,SKP PI CYCLE,J/IOFET	;DATA/CON I/O
	TEST AR.BR,TEST FETCH,J/NOP	;CONSO
;BLKI/BLKO SCREWED AROUND WITH TO TRY TO STOP PI LOSSAGE
BLK4:	TEST BRL,TEST FETCH,SKP PI CYCLE,J/CLRFPD

=1****0
IOFET:	I FETCH,J/NOP			;HERE IF NOT PI CYCLE
	DISMISS,J/PIFET			;DISMISS INTRPT AFTER DATA/CON I/O

=1**010
BLK2:	MEM_AR,BR/AR,ARL_0.C,B DISP,J/BLK3
BLK1:	AR_AR+1,GEN CRY18,STORE,J/BLK2	;UPDATE POINTER WORD
=111	SKP PI CYCLE,J/BLK2		;IF FPD & NOT PI, DON'T INCREMENT
=1*101					;DO DATAI OR DATAO
BLK3:	VMA_AR,LOAD AR,SET FPD,J/IO	;GET DATA TO OUTPUT
	VMA_AR,SET FPD,J/IO		;INPUT DO BEFORE MEM

;;;NOTE NOTE NOTE SET FPD INHIBITED BY HARDWARE IF PI CYCLE (SCD5)
;SUBROUTINES TO HANDLE EBUS
;CALL WITH "SKP IO LEGAL"
;ENTER AFTER LOADING AR IF OUTPUT FUNCTION

=00
GTEBUS:	AR_BR,J/UUO			;HERE IF IO ILLEGAL IN THIS MODE
	REQ EBUS,CALL,J/WGRANT		;ASK PI SYSTEM FOR BUS
=11					;RETURN TO TRANSFER ROUTINE

;SUBROUTINE TO PERFORM EBUS TRANSFER
;SETUP CONTROLLER SELECT AND FUNCTION LINES BEFORE CALL
;IF OUTPUT, ALSO PUT AR ONTO EBUS DATA LINES

EBUSX:	GEN AR,TIME/5T,			;WAIT AFTER ASSERTING FUNCTION
		SET EBUS DEMAND,J/WXFER	; AFTER 300 NS, ASSERT DEMAND
=0
EBUSW:	AR_EBUS,GEN AR,
		CLR EBUS DEMAND,J/RELEB	;STROBE DATA AND DROP DEMAND
WXFER:	GEN AR,SKP -EBUS XFER,J/EBUSW	;WAIT FOR TRANSFER

RELEB:	GEN AR,REL EBUS,TIME/5T,	;DROP DATA, CS, AND FCN
		RETURN3			;AFTER 150 NS, THEN RELEASE BUS


;SUBROUTINE TO WAIT FOR PI SYSTEM TO GRANT EBUS
; IT WILL EITHER SEND EBUS GRANT, OR PI READY

=0
WGRANT:	SKP -EBUS GRANT,J/WGRNT1	;GOT IT?
	DROP EBUS REQ,J/TAKINT
=0
WGRNT1:	IO INIT,GEN AR,J/WGRNT2		;GOT IT, SETUP CS, FCN, AND DATA
	SKP INTRPT,J/WGRANT		;DIDN'T GET IT, TEST FOR INTERUPT
WGRNT2:	GEN AR,TIME/5T,			;JUST WAIT
		EBUS CTL/IO INIT,RETURN3

;HERE TO START PI CYCLE TRANSFER.  HOLD EBUS CTL SELECTION

EBUSI:	TIME/5T,EBUS CTL/DATAI,J/EBUSX
EBUSO:	GEN AR,TIME/5T,EBUS CTL/DATAO,J/EBUSX

;SUBROUTINES TO CHECK IO LEGALITY FOR INTERNAL I/O INSTRUCTIONS

.IF/MODEL.B
3002:
.IFNOT/MODEL.B
2002:					;ACCESSIBLE ON EXTEND [0]
.ENDIF/MODEL.B
IOCHK:	AR_BR,J/UUO			;NAUGHTY, MUST'NT DO
.IF/MODEL.B
3003:
.IFNOT/MODEL.B
2003:
.ENDIF/MODEL.B
RET1:	RETURN1				;ONE-CYCLE NULL ROUTINE

=0
GETEEB:	AR_BR,J/UUO			;IO ILLEGAL IN THIS MODE
GTEEB1:	GET ECL EBUS,RETURN1
.TOC	"INTERNAL DEVICE FUNCTIONS -- APR, CCA"

=0****00***0
SWEEP:	BR/AR,SC_#,#/9.,CALL,
		SKP IO LEGAL,J/IOCHK	;ALLOWED?
	AR_SHIFT			;MOVE PAGE # TO PLACE
=	VMA_AR,SWEEP CACHE		;START A SWEEP
MBREL:	MB WAIT,J/IFNOP			;COMPLETE REG FUNC BEFORE FETCH


=0****00**00
APRDO:	CALL,SKP IO LEGAL,J/GETEEB	;SET ADDR BREAK
	DATAO APR,J/RELEEB
APRBO:	BR/AR,CALL,SKP IO LEGAL,J/IOCHK	;SET CACHE REFILL ALGORITHM
	WR REFILL RAM,J/MBREL		;INFO ALREADY IN VMA
=

=0****00*000
APRDI:	CALL,SKP IO LEGAL,J/GETEEB	;READ ADDR BREAK
	DATAI APR(L),J/RELEEB
=010
.IFNOT/DDT.BUG				;[346] Normal code
APRBI:	CALL,SKP IO LEGAL,J/IOCHK	;RETURN MICRO VERSION, SERIAL #
	AR_SERIAL,TIME/3T,		;READ SERIAL NUMBER
		CALL,J/UVERS		;GET MICRO-CODE VERSION IN AR
=111	ARL_ARR.S,AR_BR			;COMB SERIAL WITH VERSION
=	AR0-8_#,STORE,OPTIONS,		;SET OPTION FLAGS
		J/STMEM
.IF/DDT.BUG				;[346] Gross hack to make EDDT work
APRBI:	AR_SERIAL,TIME/3T		;[346] Get hardware serial number
=
=0	AR_AR SWAP,FE_#,OPTIONS,	;Set to test bit 23
		SKP IO LEGAL,CALL [IOCHK]; Is this a legal instruction here?
	GEN P AND #,#/1,SKP SCAD NZ	;Was bit 23 set?
=0*0
SEROK:	AR_AR SWAP,CALL [UVERS]		;Maybe not. Get microcode version
	P_P AND #,#/76,J/SERFIX		;Yes. Clean it and move it
	ARL_ARR,ARR_BR			;It's fixed. Shuffle version to spot
=	AR0-8_FE,STORE,J/STMEM		;Move in options and store result
;
SERFIX:	FE_FE+#,#/10,J/SEROK		;OR in bit 5 for option
.ENDIF/DDT.BUG				;[346] All this code is GROSS!!

=0****00**00
APRCO:	BR/AR,ARL_ARR.M,ARR_ARR,CALL.M,	;SET APR FLAGS
		SKP IO LEGAL,J/GETEEB
	CONO APR, J/APRCO7		;[272]
APRCI:	BR/AR,CALL,
		SKP IO LEGAL,J/GETEEB	;READ APR FLAGS
	CONI APR(R)			;GET RIGHT HALF OF APR CONDITIONS
=	ARX_AR SWAP,CONI APR(L)		;NOW LH COND TO AR LEFT
	AR_ARX,ARL_ARL,J/RELEEB		;COMBINE HALVES
APRCO7:		CONO APR,J/RELEEB	;[272]
.TOC	"INTERNAL DEVICE FUNCTIONS -- PI"

=0****00*000
.IFNOT/INSTR.STAT
PIDO:
PIDI:	AR_BR,J/UUO			;DATAI/O PI, UNASSIGNED

.IF/INSTR.STAT
;DATAO PI, SETS UP BUFFER POINTERS FOR TRACKS
;DATAI PI, READS CURRENT BUFFER POINTER

PIDI:
PIDO:	BR/AR,ARL+ARX_0.M,CALL.M,	;CHECK IO LEGALITY
		SKP IO LEGAL,J/IOCHK
	SC_#,#/9.,B DISP,SKP BR0,J/PIDX	;NOW, WHAT TO DO?
.ENDIF/INSTR.STAT

PIBI:	READ ERA,J/RDEBRG		;GET AND STORE
=0
PIBO:	FE_#,#/7,CALL,			;NUMBER OF TIMES TO TRY
		SKP IO LEGAL,J/IOCHK	;SBUS DIAGNOSTIC
DODIAG:	SBUS DIAG,BR/AR			;SEND THE DIAG FUNCTION FROM AR
=
.DEFAULT/MOS=0
.IFNOT/MOS
	AR/CACHE,VMA_VMA+1,STORE,J/STMEM ;STORE THE RESPONSE
.IF/MOS
	AR/CACHE,MB WAIT		;[225]GET THE DATA.
	GEN AR+1,SKP AD NE		;IF MEMORY RETURNED -1 TRY AGAIN
=0
	FE_FE-1,SKP SCAD0,J/SDTEST	;IT IS SEE IF TOO MANY TRIES
SDONE:	VMA_VMA+1,STORE,J/STMEM		;STORE THE RESPONSE
=0
SDTEST:	AR_BR,J/DIAG1			;[225]RECOVER THE FUNC AND RETRY.
	AR_0S,J/SDONE			;TOO MANY TRIES QUIT RETURNING 0
.ENDIF/MOS

=0****00*000
PICO:	BR/AR,ARL_ARR.M,ARR_ARR,
		CALL.M,SKP IO LEGAL,J/PICOM1
=11	CONO PI,J/PICOM2		;SEND THE DATA
=0****00*100
PICI:	BR/AR,CALL,SKP IO LEGAL,J/PICOM1
=11	CONI PI(R)			;READ RH TO AR LEFT
=	ARX_AR SWAP,			;RH COND TO ARX RH
		CONI PI(PAR)		; AND PARITY ENABLES TO RH
	BRX/ARX,ARX_AR,			;READY TO COMB RH PARTS
		CONI PI(L)		; AND LH TO AR LEFT
	AR_ARX*BRX,AD/OR,ARL_ARL	;COMBINE THEM
PICOM2:	REL EBUS,GEN AR,B WRITE,J/IOTEND

=0
PICOM1:	AR_BR,J/UUO			;LOSE
	REQ EBUS,J/WGRANT		;OK, WAIT TO GET FULL EBUS
.TOC	"TRACKS SUPPORT"
;
;	According to the University of Essex, when TRACKS is used with
;	address break enabled, the monitor cannot disable address break
;	for the actual execution of the instruction unless we include
;	"ABORT INSTR" as part of the TRACKS loop.  Accordingly, this is
;	now done for all the different flavors of TRACKS.  Thanks, folks.
;
;[317]	During an attempt to implement uncounting of doubly counted op
;	codes for the OP.CNT conditional, we learned:  (1) EA
;	calculation requires that VMA be initialized to the instruction
;	location (usually PC) for the local/global stuff to work properly.
;	Beware!  (This is important if you try to do something after
;	fetching an instruction but before you EA calc it.)  (2) NICOND
;	clears the trap enable flag.  If INSTR.STAT is on, this will force
;	the dispatch to the statistics logic without taking the trap,
;	which will thus be lost and gone forever.  This is a hardware bug,
;	but it's rather impossible to ECO it at this late date.
;
;[321]	The solution to this is to ignore the statistics flag if a trap
;	is ready.  See the block at NEXT for details.  (It's not really
;	a hardware bug after all.)
;
.IF/INSTR.STAT
=00
PIDX:	CLR TRACKS EN,J/IFNOP		;TURN TRACKS OFF
.IF/TRACKS
	ARX_SHIFT,ARL_BRL,ARR_0.S,J/PIDO2
.IFNOT/TRACKS
	ARX_SHIFT,AR_2,J/PIDX1		;[315] Turn statistics on
.ENDIF/TRACKS
=11	AR_TRX				;READ BACK POINTER
	ARL_0.M				;GET INDEX PART
	AR_AR+TRB,STORE,J/STMEM		;DONE WITH DATAI

.IFNOT/TRACKS
PIDX1:	AR_ARX+AR*4			;SAVE PAGE NUMBERS IN TRX REGISTERS
	TRB_AR				;INITIAL GARBAGE HERE
	VMA_ARX,LOAD AR,PHYS REF	
	AR_MEM
	VMA_ARX+1,LOAD AR,PHYS REF
	TRX_AR,ARX_ARX+1		;[315] Must wait one cycle for
	AR_MEM				;parity check before writing AC
	VMA_ARX+1,LOAD AR,PHYS REF
	TRX1_AR,ARX_ARX+1		;[315] Note that this will always
	AR_MEM				;make it before AR is smashed
	VMA_ARX+1,LOAD AR,PHYS REF
	TRX2_AR
	AR_MEM
	SET TRACKS EN			;[315] Might as well do this now
	TRX3_AR,I FETCH,J/NOP		;SAVE TABLE PAGE #, TURN ON
.ENDIF/TRACKS

PIDO2:	TRX_AR,AR_ARX			;SET UP INDEX
	TRB_AR				;AND BASE
	SET TRACKS EN,J/IFNOP		;TURN TRACKS ON

.IF/TRACKS
;HERE WHEN NICOND FINDS TRACKS ENABLED
=0
TRK1:	TRX_AR,J/TRK2			;PUT BACK UPDATED INDEX
	AR_AR SWAP			;END OF BUFFER.  RESET
	AR_-AR,J/TRK1			; ORIGINAL INDEX

TRK2:	ARL_0.M
	AR_AR+TRB			;ADDRESS TRACKS BUFFER
	VMA_AR,PHYS REF			;TO MAKE MODEL A WORK
	AR_PC,STORE,PHYS REF		; PUT PC THERE
	MEM_AR,VMA/PC,CLR TRACKS EN	;PREVENT NICOND SEEING TRACKS...
	ABORT INSTR			;[306] Make address break work by
					; copying AD BRK CYC to AD FAIL INH
	SET TRACKS EN			;...UNTIL NEXT TIME
	DISP/NICOND,J/NEXT		;GO DO NEXT INSTR
.ENDIF/TRACKS
.IF/OP.CNT
;HERE WHEN NICOND FINDS OPCODE COUNTING ENABLED
; SKIP IF USER MODE
;[316] Make this register usage compatible with timing version below by
; making it use TRX2 (for exec mode counts pointer) and TRX3 (for user mode
; counts pointer) instead of TRX and TRX+1.
;[317] A massive attempt to uncount doubly counted instructions when an
; interrupt was detected has been backed off.  See INSTR.STAT dispatch logic
; above for commentary.
;
=0
OPCT1:	AR_TRX2,SKP AC REF,J/OPCT2	;[316] TRX HAS PAGE # FOR EXEC TABLE
	AR_TRX3,SKP AC REF		;[316] NEXT PAGE IS FOR USER
=0
OPCT2:	AR_SHIFT,MQ_SHIFT,		;[317] Save VMA of increment
		CLR TRACKS EN,J/OPCT3	;OPCODE INDEXES INTO TABLE
	ARX_FM(VMA),J/OPCT2		;GET INSTR FROM FM
;
OPCT3:	VMA_AR,LOAD AR,PHYS REF		;GET TABLE ENTRY
	AR_MEM				;[306] Make address break work
	BR/AR,AR_AR+1,STORE		;ADD THIS OCCURANCE TO IT, keep old
	MEM_AR,VMA/PC
	SET TRACKS EN			;LET US GET BACK NEXT NICOND
	DISP/NICOND			;DO INSTR IN ARX
;
;	In an attempt to prevent an interrupt after counting an instruction,
;	we now fake the second NICOND in line.
;
=0000	AR_BR,CLR TRACKS EN,J/OPFIX	;Some kind of odd condition.
=0010	AR_BR,CLR TRACKS EN,J/OPFIX	; Uncount the instruction
	AR_BR,CLR TRACKS EN,J/OPFIX
	AR_BR,CLR TRACKS EN,J/OPFIX
	AR_BR,CLR TRACKS EN,J/OPFIX
	AR_BR,CLR TRACKS EN,J/OPFIX
=1010	BRX/ARX,AR_ARX,SET ACCOUNT EN,	;The usual case
		XR,EA MOD DISP,J/COMPEA
	AR_BR,CLR TRACKS EN,J/OPFIX
=1110	GEN ARX,LOAD IR,#/0,J/XCTGO	;Instruction in registers
	AR_BR,CLR TRACKS EN
;
OPFIX:	VMA_MQ,STORE,PHYS REF		;Restore old count
	MEM_AR,VMA/PC
	SET TRACKS EN			;Turn TRACKS back on
	DISP/NICOND,J/NEXT		; and do it yet again
.ENDIF/OP.CNT
.IF/OP.TIME
;HERE TO ADD UP TIME SPENT IN INSTR'S

OPTM0:	SC_#,#/9.,SKP USER,J/OPTM1
=0
OPTM1:	BR_AR LONG,AR_TRX2,SKP AC REF,	;INSTR IN ARX PAGE IN AR
		J/OPTM2
	BR_AR LONG,AR_TRX3,SKP AC REF,	;INSTR IN ARX PAGE IN AR
		J/OPTM2
=0
OPTM2:	AR_SHIFT,ABORT INSTR,J/OPTM3	;[306] GENERATE ADDR TO INCREMENT
					;NEXT GET ADDR FOR THIS
	ARX_FM(VMA),J/OPTM2		;GET NEXT INSTR FROM FM
OPTM3:	VMA_AR,LOAD AR,UNCSH PHYS REF	;BUMP COUNT LOCATION
	AR_MEM
	AR_AR+1,STORE
	MEM_AR,SKP USER
=0	AR_TRX,J/OPTM4
	AR_TRX1
OPTM4:	AR_SHIFT,ARX_TRB
	TRB_AR				;SAVE NEXT LOC TO BUMP
	RD+CLR PA			;TIME TO AR
	MTR CTL/CLR PERF
	VMA_ARX,LOAD ARX,UNCSH PHYS REF	;GET TABLE ENTRY
	AR_AR-BR,ARL_0.S		;COMPENSATE TIME FOR THIS CODE
	BR/AR,ARX_MEM,SKP AR18		;IF THIS WAS AN ENABLED STATE,
=0	AR_ARX+BR,STORE			;WRITE IT BACK
	MEM_AR,VMA/PC			;NOW SETUP NEXT INSTR AGAIN
	ARX_BRX,SET TRK+PA EN		;RESTORE STATISTICS FLAGS
	DISP/NICOND,J/NEXT
.ENDIF/OP.TIME
;THIS IS THE SECOND ORDER STATISTICS GATHERING CODE
.IFNOT/SO2.CNT
.IF/SO.CNT
;THIS IS NON DEBUGED CODE THAT IS IN A VERY PRIMATIVE STATE
;IT WAS ABANDONED BETWEEN EDITS AS THE MONITOR NEEDED SOMETHING
;SLIGHTLY DIFFERENT
;THIS IS CODE TO DO A SECOND ORDER STATISTIC IN THE SECOND 128K
;EACH ENTRY IS A HALF WORD
;THE LOW ORDER BIT OF <LAST OPCODE><THIS OPCODE> CONCATENATION
;DETERMINES WHICH HALFWORD IS INCREMENTED. OFF IS HIGH
;IF A HALFWORD OVERFLOWS THE CODE TURNS ITSELF OFF AND WRITES -1
;AT LOCATION 400000
;TRX HIDES THE LOCATION PRESENTED TRB THE LAST OPCODE

;	THIS IS IN THE NEXT LOOP COMMENTED HERE FOR DOCUMENTATION
;TRK0:	ARX_TRB,BRX/ARX,SKP AC REF,J/TRK1;GET PREV INSTR HIDE THIS ONE

=0
TRK1:	AR_1,SC_#,#/9.,J/TRK2		;SHIFT IN FIRST OPCODE
	ARX_FM(VMA),AR_ARX		;GET THE INSTRUCTION FROM FM
	BRX/ARX,AR_1,SC_#,#/9.,ARX_AR	; WHEN IT HIDES THERE
TRK2:	AR_SHIFT,SC_#,#/8.,ARX_BRX	;SETUP TO DO THE NEXT OPCODE
	AR_SHIFT,CLR TRACKS EN		;CONVIENT TO SHUT OFF TRACKS
	VMA_AR,LOAD ARX,PHYS REF,AR_ARX	;LOW BIT OF INSTR WHERE CAN TEST
	ARX_SHIFT,TRB_AR		;LOW BIT OF INSTR TO HIGH BIT
	ARL_0.S,ARR_1S,SKP ARX0		;SEE WHICH HALFWORD TO INC
					; ALSO SETTING UP FOR TEST IN
					; LOW INCREMENT
=0	ARL_1.M,ARR_0.M,J/TRK3		;INC HIGH
	ARX_MEM				;INC LOW
	BR/AR,ARX_ARX+1,AR/ADX,STORE	;INCREMENT LOW HALF AND STORE IT
	TEST AR.BR,SKP CRY0		;USING AND-1 HACK TO TEST OVFLOW
=0	AR_0S,J/TRKLOS			;OVERFLOWED FIXUP TO LOSE
	MEM_AR,ARX_BRX,VMA/PC,AR_BRX	;NO OVERFLOW GET OUT ALSO
TRKN1:	SET TRACKS EN			; SAVE AWAY THIS OPCODE
TRKND:	DISP/NICOND,J/NEXT		;AND DO NEXT INSTR

TRK3:	ARX_MEM,BR/AR			;GET WORD TO INC
	AR_ARX+BR,STORE,SKP CRY0	;COMPUTE AND CHECK FOR OVERFLOW
=0	ARX_BRX,VMA/PC,MEM_AR,AR_BRX,	;SAVE AWAY THIS INSTR
		J/TRKN1			; AND GET OUT
	AR_0.C,ARX_BRX,MEM_AR,J/TRKLOS	;SHUT DOWN TRACKS ON OVERFLOW


TRKLOS:	AR_1,SC_#,#/17.			;WHEN LOSS PUT -1 IN 400000
	AR_SHIFT
	GEN AR,VMA/AD,PHYS REF		;SHUT OFF TRACKS AND QUIT
	AR_TRB,STORE
	MEM_AR,VMA/AD
	J/TRKND

.ENDIF/SO.CNT
.IF/SO2.CNT
;THIS ONE DOES THE COUNTING IN 128K STARTING AT AN ADDRESS PRESENTED IT
;THIS IS CODE TO DO A SECOND ORDER STATISTIC IN THE SECOND 128K
;EACH ENTRY IS A HALF WORD
;THE LOW ORDER BIT OF <LAST OPCODE><THIS OPCODE> CONCATENATION
;DETERMINES WHICH HALFWORD IS INCREMENTED. OFF IS HIGH
;IF A HALFWORD OVERFLOWS THE CODE TURNS ITSELF OFF AND WRITES -1
;AT LOCATION PRESENTED
;TRX HIDES THE LOCATION PRESENTED TRB THE LAST OPCODE

;	THIS IS IN THE NEXT LOOP COMMENTED HERE FOR DOCUMENTATION
;TRK0:	ARX_TRB,BRX/ARX,SKP AC REF,J/TRK1;GET PREV INSTR HIDE THIS ONE

=0
TRK1:	AR_0S,SC_#,#/9.,J/TRK2		;SHIFT IN FIRST OPCODE
	ARX_FM(VMA),AR_ARX		;GET THE INSTRUCTION FROM FM
	BRX/ARX,AR_0S,SC_#,#/9.,ARX_AR	; WHEN IT HIDES THERE
TRK2:	AR_SHIFT,SC_#,#/8.,ARX_BRX	;SETUP TO DO THE NEXT OPCODE
	AR_SHIFT,CLR TRACKS EN		;CONVIENT TO SHUT OFF TRACKS
	AR_AR+TRX			;BUMPS BY NUMBER FED IT
	VMA_AR,LOAD ARX,PHYS REF,AR_ARX	;LOW BIT OF INSTR WHERE CAN TEST
	ARX_SHIFT,TRB_AR		;LOW BIT OF INSTR TO HIGH BIT
	ARL_0.S,ARR_1S,SKP ARX0		;SEE WHICH HALFWORD TO INC
					; ALSO SETTING UP FOR TEST IN
					; LOW INCREMENT
=0	ARL_1.M,ARR_0.M,J/TRK3		;INC HIGH
	ARX_MEM,ABORT INSTR		;[306] INC LOW
	BR/AR,ARX_ARX+1,AR/ADX,STORE	;INCREMENT LOW HALF AND STORE IT
	TEST AR.BR,SKP CRY0		;USING AND-1 HACK TO TEST OVFLOW
=0	AR_0S,J/TRKLOS			;OVERFLOWED FIXUP TO LOSE
	MEM_AR,ARX_BRX,VMA/PC,AR_BRX	;NO OVERFLOW GET OUT ALSO
TRKN1:	SET TRACKS EN			; SAVE AWAY THIS OPCODE
TRKND:	DISP/NICOND,J/NEXT		;AND DO NEXT INSTR

TRK3:	ARX_MEM,BR/AR,ABORT INSTR	;[306] GET WORD TO INC
	AR_ARX+BR,STORE,SKP CRY0	;COMPUTE AND CHECK FOR OVERFLOW
=0	ARX_BRX,VMA/PC,MEM_AR,AR_BRX,	;SAVE AWAY THIS INSTR
		J/TRKN1			; AND GET OUT
	AR_0.C,ARX_BRX,MEM_AR,J/TRKLOS	;SHUT DOWN TRACKS ON OVERFLOW


TRKLOS:	AR_TRX
	GEN AR,VMA/AD,PHYS REF	;WRITE -1 IN PRESENTED LOCATION
	AR_TRB,STORE
	MEM_AR,VMA/PC		;NEED AN INSTRUCTION TO GIVE
	J/TRKND			;TIME TO NICOND AFTER VMA/PC

.ENDIF/SO2.CNT
.ENDIF/INSTR.STAT
.TOC	"INTERNAL DEVICE FUNCTIONS -- PAG"

=0****00**00
.IFNOT/KLPAGE
PAGBO:	BR/AR,CLR FE,CALL,		;INVALIDATE ONE PAGE TABLE LINE
		SKP IO LEGAL,J/IOCHK
PAGBO1:	PT SEL_INVAL,J/PTLOOP		;SETUP INITIAL PT WR SELECT
.IF/KLPAGE
PAGBO:	AR_0S,BR/AR,CALL,		;CLEAR ONE PAGE TABLE ENTRY
		SKP IO LEGAL,J/IOCHK
	WR PT ENTRY,J/IFNOP
.ENDIF/KLPAGE
PAGDO:	ARX_AR (AD),ARR_ARL,ARL_ARL.M,	;SETUP USER CONTEXT
		CALL.M,SKP IO LEGAL,J/GETEEB
	DATAO PAG(L),AR_ARX		;SETUP AC BLOCKS, PREV CTXT
=	SKP AR2,SC_#,#/9.
=0
TIMCO1:	MTR CTL/CONO TIM,J/RELEEB	;DO NOT CHANGE UBR
.IF/PAGCNT				;[327] Count DATAO PAG with bit 2
	MQ_AR,AR_TRX3+1			;[327] Do the count
	TRX3_AR,AR_MQ
.ENDIF/PAGCNT				;[327]
	FE_P AND #,#/4,MQ_SHIFT,	;[333] Save bit 3 for keep test
		SKP AR18,AR_0S		;STORE ACCT?
=0*0	AR0-8_#,#/100,CALL,J/PAGD2	;YES, START WITH EBOX CNT
	VMA_MQ,LOAD UBR,CALL [CLRPT]	;[333] No. Set for page table clear
.IF/BIG.PT				;[333]
=1*1	SKP SC NE,J/KEEPME		;[333] Might keep keep me bits
.IFNOT/BIG.PT
=1*1	PT SEL_INVAL,J/PTLOOP		;SETUP INITIAL PT WR SELECT
.ENDIF/BIG.PT				;[333]
;
;	PAGD2 is set up as a subroutine for addressing convenience only.
;
=0
PAGD2:	ARX_AR,SC_#,#/13.,CALL,J/EMTR	;UPDATE THE EBOX ACCT
	MB WAIT,AR0-8_#,#/140		;READY TO GET CACHE ACCT
	ARX_AR,SC_#,#/13.,J/CMTR	;RETURN ABOVE TO CLR PT


=0****00**00
PAGDI:	SC_#,#/70,SKP IO LEGAL,
		CALL,J/GETEEB
.IFNOT/MODEL.B
	DATAI PAG(L),CALL,J/PCTXT	;FIRST GET AC BLOCKS & CWSX
.IF/MODEL.B
	DATAI PAG(L),ARX_1B17-1,	;PUT AC BLKS IN AR,
		CALL,J/PCTXT		; [0,,-1] IN ARX
.ENDIF/MODEL.B
PAGBI:	AR_BR,J/UUO			;BLKI PAG, IS UNASSIGNED
	AR_SHIFT,ARL_BRL,J/RELEEB	;COMBINE UBR WITH AC BLKS, CWSX
=
.IFNOT/MODEL.B
PCTXT:	P_SC				;PLUG IN LOAD-ENABLE BITS
=0*	BR/AR,AR_0S,READ UBR,		;ASK MBOX FOR UBR LOC'N
		CALL,J/XFERW		;NOW READ IT
	AR_EBUS REG
.IF/MODEL.B
PCTXT:	P_SC,ARX_ARX*8			;STUFF IN LOAD EN, ARX=7,,-10
	BR/AR,AR12-17_PREV SEC,ARX_ARX*8
	BR/AR,AR_ARX*BR,AD/ANDCA	;PCS TO BR, LD EN, AC BLKS TO AR
=0*	AR_AR*BR,AD/OR,READ UBR,	;LH READY IN AR.  GET UBR
		CALL,J/XFERW
	BR/AR,AR_EBUS REG		;LH TO BR.  READ UBR ADDRESS
.ENDIF/MODEL.B
	ARX_AR,AR_0S,SC_#,#/27.,	;READY TO MOVE INTO POSITION
		RETURN3
;CONI/O PAG,

=0****00**00
PAGCO:	BR/AR,ARL_ARR.M,ARR_ARR,ARX_0S,	;SET EXEC CONTEXT
		SKP IO LEGAL,CALL.M,J/GETEEB
	CONO PAG,J/SETEBR		;SET CACHE, SEC, TRAP EN FLAGS

PAGCI:	BR/AR,AR_0S,CALL,SKP IO LEGAL,	;READ EXEC CONTEXT
		SC_#,#/9.,J/GETEEB
	CONI PAG			;READ CACHE, SEC, TRAP EN
=
=0*	ARX_AR SWAP,AR_0S,READ EBR,	;SETUP EPT LOC'N TO READ
		CALL,J/XFERW
	AR_EBUS REG,			;GET EBR IN AR
		BRX/ARX,ARX_0S		;SAVE FLAGS IN LH OF BRX
	ARX_SHIFT,REL ECL EBUS		;MOVE EBR LOC LEFT
	ARR_0.M,ADB/BR,ADA EN/EN,AD/OR,ARL/ADX	;COMBINE, THEN PUT IN RH
	AR_AR SWAP,B WRITE,J/IOTEND	;STORE THE RESULT

;HERE TO FINISH CONO PAG,

=000					;[342]
SETEBR:	SC_#,#/9.,CALL,J/SHIFT		;MOVE EBR LOC'N TO POSITION
=010	VMA_AR,LOAD EBR,CALL [CLRPT]	;[333]SETUP EBR
=110					;[342]SETUP INITIAL PT WR SELECT
KEEPME:	PT SEL_INVAL,J/PTLOOP		;[342] FOR NON KLPAGE THIS CAN SEND
					; THE USER TO PAGBO1 AND SAVE 1
					; UCODE LOCATION
.IF/BIG.PT				;[333] Entry from DATAO
	PT SEL_INVAL (KEEP),J/KEEPCL	;[342] Hang on to KEEP pages
.ENDIF/BIG.PT				;[333]
=
=110
PTLOOP:	AR_AR+BR,VMA/AD,FE_FE-1,	;SELECT A LINE OF PT
		CLR PT LINE,TIME/3T,	;DO THE WORK
		BYTE DISP,J/PTLOOP	;LOOP TO CLEAR ALL
	PT SEL_NORMAL,J/IFNOP		;RESET PT WR SELECTION
.IF/BIG.PT				;[333]
=110
KEEPCL:	AR_AR+BR,VMA/AD,FE_FE-1,TIME/3T,;SELECT A LINE OF PT
		CLR PT LINE (KEEP),	;DO THE WORK
		BYTE DISP,J/KEEPCL	;Hang onto lines with KEEP ME set
	PT SEL_NORMAL,J/IFNOP		;RESET PT WR SELECTION
.ENDIF/BIG.PT				;[333]
;
;	[333] Set up to clear hardware page table after setting EBR or
;	UBR.  KEEP ME pages may or may not be cleared, depending upon the
;	setting of DATAO PAG bit 3.  (Clear everything for CONO PAG.)
;
CLRPT:	AR_0S,ARX_0S,REL ECL EBUS	;[334]DON'T HANG UP BUS FOR THIS
=0	AR0-8_#,#/10,MB WAIT,		;WAIT FOR U/E BR LOAD
		SC_FE,CALL [ARSWAP]	;[334]GET 1B23
	BR/AR,AR_0S,VMA/AD,		;[333][334] START CLEARING AT ZERO
		FE_#,#/63.,RETURN4	;SETUP LOOP COUNT
.TOC	"INTERNAL DEVICE FUNCTIONS -- TIM & MTR"

=0****00***0
RDMTR:	AR_BR,CALL,			;GET E TO AR
		SKP IO LEGAL,J/GETEEB	;GRAB CONTROL OF EBUS
	MQ_AR,AR_0S,			;SAVE E IN MQ
		SC_#,#/13.,B DISP	;WHICH COUNTER?
=
=00	AR_TIME BASE,J/RDMTR1		;DATAI TIM,
	AR_PERF CNT,J/RDMTR1		;BLKI TIM,
	AR_EBOX CNT,J/RDMTR1		;DATAI MTR,
	AR_CACHE CNT,J/RDMTR1		;BLKI MTR,

=0
RDMTR1:	ARL+ARX_0.M,B DISP,		;SHIFT COUNT INTO POSITION
		CALL.M,J/MTRDBL		;ADD DOUBLE WORD FROM PT
	AR_AR+BR LONG,REL ECL EBUS
	VMA_MQ,STORE,SC_#,#/35.,J/DMVM1	;STORE TOTAL AT E & E+1

=0****00**00
TIMCO:	BR/AR,CALL,SKP IO LEGAL,J/GETEEB
	CONO TIM,J/TIMCO1
TIMCI:	BR/AR,AR_0S,CALL,
		SKP IO LEGAL,J/GETEEB
	AR_INTERVAL			;INTERVAL GOES TO LH
=	ARX_AR SWAP,AR_0S
	AR_PERIOD			;PERIOD TO RH
TIMBO1:	MTR CTL/LD PA LH,		;KEEP MTR DECODE FOR TIMBO
		ARL_ARXL,J/RELEEB	;COMBINE PERIOD WITH INTERVAL

=0****00**00
MTRCO:	BR/AR,ARL_ARR.M,ARR_ARR,
		CALL.M,SKP IO LEGAL,J/GETEEB
	CONO MTR,J/MTRCO1
MTRCI:	BR/AR,AR_0S,CALL,
		SKP IO LEGAL,J/GETEEB
	CONI MTR			;READ BACK CONDITIONS
=
MTRCO1:	ARL_0.S,MTR CTL/CONO MTR,J/RELEEB

=0****00**00
TIMDO:	AR_BR,J/UUO			;DATAO TIM, UNDEFINED
=10
TIMBO:	ARX_AR,AR_0S,CALL,		;SAVE ENABLES, CLEAR AR
		SKP IO LEGAL,J/GETEEB	;CHECK LEGALITY, GET BUS
	BLKO TIM(L),AR_ARX		;TURN OFF BY CLEARING LH ENABLES
=	BLKO TIM(R),AR_AR SWAP		;SEND RH
	BLKO TIM(L),J/TIMBO1		;SEND LH, TURNING ON AGAIN
;HERE WHEN METER INCREMENT REQUEST DETECTED

MTRREQ:	GET ECL EBUS			;TAKE CONTROL OF BUS
	AR_MTR REQ			;WHAT TYPE REQUEST?
=0	MQ_AR,AR_AR*2,CALL,		;GET READY TO DISP
		VMA_#,#/514,J/MTRRQ0
	REL ECL EBUS			;DONE
	MB WAIT,SET ACCOUNT EN,J/PIFET	;FETCH NEXT INSTR

MTRRQ0:	ARX_AR SWAP,DISP/SH0-3,AR_0S,	;DISPATCH ON REQUEST TYPE
		SC_#,#/13.
=000
	RD+CLR TB,J/TMTR1		;TIME BASE
	RD+CLR PA,J/PMTR1		;PERF ANALYSIS CNT
EMTR:	RD+CLR E CNT,J/EMTR1		;EBOX CNT
CMTR:	RD+CLR C CNT,J/CMTR1		;CACHE CNT
	REL ECL EBUS			;INTERVAL -- VECTOR INTERRUPT
=	SET PI CYCLE
	SET ACCOUNT EN,J/PIINST

TMTR1:	MTR CTL/CLR TIME,J/MTRRQ1	;HOLD SELECTS FOR
PMTR1:	MTR CTL/CLR PERF,J/MTRRQ1	;MTR CTL FUNCTION
EMTR1:	MTR CTL/CLR E CNT,J/MTRRQ1	; TO PREVENT RACE
CMTR1:	MTR CTL/CLR M CNT,J/MTRRQ1	; AND POSSIBLE GLITCHES

;HERE WITH RELEVANT COUNT IN ARR, GARBAGE IN ARL

MTRRQ1:	ABORT INSTR
=0	ARL+ARX_0.M,ARX0-3 DISP,	;CLEAR GARBAGE & RE-DISPATCH
		CALL.M,J/MTRDBL		; TO ADD DOUBLE COUNTER FROM PT
	AR_AR+BR LONG,SC_#,#/35.,
		VMA_VMA-1,STORE		;STORE BACK IN PROCESS TABLE
	MEM_AR,AR_0S			;HI PART TO MEM
	AR_SHIFT,VMA_VMA+1,STORE,RETURN1

;HERE TO PICK UP DOUBLEWORD FROM PROCESS TABLE
; AND ADD CURRENT CONTENTS OF APPROPRIATE METER

=00
MTRDBL:	AR_0S,ARX_SHIFT,
		VMA_#,#/510,J/RDEMTR	;TIME BASE IN EPT 510-511
	AR_0S,ARX_SHIFT,
		VMA_#,#/512,J/RDEMTR	;PERF CNT IN EPT 512-513
	AR_0S,ARX_SHIFT,
		VMA_#,#/504,J/RDUMTR	;EBOX ACCT IN UPT 504-505
	AR_0S,ARX_SHIFT,
		VMA_#,#/506,J/RDUMTR	;CACHE ACCT IN UPT 506-507

RDEMTR:	BR_AR LONG,			;SAVE COUNT IN BR!BRX
		LOAD AR,EPT REF,J/RDMTR2;GET HIGH WORD FROM EPT
RDUMTR:	BR_AR LONG,LOAD AR,UPT REF	; OR UPT AS APPROP
=0*
RDMTR2:	FIN XFER,VMA_VMA+1,LOAD ARX,	;NOW GET LOW WORD
		CALL,J/XFERW		;GO WAIT FOR IT
	ARX_ARX*2,RETURN1
.TOC	"PRIORITY INTERRUPT PROCESSING"
;HERE WHEN PRIORITY INTERRUPT REQUEST DETECTED
;PI LOGIC HAS DONE HANDSHAKE TO BRING FUNCTION WORD IN ON EBUS
; FUNCTION WORD IS NOW IN AR, SC=2

;THE FORMAT OF THE FUNCTION WORD IS --
;    0-2	ADDRESS SPACE FOR THE FUNCTION
;	0=EPT
;	1=EXEC VIRTUAL
;	4=PHYSICAL
;	OTHERS UNDEFINED
;    3-5	FUNCTION TO PERFORM (SEE LIST BELOW AT PIDISP)
;      6	FUNCTION QUALIFIER
;   7-10	PHYSICAL DEVICE # ON EBUS
;  11-12	UNDEFINED
;  13-35	ADDRESS FOR FUNCTION

PICYC1:	SET PI CYCLE,MQ_AR		;START PI CYCLE
	FM[SV.IOP]_AR			;[234] save IOP function word
					; in AC3.
	VMA_AR AND ADMSK,ARX/AD,SH DISP	;EXTRACT ADDR, DISP ON FCN
=1000					;3-5 IS FUNCTION TO PERFORM
PIDISP:	VMA_40+PI*2,J/PIINST		;(0) STANDARD INTERRUPT
	VMA_40+PI*2,J/PIINST		;(1) DITTO
	AR_AR*4,SC_#,#/5,J/PIVECT	;(2) VECTOR
	LOAD AR,J/PIINCR		;(3) INCREMENT
	SKP AR6,J/PIDATO		;(4) DATAO
	BRX/ARX,TIME/5T,J/PIDATI	;(5) DATAI
	AR_AR*4,SKP AR6,J/PIBYTE	;(6) BYTE TRANSFER
.IFNOT/IPA20				;[265]
	VMA_40+PI*2,J/PIINST		;(7) UNDEFINED
.IF/IPA20				;[265]
	VMA_AR AND ADMSK, J/PHYS0	;(7) KLIPA   [265]
.ENDIF/IPA20

PICYC2:	VMA_41+PI*2,J/PIINST		;2ND PART OF STD INT

PIVECT:	FE_# AND S,#/30,AR_0S,SH DISP	;WHAT KIND OF DEVICE?
=0011
PIINST:	EPT FETCH,J/XCTW		;CHAN 0-3
	EPT FETCH,J/XCTW		;CHAN 4-7
	AR0-8_FE+#,#/142,J/DTEVEC	;DTE 0-3
	LOAD ARX,J/XCTW			;EXTERNAL DEVICE
=0*
DTEVEC:	ARX_AR,AR_0S,SC_#,#/9.,CALL,J/SHIFT
	VMA_AR,EPT FETCH,J/XCTW

=0101
PILD:	LOAD AR,EPT REF,J/XFERW		;GET DATUM FROM EPT
	LOAD AR,J/XFERW			; OR EXEC VIRTUAL ADDR SPACE
.IFNOT/MODEL.B
	VMA_ARX,LOAD AR,
		PHYS REF,J/XFERW	; OR PHYSICAL MEMORY, AS REQUESTED
.IF/MODEL.B
	VMA_ARX AND ADMSK,ARX/AD,J/PHYS2;FORCE AC'S FOR 0-17
.ENDIF/MODEL.B
.IFNOT/MODEL.B			;[224] 
IOPFIN:	SET ACCOUNT EN,J/PIDONE		;IN CASE OF EBUS PROBLEMS
.ENDIF/MODEL.B			;[224]

;HERE TO PERFORM INCREMENT FUNCTION

PIINCR:	AR_MEM,SKP AR6			;GET WORD, INCR OR DECR?
=0	AR_AR+1,STORE,J/PIDONE
	AR_AR-1,STORE,J/PIDONE
;HERE FOR DATAO (EXAMINE) FUNCTION

=0000
PIDATO:	AR0-3 DISP,CALL.M,J/PILD	;GET DATA FROM REQUESTED ADR SPC
	AR_AR*4,CALL,J/RDEX		;RESTRICTED EXAMINE
PIOUT:	AR_MEM,SET DATAO,CALL,J/EBUSO	;SEND DATA
PIDONE:	MEM_AR,DISMISS			;DONE, DISMISS & RESUME NORMAL
PIFET:	VMA/PC,FETCH,J/NOP		;RESUME AS BEFORE
=0101	VMA_AR-1,CALL,J/DEXCHK		;GO PROT/RELOC THIS EXAM
.IFNOT/MODEL.B
=0111	VMA_ARX,LOAD AR,PHYS REF,J/PIOUT;PROTECTED PHYSICAL
.IF/MODEL.B
=0111	VMA_ARX AND ADMSK,ARX/AD,J/PHYS1;FORCE AC'S FOR 0-17
.ENDIF/MODEL.B
=1111	J/PIOUT				;PROT VIOLATION.  SEND 0

;HERE FOR DATAI (DEPOSIT) FUNCTION

=10
PIDATI:	SET DATAI,TIME/5T,CALL,J/EBUSI	;READ THE DATA
	ARX_AR,AR_MQ			;DATUM TO ARX, GET FCN WORD
	BRX/ARX,ARX_BRX,SKP AR6		;RESTRICTED?
=0000	AR0-3 DISP,AR_BRX,J/PIST	;NO, STORE AS REQUESTED
	AR_AR*4,CALL,J/RDEX		;YES, GET PROT/RELOC ADDR
=0101	VMA_AR+1,CALL,J/DEXCHK		;VERIFY LEGALITY
=0111	AR_BRX,J/PSTOR			;DATA IN AR, ADDR IN ARX. STORE PHYS
=1111	J/PIDONE			;PROT VIOLATION, STORE NOTHING

=0101
PIST:	STORE,EPT REF,J/PIDONE
	STORE,J/PIDONE
.IFNOT/MODEL.B
PSTOR:	VMA_ARX,STORE,PHYS REF,J/PIDONE
.IF/MODEL.B
PSTOR:	VMA_ARX AND ADMSK,ARX/AD,J/PHYS3;FORCE AC'S FOR 0-17
.ENDIF/MODEL.B
	J/PIDONE

RDEX:	FE_# AND S,#/30,AR_ARX		;DTE# *8 TO FE, ADDR TO AR
	BR/AR,AR0-8_FE+#,#/145		;SAVE ADDR TO BR, GET EPT LOC
GTAR08:	ARX_AR,AR_0S,SC_#,#/9.
	AR_SHIFT,RETURN4

=0*
DEXCHK:	CALL,J/PILD			;PROTECTION WORD FROM EPT
	SKP AR GT BR			;ALLOWED?
=00	AR_0S,RETURN12			;NO, SEND 0, STORE NOTHING
	VMA_VMA+1,CALL,J/PILD		;YES, GET RELOCATION WORD
=11	AR_AR+BR			;RELOCATE TO PHYSICAL ADDR
	ARX_AR AND ADMSK,RETURN2	;STRIP TO 23 BITS
.IF/IPA20
					;BEGIN EDIT [265]
PHYS0:	LOAD AR, PHYS REF CACHE		;[311]START READ
	AR_MEM				;FINISH READ
=10	AR_AR+1, SET DATAO,		;INCREMENT THE LOCATION
		CALL [EBUSO]		;AND SEND DATA OVER THE EBUS
	STORE, PHYS REF CACHE,		;[311]UPDATE MEMORY
		J/PIDONE		;FINISH MEMORY CYCLE
.ENDIF/IPA20				;END EDIT [265]
;FORCE AC'S FOR 0-17

.IF/MODEL.B
=00
PHYS1:	SC_#,#/32.,CALL,J/CHKAC		;DATAO (EXAMINE)
=10	LOAD AR,J/PIOUT			;AC REF DONT USE PHYS REF
	LOAD AR,PHYS REF,J/PIOUT	;NOT AC'S GET PHYSICAL MEMORY

=00
PHYS2:	SC_#,#/32.,CALL,J/CHKAC		;DATAO (EXAMINE)
=10	LOAD AR,J/XFERW
	LOAD AR,PHYS REF,J/XFERW	;NOT AC'S GET PHYSICAL MEMORY

=00
PHYS3:	SC_#,#/32.,CALL,J/CHKAC
=10	STORE,J/PIDONE
	STORE,PHYS REF,J/PIDONE

CHKAC:	ARX_SHIFT			;GET ADDRESS WITHOUT 32-35
	ARX_ARX AND ADMSK,		;FLUSH GARBAGE IN 0-3
		SKP AD NE,RETURN2	;AND MAKE THE TEST
.ENDIF/MODEL.B
;HERE FOR BYTE TRANSFERS

=000
PIBYTE:	FE_# AND S,#/30,CALL,J/PIBPA	;OUT... GET BP ADDR
	SET DATAI,CALL,J/EBUSI		;IN ... FIRST READ THE DATA
=011	ARX_AR,AR_MQ*4,J/PIDPB		;GOT IT, GO DEPOSIT IT

=100	VMA_AR,CALL,J/PIIBP		;GO INCREMENT OUTPUT BP
	SC_FE+SC,CALL,J/LDB1		;GO LOAD BYTE FROM IT
=111	J/PIOUT				;THEN SEND BYTE

=000
PIDPB:	BRX/ARX,FE_# AND S,#/30,	;HERE WITH INPUT DATA
		CALL,J/PIBPA
=100	VMA_AR+1,CALL,J/PIIBP		;GO INCREMENT INPUT BYTE PTR
	AR_BRX,SC_#-SC,#/36.,		;STORE BYTE WITH IT
		SKP SCAD0,CALL,J/DPB1
=111	J/PIDONE

PIBPA:	AR0-8_FE+#,#/140,J/GTAR08

=00*
PIIBP:	CALL,J/PILD			;GET POINTER FROM EPT
	P_P-S,SKP SCAD0,CALL.M,J/IBPS	;INCREMENT IT
=11*	ARX_AR,SC_P,J/BYTEA		;NOW EVALUATE ITS ADDR
.TOC	"KL-MODE PAGE REFILL LOGIC"

.IF/KLPAGE
;HERE ON ANY PAGE FAILURE
;THE POSSIBLE CAUSES ARE --
;  1:	A PARITY ERROR WAS DETECTED IN AR OR ARX FOLLOWING A READ
;	REFERENCE.  IN THIS CASE WE SAVE THE BAD WORD IN A RESERVED
;	LOCATION IN FAST MEMORY BLOCK 7, AND RETURN A PAGE FAIL CODE
;	INDICATING THE ERROR.
;  2:	THE MBOX DETECTED A PROPRIETARY VIOLATION OR PAGE TABLE PARITY
;	ERROR, OR THE EBOX FOUND THE SELECTED ADDRESS BREAK CONDITION.
;	IN THIS CASE, WE RETURN THE PAGE FAIL CODE GENERATED BY THE
;	MBOX (SEE PRINT PAG4).
;  3:	A REFERENCE OCCURRED FOR A VIRTUAL PAGE FOR WHICH THE HARDWARE
;	PAGE TABLE DIRECTORY HAD NO VALID MATCH.  IN THIS CASE, WE
;	WRITE THE PAGE TABLE DIRECTORY FROM THE VMA, AND CLEAR THE
;	ACCESS BITS FOR ALL PAGE ENTRIES CONTROLLED BY THE SELECTED
;	DIRECTORY ENTRY.  WE THEN JOIN THE REFILL CODE, BELOW.
;  4:	A REFERENCE OCCURRED FOR A VIRTUAL PAGE FOR WHICH THE ACCESS BIT
;	IN THE HARDWARE PAGE TABLE WAS OFF, OR A WRITE OCCURRED TO A
;	PAGE WHOSE WRITABLE BIT WAS OFF.  IN THIS CASE, WE EVALUATE THE
;	PAGING POINTERS IN CORE TO DETERMINE WHETHER THE ACCESS SHOULD
;	BE ALLOWED, AND IF SO, THE PHYSICAL PAGE TO WHICH IT SHOULD BE
;	TRANSLATED.  WE THEN EITHER PAGE FAIL, OR WRITE A PAGE ENTRY
;	INTO THE HARDWARE PAGE TABLE AND RESTART THE REFERENCE.
;
;	[322] Note that in the latter case, if a page should be accessible
;	but not writable, it is the microcode's responsibility to turn on
;	bit 2 of the page fail word (the Accessible bit) if a write
;	reference is attempted to such a page.  Currently, this is done only
;	if no CST is present (TOPS-10 operating mode), since TOPS-20
;	retraces the page map from scratch and thus generates the correct
;	information.  The bit can be made correct for the CST present case
;	(see code near NOTWR), but since we are now quite tight on control
;	store, we have chosen not to implement this.
;
;	If you are looking at this code for the first time, be aware that
;	only AR, ARX, SC, and FE are saved and restored here; thus BRX and
;	MQ are strictly off limits for this code.
;
.IFNOT/MODEL.B
2377:	CLR ACCOUNT EN,FORCE AR-ARX,J/PF1
.IF/MODEL.B
3777:	CLR ACCOUNT EN,FORCE AR-ARX,J/PF1
.ENDIF/MODEL.B
1777:	CLR ACCOUNT EN,FORCE AR-ARX
PF1:	SV.AR_AR,AR_ARX,ARX_AR (AD)	;SAVE CURRENT AR
	SV.ARX_AR,AR_ARX,ARX_AR (AD)	; AND ARX
.IF/PAGCNT				;[327] Page fault counting
	AR_TRX2+1			;[327] Count this page fault
	TRX2_AR
	AR_SV.AR			;[346] Don't lose initial AR
.ENDIF/PAGCNT				;[327]
	GET ECL EBUS,PF DISP,J/PF2	;PARITY ERROR?
=1100
PF2:
.IFNOT/PAGCNT				;[327]
=1101	FE_#,#/36,SKP RPW,J/PFPAR	;YES.  AR PARITY ERROR, CODE 36
					;CHECK FOR MIDDLE OF RPW CYCLE
.IF/PAGCNT
=1101	AR_SV.AR,J/ARPAR		;[327] AR parity error. Get back
.ENDIF/PAGCNT				;[327] saved AR
	AR_ARX,FE_#,#/37,SKP RPW,J/PFPAR;[307] YES, ARX PARITY. COULD BE RPW
	AR_EBUS REG,MB WAIT		;NO. GET PAGE FAIL WORD
	REL ECL EBUS,PF DISP,J/PF4	;EBOX HANDLING REQUIRED?
;
.IF/PAGCNT				;[327]
ARPAR:	FE_#,#/36,SKP RPW,J/PFPAR	;Set code 36 and check for RPW
.ENDIF/PAGCNT

;HERE ON ANY PARITY ERROR
;SKIP IF MIDDLE OF READ-PAUSE-WRITE CYCLE, IN WHICH CASE WE
; MUST WRITEBACK THE DATA TO PREVENT INCOMPLETE CYCLE
=0
PFPAR:	VMA_VMA HELD,J/PFPAR1		;MAY HAVE CHANGED AT MBWAIT
	STORE				;WRITEBACK WITH GOOD PARITY
PFPAR1:	MAP,SC_#,#/140			;GET MAP INFO ON REF
PFPAR2:	SV.PAR_AR,MB WAIT		;[234]SAVE WORD WITH BAD PARITY
	AR_EBUS REG			;READ MAP INFO
	REL ECL EBUS,SC_P AND SC	;GET USER BIT FROM MAP WORD
	P_FE OR SC,J/PF4		;STUFF IN PARITY ERROR CODE
;HERE WITH PAGE FAIL WORD IN AR
; TESTING FOR EBOX HANDLING REQUIRED.

=0111
PF4:	SV.PFW_AR,SR DISP,J/CLEAN	;NO, GO CLEAN UP
	SV.PFW_AR,AR_BR,BR/AR		;YES, GET BR TOO
	SV.BR_AR,AR_0S			;SAVE BR
	AR0-8_FE			;NOW SAVE 10-BIT REGS
	ARX_AR (AD),AR0-8_SC		;FE TO ARX, SC TO AR
	ARR_ARL,ARL_ARX (ADX),		;FE IN ARL, SC IN ARR
		ARX_VMA HELD		;GET VMA WHICH FAILED
	SV.SC_AR,AR_ARX,		;HOLD SC & FE
		GEN BR*2,SIGNS DISP	;TEST FOR PT DIR MATCH
=1110
PGRF1:	SV.VMA_AR,ARX_AR SWAP,ARR_ARL,	;GET SEC # TO AR32-35
		DISP/EA MOD,J/PGRF2	; SEC < 20?

;	HERE TO WRITE PT DIR, & CLR 4 PAGE ENTRIES.  If the expanded
;	page table ECO has been installed, this will only clear two entries
;	(since they go in pairs for that case), but in either case the
;	right thing will happen. [333]
;
	AR_0S,COND/MBOX CTL,MBOX CTL/2,	;READY TO CLEAR EVEN PAIR
		FE_P AND #,#/2,SC/SCAD	;GET WRITE REF BIT TO FE & SC
	COND/MBOX CTL,MBOX CTL/33,	;CLR EVEN, WR DIR, SEL ODD
		TIME/3T,FE_FE+SC,SC/SCAD; WR REF = 4 NOW
	COND/MBOX CTL,MBOX CTL/10,	;CLR ODD, RESET NORMAL SELECT
		TIME/3T,FE_FE+SC,AR_BR	;GET PFW BACK, WR REF = 10
	SC_# AND AR0-8,#/401		;GET USER & PAGED REF BITS
	AR0-8_FE OR SC			;COMBINE WITH WR REF BIT
	SV.PFW_AR,BR/AR,AR_ARX,J/PGRF1	;REJOIN MAIN PATH
;	HERE TO TRACE PAGE POINTERS FOR THIS ADDRESS
;	VMA WHICH FAILED IS IN ARX AND AR WITH THE HALVES SWAPPED
;	PAGE FAIL WORD IS IN BR
;	[333] Bit 5 of all access pointers is implemented as "Keep" for
;	pages which should not be swept from the page map on DATAO PAG
;	UBR reload unless bit 3 is also set.
;

.IFNOT/EPT540
=1101
PGRF2:	VMA_#+AR32-35,#/440,		;YES.
		SIGNS DISP,J/PGRF3	; USER REF?
	VMA_#+AR32-35,#/460,		;NO
		SIGNS DISP,J/PGRF3
.IF/EPT540
=1101
PGRF2:	VMA_#+AR32-35,#/540,		;YES.
		SIGNS DISP,J/PGRF3	; USER REF?
	VMA_#+AR32-35,#/560,		;NO
		SIGNS DISP,J/PGRF3
.ENDIF/EPT540
=1101
PGRF3:	LOAD AR,EPT REF,FE_-1,J/SECPTR	;Initialize APWKC bits, get section
	LOAD AR,UPT REF,FE_-1		; pointer from EPT or UPT

;HERE TO FIND PAGE MAP WITH SECTION POINTER

SECPTR:	AR_MEM,SC_#,#/9,SKP INTRPT	;GET SECTION POINTER
=1000	FE_FE AND AR0-8,BR/AR,		;COMBINE ACCESS BITS
		AR0-3 DISP		;SPT INDEX IN ARR, DISP ON TYPE
=1001	AR_SV.BR,J/PFT			;NO ACCESS TO SECTION (OR INTRPT)
=1011
SECIMM:	ARX_SHIFT,ARL_0.M,J/PGRF5	;IMMEDIATE
=1101	ARL_0.M,J/LDIND			;SHARED
=1111	ARL_0.M				;INDIRECT SECTION POINTER
;
;	WARNING:  do not use the technique at LDIND to allow
;	interrupts out of section pointer loops, as that will have
;	adverse effects on byte transfers and console executes.
;
	VMA_AR+SBR,AR_ARX		;LOOK IN SPT
	BR/AR,AR_BR,LOAD AR,PHYS REF	;CALL FOR SPT ENTRY
	ARX_SHIFT,AR_MEM		;SEC PTR INDEX TO ARX0-8
	AR_SHIFT,ARX_BR			;NEW SEC PTR ADDR TO AR
	GEN # AND AR0-8,#/77,SKP SCAD NE,
		VMA_AR
=0	LOAD AR,PHYS REF,J/SECPTR
	AR_SV.BR,J/PFT			;TRAP, SEC MAP NOT IN CORE
;
;	We must turn off special cycle for indirect pointers so that
;	we can take an interrupt.  However, we can't do it if PXCT or
;	SXCT might be active.  Thus, a kernel mode program can get into
;	a page fail loop that the microcode cannot exit.
;
=0
LDIND:	VMA_AR+SBR,J/LDIND1		;FOR INDIRECT PAGE POINTERS
	CLR SPECIAL CYCLE,J/LDIND
;
;	This fixes the glitch that INSTR FETCH (NICOND) doesn't
;	clear 'CON4 INT DISABLE L' before fetching user's instruction.
;					;SHARED SEC = INDRCT PAG
LDIND1:	LOAD AR,PHYS REF		;GET PAGE MAP ADDR
	AR_MEM,J/SECIMM


;HERE WITH PAGE NO OF PAGE MAP IN AR,
; VIRTUAL PAGE NO WITHIN SECTION IN ARX0-8

.IF/NOCST
PGRF5:	TEST CBR			;[247] CBR = 0 MEANS NO CST UPDATE
.IF/BIG.PT				;[346]
=0	AR_ARX,FE_FE AND #,#/174,	;[247][333] NO CST UPDATE
		J/NO.CST		;[247]
.IFNOT/BIG.PT				;[346]
=0	AR_ARX,FE_FE AND #,#/164,	;[247] NO CST UPDATE. Eat bit 5
		J/NO.CST		;[247] if no big page table
.ENDIF/BIG.PT				;[346]
.IFNOT/NOCST				;[247]
PGRF5:
.ENDIF/NOCST				;[247]
	VMA_AR+CBR,AR_ARX		;GENERATE CST ADDRESS
	GEN # AND AR0-8,#/77,		;IS PAGE MAP IN CORE?
		SKP SCAD NE
=0	LOAD AR,PHYS REF,		;GET CST ENTRY FOR PAGE MAP
		BR/AR,J/PGRF6		;SAVE PAGE PTR ADDR IN BR
	AR_SV.BR,J/PFT			;NOT IN CORE, PAGE FAIL TRAP
;
.IF/BIG.PT				;[346]
PGRF6:	AR_MEM,FE_FE AND #,#/174	;[333]HERE IF CST FOR PAGE MAP
.IFNOT/BIG.PT				;[346]
PGRF6:	AR_MEM,FE_FE AND #,#/164	;HERE IF CST FOR PAGE MAP. No K bit
.ENDIF/BIG.PT				;[346] if no big page table
	AR_AR AND CSMSK,SKP P NE	;BEGIN CST UPDATE
=0	AR_SV.BR,J/PFT			;AGE TRAP, MAP BEING SWAPPED
	AR_AR OR PUR,STORE		;PUT CST WORD BACK
.IFNOT/NOCST				;[247]
	MEM_AR,VMA_BR,PHYS REF		;PHYS REF MAKES MODEL.A LOAD
					;LONG VMA
	LOAD AR,PHYS REF		;GET PAGE MAP ENTRY
	AR_MEM,FE_FE OR #,#/100,	;PAGE POINTER
		SKP INTRPT		;CHECK FOR LONG INDIRECT
					;POINTER
.IF/NOCST				;[247]
	MEM_AR,VMA_BR,PHYS REF,J/NOCST0	;PHYS REF MAKES MODEL.A LOAD
					;LONG VMA
NO.CST:	GEN # AND AR0-8, #/77,		;[247] page map in core ?
		VMA_AR,SKP SCAD NE	;[247]
=0
NOCST0:	LOAD AR,PHYS REF, J/NOCST1	;[247] GET PAGE MAP ENTRY
	AR_SV.BR, J/PFT			;[247] not in core, pf trap
NOCST1:	AR_MEM,FE_FE OR #,#/100,	;[247] PAGE POINTER
		SKP INTRPT		;[247] CHECK FOR LONG INDIRECT
.ENDIF/NOCST				;[247] POINTER
;
;	HERE WITH PAGE MAP ENTRY IN AR
;	FE HAS ACCUMULATED ACCESS BITS -- APWKC*4
;	SC CONTAINS 9.
;
=1000	FE_FE AND AR0-8,AR0-3 DISP,	;COMBINE PWKC, DISP ON TYPE
		ARX_SV.VMA,TIME/3T	;[346] GET BACK SAVED VMA
=1001	AR_SV.BR,J/PFT			;0=NO ACCESS (OR HERE ON INTRPT)
=1011
LDIMM:	ARL_SHIFT,FE_FE SHRT,		;1=IMMEDIATE, LOAD PT
		ARX_ARX*2 COMP,		; GET -WR REF TO ARX03
		SC_#,#/4,J/LDPT		;[333] Set to move K bit
=1101	ARL_0.M,J/LDSHR			;2=SHARED, GET SPT ENTRY
=1111	ARL_0.M,ARX_SHIFT,SKP USER,	;3=INDIRECT, LOOP
		J/LDIND
;
;	HERE TO GET SHARED PAGE POINTER OUT OF SPT
;
LDSHR:	VMA_AR+SBR			;ADDRESS OF SPT ENTRY
	LOAD AR,PHYS REF
	AR_MEM,FE_FE OR #,#/100,J/LDIMM	;TREAT SPT ENTRY AS IMMED

;
;	HERE WITH IMMEDIATE PAGE NO IN AR TO LOAD INTO PT
;

LDPT:	GEN # AND AR0-8,#/77,SKP SCAD NE;Test storage medium
.IF/BIG.PT				;[333]
=0	ARL_0.M,GEN FE AND SC,		;[333]In core. Is Keep bit set?
		SKP SCAD NE,J/LDPT1
.IFNOT/BIG.PT
=0	ARL_0S,J/LDPT1
.ENDIF/BIG.PT				;[333]
	AR_SV.BR,J/PFT			;PAGE NOT IN CORE
;
.IF/BIG.PT				;[333]
=0
.ENDIF/BIG.PT
LDPT1:	ARX_AR,AR_ARX*.25,SC_1,J/KMOVED	;[333]No K. GET -WR REF TO AR05
.IF/BIG.PT
	AR0-8_#,#/10,FE_FE-SC,J/LDPT1	;[333]K set. Move to bit 5 for now
.ENDIF/BIG.PT
;
.IF/NOCST				;[247]
KMOVED:	TEST CBR, SC_P AND SC		;[247][333]CBR = 0? (-WR REF TO SC)
=0	SC_-SC,AR_ARX,ARX_AR (AD),
		J/NOUPDT		;[247] YES, SKIP SOME
.IFNOT/NOCST				;[333]
KMOVED:					;[333]
.ENDIF/NOCST				;[247]
	VMA_ARX+CBR,AR_ARX,SC_P AND SC	;PAGE IN CORE. SC_-WR REF
;
;	NOW GET CST ENTRY FOR THIS PAGE.
;
GTCST:	LOAD AR,PHYS REF,ARX_AR SWAP,	;Shuffle K over to bit 23
		SC_-SC,AR_1		;SC=0 IF WR REF, ELSE -1
	GEN FE AND #,#/10,SKP SCAD NE,	;SKIP IF WRITABLE
		BR/AR,MB WAIT		;GET CST ENTRY & BIT FOR TESTING
=0	GEN P AND SC,SKP SCAD NE,	;FAIL IF WRITING OR AGE=0
		AR_AR AND CSMSK,J/NOTWR	;STRIP OLD AGE FROM CST
;
;	[303] Looks like it's writable.  Make one final check by looking
;	at bit 18 of the CST entry, and abort if it's not set.
;
	TEST AR.BR,SKP CRY0,		;POSSIBLY WRITABLE--SKIP IF CST
		GEN #-SC,#/-1,BYTE DISP	; WRITTEN OR THIS IS WRITE REF
=110	FE_FE-#,#/4,J/STCST		;[305] TEMPORARILY UNWRITABLE, SET S
.IF/CST.WRITE				;[314]
	AR_AR*BR,AD/OR,FE_FE OR #,#/4,	;SET CST WRITTEN AND SOFT BITS
		SKP AR18		;IS IT REALLY WRITABLE? [303]
=0	AR_SV.BR,J/PFT			;NOT REALLY. BAIL OUT
.IFNOT/CST.WRITE			;[314]
	AR_AR*BR,AD/OR,FE_FE OR #,#/4	;[314] Set CST written and soft bits
.ENDIF/CST.WRITE			;[314]
STCST:	AR_AR AND CSMSK,SKP P NE	;[305] WRITABLE. CLEAR, TEST OLD AGE
;
;	[322] At this point we should check whether we got here as a result
;	of an age trap (in which case we just take the page failure) or not,
;	in which case the failure was due to a write reference and we should
;	set bit 2 (the A bit) in the PFW.  This is not currently done
;	because (1) nobody needs it now, and (2) we are very short on CRAM
;	space.
;
=0
NOTWR:	AR_SV.BR,J/PFT			;WRITE OR AGE TRAP
.IFNOT/NOCST				;[247]
	AR_AR OR PUR,STORE		;SET USE BITS, STORE BACK CST
	MB WAIT,VMA_SV.VMA,		;RELOAD VMA FOR ORIGINAL REF
		AR_SV.VMA,SC_1		;READY TO TEST VMA USER
	GEN P AND SC,SKP SCAD NE,	;TEST VMA USER, copy page # to ARL,
		AR_ARX,			;[333] K to AR bit 23, APMWC0 TO SC
		SC_FE,ARX_AR (AD)	; MAP BIT TO ARX
=0	P_P OR SC#,EXEC REF,J/WRHPT	;BUILD PT ENTRY, CLEAR VMA USER
	P_P OR SC#,USER REF		; OR SET USER, AS NECESSARY
WRHPT:	WR PT ENTRY,FE_#,#/10,AR_ARX*4	;UPDATE HARDWARE TABLE
.IF/NOCST
	AR_AR OR PUR,STORE,J/WRHPT	;[247]SET USE BITS,
					; STORE BACK CST
;
NOUPDT:	GEN FE AND #, #/10, ARX_AR SWAP,
		AR_ARX (AD),SKP SCAD NE	;[247] SKIP IF WRITABLE
=0	AR_SV.PFW,GEN P AND SC,		;[322] Get saved PFW and
		SKP SCAD NE,J/NOT.WR	;[247]FAIL IF WRITING
	FE_FE OR #, #/4, J/WRHPT	;[247]SET WRITABLE BIT
;
WRFAIL:	SV.PFW_AR,J/NOTWR		;[322]Restore PFW and page fail
;
=0					;[323]
NOT.WR:	AR0-8_# OR AR0-8,#/100,J/WRFAIL	;[322]Write failure. Set A in PFW
WRHPT:	RSTR VMA_SV.VMA,AR_ARX,SC_FE	;RELOAD ORIGINAL VMA
	P_P OR SC			;[333]COMBINE APMWC WITH PAGE #, K
	WR PT ENTRY			;UPDATE HARDWARE PAGE TABLE
.ENDIF/NOCST
;HERE WHEN MAP INFO WRITTEN INTO HARDWARE PAGE TABLE
; WE NOW NEED ONLY RESTORE THE REGISTERS WE HAVE USED, AND RESTART THE
; MEMORY REFERENCE WHICH FAILED, RETURNING TO THE MICROINSTRUCTION
; WHICH WAITS FOR ITS COMPLETION.  (EXCEPT FOR MAP)

.IFNOT/MODEL.B
	GEN FE AND S,SKP SCAD NE,	;TEST FOR MAP INSTR
		AR_SV.SC
.IF/MODEL.B
	AR_SV.SC
.ENDIF/MODEL.B

;HERE TO RESTORE REGISTERS AND RESTART REFERENCE WHICH FAILED

=0	SC_EXP,FE_EXP,SKP AR0,		;RESTORE FE
		AR_AR SWAP,ARX_SV.BR,J/PGRST1
.IFNOT/MODEL.B
	AR_SV.VMA,ARX_SV.VMA,J/COMPEA	;*MAP* RESTART FROM AREAD
.IF/MODEL.B
=
.ENDIF/MODEL.B
=0
PGRST1:	SC_EXP,SKP AR0,			;RESTORE SC
		AR_ARX,ARX_SV.AR,J/PGRST2
	FE_-SC-1,J/PGRST1		;MAKE FE NEG
=0
PGRST2:	BR/AR,AR_ARX,			;RESTORE BR AND AR
		ARX_SV.ARX,J/PGRST3	; AND ARX
	SC_-SC-1,BR/AR,AR_ARX,		;NEGATE SC
		ARX_SV.ARX

;HERE RETURN TO POINT OF FAULT.  THERE MUST BE EXACTLY ONE MICRO-
; INSTRUCTION, OF 2 OR 3 TICKS, BETWEEN THE REQUEST AND THE RETURN.
; AT LEAST ONE IS REQUIRED TO GET NICOND LOGIC SET UP CORRECTLY IN
; CASE THIS IS A FETCH, BUT THERE MUST NOT BE TIME FOR A READ TO
; READ REFERENCE TO COMPLETE, BECAUSE THE MB WAIT INSTRUCTION TO WHICH
; WE RETURN MAY EXPECT TO GET SOMETHING OUT OF AR OR ARX BEFORE THE
; MBOX RESPONSE.  SEE DPB1.

PGRST3:	REQ SV.VMA			;RESTART FAULTED REQUEST
	SET ACCOUNT EN,RETURN0		;RETURN TO POINT OF FAILURE


;HERE ON A TRAP CONDITION DETECTED BY REFILL LOGIC
;AR CONTAINS SAVED BR

PFT:	BR/AR,VMA_SV.VMA,		;RESTORE BR & VMA
		SR DISP,J/CLEAN		;TAKE TRAP
.TOC	"KI-MODE PAGE FAIL HANDLING"

.IFNOT/KLPAGE
.IFNOT/MODEL.B
2377:	CLR ACCOUNT EN,FORCE AR-ARX,J/PFSAVE
.IF/MODEL.B
3777:	CLR ACCOUNT EN,FORCE AR-ARX,J/PFSAVE
.ENDIF/MODEL.B
1777:	CLR ACCOUNT EN,FORCE AR-ARX	;DON'T CHARGE PAGE FAIL TO USER
PFSAVE:	SV.AR_AR,AR_ARX			;PRESERVE AR, ARX
	SV.ARX_AR,SR DISP,J/CLEAN	;NOW CHECK FOR CLEANUP REQUIRED

.ENDIF/KLPAGE
;HERE ON PAGE FAIL OR INTERRUPT WHICH REQUIRES CLEANUP IN ORDER
; TO BE CORRECTLY RESTARTABLE AFTER SERVICE...

=1*0000
CLEAN:	FE_#,#/37,SKP INTRPT,J/PGF1	;HERE FOR INTRPT OR PGF?

;(1) HERE ON EDIT SOURCE FAIL

	AR_SRCP,SR_0,J/BACKS		;BACK UP SRC POINTER

;(2) HERE ON ANY FAILURE IN DECIMAL TO BINARY

	AR_BR LONG,SR_1,J/D2BPF		;GET ACCUMULATED BINARY

;(3) HERE ON DST FAIL IN BINARY TO DECIMAL FILL

	AR_DLEN COMP,SR_#,#/4,J/B2DFPF

;(4) HERE ON EDIT DST FAIL WITH NO SRC POINTER UPDATE

	SR_0,J/BACKD			;BACK UP DST POINTER ONLY

;(5) HERE ON EDIT DST FAIL AFTER UPDATING SRC POINTER

	SR_1,J/BACKD			;BACK UP DST, THEN SRC

;(6) HERE ON DESTINATION FAILURE IN BINARY TO DECIMAL

	SR_BDT,J/BACKD			;BACK UP DST, THEN SAVE FRACTION

;(7) HERE ON BLT FAILURE
.IF/KLPAGE
	ARX_SV.ARX,J/BLTPF		;GET DEST ADDR AGAIN
.IFNOT/KLPAGE
BLTPF:	AR_ARX+BR,SR_0,J/BLTPF1		;CURRENT SRC ADDR
.ENDIF/KLPAGE
;(10) HERE ON TRANSLATION FAILURE IN BINARY TO DECIMAL

	AR_BR LONG,SR_0,J/B2DPF		;GET BINARY FRACTION

;(11) HERE ON SRC FAILURE IN COMPARE OR MOVE STRING

	AR_DLEN,SR_1,J/STRPF		;PUT LENGTHS BACK, THEN BACK SRC

;(12) HERE ON DST FAILURE IN COMPARE OR MOVE STRING

	AR_DLEN,SR_#,#/4,J/STRPF

;(13) HERE ON DST FAILURE AFTER UPDATING SRC IN COMPARE OR MOVE

	SR_SRC,J/BACKD			;BACK DST, THEN HANDLE AS SRC FAIL

;(14) HERE ON DST FILL FAILURE IN MOVRJ

	AR_DLEN,SR_#,#/4,J/STRPF4
.IF/KLPAGE
;(15) HERE ON PAGE FAILURE IN MAP INSTRUCTION.  RETURN PAGE FAIL WORD

	AR_SV.PFW,SKP IO LEGAL,J/MAP2	;RETURN PFW IN AC
.ENDIF/KLPAGE
.IF/XADDR
;(16) HERE ON PAGE FAIL IN XBLT

	AR_BR LONG,SR_0,J/XBLTPF
.ENDIF/XADDR
.IF/MODEL.B
;(17)	HERE ON FAILURE IN WORD MOVE STRING 

	AR_DLEN,SR_0,J/STRPF4
.ENDIF/MODEL.B
=
;HERE ON ANY PAGE FAILURE OR PI REQUEST IN LONG INSTRUCTIONS
; SKIP IF PI REQUEST, WHICH TAKES PRIORITY

.IF/KLPAGE
=0
.IFNOT/SHIFT.MUUO
PGF1:	MB WAIT,VMA_#,#/500,J/PGF2
.IF/SHIFT.MUUO
PGF1:	MB WAIT,VMA_#,#/501,J/PGF2	;SHIFT TO CLOSER MATCH XADDR FORM
.ENDIF/SHIFT.MUUO
	SET ACCOUNT EN,J/TAKINT		;CLEANUP DONE, SERVE INTRPT
PGF2:	AR_SV.PFW,SKP PI CYCLE,J/PGF4	;GET BACK PAGE FAIL WORD
.IFNOT/KLPAGE
=0
PGF1:	GET ECL EBUS,CLR SC,
		PF DISP,J/PGF2
	SET ACCOUNT EN,J/TAKINT		;HERE TO SERVE INTRPT, DO IT
=1100
PGF2:
=01	AR_SV.AR,FE_FE-1,		;AR PARITY ERROR
		SKP RPW,J/PGF6		;DO WE NEED TO RESTART RPW?
=10	VMA_VMA HELD,MAP,SC_FE		;ARX PARITY ERROR, PF CODE 37
PGF3:	MB WAIT,VMA_#,#/500
	AR_EBUS REG			;READ PAGE FAIL WORD
	REL ECL EBUS
	P_P OR SC,SKP PI CYCLE		;STUFF ERROR CODE IF PARITY
.ENDIF/KLPAGE
=00
PGF4:	ARX_AR,AR_VMA HELD,SC_#,#/13.,	;READY TO COMBINE PF WORD
		CALL,J/ROTS		; WITH ADDRESS
	ARX_AR,AR_VMA HELD,SC_#,#/13.,	;READY TO COMBINE PF WORD
		J/IOPGF			; WITH ADDRESS
=11	AR_SHIFT,ABORT INSTR		;RECOVER TRAP FLAGS, IF ANY
.IFNOT/XADDR
	STORE,UPT REF			;PUT PAGE FAIL WORD AT 500
	FIN STORE,AR_PC,
		VMA_VMA+1,STORE		;STORE OLD PC AT 501 OR 502
	FIN STORE,AR_0S,
		VMA_VMA+1,LOAD AR	;GET NEW PC FROM 502 OR 503
	SET ACCOUNT EN,J/NEWPC
.IF/XADDR
	STORE,UPT REF,ARX_PC		;PAGE FAULT WORD TO 500
	AR_ARX ANDC ADMSK,MB WAIT,	;GET PC FLAGS FOR STORING
		BRX/ARX,ARX/AD		;FULL PC IN BRX, FLAGS IN ARX
	AR_0.S,SKP USER
=0	AR12-17_PREV SEC,CALL [ARSWAP]	;[334] GET PCS IF EXEC MODE
	ARL_ARXL,ARR_ARR,		;FLAGS WORD IN AR
		VMA_VMA+1,STORE		;STORE FLAGS WORD IN 501
	AR_ARX*BRX,AD/ANDCA,		;GET PC ADDRESS
		VMA_VMA+1,STORE		; STORE IT IN 502
	AR_0S,VMA_VMA+1,LOAD AR		;GET NEW PC ADDRESS FROM 503
	SET FLAGS_AR			;CLEAR ALL FLAGS
	AR_MEM,SET ACCOUNT EN,J/ARJMP	;NEW ADDRESS FOR PC
.ENDIF/XADDR

.IFNOT/KLPAGE

;HERE ON PARITY ERROR IN AR.  SKIP IF READ-PAUSE-WRITE IN PROGRESS
=0
PGF6:	VMA_VMA HELD,MAP,		;AR PARITY ERROR
		SC_FE,J/PGF3		;PF CODE 36
	STORE,J/PGF6			;COMPLETE CYCLE, WITH GOOD PAR
.ENDIF/KLPAGE
.TOC	"PAGE FAIL/INTERRUPT CLEANUP FOR SPECIAL INSTRUCTIONS"

;HERE ON PAGE FAIL DURING PI CYCLE

.IFNOT/MODEL.B			 	;[224][274]
IOPGF:	AR_SHIFT,ARX_SHIFT,SC_#-SC,	;TROUBLE... CREATE PAGE FAIL WORD
		#/36.
	AR_SHIFT,SET IO PF
	SV.IOPF_AR,J/IOPFIN		;FINISH  IOPF ROUTINE
.IF/MODEL.B				;[224] DO FANCY STUFF FOR DTE.
IOPGF:	AR_FM[SV.IOP]			;[274] GET THE SAVED API WORD
	SV.IOPF_AR			;[224] SAVE IT IN AC BLK 7.
	BR/AR,AR_SV.AR			;[224] KEEP IOPF WORD AROUND,
	SET IO PF			;[224][274] HANDLE DTE.

;[223] THIS RESTARTS THE DTE'S CLOCK TO PREVENT A DEX FAILURE.
=10	SET DATAO,CALL,J/EBUSO		;[223] SEND THE DATA TO THE DTE.
	AR_BR,SET ACCOUNT EN,J/PIDONE	;[223] AND FINISH THE INTRPT.
.ENDIF/MODEL.B				;[224]


	;HERE ON BLT PAGE FAIL

.IF/KLPAGE
BLTPF:	AR_ARX+BR,SR_0			;CURRENT SRC ADDR
.ENDIF/KLPAGE
BLTPF1:	AR_ARX (AD),ARL_ARR
PGFAC0:	AC0_AR,SR DISP,J/CLEAN		;BEGIN NORMAL PF WORK

;HERE ON XBLT PAGE FAIL OR INTERRUPT
.IF/XADDR

XBLTPF:	AC1_AR,AR_ARX
	AC2_AR,J/CLEAN
.ENDIF/XADDR

;HERE ON VARIOUS CASES OF STRING/EDIT FAILURE

BACKS:	P_P+S
	SRCP_AR,SR DISP,J/CLEAN		;RE-DISPATCH FOR MORE

BACKD:	AR_DSTP
.IF/MODEL.B
	P_P+S.C,SEL DSTP		;PRESEL NUM FIELD FOR HARDW GLITCH
.IFNOT/MODEL.B
	P_P+S
.ENDIF/MODEL.B
	DSTP_AR,SR DISP,J/CLEAN

D2BPF:	AC3_AR,AR_0S,SC_#,#/35.		;PUT AWAY HIGH BINARY
	AR_SHIFT,ARX_-SLEN		;LOW TO AR, REMAINING LEN TO ARX
.IF/MODEL.B
	SEL DSTP			;PRESEL NUM FIELD FOR HARDW GLITCH
.ENDIF/MODEL.B
	AC4_AR,AR_ARX,J/STRPF2		;PUT LOW AWAY

B2DFPF:	AR_AR*T0,AD/OR,J/B2DPF2

B2DPF:	AC0_AR,AR_ARX			;HIGH FRACTION TO AC
	AC1_AR				;LOW TO AC1
	AR_AC3				;GET FLAGS
B2DPF2:	AR_AR*SLEN,AD/A-B,J/STRPF3	;REBUILD FLAGS+LEN

STRPF:	BR/AR,AR_-SLEN,SKP AR0		;WHICH IS LONGER?
=0
STRPF1:	AC3_AR,AR_AR+BR,J/STRPF2	;SRC LONGER
	ARX_AR,AR_AR*SFLGS,AD/OR	;DST.  BUILD SRC LEN+FLAGS
	AC0_AR,AR_ARX-BR		;THAT'S AWAY, MAKE DST LEN
STRPF3:	AC3_AR,SR DISP,J/CLEAN		;OK, NOW BACK UP SRC IF REQ'D

STRPF2:	AR_AR*SFLGS,AD/OR,J/PGFAC0

STRPF4:	BR/AR,AR_SLEN COMP,SKP AR0,J/STRPF1