1/* 2 * arch/sh/kernel/cpu/sh2/entry.S 3 * 4 * The SH-2 exception entry 5 * 6 * Copyright (C) 2005,2006 Yoshinori Sato 7 * Copyright (C) 2005 AXE,Inc. 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 <asm/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 ! already saved r0/r1 40 mov.l r2,@-sp 41 mov.l r3,@-sp 42 mov r0,r1 43 cli 44 mov.l $cpu_mode,r2 45 mov.l @r2,r0 46 mov.l @(5*4,r15),r3 ! previous SR 47 shll2 r3 ! set "S" flag 48 rotl r0 ! T <- "S" flag 49 rotl r0 ! "S" flag is LSB 50 rotcr r3 ! T -> r3:b30 51 shlr r3 52 shlr r0 53 bt/s 1f 54 mov.l r3,@(5*4,r15) ! copy cpu mode to SR 55 ! switch to kernel mode 56 mov #1,r0 57 rotr r0 58 rotr r0 59 mov.l r0,@r2 ! enter kernel mode 60 mov.l $current_thread_info,r2 61 mov.l @r2,r2 62 mov #0x20,r0 63 shll8 r0 64 add r2,r0 65 mov r15,r2 ! r2 = user stack top 66 mov r0,r15 ! switch kernel stack 67 add #-4,r15 ! dummy 68 mov.l r1,@-r15 ! TRA 69 sts.l macl, @-r15 70 sts.l mach, @-r15 71 stc.l gbr, @-r15 72 mov.l @(4*4,r2),r0 73 mov.l @(5*4,r2),r1 74 mov.l r1,@-r15 ! original SR 75 sts.l pr,@-r15 76 mov.l r0,@-r15 ! original PC 77 mov r2,r3 78 add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame 79 mov.l r3,@-r15 ! original SP 80 mov.l r14,@-r15 81 mov.l r13,@-r15 82 mov.l r12,@-r15 83 mov.l r11,@-r15 84 mov.l r10,@-r15 85 mov.l r9,@-r15 86 mov.l r8,@-r15 87 mov.l r7,@-r15 88 mov.l r6,@-r15 89 mov.l r5,@-r15 90 mov.l r4,@-r15 91 mov r2,r8 ! copy user -> kernel stack 92 mov.l @r8+,r3 93 mov.l r3,@-r15 94 mov.l @r8+,r2 95 mov.l r2,@-r15 96 mov.l @r8+,r1 97 mov.l r1,@-r15 98 mov.l @r8+,r0 99 bra 2f 100 mov.l r0,@-r15 1011: 102 ! in kernel exception 103 mov #(22-4-4-1)*4+4,r0 104 mov r15,r2 105 sub r0,r15 106 mov.l @r2+,r0 ! old R3 107 mov.l r0,@-r15 108 mov.l @r2+,r0 ! old R2 109 mov.l r0,@-r15 110 mov.l @r2+,r0 ! old R1 111 mov.l r0,@-r15 112 mov.l @r2+,r0 ! old R0 113 mov.l r0,@-r15 114 mov.l @r2+,r3 ! old PC 115 mov.l @r2+,r0 ! old SR 116 add #-4,r2 ! exception frame stub (sr) 117 mov.l r1,@-r2 ! TRA 118 sts.l macl, @-r2 119 sts.l mach, @-r2 120 stc.l gbr, @-r2 121 mov.l r0,@-r2 ! save old SR 122 sts.l pr,@-r2 123 mov.l r3,@-r2 ! save old PC 124 mov r2,r0 125 add #8*4,r0 126 mov.l r0,@-r2 ! save old SP 127 mov.l r14,@-r2 128 mov.l r13,@-r2 129 mov.l r12,@-r2 130 mov.l r11,@-r2 131 mov.l r10,@-r2 132 mov.l r9,@-r2 133 mov.l r8,@-r2 134 mov.l r7,@-r2 135 mov.l r6,@-r2 136 mov.l r5,@-r2 137 mov.l r4,@-r2 138 mov.l @(OFF_R0,r15),r0 139 mov.l @(OFF_R1,r15),r1 140 mov.l @(OFF_R2,r15),r2 141 mov.l @(OFF_R3,r15),r3 1422: 143 mov #OFF_TRA,r8 144 add r15,r8 145 mov.l @r8,r9 146 mov #64,r8 147 cmp/hs r8,r9 148 bt interrupt_entry ! vec >= 64 is interrupt 149 mov #32,r8 150 cmp/hs r8,r9 151 bt trap_entry ! 64 > vec >= 32 is trap 152 mov.l 4f,r8 153 mov r9,r4 154 shll2 r9 155 add r9,r8 156 mov.l @r8,r8 157 mov #0,r9 158 cmp/eq r9,r8 159 bf 3f 160 mov.l 8f,r8 ! unhandled exception 1613: 162 mov.l 5f,r10 163 jmp @r8 164 lds r10,pr 165 166interrupt_entry: 167 mov r9,r4 168 mov r15,r5 169 mov.l 6f,r9 170 mov.l 7f,r8 171 jmp @r8 172 lds r9,pr 173 174 .align 2 1754: .long exception_handling_table 1765: .long ret_from_exception 1776: .long ret_from_irq 1787: .long do_IRQ 1798: .long do_exception_error 180 181trap_entry: 182 mov #0x30,r8 183 cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall 184 bt 1f 185 add #-0x10,r9 ! convert SH2 to SH3/4 ABI 1861: 187 shll2 r9 ! TRA 188 mov #OFF_TRA,r8 189 add r15,r8 190 mov.l r9,@r8 191 mov r9,r8 192#ifdef CONFIG_TRACE_IRQFLAGS 193 mov.l 2f, r9 194 jsr @r9 195 nop 196#endif 197 sti 198 bra system_call 199 nop 200 201 .align 2 202#ifdef CONFIG_TRACE_IRQFLAGS 2032: .long trace_hardirqs_on 204#endif 205 206#if defined(CONFIG_SH_STANDARD_BIOS) 207 /* Unwind the stack and jmp to the debug entry */ 208ENTRY(sh_bios_handler) 209 mov r15,r0 210 add #(22-4)*4-4,r0 211 ldc.l @r0+,gbr 212 lds.l @r0+,mach 213 lds.l @r0+,macl 214 mov r15,r0 215 mov.l @(OFF_SP,r0),r1 216 mov #OFF_SR,r2 217 mov.l @(r0,r2),r3 218 mov.l r3,@-r1 219 mov #OFF_SP,r2 220 mov.l @(r0,r2),r3 221 mov.l r3,@-r1 222 mov r15,r0 223 add #(22-4)*4-8,r0 224 mov.l 1f,r2 225 mov.l @r2,r2 226 stc sr,r3 227 mov.l r2,@r0 228 mov.l r3,@r0 229 mov.l r1,@(8,r0) 230 mov.l @r15+, r0 231 mov.l @r15+, r1 232 mov.l @r15+, r2 233 mov.l @r15+, r3 234 mov.l @r15+, r4 235 mov.l @r15+, r5 236 mov.l @r15+, r6 237 mov.l @r15+, r7 238 mov.l @r15+, r8 239 mov.l @r15+, r9 240 mov.l @r15+, r10 241 mov.l @r15+, r11 242 mov.l @r15+, r12 243 mov.l @r15+, r13 244 mov.l @r15+, r14 245 add #8,r15 246 lds.l @r15+, pr 247 rte 248 mov.l @r15+,r15 249 .align 2 2501: .long gdb_vbr_vector 251#endif /* CONFIG_SH_STANDARD_BIOS */ 252 253ENTRY(address_error_handler) 254 mov r15,r4 ! regs 255 add #4,r4 256 mov #OFF_PC,r0 257 mov.l @(r0,r15),r6 ! pc 258 mov.l 1f,r0 259 jmp @r0 260 mov #0,r5 ! writeaccess is unknown 261 .align 2 262 2631: .long do_address_error 264 265restore_all: 266 cli 267#ifdef CONFIG_TRACE_IRQFLAGS 268 mov.l 1f, r0 269 jsr @r0 270 nop 271#endif 272 mov r15,r0 273 mov.l $cpu_mode,r2 274 mov #OFF_SR,r3 275 mov.l @(r0,r3),r1 276 mov.l r1,@r2 277 shll2 r1 ! clear MD bit 278 shlr2 r1 279 mov.l @(OFF_SP,r0),r2 280 add #-8,r2 281 mov.l r2,@(OFF_SP,r0) ! point exception frame top 282 mov.l r1,@(4,r2) ! set sr 283 mov #OFF_PC,r3 284 mov.l @(r0,r3),r1 285 mov.l r1,@r2 ! set pc 286 add #4*16+4,r0 287 lds.l @r0+,pr 288 add #4,r0 ! skip sr 289 ldc.l @r0+,gbr 290 lds.l @r0+,mach 291 lds.l @r0+,macl 292 get_current_thread_info r0, r1 293 mov.l $current_thread_info,r1 294 mov.l r0,@r1 295 mov.l @r15+,r0 296 mov.l @r15+,r1 297 mov.l @r15+,r2 298 mov.l @r15+,r3 299 mov.l @r15+,r4 300 mov.l @r15+,r5 301 mov.l @r15+,r6 302 mov.l @r15+,r7 303 mov.l @r15+,r8 304 mov.l @r15+,r9 305 mov.l @r15+,r10 306 mov.l @r15+,r11 307 mov.l @r15+,r12 308 mov.l @r15+,r13 309 mov.l @r15+,r14 310 mov.l @r15,r15 311 rte 312 nop 313 314 .align 2 315#ifdef CONFIG_TRACE_IRQFLAGS 3161: .long trace_hardirqs_off 317#endif 318$current_thread_info: 319 .long __current_thread_info 320$cpu_mode: 321 .long __cpu_mode 322 323! common exception handler 324#include "../../entry-common.S" 325 326 .data 327! cpu operation mode 328! bit30 = MD (compatible SH3/4) 329__cpu_mode: 330 .long 0x40000000 331 332 .section .bss 333__current_thread_info: 334 .long 0 335 336ENTRY(exception_handling_table) 337 .space 4*32 338