aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/sh3/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/sh3/entry.S')
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S357
1 files changed, 194 insertions, 163 deletions
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index b4106d0c68e..55da0ff9848 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -16,6 +16,7 @@
16#include <asm/unistd.h> 16#include <asm/unistd.h>
17#include <cpu/mmu_context.h> 17#include <cpu/mmu_context.h>
18#include <asm/page.h> 18#include <asm/page.h>
19#include <asm/cache.h>
19 20
20! NOTE: 21! NOTE:
21! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address 22! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -187,44 +188,35 @@ call_dae:
187#if defined(CONFIG_SH_STANDARD_BIOS) 188#if defined(CONFIG_SH_STANDARD_BIOS)
188 /* Unwind the stack and jmp to the debug entry */ 189 /* Unwind the stack and jmp to the debug entry */
189ENTRY(sh_bios_handler) 190ENTRY(sh_bios_handler)
190 mov.l @r15+, r0 191 mov.l 1f, r8
191 mov.l @r15+, r1 192 bsr restore_regs
192 mov.l @r15+, r2 193 nop
193 mov.l @r15+, r3 194
194 mov.l @r15+, r4 195 lds k2, pr ! restore pr
195 mov.l @r15+, r5 196 mov k4, r15
196 mov.l @r15+, r6
197 mov.l @r15+, r7
198 stc sr, r8
199 mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F
200 or r9, r8
201 ldc r8, sr ! here, change the register bank
202 mov.l @r15+, r8
203 mov.l @r15+, r9
204 mov.l @r15+, r10
205 mov.l @r15+, r11
206 mov.l @r15+, r12
207 mov.l @r15+, r13
208 mov.l @r15+, r14
209 mov.l @r15+, k0
210 ldc.l @r15+, spc
211 lds.l @r15+, pr
212 mov.l @r15+, k1
213 ldc.l @r15+, gbr
214 lds.l @r15+, mach
215 lds.l @r15+, macl
216 mov k0, r15
217 ! 197 !
218 mov.l 2f, k0 198 mov.l 2f, k0
219 mov.l @k0, k0 199 mov.l @k0, k0
220 jmp @k0 200 jmp @k0
221 ldc k1, ssr 201 ldc k3, ssr
222 .align 2 202 .align 2
2231: .long 0x300000f0 2031: .long 0x300000f0
2242: .long gdb_vbr_vector 2042: .long gdb_vbr_vector
225#endif /* CONFIG_SH_STANDARD_BIOS */ 205#endif /* CONFIG_SH_STANDARD_BIOS */
226 206
227restore_all: 207! restore_regs()
208! - restore r0, r1, r2, r3, r4, r5, r6, r7 from the stack
209! - switch bank
210! - restore r8, r9, r10, r11, r12, r13, r14, r15 from the stack
211! - restore spc, pr*, ssr, gbr, mach, macl, skip default tra
212! k2 returns original pr
213! k3 returns original sr
214! k4 returns original stack pointer
215! r8 passes SR bitmask, overwritten with restored data on return
216! r9 trashed
217! BL=0 on entry, on exit BL=1 (depending on r8).
218
219ENTRY(restore_regs)
228 mov.l @r15+, r0 220 mov.l @r15+, r0
229 mov.l @r15+, r1 221 mov.l @r15+, r1
230 mov.l @r15+, r2 222 mov.l @r15+, r2
@@ -234,10 +226,9 @@ restore_all:
234 mov.l @r15+, r6 226 mov.l @r15+, r6
235 mov.l @r15+, r7 227 mov.l @r15+, r7
236 ! 228 !
237 stc sr, r8 229 stc sr, r9
238 mov.l 7f, r9 230 or r8, r9
239 or r9, r8 ! BL =1, RB=1 231 ldc r9, sr
240 ldc r8, sr ! here, change the register bank
241 ! 232 !
242 mov.l @r15+, r8 233 mov.l @r15+, r8
243 mov.l @r15+, r9 234 mov.l @r15+, r9
@@ -248,12 +239,20 @@ restore_all:
248 mov.l @r15+, r14 239 mov.l @r15+, r14
249 mov.l @r15+, k4 ! original stack pointer 240 mov.l @r15+, k4 ! original stack pointer
250 ldc.l @r15+, spc 241 ldc.l @r15+, spc
251 lds.l @r15+, pr 242 mov.l @r15+, k2 ! original PR
252 mov.l @r15+, k3 ! original SR 243 mov.l @r15+, k3 ! original SR
253 ldc.l @r15+, gbr 244 ldc.l @r15+, gbr
254 lds.l @r15+, mach 245 lds.l @r15+, mach
255 lds.l @r15+, macl 246 lds.l @r15+, macl
256 add #4, r15 ! Skip syscall number 247 rts
248 add #4, r15 ! Skip syscall number
249
250restore_all:
251 mov.l 7f, r8
252 bsr restore_regs
253 nop
254
255 lds k2, pr ! restore pr
257 ! 256 !
258#ifdef CONFIG_SH_DSP 257#ifdef CONFIG_SH_DSP
259 mov.l @r15+, k0 ! DSP mode marker 258 mov.l @r15+, k0 ! DSP mode marker
@@ -294,7 +293,7 @@ skip_restore:
294 mov #0xf0, k1 293 mov #0xf0, k1
295 extu.b k1, k1 294 extu.b k1, k1
296 not k1, k1 295 not k1, k1
297 and k1, k2 ! Mask orignal SR value 296 and k1, k2 ! Mask original SR value
298 ! 297 !
299 mov k3, k0 ! Calculate IMASK-bits 298 mov k3, k0 ! Calculate IMASK-bits
300 shlr2 k0 299 shlr2 k0
@@ -313,7 +312,6 @@ skip_restore:
313 mov #0, k1 312 mov #0, k1
314 mov.b k1, @k0 313 mov.b k1, @k0
315#endif 314#endif
316 mov.l @r15+, k2 ! restore EXPEVT
317 mov k4, r15 315 mov k4, r15
318 rte 316 rte
319 nop 317 nop
@@ -336,81 +334,55 @@ skip_restore:
336ENTRY(vbr_base) 334ENTRY(vbr_base)
337 .long 0 335 .long 0
338! 336!
337! 0x100: General exception vector
338!
339 .balign 256,0,256 339 .balign 256,0,256
340general_exception: 340general_exception:
341 mov.l 1f, k2 341#ifndef CONFIG_CPU_SUBTYPE_SHX3
342 mov.l 2f, k3 342 bra handle_exception
343#ifdef CONFIG_CPU_SUBTYPE_SHX3 343 sts pr, k3 ! save original pr value in k3
344 mov.l @k2, k2 344#else
345 mov.l 1f, k4
346 mov.l @k4, k4
345 347
346 ! Is EXPEVT larger than 0x800? 348 ! Is EXPEVT larger than 0x800?
347 mov #0x8, k0 349 mov #0x8, k0
348 shll8 k0 350 shll8 k0
349 cmp/hs k0, k2 351 cmp/hs k0, k4
350 bf 0f 352 bf 0f
351 353
352 ! then add 0x580 (k2 is 0xd80 or 0xda0) 354 ! then add 0x580 (k2 is 0xd80 or 0xda0)
353 mov #0x58, k0 355 mov #0x58, k0
354 shll2 k0 356 shll2 k0
355 shll2 k0 357 shll2 k0
356 add k0, k2 358 add k0, k4
3570: 3590:
358 bra handle_exception 360 ! Setup stack and save DSP context (k0 contains original r15 on return)
361 bsr prepare_stack_save_dsp
359 nop 362 nop
360#else
361 bra handle_exception
362 mov.l @k2, k2
363#endif
364 .align 2
3651: .long EXPEVT
3662: .long ret_from_exception
367!
368!
369 363
370 .balign 1024,0,1024 364 ! Save registers / Switch to bank 0
371tlb_miss: 365 mov k4, k2 ! keep vector in k2
372 mov.l 1f, k2 366 mov.l 1f, k4 ! SR bits to clear in k4
373 mov.l 4f, k3 367 bsr save_regs ! needs original pr value in k3
374 bra handle_exception 368 nop
375 mov.l @k2, k2 369
376! 370 bra handle_exception_special
377 .balign 512,0,512
378interrupt:
379 mov.l 3f, k3
380#if defined(CONFIG_KGDB)
381 mov.l 2f, k2
382 ! Debounce (filter nested NMI)
383 mov.l @k2, k0
384 mov.l 5f, k1
385 cmp/eq k1, k0
386 bf 0f
387 mov.l 6f, k1
388 tas.b @k1
389 bt 0f
390 rte
391 nop 371 nop
392 .align 2
3932: .long INTEVT
3945: .long NMI_VEC
3956: .long in_nmi
3960:
397#endif /* defined(CONFIG_KGDB) */
398 bra handle_exception
399 mov #-1, k2 ! interrupt exception marker
400 372
401 .align 2 373 .align 2
4021: .long EXPEVT 3741: .long EXPEVT
4033: .long ret_from_irq 375#endif
4044: .long ret_from_exception
405 376
406! 377! prepare_stack_save_dsp()
407! 378! - roll back gRB
408 .align 2 379! - switch to kernel stack
409ENTRY(handle_exception) 380! - save DSP
410 ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), 381! k0 returns original sp (after roll back)
411 ! save all registers onto stack. 382! k1 trashed
412 ! 383! k2 trashed
413 384
385prepare_stack_save_dsp:
414#ifdef CONFIG_GUSA 386#ifdef CONFIG_GUSA
415 ! Check for roll back gRB (User and Kernel) 387 ! Check for roll back gRB (User and Kernel)
416 mov r15, k0 388 mov r15, k0
@@ -430,7 +402,7 @@ ENTRY(handle_exception)
4302: mov k1, r15 ! SP = r1 4022: mov k1, r15 ! SP = r1
4311: 4031:
432#endif 404#endif
433 405 ! Switch to kernel stack if needed
434 stc ssr, k0 ! Is it from kernel space? 406 stc ssr, k0 ! Is it from kernel space?
435 shll k0 ! Check MD bit (bit30) by shifting it into... 407 shll k0 ! Check MD bit (bit30) by shifting it into...
436 shll k0 ! ...the T bit 408 shll k0 ! ...the T bit
@@ -443,18 +415,17 @@ ENTRY(handle_exception)
443 add current, k1 415 add current, k1
444 mov k1, r15 ! change to kernel stack 416 mov k1, r15 ! change to kernel stack
445 ! 417 !
4461: mov.l 2f, k1 4181:
447 !
448#ifdef CONFIG_SH_DSP 419#ifdef CONFIG_SH_DSP
449 mov.l r2, @-r15 ! Save r2, we need another reg 420 ! Save DSP context if needed
450 stc sr, k4 421 stc sr, k1
451 mov.l 1f, r2 422 mov #0x10, k2
452 tst r2, k4 ! Check if in DSP mode 423 shll8 k2 ! DSP=1 (0x00001000)
453 mov.l @r15+, r2 ! Restore r2 now 424 tst k2, k1 ! Check if in DSP mode (passed in k2)
454 bt/s skip_save 425 bt/s skip_save
455 mov #0, k4 ! Set marker for no stack frame 426 mov #0, k1 ! Set marker for no stack frame
456 427
457 mov r2, k4 ! Backup r2 (in k4) for later 428 mov k2, k1 ! Save has-frame marker
458 429
459 ! Save DSP registers on stack 430 ! Save DSP registers on stack
460 stc.l mod, @-r15 431 stc.l mod, @-r15
@@ -473,35 +444,74 @@ ENTRY(handle_exception)
473 ! as we're not at all interested in supporting ancient toolchains at 444 ! as we're not at all interested in supporting ancient toolchains at
474 ! this point. -- PFM. 445 ! this point. -- PFM.
475 446
476 mov r15, r2 447 mov r15, k2
477 .word 0xf653 ! movs.l a1, @-r2 448 .word 0xf653 ! movs.l a1, @-r2
478 .word 0xf6f3 ! movs.l a0g, @-r2 449 .word 0xf6f3 ! movs.l a0g, @-r2
479 .word 0xf6d3 ! movs.l a1g, @-r2 450 .word 0xf6d3 ! movs.l a1g, @-r2
480 .word 0xf6c3 ! movs.l m0, @-r2 451 .word 0xf6c3 ! movs.l m0, @-r2
481 .word 0xf6e3 ! movs.l m1, @-r2 452 .word 0xf6e3 ! movs.l m1, @-r2
482 mov r2, r15 453 mov k2, r15
483 454
484 mov k4, r2 ! Restore r2
485 mov.l 1f, k4 ! Force DSP stack frame
486skip_save: 455skip_save:
487 mov.l k4, @-r15 ! Push DSP mode marker onto stack 456 mov.l k1, @-r15 ! Push DSP mode marker onto stack
488#endif 457#endif
489 ! Save the user registers on the stack. 458 rts
490 mov.l k2, @-r15 ! EXPEVT 459 nop
491 460!
492 mov #-1, k4 461! 0x400: Instruction and Data TLB miss exception vector
493 mov.l k4, @-r15 ! set TRA (default: -1) 462!
494 ! 463 .balign 1024,0,1024
464tlb_miss:
465 sts pr, k3 ! save original pr value in k3
466
467handle_exception:
468 mova exception_data, k0
469
470 ! Setup stack and save DSP context (k0 contains original r15 on return)
471 bsr prepare_stack_save_dsp
472 PREF(k0)
473
474 ! Save registers / Switch to bank 0
475 mov.l 5f, k2 ! vector register address
476 mov.l 1f, k4 ! SR bits to clear in k4
477 bsr save_regs ! needs original pr value in k3
478 mov.l @k2, k2 ! read out vector and keep in k2
479
480handle_exception_special:
481 ! Setup return address and jump to exception handler
482 mov.l 7f, r9 ! fetch return address
483 stc r2_bank, r0 ! k2 (vector)
484 mov.l 6f, r10
485 shlr2 r0
486 shlr r0
487 mov.l @(r0, r10), r10
488 jmp @r10
489 lds r9, pr ! put return address in pr
490
491 .align L1_CACHE_SHIFT
492
493! save_regs()
494! - save default tra, macl, mach, gbr, ssr, pr* and spc on the stack
495! - save r15*, r14, r13, r12, r11, r10, r9, r8 on the stack
496! - switch bank
497! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
498! k0 contains original stack pointer*
499! k1 trashed
500! k3 passes original pr*
501! k4 passes SR bitmask
502! BL=1 on entry, on exit BL=0.
503
504ENTRY(save_regs)
505 mov #-1, r1
506 mov.l k1, @-r15 ! set TRA (default: -1)
495 sts.l macl, @-r15 507 sts.l macl, @-r15
496 sts.l mach, @-r15 508 sts.l mach, @-r15
497 stc.l gbr, @-r15 509 stc.l gbr, @-r15
498 stc.l ssr, @-r15 510 stc.l ssr, @-r15
499 sts.l pr, @-r15 511 mov.l k3, @-r15 ! original pr in k3
500 stc.l spc, @-r15 512 stc.l spc, @-r15
501 ! 513
502 lds k3, pr ! Set the return address to pr 514 mov.l k0, @-r15 ! original stack pointer in k0
503 !
504 mov.l k0, @-r15 ! save orignal stack
505 mov.l r14, @-r15 515 mov.l r14, @-r15
506 mov.l r13, @-r15 516 mov.l r13, @-r15
507 mov.l r12, @-r15 517 mov.l r12, @-r15
@@ -509,13 +519,23 @@ skip_save:
509 mov.l r10, @-r15 519 mov.l r10, @-r15
510 mov.l r9, @-r15 520 mov.l r9, @-r15
511 mov.l r8, @-r15 521 mov.l r8, @-r15
512 ! 522
513 stc sr, r8 ! Back to normal register bank, and 523 mov.l 0f, k3 ! SR bits to set in k3
514 or k1, r8 ! Block all interrupts 524
515 mov.l 3f, k1 525 ! fall-through
516 and k1, r8 ! ... 526
517 ldc r8, sr ! ...changed here. 527! save_low_regs()
518 ! 528! - modify SR for bank switch
529! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
530! k3 passes bits to set in SR
531! k4 passes bits to clear in SR
532
533ENTRY(save_low_regs)
534 stc sr, r8
535 or k3, r8
536 and k4, r8
537 ldc r8, sr
538
519 mov.l r7, @-r15 539 mov.l r7, @-r15
520 mov.l r6, @-r15 540 mov.l r6, @-r15
521 mov.l r5, @-r15 541 mov.l r5, @-r15
@@ -523,52 +543,63 @@ skip_save:
523 mov.l r3, @-r15 543 mov.l r3, @-r15
524 mov.l r2, @-r15 544 mov.l r2, @-r15
525 mov.l r1, @-r15 545 mov.l r1, @-r15
526 mov.l r0, @-r15
527
528 /*
529 * This gets a bit tricky.. in the INTEVT case we don't want to use
530 * the VBR offset as a destination in the jump call table, since all
531 * of the destinations are the same. In this case, (interrupt) sets
532 * a marker in r2 (now r2_bank since SR.RB changed), which we check
533 * to determine the exception type. For all other exceptions, we
534 * forcibly read EXPEVT from memory and fix up the jump address, in
535 * the interrupt exception case we jump to do_IRQ() and defer the
536 * INTEVT read until there. As a bonus, we can also clean up the SR.RB
537 * checks that do_IRQ() was doing..
538 */
539 stc r2_bank, r8
540 cmp/pz r8
541 bf interrupt_exception
542 shlr2 r8
543 shlr r8
544 mov.l 4f, r9
545 add r8, r9
546 mov.l @r9, r9
547 jmp @r9
548 nop
549 rts 546 rts
550 nop 547 mov.l r0, @-r15
551 548
549!
550! 0x600: Interrupt / NMI vector
551!
552 .balign 512,0,512
553ENTRY(handle_interrupt)
554#if defined(CONFIG_KGDB)
555 mov.l 2f, k2
556 ! Debounce (filter nested NMI)
557 mov.l @k2, k0
558 mov.l 9f, k1
559 cmp/eq k1, k0
560 bf 11f
561 mov.l 10f, k1
562 tas.b @k1
563 bt 11f
564 rte
565 nop
552 .align 2 566 .align 2
5531: .long 0x00001000 ! DSP=1 5679: .long NMI_VEC
5542: .long 0x000080f0 ! FD=1, IMASK=15 56810: .long in_nmi
5553: .long 0xcfffffff ! RB=0, BL=0 56911:
5564: .long exception_handling_table 570#endif /* defined(CONFIG_KGDB) */
571 sts pr, k3 ! save original pr value in k3
572 mova exception_data, k0
557 573
558interrupt_exception: 574 ! Setup stack and save DSP context (k0 contains original r15 on return)
559 mov.l 1f, r9 575 bsr prepare_stack_save_dsp
576 PREF(k0)
577
578 ! Save registers / Switch to bank 0
579 mov.l 1f, k4 ! SR bits to clear in k4
580 bsr save_regs ! needs original pr value in k3
581 mov #-1, k2 ! default vector kept in k2
582
583 ! Setup return address and jump to do_IRQ
584 mov.l 4f, r9 ! fetch return address
585 lds r9, pr ! put return address in pr
560 mov.l 2f, r4 586 mov.l 2f, r4
561 mov.l @r4, r4 587 mov.l 3f, r9
588 mov.l @r4, r4 ! pass INTEVT vector as arg0
562 jmp @r9 589 jmp @r9
563 mov r15, r5 590 mov r15, r5 ! pass saved registers as arg1
564 rts
565 nop
566
567 .align 2
5681: .long do_IRQ
5692: .long INTEVT
570 591
571 .align 2
572ENTRY(exception_none) 592ENTRY(exception_none)
573 rts 593 rts
574 nop 594 nop
595
596 .align L1_CACHE_SHIFT
597exception_data:
5980: .long 0x000080f0 ! FD=1, IMASK=15
5991: .long 0xcfffffff ! RB=0, BL=0
6002: .long INTEVT
6013: .long do_IRQ
6024: .long ret_from_irq
6035: .long EXPEVT
6046: .long exception_handling_table
6057: .long ret_from_exception