	.title "ODYSSEY NS32GX320 FOREGROUND MONITOR"

#
#	MKT:@(#) 64778-18000 A.00.00 NS32GX320 EMUL FOREGROUND MONITOR        18Sep90                
#
# This foreground monitor is used by the 64778A NS32GX320 emulator 
# to access processor and target resources.  It is also used to
# implement processor run control.  The foreground monitor is 
# entered in one of three ways.  An emulation controller generated 
# reset into the monitor will begin execution at relative address
# 0 in the monitor.  This is the RESETENTRY.  An emulation 
# controller generated NMI will force execution into the monitor
# at the BREAKENTRY.  In this case the exception processing will
# have its stack reads and writes forced to particular monitor memory
# locations.  The third entry method is through normal exception
# processing such as when processing software breakpoints and 
# single-stepping.  This results in entry at EXCEPTIONENTRY.  The 
# configuration item "cf excp" can be used to set up other user 
# induced exceptions to result in entry into the foreground monitor.

# If the monitor is entered through the BREAKENTRY or RESETENTRY
# then it has entered through the background mode.  In these cases
# once the monitor has saved its state, it will exit the background
# portion and enter the foreground mode of the foreground monitor.
# Once in this mode the foreground monitor will accept target 
# generated interrupts.  The monitor is exited by executing a return
# from trap (rett) instruction.  Prior to execution of this instruction
# the stack is modifed to contain the desired values for the PC and
# PSR registers.  If the stack cannot be modified then the exit from
# monitor will fail.

# This forground monitor has been coded to be PC relative and 
# therefore can be loaded anywhere in the 32 bit address space.
# However, in order to communicate effectively, the emulation
# controller expects certain variables to be at known address
# offsets.  In addition several hardware communication functions
# which are at the begining of the monitor must not be moved.  

# The monitor start address must always be aligned to a 32K byte
# boundary.  The monitor is always assembled and linked such 
# that the text space starts at 0 and the data space starts 
# at 0xc00.  The entire size of the monitor cannot exceed 4096 
# bytes. 

# A user supplied forground monitor can be used by loading using
# the load command with the -f option.  This will change the 
# default foreground monitor until the emulator is reinitialized.
# User supplied monitors must be assembled and linked using the
# same restrictions as described above.


#**********************************************************************#
# MONITOR OFFSET VALUES 
# The controller will access certain values within the monitor.  This
# is accomplished by reading and writing monitor memory at predetermined
# monitor offsets.  The following monitor offsets are defined.
#
#   Location          Monitor Offset
#   --------          --------------
#   resetentry            0x000
#   breakentry            0x1010 or 0x2020
#   exception_table       0x0dc
#   CMD_BLOCK             0xd80
#     cmd_num             0xd80
#     count               0xd84
#     start_addr          0xd88
#     hw_config           0xd8c
#     accessmode          0xd90
#     functioncode        0xd94
#     regnumber           0xd98
#     loadaddress         0xd9c
#     defregisters        0xda0
#     psrmask             0xda4
#   STATUS_BLOCK          0xdb0
#     semaphore           0xdb0
#     are_you_there       0xdb1
#     running             0xdb2
#     mon_entry           0xdb4
#   DATA_BUF              0xdc0
#     data_buf            0xdc0
#   REGISTERS             0xeec
#   JAMIN_STACK           0x7f80
#   JAMOUT_STACK          0x7fc0
#**********************************************************************#

#**********************************************************************#
# MONITOR CONSTANTS

# Monitor Command Values - Controller will request one of these commands
	.set	CMDEXIT,   1
	.set	CMDRDMEM,  2
	.set	CMDWRMEM,  3
	.set	CMDRDIO,   4
	.set	CMDWRIO,   5
	.set	CMDRDREG,  6
	.set	CMDRDFPU,  7
	.set	CMDRDDBG,  8
	.set	CMDRDDMA,  9
	.set	CMDRDICU,  10
	.set	CMDRDTIMER,11
	.set	CMDWRREG,  12
	.set	CMDWAITRST,13
	.set	CMDEXITNR, 14

#  Monitor entry values - Indicates Entry Method
#  Jam Entry
	.set	CHECKED_ENTRY,31
	.set	RESET_ENTRY,24
	.set	CMB_REENTRY,25
	.set	BREAK_ENTRY,26

#  Exception Entry
	.set    NVI_ENTRY,0
	.set    NMI_ENTRY,1
	.set    RESERVED_ENTRY,2
	.set    SLAVE_ENTRY,3
	.set    ILL_ENTRY,4
	.set    SVC_ENTRY,5
	.set    DVZ_ENTRY,6
	.set    FLG_ENTRY,7
	.set    BPT_ENTRY,8
	.set    TRC_ENTRY,9
	.set    UND_ENTRY,10
	.set    RBE_ENTRY,11
	.set    NBE_ENTRY,12
	.set    OVF_ENTRY,13
	.set    DBG_ENTRY,14

#  Semaphore values - For Monitor / Controller Synchronization
	.set	NO_CMD,       0
	.set	NEW_CMD,      1
	.set	CMD_STARTED,  2
	.set	MON_FINISHED, 3

#  Monitor status - are_you_there values
	.set    RESPOND,     0
	.set    MON_LOOP,    h'12
	.set    WAIT_CMB,    h'34
	.set    WAIT_RST,    h'56

#  Access Modes - For Target Memory
	.set    BYTEACCESS,  1
	.set    WORDACCESS,  2
	.set    DOUBLEACCESS,4

#  Function Codes  
	.set    ILLEGAL_FC,  0
	.set    DONTCARE_FC, 1
	.set    SUPER_FC,    2
	.set    USER_FC,     3

#  IOB Signals Bit Positions
	.set	OKTORUN, 4
	.set	ANYBRK,  0

