;*****************************************************
;                                                    *
;                  DYNATRACE                         *
;                    V 2.0                           *
;                                                    *
;     COPYRIGHT (C) 1976, BY RICHARD E. MEADOR       *
;                            SACRAMENTO, CALIFORNIA  *
;                                             95826  *
;                                                    *
;      ALL RIGHTS RESERVED WITH THE EXCEPTION OF     *
; REPRODUCTION BY THOSE INDIVIDUALS FOR THEIR OWN    *
; NONCOMERCIAL USE WHO HAVE PURCHASED DYNATRACE FROM *
; AN AUTHORIZED DISTRIBUTOR.                         *
;                                                    *
;*****************************************************
;
;
;
	ORG	8000H
DYNAT:	DS	400H	;BASE ADDRESS OF PROGRAM
STACK   EQU     DYNAT+0C00H       ;SET UP SYSTEM STACK
CONPRT	EQU	0C8H	;CONTROL PORT ADDRESS
SCREEN  EQU     0BC00H  ;1K OF BUFFER FOR SCREEN
TOS     EQU     (SCREEN+1024)/256    ;LAST BUFFER ADDRESS+1
MIDSCR  EQU     SCREEN+448      ;TOP LINE OF ROLLUP PORTION OF SCREEN
LINE    EQU     64      ;64 CHARACTERS/LINE
LINE1   EQU     SCREEN+LINE
LINE2   EQU     LINE1+64
LINE3   EQU     LINE2+64
LINE4   EQU     LINE3+64
LINE5   EQU     LINE4+64
LINE15  EQU     SCREEN+960
PCH     EQU     LINE1+8 ;PC HEX DISPLAY LOCATION
INSTA   EQU     LINE2+8 ;INSTRUCTION ASCII DISPLAY LOCATION
INSTH   EQU     LINE2+18        ;INSTRUCTION HEX DISPLAY LOCATION
SB      EQU     LINE4+8 ;SIGN FLAG BINARY DISPLAY LOCATION
ZB      EQU     LINE4+9 ;ZERO FLAG BINARY DISPLAY LOCATION
ACB     EQU     LINE4+11        ;AUX CARRY FLAG BINARY DISPLAY LOCATION
PB      EQU     LINE4+13        ;PARITY FLAG BINARY DISPLAY LOCATION
CYB     EQU     LINE4+15        ;CARRY FLAG BINARY DISPLAY LOCATION
ACCH    EQU     LINE1+22        ;ACCUMULATOR HEX DISPLAY LOCATION
ACCB    EQU     LINE1+25        ;ACCUMULATOR BINARY DISPLAY LOCATION
BCH     EQU     LINE1+37        ;B REG HEX DISPLAY LOCATION
BCB     EQU     LINE1+42        ;B REG BINARY DISPLAY LOCATION
DEH     EQU     LINE2+37        ;DE REG PR HEX DISPLAY LOCATION
DEB     EQU     LINE2+42        ;DE REG PR BINARY DISPLAY LOCATION
HLH     EQU     LINE3+37        ;HL REG PR HEX DISPLAY LOCATION
HLB     EQU     LINE3+42        ;HL REG PR BINARY DISPLAY LOCATION
SPH     EQU     LINE4+37        ;SP REG PR HEX DISPLAY LOCATION
KSTAT   EQU     6EH
KEYBRD  EQU     6CH
KBDRDY  EQU     80H
RSTAT	EQU	07H
READER  EQU     06H
RDRRDY  EQU     02H
SWTCHS  EQU     0FFH
CR      EQU     0DH
LF      EQU     0AH
ESC     EQU     1BH
;
;
;STORAGE DEFINITION STATEMENTS
;
        ORG     DYNAT+0B80H   ;SYSTEM WORKING STORAGE AREA
PC1:	DS	2	;USER'S PROGRAM COUNTER STORAGE
STKPTR:	DS	2	;USER'S STACK POINTER STORAGE
BC:     DS      2       ;USER'S BC REG PR STORAGE
DE:     DS      2       ;USER'S DE REG PR STORAGE
HL:     DS      2       ;USER'S HL REG PR STORAGE
STSWRD: DS      1       ;USER'S STATUS FLAG STORAGE
AC:     DS      1       ;USER'S ACCUMULATOR STORAGE
PC:     DS      2       ;USER'S PRIMARY PROGRAM COUNTER STORAGE
BINFLG: DB      0       ;BINARY DISPLAY SWITCH(0=>NO BINARY DISPLAY)
CPOSIT: DS      2       ;CURSER POSITION FOR ROLLUP PORTION OF SCREEN
STKTMP: DS      2       ;TEMPORARY STORAGE FOR SYSTEM STACK
BASE:   DS      2       ;BASE ADDRESS STORAGE FOR VARIOUS ROUTINES
LAST:   DS      2       ;LAST    '       '     '     '       '
FROM:   DB      'FROM-' ;MESSAGES
TO:     DB      'TO-'   ;
ASCII:  DB      '0123456789ABCDEF'      ;ASCII HEX DIGIT TABLE
MOVENM: DB      'MOV  ,  '      ;MOVE MNUMONIC
	DB	'COPYRIGHT (C) 1976, RICHARD E. MEADOR'
;
;CODE BEGINS HERE
;
	ORG	100H
DBYTE	EQU	8000H	;PROGRAM WILL RUN HERE

	LXI	H,0400H	;PROGRAM BASE POINTER
	LXI	D,DBYTE	;NEW BASE POINTER
LOOP	MOV	A,M	;PICK UP 1ST CHAR
	STAX	D	;STORE AT NEW BASE
	INX	H
	INX	D
	MOV	A,H	;MOVE POINTER
	CPI	10H	;
	JNZ	LOOP	;DO UNTIL DONE
	JMP	DBYTE	;GO TO NEW LOCATION
;
;
;
        ORG     DYNAT   ;START ADDRESS
START:  LXI     SP,STACK        ;DEFINE SYSTEM STACK
        CALL    CLRSCR  ;CLEAR VIDEO SCREEN
        CALL    SETSCR  ;SET UP DISPLAY OF USER REGISTERS
        MVI     A,0     ;CLEAR ACCUMULATOR
        MVI     B,14    ;SET CLEAR COUNT
        LXI     H,PC1   ;SET FIRST ADDRESS TO BE CLEARED
VDM010: MOV     M,A     ;CLEAR
        INX     H       ;NEXT ADDRESS
        DCR     B       ;1 LESS TO DO
        JNZ     VDM010  ;DONE?
        LXI     H,PC1        ;YES, DEFINE USER'S STACK POINTER
        SHLD    STKPTR      ;
VDM015: CALL    DSREGS  ;DISPLAY CONTENTS OF USER'S REGISTERS
        CALL    KEYBDI  ;GET COMMAND
        CPI     40H     ;CHECK FOR ALPHA
        JM      VDM020  ;IGNORE IF NOT
        CPI     5BH     ;
        JP      VDM020  ;
        LXI     H,KEYTAB        ;GET COMMAND LOCATOR TABLE BASE ADDRESS
        SBI     40H     ;SUBTRACT ASCII BIAS FROM RECEIVED COMMAND
        RLC             ;DOUBLE FOR WORD INDEXING
        ADD     L       ;ADD INDEX
        MOV     L,A     ;
        MVI     A,0     ;        ADC     H       ;
        MOV     H,A     ;
        MOV     E,M     ;GET COMMAND ADDRESS FROM TABLE
        INX     H       ;
        MOV     D,M     ;
        LXI     H,VDM020        ;SET UP RETURN ADDRESS
        PUSH    H       ;SAVE ON STACK
        XCHG            ;HL=COMMAND ROUTINE ADDRESS
        PCHL            ;(THIS IS REALLY A CALL TO A COMMAND ROUTINE)
VDM020: LXI     H,LINE15        ;RESET CURSOR
        SHLD    CPOSIT  ;
        JMP     VDM015  ;END OF COMMAND PROCESSING LOOP
;
;COMMAND LOCATOR TABLE
;
KEYTAB: DW      UTURN   ;A-NOP
        DW      BINARY  ;B-BINARY DISPLAY TOGGLE
        DW      CALSUB  ;C-CALL USER SUB-PROGRAM
        DW      DUMPME  ;D-DUMP MEMORY TO SCREEN
        DW      UTURN   ;E-NOP
        DW      UTURN   ;F-NOP
        DW      GO      ;G-EXECUTE USER PROGRAM INTERPRETIVELY
        DW      UTURN   ;H-NOP
        DW      ISPEED  ;I-SET EXECUTION SPEED OF INTERPRETER
        DW      UTURN   ;J-NOP
        DW      UTURN   ;K-NOP
        DW      LOADRG  ;L-LOAD REGISTER PAIR
        DW      MEMSTR  ;M-STORE BYTES IN CONSECUTIVE MEMORY LOCATIONS
        DW      UTURN   ;N-NOP
        DW      UTURN   ;O-NOP
        DW      UTURN   ;P-NOP
        DW      UTURN   ;Q-NOP
        DW      READTP  ;R-READ PAPER TAPE
        DW      STEP    ;S-INTERPRET ONE INSTRUCTION
        DW      UTURN   ;T-NOP
        DW      UTURN   ;U-NOP
        DW      UTURN   ;V-NOP
        DW      UTURN   ;W-NOP
        DW      UTURN   ;X-NOP
        DW      UTURN   ;Y-NOP
        DW      ZERMEM  ;Z-ZERO MEMORY
;
;
;
UTURN:  RET             ;DUMMY ROUTINE FOR NOP'S
;
;
;  CLEAR VDM ROUTINE
;
CLRSCR: MVI     A,0     ;CONTROL PORT IINITIALIZATUIION WORD
        OUT     CONPRT  ;SEND
        LXI     B,SCREEN        ;BASE ADDRESS OF VDM BUFFER
CLR010: MVI     A,' '   ;ASCII SPACE
        STAX    B       ;CLEAR 1 BUFFER WORD
        INX     B       ;UPDATE BUFFER POINTER
        MVI     A,TOS AND 0FFH   ;LAST BUFFER ADDRESS +1
        CMP     B       ;CHECK FOR END OF BUFFER AREA
        JNZ     CLR010  ;DO UNTIL DONE
        LXI     H,LINE15        ;INITIAL CURSOR LOCATION
        SHLD    CPOSIT  ;STORE TO CURSOR SAVE
        RET             ;EXIT
;
;  SET DISPLAY OF USER'S REGISTERS
;
SETSCR: LXI     H,'PC'          ;PC
        SHLD    LINE1+5
        MVI     A,'A'           ;A
        STA     LINE1+20
        LXI     H,'BC'          ;BC
        SHLD    LINE1+34
        LXI     H,'IN'          ;IN
        SHLD    LINE2+2
        LXI     H,'ST'          ;ST
        SHLD    LINE2+4
        MVI     A,'R'           ;R
        STA     LINE2+6
        LXI     H,'DE'          ;DE
        SHLD    LINE2+34
        MVI     A,'C'           ;C
        STA     LINE3+15
        MVI     A,'Z'           ;Z
        STA     LINE3+9
        MVI     A,'P'           ;P
        STA     LINE3+13
        MVI     A,'S'           ;S
        STA     LINE3+8
        MVI     A,'A'           ;A
        STA     LINE3+11
        LXI     H,'HL'          ;HL
        SHLD    LINE3+34
        LXI     H,'SP'          ;SP
        SHLD    LINE4+34
        LXI     H,'PS'
        SHLD    LINE4+4
        MVI     A,'W'
        STA     LINE4+6
        MVI     A,'0'
        STA     LINE4+10
        STA     LINE4+12
        INR     A
        STA     LINE4+14
        RET
;
;MOVE THE NUMBER OF BYTES INDICATED IN DE
;FROM THE ADDRESS BEGINNING IN BC
;TO THE ADDRESS BEGINNING IN HL
;
SETLNE: LDAX    B       ;GETBYTE
        MOV     M,A     ;TRANSFER
        INX     H       ;UPDATE DESTINATION POINTER
        INX     B       ;UPDATE SOURCE POINTER
        DCX     D       ;UPDATE COUNT
        MOV     A,E     ;CHECK FOR COMPLETION
        CPI     0       ;
        JNZ     SETLNE  ;
        MOV     A,D     ;
        CPI     0       ;
        JNZ     SETLNE  ;
        RET             ;EXIT
;
; DISPLAY REGISTERS ROUTINE
;
;THIS ROUTINE DECODES THE USER'S REGISTER INFORMATION
;     AND FORMATS IT FOR DISPLAY ON THE CRT SCREEN
;
DSREGS: PUSH    B       ;SAVE ALL REGISTERS
        PUSH    D       ;
        PUSH    H       ;
        PUSH    PSW     ;
        LXI     D,PC1   ;
        LXI     H,PCH+2 ;
        CALL    DSPHEX  ;
        LXI     D,PC1+1 ;
        LXI     H,PCH   ;
        CALL    DSPHEX  ;
        LXI     D,STKPTR    ;
        LXI     H,SPH+2 ;
        CALL    DSPHEX  ;
        LXI     D,STKPTR+1  ;
        LXI     H,SPH   ;
        CALL    DSPHEX  ;
        LXI     D,BC    ;
        LXI     H,BCH+2 ;
        CALL    DSPHEX  ;
        LXI     D,BC+1  ;
        LXI     H,BCH   ;
        CALL    DSPHEX  ;
        LXI     D,DE    ;
        LXI     H,DEH+2 ;
        CALL    DSPHEX  ;
        LXI     D,DE+1  ;
        LXI     H,DEH   ;
        CALL    DSPHEX  ;
        LXI     D,HL    ;
        LXI     H,HLH+2 ;
        CALL    DSPHEX  ;
        LXI     D,HL+1  ;
        LXI     H,HLH   ;
        CALL    DSPHEX  ;
        LXI     D,AC    ;
        LXI     H,ACCH  ;
        CALL    DSPHEX  ;
        LDA     STSWRD  ;
        LXI     H,CYB   ;
        RAR             ;
        MVI     M,'0'   ;
        JNC     DSR010  ;
        MVI     M,'1'   ;
DSR010: RAR             ;
        RAR             ;
        LXI     H,PB    ;
        MVI     M,'0'   ;
        JNC     DSR020  ;
        MVI     M,'1'   ;
DSR020: RAR             ;
        RAR             ;
        LXI     H,ACB   ;
        MVI     M,'0'   ;
        JNC     DSR030  ;
        MVI     M,'1'   ;
DSR030: RAR             ;
        RAR             ;
        LXI     H,ZB    ;
        MVI     M,'0'   ;
        JNC     DSR040  ;
        MVI     M,'1'   ;
DSR040: RAR             ;
        LXI     H,SB    ;
        MVI     M,'0'   ;
        JNC     DSR050  ;
        MVI     M,'1'   ;
DSR050: POP     PSW     ;
        POP     H       ;
        POP     D       ;
        POP     B       ;
        LDA     BINFLG  ;CHECK FOR BINARY DISPLAY FLAG SET
        ANA     A       ;
        RZ              ;DONE IF NOT SET
        PUSH    B       ;
        PUSH    D       ;
        PUSH    H       ;
        PUSH    PSW     ;
        LXI     D,AC    ;
        LXI     H,ACCB  ;
        CALL    DSPBIN  ;
        LXI     D,BC    ;
        LXI     H,BCB+9 ;
        CALL    DSPBIN  ;
        LXI     D,BC+1  ;
        LXI     H,BCB   ;
        CALL    DSPBIN  ;
        LXI     D,DE    ;
        LXI     H,DEB+9 ;
        CALL    DSPBIN  ;
        LXI     D,DE+1  ;
        LXI     H,DEB   ;
        CALL    DSPBIN  ;
        LXI     D,HL    ;
        LXI     H,HLB+9 ;
        CALL    DSPBIN  ;
        LXI     D,HL+1  ;
        LXI     H,HLB   ;
        CALL    DSPBIN  ;
        POP     PSW     ;
        POP     H       ;
        POP     D       ;
        POP     B       ;
        RET             ;
;
; DECODE REGISTERS FOR DISPLAY ROUTINE
;
DSPHEX: LDAX    D       ;GET REGISTER CONTENTS
        RRC             ;SCALE ACCUMULATOR DOWN TO GET UPPER HEX DIGIT
        RRC             ;
        RRC             ;
        RRC             ;
        ANI     0FH     ;MASK OFF UNWANTED BITS
        LXI     B,ASCII ;BASE ADDRESS OF ASCIIDIGIT TABLE
        ADD     C       ;ADD ACCUMULATOR TO BC TO GET ADDRESS OF DIGIT
        MOV     C,A     ;
        MVI     A,0     ;
        ADC     B       ;
        MOV     B,A     ;
        LDAX    B       ;
        MOV     M,A     ;STORE ASCII CODE FOR HEX DIGIT
        INX     H       ;INCREMENT SCREEN POSITION
        LDAX    D       ;GET REGISTER CONTENTS AGAIN
        ANI     0FH     ;DO THE SAME FOR THE LOWER HEX DIGIT
        LXI     B,ASCII ;
        ADD     C       ;
        MOV     C,A     ;
        MVI     A,0     ;
        ADC     B       ;
        MOV     B,A     ;
        LDAX    B       ;
        MOV     M,A     ;
        RET             ;
;
; DECODE REGISTER TO BINARY DISPLAY ROUTINE
;
DSPBIN: LDAX    D       ;GET USER REGISTER CONTENTS
        MVI     C,8     ;# OF BITS
DSP010: RAL             ;SHIFT UPPER BIT TO CARRY FOR CHECKING
        MVI     M,'0'   ;ASSUME ZERO
        JNC     DSP020  ;CHECK FOR ONE
        MVI     M,'1'   ;CHANGE IF ONE
DSP020: INX     H       ;MOVE TO NEXT SCREEN POSITION
        DCR     C       ;COUNT OFF
        JNZ     DSP010  ;DONE?
        RET             ;YES
