 #*****************************************************************************
 #
 #                              Reset
 #
 # 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        "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__

#ifdef DSPM_SUPPORT
    .globl	_place_back_dspm_bpt__ 
    .comm	_clptr__,4
    .comm	_dspm_nmi__,1
#endif

    .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
         
    .comm       _ram_intbase__,4
    .comm       _rom_intbase__,4
#   define         DEBUG_CMON      sprd    intbase,_ram_intbase__        \
                                 lprd    intbase,_rom_intbase__        


#   define         END_DEBUG_CMON  sprd    intbase,_rom_intbase__        \
                                 lprd    intbase,_ram_intbase__        
    .globl _START_BSS__
    .globl _END_BSS__

#else

#   define  DEBUG_CMON
#   define  END_DEBUG_CMON 
#endif

.macro interrupt_disable
	bicpsrw	$(0x800)
.endm

    .udata
ram_module_table__::
    .blkd       4

#ifndef public
#if (ROM_START < 0x10000)
#       define CMON_MOD rom_module_table__
#else
#       define CMON_MOD ram_module_table__
#endif
#endif

    .text


 #/*^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.
 #
 #-----------------------------------------------------------------------------

        .align        4

_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.

	movd	$rom_entry, r0
	jump	0(r0)

rom_entry:

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

	TURN_OFF_SHADOW	    
     #
     # The following command will cause a trap if it is reached 
     # in user mode, by mistake.
     #

	#bicpsrw     $0x200

     #
     # Execute board specific initialization. The label name after the
     # branch must not be changed. It is used to jump back.
     #

#else 
     #
     # fills all bss with 0xffffffff 
     # 
	addr	_START_BSS__,r0
	addr	_END_BSS__ ,r1
fill_loop:
	movd	$0xffffffff,0(r0)
	addqd	4,r0
	cmpd	r0,r1
	blt		fill_loop
#endif
	LED(LED_1)

#ifndef DEBUG
	.comm 	    _pu_pattern__,4
	movd	    _pu_pattern__, r5	   # detect a power up reset
	movd	    $0x96a5d30f, r6
	cmpd	    r5, r6
	JMP_TO_DIAGNOS			   # (bne _start_pu__) and do pu diag
#endif

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

	LED(LED_2)
	bsr	    _init_data__
	addr        rom_module_table__,_cmon_mod__
	addr        normal_intbase__,_cmon_normal_intbase__
	addr        de_intbase__,_cmon_de_intbase__

	LED(LED_3)
#ifndef DEBUG
	bsr	_init_sio__
#endif

	LED(LED_4)
	movqd       RESET,_reset_type__    # signal that it was a reset
	bsr         _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. Dbg can be reached in
 # the 532 also by a hardware breakpoint.
 #
 #-----------------------------------------------------------------------------

nmi_routine__::
    DEBUG_CMON
    movqd       1,_pending_flag__	# signal a possible pending interrupt
    movqd       NMI,_reset_type__	# signal that it was an nmi trap
    br          nmi_and_dbg

dbg_routine__::
    interrupt_disable
    DEBUG_CMON
    movqd       DBG,_reset_type__	# signal that it was a dbg trap

nmi_and_dbg:
    #
    # Check if traped in user time or monitor time
    #
    cmpd	0(sp), $_START_TXT__
    blo	        user_time
    cmpd	0(sp), $_END_TXT__
    bhs		user_time
mon_time:
    cmpqb       MON_TIME,_exec_mode__	#
    beq         nmi_mon_time		# 

    br          exit_cmon	    	# return to prev activation of cmon;

user_time:
    bsr         save_user_cpu_regs	#   save users cpu regs, load cmon's
    bsr         _cont_nmi_user__	#   cont_nmi_user__()

nmi_mon_time:				# }
    bsr         _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__::
    interrupt_disable
    DEBUG_CMON
trc_routine1:
    bsr         save_user_cpu_regs     # save users cpu regs, load cmon's
    bsr         _cont_trace__          # cont_trace__()





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

bpt_routine__::
    interrupt_disable
    DEBUG_CMON
    bsr         save_user_cpu_regs     # save users cpu regs, load cmon's
    bsr         _cont_bpt__            # cont_bpt__()

 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                                Abort
 #
 # This is the abort routine. It is triggered by the MMU's because of memory
 # protection, invalid page or hardware breakpoint.
 #
 #-----------------------------------------------------------------------------

abt_routine__::
    DEBUG_CMON
    tbitd       $PSR_U,6(sp)		# if (NOT psr u) { /* super mode */
    bfs         abt1			# 

 #
 # If the abort occured on the rett instruction, the PSR-MOD-PC on the
 # stack are cmon's. We need to remove them to reach the PSR-MOD-PC of
 # the user (that were placed there just before the rett).
 #

    addr        exit_cmon,temp		# if (abort address == rett of cmon) {
    cmpd        0(sp),temp		# 
    bne         abt1			#
    adjspb      $-8			#   remove return address of cmon
abt1:					# }
    cmpqd       USER_TIME,_exec_mode__	# if (trap didn't occur in user time) 
    bne         exit_cmon		#   return to prev activation of cmon;
    bsr         save_user_cpu_regs	# save users cpu regs, load cmon's
    bsr         _cont_abort__		# cont_abort__()





 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                                Supervisor call
 #
 # This is the supervisor call routine.
 #
 #-----------------------------------------------------------------------------

