OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [h8300/] [arch/] [current/] [src/] [vectors.S] - Rev 786

Compare with Previous | Blame | View Log

##=============================================================================
##
##      vectors.S
##
##      H8/300 exception vectors
##
##=============================================================================
## ####ECOSGPLCOPYRIGHTBEGIN####                                            
## -------------------------------------------                              
## This file is part of eCos, the Embedded Configurable Operating System.   
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, 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.,    
## 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 v2.                                               
##
## This exception does not invalidate any other reasons why a work based    
## on this file might be covered by the GNU General Public License.         
## -------------------------------------------                              
## ####ECOSGPLCOPYRIGHTEND####                                              
##=============================================================================
#######DESCRIPTIONBEGIN####
##
## Author(s):   Yoshinori Sato
## Contributors: Yoshinori Sato
## Date:        2002-02-14
## Purpose:     H8/300 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>

#ifdef CYGPKG_REDBOOT
#include <pkgconf/redboot.h>
#endif
        
#ifdef CYGPKG_KERNEL

#include <pkgconf/kernel.h>
        
#endif          

#include <cyg/hal/arch.inc>     
#include <cyg/hal/basetype.h>   
#include <cyg/hal/variant.inc>
                        
        
##-----------------------------------------------------------------------------
        
#ifdef CYGPKG_HAL_H8300_H8300H
        .h8300h
        .macro  shll2 reg
        shll.l  \reg
        shll.l  \reg
        .endm
        .macro  shlr2 reg
        shlr.l  \reg
        shlr.l  \reg
        .endm
#endif
#ifdef CYGPKG_HAL_H8300_H8S
        .h8300s
        .macro  shll2 reg
        shll.l  #2,\reg
        .endm
        .macro  shlr2 reg
        shlr.l  #2,\reg
        .endm
#endif
        
#ifdef CYGPKG_CYGMON
##-----------------------------------------------------------------------------
## Macros for Stack handling when running Cygmon
                        
.macro hal_cygmon_switch_app_stack
#ifdef CYGPKG_HAL_H8300_H8300H
        ; Switch to interrupt stack to handle exception

        ; First, save some scratch registers
        mov.l   er0,@-sp
        mov.l   er1,@-sp

        ; Copy the exception frame
        mov.l   #__cygmon_interrupt_stack,er0
        mov.l   @(8:16,sp),er1
        mov.l   er1,@-er0

        ; Save the pre-exception sp in the register image        
        mov.l   sp,@-er0

        ; Actually switch the stack
        mov.l   er0,sp
        
        mov.l   @sp,er0
        adds    #4,er0
        adds    #4,er0
        mov.l   er0,@sp

        ; Now, restore the scratch registers
        mov.l   @(-4:16,er0),er1
        mov.l   @(-8:16,er0),er0
#endif
#ifdef CYGPKG_HAL_H8300_H8S
        ; Switch to interrupt stack to handle exception

        ; First, save some scratch registers
        stm.l   er0-er1,@-sp
        
        ; Copy the exception frame
        mov.l   #__cygmon_interrupt_stack,er0
        mov.l   @(10,sp:16),er1
        mov.l   er1,@-er0
        mov.w   @(10,sp:16),r1
        mov.w   r1,@-er0

        ; Save the pre-exception sp in the register image        
        mov.l   sp,@-er0

        ; Actually switch the stack
        mov.l   er0,sp
        
        mov.l   @sp,er0
        adds    #4,er0
        adds    #4,er0
        mov.l   er0,@sp

        ; Now, restore the scratch registers
        mov.l   @(-4:16,er0),er1
        mov.l   @(-8:16,er0),er0
#endif
.endm

.macro hal_cygmon_restore_app_stack
        // For cygmon we are switching stacks immediately on exception.
        // We must wait until the very end before restoring the original stack.

