678 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			678 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| /*
 | |
|  * (C) Copyright 2008 - 2013 Tensilica Inc.
 | |
|  * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
 | |
|  *
 | |
|  * SPDX-License-Identifier:	GPL-2.0+
 | |
|  */
 | |
| 
 | |
| #include <config.h>
 | |
| #include <asm/asmmacro.h>
 | |
| #include <asm/cacheasm.h>
 | |
| #include <asm/regs.h>
 | |
| #include <asm/arch/tie.h>
 | |
| #include <asm-offsets.h>
 | |
| 
 | |
| /*
 | |
|  * Offsets into the the pt_regs struture.
 | |
|  * Make sure these always match with the structure defined in ptrace.h!
 | |
|  */
 | |
| 
 | |
| #define PT_PC		0
 | |
| #define PT_PS		4
 | |
| #define PT_DEPC		8
 | |
| #define PT_EXCCAUSE	12
 | |
| #define PT_EXCVADDR	16
 | |
| #define PT_DEBUGCAUSE	20
 | |
| #define PT_WMASK	24
 | |
| #define PT_LBEG		28
 | |
| #define PT_LEND		32
 | |
| #define PT_LCOUNT	36
 | |
| #define PT_SAR		40
 | |
| #define PT_WINDOWBASE	44
 | |
| #define PT_WINDOWSTART	48
 | |
| #define PT_SYSCALL	52
 | |
| #define PT_ICOUNTLEVEL	56
 | |
| #define PT_RESERVED	60
 | |
| #define PT_AREG		64
 | |
| #define PT_SIZE		(64 + 64)
 | |
| 
 | |
| /*
 | |
|  * Cache attributes are different for full MMU and region protection.
 | |
|  */
 | |
| 
 | |
| #if XCHAL_HAVE_PTP_MMU
 | |
| #define CA_WRITEBACK	(0x7)
 | |
| #else
 | |
| #define CA_WRITEBACK	(0x4)
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Reset vector.
 | |
|  * Only a trampoline to jump to _start
 | |
|  * (Note that we have to mark the section writable as the section contains
 | |
|  *  a relocatable literal)
 | |
|  */
 | |
| 
 | |
| 	.section .ResetVector.text, "awx"
 | |
| 	.global _ResetVector
 | |
| _ResetVector:
 | |
| 
 | |
| 	j	1f
 | |
| 	.align 4
 | |
| 2:	.long	_start
 | |
| 1:	l32r	a2, 2b
 | |
| 	jx	a2
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Processor initialization. We still run in rom space.
 | |
|  *
 | |
|  * NOTE: Running in ROM
 | |
|  *  For Xtensa, we currently don't allow to run some code from ROM but
 | |
|  *  unpack the data immediately to memory. This requires, for example,
 | |
|  *  that DDR has been set up before running U-Boot. (See also comments
 | |
|  *  inline for ways to change it)
 | |
|  */
 | |
| 
 | |
| 	.section .reset.text, "ax"
 | |
| 	.global _start
 | |
| 	.align 4
 | |
| _start:
 | |
| 	/* Keep a0 = 0 for various initializations */
 | |
| 
 | |
| 	movi	a0, 0
 | |
| 
 | |
| 	/*
 | |
| 	 * For full MMU cores, put page table at unmapped virtual address.
 | |
| 	 * This ensures that accesses outside the static maps result
 | |
| 	 * in miss exceptions rather than random behaviour.
 | |
| 	 */
 | |
| 
 | |
| #if XCHAL_HAVE_PTP_MMU
 | |
| 	wsr	a0, PTEVADDR
 | |
| #endif
 | |
| 
 | |
| 	/* Disable dbreak debug exceptions */
 | |
| 
 | |
| #if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0
 | |
| 	.set	_index, 0
 | |
| 	.rept	XCHAL_NUM_DBREAK
 | |
| 	wsr	a0, DBREAKC + _index
 | |
| 	.set	_index, _index + 1
 | |
| 	.endr
 | |
| #endif
 | |
| 
 | |
| 	/* Reset windowbase and windowstart */
 | |
| 
 | |
| #if XCHAL_HAVE_WINDOWED
 | |
| 	movi	a3, 1
 | |
| 	wsr	a3, windowstart
 | |
| 	wsr	a0, windowbase
 | |
| 	rsync
 | |
| 	movi	a0, 0			/* windowbase might have changed */
 | |
| #endif
 | |
| 
 | |
| 	/*
 | |
| 	 * Vecbase in bitstream may differ from header files
 | |
| 	 * set or check it.
 | |
| 	 */
 | |
| 
 | |
| #if XCHAL_HAVE_VECBASE
 | |
| 	movi	a3, XCHAL_VECBASE_RESET_VADDR	/* VECBASE reset value */
 | |
| 	wsr	a3, VECBASE
 | |
| #endif
 | |
| 
 | |
| #if XCHAL_HAVE_LOOPS
 | |
| 	/* Disable loops */
 | |
| 
 | |
| 	wsr	a0, LCOUNT
 | |
| #endif
 | |
| 
 | |
| 	/* Set PS.WOE = 0, PS.EXCM = 0 (for loop), PS.INTLEVEL = EXCM level */
 | |
| 
 | |
| #if XCHAL_HAVE_XEA1
 | |
| 	movi	a2, 1
 | |
| #else
 | |
| 	movi	a2, XCHAL_EXCM_LEVEL
 | |
| #endif
 | |
| 	wsr	a2, PS
 | |
| 	rsync
 | |
| 
 | |
| 	/* Unlock and invalidate caches */
 | |
| 
 | |
| 	___unlock_dcache_all a2, a3
 | |
| 	___invalidate_dcache_all a2, a3
 | |
| 	___unlock_icache_all a2, a3
 | |
| 	___invalidate_icache_all a2, a3
 | |
| 
 | |
| 	isync
 | |
| 
 | |
| 	/* Unpack data sections */
 | |
| 
 | |
| 	movi	a2, __reloc_table_start
 | |
| 	movi	a3, __reloc_table_end
 | |
| 
 | |
| 1:	beq	a2, a3, 3f	# no more entries?
 | |
| 	l32i	a4, a2, 0	# start destination (in RAM)
 | |
| 	l32i	a5, a2, 4	# end destination (in RAM)
 | |
| 	l32i	a6, a2, 8	# start source (in ROM)
 | |
| 	addi	a2, a2, 12	# next entry
 | |
| 	beq	a4, a5, 1b	# skip, empty entry
 | |
| 	beq	a4, a6, 1b	# skip, source and destination are the same
 | |
| 
 | |
| 	/* If there's memory protection option with 512MB TLB regions and
 | |
| 	 * cache attributes in TLB entries and caching is not inhibited,
 | |
| 	 * enable data/instruction cache for relocated image.
 | |
| 	 */
 | |
| #if XCHAL_HAVE_SPANNING_WAY && \
 | |
| 	(!defined(CONFIG_SYS_DCACHE_OFF) || \
 | |
| 	 !defined(CONFIG_SYS_ICACHE_OFF))
 | |
| 	srli	a7, a4, 29
 | |
| 	slli	a7, a7, 29
 | |
| 	addi	a7, a7, XCHAL_SPANNING_WAY
 | |
| #ifndef CONFIG_SYS_DCACHE_OFF
 | |
| 	rdtlb1	a8, a7
 | |
| 	srli	a8, a8, 4
 | |
| 	slli	a8, a8, 4
 | |
| 	addi	a8, a8, CA_WRITEBACK
 | |
| 	wdtlb	a8, a7
 | |
| #endif
 | |
| #ifndef CONFIG_SYS_ICACHE_OFF
 | |
| 	ritlb1	a8, a7
 | |
| 	srli	a8, a8, 4
 | |
| 	slli	a8, a8, 4
 | |
| 	addi	a8, a8, CA_WRITEBACK
 | |
| 	witlb	a8, a7
 | |
| #endif
 | |
| 	isync
 | |
| #endif
 | |
| 
 | |
| 2:	l32i	a7, a6, 0
 | |
| 	addi	a6, a6, 4
 | |
| 	s32i	a7, a4, 0
 | |
| 	addi	a4, a4, 4
 | |
| 	bltu	a4, a5, 2b
 | |
| 	j	1b
 | |
| 
 | |
| 3:	/* All code and initalized data segments have been copied */
 | |
| 
 | |
