Merge branch 'fix/hda' into for-linus
[pandora-kernel.git] / arch / blackfin / include / asm / context.S
1 /*
2  * File:         arch/blackfin/kernel/context.S
3  * Based on:
4  * Author:
5  *
6  * Created:
7  * Description:
8  *
9  * Modified:
10  *               Copyright 2004-2007 Analog Devices Inc.
11  *
12  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, see the file COPYING, or write
26  * to the Free Software Foundation, Inc.,
27  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29
30 /*
31  * NOTE!  The single-stepping code assumes that all interrupt handlers
32  * start by saving SYSCFG on the stack with their first instruction.
33  */
34
35 /*
36  * Code to save processor context.
37  *  We even save the register which are preserved by a function call
38  *       - r4, r5, r6, r7, p3, p4, p5
39  */
40 .macro save_context_with_interrupts
41         [--sp] = SYSCFG;
42
43         [--sp] = P0;    /*orig_p0*/
44         [--sp] = R0;    /*orig_r0*/
45
46         [--sp] = ( R7:0, P5:0 );
47         [--sp] = fp;
48         [--sp] = usp;
49
50         [--sp] = i0;
51         [--sp] = i1;
52         [--sp] = i2;
53         [--sp] = i3;
54
55         [--sp] = m0;
56         [--sp] = m1;
57         [--sp] = m2;
58         [--sp] = m3;
59
60         [--sp] = l0;
61         [--sp] = l1;
62         [--sp] = l2;
63         [--sp] = l3;
64
65         [--sp] = b0;
66         [--sp] = b1;
67         [--sp] = b2;
68         [--sp] = b3;
69         [--sp] = a0.x;
70         [--sp] = a0.w;
71         [--sp] = a1.x;
72         [--sp] = a1.w;
73
74         [--sp] = LC0;
75         [--sp] = LC1;
76         [--sp] = LT0;
77         [--sp] = LT1;
78         [--sp] = LB0;
79         [--sp] = LB1;
80
81         [--sp] = ASTAT;
82
83         [--sp] = r0;    /* Skip reserved */
84         [--sp] = RETS;
85         r0 = RETI;
86         [--sp] = r0;
87         [--sp] = RETX;
88         [--sp] = RETN;
89         [--sp] = RETE;
90         [--sp] = SEQSTAT;
91         [--sp] = r0;    /* Skip IPEND as well. */
92         /* Switch to other method of keeping interrupts disabled.  */
93 #ifdef CONFIG_DEBUG_HWERR
94         r0 = 0x3f;
95         sti r0;
96 #else
97         cli r0;
98 #endif
99         [--sp] = RETI;  /*orig_pc*/
100         /* Clear all L registers.  */
101         r0 = 0 (x);
102         l0 = r0;
103         l1 = r0;
104         l2 = r0;
105         l3 = r0;
106 .endm
107
108 .macro save_context_syscall
109         [--sp] = SYSCFG;
110
111         [--sp] = P0;    /*orig_p0*/
112         [--sp] = R0;    /*orig_r0*/
113         [--sp] = ( R7:0, P5:0 );
114         [--sp] = fp;
115         [--sp] = usp;
116
117         [--sp] = i0;
118         [--sp] = i1;
119         [--sp] = i2;
120         [--sp] = i3;
121
122         [--sp] = m0;
123         [--sp] = m1;
124         [--sp] = m2;
125         [--sp] = m3;
126
127         [--sp] = l0;
128         [--sp] = l1;
129         [--sp] = l2;
130         [--sp] = l3;
131
132         [--sp] = b0;
133         [--sp] = b1;
134         [--sp] = b2;
135         [--sp] = b3;
136         [--sp] = a0.x;
137         [--sp] = a0.w;
138         [--sp] = a1.x;
139         [--sp] = a1.w;
140
141         [--sp] = LC0;
142         [--sp] = LC1;
143         [--sp] = LT0;
144         [--sp] = LT1;
145         [--sp] = LB0;
146         [--sp] = LB1;
147
148         [--sp] = ASTAT;
149
150         [--sp] = r0;    /* Skip reserved */
151         [--sp] = RETS;
152         r0 = RETI;
153         [--sp] = r0;
154         [--sp] = RETX;
155         [--sp] = RETN;
156         [--sp] = RETE;
157         [--sp] = SEQSTAT;
158         [--sp] = r0;    /* Skip IPEND as well. */
159         [--sp] = RETI;  /*orig_pc*/
160         /* Clear all L registers.  */
161         r0 = 0 (x);
162         l0 = r0;
163         l1 = r0;
164         l2 = r0;
165         l3 = r0;
166 .endm
167
168 .macro save_context_no_interrupts
169         [--sp] = SYSCFG;
170         [--sp] = P0;    /* orig_p0 */
171         [--sp] = R0;    /* orig_r0 */
172         [--sp] = ( R7:0, P5:0 );
173         [--sp] = fp;
174         [--sp] = usp;
175
176         [--sp] = i0;
177         [--sp] = i1;
178         [--sp] = i2;
179         [--sp] = i3;
180
181         [--sp] = m0;
182         [--sp] = m1;
183         [--sp] = m2;
184         [--sp] = m3;
185
186         [--sp] = l0;
187         [--sp] = l1;
188         [--sp] = l2;
189         [--sp] = l3;
190
191         [--sp] = b0;
192         [--sp] = b1;
193         [--sp] = b2;
194         [--sp] = b3;
195         [--sp] = a0.x;
196         [--sp] = a0.w;
197         [--sp] = a1.x;
198         [--sp] = a1.w;
199
200         [--sp] = LC0;
201         [--sp] = LC1;
202         [--sp] = LT0;
203         [--sp] = LT1;
204         [--sp] = LB0;
205         [--sp] = LB1;
206
207         [--sp] = ASTAT;
208
209 #ifdef CONFIG_KGDB
210         fp     = 0(Z);
211         r1     = sp;
212         r1    += 60;
213         r1    += 60;
214         r1    += 60;
215         [--sp] = r1;
216 #else
217         [--sp] = r0;    /* Skip reserved */
218 #endif
219         [--sp] = RETS;
220         r0 = RETI;
221         [--sp] = r0;
222         [--sp] = RETX;
223         [--sp] = RETN;
224         [--sp] = RETE;
225         [--sp] = SEQSTAT;
226 #ifdef CONFIG_DEBUG_KERNEL
227         p1.l = lo(IPEND);
228         p1.h = hi(IPEND);
229         r1 = [p1];
230         [--sp] = r1;
231 #else
232         [--sp] = r0;    /* Skip IPEND as well. */
233 #endif
234         [--sp] = r0;  /*orig_pc*/
235         /* Clear all L registers.  */
236         r0 = 0 (x);
237         l0 = r0;
238         l1 = r0;
239         l2 = r0;
240         l3 = r0;
241 .endm
242
243 .macro restore_context_no_interrupts
244         sp += 4;        /* Skip orig_pc */
245         sp += 4;        /* Skip IPEND */
246         SEQSTAT = [sp++];
247         RETE = [sp++];
248         RETN = [sp++];
249         RETX = [sp++];
250         r0 = [sp++];
251         RETI = r0;      /* Restore RETI indirectly when in exception */
252         RETS = [sp++];
253
254         sp += 4;        /* Skip Reserved */
255
256         ASTAT = [sp++];
257
258         LB1 = [sp++];
259         LB0 = [sp++];
260         LT1 = [sp++];
261         LT0 = [sp++];
262         LC1 = [sp++];
263         LC0 = [sp++];
264
265         a1.w = [sp++];
266         a1.x = [sp++];
267         a0.w = [sp++];
268         a0.x = [sp++];
269         b3 = [sp++];
270         b2 = [sp++];
271         b1 = [sp++];
272         b0 = [sp++];
273
274         l3 = [sp++];
275         l2 = [sp++];
276         l1 = [sp++];
277         l0 = [sp++];
278
279         m3 = [sp++];
280         m2 = [sp++];
281         m1 = [sp++];
282         m0 = [sp++];
283
284         i3 = [sp++];
285         i2 = [sp++];
286         i1 = [sp++];
287         i0 = [sp++];
288
289         sp += 4;
290         fp = [sp++];
291
292         ( R7 : 0, P5 : 0) = [ SP ++ ];
293         sp += 8;        /* Skip orig_r0/orig_p0 */
294         SYSCFG = [sp++];
295 .endm
296
297 .macro restore_context_with_interrupts
298         sp += 4;        /* Skip orig_pc */
299         sp += 4;        /* Skip IPEND */
300         SEQSTAT = [sp++];
301         RETE = [sp++];
302         RETN = [sp++];
303         RETX = [sp++];
304         RETI = [sp++];
305         RETS = [sp++];
306
307 #ifdef CONFIG_SMP
308         GET_PDA(p0, r0);
309         r0 = [p0 + PDA_IRQFLAGS];
310 #else
311         p0.h = _bfin_irq_flags;
312         p0.l = _bfin_irq_flags;
313         r0 = [p0];
314 #endif
315         sti r0;
316
317         sp += 4;        /* Skip Reserved */
318
319         ASTAT = [sp++];
320
321         LB1 = [sp++];
322         LB0 = [sp++];
323         LT1 = [sp++];
324         LT0 = [sp++];
325         LC1 = [sp++];
326         LC0 = [sp++];
327
328         a1.w = [sp++];
329         a1.x = [sp++];
330         a0.w = [sp++];
331         a0.x = [sp++];
332         b3 = [sp++];
333         b2 = [sp++];
334         b1 = [sp++];
335         b0 = [sp++];
336
337         l3 = [sp++];
338         l2 = [sp++];
339         l1 = [sp++];
340         l0 = [sp++];
341
342         m3 = [sp++];
343         m2 = [sp++];
344         m1 = [sp++];
345         m0 = [sp++];
346
347         i3 = [sp++];
348         i2 = [sp++];
349         i1 = [sp++];
350         i0 = [sp++];
351
352         sp += 4;
353         fp = [sp++];
354
355         ( R7 : 0, P5 : 0) = [ SP ++ ];
356         sp += 8;        /* Skip orig_r0/orig_p0 */
357         csync;
358         SYSCFG = [sp++];
359         csync;
360 .endm
361
362 .macro save_context_cplb
363         [--sp] = (R7:0, P5:0);
364         [--sp] = fp;
365
366         [--sp] = a0.x;
367         [--sp] = a0.w;
368         [--sp] = a1.x;
369         [--sp] = a1.w;
370
371         [--sp] = LC0;
372         [--sp] = LC1;
373         [--sp] = LT0;
374         [--sp] = LT1;
375         [--sp] = LB0;
376         [--sp] = LB1;
377
378         [--sp] = RETS;
379 .endm
380
381 .macro restore_context_cplb
382         RETS = [sp++];
383
384         LB1 = [sp++];
385         LB0 = [sp++];
386         LT1 = [sp++];
387         LT0 = [sp++];
388         LC1 = [sp++];
389         LC0 = [sp++];
390
391         a1.w = [sp++];
392         a1.x = [sp++];
393         a0.w = [sp++];
394         a0.x = [sp++];
395
396         fp = [sp++];
397
398         (R7:0, P5:0) = [SP++];
399 .endm