Loading...
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 | /* * Copyright (c) 2016 Cadence Design Systems, Inc. * SPDX-License-Identifier: Apache-2.0 */ /* * Control arrives here at _start from the reset vector or from crt0-app.S. */ #include <xtensa_rtos.h> /* Exports */ .global _start /* * Imports * __stack from linker script (see LSP Ref Manual) * _bss_table_start from linker script (see LSP Ref Manual) * _bss_table_end from linker script (see LSP Ref Manual) * _Cstart Entry point into Zephyr C domain * __stack from linker script (see LSP Ref Manual) */ .global __start .type _Cstart, @function /* Macros to abstract away ABI differences */ #if __XTENSA_CALL0_ABI__ # define CALL call0 # define CALLX callx0 # define ARG1 a2 /* 1st outgoing call argument */ # define ARG2 a3 /* 2nd outgoing call argument */ # define ARG3 a4 /* 3rd outgoing call argument */ # define ARG4 a5 /* 4th outgoing call argument */ # define ARG5 a6 /* 5th outgoing call argument */ #else # define CALL call4 # define CALLX callx4 # define ARG1 a6 /* 1st outgoing call argument */ # define ARG2 a7 /* 2nd outgoing call argument */ # define ARG3 a8 /* 3rd outgoing call argument */ # define ARG4 a9 /* 4th outgoing call argument */ # define ARG5 a10 /* 5th outgoing call argument */ #endif .text .align 4 _start: __start: /* * _start is typically NOT at the beginning of the text segment -- * it is always called from either the reset vector or other code * that does equivalent initialization (such as crt0-app.S). * * Assumptions on entry to _start: * - low (level-one) and medium priority interrupts are disabled * via PS.INTLEVEL and/or INTENABLE (PS.INTLEVEL is expected to * be zeroed, to potentially enable them, before calling main) * - C calling context not initialized: * - PS not initialized * - SP not initialized * - the following are initialized: * - LITBASE, cache attributes, WindowBase, WindowStart, * CPENABLE, FP's FCR and FSR, EXCSAVE[n] * Keep a0 zero. It is used to initialize a few things. * It is also the return address, where zero indicates * that the frame used by _start is the bottommost frame. * */ /* not needed for Xtensa TX */ #if !XCHAL_HAVE_HALT || !XCHAL_HAVE_BOOTLOADER movi a0, 0 /* keep this register zero. */ #endif /* * Initialize the stack pointer. * See the "ABI and Software Conventions" chapter in the * Xtensa ISA Reference manual for details. * * NOTE: Because the _start routine does not use any memory in its * stack frame, and because all of its CALL instructions use a * window size of 4, the stack frame for _start can be empty. */ movi sp, __stack /* * Now that sp (a1) is set, we can set PS as per the application (user * vector mode, enable interrupts, enable window exceptions if * applicable). */ #if XCHAL_HAVE_EXCEPTIONS # ifdef __XTENSA_CALL0_ABI__ /* PS.WOE = 0, PS.UM = 1, PS.EXCM = 0, PS.INTLEVEL = 0 */ movi a3, PS_UM # else /* PS.WOE = 1, PS.UM = 1, PS.EXCM = 0, PS.INTLEVEL = 0 */ movi a3, PS_UM|PS_WOE # endif wsr a3, PS rsync #endif /* * Do any initialization that affects the memory map, such as * setting up TLB entries, that needs to be done before we can * successfully clear BSS (e.g. if some BSS segments are in * remapped areas). * * NOTE: This hook works where the reset vector does not unpack * segments (see "ROM packing" in the LSP manual), or where * unpacking of segments is not affected by memory remapping. * If ROM unpacking is affected, TLB setup must be done in * assembler from the reset vector. * * The __memmap_init() routine can be a C function, however it * does not have BSS initialized! In particular, __memmap_init() * cannot set BSS variables, i.e. uninitialized global variables * (they'll be wiped out by the following BSS clear), nor can it * assume they are yet initialized to zero. * * The __memmap_init() function is optional. It is marked as a * weak symbol, so that it gets valued zero if not defined. */ .weak __memmap_init movi a4, __memmap_init beqz a4, 1f CALLX a4 1: #if !XCHAL_HAVE_BOOTLOADER /* boot loader takes care of zeroing BSS */ # ifdef __XTENSA_CALL0_ABI__ /* Clear a0 again as possible CALLX to __memmap_init changed it. */ movi a0, 0 # endif /* * Clear the BSS (uninitialized data) segments. * This code supports multiple zeroed sections (*.bss). * * Register allocation: * a0 = 0 * a6 = pointer to start of table, and through table * a7 = pointer to end of table * a8 = start address of bytes to be zeroed * a9 = end address of bytes to be zeroed * a10 = length of bytes to be zeroed */ movi a6, _bss_table_start movi a7, _bss_table_end bgeu a6, a7, .L3zte .L0zte: l32i a8, a6, 0 /* get start address, assumed multiple of 4 */ l32i a9, a6, 4 /* get end address, assumed multiple of 4 */ addi a6, a6, 8 /* next entry */ sub a10, a9, a8 /* a10 = length, assumed a multiple of 4 */ bbci.l a10, 2, .L1zte s32i a0, a8, 0 /* clear 4 bytes to make len multiple of 8 */ addi a8, a8, 4 .L1zte: bbci.l a10, 3, .L2zte s32i a0, a8, 0 /* clear 8 bytes to make len multiple of 16 */ s32i a0, a8, 4 addi a8, a8, 8 .L2zte: srli a10, a10, 4 /* len is now multiple of 16, divide by 16 */ floopnez a10, clearzte s32i a0, a8, 0 /* clear 16 bytes at a time... */ s32i a0, a8, 4 s32i a0, a8, 8 s32i a0, a8, 12 addi a8, a8, 16 floopend a10, clearzte bltu a6, a7, .L0zte /* loop until end of table of *.bss sections */ .L3zte: #endif /* !XCHAL_HAVE_BOOTLOADER */ /* Enter C domain, never returns from here */ CALL _Cstart .size _start, . - _start |