OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [libgloss/] [bfin/] [basiccrt.S] - Blame information for rev 158

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/*
2
 * Basic startup code for Blackfin processor
3
 *
4
 * Copyright (C) 2008 Analog Devices, Inc.
5
 *
6
 * The authors hereby grant permission to use, copy, modify, distribute,
7
 * and license this software and its documentation for any purpose, provided
8
 * that existing copyright notices are retained in all copies and that this
9
 * notice is included verbatim in any distributions. No written agreement,
10
 * license, or royalty fee is required for any of the authorized uses.
11
 * Modifications to this software may be copyrighted by their authors
12
 * and need not follow the licensing terms described here, provided that
13
 * the new terms are clearly indicated on the first page of each file where
14
 * they apply.
15
 */
16
 
17
// basic startup code which
18
// - turns the cycle counter on
19
// - loads up FP & SP (both supervisor and user)
20
// - initialises the device drivers (FIOCRT)
21
// - calls monstartup to set up the profiling routines (PROFCRT)
22
// - calls the C++ startup (CPLUSCRT)
23
// - initialises argc/argv (FIOCRT/normal)
24
// - calls _main
25
// - calls _exit (which calls monexit to dump accumulated prof data (PROFCRT))
26
// - defines dummy IO routines (!FIOCRT)
27
 
28
#include 
29
#include 
30
#include 
31
 
32
#define IVBh (EVT0 >> 16)
33
#define IVBl (EVT0 & 0xFFFF)
34
#define UNASSIGNED_VAL 0
35
#define UNASSIGNED_FILL 0
36
// just IVG15
37
#define INTERRUPT_BITS 0x400
38
#if defined(_ADI_THREADS) || \
39
    !defined(__ADSPLPBLACKFIN__) || defined(__ADSPBF561__) || defined(__ADSPBF566__)
40
#define SET_CLOCK_SPEED 0
41
#else
42
#define SET_CLOCK_SPEED 1
43
#endif
44
 
45
#if SET_CLOCK_SPEED == 1
46
#include 
47
#define SET_CLK_MSEL 0x16
48
#define SET_CLK_DF 0
49
#define SET_CLK_LOCK_COUNT 0x300
50
#define SET_CLK_CSEL 0
51
#define SET_CLK_SSEL 5
52
 
53
/*
54
** CLKIN == 27MHz on the EZ-Kits.
55
** D==0 means CLKIN is passed to PLL without dividing.
56
** MSEL==0x16 means VCO==27*0x16 == 594MHz
57
** CSEL==0 means CCLK==VCO == 594MHz
58
** SSEL==5 means SCLK==VCO/5 == 118MHz
59
*/
60
 
61
#endif
62
 
63
#ifdef __ADSPBF561_COREB__
64
        .section        .b.text,"ax",@progbits
65
        .align 2;
66
        .global __coreb_start;
67
        .type __coreb_start, STT_FUNC;
68
__coreb_start:
69
#else
70
        .text;
71
        .align 2;
72
        .global __start;
73
        .type __start, STT_FUNC;
74
__start:
75
#endif
76
#if WA_05000109
77
        // Avoid Anomaly ID 05000109.
78
#       define SYSCFG_VALUE 0x30
79
        R1 = SYSCFG_VALUE;
80
        SYSCFG = R1;
81
#endif
82
#if WA_05000229
83
   // Avoid Anomaly 05-00-0229: DMA5_CONFIG and SPI_CTL not cleared on reset.
84
   R1 = 0x400;
85
#if defined(__ADSPBF538__) || defined(__ADSPBF539__)
86
   P0.L = SPI0_CTL & 0xFFFF;
87
   P0.H = SPI0_CTL >> 16;
88
   W[P0] = R1.L;
89
#else
90
   P0.L = SPI_CTL & 0xFFFF;
91
   P0.H = SPI_CTL >> 16;
92
   W[P0] = R1.L;
93
#endif
94
   P0.L = DMA5_CONFIG & 0xFFFF;
95
   P0.H = DMA5_CONFIG >> 16;
96
   R1 = 0;
97
   W[P0] = R1.L;
98
#endif
99
        // Zap loop counters to zero, to make sure that
100
        // hw loops are disabled - it could be really baffling
101
        // if the counters and bottom regs are set, and we happen
102
        // to run into them.
103
        R7 = 0;
104
        LC0 = R7;
105
        LC1 = R7;
106
 
107
        // Clear the DAG Length regs too, so that it's safe to
108
        // use I-regs without them wrapping around.
109
        L0 = R7;
110
        L1 = R7;
111
        L2 = R7;
112
        L3 = R7;
