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