ER[DGM];		*TEST OF PROCESSOR AND DISK MEMORY INTERFACES

TARGET[ILC];

%TO ASSEMBLE:	MICRO/L LANG DGM -OR- MICRO/L LANG2 DGM
TO RUN:		MIDAS RDGM
		START;G		FOR ORDINARY MEMORY TESTING
		START1;G	FOR INTERRUPT SYSTEM TESTING
		XSTART;G	FOR INTERRUPT SYSTEM TESTING

COMPARISON ERRORS ARE MASKED BY "DMASK" AND "DMASKL" (PROCESSOR INTERFACE MASKS)
AND "KDMASK" AND "KDMASKL" (DISK INTERFACE).

TEST THE MAIN MEMORY INTERFACE FOR THE PROCESSOR AND FOR THE DISK CONTROL.
BEGIN BY CHECKING OUT THE LOADING AND READING OF MAR, MDR, MDRL, KMAR,
KMDR, AND KMDRL FROM/TO THE BUS.  ORIGINALLY LOAD MAR VIA THE MAPVA←
DESTINATION WHICH IS ALSO CHECKED OUT.	THEN CHECK THAT ALL OF THE MEMORY
REFERENCE FUNCTIONS AND DESTINATIONS LOAD MAR CORRECTLY BUT POSTPONE
CHECKING OUT MEMORY DATA UNTIL LATER.

***NOTE:  NOT ALL BITS OF KMAR CAN BE CHECKED OUT BECAUSE THERE IS NO WAY
***TO LOAD THAT REGISTER WITHOUT MAKING A MEMORY REFERENCE.
***MEMORY ERRORS HANG THE PROCESSOR UNDER CONTROL OF A HARDWARE SWITCH

***DO NOT ASSEMBLE THIS PROGRAM WITH DG1 (SM, RM, AND LM TESTS).
***DG0, DG1, AND DGP SHOULD WORK BEFORE THIS IS TRIED.	FIRST VERIFY THAT DGM
***WORKS WITH THE DATA COMPARE MASKS SET T0 0.	THEN TRY IT WITH FULL
***DATA COMPARE.

TO CHECKOUT ONLY DISK MEMORY INTERFACE, PUT BREAKPOINT AT "MCTEST", START
AT "TKWRT".

TO CHECKOUT ONLY PROCESSOR MEMORY INTERFACE, PUT BREAKPOINT AT "TKWRT",
START AT "START" (TESTS READ←, WRITE←, AND RMW←)

TO TEST XREF, RREF, RMWREF, WREF, ETC., START AT "TREFS" (BREAKS AT END
OF DIAGNOSTIC).	THIS DOESN'T CHECK OUT VERY MANY ADDRESSES; TO CHECK
MORE ADDRESSES, PATCH "TREF1+1" TO BE "CALL[AGEN], P←LADR"

"START1" COMBINES A CONSTANT INTERRUPT REQUEST AND TRIVIAL INTERRUPT
ROUTINE WITH PARTS OF THE MEMORY DIAGNOSTIC TO CHECK FOR INTERACTIONS
AND FAILURES HAVING TO DO WITH THE ONSET/TERMINATION OF INTERRUPTS AND/OR
WITH THE STOP LOGIC.  SINCE THE INTERRUPT ROUTINE RETURNS WITHOUT PREIRET,
AT LEAST ONE NON-INTERRUPT INSTRUCTION IS EXECUTED BETWEEN EACH INTERRUPT.
THE CHANNEL 17 INTERRUPT IS USED.  ALTERNATE ENTRY POINT "XSTART" IS
FOR OCCASIONAL DISK SECTOR INTERRUPTS FROM UNIT A INSTEAD OF CONSTANT
INTERRUPTS.  "DGI" SHOULD RUN BEFORE TRYING "START1" OR "XSTART".
%

*AGGRAVATE PROBLEMS CAUSED BY DENSITY OF 1'S IN IM
DEFAULT[IM,(GOTO[3777,NEVER], Q←Q, PQ RCY [0], LA[37], RA[37], A0,
	SA[377], B←NULL, NOF2, NOZ, T[0])];

INSERT[DGIB.MC];

IM[XILC,5];
XILC[(CALL[SECIROU], X←YKPTR←KUNIT)];

*FALL THRU HERE FROM "MCYCLE"
	SETSF[IENABLE&G], DGOTO[TMDR];
	GOTO[TMINIT,G=1];

START1:	KUNIT←P←NULL, CLEARF[-1S];
	ARM←P+1;
	SETF[IENABLE&G], GOTO[TMINIT];

XSTART:	X←7S;
	KUNIT←X, CALL[RETN]; *ALLOW TWO CYCLES SETTLING TIME AFTER KSET←
	DECX;
	KSET←100 000000S, GOTO[.-2,X>=0]; *DESELECT ALL DISK UNITS
	COUNT←ARM←NULL, INHINT;
	KUNIT←NULL, INHINT;
	IRET, P←MDR, INHINT;
	P←NULL, CLEARF[-1S];
	KSET←441600 200000S; *ENABLE SECTOR INTS. ON UNIT 0
	ARM←2000S;
	SETF[10S];
	SETF[IENABLE&G], GOTO[TMINIT];

SV[MLOW,0];		*LOWEST ADDRESS USED IN DATA OPERATIONS
SV[MHIGH,777777];	*HIGHEST ADDRESS USED IN DATA OPERATIONS
SV[MAMASK,777777 777777];	*MASK OF BITS FOR MEM. ADDR.****NOT IMPLEMENTED
SV[DMASK,777777 777777]; SV[DMASKL,17];	*MASK FOR MEMORY DATA COMPARES
SV[KDMASK,777777 777777]; SV[KDMASKL,17]; *MASK FOR DISK MEMORY COMPARES