113
 
114
        // Zero ITEST_COMMAND and DTEST_COMMAND
115
        // (in case they have crud in them and
116
        // does a write somewhere when we enable cache)
117
        I0.L = (ITEST_COMMAND & 0xFFFF);
118
        I0.H = (ITEST_COMMAND >> 16);
119
        I1.L = (DTEST_COMMAND & 0xFFFF);
120
        I1.H = (DTEST_COMMAND >> 16);
121
        R7 = 0;
122
        [I0] = R7;
123
        [I1] = R7;
124
        // It seems writing ITEST_COMMAND from SDRAM with icache enabled
125
        // needs SSYNC.
126
#ifdef __BFIN_SDRAM
127
        SSYNC;
128
#else
129
        CSYNC;
130
#endif
131
 
132
        // Initialise the Event Vector table.
133
        P0.H = IVBh;
134
        P0.L = IVBl;
135
 
136
        // Install __unknown_exception_occurred in EVT so that
137
        // there is defined behaviour.
138
        P0 += 2*4;              // Skip Emulation and Reset
139
        P1 = 13;
140
        R1.L = __unknown_exception_occurred;
141
        R1.H = __unknown_exception_occurred;
142
        LSETUP (L$ivt,L$ivt) LC0 = P1;
143
L$ivt:  [P0++] = R1;
144
        // Set IVG15's handler to be the start of the mode-change
145
        // code. Then, before we return from the Reset back to user
146
        // mode, we'll raise IVG15. This will mean we stay in supervisor
147
        // mode, and continue from the mode-change point., but at a
148
        // much lower priority.
149
        P1.H = L$supervisor_mode;
150
        P1.L = L$supervisor_mode;
151
        [P0] = P1;
152
 
153
        // Initialise the stack.
154
        // Note: this points just past the end of the section.
155
        // First write should be with [--SP].
156
#ifdef __BFIN_SDRAM
157
        SP.L = __end + 0x400000 - 12;
158
        SP.H = __end + 0x400000 - 12;
159
#else
160
#ifdef __ADSPBF561_COREB__
161
        SP.L=__coreb_stack_end - 12;
162
        SP.H=__coreb_stack_end - 12;
163
#else
164
        SP.L=__stack_end - 12;
165
        SP.H=__stack_end - 12;
166
#endif
167
#endif
168
        usp = sp;
169
 
170
        // We're still in supervisor mode at the moment, so the FP
171
        // needs to point to the supervisor stack.
172
        FP = SP;
173
 
174
        // And make space for incoming "parameters" for functions
175
        // we call from here:
176
        SP += -12;
177
 
178
        // Zero out bss section
179
#ifdef __BFIN_SDRAM
180
        R0.L = ___bss_start;
181
        R0.H = ___bss_start;
182
        R1.L = __end;
183
        R1.H = __end;
184
#else
185
#ifdef __ADSPBF561_COREB__
186
        R0.L = __coreb_bss_start;
187
        R0.H = __coreb_bss_start;
188
        R1.L = __coreb_bss_end;
189
        R1.H = __coreb_bss_end;
190
#else
191
        R0.L = __bss_start;
192
        R0.H = __bss_start;
193
        R1.L = __bss_end;
194
        R1.H = __bss_end;
195
#endif
196
#endif
197
        R2 = R1 - R0;
198
        R1 = 0;
199
#ifdef __ADSPBF561_COREB__
200
        CALL.X __coreb_memset;
201
#else
202
        CALL.X _memset;
203
#endif
204
 
205
        R0 = INTERRUPT_BITS;
206
        R0 <<= 5;       // Bits 0-4 not settable.
207
        // CALL.X __install_default_handlers;
208
        R4 = R0;                // Save modified list
209
 
210
        R0 = SYSCFG;            // Enable the Cycle counter
211
        BITSET(R0,1);
212
        SYSCFG = R0;
213
 
214
#if WA_05000137
215
        // Avoid anomaly #05000137
216
 
217
        // Set the port preferences of DAG0 and DAG1 to be
218
        // different; this gives better performance when
219
        // performing dual-dag operations on SDRAM.
220
        P0.L = DMEM_CONTROL & 0xFFFF;
221
        P0.H = DMEM_CONTROL >> 16;
222
        R0 = [P0];
223
        BITSET(R0, 12);
224
        BITCLR(R0, 13);
225
        [P0] = R0;
226
        CSYNC;
227
#endif
228
 
229
        // Reinitialise data areas in RAM from ROM, if MemInit's
230
        // been used.
231
        // CALL.X _mi_initialize;
232
 