;
;SIMULATOR CODE BEGINS HERE
;  ONE 8080 INSTRUCTION AS INDICATED BY THE USER'S PC REGISTER
STEP:   LHLD    PC      ;GET USER'S PROGRAM COUNTER VALUE
        SHLD    PC1     ;SAVE FOR LAGGING DISPLAY
        MOV     A,M     ;GET THE CONTENTS OF MEMORY LOCATION INDICATED
        CPI     40H     ;CHECK FOR CODES 0-3F HEX
        JC      STP010  ;LOW ORDER 64 OPCODES?
        CPI     80H     ;NO, CHECK FOR 40-7F HEX
        JNC     STP020  ;IS A REGISTER TO REGISTER MOVE INSTRUCTION?
        CALL    MOVE    ;YES, EXECUTE IT
        RET             ;RETURN TO MONITOR
STP010: CALL    OPLOW   ;LOW ORDER OP CODES
        RET             ;RETURN TO MONITOR
STP020: CPI     0C0H    ;CHECK FOR 80-BF HEX
        JNC     STP030  ;ARTHMETIC INSTRUCTION?
        CALL    ARITH   ;YES, EXECUTE
        RET             ;RETURN TO MONITOR
STP030: CALL    OPHIGH  ;HIGH ORDER OP CODE
        RET             ;RETURN TO MONITOR
;
; EXECUTE INSTRUCTION ROUTINE
;
OPEXEC: LXI     H,0     ;SAVE MONITOR'S STACK POINTER
        DAD     SP
        SHLD    STKTMP
        LHLD    STSWRD  ;LOAD REAL REGISTERS WITH USER'S DATA
        PUSH    H       
        POP     PSW     
        LHLD    STKPTR
        SPHL
        LHLD    BC
        MOV     B,H
        MOV     C,L
        LHLD    DE
        XCHG
        LHLD    HL
INSTR:  DS      3       ;INSTRUCTION TO BE EXECUTED IS STORED HERE
                        ; IF IT WILL NOT CAUSE LOSS OF CONTROL
        SHLD    HL      ;SAVE USER REGISTER VALUES
        PUSH    PSW     ;
        POP     H       ;
        SHLD    STSWRD  ;
        LXI     H,0     ;
        DAD     SP      ;
        SHLD    STKPTR      ;
        XCHG            ;
        SHLD    DE      ;
        LHLD    STKTMP  ;GET MONITOR'S STACK POINTER
        SPHL            ;
        MOV     H,B     ;
        MOV     L,C     ;
        SHLD    BC      ;
        RET             ;
;
; MOV COMMAND EXECUTION ROUTINE
;
MOVE:   MOV     B,A     ;SAVE OP CODE
        ANI     07H     ;DECODE SOURCE REGISTER
        MVI     D,0     ;
        MOV     E,A     ;
        LXI     H,RGSTRS        ;
        DAD     D       ;
        MOV     A,M     ;GET REGISTER NAME
        STA     MOVENM+6   ;SET UP NMEUMONIC
        MOV     A,B     ;RESTORE OP CODE
        RRC             ;
        RRC             ;
        RRC             ;
        ANI     07H     ;DO SAME FOR DESTINATION REGISTER
        MOV     E,A     ;
        LXI     H,RGSTRS        ;
        DAD     D       ;
        MOV     A,M     ;
        STA     MOVENM+4   ;
        MOV     A,B     ;
        MVI     B,1     ;# OF BYTES IN INSTRUCTION
        CALL    MVINST  ;COPY INSTRUCTION INTO EXECUTION AREA
        LXI     H,INSTA ;DISPLAY NMEUMONIC
        LXI     B,MOVENM   ;
        LXI     D,8     ;
        CALL    SETLNE  ;
        CALL    OPEXEC  ;GO EXECUTE INSTRUCTION
        RET             ;DONE,
;
; ARITHMETIC INSTRUCTION EXECUTION ROUTINE
;
ARITH:  MOV     B,A     ;SAVE OP CODE
        LXI     H,ARITHN        ;GET ADDRESS OF ARITH NMEUMONICS
        ANI     38H     ;ISOLATE REGISTER OPERAND
        MVI     D,0     ;
        MOV     E,A     ;
        DAD     D       ;ADD INDEX TO GET APPROPRIATE NMEUMONIC
        PUSH    H       ;SAVE TEMPORARILY
        MOV     A,B     ;RESTORE OPCODE
        ANI     07H     ;ISOLATE REGISTER OPERAND #
        LXI     H,RGSTRS        ;GET REGISTER NAME LIST ADDRESS
        MOV     E,A     ;
        DAD     D       ;ADD INDEX TO GET CORRECT REGISTER NMEUMONIC
        MOV     A,M     ;GET NMEUMONIC
        POP     H       ;RETRIEVE INSTRUCTION NMEUMONIC ADDRESS
	MVI	E,4	;
	DAD	D	;
        MOV     M,A     ;MOVE REGISTER NAME TO MEMORY
        DCX     SP      ;
        DCX     SP      ;
        MOV     A,B     ;RESTORE OP CODE
        MVI     B,1     ;SET # OF BYTES IN OPCODE
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        LXI     H,INSTA ;DISPLAY NMEUMONIC
        LXI     D,8     ;
        POP     B       ;
        CALL    SETLNE  ;
        CALL    OPEXEC  ;GO EXECUTE INSTRUCTION
        RET             ;
;
;ARITHMETIC INSTRUCTION NMEUMONICS
;
ARITHN: DB      'ADD     '      ;ADD REGISTER TO ACCUMULATOR
        DB      'ADC     '      ;ADD REGISTER+CARRY TO ACCUMULATOR
        DB      'SUB     '      ;SUB REGISTER FROM ACCUMULATOR
        DB      'SBB     '      ;SUB REGISTER+CARRY FROM ACCUMULATOR
        DB      'ANA     '      ;LOGICAL AND REGISTER WITH ACCUMULATOR
        DB      'XRA     '      ;LOGICAL EXCLUSIVE OR REGISTER WITH ACCU
        DB      'ORA     '      ;LOGICAL OR REGISTER WITH ACCUMULATOR
        DB      'CMP     '      ;COMPARE REGISTER WITH ACCUMULATOR
;
; LOW ORDER INSTRUCTION EXECUTION ROUINE
; OP CODES 0-3F HEX
OPLOW:  MOV     E,A     ;SAVE OP CODE
        ANI     07H     ;DETERMINE CLASS AND BRANCH TO APPRPRIATE ROUTINE
        RLC             ;
        MOV     C,A     ;
        MVI     B,0     ;
        LXI     H,OPTAB ;
        DAD     B       ;
        MOV     A,E     ;
        MOV     E,M     ;
        INX     H       ;
        MOV     D,M     ;
        XCHG            ;
        PCHL            ;
;
;OP CODE SIMULATION ROUTINE LOOKUP TABLE
;
OPTAB:  DW      NPINST     ; NO-OP ROUTINE POINTER
        DW      LXIDAD  ; LXI & DAD ROUTINE POINTER
        DW      LDSTRX  ; LDAX & STAX ROUTIN POINTER
        DW      INXDCX  ;INX & DCX ROUTINE POINTER
        DW      INRDCR  ; INR & DCR ROUTINE POINTER
        DW      INRDCR  ; SAME
        DW      MVIMM     ; MVI ROUTINE POINTER
        DW      ROTATE  ; ROTATE POINTER
;
; A=OP CODE, B= NO. OF BYTES
;
MVINST: STA     INSTR   ;STORE OP CODE TO EXECUTION AREA
        PUSH    B       ;SAVE NUMBER OF BYTES IN OP CODE
        CALL    HEXASC  ;CONVERT OP CODE TO ASCII/HEX EQUIVALANT
        MOV     H,C     ;TRANSFER FOR DOUBLE LENGTH STORE
        MOV     L,B     ;
        SHLD    INSTH   ;STORE ASCII CODES OF OP CODE TO VDM BUFFER
        POP     B       ;RETRIEVE NUMBER OF BYTES IN INSTRUCTION
        LXI     D,INSTR+1       ;GET ADDRESS OF NEXT LOCATION IN EXECUTI
        MVI     A,0     ;ZERO NEXT 2 BYTES IN EXECUTION AREA
        STAX    D       ;    IN CASE INSTRUCTION<3 BYTES
        STA     INSTR+2 ;
        MVI     H,' '   ;CLEAR PREVIOUS EXECUTION FROM SCREEN
        MOV     L,H     ;
        SHLD    INSTH+2 ;
        SHLD    INSTH+4 ;
        LXI     H,INSTH+2       ;SET TO DISPLAY REST OF INSTRUCTION IF A
        SHLD    STKTMP  ;SAVE VDM BUFFER LOCATION OF ASCII/HEX DISPLAY A
        LHLD    PC      ;GET USER'S PROGRAM COUNTER
        INX     H       ;UPDATE IT
MVI010: DCR     B       ;COUNT OFF NUMBER OF BYTES IN INSTRUCTION
        JZ      MVI020  ;EXIT IF DONE
        MOV     A,M     ;GET NEXT BYTE OF INSTRUCTION FROM USER'S PROGRA
        INX     H       ;UPDATE USER'S PROGRAM COUNTER
        STAX    D       ;STORE BYTE TO EXECUTION AREA
        INX     D       ;UPDATE EXECUTION BUFFER POINTER
        PUSH    B       ;SAVE NUMBER OF BYTES IN INSTRUCTION
        PUSH    D       ;SAVE EXECUTION BUFFER POINTER
        PUSH    H       ;SAVE USER'S PROGRAM COUNTER
        CALL    HEXASC  ;CONVERT NEXT BYTE OF INSTRUCTION TO ASCII/HEX C
        LHLD    STKTMP  ;RETRIEVE VDM BUFFER LOCATIN OF ASCII/HEX DISPLA
        MOV     M,B     ;MOVE ASCII/HEX CODES OF CURRENT INSTRUCTION BYT
        INX     H       ;   TO VDM BUFFER AREA
        MOV     M,C     ;
        INX     H       ;
        SHLD    STKTMP  ;SAVE VDM BUFFER LOCATION AGAIN
        POP     H       ;RETRIEVE USER'S PROGRAM COUNTER
        POP     D       ;RETRIEVE EXECUTION BUFFER POINTER
        POP     B       ;RETRIEVE NUMBER OF BYTES LEFT IN INSTRUCTION
        JMP     MVI010  ;CONTINUE UNTIL ALL BYTES MOVED
MVI020: SHLD    PC      ;STORE UPDATED USER'S PROGRAM COUNTER
        RET             ;EXIT
;
;
; MOVE NMUMONIC TO BUFFER
;
MVNMNC: LXI     H,INSTA ;GET VDM BUFFER LOCATION OF MNEUMONIC DISPLAY AR
        PUSH    D       ;SAVE D REGISTER
        LXI     D,4     ;SET NUMBER OF BYTES TO TRANSFER
        CALL    SETLNE  ;DO TRANSFER
        POP     B       ;GET OLD D REGISTER
        MVI     D,' '   ;THE FOLLOWING CODE MOVES THE ASCII CHARACTERS O
        MOV     M,D     ;   THE REGISTERS USED BY THE INSTRUCTION TO THE
        INX     H       ;       THE VDM BUFFER AREA
        MOV     M,C     ;
        INX     H       ;
        MOV     M,B     ;
        INX     H       ;
        MOV     M,D     ;
        RET             ;
;
; GET REGISTER PAIR ROUTINE
;
GETRP:  ANI     30H     ;MASK REGISTER PAIR FIELD
        RRC             ;SCALE FOR INDEXING
        RRC             ;
        RRC             ;
        MOV     E,A     ;BUILD INDEX IN DE
        MVI     D,0     ;
        LXI     H,REGPAR        ;GET BASE ADDRESS OF REG PAIR MNEUMONICS
        DAD     D       ;ADD INDEX
        SHLD    GET010+1        ;SAVE POINTER
GET010: LHLD    0       ;0 IS REPLACED BY POINTER FROM ABOVE
        XCHG            ;POSITION FOR SUB ROUTINE CALL
        CALL    MVNMNC  ;DISPLAY OP CODE
        RET             ;
;
; EXECUTE NO-OP ROUTINE
;
NPINST:    MVI     B,1     ;SET INSTRUCTION LENGTH
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        LXI     D,'  '  ;NO REGISTER DATA
        LXI     B,LOWOP ;ADDRESS OF NOP MNEUMONIC
        CALL    MVNMNC  ;DISPLAY OP CODE
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
;  EXECUTE LXI AND DAD INSTRUCTIONS ROUTINE
;
LXIDAD:	MOV	B,A	;SAVE INSTRUCTION
        ANI     08H     ;ISOLATE LXI/DAD BIT
        MOV     A,B     ;RESTORE INSTRUCTION
        MVI     B,1     ;ASSUME DAD INSTRUCTION
        JNZ     LXI010  ;DAD OR LXI?
	MVI	B,3	;LXI, CHANGE INSTRUCTION LENGTH TO 3 BYTES
LXI010: PUSH    PSW     ;SAVE INSTRUCTION DESIGNATOR WHICH IS THE ZERO F
        CALL    MVINST  ;DISPLAY OP CODE
        POP     PSW     ;RETRIEVE FLAG
        LXI     B,LOWOP1+4      ;ASSUME DAD
        JNZ     LXI020  ;DAD/LXI?
	LXI	B,LOWOP1	;LXI, CHANGE POINTER
LXI020: CALL    GETRP   ;ISOLATE REG PAIR
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
; LDA STA LDAX STAX SHLD LHLD  EXECUTION ROUTINE
;
LDSTRX: MOV     C,A     ;SAVE INSTRUCTION
        ANI     20H     ;ISOLATE (LDX,STX)/(LHLD,SHLD,LDA,STA) BIT
        MOV     A,C     ;RESTORE INSTRUCTION
        JNZ     LDS020  ;(LDX,STX)/(LHLD,SHLD,LDA,STA)?
        ANI     08H     ;ISOLATE LDX/STX BIT
        MOV     A,C     ;RESTORE INSTRUCTION
        MVI     B,1     ;INSTRUCTION LENGTH IS 1 FOR BOTH
        PUSH    PSW     ;SAVE DESIGNATOR BIT
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        POP     PSW     ;RETRIEVE DESIGNATOR BIT
        LXI     B,LOWOP2        ;ASSUME STAX
        JZ      LDS010  ;STAX/LDAX?
	LXI	B,LOWOP2+4	;LDAX, CHANGE MNEUMONIC POINTER
LDS010: CALL    GETRP   ;DETERMINE REGISTER PAIR
        JMP     LDS030  ;GO EXECUTE
LDS020:	MVI	B,3	;(LHLD,SHLD,LDA,STA), SET LENGTH TO 3 BYTES
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        MOV     A,C     ;RESTORE INSTRUCTION
        ANI     18H     ;ISOLATE INSTRUCTION DESIGNATOR
        RRC             ;SCALE FOR INDEXING
        MOV     E,A     ;BUILD INDEX
        MVI     D,0     ;
        LXI     H,LOWOP2+8      ;GET BASE ADDRESS OF INSTRUCTION GROUP
        DAD     D       ;ADD INDEX
        MOV     B,H     ;POSITION FOR CALL
        MOV     C,L     ;
        LXI     D,'  '  ;SET REG TYPE TO NULL
        CALL    MVNMNC  ;DISPLAY CODE
LDS030: CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
; INX DCX EXECUTION ROUTINE
;
INXDCX: MOV     C,A     ;SAVE INSTRUCTION
        MVI     B,1     ;THESE ARE ALL ONE BYTE
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        MOV     A,C     ;RESTORE INSTRUCTION
        PUSH    PSW     ;SAVE IT AGAIN
        ANI     08H     ;ISOLATE DESIGNATOR BIT
        LXI     B,LOWOP3        ;ASSUME INX
        JZ      INX010  ;INX/DCX?
	LXI	B,LOWOP3+4	;DCX, CHAINGE POINTER
INX010: POP     PSW     ;GET INSTRUCTION BACK
        CALL    GETRP   ;DETERMINE REG PAIR
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
; INR DCR EXECUTION ROUTINE
;
INRDCR: MOV     C,A     ;SAVE INSTRUCTION
        MVI     B,1     ;THESE ARE ALL ONE BYTE
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        MOV     A,C     ;RESTORE INSTRUCTION
        STA     STKTMP  ;SAVE IT AGAIN
        LXI     B,LOWOP4        ;ASSUME INR
        ANI     01H     ;CHECK DESIGNATOR BIT
        JZ      INR010  ;INR/DCR?
	LXI	B,LOWOP5	;DCR, CHANGE POINTER
INR010: LDA     STKTMP  ;GET INSTRUCTION BACK
        CALL    GETREG  ;DETERMINE REGISTER
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
; MVI EXECUTION ROUTINE
;
MVIMM:    MOV     C,A     ;SAVE INSTRUCTION
        MVI     B,2     ;THESE ARE ALL 2 BYTE INSTRUCTIONS
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        MOV     A,C     ;RESTORE INSTRUCTION
        LXI     B,LOWOP6        ;SET POINTER MVI MNEUMONIC
        CALL    GETREG  ;DETERMINE REGISTER
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
; RLC RRC RAL RAR DAA CMA STC CMC
; EXECUTION ROUTINE
;
ROTATE: MOV     C,A     ;SAVE INSTRUCTION
        MVI     B,1     ;THESE ARE ALL ONE BYTE INSTRUCTIONS
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        MOV     A,C     ;RESTORE INSTRUCTION
        ANI     38H     ;ISOLATE DESIGNATOR BITS
        RRC             ;SCALE FOR INDEXING
        MOV     E,A     ;CONSTRUCT INDEX
        MVI     D,0     ;
        LXI     H,LOWOP7        ;GET BASE OF ADDRESS OF MNEUMONICS
        DAD     D       ;ADD INDEX
        MOV     C,L     ;POSITION ADDRESS FOR SUBROUTINE CALL
        MOV     B,H     ;
        LXI     D,'  '  ;SET REGISTER TO NULL
        CALL    MVNMNC  ;DISPLAY OP CODE
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
; GET REGISTER ROUTINE
;
GETREG: ANI     38H     ;ISOLATE REGISTER DESIGNATOR BITS
        RRC             ;SCALE FOR INDEXING
        RRC             ;
        RRC             ;
        MOV     E,A     ;CONSTRUCT INDEX WORD
        MVI     D,0     ;
        LXI     H,RGSTRS        ;GET BASE ADDRESS OF REGISTER CODES
        DAD     D       ;ADD INDEX
        MVI     E,' '   ;OTHER REGISTER IS NULL
        MOV     D,M     ;GET THIS REGISTER
        CALL    MVNMNC  ;DISPLAY OP CODE AND REGISTER
        RET             ;