| 	/* Setup PS, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
 | |
| 
 | |
| #if __XTENSA_CALL0_ABI__
 | |
| 	movi	a2, XCHAL_EXCM_LEVEL
 | |
| #else
 | |
| 	movi	a2, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
 | |
| #endif
 | |
| 	wsr	a2, PS
 | |
| 	rsync
 | |
| 
 | |
| 	/* Writeback */
 | |
| 
 | |
| 	___flush_dcache_all a2, a3
 | |
| 
 | |
| #ifdef __XTENSA_WINDOWED_ABI__
 | |
| 	/*
 | |
| 	 * In windowed ABI caller and call target need to be within the same
 | |
| 	 * gigabyte. Put the rest of the code into the text segment and jump
 | |
| 	 * there.
 | |
| 	 */
 | |
| 
 | |
| 	movi	a4, .Lboard_init_code
 | |
| 	jx	a4
 | |
| 
 | |
| 	.text
 | |
| 	.align	4
 | |
| .Lboard_init_code:
 | |
| #endif
 | |
| 
 | |
| 	movi	a0, 0
 | |
| 	movi	sp, (CONFIG_SYS_TEXT_ADDR - 16) & 0xfffffff0
 | |
| 
 | |
| #ifdef CONFIG_DEBUG_UART
 | |
| 	movi	a4, debug_uart_init
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	callx0	a4
 | |
| #else
 | |
| 	callx4	a4
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| 	movi	a4, board_init_f_alloc_reserve
 | |
| 
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	mov	a2, sp
 | |
| 	callx0	a4
 | |
| 	mov	sp, a2
 | |
| #else
 | |
| 	mov	a6, sp
 | |
| 	callx4	a4
 | |
| 	movsp	sp, a6
 | |
| #endif
 | |
| 
 | |
| 	movi	a4, board_init_f_init_reserve
 | |
| 
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	callx0	a4
 | |
| #else
 | |
| 	callx4	a4
 | |
| #endif
 | |
| 
 | |
|         /*
 | |
| 	 * Call board initialization routine (never returns).
 | |
| 	 */
 | |
| 
 | |
| 	movi	a4, board_init_f
 | |
| 
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	movi	a2, 0
 | |
| 	callx0	a4
 | |
| #else
 | |
| 	movi	a6, 0
 | |
| 	callx4	a4
 | |
| #endif
 | |
| 	/* Never Returns */
 | |
| 	ill
 | |
| 
 | |
| /*
 | |
|  * void relocate_code (addr_sp, gd, addr_moni)
 | |
|  *
 | |
|  * This "function" does not return, instead it continues in RAM
 | |
|  * after relocating the monitor code.
 | |
|  *
 | |
|  * a2 = addr_sp
 | |
|  * a3 = gd
 | |
|  * a4 = destination address
 | |
|  */
 | |
| 	.text
 | |
| 	.globl relocate_code
 | |
| 	.align 4
 | |
| relocate_code:
 | |
| 	abi_entry
 | |
| 
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	mov	a1, a2
 | |
| 	mov	a2, a3
 | |
| 	mov	a3, a4
 | |
| 	movi	a0, board_init_r
 | |
| 	callx0	a0
 | |
| #else
 | |
| 	/* We can't movsp here, because the chain of stack frames may cross
 | |
| 	 * the now reserved memory. We need to toss all window frames except
 | |
| 	 * the current, create new pristine stack frame and start from scratch.
 | |
| 	 */
 | |
| 	rsr	a0, windowbase
 | |
| 	ssl	a0
 | |
| 	movi	a0, 1
 | |
| 	sll	a0, a0
 | |
| 	wsr	a0, windowstart
 | |
| 	rsync
 | |
| 
 | |
| 	movi	a0, 0
 | |
| 
 | |
| 	/* Reserve 16-byte save area */
 | |
| 	addi	sp, a2, -16
 | |
| 	mov	a6, a3
 | |
| 	mov	a7, a4
 | |
| 	movi	a4, board_init_r
 | |
| 	callx4	a4
 | |
| #endif
 | |
| 	ill
 | |
| 
 | |
| #if XCHAL_HAVE_EXCEPTIONS
 | |
| 
 | |
