patch-2_6_7-vs1_9_1_12
[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 #ifdef CONFIG_PXA27x
627                 mrc     p6, 0, \irqstat, c0, c0, 0              @ ICIP
628                 mrc     p6, 0, \irqnr, c1, c0, 0                @ ICMR
629 #else
630                 mov     \base, #io_p2v(0x40000000)      @ IIR Ctl = 0x40d00000
631                 add     \base, \base, #0x00d00000
632                 ldr     \irqstat, [\base, #0]           @ ICIP
633                 ldr     \irqnr, [\base, #4]             @ ICMR
634 #endif
635                 ands    \irqnr, \irqstat, \irqnr
636                 beq     1001f
637                 rsb     \irqstat, \irqnr, #0
638                 and     \irqstat, \irqstat, \irqnr
639                 clz     \irqnr, \irqstat
640                 rsb     \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
641 1001:
642                 .endm
643
644                 .macro  irq_prio_table
645                 .endm
646
647 #elif defined (CONFIG_ARCH_IXP4XX)
648
649                 .macro  disable_fiq
650                 .endm
651                 
652                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
653                 ldr     \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
654                 ldr     \irqstat, [\irqstat]            @ get interrupts
655                 cmp     \irqstat, #0
656                 beq     1002f
657                 clz     \irqnr, \irqstat
658                 mov     \base, #31
659                 subs    \irqnr, \base, \irqnr
660                 
661 /*
662 1001:           tst     \irqstat, #1
663                 addeq   \irqnr, \irqnr, #1
664                 moveq   \irqstat, \irqstat, lsr #1
665                 tsteq   \irqnr, #32
666                 beq     1001b
667                 teq     \irqnr, #32
668 */
669 1002:
670                 .endm
671
672                 .macro  irq_prio_table
673                 .endm
674
675 #elif defined(CONFIG_ARCH_OMAP)
676
677                 .macro  disable_fiq
678                 .endm
679
680                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
681                 ldr     \base, =IO_ADDRESS(OMAP_IH1_BASE)
682                 ldr     \irqnr, [\base, #IRQ_ITR_REG_OFFSET]
683                 ldr     \tmp, [\base, #IRQ_MIR_REG_OFFSET]
684                 mov     \irqstat, #0xffffffff
685                 bic     \tmp, \irqstat, \tmp
686                 tst     \irqnr, \tmp
687                 beq     1510f
688
689                 ldr     \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET]
690                 cmp     \irqnr, #0
691                 ldreq   \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
692                 cmpeq   \irqnr, #INT_IH2_IRQ
693                 ldreq   \base, =IO_ADDRESS(OMAP_IH2_BASE)
694                 ldreq   \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
695                 addeqs  \irqnr, \irqnr, #32
696 1510:
697                 .endm
698
699                 .macro  irq_prio_table
700                 .endm
701
702 #elif defined(CONFIG_ARCH_S3C2410)
703                 /* S3C2410X IRQ Handler, <ben@simtec.co.uk> */
704
705                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
706
707 30000:
708                 mov     \tmp, #S3C2410_VA_IRQ
709                 ldr     \irqnr, [ \tmp, #0x14 ]         @ get irq no
710                 teq     \irqnr, #4
711                 teqne   \irqnr, #5
712                 beq     1002f                           @ external irq reg
713                 teq     \irqnr, #16
714                 beq     1003f                           @ lcd controller
715
716                 @ debug check to see if interrupt reported is the same
717                 @ as the offset....
718
719                 teq     \irqnr, #0
720                 beq     20002f
721                 ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
722                 mov     \irqstat, \irqstat, lsr \irqnr
723                 tst     \irqstat, #1
724                 bne     20002f
725
726 #if 1
727                 stmfd   r13!, { r0 - r4 , r14 }
728                 ldr     r1,     [ \tmp, #0x14 ]         @ intoffset
729                 ldr     r2,     [ \tmp, #0x10 ]         @ INTPND
730                 ldr     r3,     [ \tmp, #0x00 ]         @ SRCPND
731                 adr     r0, 20003f
732                 bl      printk
733                 b       20004f
734 #endif
735 20003:
736                 .ascii  "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
737                 .byte   0
738                 .align  4
739 20004:
740                 mov     r1, #1
741                 mov     \tmp, #S3C2410_VA_IRQ
742                 ldmfd   r13!, { r0 - r4 , r14 }
743
744                 @ try working out interript number for ourselves
745                 mov     \irqnr, #0
746                 ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
747 10021:
748                 movs    \irqstat, \irqstat, lsr#1
749                 bcs     30000b          @ try and re-start the proccess
750                 add     \irqnr, \irqnr, #1
751                 cmp     \irqnr, #32
752                 ble     10021b
753
754                 @ found no interrupt, set Z flag and leave
755                 movs    \irqnr, #0
756                 b       1001f
757
758 20005:
759 20002:          @ exit
760                 @ we base the s3c2410x interrupts at 16 and above to allow
761                 @ isa peripherals to have their standard interrupts, also
762                 @ ensure that Z flag is un-set on exit
763
764                 @ note, we cannot be sure if we get IRQ_EINT0 (0) that
765                 @ there is simply no interrupt pending, so in all other
766                 @ cases we jump to say we have found something, otherwise
767                 @ we check to see if the interrupt really is assrted
768                 adds    \irqnr, \irqnr, #IRQ_EINT0
769                 teq     \irqnr, #IRQ_EINT0
770                 bne     1001f                           @ exit
771                 ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
772                 teq     \irqstat, #0
773                 moveq   \irqnr, #0
774                 b       1001f
775
776                 @ we get here from no main or external interrupts pending
777 1002:
778                 add     \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
779                 ldr     \irqstat, [ \tmp, # 0xa8 ]      @ EXTINTPEND
780                 ldr     \irqnr, [ \tmp, # 0xa4 ]        @ EXTINTMASK
781
782                 bic     \irqstat, \irqstat, \irqnr      @ clear masked irqs
783
784                 mov     \irqnr, #IRQ_EINT4              @ start extint nos
785                 mov     \irqstat, \irqstat, lsr#4       @ ignore bottom 4 bits
786 10021:
787                 movs    \irqstat, \irqstat, lsr#1
788                 bcs     1004f
789                 add     \irqnr, \irqnr, #1
790                 cmp     \irqnr, #IRQ_EINT23
791                 ble     10021b
792
793                 @ found no interrupt, set Z flag and leave
794                 movs    \irqnr, #0
795                 b       1001f
796
797 1003:
798                 @ lcd interrupt has been asserted...
799                 add     \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ
800                 ldr     \irqstat, [ \tmp, # 0x54 ]      @ lcd int pending
801
802                 tst     \irqstat, #2
803                 movne   \irqnr, #IRQ_LCD_FRAME
804                 tst     \irqstat, #1
805                 movne   \irqnr, #IRQ_LCD_FIFO
806
807                 @ fall through to exit with flags updated
808
809 1004:           @ ensure Z flag clear in case our MOVS shifted out the last bit
810                 teq     \irqnr, #0
811 1001:
812                 @ exit irq routine
813                 .endm
814
815
816                 /* currently don't need an disable_fiq macro */
817
818                 .macro  disable_fiq
819                 .endm
820
821                 /* we don't have an irq priority table */
822                 .macro irq_prio_table
823                 .endm
824
825 #elif defined(CONFIG_ARCH_LH7A400)
826
827 # if defined (CONFIG_ARCH_LH7A404)
828 #  error "LH7A400 and LH7A404 are mutually exclusive"
829 # endif
830                 .macro  disable_fiq
831                 .endm
832
833                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
834                 mov     \irqnr, #0
835                 mov     \base, #io_p2v(0x80000000)      @ APB registers
836                 ldr     \irqstat, [\base, #0x500]       @ PIC INTSR
837
838 1001:           movs    \irqstat, \irqstat, lsr #1      @ Shift into carry
839                 bcs     1008f                           @ Bit set; irq found
840                 add     \irqnr, \irqnr, #1
841                 bne     1001b                           @ Until no bits
842                 b       1009f                           @ Nothing?  Hmm.
843 1008:           movs    \irqstat, #1                    @ Force !Z
844 1009:
845                .endm
846
847                .macro  irq_prio_table
848                .endm
849
850 #elif defined(CONFIG_ARCH_LH7A404)
851
852                 .macro  disable_fiq
853                 .endm
854
855                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
856                 mov     \irqnr, #0                      @ VIC1 irq base
857                 mov     \base, #io_p2v(0x80000000)      @ APB registers
858                 add     \base, \base, #0x8000
859                 ldr     \tmp, [\base, #0x0030]          @ VIC1_VECTADDR
860                 tst     \tmp, #VA_VECTORED              @ Direct vectored
861                 bne     1002f
862                 tst     \tmp, #VA_VIC1DEFAULT           @ Default vectored VIC1
863                 ldrne   \irqstat, [\base, #0]           @ VIC1_IRQSTATUS
864                 bne     1001f
865                 add     \base, \base, #(0xa000 - 0x8000)
866                 ldr     \tmp, [\base, #0x0030]          @ VIC2_VECTADDR
867                 tst     \tmp, #VA_VECTORED              @ Direct vectored
868                 bne     1002f
869                 ldr     \irqstat, [\base, #0]           @ VIC2_IRQSTATUS
870                 mov     \irqnr, #32                     @ VIC2 irq base
871
872 1001:           movs    \irqstat, \irqstat, lsr #1      @ Shift into carry
873                 bcs     1008f                           @ Bit set; irq found
874                 add     \irqnr, \irqnr, #1
875                 bne     1001b                           @ Until no bits
876                 b       1009f                           @ Nothing?  Hmm.
877 1002:           and     \irqnr, \tmp, #0x3f             @ Mask for valid bits
878 1008:           movs    \irqstat, #1                    @ Force !Z
879                 str     \tmp, [\base, #0x0030]          @ Clear vector
880 1009:
881                .endm
882
883                .macro  irq_prio_table
884                .endm
885
886 #else
887 #error Unknown architecture
888 #endif
889
890 /*
891  * Invalid mode handlers
892  */
893 __pabt_invalid: sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
894                 stmia   sp, {r0 - lr}                   @ Save XXX r0 - lr
895                 ldr     r4, .LCabt
896                 mov     r1, #BAD_PREFETCH
897                 b       1f
898
899 __dabt_invalid: sub     sp, sp, #S_FRAME_SIZE
900                 stmia   sp, {r0 - lr}                   @ Save SVC r0 - lr [lr *should* be intact]
901                 ldr     r4, .LCabt
902                 mov     r1, #BAD_DATA
903                 b       1f
904
905 __irq_invalid:  sub     sp, sp, #S_FRAME_SIZE           @ Allocate space on stack for frame
906                 stmfd   sp, {r0 - lr}                   @ Save r0 - lr
907                 ldr     r4, .LCirq
908                 mov     r1, #BAD_IRQ
909                 b       1f
910
911 __und_invalid:  sub     sp, sp, #S_FRAME_SIZE
912                 stmia   sp, {r0 - lr}
913                 ldr     r4, .LCund
914                 mov     r1, #BAD_UNDEFINSTR             @ int reason
915
916 1:              zero_fp
917                 ldmia   r4, {r5 - r7}                   @ Get XXX pc, cpsr, old_r0
918                 add     r4, sp, #S_PC
919                 stmia   r4, {r5 - r7}                   @ Save XXX pc, cpsr, old_r0
920                 mov     r0, sp
921                 and     r2, r6, #31                     @ int mode
922                 b       bad_mode
923
924 /*
925  * SVC mode handlers
926  */
927                 .align  5
928 __dabt_svc:     sub     sp, sp, #S_FRAME_SIZE
929                 stmia   sp, {r0 - r12}                  @ save r0 - r12
930                 ldr     r2, .LCabt
931                 add     r0, sp, #S_FRAME_SIZE
932                 ldmia   r2, {r2 - r4}                   @ get pc, cpsr
933                 add     r5, sp, #S_SP
934                 mov     r1, lr
935                 stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
936                 mrs     r9, cpsr                        @ Enable interrupts if they were
937                 tst     r3, #PSR_I_BIT
938                 biceq   r9, r9, #PSR_I_BIT              @ previously
939 /*
940  * This routine must not corrupt r9
941  */
942 #ifdef MULTI_ABORT
943                 ldr     r4, .LCprocfns                  @ pass r2, r3 to
944                 mov     lr, pc                          @ processor code
945                 ldr     pc, [r4]                        @ call processor specific code
946 #else
947                 bl      CPU_ABORT_HANDLER
948 #endif
949                 msr     cpsr_c, r9
950                 mov     r2, sp
951                 bl      do_DataAbort
952                 disable_irq r0
953                 ldr     r0, [sp, #S_PSR]
954                 msr     spsr, r0
955                 ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
956
957                 .align  5
958 __irq_svc:      sub     sp, sp, #S_FRAME_SIZE
959                 stmia   sp, {r0 - r12}                  @ save r0 - r12
960                 ldr     r7, .LCirq
961                 add     r5, sp, #S_FRAME_SIZE
962                 ldmia   r7, {r7 - r9}
963                 add     r4, sp, #S_SP
964                 mov     r6, lr
965                 stmia   r4, {r5, r6, r7, r8, r9}        @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
966 #ifdef CONFIG_PREEMPT
967                 get_thread_info r8
968                 ldr     r9, [r8, #TI_PREEMPT]           @ get preempt count
969                 add     r7, r9, #1                      @ increment it
970                 str     r7, [r8, #TI_PREEMPT]
971 #endif
972 1:              get_irqnr_and_base r0, r6, r5, lr
973                 movne   r1, sp
974                 @
975                 @ routine called with r0 = irq number, r1 = struct pt_regs *
976                 @
977                 adrsvc  ne, lr, 1b
978                 bne     asm_do_IRQ
979 #ifdef CONFIG_PREEMPT
980                 ldr     r0, [r8, #TI_FLAGS]             @ get flags
981                 tst     r0, #_TIF_NEED_RESCHED
982                 blne    svc_preempt
983 preempt_return:
984                 ldr     r0, [r8, #TI_PREEMPT]           @ read preempt value
985                 teq     r0, r7
986                 str     r9, [r8, #TI_PREEMPT]           @ restore preempt count
987                 strne   r0, [r0, -r0]                   @ bug()
988 #endif
989                 ldr     r0, [sp, #S_PSR]                @ irqs are already disabled
990                 msr     spsr, r0
991                 ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
992
993                 .ltorg
994
995 #ifdef CONFIG_PREEMPT
996 svc_preempt:    teq     r9, #0                          @ was preempt count = 0
997                 ldreq   r6, .LCirq_stat
998                 movne   pc, lr                          @ no
999                 ldr     r0, [r6, #4]                    @ local_irq_count
1000                 ldr     r1, [r6, #8]                    @ local_bh_count
1001                 adds    r0, r0, r1
1002                 movne   pc, lr
1003                 mov     r7, #PREEMPT_ACTIVE
1004                 str     r7, [r8, #TI_PREEMPT]           @ set PREEMPT_ACTIVE
1005 1:              enable_irq r2                           @ enable IRQs
1006                 bl      schedule
1007                 disable_irq r0                          @ disable IRQs
1008                 ldr     r0, [r8, #TI_FLAGS]             @ get new tasks TI_FLAGS
1009                 tst     r0, #_TIF_NEED_RESCHED
1010                 beq     preempt_return                  @ go again
1011                 b       1b
1012 #endif
1013
1014                 .align  5
1015 __und_svc:      sub     sp, sp, #S_FRAME_SIZE
1016                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1017                 ldr     r3, .LCund
1018                 mov     r4, lr
1019                 ldmia   r3, {r5 - r7}
1020                 add     r3, sp, #S_FRAME_SIZE
1021                 add     r2, sp, #S_SP
1022                 stmia   r2, {r3 - r7}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1023
1024                 ldr     r0, [r5, #-4]                   @ r0 = instruction
1025                 adrsvc  al, r9, 1f                      @ r9 = normal FP return
1026                 bl      call_fpe                        @ lr = undefined instr return
1027
1028                 mov     r0, sp                          @ struct pt_regs *regs
1029                 bl      do_undefinstr
1030
1031 1:              disable_irq r0
1032                 ldr     lr, [sp, #S_PSR]                @ Get SVC cpsr
1033                 msr     spsr, lr
1034                 ldmia   sp, {r0 - pc}^                  @ Restore SVC registers
1035
1036                 .align  5
1037 __pabt_svc:     sub     sp, sp, #S_FRAME_SIZE
1038                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1039                 ldr     r2, .LCabt
1040                 add     r0, sp, #S_FRAME_SIZE
1041                 ldmia   r2, {r2 - r4}                   @ get pc, cpsr
1042                 add     r5, sp, #S_SP
1043                 mov     r1, lr
1044                 stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1045                 mrs     r9, cpsr                        @ Enable interrupts if they were
1046                 tst     r3, #PSR_I_BIT
1047                 biceq   r9, r9, #PSR_I_BIT              @ previously
1048                 msr     cpsr_c, r9
1049                 mov     r0, r2                          @ address (pc)
1050                 mov     r1, sp                          @ regs
1051                 bl      do_PrefetchAbort                @ call abort handler
1052                 disable_irq r0
1053                 ldr     r0, [sp, #S_PSR]
1054                 msr     spsr, r0
1055                 ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
1056
1057                 .align  5
1058 .LCirq:         .word   __temp_irq
1059 .LCund:         .word   __temp_und
1060 .LCabt:         .word   __temp_abt
1061 #ifdef MULTI_ABORT
1062 .LCprocfns:     .word   processor
1063 #endif
1064 .LCfp:          .word   fp_enter
1065 #ifdef CONFIG_PREEMPT
1066 .LCirq_stat:    .word   irq_stat
1067 #endif
1068
1069                 irq_prio_table
1070
1071 /*
1072  * User mode handlers
1073  */
1074                 .align  5
1075 __dabt_usr:     sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
1076                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1077                 ldr     r7, .LCabt
1078                 add     r5, sp, #S_PC
1079                 ldmia   r7, {r2 - r4}                   @ Get USR pc, cpsr
1080                 stmia   r5, {r2 - r4}                   @ Save USR pc, cpsr, old_r0
1081                 stmdb   r5, {sp, lr}^
1082                 alignment_trap r7, r7, __temp_abt
1083                 zero_fp
1084 #ifdef MULTI_ABORT
1085                 ldr     r4, .LCprocfns                  @ pass r2, r3 to
1086                 mov     lr, pc                          @ processor code
1087                 ldr     pc, [r4]                        @ call processor specific code
1088 #else
1089                 bl      CPU_ABORT_HANDLER
1090 #endif
1091                 enable_irq r2                           @ Enable interrupts
1092                 mov     r2, sp
1093                 adrsvc  al, lr, ret_from_exception
1094                 b       do_DataAbort
1095
1096                 .align  5
1097 __irq_usr:      sub     sp, sp, #S_FRAME_SIZE
1098                 stmia   sp, {r0 - r12}                  @ save r0 - r12
1099                 ldr     r4, .LCirq
1100                 add     r8, sp, #S_PC
1101                 ldmia   r4, {r5 - r7}                   @ get saved PC, SPSR
1102                 stmia   r8, {r5 - r7}                   @ save pc, psr, old_r0
1103                 stmdb   r8, {sp, lr}^
1104                 alignment_trap r4, r7, __temp_irq
1105                 zero_fp
1106 #ifdef CONFIG_PREEMPT
1107                 get_thread_info r8
1108                 ldr     r9, [r8, #TI_PREEMPT]           @ get preempt count
1109                 add     r7, r9, #1                      @ increment it
1110                 str     r7, [r8, #TI_PREEMPT]
1111 #endif
1112 1:              get_irqnr_and_base r0, r6, r5, lr
1113                 movne   r1, sp
1114                 adrsvc  ne, lr, 1b
1115                 @
1116                 @ routine called with r0 = irq number, r1 = struct pt_regs *
1117                 @
1118                 bne     asm_do_IRQ
1119 #ifdef CONFIG_PREEMPT
1120                 ldr     r0, [r8, #TI_PREEMPT]
1121                 teq     r0, r7
1122                 str     r9, [r8, #TI_PREEMPT]
1123                 strne   r0, [r0, -r0]
1124                 mov     tsk, r8
1125 #else
1126                 get_thread_info tsk
1127 #endif
1128                 mov     why, #0
1129                 b       ret_to_user
1130
1131                 .ltorg
1132
1133                 .align  5
1134 __und_usr:      sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
1135                 stmia   sp, {r0 - r12}                  @ Save r0 - r12
1136                 ldr     r4, .LCund
1137                 add     r8, sp, #S_PC
1138                 ldmia   r4, {r5 - r7}
1139                 stmia   r8, {r5 - r7}                   @ Save USR pc, cpsr, old_r0
1140                 stmdb   r8, {sp, lr}^                   @ Save user sp, lr
1141                 alignment_trap r4, r7, __temp_und
1142                 zero_fp
1143                 tst     r6, #PSR_T_BIT                  @ Thumb mode?
1144                 bne     fpundefinstr                    @ ignore FP
1145                 sub     r4, r5, #4
1146 1:              ldrt    r0, [r4]                        @ r0  = instruction
1147                 adrsvc  al, r9, ret_from_exception      @ r9  = normal FP return
1148                 adrsvc  al, lr, fpundefinstr            @ lr  = undefined instr return
1149
1150 /*
1151  * The out of line fixup for the ldrt above.
1152  */
1153                 .section .fixup, "ax"
1154 2:              mov     pc, r9
1155                 .previous
1156                 .section __ex_table,"a"
1157                 .long   1b, 2b
1158                 .previous
1159
1160 /*
1161  * r0 = instruction.
1162  *
1163  * Check whether the instruction is a co-processor instruction.
1164  * If yes, we need to call the relevant co-processor handler.
1165  *
1166  * Note that we don't do a full check here for the co-processor
1167  * instructions; all instructions with bit 27 set are well
1168  * defined.  The only instructions that should fault are the
1169  * co-processor instructions.  However, we have to watch out
1170  * for the ARM6/ARM7 SWI bug.
1171  *
1172  * Emulators may wish to make use of the following registers:
1173  *  r0  - instruction opcode.
1174  *  r10 - this threads thread_info structure.
1175  */
1176 call_fpe:       enable_irq r10                          @ Enable interrupts
1177                 tst     r0, #0x08000000                 @ only CDP/CPRT/LDC/STC have bit 27
1178 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
1179                 and     r8, r0, #0x0f000000             @ mask out op-code bits
1180                 teqne   r8, #0x0f000000                 @ SWI (ARM6/7 bug)?
1181 #endif
1182                 moveq   pc, lr
1183                 get_thread_info r10                     @ get current thread
1184                 and     r8, r0, #0x00000f00             @ mask out CP number
1185                 mov     r7, #1
1186                 add     r6, r10, #TI_USED_CP
1187                 strb    r7, [r6, r8, lsr #8]            @ set appropriate used_cp[]
1188                 add     pc, pc, r8, lsr #6
1189                 mov     r0, r0
1190
1191                 mov     pc, lr                          @ CP#0
1192                 b       do_fpe                          @ CP#1 (FPE)
1193                 b       do_fpe                          @ CP#2 (FPE)
1194                 mov     pc, lr                          @ CP#3
1195                 mov     pc, lr                          @ CP#4
1196                 mov     pc, lr                          @ CP#5
1197                 mov     pc, lr                          @ CP#6
1198                 mov     pc, lr                          @ CP#7
1199                 mov     pc, lr                          @ CP#8
1200                 mov     pc, lr                          @ CP#9
1201                 mov     pc, lr                          @ CP#10 (VFP)
1202                 mov     pc, lr                          @ CP#11 (VFP)
1203                 mov     pc, lr                          @ CP#12
1204                 mov     pc, lr                          @ CP#13
1205                 mov     pc, lr                          @ CP#14 (Debug)
1206                 mov     pc, lr                          @ CP#15 (Control)
1207
1208 do_fpe:         ldr     r4, .LCfp
1209                 add     r10, r10, #TI_FPSTATE           @ r10 = workspace
1210                 ldr     pc, [r4]                        @ Call FP module USR entry point
1211
1212 /*
1213  * The FP module is called with these registers set:
1214  *  r0  = instruction
1215  *  r5  = PC
1216  *  r9  = normal "successful" return address
1217  *  r10 = FP workspace
1218  *  lr  = unrecognised FP instruction return address
1219  */
1220
1221                 .data
1222 ENTRY(fp_enter)
1223                 .word   fpundefinstr
1224                 .text
1225
1226 fpundefinstr:   mov     r0, sp
1227                 adrsvc  al, lr, ret_from_exception
1228                 b       do_undefinstr
1229
1230                 .align  5
1231 __pabt_usr:     sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
1232                 stmia   sp, {r0 - r12}                  @ Save r0 - r12
1233                 ldr     r4, .LCabt
1234                 add     r8, sp, #S_PC
1235                 ldmia   r4, {r5 - r7}                   @ Get USR pc, cpsr
1236                 stmia   r8, {r5 - r7}                   @ Save USR pc, cpsr, old_r0
1237                 stmdb   r8, {sp, lr}^                   @ Save sp_usr lr_usr
1238                 alignment_trap r4, r7, __temp_abt
1239                 zero_fp
1240                 enable_irq r0                           @ Enable interrupts
1241                 mov     r0, r5                          @ address (pc)
1242                 mov     r1, sp                          @ regs
1243                 bl      do_PrefetchAbort                @ call abort handler
1244                 /* fall through */
1245 /*
1246  * This is the return code to user mode for abort handlers
1247  */
1248 ENTRY(ret_from_exception)
1249                 get_thread_info tsk
1250                 mov     why, #0
1251                 b       ret_to_user
1252
1253 /*
1254  * Register switch for ARMv3 and ARMv4 processors
1255  * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
1256  * previous and next are guaranteed not to be the same.
1257  */
1258 ENTRY(__switch_to)
1259                 add     ip, r1, #TI_CPU_SAVE
1260                 ldr     r3, [r2, #TI_CPU_DOMAIN]!
1261                 stmia   ip, {r4 - sl, fp, sp, lr}       @ Store most regs on stack
1262                 mcr     p15, 0, r3, c3, c0, 0           @ Set domain register
1263                 ldmib   r2, {r4 - sl, fp, sp, pc}       @ Load all regs saved previously
1264
1265                 __INIT
1266 /*
1267  * Vector stubs.  NOTE that we only align 'vector_IRQ' to a cache line boundary,
1268  * and we rely on each stub being exactly 48 (1.5 cache lines) in size.  This
1269  * means that we only ever load two cache lines for this code, or one if we're
1270  * lucky.  We also copy this code to 0x200 so that we can use branches in the
1271  * vectors, rather than ldr's.
1272  */
1273                 .align  5
1274 __stubs_start:
1275 /*
1276  * Interrupt dispatcher
1277  * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1278  */
1279 vector_IRQ:     @
1280                 @ save mode specific registers
1281                 @
1282                 ldr     r13, .LCsirq
1283                 sub     lr, lr, #4
1284                 str     lr, [r13]                       @ save lr_IRQ
1285                 mrs     lr, spsr
1286                 str     lr, [r13, #4]                   @ save spsr_IRQ
1287                 @
1288                 @ now branch to the relevant MODE handling routine
1289                 @
1290                 mrs     r13, cpsr
1291                 bic     r13, r13, #MODE_MASK
1292                 orr     r13, r13, #MODE_SVC
1293                 msr     spsr, r13                       @ switch to SVC_32 mode
1294
1295                 and     lr, lr, #15
1296                 ldr     lr, [pc, lr, lsl #2]
1297                 movs    pc, lr                          @ Changes mode and branches
1298
1299 .LCtab_irq:     .word   __irq_usr                       @  0  (USR_26 / USR_32)
1300                 .word   __irq_invalid                   @  1  (FIQ_26 / FIQ_32)
1301                 .word   __irq_invalid                   @  2  (IRQ_26 / IRQ_32)
1302                 .word   __irq_svc                       @  3  (SVC_26 / SVC_32)
1303                 .word   __irq_invalid                   @  4
1304                 .word   __irq_invalid                   @  5
1305                 .word   __irq_invalid                   @  6
1306                 .word   __irq_invalid                   @  7
1307                 .word   __irq_invalid                   @  8
1308                 .word   __irq_invalid                   @  9
1309                 .word   __irq_invalid                   @  a
1310                 .word   __irq_invalid                   @  b
1311                 .word   __irq_invalid                   @  c
1312                 .word   __irq_invalid                   @  d
1313                 .word   __irq_invalid                   @  e
1314                 .word   __irq_invalid                   @  f
1315
1316                 .align  5
1317
1318 /*
1319  * Data abort dispatcher - dispatches it to the correct handler for the processor mode
1320  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1321  */
1322 vector_data:    @
1323                 @ save mode specific registers
1324                 @
1325                 ldr     r13, .LCsabt
1326                 sub     lr, lr, #8
1327                 str     lr, [r13]
1328                 mrs     lr, spsr
1329                 str     lr, [r13, #4]
1330                 @
1331                 @ now branch to the relevant MODE handling routine
1332                 @
1333                 mrs     r13, cpsr
1334                 bic     r13, r13, #MODE_MASK
1335                 orr     r13, r13, #MODE_SVC
1336                 msr     spsr, r13                       @ switch to SVC_32 mode
1337
1338                 and     lr, lr, #15
1339                 ldr     lr, [pc, lr, lsl #2]
1340                 movs    pc, lr                          @ Changes mode and branches
1341
1342 .LCtab_dabt:    .word   __dabt_usr                      @  0  (USR_26 / USR_32)
1343                 .word   __dabt_invalid                  @  1  (FIQ_26 / FIQ_32)
1344                 .word   __dabt_invalid                  @  2  (IRQ_26 / IRQ_32)
1345                 .word   __dabt_svc                      @  3  (SVC_26 / SVC_32)
1346                 .word   __dabt_invalid                  @  4
1347                 .word   __dabt_invalid                  @  5
1348                 .word   __dabt_invalid                  @  6
1349                 .word   __dabt_invalid                  @  7
1350                 .word   __dabt_invalid                  @  8
1351                 .word   __dabt_invalid                  @  9
1352                 .word   __dabt_invalid                  @  a
1353                 .word   __dabt_invalid                  @  b
1354                 .word   __dabt_invalid                  @  c
1355                 .word   __dabt_invalid                  @  d
1356                 .word   __dabt_invalid                  @  e
1357                 .word   __dabt_invalid                  @  f
1358
1359                 .align  5
1360
1361 /*
1362  * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode
1363  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1364  */
1365 vector_prefetch:
1366                 @
1367                 @ save mode specific registers
1368                 @
1369                 ldr     r13, .LCsabt
1370                 sub     lr, lr, #4
1371                 str     lr, [r13]                       @ save lr_ABT
1372                 mrs     lr, spsr
1373                 str     lr, [r13, #4]                   @ save spsr_ABT
1374                 @
1375                 @ now branch to the relevant MODE handling routine
1376                 @
1377                 mrs     r13, cpsr
1378                 bic     r13, r13, #MODE_MASK
1379                 orr     r13, r13, #MODE_SVC
1380                 msr     spsr, r13                       @ switch to SVC_32 mode
1381
1382                 ands    lr, lr, #15
1383                 ldr     lr, [pc, lr, lsl #2]
1384                 movs    pc, lr
1385
1386 .LCtab_pabt:    .word   __pabt_usr                      @  0 (USR_26 / USR_32)
1387                 .word   __pabt_invalid                  @  1 (FIQ_26 / FIQ_32)
1388                 .word   __pabt_invalid                  @  2 (IRQ_26 / IRQ_32)
1389                 .word   __pabt_svc                      @  3 (SVC_26 / SVC_32)
1390                 .word   __pabt_invalid                  @  4
1391                 .word   __pabt_invalid                  @  5
1392                 .word   __pabt_invalid                  @  6
1393                 .word   __pabt_invalid                  @  7
1394                 .word   __pabt_invalid                  @  8
1395                 .word   __pabt_invalid                  @  9
1396                 .word   __pabt_invalid                  @  a
1397                 .word   __pabt_invalid                  @  b
1398                 .word   __pabt_invalid                  @  c
1399                 .word   __pabt_invalid                  @  d
1400                 .word   __pabt_invalid                  @  e
1401                 .word   __pabt_invalid                  @  f
1402
1403                 .align  5
1404
1405 /*
1406  * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode
1407  * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1408  */
1409 vector_undefinstr:
1410                 @
1411                 @ save mode specific registers
1412                 @
1413                 ldr     r13, .LCsund
1414                 str     lr, [r13]                       @ save lr_UND
1415                 mrs     lr, spsr
1416                 str     lr, [r13, #4]                   @ save spsr_UND
1417                 @
1418                 @ now branch to the relevant MODE handling routine
1419                 @
1420                 mrs     r13, cpsr
1421                 bic     r13, r13, #MODE_MASK
1422                 orr     r13, r13, #MODE_SVC
1423                 msr     spsr, r13                       @ switch to SVC_32 mode
1424
1425                 and     lr, lr, #15
1426                 ldr     lr, [pc, lr, lsl #2]
1427                 movs    pc, lr                          @ Changes mode and branches
1428
1429 .LCtab_und:     .word   __und_usr                       @  0 (USR_26 / USR_32)
1430                 .word   __und_invalid                   @  1 (FIQ_26 / FIQ_32)
1431                 .word   __und_invalid                   @  2 (IRQ_26 / IRQ_32)
1432                 .word   __und_svc                       @  3 (SVC_26 / SVC_32)
1433                 .word   __und_invalid                   @  4
1434                 .word   __und_invalid                   @  5
1435                 .word   __und_invalid                   @  6
1436                 .word   __und_invalid                   @  7
1437                 .word   __und_invalid                   @  8
1438                 .word   __und_invalid                   @  9
1439                 .word   __und_invalid                   @  a
1440                 .word   __und_invalid                   @  b
1441                 .word   __und_invalid                   @  c
1442                 .word   __und_invalid                   @  d
1443                 .word   __und_invalid                   @  e
1444                 .word   __und_invalid                   @  f
1445
1446                 .align  5
1447
1448 /*=============================================================================
1449  * Undefined FIQs
1450  *-----------------------------------------------------------------------------
1451  * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
1452  * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
1453  * Basically to switch modes, we *HAVE* to clobber one register...  brain
1454  * damage alert!  I don't think that we can execute any code in here in any
1455  * other mode than FIQ...  Ok you can switch to another mode, but you can't
1456  * get out of that mode without clobbering one register.
1457  */
1458 vector_FIQ:     disable_fiq
1459                 subs    pc, lr, #4
1460
1461 /*=============================================================================
1462  * Address exception handler
1463  *-----------------------------------------------------------------------------
1464  * These aren't too critical.
1465  * (they're not supposed to happen, and won't happen in 32-bit data mode).
1466  */
1467
1468 vector_addrexcptn:
1469                 b       vector_addrexcptn
1470
1471 /*
1472  * We group all the following data together to optimise
1473  * for CPUs with separate I & D caches.
1474  */
1475                 .align  5
1476
1477 .LCvswi:        .word   vector_swi
1478
1479 .LCsirq:        .word   __temp_irq
1480 .LCsund:        .word   __temp_und
1481 .LCsabt:        .word   __temp_abt
1482
1483 __stubs_end:
1484
1485                 .equ    __real_stubs_start, .LCvectors + 0x200
1486
1487 .LCvectors:     swi     SYS_ERROR0
1488                 b       __real_stubs_start + (vector_undefinstr - __stubs_start)
1489                 ldr     pc, __real_stubs_start + (.LCvswi - __stubs_start)
1490                 b       __real_stubs_start + (vector_prefetch - __stubs_start)
1491                 b       __real_stubs_start + (vector_data - __stubs_start)
1492                 b       __real_stubs_start + (vector_addrexcptn - __stubs_start)
1493                 b       __real_stubs_start + (vector_IRQ - __stubs_start)
1494                 b       __real_stubs_start + (vector_FIQ - __stubs_start)
1495
1496 ENTRY(__trap_init)
1497                 stmfd   sp!, {r4 - r6, lr}
1498
1499                 adr     r1, .LCvectors                  @ set up the vectors
1500                 ldmia   r1, {r1, r2, r3, r4, r5, r6, ip, lr}
1501                 stmia   r0, {r1, r2, r3, r4, r5, r6, ip, lr}
1502
1503                 add     r2, r0, #0x200
1504                 adr     r0, __stubs_start               @ copy stubs to 0x200
1505                 adr     r1, __stubs_end
1506 1:              ldr     r3, [r0], #4
1507                 str     r3, [r2], #4
1508                 cmp     r0, r1
1509                 blt     1b
1510                 LOADREGS(fd, sp!, {r4 - r6, pc})
1511
1512                 .data
1513
1514 /*
1515  * Do not reorder these, and do not insert extra data between...
1516  */
1517
1518 __temp_irq:     .word   0                               @ saved lr_irq
1519                 .word   0                               @ saved spsr_irq
1520                 .word   -1                              @ old_r0
1521 __temp_und:     .word   0                               @ Saved lr_und
1522                 .word   0                               @ Saved spsr_und
1523                 .word   -1                              @ old_r0
1524 __temp_abt:     .word   0                               @ Saved lr_abt
1525                 .word   0                               @ Saved spsr_abt
1526                 .word   -1                              @ old_r0
1527
1528                 .globl  cr_alignment
1529                 .globl  cr_no_alignment
1530 cr_alignment:
1531                 .space  4
1532 cr_no_alignment:
1533                 .space  4