http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / kernel / linux / 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
10 #ifndef MODE_SVC
11 #define MODE_SVC 0x13
12 #endif
13
14         .macro  zero_fp
15 #ifdef CONFIG_FRAME_POINTER
16         mov     fp, #0
17 #endif
18         .endm
19
20         .text
21
22 @ Bad Abort numbers
23 @ -----------------
24 @
25 #define BAD_PREFETCH    0
26 #define BAD_DATA        1
27 #define BAD_ADDREXCPTN  2
28 #define BAD_IRQ         3
29 #define BAD_UNDEFINSTR  4
30
31 #define PT_TRACESYS     0x00000002
32
33 @ OS version number used in SWIs
34 @  RISC OS is 0
35 @  RISC iX is 8
36 @
37 #define OS_NUMBER       9
38 #define ARMSWI_OFFSET   0x000f0000
39
40 @
41 @ Stack format (ensured by USER_* and SVC_*)
42 @
43 #define S_FRAME_SIZE    72
44 #define S_OLD_R0        68
45 #define S_PSR           64
46
47 #define S_PC            60
48 #define S_LR            56
49 #define S_SP            52
50 #define S_IP            48
51 #define S_FP            44
52 #define S_R10           40
53 #define S_R9            36
54 #define S_R8            32
55 #define S_R7            28
56 #define S_R6            24
57 #define S_R5            20
58 #define S_R4            16
59 #define S_R3            12
60 #define S_R2            8
61 #define S_R1            4
62 #define S_R0            0
63 #define S_OFF           8
64
65         .macro  set_cpsr_c, reg, mode
66         msr     cpsr_c, \mode
67         .endm
68
69 #if __LINUX_ARM_ARCH__ >= 6
70         .macro  disable_irq, temp
71         cpsid   i
72         .endm
73
74         .macro  enable_irq, temp
75         cpsie   i
76         .endm
77 #else
78         .macro  disable_irq, temp
79         set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC
80         .endm
81
82         .macro  enable_irq, temp
83         set_cpsr_c \temp, #MODE_SVC
84         .endm
85 #endif
86
87         .macro  save_user_regs
88         sub     sp, sp, #S_FRAME_SIZE
89         stmia   sp, {r0 - r12}                  @ Calling r0 - r12
90         add     r8, sp, #S_PC
91         stmdb   r8, {sp, lr}^                   @ Calling sp, lr
92         mrs     r8, spsr                        @ called from non-FIQ mode, so ok.
93         str     lr, [sp, #S_PC]                 @ Save calling PC
94         str     r8, [sp, #S_PSR]                @ Save CPSR
95         str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
96         .endm
97
98         .macro  restore_user_regs
99         ldr     r1, [sp, #S_PSR]                @ Get calling cpsr
100         disable_irq ip                          @ disable IRQs
101         ldr     lr, [sp, #S_PC]!                @ Get PC
102         msr     spsr_cxsf, r1                   @ save in spsr_svc
103         ldmdb   sp, {r0 - lr}^                  @ Get calling r0 - lr
104         mov     r0, r0
105         add     sp, sp, #S_FRAME_SIZE - S_PC
106         movs    pc, lr                          @ return & move spsr_svc into cpsr
107         .endm
108
109 /*
110  * Must be called with IRQs already disabled.
111  */
112         .macro  fast_restore_user_regs
113         ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
114         ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
115         msr     spsr_cxsf, r1                   @ save in spsr_svc
116         ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
117         mov     r0, r0
118         add     sp, sp, #S_FRAME_SIZE - S_PC
119         movs    pc, lr                          @ return & move spsr_svc into cpsr
120         .endm
121
122 /*
123  * Must be called with IRQs already disabled.
124  */
125         .macro  slow_restore_user_regs
126         ldr     r1, [sp, #S_PSR]                @ get calling cpsr
127         ldr     lr, [sp, #S_PC]!                @ get pc
128         msr     spsr_cxsf, r1                   @ save in spsr_svc
129         ldmdb   sp, {r0 - lr}^                  @ get calling r1 - lr
130         mov     r0, r0
131         add     sp, sp, #S_FRAME_SIZE - S_PC
132         movs    pc, lr                          @ return & move spsr_svc into cpsr
133         .endm
134
135         .macro  mask_pc, rd, rm
136         .endm
137
138         .macro  get_thread_info, rd
139         mov     \rd, sp, lsr #13
140         mov     \rd, \rd, lsl #13
141         .endm
142
143 /*
144  * Like adr, but force SVC mode (if required)
145  */
146         .macro  adrsvc, cond, reg, label
147         adr\cond        \reg, \label
148         .endm
149
150         .macro  alignment_trap, rbase, rtemp, sym
151 #ifdef CONFIG_ALIGNMENT_TRAP
152 #define OFF_CR_ALIGNMENT(x)     cr_alignment - x
153
154         ldr     \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
155         mcr     p15, 0, \rtemp, c1, c0
156 #endif
157         .endm
158
159
160 /*
161  * These are the registers used in the syscall handler, and allow us to
162  * have in theory up to 7 arguments to a function - r0 to r6.
163  *
164  * r7 is reserved for the system call number for thumb mode.
165  *
166  * Note that tbl == why is intentional.
167  *
168  * We must set at least "tsk" and "why" when calling ret_with_reschedule.
169  */
170 scno    .req    r7              @ syscall number
171 tbl     .req    r8              @ syscall table pointer
172 why     .req    r8              @ Linux syscall (!= 0)
173 tsk     .req    r9              @ current thread_info
174
175 /*
176  * Get the system call number.
177  */
178         .macro  get_scno
179 #ifdef CONFIG_ARM_THUMB
180         tst     r8, #PSR_T_BIT          @ this is SPSR from save_user_regs
181         addne   scno, r7, #OS_NUMBER << 20 @ put OS number in
182         ldreq   scno, [lr, #-4]
183
184 #else
185         mask_pc lr, lr
186         ldr     scno, [lr, #-4]         @ get SWI instruction
187 #endif
188         .endm