ER[PISYS];

*I = 99 + 32 DATA IM ENTRIES

*RIGHT BANK ALLOCATION
*10 DISK CHECKSUM REGISTERS, THEN
RVN[RTEMP]; RVN[RTEMP1]; RVN[ICTR]; RVN[OLDPC];
RVN[REFADR]; RVN[RPGRT]; RVN[RPGRT2]; RVN[RPGRT3];


*LEFT BANK ALLOCATION
*20 AC'S, THEN
LVN[LTEMP]; LVN[LEFADR]; LVN[LPGRT]; LVN[LPGRT2]; LVN[LPGRT3];
LV[-1L,777777 777777];


%SCRATCH MEMORY ALLOCATION
WORDS 0-17 AND 400-777 ARE NOT ADDRESSABLE EXCEPT BY USING THE Y REGISTER.
WORDS 0-43 HOLD VALUES 2↑N WHERE N = THE LOCATION.
WORDS 0-327 HOLD CONSTANTS,  330-376 HOLD VARIABLES.  WORDS 400-600
ARE USED BY THE DISK DRIVER MICROCODE TO KEEP TRACK OF THE STATE OF THE
8 DISK UNITS.  EACH UNIT GETS A BLOCK OF 20B WORDS.  600-643 INTTAB;
644-652 IONTAB;
WORD 17 OF EACH DISK BLOCK FOR INSTRUCTION COUNTERS,
WORD 16 FOR EVENT COUNTERS.
WORD 15 FOR BLISP STATE DISPATCH
%

SM[IOTD,653];	*IO DISPATCH TABLE FOR OPCODES 700 AND 712
SM[BLDISP,677];	*BLISP OPCODE DISPATCH
SM[BLOPXT,713];	*BLISP OPCODE EXTENSION
*! MAXC1 ONLY
SM[CHKTAB,753];	*CHECKER CONTROL TABLE
*!
*~ MAXC2 ONLY
SM[CHKTAB,752]; *CHECKER CONTROL TABLE
*~
SM[KCOMS,766];	*DISK COMMAND TRIPLE DISPATCH TO 777

TARGET[SLC];

%THIS TABLE IS USED TO CONVERT INTEGER I INTO 2↑I.  THIS IS NEEDED
TO CONVERT DEVICE NUMBERS INTO DEVICE BIT MASKS.  ALSO, MOST OF THE
ONE BIT NUMBERS ARE USED ELSEWHERE IN THE MICROCODE.
%
1V; 2V; 4V; 10V; 20V; 40V; 100V; 200V; 400V; 1000V; 2000V; 4000V;
10000V; 20000V; 40000V; 100000V;
SV[200000S,200000]; SV[400000S,400000]; SV[1 000000S,1 000000];
SV[2 000000S,2 000000]; SV[4 000000S, 4 000000];
SV[10 000000S,10 000000]; SV[20 000000S,20 000000];
SV[40 000000S,40 000000]; SV[100 000000S,100 000000];
SV[200 000000S,200 000000]; SV[400 000000S,400 000000];
SV[1000 000000S,1000 000000]; SV[2000 000000S,2000 000000];
SV[4000 000000S,4000 000000]; SV[10000 000000S,10000 000000];
SV[20000 000000S,20000 000000]; SV[40000 000000S,40000 000000];
SV[100000 000000S,100000 000000]; SV[200000 000000S,200000 000000];
SV[400000 000000S,400000 000000];

%TABLE OF L.H.'S FOR "WPC" USED BY "LENTER".  B[0,10] HOLD THE CYCLE VALUE
FOR POSITIONING THE CURRENT BYTE; B[11,14] HOLD 1 (LOADED INTO AC);
B[16,20] HOLD A COUNT WHICH OVERFLOWS INTO THE INDIRECT BIT ON
ADVANCING FROM BYTE 4 TO BYTE 0 OF THE NEXT WORD; B[21,22] HOLD
THE LOW BITS OF PC FOR THE PREVIOUS BYTE.  MUST BE BOUNDARY OF 4.
%
B4TAB:	33037 000000V;
	22044 000000V;
	11051 000000V;
	   56 000000V;


SV[-1S,777777 777777];

