/* ** 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 // defines silicon anomaly macros #include // defines interrupt support #include // defines MMR macros #include // OSAL support #include // 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 */ .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 */ /* ** Initializes the processor, memory, C runtime and heaps. */ .EXTERN ___lib_setup_c; CALL ___lib_setup_c; /*$VDSG */ .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 */ /* ** 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 */ .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 */ .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: