分支自 DSP/ADSP21569/DSP-21569

wanglei
2024-03-27 ec21e6d7b11751cba2501c690d0e16fcb0581d3c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
** ADSP-21569 startup code generated on Aug 02, 2023 at 21:46:12.
*/
/*
** Copyright (C) 2000-2022 Analog Devices Inc., All Rights Reserved.
**
** This file is generated automatically based upon the options selected
** in the System Configuration utility. Changes to the Startup Code configuration
** should be made by modifying the appropriate options rather than editing
** this file. To access the System Configuration utility, double-click the
** system.svc file from a navigation view.
**
** Custom additions can be inserted within the user-modifiable sections. These
** sections are bounded by comments that start with "$VDSG". Only changes
** placed within these sections are preserved when this file is re-generated.
**
** Product      : CrossCore Embedded Studio
** Tool Version : 6.2.3.3
*/
 
.FILE_ATTR libGroup="startup";
.FILE_ATTR libName="libc";
 
.FILE_ATTR libFunc="___lib_prog_term";
.FILE_ATTR FuncName="___lib_prog_term";
.FILE_ATTR libFunc="start";
.FILE_ATTR FuncName="start";
.FILE_ATTR prefersMem="any";
.FILE_ATTR prefersMemNum="50";
 
#include <sys/anomaly_macros_rtl.h> // defines silicon anomaly macros
#include <interrupt.h>              // defines interrupt support
#include <platform_include.h>       // defines MMR macros
#include <adi_osal.h>               // OSAL support
#include <sys/fatal_error_code.h>   // defines fatal error support
 
/* End marker for the list of static constructors.
** seg_ctdml has to be mapped right after seg_ctdm.
*/
 
.SECTION/DATA/DOUBLEANY seg_ctdml;
.RETAIN_NAME __ctor_NULL_marker;
.GLOBAL __ctor_NULL_marker;
.VAR __ctor_NULL_marker = 0;
 
/* The .gdt (global dispatch table) data is used by the C++ exception
** runtime library support to determine which area of code a particular
** exception belongs. These .gdt sections must be mapped to contiguous
** memory by the LDF starting with this one and and ending with .gdtl.
** The word addressed variants of these sections also need to be included
** and are called .gdt32 and .gdtl32.
*/
 
.SECTION/DOUBLEANY .gdt;
.ALIGN 4;
.BYTE __eh_gdt.[4];
.GLOBAL __eh_gdt.;
.TYPE __eh_gdt.,STT_OBJECT;
 
.SECTION/DM/DOUBLEANY .gdt32;
.VAR ___eh_gdt[1];
.GLOBAL ___eh_gdt;
.TYPE ___eh_gdt,STT_OBJECT;
 
/* Suppress the assemblers informational message regarding the automatic
** call sequence change it does when building -swc.
*/
.MESSAGE/SUPPRESS 2536;
 
 
.GLOBAL start;
 
.SECTION/CODE/DOUBLEANY seg_pmco;
 
start:
 
      /* Disable the BTB. */
      R0 = DM(REG_SHBTB0_CFG);              /* Get current BTB configuration. */
      R0 = BSET R0 BY BITP_SHBTB_CFG_DIS;   /* Disable the BTB                */
      DM(REG_SHBTB0_CFG) = R0;              /* Write back to BTB_CFG MMR.     */
      /* After a write to the SHBTB_CFG register there must be at least
      ** 12 48-bit (ISA) instructions, which do not involve any change
      ** of flow.
      */
      .NOCOMPRESS;
      NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
      .COMPRESS;
 
      /* Ensure caches are disabled - enables a soft reset to jump to start
      ** and also avoids problems if a preload enables caches.
      */
      /* Cache configuration updates only while executing in L1 memory. */
      R0 = 0;
      JUMP (.disable_caches);
.SECTION/SW/DOUBLEANY seg_int_code;
.disable_caches:
      DM(REG_SHL1C0_CFG) = R0;
      /* 12 uncompressed NOPs after a cache MMR access. */
      .NOCOMPRESS;
      NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
      .COMPRESS;
      JUMP (.caches_disabled);
.PREVIOUS;
.caches_disabled:
 
      /* Enable instruction, data and system transfer parity checking for
      ** parts and revisions that have all required support. The ADSP-SC58x
      ** and ADSP-2158x revisions 0.0 and 0.1 system reset does not work and
      ** this is required so we don't enable parity for these.
      */
#if !defined(__IS_FPGA__) && \
    (!defined(__ADSPSC589_FAMILY__) || \
     (!defined(__SILICON_REVISION__) || \
      ((__SILICON_REVISION__ >= 0x0100) && (__SILICON_REVISION__ != 0xFFFF))))
      BIT SET MODE1 (BITM_REGF_MODE1_IPERREN | BITM_REGF_MODE1_DPERREN |
                     BITM_REGF_MODE1_SPERREN );
      /* Wait 11 cycles for the change to take effect. */
      NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
      #define ENABLED_PARITY_ERROR_CHECKING
#else
      /* Explicitly disable parity error checking when we don't enable it
      ** for the application. This may be necessary for ADSP-215xx (non-ARM)
      ** parts as the SHARC+ boot can enable parity error checking.
      */
      BIT CLR MODE1 (BITM_REGF_MODE1_IPERREN | BITM_REGF_MODE1_DPERREN |
                     BITM_REGF_MODE1_SPERREN );
      /* Wait 11 cycles for the change to take effect. */
      NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
#endif
 
      /* Zero all the BTB memory locations to initialize the parity bits. */
      I0 = 0x31000;
      L0 = 0;
      M0 = 1;
      R0 = 0;
      LCNTR = 0x400, DO (PC,.BTB_init_loop) UNTIL LCE;
.BTB_init_loop:
         DM(I0, M0) = R0;
 
      /* Also zero the L1 cache memory locations... **/
 
      /* ... Icache tag */
      I0 = 0x3E400;
      LCNTR = 0x400, DO (PC,.icache_tag_loop) UNTIL LCE;
.icache_tag_loop:
         DM(I0, M0) = R0;
 
      /* ... then dcache (dmcache + pmcache) tag */
      I0 = 0x3C000;
      LCNTR = 0x1000, DO (PC,.dcache_tag_loop) UNTIL LCE;
.dcache_tag_loop:
        DM(I0, M0) = R0;
 
      /* ... then dmcache LRU/DIRTY */
      I0 = 0x3D100;
      LCNTR = 0x100, DO (PC,.dmcache_dirty_loop) UNTIL LCE;
.dmcache_dirty_loop:
        DM(I0, M0) = R0;
 
      /* ... then pmcache LRU/DIRTY */
      I0 = 0x3D300;
      LCNTR = 0x100, DO (PC,.pmcache_dirty_loop) UNTIL LCE;
.pmcache_dirty_loop:
        DM(I0, M0) = R0;
 
      /* ... then icache LRU/DIRTY */
      I0 = 0x3d500;
      LCNTR = 0x80, DO (PC,.icache_dirty_loop) UNTIL LCE;
.icache_dirty_loop:
        DM(I0, M0) = R0;
 
      R0 = DM(REG_SHBTB0_CFG);              /* Get current BTB configuration. */
      R0 = BCLR R0 BY BITP_SHBTB_CFG_DIS;   /* Enable the BTB                 */
      R0 = BSET R0 BY BITP_SHBTB_CFG_INVAL; /* Invalidate the BTB             */
      /* Turn off software return prediction in the BTB, because we can't
      ** guarantee i12 has a valid code address, and a speculative access
      ** to an invalid address can cause a hardware error.
      */
      R0 = BSET R0 BY BITP_SHBTB_CFG_SRETDIS; /* Software return disable.     */
      DM(REG_SHBTB0_CFG) = R0;              /* Write back to BTB_CFG MMR.     */
      /* After a write to the SHBTB_CFG register there must be at least
      ** 12 48-bit (ISA) instructions, which do not involve any change of
      ** flow.
      */
      .NOCOMPRESS;
      NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
      .COMPRESS;
 
     /* There might be entries on the loop, PC and status stacks. Clear them all. 
     ** First, clear the loop stack.
     */
     BIT TST STKY BITM_REGF_STKYX_LSEM;
.pop_loop_stack:
     IF TF JUMP (PC, .loop_stack_empty);
     JUMP (PC, .pop_loop_stack) (DB);
       POP LOOP;
       BIT TST STKY BITM_REGF_STKYX_LSEM;
.loop_stack_empty:
 
     /* Then, clear the status stack. */
     BIT TST STKY BITM_REGF_STKYX_SSEM;
.pop_status_stack:
     IF TF JUMP (PC, .status_stack_empty);
     JUMP (PC, .pop_status_stack) (DB);
       POP STS;
       BIT TST STKY BITM_REGF_STKYX_SSEM;
.status_stack_empty:
 
     /* Then clear the PC stack. PC stack cannot be popped in a delay slot. */
.pop_pc_stack:
     BIT TST STKY BITM_REGF_STKYX_PCEM;
     IF TF JUMP (PC, .pc_stack_empty);
     POP PCSTK;
     JUMP (PC, .pop_pc_stack);
.pc_stack_empty:
 
      /* Set the vector register to 'start' so that if the processor
      ** is reset the processor bypasses the boot ROM code.
      */
      R0 = start;
      DM(REG_RCU0_SVECT0) = R0;
 
 
/*$VDSG<insert-code-very-beginning>                             */
.start_of_user_code_very_beginning:
      /*
      ** Insert any additional code to be executed before any other
      ** startup code here.
      ** Code inserted here is preserved when this file is re-generated.
      ** Note that the C runtime environment hasn't been set up yet
      ** so you cannot call C or C++ functions.
      */
.end_of_user_code_very_beginning:
/*$VDSG<insert-code-very-beginning>                             */
 
      /*
      ** Initializes the processor, memory, C runtime and heaps.
      */
      .EXTERN ___lib_setup_c;
      CALL ___lib_setup_c;
 
 
