 #*****************************************************************************
 #
 #                              Traps_ext
 #
 # This module contains the trap handler routines of CMON.
 # It does what has to be done in assembly, and then calls the appropriate 
 # function in traps.c .
 # 
 # NOTE: Do not add any PC relative code or variables before the "_reset__"
 #       label. _reset__ has to be the start of code!!!
 #
 # Note that comment lines must begin with a blank so cpp will not regard 
 # them.
 #
 # History:
 #   +----------+------------+------------------------------------------------+
 #   |   Date   |     by     |     Description                                |
 #   +----------+------------+------------------------------------------------+
 #   |          | Coby       | Written                                        |
 #   +----------+------------+------------------------------------------------+
 #
 #*****************************************************************************


        .file        "sf_reset.s"


#include "global.h"
#include "reset.h"

 #-----------------------------------------------------------------------------
 #                                 
 #                                 Variable definitions
 # 
 #-----------------------------------------------------------------------------

 #
 # The possible execution modes.
 #

#ifndef public

#define USER_TIME 0
#define MON_TIME  1

#endif

 #
 # The possible trace modes.
 #

#ifndef public

#define NON_CMON_TRACE      0
#define STEP_N              1
#define WATCH               2
#define STEP_BEFORE_GO      3
#define STEP_BEFORE_STEP_N  4
#define STEP_BEFORE_WATCH   5

#endif

    .globl      init_cpu__
    .globl      save_user_cpu_regs, load_user_cpu_regs
    .globl      _cont_reset__, _cont_nmi_user__, _cont_trace__, _cont_bpt__
    .globl      _cont_abort__, _cont_misc_traps__

    .comm       _cmon_sp__,4
    .comm       _cmon_fp__,4
    .comm       temp,4

#ifdef DEBUG
 # Macros to allow full monitor debbuging
 # perform interrupt dispatch table switch
 # while in application time intbase points to cmon dispatch table
 # while in cmon time intbase points to burned monitor dispatch table

#ifdef	SIM_32K
 #
 # In case of simulation we also have to save two temporary scratch that are
 # used by both monitor and application
 #
    .bss sb_1000 ,4,4
    .bss sb_1004 ,4,4
    
    .macro  SAVE_SCRATCH
	    movd    1000(sb), sb_1000
	    movd    1004(sb), sb_1004
    .endm
    .macro  LOAD_SCRATCH
	    movd    sb_1000, 1000(sb)
	    movd    sb_1004, 1004(sb)
    .endm
    
	
#else
    .macro  SAVE_SCRATCH
    .endm
    .macro  LOAD_SCRATCH
    .endm

#endif /* SIM_32K */
      
    .comm       _ram_intbase__,4
    .comm       _rom_intbase__,4

    .macro         DEBUG_CMON    
				 spr     intbase, r15
				 stord	r15, _ram_intbase__
                                 loadd	_rom_intbase__, r15
                                 lpr    r15, intbase        
				 SAVE_SCRATCH
    .endm

    .macro         END_DEBUG_CMON 
				 spr     intbase, r15
				 stord	r15, _rom_intbase__
                                 loadd	_ram_intbase__, r15
                                 lpr    r15, intbase        
				 LOAD_SCRATCH
    .endm



    .globl _START_BSS__
    .globl _END_BSS__

#else

#   define  DEBUG_CMON
#   define  END_DEBUG_CMON 
#endif
#ifdef SIM_32K
	
	#
	#  The monitors allocates a buffer to no existent SF register on 32K
	#  The SB will be initialized to this buffer and this buffer will be 
	#  used by both the application and the monitor.
	#
	
	.comm _memory_mapped_reg__, 1100
#endif



 #----------------------------------------------------------------------------
 #                   Macro definitions 
 #----------------------------------------------------------------------------
 

 #
 # Calls to save / restore  user registers
 #  It is assumed that r15 is the only register free for usage in this macro.
 #
 
count := 0

.macro	save_user_reg
	    bal	    r15, save_user_cpu_regs
	    spr	    cfg, r0			# test FPU bit on cfg
	    tbit    $(CFG_F), r0
	    bfc	    cont_save{count}
	    bal	    r15, save_user_float__
	cont_save{count}:
	count := {{count} + 1}
.endm

.macro	load_user_reg
	    spr		cfg, r0			# test FPU bit on cfg
	    tbit	$(CFG_F), r0
	    bfc		cont_load{count}
	    bal		r15, restore_user_float__
	cont_load{count}:
	    bal		r15, load_user_cpu_regs	# restore the users registers
	count := {{count} + 1}
.endm

.macro  interrupt_disable
	 spr		psr, r15
	 andw		$(0xf7ff),r15, r15
	 lpr		r15, psr
.endm
	    
 #/*^L*/
 #-----------------------------------------------------------------------------
 #          
 #                             Reset
 #
 # This is the reset routine. It activates the board specific initialization
 # and other initialization routines.
 # Note: Do not touch R0 and R1 until the init_cpu routine has been called.
 #       these registers contain important information in the 532.
 #
 #-----------------------------------------------------------------------------


_reset__::
#ifndef DEBUG

     #
     # Upon startup the ROM address space is mapped to 0. The branch 
     # causes the PC to point to the ROM.
     #
     # ROM_START is defined in the board definition file.

        ord         $rom_entry,  c0,  r0
        jump        r0

	#	br      ROM_START + rom_entry

rom_entry:

     #
     # This macro should turn the shadow feature off
     # it is defined in the board definition file
     #

	TURN_OFF_SHADOW	    


#else


     #
     # fills all bss with 0xffffffff 
     # 
	ord	$_START_BSS__, c0, r0
	ord	$_END_BSS__, c0  ,r1
	ord    $0xffffffff, c0, r2
fill_loop:
	stord	r2 ,0(r0)
	addd	$4, r0, r0
	cmpd	r0, r1, c0
	blt		fill_loop
#endif

	JMP_TO_DIAGNOS

	br          init_cpu__             # init user and CMON cpu registers
end_init_cpu__::
 #
 # Initialize global variables
 #

	bal	    r15, _init_data__
	ord        $dispatch_table__, c0  , r0
	stord	    r0, _cmon_de_intbase__

	bal	    r15, _init_sio__

	ord       $RESET, c0, r0
	stord	    r0, _reset_type__    # signal that it was a reset
	bal         r15, _cont_reset__   # continue in C

 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                                Nmi and Dbg
 #
 # These are the NMI and DBG routines. They are very simmilar and so, are 
 # written together.
 # They can be reached because of an outside trigger.
 #
 #-----------------------------------------------------------------------------

nmi_routine__::
    stord	r15, _save_R15__
    DEBUG_CMON
    ord		$1, c0, r15
    stord       r15, _pending_flag__	# signal a possible pending interrupt
    ord		$NMI, c0, r15
    stord	r15, _reset_type__      # signal that it was an nmi trap
    br          nmi_and_dbg

dbg_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$DBG, c0, r15
    stord	r15, _reset_type__	# signal that it was an dbg trap

nmi_and_dbg:
    spr		isp, r15
    loadd	0(r15), r15
    cmpd	$_START_TXT__, r15, c0
    bhs		user_time

    cmpd	$_END_TXT__, r15, c0
    blo		user_time
mon_time:
    loadd	 _exec_mode__,r15
    cmpb        $MON_TIME, r15, c0
    beq         nmi_mon_time		# if (trapped in monitor time)

    br		exit_cmon
user_time:
    save_user_reg			#   save users cpu regs, load cmon's
    bal         r15, _cont_nmi_user__	#   cont_nmi_user__()
nmi_mon_time:				# 
    bal         r15, _cont_reset__	# cont_reset__()





 #-----------------------------------------------------------------------------
 #
 #                                Trace 
 #
 # This is the trace routine. It is triggered because a single step ended.
 # Note that we do not enter monitor time immediately. First we have to check
 # why we stepped and if we need to continue stepping.
 #
 #-----------------------------------------------------------------------------

trc_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON		
    save_user_reg			# save users cpu regs, load cmon's
    bal		r15, _cont_trace__	# cont_trace__()





 #-----------------------------------------------------------------------------
 #
 #                                Breakpoint
 #
 # This is the breakpoint routine. It is triggered because of software 
 # breakpoints.
 #
 #-----------------------------------------------------------------------------

bpt_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    save_user_reg			# save users cpu regs, load cmon's
    bal		r15, _cont_bpt__	# cont_bpt__()




 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                                Supervisor call
 #
 # This is the supervisor call routine.
 # Upon entring to the svc,  volatile registers are saved.
 #
 #-----------------------------------------------------------------------------

svc_routine__::
    stord	r15, _save_R15__
    DEBUG_CMON
#ifdef	SIM_32K
    bispsrw	$0x200			# Force clear bit
#endif
    stord	SP, _save_R30__

    loadd	 _cmon_sp__,SP		# load CMON Stack

    subd	$(0x48), SP, SP		# allocate 18 Double words on stack

    stord   r4,0x18(SP)			# Save volatile registers
    stord   r5,0x1c(SP)
    stord   r6,0x20(SP)
    stord   r7,0x24(SP)
    stord   r16,0x28(SP)
    stord   r17,0x2c(SP)
    stord   r18,0x30(SP)
    stord   r19,0x34(SP)
    stord   r20,0x38(SP)
    stord   r21,0x3c(SP)
    stord   r22,0x40(SP)
    stord   r23,0x44(SP)

    spr		  isp, r4
    loadd	4(r4),r5		# load r5 with user PSR
    loadd	0(r4), r4		# load r4 with user PC
    stord	r5, 0x14(SP)		# store PSR on CMON stack
    stord	r4, 0x10(SP)		# store PC on CMON stcak
    
svca:		
	    # Save r0-r3 on stack. These registers
	    # contains the input for the svc's

    stord	r0, 0xc(SP)
    stord	r1, 0x8(SP)
    stord	r2, 0x4(SP)
    stord	r3, 0x0(SP)
    
    ord		SP, c0, r4		# This current sp will be the only
					# parameter for svc_main__. It will be
					# used as a pointer to a structure of
					# saved regs.
					
    bal		r15, _svc_main__	# call the main svc routine
    cmpd	c0, r0, c0		# Check return code
    bne         svcerr			# if not 0 (NULL) there is an error

	    # restore r0-r3 from stack.
    loadd	0xc(SP), r0
    loadd	0x8(SP), r1
    loadd	0x4(SP), r2
    loadd	0x0(SP), r3

    loadd	0x14(SP), r5		# load PSR value to r5
    loadd	0x10(SP), r4		# load PC value to r4

    spr		isp, r6			# r6 = Top of stack
    cmpb        $11, r0, c0		# Was this svc 11 ?
    bne         svcext			# No - do nothing
    addd	$(-8), r6, r6		# allocate space to  another PSR PC
    lpr		 r6, isp		# On stack.
svcext:        
    stord	r5, 4(r6)		# restore PSR value to the stack
    stord	r4, 0(r6)		# restore PC value to the stack

    loadd   0x18(SP), r4		# restore r4-r7 r16-r23
    loadd   0x1c(SP), r5
    loadd   0x20(SP), r6
    loadd   0x24(SP), r7
    loadd   0x28(SP), r16
    loadd   0x2c(SP), r17
    loadd   0x30(SP), r18
    loadd   0x34(SP), r19
    loadd   0x38(SP), r20
    loadd   0x3c(SP), r21
    loadd   0x40(SP), r22
    loadd   0x44(SP), r23
    END_DEBUG_CMON
    loadd	_save_R15__, r15	# restore original r15
    loadd	_save_R30__, SP		# restore original r30
    retx        			# return from svc

svcerr:
    .bss	svc_err_ptr,4,4
    stord	r0,svc_err_ptr		# store svc err msg pointer
	    
    loadd   0xc(SP), r0			# restore r0-r3 from stack.
    loadd   0x8(SP), r1
    loadd   0x4(SP), r2
    loadd   0x0(SP), r3
    
    loadd   0x18(SP),  r4               # restore r4-r7 r16-r23
    loadd   0x1c(SP),  r5
    loadd   0x20(SP),  r6
    loadd   0x24(SP),  r7
    loadd   0x28(SP),  r16
    loadd   0x2c(SP),  r17
    loadd   0x30(SP),  r18
    loadd   0x34(SP),  r19
    loadd   0x38(SP),  r20
    loadd   0x3c(SP),  r21
    loadd   0x40(SP),  r22
    loadd   0x44(SP),  r23

    loadd	_save_R15__, r15	# restore original r15
    loadd	_save_R30__, SP		# restore original r30
    save_user_reg			# save users cpu regs, load cmon's
    
    loadd	svc_err_ptr, r4		# parameter svc err msg pointer
    br		_cont_svc_err__		# cont_svc_err__(svc_err_ptr)
        
        
        
 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                           Miscellaneous traps
 #
 # These routines treat the traps which aren't used by cmon. 
 # They place a signal on the stack (since we didn't save the SB and other
 # registers yet). Then they jump to a common routine.
 #
 #-----------------------------------------------------------------------------

nvi_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$NVI_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine      
fpu_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$FPU_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine            
ill_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON          
    ord		$ILL_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine
dvz_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$DVZ_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine
flg_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$FLG_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine
und_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$UND_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine
rbe_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$RBE_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine
nbe_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$NBE_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine
ovf_routine__::
    stord	r15, _save_R15__
    interrupt_disable
    DEBUG_CMON
    ord		$OVF_TRAP, c0, r15
    stord	r15, _trap_type__
    br          misc_trap_routine



 #-----------------------------------------------------------------------------
 #
 #                           Misc_trap_routine
 #
 # This routine treat the traps which aren't used by cmon. 
 # It receives the trap type on the stack. 
 # If the trap happened when we were in monitor mode (relevant for UND and RBE)
 # there is no need to save the user registers. Instead, reload cmon's default
 # values.
 #
 #-----------------------------------------------------------------------------

misc_trap_routine:
    loadd	_exec_mode__, r15
    cmpd	$MON_TIME, r15, c0	# if (NOT monitor time) {
    beq         misc_trap_mon		#
    save_user_reg			#   save users cpu regs, load cmon's
    br          misc_trap_end		# }
misc_trap_mon:				# else {
    loadd       _cmon_sp__, SP		#   load cmon sp
misc_trap_end:				# }
    bal		r15, _cont_misc_traps__	# cont_misc_traps__()








 #-----------------------------------------------------------------------------
 #
 #                           Leave_cmon__
 #
 # This routine is called from the C function return_to_user__. It finishes 
 # the return.
 #
 #-----------------------------------------------------------------------------

_leave_cmon__::
    load_user_reg
exit_cmon:
    END_DEBUG_CMON
    loadd	_save_R15__, r15
    retx				# return from trap
 #/*^L*/

 #
 # The interrupt dispatch table 
 #

    .align 4

dispatch_table__::
    .double     0
    .double     nmi_routine__
    .double     0
    .double     fpu_routine__
    .double     ill_routine__
    .double     svc_routine__
    .double     dvz_routine__
    .double     flg_routine__
    .double     bpt_routine__
    .double     trc_routine__
    .double     und_routine__
    .double     0
    .double     0
    .double     ovf_routine__
    .double     dbg_routine__
    .double     _reset__

    .align 8
