]> git.proxmox.com Git - qemu.git/blobdiff - target-mips/translate.c
target-mips: allow microMIPS SWP and SDP to have RD equal to BASE
[qemu.git] / target-mips / translate.c
index d43d72deea1f3a942debdcc0b2a8c1242129784b..b29341953622c0464d7f8043ce52db64ba02c972 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
 #include "cpu.h"
-#include "exec-all.h"
 #include "disas.h"
 #include "tcg-op.h"
-#include "qemu-common.h"
 
 #include "helper.h"
 #define GEN_HELPER 1
@@ -267,6 +259,19 @@ enum {
     OPC_MUL      = 0x02 | OPC_SPECIAL2,
     OPC_MSUB     = 0x04 | OPC_SPECIAL2,
     OPC_MSUBU    = 0x05 | OPC_SPECIAL2,
+    /* Loongson 2F */
+    OPC_MULT_G_2F   = 0x10 | OPC_SPECIAL2,
+    OPC_DMULT_G_2F  = 0x11 | OPC_SPECIAL2,
+    OPC_MULTU_G_2F  = 0x12 | OPC_SPECIAL2,
+    OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
+    OPC_DIV_G_2F    = 0x14 | OPC_SPECIAL2,
+    OPC_DDIV_G_2F   = 0x15 | OPC_SPECIAL2,
+    OPC_DIVU_G_2F   = 0x16 | OPC_SPECIAL2,
+    OPC_DDIVU_G_2F  = 0x17 | OPC_SPECIAL2,
+    OPC_MOD_G_2F    = 0x1c | OPC_SPECIAL2,
+    OPC_DMOD_G_2F   = 0x1d | OPC_SPECIAL2,
+    OPC_MODU_G_2F   = 0x1e | OPC_SPECIAL2,
+    OPC_DMODU_G_2F  = 0x1f | OPC_SPECIAL2,
     /* Misc */
     OPC_CLZ      = 0x20 | OPC_SPECIAL2,
     OPC_CLO      = 0x21 | OPC_SPECIAL2,
@@ -293,6 +298,20 @@ enum {
     OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
     OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
     OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
+
+    /* Loongson 2E */
+    OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
+    OPC_MULTU_G_2E  = 0x19 | OPC_SPECIAL3,
+    OPC_DIV_G_2E    = 0x1A | OPC_SPECIAL3,
+    OPC_DIVU_G_2E   = 0x1B | OPC_SPECIAL3,
+    OPC_DMULT_G_2E  = 0x1C | OPC_SPECIAL3,
+    OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
+    OPC_DDIV_G_2E   = 0x1E | OPC_SPECIAL3,
+    OPC_DDIVU_G_2E  = 0x1F | OPC_SPECIAL3,
+    OPC_MOD_G_2E    = 0x22 | OPC_SPECIAL3,
+    OPC_MODU_G_2E   = 0x23 | OPC_SPECIAL3,
+    OPC_DMOD_G_2E   = 0x26 | OPC_SPECIAL3,
+    OPC_DMODU_G_2E  = 0x27 | OPC_SPECIAL3,
 };
 
 /* BSHFL opcodes */
@@ -583,7 +602,7 @@ static inline void gen_load_srsgpr (int from, int to)
         TCGv_i32 t2 = tcg_temp_new_i32();
         TCGv_ptr addr = tcg_temp_new_ptr();
 
-        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
+        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
         tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
         tcg_gen_andi_i32(t2, t2, 0xf);
         tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
@@ -606,7 +625,7 @@ static inline void gen_store_srsgpr (int from, int to)
         TCGv_ptr addr = tcg_temp_new_ptr();
 
         gen_load_gpr(t0, from);
-        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
+        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
         tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
         tcg_gen_andi_i32(t2, t2, 0xf);
         tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
@@ -623,28 +642,28 @@ static inline void gen_store_srsgpr (int from, int to)
 /* Floating point register moves. */
 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
 {
-    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
+    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
 }
 
 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
 {
-    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
 }
 
 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
 {
-    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
+    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
 }
 
 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
 {
-    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
 }
 
 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
 {
     if (ctx->hflags & MIPS_HFLAG_F64) {
-        tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
+        tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
     } else {
         TCGv_i32 t0 = tcg_temp_new_i32();
         TCGv_i32 t1 = tcg_temp_new_i32();
@@ -659,7 +678,7 @@ static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
 {
     if (ctx->hflags & MIPS_HFLAG_F64) {
-        tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
+        tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
     } else {
         TCGv_i64 t0 = tcg_temp_new_i64();
         TCGv_i32 t1 = tcg_temp_new_i32();
@@ -709,7 +728,7 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
     }
 }
 
-static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
+static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
 {
     ctx->saved_hflags = ctx->hflags;
     switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
@@ -807,7 +826,7 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
 
 /* This code generates a "reserved instruction" exception if the
    CPU does not support the instruction set corresponding to flags. */
-static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
+static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
 {
     if (unlikely(!(env->insn_flags & flags)))
         generate_exception(ctx, EXCP_RI);
@@ -886,7 +905,7 @@ FOP_CONDS(abs, 1, ps, FMT_PS, 64)
 
 /* load/store instructions. */
 #define OP_LD(insn,fname)                                                 \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)   \
 {                                                                         \
     tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx);                        \
 }
@@ -902,7 +921,7 @@ OP_LD(ld,ld64);
 #undef OP_LD
 
 #define OP_ST(insn,fname)                                                  \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
+static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx)   \
 {                                                                          \
     tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx);                        \
 }
@@ -916,18 +935,18 @@ OP_ST(sd,st64);
 
 #ifdef CONFIG_USER_ONLY
 #define OP_LD_ATOMIC(insn,fname)                                           \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)  \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)    \
 {                                                                          \
     TCGv t0 = tcg_temp_new();                                              \
     tcg_gen_mov_tl(t0, arg1);                                              \
     tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx);                         \
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr));                \
-    tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval));                \
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr));                \
+    tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval));                \
     tcg_temp_free(t0);                                                     \
 }
 #else
 #define OP_LD_ATOMIC(insn,fname)                                           \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)  \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)    \
 {                                                                          \
     gen_helper_2i(insn, ret, arg1, ctx->mem_idx);                          \
 }
@@ -940,7 +959,7 @@ OP_LD_ATOMIC(lld,ld64);
 
 #ifdef CONFIG_USER_ONLY
 #define OP_ST_ATOMIC(insn,fname,ldname,almask)                               \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
+static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
 {                                                                            \
     TCGv t0 = tcg_temp_new();                                                \
     int l1 = gen_new_label();                                                \
@@ -948,14 +967,14 @@ static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ct
                                                                              \
     tcg_gen_andi_tl(t0, arg2, almask);                                       \
     tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);                              \
-    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr));          \
+    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));          \
     generate_exception(ctx, EXCP_AdES);                                      \
     gen_set_label(l1);                                                       \
-    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr));                  \
+    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr));                  \
     tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2);                            \
     tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20));                        \
-    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg));                   \
-    tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval));              \
+    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg));                   \
+    tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval));              \
     gen_helper_0i(raise_exception, EXCP_SC);                                 \
     gen_set_label(l2);                                                       \
     tcg_gen_movi_tl(t0, 0);                                                  \
@@ -964,7 +983,7 @@ static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ct
 }
 #else
 #define OP_ST_ATOMIC(insn,fname,ldname,almask)                               \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
+static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
 {                                                                            \
     TCGv t0 = tcg_temp_new();                                                \
     gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx);                       \
@@ -1005,43 +1024,45 @@ static target_ulong pc_relative_pc (DisasContext *ctx)
     return pc;
 }
 