233
#if defined(__ADSPLPBLACKFIN__)
234
#if SET_CLOCK_SPEED == 1
235
 
236
#if 0
237
        // Check if this feature is enabled, i.e. ___clk_ctrl is defined to non-zero
238
        P0.L = ___clk_ctrl;
239
        P0.H = ___clk_ctrl;
240
        R0 = MAX_IN_STARTUP;
241
        R1 = [P0];
242
        R0 = R0 - R1;
243
        CC = R0;
244
        IF CC JUMP L$clock_is_set;
245
#endif
246
 
247
        // Investigate whether we are a suitable revision
248
        // for boosting the system clocks.
249
        // speed.
250
        P0.L = DSPID & 0xFFFF;
251
        P0.H = DSPID >> 16;
252
        R0 = [P0];
253
        R0 = R0.L (Z);
254
        CC = R0 < 2;
255
        IF CC JUMP L$clock_is_set;
256
 
257
        // Set the internal Voltage-Controlled Oscillator (VCO)
258
        R0 = SET_CLK_MSEL (Z);
259
        R1 = SET_CLK_DF (Z);
260
        R2 = SET_CLK_LOCK_COUNT (Z);
261
        CALL.X __pll_set_system_vco;
262
 
263
        // Set the Core and System clocks
264
        R0 = SET_CLK_CSEL (Z);
265
        R1 = SET_CLK_SSEL (Z);
266
        CALL.X __pll_set_system_clocks;
267
 
268
L$clock_is_set:
269
#endif
270
#endif /* ADSPLPBLACKFIN */
271
 
272
#if defined(__ADSPBF561__) || defined(__ADSPBF566__)
273
        // Initialise the multi-core data tables.
274
        // A dummy function will be called if we are not linking with
275
        // -multicore
276
        // CALL.X __mc_data_initialise;
277
#endif
278
 
279
#if 0
280
        // Write the cplb exception handler to the EVT if approprate and
281
        // initialise the CPLBs if they're needed. couldn't do
282
        // this before we set up the stacks.
283
        P2.H = ___cplb_ctrl;
284
        P2.L = ___cplb_ctrl;
285
        R0 = CPLB_ENABLE_ANY_CPLBS;
286
        R6 = [P2];
287
        R0 = R0 & R6;
288
        CC = R0;
289
        IF !CC JUMP L$no_cplbs;
290
#if !defined(_ADI_THREADS)
291
        P1.H = __cplb_hdr;
292
        P1.L = __cplb_hdr;
293
        P0.H = IVBh;
294
        P0.L = IVBl;
295
        [P0+12] = P1;   // write exception handler
296
#endif /* _ADI_THREADS */
297
        R0 = R6;
298
        CALL.X __cplb_init;
299
#endif
300
L$no_cplbs:
301
        //  Enable interrupts
302
        STI R4;         // Using the mask from default handlers
303
        RAISE 15;
304
 
305
        // Move the processor into user mode.
306
        P0.L=L$still_interrupt_in_ipend;
307
        P0.H=L$still_interrupt_in_ipend;
308
        RETI=P0;
309
 
310
L$still_interrupt_in_ipend:
311
        rti;    // keep doing 'rti' until we've 'finished' servicing all
312
                // interrupts of priority higher than IVG15. Normally one
313
                // would expect to only have the reset interrupt in IPEND
314
                // being serviced, but occasionally when debugging this may
315
                // not be the case - if restart is hit when servicing an
316
                // interrupt.
317
                //
318
                // When we clear all bits from IPEND, we'll enter user mode,
319
                // then we'll automatically jump to supervisor_mode to start
320
                // servicing IVG15 (which we will 'service' for the whole
321
                // program, so that the program is in supervisor mode.
322
                //
323
                // Need to do this to 'finish' servicing the reset interupt.
324
 
325
L$supervisor_mode:
326
        [--SP] = RETI;  // re-enables the interrupt system
327
 
328
        R0.L = UNASSIGNED_VAL;
329
        R0.H = UNASSIGNED_VAL;
330
#if UNASSIGNED_FILL
331
        R2=R0;
332
        R3=R0;
333
        R4=R0;
334
        R5=R0;
335
        R6=R0;
336
        R7=R0;
337
        P0=R0;
338
        P1=R0;
339
        P2=R0;
340
        P3=R0;
341
        P4=R0;
342
        P5=R0;
343
#endif
344
        // Push a RETS and Old FP onto the stack, for sanity.
345
        [--SP]=R0;
346
        [--SP]=R0;
347
        // Make sure the FP is sensible.
348
        FP = SP;
349
 
350
        // And leave space for incoming "parameters"
