Google
 

Trailing-Edge - PDP-10 Archives - klad_sources - klad.sources/msstrc.b36
There are no other files named msstrc.b36 in the archive.
%TITLE 'MAIN CONTROL AND COMMON ROUTINES FOR STIRS DIAGNOSTICS'

MODULE MSSTRC (
		LANGUAGE(BLISS36)
		) =

BEGIN

!
!                     COPYRIGHT (C) 1979
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS 01754
!
! THIS SOFTWARE IS FURNISHED  UNDER A LICENSE FOR USE ONLY ON A SINGLE
! COMPUTER  SYSTEM AND  MAY BE  COPIED ONLY WITH  THE INCLUSION OF THE
! ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE, OR ANY OTHER COPIES THEREOF,
! MAY NOT BE PROVIDED OR  OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON
! EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE
! TERMS.  TITLE TO AND  OWNERSHIP OF THE  SOFTWARE  SHALL AT ALL TIMES
! REMAIN IN DEC.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD  NOT BE CONSTRUED  AS A COMMITMENT  BY DIGITAL  EQUIPMENT
! CORPORATION.
!
! DEC ASSUMES  NO  RESPONSIBILITY  FOR  THE USE OR  RELIABILITY OF ITS
!SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
!

!++
! FACILITY:  DECSYSTEM 2020 DIAGNOSTIC RELEASE TAPE 'DSTIR'
!
!
! ABSTRACT:
!
!	THIS MODULE CONTAINS THE MAIN CONTROL AND COMMON SUBROUTINES
!	FOR THE KS10 (2020) STIMULUS-RESPONSE (STIRS) DIAGNOSTICS.  IT
!	IS LINKED WITH A TEST MODULE AND A DATA MODULE TO PRODUCE A
!	FAULT ISOLATION DIAGNOSTIC FOR A KS10 MODULE.
!
! ENVIRONMENT:  RUND UNDER 'CSL' ON A TOPS-20 SYSTEM.
!
! AUTHOR: RICHARD MURATORI	, CREATION DATE: 13-APR-1979
!
! MODIFIED BY:
!
!	RICH MURATORI, 23-MAY-79; VERSION 0.1
!--

!
! TABLE OF CONTENTS:
!

FORWARD ROUTINE
    CONTROL : NOVALUE,			!MAIN CONTROL ROUTINE
    PRINT_HEADER : NOVALUE,		!PRINTS PROGRAM HEADER
    PRT_FEATURES : NOVALUE,		!PRINTS LIST OF ACTIVATED FEATURES
    ASK_FEATURES : NOVALUE,		!ASKS USER ABOUT ACTIVATING FEATURES
    MEMSIZE,				!ASKS USER WHAT KS10 MEMORY SIZE IS
    GET_NUM,				!GET USER INPUTTED NUMBER FROM TTY
    INIT_DATA : NOVALUE,		!INITIALIZES DATA BASE BEFORE TESTING
    DISPATCH : NOVALUE,			!TEST DISPATCH ROUTINE
    RUN_CHK,				!CHECKS WHETHER NEXT TEST SHOULD BE RUN
    NET_RPT : NOVALUE,			!PRINTS LIST OF POSSIBLY-FAULTY NETWORKS

!THE FOLLOWING FOUR ERROR HANDLER ROUTINES ALSO DO FAULT ISOLATION

    ERR : NOVALUE,			!SIMPLE ERROR HANDLER
    ERRCA : NOVALUE,			!ERROR HANDLER WITH CORRECT AND ACTUAL
    ERRCAS : NOVALUE,			!ERROR HANDLER WITH CORRECT AND ACTUAL
					! AND SPECIAL PRINTING
    ERRS : NOVALUE,			!ERROR HANDLER WITH SPECIAL PRINTING

!THE FOLLOWING FOUR ERROR HANDLER ROUTINES DO NOT DO FAULT ISOLATION

    ERRM : NOVALUE,			!SIMPLE ERROR HANDLER
    ERMCA : NOVALUE,			!ERROR HANDLER WITH CORRECT AND ACTUAL
    ERMCAS : NOVALUE,			!ERROR HANDLER WITH CORRECT AND ACTUAL
					! AND SPECIAL PRINTING
    ERMS : NOVALUE,			!ERROR HANDLER WITH SPECIAL PRINTING
    ERR_RPT : NOVALUE,			!ERROR MESSAGE PRINTING
    PRT_SPEC : NOVALUE,			!SPECIAL PRINTER
    GET_CHAR,				!GETS NEXT CHARACTER FROM MESSAGE FILE
    FIND_NUM,				!LOOKS FOR TEST OR MESSAGE # IN MSG FILE
    PRINT_CA : NOVALUE,			!PRINTS CORRECT AND ACTUAL DATA
    PRT_GTR_12 : NOVALUE,		!PRINTS CORRECT AND ACTUAL DATA GREATER
					! THAN 12 OCTAL DIGITS
    PNUM : NOVALUE,			!PRINTS AN OCTAL NUMBER ON TTY
    NOERR : NOVALUE,			!DOES 'NO ERROR' FAULT ISOLATION
    FAILURE : NOVALUE,			!DOES 'ERROR' FAULT ISOLATION
    LOOP_CHK,				!CHECKS FOR ERROR LOOPING CONDITION
    FLP_CHK,				!CHECKS FOR FAST ERROR LOOPING CONDITION
    CHK_ERR_MSG : NOVALUE,		!CHECKS FOR PENDING 8080 ERROR MESSAGE
    WAIT : NOVALUE,			!WAIT LOOP
    PRT_ERR : NOVALUE,			!PRINTS UNEXPECTED ERROR MESSAGE
    SEND_LINE,				!CONCCATENATES AND SENDS 8080 COMMANDS
    TIMED_OUT : NOVALUE,		!REPORTS 8080 RESPONSE TIME OUT
    REPEAT : NOVALUE,			!GENERATES 8080 REPEAT CMD
    PTSTNUM : NOVALUE,			!PRINTS CURRENT TEST NUMBER
    CP : NOVALUE,			!DOES CPU PULSING WITH SINGLE STEP CHECKING
    CP_NOSS : NOVALUE,			!DOES CPU PULSING WITH NO SINGLE STEP CHECKING
    SEND_CP : NOVALUE,			!CREATES 8080 'CP' CMD
    SS_UC : NOVALUE,			!DOES SINGLE STEPPING WITH 'CP' CMDS
    SEND_NUL,				!FORCES SENDING OF COMMAND LINE
    SETNXT : NOVALUE,			!SETS NEXT CRAM ADDRESS
    EXNEXT,				!EXAMINES NEXT CRAM ADDRESS
    WR_CRAM,				!TESTS CRAM ON CRA BOARD
    X1,					!LOADS AND EXECUTES 8080 X1 SUBROUTINE
    LOADUC : NOVALUE,			!LOADS KS10 MICROCODE
    MR : NOVALUE,			!DOES A KS10 MASTER RESET
    PE : NOVALUE,			!ENABLE/DISABLE 8080 PARITY DETECTION
    CE : NOVALUE,			!ENABLE/DISABLE KS10 CACHING
    CS : NOVALUE,			!START KS10 CPU CLOCK
    CH : NOVALUE,			!HALT KS10 CPU CLOCK
    TP : NOVALUE,			!ENABLE/DISABLE KS10 TRAPPING
    TE : NOVALUE,			!ENABLE/DISABLE KS10 1 MSEC TIMER
    EJ,					!DO AN 'EJ' CMD
    SC_0 : NOVALUE,			!TURN OFF SOFT CRAM ERROR RECOVERY
    EC,					!EXAMINE CRAM CONTENTS
    LCA : NOVALUE,			!LOAD CRAM ADDRESS
    DC_035 : NOVALUE,			!DEPOSIT CRAM CONTENTS
    MOD_FLD : NOVALUE,			!MODIFY A 12-BIT CRAM DATA FIELD
    DM_CHK,				!DEPOSIT INTO MEMORY AND CHECK FOR ERROR RESPONSE
    MEM_DEPOSIT : NOVALUE,		!DEPOSIT DATA INTO MEMORY LOCATION
    MEM_EXAMINE,			!EXAMINE MEMORY LOCATION
    EM_CHK,				!EXAMINE MEMORY AND CHECK FOR ERROR RESPONSE
    EM,					!EXAMINE MEMORY
    MSG_CHK : NOVALUE,			!CHECK FOR EXPECTED ERROR RESPONSE
    DN : NOVALUE,			!DO A DEPOSIT NEXT
    IO_DEPOSIT : NOVALUE,		!DEPOSIT INTO KS10 BUS I/O REGISTER
    IO_EXAMINE,				!EXAMINE A KS10 BUS I/O REGISTER
    EI,					!EXAMINE A KS10 BUS I/O REGISTER
    EI_CHK,				!EXAMINE I/O REGISTER AND CHECK FOR ERROR RESPONSE
    INSERT_NUM,				!INSERT A NUMBER FIELD IN AN 8080 CMD
    REG_EXAMINE,			!EXAMINE AN 8080 REGISTER
    WRT100 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 100
    WRT102 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 102
    WRT103 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 103
    WRT104 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 104
    WRT105 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 105
    WRT106 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 106
    WRT107 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 107
    WRT110 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 110
    WRT111 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 111
    WRT112 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 112
    WRT113 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 113
    WRT114 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 114
    WRT115 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 115
    WRT116 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 116
    WRT204 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 204
    WRT205 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 205
    WRT206 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 206
    WRT210 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 210
    WRT212 : NOVALUE,			!DEPOSIT INTO 8080 REGISTER 212
    REG_DEPOSIT : NOVALUE,		!DEPOSIT INTO 8080 REGISTER
    TICK : NOVALUE,			!GENERATE CLOCK TICKS
    TICK_NOSS : NOVALUE,		!GENERATE CLOCK TICKS WITH NO SINGLE STEP
    SEND_TICK : NOVALUE,		!SEND COMMANDS TO DO CLOCK TICKS
    SS_TICK : NOVALUE,			!SINGLE TICK SYSTEM CLOCK
    SYNC_CLK : NOVALUE;			!SYNC SYSTEM CLOCK

!
! INCLUDE FILES:
!

REQUIRE 'CSLMAC.R36';			!MACROS TO CUMMUNICATE WITH 'CSL'

REQUIRE 'REGBIT.R36';			!8080 REGISTER BIT DEFINITIONS

!
! MACROS:
!
!	NONE
!
! EQUATED SYMBOLS:
!

LITERAL
    CONTROL_EDIT = 1,			!EDIT NUMBER OF THIS MODULE
    CONTROL_VERSION = 1;		!VERSION NUMBER OF THIS MODULE

BIND

!THE FOLLOWING IS AN 8080 SUBROUTINE WHICH IS LOADED AND USED BY THE
!'SETNXT' AND 'EXNEXT' ROUTINES.
!
! 332 327 042 X1CMD:	JC	RHSAVE		;JUMP IF NO ARG TYPED
! 315 254 013		CALL	LCCMD		;ELSE, GO READ IN CRAM ADDRESS
! 052 004 040		LHLD	CRMAD		;GET ADDR IN H,L
! 303 267 014		JMP	CADWR		;GO WRITE ADDR & RETURN
!
! 076 001     RHSAVE:	MVI	A,01		;GET CODE FOR 'NXT'
! 315 331 014		CALL	READC		;READ 'NXT'
! 315 300 030		CALL	P16.		;PRINT RESULTS
! 347 002		PCRLF			;WITH <CR-LF>
! 311			RET			;AND OUT
	    CADSUB = PLIT(UPLIT(%ASCIZ 'LK20054,DK332,DN327,DN42,DN315,DN254,DN13,DN52,DN4,DN40,DN303,DN267,DN14'),
			UPLIT (%ASCIZ'LK21327,DK76,DN1,DN315,DN331,DN14,DN315,DN300,DN30,DN347,DN2,DN311'));

BUILTIN
    COPYII,
    POINT,
    SCANI,
    REPLACEI;

!
! OWN STORAGE
!

STRUCTURE
    CHAR_BUF [I; N] =				!STRUCTURE FOR PACKING ASCII CHARS
	[(N + 5)/5]
	(CHAR_BUF + I/5)<29 - (I MOD 5)*7, 7, 0>;

GLOBAL
    NO_SUBSET : INITIAL (0),			!FLAG FOR SUBSET CHECKING IN 'RUN_CHK'
    TIMOUT,					!FLAG FOR 8080 RESPONSE TIMEOUT
    ERRFLG,					!ERROR FLAG. SET BY 'ERR_RPT' AND CLEARED BY 'LOOP_CHK'
    RPT_ERR_FLAG;				!FLAG TO TURN ON/OFF 8080 ERROR RESPONSE REPORTING

OWN
    LINE_BUF : CHAR_BUF [80],		!BUFFER TO HOLD 8080 CMD LINE CHARS
    NETWRDS,				!NUMBER OF 36-BIT WORDS IN FAULTY NETWORK BITVECTOR
    SCRIPT_RUN,				!FLAG INDICATING WHETHER SCRIPT IS RUNNING
    HAD_FAILURE,			!FLAG INDICATING THAT FAILURE OCCURRED
    TEST_NUM,				!NUMBER OF TEST BEING EXECUTED
    MSG_FILE_OPEN,			!FLAG INDICATING MESSAGE FILE IS OPENED
    PAGE_IN,				!FLAG INDICATING THAT A PAGE OF MESSAGE FILE IS IN MEMORY
    LOOP_ERR_NUM,			!NUMBER OF ERROR BEING LOOPED ON
    LAST_MEM_ADDR,			!LAST KS10 MEMORY ADDRESS REFERENCED
    LAST_IO_ADDR,			!LAST KS10 I/O ADDR REFERENCED
    LAST_REG_ADDR,			!LAST 8080 REGISTER REFERENCED
    SUB_LOADED,				!FLAG INDICATING WHICH 8080 SUBROUTINE IS LOADED
    LINE_CHARS,				!NUMBERS OF CHARS LOADED IN 8080 CMD LINE
    BELL_ON_ERR : INITIAL (0),		!BELL-ON-ERROR FEATURE FLAG
    LOOP_ON_ERR : INITIAL (0),		!LOOP-ON-ERROR FEATURE FLAG
    FAST_LOOP : INITIAL (0),		!FAST ERROR LOOPING FEATURE FLAG
    LOOP_ON_TEST : INITIAL (0),		!LOOP-ON-TEST FEATURE FLAG
    LOOP_TEST,				!TEST NUMBER TO LOOP ON
    TEXT_INH : INITIAL (0),		!TEXT-INHIBIT FEATURE FLAG
    SINGLE_STEP : INITIAL (0),		!SINGLE-STEPPING FEATURE FLAG
    LOOP_ON_PRG : INITIAL (0),		!LOOP-ON-PROGRAM FEATURE FLAG
    LOOPING,				!FLAG INDICTING THAT PROGRAM IS LOOPING ON ERROR
    NO_ISOLATION : INITIAL (0),		!NO-FAULT-ISOLATION FEATURE FLAG
    PRT_TST_NUM : INITIAL (0),		!PRINT-TEST-NUMBERS FEATURE FLAG
    PATCH : VECTOR [20] INITIAL ( REP 20 OF (0)); !PROGRAM PATCH AREA

GLOBAL BIND
    LPONTST = LOOP_ON_TEST;

!
! EXTERNAL REFERENCES:
!

EXTERNAL
    MSGFIL,				!NAME OF ERROR MESSAGE FILE (FROM TEST MODULE)
    NET_FAULTS,				!CUMULATIVE POSSIBLY-FAULTY BITVECTOR (IN DATA MODULE)
    ES_TBL,				!TABLE OF FAULTY-NETWORK BITVECTORS (IN DATA MODULE)
    NES_TBL;				!TABLE OF NOT-FAULTY-NETWORK BITVECTORS (IN DATA MODULE)

EXTERNAL LITERAL
    MAXNETS,				!NUMBER OF NETWORKS ON BOARD UNDER TEST
    MAXTEST;				!NUMBER OF TESTS IN TEST MODULE

MAP
    NET_FAULTS : BITVECTOR,
    ES_TBL : VECTOR,
    NES_TBL : VECTOR;
GLOBAL ROUTINE CONTROL : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS THE MAIN CONTROL FOR THE RUNNING OF STIRS AND IS
!	THE ENTRY POINT TO WHICH THE 'CSL' PROGRAM TRANSFERS TO START
!	STIRS EXECUTION.  THE FIRST TIME THE PROGRAM IS STARTED, THE
!	PROGRAM NAME AND THE EDIT AND VERSION NUMBERS FOR THE MODULES
!	ARE REPORTED.  THEN A LIST OF THE ACTIVATED FEATURES IS PRINTED.
!	THE USER IS ASKED IF HE WANTS TO CHANGE THAT LIST.  IF HE DOES,
!	THEN HE IS ASKED FEATURE-BY-FEATURE WHETHER OR NOT HE WANTS TO
!	ACTIVATE IT.  WHEN THE FEATURE ACTIVATION IS COMPLETED, AN
!	INITALIZATION ROUTINE IS CALLED TO INITALIZE THE DATA BASE. THEN
!	THE DISPATCH ROUTINE IS CALLED TO INVOKE THE RUNNING OF THE
!	TESTS.  WHEN ALL TESTS HAVE BEEN RUN, THE FAULTY NETWORK
!	REPORTING ROUTINE IS CALLED TO PRINT THE LIST OF POSSIBLY FAULTY
!	NETWORKS AS CONTAINED IS THE DATA BASE DERIVED BY RUNNING THE
!	TESTS.
!	IF THE 'LOOP ON PROGRAM' FEATURE IS ACTIVATED, THE ENTIRE TEST
!	SEQUENCE IS REPEATED INDEFINITELY.  OTHERWISE, CONTROL IS
!	RETURNED TO THE 'CSL' PROGRAM VIA AN END-OF-PROGRAM UUO.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	LOOP_ON_PRG	= 1 IF INDEFINITE PROGRAM PASSES ARE TO BE RUN
!			  0 IF ONLY ONE PROGRAM PASSES IS TO BE RUN
!	AC0		= THE 'CSL' PROGRAM PASSES A FLAG IN AC0.
!			  1 MEANS THE PROGRAM IS BEING RUN AS PART OF A
!				FAULT INSERTION OR QV SCRIPT. HENCE,
!				DON'T ASK QUESTIONS.
!			  0 MEANS NORMAL OPERATION.
!
! IMPLICIT OUTPUTS:
!
!	AC0 IS LOADED WITH A FLAG.  0 MEANS NO FAILURES WERE DETECTED.
!				    1 MEANS FAILURE(S) OCCURRED.
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!--

    BEGIN

    EXTERNAL ROUTINE
	SPEC_DIALOGUE : NOVALUE;		!ALLOWS SPECIAL START-UP DIALOGUE BASED ON TEST MODULE

    REGISTER
	AC0 = 0;

    OWN
	PASS_CNT,				!COUNTER FOR PROGRAM PASS COUNT
	FIRST_PASS : INITIAL (0);		!FLAG USED TO DETERMINE PRINTING OF PROGRAM NAME

    SCRIPT_RUN = .AC0;				!GET SCRIPTING FLAG
!IF IT IS THE FIRST PASS OF THE PROGRAM, THEN TYPE THE PROGRAM NAME
!AND VERSION NUMBERS AND ANY SPECIAL STARTUP DIALOGUE.

    IF .FIRST_PASS EQL 0
    THEN
	BEGIN
	PRINT_HEADER ();
	FIRST_PASS = 1;				!SET FLAG SO WE ONLY DO THIS BLOCK ONCE
	SPEC_DIALOGUE ();			!GO DO SPECIAL DIALOGUE IN TEST MODULE
	END;

!IF THIS IS A SCRIPTING RUN, DON'T PRINT FEATURES OR ASK QUESTIONS.

    IF .SCRIPT_RUN EQL 0
    THEN
	BEGIN
	PRT_FEATURES ();			!GO PRINT LIST OF FEATURES
	ASK_FEATURES ();			!GO ASK FOR FEATURE CHANGES
	END;

    PASS_CNT = 0;				!INITIALIZE PASS COUNT
!REPEAT THE TESTING INDEFINITELY IF THE 'LOOP-ON-PROGRAM' FEATURE IS
!ACTIVATED.

    DO
	BEGIN
	INIT_DATA ();				!INITIALIZE THE DATA BASE AND FLAGS
	DISPATCH ();				!GO DISPATCH TO THE TEST ROUTINES
	NET_RPT ();				!REPORT RESULTS OF FAULT ISOLATION
	PASS_CNT = .PASS_CNT + 1;		!INCREMENT PASS COUNT
	PRT_TXT_F ('END OF PASS #');
	PRT_DEC_F (.PASS_CNT);
	PRT_CRLF_F;
	END
    WHILE .LOOP_ON_PRG NEQ 0;

    AC0 = .HAD_FAILURE;				!SET AC0 WITH FAILURE FLAG FOR 'CSL'
    EOP_UUO;					!RETURN TO 'CSL'
    END;

ROUTINE PRINT_HEADER : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PRINTS THE PROGRAM NAME AND THE EDIT AND VERSION
!	NUMBERS OF THE THREE MODULES WHICH MAKE UP A STIRS PROGRAM -
!	THE CONTROL MODULE (THIS ONE), THE TEST MODULE, AND THE DATA
!	BASE MODULE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	PRGNAM		= THIS IS THE ADDRESS OF THE PLIT CONTAINING
!			  THE PROGRAM NAME.  IT IS A GLOBAL VARIABLE
!			  WHICH IS DEFINED IN THE TEST MODULE.
!	CONTROL_VERSION	= THIS IS A LITERAL VALUE DEFINING THE VERSION
!			  NUMBER OF THIS MODULE (CONTROL).
!	CONTROL_EDIT	= THIS IS A LITERAL VALUE DEFINING THE EDIT
!			  LEVEL OF THIS MODULE (CONTROL).
!	TEST_VERSION	= THIS IS A GLOBAL LITERAL VALUE DEFINING THE
!			  VERSION NUMBER OF THE TEST MODULE.  IT IS
!			  DEFINED IN THE TEST MODULE.
!	TEST_EDIT	= THIS IS A GLOBAL LITERAL VALUE DEFINING THE
!			  EDIT LEVEL OF THE TEST MODULE.  IT IS
!			  DEFINED IN THE TEST MODULE.
!	DATA_VERSION	= THIS IS A GLOBAL LITERAL VALUE DEFINING THE
!			  VERSION NUMBER OF THE DATA BASE MODULE.  IT IS
!			  DEFINED IN THE DATA BASE MODULE.
!	DATA_EDIT	= THIS IS A GLOBAL LITERAL VALUE DEFINING THE
!			  EDIT LEVEL OF THE DATA BASE MODULE.  IT IS
!			  DEFINED IN THE DATA BASE MODULE.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	THE PROGRAM NAME AND THE VERSION AND EDIT NUMBERS OF THE
!	THREE MODULES ARE PRINTED ON THE TTY.
!--

    BEGIN

    EXTERNAL
	PRGNAM;					!PLIT WITH PROGRAM NAME

    EXTERNAL LITERAL
	TEST_VERSION,				!VERSION NUMBER OF TEST MODULE
	TEST_EDIT,				!EDIT NUMBER OF TEST MODULE
	DATA_VERSION,				!VERSION NUMBER OF DATA MODULE
	DATA_EDIT;				!EDIT NUMBER OF DATA MODULE

    REGISTER
	AC0 = 0;

    PRT_MSG_F (PRGNAM);				!PRINT THE PROGRAM NAME
    PRT_CRLF_F;
    PRT_TXT_F ('CONTROL MODULE ');
    PRT_DEC_F (CONTROL_EDIT);			!PRINT THE EDIT # OF THIS MODULE
    PRT_TXT_F ('.');
    PRT_DEC_F (CONTROL_VERSION);		!PRINT THE VERSION # OF THIS MODULE
    PRT_TXT_F ('    TEST MODULE ');
    PRT_DEC_F (TEST_EDIT);			!PRINT THE EDIT # OF THE TEST MODULE
    PRT_TXT_F ('.');
    PRT_DEC_F (TEST_VERSION);			!PRINT VERSION # OF TEST MODULE
    PRT_TXT_F ('    DATA MODULE ');
    PRT_DEC_F (DATA_EDIT);			!PRINT EDIT # OF DATA MODULE
    PRT_TXT_F ('.');
    PRT_DEC_F (DATA_VERSION);			!PRINT VERSION # OF DATA MODULE
    PRT_CRLF_F;
    PRT_CRLF_F;
    END;
