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

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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