* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / arm / kernel / entry-armo.S
blob5d9ce0ac6622b5f107ea5ad5602d6deac8e5abc4
1 /*
2  * linux/arch/arm/kernel/entry-armo.S
3  *
4  * Copyright (C) 1995,1996,1997,1998 Russell King.
5  *
6  * Low-level vector interface routines
7  *
8  * Design issues:
9  *  - We have several modes that each vector can be called from,
10  *    each with its own set of registers.  On entry to any vector,
11  *    we *must* save the registers used in *that* mode.
12  *
13  *  - This code must be as fast as possible.
14  *
15  * There are a few restrictions on the vectors:
16  *  - the SWI vector cannot be called from *any* non-user mode
17  *
18  *  - the FP emulator is *never* called from *any* non-user mode undefined
19  *    instruction.
20  *
21  * Ok, so this file may be a mess, but its as efficient as possible while
22  * adhering to the above criteria.
23  */
24 #include <linux/linkage.h>
26 #include <asm/assembler.h>
27 #include <asm/errno.h>
28 #include <asm/hardware.h>
30 #include "../lib/constants.h"
32                 .text
34 @ Offsets into task structure
35 @ ---------------------------
37 #define STATE           0
38 #define COUNTER         4
39 #define PRIORITY        8
40 #define FLAGS           12
41 #define SIGPENDING      16
43 #define PF_TRACESYS     0x20
45 @ Bad Abort numbers
46 @ -----------------
48 #define BAD_PREFETCH    0
49 #define BAD_DATA        1
50 #define BAD_ADDREXCPTN  2
51 #define BAD_IRQ         3
52 #define BAD_UNDEFINSTR  4
54 @ OS version number used in SWIs
55 @  RISC OS is 0
56 @  RISC iX is 8
58 #define OS_NUMBER       9
61 @ Stack format (ensured by USER_* and SVC_*)
63 #define S_OLD_R0        64
64 #define S_PSR           60
65 #define S_PC            60
66 #define S_LR            56
67 #define S_SP            52
68 #define S_IP            48
69 #define S_FP            44
70 #define S_R10           40
71 #define S_R9            36
72 #define S_R8            32
73 #define S_R7            28
74 #define S_R6            24
75 #define S_R5            20
76 #define S_R4            16
77 #define S_R3            12
78 #define S_R2            8
79 #define S_R1            4
80 #define S_R0            0
82 #ifdef IOC_BASE
83 /* IOC / IOMD based hardware */
84                 .equ    ioc_base_high, IOC_BASE & 0xff000000
85                 .equ    ioc_base_low, IOC_BASE & 0x00ff0000
86                 .macro  disable_fiq
87                 mov     r12, #ioc_base_high
88                 .if     ioc_base_low
89                 orr     r12, r12, #ioc_base_low
90                 .endif
91                 strb    r12, [r12, #0x38]       @ Disable FIQ register
92                 .endm
94                 .macro  get_irqnr_and_base, irqnr, base
95                 mov     r4, #ioc_base_high              @ point at IOC
96                 .if     ioc_base_low
97                 orr     r4, r4, #ioc_base_low
98                 .endif
99                 ldrb    \irqnr, [r4, #0x24]             @ get high priority first
100                 adr     \base, irq_prio_h
101                 teq     \irqnr, #0
102                 ldreqb  \irqnr, [r4, #0x14]             @ get low priority
103                 adreq   \base, irq_prio_l
104                 .endm
107  * Interrupt table (incorporates priority)
108  */
109                 .macro  irq_prio_table
110 irq_prio_l:     .byte    0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
111                 .byte    4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
112                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
113                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
114                 .byte    6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
115                 .byte    6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
116                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
117                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
118                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
119                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
120                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
121                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
122                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
123                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
124                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
125                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
126 irq_prio_h:     .byte    0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
127                 .byte   12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
128                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
129                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
130                 .byte   14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
131                 .byte   14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
132                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
133                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
134                 .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
135                 .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
136                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
137                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
138                 .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
139                 .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
140                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
141                 .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
142                 .endm
143 #else
144 #error Unknown architecture
145 #endif
147 /*=============================================================================
148  * For entry-common.S
149  */
151                 .macro  save_user_regs
152                 str     r0, [sp, #-4]!
153                 str     lr, [sp, #-4]!
154                 sub     sp, sp, #15*4
155                 stmia   sp, {r0 - lr}^
156                 mov     r0, r0
157                 .endm
159                 .macro  restore_user_regs
160                 ldmia   sp, {r0 - lr}^
161                 mov     r0, r0
162                 ldr     lr, [sp, #15*4]
163                 add     sp, sp, #15*4+8
164                 movs    pc, lr
165                 .endm
167                 .macro  mask_pc, rd, rm
168                 bic     \rd, \rm, #PCMASK
169                 .endm
171                 .macro  arm700_bug_check, instr, temp
172                 .endm
174                 .macro  enable_irqs, temp
175                 teqp    pc, #0x00000003
176                 .endm
178                 .macro  initialise_traps_extra
179                 .endm
181                 .macro  get_current_task, rd
182                 mov     \rd, sp, lsr #13
183                 mov     \rd, \rd, lsl #13
184                 .endm
186                 /*
187                  * Like adr, but force SVC mode (if required)
188                  */
189                 .macro  adrsvc, cond, reg, label
190                 adr\cond        \reg, \label
191                 orr\cond        \reg, \reg, #0x08000003
192                 .endm
194 #if 0
196  * Uncomment these if you wish to get more debugging into about data aborts.
197  */
198 #define FAULT_CODE_LDRSTRPOST   0x80
199 #define FAULT_CODE_LDRSTRPRE    0x40
200 #define FAULT_CODE_LDRSTRREG    0x20
201 #define FAULT_CODE_LDMSTM       0x10
202 #define FAULT_CODE_LDCSTC       0x08
203 #endif
204 #define FAULT_CODE_PREFETCH     0x04
205 #define FAULT_CODE_WRITE        0x02
206 #define FAULT_CODE_USER         0x01
209 #define SVC_SAVE_ALL                            \
210                 str     sp, [sp, #-16]!         ;\
211                 str     lr, [sp, #8]            ;\
212                 str     lr, [sp, #4]            ;\
213                 stmfd   sp!, {r0 - r12}         ;\
214                 mov     r0, #-1                 ;\
215                 str     r0, [sp, #S_OLD_R0]     ;\
216                 mov     fp, #0
218 #define SVC_IRQ_SAVE_ALL                        \
219                 str     sp, [sp, #-16]!         ;\
220                 str     lr, [sp, #4]            ;\
221                 ldr     lr, .LCirq              ;\
222                 ldr     lr, [lr]                ;\
223                 str     lr, [sp, #8]            ;\
224                 stmfd   sp!, {r0 - r12}         ;\
225                 mov     r0, #-1                 ;\
226                 str     r0, [sp, #S_OLD_R0]     ;\
227                 mov     fp, #0
229 #define SVC_RESTORE_ALL                         \
230                 ldmfd   sp, {r0 - pc}^
231                 
232 /*=============================================================================
233  * Undefined FIQs
234  *-----------------------------------------------------------------------------
235  */
236 _unexp_fiq:     ldr     sp, .LCfiq
237                 mov     r12, #IOC_BASE
238                 strb    r12, [r12, #0x38]       @ Disable FIQ register
239                 teqp    pc, #0x0c000003
240                 mov     r0, r0
241                 stmfd   sp!, {r0 - r3, ip, lr}
242                 adr     r0, Lfiqmsg
243                 bl      SYMBOL_NAME(printk)
244                 ldmfd   sp!, {r0 - r3, ip, lr}
245                 teqp    pc, #0x0c000001
246                 mov     r0, r0
247                 movs    pc, lr
249 Lfiqmsg:        .ascii  "*** Unexpected FIQ\n\0"
250                 .align
252 .LCfiq:         .word   __temp_fiq
253 .LCirq:         .word   __temp_irq
255 /*=============================================================================
256  * Undefined instruction handler
257  *-----------------------------------------------------------------------------
258  * Handles floating point instructions
259  */
260 vector_undefinstr:
261                 tst     lr,#3
262                 bne     __und_svc
263                 save_user_regs
264                 mov     fp, #0
265                 teqp    pc, #I_BIT | MODE_SVC
266 .Lbug_undef:
267                 ldr     r4, .LC2
268                 ldr     pc, [r4]                        @ Call FP module USR entry point
270                 .globl  SYMBOL_NAME(fpundefinstr)
271 SYMBOL_NAME(fpundefinstr):                              @ Called by FP module on undefined instr
272                 mov     r0, lr
273                 mov     r1, sp
274                 teqp    pc, #MODE_SVC
275                 bl      SYMBOL_NAME(do_undefinstr)
276                 b       ret_from_exception              @ Normal FP exit
278 __und_svc:      SVC_SAVE_ALL                            @ Non-user mode
279                 mask_pc r0, lr
280                 and     r2, lr, #3
281                 sub     r0, r0, #4
282                 mov     r1, sp
283                 bl      SYMBOL_NAME(do_undefinstr)
284                 SVC_RESTORE_ALL
286 /* We get here if an undefined instruction happens and the floating
287  * point emulator is not present.  If the offending instruction was
288  * a WFS, we just perform a normal return as if we had emulated the
289  * operation.  This is a hack to allow some basic userland binaries
290  * to run so that the emulator module proper can be loaded. --philb
291  */
292 fpe_not_present:
293                 adr     r10, wfs_mask_data
294                 ldmia   r10, {r4, r5, r6, r7, r8}
295                 ldr     r10, [sp, #S_PC]                @ Load PC
296                 sub     r10, r10, #4
297                 mask_pc r10, r10
298                 ldrt    r10, [r10]                      @ get instruction
299                 and     r5, r10, r5
300                 teq     r5, r4                          @ Is it WFS?
301                 beq     ret_from_exception
302                 and     r5, r10, r8
303                 teq     r5, r6                          @ Is it LDF/STF on sp or fp?
304                 teqne   r5, r7
305                 bne     fpundefinstr
306                 tst     r10, #0x00200000                @ Does it have WB
307                 beq     ret_from_exception
308                 and     r4, r10, #255                   @ get offset
309                 and     r6, r10, #0x000f0000
310                 tst     r10, #0x00800000                @ +/-
311                 ldr     r5, [sp, r6, lsr #14]           @ Load reg
312                 rsbeq   r4, r4, #0
313                 add     r5, r5, r4, lsl #2
314                 str     r5, [sp, r6, lsr #14]           @ Save reg
315                 b       ret_from_exception
317 wfs_mask_data:  .word   0x0e200110                      @ WFS/RFS
318                 .word   0x0fef0fff
319                 .word   0x0d0d0100                      @ LDF [sp]/STF [sp]
320                 .word   0x0d0b0100                      @ LDF [fp]/STF [fp]
321                 .word   0x0f0f0f00
323 .LC2:           .word   SYMBOL_NAME(fp_enter)
325 /*=============================================================================
326  * Prefetch abort handler
327  *-----------------------------------------------------------------------------
328  */
330 vector_prefetch:
331                 sub     lr, lr, #4
332                 tst     lr, #3
333                 bne     __pabt_invalid
334                 save_user_regs
335                 teqp    pc, #0x00000003         @ NOT a problem - doesnt change mode
336                 mask_pc r0, lr                  @ Address of abort
337                 mov     r1, sp                  @ Tasks registers
338                 bl      SYMBOL_NAME(do_PrefetchAbort)
339                 teq     r0, #0                  @ If non-zero, we believe this abort..
340                 bne     ret_from_sys_call
341 #ifdef DEBUG_UNDEF
342                 adr     r0, t
343                 bl      SYMBOL_NAME(printk)
344 #endif
345                 ldr     lr, [sp,#S_PC]          @ program to test this on.  I think its
346                 b       .Lbug_undef             @ broken at the moment though!)
348 __pabt_invalid: SVC_SAVE_ALL
349                 mov     r0, sp                          @ Prefetch aborts are definitely *not*
350                 mov     r1, #BAD_PREFETCH               @ allowed in non-user modes.  We cant
351                 and     r2, lr, #3                      @ recover from this problem.
352                 b       SYMBOL_NAME(bad_mode)
354 #ifdef DEBUG_UNDEF
355 t:              .ascii "*** undef ***\r\n\0"
356                 .align
357 #endif
359 /*=============================================================================
360  * Address exception handler
361  *-----------------------------------------------------------------------------
362  * These aren't too critical.
363  * (they're not supposed to happen).
364  * In order to debug the reason for address exceptions in non-user modes,
365  * we have to obtain all the registers so that we can see what's going on.
366  */
368 vector_addrexcptn:
369                 sub     lr, lr, #8
370                 tst     lr, #3
371                 bne     Laddrexcptn_not_user
372                 save_user_regs
373                 teq     pc, #0x00000003
374                 mask_pc r0, lr                  @ Point to instruction
375                 mov     r1, sp                  @ Point to registers
376                 mov     r2, #0x400
377                 mov     lr, pc
378                 bl      SYMBOL_NAME(do_excpt)
379                 b       ret_from_exception
381 Laddrexcptn_not_user:
382                 SVC_SAVE_ALL
383                 and     r2, lr, #3
384                 teq     r2, #3
385                 bne     Laddrexcptn_illegal_mode
386                 teqp    pc, #0x00000003         @ NOT a problem - doesnt change mode
387                 mask_pc r0, lr
388                 mov     r1, sp
389                 orr     r2, r2, #0x400
390                 bl      SYMBOL_NAME(do_excpt)
391                 ldmia   sp, {r0 - lr}           @ I cant remember the reason I changed this...
392                 add     sp, sp, #15*4
393                 movs    pc, lr
395 Laddrexcptn_illegal_mode:
396                 mov     r0, sp
397                 str     lr, [sp, #-4]!
398                 orr     r1, r2, #0x0c000000
399                 teqp    r1, #0                  @ change into mode (wont be user mode)
400                 mov     r0, r0
401                 mov     r1, r8                  @ Any register from r8 - r14 can be banked
402                 mov     r2, r9
403                 mov     r3, r10
404                 mov     r4, r11
405                 mov     r5, r12
406                 mov     r6, r13
407                 mov     r7, r14
408                 teqp    pc, #0x04000003         @ back to svc
409                 mov     r0, r0
410                 stmfd   sp!, {r1-r7}
411                 ldmia   r0, {r0-r7}
412                 stmfd   sp!, {r0-r7}
413                 mov     r0, sp
414                 mov     r1, #BAD_ADDREXCPTN
415                 b       SYMBOL_NAME(bad_mode)
417 /*=============================================================================
418  * Interrupt (IRQ) handler
419  *-----------------------------------------------------------------------------
420  * Note: if in user mode, then *no* kernel routine is running, so do not have
421  *       to save svc lr
422  * (r13 points to irq temp save area)
423  */
425 vector_IRQ:     ldr     r13, .LCirq                     @ I will leave this one in just in case...
426                 sub     lr, lr, #4
427                 str     lr, [r13]
428                 tst     lr, #3
429                 bne     __irq_svc
430                 teqp    pc, #0x08000003
431                 mov     r0, r0
432                 ldr     lr, .LCirq
433                 ldr     lr, [lr]
434                 save_user_regs
436 1:              get_irqnr_and_base r6, r5
437                 teq     r6, #0
438                 ldrneb  r0, [r5, r6]                    @ get IRQ number
439                 movne   r1, sp
440                 @
441                 @ routine called with r0 = irq number, r1 = struct pt_regs *
442                 @
443                 adr     lr, 1b
444                 orr     lr, lr, #0x08000003             @ Force SVC
445                 bne     do_IRQ
446                 mov     r4, #0
447                 b       ret_with_reschedule
449                 irq_prio_table
451 __irq_svc:      teqp    pc, #0x08000003
452                 mov     r0, r0
453                 SVC_IRQ_SAVE_ALL
454                 and     r2, lr, #3
455                 teq     r2, #3
456                 bne     __irq_invalid
457 1:              get_irqnr_and_base r6, r5
458                 teq     r6, #0
459                 ldrneb  r0, [r5, r6]                    @ get IRQ number
460                 movne   r1, sp
461                 @
462                 @ routine called with r0 = irq number, r1 = struct pt_regs *
463                 @
464                 adr     lr, 1b
465                 orr     lr, lr, #0x08000003             @ Force SVC
466                 bne     do_IRQ                          @ Returns to 1b
467                 SVC_RESTORE_ALL
469 __irq_invalid:  mov     r0, sp
470                 mov     r1, #BAD_IRQ
471                 b       SYMBOL_NAME(bad_mode)
473 /*=============================================================================
474  * Data abort handler code
475  *-----------------------------------------------------------------------------
477  * This handles both exceptions from user and SVC modes, computes the address
478  *  range of the problem, and does any correction that is required.  It then
479  *  calls the kernel data abort routine.
481  * This is where I wish that the ARM would tell you which address aborted.
482  */
484 vector_data:    sub     lr, lr, #8              @ Correct lr
485                 tst     lr, #3
486                 bne     Ldata_not_user
487                 save_user_regs
488                 teqp    pc, #0x00000003         @ NOT a problem - doesnt change mode
489                 mask_pc r0, lr
490                 mov     r2, #FAULT_CODE_USER
491                 bl      Ldata_do
492                 b       ret_from_exception
494 Ldata_not_user:
495                 SVC_SAVE_ALL
496                 and     r2, lr, #3
497                 teq     r2, #3
498                 bne     Ldata_illegal_mode
499                 tst     lr, #0x08000000
500                 teqeqp  pc, #0x00000003         @ NOT a problem - doesnt change mode
501                 mask_pc r0, lr
502                 mov     r2, #0
503                 bl      Ldata_do
504                 SVC_RESTORE_ALL
506 Ldata_illegal_mode:
507                 mov     r0, sp
508                 mov     r1, #BAD_DATA
509                 b       SYMBOL_NAME(bad_mode)
511 Ldata_do:       mov     r3, sp
512                 ldr     r4, [r0]                @ Get instruction
513                 tst     r4, #1 << 20            @ Check to see if it is a write instruction
514                 orreq   r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction
515                 mov     r1, r4, lsr #22         @ Now branch to the relevent processing routine
516                 and     r1, r1, #15 << 2
517                 add     pc, pc, r1
518                 movs    pc, lr
519                 b       Ldata_unknown
520                 b       Ldata_unknown
521                 b       Ldata_unknown
522                 b       Ldata_unknown
523                 b       Ldata_ldrstr_post       @ ldr   rd, [rn], #m
524                 b       Ldata_ldrstr_numindex   @ ldr   rd, [rn, #m]    @ RegVal
525                 b       Ldata_ldrstr_post       @ ldr   rd, [rn], rm
526                 b       Ldata_ldrstr_regindex   @ ldr   rd, [rn, rm]
527                 b       Ldata_ldmstm            @ ldm*a rn, <rlist>
528                 b       Ldata_ldmstm            @ ldm*b rn, <rlist>
529                 b       Ldata_unknown
530                 b       Ldata_unknown
531                 b       Ldata_ldrstr_post       @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
532                 b       Ldata_ldcstc_pre        @ ldc   rd, [rn, #m]
533                 b       Ldata_unknown
534 Ldata_unknown:  @ Part of jumptable
535                 mov     r0, r1
536                 mov     r1, r4
537                 mov     r2, r3
538         mov r3, lr
539                 b       baddataabort
541 Ldata_ldrstr_post:
542                 mov     r0, r4, lsr #14         @ Get Rn
543                 and     r0, r0, #15 << 2        @ Mask out reg.
544                 teq     r0, #15 << 2
545                 ldr     r0, [r3, r0]            @ Get register
546                 biceq   r0, r0, #PCMASK
547                 mov     r1, r0
548 #ifdef FAULT_CODE_LDRSTRPOST
549                 orr     r2, r2, #FAULT_CODE_LDRSTRPOST
550 #endif
551                 b       SYMBOL_NAME(do_DataAbort)
553 Ldata_ldrstr_numindex:
554                 mov     r0, r4, lsr #14         @ Get Rn
555                 and     r0, r0, #15 << 2        @ Mask out reg.
556                 teq     r0, #15 << 2
557                 ldr     r0, [r3, r0]            @ Get register
558                 mov     r1, r4, lsl #20
559                 biceq   r0, r0, #PCMASK
560                 tst     r4, #1 << 23
561                 addne   r0, r0, r1, lsr #20
562                 subeq   r0, r0, r1, lsr #20
563                 mov     r1, r0
564 #ifdef FAULT_CODE_LDRSTRPRE
565                 orr     r2, r2, #FAULT_CODE_LDRSTRPRE
566 #endif
567                 b       SYMBOL_NAME(do_DataAbort)
569 Ldata_ldrstr_regindex:
570                 mov     r0, r4, lsr #14         @ Get Rn
571                 and     r0, r0, #15 << 2        @ Mask out reg.
572                 teq     r0, #15 << 2
573                 ldr     r0, [r3, r0]            @ Get register
574                 and     r7, r4, #15
575                 biceq   r0, r0, #PCMASK
576                 teq     r7, #15                 @ Check for PC
577                 ldr     r7, [r3, r7, lsl #2]    @ Get Rm
578                 and     r8, r4, #0x60           @ Get shift types
579                 biceq   r7, r7, #PCMASK
580                 mov     r9, r4, lsr #7          @ Get shift amount
581                 and     r9, r9, #31
582                 teq     r8, #0
583                 moveq   r7, r7, lsl r9
584                 teq     r8, #0x20               @ LSR shift
585                 moveq   r7, r7, lsr r9
586                 teq     r8, #0x40               @ ASR shift
587                 moveq   r7, r7, asr r9
588                 teq     r8, #0x60               @ ROR shift
589                 moveq   r7, r7, ror r9
590                 tst     r4, #1 << 23
591                 addne   r0, r0, r7
592                 subeq   r0, r0, r7              @ Apply correction
593                 mov     r1, r0
594 #ifdef FAULT_CODE_LDRSTRREG
595                 orr     r2, r2, #FAULT_CODE_LDRSTRREG
596 #endif
597                 b       SYMBOL_NAME(do_DataAbort)
599 Ldata_ldmstm:
600                 mov     r7, #0x11
601                 orr     r7, r7, r7, lsl #8
602                 and     r0, r4, r7
603                 and     r1, r4, r7, lsl #1
604                 add     r0, r0, r1, lsr #1
605                 and     r1, r4, r7, lsl #2
606                 add     r0, r0, r1, lsr #2
607                 and     r1, r4, r7, lsl #3
608                 add     r0, r0, r1, lsr #3
609                 add     r0, r0, r0, lsr #8
610                 add     r0, r0, r0, lsr #4
611                 and     r7, r0, #15             @ r7 = no. of registers to transfer.
612                 mov     r5, r4, lsr #14         @ Get Rn
613                 and     r5, r5, #15 << 2
614                 ldr     r0, [r3, r5]            @ Get reg
615                 eor     r6, r4, r4, lsl #2
616                 tst     r6, #1 << 23            @ Check inc/dec ^ writeback
617                 rsbeq   r7, r7, #0
618                 add     r7, r0, r7, lsl #2      @ Do correction (signed)
619                 subne   r1, r7, #1
620                 subeq   r1, r0, #1
621                 moveq   r0, r7
622                 tst     r4, #1 << 21            @ Check writeback
623                 strne   r7, [r3, r5]
624                 eor     r6, r4, r4, lsl #1
625                 tst     r6, #1 << 24            @ Check Pre/Post ^ inc/dec
626                 addeq   r0, r0, #4
627                 addeq   r1, r1, #4
628                 teq     r5, #15*4               @ CHECK FOR PC
629                 biceq   r1, r1, #PCMASK
630                 biceq   r0, r0, #PCMASK
631 #ifdef FAULT_CODE_LDMSTM
632                 orr     r2, r2, #FAULT_CODE_LDMSTM
633 #endif
634                 b       SYMBOL_NAME(do_DataAbort)
636 Ldata_ldcstc_pre:
637                 mov     r0, r4, lsr #14         @ Get Rn
638                 and     r0, r0, #15 << 2        @ Mask out reg.
639                 teq     r0, #15 << 2
640                 ldr     r0, [r3, r0]            @ Get register
641                 mov     r1, r4, lsl #24         @ Get offset
642                 biceq   r0, r0, #PCMASK
643                 tst     r4, #1 << 23
644                 addne   r0, r0, r1, lsr #24
645                 subeq   r0, r0, r1, lsr #24
646                 mov     r1, r0
647 #ifdef FAULT_CODE_LDCSTC
648                 orr     r2, r2, #FAULT_CODE_LDCSTC
649 #endif
650                 b       SYMBOL_NAME(do_DataAbort)
653  * Register switch for older 26-bit only ARMs
654  */
655 ENTRY(__switch_to)
656                 stmfd   sp!, {r4 - sl, fp, lr}          @ Store most regs on stack
657                 str     sp, [r0, #TSS_SAVE]             @ Save sp_SVC
658                 ldr     sp, [r1, #TSS_SAVE]             @ Get saved sp_SVC
659                 ldmfd   sp!, {r4 - sl, fp, pc}^         @ Load all regs saved previously
662  *=============================================================================
663  *              Low-level interface code
664  *-----------------------------------------------------------------------------
665  *              Trap initialisation
666  *-----------------------------------------------------------------------------
668  * Note - FIQ code has changed.  The default is a couple of words in 0x1c, 0x20
669  * that call _unexp_fiq.  Nowever, we now copy the FIQ routine to 0x1c (removes
670  * some excess cycles).
672  * What we need to put into 0-0x1c are branches to branch to the kernel.
673  */
675                 .section ".text.init",#alloc,#execinstr
677 .Ljump_addresses:
678                 swi     SYS_ERROR0
679                 .word   vector_undefinstr       - 12
680                 .word   vector_swi              - 16
681                 .word   vector_prefetch         - 20
682                 .word   vector_data             - 24
683                 .word   vector_addrexcptn       - 28
684                 .word   vector_IRQ              - 32
685                 .word   _unexp_fiq              - 36
686                 b       . + 8
688  * initialise the trap system
689  */
690 ENTRY(trap_init)
691                 stmfd   sp!, {r4 - r7, lr}
692                 adr     r1, .Ljump_addresses
693                 ldmia   r1, {r1 - r7, ip, lr}
694                 orr     r2, lr, r2, lsr #2
695                 orr     r3, lr, r3, lsr #2
696                 orr     r4, lr, r4, lsr #2
697                 orr     r5, lr, r5, lsr #2
698                 orr     r6, lr, r6, lsr #2
699                 orr     r7, lr, r7, lsr #2
700                 orr     ip, lr, ip, lsr #2
701                 mov     r0, #0
702                 stmia   r0, {r1 - r7, ip}
703                 ldmfd   sp!, {r4 - r7, pc}^
705                 .text
707 #include "entry-common.S"
709                 .bss
710 __temp_irq:     .space  4                               @ saved lr_irq
711 __temp_fiq:     .space  128