svc_routine__::
    DEBUG_CMON
    cmpb        r0,$11                 # Is this svc 11 ?
    bne         svca                   # No - do nothing
    movd        4(sp),tos              # Duplicate the saved pc and psr/mod
    movd        4(sp),tos              # on stack. This duplicated value are
                                       # going to be overriden by value of
                                       # a trap routine that will later on will
                                       # return to the svc issuer
svca:        
    save        [r0,r1,r2,r3]          # Push r0-r3 on stack. These registers
                                       # contains the input for the svc's
    sprd        sp,tos                 # This current sp will be the only
                             # parameter for svc_main__. It will be used
                             # As a pointer to a structure of saved regs.
    bsr         _svc_main__            # call the main svc routine
    adjspb      $-4                    # remove the parameter from stack
    cmpqb       0,r0                   # Check return code
    bne         svcerr                 # if not 0 (NULL) there is an error
    restore     [r0,r1,r2,r3]          # Restore r0-r3
    cmpb        r0,$10                 # Was this svc 10 ?
    bne         svcext                 # No - do nothing
    movd        32(sp),r1              # Restore r0,r1 without changing the
    movd        36(sp),r0              # sp
    movd        tos,32(sp)             # Move the saved pc mod and psr to their
    movd        tos,32(sp)             # new locations
    restore     [r2,r3,r4,r5,r6,r7]    # Now r2-r7 can be restored too
        
svcext:        
    END_DEBUG_CMON
    rett        0                      # return from svc

svcerr:
    .bss        svc_err_ptr,4,4
    movd        r0,svc_err_ptr         # store svc err msg pointer (returned by
                                       # svc_main__)
    restore     [r0,r1,r2,r3]          # restore user registers
    bsr         save_user_cpu_regs     # save users cpu regs, load cmon's
    movd        svc_err_ptr,tos        # push svc err msg pointer
    bsr         _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__::
    interrupt_disable
    DEBUG_CMON
    movd       $NVI_TRAP,tos
    br          misc_trap_routine      
fpu_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $FPU_TRAP,tos
    br          misc_trap_routine            
ill_routine__::
    interrupt_disable
    DEBUG_CMON          
    movd        $ILL_TRAP,tos
    br          misc_trap_routine
dvz_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $DVZ_TRAP,tos
    br          misc_trap_routine
flg_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $FLG_TRAP,tos
    br          misc_trap_routine
und_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $UND_TRAP,tos
    br          misc_trap_routine
rbe_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $RBE_TRAP,tos
    br          misc_trap_routine
nbe_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $NBE_TRAP,tos
    br          misc_trap_routine
ovf_routine__::
    interrupt_disable
    DEBUG_CMON
    movd        $OVF_TRAP,tos
    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:
    movd        tos,_trap_type__       # trap_type = parameter from stack
    cmpqd       MON_TIME,_exec_mode__  # if (NOT monitor time) {
    beq         misc_trap_mon          #
    bsr         save_user_cpu_regs     #   save users cpu regs, load cmon's
    br          misc_trap_end          # }
misc_trap_mon:                         # else {
    lprw        psr,$0		       #   load cmon psr
    lprd        sp,_cmon_sp__          #   load cmon sp
    lprd        fp,_cmon_fp__          #   load cmon fp
misc_trap_end:                         # }
    bsr         _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__::
#ifdef DSPM_SUPPORT
    bsr		_place_back_dspm_bpt__
#endif

    bsr         load_user_cpu_regs     # restore the users registers
exit_cmon:
    END_DEBUG_CMON
#ifdef DSPM_SUPPORT
    cmpb	$1, _dspm_nmi__	       # Did we stopped in DSPM breakpoint
    bne		exit_cmon1
    movb	$0, _dspm_nmi__		
    movw	_clptr__, @CLPTR_REG_ADDR    # Activate the DSPM
exit_cmon1:
#endif
    rett        0                      # return from trap
 #/*^L*/
 #
 # The interrupt dispatch table in the form of a link table.
 # Note that the first word in each two word entry should contain the
 # address of the module table. 
 #

.align 4
normal_intbase__::
    .word       CMON_MOD
    .word       nvi_routine__-_reset__
    .word       CMON_MOD     
    .word       nmi_routine__-_reset__
    .word       CMON_MOD     
    .word       abt_routine__-_reset__
    .word       CMON_MOD     
    .word       fpu_routine__-_reset__
    .word       CMON_MOD     
    .word       ill_routine__-_reset__
    .word       CMON_MOD     
    .word       svc_routine__-_reset__
    .word       CMON_MOD     
    .word       dvz_routine__-_reset__
    .word       CMON_MOD     
    .word       flg_routine__-_reset__
    .word       CMON_MOD     
    .word       bpt_routine__-_reset__
    .word       CMON_MOD     
    .word       trc_routine__-_reset__
    .word       CMON_MOD     
    .word       und_routine__-_reset__
    .word       CMON_MOD     
    .word       rbe_routine__-_reset__
    .word       CMON_MOD     
    .word       nbe_routine__-_reset__
    .word       CMON_MOD     
    .word       ovf_routine__-_reset__
    .word       CMON_MOD     
    .word       dbg_routine__-_reset__
    .word       CMON_MOD     
    .word       _reset__-_reset__

 #
 # The interrupt dispatch table for direct exception mode, in PC relative form.
 #

de_intbase__::
    .double     nvi_routine__
    .double     nmi_routine__
    .double     abt_routine__
    .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     rbe_routine__
    .double     nbe_routine__
    .double     ovf_routine__
    .double     dbg_routine__
    .double     _reset__

 #
 # The module table
 #

rom_module_table__::
    .double     0
    .double     normal_intbase__
    .double     _reset__
    .double     0

