********************************************************************************
* A Hewlett-Packard Software Product
* Copyright Hewlett-Packard Co. 1993
*
* All Rights Reserved. Reproduction, adaptation, or translation without prior
* written  permission  is prohibited, except as allowed under copyright laws.
********************************************************************************
* Customizable Foreground Monitor for HP 64783 Motorola 68040 Emulator
*
* The emulation monitor is the vehicle by which the following emulator
* functions are performed:
*
*      read/write emulation/target memory space
*      display/modify registers
*      run/step user program
*      break away from user program
*
* The monitor must be linked on a 4K byte boundary and cannnot exceed 4K bytes
* in size.  The starting address is specified in the "ORG" statement at the
* start of this file (address must end in $000).  This address must match the
* address used for the monitor address configuration question within the
* emulation interface.  In this manner, communication between the monitor and
* the emulator operating software can be established.
*
* The monitor consists of $680 bytes of data space followed by $980 bytes of
* code space.  The emulator operating software communicates with the monitor
* through the data space and no changes should be made to this portion of the
* monitor.  See areas marked as "USER MODIFIABLE" for specific customizations
* typically required by target systems.
********************************************************************************

	CHIP    68040
	ORG     $XXXXX000     must be on 4K boundary (ending in $000)

********************************************************************************
*****************   M O N I T O R   D A T A   S E C T I O N   ******************
********************************************************************************

********************************************************************************
* Monitor Vector Table - 256 bytes 
********************************************************************************
MONDATA		DC.L    MONSTACK           Reset Initial Interrupt Stack Pointer
		DC.L    RESET_ENTRY        Reset Initial Program Counter
		DC.L    ERROR_ENTRY        Access Fault
		DC.L    ERROR_ENTRY        Address Error
		DC.L	ERROR_ENTRY        Illegal Instruction
		DC.L    ERROR_ENTRY        Zero Divide
		DC.L    ERROR_ENTRY        CHK,CHK2 Instructions
		DC.L    ERROR_ENTRY        FTRAPcc,TRAPcc,TRAPV Instructions
		DC.L    ERROR_ENTRY        Privilege Violation
		DC.L	TRACE_ENTRY        Trace Entry
		DC.L    ERROR_ENTRY        Unimplemented A-Line Instruction
		DC.L    ERROR_ENTRY        Unimplemented F-Line Instruction
		DCB.W   2,$484F            Unassigned/Reserved (vector 12)
		DC.L    1                  Unassigned/Reserved (vector 13)
		DC.L    ERROR_ENTRY        Format Error
		DC.L    ERROR_ENTRY        Uninitialized Interrupt
		DCB.L   4,BREAKPOINT_ENTRY Unassigned/Reserved
		DCB.L   4,INTERRUPT_ENTRY  Unassigned/Reserved
		DCB.L   8,ERROR_ENTRY      Spurious/autovector interrupts
		DCB.L   16,ERROR_ENTRY     Trap #0-15 Instruction Vectors
		DCB.L   8,ERROR_ENTRY      FP Exceptions
		DCB.L   4,1                Unassigned/Reserved (vector 56-59)
MON_EXIT        DC.L	0                  Reserved (vector 60)
MON_MOP         DC.L	0                  Reserved (vector 61)
MON_XLX         DC.L	0                  Reserved for I/O port (vector 62)
MON_FGTRAN      DC.L	0                  Reserved (vector 63)

********************************************************************************
* Monitor Variables - 256 bytes
********************************************************************************
MON_RANGE                    ; Monitor Code Address Range for CMP2
MON_STARTADDR   DC.L MONPROG
MON_ENDADDR     DC.L MONPROGEND

* Monitor Control Registers 
CMD_HANDSHAKE   DC.B 0       ; nonzero if command being executed
CMD_CONTROL     DC.B 0       ; command to be executed
CMD_RESULT      DC.B 0       ; result of executed command
MEM_FCS         DC.B 0       ; function codes to use for read/write
MEM_ADDR        DC.L 0       ; target address for read/write
MEM_BYTES       DC.W 0       ; number of bytes to transfer
MEM_SIZE        DC.W 0       ; access size to use for read/write
MEM_MMUSR       DC.L 0       ; mmu status register after ptest
MON_LASTENTRY   DC.B 0       ; last exception entry into monitor
MON_CONTROL     DC.B 0       ; miscellaneous flags
MON_INTRLEVEL   DC.B 0       ; minimum interrupt level (foregound only)
MON_KAFCS       DC.B 0       ; keep alive address (background only)
MON_KAADDR      DC.L 0       ; keep alive address (background only)
REG_MASK        DC.W 0

TMP1            DS.B 14
TMP2            DS.B 16
TMP3            DS.B 16
TMP4            DS.B 32

* User Registers
MPC             DC.L 0       ; program counter
RSVD_1          DC.W 0       ; padding
MSR             DC.W $2700   ; status register
MREGS
MD0             DC.L 0       ; data registers D0-D7
MD1             DC.L 0
MD2             DC.L 0
MD3             DC.L 0
MD4             DC.L 0
MD5             DC.L 0
MD6             DC.L 0
MD7             DC.L 0
MA0             DC.L 0       ; address registers A0-A7
MA1             DC.L 0
MA2             DC.L 0
MA3             DC.L 0
MA4             DC.L 0
MA5             DC.L 0
MA6             DC.L 0
MA7             DC.L 0
MUSP            DC.L 0       ; user stack pointer
MMSP            DC.L 0       ; master stack pointer
MISP            DC.L 0       ; interrupt stack pointer
MVBR            DC.L 0       ; vector base register
MCACR           DC.L 0       ; cache control register
MSFC            DC.L 0       ; source function code register
MDFC            DC.L 0       ; destination function code register
RSVD_2          DC.W 0       ; padding
MVO             DC.W 0       ; stack frame format word

* Table of Exception Stack Frame Sizes
FRAMESIZE       DC.W 8       ; format $0 - four word stack frame
		DC.W 8       ; format $1 - throwaway four word stack frame
		DC.W 12      ; format $2 - six word stack frame
		DC.W 12      ; format $3 - FP post instruction stack frame
		DC.W 16      ; format $4 - unimplemented FP stack frame (EC040)
		DC.W 0,0     ; format $5-$6 - invalid/undefined
		DC.W 60      ; format $7 - access error stack frame
		DC.W 0,0,0,0 ; format $8-$B - invalid/undefined
		DC.W 0,0,0,0 ; format $C-$F - invalid/undefined

TMP5            DS.B 8

********************************************************************************
* Monitor Transfer Buffer - 1024 bytes
********************************************************************************
MONTRANS	DS.B $400

********************************************************************************
* Monitor Interrupt Stack - 128 bytes
********************************************************************************
		DS.B $80
MONSTACK