/*$VDSG<insert-code-after-setup>                                */
.start_of_user_code_after_setup:
      /*
      ** Insert any additional code to be executed at the start after
      ** the C runtime and hardware has been initialized.
      ** Code inserted here is preserved when this file is re-generated.
      */
.end_of_user_code_after_setup:
/*$VDSG<insert-code-after-setup>                                */
 
      /*
      ** Enable the ILOPI interrupt to support illegal opcode detection.
      ** The interrupt vector code for Illegal Opcode detection
      ** jumps directly to stub handler _adi_ilop_detected.
      */
      .EXTERN adi_rtl_activate_dispatched_handler.;
      R4 = ADI_CID_ILOPI;
      CJUMP adi_rtl_activate_dispatched_handler. (DB);
         DM(I7, M7) = R2;
         DM(I7, M7) = PC;
 
#if defined(ENABLED_PARITY_ERROR_CHECKING)
      /*
      ** Enable the PARI interrupt to support L1 parity error detection.
      ** The interrupt vector code for this interrupt jumps directly
      ** to stub handler _adi_parity_error_detected.
      */
      .EXTERN adi_rtl_activate_dispatched_handler.;
      R4 = ADI_CID_PARI;
      CJUMP adi_rtl_activate_dispatched_handler. (DB);
         DM(I7, M7) = R2;
         DM(I7, M7) = PC;
#endif
 
      /*
      ** Call the OSAL init function.
      */
      .EXTERN adi_osal_Init.;    // ADI_OSAL_STATUS adi_osal_Init(void);
      CJUMP adi_osal_Init. (DB);
         DM(I7, M7) = R2;
         DM(I7, M7) = PC;
 
      R1 = E_ADI_OSAL_SUCCESS;
      COMPU(R0, R1);
      IF NE JUMP .osal_Init_failed;
 
      /*
      ** Call all the byte-addressed then word-addressed C++ static
      ** class instance constructors.
      */
      .EXTERN  __ctors, _ctors.; // defined in the LDF file
 
      I0 = _ctors.;              // load pointer to the list of constructors
                                 // for byte addressing into call preserved I0
 
      R15 = 2;                   // counter held in R15
      R5 = I6;                   // hold current I6 in preserved register R5
 
.call_ctors_start:
      R0 = DM(I0, M6);           // get the address of the first constructor
      R0 = PASS R0, I13 = R0;    // check if it's the NULL list terminator
.call_ctors:
      IF EQ JUMP (PC, .call_ctors_next); // if NULL we found the list end
 
      I6 = I7;
      JUMP (M13, I13) (DB);      // call the constructor
         DM(I7, M7) = R5;
         DM(I7, M7) = PC;
      JUMP (PC, .call_ctors) (DB);
         R0 = DM(I0, M6);        // get the address of the next constructor
         R0 = PASS R0, I13 = R0; // check if it's the NULL list terminator
.call_ctors_next:
      R15 = R15 - 1;             // decrement counter
      If EQ JUMP (PC, .call_ctors_exit);
 
      I0 = __ctors;              // word-addressing constructors list
 
      I7 = B2W(I7);
      B7 = B2W(B7);
      JUMP (PC, .call_ctors_start) (DB);
         I6 = B2W(I6);
         B6 = B2W(B6);
.call_ctors_exit:
 
      /*
      ** Transform back to byte-addressed frame.
      */
      I7 = W2B(I7);
      B7 = W2B(B7);
      I6 = W2B(I6);
      B6 = W2B(B6);
 
      R4 = R4 - R4,              // argc = 0
         R8 = M5;                // argv = NULL
 
 
/*$VDSG<insert-code-before-call-to-main>                        */
.start_of_user_code1:
      /*
      ** Insert any additional code to be executed before calling main() here.
      ** Code inserted here is preserved when this file is re-generated.
      ** Avoid clobbering the values of registers R4 and R8 as they hold
      ** the argc and argv parameters for main().
      */
.end_of_start_of_user_code1:
/*$VDSG<insert-code-before-call-to-main>                        */
 
      .EXTERN main.;
      JUMP main. (DB);           // call main()
         DM(I7, M7) = 0;         // NULL FP to terminate call stack unwinding
         DM(I7, M7) = ___lib_prog_term-1;
 
.start.end:
 
      .GLOBAL ___lib_prog_term;
___lib_prog_term:                // Automatic breakpoint location.
      NOP;                       // Placed prior to loop label so that we
                                 // break only once.
.lib_prog_term_loop:
      IDLE;
      JUMP .lib_prog_term_loop;  // Stay put.
.___lib_prog_term.end:
 
      /*
      ** The call to _adi_osal_Init returned an error so call _adi_fatal_error.
      */
      .EXTERN adi_fatal_error.;
.osal_Init_failed:
      R12 = R0;                  // pass adi_osal_Init result value
      JUMP adi_fatal_error. (DB); // doesn't return
         R4 = _AFE_G_LibraryError;
         R8 = _AFE_S_adi_osal_Init_failure;
.osal_Init_failed.end: