;##############################################################################
;
;    EMULATION FOREGROUND MONITOR FOR 64792 EMULATOR
;
; MKT:@(#) 64792-18021 A.00.05 V50/50HL EMULATION FOREGROUND MONITOR    05Nov92                       
;
;##############################################################################
;
;    The emulation foreground monitor is the vehicle by which the following
;    emulator functions are effected if the 64792 emulator is configured to
;    operate with a foreground monitor.
;
;        read/write target system memory
;        read/write target system io
;        display/modify registers
;        execute user program
;        break away from user program
;
;    The 64792 foreground monitor must start on a 4k byte boundary.
;    The desired 4k byte boundary should be specified in
;
;        MONSEGMENT	EQU	xxxxH
;
;    statement at the start of the monitor as its PS (program segment) of
;    the monitor location.  The address must be specified in the emulator
;    configuration below.
;
;        cf mon=fg..xx000
;
;    The following areas are inhibited from locating foreground monitor.
;
;             0H -    0FFFH
;        0FF000H -  0FFFFFH
;
;    In this manner, communication between the foreground monitor and the
;    emulator operating software can be established.
;
;
;    The few sections of the foreground monitor cannot be modified and their
;    location with respect to the start of the foreground monitor cannot be
;    altered. These include the following:
;
;	 MONITOR VARIABLES
;	 MONITOR VECTOR TABLE 
;	 KEY MONITOR ENTRY BACKGROUND
;	 KEY MONITOR ENTRY FOREGROUND
;
;    The "MONITOR VARIABLES" section contains three parts.  The first section
;    is a group  of variables  that act as  the communications path  between
;    the foreground monitor and the emulation controller.  The "COMM_BUF" is
;    which is used to transfer a block of data between the emulation controller
;    and the target system memory.  The last section "JAM_STACK" is a stack
;    used by the monitor when it is in a background state for a few bus
;    cycles upon transition to the foreground monitor. 
;
;    The "MONITOR VECTOR TABLE" is used exclusively by the emulator to tran-
;    sition into the foreground monitor from reset, from software breakpoints
;    or from emulation generated breaks like the break command or a write to
;    rom.  The monitor vector is not a replacement for the target system's
;    exception vector table.
;
;    The "KEY MONITOR ENTRY BACKGROUND" routines involve a brief stop in the
;    background monitor and therefore cannot be modified or moved with respect
;    to the start of the monitor.
;
;    The "KEY MONITOR ENTRY FOREGROUND" routine is executed after transition
;    from the background state to the foreground monitor.
;
;
;    To perform single stepping with the foreground monitor, the "Break Flag"
;    vector (Vector 1) in the target system must point to "UEE_BRK_FLAG" in
;    the foreground monitor.
;
;##############################################################################

		NAME	fm70216


;##############################################################################
;# MONITOR VARIABLES                                                          #
;##############################################################################

MONSEGMENT	EQU	0F000H
 
; Constant definition for register initializing
RG_PC		EQU 0
RG_PS		EQU 0FFFFH
RG_PSW		EQU 0F002H

; Constant definition for System i/o initializing and internal io accessing
RG_CLASS_BAS	EQU 00E0H
RG_CLASS_SIO	EQU 0100H
RG_CLASS_ICU	EQU 012AH
RG_CLASS_TCU	EQU 013EH
RG_CLASS_SCU	EQU 014CH
RG_CLASS_DMA1	EQU 0158H
RG_CLASS_DMA2	EQU 017AH

NUM_CLASS_SIO	EQU 21
NUM_CLASS_ICU	EQU 4
NUM_CLASS_TCU	EQU 6
NUM_CLASS_SCU	EQU 2
NUM_CLASS_DMA1	EQU 17
NUM_CLASS_DMA2	EQU 13

RG_DUMY		EQU 0FFFFH
RG_BSEL		EQU 0FFE0H
RG_BADR		EQU 0FFE1H
RG_BRC		EQU 0FFE9H
RG_WCY3		EQU 0FFEAH
RG_WIOB		EQU 0FFEBH
RG_WSMB		EQU 0FFECH
RG_EXWB		EQU 0FFEDH
RG_TCKS		EQU 0FFF0H
RG_SBCR		EQU 0FFF1H
RG_RFC		EQU 0FFF2H
RG_WMB		EQU 0FFF4H
RG_WCY1		EQU 0FFF5H
RG_WCY2		EQU 0FFF6H
RG_SCTL		EQU 0FFF7H
RG_SULA		EQU 0FFF8H
RG_TULA		EQU 0FFF9H
RG_IULA		EQU 0FFFAH
RG_DULA		EQU 0FFFBH
RG_OPHA		EQU 0FFFCH
RG_OPSEL	EQU 0FFFDH
RG_OPCN		EQU 0FFFEH

;##############################################################################
;# MONITOR VECTOR TABLE                                                       #
;##############################################################################

Fgmon           SEGMENT AT MONSEGMENT
	        ORG	00000H
MONITOR_VECTOR  DD 0
		DD 0
		DW OFFSET TRAP_ENT
		DW SEG TRAP_ENT
Fgmon           ENDS


Fgmon           SEGMENT AT MONSEGMENT
                ORG    00010H
; Monitor Control Variables
CMD_TYPE_RES	DB 80H		;monitor command type
CMDDONE           EQU 080H      ; - command done, stay in monitor
CMDEXIT           EQU 001H      ; - exit monitor
CMDWRMEM          EQU 003H      ; - write target memory
CMDRDMEM          EQU 004H      ; - read target memory
CMDWRTIO          EQU 005H      ; - write target io
CMDRDTIO          EQU 006H      ; - read target io
CMDWAITRST        EQU 007H      ; - wait for target reset
CMDRDIIO          EQU 009H      ; - read internal io register
CMDWRIIO          EQU 00AH      ; - write internal io register
CMDRDIIOCLS       EQU 00BH      ; - read internal io class read
CMDILL            EQU 0FFH      ; - command error

I_AM_HERE	DB 0		;monitor status
INMONLOOP	  EQU 011H	; - running in monitor loop
WAITFORRST        EQU 033H      ; - waiting for target system reset
ILLCMDLOOP   	  EQU 0AAH      ; - running in command error loop

RW_COUNT	DW 0		;0012
		DB 0            ;0014
RW_ACCESS	DB 0		;0015
SEG_LOW		DB 0		;0016
SEG_HIGH	DB 0		;0017
OFF_LOW		DB 0		;0018
OFF_HIGH	DB 0		;0019
REG_NUM		DW 0		;001A
FIRST_ENTRY	DB 1		;reset entry flag
		DB 0
BCTL_ADDR       DW 0            ;001E
ENTRY_TYPE	DB 0		;0020
Fgmon           ENDS


; Register Buffer
;   These buffers are filled on entering monitor.
;   Contents of register is accessed here by driver in backckground.
Fgmon           SEGMENT AT MONSEGMENT
   		ASSUME PS:Fgmon,DS0:Fgmon
                ORG    000E0H
REG_START: 
REG_PC		DW   RG_PC	;program counter
REG_PS		DW   RG_PS	;program segment
REG_PSW		DW   RG_PSW	;program status word
REG_AW		DW 0		;reg aw
REG_BW		DW 0		;reg bw
REG_CW		DW 0		;reg cw
REG_DW		DW 0		;reg dw
REG_SP		DW 0		;stack pointer
REG_BP		DW 0		;base pointer
REG_IX		DW 0		;index reg. x
REG_IY		DW 0		;index reg. y
REG_DS0		DW 0		;data segment 0
REG_DS1		DW 0		;data segment 1
REG_SS		DW 0		;stack segment
Fgmon           ENDS


; Internal I/O Register Buffer Array
;   These buffers are filled on entering monitor.
;   Following are array of pointer indicate location of each internal io
;   register read/write routine.
Fgmon           SEGMENT AT MONSEGMENT
                ORG    00100H
; System I/O register
REG_BSEL	DW BSEL_RW	;DMA bank select register
REG_BADR	DW BADR_RW	;DMA bank address register
REG_BRC		DW BRC_RW	;SCU baud rate counter
REG_WCY3	DW WCY3_RW	;WCU wait cycle set register3
REG_WIOB	DW WIOB_RW	;WCU wait I/O block set register
REG_WSMB	DW WSMB_RW	;WCU wait sub memory block set register
REG_EXWB	DW EXWB_RW	;WCU extend wait block set register
REG_TCKS	DW TCKS_RW	;TCU clock select register
REG_SBCR	DW SBCR_RW	;Standby control register
REG_RFC		DW RFC_RW	;Refresh control register
REG_WMB		DW WMB_RW	;WCU memory bank set register 
REG_WCY1	DW WCY1_RW	;WCU wait cycle set register1
REG_WCY2	DW WCY2_RW	;WCU wait cycle set register2
REG_SCTL	DW SCTL_RW	;System control register
REG_SULA	DW SULA_RW	;SCU low address register
REG_TULA	DW TULA_RW	;TCU low address register
REG_IULA	DW IULA_RW	;ICU low address register
REG_DULA	DW DULA_RW	;DMAU low address register
REG_OPHA	DW OPHA_RW	;Internal peripheral high address register
REG_OPSEL	DW OPSEL_RW	;On-chip peripheral select register
REG_OPCN	DW OPCN_RW	;On-chip peripheral connection register

; ICU registers
REG_IMKW	DW IMKW_RW	;Interrupt mask word
REG_IRQ		DW IRQ_RW	;Interrupt request word
REG_IIS		DW IIS_RW	;Interrupt status word
REG_IPOL	DW IPOL_RW	;Interrupt polling status
REG_IPFW	DW IPFW_RW	;Interrupt priority word
REG_IMDW	DW IMDW_RW	;Interrupt mode word
REG_IIW1	DW IIW1_RW	;Interrupt initialize word 1
REG_IIW2	DW IIW2_RW	;Interrupt initialize word 2
REG_IIW3	DW IIW3_RW	;Interrupt initialize word 3
REG_IIW4	DW IIW4_RW	;Interrupt initialize word 4

; TCU registers
REG_TCT0	DW TCT0_RW	;Timer count 0
REG_TST0	DW TST0_RW	;Timer status 0
REG_TCT1	DW TCT1_RW	;Timer count 11
REG_TST1	DW TST1_RW	;Timer status 1
REG_TCT2	DW TCT2_RW	;Timer count 2
REG_TST2	DW TST2_RW	;Timer status 2
REG_TMD		DW TMD_RW	;Timer mode set 

; SCU registers
REG_SRB		DW SRB_RW	;Serial receive buffer
REG_SST		DW SST_RW	;Serial status register
REG_STB		DW STB_RW	;Serial transfer buffer
REG_SCM		DW SCM_RW	;Serial command register
REG_SMD		DW SMD_RW	;Serial mode register
REG_SIMK	DW SIMK_RW	;Serial interrupt mask register

; DMAU registers
;   uPD71071 mode
REG_DICM	DW DICM_RW	;DMAU initialize register
REG_DCH		DW DCH_RW	;DMAU channel register
REG_DBC0	DW DBC0_RW	;DMAU base count register 0
REG_DBC1	DW DBC1_RW	;DMAU base count register 1
REG_DBC2	DW DBC2_RW	;DMAU base count register 2
REG_DBC3	DW DBC3_RW	;DMAU base count register 3
REG_DBA0	DW DBA0_RW	;DMAU base address register 0
REG_DBA1	DW DBA1_RW	;DMAU base address register 1
REG_DBA2	DW DBA2_RW	;DMAU base address register 2
REG_DBA3	DW DBA3_RW	;DMAU base address register 3
REG_DMD0	DW DMD0_RW	;DMAU mode control register 0
REG_DMD1	DW DMD1_RW	;DMAU mode control register 1
REG_DMD2	DW DMD2_RW	;DMAU mode control register 2
REG_DMD3	DW DMD3_RW	;DMAU mode control register 3
REG_DDC		DW DDC_RW	;DMAU device control register
REG_DST		DW DST_RW	;DMAU status register
REG_DMK		DW DMK_RW	;DMAU mask register

;   uPD71037 mode
REG_CMD		DW CMD_RW	;DMAU command/status register
REG_BANK0	DW BANK0_RW	;DMAU bank register 0
REG_BANK1	DW BANK1_RW	;DMAU bank register 1
REG_BANK2	DW BANK2_RW	;DMAU bank register 2
REG_BANK3	DW BANK3_RW	;DMAU bank register 3
REG_ADR0	DW ADR0_RW	;DMAU address register 0
REG_ADR1	DW ADR1_RW	;DMAU address register 1
REG_ADR2	DW ADR2_RW	;DMAU address register 2
REG_ADR3	DW ADR3_RW	;DMAU address register 3
REG_CNT0	DW CNT0_RW	;DMAU count register 0
REG_CNT1	DW CNT1_RW	;DMAU count register 1
REG_CNT2	DW CNT2_RW	;DMAU count register 2
REG_CNT3	DW CNT3_RW	;DMAU count register 3
REG_SFRQ	DW SFRQ_RW	;DMAU software request register 
REG_SMSK	DW SMSK_RW	;DMAU single mask register 
REG_MODE	DW MODE_RW	;DMAU mode register 
REG_CLBP	DW CLBP_RW	;DMAU clear byte pointer register
REG_INIT	DW INIT_RW	;DMAU initialize register
REG_CMSK	DW CMSK_RW	;DMAU clear mask register
REG_AMSK	DW AMSK_RW	;DMAU all mask register
CP_IOAG		DB 0		;indicate address interval
Fgmon           ENDS


Fgmon           SEGMENT AT MONSEGMENT
	        ORG	00400H
TRAP_ENT:	MOV    PS:TMP_SS,SS
        	MOV    PS:TMP_SP,SP
		MOV    SS,PS:DATA_SEGMENT
		MOV    SP,OFFSET JAM_STACK_CP
                PUSH   PS:JAM_STACK+6
                PUSH   PS:JAM_STACK+4
                PUSH   PS:JAM_STACK+2
                PUSH   PS:JAM_STACK
		MOV    SP,OFFSET JAM_STACK+8
		PUSH   PSW	
		PUSH   SEG FG_BRK_ENT		
		PUSH   OFFSET FG_BRK_ENT		
                BR     NEAR PTR BCTL_EXITBKG0
		DB     10 DUP (90H)

                EVEN
BCTL_EXITBKG0:  MOV    AW,AW
                MOV    AW,AW
                MOV    AW,AW
BCTL_EXITBKG:   RETI
		DB     10 DUP (90H)


;##############################################################################
;# KEY MONITOR ENTRY FOREGROUND                                               #
;##############################################################################

MONITOR_START:
FG_BRK_ENT:	PUSH   DS0		;push DS0 to F06H  sp=F06
		MOV    DS0,PS:DATA_SEGMENT
		MOV    ENTRY_TYPE,0
		TEST1  FIRST_ENTRY,0
		BNZ    FG_RST_BRK_ENT 		
		BR     NEAR PTR MONITOR_ENT

FG_RST_BRK_ENT:	MOV    FIRST_ENTRY,0
		POP    REG_DS0
                MOV    REG_PC, RG_PC
                MOV    REG_PS, RG_PS
                MOV    REG_PSW, RG_PSW
		BR     NEAR PTR MONITOR_LP_ENT


;##############################################################################
;# MONITOR ENTRY                                                              #
;##############################################################################

; MONITOR ENTRY
;   This routine stores user's register values to the "MONITOR VARIABLES".

MONITOR_ENT:	MOV    REG_AW,AW
		MOV    REG_BW,BW
		MOV    REG_CW,CW
		MOV    REG_DW,DW
		MOV    REG_IX,IX
		MOV    REG_IY,IY
		MOV    REG_BP,BP
		POP    REG_DS0
		MOV    REG_DS1,DS1
		MOV    AW,TMP_SS
		MOV    REG_SS,AW
		MOV    AW,TMP_SP
		MOV    BW,AW
		ADD    AW,06H
		MOV    REG_SP,AW
		MOV    IX,OFFSET REG_START
		AND    BW,7H
		OR     BW,OFFSET JAM_STACK_CP-8
		TEST1  BL,0
		BZ     STORE_REG_EVEN

STORE_REG_ODD:  MOV    AH,[BW]
                MOV    [IX],AH                       ;copy PC(L)
                INC    BL
                AND    BL,0F6H
                MOV    AW,[BW]
                MOV    [IX+1],AW                     ;copy PC(H),PS(L)
                ADD    BL,2H
                AND    BL,0F6H
                MOV    AW,[BW]
                MOV    [IX+3],AW                     ;copy PS(H),PSW(L)
                ADD    BL,2H
                AND    BL,0F6H
                MOV    AH,[BW]
                MOV    [IX+5],AH                     ;copy PSW(H)
                BR     NEAR PTR CHK_RE_ENT

STORE_REG_EVEN: MOV    AW,[BW]
                MOV    [IX],AW                       ;copy PC
                ADD    BL,2H
                AND    BL,0F6H
                MOV    AW,[BW]
                MOV    [IX+2],AW                     ;copy PS
                ADD    BL,2H
                AND    BL,0F6H
                MOV    AW,[BW]
                MOV    [IX+4],AW                     ;copy PSW

CHK_RE_ENT:     CMP    REG_PS,SEG EXCEPT_START 
		BNE    SHORT MONITOR_LP_ENT
		CMP    REG_PC,OFFSET EXCEPT_START 
		BNH    SHORT MONITOR_LP_ENT
		CMP    REG_PC,OFFSET EXCEPT_END 
		BNH    SHORT EXIT_MONITOR0


;##############################################################################
;# MONITOR CONTROL LOOP                                                       # 
;##############################################################################

; MONITOR CONTROL LOOP
;   The foregrund monitor waits in this loop until the emulator controller
;   requests an action by setting CMD_TYPE_RES.

MONITOR_LP_ENT: MOV    CP_IOAG,0
		MOV    CMD_TYPE_RES, CMDDONE	;command done, stay in monitor
                CLR1   DIR                      ;set-up for auto_inc

MONITOR_LP:	MOV    I_AM_HERE, INMONLOOP    	;running in monitor loop
                MOV    AL,CMD_TYPE_RES      	;check whether cmd is requested
                AND    AL, CMDDONE             	;mask msb
                BNZ    MONITOR_LP    		;stay in mpnitor


; COMMAND REQUEST
;   When a command has been requested, this routine determines the type of
;   command requested and initiates the appropriate action.

CMD_REQUEST:	MOV    AL,CMD_TYPE_RES		;get command type
	 	CMP    AL, CMDRDMEM
		BE     TRGT_MEM_RD0		;read target memory
		CMP    AL, CMDWRMEM
		BE     TRGT_MEM_WR0		;write target memory
		CMP    AL, CMDRDTIO
		BE     TRGT_IO_RD0		;read target io
		CMP    AL, CMDWRTIO
		BE     TRGT_IO_WR0		;write tagert io
		CMP    AL, CMDEXIT
		BE     EXIT_MONITOR		;exit monitor
		CMP    AL, CMDWAITRST
		BE     PRCS_TRGT_RST		;wait for target reset
		CMP    AL, CMDRDIIO
		BE     IIO_RD0			;read internal io register
		CMP    AL, CMDWRIIO
		BE     IIO_WR0			;write internal io register
		CMP    AL, CMDRDIIOCLS
		BE     IIO_CLASS_RD0		;read internal io class read

; COMMAND ERROR LOOP

CMD_ILL:	MOV    CMD_TYPE_RES, CMDILL	;running in command error loop
       		MOV    I_AM_HERE, ILLCMDLOOP
		BR     NEAR PTR CMD_ILL

; indirect branch
EXIT_MONITOR0:	BR     NEAR PTR EXIT_MONITOR

TRGT_MEM_RD0:	BR     NEAR PTR TRGT_MEM_RD
TRGT_MEM_WR0:	BR     NEAR PTR TRGT_MEM_WR
TRGT_IO_RD0:	BR     NEAR PTR TRGT_IO_RD
TRGT_IO_WR0:	BR     NEAR PTR TRGT_IO_WR
IIO_RD0:	BR     NEAR PTR IIO_ACCESS
IIO_WR0:	BR     NEAR PTR IIO_ACCESS
IIO_CLASS_RD0:	BR     NEAR PTR IIO_CLASS_READ

; WAIT FOR TARGET SYSTEM RESET
;   When run from target reset command is given, monitor loops here until
;   target reset signal actually comes inside the emulator.

PRCS_TRGT_RST:	MOV   CMD_TYPE_RES, CMDDONE	;command done
WAIT_RST_LOOP:	MOV   I_AM_HERE, WAITFORRST	;waiting for target reset
		BR    NEAR PTR WAIT_RST_LOOP


; MONITOR EXIT ROUTINE
;   This routine performs the transition from foreground monitor operation
;   to execution of the users program.

EXIT_MONITOR:	DI
		MOV    SS,REG_SS
		MOV    SP,REG_SP
		PUSH   REG_PSW
		PUSH   REG_PS
		PUSH   REG_PC
      		MOV    AW,REG_AW
		MOV    DW,REG_DW
          	MOV    BW,REG_BW
		MOV    CW,REG_CW
		MOV    IX,REG_IX
		MOV    IY,REG_IY
		MOV    BP,REG_BP
		MOV    DS1,REG_DS1
        	MOV    CMD_TYPE_RES, CMDDONE		;command done
		MOV    DS0,REG_DS0
                RETI				;return to user program
		DB     10 DUP (90H)


; TARGET MEMORY WRITE ROUTINE
;   This routine writes data to target system memory.
;   The data was loaded into the 'COMM_BUF' by the emulation
;   controller.  'SEG_xx','OFF_xx' variable contains the starting
;   address seg/offset and 'RW_COUNT' variable contains the number of
;   bytes of write data.

TRGT_MEM_WR:	MOV    AL,OFF_LOW
		MOV    AH,OFF_HIGH
		MOV    IY,AW
		MOV    BW,AW
           	MOV    AL,SEG_LOW
		MOV    AH,SEG_HIGH
		MOV    DS1,AW
		MOV    IX,OFFSET COMM_BUF
		MOV    CW,RW_COUNT
		CMP    PS:RW_ACCESS,'w'
		BNE    SHORT MEM_BYTE_WR
		AND    BW,0001H
		BNZ    MEM_BYTE_WR
MEM_WORD_WR:	SHR    CW,1
		REP    MOVBKW
		BR     NEAR PTR MONITOR_LP_ENT
MEM_BYTE_WR:	REP    MOVBKB
		BR     NEAR PTR MONITOR_LP_ENT


; TARGET MEMORY READ ROUTINE
;   This routine reads data from target system memory.
;   'SEG_xx','OFF_xx' variable contains the starting address seg/offset
;   and 'RW_COUNT' variable contains the number of
;   bytes of read data.  The data is stored in the 'COMM_BUF'.

TRGT_MEM_RD:
		MOV    AW,DS0	
		MOV    DS1,AW	
		MOV    AL,OFF_LOW
		MOV    AH,OFF_HIGH
		MOV    IX,AW
		MOV    BW,AW
		MOV    IY,OFFSET COMM_BUF
		MOV    CW,RW_COUNT
           	MOV    AL,SEG_LOW
		MOV    AH,SEG_HIGH
		PUSH   DS0
		MOV    DS0,AW	
		CMP    PS:RW_ACCESS,'w'
		BNE    SHORT MEM_BYTE_RD
		AND    BW,0001H
		BNZ    MEM_BYTE_RD
MEM_WORD_RD:	SHR    CW,1
		REP    MOVBKW
		POP    DS0
		BR     NEAR PTR MONITOR_LP_ENT
MEM_BYTE_RD:	REP    MOVBKB
		POP    DS0
		BR     NEAR PTR MONITOR_LP_ENT


; TARGET IO WRITE ROUTINE
;   This routine writes io from target system.
;   'SEG_xx','OFF_xx' variable contains the starting address seg/offset
;   and 'RW_COUNT' variable contains the number of
;   bytes of read data.  The data is stored in the 'COMM_BUF'.

TRGT_IO_WR:	MOV    DL,OFF_LOW
		MOV    DH,OFF_HIGH
		MOV    AW,DW
		MOV    IX,OFFSET COMM_BUF
		MOV    CW,RW_COUNT
		CMP    RW_ACCESS,'w'
		BNE    SHORT IO_BYTE_WR
		AND    AW,0001H
		BNZ    IO_BYTE_WR
IO_WORD_WR:	MOV    AW,WORD PTR[IX]
                OUT    DW,AW
                INC    IX 
                INC    IX
                INC    DW
                INC    DW
		DEC    CW
                DBNZ   IO_WORD_WR
		BR     NEAR PTR MONITOR_LP_ENT
IO_BYTE_WR:	MOV    AL,BYTE PTR[IX]
                OUT    DW,AL
                INC    IX 
                INC    DW 
                DBNZ   IO_BYTE_WR
		BR     NEAR PTR MONITOR_LP_ENT


; TARGET IO READ ROUTINE
;   This routine reads io from target system.
;   'SEG_xx','OFF_xx' variable contains the starting address seg/offset
;   and 'RW_COUNT' variable contains the number of
;   bytes of read data.  The data is stored in the 'COMM_BUF'.

TRGT_IO_RD:	MOV    DL,OFF_LOW
		MOV    DH,OFF_HIGH
		MOV    AW,DW
		MOV    IY,OFFSET COMM_BUF
		MOV    CW,RW_COUNT
		CMP    RW_ACCESS,'w'
		BNE    SHORT IO_BYTE_RD
		AND    AW,0001H
		BNZ    IO_BYTE_RD
IO_WORD_RD:	IN     AW,DW
                MOV    WORD PTR[IY],AW
                INC    DW
                INC    DW 
                INC    IY 
                INC    IY
		DEC    CW
                DBNZ   IO_WORD_RD
		BR     NEAR PTR MONITOR_LP_ENT
IO_BYTE_RD:      IN     AL,DW
                MOV    BYTE PTR[IY],AL
                INC    DW 
                INC    IY
                DBNZ   IO_BYTE_RD 
		BR     NEAR PTR MONITOR_LP_ENT


; INTERNAL IO READ/WRITE ROUTINE
;   Determine which internal io register this routine read according to 
;   value od REG_NUM given by controller and pointer array.
;   Then call subroutine actual internal io read/write.

IIO_ACCESS: 	MOV    IY,OFFSET COMM_BUF
		MOV    IX,REG_NUM
		MOV    AW,[IX]
		CALL   AW
		BR     NEAR PTR MONITOR_LP_ENT


; INTERNAL IO CLASS READ ROUTINE
;   Determine which internal io register class this routine read according to 
;   value od REG_NUM given by controller and pointer array.
;   Then call subroutine actual internal io read.

IIO_CLASS_READ:	MOV    CMD_TYPE_RES, CMDRDIIO
		MOV    IY,OFFSET COMM_BUF
		MOV    IX,REG_NUM
CLASS_SIO:	CMP    REG_NUM, RG_CLASS_SIO
		BNE    SHORT CLASS_ICU
		MOV    CW, NUM_CLASS_SIO
		BR     NEAR PTR READ_EX
CLASS_ICU:	CMP    REG_NUM, RG_CLASS_ICU
		BNE    SHORT CLASS_TCU
		MOV    CW, NUM_CLASS_ICU
		BR     NEAR PTR READ_EX
CLASS_TCU:	CMP    REG_NUM, RG_CLASS_TCU
		BNE    SHORT CLASS_SCU
		MOV    CW, NUM_CLASS_TCU
		BR     NEAR PTR READ_EX
CLASS_SCU:	CMP    REG_NUM, RG_CLASS_SCU
		BNE    SHORT CLASS_DMA1 
		MOV    CW, NUM_CLASS_SCU
		BR     NEAR PTR READ_EX
CLASS_DMA1:	CMP    REG_NUM, RG_CLASS_DMA1 
		BNE    SHORT CLASS_DMA2	
		MOV    CW, NUM_CLASS_DMA1
		BR     NEAR PTR READ_EX
CLASS_DMA2:     MOV    CW, NUM_CLASS_DMA2
READ_EX:	MOV    AW,[IX]
		PUSH   CW
		PUSH   IX
		CALL   AW
		POP    IX
		POP    CW
		ADD    IX,2
		INC    IY
		DBNZ   READ_EX
		BR     NEAR PTR MONITOR_LP_ENT


; Subroutine system io read/write operation.
; Communication buffer address is set in IY register.

BSEL_RW:	MOV    DW, RG_BSEL
		BR     NEAR PTR SIO_RW
BADR_RW:	MOV    DW, RG_BADR
		BR     NEAR PTR SIO_RW
BRC_RW:		MOV    DW, RG_BRC
		BR     NEAR PTR SIO_RW
WCY3_RW:	MOV    DW, RG_WCY3
		BR     NEAR PTR SIO_RW
WIOB_RW:	MOV    DW, RG_WIOB
		BR     NEAR PTR SIO_RW
WSMB_RW:	MOV    DW, RG_WSMB
		BR     NEAR PTR SIO_RW
EXWB_RW:	MOV    DW, RG_EXWB
		BR     NEAR PTR SIO_RW
TCKS_RW:	MOV    DW, RG_TCKS
		BR     NEAR PTR SIO_RW
SBCR_RW:	MOV    DW, RG_SBCR
		BR     NEAR PTR SIO_RW
RFC_RW:		MOV    DW, RG_RFC
		BR     NEAR PTR SIO_RW
WMB_RW:		MOV    DW, RG_WMB
		BR     NEAR PTR SIO_RW
WCY1_RW:	MOV    DW, RG_WCY1
		BR     NEAR PTR SIO_RW
WCY2_RW:	MOV    DW, RG_WCY2
		BR     NEAR PTR SIO_RW
SCTL_RW:	MOV    DW, RG_SCTL
		BR     NEAR PTR SIO_RW
SULA_RW:	MOV    DW, RG_SULA
		BR     NEAR PTR SIO_RW
TULA_RW:	MOV    DW, RG_TULA
		BR     NEAR PTR SIO_RW
IULA_RW:	MOV    DW, RG_IULA
		BR     NEAR PTR SIO_RW
DULA_RW:	MOV    DW, RG_DULA
		BR     NEAR PTR SIO_RW
OPHA_RW:	MOV    DW, RG_OPHA
		BR     NEAR PTR SIO_RW
OPSEL_RW:	MOV    DW, RG_OPSEL
		BR     NEAR PTR SIO_RW
OPCN_RW:	MOV    DW, RG_OPCN
		BR     NEAR PTR SIO_RW
SIO_RW:		CMP    CMD_TYPE_RES, CMDRDIIO
		BE     SIO_READ
SIO_WRITE:	MOV    AL,BYTE PTR [IY]
		OUT    DW,AL
		BR     NEAR PTR SIO_RW_END
SIO_READ:	PUSH   DW			;clear unused bit of register
		MOV    DW, RG_DUMY
		MOV    AL,0
		OUT    DW,AL
		POP    DW
		IN     AL,DW
		MOV    BYTE PTR [IY],AL
SIO_RW_END:	RET


; Subroutine peripheral(ICU) register read/write operation.
; Communication buffer address id set in IY register.

IRQ_RW:		MOV    CL,0AH
		BR     NEAR PTR RQ_IS_POL_RD
IIS_RW:		MOV    CL,0BH
		BR     NEAR PTR RQ_IS_POL_RD
IPOL_RW:	MOV    CL,0CH
		BR     NEAR PTR RQ_IS_POL_RD
RQ_IS_POL_RD:	MOV    AW,0
		CALL   COMN_WR
		CALL   COMN_RD
		MOV    BYTE PTR [IY],CL
		RET
IMKW_RW:	MOV    AW,1
		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		RET
IIW2_RW:
IIW3_RW:
IIW4_RW:	MOV    AW,1
		BR     NEAR PTR IW_PFW_MDW_WR
IPFW_RW:
IMDW_RW:
IIW1_RW:	MOV    AW,0
		BR     NEAR PTR IW_PFW_MDW_WR
IW_PFW_MDW_WR:	MOV    CL,BYTE PTR [IY]
		CALL   COMN_WR
		RET


; Subroutine peripheral(TCU) register read/write operation.
; Communication buffer address is set in IY register.

TCT0_RW:	MOV    CL,0C2H	;Multiple Latch counter 0 status/count
		MOV    AW,0		;Address offset of counter 0
		BR     NEAR PTR TCT_RW

TCT1_RW:	MOV    CL,0C4H	;Multiple Latch counter 1 status/count
		MOV    AW,1		;Address offset of counter 1
		BR     NEAR PTR TCT_RW

TCT2_RW:	MOV    CL,0C8H	;Multiple Latch counter 2 status/count
		MOV    AW,2		;Address offset of counter 2

TCT_RW:		CMP    CMD_TYPE_RES, CMDRDIIO
		BE     TCT_READ

TCT_WRITE:	OR     CL,20H		;Set multiple latch command status only
TCT_READ:	CALL   TMD_WR	 	;Write multiple latch command
		CALL   COMN_RD		;Status read
		AND    CL,30H		;Read/write mode check
		CMP    CL,30H
		BE     READ_2B
		CMP    CL,10H
		BE     READ_LB

READ_HB:	MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		MOV    BYTE PTR [IY+1],0
		BR     NEAR PTR TCT_READ_END

READ_LB:	MOV    CL,BYTE PTR [IY+1]
		CALL   COMN_RW
		MOV    BYTE PTR [IY+1],CL
		MOV    BYTE PTR [IY],0
		BR     NEAR PTR TCT_READ_END

READ_2B:	MOV    CL,BYTE PTR [IY+1]
		CALL   COMN_RW
		MOV    BYTE PTR [IY+1],CL
		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
TCT_READ_END:	INC    IY
		RET

TST0_RW:	MOV    AW,0		;Address offset of counter 0
		MOV    CL,0E2H	;Multiple Latch counter 0 status
		BR     NEAR PTR TST_READ

TST1_RW:	MOV    AW,1		;Address offset of counter 1
		MOV    CL,0E4H	;Multiple Latch counter 0 status
		BR     NEAR PTR TST_READ

TST2_RW:	MOV    AW,2		;Address offset of counter 2
		MOV    CL,0E8H	;Multiple Latch counter 0 status
		BR     NEAR PTR TST_READ

TST_READ:	CALL   TMD_WR		;Write multiple latch command
		CALL   COMN_RD
		MOV    BYTE PTR [IY],CL
		RET

TMD_RW:		MOV    CL,BYTE PTR [IY]
TMD_WR:		PUSH   AW 
		MOV    AW,3
		CALL   COMN_WR
		POP    AW
		RET


; Subroutine peripheral(SCU) register read/write operation.
; Communication buffer address is set in IY register.

STB_RW:
SRB_RW:		MOV    AW,0		;Set offset into AW
		BR     NEAR PTR ALL_SCU_RW

SCM_RW:
SST_RW:		MOV    AW,1		;Set offset into AW
		BR     NEAR PTR ALL_SCU_RW

SMD_RW:		MOV    AW,2		;Set offset into AW
		BR     NEAR PTR ALL_SCU_RW

SIMK_RW:	MOV    AW,3		;Set offset into AW
		BR     NEAR PTR ALL_SCU_RW

ALL_SCU_RW:	MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		RET


; Subroutine peripheral(DMA) register read/write operation.
; COmmunication buffer address is set in IY register.
;
; 71071 mode register read/write

DICM_RW:	MOV    AW,0		;Set address offset into AW
		BR     NEAR PTR ICM_CH_RW

DCH_RW:		MOV    AW,1		;Set address offset into AW
		BR     NEAR PTR ICM_CH_RW

DST_RW:		MOV    AW,11		;Set address offset into AW
		BR     NEAR PTR ICM_CH_RW

DMK_RW:		MOV    AW,15		;Set address offset into AW
		BR     NEAR PTR ICM_CH_RW

ICM_CH_RW:	MOV    IX,AW
		MOV    CP_IOAG,1	;set IOAG 1
		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		RET

DBC0_RW:	MOV    CW,0		;Set channel number
		BR     NEAR PTR DBC_COMN

DBC1_RW:	MOV    CW,1		;Set channel number
		BR     NEAR PTR DBC_COMN

DBC2_RW:	MOV    CW,2		;Set channel number
		BR     NEAR PTR DBC_COMN

DBC3_RW:	MOV    CW,3		;Set channel number
		BR     NEAR PTR DBC_COMN

DBC_COMN:	MOV    BW,2		;Set number of byte
		MOV    AW,02H		;Set address offset
		BR     NEAR PTR BC_BA_MD_RW

DBA0_RW:	MOV    CW,0		;Set channel number
		BR     NEAR PTR DBA_COMN

DBA1_RW:	MOV    CW,1		;Set channel number
		BR     NEAR PTR DBA_COMN

DBA2_RW:	MOV    CW,2		;Set channel number
		BR     NEAR PTR DBA_COMN

DBA3_RW:	MOV    CW,3		;Set channel number
		BR     NEAR PTR DBA_COMN

DBA_COMN:	MOV    BW,3		;Set number of byte
		MOV    AW,04H		;Set address offset 
		BR     NEAR PTR BC_BA_MD_RW
		 
DMD0_RW:	MOV    CW,0		;Set channel number
		BR     NEAR PTR DMD_COMN

DMD1_RW:	MOV    CW,1		;Set channel number
		BR     NEAR PTR DMD_COMN

DMD2_RW:	MOV    CW,2		;Set channel number
		BR     NEAR PTR DMD_COMN

DMD3_RW:	MOV    CW,3		;Set channel number
		BR     NEAR PTR DMD_COMN

DMD_COMN:	MOV    BW,1		;Set number of byte
		MOV    AW,0AH		;Set address offset 
		BR     NEAR PTR BC_BA_MD_RW

BC_BA_MD_RW:	MOV    IX,AW
		MOV    CP_IOAG,1		;set IOAG 1
		PUSH   IX
		PUSH   AW
		PUSH   BW
		PUSH   CW
		MOV    AW,1			;Set DCH address offset
		CALL   COMN_RD			;Read DCH
		MOV    BL,CL			;Convert read format to
		AND    BL,10H			; write format
		SHR    BL,2
		MOV    AL,CL
		AND    AW,000FH
		MOV    CL,2
		DIVU   CL			;AW/2->AL,AW%2->AH
		CMP    AL,4
		BNE    SHORT MAKE_WDAT
		MOV    AL,3 
MAKE_WDAT:	OR     AL,BL			;Set DCH write data in AL
		MOV    IX,AW			;Set DCH write data in IX
		POP    CW 			;Pop channel No.
		OR     CL,BL			;Set BASE
		MOV    AW,1
		CALL   COMN_WR			;Write DCH

		POP    BW			;Number of bytes
		POP    AW			;Address offset
		CMP    BW,3
		BNE    SHORT NOT_DBA
		MOV    BYTE PTR [IY],0
		INC    IY
NOT_DBA:	ADD    IY,BW
		DEC    IY
		MOV    DW,IY
ACT_RW:		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		DEC    IY
		INC    AW
		DEC    BW
		BNZ    ACT_RW

		MOV    CW,IX
		MOV    AW,1
		CALL   COMN_WR			;Write default data to DCH

		MOV    IY,DW
		POP    IX
		RET

DDC_RW:		
		MOV    CP_IOAG,1		;Set IOAG 1
		MOV    AW,9			;Set address offset into AW
		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		INC    IY
		MOV    AW,8
		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		RET

; 71037 mode register read/write
BANK0_RW:	MOV    AW,0
		BR     NEAR PTR BANK_RW
BANK1_RW:	MOV    AW,1
		BR     NEAR PTR BANK_RW
BANK2_RW:	MOV    AW,2
		BR     NEAR PTR BANK_RW
BANK3_RW:	MOV    AW,3
		BR     NEAR PTR BANK_RW

BANK_RW:	CALL   SET_BKRA
		CMP    CMD_TYPE_RES, CMDRDIIO
		BE     BANK_READ
BANK_WRITE:	MOV    AL,BYTE PTR [IY]
		OUT    DW,AL
		RET
BANK_READ:	IN     AL,DW
		MOV    BYTE PTR [IY],AL
		RET

ADR0_RW:	MOV    AW,0			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
ADR1_RW:	MOV    AW,2			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
ADR2_RW:	MOV    AW,4			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
ADR3_RW:	MOV    AW,6			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
CNT0_RW:	MOV    AW,1			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
CNT1_RW:	MOV    AW,3			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
CNT2_RW:	MOV    AW,5			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW
CNT3_RW:	MOV    AW,7			;Set address offset into AW
		BR     NEAR PTR ADR_CNT_RW

ADR_CNT_RW:	PUSH   AW
		MOV    AW,12
		CALL   COMN_WR			;Clear byte pointer F/F
		POP    AW
		MOV    CL,BYTE PTR [IY+1]
		CALL   COMN_RW			;Lower byte
		MOV    BYTE PTR [IY+1],CL
		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW			;Upper byte
		MOV    BYTE PTR [IY],CL
		INC    IY
		RET

CMD_RW:		MOV    AW,8			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
SFRQ_RW:	MOV    AW,9			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
SMSK_RW:	MOV    AW,10			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
MODE_RW:	MOV    AW,11			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
CLBP_RW:	MOV    AW,12			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
INIT_RW:	MOV    AW,13			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
CMSK_RW:	MOV    AW,14			;Set Address offset into AW
		BR     NEAR PTR ETC_RW
AMSK_RW:	MOV    AW,15			;Set Address offset into AW
		BR     NEAR PTR ETC_RW

ETC_RW:		MOV    CL,BYTE PTR [IY]
		CALL   COMN_RW
		MOV    BYTE PTR [IY],CL
		RET


; INTERNAL IO REGISTER READ/WRITE COMMON ROUTINE
;  AW -> Offset from base address
;  CL -> Data buffer

COMN_RD:	PUSH   BW
		MOV    BL,CMD_TYPE_RES
		MOV    CMD_TYPE_RES, CMDRDIIO
		BR     NEAR PTR COMN_RW_CALL
COMN_WR:	PUSH   BW
		MOV    BL,CMD_TYPE_RES
		MOV    CMD_TYPE_RES, CMDWRIIO
COMN_RW_CALL:	CALL   COMN_RW
		MOV    CMD_TYPE_RES,BL
		POP    BW
		RET
COMN_RW:	PUSH   AW
		PUSH   DW
		PUSH   CW
		CALL   SET_BADDR
		MULU   CL
		ADD    DW,AW
		POP    CW
		CMP    CMD_TYPE_RES, CMDRDIIO
		BE     COMN_READ
COMN_WRITE:	MOV    AL,CL
		OUT    DW,AL
		POP    DW
		POP    AW
		RET
COMN_READ:	IN     AL,DW
		MOV    CL,AL
		POP    DW
		POP    AW
		RET

		
; Set base address sub routine.
; Set peripheral register base address into DW
; and Set address interval into CW according to IOAG.

SET_BADDR:					;OPHA read
						;Use CW,DW
						;CW<-Addr. interval
						;DW<-Base addr.
		PUSH   AW
		PUSH   BW
		PUSH   IY
		PUSH   IX
		MOV    DW, RG_OPHA
		IN     AL,DW
		MOV    BH,AL
		MOV    AW,REG_NUM

SET_IULA:	CMP    AW, RG_CLASS_TCU
		BGE    SET_TULA
		MOV    DW, RG_IULA
		BR     NEAR PTR SET_END

SET_TULA:	CMP    AW, RG_CLASS_SCU
		BGE    SET_SULA
		MOV    DW, RG_TULA
		BR     NEAR PTR SET_END

SET_SULA:	CMP    AW, RG_CLASS_DMA1
		BGE    SET_DULA
		MOV    DW, RG_SULA
		BR     NEAR PTR SET_END

SET_DULA:	MOV    DW, RG_DULA
		BR     NEAR PTR SET_END

SET_END:	IN     AL,DW
		MOV    BL,AL			;set base address in BW
		MOV    CW,0
		MOV    AL, CP_IOAG
		XOR    AL,01			;bit 0 inverse
		ADD    AL,01
		MOV    CL,AL			;set Address interval in CW
		MOV    DW,BW			;set Base address in DW
		POP    IX
		POP    IY
		POP    BW
		POP    AW
		RET


;  Set DMA bank register address sub routine.
;  Get bank No. from AW.
;  Set bank register address into DW.

SET_BKRA:					;Set bank register address
						;AW<- get b-register No.
						;DW<- put io address
		PUSH   BW
		PUSH   CW
		PUSH   IX
		PUSH   IY
		PUSH   AW
		MOV    DW, RG_OPHA
		IN     AL,DW
		MOV    BH,AL
		MOV    DW, RG_BADR
		IN     AL,DW
		MOV    BL,AL
		MOV    DW, RG_BSEL
		IN     AL,DW
		MOV    CL,AL
		POP    AW
BANK0:		CMP    AW,0
		BNE    SHORT BANK1
		AND    CL,03H
		BR     NEAR PTR IOAG_CHK
BANK1:		CMP    AW,1		
		BNE    SHORT BANK2
		AND    CL,0CH
		SHR    CL,2
		BR     NEAR PTR IOAG_CHK
BANK2:		CMP    AW,2	
		BNE    SHORT BANK3
		AND    CL,30H
		SHR    CL,4
		BR     NEAR PTR IOAG_CHK
BANK3:		AND    CL,0C0H
		SHR    CL,6
IOAG_CHK:	MOV    CH, CP_IOAG
		BZ     IOAG_0
IOAG_1:		AND    BW,0FFFCH
		OR     BL,CL
		BR     NEAR PTR COPY2DW
IOAG_0:		AND    BW,0FFF9H
		SHL    CL,1
		OR     BL,CL
COPY2DW:	MOV    DW,BW
		POP    IY
		POP    IX
		POP    CW
		POP    BW
		RET

EXCEPT_START:

; RESET ENTRY
;   This is the entry routine that a reset: initial PC in the target exception
;   vector table should point to if the user wants the emulator to vector to
;   the foreground monitor from target system resets.  The status register is
;   set to 0F002H.  The PC is set to JUMP_ENT.

FG_RST_ENT:	MOV    SS,PS:DATA_SEGMENT
                MOV    SP,OFFSET MONITOR_STACK
          	MOV    DS0,PS:DATA_SEGMENT
                MOV    ENTRY_TYPE,0
                MOV    REG_PC,OFFSET JUMP_ENT
                MOV    REG_PS,SEG JUMP_ENT
                MOV    REG_PSW, RG_PSW
                BR     NEAR PTR MONITOR_LP_ENT

UEE_DIV_ERR:    MOV    PS:ENTRY_TYPE,01H
                BR     NEAR PTR EXCEPT_ENT

UEE_BRK_FLAG:   MOV    PS:ENTRY_TYPE,02H
                BR     NEAR PTR EXCEPT_ENT

UEE_NMI:        MOV    PS:ENTRY_TYPE,03H
                BR     NEAR PTR EXCEPT_ENT

UEE_BRK_3:      MOV    PS:ENTRY_TYPE,04H
                BR     NEAR PTR EXCEPT_ENT

UEE_BRKV:       MOV    PS:ENTRY_TYPE,05H
                BR     NEAR PTR EXCEPT_ENT

UEE_CHKIND:     MOV    PS:ENTRY_TYPE,06H
                BR     NEAR PTR EXCEPT_ENT

UEE_BRKIMMD8:	MOV    PS:ENTRY_TYPE,07H
                BR     NEAR PTR EXCEPT_ENT

UEE_BRKEM:	MOV    PS:ENTRY_TYPE,08H
                BR     NEAR PTR EXCEPT_ENT

UEE_INT:	MOV    PS:ENTRY_TYPE,09H
                BR     NEAR PTR EXCEPT_ENT

UEE_CALLN:	MOV    PS:ENTRY_TYPE,0AH
                BR     NEAR PTR EXCEPT_ENT

JUMP_ENT:	MOV    PS:ENTRY_TYPE,0BH

; EXCEPTION PROCESS ENTRY
;   This routine is executed when the monitor is entered from an exception
;   process.

EXCEPT_ENT:	
		POP    PS:REG_PC
                POP    PS:REG_PS
		CMP    PS:REG_PS,SEG MONITOR_START
                BNE    SHORT EXCEPT_ENT_OK
                CMP    PS:REG_PC,OFFSET MONITOR_START
                BNH    SHORT EXCEPT_ENT_OK
                CMP    PS:REG_PC,OFFSET MONITOR_END
                BNL    SHORT EXCEPT_ENT_OK
                PUSH   PS:REG_PS
		PUSH   PS:REG_PC
          	RETI

EXCEPT_ENT_OK:	MOV    REG_DS0,DS0
                MOV    DS0,PS:DATA_SEGMENT
                POP    REG_PSW
		MOV    REG_SS,SS
		MOV    REG_SP,SP
		MOV    SS,PS:DATA_SEGMENT
                MOV    SP,OFFSET MONITOR_STACK
                MOV    REG_AW,AW
                MOV    REG_BW,BW
                MOV    REG_CW,CW
                MOV    REG_DW,DW
                MOV    REG_IX,IX
                MOV    REG_IY,IY
                MOV    REG_BP,BP
                MOV    REG_DS1,DS1
		BR     NEAR PTR MONITOR_LP_ENT
EXCEPT_END:
MONITOR_END:
Fgmon           ENDS


Fgmon           SEGMENT AT MONSEGMENT
                ORG    00E00H

COMM_BUF	DB 256 DUP (?)		;transfer buffer
Fgmon           ENDS


Fgmon           SEGMENT AT MONSEGMENT
		ORG    00F00H
JAM_STACK       DW 4 DUP (?) 		;jam stack
TMP_SS		DW  0
TMP_SP		DW  0
DATA_SEGMENT	DW  SEG MONITOR_STACK
Fgmon           ENDS


Fgmon           SEGMENT AT MONSEGMENT
	        ORG	00F10H
INFO_BLOCK      DW  '64'	;monitor information block
                DW  '79'
                DW  '2A'
                DW  0
		DW  TRAP_ENT-MONITOR_VECTOR
		DW  1010H
		DW  BCTL_EXITBKG-MONITOR_VECTOR
		DW  0909H
		DW  JAM_STACK+6-MONITOR_VECTOR
		DW  2020H
		DW  0
Fgmon		ENDS


Fgmon           SEGMENT AT MONSEGMENT
	        ORG	00FE0H
		DW 4 DUP (?)		;jam stack copy
JAM_STACK_CP: 
Fgmon           ENDS

;##############################################################################
;# KEY MONITOR ENTRY BACKGROUND                                               #
;##############################################################################

Fgmon           SEGMENT AT MONSEGMENT
	        ORG	00FF0H
   		ASSUME PS:Fgmon,DS0:Fgmon

MONITOR_STACK: 
BKG_RST_ENT     DB     14 DUP (90H)
		BR     NEAR PTR BKG_RST_ENT
Fgmon		ENDS



                END