| /*
 | |
|  * Exception vectors.
 | |
|  *
 | |
|  *  Various notes:
 | |
|  *   - We currently don't use the user exception vector (PS.UM is always 0),
 | |
|  *     but do define such a vector, just in case. They both jump to the
 | |
|  *     same exception handler, though.
 | |
|  *   - We currently only save the bare minimum number of registers:
 | |
|  *     a0...a15, sar, loop-registers, exception register (epc1, excvaddr,
 | |
|  *     exccause, depc)
 | |
|  *   - WINDOWSTART is only saved to identify if registers have been spilled
 | |
|  *     to the wrong stack (exception stack) while executing the exception
 | |
|  *     handler.
 | |
|  */
 | |
| 
 | |
| 	.section .KernelExceptionVector.text, "ax"
 | |
| 	.global _KernelExceptionVector
 | |
| _KernelExceptionVector:
 | |
| 
 | |
| 	wsr	a2, EXCSAVE1
 | |
| 	movi	a2, ExceptionHandler
 | |
| 	jx	a2
 | |
| 
 | |
| 	.section .UserExceptionVector.text, "ax"
 | |
| 	.global _UserExceptionVector
 | |
| _UserExceptionVector:
 | |
| 
 | |
| 	wsr	a2, EXCSAVE1
 | |
| 	movi	a2, ExceptionHandler
 | |
| 	jx	a2
 | |
| 
 | |
| #if !XCHAL_HAVE_XEA1
 | |
| 	.section .DoubleExceptionVector.text, "ax"
 | |
| 	.global _DoubleExceptionVector
 | |
| _DoubleExceptionVector:
 | |
| 
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	wsr	a0, EXCSAVE1
 | |
| 	movi    a0, hang                # report and ask user to reset board
 | |
| 	callx0	a0
 | |
| #else
 | |
| 	wsr	a4, EXCSAVE1
 | |
| 	movi    a4, hang                # report and ask user to reset board
 | |
| 	callx4	a4
 | |
| #endif
 | |
| #endif
 | |
| 	/* Does not return here */
 | |
| 
 | |
| 
 | |
| 	.text
 | |
| 	.align 4
 | |
| ExceptionHandler:
 | |
| 
 | |
| 	rsr	a2, EXCCAUSE		# find handler
 | |
| 
 | |
| #if XCHAL_HAVE_WINDOWED
 | |
| 	/* Special case for alloca handler */
 | |
| 
 | |
| 	bnei	a2, 5, 1f		# jump if not alloca exception
 | |
| 
 | |
| 	addi	a1, a1, -16 - 4		# create a small stack frame
 | |
| 	s32i	a3, a1, 0		# and save a3 (a2 still in excsave1)
 | |
| 	movi	a2, fast_alloca_exception
 | |
| 	jx	a2			# jump to fast_alloca_exception
 | |
| #endif
 | |
| 	/* All other exceptions go here: */
 | |
| 
 | |
| 	/* Create ptrace stack and save a0...a3 */
 | |
| 
 | |
| 1:	addi	a2, a1, - PT_SIZE - 16
 | |
| 	s32i	a0, a2, PT_AREG + 0 * 4
 | |
| 	s32i	a1, a2, PT_AREG + 1 * 4
 | |
| 	s32i	a3, a2, PT_AREG + 3 * 4
 | |
| 	rsr	a3, EXCSAVE1
 | |
| 	s32i	a3, a2, PT_AREG + 2 * 4
 | |
| 	mov	a1, a2
 | |
| 
 | |
| 	/* Save remaining AR registers */
 | |
| 
 | |
| 	s32i	a4, a1, PT_AREG + 4 * 4
 | |
| 	s32i	a5, a1, PT_AREG + 5 * 4
 | |
| 	s32i	a6, a1, PT_AREG + 6 * 4
 | |
| 	s32i	a7, a1, PT_AREG + 7 * 4
 | |
| 	s32i	a8, a1, PT_AREG + 8 * 4
 | |
| 	s32i	a9, a1, PT_AREG + 9 * 4
 | |
| 	s32i	a10, a1, PT_AREG + 10 * 4
 | |
| 	s32i	a11, a1, PT_AREG + 11 * 4
 | |
| 	s32i	a12, a1, PT_AREG + 12 * 4
 | |
| 	s32i	a13, a1, PT_AREG + 13 * 4
 | |
| 	s32i	a14, a1, PT_AREG + 14 * 4
 | |
| 	s32i	a15, a1, PT_AREG + 15 * 4
 | |
| 
 | |
