1/* 2 * arch/sh/kernel/cpu/sh2a/entry.S 3 * 4 * The SH-2A exception entry 5 * 6 * Copyright (C) 2008 Yoshinori Sato 7 * Based on arch/sh/kernel/cpu/sh2/entry.S 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 */ 13 14#include <linux/linkage.h> 15#include <asm/asm-offsets.h> 16#include <asm/thread_info.h> 17#include <cpu/mmu_context.h> 18#include <asm/unistd.h> 19#include <asm/errno.h> 20#include <asm/page.h> 21 22/* Offsets to the stack */ 23OFF_R0 = 0 /* Return value. New ABI also arg4 */ 24OFF_R1 = 4 /* New ABI: arg5 */ 25OFF_R2 = 8 /* New ABI: arg6 */ 26OFF_R3 = 12 /* New ABI: syscall_nr */ 27OFF_R4 = 16 /* New ABI: arg0 */ 28OFF_R5 = 20 /* New ABI: arg1 */ 29OFF_R6 = 24 /* New ABI: arg2 */ 30OFF_R7 = 28 /* New ABI: arg3 */ 31OFF_SP = (15*4) 32OFF_PC = (16*4) 33OFF_SR = (16*4+2*4) 34OFF_TRA = (16*4+6*4) 35 36#include <asm/entry-macros.S> 37 38ENTRY(exception_handler) 39 ! stack 40 ! r0 <- point sp 41 ! r1 42 ! pc 43 ! sr 44 ! r0 = temporary 45 ! r1 = vector (pseudo EXPEVT / INTEVT / TRA) 46 mov.l r2,@-sp 47 cli 48 mov.l $cpu_mode,r2 49 bld.b #6,@(0,r2) !previus SR.MD 50 bst.b #6,@(4*4,r15) !set cpu mode to SR.MD 51 bt 1f 52 ! switch to kernel mode 53 bset.b #6,@(0,r2) !set SR.MD 54 mov.l $current_thread_info,r2 55 mov.l @r2,r2 56 mov #(THREAD_SIZE >> 8),r0 57 shll8 r0 58 add r2,r0 ! r0 = kernel stack tail 59 mov r15,r2 ! r2 = user stack top 60 mov r0,r15 ! switch kernel stack 61 mov.l r1,@-r15 ! TRA 62 sts.l macl, @-r15 63 sts.l mach, @-r15 64 stc.l gbr, @-r15 65 mov.l @(4*4,r2),r0 66 mov.l r0,@-r15 ! original SR 67 sts.l pr,@-r15 68 mov.l @(3*4,r2),r0 69 mov.l r0,@-r15 ! original PC 70 mov r2,r0 71 add #(3+2)*4,r0 ! rewind r0 - r3 + exception frame 72 lds r0,pr ! pr = original SP 73 movmu.l r3,@-r15 ! save regs 74 mov r2,r8 ! r8 = previus stack top 75 mov r1,r9 ! r9 = interrupt vector 76 ! restore previous stack 77 mov.l @r8+,r2 78 mov.l @r8+,r0 79 mov.l @r8+,r1 80 bra 2f 81 movml.l r2,@-r15 821: 83 ! in kernel exception 84 mov r15,r2 85 add #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15 86 movmu.l r3,@-r15 87 mov r2,r8 ! r8 = previous stack top 88 mov r1,r9 ! r9 = interrupt vector 89 ! restore exception frame & regs 90 mov.l @r8+,r2 ! old R2 91 mov.l @r8+,r0 ! old R0 92 mov.l @r8+,r1 ! old R1 93 mov.l @r8+,r10 ! old PC 94 mov.l @r8+,r11 ! old SR 95 movml.l r2,@-r15 96 mov.l r10,@(OFF_PC,r15) 97 mov.l r11,@(OFF_SR,r15) 98 mov.l r8,@(OFF_SP,r15) ! save old sp 99 mov r15,r8 100 add #OFF_TRA + 4,r8 101 mov.l r9,@-r8 102 sts.l macl,@-r8 103 sts.l mach,@-r8 104 stc.l gbr,@-r8 105 add #-4,r8 106 sts.l pr,@-r8 1072: 108 ! dispatch exception / interrupt 109 mov #64,r8 110 cmp/hs r8,r9 111 bt interrupt_entry ! vec >= 64 is interrupt 112 mov #32,r8 113 cmp/hs r8,r9 114 bt trap_entry ! 64 > vec >= 32 is trap 115 116 mov.l 4f,r8 117 mov r9,r4 118 shll2 r9 119 add r9,r8 120 mov.l @r8,r8 ! exception handler address 121 tst r8,r8 122 bf 3f 123 mov.l 8f,r8 ! unhandled exception 1243: 125 mov.l 5f,r10 126 jmp @r8 127 lds r10,pr 128 129interrupt_entry: 130 mov r9,r4 131 mov r15,r5 132 mov.l 7f,r8 133 mov.l 6f,r9 134 jmp @r8 135 lds r9,pr 136 137 .align 2 1384: .long exception_handling_table 1395: .long ret_from_exception 1406: .long ret_from_irq 1417: .long do_IRQ 1428: .long exception_error 143 144trap_entry: 145 mov #0x30,r8 146 cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall 147 bt 1f 148 add #-0x10,r9 ! convert SH2 to SH3/4 ABI 1491: 150 shll2 r9 ! TRA 151 bra system_call ! jump common systemcall entry 152 mov r9,r8 153 154#if defined(CONFIG_SH_STANDARD_BIOS) 155 /* Unwind the stack and jmp to the debug entry */ 156ENTRY(sh_bios_handler) 157 mov r15,r0 158 add #(22-4)*4-4,r0 159 ldc.l @r0+,gbr 160 lds.l @r0+,mach 161 lds.l @r0+,macl 162 mov r15,r0 163 mov.l @(OFF_SP,r0),r1 164 mov.l @(OFF_SR,r2),r3 165 mov.l r3,@-r1 166 mov.l @(OFF_SP,r2),r3 167 mov.l r3,@-r1 168 mov r15,r0 169 add #(22-4)*4-8,r0 170 mov.l 1f,r2 171 mov.l @r2,r2 172 stc sr,r3 173 mov.l r2,@r0 174 mov.l r3,@(4,r0) 175 mov.l r1,@(8,r0) 176 movml.l @r15+,r14 177 add #8,r15 178 lds.l @r15+, pr 179 mov.l @r15+,r15 180 rte 181 nop 182 .align 2 1831: .long gdb_vbr_vector 184#endif /* CONFIG_SH_STANDARD_BIOS */ 185 186ENTRY(address_error_trap_handler) 187 mov r15,r4 ! regs 188 mov.l @(OFF_PC,r15),r6 ! pc 189 mov.l 1f,r0 190 jmp @r0 191 mov #0,r5 ! writeaccess is unknown 192 193 .align 2 1941: .long do_address_error 195 196restore_all: 197 stc sr,r0 198 or #0xf0,r0 199 ldc r0,sr ! all interrupt block (same BL = 1) 200 ! restore special register 201 ! overlap exception frame 202 mov r15,r0 203 add #17*4,r0 204 lds.l @r0+,pr 205 add #4,r0 206 ldc.l @r0+,gbr 207 lds.l @r0+,mach 208 lds.l @r0+,macl 209 mov r15,r0 210 mov.l $cpu_mode,r2 211 bld.b #6,@(OFF_SR,r15) 212 bst.b #6,@(0,r2) ! save CPU mode 213 mov.l @(OFF_SR,r0),r1 214 shll2 r1 215 shlr2 r1 ! clear MD bit 216 mov.l @(OFF_SP,r0),r2 217 add #-8,r2 218 mov.l r2,@(OFF_SP,r0) ! point exception frame top 219 mov.l r1,@(4,r2) ! set sr 220 mov.l @(OFF_PC,r0),r1 221 mov.l r1,@r2 ! set pc 222 get_current_thread_info r0, r1 223 mov.l $current_thread_info,r1 224 mov.l r0,@r1 225 movml.l @r15+,r14 226 mov.l @r15,r15 227 rte 228 nop 229 230 .align 2 231$current_thread_info: 232 .long __current_thread_info 233$cpu_mode: 234 .long __cpu_mode 235 236! common exception handler 237#include "../../entry-common.S" 238 239 .data 240! cpu operation mode 241! bit30 = MD (compatible SH3/4) 242__cpu_mode: 243 .long 0x40000000 244 245 .section .bss 246__current_thread_info: 247 .long 0 248 249ENTRY(exception_handling_table) 250 .space 4*32 251