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

4.104.114.9
Last change on this file since 4daebbd was 4daebbd, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 14, 2008 at 3:25:14 PM

2008-08-14 Sebastian Huber <sebastian.huber@…>

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