********************************************************************************
* Monitor Equates
********************************************************************************
* Equates for CMD_CONTROL
CC_SWINMON      EQU     0     ;are you there?
CC_EXITMON      EQU     1     ;exit monitor
CC_MEMREAD      EQU     2     ;read memory
CC_MEMWRITE     EQU     3     ;write memory
CC_FPUREAD      EQU     4     ;read fpu registers 
CC_FPUWRITE     EQU     5     ;write fpu registers 
CC_MMUREAD      EQU     6     ;read mmu registers 
CC_MMUWRITE     EQU     7     ;write mmu registers 
CC_MMUTRANS     EQU     8     ;ptest address

* Equates for CMD_RESULT (vector numbers)
CR_SUCCESS      EQU     0     ;success
CR_RESET        EQU     1     ;target reset
CR_ACCFAULT     EQU     2     ;access fault
CR_ADDRERROR    EQU     3     ;address error
CR_ILLEGAL      EQU     4     ;illegal instruction
CR_BADREQUEST   EQU     64    ;bogus command requested
CR_ACCVIO       EQU     65    ;access violation (grd/wrrom)
CR_TIMEOUT      EQU     66    ;reserved
CR_DPBUSERROR   EQU     67    ;reserved

* Equates for MON_CONTROL
MC_TRACEMODE    EQU     0     ;single step being performed
MC_KEEPALIVE    EQU     1     ;enable keep alive access (background only)
MC_MMUENABLED   EQU     1     ;mmu enabled (foreground only)
MC_CMBWAIT      EQU     2     ;monitor in CMB wait loop
MC_BKPTREENTRY  EQU     3     ;monitor executed BKPT to transition hardware
MC_IDLE         EQU     4     ;monitor in idle loop

* Equates for MON_XLX (flags from xilinix hardware)
MX_CMBBRK_L     EQU     0     ;exit CMB wait and abort exit
MX_CMBRDY_L     EQU     1     ;exit CMB wait and continue exit
MX_EMRDY        EQU     2     ;state of emulation ready 
MX_ACCVIO       EQU     3     ;access violation occurred

* Equates for MON_LASTENTRY (vector numbers)
ML_UNDEFINED    EQU     0    
ML_RESET        EQU     1     ;emulation/target reset
ML_BREAKPOINT   EQU     4     ;breakpoint exception
ML_TRACE        EQU     9     ;trace exception
ML_INTERRUPT    EQU     31    ;interrupt exception

* Equates for MEM_SIZE
MS_BYTES        EQU     0
MS_WORDS        EQU     1
MS_LONGS        EQU     2

* Equates for REG_MASK (bit positions)
RM_FP0          EQU     0     ;fpu registers
RM_FP1          EQU     1
RM_FP2          EQU     2
RM_FP3          EQU     3
RM_FP4          EQU     4
RM_FP5          EQU     5
RM_FP6          EQU     6
RM_FP7          EQU     7
RM_FPIAR        EQU     10
RM_FPSR         EQU     11
RM_FPCR         EQU     12

RM_DTT0         EQU     0     ;mmu registers
RM_DTT1         EQU     1
RM_ITT0         EQU     2
RM_ITT1         EQU     3
RM_TC           EQU     4
RM_SRP          EQU     5
RM_URP          EQU     6
RM_MMUSR        EQU     7


********************************************************************************
****************  M O N I T O R   P R O G   S E C T I O N  *********************
********************************************************************************
MONPROG
********************************************************************************
* Monitor entry point for a trace exception.  Since there is no unique hardware
* event for the emulator to detect the start of trace exception processing, the
* emulator requires that the user's trace vector point to this address.
********************************************************************************
TRACE_ENTRY
	MOVE.L  A5,-(A7)               save user's A5 on the stack
	MOVE.W  #$2024,MVO             save entry point (stack format word)
	BRA     CHECK_MONSTATE

********************************************************************************
* Monitor entry point for reset into monitor.  When the processor initiates
* reset exception processing, the emulator transitions the monitor state
* machine into the foreground control state and "jams" this address onto the
* data bus during the reset vector fetch.   If a target reset occurs while the
* monitor is running, the monitor aborts any command in process and returns to
* the monitor idle loop.
********************************************************************************
RESET_ENTRY
	MOVE.B  #ML_RESET,MON_LASTENTRY     save entry point
	MOVE.B  #CR_RESET,CMD_RESULT        abort command
	BRA     CHECK_MONSTATE

********************************************************************************
* Monitor entry point for software breakpoints.  When the emulator detects a
* breakpoint acknowledge cycle, it "jams" this address onto the data bus when
* the processor fetches the illegal instruction vector.  Both caches and all
* interrupts are also disabled at this time.  A format $0 stack frame is
* written to memory.  To guarantee cache coherency in cache copyback mode,
* dirty cache lines must be written to memory.
*
* Because the emulator hardware cannot detect certain entry points, such as
* trace and user exception, the monitor may set the MC_BKPTREENTRY flag and
* execute a breakpoint instruction to force the hardware into the protected
* state with caches and interrupts disabled.  If this flag is set on entry,
* this routine returns directly to BKPTREENTRY in CHECK_MONSTATE.
********************************************************************************
BREAKPOINT_ENTRY
	BTST    #MC_BKPTREENTRY,MON_CONTROL
	BNE     BKPTREENTRY

	MOVE.L  A5,-(A7)              save user's A5 on stack
	MOVE.W  #$0010,MVO            save entry point (stack format word)
	BRA     STACK_COPYBACK        

********************************************************************************
* Monitor entry point for level 7 interrupt.  During the interrupt acknowledge
* bus cycle, the emulation hardware transitions the monitor state machine into
* the foreground control state (interrupts and caches disabled) and "jams" the
* address of this routine onto the data bus during the vector fetch.  A format
* $0 stack frame is written to memory.  A format $1 throwaway stack is written
* to memory if the interrupt stack was not active at the time of the interrupt.
* To guarantee cache coherency in cache copyback mode, dirty cache lines must
* be written to memory. 
********************************************************************************
INTERRUPT_ENTRY
	MOVE.L  A5,-(A7)              save user's A5 on stack
	MOVE.W  #$007C,MVO            save entry point (stack format word)
	BRA     STACK_COPYBACK

********************************************************************************
* Exception handler for exceptions generated during monitor commands.  During
* monitor command execution, all target interrupts are blocked and VBR points
* to the monitor's vector table.  This entry point can also be used to trap
* exceptions generated during target execution if VBR points to the base
* address of the monitor or individual vectors point to this address.
********************************************************************************
ERROR_ENTRY
	MOVE.L  A5,-(A7)               save user's A5 on the stack
	MOVE.W  10(A7),MVO             save entry point (stack format word)
	ORI.W   #1,MVO                 prevents removal of user's stack frame
	BRA     CHECK_MONSTATE

