        PAGE    132,60,1,1
        IDENT   2,0

;
;       **** DSPBUG ****
;
;       MONITOR FOR THE DSP56000
;
;       COPYRIGHT (C) BY MOTOROLA INC, ALL RIGHTS RESERVED
;
;*      ALTHOUGH THE INFORMATION CONTAINED HEREIN,    *
;*      AS WELL AS ANY INFORMATION PROVIDED RELATIVE  *
;*      THERETO, HAS BEEN CAREFULLY REVIEWED AND IS   *
;*      BELIEVED ACCURATE, MOTOROLA ASSUMES NO        *
;*      LIABILITY ARISING OUT OF ITS APPLICATION OR   *
;*      USE, NEITHER DOES IT CONVEY ANY LICENSE UNDER *
;*      ITS PATENT RIGHTS NOR THE RIGHTS OF OTHERS.   *
;*
        PAGE
;       
;       DSPBUG is a standalone debug monitor for the Motorola DSP56001
;       digital signal processor.  .  A MC2681 dual universal asynchronous
;       receiver/transmitter (DUART) is assumed to be located in
;       peripheral space at Y:$FFC0.  The DUART requires 4 wait states to be
;       programed in the bus control register (BCR) at a processor speed 
;       of 20.5 MHz.  The DUART is initialized to 9600 baud (also see
;       conditional assembly symbols) and the terminal is assumed to
;       be attached to serial port A.  A host computer is assumed to be
;       attached to serial port B although provisions are made for 
;       single serial control (such as an IBM-PC).  Powerup options are
;       provided to allow the on-chip serial communications interface
;       (SCI) to be used as the default communications port.
;       
;
;       DSPBUG assumes one of three different methods of powering up:
;       1. Booting from two 8Kx8 EPROMS located at P:C000 and transferring
;          DSPBUG to RAM at P:E000.  The formatted EPROMS are generated
;          by the FORTRAN program BOOTGEN.  Note that the formatting
;          program is required because 8K is not evenly divisible by 3
;          and the DSPBUG program must boot from a low and then a middle
;          EPROM.  The output of the program is two files:
;               DSPBUG.LOW - S19 Motorola hex file of the P:C000 low byte
;               DSPBUG.MID - S19 Motorola hex file of the P:C000 mid byte
;          The high byte specifies specific powerup options (see below).
;          The following describes how to generate the EPROMS:
;          $ asm56000 -l -b -a dspbug
;          $ run bootgen
;               input file:dspbug.mod
;          This is the most typical mode of DSPBUG operation.
;
;       2. Running directly from three 8Kx8 EPROMs located at P:E000 and
;          using internal memory at P:40 for scratch pad.
;          This may be used if no external high speed RAM is available.
;          However, DSPBUG uses internal P memory and there may not be
;          enough P memory left for program development.  This is not
;          a preferred method of using DSPBUG. Using this method, DSPBUG may
;          be formatted with the utility SREC as follows:
;          $ asm56000 -l -b -a dspbug
;          $ srec -3 dspbug
;          The output is in Motorola S record format in the files
;          DSPBUG.P0, DSPBUG.P1, DSPBUG.P2.
;          This method of DSPBUG is not very useful.
;           
;       3. Booting from a single 32Kx8 EPROM located at P:8000 and
;          transferring to RAM at P:0800.  Using this method, DSPBUG may
;          be formatted with the utility SREC as follows:
;          $ asm56000 -l -b -a dspbug
;          $ srec dspbug
;          The output is in Motorola S record format in the file DSPBUG.P and
;          is programmed by downloading into an EPROM programmer with an
;          offset of zero. The special powerup options are specified in the
;          high byte at P:FFFF (see below). The EPROM resides in the
;          low byte of P:8000.
;          This method is useful when only 1 external part is available for
;          booting.
;
;
        PAGE
;       The upper byte is used for special powerup options
;       although the monitor may be modified to make these options
;       permanent.  If booting method 1 or 3 is used, the options may
;       be programmed with 15K resistors to the data lines or the options
;       may be programmed into the first byte of an EPROM and plugged 
;       into the high byte of P:$C000.  If booting method 2 is used, the
;       options are specified at location P:FFFF of the high EPROM.
;   
;   D23     D22     D21     D20     D19     D18     D17     D16          
;   Boot    Special OPT1    OPT2    <-   Multiboard address  ->
;                                        or SCI Baud Rate
;   
;   0        X       X       X      Boot from the host interface
;   1        1       X       X      Boot from the external EPROM
;                                   (Normal operation for DSPBUG)
;        DSPBUG Special Operating Modes (D22=0)                            
;   1        0       0       0      Multiboard, CMD level powerup
;   1        0       0       1      Multiboard, inactive powerup
;   1        0       1       0      SCI interface for terminal port
;   1        0       1       1      Host Interface for terminal port
;
;
;        D19 D18 D17 D16  Baud rate if powering up on the SCI
;         0   0   0   0     300        20.48 Mhz Crystal
;         0   0   0   1    1200
;         0   0   1   0    2400
;         0   0   1   1    4800
;         0   1   0   0    9600
;         0   1   0   1   19200
;         0   1   1   0   38400
;         0   1   1   1   76800
;
;       The multiboard powerup option allows several prototypes to     
;       be connected in parallel to a single serial port via a 
;       special serial cable with a few diodes.  This mode assumes that 
;       the RS-232 signals are wire-ORed on the serial transmit from
;       the DSP boards on both the terminal and host computer serial ports.
;       At powerup of each DSP board, the address of the board is provided,
;       and whether the board should powerup at the command level or remain
;       inactive.  If the board is inactive, the board may be activated
;       and brought to the command level by sending a CONTROL/W followed
;       by the ASCII character number of the board.  For example, the
;       sequence "CONTROL/W" followed by "0" will activate the DSP board
;       with address zero.  The board may be put in the inactive state
;       by using the OFF command when in the multiboard mode.
;
        PAGE
;   Command Overview:
;   
;   Execution Control:
;   GO [ADDR]                     Begin execution
;   JSR [ADDR]                    Call a subroutine
;   GOB [BREAKPOINT]              Set temporary breakpoint and 
;                                 begin execution at current PC
;   
;   Debugging:
;   BRK <[S,R,-,<CR>]>            Breakpoints
;   NBR [NUMBER OF BREAKPOINTS]   Number of breakpoints to execute
;                                 before stopping
;   TRA [N INSTRUCTIONS]          Trace
;   
;   Program/Data Transfers:
;   DHE                           Define host exit character
;   HST                           Enter transparent communications
;   LOA                           Load OMF records 
;   UPL <[P,X,Y]>:<ADD1> <ADD2> <[O,D]>
;                                 Upload memory to the host
;   VER                           Verify OMF records
;   
;   Device Configuration:
;   BDA [BAUD RATE]               Change the baud rate for DUART-A
;   BDB [BAUD RATE]               Change the baud rate for DUART-B
;   BDS [BAUD RATE]               Change the baud rate for the SCI
;   DHP [DEVICE]                  Define host port device
;   DTP [DEVICE]                  Define terminal port device
;   INI [DEVICE]                  Initialize device
;   
;   Display:
;   DIS                           Display registers
;   DMP <[P,X,Y]>:<ADD1> [ADD2]   Dump memory
;   DST                           Display Stack
;   DVD                           Device display
;   FND <[P,X,Y]>:<ADD1> <ADD2> <VALUE> [MASK]
;                                 Find value in memory
;   RD  <[P,X,Y]>:<ADDR>          Read memory location
;   
;   Modify:
;   COP <[P,X,Y]>:<ADD1> <ADD2> <[P,X,Y]>:<ADDR>
;                                 Copy memory
;   FIL <[P,X,Y]>:<ADD1> <ADD2> [VALUE]
;                                 Fill memory
;   MEM <[P,X,Y]>:<ADDR>          Memory examine/modify           
;   REG                           Register examine/modify
;   STK                           Stack examine/modify
;   WRT <[P,X,Y]>:<ADDR> <VALUE> [REPEAT]
;                                 Write without verify
;   
;   Miscellaneous:
;   EVA <ARG1> <[+,-,*,/]> <ARG2> Evaluate expression
;   HEL                           Help
;   
;       FOR ADDITIONAL INFORMATION, CONSULT THE "DSPBUG USER'S MANUAL"
;

;
;       CONDITIONAL ASSEMBLY EQUATES TO CONTROL ASSEMBLY OPTIONS
;

BOOTMODE        EQU     1       ;BOOT MODE
;
;       OTHER EQUATES FOR HANDLING INVALID NUMBERS, INCLUDING/EXCLUDING
;       THE EXECUTION TIMER, ALTERNATE BAUD RATE.
;
HEXERR  EQU     1               ;SET TO 0 = IF HEX ERROR GO TO DSPBUG
                                ;       1 = IGNORE INVALID HEX CHARACTERS
EXETMR  EQU     1               ;SET TO 0 = DO NOT USE DUART TIMER
                                ;       1 = USE DUART TIMER FOR EXECUTION TIMER
ALTBAUD EQU     0               ;SET TO 0 = DEFAULT BAUD RATE PWR UP 9600
                                ;       1 = ALTERNATE BAUD RATE 19200


        IF      BOOTMODE==1
        MSG     '*** BOOT FROM 2 8Kx8 EPROMS AT P:C000 AND ***'
        MSG     '*** TRANSFER TO RAM AT P:E000             ***'
MROM    EQU     $E000           ;IF BOOTING FROM 2 8Kx8 EPROMS
        ORG     P:MROM          ;LOAD AT E000
        ENDIF

        IF      BOOTMODE==2
        MSG     '*** SETUP FOR THREE EXTERNAL EPROMS AT P:E000 ***'
MROM    EQU     $E000           ;IF EXTERNAL EPROMS
        ORG     P:MROM          ;LOAD AT E000
        ENDIF                                                                  

        IF      BOOTMODE==3
        MSG     '** BOOT FROM A 32Kx8 EPROM AT P:8000 AND TRANSFER **'
        MSG     '** TO RAM AT P:0800                               **'
MROM    EQU     $0800           ;IF BOOTING FROM 32Kx8 EPROM
        ORG     P:MROM,P:0      ;LOAD AT MROM, PUT AT 0 FOR 'SREC'
        ENDIF




        IF      HEXERR                 
        MSG     '*** IGNORE INVALID HEX CHARACTERS ***'
        ELSE     
        MSG     '*** ERROR ON INVALID HEX CHARACTERS ***'
        ENDIF

        IF      EXETMR
        MSG     '*** DUART TIMER IS USED FOR EXECUTION TIMING ***'
        ELSE
        MSG     '*** DUART TIMER IS NOT USED ***'
        ENDIF

        IF      ALTBAUD
        MSG     '*** DEFAULT BAUD RATE 19200 BAUD'
        ELSE
        MSG     '*** DEFAULT BAUD RATE 9600 BAUD'
        ENDIF

        PAGE

IPR     EQU     $FFFF           ;INTERRUPT PRIORITY REGISTER
BCR     EQU     $FFFE           ;BUS CONTROL REGISTER
PBC     EQU     $FFE0           ;PORT B CONTROL REGISTER
PCC     EQU     $FFE1           ;PORT C CONTROL REGISTER
HRDF    EQU     $0              ;HOST RECEIVE DATA FULL BIT
HTDE    EQU     $1              ;HOST TRANSMIT DATA EMPTY
HSR     EQU     $FFE9           ;HOST STATUS REGISTER
HTX     EQU     $FFEB           ;HOST TRANSMIT REGISTER
HRX     EQU     $FFEB           ;HOST RECEIVE REGISTER
SCR     EQU     $FFF0           ;SCI CONTROL REGISTER
SCCR    EQU     $FFF2           ;SCI CLOCK CONTROL REGISTER
SSR     EQU     $FFF1           ;SCI STATUS REGISTER
STXL    EQU     $FFF4           ;SCI TX LOW
SRXL    EQU     $FFF4           ;SCI RX LOW
TDRE    EQU     1               ;TRANSMIT DATA REGISTER EMPTY FLAG
RDRF    EQU     2               ;RECEIVE DATA REGISTER FULL FLAG

PROMPT  EQU     '>'             ;PROMPT CHARACTER

DSP_BCR EQU     $FFFF           ;BCR FOR MONITOR
DUART   EQU     $FFC0           ;LOCATION OF DUART
DUARTA  EQU     DUART           ;DUARTA IS FIRST 8 LOCATIONS
DUARTB  EQU     DUART+8         ;DUARTB IS NEXT 8 LOCATIONS
CTUR    EQU     DUART+6         ;COUNTER UPPER REGISTER
CTLR    EQU     DUART+7         ;COUNTER LOWER REGISTER
START_CTR       EQU     DUART+14        ;START ADDRESS OF COUNTER
STOP_CTR        EQU     DUART+15        ;STOP ADDRESS OF COUNTER
ISR     EQU     DUART+5         ;DUART INTERRUPT STATUS REGISTER
NUMBRK  EQU     10              ;NUMBER OF BREAKPOINTS
STAR    EQU     $2A
DASH    EQU     $2D
QMARK   EQU     $3F
COLON   EQU     $3A
SPACE   EQU     $20
EQUAL   EQU     $3D
CR      EQU     13
LF      EQU     10
DEL     EQU     $7F
REGSTART        EQU     34      ;STARTING REGISTER FOR 'REG' COMMAND

CTRLC   EQU     03
CTRLQ   EQU     17
CTRLR   EQU     18
CTRLS   EQU     19
CTRLW   EQU     23
CTRLY   EQU     25
CTRLZ   EQU     26
                  
OP_JSR  EQU     $0BF080         ;OPCODE FOR "JSR"
OP_SWI  EQU     $000006         ;OPCODE FOR "SWI"
OP_JMP  EQU     $0AF080         ;OPCODE FOR "JMP"

        PAGE

SAVE_USER       MACRO           ;MACRO TO SAVE THE USER'S CONTEXT
        MOVE    R0,P:USR_R0     ;SAVE USER R0
        MOVE    R1,P:USR_R1     ;SAVE USER R1
        MOVE    SSL,R0                  ;GET USER SR FROM INTERRUPT
        MOVE    SSH,R1                  ;GET USER PC FROM INTERRUPT
        JSR     SAVE_CONTEXT            ;SAVE THE USER'S CONTEXT
        ENDM
                  


PRTVAL  MACRO   VAL             ;SINGLE CHARACTER OUTPUT ROUTINE
        MOVE    #<VAL,A         ;LOAD CHARACTER TO OUTPUT
        JSR     OUT2            ;OUTPUT CHARACTER
        ENDM


        PAGE
;
;       User utility table.  This table provides access to the
;       monitor's utility routines that the user may want to use.
;
        JMP     DSPBUG          ;MONITOR COLD RESET
        JMP     CMD             ;MONITOR WARM START
        JMP     SET_TERM        ;SET TERMINAL AS I/O DEVICE
        JMP     SET_HOST        ;SET HOST AS I/O DEVICE
        JMP     DEFINE_TERM     ;SET TERMINAL WITH DEV IN B AND INIT DEV
        JMP     DEFINE_HOST     ;SET HOST WITH DEV IN B AND INIT DEV
        JMP     IN0X            ;SCAN INPUT DEVICE
        JMP     IN1X            ;8 BIT DATA INPUT TO A1 (LOWER BYTE)
        JMP     IN2X            ;INPUT CH, MASK PARITY, TOP BYTE OF A1
        JMP     IN3X            ;IN3 + ECHO CHARACTER
        JMP     INBYTEX         ;INPUT A 2 NIBBLE BYTE
        JMP     INADDX          ;INPUT A 4 NIBBLE ADDRESS INTO B1
        JMP     INDATX          ;INPUT A 6 NIBBLE DATA VALUE INTO B1
        JMP     INBYTE_NLSX     ;INPUT A 2 NIBBLE BYTE
        JMP     INADD_NLSX      ;INPUT A 4 NIBBLE ADDRESS INTO B1
        JMP     INDAT_NLSX      ;INPUT A 6 NIBBLE DATA VALUE INTO B1
        JMP     OUT0X           ;8 BIT OUTPUT FROM A1 (LOWER BYTE) NO CTRL/S/Q
        JMP     OUT1X           ;8 BIT DATA OUTPUT FROM A1 (LOWER BYTE)
        JMP     OUT2X           ;MASK PARITY, OUTPUT CH FROM TOP BYTE OF A1
        JMP     OUT3X           ;OUTPUT 3 PACKED CHARACTERS IN A1
        JMP     OUT4X           ;OUTPUT N0 PACKED CHARS POINTED TO BY R0
        JMP     OUT5X           ;OUTPUT CHARS POINTED TO BY R0 ENDING WITH 0
        JMP     OUTBYTEX        ;OUTPUT 2 NIBBLE BYTE FROM B1 IN HEX
        JMP     OUTADDX         ;OUTPUT A ADDRESS FROM B1 IN HEX
        JMP     OUTDATX         ;OUTPUT A DATA VALUE FROM B1 IN HEX
        JMP     OUTINTX         ;OUTPUT 16 BITS FROM B1 AS DECIMAL INTEGER
        JMP     ADDCMDX         ;ADD COMMAND TO COMMAND TABLE
        JMP     CRLFX           ;OUTPUT <CR><LF>
        JMP     PRTSPCX         ;OUTPUT A SPACE
        JMP     UP_DATA         ;UPLOAD IN DATA FORMAT
        JMP     UP_OMF          ;UPLOAD IN OMF RECORDS
        JMP     OUTFRACX        ;OUTPUT B AS A FRACTION
        JMP     ININTX          ;INPUT 6 DIGITS AS DECIMAL INTEGER
        DC      $427920         ;END OF JUMP          
        DC      $422E4C         ;TABLE
        DC      $2E4C2E         ;SEQUENCE STRING

;
;       USER CONTEXT SAVE/RESTORE FOR UTILITY SUBROUTINES
;

IN0X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     IN0             ;SCAN INPUT DEVICE                        
        MOVE    SR,B            ;GET SR
        REP     #16             ;SHIFT OFF MR, KEEP CCR
        LSL     B
        REP     #16             ;SHIFT BACK
        LSR     B
        MOVE    B1,X0           ;KEEP NEW CCR
        MOVE    P:USR_SR,B      ;GET OLD MR,CCR
        REP     #8              ;SHIFT OFF OLD CCR, KEEP MR
        LSR     B
        REP     #8              ;SHIFT BACK
        LSL     B
        OR      X0,B            ;MERGE NEW CCR WITH OLD MR
        MOVE    B1,P:USR_SR     ;SAVE AS NEW SR
IN0XC                
        MOVE    A2,P:USR_A2     ;SAVE A
        MOVE    A1,P:USR_A1
        MOVE    A0,P:USR_A0
        JMP     RESTORE_USER            ;RESTORE REGISTERS
IN1X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     IN1
        JMP     IN0XC
IN2X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     IN2
        JMP     IN0XC
IN3X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     IN3
        JMP     IN0XC
INBYTEX
        SAVE_USER      
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     INBYTE
        JMP     INXC
INADDX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     INADD
        JMP     INXC
INDATX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     INDAT
        JMP     INXC
INBYTE_NLSX
        SAVE_USER      
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     INBYTE_NLS
        JMP     INXC
INADD_NLSX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     INADD_NLS
        JMP     INXC
INDAT_NLSX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     INDAT_NLS
        JMP     INXC
INXC
        MOVE    A2,P:USR_A2
        MOVE    A1,P:USR_A1     ;SAVE DELIMITER
        MOVE    A0,P:USR_A0
        MOVE    B2,P:USR_B2
        MOVE    B1,P:USR_B1     ;SAVE VALUE
        MOVE    B0,P:USR_B0
        MOVE    R7,P:USR_R7     ;SAVE CHARACTER COUNT
        JMP     RESTORE_USER
OUT0X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_A1,A
        JSR     OUT0
        JMP     RESTORE_USER
OUT1X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_A1,A
        JSR     OUT1
        JMP     RESTORE_USER
OUT2X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_A1,A
        JSR     OUT2
        JMP     RESTORE_USER
OUT3X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_A1,A
        JSR     OUT3
        JMP     RESTORE_USER
OUT4X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_R0,R0
        MOVE    P:USR_N0,N0
        JSR     OUT4
        MOVE    R0,P:USR_R0
        JMP     RESTORE_USER
OUT5X
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_R0,R0
        JSR     OUT5
        MOVE    R0,P:USR_R0
        JMP     RESTORE_USER
                      
OUTBYTEX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_B1,B      ;GET VALUE TO OUTPUT
        JSR     OUTBYTE
        JMP     RESTORE_USER
OUTADDX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_B1,B      ;GET VALUE TO OUTPUT
        JSR     OUTADD
        JMP     RESTORE_USER
OUTDATX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_B1,B      ;GET VALUE TO OUTPUT
        JSR     OUTDAT
        JMP     RESTORE_USER
OUTINTX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_B1,B      ;GET VALUE TO OUTPUT
        JSR     OUTINT
        JMP     RESTORE_USER
OUTFRACX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_B1,B      ;GET VALUE TO CONVERT
        JSR     OUTFRAC                 ;CONVERT IT
        JMP     RESTORE_USER                    ;RESTORE REGISTERS,STACK AND RETURN
ADDCMDX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_A1,A
        MOVE    P:USR_R7,R7
        MOVE    P:USR_M7,M7
        JSR     ADDCMD
        JMP     RESTORE_USER
CRLFX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     CRLF
        JMP     RESTORE_USER
PRTSPCX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     PRTSPC
        JMP     RESTORE_USER
UP_DATAX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_X0,X0
        MOVE    P:USR_R2,R2
        MOVE    P:USR_N2,N2
        JSR     UP_DATA
        JMP     RESTORE_USER
UP_OMFX
        SAVE_USER
        JSR     SET_USER        ;SET USER I/O DEVICE
        MOVE    P:USR_X0,X0
        MOVE    P:USR_R2,R2
        MOVE    P:USR_N2,N2
        JSR     UP_OMF
        JMP     RESTORE_USER

ININTX
        SAVE_USER               ;SAVE USER CONTEXT
        JSR     SET_USER        ;SET USER I/O DEVICE
        JSR     ININT           ;INPUT AS INTEGER
        JMP     INXC            ;SAVE DATA

        PAGE
;
;       DSPBUG STARTUP.  SET BCR AND STACK EXCEPTION VECTOR.
;
DSPBUG
        MOVEP   #$FFFF,X:BCR    ;SET UP BCR FOR MAX WAIT STATES
        MOVEC   #$0300,SR       ;NO SCALING, SET IPL TO 3
        MOVE    #OP_JMP,A       ;GET OPCODE FOR JMP
        MOVE    A,P:$0002       ;SET IN STACK EXCEPTION VECTOR
        MOVE    #STKERR,A       ;GET ADDRESS FOR STACK ERROR VECTOR
        MOVE    A,P:$0003       ;SAVE IN STACK EXCEPTION LOCATION
        MOVE    #0,SP           ;CLEAR THE STACK
;
;       SET NUMBER OF BREAKPOINTS TO HIT BEFORE STOPPING AS
;       DEFAULT OF 1
;
        MOVE    #>1,X0          ;GET A 1
        MOVE    X0,P:NBRVAL     ;SAVE DEFAULT
;
;       SET TERMINAL DEVICE
;
        IF      BOOTMODE==2                
        MOVE    #$FFFF,R0       ;POINT TO $FFFF
        ELSE
        MOVE    #$C000,R0       ;POINT TO $C000
        ENDIF
        MOVE    #65535,X0       ;GET A LARGE NUMBER
        REP     X0              ;READ A LOT TO ALLOW RESISTORS TO SETTLE
        MOVE    P:(R0),A        ;GET DATA AT LOCATION P:$C000
        MOVE    A,P:MDSTAT      ;SAVE SPECIAL OPERATION STATUS
        MOVE    #$400000,X0     ;MASK FOR D22
        AND     X0,A    #>1,B   ;SEE IF SPECIAL MODE (D22=0), GET 1
        JNE     _DEVSET         ;IF D22=1, NOT SPECIAL, SET DUART A
        MOVE    P:MDSTAT,A      ;GET DATA
        MOVE    #$200000,X0     ;MASK FOR D21 (SEE IF MULTIBOARD)
        AND     X0,A    #$100000,X0     ;MASK, GET MASK FOR D20
        JEQ     _DEVSET         ;USE DUART A IN MULTIBOARD
        MOVE    P:MDSTAT,A      ;GET DATA
        AND     X0,A    #>3,B   ;MASK D20, SET SCI IN B
        MOVE    #>4,X0          ;GET CODE FOR VME INTERFACE
        TNE     X0,B            ;IF D20=1, THEN SET VME, ELSE SCI
_DEVSET
        MOVE    B,P:IODEV       ;SET I/O DEVICE
        MOVE    B,P:TDEV        ;SET AS CURRENT TERMINAL DEVICE
        MOVE    B,P:USR_DEV     ;SET AS CURRENT USER DEVICE
        JSR     DEFINE_TERM     ;INITIALIZE DEVICE
;
;       DETERMINE MULTIBOARD ADDRESS
;
        MOVE    P:MDSTAT,A              ;GET POWERUP STATUS OF P:$C000
        REP     #16                     ;SHIFT DOWN ADDRESS OF BOARD
        ASR     A
        MOVE    #>$F,X0                 ;MASK FOR 4 BITS
        AND     X0,A                    ;KEEP ONLY 4 BITS
        MOVE    A1,P:MDADD              ;SAVE AS MULTIBOARD ADDRESS
;
;       SET UP DEFAULT VALUES FOR USER REGISTERS, SET LINEAR ADDRESSING
;
        MOVE    #MROM,SSH       ;INITIAL PC, START OF MONITOR
        MOVE    SR,SSL          ;INITIAL STATUS REGISTER FOR USER
        SAVE_USER               ;SAVE POWERUP MODE AS THE USER'S CONTEXT
        JSR     COP_REG         ;COPY NEW REGISTERS TO OLD ONES
;
;       SET THE SCI BAUD RATE DEPENDING ON BITS D19-D16 ON POWERUP.
;       IF THE SCI IS LATER INITIALIZED, IT WILL BE SET TO 9600 BAUD.
;
        MOVE    #SCIBAUD,N0     ;POINT TO SCI BAUD RATE TABLE
        MOVE    P:MDADD,R0      ;GET BITS D19-D16
        NOP                     ;CLEAR PIPE
        MOVEP   P:(R0+N0),X:SCCR        ;SET SCI BAUD RATE
;
;       SET HOST DEVICE TO DUART B
;
        MOVE    #>2,X0          ;2=DUARTB
        MOVE    X0,P:HDEV       ;SET HOST DEVICE
        MOVE    #>$01,X0        ;DEFAULT HOST EXIT CHARACTER =CTRL/A
        MOVE    X0,P:HST_EXIT   ;SAVE DEFAULT EXIT CHARACTER
;
;       INITIALIZE DUARTS
;
        MOVE    #DUART,R0       ;POINT TO DUART
        MOVE    #DRTTBL,R1      ;POINT TO VALUES FOR CONTROL REGISTERS
        DO      #DTBLLEN,_L1    ;NUMBER OF VALUES TO STORE
        MOVE    P:(R1)+,N0      ;GET OFFSET FOR CONTROL REGISTER
        MOVE    P:(R1)+,A1      ;GET VALUE FOR CONTROL REGISTER
        MOVE    A1,Y:(R0+N0)    ;SET CONTROL REGISTER