-/* Load and store */
-static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
-                      int base, int16_t offset)
+/* Load */
+static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+                    int rt, int base, int16_t offset)
 {
-    const char *opn = "ldst";
-    TCGv t0 = tcg_temp_new();
-    TCGv t1 = tcg_temp_new();
+    const char *opn = "ld";
+    TCGv t0, t1;
+
+    if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
+        /* Loongson CPU uses a load to zero register for prefetch.
+           We emulate it as a NOP. On other CPU we must perform the
+           actual memory access. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
 
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
     gen_base_offset_addr(ctx, t0, base, offset);
-    /* Don't do NOP if destination is zero: we must perform the actual
-       memory access. */
+
     switch (opc) {
 #if defined(TARGET_MIPS64)
     case OPC_LWU:
         save_cpu_state(ctx, 0);
-        op_ldst_lwu(t0, t0, ctx);
+        op_ld_lwu(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lwu";
         break;
     case OPC_LD:
         save_cpu_state(ctx, 0);
-        op_ldst_ld(t0, t0, ctx);
+        op_ld_ld(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "ld";
         break;
     case OPC_LLD:
-        save_cpu_state(ctx, 0);
-        op_ldst_lld(t0, t0, ctx);
+        save_cpu_state(ctx, 1);
+        op_ld_lld(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lld";
         break;
-    case OPC_SD:
-        save_cpu_state(ctx, 0);
-        gen_load_gpr(t1, rt);
-        op_ldst_sd(t1, t0, ctx);
-        opn = "sd";
-        break;
     case OPC_LDL:
         save_cpu_state(ctx, 1);
         gen_load_gpr(t1, rt);
@@ -1049,12 +1070,6 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
         gen_store_gpr(t1, rt);
         opn = "ldl";
         break;
-    case OPC_SDL:
-        save_cpu_state(ctx, 1);
-        gen_load_gpr(t1, rt);
-        gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
-        opn = "sdl";
-        break;
     case OPC_LDR:
         save_cpu_state(ctx, 1);
         gen_load_gpr(t1, rt);
@@ -1062,72 +1077,50 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
         gen_store_gpr(t1, rt);
         opn = "ldr";
         break;
-    case OPC_SDR:
-        save_cpu_state(ctx, 1);
-        gen_load_gpr(t1, rt);
-        gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
-        opn = "sdr";
-        break;
     case OPC_LDPC:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
         gen_op_addr_add(ctx, t0, t0, t1);
-        op_ldst_ld(t0, t0, ctx);
+        op_ld_ld(t0, t0, ctx);
         gen_store_gpr(t0, rt);
+        opn = "ldpc";
         break;
 #endif
     case OPC_LWPC:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
         gen_op_addr_add(ctx, t0, t0, t1);
-        op_ldst_lw(t0, t0, ctx);
+        op_ld_lw(t0, t0, ctx);
         gen_store_gpr(t0, rt);
+        opn = "lwpc";
         break;
     case OPC_LW:
         save_cpu_state(ctx, 0);
-        op_ldst_lw(t0, t0, ctx);
+        op_ld_lw(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lw";
         break;
-    case OPC_SW:
-        save_cpu_state(ctx, 0);
-        gen_load_gpr(t1, rt);
-        op_ldst_sw(t1, t0, ctx);
-        opn = "sw";
-        break;
     case OPC_LH:
         save_cpu_state(ctx, 0);
-        op_ldst_lh(t0, t0, ctx);
+        op_ld_lh(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lh";
         break;
-    case OPC_SH:
-        save_cpu_state(ctx, 0);
-        gen_load_gpr(t1, rt);
-        op_ldst_sh(t1, t0, ctx);
-        opn = "sh";
-        break;
     case OPC_LHU:
         save_cpu_state(ctx, 0);
-        op_ldst_lhu(t0, t0, ctx);
+        op_ld_lhu(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lhu";
         break;
     case OPC_LB:
         save_cpu_state(ctx, 0);
-        op_ldst_lb(t0, t0, ctx);
+        op_ld_lb(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lb";
         break;
-    case OPC_SB:
-        save_cpu_state(ctx, 0);
-        gen_load_gpr(t1, rt);
-        op_ldst_sb(t1, t0, ctx);
-        opn = "sb";
-        break;
     case OPC_LBU:
         save_cpu_state(ctx, 0);
-        op_ldst_lbu(t0, t0, ctx);
+        op_ld_lbu(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lbu";
         break;
@@ -1138,12 +1131,6 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
         gen_store_gpr(t1, rt);
         opn = "lwl";
         break;
-    case OPC_SWL:
-        save_cpu_state(ctx, 1);
-        gen_load_gpr(t1, rt);
-        gen_helper_2i(swl, t1, t0, ctx->mem_idx);
-        opn = "swr";
-        break;
     case OPC_LWR:
         save_cpu_state(ctx, 1);
         gen_load_gpr(t1, rt);
@@ -1151,24 +1138,80 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
         gen_store_gpr(t1, rt);
         opn = "lwr";
         break;
-    case OPC_SWR:
-        save_cpu_state(ctx, 1);
-        gen_load_gpr(t1, rt);
-        gen_helper_2i(swr, t1, t0, ctx->mem_idx);
-        opn = "swr";
-        break;
     case OPC_LL:
         save_cpu_state(ctx, 1);
-        op_ldst_ll(t0, t0, ctx);
+        op_ld_ll(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "ll";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
     tcg_temp_free(t0);
     tcg_temp_free(t1);
 }
 
+/* Store */
+static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
+                    int base, int16_t offset)
+{
+    const char *opn = "st";
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+
+    gen_base_offset_addr(ctx, t0, base, offset);
+    gen_load_gpr(t1, rt);
+    switch (opc) {
+#if defined(TARGET_MIPS64)
+    case OPC_SD:
+        save_cpu_state(ctx, 0);
+        op_st_sd(t1, t0, ctx);
+        opn = "sd";
+        break;
+    case OPC_SDL:
+        save_cpu_state(ctx, 1);
+        gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
+        opn = "sdl";
+        break;
+    case OPC_SDR:
+        save_cpu_state(ctx, 1);
+        gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
+        opn = "sdr";
+        break;
+#endif
+    case OPC_SW:
+        save_cpu_state(ctx, 0);
+        op_st_sw(t1, t0, ctx);
+        opn = "sw";
+        break;
+    case OPC_SH:
+        save_cpu_state(ctx, 0);
+        op_st_sh(t1, t0, ctx);
+        opn = "sh";
+        break;
+    case OPC_SB:
+        save_cpu_state(ctx, 0);
+        op_st_sb(t1, t0, ctx);
+        opn = "sb";
+        break;
+    case OPC_SWL:
+        save_cpu_state(ctx, 1);
+        gen_helper_2i(swl, t1, t0, ctx->mem_idx);
+        opn = "swl";
+        break;
+    case OPC_SWR:
+        save_cpu_state(ctx, 1);
+        gen_helper_2i(swr, t1, t0, ctx->mem_idx);
+        opn = "swr";
+        break;
+    }
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+
 /* Store conditional */
 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
                          int base, int16_t offset)
@@ -1187,17 +1230,18 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
     switch (opc) {
 #if defined(TARGET_MIPS64)
     case OPC_SCD:
-        save_cpu_state(ctx, 0);
-        op_ldst_scd(t1, t0, rt, ctx);
+        save_cpu_state(ctx, 1);
+        op_st_scd(t1, t0, rt, ctx);
         opn = "scd";
         break;
 #endif
     case OPC_SC:
         save_cpu_state(ctx, 1);
-        op_ldst_sc(t1, t0, rt, ctx);
+        op_st_sc(t1, t0, rt, ctx);
         opn = "sc";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
     tcg_temp_free(t1);
     tcg_temp_free(t0);
@@ -1263,12 +1307,13 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
         generate_exception(ctx, EXCP_RI);
         goto out;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
  out:
     tcg_temp_free(t0);
 }
 
-static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
+static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
                           uint32_t op, int rt, int rs, int16_t imm)
 {
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
@@ -1280,7 +1325,7 @@ static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
 }
 
 /* Arithmetic with immediate operand */
-static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                            int rt, int rs, int16_t imm)
 {
     target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
@@ -1363,11 +1408,12 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
         break;
 #endif
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
 }
 
 /* Logic with immediate operand */
-static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
 {
     target_ulong uimm;
     const char *opn = "imm logic";
@@ -1405,11 +1451,12 @@ static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t
         opn = "lui";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
 }
 
 /* Set on less than with immediate operand */
-static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
 {
     target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
     const char *opn = "imm arith";
@@ -1432,12 +1479,13 @@ static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t im
         opn = "sltiu";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
     tcg_temp_free(t0);
 }
 
 /* Shifts with immediate operand */
-static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm = ((uint16_t)imm) & 0x1f;
@@ -1523,12 +1571,13 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
         break;
 #endif
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
     tcg_temp_free(t0);
 }
 
 /* Arithmetic */
-static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                        int rd, int rs, int rt)
 {
     const char *opn = "arith";
@@ -1703,11 +1752,12 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
         opn = "mul";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
 }
 
 /* Conditional move */
-static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
 {
     const char *opn = "cond move";
     int l1;
@@ -1740,11 +1790,12 @@ static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
         tcg_gen_movi_tl(cpu_gpr[rd], 0);
     gen_set_label(l1);
 
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
 }
 
 /* Logic */
-static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
 {
     const char *opn = "logic";
 
@@ -1800,11 +1851,12 @@ static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
         opn = "xor";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
 }
 
 /* Set on lower than */
-static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
 {
     const char *opn = "slt";
     TCGv t0, t1;
@@ -1829,13 +1881,14 @@ static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
         opn = "sltu";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
     tcg_temp_free(t0);
     tcg_temp_free(t1);
 }
 
 /* Shifts */
-static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
                        int rd, int rs, int rt)
 {
     const char *opn = "shifts";
@@ -1909,6 +1962,7 @@ static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
         break;
 #endif
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
     tcg_temp_free(t0);
     tcg_temp_free(t1);
@@ -1948,6 +2002,7 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
         opn = "mtlo";
         break;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s", opn, regnames[reg]);
 }
 
@@ -2180,6 +2235,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         generate_exception(ctx, EXCP_RI);
         goto out;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
  out:
     tcg_temp_free(t0);
@@ -2259,6 +2315,7 @@ static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
         goto out;
     }
     gen_store_gpr(t0, rd);
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
 
  out:
@@ -2299,8 +2356,224 @@ static void gen_cl (DisasContext *ctx, uint32_t opc,
         break;
 #endif
     }
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
+    tcg_temp_free(t0);
+}
+
+/* Godson integer instructions */
+static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
+                                int rd, int rs, int rt)
+{
+    const char *opn = "loongson";
+    TCGv t0, t1;
+
+    if (rd == 0) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (opc) {
+    case OPC_MULT_G_2E:
+    case OPC_MULT_G_2F:
+    case OPC_MULTU_G_2E:
+    case OPC_MULTU_G_2F:
+#if defined(TARGET_MIPS64)
+    case OPC_DMULT_G_2E:
+    case OPC_DMULT_G_2F:
+    case OPC_DMULTU_G_2E:
+    case OPC_DMULTU_G_2F:
+#endif
+        t0 = tcg_temp_new();
+        t1 = tcg_temp_new();
+        break;
+    default:
+        t0 = tcg_temp_local_new();
+        t1 = tcg_temp_local_new();
+        break;
+    }
+
+    gen_load_gpr(t0, rs);
+    gen_load_gpr(t1, rt);
+
+    switch (opc) {
+    case OPC_MULT_G_2E:
+    case OPC_MULT_G_2F:
+        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+        tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+        opn = "mult.g";
+        break;
+    case OPC_MULTU_G_2E:
+    case OPC_MULTU_G_2F:
+        tcg_gen_ext32u_tl(t0, t0);
+        tcg_gen_ext32u_tl(t1, t1);
+        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+        tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+        opn = "multu.g";
+        break;
+    case OPC_DIV_G_2E:
+    case OPC_DIV_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            int l3 = gen_new_label();
+            tcg_gen_ext32s_tl(t0, t0);
+            tcg_gen_ext32s_tl(t1, t1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l3);
+            gen_set_label(l1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
+            tcg_gen_mov_tl(cpu_gpr[rd], t0);
+            tcg_gen_br(l3);
+            gen_set_label(l2);
+            tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+            gen_set_label(l3);
+        }
+        opn = "div.g";
+        break;
+    case OPC_DIVU_G_2E:
+    case OPC_DIVU_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            tcg_gen_ext32u_tl(t0, t0);
+            tcg_gen_ext32u_tl(t1, t1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l2);
+            gen_set_label(l1);
+            tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+            gen_set_label(l2);
+        }
+        opn = "divu.g";
+        break;
+    case OPC_MOD_G_2E:
+    case OPC_MOD_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            int l3 = gen_new_label();
+            tcg_gen_ext32u_tl(t0, t0);
+            tcg_gen_ext32u_tl(t1, t1);
+            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
+            gen_set_label(l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l3);
+            gen_set_label(l2);
+            tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+            gen_set_label(l3);
+        }
+        opn = "mod.g";
+        break;
+    case OPC_MODU_G_2E:
+    case OPC_MODU_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            tcg_gen_ext32u_tl(t0, t0);
+            tcg_gen_ext32u_tl(t1, t1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l2);
+            gen_set_label(l1);
+            tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+            gen_set_label(l2);
+        }
+        opn = "modu.g";
+        break;
+#if defined(TARGET_MIPS64)
+    case OPC_DMULT_G_2E:
+    case OPC_DMULT_G_2F:
+        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+        opn = "dmult.g";
+        break;
+    case OPC_DMULTU_G_2E:
+    case OPC_DMULTU_G_2F:
+        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+        opn = "dmultu.g";
+        break;
+    case OPC_DDIV_G_2E:
+    case OPC_DDIV_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            int l3 = gen_new_label();
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l3);
+            gen_set_label(l1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+            tcg_gen_mov_tl(cpu_gpr[rd], t0);
+            tcg_gen_br(l3);
+            gen_set_label(l2);
+            tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+            gen_set_label(l3);
+        }
+        opn = "ddiv.g";
+        break;
+    case OPC_DDIVU_G_2E:
+    case OPC_DDIVU_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l2);
+            gen_set_label(l1);
+            tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+            gen_set_label(l2);
+        }
+        opn = "ddivu.g";
+        break;
+    case OPC_DMOD_G_2E:
+    case OPC_DMOD_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            int l3 = gen_new_label();
+            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+            gen_set_label(l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l3);
+            gen_set_label(l2);
+            tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+            gen_set_label(l3);
+        }
+        opn = "dmod.g";
+        break;
+    case OPC_DMODU_G_2E:
+    case OPC_DMODU_G_2F:
+        {
+            int l1 = gen_new_label();
+            int l2 = gen_new_label();
+            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+            tcg_gen_movi_tl(cpu_gpr[rd], 0);
+            tcg_gen_br(l2);
+            gen_set_label(l1);
+            tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+            gen_set_label(l2);
+        }
+        opn = "dmodu.g";
+        break;
+#endif
+    }
+
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
     tcg_temp_free(t0);
