Back to home page

LXR

 
 

    


0001 /*
0002  * arch/sh/kernel/cpu/sh2a/entry.S
0003  *
0004  * The SH-2A exception entry
0005  *
0006  * Copyright (C) 2008 Yoshinori Sato
0007  * Based on arch/sh/kernel/cpu/sh2/entry.S
0008  *
0009  * This file is subject to the terms and conditions of the GNU General Public
0010  * License.  See the file "COPYING" in the main directory of this archive
0011  * for more details.
0012  */
0013 
0014 #include <linux/linkage.h>
0015 #include <asm/asm-offsets.h>
0016 #include <asm/thread_info.h>
0017 #include <cpu/mmu_context.h>
0018 #include <asm/unistd.h>
0019 #include <asm/errno.h>
0020 #include <asm/page.h>
0021     
0022 /* Offsets to the stack */
0023 OFF_R0  =  0        /* Return value. New ABI also arg4 */
0024 OFF_R1  =  4        /* New ABI: arg5 */
0025 OFF_R2  =  8        /* New ABI: arg6 */
0026 OFF_R3  =  12       /* New ABI: syscall_nr */
0027 OFF_R4  =  16       /* New ABI: arg0 */
0028 OFF_R5  =  20       /* New ABI: arg1 */
0029 OFF_R6  =  24       /* New ABI: arg2 */
0030 OFF_R7  =  28       /* New ABI: arg3 */
0031 OFF_SP  =  (15*4)
0032 OFF_PC  =  (16*4)
0033 OFF_SR  =  (16*4+2*4)
0034 OFF_TRA =  (16*4+6*4)
0035 
0036 #include <asm/entry-macros.S>
0037 
0038 ENTRY(exception_handler)
0039     ! stack
0040     ! r0 <- point sp
0041     ! r1
0042     ! pc
0043     ! sr
0044     ! r0 = temporary
0045     ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
0046     mov.l   r2,@-sp
0047     cli
0048     mov.l   $cpu_mode,r2
0049     bld.b   #6,@(0,r2)  !previus SR.MD
0050     bst.b   #6,@(4*4,r15)   !set cpu mode to SR.MD
0051     bt  1f
0052     ! switch to kernel mode
0053     bset.b  #6,@(0,r2)  !set SR.MD
0054     mov.l   $current_thread_info,r2
0055     mov.l   @r2,r2
0056     mov #(THREAD_SIZE >> 8),r0
0057     shll8   r0
0058     add r2,r0       ! r0 = kernel stack tail
0059     mov r15,r2      ! r2 = user stack top
0060     mov r0,r15      ! switch kernel stack
0061     mov.l   r1,@-r15    ! TRA
0062     sts.l   macl, @-r15
0063     sts.l   mach, @-r15
0064     stc.l   gbr, @-r15
0065     mov.l   @(4*4,r2),r0
0066     mov.l   r0,@-r15    ! original SR
0067     sts.l   pr,@-r15
0068     mov.l   @(3*4,r2),r0
0069     mov.l   r0,@-r15    ! original PC
0070     mov r2,r0
0071     add #(3+2)*4,r0 ! rewind r0 - r3 + exception frame
0072     lds r0,pr       ! pr = original SP
0073     movmu.l r3,@-r15    ! save regs
0074     mov r2,r8       ! r8 =  previus stack top
0075     mov r1,r9       ! r9 = interrupt vector
0076     ! restore previous stack
0077     mov.l   @r8+,r2
0078     mov.l   @r8+,r0
0079     mov.l   @r8+,r1
0080     bra 2f
0081      movml.l r2,@-r15
0082 1:
0083     ! in kernel exception
0084     mov r15,r2
0085     add #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
0086     movmu.l r3,@-r15
0087     mov r2,r8       ! r8 = previous stack top
0088     mov r1,r9       ! r9 = interrupt vector
0089     ! restore exception frame & regs
0090     mov.l   @r8+,r2     ! old R2
0091     mov.l   @r8+,r0     ! old R0
0092     mov.l   @r8+,r1     ! old R1
0093     mov.l   @r8+,r10    ! old PC
0094     mov.l   @r8+,r11    ! old SR
0095     movml.l r2,@-r15
0096     mov.l   r10,@(OFF_PC,r15)
0097     mov.l   r11,@(OFF_SR,r15)
0098     mov.l   r8,@(OFF_SP,r15)    ! save old sp
0099     mov r15,r8
0100     add #OFF_TRA + 4,r8
0101     mov.l   r9,@-r8
0102     sts.l   macl,@-r8
0103     sts.l   mach,@-r8
0104     stc.l   gbr,@-r8
0105     add #-4,r8
0106     sts.l   pr,@-r8
0107 2:
0108     ! dispatch exception / interrupt
0109     mov #64,r8
0110     cmp/hs  r8,r9
0111     bt  interrupt_entry ! vec >= 64 is interrupt
0112     mov #31,r8
0113     cmp/hs  r8,r9
0114     bt  trap_entry  ! 64 > vec >= 31  is trap
0115 
0116     mov.l   4f,r8
0117     mov r9,r4
0118     shll2   r9
0119     add r9,r8
0120     mov.l   @r8,r8      ! exception handler address
0121     tst r8,r8
0122     bf  3f
0123     mov.l   8f,r8       ! unhandled exception
0124 3:
0125     mov.l   5f,r10
0126     jmp @r8
0127      lds    r10,pr
0128 
0129 interrupt_entry:
0130     mov r9,r4
0131     mov r15,r5
0132     mov.l   7f,r8
0133     mov.l   6f,r9
0134     jmp @r8
0135      lds    r9,pr
0136 
0137     .align  2
0138 4:  .long   exception_handling_table
0139 5:  .long   ret_from_exception
0140 6:  .long   ret_from_irq
0141 7:  .long   do_IRQ
0142 8:  .long   exception_error
0143 
0144 trap_entry:
0145     mov #0x30,r8
0146     cmp/ge  r8,r9       ! vector 0x1f-0x2f is systemcall
0147     bt  1f
0148     mov     #0x1f,r9    ! convert to unified SH2/3/4 trap number
0149 1:  
0150     shll2   r9          ! TRA
0151     bra system_call ! jump common systemcall entry
0152      mov    r9,r8
0153     
0154 #if defined(CONFIG_SH_STANDARD_BIOS)
0155     /* Unwind the stack and jmp to the debug entry */
0156 ENTRY(sh_bios_handler)
0157     mov r15,r0
0158     add #(22-4)*4-4,r0
0159     ldc.l   @r0+,gbr
0160     lds.l   @r0+,mach
0161     lds.l   @r0+,macl
0162     mov r15,r0
0163     mov.l   @(OFF_SP,r0),r1
0164     mov.l   @(OFF_SR,r2),r3
0165     mov.l   r3,@-r1
0166     mov.l   @(OFF_SP,r2),r3
0167     mov.l   r3,@-r1
0168     mov r15,r0
0169     add #(22-4)*4-8,r0
0170     mov.l   1f,r2
0171     mov.l   @r2,r2
0172     stc sr,r3
0173     mov.l   r2,@r0
0174     mov.l   r3,@(4,r0)
0175     mov.l   r1,@(8,r0)
0176     movml.l @r15+,r14
0177     add #8,r15
0178     lds.l   @r15+, pr
0179     mov.l   @r15+,r15
0180     rte
0181      nop
0182     .align  2
0183 1:  .long   gdb_vbr_vector
0184 #endif /* CONFIG_SH_STANDARD_BIOS */
0185 
0186 ENTRY(address_error_trap_handler)
0187     mov r15,r4              ! regs
0188     mov.l   @(OFF_PC,r15),r6        ! pc
0189     mov.l   1f,r0
0190     jmp @r0
0191      mov    #0,r5               ! writeaccess is unknown
0192 
0193     .align  2
0194 1:  .long   do_address_error
0195 
0196 restore_all:
0197     stc sr,r0
0198     or  #0xf0,r0
0199     ldc r0,sr               ! all interrupt block (same BL = 1)
0200     ! restore special register
0201     ! overlap exception frame
0202     mov r15,r0
0203     add #17*4,r0
0204     lds.l   @r0+,pr
0205     add #4,r0
0206     ldc.l   @r0+,gbr
0207     lds.l   @r0+,mach
0208     lds.l   @r0+,macl
0209     mov r15,r0
0210     mov.l   $cpu_mode,r2
0211     bld.b   #6,@(OFF_SR,r15)
0212     bst.b   #6,@(0,r2)          ! save CPU mode
0213     mov.l   @(OFF_SR,r0),r1
0214     shll2   r1
0215     shlr2   r1              ! clear MD bit
0216     mov.l   @(OFF_SP,r0),r2
0217     add #-8,r2
0218     mov.l   r2,@(OFF_SP,r0)         ! point exception frame top
0219     mov.l   r1,@(4,r2)          ! set sr
0220     mov.l   @(OFF_PC,r0),r1
0221     mov.l   r1,@r2              ! set pc
0222     get_current_thread_info r0, r1
0223     mov.l   $current_thread_info,r1
0224     mov.l   r0,@r1
0225     movml.l @r15+,r14
0226     mov.l   @r15,r15
0227     rte
0228      nop
0229 
0230     .align 2
0231 $current_thread_info:
0232     .long   __current_thread_info
0233 $cpu_mode:  
0234     .long   __cpu_mode
0235         
0236 ! common exception handler
0237 #include "../../entry-common.S"
0238     
0239     .data
0240 ! cpu operation mode 
0241 ! bit30 = MD (compatible SH3/4)
0242 __cpu_mode:
0243     .long   0x40000000
0244         
0245     .section    .bss
0246 __current_thread_info:
0247     .long   0
0248 
0249 ENTRY(exception_handling_table)
0250     .space  4*32