Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:24

0001 /*  cpu_asm.S
0002  *
0003  *  This file contains the basic algorithms for all assembly code used
0004  *  in the Blackfin port of RTEMS.  These algorithms must be implemented
0005  *  in assembly language
0006  *
0007  *  Copyright (c) 2008 Kallisti Labs, Los Gatos, CA, USA
0008  *             written by Allan Hessenflow <allanh@kallisti.com>
0009  *
0010  *  Based on earlier version:
0011  *
0012  *  Copyright (c) 2006 by Atos Automacao Industrial Ltda.
0013  *             written by Alain Schaefer <alain.schaefer@easc.ch>
0014  *                     and Antonio Giovanini <antonio@atos.com.br>
0015  *
0016  *  The license and distribution terms for this file may be
0017  *  found in the file LICENSE in this distribution or at
0018  *  http://www.rtems.org/license/LICENSE.
0019  */
0020 
0021 #ifdef HAVE_CONFIG_H
0022 #include "config.h"
0023 #endif
0024 
0025 #include <rtems/asm.h>
0026 #include <rtems/score/cpu_asm.h>
0027 #include <rtems/score/bfin.h>
0028 #include <rtems/bfin/bfin.h>
0029 #include <rtems/score/percpu.h>
0030 
0031 #define LO(con32) ((con32) & 0xFFFF)
0032 #define HI(con32) (((con32) >> 16) & 0xFFFF)
0033 
0034 
0035 #if 0
0036 /* some debug routines */
0037     .globl SYM(_CPU_write_char);
0038 SYM(_CPU_write_char):
0039     p0.h = 0xffc0;
0040     p0.l = 0x0400;
0041 txWaitLoop:
0042     r1 = w[p0 + 0x14];
0043     cc = bittst(r1, 5);
0044     if !cc jump txWaitLoop;
0045     w[p0 + 0x00] = r0;
0046     rts;
0047 
0048     .globl SYM(_CPU_write_crlf);
0049 SYM(_CPU_write_crlf):
0050     r0 = '\r';
0051     [--sp] = rets;
0052     call SYM(_CPU_write_char);
0053     rets = [sp++];
0054     r0 = '\n';
0055     jump SYM(_CPU_write_char);
0056 
0057 SYM(_CPU_write_space):
0058     r0 = ' ';
0059     jump SYM(_CPU_write_char);
0060 
0061     .globl SYM(_CPU_write_nybble);
0062 SYM(_CPU_write_nybble:)
0063     r1 = 0x0f;
0064     r0 = r0 & r1;
0065     r0 += '0';
0066     r1 = '9';
0067     cc = r0 <= r1;
0068     if cc jump SYM(_CPU_write_char);
0069     r0 += 'a' - '0' - 10;
0070     jump SYM(_CPU_write_char);
0071 
0072     .globl SYM(_CPU_write_byte);
0073 SYM(_CPU_write_byte):
0074     [--sp] = r0;
0075     [--sp] = rets;
0076     r0 >>= 4;
0077     call SYM(_CPU_write_nybble);
0078     rets = [sp++];
0079     r0 = [sp++];
0080     jump SYM(_CPU_write_nybble);
0081 
0082 SYM(_CPU_write_chawmp):
0083     [--sp] = r0;
0084     [--sp] = rets;
0085     r0 >>= 8;
0086     call SYM(_CPU_write_byte);
0087     rets = [sp++];
0088     r0 = [sp++];
0089     jump SYM(_CPU_write_byte);
0090 
0091 SYM(_CPU_write_gawble):
0092     [--sp] = r0;
0093     [--sp] = rets;
0094     r0 >>= 16;
0095     call SYM(_CPU_write_chawmp);
0096     rets = [sp++];
0097     r0 = [sp++];
0098     jump SYM(_CPU_write_chawmp);
0099 
0100 SYM(_CPU_dump_registers):
0101     [--sp] = rets;
0102     [--sp] = r0;
0103     [--sp] = r1;
0104     [--sp] = p0;
0105     r0 = [sp + 8];
0106     call SYM(_CPU_write_gawble);
0107     call SYM(_CPU_write_space);
0108     r0 = [sp + 4];
0109     call SYM(_CPU_write_gawble);
0110     call SYM(_CPU_write_space);
0111     r0 = r2;
0112     call SYM(_CPU_write_gawble);
0113     call SYM(_CPU_write_space);
0114     r0 = r3;
0115     call SYM(_CPU_write_gawble);
0116     call SYM(_CPU_write_space);
0117     r0 = r4;
0118     call SYM(_CPU_write_gawble);
0119     call SYM(_CPU_write_space);
0120     r0 = r5;
0121     call SYM(_CPU_write_gawble);
0122     call SYM(_CPU_write_space);
0123     r0 = r6;
0124     call SYM(_CPU_write_gawble);
0125     call SYM(_CPU_write_space);
0126     r0 = r7;
0127     call SYM(_CPU_write_gawble);
0128     call SYM(_CPU_write_crlf);
0129     r0 = [sp];
0130     call SYM(_CPU_write_gawble);
0131     call SYM(_CPU_write_space);
0132     r0 = p1;
0133     call SYM(_CPU_write_gawble);
0134     call SYM(_CPU_write_space);
0135     r0 = p2;
0136     call SYM(_CPU_write_gawble);
0137     call SYM(_CPU_write_space);
0138     r0 = p3;
0139     call SYM(_CPU_write_gawble);
0140     call SYM(_CPU_write_space);
0141     r0 = p4;
0142     call SYM(_CPU_write_gawble);
0143     call SYM(_CPU_write_space);
0144     r0 = p5;
0145     call SYM(_CPU_write_gawble);
0146     call SYM(_CPU_write_space);
0147     r0 = fp;
0148     call SYM(_CPU_write_gawble);
0149     call SYM(_CPU_write_space);
0150     r0 = sp;
0151     r0 += 16;
0152     call SYM(_CPU_write_gawble);
0153     call SYM(_CPU_write_crlf);
0154 
0155     p0 = [sp++];
0156     r1 = [sp++];
0157     r0 = [sp++];
0158     rets = [sp++];
0159     rts;
0160 
0161     .globl SYM(_CPU_Exception_handler);
0162 SYM(_CPU_Exception_handler):
0163     usp = sp;
0164     sp.h = 0xffb0;
0165     sp.l = 0x1000;
0166     [--sp] = (r7:0,p5:0);
0167 
0168     r0 = 'x';
0169     call SYM(_CPU_write_char);
0170     jump hcf;
0171 
0172 
0173     .globl SYM(_CPU_Emulation_handler);
0174 SYM(_CPU_Emulation_handler):
0175     usp = sp;
0176     sp.h = 0xffb0;
0177     sp.l = 0x1000;
0178     [--sp] = (r7:0,p5:0);
0179 
0180     r0 = 'e';
0181     call SYM(_CPU_write_char);
0182     jump hcf;
0183 
0184     .globl SYM(_CPU_Reset_handler);
0185 SYM(_CPU_Reset_handler):
0186     usp = sp;
0187     sp.h = 0xffb0;
0188     sp.l = 0x1000;
0189     [--sp] = (r7:0,p5:0);
0190 
0191     r0 = 'r';
0192     call SYM(_CPU_write_char);
0193     jump hcf;
0194 
0195     .globl SYM(_CPU_NMI_handler);
0196 SYM(_CPU_NMI_handler):
0197     usp = sp;
0198     sp.h = 0xffb0;
0199     sp.l = 0x1000;
0200     [--sp] = (r7:0,p5:0);
0201 
0202     r0 = 'n';
0203     call SYM(_CPU_write_char);
0204     jump hcf;
0205 
0206     .globl SYM(_CPU_Unhandled_Interrupt_handler);
0207 SYM(_CPU_Unhandled_Interrupt_handler):
0208     usp = sp;
0209     sp.h = 0xffb0;
0210     sp.l = 0x1000;
0211     [--sp] = (r7:0,p5:0);
0212 
0213     call SYM(_CPU_write_crlf);
0214     r0 = 'i';
0215     call SYM(_CPU_write_char);
0216     p0.h = HI(IPEND);
0217     p0.l = LO(IPEND);
0218     r0 = [p0];
0219     call SYM(_CPU_write_chawmp);
0220     jump hcf;
0221 
0222 hcf:
0223     idle;
0224     jump hcf;
0225 
0226 #endif
0227 
0228 
0229 /*  _CPU_Context_switch
0230  *
0231  *  This routine performs a normal non-FP context switch.
0232  *
0233  *  bfin Specific Information:
0234  *
0235  *  For now we simply save all registers.
0236  *
0237  */
0238 
0239 /* make sure this sequence stays in sync with the definition for
0240    Context_Control in rtems/score/cpu.h */
0241     .globl SYM(_CPU_Context_switch)
0242 SYM(_CPU_Context_switch):
0243     /* Start saving context R0 = current, R1=heir */
0244     p0 = r0;
0245     [p0++] = r4;
0246     [p0++] = r5;
0247     [p0++] = r6;
0248     [p0++] = r7;
0249 
0250     /* save pointer registers */
0251     [p0++] = p3;
0252     [p0++] = p4;
0253     [p0++] = p5;
0254     [p0++] = fp;
0255     [p0++] = sp;
0256 
0257     /* save rets */
0258     r0 = rets;
0259     [p0++] = r0;
0260 
0261     /* save IMASK */
0262     p1.h = HI(IMASK);
0263     p1.l = LO(IMASK);
0264     r0 = [p1];
0265     [p0++] = r0;
0266 
0267     p0 = r1;
0268 restore:
0269     /* restore data registers */
0270     r4 = [p0++];
0271     r5 = [p0++];
0272     r6 = [p0++];
0273     r7 = [p0++];
0274 
0275     /* restore pointer registers */
0276     p3 = [p0++];
0277     p4 = [p0++];
0278     p5 = [p0++];
0279     fp = [p0++];
0280     sp = [p0++];
0281 
0282     /* restore rets */
0283     r0 = [p0++];
0284     rets = r0;
0285 
0286     /* restore IMASK */
0287     r0 = [p0++];
0288     p1.h = HI(IMASK);
0289     p1.l = LO(IMASK);
0290     [p1] = r0;
0291 
0292     rts;
0293 
0294 
0295 /*
0296  *  _CPU_Context_restore
0297  *
0298  *  This routine is generally used only to restart self in an
0299  *  efficient manner.  It may simply be a label in _CPU_Context_switch.
0300  *
0301  *  NOTE: May be unnecessary to reload some registers.
0302  *
0303  *  Blackfin Specific Information:
0304  *
0305  *  none
0306  *
0307  */
0308     .globl SYM(_CPU_Context_restore)
0309 SYM(_CPU_Context_restore):
0310     p0 = r0;
0311     jump restore;
0312 
0313 
0314     .globl SYM(_ISR_Handler)
0315 SYM(_ISR_Handler):
0316     /* all interrupts are disabled at this point */
0317     /* the following few items are pushed onto the task stack for at
0318        most one interrupt; nested interrupts will be using the interrupt
0319        stack for everything. */
0320     [--sp] = astat;
0321     [--sp] = p1;
0322     [--sp] = p0;
0323     [--sp] = r1;
0324     [--sp] = r0;
0325     p0.h = ISR_NEST_LEVEL;
0326     p0.l = ISR_NEST_LEVEL;
0327     r0 = [p0];
0328     r0 += 1;
0329     [p0] = r0;
0330     cc = r0 <= 1 (iu);
0331     if !cc jump noStackSwitch;
0332     /* setup interrupt stack */
0333     r0 = sp;
0334     p0.h = INTERRUPT_STACK_HIGH;
0335     p0.l = INTERRUPT_STACK_HIGH;
0336     sp = [p0];
0337     [--sp] = r0;
0338 noStackSwitch:
0339     /* disable thread dispatch */
0340     p0.h = THREAD_DISPATCH_DISABLE_LEVEL;
0341     p0.l = THREAD_DISPATCH_DISABLE_LEVEL;
0342     r0 = [p0];
0343     r0 += 1;
0344     [p0] = r0;
0345 
0346     [--sp] = reti;  /* interrupts are now enabled */
0347 
0348     /* figure out what vector we are */
0349     p0.h = HI(IPEND);
0350     p0.l = LO(IPEND);
0351     r1 = [p0];
0352     /* we should only get here for events that require RTI to return */
0353     r1 = r1 >> 5;
0354     r0 = 4;
0355     /* at least one bit must be set, so this loop will exit */
0356 vectorIDLoop:
0357     r0 += 1;
0358     r1 = rot r1 by -1;
0359     if !cc jump vectorIDLoop;
0360 
0361     [--sp] = r2;
0362     r2.h = SYM(_ISR_Vector_table);
0363     r2.l = SYM(_ISR_Vector_table);
0364     r1 = r0 << 2;
0365     r1 = r1 + r2;
0366     p0 = r1;
0367     p0 = [p0];
0368     cc = p0 == 0;
0369     if cc jump noHandler;
0370 
0371     /* r2, r0, r1, p0, p1, astat are already saved */
0372     [--sp] = a1.x;
0373     [--sp] = a1.w;
0374     [--sp] = a0.x;
0375     [--sp] = a0.w;
0376     [--sp] = r3;
0377     [--sp] = p3;
0378     [--sp] = p2;
0379     [--sp] = lc1;
0380     [--sp] = lc0;
0381     [--sp] = lt1;
0382     [--sp] = lt0;
0383     [--sp] = lb1;
0384     [--sp] = lb0;
0385     [--sp] = i3;
0386     [--sp] = i2;
0387     [--sp] = i1;
0388     [--sp] = i0;
0389     [--sp] = m3;
0390     [--sp] = m2;
0391     [--sp] = m1;
0392     [--sp] = m0;
0393     [--sp] = l3;
0394     [--sp] = l2;
0395     [--sp] = l1;
0396     [--sp] = l0;
0397     [--sp] = b3;
0398     [--sp] = b2;
0399     [--sp] = b1;
0400     [--sp] = b0;
0401     [--sp] = rets;
0402     /* call user isr; r0 = vector number, r1 = frame pointer */
0403     r1 = fp; /* is this really what should be passed here? */
0404     r2 = 0;
0405     l0 = r2;
0406     l1 = r2;
0407     l2 = r2;
0408     l3 = r2;
0409     sp += -12; /* bizarre abi... */
0410     call (p0);
0411     sp += 12;
0412     rets = [sp++];
0413     b0 = [sp++];
0414     b1 = [sp++];
0415     b2 = [sp++];
0416     b3 = [sp++];
0417     l0 = [sp++];
0418     l1 = [sp++];
0419     l2 = [sp++];
0420     l3 = [sp++];
0421     m0 = [sp++];
0422     m1 = [sp++];
0423     m2 = [sp++];
0424     m3 = [sp++];
0425     i0 = [sp++];
0426     i1 = [sp++];
0427     i2 = [sp++];
0428     i3 = [sp++];
0429     lb0 = [sp++];
0430     lb1 = [sp++];
0431     lt0 = [sp++];
0432     lt1 = [sp++];
0433     lc0 = [sp++];
0434     lc1 = [sp++];
0435     p2 = [sp++];
0436     p3 = [sp++];
0437     r3 = [sp++];
0438     a0.w = [sp++];
0439     a0.x = [sp++];
0440     a1.w = [sp++];
0441     a1.x = [sp++];
0442 
0443 noHandler:
0444     r2 = [sp++];
0445     /* this disables interrupts again */
0446     reti = [sp++];
0447 
0448     p0.h = ISR_NEST_LEVEL;
0449     p0.l = ISR_NEST_LEVEL;
0450     r0 = [p0];
0451     r0 += -1;
0452     [p0] = r0;
0453     cc = r0 == 0;
0454     if !cc jump noStackRestore;
0455     sp = [sp];
0456 noStackRestore:
0457 
0458     /* check this stuff to ensure context_switch_necessary and
0459        isr_signals_to_thread_executing are being handled appropriately. */
0460     p0.h = THREAD_DISPATCH_DISABLE_LEVEL;
0461     p0.l = THREAD_DISPATCH_DISABLE_LEVEL;
0462     r0 = [p0];
0463     r0 += -1;
0464     [p0] = r0;
0465     cc = r0 == 0;
0466     if !cc jump noDispatch
0467 
0468     /* do thread dispatch if necessary */
0469     p0.h = DISPATCH_NEEDED;
0470     p0.l = DISPATCH_NEEDED;
0471     r0 = B[p0] (Z);
0472     cc = r0 == 0;
0473     if cc jump noDispatch
0474 doDispatch:
0475     raise 15;
0476 noDispatch:
0477     r0 = [sp++];
0478     r1 = [sp++];
0479     p0 = [sp++];
0480     p1 = [sp++];
0481     astat = [sp++];
0482     rti
0483 
0484 
0485 /* the approach here is for the main interrupt handler, when a dispatch is
0486    wanted, to do a "raise 15".  when the main interrupt handler does its
0487    "rti", the "raise 15" takes effect and we end up here.  we can now
0488    safely call _Thread_Dispatch, and do an "rti" to get back to the
0489    original interrupted function.  this does require self-nesting to be
0490    enabled; the maximum nest depth is the number of tasks. */
0491     .global SYM(_ISR15_Handler)
0492 SYM(_ISR15_Handler):
0493     [--sp] = reti;
0494     [--sp] = rets;
0495     [--sp] = astat;
0496     [--sp] = a1.x;
0497     [--sp] = a1.w;
0498     [--sp] = a0.x;
0499     [--sp] = a0.w;
0500     [--sp] = r3;
0501     [--sp] = r2;
0502     [--sp] = r1;
0503     [--sp] = r0;
0504     [--sp] = p3;
0505     [--sp] = p2;
0506     [--sp] = p1;
0507     [--sp] = p0;
0508     [--sp] = lc1;
0509     [--sp] = lc0;
0510     [--sp] = lt1;
0511     [--sp] = lt0;
0512     [--sp] = lb1;
0513     [--sp] = lb0;
0514     [--sp] = i3;
0515     [--sp] = i2;
0516     [--sp] = i1;
0517     [--sp] = i0;
0518     [--sp] = m3;
0519     [--sp] = m2;
0520     [--sp] = m1;
0521     [--sp] = m0;
0522     [--sp] = l3;
0523     [--sp] = l2;
0524     [--sp] = l1;
0525     [--sp] = l0;
0526     [--sp] = b3;
0527     [--sp] = b2;
0528     [--sp] = b1;
0529     [--sp] = b0;
0530     r2 = 0;
0531     l0 = r2;
0532     l1 = r2;
0533     l2 = r2;
0534     l3 = r2;
0535     sp += -12; /* bizarre abi... */
0536     call SYM(_Thread_Dispatch);
0537     sp += 12;
0538     b0 = [sp++];
0539     b1 = [sp++];
0540     b2 = [sp++];
0541     b3 = [sp++];
0542     l0 = [sp++];
0543     l1 = [sp++];
0544     l2 = [sp++];
0545     l3 = [sp++];
0546     m0 = [sp++];
0547     m1 = [sp++];
0548     m2 = [sp++];
0549     m3 = [sp++];
0550     i0 = [sp++];
0551     i1 = [sp++];
0552     i2 = [sp++];
0553     i3 = [sp++];
0554     lb0 = [sp++];
0555     lb1 = [sp++];
0556     lt0 = [sp++];
0557     lt1 = [sp++];
0558     lc0 = [sp++];
0559     lc1 = [sp++];
0560     p0 = [sp++];
0561     p1 = [sp++];
0562     p2 = [sp++];
0563     p3 = [sp++];
0564     r0 = [sp++];
0565     r1 = [sp++];
0566     r2 = [sp++];
0567     r3 = [sp++];
0568     a0.w = [sp++];
0569     a0.x = [sp++];
0570     a1.w = [sp++];
0571     a1.x = [sp++];
0572     astat = [sp++];
0573     rets = [sp++];
0574     reti = [sp++];
0575     rti;
0576