_L1
;
;       SET NOPS FOR THE NMI VECTOR
;                  
        CLR     A               ;NOP=000000
        MOVE    A,P:$001E
        MOVE    A,P:$001F
;
;       CLEAR BREAKPOINT TABLE
;
        CLR     A     #BPLOC,R0 ;SET A TO ZERO, POINT TO BREAKPOINT TABLE
        REP     #NUMBRK         ;DO NUMBER OF BREAKPOINTS
        MOVE    A,P:(R0)+       ;CLEAR TABLE
;
;       CLEAR THE TEMPORARY BREAKPOINT (FOR GOB COMMAND)
;
        MOVE    A,P:TEMPBP      ;CLEAR IT
;                      
;       PRINT RESET MESSAGE UNLESS WE ARE IN MULTIBOARD AND POWERING UP
;       IN THE 'OFF' CONDITION
;
        JSR     CKMBRD          ;SEE IF IN MULTIBOARD
        JNE     RSTMSG          ;NO, NOT MULTIBOARD
        MOVE    P:MDSTAT,A      ;GET UPPER BYTE OF BOOT AREA
        MOVE    #>$100000,X0    ;MASK FOR D20
        AND     X0,A            ;SEE IF D20 IS SET
        JNE     MDOFF           ;YES, EXECUTE OFF COMMAND
RSTMSG
        MOVE    #INIMSG,R0      ;POINT TO MESSAGE
        JSR     OUT5            ;OUTPUT MSG
        MOVE    #RAMEND,B       ;GET END OF MONITOR SPACE
        JSR     OUTADD          ;TELL USER
;
;       COMMAND ENTRY POINT
;     
CMD
        MOVE    #0,SP           ;CLEAR SP IF USER HAS IT SCREWED UP
        MOVE    #$FFFF,M0       ;SET ALL ADDRESS REGISTERS FOR LINEAR
        MOVE    M0,M1
        MOVE    M0,M2
        MOVE    M0,M3                               
        MOVE    M0,M4                                   
        MOVE    M0,M5
        MOVE    M0,M6
        MOVE    M0,M7
        MOVE    #CMDMSG,R0      ;PRINT CR,LF,PROMPT
        JSR     OUT5
        JSR     CKMBRD          ;CHECK IF MULTIBOARD
        JNE     _NOMD           ;NOT MULTIBOARD
        MOVE    P:MDADD,B       ;GET ADDRESS OF THE BOARD FROM DUART INPUT PORT
        JSR     OUTBYTE         ;OUTPUT IT
_NOMD
        PRTVAL  PROMPT          ;OUTPUT PROMPT
        CLR     B       #0,R7   ;CLEAR INPUT STRING, CHARACTER COUNT
_READCHR
        JSR     IN2UC           ;GET INPUT CHARACTER, CONVERT TO UPPER CASE
        MOVE    A,Y0            ;SAVE INPUT CHARACTER
        MOVE    #'.',X0         ;GET POINT
        CMP     X0,A    #CTRLS,X0       ;SEE IF QUICK TRACE
        JEQ     QTRACE          ;YES
        CMP     X0,A    #CTRLQ,X0       ;SEE IF CTRLS
        JEQ     _READCHR        ;YES, IGNORE IT
        CMP     X0,A    #DEL,X0 ;SEE IF CTRLQ
        JEQ     _READCHR        ;YES, IGNORE IT
        CMP     X0,A    #CR,X0  ;SEE IF DEL
        JEQ     _DEL            ;YES
        CMP     X0,A    #SPACE,X0       ;SEE IF CR
        JEQ     _DLM            ;YES, DELIMITER
        CMP     X0,A    #'A',X0 ;SEE IF SPACE
        JEQ     _DLM            ;YES, DELIMITER
        CMP     X0,A    #'Z',X0 ;SEE IF LESS THAN A
        JLT     CMD             ;YES
        CMP     X0,A            ;SEE IF GREATER THAN Z
        JGT     CMD             ;YES
        JSR     OUT2            ;ECHO
        MOVE    Y0,A            ;RESTORE INPUT CHARACTER
        DO      #8,_MOVEIT      ;PACK INTO B
        LSL     A               ;SHIFT OUT OF A
        ROL     B               ;SHIFT INTO B
_MOVEIT
        MOVE    (R7)+           ;INCREMENT CHARACTER COUNT
        MOVE    #>3,A           ;GET 3 (MAX NUMBER OF INPUT CHRS)
        MOVE    R7,X0           ;GET CHARACTER COUNT
        CMP     X0,A            ;SEE IF 3 CHARACTERS YET
        JNE     _READCHR        ;NO, GO GET MORE
_FULL
        JSR     IN2             ;READ A NEW CHARACTER
        MOVE    A,Y0            ;SAVE INPUT IN Y0 FOR LATER
        MOVE    #DEL,X0         ;GET DELETE CHARACTER
        CMP     X0,A    #CR,X0  ;SEE IF DELETE
        JEQ     _DEL            ;YES, DELETE LAST CHARACTER
        CMP     X0,A    #SPACE,X0       ;SEE IF CR
        JEQ     _DLM            ;YES, DELIMITER
        CMP     X0,A            ;SEE IF SPACE
        JEQ     _DLM            ;YES, DELIMITER
        JMP     _FULL           ;GET ANOTHER CHARACTER
_DEL
        MOVE    R7,A            ;GET CHARACTER COUNT
        TST     A               ;SEE IF NO CHARACTERS
        JEQ     CMD             ;NO CHARACTERS
        MOVE    (R7)-           ;DECREMENT CHARACTER COUNT
        REP     #8              ;REMOVE LAST CHARACTER
        LSR     B               ;SHIFT IT OUT
        MOVE    #$082008,A      ;LOAD BS,SP,BS
        JSR     OUT3            ;REMOVE LAST CHARACTER ON SCREEN
        JMP     _READCHR        ;READ A NEW CHARACTER
_DLM
        MOVE    #PADTBL,N7      ;AMOUNT TO SHIFT
        JSR     PRTSPC          ;PRINT DELIMITER SPACE
        MOVE    P:(R7+N7),A1    ;GET ADJUSTMENT COUNT
        REP     A1              ;SHIFT CHARACTERS IF NEEDED
        ROL     B               ;DO IT
        MOVE    #MSKTBL,N7      ;POINT TO COMMAND MASK TABLE
        MOVE    #CMDTBL,R0      ;POINT TO COMMAND TABLE
        MOVE    P:(R7+N7),X0    ;GET MASK
        DO      #CMDTBLLEN,_ESRCH       ;SEAR COMMAND TABLE
        MOVE    P:(R0)+,A       ;GET THE COMMAND TEXT
        MOVE    P:(R0)+,R1      ;GET COMMAND ADDRESS
        AND     X0,A    (R0)+   ;KEEP ONLY THE LENGTH OF INPUT STRING,SKP
        CMP     A,B             ;SEE IF COMMAND MATCHES
        JNE     _NOMCH          ;NO
        ENDDO                   ;YES, CLEAN UP LOOP
        MOVE    #CR,A           ;GET CODE FOR <CR>
        CMP     Y0,A            ;SET Z FLAG IN SR IF DELIMITER WAS <CR>
        JMP     (R1)            ;AND EXECUTE COMMAND
_NOMCH
        NOP                     ;END LOOP
_ESRCH
        MOVE    #BADCMD,R0      ;GIVE CMD NOT FOUND MSG
        JSR     OUT5            ;OUTPUT MSG
        JMP     CMD             ;GO TO COMMAND LEVEL

        PAGE
;
;       MEMORY COMMAND
;
;       MEM <[X,Y,P]>:<ADDR>
;       SUBCOMMANDS (AFTER DATA IS PRINTED):
;               <CR>    NEXT LOCATION
;               <SP>    DEPOSIT VALUE
;               ^       PREVIOUS LOCATION
;               CTRL/Y  EXIT
;
MEM
        JSR     GETPXY          ;GET MEMORY SPACE AND ADDRESS
        MOVE    B1,R2           ;PUT ADDRESS IN ADDRESS REGISTER
_DMEM
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:MEMT,A1       ;GET MEMORY TYPE
        JSR     OUT2            ;PRINT IT
        PRTVAL  COLON           ;OUTPUT COLON
        MOVE    R2,B            ;COPY CURRENT MEMORY POINTER
        JSR     OUTADD          ;OUTPUT ADDRESS
        JSR     GETMEM          ;GET THE MEMORY INTO B
        MOVE    (R2)-           ;POINT MEMORY POINTER BACK TO CURRENT LOCATION
        JSR     OUTFRAC         ;OUTPUT AS FRACTION
        JSR     PRTSPC          ;OUTPUT SPACE
        MOVE    Y1,B            ;RESTORE NUMBER
        JSR     OUTDAT          ;OUTPUT THE DATA
_OPT
        JSR     IN2             ;GET OPTION
        MOVE    #CR,X1          ;LOAD <CR>
        CMP     X1,A    #'^',X1 ;SEE IF <CR>
        JEQ     _NEXT           ;YES, NEXT
        CMP     X1,A    #CTRLY,X1       ;SEE IF "^"
        JEQ     _UP             ;YES, GO DO PREVIOUS
        CMP     X1,A    #SPACE,X1       ;SEE IF CTRLY
        JEQ     CMD             ;EXIT
        CMP     X1,A    #CTRLC,X1       ;SEE IF SPACE
        JEQ     _CHANGE         ;YES, CHANGE IT
        CMP     X1,A            ;SEE IF CTRLC
        JEQ     CMD             ;EXIT
        MOVE    #OPTMSG,R0      ;GET OPTION ERROR MESSAGE
        JSR     OUT5
        JMP     _DMEM           ;REDISPLAY MEMORY
;                       
;       CHANGE VALUE     
;                                              
_CHANGE
        MOVE    #'  >',A        ;PROMPT
        JSR     OUT3            ;OUTPUT IT
        JSR     INDAT           ;GET NEW DATA
        MOVE    A,Y1            ;SAVE DELIMITER
        MOVE    R7,A            ;GET NIBBLE COUNT
        TST     A               ;SEE IF NO INPUT
        JEQ     _DMEM           ;YES, DO NOT CHANGE
        JSR     SETMEM          ;SET THE MEMORY
        MOVE    #'^',A          ;GET UP ARROW
        CMP     Y1,A            ;SEE IF DELIMITER IS ^
        JEQ     _PREV           ;YES
        JMP     _DMEM           ;GO TO NEXT LOCATION
_PREV
        MOVE    (R2)-           ;GO TO PREVIOUS
;
;       "^"     DISPLAY PREVIOUS LOCATION
;
_UP
        MOVE    (R2)-           ;DEC MEMORY POINTER     
        JMP     _DMEM           ;DISPLAY MEMORY
;
;       DISPLAY NEXT LOCATION AND DATA
;
_NEXT
        MOVE    (R2)+           ;POINT TO NEXT LOCATION
        JMP     _DMEM           ;DISPLAY MEMORY
        PAGE
;
;       BREAKPOINT SETTING/CLEARING/DISPLAY
;
;       BRK <CR>                DISPLAY BREAKPOINTS
;       BRK S AAAA<CR>  SET BREAKPOINT AT LOCATION AAAA
;       BRK R AAAA<CR>  REMOVE BREAKPOINT FROM LOCATION AAAA
;       BRK -           REMOVE ALL BREAKPOINTS
;
BREAK
        JEQ     _CR             ;IF DELIMITER WAS CR, DISPLAY TABLE
        JSR     IN3UC           ;GET  S, R OR -
        MOVE    #'S',X1         ;GET S
        CMP     X1,A    #'R',X1 ;SEE IF S
        JEQ     _S              ;YES
        CMP     X1,A    #'-',X1 ;SEE IF R
        JEQ     _R              ;YES
        CMP     X1,A    #CR,X1  ;SEE IF -
        JEQ     _DASH           ;YES
        CMP     X1,A            ;SEE IF <CR>
        JEQ     _CR             ;YES
        MOVE    #BRKOPTMSG,R0   ;GET BREAKPOINT OPTION MESSAGE
        JSR     OUT5            ;PRINT IT
        JMP     CMD
;
;       <CR>    DISPLAY ALL BREAKPOINTS
;          
_CR
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    #BPLOC,R0       ;POINT TO LOCATION TABLE
        DO      #NUMBRK,_CR1    ;DO ALL ENTRIES
        MOVE    P:(R0)+,B       ;GET BREAKPOINT ADDRESS
        JSR     OUTADD          ;OUTPUT ADDRESS
        JSR     PRTSPC          ;PRINT SPACE
_CR1
        JMP     CMD             ;GO TO COMMAND LEVEL
;
;       S       SET A NEW BREAKPOINT
;
_S
        JSR     PRTSPC          ;PRINT SPACE
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT LOCATION TABLE
        DO      #NUMBRK,_S0     ;SEARCH FOR A 0 IN THE TABLE
        MOVE    P:(R0),A        ;GET THE LOCATION
        TST     A               ;SET FLAGS
        JNE     _S1             ;NOT ZERO
        ENDDO                   ;IT IS ZERO, EXIT LOOP
        JMP     _S2
_S1
        MOVE    (R0)+           ;POINT TO NEXT LOCATION
_S0
        MOVE    #BPTBLFUL,R0    ;TABLE FULL MESSAGE
        JSR     OUT5            ;PRINT IT OUT
        JMP     CMD
_S2
        PRTVAL  $3E             ;AVAILABLE SPACE, GIVE PROMPT
        JSR     INADD           ;GET THE NEW ADDRESS
;
;       SEE IF ALREADY IN TABLE.  IF IT IS, IGNORE NEW SET COMMAND
;
        MOVE    #BPLOC,R1       ;POINT TO BREAKPOINT TABLE
        DO      #NUMBRK,_S5     ;SCAN TABLE
        MOVE    P:(R1)+,X0      ;GET BREAKPOINT
        CMP     X0,B            ;SEE IF ALREADY IN TABLE
        JNE     _S6             ;NO
        ENDDO                   ;CLEANUP THE LOOP
        JMP     _CR             ;DO NOT SET A NEW ONE
_S6
        NOP                     ;END LOOP
_S5
        MOVE    B,P:(R0)        ;PUT NEW BREAKPOINT IN TABLE
        JMP     _CR             ;AND DISPLAY TABLE
;
;       R       REMOVE BREAKPOINT
;
_R
        JSR     PRTSPC          ;GIVE A SPACE
        PRTVAL  $3E             ;PROMPT FOR THE ADDRESS
        JSR     INADD           ;GET ADDRESS TO REMOVE
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT LOCATION TABLE
        DO      #NUMBRK,_R1     ;SEARCH TABLE FOR ADDRESS
        MOVE    P:(R0),X1       ;GET THE ADDRESS
        CMP     X1,B            ;SEE IF THE SAME
        JNE     _R2             ;NOT ZERO SO NOT THE SAME
        ENDDO                   ;IT IS ZERO, IT MATCHED
        CLR     B               ;GET A ZERO
        MOVE    B,P:(R0)        ;PUT A ZERO IN THE TABLE
        JMP     _CR             ;DO <CR><LF> AND DISPLAY TABLE
_R2
        MOVE    (R0)+           ;INCREMENT TO NEXT ADDRESS
_R1
        MOVE    #BPNTFND,R0     ;BREAKPOINT NOT FOUND
        JSR     OUT5            ;PRINT IT OUT
        JMP     CMD
;
;       DASH    REMOVE ALL BREAKPOINTS
;
_DASH
        CLR     A       #BPLOC,R0       ;GET A ZERO, POINT TO BP TABLE
        REP     #NUMBRK         ;ZERO THE ENTIRE TABLE
        MOVE    A,P:(R0)+       ;SAVE ZEROS
        JMP     _CR             ;DO <CR><LF> AND DISPLAY TABLE

        PAGE
;
;       REG             REGISTER DISPLAY/MODIFY
;
;       SUBCOMMANDS FOR DISPLAY/MODIFY MODE:
;               CTRL/Y          EXIT
;               <SP>            CHANGE VALUE
;               <CR>            GO TO NEXT REGISTER
;               ^               GO TO PREVIOUS REGISTER
;
REG
        JSR     CRLF            ;OUTPUT CRLF
PTRINI
        MOVE    #REGLST+REGSTART,R0     ;POINT TO REGISTER NAME LIST
        MOVE    #REGVAL+REGSTART,R4     ;POINT TO VALUES STORED IN REGISTERS
        MOVE    #REGLEN+REGSTART,R5     ;TABLE OF REGISTER LENGTHS
        MOVE    #REGSHFT+REGSTART,R3    ;SHIFT TO DISPLAY REGISTER VALUE
        MOVE    #REGLST,R1              ;START OF REGISTER LIST
        MOVE    #REGLST+NUMREG-1,R2     ;POINT TO LAST REG NAME
REGLOOP
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:(R0),A1       ;GET REG NAME
        JSR     OUT3            ;OUTPUT REGISTER NAME
        PRTVAL  EQUAL           ;OUTPUT EQUAL SIGN
        JSR     OUTREG          ;OUTPUT THE REGISTER
        JSR     IN2             ;GET SUBCOMMAND 
        MOVE    #CTRLY,X1       ;GET CTRL/Y
        CMP     X1,A    #CR,X1  ;SEE IF CTRL/Y
        JEQ     CMD             ;YES, EXIT REGISTER CHANGE
        CMP     X1,A    #SPACE,X1       ;SEE IF CR
        JEQ     _NEXT           ;YES
        CMP     X1,A    #'^',X1 ;SEE IF SPACE
        JEQ     _CHANGE
        CMP     X1,A    #CTRLC,X1       ;SEE IF UP ARROW   
        JEQ     _PREV           ;DO PREVIOUS REGISTER
        CMP     X1,A            ;SEE IF CTRLC
        JEQ     CMD             ;EXIT
        MOVE    R0,P:TEMP1      ;SAVE R0
        MOVE    #OPTMSG,R0      ;GET OPTION ERROR MESSAGE
        JSR     OUT5
        MOVE    P:TEMP1,R0      ;GET R0
        JMP     REGLOOP
;
;       ^       GO TO PREVIOUS REGISTER                         
;
_PREV
        MOVE    P:(R1),A        ;GET FIRST REG NAME
        MOVE    P:(R0),B        ;GET CURRENT REG NAME
        CMP     A,B             ;SEE IF THE SAME
        JNE     _UP1            ;NO THE SAME, SO NOT AT TOP
        DO      #NUMREG-1,_UP2  ;AT TOP, SHIFT ALL PTRS DOWN
        MOVE    X:(R0)+,X0  Y:(R4)+,Y0
        MOVE    X:(R3)+,X0 Y:(R5)+,Y0
_UP2
        JMP     REGLOOP         ;GO TO DISPLAY
_UP1
        MOVE    X:(R0)-,X0  Y:(R4)-,Y0  ;ADJUST POINTERS WITH DUMMY LOADS
        MOVE    X:(R3)-,X0  Y:(R5)-,Y0
        JMP     REGLOOP
;
;       GO TO NEXT REGISTER
;
_NEXT
        MOVE    P:(R0),A        ;GET CURRENT REG NAME
        MOVE    P:(R2),B        ;GET LAST REG NAME
        CMP     A,B             ;SEE IF THEY ARE THE SAME
        JEQ     _WRAP           ;WRAP AROUND TO TOP
        MOVE    X:(R0)+,X0  Y:(R4)+,Y0  ;ADJUST POINTERS WITH DUMMY LOADS
        MOVE    X:(R3)+,X0  Y:(R5)+,Y0
        JMP     REGLOOP                                  
_WRAP
        MOVE    #REGLST,R0      ;POINT TO REGISTER NAME LIST
        MOVE    #REGVAL,R4      ;POINT TO VALUES STORED IN REGISTERS
        MOVE    #REGLEN,R5      ;TABLE OF REGISTER LENGTHS
        MOVE    #REGSHFT,R3     ;SHIFT TO DISPLAY REGISTER VALUE
        JMP     REGLOOP         ;GO BACK TO REGISTER LOOP

;
;       CHANGE REGISTER VALUE
;
_CHANGE
        MOVE    #'  >',A        ;PROMPT USER
        JSR     OUT3            ;PRINT IT
        JSR     INREG           ;INPUT NEW REGISTER VALUE
        MOVE    A,Y1            ;SAVE DELIMITER
        MOVE    R7,A            ;GET NIBBLE COUNT
        TST     A               ;SEE IF NO INPUT
        JEQ     _NEXT           ;YES, DO NOT CHANGE REGISTER
        MOVE    B1,P:(R4)       ;SAVE NEW VALUE
        MOVE    #'^',A          ;GET UP ARROW
        CMP     Y1,A            ;SEE IF DELIMITER WAS UP ARROW
        JEQ     _PREV           ;YES, GO TO PREVIOUS
        JMP     _NEXT           ;GOTO NEXT REGISTER
;
;       DUMP ALL REGISTERS IN HORIZONTAL FORMAT
;
DISREG
        JSR     DMPREG          ;DUMP THE REGISTERS
        JMP     CMD             ;GO TO COMMAND LEVEL
        PAGE
;
;       GOB [BREAKPOINT]
;
GOB
        JEQ     GO              ;IF NO BREAKPOINT, DO GO COMMAND
        JSR     INADD           ;GET BREAKPOINT ADDRESS
        MOVE    B,X0            ;SAVE IT
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT TABLE
        DO      #NUMBRK,_S0     ;SCAN TABLE
        MOVE    P:(R0),A        ;GET BREAKPOINT ADDRESS
        TST     A               ;SEE IF ZERO
        JNE     _S1             ;NO, THEREFORE IT IS A VALID ADDRESS
        ENDDO                   ;IT IS EMPTY, CLEANUP LOOP
        JMP     _S2             ;AND EXIT
_S1
        CMP     X0,A            ;SEE IF ALREADY IN TABLE
        JNE     _S3             ;NO
        ENDDO                   ;YES, CLEAN UP LOOP
        JMP     GO              ;DO GO COMMAND WITH JEQ
_S3
        MOVE    (R0)+           ;POINT TO NEXT
_S0
        MOVE    #BPTBLFUL,R0    ;FULL MESSAGE
        JSR     OUT5
        JMP     CMD
_S2
        MOVE    X0,P:(R0)       ;PUT IN TEMP BREAKPOINT
        MOVE    X0,P:TEMPBP     ;SAVE TEMP BREAK POINT
        MOVE    #0,A            ;GET A ZERO, BUT DO NOT CHANGE Z FLAG
        MOVE    A,P:CFLAG       ;CLEAR CALL FLAG TO INDICATE GO COMMAND
        JMP     GO_SWI          ;IF CR, DO NOT PROMPT FOR ADDRESS
        PAGE
;
;       JSR [ADDR]              CALL USER SUBROUTINE
;
CALL
        MOVE    #1,A            ;FLAG FOR CALL COMMAND
        MOVE    A,P:CFLAG       ;SET THE FLAG
        JEQ     GO_SWI          ;IF CR, DO NOT PROMPT FOR ADDRESS
        JMP     GOC             ;DO GO AND CALL
;
;       GO [ADDR]               START PROGRAM EXECUTION AT ADDR
;
GO
        MOVE    #0,A            ;GET A ZERO, BUT DO NOT CHANGE Z FLAG
        MOVE    A,P:CFLAG       ;CLEAR CALL FLAG TO INDICATE GO COMMAND
        JEQ     GO_SWI          ;IF CR, DO NOT PROMPT FOR ADDRESS
GOC
        JSR     INADD           ;GET START ADDRESS
        MOVE    R7,A            ;GET NUMBER OF NIBBLES INPUT
        TST     A               ;SEE IF NO ADDRESS
        JEQ     GO_SWI          ;USE CURRENT PC
        MOVE    B1,P:USR_PC     ;SAVE STARTING PC
GO_SWI
        JSR     CRLF            ;DO <CR><LF>
        IF      EXETMR
        MOVEP   #>$FF,Y:CTUR    ;RESET COUNTER
        MOVEP   #>$FF,Y:CTLR    ;FOR TIMING ROUTINES
        ENDIF
;
;       SEE IF THE USER STACK POINTER IS ALL RIGHT
;
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        CLR     B       #>$10,X0        ;GET A 0, MASK FOR SE BIT
        AND     X0,A                    ;SEE IF STACK ERROR BIT IS SET
        JEQ     OKSTACK                 ;STACK ERROR BIT IS NOT SET
NGUSRSTK
        MOVE    B,P:CFLAG               ;CLEAR "JSR" FLAG IF SET
        MOVE    #BADSP,R0               ;POINT TO ERROR MESSAGE
        JSR     OUT5                    ;OUTPUT MESSAGE
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
OKSTACK
;
;       COPY THE NEW REGISTERS TO THE OLD REGISTER AREA
;
        JSR     COP_REG         ;COPY THE REGISTERS
;
;       SEE IF THE USER HAS SET ANY BREAKPOINTS. IF NO BREAKPOINTS
;       HAVE BEEN SET, GIVE A WARNING MESSAGE.
;
CKBPST
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT TABLE
        DO      #NUMBRK,_ANYBP  ;SCAN TABLE
        MOVE    P:(R0)+,A       ;GET BREAKPOINT
        TST     A               ;SET FLAGS
        JEQ     _ZIP            ;NO BREAKPOINT
        ENDDO                   ;CLEANUP LOOP IF A BREAKPOINT IS IN THE TABLE
        JMP     _HAVEBP         ;BECAUSE WE HAVE A BREAKPOINT
_ZIP
        NOP                     ;PLACE TO END LOOP
_ANYBP
        MOVE    #WNBPMSG,R0     ;POINT TO WARNING MESSAGE
        JSR     OUT5            ;AND PRINT IT OUT
_HAVEBP
;
;       SET NUMBER OF BREAKPOINTS BEFORE STOPPING
;
        MOVE    P:NBRVAL,X0     ;GET NUMBER OF BREAKS BEFORE STOPPING
        MOVE    X0,P:NBRCT      ;SAVE IN COUNTER
;
;       SEE IF THE PC IS POINTING TO A BREAKPOINT.  IF IT IS, DO
;       A PROCEED COMMAND WHICH WILL TRACE 1 INSTRUCTION TO GET PAST THE
;       BREAKPOINT AND THEN REENTER THE GO COMMAND TO SET THE BREAKPOINTS.
;
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT TABLE
        MOVE    P:USR_PC,X0     ;GET USER PC
        DO      #NUMBRK,_CKBRK  ;SEARCH THE TABLE
        MOVE    P:(R0)+,A       ;GET THE BREAKPOINT
        CMP     X0,A            ;SEE IF IT IS THE SAME AS THE PC
        JNE     _NO             ;NO
        ENDDO                   ;CLEAN UP THE DO LOOP
        JMP     PRO3            ;DO PROCEED COMMAND
_NO
        NOP                     ;PLACE TO END DO LOOP
_CKBRK
;
SET_SWI
;
;       SET VECTOR FOR SWI TO IMPLEMENT BREAKPOINTS
;
        MOVE    #>OP_JSR,Y0     ;LOAD "JSR"
        MOVE    #SWIENT,R1      ;MONITOR SWI ENTRY POINT
        MOVE    Y0,P:$0006      ;SAVE JSR
        MOVE    R1,P:$0007      ;SAVE LOCATION TO VECTOR TO
        MOVE    #>OP_SWI,Y0     ;LOAD "SWI"

