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