LOWOP:  DB      'NOP '  ;NO-OP
LOWOP1: DB      'LXI '  ;LOAD REGISTER PAIR IMMEDIATE(EXTENDED)
        DB      'DAD '  ;DOUBLE LENGTH ADD
LOWOP2: DB      'STAX'  ;STORE ACCUMULATOR INDIRECT THROUGH REG PAIR
        DB      'LDAX'  ;LOAD ACCUMULATOR INDIRECT THROUGH REG PAIR
        DB      'SHLD'  ;STORE HL DIRECT
        DB      'LHLD'  ;LOAD HL DIRECT
        DB      'STA '  ;STORE ACCUMULATOR DIRECT
        DB      'LDA '  ;LOAD ACCUMULATOR DIRECT
LOWOP3: DB      'INX '  ;INCREMENT REGISTER PAIR
        DB      'DCX '  ;DECREMENT REGISTER PAIR
LOWOP4: DB      'INR '  ;INCREMENT REGISTER
LOWOP5: DB      'DCR '  ;DECREMENT REGISTER
LOWOP6: DB      'MVI '  ;MOVE DATA IMMEDIATE TO REGISTER
LOWOP7: DB      'RLC '  ;ROTATE LEFT THROUGH CARRY
        DB      'RRC '  ;ROTATE RIGHT THROUGH CARRY
        DB      'RAL '  ;ROTATE ARITHMETIC LEFT
        DB      'RAR '  ;ROTATE ARITHMETIC RIGHT
        DB      'DAA '  ;DECIMAL ADJUST ACCUMULATOR
        DB      'CMA '  ;COMPLIMENT ACCUMULATOR
        DB      'STC '  ;SET CARRY
        DB      'CMC '  ;COMPLIMENT CARRY
RGSTRS: DB      'BCDEHLMA'      ;REGISTER CODES
REGPAR: DB      'B D H SP'      ;REGISTER PAIR CODES
FLAGS:  DB      'NZZ NCC POPEP M '      ;STATUS FLAG CODES
;
;
;
KEYBDI: PUSH    H       ;SAVE HL
        LHLD    CPOSIT  ;GET CURSOE POSITION
KEY005: IN      KSTAT  ;CHECK 3P+S STATUS
        ANI     KBDRDY  ;LOOK FOR KEY BOARD READY
        JNZ     KEY005  ;LOOP ON NO DATA AVAILABLE
        IN      KEYBRD  ;GET DATA FROM ASCII KEYBOARD
        ANI     7FH     ;STRIP OFF PARITY BIT
        MOV     B,A     ;SAVE CHARACTER
        CPI     ESC     ;CHECK FOR ESCAPE SEQUENCE
        JNZ     KEY007  ;WAS IT?
	LXI	SP,STACK	;YES, RESET STACK POINTER
        CALL    BMPLNE  ;SCROLL UP ONE LINE
        JMP     VDM015  ;RESUME SCAN LOOP
KEY007: CPI     CR      ;CHECK FOR CARRIAGE RETURN
        JZ      KEY020  ;WAS IT
KEY010:	MOV	M,A	;NO, DISPLAY CHARACTER
        INX     H       ;UPDATE CURSER
        MOV     A,H     ;CHECK FOR VDM BUFFER OVERFLOW
        CPI     TOS AND 0FFH     ;
        JC      KEY030  ;
KEY020: CALL    BMPLNE  ;SCROLL UP ON BUFFER FULL
        LXI     H,LINE15        ;RESET CURSOR TO BEGINNING OF LAST LINE
KEY030: MOV     A,B     ;RESTORE CHARATER RECEIVED FROM KEYBOARD
        SHLD    CPOSIT  ;STORE UPDATED CURSOR
        POP     H       ;RESTORE ORIGINAL CONTENTS OF HL
        RET             ;
;
;
;
BMPLNE: PUSH    H       ;SAVE HL
        PUSH    D       ;SAVE DE
        PUSH    B       ;SAVE BC
        PUSH    PSW     ;SAVE PSW
        LXI     H,MIDSCR        ;BUFFER ADDRESS TO MOVE OLD DATA TO
        LXI     B,MIDSCR+LINE   ;BUFFER ADDRESS TO GET OLD DATA FROM
        MVI     E,8     ;NUMBER OF LINES TO BE SCROLLED
BMP010: PUSH    D       ;SAVE
        LXI     D,64    ;NUMBER OF CHARACTERS PER LINE
        CALL    SETLNE  ;SCROLL ONE LINE AT A TIME FROM THE TOP DOWN
        POP     D       ;GET NUMBER OF LINES LEFT TO GO
        DCR     E       ;COUNT OFF ONE MORE
        JNZ     BMP010  ;DO UNTIL DONE
        MVI     A,' '   ;STE TO SPACE OUT LAST LINE
        MVI     D,64    ;BLANK OUT ALL CHARACTERS ON LAST LINE
        LXI     H,LINE15        ;GET ADDRESS OF FIRST CHARACTER OF LAST 
BMP020: MOV     M,A     ;BLANK IT OUT
        INX     H       ;UPDATE POINTER
        DCR     D       ;COUNT DOWN
        JNZ     BMP020  ;DO WHILE NOT DONE
        LXI     H,LINE15        ;RESET CURSOR
        SHLD    CPOSIT  ;
        POP     PSW     ;RESTORE ORIGINAL REGISTER CONTENTS
        POP     B       ;
        POP     D       ;
        POP     H       ;
        RET             ;
;
;
;
BINARY: LDA     BINFLG  ;GET BINARY DISPLAY FLAG
        CMA             ;TOGGLE IT
        STA     BINFLG  ;PUT IT BACK
        CALL    CLRSCR  ;RESET SCREEN
        CALL    SETSCR  ;
        RET             ;
;
;
;
GTLMTS: CALL    BMPLNE  ;SCROLL UP
        LXI     B,FROM  ;DISPLAY FROM MESSAGE
        LXI     H,LINE15        ;
        LXI     D,5     ;
        CALL    SETLNE  ;
        LXI     H,LINE15+5      ;
        SHLD    CPOSIT  ;
        CALL    GETADR  ;GET ONE HEX NUMBER OF UP TO 4 DIGITS
        SHLD    BASE    ;THAT WAS THE BASE ADDRESS
        CALL    BMPLNE  ;SCROLL UP
        LXI     B,TO    ;DISPLAY TO MESSAGE
        LXI     H,LINE15        ;
        LXI     D,3     ;
        CALL    SETLNE  ;
        LXI     H,LINE15+3      ;
        SHLD    CPOSIT  ;
        CALL    GETADR  ;GET ONE HEX NUMBER
        XCHG            ;MOVE TO DE
        LHLD    BASE    ;GET BASE ADDRESS
        CALL    BMPLNE  ;SCROLL UP
        RET             ;
;
;
;
DUMPME: CALL    GTLMTS  ;GET DUMP LIMITS
DMP010: PUSH    D       ;SAVE LAST ADDRESS
        CALL    DMEM16  ;DISPLAY 16 BYTES
        POP     D       ;GET LAST ADDRESS
        MOV     A,E     ;SEE IF LAST ADDRESS EXCEEDED
        SUB     L       ;
        MOV     A,D     ;
        SBB     H       ;
        JP      DMP010  ;CONTINUE DUMPING IF NOT
        RET             ;
;
;
;
GETBYT: MVI     E,2     ;GET TWO CHARACTERS FROM KEY BOARD
	JMP	GTA005	;GO AROUND NEXT ENTRY POINT
GETADR:	MVI	E,4	;GET 4 CHARACTERSFROM KEYBOARD
GTA005:	LXI	H,0	;START WITH ZERO
GTA010:	CALL	KEYBDI	;GET ACHARACTER FROM THE KEYBOARD
        CPI     CR      ;CHECK FOR TERMINATOR
        JZ      GTA020  ;EXIT ON END OF NUMBER
        CALL    ASCHEX  ;CONVERT CHARACTER TO HEX DIGIT
        MOV     C,A     ;POISITION FOR ADD
        MVI     B,0     ;
        DAD     H       ;MULTIPLY HL BY 16
        DAD     H       ;
        DAD     H       ;
        DAD     H       ;
        DAD     B       ;ADD LAST CHARACTER RECIEVED
        DCR     E       ;COUNT OFF NUMBER OF DIGITS
        JNZ     GTA010  ;DO UNTIL COUNT EXAUSTED OR CARRIAGE RETURN