ROUTINE PRT_FEATURES : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PRINTS A LIST OF ACTIVATED FEATURES.  IF NO
!	FEATURES ARE ACTIVATED, IT PRINTS 'NONE'.
!	THE FEATURES WHICH ARE COMMON TO ALL THE DIFFERENT TEST MODULES
!	ARE MAINTAINED IN THIS MODULE.  HOWEVER, SOME TEST MODULES HAVE
!	SPECIAL FEATURES WHICH ARE MAINTAINED BY THE TEST MODULE.
!	WHETHER OR NOT SUCH FEATURES ARE ACTIVATED IS PRINTED BY THE
!	'SPEC_PRT' ROUTINE, WHICH RESIDES IN THE TEST MODULE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	FEATURES SWITCHES -
!	BELL_ON_ERR	= 1 IF BELL IS TO BE RUNG ON DETECTION OF ERROR
!			  0 IF BELL IS NOT TO BE RUNG
!	LOOP_ON_ERR	= 1 IF PROGRAM IS TO LOOP ON FAILING ERROR
!			  0 IF NO LOOPING IS DESIRED
!	LOOP_ON_TEST	= 1 IF PROGRAM IS TO LOOP ON SPECIFIED TEST
!			  0 IF NO TEST LOOPING IS DESIRED
!	LOOP_TEST	= NUMBER OF TEST ON WHICH PROGRAM IS TO LOOP.
!			  THIS DATA IS MEANINGFUL ONLY IF 'LOOP_ON_TEST'
!			  SWITCH IS ACTIVATED.
!	NO_ISOLATION	= 1 IF FAULT ISOLATION IS TO BE TURNED OFF.
!			  0 IF FAULT ISOLATION IS TO BE PERFORMED.
!	SINGLE_STEP	= 1 IF USER WISHES TO MANUALLY SINGLE STEP THE
!			    DIAGNOSTIC MICROCODE OR THE SYSTEM CLOCK.
!			  0 IF NO MANUAL SINGLE STEPPING IS DESIRED
!	TEXT_INH	= 1 IF FUNCTIONAL ERROR DESCRIPTIONS ARE NOT TO
!			    BE PRINTED. (ONLY TEST AND ERROR NUMBERS AND
!			    CORRECT AND ACTUAL DATA).
!			  0 IF FULL ERROR PRINTOUTS ARE DESIRED.
!	LOOP_ON_PRG	= 1 IF INDEFINITE PROGRAM PASSES ARE TO BE RUN
!			  0 IF ONLY ONE PROGRAM PASSES IS TO BE RUN
!	PRT_TST_NUM	= 1 IF USER WANTS TEST NUMBERS PRINTED AS TESTS ARE RUN
!			  0 IF NO TEST NUMBERS ARE TO BE PRINTED
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PRINTS A LIST OF ACTIVATED FEATURES ON THE TTY.
!
!--
    BEGIN

    EXTERNAL ROUTINE
	SPEC_PRT;		!ROUTINE IN TEST MODULE TO PRINT SPECIAL FEATURES

    REGISTER
	AC0 = 0;


    PTXT_CRLF_F ('FEATURES ACTIVATED:');

!IF ANY FEATURE IS ACTIVATED, THEN PRINT THOSE THAT ARE.

    IF ( SPEC_PRT()	OR		!SPEC_PRT RETURNS 1 IF IT PRINTED ANY FEATURES
	.BELL_ON_ERR	OR
	.LOOP_ON_ERR	OR
	.LOOP_ON_TEST	OR
	.TEXT_INH	OR
	.SINGLE_STEP	OR
	.LOOP_ON_PRG	OR
	.PRT_TST_NUM	OR
	.NO_ISOLATION)	EQL 0

    THEN
	PTXT_CRLF_F ('NONE')			!NO FEATURES ACTIVATED
    ELSE

!PRINT LIST OF THOSE FEATURES WHICH ARE ACTIVATED

	BEGIN

	IF .BELL_ON_ERR THEN PTXT_CRLF_F ('RING BELL ON ERROR');

	IF .LOOP_ON_ERR NEQ 0
	THEN
	    BEGIN
	    PRT_TXT_F ('LOOP ON ERROR');

	    IF .FAST_LOOP NEQ 0 THEN PRT_TXT_F (' (FAST LOOPING WHERE POSSIBLE)');

	    PRT_CRLF_F;
	    END;

	IF .LOOP_ON_TEST NEQ 0
	THEN
	    BEGIN
	    PRT_TXT_F ('LOOP ON TEST NUMBER ');
	    PRT_DEC_F (.LOOP_TEST);
	    PRT_CRLF_F;
	    END;

	IF .NO_ISOLATION NEQ 0 THEN PTXT_CRLF_F ('NO FAULT ISOLATION');

	IF .SINGLE_STEP NEQ 0 THEN PTXT_CRLF_F ('SINGLE STEP DIAGNOSTIC MICROCODE AND SYSTEM CLOCK');

	IF .TEXT_INH NEQ 0 THEN PTXT_CRLF_F ('SHORT ERROR PRINTOUTS');

	IF .LOOP_ON_PRG THEN PTXT_CRLF_F ('LOOP ON PROGRAM');

	IF .PRT_TST_NUM THEN PTXT_CRLF_F ('PRINTING TEST NUMBERS');

	END;

    PRT_CRLF_F;
    END;
ROUTINE ASK_FEATURES : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CONTROLS THE ACTIVATION OF PROGRAM RUNTIME FEATURES.
!	IT FIRST ASKS THE USER IF HE/SHE WISHES TO CHANGE ACTIVATED
!	FEATURES.  IF NOT, NOTHING IS DONE.  IF YES, THEN THE USER IS
!	ASKED IF HE/SHE WISHES TO ACTIVATE EACH FEATURE, ONE AT A TIME.
!	THE FLAG ASSOCIATED WITH EACH FEATURE IS SET OR CLEARED BASED
!	ON THE RESPONSE.  THE ASKING OF SOME OF THE QUESTIONS IS 
!	CONDITIONAL ON PREVIOUS RESPONSES.  SPECIFICALLY, IF 'LOOPING
!	ON ERROR' IS NOT ACTIVATED, THEN IT IS NOT NECESSARY TO ASK IF
!	'FAST LOOPING' IS DESIRED.  ALSO, IF 'LOOP ON TEST' IS ACTIVATED,
!	THEN IT IS NOT NECESSARY TO ASK IF 'LOOP ON PROGRAM' OR 'PRINTING
!	OF TEST NUMBERS' ARE DESIRED.
!	THE ACTIVATION OF SPECIAL FEATURES PECULIAR TO A GIVEN TEST
!	MODULE IS CONTROLLED BY THE 'SPEC_ASK' ROUTINE WHICH RESIDES IN
!	THE TEST MODULE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	FEATURES SWITCHES -
!	BELL_ON_ERR	= 1 IF BELL IS TO BE RUNG ON DETECTION OF ERROR
!			  0 IF BELL IS NOT TO BE RUNG
!	LOOP_ON_ERR	= 1 IF PROGRAM IS TO LOOP ON FAILING ERROR
!			  0 IF NO LOOPING IS DESIRED
!	LOOP_ON_TEST	= 1 IF PROGRAM IS TO LOOP ON SPECIFIED TEST
!			  0 IF NO TEST LOOPING IS DESIRED
!	LOOP_TEST	= NUMBER OF TEST ON WHICH PROGRAM IS TO LOOP.
!			  THIS DATA IS MEANINGFUL ONLY IF 'LOOP_ON_TEST'
!			  SWITCH IS ACTIVATED.
!	NO_ISOLATION	= 1 IF FAULT ISOLATION IS TO BE TURNED OFF.
!			  0 IF FAULT ISOLATION IS TO BE PERFORMED.
!	SINGLE_STEP	= 1 IF USER WISHES TO MANUALLY SINGLE STEP THE
!			    DIAGNOSTIC MICROCODE AND THE SYSTEM CLOCK.
!			  0 IF NO MANUAL SINGLE STEPPING IS DESIRED
!	TEXT_INH	= 1 IF FUNCTIONAL ERROR DESCRIPTIONS ARE NOT TO
!			    BE PRINTED. (ONLY TEST AND ERROR NUMBERS AND
!			    CORRECT AND ACTUAL DATA).
!			  0 IF FULL ERROR PRINTOUTS ARE DESIRED.
!	LOOP_ON_PRG	= 1 IF INDEFINITE PROGRAM PASSES ARE TO BE RUN
!			  0 IF ONLY ONE PROGRAM PASSES IS TO BE RUN
!	PRT_TST_NUM	= 1 IF USER WANTS TEST NUMBERS PRINTED AS TESTS ARE RUN
!			  0 IF NO TEST NUMBERS ARE TO BE PRINTED
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!
!--
    BEGIN

    EXTERNAL ROUTINE
	SPEC_ASK : NOVALUE;

    REGISTER
	AC0 = 0;

    PRT_TXT_F ('DO YOU WISH TO CHANGE ACTIVATED FEATURES?');

    IF TTI_YES
    THEN
	BEGIN
	SPEC_ASK ();				!GO ASK ABOUT SPECIAL FEATURES
	PRT_TXT_F ('RING BELL ON ERROR?');
	BELL_ON_ERR = TTI_YES;
	PRT_TXT_F ('INHIBIT FAULT ISOLATION?');
	NO_ISOLATION = TTI_YES;
	PRT_TXT_F ('SHORT ERROR PRINTOUTS?');
	TEXT_INH = TTI_YES;
	PRT_TXT_F ('SINGLE STEPPING OF DIAG MICROCODE AND SYSTEM CLOCK?');
	SINGLE_STEP = TTI_YES;
	PRT_TXT_F ('LOOP ON ERROR?');

!IF 'LOOP ON ERROR' IS NOT ACTIVATED, IT IS NOT NECESSARY TO ASK ABOUT
!'FAST LOOPING'.

	IF (LOOP_ON_ERR = TTI_YES) NEQ 0
	THEN
	    BEGIN
	    PRT_TXT_F ('FAST LOOPING WHERE POSSIBLE?');
	    FAST_LOOP = TTI_YES;
	    END
	ELSE
	    FAST_LOOP = 0;

	PRT_TXT_F ('LOOP ON SPECIFIC TEST?');

!IF 'LOOP ON TEST' IS ACTIVATED, THEN ASK WHICH TEST NUMBER TO LOOP ON.
!AND DON'T BOTHER TO ASK ABOUT 'LOOP ON PROGRAM' OR 'PRINT TEST NUMBERS'.

	IF (LOOP_ON_TEST = TTI_YES) NEQ 0
	THEN
	    BEGIN
	    LOOP_ON_PRG = PRT_TST_NUM = 0;
	    LOOP_TEST = GET_NUM (UPLIT (%ASCIZ'TEST NUMBER'), MAXTEST);
	    END
	ELSE
	    BEGIN
	    PRT_TXT_F ('LOOP ON PROGRAM?');
	    LOOP_ON_PRG = TTI_YES;
	    PRT_TXT_F ('PRINT TEST NUMBERS AS THEY ARE RUN?');
	    PRT_TST_NUM = TTI_YES;
	    END;

	END;

    PRT_CRLF_F;
    END;

GLOBAL ROUTINE MEMSIZE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE ASKS THE USER HOW MUCH MEMORY EXISTS ON THE KS10
!	UNDER TEST.  IT IS CALLED FROM A TEST MODULE DURING THE START-
!	UP DIALOGUE.  IF THE PROGRAM IS BEING RUN IN THE SCRIPTED MODE,
!	NO QUESTIONS CAN BE ASKED.  SO A DEFAULT SIZE OF 128K IS ASSUMED.
!	THIS ASSUMPTION IS PRINTED ON THE TTY.  IF THE USER TYPES AN
!	INVALID NUMBER OR FORMAT, HE/SHE IS REPROMPTED UNTIL A VALID
!	RESPONSE IS GIVEN.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	THE AMOUNT OF MEMORY ON THE KS10 UNDER TEST, IN 'K'.
!
! SIDE EFFECTS:
!
!	NONE
!
!--
    BEGIN

    REGISTER
	AC0 = 0;


!IF WE'RE NOT SCRIPTING, ASK HOW MUCH MEMORY KS10 HAS?

    IF .SCRIPT_RUN EQL 0
    THEN
	BEGIN
	PRT_TXT_F ('HOW MANY K OF MEMORY DOES THE KS10 HAVE (IN DECIMAL)?:');

!STAY IN THE LOOP UNTIL A VALID ANSWER IS RECEIVED

	WHILE 1 DO
	    BEGIN

!THE TTI_DEC UUO RETURNS A 0 IF AN INVALID NUMBER FORMAT WAS RECEIVED.  IT
!RETURNS A 1 IF A VALID FORMAT WAS RECEIVED WITH THE NUMBER IN AC0.

	    IF TTI_DEC
	    THEN
		SELECTONEU .AC0 OF		!CHECK FOR VALID NUMBER
		    SET
		    [64,128,192,256,320,384,448,512]:	RETURN .AC0;
		    [OTHERWISE]:	PTXT_CRLF_F ('INVALID NUMBER');
		    TES
	    ELSE
		BEGIN
		PTXT_CRLF_F ('INVALID NUMBER FORMAT');
		TTI_CLR;			!CLEAR BAD INPUT FROM BUFFER
		END;

!REPROMPT USER, TELL HIM VALID RESPONSES.

	    PRT_TXT_F ('TRY AGAIN, NUMBER MUST BE 64,128,192,256,320,384,448,512: ');
	    END
	END
    ELSE
	BEGIN
	PTXT_CRLF_F ('ASSUMING 128K OF MEMORY ON KS10 UNDER TEST');
	RETURN 128;
	END;
    0					!TO AVOID INFO MESSAGE WHEN COMPILING
    END;

ROUTINE GET_NUM (PROMPT, MAXVAL) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO INPUT A NUMBER FROM THE TTY.
!	IT TYPES THE PROMPT POINTED TO BY THE PASSED PARAMETER 'PROMPT'
!	AND INDICATES THE MAXIMUM ALLOWED VALUE ( AS DICTATED BY THE
!	PASSED PARAMETER MAXVAL).  IT THEN WAITS FOR INPUT USING
!	A 'CSL' PROGRAM ROUTINE INVOKED BY A LUUO.  THE INPUT IS
!	INTERPRETED AS DECIMAL.  IF THE NUMBER RECEIVED IS NOT A VALID
!	TEST NUMBER (OUT OF RANGE) OR IF THE TTY INPUT WAS IN A NON-
!	DECIMAL FORMAT, THEN AN ERROR MESSAGE IS TYPED AND THE PROMPT
!	IS REPEATED.
!
! FORMAL PARAMETERS:
!
!	PROMPT		= POINTER TO AN ASCIZ PROMPT MESSAGE
!	MAXVAL		= MAXIMUM VALUE ALLOWED AS INPUT
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	DECIMAL NUMBER RECEIVED AS TTY INPUT
!
! SIDE EFFECTS:
!
!	PRINTS PROMPT MESSAGE ON TTY AND RECEIVES USER RESPONSE.
!	IF TTY INPUT IS INVALID, PROMPT IS REPEATED.
!--

    BEGIN

    REGISTER
	AC0 = 0;

!STAY IN LOOP UNTIL USER GIVES VALID RESPONSE

    WHILE 1 DO
	BEGIN
	PRT_MSG_F (.PROMPT);			!TYPE PROMPT
	PRT_TXT_F (' (MAXIMUM ');
	PRT_DEC_F (.MAXVAL);
	PRT_TXT_F ('):');

!THE TTI_DEC UUO RETURNS A 0 IF AN INVALID NUMBER FORMAT WAS RECEIVED.  IT
!RETURNS A 1 IF A VALID FORMAT WAS RECEIVED WITH THE NUMBER IN AC0.

	IF TTI_DEC
	THEN

	    IF (.AC0 GTR 0) AND (.AC0 LEQ .MAXVAL)	!IS NUMBER OUT OF RANGE
	    THEN
		RETURN .AC0			!NO, RETURN WITH NUMBER
	    ELSE
		PTXT_CRLF_F ('NUMBER OUT OF RANGE') !YES, PRINT ERROR MESSAGE

	ELSE
	    BEGIN
	    PTXT_CRLF_F ('INVALID NUMBER FORMAT'); !PRINT ERROR MESSAGE
	    TTI_CLR;				!CLEAR TTY INPUT BUFFER
	    END;

	END;

    0					!TO AVOID INFO MESSAGE WHEN COMPILING
    END;
ROUTINE INIT_DATA : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE INITIALIZES THOSE ITEMS OF THE DATA BASE WHICH
!	NEED INITIALIZATION, INCLUDING THE POSSIBLE-FAULTY-NETWORK
!	VECTOR AND ASSORTED PROGRAM FLAGS.  IT ALSO PASSES 'CONTROL-T'
!	INFORMATION TO 'CSL'.  NAMELY, THE NUMBER OF TESTS AND THE
!	ADDRESS WHERE THE NUMBER OF THE TEST BEING RUN IS STORED.
!	LASTLY, IT CALLS A 'TEST_INIT' ROUTINE LOCATED IN THE TEST
!	MODULE TO DO ANY SPECIAL INITIALIZATION.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	MAXNETS		= A GLOBAL LITERAL DEFINING THE NUMBER OF NETWORKS
!			  IN THE BOARD BEING TESTED.
!	MAXTEST		= A GLOBAL LITERAL DEFINING THE NUMBER OF TESTS
!	TEST_NUM	= THE ADDRESS OF THE TEST BEING EXECUTED
!
! IMPLICIT OUTPUTS:
!
!	HAD_FAILURE	= FLAG INDICATING IF ERROR WAS DETECTED
!	MSG_FILE_OPEN	= FLAG INDICATING WHETHER ERROR MESSAGE FILE IS OPEN
!	LAST_MEM_ADDR	= LAST MEMORY ADDRESSED REFERENCED BYF 'LA' OR 'EM' COMMAND
!	LAST_IO_ADDR	= LAST I/O ADDRESSED REFERENCED BY 'LI' OR 'EI' COMMAND
!	LAST_REG_ADDR	= LAST REGISTER ADDRESSED REFERENCED BY 'LR' OR 'ER' COMMAND
!	SUB_LOADED	= FLAG INDICATING WHETHER 'X1' SUBROUTINE IS LOADED
!	LOOPING		= FLAG INDICATING THAT PROGRAM IS LOOPING ON ERROR
!	LINE_CHARS	= COUNTER USED BY 'SEND_LINE' ROUTINE TO COUNT THE # OF CHARS IN CMD LINE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!--

    BEGIN

    EXTERNAL ROUTINE
	TEST_INIT;

    REGISTER
	AC0 = 0;

    MAP
	NET_FAULTS : VECTOR;

    NETWRDS = (MAXNETS + 35)/36;

    INCR I FROM 0 TO .NETWRDS - 1 BY 1 DO
	NET_FAULTS [.I] = -1;

    HAD_FAILURE = 0;				!INIT TO NO FAILURE STATE
    MSG_FILE_OPEN = 0;				!INIT TO FILE NOT OPEN STATE

!INIT ADDRESS FLAGS TO NON-EXISTENT ADDRESSES
    LAST_MEM_ADDR = -1;
    LAST_IO_ADDR = -1;
    LAST_REG_ADDR = -1;

    SUB_LOADED = 0;				!INIT TO SUB NOT LOADED STATE
    LOOPING = 0;				!INIT TO NOT LOOPING STATE
    LINE_CHARS = 0;				!INIT TO ZERO CHAR COUNT
    AC0<18, 18> = MAXTEST;			!PUT MAX # OF TESTS IN LH OF AC0
    AC0<0, 18> = TEST_NUM;			!PUT ADDR OF TEST NUMBER LOC IN RH OF AC0
    SEND_INFO;					!PASS CONTROL-T INFO TO 'CSL'
    TEST_INIT ();				!CALL TEST MODULE INIT ROUTINE
    END;
ROUTINE DISPATCH : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CONTROLS THE TEST DISPATCHING.  IF THE USER HAS
!	SELECTED TO LOOP ON A SPECIFIED TEST, THEN THE TEST HE HAS
!	SPECIFIED IS IMMEDIATELY EXECUTED AND INDEFINITELY REPEATED.
!	AFTER THE FIRST EXECUTION OF THAT TEST A MESSAGE IS TYPED
!	INFORMING THE USER THAT HE IS LOOPING ON THAT TEST.
!	IF LOOP-ON-TEST IS NOT ACTIVATED THEN NORMAL TEST DISPATCHING
!	IS DONE.  THE TESTS ARE CONSIDERED IN SEQUENTIAL ORDER.  FIRST,
!	THE 'RUN_CHK' ROUTINE IS CALLED TO DETERMINE WHETHER OR NOT THE
!	TEST SHOULD BE EXECUTED (SEE DESCRIPTION OF 'RUN_CHK' FOR
!	DETAILS).  IF NOT, THEN THE TEST IS SKIPPED.  IF YES, THEN THE
!	TEST IS DISPATCHED TO VIA THE TEST DISPATCH TABLE.
!	RETURN TO THE CALLING PROGRAM IS MADE AFTER ALL TESTS HAVE
!	BEEN EITHER SKIPPED OR EXECUTED.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	FEATURES SWITCHES:
!	LOOP_ON_TEST	= 1 IF PROGRAM IS TO LOOP ON SPECIFIED TEST
!			  0 IF NO TEST LOOPING IS DESIRED
!	LOOP_TEST	= NUMBER OF TEST ON WHICH PROGRAM IS TO LOOP.
!			  THIS DATA IS MEANINGFUL ONLY IF 'LOOP_ON_TEST'
!			  SWITCH IS ACTIVATED.
!	PRT_TST_NUM	= 1 IF USER WANTS TEST NUMBERS PRINTED AS TESTS ARE RUN
!			  0 IF NO TEST NUMBERS ARE TO BE PRINTED
!	MAXTEST		= NUMBER OF TESTS TO BE RUN
!	TEST_DISP	= TEST DISPATCH TABLE. THIS CONTAIN STARTING
!			  ADDRESSES OF THE TESTS AND IS LOCATED IN THE
!			  DATA MODULE.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	TEST_NUM	= THE NUMBER OF THE TEST BEING EXECUTED
!	IF 'PRT_TST_NUM' FEATURE IS ACTIVATED, A 'STARTING TEST NUMBER X'
!		MESSAGE WILL GET PRINTED BEFORE EACH TEST IS RUN.
!	IF 'LOOP_ON_TEST' FEATURE IS ACTIVATED, A MESSAGE TO THAT EFFECT
!		WILL BE PRINTED AFTER THE FIRST EXECUTION OF THAT TEST.
!--

    BEGIN

    EXTERNAL
	TEST_DISP;				!TEST DISPATCH TABLE

    MAP
	TEST_DISP : VECTOR;

    REGISTER
	AC0 = 0;

    LOCAL
	FIRST;					!FLAG FOR LOOPING MESSAGE PRINTING

!IF 'LOOP ON TEST' FEATURE IS ACTIVATED, THEN INDEFINITELY LOOP ON TEST SPECIFIED
!IN 'LOOP_TEST'.

    IF .LOOP_ON_TEST NEQ 0
    THEN
	BEGIN
	TEST_NUM = .LOOP_TEST;			!GET NUMBER OF TEST TO LOOP ON
	FIRST = 1;				!SET FIRST TIME THRU FLAG

	WHILE 1 DO
	    BEGIN
	    (.TEST_DISP [.LOOP_TEST - 1]) ();	!GO EXECUTE TEST

	    IF .FIRST EQL 1			!IF FIRST TIME THRU THEN PRINT MESSAGE
	    THEN
		BEGIN
		PRINT_TXT ('YOU ARE LOOPING ON TEST NUMBER ');
		PRINT_DEC (.LOOP_TEST);
		PRINT_CRLF;
		FIRST = 0;			!CLEAR FIRST TIME THRU FLAG
		END;

	    END;

	END;

!SEQUENTIALLY EXECUTE THE TESTS.  BEFORE RUNNING EACH ONE CHECK IF IT SHOULD BE
!RUN.

    INCR I FROM 1 TO MAXTEST BY 1 DO
	BEGIN
	TEST_NUM = .I;				!GET NEXT TEST NUMBER

	IF RUN_CHK ()				!SHOULD THIS TEST BE RUN?
	THEN
	    BEGIN				!YES

	    IF .PRT_TST_NUM NEQ 0		!IF PRINT TEST #S SWITCH IS SET
	    THEN
		BEGIN
		PRINT_TXT ('STARTING ');	!THEN PRINT MESSAGE
		PTSTNUM ();
		END;

	    (.TEST_DISP [.TEST_NUM - 1]) ();	!EXECUTE TEST
	    END;

	END;

    END;
ROUTINE RUN_CHK =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PERFORMS A CHECK TO DETERMINE WHETHER OR NOT THE
!	NEXT TEST SHOULD BE EXECUTED.
!	IF THE 'NO_ISOLATION' SWITCH IS ACTIVATED THEN ALL TESTS ARE TO
!	BE EXECUTED. THEREFORE, AN IMMEDIATE RUN-THE-TEST RETURN (1) IS
!	MADE.
!	THE DECISION TO RUN IS MADE BY COMPARING THE CUMULATIVE FAULTY
!	NETWORKS VECTOR WITH THE VECTORS FOR THE TEST BEING EVALUATED.
!	IF THERE IS NO OVERLAP BETWEEN THEM, THE TEST IS NOT RUN.  THIS
!	INDICATES A CONDITION WHERE THE TEST WILL NOT DETECT ANY OF THE
!	FAULTS WHICH HAVE ALREADY BEEN ESTABLISHED AS POSSIBLE. IF THERE
!	IS OVERLAP, THEN A FURTHER CHECK IS MADE TO INSURE THAT THE
!	CUMULATIVE VECTOR  IS NOT JUST A SUBSET OF THE TEST VECTORS. IF
!	IT IS, THEN THE TEST IS NOT RUN.  THIS INDICATES A CONDITION
!	WHERE THE TEST WILL NOT YIELD ANY FURTHER FAULT RESOLUTION. IF
!	THERE IS OVERLAP AND IT IS NOT A SUBSET, THEN THE TEST IS RUN.
!	A GLOBAL FLAG IS PROVIDED WHICH CAN BE SET BY THE TEST MODULE TO
!	INHIBIT THE SUBSET CHECKING.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	ES_TBL		= TABLE OF POINTERS TO TEST ERROR SIGNATURES (VECTORS)
!	NES_TBL		= TABLE OF POINTERS TO 'NO ERROR' SIGNATURES (VECTORS)
!	NET_FAULTS	= CUMULATIVE FAULTY NETWORK VECTOR
!	NETWRDS		= NUMBER OF 36-BIT WORDS IN NET_FAULTS
!	TEST_NUM	= NUMBER OF TEST TO BE EVALUATED
!	NO_ISOLATION	= 1 IF NOT DOING FAULT ISOLATION - RUN ALL TESTS
!			  0 IF DOING FAULT ISOLATION
!	NO_SUBSET	= GLOBAL FLAG FOR SUBSET CHECKING
!			  1 - DON'T CHECK FOR SUBSET
!			  0 - CHECK FOR SUBSET
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	1 IF TEST IS TO BE RUN
!	0 IF TEST IS NOT TO BE RUN
!
! SIDE EFFECTS:
!
!	NONE
!--

    BEGIN

    OWN
	TEMP : VECTOR [10];			!TEMP STORAGE

    LOCAL
	OVERLAP,				!BITVECTOR OVERLAP FLAG
	CNT,					!COUNTER FOR # OF BITVECTORS
	PTR,					!TEMP POINTER
	SIG_PTR;				!POINTER TO BITVECTOR

    MAP
	NET_FAULTS : VECTOR,
	PTR : REF VECTOR,
	SIG_PTR : REF VECTOR;

