--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Generation of main entry point for the guest, exception handling.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ *
+ * Copyright (C) 2016 Imagination Technologies Ltd.
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/msa.h>
+#include <asm/setup.h>
+#include <asm/uasm.h>
+
+/* Register names */
+#define ZERO           0
+#define AT             1
+#define V0             2
+#define V1             3
+#define A0             4
+#define A1             5
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define T0             8
+#define T1             9
+#define T2             10
+#define T3             11
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
+
+#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+#define T0             12
+#define T1             13
+#define T2             14
+#define T3             15
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+#define S0             16
+#define S1             17
+#define T9             25
+#define K0             26
+#define K1             27
+#define GP             28
+#define SP             29
+#define RA             31
+
+/* Some CP0 registers */
+#define C0_HWRENA      7, 0
+#define C0_BADVADDR    8, 0
+#define C0_ENTRYHI     10, 0
+#define C0_STATUS      12, 0
+#define C0_CAUSE       13, 0
+#define C0_EPC         14, 0
+#define C0_EBASE       15, 1
+#define C0_CONFIG3     16, 3
+#define C0_CONFIG5     16, 5
+#define C0_DDATA_LO    28, 3
+#define C0_ERROREPC    30, 0
+
+#define CALLFRAME_SIZ   32
+
+enum label_id {
+       label_fpu_1 = 1,
+       label_msa_1,
+       label_return_to_host,
+       label_kernel_asid,
+};
+
+UASM_L_LA(_fpu_1)
+UASM_L_LA(_msa_1)
+UASM_L_LA(_return_to_host)
+UASM_L_LA(_kernel_asid)
+
+static void *kvm_mips_build_enter_guest(void *addr);
+static void *kvm_mips_build_ret_from_exit(void *addr);
+static void *kvm_mips_build_ret_to_guest(void *addr);
+static void *kvm_mips_build_ret_to_host(void *addr);
+
+/**
+ * kvm_mips_build_vcpu_run() - Assemble function to start running a guest VCPU.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble the start of the vcpu_run function to run a guest VCPU. The function
+ * conforms to the following prototype:
+ *
+ * int vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu);
+ *
+ * The exit from the guest and return to the caller is handled by the code
+ * generated by kvm_mips_build_ret_to_host().
+ *
+ * Returns:    Next address after end of written function.
+ */
+void *kvm_mips_build_vcpu_run(void *addr)
+{
+       u32 *p = addr;
+       unsigned int i;
+
+       /*
+        * A0: run
+        * A1: vcpu
+        */
+
+       /* k0/k1 not being used in host kernel context */
+       uasm_i_addiu(&p, K1, SP, -(int)sizeof(struct pt_regs));
+       for (i = 16; i < 32; ++i) {
+               if (i == 24)
+                       i = 28;
+               UASM_i_SW(&p, i, offsetof(struct pt_regs, regs[i]), K1);
+       }
+
+       /* Save hi/lo */
+       uasm_i_mflo(&p, V0);
+       UASM_i_SW(&p, V0, offsetof(struct pt_regs, lo), K1);
+       uasm_i_mfhi(&p, V1);
+       UASM_i_SW(&p, V1, offsetof(struct pt_regs, hi), K1);
+
+       /* Save host status */
+       uasm_i_mfc0(&p, V0, C0_STATUS);
+       UASM_i_SW(&p, V0, offsetof(struct pt_regs, cp0_status), K1);
+
+       /* Save DDATA_LO, will be used to store pointer to vcpu */
+       uasm_i_mfc0(&p, V1, C0_DDATA_LO);
+       UASM_i_SW(&p, V1, offsetof(struct pt_regs, cp0_epc), K1);
+
+       /* DDATA_LO has pointer to vcpu */
+       uasm_i_mtc0(&p, A1, C0_DDATA_LO);
+
+       /* Offset into vcpu->arch */
+       uasm_i_addiu(&p, K1, A1, offsetof(struct kvm_vcpu, arch));
+
+       /*
+        * Save the host stack to VCPU, used for exception processing
+        * when we exit from the Guest
+        */
+       UASM_i_SW(&p, SP, offsetof(struct kvm_vcpu_arch, host_stack), K1);
+
+       /* Save the kernel gp as well */
+       UASM_i_SW(&p, GP, offsetof(struct kvm_vcpu_arch, host_gp), K1);
+
+       /*
+        * Setup status register for running the guest in UM, interrupts
+        * are disabled
+        */
+       UASM_i_LA(&p, K0, ST0_EXL | KSU_USER | ST0_BEV);
+       uasm_i_mtc0(&p, K0, C0_STATUS);
+       uasm_i_ehb(&p);
+
+       /* load up the new EBASE */
+       UASM_i_LW(&p, K0, offsetof(struct kvm_vcpu_arch, guest_ebase), K1);
+       uasm_i_mtc0(&p, K0, C0_EBASE);
+
+       /*
+        * Now that the new EBASE has been loaded, unset BEV, set
+        * interrupt mask as it was but make sure that timer interrupts
+        * are enabled
+        */
+       uasm_i_addiu(&p, K0, ZERO, ST0_EXL | KSU_USER | ST0_IE);
+       uasm_i_andi(&p, V0, V0, ST0_IM);
+       uasm_i_or(&p, K0, K0, V0);
+       uasm_i_mtc0(&p, K0, C0_STATUS);
+       uasm_i_ehb(&p);
+
+       p = kvm_mips_build_enter_guest(p);
+
+       return p;
+}
+
+/**
+ * kvm_mips_build_enter_guest() - Assemble code to resume guest execution.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble the code to resume guest execution. This code is common between the
+ * initial entry into the guest from the host, and returning from the exit
+ * handler back to the guest.
+ *
+ * Returns:    Next address after end of written function.
+ */
+static void *kvm_mips_build_enter_guest(void *addr)
+{
+       u32 *p = addr;
+       unsigned int i;
+       struct uasm_label labels[2];
+       struct uasm_reloc relocs[2];
+       struct uasm_label *l = labels;
+       struct uasm_reloc *r = relocs;
+
+       memset(labels, 0, sizeof(labels));
+       memset(relocs, 0, sizeof(relocs));
+
+       /* Set Guest EPC */
+       UASM_i_LW(&p, T0, offsetof(struct kvm_vcpu_arch, pc), K1);
+       uasm_i_mtc0(&p, T0, C0_EPC);
+
+       /* Set the ASID for the Guest Kernel */
+       UASM_i_LW(&p, T0, offsetof(struct kvm_vcpu_arch, cop0), K1);
+       UASM_i_LW(&p, T0, offsetof(struct mips_coproc, reg[MIPS_CP0_STATUS][0]),
+                 T0);
+       uasm_i_andi(&p, T0, T0, KSU_USER | ST0_ERL | ST0_EXL);
+       uasm_i_xori(&p, T0, T0, KSU_USER);
+       uasm_il_bnez(&p, &r, T0, label_kernel_asid);
+        uasm_i_addiu(&p, T1, K1,
+                     offsetof(struct kvm_vcpu_arch, guest_kernel_asid));
+       /* else user */
+       uasm_i_addiu(&p, T1, K1,
+                    offsetof(struct kvm_vcpu_arch, guest_user_asid));
+       uasm_l_kernel_asid(&l, p);
+
+       /* t1: contains the base of the ASID array, need to get the cpu id  */
+       /* smp_processor_id */
+       UASM_i_LW(&p, T2, offsetof(struct thread_info, cpu), GP);
+       /* x4 */
+       uasm_i_sll(&p, T2, T2, 2);
+       UASM_i_ADDU(&p, T3, T1, T2);
+       UASM_i_LW(&p, K0, 0, T3);
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       /* x sizeof(struct cpuinfo_mips)/4 */
+       uasm_i_addiu(&p, T3, ZERO, sizeof(struct cpuinfo_mips)/4);
+       uasm_i_mul(&p, T2, T2, T3);
+
+       UASM_i_LA_mostly(&p, AT, (long)&cpu_data[0].asid_mask);
+       UASM_i_ADDU(&p, AT, AT, T2);
+       UASM_i_LW(&p, T2, uasm_rel_lo((long)&cpu_data[0].asid_mask), AT);
+       uasm_i_and(&p, K0, K0, T2);
+#else
+       uasm_i_andi(&p, K0, K0, MIPS_ENTRYHI_ASID);
+#endif
+       uasm_i_mtc0(&p, K0, C0_ENTRYHI);
+       uasm_i_ehb(&p);
+
+       /* Disable RDHWR access */
+       uasm_i_mtc0(&p, ZERO, C0_HWRENA);
+
+       /* load the guest context from VCPU and return */
+       for (i = 1; i < 32; ++i) {
+               /* Guest k0/k1 loaded later */
+               if (i == K0 || i == K1)
+                       continue;
+               UASM_i_LW(&p, i, offsetof(struct kvm_vcpu_arch, gprs[i]), K1);
+       }
+
+       /* Restore hi/lo */
+       UASM_i_LW(&p, K0, offsetof(struct kvm_vcpu_arch, hi), K1);
+       uasm_i_mthi(&p, K0);
+
+       UASM_i_LW(&p, K0, offsetof(struct kvm_vcpu_arch, lo), K1);
+       uasm_i_mtlo(&p, K0);
+
+       /* Restore the guest's k0/k1 registers */
+       UASM_i_LW(&p, K0, offsetof(struct kvm_vcpu_arch, gprs[K0]), K1);
+       UASM_i_LW(&p, K1, offsetof(struct kvm_vcpu_arch, gprs[K1]), K1);
+
+       /* Jump to guest */
+       uasm_i_eret(&p);
+
+       uasm_resolve_relocs(relocs, labels);
+
+       return p;
+}
+
+/**
+ * kvm_mips_build_exception() - Assemble first level guest exception handler.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble exception vector code for guest execution. The generated vector will
+ * jump to the common exception handler generated by kvm_mips_build_exit().
+ *
+ * Returns:    Next address after end of written function.
+ */
+void *kvm_mips_build_exception(void *addr)
+{
+       u32 *p = addr;
+
+       /* Save guest k0 */
+       uasm_i_mtc0(&p, K0, C0_ERROREPC);
+       uasm_i_ehb(&p);
+
+       /* Get EBASE */
+       uasm_i_mfc0(&p, K0, C0_EBASE);
+       /* Get rid of CPUNum */
+       uasm_i_srl(&p, K0, K0, 10);
+       uasm_i_sll(&p, K0, K0, 10);
+       /* Save k1 @ offset 0x3000 */
+       UASM_i_SW(&p, K1, 0x3000, K0);
+
+       /* Exception handler is installed @ offset 0x2000 */
+       uasm_i_addiu(&p, K0, K0, 0x2000);
+       /* Jump to the function */
+       uasm_i_jr(&p, K0);
+        uasm_i_nop(&p);
+
+       return p;
+}
+
+/**
+ * kvm_mips_build_exit() - Assemble common guest exit handler.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble the generic guest exit handling code. This is called by the
+ * exception vectors (generated by kvm_mips_build_exception()), and calls
+ * kvm_mips_handle_exit(), then either resumes the guest or returns to the host
+ * depending on the return value.
+ *
+ * Returns:    Next address after end of written function.
+ */
+void *kvm_mips_build_exit(void *addr)
+{
+       u32 *p = addr;
+       unsigned int i;
+       struct uasm_label labels[3];
+       struct uasm_reloc relocs[3];
+       struct uasm_label *l = labels;
+       struct uasm_reloc *r = relocs;
+
+       memset(labels, 0, sizeof(labels));
+       memset(relocs, 0, sizeof(relocs));
+
+       /*
+        * Generic Guest exception handler. We end up here when the guest
+        * does something that causes a trap to kernel mode.
+        */
+
+       /* Get the VCPU pointer from DDATA_LO */
+       uasm_i_mfc0(&p, K1, C0_DDATA_LO);
+       uasm_i_addiu(&p, K1, K1, offsetof(struct kvm_vcpu, arch));
+
+       /* Start saving Guest context to VCPU */
+       for (i = 0; i < 32; ++i) {
+               /* Guest k0/k1 saved later */
+               if (i == K0 || i == K1)
+                       continue;
+               UASM_i_SW(&p, i, offsetof(struct kvm_vcpu_arch, gprs[i]), K1);
+       }
+
+       /* We need to save hi/lo and restore them on the way out */
+       uasm_i_mfhi(&p, T0);
+       UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, hi), K1);
+
+       uasm_i_mflo(&p, T0);
+       UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, lo), K1);
+
+       /* Finally save guest k0/k1 to VCPU */
+       uasm_i_mfc0(&p, T0, C0_ERROREPC);
+       UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, gprs[K0]), K1);
+
+       /* Get GUEST k1 and save it in VCPU */
+       uasm_i_addiu(&p, T1, ZERO, ~0x2ff);
+       uasm_i_mfc0(&p, T0, C0_EBASE);
+       uasm_i_and(&p, T0, T0, T1);
+       UASM_i_LW(&p, T0, 0x3000, T0);
+       UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, gprs[K1]), K1);
+
+       /* Now that context has been saved, we can use other registers */
+
+       /* Restore vcpu */
+       uasm_i_mfc0(&p, A1, C0_DDATA_LO);
+       uasm_i_move(&p, S1, A1);
+
+       /* Restore run (vcpu->run) */
+       UASM_i_LW(&p, A0, offsetof(struct kvm_vcpu, run), A1);
+       /* Save pointer to run in s0, will be saved by the compiler */
+       uasm_i_move(&p, S0, A0);
+
+       /*
+        * Save Host level EPC, BadVaddr and Cause to VCPU, useful to process
+        * the exception
+        */
+       uasm_i_mfc0(&p, K0, C0_EPC);
+       UASM_i_SW(&p, K0, offsetof(struct kvm_vcpu_arch, pc), K1);
+
+       uasm_i_mfc0(&p, K0, C0_BADVADDR);
+       UASM_i_SW(&p, K0, offsetof(struct kvm_vcpu_arch, host_cp0_badvaddr),
+                 K1);
+
+       uasm_i_mfc0(&p, K0, C0_CAUSE);
+       uasm_i_sw(&p, K0, offsetof(struct kvm_vcpu_arch, host_cp0_cause), K1);
+
+       /* Now restore the host state just enough to run the handlers */
+
+       /* Switch EBASE to the one used by Linux */
+       /* load up the host EBASE */
+       uasm_i_mfc0(&p, V0, C0_STATUS);
+
+       uasm_i_lui(&p, AT, ST0_BEV >> 16);
+       uasm_i_or(&p, K0, V0, AT);
+
+       uasm_i_mtc0(&p, K0, C0_STATUS);
+       uasm_i_ehb(&p);
+
+       UASM_i_LA_mostly(&p, K0, (long)&ebase);
+       UASM_i_LW(&p, K0, uasm_rel_lo((long)&ebase), K0);
+       uasm_i_mtc0(&p, K0, C0_EBASE);
+
+       /*
+        * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
+        * trigger FPE for pending exceptions.
+        */
+       uasm_i_lui(&p, AT, ST0_CU1 >> 16);
+       uasm_i_and(&p, V1, V0, AT);
+       uasm_il_beqz(&p, &r, V1, label_fpu_1);
+        uasm_i_nop(&p);
+       uasm_i_cfc1(&p, T0, 31);
+       uasm_i_sw(&p, T0, offsetof(struct kvm_vcpu_arch, fpu.fcr31), K1);
+       uasm_i_ctc1(&p, ZERO, 31);
+       uasm_l_fpu_1(&l, p);
+
+#ifdef CONFIG_CPU_HAS_MSA
+       /*
+        * If MSA is enabled, save MSACSR and clear it so that later
+        * instructions don't trigger MSAFPE for pending exceptions.
+        */
+       uasm_i_mfc0(&p, T0, C0_CONFIG3);
+       uasm_i_ext(&p, T0, T0, 28, 1); /* MIPS_CONF3_MSAP */
+       uasm_il_beqz(&p, &r, T0, label_msa_1);
+        uasm_i_nop(&p);
+       uasm_i_mfc0(&p, T0, C0_CONFIG5);
+       uasm_i_ext(&p, T0, T0, 27, 1); /* MIPS_CONF5_MSAEN */
+       uasm_il_beqz(&p, &r, T0, label_msa_1);
+        uasm_i_nop(&p);
+       uasm_i_cfcmsa(&p, T0, MSA_CSR);
+       uasm_i_sw(&p, T0, offsetof(struct kvm_vcpu_arch, fpu.msacsr),
+                 K1);
+       uasm_i_ctcmsa(&p, MSA_CSR, ZERO);
+       uasm_l_msa_1(&l, p);
+#endif
+
+       /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
+       uasm_i_addiu(&p, AT, ZERO, ~(ST0_EXL | KSU_USER | ST0_IE));
+       uasm_i_and(&p, V0, V0, AT);
+       uasm_i_lui(&p, AT, ST0_CU0 >> 16);
+       uasm_i_or(&p, V0, V0, AT);
+       uasm_i_mtc0(&p, V0, C0_STATUS);
+       uasm_i_ehb(&p);
+
+       /* Load up host GP */
+       UASM_i_LW(&p, GP, offsetof(struct kvm_vcpu_arch, host_gp), K1);
+
+       /* Need a stack before we can jump to "C" */
+       UASM_i_LW(&p, SP, offsetof(struct kvm_vcpu_arch, host_stack), K1);
+
+       /* Saved host state */
+       uasm_i_addiu(&p, SP, SP, -(int)sizeof(struct pt_regs));
+
+       /*
+        * XXXKYMA do we need to load the host ASID, maybe not because the
+        * kernel entries are marked GLOBAL, need to verify
+        */
+
+       /* Restore host DDATA_LO */
+       UASM_i_LW(&p, K0, offsetof(struct pt_regs, cp0_epc), SP);
+       uasm_i_mtc0(&p, K0, C0_DDATA_LO);
+
+       /* Restore RDHWR access */
+       UASM_i_LA_mostly(&p, K0, (long)&hwrena);
+       uasm_i_lw(&p, K0, uasm_rel_lo((long)&hwrena), K0);
+       uasm_i_mtc0(&p, K0, C0_HWRENA);
+
+       /* Jump to handler */
+       /*
+        * XXXKYMA: not sure if this is safe, how large is the stack??
+        * Now jump to the kvm_mips_handle_exit() to see if we can deal
+        * with this in the kernel
+        */
+       UASM_i_LA(&p, T9, (unsigned long)kvm_mips_handle_exit);
+       uasm_i_jalr(&p, RA, T9);
+        uasm_i_addiu(&p, SP, SP, -CALLFRAME_SIZ);
+
+       uasm_resolve_relocs(relocs, labels);
+
+       p = kvm_mips_build_ret_from_exit(p);
+
+       return p;
+}
+
+/**
+ * kvm_mips_build_ret_from_exit() - Assemble guest exit return handler.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble the code to handle the return from kvm_mips_handle_exit(), either
+ * resuming the guest or returning to the host depending on the return value.
+ *
+ * Returns:    Next address after end of written function.
+ */
+static void *kvm_mips_build_ret_from_exit(void *addr)
+{
+       u32 *p = addr;
+       struct uasm_label labels[2];
+       struct uasm_reloc relocs[2];
+       struct uasm_label *l = labels;
+       struct uasm_reloc *r = relocs;
+
+       memset(labels, 0, sizeof(labels));
+       memset(relocs, 0, sizeof(relocs));
+
+       /* Return from handler Make sure interrupts are disabled */
+       uasm_i_di(&p, ZERO);
+       uasm_i_ehb(&p);
+
+       /*
+        * XXXKYMA: k0/k1 could have been blown away if we processed
+        * an exception while we were handling the exception from the
+        * guest, reload k1
+        */
+
+       uasm_i_move(&p, K1, S1);
+       uasm_i_addiu(&p, K1, K1, offsetof(struct kvm_vcpu, arch));
+
+       /*
+        * Check return value, should tell us if we are returning to the
+        * host (handle I/O etc)or resuming the guest
+        */
+       uasm_i_andi(&p, T0, V0, RESUME_HOST);
+       uasm_il_bnez(&p, &r, T0, label_return_to_host);
+        uasm_i_nop(&p);
+
+       p = kvm_mips_build_ret_to_guest(p);
+
+       uasm_l_return_to_host(&l, p);
+       p = kvm_mips_build_ret_to_host(p);
+
+       uasm_resolve_relocs(relocs, labels);
+
+       return p;
+}
+
+/**
+ * kvm_mips_build_ret_to_guest() - Assemble code to return to the guest.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble the code to handle return from the guest exit handler
+ * (kvm_mips_handle_exit()) back to the guest.
+ *
+ * Returns:    Next address after end of written function.
+ */
+static void *kvm_mips_build_ret_to_guest(void *addr)
+{
+       u32 *p = addr;
+
+       /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
+       uasm_i_mtc0(&p, S1, C0_DDATA_LO);
+
+       /* Load up the Guest EBASE to minimize the window where BEV is set */
+       UASM_i_LW(&p, T0, offsetof(struct kvm_vcpu_arch, guest_ebase), K1);
+
+       /* Switch EBASE back to the one used by KVM */
+       uasm_i_mfc0(&p, V1, C0_STATUS);
+       uasm_i_lui(&p, AT, ST0_BEV >> 16);
+       uasm_i_or(&p, K0, V1, AT);
+       uasm_i_mtc0(&p, K0, C0_STATUS);
+       uasm_i_ehb(&p);
+       uasm_i_mtc0(&p, T0, C0_EBASE);
+
+       /* Setup status register for running guest in UM */
+       uasm_i_ori(&p, V1, V1, ST0_EXL | KSU_USER | ST0_IE);
+       UASM_i_LA(&p, AT, ~(ST0_CU0 | ST0_MX));
+       uasm_i_and(&p, V1, V1, AT);
+       uasm_i_mtc0(&p, V1, C0_STATUS);
+       uasm_i_ehb(&p);
+
+       p = kvm_mips_build_enter_guest(p);
+
+       return p;
+}
+
+/**
+ * kvm_mips_build_ret_to_host() - Assemble code to return to the host.
+ * @addr:      Address to start writing code.
+ *
+ * Assemble the code to handle return from the guest exit handler
+ * (kvm_mips_handle_exit()) back to the host, i.e. to the caller of the vcpu_run
+ * function generated by kvm_mips_build_vcpu_run().
+ *
+ * Returns:    Next address after end of written function.
+ */
+static void *kvm_mips_build_ret_to_host(void *addr)
+{
+       u32 *p = addr;
+       unsigned int i;
+
+       /* EBASE is already pointing to Linux */
+       UASM_i_LW(&p, K1, offsetof(struct kvm_vcpu_arch, host_stack), K1);
+       uasm_i_addiu(&p, K1, K1, -(int)sizeof(struct pt_regs));
+
+       /* Restore host DDATA_LO */
+       UASM_i_LW(&p, K0, offsetof(struct pt_regs, cp0_epc), K1);
+       uasm_i_mtc0(&p, K0, C0_DDATA_LO);
+
+       /*
+        * r2/v0 is the return code, shift it down by 2 (arithmetic)
+        * to recover the err code
+        */
+       uasm_i_sra(&p, K0, V0, 2);
+       uasm_i_move(&p, V0, K0);
+
+       /* Load context saved on the host stack */
+       for (i = 16; i < 31; ++i) {
+               if (i == 24)
+                       i = 28;
+               UASM_i_LW(&p, i, offsetof(struct pt_regs, regs[i]), K1);
+       }
+
+       UASM_i_LW(&p, K0, offsetof(struct pt_regs, hi), K1);
+       uasm_i_mthi(&p, K0);
+
+       UASM_i_LW(&p, K0, offsetof(struct pt_regs, lo), K1);
+       uasm_i_mtlo(&p, K0);
+
+       /* Restore RDHWR access */
+       UASM_i_LA_mostly(&p, K0, (long)&hwrena);
+       uasm_i_lw(&p, K0, uasm_rel_lo((long)&hwrena), K0);
+       uasm_i_mtc0(&p, K0, C0_HWRENA);
+
+       /* Restore RA, which is the address we will return to */
+       UASM_i_LW(&p, RA, offsetof(struct pt_regs, regs[RA]), K1);
+       uasm_i_jr(&p, RA);
+        uasm_i_nop(&p);
+
+       return p;
+}
+
 
+++ /dev/null
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Main entry point for the guest, exception handling.
- *
- * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
- * Authors: Sanjay Lal <sanjayl@kymasys.com>
- */
-
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/asm-offsets.h>
-
-#define _C_LABEL(x)     x
-#define MIPSX(name)     mips32_ ## name
-#define CALLFRAME_SIZ   32
-
-/*
- * VECTOR
- *  exception vector entrypoint
- */
-#define VECTOR(x, regmask)      \
-    .ent    _C_LABEL(x),0;      \
-    EXPORT(x);
-
-#define VECTOR_END(x)      \
-    EXPORT(x);
-
-/* Overload, Danger Will Robinson!! */
-#define PT_HOST_USERLOCAL   PT_EPC
-
-#define CP0_DDATA_LO        $28,3
-
-/* Resume Flags */
-#define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
-
-#define RESUME_GUEST            0
-#define RESUME_HOST             RESUME_FLAG_HOST
-
-/*
- * __kvm_mips_vcpu_run: entry point to the guest
- * a0: run
- * a1: vcpu
- */
-       .set    noreorder
-
-FEXPORT(__kvm_mips_vcpu_run)
-       /* k0/k1 not being used in host kernel context */
-       INT_ADDIU k1, sp, -PT_SIZE
-       LONG_S  $16, PT_R16(k1)
-       LONG_S  $17, PT_R17(k1)
-       LONG_S  $18, PT_R18(k1)
-       LONG_S  $19, PT_R19(k1)
-       LONG_S  $20, PT_R20(k1)
-       LONG_S  $21, PT_R21(k1)
-       LONG_S  $22, PT_R22(k1)
-       LONG_S  $23, PT_R23(k1)
-
-       LONG_S  $28, PT_R28(k1)
-       LONG_S  $29, PT_R29(k1)
-       LONG_S  $30, PT_R30(k1)
-       LONG_S  $31, PT_R31(k1)
-
-       /* Save hi/lo */
-       mflo    v0
-       LONG_S  v0, PT_LO(k1)
-       mfhi    v1
-       LONG_S  v1, PT_HI(k1)
-
-       /* Save host status */
-       mfc0    v0, CP0_STATUS
-       LONG_S  v0, PT_STATUS(k1)
-
-       /* Save DDATA_LO, will be used to store pointer to vcpu */
-       mfc0    v1, CP0_DDATA_LO
-       LONG_S  v1, PT_HOST_USERLOCAL(k1)
-
-       /* DDATA_LO has pointer to vcpu */
-       mtc0    a1, CP0_DDATA_LO
-
-       /* Offset into vcpu->arch */
-       INT_ADDIU k1, a1, VCPU_HOST_ARCH
-
-       /*
-        * Save the host stack to VCPU, used for exception processing
-        * when we exit from the Guest
-        */
-       LONG_S  sp, VCPU_HOST_STACK(k1)
-
-       /* Save the kernel gp as well */
-       LONG_S  gp, VCPU_HOST_GP(k1)
-
-       /*
-        * Setup status register for running the guest in UM, interrupts
-        * are disabled
-        */
-       li      k0, (ST0_EXL | KSU_USER | ST0_BEV)
-       mtc0    k0, CP0_STATUS
-       ehb
-
-       /* load up the new EBASE */
-       LONG_L  k0, VCPU_GUEST_EBASE(k1)
-       mtc0    k0, CP0_EBASE
-
-       /*
-        * Now that the new EBASE has been loaded, unset BEV, set
-        * interrupt mask as it was but make sure that timer interrupts
-        * are enabled
-        */
-       li      k0, (ST0_EXL | KSU_USER | ST0_IE)
-       andi    v0, v0, ST0_IM
-       or      k0, k0, v0
-       mtc0    k0, CP0_STATUS
-       ehb
-
-       /* Set Guest EPC */
-       LONG_L  t0, VCPU_PC(k1)
-       mtc0    t0, CP0_EPC
-
-FEXPORT(__kvm_mips_load_asid)
-       /* Set the ASID for the Guest Kernel */
-       PTR_L   t0, VCPU_COP0(k1)
-       LONG_L  t0, COP0_STATUS(t0)
-       andi    t0, KSU_USER | ST0_ERL | ST0_EXL
-       xori    t0, KSU_USER
-       bnez    t0, 1f          /* If kernel */
-        INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
-       INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
-1:
-       /* t1: contains the base of the ASID array, need to get the cpu id */
-       LONG_L  t2, TI_CPU($28)             /* smp_processor_id */
-       INT_SLL t2, t2, 2                   /* x4 */
-       REG_ADDU t3, t1, t2
-       LONG_L  k0, (t3)
-#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
-       li      t3, CPUINFO_SIZE/4
-       mul     t2, t2, t3              /* x sizeof(struct cpuinfo_mips)/4 */
-       LONG_L  t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
-       and     k0, k0, t2
-#else
-       andi    k0, k0, MIPS_ENTRYHI_ASID
-#endif
-       mtc0    k0, CP0_ENTRYHI
-       ehb
-
-       /* Disable RDHWR access */
-       mtc0    zero, CP0_HWRENA
-
-       .set    noat
-       /* Now load up the Guest Context from VCPU */
-       LONG_L  $1, VCPU_R1(k1)
-       LONG_L  $2, VCPU_R2(k1)
-       LONG_L  $3, VCPU_R3(k1)
-
-       LONG_L  $4, VCPU_R4(k1)
-       LONG_L  $5, VCPU_R5(k1)
-       LONG_L  $6, VCPU_R6(k1)
-       LONG_L  $7, VCPU_R7(k1)
-
-       LONG_L  $8, VCPU_R8(k1)
-       LONG_L  $9, VCPU_R9(k1)
-       LONG_L  $10, VCPU_R10(k1)
-       LONG_L  $11, VCPU_R11(k1)
-       LONG_L  $12, VCPU_R12(k1)
-       LONG_L  $13, VCPU_R13(k1)
-       LONG_L  $14, VCPU_R14(k1)
-       LONG_L  $15, VCPU_R15(k1)
-       LONG_L  $16, VCPU_R16(k1)
-       LONG_L  $17, VCPU_R17(k1)
-       LONG_L  $18, VCPU_R18(k1)
-       LONG_L  $19, VCPU_R19(k1)
-       LONG_L  $20, VCPU_R20(k1)
-       LONG_L  $21, VCPU_R21(k1)
-       LONG_L  $22, VCPU_R22(k1)
-       LONG_L  $23, VCPU_R23(k1)
-       LONG_L  $24, VCPU_R24(k1)
-       LONG_L  $25, VCPU_R25(k1)
-
-       /* k0/k1 loaded up later */
-
-       LONG_L  $28, VCPU_R28(k1)
-       LONG_L  $29, VCPU_R29(k1)
-       LONG_L  $30, VCPU_R30(k1)
-       LONG_L  $31, VCPU_R31(k1)
-
-       /* Restore hi/lo */
-       LONG_L  k0, VCPU_LO(k1)
-       mtlo    k0
-
-       LONG_L  k0, VCPU_HI(k1)
-       mthi    k0
-
-FEXPORT(__kvm_mips_load_k0k1)
-       /* Restore the guest's k0/k1 registers */
-       LONG_L  k0, VCPU_R26(k1)
-       LONG_L  k1, VCPU_R27(k1)
-
-       /* Jump to guest */
-       eret
-EXPORT(__kvm_mips_vcpu_run_end)
-
-VECTOR(MIPSX(exception), unknown)
-/* Find out what mode we came from and jump to the proper handler. */
-       mtc0    k0, CP0_ERROREPC        #01: Save guest k0
-       ehb                             #02:
-
-       mfc0    k0, CP0_EBASE           #02: Get EBASE
-       INT_SRL k0, k0, 10              #03: Get rid of CPUNum
-       INT_SLL k0, k0, 10              #04
-       LONG_S  k1, 0x3000(k0)          #05: Save k1 @ offset 0x3000
-       INT_ADDIU k0, k0, 0x2000        #06: Exception handler is
-                                       #    installed @ offset 0x2000
-       j       k0                      #07: jump to the function
-        nop                            #08: branch delay slot
-VECTOR_END(MIPSX(exceptionEnd))
-.end MIPSX(exception)
-
-/*
- * Generic Guest exception handler. We end up here when the guest
- * does something that causes a trap to kernel mode.
- */
-NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
-       /* Get the VCPU pointer from DDTATA_LO */
-       mfc0    k1, CP0_DDATA_LO
-       INT_ADDIU k1, k1, VCPU_HOST_ARCH
-
-       /* Start saving Guest context to VCPU */
-       LONG_S  $0, VCPU_R0(k1)
-       LONG_S  $1, VCPU_R1(k1)
-       LONG_S  $2, VCPU_R2(k1)
-       LONG_S  $3, VCPU_R3(k1)
-       LONG_S  $4, VCPU_R4(k1)
-       LONG_S  $5, VCPU_R5(k1)
-       LONG_S  $6, VCPU_R6(k1)
-       LONG_S  $7, VCPU_R7(k1)
-       LONG_S  $8, VCPU_R8(k1)
-       LONG_S  $9, VCPU_R9(k1)
-       LONG_S  $10, VCPU_R10(k1)
-       LONG_S  $11, VCPU_R11(k1)
-       LONG_S  $12, VCPU_R12(k1)
-       LONG_S  $13, VCPU_R13(k1)
-       LONG_S  $14, VCPU_R14(k1)
-       LONG_S  $15, VCPU_R15(k1)
-       LONG_S  $16, VCPU_R16(k1)
-       LONG_S  $17, VCPU_R17(k1)
-       LONG_S  $18, VCPU_R18(k1)
-       LONG_S  $19, VCPU_R19(k1)
-       LONG_S  $20, VCPU_R20(k1)
-       LONG_S  $21, VCPU_R21(k1)
-       LONG_S  $22, VCPU_R22(k1)
-       LONG_S  $23, VCPU_R23(k1)
-       LONG_S  $24, VCPU_R24(k1)
-       LONG_S  $25, VCPU_R25(k1)
-
-       /* Guest k0/k1 saved later */
-
-       LONG_S  $28, VCPU_R28(k1)
-       LONG_S  $29, VCPU_R29(k1)
-       LONG_S  $30, VCPU_R30(k1)
-       LONG_S  $31, VCPU_R31(k1)
-
-       .set at
-
-       /* We need to save hi/lo and restore them on the way out */
-       mfhi    t0
-       LONG_S  t0, VCPU_HI(k1)
-
-       mflo    t0
-       LONG_S  t0, VCPU_LO(k1)
-
-       /* Finally save guest k0/k1 to VCPU */
-       mfc0    t0, CP0_ERROREPC
-       LONG_S  t0, VCPU_R26(k1)
-
-       /* Get GUEST k1 and save it in VCPU */
-       PTR_LI  t1, ~0x2ff
-       mfc0    t0, CP0_EBASE
-       and     t0, t0, t1
-       LONG_L  t0, 0x3000(t0)
-       LONG_S  t0, VCPU_R27(k1)
-
-       /* Now that context has been saved, we can use other registers */
-
-       /* Restore vcpu */
-       mfc0    a1, CP0_DDATA_LO
-       move    s1, a1
-
-       /* Restore run (vcpu->run) */
-       LONG_L  a0, VCPU_RUN(a1)
-       /* Save pointer to run in s0, will be saved by the compiler */
-       move    s0, a0
-
-       /*
-        * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
-        * process the exception
-        */
-       mfc0    k0,CP0_EPC
-       LONG_S  k0, VCPU_PC(k1)
-
-       mfc0    k0, CP0_BADVADDR
-       LONG_S  k0, VCPU_HOST_CP0_BADVADDR(k1)
-
-       mfc0    k0, CP0_CAUSE
-       sw      k0, VCPU_HOST_CP0_CAUSE(k1)
-
-       /* Now restore the host state just enough to run the handlers */
-
-       /* Switch EBASE to the one used by Linux */
-       /* load up the host EBASE */
-       mfc0    v0, CP0_STATUS
-
-       or      k0, v0, ST0_BEV
-
-       mtc0    k0, CP0_STATUS
-       ehb
-
-       LONG_L  k0, ebase
-       mtc0    k0,CP0_EBASE
-
-       /*
-        * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
-        * trigger FPE for pending exceptions.
-        */
-       and     v1, v0, ST0_CU1
-       beqz    v1, 1f
-        nop
-       .set    push
-       SET_HARDFLOAT
-       cfc1    t0, fcr31
-       sw      t0, VCPU_FCR31(k1)
-       ctc1    zero,fcr31
-       .set    pop
-1:
-
-#ifdef CONFIG_CPU_HAS_MSA
-       /*
-        * If MSA is enabled, save MSACSR and clear it so that later
-        * instructions don't trigger MSAFPE for pending exceptions.
-        */
-       mfc0    t0, CP0_CONFIG3
-       ext     t0, t0, 28, 1 /* MIPS_CONF3_MSAP */
-       beqz    t0, 1f
-        nop
-       mfc0    t0, CP0_CONFIG5
-       ext     t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */
-       beqz    t0, 1f
-        nop
-       _cfcmsa t0, MSA_CSR
-       sw      t0, VCPU_MSA_CSR(k1)
-       _ctcmsa MSA_CSR, zero
-1:
-#endif
-
-       /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
-       and     v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
-       or      v0, v0, ST0_CU0
-       mtc0    v0, CP0_STATUS
-       ehb
-
-       /* Load up host GP */
-       LONG_L  gp, VCPU_HOST_GP(k1)
-
-       /* Need a stack before we can jump to "C" */
-       LONG_L  sp, VCPU_HOST_STACK(k1)
-
-       /* Saved host state */
-       INT_ADDIU sp, sp, -PT_SIZE
-
-       /*
-        * XXXKYMA do we need to load the host ASID, maybe not because the
-        * kernel entries are marked GLOBAL, need to verify
-        */
-
-       /* Restore host DDATA_LO */
-       LONG_L  k0, PT_HOST_USERLOCAL(sp)
-       mtc0    k0, CP0_DDATA_LO
-
-       /* Restore RDHWR access */
-       INT_L   k0, hwrena
-       mtc0    k0, CP0_HWRENA
-
-       /* Jump to handler */
-FEXPORT(__kvm_mips_jump_to_handler)
-       /*
-        * XXXKYMA: not sure if this is safe, how large is the stack??
-        * Now jump to the kvm_mips_handle_exit() to see if we can deal
-        * with this in the kernel
-        */
-       PTR_LA  t9, kvm_mips_handle_exit
-       jalr.hb t9
-        INT_ADDIU sp, sp, -CALLFRAME_SIZ           /* BD Slot */
-
-       /* Return from handler Make sure interrupts are disabled */
-       di
-       ehb
-
-       /*
-        * XXXKYMA: k0/k1 could have been blown away if we processed
-        * an exception while we were handling the exception from the
-        * guest, reload k1
-        */
-
-       move    k1, s1
-       INT_ADDIU k1, k1, VCPU_HOST_ARCH
-
-       /*
-        * Check return value, should tell us if we are returning to the
-        * host (handle I/O etc)or resuming the guest
-        */
-       andi    t0, v0, RESUME_HOST
-       bnez    t0, __kvm_mips_return_to_host
-        nop
-
-__kvm_mips_return_to_guest:
-       /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */
-       mtc0    s1, CP0_DDATA_LO
-
-       /* Load up the Guest EBASE to minimize the window where BEV is set */
-       LONG_L  t0, VCPU_GUEST_EBASE(k1)
-
-       /* Switch EBASE back to the one used by KVM */
-       mfc0    v1, CP0_STATUS
-       or      k0, v1, ST0_BEV
-       mtc0    k0, CP0_STATUS
-       ehb
-       mtc0    t0, CP0_EBASE
-
-       /* Setup status register for running guest in UM */
-       or      v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
-       and     v1, v1, ~(ST0_CU0 | ST0_MX)
-       mtc0    v1, CP0_STATUS
-       ehb
-
-       /* Set Guest EPC */
-       LONG_L  t0, VCPU_PC(k1)
-       mtc0    t0, CP0_EPC
-
-       /* Set the ASID for the Guest Kernel */
-       PTR_L   t0, VCPU_COP0(k1)
-       LONG_L  t0, COP0_STATUS(t0)
-       andi    t0, KSU_USER | ST0_ERL | ST0_EXL
-       xori    t0, KSU_USER
-       bnez    t0, 1f          /* If kernel */
-        INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
-       INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
-1:
-       /* t1: contains the base of the ASID array, need to get the cpu id  */
-       LONG_L  t2, TI_CPU($28)         /* smp_processor_id */
-       INT_SLL t2, t2, 2               /* x4 */
-       REG_ADDU t3, t1, t2
-       LONG_L  k0, (t3)
-#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
-       li      t3, CPUINFO_SIZE/4
-       mul     t2, t2, t3              /* x sizeof(struct cpuinfo_mips)/4 */
-       LONG_L  t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
-       and     k0, k0, t2
-#else
-       andi    k0, k0, MIPS_ENTRYHI_ASID
-#endif
-       mtc0    k0, CP0_ENTRYHI
-       ehb
-
-       /* Disable RDHWR access */
-       mtc0    zero, CP0_HWRENA
-
-       .set    noat
-       /* load the guest context from VCPU and return */
-       LONG_L  $0, VCPU_R0(k1)
-       LONG_L  $1, VCPU_R1(k1)
-       LONG_L  $2, VCPU_R2(k1)
-       LONG_L  $3, VCPU_R3(k1)
-       LONG_L  $4, VCPU_R4(k1)
-       LONG_L  $5, VCPU_R5(k1)
-       LONG_L  $6, VCPU_R6(k1)
-       LONG_L  $7, VCPU_R7(k1)
-       LONG_L  $8, VCPU_R8(k1)
-       LONG_L  $9, VCPU_R9(k1)
-       LONG_L  $10, VCPU_R10(k1)
-       LONG_L  $11, VCPU_R11(k1)
-       LONG_L  $12, VCPU_R12(k1)
-       LONG_L  $13, VCPU_R13(k1)
-       LONG_L  $14, VCPU_R14(k1)
-       LONG_L  $15, VCPU_R15(k1)
-       LONG_L  $16, VCPU_R16(k1)
-       LONG_L  $17, VCPU_R17(k1)
-       LONG_L  $18, VCPU_R18(k1)
-       LONG_L  $19, VCPU_R19(k1)
-       LONG_L  $20, VCPU_R20(k1)
-       LONG_L  $21, VCPU_R21(k1)
-       LONG_L  $22, VCPU_R22(k1)
-       LONG_L  $23, VCPU_R23(k1)
-       LONG_L  $24, VCPU_R24(k1)
-       LONG_L  $25, VCPU_R25(k1)
-
-       /* $/k1 loaded later */
-       LONG_L  $28, VCPU_R28(k1)
-       LONG_L  $29, VCPU_R29(k1)
-       LONG_L  $30, VCPU_R30(k1)
-       LONG_L  $31, VCPU_R31(k1)
-
-FEXPORT(__kvm_mips_skip_guest_restore)
-       LONG_L  k0, VCPU_HI(k1)
-       mthi    k0
-
-       LONG_L  k0, VCPU_LO(k1)
-       mtlo    k0
-
-       LONG_L  k0, VCPU_R26(k1)
-       LONG_L  k1, VCPU_R27(k1)
-
-       eret
-       .set    at
-
-__kvm_mips_return_to_host:
-       /* EBASE is already pointing to Linux */
-       LONG_L  k1, VCPU_HOST_STACK(k1)
-       INT_ADDIU k1,k1, -PT_SIZE
-
-       /* Restore host DDATA_LO */
-       LONG_L  k0, PT_HOST_USERLOCAL(k1)
-       mtc0    k0, CP0_DDATA_LO
-
-       /*
-        * r2/v0 is the return code, shift it down by 2 (arithmetic)
-        * to recover the err code
-        */
-       INT_SRA k0, v0, 2
-       move    $2, k0
-
-       /* Load context saved on the host stack */
-       LONG_L  $16, PT_R16(k1)
-       LONG_L  $17, PT_R17(k1)
-       LONG_L  $18, PT_R18(k1)
-       LONG_L  $19, PT_R19(k1)
-       LONG_L  $20, PT_R20(k1)
-       LONG_L  $21, PT_R21(k1)
-       LONG_L  $22, PT_R22(k1)
-       LONG_L  $23, PT_R23(k1)
-
-       LONG_L  $28, PT_R28(k1)
-       LONG_L  $29, PT_R29(k1)
-       LONG_L  $30, PT_R30(k1)
-
-       LONG_L  k0, PT_HI(k1)
-       mthi    k0
-
-       LONG_L  k0, PT_LO(k1)
-       mtlo    k0
-
-       /* Restore RDHWR access */
-       INT_L   k0, hwrena
-       mtc0    k0, CP0_HWRENA
-
-       /* Restore RA, which is the address we will return to */
-       LONG_L  ra, PT_R31(k1)
-       j       ra
-        nop
-
-VECTOR_END(MIPSX(GuestExceptionEnd))
-.end MIPSX(GuestException)
-
-MIPSX(exceptions):
-       ####
-       ##### The exception handlers.
-       #####
-       .word _C_LABEL(MIPSX(GuestException))   #  0
-       .word _C_LABEL(MIPSX(GuestException))   #  1
-       .word _C_LABEL(MIPSX(GuestException))   #  2
-       .word _C_LABEL(MIPSX(GuestException))   #  3
-       .word _C_LABEL(MIPSX(GuestException))   #  4
-       .word _C_LABEL(MIPSX(GuestException))   #  5
-       .word _C_LABEL(MIPSX(GuestException))   #  6
-       .word _C_LABEL(MIPSX(GuestException))   #  7
-       .word _C_LABEL(MIPSX(GuestException))   #  8
-       .word _C_LABEL(MIPSX(GuestException))   #  9
-       .word _C_LABEL(MIPSX(GuestException))   # 10
-       .word _C_LABEL(MIPSX(GuestException))   # 11
-       .word _C_LABEL(MIPSX(GuestException))   # 12
-       .word _C_LABEL(MIPSX(GuestException))   # 13
-       .word _C_LABEL(MIPSX(GuestException))   # 14
-       .word _C_LABEL(MIPSX(GuestException))   # 15
-       .word _C_LABEL(MIPSX(GuestException))   # 16
-       .word _C_LABEL(MIPSX(GuestException))   # 17
-       .word _C_LABEL(MIPSX(GuestException))   # 18
-       .word _C_LABEL(MIPSX(GuestException))   # 19
-       .word _C_LABEL(MIPSX(GuestException))   # 20
-       .word _C_LABEL(MIPSX(GuestException))   # 21
-       .word _C_LABEL(MIPSX(GuestException))   # 22
-       .word _C_LABEL(MIPSX(GuestException))   # 23
-       .word _C_LABEL(MIPSX(GuestException))   # 24
-       .word _C_LABEL(MIPSX(GuestException))   # 25
-       .word _C_LABEL(MIPSX(GuestException))   # 26
-       .word _C_LABEL(MIPSX(GuestException))   # 27
-       .word _C_LABEL(MIPSX(GuestException))   # 28
-       .word _C_LABEL(MIPSX(GuestException))   # 29
-       .word _C_LABEL(MIPSX(GuestException))   # 30
-       .word _C_LABEL(MIPSX(GuestException))   # 31