+    tcg_temp_free(t1);
 }
 
 /* Traps */
@@ -2405,7 +2678,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
         likely(!ctx->singlestep_enabled)) {
         tcg_gen_goto_tb(n);
         gen_save_pc(dest);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         gen_save_pc(dest);
         if (ctx->singlestep_enabled) {
@@ -2764,7 +3037,7 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
     case OPC_DINSU:
         if (lsb > msb)
             goto fail;
-        mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
+        mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
         gen_load_gpr(t0, rt);
         tcg_gen_andi_tl(t0, t0, ~mask);
         tcg_gen_shli_tl(t1, t1, lsb + 32);
@@ -2898,7 +3171,7 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
     tcg_gen_st_tl(arg, cpu_env, off);
 }
 
-static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -2909,7 +3182,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 0:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
             rn = "Index";
             break;
         case 1:
@@ -2939,37 +3212,37 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             break;
         case 1:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
+            gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
+            gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
+            gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
         default:
@@ -2979,7 +3252,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 2:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryLo0";
             break;
@@ -3025,7 +3298,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 3:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryLo1";
             break;
@@ -3036,7 +3309,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 4:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "Context";
             break;
@@ -3051,12 +3324,12 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 5:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
             rn = "PageMask";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
             rn = "PageGrain";
             break;
         default:
@@ -3066,32 +3339,32 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 6:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
             rn = "Wired";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
             rn = "SRSConf0";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
             rn = "SRSConf1";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
             rn = "SRSConf2";
             break;
         case 4:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
             rn = "SRSConf3";
             break;
         case 5:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
             rn = "SRSConf4";
             break;
         default:
@@ -3102,7 +3375,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
             rn = "HWREna";
             break;
         default:
@@ -3112,7 +3385,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 8:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "BadVAddr";
             break;
@@ -3129,8 +3402,10 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             gen_helper_mfc0_count(arg);
             if (use_icount) {
                 gen_io_end();
-                ctx->bstate = BS_STOP;
             }
+            /* Break the TB to be able to take timer interrupts immediately
+               after reading count.  */
+            ctx->bstate = BS_STOP;
             rn = "Count";
             break;
         /* 6,7 are implementation dependent */
@@ -3141,7 +3416,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 10:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EntryHi";
             break;
@@ -3152,7 +3427,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 11:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
             rn = "Compare";
             break;
         /* 6,7 are implementation dependent */
@@ -3163,22 +3438,22 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 12:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
             rn = "Status";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
             rn = "IntCtl";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
             rn = "SRSCtl";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             rn = "SRSMap";
             break;
         default:
@@ -3188,7 +3463,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 13:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
             rn = "Cause";
             break;
         default:
@@ -3198,7 +3473,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 14:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "EPC";
             break;
@@ -3209,12 +3484,12 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 15:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
             rn = "PRid";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
             rn = "EBase";
             break;
         default:
@@ -3224,29 +3499,29 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 16:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
             rn = "Config";
             break;
         case 1:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
             rn = "Config1";
             break;
         case 2:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
             rn = "Config2";
             break;
         case 3:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
             rn = "Config3";
             break;
         /* 4,5 are reserved */
         /* 6,7 are implementation dependent */
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
             rn = "Config6";
             break;
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
             rn = "Config7";
             break;
         default:
@@ -3288,7 +3563,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         case 0:
 #if defined(TARGET_MIPS64)
             check_insn(env, ctx, ISA_MIPS3);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "XContext";
             break;
@@ -3301,7 +3576,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
             rn = "Framemask";
             break;
         default:
@@ -3342,7 +3617,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "DEPC";
             break;
@@ -3353,7 +3628,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 25:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
             rn = "Performance0";
             break;
         case 1:
@@ -3408,14 +3683,14 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
             rn = "TagLo";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
             rn = "DataLo";
             break;
         default:
@@ -3428,14 +3703,14 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
             rn = "TagHi";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
             rn = "DataHi";
             break;
         default:
@@ -3445,7 +3720,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 30:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "ErrorEPC";
             break;
@@ -3457,7 +3732,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -3467,6 +3742,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     default:
        goto die;
     }