#  CFG Register Number and Bit Positions
	.set	FPU_CFG,        1   # Bit position of FPU in CFG register
	.set    DE_CFG,         8   # Bit position of DE in CFG register
	.set    DC_CFG,         9   # Bit position of DC in CFG register
	.set    IC_CFG,         11  # Bit position of IC in CFG register
	.set    PSR_T,          1   # Bit position of T in PSR register
	.set    PSR_U,          8   # Bit position of U in PSR register
	.set    PSR_S,          9   # Bit position of S in PSR register
	.set    PSR_P,          10  # Bit position of P in PSR register
        .set    DEFAULT_CFG,    0   # Bit position for load cfg register
        .set    DEFAULT_SP0,    1   # Bit position for load sp0 register


	.set    REG_R0_NUM,     0   # Assigned number for R0 register
	.set    REG_R1_NUM,     1   # Assigned number for R1 register
	.set    REG_R2_NUM,     2   # Assigned number for R2 register
	.set    REG_R3_NUM,     3   # Assigned number for R3 register
	.set    REG_R4_NUM,     4   # Assigned number for R4 register
	.set    REG_R5_NUM,     5   # Assigned number for R5 register
	.set    REG_R6_NUM,     6   # Assigned number for R6 register
	.set    REG_R7_NUM,     7   # Assigned number for R7 register

	.set    REG_PC_NUM,     8   # Assigned number for PC register
	.set    REG_SP_NUM,     9   # Assigned number for SP register
	.set    REG_SP0_NUM,   10   # Assigned number for SP0 register
	.set    REG_SP1_NUM,   11   # Assigned number for SP1 register
	.set    REG_PSR_NUM,   12   # Assigned number for PSR register
	.set    REG_CFG_NUM,   13   # Assigned number for CFG register
	.set    REG_FP_NUM,    14   # Assigned number for FP register
	.set    REG_SB_NUM,    15   # Assigned number for SB register
	.set    REG_INTBASE_NUM, 16   # Assigned number for INTBASE register
	.set    REG_MOD_NUM,   17   # Assigned number for MOD register
   
	.set    REG_FSR_NUM,   18   # Assigned number for FSR register
	.set    REG_F0_NUM,    19   # Assigned number for F0 register
	.set    REG_F1_NUM,    20   # Assigned number for F2 register
	.set    REG_F2_NUM,    21   # Assigned number for F3 register
	.set    REG_F3_NUM,    22   # Assigned number for F3 register
	.set    REG_F4_NUM,    23   # Assigned number for F4 register
	.set    REG_F5_NUM,    24   # Assigned number for F5 register
	.set    REG_F6_NUM,    25   # Assigned number for F6 register
	.set    REG_F7_NUM,    26   # Assigned number for F7 register
	.set    REG_L0_NUM,    27   # Assigned number for L0 register
	.set    REG_L1_NUM,    28   # Assigned number for L2 register
	.set    REG_L2_NUM,    29   # Assigned number for L3 register
	.set    REG_L3_NUM,    30   # Assigned number for L3 register
	.set    REG_L4_NUM,    31   # Assigned number for L4 register
	.set    REG_L5_NUM,    32   # Assigned number for L5 register
	.set    REG_L6_NUM,    33   # Assigned number for L6 register
	.set    REG_L7_NUM,    34   # Assigned number for L7 register

        .set    REG_DCR_NUM,   35   # Assigned number for DCR register
        .set    REG_DSR_NUM,   36   # Assigned number for DSR register
        .set    REG_CAR_NUM,   37   # Assigned number for CAR register
        .set    REG_BPC_NUM,   38   # Assigned number for BPC register

        .set    REG_STAT_NUM,  39   # Assigned number for STAT register
        .set    REG_IMSK_NUM,  40   # Assigned number for IMSK register
        .set    REG_DSTAT_NUM, 41   # Assigned number for DSTAT register

        .set    REG_ADCA0_NUM, 42   # Assigned number for ADCA0 register
        .set    REG_ADRA0_NUM, 43   # Assigned number for ADRA0 register
        .set    REG_ADCB0_NUM, 44   # Assigned number for ADCB0 register
        .set    REG_ADRB0_NUM, 45   # Assigned number for ADRB0 register
        .set    REG_BLTC0_NUM, 46   # Assigned number for BLTC0 register
        .set    REG_BLTR0_NUM, 47   # Assigned number for BLTR0 register
        .set    REG_MODE0_NUM, 48   # Assigned number for MODE0 register
        .set    REG_CNTL0_NUM, 49   # Assigned number for CNTL0 register

        .set    REG_ADCA1_NUM, 50   # Assigned number for ADCA1 register
        .set    REG_ADRA1_NUM, 51   # Assigned number for ADRA1 register
        .set    REG_ADCB1_NUM, 52   # Assigned number for ADCB1 register
        .set    REG_ADRB1_NUM, 53   # Assigned number for ADRB1 register
        .set    REG_BLTC1_NUM, 54   # Assigned number for BLTC1 register
        .set    REG_BLTR1_NUM, 55   # Assigned number for BLTR1 register
        .set    REG_MODE1_NUM, 56   # Assigned number for MODE1 register
        .set    REG_CNTL1_NUM, 57   # Assigned number for CNTL1 register

        .set    REG_VECT_NUM,  58   # Assigned number for VECT register
        .set    REG_ISRV_NUM,  59   # Assigned number for ISRV register

        .set    REG_TC0_NUM,   60   # Assigned number for TC0 register
        .set    REG_TRCA0_NUM, 61   # Assigned number for TRCA0 register
        .set    REG_TRCB0_NUM, 62   # Assigned number for TRCB0 register
        .set    REG_TCNT0_NUM, 63   # Assigned number for TCNT0 register

        .set    REG_TC1_NUM,   64   # Assigned number for TC1 register
        .set    REG_TRCA1_NUM, 65   # Assigned number for TRCA1 register
        .set    REG_TRCB1_NUM, 66   # Assigned number for TRCB1 register
        .set    REG_TCNT1_NUM, 67   # Assigned number for TCNT1 register

        .set    REG_TC2_NUM,   68   # Assigned number for TC2 register
        .set    REG_TRCA2_NUM, 69   # Assigned number for TRCA2 register
        .set    REG_TRCB2_NUM, 70   # Assigned number for TRCB2 register
        .set    REG_TCNT2_NUM, 71   # Assigned number for TCNT2 register

#  Other Constants
	.set	FALSE,0
	.set	TRUE,1
	.set    JAMINSTACK,0x7f80
	.set    JAMOUTSTACK,0x7fc0
#**********************************************************************#

	.text
# CODE space is linked at 0;  All memory references are PC relative

#**********************************************************************#
#
MONITOR_ENTRY_POINTS:

# From reset, monitor will be entered at location 0

# From break, monitor will be entered at location 0x1010 or 0x2020.
# Address 0x1010 or 0x2020 are determined from the dispatch table
# during NMI processing.  The dispatch table has been set up
# to work regardless of the intbase register contents and mode 
# of exception processing.  Every location in the dispatch table
# contains 0x10, and therefore the new address to run from will
# always be 0x10101010 for direct execpetion mode and 0x10102020
# for module exception mode.  Since jamming will force the
# upper 17 bits to 0, the final effective new addresses are 0x01010
# and 0x02020.


# RESETENTRY
# ADDRESS 0
	# Reset entry point - processor starts excuting at 0 from reset

procreset:
	br	resetentry

# ADDRESS 0x1010
# This four byte instruction is configured in loadmonitor ()
	jump	@breakentry

# ADDRESS 0x2020
# This four byte instruction is configured in loadmonitor ()
	jump	@breakentry

#**********************************************************************#
# Hardware access functions are placed here to assure that they stay
# at the same position.  The monitor control bits within the emulation
# hardware has been set up for the following key locations so as to trigger
# hardware state machines when certain monitor locations are accessed.
#
# These functions are procedurized and include many nop's to ensure that
# bus cycles will be deterministic, behaving in exactly the same way
# every time.
#**********************************************************************#

#**********************************************************************#
# This function reads the IOB signals.  This function is at a special
# location to trigger the circuitry required to read these signals.
# Instruction will cause two read - write pairs.  We want to trigger 
# a jam on the second read.  The write from the first pair will occur
# immediately prior to the second read.  The trigger point is set to
# on the second write address location.
#
# READ_IOB

	.align 4
read_iob:
	movmb    %dummy2,%dummy1,2
	br       .LL171
#**********************************************************************#

	.space	16

#**********************************************************************#
# This function sets the signal setemulrdy low.  This function is at a
# special location to trigger the circuitry required to do this.
#
# SETEMULRDY_LOW

	.align 4
setemulrdy_low:
	# Monitor bit trigger - address of following instruction
	br       .LL17
#**********************************************************************#

	.space	16

#**********************************************************************#
# This function located at a special location so as to trigger 
# the exit from background monitor circuitry.
#
# BACKGROUND_EXIT

	.align 4
background_exit:
	# Monitor bit trigger - address of following instruction
 	reti
#**********************************************************************#

	.space  16

#**********************************************************************#
# This function transfers the data pointed to by register r7 to the
# location pointed to by the register r6.  This function is at a 
# special location to trigger the target system access circuitry.
# It must trigger the hardware for read from target system.
# Trigger location is set to the location one bus cycle before the read
#
# TARGETREADMOP

	.align 4

targetreadmop:
 	movb	0(r7),0(r6)
	nop
	nop
	br	.RT06
#**********************************************************************#

	.space 16

#**********************************************************************#
# This function transfers the data pointed to by register r7 to the
# location pointed to by the register r6.  This function is at a 
# special location to trigger the target system access circuitry.
# It must trigger the hardware for read from target system.
# Trigger location is set to the location one bus cycle before the read
#
# TARGETWRITEMOP

	.align 4

targetwritemop:
 	movb	0(r7),0(r6)
	nop
	nop
	br	.WT06
#**********************************************************************#

	.space 16

#**********************************************************************#
# This function located at a special location so as to trigger 
# the exit from monitor circuitry.
#
# MONITOR_EXIT

	.align 4
monitor_exit:
	# Monitor bit trigger - address of following instruction
 	rett  $(0)
#**********************************************************************#

	.space  16

#**********************************************************************#
# This table provides a mechanism of entry into the exception processing
# functions.  This table is at a known offset in the foreground monitor
# and cannot be changed.
#
# EXCEPTION_TABLE

	.align 4