#ifdef CYGPKG_HAL_H8300_H8300H
        ; Save some scratch registers
        subs    #4,sp
        mov.l   er0,@-sp
        mov.l   er1,@-sp

        ; We need to restore the application stack pointer, but we also
        ; need to restore the exception frame.
        mov.l   @(12:16,sp),er0
        mov.l   @(16:16,sp),er1
        mov.l   er1,@er0
        mov.l   er0,@(8:16,sp)

        ; Restore the scratch registers
        mov.l   @sp+,er1
        mov.l   @sp+,er0
        mov.l   @sp+,sp                 // Restore the frame-adjusted SP
#endif
#ifdef CYGPKG_HAL_H8300_H8S
        ; Save some scratch registers
        subs    #4,sp
        stm.l   er0-er1,@-sp

        ; We need to restore the application stack pointer, but we also
        ; need to restore the exception frame.
        mov.l   @(12:16,sp),er0
        mov.w   @(16:16,sp),r1
        mov.w   r1,@er0
        mov.l   @(18:16,sp),er1
        mov.l   er1,@er0
        mov.l   er0,@(8:16,sp)

        ; Restore the scratch registers
        ldm.l   @sp+,er0-er1
        mov.l   @sp+,sp                 // Restore the frame-adjusted SP
#endif
.endm

#endif // CYGPKG_CYGMON

##-----------------------------------------------------------------------------
                
#if (defined(CYG_HAL_STARTUP_ROM) || \
     defined(CYGPKG_HAL_H8300_H8300H_SIM) || \
     defined(CYGPKG_HAL_H8300_H8S_SIM))
    
        .section .vectors,"a"
        
        .globl  reset_vector

reset_vector:
        .long   CYG_LABEL_DEFN(_start)
        .long   CYG_LABEL_DEFN(_start)
vector  =       2
        .rept   CYG_ISR_TABLE_SIZE-2
        .long   interrupt_redirect_table+vector*4
vector  =       vector + 1
        .endr
#endif

#if !defined(CYGSEM_HAL_H8300_VECTOR_HOOK)
        .section .int_hook_table,"ax"
interrupt_redirect_table:       
vector  =       0
        .rept   CYG_ISR_TABLE_SIZE
        jsr     @interrupt_entry
vector  =       vector + 1
        .endr
#else
        .section .int_hook_table,"x"
interrupt_redirect_table:       
        .space  4*CYG_ISR_TABLE_SIZE
#endif

##-----------------------------------------------------------------------------
## Startup code
                        
        .text

        .globl  CYG_LABEL_DEFN(_start)
CYG_LABEL_DEFN(_start):
        ; set up stack

        mov.l   #__interrupt_stack,sp
        
        ; Initialize hardware
        hal_cpu_init
        hal_mmu_init
        hal_memc_init
        hal_diag_init
        hal_intc_init
        hal_cache_init
        hal_timer_init
        hal_mon_init

#ifdef CYG_HAL_STARTUP_ROM
        
        ; Copy data from ROM to RAM

        mov.l   #CYG_LABEL_DEFN(__rom_data_start),er5
        mov.l   #CYG_LABEL_DEFN(__ram_data_start),er6
        mov.l   #CYG_LABEL_DEFN(__ram_data_end),er4
        sub.l   er6,er4
        shlr2   er4
1:      
        mov.l   @er5+,er0
        mov.l   er0,@er6
        adds    #4,er6
        dec.l   #1,er4
        bne     1b

#endif

#if defined(CYGSEM_HAL_H8300_VECTOR_HOOK)
        ; Setup Interrupt Vector (virtual)

        ;; check rom table
        mov.l   #8*4,er0
        mov.l   @er0+,er1
        adds    #4,er1
        mov.b   #3,r3l
1:
        mov.l   @er0+,er2
        cmp.l   er1,er2
        bne     3f
        adds    #4,er1
        dec.b   r3l
        bne     1b
        ;; calculate vector address
        mov.l   @8*4,er0
        and.w   #0xff,e0
        sub.l   #8*4,er0
        ;; build ram vector
        mov.l   er0,@__interrupt_table
        mov.l   #0x5e000000+interrupt_entry,er1
        mov.l   #save_vector_table,er3
        mov.b   #0,r2l