351
        SP += -12;
352
 
353
#ifdef PROFCRT
354
        CALL.X monstartup; // initialise profiling routines
355
#endif  /* PROFCRT */
356
 
357
#ifndef __ADSPBF561_COREB__
358
        CALL.X __init;
359
 
360
        R0.L = __fini;
361
        R0.H = __fini;
362
        CALL.X _atexit;
363
#endif
364
 
365
#if !defined(_ADI_THREADS)
366
#ifdef FIOCRT
367
        // FILE IO provides access to real command-line arguments.
368
        CALL.X __getargv;
369
        r1.l=__Argv;
370
        r1.h=__Argv;
371
#else
372
        // Default to having no arguments and a null list.
373
        R0=0;
374
#ifdef __ADSPBF561_COREB__
375
        R1.L=L$argv_coreb;
376
        R1.H=L$argv_coreb;
377
#else
378
        R1.L=L$argv;
379
        R1.H=L$argv;
380
#endif
381
#endif /* FIOCRT */
382
#endif /* _ADI_THREADS */
383
 
384
        // At long last, call the application program.
385
#ifdef __ADSPBF561_COREB__
386
        CALL.X _coreb_main;
387
#else
388
        CALL.X _main;
389
#endif
390
 
391
#if !defined(_ADI_THREADS)
392
#ifndef __ADSPBF561_COREB__
393
        CALL.X _exit;   // passing in main's return value
394
#endif
395
#endif
396
 
397
#ifdef __ADSPBF561_COREB__
398
        .size   __coreb_start, .-__coreb_start
399
#else
400
        .size   __start, .-__start
401
#endif
402
 
403
        .align 2
404
        .type __unknown_exception_occurred, STT_FUNC;
405
__unknown_exception_occurred:
406
        // This function is invoked by the default exception
407
        // handler, if it does not recognise the kind of
408
        // exception that has occurred. In other words, the
409
        // default handler only handles some of the system's
410
        // exception types, and it does not expect any others
411
        // to occur. If your application is going to be using
412
        // other kinds of exceptions, you must replace the
413
        // default handler with your own, that handles all the
414
        // exceptions you will use.
415
        //
416
        // Since there's nothing we can do, we just loop here
417
        // at what we hope is a suitably informative label.
418
        IDLE;
419
        CSYNC;
420
        JUMP __unknown_exception_occurred;
421
        RTS;
422
        .size __unknown_exception_occurred, .-__unknown_exception_occurred
423
 
424
#if defined(__ADSPLPBLACKFIN__)
425
#if SET_CLOCK_SPEED == 1
426
 
427
/*
428
** CLKIN == 27MHz on the EZ-Kits.
429
** D==0 means CLKIN is passed to PLL without dividing.
430
** MSEL==0x16 means VCO==27*0x16 == 594MHz
431
** CSEL==0 means CCLK==VCO == 594MHz
432
** SSEL==5 means SCLK==VCO/5 == 118MHz
433
*/
434
 
435
// int pll_set_system_clocks(int csel, int ssel)
436
// returns 0 for success, -1 for error.
437
 
438
        .align 2
439
        .type __pll_set_system_clocks, STT_FUNC;
440
__pll_set_system_clocks:
441
        P0.H = PLL_DIV >> 16;
442
        P0.L = PLL_DIV & 0xFFFF;
443
        R2 = W[P0] (Z);
444
 
445
        // Plant CSEL and SSEL
446
        R0 <<= 16;
447
        R0.L = (4 << 8) | 2;    // 2 bits, at posn 4
448
        R1 <<= 16;
449
        R1.L = 4;               // 4 bits, at posn 0
450
        R2 = DEPOSIT(R2, R0);
451
 
452
#if defined(__WORKAROUND_DREG_COMP_LATENCY)
453
        // Work around anomaly 05-00-0209 which affects the DEPOSIT
454
        // instruction (and the EXTRACT, SIGNBITS, and EXPADJ instructions)
455
        // if the previous instruction created any of its operands
456
        NOP;
457
#endif
458
 
459
        R2 = DEPOSIT(R2, R1);
460
 
461
        W[P0] = R2;
462
        SSYNC;
463
        RTS;
464
        .size __pll_set_system_clocks, .-__pll_set_system_clocks
465
 
466
// int pll_set_system_vco(int msel, int df, lockcnt)
467
        .align 2
468
        .type __pll_set_system_vco, STT_FUNC;
469
__pll_set_system_vco:
470
        P0.H = PLL_CTL >> 16;
471
        P0.L = PLL_CTL & 0xFFFF;
472
        R3 = W[P0] (Z);