********************************************************************************
* At this point, the caches are disabled in hardware.  To guarantee cache 
* coherency in cache copyback mode, dirty cache lines must be written to
* memory.  Since dirty cache lines can potentially overwrite monitor entry
* stack frames in memory, the stacked data is copied to a monitor buffer
* before executing the CPUSH instruction.
********************************************************************************
STACK_COPYBACK
	MOVEC   CACR,A5
	TST.L   A5
	BPL     CHECK_REENTRY         data cache not enabled

	LEA     MONSTACK-20,A5        copy stacked data to monitor buffer
	MOVE.L  (A7)+,(A5)+
	MOVE.L  (A7)+,(A5)+
	MOVE.L  (A7)+,(A5)+
	BFTST   -2(A7){0:4}
	BEQ.B   CPUSHDATA             not throwaway frame
	ORI.W   #$1000,SR
	MOVE.L  (A7)+,(A5)+
	MOVE.L  (A7)+,(A5)+
	CPUSHA  DC                    write dirty cache lines to memory
	MOVE.L  -(A5),-(A7)
	MOVE.L  -(A5),-(A7)
	ANDI.W   #"$1000,SR
	BRA.B   CPUSHDONE
CPUSHDATA
	CPUSHA  DC                    write dirty cache lines to memory
CPUSHDONE
	MOVE.L  -(A5),-(A7)
	MOVE.L  -(A5),-(A7)
	MOVE.L  -(A5),-(A7)
	BRA     CHECK_REENTRY

********************************************************************************
* Check monitor state machine and transition hardware into protected monitor
* state with interrupts and caches disabled as necessary.  Normally, the
* hardware changes state automatically when the it "jams" vectors during
* exception processing.  Certain transitions into the monitor, such as trace
* and user exception, are not "jammed" and do not automatically transition
* the monitor state machine.  To force this transition, the monitor executes
* a breakpoint instruction with the MC_BKPTREENTRY flag set.  The breakpoint
* entry routine checks this flag and returns to BKPTREENTRY if set.
********************************************************************************
CHECK_MONSTATE
	BTST    #MX_EMRDY,MON_XLX        query hardware state machine
	BEQ.B   CHECK_REENTRY

	BSET    #MC_BKPTREENTRY,MON_CONTROL  force hardware nto protected state
	BKPT    #7                       with caches and interrupts disabled

BKPTREENTRY
	ADDQ.L  #8,A7                    pop 4 word stack frame
	BCLR    #MC_BKPTREENTRY,MON_CONTROL
	MOVEC   CACR,A5                  if user enabled cache, force cache
	TST.L   A5                       coherency for cache copyback mode
	BPL.B   CHECK_REENTRY            since we did not do STACK_COPYBACK
	CPUSHA  DC

	** fall through **

********************************************************************************
* Check for monitor reentry.  Monitor reentry is determined by comparing the PC
* in the exception stack frame against the address range of the monitor.  If the
* PC is outside the monitor, all user registers are saved and the exception
* stack frame is removed.  Otherwise, it is assumed that the exception was
* caused by monitor command execution and does not affect user registers.  The
* only exception occurs when an access violation occurs in conjunction with a
* single step.  Trace exception processing is immediately followed by interrupt
* processing.  If the interrupt stack frame ever contains the address of the
* monitor TRACE_ENTRY, the interrupt stack is removed and the trace exception
* is processed normally.
********************************************************************************
CHECK_REENTRY
	CMPI.B  #CR_RESET,CMD_RESULT
	BEQ     MON_MAIN 
	MOVE.L  6(A7),A5
	CMP2.L  MON_RANGE,A5             check for monitor reentry
	BCS     USER_ENTRY

	LEA     TRACE_ENTRY,A5           check for access violation interrupt
	CMP.L   6(A7),A5                 after a successful single step
	MOVE.L  (A7)+,A5                 remove stacked A5
	BNE.B   MON_EXCEPTION
	RTE

********************************************************************************
***********************  M O N I T O R   E X C E P T I O N  ********************
********************************************************************************

********************************************************************************
* Exception handler for exceptions generated during monitor command execution.
* The monitor attempts to recover from certain access faults during memory
* read or write commands.  All other exceptions abort the command in process.
********************************************************************************
MON_EXCEPTION
	MOVEM.L D0-D2/A0,TMP2         save working registers

	BFEXTU  MVO{0:4},D0
	CMPI.B  #7,D0
	BNE     MON_ERROR             not format $7 access fault

	MOVE.W  12(A7),D0             read special status word
	BTST    #10,D0
	BEQ     MON_ERROR             target bus error (ssw ATC bit)

	MOVEC   D0,DFC                ATC fault - ptest fault address
	MOVE.L  20(A7),A0
	MOVEC   MMUSR,D2
	PTESTR  (A0)
	MOVEC   MMUSR,D1
	MOVEC   D2,MMUSR

	BTST    #11,D1
	BNE     MON_ERROR             target bus error (mmusr B bit)

********************************************************************************
* If the access fault resulted from a nonresident page, the monitor aborts the
* access and returns an error.  If customized, the monitor can be configured to
* invoke the target system's access fault handler at this point to swap in the
* correct page.
********************************************************************************
NONRESIDENT
	BTST    #0,D1
	BNE     TRANSPARENT           resident page (mmusr R bit)

********************************************************************************
* USER MODIFIABLE CODE - SWAPPING IN NONRESIDENT PAGES
*   Uncomment the following lines if you want the monitor to call the target
*   system's access fault handler to swap-in nonresident pages.  The monitor
*   copies all its registers and the access error stack frame to the user's
*   interrupt stack, restores all user registers, exits the monitor control
*   state and jumps to directly to the target system's access fault handler.
*   Regardless whether the nonresident page is swapped-in, the target system's
*   access fault handler must return to the monitor via RTE.  Upon return, the
*   monitor either retries the original memory access if the page was swapped-
*   in or aborts the memory access if not.
********************************************************************************
*	MOVE.L  A7,TMP1                save all monitor registers, except stack
*	MOVE.L  MISP,A7                pointer, on user's interrupt stack
*	MOVEM.L D0-D7/A0-A6,-(A7)
*
*	MOVE.L  #29,D0                 copy 30 word access error stack frame
*	LEA     ([TMP1,PC],60),A0      from monitor's stack to user's stack
*SFCOPY	MOVE.W  -(A0),-(A7)
*	DBF     D0,SFCOPY
*	LEA     USER_RETURN,A0         set PC in user's stack frame so that
*	MOVE.L  A0,2(A7)               control returns here after user's RTE
*
*	MOVE.L  MVBR,D0                restore most registers in case they are
*	MOVEC   D0,VBR                 needed by user's access fault handler
*	MOVE.L  MCACR,D0
*	MOVEC   D0,CACR
*	MOVEM.L MREGS,D0-D7/A0-A6
*	TST.L   MON_MOP             DO NOT MODIFY - exit fg ctrl state
*	
*	MOVE.L  ([MVBR,PC],8),A0       call user's access fault handler
*	JMP     (A0)
*	
*USER_RETURN
*	NOP                            return to a few NOPs just in case fault
*	NOP                            handler decides not to retry the access
*	NOP                            and increments PC past the instruction
*	PFLUSHA
*	MOVEC   CACR,D0                disable caches in software and force
*	BCLR    #31,D0                 cache coherency before transition to
*	BEQ.B   CDIS                   foreground control state (disables
*	MOVEC   D0,CACR                caches and interrupts in hardware)
*	CPUSHA  DC
*CDIS	TST.L   MON_MOP                DO NOT MODIFY - enter fg ctrl state
*	MOVEM.L (A7)+,D0-D7/A0-A6      restore monitor's registers
*	MOVE.L  TMP1,A7
*	LEA     MONDATA,A5
*	MOVEC   A5,VBR                
********************************************************************************
	BRA     MON_RETRY

