Merge remote-tracking branch 'spi/topic/core' into spi-next
[sfrench/cifs-2.6.git] / arch / arc / include / asm / entry-arcv2.h
1
2 #ifndef __ASM_ARC_ENTRY_ARCV2_H
3 #define __ASM_ARC_ENTRY_ARCV2_H
4
5 #include <asm/asm-offsets.h>
6 #include <asm/irqflags-arcv2.h>
7 #include <asm/thread_info.h>    /* For THREAD_SIZE */
8
9 /*------------------------------------------------------------------------*/
10 .macro INTERRUPT_PROLOGUE       called_from
11
12         ; Before jumping to Interrupt Vector, hardware micro-ops did following:
13         ;   1. SP auto-switched to kernel mode stack
14         ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
15         ;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
16         ;
17         ; Now manually save: r12, sp, fp, gp, r25
18
19         PUSH    r30
20         PUSH    r12
21
22         ; Saving pt_regs->sp correctly requires some extra work due to the way
23         ; Auto stack switch works
24         ;  - U mode: retrieve it from AUX_USER_SP
25         ;  - K mode: add the offset from current SP where H/w starts auto push
26         ;
27         ; Utilize the fact that Z bit is set if Intr taken in U mode
28         mov.nz  r9, sp
29         add.nz  r9, r9, SZ_PT_REGS - PT_sp - 4
30         bnz     1f
31
32         lr      r9, [AUX_USER_SP]
33 1:
34         PUSH    r9      ; SP
35
36         PUSH    fp
37         PUSH    gp
38
39 #ifdef CONFIG_ARC_CURR_IN_REG
40         PUSH    r25                     ; user_r25
41         GET_CURR_TASK_ON_CPU    r25
42 #else
43         sub     sp, sp, 4
44 #endif
45
46 .ifnc \called_from, exception
47         sub     sp, sp, 12      ; BTA/ECR/orig_r0 placeholder per pt_regs
48 .endif
49
50 .endm
51
52 /*------------------------------------------------------------------------*/
53 .macro INTERRUPT_EPILOGUE       called_from
54
55 .ifnc \called_from, exception
56         add     sp, sp, 12      ; skip BTA/ECR/orig_r0 placeholderss
57 .endif
58
59 #ifdef CONFIG_ARC_CURR_IN_REG
60         POP     r25
61 #else
62         add     sp, sp, 4
63 #endif
64
65         POP     gp
66         POP     fp
67
68         ; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
69         ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
70         add.z   sp, sp, 4
71         bz      1f
72
73         POPAX   AUX_USER_SP
74 1:
75         POP     r12
76         POP     r30
77
78 .endm
79
80 /*------------------------------------------------------------------------*/
81 .macro EXCEPTION_PROLOGUE
82
83         ; Before jumping to Exception Vector, hardware micro-ops did following:
84         ;   1. SP auto-switched to kernel mode stack
85         ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
86         ;
87         ; Now manually save the complete reg file
88
89         PUSH    r9              ; freeup a register: slot of erstatus
90
91         PUSHAX  eret
92         sub     sp, sp, 12      ; skip JLI, LDI, EI
93         PUSH    lp_count
94         PUSHAX  lp_start
95         PUSHAX  lp_end
96         PUSH    blink
97
98         PUSH    r11
99         PUSH    r10
100
101         ld.as   r9,  [sp, 10]   ; load stashed r9 (status32 stack slot)
102         lr      r10, [erstatus]
103         st.as   r10, [sp, 10]   ; save status32 at it's right stack slot
104
105         PUSH    r9
106         PUSH    r8
107         PUSH    r7
108         PUSH    r6
109         PUSH    r5
110         PUSH    r4
111         PUSH    r3
112         PUSH    r2
113         PUSH    r1
114         PUSH    r0
115
116         ; -- for interrupts, regs above are auto-saved by h/w in that order --
117         ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
118         ;
119         ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
120         ; Although H/w exception micro-ops do set Z flag for U mode (just like
121         ; for interrupts), it could get clobbered in case we soft land here from
122         ; a TLB Miss exception handler (tlbex.S)
123
124         and     r10, r10, STATUS_U_MASK
125         xor.f   0, r10, STATUS_U_MASK
126
127         INTERRUPT_PROLOGUE  exception
128
129         PUSHAX  erbta
130         PUSHAX  ecr             ; r9 contains ECR, expected by EV_Trap
131
132         PUSH    r0              ; orig_r0
133 .endm
134
135 /*------------------------------------------------------------------------*/
136 .macro EXCEPTION_EPILOGUE
137
138         ; Assumes r0 has PT_status32
139         btst   r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE
140
141         add     sp, sp, 8       ; orig_r0/ECR don't need restoring
142         POPAX   erbta
143
144         INTERRUPT_EPILOGUE  exception
145
146         POP     r0
147         POP     r1
148         POP     r2
149         POP     r3
150         POP     r4
151         POP     r5
152         POP     r6
153         POP     r7
154         POP     r8
155         POP     r9
156         POP     r10
157         POP     r11
158
159         POP     blink
160         POPAX   lp_end
161         POPAX   lp_start
162
163         POP     r9
164         mov     lp_count, r9
165
166         add     sp, sp, 12      ; skip JLI, LDI, EI
167         POPAX   eret
168         POPAX   erstatus
169
170         ld.as   r9, [sp, -12]   ; reload r9 which got clobbered
171 .endm
172
173 .macro FAKE_RET_FROM_EXCPN
174         lr      r9, [status32]
175         bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
176         or      r9, r9, (STATUS_L_MASK|STATUS_IE_MASK)
177         kflag   r9
178 .endm
179
180 /* Get thread_info of "current" tsk */
181 .macro GET_CURR_THR_INFO_FROM_SP  reg
182         bmskn \reg, sp, THREAD_SHIFT - 1
183 .endm
184
185 /* Get CPU-ID of this core */
186 .macro  GET_CPU_ID  reg
187         lr  \reg, [identity]
188         xbfu \reg, \reg, 0xE8   /* 00111    01000 */
189                                 /* M = 8-1  N = 8 */
190 .endm
191
192 #endif