xref: /openbmc/u-boot/arch/xtensa/cpu/start.S (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini/* SPDX-License-Identifier: GPL-2.0+ */
2c978b524SChris Zankel/*
3c978b524SChris Zankel * (C) Copyright 2008 - 2013 Tensilica Inc.
4c978b524SChris Zankel * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
5c978b524SChris Zankel */
6c978b524SChris Zankel
7c978b524SChris Zankel#include <config.h>
8c978b524SChris Zankel#include <asm/asmmacro.h>
9c978b524SChris Zankel#include <asm/cacheasm.h>
10c978b524SChris Zankel#include <asm/regs.h>
11c978b524SChris Zankel#include <asm/arch/tie.h>
12c978b524SChris Zankel#include <asm-offsets.h>
13c978b524SChris Zankel
14c978b524SChris Zankel/*
15c978b524SChris Zankel * Offsets into the the pt_regs struture.
16c978b524SChris Zankel * Make sure these always match with the structure defined in ptrace.h!
17c978b524SChris Zankel */
18c978b524SChris Zankel
19c978b524SChris Zankel#define PT_PC		0
20c978b524SChris Zankel#define PT_PS		4
21c978b524SChris Zankel#define PT_DEPC		8
22c978b524SChris Zankel#define PT_EXCCAUSE	12
23c978b524SChris Zankel#define PT_EXCVADDR	16
24c978b524SChris Zankel#define PT_DEBUGCAUSE	20
25c978b524SChris Zankel#define PT_WMASK	24
26c978b524SChris Zankel#define PT_LBEG		28
27c978b524SChris Zankel#define PT_LEND		32
28c978b524SChris Zankel#define PT_LCOUNT	36
29c978b524SChris Zankel#define PT_SAR		40
30c978b524SChris Zankel#define PT_WINDOWBASE	44
31c978b524SChris Zankel#define PT_WINDOWSTART	48
32c978b524SChris Zankel#define PT_SYSCALL	52
33c978b524SChris Zankel#define PT_ICOUNTLEVEL	56
34c978b524SChris Zankel#define PT_RESERVED	60
35c978b524SChris Zankel#define PT_AREG		64
36c978b524SChris Zankel#define PT_SIZE		(64 + 64)
37c978b524SChris Zankel
38c978b524SChris Zankel/*
39c978b524SChris Zankel * Cache attributes are different for full MMU and region protection.
40c978b524SChris Zankel */
41c978b524SChris Zankel
42c978b524SChris Zankel#if XCHAL_HAVE_PTP_MMU
43c978b524SChris Zankel#define CA_WRITEBACK	(0x7)
44c978b524SChris Zankel#else
45c978b524SChris Zankel#define CA_WRITEBACK	(0x4)
46c978b524SChris Zankel#endif
47c978b524SChris Zankel
48c978b524SChris Zankel/*
49c978b524SChris Zankel * Reset vector.
50c978b524SChris Zankel * Only a trampoline to jump to _start
51c978b524SChris Zankel * (Note that we have to mark the section writable as the section contains
52c978b524SChris Zankel *  a relocatable literal)
53c978b524SChris Zankel */
54c978b524SChris Zankel
55c978b524SChris Zankel	.section .ResetVector.text, "awx"
56c978b524SChris Zankel	.global _ResetVector
57c978b524SChris Zankel_ResetVector:
58c978b524SChris Zankel
59c978b524SChris Zankel	j	1f
60c978b524SChris Zankel	.align 4
61c978b524SChris Zankel2:	.long	_start
62c978b524SChris Zankel1:	l32r	a2, 2b
63c978b524SChris Zankel	jx	a2
64c978b524SChris Zankel
65c978b524SChris Zankel
66c978b524SChris Zankel/*
67c978b524SChris Zankel * Processor initialization. We still run in rom space.
68c978b524SChris Zankel *
69c978b524SChris Zankel * NOTE: Running in ROM
70c978b524SChris Zankel *  For Xtensa, we currently don't allow to run some code from ROM but
71c978b524SChris Zankel *  unpack the data immediately to memory. This requires, for example,
72c978b524SChris Zankel *  that DDR has been set up before running U-Boot. (See also comments
73c978b524SChris Zankel *  inline for ways to change it)
74c978b524SChris Zankel */
75c978b524SChris Zankel
76c978b524SChris Zankel	.section .reset.text, "ax"
77c978b524SChris Zankel	.global _start
78c978b524SChris Zankel	.align 4
79c978b524SChris Zankel_start:
80c978b524SChris Zankel	/* Keep a0 = 0 for various initializations */
81c978b524SChris Zankel
82c978b524SChris Zankel	movi	a0, 0
83c978b524SChris Zankel
84c978b524SChris Zankel	/*
85c978b524SChris Zankel	 * For full MMU cores, put page table at unmapped virtual address.
86c978b524SChris Zankel	 * This ensures that accesses outside the static maps result
87c978b524SChris Zankel	 * in miss exceptions rather than random behaviour.
88c978b524SChris Zankel	 */
89c978b524SChris Zankel
90c978b524SChris Zankel#if XCHAL_HAVE_PTP_MMU
91c978b524SChris Zankel	wsr	a0, PTEVADDR
92c978b524SChris Zankel#endif
93c978b524SChris Zankel
94c978b524SChris Zankel	/* Disable dbreak debug exceptions */
95c978b524SChris Zankel
96c978b524SChris Zankel#if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0
97c978b524SChris Zankel	.set	_index, 0
98c978b524SChris Zankel	.rept	XCHAL_NUM_DBREAK
99c978b524SChris Zankel	wsr	a0, DBREAKC + _index
100c978b524SChris Zankel	.set	_index, _index + 1
101c978b524SChris Zankel	.endr
102c978b524SChris Zankel#endif
103c978b524SChris Zankel
104c978b524SChris Zankel	/* Reset windowbase and windowstart */
105c978b524SChris Zankel
106c978b524SChris Zankel#if XCHAL_HAVE_WINDOWED
107c978b524SChris Zankel	movi	a3, 1
108c978b524SChris Zankel	wsr	a3, windowstart
109c978b524SChris Zankel	wsr	a0, windowbase
110c978b524SChris Zankel	rsync
111c978b524SChris Zankel	movi	a0, 0			/* windowbase might have changed */
112c978b524SChris Zankel#endif
113c978b524SChris Zankel
114c978b524SChris Zankel	/*
115c978b524SChris Zankel	 * Vecbase in bitstream may differ from header files
116c978b524SChris Zankel	 * set or check it.
117c978b524SChris Zankel	 */
118c978b524SChris Zankel
119c978b524SChris Zankel#if XCHAL_HAVE_VECBASE
120c978b524SChris Zankel	movi	a3, XCHAL_VECBASE_RESET_VADDR	/* VECBASE reset value */
121c978b524SChris Zankel	wsr	a3, VECBASE
122c978b524SChris Zankel#endif
123c978b524SChris Zankel
124c978b524SChris Zankel#if XCHAL_HAVE_LOOPS
125c978b524SChris Zankel	/* Disable loops */
126c978b524SChris Zankel
127c978b524SChris Zankel	wsr	a0, LCOUNT
128c978b524SChris Zankel#endif
129c978b524SChris Zankel
130c978b524SChris Zankel	/* Set PS.WOE = 0, PS.EXCM = 0 (for loop), PS.INTLEVEL = EXCM level */
131c978b524SChris Zankel
132c978b524SChris Zankel#if XCHAL_HAVE_XEA1
133c978b524SChris Zankel	movi	a2, 1
134c978b524SChris Zankel#else
135c978b524SChris Zankel	movi	a2, XCHAL_EXCM_LEVEL
136c978b524SChris Zankel#endif
137c978b524SChris Zankel	wsr	a2, PS
138c978b524SChris Zankel	rsync
139c978b524SChris Zankel
140c978b524SChris Zankel	/* Unlock and invalidate caches */
141c978b524SChris Zankel
142c978b524SChris Zankel	___unlock_dcache_all a2, a3
143c978b524SChris Zankel	___invalidate_dcache_all a2, a3
144c978b524SChris Zankel	___unlock_icache_all a2, a3
145c978b524SChris Zankel	___invalidate_icache_all a2, a3
146c978b524SChris Zankel
147c978b524SChris Zankel	isync
148c978b524SChris Zankel
149c978b524SChris Zankel	/* Unpack data sections */
150c978b524SChris Zankel
151c978b524SChris Zankel	movi	a2, __reloc_table_start
152c978b524SChris Zankel	movi	a3, __reloc_table_end
153c978b524SChris Zankel
154c978b524SChris Zankel1:	beq	a2, a3, 3f	# no more entries?
155c978b524SChris Zankel	l32i	a4, a2, 0	# start destination (in RAM)
156c978b524SChris Zankel	l32i	a5, a2, 4	# end destination (in RAM)
157c978b524SChris Zankel	l32i	a6, a2, 8	# start source (in ROM)
158c978b524SChris Zankel	addi	a2, a2, 12	# next entry
159c978b524SChris Zankel	beq	a4, a5, 1b	# skip, empty entry
160c978b524SChris Zankel	beq	a4, a6, 1b	# skip, source and destination are the same
161c978b524SChris Zankel
162c978b524SChris Zankel	/* If there's memory protection option with 512MB TLB regions and
163c978b524SChris Zankel	 * cache attributes in TLB entries and caching is not inhibited,
164c978b524SChris Zankel	 * enable data/instruction cache for relocated image.
165c978b524SChris Zankel	 */
166c978b524SChris Zankel#if XCHAL_HAVE_SPANNING_WAY && \
167c978b524SChris Zankel	(!defined(CONFIG_SYS_DCACHE_OFF) || \
168c978b524SChris Zankel	 !defined(CONFIG_SYS_ICACHE_OFF))
169c978b524SChris Zankel	srli	a7, a4, 29
170c978b524SChris Zankel	slli	a7, a7, 29
171c978b524SChris Zankel	addi	a7, a7, XCHAL_SPANNING_WAY
172c978b524SChris Zankel#ifndef CONFIG_SYS_DCACHE_OFF
173c978b524SChris Zankel	rdtlb1	a8, a7
174c978b524SChris Zankel	srli	a8, a8, 4
175c978b524SChris Zankel	slli	a8, a8, 4
176c978b524SChris Zankel	addi	a8, a8, CA_WRITEBACK
177c978b524SChris Zankel	wdtlb	a8, a7
178c978b524SChris Zankel#endif
179c978b524SChris Zankel#ifndef CONFIG_SYS_ICACHE_OFF
180c978b524SChris Zankel	ritlb1	a8, a7
181c978b524SChris Zankel	srli	a8, a8, 4
182c978b524SChris Zankel	slli	a8, a8, 4
183c978b524SChris Zankel	addi	a8, a8, CA_WRITEBACK
184c978b524SChris Zankel	witlb	a8, a7
185c978b524SChris Zankel#endif
186c978b524SChris Zankel	isync
187c978b524SChris Zankel#endif
188c978b524SChris Zankel
189c978b524SChris Zankel2:	l32i	a7, a6, 0
190c978b524SChris Zankel	addi	a6, a6, 4
191c978b524SChris Zankel	s32i	a7, a4, 0
192c978b524SChris Zankel	addi	a4, a4, 4
193c978b524SChris Zankel	bltu	a4, a5, 2b
194c978b524SChris Zankel	j	1b
195c978b524SChris Zankel
196c978b524SChris Zankel3:	/* All code and initalized data segments have been copied */
197c978b524SChris Zankel
198c978b524SChris Zankel	/* Setup PS, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
199c978b524SChris Zankel
200c978b524SChris Zankel#if __XTENSA_CALL0_ABI__
201c978b524SChris Zankel	movi	a2, XCHAL_EXCM_LEVEL
202c978b524SChris Zankel#else
203c978b524SChris Zankel	movi	a2, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
204c978b524SChris Zankel#endif
205c978b524SChris Zankel	wsr	a2, PS
206c978b524SChris Zankel	rsync
207c978b524SChris Zankel
208c978b524SChris Zankel	/* Writeback */
209c978b524SChris Zankel
210c978b524SChris Zankel	___flush_dcache_all a2, a3
211c978b524SChris Zankel
212c978b524SChris Zankel#ifdef __XTENSA_WINDOWED_ABI__
213c978b524SChris Zankel	/*
214c978b524SChris Zankel	 * In windowed ABI caller and call target need to be within the same
215c978b524SChris Zankel	 * gigabyte. Put the rest of the code into the text segment and jump
216c978b524SChris Zankel	 * there.
217c978b524SChris Zankel	 */
218c978b524SChris Zankel
219c978b524SChris Zankel	movi	a4, .Lboard_init_code
220c978b524SChris Zankel	jx	a4
221c978b524SChris Zankel
222c978b524SChris Zankel	.text
223c978b524SChris Zankel	.align	4
224c978b524SChris Zankel.Lboard_init_code:
225c978b524SChris Zankel#endif
226c978b524SChris Zankel
227c978b524SChris Zankel	movi	a0, 0
22810117a29SMax Filippov	movi	sp, (XTENSA_SYS_TEXT_ADDR - 16) & 0xfffffff0
229c978b524SChris Zankel
230c978b524SChris Zankel#ifdef CONFIG_DEBUG_UART
231c978b524SChris Zankel	movi	a4, debug_uart_init
232c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
233c978b524SChris Zankel	callx0	a4
234c978b524SChris Zankel#else
235c978b524SChris Zankel	callx4	a4
236c978b524SChris Zankel#endif
237c978b524SChris Zankel#endif
238c978b524SChris Zankel
239c978b524SChris Zankel	movi	a4, board_init_f_alloc_reserve
240c978b524SChris Zankel
241c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
242c978b524SChris Zankel	mov	a2, sp
243c978b524SChris Zankel	callx0	a4
244c978b524SChris Zankel	mov	sp, a2
245c978b524SChris Zankel#else
246c978b524SChris Zankel	mov	a6, sp
247c978b524SChris Zankel	callx4	a4
248c978b524SChris Zankel	movsp	sp, a6
249c978b524SChris Zankel#endif
250c978b524SChris Zankel
251c978b524SChris Zankel	movi	a4, board_init_f_init_reserve
252c978b524SChris Zankel
253c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
254c978b524SChris Zankel	callx0	a4
255c978b524SChris Zankel#else
256c978b524SChris Zankel	callx4	a4
257c978b524SChris Zankel#endif
258c978b524SChris Zankel
259c978b524SChris Zankel        /*
260c978b524SChris Zankel	 * Call board initialization routine (never returns).
261c978b524SChris Zankel	 */
262c978b524SChris Zankel
263c978b524SChris Zankel	movi	a4, board_init_f
264c978b524SChris Zankel
265c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
266c978b524SChris Zankel	movi	a2, 0
267c978b524SChris Zankel	callx0	a4
268c978b524SChris Zankel#else
269c978b524SChris Zankel	movi	a6, 0
270c978b524SChris Zankel	callx4	a4
271c978b524SChris Zankel#endif
272c978b524SChris Zankel	/* Never Returns */
273c978b524SChris Zankel	ill
274c978b524SChris Zankel
275c978b524SChris Zankel/*
276c978b524SChris Zankel * void relocate_code (addr_sp, gd, addr_moni)
277c978b524SChris Zankel *
278c978b524SChris Zankel * This "function" does not return, instead it continues in RAM
279c978b524SChris Zankel * after relocating the monitor code.
280c978b524SChris Zankel *
281c978b524SChris Zankel * a2 = addr_sp
282c978b524SChris Zankel * a3 = gd
283c978b524SChris Zankel * a4 = destination address
284c978b524SChris Zankel */
285c978b524SChris Zankel	.text
286c978b524SChris Zankel	.globl relocate_code
287c978b524SChris Zankel	.align 4
288c978b524SChris Zankelrelocate_code:
289c978b524SChris Zankel	abi_entry
290c978b524SChris Zankel
291c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
292c978b524SChris Zankel	mov	a1, a2
293c978b524SChris Zankel	mov	a2, a3
294c978b524SChris Zankel	mov	a3, a4
295c978b524SChris Zankel	movi	a0, board_init_r
296c978b524SChris Zankel	callx0	a0
297c978b524SChris Zankel#else
298c978b524SChris Zankel	/* We can't movsp here, because the chain of stack frames may cross
299c978b524SChris Zankel	 * the now reserved memory. We need to toss all window frames except
300c978b524SChris Zankel	 * the current, create new pristine stack frame and start from scratch.
301c978b524SChris Zankel	 */
302c978b524SChris Zankel	rsr	a0, windowbase
303c978b524SChris Zankel	ssl	a0
304c978b524SChris Zankel	movi	a0, 1
305c978b524SChris Zankel	sll	a0, a0
306c978b524SChris Zankel	wsr	a0, windowstart
307c978b524SChris Zankel	rsync
308c978b524SChris Zankel
309c978b524SChris Zankel	movi	a0, 0
310c978b524SChris Zankel
311c978b524SChris Zankel	/* Reserve 16-byte save area */
312c978b524SChris Zankel	addi	sp, a2, -16
313c978b524SChris Zankel	mov	a6, a3
314c978b524SChris Zankel	mov	a7, a4
315c978b524SChris Zankel	movi	a4, board_init_r
316c978b524SChris Zankel	callx4	a4
317c978b524SChris Zankel#endif
318c978b524SChris Zankel	ill
319c978b524SChris Zankel
320c978b524SChris Zankel#if XCHAL_HAVE_EXCEPTIONS
321c978b524SChris Zankel
322c978b524SChris Zankel/*
323c978b524SChris Zankel * Exception vectors.
324c978b524SChris Zankel *
325c978b524SChris Zankel *  Various notes:
326c978b524SChris Zankel *   - We currently don't use the user exception vector (PS.UM is always 0),
327c978b524SChris Zankel *     but do define such a vector, just in case. They both jump to the
328c978b524SChris Zankel *     same exception handler, though.
329c978b524SChris Zankel *   - We currently only save the bare minimum number of registers:
330c978b524SChris Zankel *     a0...a15, sar, loop-registers, exception register (epc1, excvaddr,
331c978b524SChris Zankel *     exccause, depc)
332c978b524SChris Zankel *   - WINDOWSTART is only saved to identify if registers have been spilled
333c978b524SChris Zankel *     to the wrong stack (exception stack) while executing the exception
334c978b524SChris Zankel *     handler.
335c978b524SChris Zankel */
336c978b524SChris Zankel
337c978b524SChris Zankel	.section .KernelExceptionVector.text, "ax"
338c978b524SChris Zankel	.global _KernelExceptionVector
339c978b524SChris Zankel_KernelExceptionVector:
340c978b524SChris Zankel
341c978b524SChris Zankel	wsr	a2, EXCSAVE1
342c978b524SChris Zankel	movi	a2, ExceptionHandler
343c978b524SChris Zankel	jx	a2
344c978b524SChris Zankel
345c978b524SChris Zankel	.section .UserExceptionVector.text, "ax"
346c978b524SChris Zankel	.global _UserExceptionVector
347c978b524SChris Zankel_UserExceptionVector:
348c978b524SChris Zankel
349c978b524SChris Zankel	wsr	a2, EXCSAVE1
350c978b524SChris Zankel	movi	a2, ExceptionHandler
351c978b524SChris Zankel	jx	a2
352c978b524SChris Zankel
353c978b524SChris Zankel#if !XCHAL_HAVE_XEA1
354c978b524SChris Zankel	.section .DoubleExceptionVector.text, "ax"
355c978b524SChris Zankel	.global _DoubleExceptionVector
356c978b524SChris Zankel_DoubleExceptionVector:
357c978b524SChris Zankel
358c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
359c978b524SChris Zankel	wsr	a0, EXCSAVE1
360c978b524SChris Zankel	movi    a0, hang                # report and ask user to reset board
361c978b524SChris Zankel	callx0	a0
362c978b524SChris Zankel#else
363c978b524SChris Zankel	wsr	a4, EXCSAVE1
364c978b524SChris Zankel	movi    a4, hang                # report and ask user to reset board
365c978b524SChris Zankel	callx4	a4
366c978b524SChris Zankel#endif
367c978b524SChris Zankel#endif
368c978b524SChris Zankel	/* Does not return here */
369c978b524SChris Zankel
370c978b524SChris Zankel
371c978b524SChris Zankel	.text
372c978b524SChris Zankel	.align 4
373c978b524SChris ZankelExceptionHandler:
374c978b524SChris Zankel
375c978b524SChris Zankel	rsr	a2, EXCCAUSE		# find handler
376c978b524SChris Zankel
377c978b524SChris Zankel#if XCHAL_HAVE_WINDOWED
378c978b524SChris Zankel	/* Special case for alloca handler */
379c978b524SChris Zankel
380c978b524SChris Zankel	bnei	a2, 5, 1f		# jump if not alloca exception
381c978b524SChris Zankel
382c978b524SChris Zankel	addi	a1, a1, -16 - 4		# create a small stack frame
383c978b524SChris Zankel	s32i	a3, a1, 0		# and save a3 (a2 still in excsave1)
384c978b524SChris Zankel	movi	a2, fast_alloca_exception
385c978b524SChris Zankel	jx	a2			# jump to fast_alloca_exception
386c978b524SChris Zankel#endif
387c978b524SChris Zankel	/* All other exceptions go here: */
388c978b524SChris Zankel
389c978b524SChris Zankel	/* Create ptrace stack and save a0...a3 */
390c978b524SChris Zankel
391c978b524SChris Zankel1:	addi	a2, a1, - PT_SIZE - 16
392c978b524SChris Zankel	s32i	a0, a2, PT_AREG + 0 * 4
393c978b524SChris Zankel	s32i	a1, a2, PT_AREG + 1 * 4
394c978b524SChris Zankel	s32i	a3, a2, PT_AREG + 3 * 4
395c978b524SChris Zankel	rsr	a3, EXCSAVE1
396c978b524SChris Zankel	s32i	a3, a2, PT_AREG + 2 * 4
397c978b524SChris Zankel	mov	a1, a2
398c978b524SChris Zankel
399c978b524SChris Zankel	/* Save remaining AR registers */
400c978b524SChris Zankel
401c978b524SChris Zankel	s32i	a4, a1, PT_AREG + 4 * 4
402c978b524SChris Zankel	s32i	a5, a1, PT_AREG + 5 * 4
403c978b524SChris Zankel	s32i	a6, a1, PT_AREG + 6 * 4
404c978b524SChris Zankel	s32i	a7, a1, PT_AREG + 7 * 4
405c978b524SChris Zankel	s32i	a8, a1, PT_AREG + 8 * 4
406c978b524SChris Zankel	s32i	a9, a1, PT_AREG + 9 * 4
407c978b524SChris Zankel	s32i	a10, a1, PT_AREG + 10 * 4
408c978b524SChris Zankel	s32i	a11, a1, PT_AREG + 11 * 4
409c978b524SChris Zankel	s32i	a12, a1, PT_AREG + 12 * 4
410c978b524SChris Zankel	s32i	a13, a1, PT_AREG + 13 * 4
411c978b524SChris Zankel	s32i	a14, a1, PT_AREG + 14 * 4
412c978b524SChris Zankel	s32i	a15, a1, PT_AREG + 15 * 4
413c978b524SChris Zankel
414c978b524SChris Zankel	/* Save SRs */
415c978b524SChris Zankel
416c978b524SChris Zankel#if XCHAL_HAVE_WINDOWED
417c978b524SChris Zankel	rsr	a2, WINDOWSTART
418c978b524SChris Zankel	s32i	a2, a1, PT_WINDOWSTART
419c978b524SChris Zankel#endif
420c978b524SChris Zankel
421c978b524SChris Zankel	rsr	a2, SAR
422c978b524SChris Zankel	rsr	a3, EPC1
423c978b524SChris Zankel	rsr	a4, EXCVADDR
424c978b524SChris Zankel	s32i	a2, a1, PT_SAR
425c978b524SChris Zankel	s32i	a3, a1, PT_PC
426c978b524SChris Zankel	s32i	a4, a1, PT_EXCVADDR
427c978b524SChris Zankel
428c978b524SChris Zankel#if XCHAL_HAVE_LOOPS
429c978b524SChris Zankel	movi	a2, 0
430c978b524SChris Zankel	rsr	a3, LBEG
431c978b524SChris Zankel	xsr	a2, LCOUNT
432c978b524SChris Zankel	s32i	a3, a1, PT_LBEG
433c978b524SChris Zankel	rsr	a3, LEND
434c978b524SChris Zankel	s32i	a2, a1, PT_LCOUNT
435c978b524SChris Zankel	s32i	a3, a1, PT_LEND
436c978b524SChris Zankel#endif
437c978b524SChris Zankel
438c978b524SChris Zankel	/* Set up C environment and call registered handler */
439c978b524SChris Zankel	/* Setup stack, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
440c978b524SChris Zankel
441c978b524SChris Zankel	rsr	a2, EXCCAUSE
442c978b524SChris Zankel#if XCHAL_HAVE_XEA1
443c978b524SChris Zankel	movi	a3, (1<<PS_WOE_BIT) | 1
444c978b524SChris Zankel#elif __XTENSA_CALL0_ABI__
445c978b524SChris Zankel	movi	a3, XCHAL_EXCM_LEVEL
446c978b524SChris Zankel#else
447c978b524SChris Zankel	movi	a3, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
448c978b524SChris Zankel#endif
449c978b524SChris Zankel	xsr	a3, PS
450c978b524SChris Zankel	rsync
451c978b524SChris Zankel	s32i	a2, a1, PT_EXCCAUSE
452c978b524SChris Zankel	s32i	a3, a1, PT_PS
453c978b524SChris Zankel
454c978b524SChris Zankel	movi	a0, exc_table
455c978b524SChris Zankel	addx4	a0, a2, a0
456c978b524SChris Zankel	l32i	a0, a0, 0
457c978b524SChris Zankel#ifdef __XTENSA_CALL0_ABI__
458c978b524SChris Zankel	mov	a2, a1			# Provide stack frame as only argument
459c978b524SChris Zankel	callx0	a0
460c978b524SChris Zankel	l32i	a3, a1, PT_PS
461c978b524SChris Zankel#else
462c978b524SChris Zankel	mov	a6, a1			# Provide stack frame as only argument
463c978b524SChris Zankel	callx4	a0
464c978b524SChris Zankel#endif
465c978b524SChris Zankel
466c978b524SChris Zankel	/* Restore PS and go to exception mode (PS.EXCM=1) */
467c978b524SChris Zankel
468c978b524SChris Zankel	wsr	a3, PS
469c978b524SChris Zankel
470c978b524SChris Zankel	/* Restore SR registers */
471c978b524SChris Zankel
472c978b524SChris Zankel#if XCHAL_HAVE_LOOPS
473c978b524SChris Zankel	l32i	a2, a1, PT_LBEG
474c978b524SChris Zankel	l32i	a3, a1, PT_LEND
475c978b524SChris Zankel	l32i	a4, a1, PT_LCOUNT
476c978b524SChris Zankel	wsr	a2, LBEG
477c978b524SChris Zankel	wsr	a3, LEND
478c978b524SChris Zankel	wsr	a4, LCOUNT
479c978b524SChris Zankel#endif
480c978b524SChris Zankel
481c978b524SChris Zankel	l32i	a2, a1, PT_SAR
482c978b524SChris Zankel	l32i	a3, a1, PT_PC
483c978b524SChris Zankel	wsr	a2, SAR
484c978b524SChris Zankel	wsr	a3, EPC1
485c978b524SChris Zankel
486c978b524SChris Zankel#if XCHAL_HAVE_WINDOWED
487c978b524SChris Zankel	/* Do we need to simulate a MOVSP? */
488c978b524SChris Zankel
489c978b524SChris Zankel	l32i	a2, a1, PT_WINDOWSTART
490c978b524SChris Zankel	addi	a3, a2, -1
491c978b524SChris Zankel	and	a2, a2, a3
492c978b524SChris Zankel	beqz	a2, 1f			# Skip if regs were spilled before exc.
493c978b524SChris Zankel
494c978b524SChris Zankel	rsr	a2, WINDOWSTART
495c978b524SChris Zankel	addi	a3, a2, -1
496c978b524SChris Zankel	and	a2, a2, a3
497c978b524SChris Zankel	bnez	a2, 1f			# Skip if registers aren't spilled now
498c978b524SChris Zankel
499c978b524SChris Zankel	addi	a2, a1, -16
500c978b524SChris Zankel	l32i	a4, a2, 0
501c978b524SChris Zankel	l32i	a5, a2, 4
502c978b524SChris Zankel	s32i	a4, a1, PT_SIZE + 0
503c978b524SChris Zankel	s32i	a5, a1, PT_SIZE + 4
504c978b524SChris Zankel	l32i	a4, a2, 8
505c978b524SChris Zankel	l32i	a5, a2, 12
506c978b524SChris Zankel	s32i	a4, a1, PT_SIZE + 8
507c978b524SChris Zankel	s32i	a5, a1, PT_SIZE + 12
508c978b524SChris Zankel#endif
509c978b524SChris Zankel
510c978b524SChris Zankel	/* Restore address register */
511c978b524SChris Zankel
512c978b524SChris Zankel1:	l32i	a15, a1, PT_AREG + 15 * 4
513c978b524SChris Zankel	l32i	a14, a1, PT_AREG + 14 * 4
514c978b524SChris Zankel	l32i	a13, a1, PT_AREG + 13 * 4
515c978b524SChris Zankel	l32i	a12, a1, PT_AREG + 12 * 4
516c978b524SChris Zankel	l32i	a11, a1, PT_AREG + 11 * 4
517c978b524SChris Zankel	l32i	a10, a1, PT_AREG + 10 * 4
518c978b524SChris Zankel	l32i	a9, a1, PT_AREG + 9 * 4
519c978b524SChris Zankel	l32i	a8, a1, PT_AREG + 8 * 4
520c978b524SChris Zankel	l32i	a7, a1, PT_AREG + 7 * 4
521c978b524SChris Zankel	l32i	a6, a1, PT_AREG + 6 * 4
522c978b524SChris Zankel	l32i	a5, a1, PT_AREG + 5 * 4
523c978b524SChris Zankel	l32i	a4, a1, PT_AREG + 4 * 4
524c978b524SChris Zankel	l32i	a3, a1, PT_AREG + 3 * 4
525c978b524SChris Zankel	l32i	a2, a1, PT_AREG + 2 * 4
526c978b524SChris Zankel	l32i	a0, a1, PT_AREG + 0 * 4
527c978b524SChris Zankel
528c978b524SChris Zankel	l32i	a1, a1, PT_AREG + 1 * 4 # Remove ptrace stack frame
529c978b524SChris Zankel
530c978b524SChris Zankel	rfe
531c978b524SChris Zankel
532c978b524SChris Zankel#endif /* XCHAL_HAVE_EXCEPTIONS */
533c978b524SChris Zankel
534c978b524SChris Zankel#if XCHAL_HAVE_WINDOWED
535c978b524SChris Zankel
536c978b524SChris Zankel/*
537c978b524SChris Zankel * Window overflow and underflow handlers.
538c978b524SChris Zankel * The handlers must be 64 bytes apart, first starting with the underflow
539c978b524SChris Zankel * handlers underflow-4 to underflow-12, then the overflow handlers
540c978b524SChris Zankel * overflow-4 to overflow-12.
541c978b524SChris Zankel *
542c978b524SChris Zankel * Note: We rerun the underflow handlers if we hit an exception, so
543c978b524SChris Zankel *	 we try to access any page that would cause a page fault early.
544c978b524SChris Zankel */
545c978b524SChris Zankel
546c978b524SChris Zankel	.section .WindowVectors.text, "ax"
547c978b524SChris Zankel
548c978b524SChris Zankel/* 4-Register Window Overflow Vector (Handler) */
549c978b524SChris Zankel
550c978b524SChris Zankel	.align 64
551c978b524SChris Zankel.global _WindowOverflow4
552c978b524SChris Zankel_WindowOverflow4:
553c978b524SChris Zankel	s32e	a0, a5, -16
554c978b524SChris Zankel	s32e	a1, a5, -12
555c978b524SChris Zankel	s32e	a2, a5,  -8
556c978b524SChris Zankel	s32e	a3, a5,  -4
557c978b524SChris Zankel	rfwo
558c978b524SChris Zankel
559c978b524SChris Zankel
560c978b524SChris Zankel/* 4-Register Window Underflow Vector (Handler) */
561c978b524SChris Zankel
562c978b524SChris Zankel	.align 64
563c978b524SChris Zankel.global _WindowUnderflow4
564c978b524SChris Zankel_WindowUnderflow4:
565c978b524SChris Zankel	l32e	a0, a5, -16
566c978b524SChris Zankel	l32e	a1, a5, -12
567c978b524SChris Zankel	l32e	a2, a5,  -8
568c978b524SChris Zankel	l32e	a3, a5,  -4
569c978b524SChris Zankel	rfwu
570c978b524SChris Zankel
571c978b524SChris Zankel/*
572c978b524SChris Zankel * a0:	a0
573c978b524SChris Zankel * a1:	new stack pointer = a1 - 16 - 4
574c978b524SChris Zankel * a2:	available, saved in excsave1
575c978b524SChris Zankel * a3:	available, saved on stack *a1
576c978b524SChris Zankel */
577c978b524SChris Zankel
578c978b524SChris Zankel/* 15*/	.byte	0xff
579c978b524SChris Zankel
580c978b524SChris Zankelfast_alloca_exception:	/* must be at _WindowUnderflow4 + 16 */
581c978b524SChris Zankel
582c978b524SChris Zankel/* 16*/	rsr	a2, PS
583c978b524SChris Zankel/* 19*/	rsr	a3, WINDOWBASE
584c978b524SChris Zankel/* 22*/	extui	a2, a2, PS_OWB_SHIFT, PS_OWB_SHIFT
585c978b524SChris Zankel/* 25*/	xor	a2, a2, a3
586c978b524SChris Zankel/* 28*/	rsr	a3, PS
587c978b524SChris Zankel/* 31*/	slli	a2, a2, PS_OWB_SHIFT
588c978b524SChris Zankel/* 34*/	xor	a2, a3, a2
589c978b524SChris Zankel/* 37*/	wsr	a2, PS
590c978b524SChris Zankel
591c978b524SChris Zankel/* 40*/	_l32i	a3, a1, 0
592c978b524SChris Zankel/* 43*/	addi	a1, a1, 16 + 4
593c978b524SChris Zankel/* 46*/	rsr	a2, EXCSAVE1
594c978b524SChris Zankel
595c978b524SChris Zankel/* 49*/	rotw	-1
596c978b524SChris Zankel/* 52*/	_bbci.l	a4, 31, _WindowUnderflow4	/* 0x: call4 */
597c978b524SChris Zankel/* 55*/	rotw	-1
598c978b524SChris Zankel/* 58*/	_bbci.l	a8, 30, _WindowUnderflow8	/* 10: call8 */
599c978b524SChris Zankel/* 61*/ _j	__WindowUnderflow12		/* 11: call12 */
600c978b524SChris Zankel/* 64*/
601c978b524SChris Zankel
602c978b524SChris Zankel/* 8-Register Window Overflow Vector (Handler) */
603c978b524SChris Zankel
604c978b524SChris Zankel	.align 64
605c978b524SChris Zankel.global _WindowOverflow8
606c978b524SChris Zankel_WindowOverflow8:
607c978b524SChris Zankel	s32e	a0, a9, -16
608c978b524SChris Zankel	l32e	a0, a1, -12
609c978b524SChris Zankel	s32e	a2, a9,  -8
610c978b524SChris Zankel	s32e	a1, a9, -12
611c978b524SChris Zankel	s32e	a3, a9,  -4
612c978b524SChris Zankel	s32e	a4, a0, -32
613c978b524SChris Zankel	s32e	a5, a0, -28
614c978b524SChris Zankel	s32e	a6, a0, -24
615c978b524SChris Zankel	s32e	a7, a0, -20
616c978b524SChris Zankel	rfwo
617c978b524SChris Zankel
618c978b524SChris Zankel/* 8-Register Window Underflow Vector (Handler) */
619c978b524SChris Zankel
620c978b524SChris Zankel	.align 64
621c978b524SChris Zankel.global _WindowUnderflow8
622c978b524SChris Zankel_WindowUnderflow8:
623c978b524SChris Zankel	l32e	a1, a9, -12
624c978b524SChris Zankel	l32e	a0, a9, -16
625c978b524SChris Zankel	l32e	a7, a1, -12
626c978b524SChris Zankel	l32e	a2, a9,  -8
627c978b524SChris Zankel	l32e	a4, a7, -32
628c978b524SChris Zankel	l32e	a3, a9,  -4
629c978b524SChris Zankel	l32e	a5, a7, -28
630c978b524SChris Zankel	l32e	a6, a7, -24
631c978b524SChris Zankel	l32e	a7, a7, -20
632c978b524SChris Zankel	rfwu
633c978b524SChris Zankel
634c978b524SChris Zankel/* 12-Register Window Overflow Vector (Handler) */
635c978b524SChris Zankel
636c978b524SChris Zankel	.align 64
637c978b524SChris Zankel.global _WindowOverflow12
638c978b524SChris Zankel_WindowOverflow12:
639c978b524SChris Zankel	s32e	a0,  a13, -16
640c978b524SChris Zankel	l32e	a0,  a1,  -12
641c978b524SChris Zankel	s32e	a1,  a13, -12
642c978b524SChris Zankel	s32e	a2,  a13,  -8
643c978b524SChris Zankel	s32e	a3,  a13,  -4
644c978b524SChris Zankel	s32e	a4,  a0,  -48
645c978b524SChris Zankel	s32e	a5,  a0,  -44
646c978b524SChris Zankel	s32e	a6,  a0,  -40
647c978b524SChris Zankel	s32e	a7,  a0,  -36
648c978b524SChris Zankel	s32e	a8,  a0,  -32
649c978b524SChris Zankel	s32e	a9,  a0,  -28
650c978b524SChris Zankel	s32e	a10, a0,  -24
651c978b524SChris Zankel	s32e	a11, a0,  -20
652c978b524SChris Zankel	rfwo
653c978b524SChris Zankel
654c978b524SChris Zankel/* 12-Register Window Underflow Vector (Handler) */
655c978b524SChris Zankel
656c978b524SChris Zankel	.org _WindowOverflow12 + 64 - 3
657c978b524SChris Zankel__WindowUnderflow12:
658c978b524SChris Zankel	rotw	-1
659c978b524SChris Zankel.global _WindowUnderflow12
660c978b524SChris Zankel_WindowUnderflow12:
661c978b524SChris Zankel	l32e	a1,  a13, -12
662c978b524SChris Zankel	l32e	a0,  a13, -16
663c978b524SChris Zankel	l32e	a11, a1,  -12
664c978b524SChris Zankel	l32e	a2,  a13,  -8
665c978b524SChris Zankel	l32e	a4,  a11, -48
666c978b524SChris Zankel	l32e	a8,  a11, -32
667c978b524SChris Zankel	l32e	a3,  a13,  -4
668c978b524SChris Zankel	l32e	a5,  a11, -44
669c978b524SChris Zankel	l32e	a6,  a11, -40
670c978b524SChris Zankel	l32e	a7,  a11, -36
671c978b524SChris Zankel	l32e	a9,  a11, -28
672c978b524SChris Zankel	l32e	a10, a11, -24
673c978b524SChris Zankel	l32e	a11, a11, -20
674c978b524SChris Zankel	rfwu
675c978b524SChris Zankel
676c978b524SChris Zankel#endif /* XCHAL_HAVE_WINDOWED */
677