+    (void)rn; /* avoid a compiler warning */
     LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
     return;
 
@@ -3475,7 +3751,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -3539,12 +3815,12 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
@@ -3748,7 +4024,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSMap";
@@ -3771,7 +4047,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 14:
         switch (sel) {
         case 0:
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
             rn = "EPC";
             break;
         default:
@@ -3931,7 +4207,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
             rn = "DEPC";
             break;
         default:
@@ -4034,7 +4310,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     case 30:
         switch (sel) {
         case 0:
-            gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
+            gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
             rn = "ErrorEPC";
             break;
         default:
@@ -4045,7 +4321,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -4057,6 +4333,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
     default:
        goto die;
     }
+    (void)rn; /* avoid a compiler warning */
     LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
     /* For simplicity assume that all writes can cause interrupts.  */
     if (use_icount) {
@@ -4071,7 +4348,7 @@ die:
 }
 
 #if defined(TARGET_MIPS64)
-static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -4082,7 +4359,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 0:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
             rn = "Index";
             break;
         case 1:
@@ -4112,37 +4389,37 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             break;
         case 1:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
             check_insn(env, ctx, ASE_MT);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
         default:
@@ -4152,7 +4429,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 2:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
             rn = "EntryLo0";
             break;
         case 1:
@@ -4197,7 +4474,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 3:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
             rn = "EntryLo1";
             break;
         default:
@@ -4207,7 +4484,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 4:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
             rn = "Context";
             break;
         case 1:
@@ -4221,12 +4498,12 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 5:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
             rn = "PageMask";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
             rn = "PageGrain";
             break;
         default:
@@ -4236,32 +4513,32 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 6:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
             rn = "Wired";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
             rn = "SRSConf0";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
             rn = "SRSConf1";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
             rn = "SRSConf2";
             break;
         case 4:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
             rn = "SRSConf3";
             break;
         case 5:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
             rn = "SRSConf4";
             break;
         default:
@@ -4272,7 +4549,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
             rn = "HWREna";
             break;
         default:
@@ -4282,7 +4559,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 8:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
             rn = "BadVAddr";
             break;
         default:
@@ -4298,8 +4575,10 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             gen_helper_mfc0_count(arg);
             if (use_icount) {
                 gen_io_end();
-                ctx->bstate = BS_STOP;
             }
+            /* Break the TB to be able to take timer interrupts immediately
+               after reading count.  */
+            ctx->bstate = BS_STOP;
             rn = "Count";
             break;
         /* 6,7 are implementation dependent */
@@ -4310,7 +4589,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 10:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
             rn = "EntryHi";
             break;
         default:
@@ -4320,7 +4599,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 11:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
             rn = "Compare";
             break;
         /* 6,7 are implementation dependent */
@@ -4331,22 +4610,22 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 12:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
             rn = "Status";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
             rn = "IntCtl";
             break;
         case 2:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
             rn = "SRSCtl";
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             rn = "SRSMap";
             break;
         default:
@@ -4356,7 +4635,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 13:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
             rn = "Cause";
             break;
         default:
@@ -4366,7 +4645,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 14:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
             rn = "EPC";
             break;
         default:
@@ -4376,12 +4655,12 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 15:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
             rn = "PRid";
             break;
         case 1:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
             rn = "EBase";
             break;
         default:
@@ -4391,28 +4670,28 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 16:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
             rn = "Config";
             break;
         case 1:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
             rn = "Config1";
             break;
         case 2:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
             rn = "Config2";
             break;
         case 3:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
             rn = "Config3";
             break;
        /* 6,7 are implementation dependent */
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
             rn = "Config6";
             break;
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
             rn = "Config7";
             break;
         default:
@@ -4453,7 +4732,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             check_insn(env, ctx, ISA_MIPS3);
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
             rn = "XContext";
             break;
         default:
@@ -4464,7 +4743,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
             rn = "Framemask";
             break;
         default:
@@ -4505,7 +4784,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
             rn = "DEPC";
             break;
         default:
@@ -4515,7 +4794,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 25:
         switch (sel) {
         case 0:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
             rn = "Performance0";
             break;
         case 1:
@@ -4571,14 +4850,14 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
             rn = "TagLo";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
             rn = "DataLo";
             break;
         default:
@@ -4591,14 +4870,14 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         case 2:
         case 4:
         case 6:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
             rn = "TagHi";
             break;
         case 1:
         case 3:
         case 5:
         case 7:
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
             rn = "DataHi";
             break;
         default:
@@ -4608,7 +4887,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 30:
         switch (sel) {
         case 0:
-            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
             rn = "ErrorEPC";
             break;
         default:
@@ -4619,7 +4898,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -4629,6 +4908,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     default:
         goto die;
     }
+    (void)rn; /* avoid a compiler warning */
     LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
     return;
 
@@ -4637,7 +4917,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
@@ -4701,12 +4981,12 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             break;
         case 5:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
             check_insn(env, ctx, ASE_MT);
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
@@ -4914,7 +5194,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
             break;
         case 3:
             check_insn(env, ctx, ISA_MIPS32R2);
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSMap";
@@ -4927,7 +5207,17 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             save_cpu_state(ctx, 1);
+            /* Mark as an IO operation because we may trigger a software
+               interrupt.  */
+            if (use_icount) {
+                gen_io_start();
+            }
             gen_helper_mtc0_cause(arg);
+            if (use_icount) {
+                gen_io_end();
+            }
+            /* Stop translation as we may have triggered an intetrupt */
+            ctx->bstate = BS_STOP;
             rn = "Cause";
             break;
         default:
@@ -4937,7 +5227,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 14:
         switch (sel) {
         case 0:
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
             rn = "EPC";
             break;
         default:
@@ -5084,7 +5374,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
             rn = "DEPC";
             break;
         default:
@@ -5187,7 +5477,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     case 30:
         switch (sel) {
         case 0:
-            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
             rn = "ErrorEPC";
             break;
         default:
@@ -5198,7 +5488,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
         switch (sel) {
         case 0:
             /* EJTAG support */
-            gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
+            gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
             rn = "DESAVE";
             break;
         default:
@@ -5210,6 +5500,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
     default:
         goto die;
     }
+    (void)rn; /* avoid a compiler warning */
     LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
     /* For simplicity assume that all writes can cause interrupts.  */
     if (use_icount) {
@@ -5224,7 +5515,7 @@ die:
 }
 #endif /* TARGET_MIPS64 */
 
-static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
+static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
                      int u, int sel, int h)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
@@ -5239,6 +5530,19 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
         tcg_gen_movi_tl(t0, -1);
     else if (u == 0) {
         switch (rt) {
+        case 1:
+            switch (sel) {
+            case 1:
+                gen_helper_mftc0_vpecontrol(t0);
+                break;
+            case 2:
+                gen_helper_mftc0_vpeconf0(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
         case 2:
             switch (sel) {
             case 1:
@@ -5285,6 +5589,46 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
                 gen_mfc0(env, ctx, t0, rt, sel);
                 break;
             }
+        case 13:
+            switch (sel) {
+            case 0:
+                gen_helper_mftc0_cause(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
+        case 14:
+            switch (sel) {
+            case 0:
+                gen_helper_mftc0_epc(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
+        case 15:
+            switch (sel) {
+            case 1:
+                gen_helper_mftc0_ebase(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
+        case 16:
+            switch (sel) {
+            case 0 ... 7:
+                gen_helper_mftc0_configx(t0, tcg_const_tl(sel));
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
         case 23:
             switch (sel) {
             case 0:
@@ -5388,7 +5732,7 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
+static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
                      int u, int sel, int h)
 {
     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
@@ -5404,6 +5748,19 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
         /* NOP */ ;
     else if (u == 0) {
         switch (rd) {
+        case 1:
+            switch (sel) {
+            case 1:
+                gen_helper_mttc0_vpecontrol(t0);
+                break;
+            case 2:
+                gen_helper_mttc0_vpeconf0(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
         case 2:
             switch (sel) {
             case 1:
@@ -5450,6 +5807,26 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
                 gen_mtc0(env, ctx, t0, rd, sel);
                 break;
             }
+        case 13:
+            switch (sel) {
+            case 0:
+                gen_helper_mttc0_cause(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
+        case 15:
+            switch (sel) {
+            case 1:
+                gen_helper_mttc0_ebase(t0);
+                break;
+            default:
+                goto die;
+                break;
+            }
+            break;
         case 23:
             switch (sel) {
             case 0:
@@ -5552,10 +5929,11 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
+static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
 {
     const char *opn = "ldst";
 
+    check_cp0_enabled(ctx);
     switch (opc) {
     case OPC_MFC0:
         if (rt == 0) {
@@ -5670,12 +6048,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
         generate_exception(ctx, EXCP_RI);
         return;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
 }
 #endif /* !CONFIG_USER_ONLY */
 
 /* CP1 Branches (before delay slot) */
-static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
+static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
                                  int32_t cc, int32_t offset)
 {
     target_ulong btarget;
@@ -5721,7 +6100,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
             TCGv_i32 t1 = tcg_temp_new_i32();
             tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
-            tcg_gen_nor_i32(t0, t0, t1);
+            tcg_gen_nand_i32(t0, t0, t1);
             tcg_temp_free_i32(t1);
             tcg_gen_andi_i32(t0, t0, 1);
             tcg_gen_extu_i32_tl(bcond, t0);
@@ -5745,11 +6124,11 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
             TCGv_i32 t1 = tcg_temp_new_i32();
             tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
-            tcg_gen_or_i32(t0, t0, t1);
+            tcg_gen_and_i32(t0, t0, t1);
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
-            tcg_gen_or_i32(t0, t0, t1);
+            tcg_gen_and_i32(t0, t0, t1);
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
-            tcg_gen_nor_i32(t0, t0, t1);
+            tcg_gen_nand_i32(t0, t0, t1);
             tcg_temp_free_i32(t1);
             tcg_gen_andi_i32(t0, t0, 1);
             tcg_gen_extu_i32_tl(bcond, t0);
@@ -5779,6 +6158,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
         generate_exception (ctx, EXCP_RI);
         goto out;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
                ctx->hflags, btarget);
     ctx->btarget = btarget;
@@ -6008,6 +6388,7 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
         generate_exception (ctx, EXCP_RI);
         goto out;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
 
  out:
@@ -6425,7 +6806,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
             TCGv_i32 fp1 = tcg_temp_new_i32();
 
             gen_load_fpr32(fp0, fs);
-            gen_load_fpr32(fp1, fd);
+            gen_load_fpr32(fp1, ft);
             gen_helper_float_recip2_s(fp0, fp0, fp1);
             tcg_temp_free_i32(fp1);
             gen_store_fpr32(fp0, fd);
@@ -6520,7 +6901,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
 
             gen_load_fpr32(fp32_0, fs);
             gen_load_fpr32(fp32_1, ft);
-            tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
+            tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
             tcg_temp_free_i32(fp32_1);
             tcg_temp_free_i32(fp32_0);
             gen_store_fpr64(ctx, fp64, fd);
@@ -7163,7 +7544,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
             TCGv_i64 fp1 = tcg_temp_new_i64();
 
             gen_load_fpr64(ctx, fp0, fs);
-            gen_load_fpr64(ctx, fp1, fd);
+            gen_load_fpr64(ctx, fp1, ft);
             gen_helper_float_recip2_ps(fp0, fp0, fp1);
             tcg_temp_free_i64(fp1);
             gen_store_fpr64(ctx, fp0, fd);
@@ -7335,6 +7716,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
         generate_exception (ctx, EXCP_RI);
         return;
     }
+    (void)opn; /* avoid a compiler warning */
     switch (optype) {
     case BINOP:
         MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
@@ -7361,8 +7743,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
     } else if (index == 0) {
         gen_load_gpr(t0, base);
     } else {
-        gen_load_gpr(t0, index);
-        gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
+        gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
     }
     /* Don't do NOP if destination is zero: we must perform the actual
        memory access. */
@@ -7447,6 +7828,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
         break;
     }
     tcg_temp_free(t0);
+    (void)opn; (void)store; /* avoid compiler warnings */
     MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
                regnames[index], regnames[base]);
 }
@@ -7720,16 +8102,21 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
         generate_exception (ctx, EXCP_RI);
         return;
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
                fregnames[fs], fregnames[ft]);
 }
 
 static void
-gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
+gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
 {
     TCGv t0;
 
+#if !defined(CONFIG_USER_ONLY)
+    /* The Linux kernel will emulate rdhwr if it's not supported natively.
+       Therefore only check the ISA in system mode.  */
     check_insn(env, ctx, ISA_MIPS32R2);
+#endif
     t0 = tcg_temp_new();
 
     switch (rd) {
@@ -7755,7 +8142,7 @@ gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
         break;
     case 29:
 #if defined(CONFIG_USER_ONLY)
-        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
+        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
         gen_store_gpr(t0, rt);
         break;
 #else
@@ -7770,7 +8157,7 @@ gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
     tcg_temp_free(t0);
 }
 
-static void handle_delay_slot (CPUState *env, DisasContext *ctx,
+static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
                                int insn_bytes)
 {
     if (ctx->hflags & MIPS_HFLAG_BMASK) {
@@ -8003,22 +8390,22 @@ static void gen_mips16_save (DisasContext *ctx,
     case 4:
         gen_base_offset_addr(ctx, t0, 29, 12);
         gen_load_gpr(t1, 7);
-        op_ldst_sw(t1, t0, ctx);
+        op_st_sw(t1, t0, ctx);
         /* Fall through */
     case 3:
         gen_base_offset_addr(ctx, t0, 29, 8);
         gen_load_gpr(t1, 6);
-        op_ldst_sw(t1, t0, ctx);
+        op_st_sw(t1, t0, ctx);
         /* Fall through */
     case 2:
         gen_base_offset_addr(ctx, t0, 29, 4);
         gen_load_gpr(t1, 5);
-        op_ldst_sw(t1, t0, ctx);
+        op_st_sw(t1, t0, ctx);
         /* Fall through */
     case 1:
         gen_base_offset_addr(ctx, t0, 29, 0);
         gen_load_gpr(t1, 4);
-        op_ldst_sw(t1, t0, ctx);
+        op_st_sw(t1, t0, ctx);
     }
 
     gen_load_gpr(t0, 29);
@@ -8026,7 +8413,7 @@ static void gen_mips16_save (DisasContext *ctx,
 #define DECR_AND_STORE(reg) do {                \
         tcg_gen_subi_tl(t0, t0, 4);             \
         gen_load_gpr(t1, reg);                  \
-        op_ldst_sw(t1, t0, ctx);                \
+        op_st_sw(t1, t0, ctx);                  \
     } while (0)
 
     if (do_ra) {
@@ -8126,7 +8513,7 @@ static void gen_mips16_restore (DisasContext *ctx,
 
 #define DECR_AND_LOAD(reg) do {                 \
         tcg_gen_subi_tl(t0, t0, 4);             \
-        op_ldst_lw(t1, t0, ctx);                \
+        op_ld_lw(t1, t0, ctx);                  \
         gen_store_gpr(t1, reg);                 \
     } while (0)
 
@@ -8236,7 +8623,7 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm,
 }
 
 #if defined(TARGET_MIPS64)
-static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
+static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
                                int ry, int funct, int16_t offset,
                                int extended)
 {
@@ -8244,17 +8631,17 @@ static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
     case I64_LDSP:
         check_mips_64(ctx);
         offset = extended ? offset : offset << 3;
-        gen_ldst(ctx, OPC_LD, ry, 29, offset);
+        gen_ld(env, ctx, OPC_LD, ry, 29, offset);
         break;
     case I64_SDSP:
         check_mips_64(ctx);
         offset = extended ? offset : offset << 3;
-        gen_ldst(ctx, OPC_SD, ry, 29, offset);
+        gen_st(ctx, OPC_SD, ry, 29, offset);
         break;
     case I64_SDRASP:
         check_mips_64(ctx);
         offset = extended ? offset : (ctx->opcode & 0xff) << 3;
-        gen_ldst(ctx, OPC_SD, 31, 29, offset);
+        gen_st(ctx, OPC_SD, 31, 29, offset);
         break;
     case I64_DADJSP:
         check_mips_64(ctx);
@@ -8266,7 +8653,7 @@ static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
             generate_exception(ctx, EXCP_RI);
         } else {
             offset = extended ? offset : offset << 3;
-            gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
+            gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
         }
         break;
     case I64_DADDIU5:
@@ -8288,7 +8675,7 @@ static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
 }
 #endif
 
-static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
+static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
                                        int *is_branch)
 {
     int extend = lduw_code(ctx->pc + 2);
@@ -8350,7 +8737,7 @@ static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
 #if defined(TARGET_MIPS64)
     case M16_OPC_LD:
             check_mips_64(ctx);
-        gen_ldst(ctx, OPC_LD, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LD, ry, rx, offset);
         break;
 #endif
     case M16_OPC_RRIA:
@@ -8387,7 +8774,7 @@ static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
             gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
             break;
         case I8_SWRASP:
-            gen_ldst(ctx, OPC_SW, 31, 29, imm);
+            gen_st(ctx, OPC_SW, 31, 29, imm);
             break;
         case I8_ADJSP:
             gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
@@ -8426,46 +8813,46 @@ static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_SD:
-        gen_ldst(ctx, OPC_SD, ry, rx, offset);
+        gen_st(ctx, OPC_SD, ry, rx, offset);
         break;
 #endif
     case M16_OPC_LB:
-        gen_ldst(ctx, OPC_LB, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LB, ry, rx, offset);
         break;
     case M16_OPC_LH:
-        gen_ldst(ctx, OPC_LH, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LH, ry, rx, offset);
         break;
     case M16_OPC_LWSP:
-        gen_ldst(ctx, OPC_LW, rx, 29, offset);
+        gen_ld(env, ctx, OPC_LW, rx, 29, offset);
         break;
     case M16_OPC_LW:
-        gen_ldst(ctx, OPC_LW, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LW, ry, rx, offset);
         break;
     case M16_OPC_LBU:
-        gen_ldst(ctx, OPC_LBU, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
         break;
     case M16_OPC_LHU:
-        gen_ldst(ctx, OPC_LHU, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
         break;
     case M16_OPC_LWPC:
-        gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
+        gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_LWU:
-        gen_ldst(ctx, OPC_LWU, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
         break;
 #endif
     case M16_OPC_SB:
-        gen_ldst(ctx, OPC_SB, ry, rx, offset);
+        gen_st(ctx, OPC_SB, ry, rx, offset);
         break;
     case M16_OPC_SH:
-        gen_ldst(ctx, OPC_SH, ry, rx, offset);
+        gen_st(ctx, OPC_SH, ry, rx, offset);
         break;
     case M16_OPC_SWSP:
-        gen_ldst(ctx, OPC_SW, rx, 29, offset);
+        gen_st(ctx, OPC_SW, rx, 29, offset);
         break;
     case M16_OPC_SW:
-        gen_ldst(ctx, OPC_SW, ry, rx, offset);
+        gen_st(ctx, OPC_SW, ry, rx, offset);
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_I64:
@@ -8480,7 +8867,7 @@ static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
     return 4;
 }
 
-static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
+static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
                               int *is_branch)
 {
     int rx, ry;
@@ -8558,7 +8945,7 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
 #if defined(TARGET_MIPS64)
     case M16_OPC_LD:
         check_mips_64(ctx);
-        gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
+        gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
         break;
 #endif
     case M16_OPC_RRIA:
@@ -8613,7 +9000,7 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
                                    ((int8_t)ctx->opcode) << 1);
                 break;
             case I8_SWRASP:
-                gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
+                gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
                 break;
             case I8_ADJSP:
                 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
@@ -8677,47 +9064,47 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
 #if defined(TARGET_MIPS64)
     case M16_OPC_SD:
         check_mips_64(ctx);
-        gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
+        gen_st(ctx, OPC_SD, ry, rx, offset << 3);
         break;
 #endif
     case M16_OPC_LB:
-        gen_ldst(ctx, OPC_LB, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LB, ry, rx, offset);
         break;
     case M16_OPC_LH:
-        gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
+        gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
         break;
     case M16_OPC_LWSP:
-        gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
+        gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
         break;
     case M16_OPC_LW:
-        gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
+        gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
         break;
     case M16_OPC_LBU:
-        gen_ldst(ctx, OPC_LBU, ry, rx, offset);
+        gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
         break;
     case M16_OPC_LHU:
-        gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
+        gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
         break;
     case M16_OPC_LWPC:
-        gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
+        gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
         break;
 #if defined (TARGET_MIPS64)
     case M16_OPC_LWU:
         check_mips_64(ctx);
-        gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
+        gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
         break;
 #endif
     case M16_OPC_SB:
-        gen_ldst(ctx, OPC_SB, ry, rx, offset);
+        gen_st(ctx, OPC_SB, ry, rx, offset);
         break;
     case M16_OPC_SH:
-        gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
+        gen_st(ctx, OPC_SH, ry, rx, offset << 1);
         break;
     case M16_OPC_SWSP:
-        gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
+        gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
         break;
     case M16_OPC_SW:
-        gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
+        gen_st(ctx, OPC_SW, ry, rx, offset << 2);
         break;
     case M16_OPC_RRR:
         {
@@ -9394,14 +9781,14 @@ static int mmreg2 (int r)
 /* Zero-extended immediate */
 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
 
-static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
+static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
 {
     int rd = mmreg(uMIPS_RD(ctx->opcode));
 
     gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
 }
 
-static void gen_addiur2 (CPUState *env, DisasContext *ctx)
+static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
 {
     static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
     int rd = mmreg(uMIPS_RD(ctx->opcode));
@@ -9410,7 +9797,7 @@ static void gen_addiur2 (CPUState *env, DisasContext *ctx)
     gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
 }
 
-static void gen_addiusp (CPUState *env, DisasContext *ctx)
+static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
 {
     int encoded = ZIMM(ctx->opcode, 1, 9);
     int decoded;
@@ -9428,7 +9815,7 @@ static void gen_addiusp (CPUState *env, DisasContext *ctx)
     gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
 }
 
-static void gen_addius5 (CPUState *env, DisasContext *ctx)
+static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
 {
     int imm = SIMM(ctx->opcode, 1, 4);
     int rd = (ctx->opcode >> 5) & 0x1f;
@@ -9436,7 +9823,7 @@ static void gen_addius5 (CPUState *env, DisasContext *ctx)
     gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
 }
 
-static void gen_andi16 (CPUState *env, DisasContext *ctx)
+static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
 {
     static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
                                  31, 32, 63, 64, 255, 32768, 65535 };
@@ -9489,7 +9876,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
 }
 
 
-static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
+static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     int rd = mmreg((ctx->opcode >> 3) & 0x7);
     int rs = mmreg(ctx->opcode & 0x7);
@@ -9631,7 +10018,7 @@ static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
     }
 
     save_cpu_state(ctx, 0);
-    op_ldst_lw(t1, t0, ctx);
+    op_ld_lw(t1, t0, ctx);
     gen_store_gpr(t1, rd);
 
     tcg_temp_free(t0);
@@ -9644,7 +10031,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
     const char *opn = "ldst_pair";
     TCGv t0, t1;
 
-    if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
+    if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
         generate_exception(ctx, EXCP_RI);
         return;
     }
@@ -9656,54 +10043,63 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
 
     switch (opc) {
     case LWP:
+        if (rd == base) {
+            generate_exception(ctx, EXCP_RI);
+            return;
+        }
         save_cpu_state(ctx, 0);
-        op_ldst_lw(t1, t0, ctx);
+        op_ld_lw(t1, t0, ctx);
         gen_store_gpr(t1, rd);
         tcg_gen_movi_tl(t1, 4);
         gen_op_addr_add(ctx, t0, t0, t1);
-        op_ldst_lw(t1, t0, ctx);
+        op_ld_lw(t1, t0, ctx);
         gen_store_gpr(t1, rd+1);
         opn = "lwp";
         break;
     case SWP:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         gen_load_gpr(t1, rd);
-        op_ldst_sw(t1, t0, ctx);
+        op_st_sw(t1, t0, ctx);
         tcg_gen_movi_tl(t1, 4);
         gen_op_addr_add(ctx, t0, t0, t1);
         gen_load_gpr(t1, rd+1);
-        op_ldst_sw(t1, t0, ctx);
+        op_st_sw(t1, t0, ctx);
         opn = "swp";
         break;
 #ifdef TARGET_MIPS64
     case LDP:
+        if (rd == base) {
+            generate_exception(ctx, EXCP_RI);
+            return;
+        }
         save_cpu_state(ctx, 0);
-        op_ldst_ld(t1, t0, ctx);
+        op_ld_ld(t1, t0, ctx);
         gen_store_gpr(t1, rd);
         tcg_gen_movi_tl(t1, 8);
         gen_op_addr_add(ctx, t0, t0, t1);
-        op_ldst_ld(t1, t0, ctx);
+        op_ld_ld(t1, t0, ctx);
         gen_store_gpr(t1, rd+1);
         opn = "ldp";
         break;
     case SDP:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         gen_load_gpr(t1, rd);
-        op_ldst_sd(t1, t0, ctx);
+        op_st_sd(t1, t0, ctx);
         tcg_gen_movi_tl(t1, 8);
         gen_op_addr_add(ctx, t0, t0, t1);
         gen_load_gpr(t1, rd+1);
-        op_ldst_sd(t1, t0, ctx);
+        op_st_sd(t1, t0, ctx);
         opn = "sdp";
         break;
 #endif
     }
+    (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
     tcg_temp_free(t0);
     tcg_temp_free(t1);
 }
 
-static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
+static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
                            int *is_branch)
 {
     int extension = (ctx->opcode >> 6) & 0x3f;
@@ -9734,6 +10130,7 @@ static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
 #ifndef CONFIG_USER_ONLY
     case MFC0:
     case MFC0 + 32:
+        check_cp0_enabled(ctx);
         if (rt == 0) {
             /* Treat as NOP. */
             break;
@@ -9742,6 +10139,7 @@ static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
         break;
     case MTC0:
     case MTC0 + 32:
+        check_cp0_enabled(ctx);
         {
             TCGv t0 = tcg_temp_new();
 
@@ -9838,10 +10236,12 @@ static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
     case 0x05:
         switch (minor) {
         case RDPGPR:
+            check_cp0_enabled(ctx);
             check_insn(env, ctx, ISA_MIPS32R2);
             gen_load_srsgpr(rt, rs);
             break;
         case WRPGPR:
+            check_cp0_enabled(ctx);
             check_insn(env, ctx, ISA_MIPS32R2);
             gen_store_srsgpr(rt, rs);
             break;
@@ -9882,6 +10282,7 @@ static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
     case 0x1d:
         switch (minor) {
         case DI:
+            check_cp0_enabled(ctx);
             {
                 TCGv t0 = tcg_temp_new();
 
@@ -9894,6 +10295,7 @@ static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
             }
             break;
         case EI:
+            check_cp0_enabled(ctx);
             {
                 TCGv t0 = tcg_temp_new();
 
@@ -9977,7 +10379,7 @@ enum {
     FMT_DWL_L = 2
 };
 
-static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
+static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
 {
     int extension = (ctx->opcode >> 6) & 0x3ff;
     uint32_t mips32_op;
@@ -10223,7 +10625,7 @@ static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
     }
 }
 
-static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
+static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
                                     uint16_t insn_hw1, int *is_branch)
 {
     int32_t offset;
@@ -10374,6 +10776,7 @@ static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
         minor = (ctx->opcode >> 12) & 0xf;
         switch (minor) {
         case CACHE:
+            check_cp0_enabled(ctx);
             /* Treat as no-op. */
             break;
         case LWC2:
@@ -10798,40 +11201,44 @@ static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
         switch (minor) {
         case LWL:
             mips32_op = OPC_LWL;
-            goto do_ldst_lr;
+            goto do_ld_lr;
         case SWL:
             mips32_op = OPC_SWL;
-            goto do_ldst_lr;
+            goto do_st_lr;
         case LWR:
             mips32_op = OPC_LWR;
-            goto do_ldst_lr;
+            goto do_ld_lr;
         case SWR:
             mips32_op = OPC_SWR;
-            goto do_ldst_lr;
+            goto do_st_lr;
 #if defined(TARGET_MIPS64)
         case LDL:
             mips32_op = OPC_LDL;
-            goto do_ldst_lr;
+            goto do_ld_lr;
         case SDL:
             mips32_op = OPC_SDL;
-            goto do_ldst_lr;
+            goto do_st_lr;
         case LDR:
             mips32_op = OPC_LDR;
-            goto do_ldst_lr;
+            goto do_ld_lr;
         case SDR:
             mips32_op = OPC_SDR;
-            goto do_ldst_lr;
+            goto do_st_lr;
         case LWU:
             mips32_op = OPC_LWU;
-            goto do_ldst_lr;
+            goto do_ld_lr;
         case LLD:
             mips32_op = OPC_LLD;
-            goto do_ldst_lr;
+            goto do_ld_lr;
 #endif
         case LL:
             mips32_op = OPC_LL;
-        do_ldst_lr:
-            gen_ldst(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+            goto do_ld_lr;
+        do_ld_lr:
+            gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+            break;
+        do_st_lr:
+            gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
             break;
         case SC:
             gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
@@ -10935,37 +11342,41 @@ static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
         /* Loads and stores */
     case LB32:
         mips32_op = OPC_LB;
-        goto do_ldst;
+        goto do_ld;
     case LBU32:
         mips32_op = OPC_LBU;
-        goto do_ldst;
+        goto do_ld;
     case LH32:
         mips32_op = OPC_LH;
-        goto do_ldst;
+        goto do_ld;
     case LHU32:
         mips32_op = OPC_LHU;
-        goto do_ldst;
+        goto do_ld;
     case LW32:
         mips32_op = OPC_LW;
-        goto do_ldst;
+        goto do_ld;
 #ifdef TARGET_MIPS64
     case LD32:
         mips32_op = OPC_LD;
-        goto do_ldst;
+        goto do_ld;
     case SD32:
         mips32_op = OPC_SD;
-        goto do_ldst;
+        goto do_st;
 #endif
     case SB32:
         mips32_op = OPC_SB;
-        goto do_ldst;
+        goto do_st;
     case SH32:
         mips32_op = OPC_SH;
-        goto do_ldst;
+        goto do_st;
     case SW32:
         mips32_op = OPC_SW;
-    do_ldst:
-        gen_ldst(ctx, mips32_op, rt, rs, imm);
+        goto do_st;
+    do_ld:
+        gen_ld(env, ctx, mips32_op, rt, rs, imm);
+        break;
+    do_st:
+        gen_st(ctx, mips32_op, rt, rs, imm);
         break;
     default:
         generate_exception(ctx, EXCP_RI);
@@ -10973,7 +11384,7 @@ static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
     }
 }
 
-static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     uint32_t op;
 
@@ -11115,7 +11526,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = 28;            /* GP */
             int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
 
-            gen_ldst(ctx, OPC_LW, rd, rb, offset);
+            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
         }
         break;
     case POOL16F:
@@ -11147,7 +11558,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int16_t offset = ZIMM(ctx->opcode, 0, 4);
             offset = (offset == 0xf ? -1 : offset);
 
-            gen_ldst(ctx, OPC_LBU, rd, rb, offset);
+            gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
         }
         break;
     case LHU16:
@@ -11156,7 +11567,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
 
-            gen_ldst(ctx, OPC_LHU, rd, rb, offset);
+            gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
         }
         break;
     case LWSP16:
@@ -11165,7 +11576,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = 29;            /* SP */
             int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
 
-            gen_ldst(ctx, OPC_LW, rd, rb, offset);
+            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
         }
         break;
     case LW16:
@@ -11174,7 +11585,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
 
-            gen_ldst(ctx, OPC_LW, rd, rb, offset);
+            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
         }
         break;
     case SB16:
@@ -11183,7 +11594,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4);
 
-            gen_ldst(ctx, OPC_SB, rd, rb, offset);
+            gen_st(ctx, OPC_SB, rd, rb, offset);
         }
         break;
     case SH16:
@@ -11192,7 +11603,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
 
-            gen_ldst(ctx, OPC_SH, rd, rb, offset);
+            gen_st(ctx, OPC_SH, rd, rb, offset);
         }
         break;
     case SWSP16:
@@ -11201,7 +11612,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = 29;            /* SP */
             int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
 
-            gen_ldst(ctx, OPC_SW, rd, rb, offset);
+            gen_st(ctx, OPC_SW, rd, rb, offset);
         }
         break;
     case SW16:
@@ -11210,7 +11621,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
 
-            gen_ldst(ctx, OPC_SW, rd, rb, offset);
+            gen_st(ctx, OPC_SW, rd, rb, offset);
         }
         break;
     case MOVE16:
@@ -11290,7 +11701,7 @@ static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branc
 
 #endif
 
-static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     int32_t offset;
     int rs, rt, rd, sa;
@@ -11350,7 +11761,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_MOVN:         /* Conditional move */
         case OPC_MOVZ:
-            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
+            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
+                                 INSN_LOONGSON2E | INSN_LOONGSON2F);
             gen_cond_move(env, op1, rd, rs, rt);
             break;
         case OPC_ADD ... OPC_SUBU:
@@ -11565,6 +11977,15 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             }
             /* Treat as NOP. */
             break;
+        case OPC_DIV_G_2F:
+        case OPC_DIVU_G_2F:
+        case OPC_MULT_G_2F:
+        case OPC_MULTU_G_2F:
+        case OPC_MOD_G_2F:
+        case OPC_MODU_G_2F:
+            check_insn(env, ctx, INSN_LOONGSON2F);
+            gen_loongson_integer(ctx, op1, rd, rs, rt);
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DCLO:
         case OPC_DCLZ:
@@ -11572,6 +11993,15 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             check_mips_64(ctx);
             gen_cl(ctx, op1, rd, rs);
             break;
+        case OPC_DMULT_G_2F:
+        case OPC_DMULTU_G_2F:
+        case OPC_DDIV_G_2F:
+        case OPC_DDIVU_G_2F:
+        case OPC_DMOD_G_2F:
+        case OPC_DMODU_G_2F:
+            check_insn(env, ctx, INSN_LOONGSON2F);
+            gen_loongson_integer(ctx, op1, rd, rs, rt);
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special2");
@@ -11620,6 +12050,12 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
                 tcg_temp_free(t0);
             }
             break;
+        case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
+        case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
+        case OPC_MOD_G_2E ... OPC_MODU_G_2E:
+            check_insn(env, ctx, INSN_LOONGSON2E);
+            gen_loongson_integer(ctx, op1, rd, rs, rt);
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -11633,6 +12069,12 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             op2 = MASK_DBSHFL(ctx->opcode);
             gen_bshfl(ctx, op2, rt, rd);
             break;
+        case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
+        case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
+        case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
+            check_insn(env, ctx, INSN_LOONGSON2E);
+            gen_loongson_integer(ctx, op1, rd, rs, rt);
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
@@ -11692,22 +12134,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
                 switch (op2) {
                 case OPC_DMT:
                     check_insn(env, ctx, ASE_MT);
-                    gen_helper_dmt(t0, t0);
+                    gen_helper_dmt(t0);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_EMT:
                     check_insn(env, ctx, ASE_MT);
-                    gen_helper_emt(t0, t0);
+                    gen_helper_emt(t0);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_DVPE:
                     check_insn(env, ctx, ASE_MT);
-                    gen_helper_dvpe(t0, t0);
+                    gen_helper_dvpe(t0);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_EVPE:
                     check_insn(env, ctx, ASE_MT);
-                    gen_helper_evpe(t0, t0);
+                    gen_helper_evpe(t0);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_DI:
@@ -11774,15 +12216,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
          *is_branch = 1;
          break;
     case OPC_LB ... OPC_LWR: /* Load and stores */
+    case OPC_LL:
+         gen_ld(env, ctx, op, rt, rs, imm);
+         break;
     case OPC_SB ... OPC_SW:
     case OPC_SWR:
-    case OPC_LL:
-         gen_ldst(ctx, op, rt, rs, imm);
+         gen_st(ctx, op, rt, rs, imm);
          break;
     case OPC_SC:
          gen_st_cond(ctx, op, rt, rs, imm);
          break;
     case OPC_CACHE:
+        check_cp0_enabled(ctx);
         check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
@@ -11903,13 +12348,17 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
     /* MIPS64 opcodes */
     case OPC_LWU:
     case OPC_LDL ... OPC_LDR:
-    case OPC_SDL ... OPC_SDR:
     case OPC_LLD:
     case OPC_LD:
+        check_insn(env, ctx, ISA_MIPS3);
+        check_mips_64(ctx);
+        gen_ld(env, ctx, op, rt, rs, imm);
+        break;
+    case OPC_SDL ... OPC_SDR:
     case OPC_SD:
         check_insn(env, ctx, ISA_MIPS3);
         check_mips_64(ctx);
-        gen_ldst(ctx, op, rt, rs, imm);
+        gen_st(ctx, op, rt, rs, imm);
         break;
     case OPC_SCD:
         check_insn(env, ctx, ISA_MIPS3);
@@ -11940,7 +12389,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
 }
 
 static inline void
-gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
                                 int search_pc)
 {
     DisasContext ctx;
@@ -12057,7 +12506,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
     } else {
         switch (ctx.bstate) {
         case BS_STOP:
-            gen_helper_interrupt_restart();
             gen_goto_tb(&ctx, 0, ctx.pc);
             break;
         case BS_NONE:
@@ -12065,7 +12513,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
             gen_goto_tb(&ctx, 0, ctx.pc);
             break;
         case BS_EXCP:
-            gen_helper_interrupt_restart();
             tcg_gen_exit_tb(0);
             break;
         case BS_BRANCH:
@@ -12095,18 +12542,17 @@ done_generating:
 #endif
 }
 
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-static void fpu_dump_state(CPUState *env, FILE *f,
-                           int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
+static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
                            int flags)
 {
     int i;
@@ -12135,8 +12581,8 @@ static void fpu_dump_state(CPUState *env, FILE *f,
     } while(0)
 
 
-    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%08x(0x%02x)\n",
-                env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
+    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%02x\n",
+                env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
                 get_float_exception_flags(&env->active_fpu.fp_status));
     for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
         fpu_fprintf(f, "%3s: ", fregnames[i]);
@@ -12153,8 +12599,8 @@ static void fpu_dump_state(CPUState *env, FILE *f,
 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
 
 static void
-cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
-                                int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
+                                fprintf_function cpu_fprintf,
                                 int flags)
 {
     int i;
@@ -12180,8 +12626,7 @@ cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
 }
 #endif
 
-void cpu_dump_state (CPUState *env, FILE *f,
-                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
                      int flags)
 {
     int i;
@@ -12223,36 +12668,36 @@ static void mips_tcg_init(void)
     TCGV_UNUSED(cpu_gpr[0]);
     for (i = 1; i < 32; i++)
         cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, active_tc.gpr[i]),
+                                        offsetof(CPUMIPSState, active_tc.gpr[i]),
                                         regnames[i]);
     cpu_PC = tcg_global_mem_new(TCG_AREG0,
-                                offsetof(CPUState, active_tc.PC), "PC");
+                                offsetof(CPUMIPSState, active_tc.PC), "PC");
     for (i = 0; i < MIPS_DSP_ACC; i++) {
         cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
-                                       offsetof(CPUState, active_tc.HI[i]),
+                                       offsetof(CPUMIPSState, active_tc.HI[i]),
                                        regnames_HI[i]);
         cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
-                                       offsetof(CPUState, active_tc.LO[i]),
+                                       offsetof(CPUMIPSState, active_tc.LO[i]),
                                        regnames_LO[i]);
         cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, active_tc.ACX[i]),
+                                        offsetof(CPUMIPSState, active_tc.ACX[i]),
                                         regnames_ACX[i]);
     }
     cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUState, active_tc.DSPControl),
+                                     offsetof(CPUMIPSState, active_tc.DSPControl),
                                      "DSPControl");
     bcond = tcg_global_mem_new(TCG_AREG0,
-                               offsetof(CPUState, bcond), "bcond");
+                               offsetof(CPUMIPSState, bcond), "bcond");
     btarget = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, btarget), "btarget");
