1/* 2 * Copyright (c) 2016 Cadence Design Systems, Inc. 3 * SPDX-License-Identifier: Apache-2.0 4 */ 5 6/* 7 * Control arrives here at _start from the reset vector. 8 */ 9 10#include <xtensa/coreasm.h> 11 12/* Exports */ 13.global _start 14 15/* 16 * Imports 17 * __stack from linker script (see LSP Ref Manual) 18 * _bss_table_start from linker script (see LSP Ref Manual) 19 * _bss_table_end from linker script (see LSP Ref Manual) 20 * z_cstart Entry point into Zephyr C domain 21 * __stack from linker script (see LSP Ref Manual) 22 */ 23 24.global __start 25.type z_prep_c, @function 26 27 28/* Macros to abstract away ABI differences */ 29 30#if __XTENSA_CALL0_ABI__ 31# define CALL call0 32# define CALLX callx0 33# define ARG1 a2 /* 1st outgoing call argument */ 34# define ARG2 a3 /* 2nd outgoing call argument */ 35# define ARG3 a4 /* 3rd outgoing call argument */ 36# define ARG4 a5 /* 4th outgoing call argument */ 37# define ARG5 a6 /* 5th outgoing call argument */ 38#else 39# define CALL call4 40# define CALLX callx4 41# define ARG1 a6 /* 1st outgoing call argument */ 42# define ARG2 a7 /* 2nd outgoing call argument */ 43# define ARG3 a8 /* 3rd outgoing call argument */ 44# define ARG4 a9 /* 4th outgoing call argument */ 45# define ARG5 a10 /* 5th outgoing call argument */ 46#endif 47 48 .text 49 .align 4 50 51_start: 52 /* 53 * _start is typically NOT at the beginning of the text segment -- 54 * it is always called from either the reset vector (__start) or other 55 * code that does equivalent initialization. 56 * 57 * Assumptions on entry to _start: 58 * - low (level-one) and medium priority interrupts are disabled 59 * via PS.INTLEVEL and/or INTENABLE 60 * - C calling context not initialized: 61 * - PS not initialized 62 * - SP not initialized 63 * - the following are initialized: 64 * - LITBASE, cache attributes, WindowBase, WindowStart, 65 * CPENABLE, FP's FCR and FSR, EXCSAVE[n] 66 67 * Keep a0 zero. It is used to initialize a few things. 68 * It is also the return address, where zero indicates 69 * that the frame used by _start is the bottommost frame. 70 * 71 */ 72/* not needed for Xtensa TX */ 73#if !XCHAL_HAVE_HALT || !XCHAL_HAVE_BOOTLOADER 74 movi a0, 0 /* keep this register zero. */ 75#endif 76 77 /* 78 * Initialize the stack pointer. 79 * See the "ABI and Software Conventions" chapter in the 80 * Xtensa ISA Reference manual for details. 81 * 82 * NOTE: Because the _start routine does not use any memory in its 83 * stack frame, and because all of its CALL instructions use a 84 * window size of 4, the stack frame for _start can be empty. 85 */ 86 movi sp, __stack 87 88 /* 89 * Now that sp (a1) is set, we can set PS as per the application (user 90 * vector mode, disable interrupts, enable window exceptions if 91 * applicable). 92 */ 93#if XCHAL_HAVE_EXCEPTIONS 94# ifdef __XTENSA_CALL0_ABI__ 95 /* 96 * PS.WOE = 0 97 * PS.UM = 1 98 * PS.EXCM = 0 99 * PS.INTLEVEL = XCHAL_EXCM_LEVEL 100 */ 101 movi a3, PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) 102# else 103 /* 104 * PS.WOE = 1 105 * PS.UM = 1 106 * PS.EXCM = 0 107 * PS.INTLEVEL = XCHAL_EXCM_LEVEL 108 */ 109 movi a3, PS_UM|PS_WOE|PS_INTLEVEL(XCHAL_EXCM_LEVEL) 110# endif 111 wsr a3, PS 112 rsync 113#endif 114 115 116 /* 117 * Do any initialization that affects the memory map, such as 118 * setting up TLB entries, that needs to be done before we can 119 * successfully clear BSS (e.g. if some BSS segments are in 120 * remapped areas). 121 * 122 * NOTE: This hook works where the reset vector does not unpack 123 * segments (see "ROM packing" in the LSP manual), or where 124 * unpacking of segments is not affected by memory remapping. 125 * If ROM unpacking is affected, TLB setup must be done in 126 * assembler from the reset vector. 127 * 128 * The __memmap_init() routine can be a C function, however it 129 * does not have BSS initialized! In particular, __memmap_init() 130 * cannot set BSS variables, i.e. uninitialized global variables 131 * (they'll be wiped out by the following BSS clear), nor can it 132 * assume they are yet initialized to zero. 133 * 134 * The __memmap_init() function is optional. It is marked as a 135 * weak symbol, so that it gets valued zero if not defined. 136 */ 137 .weak __memmap_init 138 movi a4, __memmap_init 139 beqz a4, 1f 140 CALLX a4 1411: 142 143#if !XCHAL_HAVE_BOOTLOADER /* boot loader takes care of zeroing BSS */ 144 145# ifdef __XTENSA_CALL0_ABI__ 146 /* Clear a0 again as possible CALLX to __memmap_init changed it. */ 147 movi a0, 0 148# endif 149 150 /* 151 * Clear the BSS (uninitialized data) segments. 152 * This code supports multiple zeroed sections (*.bss). 153 * 154 * Register allocation: 155 * a0 = 0 156 * a6 = pointer to start of table, and through table 157 * a7 = pointer to end of table 158 * a8 = start address of bytes to be zeroed 159 * a9 = end address of bytes to be zeroed 160 * a10 = length of bytes to be zeroed 161 */ 162 movi a6, _bss_table_start 163 movi a7, _bss_table_end 164 bgeu a6, a7, .L3zte 165 166.L0zte: l32i a8, a6, 0 /* get start address, assumed multiple of 4 */ 167 l32i a9, a6, 4 /* get end address, assumed multiple of 4 */ 168 addi a6, a6, 8 /* next entry */ 169 sub a10, a9, a8 /* a10 = length, assumed a multiple of 4 */ 170 bbci.l a10, 2, .L1zte 171 s32i a0, a8, 0 /* clear 4 bytes to make len multiple of 8 */ 172 addi a8, a8, 4 173.L1zte: bbci.l a10, 3, .L2zte 174 s32i a0, a8, 0 /* clear 8 bytes to make len multiple of 16 */ 175 s32i a0, a8, 4 176 addi a8, a8, 8 177.L2zte: srli a10, a10, 4 /* len is now multiple of 16, divide by 16 */ 178 floopnez a10, clearzte 179 s32i a0, a8, 0 /* clear 16 bytes at a time... */ 180 s32i a0, a8, 4 181 s32i a0, a8, 8 182 s32i a0, a8, 12 183 addi a8, a8, 16 184 floopend a10, clearzte 185 186 bltu a6, a7, .L0zte /* loop until end of table of *.bss sections */ 187.L3zte: 188 189#endif /* !XCHAL_HAVE_BOOTLOADER */ 190 191 /* Enter C domain, never returns from here */ 192 CALL z_prep_c 193 194 .size _start, . - _start 195