Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / unicore32 / kernel / entry.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * linux/arch/unicore32/kernel/entry.S
4  *
5  * Code specific to PKUnity SoC and UniCore ISA
6  *
7  * Copyright (C) 2001-2010 GUAN Xue-tao
8  *
9  *  Low-level vector interface routines
10  */
11 #include <linux/init.h>
12 #include <linux/linkage.h>
13 #include <asm/assembler.h>
14 #include <asm/errno.h>
15 #include <asm/thread_info.h>
16 #include <asm/memory.h>
17 #include <asm/unistd.h>
18 #include <generated/asm-offsets.h>
19 #include "debug-macro.S"
20
21 @
22 @ Most of the stack format comes from struct pt_regs, but with
23 @ the addition of 8 bytes for storing syscall args 5 and 6.
24 @
25 #define S_OFF           8
26
27 /*
28  * The SWI code relies on the fact that R0 is at the bottom of the stack
29  * (due to slow/fast restore user regs).
30  */
31 #if S_R0 != 0
32 #error "Please fix"
33 #endif
34
35         .macro  zero_fp
36 #ifdef CONFIG_FRAME_POINTER
37         mov     fp, #0
38 #endif
39         .endm
40
41         .macro  alignment_trap, rtemp
42 #ifdef CONFIG_ALIGNMENT_TRAP
43         ldw     \rtemp, .LCcralign
44         ldw     \rtemp, [\rtemp]
45         movc    p0.c1, \rtemp, #0
46 #endif
47         .endm
48
49         .macro  load_user_sp_lr, rd, rtemp, offset = 0
50         mov     \rtemp, asr
51         xor     \rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
52         mov.a   asr, \rtemp                     @ switch to the SUSR mode
53
54         ldw     sp, [\rd+], #\offset            @ load sp_user
55         ldw     lr, [\rd+], #\offset + 4        @ load lr_user
56
57         xor     \rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
58         mov.a   asr, \rtemp                     @ switch back to the PRIV mode
59         .endm
60
61         .macro  priv_exit, rpsr
62         mov.a   bsr, \rpsr
63         ldm.w   (r0 - r15), [sp]+
64         ldm.b   (r16 - pc), [sp]+               @ load r0 - pc, asr
65         .endm
66
67         .macro  restore_user_regs, fast = 0, offset = 0
68         ldw     r1, [sp+], #\offset + S_PSR     @ get calling asr
69         ldw     lr, [sp+], #\offset + S_PC      @ get pc
70         mov.a   bsr, r1                         @ save in bsr_priv
71         .if     \fast
72         add     sp, sp, #\offset + S_R1         @ r0 is syscall return value
73         ldm.w   (r1 - r15), [sp]+               @ get calling r1 - r15
74         ldur    (r16 - lr), [sp]+               @ get calling r16 - lr
75         .else
76         ldm.w   (r0 - r15), [sp]+               @ get calling r0 - r15
77         ldur    (r16 - lr), [sp]+               @ get calling r16 - lr
78         .endif
79         nop
80         add     sp, sp, #S_FRAME_SIZE - S_R16
81         mov.a   pc, lr                          @ return
82                                                 @ and move bsr_priv into asr
83         .endm
84
85         .macro  get_thread_info, rd
86         mov     \rd, sp >> #13
87         mov     \rd, \rd << #13
88         .endm
89
90         .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
91         ldw     \base, =(PKUNITY_INTC_BASE)
92         ldw     \irqstat, [\base+], #0xC        @ INTC_ICIP
93         ldw     \tmp,     [\base+], #0x4        @ INTC_ICMR
94         and.a   \irqstat, \irqstat, \tmp
95         beq     1001f
96         cntlz   \irqnr, \irqstat
97         rsub    \irqnr, \irqnr, #31
98 1001:   /* EQ will be set if no irqs pending */
99         .endm
100
101 #ifdef CONFIG_DEBUG_LL
102         .macro  printreg, reg, temp
103                 adr     \temp, 901f
104                 stm     (r0-r3), [\temp]+
105                 stw     lr, [\temp+], #0x10
106                 mov     r0, \reg
107                 b.l     printhex8
108                 mov     r0, #':'
109                 b.l     printch
110                 mov     r0, pc
111                 b.l     printhex8
112                 adr     r0, 902f
113                 b.l     printascii
114                 adr     \temp, 901f
115                 ldm     (r0-r3), [\temp]+
116                 ldw     lr, [\temp+], #0x10
117                 b       903f
118 901:    .word   0, 0, 0, 0, 0   @ r0-r3, lr
119 902:    .asciz  ": epip4d\n"
120         .align
121 903:
122         .endm
123 #endif
124
125 /*
126  * These are the registers used in the syscall handler, and allow us to
127  * have in theory up to 7 arguments to a function - r0 to r6.
128  *
129  * Note that tbl == why is intentional.
130  *
131  * We must set at least "tsk" and "why" when calling ret_with_reschedule.
132  */
133 scno    .req    r21             @ syscall number
134 tbl     .req    r22             @ syscall table pointer
135 why     .req    r22             @ Linux syscall (!= 0)
136 tsk     .req    r23             @ current thread_info
137
138 /*
139  * Interrupt handling.  Preserves r17, r18, r19
140  */
141         .macro  intr_handler
142 1:      get_irqnr_and_base r0, r6, r5, lr
143         beq     2f
144         mov     r1, sp
145         @
146         @ routine called with r0 = irq number, r1 = struct pt_regs *
147         @
148         adr     lr, 1b
149         b       asm_do_IRQ
150 2:
151         .endm
152
153 /*
154  * PRIV mode handlers
155  */
156         .macro  priv_entry
157         sub     sp, sp, #(S_FRAME_SIZE - 4)
158         stm     (r1 - r15), [sp]+
159         add     r5, sp, #S_R15
160         stm     (r16 - r28), [r5]+
161
162         ldm     (r1 - r3), [r0]+
163         add     r5, sp, #S_SP - 4       @ here for interlock avoidance
164         mov     r4, #-1                 @  ""  ""      ""       ""
165         add     r0, sp, #(S_FRAME_SIZE - 4)
166         stw.w   r1, [sp+], #-4          @ save the "real" r0 copied
167                                         @ from the exception stack
168
169         mov     r1, lr
170
171         @
172         @ We are now ready to fill in the remaining blanks on the stack:
173         @
174         @  r0 - sp_priv
175         @  r1 - lr_priv
176         @  r2 - lr_<exception>, already fixed up for correct return/restart
177         @  r3 - bsr_<exception>
178         @  r4 - orig_r0 (see pt_regs definition in ptrace.h)
179         @
180         stm     (r0 - r4), [r5]+
181         .endm
182
183 /*
184  * User mode handlers
185  *
186  */
187         .macro  user_entry
188         sub     sp, sp, #S_FRAME_SIZE
189         stm     (r1 - r15), [sp+]
190         add     r4, sp, #S_R16
191         stm     (r16 - r28), [r4]+
192
193         ldm     (r1 - r3), [r0]+
194         add     r0, sp, #S_PC           @ here for interlock avoidance
195         mov     r4, #-1                 @  ""  ""     ""        ""
196
197         stw     r1, [sp]                @ save the "real" r0 copied
198                                         @ from the exception stack
199
200         @
201         @ We are now ready to fill in the remaining blanks on the stack:
202         @
203         @  r2 - lr_<exception>, already fixed up for correct return/restart
204         @  r3 - bsr_<exception>
205         @  r4 - orig_r0 (see pt_regs definition in ptrace.h)
206         @
207         @ Also, separately save sp_user and lr_user
208         @
209         stm     (r2 - r4), [r0]+
210         stur    (sp, lr), [r0-]
211
212         @
213         @ Enable the alignment trap while in kernel mode
214         @
215         alignment_trap r0
216
217         @
218         @ Clear FP to mark the first stack frame
219         @
220         zero_fp
221         .endm
222
223         .text
224
225 @
226 @ __invalid - generic code for failed exception
227 @                       (re-entrant version of handlers)
228 @
229 __invalid:
230         sub     sp, sp, #S_FRAME_SIZE
231         stm     (r1 - r15), [sp+]
232         add     r1, sp, #S_R16
233         stm     (r16 - r28, sp, lr), [r1]+
234
235         zero_fp
236
237         ldm     (r4 - r6), [r0]+
238         add     r0, sp, #S_PC           @ here for interlock avoidance
239         mov     r7, #-1                 @  ""   ""    ""        ""
240         stw     r4, [sp]                @ save preserved r0
241         stm     (r5 - r7), [r0]+        @ lr_<exception>,
242                                         @ asr_<exception>, "old_r0"
243
244         mov     r0, sp
245         mov     r1, asr
246         b       bad_mode
247 ENDPROC(__invalid)
248
249         .align  5
250 __dabt_priv:
251         priv_entry
252
253         @
254         @ get ready to re-enable interrupts if appropriate
255         @
256         mov     r17, asr
257         cand.a  r3, #PSR_I_BIT
258         bne     1f
259         andn    r17, r17, #PSR_I_BIT
260 1:
261
262         @
263         @ Call the processor-specific abort handler:
264         @
265         @  r2 - aborted context pc
266         @  r3 - aborted context asr
267         @
268         @ The abort handler must return the aborted address in r0, and
269         @ the fault status register in r1.
270         @
271         movc    r1, p0.c3, #0           @ get FSR
272         movc    r0, p0.c4, #0           @ get FAR
273
274         @
275         @ set desired INTR state, then call main handler
276         @
277         mov.a   asr, r17
278         mov     r2, sp
279         b.l     do_DataAbort
280
281         @
282         @ INTRs off again before pulling preserved data off the stack
283         @
284         disable_irq r0
285
286         @
287         @ restore BSR and restart the instruction
288         @
289         ldw     r2, [sp+], #S_PSR
290         priv_exit r2                            @ return from exception
291 ENDPROC(__dabt_priv)
292
293         .align  5
294 __intr_priv:
295         priv_entry
296
297         intr_handler
298
299         mov     r0, #0                          @ epip4d
300         movc    p0.c5, r0, #14
301         nop; nop; nop; nop; nop; nop; nop; nop
302
303         ldw     r4, [sp+], #S_PSR               @ irqs are already disabled
304
305         priv_exit r4                            @ return from exception
306 ENDPROC(__intr_priv)
307
308         .ltorg
309
310         .align  5
311 __extn_priv:
312         priv_entry
313
314         mov     r0, sp                          @ struct pt_regs *regs
315         mov     r1, asr
316         b       bad_mode                        @ not supported
317 ENDPROC(__extn_priv)
318
319         .align  5
320 __pabt_priv:
321         priv_entry
322
323         @
324         @ re-enable interrupts if appropriate
325         @
326         mov     r17, asr
327         cand.a  r3, #PSR_I_BIT
328         bne     1f
329         andn    r17, r17, #PSR_I_BIT
330 1:
331
332         @
333         @ set args, then call main handler
334         @
335         @  r0 - address of faulting instruction
336         @  r1 - pointer to registers on stack
337         @
338         mov     r0, r2                  @ pass address of aborted instruction
339         mov     r1, #5
340         mov.a   asr, r17
341         mov     r2, sp                  @ regs
342         b.l     do_PrefetchAbort        @ call abort handler
343
344         @
345         @ INTRs off again before pulling preserved data off the stack
346         @
347         disable_irq r0
348
349         @
350         @ restore BSR and restart the instruction
351         @
352         ldw     r2, [sp+], #S_PSR
353         priv_exit r2                    @ return from exception
354 ENDPROC(__pabt_priv)
355
356         .align  5
357 .LCcralign:
358         .word   cr_alignment
359
360         .align  5
361 __dabt_user:
362         user_entry
363
364 #ifdef CONFIG_UNICORE_FPU_F64
365         cff     ip, s31
366         cand.a  ip, #0x08000000         @ FPU execption traps?
367         beq     209f
368
369         ldw     ip, [sp+], #S_PC
370         add     ip, ip, #4
371         stw     ip, [sp+], #S_PC
372         @
373         @ fall through to the emulation code, which returns using r19 if
374         @ it has emulated the instruction, or the more conventional lr
375         @ if we are to treat this as a real extended instruction
376         @
377         @  r0 - instruction
378         @
379 1:      ldw.u   r0, [r2]
380         adr     r19, ret_from_exception
381         adr     lr, 209f
382         @
383         @ fallthrough to call do_uc_f64
384         @
385 /*
386  * Check whether the instruction is a co-processor instruction.
387  * If yes, we need to call the relevant co-processor handler.
388  *
389  * Note that we don't do a full check here for the co-processor
390  * instructions; all instructions with bit 27 set are well
391  * defined.  The only instructions that should fault are the
392  * co-processor instructions.
393  *
394  * Emulators may wish to make use of the following registers:
395  *  r0  = instruction opcode.
396  *  r2  = PC
397  *  r19 = normal "successful" return address
398  *  r20 = this threads thread_info structure.
399  *  lr  = unrecognised instruction return address
400  */
401         get_thread_info r20                     @ get current thread
402         and     r8, r0, #0x00003c00             @ mask out CP number
403         mov     r7, #1
404         stb     r7, [r20+], #TI_USED_CP + 2     @ set appropriate used_cp[]
405
406         @ F64 hardware support entry point.
407         @  r0  = faulted instruction
408         @  r19 = return address
409         @  r20 = fp_state
410         enable_irq r4
411         add     r20, r20, #TI_FPSTATE   @ r20 = workspace
412         cff     r1, s31                 @ get fpu FPSCR
413         andn    r2, r1, #0x08000000
414         ctf     r2, s31                 @ clear 27 bit
415         mov     r2, sp                  @ nothing stacked - regdump is at TOS
416         mov     lr, r19                 @ setup for a return to the user code
417
418         @ Now call the C code to package up the bounce to the support code
419         @   r0 holds the trigger instruction
420         @   r1 holds the FPSCR value
421         @   r2 pointer to register dump
422         b       ucf64_exchandler
423 209:
424 #endif
425         @
426         @ Call the processor-specific abort handler:
427         @
428         @  r2 - aborted context pc
429         @  r3 - aborted context asr
430         @
431         @ The abort handler must return the aborted address in r0, and
432         @ the fault status register in r1.
433         @
434         movc    r1, p0.c3, #0           @ get FSR
435         movc    r0, p0.c4, #0           @ get FAR
436
437         @
438         @ INTRs on, then call the main handler
439         @
440         enable_irq r2
441         mov     r2, sp
442         adr     lr, ret_from_exception
443         b       do_DataAbort
444 ENDPROC(__dabt_user)
445
446         .align  5
447 __intr_user:
448         user_entry
449
450         get_thread_info tsk
451
452         intr_handler
453
454         mov     why, #0
455         b       ret_to_user
456 ENDPROC(__intr_user)
457
458         .ltorg
459
460         .align  5
461 __extn_user:
462         user_entry
463
464         mov     r0, sp
465         mov     r1, asr
466         b       bad_mode
467 ENDPROC(__extn_user)
468
469         .align  5
470 __pabt_user:
471         user_entry
472
473         mov     r0, r2                  @ pass address of aborted instruction.
474         mov     r1, #5
475         enable_irq r1                   @ Enable interrupts
476         mov     r2, sp                  @ regs
477         b.l     do_PrefetchAbort        @ call abort handler
478         /* fall through */
479 /*
480  * This is the return code to user mode for abort handlers
481  */
482 ENTRY(ret_from_exception)
483         get_thread_info tsk
484         mov     why, #0
485         b       ret_to_user
486 ENDPROC(__pabt_user)
487 ENDPROC(ret_from_exception)
488
489 /*
490  * Register switch for UniCore V2 processors
491  * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
492  * previous and next are guaranteed not to be the same.
493  */
494 ENTRY(__switch_to)
495         add     ip, r1, #TI_CPU_SAVE
496         stm.w   (r4 - r15), [ip]+
497         stm.w   (r16 - r27, sp, lr), [ip]+
498
499 #ifdef  CONFIG_UNICORE_FPU_F64
500         add     ip, r1, #TI_FPSTATE
501         sfm.w   (f0  - f7 ), [ip]+
502         sfm.w   (f8  - f15), [ip]+
503         sfm.w   (f16 - f23), [ip]+
504         sfm.w   (f24 - f31), [ip]+
505         cff     r4, s31
506         stw     r4, [ip]
507
508         add     ip, r2, #TI_FPSTATE
509         lfm.w   (f0  - f7 ), [ip]+
510         lfm.w   (f8  - f15), [ip]+
511         lfm.w   (f16 - f23), [ip]+
512         lfm.w   (f24 - f31), [ip]+
513         ldw     r4, [ip]
514         ctf     r4, s31
515 #endif
516         add     ip, r2, #TI_CPU_SAVE
517         ldm.w   (r4 - r15), [ip]+
518         ldm     (r16 - r27, sp, pc), [ip]+      @ Load all regs saved previously
519 ENDPROC(__switch_to)
520
521         .align  5
522 /*
523  * This is the fast syscall return path.  We do as little as
524  * possible here, and this includes saving r0 back into the PRIV
525  * stack.
526  */
527 ret_fast_syscall:
528         disable_irq r1                          @ disable interrupts
529         ldw     r1, [tsk+], #TI_FLAGS
530         cand.a  r1, #_TIF_WORK_MASK
531         bne     fast_work_pending
532
533         @ fast_restore_user_regs
534         restore_user_regs fast = 1, offset = S_OFF
535
536 /*
537  * Ok, we need to do extra processing, enter the slow path.
538  */
539 fast_work_pending:
540         stw.w   r0, [sp+], #S_R0+S_OFF          @ returned r0
541 work_pending:
542         cand.a  r1, #_TIF_NEED_RESCHED
543         bne     work_resched
544         mov     r0, sp                          @ 'regs'
545         mov     r2, why                         @ 'syscall'
546         cand.a  r1, #_TIF_SIGPENDING            @ delivering a signal?
547         cmovne  why, #0                         @ prevent further restarts
548         b.l     do_notify_resume
549         b       ret_slow_syscall                @ Check work again
550
551 work_resched:
552         b.l     schedule
553 /*
554  * "slow" syscall return path.  "why" tells us if this was a real syscall.
555  */
556 ENTRY(ret_to_user)
557 ret_slow_syscall:
558         disable_irq r1                          @ disable interrupts
559         get_thread_info tsk                     @ epip4d, one path error?!
560         ldw     r1, [tsk+], #TI_FLAGS
561         cand.a  r1, #_TIF_WORK_MASK
562         bne     work_pending
563 no_work_pending:
564         @ slow_restore_user_regs
565         restore_user_regs fast = 0, offset = 0
566 ENDPROC(ret_to_user)
567
568 /*
569  * This is how we return from a fork.
570  */
571 ENTRY(ret_from_fork)
572         b.l     schedule_tail
573         b       ret_slow_syscall
574 ENDPROC(ret_from_fork)
575
576 ENTRY(ret_from_kernel_thread)
577         b.l     schedule_tail
578         mov     r0, r5
579         adr     lr, ret_slow_syscall
580         mov     pc, r4
581 ENDPROC(ret_from_kernel_thread)
582
583 /*=============================================================================
584  * SWI handler
585  *-----------------------------------------------------------------------------
586  */
587         .align  5
588 ENTRY(vector_swi)
589         sub     sp, sp, #S_FRAME_SIZE
590         stm     (r0 - r15), [sp]+               @ Calling r0 - r15
591         add     r8, sp, #S_R16
592         stm     (r16 - r28), [r8]+              @ Calling r16 - r28
593         add     r8, sp, #S_PC
594         stur    (sp, lr), [r8-]                 @ Calling sp, lr
595         mov     r8, bsr                         @ called from non-REAL mode
596         stw     lr, [sp+], #S_PC                @ Save calling PC
597         stw     r8, [sp+], #S_PSR               @ Save ASR
598         stw     r0, [sp+], #S_OLD_R0            @ Save OLD_R0
599         zero_fp
600
601         /*
602          * Get the system call number.
603          */
604         sub     ip, lr, #4
605         ldw.u   scno, [ip]                      @ get SWI instruction
606
607 #ifdef CONFIG_ALIGNMENT_TRAP
608         ldw     ip, __cr_alignment
609         ldw     ip, [ip]
610         movc    p0.c1, ip, #0                   @ update control register
611 #endif
612         enable_irq ip
613
614         get_thread_info tsk
615         ldw     tbl, =sys_call_table            @ load syscall table pointer
616
617         andn    scno, scno, #0xff000000         @ mask off SWI op-code
618         andn    scno, scno, #0x00ff0000         @ mask off SWI op-code
619
620         stm.w   (r4, r5), [sp-]                 @ push fifth and sixth args
621         ldw     ip, [tsk+], #TI_FLAGS           @ check for syscall tracing
622         cand.a  ip, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
623         bne     __sys_trace
624
625         csub.a  scno, #__NR_syscalls            @ check upper syscall limit
626         adr     lr, ret_fast_syscall            @ return address
627         bea     1f
628         ldw     pc, [tbl+], scno << #2          @ call sys_* routine
629 1:
630         add     r1, sp, #S_OFF
631 2:      mov     why, #0                         @ no longer a real syscall
632         b       sys_ni_syscall                  @ not private func
633
634         /*
635          * This is the really slow path.  We're going to be doing
636          * context switches, and waiting for our parent to respond.
637          */
638 __sys_trace:
639         mov     r2, scno
640         add     r1, sp, #S_OFF
641         mov     r0, #0                          @ trace entry [IP = 0]
642         b.l     syscall_trace
643
644         adr     lr, __sys_trace_return          @ return address
645         mov     scno, r0                        @ syscall number (possibly new)
646         add     r1, sp, #S_R0 + S_OFF           @ pointer to regs
647         csub.a  scno, #__NR_syscalls            @ check upper syscall limit
648         bea     2b
649         ldm     (r0 - r3), [r1]+                @ have to reload r0 - r3
650         ldw     pc, [tbl+], scno << #2          @ call sys_* routine
651
652 __sys_trace_return:
653         stw.w   r0, [sp+], #S_R0 + S_OFF        @ save returned r0
654         mov     r2, scno
655         mov     r1, sp
656         mov     r0, #1                          @ trace exit [IP = 1]
657         b.l     syscall_trace
658         b       ret_slow_syscall
659
660         .align  5
661 #ifdef CONFIG_ALIGNMENT_TRAP
662         .type   __cr_alignment, #object
663 __cr_alignment:
664         .word   cr_alignment
665 #endif
666         .ltorg
667
668 ENTRY(sys_rt_sigreturn)
669                 add     r0, sp, #S_OFF
670                 mov     why, #0         @ prevent syscall restart handling
671                 b       __sys_rt_sigreturn
672 ENDPROC(sys_rt_sigreturn)
673
674         __INIT
675
676 /*
677  * Vector stubs.
678  *
679  * This code is copied to 0xffff0200 so we can use branches in the
680  * vectors, rather than ldr's.  Note that this code must not
681  * exceed 0x300 bytes.
682  *
683  * Common stub entry macro:
684  *   Enter in INTR mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
685  *
686  * SP points to a minimal amount of processor-private memory, the address
687  * of which is copied into r0 for the mode specific abort handler.
688  */
689         .macro  vector_stub, name, mode
690         .align  5
691
692 vector_\name:
693         @
694         @ Save r0, lr_<exception> (parent PC) and bsr_<exception>
695         @ (parent ASR)
696         @
697         stw     r0, [sp]
698         stw     lr, [sp+], #4           @ save r0, lr
699         mov     lr, bsr
700         stw     lr, [sp+], #8           @ save bsr
701
702         @
703         @ Prepare for PRIV mode.  INTRs remain disabled.
704         @
705         mov     r0, asr
706         xor     r0, r0, #(\mode ^ PRIV_MODE)
707         mov.a   bsr, r0
708
709         @
710         @ the branch table must immediately follow this code
711         @
712         and     lr, lr, #0x03
713         add     lr, lr, #1
714         mov     r0, sp
715         ldw     lr, [pc+], lr << #2
716         mov.a   pc, lr                  @ branch to handler in PRIV mode
717 ENDPROC(vector_\name)
718         .align  2
719         @ handler addresses follow this label
720         .endm
721
722         .globl  __stubs_start
723 __stubs_start:
724 /*
725  * Interrupt dispatcher
726  */
727         vector_stub     intr, INTR_MODE
728
729         .long   __intr_user                     @  0  (USER)
730         .long   __invalid                       @  1
731         .long   __invalid                       @  2
732         .long   __intr_priv                     @  3  (PRIV)
733
734 /*
735  * Data abort dispatcher
736  * Enter in ABT mode, bsr = USER ASR, lr = USER PC
737  */
738         vector_stub     dabt, ABRT_MODE
739
740         .long   __dabt_user                     @  0  (USER)
741         .long   __invalid                       @  1
742         .long   __invalid                       @  2  (INTR)
743         .long   __dabt_priv                     @  3  (PRIV)
744
745 /*
746  * Prefetch abort dispatcher
747  * Enter in ABT mode, bsr = USER ASR, lr = USER PC
748  */
749         vector_stub     pabt, ABRT_MODE
750
751         .long   __pabt_user                     @  0 (USER)
752         .long   __invalid                       @  1
753         .long   __invalid                       @  2 (INTR)
754         .long   __pabt_priv                     @  3 (PRIV)
755
756 /*
757  * Undef instr entry dispatcher
758  * Enter in EXTN mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
759  */
760         vector_stub     extn, EXTN_MODE
761
762         .long   __extn_user                     @  0 (USER)
763         .long   __invalid                       @  1
764         .long   __invalid                       @  2 (INTR)
765         .long   __extn_priv                     @  3 (PRIV)
766
767 /*
768  * We group all the following data together to optimise
769  * for CPUs with separate I & D caches.
770  */
771         .align  5
772
773 .LCvswi:
774         .word   vector_swi
775
776         .globl  __stubs_end
777 __stubs_end:
778
779         .equ    stubs_offset, __vectors_start + 0x200 - __stubs_start
780
781         .globl  __vectors_start
782 __vectors_start:
783         jepriv  SYS_ERROR0
784         b       vector_extn + stubs_offset
785         ldw     pc, .LCvswi + stubs_offset
786         b       vector_pabt + stubs_offset
787         b       vector_dabt + stubs_offset
788         jepriv  SYS_ERROR0
789         b       vector_intr + stubs_offset
790         jepriv  SYS_ERROR0
791
792         .globl  __vectors_end
793 __vectors_end:
794
795         .data
796
797         .globl  cr_alignment
798         .globl  cr_no_alignment
799 cr_alignment:
800         .space  4
801 cr_no_alignment:
802         .space  4