/*1* arch/xtensa/kernel/vectors.S2*3* This file contains all exception vectors (user, kernel, and double),4* as well as the window vectors (overflow and underflow), and the debug5* vector. These are the primary vectors executed by the processor if an6* exception occurs.7*8* This file is subject to the terms and conditions of the GNU General9* Public License. See the file "COPYING" in the main directory of10* this archive for more details.11*12* Copyright (C) 2005 - 2008 Tensilica, Inc.13*14* Chris Zankel <[email protected]>15*16*/1718/*19* We use a two-level table approach. The user and kernel exception vectors20* use a first-level dispatch table to dispatch the exception to a registered21* fast handler or the default handler, if no fast handler was registered.22* The default handler sets up a C-stack and dispatches the exception to a23* registerd C handler in the second-level dispatch table.24*25* Fast handler entry condition:26*27* a0: trashed, original value saved on stack (PT_AREG0)28* a1: a129* a2: new stack pointer, original value in depc30* a3: dispatch table31* depc: a2, original value saved on stack (PT_DEPC)32* excsave_1: a333*34* The value for PT_DEPC saved to stack also functions as a boolean to35* indicate that the exception is either a double or a regular exception:36*37* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception38* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception39*40* Note: Neither the kernel nor the user exception handler generate literals.41*42*/4344#include <linux/linkage.h>45#include <linux/pgtable.h>46#include <asm/asmmacro.h>47#include <asm/ptrace.h>48#include <asm/current.h>49#include <asm/asm-offsets.h>50#include <asm/processor.h>51#include <asm/page.h>52#include <asm/thread_info.h>53#include <asm/vectors.h>5455#define WINDOW_VECTORS_SIZE 0x180565758/*59* User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0)60*61* We get here when an exception occurred while we were in userland.62* We switch to the kernel stack and jump to the first level handler63* associated to the exception cause.64*65* Note: the saved kernel stack pointer (EXC_TABLE_KSTK) is already66* decremented by PT_USER_SIZE.67*/6869.section .UserExceptionVector.text, "ax"7071ENTRY(_UserExceptionVector)7273xsr a3, excsave1 # save a3 and get dispatch table74wsr a2, depc # save a275l32i a2, a3, EXC_TABLE_KSTK # load kernel stack to a276s32i a0, a2, PT_AREG0 # save a0 to ESF77rsr a0, exccause # retrieve exception cause78s32i a0, a2, PT_DEPC # mark it as a regular exception79addx4 a0, a0, a3 # find entry in table80l32i a0, a0, EXC_TABLE_FAST_USER # load handler81xsr a3, excsave1 # restore a3 and dispatch table82jx a08384ENDPROC(_UserExceptionVector)8586/*87* Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0)88*89* We get this exception when we were already in kernel space.90* We decrement the current stack pointer (kernel) by PT_KERNEL_SIZE and91* jump to the first-level handler associated with the exception cause.92*93* Note: we need to preserve space for the spill region.94*/9596.section .KernelExceptionVector.text, "ax"9798ENTRY(_KernelExceptionVector)99100xsr a3, excsave1 # save a3, and get dispatch table101wsr a2, depc # save a2102addi a2, a1, -16 - PT_KERNEL_SIZE # adjust stack pointer103s32i a0, a2, PT_AREG0 # save a0 to ESF104rsr a0, exccause # retrieve exception cause105s32i a0, a2, PT_DEPC # mark it as a regular exception106addx4 a0, a0, a3 # find entry in table107l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address108xsr a3, excsave1 # restore a3 and dispatch table109jx a0110111ENDPROC(_KernelExceptionVector)112113/*114* Double exception vector (Exceptions with PS.EXCM == 1)115* We get this exception when another exception occurs while were are116* already in an exception, such as window overflow/underflow exception,117* or 'expected' exceptions, for example memory exception when we were trying118* to read data from an invalid address in user space.119*120* Note that this vector is never invoked for level-1 interrupts, because such121* interrupts are disabled (masked) when PS.EXCM is set.122*123* We decode the exception and take the appropriate action. However, the124* double exception vector is much more careful, because a lot more error125* cases go through the double exception vector than through the user and126* kernel exception vectors.127*128* Occasionally, the kernel expects a double exception to occur. This usually129* happens when accessing user-space memory with the user's permissions130* (l32e/s32e instructions). The kernel state, though, is not always suitable131* for immediate transfer of control to handle_double, where "normal" exception132* processing occurs. Also in kernel mode, TLB misses can occur if accessing133* vmalloc memory, possibly requiring repair in a double exception handler.134*135* The variable at TABLE_FIXUP offset from the pointer in EXCSAVE_1 doubles as136* a boolean variable and a pointer to a fixup routine. If the variable137* EXC_TABLE_FIXUP is non-zero, this handler jumps to that address. A value of138* zero indicates to use the default kernel/user exception handler.139* There is only one exception, when the value is identical to the exc_table140* label, the kernel is in trouble. This mechanism is used to protect critical141* sections, mainly when the handler writes to the stack to assert the stack142* pointer is valid. Once the fixup/default handler leaves that area, the143* EXC_TABLE_FIXUP variable is reset to the fixup handler or zero.144*145* Procedures wishing to use this mechanism should set EXC_TABLE_FIXUP to the146* nonzero address of a fixup routine before it could cause a double exception147* and reset it before it returns.148*149* Some other things to take care of when a fast exception handler doesn't150* specify a particular fixup handler but wants to use the default handlers:151*152* - The original stack pointer (in a1) must not be modified. The fast153* exception handler should only use a2 as the stack pointer.154*155* - If the fast handler manipulates the stack pointer (in a2), it has to156* register a valid fixup handler and cannot use the default handlers.157*158* - The handler can use any other generic register from a3 to a15, but it159* must save the content of these registers to stack (PT_AREG3...PT_AREGx)160*161* - These registers must be saved before a double exception can occur.162*163* - If we ever implement handling signals while in double exceptions, the164* number of registers a fast handler has saved (excluding a0 and a1) must165* be written to PT_AREG1. (1 if only a3 is used, 2 for a3 and a4, etc. )166*167* The fixup handlers are special handlers:168*169* - Fixup entry conditions differ from regular exceptions:170*171* a0: DEPC172* a1: a1173* a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE174* a3: exctable175* depc: a0176* excsave_1: a3177*178* - When the kernel enters the fixup handler, it still assumes it is in a179* critical section, so EXC_TABLE_FIXUP variable is set to exc_table.180* The fixup handler, therefore, has to re-register itself as the fixup181* handler before it returns from the double exception.182*183* - Fixup handler can share the same exception frame with the fast handler.184* The kernel stack pointer is not changed when entering the fixup handler.185*186* - Fixup handlers can jump to the default kernel and user exception187* handlers. Before it jumps, though, it has to setup a exception frame188* on stack. Because the default handler resets the register fixup handler189* the fixup handler must make sure that the default handler returns to190* it instead of the exception address, so it can re-register itself as191* the fixup handler.192*193* In case of a critical condition where the kernel cannot recover, we jump194* to unrecoverable_exception with the following entry conditions.195* All registers a0...a15 are unchanged from the last exception, except:196*197* a0: last address before we jumped to the unrecoverable_exception.198* excsave_1: a0199*200*201* See the handle_alloca_user and spill_registers routines for example clients.202*203* FIXME: Note: we currently don't allow signal handling coming from a double204* exception, so the item markt with (*) is not required.205*/206207.section .DoubleExceptionVector.text, "ax"208209ENTRY(_DoubleExceptionVector)210211xsr a3, excsave1212s32i a2, a3, EXC_TABLE_DOUBLE_SAVE213214/* Check for kernel double exception (usually fatal). */215216rsr a2, ps217_bbsi.l a2, PS_UM_BIT, 1f218j .Lksp219220.align 4221.literal_position2221:223/* Check if we are currently handling a window exception. */224/* Note: We don't need to indicate that we enter a critical section. */225226xsr a0, depc # get DEPC, save a0227228#ifdef SUPPORT_WINDOWED229movi a2, WINDOW_VECTORS_VADDR230_bltu a0, a2, .Lfixup231addi a2, a2, WINDOW_VECTORS_SIZE232_bgeu a0, a2, .Lfixup233234/* Window overflow/underflow exception. Get stack pointer. */235236l32i a2, a3, EXC_TABLE_KSTK237238/* Check for overflow/underflow exception, jump if overflow. */239240bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow241242/*243* Restart window underflow exception.244* Currently:245* depc = orig a0,246* a0 = orig DEPC,247* a2 = new sp based on KSTK from exc_table248* a3 = excsave_1249* excsave_1 = orig a3250*251* We return to the instruction in user space that caused the window252* underflow exception. Therefore, we change window base to the value253* before we entered the window underflow exception and prepare the254* registers to return as if we were coming from a regular exception255* by changing depc (in a0).256* Note: We can trash the current window frame (a0...a3) and depc!257*/258_DoubleExceptionVector_WindowUnderflow:259xsr a3, excsave1260wsr a2, depc # save stack pointer temporarily261rsr a0, ps262extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH263wsr a0, windowbase264rsync265266/* We are now in the previous window frame. Save registers again. */267268xsr a2, depc # save a2 and get stack pointer269s32i a0, a2, PT_AREG0270xsr a3, excsave1271rsr a0, exccause272s32i a0, a2, PT_DEPC # mark it as a regular exception273addx4 a0, a0, a3274xsr a3, excsave1275l32i a0, a0, EXC_TABLE_FAST_USER276jx a0277278#else279j .Lfixup280#endif281282/*283* We only allow the ITLB miss exception if we are in kernel space.284* All other exceptions are unexpected and thus unrecoverable!285*/286287#ifdef CONFIG_MMU288.extern fast_second_level_miss_double_kernel289290.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */291292rsr a3, exccause293beqi a3, EXCCAUSE_ITLB_MISS, 1f294addi a3, a3, -EXCCAUSE_DTLB_MISS295bnez a3, .Lunrecoverable2961: movi a3, fast_second_level_miss_double_kernel297jx a3298#else299.equ .Lksp, .Lunrecoverable300#endif301302/* Critical! We can't handle this situation. PANIC! */303304.extern unrecoverable_exception305306.Lunrecoverable_fixup:307l32i a2, a3, EXC_TABLE_DOUBLE_SAVE308xsr a0, depc309310.Lunrecoverable:311rsr a3, excsave1312wsr a0, excsave1313call0 unrecoverable_exception314315.Lfixup:/* Check for a fixup handler or if we were in a critical section. */316317/* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave1: a3 */318319/* Enter critical section. */320321l32i a2, a3, EXC_TABLE_FIXUP322s32i a3, a3, EXC_TABLE_FIXUP323beq a2, a3, .Lunrecoverable_fixup # critical section324beqz a2, .Ldflt # no handler was registered325326/* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */327328jx a2329330.Ldflt: /* Get stack pointer. */331332l32i a2, a3, EXC_TABLE_DOUBLE_SAVE333addi a2, a2, -PT_USER_SIZE334335/* a0: depc, a1: a1, a2: kstk, a3: exctable, depc: a0, excsave: a3 */336337s32i a0, a2, PT_DEPC338l32i a0, a3, EXC_TABLE_DOUBLE_SAVE339xsr a0, depc340s32i a0, a2, PT_AREG0341342/* a0: avail, a1: a1, a2: kstk, a3: exctable, depc: a2, excsave: a3 */343344rsr a0, exccause345addx4 a0, a0, a3346xsr a3, excsave1347l32i a0, a0, EXC_TABLE_FAST_USER348jx a0349350#ifdef SUPPORT_WINDOWED351/*352* Restart window OVERFLOW exception.353* Currently:354* depc = orig a0,355* a0 = orig DEPC,356* a2 = new sp based on KSTK from exc_table357* a3 = EXCSAVE_1358* excsave_1 = orig a3359*360* We return to the instruction in user space that caused the window361* overflow exception. Therefore, we change window base to the value362* before we entered the window overflow exception and prepare the363* registers to return as if we were coming from a regular exception364* by changing DEPC (in a0).365*366* NOTE: We CANNOT trash the current window frame (a0...a3), but we367* can clobber depc.368*369* The tricky part here is that overflow8 and overflow12 handlers370* save a0, then clobber a0. To restart the handler, we have to restore371* a0 if the double exception was past the point where a0 was clobbered.372*373* To keep things simple, we take advantage of the fact all overflow374* handlers save a0 in their very first instruction. If DEPC was past375* that instruction, we can safely restore a0 from where it was saved376* on the stack.377*378* a0: depc, a1: a1, a2: kstk, a3: exc_table, depc: a0, excsave1: a3379*/380_DoubleExceptionVector_WindowOverflow:381extui a2, a0, 0, 6 # get offset into 64-byte vector handler382beqz a2, 1f # if at start of vector, don't restore383384addi a0, a0, -128385bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12386387/*388* This fixup handler is for the extremely unlikely case where the389* overflow handler's reference thru a0 gets a hardware TLB refill390* that bumps out the (distinct, aliasing) TLB entry that mapped its391* prior references thru a9/a13, and where our reference now thru392* a9/a13 gets a 2nd-level miss exception (not hardware TLB refill).393*/394movi a2, window_overflow_restore_a0_fixup395s32i a2, a3, EXC_TABLE_FIXUP396l32i a2, a3, EXC_TABLE_DOUBLE_SAVE397xsr a3, excsave1398399bbsi.l a0, 7, 2f400401/*402* Restore a0 as saved by _WindowOverflow8().403*/404405l32e a0, a9, -16406wsr a0, depc # replace the saved a0407j 3f4084092:410/*411* Restore a0 as saved by _WindowOverflow12().412*/413414l32e a0, a13, -16415wsr a0, depc # replace the saved a04163:417xsr a3, excsave1418movi a0, 0419s32i a0, a3, EXC_TABLE_FIXUP420s32i a2, a3, EXC_TABLE_DOUBLE_SAVE4211:422/*423* Restore WindowBase while leaving all address registers restored.424* We have to use ROTW for this, because WSR.WINDOWBASE requires425* an address register (which would prevent restore).426*427* Window Base goes from 0 ... 7 (Module 8)428* Window Start is 8 bits; Ex: (0b1010 1010):0x55 from series of call4s429*/430431rsr a0, ps432extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH433rsr a2, windowbase434sub a0, a2, a0435extui a0, a0, 0, 3436437l32i a2, a3, EXC_TABLE_DOUBLE_SAVE438xsr a3, excsave1439beqi a0, 1, .L1pane440beqi a0, 3, .L3pane441442rsr a0, depc443rotw -2444445/*446* We are now in the user code's original window frame.447* Process the exception as a user exception as if it was448* taken by the user code.449*450* This is similar to the user exception vector,451* except that PT_DEPC isn't set to EXCCAUSE.452*/4531:454xsr a3, excsave1455wsr a2, depc456l32i a2, a3, EXC_TABLE_KSTK457s32i a0, a2, PT_AREG0458rsr a0, exccause459460s32i a0, a2, PT_DEPC461462_DoubleExceptionVector_handle_exception:463addi a0, a0, -EXCCAUSE_UNALIGNED464beqz a0, 2f465addx4 a0, a0, a3466l32i a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED467xsr a3, excsave1468jx a04692:470movi a0, user_exception471xsr a3, excsave1472jx a0473474.L1pane:475rsr a0, depc476rotw -1477j 1b478479.L3pane:480rsr a0, depc481rotw -3482j 1b483#endif484485ENDPROC(_DoubleExceptionVector)486487#ifdef SUPPORT_WINDOWED488489/*490* Fixup handler for TLB miss in double exception handler for window owerflow.491* We get here with windowbase set to the window that was being spilled and492* a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12493* (bit set) window.494*495* We do the following here:496* - go to the original window retaining a0 value;497* - set up exception stack to return back to appropriate a0 restore code498* (we'll need to rotate window back and there's no place to save this499* information, use different return address for that);500* - handle the exception;501* - go to the window that was being spilled;502* - set up window_overflow_restore_a0_fixup as a fixup routine;503* - reload a0;504* - restore the original window;505* - reset the default fixup routine;506* - return to user. By the time we get to this fixup handler all information507* about the conditions of the original double exception that happened in508* the window overflow handler is lost, so we just return to userspace to509* retry overflow from start.510*511* a0: value of depc, original value in depc512* a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE513* a3: exctable, original value in excsave1514*/515516__XTENSA_HANDLER517.literal_position518519ENTRY(window_overflow_restore_a0_fixup)520521rsr a0, ps522extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH523rsr a2, windowbase524sub a0, a2, a0525extui a0, a0, 0, 3526l32i a2, a3, EXC_TABLE_DOUBLE_SAVE527xsr a3, excsave1528529_beqi a0, 1, .Lhandle_1530_beqi a0, 3, .Lhandle_3531532.macro overflow_fixup_handle_exception_pane n533534rsr a0, depc535rotw -\n536537xsr a3, excsave1538wsr a2, depc539l32i a2, a3, EXC_TABLE_KSTK540s32i a0, a2, PT_AREG0541542movi a0, .Lrestore_\n543s32i a0, a2, PT_DEPC544rsr a0, exccause545j _DoubleExceptionVector_handle_exception546547.endm548549overflow_fixup_handle_exception_pane 2550.Lhandle_1:551overflow_fixup_handle_exception_pane 1552.Lhandle_3:553overflow_fixup_handle_exception_pane 3554555.macro overflow_fixup_restore_a0_pane n556557rotw \n558/* Need to preserve a0 value here to be able to handle exception559* that may occur on a0 reload from stack. It may occur because560* TLB miss handler may not be atomic and pointer to page table561* may be lost before we get here. There are no free registers,562* so we need to use EXC_TABLE_DOUBLE_SAVE area.563*/564xsr a3, excsave1565s32i a2, a3, EXC_TABLE_DOUBLE_SAVE566movi a2, window_overflow_restore_a0_fixup567s32i a2, a3, EXC_TABLE_FIXUP568l32i a2, a3, EXC_TABLE_DOUBLE_SAVE569xsr a3, excsave1570bbsi.l a0, 7, 1f571l32e a0, a9, -16572j 2f5731:574l32e a0, a13, -165752:576rotw -\n577578.endm579580.Lrestore_2:581overflow_fixup_restore_a0_pane 2582583.Lset_default_fixup:584xsr a3, excsave1585s32i a2, a3, EXC_TABLE_DOUBLE_SAVE586movi a2, 0587s32i a2, a3, EXC_TABLE_FIXUP588l32i a2, a3, EXC_TABLE_DOUBLE_SAVE589xsr a3, excsave1590rfe591592.Lrestore_1:593overflow_fixup_restore_a0_pane 1594j .Lset_default_fixup595.Lrestore_3:596overflow_fixup_restore_a0_pane 3597j .Lset_default_fixup598599ENDPROC(window_overflow_restore_a0_fixup)600601#endif602603/*604* Debug interrupt vector605*606* There is not much space here, so simply jump to another handler.607* EXCSAVE[DEBUGLEVEL] has been set to that handler.608*/609610.section .DebugInterruptVector.text, "ax"611612ENTRY(_DebugInterruptVector)613614xsr a3, SREG_EXCSAVE + XCHAL_DEBUGLEVEL615s32i a0, a3, DT_DEBUG_SAVE616l32i a0, a3, DT_DEBUG_EXCEPTION617jx a0618619ENDPROC(_DebugInterruptVector)620621622623/*624* Medium priority level interrupt vectors625*626* Each takes less than 16 (0x10) bytes, no literals, by placing627* the extra 8 bytes that would otherwise be required in the window628* vectors area where there is space. With relocatable vectors,629* all vectors are within ~ 4 kB range of each other, so we can630* simply jump (J) to another vector without having to use JX.631*632* common_exception code gets current IRQ level in PS.INTLEVEL633* and preserves it for the IRQ handling time.634*/635636.macro irq_entry_level level637638.if XCHAL_EXCM_LEVEL >= \level639.section .Level\level\()InterruptVector.text, "ax"640ENTRY(_Level\level\()InterruptVector)641wsr a0, excsave2642rsr a0, epc\level643wsr a0, epc1644.if \level <= LOCKLEVEL645movi a0, EXCCAUSE_LEVEL1_INTERRUPT646.else647movi a0, EXCCAUSE_MAPPED_NMI648.endif649wsr a0, exccause650rsr a0, eps\level651# branch to user or kernel vector652j _SimulateUserKernelVectorException653.endif654655.endm656657irq_entry_level 2658irq_entry_level 3659irq_entry_level 4660irq_entry_level 5661irq_entry_level 6662663#if XCHAL_EXCM_LEVEL >= 2664/*665* Continuation of medium priority interrupt dispatch code.666* On entry here, a0 contains PS, and EPC2 contains saved a0:667*/668__XTENSA_HANDLER669.align 4670_SimulateUserKernelVectorException:671addi a0, a0, (1 << PS_EXCM_BIT)672#if !XTENSA_FAKE_NMI673wsr a0, ps674#endif675bbsi.l a0, PS_UM_BIT, 1f # branch if user mode676xsr a0, excsave2 # restore a0677j _KernelExceptionVector # simulate kernel vector exception6781: xsr a0, excsave2 # restore a0679j _UserExceptionVector # simulate user vector exception680#endif681682683/* Window overflow and underflow handlers.684* The handlers must be 64 bytes apart, first starting with the underflow685* handlers underflow-4 to underflow-12, then the overflow handlers686* overflow-4 to overflow-12.687*688* Note: We rerun the underflow handlers if we hit an exception, so689* we try to access any page that would cause a page fault early.690*/691692#define ENTRY_ALIGN64(name) \693.globl name; \694.align 64; \695name:696697.section .WindowVectors.text, "ax"698699700#ifdef SUPPORT_WINDOWED701702/* 4-Register Window Overflow Vector (Handler) */703704ENTRY_ALIGN64(_WindowOverflow4)705706s32e a0, a5, -16707s32e a1, a5, -12708s32e a2, a5, -8709s32e a3, a5, -4710rfwo711712ENDPROC(_WindowOverflow4)713714/* 4-Register Window Underflow Vector (Handler) */715716ENTRY_ALIGN64(_WindowUnderflow4)717718l32e a0, a5, -16719l32e a1, a5, -12720l32e a2, a5, -8721l32e a3, a5, -4722rfwu723724ENDPROC(_WindowUnderflow4)725726/* 8-Register Window Overflow Vector (Handler) */727728ENTRY_ALIGN64(_WindowOverflow8)729730s32e a0, a9, -16731l32e a0, a1, -12732s32e a2, a9, -8733s32e a1, a9, -12734s32e a3, a9, -4735s32e a4, a0, -32736s32e a5, a0, -28737s32e a6, a0, -24738s32e a7, a0, -20739rfwo740741ENDPROC(_WindowOverflow8)742743/* 8-Register Window Underflow Vector (Handler) */744745ENTRY_ALIGN64(_WindowUnderflow8)746747l32e a1, a9, -12748l32e a0, a9, -16749l32e a7, a1, -12750l32e a2, a9, -8751l32e a4, a7, -32752l32e a3, a9, -4753l32e a5, a7, -28754l32e a6, a7, -24755l32e a7, a7, -20756rfwu757758ENDPROC(_WindowUnderflow8)759760/* 12-Register Window Overflow Vector (Handler) */761762ENTRY_ALIGN64(_WindowOverflow12)763764s32e a0, a13, -16765l32e a0, a1, -12766s32e a1, a13, -12767s32e a2, a13, -8768s32e a3, a13, -4769s32e a4, a0, -48770s32e a5, a0, -44771s32e a6, a0, -40772s32e a7, a0, -36773s32e a8, a0, -32774s32e a9, a0, -28775s32e a10, a0, -24776s32e a11, a0, -20777rfwo778779ENDPROC(_WindowOverflow12)780781/* 12-Register Window Underflow Vector (Handler) */782783ENTRY_ALIGN64(_WindowUnderflow12)784785l32e a1, a13, -12786l32e a0, a13, -16787l32e a11, a1, -12788l32e a2, a13, -8789l32e a4, a11, -48790l32e a8, a11, -32791l32e a3, a13, -4792l32e a5, a11, -44793l32e a6, a11, -40794l32e a7, a11, -36795l32e a9, a11, -28796l32e a10, a11, -24797l32e a11, a11, -20798rfwu799800ENDPROC(_WindowUnderflow12)801802#endif803804.text805806807