diff packages/hal/sh/arch/current/src/vectors.S @ 76:435cced73e2f ecos-v1_3_1-release

eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
author jlarmour
date Tue, 28 Mar 2000 14:10:45 +0000
parents
children 2085233a121a
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/hal/sh/arch/current/src/vectors.S
@@ -0,0 +1,1021 @@
+##==========================================================================
+##
+##      vectors.S
+##
+##      SH exception vectors
+##
+##==========================================================================
+#####COPYRIGHTBEGIN####
+#                                                                          
+# -------------------------------------------                              
+# The contents of this file are subject to the Red Hat eCos Public License 
+# Version 1.1 (the "License"); you may not use this file except in         
+# compliance with the License.  You may obtain a copy of the License at    
+# http://www.redhat.com/                                                   
+#                                                                          
+# Software distributed under the License is distributed on an "AS IS"      
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+# License for the specific language governing rights and limitations under 
+# the License.                                                             
+#                                                                          
+# The Original Code is eCos - Embedded Configurable Operating System,      
+# released September 30, 1998.                                             
+#                                                                          
+# The Initial Developer of the Original Code is Red Hat.                   
+# Portions created by Red Hat are                                          
+# Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+# All Rights Reserved.                                                     
+# -------------------------------------------                              
+#                                                                          
+#####COPYRIGHTEND####
+##==========================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s):    jskov
+## Contributors: jskov
+## 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 <cyg/hal/arch.inc>
+#include <cyg/hal/sh_regs.h>
+#include <cyg/hal/sh_offsets.inc>
+
+#include <cyg/hal/hal_intr.h>
+
+
+#===========================================================================
+
+        .file   "vectors.S"
+
+#undef __DEBUG
+        
+#===========================================================================
+# SR initialization value
+# zero all bits except:
+# MD = Processor operation mode field (privileged mode)
+# I0-3 = Mask out all interrupts but NMI.
+#
+# When saving or restoring the state of an exception or interrupt, the bit
+# CYGARC_REG_SR_RB is also set, switching the register bank. When this bit
+# is set, interrupts must be disabled.
+#
+# Note: We could also use the BL bit to prevent interrupts, but that would
+#       also prevent the use of breakpoints.
+
+#define CYG_SR (CYGARC_REG_SR_MD|CYGARC_REG_SR_IMASK)
+#define CYG_SR_BANK1 (CYGARC_REG_SR_MD|CYGARC_REG_SR_IMASK|CYGARC_REG_SR_RB)
+
+#===========================================================================
+# Start by defining the exceptions vectors.
+        .section ".vectors","ax"
+rom_vectors:    
+
+
+# reset            0xa0000000
+# other exceptions VBR+0x100
+# tlb miss         VBR+0x400
+# interrupts       VBR+0x600
+
+        .globl __reset;
+__reset:
+        # Put CPU in a well-known state, disable interrupts.
+        mov.l   $nCYG_SR,r1
+        ldc     r1,sr
+
+        # Initialize VBR if necessary
+#if	defined(CYG_HAL_STARTUP_ROM) ||			\
+	(	defined(CYG_HAL_STARTUP_RAM) &&		\
+		!defined(CYGSEM_HAL_USE_ROM_MONITOR))
+        mov.l   $__reset,r1             ! Set VBR
+        ldc     r1,vbr
+#endif
+
+#ifdef CYG_HAL_STARTUP_ROM
+        # This code will be executed from address 0 if started from ROM.
+        # We do not need it when starting from RAM.
+        mov.l   $_start,r0
+        jmp     @r0
+         nop
+        .align 2
+$_start:
+        .long _start
+#endif
+
+#===========================================================================
+# Real startup code.
+
+        .globl  _start
+_start:
+        # Initialize CPU
+        mov     #0,r0
+        mov     #CYGARC_REG_CCR,r1      ! Disable cache
+        mov.l   r0,@r1
+        mov     #CYGARC_REG_MMUCR,r1    ! Disable MMU
+        mov.l   r0,@r1
+        mov     #CYGARC_REG_BBRA,r1     ! Disable UBC Channel A
+        mov.w   r0,@r1
+        mov     #CYGARC_REG_BBRB,r1     ! Disable UBC Channel B
+        mov.w   r0,@r1
+        mov     #CYGARC_REG_BRCR,r1     ! Reset UBC common register
+        mov.w   r0,@r1
+        mov.l   $CYGARC_REG_TSTR,r1     ! Disable timers
+        mov.b   r0,@r1
+        mov.l   $CYGARC_REG_IPRA,r1     ! Disable interrupt request sources
+        mov.w   r0,@r1
+        mov.l   $CYGARC_REG_IPRB,r1
+        mov.w   r0,@r1
+        
+#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.
+        mov.l    $_hal_hardware_init,r0
+        jsr      @r0
+         nop
+
+        # Set up monitor related stuff (vectors primarily)
+        hal_mon_init
+
+        # set up stack
+        mov.l    $__startup_stack,r15
+
+#if defined(CYG_HAL_STARTUP_ROM)
+
+        # 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:
+#endif
+
+        # 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_hal_enable_caches,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
+
+
+        mov.l    $_cyg_start,r1
+        jsr      @r1
+         nop
+9:      
+        bra      9b                     ! if we return, loop
+         nop
+
+        .align  2
+$nCYG_SR:
+        .long   CYG_SR
+$__startup_stack:
+        .long   __startup_stack
+$__reset:
+        .long   __reset
+$CYGARC_REG_TSTR:
+        .long   CYGARC_REG_TSTR
+$CYGARC_REG_IPRA:
+        .long   CYGARC_REG_IPRA
+$CYGARC_REG_IPRB:
+        .long   CYGARC_REG_IPRB
+
+        .extern _hal_hardware_init
+        .extern __bss_start
+        .extern __bss_end
+        .extern _cyg_hal_invoke_constructors
+        .extern _cyg_start
+        .extern __rom_data_start
+        .extern __ram_data_start
+        .extern __ram_data_end
+
+$_hal_hardware_init:
+        .long   _hal_hardware_init
+$__bss_start:
+        .long   __bss_start
+$__bss_end:
+        .long   __bss_end
+$_cyg_hal_invoke_constructors:
+        .long   _cyg_hal_invoke_constructors
+$_cyg_hal_enable_caches:
+        .long   _cyg_hal_enable_caches
+$_cyg_start:
+        .long   _cyg_start
+$__rom_data_start:
+        .long   __rom_data_start
+$__ram_data_start:
+        .long   __ram_data_start
+$__ram_data_end:
+        .long   __ram_data_end
+
+
+
+#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+        .extern _initialize_stub
+$_initialize_stub:
+        .long   _initialize_stub
+#endif
+
+        
+        .org    0x100
+__exception:
+
+#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
+        mov     #1,r7
+#endif
+
+#ifdef __DEBUG
+        mov     #CYGARC_REG_EXCEVT,r1
+        mov.l   @r1,r1
+        mov.l   $trapval,r0
+        cmp/eq  r0,r1
+        bt      1f
+        mov.l   $safe_excevt,r0
+        mov.l   r1,@r0
+1:      
+#endif
+
+        mov     #CYGARC_REG_EXCEVT,r1
+        mov.l   @r1,r1
+        shlr2   r1
+        shlr    r1                      ! divide cause by 0x08
+        mov.l   $_hal_vsr_table,r0
+        mov.l   @(r0,r1),r1
+        jmp     @r1
+         nop
+        
+        .align   2
+$_hal_vsr_table:
+        .long   _hal_vsr_table
+
+#ifdef __DEBUG
+$safe_excevt:
+        .long   0x080d0200
+$trapval:
+        .long   0x00000160
+#endif
+
+#---------------------------------------------------------------------------
+# 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.
+
+        .globl  _cyg_hal_default_exception_vsr
+_cyg_hal_default_exception_vsr:
+        
+        # We come here with all register containing their
+        # pre-exception values except:
+        # r0_b-r7_b  = saved r0-r7
+        # r7    = vector #
+        # spc   = saved pc
+        # ssr   = saved sr
+      
+        # Save away some registers
+        mov     r15,r1                  ! entry sp
+
+#ifdef __DEBUG
+        mov.l   $exc_state_marker,r0
+        mov.l   r0,@-r15
+        mov     #CYGARC_REG_EXCEVT,r0
+        mov.l   @r0,r0
+        mov.l   r0,@-r15
+#endif
+
+#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
+        add     #-12,r15                ! Space for cause, gbr, and vbr
+#else
+        add     #-4,r15                 ! Space for cause
+
+        stc     gbr,r0                  ! GBR
+        mov.l   r0,@-r15
+        stc     vbr,r0                  ! VBR
+        mov.l   r0,@-r15
+#endif
+
+        stc     spc,r0
+        mov.l   r0,@-r15                ! PC
+        stc     ssr,r0
+        mov.l   r0,@-r15                ! SR
+
+        sts.l   pr,@-r15                ! PR
+        sts.l   mach,@-r15              ! mach
+        sts.l   macl,@-r15              ! macl
+
+        mov.l   r1,@-r15                ! entry sp
+        mov.l   r14,@-r15               ! r14-r0
+        mov.l   r13,@-r15
+        mov.l   r12,@-r15
+        mov.l   r11,@-r15
+        mov.l   r10,@-r15
+        mov.l   r9,@-r15
+        mov.l   r8,@-r15
+        stc.l   r7_bank,@-r15
+        stc.l   r6_bank,@-r15
+        stc.l   r5_bank,@-r15
+        stc.l   r4_bank,@-r15
+        stc.l   r3_bank,@-r15
+        stc.l   r2_bank,@-r15
+        stc.l   r1_bank,@-r15
+        stc.l   r0_bank,@-r15
+
+        # After setting the SR it will be possible to use breakpoints.
+        mov.l   $nCYG_SR1,r1
+        ldc     r1,sr
+        # ------------------------------------------------------------
+        # Register bank has changed now. 
+
+#ifdef __DEBUG
+        # 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
+        mov     #CYGARC_REG_EXCEVT,r0
+        mov.l   @r0,r4
+        mov     #-5,r0                  ! divide cause by 0x20
+        shld    r0,r4
+        mov     #CYGARC_SHREG_EVENT,r0
+        mov.l   r4,@(r0,r15)            ! store decoded vector number back
+
+        # 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
+$nCYG_SR1:
+        .long   CYG_SR
+
+#ifdef __DEBUG
+$exc_state_marker:
+        .long   0x77777770
+#endif
+        
+        .extern _cyg_hal_exception_handler
+
+$_cyg_hal_exception_handler:
+        .long _cyg_hal_exception_handler
+
+        ! When the call returns it will go to restore_state.
+
+        .org    0x400
+__tlb_miss:
+#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
+        mov      #2,r7
+#endif
+
+#ifdef __DEBUG
+        mov      #CYGARC_REG_EXCEVT,r1
+        mov.l    @r1,r1
+        mov.l    $safe_excevt2,r0
+        mov.l    r1,@r0
+#endif
+
+        mov     #CYGARC_REG_EXCEVT,r1
+        mov.l   @r1,r1
+        shlr2   r1
+        shlr    r1                      ! divide cause by 0x08
+        mov.l   $_hal_vsr_table2,r0
+        mov.l   @(r0,r1),r1
+        jmp     @r1
+         nop
+
+        .align   2
+$_hal_vsr_table2:
+        .long    _hal_vsr_table
+
+#ifdef __DEBUG
+$safe_excevt2:
+        .long   0x080d0200
+#endif
+
+        .org    0x600
+__interrupt:        
+
+#ifdef CYGHWR_HAL_SH_HANDLE_SPURIOUS_INTERRUPTS
+        # A spurious interrupt with INTEVT=0 may be caused by
+        # clearing of BL. Those interrupts need to be ignored.
+        mov     #CYGARC_REG_INTEVT,r0
+        mov.l   @r0,r0
+        cmp/eq  #0,r0
+        bf      1f
+        rte
+         nop
+1:      
+#endif        
+
+#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
+        mov      #3,r7
+#endif
+
+#ifdef __DEBUG
+        mov      #CYGARC_REG_INTEVT,r1
+        mov.l    @r1,r1
+        mov.l    $safe_intevt,r0
+        mov.l    r1,@r0
+#endif
+
+        mov.l    $_hal_vsr_table_int,r1
+        mov.l    @r1,r1
+        jmp      @r1
+         nop
+
+        .align   2
+$_hal_vsr_table_int:
+        .long    _hal_vsr_table+CYGNUM_HAL_VECTOR_INTERRUPT*4
+
+#ifdef __DEBUG
+$safe_intevt:
+        .long   0x080d0204
+#endif
+
+rom_vectors_end:        
+
+
+#---------------------------------------------------------------------------
+# Common interrupt handling code.
+
+        .globl _cyg_hal_default_interrupt_vsr
+_cyg_hal_default_interrupt_vsr:
+
+        # We come here with all register containing their
+        # pre-exception values except:
+        # r0_b-r7_b  = saved r0-r7
+        # r7    = vector #
+        # spc   = saved pc
+        # ssr   = saved sr
+        
+        # Save away some registers
+        mov     r15,r1                  ! entry sp
+
+#ifdef __DEBUG
+        mov.l   $int_state_marker,r0
+        mov.l   r0,@-r15
+        mov     #CYGARC_REG_INTEVT,r0
+        mov.l   @r0,r0
+        mov.l   r0,@-r15
+#endif
+        
+#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
+        add     #-12,r15                ! Space for cause, gbr, and vbr
+#else
+        add     #-4,r15                 ! Space for cause
+
+        stc     gbr,r0                  ! GBR
+        mov.l   r0,@-r15
+        stc     vbr,r0                  ! VBR
+        mov.l   r0,@-r15
+#endif
+
+        stc     spc,r0
+        mov.l   r0,@-r15                ! PC
+        stc     ssr,r0
+        mov.l   r0,@-r15                ! SR
+
+        sts.l   pr,@-r15                ! PR
+        sts.l   mach,@-r15              ! mach
+        sts.l   macl,@-r15              ! macl
+
+        mov.l   r1,@-r15                ! entry sp
+        mov.l   r14,@-r15               ! r14-r0
+        mov.l   r13,@-r15
+        mov.l   r12,@-r15
+        mov.l   r11,@-r15
+        mov.l   r10,@-r15
+        mov.l   r9,@-r15
+        mov.l   r8,@-r15
+        stc.l   r7_bank,@-r15
+        stc.l   r6_bank,@-r15
+        stc.l   r5_bank,@-r15
+        stc.l   r4_bank,@-r15
+        stc.l   r3_bank,@-r15
+        stc.l   r2_bank,@-r15
+        stc.l   r1_bank,@-r15
+        stc.l   r0_bank,@-r15
+
+        # After setting the SR it will be possible to use breakpoints.
+        mov.l   $nCYG_SR2,r1
+        ldc     r1,sr
+        # ------------------------------------------------------------
+        # Register bank has changed now. 
+
+#ifdef __DEBUG
+        # 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,
+        # call into C to do something with it.
+
+        # 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   $__interrupt_stack_base,r0
+        mov.l   $__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
+$_cyg_instrument:
+        .extern _cyg_instrument
+        .long   _cyg_instrument
+1:
+#endif
+
+        # Decode the interrupt vector
+        mov     #CYGARC_REG_INTEVT,r0
+        mov.l   @r0,r4
+        mov     #-5,r0                  ! divide cause by 0x20
+        shld    r0,r4
+        add     #-14,r4                 ! adjust so NMI becomes 0
+        mov     #CYGARC_SHREG_EVENT,r0
+        mov.l   r4,@(r0,r8)             ! store decoded vector number back
+                                        ! to saved state.
+
+        // Find ISR index.
+#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
+#define CYG_ISR_TABLE_SIZE    1
+        mov     #0,r9                   ! only one ISR in the table
+#else //  CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
+#define CYG_ISR_TABLE_SIZE    CYGNUM_HAL_ISR_COUNT
+        mov     r4,r9
+        shll2   r9                      ! get from vector number to ISR index
+#endif //  CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
+
+
+#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
+        mov     #CYGNUM_HAL_INTERRUPT_SCI_RXI,r1
+        cmp/eq  r1,r4
+        bf      2f
+        mov     r4,r10                   ! save across call.
+        mov     #CYGARC_SHREG_PC,r4
+        add     r8,r4
+        mov.l   @r4,r4
+        mov.l   $_cyg_hal_gdb_isr,r1
+        jsr     @r1                     ! returns 1 if the proper isr must be
+         nop                            ! called (i.e., if it was not a GDB 
+        mov     r10,r4                  ! interrupt)
+        cmp/eq  #0,r0
+        bt      skip_isr_proper
+        bra     2f
+         nop
+        .align  2
+        .extern _cyg_hal_gdb_isr
+$_cyg_hal_gdb_isr:
+        .long   _cyg_hal_gdb_isr
+2:
+#endif
+
+#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
+
+#ifdef CYGPKG_HAL_SH_EDK7708
+        # 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 CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
+        # If interrupt was caused by GDB, the ISR call above
+        # is skipped by jumping here.
+skip_isr_proper:
+#endif
+
+#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
+        mov.l   $_safe_addr,r0
+        mov.l   @r0,r1
+        add     #1,r1
+        mov.l   r1,@r0
+        add     #4,r0
+
+        mov     r15,r1
+        mov     #CYGARC_SH_EXCEPTION_SIZE/4,r2
+1:      mov.l   @r1+,r3
+        mov.l   r3,@r0
+        add     #4,r0
+        dt      r2
+        bf      1b
+
+        bra     2f
+         nop
+        .align  2
+$_safe_addr:
+        .long   0x080d0000-4
+2:      
+#endif
+
+        # Disable interrupts and switch register bank during the restore 
+        # operation
+        mov.l   $nCYG_SR_BANK1,r1
+        ldc     r1,sr
+        # ------------------------------------------------------------
+        # Register bank has changed now. 
+
+        #
+        # Single step debugging becomes impossible after this point!
+        #
+
+        mov     r15,r0
+        ldc.l   @r0+,r0_bank
+        ldc.l   @r0+,r1_bank
+        ldc.l   @r0+,r2_bank
+        ldc.l   @r0+,r3_bank
+        ldc.l   @r0+,r4_bank
+        ldc.l   @r0+,r5_bank
+        ldc.l   @r0+,r6_bank
+        ldc.l   @r0+,r7_bank
+        mov.l   @r0+,r8
+        mov.l   @r0+,r9
+        mov.l   @r0+,r10
+        mov.l   @r0+,r11
+        mov.l   @r0+,r12
+        mov.l   @r0+,r13
+        mov.l   @r0+,r14
+        mov.l   @r0+,r15                ! return SP
+
+        lds.l   @r0+,macl               ! macl
+        lds.l   @r0+,mach               ! mach
+        lds.l   @r0+,pr                 ! PR
+
+        mov.l   @r0+,r2
+        ldc     r2,ssr                  ! return SR
+        mov.l   @r0+,r2
+        ldc     r2,spc                  ! return PC
+
+#ifndef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
+        mov.l   @r0+,r2
+        ldc     r2,vbr                  ! return VBR
+        mov.l   @r0+,r2
+        ldc     r2,gbr                  ! return GBR
+#endif
+
+        rte
+         nop
+
+
+#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
+        .globl _hal_interrupt_stack_call_pending_DSRs
+_hal_interrupt_stack_call_pending_DSRs: 
+        # Change to interrupt stack
+        mov     r15,r2
+        mov.l   $__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        
+#ifdef __DEBUG
+$int_state_marker:
+        .long   0x77777771
+#endif
+
+#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK 
+$__interrupt_stack:
+        .long   __interrupt_stack
+$__interrupt_stack_base:
+        .long   __interrupt_stack_base
+#endif
+$nCYG_SR2:
+        .long   CYG_SR
+$nCYG_SR_BANK1:
+        .long   CYG_SR_BANK1
+$_hal_interrupt_handlers:
+        .long   _hal_interrupt_handlers
+$_hal_interrupt_data:
+        .long   _hal_interrupt_data
+$_hal_interrupt_objects:
+        .long   _hal_interrupt_objects
+
+#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
+$cyg_hal_ILVL_table:
+        .long   _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
+        .extern _cyg_scheduler_sched_lock
+        .extern _interrupt_end
+        .extern _cyg_interrupt_call_pending_DSRs
+
+$_cyg_interrupt_call_pending_DSRs:
+        .long   _cyg_interrupt_call_pending_DSRs
+$cyg_scheduler_sched_lock:
+        .long   cyg_scheduler_sched_lock
+$_interrupt_end:
+        .long   _interrupt_end
+#endif
+
+#---------------------------------------------------------------------------
+# Interrupt vector tables.
+# These tables contain the isr, data and object pointers used to deliver
+# interrupts to user code.
+
+        .data
+
+        .extern _hal_default_isr
+
+        .globl  _hal_interrupt_handlers
+_hal_interrupt_handlers:
+        .rept   CYG_ISR_TABLE_SIZE
+        .long   _hal_default_isr
+        .endr
+
+        .globl  _hal_interrupt_data
+_hal_interrupt_data:
+        .rept   CYG_ISR_TABLE_SIZE
+        .long   0
+        .endr
+
+        .globl  _hal_interrupt_objects
+_hal_interrupt_objects:
+        .rept   CYG_ISR_TABLE_SIZE
+        .long   0
+        .endr
+
+#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
+        .globl  _cyg_hal_ILVL_table
+_cyg_hal_ILVL_table:
+        # The first entries in the table have static priorities.
+
+        .byte   0xf                     // NMI
+        .byte   0xf                     // Reserved
+        .byte   0xf                     // LVL0
+        .byte   0xe                     // LVL1
+        .byte   0xd                     // LVL2
+        .byte   0xc                     // LVL3
+        .byte   0xb                     // LVL4
+        .byte   0xa                     // LVL5
+        .byte   0x9                     // LVL6
+        .byte   0x8                     // LVL7
+        .byte   0x7                     // LVL8
+        .byte   0x6                     // LVL9
+        .byte   0x5                     // LVL10
+        .byte   0x4                     // LVL11
+        .byte   0x3                     // LVL12
+        .byte   0x2                     // LVL13
+        .byte   0x1                     // LVL14
+        .byte   0xf                     // Reserved
+
+        # The rest of the table consists of programmable levels, maintained
+        # by the HAL_INTERRUPT_SET_LEVEL macro.
+#ifdef CYGPKG_HAL_SH_EDK7708
+        .rept   (CYGNUM_HAL_ISR_MAX-CYGNUM_HAL_INTERRUPT_RESERVED_3E0)
+        .byte   0xf
+        .endr
+#endif // CYGPKG_HAL_SH_EDK7708
+#endif // CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
+
+#---------------------------------------------------------------------------
+## Temporary interrupt stack
+        
+        .section ".bss"
+
+#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK 
+        .balign 16
+        .global _cyg_interrupt_stack_base
+_cyg_interrupt_stack_base:
+__interrupt_stack_base:
+        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
+        .byte 0
+        .endr
+        .balign 16
+        .global _cyg_interrupt_stack
+_cyg_interrupt_stack:
+__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
+__startup_stack_base:
+        .rept   STARTUP_STACK_SIZE
+        .byte 0
+        .endr
+        .balign 16
+__startup_stack:
+        .long   0,0,0,0
+
+#---------------------------------------------------------------------------
+# end of vectors.S