aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/entry.S
diff options
context:
space:
mode:
authorYoshinori Sato <ysato@users.sourceforge.jp>2006-11-05 02:15:19 -0500
committerPaul Mundt <lethal@linux-sh.org>2006-12-05 20:45:36 -0500
commitde39840646a223ae13a346048c280b7c871bf56e (patch)
treeaa2449880c12310ccb92540bfd63e43e8a568745 /arch/sh/kernel/entry.S
parent0983b31849bbe1fe82520947acc1bec97c457d4b (diff)
sh: Exception vector rework and SH-2/SH-2A support.
This splits out common bits from the existing exception handler for use between SH-2/SH-2A and SH-3/4, and adds support for the SH-2/2A exceptions. Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/entry.S')
-rw-r--r--arch/sh/kernel/entry.S843
1 files changed, 0 insertions, 843 deletions
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
deleted file mode 100644
index 39aaefb2d83f..000000000000
--- a/arch/sh/kernel/entry.S
+++ /dev/null
@@ -1,843 +0,0 @@
1/*
2 * linux/arch/sh/entry.S
3 *
4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
5 * Copyright (C) 2003 - 2006 Paul Mundt
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 *
11 */
12#include <linux/sys.h>
13#include <linux/errno.h>
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
20! NOTE:
21! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
22! to be jumped is too far, but it causes illegal slot exception.
23
24/*
25 * entry.S contains the system-call and fault low-level handling routines.
26 * This also contains the timer-interrupt handler, as well as all interrupts
27 * and faults that can result in a task-switch.
28 *
29 * NOTE: This code handles signal-recognition, which happens every time
30 * after a timer-interrupt and after each system call.
31 *
32 * NOTE: This code uses a convention that instructions in the delay slot
33 * of a transfer-control instruction are indented by an extra space, thus:
34 *
35 * jmp @k0 ! control-transfer instruction
36 * ldc k1, ssr ! delay slot
37 *
38 * Stack layout in 'ret_from_syscall':
39 * ptrace needs to have all regs on the stack.
40 * if the order here is changed, it needs to be
41 * updated in ptrace.c and ptrace.h
42 *
43 * r0
44 * ...
45 * r15 = stack pointer
46 * spc
47 * pr
48 * ssr
49 * gbr
50 * mach
51 * macl
52 * syscall #
53 *
54 */
55#if defined(CONFIG_KGDB_NMI)
56NMI_VEC = 0x1c0 ! Must catch early for debounce
57#endif
58
59/* Offsets to the stack */
60OFF_R0 = 0 /* Return value. New ABI also arg4 */
61OFF_R1 = 4 /* New ABI: arg5 */
62OFF_R2 = 8 /* New ABI: arg6 */
63OFF_R3 = 12 /* New ABI: syscall_nr */
64OFF_R4 = 16 /* New ABI: arg0 */
65OFF_R5 = 20 /* New ABI: arg1 */
66OFF_R6 = 24 /* New ABI: arg2 */
67OFF_R7 = 28 /* New ABI: arg3 */
68OFF_SP = (15*4)
69OFF_PC = (16*4)
70OFF_SR = (16*4+8)
71OFF_TRA = (16*4+6*4)
72
73
74#define k0 r0
75#define k1 r1
76#define k2 r2
77#define k3 r3
78#define k4 r4
79
80#define g_imask r6 /* r6_bank1 */
81#define k_g_imask r6_bank /* r6_bank1 */
82#define current r7 /* r7_bank1 */
83
84/*
85 * Kernel mode register usage:
86 * k0 scratch
87 * k1 scratch
88 * k2 scratch (Exception code)
89 * k3 scratch (Return address)
90 * k4 scratch
91 * k5 reserved
92 * k6 Global Interrupt Mask (0--15 << 4)
93 * k7 CURRENT_THREAD_INFO (pointer to current thread info)
94 */
95
96!
97! TLB Miss / Initial Page write exception handling
98! _and_
99! TLB hits, but the access violate the protection.
100! It can be valid access, such as stack grow and/or C-O-W.
101!
102!
103! Find the pmd/pte entry and loadtlb
104! If it's not found, cause address error (SEGV)
105!
106! Although this could be written in assembly language (and it'd be faster),
107! this first version depends *much* on C implementation.
108!
109
110#define CLI() \
111 stc sr, r0; \
112 or #0xf0, r0; \
113 ldc r0, sr
114
115#define STI() \
116 mov.l __INV_IMASK, r11; \
117 stc sr, r10; \
118 and r11, r10; \
119 stc k_g_imask, r11; \
120 or r11, r10; \
121 ldc r10, sr
122
123#if defined(CONFIG_PREEMPT)
124# define preempt_stop() CLI()
125#else
126# define preempt_stop()
127# define resume_kernel restore_all
128#endif
129
130#if defined(CONFIG_MMU)
131 .align 2
132ENTRY(tlb_miss_load)
133 bra call_dpf
134 mov #0, r5
135
136 .align 2
137ENTRY(tlb_miss_store)
138 bra call_dpf
139 mov #1, r5
140
141 .align 2
142ENTRY(initial_page_write)
143 bra call_dpf
144 mov #1, r5
145
146 .align 2
147ENTRY(tlb_protection_violation_load)
148 bra call_dpf
149 mov #0, r5
150
151 .align 2
152ENTRY(tlb_protection_violation_store)
153 bra call_dpf
154 mov #1, r5
155
156call_dpf:
157 mov.l 1f, r0
158 mov r5, r8
159 mov.l @r0, r6
160 mov r6, r9
161 mov.l 2f, r0
162 sts pr, r10
163 jsr @r0
164 mov r15, r4
165 !
166 tst r0, r0
167 bf/s 0f
168 lds r10, pr
169 rts
170 nop
1710: STI()
172 mov.l 3f, r0
173 mov r9, r6
174 mov r8, r5
175 jmp @r0
176 mov r15, r4
177
178 .align 2
1791: .long MMU_TEA
1802: .long __do_page_fault
1813: .long do_page_fault
182
183 .align 2
184ENTRY(address_error_load)
185 bra call_dae
186 mov #0,r5 ! writeaccess = 0
187
188 .align 2
189ENTRY(address_error_store)
190 bra call_dae
191 mov #1,r5 ! writeaccess = 1
192
193 .align 2
194call_dae:
195 mov.l 1f, r0
196 mov.l @r0, r6 ! address
197 mov.l 2f, r0
198 jmp @r0
199 mov r15, r4 ! regs
200
201 .align 2
2021: .long MMU_TEA
2032: .long do_address_error
204#endif /* CONFIG_MMU */
205
206#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
207! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
208! If both are configured, handle the debug traps (breakpoints) in SW,
209! but still allow BIOS traps to FW.
210
211 .align 2
212debug_kernel:
213#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
214 /* Force BIOS call to FW (debug_trap put TRA in r8) */
215 mov r8,r0
216 shlr2 r0
217 cmp/eq #0x3f,r0
218 bt debug_kernel_fw
219#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
220
221debug_enter:
222#if defined(CONFIG_SH_KGDB)
223 /* Jump to kgdb, pass stacked regs as arg */
224debug_kernel_sw:
225 mov.l 3f, r0
226 jmp @r0
227 mov r15, r4
228 .align 2
2293: .long kgdb_handle_exception
230#endif /* CONFIG_SH_KGDB */
231
232#if defined(CONFIG_SH_STANDARD_BIOS)
233 /* Unwind the stack and jmp to the debug entry */
234debug_kernel_fw:
235 mov.l @r15+, r0
236 mov.l @r15+, r1
237 mov.l @r15+, r2
238 mov.l @r15+, r3
239 mov.l @r15+, r4
240 mov.l @r15+, r5
241 mov.l @r15+, r6
242 mov.l @r15+, r7
243 stc sr, r8
244 mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F
245 or r9, r8
246 ldc r8, sr ! here, change the register bank
247 mov.l @r15+, r8
248 mov.l @r15+, r9
249 mov.l @r15+, r10
250 mov.l @r15+, r11
251 mov.l @r15+, r12
252 mov.l @r15+, r13
253 mov.l @r15+, r14
254 mov.l @r15+, k0
255 ldc.l @r15+, spc
256 lds.l @r15+, pr
257 mov.l @r15+, k1
258 ldc.l @r15+, gbr
259 lds.l @r15+, mach
260 lds.l @r15+, macl
261 mov k0, r15
262 !
263 mov.l 2f, k0
264 mov.l @k0, k0
265 jmp @k0
266 ldc k1, ssr
267 .align 2
2681: .long 0x300000f0
2692: .long gdb_vbr_vector
270#endif /* CONFIG_SH_STANDARD_BIOS */
271
272#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
273
274
275 .align 2
276debug_trap:
277#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
278 mov #OFF_SR, r0
279 mov.l @(r0,r15), r0 ! get status register
280 shll r0
281 shll r0 ! kernel space?
282 bt/s debug_kernel
283#endif
284 mov.l @r15, r0 ! Restore R0 value
285 mov.l 1f, r8
286 jmp @r8
287 nop
288
289 .align 2
290ENTRY(exception_error)
291 !
292 STI()
293 mov.l 2f, r0
294 jmp @r0
295 nop
296
297!
298 .align 2
2991: .long break_point_trap_software
3002: .long do_exception_error
301
302 .align 2
303ret_from_exception:
304 preempt_stop()
305ENTRY(ret_from_irq)
306 !
307 mov #OFF_SR, r0
308 mov.l @(r0,r15), r0 ! get status register
309 shll r0
310 shll r0 ! kernel space?
311 bt/s resume_kernel ! Yes, it's from kernel, go back soon
312 GET_THREAD_INFO(r8)
313
314#ifdef CONFIG_PREEMPT
315 bra resume_userspace
316 nop
317ENTRY(resume_kernel)
318 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
319 tst r0, r0
320 bf noresched
321need_resched:
322 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
323 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
324 bt noresched
325
326 mov #OFF_SR, r0
327 mov.l @(r0,r15), r0 ! get status register
328 and #0xf0, r0 ! interrupts off (exception path)?
329 cmp/eq #0xf0, r0
330 bt noresched
331
332 mov.l 1f, r0
333 mov.l r0, @(TI_PRE_COUNT,r8)
334
335 STI()
336 mov.l 2f, r0
337 jsr @r0
338 nop
339 mov #0, r0
340 mov.l r0, @(TI_PRE_COUNT,r8)
341 CLI()
342
343 bra need_resched
344 nop
345noresched:
346 bra restore_all
347 nop
348
349 .align 2
3501: .long PREEMPT_ACTIVE
3512: .long schedule
352#endif
353
354ENTRY(resume_userspace)
355 ! r8: current_thread_info
356 CLI()
357 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
358 tst #_TIF_WORK_MASK, r0
359 bt/s restore_all
360 tst #_TIF_NEED_RESCHED, r0
361
362 .align 2
363work_pending:
364 ! r0: current_thread_info->flags
365 ! r8: current_thread_info
366 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
367 bf/s work_resched
368 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
369work_notifysig:
370 bt/s restore_all
371 mov r15, r4
372 mov r12, r5 ! set arg1(save_r0)
373 mov r0, r6
374 mov.l 2f, r1
375 mova restore_all, r0
376 jmp @r1
377 lds r0, pr
378work_resched:
379#ifndef CONFIG_PREEMPT
380 ! gUSA handling
381 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
382 mov r0, r1
383 shll r0
384 bf/s 1f
385 shll r0
386 bf/s 1f
387 mov #OFF_PC, r0
388 ! SP >= 0xc0000000 : gUSA mark
389 mov.l @(r0,r15), r2 ! get user space PC (program counter)
390 mov.l @(OFF_R0,r15), r3 ! end point
391 cmp/hs r3, r2 ! r2 >= r3?
392 bt 1f
393 add r3, r1 ! rewind point #2
394 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
395 !
3961:
397#endif
398 mov.l 1f, r1
399 jsr @r1 ! schedule
400 nop
401 CLI()
402 !
403 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
404 tst #_TIF_WORK_MASK, r0
405 bt restore_all
406 bra work_pending
407 tst #_TIF_NEED_RESCHED, r0
408
409 .align 2
4101: .long schedule
4112: .long do_notify_resume
412
413 .align 2
414syscall_exit_work:
415 ! r0: current_thread_info->flags
416 ! r8: current_thread_info
417 tst #_TIF_SYSCALL_TRACE, r0
418 bt/s work_pending
419 tst #_TIF_NEED_RESCHED, r0
420 STI()
421 ! XXX setup arguments...
422 mov.l 4f, r0 ! do_syscall_trace
423 jsr @r0
424 nop
425 bra resume_userspace
426 nop
427
428 .align 2
429syscall_trace_entry:
430 ! Yes it is traced.
431 ! XXX setup arguments...
432 mov.l 4f, r11 ! Call do_syscall_trace which notifies
433 jsr @r11 ! superior (will chomp R[0-7])
434 nop
435 ! Reload R0-R4 from kernel stack, where the
436 ! parent may have modified them using
437 ! ptrace(POKEUSR). (Note that R0-R2 are
438 ! used by the system call handler directly
439 ! from the kernel stack anyway, so don't need
440 ! to be reloaded here.) This allows the parent
441 ! to rewrite system calls and args on the fly.
442 mov.l @(OFF_R4,r15), r4 ! arg0
443 mov.l @(OFF_R5,r15), r5
444 mov.l @(OFF_R6,r15), r6
445 mov.l @(OFF_R7,r15), r7 ! arg3
446 mov.l @(OFF_R3,r15), r3 ! syscall_nr
447 ! Arrange for do_syscall_trace to be called
448 ! again as the system call returns.
449 mov.l 2f, r10 ! Number of syscalls
450 cmp/hs r10, r3
451 bf syscall_call
452 mov #-ENOSYS, r0
453 bra syscall_exit
454 mov.l r0, @(OFF_R0,r15) ! Return value
455
456/*
457 * Syscall interface:
458 *
459 * Syscall #: R3
460 * Arguments #0 to #3: R4--R7
461 * Arguments #4 to #6: R0, R1, R2
462 * TRA: (number of arguments + 0x10) x 4
463 *
464 * This code also handles delegating other traps to the BIOS/gdb stub
465 * according to:
466 *
467 * Trap number
468 * (TRA>>2) Purpose
469 * -------- -------
470 * 0x0-0xf old syscall ABI
471 * 0x10-0x1f new syscall ABI
472 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
473 *
474 * Note: When we're first called, the TRA value must be shifted
475 * right 2 bits in order to get the value that was used as the "trapa"
476 * argument.
477 */
478
479 .align 2
480 .globl ret_from_fork
481ret_from_fork:
482 mov.l 1f, r8
483 jsr @r8
484 mov r0, r4
485 bra syscall_exit
486 nop
487 .align 2
4881: .long schedule_tail
489 !
490ENTRY(system_call)
491 mov.l 1f, r9
492 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
493 !
494 ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
495 mov #0x7f, r9
496 cmp/hi r9, r8
497 bt/s 0f
498 mov #OFF_TRA, r9
499 add r15, r9
500 !
501 mov.l r8, @r9 ! set TRA value to tra
502 STI()
503 ! Call the system call handler through the table.
504 ! First check for bad syscall number
505 mov r3, r9
506 mov.l 2f, r8 ! Number of syscalls
507 cmp/hs r8, r9
508 bf/s good_system_call
509 GET_THREAD_INFO(r8)
510syscall_badsys: ! Bad syscall number
511 mov #-ENOSYS, r0
512 bra resume_userspace
513 mov.l r0, @(OFF_R0,r15) ! Return value
514 !
5150:
516 bra debug_trap
517 nop
518 !
519good_system_call: ! Good syscall number
520 mov.l @(TI_FLAGS,r8), r8
521 mov #_TIF_SYSCALL_TRACE, r10
522 tst r10, r8
523 bf syscall_trace_entry
524 !
525syscall_call:
526 shll2 r9 ! x4
527 mov.l 3f, r8 ! Load the address of sys_call_table
528 add r8, r9
529 mov.l @r9, r8
530 jsr @r8 ! jump to specific syscall handler
531 nop
532 mov.l @(OFF_R0,r15), r12 ! save r0
533 mov.l r0, @(OFF_R0,r15) ! save the return value
534 !
535syscall_exit:
536 CLI()
537 !
538 GET_THREAD_INFO(r8)
539 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
540 tst #_TIF_ALLWORK_MASK, r0
541 bf syscall_exit_work
542restore_all:
543 mov.l @r15+, r0
544 mov.l @r15+, r1
545 mov.l @r15+, r2
546 mov.l @r15+, r3
547 mov.l @r15+, r4
548 mov.l @r15+, r5
549 mov.l @r15+, r6
550 mov.l @r15+, r7
551 !
552 stc sr, r8
553 mov.l 7f, r9
554 or r9, r8 ! BL =1, RB=1
555 ldc r8, sr ! here, change the register bank
556 !
557 mov.l @r15+, r8
558 mov.l @r15+, r9
559 mov.l @r15+, r10
560 mov.l @r15+, r11
561 mov.l @r15+, r12
562 mov.l @r15+, r13
563 mov.l @r15+, r14
564 mov.l @r15+, k4 ! original stack pointer
565 ldc.l @r15+, spc
566 lds.l @r15+, pr
567 mov.l @r15+, k3 ! original SR
568 ldc.l @r15+, gbr
569 lds.l @r15+, mach
570 lds.l @r15+, macl
571 add #4, r15 ! Skip syscall number
572 !
573#ifdef CONFIG_SH_DSP
574 mov.l @r15+, k0 ! DSP mode marker
575 mov.l 5f, k1
576 cmp/eq k0, k1 ! Do we have a DSP stack frame?
577 bf skip_restore
578
579 stc sr, k0 ! Enable CPU DSP mode
580 or k1, k0 ! (within kernel it may be disabled)
581 ldc k0, sr
582 mov r2, k0 ! Backup r2
583
584 ! Restore DSP registers from stack
585 mov r15, r2
586 movs.l @r2+, a1
587 movs.l @r2+, a0g
588 movs.l @r2+, a1g
589 movs.l @r2+, m0
590 movs.l @r2+, m1
591 mov r2, r15
592
593 lds.l @r15+, a0
594 lds.l @r15+, x0
595 lds.l @r15+, x1
596 lds.l @r15+, y0
597 lds.l @r15+, y1
598 lds.l @r15+, dsr
599 ldc.l @r15+, rs
600 ldc.l @r15+, re
601 ldc.l @r15+, mod
602
603 mov k0, r2 ! Restore r2
604skip_restore:
605#endif
606 !
607 ! Calculate new SR value
608 mov k3, k2 ! original SR value
609 mov.l 9f, k1
610 and k1, k2 ! Mask orignal SR value
611 !
612 mov k3, k0 ! Calculate IMASK-bits
613 shlr2 k0
614 and #0x3c, k0
615 cmp/eq #0x3c, k0
616 bt/s 6f
617 shll2 k0
618 mov g_imask, k0
619 !
6206: or k0, k2 ! Set the IMASK-bits
621 ldc k2, ssr
622 !
623#if defined(CONFIG_KGDB_NMI)
624 ! Clear in_nmi
625 mov.l 6f, k0
626 mov #0, k1
627 mov.b k1, @k0
628#endif
629 mov.l @r15+, k2 ! restore EXPEVT
630 mov k4, r15
631 rte
632 nop
633
634 .align 2
6351: .long TRA
6362: .long NR_syscalls
6373: .long sys_call_table
6384: .long do_syscall_trace
6395: .long 0x00001000 ! DSP
6407: .long 0x30000000
6419:
642__INV_IMASK:
643 .long 0xffffff0f ! ~(IMASK)
644
645! Exception Vector Base
646!
647! Should be aligned page boundary.
648!
649 .balign 4096,0,4096
650ENTRY(vbr_base)
651 .long 0
652!
653 .balign 256,0,256
654general_exception:
655 mov.l 1f, k2
656 mov.l 2f, k3
657 bra handle_exception
658 mov.l @k2, k2
659 .align 2
6601: .long EXPEVT
6612: .long ret_from_exception
662!
663!
664 .balign 1024,0,1024
665tlb_miss:
666 mov.l 1f, k2
667 mov.l 4f, k3
668 bra handle_exception
669 mov.l @k2, k2
670!
671 .balign 512,0,512
672interrupt:
673 mov.l 2f, k2
674 mov.l 3f, k3
675#if defined(CONFIG_KGDB_NMI)
676 ! Debounce (filter nested NMI)
677 mov.l @k2, k0
678 mov.l 5f, k1
679 cmp/eq k1, k0
680 bf 0f
681 mov.l 6f, k1
682 tas.b @k1
683 bt 0f
684 rte
685 nop
686 .align 2
6875: .long NMI_VEC
6886: .long in_nmi
6890:
690#endif /* defined(CONFIG_KGDB_NMI) */
691 bra handle_exception
692 mov #-1, k2 ! interrupt exception marker
693
694 .align 2
6951: .long EXPEVT
6962: .long INTEVT
6973: .long ret_from_irq
6984: .long ret_from_exception
699
700!
701!
702 .align 2
703ENTRY(handle_exception)
704 ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
705 ! save all registers onto stack.
706 !
707 stc ssr, k0 ! Is it from kernel space?
708 shll k0 ! Check MD bit (bit30) by shifting it into...
709 shll k0 ! ...the T bit
710 bt/s 1f ! It's a kernel to kernel transition.
711 mov r15, k0 ! save original stack to k0
712 /* User space to kernel */
713 mov #(THREAD_SIZE >> 8), k1
714 shll8 k1 ! k1 := THREAD_SIZE
715 add current, k1
716 mov k1, r15 ! change to kernel stack
717 !
7181: mov.l 2f, k1
719 !
720#ifdef CONFIG_SH_DSP
721 mov.l r2, @-r15 ! Save r2, we need another reg
722 stc sr, k4
723 mov.l 1f, r2
724 tst r2, k4 ! Check if in DSP mode
725 mov.l @r15+, r2 ! Restore r2 now
726 bt/s skip_save
727 mov #0, k4 ! Set marker for no stack frame
728
729 mov r2, k4 ! Backup r2 (in k4) for later
730
731 ! Save DSP registers on stack
732 stc.l mod, @-r15
733 stc.l re, @-r15
734 stc.l rs, @-r15
735 sts.l dsr, @-r15
736 sts.l y1, @-r15
737 sts.l y0, @-r15
738 sts.l x1, @-r15
739 sts.l x0, @-r15
740 sts.l a0, @-r15
741
742 ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
743
744 ! FIXME: Make sure that this is still the case with newer toolchains,
745 ! as we're not at all interested in supporting ancient toolchains at
746 ! this point. -- PFM.
747
748 mov r15, r2
749 .word 0xf653 ! movs.l a1, @-r2
750 .word 0xf6f3 ! movs.l a0g, @-r2
751 .word 0xf6d3 ! movs.l a1g, @-r2
752 .word 0xf6c3 ! movs.l m0, @-r2
753 .word 0xf6e3 ! movs.l m1, @-r2
754 mov r2, r15
755
756 mov k4, r2 ! Restore r2
757 mov.l 1f, k4 ! Force DSP stack frame
758skip_save:
759 mov.l k4, @-r15 ! Push DSP mode marker onto stack
760#endif
761 ! Save the user registers on the stack.
762 mov.l k2, @-r15 ! EXPEVT
763
764 mov #-1, k4
765 mov.l k4, @-r15 ! set TRA (default: -1)
766 !
767 sts.l macl, @-r15
768 sts.l mach, @-r15
769 stc.l gbr, @-r15
770 stc.l ssr, @-r15
771 sts.l pr, @-r15
772 stc.l spc, @-r15
773 !
774 lds k3, pr ! Set the return address to pr
775 !
776 mov.l k0, @-r15 ! save orignal stack
777 mov.l r14, @-r15
778 mov.l r13, @-r15
779 mov.l r12, @-r15
780 mov.l r11, @-r15
781 mov.l r10, @-r15
782 mov.l r9, @-r15
783 mov.l r8, @-r15
784 !
785 stc sr, r8 ! Back to normal register bank, and
786 or k1, r8 ! Block all interrupts
787 mov.l 3f, k1
788 and k1, r8 ! ...
789 ldc r8, sr ! ...changed here.
790 !
791 mov.l r7, @-r15
792 mov.l r6, @-r15
793 mov.l r5, @-r15
794 mov.l r4, @-r15
795 mov.l r3, @-r15
796 mov.l r2, @-r15
797 mov.l r1, @-r15
798 mov.l r0, @-r15
799
800 /*
801 * This gets a bit tricky.. in the INTEVT case we don't want to use
802 * the VBR offset as a destination in the jump call table, since all
803 * of the destinations are the same. In this case, (interrupt) sets
804 * a marker in r2 (now r2_bank since SR.RB changed), which we check
805 * to determine the exception type. For all other exceptions, we
806 * forcibly read EXPEVT from memory and fix up the jump address, in
807 * the interrupt exception case we jump to do_IRQ() and defer the
808 * INTEVT read until there. As a bonus, we can also clean up the SR.RB
809 * checks that do_IRQ() was doing..
810 */
811 stc r2_bank, r8
812 cmp/pz r8
813 bf interrupt_exception
814 shlr2 r8
815 shlr r8
816 mov.l 4f, r9
817 add r8, r9
818 mov.l @r9, r9
819 jmp @r9
820 nop
821 rts
822 nop
823
824 .align 2
8251: .long 0x00001000 ! DSP=1
8262: .long 0x000080f0 ! FD=1, IMASK=15
8273: .long 0xcfffffff ! RB=0, BL=0
8284: .long exception_handling_table
829
830interrupt_exception:
831 mov.l 1f, r9
832 jmp @r9
833 nop
834 rts
835 nop
836
837 .align 2
8381: .long do_IRQ
839
840 .align 2
841ENTRY(exception_none)
842 rts
843 nop