diff options
Diffstat (limited to 'libgloss/mips/hal/mips_excpt_entry.S')
-rw-r--r-- | libgloss/mips/hal/mips_excpt_entry.S | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/libgloss/mips/hal/mips_excpt_entry.S b/libgloss/mips/hal/mips_excpt_entry.S new file mode 100644 index 0000000..f1e6a41 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_entry.S @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _FUNCTION_SECTIONS_ + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> +#include <mips/ctx.S> + +MIPS_NOMIPS16 + +/* Stack adjustment for ABI parameter area. */ +#define ADJ (NARGSAVE * SZARG) +/* + * Round the context size up to a 16-byte boundary which is the maximum + * stack alignment required for any supported ABI. + */ +#define CTX_SIZEROUND ((CTX_SIZE + ALSZ) & ALMASK) + +/* + * Exception entry points. These are designed for use at EBASE when + * STATUS.BEV is clear. + * The entry points will either chain on to a user-supplied function + * or loop indefinitely. + */ + +LEAF(__exception_entry) + .set push + .set noat +.weak _mips_tlb_refill + _mips_tlb_refill = __exception_save +__tlb_refill_loop: + /* + * Support an alternative entry point at the start of the exception + * vector. Since the exception vector is normally placed first + * in the link map this allows a user to start execution from the + * same address that an executable is loaded to. + */ + LA k1, __first_boot + lw k1, 0(k1) + beqz k1, 1f + /* + * The start code is responsible for clearing __first_boot prior + * to installing the exception handlers. + */ + LA k1, _start + jr k1 +1: + /* Support the case where no handler is defined. */ + LA k1, _mips_tlb_refill + beqz k1, __tlb_refill_loop + jr k1 + + .org 0x80 +.weak _mips_xtlb_refill + _mips_xtlb_refill = __exception_save +__xtlb_refill_loop: + LA k1, _mips_xtlb_refill + beqz k1, __xtlb_refill_loop + jr k1 + + .org 0x100 +.weak _mips_cache_error +__cache_error_loop: + LA k1, _mips_cache_error + beqz k1, __cache_error_loop + jr k1 + + .org 0x180 +.weak _mips_general_exception +__general_exception_loop: + /* + * Free up k1, defering sp adjustment until later. Preserving k1 + * may be undesirable if an exception occurs due to a corrupt + * stack but since the default handlers use the user-stack to + * store the context then there is nothing to lose. + */ + REG_S k1, (-CTX_SIZEROUND + CTX_K1)(sp) + + LA k1, _mips_general_exception + beqz k1, __general_exception_loop + jr k1 + .set pop +END(__exception_entry) + +/* + * FUNCTION: __exception_save + * + * DESCRIPTION: Saves the GP context to the stack and invokes + * _mips_handle_exception with appropriate arguments. +*/ +ANESTED(__exception_save, _mips_general_exception, CTX_SIZEROUND + ADJ, zero) + .globl __exception_save; + .set push + .set noat + + /* Create pointer to gp_ctx. */ + PTR_ADDU k1, sp, -CTX_SIZEROUND + + /* Save context. */ + _gpctx_save + /* va0 now holds C0_STATUS. */ + + /* Finish storing the rest of the CP0 registers. */ + PTR_MFC0 t0, C0_BADVADDR + REG_S t0, CTX_BADVADDR(k1) + +#if __mips_isa_rev < 6 + move t0, zero + move t1, zero + mfc0 t2, C0_CONFIG3 + ext t3, t2, CFG3_BP_SHIFT, 1 + beqz t3, 1f +#else + /* MIPSR6 guarantees all CP0 regs are defined to at + least return zero. */ +#endif + mfc0 t0, C0_BADPINSTR +#if __mips_isa_rev < 6 +1: + ext t2, t2, CFG3_BI_SHIFT, 1 + beqz t2, 1f +#endif + mfc0 t1, C0_BADINSTR +1: + sw t0, CTX_BADPINSTR(k1) + sw t1, CTX_BADINSTR(k1) + + /* Get and store the exception cause. */ + mfc0 t0, C0_CR + sw t0, CTX_CAUSE(k1) + + /* Extract the cause code for argument 1. */ + ext a1, t0, CR_X_SHIFT, CR_X_BITS + + /* Create the argument space. */ + addiu sp, k1, -ADJ + + /* Clear EXL. Exceptions can now nest. */ + ins va0, zero, SR_EXL_SHIFT, 1 + mtc0 va0, C0_SR + + /* Move the gp_ctx pointer for argument 0. */ + addiu a0, sp, ADJ + + /* Manually set up the return address to restore the context below. */ + LA ra, __exception_restore + + /* Call the handler, indirect through t9 albeit not for any specific + reason. */ + LA t9, _mips_handle_exception + jr t9 + + .set pop +END(__exception_save) + +/* + * FUNCTION: __exception_restore + * + * DESCRIPTION: Load the GP context from immediately above the stack + * pointer and eret. + */ +LEAF(__exception_restore) + .set push + .set noat + + /* Skip past the argument save area and fall through. */ + addiu a0, sp, ADJ + +/* + * FUNCTION: __gpctx_load_eret + * + * DESCRIPTION: Load the GP context from the address in register a0 + * and eret. + */ +AENT(__gpctx_load_eret) + + _gpctx_load + + /* Return from exception. */ + eret + .set pop +END(__exception_restore) |