********************************************************************************
* If TTR hit, the access fault could have only resulted from a write protection
* violation.  If this happens during CC_MEMWRITE command, the monitor attempts
* to recover from this error by clearing the write protect bit in each data TTR
* and returning from exception.  Modified registers are restored upon completion
* of the memory access.
********************************************************************************
TRANSPARENT
	BTST    #1,D1
	BEQ.B   SPROTECTED            not transparent (mmusr T bit)
	CMPI.B  #CC_MEMWRITE,CMD_CONTROL
	BNE     MON_ERROR             not CC_MEMWRITE

WPROTECT_DTT0
	MOVEC   DTT0,D2
	BCLR    #2,D2
	BEQ.B   WPROTECT_DTT1         not write protected
	MOVEC   D2,DTT0               clear write protect bit
	BSET    #RM_DTT0,REG_MASK+1
WPROTECT_DTT1
	MOVEC   DTT1,D2
	BCLR    #2,D2
	BEQ     MON_RETRY             not write protected
	MOVEC   D2,DTT1               clear write protect bit
	BSET    #RM_DTT1,REG_MASK+1
	BRA     MON_RETRY

********************************************************************************
* If the access fault resulted from a user access to a supervisor protected
* page, the monitor aborts the memory access and returns an error.
********************************************************************************
SPROTECTED
	BTST    #7,D1
	BEQ.B   WPROTECTED            not protected
	BTST    #2,D0
	BNE.B   WPROTECTED            not user address space
	BRA     MON_ERROR             supervisor violation

********************************************************************************
* If the access fault resulted from a write access to write protected page,
* the monitor attempts to recover by clearing the write protect bit(s) in the
* user's translation tables and returning from exception.  Each descriptor at
* levels A-C/IND is checked for write protection.  These bits are restored
* after the memory access completes.
********************************************************************************
WPROTECTED
	BTST    #2,D1
	BEQ     MON_ERROR             not protected (mmusr W bit)
	CMPI.B  #CC_MEMWRITE,CMD_CONTROL
	BNE     MON_ERROR             not CC_MEMWRITE

	MOVEC   TC,D1                 disable mmu to access tables
	BCLR    #15,D1
	MOVEC   D1,TC
	MOVE.L  A0,D1                 save logical fault address
	BSET    #RM_MMUSR,REG_MASK+1  flags we modified translation tables

	LEA     TMP3,A5               TMP3=address(es) of modified descriptors
	MOVEC   URP,D2
	BTST    #2,D0                 
	BEQ.B   LEVELA                not supervisor (ssw TM2 bit)
	MOVEC   SRP,D2
LEVELA
	ANDI.L  #$FFFFFE00,D2
	MOVE.L  D2,A0                 A0=base address of table
	BFEXTU  D1{0:7},D2            D2=table index fa[31:25]
	LEA     (A0,D2*4),A0          A0=descriptor address
	MOVE.L  (A0),D2               read descriptor 
	BCLR    #2,D2
	BEQ.B   LEVELB
	MOVE.L  D2,(A0)               write descriptor w/o write protect
	MOVE.L  A0,(A5)+              save descriptor address
LEVELB
	ANDI.L  #$FFFFFE00,D2
	MOVE.L  D2,A0                 A0=base address of table
	BFEXTU  D1{7:7},D2            D2=table index fa[24:18]
	LEA     (A0,D2*4),A0          A0=descriptor address
	MOVE.L  (A0),D2               read descriptor 
	BCLR    #2,D2
	BEQ.B   LEVELC
	MOVE.L  D2,(A0)               write descriptor w/o write protect
	MOVE.L  A0,(A5)+              save descriptor address
LEVELC
	MOVEC   TC,D0
	BTST    #14,D0
	BEQ.B   PAGE4K
	ANDI.L  #$FFFFFE00,D2
	MOVE.L  D2,A0                 A0=base address of table
	BFEXTU  D1{14:5},D2           D2=table index fa[17:13]
	BRA.B   PAGE8K
PAGE4K
	AND.L   #$FFFFFF00,D2
	MOVE.L  D2,A0                 A0=base address of table
	BFEXTU  D1{14:6},D2           D2=table index fa[17:12]
PAGE8K
	LEA     (A0,D2*4),A0          A0=descriptor address
	MOVE.L  (A0),D2               read descriptor
	BTST    #0,D2
	BNE.B   NOTINDIRECT           not indirect (PDT == x1)
	ANDI.L  #$FFFFFFFC,D2
	MOVE.L  D2,A0
	MOVE.L  (A0),D2               read indirect descriptor
NOTINDIRECT
	BCLR    #2,D2
	BEQ.B   LEVELNONE
	MOVE.L  D2,(A0)               write descriptor w/o write protect
	MOVE.L  A0,(A5)+              save descriptor address

LEVELNONE
	MOVE.L  #$FFFFFFFF,(A5)       terminate list with address -1
	MOVE.L  D1,A0

	MOVEC   TC,D2                 enable mmu
	BSET    #15,D2
	MOVEC   D2,TC

********************************************************************************
* Recover from access fault exception.  Retest the fault address to invalidate
* the current ATC entry and to verify the original access fault does not occur.
* Restore temporary registers and return from the exception.
********************************************************************************
MON_RETRY
	MOVEC   MMUSR,D2
	PTESTR  (A0)                  
	MOVEC   MMUSR,D1
	MOVEC   D2,MMUSR
	BTST    #0,D1
	BEQ     MON_ERROR             nonresident page
	BTST    #2,D1
	BEQ.B   RETRY_RTE             page not write protected
	TST.W   REG_MASK         
	BNE     MON_ERROR             already tried to remove write protection
	
RETRY_RTE
	MOVEM.L TMP2,D0-D2/A0
	RTE	

********************************************************************************
* Unrecoverable exception during monitor command execution.  Copy the exception
* stack frame to the start of the monitor transfer buffer for processing by the
* emulation drivers and abort abort the command in process by returning the
* exception vector number. When aborting a memory read/write command, execution
* resumes at RDWR_EPILOG in case the monitor needs to restored modified MMU
* registers and/or descriptors.
********************************************************************************
MON_ERROR
	BFEXTU  MVO{6:8},D0               use vector number as error code; if 
	MOVE.B  D0,CMD_RESULT             no command is in process, save value
	TST.B   CMD_HANDSHAKE             to lastentry to force async message
	BNE.B   COPYSTACK                 
	MOVE.B  D0,MON_LASTENTRY
COPYSTACK
	LEA     MONTRANS,A0               copy exception stack frame to the
	BFEXTU  MVO{0:4},D0               start of the monitor transfer buffer
	MOVE.W  (FRAMESIZE,PC,D0*2),D0    for processing by the drivers
	LSR.W   #2,D0
	SUBQ    #1,D0                    
COPYLOOP
	MOVE.L  (A7)+,(A0)+
	DBF     D0,COPYLOOP

	CMPI.B  #CC_MEMREAD,CMD_CONTROL
	BEQ     RDWR_EPILOG
	CMPI.B  #CC_MEMWRITE,CMD_CONTROL
	BEQ     RDWR_EPILOG
	BRA     MON_MAIN

********************************************************************************
**************  E N T R Y   F R O M   U  S E R   P R O G R A M   ***************
********************************************************************************

********************************************************************************
* Save all user registers and process and remove the exception stack frame.
********************************************************************************
USER_ENTRY
	MOVEM.L D0-D7/A0-A6,MREGS
	MOVE.L  (A7)+,MA5
	MOVE.L  USP,A0
	MOVE.L  A0,MUSP
	MOVEC   VBR,A0
	MOVE.L  A0,MVBR
	MOVEC   CACR,A0
	MOVE.L  A0,MCACR
	MOVEC   SFC,A0
	MOVE.L  A0,MSFC
	MOVEC   DFC,A0 
	MOVE.L  A0,MDFC

	BFEXTU  MVO{6:8},D0              set entry point to vector number
	MOVE.B  D0,MON_LASTENTRY

	BFEXTU  6(A7){0:4},D0            if stack frame format word indicates
	CMPI.B  #1,D0                    stack frame is format $1 throwaway
	BNE.B   NOT_THROWAWAY            frame, pop and discard the stack frame
	ADDA.W  (FRAMESIZE,PC,D0*2),A7   and switch over to user's master stack
	ORI.W   #$1000,SR
	BFEXTU  6(A7){0:4},D0

NOT_THROWAWAY
	MOVEQ   #0,D1                    set D1 to size of stack frame to be
	MOVE.W  6(A7),D2                 removed from the user's stack;  this
	EOR.W   D2,MVO                   value is zero if the stack frame
	BNE.B   SAVE_STACKFRAME          format word does not match the entry
	MOVE.W  (FRAMESIZE,PC,D0*2),D1   point indicated frame is to be saved

SAVE_STACKFRAME
	MOVE.W  (A7),MSR                 read first 4 words common to all stack
	MOVE.L  2(A7),MPC                frames and save user's PC, SR, and VO
	MOVE.W  6(A7),MVO

	ADDA.L  D1,A7                    adjust user's stack pointer and
	MOVEC   MSP,A0                   save MSP and ISP values
	MOVE.L  A0,MMSP
	MOVEC   ISP,A0
	MOVE.L  A0,MISP

********************************************************************************
* When tracing an instruction, make sure the T0/T1 status bits are not left on
* the stack.  When tracing an instruction that causes an exception (ie: TRAP,
* CHK, ALINE), the T0/T1 status bits must be cleared in the user's exception
* stack frame.  This prevents an unexpected step break from occurring if a run
* is issued before the return from exception.
********************************************************************************
	BTST    #MC_TRACEMODE,MON_CONTROL 
	BEQ.B   MON_MAIN                 not tracing

	TST.B   D1
	BEQ.B   CLEAR_TBITS              stack frame not removed
	BFTST   MSR{0:2}         
	BEQ.B   CLEAR_TBITS              removed stack frame did not have T0/T1
	BRA.B   MON_MAIN

CLEAR_TBITS
	CMPA.L  MA7,A7                   double check that a new stack frame
	BGT.B   MON_MAIN                 exists on the stack since last exit
	BFCLR   (A7){0:2}                then unconditionally clear T0/T1

	* fall through to MON_MAIN *

********************************************************************************
********************   M O N I T O R   I D L E   L O O P   *********************
********************************************************************************

********************************************************************************
* During the monitor idle loop, the monitor can be interrupted by the target
* system.  The interrupt priority level (IPL) is set to the value defined in
* configuration or the user's IPL in effect upon monitor entry, whichever is
* greater.  Most user registers are restored while running in the idle loop.
* When a command is requested, the monitor transitions into a control state
* with interrupts and caches disabled.  The monitor uses its own vector table
* and stack to trap any exceptions generated during command execution.
********************************************************************************
MON_MAIN
	CLR.B   CMD_HANDSHAKE          flag command completion

	MOVE.W  SR,D0                  select interrupt stack and IPL
	BCLR    #12,D0
	BFEXTU  MSR{5:3},D1
	CMP.B   MON_INTRLEVEL,D1
	BGE.B   USE_PRIOR
	MOVE.B  MON_INTRLEVEL,D1
USE_PRIOR
	BFINS   D1,D0{21:3}
	MOVE.W  D0,SR

	MOVE.L  MVBR,D0                restore all user registers before
	MOVEC   D0,VBR                 enterinig idle loop because they
	MOVE.L  MCACR,D0               may be needed by target interrupt
	MOVEC   D0,CACR                exception handler
	MOVE.L  MSFC,D0                            
	MOVEC   D0,SFC
	MOVE.L  MDFC,D0
	MOVEC   D0,DFC
  	MOVE.L  MUSP,D0
	MOVEC   D0,USP
	MOVE.L  MMSP,D0
	MOVEC   D0,MSP
	MOVE.L  MISP,D0
	MOVEC   D0,ISP
	MOVEM.L MREGS,D0-D7/A0-A6

	BSET    #MC_IDLE,MON_CONTROL   DO NOT MODIFY - flag idle loop entry
	TST.L   MON_MOP                DO NOT MODIFY - exit fg ctrl state

MON_LOOP
************************************************************************
* USER MODIFIABLE CODE - 
*   If the target system requires that a watchdog timer be reset on a
*   regular basis, code can be added here to access a particular address
*   or to call a target system subroutine.  Since the foreground monitor
*   is interruptable, target systems which reset watchdog timers from
*   an interrupt handler may require no changes.  However, the monitor
*   interrupt priority configuration question and the interrupt priority
*   mask in the SR must be set appropriately on monitor entry.
************************************************************************
	TST.B   CMD_HANDSHAKE          check for command request
	BEQ.B   MON_LOOP

	MOVEC   CACR,D0                transition to foreground control state
	BCLR    #31,D0                 with interrupts/caches disabled
	BEQ.B   DC_DISABLED
	MOVEC   D0,CACR
	CPUSHA  DC
DC_DISABLED
	TST.L   MON_MOP                DO NOT MODIFY - enter fg ctrl state
	BCLR    #MC_IDLE,MON_CONTROL   DO NOT MODIFY - flag idle loop exit
	LEA     MONSTACK,A7
	LEA     MONDATA,A5
	MOVEC   A5,VBR                
	CINVA   IC                     flush instruction cache
	PFLUSHA                        flush address translation cache 

	MOVEQ   #0,D0                  execute command
	MOVE.B  CMD_CONTROL,D0
	CMPI.W  #(CMD_TABLE_END-CMD_TABLE)/2,D0
	BPL.B   BADREQUEST
	MOVE.B  #CR_SUCCESS,CMD_RESULT
	MOVE.W  (CMD_TABLE,PC,D0.W*2),D1
	JMP     (CMD_TABLE,PC,D1.W)