;
;       REPLACE THE USER'S OPCODES WITH SWI'S.  SAVE THE ACTUAL OPCODE
;       IN A TABLE. WHEN THE SWI VECTOR IS TAKEN, THE SWI'S ARE REPLACED
;       WITH THE ACTUAL OPCODES.
;
        MOVE    #BPLOC,R0       ;TABLE OF BREAK POINT ADDRESSES
        MOVE    #OPSAVE,R4      ;TABLE OF ACTUAL OPCODES
        DO      #NUMBRK,_L1     ;REPLACE OPCODES WITH SWI'S
        MOVE    P:(R0),A        ;GET ADDRESS
        TST     A               ;SEE IF ZERO
        JEQ     _L2             ;YES, NO BREAKPOINT
        MOVE    A1,R1           ;PUT IN ADDRESS REG FOR INDEXING
        NOP
        MOVE    P:(R1),Y1       ;GET OLD OPCODE 
        MOVE    Y1,P:(R4)       ;SAVE OPCODE
        MOVE    Y0,P:(R1)       ;REPLACE USER OPCODE WITH SWI
_L2
        MOVE    X:(R0)+,X0  Y:(R4)+,Y1  ;SHIFT POINTERS
_L1
;
;       RESTORE THE USER'S STACK AND REGISTERS. 
;       IF THE CALL COMMAND IS BEING USED,
;       THEN PUSH A RETURN TO MONITOR ADDRESS ON THE STACK ALSO (TO BE
;       EXECUTED BY THE USER'S RTS).
;
RESTORE_USER
        MOVEC   #0,SP           ;RESET STACK POINTER
        MOVE    P:USR_SP,A      ;NUMBER OF USER STACK ENTRIES
        MOVE    #>000001,X0     ;GET A ONE TO SUBTRACT
        MOVE    #USTK+30,R0     ;END OF USER SAVED STACK
        MOVE    #_FULL,R5       ;WHERE TO JUMP WHEN STACK IS FULL
        DUP     15              ;FILL 15 POSSIBLE ENTRIES
        TST     A               ;SEE IF NOTHING TO LOAD
        JEQ     (R5)            ;DONE LOADING STACK
        MOVE    P:-(R0),SSH     ;LOAD DATA ON STACK
        MOVE    P:-(R0),SSL     ;LOAD LOW VALUE ON STACK
        SUB     X0,A            ;DECREMENT NUMBER OF VALUES TO LOAD
        ENDM
_FULL
        MOVE    #OP_JSR,Y0      ;GET A "JSR"
        MOVE    Y0,P:$001E      ;SET UP NMI VECTOR
        MOVE    #NMIVEC,Y0      ;GET MONITOR NMI ENTRY POINT
        MOVE    Y0,P:$001F      ;SAVE IT IN VECTOR TABLE
        MOVE    P:CFLAG,A       ;GET CALL/GO FLAG
        TST     A               ;CHECK VALUE
        JEQ     _NOTCALL        ;GO COMMAND
        MOVE    #CALLENT,SSH    ;ENTRY POINT FROM USER RTS AFTER CALL CMD
        MOVE    SR,SSL          ;MONITOR STATUS
        CLR     A               ;GET A ZERO
        MOVE    A,P:CFLAG       ;RESET CALL FLAG
_NOTCALL
;
;       RESTORE THE USER'S REGISTERS AND PUSH ONTO THE STACK THE 
;       USER'S STACK PC AND STATUS REGISTER.  THEN DO A RTI TO EXECUTE
;       THE USER'S CODE
;
        MOVEP   P:USR_IPR,X:IPR ;SET USER IPR
        MOVE    P:USR_DEV,X0            ;GET USER I/O DEVICE
        MOVE    X0,P:IODEV      ;RESTORE IT
        MOVE    P:USR_R0,R0
        MOVE    P:USR_R1,R1
        MOVE    P:USR_R2,R2
        MOVE    P:USR_R3,R3
        MOVE    P:USR_R4,R4
        MOVE    P:USR_R5,R5
        MOVE    P:USR_R6,R6
        MOVE    P:USR_R7,R7
        MOVE    P:USR_N0,N0
        MOVE    P:USR_N1,N1
        MOVE    P:USR_N2,N2
        MOVE    P:USR_N3,N3
        MOVE    P:USR_N4,N4
        MOVE    P:USR_N5,N5
        MOVE    P:USR_N6,N6
        MOVE    P:USR_N7,N7
        MOVE    P:USR_M0,M0
        MOVE    P:USR_M1,M1
        MOVE    P:USR_M2,M2
        MOVE    P:USR_M3,M3
        MOVE    P:USR_M4,M4
        MOVE    P:USR_M5,M5
        MOVE    P:USR_M6,M6
        MOVE    P:USR_M7,M7
        MOVE    P:USR_X0,X0
        MOVE    P:USR_X1,X1
        MOVE    P:USR_Y0,Y0
        MOVE    P:USR_Y1,Y1
        MOVE    P:USR_A2,A2
        MOVE    P:USR_A1,A1
        MOVE    P:USR_A0,A0
        MOVE    P:USR_B2,B2
        MOVE    P:USR_B1,B1
        MOVE    P:USR_B0,B0
        MOVE    P:USR_OMR,OMR
        MOVE    P:USR_LA,LA
        MOVE    P:USR_LC,LC
        MOVE    P:USR_PC,SSH    ;SET PC
        MOVE    P:USR_SR,SSL    ;SET SR
        IF      EXETMR
        JCLR    #0,Y:START_CTR,*+2      ;START EXECUTION COUNTER
        ENDIF
        MOVEP   P:USR_BCR,X:BCR ;SET USER BCR
        RTI                     ;RETURN TO EXECUTE USERS CODE
;
;       ENTRY POINT FOR BREAKPOINTS
;
SWIENT
        SAVE_USER               ;SAVE USER STATE
        CLR     A               ;GENERATE NOP CODE
        MOVE    A1,P:$001E      ;NOP OUT THE NMI INTERRUPT VECTOR
        MOVE    A1,P:$001F
        IF      EXETMR
;
;       SET EXECUTION TIMER FROM THE PLACE IT STOPPED
;
        MOVEP   Y:CTUR,X0       ;GET TIMER UPPER
        MOVEP   X0,Y:CTUR       ;RESET UPPER COUNT DOWN
        MOVEP   Y:CTLR,X0       ;GET TIMER LOWER
        MOVEP   X0,Y:CTLR       ;RESET LOWER COUNT DOWN
        ENDIF
;
;       BACKUP THE USER'S PC BY ONE BECAUSE THE SWI CAUSES THE 
;       PC TO BE INCREMENTED BEFORE IT IS PUSHED ON THE STACK
;
        MOVE    P:USR_PC,R0     ;GET THE USER PC
        NOP                             ;CLEAR PIPE
        MOVE    (R0)-                   ;POINT PC BACK TO WHERE  PC STOPPED
        MOVE    R0,P:USR_PC     ;SAVE ACTUAL PC
;
;       CHECK TO SEE IF THE SWI WAS CAUSED BY A BREAKPOINT.
;       IF IT IS NOT A BREAKPOINT, THE USER USED A SWI.
;
        MOVE    P:USR_PC,X0     ;GET USER'S PC
        MOVE    #BPLOC,R0               ;POINT TO BREAKPOINT TABLE
        DO      #NUMBRK,_CKTAB          ;CHECK BREAKPOINT TABLE
        MOVE    P:(R0)+,A               ;GET BREAKPOINT
        CMP     X0,A                    ;SEE IF A MATCH
        JNE     _NO                     ;NOPE
        ENDDO                           ;YES, WE HAVE A MATCH
        JSR     RES_UOPS                ;RESTORE THE USER'S OPCODES
        JMP     _ECHK                   ;DONE CHECKING
_NO
        NOP                             ;PLACE TO END LOOP
_CKTAB
        JSR     RES_UOPS                ;RESTORE THE USER'S OPCODES
;
;       SEE IF BREAKPOINT OCCURRED AT LA OF A LOOP
;
        MOVE    P:USR_SP,X0     ;GET USER STACK POINTER
        MOVE    #USTK+31,A              ;POINT TO END OF STACK AREA+1
        SUB     X0,A                    ;BACK UP 
        SUB     X0,A    #>1,X0          ;TO SSH
        MOVE    A1,R0                   ;PUT IN R0 FOR INDEXING
        MOVE    P:USR_PC,X1     ;GET USER PC
        MOVE    P:(R0),B                ;GET SSH
        SUB     X0,B                    ;BACK IT UP ONE
        CMP     X1,B                    ;SEE IF BREAK WAS AT LA
        JNE     _NOTLA                  ;NO
        MOVE    P:USR_LA,X1     ;GET LA
        MOVE    X1,P:USR_PC     ;SET IT AS THE NEW PC
        MOVE    P:USR_LC,A      ;GET THE LOOP COUNTER
        ADD     X0,A                    ;INCREMENT IT
        MOVE    A,P:USR_LC      ;SAVE NEW LOOP COUNTER
        JMP     _ECHK                   ;AND PROCESS AS A NORMAL BREAKPOINT
;
;       REPORT UNKNOWN SWI
;
_NOTLA
        MOVE    #UIM,R0                 ;UNKNOWN SWI INTERRUPT MSG
        JSR     OUT5                    ;PRINT IT
        MOVE    P:USR_PC,B      ;GET PC
        JSR     OUTADD                  ;OUTPUT IT
        JMP     UNKSWI                  ;RETURN TO COMMAND LEVEL
_ECHK
;
;       CHECK TO SEE IF THE REQUIRED NUMBER OF BREAKPOINTS HAVE BEEN
;       TAKEN BEFORE STOPPING
;
        MOVE    P:NBRCT,A       ;GET BREAKPOINT COUNT
        MOVE    #>1,X0          ;GET A ONE
        SUB     X0,A            ;DECREMENT COUNT
        JEQ     STOPEXE         ;NOW ZERO, SO STOP EXECUTION
        MOVE    A,P:NBRCT       ;SAVE NEW BREAKPOINT COUNT
        JMP     PRO3            ;DO PROCEED COMMAND TO CONTINUE FROM BP
;
;       PRINT OUT BREAKPOINT MESSAGE AND DUMP REGISTERS
;
STOPEXE
        MOVE    #BRKPMSG,R0     ;POINT TO BREAKPOINT MESSAGE
        JSR     OUT5
UNKSWI
        JSR     DMPREG          ;DUMP REGISTERS
        JMP     TMR_PRT

;
;       ENTRY POINT WHEN USING THE CALL COMMAND.  THIS POINT IS
;       REACHED BY THE USER SUBROUTINE DOING A RTS AND RETURNING
;       TO THIS POINT.  SINCE THE RETURN TO THIS POINT IS NOT VIA ANY
;       INTERRUPT, A DUMMY PC AND THE ACTUAL SR IS PUSHED ONTO THE STACK
;       AND THEN THE CONTEXT IS PROCESSED AS AN INTERRUPT.
;
CALLENT
        MOVE    P:USR_PC,SSH    ;SET OLD STARTING PC AS PC
        MOVE    SR,SSL          ;USER SR AS DEFAULT SR
        SAVE_USER               ;SAVE USER STATE
        CLR     A               ;GENERATE NOP CODE
        MOVE    A,P:$001E       ;NOP OUT THE NMI INTERRUPT VECTOR
        MOVE    A,P:$001F
        JSR     RES_UOPS        ;RESTORE USER'S OPCODES
        MOVE    #RTNMSG,R0      ;MESSAGE FOR TELLING RETURN MONITOR
        JSR     OUT5            ;PRINT IT
        JSR     DMPREG          ;DUMP REGISTERS
        JMP     TMR_PRT         ;GO PRINT EXECUTION TIMER
;
;               PROCEED FROM BREAKPOINT.  THIS WILL DO A TRACE ON THE
;               CURRENT INSTRUCTION; THE TRACE ENTRY POINT WILL THEN
;               POINT TO THE GO COMMAND TO SET UP BREAKPOINTS AND THEN
;               CONTINUE EXECUTION WITH THE BREAKPOINTS IN PLACE.
;
PRO3
        MOVE    #TRACE1,R5      ;ENTRY POINT FOR TRACE IF PROCEEDING FROM SWI
;
;       DO SINGLE STEP FOR TRACE COMMAND.  THIS WILL POINT THE
;       TRACE VECTOR BACK TO THE TRACE COMMAND AND EXECUTE 1 INSTRUCTION.
;       NOTE THAT THE PC IS IN R5
;
PRO1
        MOVE    #>OP_JSR,Y0     ;GET "JSR"
        MOVE    Y0,P:$0004      ;SAVE IN TRACE VECTOR
        MOVE    R5,P:$0005      ;SAVE TRACE ROUTINE VECTOR
;
;       CONTINUE TRACING.  THIS POINT IS ENTERED IF WE TRACED AN INSTRUCTION
;       BUT THERE ARE MORE TO TRACE.  THIS CONTINUES THE TRACE OPERATION
;       WITH THE TRACE VECTOR STILL POINTING TO THE TRACE COMMAND
;
PRO2                                      
        MOVE    #>$002000,X0    ;GET MASK TO SET "T" BIT
        MOVE    P:USR_SR,A      ;GET USER STATUS REGISTER
        OR      X0,A            ;SET T BIT IN USER SR
        MOVE    A1,P:USR_SR     ;SAVE NEW USER SR WITH T BIT SET
;
;       THIS IS A TEMPORY FIX BECAUSE OF THE "2B38EXXXX" MASK PROBLEM.
;       THIS WILL MAKE THE USER'S IPR ZERO ONLY WHEN TRACING.
;
        MOVE    P:USR_IPR,X0    ;GET USER'S IPR
        MOVE    X0,P:IPR_TEMP           ;SAVE IPR
        CLR     A                       ;GET A ZERO
        MOVE    A,P:USR_IPR     ;PUT A 0 IN USER'S IPR
;       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;END OF BUG FIXES
        JMP     RESTORE_USER    ;GO RESTORE REGISTERS AND TRACE 1 INSTRUCTION
;
;       TRACE1 - ENTRY POINT IF PROCEEDING FROM A BREAKPOINT (SWI)
;                   
TRACE1
        SAVE_USER               ;SAVE THE USER STATE
;
;       THIS IS A FIX BECAUSE OF THE DSP "2B38EXXXX" MASK PROBLEM
;       IF THE USER CHANGED HIS IPR, THEN KEEP THE CURRENT VALUE THAT
;       THE USER SET. IF THE IPR DID NOT CHANGE (IT IS STILL ZERO) THEN
;       RESTORE THE PREVIOUS VALUE.  A PROBLEM WITH THIS BUG FIX IS THAT
;       THE USER CAN NOT TRACE CODE THAT SETS THE IPR TO ZERO.
;
        MOVE    P:USR_IPR,A     ;GET USER'S IPR
        TST     A                       ;SEE IF ZERO
        JNE     _CHANGED                ;NO, IT CHANGED
        MOVE    P:IPR_TEMP,X0   ;GET THE SAVED USER'S IPR
        MOVE    X0,P:USR_IPR    ;PUT IT BACK IN THE REGISTER BLOCK
_CHANGED
;       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;END OF BUG FIXES
        MOVE    #>$00DFFF,X0    ;MASK TO REMOVE T BIT
        MOVE    P:USR_SR,A1             ;GET USER SR
        AND     X0,A                    ;REMOVE USER T BIT
        MOVE    A1,P:USR_SR             ;SAVE USER SR WITHOUT T BIT
        IF      EXETMR
;
;       SET EXECUTION TIMER FROM THE PLACE IT STOPPED
;
        MOVEP   Y:CTUR,X0       ;GET TIMER UPPER
        MOVEP   X0,Y:CTUR       ;RESET UPPER COUNT DOWN
        MOVEP   Y:CTLR,X0       ;GET TIMER LOWER
        MOVEP   X0,Y:CTLR       ;RESET LOWER COUNT DOWN
        ENDIF

        JMP     SET_SWI         ;GO SET SWI'S AND EXECUTE GO COMMAND
;
;       QTRACE - "." COMMAND TO TRACE 1 INSTRUCTION
;
QTRACE
        MOVE    #>1,B1          ;SET FOR TRACE 1 INSTRUCTION
        JMP     TRACEP          ;DO TRACE
;
;       TRA [N]         TRACE N INSTRUCTIONS
;   
TRACE
        JEQ     QTRACE          ;IF <CR> DELIMITER, TRACE 1
        JSR     INADD           ;GET NUMBER OF INSTRUCTIONS TO TRACE
        TST     B               ;SEE IF ZERO ENTERED
        JEQ     QTRACE          ;YES, TRACE JUST ONE INSTEAD
TRACEP
        MOVE    B1,P:NUMTR      ;SAVE AS NUMBER OF INSTRUCTIONS TO TRACE
        CLR     A               ;GET A ZERO
        MOVE    A,P:CFLAG       ;RESET CALL FLAG
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    #TRACE2,R5      ;POINT TRACE ENTRY POINT TO TRACE2
;
;       CHECK TO SEE IF THE USER'S STACK POINTER IS OK
;
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        CLR     B       #>$10,X0        ;GET A 0, MASK FOR SE BIT
        AND     X0,A                    ;SEE IF STACK ERROR BIT IS SET
        JNE     NGUSRSTK                ;STACK ERROR BIT IS SET

;
;       COPY THE NEW REGISTERS TO THE OLD REGISTER AREA
;
        JSR     COP_REG         ;COPY THE REGISTERS
        JMP     PRO1            ;SET UP TRACE AND DO SINGLE STEP
;
;       TRACE2 - ENTRY POINT IF USING THE TRACE COMMAND
;
TRACE2
        SAVE_USER               ;SAVE USER STATE
;
;       THIS IS A FIX BECAUSE OF THE DSP "2B38EXXXX" MASK PROBLEM
;       IF THE USER CHANGED HIS IPR, THEN KEEP THE CURRENT VALUE THAT
;       THE USER SET. IF THE IPR DID NOT CHANGE (IT IS STILL ZERO) THEN
;       RESTORE THE PREVIOUS VALUE.  A PROBLEM WITH THIS BUG FIX IS THAT
;       THE USER CAN NOT TRACE CODE THAT SETS THE IPR TO ZERO.
;
        MOVE    P:USR_IPR,A     ;GET USER'S IPR
        TST     A                       ;SEE IF ZERO
        JNE     _CHANGED                ;NO, IT CHANGED
        MOVE    P:IPR_TEMP,X0   ;GET THE SAVED USER'S IPR
        MOVE    X0,P:USR_IPR    ;PUT IT BACK IN THE REGISTER BLOCK
_CHANGED
;       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;END OF BUG FIXES
        MOVE    P:USR_SR,A1     ;GET USER SR
        MOVE    #>$DFFF,X1      ;GET MASK TO REMOVE T BIT
        AND     X1,A            ;REMOVE USER T BIT
        MOVE    A1,P:USR_SR     ;SAVE USER SR WITHOUT T BIT
        MOVE    #'TR-',A1       ;GET "TR-" MSG
        JSR     OUT3            ;PRINT IT FOR USER
        MOVE    P:USR_PC,B      ;GET USER PC
        JSR     OUTADD          ;PRINT OUT ADDRESS WE STOPPED AT
;
;       IF THE PC IS IN THE BREAKPOINT TABLE, STOP AT THE BREAKPOINT
;
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT ADDRESSES
        MOVE    P:USR_PC,X0     ;GET THE USER PC
        DO      #NUMBRK,_CKBRK  ;CHECK BREAKPOINT TABLE
        MOVE    P:(R0)+,A       ;GET THE BREAKPOINT
        CMP     X0,A            ;SEE IF IN TABLE
        JNE     _NOTBP          ;NO, NOT THIS ONE
        ENDDO                   ;EXIT THE DO LOOP
        CLR     A               ;GENERATE NOP CODE
        MOVE    A1,P:$001E      ;NOP OUT THE NMI INTERRUPT VECTOR
        MOVE    A1,P:$001F      ;DO DISABLE THE ABORT
        JMP     STOPEXE         ;STOP EXECUTION
_NOTBP
        NOP                     ;PLACE TO END LOOP
_CKBRK
        JSR     CRLF            ;OUTPUT <CR><LF>
;
;       CHECK TO SEE IF WE ARE DONE TRACING (CHECK THE TRACE COUNT)
;
        MOVE    #>1,X0          ;GET A 1
        MOVE    P:NUMTR,A       ;GET NUMBER OF INSTRUCTIONS TO TRACE
        SUB     X0,A            ;DECREMENT NUMBER OF INSTRUCTIONS TO TRACE
        JNE     _M              ;MORE TO TRACE
        CLR     A               ;GENERATE NOP CODE
        MOVE    A1,P:$001E      ;NOP OUT THE NMI INTERRUPT VECTOR
        MOVE    A1,P:$001F      ;DO DISABLE THE ABORT
        JSR     DMPREG          ;DUMP THE REGISTERS
        JMP     CMD             ;ALL DONE, GO TO COMMAND LEVEL
_M
        MOVE    A1,P:NUMTR      ;SAVE NEW COUNT
        JMP     PRO2            ;DO ANOTHER TRACE
;
;       ENTRY POINT FOR USER GENERATED NMI INTERRUPT.
;       THIS INTERRUPT IS GENERATED BY PUTTING +10 VOLTS ON IRQB.
;
NMIVEC
        SAVE_USER               ;SAVE THE USER'S STATE
        CLR     A               ;GENERATE NOP CODE
        MOVE    A,P:$001E       ;NOP OUT THE NMI INTERRUPT VECTOR
        MOVE    A,P:$001F
        JSR     RES_UOPS        ;RESTORE THE USER'S OPCODES
        MOVE    #ABOMSG,R0      ;POINT TO ABORT MESSAGE
        JSR     OUT5            ;PRINT IT OUT
        JSR     DMPREG          ;DUMP THE REGISTERS
        JMP     CMD             ;GO TO COMMAND LEVEL
;
;       RESTORE THE USER'S OPCODES.  THIS WILL SCAN THE BREAKPOINT TABLE
;       AND IF THERE IS A BREAKPOINT, THE OPCODE FROM THE TABLE WILL BE
;       PUT BACK INTO THE USER'S CODE.
;
RES_UOPS
        MOVE    #BPLOC,R0       ;TABLE OF BREAK POINT ADDRESSES
        MOVE    #OPSAVE,R4      ;TABLE OF ACTUAL OPCODES
        DO      #NUMBRK,_L1     ;REPLACE OPCODES
        MOVE    P:(R0),A        ;GET ADDRESS
        TST     A               ;SEE IF ZERO
        JEQ     _L2             ;YES, NO BREAKPOINT
        MOVE    A1,R1           ;PUT IN ADDRESS REG FOR INDEXING
        MOVE    P:(R4),Y1       ;GET OPCODE FROM TABLE
        MOVE    Y1,P:(R1)       ;REPLACE USER'S OPCODE
_L2
        MOVE    X:(R0)+,X0  Y:(R4)+,Y1  ;SHIFT POINTERS
_L1  
;
;       NOW REMOVE THE TEMPORARY BREAKPOINT FROM THE TABLE IF IT 
;       IS THERE.
;
        MOVE    P:TEMPBP,A      ;GET TEMP BREAKPOINT
        TST     A   #0,X1       ;TEST IT
        JEQ     _DONE           ;NO TEMP BREAKPOINT
        MOVE    #BPLOC,R0       ;POINT TO BREAKPOINT TABLE
        DO      #NUMBRK,_DONE   ;SCAN TABLE
        MOVE    P:(R0),X0       ;GET BREAKPOINT
        CMP     X0,A            ;SEE IF MATCH
        JNE     _NO             ;NOPE
        MOVE    X1,P:(R0)       ;CLEAR IN TABLE
        MOVE    X1,P:TEMPBP     ;CLEAR TEMP BREAKPOINT
        ENDDO
        JMP     _DONE           ;EXIT
_NO
        MOVE    (R0)+           ;CONTINUE SCANNING TABLE
_DONE
        RTS                     ;RETURN WHEN DONE
;                 
;       PRINT THE EXECUTION TIMER
;
TMR_PRT
        JSR     CRLF
        IF      EXETMR
        MOVE    P:DRTISR,A      ;GET DUART INTERRUPT STATUS REGISTER
        MOVE    #>$08,X0        ;GET MASK FOR ISR[3]
        AND     X0,A            ;MASK FOR TIMER OVERFLOW BIT
        JEQ     _NOOFL          ;IF ZERO, NO OVERFLOW
        MOVE    #TOFMSG,R0      ;POINT TO OVERFLOW MESSAGE
        JSR     OUT5            ;DISPLAY MESSAGE
        JMP     CMD
_NOOFL
        MOVE    #EXEMSG,R0      ;POINT TO MSG
        JSR     OUT5            ;PRINT IT
        MOVE    Y:CTLR,B2       ;GET COUNTER LOWER
        REP     #8              ;SHIFT IT DOWN
        ASR     B
        MOVE    Y:CTUR,B2       ;GET COUNTER UPPER
        REP     #16             ;SHIFT IT DOWN
        ASR     B
        NOT     B       #.27125,X1      ;MAKE IT COUNT UP, GET FRACTION
        MOVE    #$FFFF,X0       ;MASK FOR LOWER 4 NIBBLES
        AND     X0,B            ;KEEP ONLY LOWER 4 NIBBLES
        MOVE    B1,X0           ;PUT IN X FOR MUL
        MPY     X1,X0,B         ;MUL BY .27125
        REP     #4              ;MUL BY 16
        ASL     B               ;FOR A TOTAL OF MUL BY 4.34
        RND     B               ;BECAUSE IT IS 4.34 uS/COUNT
        JSR     OUTINT          ;OUTPUT IT IN DECIMAL
        MOVE    #TMRMSG,R0      ;POINT TO MESSAGE
        JSR     OUT5            ;PRINT IT
        MOVE    P:NBRVAL,X0     ;GET NUMBER OF BREAKPOINTS EXECUTED
        MOVE    #.27125,X1      ;GET .27125
        MPY     X0,X1,B         ;SCALE # OF BREAKPOINTS
        REP     #4              ;MULTIPLY BY 16
        ASL     B
        RND     B               ;ROUND RESULT
        JSR     OUTINT          ;OUTPUT ACCURACY
        MOVE    #' uS',A        ;MESSAGE
        JSR     OUT3            ;PRINT IT
        ENDIF
        JMP     CMD

        PAGE
;
;       DMP <[P,X,Y]>:<ADDR1> [ADDR2]   DUMP P,X OR Y MEMORY FROM ADDR1
;                                       TO ADDR2
;
DUMP
        JSR     GETPXY          ;GET MEMORY SPACE AND AN ADDRESS INTO B1
        MOVE    #>$00FFF8,X1    ;GET $FFF8
        AND     X1,B            ;START DUMP ON 8 WORD ADDRESS
        MOVE    B1,R2           ;SAVE STARTING ADDRESS
        MOVE    #CR,X0          ;GET CR
        CMP     X0,A            ;SEE IF DELIMITER WAS A CR
        JNE     _NOTCR          ;NO
        MOVE    #>4,B           ;DUMP 4 LINES IF CR WAS DELIMITER
        JMP     _DUMPIT         ;GO DO DUMP
_NOTCR
        PRTVAL  DASH            ;PRINT DASH
        JSR     INADD           ;GET ENDING ADDRESS
        MOVE    R2,A            ;GET STARTING ADDRESS AGAIN
        SUB     A,B     #>1,X1  ;GET LENGTH OF DUMP, GET 1
        REP     #3              ;SCALE TO 8 WORDS/LINE
        LSR     B
        ADD     X1,B            ;INCREMENT B1
_DUMPIT
        DO      B1,_E1          ;NUMBER OF LINES TO DUMP
        JSR     CRLF            ;OUTPUT CR,LF FIRST
        MOVE    P:MEMT,A1       ;GET MEMORY TYPE
        JSR     OUT2            ;OUTPUT IT
        PRTVAL  COLON           ;OUTPUT COLON
        MOVE    R2,B            ;GET CURRENT ADDRESS TO DUMP
        JSR     OUTADD          ;OUTPUT ADDRESS
        JSR     PRTSPC          ;PRINT A SPACE
        DO      #8,_E2          ;OUTPUT 8 VALUES/LINE
        JSR     GETMEM          ;GET MEMORY
        JSR     OUTDAT          ;OUTPUT THE DATA
        JSR     PRTSPC          ;OUTPUT SPACE
_E2
        NOP                     ;GIVE LOOP A PLACE TO END
_E1
        JMP     CMD             ;GO TO COMMAND LEVEL
        PAGE
;
;       HST             ENTER TRANSPARENT COMMUNICATIONS WITH HOST.
;                       CTRL/A IS THE DEFAULT EXIT CHARACTER.
;                       DHE CAN BE USED TO CHANGE THE EXIT CHARACTER.
;
HOST
        JSR     CRLF                    ;OUTPUT <CR><LF>
        MOVE    P:HST_EXIT,Y0           ;GET EXIT CHARACTER
        MOVE    #>$7F,Y1                ;PARITY MASK
_CKTERM
        JSR     SET_TERM                ;SET TERMINAL AS I/O DEVICE
        JSR     IN0                     ;SCAN INPUT DEVICES
        JEQ     _CKHOST                 ;NO DATA, CHECK HOST
        MOVE    A,B                     ;COPY INPUT
        AND     Y1,B                    ;MASK PARITY
        MOVE    B1,B                    ;SIGN EXTEND AND ZERO B0
        CMP     Y0,B                    ;SEE IF EXIT
        JEQ     CMD                     ;YES, RETURN TO COMMAND LEVEL
        JSR     SET_HOST                ;SET HOST AS I/O DEVICE
        JSR     OUT0                    ;OUTPUT CHARACTER
_CKHOST
        JSR     SET_HOST                ;SET HOST AS I/O DEVICE
        JSR     IN0                     ;SCAN INPUT DEVICE           
        JEQ     _CKTERM                 ;NO DATA
        JSR     SET_TERM                ;SET TERMINAL AS I/O DEVICE
        JSR     OUT0                    ;SEND DATA
        JMP     _CKTERM                 ;GO AND CHECK TERMINAL
        PAGE
;
;       VER             VERIFY A DSP56000 FILE IS IN MEMORY AND
;                       PRINT OUT DIFFERENCES
;
VERIFY
        MOVE    #1,A            ;SET FLAG NOT EQUAL TO ZERO
        MOVE    A,P:VFLAG       ;SAVE FLAG
        JMP     LCR             ;GO JOIN LOAD CODE
;
;       LOA             LOAD DSP56000 OBJECT FILE
;                       THIS SENDS A <CR> TO THE HOST PORT AND THEN
;                       LOADS OMF RECORDS.
;
LOAD
        CLR     A               ;GET A ZERO
        MOVE    A,P:VFLAG       ;IF FLAG IS ZERO => LOAD
LCR
        JSR     CRLF            ;DO A CR,LF
        JSR     SET_HOST        ;SET HOST AS I/O DEVICE
        PRTVAL  CR              ;OUTPUT <CR> TO HOST
USWT
        JSR     SET_TERM        ;SET FOR TERMINAL I/O
        JSR     IN0             ;SEE IF DATA
        JNE     _DATA           ;YES
        JSR     SET_HOST        ;SET HOST FOR I/O
        JSR     IN0             ;SEE IF DATA
        JEQ     USWT            ;NO
_DATA
        CLR     B       #>$7F,X0        ;GET A ZERO IN B FOR LATER, PARITY MASK
        AND     X0,A    #>'_',X0        ;MASK PARITY
        CMP     X0,A    #>CTRLC,X0      ;SEE IF UNDERSCORE
        JEQ     GOTUS           ;YES
        CMP     X0,A    #>CTRLY,X0      ;SEE IF CTRL/C
        JEQ     CMD             ;YES, RETURN TO COMMAND LEVEL
        CMP     X0,A            ;SEE IF CTRL/Y
        JEQ     CMD             ;YES
        JMP     USWT            ;WAIT FOR UNDERSCORE
GOTUS
        MOVE    B,P:LFLAG       ;SET FLAG FOR LONG MEMORY ACCESSES TO ZERO
        JSR     HIN1            ;GET 3 CHARACTERS FROM HOST INTO B1
        MOVE    #'DAT',X1       ;GET TEXT FOR DATA RECORD
        CMP     X1,B    #'END',X1       ;SEE IF DATA RECORD
        JEQ     _DODAT          ;YES, PROCESS IT
        CMP     X1,B    #'BLO',X1       ;SEE IF END
        JEQ     _DOEND          ;YES
        CMP     X1,B            ;SEE IF BLOCKDATA RECORD
        JEQ     _BLKDTA         ;YES
        JMP     USWT            ;WAIT FOR US
;                          
;       DO "_DATA [P,X,Y,L] ADDR" RECORDS
;
_DODAT
        JSR     HIN1            ;INPUT 3 CHARACTERS FROM HOST
        MOVE    B1,P:MEMT       ;SAVE MEMORY TYPE
        JSR     _DSPLYSP        ;DISPLAY THE MEMORY SPACE
        MOVE    #4,N0           ;NUMBER OF ASCII HEX CHARACTERS TO EXPECT
        JSR     HIN2            ;GET MEMORY ADDRESS
        MOVE    B1,R0           ;PUT IN ADDRESS REG
        MOVE    #6,N0           ;NUMBER OF CHARACTERS IN DATA RECORD
_GETDAT
        JSR     HIN2            ;GET DATA
        CLR     A
        MOVE    P:MEMT,A1       ;GET MEMORY TYPE
        MOVE    #'A P',X1       ;GET P
        CMP     X1,A    #'A X',X1       ;SEE IF P MEMORY
        JEQ     _PM                 
        CMP     X1,A    #'A Y',X1       ;SEE IF X MEMORY
        JEQ     _XM
        CMP     X1,A    #'A L',X1       ;SEE IF Y MEMORY
        JEQ     _YM
        CMP     X1,A                    ;SEE IF LONG MEMORY
        JNE     BADXYP          ;NO, ERROR
;
;       LONG MEMORY. DECIDE IF IT REALLY BELONGS IN X OR Y MEMORY
;
        MOVE    P:LFLAG,A       ;GET LONG MEMORY FLAG
        MOVE    #>1,X1          ;GET A 1
        ADD     X1,A            ;INCREMENT A
        MOVE    A1,P:LFLAG      ;SAVE NEW A
        AND     X1,A            ;MASK FOR LSB OF A
        JNE     _XM             ;IF LSB IS ODD, DO X MEMORY
        MOVE    (R0)-           ;BACK UP TO MEMORY LOCATION AND DO Y
;
;       LOAD/VERIFIY Y MEMORY
;
_YM
        MOVE    P:VFLAG,A       ;GET VERIFY/LOAD FLAG
        TST     A               ;CHECK FLAG VALUE
        JEQ     _YLOAD          ;IT IS ZERO SO DO A LOAD
        MOVE    B1,X1           ;SAVE INPUT VALUE
        MOVE    Y:(R0),B        ;GET MEMORY VALUE
        CMP     X1,B            ;SEE IF SAME
        JNE     _VFAIL          ;NO GO REPORT ERROR
_YLOAD
        MOVE    B1,Y:(R0)+      ;SAVE DATA IN Y MEMORY SPACE
        JMP     _GETDAT         ;WAIT FOR MORE DATA
;
;       LOAD/VERIFY X MEMORY
;
_XM
        MOVE    P:VFLAG,A       ;GET VERIFY/LOAD FLAG
        TST     A               ;SEE IF ZERO
        JEQ     _XLOAD          ;YES, SO DO A LOAD
        MOVE    B1,X1           ;SAVE INPUT VALUE
        MOVE    X:(R0),B        ;GET MEMORY VALUE
        CMP     X1,B            ;SEE IF SAME
        JNE     _VFAIL          ;NO, VERIFY FAIL
_XLOAD
        MOVE    B1,X:(R0)+      ;SAVE DATA IN X MEMORY SPACE
        JMP     _GETDAT
;
;       LOAD/VERIFY P MEMORY
;
_PM
        MOVE    P:VFLAG,A       ;GET VERIFY/LOAD FLAG
        TST     A               ;SEE IF ZERO
        JEQ     _PLOAD          ;YES, DO A P LOAD
        MOVE    B1,X1           ;SAVE INPUT VALUE
        MOVE    P:(R0),B        ;GET MEMORY VALUE
        CMP     X1,B            ;SEE IF SAME
        JNE     _VFAIL          ;NO
_PLOAD
        MOVE    B1,P:(R0)+      ;SAVE DATA IN Y MEMORY SPACE
        JMP     _GETDAT
;
;       VERIFY ERROR OUTPUT ROUTINE
;
_VFAIL
        MOVE    X1,P:VFIN       ;SAVE INPUT VALUE FROM SERIAL PORT
        MOVE    B1,P:VFMEM      ;SAVE MEMORY VALUE
        JSR     SET_TERM        ;SET TERMINAL AS I/O DEVICE
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:MEMT,A        ;GET THE MEMORY SPACE ID
        REP     #16             ;SHIFT TO TOP
        LSL     A               ;PUT IN FORMAT FOR OUTPUT ROUTINE
        JSR     OUT2            ;OUTPUT SPACE
        PRTVAL  COLON           ;OUTPUT A COLON
        MOVE    R0,B            ;GET THE ERROR ADDRESS
        JSR     OUTADD          ;OUTPUT THE ADDRESS
        JSR     PRTSPC          ;OUTPUT A SPACE
        MOVE    P:VFMEM,B       ;GET THE MEMORY LOCATION THAT DIDN'T MATCH
        JSR     OUTDAT          ;PRINT IT
        JSR     PRTSPC          ;PRINT A SPACE
        MOVE    #'IN:',A        ;GET 'IN:' MSG TO ID THE INPUT VALUE
        JSR     OUT3            ;OUTPUT THE CHARACTERS
        MOVE    P:VFIN,B        ;GET THE INPUT DATA THAT DIDN'T MATCH
        JSR     OUTDAT          ;OUTPUT THE DATA
        JMP     CMD
;
;       DO "_BLOCKDATA [X,P,Y,L] ADDR RCNT VALUE" TYPE RECORDS
;
_BLKDTA
        JSR     IN2             ;GET NEXT CHARACTER FROM HOST
        MOVE    #'T',X0         ; GET "T"
        CMP     X0,A  
        JNE     _BLKDTA         ;WAIT FOR "T" IN "BLOCKDATA" RECORD
        JSR     HIN1            ;GET "A X", "A Y" OR "A P"
        MOVE    B1,P:MEMT               ;SAVE MEMORY TYPE
        JSR     _DSPLYSP        ;DISPLAY THE MEMORY SPACE
        MOVE    #4,N0           ;NEXT 4 NIBBLES ARE ADDRESS
        JSR     HIN2            ;GET ADDRESS
        MOVE    B1,R0           ;SAVE ADDRESS POINTER
        JSR     HIN2            ;GET REPEAT COUNT
        MOVE    B1,R1           ;SAVE REPEAT COUNT
        MOVE    #6,N0           ;DATA IS 6 NIBBLES LONG
        JSR     HIN2            ;GET DATA
        MOVE    P:MEMT,A        ;GET MEMORY TYPE
        MOVE    #'A X',X0       ;GET CODE FOR X MEMORY
        CMP     X0,A    #'A Y',X0       ;SEE IF X MEMORY, GET Y
        JEQ     _BLKX           ;FILL X MEMORY
        CMP     X0,A    #'A P',X0       ;SEE IF Y MEMORY, GET P
        JEQ     _BLKY           ;FILL Y MEMORY
        CMP     X0,A    #'A L',X0       ;SEE IF P MEMORY, GET L
        JEQ     _BLKP           ;FILL P MEMORY
        CMP     X0,A            ;SEE IF L MEMORY
        JNE     BADXYP          ;NOT P,L,X OR Y
;
;       VERIFY/BLOCK FILL L MEMORY
;
_BLKL
        MOVE    B1,P:TEMP1      ;SAVE X PART OF L MEMORY
        JSR     HIN2            ;GET Y PART OF L MEMORY
        MOVE    B1,P:TEMP2      ;SAVE Y PART OF L MEMORY
        DO      R1,_LFILL       ;DO L MEMORY
        MOVE    P:TEMP1,B       ;GET DATA FOR X MEMORY
        MOVE    P:VFLAG,A       ;GET LOAD/VERIFY FLAG
        TST     A       B1,X1   ;SEE IF ZERO, COPY B
        JEQ     _LBLKX          ;DO FILL OF X MEMORY
        MOVE    X:(R0),B        ;GET X DATA
        CMP     X1,B            ;SEE IF MATCH
        JEQ     _LBLKX          ;YES
        ENDDO                   ;NO, VERIFY ERROR
        JMP     _VFAIL          ;GO TO VERIFY FAIL
_LBLKX
        MOVE    B1,X:(R0)       ;SAVE VALUE IN MEMORY

        MOVE    P:TEMP2,B       ;GET DATA FOR Y MEMORY
        MOVE    P:VFLAG,A       ;GET LOAD/VERIFY FLAG
        TST     A       B1,X1   ;SEE IF ZERO, COPY B
        JEQ     _LBLKY          ;DO FILL OF Y MEMORY
        MOVE    Y:(R0),B        ;GET Y DATA
        CMP     X1,B            ;SEE IF MATCH
        JEQ     _LBLKY          ;YES
        ENDDO                   ;NO, VERIFY ERROR
        JMP     _VFAIL          ;GO TO VERIFY FAIL
_LBLKY
        MOVE    B1,Y:(R0)+      ;SAVE VALUE IN MEMORY
_LFILL
        JMP     USWT            ;GO WAIT FOR UNDERSCORE

;
;       VERIFY/BLOCK FILL P MEMORY
;
_BLKP
        DO      R1,_PFILL       ;FILL P MEMORY
        MOVE    P:VFLAG,A       ;GET LOAD/VERIFY FLAG
        TST     A       B1,X1   ;SEE IF ZERO, COPY B
        JEQ     _PBLK           ;YES, DO BLOCK LOAD
        MOVE    P:(R0),B        ;GET MEMORY VALUE
        CMP     X1,B            ;SEE IF THE SAME
        JEQ     _PBLK           ;YES, CONTINUE
        ENDDO                   ;END DO LOOP AND
        JMP     _VFAIL          ;GO REPORT THE VERIFY FAILURE
_PBLK
        MOVE    B1,P:(R0)+
_PFILL
        JMP     USWT            ;GO GET NEXT RECORD
;
;       VERIFY/BLOCK FILL X MEMORY
;
_BLKX                                                  
        DO      R1,_XFILL       ;FILL X MEMORY
        MOVE    P:VFLAG,A       ;GET LOAD/VERIFY FLAG
        TST     A       B1,X1   ;SEE IF ZERO, COPY B
        JEQ     _XBLK           ;YES, DO BLOCK LOAD
        MOVE    X:(R0),B        ;GET MEMORY VALUE
        CMP     X1,B            ;SEE IF SAME
        JEQ     _XBLK           ;YES, CONTINUE
        ENDDO                   ;EXIT THE DO LOOP
        JMP     _VFAIL          ;REPORT THE VERIFY ERROR
_XBLK
        MOVE    B1,X:(R0)+
_XFILL
        JMP     USWT
;
;       VERIFY/BLOCK FILL Y MEMORY
;
_BLKY
        DO      R1,_YFILL       ;FILL Y MEMORY
        MOVE    P:VFLAG,A       ;GET THE LOAD/VERIFY FLAG
        TST     A       B1,X1   ;SEE IF ZERO, COPY B
        JEQ     _YBLK           ;YES, LOAD Y BLOCK
        MOVE    Y:(R0),B        ;GET MEMORY VALUE
        CMP     X1,B            ;SEE IF SAME
        JEQ     _YBLK           ;YES, CONTINUE
        ENDDO                   ;END THE DO LOOP
        JMP     _VFAIL          ;REPORT THE VERIFY ERROR
_YBLK
        MOVE    B1,Y:(R0)+      ;SAVE DATA IN Y MEMORY
_YFILL
        JMP     USWT
;
;       DO "_END ADDR" RECORDS. THE P ADDRESS IS USED TO INITIALIZE
;       THE USER PC. GIVING A "P" COMMAND WILL START THE PROGRAM AT THE
;       ADDRESS GIVEN IN THE _END DIRECTIVE.
;
_DOEND
        JSR     IN2             ;GET NEXT CHARACTER
        MOVE    #SPACE,X0       ;GET A SPACE
        MOVE    P:USR_PC,B      ;GET CURRENT PC
        CMP     X0,A            ;SEE IF NEXT CHARACTER AFTER "END" IS A SPACE
        JNE     _NOADDR         ;NO, MUST BE NO ADDRESS ON END RECORD
        MOVE    #4,N0           ;SET TO GET 4 NIBBLE STARTING ADDRESS
        JSR     HIN2            ;GET START ADDRESS
        MOVE    B1,P:USR_PC     ;SAVE INITIAL USER PC
_NOADDR
        JSR     SET_TERM        ;SET TERMINAL AS I/O DEVICE
        JSR     CRLF            ;OUTPUT <CR><LF>
        MOVE    #'PC=',A1       ;MSG FOR USER
        JSR     OUT3            ;PRINT MSG
        JSR     OUTADD          ;OUTPUT DEFAULT PC
        JMP     CMD             ;GO TO COMMAND LEVEL
_DSPLYSP
        JSR     SET_TERM        ;SET TERMINAL AS I/O DEVICE
        MOVE    P:MEMT,A        ;GET MEMORY SPACE INDICATOR
        JSR     OUT1            ;OUTPUT THE MEMORY SPACE TO USER
        JSR     SET_HOST        ;SET HOST AS I/O DEVICE

        RTS
BADXYP
        JSR     SET_TERM                ;SET TERMINAL FOR I/O
        MOVE    #BADREC,R0              ;BAD RECORD MSG
        JSR     OUT5
        JMP     CMD
;
;       HOST I/O ROUTINES
;
;       READ 3 CHARACTERS, MASK PARITY AND PACK INTO B1
;
HIN1
        CLR     A                       ;DO NOT WANT LIMITS
        CLR     B       #>$7F,X1        ;CLEAR B, GET PARITY MASK
        DO      #3,_L1                  ;3 CHARACTERS
        JSR     IN1                     ;INPUT CHARACTER INTO A1
        AND     X1,A                    ;MASK PARITY
        REP     #8                      ;SHIFT OTHER BYTES
        LSL     B
        ADD     A,B                     ;ADD IN NEW BYTE
_L1
        RTS
;
;       HIN2 - READ A VARIABLE AMOUNT OF ASCII HEX (SPECIFIED BY N0) AND
;               CONVERT TO A VALUE IN B1.
;               IF A UNDERSCORE IS DETECTED, CONTROL IS PASSED BACK TO
;               THE RECORD PARSING ROUTINE.
;
HIN2
        CLR     A
        CLR     B       #0,R7   ;NIBBLE COUNT
        DO      N0,_L1          ;NUMBER OF ASCII BYTES TO GET
_L3
        JSR     IN1             ;GET CHARACTER FROM HOST
        MOVE    #>$7F,X0        ;PARITY MASK
        AND     X0,A  #>$5F,X1  ;MASK PARITY, GET UNDERSCORE
        CMP     X1,A  #>$30,X1  ;SEE IF UNDERSCORE, GET 0
        JNE     _L2             ;NOT UDERSCORE
        ENDDO                   ;CLEAN OFF LOOP
        MOVE    SP,R0           ;GET CURRENT STACK POINTER
        NOP                     ;CLEAR PIPE
        MOVE    (R0)-           ;CLEAN OFF RETURN ADDRESS
        MOVE    R0,SP           ;SET NEW STACK POINTER
        JMP     GOTUS           ;GOT AN UNDERSCORE, GO GET REST OF RECORD
_L5
        MOVE    R7,A            ;GET NIBBLE COUNT
        TST     A               ;SEE IF NO NIBBLES YET
        JEQ     _L3             ;NO NIBBLES, KEEP SEARCHING
        ENDDO                   ;WE HAVE NIBBLES, TAKE AS DELIMITER
        RTS                     ;RETURN WITH PARTIAL NUMBER
_L2
        CMP     X1,A    #>$39,X1        ;SEE IF LESS THAN 0, GET 9
        JLT     _L5                     ;NOT ASCII HEX
        CMP     X1,A    #>$41,X1        ;SEE IF 0-9, GET "A"
        JLE     _L4                     ; IT IS 0-9
        CMP     X1,A    #>$46,X1        ;SEE IF LESS THAN "A", GET "F"
        JLT     _L5                     ;LESS THAN A
        CMP     X1,A    #>$07,X1        ;SEE IF A-F, GET SHIFT
        JGT     _L5                     ;NO ABOVE F
        SUB     X1,A                    ;SHIFT A-F
_L4
        MOVE    #>$30,X1                ;GET 0
        SUB     X1,A                    ;CONVERT TO NYBBLE
        REP     #4                      ;SHIFT OTHER NIBBLES
        LSL     B
        ADD     A,B     (R7)+           ;ADD CURRENT NYBBLE TO OTHER NIBBLES
_L1
        RTS
        PAGE
;
;       HEL     HELP COMMAND
;
HELP
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    #CMDTBL+3,R1    ;POINT TO COMMAND TABLE
        DO      #CMDTBLLEN-1,_EH        ;OUTPUT COMMANDS
        MOVE    P:(R1)+,A               ;GET COMMAND TEXT
        JSR     OUT3            ;OUTPUT COMMAND NAME
        JSR     PRTSPC          ;OUTPUT A SPACE
        MOVE    (R1)+           ;SKIP COMMAND ADDRESS
        MOVE    P:(R1)+,R0      ;POINT TO HELP MSG
        JSR     OUT5            ;OUTPUT MESSAGE
        JSR     CRLF            ;OUTPUT CR,LF
_EH
        JMP     CMD             ;RETURN TO COMMAND LEVEL
        PAGE
;
;       FIL <[X,Y,P]>:<ADD1> <ADD2> [VALUE]
;
;       FILL X,Y OR P MEMORY FROM ADD1 TO ADD2 WITH VALUE.
;       AND VERIFY THE WRITE OPERATION.  THIS WILL SAVE THE
;       LOCATION N+1, THEN WRITE THE COMPLEMENT INTO THE DATA AT N+1
;       BEFORE READING N.  THIS IS BECAUSE THE OUTPUT DATA WILL BE
;       HELD INTERNALLY IN THE CHIP AND THE COMPLEMENT WILL CHANGE IT.
;
FILL
        JSR     GETPXY          ;GET MEMORY SPACE AND ADDRESS
        MOVE    B1,R2           ;SAVE STARTING ADDRESS
        PRTVAL  DASH            ;OUTPUT DASH
        JSR     INADD           ;GET ENDING ADDRESS
        MOVE    A,Y0            ;SAVE DELIMITER
        MOVE    R2,A            ;GET THE STARTING ADDRESS
        SUB     A,B     #>1,X0  ;FIND TOTAL NUMBER OF WORDS TO FILL
        ADD     X0,B            ;INC TOTAL NUMBER 
        MOVE    B1,N2           ;SAVE NUMBER OF WORDS TO FILL
        MOVE    #CR,A           ;GET VALUE FOR CR
        CMP     Y0,A            ;SEE IF DELIMITER IS CR
        JNE     _NOTCR          ;NO
        CLR     B               ;DEFAULT OF ZERO
        JMP     _FILLIT         ;DO FILL
_NOTCR
        JSR     PRTSPC          ;PUT A SPACE AFTER SECOND ADDRESS
        JSR     INDAT           ;GET DATA VALUE
_FILLIT
        MOVE    B1,P:TEMP1      ;SAVE INPUT VALUE
        DO      N2,_L2          ;MEMORY SCAN LOOP
        MOVE    P:TEMP1,B       ;GET DATA TO SAVE
        MOVE    B,X1            ;COPY DATA TO SAVE
        JSR     SETMEM          ;SAVE IN MEMORY, POINT TO N+1
        JSR     GETMEM          ;GET N+1, POINT TO N+2
        MOVE    B,P:TEMP2       ;SAVE VALUE OF N+1
        NOT     B       (R2)-   ;COMPLEMENT DATA OF N+1, POINT TO N+1
        JSR     SETMEM          ;WRITE COMPLEMENT OF N+1
        MOVE    (R2)-           ;POINT TO N+1
        MOVE    (R2)-           ;POINT TO N
        JSR     GETMEM          ;GET THE CONTENTS OF N, POINT TO N+1
        CMP     X1,B            ;SEE IF A MATCH
        JEQ     _L1             ;YES
        JSR     CRLF            ;NO MATCH
        MOVE    #'ERR',A
        JSR     OUT3            ;OUTPUT ROM MSG
        MOVE    (R2)-           ;POINT TO ADDRESS N
        JSR     PRTSPC          ;PRINT A SPACE
        MOVE    R2,B            ;GET ERROR ADDRESS
        JSR     OUTADD          ;PRINT IT OUT
        MOVE    (R2)+           ;POINT TO N+1
_L1
        MOVE    P:TEMP2,B       ;GET DATA FOR N+1
        JSR     SETMEM          ;RESTORE IT, POINT TO N+2
        MOVE    (R2)-           ;POINT TO N+1 FOR NEXT PASS
_L2
        JMP     CMD             ;RETURN TO COMMAND LEVEL
        PAGE
;
;       DST     DISPLAY USER STACK
;
STACK_D
        JSR     CRLF
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        MOVE    #>$10,X0                ;MASK FOR SE BIT
        AND     X0,A    #0,B            ;SEE IF STACK ERROR BIT IS SET, 0 B
        JNE     NGUSRSTK                ;STACK ERROR BIT IS SET
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        TST     A               ;SEE IF USER STACK IS MT
        JNE     _NOTMT          ;NO
        MOVE    #STKMT,R0       ;POINT TO MT MSG
        JSR     OUT5            ;OUTPUT MSG
        JMP     CMD             ;RETURN TO COMMAND LEVEL
_NOTMT
        MOVE    #SHLM,R0        ;GET MESSAGE
        JSR     OUT5
        MOVE    #>1,R0          ;SAVE AS COUNT
        MOVE    #USTK+30,R4     ;GET POINTER TO LAST ELEMENT IN SAVED STACK
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        DO      A1,_EPRT        ;PRINT STACK
        MOVE    R0,B            ;GET COUNT
        JSR     OUTBYTE         ;OUTPUT COUNT
        JSR     PRTSPC          ;OUTPUT SPACE
        MOVE    P:-(R4),B       ;GET SSH
        JSR     OUTADD          ;PRINT IT
        JSR     PRTSPC          ;PRINT SPACE
        MOVE    P:-(R4),B       ;GET SSL
        JSR     OUTADD          ;PRINT IT
        MOVE    (R0)+           ;INCREMENT COUNT
        JSR     CRLF            ;DO CR,LF
_EPRT
        JMP     CMD             ;GO TO COMMAND LEVEL
        PAGE
;
;       STK      EDIT USER STACK
;       SUBCOMMANDS AFTER THE REGISTER IS DISPLAYED:
;       CTRL/Y          EXIT
;       <SP>            CHANGE STACK LOCATION
;       <CR>            NEXT STACK LOCATION
;       ^               PREVIOUS STACK LOCATION
;
STACK_E
        JSR     CRLF
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        MOVE    #>$10,X0                ;MASK FOR SE BIT
        AND     X0,A    #0,B            ;SEE IF STACK ERROR BIT IS SET, 0 B
        JNE     NGUSRSTK                ;STACK ERROR BIT IS SET
        MOVE    P:USR_SP,A      ;GET USER STACK POINTER
        TST     A                       ;SEE IF STACK IS MT
        JNE     _NOTMT                  ;NO
        MOVE    #STKMT,R0               ;GET STACK MT MSG
        JSR     OUT5                    ;PRINT IT
        JMP     CMD
_NOTMT
        MOVE    #USTK+30,R4             ;END OF STACK (SSH-1)
        MOVE    #>1,R5                  ;COUNT
        MOVE    (R4)-                   ;ADJUST POINTER 
_DSPLY
        JSR     CRLF
        MOVE    R5,B                    ;GET COUNT
        MOVE    #>1,X0                  ;GET A 1
        ADD     X0,B                    ;INC COUNT
        ASR     B                       ;AND DIVDE BY 2
        JSR     OUTBYTE                 ;PRINT OUT CURRENT STACK LOCATION
        JSR     PRTSPC
        MOVE    R5,B                    ;GET THE COUNT AGAIN
        MOVE    #'SSH',A                ;ASSUME IT IS SSH
        MOVE    #>1,X0                  ;GET A 1
        AND     X0,B    #'SSL',X1       ;SEE IF COUNT IS ODD OR EVEN
        TEQ     X1,A                    ;IF EVEN IT IS SSL
        JSR     OUT3                    ;PRINT IT
        MOVE    #' = ',A                ;GET EQUAL SIGN
        JSR     OUT3                    ;OUTPUT IT
        MOVE    P:(R4),B                ;GET SSH OR SSL
        JSR     OUTADD                  ;OUTPUT IT
        JSR     IN2                     ;GET INPUT
        MOVE    #SPACE,X0               ;GET SPACE
        CMP     X0,A    #CR,X0          ;SEE IF SPACE
        JEQ     _CHANGE                 ;YES, CHANGE IT
        CMP     X0,A    #CTRLY,X0       ;SEE IF CR
        JEQ     _NEXT                   ;YES, GO TO NEXT
        CMP     X0,A    #'^',X0         ;SEE IF EXIT
        JEQ     CMD                     ;YES, EXIT
        CMP     X0,A    #CTRLC,X0       ;SEE IF UP ARROW
        JEQ     _PREV                   ;YES, DO PREVIOUS
        CMP     X0,A                    ;SEE IF CTRLC
        JEQ     CMD                     ;YES, EXIT
        MOVE    #OPTMSG,R0      ;GET OPTION ERROR MESSAGE
        JSR     OUT5
        JMP     _DSPLY
_CHANGE
        MOVE    #'  >',A                ;GET PROMPT
        JSR     OUT3                    ;PRINT IT
        JSR     INADD                   ;GET NEW DATA
        MOVE    A,Y0                    ;SAVE DELIMITER
        MOVE    R7,A                    ;GET CHARACTER COUNT
        TST     A                       ;CHECK CHARACTER COUNT
        JEQ     _NEXT                   ;NO DEPOSIT
        MOVE    B,P:(R4)                ;SAVE NEW DATA
        MOVE    #'^',A                  ;GET UP ARROW
        CMP     Y0,A                    ;SEE IF DELIMITER IS UP ARROW
        JEQ     _PREV                   ;YES
_NEXT
        MOVE    (R5)+
        MOVE    (R4)-                   ;POINT TO NEW DATA
        MOVE    P:USR_SP,A              ;GET USER STACK POINTER
        ASL     A       R5,X0           ;MUL BY 2, GET COUNT
        CMP     X0,A                    ;COMPARE TO STACK POINTER
        JLT     _PREV                   ;BACKUP IF TOO FAR
        JMP     _DSPLY
_PREV
        MOVE    (R5)-                   ;BACK UP COUNT
        MOVE    (R4)+                   ;BACK UP MEMORY POINTER
        MOVE    R5,A                    ;GET COUNT
        TST     A                       ;SEE IF ZERO
        JEQ     _NOTMT                  ;YES, RESET POINTERS
        JMP     _DSPLY                  ;JUST DO DISPLAY OF PREVIOUS
        PAGE
;
;       STKERR          ENTRY POINT IF A STACK EXCEPTION OCCURS
;
STKERR
        ORI     #$03,MR                 ;SET MONITOR IPL TO 3
        MOVE    SP,P:USR_SP             ;STACK POINTER
        MOVEP   X:BCR,P:USR_BCR         ;GET USER BCR
        MOVEP   #DSP_BCR,X:BCR          ;SET DSP BCR
        IF      EXETMR
        JCLR    #0,Y:STOP_CTR,*+2       ;STOP EXECUTION TIMER
        ENDIF
        MOVEP   X:IPR,P:USR_IPR         ;GET INTERRUPT PRIORITY REGISTER
        MOVE    P:IODEV,X0              ;GET CURRENT USER I/O DEVICE
        MOVE    X0,P:USR_DEV            ;SAVE IT
        MOVE    #15,SP                  ;SET STACK POINTER TO DUMP
;
;       SAVE THE CURRENT STACK
;
        MOVE    #USTK,R4                ;USER STACK AREA
        MOVE    #<15,A                  ;NUMBER OF LEVELS TO PULL OFF
        MOVE    #<1,X0                  ;COUNTER
_SAVSTK
        MOVE    SSL,P:(R4)+             ;GET LOW PART OF STACK
        MOVE    SSH,P:(R4)+             ;GET HIGH PART OF STACK
        SUB     X0,A                    ;DECREMENT COUNT
        JNE     _SAVSTK                 ;NOT DONE
;
;       CLEANUP AND REPORT ERROR
;
        MOVE    #0,SP           ;RESET STACK POINTER
        JSR     RES_UOPS        ;RESTORE USER'S OPCODES
        JSR     SET_TERM        ;SET TERMINAL FOR I/O
        MOVE    #STKUNDER,R0    ;POINT TO STACK UNDERFLOW ERROR MESSAGE
        MOVE    P:USR_SP,A      ;GET STACK POINTER
        MOVE    #>$000020,X0    ;MASK FOR UNDERFLOW FLAG
        AND     X0,A            ;SEE IF UNDERFLOW
        JNE     _UNDER          ;YES, UNDERFLOW
        MOVE    #STKOVER,R0     ;POINT TO OVERFLOW MESSAGE
_UNDER
        JSR     OUT5            ;PRINT IT
;
;       DUMP THE STACK
;
        MOVE    #SHLM,R0        ;GET MESSAGE
        JSR     OUT5
        MOVE    #>1,R0          ;SET COUNT
        MOVE    #USTK+30,R4     ;GET POINTER TO LAST ELEMENT IN SAVED STACK
        DO      #15,_EPRT       ;PRINT STACK
        MOVE    R0,B            ;GET COUNT
        JSR     OUTBYTE         ;OUTPUT COUNT
        JSR     PRTSPC          ;OUTPUT SPACE
        MOVE    P:-(R4),B       ;GET SSH
        JSR     OUTADD          ;PRINT IT
        JSR     PRTSPC          ;PRINT SPACE
        MOVE    P:-(R4),B       ;GET SSL
        JSR     OUTADD          ;PRINT IT
        MOVE    (R0)+           ;INCREMENT COUNT
        JSR     CRLF            ;DO CR,LF
_EPRT

        JMP     CMD             ;GO TO COMMAND LEVEL
        PAGE
;
;       DISPLAY REGISTERS IN A HORIZONTAL FORMAT.  IF A REGISTER
;       HAS CHANGED, PRINT A STAR AFTER THE EQUAL SIGN
;
DMPREG
        MOVE    #REGLST+25,R0   ;REGISTER NAMES
        MOVE    #REGVAL+25,R4   ;REGISTER VALUES
        MOVE    #REGOLD+25,R1   ;OLD REGISTERS
        MOVE    #REGLEN+25,R5   ;LENGTH IN NIBBLES
        MOVE    #REGSHFT+25,R3  ;SHIFT
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    #OFFTBL,R7      ;POINT TO OFFSETS TO NEXT REGISTER
        DO      #8,_E2          ;NUMBER OF ROWS IN OUTPUT
        MOVE    P:(R7)+,A1      ;GET NUMBER OF SPACES TO PAD
        DO      A1,_EFP         ;DO FIELD PAD
        JSR     PRTSPC          ;OUTPUT SPACES
_EFP
        MOVE    P:(R7)+,A1      ;GET NUMBER OF COLUMNS
        DO      A1,_E1          ;OUTPUT REGS
        MOVE    P:(R0),A        ;GET REG NAME
        JSR     OUT3            ;OUTPUT IT
        PRTVAL  EQUAL           ;PRINT EQUAL SIGN
        MOVE    P:(R4),A        ;GET CURRENT REGISTER
        MOVE    P:(R1),X0       ;GET SAVED REGISTER
        CMP     X0,A            ;COMPARE
        JEQ     _SAME           ;NO CHANGE
        PRTVAL  STAR            ;PRINT A STAR
        JMP     _CONT
_SAME
        JSR     PRTSPC          ;PRINT A SPACE
_CONT
        JSR     OUTREG          ;OUTPUT THE REGISTER            
        MOVE    #>7,A           ;GET PAD LENGTH
        MOVE    P:(R5),X0       ;GET LENGTH IN NIBBLES
        SUB     X0,A            ;GET PAD ADJUSTMENT
        DO      A1,_PAD         ;PAD WITH SPACES TO NEXT COLUMN
        JSR     PRTSPC          ;PRINT A SPACE
_PAD
        MOVE    P:(R7)+,N0      ;GET ADJUSTMENT FOR NEXT REGISTER
        MOVE    N0,N3           ;ALL ADJUSTMENTS ARE THE SAME
        MOVE    N0,N1
        MOVE    N0,N4
        MOVE    N0,N5
        MOVE    X:(R0)+N0,X0  Y:(R4)+N4,Y0      ;ADJUST POINTERS
        MOVE    X:(R3)+N3,X0  Y:(R5)+N5,Y0
        MOVE    (R1)+N1
_E1
        JSR     CRLF            ;OUTPUT CR,LF
_E2
        RTS
        PAGE    
;
;       DTP [DRV]       DEFINE TERMINAL PORT
;                       1 - DUART A
;                       2 - DUART B
;                       3 - DSP SCI
;                       4 - DSP HOST PORT
;
DTP
        JEQ     _CR             ;IF CR, DISPLAY
        JSR     INDAT           ;GET DEVICE CODE
        MOVE    R7,A            ;GET CHARACTER COUNT
        TST     A
        JEQ     _CR             ;NO INPUT,DISPLAY DEVICE CODE
        MOVE    B1,P:TDEV       ;SET THE TERMINAL DEVICE
        MOVE    B1,P:IODEV      ;SET THE CURRENT I/O DEVICE
        JSR     DEV_INIT        ;INITIALIZE THE DEVICE
_CR
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:TDEV,B        ;GET THE HOST DEVICE
        JSR     OUTDAT          ;OUTPUT DEVICE
        MOVE    P:TDEV,X0       ;GET DEVICE CODE
        JMP     DSPNAME         ;GO DISPLAY DEVICE NAME
;
;       SUBROUTINE FOR USER TO DEFINE A DIFFERENT DEVICE FOR THE TERMINAL PORT
;
DEFINE_TERM
        MOVE    B1,P:TDEV       ;SET TERMINAL DEVICE
        JMP     DEV_INIT        ;INITIALIZE THE DEVICE AND RETURN
;
;       DISPLAY DEVICE NAME
;
DSPNAME
        JSR     PRTSPC          ;PRINT A SPACE FIRST
        MOVE    #IOTBL,R0       ;POINT TO IO TABLE
        DO      #IOTBLLEN,_E1   ;SEARCH TABLE FOR DEVICE IN X0
        MOVE    P:(R0)+,A       ;GET DEVICE CODE
        CMP     X0,A            ;SEE IF A MATCH
        JNE     _NO             ;NO
        ENDDO
        MOVE    P:(R0),A        ;GET DEVICE NAME
        JSR     OUT3            ;PRINT IT
        JMP     CMD             ;RETURN TO COMMAND LEVEL
_NO
        MOVE    (R0)+           ;ADJUST POINTER
        MOVE    (R0)+           ;ADJUST POINTER
        MOVE    (R0)+           ;ADJUST POINTER
        MOVE    (R0)+           ;ADJUST POINTER
_E1
        JMP     CMD             ;RETURN TO COMMAND LEVEL
        PAGE
;
;       DHP [DRV]       DEFINE HOST PORT
;                       1 - DUART A
;                       2 - DUART B
;                       3 - DSP SCI
;                       4 - DSP HOST PORT
;
DHP
        JEQ     _CR             ;IF CR DELIMITER, DISPLAY
        JSR     INDAT           ;GET DEVICE CODE
        MOVE    R7,A            ;GET CHARACTER COUNT
        TST     A
        JEQ     _CR             ;DISPLAY INPUT
        MOVE    B1,P:HDEV       ;SET THE HOST DEVICE
        JSR     DEV_INIT        ;INITIALIZE THE DEVICE
_CR
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:HDEV,B        ;GET THE HOST DEVICE
        JSR     OUTDAT          ;OUTPUT DEVICE
        MOVE    P:HDEV,X0       ;GET HOST DEVICE
        JMP     DSPNAME         ;GO DISPLAY ITS NAME
;
;       SUBROUTINE FOR USER TO CHANGE HOST PORT TO A DIFFERENT DEVICE
;
DEFINE_HOST
        MOVE    B1,P:HDEV       ;SAVE THE HOST DEVICE
        JMP     DEV_INIT        ;INIT DEVICE AND RETURN TO USER
        PAGE
;
;       INITALIZE THE DEVICE IN REG B
;
DEV_INIT
        JSR     IOSET           ;SET UP FOR I/O, POINT TO I/O TABLE
        DO      #IOTBLLEN,_ESET ;FIND DEVICE
        MOVE    P:(R0)+,X0      ;GET DEVICE CODE
        CMP     X0,B    (R0)+   ;SEE IF THIS DEVICE
        MOVE    (R0)+           ;ADJUST POINTER
        MOVE    (R0)+           ;ADJUST POINTER
        JNE     _NO             ;NO MATCH
        ENDDO                   ;A MATCH, CLEAN UP LOOP
        MOVE    P:(R0),R0       ;GET ADDRESS OF DEVICE SET UP ROUTINE
        NOP                     ;CLEAR PIPE
        JSR     (R0)            ;EXECUTE ROUTINE
        JMP     RESX0R0         ;RESTORE REGISTERS AND RETURN
_NO
        MOVE    (R0)+           ;INCREMENT TO NEXT DRIVER
_ESET
        JMP     RESX0R0         ;RESTORE REGISTERS AND RETURN
        PAGE
;
;       UPL <[P,X,Y]>:<ADD1><ADD2> <[O,D]>
;               TRANSFER MEMORY TO HOST PORT.  THIS IS USED TO DUMP
;               BLOCKS OF DATA TO THE HOST USING CTRL/Q/S PROTOCOL.
;
UPLOAD
        JSR     GETPXY          ;GET MEMORY SPACE AND STARTING ADDRESS
        MOVE    B1,R2           ;SAVE STARTING ADDRESS
        PRTVAL  DASH            ;PRINT OUT DASH
        JSR     INADD           ;GET ENDING ADDRESS
        MOVE    B1,R4           ;SAVE ENDING ADDRESS
        MOVE    R2,A            ;COPY STARTING ADDRESS
        SUB     A,B     #>1,X0  ;FIND LENGTH OF TRANSFER
        ADD     X0,B            ;ADJUST LENGTH
        MOVE    B1,N2           ;SAVE LENGTH
        JSR     PRTSPC          ;PRINT A SPACE

        JSR     IN3UC           ;GET UPLOAD FORMAT
        MOVE    #'D',X0         ;GET D
        CMP     X0,A    #'O',X0 ;SEE IF 'DATA' FORMAT
        JEQ     _DATA_F         ;YES                 
        CMP     X0,A            ;SEE IF 'OMF' FORMAT
        JEQ     _DATA_OMF       ;YES
        MOVE    #BADFMT,R0      ;BAD FORMAT
        JSR     OUT5
        JMP     CMD
_DATA_OMF
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:MEMT,X0       ;GET MEMORY SPACE
        JSR     UP_OMF          ;UPLOAD IN OMF FORMAT
        JMP     CMD
_DATA_F
        JSR     CRLF            ;OUTPUT CR,LF
        MOVE    P:MEMT,X0       ;GET MEMORY SPACE
        JSR     UP_DATA         ;UPLOAD IN DATA FORMAT
        JMP     CMD
;
;       EXIT UPLOAD COMMAND
;
CLEANUP
        JSR     SET_TERM        ;SET TERMINAL AS I/O DEVICE
        RTS
;
;       UPLOAD OMF RECORDS.
;       PARAMETERS:
;               X0 - MEMORY TYPE: X,Y OR P IN TOP BYTE OF X0
;               R2 - STARTING ADDRESS
;               N2 - LENGTH OF TRANSFER
;               M2 - LINEAR
;
UP_OMF
        MOVE    X0,P:MEMT       ;SAVE MEMORY TYPE
        JSR     SET_HOST        ;SET HOST DEVICE FOR I/O
        MOVE    R2,R3           ;COPY STARTING ADDRESS
        MOVE    #'_DA',A        ;PRINT "_DATA..." RECORD
        JSR     OUT3            ;PRINT "_DA"
        MOVE    #'TA ',A
        JSR     OUT3            ;PRINT "TA "
        MOVE    P:MEMT,A        ;GET MEMORY SPACE
        JSR     OUT2            ;PRINT IT
        JSR     PRTSPC          ;OUTPUT A SPACE
        MOVE    R2,B            ;GET STARTING ADDRESS
        JSR     OUTADD          ;OUTPUT ADDRESS
        PRTVAL  CR              ;SEND CR AFTER RECORD
        JSR     UPASCII         ;DO ASCII UPLOAD
        MOVE    #'_EN',A        ;PRINT OUT END DIRECTIVE
        JSR     OUT3            ;PRINT "_EN"
        PRTVAL  $44             ;PRINT "D"
        JSR     PRTSPC          ;PRINT SPACE
        MOVE    R3,B            ;GET START OF BLOCK
        JSR     OUTADD          ;OUTPUT THE ADDRESS
        PRTVAL  CR              ;PRINT A <CR>
        JMP     CLEANUP         ;CLEAN UP AND EXIT
;
;       UPLOAD IN DATA FORMAT.
;       PARAMETERS:
;               X0 - MEMORY TYPE: X,Y OR P IN TOP BYTE OF X0
;               R2 - STARTING ADDRESS OF TRANSFER
;               N2 - LENGTH OF TRANSFER
;               M2 - LINEAR
;
UP_DATA
        MOVE    X0,P:MEMT       ;SAVE MEMORY TYPE
        JSR     SET_HOST        ;SET HOST DEVICE FOR I/O
        JSR     UPASCII         ;DO ASCII UPLOAD
        JMP     CLEANUP         ;CLEANUP AND EXIT
;
;       ASCII UPLOAD ROUTINE FOR OMF AND DATA FORMATS
;
UPASCII
        DO      N2,_EOUT        ;OUTPUT DATA
        JSR     GETMEM          ;GET THE MEMORY
        JSR     OUTDAT          ;OUTPUT DATA
        PRTVAL  CR              ;OUTPUT CR
_EOUT
        RTS
        PAGE
;
;       NBR [#BRKS]     SET/DISPLAY NUMBER OF BREAKPOINTS BEFORE STOPPING
;
;       THIS ROUTINE IS USED TO SET/DISPLAY THE NUMBER OF BREAKPOINTS
;       TO BE EXECUTED BEFORE STOPPING
;
NBREAKS
        JEQ     _DISP           ;IF CR, DO DISPLAY
        JSR     INADD           ;GET NUMBER
        MOVE    R7,A            ;GET NUMBER OF INPUT NIBBLES
        TST     A               ;SEE IF ZERO
        JEQ     _DISP           ;JUST DISPLAY
        MOVE    B,P:NBRVAL      ;SAVE VALUE
_DISP
        MOVE    #BRCTM,R0       ;POINT TO MESSAGE
        JSR     OUT5            ;OUTPUT MESSAGE
        MOVE    P:NBRVAL,B      ;GET NUMBER OF BREAKS BEFORE STOPPING
        JSR     OUTADD          ;OUTPUT IT
        JSR     CRLF            ;OUTPUT CR,LF
        JMP     CMD             ;RETURN TO COMMAND LEVEL
        PAGE                
;
;       ROUTINE TO ALLOW USER TO ADD HIS OWN COMMANDS TO COMMAND TABLE
;       INPUTS: A  = 3 CHARACTER COMMAND NAME
;               R7 = COMMAND ADDRESS
;               M7 = COMMAND HELP MESSAGE ADDRESS
;
ADDCMD
        MOVE    R0,P:R0SAVE     ;SAVE R0
        MOVE    #CMDTBL,R0      ;POINT TO COMMAND TABLE
        MOVE    #'***',X0       ;UNUSED COMMAND NAME
        DO      #CMDTBLLEN,_ES  ;SEARCH COMMAND TABLE FOR EMPTY SLOT
        MOVE    P:(R0),B        ;GET COMMAND NAME
        CMP     X0,B            ;SEE IF MT
        JNE     _NO             ;NO
        ENDDO                   ;WE HAVE SPACE
        MOVE    A1,P:(R0)+      ;SAVE COMMAND NAME
        MOVE    R7,P:(R0)+      ;SAVE COMMAND ENTRY POINT
        MOVE    M7,P:(R0)       ;SAVE HELP MESSAGE ADDRESS
        JMP     RESX0R0         ;RESTORE REGISTERS AND RETURN
_NO
        MOVE    (R0)+           ;MOVE TO COMMAND ADDRESS
        MOVE    (R0)+           ;MOVE TO COMMAND HELP ADDRESS
        MOVE    (R0)+           ;MOVE TO NEXT COMMAND ENTRY
_ES
        JMP     RESX0R0         ;RESTORE REGISTERS AND RETURN
        PAGE
;
;       DHE     COMMAND TO LET THE USER SPECIFY/DISPLAY THE
;               CHARACTER USED TO EXIT THE 'HST' COMMAND.
;       DHE<CR> DISPLAY THE VALUE
;       DHE<SP> CHANGE THE VALUE AND THEN DISPLAY IT FOR VERIFICATION
;
HEXIT
        JEQ     _DISPLAY        ;DISPLAY THE VALUE IF DELIMITER IS <CR>
        MOVE    #HEX1M,R0       ;POINT TO MSG
        JSR     OUT5            ;OUTPUT PROMPT
        JSR     IN1             ;GET CHARACTER
        MOVE    #>$7F,X0        ;GET PARITY MASK    
        AND     X0,A            ;MASK PARITY
        MOVE    A1,P:HST_EXIT   ;SAVE THE EXIT CHARACTER
_DISPLAY
        MOVE    #HEX2M,R0       ;POINT TO MSG
        JSR     OUT5            ;MESSAGE FOR DISPLAY
        MOVE    P:HST_EXIT,B    ;GET THE EXIT CHARACTER
        JSR     OUTBYTE         ;OUTPUT THE CHARACTER VALUE
        JMP     CMD             ;RETURN TO COMMAND LEVEL
        PAGE
;
;       OFF      SHUT OFF MULTIBOARD MODE.  IF MULTIBOARD IS ENABLED, THIS
;               ROUTINE WILL DISABLE THE MULTIBOARD MODE BY PUTTING THE EXP
;               BOARD INTO A LOOP TO LOOK FOR ITS ADDRESS.  
;               IF A CTRL/W IS RECEIVED (WAKE UP) FOLLOWED BY THE ADDRESS
;               OF THE BOARD, CONTROL WILL RETURN TO THE COMMAND LEVEL.
;
MDOFF
        JSR     CKMBRD                  ;SEE IF MULTIBOARD
        JEQ     _MDON                   ;MULTIBOARD ON
        MOVE    #MDOFFMSG,R0            ;POINT TO MESSAGE
        JSR     OUT5
        JMP     CMD
_MDON
        JSR     SET_TERM                ;SET TERMINAL AS I/O DEVICE
_WT
        JSR     IN2                     ;GET CHARACTER
        MOVE    #CTRLW,X0               ;GET WAKE CHARACTER
        CMP     X0,A                    ;SEE IF MATCH
        JNE     _WT
_WT2
        JSR     IN2                     ;GET WAKE ADDRESS
        MOVE    #CTRLW,X0               ;GET CTRL/W
        CMP     X0,A    #'0',X0         ;SEE IF CTRL/W
        JEQ     _WT2                    ;YES
        SUB     X0,A    #$A,X0          ;SHIFT FOR ASCII TO HEX
        CMP     X0,A    #7,X0           ;SEE IF GREATER THAN 10
        JLT     _ZN                     ;NO
        SUB     X0,A                    ;ADJUST FOR A-F
_ZN
        MOVE    P:MDADD,X0              ;GET MULTIDROP ADDRESS
        REP     #16                     ;SHIFT DOWN INPUT
        ASR     A
        CMP     X0,A                    ;SEE IF ADDRESS MATCHES
        JEQ     RSTMSG                  ;YES
        JMP     _WT                     ;NO
        PAGE
;
;       CALCULATE - 4 FUNCTION HEX CALCULATOR
;       CAL <NUMBER1> <[+,-,*,/,.]> <NUMBER2>
;
CALCULATE
        JSR     INDAT                   ;GET FIRST ARGUMENT
        MOVE    B1,P:TEMP1              ;SAVE IT
        JSR     PRTSPC
        JSR     IN3                     ;GET FUNCTION
        MOVE    #'+',X0 
        CMP     X0,A    #'-',X0         ;SEE IF ADD
        JEQ     _ADD                    ;YES
        CMP     X0,A    #'*',X0         ;SEE IF SUBTRACT
        JEQ     _SUB                    ;YES
        CMP     X0,A    #'/',X0         ;SEE IF MULTIPLY
        JEQ     _MUL                    ;YES
        CMP     X0,A    #'.',X0         ;SEE IF DIVIDE
        JEQ     _DIV                    ;YES
        CMP     X0,A                    ;SEE IF POINT
        JEQ     _FRAC                   ;YES
        MOVE    #CALOPT,R0              ;POINT TO MESSAGE
        JSR     OUT5                    ;PRINT IT
        JMP     CMD
_ADD
        JSR     _NXTPRM                 ;GET NEXT PARAMETER
        ADD     X0,B                    ;ADD
_OUT
        JSR     OUTDAT                  ;OUTPUT RESULT FROM B1
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
_SUB
        JSR     _NXTPRM                 ;GET NEXT PARAMETER
        SUB     X0,B                    ;DO SUBTRACT
        NEG     B                       ;NEGATE BECAUSE PARMS ARE BACKWARDS
        JMP     _OUT                    ;PRINT IT AND RETURN
_MUL
        JSR     _NXTPRM                 ;GET NEXT PARAMETER
        MOVE    B1,X1                   ;PUT SECOND PARM IN X1
        MPY     X0,X1,B                 ;FORM PRODUCT
        MOVE    B0,P:TEMP1              ;SAVE LOWER PRODUCT TERM
        JSR     OUTDAT                  ;PRINT OUT UPPER PRODUCT TERM
        JSR     PRTSPC                  ;PRINT A SPACE
        MOVE    P:TEMP1,B               ;RESTORE LOWER PRODUCT TERM
        JMP     _OUT                    ;PRINT IT OUT AND RETURN
_DIV
        JSR     _NXTPRM                 ;GET THE NEXT PARAMETER
        MOVE    B1,X1                   ;SAVE DIVISER
        MOVE    X0,A                    ;COPY DIVIDEND
        TFR     A,B                     ;COPY A
        ABS     A                       ;MAKE IT POSITIVE
        EOR     X1,B                    ;FORM FINAL SIGN
        AND     #$FE,CCR                ;CLEAR CARRY
        REP     #24                     ;FORM QUOTIENT
        DIV     X1,A                    ;DO DIVISION
        JPL     _OK                     ;NO SIGN FIX
        NEG     A                       ;FLIP SIGN
_OK
        MOVE    A0,B                    ;PUT RESULT IN B
        JMP     _OUT                    ;OUTPUT RESULT
_NXTPRM
        JSR     PRTSPC
        JSR     INDAT                   ;GET NEXT PARAMETER
        MOVE    #'=',A                  ;GET EQUAL SIGN
        JSR     OUT2                    ;OUTPUT IT
        MOVE    P:TEMP1,X0              ;GET PREVIOUS PARAMETER
        RTS
_FRAC
        MOVE    P:TEMP1,B               ;GET VALUE TO CONVERT
        JSR     OUTFRAC                 ;OUTPUT IT AS FRACTION
        JMP     CMD

        PAGE
;
;       RD  <[P,X,Y]>:<ADDR>
;       MONITOR - MONITOR MEMORY LOCATION AND IF IT CHANGES, PRINT
;                 OUT THE NEW VALUE.  THE INITIAL VALUE IS ASSUMED
;                 TO BE ZERO.  THIS IS VERY USEFUL WHEN MONITORING
;                 THE VALUE IN A PIA INPUT PORT, A STATUS REGISTER
;                 OR A RECEIVE DATA REGISTER.
;
MONITOR
        JSR     GETPXY                  ;GET SPACE AND ADDRESS
        MOVE    B1,R2                   ;SAVE IT
        JSR     CRLF
        MOVE    #0,Y1                   ;GET INTIAL VALUE
_L1
        JSR     IN0                     ;SCAN TERMINAL FOR INPUT
        JEQ     _L2                     ;NO INPUT
        MOVE    #>CTRLY,X0              ;GET ABORT CHARACTER
        CMP     X0,A    #>CTRLC,X0      ;SEE IF ABORT
        JEQ     CMD                     ;YES, RETURN TO COMMAND LEVEL
        CMP     X0,A                    ;SEE IF CTRL/C
        JEQ     CMD                     ;YES, ABORT
_L2
        JSR     GETMEM                  ;GET THE MEMORY LOCATION
        CMP     Y1,B  (R2)-             ;SEE IF IT CHANGED, POINT R2 BACK
        JEQ     _L1                     ;NO CHANGE
        MOVE    B,P:TEMP1               ;SAVE NEW VALUE
        MOVE    P:MEMT,A                ;GET MEMORY SPACE
        JSR     OUT2                    ;OUTPUT IT
        PRTVAL  COLON                   ;PRINT COLON
        MOVE    R2,B                    ;GET ADDRESS
        JSR     OUTADD                  ;PRINT IT OUT
        JSR     PRTSPC                  ;PRINT A SPACE
        MOVE    P:TEMP1,B               ;GET NEW VALUE
        JSR     OUTDAT                  ;OUTPUT IT
        JSR     CRLF                    ;DO CR,LF
        MOVE    P:TEMP1,Y1              ;GET NEW VALUE
        JMP     _L1                     ;AND CONTINUE SCANNING
        PAGE
;
;       WRT <[P,X,Y]>:<ADDR> <VALUE> [REPEAT]
;       WRITE A VALUE INTO THE MEMORY LOCATION WITHOUT VERIFICATION.
;       THIS IS USEFUL WHEN WRITING REGISTERS THAT READ DIFFERENTLY
;       SUCH AS TX/RX REGISTERS OR STATUS/CONFIGURATION REGISTERS
;       OR PIA OUTPUT REGISTERS.
;
WRITE
        JSR     GETPXY                  ;GET ADDRESS TO WRITE
        MOVE    B1,R2                   ;PUT IN R2 FOR INDEXING
        JSR     PRTSPC                  ;PRINT A SPACE
        JSR     INDAT                   ;INPUT DATA VALUE
        MOVE    B1,P:TEMP1              ;SAVE INPUT VALUE
        MOVE    #CR,X0                  ;GET CODE FOR CR
        CMP     X0,A                    ;SEE IF DELIMITER IS CR
        JEQ     _FOREVR                 ;YES
        JSR     PRTSPC                  ;DO A SPACE
        JSR     INDAT                   ;GET REPEAT COUNT
        MOVE    B1,R0                   ;SAVE REPEAT COUNT
        MOVE    P:TEMP1,B               ;GET INPUT DATA
        DO      R0,_ESET                ;SET MEMORY
        JSR     SETMEM                  ;DO IT
        MOVE    (R2)-                   ;POINT R BACK
_ESET
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
_FOREVR
        JSR     CRLF                    ;OUTPUT CR,LF
_DO4EVR
        MOVE    P:TEMP1,B               ;GET INPUT VALUE
        JSR     SETMEM                  ;SET IN MEMORY
        MOVE    (R2)-                   ;POINT BACK
        JSR     IN0                     ;SCAN INPUT DEVICE
        JEQ     _DO4EVR                 ;NO INPUT
        MOVE    #>CTRLC,X0              ;GET CTRL/C CODE
        CMP     X0,A    #>CTRLY,X0      ;SEE IF CTRL/C
        JEQ     CMD                     ;YES, EXIT
        CMP     X0,A                    ;SEE IF CTRL/Y
        JEQ     CMD                     ;YES, EXIT
        JMP     _DO4EVR                 ;NO, CONTINUE
        PAGE
;
;       INI <DRV>
;       INITIALIZE DEVICE DRIVER
;
INIT
        JSR     INDAT                   ;GET THE DEVICE DRIVER NUMBER
        JSR     DEV_INIT                ;INITIALIZE THE DEVICE
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
        PAGE
;
;       FND     <[P,X,Y]>:<ADD1><ADD2><VALUE>[MASK]
;       SEARCH THE MEMORY FROM ADD1 THROUGH ADD2 FOR THE
;       NUMBER VALUE.  THE MEMORY LOCATION IS OPTIONALLY MASKED BY
;       'MASK' BEFORE THE COMPARE IS PERFORMED.
;
FIND
        JSR     GETPXY                  ;GET MEMORY AND STARTING ADDRESS
        MOVE    B1,R2                   ;SAVE STARTING ADDRESS
        PRTVAL  DASH
        JSR     INADD                   ;GET ENDING ADDRESS
        MOVE    R2,A                    ;GET STARTING ADDRESS
        SUB     A,B     #>1,X0          ;FIND LENGTH
        ADD     X0,B                    ;FIND TOTAL # OF MEMORY LOCATIONS
        MOVE    B,N2                    ;SAVE TOTAL
        JSR     PRTSPC
        JSR     INDAT                   ;GET DATA TO SEARCH FOR
        MOVE    B1,P:TEMP3              ;SAVE IT
        MOVE    #CR,X0                  ;GET CR
        CMP     X0,A    #$FFFFFF,Y0     ;SEE IF DELIMITER WAS CR,DEFAULT MASK
        JEQ     _GOTMASK
        JSR     PRTSPC                  ;PRINT A SPACE
        JSR     INDAT                   ;GET THE MASK
        MOVE     B1,Y0                  ;SAVE MASK
_GOTMASK
        DO      N2,_ELOOK               ;SEARCH MEMORY LOOP
        JSR     GETMEM                  ;GET THE MEMORY
        MOVE    P:TEMP3,X1              ;RESTORE DATA
        AND     Y0,B                    ;MASK B
        MOVE    B1,B                    ;SIGN EXTEND AND ZERO LOWER
        CMP     X1,B    (R2)-           ;SEE IF MATCH, POINT R2 BACK
        JNE     _NOMATCH                ;NO MATCH
        MOVE    Y0,P:TEMP1              ;SAVE MASK
        MOVE    R2,B                    ;GET MATCH ADDRESS
        JSR     CRLF
        JSR     OUTADD                  ;PRINT ADDRESS
        JSR     PRTSPC                  ;PRINT A SPACE
        JSR     GETMEM                  ;GET THE DATA AGAIN
        JSR     OUTDAT                  ;OUTPUT THE DATA
        MOVE    P:TEMP1,Y0              ;RESTORE MASK
        MOVE    (R2)-                   ;MOVE R2 BACK
_NOMATCH
        MOVE    (R2)+                   ;MOVE TO NEXT
_ELOOK
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
        PAGE
;
;       COP <[P,X,Y]>:<ADD1><ADD2> <[P,X,Y]>:<DEST>
;
;       COPY MEMORY WITH VERIFY
;
MOVE_MEM
        JSR     GETPXY                  ;GET SOURCE SPACE AND START ADDR
        MOVE    B1,R4                   ;SAVE SOURCE START ADDR
        MOVE    P:MEMT,X0               ;GET SOURCE MEMORY SPACE
        MOVE    X0,P:TEMP1              ;SAVE SOURCE MEMORY SPACE
        PRTVAL  DASH                    ;INDICATE RANGE
        JSR     INADD                   ;GET END OF RANGE
        MOVE    R4,A                    ;GET START OF RANGE
        SUB     A,B     #>1,X0          ;GET LENGTH
        ADD     X0,B                    ;ADJUST LENGTH
        MOVE    B1,N4                   ;SAVE LENGTH
        JSR     PRTSPC  
        JSR     GETPXY                  ;GET DESTINATION SPACE AND ADDRESS
        MOVE    P:MEMT,X0               ;GET DESTINATION SPACE
        MOVE    X0,P:TEMP2              ;SAVE DESTINATION SPACE
        MOVE    B1,R5                   ;SAVE DESTINATION ADDRESS
        DO      N4,_EMOVE               ;DO MOVE
        MOVE    P:TEMP1,X0              ;GET SOURCE SPACE
        MOVE    X0,P:MEMT               ;SET SOURCE SPACE
        MOVE    R4,R2                   ;GET SOURCE ADDRESS
        JSR     GETMEM                  ;GET THE MEMORY
        MOVE    R2,R4                   ;SAVE NEW SOURCE
        MOVE    P:TEMP2,X0              ;GET DESTINATION SPACE
        MOVE    X0,P:MEMT               ;SET DESTINATION SPACE
        MOVE    R5,R2                   ;SET DESTINATION ADDRESS
        JSR     SETMEM                  ;SET THE MEMORY
        MOVE    R2,R5                   ;SAVE NEW SOURCE
        MOVE    B,Y0                    ;SAVE DATA
        JSR     GETMEM                  ;GET MEM+1
        MOVE    B,P:TEMP3               ;SAVE MEM+1 DATA
        NOT     B  (R2)-                ;GEM COMPLEMENT OF MEM+1, POINT BACK
        JSR     SETMEM                  ;WRITE COMPLEMENT TO MEM+1
        MOVE    (R2)-                   ;BACK UP TO MEM+1
        MOVE    (R2)-                   ;BACK UP TO MEM
        JSR     GETMEM                  ;READ BACK MEMORY VALUE
        CMP     Y0,B                    ;SEE IF WRITE WAS OK
        JEQ     _OK                     ;YES
        JSR     CRLF                    ;WE HAVE AN ERROR
        MOVE    #'ERR',A                ;GET MSG
        MOVE    (R2)-                   ;GET ERROR ADDRESS
        JSR     OUT3                    ;PRINT IT
        JSR     PRTSPC                  ;PRINT SPACE
        MOVE    R2,B                    ;GET ERROR ADDRESS
        JSR     OUTADD                  ;PRINT ERROR ADDRESS
        MOVE    (R2)+                   ;POINT TO MEM+1
_OK
        MOVE    P:TEMP3,B               ;GET MEM+1 DATA
        JSR     SETMEM                  ;SET IT
_EMOVE
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
        PAGE
;
;       DVD     DEVICE DISPLAY.  DISPLAY EACH DRIVER NUMBER
;               AND THE 3 LETTER NAME ASSOCIATED WITH IT
;
DEVICES
        MOVE    #IOTBL,R3               ;POINT TO I/O TABLE
        DO      #IOTBLLEN,_E1           ;DO TABLE
        JSR     CRLF
        MOVE    P:(R3)+,B               ;GET DEVICE CODE
        JSR     OUTDAT                  ;DISPLAY IT
        JSR     PRTSPC                  ;OUTPUT SPACE
        MOVE    P:(R3)+,A               ;GET DEVICE NAME
        JSR     OUT3                    ;PRINT IT
        MOVE    (R3)+
        MOVE    (R3)+
        MOVE    (R3)+
_E1
        JMP     CMD                     ;RETURN TO COMMAND LEVEL
        PAGE
;
;       BDA <[300,1200,2400,4800,9600,19200]> SET BAUD RATE FOR DUART-A
;
BAUDA
        JEQ     CMD                     ;IF DELIMITER IS <CR> THEN EXIT
        JSR     GETBAUD                 ;GET BAUD RATE AND CODE
        MOVEP   X0,Y:DUART+1            ;SET NEW BAUD RATE FOR DUART-A
        JMP     CMD
;
;       BDB <[300,1200,2400,4800,9600,19200]> SET BAUD RATE FOR DUART-B
;
BAUDB
        JEQ     CMD                     ;IF DELIMITER IS <CR> THEN EXIT
        JSR     GETBAUD                 ;GET BAUD RATE AND CODE
        MOVEP   X0,Y:DUART+9            ;SET NEW BAUD RATE
        JMP     CMD
;
;       INPUT NEW BAUD RATE AND DETERMINE THE DUART CODE FOR IT
;
GETBAUD
        JSR     INDAT                   ;GET BAUD RATE
        MOVE    #BAUDTBL,R0             ;POINT TO BAUD RATE TABLE
        DO      #BDTBLLEN,NFBAUD        ;SCAN TABLE
        MOVE    P:(R0)+,X0              ;GET BAUD RATE
        CMP     X0,B                    ;SEE IF MATCH
        JNE     _NOMATCH                ;NO
        ENDDO                           ;MATCH, CLEAN UP LOOP
        MOVE    P:(R0),X0               ;GET DUART CODE
        RTS                             ;AND RETURN
_NOMATCH
        MOVE    (R0)+                   ;POINT TO NEXT BAUD RATE
NFBAUD
        MOVE    #BADBAUD,R0
        JSR     OUT5                    ;BAUD RATE NOT IN TABLE
        JMP     CMD
        PAGE
;
;       BDS <[300,1200,2400,4800,9600,19200>]
;               SELECT BAUD RATE FOR SCI.  THIS ASSUMES THE SCI
;               HAS BEEN INITIALIZED
;
BAUDSCI
        JEQ     CMD                     ;IF DELIMITER IS <CR> THEN EXIT
        JSR     INDAT                   ;GET BAUD RATE
        MOVE    #SCIBAUD,R4             ;POINTER TO SCI INITIALIZATION TABLE
        MOVE    #BAUDTBL,R0             ;POINT TO BAUD RATE TABLE
        DO      #BDTBLLEN,_ES           ;SCAN BAUD RATE TABLE
        MOVE    P:(R0)+,X0              ;GET BAUD RATE
        CMP     X0,B                    ;SEE IF MATCH
        JNE     _NOMATCH                ;NO MATCH
        ENDDO                           ;WE HAVE A MATCH, CLEAN UP LOOP
        MOVEP   P:(R4),X:SCCR           ;SET SCI CLOCK REGISTER
        JMP     CMD
_NOMATCH
        MOVE    X:(R0)+,X0  Y:(R4)+,Y0  ;INCREMENT POINTERS
_ES
        JMP     NFBAUD                  ;NOT FOUND BAUD
        PAGE
;                                              
;       RETURN DATA IN MEMORY SPACE SPECIFIED BY MEMT AND POINTED TO BY
;       R2 AND INCREMENT R2 TO THE NEXT LOCATION
;
GETMEM
        MOVE    P:MEMT,B                ;GET MEMORY SPACE
        MOVE    #'X',X0                 ;GET A X
        CMP     X0,B    #'Y',X0         ;SEE IF X
        JEQ     _RXM                    ;YES
        CMP     X0,B                    ;SEE IF Y
        JEQ     _RYM                    ;YES
        MOVE    P:(R2)+,B               ;GET P MEMORY
        RTS
_RXM
        MOVE    X:(R2)+,B               ;GET X MEMORY
        RTS
_RYM
        MOVE    Y:(R2)+,B               ;GET Y MEMORY
        RTS
;
;       SAVE THE VALUE IN REG B TO THE MEMORY LOCATION INDICATED IN
;       MEMT AND POINTED TO BY R2 AND INCREMENT R2.
;
SETMEM
        MOVE    P:MEMT,A        ;GET THE MEMORY SPACE
        MOVE    #'X',X0         ;GET A 'X'
        CMP     X0,A    #'Y',X0 ;SEE IF X SPACE
        JEQ     _XSPACE         ;YES
        CMP     X0,A            ;SEE IF Y SPACE
        JEQ     _YSPACE         ;YES
        MOVE    B1,P:(R2)+      ;MUST BE P MEMORY, SAVE IT
        RTS                     ;AND RETURN
_XSPACE
        MOVE    B1,X:(R2)+      ;SAVE IN X MEMORY
        RTS
_YSPACE
        MOVE    B1,Y:(R2)+      ;SAVE IN Y MEMORY
        RTS
        PAGE
;
;       COPY THE REGISTERS FROM THE CURRENT WORKING SET TO THE
;       OLD REGISTER AREA.  AFTER RETURNING FROM THE GO OR CAL COMMAND,
;       IT IS POSSIBLE TO SEE WHAT REGISTERS HAVE CHANGED
;
COP_REG
        MOVE    #REGVAL,R0      ;POINT TO CURRENT REGISTERS
        MOVE    #REGOLD,R1      ;OLD REGISTER SAVE AREA
        DO      #NUMREG,_E1     ;COPY REGISTERS
        MOVE    P:(R0)+,A       ;GET REGISTER
        MOVE    A1,P:(R1)+      ;SAVE IT
_E1
        RTS
        PAGE
;
;       OUTFRAC - OUTPUT NUMBER IN B AS A DECIMAL FRACTION
;
OUTFRAC
        TST     B       B,Y1    ;CHECK SIGN OF NUMBER, SAVE NUMBER
        JPL     _POSSGN         ;POSITIVE
        ABS     B       #' -.',A        ;MAKE POSITIVE, GET SIGN INFO
        JMP     _PRTSGN         ;PRINT THE SIGN
_POSSGN
        MOVE    #' +.',A        ;THE NUMBER IS POSITIVE
_PRTSGN
        JSR     OUT3            ;OUTPUT THE SIGN
        MOVE    B,X0            ;PUT IN X0
        CLR     B    #>$A,Y0    ;CLEAR STRING, GET BASE ADJUSTMENT
        DO      #8,_EXV         ;CONVERT 8 DECIMAL DIGITS
        MPY     X0,Y0,A         ;SHIFT OUT DIGIT
        REP     #4              ;SHIFT UP PREVIOUS DIGITS
        ASL     B     A1,X0     ;AND COPY NEW DIGIT
        ADD     X0,B  A0,A      ;ADD IN NEW DIGIT, COPY REMAINDER
        LSR     A               ;COMPENSATE FOR SIGN BIT
        MOVE    A1,X0           ;MOVE FOR NEXT PASS
_EXV
        REP     #8              ;SHIFT 2 DIGITS OUT OF EXTENTION
        ASR     B               ;SHIFT THEM OUT
        MOVE    B0,P:FRACSAVE   ;SAVE LOWER DIGITS
        JSR     OUTDAT          ;OUTPUT UPPER DIGITS IN DECIMAL
        MOVE    P:FRACSAVE,B    ;GET OTHER 2 DIGITS
        REP     #16             ;PUT IN LOWER BYTE
        ASR     B               ;SHIFT IT DOWN
        JSR     OUTBYTE         ;OUTPUT THEM AS A BYTE
        RTS
        

        PAGE
;
;       IN0             SCAN THE INPUT DEVICE POINTED TO BY P:IODEV TO
;                       SEE IF THERE IS A INPUT CHARACTER PENDING.  IF NO
;                       CHARACTER IS PENDING, Z=1 ELSE REG A=INPUT AND Z=0.
;
IN0
        JSR     IOSET           ;SETUP THE I/O OPERATION
        DO      #IOTBLLEN,_EIN  ;SCAN TABLE FOR DRIVER
        MOVE    P:(R0)+,X0      ;GET I/O DEVICE NUMBER
        CMP     X0,A  (R0)+     ;SEE IF THIS DRIVER
        MOVE    (R0)+           ;ADJUST POINTER
        JNE     _NO             ;NO
        ENDDO                   ;CLEANUP DO LOOP
        MOVE    P:(R0),R0       ;GET INPUT ROUTINE ADDRESS
        CLR     A               ;CLEAR RETURN VALUE
        JMP     (R0)            ;EXECUTE INPUT SCAN ROUTINE
_NO
        MOVE    (R0)+           ;INCREMENT TO NEXT DRIVER
        MOVE    (R0)+
_EIN
        CLR     A               ;CLEAR RETURN REG
;
;       NO DATA FROM INPUT DEVICE
;
NO_DATA
        TST     A               ;SET Z=1 SINCE A=0
        JMP     RESX0R0         ;RESTORE REGISTERS
;
;       MASK TO KEEP ONLY THE LOWER 8 BITS OF INPUT
;
MASK_DATA
        MOVE    #>$0000FF,X0    ;GET MASK
        AND     X0,A            ;MASK INPUT
        MOVE    A1,A            ;SIGN EXTEND AND A0 ZERO
        ANDI    #$FB,CCR        ;SET Z=0 TO INDICATE VALID DATA
        JMP     RESX0R0         ;RESTORE X0,R0 AND RETURN
;
;       IN1 - INPUT 8 BIT DATA INTO THE LOWER BYTE OF A1
;
IN1
        JSR     IN0             ;SCAN INPUT DEVICE
        JEQ     IN1             ;NO INPUT, WAIT FOR IT
        RTS                                         
;
;       IN2 - INPUT CHARACTER INTO A1, PUT INTO TOP BYTE OF A1, MASK PARITY
;
IN2
        JSR     IN1             ;GET BYTE INTO LOWER A1
IN2CONT
        REP     #17             ;SHIFT TO TOP AND REMOVE PARITY
        LSL     A
        LSR     A               ;SHIFT IN 0 FOR MS BIT
        RTS                     ;AND RETURN
;
;       IN3 - INPUT CHARACTER INTO A1, PUT INTO TOP BYTE OF A1,
;               MASK PARITY AND ECHO
;
IN3
        JSR     IN1             ;GET BYTE INTO LOWER A1
        JSR     OUT1            ;OUTPUT BYTE
        JMP     IN2CONT         ;GO USE IN2 ROUTINE
;
;       IN3UC - INPUT CHARACTER INTO A1, PUT INTO TOP BYTE OF A1,
;               MASK PARITY, ECHO AND CONVERT TO UPPER CASE
;
IN3UC
        JSR     IN3             ;GET CHAR, ECHO
        JMP     UCASE           ;CONVERT TO UPPER CASE
;
;       IN2UC - INPUT CHARACTER INTO A1, PUT INTO TOP BYTE OF A1,
;               MASK PARITY, CONVERT TO UPPER CASE
;
IN2UC
        JSR     IN2             ;GET CHAR, ECHO, MASK
UCASE
        MOVE    #'a',X1         ;GET LC A
        CMP     X1,A    #'z',X1 ;COMPARE
        JLT     _NO             ;LOWER THAN LOWER CASE A
        CMP     X1,A    #<$20,X1        ;COMPARE TO Z,GET CONVERSION FACTOR
        JGT     _NO             ;ABOVE LOWER CASE Z
        SUB     X1,A            ;CONVERT TO UPPER CASE
_NO
        RTS

        PAGE
;
;       ABORT THE OUTPUT, CLEAN UP LOOP FLAG AND GO TO COMMAND LEVEL
;
ABOOUT  ANDI    #$7F,MR         ;CLEAR LOOP FLAG
        JSR     SET_TERM        ;SET TERMINAL FOR I/O
        JMP     CMD             ;GO TO COMMAND LEVEL
;
;       OUT2 - OUTPUT BYTE IN TOP PART OF A1
;
OUT2
        REP     #16
        LSR     A               ;SHIFT TOP BYTE TO BOTTOM
;
;       OUT1 - OUTPUT 8 BIT DATA FROM A1 WITH CTRL/S/Q PROTOCOL
;
OUT1
        MOVE    A1,P:IOSAVE     ;SAVE DATA TO OUTPUT
        JSR     IN0             ;SEE IF INPUT CHARACTER PENDING
        JEQ     _START          ;NO
        REP     #17             ;SHIFT TO TOP AND REMOVE PARITY
        LSL     A
        MOVE    X0,P:OUT1SAVE   ;SAVE X0 FOR USER
        LSR     A       #CTRLC,X0       ;PUT 0 IN PARITY, GET CTRLC CODE
        CMP     X0,A    #CTRLY,X0       ;SEE IF CTRL/C
        JEQ     ABOOUT                  ;YES, ABORT OUTPUT
        CMP     X0,A    #CTRLS,X0       ;SEE IF CTRL/Y, GET CTRLS
        JEQ     ABOOUT                  ;YES, ABORT OUTPUT
        CMP     X0,A            ;SEE IF CTRL/S
        JNE     _RESX0          ;NO
_GETQ
        JSR     IN2             ;GET AN INPUT CHARACTER
        MOVE    #CTRLC,X0       ;GET CTRL/C CODE
        CMP     X0,A    #CTRLY,X0       ;SEE IF CTRL/C, GET CTRL/Y
        JEQ     ABOOUT          ;ABORT OUTPUT
        CMP     X0,A    #CTRLQ,X0       ;SEE IF CTRL/Y, GET START CODE
        JEQ     ABOOUT          ;ABORT OUTPUT
        CMP     X0,A            ;SEE IF CTRL/Q
        JNE     _GETQ           ;NO, WAIT FOR ONE
_RESX0
        MOVE    P:OUT1SAVE,X0   ;RESTORE X0
_START
        MOVE    P:IOSAVE,A      ;GET THE CHARACTER TO OUTPUT
;
;       OUT0 - GENERIC OUTPUT ROUTINE.  THIS ROUTINE WILL OUTPUT A BYTE
;               FROM THE LOWER BYTE OF A1 TO THE DEVICE POINTED TO BY
;               IODEV.
;
OUT0
        MOVE    A1,P:IOSAVE     ;SAVE DATA TO OUTPUT
        JSR     IOSET           ;SET UP THE I/O
        DO      #IOTBLLEN,_EOUT
        MOVE    P:(R0)+,X0      ;GET DEVICE CODE
        CMP     X0,A    (R0)+   ;SEE IF THIS DEVICE CODE
        JNE     _NO             ;NO
        ENDDO                   ;CLEAN UP DO LOOP
        MOVE    P:(R0),R0       ;POINT TO OUTPUT DRIVER
        MOVE    P:IOSAVE,A      ;GET THE DATA TO OUTPUT
        JMP     (R0)            ;EXECUTE OUTPUT DRIVER
_NO
        MOVE    (R0)+           ;INCREMENT TO NEXT DEVICE CODE
        MOVE    (R0)+
        MOVE    (R0)+
_EOUT
;
;       RESTORE X0 AND R0
;
RESX0R0
        MOVE    P:X0SAVE,X0     ;RESTORE X0
        MOVE    P:R0SAVE,R0     ;RESTORE R0    
        RTS
;
;       OUT3 - OUTPUT 3 ASCII CHARACTERS IN A1
;                
OUT3
        MOVE    A1,P:OUT3SAVE   ;SAVE CHARACTERS
        JSR     OUT2            ;OUTPUT TOP CHARACTER
        MOVE    P:OUT3SAVE,A    ;GET CHARACTERS
        REP     #8              ;SHIFT MIDDLE BYTE TO BOTTOM
        ASR     A
        JSR     OUT1            ;OUTPUT IT
        MOVE    P:OUT3SAVE,A    ;GET CHARACTERS
        JSR     OUT1            ;OUTPUT BOTTOM BYTE
        RTS
;          
;       OUT4 - OUTPUT N0 PACKED TEXT POINTED TO BY R0
;
OUT4                                      
        DO      N0,_EOUT4       ;NUMBER OF PACKED CHARACTER WORDS
        MOVE    P:(R0)+,A       ;GET CHARACTERS
        JSR     OUT3            ;OUTPUT CHARACTERS
_EOUT4
        RTS
;          
;       OUT5 - OUTPUT PACKED TEXT POINTED TO BY R0, ENDING WITH ZERO
;
OUT5                                      
        MOVE    P:(R0)+,A       ;GET CHARACTERS
        TST     A               ;SEE IF ZERO
        JEQ     _EOUT5          ;YES, GET OUT
        JSR     OUT3            ;OUTPUT CHARACTERS
        JMP     OUT5            ;DO MORE
_EOUT5
        RTS
;
;       COMMON SETUP FOR I/O CALLING SEQUENCE
;
IOSET
        MOVE    X0,P:X0SAVE     ;SAVE X0 FOR USER
        MOVE    R0,P:R0SAVE     ;SAVE R0 FOR USER
        MOVE    #IOTBL,R0       ;POINT TO I/O DRIVER TABLE
        MOVE    P:IODEV,A       ;GET THE I/O DEVICE CODE
        RTS
        PAGE
;
;       OUTPUT DRIVERS
;
OUT_NULL
        JMP     RESX0R0         ;NULL DEVICE
OUT_DRTA
        JCLR    #2,Y:DUARTA+1,* ;WAIT FOR DUART A TO BE READY
        MOVEP   A1,Y:DUARTA+3   ;OUTPUT DATA
        JMP     RESX0R0         ;RESTORE AND RETURN
OUT_DRTB
        JCLR    #2,Y:DUARTB+1,* ;WAIT FOR DUART B TO BE READY
        MOVEP   A1,Y:DUARTB+3   ;OUTPUT DATA
        JMP     RESX0R0         ;RESTORE AND RETURN
OUT_DSPSCI
        JCLR    #TDRE,X:SSR,*   ;WAIT FOR SCI TO BE READY
        MOVEP   A1,X:STXL       ;TRANSMIT DATA
        JMP     RESX0R0         ;RESTORE AND RETURN
OUT_DSPHOST
        JCLR    #HTDE,X:HSR,*   ;WAIT FOR HOST INTERFACE TO BE READY
        MOVE    A1,X:HTX        ;SEND TO DSP HOST INTERFACE
        JMP     RESX0R0         ;RESTORE AND RETURN
        PAGE
;
;       INPUT DRIVERS
;
IN_NULL
        MOVE    #>'N',A                 ;RETURNED DATA IS 'N'
        JMP     MASK_DATA               ;MASK THE DATA
IN_DRTA
        JCLR    #0,Y:DUARTA+1,NO_DATA   ;SEE IF DATA IN DUART A
        MOVEP   Y:DUARTA+3,A            ;GET DATA
        JMP     MASK_DATA
IN_DRTB
        JCLR    #0,Y:DUARTB+1,NO_DATA   ;SEE IF DATA IN DUART B
        MOVEP   Y:DUARTB+3,A            ;GET DATA
        JMP     MASK_DATA
IN_DSPSCI
        JCLR    #RDRF,X:SSR,NO_DATA     ;SEE IF DATA IN DSP SCI
        MOVEP   X:SRXL,A                ;GET DATA
        JMP     MASK_DATA
IN_DSPHOST
        JCLR    #HRDF,X:HSR,NO_DATA     ;SEE IF DATA IN DSP HOST INTERFACE
        MOVEP   X:HRX,A                 ;GET DATA
        JMP     MASK_DATA
        PAGE
;
;       DEVICE DRIVERS SETUP ROUTINES
;
SET_NULL
        RTS                     ;NO SETUP
SET_DRTA
        RTS                     ;NO SETUP
SET_DRTB
        RTS                     ;NO SETUP
SET_DSPSCI
        MOVEP   #$0302,X:SCR    ;ENABLE TX,RX: 8 BIT DATA, 1 START, 1 STOP
        MOVEP   #$0020,X:SCCR   ;CD=32 (/33), INT CLK =>9706 BAUD
        MOVEP   X:PCC,A         ;GET PORT C CONTROL REGISTER
        MOVE    #>7,X0          ;MASK TO ENABLE SCI BITS
        OR      X0,A            ;SET BITS ON IN A
        MOVEP   A1,X:PCC        ;ENABLE SCI
        RTS
SET_DSPHOST
        MOVEP   #1,X:PBC        ;ENABLE DSP HOST INTERFACE
        RTS
        PAGE
;
;       INBYTE_NLS - INPUT A BYTE BUT IGNORE LEADING BLANKS
;
INBYTE_NLS
        JSR     WAITHEX         ;GO WAIT FOR THE FIRST HEX CHARACTER
        CLR     B       #>2,X0  ;SET CHARACTER COUNT
        JMP     INCONT          ;CONTINUE INPUT
;
;       INADD_NLS - INPUT A ADDRESS BUT IGNORE LEADING BLANKS
;
INADD_NLS
        JSR     WAITHEX         ;GO WAIT FOR THE FIRST HEX CHARACTER
        CLR     B       #>4,X0  ;SET CHARACTER COUNT
        JMP     INCONT          ;CONTINUE INPUT
;
;       INDAT_NLS - INPUT DATA BUT IGNORE LEADING BLANKS
;
INDAT_NLS
        JSR     WAITHEX         ;GO WAIT FOR THE FIRST HEX CHARACTER
        CLR     B       #>6,X0  ;SET CHARACTER COUNT
        JMP     INCONT          ;CONTINUE INPUT
;
;       WAIT FOR A HEX CHARACTER.  IF BLANKS ARE INPUT, IGNORE THEM
;
WAITHEX
        JSR     IN2             ;GET INPUT CHARACTER
        MOVE    #SPACE,X0       ;GET CODE FOR SPACE
        CMP     X0,A    #0,R7   ;SEE IF SPACE, CLEAR CHAR COUNT
        JEQ     WAITHEX         ;YES, IGNORE IT
        RTS                     ;RETURN WITH FIRST HEX CHARACTER

        PAGE
;
;       ININT - READ 6 DECIMAL DIGITS AND CONVERT TO HEX
;               THE BINARY VALUE IS RETURNED IN B.
;
ININT
        CLR     B       #0,R7   ;CLEAR TOTAL, CLEAR CHAR COUNT
        MOVE            #>6,X0  ;NUMBER OF DECIMAL DIGITS
_INDIG
        JSR     IN2UC           ;GET NUMBER
        MOVE            A1,Y0   ;SAVE INPUT CHARACTER
        MOVE            #CTRLS,X1       ;GET CTRL/S
        CMP     X1,A    #CTRLQ,X1       ;SEE IF CTRL/S
        JEQ     _INDIG                  ;YES, DISCARD
        CMP     X1,A    #CTRLC,X1       ;SEE IF CTRL/Q
        JEQ     _INDIG                  ;YES, DISCARD
        CMP     X1,A    #CTRLY,X1       ;SEE IF CTRL/C
        JEQ     ABOOUT                  ;YES ABORT
        CMP     X1,A    #DEL,X1         ;SEE IF CTRL/Y
        JEQ     ABOOUT                  ;YES, ABORT
        CMP     X1,A    #CR,X1          ;SEE IF DELETE
        JEQ     _DEL                    ;YES, DELETE
        CMP     X1,A    #SPACE,X1       ;SEE IF CR
        JEQ     _DLM                    ;YES, DELIMITER
        CMP     X1,A    #'9',X1         ;SEE IF SPACE
        JEQ     _DLM                    ;YES, DELIMITER
        CMP     X1,A    #'0',X1         ;SEE IF HIGHER THAN 9
        JGT     _INDIG                  ;YES, DISCARD
        CMP     X1,A                    ;SEE IF LESS THAN 0
        JLT     _INDIG                  ;YES, DISCARD
        SUB     X1,A    (R7)+           ;ADJUST TO BINARY, INC CHAR COUNT
        REP     #16                     ;SHIFT VALUE DOWN
        ASR     A
        MOVE    B1,X1                   ;MOVE PREVIOUS VALUE
        MOVE    #>10,Y1                 ;ADJUST FOR DECIMAL
        MPY     X1,Y1,B                 ;SCALE PREVIOUS VALUE
        ASR     B       A1,X1           ;ADJUST FOR FRAC MUL, MOVE INPUT
        MOVE    B0,B                    ;MOVE RESULT
        ADD     X1,B    Y0,A            ;ADD IN NEW DIG, RESTORE INPUT
        JSR     OUT2                    ;ECHO INPUT
        MOVE    R7,A                    ;GET CHAR COUNT
        CMP     X0,A                    ;SEE IF FIELD IS FULL
        JNE     _INDIG                  ;NO, GET MORE
_FULL
        JSR     IN2                     ;GET INPUT
        MOVE            #CTRLS,X1       ;GET CTRL/S
        CMP     X1,A    #CTRLQ,X1       ;SEE IF CTRL/S
        JEQ     _FULL                   ;YES, DISCARD
        CMP     X1,A    #CTRLC,X1       ;SEE IF CTRL/Q
        JEQ     _FULL                   ;YES, DISCARD
        CMP     X1,A    #CTRLY,X1       ;SEE IF CTRL/C
        JEQ     ABOOUT                  ;YES ABORT
        CMP     X1,A    #DEL,X1         ;SEE IF CTRL/Y
        JEQ     ABOOUT                  ;YES, ABORT
        CMP     X1,A    #CR,X1          ;SEE IF DELETE
        JEQ     _DEL                    ;YES, DELETE
        CMP     X1,A    #SPACE,X1       ;SEE IF CR
        JEQ     _DLM                    ;YES, DELIMITER
        CMP     X1,A                    ;SEE IF SPACE
        JEQ     _DLM                    ;YES, DELIMITER
        JMP     _FULL                   ;NONE OF THE ABOVE
_DLM
        RTS                             ;RETURN IF  DELIMITER
_DEL
        MOVE    R7,A                    ;GET CHARACTER COUNT
        TST     A               B1,Y0   ;SEE IF ZERO, MOVE VALUE
        JEQ     _INDIG                  ;YES, NOTHING TO DELETE
        MOVE    #>$0CCCCD,X1            ;GET .1
        MPY     Y0,X1,B         (R7)-   ;SCALE BACK, DEC CHAR COUNT
        MOVE    B1,B                    ;EXTEND AND ZERO RESULT
        MOVE            #$082008,A      ;GET BS,SPACE,BS
        JSR     OUT3                    ;DELETE PREVIOUS FROM SCREEN
        JMP     _INDIG                  ;GET MORE DIGITS

        PAGE
;
;       INBYTE - READ 2 ASCII HEX NIBBLES AND RETURN THE BYTE IN
;               THE LOWER PART OF B1
;
INBYTE
        MOVE    #>2,X0          ;READ 2 NIBBLES
        JMP     INMORE          ;GO DO READING
;
;       INREG - READ A NEW VALUE FOR REGISTER
;
INREG
        MOVE    P:(R5),X0       ;GET NUMBER OF NIBBLES IN REGISTER VALUE
        JMP     INMORE          ;GET THE DATA
        
;
;       INADD - READ 4 CHARACTERS AND CONVERT TO A VALUE IN B1
;
INADD
        MOVE    #>4,X0          ;SET FOR READING 4 NIBBLES
        JMP     INMORE
;
;       INDAT - READ 6 CHARACTERS AND CONVERT TO A VALUE IN B1
;
INDAT
        MOVE    #>6,X0          ;SET FOR READING 6 NIBBLES
INMORE
        CLR     B       #0,R7   ;COUNT OF NUMBER OF INPUT CHARACTERS
RDCHR
        JSR     IN2UC           ;GET CHARACTER
INCONT
        MOVE    A1,Y0           ;SAVE INPUT CHARACTER
        MOVE    #CTRLS,X1       ;GET CTRL/S CODE
        CMP     X1,A    #CTRLQ,X1       ;SEE IF CTRL/S, GET CTRL/Q
        JEQ     RDCHR           ;IF CTRL/S, IGNORE IT
        CMP     X1,A    #CTRLC,X1       ;SEE IF CTRL/Q, GET CTRL/C
        JEQ     RDCHR           ;IF CTRL/Q, IGNORE IT
        CMP     X1,A    #CTRLY,X1       ;SEE IF CTRL/C, GET CTRL/Y
        JEQ     ABOOUT          ;IF CTRL/C, CLEANUP AND EXIT
        CMP     X1,A    #DEL,X1         ;SEE IF CTRL/Y, GET DELETE
        JEQ     ABOOUT          ;IF CTRL/Y, CLEANUP AND EXIT
        CMP     X1,A    #'^',X1 ;SEE IF $7F ( <DEL> )
        JEQ     _DEL            ;YES
        CMP     X1,A    #CR,X1  ;SEE IF UP ARROW
        JEQ     _DLM            ;YES
        CMP     X1,A    #SPACE,X1       ;SEE IF <CR>
        JEQ     _DLM            ;YES, IT IS A DELIMITER
        CMP     X1,A    #$30,X1 ;SEE IF <SP>, GET A ZERO
        JEQ     _DLM            ;YES, IT IS A DELIMITER
        CMP     X1,A    #$39,X1 ;SEE IF LESS THAN 0, GET 9
        IF      HEXERR
        JLT     RDCHR           ;IGNORE BAD HEX
        ELSE
        JLT     _BADCHR         ;NOT ASCII HEX
        ENDIF
        CMP     X1,A    #$41,X1 ;COMPARE TO 9, GET "A"
        JLE     _L1             ;OK CHARACTER 0-9
        CMP     X1,A    #$46,X1 ;COMPARE TO "A", GET "F"
        IF      HEXERR
        JLT     RDCHR           ;IGNORE BAD HEX
        ELSE
        JLT     _BADCHR         ;NOT ASCII HEX
        ENDIF
        CMP     X1,A    #7,X1   ;COMPARE TO "F", GET ALPHA ADJUST
        IF      HEXERR
        JGT     RDCHR           ;IGNORE BAD HEX
        ELSE
        JGT     _BADCHR         ;NOT ASCII HEX
        ENDIF
        SUB     X1,A            ;ADJUST FOR A-F
_L1
        MOVE    #$30,X1         ;GET 0
        SUB     X1,A    (R7)+   ;CONVERT TO BINARY, INC NIBBLE COUNT
        REP     #4              ;SHIFT NIBBLE TO TOP OF REG
        LSL     A
        DO      #4,_L2          ;SHIFT INTO B
        LSL     A               ;SHIFT OUT OF A
        ROL     B               ;SHIFT INTO B
_L2        
        MOVE    Y0,A            ;RESTORE INPUT CHARACTER
        JSR     OUT2            ;SHIFT DOWN AND OUTPUT
        MOVE    X0,A            ;GET NUMBER OF CHARACTERS TO GET
        MOVE    R7,X1           ;GET NUMBER OF CHARACTERS SO FAR
        CMP     X1,A            ;SEE IF FULL
        JNE     RDCHR           ;NO, GET MORE NIBBLES
_L3
        JSR     IN2             ;GET ANOTHER CHARACTER
        MOVE    #CTRLC,X1       ;GET CTRL/C
        CMP     X1,A    #CTRLY,X1       ;SEE IF CTRLC
        JEQ     ABOOUT          ;YES, CLEANUP AND EXIT
        CMP     X1,A    #DEL,X1 ;SEE IF CTRL/Y
        JEQ     ABOOUT          ;YES, CLEANUP AND EXIT
        CMP     X1,A    #CR,X1  ;SEE IF <DEL>
        JEQ     _DEL            ;YES
        CMP     X1,A    #SPACE,X1       ;SEE IF <CR>
        JEQ     _DLM            ;YES, IT IS A DELIMITER
        CMP     X1,A    #'^',X1 ;SEE IF <SP>
        JEQ     _DLM            ;YES
        CMP     X1,A            ;SEE IF UP ARROW
        JEQ     _DLM            ;YES
        JMP     _L3             ;NOT DELIMITER OR <DEL>, TRY AGAIN
_BADCHR
        MOVEC   #0,SP           ;RESET STACK
        MOVE    #BADCM,R0       ;POINT TO MESSAGE
        JSR     OUT5            ;PRINT THE MSG
        JMP     CMD
_DEL    
        MOVE    R7,A            ;GET CHARACTER COUNT
        TST     A               ;SEE IF NO INPUT YET
        JEQ     RDCHR           ;YES, NOTHING READ YET
        MOVE    (R7)-           ;DECREMENT CHARACTER COUNT
        REP     #4              ;REMOVE PREVIOUS NIBBLE
        LSR     B               ;REMOVE IT
        MOVE    #$082008,A      ;GET <BS><SP><BS>
        JSR     OUT3            ;REMOVE LAST CHARACTER FROM SCREEN
        JMP     RDCHR           ;GET NEXT CHARACTER
_DLM
        RTS                     ;HIT A DELIMITER (<CR><SP>)
        PAGE
;
;       GETPXY          ROUTINE TO READ P,X OR Y; VALIDATE
;                       THE MEMORY SPACE AND GIVE AN ERROR IF IT IS INVALID;
;                       SAVE THE MEMORY TYPE; OUTPUT A COLON; READ
;                       A ADDRESS FOR THE SPACE
GETPXY
        JSR     IN3UC           ;GET [P,X,Y]
        MOVE    #'P',X0         ;GET P
        CMP     X0,A    #'X',X0 ;SEE IF P MEMORY
        JEQ     _OK             ;YES
        CMP     X0,A    #'Y',X0
        JEQ     _OK             ;X MEMORY
        CMP     X0,A            ;SEE IF Y
        JEQ     _OK             ;YES
        MOVE    #0,SP           ;CLEAR STACK
        MOVE    #GETMSG,R0      ;ERROR MESSAGE
        JSR     OUT5            ;OUTPUT MESSAGE
        JMP     CMD             ;RETURN TO COMMAND LEVEL
_OK
        MOVE    A1,P:MEMT       ;SAVE THE MEMORY TYPE
        PRTVAL  COLON           ;PUT A COLON AFTER MEMORY TYPE
        JSR     INADD           ;AND READ AN ADDRESS
        RTS                     ;RETURN TO MAIN ROUTINE
        PAGE
;
;       OUTINT - OUTPUT 16 BIT VALUE IN B1 AS DECIMAL
;
OUTINT
        MOVE    R0,Y1           ;SAVE R0
        MOVE    B1,B            ;SIGN EXTEND AND LOWER ZERO
        MOVE    #B10TBL,R0      ;TABLE OF POWERS OF 10 DIVIDED BY 2**23
        CLR     A       #>1,X1  ;GET ONE
        MOVE    P:(R0)+,X0      ;GET FIRST POWER
        DO      #6,_E1          ;DO 5 DECADES
        REP     #4              ;SHIFT UP PREVIOUS DECADE
        ASL     A
_E2
        SUB     X0,B            ;SUBTRACT CURRENT DECADE
        JMI     _E3             ;TOO MUCH
        ADD     X1,A            ;INCREMENT FOR CURRENT DECADE
        JMP     _E2             ;AND CONTINUE SUBTRACTING
_E3
        ADD     X0,B            ;READJUST FOR NEXT PASS
        MOVE    P:(R0)+,X0      ;GET NEXT POWER
_E1     
        MOVE    A1,B            ;PUT VALUE IN B FOR OUTPUT
        MOVE    Y1,R0           ;RESTORE R0
        JMP     OUTDAT          ;OUTPUT 6 NIBBLES AS DECIMAL
;
;       OUTBYTE - OUTPUT 2 ASCII HEX CHARACTERS FROM THE LOWER BYTE OF B1
;
OUTBYTE
        MOVE    #>2,X0          ;NUMBER OF HEX CHARACTERS TO OUTPUT
        REP     #16             ;SHIFT TO TOP OF REG
        ASL     B               ;PUT BOTTOM BYTE IN TOP OF REG FOR OUTPUT
        JMP     OUTMORE         ;DO OUTPUT
;
;       OUTREG - OUTPUT REGISTER CONTENTS
;                 
OUTREG
        MOVE    P:(R3),N3       ;GET SHIFT TO DISPLAY REGISTER
        MOVE    P:(R5),X0       ;GET REGISTER LENGTH
        MOVE    P:(R4),B1       ;GET REGISTER VALUE 
        REP     N3              ;LEFT JUSTIFY VALUE
        ROL     B
        JMP     OUTMORE         ;OUTPUT VALUE
;
;       OUTADD - CONVERT VALUE IN B1 TO ASCII AND OUTPUT 4 CHARACTERS TO DUARTA
;          
OUTADD
        MOVE    #>4,X0          ;OUTPUT 4 NIBBLES
        REP     #8              ;SHIFT TO TOP OF REGISTER
        ASL     B
        JMP     OUTMORE
;          
;       OUTDAT - CONVERT VALUE IN B1 TO ASCII AND OUTPUT 6 CHARS TO DUARTA
;                 
OUTDAT
        MOVE    #>6,X0          ;SET FOR OUTPUT 6 NIBBLES
OUTMORE
        MOVE    #0,B2           ;CLEAR EXTENTION
        MOVE    #0,B0           ;CLEAR B0
        DO      X0,_L1          ;OUTPUT CHARACTERS (NIBBLES)
        TFR     B,A  #$F0,X0    ;COPY UPPER NYBBLE. MASK FOR UPPER NYBBLE
        AND     X0,A  #'0',X0   ;MASK UPPER NYBBLE. SHIFT FOR ASCII 0
        REP     #4                               
        LSR     A               ;SHIFT NYBBLE TO BOTTOM OF UPPER BYTE
        ADD     X0,A  #'9',X0   ;MAKE NYBBLE ASCII. LOAD MAX VALUE OF DIG
        CMP     X0,A  #7,X0     ;SEE IF 0-9. LOAD SHIFT FOR A-F
        JLE     _L2             ;IT IS 0-9                 
        ADD     X0,A            ;IT IS A-F, ADD SHIFT
_L2
        JSR     OUT2            ;OUTPUT
        REP     #4              ;SHIFT NEXT NYBBLE INTO POSITION
        LSL     B               ;SHIFT IT
_L1
        RTS

        PAGE
;
;       OUTPUT <CR><LF>
;
CRLF
        PRTVAL  CR              ;OUTPUT <CR>
        PRTVAL  LF              ;OUTPUT <LF>
        RTS
;
;       OUTPUT A <SPACE>
;
PRTSPC
        PRTVAL  SPACE           ;OUTPUT A SPACE
        RTS
;
;       SET TERMINAL AS I/O DEVICE
;
SET_TERM
        MOVE    X0,P:X0SAVE     ;SAVE X0
        MOVE    P:TDEV,X0       ;GET TERMINAL DEVICE
        MOVE    X0,P:IODEV      ;SET TERMINAL IN I/O ROUTINE
        MOVE    P:X0SAVE,X0     ;RESTORE X0
        RTS
;
;       SET HOST AS I/O DEVICE
;
SET_HOST
        MOVE    X0,P:X0SAVE     ;SAVE X0
        MOVE    P:HDEV,X0       ;GET TERMINAL DEVICE
        MOVE    X0,P:IODEV      ;SET TERMINAL IN I/O ROUTINE
        MOVE    P:X0SAVE,X0     ;RESTORE X0
        RTS
;
;       SET THE USER I/O DEVICE
;
SET_USER
        MOVE    P:USR_DEV,X0    ;GET USER DEVICE
        MOVE    X0,P:IODEV      ;SET THE I/O DEVICE
        RTS
;
;       CHECK TO SEE IF WE POWERED UP IN MULTIBOARD MODE
;
CKMBRD
        MOVE    P:MDSTAT,A              ;GET POWERUP STATUS
        MOVE    #>$600000,X0            ;MASK FOR SPECIAL-MULTIBOARD
        AND     X0,A                    ;DO MASK
        RTS

        PAGE
;
;       SAVE THE USER'S CONTEXT AFTER AN INTERRUPT. BY THE TIME WE GET HERE,
;       THE USER'S R0 AND R1 HAVE ALREADY BEEN SAVED.  R0 HAS THE USER'S SR
;       FROM THE INTERRUPT AND R1 HAS THE PC.
;
SAVE_CONTEXT
        MOVEC   #$0300,SR       ;NO SCALING, SET IPL TO 3
        MOVEP   X:BCR,P:USR_BCR ;GET USER BCR
        MOVEP   #DSP_BCR,X:BCR          ;SET DSP BCR
        IF      EXETMR
        MOVEP   Y:ISR,P:DRTISR  ;GET DUART INTERRUPT STATUS REGISTER
        JCLR    #0,Y:STOP_CTR,*+2       ;STOP EXECUTION TIMER
        ENDIF
        MOVE    R0,P:USR_SR     ;SAVE USER'S SR
        MOVE    R1,P:USR_PC     ;SAVE USER'S PC
        MOVE    SSL,R0                  ;GET THE CALLER'S SR
        MOVE    SSH,R1                  ;GET THE CALLER'S PC
        MOVE    R2,P:USR_R2
        MOVE    R3,P:USR_R3
        MOVE    R4,P:USR_R4
        MOVE    R5,P:USR_R5
        MOVE    R6,P:USR_R6
        MOVE    R7,P:USR_R7
        MOVE    N0,P:USR_N0
        MOVE    N1,P:USR_N1
        MOVE    N2,P:USR_N2
        MOVE    N3,P:USR_N3
        MOVE    N4,P:USR_N4
        MOVE    N5,P:USR_N5
        MOVE    N6,P:USR_N6
        MOVE    N7,P:USR_N7
        MOVE    M0,P:USR_M0
        MOVE    M1,P:USR_M1
        MOVE    M2,P:USR_M2
        MOVE    M3,P:USR_M3
        MOVE    M4,P:USR_M4
        MOVE    M5,P:USR_M5
        MOVE    M6,P:USR_M6
        MOVE    M7,P:USR_M7
        MOVE    X0,P:USR_X0
        MOVE    X1,P:USR_X1
        MOVE    Y0,P:USR_Y0
        MOVE    Y1,P:USR_Y1
        MOVE    A2,P:USR_A2
        MOVE    A1,P:USR_A1
        MOVE    A0,P:USR_A0
        MOVE    B2,P:USR_B2
        MOVE    B1,P:USR_B1
        MOVE    B0,P:USR_B0
        MOVE    OMR,P:USR_OMR
        MOVE    LA,P:USR_LA
        MOVE    LC,P:USR_LC
        MOVE    SP,P:USR_SP     ;STACK POINTER
        MOVEP   X:IPR,P:USR_IPR ;GET INTERRUPT PRIORITY REGISTER
        MOVE    P:IODEV,X0              ;GET CURRENT USER I/O DEVICE
        MOVE    X0,P:USR_DEV            ;SAVE IT
;
;       SET FOR LINEAR ADDRESSING
;
        MOVE    #$FFFF,M0       ;SET ALL ADDRESS REGISTERS FOR LINEAR
        MOVE    M0,M1
        MOVE    M0,M2
        MOVE    M0,M3                               
        MOVE    M0,M4                                   
        MOVE    M0,M5
        MOVE    M0,M6
        MOVE    M0,M7
;
;       SAVE THE USER'S STACK
;
        MOVE    #_MTSTK,R5      ;PLACE TO JUMP TO IF STACK IS MT
        MOVE    #USTK+30,A      ;GET END OF USER STACK AREA
        MOVE    P:USR_SP,B      ;GET NUMBER OF STACK ENTRIES
        ASL     B                       ;2 ENTRIES/STACK ELEMENT
        SUB     B,A                     ;BACK UP POINTER
        MOVE    A1,R4                   ;BEGINNING OF SAVE AREA
        DUP     15              ;COULD BE 15 USER THINGS ON STACK
        MOVEC   SP,A            ;GET THE USER STACK POINTER
        TST     A               ;SEE IF IT IS ZERO (EMPTY)
        JEQ     (R5)            ;YES, JUMP OUT
        MOVE    SSL,P:(R4)+     ;SAVE LOW PART OF STACK
        MOVE    SSH,P:(R4)+     ;SAVE HIGH PART AND DEC SP
        ENDM
_MTSTK
        NOP
;
;       RESTORE THE PC OF THE SUBROUTINE THAT CALLED US
;
        MOVE    R1,SSH                  ;RESTORE CALLER'S PC
        MOVE    R0,SSL                  ;RESTORE CALLER'S SR
;
;       NOW THAT THE CALLER'S INFO ON THE STACK IS RESTORED, GO SET
;       THE TERMINAL FOR I/O AND RETURN TO THE CALLER
;
        JMP     SET_TERM                ;SET TERMINAL AS I/O DEVICE AND RETURN


        PAGE
             
CMDTBL
        DC      0,CMD,0                 ;NO COMMAND GIVEN
        DC      'BDA',BAUDA,BDA_HLP     ;SET BAUD RATE FOR DUART A
        DC      'BDB',BAUDB,BDB_HLP     ;SET BAUD RATE FOR DUART B
        DC      'BDS',BAUDSCI,BDS_HLP   ;SET BAUD RATE FOR SCI
        DC      'BRK',BREAK,BRK_HLP     ;BREAKPOINT COMMAND
        DC      'COP',MOVE_MEM,COP_HLP  ;COPY MEMORY
        DC      'DIS',DISREG,DIS_HLP    ;DISPLAY REGISTER IN A HORIZONTAL FORMAT
        DC      'DHE',HEXIT,DHE_HLP     ;SPECIFY/DISPLAY HOST EXIT CHARACTER
        DC      'DHP',DHP,DHP_HLP       ;DEFINE HOST PORT
        DC      'DMP',DUMP,DMP_HLP      ;DUMP MEMORY
        DC      'DST',STACK_D,DST_HLP   ;DISPLAY STACK
        DC      'DTP',DTP,DTP_HLP       ;DEFINE TERMINAL PORT
        DC      'DVD',DEVICES,DVD_HLP   ;DEVICE DISPLAY
        DC      'EVA',CALCULATE,EVA_HLP ;EVALUATE EXPRESSION
        DC      'FIL',FILL,FIL_HLP      ;FILL MEMORY
        DC      'FND',FIND,FND_HLP      ;FIND COMMAND
        DC      'GO ',GO,GO_HLP         ;GO EXECUTE PROGRAM/PROCEED EXECUTION
        DC      'GOB',GOB,GOB_HLP       ;GO WITH BREAKPOINT
        DC      'HEL',HELP,HEL_HLP      ;HELP COMMAND
        DC      'HST',HOST,HST_HLP      ;HOST TRANSPARENT MODE
        DC      'INI',INIT,INI_HLP      ;INITIALIZE DRIVER
        DC      'JSR',CALL,JSR_HLP      ;CALL SUBROUTINE
        DC      'LOA',LOAD,LOA_HLP      ;LOAD PROGRAM
        DC      'MEM',MEM,MEM_HLP       ;MEMORY DISPLAY/MODIFY COMMAND
        DC      'NBR',NBREAKS,NBR_HLP   ;SET/DISPLAY # OF BREAKS BEFORE STOPPING
        DC      'OFF',MDOFF,OFF_HLP     ;SHUT OFF BOARD 
        DC      'REG',REG,REG_HLP       ;REGISTER COMMAND
        DC      'RD ',MONITOR,MON_HLP   ;MONITOR MEMORY FOR CHANGES
        DC      'STK',STACK_E,STK_HLP   ;USER STACK EDIT
        DC      'TRA',TRACE,TRA_HLP     ;TRACE INSTRUCTIONS
        DC      'UPL',UPLOAD,UPL_HLP    ;UPLOAD MEMORY TO HOST
        DC      'VER',VERIFY,VER_HLP    ;VERIFY PROGRAM
        DC      'WRT',WRITE,WRT_HLP     ;WRITE LOCATION WITHOUT VERIFICATION
        DC      '***',CMD,RFU_HLP       ;RESERVED FOR USER
        DC      '***',CMD,RFU_HLP       ;RESERVED FOR USER
        DC      '***',CMD,RFU_HLP       ;RESERVED FOR USER
        DC      '***',CMD,RFU_HLP       ;RESERVED FOR USER
        DC      '***',CMD,RFU_HLP       ;RESERVED FOR USER
CMDTBLLEN       EQU     (*-CMDTBL)/3    ;LENGTH OF COMMAND TABLE        
                                                    
BDA_HLP DC      '[BAUD] SET BAUD RATE FOR DUART-A',0
BDB_HLP DC      '[BAUD] SET BAUD RATE FOR DUART-B',0
BDS_HLP DC      '[BAUD] SET BAUD RATE FOR SCI',0
BRK_HLP DC      '<[S,R,-,<CR>]> SET/REMOVE/REMOVE ALL/DISPLAY BREAKPOINTS',0
COP_HLP DC      '<[P,X,Y]>:<ADD1><ADD2> <[P,X,Y]>:<DEST>  COPY MEMORY',0
DIS_HLP DC      'DISPLAY USER REGISTERS',0
DHE_HLP DC      'DISPLAY/SET HOST COMMAND EXIT CHARACTER',0
DHP_HLP DC      '[DEV] DISPLAY/SET HOST PORT DRIVER NUMBER',0
DMP_HLP DC      '<[P,X,Y]>:<ADD1><ADD2>  DUMP MEMORY',0
DST_HLP DC      'DISPLAY THE DATA IN THE USER STACK',0
DTP_HLP DC      '[DEV] DISPLAY/SET HOST PORT DRIVER NUMBER',0
DVD_HLP DC      ' DISPLAY DEVICES IN DEVICE TABLE',0
EVA_HLP DC      '<NUM1><[+,-,*,/]><NUM2> FRACTIONAL CALCULATOR',0
FIL_HLP DC      '<[P,X,Y]>:<ADD1><ADD2><VALUE>  FILL MEMORY WITH VALUE',0
FND_HLP DC      '<[P,X,Y]>:<ADD1><ADD2><VALUE>[MASK] FIND VALUE IN MEMORY',0
GO_HLP  DC      '[ADDR]  START EXECUTION AT ADDRESS (OR CURRENT PC)',0
GOB_HLP DC      '[BRKPT] SET TEMP BREAKPOINT AND BEGIN EXECUTION AT PC',0
HEL_HLP DC      'THIS HELP MESSAGE',0                                       
HST_HLP DC      'ENTER TRANSPARENT COMMUNICATIONS WITH THE HOST PORT',0
INI_HLP DC      '<DEV>   INITIALIZE DEVICE DRIVER',0
JSR_HLP DC      '[ADDR] CALL USER SUBROUTINE AND RETURN TO MONITOR',0
LOA_HLP DC      'SEND <CR> TO HOST AND LOAD OMF RECORDS FROM HOST PORT',0
MEM_HLP DC      '<[P,X,Y]>:<ADDR> EXAMINE/CHANGE MEMORY',0
MON_HLP DC      '<[P,X,Y]>:<ADDR> READ MEMORY AND DISPLAY IF IT CHANGES',0
NBR_HLP DC      '[NBRKS] SET/DISPLAY NUMBER OF BREAKS TO HIT BEFORE STOPPING',0
OFF_HLP DC      'SHUT OFF BOARD (MULTIBOARD ONLY) AND WAIT FOR ITS ADDRESS',0
REG_HLP DC      'DISPLAY EACH REGISTER AND MODIFY',0
STK_HLP DC      'EDIT USER STACK',0
TRA_HLP DC      '[N] TRACE N INSTRUCTIONS',$0D0A20
        DC      '.  TRACE 1 INSTRUCTION.',0
UPL_HLP DC      'UPLOAD OMF RECORDS TO THE HOST PORT',0
VER_HLP DC      'SEND <CR> TO HOST PORT AND VERIFY RECORDS IN MEMORY',0
WRT_HLP DC      '<[P,X,Y]>:<ADDR> <N> [REP] WRITE VALUE',0
RFU_HLP DC      'RESERVED FOR USER DEFINITION (SEE ADDCMD)',0

PADTBL
        DC      25,16,8,25
MSKTBL
        DC      $000000,$FF0000,$FFFF00,$FFFFFF
BADCMD
        DC      '-- CMD ERR; ENTER: HEL',0
STKMT
        DC      'STACK EMPTY ',0
STKUNDER
        DC      'STACK UNDERFLOW',$200D0A,0
STKOVER
        DC      'STACK OVERFLOW',$200D0A,0
BRCTM
        DC      $200D0A         ;SP,CR,LF
        DC      'NUM BRKS=',0

SHLM
        DC      $200D0A
        DC      '    SSH  SSL',$200D0A,0

HEX1M
        DC      $200D0A,'HOST EXIT CHARACTER>',0
HEX2M
        DC      $200D0A,'VALUE OF HST EXIT CHARACTER: ',0

REGLST
        DC      ' R0 R1 R2 R3 R4 R5 R6 R7'
        DC      ' N0 N1 N2 N3 N4 N5 N6 N7'
        DC      ' M0 M1 M2 M3 M4 M5 M6 M7'
        DC      ' X0 X1 Y0 Y1'
        DC      ' A2 A1 A0 B2 B1 B0'
        DC      ' PC SROMR LA LC SPBCRIPR'
NUMREG  EQU     *-REGLST
REGLEN  
        DC      4,4,4,4,4,4,4,4         ;R0-R7
        DC      4,4,4,4,4,4,4,4         ;N0-N7
        DC      4,4,4,4,4,4,4,4         ;M0-M7       
        DC      6,6,6,6                 ;X0,X1,Y0,Y1
        DC      2,6,6,2,6,6             ;A,B
        DC      4,4,2,4,4,2,4,4         ;PC,SR,OMR,LA,LC,SP,BCR,IPR

REGSHFT                              
        DC      8,8,8,8,8,8,8,8         ;R0-R7
        DC      8,8,8,8,8,8,8,8         ;N0-N7
        DC      8,8,8,8,8,8,8,8         ;M0-M7
        DC      25,25,25,25             ;X0,X1,Y0,Y1
        DC      16,25,25,16,25,25       ;A,B
        DC      8,8,16,8,8,16,8,8       ;PC,SR,OMR,LA,LC,SP,BCR,IPR
OFFTBL            
        DC      13,5                     
        DC      -1,-17,8,8,4
        DC      13,5
        DC      -1,-20,8,8,6
        DC      1,6
        DC      1,1,-25,8,8,10
        DC      1,6
        DC      1,1,-29,8,8,-17
        DC      37,3
        DC      8,8,15
        DC      1,6
        DC      1,1,-34,8,8,19
        DC      1,6
        DC      1,1,-38,8,8,23
        DC      13,5
        DC      1,-41,8,8,0
INIMSG
        DC      $200D0A,'(C) COPYRIGHT MOTOROLA INC. 1988 ALL RIGHTS RESERVED'
        IF      HEXERR
        DC      $200D0A,'* INVALID HEX DIGITS IGNORED *'
        ELSE
        DC      $200D0A,'* INVALID HEX DIGITS ERRORED *'
        ENDIF
        IF      EXETMR
        DC      $200D0A,'* DUART TIMER IS EXECUTION TIMER *'
        ELSE
        DC      $200D0A,'* DUART TIMER IS UNUSED *'
        ENDIF
        DC      $0A0D0A,'V2.032488; $E000-$',0
GETMSG
        DC      ' ENTER: [P,X,Y]',0
EXEMSG
        DC      'EXEC TIME = ',0
TMRMSG
        DC      '  +/- ',0
TOFMSG
        DC      'EXEC TIME EXCEEDS .284 SEC',0
WNBPMSG
        DC      'WARNING: NO BREAKPOINTS SET',$200D0A,0
BADCM
        DC      ' HEX NUMERIC REQUIRED',0
UIM
        DC      $200D0A,'UNKNOWN SWI INTERRUPT AT ',0
RTNMSG
        DC      $200D0A,'USER RTS ',0
CMDMSG
        DC      $200D0A,'DSPBUG',0
BRKPMSG                                    
        DC      $200D0A,'BREAKPOINT',$200D0A,0
ABOMSG
        DC      $200D0A,'ABORT ',$200D0A,0
OPTMSG
        DC      ' -- ENTER: <CR>,<SP>,CTRL-C,CTRL-Y,^',0
BRKOPTMSG
        DC      ' -- ENTER: S,R,<CR>,-',0
BPTBLFUL
        DC      ' -- BREAKPOINT TABLE FULL',0
BPNTFND
        DC      ' -- BREAKPOINT NOT FOUND',0
BADFMT
        DC      ' -- ENTER: O,D',0
CALOPT
        DC      ' -- ENTER: +,-,*,/,.',0
BADREC
        DC      $200D0A,'BAD RECORD',0
MDOFFMSG
        DC      '-- NOT IN MULTIBOARD MODE',0
BADBAUD
        DC      'UNKNOWN BAUD RATE',0
BADSP
        DC      'ERROR: SE BIT ON STACK POINTER IS SET',0
BAUDTBL
        DC      $300,$44                ;300 BAUD
        DC      $1200,$66               ;1200 BAUD
        DC      $2400,$88               ;2400 BAUD
        DC      $4800,$99               ;4800 BAUD
        DC      $9600,$BB               ;9600 BAUD
        DC      $19200,$CC              ;19200 BAUD
BDTBLLEN        EQU     (*-BAUDTBL)/2   ;NUMBER OF BAUD RATES
;
;       SCI BAUD RATE TABLE.  THIS TABLE IS ONLY USED WHEN IN POWERUP
;       IN SPECIAL MODE AND ON THE SCI FOR THE TERMINAL PORT.
;
SCIBAUD
;                       20.48 MHZ TABLE
        DC      1067                    ;/1068, 300 BAUD - 0
        DC      266                     ;/267, 1200 BAUD - 1
        DC      132                     ;/133, 2400 BAUD - 2
        DC      66                      ;/67, 4800 BAUD  - 3
        DC      32                      ;/33, 9600 BAUD  - 4
        DC      16                      ;/17, 19200 BAUD - 5
        DC      7                       ;/8, 38.4K BAUD  - 6
        DC      3                       ;/4, 76.8K BAUD  - 7
;                       26.624 MHZ TABLE
        DC      1386                    ;/1387, 300 BAUD - 8
        DC      346                     ;/347, 1200 BAUD - 9
        DC      172                     ;/173, 2400 BAUD - 10
        DC      86                      ;/87,  4800 BAUD - 11
        DC      42                      ;/43,  9600 BAUD - 12
        DC      21                      ;/22, 19200 BAUD - 13
        DC      10                      ;/11, 38400 BAUD - 14
        DC      4                       ;/5,  76800 BAUD - 15
;
;       DUART INITIALIZATION TABLE FOR NORMAL MODE
;
DRTTBL
        DC      $02,$22         ;RESET RX
        DC      $02,$38         ;RESET TX
        DC      $0A,$22         ;RESET RX
        DC      $0A,$38         ;RESET TX

        DC      $02,$40         ;RESET ERROR STATUS
        DC      $02,$10         ;RESET POINTER
        DC      $0A,$40         ;RESET ERROR STATUS       
        DC      $0A,$10         ;RESET POINTER

        DC      $04,$B0         ;BAUD RATE SET 2, COUNTER MODE, X1/XTL CLOCK
        DC      $05,$00         ;CLEAR INTERRUPT MASK

        DC      $00,$13         ;8 BIT DATA, NO PARITY
        DC      $00,$07         ;1 STOP BIT
        IF      ALTBAUD
        DC      $01,$CC         ;19200 BAUD TX,RX
        ELSE
        DC      $01,$BB         ;9600 BAUD TX,RX
        ENDIF
        DC      $02,$05         ;ENABLE TX,RX
        DC      $08,$13         ;8 BIT DATA, NO PARITY
        DC      $08,$07         ;1 STOP BIT
        IF      ALTBAUD
        DC      $09,$CC         ;19200 BAUD TX,RX
        ELSE
        DC      $09,$BB         ;9600 BAUD TX,RX
        ENDIF
        DC      $0A,$05         ;ENABLE TX,RX
DTBLLEN EQU     (*-DRTTBL)/2
;
;       I/O DRIVER TABLE: DRIVER NUMBER, OUTPUT ROUTINE, INPUT, INIT
;
IOTBL
        DC      $000000,'NUL',OUT_NULL,IN_NULL,SET_NULL ;NULL DEVICE
        DC      $000001,'DRA',OUT_DRTA,IN_DRTA,SET_DRTA ;DUART A
        DC      $000002,'DRB',OUT_DRTB,IN_DRTB,SET_DRTB ;DUART B
        DC      $000003,'SCI',OUT_DSPSCI,IN_DSPSCI,SET_DSPSCI   ;SCI
        DC      $000004,'HST',OUT_DSPHOST,IN_DSPHOST,SET_DSPHOST        ;HOST
IOTBLLEN        EQU     (*-IOTBL)/5
;
;       TABLE FOR HEX TO BASE10 HEX CONVERSION
;
B10TBL
        DC      100000,10000,1000,100,10,1

ROMEND  EQU     *
ROMSIZE EQU     ROMEND-MROM     ;TOTAL SIZE OF PROGRAM IN EPROM
        IF      BOOTMODE==1
        IF      (ROMSIZE>5428)
        MSG     '     '
        MSG     '***************************************************'
        MSG     '** PROGRAM IS TO BIG TO DO BOOTSTRAP FROM EPROMS **'
        MSG     '***************************************************'
        ENDIF
        ENDIF

        IF      BOOTMODE==2
        ORG     P:$FFFF         ;POWERUP OPTION DEFALUT TO NORMAL
        DC      $FFFFFF
        MSG     '... DO NOT WORRY ABOUT THE WARNING YOU JUST RECEIVED.'
        ENDIF

        PAGE
;
;       SCRATCH PAD RAM FOR DSPBUG
;
        IF      BOOTMODE==1     ;IF IN RAM, START SCRATCH AFTER DSPBUG
        ORG     P:
        ENDIF
        IF      BOOTMODE==2     ;IF EXTERNAL EPROMS
        ORG     P:$40           ;START SCRATCH PAD INTERNAL
        ENDIF                   ;OTHERWISE, SCRATCH PAD FOLLOWS DSPBUG
        IF      BOOTMODE==3     ;IF IN RAM, START SCRATCH AFTER DSPBUG
        ORG     P:
        ENDIF
                                                                  
REGVAL  DS      NUMREG          ;REGISTER STORAGE
;
;       OFFSETS FOR USER REGISTERS
;
USR_R0  EQU     REGVAL+00
USR_R1  EQU     REGVAL+01
USR_R2  EQU     REGVAL+02
USR_R3  EQU     REGVAL+03
USR_R4  EQU     REGVAL+04
USR_R5  EQU     REGVAL+05
USR_R6  EQU     REGVAL+06
USR_R7  EQU     REGVAL+07
USR_N0  EQU     REGVAL+08
USR_N1  EQU     REGVAL+09
USR_N2  EQU     REGVAL+10
USR_N3  EQU     REGVAL+11
USR_N4  EQU     REGVAL+12
USR_N5  EQU     REGVAL+13
USR_N6  EQU     REGVAL+14
USR_N7  EQU     REGVAL+15
USR_M0  EQU     REGVAL+16
USR_M1  EQU     REGVAL+17
USR_M2  EQU     REGVAL+18
USR_M3  EQU     REGVAL+19
USR_M4  EQU     REGVAL+20
USR_M5  EQU     REGVAL+21
USR_M6  EQU     REGVAL+22
USR_M7  EQU     REGVAL+23
USR_X0  EQU     REGVAL+24
USR_X1  EQU     REGVAL+25
USR_Y0  EQU     REGVAL+26
USR_Y1  EQU     REGVAL+27
USR_A2  EQU     REGVAL+28
USR_A1  EQU     REGVAL+29
USR_A0  EQU     REGVAL+30
USR_B2  EQU     REGVAL+31
USR_B1  EQU     REGVAL+32
USR_B0  EQU     REGVAL+33
USR_PC  EQU     REGVAL+34
USR_SR  EQU     REGVAL+35
USR_OMR EQU     REGVAL+36
USR_LA  EQU     REGVAL+37
USR_LC  EQU     REGVAL+38
USR_SP  EQU     REGVAL+39
USR_BCR EQU     REGVAL+40
USR_IPR EQU     REGVAL+41

REGOLD  DS      NUMREG          ;OLD REGISTERS
MEMT    DS      1               ;MEMORY TYPE X,Y,P
BPLOC   DS      NUMBRK          ;BREAK POINT LOCATION TABLE
OPSAVE  DS      NUMBRK          ;USERS ACTUAL OPCODES
NUMTR   DS      1               ;NUMBER OF INSTRUCTIONS TO TRACE
USP     DS      1               ;USER'S STACK POINTER
USTK    DS      30              ;USER'S STACK
CFLAG   DS      1               ;CALL FLAG(=0 FOR GO, =1 FOR CALL)
VFLAG   DS      1               ;VERIFY/LOAD FLAG (=0 FOR LOAD, =1 FOR VERIFY)
VFMEM   DS      1               ;MEMORY DATA WHEN VERIFY FAILS
VFIN    DS      1               ;INPUT DATA WHEN VERIFY FAILS
IODEV   DS      1               ;DEVICE CODE FOR I/O DRIVERS
TDEV    DS      1               ;CODE FOR CURRENT TERMINAL DEVICE
HDEV    DS      1               ;CODE FOR CURRENT HOST DEVICE
USR_DEV DS      1               ;USER I/O DEVICE
IOSAVE  DS      1               ;CHARACTER SAVED WHILE CHECKING IO DEVICE
X0SAVE  DS      1               ;SAVED VALUE OF X0 WHILE DOING I/O
R0SAVE  DS      1               ;SAVED VALUE OF R0 WHILE DOING I/O
OUT1SAVE        DS      1       ;SAVED VALUE OF X0 WHILE DOING CTRL/S/Q
OUT3SAVE        DS      1       ;USED TO SAVE CHARACTERS BEING OUTPUT IN OUT3
NBRVAL  DS      1               ;NUMBER OF BREAKPOINTS TO HIT BEFORE STOPPING
NBRCT   DS      1               ;THE COUNT OF NUMBER OF BREAKPOINTS HIT SO FAR
HST_EXIT        DS      1       ;CHARACTER TO EXIT 'HST' COMMAND (DEFAULT CTRLA)
TEMP1   DS      1               ;TEMP FOR CALCULATIONS
TEMP2   DS      1               ;TEMP FOR CALCULATIONS
TEMP3   DS      1               ;TEMP FOR CALCULATIONS
IPR_TEMP        DS      1       ;TEMP FOR USER'S IPR BECAUSE OF DSP BUGS
DRTISR  DS      1               ;DUART ISR FOR TIMER
MDSTAT  DS      1               ;POWERUP STATUS OF DUART
MDADD   DS      1               ;MULDROP ADDRESS
LFLAG   DS      1               ;POINTER TO X/Y MEMORY WHEN LOADING L MEMORY
FRACSAVE        DS      1       ;TEMP FOR OUTFRAC SUBROUTINE
TEMPBP  DS      1               ;TEMP BREAKPOINT
RAMEND  EQU     *

        IF      BOOTMODE==3     ;IF 32Kx8 PART, INCLUDE THIS LOADER
;
;       LOADER FOR DSPBUG.  THIS LOADER IS USED ONLY WHEN THE 'MAP'
;       OPTION IS SET TO 1.  THIS MEANS THAT DSPBUG IS BOOTING FROM A 32Kx8
;       EPROM LOCATED AT 8000.  THIS LOADER IS LOCATED AT C000 BUT ORGED
;       AT 0.  AT POWERUP, THIS LOADER IS LOADED INTO INTERNAL MEMORY AT
;       P:0 AND THEN READS THE EPROM AT P:8000 AND TRANSFERS DSPBUG TO
;       MEMORY AT P:0800.
;
        OPT     NOINTR
        ORG     P:$0000,P:$4000 ;ORG AT 0, LOCATE AT (C000-8000)
;
        MOVE    #$8000,R0       ;START OF OP SYS IN EPROM
        MOVE    #MROM,R1        ;PLACE TO PUT OPSYS
        MOVE    #5428,X0
        DO      X0,_L1  ;5428 P STEPS OF DSPBUG
        DO      #3,_L2          ;3 BYTES/WORD
        MOVE    P:(R0)+,A2      ;GET BYTE
        REP     #8              ;SHIFT 
        ASR     A               ;TO FORM WORD
_L2
        MOVE    A1,P:(R1)+      ;SAVE IN PROG RAM
_L1
        JMP     MROM            ;GO START MONITOR
        ENDIF

        END