SVN[SDATA]; SVN[SDATAL];		*HOLD DATA INVOLVED IN CURRENT REFERENCE
SVN[SBASE]; SVN[SBASEL];		*STARTING NUMBER FOR PASS THRU MAIN MEMORY
SVN[SADR];			*CURRENT ADDRESS

MC[XCTN,XCTN]; *MASK OF THE FOUR XCT BITS THAT FORCE USER MODE ON REF'S
MC[XCT0,XCT0]; *XCT0 CONTROLS IREF
MC[NXCT0,XCT1,XCT2,XCT3];
MC[XCT1,XCT1]; *XCT1 CONTROLS RREF
MC[NXCT1,XCT0,XCT2,XCT3];
MC[XCT2,XCT2]; *CONTROLS BIREF
MC[NXCT2,XCT0,XCT1,XCT3];
MC[XCT3,XCT3]; *CONTROLS WREF
MC[NXCT3,XCT0,XCT1,XCT2];
MC[CFM&CUM&XCTN,CFM,CUM,XCTN];
MC[CFM&CUM&XCT0,CFM,CUM,XCT0];
MC[CFM&CUM&XCT1,CFM,CUM,XCT1];
MC[CFM&CUM&XCT2,CFM,CUM,XCT2];
MC[CFM&CUM&XCT3,CFM,CUM,XCT3];
MC[UM&CUM&K&G,UM,CUM,K,G];
NMC[NOTG,G];
NMC[NOTUM,UM];
NMC[NOTCUM,CUM];
NMC[NOTGUMCUM,G,UM,CUM];
MC[CUM&UM,CUM,UM];
MC[CUM&H,CUM,H];
MC[UM,UM];
MC[UM&K,UM,K];
MC[CUM&XCTN,CUM,XCTN];
MC[NWP,RP,XP];
MC[CUM&NXCT0,CUM,XCT1,XCT2,XCT3];
MC[CUM&NXCT1,CUM,XCT0,XCT2,XCT3];
MC[CUM&NXCT2,CUM,XCT0,XCT1,XCT3];
MC[CUM&NXCT3,CUM,XCT0,XCT1,XCT2];
*PARAMETERS FOR THE MAP MEMORY ENTRIES
MP[RP,22]; *READ PERMIT BIT (0 ENABLES IREF, BIREF, RREF, AND PARTLY RMWREF)
MP[WP,23]; *WRITE PERMIT (0 ENABLES WREF AND PARTLY RMWREF)
MP[XP,24]; *EXECUTE PERMIT (0 ENABLES XREF)
MC[RP,RP];
MC[WP,WP];
MC[XP,XP];
MC[RP&WP,RP,WP];
MC[RP&WP&XP,RP,WP,XP];

RVN[RSAVE]; RVN[RNADR]; RVN[RTEMP]; RVN[RTEMP1]; RVN[RTEMP2]; RVN[RTEMP3];
LVN[LTEMP]; LVN[LTEMP1]; LVN[LTEMP2]; LVN[LSAVE]; LVN[LADR]; LVN[LINT];

SECIROU: LINT←Q, P←Y, Q←400R, CALL[PQCOMP]; *Y NOT LOADED CORRECTLY BY INTERRUPT INSTRUCTION
	KREAD←SADR;
*443600 200000S WOULD BE USED BELOW TO RESET THE SECTOR INTERRUPT REQUEST
*BUT HAVING THE INTERRUPT REPEAT OVER AND OVER IS MORE USEFUL
	KSET←441600 200000S; *DON'T INVOKE STOP LOGIC ON NEXT INSTRUCTION
	P←P1, IRET, RETURN, Q←LINT;

INTROU:	P←Y, LINT←Q;
	Q←400S, CALL[PQCOMP]; *Y NOT LOADED CORRECTLY BY INTERRUPT INSTRUCTION
	IRET, P←P1, RETURN, Q←LINT;

*RTEMP HOLDS P ARGUMENT AND RTEMP1 HOLDS Q ARGUMENT FOR RCY [44-Y]
TMINIT:	RTEMP←A0;
	RTEMP1←A1, CALL[PQRCY44-YT];
	RTEMP←A0;
	RTEMP1←A0, CALL[PQRCY44-YT];
	RTEMP←A1;
	RTEMP1←A0, CALL[PQRCY44-YT];
	RTEMP←A1;
	RTEMP1←A1, CALL[PQRCY44-YT];
	GOTO[YLOADT];

PQRCY44-YT: P←777S, A0;
PQ44-YL0: Y←P, Q←RTEMP1, CLEARF[H], GOTO[PQ44-YL,ALU<0];
	LTEMP←P-1, P←RTEMP;
	PQ RCY [44-Y];
	P←LTEMP, Q←77R, CALL[CBRK,H=0];
	P-Q-1, GOTO[PQ44-YL0];

PQ44-YL: Y←P, Q←RTEMP1, CLEARF[H], GOTO[PQ44-YT1,ALU<0];
	LTEMP←P-1, P←RTEMP;
	PQ RCY [44-Y], CALL[H=1T];
	P←LTEMP, Q←44R;
	P-Q-1, P←LTEMP, GOTO[PQ44-YL];

PQ44-YT1: P←44R;
	RTEMP3←P; *VALUE FOR Y
	Y←P, P←RTEMP, CLEARF[H];
	LTEMP2←P, Q←RTEMP1;
	PQ RCY [44-Y], RTEMP2←Q;
	Q←RTEMP, CALL[PQCOMP]; *PQ RCY [44-Y] FAILED ON [Y] = 44
	CALL[CBRK,H=1];

