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