*CONSTANTS USED EITHER IN PISYS OR IN MORE THAN ONE OTHER FILE
MC[NOVA&H,NOVA,H];
MC[PICYCLE&K,PICYCLE,K];
MC[PIACTIVE&G,PIACTIVE,G];
MC[PIACTIVE&MICRO,PIACTIVE,MICRO];
MC[NOVA&MICRO&H,NOVA,MICRO,H];
MC[UM&J,UM,J];
MC[UM&J&K,UM,J,K];
SM[G,IP[1S]]; ***DEPARAMETERIZED TO MERGE IDENTICAL CONSTANTS
SM[H,IP[2S]]; ***
SM[J,IP[4S]]; ***
SM[K,IP[10S]]; ***
SM[IENABLE,IP[100S]];  ***
SM[MICRO,IP[200S]]; ***
MC[TFLAGSPI,UM,XCTN];
MC[INCMP&K,INCMP,K];
***KLUDGES SO THAT MICROCODE DOESN'T HAVE TO BE ASSEMBLED IN SERIES
MC[CFM&UM&G,CFM,UM,G];		*USED BY SLH AND CONT
MC[BIS&MD0&MD1&MD2&J,MD0,MD1,MD2,BIS,J];	*USED BY CONT
MC[MD2&G,MD2,G];	*USED BY MAP, BLISP
SM[OVF,IP[400000 000000S]];	***USED BY "ARITH" AND "IOCOM"
SM[FOVF,IP[40000 000000S]];	***USED BY "IOCOM"
MC[FINTS,OVF,FOVF,PDOVF];
MC[LOGF&K,LOGF,K];

*INTER-PROCESSOR COMMUNICATION LOCATIONS.

*SM[SWICH,IP[0S]];	*WORD FOR SIMULATED DATA SWITCHES
*SM[LITES,IP[1S]];	*FOR OUTPUT TO SIMULATED LIGHTS
%SM[MTBS,IP[3S]];	*POINTS AT NVIO COMMUNICATION BLOCK (NOT PRESENTLY USED):

(0) TMC CONO WORD
(1) MAXC INPUT MAGTAPE WORD COUNT
(2) NVCHKA ARG FOR NVIO BUGCHK'S
(3) MAGTAPE STATUS INPUT
(4) MTAC1 NOT USED BY MICROCODE
(5,10) PAGE CROSSING REMAP WORDS BITS 0:17 PREVIOUS PAGE, 20:37 NEW PAGE
(11) TODCLK
(12) CDVS
(13) NVIO BUGCHK POINTER
(14,23) MAGTAPE STATUS WORDS
(24) PSCAN
(25) MEMORY ERRORS AS READ BY HARDWARE
(26,31) MCA INPUT BUFFER (BEGIN, MAXC READ, NOVA WRITE, END)
(32,35) MCA OUTPUT BUFFER (BEGIN, NOVA READ, MAXC WRITE, END)
(36,76) MCA BYTES OUTPUT BY MAXC
(77,137) MCA BYTES OUTPUT BY NOVA
(140) NVIO FREE STORAGE
(141,240) MCA HOST TRANSLATION TABLE
(241,264) FLASHING REGISTER CAPTION (80 8-BIT BYTES)
(265,271) FLASHING REGISTER POINTERS
(272) PUP INPUT BUFFER POINTER
(273) PUP OUTPUT BUFFER POINTER
(274) IMP INPUT BUFFER POINTER
(275) IMP OUTPUT BUFFER POINTER
(276) IMP STATUS IN
%
SM[DLSBS,IP[4S]];*POINTS TO 104 WORD BLOCK: MUST NOT CROSS PAGE BOUNDARY
%(0) OUTPUT DONE BIT WORD
(2) DO-OUTPUT BIT WORD
(3) DO-INPUT BIT WORD
100-WORD IN-OUT BUFFER
%
SM[MAXNV,IP[5S]];   *BIT TABLE FOR SIGNALS FROM MAXC TO NOVA

%BITS IN MAXNV (NOT USED BY MICROCODE EXCEPT I/O RESET REQUEST):
(37) PUP BEGIN OUTPUT
(36) PUP BEGIN INPUT
(35) MAXC INTERRUPT CHANGE DEVICE SPEED
(34) IMP BEGIN INPUT
(33) MAXC INTERRUPT MCA OUTPUT
(32) IMP BEGIN OUTPUT
(27) MAXC INTERRUPT CONO TMC REQUEST
(25) MAXC INTERRUPT DLS OUTPUT REQUEST
(24) MAXC INTERRUPT I/O RESET REQUEST
%
SM[NVMAX,IP[6S]];   *BIT WORD FOR SIGNALS FROM NOVA TO MAXC
*7 = PROGRAM STARTING ADDRESS FOR CONSOLE "START"

TARGET[ILC];

*5, 11, 12, AND 13 ARE INITIALIZED BY KINT.

*MICROPROCESSOR SOMETIMES CRASHES AT 0 AND 1 ON FUNNY INTERRUPTS
REPEAT[2,ILC[(BRKP[1], FRZBALUBC, CALL[SCRASH])]];
PPQ:	P←P+Q, RETURN; *BLISP
UPQ:	Q←P OR Q, FRZBALUBC, INHINT, RETURN;
CLRPQ:	Q←P AND NOT Q, FRZBALUBC, INHINT, RETURN;
IM[ILC,6];
PQORP:	RTEMP←P←P OR Q, FRZBALUBC, RETURN;
QNQ:	Q←NOT Q, RETURN; *ARITH
PMDR:	P←MDR, FRZBALUBC, RETURN; *MAP, MAIN, BLISP
IM[ILC,14];
QL1:	Q LSH 1, FRZBALUBC, RETURN; *BLISP
PMQ:	P←P-Q, Q←RTEMP, RETURN; *BLISP, MAP


%"SPUNT" CALLED FOR A SOFT HALT.  ;P TO MIDAS PROCEEDS SAFELY.

"SCRASH" CALLED FOR A HARD HALT.  ;P IS A NO-OP AFTER A CRASH.

THE CONCEPT BEHIND PUNT AND CRASH IS THAT A NAIVE USER SHOULD BE ABLE TO
WALK UP AND OPTIMISTICALLY TYPE ;P WITH A REASONABLE HOPE OF RESTARTING
THE SYSTEM AND NO CHANCE AT ALL OF MAKING THINGS WORSE.

"START" (LOCATION 23) LOADS PC FROM MAIN 7 AND RUNS.

"RESET" (LOCATION 21) PERFORMS A PROCESSOR RESET, CLEARING THE MAP, APR,
AND PI SYSTEM, BUT NOT CHANGING THE PC NOR SENDING IORESET TO THE NOVA.
"RESET" FINISHES AT "PUNT" WITH "START" ON THE STACK.

"INIT" CHECKS OUT THE MICROPROCESSOR AND MICROCODE WITH
WHATEVER STUFF IS AVAILABLE, PUNTING IF EVERYTHING IS OK,
CRASHING IF SOMETHING IS FOUND TO BE WRONG.
%

SCRASH:	LPGRT3←P, P←400000S, DGOTO[.+1];
	B←P←P-1, GOTO[.,ALU>=0];
	P←LPGRT3, BRKP[1], FRZBALUBC, GOTO[.];

*NVIO KNOWS RESET=21
RESET:	INHINT, LPGRT3←P, Q←SSRC[LOGT], CALL[PRESC]; *PRESERVE LOGT
	SSINK[LOGT], BQ, CALL[SPUNT];

*NVIO KNOWS START=23
START:	READ←7S, CALL[RETN];
	SSINK[PC], MDR, GOTO[REMAPPC]; *=PC←MDR (BYPASS FORWARD REF. PROBLEM)

INIT:	Q←A0, AC←10S, CALL[CHECK];

*SLOW PUNT TO LET DISK TRANSFERS FINISH (CLOBBERS BALUBC, LPGRT3)
SPUNT:	LPGRT3←P, P←400000S, DGOTO[.+1];
	B←P←P-1, GOTO[.,ALU>=0];
	P←LPGRT3, FRZBALUBC, BRKP[1], RETURN;

%THE PARAMETERS WHICH CAN BE CHANGED BY "SLOC" ARE ASSIGNED LOCATIONS IN THE SM
TABLE BEGINNING AT "SLMIC" AND ARE ENUMERATED BELOW.  THESE VARIABLES, INTCONDH,
PISTAT, MICINTS, NOTFCOND, APRPIMCOND, APRLEV, THE 44 "INTTAB" ENTRIES,
AND 7 "IONTAB" ENTRIES ARE RESTORED FROM AN IM TABLE CALLED "GOTAB" WHENEVER
THE CONSOLE "RESET" FUNCTION IS EXECUTED.
%

SV[RESCNT,23]; *RESTORE COUNT - 1 = SLOC LENGTH + 10 - 1
SM[SLOCLOW,IP[14S]]; *SLOC TABLE LENGTH
SLC[GOTAB: E1[ILC]]; *ORIGIN OF IM TABLE
SET[SLMIC,IP[VSLC]]; *ORIGIN OF SM TABLE

*ORIGIN OF IM TABLE
W[0,0,571,0,0,3000];
SVN[TSTAT];
SVN[MBASE];
W[0,2,0,0,0,4000];
SVN[SPT];
SVN[CST];
W[0,0,70,0,0,71];
SVN[MLTRAP];
SVN[PSWITCH];
W[0,0,1000,0,3,4000];
SVN[JSYST];
SVN[LOGT];
W[0,0,0,0,0,0];
SVN[ST];
SVN[SNIL];
W[0,0,0,0,0,0];
SVN[SKPRGLM];
SVN[TYPTAB];

*THE 10 VARIABLES BELOW ARE ALSO RESTORED BY RESET
W[0,0,22,0,0,0];
SVN[INTCONDH]; *NOVA&H=22
SVN[MICINTS]; *0
W[7777,5777,7777,2200,0,0];
SVN[NOTFCOND]; *NMC[PDOVF]
SVN[APRPIMCOND]; *MC[NXM,POWFB]
W[0,0,0,0,0,7];
SVN[APRLEV]; *0
SVN[@ICTR]; *POINTER TO CURRENT INSTRUCTION COUNTER
  SM[EVCTR,16];	*EVENT COUNTERS STORED IN WORD 16 OF EACH DISK BLOCK
		*0  NO. TIMES MAP LOADED
		*1  COUNT OF CALLS TO "PIX"
  SM[YICTR,17];	*INSTRUCTION COUNTERS STORED IN WORD 17 OF EACH DISK BLOCK
W[0,0,0,0,0,0];
SVN[PISTAT];
SVN[RESV];	*RESERVE LOCATION

SVN[PC];	*PROGRAM COUNTER

SVN[STEMP]; SVN[STEMP1];

%WHEN AN INTERRUPT BEGINS AT SOME PRIORITY LEVEL, A MICROCODED ROUTINE IS
EXECUTED FIRST.  NO HIGHER PRIORITY INTERRUPTS OCCUR UNTIL THE PDP-10 PORTION
OF THE INTERRUPT ROUTINE IS ENTERED THROUGH A PI CYCLE.  ALSO, WHEN TWO DEVICES
ARE ASSIGNED THE SAME PRIORITY, THE ONE WITH THE RIGHTMOST BIT ASSIGNMENT
(SMALLEST DEVICE NUMBER) IS SERVICED FIRST.

THE MICROCODE MAINTAINS TWO SM TABLES:  "IONTABX"+1 POINTS TO A
SEVEN-WORD TABLE WHOSE ENTRIES CONTAIN ONES IN THE BIT POSITIONS
CORRESPONDING TO DEVICES ASSIGNED TO THE PRIORITY LEVEL (WORD 0 IS FOR
PRIORITY 1, WORD 1 FOR PRIORITY 2, ETC.);  "INTTAB" POINTS TO
A 44-WORD TABLE WHOSE ENTRIES CONTAIN A 1-BIT FLAG, AN 11-BIT MICROADDRESS,
AND 24-BIT PARAMETER.  THE BIT POSITIONS IN MICINTS AND IN NVMAX ALSO
CORRESPOND TO THESE DEVICES.  THE FLAG=0 WILL SET G=1 ON INTERRUPTS AND
SIGNALS "PICYC" NOT TO CLEAR THE INTERRUPT REQUEST IN MICINTS.

THE DEVICE NUMBERS AND INTERPRETATION ARE GIVEN BELOW:
0-7	DISKS			KPISV (AUTOMATIC DISMISSAL)
10	CLOCK			CPICYC (MANUAL DISMISSAL)
11	MAGTAPE			CPICYC
12	UNUSED			CPICYC
13	DLS			PICYC (AUTODISMISSING)
14	IMP INPUT DONE		PICYC
15	IMP OUTPUT DONE		PICYC
16	PUP INPUT DONE		PICYC
17	PUP OUTPUT DONE		PICYC
20-25	UNUSED			PICYC
26	PUSHDOWN OVERFLOW	CPICYC
27	UNUSED			PICYC
30-36	MANUAL INTERRUPTS 7-1	PICYC
37	POWER FAILURE		CPICYC
40	FLOATING OVERFLOW	CPICYC
41	PARITY			CPICYC
42	MEMORY TIMEOUT		CPICYC
43	OVERFLOW		CPICYC

"PICYC" EXECUTES A PICYCLE AT THE ADDRESS CONTAINED IN THE 24-BIT PARAMETER
IN "INTTAB" POINTED TO BY "STEMP1", DISMISSING THE REQUEST IFF G=1.
**K = 1 FOR XCT, G=1 IFF SIGN BIT FROM INTTAB=0.
TIMING = M + 6
I = 6
%
PICYC:	Q←X←STEMP1;
	SETSF[UM&J], Y←Q, P←A1, XMASK;
	Q←P+1, P←MICINTS, INHINT;
	Q←P AND NOT Q, CLEARF[TFLAGSPI], INHINT, CALL[KPIS1,G=1];
	MAPVA←Q←SY, P←777777R, ACFS;
	REFADR←P←P AND Q, SETF[PICYCLE&K], AC←NULL, GOTO[XCT];

%"KPISV" IS ENTERED FROM THE PI SYSTEM CODE WHEN A DISK INTERRUPT IS
SERVICED.  "STEMP1" CONTAINS A POINTER TO THE ENTRY FOR THE DEVICE IN
"INTTAB".  SO [STEMP1]-[INTTAB]-1 = [STEMP1]-600 = [STEMP1] AND 7 = UNIT NUMBER.
"KPISV" IS RESPONSIBLE FOR STORING THE CURRENT DISK ADDRESS
(ONLY THE CURRENT SECTOR, PACK, AND ARM POSITION NEED BE CORRECT) AT
[KBLK] +2 AND FOR EXITING TO A PDP-10 SERVICE ROUTINE VIA A PICYCLE.
EACH DISK UNIT SHOULD BE ASSIGNED BY THE PDP-10 TO A DIFFERENT INTERRUPT
LOCATION (BUT PROBABLY THE SAME PRIORITY LEVEL).  THE REASON WHY SOME STUFF IN
THE SECTOR MICROINTERRUPT SERVICE ROUTINE IS NOT DONE BY "KPISV" (SUCH AS
INCREMENTING THE SECTOR) IS THAT WE ENVISION PDP-10 PROGRAMS MANUALLY
INITIATING DISK INTERRUPTS TO ACCOMPLISH COMMAND SETUP WHEN NEW REQUESTS
ARRIVE, AND IF THE "KPISV" ROUTINE WERE INCREMENTING THE SECTOR,
IT WOULD HAVE DIFFICULTY DISTINGUISHING BETWEEN A MANUALLY INITIATED
INTERRUPT AND A REAL SECTOR INTERRUPT.
THE PDP-10 DISK INTERRUPT SERVICE ROUTINE SHOULD 0 [KBLK+1] AFTER A
COMMAND COMPLETION SO THAT MANUALLY INITIATED INTERRUPTS DON'T ATTEMPT
TO CLEANUP THAT COMMAND AGAIN.
**MUST NOT CLOBBER G (LEAVE IT =1 FOR PICYC)
I = 5
%

KPISV:	Q←STEMP1, P←A1, BAMASK[3]; *KNOW INTTAB=600
	YKPTR←X←P AND Q; *KNOW DISKS ARE DEVICES 0 TO 7
	P←SSRC[KBLK];
	P←P+1, MDR←SSRC[KA];
	WRITE←P+1, INHINT, GOTO[PICYC];

SM[INTTAB,IP[600S]];	*INTTAB STARTS AT 600 (MUST BE BOUNDARY OF 100)
SV[IONTABX,643];	*IONTAB STARTS AT 644
SV[IMINTT,IP[ILC]];
**THESE ARE PARAMETERIZED IN THE NOVA SOFTWARE AND EASY TO CHANGE
SET[CPICYC,ADD[4000,IP[PICYC]]];
REPEAT[4,ILC[W[IP[KPISV],0,0,IP[KPISV],0,0]]];
MP[CLKB,33]; SV[CLKDV,610]; *APR CLOCK = DEVICE 10B
SM[DLSDV,IP[13S]]; SM[DLSINT,IP[4000S]]; *DATA LINE SCANNER OR CONSOLE TTY INT.
*CLOCK (10), MAGTAPE (11), --- (12), DLS (13)
W[CPICYC,0,0,CPICYC,0,0];
W[CPICYC,0,0,IP[PICYC],0,0];
*IMP INPUT DONE (14), IMP OUTPUT DONE (15), PUP INPUT DONE (16),
*PUP OUTPUT DONE (17), MCA INPUT DONE (20), (21-25 ALSO)
REPEAT[5,ILC[W[IP[PICYC],0,0,IP[PICYC],0,0]]];
*PUSHDOWN OVERFLOW (26) AND UNASSIGNED (27)
W[CPICYC,0,0,IP[PICYC],0,0];
SV[PDLDV,626]; *PUSHDOWN OVERFLOW
W[IP[PICYC],0,56,IP[PICYC],0,54]; *MANUAL INTS. 7 AND 6
W[IP[PICYC],0,52,IP[PICYC],0,50]; *5 AND 4
W[IP[PICYC],0,46,IP[PICYC],0,44]; *3 AND 2
W[IP[PICYC],0,42,CPICYC,0,0]; *1 AND POWER FAILURE
W[CPICYC,0,0,CPICYC,0,0]; *FLOATING OVERFLOW AND PARITY ERROR
W[CPICYC,0,0,CPICYC,0,0]; *NON-EXISTENT MEMORY AND OVERFLOW
SV[APRINTS,760020 000400]; *OVF, NXM, FOVF, PARITY, POWFB, PDOVF, CLKB
SM[OVFDV,IP[IONTABX]];  *OVERFLOW (CONSOLE HALT)

*IONTAB INITIALIZATION
W[100,0,0,40,0,0]; W[20,0,0,10,0,0]; W[4,0,0,2,0,0]; W[1,0,0,0,0,0];


%THE "IREAD" AND "ILOAD" ROUTINES TRANSFER A BLOCK OF WORDS FROM IM
TO SM OR FROM SM TO IM.  ILOAD ISN'T USED CURRENTLY.

ILOAD:	Q←SY, INCY, GOTO[.+1];
	NPC←P, GOTO[RETN,X<0];
	I←Q, DGOTO[.+1], INHINT; *IM[0,43]
	Q←SY, INCY, GOTO[.+1];
	NPC←P, DECX;
	I←Q, DGOTO[ILOAD], P←P+1; *IM[44,107]

WASTE AN INSTRUCTION AFTER EACH READING OF IM BECAUSE OF PROBLEM WHEN
DATA FROM IM SELECTS IM AS A BUS SOURCE OR DESTINATION.  CALLED WITH IM
ADDRESS IN P, COUNT - 1 OF SM REGISTERS TO FILL IN X, POINTER TO SM
BLOCK IN Y
I = 9
%

*! MAXC1 ONLY
IREAD0:	Q←P, DECX, RETURN[X<0];
	SY←Q, INCY, P←LTEMP, RETURN[X<0];
IREAD:	NPC←MDR←P;
	P←I, DGOTO[.+1], LTEMP←P+1, INHINT; *IM[0,43]
	INHINT, GOTO[.+1];	*MUST BE NO-OP
	NPC←MDR, DECX, GOTO[.+1]; *NOT SURE WHETHER GOTO HERE IS NECESSARY
	P←I, DGOTO[.+1], Q←P; *IM[44,107]
	INHINT, GOTO[.+1];	*MUST BE NO-OP
	SY←Q, INCY, GOTO[IREAD0], INHINT;
*!
*~ MAXC2 ONLY
IREAD:	NPC←Q←P, DECX, GOTO[RETN,X<0];
	I, DGOTO[.+1], P←P+1, INHINT; *EREG←IM[0,43]
	MDR←EREG, GOTO[.+1];
	SY←MDR, INCY;
	NPC←Q, DECX, GOTO[RETN,X<0];
	I, DGOTO[.+1]; *EREG←IM[44,107]
	MDR←EREG, GOTO[.+1];
	SY←MDR, INCY, GOTO[IREAD];
*~


*SOME SHORT COMMON SUBROUTINES
*I = 2

QF1:	Q←1S, FRZBALUBC, RETURN; *BLISP
QPQ:	Q←P+Q, RETURN; *KINT

%MAXC CHECKS FOR INTERRUPTS IN EXACTLY THOSE PLACES WHERE THE PDP-10 DOES.
EACH POSSIBLE CAUSE OF AN INTERRUPT IS REPRESENTED BY A "1" IN F,
SO THE CHECK IS ACCOMPLISHED BY THE FOLLOWING SEQUENCE:
   SETSF[INTCONDH];
   GOTO[PI,H=1];
INTCONDH CONTAINS THE NOVA FLAG, THE MICRO FLAG UNLESS NO INTERRUPTS
ARE POSSIBLE, AND THE VARIOUS APR AND PI INTERRUPT CONDITIONS WHEN
THEY ARE INDIVIDUALLY POSSIBLE.  INTCONDH IS CONSTRUCTED BY "CONINTCOND"
FROM PISTAT (WHICH CONTAINS THE P.I.-IN-PROGRESS BITS) AND NOTFCOND
(WHICH CONTAINS A 0 IN EVERY FLAG THAT SHOULD BE TESTED FOR AN INTERRUPT)
AND THE FLAG PIACTIVE.  CONINTCOND IS CALLED WHEN INTERRUPTS ARE INITIATED
OR TERMINATED, CHANNELS ENABLED/DISABLED, OR PI LEVELS OR THE PI SYSTEM
TURNED ON/OFF.

