vectors.s

来自「开放源码实时操作系统源码.」· S 代码 · 共 643 行 · 第 1/2 页

S
643
字号
##==========================================================================
##
##      vectors.S
##
##      SH exception vectors
##
##==========================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
## Copyright (C) 2003 Nick Garnett 
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
##==========================================================================
#######DESCRIPTIONBEGIN####
##
## Author(s):    jskov
## Contributors: jskov, gthomas, nickg
## Date:         1999-05-01
## Purpose:      SH exception vectors
## Description:  This file defines the code placed into the exception
##               vectors. It also contains the first level default VSRs
##               that save and restore state for both exceptions and
##               interrupts.
##
######DESCRIPTIONEND####
##
##==========================================================================

#include <pkgconf/hal.h>
#include <pkgconf/hal_sh.h>

#ifdef CYGPKG_KERNEL
#include <pkgconf/kernel.h>     // CYGPKG_KERNEL_INSTRUMENT
#endif
#include CYGHWR_MEMORY_LAYOUT_H
        
#include <cyg/hal/arch.inc>
#include <cyg/hal/variant.inc>
#include <cyg/hal/sh_regs.h>
#include <cyg/hal/sh_offsets.inc>

#===========================================================================

//        .file   "vectors.S"

#define n__DEBUG
        
#===========================================================================
# Start by defining the exceptions vectors.

        .section ".vectors","ax"
# Include exception entry code since it exists in two variants,
# depending on the CPU model. This file also defines macros used
# for exception return.

FUNC_START(_vector_code_vma)

#include CYGBLD_HAL_VAR_EXCEPTION_MODEL_INC

#---------------------------------------------------------------------------
# This code handles the common part of all exception handlers.
# It saves the machine state onto the stack  and then calls
# a "C" routine to do the rest of the work. This work may result
# in thread switches, and changes to the saved state. When we return
# here the saved state is restored and execution is continued.

FUNC_START(cyg_hal_default_exception_vsr)
	hal_cpu_save_regs
	hal_exception_entry_extras
#ifdef __DEBUG
        mov.l   1f,r0
        mov.l   r0,@-r15
	bra	2f
	 nop
	.align  2
1:      .long   0x77777770
2:
        # It is safe to use breakpoints below this point.
        .globl  _cyg_hal_default_exception_vsr_bp_safe
_cyg_hal_default_exception_vsr_bp_safe:
#endif

	# Make sure the saved registers structure contain
	# the decoded exception number
	hal_exception_translate

        mov      r15,r4                 ! R4 = register dump
        
#if (defined(CYGSEM_HAL_ROM_MONITOR) || defined(CYGPKG_REDBOOT)) && \
    defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK)

        mov.l   $cyg_interrupt_stack_base,r0
        mov.l   $cyg_interrupt_stack,r1
        cmp/hi  r15,r0                  ! if r0 > r15 or
        bt      2f
        cmp/hi  r1,r15                  ! if r15 > r1
        bf      1f
2:      mov     r1,r15                  ! change to supervisor stack
1:      mov.l   r4,@-r15                ! save old stack pointer

#endif
        
        # The entire CPU state is now stashed on the stack,
        # call into C to do something with it.

        mov.l   $cyg_hal_exception_handler,r0
        jsr     @r0                     ! call C code, r4 = registers
         nop

#if (defined(CYGSEM_HAL_ROM_MONITOR) || defined(CYGPKG_REDBOOT)) && \
    defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK)

        # If we are returning from the last nested exception, move back
        # to the thread stack. 
        # Since we have arranged for the top of stack location to
        # contain the sp we need to go back to here, just pop it off
        # and put it in SP.

        mov.l   @r15,r15
#endif
        
        bra     restore_state
         nop
        
        .align  2
        SYM_PTR_REF(cyg_hal_exception_handler)

#---------------------------------------------------------------------------
# Common interrupt handling code.

FUNC_START(cyg_hal_default_interrupt_vsr)
	hal_cpu_save_regs
	hal_interrupt_entry_extras
	
#ifdef __DEBUG
        mov.l   1f,r0
        mov.l   r0,@-r15
 	bra	2f
	 nop
	.align  2
1:	.long   0x77777771
2:
        # It is safe to use breakpoints below this point.
        .globl  _cyg_hal_default_interrupt_vsr_bp_safe