+                                 offsetof(CPUMIPSState, btarget), "btarget");
     hflags = tcg_global_mem_new_i32(TCG_AREG0,
-                                    offsetof(CPUState, hflags), "hflags");
+                                    offsetof(CPUMIPSState, hflags), "hflags");
 
     fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
-                                      offsetof(CPUState, active_fpu.fcr0),
+                                      offsetof(CPUMIPSState, active_fpu.fcr0),
                                       "fcr0");
     fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
-                                       offsetof(CPUState, active_fpu.fcr31),
+                                       offsetof(CPUMIPSState, active_fpu.fcr31),
                                        "fcr31");
 
     /* register helpers */
@@ -12264,31 +12709,32 @@ static void mips_tcg_init(void)
 
 #include "translate_init.c"
 
-CPUMIPSState *cpu_mips_init (const char *cpu_model)
+MIPSCPU *cpu_mips_init(const char *cpu_model)
 {
+    MIPSCPU *cpu;
     CPUMIPSState *env;
     const mips_def_t *def;
 
     def = cpu_mips_find_by_name(cpu_model);
     if (!def)
         return NULL;
-    env = qemu_mallocz(sizeof(CPUMIPSState));
+    cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
+    env = &cpu->env;
     env->cpu_model = def;
     env->cpu_model_str = cpu_model;
 
-    cpu_exec_init(env);
 #ifndef CONFIG_USER_ONLY
     mmu_init(env, def);
 #endif
     fpu_init(env, def);
     mvp_init(env, def);
     mips_tcg_init();
-    cpu_reset(env);
+    cpu_reset(CPU(cpu));
     qemu_init_vcpu(env);
-    return env;
+    return cpu;
 }
 