CMD_TABLE
	DC.W    YO_MONITOR-CMD_TABLE      command 0 - are you there?
	DC.W    EXIT_MONITOR-CMD_TABLE    command 1 - exit monitor
	DC.W    READ_MEMORY-CMD_TABLE     command 2 - read memory
	DC.W    WRITE_MEMORY-CMD_TABLE    command 3 - write memory
	DC.W    READ_FPUREGS-CMD_TABLE    command 4 - read fpu registers
	DC.W    WRITE_FPUREGS-CMD_TABLE   command 5 - write fpu registers
	DC.W    READ_MMUREGS-CMD_TABLE    command 6 - read mmu registers
	DC.W    WRITE_MMUREGS-CMD_TABLE   command 7 - write mmu registers
	DC.W    MMU_TRANSLATE-CMD_TABLE   command 8 - translate address
CMD_TABLE_END

********************************************************************************
**************   I N V A L I D   C O M M A N D   I N D E X   *******************
********************************************************************************
BADREQUEST
	MOVE.B  #CR_BADREQUEST,CMD_RESULT
	BRA     MON_MAIN

********************************************************************************
*****************   S O F T W A R E   H A N D S H A K E   **********************
********************************************************************************
YO_MONITOR
	BRA     MON_MAIN

********************************************************************************
***********************   E X I T   M O N I T O R   ****************************
********************************************************************************

********************************************************************************
* Push exception stack frame on user's master and/or interrupt stacks, restore
* all registers, wait for coordinated start (if active), and exit via an RTE.
* A format $0 frame is pushed on the interrupt stack if the M (master) bit is
* clear in the user's SR.  Otherwise a format $1 throwaway frame is pushed on
* the interrupt stack and the format $0 frame is pushed on the master stack.
* The exit is aborted if a memory access violation occurs or either stack is
* not located in read/write memory.
********************************************************************************
EXIT_MONITOR
	LEA     ([MISP,PC],-8),A0      prepare to push a format $0 or $1 frame
	MOVE.W  MSR,D0                 on the user's interrupt stack
	MOVE.L  MPC,D1
	BTST    #12,D0
	BEQ.B   WRITE_FMT0
WRITE_FMT1
	ORI.W   #$2000,D0              push format $1 throwaway stack frame
	MOVE.W  #$107C,D2              on interrupt stack with supervisor bit
	BSR     WRITE_STACKFRAME       then switch to master stack and restore
	LEA     ([MMSP,PC],-8),A0      original value of supervisor bit
	MOVE.W  MSR,D0                 on the user's interrupt stack
WRITE_FMT0
	MOVE.W  #$007C,D2              push format $0 stack frame on either
	BSR     WRITE_STACKFRAME       interrupt or master stack

	MOVE.L  MVBR,D0                restore all user registers before
	MOVEC   D0,VBR                 entering cmb wiat loop because they
	MOVE.L  MCACR,D0               may be needed by target interrupt
	MOVEC   D0,CACR                exception handler
	MOVE.L  MSFC,D0                            
	MOVEC   D0,SFC
	MOVE.L  MDFC,D0
	MOVEC   D0,DFC
  	MOVE.L  MUSP,D0
	MOVEC   D0,USP
	MOVE.L  MMSP,D0
	BTST	#4,MSR                 If the M bit is set, decrement MSP for
	BEQ.B  	NO_MASTERFRAME         for the format $0 frame placed on the
	SUBQ    #8,D0                  master stack
NO_MASTERFRAME
	MOVEC   D0,MSP
	LEA     ([MISP,PC],-8),A7      
	MOVEM.L MREGS,D0-D7/A0-A6
	CLR.B   CMD_HANDSHAKE          flag command completion

********************************************************************************
* Wait for coordinated measurement start (if active).  The CMB_READY flag true
* indicates that it is okay to continue exiting the monitor.  If the CMB_BREAK
* flag true occurs before CMB_READY, the exit is aborted and the monitor returns
* to the main idle loop.  Because the monitor can be interrupted during this
* wait loop, all registers user must be restored.
********************************************************************************
	TST.B   MON_FGTRAN             assert emulation ready (ERY)
CMB_WAIT_LOOP
	BTST    #MX_CMBRDY_L,MON_XLX
	BEQ     BG_EXIT_RTE            cmb ready - continue exit

	BSET 	#MC_CMBWAIT,MON_CONTROL   flag cmb wait for drivers
	BTST    #MX_CMBBRK_L,MON_XLX
	BNE.B   CMB_WAIT_LOOP          not CMB break - continue wait
CMB_BREAK
	TST.B   MON_FGTRAN             deaasert emulation ready (ERY)
	BRA     MON_MAIN

********************************************************************************
* Create a 4-word stack frame on the user's stack.  A0 must point to the user's
* stack (predecremented) and D0/D1/D2 must contain SR/PC/VO values respectively.
* This routine verifies all write accesses and aborts if it detects unresponsive
* memory or other access violation (grd/wrrom/hung bus cycle).
********************************************************************************
WRITE_STACKFRAME
	MOVE.L  A0,MA7                 save stack pointer for errors/reentry

	MOVE.W  D0,(A0)                create stack frame on user's stack
	MOVE.L  D1,2(A0)
	MOVE.W  D2,6(A0)
	BTST  	#MX_ACCVIO,MON_XLX
	BNE.B   STACK_PROBLEMS         access violation (grd/wrrom/hung)
	CMP.W   (A0),D0
	BNE.B   STACK_PROBLEMS         read != write
	CMP.L   2(A0),D1
	BNE.B   STACK_PROBLEMS         read != write
	CMP.W   6(A0),D2
	BNE.B   STACK_PROBLEMS         read != write
	RTS

STACK_PROBLEMS
	MOVE.B  #CR_ACCVIO,CMD_RESULT
	BRA     MON_MAIN

********************************************************************************
******************   R E A D / W R I T E   M E M O R Y   ***********************
********************************************************************************

********************************************************************************
* Copy data from target memory or non-dual ported emulation memory into the
* monitor transfer buffer
********************************************************************************
READ_MEMORY
	LEA     (RD_JUMPTABLE,PC),A2
	BRA.B   RDWR_MEMORY

RD_JUMPTABLE
	DC.W    RD_BYTE-RD_JUMPTABLE
	DC.W    RD_WORD-RD_JUMPTABLE
	DC.W    RD_LONG-RD_JUMPTABLE

RD_BYTE
	MOVES.B (A0)+,D0
	MOVE.B  D0,(A1)+
	BRA     RDWR_CHECK
RD_WORD
	MOVES.W (A0)+,D0
	MOVE.W  D0,(A1)+
	BRA     RDWR_CHECK
RD_LONG
	MOVES.L (A0)+,D0
	MOVE.L  D0,(A1)+
	BRA     RDWR_CHECK

********************************************************************************
* Copy data from the monitor transfer buffer to target memory or non-dual
* ported emulation memory.
********************************************************************************
WRITE_MEMORY
	LEA     (WR_JUMPTABLE,PC),A2
	BRA.B   RDWR_MEMORY