_cyg_hal_default_interrupt_vsr_bp_safe:
#endif

        # The entire CPU state is now stashed on the stack,
        # increment the scheduler lock and call the ISR
        # for this vector.

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT                 
        mov.l   $cyg_scheduler_sched_lock,r0
        mov.l   @r0,r1
        add     #1,r1
        mov.l   r1,@r0
#endif

        mov     r15,r8                  ! R8 = register dump

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK 

        mov.l   $cyg_interrupt_stack_base,r0
        mov.l   $cyg_interrupt_stack,r1
        cmp/hi  r15,r0                  ! if r0 > r15 or
        bt      2f
        cmp/hi  r1,r15                  ! if r15 > r1
        bf      1f
2:      mov     r1,r15                  ! change to supervisor stack
1:      mov.l   r8,@-r15                ! save old stack pointer

#endif

#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
        mov.l   $n0301,r4               ! arg0 = type = INTR,RAISE
        mov     r7,r5                   ! arg1 = vector number
        mov.l   $cyg_instrument,r0
        mov     #0,r6                   ! arg2 = 0
        jsr      @r0                    ! call instrument function
         nop
        bra     1f
         nop

        .align  2
$n0301: 
        .long   0x0301
        SYM_PTR_REF(cyg_instrument)
1:
#endif

        # Decode the interrupt vector, and find ISR index
        mov     #CYGARC_SHREG_EVENT,r0
        mov.l   @(r0,r8),r4             ! load existing vector number
        hal_intc_decode r1,r4
        mov.l   r4,@(r0,r8)             ! store decoded vector number back
                                        ! to saved state.
        hal_intc_translate r4,r9

#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
        # If we are supporting Ctrl-C interrupts from GDB, we must squirrel
        # away a pointer to the save interrupt state here so that we can
        # plant a breakpoint at some later time.
        
        mov.l   $hal_saved_interrupt_state,r1
        mov.l   r8,@r1
#endif

#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING

#if defined(CYGARC_SH_SOFTWARE_IP_UPDATE)
        # The interrupt mask bits in the SR are not updated by the
        # CPU. Proper nested operation requires the level to be
        # found and put in the SR.

        # R4 contains the vector number:
        # CYGNUM_HAL_INTERRUPT_NMI:     
        #  Ix = 15
        # CYGNUM_HAL_INTERRUPT_LVL0-CYGNUM_HAL_INTERRUPT_LVL14:
        #  Ix = 15-(CYGNUM_HAL_INTERRUPT_LVL0-R4)
        # IRA sources:
        #  Get level from IRA
        # IRB sources:
        #  Get level from IRB

        # However, doing mutiple checks and branches here is not smart.
        # Instead rely on alternative implementation where all programmed
        # priorities are also kept in a table.

        mov.l   $cyg_hal_ILVL_table,r0
        mov.b   @(r0,r4),r0
        shll2   r0
        shll2   r0
        mov.l   $unmasked_SR,r1
        or      r0,r1
        ldc     r1,sr
#endif

#endif

        mov     r9,r0
        mov.l   $hal_interrupt_handlers,r1 ! get interrupt handler
        mov.l   @(r0,r1),r1

        mov.l   $hal_interrupt_data,r5 ! get interrupt data
        mov.l   @(r0,r5),r5

        jsr     @r1                     ! r4=vector, r5=data
         nop

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK

        # If we are returning from the last nested interrupt, move back
        # to the thread stack. interrupt_end() must be called on the
        # thread stack since it potentially causes a context switch.
        # Since we have arranged for the top of stack location to
        # contain the sp we need to go back to here, just pop it off
        # and put it in SP.

        mov.l   @r15,r15
#endif

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT

        # We only need to call _interrupt_end() when there is a kernel
        # present to do any tidying up.
        
        # on return r0 bit 1 will indicate whether a DSR is
        # to be posted. Pass this together with a pointer to
        # the interrupt object we have just used to the
        # interrupt tidy up routine.
        mov     r0,r4                   ! arg1 = isr_ret

        # Note that r8 and r9 are defined to be preserved across
        # calls by the calling convention, so they still contain
        # the register dump and the vector table index respectively.

        mov.l   $hal_interrupt_objects,r0  ! get interrupt object table
        mov.l   @(r0,r9),r5             ! arg2 = interrupt object
        mov.l   $interrupt_end,r0
        mov     r8,r6                   ! arg3 = saved register dump
        jsr     @r0                     ! call into C to finish off
         nop
#endif

restore_state:  
        # All done, restore CPU state and continue
#ifdef __DEBUG
	# skip past debug marker
	add     #4,sp
#endif

	hal_cpu_restore_regs_return

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?