Linux 3.12.28
[linux/fpc-iii.git] / arch / blackfin / include / asm / context.S
blob507e7aa6a561d56f0e744181c52ceeef9eab7834
1 /*
2  * Copyright 2007-2009 Analog Devices Inc.
3  *
4  * Licensed under the GPL-2 or later.
5  */
7 /*
8  * NOTE!  The single-stepping code assumes that all interrupt handlers
9  * start by saving SYSCFG on the stack with their first instruction.
10  */
13  * Code to save processor context.
14  *  We even save the register which are preserved by a function call
15  *       - r4, r5, r6, r7, p3, p4, p5
16  */
17 .macro save_context_with_interrupts
18         [--sp] = SYSCFG;
20         [--sp] = P0;    /*orig_p0*/
21         [--sp] = R0;    /*orig_r0*/
23         [--sp] = ( R7:0, P5:0 );
24         [--sp] = fp;
25         [--sp] = usp;
27         [--sp] = i0;
28         [--sp] = i1;
29         [--sp] = i2;
30         [--sp] = i3;
32         [--sp] = m0;
33         [--sp] = m1;
34         [--sp] = m2;
35         [--sp] = m3;
37         [--sp] = l0;
38         [--sp] = l1;
39         [--sp] = l2;
40         [--sp] = l3;
42         [--sp] = b0;
43         [--sp] = b1;
44         [--sp] = b2;
45         [--sp] = b3;
46         [--sp] = a0.x;
47         [--sp] = a0.w;
48         [--sp] = a1.x;
49         [--sp] = a1.w;
51         [--sp] = LC0;
52         [--sp] = LC1;
53         [--sp] = LT0;
54         [--sp] = LT1;
55         [--sp] = LB0;
56         [--sp] = LB1;
58         [--sp] = ASTAT;
60         [--sp] = r0;    /* Skip reserved */
61         [--sp] = RETS;
62         r0 = RETI;
63         [--sp] = r0;
64         [--sp] = RETX;
65         [--sp] = RETN;
66         [--sp] = RETE;
67         [--sp] = SEQSTAT;
68         [--sp] = r0;    /* Skip IPEND as well. */
69         /* Switch to other method of keeping interrupts disabled.  */
70 #ifdef CONFIG_DEBUG_HWERR
71         r0 = 0x3f;
72         sti r0;
73 #else
74         cli r0;
75 #endif
76 #ifdef CONFIG_TRACE_IRQFLAGS
77         sp += -12;
78         call _trace_hardirqs_off;
79         sp += 12;
80 #endif
81         [--sp] = RETI;  /*orig_pc*/
82         /* Clear all L registers.  */
83         r0 = 0 (x);
84         l0 = r0;
85         l1 = r0;
86         l2 = r0;
87         l3 = r0;
88 .endm
90 .macro save_context_syscall
91         [--sp] = SYSCFG;
93         [--sp] = P0;    /*orig_p0*/
94         [--sp] = R0;    /*orig_r0*/
95         [--sp] = ( R7:0, P5:0 );
96         [--sp] = fp;
97         [--sp] = usp;
99         [--sp] = i0;
100         [--sp] = i1;
101         [--sp] = i2;
102         [--sp] = i3;
104         [--sp] = m0;
105         [--sp] = m1;
106         [--sp] = m2;
107         [--sp] = m3;
109         [--sp] = l0;
110         [--sp] = l1;
111         [--sp] = l2;
112         [--sp] = l3;
114         [--sp] = b0;
115         [--sp] = b1;
116         [--sp] = b2;
117         [--sp] = b3;
118         [--sp] = a0.x;
119         [--sp] = a0.w;
120         [--sp] = a1.x;
121         [--sp] = a1.w;
123         [--sp] = LC0;
124         [--sp] = LC1;
125         [--sp] = LT0;
126         [--sp] = LT1;
127         [--sp] = LB0;
128         [--sp] = LB1;
130         [--sp] = ASTAT;
132         [--sp] = r0;    /* Skip reserved */
133         [--sp] = RETS;
134         r0 = RETI;
135         [--sp] = r0;
136         [--sp] = RETX;
137         [--sp] = RETN;
138         [--sp] = RETE;
139         [--sp] = SEQSTAT;
140         [--sp] = r0;    /* Skip IPEND as well. */
141         [--sp] = RETI;  /*orig_pc*/
142         /* Clear all L registers.  */
143         r0 = 0 (x);
144         l0 = r0;
145         l1 = r0;
146         l2 = r0;
147         l3 = r0;
148 .endm
150 .macro save_context_no_interrupts
151         [--sp] = SYSCFG;
152         [--sp] = P0;    /* orig_p0 */
153         [--sp] = R0;    /* orig_r0 */
154         [--sp] = ( R7:0, P5:0 );
155         [--sp] = fp;
156         [--sp] = usp;
158         [--sp] = i0;
159         [--sp] = i1;
160         [--sp] = i2;
161         [--sp] = i3;
163         [--sp] = m0;
164         [--sp] = m1;
165         [--sp] = m2;
166         [--sp] = m3;
168         [--sp] = l0;
169         [--sp] = l1;
170         [--sp] = l2;
171         [--sp] = l3;
173         [--sp] = b0;
174         [--sp] = b1;
175         [--sp] = b2;
176         [--sp] = b3;
177         [--sp] = a0.x;
178         [--sp] = a0.w;
179         [--sp] = a1.x;
180         [--sp] = a1.w;
182         [--sp] = LC0;
183         [--sp] = LC1;
184         [--sp] = LT0;
185         [--sp] = LT1;
186         [--sp] = LB0;
187         [--sp] = LB1;
189         [--sp] = ASTAT;
191 #ifdef CONFIG_KGDB
192         fp     = 0(Z);
193         r1     = sp;
194         r1    += 60;
195         r1    += 60;
196         r1    += 60;
197         [--sp] = r1;
198 #else
199         [--sp] = r0;    /* Skip reserved */
200 #endif
201         [--sp] = RETS;
202         r0 = RETI;
203         [--sp] = r0;
204         [--sp] = RETX;
205         [--sp] = RETN;
206         [--sp] = RETE;
207         [--sp] = SEQSTAT;
208 #ifdef CONFIG_DEBUG_KERNEL
209         p1.l = lo(IPEND);
210         p1.h = hi(IPEND);
211         r1 = [p1];
212         [--sp] = r1;
213 #else
214         [--sp] = r0;    /* Skip IPEND as well. */
215 #endif
216         [--sp] = r0;  /*orig_pc*/
217         /* Clear all L registers.  */
218         r0 = 0 (x);
219         l0 = r0;
220         l1 = r0;
221         l2 = r0;
222         l3 = r0;
223 .endm
225 .macro restore_context_no_interrupts
226         sp += 4;        /* Skip orig_pc */
227         sp += 4;        /* Skip IPEND */
228         SEQSTAT = [sp++];
229         RETE = [sp++];
230         RETN = [sp++];
231         RETX = [sp++];
232         r0 = [sp++];
233         RETI = r0;      /* Restore RETI indirectly when in exception */
234         RETS = [sp++];
236         sp += 4;        /* Skip Reserved */
238         ASTAT = [sp++];
240         LB1 = [sp++];
241         LB0 = [sp++];
242         LT1 = [sp++];
243         LT0 = [sp++];
244         LC1 = [sp++];
245         LC0 = [sp++];
247         a1.w = [sp++];
248         a1.x = [sp++];
249         a0.w = [sp++];
250         a0.x = [sp++];
251         b3 = [sp++];
252         b2 = [sp++];
253         b1 = [sp++];
254         b0 = [sp++];
256         l3 = [sp++];
257         l2 = [sp++];
258         l1 = [sp++];
259         l0 = [sp++];
261         m3 = [sp++];
262         m2 = [sp++];
263         m1 = [sp++];
264         m0 = [sp++];
266         i3 = [sp++];
267         i2 = [sp++];
268         i1 = [sp++];
269         i0 = [sp++];
271         sp += 4;
272         fp = [sp++];
274         ( R7 : 0, P5 : 0) = [ SP ++ ];
275         sp += 8;        /* Skip orig_r0/orig_p0 */
276         SYSCFG = [sp++];
277 .endm
279 .macro restore_context_with_interrupts
280         sp += 4;        /* Skip orig_pc */
281         sp += 4;        /* Skip IPEND */
282         SEQSTAT = [sp++];
283         RETE = [sp++];
284         RETN = [sp++];
285         RETX = [sp++];
286         RETI = [sp++];
288 #ifdef CONFIG_TRACE_IRQFLAGS
289         sp += -12;
290         call _trace_hardirqs_on;
291         sp += 12;
292 #endif
294         RETS = [sp++];
296 #ifdef CONFIG_SMP
297         GET_PDA(p0, r0);
298         r0 = [p0 + PDA_IRQFLAGS];
299 #else
300         p0.h = _bfin_irq_flags;
301         p0.l = _bfin_irq_flags;
302         r0 = [p0];
303 #endif
304         sti r0;
306         sp += 4;        /* Skip Reserved */
308         ASTAT = [sp++];
310         LB1 = [sp++];
311         LB0 = [sp++];
312         LT1 = [sp++];
313         LT0 = [sp++];
314         LC1 = [sp++];
315         LC0 = [sp++];
317         a1.w = [sp++];
318         a1.x = [sp++];
319         a0.w = [sp++];
320         a0.x = [sp++];
321         b3 = [sp++];
322         b2 = [sp++];
323         b1 = [sp++];
324         b0 = [sp++];
326         l3 = [sp++];
327         l2 = [sp++];
328         l1 = [sp++];
329         l0 = [sp++];
331         m3 = [sp++];
332         m2 = [sp++];
333         m1 = [sp++];
334         m0 = [sp++];
336         i3 = [sp++];
337         i2 = [sp++];
338         i1 = [sp++];
339         i0 = [sp++];
341         sp += 4;
342         fp = [sp++];
344         ( R7 : 0, P5 : 0) = [ SP ++ ];
345         sp += 8;        /* Skip orig_r0/orig_p0 */
346         csync;
347         SYSCFG = [sp++];
348         csync;
349 .endm
351 .macro save_context_cplb
352         [--sp] = (R7:0, P5:0);
353         [--sp] = fp;
355         [--sp] = a0.x;
356         [--sp] = a0.w;
357         [--sp] = a1.x;
358         [--sp] = a1.w;
360         [--sp] = LC0;
361         [--sp] = LC1;
362         [--sp] = LT0;
363         [--sp] = LT1;
364         [--sp] = LB0;
365         [--sp] = LB1;
367         [--sp] = RETS;
368 .endm
370 .macro restore_context_cplb
371         RETS = [sp++];
373         LB1 = [sp++];
374         LB0 = [sp++];
375         LT1 = [sp++];
376         LT0 = [sp++];
377         LC1 = [sp++];
378         LC0 = [sp++];
380         a1.w = [sp++];
381         a1.x = [sp++];
382         a0.w = [sp++];
383         a0.x = [sp++];
385         fp = [sp++];
387         (R7:0, P5:0) = [SP++];
388 .endm
390 .macro pseudo_long_call func:req, scratch:req
391 #ifdef CONFIG_ROMKERNEL
392         \scratch\().l = \func;
393         \scratch\().h = \func;
394         call (\scratch);
395 #else
396         call \func;
397 #endif
398 .endm
400 #if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
401 # define EX_SCRATCH_REG RETN
402 #elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
403 # define EX_SCRATCH_REG RETE
404 #else
405 # define EX_SCRATCH_REG CYCLES
406 #endif