 
;##############################################################################
;
;    EMULATION FOREGROUND MONITOR FOR 64756 EMULATOR
;
; MKT:@(#) 64756-18018 A.00.04 70136 EMULATION FOREGROUND MONITOR       03Sep92                      
;
;##############################################################################
;
;    The emulation foreground monitor is the vehicle by which the following
;    emulator functions are effected if the 64756 emulator is configured to
;    operate with a foreground monitor.
;
;        read/write target system memory
;        read/write target system io port
;        display/modify registers
;        execute user program
;        break away from user program
;
;    The 64756 foreground monitor must start on a 4k byte boundary.
;    The desired 4k byte boundary should be specified in
;
;        MONSEGMENT	EQU	xx00H
;
;    statement at the start of the monitor as its PS (program segment) of the
;    real address 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 when
;    extend mode is not used.
;
;             0H -    0FFFH
;        0FF000H -  0FFFFFH
;        100000H - 0FFFFFFH
;
;    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:
;
;        Background Exception Vectors
;        Monitor Control
;        Brief Background State Entry
;        Foreground Monitor Entry
;
;
;    The "Background Exception Vectors" is used exclusively by the emulator
;    to transition into the foreground monitor from reset, from software bre-
;    akpoints 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 "Monitor Control" section contains four parts.  The first section is
;    the "Monitor Control Variables" which consists of variables used in the
;    monitor and background control memory.  The second is "Register Buffer",
;    the third is "Internal I/O Register Buffer".  These areas are used as
;    temporary buffer for storing the the contents of each register at enter-
;    ing monitor and for restoring them at exiting monitor.  The last section
;    "Communication Variables and Transfer Buffer" is a group of variables
;    that act as the communications path between the foreground monitor and
;    the emulation controller.
;
;    The "Brief Background State Entry" 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 "Foreground Monitor Entry" 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.
;
;
;    To perform display/modify target memory as extended address mode, monitor
;    temporarily BRKXA to extended mode for figuring out proper address and
;    RETXA to normal mode after the access is over.  PGR64 (page register 64)
;    is used for figuring out intentional extended address for target memory
;    access in case the specified access address given by  emulation controller
;    is extended. You can also change this page register number by means of
;    changing "FGMONPGR" in monitor constant section. ( Now PGMONPGR is 64 )
;
;    Emulation foreground monitor basically run only in the last address mode.
;    For this foreground monitor use with user program which exist any trans-
;    ition from/to normal address mode and extended address mode, following
;    vectors for BRKXA/RETXA should be assigned correctly in user's exception
;    vector table.  Default vector number is 240(0F0H) as following.
;
;		FGMON_VECNO	EQU	240
;
;		DD	BrkorRetXa
;
;
;    Emulation foreground monitor use following two page registers in order
;    to run in extend mode. The first one is PGR0, because a processor read
;    vector at 0-3ffH in extend address mode when processor return from extend
;    to normal mode.( PGR1 is selected in address range 0-3ffH ). The other
;    page register number is determined by fore ground monitor address. Emula-
;    tion fore ground monitor set that page register appropriately.
;
;##############################################################################

;##############################################################################
; Global Declaration
;##############################################################################

                PUBLIC  BrkorRetXa

		PUBLIC	UEE_DIV_ERR,	UEE_BRK_FLAG,	UEE_NMI
		PUBLIC	UEE_BRK_3,	UEE_BRKV,	UEE_CHKIND
		PUBLIC	UEE_UNDFND_TRAP,UEE_72291_ERR,	UEE_CP_ABSENT
		PUBLIC	UEE_BRK_IMM8,	UEE_INT

 
;##############################################################################
; Monitor Constants
;##############################################################################
 
PROG		SEGMENT	BYTE PUBLIC
		ASSUME	PS:PROG
		NAME	fm70136


MONSEGMENT	EQU	0100H 			; 4 Kbyte boundary
 
USERSS		EQU	MONSEGMENT		; stack used for monitor
USERSP		EQU	01000H			;  temporarily
 
FGMON_PSW	EQU	0F202H
MONOFFSET	EQU	0500H			; fgmon entry offset

FGMON_VECNO	EQU	240			; BRKXA/RETXA vector
						;           used in fgmon
FGMONPGR	EQU	64			; pgr for fg mon internal use
 
PROG		ENDS
 

 
;##############################################################################
; Background Exception Vectors
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00000H
 
BKG_EXCPT_VEC	DD	0
		DD	0
		DD	BkgStateEntry		; vec. 2
 
 
Fgmon		ENDS

Fgmon		SEGMENT AT MONSEGMENT
		ORG	00080H
 
		DD	RetFrmExAddrMode	; vec. 32
		DD	BreakToExAddrMode	; vec. 33
 
Fgmon		ENDS
 
 

;##############################################################################
; Monitor Control
;##############################################################################
 
;##############################################################################
; Monitor Control Variables
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	000C0H
 
LAST_SPADDR	DB	0			; 0C0H
FG_ADDR_MODE	DB	0			; 0C1H
EXIT_TYPE	DB	0			; 0C2H
		DB	0			; 0C3H alignment
FG_REG_PSW	DW	FGMON_PSW		; 0C4H
FG_REG_PS	DW	MONSEGMENT		; 0C6H
FG_REG_PC	DW	MONOFFSET		; 0C8H
 
BCTL00_1_ADDR	DW	BCTL00H_1-BKG_EXCPT_VEC	; 0CAH	return from background
BCTL00_1_VAR	DB	08H			; 0CCH
BCTL03_1_ADDR	DW	BCTL03H_1-BKG_EXCPT_VEC	; 0CDH  set emulator ready
BCTL03_1_VAR	DB	01H			; 0CFH
BCTLXX_1_ADDR	DW	BCTLXXH_1-BKG_EXCPT_VEC	; 0D0H
BCTLXX_1_VAR	DB	0			; 0D2H
BCTLXX_2_ADDR	DW	BCTLXXH_2-BKG_EXCPT_VEC	; 0D3H
BCTLXX_2_VAR	DB	0			; 0D5H
 
INIT_ENTRY	DB	0			; 0D6H
 
Fgmon		ENDS

 
;##############################################################################
; Register Buffer
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	000E0H
 
REG_PS		DW	0			; program segment
REG_PC		DW	0			; program counter
REG_PSW		DW	0F002H			; 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
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00100H
 
REG_PGR01	DW	0000H
REG_PGR02	DW	0000H
REG_PGR03	DW	0000H
REG_PGR04	DW	0000H
REG_PGR05	DW	0000H
REG_PGR06	DW	0000H
REG_PGR07	DW	0000H
REG_PGR08	DW	0000H
REG_PGR09	DW	0000H
REG_PGR10	DW	0000H
REG_PGR11	DW	0000H
REG_PGR12	DW	0000H
REG_PGR13	DW	0000H
REG_PGR14	DW	0000H
REG_PGR15	DW	0000H
REG_PGR16	DW	0000H
REG_PGR17	DW	0000H
REG_PGR18	DW	0000H
REG_PGR19	DW	0000H
REG_PGR20	DW	0000H
REG_PGR21	DW	0000H
REG_PGR22	DW	0000H
REG_PGR23	DW	0000H
REG_PGR24	DW	0000H
REG_PGR25	DW	0000H
REG_PGR26	DW	0000H
REG_PGR27	DW	0000H
REG_PGR28	DW	0000H
REG_PGR29	DW	0000H
REG_PGR30	DW	0000H
REG_PGR31	DW	0000H
REG_PGR32	DW	0000H
REG_PGR33	DW	0000H
REG_PGR34	DW	0000H
REG_PGR35	DW	0000H
REG_PGR36	DW	0000H
REG_PGR37	DW	0000H
REG_PGR38	DW	0000H
REG_PGR39	DW	0000H
REG_PGR40	DW	0000H
REG_PGR41	DW	0000H
REG_PGR42	DW	0000H
REG_PGR43	DW	0000H
REG_PGR44	DW	0000H
REG_PGR45	DW	0000H
REG_PGR46	DW	0000H
REG_PGR47	DW	0000H
REG_PGR48	DW	0000H
REG_PGR49	DW	0000H
REG_PGR50	DW	0000H
REG_PGR51	DW	0000H
REG_PGR52	DW	0000H
REG_PGR53	DW	0000H
REG_PGR54	DW	0000H
REG_PGR55	DW	0000H
REG_PGR56	DW	0000H
REG_PGR57	DW	0000H
REG_PGR58	DW	0000H
REG_PGR59	DW	0000H
REG_PGR60	DW	0000H
REG_PGR61	DW	0000H
REG_PGR62	DW	0000H
REG_PGR63	DW	0000H
REG_PGR64	DW	0000H
 
REG_XAM		DB	00000000B		; 0180H
 
Fgmon		ENDS

 
;##############################################################################
; Monitor & Driver Communication Variables and Transfer Buffer
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00200H
 
CMD_TYPE_RES	DB	80H			; 0200H
I_AM_HERE	DB	0			; 0201H
RW_SIZE_LOW	DW	0			; 0202H
;RW_SIZE_HIGH	DB	0			; 0203H
		DB	0                       ; 0204H
RW_ACCESS	DB	0			; 0205H
ADDR_MODE	DB	0			; 0206H
		DB	0			; 0207H
PGR_LOW		DB	0			; 0208H
PGR_HIGH	DB	0			; 0209H
SEG_LOW		DB	0			; 020AH
SEG_HIGH	DB	0			; 020BH
OFF_LOW		DB	0			; 020CH
OFF_HIGH	DB	0			; 020DH
 
EXCPT_ENTRY	DB	0			; 020EH
RESERVED	DB	0			; 020FH		reserved
 
COMM_BUF	DB	256 DUP (?)		; 0210H through 030FH
 
Fgmon		ENDS
 
 
;##############################################################################
; Brief Background State Entry
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00310H
 	        ASSUME PS:Fgmon,DS0:Fgmon
BkgStateEntry:
		MOV	PS:EXCPT_ENTRY,0	; any break entry
 
 
;##############################################################################
; Store Registers Used in Background State
 
START_BKG:	MOV	PS:REG_AW,AW
		MOV	PS:REG_DW,DW
 
 
;##############################################################################
; Check Stack Pointer whether Odd or Even
 
		MOV	AW,SP
		AND	AW,0001H
		BZ	STORE_EVEN
 
 
;##############################################################################
; Store Registers PSW, PS and PC and Set Them for Foreground Monitor
 
STORE_ODD:	MOV	AL,PS:JAM_STACK+07H	; store pc
		MOV	AH,PS:JAM_STACK+04H
		MOV	PS:REG_PC,AW
		MOV	AL,PS:JAM_STACK+0BH	; store ps
		MOV	AH,PS:JAM_STACK+08H
		MOV	PS:REG_PS,AW
		MOV	AL,PS:JAM_STACK+0FH	; store psw
		MOV	AH,PS:JAM_STACK+0CH
		MOV	PS:REG_PSW,AW
 
FG_RESTORE_ODD:	MOV	AW,PS:REG_PSW		; restore fgmon psw
		MOV	PS:JAM_STACK+07H,AL
		MOV	PS:JAM_STACK+04H,AH
		MOV	AW,PS:FG_REG_PS		; restore fgmon ps
		MOV	PS:JAM_STACK+0BH,AL
		MOV	PS:JAM_STACK+08H,AH
		MOV	AW,PS:FG_REG_PC		; restore fgmon pc
		MOV	PS:JAM_STACK+0FH,AL
		MOV	PS:JAM_STACK+0CH,AH
		BR	CHECK_LA_MODE1
 
STORE_EVEN:	MOV	AW,WORD PTR PS:JAM_STACK+0AH
		MOV	PS:REG_PC,AW		; store pc
		MOV	AW,WORD PTR PS:JAM_STACK+0CH
		MOV	PS:REG_PS,AW		; store ps
		MOV	AW,WORD PTR PS:JAM_STACK+0EH
		MOV	PS:REG_PSW,AW		; store psw
 
FG_RESTORE_EVEN:MOV	AW,PS:REG_PSW		; restore fgmon psw
		MOV	WORD PTR PS:JAM_STACK+0AH,AW
		MOV	AW,PS:FG_REG_PS		; restore fgmon ps
		MOV	WORD PTR PS:JAM_STACK+0CH,AW
		MOV	AW,PS:FG_REG_PC		; restore fgmon pc
		MOV	WORD PTR PS:JAM_STACK+0EH,AW
 
 
;##############################################################################
; Get Into Normal Address Mode (Background)
 
CHECK_LA_MODE1:	MOV	DW,0FF80H
		IN	AL,DW			; read xam io register
		MOV	PS:REG_XAM,AL		; store xam
		AND	AL,01H			; check last address mode
		BZ	FROM_NRML_MODE1
 
FROM_EXTD_MODE1:MOV	PS:FG_ADDR_MODE,01H	; set addr mode var (extended)
		RETXA	32
 
FROM_NRML_MODE1:MOV	PS:FG_ADDR_MODE,00H	; set addr mode var (normal)
		BR	PGRNO_FIND
 
RetFrmExAddrMode:
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
BCTL03H_1:					; bctl03 set emulator ready
 
 
;##############################################################################
; Page register set for extend mode while running fore ground monitor

PGRNO_FIND:	MOV	AW,PS			; set ps data to aw
		SHR	AW,10H			; set pgr no. to aw by shifting
		MOV	DW,AW

CALC_PGR_ADDR:	SHL	DW,1			; aw = aw * 2
		ADD	DW,0FF00H		; calculate pgr address
		OUT	DW,AW			; pgr set

		MOV	DW,0FF00H		; set pgr1 addr
		MOV	AW,0
		OUT	DW,AW			; set pgr1=0

		MOV	AL,PS:FG_ADDR_MODE
		AND	AL,01H			; check last address mode
		BZ	GOTO_FGMON


;############################################################################
; Return to extend mode

RET_TO_EXTEND:
		BRKXA	33

BreakToExAddrMode:


;##############################################################################
; Exit Background State and Go To Foreground Monitor
 
GOTO_FGMON:	NOP
		NOP
		NOP
 
BCTL00H_1:	NOP				; bctl00 makes load jam counter
		NOP
		NOP
		DB	0FH			; instruction used in emulator
		DB	0CFH			;  for exiting background state
 
Fgmon		ENDS
 

 
;##############################################################################
; Foreground Monitor Entry
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00500H
 
 
;##############################################################################
; Store Registers Other Than AW and DW
 
MONITOR:	MOV	PS:REG_SS,SS		; from background
		MOV	PS:REG_SP,SP
 
MON_FG_ENT:	MOV	PS:REG_BW,BW		; from foreground
		MOV	PS:REG_CW,CW
		MOV	PS:REG_IX,IX
		MOV	PS:REG_IY,IY
		MOV	PS:REG_BP,BP
		MOV	PS:REG_DS0,DS0
		MOV	PS:REG_DS1,DS1
 
 
;##############################################################################
; Set Monitor Stack Pointer
 
		CMP	PS:INIT_ENTRY,0		; first entry from bkg
		BNZ	ADDRM_CHK
 
		MOV	PS:INIT_ENTRY,1		; not first entry
		MOV	AW, USERSS
		MOV	SS,AW
		MOV	PS:REG_SS, USERSS
		MOV	SP, USERSP
		MOV	PS:REG_SP, USERSP
 
;##############################################################################
; Clear DIR flag for block move

		CLR1	DIR

;##############################################################################
; Address Mode Check

ADDRM_CHK:
		CMP	PS:FG_ADDR_MODE,01	; check address mode
		BNE	STORE_PGRS
		PUSH	PSW
		DI
		CALL	S_RETXA


;##############################################################################
; Store Page Registers
 
STORE_PGRS:	MOV	AW,0FF00H
		MOV	DW,AW			; set dw to pgr1
		MOV	IY,OFFSET REG_PGR01	; set iy to reg_pgr1
		MOV	CW,40H			; 64 word counts
 
STORE_IOREG:	IN	AW,DW
		MOV	PS:WORD PTR [IY],AW
		INC	IY
		INC	IY
		INC	DW
		INC	DW
		DBNZ	STORE_IOREG
 
 
;##############################################################################
; Address Mode Check

		CMP	PS:FG_ADDR_MODE,01	; check address mode
		BNE	MON_LOOP
		CALL	S_BRKXA
		POP	PSW


;##############################################################################
; Monitor Command Completion
 
CMD_COMPLETE:
 
 
;##############################################################################
; Monitor Command Waiting Main Loop
 
MON_LOOP:	MOV	AL,11H
		MOV	PS:I_AM_HERE,AL		; monitor is in the main loop
 
	        MOV	AL,PS:CMD_TYPE_RES	; check command requested
		AND	AL,80H
		BNZ	MON_LOOP
 
 
;##############################################################################
; Command Interpreter
 
CMD_REQUEST: 	CMP	PS:CMD_TYPE_RES,04H	; target memory read
		BE	TRGT_MEM_RD0
		CMP	PS:CMD_TYPE_RES,03H	; target memory write
		BE	TRGT_MEM_WR0
		CMP	PS:CMD_TYPE_RES,06H	; target io read
		BE	TRGT_IO_RD0
		CMP	PS:CMD_TYPE_RES,05H	; target io write
		BE	TRGT_IO_WR0
		CMP	PS:CMD_TYPE_RES,01H	; exit monitor (run)
		BE	PRCS_EXIT
		CMP	PS:CMD_TYPE_RES,02H	; exit monitor (step)
		BE	PRCS_STEP
		CMP	PS:CMD_TYPE_RES,07H	; goto target reset loop
		BE	PRCS_TRGT_RST
CMD_ILGL:	MOV	PS:CMD_TYPE_RES,0FFH	; command illegal
		BR	CMD_COMPLETE
 
TRGT_MEM_RD0:	BR	TRGT_MEM_RD
TRGT_MEM_WR0:	BR	TRGT_MEM_WR
TRGT_IO_RD0:	BR	TRGT_IO_RD
TRGT_IO_WR0:	BR	TRGT_IO_WR
 
PRCS_EXIT:	MOV	PS:CMD_TYPE_RES,80H	; command recognized
		MOV	PS:EXIT_TYPE,01H	; exit with run
		BR	EXIT_START
 
PRCS_STEP:	MOV	PS:CMD_TYPE_RES,80H	; command recognized
		MOV	PS:EXIT_TYPE,02H	; exit with step
		BR	EXIT_START
 
PRCS_TRGT_RST:	MOV	PS:CMD_TYPE_RES,80H	; command recognized
		BR	TRGT_RESET
 
Fgmon		ENDS
 
 
;##############################################################################
; Target Memory Write
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00600H
 
TRGT_MEM_WR:
		CMP	PS:FG_ADDR_MODE,01	; check address mode
		BNE	TGT_M_WR
		PUSH	PSW
		DI
		CALL	S_RETXA

TGT_M_WR:	MOV	AL,PS:SEG_LOW
		MOV	AH,0
		CMP	PS:ADDR_MODE,01		; check accessing address mode
		BE	NML_WR_SEG
		MOV	AH,FGMONPGR		; set segment reg. as to
		DEC	AH			;  use FGMONPGR
		SHL	AH,2
NML_WR_SEG:	ADD	AH,PS:SEG_HIGH
		MOV	DS1,AW			; set ds1 to tgt addr segment
		MOV	AL,PS:OFF_LOW
		MOV	AH,PS:OFF_HIGH
		MOV	IY,AW			; set iy to tgt addr offset
		MOV	BW,AW			; keep contents of aw in bw
		MOV	AW,MONSEGMENT
		MOV	DS0,AW			; set ds0 to monitor segment
		MOV	IX,OFFSET COMM_BUF	; set ix to comm_buf
		MOV	CW,PS:RW_SIZE_LOW	; set cw byte counts

		CMP	PS:ADDR_MODE,01
		BE	CHECK_WRACSIZE
		MOV	AL,PS:PGR_LOW
		MOV	AH,PS:PGR_HIGH
		MOV	DL,FGMONPGR		; set address of pgr that is
		DEC	DL			;  defined by top of fg monitor
		SHL	DL,1
		MOV	DH,0FFH
		OUT	DW,AW

CHECK_WRACSIZE:	CMP	PS:RW_ACCESS,'w'	; check access size word or byte
		BNE	BYTE_WR_START
		AND	BW,0001H
		BNZ	BYTE_WR_START


WORD_WR_START:
		CMP	PS:ADDR_MODE,01		; check accessing address mode
		BE	MEM_WORD_WR
		CALL	S_BRKXA

		MOV	BW,0
		TEST1	CW,0
		BZ	MEM_EW_WR		; if byte count is not even
		DEC	CW			;  then decrease byte count
		BZ	MEM_REST_WR
		MOV	BW,01			; remember decrement of cw
MEM_EW_WR:	SHR	CW,1			; byte count / 2 ( word count)

MEM_WORD_WR:	REP	MOVBKW

		CMP	BW,0
		BE	MEM_WR_FIN		; if byte count was odd
MEM_REST_WR:	MOV	CW,1			;  then go to byte write
		BR	MEM_BYTE_WR		;   to write 1 more byte

BYTE_WR_START:
		CMP	PS:ADDR_MODE,01		; check accessing address mode
		BE	MEM_BYTE_WR
		CALL	S_BRKXA

MEM_BYTE_WR:	REP	MOVBKB

MEM_WR_FIN:
		CMP	PS:ADDR_MODE,01		; check accessed address mode
		BE	TGT_WR_FIN
		CALL	S_RETXA
		BR	TGT_WR_FIN

TGT_WR_FIN:
		CMP	PS:FG_ADDR_MODE,01H	; check address mode
		BNE	WR_FIN
		CALL	S_BRKXA
		POP	PSW

WR_FIN:
		MOV	PS:CMD_TYPE_RES,80H	; command finished
		BR	CMD_COMPLETE
 
Fgmon		ENDS
 
 

;##############################################################################
; Target Memory Read
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00700H
 
TRGT_MEM_RD:
		CMP	PS:FG_ADDR_MODE,01	; check address mode
		BNE	TGT_M_RD
		PUSH	PSW
		DI
		CALL	S_RETXA

TGT_M_RD:	MOV	AL,PS:SEG_LOW
		MOV	AH,0
		CMP	PS:ADDR_MODE,01		; check accessing address mode
		BE	NML_RD_SEG
		MOV	AH,FGMONPGR		; set segment reg. as to
		DEC	AH			;  use FGMONPGR
		SHL	AH,2
NML_RD_SEG:	ADD	AH,PS:SEG_HIGH
		MOV	DS0,AW			; set ds0 to tgt addr segment
		MOV	AL,PS:OFF_LOW
		MOV	AH,PS:OFF_HIGH
		MOV	IX,AW			; set ix to tgt addr offset
		MOV	BW,AW			; keep contents of aw in bw
		MOV	AW,MONSEGMENT
		MOV	DS1,AW			; set ds1 to monitor segment
		MOV	IY,OFFSET COMM_BUF	; set iy to comm_buf
		MOV	CW,PS:RW_SIZE_LOW	; set cw byte counts

		CMP	PS:ADDR_MODE,01
		BE	CHECK_RDACSIZE
		MOV	AL,PS:PGR_LOW
		MOV	AH,PS:PGR_HIGH
		MOV	DL,FGMONPGR		; set address of pgr that is
		DEC	DL			;  defined by top of fg monitor
		SHL	DL,1
		MOV	DH,0FFH
		OUT	DW,AW

CHECK_RDACSIZE:	CMP	PS:RW_ACCESS,'w'	; check access size word or byte
		BNE	BYTE_RD_START
		AND	BW,0001H
		BNZ	BYTE_RD_START


WORD_RD_START:
		CMP	PS:ADDR_MODE,01		; check accessing address mode
		BE	MEM_WORD_RD
		CALL	S_BRKXA

		MOV	BW,0
		TEST1	CW,0
		BZ	MEM_EW_RD		; if byte count is not even
		DEC	CW			;  then decrease byte count
		BZ	MEM_REST_RD
		MOV	BW,01			; remember decrement of cw
MEM_EW_RD:	SHR	CW,1			; byte count / 2 ( word count)

MEM_WORD_RD:	REP	MOVBKW

		CMP	BW,0
		BE	MEM_RD_FIN		; if byte count was odd
MEM_REST_RD:	MOV	CW,1			;  then go to byte write
		BR	MEM_BYTE_RD		;   to write 1 more byte

BYTE_RD_START:
		CMP	PS:ADDR_MODE,01		; check accessing address mode
		BE	MEM_BYTE_RD
		CALL	S_BRKXA

MEM_BYTE_RD:	REP	MOVBKB

MEM_RD_FIN:
		CMP	PS:ADDR_MODE,01		; check accessed address mode
		BE	TGT_RD_FIN
		CALL	S_RETXA
		BR	TGT_RD_FIN

TGT_RD_FIN:
		CMP	PS:FG_ADDR_MODE,01H	; check address mode
		BNE	RD_FIN
		CALL	S_BRKXA
		POP	PSW

RD_FIN:
		MOV	PS:CMD_TYPE_RES,80H	; command finished
		BR	CMD_COMPLETE
 
Fgmon		ENDS
 

 
;##############################################################################
; Target IO Write
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00800H
 
TRGT_IO_WR:	MOV	DL,PS:OFF_LOW		; set dw (dl, dh) to get
		MOV	DH,PS:OFF_HIGH		;  tgt io address
		MOV	AW,DW			; copy io address to aw
		MOV	IX,OFFSET COMM_BUF	; set iy to pint comm_buf
		MOV	CW,PS:RW_SIZE_LOW	; cw indicates how many bytes

		CMP	PS:RW_ACCESS,'w'	; if not access size is word
		BNE	IO_BYTE_WR		;  then goto io_byte_wr
		AND	AW,0001H		;  if not start address is even
		BNZ	IO_BYTE_WR		;   then goto io_byte_wr

		MOV	BW,0
		TEST1	CW,0
		BZ	IO_WORD_WR		; if byte count is not even
		DEC	CW			;  then decrease byte count
		BZ	IO_REST_WR
		MOV	BW,01			; remember decrement of cw

IO_WORD_WR:	MOV	AW,PS:WORD PTR[IX]	; comm_buf --> reg. al
		OUT	DW,AW			; reg. al --> tgt io(1 byte)
		INC	IX			; increment comm_buf addr.
		INC	IX			; increment comm_buf addr.
		INC	DW			; increment target io. addr.
		INC	DW			; increment target io. addr.
		DEC	CW			; decrement cw by one
		DBNZ	IO_WORD_WR		; continue mop_write while cw
						;   is not zero
		CMP	BW,0
		BE	IO_WR_FIN		; if byte count was odd
IO_REST_WR:	MOV	CW,1			;  then go to byte write
		BR	IO_BYTE_WR		;   to write 1 more byte

		BR	IO_WR_FIN

IO_BYTE_WR:	MOV	AL,PS:BYTE PTR[IX]	; comm_buf --> reg. al
		OUT	DW,AL			; reg. al --> tgt io(1 byte)
		INC	IX			; increment comm_buf addr.
		INC	DW			; increment target io. addr.
		DBNZ	IO_BYTE_WR		; continue mop_write while cw
						;   is not zero
IO_WR_FIN:	MOV	PS:CMD_TYPE_RES,80H	; tell the driver command has
		BR	CMD_COMPLETE		;  just successfully finished
 
Fgmon		ENDS

 
 
;##############################################################################
; Target IO Read
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00870H
 
TRGT_IO_RD:	MOV	DL,PS:OFF_LOW		; set dw (dl, dh) to get
		MOV	DH,PS:OFF_HIGH		;  tgt io address
		MOV	AW,DW			; copy io address to aw
		MOV	IY,OFFSET COMM_BUF	; set iy to pint comm_buf
		MOV	CW,PS:RW_SIZE_LOW	; cw indicates how many bytes

		CMP	PS:RW_ACCESS,'w'	; if not access size is word
		BNE	IO_BYTE_RD		;  then goto io_byte_rd
		AND	AW,0001H		;  if not start address is even
		BNZ	IO_BYTE_RD		;   then goto io_byte_rd

		MOV	BW,0
		TEST1	CW,0
		BZ	IO_WORD_RD		; if byte count is not even
		DEC	CW			;  then decrease byte count
		BZ	IO_REST_RD
		MOV	BW,01			; remember decrement of cw

IO_WORD_RD:	IN	AW,DW			; tgt io(2 byte) --> reg. aw
		MOV	PS:WORD PTR[IY],AW	; reg. aw --> comm_buf
		INC	DW			; increment terget io. addr.
		INC	DW			;  by two
		INC	IY			; increment comm_buf addr.
		INC	IY			;  by two
		DEC	CW			; decrement cw by one
		DBNZ	IO_WORD_RD		; continue mop_write while cw
						;   is not zero
		CMP	BW,0
		BE	IO_RD_FIN		; if byte count was odd
IO_REST_RD:	MOV	CW,1			;  then go to byte write
		BR	IO_BYTE_RD		;   to write 1 more byte

		BR	IO_RD_FIN

IO_BYTE_RD:	IN	AL,DW			; tgt io(1 byte) --> reg. al
		MOV	PS:BYTE PTR[IY],AL	; reg. al --> comm_buf
		INC	DW			; increment terget io. addr.
		INC	IY			; increment comm_buf addr.
		DBNZ	IO_BYTE_RD		; continue mop_write while cw
						;   is not zero
IO_RD_FIN:	MOV	PS:CMD_TYPE_RES,80H	; tell the driver command has
		BR	CMD_COMPLETE		;  just successfully finished
 
Fgmon		ENDS
 

 
;##############################################################################
; Target Reset Waiting Loop
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	008D0H
 
TRGT_RESET:	MOV	AL,33H			; monitor is in the target reset
		MOV	PS:I_AM_HERE,AL		;  waiting loop
 
	        CMP	PS:CMD_TYPE_RES,7FH	; check back-to-main request
		BNE	TRGT_RESET
		BR	CMD_COMPLETE
 
Fgmon		ENDS
 

 
;##############################################################################
; Monitor Exit Routine
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	008F0H
 
EXIT_START:
 

;##############################################################################
; Address Mode Check

		CMP	PS:FG_ADDR_MODE,01	; check address mode
		BNE	RESTORE_PGRS
		PUSH	PSW
		DI
		CALL	S_RETXA


;##############################################################################
; Restore Page Registers
 
RESTORE_PGRS:	MOV	AW,0FF00H
		MOV	DW,AW			; set dw to pgr1
		MOV	IY,OFFSET REG_PGR01	; set iy to reg_pgr0
		MOV	CW,40H			; 64 word counts
 
RESTORE_IOREG:	MOV	AW,PS:WORD PTR [IY]
		OUT	DW,AW
		INC	IY
		INC	IY
		INC	DW
		INC	DW
		DBNZ	RESTORE_IOREG
 
 
;##############################################################################
; Address Mode Check

		CMP	PS:FG_ADDR_MODE,01	; check address mode
		BNE	SET_BFLG
		CALL	S_BRKXA
		POP	PSW

 
;##############################################################################
; Set BRK Flag for Single Step Exit
 
SET_BFLG:	MOV	AL,PS:EXIT_TYPE
		CMP	AL,01H
		BE	SET_PSPCPSW
		OR	PS:REG_PSW,0100H	; set brk flag
 
 
;##############################################################################
; Stack registers PS, PC and PSW
 
SET_PSPCPSW:	PUSH	PS:REG_PSW		; restore psw
		PUSH	PS:REG_PS		; restore ps
		PUSH	PS:REG_PC		; restore pc
 
 
;##############################################################################
; Adjust Stack Pointer (-)
 
ADJ_SP_MINUS:	SUB	PS:REG_SP,06H
 
 
;##############################################################################
; Restore Registers
 
RESTORE_REG:	MOV	AW,PS:REG_AW
		MOV	BW,PS:REG_BW
		MOV	CW,PS:REG_CW
		MOV	DW,PS:REG_DW
		MOV	IX,PS:REG_IX
		MOV	IY,PS:REG_IY
		MOV	BP,PS:REG_BP
		MOV	DS0,PS:REG_DS0
		MOV	DS1,PS:REG_DS1
		MOV	SS,PS:REG_SS
		MOV	SP,PS:REG_SP
 
 
;##############################################################################
; Exit Foreground Monitor and Get Into User Program
 
RUN_EXIT:	RETI
 
Fgmon		ENDS

 
 
;##############################################################################
; User Exception Entries
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00A00H
 
UEE_DIV_ERR:	MOV	PS:EXCPT_ENTRY,01H	; 0A00H  divide error
		BR	FG_ENTRY
 
UEE_BRK_FLAG:	MOV	PS:EXCPT_ENTRY,02H	; 0A09H  break flag (step)
		BR	FG_ENTRY
 
UEE_NMI: 	MOV	PS:EXCPT_ENTRY,03H	; 0A12H  nmi
		BR	FG_ENTRY
 
UEE_BRK_3:	MOV	PS:EXCPT_ENTRY,04H	; 0A1BH  brk 3 instruction
		BR	FG_ENTRY
 
UEE_BRKV:	MOV	PS:EXCPT_ENTRY,05H	; 0A24H  brkv instruction
		BR	FG_ENTRY
 
UEE_CHKIND:	MOV	PS:EXCPT_ENTRY,06H	; 0A2DH  check index boundary
		BR	FG_ENTRY
 
UEE_UNDFND_TRAP:MOV	PS:EXCPT_ENTRY,07H	; 0A36H  undefined instruction
		BR	FG_ENTRY
 
UEE_72291_ERR:	MOV	PS:EXCPT_ENTRY,08H	; 0A3FH  upd72291 error
		BR	FG_ENTRY
 
UEE_CP_ABSENT:	MOV	PS:EXCPT_ENTRY,09H	; 0A48H  co-processor absence
		BR	FG_ENTRY
 
UEE_BRK_IMM8:	MOV	PS:EXCPT_ENTRY,0AH	; 0A51H  brk imm8 instruction
		BR	FG_ENTRY
 
UEE_INT:	MOV	PS:EXCPT_ENTRY,0BH	; 0A5AH  int
		BR	FG_ENTRY
 
Fgmon		ENDS

 
;##############################################################################
; User Exception Foreground Entry
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00AA0H
 
FG_ENTRY:	MOV	PS:REG_AW,AW
		MOV	PS:REG_DW,DW
 
;##############################################################################
; Store Registers PSW, PS and PC
 
		POP	PS:REG_PC
		POP	PS:REG_PS
		POP	PS:REG_PSW
 
;##############################################################################
; Store Registers SP and SS

		MOV	PS:REG_SP,SP
		MOV	PS:REG_SS,SS
 
;##############################################################################
; Check Last Exit and Clear BRK Flag
 
		CMP	PS:EXIT_TYPE,02H	; check last exit type
		BNE	CHECK_LA_MODE2
		AND	PS:REG_PSW,0FEFFH	; clear brk flag
 
		PUSH	PS:REG_PSW		; set user data to psw
		POP	PSW			;  because ie flag was cleared
						;  cause to brk flag break
 
;##############################################################################
; Get Into Normal Address Mode (Foreground)
 
CHECK_LA_MODE2:	MOV	DW,0FF80H
		IN	AL,DW			; read xam io register
		MOV	PS:REG_XAM,AL		; store xam
		AND	AL,01H			; check last address mode
		BZ	FROM_NRML_MODE2
 
FROM_EXTD_MODE2:MOV	PS:FG_ADDR_MODE,01H	; set addr mode var (extended)
		BR	MON_FG_ENT
 
FROM_NRML_MODE2:MOV	PS:FG_ADDR_MODE,00H	; set addr mode var (normal)
		BR	MON_FG_ENT
 

;##############################################################################
; Break to Extend Mode & Return From Extend Mode Subroutine

S_BRKXA:	NOP
		BRKXA   FGMON_VECNO


S_RETXA:	NOP
		RETXA   FGMON_VECNO

BrkorRetXa:
                RET

Fgmon		ENDS
 
 
;##############################################################################
; Jamming Stack used in Background State
;##############################################################################
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	0E00H
 
JAM_STACK	DB	0		; 0E00H
		DB	0		; 0E01H
		DB	0		; 0E02H
		DB	0		; 0E03H
					;          SP=even     SP=odd
					;         |         |  |         |
		DB	0		; 0E04H   |         |  | PC  (h) |
		DB	0		; 0E05H   |         |  |         |
		DB	0		; 0E06H   |         |  |         |
		DB	0		; 0E07H   |         |  | PC  (l) |
		DB	0		; 0E08H   |         |  | PS  (h) |
		DB	0		; 0E09H   |         |  |         |
		DB	0		; 0E0AH   | PC  (l) |  |         |
		DB	0		; 0E0BH   | PC  (h) |  | PS  (l) |
		DB	0		; 0E0CH   | PS  (l) |  | PSW (h) |
		DB	0		; 0E0DH   | PS  (h) |  |         |
		DB	0		; 0E0EH   | PSW (l) |  |         |
		DB	0		; 0E0FH   | PSW (h) |  | PSW (l) |
					;         |         |  |         |
 
Fgmon		ENDS

 
;##############################################################################
; Reserved Background Control Memory
;
;   currently these two background control memory are not used, but reserved
;    for the future modification
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00EF0H
BCTLXXH_1:
 
Fgmon		ENDS

Fgmon		SEGMENT AT MONSEGMENT
		ORG	00EF2H
BCTLXXH_2:
 
Fgmon		ENDS

 
;##############################################################################
; Spared Area for Any User Code
;
;   monitor temporary stack is used from the bottom of the spared area
 
Fgmon		SEGMENT AT MONSEGMENT
		ORG	00F00H
 
TEMP_STACK	DB     256 DUP (?)
 
Fgmon		ENDS
 

 
;##############################################################################
;       The End of 70136 Foreground Monitor
;##############################################################################
 
END