exception_table:
	movb	 $(NVI_ENTRY),%monentrybit       # vector 0
	br	 exceptionentry
	movb	 $(NMI_ENTRY),%monentrybit       # vector 1
	br	 exceptionentry
	movb	 $(RESERVED_ENTRY),%monentrybit  # vector 2
	br	 exceptionentry
	movb	 $(SLAVE_ENTRY),%monentrybit     # vector 3
	br	 exceptionentry
	movb	 $(ILL_ENTRY),%monentrybit       # vector 4
	br	 exceptionentry
	movb	 $(SVC_ENTRY),%monentrybit       # vector 5
	br	 exceptionentry
	movb	 $(DVZ_ENTRY),%monentrybit       # vector 6
	br	 exceptionentry
	movb	 $(FLG_ENTRY),%monentrybit       # vector 7
	br	 exceptionentry
	movb	 $(BPT_ENTRY),%monentrybit       # vector 8
	br	 exceptionentry
	movb	 $(TRC_ENTRY),%monentrybit       # vector 9
	br	 exceptionentry
	movb	 $(UND_ENTRY),%monentrybit       # vector 10
	br	 exceptionentry
	movb	 $(RBE_ENTRY),%monentrybit       # vector 11
	br	 exceptionentry
	movb	 $(NBE_ENTRY),%monentrybit       # vector 12
	br	 exceptionentry
	movb	 $(OVF_ENTRY),%monentrybit       # vector 13
	br	 exceptionentry
	movb	 $(DBG_ENTRY),%monentrybit       # vector 14
	br	 exceptionentry

#**********************************************************************#

#**********************************************************************#
# Break from foreground will cause execution in monitor 
# based on dispatch table.  Entry should always specify
# this entry, breakentry.
# Monitor will execute in background until exit to monitor_loop
#
# BREAKENTRY

	.align 4