WR_JUMPTABLE
	DC.W 	WR_BYTE-WR_JUMPTABLE
	DC.W    WR_WORD-WR_JUMPTABLE
	DC.W    WR_LONG-WR_JUMPTABLE

WR_BYTE
	MOVE.B  (A1)+,D0
	MOVES.B D0,(A0)+
	BRA     RDWR_CHECK
WR_WORD
	MOVE.W  (A1)+,D0
	MOVES.W D0,(A0)+
	BRA     RDWR_CHECK
WR_LONG
	MOVE.L  (A1)+,D0
	MOVES.L D0,(A0)+
	BRA     RDWR_CHECK

********************************************************************************
RDWR_MEMORY
	MOVEA.L MEM_ADDR,A0           A0=target address
	LEA     MONTRANS,A1           A1=monitor transfer buffer
	MOVE.W  MEM_BYTES,D2          D2=number of bytes
	MOVE.W  MEM_SIZE,D3           D3=access size
	MOVE.B  MEM_FCS,D4            D4=function code
	MOVEC   D4,SFC                SFC=function code
	MOVEC   D4,DFC                DFC=function code

	CLR.W   REG_MASK              assume no mmu changes

	BCLR    #3,D4                 if physical access requested and MMU
	BEQ.B   REALIGN               is currently enabled, temporarily
	MOVEC   TC,D0                 disable the MMU for the duration of
	BCLR    #15,D0                of the access
	BEQ.B   REALIGN
	MOVEC   D0,TC
	BSET    #RM_TC,REG_MASK+1

REALIGN
	MOVE.W  D3,D4                 start with requested access size
CHECKALIGN
	MOVE.L  A0,D5                 check alignment - word or long accesses
	LSR.L   D4,D5                 must start on word or long boundary
	LSL.L   D4,D5                 respectively
	CMP.L   A0,D5
	BEQ.B   ALIGNED
MISALIGNED
	SUBQ    #1,D4                    use next smaller access size
	BRA.B   CHECKALIGN

ALIGNED
	MOVE.W  D2,D1                    set D1 to loop count
	LSR.W   D4,D1
	BEQ.B   MISALIGNED               insufficient bytes for access size
	CMP.W   D3,D4
	BEQ.B   WASALIGNED
	MOVEQ   #1,D1                    set loop count=1 if forcing alignment
WASALIGNED
	MOVE    D1,D5
	SUBQ    #1,D1
	MOVE.W  (0,A2,D4.W*2),D6         select correct access routine
	LEA     (0,A2,D6.W),A3

RDWR_LOOP
	JMP     (A3)
RDWR_CHECK
	BTST    #MX_ACCVIO,MON_XLX       check for guarded/wrrom access
	DBNE    D1,RDWR_LOOP
	BNE.B   RDWR_ERROR

	LSL.W   D4,D5                 reduce total byte count
	SUB.W   D5,D2
	BEQ.B   RDWR_EPILOG
	CMP.W   D4,D2                 use original access size iff reduced to
	BGE.B   REALIGN               * force alignment, otherwise use smaller
	BRA.B   MISALIGNED            * access size to output remaining bytes

RDWR_ERROR
	MOVE.B  #CR_ACCVIO,CMD_RESULT

********************************************************************************
* Restore MMU registers/table entires if modified to perform access
********************************************************************************
RDWR_EPILOG
	MOVE.W  REG_MASK,D0
	BEQ     MON_MAIN              no funny stuff

********************************************************************************
* If RM_TC bit is set, the monitor temporarily cleared the enable bit in the
* user's TC register to perform a physical memory access.  Restore it.
********************************************************************************
TC_E_BIT
	BTST    #RM_TC,D0
	BEQ.B   DTT0_W_BIT
TC_ENABLE
	MOVEC   TC,D1
	BSET    #15,D1
	MOVEC   D1,TC
	BRA     MON_MAIN

********************************************************************************
* If RM_DTT0 bit is set, the monitor temporarily cleared the write protect bit
* in the user's DTT0 register during a memory write access.  Restore it.
********************************************************************************
DTT0_W_BIT
	BTST    #RM_DTT0,D0
	BEQ.B   DTT1_W_BIT

	MOVEC   DTT0,D1
	BSET    #2,D1
	MOVEC   D1,DTT0

********************************************************************************
* If RM_DTT1 bit is set, the monitor temporarily cleared the write protect bit
* in the user's DTT1 register during a memory write access.  Restore it.
********************************************************************************
DTT1_W_BIT
	BTST    #RM_DTT1,D0
	BEQ.B   DESC_W_BIT

	MOVEC   DTT1,D1
	BSET    #2,D1
	MOVEC   D1,DTT1

********************************************************************************
* If RM_MMUSR bit set, the monitor temporarily cleared the write protect bit
* in one or more translation table descriptors located in memory.  Buffer TMP3
* contains a list of descriptor address(es) which need to be restored.
********************************************************************************
DESC_W_BIT
	BTST    #RM_MMUSR,D0
	BEQ     MON_MAIN              

	LEA     TMP3,A0              address(es) of modified descriptors
	MOVEC   TC,D1                turn off mmu to access tables
	BCLR    #15,D1
	MOVEC   D1,TC
DESC_LOOP                
	MOVE.L  (A0)+,A1
	CMPA    #$FFFFFFFF,A1        address -1 terminates list
	BEQ.B   TC_ENABLE
	BSET    #2,3(A1)
	BRA.B   DESC_LOOP


********************************************************************************
************   R E A D / W R I T E   F P U   R E G I S T E R S   ***************
********************************************************************************

********************************************************************************
* Monitor command to read selected FPU registers.  Registers are selected with
* REG_MASK.  Register values are always stored in the monitor transfer buffer
* in the same relative order:  FPCR,FPSR,FPIAR,FP0-FP7
********************************************************************************
READ_FPUREGS
	FSAVE     -(A7)
	MOVE.W    REG_MASK,D0
	LEA       MONTRANS,A1
	ADDA.W    MEM_BYTES,A1
RD_FPDATA
	BFTST     D0{24:8}
	BEQ.B     RD_FPIAR
	FMOVEM.X  D0,-(A1)
RD_FPIAR
	BTST      #RM_FPIAR,D0
	BEQ.B     RD_FPSR
	FMOVE.L   FPIAR,-(A1)
RD_FPSR
	BTST      #RM_FPSR,D0
	BEQ.B     RD_FPCR
	FMOVE.L   FPSR,-(A1)
RD_FPCR
	BTST      #RM_FPCR,D0
	BEQ.B     RD_RESTORE
	FMOVE.L   FPCR,-(A1)
RD_RESTORE
	TST.B     (A7)                 ;do not restore NULL state frame since
	BEQ.B     RD_FPDONE            ;it effectively resets the FPCP
	FRESTORE  (A7)+
RD_FPDONE
	BRA       MON_MAIN