GTA020: RET             ;
;
;
;
ASCHEX: SBI     '0'     ;SUBTRACT OFF ASCII BIAS
        JM      ASC010  ;CHAR<0?
        CPI     10      ;NO,
        RC              ;DONE IF CHAR<=9
        SBI     07H     ;ADJUST FOR ALPHA BIAS
        CPI     LF      ;
        JC      ASC010  ;
        CPI     10H     ;CHAR>0FH?
        RC              ;NO, RETURN
ASC010: MVI     A,0     ;RETURN ZERO IF ILLEAGLE
        RET             ;
;
;DUMP 16 BYTES TO TTY
;
DMEM16: MOV     A,L     ;DISPLAY ADDRESS
        CALL    HEXASC  ;
        PUSH    B       ;
        MOV     A,H     ;
        CALL    HEXASC  ;
        LXI     D,LINE15        ;
        XCHG            ;
        MOV     M,B     ;
        INX     H       ;
        MOV     M,C     ;
        INX     H       ;
        POP     B       ;
        MOV     M,B     ;
        INX     H       ;
        MOV     M,C     ;
        MVI     B,16    ;NUMBER OF BYTES TO DISPLAY
DME010: PUSH    B       ;SAVE
        INX     H       ;UPDATE ADDRESS
        LDAX    D       ;GET BYTE FROM MEMORY
        INX     D       ;UPDATE POINTER
        CALL    HEXASC  ;CONVERT TO ASCII CHARACTERS AND DISPLAY
        INX     H       ;
        MOV     M,B     ;
        INX     H       ;
        MOV     M,C     ;
        POP     B       ;
        DCR     B       ;
        JNZ     DME010  ;DO UNTIL ALL 16 DISPLAYED
        CALL    BMPLNE  ;SCROLL UP
        XCHG            ;
        RET             ;
;
;CONVERT BYTE IN ACCUMULATOR TO ASCII DIGITS
;
HEXASC: PUSH    D       ;SAVE DE
        PUSH    H       ;SAVE HL
        LXI     H,ASCII ;GET BASE ADDRESS OF ASCII CODE
        MOV     B,A     ;SAVE DATA
        ANI     0FH     ;DO LOWER HEX DIGIT FIRST
        MOV     E,A     ;SET UP FOR INDEXING
        MVI     D,0     ;
        DAD     D       ;ADD INDEX
        MOV     C,M     ;GET CHARACTER
        MOV     A,B     ;RESTORE DATA
        ANI     0F0H    ;DO UPPER HEX DIGIT
        RRC             ;SCALE DOWN FOR INDEXING
        RRC             ;
        RRC             ;
        RRC             ;
        MOV     E,A     ;SET UP FOR INDEXING
        LXI     H,ASCII ;GET BASE ADDRESS OF ASCII CODES AGAIN
        DAD     D       ;ADD INDEX
        MOV     B,M     ;GET CHARACTER
        POP     H       ;RESTORE HL
        POP     D       ;RESTORE DE
        RET             ;
;
;LOAD REGISTERS FROM KEYBOARD ROUTINE
;
LOADRG: CALL    KEYBDI  ;GET REGISTER IDENTIFIER
        LXI     H,LDREGS        ;DETERMINE SELECTED REGISTER
        MVI     D,6     ;6 POSSIBLE REGISTER PAIRS
        MOV     B,A     ;SAVE REGISTER DESIGNATOR
LOA010: MOV     A,M     ;GET ONE FROM MEMORY
        CMP     B       ;CHECK AGAINST SELECTED REGISTER PAIR
        JZ      LOA020  ;MATCH
        INX     H       ;NO, KEEP LOOKING
        DCR     D       ;
        JNZ     LOA010  ;
        RET             ;RETURN IF NOT FOUND
LOA020: MOV     A,D     ;GET INDEX NUMBER
        DCR     A       ;ADJUST
        RLC             ;SCALE
        MOV     E,A     ;SET UP INDEX
        MVI     D,0     ;
        PUSH    D       ;SAVE INDEX
        CALL    GETADR  ;GET A HEX NUMBER FROM KEYBOARD
        XCHG            ;RELOCATE NUMBER TO LESS CONVENIENT REGISTER
        POP     H       ;GET INDEX BACK
        MOV     A,L     ;MOVE TO ACCUMULATOR
        ANA     A       ;SET FLAGS
        JNZ     LOA030  ;IS IT THE PC REGISTER?
        PUSH    H       ;YES,
        LXI     B,PC    ;GET ADDRESS OF USER'S PC REG
        DAD     B       ;THIS IS REDUNDANT
        MOV     M,E     ;STORE DATA TO USER'S PC REGISTER
        INX     H       ;
        MOV     M,D     ;
        POP     H       ;
LOA030: LXI     B,PC1   ;STORE DATE TO USER REGISTER
        DAD     B       ;
        MOV     M,E     ;
        INX     H       ;
        MOV     M,D     ;
        CALL    BMPLNE  ;
        RET             ;
LDREGS: DB      'AHDBSP'        ;POSSIBLE REGISTER DESIGNATIONS
;
;STORE DATA TO MEMORY ROUTINE
;
MEMSTR: CALL    GETADR  ;GET BEGINNING ADDRESS
MEM010: PUSH    H       ;SAVE IT
        LHLD    CPOSIT  ;GET CURSOR POSITION
        MVI     A,'-'   ;DISPLAY PROMPT
        MOV     M,A     ;
        INX     H       ;UPDATE CURSOR
        SHLD    CPOSIT  ;RESTORE UPDATED CURSOR
        CALL    GETBYT  ;GET A DATA BYTE
        MOV     A,E     ;GET NUMBER OF BYTES RECIEVED
        CPI     2       ;CHECK FOR NONE RECIEVED
        JNZ     MEM020  ;ANY DATA RECIEVED?
        POP     H       ;NO, RESTORE HL
        RET             ;GET OUT OF HERE
MEM020: MOV     A,L     ;MOVE DATA BYTE TO ACCUMULATOR
        POP     H       ;GET ADDRESS BACK
        MOV     M,A     ;STORE DATA TO MEMORY
        INX     H       ;UPDATE ADDRESS
        JMP     MEM010  ;CONTINUE
;
;CALL USER SUBROUTINE
;
CALSUB: LHLD    CPOSIT  ;GET CURSOE POSITION
        MVI     A,'-'   ;DISPLAY PROMPT
        MOV     M,A     ;
        INX     H       ;UPDATE CURSOR POSITION
        SHLD    CPOSIT  ;RESTORE CURSOR
        MVI     A,0CDH  ;LOAD ACCUMULATOR WITH A CALL INSTRUCTION
        STA     INSTR   ;MOVE TO EXECUTION AREA
        CALL    GETADR  ;GET ADDRESS OF SUBROUTINE TO BE EXECUTED
        SHLD    INSTR+1 ;STORE ADDRESS TO EXECUTION AREA PLUS ONE
        CALL    BMPLNE  ;SCROLL UP
        CALL    OPEXEC  ;EXECUTE SUBROUTINE
        CALL    CLRSCR  ;CLEAR ANY GARBAGE FROM SCREEN
        CALL    SETSCR  ;SET UPSCREEN AGAIN
        RET             ;
;
;HIGH ORDER INSTRUCTION DECODE ROUTINE
;
OPHIGH: MOV     E,A     ;SAVE INSTRUCTION
        ANI     07H     ;DETERMINE SUB CLASS
        RLC             ;SCALE FOR INDEX
        MOV     C,A     ;POSITION FOR INDEXING
        MVI     B,0     ;
        LXI     H,HOPTAB        ;GET HIGH ORDER INSTRUCTION TABLE BASE A
        DAD     B       ;ADD INDEX
        MOV     A,E     ;RESTORE INSTRUCTION
        MOV     E,M     ;GET ADDRESS OF INSTRUCTION ROUTINE
        INX     H       ;
        MOV     D,M     ;
        XCHG            ;MOVE TO HL
        PCHL            ;PASS CONTROL TO APPROPIATE ROUTINE
;
HOPTAB: DW      RETURN  ;RETURN
        DW      PPINST     ;POP
        DW      JUMP    ;JUMP
        DW      MISC    ;MISC
        DW      CLINST    ;CALL
        DW      PSINST    ;PUSH
        DW      IMMEDT  ;IMMEDIATE
        DW      RESTRT  ;RESTART
;
HIGHOP: DB      'R   '  ;CONDITIONAL RETURN
HIHOP1: DB      'POP '  ;POP
        DB      'RET '  ;UNCONDITIONAL ROUTINE
        DB      '*NOP'  ;UNIMPLEMENTED OP CODES
        DB      'PCHL'  ;INDIRECT JUMP
        DB      'SPHL'  ;LOAD STACK POINTER WITH HL