| 	/* Save SRs */
 | |
| 
 | |
| #if XCHAL_HAVE_WINDOWED
 | |
| 	rsr	a2, WINDOWSTART
 | |
| 	s32i	a2, a1, PT_WINDOWSTART
 | |
| #endif
 | |
| 
 | |
| 	rsr	a2, SAR
 | |
| 	rsr	a3, EPC1
 | |
| 	rsr	a4, EXCVADDR
 | |
| 	s32i	a2, a1, PT_SAR
 | |
| 	s32i	a3, a1, PT_PC
 | |
| 	s32i	a4, a1, PT_EXCVADDR
 | |
| 
 | |
| #if XCHAL_HAVE_LOOPS
 | |
| 	movi	a2, 0
 | |
| 	rsr	a3, LBEG
 | |
| 	xsr	a2, LCOUNT
 | |
| 	s32i	a3, a1, PT_LBEG
 | |
| 	rsr	a3, LEND
 | |
| 	s32i	a2, a1, PT_LCOUNT
 | |
| 	s32i	a3, a1, PT_LEND
 | |
| #endif
 | |
| 
 | |
| 	/* Set up C environment and call registered handler */
 | |
| 	/* Setup stack, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
 | |
| 
 | |
| 	rsr	a2, EXCCAUSE
 | |
| #if XCHAL_HAVE_XEA1
 | |
| 	movi	a3, (1<<PS_WOE_BIT) | 1
 | |
| #elif __XTENSA_CALL0_ABI__
 | |
| 	movi	a3, XCHAL_EXCM_LEVEL
 | |
| #else
 | |
| 	movi	a3, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
 | |
| #endif
 | |
| 	xsr	a3, PS
 | |
| 	rsync
 | |
| 	s32i	a2, a1, PT_EXCCAUSE
 | |
| 	s32i	a3, a1, PT_PS
 | |
| 
 | |
| 	movi	a0, exc_table
 | |
| 	addx4	a0, a2, a0
 | |
| 	l32i	a0, a0, 0
 | |
| #ifdef __XTENSA_CALL0_ABI__
 | |
| 	mov	a2, a1			# Provide stack frame as only argument
 | |
| 	callx0	a0
 | |
| 	l32i	a3, a1, PT_PS
 | |
| #else
 | |
| 	mov	a6, a1			# Provide stack frame as only argument
 | |
| 	callx4	a0
 | |
| #endif
 | |
| 
 | |
| 	/* Restore PS and go to exception mode (PS.EXCM=1) */
 | |
| 
 | |
| 	wsr	a3, PS
 | |
| 
 | |
| 	/* Restore SR registers */
 | |
| 
 | |
| #if XCHAL_HAVE_LOOPS
 | |
| 	l32i	a2, a1, PT_LBEG
 | |
| 	l32i	a3, a1, PT_LEND
 | |
| 	l32i	a4, a1, PT_LCOUNT
 | |
| 	wsr	a2, LBEG
 | |
| 	wsr	a3, LEND
 | |
| 	wsr	a4, LCOUNT
 | |
| #endif
 | |
| 
 | |
| 	l32i	a2, a1, PT_SAR
 | |
| 	l32i	a3, a1, PT_PC
 | |
| 	wsr	a2, SAR
 | |
| 	wsr	a3, EPC1
 | |
| 
 | |
| #if XCHAL_HAVE_WINDOWED
 | |
| 	/* Do we need to simulate a MOVSP? */
 | |
| 
 | |
| 	l32i	a2, a1, PT_WINDOWSTART
 | |
| 	addi	a3, a2, -1
 | |
| 	and	a2, a2, a3
 | |
| 	beqz	a2, 1f			# Skip if regs were spilled before exc.
 | |
| 
 | |
| 	rsr	a2, WINDOWSTART
 | |
| 	addi	a3, a2, -1
 | |
| 	and	a2, a2, a3
 | |
| 	bnez	a2, 1f			# Skip if registers aren't spilled now
 | |
| 
 | |
| 	addi	a2, a1, -16
 | |
| 	l32i	a4, a2, 0
 | |
| 	l32i	a5, a2, 4
 | |
| 	s32i	a4, a1, PT_SIZE + 0
 | |
| 	s32i	a5, a1, PT_SIZE + 4
 | |
