import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / arm / kernel / entry-header.S
1 #include <linux/config.h> /* for CONFIG_ARCH_xxxx */
2 #include <linux/linkage.h>
3
4 #include <asm/assembler.h>
5 #include <asm/constants.h>
6 #include <asm/errno.h>
7 #include <asm/hardware.h>
8 #include <asm/arch/irqs.h>
9 #include <asm/proc-fns.h>
10
11 #ifndef MODE_SVC
12 #define MODE_SVC 0x13
13 #endif
14
15                 .macro  zero_fp
16 #ifdef CONFIG_FRAME_POINTER
17                 mov     fp, #0
18 #endif
19                 .endm
20
21                 .text
22
23 @ Bad Abort numbers
24 @ -----------------
25 @
26 #define BAD_PREFETCH    0
27 #define BAD_DATA        1
28 #define BAD_ADDREXCPTN  2
29 #define BAD_IRQ         3
30 #define BAD_UNDEFINSTR  4
31
32 #define PT_TRACESYS     0x00000002
33
34 @ OS version number used in SWIs
35 @  RISC OS is 0
36 @  RISC iX is 8
37 @
38 #define OS_NUMBER       9
39 #define ARMSWI_OFFSET   0x000f0000
40
41 @
42 @ Stack format (ensured by USER_* and SVC_*)
43 @
44 #ifdef CONFIG_CPU_32
45 #define S_FRAME_SIZE    72
46 #define S_OLD_R0        68
47 #define S_PSR           64
48 #else
49 #define S_FRAME_SIZE    68
50 #define S_OLD_R0        64
51 #define S_PSR           60
52 #endif
53
54 #define S_PC            60
55 #define S_LR            56
56 #define S_SP            52
57 #define S_IP            48
58 #define S_FP            44
59 #define S_R10           40
60 #define S_R9            36
61 #define S_R8            32
62 #define S_R7            28
63 #define S_R6            24
64 #define S_R5            20
65 #define S_R4            16
66 #define S_R3            12
67 #define S_R2            8
68 #define S_R1            4
69 #define S_R0            0
70 #define S_OFF           8
71
72 #ifdef CONFIG_CPU_32
73         .macro  set_cpsr_c, reg, mode
74 #if 1
75         /* broken binutils */
76         mov     \reg, \mode
77         msr     cpsr_c, \reg
78 #else
79         msr     cpsr_c, \mode
80 #endif
81         .endm
82
83         .macro  disable_irq, temp
84         set_cpsr_c \temp, #I_BIT | MODE_SVC
85         .endm
86
87         .macro  enable_irq, temp
88         set_cpsr_c \temp, #MODE_SVC
89         .endm
90
91                 .macro  save_user_regs
92                 sub     sp, sp, #S_FRAME_SIZE
93                 stmia   sp, {r0 - r12}                  @ Calling r0 - r12
94                 add     r8, sp, #S_PC
95                 stmdb   r8, {sp, lr}^                   @ Calling sp, lr
96                 mrs     r8, spsr                        @ called from non-FIQ mode, so ok.
97                 str     lr, [sp, #S_PC]                 @ Save calling PC
98                 str     r8, [sp, #S_PSR]                @ Save CPSR
99                 str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
100                 .endm
101
102 /*
103  * Must be called with IRQs already disabled.
104  */
105                 .macro  restore_user_regs
106                 ldr     r1, [sp, #S_PSR]                @ Get calling cpsr
107                 ldr     lr, [sp, #S_PC]!                @ Get PC
108                 msr     spsr, r1                        @ save in spsr_svc
109                 ldmdb   sp, {r0 - lr}^                  @ Get calling r0 - lr
110                 mov     r0, r0
111                 add     sp, sp, #S_FRAME_SIZE - S_PC
112                 movs    pc, lr                          @ return & move spsr_svc into cpsr
113                 .endm
114
115 /*
116  * Must be called with IRQs already disabled.
117  */
118                 .macro  fast_restore_user_regs
119                 ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
120                 ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
121                 msr     spsr, r1                        @ save in spsr_svc
122                 ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
123                 mov     r0, r0
124                 add     sp, sp, #S_FRAME_SIZE - S_PC
125                 movs    pc, lr                          @ return & move spsr_svc into cpsr
126                 .endm
127
128                 .macro  mask_pc, rd, rm
129                 .endm
130
131                 .macro  get_current_task, rd
132                 mov     \rd, sp, lsr #13
133                 mov     \rd, \rd, lsl #13
134                 .endm
135
136                 /*
137                  * Like adr, but force SVC mode (if required)
138                  */
139                 .macro  adrsvc, cond, reg, label
140                 adr\cond        \reg, \label
141                 .endm
142
143                 .macro  alignment_trap, rbase, rtemp, sym
144 #ifdef CONFIG_ALIGNMENT_TRAP
145 #define OFF_CR_ALIGNMENT(x)     cr_alignment - x
146
147                 ldr     \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
148                 mcr     p15, 0, \rtemp, c1, c0
149 #endif
150                 .endm
151
152 #else
153                 .macro  save_user_regs
154                 sub     sp, sp, #S_FRAME_SIZE
155                 str     r0, [sp, #S_OLD_R0]
156                 str     lr, [sp, #S_PC]
157                 stmia   sp, {r0 - lr}^
158                 mov     r0, r0
159                 .endm
160
161                 .macro  restore_user_regs
162                 ldmia   sp, {r0 - lr}^
163                 mov     r0, r0
164                 ldr     lr, [sp, #S_PC]
165                 add     sp, sp, #S_FRAME_SIZE
166                 movs    pc, lr
167                 .endm
168
169                 .macro  fast_restore_user_regs
170                 add     sp, sp, #S_OFF + S_PC
171                 ldmdb   sp, {r1 - lr}^
172                 mov     r0, r0
173                 ldr     lr, [sp], #S_FRAME_SIZE - S_PC
174                 movs    pc, lr
175                 .endm
176
177                 .macro  mask_pc, rd, rm
178                 bic     \rd, \rm, #PCMASK
179                 .endm
180
181                 .macro  disable_irq, temp
182                 teqp    pc, #0x08000003
183                 .endm
184
185                 .macro  enable_irq, temp
186                 teqp    pc, #0x00000003
187                 .endm
188
189                 .macro  initialise_traps_extra
190                 .endm
191
192                 .macro  get_current_task, rd
193                 mov     \rd, sp, lsr #13
194                 mov     \rd, \rd, lsl #13
195                 .endm
196
197                 /*
198                  * Like adr, but force SVC mode (if required)
199                  */
200                 .macro  adrsvc, cond, reg, label
201                 adr\cond        \reg, \label
202                 orr\cond        \reg, \reg, #0x08000003
203                 .endm
204
205 #endif
206
207
208 /*
209  * These are the registers used in the syscall handler, and allow us to
210  * have in theory up to 7 arguments to a function - r0 to r6.
211  *
212  * r7 is reserved for the system call number for thumb mode.
213  *
214  * Note that tbl == why is intentional.
215  *
216  * We must set at least "tsk" and "why" when calling ret_with_reschedule.
217  */
218 scno    .req    r7                              @ syscall number
219 tbl     .req    r8                              @ syscall table pointer
220 why     .req    r8                              @ Linux syscall (!= 0)
221 tsk     .req    r9                              @ current task
222
223 /*
224  * Get the system call number.
225  */
226         .macro  get_scno
227 #ifdef CONFIG_ARM_THUMB
228         tst     r8, #T_BIT              @ this is SPSR from save_user_regs
229         addne   scno, r7, #OS_NUMBER << 20 @ put OS number in
230         ldreq   scno, [lr, #-4]
231
232 #else
233         mask_pc lr, lr
234         ldr     scno, [lr, #-4]         @ get SWI instruction
235 #endif
236         .endm
237