HIHOP2: DB      'J   '  ;CONDITIONAL JUMP
HIHOP3: DB      'JMP '  ;UNCONDITIONAL JUMP
        DB      '*NOP'  ;UNIMPLEMENTED OP CODE
        DB      'OUT '  ;OUTPUT
        DB      'IN  '  ;INPUT
        DB      'XTHL'  ;EXCHANGE HL AND TOP OF STACK
        DB      'XCHG'  ;EXCHANGE HL AND DE
        DB      'DI  '  ;DISABLE INTERRUPTS
        DB      'EI  '  ;ENABLE INTERRUPTS
HIHOP4: DB      'C   '  ;CONDITIONAL CALL
HIHOP5: DB      'PUSH'  ;PUSH
        DB      'CALL'  ;UNCONDITIONAL CALL
        DB      '*NOP'  ;UNIMPLEMENTED OP CODE
HIHOP6: DB      'ADI '  ;ADD IMMEDIATE
        DB      'ACI '  ;ADD IMMEDIATE WITH CARRY
        DB      'SUI '  ;SUBTRACT IMMEDIATE
        DB      'SBI '  ;SUBTRACT IMMEDIATE WITH BORROW
        DB      'ANI '  ;AND IMMEDIATE
        DB      'XRI '  ;EXCLUSIVE OR IMMEDIATE
        DB      'ORI '  ;OR IMMEDIATE
        DB      'CPI '  ;COMPARE IMMEDIATE
HIHOP7: DB      'RST '  ;RESTART
;
;DETERMINE CONDITIONAL FLAG ROUTINE
;
GTFLAG: ANI     38H     ;ISOLATE CONDITION BITS
        PUSH    H       ;SAVE HL
        RRC             ;SCALE FOR INDEXING
        RRC             ;
        MVI     D,0     ;
        MOV     E,A     ;CONSTRUCT INDEX
        LXI     H,FLAGS ;GET BASE ADDRESS OF FLAG CODES
        DAD     D       ;ADD INDEX
        MOV     A,M     ;GET FLAG CODE
        STAX    B       ;STORE TO VDM BUFFER
        INX     B       ;UPDATE POINTER
        INX     H       ;UPDATE FLAG LOCATOR
        MOV     A,M     ;GET SECOND CHARACTER OF FLAG
        STAX    B       ;DISPLAY IT
        LXI     D,'  '  ;OTHER CHARACTERS ARE BLANK
        POP     B       ;GET OLD HL
        CALL    MVNMNC  ;DISPLAY OP CODE
        RET             ;
;
;TEST FLAG FOR CONDITION
;
TSTFLG: ANI     38H     ;ISOLATE FLAG
        ORI     0C0H    ;ASSEMBLE A RETURN ON CONDITION INSTRUCTION
        STA     TST010  ;STORE FOR LATER EXECUTION
        LHLD    STSWRD  ;GET USER STATUS WORD
        PUSH    H       ;MOVE TO REAL FLAGS
        POP     PSW     ;
        MVI     A,1     ;A=1 MEANS CONDITION TRUE
TST010: RET             ;THIS IS REPLACED BY A CONDITIONAL RETURN
        MVI     A,0     ;CLEAR A IF CONDITION FALSE
        RET             ;
;
;CONDITIONAL JUMPS
;
JUMP:   LHLD    PC      ;GET USER PROGRAM COUNTER
        PUSH    H       ;SAVE IT
        PUSH    PSW     ;SAVE PSW
        MVI     B,3     ;THIS IS 3 BYTES
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        POP     PSW     ;GET PSW BACK
        PUSH    PSW     ;SAVE IT AGAIN
        LXI     H,HIHOP2        ;ADDRESS OF MNEUMONIC
        LXI     B,HIHOP2+1      ;ADDRESS TO PUT FLAG INTO
        CALL    GTFLAG          ;WHAT CONDITION?
        POP     PSW             ;GET INSTRUCTION BACK
        CALL    TSTFLG          ;TEST CONDITION
        POP     H               ;GET PC AGAIN
        ANA     A               ;CHECK RESULT OF FLAG TEST
        RZ              ;RETURN IF RESULT WAS NEGATIVE
        INX     H       ;UPDATE PC
        MOV     A,M     ;GET ADDRESS TO JUMP TO
        STA     PC      ;AND STORE TO USER'S PROGRAM COUNTER
        INX     H       ;
        MOV     A,M     ;
        STA     PC+1    ;
        RET             ;
;
;THIS ROUTINE PROCESSES ALL IMMEDIATE MODE COMMANDS
;
IMMEDT: MOV     C,A     ;SAVE INSTRUCTION
        MVI     B,2     ;ALL ARE 2 BYTES
        CALL    MVINST  ;MOVE INSTRUCTION TO EXECUTION AREA
        MOV     A,C     ;RSTORE INSTRUCTION
        ANI     38H     ;DETERMINE TYPE OF IMMEDIATE INSTRUCTION
        RRC             ;SCALE FOR INDEXING
        MOV     E,A     ;POSITION FOR INDEXING
        MVI     D,0     ;
        LXI     H,HIHOP6        ;GET BASE ADDRESS OF IMMEDIATE CODES
        DAD     D       ;ADD INDEX
        MOV     B,H     ;POSITION FOR SUBROUTINE CALL
        MOV     C,L     ;
        LXI     D,'  '  ;OTHER CHARACTERS ARE BLANK
        CALL    MVNMNC  ;DISPLAY MNEUMONIC
        CALL    OPEXEC  ;EXECUTE INSTRUCTION
        RET             ;
;
;MISCELANEOUS INSTRUCTIONS
;
MISC:   PUSH    PSW     ;SAVE INSTRUCTION
        ANI     38H     ;DETERMINE TYPE
        RRC             ;
        MOV     E,A     ;
        MVI     D,0     ;
        LXI     H,HIHOP3        ;
        DAD     D       
        MOV     C,L     ;
        MOV     B,H     ;
        LXI     D,'  '  ;
        CALL    MVNMNC  ;DISPLAY CODE
        POP     PSW     ;GET INSTRUCTION
        CPI     0E3H    ;
        JNC     XSDE    ;
        CPI     0D3H    ;
        JNC     IO      ;
        CPI     0CBH    ;
        JNC     NOOP    ;
        MVI     B,3     ;
        CALL    MVINST  ;
        LHLD    PC      ;
        DCX     H       ;
        MOV     A,M     ;
        STA     PC+1    ;
        DCX     H       ;
        MOV     A,M     ;
        STA     PC      ;
        RET             ;
NOOP:   LXI     B,HIHOP5+8      ;
        LXI     D,'  '  ;
        CALL    MVNMNC  ;
        MVI     B,1     ;
        CALL    MVINST  ;
        RET             ;
IO:     MVI     B,2     ;
        CALL    MVINST  ;
        CALL    OPEXEC  ;
        RET             ;
XSDE:   MVI     B,1     ;
        CALL    MVINST  ;
        CALL    OPEXEC  ;
        RET             ;
;
;CONDITIONAL CALL ROUTINE
;
CLINST: PUSH    PSW     ;
        MVI     B,3     ;
        CALL    MVINST  ;
        POP     PSW     ;
        PUSH    PSW     ;
        LXI     H,HIHOP4        ;
        LXI     B,HIHOP4+1      ;
        CALL    GTFLAG  ;
        POP     PSW     ;
        CALL    TSTFLG  ;
        ANA     A       ;
        RZ              
CAL010: LHLD    PC      ;
        XCHG            ;
        LHLD    STKPTR      ;
        DCX     H       ;
        MOV     M,D     ;
        DCX     H       ;
        MOV     M,E     ;
        SHLD    STKPTR      ;
        LHLD    PC      ;
        DCX     H       ;
        MOV     A,M     ;
        STA     PC+1    ;
        DCX     H       ;
        MOV     A,M     ;
        STA     PC      ;
        RET             ;
;
;CONDITIONAL RETURN
;
RETURN: PUSH    PSW     ;
        MVI     B,1     ;
        CALL    MVINST  ;
        POP     PSW     ;
        PUSH    PSW     ;
        LXI     H,HIGHOP        ;
        LXI     B,HIGHOP+1      ;
        CALL    GTFLAG  ;
        POP     PSW     ;
        CALL    TSTFLG  ;
        ANA     A       ;
        RZ              ;
RET010: LHLD    STKPTR      ;
        MOV     A,M     ;
        STA     PC      ;
        INX     H       ;
        MOV     A,M     ;
        STA     PC+1    ;
        INX     H       ;
        SHLD    STKPTR      ;
        RET             ;
;
;MISCELAEOUS STACK INSRUCTIONS
;
STKWRD: DB      ' B   D   H   PSW'      ;
;
PPINST: PUSH    PSW     ;
        ANI     08H     ;
        JNZ     NOTPOP  ;
        LXI     B,HIHOP1        ;
