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

4.115
Last change on this file since d5ec0480 was d5ec0480, checked in by Joel Sherrill <joel.sherrill@…>, on 06/16/10 at 17:19:31

2010-06-16 Joel Sherrill <joel.sherrilL@…>

  • cpu_asm.S: Use SYM macro to be consistent with other ports.
  • Property mode set to 100644
File size: 11.0 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 SYM(_CPU_write_char);
39SYM(_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 SYM(_CPU_write_crlf);
50SYM(_CPU_write_crlf):
51        r0 = '\r';
52        [--sp] = rets;
53        call SYM(_CPU_write_char);
54        rets = [sp++];
55        r0 = '\n';
56        jump SYM(_CPU_write_char);
57
58SYM(_CPU_write_space):
59        r0 = ' ';
60        jump SYM(_CPU_write_char);
61
62        .globl SYM(_CPU_write_nybble);
63SYM(_CPU_write_nybble:)
64        r1 = 0x0f;
65        r0 = r0 & r1;
66        r0 += '0';
67        r1 = '9';
68        cc = r0 <= r1;
69        if cc jump SYM(_CPU_write_char);
70        r0 += 'a' - '0' - 10;
71        jump SYM(_CPU_write_char);
72
73        .globl SYM(_CPU_write_byte);
74SYM(_CPU_write_byte):
75        [--sp] = r0;
76        [--sp] = rets;
77        r0 >>= 4;
78        call SYM(_CPU_write_nybble);
79        rets = [sp++];
80        r0 = [sp++];
81        jump SYM(_CPU_write_nybble);
82
83SYM(_CPU_write_chawmp):
84        [--sp] = r0;
85        [--sp] = rets;
86        r0 >>= 8;
87        call SYM(_CPU_write_byte);
88        rets = [sp++];
89        r0 = [sp++];
90        jump SYM(_CPU_write_byte);
91
92SYM(_CPU_write_gawble):
93        [--sp] = r0;
94        [--sp] = rets;
95        r0 >>= 16;
96        call SYM(_CPU_write_chawmp);
97        rets = [sp++];
98        r0 = [sp++];
99        jump SYM(_CPU_write_chawmp);
100
101SYM(_CPU_dump_registers):
102        [--sp] = rets;
103        [--sp] = r0;
104        [--sp] = r1;
105        [--sp] = p0;
106        r0 = [sp + 8];
107        call SYM(_CPU_write_gawble);
108        call SYM(_CPU_write_space);
109        r0 = [sp + 4];
110        call SYM(_CPU_write_gawble);
111        call SYM(_CPU_write_space);
112        r0 = r2;
113        call SYM(_CPU_write_gawble);
114        call SYM(_CPU_write_space);
115        r0 = r3;
116        call SYM(_CPU_write_gawble);
117        call SYM(_CPU_write_space);
118        r0 = r4;
119        call SYM(_CPU_write_gawble);
120        call SYM(_CPU_write_space);
121        r0 = r5;
122        call SYM(_CPU_write_gawble);
123        call SYM(_CPU_write_space);
124        r0 = r6;
125        call SYM(_CPU_write_gawble);
126        call SYM(_CPU_write_space);
127        r0 = r7;
128        call SYM(_CPU_write_gawble);
129        call SYM(_CPU_write_crlf);
130        r0 = [sp];
131        call SYM(_CPU_write_gawble);
132        call SYM(_CPU_write_space);
133        r0 = p1;
134        call SYM(_CPU_write_gawble);
135        call SYM(_CPU_write_space);
136        r0 = p2;
137        call SYM(_CPU_write_gawble);
138        call SYM(_CPU_write_space);
139        r0 = p3;
140        call SYM(_CPU_write_gawble);
141        call SYM(_CPU_write_space);
142        r0 = p4;
143        call SYM(_CPU_write_gawble);
144        call SYM(_CPU_write_space);
145        r0 = p5;
146        call SYM(_CPU_write_gawble);
147        call SYM(_CPU_write_space);
148        r0 = fp;
149        call SYM(_CPU_write_gawble);
150        call SYM(_CPU_write_space);
151        r0 = sp;
152        r0 += 16;
153        call SYM(_CPU_write_gawble);
154        call SYM(_CPU_write_crlf);
155
156        p0 = [sp++];
157        r1 = [sp++];
158        r0 = [sp++];
159        rets = [sp++];
160        rts;
161
162        .globl SYM(_CPU_Exception_handler);
163SYM(_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 SYM(_CPU_write_char);
171        jump hcf;
172
173
174        .globl SYM(_CPU_Emulation_handler);
175SYM(_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 SYM(_CPU_write_char);
183        jump hcf;
184
185        .globl SYM(_CPU_Reset_handler);
186SYM(_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 SYM(_CPU_write_char);
194        jump hcf;
195
196        .globl SYM(_CPU_NMI_handler);
197SYM(_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 SYM(_CPU_write_char);
205        jump hcf;
206
207        .globl SYM(_CPU_Unhandled_Interrupt_handler);
208SYM(_CPU_Unhandled_Interrupt_handler):
209        usp = sp;
210        sp.h = 0xffb0;
211        sp.l = 0x1000;
212        [--sp] = (r7:0,p5:0);
213
214        call SYM(_CPU_write_crlf);
215        r0 = 'i';
216        call SYM(_CPU_write_char);
217        p0.h = HI(IPEND);
218        p0.l = LO(IPEND);
219        r0 = [p0];
220        call SYM(_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 SYM(_CPU_Context_switch)
243SYM(_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 SYM(_CPU_Context_restore)
310SYM(_CPU_Context_restore):
311        p0 = r0;
312        jump restore;
313
314
315        .globl SYM(_ISR_Handler)
316        .extern SYM(_CPU_Interrupt_stack_high)
317        .extern SYM(_ISR_Nest_level)
318        .extern SYM(_Thread_Dispatch_disable_level)
319        .extern SYM(_Context_Switch_necessary)
320        .extern SYM(_ISR_Signals_to_thread_executing)
321SYM(_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 = SYM(_ISR_Nest_level);
332        p0.l = SYM(_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 = SYM(_CPU_Interrupt_stack_high);
341        p0.l = SYM(_CPU_Interrupt_stack_high);
342        sp = [p0];
343        [--sp] = r0;
344noStackSwitch:
345        /* disable thread dispatch */
346        p0.h = SYM(_Thread_Dispatch_disable_level);
347        p0.l = SYM(_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 = SYM(_ISR_Vector_table);
369        p0.l = SYM(_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] = lc1;
387        [--sp] = lc0;
388        [--sp] = lt1;
389        [--sp] = lt0;
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        /* call user isr; r0 = vector number, r1 = frame pointer */
410        r1 = fp; /* is this really what should be passed here? */
411        r2 = 0;
412        l0 = r2;
413        l1 = r2;
414        l2 = r2;
415        l3 = r2;
416        sp += -12; /* bizarre abi... */
417        call (p0);
418        sp += 12;
419        rets = [sp++];
420        b0 = [sp++];
421        b1 = [sp++];
422        b2 = [sp++];
423        b3 = [sp++];
424        l0 = [sp++];
425        l1 = [sp++];
426        l2 = [sp++];
427        l3 = [sp++];
428        m0 = [sp++];
429        m1 = [sp++];
430        m2 = [sp++];
431        m3 = [sp++];
432        i0 = [sp++];
433        i1 = [sp++];
434        i2 = [sp++];
435        i3 = [sp++];
436        lb0 = [sp++];
437        lb1 = [sp++];
438        lt0 = [sp++];
439        lt1 = [sp++];
440        lc0 = [sp++];
441        lc1 = [sp++];
442        p2 = [sp++];
443        p3 = [sp++];
444        r3 = [sp++];
445        a0.w = [sp++];
446        a0.x = [sp++];
447        a1.w = [sp++];
448        a1.x = [sp++];
449
450noHandler:
451        r2 = [sp++];
452        /* this disables interrupts again */
453        reti = [sp++];
454
455        p0.h = SYM(_ISR_Nest_level);
456        p0.l = SYM(_ISR_Nest_level);
457        r0 = [p0];
458        r0 += -1;
459        [p0] = r0;
460        cc = r0 == 0;
461        if !cc jump noStackRestore;
462        sp = [sp];
463noStackRestore:
464
465        /* check this stuff to ensure context_switch_necessary and
466           isr_signals_to_thread_executing are being handled appropriately. */
467        p0.h = SYM(_Thread_Dispatch_disable_level);
468        p0.l = SYM(_Thread_Dispatch_disable_level);
469        r0 = [p0];
470        r0 += -1;
471        [p0] = r0;
472        cc = r0 == 0;
473        if !cc jump noDispatch
474
475        /* do thread dispatch if necessary */
476        p0.h = SYM(_Context_Switch_necessary);
477        p0.l = SYM(_Context_Switch_necessary);
478        r0 = B[p0] (Z);
479        cc = r0 == 0;
480        p0.h = SYM(_ISR_Signals_to_thread_executing);
481        p0.l = SYM(_ISR_Signals_to_thread_executing);
482        if !cc jump doDispatch
483        r0 = B[p0] (Z);
484        cc = r0 == 0;
485        if cc jump noDispatch
486doDispatch:
487        r0 = 0;
488        B[p0] = r0;
489        raise 15;
490noDispatch:
491        r0 = [sp++];
492        r1 = [sp++];
493        p0 = [sp++];
494        p1 = [sp++];
495        astat = [sp++];
496        rti
497
498
499/* the approach here is for the main interrupt handler, when a dispatch is
500   wanted, to do a "raise 15".  when the main interrupt handler does its
501   "rti", the "raise 15" takes effect and we end up here.  we can now
502   safely call _Thread_Dispatch, and do an "rti" to get back to the
503   original interrupted function.  this does require self-nesting to be
504   enabled; the maximum nest depth is the number of tasks. */
505        .global SYM(_ISR15_Handler)
506SYM(_ISR15_Handler):
507        [--sp] = reti;
508        [--sp] = rets;
509        [--sp] = astat;
510        [--sp] = a1.x;
511        [--sp] = a1.w;
512        [--sp] = a0.x;
513        [--sp] = a0.w;
514        [--sp] = r3;
515        [--sp] = r2;
516        [--sp] = r1;
517        [--sp] = r0;
518        [--sp] = p3;
519        [--sp] = p2;
520        [--sp] = p1;
521        [--sp] = p0;
522        [--sp] = lc1;
523        [--sp] = lc0;
524        [--sp] = lt1;
525        [--sp] = lt0;
526        [--sp] = lb1;
527        [--sp] = lb0;
528        [--sp] = i3;
529        [--sp] = i2;
530        [--sp] = i1;
531        [--sp] = i0;
532        [--sp] = m3;
533        [--sp] = m2;
534        [--sp] = m1;
535        [--sp] = m0;
536        [--sp] = l3;
537        [--sp] = l2;
538        [--sp] = l1;
539        [--sp] = l0;
540        [--sp] = b3;
541        [--sp] = b2;
542        [--sp] = b1;
543        [--sp] = b0;
544        r2 = 0;
545        l0 = r2;
546        l1 = r2;
547        l2 = r2;
548        l3 = r2;
549        sp += -12; /* bizarre abi... */
550        call SYM(_Thread_Dispatch);
551        sp += 12;
552        b0 = [sp++];
553        b1 = [sp++];
554        b2 = [sp++];
555        b3 = [sp++];
556        l0 = [sp++];
557        l1 = [sp++];
558        l2 = [sp++];
559        l3 = [sp++];
560        m0 = [sp++];
561        m1 = [sp++];
562        m2 = [sp++];
563        m3 = [sp++];
564        i0 = [sp++];
565        i1 = [sp++];
566        i2 = [sp++];
567        i3 = [sp++];
568        lb0 = [sp++];
569        lb1 = [sp++];
570        lt0 = [sp++];
571        lt1 = [sp++];
572        lc0 = [sp++];
573        lc1 = [sp++];
574        p0 = [sp++];
575        p1 = [sp++];
576        p2 = [sp++];
577        p3 = [sp++];
578        r0 = [sp++];
579        r1 = [sp++];
580        r2 = [sp++];
581        r3 = [sp++];
582        a0.w = [sp++];
583        a0.x = [sp++];
584        a1.w = [sp++];
585        a1.x = [sp++];
586        astat = [sp++];
587        rets = [sp++];
588        reti = [sp++];
589        rti;
590
Note: See TracBrowser for help on using the repository browser.