aboutsummaryrefslogtreecommitdiff
path: root/libgloss/mips/hal/mips_excpt_entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/mips/hal/mips_excpt_entry.S')
-rw-r--r--libgloss/mips/hal/mips_excpt_entry.S210
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)