********************************************************************************
* Monitor command to write selected FPU registers.  Registers are selected with
* REG_MASK.  Register values are always stored in the monitor transfer buffer
* in the same relative order:  FPCR,FPSR,FPIAR,FP0-FP7
********************************************************************************
WRITE_FPUREGS
	FSAVE     -(A7)
	MOVE.W    REG_MASK,D0
	LEA       MONTRANS,A1
WR_FPCR
	BTST      #RM_FPCR,D0
	BEQ.B     WR_FPSR
	FMOVE.L   (A1)+,FPCR
WR_FPSR
	BTST      #RM_FPSR,D0
	BEQ.B     WR_FPIAR
	FMOVE.L   (A1)+,FPSR
WR_FPIAR
	BTST      #RM_FPIAR,D0
	BEQ.B     WR_FPDATA
	FMOVE.L   (A1)+,FPIAR
WR_FPDATA
	BFTST     D0{24:8}
	BEQ.B     WR_RESTORE
	FMOVEM.X  (A1)+,D0
WR_RESTORE
	TST.B     (A7)                 ;do not restore NULL state frame since
	BEQ.B     WR_FPDONE            ;it effectively resets the FPCP undoing
	FRESTORE  (A7)+                ;any register modifications
WR_FPDONE
	BRA       MON_MAIN


********************************************************************************
************   R E A D / W R I T E   M M U   R E G I S T E R S   ***************
********************************************************************************

********************************************************************************
* Monitor command to read selected MMU registers.  Registers are selected with
* REG_MASK.  Register values are always stored in the monitor transfer buffer
* in the same relative order:  TC/SRP/URP/MMUSR/DTTn/ITTn.
********************************************************************************
READ_MMUREGS
	MOVE.W  REG_MASK,D0
	LEA     MONTRANS,A1
RD_TC
	BTST    #RM_TC,D0
	BEQ.B   RD_SRP
	MOVEC   TC,D1
	MOVE.W  D1,(A1)+
RD_SRP
	BTST    #RM_SRP,D0
	BEQ.B   RD_URP
	MOVEC   SRP,D1
	MOVE.L  D1,(A1)+
RD_URP
	BTST    #RM_URP,D0
	BEQ.B   RD_MMUSR
	MOVEC   URP,D1
	MOVE.L  D1,(A1)+
RD_MMUSR
	BTST    #RM_MMUSR,D0
	BEQ.B   RD_DTT0
	MOVEC   MMUSR,D1
	MOVE.L  D1,(A1)+
RD_DTT0
	BTST    #RM_DTT0,D0
	BEQ.B   RD_DTT1
	MOVEC   DTT0,D1
	MOVE.L  D1,(A1)+
RD_DTT1
	BTST    #RM_DTT1,D0
	BEQ.B   RD_ITT0
	MOVEC   DTT1,D1
	MOVE.L  D1,(A1)+
RD_ITT0
	BTST    #RM_ITT0,D0
	BEQ.B   RD_ITT1
	MOVEC   ITT0,D1
	MOVE.L  D1,(A1)+
RD_ITT1
	BTST    #RM_ITT1,D0
	BEQ     MON_MAIN
	MOVEC   ITT1,D1
	MOVE.L  D1,(A1)+
	BRA	MON_MAIN

********************************************************************************
* Monitor command to write selected MMU registers.  Registers are selected with
* REG_MASK.  Register values are always read from the monitor transfer buffer
* in the same relative order:  TC/SRP/URP/MMUSR/DTTn/ITTn.
********************************************************************************
WRITE_MMUREGS
	MOVE.W  REG_MASK,D0
	LEA     MONTRANS,A1
WR_TC
	BTST    #RM_TC,D0
	BEQ.B   WR_SRP
	MOVE.W  (A1)+,D1
	MOVEC   D1,TC
WR_SRP
	BTST    #RM_SRP,D0
	BEQ.B   WR_URP
	MOVE.L  (A1)+,D1
	MOVEC   D1,SRP
WR_URP
	BTST    #RM_URP,D0
	BEQ.B   WR_MMUSR
	MOVE.L  (A1)+,D1
	MOVEC   D1,URP
WR_MMUSR
	BTST    #RM_MMUSR,D0
	BEQ.B   WR_DTT0
	MOVE.L  (A1)+,D1
	MOVEC   D1,MMUSR
WR_DTT0
	BTST    #RM_DTT0,D0
	BEQ.B   WR_DTT1
	MOVE.L  (A1)+,D1
	MOVEC   D1,DTT0
WR_DTT1
	BTST    #RM_DTT1,D0
	BEQ.B   WR_ITT0
	MOVE.L  (A1)+,D1
	MOVEC   D1,DTT1
WR_ITT0
	BTST    #RM_ITT0,D0
	BEQ.B   WR_ITT1
	MOVE.L  (A1)+,D1
	MOVEC   D1,ITT0
WR_ITT1
	BTST    #RM_ITT1,D0
	BEQ     MON_MAIN
	MOVE.L  (A1)+,D1
	MOVEC   D1,ITT1
	BRA	MON_MAIN

********************************************************************************
*******************   M M U   T E S T   A D D R E S S   ************************
********************************************************************************

********************************************************************************
* Monitor command to translate address using PTESTR
********************************************************************************
MMU_TRANSLATE
	MOVEC   TC,D2
	BTST    #15,D2
	BEQ     BADREQUEST           MMU not enabled

	MOVEA.L MEM_ADDR,A0
	MOVE.B  MEM_FCS,D0
	MOVEC   D0,DFC
	MOVEC   MMUSR,D0
	PTESTR  (A0)
	MOVEC   MMUSR,D1
	MOVEC   D0,MMUSR

	BTST    #14,D2                  WARNING:  when using 8K pages, MMUSR
	BEQ.B   MT_DONE                 bit 12 is undefined; force this bit to
	BCLR    #12,D1                  a known value by copying bit 12 from
	MOVE.L  A0,D0                   the logical address
	BTST    #12,D0
	BEQ.B   MT_DONE
	BSET    #12,D1
MT_DONE
	MOVE.L  D1,MEM_MMUSR
	BRA     MON_MAIN

********************************************************************************
* Exit cycle sequences - DO NOT MODIFY -- THESE ARE TRIED AND TESTED SEQUENCES
********************************************************************************
	ORG     MONDATA+$FD0                    very end of monitor
BG_EXIT_RTE
	MOVE.W  D6,D6
	MOVE.W  D6,D6
	MOVE.W  D6,D6
	MOVE.W  D6,D6
	MOVE.W  D6,D6
	MOVE.W  D6,D6
	MOVE.W  D6,D6
	NOP
	MULS.L  #1,D6	
	CMP.B   (MON_EXIT,PC),D6   fix on even word boundary
	RTE 
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
MONPROGEND

;****************************************************************************
; Identification strings to indicate revision level and origin of this file
;
; MKT:@(#) 64783A      A.02.03 68040 EMULATION FIRMWARE       64783     28Apr97                      
; CPR:@(#)                                                                      
; @(SUBID) MP:                                  
; @(SUBID) MAIN: /lsd/zodiac/inst/m68040/drivers 0.22  28Apr97 14:01:19         
;****************************************************************************