473
        P2 = R3;                // Save copy
474
        R3 >>= 1;               // Drop old DF
475
        R1 = ROT R1 BY -1;      // Move DF into CC
476
        R3 = ROT R3 BY 1;       // and into ctl space.
477
        R0 <<= 16;              // Set up pattern reg
478
        R0.L = (9<<8) | 6;      // (6 bits at posn 9)
479
        R1 = P2;                // Get the old version
480
        R3 = DEPOSIT(R3, R0);
481
        CC = R1 == R3;          // and if we haven't changed
482
        IF CC JUMP L$done;      // Anything, return
483
 
484
        CC = R2 == 0;           // Use default lockcount if
485
        IF CC JUMP L$wakeup;    // user one is zero.
486
        P2.H = PLL_LOCKCNT >> 16;
487
        P2.L = PLL_LOCKCNT & 0xFFFF;
488
        W[P2] = R2;             // Set the lock counter
489
L$wakeup:
490
        P2.H = SIC_IWR >> 16;
491
        P2.L = SIC_IWR & 0xFFFF;
492
        R2 = [P2];
493
        BITSET(R2, 0);          // enable PLL Wakeup
494
        [P2] = R2;
495
 
496
        W[P0] = R3;             // Update PLL_CTL
497
        SSYNC;
498
 
499
        CLI R2;                 // Avoid unnecessary interrupts
500
        IDLE;                   // Wait until PLL has locked
501
        STI R2;                 // Restore interrupts.
502
 
503
L$done:
504
        RTS;
505
        .size __pll_set_system_vco, .-__pll_set_system_vco
506
#endif
507
#endif /* ADSPLPBLACKFIN */
508
 
509
#ifdef __ADSPBF561_COREB__
510
        .section        .b.text,"ax",@progbits
511
        .type __coreb_memset, STT_FUNC
512
__coreb_memset:
513
        P0 = R0 ;              /* P0 = address */
514
        P2 = R2 ;              /* P2 = count   */
515
        R3 = R0 + R2;          /* end          */
516
        CC = R2 <= 7(IU);
517
        IF CC JUMP  .Ltoo_small;
518
        R1 = R1.B (Z);         /* R1 = fill char */
519
        R2 =  3;
520
        R2 = R0 & R2;          /* addr bottom two bits */
521
        CC =  R2 == 0;             /* AZ set if zero.   */
522
        IF !CC JUMP  .Lforce_align ;  /* Jump if addr not aligned. */
523
 
524
.Laligned:
525
        P1 = P2 >> 2;          /* count = n/4        */
526
        R2 = R1 <<  8;         /* create quad filler */
527
        R2.L = R2.L + R1.L(NS);
528
        R2.H = R2.L + R1.H(NS);
529
        P2 = R3;
530
 
531
        LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
532
.Lquad_loop:
533
        [P0++] = R2;
534
 
535
        CC = P0 == P2;
536
        IF !CC JUMP .Lbytes_left;
537
        RTS;
538
 
539
.Lbytes_left:
540
        R2 = R3;                /* end point */
541
        R3 = P0;                /* current position */
542
        R2 = R2 - R3;           /* bytes left */
543
        P2 = R2;
544
 
545
.Ltoo_small:
546
        CC = P2 == 0;           /* Check zero count */
547
        IF CC JUMP .Lfinished;    /* Unusual */
548
 
549
.Lbytes:
550
        LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2;
551
.Lbyte_loop:
552
        B[P0++] = R1;
553
 
554
.Lfinished:
555
        RTS;
556
 
557
.Lforce_align:
558
        CC = BITTST (R0, 0);  /* odd byte */
559
        R0 = 4;
560
        R0 = R0 - R2;
561
        P1 = R0;
562
        R0 = P0;                    /* Recover return address */
563
        IF !CC JUMP .Lskip1;
564
        B[P0++] = R1;
565
.Lskip1:
566
        CC = R2 <= 2;          /* 2 bytes */
567
        P2 -= P1;              /* reduce count */
568
        IF !CC JUMP .Laligned;
569
        B[P0++] = R1;
570
        B[P0++] = R1;
571
        JUMP .Laligned;
572
.size __coreb_memset,.-__coreb_memset
573
#endif
574
 
575
#ifdef __ADSPBF561_COREB__
576
        .section        .b.bss,"aw",@progbits
577
        .align 4
578
        .type   L$argv_coreb, @object
579
        .size   L$argv_coreb, 4
580
L$argv_coreb:
581
        .zero   4
582
#else
583
        .local  L$argv
584
        .comm   L$argv,4,4
585
#endif
586
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.