breakentry:
        # Controller induced break
	sbitd	 $(BREAK_ENTRY),%mon_entry

        # This entry point is due to a break from user code to monitor -NMI
	# At this point the processor is in supervisor mode
	# PSR U is 0 - all instructions may be executed
	# PSR S is 0 - use supervisor stack pointer SP0
	# PSR I is 0 - maskable interrupts are disabled

	# Save cfg register
	sprd	 cfg,%REG_CFG

	# Save general purpose registers used in monitor
	movd     r4,%REG_R4
	movd     r5,%REG_R5
	movd     r6,%REG_R6
	movd     r7,%REG_R7
	  
        # Save the stack values before and after the break
	sprd	 sp,%return_stack
        movd     %return_stack,r7
        addd     $(8),r7
        movd     r7,%REG_SP0

	# Save the INTBASE register, to be used my get_jam
	sprd 	 intbase,%REG_INTBASE

        # Read PC, MOD, and PSR from JAMIN STACK
        # Before using the following registers must be current
        # REG_SP0
        # REG_CFG
        # REG_INTBASE
        # 
        # GET_JAM
	movqd	$(3),r5        # calculate rotate left bits
	andd	%REG_SP0,r5    # rotate_left = 32 - (REG_SP0 & 3) * 8
	lshd	$(3),r5

        # r5 contains the number of bits to shift
	# r6 contains the number of bits to rotate
	# register r6 = 32 - (8 * (lower two bits of SP0))
	movd	$(32),r4
	movd    r5,r6
	subd	r6,r4
	movd    r4,r6

	# Set up masks for PSR MOD
	# bits 1..0 of SP0
	#  00   mask_1=0xffff0000   mask_2=0x0000ffff   mask_3=0x00000000
	#  01   mask_1=0xff000000   mask_2=0x000000ff   mask_3=0x00ffff00
	#  10   mask_1=0x0000ffff   mask_2=0xffff0000   mask_3=0x00000000
	#  11   mask_1=0x00ffff00   mask_2=0xff000000   mask_3=0x000000ff
	# register r5 = 8 * (lower two bits of SP0)

	# case 00
	movd    $(h'0ffff0000),%mask_1
	comd    %mask_1,%mask_2

	movqd	$(3),r4
	andd	%REG_SP0,r4
	cmpqd	$(1),r4
	bne	.GJ7
	# case 01
	movd    $(h'0ff000000),%mask_1
	movd    $(h'0000000ff),%mask_2
	br	.GJ9
.GJ7:
	cmpqd	$(2),r4
	bne	.GJ8
	# case 10
	movd    $(h'00000ffff),%mask_1
	comd    %mask_1,%mask_2
	br	.GJ9
.GJ8:
	cmpqd	$(3),r4
	bne	.GJ9
	# case 11
	movd    $(h'000ffff00),%mask_1
	movd    $(h'0ff000000),%mask_2
.GJ9:

	# Calculate mask_3
	movd    %mask_1,r4
	ord     %mask_2,r4
	comd    r4,%mask_3

        movd    $(JAMINSTACK),r7

	# Get PSR and MOD
	andd    %mask_1,0(r7)
	movd	0(r7),%jam_value   # Always get first double of jam
	addqd	$(4),r7

	# Check for exception mode type
	tbitb	$(DE_CFG),%REG_CFG
	bfs	.GJ1

	# Module exception mode
	# For module exception mode always get a second double
	andd    %mask_2,0(r7)
	ord	0(r7),%jam_value
	addqd	$(4),r7
	# If SP0 is odd then get a third double
	tbitb	$(0),%REG_SP0
	bfc	.GJ2
	andd    %mask_3,0(r7)
	ord	0(r7),%jam_value
	addqd	$(4),r7
.GJ2:
        # Since module exception mode, need to skip reads
	# If REG_INTBASE is double aligned - three double reads
	addd	$(12),r7
	movqd	$(3),r4
	andd	%REG_INTBASE,r4
	cmpqd	$(0),r4
	beq	.GJ3
	# If not double aligned - then four double reads
	addqd	$(4),r7
.GJ3:
	br	.GJ4
.GJ1:
        # Direct exception mode
	# If bits 1..0 of REG_SP0 are 01 then need second word
	movqd	$(3),r4
	andd	%REG_SP0,r4
	cmpqd	$(1),r4
	bne	.GJ5
	andd    %mask_2,0(r7)
	ord	0(r7),%jam_value
	addqd	$(4),r7
.GJ5:
.GJ4:
        # REG_PSR is in upper 16 bits, REG_MOD is in lower 16 bits
	rotd	r6,%jam_value
	movd	%jam_value,r4
	lshd	$(-16),r4
	movw	r4,%REG_PSR
	movqw	$(-1),r4
	andw	%jam_value,r4
	movw	r4,%REG_MOD

	# Get PC
	# If REG_SP0 is double aligned need only one double
	# Set up masks for PC 
	# PC masks
	# bits 1..0 of SP0
	#  00   mask_1=0xffffffff   mask_2=0x00000000
	#  01   mask_1=0xffffff00   mask_2=0x000000ff
	#  10   mask_1=0xffff0000   mask_2=0x0000ffff
	#  11   mask_1=0xff000000   mask_2=0x00ffffff
	# register r5 = 8 * (lower two bits of SP0)

	movd    $(h'0ffffffff),%mask_1
	lshd    r5,%mask_1
	movd    %mask_1,r4
	comd    r4,mask_2

	andd    %mask_1,0(r7)
	movd	0(r7),%jam_value
	addqd	$(4),r7
	movqd	$(3),r4
	andd	%REG_SP0,r4
	cmpqd	$(0),r4
	beq	.GJ6
	# If REG_SP0 is not double aligned need two doubles
	andd    %mask_2,0(r7)
	ord	0(r7),%jam_value
.GJ6:
	movd	%jam_value,r4
	rotd	r6,r4
	movd	r4,%REG_PC

        # Clear JAMIN Stack
        addr    %JAMIN_STACK,r7
	movqd   $(0),r6 
.CJ1:
	movd    $(h'10101010),0(r7)
	addqd   $(4),r7
	addqd   $(1),r6
	cmpd    $(16),r6
	bne     .CJ1
.CJ2:

        # If direct exception mode, then MOD was not on stack
        tbitd    $(DE_CFG),%REG_CFG
	bfc      .MON0
	# If direct exception mode, then 
	# MOD and SB registers were not affected by break
	sprw 	 mod,%REG_MOD
	br	 .MON1

.MON0:
	# If module exception mode then mod register will be in 
	# JAMIN Stack.  Controller will read memory to get SB.
	# Load mod with prior break value to keep current
	# At exit value in mod register will be used to restore
	lprw 	 mod,%REG_MOD

.MON1:

	# Go to main monitor loop
        # To exit from background portion of monitor to foreground must
	# set up stack to point to monitor_loop.  A stack value is set
	# up to guarantee that a stack exists for this transfer from 
	# the background portion of the monitor to the foreground portion.

	# Set stack pointer so that it is double word aligned 
	# This makes the jamout easy - just set up PC, PSR, and
	# MOD at aligned spots - make PSR and MOD 0
	addr     %TOP_OF_MONSTACK,r6
        addd     %loadaddress,r6
        lprd     sp,r6
        adjspd   $(8)

	movd     $(JAMOUT_STACK),r7
	addr     %monitor_loop,r6
	addd     %loadaddress,r6
	movd     r6,0(r7)          # PC value - address of monitor_loop
	movw     $(0),6(r7)        # PSR value
	movw     %REG_MOD,4(r7)    # MOD value
	movd     $(0),8(r7)        # SB values

	br       %background_exit
#**********************************************************************#

#**********************************************************************#
# END OF POSITION DEPENDENT FUNCTIONS
#**********************************************************************#

#**********************************************************************#
# NORMAL EXCEPTION PROCESSING
# Monitor is executing in foreground
#  
# EXCEPTIONENTRY

	.align 4
exceptionentry:
        # This entry point is due to a normal processor exception
	# At this point the processor is in supervisor mode
	# PSR U is 0 - all instructions may be executed
	# PSR S is 0 - use supervisor stack pointer SP0
	# PSR I is 0 - maskable interrupts are disabled

	lprw     psr,$(0)

	sbitd	 %monentrybit,%mon_entry

	# Save cfg register
	sprd	 cfg,%REG_CFG

	# Do special things with PC, SP, and PSR registers
        # Save the stack values before and after the break
	sprd	 sp,%return_stack

        # Save the PC and PSR; These are the correct values prior to break
	movd     0(sp),%REG_PC
	movw     6(sp),%REG_PSR
	# Save MOD because of possible module exception mode
	movw     4(sp),%REG_MOD

	# If exception was caused by system controlled single step,
	# then T bit in PSR will be set.  Clear it to 0
	cmpqb    $(TRUE),%singlestep
	bne      .EE3
	cbitw    $(PSR_T),%REG_PSR
	movqb    $(FALSE),%singlestep

	# If pending bit is set, then wanted to single-step, but a higher
	# priority caused the exception.  Clear pending bit and indicate
	# single-step entry in addition to real cause of monitor entry
	tbitw    $(PSR_P),%REG_PSR
	bfc      .EE3
	cbitw    $(PSR_P),%REG_PSR
	sbitd    $(TRC_ENTRY),%mon_entry
.EE3:

	# Save general purpose registers used in monitor
	movd     r4,%REG_R4
	movd     r5,%REG_R5
	movd     r6,%REG_R6
	movd     r7,%REG_R7

        # Save interrupt stack pointer prior to the exception
	movd     %return_stack,r7
	addd     $(8),r7
	movd     r7,%REG_SP0

        # MOD and SB registers are special handled according to 
	# type of exeception mode.  Controller will handle SB
	# for module exception mode.

        tbitd    $(DE_CFG),%REG_CFG
	bfc      .EE0
	# If direct exception mode, then 
	# MOD and SB registers were not affected by break
	sprw 	 mod,%REG_MOD
	br	 .EE1

.EE0:
	# If module exception mode then mod register will be in 
	# monitor stack.  Controller will read memory to get SB.
	# Load mod with prior break value to keep current
	# At exit value in mod register will be used to restore
	# This value was saved earlier
	# Store in register to handle any changes to CFG register
	lprw 	 mod,%REG_MOD

.EE1:
	# Go to main monitor loop
	br	 monitor_loop
#**********************************************************************#

#**********************************************************************#
# Reset into the monitor will force execution from monitor offset 0
# Monitor will execute in background until exit to monitor_loop
#
# RESETENTRY

	.align 4
resetentry:
        # Setup of the default power-up conditions
	sbitd	 $(RESET_ENTRY),%mon_entry

	# Processor is in reset configuration
	# Execution from address 0
	# Implemented bits in PSR and CFG registers are 0

	# Save general purpose registers used in monitor
	movd     r4,%REG_R4
	movd     r5,%REG_R5
	movd     r6,%REG_R6
	movd     r7,%REG_R7

        # Configure the registers for a reset configuration
	# Load the CFG register with a default value if bit 0
	# of the variable defregisters is set.  The 32 bit 
	# value in 0(DATA_BUF) will contain the default value.

	# Load the SP0 register with a default value if bit 1
	# of the variable defregisters is set.  The 32 bit 
	# value in 4(DATA_BUF) will contain the default value.

	movqd    $(0),%REG_CFG
        tbitd    $(DEFAULT_CFG),%defregisters
	bfc      .DFCF
	addr     %DATA_BUF,r7
	movd     0(r7),%REG_CFG
.DFCF:
	movd     %REG_CFG,r7
	lprd     cfg,%REG_CFG

	# Save interrupt stack pointer; set to something useful
	addr     %TOP_OF_STACK,r6
	addd     %loadaddress,r6
	movd     r6,%REG_SP0

        tbitd    $(DEFAULT_SP0),%defregisters
	bfc      .DFSP0
	addr     %DATA_BUF,r7
	movd     4(r7),%REG_SP0
.DFSP0:

	# Calculate stack value prior to return from monitor
	movd     %REG_SP0,r7
	subd     $(8),r7
	movd     r7,%return_stack

        # Initialize PC and PSR to reset values; reset to 0
	movqd    $(0),%REG_PC
	movqw    $(0),%REG_PSR

	# Save MOD register; don't care what it is
	sprw 	 mod,%REG_MOD

	# Go to main monitor loop
        # To exit from background portion of monitor to foreground must
	# set up stack to point to monitor_loop.  A stack value is set
	# up to guarantee that a stack exists for this transfer from 
	# the background portion of the monitor to the foreground portion.

	# Set stack pointer so that it is double word aligned 
	# Since the stack may not be valid at reset, load stack pointer
	# This makes the jamout easy - just set up PC, PSR, and
	# MOD at aligned spots - make PSR and MOD 0
	addr     %TOP_OF_MONSTACK,r6
        addd     %loadaddress,r6
        lprd     sp,r6
        adjspd   $(8)

	movd     $(JAMOUTSTACK),r7
	addr     %monitor_loop,r6
	addd     %loadaddress,r6
	movd     r6,0(r7)          # PC value - address of monitor_loop
	movw     $(0),6(r7)        # PSR value
	movw     %REG_MOD,4(r7)    # MOD value
	movd     $(0),8(r7)        # SB values

	br       %background_exit
#**********************************************************************#

#**********************************************************************#
# Reenter monitor from monitor itself
# This will occur while waiting for CMB a pending break is detected
#
# REENTRY

	.align 4
reentry:
        # This entry point is due to a break while running in monitor
	sbitd	 $(CMB_REENTRY),%mon_entry

	# All registers are already saved

	# Go to main monitor loop
	br	 monitor_loop
#**********************************************************************#

#**********************************************************************#
# This is the main command loop
#
# MONITOR_LOOP

	.align 4
monitor_loop:
	cbitd    $(CHECKED_ENTRY),%mon_entry

	# Restore stack to users and restore enabled interrupts
	# All monitor entry points have initialized return_stack value
        lprd     sp,%return_stack

        # Now enable maskable interrupts, if they were enabled
        # User can select whether or not interrupts should be
        # enabled while in the monitor.  If the user wants them
        # enabled, then they are only enabled if enabled prior
        # to the monitor entry.
        movzwd   %REG_PSR,r7
        andd     %psrmask,r7       # Load orignal PSR I bit
        lprw     psr,r7

.LL2:
        # Check for a new command
	cmpqb	 $(NEW_CMD),%semaphore
	beq	 .LL3
	movb	 %are_you_there,r7
	br	 .LL4
.LL3:
	# A new command has been issued - do it
	# Signal acceptance of command
	movqb	 $(CMD_STARTED),%semaphore

        # Initialize the functioncode for target accesses
	cmpqd 	 $(DONTCARE_FC),%functioncode
	bne      .FC1
	tbitw    $(PSR_U),%REG_PSR
	bfc      .FC2
	movqd    $(USER_FC),%functioncode
	br       .FC1
.FC2:
        movqd    $(SUPER_FC),%functioncode
.FC1:

	br	 .LL15
.LL7:
        # cmd_num == CMDEXIT
	# Check CMB and return to foreground
	br	 foreground
.LL8:
        # cmd_num == CMDRDMEM
	# Read from target memory to data_buf
	br	 readtargetmem
.LL9:
        # cmd_num == CMDWRMEM
	# Write from data_buf to target memory
	br	 writetargetmem
.LL91:
        # cmd_num == CMDRDIO
	# READ from IO space to data_buf
	br	 readiospace
.LL92:
        # cmd_num == CMDWRIO
	# Write from data_buf to IO space
	br	 writeiospace
.LL10:
        # cmd_num == CMDRDREG
	# Ensure that register copies are in monitor register area
	br	 readregister
.FPU10:
        # cmd_num == CMDRDFPU
	# Ensure that register copies are in monitor register area
	br	 readfpuregister
.DBG10:
        # cmd_num == CMDRDDBG
	# Ensure that register copies are in monitor register area
	br	 readdbgregister
.DMA10:
        # cmd_num == CMDRDDMA
	# Ensure that register copies are in monitor register area
	br	 readdmaregister
.ICU10:
        # cmd_num == CMDRDICU
	# Ensure that register copies are in monitor register area
	br	 readicuregister
.TIMER10:
        # cmd_num == CMDRDTIMER
	# Ensure that register copies are in monitor register area
	br	 readtimerregister
.LL11:
        # cmd_num == CMDWRREG
	# Modify registers
	br	 writeregister
.LL12:
        # cmd_num == CMDWAITRST
	# Wait for target system reset
	br       wait_for_rst
.NR16:
        # cmd_num == CMDEXITNR
	# Return to foreground without checking CMB
	# and setting EMULRDY
	# This command is used to handle multiple 
	# exceptions, such as when stepping through
	# a hardware breakpoint.
	br	 foreground_ready
.LL14:
        # default:
	br	 .LL5
.LL15:
	movd  	 %cmd_num,r6
	cmpd	 $(CMDEXIT),r6
	bgt	 .LL14
	cmpd	 $(CMDEXITNR),r6
	blt	 .LL14
.LP6:
	casew	 .LP5+(-2)[r6:w]

.LL5:
.LL4:
        # Indicate that the monitor is in the main monitor loop
	movb	 $(MON_LOOP),%are_you_there
	br	 .LL2

.LL6:
	movqb    $(MON_FINISHED),%semaphore
	br	 .LL5

	# monitor loop branch table
	.align 4
.LP5:
	.word	.LL7 - .LP6
	.word	.LL8 - .LP6
	.word	.LL9 - .LP6
	.word	.LL91 - .LP6
	.word	.LL92 - .LP6
	.word	.LL10 - .LP6
	.word	.FPU10 - .LP6
	.word	.DBG10 - .LP6
	.word	.DMA10 - .LP6
	.word	.ICU10 - .LP6
	.word	.TIMER10 - .LP6
	.word	.LL11 - .LP6
	.word	.LL12 - .LP6
	.word	.NR16 - .LP6
#**********************************************************************#

#**********************************************************************#
# Just stay here waiting for reset- there is no other way out
#
# WAIT_FOR_RST

	.align 4
wait_for_rst:
        # Indicate that the monitor is in the waiting for reset loop
	movb	 $(TRUE),%running
	movb	 $(WAIT_RST),%are_you_there

        br       wait_for_rst
#**********************************************************************#

#**********************************************************************#
# Return from monitor to user code 
# This involves :
#   Restoring registers
#   Signalling ready on the CMB
#   Checking for CMB for OK To RUN
#     If not ready then check for pending break
#     If pending break, then reenter monitor
#
# FOREGROUND

	.align 4
foreground:
        # Indicate that this emulator is ready to go
	br	 setemulrdy_low

.LL17:
	# Indicate run has started
	movb	 $(TRUE),%running

        # Indicate that the monitor is in the waiting for CMB loop
	movb	 $(WAIT_CMB),%are_you_there

	# Read IOB signals
	br	 read_iob
.LL171:

	# If OK TO RUN
	tbitb	 $(OKTORUN),%iob_signals
	# signal is active high
	bfc	 .LL18

	# System is ready - Return to foreground
	# Check count flag for new specification of PC
	# New PC value will be in start_addr if count bit 0 is 1
	tbitd	 $(0),%count
	bfc	 .LL19
	# New PC value, stuff into stack
	movd     %start_addr,%REG_PC
.LL19:

foreground_ready:

 	# Restore registers CFG, PC, SP0, MOD, and R0-R7
	# Do special things with PC, SP, and PSR registers
	# Calculate the new address for the PC and PSR on stack
	# Stack pointer may have been changed, so have to rebuild
	# stack for correct return.
	movd     %REG_SP0,r7
	subd     $(8),r7
	movd     r7,%return_stack

	# Set the user bit in PSR to match function code
	sbitw    $(PSR_U),%REG_PSR
	cmpqd 	 $(USER_FC),%functioncode
	beq      .FC3
	cbitw    $(PSR_U),%REG_PSR
.FC3:

        # Restore the PC and PSR; These are the correct values prior to break
	# Also put MOD into stack for possible module exception mode.  If not
	# module exeption mode it doesn't matter
	sprw 	 mod,%REG_MOD
	movw     %REG_PSR,6(r7)
	movd     %REG_PC,0(r7)
	movw     %REG_MOD,4(r7)

        # Restore MOD register for possible direct execption mode
	# If module exception mode then it doesn't matter
	# SB is handled completely by the controller
	lprw 	 mod,%REG_MOD

	# Restore cfg register
	lprd 	 cfg,%REG_CFG

	# Check count flag for single step specification
	# Single step indication if count bit 1 is 1
	tbitd	 $(1),%count
	bfc	 .LL21
	# Modify return PSR to have the TRC bit set (bit 1)
	orw      $(2),6(r7)
	movqb    $(TRUE),%singlestep
.LL21:

        # Restore the interrupt stack value after the break
	lprd	 sp,%return_stack

	# Restore r4-r7 registers used in monitor prior to break
	movd     %REG_R7,r7
	movd     %REG_R6,r6
	movd     %REG_R5,r5
	movd     %REG_R4,r4

	# Tell controller that the monitor is finished
	movqb	 $(MON_FINISHED),%semaphore

	# This will stop execution of monitor at this point
	br	 %monitor_exit

.LL18:
        # CMB not ready, check for pending break
	# signal is active low
	tbitb	 $(ANYBRK),%iob_signals
	bfs	 .LL20

	# If pending break, then reenter monitor
	br	 %reentry
.LL20:
	br	 .LL17
#**********************************************************************#

#**********************************************************************#
#
# READREGISTER

	.align 4
readregister:
        # CPU registers 0..18   REG_R0_NUM..REG_BPC_NUM
	# FPU registers 18..34  REG_FSR_NUM..REG_L7_NUM
    
	# Save CPU registers into monitor buffer area
	# Registers CFG, PC, SP0, PSR, MOD, and R5-R7 are handled special
	# These registers are saved upon monitor entry and will be 
	# restored upon monitor exit.  Changes made in between are lost.
	# There is an attempt to keep all registers loaded with their
	# latest user value.

	# Save R0-R4,SP1,FP,SB,INTBASE,MOD
	movd     r0,%REG_R0
	movd     r1,%REG_R1
	movd     r2,%REG_R2
	movd     r3,%REG_R3
	bispsrw  $(b'0000001000000000)
	sprd 	 sp,%REG_SP1
	bicpsrw	 $(b'0000001000000000)
	sprd 	 cfg,%REG_CFG
	sprd 	 fp,%REG_FP
	sprd 	 sb,%REG_SB
	sprd 	 intbase,%REG_INTBASE
	sprw 	 mod,%REG_MOD

	# Update REG_SP to be either REG_SP0 or REG_SP1
        tbitw    $(PSR_S),%REG_PSR
	bfc      .RER0 
	movd     %REG_SP1,%REG_SP
	br       .RER1
.RER0:
	movd     %REG_SP0,%REG_SP
.RER1:
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# READFPUREGISTER

	.align 4
readfpuregister:
	# Save FPU registers into monitor buffer area
	# Get FPU registers if FPU present and F bit in CFG register is set
        tbitd    $(FPU_CFG),%hw_config
	bfc      .FPU7 
        tbitd    $(FPU_CFG),%REG_CFG
	bfc      .FPU7 

   	addr     %data_buf,r7
 	sfsr	 0(r7)
 	movf	 f0,4(r7)
 	movf	 f1,8(r7)
 	movf	 f2,12(r7)
 	movf	 f3,16(r7)
 	movf	 f4,20(r7)
 	movf	 f5,24(r7)
 	movf	 f6,28(r7)
 	movf	 f7,32(r7)
 	movl	 l0,36(r7)
 	movl	 l1,44(r7)
 	movl	 l2,52(r7)
 	movl	 l3,60(r7)
 	movl	 l4,68(r7)
 	movl	 l5,76(r7)
 	movl	 l6,84(r7)
 	movl	 l7,92(r7)
	# Reload fsr since reads from other registers are destructive
	lfsr	 0(r7)

.FPU7:
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# READDBGREGISTER

	.align 4
readdbgregister:
	# Save DBG registers into monitor buffer area
	# Return to monitor loop
   	addr     %data_buf,r7
	sprd     dcr,0(r7)
	sprd     dsr,4(r7)
	sprd     car,8(r7)
	sprd     bpc,12(r7)
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# READDMAREGISTER

	.align 4
readdmaregister:
	# Save DMA registers into monitor buffer area
   	addr     %data_buf,r7
	movd     $(0x0fffff010),r6
	movqd	 $(0),r5
.RDMA1:
	movd     0(r6),0(r7)
	addqd	 $(4),r7
	addqd	 $(4),r6
	addqd	 $(1),r5
	cmpd	 $(3),r5
	bhi	 .RDMA1

	movd     $(0x0fffff020),r6
	movqd	 $(0),r5
.RDMA2:
	movd     0(r6),0(r7)
	addqd	 $(4),r7
	addqd	 $(4),r6
	addqd	 $(1),r5
	cmpd	 $(16),r5
	bhi	 .RDMA2
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# READICUREGISTER

	.align 4
readicuregister:
	# Save ICU registers into monitor buffer area
   	addr     %data_buf,r7
	movd     $(0x0fffffe00),r6
	movb     0(r6),0(r7)
	movw     4(r6),1(r7)
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# READTIMERREGISTER

	.align 4
readtimerregister:
	# Save TIMER registers into monitor buffer area
   	addr     %data_buf,r7
	movd     $(0x0fffff810),r6
	movqd	 $(0),r5
.RTIMER1:
	movw     0(r6),0(r7)
	addqd	 $(2),r7
	addqd	 $(4),r6
	addqd	 $(1),r5
	cmpd	 $(12),r5
	bhi	 .RTIMER1
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# WRITEREGISTER

	.align 4
writeregister:
	# New register value has been loaded into data_buf
	# Transfer value from buffer to either monitor register area or register

	# Registers CFG, PC, SP0, PSR, MOD, and R5-R7 are handled special
	# These registers are saved upon monitor entry and will be 
	# restored upon monitor exit.  All references to these resiters are
	# made through the monitor register area.

	# The registers SP1,FP,SB,INTBASE, and FPU registers are kept 
	# up to date since they don't change while in the monitor.

	# This function uses register r6 and r7
	# Check if the write register is FPU to handle special

	# Check for FPU register to be written to
	movd	%regnumber,r6
	cmpd	$(REG_FSR_NUM),r6
	bgt	.WLL56
	cmpd	$(REG_L7_NUM),r6
	blt	.WLL56

	# Check to see if FPU is present
        tbitd    $(FPU_CFG),%hw_config
	bfc      .WLL6 
	# Check to see of FPU is enabled
        tbitd    $(FPU_CFG),%REG_CFG
	bfc      .WLL6 

	# Write to FPU register, save and restore FSR
	sfsr	 %save_reg_fsr


.WLL56:

	# Not an invalid FPU write, so continue with write to register

	addr     %data_buf,r7   # address of new register value
	br	.WLL7           # branch based on register number

.WLL8:
        # Write Register R0
        movd     0(r7),%REG_R0
	movd     %REG_R0,r0
	br	.WLL6
.WLL9:
        # Write Register R1
        movd     0(r7),%REG_R1
	movd     %REG_R1,r1
	br	.WLL6
.WLL10:
        # Write Register R2
        movd     0(r7),%REG_R2
	movd     %REG_R2,r2
	br	.WLL6
.WLL11:
        # Write Register R3
        movd     0(r7),%REG_R3
	movd     %REG_R3,r3
	br	.WLL6
.WLL12:
        # Write Register R4 - used in monitor restored at exit
        movd     0(r7),%REG_R4
	br	.WLL6
.WLL13:
        # Write Register R5 - used in monitor restored at exit
        movd     0(r7),%REG_R5
	br	.WLL6
.WLL14:
        # Write Register R6 - used in monitor restored at exit
        movd     0(r7),%REG_R6
	br	.WLL6
.WLL15:
        # Write Register R7 - used in monitor restored at exit
        movd     0(r7),%REG_R7
	br	.WLL6
.WLL16:
        # Write Register PC
        movd     0(r7),%REG_PC
	br	.WLL6
.WLL17:
        # Write Register SP
        movd     0(r7),%REG_SP
	# Update either SP0 or SP1
        tbitw    $(PSR_S),%REG_PSR
	bfc      .WLL18   # Update SP0
	br       .WLL19   # Update SP1
.WLL18:
        # Write Register SP0
        movd     0(r7),%REG_SP0
	br	.WLL6
.WLL19:
        # Write Register SP1
        movd     0(r7),%REG_SP1
	# Switch to user stack pointer
	bispsrw  $(b'0000001000000000)
	lprd 	 sp,%REG_SP1
	# Switch back to supervisor stack pointer
	bicpsrw	 $(b'0000001000000000)
	br	.WLL6
.WLL20:
        # Write Register PSR
        movw     0(r7),%REG_PSR
	br	.WLL6
.WLL21:
        # Write Register CFG
        movd     0(r7),%REG_CFG
	lprd     cfg,%REG_CFG
	br	.WLL6
.WLL22:
        # Write Register FP
        movd     0(r7),%REG_FP
	lprd     fp,%REG_FP
	br	.WLL6
.WLL23:
        # Write Register SB
        movd     0(r7),%REG_SB
	lprd     sb,%REG_SB
	br	.WLL6
.WLL24:
        # Write Register INTBASE
        movd     0(r7),%REG_INTBASE
	lprd     intbase,%REG_INTBASE
	br	.WLL6
.WLL25:
        # Write Register MOD
        movw     0(r7),%REG_MOD
	lprw     mod,%REG_MOD
	br	.WLL6
.WLL26:
        # Write Register FSR
        movd     0(r7),%save_reg_fsr
	br	.WLL57
.WLL27:
        # Write Register F0
	movf	 0(r7),f0
	br	.WLL57
.WLL28:
        # Write Register F1
	movf	 0(r7),f1
	br	.WLL57
.WLL29:
        # Write Register F2
	movf	 0(r7),f2
	br	.WLL57
.WLL30:
        # Write Register F3
	movf	 0(r7),f3
	br	.WLL57
.WLL31:
        # Write Register F4
	movf	 0(r7),f4
	br	.WLL57
.WLL32:
        # Write Register F5
	movf	 0(r7),f5
	br	.WLL57
.WLL33:
        # Write Register F6
	movf	 0(r7),f6
	br	.WLL57
.WLL34:
        # Write Register F7
	movf	 0(r7),f7
	br	.WLL57
.WLL35:
        # Write Register L0
	movl	 0(r7),l0
	br	.WLL57
.WLL36:
        # Write Register L1
	movl	 0(r7),l1
	br	.WLL57
.WLL37:
        # Write Register L2
	movl	 0(r7),l2
	br	.WLL57
.WLL38:
        # Write Register L3
	movl	 0(r7),l3
	br	.WLL57
.WLL39:
        # Write Register L4
	movl	 0(r7),l4
	br	.WLL57
.WLL40:
        # Write Register L5
	movl	 0(r7),l5
	br	.WLL57
.WLL41:
        # Write Register L6
	movl	 0(r7),l6
	br	.WLL57
.WLL42:
        # Write Register L7
	movl	 0(r7),l7
	br	.WLL57

.WLL431:
        # Write Register DCR
	lprd	 dcr,0(r7)
	br	.WLL6

.WLL432:
        # Write Register DSR
	lprd	 dsr,0(r7)
	br	.WLL6

.WLL433:
        # Write Register CAR
	lprd	 car,0(r7)
	br	.WLL6

.WLL434:
        # Write Register BPC
	lprd	 bpc,0(r7)
	br	.WLL6

.WLL441:
        # Write Register STAT
	movd     $(0xfffff010),r6
	br       .WLL502

.WLL442:
        # Write Register IMSK
	movd     $(0xfffff014),r6
	br       .WLL502

.WLL443:
        # Write Register DSTAT
	movd     $(0xfffff018),r6
	br       .WLL502

.WLL444:
        # Write Register ADCA0
	movd     $(0xfffff020),r6
	br       .WLL502

.WLL445:
        # Write Register ADRA0
	movd     $(0xfffff024),r6
	br       .WLL502

.WLL446:
        # Write Register ADCB0
	movd     $(0xfffff028),r6
	br       .WLL502

.WLL447:
        # Write Register ADRB0
	movd     $(0xfffff02c),r6
	br       .WLL502

.WLL448:
        # Write Register BLTC0
	movd     $(0xfffff030),r6
	br       .WLL502

.WLL449:
        # Write Register BLTR0
	movd     $(0xfffff034),r6
	br       .WLL502

.WLL4410:
        # Write Register MODE0
	movd     $(0xfffff038),r6
	br       .WLL502

.WLL4411:
        # Write Register CNTL0
	movd     $(0xfffff03c),r6
	br       .WLL502

.WLL4412:
        # Write Register ADCA1
	movd     $(0xfffff040),r6
	br       .WLL502

.WLL4413:
        # Write Register ADRA1
	movd     $(0xfffff044),r6
	br       .WLL502

.WLL4414:
        # Write Register ADCB1
	movd     $(0xfffff048),r6
	br       .WLL502

.WLL4415:
        # Write Register ADRB1
	movd     $(0xfffff04c),r6
	br       .WLL502

.WLL4416:
        # Write Register BLTC1
	movd     $(0xfffff050),r6
	br       .WLL502

.WLL4417:
        # Write Register BLTR1
	movd     $(0xfffff054),r6
	br       .WLL502

.WLL4418:
        # Write Register MODE1
	movd     $(0xfffff058),r6
	br       .WLL502

.WLL4419:
        # Write Register CNTL1
	movd     $(0xfffff05c),r6
	br       .WLL502

.WLL451:
        # Write Register IVCT
	movd     $(0xfffffe00),r6
	br       .WLL501

.WLL452:
        # Write Register ISRV
	movd     $(0xfffffe04),r6
	br       .WLL501


.WLL461:
        # Write Register TC0
	movd     $(0xfffff810),r6
	br       .WLL501

.WLL462:
        # Write Register TRCA0
	movd     $(0xfffff814),r6
	br       .WLL501

.WLL463:
        # Write Register TRCB0
	movd     $(0xfffff818),r6
	br       .WLL501

.WLL464:
        # Write Register TCNT0
	movd     $(0xfffff81c),r6
	br       .WLL501

.WLL465:
        # Write Register TC1
	movd     $(0xfffff820),r6
	br       .WLL501

.WLL466:
        # Write Register TRCA1
	movd     $(0xfffff824),r6
	br       .WLL501

.WLL467:
        # Write Register TRCB1
	movd     $(0xfffff828),r6
	br       .WLL501

.WLL468:
        # Write Register TCNT1
	movd     $(0xfffff82c),r6
	br       .WLL501

.WLL469:
        # Write Register TC2
	movd     $(0xfffff830),r6
	br       .WLL501

.WLL4610:
        # Write Register TRCA2
	movd     $(0xfffff834),r6
	br       .WLL501

.WLL4611:
        # Write Register TRCB2
	movd     $(0xfffff838),r6
	br       .WLL501

.WLL4612:
        # Write Register TCNT2
	movd     $(0xfffff83c),r6
	br       .WLL501

.WLL500:
	movb     0(r7),0(r6)
	br	.WLL6

.WLL501:
	movw     0(r7),0(r6)
	br	.WLL6

.WLL502:
	movd     0(r7),0(r6)
	br	.WLL6


.WLL7:
	movd	%regnumber,r6
	cmpd	$(REG_R0_NUM),r6
	bgt	.WLL54
	cmpd	$(REG_TCNT2_NUM),r6
	blt	.WLL54
.WLP4:
	casew	.WLP3[r6:w]

.WLL57:
        # FPU register was modified reload fsr register
	lfsr	 %save_reg_fsr
 
.WLL54:
.WLL6:
	# Return to monitor loop
	br	.LL6

	# writeregister branch table 
	.align 4
.WLP3:
	.word	.WLL8  - .WLP4
	.word	.WLL9  - .WLP4
	.word	.WLL10 - .WLP4
	.word	.WLL11 - .WLP4
	.word	.WLL12 - .WLP4
	.word	.WLL13 - .WLP4
	.word	.WLL14 - .WLP4
	.word	.WLL15 - .WLP4
	.word	.WLL16 - .WLP4
	.word	.WLL17 - .WLP4
	.word	.WLL18 - .WLP4
	.word	.WLL19 - .WLP4
	.word	.WLL20 - .WLP4
	.word	.WLL21 - .WLP4
	.word	.WLL22 - .WLP4
	.word	.WLL23 - .WLP4
	.word	.WLL24 - .WLP4
	.word	.WLL25 - .WLP4
	.word	.WLL26 - .WLP4
	.word	.WLL27 - .WLP4
	.word	.WLL28 - .WLP4
	.word	.WLL29 - .WLP4
	.word	.WLL30 - .WLP4
	.word	.WLL31 - .WLP4
	.word	.WLL32 - .WLP4
	.word	.WLL33 - .WLP4
	.word	.WLL34 - .WLP4
	.word	.WLL35 - .WLP4
	.word	.WLL36 - .WLP4
	.word	.WLL37 - .WLP4
	.word	.WLL38 - .WLP4
	.word	.WLL39 - .WLP4
	.word	.WLL40 - .WLP4
	.word	.WLL41 - .WLP4
	.word	.WLL42 - .WLP4
	.word	.WLL431 - .WLP4
	.word	.WLL432 - .WLP4
	.word	.WLL433 - .WLP4
	.word	.WLL434 - .WLP4

        .word   .WLL441 - .WLP4
        .word   .WLL442 - .WLP4
        .word   .WLL443 - .WLP4
        .word   .WLL444 - .WLP4
        .word   .WLL445 - .WLP4
        .word   .WLL446 - .WLP4
        .word   .WLL447 - .WLP4
        .word   .WLL448 - .WLP4
        .word   .WLL449 - .WLP4
        .word   .WLL4410 - .WLP4
        .word   .WLL4411 - .WLP4
        .word   .WLL4412 - .WLP4
        .word   .WLL4413 - .WLP4
        .word   .WLL4414 - .WLP4
        .word   .WLL4415 - .WLP4
        .word   .WLL4416 - .WLP4
        .word   .WLL4417 - .WLP4
        .word   .WLL4418 - .WLP4
        .word   .WLL4419 - .WLP4
        .word   .WLL451 - .WLP4
        .word   .WLL452 - .WLP4
        .word   .WLL461 - .WLP4
        .word   .WLL462 - .WLP4
        .word   .WLL463 - .WLP4
        .word   .WLL464 - .WLP4
        .word   .WLL465 - .WLP4
        .word   .WLL466 - .WLP4
        .word   .WLL467 - .WLP4
        .word   .WLL468 - .WLP4
        .word   .WLL469 - .WLP4
        .word   .WLL4610 - .WLP4
        .word   .WLL4611 - .WLP4
        .word   .WLL4612 - .WLP4
#**********************************************************************#

#**********************************************************************#
# Transfer count number of bytes from processor io space to monitor data_buf
#
# READIOSPACE

	.align 4
readiospace:
	movd	 %start_addr,r7   # Source address
	addr	 %data_buf,r6     # Destination address

	cmpqd	 $(BYTEACCESS),%accessmode
	beq	 transferbytes

	cmpqd	 $(WORDACCESS),%accessmode
	beq	 transferwords

	cmpqd	 $(DOUBLEACCESS),%accessmode
	beq	 transferdoubles
#**********************************************************************#

#**********************************************************************#
#
# WRITEIOSPACE

	.align 4
writeiospace:
# Transfer count number of bytes from monitor data_buf to processor io space

	addr	 %data_buf,r7      # Source address
	movd	 %start_addr,r6    # Destination address

	cmpqd	 $(BYTEACCESS),%accessmode
	beq	 transferbytes

	cmpqd	 $(WORDACCESS),%accessmode
	beq	 transferwords

	cmpqd	 $(DOUBLEACCESS),%accessmode
	beq	 transferdoubles
#**********************************************************************#

#**********************************************************************#
#
# TRANSFERBYTES

	.align 4
transferbytes:
	movqd	 $(0),r5
	cmpd	 r5,%count
	bhs	 .TB34
.TB35:
	movb     0(r7),0(r6)
	addqd	 $(1),r7
	addqd	 $(1),r6
	addqd	 $(1),r5
	cmpd	 r5,%count
	blo	 .TB35
.TB34:
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# TRANSFERWORDS

	.align 4
transferwords:
	movqd	 $(0),r5
	cmpd	 r5,%count
	bhs	 .TW34
.TW35:
	movw     0(r7),0(r6)
	addqd	 $(2),r7
	addqd	 $(2),r6
	addqd	 $(2),r5
	cmpd	 r5,%count
	blo	 .TW35
.TW34:
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
#
# TRANSFERDOUBLES

	.align 4
transferdoubles:
	movqd	 $(0),r5
	cmpd	 r5,%count
	bhs	 .TD34
.TD35:
	movd     0(r7),0(r6)
	addqd	 $(4),r7
	addqd	 $(4),r6
	addqd	 $(4),r5
	cmpd	 r5,%count
	blo	 .TD35
.TD34:
	# Return to monitor loop
	br	.LL6
#**********************************************************************#

#**********************************************************************#
# Transfer count number of bytes from target to monitor data_buf
#
# READTARGETMEM

	.align 4
readtargetmem:
	movd	 %start_addr,r7   # Source address
	addr	 %data_buf,r6     # Destination address
	movqd    $(1),r4
	addr     %targetreadmop,r5

	cmpqd	 $(BYTEACCESS),%accessmode
	bne	 .RT01

	# BYTE Accessmode
	movqd    $(1),r4
	movb     $(0x94),0(r5)   # movb  0(r7),0(r6)
	br	 .RT03

.RT01:
	cmpqd	 $(WORDACCESS),%accessmode
	bne	 .RT02

	# WORD Accessmode
	movqd    $(2),r4
	movb     $(0x95),0(r5)   # movw  0(r7),0(r6)
	br	 .RT03

.RT02:
	cmpqd	 $(DOUBLEACCESS),%accessmode
	bne	 .RT03

	# DOUBLE Accessmode
	movb     $(0x97),0(r5)   # movd  0(r7),0(r6)
	movqd    $(4),r4

.RT03:
	movqd	 $(0),r5
	cmpd	 r5,%count
	bhs	 .RT04
.RT05:
        # read count number of bytes using selected access mode
	br	 targetreadmop
.RT06:
	addd	 r4,r7
	addd	 r4,r6
	addd	 r4,r5
	cmpd	 r5,%count
	blo	 .RT05
.RT04:
	br	.LL6
#**********************************************************************#

#**********************************************************************#
# Transfer count number of bytes from monitor data_buf to target memory
#
# WRITETARGETMEM

	.align 4
writetargetmem:
	addr	 %data_buf,r7      # Source address
	movd	 %start_addr,r6    # Destination address
	movqd    $(1),r4
	addr     %targetwritemop,r5

	cmpqd	 $(BYTEACCESS),%accessmode
	bne	 .WT01

	# BYTE Accessmode
	movqd    $(1),r4
	movb     $(0x94),0(r5)   # movb  0(r7),0(r6)
	br	 .WT03

.WT01:
	cmpqd	 $(WORDACCESS),%accessmode
	bne	 .WT02

	# WORD Accessmode
	movqd    $(2),r4
	movb     $(0x95),0(r5)   # movw  0(r7),0(r6)
	br	 .WT03

.WT02:
	cmpqd	 $(DOUBLEACCESS),%accessmode
	bne	 .WT03

	# DOUBLE Accessmode
	movb     $(0x97),0(r5)   # movd  0(r7),0(r6)
	movqd    $(4),r4

.WT03:
	movqd	 $(0),r5
	cmpd	 r5,%count
	bhs	 .WT04
.WT05:
        # read count number of bytes using selected access mode
	br	 targetwritemop
.WT06:
	addd	 r4,r7
	addd	 r4,r6
	addd	 r4,r5
	cmpd	 r5,%count
	blo	 .WT05
.WT04:
	br	.LL6
#**********************************************************************#

#**********************************************************************#
# Variables used internally and can be anywhere are in the text space
			.align 4
return_stack:           .double 0  # u_int32
save_reg_fsr:           .double 0  # u_int32
jam_value:              .double 0  # u_int32
mask: 			.double 0  # u_int32
mask_1:	  		.double 0  # u_int32
mask_2:	  		.double 0  # u_int32
mask_3:  		.double 0  # u_int32
singlestep:             .byte FALSE  # u_int8

# Variables which are communicated with externally are predefined addresses
# monitor data space is linked at 0xc00

		.data

#**********************************************************************#
# The bottom 128 bytes (0c00..0c7f) are used for a default dispatch table  
# The middle 128 bytes (0c80..0cff) are used for a monitor stack
# The upper 128 bytes (0d00..0d7f) are used for default stack space

# ADDRESS = 0xc00

		.space 256
TOP_OF_MONSTACK:
		.space 128
TOP_OF_STACK:
#**********************************************************************#

#**********************************************************************#
# This area contains all monitor variables.  All must remain at a known
# offset to be accessible by the controller.
# ADDRESS = 0xd80

CMD_BLOCK:
cmd_num: 	.double NO_CMD     # 0xd80  u_int32  
count:	 	.double 0   	   # 0xd84  u_int32
start_addr: 	.double 0          # 0xd88  u_int32 *
hw_config:      .double 0          # 0xd8c  u_int32
accessmode:	.double BYTEACCESS # 0xd90  u_int32
functioncode:   .double SUPER_FC   # 0xd94  u_int32
regnumber: 	.double 0          # 0xd98  u_int32
loadaddress: 	.double procreset  # 0xd9c  u_int32
defregisters:   .double 0          # 0xda0  u_int32
psrmask:        .double 0          # 0xda4  u_int32

                .space  3          # 0xda8
dummy1:         .byte   0          # 0xdab
iob_signals:    .byte   0          # 0xdac  u_int8 
		.byte   0 
		.byte   0
dummy2:         .byte   0          # 0xdaf

# ADDRESS = 0xdb0

STATUS_BLOCK:
semaphore:	.byte NO_CMD       # 0xdb0  u_int8 
are_you_there:  .byte RESPOND      # 0xdb1  u_int8
running:        .byte FALSE        # 0xdb2  u_int8

		.align 4
mon_entry:	.double h'80000000 # 0xdb4  u_int32
monentrybit:	.double CHECKED_ENTRY
		.double 0          # space saver

# ADDRESS = 0xdc0

		.align 4
DATA_BUF:
data_buf: 	.space 300         # 0xdc0  u_int8 [300]

# ADDRESS = 0xeec
		.align 4
REGISTERS:
REG_R0:		.double 0 
REG_R1: 	.double 0
REG_R2: 	.double 0
REG_R3: 	.double 0
REG_R4: 	.double 0
REG_R5: 	.double 0
REG_R6: 	.double 0
REG_R7: 	.double 0
REG_PC: 	.double 0
REG_SP: 	.double 0
REG_SP0: 	.double 0
REG_SP1: 	.double 0
REG_PSR: 	.word   0
REG_CFG: 	.double 0
REG_FP: 	.double 0
REG_SB: 	.double 0
REG_INTBASE: 	.double 0
REG_MOD: 	.word   0

# ADDRESS = 0xf30

# This 128 byte area is used as the stack for saving PC, PSR, and MOD
# during exception processing of break induced NMI
# During the jam into the monitor this area will be the interrupt
# stack used for saving the PC, PSR, and MOD depending on the
# exception mode.  This area will also be used during exit from
# the monitor, again as the interrupt stack area.  The return PC,
# PSR, and optionally the MOD will be read from this area.

# ADDRESS = 0x7f80
		.bss JAMIN_STACK, 64, 2


# This 128 byte area is used as the dispatch vector table
# during exception processing of break induced NMI
# During the jam into the monitor this area will be read to 
# determine the address of the monitor breakentry entry point.
# During this time only the least significant 7 bits of the  
# address bus are used.

# ADDRESS = 0x7fc0
		.bss JAMOUT_STACK, 64, 2