| 	l32i	a4, a2, 8
 | |
| 	l32i	a5, a2, 12
 | |
| 	s32i	a4, a1, PT_SIZE + 8
 | |
| 	s32i	a5, a1, PT_SIZE + 12
 | |
| #endif
 | |
| 
 | |
| 	/* Restore address register */
 | |
| 
 | |
| 1:	l32i	a15, a1, PT_AREG + 15 * 4
 | |
| 	l32i	a14, a1, PT_AREG + 14 * 4
 | |
| 	l32i	a13, a1, PT_AREG + 13 * 4
 | |
| 	l32i	a12, a1, PT_AREG + 12 * 4
 | |
| 	l32i	a11, a1, PT_AREG + 11 * 4
 | |
| 	l32i	a10, a1, PT_AREG + 10 * 4
 | |
| 	l32i	a9, a1, PT_AREG + 9 * 4
 | |
| 	l32i	a8, a1, PT_AREG + 8 * 4
 | |
| 	l32i	a7, a1, PT_AREG + 7 * 4
 | |
| 	l32i	a6, a1, PT_AREG + 6 * 4
 | |
| 	l32i	a5, a1, PT_AREG + 5 * 4
 | |
| 	l32i	a4, a1, PT_AREG + 4 * 4
 | |
| 	l32i	a3, a1, PT_AREG + 3 * 4
 | |
| 	l32i	a2, a1, PT_AREG + 2 * 4
 | |
| 	l32i	a0, a1, PT_AREG + 0 * 4
 | |
| 
 | |
| 	l32i	a1, a1, PT_AREG + 1 * 4 # Remove ptrace stack frame
 | |
| 
 | |
| 	rfe
 | |
| 
 | |
| #endif /* XCHAL_HAVE_EXCEPTIONS */
 | |
| 
 | |
| #if XCHAL_HAVE_WINDOWED
 | |
| 
 | |
| /*
 | |
|  * Window overflow and underflow handlers.
 | |
|  * The handlers must be 64 bytes apart, first starting with the underflow
 | |
|  * handlers underflow-4 to underflow-12, then the overflow handlers
 | |
|  * overflow-4 to overflow-12.
 | |
|  *
 | |
|  * Note: We rerun the underflow handlers if we hit an exception, so
 | |
|  *	 we try to access any page that would cause a page fault early.
 | |
|  */
 | |
| 
 | |
| 	.section .WindowVectors.text, "ax"
 | |
| 
 | |
| /* 4-Register Window Overflow Vector (Handler) */
 | |
| 
 | |
| 	.align 64
 | |
| .global _WindowOverflow4
 | |
| _WindowOverflow4:
 | |
| 	s32e	a0, a5, -16
 | |
| 	s32e	a1, a5, -12
 | |
| 	s32e	a2, a5,  -8
 | |
| 	s32e	a3, a5,  -4
 | |
| 	rfwo
 | |
| 
 | |
| 
 | |
| /* 4-Register Window Underflow Vector (Handler) */
 | |
| 
 | |
| 	.align 64
 | |
| .global _WindowUnderflow4
 | |
| _WindowUnderflow4:
 | |
| 	l32e	a0, a5, -16
 | |
| 	l32e	a1, a5, -12
 | |
| 	l32e	a2, a5,  -8
 | |
| 	l32e	a3, a5,  -4
 | |
| 	rfwu
 | |
| 
 | |
| /*
 | |
|  * a0:	a0
 | |
|  * a1:	new stack pointer = a1 - 16 - 4
 | |
|  * a2:	available, saved in excsave1
 | |
|  * a3:	available, saved on stack *a1
 | |
|  */
 | |
| 
 | |
| /* 15*/	.byte	0xff
 | |
| 
 | |
| fast_alloca_exception:	/* must be at _WindowUnderflow4 + 16 */
 | |
| 
 | |
| /* 16*/	rsr	a2, PS
 | |
| /* 19*/	rsr	a3, WINDOWBASE
 | |
| /* 22*/	extui	a2, a2, PS_OWB_SHIFT, PS_OWB_SHIFT
 | |
| /* 25*/	xor	a2, a2, a3
 | |
| /* 28*/	rsr	a3, PS
 | |
| /* 31*/	slli	a2, a2, PS_OWB_SHIFT
 | |
| /* 34*/	xor	a2, a3, a2
 | |
