2 * linux/arch/arm/kernel/entry-armv.S
4 * Copyright (C) 1996,1997,1998 Russell King.
5 * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Low-level vector interface routines
13 * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes
14 * it to save wrong values... Be aware!
16 #include <linux/config.h>
17 #include <linux/init.h>
19 #include <asm/thread_info.h>
21 #include <asm/ptrace.h>
22 #include <asm/vfpmacros.h>
24 #include "entry-header.S"
27 /* IOC / IOMD based hardware */
28 #include <asm/hardware/iomd.h>
30 .equ ioc_base_high, IOC_BASE & 0xff000000
31 .equ ioc_base_low, IOC_BASE & 0x00ff0000
33 mov r12, #ioc_base_high
35 orr r12, r12, #ioc_base_low
37 strb r12, [r12, #0x38] @ Disable FIQ register
40 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
41 mov r4, #ioc_base_high @ point at IOC
43 orr r4, r4, #ioc_base_low
45 ldrb \irqstat, [r4, #IOMD_IRQREQB] @ get high priority first
46 ldr \base, =irq_prio_h
49 ldreqb \irqstat, [r4, #IOMD_DMAREQ] @ get dma
50 addeq \base, \base, #256 @ irq_prio_h table size
54 ldreqb \irqstat, [r4, #IOMD_IRQREQA] @ get low priority
55 addeq \base, \base, #256 @ irq_prio_d table size
58 ldreqb \irqstat, [r4, #IOMD_IRQREQC]
59 addeq \base, \base, #256 @ irq_prio_l table size
63 ldreqb \irqstat, [r4, #IOMD_IRQREQD]
64 addeq \base, \base, #256 @ irq_prio_lc table size
67 2406: ldrneb \irqnr, [\base, \irqstat] @ get IRQ number
71 * Interrupt table (incorporates priority). Please note that we
72 * rely on the order of these tables (see above code).
75 irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
76 .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
77 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
78 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
79 .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
80 .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
81 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
82 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
83 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
84 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
85 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
86 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
87 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
88 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
89 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
90 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
92 irq_prio_d: .byte 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
93 .byte 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
94 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
95 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
96 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
97 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
98 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
99 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
100 .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
101 .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
102 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
103 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
104 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
105 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
106 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
107 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
109 irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
110 .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
111 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
112 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
113 .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
114 .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
115 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
116 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
117 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
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
126 irq_prio_lc: .byte 24,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
127 .byte 28,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
128 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
129 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
130 .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
131 .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
132 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
133 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
134 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
135 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
136 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
137 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
138 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
139 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
140 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
141 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
144 irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
145 .byte 44,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
146 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
147 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
148 .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
149 .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
150 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
151 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
152 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
153 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
154 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
155 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
156 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
157 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
158 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
159 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
163 #elif defined(CONFIG_ARCH_EBSA110)
165 #define IRQ_STAT 0xff000000 /* read */
170 .macro get_irqnr_and_base, irqnr, stat, base, tmp
172 ldrb \stat, [\base] @ get interrupts
175 addeq \irqnr, \irqnr, #4
176 moveq \stat, \stat, lsr #4
178 addeq \irqnr, \irqnr, #2
179 moveq \stat, \stat, lsr #2
181 addeq \irqnr, \irqnr, #1
182 moveq \stat, \stat, lsr #1
183 tst \stat, #1 @ bit 0 should be set
186 .macro irq_prio_table
189 #elif defined(CONFIG_ARCH_SHARK)
194 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
198 strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */
199 ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7
200 and \irqstat, \irqnr, #0x80
203 and \irqnr, \irqnr, #7
206 43: mov \irqstat, #0x0C
207 strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
208 ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8
209 and \irqstat, \irqnr, #0x80
212 and \irqnr, \irqnr, #7
213 add \irqnr, \irqnr, #8
217 .macro irq_prio_table
220 #elif defined(CONFIG_FOOTBRIDGE)
221 #include <asm/hardware/dec21285.h>
226 .equ dc21285_high, ARMCSR_BASE & 0xff000000
227 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff
229 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
230 mov r4, #dc21285_high
232 orr r4, r4, #dc21285_low
234 ldr \irqstat, [r4, #0x180] @ get interrupts
236 mov \irqnr, #IRQ_SDRAMPARITY
237 tst \irqstat, #IRQ_MASK_SDRAMPARITY
240 tst \irqstat, #IRQ_MASK_UART_RX
241 movne \irqnr, #IRQ_CONRX
244 tst \irqstat, #IRQ_MASK_DMA1
245 movne \irqnr, #IRQ_DMA1
248 tst \irqstat, #IRQ_MASK_DMA2
249 movne \irqnr, #IRQ_DMA2
252 tst \irqstat, #IRQ_MASK_IN0
253 movne \irqnr, #IRQ_IN0
256 tst \irqstat, #IRQ_MASK_IN1
257 movne \irqnr, #IRQ_IN1
260 tst \irqstat, #IRQ_MASK_IN2
261 movne \irqnr, #IRQ_IN2
264 tst \irqstat, #IRQ_MASK_IN3
265 movne \irqnr, #IRQ_IN3
268 tst \irqstat, #IRQ_MASK_PCI
269 movne \irqnr, #IRQ_PCI
272 tst \irqstat, #IRQ_MASK_DOORBELLHOST
273 movne \irqnr, #IRQ_DOORBELLHOST
276 tst \irqstat, #IRQ_MASK_I2OINPOST
277 movne \irqnr, #IRQ_I2OINPOST
280 tst \irqstat, #IRQ_MASK_TIMER1
281 movne \irqnr, #IRQ_TIMER1
284 tst \irqstat, #IRQ_MASK_TIMER2
285 movne \irqnr, #IRQ_TIMER2
288 tst \irqstat, #IRQ_MASK_TIMER3
289 movne \irqnr, #IRQ_TIMER3
292 tst \irqstat, #IRQ_MASK_UART_TX
293 movne \irqnr, #IRQ_CONTX
296 tst \irqstat, #IRQ_MASK_PCI_ABORT
297 movne \irqnr, #IRQ_PCI_ABORT
300 tst \irqstat, #IRQ_MASK_PCI_SERR
301 movne \irqnr, #IRQ_PCI_SERR
304 tst \irqstat, #IRQ_MASK_DISCARD_TIMER
305 movne \irqnr, #IRQ_DISCARD_TIMER
308 tst \irqstat, #IRQ_MASK_PCI_DPERR
309 movne \irqnr, #IRQ_PCI_DPERR
312 tst \irqstat, #IRQ_MASK_PCI_PERR
313 movne \irqnr, #IRQ_PCI_PERR
317 .macro irq_prio_table
320 #elif defined(CONFIG_ARCH_NEXUSPCI)
325 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
326 ldr \irqstat, =INTCONT_BASE
327 ldr \base, =soft_irq_mask
328 ldr \irqstat, [\irqstat] @ get interrupts
331 and \irqstat, \irqstat, \base @ mask out disabled ones
332 1001: tst \irqstat, #1
333 addeq \irqnr, \irqnr, #1
334 moveq \irqstat, \irqstat, lsr #1
340 .macro irq_prio_table
348 #elif defined(CONFIG_ARCH_TBOX)
353 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
354 ldr \irqstat, =0xffff7000
355 ldr \irqstat, [\irqstat] @ get interrupts
356 ldr \base, =soft_irq_mask
359 and \irqstat, \irqstat, \base @ mask out disabled ones
360 1001: tst \irqstat, #1
361 addeq \irqnr, \irqnr, #1
362 moveq \irqstat, \irqstat, lsr #1
368 .macro irq_prio_table
376 #elif defined(CONFIG_ARCH_SA1100)
381 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
382 mov r4, #0xfa000000 @ ICIP = 0xfa050000
383 add r4, r4, #0x00050000
384 ldr \irqstat, [r4] @ get irqs
385 ldr \irqnr, [r4, #4] @ ICMR = 0xfa050004
386 ands \irqstat, \irqstat, \irqnr
390 moveq \irqstat, \irqstat, lsr #8
391 addeq \irqnr, \irqnr, #8
392 tsteq \irqstat, #0xff
393 moveq \irqstat, \irqstat, lsr #8
394 addeq \irqnr, \irqnr, #8
395 tsteq \irqstat, #0xff
396 moveq \irqstat, \irqstat, lsr #8
397 addeq \irqnr, \irqnr, #8
399 moveq \irqstat, \irqstat, lsr #4
400 addeq \irqnr, \irqnr, #4
402 moveq \irqstat, \irqstat, lsr #2
403 addeq \irqnr, \irqnr, #2
405 addeqs \irqnr, \irqnr, #1
409 .macro irq_prio_table
412 #elif defined(CONFIG_ARCH_L7200)
413 #include <asm/hardware.h>
415 .equ irq_base_addr, IO_BASE_2
420 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
421 mov \irqstat, #irq_base_addr @ Virt addr IRQ regs
422 add \irqstat, \irqstat, #0x00001000 @ Status reg
423 ldr \irqstat, [\irqstat, #0] @ get interrupts
425 1001: tst \irqstat, #1
426 addeq \irqnr, \irqnr, #1
427 moveq \irqstat, \irqstat, lsr #1
433 .macro irq_prio_table
436 #elif defined(CONFIG_ARCH_INTEGRATOR)
441 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
442 /* FIXME: should not be using soo many LDRs here */
443 ldr \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
444 mov \irqnr, #IRQ_PIC_START
445 ldr \irqstat, [\base, #IRQ_STATUS] @ get masked status
446 ldr \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
448 ldreq \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
449 moveq \irqnr, #IRQ_CIC_START
451 1001: tst \irqstat, #15
453 add \irqnr, \irqnr, #4
454 movs \irqstat, \irqstat, lsr #4
456 1002: tst \irqstat, #1
458 add \irqnr, \irqnr, #1
459 movs \irqstat, \irqstat, lsr #1
461 1003: /* EQ will be set if no irqs pending */
464 .macro irq_prio_table
467 #elif defined(CONFIG_ARCH_VERSATILE_PB)
472 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
473 ldr \base, =IO_ADDRESS(VERSATILE_VIC_BASE)
474 ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
479 1001: tst \irqstat, #15
481 add \irqnr, \irqnr, #4
482 movs \irqstat, \irqstat, lsr #4
484 1002: tst \irqstat, #1
486 add \irqnr, \irqnr, #1
487 movs \irqstat, \irqstat, lsr #1
489 1003: /* EQ will be set if no irqs pending */
491 @ clz \irqnr, \irqstat
492 @1003: /* EQ will be set if we reach MAXIRQNUM */
495 .macro irq_prio_table
498 #elif defined(CONFIG_ARCH_CLPS711X)
500 #include <asm/hardware/clps7111.h>
505 #if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
506 #error INTSR stride != INTMR stride
509 .macro get_irqnr_and_base, irqnr, stat, base, mask
510 mov \base, #CLPS7111_BASE
511 ldr \stat, [\base, #INTSR1]
512 ldr \mask, [\base, #INTMR1]
514 mov \mask, \mask, lsl #16
515 and \stat, \stat, \mask, lsr #16
516 movs \stat, \stat, lsr #4
519 add \base, \base, #INTSR2 - INTSR1
520 ldr \stat, [\base, #INTSR1]
521 ldr \mask, [\base, #INTMR1]
523 mov \mask, \mask, lsl #16
524 and \stat, \stat, \mask, lsr #16
526 1001: tst \stat, #255
527 addeq \irqnr, \irqnr, #8
528 moveq \stat, \stat, lsr #8
530 addeq \irqnr, \irqnr, #4
531 moveq \stat, \stat, lsr #4
533 addeq \irqnr, \irqnr, #2
534 moveq \stat, \stat, lsr #2
536 addeq \irqnr, \irqnr, #1
537 moveq \stat, \stat, lsr #1
538 tst \stat, #1 @ bit 0 should be set
541 .macro irq_prio_table
544 #elif defined (CONFIG_ARCH_CAMELOT)
545 #include <asm/arch/platform.h>
546 #undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */
547 #include <asm/arch/int_ctrl00.h>
552 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
554 ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE))
555 ldr \irqnr,[\irqstat]
557 subne \irqnr,\irqnr,#1
562 .macro irq_prio_table
565 #elif defined(CONFIG_ARCH_IOP321)
570 * Note: only deal with normal interrupts, not FIQ
572 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
574 mrc p6, 0, \irqstat, c8, c0, 0 @ Read IINTSRC
579 subs \irqnr,\base,\irqnr
580 add \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT
584 .macro irq_prio_table
587 #elif defined(CONFIG_ARCH_IOP331)
592 * Note: only deal with normal interrupts, not FIQ
594 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
596 mrc p6, 0, \irqstat, c4, c0, 0 @ Read IINTSRC0
599 mrc p6, 0, \irqstat, c5, c0, 0 @ Read IINTSRC1
605 * subs \irqnr,\base,\irqnr
607 rsbs \irqnr,\irqnr,#31 @ recommend by RMK
608 add \irqnr,\irqnr,#IRQ_IOP331_XINT8
610 1002: clz \irqnr, \irqstat
612 subs \irqnr,\base,\irqnr
613 add \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT
617 .macro irq_prio_table
620 #elif defined(CONFIG_ARCH_PXA)
625 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
627 mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP
628 mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR
630 mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000
631 add \base, \base, #0x00d00000
632 ldr \irqstat, [\base, #0] @ ICIP
633 ldr \irqnr, [\base, #4] @ ICMR
635 ands \irqnr, \irqstat, \irqnr
637 rsb \irqstat, \irqnr, #0
638 and \irqstat, \irqstat, \irqnr
640 rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
644 .macro irq_prio_table
647 #elif defined(CONFIG_ARCH_IXP2000)
652 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
654 mov \irqnr, #0x0 @clear out irqnr as default
655 mov \base, #0xfe000000
656 orr \base, \base, #0x00ff0000
657 orr \base, \base, #0x0000a000
658 orr \base, \base, #0x08
659 ldr \irqstat, [\base] @ get interrupts
660 mov \tmp, #IXP2000_VALID_IRQ_MASK & 0xff000000
661 orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x00ff0000
662 orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x0000ff00
663 orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x000000ff
664 and \irqstat, \irqstat, \tmp
671 subs \irqnr, \base, \irqnr
674 * We handle PCIA and PCIB here so we don't have an
675 * extra layer of code just to check these two bits.
677 cmp \irqnr, #IRQ_IXP2000_PCI
680 mov \base, #0xfe000000
681 orr \base, \base, #0x00fd0000
682 orr \base, \base, #0x0000e100
683 orr \base, \base, #0x00000058
684 ldr \irqstat, [\base]
688 movne \irqnr, #IRQ_IXP2000_PCIA
693 movne \irqnr, #IRQ_IXP2000_PCIB
698 .macro irq_prio_table
701 #elif defined (CONFIG_ARCH_IXP4XX)
706 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
707 ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
708 ldr \irqstat, [\irqstat] @ get interrupts
713 subs \irqnr, \base, \irqnr
716 1001: tst \irqstat, #1
717 addeq \irqnr, \irqnr, #1
718 moveq \irqstat, \irqstat, lsr #1
726 .macro irq_prio_table
729 #elif defined(CONFIG_ARCH_OMAP)
734 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
735 ldr \base, =IO_ADDRESS(OMAP_IH1_BASE)
736 ldr \irqnr, [\base, #IRQ_ITR_REG_OFFSET]
737 ldr \tmp, [\base, #IRQ_MIR_REG_OFFSET]
738 mov \irqstat, #0xffffffff
739 bic \tmp, \irqstat, \tmp
743 ldr \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET]
745 ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
746 cmpeq \irqnr, #INT_IH2_IRQ
747 ldreq \base, =IO_ADDRESS(OMAP_IH2_BASE)
748 ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
749 addeqs \irqnr, \irqnr, #32
753 .macro irq_prio_table
756 #elif defined(CONFIG_ARCH_S3C2410)
757 /* S3C2410X IRQ Handler, <ben@simtec.co.uk> */
759 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
762 mov \tmp, #S3C2410_VA_IRQ
763 ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
766 beq 1002f @ external irq reg
768 beq 1003f @ lcd controller
770 @ debug check to see if interrupt reported is the same
775 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
776 mov \irqstat, \irqstat, lsr \irqnr
781 stmfd r13!, { r0 - r4 , r14 }
782 ldr r1, [ \tmp, #0x14 ] @ intoffset
783 ldr r2, [ \tmp, #0x10 ] @ INTPND
784 ldr r3, [ \tmp, #0x00 ] @ SRCPND
790 .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
795 mov \tmp, #S3C2410_VA_IRQ
796 ldmfd r13!, { r0 - r4 , r14 }
798 @ try working out interript number for ourselves
800 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
802 movs \irqstat, \irqstat, lsr#1
803 bcs 30000b @ try and re-start the proccess
804 add \irqnr, \irqnr, #1
808 @ found no interrupt, set Z flag and leave
814 @ we base the s3c2410x interrupts at 16 and above to allow
815 @ isa peripherals to have their standard interrupts, also
816 @ ensure that Z flag is un-set on exit
818 @ note, we cannot be sure if we get IRQ_EINT0 (0) that
819 @ there is simply no interrupt pending, so in all other
820 @ cases we jump to say we have found something, otherwise
821 @ we check to see if the interrupt really is assrted
822 adds \irqnr, \irqnr, #IRQ_EINT0
823 teq \irqnr, #IRQ_EINT0
825 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
830 @ we get here from no main or external interrupts pending
832 add \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
833 ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND
834 ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK
836 bic \irqstat, \irqstat, \irqnr @ clear masked irqs
838 mov \irqnr, #IRQ_EINT4 @ start extint nos
839 mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits
841 movs \irqstat, \irqstat, lsr#1
843 add \irqnr, \irqnr, #1
844 cmp \irqnr, #IRQ_EINT23
847 @ found no interrupt, set Z flag and leave
852 @ lcd interrupt has been asserted...
853 add \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ
854 ldr \irqstat, [ \tmp, # 0x54 ] @ lcd int pending
857 movne \irqnr, #IRQ_LCD_FRAME
859 movne \irqnr, #IRQ_LCD_FIFO
861 @ fall through to exit with flags updated
863 1004: @ ensure Z flag clear in case our MOVS shifted out the last bit
870 /* currently don't need an disable_fiq macro */
875 /* we don't have an irq priority table */
876 .macro irq_prio_table
879 #elif defined(CONFIG_ARCH_LH7A400)
881 # if defined (CONFIG_ARCH_LH7A404)
882 # error "LH7A400 and LH7A404 are mutually exclusive"
887 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
889 mov \base, #io_p2v(0x80000000) @ APB registers
890 ldr \irqstat, [\base, #0x500] @ PIC INTSR
892 1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry
893 bcs 1008f @ Bit set; irq found
894 add \irqnr, \irqnr, #1
895 bne 1001b @ Until no bits
896 b 1009f @ Nothing? Hmm.
897 1008: movs \irqstat, #1 @ Force !Z
901 .macro irq_prio_table
904 #elif defined(CONFIG_ARCH_LH7A404)
909 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
910 mov \irqnr, #0 @ VIC1 irq base
911 mov \base, #io_p2v(0x80000000) @ APB registers
912 add \base, \base, #0x8000
913 ldr \tmp, [\base, #0x0030] @ VIC1_VECTADDR
914 tst \tmp, #VA_VECTORED @ Direct vectored
916 tst \tmp, #VA_VIC1DEFAULT @ Default vectored VIC1
917 ldrne \irqstat, [\base, #0] @ VIC1_IRQSTATUS
919 add \base, \base, #(0xa000 - 0x8000)
920 ldr \tmp, [\base, #0x0030] @ VIC2_VECTADDR
921 tst \tmp, #VA_VECTORED @ Direct vectored
923 ldr \irqstat, [\base, #0] @ VIC2_IRQSTATUS
924 mov \irqnr, #32 @ VIC2 irq base
926 1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry
927 bcs 1008f @ Bit set; irq found
928 add \irqnr, \irqnr, #1
929 bne 1001b @ Until no bits
930 b 1009f @ Nothing? Hmm.
931 1002: and \irqnr, \tmp, #0x3f @ Mask for valid bits
932 1008: movs \irqstat, #1 @ Force !Z
933 str \tmp, [\base, #0x0030] @ Clear vector
937 .macro irq_prio_table
940 #elif defined(CONFIG_ARCH_IMX)
944 #define AITC_NIVECSR 0x40
945 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
946 ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE)
947 @ Load offset & priority of the highest priority
949 ldr \irqnr, [\irqstat, #AITC_NIVECSR]
950 @ Shift off the priority leaving the offset or
952 mov \irqnr, \irqnr, lsr #16
953 ldr \irqstat, =1 @ dummy compare
954 ldr \base, =0xFFFF // invalid interrupt
959 tst \irqstat, #1 @ to make the condition code = TRUE
962 .macro irq_prio_table
965 #elif defined(CONFIG_ARCH_H720X)
970 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
971 #if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
972 @ we could use the id register on H7202, but this is not
973 @ properly updated when we come back from asm_do_irq
974 @ without a previous return from interrupt
975 @ (see loops below in irq_svc, irq_usr)
976 @ We see unmasked pending ints only, as the masked pending ints
977 @ are not visible here
979 mov \base, #0xf0000000 @ base register
980 orr \base, \base, #0x24000 @ irqbase
981 ldr \irqstat, [\base, #0x04] @ get interrupt status
982 #if defined (CONFIG_CPU_H7201)
983 ldr \tmp, =0x001fffff
985 mvn \tmp, #0xc0000000
987 and \irqstat, \irqstat, \tmp @ mask out unused ints
991 orr \tmp, \tmp, #0xff
993 addeq \irqnr, \irqnr, #16
994 moveq \irqstat, \irqstat, lsr #16
996 addeq \irqnr, \irqnr, #8
997 moveq \irqstat, \irqstat, lsr #8
999 addeq \irqnr, \irqnr, #4
1000 moveq \irqstat, \irqstat, lsr #4
1002 addeq \irqnr, \irqnr, #2
1003 moveq \irqstat, \irqstat, lsr #2
1005 addeq \irqnr, \irqnr, #1
1006 moveq \irqstat, \irqstat, lsr #1
1007 tst \irqstat, #1 @ bit 0 should be set
1010 .macro irq_prio_table
1014 #error hynix processor selection missmatch
1017 #elif defined(CONFIG_ARCH_MOXACPU)
1021 .macro get_fiqnr_and_base, irqnr, irqstat, base, tmp
1022 ldr \base, =(IO_ADDRESS(CPE_IC_BASE)+FIQ_STATUS_REG)
1023 ldr \irqstat, [\base]
1028 add \irqnr, \irqnr, #1
1029 mov \irqstat, \irqstat, lsr #1
1035 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
1036 ldr \base, =(IO_ADDRESS(CPE_IC_BASE)+IRQ_STATUS_REG)
1037 ldr \irqstat, [\base]
1042 add \irqnr, \irqnr, #1
1043 mov \irqstat, \irqstat, lsr #1
1049 .macro irq_prio_table
1053 #error Unknown architecture
1057 * Invalid mode handlers
1059 __pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1060 stmia sp, {r0 - lr} @ Save XXX r0 - lr
1062 mov r1, #BAD_PREFETCH
1065 __dabt_invalid: sub sp, sp, #S_FRAME_SIZE
1066 stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact]
1071 __irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame
1072 stmfd sp, {r0 - lr} @ Save r0 - lr
1077 __und_invalid: sub sp, sp, #S_FRAME_SIZE
1080 mov r1, #BAD_UNDEFINSTR @ int reason
1083 ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
1085 stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
1087 and r2, r6, #31 @ int mode
1094 __dabt_svc: sub sp, sp, #S_FRAME_SIZE
1095 stmia sp, {r0 - r12} @ save r0 - r12
1097 add r0, sp, #S_FRAME_SIZE
1098 ldmia r2, {r2 - r4} @ get pc, cpsr
1101 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1102 mrs r9, cpsr @ Enable interrupts if they were
1104 biceq r9, r9, #PSR_I_BIT @ previously
1106 * This routine must not corrupt r9
1109 ldr r4, .LCprocfns @ pass r2, r3 to
1110 mov lr, pc @ processor code
1111 ldr pc, [r4] @ call processor specific code
1113 bl CPU_ABORT_HANDLER
1119 ldr r0, [sp, #S_PSR]
1121 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
1124 __irq_svc: sub sp, sp, #S_FRAME_SIZE
1125 stmia sp, {r0 - r12} @ save r0 - r12
1127 add r5, sp, #S_FRAME_SIZE
1131 stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1132 #ifdef CONFIG_PREEMPT
1134 ldr r9, [r8, #TI_PREEMPT] @ get preempt count
1135 add r7, r9, #1 @ increment it
1136 str r7, [r8, #TI_PREEMPT]
1138 1: get_irqnr_and_base r0, r6, r5, lr
1141 @ routine called with r0 = irq number, r1 = struct pt_regs *
1145 #ifdef CONFIG_PREEMPT
1146 ldr r0, [r8, #TI_FLAGS] @ get flags
1147 tst r0, #_TIF_NEED_RESCHED
1150 ldr r0, [r8, #TI_PREEMPT] @ read preempt value
1152 str r9, [r8, #TI_PREEMPT] @ restore preempt count
1153 strne r0, [r0, -r0] @ bug()
1155 ldr r0, [sp, #S_PSR] @ irqs are already disabled
1157 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
1161 #ifdef CONFIG_PREEMPT
1162 svc_preempt: teq r9, #0 @ was preempt count = 0
1163 ldreq r6, .LCirq_stat
1165 ldr r0, [r6, #4] @ local_irq_count
1166 ldr r1, [r6, #8] @ local_bh_count
1169 mov r7, #PREEMPT_ACTIVE
1170 str r7, [r8, #TI_PREEMPT] @ set PREEMPT_ACTIVE
1171 1: enable_irq r2 @ enable IRQs
1173 disable_irq r0 @ disable IRQs
1174 ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS
1175 tst r0, #_TIF_NEED_RESCHED
1176 beq preempt_return @ go again
1181 __und_svc: sub sp, sp, #S_FRAME_SIZE
1182 stmia sp, {r0 - r12} @ save r0 - r12
1186 add r3, sp, #S_FRAME_SIZE
1188 stmia r2, {r3 - r7} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1190 ldr r0, [r5, #-4] @ r0 = instruction
1191 adrsvc al, r9, 1f @ r9 = normal FP return
1192 bl call_fpe @ lr = undefined instr return
1194 mov r0, sp @ struct pt_regs *regs
1198 ldr lr, [sp, #S_PSR] @ Get SVC cpsr
1200 ldmia sp, {r0 - pc}^ @ Restore SVC registers
1203 __pabt_svc: sub sp, sp, #S_FRAME_SIZE
1204 stmia sp, {r0 - r12} @ save r0 - r12
1206 add r0, sp, #S_FRAME_SIZE
1207 ldmia r2, {r2 - r4} @ get pc, cpsr
1210 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1211 mrs r9, cpsr @ Enable interrupts if they were
1213 biceq r9, r9, #PSR_I_BIT @ previously
1215 mov r0, r2 @ address (pc)
1217 bl do_PrefetchAbort @ call abort handler
1219 ldr r0, [sp, #S_PSR]
1221 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
1224 .LCirq: .word __temp_irq
1225 .LCund: .word __temp_und
1226 .LCabt: .word __temp_abt
1228 .LCprocfns: .word processor
1230 .LCfp: .word fp_enter
1231 #ifdef CONFIG_PREEMPT
1232 .LCirq_stat: .word irq_stat
1238 * User mode handlers
1241 __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1242 stmia sp, {r0 - r12} @ save r0 - r12
1245 ldmia r7, {r2 - r4} @ Get USR pc, cpsr
1246 stmia r5, {r2 - r4} @ Save USR pc, cpsr, old_r0
1248 alignment_trap r7, r7, __temp_abt
1251 ldr r4, .LCprocfns @ pass r2, r3 to
1252 mov lr, pc @ processor code
1253 ldr pc, [r4] @ call processor specific code
1255 bl CPU_ABORT_HANDLER
1257 enable_irq r2 @ Enable interrupts
1259 adrsvc al, lr, ret_from_exception
1263 __irq_usr: sub sp, sp, #S_FRAME_SIZE
1264 stmia sp, {r0 - r12} @ save r0 - r12
1267 ldmia r4, {r5 - r7} @ get saved PC, SPSR
1268 stmia r8, {r5 - r7} @ save pc, psr, old_r0
1270 alignment_trap r4, r7, __temp_irq
1272 #ifdef CONFIG_PREEMPT
1274 ldr r9, [r8, #TI_PREEMPT] @ get preempt count
1275 add r7, r9, #1 @ increment it
1276 str r7, [r8, #TI_PREEMPT]
1278 1: get_irqnr_and_base r0, r6, r5, lr
1282 @ routine called with r0 = irq number, r1 = struct pt_regs *
1285 #ifdef CONFIG_PREEMPT
1286 ldr r0, [r8, #TI_PREEMPT]
1288 str r9, [r8, #TI_PREEMPT]
1300 __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1301 stmia sp, {r0 - r12} @ Save r0 - r12
1305 stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
1306 stmdb r8, {sp, lr}^ @ Save user sp, lr
1307 alignment_trap r4, r7, __temp_und
1309 tst r6, #PSR_T_BIT @ Thumb mode?
1310 bne fpundefinstr @ ignore FP
1312 1: ldrt r0, [r4] @ r0 = instruction
1313 adrsvc al, r9, ret_from_exception @ r9 = normal FP return
1314 adrsvc al, lr, fpundefinstr @ lr = undefined instr return
1317 * The out of line fixup for the ldrt above.
1319 .section .fixup, "ax"
1322 .section __ex_table,"a"
1329 * Check whether the instruction is a co-processor instruction.
1330 * If yes, we need to call the relevant co-processor handler.
1332 * Note that we don't do a full check here for the co-processor
1333 * instructions; all instructions with bit 27 set are well
1334 * defined. The only instructions that should fault are the
1335 * co-processor instructions. However, we have to watch out
1336 * for the ARM6/ARM7 SWI bug.
1338 * Emulators may wish to make use of the following registers:
1339 * r0 - instruction opcode.
1340 * r10 - this threads thread_info structure.
1343 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
1344 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
1345 and r8, r0, #0x0f000000 @ mask out op-code bits
1346 teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)?
1349 get_thread_info r10 @ get current thread
1350 and r8, r0, #0x00000f00 @ mask out CP number
1352 add r6, r10, #TI_USED_CP
1353 strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[]
1354 #ifdef CONFIG_IWMMXT
1355 @ Test if we need to give access to iWMMXt coprocessors
1356 ldr r5, [r10, #TI_FLAGS]
1357 rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only
1358 movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1)
1359 bcs iwmmxt_task_enable
1362 add pc, pc, r8, lsr #6
1366 b do_fpe @ CP#1 (FPE)
1367 b do_fpe @ CP#2 (FPE)
1376 b do_vfp @ CP#10 (VFP)
1377 b do_vfp @ CP#11 (VFP)
1379 mov pc, lr @ CP#10 (VFP)
1380 mov pc, lr @ CP#11 (VFP)
1384 mov pc, lr @ CP#14 (Debug)
1385 mov pc, lr @ CP#15 (Control)
1387 do_fpe: ldr r4, .LCfp
1388 add r10, r10, #TI_FPSTATE @ r10 = workspace
1389 ldr pc, [r4] @ Call FP module USR entry point
1392 * The FP module is called with these registers set:
1395 * r9 = normal "successful" return address
1396 * r10 = FP workspace
1397 * lr = unrecognised FP instruction return address
1405 fpundefinstr: mov r0, sp
1406 adrsvc al, lr, ret_from_exception
1410 __pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1411 stmia sp, {r0 - r12} @ Save r0 - r12
1414 ldmia r4, {r5 - r7} @ Get USR pc, cpsr
1415 stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
1416 stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr
1417 alignment_trap r4, r7, __temp_abt
1419 enable_irq r0 @ Enable interrupts
1420 mov r0, r5 @ address (pc)
1422 bl do_PrefetchAbort @ call abort handler
1425 * This is the return code to user mode for abort handlers
1427 ENTRY(ret_from_exception)
1433 * Register switch for ARMv3 and ARMv4 processors
1434 * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
1435 * previous and next are guaranteed not to be the same.
1438 add ip, r1, #TI_CPU_SAVE
1439 ldr r3, [r2, #TI_CPU_DOMAIN]!
1440 stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
1441 #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
1445 mcr p15, 0, r3, c3, c0, 0 @ Set domain register
1447 @ Always disable VFP so we can lazily save/restore the old
1448 @ state. This occurs in the context of the previous thread.
1450 bic r4, r4, #FPEXC_ENABLE
1453 #if defined(CONFIG_IWMMXT)
1454 bl iwmmxt_task_switch
1455 #elif defined(CONFIG_CPU_XSCALE)
1456 add r4, r2, #40 @ cpu_context_save->extra
1460 ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
1464 * Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary,
1465 * and we rely on each stub being exactly 48 (1.5 cache lines) in size. This
1466 * means that we only ever load two cache lines for this code, or one if we're
1467 * lucky. We also copy this code to 0x200 so that we can use branches in the
1468 * vectors, rather than ldr's.
1473 * Interrupt dispatcher
1474 * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1477 @ save mode specific registers
1481 str lr, [r13] @ save lr_IRQ
1483 str lr, [r13, #4] @ save spsr_IRQ
1484 #if 1 /* add by Victor Yu. 06-09-2005 */
1485 #ifdef CONFIG_CPU_FA_IDLE
1496 cmp r13, lr @ instruction is idle (mcr p15,0,r0,c7,c0,4)
1501 add lr, lr, #4 @ next instruction
1507 #endif /* CONFIG_CPU_FA_IDLE */
1510 @ now branch to the relevant MODE handling routine
1513 bic r13, r13, #MODE_MASK
1514 orr r13, r13, #MODE_SVC
1515 msr spsr_cxsf, r13 @ switch to SVC_32 mode
1518 ldr lr, [pc, lr, lsl #2]
1519 movs pc, lr @ Changes mode and branches
1521 .LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32)
1522 .word __irq_invalid @ 1 (FIQ_26 / FIQ_32)
1523 .word __irq_invalid @ 2 (IRQ_26 / IRQ_32)
1524 .word __irq_svc @ 3 (SVC_26 / SVC_32)
1525 .word __irq_invalid @ 4
1526 .word __irq_invalid @ 5
1527 .word __irq_invalid @ 6
1528 .word __irq_invalid @ 7
1529 .word __irq_invalid @ 8
1530 .word __irq_invalid @ 9
1531 .word __irq_invalid @ a
1532 .word __irq_invalid @ b
1533 .word __irq_invalid @ c
1534 .word __irq_invalid @ d
1535 .word __irq_invalid @ e
1536 .word __irq_invalid @ f
1541 * Data abort dispatcher - dispatches it to the correct handler for the processor mode
1542 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1545 @ save mode specific registers
1553 @ now branch to the relevant MODE handling routine
1556 bic r13, r13, #MODE_MASK
1557 orr r13, r13, #MODE_SVC
1558 msr spsr_cxsf, r13 @ switch to SVC_32 mode
1561 ldr lr, [pc, lr, lsl #2]
1562 movs pc, lr @ Changes mode and branches
1564 .LCtab_dabt: .word __dabt_usr @ 0 (USR_26 / USR_32)
1565 .word __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
1566 .word __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
1567 .word __dabt_svc @ 3 (SVC_26 / SVC_32)
1568 .word __dabt_invalid @ 4
1569 .word __dabt_invalid @ 5
1570 .word __dabt_invalid @ 6
1571 .word __dabt_invalid @ 7
1572 .word __dabt_invalid @ 8
1573 .word __dabt_invalid @ 9
1574 .word __dabt_invalid @ a
1575 .word __dabt_invalid @ b
1576 .word __dabt_invalid @ c
1577 .word __dabt_invalid @ d
1578 .word __dabt_invalid @ e
1579 .word __dabt_invalid @ f
1584 * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode
1585 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1589 @ save mode specific registers
1593 str lr, [r13] @ save lr_ABT
1595 str lr, [r13, #4] @ save spsr_ABT
1597 @ now branch to the relevant MODE handling routine
1600 bic r13, r13, #MODE_MASK
1601 orr r13, r13, #MODE_SVC
1602 msr spsr_cxsf, r13 @ switch to SVC_32 mode
1605 ldr lr, [pc, lr, lsl #2]
1608 .LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32)
1609 .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
1610 .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
1611 .word __pabt_svc @ 3 (SVC_26 / SVC_32)
1612 .word __pabt_invalid @ 4
1613 .word __pabt_invalid @ 5
1614 .word __pabt_invalid @ 6
1615 .word __pabt_invalid @ 7
1616 .word __pabt_invalid @ 8
1617 .word __pabt_invalid @ 9
1618 .word __pabt_invalid @ a
1619 .word __pabt_invalid @ b
1620 .word __pabt_invalid @ c
1621 .word __pabt_invalid @ d
1622 .word __pabt_invalid @ e
1623 .word __pabt_invalid @ f
1628 * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode
1629 * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1633 @ save mode specific registers
1636 str lr, [r13] @ save lr_UND
1638 str lr, [r13, #4] @ save spsr_UND
1640 @ now branch to the relevant MODE handling routine
1643 bic r13, r13, #MODE_MASK
1644 orr r13, r13, #MODE_SVC
1645 msr spsr_cxsf, r13 @ switch to SVC_32 mode
1648 ldr lr, [pc, lr, lsl #2]
1649 movs pc, lr @ Changes mode and branches
1651 .LCtab_und: .word __und_usr @ 0 (USR_26 / USR_32)
1652 .word __und_invalid @ 1 (FIQ_26 / FIQ_32)
1653 .word __und_invalid @ 2 (IRQ_26 / IRQ_32)
1654 .word __und_svc @ 3 (SVC_26 / SVC_32)
1655 .word __und_invalid @ 4
1656 .word __und_invalid @ 5
1657 .word __und_invalid @ 6
1658 .word __und_invalid @ 7
1659 .word __und_invalid @ 8
1660 .word __und_invalid @ 9
1661 .word __und_invalid @ a
1662 .word __und_invalid @ b
1663 .word __und_invalid @ c
1664 .word __und_invalid @ d
1665 .word __und_invalid @ e
1666 .word __und_invalid @ f
1670 /*=============================================================================
1672 *-----------------------------------------------------------------------------
1673 * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
1674 * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
1675 * Basically to switch modes, we *HAVE* to clobber one register... brain
1676 * damage alert! I don't think that we can execute any code in here in any
1677 * other mode than FIQ... Ok you can switch to another mode, but you can't
1678 * get out of that mode without clobbering one register.
1680 vector_FIQ: disable_fiq
1683 /*=============================================================================
1684 * Address exception handler
1685 *-----------------------------------------------------------------------------
1686 * These aren't too critical.
1687 * (they're not supposed to happen, and won't happen in 32-bit data mode).
1694 * We group all the following data together to optimise
1695 * for CPUs with separate I & D caches.
1699 .LCvswi: .word vector_swi
1701 .LCsirq: .word __temp_irq
1702 .LCsund: .word __temp_und
1703 .LCsabt: .word __temp_abt
1704 #if 1 /* add by Victor Yu. 06-09-2005 */
1705 #ifdef CONFIG_CPU_FA_IDLE
1706 .LCidle: .word __idle_inst
1707 #endif /* CONFIG_CPU_FA_IDLE */
1712 .equ __real_stubs_start, .LCvectors + 0x200
1714 .LCvectors: swi SYS_ERROR0
1715 b __real_stubs_start + (vector_undefinstr - __stubs_start)
1716 ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)
1717 b __real_stubs_start + (vector_prefetch - __stubs_start)
1718 b __real_stubs_start + (vector_data - __stubs_start)
1719 b __real_stubs_start + (vector_addrexcptn - __stubs_start)
1720 b __real_stubs_start + (vector_IRQ - __stubs_start)
1721 b __real_stubs_start + (vector_FIQ - __stubs_start)
1724 stmfd sp!, {r4 - r6, lr}
1726 adr r1, .LCvectors @ set up the vectors
1727 ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr}
1728 stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr}
1731 adr r0, __stubs_start @ copy stubs to 0x200
1737 #ifdef CONFIG_BDI2000_XSCALE
1740 LOADREGS(fd, sp!, {r4 - r6, pc})
1745 * Do not reorder these, and do not insert extra data between...
1748 __temp_irq: .word 0 @ saved lr_irq
1749 .word 0 @ saved spsr_irq
1751 __temp_und: .word 0 @ Saved lr_und
1752 .word 0 @ Saved spsr_und
1754 __temp_abt: .word 0 @ Saved lr_abt
1755 .word 0 @ Saved spsr_abt
1757 #if 1 /* add by Victor Yu. 06-09-2005 */
1758 #ifdef CONFIG_CPU_FA_IDLE
1760 .word 0xee070f90 @ machine code of (mcr p15,0,r0,c7,c0,4)
1761 #endif /* CONFIG_CPU_FA_IDLE */
1765 .globl cr_no_alignment