ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / kernel / entry-armv.S
1 /*
2  *  linux/arch/arm/kernel/entry-armv.S
3  *
4  *  Copyright (C) 1996,1997,1998 Russell King.
5  *  ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk)
6  *
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.
10  *
11  *  Low-level vector interface routines
12  *
13  *  Note:  there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes
14  *  it to save wrong values...  Be aware!
15  */
16 #include <linux/config.h>
17 #include <linux/init.h>
18
19 #include <asm/thread_info.h>
20 #include <asm/glue.h>
21 #include <asm/ptrace.h>
22
23 #include "entry-header.S"
24
25 #ifdef IOC_BASE
26 /* IOC / IOMD based hardware */
27 #include <asm/hardware/iomd.h>
28
29                 .equ    ioc_base_high, IOC_BASE & 0xff000000
30                 .equ    ioc_base_low, IOC_BASE & 0x00ff0000
31                 .macro  disable_fiq
32                 mov     r12, #ioc_base_high
33                 .if     ioc_base_low
34                 orr     r12, r12, #ioc_base_low
35                 .endif
36                 strb    r12, [r12, #0x38]       @ Disable FIQ register
37                 .endm
38
39                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
40                 mov     r4, #ioc_base_high              @ point at IOC
41                 .if     ioc_base_low
42                 orr     r4, r4, #ioc_base_low
43                 .endif
44                 ldrb    \irqstat, [r4, #IOMD_IRQREQB]   @ get high priority first
45                 ldr     \base, =irq_prio_h
46                 teq     \irqstat, #0
47 #ifdef IOMD_BASE
48                 ldreqb  \irqstat, [r4, #IOMD_DMAREQ]    @ get dma
49                 addeq   \base, \base, #256              @ irq_prio_h table size
50                 teqeq   \irqstat, #0
51                 bne     2406f
52 #endif
53                 ldreqb  \irqstat, [r4, #IOMD_IRQREQA]   @ get low priority
54                 addeq   \base, \base, #256              @ irq_prio_d table size
55                 teqeq   \irqstat, #0
56 #ifdef IOMD_IRQREQC
57                 ldreqb  \irqstat, [r4, #IOMD_IRQREQC]
58                 addeq   \base, \base, #256              @ irq_prio_l table size
59                 teqeq   \irqstat, #0
60 #endif
61 #ifdef IOMD_IRQREQD
62                 ldreqb  \irqstat, [r4, #IOMD_IRQREQD]
63                 addeq   \base, \base, #256              @ irq_prio_lc table size
64                 teqeq   \irqstat, #0
65 #endif
66 2406:           ldrneb  \irqnr, [\base, \irqstat]       @ get IRQ number
67                 .endm
68
69 /*
70  * Interrupt table (incorporates priority).  Please note that we
71  * rely on the order of these tables (see above code).
72  */
73                 .macro  irq_prio_table
74 irq_prio_h:     .byte    0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
75                 .byte   12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
76                 .byte   13,13,13,13,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   14,14,14,14,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   13,13,13,13,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   15,15,15,15,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   13,13,13,13,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   15,15,15,15,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   13,13,13,13,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 #ifdef IOMD_BASE
91 irq_prio_d:     .byte    0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
92                 .byte   20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
93                 .byte   21,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   22,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   21,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   23,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   21,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   22,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   21,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 #endif
108 irq_prio_l:     .byte    0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
109                 .byte    4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
110                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
111                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
112                 .byte    6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
113                 .byte    6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
114                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
115                 .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
116                 .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
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 #ifdef IOMD_IRQREQC
125 irq_prio_lc:    .byte   24,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
126                 .byte   28,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
127                 .byte   29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
128                 .byte   29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
129                 .byte   30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
130                 .byte   30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
131                 .byte   29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
132                 .byte   29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
133                 .byte   31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
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 #endif
142 #ifdef IOMD_IRQREQD
143 irq_prio_ld:    .byte   40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
144                 .byte   44,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
145                 .byte   45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
146                 .byte   45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
147                 .byte   46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
148                 .byte   46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
149                 .byte   45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
150                 .byte   45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
151                 .byte   47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
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 #endif
160                 .endm
161
162 #elif defined(CONFIG_ARCH_EBSA110)
163
164 #define IRQ_STAT                0xff000000      /* read */
165
166                 .macro  disable_fiq
167                 .endm
168
169                 .macro  get_irqnr_and_base, irqnr, stat, base, tmp
170                 mov     \base, #IRQ_STAT
171                 ldrb    \stat, [\base]                  @ get interrupts
172                 mov     \irqnr, #0
173                 tst     \stat, #15
174                 addeq   \irqnr, \irqnr, #4
175                 moveq   \stat, \stat, lsr #4
176                 tst     \stat, #3
177                 addeq   \irqnr, \irqnr, #2
178                 moveq   \stat, \stat, lsr #2
179                 tst     \stat, #1
180                 addeq   \irqnr, \irqnr, #1
181                 moveq   \stat, \stat, lsr #1
182                 tst     \stat, #1                       @ bit 0 should be set
183                 .endm
184
185                 .macro  irq_prio_table
186                 .endm
187
188 #elif defined(CONFIG_ARCH_SHARK)
189
190                 .macro  disable_fiq
191                 .endm
192
193                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
194                 mov     r4, #0xe0000000
195
196                 mov     \irqstat, #0x0C
197                 strb    \irqstat, [r4, #0x20]           @outb(0x0C, 0x20) /* Poll command */
198                 ldrb    \irqnr, [r4, #0x20]             @irq = inb(0x20) & 7
199                 and     \irqstat, \irqnr, #0x80
200                 teq     \irqstat, #0
201                 beq     43f
202                 and     \irqnr, \irqnr, #7
203                 teq     \irqnr, #2
204                 bne     44f
205 43:             mov     \irqstat, #0x0C
206                 strb    \irqstat, [r4, #0xa0]           @outb(0x0C, 0xA0) /* Poll command */
207                 ldrb    \irqnr, [r4, #0xa0]             @irq = (inb(0xA0) & 7) + 8
208                 and     \irqstat, \irqnr, #0x80
209                 teq     \irqstat, #0
210                 beq     44f
211                 and     \irqnr, \irqnr, #7
212                 add     \irqnr, \irqnr, #8
213 44:             teq     \irqstat, #0
214                 .endm
215
216                 .macro  irq_prio_table
217                 .endm
218
219 #elif defined(CONFIG_FOOTBRIDGE)
220 #include <asm/hardware/dec21285.h>
221
222                 .macro  disable_fiq
223                 .endm
224
225                 .equ    dc21285_high, ARMCSR_BASE & 0xff000000
226                 .equ    dc21285_low, ARMCSR_BASE & 0x00ffffff
227
228                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
229                 mov     r4, #dc21285_high
230                 .if     dc21285_low
231                 orr     r4, r4, #dc21285_low
232                 .endif
233                 ldr     \irqstat, [r4, #0x180]          @ get interrupts
234
235                 mov     \irqnr, #IRQ_SDRAMPARITY
236                 tst     \irqstat, #IRQ_MASK_SDRAMPARITY
237                 bne     1001f
238
239                 tst     \irqstat, #IRQ_MASK_UART_RX
240                 movne   \irqnr, #IRQ_CONRX
241                 bne     1001f
242
243                 tst     \irqstat, #IRQ_MASK_DMA1
244                 movne   \irqnr, #IRQ_DMA1
245                 bne     1001f
246
247                 tst     \irqstat, #IRQ_MASK_DMA2
248                 movne   \irqnr, #IRQ_DMA2
249                 bne     1001f
250
251                 tst     \irqstat, #IRQ_MASK_IN0
252                 movne   \irqnr, #IRQ_IN0
253                 bne     1001f
254
255                 tst     \irqstat, #IRQ_MASK_IN1
256                 movne   \irqnr, #IRQ_IN1
257                 bne     1001f
258
259                 tst     \irqstat, #IRQ_MASK_IN2
260                 movne   \irqnr, #IRQ_IN2
261                 bne     1001f
262
263                 tst     \irqstat, #IRQ_MASK_IN3
264                 movne   \irqnr, #IRQ_IN3
265                 bne     1001f
266
267                 tst     \irqstat, #IRQ_MASK_PCI
268                 movne   \irqnr, #IRQ_PCI
269                 bne     1001f
270
271                 tst     \irqstat, #IRQ_MASK_DOORBELLHOST
272                 movne   \irqnr, #IRQ_DOORBELLHOST
273                 bne     1001f
274         
275                 tst     \irqstat, #IRQ_MASK_I2OINPOST
276                 movne   \irqnr, #IRQ_I2OINPOST
277                 bne     1001f
278
279                 tst     \irqstat, #IRQ_MASK_TIMER1
280                 movne   \irqnr, #IRQ_TIMER1
281                 bne     1001f
282
283                 tst     \irqstat, #IRQ_MASK_TIMER2
284                 movne   \irqnr, #IRQ_TIMER2
285                 bne     1001f
286
287                 tst     \irqstat, #IRQ_MASK_TIMER3
288                 movne   \irqnr, #IRQ_TIMER3
289                 bne     1001f
290
291                 tst     \irqstat, #IRQ_MASK_UART_TX
292                 movne   \irqnr, #IRQ_CONTX
293                 bne     1001f
294
295                 tst     \irqstat, #IRQ_MASK_PCI_ABORT
296                 movne   \irqnr, #IRQ_PCI_ABORT
297                 bne     1001f
298
299                 tst     \irqstat, #IRQ_MASK_PCI_SERR
300                 movne   \irqnr, #IRQ_PCI_SERR
301                 bne     1001f
302
303                 tst     \irqstat, #IRQ_MASK_DISCARD_TIMER
304                 movne   \irqnr, #IRQ_DISCARD_TIMER
305                 bne     1001f
306
307                 tst     \irqstat, #IRQ_MASK_PCI_DPERR
308                 movne   \irqnr, #IRQ_PCI_DPERR
309                 bne     1001f
310
311                 tst     \irqstat, #IRQ_MASK_PCI_PERR
312                 movne   \irqnr, #IRQ_PCI_PERR
313 1001:
314                 .endm
315
316                 .macro  irq_prio_table
317                 .endm
318
319 #elif defined(CONFIG_ARCH_NEXUSPCI)
320
321                 .macro  disable_fiq
322                 .endm
323
324                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
325                 ldr     \irqstat, =INTCONT_BASE
326                 ldr     \base, =soft_irq_mask
327                 ldr     \irqstat, [\irqstat]            @ get interrupts
328                 ldr     \base, [\base]
329                 mov     \irqnr, #0
330                 and     \irqstat, \irqstat, \base       @ mask out disabled ones
331 1001:           tst     \irqstat, #1
332                 addeq   \irqnr, \irqnr, #1
333                 moveq   \irqstat, \irqstat, lsr #1
334                 tsteq   \irqnr, #32
335                 beq     1001b
336                 teq     \irqnr, #32
337                 .endm
338
339                 .macro  irq_prio_table
340                 .ltorg
341                 .bss
342 ENTRY(soft_irq_mask)
343                 .word   0
344                 .text
345                 .endm
346
347 #elif defined(CONFIG_ARCH_TBOX)
348
349                 .macro  disable_fiq
350                 .endm
351
352                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
353                 ldr     \irqstat, =0xffff7000
354                 ldr     \irqstat, [\irqstat]            @ get interrupts
355                 ldr     \base, =soft_irq_mask
356                 ldr     \base, [\base]
357                 mov     \irqnr, #0
358                 and     \irqstat, \irqstat, \base       @ mask out disabled ones
359 1001:           tst     \irqstat, #1
360                 addeq   \irqnr, \irqnr, #1
361                 moveq   \irqstat, \irqstat, lsr #1
362                 tsteq   \irqnr, #32
363                 beq     1001b
364                 teq     \irqnr, #32
365                 .endm
366
367                 .macro  irq_prio_table
368                 .ltorg
369                 .bss
370 ENTRY(soft_irq_mask)
371                 .word   0
372                 .text
373                 .endm
374
375 #elif defined(CONFIG_ARCH_SA1100)
376
377                 .macro  disable_fiq
378                 .endm
379
380                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
381                 mov     r4, #0xfa000000                 @ ICIP = 0xfa050000
382                 add     r4, r4, #0x00050000
383                 ldr     \irqstat, [r4]                  @ get irqs
384                 ldr     \irqnr, [r4, #4]                @ ICMR = 0xfa050004
385                 ands    \irqstat, \irqstat, \irqnr
386                 mov     \irqnr, #0
387                 beq     1001f
388                 tst     \irqstat, #0xff
389                 moveq   \irqstat, \irqstat, lsr #8
390                 addeq   \irqnr, \irqnr, #8
391                 tsteq   \irqstat, #0xff
392                 moveq   \irqstat, \irqstat, lsr #8
393                 addeq   \irqnr, \irqnr, #8
394                 tsteq   \irqstat, #0xff
395                 moveq   \irqstat, \irqstat, lsr #8
396                 addeq   \irqnr, \irqnr, #8
397                 tst     \irqstat, #0x0f
398                 moveq   \irqstat, \irqstat, lsr #4
399                 addeq   \irqnr, \irqnr, #4
400                 tst     \irqstat, #0x03
401                 moveq   \irqstat, \irqstat, lsr #2
402                 addeq   \irqnr, \irqnr, #2
403                 tst     \irqstat, #0x01
404                 addeqs  \irqnr, \irqnr, #1
405 1001:
406                 .endm
407
408                 .macro  irq_prio_table
409                 .endm
410
411 #elif defined(CONFIG_ARCH_L7200)
412 #include <asm/hardware.h>
413         
414                 .equ    irq_base_addr,  IO_BASE_2
415
416                 .macro  disable_fiq
417                 .endm
418  
419                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
420                 mov     \irqstat, #irq_base_addr                @ Virt addr IRQ regs
421                 add     \irqstat, \irqstat, #0x00001000         @ Status reg
422                 ldr     \irqstat, [\irqstat, #0]                @ get interrupts
423                 mov     \irqnr, #0
424 1001:           tst     \irqstat, #1
425                 addeq   \irqnr, \irqnr, #1
426                 moveq   \irqstat, \irqstat, lsr #1
427                 tsteq   \irqnr, #32
428                 beq     1001b
429                 teq     \irqnr, #32
430                 .endm
431
432                 .macro  irq_prio_table
433                 .endm
434
435 #elif defined(CONFIG_ARCH_INTEGRATOR)
436
437                 .macro  disable_fiq
438                 .endm
439
440                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
441 /* FIXME: should not be using soo many LDRs here */
442                 ldr     \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
443                 mov     \irqnr, #IRQ_PIC_START
444                 ldr     \irqstat, [\base, #IRQ_STATUS]          @ get masked status
445                 ldr     \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
446                 teq     \irqstat, #0
447                 ldreq   \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
448                 moveq   \irqnr, #IRQ_CIC_START
449
450 1001:           tst     \irqstat, #15
451                 bne     1002f
452                 add     \irqnr, \irqnr, #4
453                 movs    \irqstat, \irqstat, lsr #4
454                 bne     1001b
455 1002:           tst     \irqstat, #1
456                 bne     1003f
457                 add     \irqnr, \irqnr, #1
458                 movs    \irqstat, \irqstat, lsr #1
459                 bne     1002b
460 1003:           /* EQ will be set if no irqs pending */
461                 .endm
462
463                 .macro  irq_prio_table
464                 .endm
465
466 #elif defined(CONFIG_ARCH_VERSATILE_PB)
467
468                 .macro  disable_fiq
469                 .endm
470
471                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
472                 ldr     \base, =IO_ADDRESS(VERSATILE_VIC_BASE)
473                 ldr     \irqstat, [\base, #VIC_IRQ_STATUS]      @ get masked status
474                 mov     \irqnr, #0
475                 teq     \irqstat, #0
476                 beq     1003f
477
478 1001:           tst     \irqstat, #15
479                 bne     1002f
480                 add     \irqnr, \irqnr, #4
481                 movs    \irqstat, \irqstat, lsr #4
482                 bne     1001b
483 1002:           tst     \irqstat, #1
484                 bne     1003f
485                 add     \irqnr, \irqnr, #1
486                 movs    \irqstat, \irqstat, lsr #1
487                 bne     1002b
488 1003:           /* EQ will be set if no irqs pending */
489
490 @               clz     \irqnr, \irqstat
491 @1003:          /* EQ will be set if we reach MAXIRQNUM */
492                 .endm
493
494                 .macro  irq_prio_table
495                 .endm
496
497 #elif defined(CONFIG_ARCH_CLPS711X)
498
499 #include <asm/hardware/clps7111.h>
500
501                 .macro  disable_fiq
502                 .endm
503
504 #if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
505 #error INTSR stride != INTMR stride
506 #endif
507
508                 .macro  get_irqnr_and_base, irqnr, stat, base, mask
509                 mov     \base, #CLPS7111_BASE
510                 ldr     \stat, [\base, #INTSR1]
511                 ldr     \mask, [\base, #INTMR1]
512                 mov     \irqnr, #4
513                 mov     \mask, \mask, lsl #16
514                 and     \stat, \stat, \mask, lsr #16
515                 movs    \stat, \stat, lsr #4
516                 bne     1001f
517
518                 add     \base, \base, #INTSR2 - INTSR1
519                 ldr     \stat, [\base, #INTSR1]
520                 ldr     \mask, [\base, #INTMR1]
521                 mov     \irqnr, #16
522                 mov     \mask, \mask, lsl #16
523                 and     \stat, \stat, \mask, lsr #16
524
525 1001:           tst     \stat, #255
526                 addeq   \irqnr, \irqnr, #8
527                 moveq   \stat, \stat, lsr #8
528                 tst     \stat, #15
529                 addeq   \irqnr, \irqnr, #4
530                 moveq   \stat, \stat, lsr #4
531                 tst     \stat, #3
532                 addeq   \irqnr, \irqnr, #2
533                 moveq   \stat, \stat, lsr #2
534                 tst     \stat, #1
535                 addeq   \irqnr, \irqnr, #1
536                 moveq   \stat, \stat, lsr #1
537                 tst     \stat, #1                       @ bit 0 should be set
538                 .endm
539
540                 .macro  irq_prio_table
541                 .endm
542         
543 #elif defined (CONFIG_ARCH_CAMELOT)
544 #include <asm/arch/platform.h>
545 #undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */
546 #include <asm/arch/int_ctrl00.h>
547         
548                 .macro  disable_fiq
549                 .endm
550
551                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
552         
553                 ldr     \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE))
554                 ldr     \irqnr,[\irqstat]               
555                 cmp     \irqnr,#0
556                 subne   \irqnr,\irqnr,#1
557
558         
559                 .endm
560
561                 .macro  irq_prio_table
562                 .endm
563
564 #elif defined(CONFIG_ARCH_IOP310) || defined(CONFIG_ARCH_ADIFCC)
565
566                 .macro  disable_fiq
567                 .endm
568
569                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
570                 mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC
571                 mrc p13, 0, \base, c0, c0, 0    @ get INTCTL
572
573                 tst \irqstat, #(1<<29)      @ if INTSRC_BI
574                 tstne   \base, #(1<<3)          @ and INTCTL_BM
575                 movne   \irqnr, #IRQ_XS80200_BCU
576                 bne 1001f
577
578                 tst \irqstat, #(1<<28)      @ if INTSRC_PI
579                 tstne   \base, #(1<<2)          @ and INTCTL_PM
580                 movne   \irqnr, #IRQ_XS80200_PMU
581                 bne 1001f
582
583                 tst \irqstat, #(1<<31)      @ if INTSRC_FI
584                 tstne   \base, #(1<<0)          @ and INTCTL_FM
585                 movne   \irqnr, #IRQ_XS80200_EXTFIQ
586                 bne 1001f
587
588                 tst \irqstat, #(1<<30)      @ if INTSRC_II
589                 tstne   \base, #(1<<1)          @ and INTCTL_IM
590                 movne   \irqnr, #IRQ_XS80200_EXTIRQ
591
592 1001:
593                 .endm
594
595                 .macro  irq_prio_table
596                 .endm
597
598 #elif defined(CONFIG_ARCH_IOP321)
599                 .macro  disable_fiq
600                 .endm
601
602                 /*
603                  * Note: only deal with normal interrupts, not FIQ
604                  */
605                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
606                 mov     \irqnr, #0
607                 mrc     p6, 0, \irqstat, c8, c0, 0      @ Read IINTSRC
608                 cmp     \irqstat, #0
609                 beq     1001f
610                 clz     \irqnr, \irqstat
611                 mov     \base, #31
612                 subs    \irqnr,\base,\irqnr
613                 add     \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT
614 1001:
615                 .endm
616
617                 .macro  irq_prio_table
618                 .endm
619
620 #elif defined(CONFIG_ARCH_PXA)
621
622                 .macro  disable_fiq
623                 .endm
624
625                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
626                 mov     \base, #io_p2v(0x40000000)      @ IIR Ctl = 0x40d00000
627                 add     \base, \base, #0x00d00000
628                 ldr     \irqstat, [\base, #0]           @ ICIP
629                 ldr     \irqnr, [\base, #4]             @ ICMR
630                 ands    \irqnr, \irqstat, \irqnr
631                 beq     1001f
632                 rsb     \irqstat, \irqnr, #0
633                 and     \irqstat, \irqstat, \irqnr
634                 clz     \irqnr, \irqstat
635                 rsb     \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
636 1001:
637                 .endm
638
639                 .macro  irq_prio_table
640                 .endm
641
642 #elif defined(CONFIG_ARCH_OMAP)
643
644                 .macro  disable_fiq
645                 .endm
646
647                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
648                 ldr     \base, =IO_ADDRESS(OMAP_IH1_BASE)
649                 ldr     \irqnr, [\base, #IRQ_ITR]
650                 ldr     \tmp, [\base, #IRQ_MIR]
651                 mov     \irqstat, #0xffffffff
652                 bic     \tmp, \irqstat, \tmp
653                 tst     \irqnr, \tmp
654                 beq     1510f
655
656                 ldr     \irqnr, [\base, #IRQ_SIR_FIQ]
657                 cmp     \irqnr, #0
658                 ldreq   \irqnr, [\base, #IRQ_SIR_IRQ]
659                 cmpeq   \irqnr, #INT_IH2_IRQ
660                 ldreq   \base, =IO_ADDRESS(OMAP_IH2_BASE)
661                 ldreq   \irqnr, [\base, #IRQ_SIR_IRQ]
662                 addeqs  \irqnr, \irqnr, #32
663 1510:
664                 .endm
665
666                 .macro  irq_prio_table
667                 .endm
668
669 #elif defined(CONFIG_ARCH_S3C2410)
670                 /* S3C2410X IRQ Handler, <ben@simtec.co.uk> */
671
672                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
673
674 30000:
675                 mov     \tmp, #S3C2410_VA_IRQ
676                 ldr     \irqnr, [ \tmp, #0x14 ]         @ get irq no
677                 teq     \irqnr, #4
678                 teqne   \irqnr, #5
679                 beq     1002f                           @ external irq reg
680                 teq     \irqnr, #16
681                 beq     1003f                           @ lcd controller
682
683                 @ debug check to see if interrupt reported is the same
684                 @ as the offset....
685
686                 teq     \irqnr, #0
687                 beq     20002f
688                 ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
689                 mov     \irqstat, \irqstat, lsr \irqnr
690                 tst     \irqstat, #1
691                 bne     20002f
692
693 #if 1
694                 stmfd   r13!, { r0 - r4 , r14 }
695                 ldr     r1,     [ \tmp, #0x14 ]         @ intoffset
696                 ldr     r2,     [ \tmp, #0x10 ]         @ INTPND
697                 ldr     r3,     [ \tmp, #0x00 ]         @ SRCPND
698                 adr     r0, 20003f
699                 bl      printk
700                 b       20004f
701 #endif
702 20003:
703                 .ascii  "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
704                 .byte   0
705                 .align  4
706 20004:
707                 mov     r1, #1
708                 mov     \tmp, #S3C2410_VA_IRQ
709                 ldmfd   r13!, { r0 - r4 , r14 }
710
711                 @ try working out interript number for ourselves
712                 mov     \irqnr, #0
713                 ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
714 10021:
715                 movs    \irqstat, \irqstat, lsr#1
716                 bcs     30000b          @ try and re-start the proccess
717                 add     \irqnr, \irqnr, #1
718                 cmp     \irqnr, #32
719                 ble     10021b
720
721                 @ found no interrupt, set Z flag and leave
722                 movs    \irqnr, #0
723                 b       1001f
724
725 20005:
726 20002:          @ exit
727                 @ we base the s3c2410x interrupts at 16 and above to allow
728                 @ isa peripherals to have their standard interrupts, also
729                 @ ensure that Z flag is un-set on exit
730
731                 @ note, we cannot be sure if we get IRQ_EINT0 (0) that
732                 @ there is simply no interrupt pending, so in all other
733                 @ cases we jump to say we have found something, otherwise
734                 @ we check to see if the interrupt really is assrted
735                 adds    \irqnr, \irqnr, #IRQ_EINT0
736                 teq     \irqnr, #IRQ_EINT0
737                 bne     1001f                           @ exit
738                 ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
739                 teq     \irqstat, #0
740                 moveq   \irqnr, #0
741                 b       1001f
742
743                 @ we get here from no main or external interrupts pending
744 1002:
745                 add     \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
746                 ldr     \irqstat, [ \tmp, # 0xa8 ]      @ EXTINTPEND
747                 ldr     \irqnr, [ \tmp, # 0xa4 ]        @ EXTINTMASK
748
749                 bic     \irqstat, \irqstat, \irqnr      @ clear masked irqs
750
751                 mov     \irqnr, #IRQ_EINT4              @ start extint nos
752                 mov     \irqstat, \irqstat, lsr#4       @ ignore bottom 4 bits
753 10021:
754                 movs    \irqstat, \irqstat, lsr#1
755                 bcs     1004f
756                 add     \irqnr, \irqnr, #1
757                 cmp     \irqnr, #IRQ_EINT23
758                 ble     10021b
759
760                 @ found no interrupt, set Z flag and leave
761                 movs    \irqnr, #0
762                 b       1001f
763
764 1003:
765                 @ lcd interrupt has been asserted...
766                 add     \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ
767                 ldr     \irqstat, [ \tmp, # 0x54 ]      @ lcd int pending
768
769                 tst     \irqstat, #2
770                 movne   \irqnr, #IRQ_LCD_FRAME
771                 tst     \irqstat, #1
772                 movne   \irqnr, #IRQ_LCD_FIFO
773
774                 @ fall through to exit with flags updated
775
776 1004:           @ ensure Z flag clear in case our MOVS shifted out the last bit
777                 teq     \irqnr, #0
778 1001:
779                 @ exit irq routine
780                 .endm
781
782
783                 /* currently don't need an disable_fiq macro */
784
785                 .macro  disable_fiq
786                 .endm
787
788                 /* we don't have an irq priority table */
789                 .macro irq_prio_table
790                 .endm
791
792 #elif defined(CONFIG_ARCH_LH7A400)
793
794 # if defined (CONFIG_ARCH_LH7A404)
795 #  error "LH7A400 and LH7A404 are mutually exclusive"
796 # endif
797                 .macro  disable_fiq
798                 .endm
799
800                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
801                 mov     \irqnr, #0
802                 mov     \base, #io_p2v(0x80000000)      @ APB registers
803                 ldr     \irqstat, [\base, #0x500]       @ PIC INTSR
804
805 1001:           movs    \irqstat, \irqstat, lsr #1      @ Shift into carry
806                 bcs     1008f                           @ Bit set; irq found
807                 add     \irqnr, \irqnr, #1
808                 bne     1001b                           @ Until no bits
809                 b       1009f                           @ Nothing?  Hmm.
810 1008:           movs    \irqstat, #1                    @ Force !Z
811 1009:
812                .endm
813
814                .macro  irq_prio_table
815                .endm
816
817 #elif defined(CONFIG_ARCH_LH7A404)
818
819                 .macro  disable_fiq
820                 .endm
821
822                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
823                 mov     \irqnr, #0                      @ VIC1 irq base
824                 mov     \base, #io_p2v(0x80000000)      @ APB registers
825                 add     \base, \base, #0x8000
826                 ldr     \tmp, [\base, #0x0030]          @ VIC1_VECTADDR
827                 tst     \tmp, #VA_VECTORED              @ Direct vectored
828                 bne     1002f
829                 tst     \tmp, #VA_VIC1DEFAULT           @ Default vectored VIC1
830                 ldrne   \irqstat, [\base, #0]           @ VIC1_IRQSTATUS
831                 bne     1001f
832                 add     \base, \base, #(0xa000 - 0x8000)
833                 ldr     \tmp, [\base, #0x0030]          @ VIC2_VECTADDR
834                 tst     \tmp, #VA_VECTORED              @ Direct vectored
835                 bne     1002f
836                 ldr     \irqstat, [\base, #0]           @ VIC2_IRQSTATUS
837                 mov     \irqnr, #32                     @ VIC2 irq base
838
839 1001:           movs    \irqstat, \irqstat, lsr #1      @ Shift into carry
840                 bcs     1008f                           @ Bit set; irq found
841                 add     \irqnr, \irqnr, #1
842                 bne     1001b                           @ Until no bits
843                 b       1009f                           @ Nothing?  Hmm.
844 1002:           and     \irqnr, \tmp, #0x3f             @ Mask for valid bits
845 1008:           movs    \irqstat, #1                    @ Force !Z
846                 str     \tmp, [\base, #0x0030]          @ Clear vector
847 1009:
848                .endm
849
850                .macro  irq_prio_table
851                .endm
852
853 #else
854 #error Unknown architecture
855 #endif
856
857 /*
858  * Invalid mode handlers
859  */
860 __pabt_invalid: sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
861                 stmia   sp, {r0 - lr}                   @ Save XXX r0 - lr
862                 ldr     r4, .LCabt
863                 mov     r1, #BAD_PREFETCH
864                 b       1f
865
866 __dabt_invalid: sub     sp, sp, #S_FRAME_SIZE
867                 stmia   sp, {r0 - lr}                   @ Save SVC r0 - lr [lr *should* be intact]
868                 ldr     r4, .LCabt
869                 mov     r1, #BAD_DATA
870                 b       1f
871
872 __irq_invalid:  sub     sp, sp, #S_FRAME_SIZE           @ Allocate space on stack for frame
873                 stmfd   sp, {r0 - lr}                   @ Save r0 - lr
874                 ldr     r4, .LCirq
875                 mov     r1, #BAD_IRQ
876                 b       1f
877
878 __und_invalid:  sub     sp, sp, #S_FRAME_SIZE
879                 stmia   sp, {r0 - lr}
880                 ldr     r4, .LCund
881                 mov     r1, #BAD_UNDEFINSTR             @ int reason
882
883 1:              zero_fp
884                 ldmia   r4, {r5 - r7}                   @ Get XXX pc, cpsr, old_r0
885                 add     r4, sp, #S_PC
886                 stmia   r4, {r5 - r7}                   @ Save XXX pc, cpsr, old_r0
887                 mov     r0, sp
888                 and     r2, r6, #31                     @ int mode
889                 b       bad_mode
890
891 /*
892  * SVC mode handlers
893  */
894                 .align  5
895 __dabt_svc:     sub     sp, sp, #S_FRAME_SIZE
896                 stmia   sp, {r0 - r12}                  @ save r0 - r12
897                 ldr     r2, .LCabt
898                 add     r0, sp, #S_FRAME_SIZE
899                 ldmia   r2, {r2 - r4}                   @ get pc, cpsr
900                 add     r5, sp, #S_SP
901                 mov     r1, lr
902                 stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
903                 mrs     r9, cpsr                        @ Enable interrupts if they were
904                 tst     r3, #PSR_I_BIT
905                 biceq   r9, r9, #PSR_I_BIT              @ previously
906 /*
907  * This routine must not corrupt r9
908  */
909 #ifdef MULTI_ABORT
910                 ldr     r4, .LCprocfns                  @ pass r2, r3 to
911                 mov     lr, pc                          @ processor code
912                 ldr     pc, [r4]                        @ call processor specific code
913 #else
914                 bl      CPU_ABORT_HANDLER
915 #endif
916                 msr     cpsr_c, r9
917                 mov     r2, sp
918                 bl      do_DataAbort
919                 disable_irq r0
920                 ldr     r0, [sp, #S_PSR]
921                 msr     spsr, r0
922                 ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
923
924                 .align  5
925 __irq_svc:      sub     sp, sp, #S_FRAME_SIZE
926                 stmia   sp, {r0 - r12}                  @ save r0 - r12
927                 ldr     r7, .LCirq
928                 add     r5, sp, #S_FRAME_SIZE
929                 ldmia   r7, {r7 - r9}
930                 add     r4, sp, #S_SP
931                 mov     r6, lr
932                 stmia   r4, {r5, r6, r7, r8, r9}        @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
933 #ifdef CONFIG_PREEMPT
934                 get_thread_info r8
935                 ldr     r9, [r8, #TI_PREEMPT]           @ get preempt count
936                 add     r7, r9, #1                      @ increment it
937                 str     r7, [r8, #TI_PREEMPT]
938 #endif
939 1:              get_irqnr_and_base r0, r6, r5, lr
940                 movne   r1, sp
941                 @
942                 @ routine called with r0 = irq number, r1 = struct pt_regs *
943                 @
944                 adrsvc  ne, lr, 1b
945                 bne     asm_do_IRQ
946 #ifdef CONFIG_PREEMPT
947                 ldr     r0, [r8, #TI_FLAGS]             @ get flags
948                 tst     r0, #_TIF_NEED_RESCHED
949                 blne    svc_preempt
950 preempt_return:
951                 ldr     r0, [r8, #TI_PREEMPT]           @ read preempt value
952                 teq     r0, r7
953                 str     r9, [r8, #TI_PREEMPT]           @ restore preempt count
954                 strne   r0, [r0, -r0]                   @ bug()
955 #endif
956                 ldr     r0, [sp, #S_PSR]                @ irqs are already disabled
957                 msr     spsr, r0
958                 ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
959
960                 .ltorg
961
962 #ifdef CONFIG_PREEMPT
963 svc_preempt:    teq     r9, #0                          @ was preempt count = 0
964                 ldreq   r6, .LCirq_stat
965                 movne   pc, lr                          @ no
966                 ldr     r0, [r6, #4]                    @ local_irq_count
967                 ldr     r1, [r6, #8]                    @ local_bh_count
968                 adds    r0, r0, r1
969                 movne   pc, lr
970                 mov     r7, #PREEMPT_ACTIVE
971                 str     r7, [r8, #TI_PREEMPT]           @ set PREEMPT_ACTIVE
972 1:              enable_irq r2                           @ enable IRQs
973                 bl      schedule
974                 disable_irq r0                          @ disable IRQs
975                 ldr     r0, [r8, #TI_FLAGS]             @ get new tasks TI_FLAGS
976                 tst     r0, #_TIF_NEED_RESCHED
977                 beq     preempt_return                  @ go again
978                 b       1b
979 #endif
980
981                 .align  5
982 __und_svc:      sub     sp, sp, #S_FRAME_SIZE
983                 stmia   sp, {r0 - r12}                  @ save r0 - r12
984                 ldr     r3, .LCund
985                 mov     r4, lr
986                 ldmia   r3, {r5 - r7}
987                 add     r3, sp, #S_FRAME_SIZE
988                 add     r2, sp, #S_SP
989                 stmia   r2, {r3 - r7}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
990
991                 ldr     r0, [r5, #-4]                   @ r0 = instruction
992                 adrsvc  al, r9, 1f                      @ r9 = normal FP return
993                 bl      call_fpe                        @ lr = undefined instr return
994
995                 mov     r0, sp                          @ struct pt_regs *regs
996                 bl      do_undefinstr
997
998 1:              disable_irq r0
999                 ldr     lr, [sp, #S_PSR]                @ Get SVC cpsr
1000                 msr     spsr, lr
1001                 ldmia   sp, {r0 - pc}^                  @ Restore SVC registers
1002
1003                 .align  5
1004 __pabt_svc:     sub     sp, sp, #S_FRAME_SIZE
1005                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1006                 ldr     r2, .LCabt
1007                 add     r0, sp, #S_FRAME_SIZE
1008                 ldmia   r2, {r2 - r4}                   @ get pc, cpsr
1009                 add     r5, sp, #S_SP
1010                 mov     r1, lr
1011                 stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1012                 mrs     r9, cpsr                        @ Enable interrupts if they were
1013                 tst     r3, #PSR_I_BIT
1014                 biceq   r9, r9, #PSR_I_BIT              @ previously
1015                 msr     cpsr_c, r9
1016                 mov     r0, r2                          @ address (pc)
1017                 mov     r1, sp                          @ regs
1018                 bl      do_PrefetchAbort                @ call abort handler
1019                 disable_irq r0
1020                 ldr     r0, [sp, #S_PSR]
1021                 msr     spsr, r0
1022                 ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
1023
1024                 .align  5
1025 .LCirq:         .word   __temp_irq
1026 .LCund:         .word   __temp_und
1027 .LCabt:         .word   __temp_abt
1028 #ifdef MULTI_ABORT
1029 .LCprocfns:     .word   processor
1030 #endif
1031 .LCfp:          .word   fp_enter
1032 #ifdef CONFIG_PREEMPT
1033 .LCirq_stat:    .word   irq_stat
1034 #endif
1035
1036                 irq_prio_table
1037
1038 /*
1039  * User mode handlers
1040  */
1041                 .align  5
1042 __dabt_usr:     sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
1043                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1044                 ldr     r7, .LCabt
1045                 add     r5, sp, #S_PC
1046                 ldmia   r7, {r2 - r4}                   @ Get USR pc, cpsr
1047                 stmia   r5, {r2 - r4}                   @ Save USR pc, cpsr, old_r0
1048                 stmdb   r5, {sp, lr}^
1049                 alignment_trap r7, r7, __temp_abt
1050                 zero_fp
1051 #ifdef MULTI_ABORT
1052                 ldr     r4, .LCprocfns                  @ pass r2, r3 to
1053                 mov     lr, pc                          @ processor code
1054                 ldr     pc, [r4]                        @ call processor specific code
1055 #else
1056                 bl      CPU_ABORT_HANDLER
1057 #endif
1058                 enable_irq r2                           @ Enable interrupts
1059                 mov     r2, sp
1060                 adrsvc  al, lr, ret_from_exception
1061                 b       do_DataAbort
1062
1063                 .align  5
1064 __irq_usr:      sub     sp, sp, #S_FRAME_SIZE
1065                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1066                 ldr     r4, .LCirq
1067                 add     r8, sp, #S_PC
1068                 ldmia   r4, {r5 - r7}                   @ get saved PC, SPSR
1069                 stmia   r8, {r5 - r7}                   @ save pc, psr, old_r0
1070                 stmdb   r8, {sp, lr}^
1071                 alignment_trap r4, r7, __temp_irq
1072                 zero_fp
1073 #ifdef CONFIG_PREEMPT
1074                 get_thread_info r8
1075                 ldr     r9, [r8, #TI_PREEMPT]           @ get preempt count
1076                 add     r7, r9, #1                      @ increment it
1077                 str     r7, [r8, #TI_PREEMPT]
1078 #endif
1079 1:              get_irqnr_and_base r0, r6, r5, lr
1080                 movne   r1, sp
1081                 adrsvc  ne, lr, 1b
1082                 @
1083                 @ routine called with r0 = irq number, r1 = struct pt_regs *
1084                 @
1085                 bne     asm_do_IRQ
1086 #ifdef CONFIG_PREEMPT
1087                 ldr     r0, [r8, #TI_PREEMPT]
1088                 teq     r0, r7
1089                 str     r9, [r8, #TI_PREEMPT]
1090                 strne   r0, [r0, -r0]
1091                 mov     tsk, r8
1092 #else
1093                 get_thread_info tsk
1094 #endif
1095                 mov     why, #0
1096                 b       ret_to_user
1097
1098                 .ltorg
1099
1100                 .align  5
1101 __und_usr:      sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
1102                 stmia   sp, {r0 - r12}                  @ Save r0 - r12
1103                 ldr     r4, .LCund
1104                 add     r8, sp, #S_PC
1105                 ldmia   r4, {r5 - r7}
1106                 stmia   r8, {r5 - r7}                   @ Save USR pc, cpsr, old_r0
1107                 stmdb   r8, {sp, lr}^                   @ Save user sp, lr
1108                 alignment_trap r4, r7, __temp_und
1109                 zero_fp
1110                 tst     r6, #PSR_T_BIT                  @ Thumb mode?
1111                 bne     fpundefinstr                    @ ignore FP
1112                 sub     r4, r5, #4
1113 1:              ldrt    r0, [r4]                        @ r0  = instruction
1114                 adrsvc  al, r9, ret_from_exception      @ r9  = normal FP return
1115                 adrsvc  al, lr, fpundefinstr            @ lr  = undefined instr return
1116
1117 /*
1118  * The out of line fixup for the ldrt above.
1119  */
1120                 .section .fixup, "ax"
1121 2:              mov     pc, r9
1122                 .previous
1123                 .section __ex_table,"a"
1124                 .long   1b, 2b
1125                 .previous
1126
1127 /*
1128  * r0 = instruction.
1129  *
1130  * Check whether the instruction is a co-processor instruction.
1131  * If yes, we need to call the relevant co-processor handler.
1132  *
1133  * Note that we don't do a full check here for the co-processor
1134  * instructions; all instructions with bit 27 set are well
1135  * defined.  The only instructions that should fault are the
1136  * co-processor instructions.  However, we have to watch out
1137  * for the ARM6/ARM7 SWI bug.
1138  *
1139  * Emulators may wish to make use of the following registers:
1140  *  r0  - instruction opcode.
1141  *  r10 - this threads thread_info structure.
1142  */
1143 call_fpe:       enable_irq r10                          @ Enable interrupts
1144                 tst     r0, #0x08000000                 @ only CDP/CPRT/LDC/STC have bit 27
1145 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
1146                 and     r8, r0, #0x0f000000             @ mask out op-code bits
1147                 teqne   r8, #0x0f000000                 @ SWI (ARM6/7 bug)?
1148 #endif
1149                 moveq   pc, lr
1150                 get_thread_info r10                     @ get current thread
1151                 and     r8, r0, #0x00000f00             @ mask out CP number
1152                 mov     r7, #1
1153                 add     r6, r10, #TI_USED_CP
1154                 strb    r7, [r6, r8, lsr #8]            @ set appropriate used_cp[]
1155                 add     pc, pc, r8, lsr #6
1156                 mov     r0, r0
1157
1158                 mov     pc, lr                          @ CP#0
1159                 b       do_fpe                          @ CP#1 (FPE)
1160                 b       do_fpe                          @ CP#2 (FPE)
1161                 mov     pc, lr                          @ CP#3
1162                 mov     pc, lr                          @ CP#4
1163                 mov     pc, lr                          @ CP#5
1164                 mov     pc, lr                          @ CP#6
1165                 mov     pc, lr                          @ CP#7
1166                 mov     pc, lr                          @ CP#8
1167                 mov     pc, lr                          @ CP#9
1168                 mov     pc, lr                          @ CP#10 (VFP)
1169                 mov     pc, lr                          @ CP#11 (VFP)
1170                 mov     pc, lr                          @ CP#12
1171                 mov     pc, lr                          @ CP#13
1172                 mov     pc, lr                          @ CP#14 (Debug)
1173                 mov     pc, lr                          @ CP#15 (Control)
1174
1175 do_fpe:         ldr     r4, .LCfp
1176                 add     r10, r10, #TI_FPSTATE           @ r10 = workspace
1177                 ldr     pc, [r4]                        @ Call FP module USR entry point
1178
1179 /*
1180  * The FP module is called with these registers set:
1181  *  r0  = instruction
1182  *  r5  = PC
1183  *  r9  = normal "successful" return address
1184  *  r10 = FP workspace
1185  *  lr  = unrecognised FP instruction return address
1186  */
1187
1188                 .data
1189 ENTRY(fp_enter)
1190                 .word   fpundefinstr
1191                 .text
1192
1193 fpundefinstr:   mov     r0, sp
1194                 adrsvc  al, lr, ret_from_exception
1195                 b       do_undefinstr
1196
1197                 .align  5
1198 __pabt_usr:     sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
1199                 stmia   sp, {r0 - r12}                  @ Save r0 - r12
1200                 ldr     r4, .LCabt
1201                 add     r8, sp, #S_PC
1202                 ldmia   r4, {r5 - r7}                   @ Get USR pc, cpsr
1203                 stmia   r8, {r5 - r7}                   @ Save USR pc, cpsr, old_r0
1204                 stmdb   r8, {sp, lr}^                   @ Save sp_usr lr_usr
1205                 alignment_trap r4, r7, __temp_abt
1206                 zero_fp
1207                 enable_irq r0                           @ Enable interrupts
1208                 mov     r0, r5                          @ address (pc)
1209                 mov     r1, sp                          @ regs
1210                 bl      do_PrefetchAbort                @ call abort handler
1211                 /* fall through */
1212 /*
1213  * This is the return code to user mode for abort handlers
1214  */
1215 ENTRY(ret_from_exception)
1216                 get_thread_info tsk
1217                 mov     why, #0
1218                 b       ret_to_user
1219
1220 /*
1221  * Register switch for ARMv3 and ARMv4 processors
1222  * r0 = previous thread_info, r1 = next thread_info
1223  * previous and next are guaranteed not to be the same.
1224  */
1225 ENTRY(__switch_to)
1226                 add     ip, r1, #TI_CPU_SAVE
1227                 ldr     r3, [r2, #TI_CPU_DOMAIN]!
1228                 stmia   ip, {r4 - sl, fp, sp, lr}       @ Store most regs on stack
1229                 mcr     p15, 0, r3, c3, c0, 0           @ Set domain register
1230                 ldmib   r2, {r4 - sl, fp, sp, pc}       @ Load all regs saved previously
1231
1232                 __INIT
1233 /*
1234  * Vector stubs.  NOTE that we only align 'vector_IRQ' to a cache line boundary,
1235  * and we rely on each stub being exactly 48 (1.5 cache lines) in size.  This
1236  * means that we only ever load two cache lines for this code, or one if we're
1237  * lucky.  We also copy this code to 0x200 so that we can use branches in the
1238  * vectors, rather than ldr's.
1239  */
1240                 .align  5
1241 __stubs_start:
1242 /*
1243  * Interrupt dispatcher
1244  * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1245  */
1246 vector_IRQ:     @
1247                 @ save mode specific registers
1248                 @
1249                 ldr     r13, .LCsirq
1250                 sub     lr, lr, #4
1251                 str     lr, [r13]                       @ save lr_IRQ
1252                 mrs     lr, spsr
1253                 str     lr, [r13, #4]                   @ save spsr_IRQ
1254                 @
1255                 @ now branch to the relevant MODE handling routine
1256                 @
1257                 mrs     r13, cpsr
1258                 bic     r13, r13, #MODE_MASK
1259                 orr     r13, r13, #MODE_SVC
1260                 msr     spsr, r13                       @ switch to SVC_32 mode
1261
1262                 and     lr, lr, #15
1263                 ldr     lr, [pc, lr, lsl #2]
1264                 movs    pc, lr                          @ Changes mode and branches
1265
1266 .LCtab_irq:     .word   __irq_usr                       @  0  (USR_26 / USR_32)
1267                 .word   __irq_invalid                   @  1  (FIQ_26 / FIQ_32)
1268                 .word   __irq_invalid                   @  2  (IRQ_26 / IRQ_32)
1269                 .word   __irq_svc                       @  3  (SVC_26 / SVC_32)
1270                 .word   __irq_invalid                   @  4
1271                 .word   __irq_invalid                   @  5
1272                 .word   __irq_invalid                   @  6
1273                 .word   __irq_invalid                   @  7
1274                 .word   __irq_invalid                   @  8
1275                 .word   __irq_invalid                   @  9
1276                 .word   __irq_invalid                   @  a
1277                 .word   __irq_invalid                   @  b
1278                 .word   __irq_invalid                   @  c
1279                 .word   __irq_invalid                   @  d
1280                 .word   __irq_invalid                   @  e
1281                 .word   __irq_invalid                   @  f
1282
1283                 .align  5
1284
1285 /*
1286  * Data abort dispatcher - dispatches it to the correct handler for the processor mode
1287  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1288  */
1289 vector_data:    @
1290                 @ save mode specific registers
1291                 @
1292                 ldr     r13, .LCsabt
1293                 sub     lr, lr, #8
1294                 str     lr, [r13]
1295                 mrs     lr, spsr
1296                 str     lr, [r13, #4]
1297                 @
1298                 @ now branch to the relevant MODE handling routine
1299                 @
1300                 mrs     r13, cpsr
1301                 bic     r13, r13, #MODE_MASK
1302                 orr     r13, r13, #MODE_SVC
1303                 msr     spsr, r13                       @ switch to SVC_32 mode
1304
1305                 and     lr, lr, #15
1306                 ldr     lr, [pc, lr, lsl #2]
1307                 movs    pc, lr                          @ Changes mode and branches
1308
1309 .LCtab_dabt:    .word   __dabt_usr                      @  0  (USR_26 / USR_32)
1310                 .word   __dabt_invalid                  @  1  (FIQ_26 / FIQ_32)
1311                 .word   __dabt_invalid                  @  2  (IRQ_26 / IRQ_32)
1312                 .word   __dabt_svc                      @  3  (SVC_26 / SVC_32)
1313                 .word   __dabt_invalid                  @  4
1314                 .word   __dabt_invalid                  @  5
1315                 .word   __dabt_invalid                  @  6
1316                 .word   __dabt_invalid                  @  7
1317                 .word   __dabt_invalid                  @  8
1318                 .word   __dabt_invalid                  @  9
1319                 .word   __dabt_invalid                  @  a
1320                 .word   __dabt_invalid                  @  b
1321                 .word   __dabt_invalid                  @  c
1322                 .word   __dabt_invalid                  @  d
1323                 .word   __dabt_invalid                  @  e
1324                 .word   __dabt_invalid                  @  f
1325
1326                 .align  5
1327
1328 /*
1329  * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode
1330  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1331  */
1332 vector_prefetch:
1333                 @
1334                 @ save mode specific registers
1335                 @
1336                 ldr     r13, .LCsabt
1337                 sub     lr, lr, #4
1338                 str     lr, [r13]                       @ save lr_ABT
1339                 mrs     lr, spsr
1340                 str     lr, [r13, #4]                   @ save spsr_ABT
1341                 @
1342                 @ now branch to the relevant MODE handling routine
1343                 @
1344                 mrs     r13, cpsr
1345                 bic     r13, r13, #MODE_MASK
1346                 orr     r13, r13, #MODE_SVC
1347                 msr     spsr, r13                       @ switch to SVC_32 mode
1348
1349                 ands    lr, lr, #15
1350                 ldr     lr, [pc, lr, lsl #2]
1351                 movs    pc, lr
1352
1353 .LCtab_pabt:    .word   __pabt_usr                      @  0 (USR_26 / USR_32)
1354                 .word   __pabt_invalid                  @  1 (FIQ_26 / FIQ_32)
1355                 .word   __pabt_invalid                  @  2 (IRQ_26 / IRQ_32)
1356                 .word   __pabt_svc                      @  3 (SVC_26 / SVC_32)
1357                 .word   __pabt_invalid                  @  4
1358                 .word   __pabt_invalid                  @  5
1359                 .word   __pabt_invalid                  @  6
1360                 .word   __pabt_invalid                  @  7
1361                 .word   __pabt_invalid                  @  8
1362                 .word   __pabt_invalid                  @  9
1363                 .word   __pabt_invalid                  @  a
1364                 .word   __pabt_invalid                  @  b
1365                 .word   __pabt_invalid                  @  c
1366                 .word   __pabt_invalid                  @  d
1367                 .word   __pabt_invalid                  @  e
1368                 .word   __pabt_invalid                  @  f
1369
1370                 .align  5
1371
1372 /*
1373  * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode
1374  * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1375  */
1376 vector_undefinstr:
1377                 @
1378                 @ save mode specific registers
1379                 @
1380                 ldr     r13, .LCsund
1381                 str     lr, [r13]                       @ save lr_UND
1382                 mrs     lr, spsr
1383                 str     lr, [r13, #4]                   @ save spsr_UND
1384                 @
1385                 @ now branch to the relevant MODE handling routine
1386                 @
1387                 mrs     r13, cpsr
1388                 bic     r13, r13, #MODE_MASK
1389                 orr     r13, r13, #MODE_SVC
1390                 msr     spsr, r13                       @ switch to SVC_32 mode
1391
1392                 and     lr, lr, #15
1393                 ldr     lr, [pc, lr, lsl #2]
1394                 movs    pc, lr                          @ Changes mode and branches
1395
1396 .LCtab_und:     .word   __und_usr                       @  0 (USR_26 / USR_32)
1397                 .word   __und_invalid                   @  1 (FIQ_26 / FIQ_32)
1398                 .word   __und_invalid                   @  2 (IRQ_26 / IRQ_32)
1399                 .word   __und_svc                       @  3 (SVC_26 / SVC_32)
1400                 .word   __und_invalid                   @  4
1401                 .word   __und_invalid                   @  5
1402                 .word   __und_invalid                   @  6
1403                 .word   __und_invalid                   @  7
1404                 .word   __und_invalid                   @  8
1405                 .word   __und_invalid                   @  9
1406                 .word   __und_invalid                   @  a
1407                 .word   __und_invalid                   @  b
1408                 .word   __und_invalid                   @  c
1409                 .word   __und_invalid                   @  d
1410                 .word   __und_invalid                   @  e
1411                 .word   __und_invalid                   @  f
1412
1413                 .align  5
1414
1415 /*=============================================================================
1416  * Undefined FIQs
1417  *-----------------------------------------------------------------------------
1418  * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
1419  * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
1420  * Basically to switch modes, we *HAVE* to clobber one register...  brain
1421  * damage alert!  I don't think that we can execute any code in here in any
1422  * other mode than FIQ...  Ok you can switch to another mode, but you can't
1423  * get out of that mode without clobbering one register.
1424  */
1425 vector_FIQ:     disable_fiq
1426                 subs    pc, lr, #4
1427
1428 /*=============================================================================
1429  * Address exception handler
1430  *-----------------------------------------------------------------------------
1431  * These aren't too critical.
1432  * (they're not supposed to happen, and won't happen in 32-bit data mode).
1433  */
1434
1435 vector_addrexcptn:
1436                 b       vector_addrexcptn
1437
1438 /*
1439  * We group all the following data together to optimise
1440  * for CPUs with separate I & D caches.
1441  */
1442                 .align  5
1443
1444 .LCvswi:        .word   vector_swi
1445
1446 .LCsirq:        .word   __temp_irq
1447 .LCsund:        .word   __temp_und
1448 .LCsabt:        .word   __temp_abt
1449
1450 __stubs_end:
1451
1452                 .equ    __real_stubs_start, .LCvectors + 0x200
1453
1454 .LCvectors:     swi     SYS_ERROR0
1455                 b       __real_stubs_start + (vector_undefinstr - __stubs_start)
1456                 ldr     pc, __real_stubs_start + (.LCvswi - __stubs_start)
1457                 b       __real_stubs_start + (vector_prefetch - __stubs_start)
1458                 b       __real_stubs_start + (vector_data - __stubs_start)
1459                 b       __real_stubs_start + (vector_addrexcptn - __stubs_start)
1460                 b       __real_stubs_start + (vector_IRQ - __stubs_start)
1461                 b       __real_stubs_start + (vector_FIQ - __stubs_start)
1462
1463 ENTRY(__trap_init)
1464                 stmfd   sp!, {r4 - r6, lr}
1465
1466                 adr     r1, .LCvectors                  @ set up the vectors
1467                 ldmia   r1, {r1, r2, r3, r4, r5, r6, ip, lr}
1468                 stmia   r0, {r1, r2, r3, r4, r5, r6, ip, lr}
1469
1470                 add     r2, r0, #0x200
1471                 adr     r0, __stubs_start               @ copy stubs to 0x200
1472                 adr     r1, __stubs_end
1473 1:              ldr     r3, [r0], #4
1474                 str     r3, [r2], #4
1475                 cmp     r0, r1
1476                 blt     1b
1477                 LOADREGS(fd, sp!, {r4 - r6, pc})
1478
1479                 .data
1480
1481 /*
1482  * Do not reorder these, and do not insert extra data between...
1483  */
1484
1485 __temp_irq:     .word   0                               @ saved lr_irq
1486                 .word   0                               @ saved spsr_irq
1487                 .word   -1                              @ old_r0
1488 __temp_und:     .word   0                               @ Saved lr_und
1489                 .word   0                               @ Saved spsr_und
1490                 .word   -1                              @ old_r0
1491 __temp_abt:     .word   0                               @ Saved lr_abt
1492                 .word   0                               @ Saved spsr_abt
1493                 .word   -1                              @ old_r0
1494
1495                 .globl  cr_alignment
1496                 .globl  cr_no_alignment
1497 cr_alignment:
1498                 .space  4
1499 cr_no_alignment:
1500                 .space  4