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