ER[CHECKER]; *I=48 + JMC INSTR, S=20, MUST BE ASSEMBLED LAST

%18 6-BIT CHECKSUMS ARE FORMED AS A HAMMING CODE OVER THE DATA.  THESE
ARE COMPARED AGAINST THE VALUES STORED IN CSUM0, CSUM1, AND CSUM2.
CORRECT 6-BIT SUMS RESULT IN A 0, INCORRECT IN A 1 COMPONENT FOR THE
HAMMING ADDRESS CODE.  AN OVERALL CHECKSUM IS ALSO COMPUTED AND COMPARED
AGAINST THE VALUE STORED IN CSUMD.  IF THIS IS INCORRECT DUE TO A SINGLE
BIT FAILURE, THEN THE ADDRESS RETURNED IN AC IS THE ADDRESS OF THE WORD
COMPUTED AS FOLLOWS:
   0-7777	IM[0,43]
   10000-17777	IM[44,107]
   20000-20777	DM[0,43]
   21000-21777  DM1[0,43]
   22000-22777  DM2[0,43]
   24000-24777	SM[0,43]
THE OVERALL CHECKSUM IS RETURNED IN AC+1, AND THE 6-BIT CHECKSUMS IN
AC+2, AC+3, AND AC+4 (CORRESPONDING TO CSUMD, CSUM0, CSUM1, AND CSUM2).
ENTRY TO THE CHECKER IS MADE BY P←LAC, GOTO[CHECK].
%

*CHECKER VARIABLES
SVN[CSUMD]; SVN[CSUM0]; SVN[CSUM1]; SVN[CSUM2];

*CHECKER CONTROL TABLE
SLC[CHECKERT: E1[CHKTAB]];
SM[XSLC,IP[CHKTAB]]; TARGET[XSLC];

*L.H. HAS FIRST ADDRESS IN NEXT RANGE; R.H. HAS SUBROUTINE
E1[ILCSUM], E2[ADD[LASTOK,40]];	*0 TO LASTOK+37 (= 0 TO 4777)
E1[CHECK], E3[1];
E1[IRCSUM], E2[ADD[LASTOK,40]], E3[1];	*10000 TO 10000+LASTOK+37
E1[CHECK], E3[2];
E1[DMCSUM], E2[1000], E3[2];	*20000 TO 20777
*~ MAXC2 ONLY
E1[DM1CSUM], E2[2000], E3[2];	*21000 TO 21777
*E2[DM2CSUM], E2[3000], E3[2];	*22000 TO 22777
*~
E1[CHECK], E2[4000], E3[2];
E1[SMCSUM], E2[ADD[4000,IP[SLC]]], E3[2];	*24000 TO 24000+SLC-1
E1[CHECK], E2[ADD[4000,IP[IOTD]]], E3[2];
E1[SMCSUM], E2[ADD[4000,IP[IODEND]]], E3[2];	*24000+IOTD TO 24000+IODEND-1
E1[CHECK], E2[ADD[4001,IP[IODEND]]], E3[2];
E1[SMCSUM], E2[5000], E3[2];	*24001+IODEND TO 24777

TARGET[ILC];

%"CSUM" ENTERED WITH WORD TO BE CHECKSUMMED IN P, OVERALL CHECKSUM
IN AC+1, 6-BIT CHECKSUMS IN AC+2 (1,2,4,10,20, AND 40), AC+3
(100,200,400,1000,2000, AND 4000), AND AC+4 (10000 AND 20000),
ADDRESS IN LAC.

TIMING = 38
%

CSUM:	Q←LAC, RPGRT2←P, INCAC, X←AC;
	P←Q←LAC, RTEMP←Q;
	LTEMP←A1, PQ RCY [1], Q←RPGRT2, SETSF[J];
	P←P+Q+J, Q←RPGRT2; *AC+1 IS OVERALL CHECKSUM
*FOLD DATA TO 6 BITS
	LAC←P+J, QQ RCY [22]; *LABEL BYTES A,B,C,D,E,F
	Q←P←P+Q, INCAC;
	PQ RCY [6];	*A+D IN Q, F+C IN P
	Q←P+Q, PQ RCY [14]; *A+D+F+C IN Q, E+B IN P
	Q←P+Q, P←LTEMP, SAMASK[36], DGOTO[5];
	Y←NPC, LTEMP←P←NOT P AND Q, Q←RTEMP, GOTO[.+2];