-void cpu_reset (CPUMIPSState *env)
+void cpu_state_reset(CPUMIPSState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
@@ -12337,12 +12783,14 @@ void cpu_reset (CPUMIPSState *env)
     env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
     env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
     env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
+    env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
     env->insn_flags = env->cpu_model->insn_flags;
 
 #if defined(CONFIG_USER_ONLY)
     env->hflags = MIPS_HFLAG_UM;
-    /* Enable access to the SYNCI_Step register.  */
-    env->CP0_HWREna |= (1 << 1);
+    /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
+       hardware registers.  */
+    env->CP0_HWREna |= 0x0000000F;
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
         env->hflags |= MIPS_HFLAG_FPU;
     }
@@ -12363,8 +12811,7 @@ void cpu_reset (CPUMIPSState *env)
     env->CP0_Random = env->tlb->nb_tlb - 1;
     env->tlb->tlb_in_use = env->tlb->nb_tlb;
     env->CP0_Wired = 0;
-    /* SMP not implemented */
-    env->CP0_EBase = 0x80000000;
+    env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
     env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
     /* vectored interrupts not implemented, timer on int 7,
        no performance counters. */
@@ -12382,6 +12829,32 @@ void cpu_reset (CPUMIPSState *env)
     /* Count register increments in debug mode, EJTAG version 1 */
     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
     env->hflags = MIPS_HFLAG_CP0;
+
+    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
+        int i;
+
+        /* Only TC0 on VPE 0 starts as active.  */
+        for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
+            env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
+            env->tcs[i].CP0_TCHalt = 1;
+        }
+        env->active_tc.CP0_TCHalt = 1;
+        env->halted = 1;
+
+        if (!env->cpu_index) {
+            /* VPE0 starts up enabled.  */
+            env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
+            env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
+
+            /* TC0 starts up unhalted.  */
+            env->halted = 0;
+            env->active_tc.CP0_TCHalt = 0;
+            env->tcs[0].CP0_TCHalt = 0;
+            /* With thread 0 active.  */
+            env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
+            env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
+        }
+    }
 #endif
 #if defined(TARGET_MIPS64)
     if (env->cpu_model->insn_flags & ISA_MIPS3) {
@@ -12391,8 +12864,7 @@ void cpu_reset (CPUMIPSState *env)
     env->exception_index = EXCP_NONE;
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
 {
     env->active_tc.PC = gen_opc_pc[pc_pos];
     env->hflags &= ~MIPS_HFLAG_BMASK;