| /* 37*/	wsr	a2, PS
 | |
| 
 | |
| /* 40*/	_l32i	a3, a1, 0
 | |
| /* 43*/	addi	a1, a1, 16 + 4
 | |
| /* 46*/	rsr	a2, EXCSAVE1
 | |
| 
 | |
| /* 49*/	rotw	-1
 | |
| /* 52*/	_bbci.l	a4, 31, _WindowUnderflow4	/* 0x: call4 */
 | |
| /* 55*/	rotw	-1
 | |
| /* 58*/	_bbci.l	a8, 30, _WindowUnderflow8	/* 10: call8 */
 | |
| /* 61*/ _j	__WindowUnderflow12		/* 11: call12 */
 | |
| /* 64*/
 | |
| 
 | |
| /* 8-Register Window Overflow Vector (Handler) */
 | |
| 
 | |
| 	.align 64
 | |
| .global _WindowOverflow8
 | |
| _WindowOverflow8:
 | |
| 	s32e	a0, a9, -16
 | |
| 	l32e	a0, a1, -12
 | |
| 	s32e	a2, a9,  -8
 | |
| 	s32e	a1, a9, -12
 | |
| 	s32e	a3, a9,  -4
 | |
| 	s32e	a4, a0, -32
 | |
| 	s32e	a5, a0, -28
 | |
| 	s32e	a6, a0, -24
 | |
| 	s32e	a7, a0, -20
 | |
| 	rfwo
 | |
| 
 | |
| /* 8-Register Window Underflow Vector (Handler) */
 | |
| 
 | |
| 	.align 64
 | |
| .global _WindowUnderflow8
 | |
| _WindowUnderflow8:
 | |
| 	l32e	a1, a9, -12
 | |
| 	l32e	a0, a9, -16
 | |
| 	l32e	a7, a1, -12
 | |
| 	l32e	a2, a9,  -8
 | |
| 	l32e	a4, a7, -32
 | |
| 	l32e	a3, a9,  -4
 | |
| 	l32e	a5, a7, -28
 | |
| 	l32e	a6, a7, -24
 | |
| 	l32e	a7, a7, -20
 | |
| 	rfwu
 | |
| 
 | |
| /* 12-Register Window Overflow Vector (Handler) */
 | |
| 
 | |
| 	.align 64
 | |
| .global _WindowOverflow12
 | |
| _WindowOverflow12:
 | |
| 	s32e	a0,  a13, -16
 | |
| 	l32e	a0,  a1,  -12
 | |
| 	s32e	a1,  a13, -12
 | |
| 	s32e	a2,  a13,  -8
 | |
| 	s32e	a3,  a13,  -4
 | |
| 	s32e	a4,  a0,  -48
 | |
| 	s32e	a5,  a0,  -44
 | |
| 	s32e	a6,  a0,  -40
 | |
| 	s32e	a7,  a0,  -36
 | |
| 	s32e	a8,  a0,  -32
 | |
| 	s32e	a9,  a0,  -28
 | |
| 	s32e	a10, a0,  -24
 | |
| 	s32e	a11, a0,  -20
 | |
| 	rfwo
 | |
| 
 | |
| /* 12-Register Window Underflow Vector (Handler) */
 | |
| 
 | |
| 	.org _WindowOverflow12 + 64 - 3
 | |
| __WindowUnderflow12:
 | |
| 	rotw	-1
 | |
| .global _WindowUnderflow12
 | |
| _WindowUnderflow12:
 | |
| 	l32e	a1,  a13, -12
 | |
| 	l32e	a0,  a13, -16
 | |
| 	l32e	a11, a1,  -12
 | |
| 	l32e	a2,  a13,  -8
 | |
| 	l32e	a4,  a11, -48
 | |
| 	l32e	a8,  a11, -32
 | |
| 	l32e	a3,  a13,  -4
 | |
| 	l32e	a5,  a11, -44
 | |
| 	l32e	a6,  a11, -40
 | |
| 	l32e	a7,  a11, -36
 | |
| 	l32e	a9,  a11, -28
 | |
| 	l32e	a10, a11, -24
 | |
| 	l32e	a11, a11, -20
 | |
| 	rfwu
 | |
| 
 | |
| #endif /* XCHAL_HAVE_WINDOWED */
 |