zephyr/arch/xtensa/core/crt1.S
Anas Nashif 42396735bf xtensa: introduce prep_c for xtensa
xtensa is the only architecutre doing thing differently and introduces
inconsistency in the init process and dependencies as we attemp to
cleanup init levels and remove misused of SYS_INIT.

Introduce prep_c for this architecture and align with other
architectures.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2024-08-07 13:50:53 +02:00

195 lines
5.5 KiB
ArmAsm

/*
* Copyright (c) 2016 Cadence Design Systems, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Control arrives here at _start from the reset vector.
*/
#include <xtensa/coreasm.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)
* z_cstart Entry point into Zephyr C domain
* __stack from linker script (see LSP Ref Manual)
*/
.global __start
.type z_prep_c, @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 is typically NOT at the beginning of the text segment --
* it is always called from either the reset vector (__start) or other
* code that does equivalent initialization.
*
* Assumptions on entry to _start:
* - low (level-one) and medium priority interrupts are disabled
* via PS.INTLEVEL and/or INTENABLE
* - 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, disable 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 = XCHAL_EXCM_LEVEL
*/
movi a3, PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL)
# else
/*
* PS.WOE = 1
* PS.UM = 1
* PS.EXCM = 0
* PS.INTLEVEL = XCHAL_EXCM_LEVEL
*/
movi a3, PS_UM|PS_WOE|PS_INTLEVEL(XCHAL_EXCM_LEVEL)
# 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 z_prep_c
.size _start, . - _start