*HERE WITH FOLDED DATA IN P[0,5] AND LTEMP[0,5], ADDRESS IN Q AND RTEMP,
*AC POINTING TO THE FIRST 6 X 6 CHECKSUM WORD, 5 IN Y
	Q←(RTEMP) RSH 1, PQ RCY [6], SAMASK[36], GOTO[.+3,Y<0];
	DECY, RTEMP←Q, Q←LAC, GOTO[.-1,Q EVEN];
	PQ RCY [6], SAMASK[36], LAC←P#Q, Q←(RTEMP) RSH 1, GOTO[.-1,Y>=0];
	INCAC, AQ, P←LTEMP, Y←4S, DGOTO[MCSLP];
	INCY, GOTO[.-3,ALU#0];

*SUBROUTINE TO SHIFT IN 6 MORE CSUM ERROR BITS INTO RTEMP
CREDUC:	P←Q←P#Q, Y←5S, BAMASK[6];
	P, QQ RCY [6], DECY;
	SETFB[J,ALU#0], P←RTEMP, LTEMP←P;
	RTEMP←2P+J, P←Q←LTEMP, DGOTO[.-2];
	SAMASK[6], PQ RCY [0], RETURN[Y<0];

*BEGINNING AT DM LOCATION [LAC] IN P, CHECKSUM ONE WORD
DMCSUM:	P←D, GOTO[CSUM];

*~ MAXC2 ONLY
DM1CSUM: P←D1, GOTO[CSUM];

*DM2CSUM: P←D2, GOTO[CSUM];
*~

*! MAXC1 ONLY
ILCSUM:	NPC←P;
	P←I, DGOTO[.+1], INHINT; *IM[0,43]
	INHINT, GOTO[.+1];
	INHINT, GOTO[CSUM]; *IN CASE DATA SELECTS IM AS BUS SOURCE OR DEST.

IRCSUM:	NPC←P;
	P←I, DGOTO[.-3]; *IM[44,107]
*!
*~ MAXC2 ONLY
ILCSUM:	NPC←P;
	I, DGOTO[.+1], INHINT; *IM[0,43]
	P←EREG, GOTO[CSUM];

IRCSUM:	NPC←P;
	I, DGOTO[.-2];
*~

SMCSUM:	P←SY, GOTO[CSUM];

CSDISP:	Y←P, Q←RTEMP; *DGOTO PENDING


*CHECK FOR INTERRUPTS AFTER EACH WORD
MCSLP:	P←LX, SETSF[INTCONDH], AC←X;
	LAC←Q←P+1, GOTO[PI,H=1];
CHECK:	LAC←Q, X←11S;
	Y←CHECKERT, INCX, GOTO[CHECK1,ALU#0];
	INCAC, A1, X←AC, DGOTO[.+1];
	LAC←A0, INCAC, DGOTO[.,ALU<0];	*THIS INSTR DONE 3 TIMES
	LAC←A0, AC←X, GOTO[CHECK1];
	P-Q-1, Q←RTEMP, DECX;
	NPC←Q, GOTO[CSDISP,ALU>=0], P←LAC, RTEMP←P;
CHECK1:	P←SY, INCY, GOTO[.+1];
	RTEMP←P, PQ RCY [14], SAMASK[22], Q←LAC, GOTO[.-3,X>=0];
*DONE CHECKSUMMING.
	Q←AC, P←A1, SAMASK[2];
	AC←P+Q+1;
	P←LAC, Q←CSUM2, DECAC, RTEMP←A0, CALL[CREDUC];
	P←LAC, Q←CSUM1, DECAC, CALL[CREDUC];
	P←LAC, Q←CSUM0, DECAC, CALL[CREDUC];
	P←LAC, Q←CSUMD, DECAC;
	P←P#Q, Q←RTEMP, DGOTO[RETN];
	LAC←Q, CALL[SCRASH,ALU#0];