ER[JMC];

*I = 191

TARGET[ILC];

*! MAXC1 ONLY
SV[XPARITY,2160];	*DISK INTERRUPT CHANNELS
*!
*~ MAXC2 ONLY
SV[XPARITY,200 002160];	*DISK INTERRUPTS & PARITY (700 002160 DOESN'T WORK)
*~


%FOR THE IN-OUT RESET ROUTINE, "KRESET" TURNS OFF ALL THE DISK UNITS
BY "KOFF" (BUT DOES NOT RECALIBRATE).
I = 4
%
	DECX, RETURN[X<0];
KRESET:	KUNIT←X, DGOTO[.-1], LTEMP←A1;
	CALL[.+1,X>=0], YKPTR←X, INHINT;
	KSET←KOFFX, KNEWCOMM, INHINT, GOTO[.+3]; **NO KRDYW
%"KOFF" IS A JMC WHICH:
   1.  TURNS OFF SECTOR MICROINTERRUPTS, DISMISSES WORD INT., CLEARS
ERRORS, AND RECALIBRATES UNIT
   2.  CLEARS THE INTERRUPT REQUEST BIT IN MICINTS FOR THIS UNIT
   3.  MAXKA←NULL (SO THAT "KGO" AND "KSEEK" WILL BE REJECTED)
   4.  WIDISP←CRASH (SO THAT FALSE DISPATCH INTS WILL CRASH)
   5.  WCSA←NULL (SO THAT FALSE READ AND WRITE INTS WILL WRITE A HARMLESS
LOCATION AND CRASH)
   6.  NSDISP←NULL (SO THAT FALSE SECTOR INTS WILL CRASH)
   7.  DESELECT THE UNIT
AT CALL:  KUNIT←UNIT NO. HAS BEEN DONE
I = 10
%
KOFF:	X←KUNIT;
	KSET←KOFFL, KNEWCOMM, INHINT;  ***NO KRDYW
	P←LTEMP, AMASK[30], MAXKA←KMDR←NULL, DGOTO[SCRASH];
	WIDISP←NPC, P←P+1, INHINT, GOTO[.+1];
	Q←KSTAT, A1, DGOTO[.+1];
*CHECK "DESEL" TO SEE IF A UNIT IS REALLY THERE, ELSE "KRDYW" WILL HANG
	P AND Q, WCSA←NULL, INHINT, CALL[KRDYW,ALU=0];
	KSET←DESEL, KNEWCOMM, INHINT;
	P←A1, XMASK, INHINT, Q←MICINTS;
	P←P+1, KA←KWDATA, DGOTO[SCRASH];
	Q←NOT P AND Q, INHINT, NSDISP←NPC, GOTO[KPIS1];

%"PKSER" IS A SUBROUTINE TO LOOK AT EACH OF THE DISK UNITS AND DECIDE
ON WHICH UNIT A PARTICULAR DISK PACK IS MOUNTED.

AT CALL: PACK NO. IN RTEMP[12,21], 7 IN X.
AT RETURN: Y POINTS TO THE 16-WORD UNIT ARRAY FOR THE PACK AND KUNIT
POINTS TO THE UNIT, MAXKA IN Q, P PRESERVED.  IF THE PACK IS OFF-LINE, THE
ILLEGAL PACK BIT IS RETURNED IN AC, AND AN IMMEDIATE EXIT IS MADE.
I = 5
%
PKSER:	LPGRT←P, YKPTR←KUNIT←X, P←777777R;
	Q←MAXKA, P←NOT P, BAMASK[32];
	Q←P AND Q, P←RTEMP, DECX, DGOTO[QTOAC,X<0];
	P#Q, Q←ILLPK, DGOTO[PKSER];
	RETURN[ALU=0], P←LPGRT, Q←MAXKA;

%"KON" IS ENTERED WITH THE MAXIMUM LEGAL DISK ADDRESS IN AC FOR UNIT E.
IT RESETS THAT UNIT AND PUTS IT ON-LINE.  IF THE UNIT IS ALREADY ON
LINE IT SERVES TO RESET THE UNIT AS FOLLOWS:
   1.  NSDISP←INTRET;
   2.  ENABLE SECTOR INTERRUPTS AND CLEAR ERRORS
   3.  MAXKA←Q
   4.  CMMA←NMMA←USTATE←0
   5.  ENABLE THE DISK MICROINTERRUPT CHANNELS
   6.  KA←PACK,,7770
KBLK AND KPARAM SHOULD BE SET IN ADVANCE BY THE SLOC JMC
THERE ARE NO ERRORS.  KON ALWAYS SKIPS.
I = 7
%
*YKPTR←KUNIT←E WAS DONE BY JMC DISPATCH INSTRUCTION
KON:	MAXKA←Q, P←LTEMP, AMASK[14], DGOTO[INTRET];
	Q←P OR Q, NSDISP←NPC, INHINT, GOTO[.+1];
	KSET←SECERRS, KNEWCOMM, INHINT;
	ARM←XPARITY, INHINT;
	CMMA←KMDR←NULL, P←LTEMP, AMASK[3], DGOTO[KSEC2];
	USTATE←KWDATA, Q←NOT P AND Q, DGOTO[.+1];
	NMMA←NULL, GOTO[ASKIP];

%"KNOPDP" TURNS OFF THE PDP-10 PORTION OF DISK INTERRUPTS ON THE 
PACK SELECTED BY AC.  ERROR RETURN IF THE PACK NUMBER ISN'T FOUND
OR UNIT BUSY.  OTHERWISE, NSDISP←@INTRET AND SKIP RETURN.
AT CALL: PACK NUMBER IN Q, 377 000000 IN P
I = 5
%
KNOPDP: RTEMP←P AND Q, X←7S, CALL[PKSER];
	MDR←NMMA, DGOTO[KNOP1];
	P←(MDR) U (CMMA), DGOTO[INTRET];

CRJ:	Q←ILLOP;	*COMMAND REJECT
*! MAXC 1 ONLY
ILLRET:	Q←(KSTAT) U (Q) U (USTATE), GOTO[QTOAC];
*!
*~ MAXC 2 ONLY
ILLRET:	P←KSTAT;
	Q←(P OR Q) U (USTATE), GOTO[QTOAC];
*~

%"KSEEK" IS USED TO INITIATE A SEEK AND ENABLE PDP-10 INTERRUPTS.
ERROR RETURNS WITH STATUS IN AC ARE GIVEN FOR:
   1.  PACK NO. NOT ON-LINE
   2.  ILLEGAL ARM POSITION
   3.  SEEKING TO A DIFFERENT ARM POSITION ALREADY
   4.  HARDWARE FAILURE
OTHERWISE, A SKIP RETURN IS GIVEN.
AT ENTRY: DISK ADDRESS (PACK AND ARM) IN Q AND IN AC, 377 000000 IN P
I = 21
%
KSEEK1:	P←(MDR) U (CMMA), DGOTO[KSERV];
KNOP1:	P, Q←NPC, GOTO[.+1];
	P←PC, GOTO[ASKIP1,ALU#0]; *BUSY?
NSDASK:	NSDISP←Q, GOTO[ASKIP];

KSEEK:	RTEMP←P AND Q, P←7770S;
	LTEMP←P AND Q, X←7S, CALL[PKSER];  *LTEMP←NEW ARM POSITION
	RTEMP←P AND Q, Q←KA; *RTEMP←MAX. ARM POS.
	P←P AND Q, Q←LTEMP, MDR←NMMA; *P←CURRENT ARM POS.
	P#Q, P←RTEMP,INHINT;
*SEEK TO CURRENT POS. ENABLES PDP-10 INTERRUPTS IFF THEY ARE OFF
	P-Q, PQ RCY [33], Q←KSTAT, GOTO[KSEEK1,ALU=0];
*CHECK FOR LEGAL ARM POSITION
	GOTO[.+2,ALU>=0], RPGRT2←P, P←NOSKER;
	Q←ILLARM, GOTO[ILLRET];

*CHECK FOR HARDWARE ERRORS OR SEEKING
	P AND Q, P←(MDR) U (CMMA);
	P, P←KA, INHINT, GOTO[ILLRET,ALU#0];
*SECTOR INTERRUPTS TABOO WHILE UPDATING KA
	USTATE←NULL, INHINT, GOTO[CRJ,ALU#0];
	Q←(NOT P) U (7770S), P←LTEMP, DGOTO[KSERV];
	Q←P OR NOT Q, P←RPGRT2, NSDISP←NPC, GOTO[.+1], INHINT;
	KA←Q, Q←P, CALL[KRDYW], INHINT;
*LOAD CYLINDER REGISTER (MUST CALL KRDYW BECAUSE OF SECTOR INTS)
*(KNOW (LOADC) WILL BE F1 = READS WHICH = KNEWCOMM)
*USE "FSET" PURELY AS A GARBAGE ROUTINE TO ALLOW INTERRUPTS WHILE WAITING
	KSET←(Q) U (LOADC), INHINT, CALL[FSET];
	INHINT, CALL[KRDYW];
	KSET←SEEK, KNEWCOMM, INHINT, GOTO[ASKIP];

%"KGO" IS USED TO INITIATE ALL DATA TRANSFERS.  IT CAN BE ISSUED AT ANY TIME
AND NOTHING BAD WILL HAPPEN IF A SECTOR MICROINTERRUPT OCCURS IN
MEDIAS RES.  THE ADDRESS OF THE 9-WORD COMMAND BLOCK IS IN P.
ERROR RETURNS WITH STATUS IN AC ARE GIVEN FOR:
   1.  MAIN MEMORY ADDRESS < 20
   2.  PACK NOT ON-LINE
   3.  ARM # CURRENT ARM POSITION OR SECTOR # NEXT SECTOR
   4.  ILLEGAL HEAD SELECT
   5.  ILLEGAL OPERATION #
AT CALL:  Q CONTAINS VIRTUAL ADDRESS OF A DISK DATA TRANSFER COMMAND FOR
WHICH MAPVA←P←AQ, SAMASK[22] HAS JUST BEEN DONE.  A SKIP
RETURN IS GIVEN IF THE COMMAND IS ACCEPTED.

EACH COMMAND DISPATCH WORD CONTAINS AN INITIAL COMMAND DISPATCH IN B[30,43]
AND 6 4-BIT BYTES IN B[0,27] CONTROLLING THE PATH OF THE DISK FINITE
STATE MACHINE (SEE "DISPT" TABLE IN KINT)
I = 13
%
F[FL,0,3]; F[FM,4,7]; F[FN,10,13]; F[FO,14,17]; F[FP,20,23]; F[FQ,24,27];
M[KOP,XSLC[E1[#1]FL[#2]FM[#3]FN[#4]FO[#5]FP[#6]FQ[#7]]];
SM[XSLC,IP[KCOMS]]; *BEGINNING OF COMMAND DISPATCH TABLE (10 WORDS)
KOP[CSW,15,3];		*WRITE HEADER
KOP[CSW,15,4,12,4,13,3];	*WRITE, WRITE, WRITE
KOP[CSR,10,0,5,2];	*READ, READ
KOP[CSR,10,1,12,3];	*READ, WRITE
KOP[CSR,10,0,5,0,7,2];	*READ, READ, READ
KOP[CSR,10,0,6,0,7,2];	*READ, COMPARE, READ
KOP[CSR,10,0,5,1,13,3];	*READ, READ, WRITE
KOP[CSR,10,0,6,1,13,3];	*READ, COMPARE, WRITE
KOP[CSR,10,1,12,4,13,3];*READ, WRITE, WRITE
KOP[CSR,10,0,6,0,14,2]; *READ, COMPARE, CHECK

SV[KPREH,777400 000000];	*LEADING BITS OF DISK HEADER

***ERROR IF NOT RESIDENT PAGE, BUT NOT NECESSARILY IN MAP
KGO:	CALL[RQARG]; *Q←COMMAND AND DISK ADDRESS
	Q←(Q) U (KPREH), QQ RCY [33], DGOTO[KCOMS];
	RPGRT2←Q, Q←NPC, PQ RCY [0], SAMASK[4], GOTO[.+1]; *RPGRT2←DISK HEADER
*COMMAND REJECT ERROR IF G=1 (COMMAND BLOCK IN AC)
	Y←P+Q, P←RPGRT2, SAMASK[22], GOTO[CRJ,G=1]; *Y←OPER. CODE + KCOMS
	LPGRT←P, Q←SY, GOTO[CRJ,Y>=0];	*Y-REG. OVF IF COMMAND NO. > 11
	LPGRT2←Q, Q←RPGRT2, P←377 000000S; *LPGRT2←NSDISP VALUE
	RTEMP←P AND Q, P←LPGRT, X←7S, CALL[PKSER];
	Q←P, P←Q, BAMASK[22], MDR←ILLHD;
	P-Q, P←RPGRT2, Q←KA, INHINT;
*MUST TURN-OFF INTS. DURING VOLATILE PART
	GOTO[ILLRET,ALU<0], P←P#Q, SAMASK[14], Q←MDR, INHINT;
*KNOW SECTOR AND ARM ARE RIGHT-MOST FIELDS OF ADDRESS
	P, NMMA←MAR, Q←RPGRT2, DGOTO[NSDASK];
	NKA←Q, Q←LPGRT2, P←777777R, AMASK[7], INHINT, GOTO[.+1,ALU#0];
	NMMA←NULL, Q←P+1, GOTO[ILLRET]; *Q←200 = SECNE

*ASSIGN DEVICE X[36,43] TO PRIORITY LEVEL P[41,43], -1 IN RTEMP
ASNLEV: LTEMP←P, Q←FINTS, P←RTEMP, XMASK;
	RPGRT3←P←P+1, FRZBALUBC, DGOTO[.+3,ALU=0];
	P←P AND Q, Q←NOTFCOND, CALL[UPQ,ALU=0];
	Q←NOT P AND Q; *ENABLE FCOND
	NOTFCOND←Q, Q←RPGRT3, P←LTEMP, GOTO[SPILEV];

*ASSIGN AC[14,43] TO BE VALUE OF INTERRUPT PARAMETER FOR DEVICE [P]
ASNLOC: P-Q, Q←INTTAB, DGOTO[SETPARAM];
	GOTO[ILLIO,ALU>=0], Y←P+Q;

*ASSIGN BOTH LEVEL AND LOCATION FOR DEVICE
ALEVLOC: LTEMP←P←P, SAMASK[6], CALL[ASNLOC];
	P←LTEMP, RTEMP←A1, GOTO[ALEVX];

%*READ LEVEL INTO AC[0,13] AND PARAMETER INTO AC[14,43] FOR DEVICE [P]
*DEIMPLEMENTED FOR BYTE LISP.  JMC DISPATCH WAS Q←INTTAB, GOTO[RLEVLOC]
RLEVLOC: X←P;
	Y←P+Q, P←RTEMP, XMASK; *Y←INTTAB+DEV NO.
	Q←SY, P←LTEMP, BAMASK[30], RTEMP←P+1;
	LAC←P AND Q, Y←IONTABX, DGOTO[6];
	X←NPC, Q←A0, P←LAC, INCY, GOTO[.+1];
	Q←SY, LAC←P+Q, INCY, P←RTEMP, RETURN[ALU#0];
	P AND Q, DECX, P←LAC, Q←100 000000S, GOTO[.-1,X>=0];
	P←LAC, SAMASK[30], GOTO[PTOAC];
%

*SUBROUTINE FOR "SETIR" AND "CLRIR"
IOCK:	P←A1, XMASK, Q←FINTS;
	Q←P+1, P←Q, SETFC[MICRO,G=1];
	MDR←P AND Q;
	STEMP←MDR;
	SETFB[STEMP,G=1], GOTO[QMIC,G=1]; *SETF AND GO FOR "SETIR", CLEARF FOR "CLRIR"

%ROUTINE ENTERED WITH BITS IN MICINTS TO CLEAR IN Q, VALUES
TO BE RESTORED TO P AND TO Q IN RTEMP AND LTEMP, RESPECTIVELY.
BALUBC DOESN'T CHANGE.
%
CLRMINT: P←MICINTS, FRZBALUBC, CALL[CLRPQ], INHINT;
	MICINTS←Q, Q←LTEMP, P←RTEMP, FRZBALUBC, RETURN;

*HERE WITH FINTS IN P
*! MAXC1 ONLY
READIR:	Q←NOT F;
	LTEMP←P AND NOT Q, Q←MICINTS;
*!
*~ MAXC2 ONLY
READIR:	Q←FLAGS;
	LTEMP←P AND Q, Q←MICINTS;
*~
	P←NOT P AND Q, Q←LTEMP, GOTO[POQA];

*0 THE BIT FOR DEVICE [X] IN MAXNV AND SIGNAL THE NOVA
SIGNAL:	P←A1, XMASK, RMW←MAXNV, INHINT, CALL[RETN];
	Q←P+1, P←MDR, SIGNOVA, GOTO[PANQM];

*ENABLE/DISABLE INTERRUPTS ON PI LEVELS SELECTED BY E[35,43]
LEVX:	PQ RCY [35], AMASK[16], Q←PISTAT, CALL[UPQ,J=1];
	Q←NOT P AND Q, PISTAT←Q, GOTO[CONINTCOND,J=1];
PISTQ:	PISTAT←Q, GOTO[CONINTCOND];

MC[TTYBSY&K,TTYBSY,K];

*DLS VARIABLES
SVN[DLSOD]; SVN[DLSO]; SVN[DLSIN]; SVN[DLSB];

*RESET APR, PI, MAP, AND DISKS.  DON'T CLOBBER Q, LPGRT3
PRES:	X←RESCNT, RTEMP←Q, DGOTO[SLMIC];
	Y←NPC, CLEARF[-1S], INHINT, GOTO[.+1];
	ARM←NULL, INHINT, CALL[IREAD];
	Y←INTTAB, DGOTO[52];
	X←NPC, GOTO[.+1];
	P←IMINTT, CALL[IREAD];
PRES1:	X←7S, CALL[KRESET];	***WAIT FOR DISK ACTIVITY TO CEASE???
	SETF[IENABLE], GOTO[MAPRESET]; *RETURN "RTEMP" IN Q

%IORESET CLEARS THE CONTROL LOGIC IN ALL PERIPHERAL EQUIPMENT BUT DOES
NOT AFFECT THE PRIORITY INTERRUPT SYSTEM OR PROCESSOR FLAGS.  IT
ALSO MUST RELOAD ALL INTER-PROCESSOR COMMUNICATION VARIABLES WHICH ARE
POINTERS.
***MUST NOT CLOBBER "RTEMP" OR "STEMP1"
%
RESIO:	P←DLSOD←MDR;
IORESET: P←Q←P+1, CLEARF[TTYBSY&K], DGOTO[.+1];
	DLSO←Q, P←Q←P+1;
	DLSIN←Q, Q←P+1, P←LPGRT2, BAMASK[24]; *P←IORESET BIT -1
	DLSB←Q, LPGRT2←P+1;
*CLEAR ALL INTS EXCEPT OVF, NXM, PARITY, FOVF, POWFL, PDLOVF
	Q←17757 777777S, CALL[CLRMINT];
	WRITE←MAXNV, SIGNOVA, Q←LPGRT2, DGOTO[PRES1];
	MDR←P←NOT Q, CALL[SPUNT];

*READ "LOGF" INTO AC[23], "INCMP" INTO AC[24], NOT "PIACTIVE"
*INTO AC[25], PI LEVELS OFF INTO AC[26,34], AND PI-IN-PROG INTO AC[35,43]
PIREAD:	P←PISTAT, Q←P+1, CALL[PQORP,K=1];
	SETSF[PIACTIVE&G], DGOTO[PIRDX];
	Q RSH 1, SETSF[LOGF&K], CALL[PQORP,G=0];

%SET VALUE OF SYSTEM PARAMETER:  0 TO SLOCLOW-1 ARE IN SM TABLE,
413 + 20*UNIT AND 414 + 20*UNIT ARE "KBLK" AND "KPARAM" FOR THE DISK
UNITS RESPECTIVELY.  OTHER VALUES BETWEEN 400 AND 577 ARE RESERVED
FOR MORE DISK PARAMETERS.
%
SETSYSP: P-Q, Q←400S;
	P-Q, Q←600S, GOTO[SETSYS1,ALU<0]; *0 TO SLOCLOW-1?
	P-Q, Q←13S, GOTO[ILLIO,ALU<0]; *400-577?
	Y←P, SAMASK[4], GOTO[ILLIO,ALU>=0];
	P#Q, Q←14S;
	P#Q, Q←LAC, GOTO[QTOSY,ALU=0]; *KBLK?
	GOTO[ILLIO,ALU#0]; *KPARAM?
QTOSY:	SY←Q, RETURN;

SETSYS1: DGOTO[SLMIC];
	Q←NPC, GOTO[.+1];
	Y←P+Q, Q←LAC, GOTO[QTOSY];

*WRITE ABSOLUTE ADDRESS
WABS:  MDR←Q, RETURN;

*READ FROM ABSOLUTE ADDRESS
RABS:  Q←MDR, GOTO[QTOAC];

*MAP VIRTUAL ADDRESS [P] BY USING THE "LOADMAP" ROUTINE.  IF IT TRAPS,
*THE TRAP CAUSE MAY BE ILL. READ, WRITE, OR EXECUTE, BUT THE KIND OF
*ACCESS ATTEMPTED WILL SHOW THAT NOTHING WAS ATTEMPTED.  IT IS NOT
*NECESSARY TO CLEAR THE FORMER MAP ENTRY BEFORE DOING THIS JMC.
MVA:	P←(REFADR←P) U (1 000000S); *PGRMM
	LEFADR←P, P←RTEMP, BAMASK[26];
	Q←NOT P AND Q, CALL[LOADMAP];
	Q←MAP, PQ RCY [0], BAMASK[11];
	PQ RCY [33], SAMASK[26], Q←P, GOTO[POQA];

*AC←INSTRUCTION COUNTER.  P HAS 10, Q HAS E.  E=0 SELECTS LEVEL 1 COUNTER,
*E=1 LEVEL 2, ... , E=6 LEVEL 7, AND E=7 NON-INTERRUPT LEVEL COUNTER.
*E>7 SELECTS THE "CURRENT" INSTRUCTION COUNTER.
RICTR:	P-Q, P←@ICTR, GOTO[WICTR,G=1];
	P#Q, Q←ICTR, GOTO[QTOAC,ALU<=0];
	P←YICTR, GOTO[PTOAC,ALU#0];
	LAC←Q, ENDM;

*INSTRUCTION COUNTER←AC
WICTR:	P#Q, Q←LAC, GOTO[.+2,ALU<=0];
	GOTO[.+2,ALU#0];
	ICTR←Q, RETURN;
	YICTR←Q, RETURN;

*INCREMENT EVENT  COUNTER POINTED TO BY Y AND RETURN
EVINC:	LINT1←P, P←EVCTR, INHINT;
	Q←P+1, P←Q, INHINT;
*WRITE EVENT COUNTER 0-7 IN 16TH WORD OF DISK BLOCKS 0-7
WECTR:	Q←P, EVCTR←Q, P←LINT1, INHINT, RETURN;

*READ EVENT COUNTER E INTO AC
RECTR:	P←EVCTR, GOTO[PTOAC];

%UJMC 2 = CSUM16:	AC	-NWords,,Pointer to block
			AC+1	Initial checksum
Loop performs CSum ← (CSum + Item) LCy 1 over 16-bit items, where the first
item is bits 0:15 in the first word and the last item is bits 16:31 in the
last word, and sums are ones-complement (wraparound carry) over 16 bits.

Carries out of bits 20:35 in the checksum word are folded back after each
pair of 16-bit bytes has been processed, so that at the end of each step,
the number in AC+1 is .le. 200010b (provided that the original checksum is
.le. this value).  After the last PDP-10 word has been processed, the carry
word is folded one more time to produce a 16-bit final checksum in AC+1.

Note that if a zero count is in AC initially, so that the inner loop is
not executed, then the checksum in AC+1 will be folded precisely once;
this will produce a 16-bit result if the original value is less than
2↑17-1, a 17-bit result if the original value is less than 2↑32-1,
and a 22-bit result for arbitrary values.  If the inner loop is executed
at least once, then the original checksum can be as great as 2↑32-1 and
still produce a final result that is .le. 16 bits.  This means that after
checksumming an odd 16-bit byte at the beginning, one execution of the
opcode will produce a 16-bit result, even if the word count is 0, and
after checksumming an additional odd byte at the end, one execution of the
opcode will produce a 16-bit result.
%
*	P ← LAC, AQ, SAMASK[22], GOTO[CSUM16];

*P/ 16-bits, Q/ previous csum; P ← (P+Q) LCY 1
CS16X:	P ← P + Q;
	PQ LCY [1], Q ← MDR, RETURN;

CS16LP:	LAC ← P ← P + Q, SAMASK[22], GOTO[PI,H=1];
*P/ 777777, Q/ Pointer to block, AC/ pointer to initial csum.
CSUM16:	INCAC, GOTO[C16DON,ALU>=0];
	MAPVA ← P, CALL[RTOMDR];
	P ← MDR, Q ← A0;
*P←bits 0:15 of current word, Q←previous csum (.le. 200010b)
	PQ RCY [24], Q ← LAC, CALL[CS16X];
*Q←previous csum (.le. 1000020b), P←bits 16:31 of current word
	Q ← P, QQ RCY [4], SAMASK[20], CALL[CS16X];
*P has new checksum (.le. 2400036b); fold it to 17d bits here so that
*carries won't propagate outside bits 4:15 of the word.
	Q ← P, PQ RCY[20], SAMASK[24];
	Q ← P, P ← Q, SAMASK[20];
*Largest result from this operation (for Q = 2377777b) is 200010b.
	LAC ← P + Q, DECAC;
	P ← LAC, Q ← (2 000002R) RSH 1, SETSF[INTCONDH], GOTO[CS16LP];

*Fold 36-bit result once into the sum of the right-most 16d bits and the
*left-most 20d bits (This will result in a 16d-bit result for LAC .le.
*377776b, which is the case when the loop has run one or more times.).
C16DON:	P ← Q ← LAC, SAMASK[20];
	QQ RCY [20], Q ← P, SAMASK[24];
	LAC ← P + Q, ENDM;

%UJMC 3 = BYTBLT: A	AC	-NWords,,pointer to source block
		  D	AC+1	source to destination offset - 1
		  B	AC+2	No. unused bits at right of source
		  C	AC+3	Number of bits to right-shift the
				source word pair so that the
				right-most word has the destination
				data right-justified.
Approximate equivalent code:
	SKIPA T1,(A)
LP:	MOVE T1,T3	; Collect source word pair in T1..T2
	JUMPGE A,EXIT
	MOVE T2,1(A)
	MOVE T3,T2
	LSH T1,-B	; Squeeze out "crack" between T1 and T2
	LSHC T1,-C	; Right-shift T1..T2 so that T2 contains
			; the destination data right-justified
	LSH T2,B
	MOVEM T2,D+1(A)
	AOBJN A,LP
EXIT:	...
%
*	RTEMP1 ← Q, INCAC, GOTO[BYTB0];

BYTB0:	MAPVA ← P ← AQ, SAMASK[22], CALL[RQARG];
*Have P/ AC, Q/ memory data
	RTEMP ← Q, INCAC;		*RTEMP ← 0(AC)
	P ← RTEMP1, Q ← LAC, INCAC;
	Q ← LAC, STEMP ← Q, DECAC;	*STEMP←B
	STEMP1 ← Q, P ← P, DECAC, GOTO[BYTBA];	*STEMP1←C

*RTEMP/		0(AC) = first memory word
*STEMP1/	right-shift distance for word pair

BYTBLP:	LAC ← P ← P + Q, INCAC, GOTO[PI,H=1];
*Here the AC register contains its original value + 1 (points at D)
*P contains A, which has been put through the ALU.
BYTBA:	INCAC, GOTO[REMAPPC,ALU>=0];
	MAPVA ← P ← P + 1, SAMASK[22], CALL[RTOMDR];
	P ← RTEMP, Y ← P;
	Q ← A0;
	PQ RCY [Y], Y ← STEMP1;	*P←T1 data right-justified
	P ← MDR, Q ← P;
*RTEMP←T2 now to be T1 next time
	RTEMP ← P, PQ RCY [Y], Q ← LAC, DECAC;
	Y ← Q, Q ← P ← P, SAMASK[0], CALL[RETN];
*NOTE: delay 1 instruction after Y← before PQ RCY[44-Y]
	PQ RCY[44-Y];		*LSHIFT by B to zero unused bits
	MDR ← P, P ← REFADR, Q ← LAC, DECAC;
	MAPVA ← P ← P + Q, SAMASK[22], CALL[WMDR];
	P ← LAC, Q ← (2 000002R) RSH 1, SETSF[INTCONDH], GOTO[BYTBLP];


*Write data in MDR to address in P for which MAPVA has been done
*and return to caller.  On page fault, PC is not advanced.
WMDR:	WREF, REFADR ← P, Q ← MDR, GOTO[WMDR2,G=1];
WMDR1:	P ← (P) U (BLTWLE), RETURN[G=0];
	Q ← WMQ, LEFADR ← P, CALL[LOADMAP];
	WREF, Q ← MDR ← WDATA, GOTO[WMDR1,G=0];
WMDR2:	P ← (X) U (ACBASE), GOTO[WMDR3,H=0];
	MAPVA ← P ← (P) U (BLTWLE);
	WREFDXK, MDR ← Q, GOTO[WMDR1];

WMDR3:	LX ← Q, RETURN;

%UJMC 4 = WDUMP0:	AC	-NWords,,pointer to first src word
			AC+1	points at destination block
Loop moves two 40-bit words from the source to the destination translating
into Maxc dump format, where data bytes begin with 0:7 in the first source
word and with 0:7 in the first destination word.  Translation of nibbles is
as follows:
	Source			Destination
	xx xx xx xx s t		xx xx xx xx
	yy yy yy yy u v		-- st yy yy
				yy yy -- uv
where s and u are bits 32:35 in the two source words and t and v are the
tag bits in the source words and where -- denotes a garbage byte.  In other
words, 40-bit words from the source (including 4 tag bits/word) is copied
to the destination as 5 8-bit bytes with an extra garbage byte thrown in
between the 32nd and 33rd source bits, and the destination is packed 4
8-bit bytes/word.
%
*	P ← LAC, INCAC, GOTO[WDMP0];

WD0LP:	GOTO[REMAPPC,ALU>=0];
WDMP0:	MAPVA ← P ← P, SAMASK[22], CALL[RTOMDR];
	P ← A0, Q ← MDRL, SETSF[INTCONDH];
	PQ RCY [4], Q ← MDR, GOTO[PI,H=1];	*P/ t0 00 00 00 0
	PQ RCY [14], Q ← LAC, DECAC;	*P/ -- st 00 00 0
	RTEMP ← P, P ← Q, SAMASK[22];	*RTEMP/ -- st 00 00 0
	MAPVA ← P, CALL[WMDR];		*Write xx xx xx xx -
	P ← LAC, INCAC;
	MAPVA ← P ← P+1, SAMASK[22], CALL[RTOMDR];
	Q ← A0, P ← STEMP ← MDR;
	PQ RCY [20], Q ← RTEMP, STEMP1 ← MDRL;
	MDR ← P OR Q, P ← LAC;
	MAPVA ← P ← P+1, SAMASK[22], CALL[WMDR];
	P ← A0, Q ← STEMP;
	PQ RCY [24], Q ← STEMP1;		*P/ yy yy u0 00 0
	RTEMP ← P, 0Q RCY [4], Q ← STEMP;	*P/ v0 00 00 00 0
	PQ RCY [34], SAMASK[14], Q ← RTEMP;	*P/ 00 00 00 uv 0
	MDR ← P OR Q, Q ← LAC, P ← 2 000002R;
	MAPVA ← P ← P+Q, SAMASK[22], CALL[WMDR];
	Q ← LAC, P ← 2 000002R;
	P ← P+Q, Q ← (2 000002R) RSH 1;
	LAC ← P+Q, DECAC;
	P ← LAC, Q ← 2 000002R;
	LAC ← P ← P+Q, INCAC, GOTO[WD0LP];

%UJMC 5 = WDUMP1:	AC	-NWords,,pointer to first src word
			AC+1	Right-justified 8-bit byte from the
				previous iteration.
			AC+2	address of destination block
Like WDUMP0 but with a different destination alignment.
Translation of nibbles is as follows:
	Source			Destination
	xx xx xx xx s t		ll xx xx xx
	yy yy yy yy u v		xx -- st yy
				yy yy yy --
where ll is the byte from the previous iteration and where uv
is left right-justified in AC+1 for the next iteration.
%
*	P ← LAC, INCAC, GOTO[WDMP1];

WD1LP:	GOTO[REMAPPC,ALU>=0];
WDMP1:	MAPVA ← P ← P, SAMASK[22], CALL[RTOMDR];
	P ← STEMP ← MDR, Q ← LAC, INCAC;
	RTEMP ← P, PQ RCY [10], Q ← MDRL, SETSF[INTCONDH];
	MDR ← P, 0Q RCY [4], Q ← RTEMP, GOTO[PI,H=1];
	PQ RCY [10];			*P/ -s t0 00 00 0
	PQ RCY [14], Q ← LAC, DECAC;	*P/ xx -- st 00 0
	RTEMP ← P, P ← Q, DECAC;
	MAPVA ← P ← P, SAMASK[22], CALL[WMDR];
	P ← LAC, INCAC;
	MAPVA ← P ← P+1, SAMASK[22], CALL[RTOMDR];
	P ← STEMP ← MDR, Q ← A0, INCAC;
	PQ RCY [30], Q ← RTEMP, STEMP1 ← MDRL;
	MDR ← P OR Q, P ← LAC;
	MAPVA ← P ← P+1, SAMASK[22], CALL[WMDR];
	P ← A0, Q ← STEMP;
	PQ RCY [34];
	MDR ← P, P ← LAC, Q ← 2 000002R;
	MAPVA ← P ← P+Q, SAMASK[22], CALL[WMDR];
*Now update AC's for the iteration
	P ← LAC, Q ← 2 000002R;
	P ← P+Q, Q ← (2 000002R) RSH 1;
	LAC ← P+Q, DECAC;	*DEST AC ← DEST AC+3
	P ← A0, Q ← STEMP1;
	PQ RCY [4], Q ← STEMP;
	PQ RCY [40], SAMASK[10];
	LAC ← P, DECAC;		*Byte carried to next iteration
	P ← LAC, Q ← 2 000002R;
	LAC ← P ← P+Q, INCAC, GOTO[WD1LP];	*Source AC

%JMC, A CATCH-ALL INSTRUCTION ADDED TO THE PDP-10, IS PRIVILEGED.
E[22,30] SELECTS ONE OF 128 MICROCODED ROUTINES FOR EXECUTION.
THE TABLE OF MICROINSTRUCTIONS BEGINNING AT "ALEVX" IS USED TO DISPATCH
TO THE SELECTED ROUTINE WITH E[31,43] IN P AND AC IN Q.
I = 6 + NUJMCS + NJMCS + 72 = 116 (+8 COMMENTED OUT)
%

*MUST USE REFADR
JMC:	REFADR←P, PQ RCY [13], Q←NPC, RETURN, SETSF[UM&J], BAMASK[7];
*JMC DISPATCH.  HERE WITH -1 IN RTEMP AND LTEMP, E[30,43] IN P, AC IN Q
ALEVX:	X←P, PQ RCY [6], SAMASK[3], GOTO[ASNLEV]; *0  PILEV P[33,35] TO DEVICE P[36,43]
	Q←44S, RTEMP←Q, GOTO[ASNLOC];   *1  ASSIGN 24-BIT PARAM. TO DEV IN P
	Q←44S, RTEMP←Q, GOTO[ALEVLOC];  *2  ASSIGN BOTH LEV AND PARAM
	YKPTR←P, GOTO[WECTR];		*3  WRITE EVENT COUNTER E
	X←P, SETSF[G], GOTO[IOCK];	*4  CLEAR INTERRUPT REQUEST FOR DEV P
	X←P, SETF[G], GOTO[IOCK];	*5  INITIATE INTERRUPT REQUEST FOR DEV P
	RPGRT3←Q, PQ RCY [0], SAMASK[3], GOTO[SPILEV];  *6  SET PI LEVEL
					*FOR DEVICES SELECTED BY AC
	P←FINTS, GOTO[READIR];		*7  AC←INTERRUPTING DEVICE MASK
	P←FINTS, BRKP[1], GOTO[ILLIO];		*10  INITIATE INTS FOR DEVICES IN AC MASK
	CLEARF[PIACTIVE&G], GOTO[CONINTCOND];	*11  TURN OFF PI SYSTEM
	SETF[PIACTIVE&MICRO], GOTO[CONINTCOND];	*12  TURN ON PI SYSTEM
	SETF[INCMP&K], RETURN;   *13  ENTER INCOMPATIBLE MODE
	CLEARF[INCMP&K], RETURN; *14  LEAVE INCOMPATIBLE MODE
	X←P, SETSF[G], GOTO[SIGNAL];		*15  SIGNAL NOVA DEVICE E (BIT 43-E)
PRESC:	P←GOTAB, IRET, INHINT, GOTO[PRES];	*16  PROCESSOR RESET
	P←777777R, AMASK[17], SETSF[INCMP&K], GOTO[PIREAD];	*17  READ PI STATE
	Q←SLOCLOW, GOTO[SETSYSP];	*20 SET SYSTEM PARAMETER TO AC
MAPRESET: CLEARF[CUM&G], Y←NULL, GOTO[MAPRES];	*21  TURNOFF MAPPING
	P←Y←NULL, GOTO[SETPLO], Q←P;	*22  SET PLO EQUAL TO E
	READ←PSWITCH, GOTO[ASWIT];	*23  RELOAD BASE REGS. WITHOUT MAP CLEAR
	Q←1000S, GOTO[VPGCLR];		*24  CLEAR VIRTUAL PAGE E
	CLEARF[CUM&G], Y←A1, GOTO[MAPCLR];	*25  CLEAR ABSOLUTE PAGE E
	GOTO[USWIT], P←Y←PLO;		*26  SWITCH MAP TO NEW PROCESS
	YKPTR←KUNIT←P, GOTO[KOFF];	*27  DESELECT DISK UNIT E
	YKPTR←KUNIT←P, GOTO[KON];	*30  SELECT DISK UNIT E WITH THE
					*MAXIMUM DISK ADDRESS IN AC
	P←377 000000S, GOTO[KNOPDP];	*31  DISABLE PDP-10 SECTOR INTERRUPTS
					*FOR THE PACK IN AC
	P←377 000000S, GOTO[KSEEK];	*32  ENABLE PDP-10 SECTOR INTERRUPTS
					*AND SEEK IF ARM # CURRENT POSITION
	READ←DLSBS, GOTO[RESIO];	*33  I/O RESET
	MAPVA←P←AQ, SAMASK[22], GOTO[KGO];	*34  DO DATA TRANSFER SPECIFIED
					*BY COMMAND POINTED TO BY V.A. IN AC
	WRITE←P, INHINT, GOTO[WABS];	*35  MOVEM AC,E[31,43] ABSOLUTE
	READ←P, GOTO[RABS];             *36  MOVE AC,E[31,43] ABSOLUTE
	MAPVA←P←AQ, SAMASK[22], GOTO[MVA]; *37  MAP VIRTUAL TO ABSOLUTE
					*ADDRESS (1240,,E + 100000,,0 FOR READ
					*40400,,0 FOR WRITE AND 20000 FOR XCT)
	SETF[G], GOTO[RICT1];		*40  WRITE INST. COUNTER E
	Q←LAC, GOTO[CHECK];		*41  CHECK MICROMEMORY (MUST HAVE 0
					*IN AC AT CALL.  CLOBBERS AC TO AC+4)
	Q←P, P←NULL, SETF[J], GOTO[LEVX];	*42 TURN OFF PI LEVELS
	Q←P, P←NULL, SETF[MICRO], GOTO[LEVX];	*43 TURN ON PI LEVELS
	SETF[LOGF&K], RETURN;		*44  ENABLE OPTIONAL MAIN LOOP PATH
	CLEARF[LOGF&K], RETURN;		*45  DISABLE OPTIONAL MAIN LOOP PATH

DM[DLC,777]; DLC[E1[JMC] E2[JMC1] E3[ADD[4000,IP[ILC],NOT[IP[JMC]]]]];

JMC1:	MDR←P+Q, SETSF[G], GOTO[ILLIO,J=1];
	Q←STACK, LTEMP←RTEMP←A1;
	P-Q, NPC←MDR;
	GOTO[ILLIO,ALU>=0], P←REFADR, Q←LAC, AMASK[13], POP;

UJMC:	REFADR←P, PQ RCY [13], Q←NPC, BAMASK[7], SETSF[J], RETURN;

RICT1:	P←10L, Q←YKPTR←P, GOTO[RICTR];	*0  READ INST. COUNTER E
	YKPTR←P, GOTO[RECTR];		*1  AC←EVENT COUNTER E
	P ← LAC, AQ, SAMASK[22], GOTO[CSUM16];	*2  CSUM16
	RTEMP1 ← Q, INCAC, GOTO[BYTB0];	*3  BYTBLT
	P ← LAC, INCAC, GOTO[WDMP0];	*4  WDUMP0
	P ← LAC, INCAC, GOTO[WDMP1];	*5  WDUMP1

DM[DLC,776]; DLC[E1[UJMC] E2[JMC1] E3[ADD[4000,IP[ILC],NOT[IP[UJMC]]]]];