source: rtems/cpukit/score/cpu/bfin/cpu_asm.S @ 25ddacd

4.104.115
Last change on this file since 25ddacd was dace69bf, checked in by Joel Sherrill <joel.sherrill@…>, on 04/17/10 at 19:24:16

2010-04-17 Allan Hessenflow <allanh@…>

  • cpu.c, cpu_asm.S, rtems/score/cpu.h: Fine tune registers saved in the context. The sp and imask registers need to be saved. Also allocated 12 bytes on the stack at thread entry as the abi requires that.
  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*  cpu_asm.S
2 *
3 *  This file contains the basic algorithms for all assembly code used
4 *  in the Blackfin port of RTEMS.  These algorithms must be implemented
5 *  in assembly language
6 *
7 *  Copyright (c) 2008 Kallisti Labs, Los Gatos, CA, USA
8 *             written by Allan Hessenflow <allanh@kallisti.com>
9 *
10 *  Based on earlier version:
11 *
12 *  Copyright (c) 2006 by Atos Automacao Industrial Ltda.
13 *             written by Alain Schaefer <alain.schaefer@easc.ch>
14 *                     and Antonio Giovanini <antonio@atos.com.br>
15 *
16 *  The license and distribution terms for this file may be
17 *  found in the file LICENSE in this distribution or at
18 *  http://www.rtems.com/license/LICENSE.
19 *
20 *  $Id$
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <rtems/asm.h>
28#include <rtems/score/cpu_asm.h>
29#include <rtems/score/bfin.h>
30#include <rtems/bfin/bfin.h>
31
32#define LO(con32) ((con32) & 0xFFFF)
33#define HI(con32) (((con32) >> 16) & 0xFFFF)
34
35
36#if 0
37/* some debug routines */
38        .globl __CPU_write_char;
39__CPU_write_char:
40        p0.h = 0xffc0;
41        p0.l = 0x0400;
42txWaitLoop:
43        r1 = w[p0 + 0x14];
44        cc = bittst(r1, 5);
45        if !cc jump txWaitLoop;
46        w[p0 + 0x00] = r0;
47        rts;
48
49        .globl __CPU_write_crlf;
50__CPU_write_crlf:
51        r0 = '\r';
52        [--sp] = rets;
53        call __CPU_write_char;
54        rets = [sp++];
55        r0 = '\n';
56        jump __CPU_write_char;
57
58__CPU_write_space:
59        r0 = ' ';
60        jump __CPU_write_char;
61
62        .globl __CPU_write_nybble;
63__CPU_write_nybble:
64        r1 = 0x0f;
65        r0 = r0 & r1;
66        r0 += '0';
67        r1 = '9';
68        cc = r0 <= r1;
69        if cc jump __CPU_write_char;
70        r0 += 'a' - '0' - 10;
71        jump __CPU_write_char;
72
73        .globl __CPU_write_byte;
74__CPU_write_byte:
75        [--sp] = r0;
76        [--sp] = rets;
77        r0 >>= 4;
78        call __CPU_write_nybble;
79        rets = [sp++];
80        r0 = [sp++];
81        jump __CPU_write_nybble;
82
83__CPU_write_chawmp:
84        [--sp] = r0;
85        [--sp] = rets;
86        r0 >>= 8;
87        call __CPU_write_byte;
88        rets = [sp++];
89        r0 = [sp++];
90        jump __CPU_write_byte;
91
92__CPU_write_gawble:
93        [--sp] = r0;
94        [--sp] = rets;
95        r0 >>= 16;
96        call __CPU_write_chawmp;
97        rets = [sp++];
98        r0 = [sp++];
99        jump __CPU_write_chawmp;
100
101__CPU_dump_registers:
102        [--sp] = rets;
103        [--sp] = r0;
104        [--sp] = r1;
105        [--sp] = p0;
106        r0 = [sp + 8];
107        call __CPU_write_gawble;
108        call __CPU_write_space;
109        r0 = [sp + 4];
110        call __CPU_write_gawble;
111        call __CPU_write_space;
112        r0 = r2;
113        call __CPU_write_gawble;
114        call __CPU_write_space;
115        r0 = r3;
116        call __CPU_write_gawble;
117        call __CPU_write_space;
118        r0 = r4;
119        call __CPU_write_gawble;
120        call __CPU_write_space;
121        r0 = r5;
122        call __CPU_write_gawble;
123        call __CPU_write_space;
124        r0 = r6;
125        call __CPU_write_gawble;
126        call __CPU_write_space;
127        r0 = r7;
128        call __CPU_write_gawble;
129        call __CPU_write_crlf;
130        r0 = [sp];
131        call __CPU_write_gawble;
132        call __CPU_write_space;
133        r0 = p1;
134        call __CPU_write_gawble;
135        call __CPU_write_space;
136        r0 = p2;
137        call __CPU_write_gawble;
138        call __CPU_write_space;
139        r0 = p3;
140        call __CPU_write_gawble;
141        call __CPU_write_space;
142        r0 = p4;
143        call __CPU_write_gawble;
144        call __CPU_write_space;
145        r0 = p5;
146        call __CPU_write_gawble;
147        call __CPU_write_space;
148        r0 = fp;
149        call __CPU_write_gawble;
150        call __CPU_write_space;
151        r0 = sp;
152        r0 += 16;
153        call __CPU_write_gawble;
154        call __CPU_write_crlf;
155
156        p0 = [sp++];
157        r1 = [sp++];
158        r0 = [sp++];
159        rets = [sp++];
160        rts;
161
162        .globl __CPU_Exception_handler;
163__CPU_Exception_handler:
164        usp = sp;
165        sp.h = 0xffb0;
166        sp.l = 0x1000;
167        [--sp] = (r7:0,p5:0);
168
169        r0 = 'x';
170        call __CPU_write_char;
171        jump hcf;
172
173
174        .globl __CPU_Emulation_handler;
175__CPU_Emulation_handler:
176        usp = sp;
177        sp.h = 0xffb0;
178        sp.l = 0x1000;
179        [--sp] = (r7:0,p5:0);
180
181        r0 = 'e';
182        call __CPU_write_char;
183        jump hcf;
184
185        .globl __CPU_Reset_handler;
186__CPU_Reset_handler:
187        usp = sp;
188        sp.h = 0xffb0;
189        sp.l = 0x1000;
190        [--sp] = (r7:0,p5:0);
191
192        r0 = 'r';
193        call __CPU_write_char;
194        jump hcf;
195
196        .globl __CPU_NMI_handler;
197__CPU_NMI_handler:
198        usp = sp;
199        sp.h = 0xffb0;
200        sp.l = 0x1000;
201        [--sp] = (r7:0,p5:0);
202
203        r0 = 'n';
204        call __CPU_write_char;
205        jump hcf;
206
207        .globl __CPU_Unhandled_Interrupt_handler;
208__CPU_Unhandled_Interrupt_handler:
209        usp = sp;
210        sp.h = 0xffb0;
211        sp.l = 0x1000;
212        [--sp] = (r7:0,p5:0);
213
214        call __CPU_write_crlf;
215        r0 = 'i';
216        call __CPU_write_char;
217        p0.h = HI(IPEND);
218        p0.l = LO(IPEND);
219        r0 = [p0];
220        call __CPU_write_chawmp;
221        jump hcf;
222
223hcf:
224        idle;
225        jump hcf;
226
227#endif
228
229
230/*  _CPU_Context_switch
231 *
232 *  This routine performs a normal non-FP context switch.
233 *
234 *  bfin Specific Information:
235 *
236 *  For now we simply save all registers.
237 *
238 */
239
240/* make sure this sequence stays in sync with the definition for
241   Context_Control in rtems/score/cpu.h */
242        .globl __CPU_Context_switch
243__CPU_Context_switch:
244        /* Start saving context R0 = current, R1=heir */
245        p0 = r0;
246        [p0++] = r4;
247        [p0++] = r5;
248        [p0++] = r6;
249        [p0++] = r7;
250
251        /* save pointer registers */
252        [p0++] = p3;
253        [p0++] = p4;
254        [p0++] = p5;
255        [p0++] = fp;
256        [p0++] = sp;
257
258        /* save rets */
259        r0 = rets;
260        [p0++] = r0;
261
262        /* save IMASK */
263        p1.h = HI(IMASK);
264        p1.l = LO(IMASK);
265        r0 = [p1];
266        [p0++] = r0;
267
268        p0 = r1;
269restore:
270        /* restore data registers */
271        r4 = [p0++];
272        r5 = [p0++];
273        r6 = [p0++];
274        r7 = [p0++];
275
276        /* restore pointer registers */
277        p3 = [p0++];
278        p4 = [p0++];
279        p5 = [p0++];
280        fp = [p0++];
281        sp = [p0++];
282
283        /* restore rets */
284        r0 = [p0++];
285        rets = r0;
286
287        /* restore IMASK */
288        r0 = [p0++];
289        p1.h = HI(IMASK);
290        p1.l = LO(IMASK);
291        [p1] = r0;
292
293        rts;
294
295
296/*
297 *  _CPU_Context_restore
298 *
299 *  This routine is generally used only to restart self in an
300 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
301 *
302 *  NOTE: May be unnecessary to reload some registers.
303 *
304 *  Blackfin Specific Information:
305 *
306 *  none
307 *
308 */
309        .globl __CPU_Context_restore
310__CPU_Context_restore:
311        p0 = r0;
312        jump restore;
313
314
315        .globl __ISR_Handler
316        .extern __CPU_Interrupt_stack_high;
317        .extern __ISR_Nest_level
318        .extern __Thread_Dispatch_disable_level
319        .extern __Context_Switch_necessary
320        .extern __ISR_Signals_to_thread_executing
321__ISR_Handler:
322        /* all interrupts are disabled at this point */
323        /* the following few items are pushed onto the task stack for at
324           most one interrupt; nested interrupts will be using the interrupt
325           stack for everything. */
326        [--sp] = astat;
327        [--sp] = p1;
328        [--sp] = p0;
329        [--sp] = r1;
330        [--sp] = r0;
331        p0.h = __ISR_Nest_level;
332        p0.l = __ISR_Nest_level;
333        r0 = [p0];
334        r0 += 1;
335        [p0] = r0;
336        cc = r0 <= 1 (iu);
337        if !cc jump noStackSwitch;
338        /* setup interrupt stack */
339        r0 = sp;
340        p0.h = __CPU_Interrupt_stack_high;
341        p0.l = __CPU_Interrupt_stack_high;
342        sp = [p0];
343        [--sp] = r0;
344noStackSwitch:
345        /* disable thread dispatch */
346        p0.h = __Thread_Dispatch_disable_level;
347        p0.l = __Thread_Dispatch_disable_level;
348        r0 = [p0];
349        r0 += 1;
350        [p0] = r0;
351
352        [--sp] = reti;  /* interrupts are now enabled */
353
354        /* figure out what vector we are */
355        p0.h = HI(IPEND);
356        p0.l = LO(IPEND);
357        r1 = [p0];
358        /* we should only get here for events that require RTI to return */
359        r1 = r1 >> 5;
360        r0 = 4;
361        /* at least one bit must be set, so this loop will exit */
362vectorIDLoop:
363        r0 += 1;
364        r1 = rot r1 by -1;
365        if !cc jump vectorIDLoop;
366
367        [--sp] = r2;
368        p0.h = __ISR_Vector_table;
369        p0.l = __ISR_Vector_table;
370        r2 = [p0];
371        r1 = r0 << 2;
372        r1 = r1 + r2;
373        p0 = r1;
374        p0 = [p0];
375        cc = p0 == 0;
376        if cc jump noHandler;
377
378        /* r2, r0, r1, p0, p1, astat are already saved */
379        [--sp] = a1.x;
380        [--sp] = a1.w;
381        [--sp] = a0.x;
382        [--sp] = a0.w;
383        [--sp] = r3;
384        [--sp] = p3;
385        [--sp] = p2;
386        [--sp] = lt1;
387        [--sp] = lt0;
388        [--sp] = lc1;
389        [--sp] = lc0;
390        [--sp] = lb1;
391        [--sp] = lb0;
392        [--sp] = i3;
393        [--sp] = i2;
394        [--sp] = i1;
395        [--sp] = i0;
396        [--sp] = m3;
397        [--sp] = m2;
398        [--sp] = m1;
399        [--sp] = m0;
400        [--sp] = l3;
401        [--sp] = l2;
402        [--sp] = l1;
403        [--sp] = l0;
404        [--sp] = b3;
405        [--sp] = b2;
406        [--sp] = b1;
407        [--sp] = b0;
408        [--sp] = rets;
409        r1 = fp; /* is this really what should be passed here? */
410        /* call user isr; r0 = vector number, r1 = frame pointer */
411        sp += -12; /* bizarre abi... */
412        call (p0);
413        sp += 12;
414        rets = [sp++];
415        b0 = [sp++];
416        b1 = [sp++];
417        b2 = [sp++];
418        b3 = [sp++];
419        l0 = [sp++];
420        l1 = [sp++];
421        l2 = [sp++];
422        l3 = [sp++];
423        m0 = [sp++];
424        m1 = [sp++];
425        m2 = [sp++];
426        m3 = [sp++];
427        i0 = [sp++];
428        i1 = [sp++];
429        i2 = [sp++];
430        i3 = [sp++];
431        lb0 = [sp++];
432        lb1 = [sp++];
433        lc0 = [sp++];
434        lc1 = [sp++];
435        lt0 = [sp++];
436        lt1 = [sp++];
437        p2 = [sp++];
438        p3 = [sp++];
439        r3 = [sp++];
440        a0.w = [sp++];
441        a0.x = [sp++];
442        a1.w = [sp++];
443        a1.x = [sp++];
444
445noHandler:
446        r2 = [sp++];
447        /* this disables interrupts again */
448        reti = [sp++];
449
450        p0.h = __ISR_Nest_level;
451        p0.l = __ISR_Nest_level;
452        r0 = [p0];
453        r0 += -1;
454        [p0] = r0;
455        cc = r0 == 0;
456        if !cc jump noStackRestore;
457        sp = [sp];
458noStackRestore:
459
460        /* check this stuff to ensure context_switch_necessary and
461           isr_signals_to_thread_executing are being handled appropriately. */
462        p0.h = __Thread_Dispatch_disable_level;
463        p0.l = __Thread_Dispatch_disable_level;
464        r0 = [p0];
465        r0 += -1;
466        [p0] = r0;
467        cc = r0 == 0;
468        if !cc jump noDispatch
469
470        /* do thread dispatch if necessary */
471        p0.h = __Context_Switch_necessary;
472        p0.l = __Context_Switch_necessary;
473        r0 = B[p0] (Z);
474        cc = r0 == 0;
475        p0.h = __ISR_Signals_to_thread_executing;
476        p0.l = __ISR_Signals_to_thread_executing;
477        if !cc jump doDispatch
478        r0 = B[p0] (Z);
479        cc = r0 == 0;
480        if cc jump noDispatch
481doDispatch:
482        r0 = 0;
483        B[p0] = r0;
484        raise 15;
485noDispatch:
486        r0 = [sp++];
487        r1 = [sp++];
488        p0 = [sp++];
489        p1 = [sp++];
490        astat = [sp++];
491        rti
492
493
494/* the approach here is for the main interrupt handler, when a dispatch is
495   wanted, to do a "raise 15".  when the main interrupt handler does its
496   "rti", the "raise 15" takes effect and we end up here.  we can now
497   safely call _Thread_Dispatch, and do an "rti" to get back to the
498   original interrupted function.  this does require self-nesting to be
499   enabled; the maximum nest depth is the number of tasks. */
500        .global __ISR15_Handler
501        .extern __Thread_Dispatch
502__ISR15_Handler:
503        [--sp] = reti;
504        [--sp] = rets;
505        [--sp] = astat;
506        [--sp] = a1.x;
507        [--sp] = a1.w;
508        [--sp] = a0.x;
509        [--sp] = a0.w;
510        [--sp] = r3;
511        [--sp] = r2;
512        [--sp] = r1;
513        [--sp] = r0;
514        [--sp] = p3;
515        [--sp] = p2;
516        [--sp] = p1;
517        [--sp] = p0;
518        [--sp] = lt1;
519        [--sp] = lt0;
520        [--sp] = lc1;
521        [--sp] = lc0;
522        [--sp] = lb1;
523        [--sp] = lb0;
524        [--sp] = i3;
525        [--sp] = i2;
526        [--sp] = i1;
527        [--sp] = i0;
528        [--sp] = m3;
529        [--sp] = m2;
530        [--sp] = m1;
531        [--sp] = m0;
532        [--sp] = l3;
533        [--sp] = l2;
534        [--sp] = l1;
535        [--sp] = l0;
536        [--sp] = b3;
537        [--sp] = b2;
538        [--sp] = b1;
539        [--sp] = b0;
540        sp += -12; /* bizarre abi... */
541        call __Thread_Dispatch;
542        sp += 12;
543        b0 = [sp++];
544        b1 = [sp++];
545        b2 = [sp++];
546        b3 = [sp++];
547        l0 = [sp++];
548        l1 = [sp++];
549        l2 = [sp++];
550        l3 = [sp++];
551        m0 = [sp++];
552        m1 = [sp++];
553        m2 = [sp++];
554        m3 = [sp++];
555        i0 = [sp++];
556        i1 = [sp++];
557        i2 = [sp++];
558        i3 = [sp++];
559        lb0 = [sp++];
560        lb1 = [sp++];
561        lc0 = [sp++];
562        lc1 = [sp++];
563        lt0 = [sp++];
564        lt1 = [sp++];
565        p0 = [sp++];
566        p1 = [sp++];
567        p2 = [sp++];
568        p3 = [sp++];
569        r0 = [sp++];
570        r1 = [sp++];
571        r2 = [sp++];
572        r3 = [sp++];
573        a0.w = [sp++];
574        a0.x = [sp++];
575        a1.w = [sp++];
576        a1.x = [sp++];
577        astat = [sp++];
578        rets = [sp++];
579        reti = [sp++];
580        rti;
581
Note: See TracBrowser for help on using the repository browser.