3 // For most hardware / boards, this code sets up the C calling context
4 // (setting up stack, PS, and clearing BSS) and jumps to __clibrary_start
5 // which sets up the C library, calls constructors and registers destructors,
8 // Control arrives here at _start from the reset vector or from crt0-app.S.
10 // Copyright (c) 1998-2010 Tensilica Inc.
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <xtensa/coreasm.h>
32 #include "xtos-internal.h"
39 // __clibrary_init from C library (eg. newlib or uclibc)
40 // exit from C library
41 // main from user application
42 // board_init board-specific (uart/mingloss/tinygloss.c)
43 // xthal_dcache_all_writeback from HAL library
44 // __stack from linker script (see LSP Ref Manual)
45 // _bss_table_start from linker script (see LSP Ref Manual)
46 // _bss_table_end from linker script (see LSP Ref Manual)
50 // Macros to abstract away ABI differences
52 #if __XTENSA_CALL0_ABI__
54 # define ARG1 a2 /* 1st outgoing call argument */
55 # define ARG2 a3 /* 2nd outgoing call argument */
56 # define ARG3 a4 /* 3rd outgoing call argument */
57 # define ARG4 a5 /* 4th outgoing call argument */
58 # define ARG5 a6 /* 5th outgoing call argument */
61 # define ARG1 a6 /* 1st outgoing call argument */
62 # define ARG2 a7 /* 2nd outgoing call argument */
63 # define ARG3 a8 /* 3rd outgoing call argument */
64 # define ARG4 a9 /* 4th outgoing call argument */
65 # define ARG5 a10 /* 5th outgoing call argument */
69 /**************************************************************************/
74 // _start is typically NOT at the beginning of the text segment --
75 // it is always called from either the reset vector or other code
76 // that does equivalent initialization (such as crt0-app.S).
78 // Assumptions on entry to _start:
79 // - low (level-one) and medium priority interrupts are disabled
80 // via PS.INTLEVEL and/or INTENABLE (PS.INTLEVEL is expected to
81 // be zeroed, to potentially enable them, before calling main)
82 // - C calling context not initialized:
83 // - PS not initialized
84 // - SP not initialized
85 // - the following are initialized:
86 // - LITBASE, cache attributes, WindowBase, WindowStart,
87 // CPENABLE, FP's FCR and FSR, EXCSAVE[n]
89 // Keep a0 zero. It is used to initialize a few things.
90 // It is also the return address, where zero indicates
91 // that the frame used by _start is the bottommost frame.
93 #if !XCHAL_HAVE_HALT || !XCHAL_HAVE_BOOTLOADER // not needed for Xtensa TX
94 movi a0, 0 // keep this register zero.
97 #if XTOS_RESET_UNNEEDED && !XCHAL_HAVE_HALT
98 #include "reset-unneeded.S"
101 // Initialize the stack pointer.
102 // See the "ABI and Software Conventions" chapter in the
103 // Xtensa ISA Reference manual for details.
105 // NOTE: Because the _start routine does not use any memory in its
106 // stack frame, and because all of its CALL instructions use a
107 // window size of 4 (or zero), the stack frame for _start can be empty.
112 * Now that sp (a1) is set, we can set PS as per the application
113 * (user vector mode, enable interrupts, enable window exceptions if applicable).
115 #if XCHAL_HAVE_EXCEPTIONS
116 # ifdef __XTENSA_CALL0_ABI__
117 movi a3, PS_UM // PS.WOE = 0, PS.UM = 1, PS.EXCM = 0, PS.INTLEVEL = 0
119 movi a3, PS_UM|PS_WOE // PS.WOE = 1, PS.UM = 1, PS.EXCM = 0, PS.INTLEVEL = 0
126 #if !XCHAL_HAVE_BOOTLOADER /* boot loader takes care of zeroing BSS */
128 * Clear the BSS (uninitialized data) segments.
129 * This code supports multiple zeroed sections (*.bss).
131 * Register allocation:
133 * a6 = pointer to start of table, and through table
134 * a7 = pointer to end of table
135 * a8 = start address of bytes to be zeroed
136 * a9 = end address of bytes to be zeroed
137 * a10 = length of bytes to be zeroed
139 movi a6, _bss_table_start
140 movi a7, _bss_table_end
143 .L0zte: l32i a8, a6, 0 // get start address, assumed multiple of 4
144 l32i a9, a6, 4 // get end address, assumed multiple of 4
145 addi a6, a6, 8 // next entry
146 sub a10, a9, a8 // a10 = length, assumed a multiple of 4
147 bbci.l a10, 2, .L1zte
148 s32i a0, a8, 0 // clear 4 bytes to make length multiple of 8
150 .L1zte: bbci.l a10, 3, .L2zte
151 s32i a0, a8, 0 // clear 8 bytes to make length multiple of 16
154 .L2zte: srli a10, a10, 4 // length is now multiple of 16, divide by 16
155 floopnez a10, clearzte
156 s32i a0, a8, 0 // clear 16 bytes at a time...
161 floopend a10, clearzte
163 bltu a6, a7, .L0zte // loop until end of table of *.bss sections
168 // We can now call C code, the C calling environment has been initialized.
170 // From this point on, we use ABI-specific macros to refer to registers a0 .. a15
176 // Assume minimalist environment for memory-constrained TX cores.
177 // No C library or board initialization, no parameters passed to main
178 // (assume declared as "void main(void)") and no call to exit().
185 .type board_init, @function
186 .type __clibrary_init, @function
187 .type exit, @function
190 // Initialize the board (eg. the UART on the XT2000).
194 * Call __clibrary_init to initialize the C library:
196 * void __clibrary_init(int argc, char ** argv, char ** environ,
197 * void(*init_func)(void), void(*fini_func)(void));
200 // Pass an empty argv array, with an empty string as the program name.
202 movi ARG1, _start_argc // argc address
203 movi ARG2, _start_argv // argv = ["", 0]
204 movi ARG3, _start_envp // envp = [0]
205 movi ARG4, _init // function that calls constructors
206 movi ARG5, _fini // function that calls destructors
207 l32i ARG1, ARG1, 0 // argc = 1
210 // Call: int main(int argc, char ** argv, char ** environ);
211 movi ARG1, _start_argc // argc address
212 movi ARG2, _start_argv // argv = ["", 0]
213 movi ARG3, _start_envp // envp = [0]
214 l32i ARG1, ARG1, 0 // argc = 1
216 // The return value is the same register as the first outgoing argument.
217 CALL exit // exit with main's return value
218 // Does not return here.
221 // Mark argc/argv/envp parameters as weak so that an external
222 // object file can override them.
223 .weak _start_argc, _start_argv, _start_envp
226 .word _start_null // empty program name
229 .word 0 // end of argv array, empty string, empty environ
231 .word 1 // one argument (program name)
236 .size _start, . - _start