URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [sh/] [arch/] [v2_0/] [src/] [vectors.S] - Rev 174
Compare with Previous | Blame | View Log
##==========================================================================
##
## 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.
##
## 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
## 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
# The entire CPU state is now stashed on the stack,
# call into C to do something with it.
mov r15,r4 ! R4 = register dump
mov.l $restore_state,r0 ! get return link
lds r0,pr ! to procedure register
mov.l $cyg_hal_exception_handler,r0
jmp @r0 ! call C code, r4 = registers
nop
.align 2
$restore_state:
.long restore_state
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
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
##-----------------------------------------------------------------------------
## Execute pending DSRs on the interrupt stack with interrupts enabled.
## Note: this can only be called from code running on a thread stack
FUNC_START(hal_interrupt_stack_call_pending_DSRs)
# Change to interrupt stack
mov r15,r2
mov.l $cyg_interrupt_stack,r15
mov.l r2,@-r15 ! save old stack pointer
sts.l pr,@-r15 ! save pr on stack
stc sr,r3
mov.l r3,@-r15 ! save sr on stack
# enable interrupts
hal_cpu_int_enable r0,r1
# Call into kernel which will execute DSRs
mov.l $cyg_interrupt_call_pending_DSRs,r0
jsr @r0
nop
# Get old sr, pr, and stack values
mov.l @r15+,r3 ! get old sr
lds.l @r15+,pr ! get old pr
mov.l @r15+,r15 ! get old stack pointer
# Restore SR interrupt state
hal_cpu_int_merge r3,r0,r1
rts
nop
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
#endif // CYGFUN_HAL_COMMON_KERNEL_SUPPORT
.align 2
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
SYM_PTR_REF(hal_saved_interrupt_state)
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
SYM_PTR_REF(cyg_interrupt_stack_base)
SYM_PTR_REF(cyg_interrupt_stack)
#endif
SYM_PTR_REF(hal_interrupt_handlers)
SYM_PTR_REF(hal_interrupt_data)
SYM_PTR_REF(hal_interrupt_objects)
#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
SYM_PTR_REF(cyg_hal_ILVL_table)
$unmasked_SR:
.long (CYG_SR & ~CYGARC_REG_SR_IMASK)
#endif // CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
SYM_PTR_REF(cyg_interrupt_call_pending_DSRs)
SYM_PTR_REF(interrupt_end)
SYM_PTR_REF(cyg_scheduler_sched_lock)
#endif
#---------------------------------------------------------------------------
# Platform initialization (reset)
FUNC_START(_reset_platform)
hal_post_reset_init
#ifdef __DEBUG
mov #0,r0
mov #1,r1
mov #2,r2
mov #3,r3
mov #4,r4
mov #5,r5
mov #6,r6
mov #7,r7
mov #8,r8
mov #9,r9
mov #10,r10
mov #11,r11
mov #12,r12
mov #13,r13
mov #14,r14
#endif
# Call platform specific hardware initialization
# This may include memory controller initialization. It is not
# safe to access RAM until after this point.
# Note that caches must not be enabled until after this point,
# since we may be fiddling the FRQCR which cannot be safely done
# by code in burst/cachable memory (errata SH7-184e).
hal_hardware_init
# Now copy necessary bits to RAM and jump to the VMA base
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_SUBSETROMRAM)
# Copy data from ROM to ram
mov.l $_rom_data_start,r3 ! r3 = rom start
mov.l $_ram_data_start,r4 ! r4 = ram start
mov.l $_ram_data_end,r5 ! r5 = ram end
cmp/eq r4,r5 ! skip if no data
bt 2f
1: mov.l @r3+,r0 ! get word from ROM
mov.l r0,@r4 ! store in RAM
add #4,r4
cmp/eq r4,r5 ! compare
bf 1b ! loop if not yet done
2:
# Jump to the proper VMA base of the code.
mov.l $complete_setup,r0
jmp @r0
nop
.align 2
SYM_PTR_REF(_rom_data_start)
SYM_PTR_REF(_ram_data_start)
SYM_PTR_REF(_ram_data_end)
SYM_PTR_REF(complete_setup)
#elif defined(CYG_HAL_STARTUP_ROMRAM)
# Copy everything to the proper VMA base and jump to it.
mov.l $_vector_code_lma,r0
mov.l $_vector_code_vma,r1
mov.l $end,r2
1: mov.l @r0+,r3 ! get word from ROM
mov.l r3,@r1 ! store in RAM
add #4,r1
cmp/eq r1,r2 ! compare
bf 1b ! loop if not yet done
mov.l $complete_setup,r0
jmp @r0
nop
.align 2
SYM_PTR_REF(_vector_code_lma)
SYM_PTR_REF(_vector_code_vma)
SYM_PTR_REF(end)
SYM_PTR_REF(complete_setup)
#else
# Jump to remaining setup code. Relative branch is OK since VMA=LMA.
bra CYG_LABEL_DEFN(complete_setup)
nop
#endif
#-----------------------------------------------------------------------------
# Complete target initialization and setup.
# After this point we can use absolute addressing modes and access all the
# memory in the system.
.align 2
FUNC_START(complete_setup)
# Set up monitor related stuff (vectors primarily)
hal_mon_init
# set up stack
mov.l $startup_stack,r15
# clear BSS
mov.l $_bss_start,r3 ! r3 = start
mov.l $_bss_end,r4 ! r4 = end
mov #0,r0 ! r0 = 0
1: cmp/eq r3,r4 ! skip if no bss
bt 2f
mov.l r0,@r3 ! store zero
add #4,r3
bra 1b ! loop
nop
2:
# It is now safe to call C functions which may rely on initialized
# data.
# # Initialize MMU.
# .extern hal_MMU_init
# jsr hal_MMU_init
# nop
# Enable caches
mov.l $cyg_var_enable_caches,r1
jsr @r1
nop
# Variant HALs may need to do something special before we continue
mov.l $hal_variant_init,r1
jsr @r1
nop
# Platform initialization
mov.l $hal_platform_init,r1
jsr @r1
nop
# call c++ constructors
mov.l $cyg_hal_invoke_constructors,r1
jsr @r1
nop
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
mov.l $initialize_stub,r1
jsr @r1
nop
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
mov.l $hal_ctrlc_isr_init,r1
jsr @r1
nop
#endif
mov.l $cyg_start,r1
jsr @r1
nop
9:
bra 9b ! if we return, loop
nop
.align 2
SYM_PTR_REF(_bss_start)
SYM_PTR_REF(_bss_end)
SYM_PTR_REF(startup_stack)
SYM_PTR_REF(cyg_hal_invoke_constructors)
SYM_PTR_REF(cyg_var_enable_caches)
SYM_PTR_REF(hal_variant_init)
SYM_PTR_REF(hal_platform_init)
SYM_PTR_REF(cyg_start)
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
SYM_PTR_REF(initialize_stub)
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
SYM_PTR_REF(hal_ctrlc_isr_init)
#endif
#---------------------------------------------------------------------------
# Interrupt vector tables.
# These tables contain the isr, data and object pointers used to deliver
# interrupts to user code.
.data
.extern CYG_LABEL_DEFN(hal_default_isr)
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
#define CYG_ISR_TABLE_SIZE 1
#else
#define CYG_ISR_TABLE_SIZE CYGNUM_HAL_ISR_COUNT
#endif
SYM_DEF(hal_interrupt_handlers)
.rept CYG_ISR_TABLE_SIZE
.long CYG_LABEL_DEFN(hal_default_isr)
.endr
SYM_DEF(hal_interrupt_data)
.rept CYG_ISR_TABLE_SIZE
.long 0
.endr
SYM_DEF(hal_interrupt_objects)
.rept CYG_ISR_TABLE_SIZE
.long 0
.endr
#---------------------------------------------------------------------------
## Temporary interrupt stack
.section ".bss"
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.balign 16
SYM_DEF(cyg_interrupt_stack_base)
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
.byte 0
.endr
.balign 16
.global _cyg_interrupt_stack
SYM_DEF(cyg_interrupt_stack)
.long 0,0,0,0
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
#ifdef CYGSEM_HAL_ROM_MONITOR
// Enough space for stub to handle downloads. If using thread capabilities
// it will be using the RAM application's stack.
# define STARTUP_STACK_SIZE 1024
#else
# ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Enough space to run constructors.
// FIXME: 512 is enough for all tests. doc/examples/twothreads
// calls printf on this stack though, and so requires more space.
# define STARTUP_STACK_SIZE 1024
# else
# define STARTUP_STACK_SIZE CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
# endif
#endif
.balign 16
SYM_DEF(startup_stack_base)
.rept STARTUP_STACK_SIZE
.byte 0
.endr
.balign 16
SYM_DEF(startup_stack)
.long 0,0,0,0
#---------------------------------------------------------------------------
# end of vectors.S