2:
        ;; check saved vector
        mov.b   @er3+,r2h
        cmp.b   r2l,r2h
        beq     5f
        subs    #1,er3
        mov.l   er1,@er0
5:      
        adds    #4,er0
        inc.b   r2l
        cmp.b   #CYG_ISR_TABLE_SIZE,r2l
        bcs     2b
        bra     4f
3:
        bra     3b
4:      
                
#else
        mov.l   #interrupt_redirect_table,er0
        mov.l   er0,@__interrupt_table
#endif
        
        ; Clear BSS
        mov.l   #CYG_LABEL_DEFN(__bss_start),er5
        mov.l   #CYG_LABEL_DEFN(__bss_end),er4
        sub.l   #CYG_LABEL_DEFN(__bss_start),er4
        shlr2   er4
        sub.l   er0,er0
1:
        mov.l   er0,@er5
        adds    #4,er5
        dec.l   #1,er4
        bne     1b
        
        ; Call variant and platform HAL
        ; initialization routines.

        .extern CYG_LABEL_DEFN(hal_variant_init)
        jsr     @CYG_LABEL_DEFN(hal_variant_init)

        .extern CYG_LABEL_DEFN(hal_platform_init)
        jsr     @CYG_LABEL_DEFN(hal_platform_init)
        
        ; Call constructors

        .extern CYG_LABEL_DEFN(cyg_hal_invoke_constructors)
        jsr     @CYG_LABEL_DEFN(cyg_hal_invoke_constructors)

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
        .extern CYG_LABEL_DEFN(initialize_stub)
        jsr     @CYG_LABEL_DEFN(initialize_stub)
#endif

#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
        .extern CYG_LABEL_DEFN(hal_ctrlc_isr_init)
        jsr     @CYG_LABEL_DEFN(hal_ctrlc_isr_init)
#endif


        ; Call cyg_start
        sub.l   er0,er0
                
        .extern CYG_LABEL_DEFN(cyg_start)
        jsr     @CYG_LABEL_DEFN(cyg_start)

9:
        bra     9b              ; Loop if we return

save_vector_table:      
#if defined(CYGSEM_HAL_H8300_SAVE_STUB_VECTOR)
        .byte   5,11
#if defined(CYGPKG_HAL_H8300_SAVED_VECTORS)
        h8300_save_vectors
#endif
#endif
        .byte   0                ; end maker
        .align  2
        
interrupt_entry:
        mov.l   er0,@-sp
        mov.l   @(4:16,sp),er0  ; interrupt vector offset
        mov.l   er1,@-sp
        mov.l   @__interrupt_table,er1
        sub.l   er1,er0
        shlr2   er0
        dec.l   #1,er0
        mov.l   er0,@CYG_LABEL_DEFN(_intvector)
        mov.l   @sp+,er1
        mov.l   @sp+,er0
        adds    #4,sp
#ifdef CYGPKG_CYGMON
        hal_cygmon_switch_app_stack
#endif
        hal_cpu_save_all
        h8300_var_interrupt_entry               ; load isr address
        jmp     @er0

##-----------------------------------------------------------------------------
## The following macros are defined depending on whether the HAL is configured
## to support the kernel or not. 

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
        
        .extern CYG_LABEL_DEFN(cyg_scheduler_sched_lock)
        
        ; Increment the scheduler lock
                        
        .macro increment_sched_lock reg=er0
        mov.l   @CYG_LABEL_DEFN(cyg_scheduler_sched_lock),\reg
        inc.l   #1,\reg
        mov.l   \reg,@CYG_LABEL_DEFN(cyg_scheduler_sched_lock)
        .endm

#else
        
        .macro increment_sched_lock reg=er0
        .endm

#endif          

##-----------------------------------------------------------------------------
## Default interrupt VSR

        .text
        .globl  CYG_LABEL_DEFN(__default_interrupt_vsr)
CYG_LABEL_DEFN(__default_interrupt_vsr):

        ; We come here with all the registers pushed
        ; onto the stack.

        hal_diag_intr_start
        
        increment_sched_lock

