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

4.104.11
Last change on this file since ff8dd26 was ff8dd26, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 27, 2010 at 2:59:26 PM

2010-03-27 Joel Sherrill <joel.sherrill@…>

  • Makefile.am: Remove unused file.
  • irq.c: Removed.
  • Property mode set to 100644
File size: 10.7 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 length registers */
259        r0 = l0;
260        [p0++] = r0;
261        r0 = l1;
262        [p0++] = r0;
263        r0 = l2;
264        [p0++] = r0;
265        r0 = l3;
266        [p0++] = r0;
267
268        /* save rets */
269        r0 = rets;
270        [p0++] = r0;
271
272        /* save IMASK */
273        p1.h = HI(IMASK);
274        p1.l = LO(IMASK);
275        r0 = [p1];
276        [p0++] = r0;
277
278        p0 = r1;
279restore:
280        /* restore data registers */
281        r4 = [p0++];
282        r5 = [p0++];
283        r6 = [p0++];
284        r7 = [p0++];
285
286        /* restore pointer registers */
287        p3 = [p0++];
288        p4 = [p0++];
289        p5 = [p0++];
290        fp = [p0++];
291        sp = [p0++];
292
293        /* restore length registers */
294        r0 = [p0++];
295        l0 = r0;
296        r0 = [p0++];
297        l1 = r0;
298        r0 = [p0++];
299        l2 = r0;
300        r0 = [p0++];
301        l3 = r0;
302
303        /* restore rets */
304        r0 = [p0++];
305        rets = r0;
306
307        /* restore IMASK */
308        r0 = [p0++];
309        p1.h = HI(IMASK);
310        p1.l = LO(IMASK);
311        [p1] = r0;
312
313        rts;
314
315
316/*
317 *  _CPU_Context_restore
318 *
319 *  This routine is generally used only to restart self in an
320 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
321 *
322 *  NOTE: May be unnecessary to reload some registers.
323 *
324 *  Blackfin Specific Information:
325 *
326 *  none
327 *
328 */
329        .globl __CPU_Context_restore
330__CPU_Context_restore:
331        p0 = r0;
332        jump restore;
333
334
335        .globl __ISR_Handler
336        .extern __CPU_Interrupt_stack_high;
337        .extern __ISR_Nest_level
338        .extern __Thread_Dispatch_disable_level
339        .extern __Context_Switch_necessary
340        .extern __ISR_Signals_to_thread_executing
341__ISR_Handler:
342        /* all interrupts are disabled at this point */
343        /* the following few items are pushed onto the task stack for at
344           most one interrupt; nested interrupts will be using the interrupt
345           stack for everything. */
346        [--sp] = astat;
347        [--sp] = p1;
348        [--sp] = p0;
349        [--sp] = r1;
350        [--sp] = r0;
351        p0.h = __ISR_Nest_level;
352        p0.l = __ISR_Nest_level;
353        r0 = [p0];
354        r0 += 1;
355        [p0] = r0;
356        cc = r0 <= 1 (iu);
357        if !cc jump noStackSwitch;
358        /* setup interrupt stack */
359        r0 = sp;
360        p0.h = __CPU_Interrupt_stack_high;
361        p0.l = __CPU_Interrupt_stack_high;
362        sp = [p0];
363        [--sp] = r0;
364noStackSwitch:
365        /* disable thread dispatch */
366        p0.h = __Thread_Dispatch_disable_level;
367        p0.l = __Thread_Dispatch_disable_level;
368        r0 = [p0];
369        r0 += 1;
370        [p0] = r0;
371
372        [--sp] = reti;  /* interrupts are now enabled */
373
374        /* figure out what vector we are */
375        p0.h = HI(IPEND);
376        p0.l = LO(IPEND);
377        r1 = [p0];
378        /* we should only get here for events that require RTI to return */
379        r1 = r1 >> 5;
380        r0 = 4;
381        /* at least one bit must be set, so this loop will exit */
382vectorIDLoop:
383        r0 += 1;
384        r1 = rot r1 by -1;
385        if !cc jump vectorIDLoop;
386
387        [--sp] = r2;
388        p0.h = __ISR_Vector_table;
389        p0.l = __ISR_Vector_table;
390        r2 = [p0];
391        r1 = r0 << 2;
392        r1 = r1 + r2;
393        p0 = r1;
394        p0 = [p0];
395        cc = p0 == 0;
396        if cc jump noHandler;
397
398        /* r2, r0, r1, p0, p1, astat are already saved */
399        [--sp] = a1.x;
400        [--sp] = a1.w;
401        [--sp] = a0.x;
402        [--sp] = a0.w;
403        [--sp] = r3;
404        [--sp] = p3;
405        [--sp] = p2;
406        [--sp] = lt1;
407        [--sp] = lt0;
408        [--sp] = lc1;
409        [--sp] = lc0;
410        [--sp] = lb1;
411        [--sp] = lb0;
412        [--sp] = i3;
413        [--sp] = i2;
414        [--sp] = i1;
415        [--sp] = i0;
416        [--sp] = m3;
417        [--sp] = m2;
418        [--sp] = m1;
419        [--sp] = m0;
420        [--sp] = l3;
421        [--sp] = l2;
422        [--sp] = l1;
423        [--sp] = l0;
424        [--sp] = b3;
425        [--sp] = b2;
426        [--sp] = b1;
427        [--sp] = b0;
428        [--sp] = rets;
429        r1 = fp; /* is this really what should be passed here? */
430        /* call user isr; r0 = vector number, r1 = frame pointer */
431        sp += -12; /* bizarre abi... */
432        call (p0);
433        sp += 12;
434        rets = [sp++];
435        b0 = [sp++];
436        b1 = [sp++];
437        b2 = [sp++];
438        b3 = [sp++];
439        l0 = [sp++];
440        l1 = [sp++];
441        l2 = [sp++];
442        l3 = [sp++];
443        m0 = [sp++];
444        m1 = [sp++];
445        m2 = [sp++];
446        m3 = [sp++];
447        i0 = [sp++];
448        i1 = [sp++];
449        i2 = [sp++];
450        i3 = [sp++];
451        lb0 = [sp++];
452        lb1 = [sp++];
453        lc0 = [sp++];
454        lc1 = [sp++];
455        lt0 = [sp++];
456        lt1 = [sp++];
457        p2 = [sp++];
458        p3 = [sp++];
459        r3 = [sp++];
460        a0.w = [sp++];
461        a0.x = [sp++];
462        a1.w = [sp++];
463        a1.x = [sp++];
464
465noHandler:
466        r2 = [sp++];
467        /* this disables interrupts again */
468        reti = [sp++];
469
470        p0.h = __ISR_Nest_level;
471        p0.l = __ISR_Nest_level;
472        r0 = [p0];
473        r0 += -1;
474        [p0] = r0;
475        cc = r0 == 0;
476        if !cc jump noStackRestore;
477        sp = [sp];
478noStackRestore:
479
480        /* check this stuff to ensure context_switch_necessary and
481           isr_signals_to_thread_executing are being handled appropriately. */
482        p0.h = __Thread_Dispatch_disable_level;
483        p0.l = __Thread_Dispatch_disable_level;
484        r0 = [p0];
485        r0 += -1;
486        [p0] = r0;
487        cc = r0 == 0;
488        if !cc jump noDispatch
489
490        /* do thread dispatch if necessary */
491        p0.h = __Context_Switch_necessary;
492        p0.l = __Context_Switch_necessary;
493        r0 = B[p0] (Z);
494        cc = r0 == 0;
495        p0.h = __ISR_Signals_to_thread_executing;
496        p0.l = __ISR_Signals_to_thread_executing;
497        if !cc jump doDispatch
498        r0 = B[p0] (Z);
499        cc = r0 == 0;
500        if cc jump noDispatch
501doDispatch:
502        r0 = 0;
503        B[p0] = r0;
504        raise 15;
505noDispatch:
506        r0 = [sp++];
507        r1 = [sp++];
508        p0 = [sp++];
509        p1 = [sp++];
510        astat = [sp++];
511        rti
512
513
514/* the approach here is for the main interrupt handler, when a dispatch is
515   wanted, to do a "raise 15".  when the main interrupt handler does its
516   "rti", the "raise 15" takes effect and we end up here.  we can now
517   safely call _Thread_Dispatch, and do an "rti" to get back to the
518   original interrupted function.  this does require self-nesting to be
519   enabled; the maximum nest depth is the number of tasks. */
520        .global __ISR15_Handler
521        .extern __Thread_Dispatch
522__ISR15_Handler:
523        [--sp] = reti;
524        [--sp] = rets;
525        [--sp] = astat;
526        [--sp] = a1.x;
527        [--sp] = a1.w;
528        [--sp] = a0.x;
529        [--sp] = a0.w;
530        [--sp] = r3;
531        [--sp] = r2;
532        [--sp] = r1;
533        [--sp] = r0;
534        [--sp] = p3;
535        [--sp] = p2;
536        [--sp] = p1;
537        [--sp] = p0;
538        [--sp] = lt1;
539        [--sp] = lt0;
540        [--sp] = lc1;
541        [--sp] = lc0;
542        [--sp] = lb1;
543        [--sp] = lb0;
544        [--sp] = i3;
545        [--sp] = i2;
546        [--sp] = i1;
547        [--sp] = i0;
548        [--sp] = m3;
549        [--sp] = m2;
550        [--sp] = m1;
551        [--sp] = m0;
552        [--sp] = l3;
553        [--sp] = l2;
554        [--sp] = l1;
555        [--sp] = l0;
556        [--sp] = b3;
557        [--sp] = b2;
558        [--sp] = b1;
559        [--sp] = b0;
560        sp += -12; /* bizarre abi... */
561        call __Thread_Dispatch;
562        sp += 12;
563        b0 = [sp++];
564        b1 = [sp++];
565        b2 = [sp++];
566        b3 = [sp++];
567        l0 = [sp++];
568        l1 = [sp++];
569        l2 = [sp++];
570        l3 = [sp++];
571        m0 = [sp++];
572        m1 = [sp++];
573        m2 = [sp++];
574        m3 = [sp++];
575        i0 = [sp++];
576        i1 = [sp++];
577        i2 = [sp++];
578        i3 = [sp++];
579        lb0 = [sp++];
580        lb1 = [sp++];
581        lc0 = [sp++];
582        lc1 = [sp++];
583        lt0 = [sp++];
584        lt1 = [sp++];
585        p0 = [sp++];
586        p1 = [sp++];
587        p2 = [sp++];
588        p3 = [sp++];
589        r0 = [sp++];
590        r1 = [sp++];
591        r2 = [sp++];
592        r3 = [sp++];
593        a0.w = [sp++];
594        a0.x = [sp++];
595        a1.w = [sp++];
596        a1.x = [sp++];
597        astat = [sp++];
598        rets = [sp++];
599        reti = [sp++];
600        rti;
601
Note: See TracBrowser for help on using the repository browser.