TIMING = AT LEAST 5 CYCLES FOR INTERRUPTED INSTRUCTION OR MORE IF IT
   INTERRUPTED DURING INDIRECTION + 9 + (R IF NOVA=1)
   + [IF PIACTIVE=1, (4 + 4 * NO. LEVELS PASSED OVER IF NO NEW INT. TAKES PLACE)
ELSE (5 * LEVEL NO. + DEVICE NO. + 14 + (5 IF LEVEL # 1)) IF A NEW INTERRUPT
     TAKES PLACE]
I = 25
%

*ENTER HERE FROM MAIN OR INDIRECT LOOP WITH PC IN LTEMP
PI:	P←PC, GOTO[.+1];	*HERE FROM MAIN TO DECREMENT PC BEFORE CHECK
PI1:	P←P-1, Q←777777R, SETSF[NOVA&H], DGOTO[REMAPPC];
	P←NOTFCOND, Q←P AND Q, CALL[PIX];

%CALL HERE FROM INTERPRETERS WITH PC IN Q NOTFCOND IN P AFTER SETSF[NOVA&H].
INTERRUPTS ARE ((MICINTS U [NVMAX]) AND (NOT FINTS)) U (F AND FINTS).
LOOK AT [NVMAX] ONLY IF NOVA=1.  MUST NOT CLOBBER K & LEAVE H=0 IF RETURNS.
CLOBBERS LPGRT, LPGRT3, RPGRT, SETS UP STEMP1, PUTS 100 IN LPGRT2 FOR DSI1.
%
PIX:	OLDPC←PC←Q, GOTO[PI2,H=0];
	RMW←NVMAX, INHINT;
*! MAXC1 ONLY
	Q←P, P←NOT F;
	RPGRT←NOT P AND NOT Q, P←(MDR) U (MICINTS);
*!
*~ MAXC2 ONLY
	Q←P, P←FLAGS;
	P←(MDR) U (MICINTS), RPGRT←P AND NOT Q;
*~
	P←P AND Q, Q←RPGRT, WRESTART, B←MDR, CLEARF[NOVA&MICRO&H], DGOTO[PI3];
*CONSOLE "STOP"
	MDR←NULL, CALL[SPUNT,B<0], SETSF[PIACTIVE&G], INHINT;

*! MAXC1 ONLY
PI2:	Q←NOT F, CLEARF[MICRO];
	LPGRT2←NOT P AND NOT Q, Q←MICINTS, INHINT;
	Q←LPGRT2, P←P AND Q, SETSF[PIACTIVE&G], DGOTO[.+2]; *DGOTO=INHINT
*!
*~ MAXC2 ONLY
PI2:	Q←FLAGS, CLEARF[MICRO];
	LPGRT2←NOT P AND Q, Q←MICINTS, INHINT;
*HAVE TO TOUCH MDR BECAUSE OF STOP LOGIC PROBLEM AT PI5+2
*DGOTO = INHINT HERE
	Q←LPGRT2, P←P AND Q, B←MDR, SETSF[PIACTIVE&G], DGOTO[.+2];
*~

*HERE WITH INTERRUPT REQUESTS IN P OR Q.  SAVE THEM IN MICINTS.  USE RPGRT
*FOR INTERRUPT IN PROGRESS MASK, LPGRT3 FOR INT. REQS. ON PI LEVEL BEING
*CONSIDERED, LPGRT2 TO HOLD THE CONSTANT 100 FOR LATER.
PI3:	YKPTR←1S, Q←P OR Q, INHINT, CALL[EVINC]; *COUNT CALLS TO "PIX"
	MICINTS←Q, RETURN[G=0], P←(10L) LSH [3], A0;
	Q←LPGRT2←P, FRZBALUBC, P←PISTAT;
	Y←IONTABX, LPGRT←P, FRZBALUBC, GOTO[PI5];

*LOOP THROUGH THE 7 ENTRIES OF IONTAB UNTIL EITHER A PI LEVEL AT WHICH AN
*INTERRUPT IS IN PROGRESS IS FOUND (A BIT IN PISTAT WILL BE 1) OR UNTIL
*(MICINTS AND IONTAB[LEVEL])#0.  PISTAT CONTAINS 1'S IN (35,43) FOR INTS.
*IN PROG. (1,7), 1'S IN (26,34) FOR LEVELS OFF (1,7)
	P←SY, P AND Q, RETURN[ALU#0];
	Q←MICINTS, RPGRT←Q, CALL[ZEROP,ALU#0];
	LPGRT3←P AND Q, P←PISTAT, Q←(RPGRT) RSH 1, RETURN[ALU=0];
*PISTAT IN P, 100 IN Q AT ENTRY, LEAVE X=0 FOR DSI1
PI5:	GOTO[.-3,ALU=0], PQ RCY [7], P AND Q, X←NULL, INCY;

*HERE WITH APPROPRIATE INTERRUPT BITS IN LPGRT3, PISTAT BIT IN RPGRT
	Y←INTTAB, Q←RPGRT, P←LPGRT;
	MDR←P OR Q, Q←LPGRT3, SETSF[G], DECY;
	PISTAT←P←MDR, Q RSH 1, INCY, GOTO[.,Q EVEN];
*LEAVE ADDRESS OF MICROCODED PART OF INTERRUPT ROUTINE (NORMALLY "PICYC")
*ON STACK AND RECONSTRUCT INTERRUPT CONDITIONS.  LEAVE G=1 IFF SIGN BIT
*IN INTTAB ENTRY = 0.
	STACK←SY, Q←LPGRT2;
	POP, STEMP1←Y, GOTO[DSI1];

%CALL HERE FROM JRST 10,E.  CLOBBERS LPGRT, RPGRT, LPGRT2, AND MDR
TIMING = 1 + 2*PI LEVEL TURNED ON + CONINTCOND TIMING
I = 23
%
DISMISINT: P←A1, BAMASK[6], SETSF[PIACTIVE&G], X←NULL;
	P←PISTAT, LPGRT2←Q←P+1;
	LPGRT←P AND Q, DGOTO[.,Q EVEN];
	GOTO[.+1,ALU#0], Q RSH 1, MDR←NOVA&H, RPGRT←P AND NOT Q;
	Q←RPGRT, A0, SETF[MICRO];
	P←PISTAT←Q, Q←ICTR, FRZBALUBC, GOTO[DSI2,G=1];

CONINT0: INTCONDH←MDR, ICTR←Q, FRZBALUBC, RETURN; *A0 FOR JRST

%"CONINTCOND" IS ENTERED FROM "SPILEV" (WHEN A DEVICE CHANGES PRIORITY) AND
WHEN PIACTIVE OR PI LEVELS ARE  TURNED ON OR OFF, "DSI1" FROM "PI", AND "DSI2"
FROM "DISMISINT".  WANT TO CHECK "NOVA" FLAG EVEN WHEN NO INTERRUPTS ARE
POSSIBLE SO THAT THE CLOCK, HALT, NONXMEM, PARITY, POWER FAILURE, ETC. SIGNALS
FROM THE NOVA CAN BE PICKED UP.  THESE MAY BE TESTED BY THE PROGRAM.
THERE ISN'T ANY REASON TO CHECK "MICRO" HOWEVER.  SETUP @ICTR TO POINT TO THE
CURRENT PI LEVEL.  "RPGRT", "LPGRT2", X, Y, AND MDR ARE CLOBBERED.
TIMING = 4 IF PIACTIVE = 0, ELSE 15 + 3*PI LEVEL
%
CONINTCOND: SETSF[PIACTIVE&G], P←A1, BAMASK[6], X←NULL;
	LPGRT2←P+1, P←PISTAT, DGOTO[CONINT0,G=0];
DSI1:	MDR←NOVA&H, Q←ICTR, A0;
*FALL THROUGH OR ENTER HERE WITH 100 IN LPGRT2, WITH PISTAT IN P,
*WITH NOVA&H IN MDR
DSI2:	Q←ICTR, YKPTR←@ICTR;
	RPGRT←P, YICTR←Q, Q←LPGRT2;	*SAVE OLD INSTRUCTION COUNTER
	P AND Q, PQ RCY [7], Y←IONTABX, BAMASK[7];
*END TEST AT DSI3+2 DOESN'T WORK FOR PI LEVEL 1
	LPGRT2←P, INCY, GOTO[DSI3,ALU=0];
DSI5:	YKPTR←@ICTR←X;
	Q←YICTR, A0, GOTO[CONINT0];

*LOOP STARTS AT DSI3 WITH LEVELS OFF IN P AND LPGRT2[35,43], WITH PISTAT IN
*LPGRT, WITH 100 IN Q, NOVA&H IN MDR, POINTER TO IONTAB IN Y, 0 IN X
	INCY, P←LPGRT2, GOTO[DSI4,ALU>=0];
DSI3:	P AND Q, P←RPGRT, SAMASK[7], Q RSH 1;
	P-Q, P←MDR, INCX, GOTO[.-2,ALU#0];
	MDR←(P) U (SY), INCY, GOTO[DSI3,ALU<0], P←LPGRT2;
DSI4:	Q←MDR;
	Q←(NOT Q) U (NOTFCOND);
	MDR←(NOT Q) U (NOVA&MICRO&H), GOTO[DSI5];


%"SPILEV" IS CALLED WITH A PRIORITY LEVEL IN P, A MASK OF DEVICES TO BE
ASSIGNED TO THAT LEVEL IN Q, AND A MASK OF DEVICES TO BE ASSIGNED TO
PI LEVEL 0 IN RPGRT3.  RPGRT3 MUST CONTAIN 1'S IN ALL BITS WHERE Q
HAS THEM.  CLOBBERS LPGRT, LPGRT2
CALLED BY CONO APR, CONO PI, SEVERAL JMC'S, SETPIA.
TIMING = 27 CYCLES (- 1 CYCLE IF P=0)
I = 6
%
SPILEV:	Q←Y←IONTABX, LPGRT←Q, DGOTO[6];
	LPGRT2←P+Q, INCY, X←NPC, GOTO[.+3];
	CALL[UPQ,ALU=0], Q←NOT P AND Q, P←LPGRT, DECX;
	SY←Q, INCY, GOTO[CONINTCOND,X<0];
	P←LPGRT2, Q←Y, SETF[MICRO];
	P#Q, P←RPGRT3, Q←SY, GOTO[.-3];


%"SETPARAM" ACCEPTS A POINTER TO AN "INTTAB" ENTRY IN Y AND A 24-BIT
PARAMETER IN "RTEMP".  IT CHANGES THE INTERRUPT PARAMETER VALUE FOR THAT
DEVICE.
TIMING = 4 CYCLES
I = 3
%
SETPARAM: P←A1, BAMASK[30], Q←SY;
	Q←NOT P AND Q, P←RTEMP, SAMASK[30], CALL[UPQ];
	SY←Q, RETURN;