!IF NOT DOING FAULT ISOLATION, RUN ALL TESTS.

    IF .NO_ISOLATION NEQ 0 THEN RETURN 1;

    OVERLAP = 0;				!INIT FAULT OVERLAP FLAG
    PTR = .ES_TBL [.TEST_NUM - 1];		!GET POINTER TO TABLE OF ERROR PTRS
    CNT = .PTR [-1];				!GET NUMBER OF ERROR IN THIS TEST

!COMPARE EACH ERROR BITVECTOR WITH THE CUMULATIVE BITVECTOR

    INCR I FROM 0 TO .CNT - 1 BY 1 DO
	BEGIN
	SIG_PTR = .PTR [.I];			!GET POINTER TO ERROR BITVECTOR

!COMPARE BITVECTORS A WORD AT A TIME, ITS FASTER.

	INCR J FROM 0 TO .NETWRDS - 1 BY 1 DO
	    BEGIN
	    TEMP [.J] = .SIG_PTR [.J] AND .NET_FAULTS [.J]; !CHECK FOR OVERLAP

	    IF .TEMP [.J] NEQ 0			!IF THERE WAS OVERLAP THEN
	    THEN

		IF .NO_SUBSET EQL 0		!DOES TEST MODULE WANT SUBSET CHECKING?
		THEN
		    OVERLAP = -1		!YES, SET FLAG THAT THERE IS  FAULT OVERLAP
		ELSE
		    RETURN 1;			!NO, GIVE RUN-THE-TEST RETURN

	    END;

!IF THERE WAS OVERLAP AND SUBSET CHECKING IS NOT INHIBITED, THEN CHECK IF THE
!CUMULATIVE BITVECTOR IS A SUBSET OF THE ERROR BITVECTOR.  IF NOT, GIVE A
!RUN-THE-TEST RETURN.  IF YES, CONTINUE CHECKING NEXT BITVECTOR.

	IF .OVERLAP NEQ 0
	THEN

	    INCR J FROM 0 TO .NETWRDS - 1 BY 1 DO

		IF .TEMP [.J] NEQ .NET_FAULTS [.J] THEN RETURN 1;

	END;

!NOW CHECK IF THERE IS ANY OVERLAP BETWEEN THE 'NO ERROR' BITVECTORS AND THE
!CUMULATIVE BITVECTOR.

    PTR = .NES_TBL [.TEST_NUM - 1];		!GET POINTER TO TABLE OF NO ERROR PTRS

    IF .PTR NEQ 0				!ONLY CHECK IF THERE ARE NO ERROR BITVECTORS
    THEN
	BEGIN
	CNT = .PTR [-1];			!GET NUMBER OF NO ERROR IN THIS TEST

!COMPARE BITVECTORS FOR EACH OF THE 'NO ERROR' BITVECTORS, ONE AT A TIME.

	INCR I FROM 0 TO .CNT - 1 BY 1 DO
	    BEGIN
	    SIG_PTR = .PTR [.I];		!GET POINTER TO NO ERROR BITVECTOR

!COMPARE THE BITVECTORS A WORD AT A TIME FOR SPEED.

	    INCR J FROM 0 TO .NETWRDS - 1 BY 1 DO

		IF (.SIG_PTR [.J] AND .NET_FAULTS [.J]) NEQ 0 THEN RETURN 1;

	    END;

	END;

    RETURN 0;
    END;
ROUTINE NET_RPT : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO PRINT A LIST OF THE POSSIBLY FAULTY
!	NETWORKS AFTER ALL TESTING HAS BEEN DONE.  IT COMPILES THE LIST
!	USING THE INFORMATION IN THE FINAL CUMULATIVE FAULT VECTOR.
!	OFTEN, SEVERAL CONSECUTIVE BITS IN THE CUMULATIVE VECTOR ARE
!	ASSOCIATED WITH THE SAME NETWORK.  TO AVOID PRINTING THE SAME
!	NETWORK NAME MORE THAN ONCE, THE POINTER TO THE LAST NAME
!	PRINTED IS KEPT.  THEN BEFORE THE NEXT NETWORK NAME IS PRINTED,
!	THE POINTERS ARE COMPARED.  IF THEY ARE THE SAME THE NAME IS
!	NOT PRINTED.
!	IF THE 'NO ISOLATION' FEATURE WAS SELECTED, THEN THERE IS NO
!	LIST TO BE PRINTED.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NO_ISOLATION	= 1 IF NO FAULT ISOLATION WAS DONE - HENCE, NO LIST
!			  0 IF FAULT ISOLATION WAS DONE
!	HAD_FAILURE	= 1 IF AT LEAST ONE FAILURE WAS DETECTED
!			  0 IF NO FAILURES WERE DETECTED - HENCE, NO LIST
!	NET_FAULTS	= CUMULATIVE FAULTY NETWORK VECTOR
!	MAXNETS		= A GLOBAL LITERAL DEFINING THE NUMBER OF NETWORKS
!			  IN THE BOARD BEING TESTED.
!	NET_NAMES	= EXTERNAL TABLE OF NETWORK NAMES
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	A LIST OF POSSIBLE FAULTY NETWORKS IS PRINTED.
!--

    BEGIN

    EXTERNAL
	NET_NAMES;				!TABLE OF NETWORK NAMES

    MAP
	NET_NAMES : VECTOR;

    REGISTER
	AC0 = 0;

    LOCAL
	LAST_PTR,				!PTR TO LAST ASCIZ NAME STRING
	NAME_PTR;				!PTR TO CURRENT ASCII NAME STRING

!IF NO FAULT ISOLATION WAS DONE THEN THERE ARE NO FAULTY NETWORKS TO REPORT.

    IF .NO_ISOLATION NEQ 0			!IF NO FAULT ISOLATION WAS DONE
    THEN
	RETURN;					!DON'T REPORT ANYTHING

!THE CUMULATIVE FAULTY NETWORK BITVECTOR IS MEANINGFUL ONLY IF THERE WAS AT
!LEAST ONE ERROR.  ELSE REPORT NO FAULTS DETECTED.

    IF .HAD_FAILURE NEQ 0
    THEN
	BEGIN
	PRINT_CRLF;
	PTXT_CRLF ('POSSIBLE FAULTY NETWORKS');	!PRINT HEADING
	PTXT_CRLF ('-------- ------ --------');
	LAST_PTR = 0;				!INIT LAST PTR

!GO THRU CUMULATIVE BITVECTOR ONE BIT AT A TIME.

	INCR I FROM 0 TO MAXNETS - 1 BY 1 DO

	    IF .NET_FAULTS [.I] NEQ 0		!IF NETWORK BIT IS SET THEN
	    THEN
		BEGIN
		NAME_PTR = .NET_NAMES [.I];	!GET PTR TO NETWORK NAME

		IF .NAME_PTR NEQ .LAST_PTR	!AND PRINT IT IF IT IS DIFFERENT
						! FROM LAST NAME PRINTED.
		THEN
		    BEGIN
		    PRT_MSG_F (.NAME_PTR);	!PRINT NETWORK NAME
		    PRT_CRLF_F;
		    LAST_PTR = .NAME_PTR;	!UPDATE PTR TO LAST NAME PRINTED
		    END;

		END;

	END
    ELSE
	PTXT_CRLF_F ('NO FAULTS DETECTED');

    END;

GLOBAL ROUTINE ERR (NUM) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IN DETECTED.  IT IN
!	TURN CALLS A ROUTINE TO PERFORM FAULT ISOLATION BASED ON
!	THE ERROR AND A ROUTINE TO PRINT AN ERROR MESSAGE.  NO
!	CORRECT AND ACTUAL DATA OR SPECIAL PRINTING IS INVOLVED.
!
! FORMAL PARAMETERS:
!
!	NUM		= ERROR NUMBER
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!	THE CUMULATIVE FAULTY NETWORK VECTOR IS UPDATED BY 'FAILURE'.
!--

    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.NUM, .NUM, 0, 0, 0, 0);
    FAILURE (.NUM);
    END;

GLOBAL ROUTINE ERRCA (NUM, CORRECT, ACTUAL, DIGITS) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IN DETECTED WHICH INVOLVES
!	CORRECT AND ACTUAL DATA.  IT IN TURN CALLS A ROUTINE TO PERFORM
!	FAULT ISOLATION BASED ON THE ERROR AND A ROUTINE TO PRINT AN
!	ERROR MESSAGE.
!
! FORMAL PARAMETERS:
!
!	NUM		= ERROR NUMBER
!	CORRECT		= CORRECT DATA
!	ACTUAL		= ACTUAL DATA
!	DIGITS		= NUMBER OF OCTAL DIGITS IN CORRECT/ACTUAL DATA
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!	THE CUMULATIVE FAULTY NETWORK VECTOR IS UPDATED BY 'FAILURE'.
!--

    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.NUM, .NUM, .CORRECT, .ACTUAL, .DIGITS, 0);
    FAILURE (.NUM);
    END;

GLOBAL ROUTINE ERRCAS (ERR_NUM, MSG_NUM, CORRECT, ACTUAL, DIGITS, SPEC_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IS DETECTED WHICH INVOLVES
!	CORRECT AND ACTUAL DATA AND SPECIAL PRINTING.  IT IN TURNS CALLS
!	THE 'ERR_RPT' ROUTINE TO PRINT AN ERROR MESSAGE AND THE 'FAILURE'
!	ROUTINE TO UPDATE THE FAULTY NETWORK VECTOR.
!
! FORMAL PARAMETERS:
!
!	ERR_NUM		= ERROR NUMBER
!	MSG_NUM		= ERROR MESSAGE NUMBER
!	CORRECT		= CORRECT DATA
!	ACTUAL		= ACTUAL DATA
!	DIGITS		= NUMBER OF OCTAL DIGITS IN CORRECT/ACTUAL DATA
!	SPEC_PTR	= POINTER TO TABLE OF SPECIAL PRINT INFO
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!	THE CUMULATIVE FAULTY NETWORK VECTOR IS UPDATED BY 'FAILURE'.
!
!--
    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.ERR_NUM, .MSG_NUM, .CORRECT, .ACTUAL, .DIGITS, .SPEC_PTR);
    FAILURE (.ERR_NUM);
    END;

GLOBAL ROUTINE ERRS (ERR_NUM, MSG_NUM, SPEC_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IS DETECTED WHICH INVOLVES
!	SPECIAL PRINTING.  IT IN TURNS CALLS THE 'ERR_RPT' ROUTINE TO
!	PRINT AN ERROR MESSAGE AND THE 'FAILURE' ROUTINE TO UPDATE THE
!	CUMULATIVE FAULTY NETWORK VECTOR.
!
! FORMAL PARAMETERS:
!
!	ERR_NUM		= ERROR NUMBER
!	MSG_NUM		= ERROR MESSAGE NUMBER
!	SPEC_PTR	= POINTER TO TABLE OF SPECIAL PRINT INFO
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!	THE CUMULATIVE FAULTY NETWORK VECTOR IS UPDATED BY 'FAILURE'.
!
!--
    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.ERR_NUM, .MSG_NUM, 0, 0, 0, .SPEC_PTR);
    FAILURE (.ERR_NUM);
    END;

GLOBAL ROUTINE ERRM (NUM) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IN DETECTED.  IT IN
!	TURN CALLS THE 'ERR_RPT' ROUTINE TO PRINT AN ERROR MESSAGE.
!
! FORMAL PARAMETERS:
!
!	NUM		= ERROR NUMBER
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!--

    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.NUM, .NUM, 0, 0, 0, 0);
    END;

GLOBAL ROUTINE ERMCA (NUM, CORRECT, ACTUAL, DIGITS) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IN DETECTED WHICH INVOLVES
!	CORRECT AND ACTUAL DATA.  IT IN TURN CALLS THE 'ERR_RPT' ROUTINE
!	TO PRINT AN ERROR MESSAGE.
!
! FORMAL PARAMETERS:
!
!	NUM		= ERROR NUMBER
!	CORRECT		= CORRECT DATA
!	ACTUAL		= ACTUAL DATA
!	DIGITS		= NUMBER OF OCTAL DIGITS IN CORRECT/ACTUAL DATA
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!
!--

    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.NUM, .NUM, .CORRECT, .ACTUAL, .DIGITS, 0);
    END;

GLOBAL ROUTINE ERMCAS (MSG_NUM, CORRECT, ACTUAL, DIGITS, SPEC_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IS DETECTED WHICH INVOLVES
!	CORRECT AND ACTUAL DATA AND SPECIAL PRINTING.  IT IN TURNS CALLS
!	THE 'ERR_RPT' ROUTINE TO PRINT AN ERROR MESSAGE.
!
! FORMAL PARAMETERS:
!
!	MSG_NUM		= ERROR MESSAGE NUMBER
!	CORRECT		= CORRECT DATA
!	ACTUAL		= ACTUAL DATA
!	DIGITS		= NUMBER OF OCTAL DIGITS IN CORRECT/ACTUAL DATA
!	SPEC_PTR	= POINTER TO TABLE OF SPECIAL PRINT INFO
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!
!--
    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.MSG_NUM, .MSG_NUM, .CORRECT, .ACTUAL, .DIGITS, .SPEC_PTR);
    END;

