9ce21f68e91406420ef854eb33de490c701c8979
[linux-2.6.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_KGDB
227         r1.l = lo(IPEND);
228         r1.h = hi(IPEND);
229         [--sp] = r1;
230 #else
231         [--sp] = r0;    /* Skip IPEND as well. */
232 #endif
233         [--sp] = r0;  /*orig_pc*/
234         /* Clear all L registers.  */
235         r0 = 0 (x);
236         l0 = r0;
237         l1 = r0;
238         l2 = r0;
239         l3 = r0;
240 .endm
241
242 .macro restore_context_no_interrupts
243         sp += 4;        /* Skip orig_pc */
244         sp += 4;        /* Skip IPEND */
245         SEQSTAT = [sp++];
246         RETE = [sp++];
247         RETN = [sp++];
248         RETX = [sp++];
249         r0 = [sp++];
250         RETI = r0;      /* Restore RETI indirectly when in exception */
251         RETS = [sp++];
252
253         sp += 4;        /* Skip Reserved */
254
255         ASTAT = [sp++];
256
257         LB1 = [sp++];
258         LB0 = [sp++];
259         LT1 = [sp++];
260         LT0 = [sp++];
261         LC1 = [sp++];
262         LC0 = [sp++];
263
264         a1.w = [sp++];
265         a1.x = [sp++];
266         a0.w = [sp++];
267         a0.x = [sp++];
268         b3 = [sp++];
269         b2 = [sp++];
270         b1 = [sp++];
271         b0 = [sp++];
272
273         l3 = [sp++];
274         l2 = [sp++];
275         l1 = [sp++];
276         l0 = [sp++];
277
278         m3 = [sp++];
279         m2 = [sp++];
280         m1 = [sp++];
281         m0 = [sp++];
282
283         i3 = [sp++];
284         i2 = [sp++];
285         i1 = [sp++];
286         i0 = [sp++];
287
288         sp += 4;
289         fp = [sp++];
290
291         ( R7 : 0, P5 : 0) = [ SP ++ ];
292         sp += 8;        /* Skip orig_r0/orig_p0 */
293         SYSCFG = [sp++];
294 .endm
295
296 .macro restore_context_with_interrupts
297         sp += 4;        /* Skip orig_pc */
298         sp += 4;        /* Skip IPEND */
299         SEQSTAT = [sp++];
300         RETE = [sp++];
301         RETN = [sp++];
302         RETX = [sp++];
303         RETI = [sp++];
304         RETS = [sp++];
305
306 #ifdef CONFIG_SMP
307         GET_PDA(p0, r0);
308         r0 = [p0 + PDA_IRQFLAGS];
309 #else
310         p0.h = _bfin_irq_flags;
311         p0.l = _bfin_irq_flags;
312         r0 = [p0];
313 #endif
314         sti r0;
315
316         sp += 4;        /* Skip Reserved */
317
318         ASTAT = [sp++];
319
320         LB1 = [sp++];
321         LB0 = [sp++];
322         LT1 = [sp++];
323         LT0 = [sp++];
324         LC1 = [sp++];
325         LC0 = [sp++];
326
327         a1.w = [sp++];
328         a1.x = [sp++];
329         a0.w = [sp++];
330         a0.x = [sp++];
331         b3 = [sp++];
332         b2 = [sp++];
333         b1 = [sp++];
334         b0 = [sp++];
335
336         l3 = [sp++];
337         l2 = [sp++];
338         l1 = [sp++];
339         l0 = [sp++];
340
341         m3 = [sp++];
342         m2 = [sp++];
343         m1 = [sp++];
344         m0 = [sp++];
345
346         i3 = [sp++];
347         i2 = [sp++];
348         i1 = [sp++];
349         i0 = [sp++];
350
351         sp += 4;
352         fp = [sp++];
353
354         ( R7 : 0, P5 : 0) = [ SP ++ ];
355         sp += 8;        /* Skip orig_r0/orig_p0 */
356         csync;
357         SYSCFG = [sp++];
358         csync;
359 .endm