POP010: LXI     D,4     ;
        LXI     H,INSTA ;
        CALL    SETLNE  ;
        POP     PSW     ;
        PUSH    PSW     ;
        ANI     '0'     ;
        RRC             ;
        RRC             ;
        MOV     C,A     ;
        MVI     B,0     ;
        LXI     H,STKWRD        ;
        DAD     B       ;
        MOV     B,H     ;
        MOV     C,L     ;
        LXI     H,INSTA+4       ;
        LXI     D,4     ;
        CALL    SETLNE  ;
        POP     PSW     ;
        MVI     B,1     ;
        CALL    MVINST  ;
        CALL    OPEXEC  ;
        RET             ;
NOTPOP: POP     PSW     ;
        CPI     0C9H    ;
        JNZ     NOTRET  ;
        MVI     B,1     ;
        CALL    MVINST  ;
        LXI     B,HIHOP1+4      ;
        LXI     D,'  '  ;
        CALL    MVNMNC  ;
        JMP     RET010  ;
NOTRET: CPI     0F9H    ;
        JNZ     NTSPHL  ;
        MVI     B,1     ;
        CALL    MVINST  ;
        LXI     B,HIHOP1+16     ;
        LXI     D,'  '  ;
        CALL    MVNMNC  ;
        LHLD    HL      ;
        SHLD    STKPTR      ;
        RET             ;
NTSPHL: CPI     0E9H    ;
        JNZ     NOOP    ;
        MVI     B,1     ;
        CALL    MVINST  ;
        LXI     B,HIHOP1+12     ;
        LXI     D,'  '  ;
        CALL    MVNMNC  ;
        LXI     H,HL    ;
        MOV     A,M     ;
        STA     PC      ;
        INX     H       ;
        MOV     A,M     ;
        STA     PC+1    ;
        RET             ;
;
;PUSH AND UNCONDITIONAL CALL
;
PSINST: PUSH    PSW     ;
        ANI     08H     ;
        JNZ     CALLUN  ;
        LXI     B,HIHOP5        ;
        JMP     POP010  ;
CALLUN: POP     PSW     ;
        CPI     0CDH    ;
        JNZ     NOOP    ;
        LHLD    PC      ;
        PUSH    H       ;
        MVI     B,3     ;
        CALL    MVINST  ;
        LXI     B,HIHOP5+4      ;
        LXI     D,'  '  ;
        LXI     H,INSTA ;
        CALL    MVNMNC  ;
        POP     B       ;
        JMP     CAL010  ;
;
;RESTARTS
;
RESTRT: PUSH    PSW     ;
	MVI	B,1	;
	POP	PSW	;
        PUSH    PSW     ;
        ANI     38H     ;
        RRC             ;
        RRC             ;
        RRC             ;
        CALL    HEXASC  ;
        MOV     D,C     ;
        MVI     E,' '   ;
        LXI     B,HIHOP7        ;
        CALL    MVNMNC  ;
        LHLD    PC      ;
        XCHG            ;
        LHLD    STKPTR      ;
        DCX     H       ;
        MOV     M,D     ;
        DCX     H       ;
        MOV     M,E     ;
        SHLD    STKPTR      ;
        POP     PSW     ;
        ANI     38H     ;
        MOV     L,A     ;
        MVI     H,0     ;
        SHLD    PC      ;
        RET             ;
;
;THE GO ROUTINE CONTROLS SIMULATED EXECUTION OF USER PROGRAMS
;
GO:     LHLD    CPOSIT  ;
        MVI     A,'-'   ;
        MOV     M,A     ;
        INX     H       ;
        SHLD    CPOSIT  ;
        CALL    GETADR  ;
        SHLD    PC      ;
        CALL    BMPLNE  ;
        LXI     B,STPADR        ;
        LXI     D,8     ;
        LXI     H,LINE15        ;
        CALL    SETLNE  ;
        LXI     H,LINE15+8      ;
        SHLD    CPOSIT  ;
        CALL    GETADR  ;
        CALL    BMPLNE  ;
        XCHG            ;
GO010:  LHLD    PC      ;
        MOV     A,D     ;
        SUB     H       ;
        JNZ     GO020   ;
        MOV     A,E     ;
        SUB     L       ;
        RZ              ;
GO020:  PUSH    D       ;
        PUSH    H       ;
        LHLD    INSTSP  ;
GO030:  DCX     H       ;
        MVI     D,10H   ;
GO040:  DCR     D       ;
        JNZ     GO040   ;
        MOV     A,H     ;
        ANA     A       ;
        JNZ     GO030   ;
        CALL    STEP    ;
        CALL    DSREGS  ;
        POP     H       ;
        POP     D       ;
        IN      KSTAT  ;
        ANI     KBDRDY  ;
        RZ     	;REPLACE WITH RNZ FOR BOARDS WITH INVERTED I/O STATUS
        JMP     GO010   ;
STPADR: DB      'STOP AT-'      ;
;
;THIS ROUTINE READS INTEL FORMAT TAPES
;
READTP: CALL    BMPLNE  ;
        CALL    TAPEIN  ;
        MOV     A,C     ;
        RZ              ;
        MVI     B,0     ;
        LXI     D,16    ;
        SUI     10H     ;
        MOV     C,A     ;
        LXI     H,ERRMES        ;
        DAD     B       ;
        MOV     B,H     ;
        MOV     C,L     ;
        LHLD    CPOSIT  ;
        CALL    BMPLNE  ;
        CALL    SETLNE  ;
        CALL    BMPLNE  ;
        RET             ;
;
;
;
;
TAPEIN: MVI     C,0     ;
        MVI     A,0FFH  ;
        OUT     SWTCHS  ;
BBLK:   CALL    INPUT   ;
        CPI     3AH     ;
        JNZ     BBLK    ;
	MVI	B,0	;
        CALL    RDBYTE  ;
        MOV     D,A     ;
        CALL    RDBYTE  ;
        MOV     H,A     ;
        CALL    RDBYTE  ;
        MOV     L,A     ;
	CALL	RDBYTE	;
        MOV     E,D     ;
        INR     E       ;
LD10:   DCR     E       ;
        JZ      LD20    ;
        MOV     A,L     ;
        CMA             ;
        OUT     SWTCHS  ;
        CALL    RDBYTE  ;
        MOV     M,A     ;
	CMP	M	;
	INX	H	;
	JZ	LD10	;
	MVI	C,20H	;
	RET		;
LD20:   MOV     A,H     ;
        CMA             ;
        OUT     SWTCHS  ;
        CALL    RDBYTE  ;
        MOV     A,B     ;
        ORA     A       ;
        JZ      NBLK    ;
        MVI     C,10H   ;
        RET             ;
NBLK:   MOV     A,D     ;
        ORA     A       ;
        JNZ     BBLK    ;
        RET             ;
;
;
;
RDBYTE:	PUSH	D	;SAVE LENGTH
	CALL	INDIGT	;GET 1 HEX DIGIT FROM TAPE
	ADD	A	;MULTIPLY BY 16
	ADD	A	;
	ADD	A	;
	ADD	A	;
	MOV	D,A	;SAVE MSD
	CALL	INDIGT	;GET NEXT HEX DIGIT FROM TAPE
	ORA	D	;COMBINE HEX DIGITS TO FORM BYTE
	MOV	D,A	;SAVE BYTE WHILE DOING CHKSUM
	ADD	B	;ADD CHKSUM TO THE NEW BYTE
	MOV	B,A	;REPLACE OLD CHKSUM WITH NEW
	MOV	A,D	;GET NEW BYTE BACK
	POP	D	;RESTORE LENGTH
	RET
;
;
;
INDIGT:	CALL	INPUT	;READ A FRAME FROM TAPE
	CPI	'9'+1	;INSPECT DATA
	JM	IND010	;OK IF DATA < 10
	ADI	9	;ELSE ADJUST FOR ASCII BIAS
IND010:	ANI	0FH	;REDUCE MOD 16
	RET		;
;
;
INPUT:	IN	RSTAT	;GET READER STATUS FROM 3P+S
        ANI     RDRRDY  ;TURN OFF NON READER BITS
	JNZ	INPUT	;LOOP UNTIL DATA AVAILABLE
	IN	READER	;GET DATA
	ANI	7FH	;CLEAR PARITY BIT
        RET             ;
;
;TAPE READER ROUTINE ERROR MESSAGES
;
ERRMES: DB      'CHECK SUM ERROR '
	DB	'MEMORY FAILURE  '
;
;THIS ROUTINE ZEROES A BLOCK OF MEMORY
;
ZERMEM: CALL    GTLMTS  ;
ZER010: MVI     A,0     ;
        MOV     M,A     ;
        INX     H       ;
        MOV     A,D     ;
        SUB H           ;
        JNZ     ZER010  ;
        MOV     A,E     ;
        SUB     L       ;
        JNZ     ZER010  ;
        RET             ;
;
;
;
ISPEED: CALL    KEYBDI  ;
        CALL    ASCHEX  ;
        ADI     01H     ;
        MOV     H,A     ;
        MVI     L,0     ;
        MVI     A,10H   ;
        SUB     H       ;
        MOV     H,A     ;
        SHLD    INSTSP  ;
        CALL    BMPLNE  ;
        RET             ;
INSTSP: DW      0400H   ;
;
;
;
        END
