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