1/* -*- mode: asm -*- 2 * 3 * linux/arch/h8300/platform/h8300h/entry.S 4 * 5 * Yoshinori Sato <ysato@users.sourceforge.jp> 6 * David McCullough <davidm@snapgear.com> 7 * 8 */ 9 10/* 11 * entry.S 12 * include exception/interrupt gateway 13 * system call entry 14 */ 15 16#include <linux/sys.h> 17#include <asm/unistd.h> 18#include <asm/setup.h> 19#include <asm/segment.h> 20#include <asm/linkage.h> 21#include <asm/asm-offsets.h> 22#include <asm/thread_info.h> 23#include <asm/errno.h> 24 25#if defined(CONFIG_CPU_H8300H) 26#define USERRET 8 27INTERRUPTS = 64 28 .h8300h 29 .macro SHLL2 reg 30 shll.l \reg 31 shll.l \reg 32 .endm 33 .macro SHLR2 reg 34 shlr.l \reg 35 shlr.l \reg 36 .endm 37 .macro SAVEREGS 38 mov.l er0,@-sp 39 mov.l er1,@-sp 40 mov.l er2,@-sp 41 mov.l er3,@-sp 42 .endm 43 .macro RESTOREREGS 44 mov.l @sp+,er3 45 mov.l @sp+,er2 46 .endm 47 .macro SAVEEXR 48 .endm 49 .macro RESTOREEXR 50 .endm 51#endif 52#if defined(CONFIG_CPU_H8S) 53#define USERRET 10 54#define USEREXR 8 55INTERRUPTS = 128 56 .h8300s 57 .macro SHLL2 reg 58 shll.l #2,\reg 59 .endm 60 .macro SHLR2 reg 61 shlr.l #2,\reg 62 .endm 63 .macro SAVEREGS 64 stm.l er0-er3,@-sp 65 .endm 66 .macro RESTOREREGS 67 ldm.l @sp+,er2-er3 68 .endm 69 .macro SAVEEXR 70 mov.w @(USEREXR:16,er0),r1 71 mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */ 72 .endm 73 .macro RESTOREEXR 74 mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */ 75 mov.b r1l,r1h 76 mov.w r1,@(USEREXR:16,er0) 77 .endm 78#endif 79 80 81/* CPU context save/restore macros. */ 82 83 .macro SAVE_ALL 84 mov.l er0,@-sp 85 stc ccr,r0l /* check kernel mode */ 86 btst #4,r0l 87 bne 5f 88 89 /* user mode */ 90 mov.l sp,@SYMBOL_NAME(sw_usp) 91 mov.l @sp,er0 /* restore saved er0 */ 92 orc #0x10,ccr /* switch kernel stack */ 93 mov.l @SYMBOL_NAME(sw_ksp),sp 94 sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */ 95 SAVEREGS 96 mov.l @SYMBOL_NAME(sw_usp),er0 97 mov.l @(USERRET:16,er0),er1 /* copy the RET addr */ 98 mov.l er1,@(LRET-LER3:16,sp) 99 SAVEEXR 100 101 mov.l @(LORIG-LER3:16,sp),er0 102 mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */ 103 mov.w e1,r1 /* e1 highbyte = ccr */ 104 and #0xef,r1h /* mask mode? flag */ 105 bra 6f 1065: 107 /* kernel mode */ 108 mov.l @sp,er0 /* restore saved er0 */ 109 subs #2,sp /* set dummy ccr */ 110 SAVEREGS 111 mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */ 1126: 113 mov.b r1h,r1l 114 mov.b #0,r1h 115 mov.w r1,@(LCCR-LER3:16,sp) /* set ccr */ 116 mov.l er6,@-sp /* syscall arg #6 */ 117 mov.l er5,@-sp /* syscall arg #5 */ 118 mov.l er4,@-sp /* syscall arg #4 */ 119 .endm /* r1 = ccr */ 120 121 .macro RESTORE_ALL 122 mov.l @sp+,er4 123 mov.l @sp+,er5 124 mov.l @sp+,er6 125 RESTOREREGS 126 mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */ 127 btst #4,r0l 128 bne 7f 129 130 orc #0x80,ccr 131 mov.l @SYMBOL_NAME(sw_usp),er0 132 mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */ 133 mov.l er1,@er0 134 RESTOREEXR 135 mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */ 136 mov.b r1l,r1h 137 mov.b @(LRET+1-LER1:16,sp),r1l 138 mov.w r1,e1 139 mov.w @(LRET+2-LER1:16,sp),r1 140 mov.l er1,@(USERRET:16,er0) 141 142 mov.l @sp+,er1 143 add.l #(LRET-LER1),sp /* remove LORIG - LRET */ 144 mov.l sp,@SYMBOL_NAME(sw_ksp) 145 andc #0xef,ccr /* switch to user mode */ 146 mov.l er0,sp 147 bra 8f 1487: 149 mov.l @sp+,er1 150 adds #4,sp 151 adds #2,sp 1528: 153 mov.l @sp+,er0 154 adds #4,sp /* remove the sw created LVEC */ 155 rte 156 .endm 157 158.globl SYMBOL_NAME(system_call) 159.globl SYMBOL_NAME(ret_from_exception) 160.globl SYMBOL_NAME(ret_from_fork) 161.globl SYMBOL_NAME(ret_from_interrupt) 162.globl SYMBOL_NAME(interrupt_redirect_table) 163.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) 164.globl SYMBOL_NAME(resume) 165.globl SYMBOL_NAME(interrupt_entry) 166.globl SYMBOL_NAME(trace_break) 167 168#if defined(CONFIG_ROMKERNEL) 169 .section .int_redirect,"ax" 170SYMBOL_NAME_LABEL(interrupt_redirect_table) 171#if defined(CONFIG_CPU_H8300H) 172 .rept 7 173 .long 0 174 .endr 175#endif 176#if defined(CONFIG_CPU_H8S) 177 .rept 5 178 .long 0 179 .endr 180 jmp @SYMBOL_NAME(trace_break) 181 .long 0 182#endif 183 184 jsr @SYMBOL_NAME(interrupt_entry) /* NMI */ 185 jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */ 186 .long 0 187 .long 0 188 jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */ 189 .rept INTERRUPTS-12 190 jsr @SYMBOL_NAME(interrupt_entry) 191 .endr 192#endif 193#if defined(CONFIG_RAMKERNEL) 194.globl SYMBOL_NAME(interrupt_redirect_table) 195 .section .bss 196SYMBOL_NAME_LABEL(interrupt_redirect_table) 197 .space 4 198#endif 199 200 .section .text 201 .align 2 202SYMBOL_NAME_LABEL(interrupt_entry) 203 SAVE_ALL 204 mov.l sp,er0 205 add.l #LVEC,er0 206 btst #4,r1l 207 bne 1f 208 /* user LVEC */ 209 mov.l @SYMBOL_NAME(sw_usp),er0 210 adds #4,er0 2111: 212 mov.l @er0,er0 /* LVEC address */ 213#if defined(CONFIG_ROMKERNEL) 214 sub.l #SYMBOL_NAME(interrupt_redirect_table),er0 215#endif 216#if defined(CONFIG_RAMKERNEL) 217 mov.l @SYMBOL_NAME(interrupt_redirect_table),er1 218 sub.l er1,er0 219#endif 220 SHLR2 er0 221 dec.l #1,er0 222 mov.l sp,er1 223 subs #4,er1 /* adjust ret_pc */ 224 jsr @SYMBOL_NAME(do_IRQ) 225 jmp @SYMBOL_NAME(ret_from_interrupt) 226 227SYMBOL_NAME_LABEL(system_call) 228 subs #4,sp /* dummy LVEC */ 229 SAVE_ALL 230 andc #0x7f,ccr 231 mov.l er0,er4 232 233 /* save top of frame */ 234 mov.l sp,er0 235 jsr @SYMBOL_NAME(set_esp0) 236 mov.l sp,er2 237 and.w #0xe000,r2 238 mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l 239 btst #(TIF_SYSCALL_TRACE & 7),r2l 240 beq 1f 241 jsr @SYMBOL_NAME(do_syscall_trace) 2421: 243 cmp.l #NR_syscalls,er4 244 bcc badsys 245 SHLL2 er4 246 mov.l #SYMBOL_NAME(sys_call_table),er0 247 add.l er4,er0 248 mov.l @er0,er4 249 beq SYMBOL_NAME(ret_from_exception):16 250 mov.l @(LER1:16,sp),er0 251 mov.l @(LER2:16,sp),er1 252 mov.l @(LER3:16,sp),er2 253 jsr @er4 254 mov.l er0,@(LER0:16,sp) /* save the return value */ 255 mov.l sp,er2 256 and.w #0xe000,r2 257 mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l 258 btst #(TIF_SYSCALL_TRACE & 7),r2l 259 beq 2f 260 jsr @SYMBOL_NAME(do_syscall_trace) 2612: 262#if defined(CONFIG_SYSCALL_PRINT) 263 jsr @SYMBOL_NAME(syscall_print) 264#endif 265 orc #0x80,ccr 266 bra resume_userspace 267 268badsys: 269 mov.l #-ENOSYS,er0 270 mov.l er0,@(LER0:16,sp) 271 bra resume_userspace 272 273#if !defined(CONFIG_PREEMPT) 274#define resume_kernel restore_all 275#endif 276 277SYMBOL_NAME_LABEL(ret_from_exception) 278#if defined(CONFIG_PREEMPT) 279 orc #0x80,ccr 280#endif 281SYMBOL_NAME_LABEL(ret_from_interrupt) 282 mov.b @(LCCR+1:16,sp),r0l 283 btst #4,r0l 284 bne resume_kernel:8 /* return from kernel */ 285resume_userspace: 286 andc #0x7f,ccr 287 mov.l sp,er4 288 and.w #0xe000,r4 /* er4 <- current thread info */ 289 mov.l @(TI_FLAGS:16,er4),er1 290 and.l #_TIF_WORK_MASK,er1 291 beq restore_all:8 292work_pending: 293 btst #TIF_NEED_RESCHED,r1l 294 bne work_resched:8 295 /* work notifysig */ 296 mov.l sp,er0 297 subs #4,er0 /* er0: pt_regs */ 298 jsr @SYMBOL_NAME(do_notify_resume) 299 bra restore_all:8 300work_resched: 301 mov.l sp,er0 302 jsr @SYMBOL_NAME(set_esp0) 303 jsr @SYMBOL_NAME(schedule) 304 bra resume_userspace:8 305restore_all: 306 RESTORE_ALL /* Does RTE */ 307 308#if defined(CONFIG_PREEMPT) 309resume_kernel: 310 mov.l @(TI_PRE_COUNT:16,er4),er0 311 bne restore_all:8 312need_resched: 313 mov.l @(TI_FLAGS:16,er4),er0 314 btst #TIF_NEED_RESCHED,r0l 315 beq restore_all:8 316 mov.b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */ 317 bmi restore_all:8 318 mov.l #PREEMPT_ACTIVE,er0 319 mov.l er0,@(TI_PRE_COUNT:16,er4) 320 andc #0x7f,ccr 321 mov.l sp,er0 322 jsr @SYMBOL_NAME(set_esp0) 323 jsr @SYMBOL_NAME(schedule) 324 orc #0x80,ccr 325 bra need_resched:8 326#endif 327 328SYMBOL_NAME_LABEL(ret_from_fork) 329 mov.l er2,er0 330 jsr @SYMBOL_NAME(schedule_tail) 331 jmp @SYMBOL_NAME(ret_from_exception) 332 333SYMBOL_NAME_LABEL(resume) 334 /* 335 * Beware - when entering resume, offset of tss is in d1, 336 * prev (the current task) is in a0, next (the new task) 337 * is in a1 and d2.b is non-zero if the mm structure is 338 * shared between the tasks, so don't change these 339 * registers until their contents are no longer needed. 340 */ 341 342 /* save sr */ 343 sub.w r3,r3 344 stc ccr,r3l 345 mov.w r3,@(THREAD_CCR+2:16,er0) 346 347 /* disable interrupts */ 348 orc #0x80,ccr 349 mov.l @SYMBOL_NAME(sw_usp),er3 350 mov.l er3,@(THREAD_USP:16,er0) 351 mov.l sp,@(THREAD_KSP:16,er0) 352 353 /* Skip address space switching if they are the same. */ 354 /* FIXME: what did we hack out of here, this does nothing! */ 355 356 mov.l @(THREAD_USP:16,er1),er0 357 mov.l er0,@SYMBOL_NAME(sw_usp) 358 mov.l @(THREAD_KSP:16,er1),sp 359 360 /* restore status register */ 361 mov.w @(THREAD_CCR+2:16,er1),r3 362 363 ldc r3l,ccr 364 rts 365 366SYMBOL_NAME_LABEL(trace_break) 367 subs #4,sp 368 SAVE_ALL 369 sub.l er1,er1 370 dec.l #1,er1 371 mov.l er1,@(LORIG,sp) 372 mov.l sp,er0 373 jsr @SYMBOL_NAME(set_esp0) 374 mov.l @SYMBOL_NAME(sw_usp),er0 375 mov.l @er0,er1 376 mov.w @(-2:16,er1),r2 377 cmp.w #0x5730,r2 378 beq 1f 379 subs #2,er1 380 mov.l er1,@er0 3811: 382 and.w #0xff,e1 383 mov.l er1,er0 384 jsr @SYMBOL_NAME(trace_trap) 385 jmp @SYMBOL_NAME(ret_from_exception) 386 387 .section .bss 388SYMBOL_NAME_LABEL(sw_ksp) 389 .space 4 390SYMBOL_NAME_LABEL(sw_usp) 391 .space 4 392 393 .end 394