#if defined(CYGPKG_CYGMON)
        // For Cygmon, we saved this back when we originally switched stacks.
        mov.l   sp,er1                          ; A2 = saved thread state
#elif defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK)
        ; Increment interrupt nesting counter
        mov.l   sp,er1
        mov.l   #__interrupt_stack,er0          ; A0 = interrupt stack top
        cmp.l   #__interrupt_stack_base,sp      ; compare with base of stack
        blt     1f                              ; if lt switch to int stack
        cmp.l   er0,sp                          ; compare sp with stack top
        ble     8f                              ; if le already on istack
1:
        mov.l   er0,sp                          ; switch to new SP
8:
        mov.l   er1,@-sp                        ; save old SP
        
#else
        mov     sp,er1                          ; A2 = saved thread state
#endif
        mov.l   er1,er4

        ; Here D3 contains the table byte offset of the vector to
        ; call.

#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)

        ; Call cyg_instrument to record that this interrupt is being raised.

        .extern CYG_LABEL_DEFN(cyg_instrument)
        mov.l   #0x0301,er0                     ; type = INTR,RAISE
        mov.l   @CYG_LABEL_DEFN(_intvector),er2         ; arg2 = table offset
        jsr     CYG_LABEL_DEFN(cyg_instrument)  ; call instrumentation
        
#endif          

#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING

        ; To allow nested interrupts, we set the IE bit. We do
        ; not touch the IPL bits, so only higher priority interrupts
        ; will be nested on top of us. Also, new interrupts will not
        ; be delivered until the ISR calls 
        ; Cyg_Interrupt::acknowledge_interrupt(). At some future point
        ; we may want to do the ack stuff here to allow immediate nesting.
        
        mov.l   @CYG_LABEL_DEFN(_intvector),er0
        mov.b   @(CYG_LABEL_DEFN(cyg_hal_level_table),er0),r0l
        hal_cpu_set_int_level
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || \
    defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)

        ; If we have Ctrl-C support enabled, save a pointer to the
        ; saved CPU state here so we can plant a breakpoint there if
        ; this is a ^C.
        
        .extern CYG_LABEL_DEFN(hal_saved_interrupt_state)
        mov.l   er4,@CYG_LABEL_DEFN(hal_saved_interrupt_state)
        
#endif
        mov.l   @CYG_LABEL_DEFN(_intvector),er0
        shll2   er0
        mov.l   @(CYG_LABEL_DEFN(hal_interrupt_handlers),er0),er2
        
        mov.l   @(CYG_LABEL_DEFN(hal_interrupt_data),er0),er1

        shlr2   er0

        jsr     @er2

        ; on return d0 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.
        
        ; D3 is defined to be saved across procedure calls, and
        ; should still contain the vector byte index. Similarly,
        ; A2 should still point to the saved machine state.

#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
        ; If interrupt was caused by GDB, the ISR call above
        ; is skipped by jumping here.
2:
#endif

#if defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK) && !defined(CYGPKG_CYGMON)

        ; 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.
        
        mov.l   @sp+,sp                         ; pop old sp

#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.
                
        ; Using the vector offset in D3, get the interrupt object pointer
        ; into D1.
        mov.l   @CYG_LABEL_DEFN(_intvector),er1
        shll2   er1
        mov.l   @(CYG_LABEL_DEFN(hal_interrupt_objects),er1),er1

        ; Even when this is not the last nested interrupt, we must call
        ; _interrupt_end() to post the DSR and decrement the scheduler
        ; lock.
                
        mov.l   er3,er2                         ; arg3 = saved state.
        
        jsr     @CYG_LABEL_DEFN(interrupt_end)  ; call interrupt end fn         
#endif


#       show_interrupts

        hal_diag_restore

        hal_cpu_load_all
#ifdef CYGPKG_CYGMON
        hal_cygmon_restore_app_stack
#endif
        mov.l   er0,@-sp
        mov.l   @(4:16,sp),er0
        mov.l   er0,@__lastpc
        mov.l   @sp+,er0
        
        rte                                     ; and return

        .section        .bss
        .global CYG_LABEL_DEFN(_intvector)
CYG_LABEL_DEFN(_intvector):
        .long   0
        .global __lastpc        
__lastpc:
        .long   0
__interrupt_table:      
        .long   0

        .text   
##-----------------------------------------------------------------------------
## Execute pending DSRs on the interrupt stack with interrupts enabled.
## Note: this can only be called from code running on a thread stack
        
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
        .extern CYG_LABEL_DEFN(cyg_interrupt_call_pending_DSRs)
        .global CYG_LABEL_DEFN(hal_interrupt_stack_call_pending_DSRs)

CYG_LABEL_DEFN(hal_interrupt_stack_call_pending_DSRs):
        h8300_var_call_pending_DSR
#endif          
                
##-----------------------------------------------------------------------------
## Default TRAP VSR

        .text
        .globl  CYG_LABEL_DEFN(__default_trap_vsr)
CYG_LABEL_DEFN(__default_trap_vsr):

#ifdef CYG_HAL_DIAG_EXCPT_END
        hal_diag_excpt_start
#endif
        mov.l   @CYG_LABEL_DEFN(_intvector),er1
        cmp.l   #11,er1         ; Adjust trap entry address
        bne     1f
        h8300_trap_adjust_pc
1:      
        mov.l   sp,er0
        jsr     @CYG_LABEL_DEFN(cyg_hal_exception_handler)

#ifdef CYG_HAL_DIAG_EXCPT_END
        hal_diag_excpt_end
#endif
        hal_cpu_load_all
#ifdef CYGPKG_CYGMON
        hal_cygmon_restore_app_stack
#endif
        rte

##-----------------------------------------------------------------------------
## VSR table. The VSRs pointed to by this table are called from the stubs
## connected to the hardware.

#ifndef CYG_HAL_H8300_VSR_TABLE_DEFINED
        
        .data

        .globl  CYG_LABEL_DEFN(hal_vsr_table)
CYG_LABEL_DEFN(hal_vsr_table):  
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   0
        .long   0
        .long   0
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)
        .long   CYG_LABEL_DEFN(__default_trap_vsr)

        .rept   CYG_ISR_TABLE_SIZE-12
        .long   CYG_LABEL_DEFN(__default_interrupt_vsr)
        .endr
#endif
        
##-----------------------------------------------------------------------------
## Interrupt tables
        
        .data

        .extern CYG_LABEL_DEFN(hal_default_isr)
        
        .globl  CYG_LABEL_DEFN(hal_interrupt_handlers)
CYG_LABEL_DEFN(hal_interrupt_handlers):
        .rept   CYG_ISR_TABLE_SIZE
        .long   CYG_LABEL_DEFN(hal_default_isr)
        .endr
        
        .globl  CYG_LABEL_DEFN(hal_interrupt_data)
CYG_LABEL_DEFN(hal_interrupt_data):
        .rept   CYG_ISR_TABLE_SIZE
        .long   0
        .endr
        
        .globl  CYG_LABEL_DEFN(hal_interrupt_objects)
CYG_LABEL_DEFN(hal_interrupt_objects):
        .rept   CYG_ISR_TABLE_SIZE
        .long   0
        .endr
        
                        
##-----------------------------------------------------------------------------
## Temporary interrupt stack
        
        .section        .bss

        .balign 2
        .global _cyg_interrupt_stack_base
_cyg_interrupt_stack_base:
__interrupt_stack_base:
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
        .byte 0
        .endr
        .balign 2
        .global _cyg_interrupt_stack
_cyg_interrupt_stack:
__interrupt_stack:
        
#ifdef CYGPKG_CYGMON
        .balign 2
        .global __cygmon_interrupt_stack_base
__cygmon_interrupt_stack_base:
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
        .byte 0
        .endr
        .balign 2
        .global __cygmon_interrupt_stack
__cygmon_interrupt_stack:
#endif

        .long   0,0,0,0,0,0,0,0 

##-----------------------------------------------------------------------------

        .data
        hal_diag_data


##-----------------------------------------------------------------------------
## end of vectors.S

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.