GLOBAL ROUTINE ERMS (MSG_NUM, SPEC_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN AN ERROR IS DETECTED WHICH INVOLVES
!	SPECIAL PRINTING.  IT IN TURNS CALLS THE 'ERR_RPT' ROUTINE TO
!	PRINT AN ERROR MESSAGE.
!
! FORMAL PARAMETERS:
!
!	MSG_NUM		= ERROR MESSAGE NUMBER
!	SPEC_PTR	= POINTER TO TABLE OF SPECIAL PRINT INFO
!
! IMPLICIT INPUTS:
!
!	BELL_ON_ERROR	= 1 IF BELL IS TO BE RUNG
!			  0 IF BELL IS NOT TO BE RUNG
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ERROR MESSAGE IS PRINTED ON THE TTY.
!
!--
    BEGIN

    IF .BELL_ON_ERR NEQ 0			!IF BELL ON ERROR SWITCH IS SET
    THEN
	PBELL;					!THEN RING TTY BELL

    ERR_RPT (.MSG_NUM, .MSG_NUM, 0, 0, 0, .SPEC_PTR);
    END;

ROUTINE ERR_RPT (ERR_NUM, MSG_NUM, CORRECT, ACTUAL, DIGITS, SPEC_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO PRINT AN ERROR MESSAGE ON THE TTY
!	WHEN A ERROR IS DETECTED.
!	BEFORE THE FIRST ERROR MESSAGE IS PRINTED, A HEADING OF
!	'FAILING TESTS' IS PRINTED.  THEN FOR EACH ERROR THE TEST
!	NUMBER AND ERROR NUMBER ARE REPORTED.  IF THE TEXT INHIBIT
!	SWITCH IS ACTIVATED, NO FUNCTIONAL ERROR DESCRIPTION IS
!	PRINTED.  IF IT IS NOT ACTIVATED, THE ERROR MESSAGE FOR THE
!	FAILING TEST AND ERROR IS RETRIEVED FROM THE ERROR MESSAGE
!	FILE.  THIS IS AN ASCII FILE WITH TEST NUMBER AND ERROR NUMBER
!	FLAGS FOR EACH MESSAGE.  USING LUUO CALLS TO 'CSL' PROGRAM
!	FILE HANDLING ROUTINES, THE MESSAGE FILE IS READ UNTIL THE
!	SPECIFIED TEST AND ERROR NUMBER FLAGS ARE LOCATED.  THEN THE
!	MESSAGE IS TRANSFERRED A LINE AT A TIME INTO A BUFFER AND
!	PRINTED ON THE TTY UNTIL THE END-OF-MESSAGE TERMINATOR IS
!	REACHED.
!	SOME ERROR MESSAGES REQUIRE SPECIAL PRINTING.  THIS IS INDICATED
!	BY THE PRESENCE OF A '\' CHARACTER IN THE MESSAGE TEXT. WHEN
!	THIS CHARACTER IS DETECTED, THE 'PRT_SPEC' ROUTINE IS CALLED.
!	IF THE ERROR INVOLVES CORRECT AND ACTUAL DATA, A ROUTINE IS
!	CALLED TO PRINT THAT DATA.  THIS IS DONE REGARDLESS OF WHETHER
!	OR NOT THE TEXT INHIBIT SWITCH IS ACTIVATED.
!
! FORMAL PARAMETERS:
!
!	ERR_NUM		= ERROR NUMBER
!	MSG_NUM		= ERROR MESSAGE NUMBER
!	CORRECT		= CORRECT DATA
!	ACTUAL		= ACTUAL DATA
!	DIGITS		= NUMBER OF OCTAL DIGITS IN CORRECT/ACTUAL DATA
!	SPEC_PTR	= POINTER TO TABLE OF SPECIAL PRINT INFO
!
! IMPLICIT INPUTS:
!
!	LOOPING		= 1 IF LOOPING ON ERROR
!			  0 IF NOT LOOPING
!	LOOP_ERR_NUM	= ERROR NUMBER ON WHICH PROGRAM IS LOOPING
!			  (THIS IS MEANINGFUL ONLY IF 'LOOPING' IS A 1)
!	MSG_FILE_OPEN	= 1 IF MESSAGE FILE IS OPEN
!			  0 IF NOT OPENED
!	TEST_NUM	= NUMBER OF TEST BEING EXECUTED
!	HAD_FAILURE	= 0 IF NO PREVIOUS ERRORS
!			  1 IF ALREADY HAD ERRORS
!	TEXT_INH	= 1 IF ERROR DESCRIPTION IS NOT TO BE PRINTED
!			  0 IF DESCRIPTION IS TO BE PRINTED
!	MSGFIL		= PLIT POINTER TO SIXBIT ERROR MESSAGE FILE NAME
!	PAGE_IN		= FLAG INDICATING WHETHER A MESSAGE PAGE IS IN CORE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	AN ERROR MESSAGE IS PRINTED ON THE TTY.
!--

    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	TXT_BUF_PTR,				!BYTE POINTER INTO ERROR TEXT
	CH;					!CHARACTER FROM ERROR MSG FILE

    OWN
	LAST_ACTUAL,				!ACTUAL DATA FROM LAST ERROR MESSAGE
	TXT_BUF : CHAR_BUF [83],		!ERROR MESSAGE BUFFER
	LAST_TEST_MSG,				!# OF LAST TEST WHICH HAD ERROR
	LAST_MSG_NUM;				!# OF LAST ERROR MESSAGE PRINTED

    ERRFLG = 1;					!SET ERROR FLAG FOR 'LOOP_CHK" ROUTINE

!IF PROGRAM IS ALREADY LOOPING ON ERROR, THEN CHECK IF THIS ERROR PRECEDES THE
!ONE BEING LOOPED ON.  IF SO, THEN THIS ERROR MESSAGE MUST BE PRINTED AND THE
!LOOPING WILL BE TIGHTED TO THIS ERROR.  IF NOT, DON'T REPRINT THE ERROR MESSAGE
!JUST PRINT THE CORRECT AND ACTUAL ONLY IF THE ACTUAL CHANGED.

    IF .LOOPING NEQ 0				!ARE WE LOOPING ON ERROR?
    THEN

	IF .ERR_NUM LSS .LOOP_ERR_NUM		!YES, IS THIS A PRECEDING ERROR?
	THEN
	    MSG_FILE_OPEN = 0			!YES, SETUP TO REOPEN MSG FILE
						! AND PRINT ERROR MESSAGE
	ELSE
	    BEGIN

	    IF (.DIGITS NEQ 0) AND (.LAST_ACTUAL NEQ .ACTUAL) !NO, HAS ACTUAL CHANGED?
	    THEN
		PRINT_CA (.CORRECT, .ACTUAL, .DIGITS); !YES, PRINT NEW COR/ACT

	    RETURN;
	    END;

!IF THIS MESSAGE IS THE SAME AS THE PREVIOUS MESSAGE, THEN WE HAVE TO REOPEN
!THE MESSAGE FILE AND REREAD IT BECAUSE WE'VE ALREADY GONE PAST THE MESSAGE.

    IF (.TEST_NUM EQL .LAST_TEST_MSG) AND (.MSG_NUM LEQ .LAST_MSG_NUM)
    THEN
	MSG_FILE_OPEN = 0;			!SET FLAG TO REOPEN MESSAGE FILE

!IF THIS IS THE FIRST FAILURE, THEN PRINT THE ERROR MESSAGE HEADER.

    IF .HAD_FAILURE EQL 0
    THEN
	BEGIN
	PTXT_CRLF ('FAILING TESTS');
	PTXT_CRLF ('------- -----');
	HAD_FAILURE = -1;			!SET FLAG THAT WE HAD ERROR
	END;

    PRINT_CRLF;
    PRINT_TXT ('TEST #');
    PRINT_DEC (.TEST_NUM);			!PRINT TEST #
    PRINT_TXT ('  ERROR #');
    PRINT_DEC (.ERR_NUM);			!PRINT ERROR #
    PRINT_CRLF;

    IF .TEXT_INH EQL 0				!ONLY PRINT TEXT IF TEXT INHIBIT FEATURE IS OFF
    THEN
	BEGIN

	IF .MSG_FILE_OPEN EQL 0			!IF MESSAGE FILE ISN'T OPEN, DO IT
	THEN
	    BEGIN

	    IF FSELECT (MSGFIL)			!GO OPEN FILE
	    THEN
		BEGIN				!SUCCEEDED!
		MSG_FILE_OPEN = 1;		!SET FLAG THAT FILE IS OPEN
		PAGE_IN = 0;			!SET FLAG THAT NO PAGE IS IN CORE
		LAST_TEST_MSG = 0;		!INIT FLAG
		LAST_MSG_NUM = 0;		!INIT FLAG
		END
	    ELSE
		BEGIN				!FAILED, PRINT ERROR MESSAGE
		PRINT_TXT ('?ERROR - CANNOT OPEN MESSAGE FILE ');
		PNTSIX (.MSGFIL);		!PRINT FILNAME
		PRINT_TXT ('.');
		PNTSIX (.(MSGFIL + 1));		!PRINT EXTENSION
		PRINT_CRLF;
		RETURN;
		END;

	    END;

!IF THE CURRENT TEST NUMBER IS GREATER THAN THE ONE FOR THE ERROR LAST PRINTED,
!THEN SEARCH THRU THE MESSAGE FILE FOR THE TEST NUMBER AND KEY-CHAR.

	IF .TEST_NUM GTR .LAST_TEST_MSG
	THEN
	    BEGIN
	    LAST_TEST_MSG = FIND_NUM (.TEST_NUM, %C']');

	    IF .LAST_TEST_MSG EQL -1 THEN RETURN;

	    END;

!NOW SEARCH THRU THE FILE FOR THE MESSAGE NUMBER AND KEY-CHAR.

	LAST_MSG_NUM = FIND_NUM (.MSG_NUM, %C'[');

	IF .LAST_MSG_NUM EQL -1 THEN RETURN;

!READ ONE CHAR AT A TIME UNTIL THE START OF THE MESSAGE IS REACHED.

	DO
	    BEGIN
	    CH = GET_CHAR ();			!READ NEXT CHAR

	    IF .CH EQL -1			!DID WE REACH EOF?
	    THEN
		RETURN;				!YES, ABORT PRINTING

	    END
	UNTIL .CH EQL %C'!';			!UNTIL WE REACH START OF MESSAGE?

	TXT_BUF_PTR = POINT (TXT_BUF, 36, 7, 0, 0); !SETUP BYTE POINTER INTO BUFFER

!NOW WE SHOULD BE AT THE BEGINNING OF THE ERROR MESSAGE.  READ ONE CHAR AT A
!TIME AT PROCESS IT.

	DO
	    BEGIN
	    CH = GET_CHAR ();

	    SELECTONEU .CH OF
		SET

		[-1] :				!EOF WAS REACHED
		    RETURN;

		[%C'!'] :			!END OF MESSAGE MARKER
		    0;

		[%O'12'] :			!CAR-RET, GO PRINT MESSAGE LINE
		    BEGIN
		    REPLACEI (TXT_BUF_PTR, .CH); !PUT CR IN BUFFER
		    REPLACEI (TXT_BUF_PTR, 0);	!TERMINATE MSG LINE
		    PRINT_MSG (TXT_BUF);	!PRINT LINE
		    TXT_BUF_PTR = POINT (TXT_BUF, 36, 7, 0, 0); !REINIT BYTE PTR
		    END;

		[%C'\'] :			!SPECIAL PRINT KEY CHAR
		    BEGIN
		    REPLACEI (TXT_BUF_PTR, 0);	!TERMINATE CURRENT MSG LINE
		    PRINT_MSG (TXT_BUF);	!GO PRINT IT
		    TXT_BUF_PTR = POINT (TXT_BUF, 36, 7, 0, 0); !REINIT BYTE PTR
		    PRT_SPEC (.SPEC_PTR);	!GO DO SPECIAL PRINTING
		    END;

		[OTHERWISE] :			!PUT ALL OTHER CHARS INTO MSG LINE BUFFER
		    REPLACEI (TXT_BUF_PTR, .CH);
		TES;

	    END
	UNTIL .CH EQL %C'!';			!UNTIL WE REACH END OF MESSAGE

	END;

    IF .DIGITS NEQ 0				!IF DIGITS IS NON-ZERO, THEN
    THEN
	BEGIN
	PRINT_CA (.CORRECT, .ACTUAL, .DIGITS);	!PRINT CORRECT/ACTUAL
	LAST_ACTUAL = .ACTUAL;			!UPDATE LAST ACTUAL DATA
	END;

    END;
ROUTINE PRT_SPEC (PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE DOES THE SPECIAL PRINTING FOR ERROR MESSAGES.
!	SPECIAL PRINTING IS WHEN THE PROGRAMMER WISHES TO INSERT A
!	VARIABLE NUMBER OR TEXT STRING INTO THE ERROR MESSAGE.  THE
!	FORMAT FOR DOING THIS IS THE RESERVED CHARACTER '\' FOLLOWED BY
!	A PRINT MODE CHARACTER (O,D,S,U) FOLLOWED BY AN INDEX (0-9).
!	UPON ENTERING THIS ROUTINE, THE '\' HAS ALREADY BEEN DETECTED
!	BY THE 'ERR_RPT' ROUTINE.  THIS ROUTINE READS IN THE PRINT MODE
!	CHARACTER AND INDEX.  IT THEN USES THE INDEX TO ACCESS A TABLE
!	ENTRY IN THE TABLE POINTED TO BY THE PASSED PARAMETER.  THE
!	ENTRY IS PROCESSED BASED ON THE PRINT MODE.
!
!	PRINT MODE	ACTION
!	----------	------
!	     O		PRINT TABLE ENTRY AS OCTAL NUMBER
!	     D		PRINT TABLE ENTRY AS DECIMAL NUMBER
!	     S		PRINT ASCIZ STRING POINTED TO BY TABLE ENTRY
!	     U		PRINT TABLE ENTRY AS 12 UNSIGNED OCTAL DIGITS
!
! FORMAL PARAMETERS:
!
!	PTR		= POINTER TO A SPECIAL PRINT TABLE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PRINTS A SPECIAL NUMBER OR TEXT STRING AS PART OF AN ERROR
!	MESSAGE OR PRINTS AN ERROR MESSAGE IF INVALID CHARACTERS ARE
!	ENCOUNTERED.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	PRINT_MODE,
	INDEX;

    MAP
	PTR : REF VECTOR;

    PRINT_MODE = GET_CHAR ();			!NEXT CHAR IN MESSAGE IS PRINT MODE
    INDEX = GET_CHAR () - %O'60';		!GET NEXT MSG CHAR AND MAKE BINARY

    IF (.INDEX LSS 0) OR (.INDEX GTR 9)		!INDEX MUST BE NUMERIC
    THEN
	BEGIN
	PTSTNUM ();				!PRINT TEST NUMBER
	PTXT_CRLF ('SPECIAL PRINT NUMBER OUT OF RANGE');
	RETURN;
	END;

    AC0 = .PTR [.INDEX];			!GET ENTRY FROM SPECIAL PRINT TABLE

    SELECTONEU .PRINT_MODE OF			!PROCESS ENTRY BASED ON PRINT MODE
	SET

	[%C'O'] :
	    POCT_SUP (.AC0);			!PRINT OCTAL NUMBER

	[%C'D'] :
	    PRINT_DEC (.AC0);			!PRINT DECIMAL NUMBER

	[%C'S'] :
	    PRINT_MSG (.AC0);			!PRINT ASCIZ TEXT STRING

	[%C'U'] :
	    PRINT_OCT_12 (.AC0);		!PRINT 12 UNSIGNED OCTAL DIGITS
	[OTHERWISE]:
	    PTXT_CRLF ('INVALID SPECIAL PRINT MODE CHARACTER'); !PRINT ERROR MESSAGE
	TES;

    END;
ROUTINE GET_CHAR =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE READS THE NEXT CHARACTER FROM THE ERROR MESSAGE
!	FILE.  IT DOES SO BY MAKING AN LUUO CALL TO THE 'CSL' PROGRAM'S
!	FILE READ ROUTINE.  IF THE END-OF-FILE IS REACHED, AN ERROR
!	MESSAGE IS TYPED AND AN ERROR CODE IS RETURNED TO THE CALLING
!	ROUTINE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	PAGE_IN		= FLAG INDICATING IF PAGE OF MESSAGE TEXT IS IN BUFFER
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ASCII CHAR READ FROM MESSAGE FILE, OR
!	-1 IF END-OF-FILE IS REACHED
!
! SIDE EFFECTS:
!
!	IF END-OF-FILE IS REACHED, A MESSAGE TO THAT EFFECT WILL BE PRINTED
!--

    BEGIN

    REGISTER
	AC0 = 0;

    BIND
	EOF_MSG = UPLIT(%ASCIZ '?EOF REACHED WHILE READING MSG FILE');

    OWN
	CHAR_CNT,				!NUMBERS OF CHARS LEFT TO BE READ IN BUFFER
	CHAR_PTR;				!BYTE POINTER TO NEXT CHAR IN BUFFER

    LOCAL
	CHAR;

    IF .PAGE_IN EQL 0				!IF FLAG IS ZERO, WE NEED NEXT PAGE
    THEN

	IF FRDPAG				!TRY TO READ NEXT PAGE
	THEN

!IF THE PAGE WAS READ IN, FRDPAG RETURNS A 1 AND AC0 CONTAINS 'WORD CNT,,ADDRESS' OF BUFFER

	    BEGIN
	    CHAR_CNT = .AC0<18, 18>*5;		!COMPUTE CHAR COUNT
	    CHAR_PTR = POINT (.AC0<0, 18>, 36, 7, 0, 0);	!SETUP POINTER
	    PAGE_IN = 1;			!SET FLAG THAT PAGE IS IN BUFFER
	    END
	ELSE

!IF END-OF-FILE WAS REACHED, FRDPAG RETURNS 0

	    BEGIN
	    PRINT_MSG(EOF_MSG);			!PRINT EOF MESSAGE
	    MSG_FILE_OPEN = 0;			!RESET FLAG SO NEXT ERROR WILL REOPEN MSG FILE
	    RETURN -1;				!GIVE ERROR RETURN
	    END;

    CHAR = SCANI (CHAR_PTR);			!GET NEXT CHAR FROM BUFFER
    CHAR_CNT = .CHAR_CNT - 1;			!DECREMENT # OF CHARS LEFT IN BUFFER

    IF .CHAR_CNT EQL 0 THEN PAGE_IN = 0;	!RESET FLAG TO READ IN NEXT PAGE

    IF .CHAR EQL 0				!IF CHAR IS NULL, IT'S EOF
    THEN
	BEGIN
	PRINT_MSG(EOF_MSG);			!PRINT EOF MESSAGE
	MSG_FILE_OPEN = 0;			!RESET FLAG SO NEXT ERROR WILL REOPEN MSG FILE
	RETURN -1;				!GIVE ERROR RETURN
	END;

    RETURN .CHAR;

    END;
ROUTINE FIND_NUM (SRCH_NUM, KEY_CHAR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE SEARCHES THE ERROR MESSAGE FILE FOR THE FLAG
!	ASSOCIATED WITH THE CURRENT TEST NUMBER.
!	THIS FLAG IS OF THE FORM ']XXX' WHERE XXX IS A TEST NUMBER.
!	THE FILE IS READ A CHARACTER AT A TIME UNTIL A ']' IS REACHED.
!	THE SUCCEEDING CHARACTERS UP TO A 'CR' SHOULD ALL BE ASCII DIGITS.
!	IF NOT, AN ERROR MESSAGE IS PRINTED.  THE ASCII DIGITS ARE
!	INTERPRETED AS A DECIMAL NUMBER AND ARE CONVERTED TO A BINARY
!	NUMBER. THIS COMPARED TO THE TEST NUMBER BEING EXECUTED.
!	IF THERE IS A MATCH, THE NUMBER IS RETURNED.  OTHERWISE, THE
!	SEARCH CONTINUES.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	TEST_NUM	= NUMBER OF TEST BEING EXECUTED
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	IF TEST NUMBER FLAG IS FOUND, THE TEST NUMBER IS RETURNED.
!	IF THE END-OF-FILE IS REACHED OR AN INVALID FLAG IS FOUND, THEN
!		A -1 IS RETURNED.
!	IF AN NON-DIGIT ASCII CHAR IS FOUND IN THE NUMBER FIELD, AN
!		ERROR MESSAGE IS PRINTED AND A -1 IS RETURNED.
!
! SIDE EFFECTS:
!
!	NONE
!--

    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	CH,					!CHAR FROM BUFFER
	NUM;					!NUMBER FROM TEST NUMBER FLAG

    DO
	BEGIN

	DO
	    BEGIN
	    CH = GET_CHAR ();			!GET NEXT CHAR IN MSG FILE
	    IF .CH EQL -1			!CHECK IF EOF REACHED
	    THEN
		RETURN -1;
	    END
	WHILE .CH NEQ .KEY_CHAR;		!KEEP LOOKING TIL KEY IS FOUND

!GET THE NUMBER FOLLOWING THE KEY CHAR

	NUM = 0;				!INIT NUMBER VALUE

	WHILE 1 DO
	    BEGIN
	    CH = GET_CHAR ();			!GET NEXT DIGIT

	    SELECTONEU .CH OF			!SEE WHAT IT IS
		SET

		[%O'60' TO %O'71'] :		!ASCII NUMBER
		    BEGIN
		    NUM = .NUM*10 + (.CH - %O'60'); !SHIFT CUM VALUE AND ADD NEW VALUE
		    END;

		[%O'15'] :
		    EXITLOOP;			!CR MARKS END OF NUMBER

		[-1] :				!-1 MEANS EOF
		    RETURN -1;

		[OTHERWISE] :			!ANYTHING ELSE IS INVALID
		    BEGIN
		    PTXT_CRLF ('?NON-DIGIT CHAR IN A # FIELD OF MSG FILE');
		    RETURN -1;
		    END;
		TES;

	    END

	END
    WHILE .SRCH_NUM NEQ .NUM;			!KEEP LOOKING TIL DESIRED NUMBER IS FOUND

    RETURN .NUM;
    END;
ROUTINE PRINT_CA (CORRECT, ACTUAL, DIGITS) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PRINTS THE CORRECT AND ACTUAL DATA ASSOCIATED
!	WITH A FAILING TEST.  IT ALSO COMPUTES AND PRINTS THE
!	DISCREPANCIES, CORRECT 'XOR' ACTUAL.
!	THE DATA IS PRINTED IN OCTAL WITH THE NUMBER OF DIGITS
!	DETERMINED BY THE PASSED PARAMETER 'DIGITS'. FOR THE CASE
!	WHERE THE # OF DIGITS IS GREATER THAN 12 (THEREFORE, >36 BITS),
!	THE CORRECT AND ACTUAL PARAMETERS ARE INTERPRETED AS MULTIWORD
!	VECTORS.
!
! FORMAL PARAMETERS:
!
!	CORRECT		= CORRECT DATA
!	ACTUAL		= ACTUAL DATA
!	DIGITS		= # OF OCTAL DIGITS IN CORRECT AND ACTUAL
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	THE CORRECT, ACTUAL AND DISCREPANCY DATA ARE PRINTED ON THE TTY.
!--

    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	DISCREP : VECTOR [4];			!BUFFER FOR DISCREPANCY DATA

    PRINT_TXT ('CORRECT: ');

    IF .DIGITS GTR 12				! >12 DIGITS NEEDS SPECIAL PRINTING
    THEN
	PRT_GTR_12 (.CORRECT, .DIGITS)
    ELSE
	PNUM (.CORRECT, .DIGITS);

    PRINT_CRLF;
    PRINT_TXT ('ACTUAL:  ');

    IF .DIGITS GTR 12				! >12 DIGITS NEEDS SPECIAL PRINTING
    THEN
	PRT_GTR_12 (.ACTUAL, .DIGITS)
    ELSE
	PNUM (.ACTUAL, .DIGITS);

    PRINT_CRLF;
    PRINT_TXT ('DISCREP: ');

    IF .DIGITS GTR 12				! >12 DIGITS REQUIRES SPECIAL TREATMENT
    THEN
	BEGIN

	MAP
	    ACTUAL : REF VECTOR,
	    CORRECT : REF VECTOR;

!COMPUTE DISCREPANCY DATA WORD BY WORD
	INCR I FROM 0 TO (.DIGITS + 11)/12 BY 1 DO
	    DISCREP [.I] = .ACTUAL [.I] XOR .CORRECT [.I];

	PRT_GTR_12 (DISCREP, .DIGITS);
	END
    ELSE
	BEGIN
	DISCREP = .CORRECT XOR .ACTUAL;		!COMPUTE DISCREPANCIES
	PNUM (.DISCREP, .DIGITS);		!GO PRINT DISCREP VALUE
	END;

    PRINT_CRLF;
    END;
ROUTINE PRT_GTR_12 (PTR, DIGITS) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PRINTS AN OCTAL NUMBER POINTED TO BY 'PTR' WITH
!	'DIGITS' NUMBER OF DIGITS ( >12).
!
! FORMAL PARAMETERS:
!
!	PTR		= POINTER TO A VECTOR CONTAING THE NUMBER TO BE PRINTED
!	DIGITS		= # OF OCTAL DIGITS TO BE PRINTED ( >12)
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PRINTS AN OCTAL NUMBER ( > 12 DIGITS) ON THE TTY.
!
!--
    BEGIN

    MAP
	PTR : REF VECTOR;

    LOCAL
	TEMP;

    REGISTER
	AC0 = 0;

!PRINT 12 DIGITS AT A TIME UNTIL NUMBER OF DIGITS REMAINING IS <12.

    INCR I FROM 0 TO 3 BY 1 DO
	BEGIN
	PRINT_OCT_12 (.PTR [.I]);		!PRINT 12 DIGITS
	DIGITS = .DIGITS - 12;			!DECREMENT DIGIT COUNT

	IF .DIGITS LSS 12 THEN EXITLOOP (TEMP = .I + 1);

	END;

    IF .DIGITS GTR 0				!IF THERE ARE ANY DIGITS LEFT
    THEN
	PNUM (.PTR [.TEMP], .DIGITS);		!THEN PRINT THEM
    END;
ROUTINE PNUM (NUM, DIGITS) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PRINTS THE OCTAL NUMBER PASSED IN 'NUM'.
!	'DIGITS' NUMBER OF OCTAL DIGITS ( <12) ARE PRINTED.
!
! FORMAL PARAMETERS:
!
!	NUM		= OCTAL NUMBER TO BE PRINTED
!	DIGITS		= # OF OCTAL DIGITS ( <12) TO BE PRINTED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	AN OCTAL NUMBER ( <12 DIGITS) IS PRINTED ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

!CALL THE APPROPRIATE 'CSL' UUO BASED ON THE # OF DIGITS TO PRINT

    CASE .DIGITS FROM 1 TO 12 OF
	SET

	[1] :
	    PRINT_OCT_1 (.NUM);

	[2] :
	    PRINT_OCT_2 (.NUM);

	[3] :
	    PRINT_OCT_3 (.NUM);

	[4] :
	    PRINT_OCT_4 (.NUM);

	[5] :
	    PRINT_OCT_5 (.NUM);

	[6] :
	    PRINT_OCT_6 (.NUM);

	[7] :
	    PRINT_OCT_7 (.NUM);

	[8] :
	    PRINT_OCT_8 (.NUM);

	[11] :
	    PRINT_OCT_11 (.NUM);

	[12] :
	    PRINT_OCT_12 (.NUM);

	[INRANGE] :
	    PTXT_CRLF('INVALID NUMBER OF CORRECT/ACTUAL DIGITS');
	TES;

    END;

GLOBAL ROUTINE NOERR (INDEX) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN A NO-ERROR CONDITION IS DETECTED
!	IN A TEST.  IT PERFORMS FAULT ISOLATION BY UPDATING THE
!	CUMULATIVE FAULTY NETWORK VECTOR.  SINCE NO ERROR WAS DETECTED,
!	THE SET OF FAULTY NETWORKS WHICH WOULD HAVE CAUSED AN ERROR CAN
!	BE ELIMINATED FROM CONSIDERATION AS POSSIBLE FAULTY NETWORKS.
!	THIS IS DONE BY COMPLEMENTING THE FAULTY NETWORK VECTOR
!	ASSOCIATED WITH THE CURRENT TEST AND ERROR NUMBER AND 'ANDING'
!	THE RESULT WITH THE CUMULATIVE FAULTY NETWORK VECTOR.
!	IF THE RESULTANT CUMULATIVE VECTOR WOULD BE ALL ZEROS, THEN
!	A DISCREPANCY EXISTS.  A LIST OF POSSIBLE FAULTY NETWORKS IS
!	PRINTED USING THE CUMULATIVE VECTOR BEFORE THE 'ANDING' AND THE
!	TESTING IS ABORTED.
!	IF WE ARE LOOPING ON AN ERROR OR ON A TEST OR IF THE 'NO ISOLA-
!	TION FEATURE IS ACTIVATED, THERE IS NO NEED TO PERFORM THE
!	ISOLATION.
!
! FORMAL PARAMETERS:
!
!	INDEX		= A NUMBER TO BE USED AS AN INDEX INTO THE
!			  'NO ERROR' TABLE OF NETWORK VECTORS FOR THE
!			  CURRENT TEST.
!
! IMPLICIT INPUTS:
!
!	TEST_NUM	= NUMBER OF TEST BEING EXECUTED
!	LOOP_ON_TEST	= FLAG INDICATING LOOPING ON SPECIFIC TEST
!	LOOPING		= FLAG INDICATING LOOPING ON ERROR
!	NO_ISOLATION	= FLAG INDICATING THAT NO FAULT ISOLATION IS
!			  TO BE PERFORMED.
!	NES_TBL		= TABLE OF POINTERS TO 'NO ERROR' FAULT VECTORS
!	NET_FAULTS	= CUMULATIVE FAULTY NETWORKS VECTOR
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	THE CUMULATIVE FAULTY NETWORK VECTOR IS UPDATED OR IF A
!	DISCREPANCY IS FOUND, AN ERROR MESSAGE IS PRINTED AND TESTING
!	IS ABORTED.
!--

    BEGIN

    LOCAL
	NZ_FLAG,				!FLAG TO INDICATING IF 'ANDING' RESULT IS NON-ZERO
	NES_PTR;				!POINTER TO FAULT VECTOR

    OWN
	TEMP : VECTOR [10];			!TEMPORARY BUFFER

    MAP
	NET_FAULTS : VECTOR,
	NES_PTR : REF VECTOR;

!IF IT DOESN'T MAKE SENSE TO DO ISOLATION, JUST RETURN

    IF (.LOOP_ON_TEST OR .LOOPING OR .NO_ISOLATION) NEQ 0 THEN RETURN;

    NZ_FLAG = 0;				!INITIALIZE NON-ZERO FLAG
    NES_PTR = .NES_TBL [.TEST_NUM - 1];		!GET POINTER TO TABLE OF POINTERS FOR THIS TEST
    NES_PTR = .NES_PTR [.INDEX - 1];		!GET POINTER TO FAULTY NETWORKS VECTOR

!'AND' CUMULATIVE VECTOR WITH 'NO ERROR' VECTOR.  KEEP TRACK OF WHETHER
!RESULT IS ZERO OR NOT.

    INCR I FROM 0 TO .NETWRDS - 1 BY 1 DO
	BEGIN
	TEMP [.I] = .NET_FAULTS [.I] AND ( NOT .NES_PTR [.I]);
	NZ_FLAG = .TEMP [.I] OR .NZ_FLAG;	!IF RESULT OF FAULT ISOLATION IS NON-ZERO, SET NZ_FLAG
	END;

    IF .NZ_FLAG EQL 0				!IF RESULT WAS ZERO
    THEN
	BEGIN

	REGISTER
	    AC0 = 0;

	PRINT_CRLF;
	PTXT_CRLF ('FAULT ISOLATION DISCREPANCY, TESTING BEING ABORTED');
	PRINT_CRLF;
	NET_RPT ();				!LIST FAULTY NETWORKS
	AC0 = -1;				!TELL 'CSL' WE HAD ERROR
	EOP_UUO;				!RETURN TO 'CSL'
	END
    ELSE

!IF RESULT WAS NOT ZERO, UPDATE CUMULATIVE VECTOR

	INCR I FROM 0 TO .NETWRDS - 1 BY 1 DO
	    NET_FAULTS [.I] = .TEMP [.I];

    END;

GLOBAL ROUTINE FAILURE (ERR_NUM) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED BY THE ERROR HANDLING ROUTINES TO
!	PERFORM FAULT ISOLATION.
!	SINCE AN ERROR WAS DETECTED, THE FAULT WHICH CAUSED THE ERROR
!	MUST BE CONTAINED IN THE FAULTY NETWORKS VECTOR FOR THE CURRENT
!	TEST AND ERROR NUMBERS.  FROM PREVIOUS TESTS, WE ALSO KNOW THAT
!	THE FAULT MUST BE CONTAINED IN THE CUMULATIVE FAULTY NETWORK
!	VECTOR.  THEREFORE, THE FAULT MUST BE CONTAINED IN THAT SUBSET
!	OF NETWORKS WHICH IS COMMON TO BOTH THE CUMULATIVE VECTOR AND
!	THE TEST VECTOR.THIS SUBSET IS THE NEW CUMULATIVE FAULT VECTOR.
!	THIS IS OBTAINED BY 'ANDING' THE CUMULATIVE VECTOR WITH THE
!	VECTOR ASSOCIATED WITH THE CURRENT TEST AND ERROR NUMBERS.
!	IF THE RESULTANT CUMULATIVE VECTOR WOULD BE ALL ZEROS, THEN
!	A DISCREPANCY EXISTS.  A LIST OF POSSIBLE FAULTY NETWORKS IS
!	PRINTED USING THE CUMULATIVE VECTOR BEFORE THE 'ANDING' AND THE
!	TESTING IS ABORTED.
!	IF WE ARE LOOPING ON AN ERROR OR ON A TEST OR IF THE 'NO ISOLA-
!	TION FEATURE IS ACTIVATED, THERE IS NO NEED TO PERFORM THE
!	ISOLATION.
!
! FORMAL PARAMETERS:
!
!	ERR_NUM		= A NUMBER TO BE USED AS AN INDEX INTO THE
!			  'NO ERROR' TABLE OF NETWORK VECTORS FOR THE
!			  CURRENT TEST.
!
! IMPLICIT INPUTS:
!
!	TEST_NUM	= NUMBER OF TEST BEING EXECUTED
!	LOOP_ON_TEST	= FLAG INDICATING LOOPING ON SPECIFIC TEST
!	LOOPING		= FLAG INDICATING LOOPING ON ERROR
!	NO_ISOLATION	= FLAG INDICATING THAT NO FAULT ISOLATION IS
!			  TO BE PERFORMED.
!	ES_TBL		= TABLE OF POINTERS TO 'ERROR' FAULT VECTORS
!	NET_FAULTS	= CUMULATIVE FAULTY NETWORKS VECTOR
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	THE CUMULATIVE FAULTY NETWORK VECTOR IS UPDATED OR IF A
!	DISCREPANCY IS FOUND, AN ERROR MESSAGE IS PRINTED AND TESTING
!	IS ABORTED.
!--

    BEGIN

    LOCAL
	NZ_FLAG,				!FLAG TO INDICATING IF 'ANDING' RESULT IS NON-ZERO
	TEMP : VECTOR [10],			!TEMPORARY BUFFER
	ES_PTR;				!POINTER TO FAULT VECTOR

    MAP
	NET_FAULTS : VECTOR,
	ES_PTR : REF VECTOR;

!IF IT DOESN'T MAKE SENSE TO DO ISOLATION, JUST RETURN

    IF (.LOOP_ON_TEST OR .LOOPING OR .NO_ISOLATION) NEQ 0 THEN RETURN;

    NZ_FLAG = 0;				!INITIALIZE NON-ZERO FLAG
    ES_PTR = .ES_TBL [.TEST_NUM - 1];		!GET POINTER TO TABLE OF POINTERS FOR THIS TEST
    ES_PTR = .ES_PTR [.ERR_NUM - 1];		!GET POINTER TO FAULT VECTOR

!'AND' CUMULATIVE VECTOR WITH 'NO ERROR' VECTOR.  KEEP TRACK OF WHETHER
!RESULT IS ZERO OR NOT.

    INCR I FROM 0 TO .NETWRDS - 1 BY 1 DO
	BEGIN
	TEMP [.I] = .NET_FAULTS [.I] AND .ES_PTR [.I];
	NZ_FLAG = .TEMP [.I] OR .NZ_FLAG;	!IF RESULT OF FAULT ISOLATION IS NON-ZERO, SET NZ_FLAG
	END;

    IF .NZ_FLAG EQL 0				!IF RESULT WAS ZERO
    THEN
	BEGIN

	REGISTER
	    AC0 = 0;

	PRINT_CRLF;
	PTXT_CRLF ('FAULT ISOLATION DISCREPANCY, TESTING BEING ABORTED');
	PRINT_CRLF;
	NET_RPT ();				!LIST FAULTY NETWORKS
	AC0 = -1;				!TELL 'CSL' WE HAD ERROR
	EOP_UUO;				!RETURN TO 'CSL'
	END;

!IF RESULT WAS NOT ZERO, UPDATE CUMULATIVE FAULTY VECTOR

    INCR I FROM 0 TO .NETWRDS - 1 BY 1 DO
	    NET_FAULTS [.I] = .TEMP [.I];

    END;

GLOBAL ROUTINE LOOP_CHK (ERR_NUM) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED AFTER EVERY ERROR CHECK IN A TEST TO
!	DETERMINE IF LOOPING SHOULD BE DONE.
!	A 'LOOP' RETURN (1) WILL BE MADE FOR THE FOLLOWING CASES:
!		1. THE FIRST ERROR IS DETECTED AND LOOP-ON-ERROR
!		   IS ACTIVATED.
!		2. WE ARE ALREADY LOOPING ON ERROR X AND WE REACH THE
!		   THE POINT IN THE PROGRAM WHERE ERROR X IS CHECKED
!		   FOR.  IN THIS CASE WE LOOP REGARDLESS OF WHETHER
!		   ERROR X RECURS OR NOT.
!		3. WE ARE ALREADY LOOPING ON AN ERROR WHEN AN ERROR IS
!		   DETECTED AT AN EARLIER POINT IN THE TEST.  IN THIS
!		   CASE, WE TIGHTEN THE ERROR LOOP AND BECOME LOOPING ON
!		   THIS NEW ERROR.
!
! FORMAL PARAMETERS:
!
!	ERR_NUM		= NUMBER OF ERROR CHECK WITHIN CURRENT TEST
!
! IMPLICIT INPUTS:
!
!	ERRFLG		= FLAG INDICATING IF ERROR WAS DETECTED BY
!			  LAST ERROR CHECK
!	LOOP_ON_ERROR	= FEATURE FLAG FOR ENABLING LOOP ON ERROR
!	LOOPING		= FLAG INDICATING PROGRAM IS PRESENTLY LOOPING
!			  ON ERROR
!	LOOP_ERR_NUM	= NUMBER OF ERROR BEING LOOPED UPON
!
! IMPLICIT OUTPUTS:
!
!	LOOPING		= SAME AS ABOVE
!	LOOP_ERR_NUM	= SAME AS ABOVE
!	ERRFLG		= SAME AS ABOVE
!
! ROUTINE VALUE:
!
!	0 IF CURRENT ERROR IS NOT TO BE LOOPED UPON
!	1 IF CURRENT ERROR IS TO BE LOOPED UPON
!
! SIDE EFFECTS:
!
!	IF IT IS THE FIRST ERROR DETECTED AND LOOP-ON-ERROR IS SET,
!	THEN A 'YOU ARE LOOPING ON THIS ERROR' MESSAGE IS PRINTED.
!--

    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	ERR_FLAG;				!TEMP STORAGE FOR ERRFLG

    ERR_FLAG = .ERRFLG;				!SAVE ERRFLG FOR LATER USE
    ERRFLG = 0;					!RESET GLOBAL FLAG

!IF LOOP-ON-ERROR IS NOT ACTIVATED, GIVE DON'T LOOP RETURN

    IF .LOOP_ON_ERR EQL 0 THEN RETURN 0;

    IF .LOOPING NEQ 0				!IF WE'RE ALREADY LOOPING THEN
    THEN

	IF .LOOP_ERR_NUM EQL .ERR_NUM		!CHECK IF THIS IS THE ORIGINAL ERROR
	THEN
	    RETURN 1				!IF YES, GIVE 'DO LOOP' RETURN
	ELSE

	    IF .ERR_FLAG NEQ 0			!IF NOT, CHECK IF THIS IS A NEW ERROR
	    THEN
		BEGIN
		LOOP_ERR_NUM = .ERR_NUM;	!IF YES, SET NEW LOOP ERROR NUMBER
		PTXT_CRLF ('YOU ARE LOOPING ON THIS ERROR');
		RETURN 1;			!GIVE 'DO LOOP' RETURN
		END
	    ELSE
		RETURN 0;			!IF NOT, GIVE 'DON'T LOOP' RETURN

!WE GET HERE IF WE'RE NOT ALREADY LOOPING

    IF .ERR_FLAG NEQ 0				!DID WE JUST HAVE ERROR?
    THEN
	BEGIN
	LOOPING = 1;				!IF YES, SET FLAG FOR LOOPING
	LOOP_ERR_NUM = .ERR_NUM;		!SAVE CURRENT ERROR NUMBER
	PTXT_CRLF ('YOU ARE LOOPING ON THIS ERROR');
	RETURN 1;				!GIVE 'DO LOOP' RETURN
	END;

!IF WE GET THIS FAR, NO ERROR LOOPING IS REQUIRED
    RETURN 0;

    END;

GLOBAL ROUTINE FLP_CHK (ERR_NUM, PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED AFTER AN ERROR CHECK IN A TEST TO
!	DETERMINE IF ERROR LOOPING SHOULD BE DONE - EITHER FAST OR
!	NORMAL.
!	IF THE 'FAST LOOPING' FEATURE IS NOT ACTIVATED, CONTROL IS
!	TRANSFERRED TO THE 'LOOP_CHK' ROUTINE.  IF THE FEATURE IS
!	ACTIVATED AND AN ERROR WAS DETECTED, THEN THE COMMAND LINE
!	POINTED TO BY THE PASSED PARAMETER IS SENT TO THE 8080 FRONT
!	END.  THIS COMMAND LINE WILL END WITH AN 'RP' COMMAND AND WILL
!	IMPLEMENT A ERROR LOOP UNDER CONTROL OF 8080.  THIS MAKES FOR
!	A MUCH TIGHTER SCOPE LOOP THAN IS POSSIBLE WITH NORMAL ERROR
!	LOOPING UNDER CONTROL OF THE REMOTE HOST.  HOWEVER, SINCE
!	SENDING A COMMAND LINE WHICH ENDS IN 'RP' CAUSES THE 8080 TO
!	BE HUNG AS FAR AS THE HOST IS CONCERNED, A DETAILED EXPLANATION
!	OF THE PROCEDURE REQUIRED TO RESUME TESTING IS PRINTED ON THE
!	TTY.
!
! FORMAL PARAMETERS:
!
!	ERR_NUM		= NUMBER OF ERROR CHECK WITHIN TEST
!	PTR		= POINTER TO ASCIZ COMMAND LINE
!
! IMPLICIT INPUTS:
!
!	FAST_LOOP	= FEATURE FLAG INDICATING FAST ERROR LOOPING ACTIVATED
!	ERRFLG		= FLAG INDICATING THAT AN ERROR WAS DETECTED
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	IF 'FAST_LOOP' IS NOT ACTIVATED, THE VALUE RETURNED IS THAT
!	RETURNED BY 'LOOP_CHK' ROUTINE.  IF IT IS ACTIVATED, BUT NO
!	ERROR WAS DETECTED, A ZERO IS RETURNED.
!
! SIDE EFFECTS:
!
!	IF FAST LOOPING IS REQUIRED, A COMMAND LINE IS SENT TO THE 8080
!	AND A STEP-BY-STEP RESTART PROCEDURE IS PRINTED ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    IF .FAST_LOOP EQL 0 THEN RETURN LOOP_CHK (.ERR_NUM);

    IF .ERRFLG NEQ 0
    THEN
	BEGIN
	ERRFLG = 0;
	PRINT_CRLF;
	PRINT_TXT ('YOU ARE FAST LOOPING ON TEST #');
	PRINT_DEC (.TEST_NUM);
	PRINT_TXT (' ERROR #');
	PRINT_DEC (.ERR_NUM);
	PRINT_CRLF;
	PTXT_CRLF ('THE 8080 COMMAND LINE BEING EXECUTED IS:');
	PRINT_MSG (.PTR);
	PRINT_CRLF;
	PRINT_CRLF;
	PTXT_CRLF ('TO ABORT DO THE FOLLOWING:');
	PTXT_CRLF ('   PRESS RESET SWITCH, TYPE "MM", TYPE A CONTROL-C,');
	PTXT_CRLF ('   TYPE "QUIT", THEN TYPE "ST"');
	SEND_LINE (.PTR, -1);
	END;

    0					!TO AVOID INFO MESSAGE WHEN COMPILING
    END;

GLOBAL ROUTINE CHK_ERR_MSG (MSG_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CHECKS FOR A SPECIFIED 8080 ERROR MESSAGE WHICH
!	MAY BE PENDING IN 'CSL' INPUT BUFFER.
!	IF THE 8080 DETECTS AN ERROR WHILE IT IS IN ITS IDLE LOOP
!	(I. E., NOT EXECUTING ANY COMMAND), IT WILL SEND THE APPROP-
!	RIATE ERROR MESSAGE TO THE HOST.  SINCE THE 'CSL' IS NOT
!	EXPECTING A RESPONSE AT THAT TIME, THE MESSAGE WILL REMAIN IN
!	THE INPUT BUFFER.  IT SOME CASES, A TEST WILL STIMULATE THE
!	HARDWARE SUCH THAT ONE OF THESE ASYNCHRONOUS ERROR MESSAGES
!	WILL OCCUR.  THIS ROUTINE PROVIDES THE ABILITY TO CHECK FOR
!	THE MESSAGE AND FLUSH IT.  IF A MESSAGE IS FOUND BUT IT IS NOT
!	THE EXPECTED ONE, AN ERROR MESSAGE WILL BE PRINTED ON THE TTY
!	IF THE FLAG IS SET TO DO SO.
!
! FORMAL PARAMETERS:
!
!	MSG_PTR		= A POINTER TO THE ASCIZ STRING OF THE
!			  EXPECTED ERROR MESSAGE
!
! IMPLICIT INPUTS:
!
!	RPT_ERR_FLAG	= FLAG INDICATING WHETHER OR NOT ERRORS SHOULD
!			  BE PRINTED ON THE TTY.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	ANY ERROR MESSAGE PENDING IN 'CSL' INPUT BUFFER WILL BE FLUSHED.
!	ALSO, IF A UNEXPECTED ERROR MESSAGE IS FOUND AND THE FLAG IS
!	SET TO REPORT ERRORS, A MESSAGE IS PRINTED ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	CHR,					!STORAGE FOR MESSAGE CHAR
	MSG_BUF_PTR,				!BYTE POINTER TO EXPECTED MESSAGE
	BUF_PTR,				!BYTE POINTER TO ACTUAL ERROR MESSAGE
	SAV_PTR;				!PLACE TO SAVE ACTUAL POINTER

    WAIT (%O'400000');				!GIVE ERROR MESSAGE TIME TO GET HERE
    MSG_CHK_UUO;				!CHECK WITH 'CSL' FOR ERROR MSG
    BUF_PTR = .AC0;				!GET RESULTS

    IF .BUF_PTR NEQ 0				!IF AC0 ISN'T 0 THEN IT'S A PTR
    THEN
	BEGIN
	SAV_PTR = .BUF_PTR;			!SAVE POINTER TO START OF MESSAGE
	MSG_BUF_PTR = POINT (MSG_PTR, 36, 7, 0, 0);

!COMPARE MESSAGE WHICH 'CSL' FOUND WITH THAT WHICH IS EXPECTED (PASSED
!THROUGH POINTER 'MSG_PTR').

	WHILE (CHR = SCANI (MSG_BUF_PTR)) NEQ 0 DO

	    IF .CHR NEQ SCANI (BUF_PTR)		!CHECK IF MSG CHAR IS CORRECT
	    THEN

		IF .RPT_ERR_FLAG NEQ 0
		THEN
		    PRT_ERR (.SAV_PTR)		!GO REPORT UNEXPECTED ERROR
		ELSE
		    RETURN;

	END;

    END;

GLOBAL ROUTINE WAIT (LOOP_CNT) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE WAITS FOR A SPECIFIED NUMBER OF LOOP COUNTS.
!	IT IS NOT INTENDED TO GIVE ANY PRECISE TIMING, JUST A GROSS
!	WAIT INTERVAL.
!
! FORMAL PARAMETERS:
!
!	LOOP_CNT	= NUMBER OF TIMES TO EXECUTE WAIT LOOP
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!
!--
    BEGIN

    INCR I FROM 0 TO .LOOP_CNT BY 1 DO
	BEGIN
	0					!TO AVOID INFO MESSAGE WHEN COMPILING
	END;

    END;

ROUTINE PRT_ERR (MSG_PTR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO PRINT AN ERROR MESSAGE WHEN AN
!	UNEXPECTED ERROR RESPONSE IS RECEIVED FROM THE 8080.  AFTER
!	THE ERROR MESSAGE IS PRINTED, TESTING IS ABORTED WITH A RETURN
!	TO THE 'CSL' PROGRAM.
!	SINCE THE ERROR MESSAGE WHICH IS PASSED AS A PARAMETER MAY NOT
!	BEGIN ON AN WORD BOUNDARY, IT MUST BE TRANSFERRED INTO A PRINT
!	BUFFER BEFORE IT CAN BE PRINTED.
!
! FORMAL PARAMETERS:
!
!	MSG_PTR		= BYTE POINTER TO ERROR MESSAGE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! COMPLETION CODES:
!
!	-1 IS RETURNED IN AC0.  THIS TELLS 'CSL' WE HAD AN ERROR.
!
! SIDE EFFECTS:
!
!	AN ERROR MESSAGE IS PRINTED ON THE TTY AND TESTING IS ABORTED.
!
!--
    BEGIN

    LOCAL
	BUF_PTR,				!BYTE POINTER FOR PRINT BUFFER
	CHR;					!CHARACTER STORAGE

    OWN
	MSG_BUF : VECTOR [5];			!PRINT BUFFER

    REGISTER
	AC0 = 0;

    BUF_PTR = POINT (MSG_BUF, 36, 7, 0, 0);	!INIT BUFFER POINTER

    DO
	BEGIN
	CHR = SCANI (MSG_PTR);			!GET NEXT CHAR OF MESSAGE
	REPLACEI (BUF_PTR, .CHR);		!MOVE IT INTO PRINT BUFFER
	END
    WHILE .CHR NEQ 0;				!CONTINUE UNTIL END OF MESSAGE

    PRT_CRLF_F;
    PRT_TXT_F ('UNEXPECTED ERROR RESPONSE RECEIVED FROM 8080 DURING ');
    PTSTNUM ();					!PRINT TEST NUMBER
    PRINT_MSG (MSG_BUF);			!GO PRINT MESSAGE
    PTXT_CRLF_F ('THE LAST COMMAND LINE SENT TO THE 8080 WAS:');
    PRT_MSG_F (LINE_BUF);
    PRT_CRLF_F;
    PTXT_CRLF_F ('TESTING BEING ABORTED');
    AC0 = -1;					!TELL 'CSL' WE HAD ERROR
    EOP_UUO;					!RETURN TO 'CSL'
    END;

GLOBAL ROUTINE SEND_LINE (CMD_BUF, FORCE_SEND) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CONCATENATES 8080 COMMANDS TOGETHER ON A SINGLE
!	LINE AND SENDS THAT LINE TO THE 8080 BY PASSING IT TO THE 'CSL'
!	PROGRAM VIA A LUUO.
!	THE INPUT TO THIS ROUTINE IS AN ASCII COMMAND STRING AND A
!	'FORCE-SEND' FLAG.  IF CONCATENATING THE COMMAND STRING ONTO
!	THE CUMULATIVE COMMAND LINE WILL CAUSE IT TO EXCEED 79 CHARS
!	(THE 8080 LIMITATION), THEN THE CUMULATIVE COMMAND LINE IS
!	SENT AND THE COMMAND STRING IS USED TO START A NEW COMMAND LINE.
!	IF THE 'FORCE_SEND' FLAG IS NON-ZERO, THEN AFTER THE COMMAND
!	STRING IS CONCATENATED THE CUMULATIVE COMMAND LINE IS SENT.
!	THE 'FORCE_SEND' FLAG ALSO INDICATES THE TYPE OF COMMAND STRING
!	AND THEREFORE THE TYPE OF LUUO TO BE USED WHEN SENDING THE
!	COMMAND LINE.  IT IS NECESSARY THAT 'CSL' KNOWS WHICH FORM OF
!	RESPONSE WILL BE COMING FROM THE 8080 AS A RESULT OF SENDING IT
!	THE COMMAND LINE.
!	IF 'CSL' RETURNS AC0 = -1, THEN THE 8080 TIMED OUT IN RESPONSE
!	TO THE COMMAND LINE.  IF IT RETURNS AC0 = BYTE POINTER, THEN
!	THE 8080 RESPONDED WITH AN ERROR MESSAGE WHICH IS POINTED TO BY
!	THE BYTE POINTER.
!
! FORMAL PARAMETERS:
!
!	CMD_BUF		= ADDRESS OF COMMAND STRING
!	FORCE_SEND	= FLAG INDICATING THAT THE COMMAND STRING MUST
!			  BE SENT.  IT ALSO DICTATES THE AC FIELD OF
!			  LUUO TO BE USED.
! IMPLICIT INPUTS:
!
!	RPT_ERR_FLAG	= FLAG INDICATING WHETHER OR NOT 8080 ERRORS
!			  SHOULD BE REPORTED.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	0 IF NO COMMAND LINE IS SENT.
!	POINTER TO RESPONSE IF COMMAND LINE WAS SENT.
!
! SIDE EFFECTS:
!
!	A ASCII COMMAND LINE MAY BE SENT TO THE 8080 THROUGH THE
!	'CSL' PROGRAM.
!--

    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	CMD_BUF_PTR,				!BYTE POINTER TO COMMAND STRING
	CMD_CHARS;				!# OF CHARS IN COMMAND STRING

    OWN
	LINE_BUF_PTR;				!BYTE POINTER TO COMMAND LINE

!COMPUTE THE NUMBER OF CHARACTERS IN THE COMMAND
    TIMOUT = 0;					!RESET TIME OUT FLAG
    CMD_CHARS = 0;
    CMD_BUF_PTR = POINT (.CMD_BUF, 36, 7, 0, 0);	!INITIALIZE BYTE POINTER

    WHILE SCANI (CMD_BUF_PTR) NEQ 0		!AS LONG AS NEXT COMMAND CHAR IS NONZERO
    DO
	CMD_CHARS = .CMD_CHARS + 1;		!INCREMENT THE CHARACTER COUNT

!IF THIS COMMAND WILL NOT FIT ON THE CURRENT COMMAND LINE (WILL CAUSE
!LINE TO EXCEED 79 CHARS), THEN SEND THE CURRENT COMMAND LINE AND RESET
!PARAMETERS TO START A NEW LINE WITH THE NEW COMMAND

    IF (.CMD_CHARS + .LINE_CHARS) GTR 78
    THEN
	BEGIN
	REPLACEI (LINE_BUF_PTR, 0);		!TERMINATE COMMAND LINE
	AC0 = LINE_BUF;
	SEND_CMD_LINE;
!IF 'CSL' RETURNS AC0 = -1 THEN THE 8080 TIMED OUT. GO PRINT THE TEST
!NUMBER AND THE LAST CMD LINE SENT.

	IF .AC0 EQL -1 THEN TIMED_OUT ();

!IF 'CSL' RETURNS LH OF AC0 NON-ZERO, THEN IT CONTAINS A POINTER TO AN
!ERROR MESSAGE WHICH WAS RECEIVED FROM THE 8080.  IF REPORTING ERRORS
!IS TURNED ON, THEN GO REPORT IT AND ABORT.

	IF (.AC0<18, 18> NEQ 0) AND (.RPT_ERR_FLAG NEQ 0) THEN PRT_ERR (.AC0);

	LINE_CHARS = 0;
	END;

!IF THIS IS THE FIRST COMMAND ON THE LINE INIT THE LINE BUFFER POINTER

    IF .LINE_CHARS EQL 0
    THEN
	BEGIN

	IF .CMD_CHARS EQL 0			!IF THIS COMMAND IS A NULL CMD
	THEN
	    RETURN 0;				!THEN THERE'S NOTHING TO DO


	LINE_BUF_PTR = POINT (LINE_BUF, 36, 7, 0, 0);	!RESET BYTE POINTER
	END;

!IF THI SCOMMAND STRING ISN'T A NULL, CONCATENATE IT TO THE CUMULATIVE
!COMMAND LINE.

    IF .CMD_CHARS GTR 0
    THEN
	BEGIN

	IF .LINE_CHARS NEQ 0			!IF THIS IS NOT THE FIRST COMMAND
	THEN 					!THEN
	    BEGIN
	    REPLACEI (LINE_BUF_PTR, %C',');	!INSERT A COMMA
	    LINE_CHARS = .LINE_CHARS + 1;	!INCREMENT LINE CHAR CNT
	    END;

	CMD_BUF_PTR = POINT (.CMD_BUF, 36, 7, 0, 0);	!INITIALIZE BYTE POINTER

	INCR I FROM 1 TO .CMD_CHARS		!MOVE CMD CHARS INTO BUFFER
	    DO
	    BEGIN
	    COPYII (CMD_BUF_PTR, LINE_BUF_PTR);	!COPY CMD CHAR INTO LINE BUFFER
	    LINE_CHARS = .LINE_CHARS + 1;	!INCREMENT COMMAND CHAR COUNT
	    END;

	END;

!IF 'FORCE_SEND' FLAG IS ZERO, DON'T SEND THE COMMAND LINE.  OTHERWISE,
!SEND IT BASED ON THE VALUE OF THE FLAG.

    IF .FORCE_SEND EQL 0
    THEN
	RETURN 0
    ELSE
	BEGIN
	REPLACEI (LINE_BUF_PTR, 0);		!TERMINATE COMMAND
	AC0 = LINE_BUF;

	IF .FORCE_SEND EQL -1
	THEN
	    SEND_CMD_LINE
	ELSE

	    CASE .FORCE_SEND FROM 1 TO 10 OF
		SET

		[1] :
		    SEND_ER_LINE;		!LAST COMMAND IS 'ER'

		[2] :
		    SEND_EI_LINE;		!LAST COMMAND IS 'EI'

		[3] :
		    SEND_EJ_LINE;		!LAST COMMAND IS 'EJ'

		[4] :
		    SEND_EK_LINE;		!LAST COMMAND IS 'EK'

		[5] :
		    SEND_EB_LINE;		!LAST COMMAND IS 'EB'

		[6] :
		    SEND_EC_LINE;		!LAST COMMAND IS 'EC'

		[7] :
		    SEND_EM_LINE;		!LAST COMMAND IS 'EM'

		[8] :
		    SEND_PM_LINE;		!LAST COMMAND IS 'PM'

		[9] :
		    SEND_X1A_LINE;		!LAST COMMAND IS 'X1'

		[10] :
		    SEND_X1B_LINE;		!LAST COMMAND IS 'X1'
		TES;

	LINE_CHARS = 0;				!REINIT CHAR COUNT
!IF 'CSL' RETURNS AC0 = -1 THEN THE 8080 TIMED OUT. GO PRINT THE TEST
!NUMBER AND THE LAST CMD LINE SENT.

	IF .AC0 EQL -1 THEN TIMED_OUT ();

!IF 'CSL' RETURNS LH OF AC0 NON-ZERO, THEN IT CONTAINS A POINTER TO AN
!ERROR MESSAGE WHICH WAS RECEIVED FROM THE 8080.  IF REPORTING ERRORS
!IS TURNED ON, THEN GO REPORT IT AND ABORT.

	IF (.AC0<18, 18> NEQ 0) AND (.RPT_ERR_FLAG NEQ 0) THEN PRT_ERR (.AC0);

	RETURN .AC0;				!RETURN THE 8080 RESPONSE
	END;

    0					!TO AVOID INFO MESSAGE WHEN COMPILING
    END;

ROUTINE TIMED_OUT : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED WHEN THE 8080 TIMES OUT IN RESPONSE TO
!	A COMMAND LINE.  IT PRINTS A MESSAGE TO THAT EFFECT AND PRINTS
!	THE COMMAND LINE WHICH WAS SENT.  IT ALSO SETS THE GLOBAL FLAG
!	'TIMOUT' TO NOTIFY ANY CONCERNED TEST ROUTINES THAT THIS OCCURRED.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	LINE_BUF	= ADDRESS OF LAST COMMAND LINE SENT
!
! IMPLICIT OUTPUTS:
!
!	TIMOUT		= FLAG INDICATING THAT A TIME OUT OCCURRED
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	AN ERROR MESSAGE IS PRINTED ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    PRT_CRLF_F;
    PRT_TXT_F ('8080 TIMED OUT DURING ');
    PTSTNUM ();					!PRINT THE CURRENT TEST NUMBER
    PTXT_CRLF_F ('THE LAST COMMAND LINE SENT TO THE 8080 WAS:');
    PRT_MSG_F (LINE_BUF);			!PRINT THE LAST CMD LINE SENT
    PRT_CRLF_F;
    TIMOUT = -1;				!SET TIMED OUT FLAG
    END;

GLOBAL ROUTINE REPEAT (RPT_CNT) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CREATES AND SENDS A 'RP XXX' (REPEAT) COMMAND.
!	THE REPEAT COUNT IS PASSED AS A PARAMETER AND IS CONVERTED
!	INTO AN ASCII NUMBER WHICH BECOMES THE REPEAT FIELD OF THE
!	'RP' COMMAND.
!
! FORMAL PARAMETERS:
!
!	RPT_CNT		= REPEAT COUNT
!
! IMPLICIT INPUTS:
!
!	NONE
!	
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PASSES 'RP' COMMAND TO THE 'SEND_LINE' ROUTINE, WHERE IT GETS
!	CONCATENATED ONTO A COMMAND LINE AND SENT TO THE 8080.
!	IF THE RPT_CNT PARAMETER IS OUT OF RANGE, AN ERROR MESSAGE IS
!	PRINTED.
!--

    BEGIN

    BIND
	RPT_CMD = UPLIT (%ASCIZ'RP   ');	!RP CMD SKELETON

    LOCAL
	BUF_PTR;				!BYTE POINTER TO RP CMD STRING

    REGISTER
	AC0 = 0;

    IF (.RPT_CNT LEQ 0) OR (.RPT_CNT GTR %O'376')	!IF REPEAT COUNT IS OUT OF RANGE
    THEN 					!REPORT AS ERROR
	BEGIN
	PTSTNUM ();				!PRINT TEST NUMBER
	PTXT_CRLF ('CALL TO REPEAT ROUTINE HAS OUT OF RANGE COUNT');
	END;

    BUF_PTR = POINT (RPT_CMD, 22, 7, 0, 0);	!SET BYTE POINTER TO FIRST CHAR AFTER 'RP '
    BUF_PTR = INSERT_NUM (.BUF_PTR, .RPT_CNT, 3);	!INSERT COUNT FIELD IN CMD
    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    SEND_LINE (RPT_CMD, -1);
    END;

GLOBAL ROUTINE PTSTNUM : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PRINTS THE NUMBER OF THE TEST BEING EXECUTED.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	TEST_NUM	= NUMBER OF TEST BEING EXECUTED
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PRINTS TEST NUMBER ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    PRINT_TXT ('TEST #');
    PRINT_DEC (.TEST_NUM);
    PRINT_CRLF;
    END;

GLOBAL ROUTINE CP (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO GENERATE A 'CP' COMMAND STRING.
!	IF THE 'SINGLE STEP' FEATURE IS ACTIVATED AND THE PROGRAM IS
!	LOOPING ON A TEST OR AN ERROR, THEN THE CP'S MUST BE DONE IN
!	A CONTROLLED MANNER.  THIS IS DONE BY CALLING THE 'SS_UC'
!	ROUTINE.
!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK PULSES REQUIRED
!
! IMPLICIT INPUTS:
!
!	SINGLE_STEP	= FEATURE FLAG INDICATING THAT MICROCODE IS TO
!			  BE SINGLE STEPPED.
!	LOOPING		= FLAG INDICATING THAT PROGRAM IS LOOPING ON ERROR
!	LOOP_ON_TEST	= FEATURE FLAG INDICATING THAT PROGRAM IS LOOPING
!			  ON TEST.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	IF NOT SINGLE-STEPPING, A 'CP' COMMAND IS PASSED TO THE
!	'SEND_LINE' ROUTINE FOR CONCATENATION ONTO THE COMMAND LINE.
!	IF SINGLE-STEPPING, 'CP' COMMANDS ARE SENT UNDER USER CONTROL.
!	IF THE STEP COUNT IS OUT OF RANGE, AN ERROR MESSAGE IS PRINTED
!	ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    IF (.N LSS 1) OR (.N GTR %O'177777')	!IS STEP COUNT OUT OF RANGE
    THEN
	BEGIN
	PTSTNUM ();				!PRINT THE TEST NUMBER
	PTXT_CRLF ('MICROCODE STEP COUNT OUT OF RANGE');
	END;

!CHECK WHETHER WE SHOULD DO SINGLE STEPPING OR NOT

    IF .SINGLE_STEP AND (.LOOPING OR .LOOP_ON_TEST)
    THEN
	SS_UC (.N)				!GO DO SINGLE STEPPING
    ELSE
	SEND_CP (.N);				!GO SEND 'CP' CMD
    END;

GLOBAL ROUTINE CP_NOSS (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO GENERATE A 'CP' COMMAND STRING.
!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK PULSES REQUIRED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	A 'CP' COMMAND IS PASSED TO THE 'SEND_LINE' ROUTINE FOR
!	CONCATENATION ONTO THE COMMAND LINE.
!	IF THE STEP COUNT IS OUT OF RANGE, AN ERROR MESSAGE IS PRINTED
!	ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    IF (.N LSS 1) OR (.N GTR %O'177777')	!IS STEP COUNT OUT OF RANGE
    THEN
	BEGIN
	PTSTNUM ();				!PRINT THE TEST NUMBER
	PTXT_CRLF ('MICROCODE STEP COUNT OUT OF RANGE');
	END;

    SEND_CP (.N);				!GO SEND 'CP' CMD
    END;

ROUTINE SEND_CP (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE GENERATES A 'CP' COMMAND STRING AND PASSES IT TO
!	THE 'SEND_LINE' ROUTINE FOR CONCATENATION ONTO THE COMMAND
!	LINE.  IT TAKES THE PASSED PARAMETER 'N' AND CONVERTS IT TO BE
!	THE ASCII NUMBER FIELD OF THE 'CP' COMMAND.
!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK PULSES REQUIRED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PASSES 'CP' COMMAND TO 'SEND_LINE' ROUTINE FOR CONCATENATION
!	ONTO COMMAND LINE.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;

    BIND
	CP_CMD = UPLIT (%ASCIZ'CP      ');

    BUF_PTR = POINT (CP_CMD, 22, 7, 0, 0);	!SETUP BUFFER BYTE POINTER

    IF .N GEQ 2					! CP DEFAULTS TO DOING IT ONCE
    THEN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .N, 6);

    REPLACEI (BUF_PTR, 0);
    SEND_LINE (CP_CMD, 0);			!PASS 'CP' CMD
    END;
ROUTINE SS_UC (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE ALLOWS THE USER TO CONTROL SINGLE STEPPING OF
!	DIAGNOSTIC MICROCODE.  IT PRINTS A MESSAGE INFORMING THE USER
!	OF THE NUMBER OF MICROCODE STEPS REQUIRED IN THE FUNCTION
!	BEING EXECUTED.  IT THEN PROMPTS HIM/HER FOR THE NUMBER OF
!	STEPS DESIRED.  THE SPECIFIED NUMBER OF STEPS ARE EXECUTED
!	USING A 'CP' CMD.  THE RESULTS OF AN 'EJ' COMMAND ARE PRINTED
!	FOLLOWING THAT EXECUTION.  THIS PROCESS IS REPEATED UNTIL THE
!	REQUIRED NUMBER OF STEPS HAVE BEEN EXECUTED.  AT THAT POINT,
!	THE USER IS ASKED IF HE/SHE WISHES TO CONTINUE.  IF NOT,
!	PROGRAM CONTROL IS RETURNED TO 'CSL'.
!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK PULSES REQUIRED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PRINTS PROMPT MESSAGES ON THE TTY AND RECEIVES INPUT.
!	EXECUTES SPECIFIED NUMBER OF 'CP' AND 'EJ' COMMANDS.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    LOCAL
	EJ_PTR,					!POINTER TO 'EJ' RESULTS
	STEPS;					!COUNTER FOR # OF MICROCODE STEPS

!PRINT REQUIRED # OF MICROCODE STEPS

    PRINT_TXT ('THIS MICROCODE SEQUENCE REQUIRES ');
    PRINT_DEC (.N);
    PTXT_CRLF (' MICROCODE STEPS');

!EXECUTE USER SPECIFIED NUMBER OF MICROCODE STEPS UNTIL REQUIRED #
!ARE EXECUTED.

    DO
	BEGIN
	STEPS = GET_NUM (UPLIT (%ASCIZ'ENTER DESIRED NUMBER OF MICRO-STEPS'), .N);
	SEND_CP (.STEPS);			!PASS 'CP' CMDS
	EJ_PTR = EJ ();
	PRINT_CRLF;
	PRINT_TXT ('CUR/');
	PRINT_OCT_4 (.(.EJ_PTR));		!PRINT 'CUR' CRAM ADDR
	PRINT_TXT ('   NXT/');
	PRINT_OCT_4 (.(.EJ_PTR + 1));		!PRINT 'NXT' CRAM ADDR
	PRINT_TXT ('   J/');
	PRINT_OCT_4 (.(.EJ_PTR + 2));		!PRINT 'J' FIELD
	PRINT_TXT ('   SUB/');
	PRINT_OCT_4 (.(.EJ_PTR + 3));		!PRINT 'SUB' RETURN ADDR
	PRINT_CRLF;
	PRINT_CRLF;
	END
    WHILE (N = .N - .STEPS) GTR 0;

!FIND OUT IF USER WANTS TO CONTINUE OR RETURN TO 'CSL'

    PTXT_CRLF ('REQUIRED # OF MICRO-STEPS HAVE BEEN EXECUTED');
    PRINT_TXT ('DO YOU WANT TO CONTINUE THIS TEST?');

    IF NOT TTI_YES THEN EOP_UUO;

    END;

GLOBAL ROUTINE SEND_NUL =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CAUSES THE CUMULATIVE COMMAND LINE BEING BUILT
!	BY THE 'SEND_LINE' ROUTINE TO BE SENT TO THE 8080.  IT DOES
!	THIS BY PASSING 'SEND_LINE' A NULL COMMAND STRING WITH THE
!	'FORCE_SEND' FLAG SET TO -1.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CAUSES THE CUMULATIVE COMMAND LINE TO BE SENT TO THE 8080.
!
!--
    BEGIN

    OWN
	NUL_CMD : INITIAL (0);

    RETURN SEND_LINE (NUL_CMD, -1);		!SEND CMD LINE
    END;

GLOBAL ROUTINE SETNXT (ADDR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CAUSES THE NEXT CRAM ADDR IN THE KS10 TO BE
!	SET TO THE VALUE OF THE PASSED PARAMETER 'ADDR'.
!
! FORMAL PARAMETERS:
!
!	ADDR		= VALUE OF DESIRED NEXT CRAM ADDRESS
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	
!
! SIDE EFFECTS:
!
!	CAUSES THE KS10 NEXT CRAM ADDRESS TO BE SET TO 'ADDR'.
!
!--
    BEGIN

    LITERAL
	X1_AC = 0;

    RETURN X1 (CADSUB, .ADDR, X1_AC);		!USE 'X1' TO SET ADDR
    END;

GLOBAL ROUTINE EXNEXT =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO EXAMINE THE NEXT CRAM ADDR IN THE
!	KS10.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	KS10 NEXT CRAM ADDRESS
!
! SIDE EFFECTS:
!
!	CAUSES AN 'X1' COMMAND TO BE SENT TO THE 8080.  ALSO, IF
!	THE X1 SUBROUTINE IS NOT ALREADY LOADED, A SEQUENCE OF COMMAND
!	LINES WILL BE SENT TO LOAD IT.
!
!--
    BEGIN

    LITERAL
	X1_AC = 9;

    RETURN .X1 (CADSUB, 0, X1_AC);
    END;

GLOBAL ROUTINE WR_CRAM (DATA) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO LOAD AND EXECUTE AN 8080 SUBROUTINE
!	WHICH WRITES AND READS BITS 0-35 OF THE KS10 CRAM.
!	THE ACTUAL LOADING AND EXECUTING IS DONE BY THE 'X1' ROUTINE.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE WRITTEN INTO BITS 0-35 OF CRAM
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO THE ADDRESS AND ACTUAL DATA FOR LAST ADDRESS
!	TESTED.
!
! SIDE EFFECTS:
!
!	CAUSES 'X1' COMMAND TO BE SENT TO THE 8080.  IF THE REQUIRED
!	8080 SUBROUTINE IS NOT LOADED, IT WILL SEND A SEQUENCE OF COMMAND
!	LINES TO LOAD IT.
!
!--
    BEGIN

!THE FOLLOWING IS A LISTING OF THE 8080 SUBROUTINE WHICH GETS LOADED
!AND EXECUTED.  IT WRITES THE RECEIVED DATA PATTERN INTO THE KS10 CRAM
!BITS 0-35, READS THEM BACK AND VERIFIES THEM.  IF IT FINDS AN ERROR OR
!WHEN THE LAST ADDRESS IS TESTED, THE ADDRESS AND ACTUAL DATA ARE
!RETURNED.

!RAM ADDRESS 'RAMX1' = 20054
! 303 327 042	RAMX1:	JMP	RHSAVE
! RAM ADDRESS 'RHSAVE' = 21327
! 347		RHSAVE:	ARG36		;ASSEMBLE 36 BIT ARG
! 010			.BYTE 8
! 322 040		.ADDR	CRMTM	;PLACE TO PUT IT
! 257			XRA	A	;ZERO ACCUM
! 062 145 043		STA	ERRFLG	;CLEAR ERROR FLAG
! 072 322 040		LDA	CRMTM	;GET DATA BEING WRITTEN
! 062 146 043		STA	DATA	;STORE IT
! 315 335 014	NXTAD:	CALL	CRM.AD	;WRITE CRAM ADDRESS
! 076 002		MVI	A,2	;SET STARTING DIAG FN
! 001 010 040		LXI	B,CRMFN	;SETUP STORAGE ADDRESS
! 002		DCLP:	STAX	B	;SAVE CURRENT DIAG FN VALUE
! 072 146 043		LDA	DATA	;GET DATA TO WRITE
! 147			MOV	H,A	;PUT IT INTO H,L
! 157			MOV	L,A
! 315 303 014		CALL	WFUNC	;DO DIAG FN WRITE
! 012			LDAX	B	;GET DIAG FN
! 075			DCR	A	;DECR IT
! 362 355 042		JP	DCLP	;CONTINUE UNTIL DIAG FN = -1
! 315 205 013		CALL	CP1	;CLOCK CRAM BITS INTO REG
! 041 141 043		LXI	H,RDLST	;GET PTR TO LIST OF FNS TO READ
! 176		ECLP:	MOV	A,M	;GET DIAG FN TO ACCUM
! 043			INX	H	;UPDATE PTR
! 247			ANA	A	;CHECK FOR END OF LIST (MINUS ENTRY)
! 372 060 043		JM	SETCH	;GO INC CRAM ADDR
! 315 002 015		CALL	READC	;GO READ DIAG FN
! 042 170 040		SHLD	ECSAV	;SAVE H,L
! 041 100 040		LXI	H,TMPB2	;SETUP PTR TO DATA
! 072 146 043		LDA	DATA	;GET DATA WRITTEN
! 256			XRA	M	;COMPARE TO DATA READ
! 302 042 043		JNZ	ERR	;JUMP IF DIFFERENT
! 072 146 043		LDA	DATA	;GET DATA WRITTEN
! 346 017		ANI	17	;MASK OFF DON'T CARE BITS
! 043			INX	H	;INCR PTR TO READ DATA
! 256			XRA	M	;COMPARE
! 053			DCX	H	;RESTORE DATA PTR
! 312 045 043		JZ	NOERR2	;JUMP IF NO ERROR
! 062 145 043	ERR:	STA	ERRFLG	;SET ERROR FLAG
! 315 045 031	NOERR2:	CALL	OCTAL	;TURN DATA INTO ASCII CHAR
! 002			.BYTE	2
! 004			.BYTE	4
! 052 170 040		LHLD	ECSAV	;RESTORE H,L
! 303 001 043		JMP	ECLP	;CONTINUE READING DIAG FNS
! 072 145 043	SETCH:	LDA	ERRFLG	;GET ERROR FLAG
! 356 000		XRI	0	;CHECK FOR ZERO
! 302 102 043		JNZ	RPTIT	;JUMP IF HAD ERROR
! 052 004 040		LHLD	CRMAD	;GET CRAM ADDR
! 043			INX	H	;INCR IT
! 174			MOV	A,H	;GET HIGH ORDER ADDR BITS
! 356 010		XRI	10	;CHECK IF REACHED MAX ADDR
! 302 117 043		JNZ	POPSTK	;JUMP IF NOT
! 041 004 040	RPTIT:	LXI	H,CRMAD	;GET ADDR OF CRAM ADDR
! 315 332 030		CALL	P16	;GO PRINT ADDR
! 317 057		PSLASH		;PRINT SLASH
! 006 014		MVI	B,12.	;NUM OF CHAR TO TYPE
! 303 046 016		JMP	PCRLP	;GO TYPE CHARS AND END CMD
! 042 004 040	POPSTK:	SHLD	CRMAD	;STORE IT BACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 361			POP	PSW	;POP CHAR OFF STACK
! 303 345 042		JMP	NXTAD	;GO TEST NEXT ADDR
! 005		RDLST:	.BYTE	5	;READ 24-35
! 004			.BYTE	4	;READ 12-23
! 000			.BYTE	0	;READ 0-11
! 377			.BYTE	377	;MARKS END OF LIST
! 000		ERRFLG:	.BYTE	0
! 000		DATA:	.BYTE	0

    BIND
	SUB = PLIT (UPLIT (%ASCIZ 'LK20054,DK303,DN327,DN42,LK21327,DK347,DN10,DN322,DN40,DN257,DN62,DN145,DN43'),
		    UPLIT(%ASCIZ 'DN72,DN322,DN40,DN62,DN146,DN43,DN315,DN264,DN14,DN76,DN2,DN1,DN10,DN40,DN2'),
		    UPLIT(%ASCIZ 'DN72,DN146,DN43,DN147,DN157,DN315,DN232,DN14,DN12,DN75,DN362,DN355,DN42,DN315'),
		    UPLIT(%ASCIZ 'DN127,DN13,DN41,DN141,DN43,DN176,DN43,DN247,DN372,DN60,DN43,DN315,DN331,DN14'),
		    UPLIT(%ASCIZ 'DN42,DN170,DN40,DN41,DN100,DN40,DN72,DN146,DN43,DN256,DN302,DN42,DN43,DN72'),
		    UPLIT(%ASCIZ 'DN146,DN43,DN346,DN17,DN43,DN256,DN53,DN312,DN45,DN43,DN62,DN145,DN43,DN315'),
		    UPLIT(%ASCIZ 'DN16,DN31,DN2,DN4,DN52,DN170,DN40,DN303,DN1,DN43,DN72,DN145,DN43,DN356,DN0'),
		    UPLIT(%ASCIZ 'DN302,DN102,DN43,DN52,DN4,DN40,DN43,DN174,DN356,DN10,DN302,DN117,DN43,DN41'),
		    UPLIT(%ASCIZ 'DN4,DN40,DN315,DN303,DN30,DN317,DN57,DN6,DN14,DN303,DN375,DN15,DN42,DN4,DN40'),
		    UPLIT(%ASCIZ 'DN361,DN361,DN361,DN361,DN361,DN361,DN361,DN361,DN361,DN361,DN361,DN361,DN303'),
		    UPLIT(%ASCIZ 'DN345,DN42,DN5,DN4,DN0,DN377,DN0,DN0'));

    LITERAL
	X1_AC = 10;

    RETURN X1 (SUB, .DATA, X1_AC);
    END;

GLOBAL ROUTINE X1 (SUB_PTR, ARG, X1_AC) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE LOADS AN 8080 SUBROUTINE, IF NECESSARY, AND
!	CREATES AND SENDS AN 'X1' COMMAND TO EXECUTE THAT ROUTINE.
!	FOR THOSE X1 COMMANDS WHICH REQUIRE AN ARGUMENT, THE 'ARG'
!	PARAMETER IS CONVERTED TO AN ASCII OCTAL NUMBER FIELD ON
!	THE 'X1' COMMAND.
!
! FORMAL PARAMETERS:
!
!	SUB_PTR		= POINTER TO THE SEQUENCE OF ASCII COMMAND LINES
!			  REQUIRED TO LOAD THE 8080 SUBROUTINE
!	ARG		= VALUE TO BE USED AS THE NUMBER FIELD IN THE
!			  'X1' COMMAND
!	X1_AC		= VALUE TO BE PASSED TO 'SEND_LINE' AS THE 'FORCE
!			  SEND' FLAG.  3 VALUES ARE POSSIBLE:
!			  0 = 'X1' WITH ARGUMENT TO SET NEXT CRAM ADDRESS
!			  9 = 'X1' WITHOUT ARGUMENT TO READ NEXT CRAM ADDR
!			  10 = 'X1' WITH ARGUMENT TO WRITE AND READ CRAM
!			  	BITS 0-35
!
! IMPLICIT INPUTS:
!
!	SUB_LOADED	= FLAG CONTAINING POINTER TO SUBROUTINE SEQUENCE
!			  CURRENTLY LOADED INTO 8080.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO 8080 RESPONSE DATA, IF THERE IS ANY.
!
! SIDE EFFECTS:
!
!	CAUSES SUBROUTINE TO BE LOADED INTO 8080 RAM, IF NEEDED.
!	CAUSES 'X1' COMMAND TO BE SENT TO 8080.
!
!--
    BEGIN

    BIND
	X1_CMD = UPLIT (%ASCIZ'X1            ');

    LOCAL
	BUF_PTR;

!CHECK IF REQUIRED SUBROUTINE IS ALREADY LOADED.

    IF .SUB_LOADED NEQ .SUB_PTR			!IF CORRECT SUBROUTINE ISN'T LOADED
    THEN 					!THEN LOAD IT
	BEGIN

	INCR I FROM 0 TO .(.SUB_PTR - 1) - 1 BY 1 DO
	    SEND_LINE (.(.SUB_PTR + .I), -1);

	SUB_LOADED = .SUB_PTR;			!SET FLAG THAT IT'S LOADED
	END;

    BUF_PTR = POINT (X1_CMD, 22, 7, 0, 0);	!INIT BYTE POINTER

    IF .X1_AC EQL 0				!IF THIS IS 'X1' TO SET NEXT CRAM ADDR
    THEN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ARG, 4);	!INSERT ARG FIELD INTO CMD

    IF .X1_AC EQL 10				!IF THIS IS 'X1' TO TEST CRAM 0-35
    THEN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ARG, 12);	!INSERT ARG FIELD INTO CMD

    REPLACEI (BUF_PTR, 0);			!TERMINATE COMMAND STRING
    RETURN SEND_LINE (X1_CMD, .X1_AC);
    END;

GLOBAL ROUTINE LOADUC (CRAM_ADDR, DATA_ADDR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE LOADS THE KS10 CRAM WITH MICROCODE.
!	FIRST, IT FORCES SENDING THE CUMULATIVE COMMAND LINE BY
!	CALLING THE 'SEND_NUL' ROUTINE.  THEN IT EXECUTES AN LUUO
!	TO 'CSL' TO CAUSE THE LOADING OF A SPECIFIED BLOCK OF MICROCODE.
!
! FORMAL PARAMETERS:
!
!	CRAM_ADDR	= CRAM ADDRESS AT WHICH TO START LOADING UCODE
!	DATA_ADDR	= POINTER TO THE BLOCK OF MICROCODE TO BE LOADED.
!			  (POINTER-1) CONTAINS THE # OF 36-BIT WORDS IN
!			  THE BLOCK.  THE BLOCK CONTAINS 3-WORD ENTRY,
!			  WITH EACH ENTRY SPECIFYING THE 96 BITS OF UCODE
!			  TO BE LOADED.
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CAUSES THE CUMULATIVE COMMAND LINE TO BE SENT THEN LOADS THE
!	SPECIFIED BLOCK OF UCODE INTO THE KS10 CRAM.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    SEND_NUL ();				!SEND ANY EXISTING CMD LINE

!SETUP AC0 WITH DATA AS REQUIRED BY LUUO.

    AC0<0, 18> = .DATA_ADDR;			!POINTER TO UCODE DATA
    AC0<18, 12> = .CRAM_ADDR;			!START LOAD ADDR
    AC0<30, 6> = (.(.DATA_ADDR - 1))/3;		!# OF UCODE WORDS TO LOAD
    UUO (0, 2, 0, 0);				!GO TO 'CSL' TO LOAD UCODE
    END;

GLOBAL ROUTINE MR : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE PASSES A 'MR' (MASTER RESET) COMMAND TO THE
!	'SEND_LINE' ROUTINE FOR CONCATENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PASSES 'MR' COMMAND STRING TO 'SEND_LINE' FOR CONCATENATION
!	ONTO THE COMMAND LINE.  WHEN IT GETS EXECUTED, THE KS10 WILL
!	BE RESET.
!
!--
    BEGIN

    BIND
	MR_CMD = UPLIT (%ASCIZ'MR');		!'MR' COMMAND STRING

    SEND_LINE (MR_CMD, 0);
    END;

GLOBAL ROUTINE PE (ARG) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO TURN ON OR OFF PARITY DETECTION BY
!	THE 8080.  IT PASSES THE APPROPRIATE 'PE' COMMAND TO 'SEND_LINE'
!	FOR CONCATENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ARG		= ARGUMENT FIELD FOR PE COMMAND
!			  0 - DISBALE ALL PARITY DETECTION
!			  1 - ENABLE DATA PATH PARITY DETECTION
!			  2 - ENABLE CRAM PARITY DETECTION
!			  3 - (1 AND 2)
!			  4 - ENABLE CLOCK STOP ON PARITY ERROR
!			  5 - (1 AND 4)
!			  6 - (2 AND 4)
!			  7 - ENABLE ALL
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PASSES 'PE' COMMAND STRING TO 'SEND_LINE' FOR CONCATENATION
!	ONTO THE COMMAND LINE.  WHEN EXECUTED, IT WILL TURN ON OR OFF
!	8080 PARITY DETECTION. IF THE ARGUMENT PARAMETER IS OUT OF RANGE,
!	AN ERROR MESSAGE IS PRINTED.
!
!--
    BEGIN

    BIND
	PE_CMD = UPLIT (%ASCIZ'PE ');		!'PE' COMMAND STRING SKELETON

    LOCAL
	BUF_PTR;				!BYTE POINTER

    REGISTER
	AC0 = 0;

    IF (.ARG LSS 0) OR (.ARG GTR 7)		!CHECK IF ARG IS IN RANGE

    THEN
	BEGIN
	PTSTNUM ();				!PRINT TEST NUMBER
	PTXT_CRLF ('ARGUMENT TO PE ROUTINE NOT 0 TO 7');
	END;

    BUF_PTR = POINT (PE_CMD, 22, 7, 0, 0);
    REPLACEI (BUF_PTR, .ARG + %O'60');		!INSERT ARGUMENT FIELD
    SEND_LINE (PE_CMD, 0);
    END;

GLOBAL ROUTINE CE (ARG) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO ENABLE OR DISABLE CACHING BY THE KS10.
!	IT PASSES A 'CE' COMMAND TO THE 'SEND_LINE' ROUTINE FOR CONCAT-
!	ENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ARG		= ARGUMENT FIELD FOR 'CE' COMMAND STRING
!			  0 - DISABLE CACHING
!			  1 - ENABLE CACHING
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PASSES A 'CE' COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR
!	CONCATENATION ONTO THE COMMAND LINE.  WHEN EXECUTED, IT WILL
!	ENABLE OR DISABLE CACHING ON THE KS10.  IF THE 'ARG' PARAMETER IS
!	OUT OF RANGE, AN ERROR MESSAGE IS PRINTED.
!
!--
    BEGIN

    BIND
	CE_CMD = UPLIT (%ASCIZ'CE ');		!'CE' COMMAND STRING SKELETON

    LOCAL
	BUF_PTR;				!BYTE POINTER

    REGISTER
	AC0 = 0;

    IF (.ARG LSS 0) OR (.ARG GTR 1)		!CHECK IF ARG FIELD IS IN RANGE
    THEN
	BEGIN
	PTSTNUM ();				!PRINT TEST NUMBER
	PTXT_CRLF ('ARGUMENT TO CE ROUTINE NOT 0 OR 1');
	END;

    BUF_PTR = POINT (CE_CMD, 22, 7, 0, 0);
    REPLACEI (BUF_PTR, .ARG + %O'60');		!INSERT ARGUMENT FIELD
    SEND_LINE (CE_CMD, 0);
    END;

GLOBAL ROUTINE CS : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO START THE KS10 CPU CLOCK. IT PASSES
!	A 'CS' COMMAND TO 'SEND_LINE' FOR CONCATENATION ONTO THE COMMAND
!	LINE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'CS' COMMAND ONTO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, IT WILL START THE KS10 CPU CLOCK.
!
!--
    BEGIN

    BIND
	CS_CMD = UPLIT (%ASCIZ'CS');		!'CS' COMMAND STRING

    SEND_LINE (CS_CMD, 0);
    END;

GLOBAL ROUTINE CH : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO HALT THE KS10 CPU CLOCK. IT PASSES
!	A 'CH' COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR CONCAT-
!	ENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'CH' COMMAND STRING ONTO THE CUMULATIVE COMMAND
!	LINE. WHEN EXECUTED, IT WILL HALT THE KS10 CPU CLOCK.
!
!--
    BEGIN

    BIND
	CH_CMD = UPLIT (%ASCIZ'CH');		!'CH' COMMAND STRING

    SEND_LINE (CH_CMD, 0);
    END;

GLOBAL ROUTINE TP (ARG) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO ENABLE OR DISABLE KS10 TRAPPING. IT
!	PASSES A 'TP' COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR
!	CONCATENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ARG		= ARGUMENT FIELD FOR THE 'TP' COMMAND
!			  0 = DISBALE TRAPPING
!			  1 = ENABLE TRAPPING
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'TP' COMMAND ONTO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, IT WILL ENABLE OR DISABLE KS10 TRAPPING.  IF THE
!	'ARG' PARAMETER IS OUT OF RANGE, AN ERROR MESSAGE IS PRINTED.
!
!--
    BEGIN

    BIND
	TP_CMD = UPLIT (%ASCIZ'TP ');		!'TP' CMD STRING SKELETON

    LOCAL
	BUF_PTR;				!BYTE POINTER

    REGISTER
	AC0 = 0;

    IF (.ARG LSS 0) OR (.ARG GTR 1)		!CHECK IF ARG FIELD IS IN RANGE
    THEN
	BEGIN
	PTSTNUM ();				!PRINT TEST NUMBER
	PTXT_CRLF ('ARGUMENT TO TP ROUTINE NOT 0 OR 1');
	END;

    BUF_PTR = POINT (TP_CMD, 22, 7, 0, 0);
    REPLACEI (BUF_PTR, .ARG + %O'60');		!INSERT ARGUMENT FIELD
    SEND_LINE (TP_CMD, 0);
    END;

GLOBAL ROUTINE TE (ARG) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO ENABLE OR DISABLE THE KS10 1 MSEC
!	TIMER.  IT PASSES A 'TE' COMMAND STRING TO THE 'SEND_LINE'
!	ROUTINE FOR CONCATENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ARG		= ARGUMENT FIELD FOR 'TE' COMMAND STRING
!			  0 - DISABLE 1 MSEC TIMER
!			  1 - ENABLE 1 MSEC TIMER
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'TE' COMMAND ONTO THE CUMULATIVE COMMAND STRING.
!	WHEN EXECUTED, IT WILL ENABLE OR DISABLE THE KS10 1 MSEC TIMER.
!	IF THE 'ARG' PARAMETER IS OUT OF RANGE, AN ERROR MESSAGE IS
!	PRINTED.
!--
    BEGIN

    BIND
	TE_CMD = UPLIT (%ASCIZ'TE ');		!'TE' CMD STRING SKELETON

    LOCAL
	BUF_PTR;				!BYTE POINTER

    REGISTER
	AC0 = 0;

    IF (.ARG LSS 0) OR (.ARG GTR 1)		!CHECK IF ARG IS OUT OF RANGE
    THEN
	BEGIN
	PTSTNUM ();				!PRINT TEST NUMBER
	PTXT_CRLF ('ARGUMENT TO TE ROUTINE NOT 0 OR 1');
	END;

    BUF_PTR = POINT (TE_CMD, 22, 7, 0, 0);
    REPLACEI (BUF_PTR, .ARG + %O'60');		!INSERT ARGUMENT FIELD
    SEND_LINE (TE_CMD, 0);
    END;

GLOBAL ROUTINE EJ =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE EXECUTES AN 'EJ' COMMAND TO READ THE KS10 ADDRESS
!	PARAMTERS - NEXT CRAM ADDR, CURRENT LOCATION, MICROCODE J FIELD,
!	AND SUBROUTINE RETURN ADDRESS.  IT DOES THIS BY PASSING AN 'EJ'
!	COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR CONCATENATION ONTO
!	THE COMAND LINE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO BLOCK OF KS10 ADDRESS PARAMETERS.
!
!	POINTER -> CURRENT LOC
!		   NXT CRAM ADDR
!		   J FIELD
!		   SUB RTN ADDR
!
! SIDE EFFECTS:
!
!	CONCATENATES 'EJ' COMMAND TO CUMULATIVE COMMAND LINE AND
!	CAUSES COMMAND LINE TO BE SENT TO 8080.
!
!--
    BEGIN

    BIND
	EJ_CMD = UPLIT (%ASCIZ'EJ');		!'EJ' CMD STRING

    RETURN SEND_LINE (EJ_CMD, EJ_AC);
    END;

GLOBAL ROUTINE SC_0 : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DISABLE 8080 SOFT CRAM ERROR RECOVERY.
!	IT PASSES A 'SC 0' COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR
!	CONCATENATION ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'SC 0' COMMAND ONTO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, IT WILL DISABLE 8080 SOFT CRAM ERROR RECOVERY.
!
!--
    BEGIN

    BIND
	SC0_CMD = UPLIT (%ASCIZ'SC0');		!'SC 0' COMMAND STRING

    SEND_LINE (SC0_CMD, 0);
    END;

GLOBAL ROUTINE EC (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE EXECUTES AN 'EC' COMMAND TO EXAMINE THE CONTENTS
!	OF A SPECIFIED KS10 CRAM LOCATION.IT DOES THIS BY PASSING THE 'EC'
!	COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR CONCATENATION ONTO THE
!	COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ADDR		= CRAM ADDR TO BE READ
!			  IF -1, THEN DON'T PUT ADDR FIELD ON COMMAND STRING
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	POINTER TO THE CRAM DATA READ BY 8080
!
!	POINTER -> CRAM ADDR
!		   CRAM BITS 60-95
!		   CRAM BITS 24-59
!		   CRAM BITS 0-23
!
! SIDE EFFECTS:
!
!	CONCATENATES AN 'EC' COMMAND ONTO THE CUMULATIVE COMMAND LINE AND
!	CAUSES THAT COMMAND LINE TO BE SENT TO THE 8080.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	EC_CMD = UPLIT (%ASCIZ'EC    ');	!'EC' CMD STRING SKELETON

    BUF_PTR = POINT (EC_CMD, 22, 7, 0, 0);	!INIT BYTE POINTER

    IF .ADDR NEQ -1				!IF ADDR IS -1, DON'T ADD ADDR FIELD TO CMD
    THEN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ADDR, 4);	!INSERT ADDR FIELD INTO CMD

    REPLACEI (BUF_PTR, 0);			!TERMINATE THE COMMAND
    RETURN SEND_LINE (EC_CMD, EC_AC);		!SEND CMD AND RETURN POINTER
    END;

GLOBAL ROUTINE LCA (ADDR) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO LOAD A SPECIFIED CRAM ADDRESS.  IT
!	PASSES A 'LC' COMMAND STRING TO THE 'SEND_LINE' FOR CONCATENATION
!	ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ADDR		= VALUE TO BE USED AS ADDR FIELD IN 'LC' COMMAND
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES AN 'LC' COMMAND ONTO THE CUMUULATIVE COMMAND LINE.
!	WHEN EXECUTED, IT WILL LOAD THE SPECIFIED CRAM ADDRESS.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	LC_CMD = UPLIT (%ASCIZ'LC    ');	!'LC' CMD STRING SKELETON

    BUF_PTR = POINT (LC_CMD, 22, 7, 0, 0);	!INIT BYTE POINTER
    BUF_PTR = INSERT_NUM (.BUF_PTR, .ADDR, 4);	!INSERT ADDR FIELD INTO CMD
    REPLACEI (BUF_PTR, 0);			!TERMINATE COMMAND
    SEND_LINE (LC_CMD, 0);
    END;

GLOBAL ROUTINE DC_035 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT SPECIFIED DATA INTO BITS 0-35
!	OF THE KS10 CRAM (BITS 36-96 ARE ZEROED).  IT CREATES AND PASSES
!	A 'DC' COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR CONCATENATION
!	ONTO THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE WRITTEN INTO CRAM BITS 0-35
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'DC' COMMAND ONTO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, IT WILL WRITE THE SPECIFIED DATA INTO CRAM BITS 0-35
!	AND ZEROES BITS 36-96.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	DC_CMD = UPLIT (%ASCIZ'DC                                '); !'DC" CMD SKELETON

    BUF_PTR = POINT (DC_CMD, 22, 7, 0, 0);	!INIT BYTE POINTER
    BUF_PTR = INSERT_NUM (.BUF_PTR, .DATA, 12);	!INSERT DATA FIELD INTO CMD

    INCR I FROM 0 TO 19 BY 1 DO
	REPLACEI (BUF_PTR, %C'0');		!FILL IN ZEROS FOR CRAM BITS 36-96

    REPLACEI (BUF_PTR, 0);			!TERMINATE COMMAND STRING
    SEND_LINE (DC_CMD, 0);			!SEND CMD LINE
    END;

GLOBAL ROUTINE MOD_FLD (DIAG_FN, DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO MODIFY A 12-BIT DATA FIELD IN THE KS10
!	CRAM.  THE LOCATION MODIFIED IS THAT WHICH WAS PREVIOUSLY SELECTED
!	BY A 'DC' OR 'LC' COMMAND.  'LF' AND 'DF' COMMAND STRINGS ARE
!	PASSED TO THE 'SEND_LINE' ROUTINE FOR CONCATENATION ONTO THE
!	COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	DIAG_FN		= DIAG FUNCTION TO BE USED AS ARGUMENT FIELD IN THE
!			  'LF' COMMAND.  IT SPECIFIES WHICH MICROCODE FIELD
!			  IS TO BE MODIFIED.
!	DATA		= 12-BIT DATA TO BE DEPOSITED INTO SPECIFIED MICRO-
!			  CODE FIELD.  IT IS USED AS ARGUMENT FIELD IN THE
!			  'DF; COMMAND.
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LF' AND 'DF' COMMANDS ONTO THE CUMULATIVE COMMAND
!	LINE. WHEN EXECUTED, THEY WILL WRITE THE SPECIFIED DATA INTO
!	THE SPECIFIED 12-BIT FIELD OF THE MICROCODE.  IF THE 'DIAG_FN'
!	PARAMETER IS OUT OF RANGE, AN ERROR MESSAGE IS PRINTED.
!
!--
    BEGIN

    OWN
	CMD_BUF : CHAR_BUF [13];		!BUFFER FOR COMMAND STRING

    LOCAL
	BUF_PTR;				!BYTE POINTER

    REGISTER
	AC0 = 0;

    IF (.DIAG_FN LSS 0) OR (.DIAG_FN GTR 7)	!DO A RANGE CHECK ON DIAG FN
    THEN
	BEGIN
	PRINT_TXT ('TEST #');
	PRINT_DEC (.TEST_NUM);
	PRINT_CRLF;
	PTXT_CRLF ('DIAG FN VALUE OUT OF RANGE IN MOD_FLD CALL');
	RETURN;
	END;

    BUF_PTR = POINT (CMD_BUF, 36, 7, 0, 0);	!INIT BYTE POINTER

!CREATE THE 'LF' AND 'DF' COMMANDS IN THE BUFFER

    REPLACEI (BUF_PTR, %C'L');
    REPLACEI (BUF_PTR, %C'F');
    REPLACEI (BUF_PTR, .DIAG_FN + %O'60');	!INSERT DIAG FN INTO CMD
    REPLACEI (BUF_PTR, %C',');
    REPLACEI (BUF_PTR, %C'D');
    REPLACEI (BUF_PTR, %C'F');
    BUF_PTR = INSERT_NUM (.BUF_PTR, .DATA, 4);	!INSERT DATA FIELD INTO CMD
    REPLACEI (BUF_PTR, 0);			!TERMINATE THE COMMAND
    SEND_LINE (CMD_BUF, 0);
    END;

GLOBAL ROUTINE DM_CHK (ADDR, DATA) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE EXECUTES A DEPOSIT MEMORY, 'DM', COMMAND AND CHECKS
!	THAT NO ERROR RESPONSE IS RECEIVED.
!
! FORMAL PARAMETERS:
!
!	ADDR		= MEMORY ADDRESS TO BE WRITTEN
!	DATA		= 36-BIT DATA TO BE WRITTEN INTO MEMORY
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	0 IF NO ERROR RESPONSE IS RECEIVED.
!	1 IF AN ERROR RESPONSE IS RECEIVED.
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'DM' COMMAND ONTO THE CUMULATIVE COMMAND LINE AND
!	CAUSES THAT LINE TO BE SENT TO THE 8080.
!
!--
    BEGIN

    LOCAL
	RESPONSE;

    MEM_DEPOSIT (.ADDR, .DATA);			!CONCATENATE 'DM' COMMAND
    RESPONSE = SEND_NUL ();			!FORCE SENDING OF COMMAND LINE

!IF LEFT HALF OF RESPONSE IS NON-ZERO, IT IS A POINTER TO AN ERROR RESPONSE
!MESSAGE.

    IF .RESPONSE<18, 18> NEQ 0 THEN RETURN 1;

    RETURN 0;

    END;

GLOBAL ROUTINE MEM_DEPOSIT (ADDR, DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED 36-BIT WORD INTO A
!	SPECIFIED MEMORY LOCATION.  IT DOES THIS BY PASSING A LOAD ADDRESS,
!	'LA', COMMAND AND A DEPOSIT MEMORY, 'DM', COMMAND TO THE 'SEND_LINE'
!	ROUTINE FOR CONCATENATION ONTO THE COMMAND LINE.  IF THE LAST MEMORY
!	ADDRESS WHICH WAS REFERENCED IS THE SAME AS THE PRESENT ADDRESS, THEN
!	THE 'LA' COMMAND IS NOT NEEDED.  THE 8080 PROGRAM REMEMBERS THE LAST
!	ADDRESS REFERENCED.
!
! FORMAL PARAMETERS:
!
!	ADDR		= MEMORY ADDRESS TO BE WRITTEN
!	DATA		= 36-BIT DATA TO BE WRITTEN INTO MEMORY
!
! IMPLICIT INPUTS:
!
!	LAST_MEM_ADDR	= MEMORY ADDRESS WHICH WAS REFERENCED LAST BY AN
!			  'EM' OR 'DM' COMMAND.
!
! IMPLICIT OUTPUTS:
!
!	LAST_MEM_ADDR	= MEMORY ADDRESS SPECIFIED IN 'ADDR' PARAMETER
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LA' AND 'DM' COMMANDS ONTO THE CUMULATIVE COMMAND
!	LINE.  WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED 36-BIT WORD
!	INTO THE SPECIFIED MEMORY LOCATION.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	LA_CMD = UPLIT (%ASCIZ'LA       '),	!'LA' COMMAND STRING SKELETON
	DM_CMD = UPLIT (%ASCIZ'DM            '); !'DM' COMMAND STRING SKELETON

!IF THE PRESENT ADDRESS IS THE SAME AS THE LAST ADDRESS REFERENCED, THE 'LA'
!COMMAND IS NOT NEEDED.

    IF .ADDR NEQ .LAST_MEM_ADDR
    THEN
	BEGIN
	BUF_PTR = POINT (LA_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ADDR, 7); !INSERT ADDR FIELD INTO CMD STRING
	REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
	SEND_LINE (LA_CMD, 0);			!PASS CMD
	LAST_MEM_ADDR = .ADDR;			!UPDATE LAST MEM ADDR ACCESSED
	END;

    BUF_PTR = POINT (DM_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
    BUF_PTR = INSERT_NUM (.BUF_PTR, .DATA, 12);	!PUT DATA FIELD IN CMD STRING
    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    SEND_LINE (DM_CMD, 0);			!PASS CMD
    END;

GLOBAL ROUTINE MEM_EXAMINE (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE EXECUTES AN EXAMINE MEMORY, 'EM', COMMAND.  IT CALLS THE
!	'EM' ROUTINE TO CREATE THE 'EM' COMMAND AND CONCATENATE IT ONTO THE
!	COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ADDR		= MEMORY ADDRESS TO BE EXAMINED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CAUSES CONCATENATION OF 'EM' COMMAND ONTO CUMULATIVE COMMAND LINE AND
!	SENDING OF THAT COMMAND LINE.
!
!--
    BEGIN
    RETURN .(EM (.ADDR) + 1);
    END;

GLOBAL ROUTINE EM_CHK (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO EXECUTE AN 'EM' COMMAND AND CHECK FOR
!	A 'NXM' RESPONSE.
!
! FORMAL PARAMETERS:
!
!	ADDR		= MEMORY ADDRESS TO BE EXAMINED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	0 IF NO ERROR RESPONSE IS RECEIVED.
!	1 IF A 'NXM' ERROR RESPONSE IS RECEIVED.
!
! SIDE EFFECTS:
!
!	CAUSES CONCATENATION OF AN 'EM' COMMAND ONTO THE CUMULATIVE COMMAND
!	LINE AND SENDING OF THAT LINE. IF A NON-NXM ERROR RESPONSE IS RECEIVED,
!	AN ERROR MESSAGE IS PRINTED AND TESTING IS ABORTED.
!
!--
    BEGIN

    BIND
	NXM_MSG = UPLIT (%ASCIZ'?NXM');	!FORMAT FOR 8080 NXM ERROR MESSAGE

    LOCAL
	RESPONSE;

    RESPONSE = EM (.ADDR);			!GO SEND 'EM' COMMAND

!IF LEFT HALF OF RESPONSE IS NON-ZERO, ITS A POINTER TO AN ERROR RESPONSE.
!GO CHECK IF ITS A 'NXM' MESSAGE.

    IF .RESPONSE<18, 18> NEQ 0
    THEN
	BEGIN
	MSG_CHK (.RESPONSE, NXM_MSG);
	RETURN 1
	END;

    RETURN 0;

    END;

ROUTINE EM (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CAUSES EXECUTION OF AN 'EM' COMMAND.  IT PASSES AN
!	'EM' COMMAND STRING TO THE 'SEND_LINE' ROUTINE FOR CONCATENATION ONTO
!	THE COMMAND LINE AND FORCES THE SENDING OF THAT COMMAND LINE.  IF THE
!	LAST MEMORY ADDRESS REFERENCED IS THE SAME AS THE PRESENT ADDRESS,
!	THEN THE ADDRESS FIELD OF THE 'EM' COMMAND IS NOT NEEDED. 
!
!FORMAL PARAMETERS:
!
!	ADDR		= MEMORY ADDRESS TO BE EXAMINED
!
! IMPLICIT INPUTS:
!
!	LAST_MEM_ADDR	= MEMORY ADDRESS WHICH WAS REFERENCED LAST BY AN
!			  'EM' OR 'DM' COMMAND.
!
! IMPLICIT OUTPUTS:
!
!	LAST_MEM_ADDR	= MEMORY ADDRESS SPECIFIED IN 'ADDR' PARAMETER
!
! ROUTINE VALUE:
!
!	POINTER TO THE BLOCK OF DATA RETURNED BY THE 'EM' COMMAND.
!
!	POINTER -> ADDR
!		   DATA
!
! SIDE EFFECTS:
!
!	CONCATENATES 'EM' COMMAND ONTO CUMULATIVE COMMAND LINE AND FORCES
!	SENDING OF THAT LINE.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	EM_CMD = UPLIT (%ASCIZ'EM       ');	!'EM' CMD STRING SKELETON

    BUF_PTR = POINT (EM_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER

!IF LAST ADDRESS REFERENCED IS SAME AS PRESENT ADDRESS, THE ADDR FIELD IS
!NOT NEEDED.

    IF .ADDR NEQ .LAST_MEM_ADDR
    THEN
	BEGIN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ADDR, 7); !INSERT ADDR FIELD ON CMD STRING
	LAST_MEM_ADDR = .ADDR;			!UPDATE LAST MEM ADDR ACCESSED
	END;

    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    RETURN SEND_LINE (EM_CMD, EM_AC);		!PASS CMD
    END;
ROUTINE MSG_CHK (RESPONSE, MSG) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE COMPARES A RECEIVED ERROR RESPONSE WITH AN EXPECTED
!	ERROR RESPONSE.
!
! FORMAL PARAMETERS:
!
!	RESPONSE	= BYTE POINTER TO RECEIVED RESPONSE
!	MSG		= POINTER TO EXPECTED RESPONSE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	IF THE RECEIVED RESPONSE IS NOT THE SAME AS THE EXPECTED RESPONSE,
!	THEN THE 'PRT_ERR' ROUTINE IS CALLED TO PRINT AN ERROR MESSAGE AND
!	ABORT TESTING.
!
!--
    BEGIN

    LOCAL
	MSG_PTR,				!BYTE POINTER TO EXPECTED RESPONSE
	SAV_PTR;				!SAVED BYTE POINTER

    MSG_PTR = POINT (.MSG, 36, 7, 0, 0);	!SETUP POINTER TO EXPECTED RESPONSE
    SAV_PTR = .RESPONSE;			!SAVE POINTER TO RECEIVED RESPONSE

!COMPARE RECEIVED WITH EXPECTED RESPONSE ONE CHAR AT A TIME.  IF MISMATCH IS
!FOUND, REPORT ERROR AND ABORT.
    INCR I FROM 0 TO 3 BY 1 DO

	IF SCANI (MSG_PTR) NEQ SCANI (RESPONSE) THEN PRT_ERR (.SAV_PTR);

    END;

GLOBAL ROUTINE DN (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CONCATENATES A DEPOSIT NEXT, 'DN', COMMAND STRING ONTO
!	THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	DATA		= 36-BIT DATA TO BE DEPOSITED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	LAST_MEM_ADDR	= -1, TO INVALIDATE LAST MEM ADDRESS REFERENCED
!	LAST_IO_ADDR	= -1, TO INVALIDATE LAST I/O ADDRESS REFERENCED
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES A 'DN' COMMAND ONTO CUMULATIVE COMMAND LINE.  WHEN
!	EXECUTED, IT WILL DEPOSIT THE SPECIFIED DATA INTO THE NEXT MEMORY
!	LOCATION OR I/O REGISTER, DEPENDING ON THE ORIGINAL DEPOSIT COMMAND.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	DN_CMD = UPLIT (%ASCIZ'DN            '); !'DN' COMMAND SKELETON

    LAST_MEM_ADDR = -1;				!WIPE OUT LAST ADDRESSES
    LAST_IO_ADDR = -1;
    BUF_PTR = POINT (DN_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
    BUF_PTR = INSERT_NUM (.BUF_PTR, .DATA, 12);	!PUT DATA FIELD IN CMD
    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    SEND_LINE (DN_CMD, 0);			!PASS CMD
    END;

GLOBAL ROUTINE IO_DEPOSIT (ADDR, DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO PERFORM AN I/O DEPOSIT COMMAND.  IT
!	PASSES 'LI' AND 'DI' COMMAND STRINGS TO THE 'SEND_LINE' ROUTINE FOR
!	CONCATENATION ONTO THE COMMAND LINE.  IF THE LAST I/O REGISTER ADDR
!	REFERENCED IS THE SAME AS THE PRESENT ADDR, THEN THE 'LI' COMMAND IS
!	NOT NEEDED.
!
! FORMAL PARAMETERS:
!
!	ADDR		= I/O REGISTER ADDR TO BE WRITTEN
!	DATA		= 36-BIT DATA TO BE WRITTEN
!
! IMPLICIT INPUTS:
!
!	LAST_IO_ADDR	= LAST I/O REGISTER ADDR REFERENCED BY AN 'EI' OR
!			  'DI' COMMAND.
!
! IMPLICIT OUTPUTS:
!
!	LAST_IO_ADDR	= I/O REGISTER ADDRESS SPECIFIED IN 'ADDR' PARAMETER
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LI' AND 'DI' COMMANDS ONTO THE CUMULATIVE COMMAND
!	LINE.  WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO THE
!	SPECIFIED I/O REGISTER ADDRESS.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	LI_CMD = UPLIT (%ASCIZ'LI        '),	!'LI' CMD STRING SKELETON
	DI_CMD = UPLIT (%ASCIZ'DI            '); !'DI' CMD STRING SKELETON

!IF PRESENT I/O ADDR IS SAME AS LAST REFERENCED I/O ADDR, THEN 'LI' COMMAND
!IS NOT NEEDED.

    IF .ADDR NEQ .LAST_IO_ADDR
    THEN
	BEGIN
	BUF_PTR = POINT (LI_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ADDR, 8); !INSERT ADDR FIELD INTO CMD
	REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
	SEND_LINE (LI_CMD, 0);			!PASS CMD
	LAST_IO_ADDR = .ADDR;			!UPDATE LAST IO ADDR ACCESSED
	END;

    BUF_PTR = POINT (DI_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
    BUF_PTR = INSERT_NUM (.BUF_PTR, .DATA, 12);	!PUT DATA FIELD IN CMD
    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    SEND_LINE (DI_CMD, 0);			!PASS CMD
    END;

GLOBAL ROUTINE IO_EXAMINE (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO EXAMINE A SPECIFIED I/O REGISTER.  IT CALLS
!	THE 'EI' ROUTINE TO GENERATE AN 'EI' COMMAND AND CONCATENATE IT ONTO
!	THE COMMAND LINE.
!
! FORMAL PARAMETERS:
!
!	ADDR		= I/O REGISTER ADDRESS TO BE EXAMINED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	CONTENTS OF EXAMINED I/O REGISTER
!
! SIDE EFFECTS:
!
!	CONCATENATES AN 'EI' COMMAND ONTO THE CUMULATIVE COMMAND LINE AND
!	FORCES THAT LINE TO BE SENT.
!
!--
    BEGIN
    RETURN .(EI (.ADDR) + 1);			!SEND 'EI' CMD AND RETURN RESULTS
    END;

ROUTINE EI (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CREATES AN 'EI' COMMAND AND CALLS THE 'SEND_LINE'
!	ROUTINE TO CONCATENATE IT TO THE COMMAND LINE AND SEND THAT LINE.
!	IF THE REGISTER ADDR IS THE SAME AS THE LAST REGISTER ADDR, THEN
!	THE ADDR FIELD OF THE COMMAND STRING IS NOT NEEDED.
!
! FORMAL PARAMETERS:
!
!	ADDR		= I/O REGISTER ADDRESS TO BE EXAMINED.
!
! IMPLICIT INPUTS:
!
!	LAST_IO_ADDR	= LAST I/O REGISTER ADDR REFERENCED BY AN 'EI' OR
!			  'DI' COMMAND.
!
! IMPLICIT OUTPUTS:
!
!	LAST_IO_ADDR	= I/O REGISTER ADDRESS SPECIFIED IN 'ADDR' PARAMETER
!
! ROUTINE VALUE:
!
!	POINTER TO BLOCK OF DATA RETURNED BY 'EI' COMMAND
!
!	POINTER -> I/O ADDR
!		   DATA
!
! SIDE EFFECTS:
!
!	CONCATENATES AN 'EI' COMMAND ONTO THE CUMULATIVE COMMAND LINE
!	AND FORCES SENDING OF THAT LINE.
!
!--
    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	EI_CMD = UPLIT (%ASCIZ'EI        ');	!'EI' CMD STRING SKELETON

    BUF_PTR = POINT (EI_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER

!IF PRESENT I/O ADDR IS SAME AS LAST REFERENCED I/O ADDR, THEN THE ADDR FIELD
!IS NOT NEEDED.

    IF .ADDR NEQ .LAST_IO_ADDR
    THEN
	BEGIN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .ADDR, 8); !INSERT ADDR FIELD IN CMD STRING
	LAST_IO_ADDR = .ADDR;			!UPDATE LAST IO ADDR ACCESSED
	END;

    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    RETURN SEND_LINE (EI_CMD, EI_AC);		!PASS CMD
    END;

GLOBAL ROUTINE EI_CHK (ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO EXECUTE AN 'EI' COMMAND AND CHECK FOR
!	AN '?NDA' ERROR RESPONSE.
!
! FORMAL PARAMETERS:
!
!	ADDR		= I/O REGISTER ADDRESS TO BE EXAMINED.
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	0 IF NO ERROR RESPONSE IS RECEIVED
!	1 IF AN '?NDA' ERROR RESPONSE IS RECEIVED
!
! SIDE EFFECTS:
!
!	CONCATENATES AN 'EI' COMMAND ONTO THE CUMULATIVE COMMAND LINE AND
!	FORCES THE SENDING OF THAT LINE.  IF AN ERROR RESPONSE OTHER THAN
!	'?NDA' IS RECEIVED, AN ERROR MESSAGE IS PRINTED ON THE TTY AND 
!	TESTING IS ABORTED.
!
!--
    BEGIN

    BIND
	NDA_MSG = UPLIT (%ASCIZ'?NDA');	!FORMAT FOR 8080 NO DATA ACK MESSAGE

    LOCAL
	RESPONSE;

    RESPONSE = EI (.ADDR);			!EXECUTE 'EI' COMMAND

!IF LEFT HALF OF RESPONSE IS NON-ZERO, THEN IT IS A BYTE POINTER TO AN
!ERROR RESPONSE.  GO CHECK IF THAT RESPONSE IS '?NDA'.

    IF .RESPONSE<18, 18> NEQ 0
    THEN
	BEGIN
	MSG_CHK (.RESPONSE, NDA_MSG);		!GO CHECK FOR ?NDA
	RETURN 1				!GIVE '?NDA RECEIVED' RETURN
	END;

    RETURN 0;					!GIVE 'NO ERROR RESPONSE' RETURN

    END;

ROUTINE INSERT_NUM (BUF_PTR, NUM, DIGITS) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE INSERTS AN ARGUMENT FIELD INTO A COMMAND STRING.  IT
!	CONVERTS A PASSED BINARY VALUE INTO AN ASCII DIGITS.
!
! FORMAL PARAMETERS:
!
!	BUF_PTR		= BYTE POINTER TO POSITION IN CMD STRING WHERE
!			  ARGUMENT FIELD IS TO BE INSERTED
!	NUM		= BINARY VALUE OF ARGUMENT FIELD
!	DIGITS		= NUMBER OF ASCII DIGITS TO BE INSERTED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	BYTE POINTED UPDATED TO NEXT POSITION AFTER LAST DIGIT IN THE
!	INSERTED ARGUMENT FIELD.
!
! SIDE EFFECTS:
!
!	INSERT ASCII ARGUMENT FIELD INTO SPECIFIED COMMAND STRING.
!
!--
    BEGIN

    LOCAL
	SWITCH,					!FLAG INDICATING WHETHER OR NOT INSERTION HAS STARTED
	TEMP;					!TEMP STORAGE FOR ASCII DIGIT

    SWITCH = 0;					!INIT FLAG TO SHOW INSERTION HASN'T STARTED

!THE DIGITS ARE INSERTED FROM LEFT TO RIGHT - HIGH ORDER TO LOW ORDER.  SO THE
!PASSED NUMBER TO BE INSERTED IS PROCESSED FROM LEFT TO RIGHT IN 3-BIT
!QUANTITIES.  LEADING ZEROS ARE NOT INSERTED.  WHEN THE FIRST NON-ZERO DIGIT
!IS INSERTED, THE 'SWITCH' FLAG IS SET SO ALL SUBSEQUENT DIGITS ARE INSERTED,
!ZERO OR NOT.

    DECR I FROM .DIGITS TO 1 DO
	BEGIN
	TEMP = .NUM<(.I - 1)*3, 3>;		!GET NEXT OCTAL DIGIT

	IF (.TEMP NEQ 0) OR (.SWITCH EQL 1) OR (.I EQL 1)
	THEN
	    BEGIN
	    REPLACEI (BUF_PTR, .TEMP + %O'60');
	    SWITCH = 1;
	    END;

	END;

    RETURN .BUF_PTR;				!RETURN UPDATED BUFFER POINTER
    END;

GLOBAL ROUTINE REG_EXAMINE (REG_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CREATES AN EXAMINE REGISTER, 'ER', COMMAND AND CALLS
!	THE 'SEND_LINE' ROUTINE TO CONCATENATE IT ONTO THE COMMAND LINE AND
!	SEND IT TO THE 8080.  IF THE 8080 REGISTER ADDRESS IS THE SAME AS
!	THE LAST REGISTER REFERENCED, THEN THE ADDRESS FIELD IS NOT NEEDED.
!
! FORMAL PARAMETERS:
!
!	ADDR		= 8080 REGISTER ADDRESS TO BE EXAMINED
!
! IMPLICIT INPUTS:
!
!	LAST_REG_ADDR	= 8080 REGISTER ADDRESS WHICH WAS LAST REFERENCED BY
!			  AN 'ER' OR 'LR' COMMAND.
!
! IMPLICIT OUTPUTS:
!
!	LAST_REG_ADDR	= 8080 REGISTER ADDRESS SPECIFIED IN 'ADDR' PARAMETER
!
! ROUTINE VALUE:
!
!	CONTENTS OF 8080 REGISTER WHICH WAS EXAMINED
!
! SIDE EFFECTS:
!
!	CONCATENATES AN 'ER' COMMAND ONTO THE CUMULATIVE COMMAND LINE AND
!	FORCES SENDING OF THAT LINE.
!
!--
    BEGIN

    LOCAL
	BUF_PTR,				!BYTE POINTER
	RESPONSE;				!TEMP STORAGE FOR RESPONSE

    BIND
	ER_CMD = UPLIT (%ASCIZ'ER   ');		!'ER' CMD STRING SKELETON

    BUF_PTR = POINT (ER_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER

!IF REGISTER ADDRESS IS THE SAME AS THE LAST REFERENCED REGISTER ADDRES, THEN
!THE ADDRESS FIELD IS NOT NEEDED.

    IF .LAST_REG_ADDR NEQ .REG_ADDR
    THEN
	BEGIN
	BUF_PTR = INSERT_NUM (.BUF_PTR, .REG_ADDR, 3); !INSERT ADDR FIELD
	LAST_REG_ADDR = .REG_ADDR;		!UPDATE LAST REG ADDR
	END;

    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD STRING
    RESPONSE = SEND_LINE (ER_CMD, ER_AC);	!SEND CMD AND GET RESPONSE
    RETURN .(.RESPONSE + 1);			!RETURN JUST REG CONTENTS
    END;

GLOBAL ROUTINE WRT100 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	100.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 100
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 100.
!
!--
    BEGIN
    REG_DEPOSIT (%O'100',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT102 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	102.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 102
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 102.
!
!--
    BEGIN
    REG_DEPOSIT (%O'102',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT103 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	103.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 103
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 103.
!
!--
    BEGIN
    REG_DEPOSIT (%O'103',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT104 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	104.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 104
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 104.
!
!--
    BEGIN
    REG_DEPOSIT (%O'104',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT105 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	105.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 105
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 105.
!
!--
    BEGIN
    REG_DEPOSIT (%O'105',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT106 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	106.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 106
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 106.
!
!--
    BEGIN
    REG_DEPOSIT (%O'106',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT107 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	107.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 107
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 107.
!
!--
    BEGIN
    REG_DEPOSIT (%O'107',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT110 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	110.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 110
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 110.
!
!--
    BEGIN
    REG_DEPOSIT (%O'110',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT111 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	111.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 111
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 111.
!
!--
    BEGIN
    REG_DEPOSIT (%O'111',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT112 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	112.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 112
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 112.
!
!--
    BEGIN
    REG_DEPOSIT (%O'112',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT113 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	113.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 113
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 113.
!
!--
    BEGIN
    REG_DEPOSIT (%O'113',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT114 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	114.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 114
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 114.
!
!--
    BEGIN
    REG_DEPOSIT (%O'114',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT115 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	115.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 115
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 115.
!
!--
    BEGIN
    REG_DEPOSIT (%O'115',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT116 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	116.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 116
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 116.
!
!--
    BEGIN
    REG_DEPOSIT (%O'116',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT204 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	204.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 204
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 204.
!
!--
    BEGIN
    REG_DEPOSIT (%O'204',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT205 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	205.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 205
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 205.
!
!--
    BEGIN
    REG_DEPOSIT (%O'205',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT206 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	206.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 206
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 206.
!
!--
    BEGIN
    REG_DEPOSIT (%O'206',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT210 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	210.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 210
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 210.
!
!--
    BEGIN
    REG_DEPOSIT (%O'210',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;

GLOBAL ROUTINE WRT212 (DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO DEPOSIT A SPECIFIED VALUE INTO 8080 REGISTER
!	212.  IT CALLS THE 'REG_DEPOSIT' ROUTINE TO CREATE 'LR' AND 'DR'
!	COMMANDS.
!
! FORMAL PARAMETERS:
!
!	DATA		= DATA TO BE DEPOSITED INTO 8080 REGISTER 212
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO REGISTER 212.
!
!--
    BEGIN
    REG_DEPOSIT (%O'212',.DATA);		!GO MAKE 'LR' AND 'DR' CMDS
    END;
ROUTINE REG_DEPOSIT (REG_ADDR,DATA) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE CREATES 'LR' AND 'DR' COMMAND STRINGS AND PASSES THEM
!	TO THE 'SEND_LINE' ROUTINE FOR CONCATENATION ONTO THE COMMAND LINE.
!	IF THE 8080 REGISTER ADDRESS IS THE SAME AS THE LAST REFERENCED 
!	ADDRESS, THEN THE 'LR' COMMAND IS NOT NEEDED.
!
! FORMAL PARAMETERS:
!
!	REG_ADDR	= ADDRESS OF 8080 REGISTER TO BE WRITTEN
!	DATA		= 8-BIT DATA TO BE WRITTEN
!
! IMPLICIT INPUTS:
!
!	LAST_REG_ADDR	= ADDRESS OF 8080 REGISTER WHICH WAS LAST
!			  REFERENCED BY AN 'ER' OR 'LR' COMMAND.
!
! IMPLICIT OUTPUTS:
!
!	LAST_REG_ADDR	= 800 REGISTER ADDRESS SPECIFIED BY 'REG_ADDR'
!			  PARAMETER.
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	CONCATENATES 'LR' AND 'DR' COMMANDS TO THE CUMULATIVE COMMAND LINE.
!	WHEN EXECUTED, THEY WILL DEPOSIT THE SPECIFIED DATA INTO THE SPECIFIED
!	8080 REGISTER.
!--

    BEGIN

    LOCAL
	BUF_PTR;				!BYTE POINTER

    BIND
	DR_CMD = UPLIT (%ASCIZ'DR   '),		!'DR' CMD STRING SKELETON
	LR_CMD = UPLIT (%ASCIZ'LR   ');		!'LR' CMD STRING SKELETON

!IF THE 8080 REG ADDR IS THE SAME AS THE LAST REFERENCED REG ADDR, THEN THE
!'LR' COMMAND IS NOT NEEDED.

    IF .LAST_REG_ADDR NEQ .REG_ADDR
    THEN
	BEGIN
	BUF_PTR = POINT (LR_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
	BUF_PTR = INSERT_NUM (.BUF_PTR, .REG_ADDR, 3); !INSERT REG ADDR FIELD
	REPLACEI (BUF_PTR, 0);			!TERMINATE COMMAND
	SEND_LINE (LR_CMD, 0);			!GO CONCATENATE 'LR' CMD
	LAST_REG_ADDR = .REG_ADDR;		!UPDATE LAST REG ADDR
	END;

    BUF_PTR = POINT (DR_CMD, 22, 7, 0, 0);	!SETUP BYTE POINTER
    BUF_PTR = INSERT_NUM (.BUF_PTR, .DATA, 3);	!INSERT DATA FIELD IN CMD
    REPLACEI (BUF_PTR, 0);			!TERMINATE CMD
    SEND_LINE (DR_CMD, 0);			!GO CONCATENATE 'DR' CMD
    END;

GLOBAL ROUTINE TICK (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO GENERATE A SPECIFIED NUMBER OF SYSTEM CLOCK
!	TICKS.
!	IF THE 'SINGLE STEP' FEATURE IS ACTIVATED AND THE PROGRAM IS
!	LOOPING ON A TEST OR AN ERROR, THEN THE TICKS MUST BE DONE IN
!	A CONTROLLED MANNER.  THIS IS DONE BY CALLING THE 'SS_TICK'
!	ROUTINE.
!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK TICKS REQUIRED
!
! IMPLICIT INPUTS:
!
!	SINGLE_STEP	= FEATURE FLAG INDICATING THAT CLOCK TICKS ARE TO
!			  BE SINGLE STEPPED.
!	LOOPING		= FLAG INDICATING THAT PROGRAM IS LOOPING ON ERROR
!	LOOP_ON_TEST	= FEATURE FLAG INDICATING THAT PROGRAM IS LOOPING
!			  ON TEST.
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	IF SINGLE-STEPPING, THE CLOCK TICKS ARE DOEN UNDER USER CONTROL.
!	IF THE TICK COUNT IS OUT OF RANGE, AN ERROR MESSAGE IS PRINTED
!	ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    IF (.N LSS 1) OR (.N GTR %O'376')	!IS TICK COUNT OUT OF RANGE (FOR 'RP' CMD)
    THEN
	BEGIN
	PTSTNUM ();				!PRINT THE TEST NUMBER
	PTXT_CRLF ('TICK COUNT OUT OF RANGE');
	END;

!CHECK WHETHER WE SHOULD DO SINGLE STEPPING OR NOT

    IF .SINGLE_STEP AND (.LOOPING OR .LOOP_ON_TEST)
    THEN
	SS_TICK (.N)				!GO DO SINGLE STEPPING
    ELSE
	SEND_TICK (.N);				!GO SEND TICKS
    END;

GLOBAL ROUTINE TICK_NOSS (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE IS CALLED TO GENERATE A SPECIFIED NUMBER OF SYSTEM
!	CLOCK TICKS.  IT DOES SO BY CALLING THE 'SS_TICK' ROUTINE.

!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK TICKS REQUIRED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	A 'RP' COMMAND STRING IS CONCATENATED ONTO THE CUMULATIVE COMMAND LINE.
!	IF THE TICK COUNT IS OUT OF RANGE, AN ERROR MESSAGE IS PRINTED
!	ON THE TTY.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    IF (.N LSS 1) OR (.N GTR %O'376')	!IS TICK COUNT OUT OF RANGE
    THEN
	BEGIN
	PTSTNUM ();				!PRINT THE TEST NUMBER
	PTXT_CRLF ('TICK COUNT OUT OF RANGE');
	END;

    SEND_TICK (.N);				!EXECUTES SPECIFIED NUMBER OF TICKS
    END;

GLOBAL ROUTINE SEND_TICK (TICKS) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE EXECUTES A SPECIFIED NUMBER OF KS10 MAINTENANCE CLOCK
!	TICKS.  IT IS ASSUMED THAT THE MAIN SYSTEM CLOCK HAS ALREADY BEEN
!	DISABLED.  MAINTENANCE CLOCK TICKS ARE GENERATED BY TOGGLING THE
!	MAINT CLOCK BIT IN 8080 REGISTER 205.  THIS ROUTINE CREATES A COMMAND
!	STRING TO DO THIS TOGGLING, THEN IT ADDS A REPEAT COMMAND ON THE END.
!	THE REPEAT COUNT IS SET TO PRODUCE THE SPECIFIED NUMBER OF CLOCK
!	TICKS.
!
! FORMAL PARAMETERS:
!
!	TICKS		= NUMBER OF MAINTENANCE CLOCK TICKS REQUIRED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	FORCES SENDING OF CUMULATIVE COMMAND LINE.  THEN SENDS REPEAT COMMAND
!	STRING TO TOGGLE MAINT CLOCK BIT IN 8080 REGISTER 205.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

!IF MORE THAN 1 TICK IS REQUIRED, THEN A REPEAT COMMAND WILL BE USED.  THIS
!MEANS THAT THE CURRENT CUMULATIVE COMMAND LINE MUST BE SENT SO IT WON'T GET
!REPEATED TOO.

    IF .TICKS GTR 1 THEN SEND_NUL ();		!FORCE SENDING OF CURRENT CMD LINE

    WRT205 (MNT_CLK_ENB + MAINT_CLK);		!ASSERT MAINT CLK BIT
    WRT205 (MNT_CLK_ENB);			!NEGATE IT

!IF MORE THAN 1 TICK IS REQUIRED, ADD A REPEAT COMMAND WITH REPEAT COUNT TO
!PROVIDE REQUIRED # OF TICKS.

    IF .TICKS GTR 1 THEN REPEAT (.TICKS - 1);

    END;

ROUTINE SS_TICK (N) : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE ALLOWS THE USER TO CONTROL SINGLE TICKING OF
!	SYSTEM CLOCK.  IT PRINTS A MESSAGE INFORMING THE USER
!	OF THE NUMBER OF CLOCK TICKS REQUIRED IN THE FUNCTION
!	BEING EXECUTED.  IT THEN PROMPTS HIM/HER FOR THE NUMBER OF
!	TICKS DESIRED.  THE SPECIFIED NUMBER OF TICKS ARE EXECUTED
!	USING A 'SEND_TICK' ROUTINE.  THE RESULTS OF AN 'ER' COMMAND
!	ARE PRINTED FOLLOWING THAT EXECUTION.  THIS PROCESS IS REPEATED
!	UNTIL THE REQUIRED NUMBER OF TICKS HAVE BEEN EXECUTED.  AT
!	THAT POINT, THE USER IS ASKED IF HE/SHE WISHES TO CONTINUE.  IF NOT,
!	PROGRAM CONTROL IS RETURNED TO 'CSL'.
!
! FORMAL PARAMETERS:
!
!	N		= NUMBER OF CLOCK TICKS REQUIRED
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	PRINTS PROMPT MESSAGES ON THE TTY AND RECEIVES INPUT.
!	EXECUTES SPECIFIED NUMBER OF 'RP' AND 'ER' COMMANDS.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    OWN
	FIRST_TIME: INITIAL (0);		!FLAG FOR "NOTE" PRINTING

    LOCAL
	TICKS;					!COUNTER FOR # OF CLOCK TICKS

!PRINT REQUIRED # OF CLOCK TICKS

    PRINT_TXT ('THIS TEST SEQUENCE REQUIRES ');
    PRINT_DEC (.N);
    PTXT_CRLF (' CLOCK TICKS');
    IF .FIRST_TIME EQL 0			!ONLY PRINT "NOTE" ONCE
    THEN
	BEGIN
	FIRST_TIME = -1;			!SET FLAG
	PTXT_CRLF ('NOTE: 1 T-CLK/R-CLK CYCLE = 4 CLOCK TICKS');
	END;

!EXECUTE USER SPECIFIED NUMBER OF CLOCK TICKS UNTIL REQUIRED #
!ARE EXECUTED.

    DO
	BEGIN
	TICKS = GET_NUM (UPLIT (%ASCIZ'ENTER DESIRED NUMBER OF CLOCK TICKS'), .N);
	SEND_TICK (.TICKS);			!PASS 'RP' CMDS
	PRINT_CRLF;
	PRINT_TXT ('8080 REGISTER 303: ');
	PRINT_OCT_3 ( REG_EXAMINE (%O'303'));	!READ AND PRINT REG CONTENTS
	PRINT_CRLF;
	END
    WHILE (N = .N - .TICKS) GTR 0;

!FIND OUT IF USER WANTS TO CONTINUE OR RETURN TO 'CSL'

    PTXT_CRLF ('REQUIRED # OF CLOCK TICKS HAVE BEEN EXECUTED');
    PRINT_TXT ('DO YOU WANT TO CONTINUE THIS TEST?');

    IF NOT TTI_YES THEN EOP_UUO;

    END;

GLOBAL ROUTINE SYNC_CLK : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	THIS ROUTINE STOPS THE MAIN KS10 SYSTEM CLOCK AND SYNCHS IT TO A
!	STATE WHERE BOTH THE T-CLK AND R-CLK SIGNALS ARE NEGATED.  IT DOES
!	THIS BY TICKING THE CLOCK UNTIL THE 'R CLK ENB' SIGNAL ASSERTS.
!	THIS OCCURS WHEN THE T-CLK SIGNAL ASSERTS.  THREE MORE CLOCK TICKS
!	FROM THAT POINT WILL NEGATE BOTH T-CLK AND R-CLK.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	STOPS MAIN KS10 CLOCK AND SYNCHS IT.  IN THE PROCESS OF DOING THIS,
!	THE 'R CLK ENB' SIGNAL GETS NEGATED AND ASSERTED.
!	IF THE ROUTINE FAILS TO SYNCH THE CLOCKS, AN ERROR MESSAGE IS PRINTED
!	ON THE TTY AND TESTING IS ABORTED.
!
!--
    BEGIN

    REGISTER
	AC0 = 0;

    WRT210 (CLOSE_LATCH);			!CAUSE 'R CLK ENB' TO NEGATE
    WRT205 (MNT_CLK_ENB);			!STOP THE CLOCK
    WRT210 (0);					!NEGATE 'CLOSE LATCHS'
    TICK_NOSS (4);					!WILL TAKE AT LEAST 4 TICKS FOR
						! 'R CLK ENB' TO ASSERT.

!'R CLK ENB' SHOULD ASSERT WITHIN 4 MORE TICKS.  CHECK FOR ASSERTION AFTER
!EACH TICK.

    INCR I FROM 1 TO 4 BY 1 DO
	BEGIN
	TICK_NOSS(1);

	IF (REG_EXAMINE (%O'303') AND R_CLK_ENB0) EQL 0 !IF 'R CLK ENB' ASSERTED
	THEN
	    BEGIN
	    TICK_NOSS (3);				!GIVE 3 MORE TICKS TO MAKE
	    					!T CLK AND R CLK NEGATED
	    RETURN;
	    END;

	END;

!IF WE DROP THRU, IT MEANS WE FAILED TO SYNCH

    PTSTNUM ();					!PRINT TEST NUMBER
    PTXT_CRLF ('FAILED TO SYNC CLOCK IN MAINT MODE, TESTING BEING ABORTED');
    AC0 = .HAD_FAILURE;				!SET FLAG FOR 'CSL'
    EOP_UUO;					!RETURN COONTROL TO 'CSL'
    END;

END

ELUDOM