PQ44-YL1: Q←LTEMP2, P←RTEMP2;
	PQ RCY [1], Q←RTEMP2;
	RTEMP2←P, P←LTEMP2;
	PQ RCY [1];
	LTEMP2←P, P←RTEMP3;
	RTEMP3←P←P-1, Q←44L;
	Y←P, P←RTEMP, FRZBALUBC;
	Q←RTEMP1, SETF[H], RETURN[ALU<0];
	PQ RCY [44-Y], Q←LTEMP2, CALL[PQCOMP]; *PQ RCY [44-Y] FAILED ON Y
	CALL[CBRK,H=1]; *H NOT LEFT 0 BY PQ RCY [44-Y]
	GOTO[PQ44-YL1];
H=1T:	RETURN[H=1];
	BREAK;		*H WASN'T = 1 AFTER PQ RCY [44-Y] WITH [Y]>=44

YLOADT:	P←A1, BAMASK[22];
YTLOOP:	RTEMP1←MAPVA←P, PQ RCY [11], BAMASK[11];
	Q←Y, CALL[PQCOMP]; *INTERRUPT ROUTINE CLOBBERED Y
	P←RTEMP1, Q←400000S;
	Q←P AND Q, PQ RCY [11], BAMASK[11];
	YSHIFT←P OR Q, PQ RCY [0], BAMASK[11];
	Q←Y, CALL[PQCOMP]; *INTERRUPT ROUTINE CLOBBERED Y
	P←RTEMP1;
	Y←P, PQ RCY [0], BAMASK[11];
	Q←Y, CALL[PQCOMP]; *INTERRUPT ROUTINE CLOBBERED Y
	P←RTEMP1, Q←1000S;
	RTEMP1←P←P-Q, Q←400000S;
	P AND Q, DGOTO[TMDR];
	GOTO[YTLOOP,ALU#0];

TMDR:	P←MDR←NULL;
	Q←MDR, CALL[QZT];	*MDR OR MDR← FAILED ON 0
	MDR←P+1, P←B;
	Q←MDR, CALL[PQCOMP];	*MDR OR MDR← FAILED ON [P]
	MDR←2P, P←B;
	GOTO[.-2,ALU#0];
	P←B, B←A1;
	Q←B, MDR←2P;
	P←MDR, CALL[PQCOMP];	*MDR OR MDR← FAILED ON [Q]
	Q LCY 1;
	GOTO[.-2,Q ODD], MDR←Q;

*ON "XSTART" ENTRY TO "DGM" CODE BELOW CHECKS OUT "INHINT"
TKMDR:	P←KMDR←NULL, INHINT;
	Q←KMDR, CALL[QZT];	*KMDR OR KMDR← FAILED ON 0
	KMDR←P+1, P←B, INHINT;
	Q←KMDR, CALL[PQCOMP];	*KMDR OR KMDR← FAILED ON [P]
	KMDR←2P, P←B, INHINT;
	GOTO[.-2,ALU#0], INHINT;
	P←B, B←A1;
	Q←B, KMDR←2P, INHINT;
	P←KMDR, CALL[PQCOMP];	*KMDR OR KMDR← FAILED ON [Q]
	Q LCY 1;
	GOTO[.-2, Q ODD], KMDR←Q, INHINT;

TMDRL:	P←MDRL←NULL;
	Q←MDRL, CALL[PQCOMP];	*MDRL OR MDRL← FAILED ON [P]
	P←B, MDRL←P+1, Q←17R;	*Q←17
	P-Q;
	GOTO[.-3,ALU<=0];

TKMDRL:	P←KMDRL←NULL, INHINT;
	Q←KMDRL, CALL[PQCOMP];	*KMDRL OR KMDRL← FAILED ON [P]
	P←P+1;
	KMDRL←P, Q←17R, INHINT;
	P-Q, INHINT;
	GOTO[.-3,ALU<=0], INHINT;

*~ MAXC2 ONLY
TMDST:	CLEARF[-1S], MDR←-1S;
	MDRL←NULL;
	Q←MDR&SETTAG, P←A1, CALL[PQCOMP]; *B←MDR FAILED ON MDR&SETTAG
	P←A0, Q←FLAGS, CLEARF[-1S], CALL[PQCOMP]; *TAG FLAGS LOADED WRONG ON MDR&SETTAG
	MDRL←LTEMP←P+1;
TMDSTL:	Q←MDR&SETTAG, P←A1, CALL[PQCOMP]; *B←MDR FAILED ON MDR&SETTAG
	P←A0, Q←LTEMP;
	PQ RCY [30], Q←FLAGS, CALL[PQCOMP]; *TAG FLAGS LOADED WRONG ON MDR&SETTAG
	Q←LTEMP;
	Q LSH 1, P←A1, BAMASK[4];
	P-Q, CLEARF[-1S];
	LTEMP←MDRL←Q, GOTO[TMDSTL,ALU>0];
*~

*JUMP OVER A BUNCH OF SUBROUTINES USED BY THE TESTS WHICH FOLLOW LATER
	GOTO[TMVAT];

%THE ROUTINES BELOW ARE SUBROUTINES WHICH ARE CALLED TO GENERATE ADDRESSES
AND DATA FOR THE VARIOUS OTHER SECTIONS OF THE DIAGNOSTIC AND TO CHECK
THE RESULTS OF MEMORY READS.
%
*INITIALIZE THE MEMORY ADDRESS VARIABLES "SADR" AND "LADR"
AINI:	Q←MLOW, P←LSAVE;
	SADR←LADR←Q, Q←RSAVE, RETURN;

*GENERATE NEXT ADDRESS, RETURN IT IN Q AND THRU ALU, 17 IN P.	CALLED WITH
*PREVIOUS ADDRESS IN P.	TIMING = 3
AGEN:	Q←P+1, P←MHIGH;
AGEN0:	P-Q;
	LADR←SADR←Q, P←17R, FRZBALUBC, RETURN;

*GENERATE PREVIOUS ADDRESS LSH 1, RETURN IT IN Q AND THRU ALU BUT RETURN
*MLOW ON FIRST ADDRESS > MHIGH.  CALLED WITH PREVIOUS ADDRESS IN Q.
AGEN1:	0Q RCY [43], Q←MHIGH;
AGEN3:	P←Q, Q←P, GOTO[AGEN0];

AGEN2:	NOT(A0)Q RCY [43], Q←MHIGH, GOTO[AGEN3];

*INITIALIZE THE DATA CELLS "SDATA", "SDATAL" AND "SBASE", "SBASEL" TO A
*SINGLE 1.  TIMING = 4
DINIS1:	P←SDATA←NULL;
	Q←P+1, SBASE←NULL;
	SDATAL←Q;
	SBASEL←Q, RETURN;

*INITIALIZE THE DATA CELLS "SDATA" "SDATAL" AND "SBASE", "SBASEL" TO A
*SINGLE 0.  TIMING = 5
DINIS0:	P←Q←377777 777777S;
	SDATA←Q;
	SBASE←Q, Q←17R;
	SDATAL←Q;
	SBASEL←Q, RETURN;

*PUT SBASE, SBASEL IN SDATA, SDATAL
*TIMING = 4
DSET:	Q←SBASE;
	SDATA←Q;
	Q←SBASEL;
	SDATAL←Q, GOTO[AINI];

*RCY 1 THE 40-BIT QUANTITY IN SBASE, SBASEL AND LEAVE IT IN SDATA,SDATAL ALSO
*RETURNS WITH SDATA THRU ALU AND SDATAL IN Q
*TIMING = 8
BDADV:	Q←SBASEL;
	PQ RCY [4], Q←SBASE;
	LTEMP1←Q, PQ RCY [41], BAMASK[4], Q←SBASEL;
	RTEMP2←MDR←P, P←LTEMP1;
	SBASEL←MDR, PQ RCY [1];
	SDATAL←MDR, Q←P;
	SDATA←Q;
	SBASE←Q, AQ, RETURN, Q←RTEMP2;

*RCY BY 1 THE 40-BIT QUANTITY IN SDATA, SDATAL.
*TIMING = 7
DGEN:	Q←SDATAL, RSAVE←Q;
	LSAVE←P, PQ RCY [4], Q←SDATA;
	LTEMP1←Q, PQ RCY [41], BAMASK[4], Q←SDATAL;
	MDR←P, P←LTEMP1;
	SDATAL←MDR, PQ RCY [1];
	Q←P;
	SDATA←Q, Q←RSAVE, P←LSAVE, RETURN;

*COMPLEMENT THE DATA IN SBASE AND SBASEL AND LEAVE IT IN SDATA, SDATAL AND
*IN MDR, MDRL ALSO.
*TIMING = 5
NMDATA:	Q←SBASE, RSAVE←Q;
	LSAVE←P, P←SBASEL;
	Q←NOT Q;
	SBASE←MDR←Q, P←NOT P, BAMASK[4];
	SDATA←Q, Q←P;
	SBASEL←MDRL←Q;
	SDATAL←Q, GOTO[AINI];

*COMPLEMENT SDATA, SDATAL AND LEAVE IN MDR, MDRL
*HAVE NOT(SDATA) IN Q, SDATAL IN P AT CALL
NDGEN:	SDATA←MDR←Q, P←NOT P, BAMASK[4];
	WRESTART, MDRL←Q←P;
	SDATAL←Q, RETURN;

*COMPARE THE DATA IN MDR, MDRL TO THE DATA IN SDATA, SDATAL
*TIMING = 10
DCOMP:	LSAVE←P, P←SDATA;
	RSAVE←Q, Q←MDR;
	Q←P#Q, P←DMASK;
	Q←P AND Q, CALL[AZT], P←MDRL; *WRONG BITS FOR MDR COMPARE IN Q
	Q←SDATAL;
	Q←P#Q, P←DMASKL;
	Q←P AND Q, CALL[AZT];	*WRONG BITS FOR MDRL COMPARE IN Q
	P←LSAVE, Q←RSAVE, RETURN;

*COMPARE THE DATA IN KMDR, KMDRL TO THAT IN SDATA, SDATAL
*TIMING = 10
KDCOMP:	LSAVE←P, P←SDATA;
	RSAVE←Q, Q←KMDR;
	Q←P#Q, P←KDMASK;
	Q←P AND Q, CALL[AZT], P←KMDRL; *WRONG BITS FOR KMDR COMPARE IN Q
	Q←SDATAL;
	Q←P#Q, P←KDMASKL;
	Q←P AND Q, CALL[AZT];	*WRONG BITS FOR KMDRL COMPARE IN Q
	P←LSAVE, Q←RSAVE, RETURN;

*SUBROUTINE TO CHECK AFTERMATH OF ILLEGAL MEMORY REFERENCES IN MONITOR
*MODE.
IRFCHK:	CALL[CBRK,G=0];	*READ ILLEGAL SO SHOULD LEAVE G=1
	CALL[CBRK,H=1], SETSF[CUM&H]; *NO XCTI FLAGS SET SO H=0
	P←MAR, Q←RTEMP, CALL[PQCOMP]; *THE ADDRESS PUT INTO RTEMP AND INTO
				*MONITOR MAP ENTRY FOR THE PAGE CONTAINING
				*THE CURRENT ADDRESS CONSISTS OF THE LOW 9
				*BITS OF THE CURRENT ADDRESS AND THE COMPLEMENT
				*OF THE REST OF THE ADDRESS MASKED BY MHIGH.
				*THIS SHOULD WIND UP IN MAR REGARDLESS OF THE
				*LEGALITY OF THE REF OR WHETHER IT IS AND AC
				*REFERENCE
	CALL[CBRK,H=1], P←MHIGH; *MHIGH IS JUST A RANDOM VALUE FOR ITS
				*USE HERE TO FIND OUT WHETHER THE MEMORY INTER-
				*FACE WAS ACTIVE DESPITE THE ILLEGALITY OF THE
				*READ.
	CLEARF[-1S], Q←MDR, CALL[PQCOMP]; *CHECK FOR MDR UNCHANGED
	Q←MDRL, P←RTEMP1, CALL[PQCOMP]; *CHECK FOR MDRL UNCHANGED
	P←LADR, MDRL←P;
	MAPVA←P, RETURN;

*SUBROUTINE TO CHECK OUT THE AFTERMATH OF MONITOR MODE READ REF'S
MRCHK:	CALL[CBRK,H=1], SETSF[CUM&H]; *H=0 BECAUSE NOT A FORCED USER REF
	CALL[CBRK,H=1];	 *CUM=0 BECAUSE MONITOR MODE AND XCTI=0
RCHK:	P←MAR, Q←RTEMP, CALL[PQCOMP]; *MAR SHOULD BE [Q]
RCHK1:	P←SDATA, CALL[CBRK,G=1];	*RP OR XP WAS 0 IN MAP SO REF SUCCEEDS
	CLEARF[-1S], Q←MDR;	*COMPARE THE DATA FROM THE READ
	Q←P#Q, P←DMASK;
	P AND Q, P←MDRL;
	Q←SDATAL, CALL[CBRK,ALU#0];	*(MDR XOR SDATA) AND DMASK # 0
	Q←P#Q, P←DMASKL;
	P AND Q, P←LADR, MDR←NULL;
	Q←SDATA, RETURN[ALU=0];	*RETURN SDATA IN Q IN CASE "NDGEN" NEXT
	BRKP[1];			*(MDRL XOR SDATAL) AND DMASKL # 0

*SUBROUTINE TO CHECK AFTERMATH OF FORCED USER READS WITH CFM=1
CFMCHK:	CALL[CBRK,H=0], SETSF[CUM&H];
	CALL[CBRK,H=1]; *CUM=0 BECAUSE CFM=1
	GOTO[RCHK];

*SUBROUTINE TO TEST THE AFTERMATH OF READ REF'S IN MONITOR MODE WHICH ARE
*FORCED TO USER MODE BY THE SETTING OF AN XCTI FLAG IN F
FURCHK:	CALL[CBRK,H=0], SETSF[CUM&H]; *FORCED UM REF SO H=1
	CALL[CBRK,H=0];	 *CUM SHOULD BE 1 SINCE XCTI=1 FOR REF
	P←MAR, Q←LTEMP, CALL[PQCOMP];
	GOTO[RCHK1];

*SUBROUTINE TO TEST THE AFTERMATH OF A LEGAL USER MODE READ
URCHK:	CALL[CBRK,H=1], SETSF[CUM&H]; *NOT A FORCED UM REF
	CALL[CBRK,H=0];	 *CUM SHOULD BE 1 SINCE UM=1 FOR REF
	GOTO[RCHK];

*SUBROUTINE TO TEST THE AFTERMATH OF MAPVA←.  CALLED WITH 17 IN Q,
*ADDRESS IN P, CORRECT [F] IN RTEMP (BUT G=0).	RETURNS WITH F=0.
*TIMING = 13+1 IF AC
*! MAXC1 ONLY
TMVAX:	P-Q, Q←RTEMP, P←NOT F;
	DGOTO[TMVAAC,ALU<=0], P=Q;
*!
*~ MAXC2 ONLY
TMVAX:	P-Q, Q←RTEMP, P←FLAGS;
	P#Q, DGOTO[TMVAAC,ALU<=0];
*~
	Q←(Q) U (1S), FRZBALUBC;
TMVA0:	CALL[CBRK,ALU#0], P←LADR, Q←377S; *MAPVA← LOADED F INCORRECTLY
				*(CORRECT VALUE= RTEMP OR RTEMP+1 IF AC)
	Q←P AND Q, P←X, CALL[PQCOMP]; *MAPVA← DIDN'T LOAD X FROM B[28-35]
	P←LADR, Q←MAR, CALL[PQCOMP]; *MAPVA← DIDN'T LOAD MAR FROM [P]
	PQ RCY [11], SAMASK[11], CALL[PQCOMP], Q←Y; *MAPVA← DIDN'T LOAD Y
				*FROM B[18-26]=[P]
	RETURN, CLEARF[-1S];

*! MAXC1 ONLY
TMVAAC:	P=Q, GOTO[TMVA0];
*!
*~ MAXC2 ONLY
TMVAAC:	P#Q, GOTO[TMVA0];
*~

*TEST OUT MAPVA← ON ALL LEGAL ADDRESSES WITH THE AFFECTED REGISTERS
*BOTH ORIGINALLY 0 AND ORIGINALLY -1 AND WITH MAPVA← TESTED USING BOTH
*THE ALU TEST AND THE ACFS TEST.
*TIMING = ((MHIGH-MLOW)*16*8)+1 = ABOUT 128*(MHIGH-MLOW) CYCLES
TMVAT:	SETSF[IENABLE&G];
	SADR←MAPVA←NULL, LADR←A0, GOTO[TWRT,G=1];
	RTEMP←A0, P←LADR, CLEARF[-1S];
	MAPVA←P, Q←17R, CALL[TMVAX];
	MAPVA←A1;
	P←CUM&UM;
	RTEMP←P, P←LADR, SETF[UM];
	MAPVA←P, Q←17R, CALL[TMVAX];
	MAPVA←NULL;
	P←NOTGUMCUM;
	RTEMP←P, P←LADR, SETF[NOTUM];
	MAPVA←P, Q←17R, CALL[TMVAX];
	MAPVA←A1;
	P←NOT G;
	RTEMP←P, P←LADR, SETF[NOTCUM];
	MAPVA←P, Q←17R, CALL[TMVAX];
	MAPVA←NULL;
	RTEMP←A0, CLEARF[-1S];
	MAPVA←P←SADR, Q←17R, ACFS, CALL[TMVAX];
	MAPVA←A1;
	P←CUM&UM;
	RTEMP←P, SETF[UM];
	MAPVA←P←SADR, Q←17R, CALL[TMVAX];
	MAPVA←NULL;
	P←NOTGUMCUM;
	RTEMP←P, SETF[NOTUM];
	MAPVA←P←SADR, Q←17R, CALL[TMVAX];
	MAPVA←A1;
	P←NOT G;
	RTEMP←P, SETF[NOTCUM], CALL[RETN];
	MAPVA←P←SADR, ACFS, Q←17R, CALL[TMVAX];

*NOW TRY WRITE←, READ←, AND RMW← ALLOWING TIME FOR REFERENCES TO FINISH.
*MAR AND [F] UNCHANGED ARE CHECKED FOR AND THE DATA IS COMPARED AFTER
*ANDING WITH DMASK, DMASKL
*TIMING = 160*((MHIGH-MLOW)*81+25+3)+19 OR ABOUT 12,960*(MHIGH-MLOW) CYCLES
*! MAXC1 ONLY
TWRT:	P←NOT F;		*CHECK FOR F GETTING CLOBBERED
*!
*~ MAXC2 ONLY
TWRT:	P←FLAGS;
*~
	LTEMP←P, CALL[AINI];
TWR0:	CALL[DINIS1];		*INITIALIZE SDATA, SDATAL, SBASE, SBASEL
	CALL[SWRT];		*CHECK WRITE←, RMW←, AND READ← ON EVERY ADDRESS
				*USING DATA GENERATED FROM SBASE, SBASEL
	CALL[BDADV];		*LOOP THROUGH THE 40 VALUES OF SBASE, SBASEL
				*BDADV RETURNS WITH SBASEL IN Q (NOT SLOW SOURCE)
	GOTO[.-2,Q EVEN];	*WHICH HAVE A SINGLE 1 WITH 39 0'S
	CALL[DINIS0];		*REPEAT THE ABOVE FOR THE 40 VALUES OF SBASE,
	CALL[SWRT];		*SBASEL WHICH HAVE A SINGLE 0 WITH 39 1'S
	CALL[BDADV];		*BDADV RETURNS WITH SBASE THROUGH ALU
	GOTO[.-2,ALU<0];
*! MAXC1 ONLY
	P←NOT F, Q←LTEMP, CALL[PQCOMP]; *F SMASHED DURING THE PRECEDING
*!
*~ MAXC2 ONLY
	P←FLAGS, Q←LTEMP, CALL[PQCOMP];
*~
	GOTO[TKWRT];

*TIMING = (MHIGH-MLOW)*(19+33+29)+25
SWRT:	CALL[WLP];
	CALL[RMWLP];
	CALL[RLP];
	CALL[HSRMWLP];
	GOTO[RLP];	*RETURN TO CALLER OF SWRT

*SEQUENTIALLY WRITE ALL THE ADDRESSES IN THE MACHINE USING DATA WHICH IS
*RCY 1 FROM THE PRECEDING WORD'S DATA EACH TIME WITH THE ORIGINAL DATA
*BEING THE VALUE IN SBASE, SBASEL.
*TIMING = (MHIGH-MLOW)*19+1
WLP:	WRITE←Q←SADR, INHINT;
	MDR←SDATA, INHINT;
	MDRL←SDATAL;
	P←MAR, CALL[PQCOMP];	*WRITE DIDN'T LOAD MAR FROM B
	CALL[DGEN], Q←SDATAL;
	CALL[AGEN], P←LADR, MDR←MDR;
	GOTO[WLP,ALU>=0];
	GOTO[DSET];

*TIMING = (MHIGH-MLOW)*33+1
RMWLP:	RMW←Q←SADR, INHINT;
	P←MAR, CALL[PQCOMP];	*MAR NOT LOADED BY RMW←.  CORRECT VALUE IN Q
	Q←SDATA;
	CALL[DCOMP], P←SDATAL;	*ADDRESS OF DATA IN LADR OR SADR
	MDR←NOT Q, WRESTART;
	MDRL←NOT P, CALL[DGEN], P←LADR;
	CALL[PQCOMP], Q←MAR;	*WRESTART SMASHED MAR
	CALL[AGEN];
	GOTO[RMWLP,ALU>=0];
	GOTO[NMDATA];

*TIMING = (MHIGH-MLOW)*29+1
RLP:	READ←Q←SADR;
	P←MAR, CALL[PQCOMP];	*MAR NOT LOADED BY READ←.  CORRECT VALUE IN Q
	CALL[DCOMP];		*ADDRESS IN BOTH SADR AND LADR
	CALL[DGEN];
	CALL[AGEN], P←LADR;
	GOTO[RLP,ALU>=0];
	GOTO[DSET];

*THE FOLLOWING ROUTINE EXERCISES RMW← AT A HIGHER SPEED THAN THE PRECEDING
*TEST WITHOUT ERROR CHECKS SUCH THAT THE ERRORS ARE CAUGHT BY THE FOLLOWING
*READ← CHECK
HSRMWLP: RMW←SADR, INHINT, CALL[RETN]; ****REMOVE CALL WHEN MEM INT WORKS
	Q←MDR;
	P←MDRL, WRESTART;
	MDR←NOT Q, INHINT;
	MDRL←NOT P, CALL[DGEN];
	P←LADR, CALL[AGEN];
	GOTO[HSRMWLP,ALU>=0];
	GOTO[NMDATA];

*EXCEPT THAT [F] IS NOT CHECKED FOR BEING UNCHANGED.
*TIMING = (MHIGH-MLOW)*(19+31+29)+26
SKWRT:	CALL[KWLP];		*WRITE EVERY ADDRESS USING NUMBERS
				*GENERATED FROM THE CURRENT SBASE, SBASEL
	CALL[KRLP];		*NOW KREAD← AND CHECK THE RESULTS
	CALL[NMDATA];
	GOTO[BDADV];		*CYCLE THE DATA BASE AND RETURN

*TIMING = 80*((MHIGH-MLOW)*(19+33+29)+29)+19 = ABOUT 6,340*(MHIGH-MLOW) CYCLES
*! MAXC1 ONLY
TKWRT:	P←NOT F;
*!
*~ MAXC2 ONLY
TKWRT:	P←FLAGS;
*~
	LTEMP←P, CALL[AINI];
	CALL[DINIS1];
	CALL[SKWRT];
	GOTO[.-1, Q EVEN];
	CALL[DINIS0];
	CALL[SKWRT];
	GOTO[.-1,ALU<0];
*! MAXC1 ONLY
	P←NOT F, Q←LTEMP, CALL[PQCOMP]; *F SMASHED BY ONE OF DISK MEMORY
				*INTERFACE FUNCTIONS
*!
*~ MAXC2 ONLY
	P←FLAGS, Q←LTEMP, CALL[PQCOMP];
*~
	SETSF[IENABLE&G], DGOTO[TSTOP];
	GOTO[MCTEST,G=0];


KWLP:	KWRITE←Q←SADR, INHINT;
	KMDRL←SDATAL, INHINT;
	KMDR←SDATA;
	P←KMAR, CALL[PQCOMP];	*KWRITE← DIDN'T LOAD KMAR FROM B OR KMAR
				*BUS SOURCE FAILED
	CALL[DGEN];		*GENERATE THE NEXT DATA VALUE (PREVIOUS RCY 1)
	CALL[AGEN], P←LADR;	*GENERATE THE NEXT ADDRESS
	GOTO[KWLP,ALU>=0];	*FALL THRU WHEN ADDRESS = 0 AGAIN
	GOTO[DSET];

*TIMING = 29*(MHIGH-MLOW)+1
KRLP:	KREAD←Q←SADR;
	P←KMAR, CALL[PQCOMP];	*KREAD← DIDN'T LOAD KMAR CORRECTLY
	Q←Q;
	CALL[KDCOMP];
	CALL[DGEN];
	CALL[AGEN], P←LADR;
	GOTO[KRLP,ALU>=0];
	RETURN;

*MEMORY COMPETITION TEST USING BOTH MEMORY INTERFACES
*(1) WRITE← FROM PROC, KREAD← FROM DISK
*(2) RMW← FROM PROC, KRMW← FROM DISK
*(3) READ← FROM PROC, KREAD← FROM DISK
*(4) KWRITE← FROM DISK, READ← FROM PROC

**THIS TEST PERFORMED ONLY IF MASKS ARE ALL 1'S
MCTEST:	P←KDMASK;
	P←DMASK, NOT P;
	P←KDMASKL, Q←17R, NOT P, GOTO[TREFS,ALU#0];
	P←DMASKL, P#Q, GOTO[TREFS,ALU#0];
	P#Q, GOTO[TREFS,ALU#0];
	GOTO[TREFS,ALU#0];
	CALL[AINI], CLEARF[-1S], LTEMP←A1;
	CALL[DINIS1];
	CALL[SPKWRT];
	GOTO[.-1,Q EVEN];
	CALL[DINIS0];
	CALL[SPKWRT];
	GOTO[.-1,ALU<0];
*! MAXC1 ONLY
	P←NOT F, Q←LTEMP, CALL[PQCOMP]; *F SMASHED BY ONE OF DISK OR PROC
			*MEMORY FUNCTIONS
*!
*~ MAXC2 ONLY
	P←FLAGS, Q←LTEMP, CALL[PEQZ];
*~

*MEMORY COMPETITION TEST HITTING THE PROCESSOR INTERFACE WITH A REF
*AND THE DISK INTERFACE WITH A REFERENCE IN THE SAME MICROINSTRUCTION.
*THE PROCESSOR INTERFACE SHOULD WIN.

***NOTE THAT THE REF'S HAVE NOT BEEN TESTED YET, SO THAT THE FOLLOWING
***TEST IS OUT OF SEQUENCE.  HOWEVER, WHEN UNTESTED MAXC'S ARE BROUGHT
***UP YOU SHOULD FIRST RUN DGM WITH ALL DATA COMPARE MASKS SET TO 0.
***THIS SHOULD CATCH PROBLEMS WITH REF'S.  THESE TESTS WERE PUT HERE TO
***KEEP THEM WITH THE OTHER MEMORY BASHING TESTS.  REMEMBER THAT
***NONE OF THESE TESTS GET RUN WHEN DATA COMPARE MASKS AREN'T ALL 1'S.
MCT2:	CLEARF[-1S], CALL[MAPINI];
	CALL[DINIS1];
	CALL[KREFT];
	GOTO[.-1,Q EVEN];
	CALL[DINIS0];
	CALL[KREFT];
	GOTO[.-1,ALU<0];
	GOTO[TREFS];

PWKRLP:	Q←MDR←SDATA;
	WRITE←SADR, INHINT;
	KREAD←SADR, INHINT;
	P←MDRL←SDATAL;
	RTEMP←P, P←KMDR, CALL[PQCOMP];
	P←RTEMP, Q←KMDRL, CALL[PQCOMP];
	CALL[DGEN];
	P←LADR, CALL[AGEN];
	GOTO[PWKRLP,ALU>=0];
	GOTO[DSET];

PRKRLP:	READ←SADR;
	KREAD←SADR;
	Q←MDR;
	P←KMDR, CALL[PQCOMP];
	Q←MDRL;
	P←KMDRL, CALL[PQCOMP];
	CALL[DGEN];
	CALL[AGEN], P←LADR;
	GOTO[PRKRLP,ALU>=0];
	GOTO[DSET];

KWPRLP:	P←KMDR←SDATA;
	KWRITE←SADR, INHINT;
	READ←SADR, INHINT;
	Q←KMDRL←SDATAL;
	RTEMP←Q, Q←MDR, CALL[PQCOMP];
	Q←MDRL, P←RTEMP, CALL[PQCOMP];
	CALL[DGEN];
	P←LADR, CALL[AGEN];
	GOTO[KWPRLP,ALU>=0];
	GOTO[DSET];

SPKWRT:	CALL[PWKRLP];
	CALL[PRKRLP];
	CALL[KWPRLP];
	GOTO[BDADV];

*SUBROUTINE TO NEUTRALIZE MAP BY FILLING IT WITH READ, WRITE, AND ACCESS
*PERMISSION AND POINTING EACH VIRTUAL PAGE AT THE ABSOLUTE PAGE OF THE SAME
*NUMBER.
MAPINI:	MAP←Y, INCY, GOTO[.,Y>=0];
	MAP←Y, INCY, GOTO[.,Y<0];
	RETURN;

*PROCESSOR WREF AND KREAD←
PWREFKR: P←Q←17R, CALL[AGEN];
PWRFKRLP: MAPVA←SADR, ACFS;
	WREF, CALL[CBRK,G=1], KREAD←SADR, INHINT;
	Q←MDRL←SDATAL, INHINT, CALL[CBRK,G=1];
	RTEMP←Q, Q←MDR←SDATA;
	P←KMDR, CALL[PQCOMP];
	P←KMDRL, Q←RTEMP, CALL[PQCOMP];
	CALL[DGEN];
	P←LADR, CALL[AGEN];
	GOTO[PWRFKRLP,ALU>=0];
	GOTO[DSET];

*PROCESSOR RREF AND KWRITE←
PRREFKW: P←Q←17R, CALL[AGEN];
PRREFKWLP: Q←SDATA;
	P←SDATAL;
	MAPVA←SADR, ACFS;
	RREF, CALL[CBRK,G=1], KWRITE←SADR, INHINT;
	KMDR←NOT Q, INHINT, CALL[CBRK,G=1];
	KMDRL←NOT P;
	RTEMP←P, P←MDR, CALL[PQCOMP];
	P←RTEMP, Q←MDRL, CALL[PQCOMP];
	CALL[DGEN];
	P←LADR, CALL[AGEN];
	GOTO[PRREFKWLP,ALU>=0];
	GOTO[NMDATA];

KREFT:	CALL[PWREFKR];
	CALL[PRREFKW];
	GOTO[BDADV];

*TEST DISK MEMORY INTERFACE STOP LOGIC
TSTOP1:	CALL[AINI];	*INITIALIZE ADDRESS TO 0
TSTOPA:	READ←SADR;	*MAKE MEMORY QUADRANT BUSY
	KWRITE←SADR, INHINT;
	KMDR←A1, CALL[RETN];
	KMDR←NULL;	*SHOULD INVOKE STOP LOGIC
	KREAD←SADR, CALL[RETN];
	P←KMDR, CALL[NPZT];	*KMDR← DIDN'T INVOKE STOP LOGIC ON KWRITE←
	READ←SADR;		*MAKE MEMORY QUADRANT BUSY
	KWRITE←SADR, INHINT;
	KMDRL←KMDR←A1, CALL[RETN];
	KMDRL←NULL;		*SHOULD INVOKE STOP LOGIC
	KREAD←SADR, CALL[RETN];
	P←KMDRL, Q←17R, CALL[PQCOMP]; *KMDRL← DIDN'T INVOKE STOP LOGIC ON KWRITE←
	P←LADR, CALL[AGEN];
	GOTO[TSTOPA,ALU>=0];

*TEST PROCESSOR MEMORY INTERFACE STOP LOGIC
TSTOP2:	CALL[AINI];
TSTOPB:	KREAD←SADR;	*MAKE QUADRANT BUSY
	WRITE←SADR, INHINT;
	MDR←A1, CALL[RETN];
	MDR←NULL;	*SHOULD INVOKE STOP LOGIC
	READ←SADR, CALL[RETN];	*CHECK RESULTS
	P←MDR, CALL[NPZT];	*MDR← DIDN'T INVOKE STOP LOGIC ON WRITE←
	KREAD←SADR;	*MAKE QUADRANT BUSY
	WRITE←SADR, INHINT;
	MDRL←MDR←A1, CALL[RETN];
	MDRL←NULL;	*SHOULD INVOKE STOP LOGIC
	READ←SADR, CALL[RETN];	*CHECK RESULTS
	P←MDRL, Q←17R, CALL[PQCOMP];	*MDRL← DIDN'T INVOKE STOP LOGIC
	P←LADR, CALL[AGEN];
	GOTO[TSTOPB,ALU>=0];

INSERT[DGMB.MC];