qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features
@ 2014-07-14 16:19 Leon Alrae
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI Leon Alrae
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

This patchset provides the following set of features:
- forbidden slot
- Config5.SBRI bit
- reserved fields and reserved registers (ignore write, read 0)
- updated MIPS64R6-generic CPU

It also includes modification of the behaviour when accessing unimplemented
CP0 register - the Reserved Instruction exception is not generated.

These changes should be applied on top of the two pending MIPS64R6 patchsets.

Thanks,
Leon

Leon Alrae (6):
  target-mips: add Config5.SBRI
  target-mips: implement forbidden slot
  target-mips: CP0_Status.CU0 no longer allows the user to access CP0
  target-mips: add restrictions for possible values in registers
  target-mips: correctly handle access to unimplemented CP0 register
  target-mips: enable features in MIPS64R6-generic CPU

 target-mips/cpu.h            |   17 +-
 target-mips/op_helper.c      |   63 +++-
 target-mips/translate.c      |  659 ++++++++++++++++++++++--------------------
 target-mips/translate_init.c |   11 +-
 4 files changed, 415 insertions(+), 335 deletions(-)

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI
  2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
@ 2014-07-14 16:19 ` Leon Alrae
  2014-10-16 14:32   ` Yongbok Kim
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot Leon Alrae
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

SDBBP instruction Reserved Instruction control. The purpose of this field is
to restrict availability of SDBBP to kernel mode operation.

If the bit is set then SDBBP instruction can only be executed in kernel mode.
User execution of SDBBP will cause a Reserved Instruction exception.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |   11 +++++++++--
 target-mips/translate.c |   24 +++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 23bb22c..2a762d2 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -410,6 +410,7 @@ struct CPUMIPSState {
 #define CP0C5_CV         29
 #define CP0C5_EVA        28
 #define CP0C5_MSAEn      27
+#define CP0C5_SBRI       6
 #define CP0C5_UFR        2
 #define CP0C5_NFExists   0
     int32_t CP0_Config6;
@@ -461,7 +462,7 @@ struct CPUMIPSState {
 #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK  0xC07FF
+#define MIPS_HFLAG_TMASK  0x2C07FF
 #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
     /* The KSU flags must be the lowest bits in hflags. The flag order
        must be the same as defined for CP0 Status. This allows to use
@@ -504,6 +505,7 @@ struct CPUMIPSState {
 #define MIPS_HFLAG_DSPR2 0x80000  /* Enable access to MIPS DSPR2 resources. */
     /* Extra flag about HWREna register. */
 #define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
+#define MIPS_HFLAG_SBRI  0x200000 /* R6 SDBBP causes RI excpt. in user mode */
     target_ulong btarget;        /* Jump / branch target               */
     target_ulong bcond;          /* Branch condition (if needed)       */
 
@@ -759,7 +761,8 @@ static inline void compute_hflags(CPUMIPSState *env)
 {
     env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
                      MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
-                     MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2);
+                     MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
+                     MIPS_HFLAG_SBRI);
     if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
         !(env->CP0_Status & (1 << CP0St_ERL)) &&
         !(env->hflags & MIPS_HFLAG_DM)) {
@@ -795,6 +798,10 @@ static inline void compute_hflags(CPUMIPSState *env)
     if (env->CP0_Status & (1 << CP0St_FR)) {
         env->hflags |= MIPS_HFLAG_F64;
     }
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
+        (env->CP0_Config5 & (1 << CP0C5_SBRI))) {
+        env->hflags |= MIPS_HFLAG_SBRI;
+    }
     if (env->insn_flags & ASE_DSPR2) {
         /* Enables access MIPS DSP resources, now our cpu is DSP ASER2,
            so enable to access DSPR2 resources. */
diff --git a/target-mips/translate.c b/target-mips/translate.c
index b931574..d0f695a 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -6273,6 +6273,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
             rn = "Config3";
             break;
+        case 4:
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
+            rn = "Config4";
+            break;
+        case 5:
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
+            rn = "Config5";
+            break;
        /* 6,7 are implementation dependent */
         case 6:
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
@@ -6891,6 +6899,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             /* ignored */
             rn = "Config3";
             break;
+        case 4:
+            /* currently ignored */
+            rn = "Config4";
+            break;
+        case 5:
+            gen_helper_mtc0_config5(cpu_env, arg);
+            rn = "Config5";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
+            break;
         /* 6,7 are implementation dependent */
         default:
             rn = "Invalid config selector";
@@ -15886,7 +15904,11 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
         }
         break;
     case R6_OPC_SDBBP:
-        generate_exception(ctx, EXCP_DBp);
+        if (ctx->hflags & MIPS_HFLAG_SBRI) {
+            generate_exception(ctx, EXCP_RI);
+        } else {
+            generate_exception(ctx, EXCP_DBp);
+        }
         break;
 #if defined(TARGET_MIPS64)
     case OPC_DLSA:
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot
  2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI Leon Alrae
@ 2014-07-14 16:19 ` Leon Alrae
  2014-10-20 11:10   ` Yongbok Kim
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0 Leon Alrae
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

When conditional compact branch is encountered decode one more instruction in
current translation block - that will be forbidden slot. Instruction in
forbidden slot will be executed only if conditional compact branch is not taken.

Any control transfer instruction (CTI) which are branches, jumps, ERET,
DERET, WAIT and PAUSE will generate RI exception if executed in forbidden or
delay slot.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |    5 ++-
 target-mips/translate.c |   89 +++++++++++++++++++++++++++++++---------------
 2 files changed, 63 insertions(+), 31 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 2a762d2..a35ab9d 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -462,7 +462,7 @@ struct CPUMIPSState {
 #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK  0x2C07FF
+#define MIPS_HFLAG_TMASK  0x6C07FF
 #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
     /* The KSU flags must be the lowest bits in hflags. The flag order
        must be the same as defined for CP0 Status. This allows to use
@@ -488,7 +488,7 @@ struct CPUMIPSState {
      * the delay slot, record what type of branch it is so that we can
      * resume translation properly.  It might be possible to reduce
      * this from three bits to two.  */
-#define MIPS_HFLAG_BMASK_BASE  0x03800
+#define MIPS_HFLAG_BMASK_BASE  0x403800
 #define MIPS_HFLAG_B      0x00800 /* Unconditional branch               */
 #define MIPS_HFLAG_BC     0x01000 /* Conditional branch                 */
 #define MIPS_HFLAG_BL     0x01800 /* Likely branch                      */
@@ -506,6 +506,7 @@ struct CPUMIPSState {
     /* Extra flag about HWREna register. */
 #define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
 #define MIPS_HFLAG_SBRI  0x200000 /* R6 SDBBP causes RI excpt. in user mode */
+#define MIPS_HFLAG_FBNSLOT 0x400000 /* Forbidden slot                   */
     target_ulong btarget;        /* Jump / branch target               */
     target_ulong bcond;          /* Branch condition (if needed)       */
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d0f695a..4ed81fe 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -7686,12 +7686,20 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
     case OPC_ERET:
         opn = "eret";
         check_insn(ctx, ISA_MIPS2);
+        if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
+            MIPS_DEBUG("CTI in delay / forbidden slot");
+            goto die;
+        }
         gen_helper_eret(cpu_env);
         ctx->bstate = BS_EXCP;
         break;
     case OPC_DERET:
         opn = "deret";
         check_insn(ctx, ISA_MIPS32);
+        if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
+            MIPS_DEBUG("CTI in delay / forbidden slot");
+            goto die;
+        }
         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
             MIPS_INVAL(opn);
             generate_exception(ctx, EXCP_RI);
@@ -7703,6 +7711,10 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
     case OPC_WAIT:
         opn = "wait";
         check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
+        if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
+            MIPS_DEBUG("CTI in delay / forbidden slot");
+            goto die;
+        }
         /* If we get an exception, we want to restart at next instruction */
         ctx->pc += 4;
         save_cpu_state(ctx, 1);
@@ -7729,6 +7741,12 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
     const char *opn = "cp1 cond branch";
     TCGv_i32 t0 = tcg_temp_new_i32();
 
+    if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
+        MIPS_DEBUG("CTI in delay / forbidden slot");
+        generate_exception(ctx, EXCP_RI);
+        goto out;
+    }
+
     if (cc != 0)
         check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
 
@@ -10299,6 +10317,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes)
         save_cpu_state(ctx, 0);
         /* FIXME: Need to clear can_do_io.  */
         switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
+        case MIPS_HFLAG_FBNSLOT:
+            MIPS_DEBUG("forbidden slot");
+            gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
+            break;
         case MIPS_HFLAG_B:
             /* unconditional branch */
             MIPS_DEBUG("unconditional branch");
@@ -15711,56 +15733,56 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
         gen_branch(ctx, 4);
     } else {
         /* Conditional compact branch */
-        int l1 = gen_new_label();
+        int fs = gen_new_label();
         save_cpu_state(ctx, 0);
 
         switch (opc) {
         case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
             if (rs == 0 && rt != 0) {
                 /* OPC_BLEZALC */
-                tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
             } else if (rs != 0 && rt != 0 && rs == rt) {
                 /* OPC_BGEZALC */
-                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
             } else {
                 /* OPC_BGEUC */
-                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
+                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
             }
             break;
         case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
             if (rs == 0 && rt != 0) {
                 /* OPC_BGTZALC */
-                tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
             } else if (rs != 0 && rt != 0 && rs == rt) {
                 /* OPC_BLTZALC */
-                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
             } else {
                 /* OPC_BLTUC */
-                tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
+                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
             }
             break;
         case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
             if (rs == 0 && rt != 0) {
                 /* OPC_BLEZC */
-                tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
             } else if (rs != 0 && rt != 0 && rs == rt) {
                 /* OPC_BGEZC */
-                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
             } else {
                 /* OPC_BGEC */
-                tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
+                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
             }
             break;
         case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
             if (rs == 0 && rt != 0) {
                 /* OPC_BGTZC */
-                tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
             } else if (rs != 0 && rt != 0 && rs == rt) {
                 /* OPC_BLTZC */
-                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
+                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
             } else {
                 /* OPC_BLTC */
-                tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
+                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
             }
             break;
         case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
@@ -15789,10 +15811,10 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
                 tcg_gen_or_tl(t4, t4, input_overflow);
                 if (opc == OPC_BOVC) {
                     /* OPC_BOVC */
-                    tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1);
+                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
                 } else {
                     /* OPC_BNVC */
-                    tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1);
+                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
                 }
                 tcg_temp_free(input_overflow);
                 tcg_temp_free(t4);
@@ -15802,27 +15824,27 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
                 /* OPC_BEQZALC, OPC_BNEZALC */
                 if (opc == OPC_BEQZALC) {
                     /* OPC_BEQZALC */
-                    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
                 } else {
                     /* OPC_BNEZALC */
-                    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
                 }
             } else {
                 /* OPC_BEQC, OPC_BNEC */
                 if (opc == OPC_BEQC) {
                     /* OPC_BEQC */
-                    tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
+                    tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
                 } else {
                     /* OPC_BNEC */
-                    tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
+                    tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
                 }
             }
             break;
         case OPC_BEQZC:
-            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
+            tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
             break;
         case OPC_BNEZC:
-            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
+            tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
             break;
         default:
             MIPS_INVAL("Compact conditional branch/jump");
@@ -15831,12 +15853,11 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
         }
 
         /* Generating branch here as compact branches don't have delay slot */
-        /* TODO: implement forbidden slot */
-        gen_goto_tb(ctx, 1, ctx->pc + 4);
-        gen_set_label(l1);
-        gen_goto_tb(ctx, 0, ctx->btarget);
+        gen_goto_tb(ctx, 1, ctx->btarget);
+        gen_set_label(fs);
+
+        ctx->hflags |= MIPS_HFLAG_FBNSLOT;
         MIPS_DEBUG("Compact conditional branch");
-        ctx->bstate = BS_BRANCH;
     }
 
 out:
@@ -16054,6 +16075,16 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
     op1 = MASK_SPECIAL(ctx->opcode);
     switch (op1) {
     case OPC_SLL:          /* Shift with immediate */
+        if (sa == 5 && rd == 0 &&
+            rs == 0 && rt == 0) { /* PAUSE */
+            if (ctx->insn_flags & ISA_MIPS32R6 &&
+                ctx->hflags & MIPS_HFLAG_BMASK) {
+                MIPS_DEBUG("CTI in delay / forbidden slot");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+        }
+        /* Fallthrough */
     case OPC_SRA:
         gen_shift_imm(ctx, op1, rd, rt, sa);
         break;
@@ -17647,7 +17678,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     int num_insns;
     int max_insns;
     int insn_bytes;
-    int is_delay;
+    int is_slot;
 
     if (search_pc)
         qemu_log("search pc %d\n", search_pc);
@@ -17712,7 +17743,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
 
-        is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
+        is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
         if (!(ctx.hflags & MIPS_HFLAG_M16)) {
             ctx.opcode = cpu_ldl_code(env, ctx.pc);
             insn_bytes = 4;
@@ -17729,7 +17760,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
             break;
         }
 
-        if (is_delay) {
+        if (is_slot) {
             gen_branch(&ctx, insn_bytes);
         }
         ctx.pc += insn_bytes;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0
  2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI Leon Alrae
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot Leon Alrae
@ 2014-07-14 16:19 ` Leon Alrae
  2014-10-17  9:58   ` Yongbok Kim
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers Leon Alrae
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien


Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index a35ab9d..b981ec7 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -789,7 +789,8 @@ static inline void compute_hflags(CPUMIPSState *env)
         }
     }
 #endif
-    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
+    if (((env->CP0_Status & (1 << CP0St_CU0)) &&
+         !(env->insn_flags & ISA_MIPS32R6)) ||
         !(env->hflags & MIPS_HFLAG_KSU)) {
         env->hflags |= MIPS_HFLAG_CP0;
     }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers
  2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
                   ` (2 preceding siblings ...)
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0 Leon Alrae
@ 2014-07-14 16:19 ` Leon Alrae
  2014-10-20 10:19   ` Yongbok Kim
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register Leon Alrae
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU Leon Alrae
  5 siblings, 1 reply; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

In Release 6 not all the values are allowed to be written to a register.
If the value is not valid or unsupported then it should stay unchanged.

For pre-R6 the existing behaviour has been changed only for CP0_Index register
as the current implementation does not seem to be correct - it looks like it
tries to limit the input value but the limit is higher than the actual
number of tlb entries.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/op_helper.c |   63 ++++++++++++++++++++++++++++++++++------------
 1 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 431f3a1..4be435c 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -959,14 +959,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
 
 void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
 {
-    int num = 1;
-    unsigned int tmp = env->tlb->nb_tlb;
-
-    do {
-        tmp >>= 1;
-        num <<= 1;
-    } while (tmp);
-    env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
+    uint32_t index_p = env->CP0_Index & 0x80000000;
+    uint32_t tlb_index = arg1 & 0x7fffffff;
+    if (tlb_index < env->tlb->nb_tlb) {
+        if (env->insn_flags & ISA_MIPS32R6) {
+            index_p |= arg1 & 0x80000000;
+        }
+        env->CP0_Index = index_p | tlb_index;
+    }
 }
 
 void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
@@ -1294,8 +1294,13 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
 
 void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
 {
-    /* 1k pages not implemented */
-    env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
+    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
+    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
+        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
+         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
+         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
+        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
+    }
 }
 
 void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
@@ -1309,7 +1314,13 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
 
 void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
 {
-    env->CP0_Wired = arg1 % env->tlb->nb_tlb;
+    if (env->insn_flags & ISA_MIPS32R6) {
+        if (arg1 < env->tlb->nb_tlb) {
+            env->CP0_Wired = arg1;
+        }
+    } else {
+        env->CP0_Wired = arg1 % env->tlb->nb_tlb;
+    }
 }
 
 void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
@@ -1368,11 +1379,14 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
     }
 
     /* 1k pages not implemented */
-    val = arg1 & mask;
 #if defined(TARGET_MIPS64)
-    val &= env->SEGMask;
+    if ((env->insn_flags & ISA_MIPS32R6) && extract64(arg1, 62, 2) == 0x2) {
+        mask &= ~(0x3ull << 62);
+    }
+    mask &= env->SEGMask;
 #endif
     old = env->CP0_EntryHi;
+    val = (arg1 & mask) | (old & ~mask);
     env->CP0_EntryHi = val;
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
         sync_c0_entryhi(env, env->current_tc);
@@ -1402,6 +1416,13 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
     uint32_t val, old;
     uint32_t mask = env->CP0_Status_rw_bitmask;
 
+    if (env->insn_flags & ISA_MIPS32R6) {
+        if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) {
+            mask &= ~(3 << CP0St_KSU);
+        }
+        mask &= ~(0x00180000 & arg1);
+    }
+
     val = arg1 & mask;
     old = env->CP0_Status;
     env->CP0_Status = (env->CP0_Status & ~mask) | val;
@@ -1457,6 +1478,9 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
     if (cpu->insn_flags & ISA_MIPS32R2) {
         mask |= 1 << CP0Ca_DC;
     }
+    if (cpu->insn_flags & ISA_MIPS32R6) {
+        mask &= ~((1 << CP0Ca_WP) & arg1);
+    }
 
     cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask);
 
@@ -2381,8 +2405,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
         }
         break;
     case 25:
-        if (arg1 & 0xffffff00)
+        if (env->insn_flags & ISA_MIPS32R6 || arg1 & 0xffffff00) {
             return;
+        }
         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
                      ((arg1 & 0x1) << 23);
         break;
@@ -2398,9 +2423,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
                      ((arg1 & 0x4) << 22);
         break;
     case 31:
-        if (arg1 & 0x007c0000)
-            return;
-        env->active_fpu.fcr31 = arg1;
+        if (env->insn_flags & ISA_MIPS32R6) {
+            uint32_t mask = 0xfefc0000;
+            env->active_fpu.fcr31 = (arg1 & ~mask) |
+                (env->active_fpu.fcr31 & mask);
+        } else if (!(arg1 & 0x007c0000)) {
+            env->active_fpu.fcr31 = arg1;
+        }
         break;
     default:
         return;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register
  2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
                   ` (3 preceding siblings ...)
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers Leon Alrae
@ 2014-07-14 16:19 ` Leon Alrae
  2014-10-20 10:49   ` Yongbok Kim
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU Leon Alrae
  5 siblings, 1 reply; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien

Release 6 limits the number of cases where software can cause UNDEFINED or
UNPREDICTABLE behaviour. In this case, when accessing reserved / unimplemented
CP0 register, writes are ignored and reads return 0.

In pre-R6 the behaviour is not specified, but generating RI exception is not
what the real HW does.

Additionally, remove CP0 Random register as it became reserved in Release 6.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/translate.c |  546 +++++++++++++++++++++++------------------------
 1 files changed, 264 insertions(+), 282 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4ed81fe..cd20f35 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -4627,6 +4627,13 @@ static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
     }
 }
 
+#define CP0_CHECK(c)                            \
+    do {                                        \
+        if (!(c)) {                             \
+            goto cp0_unimplemented;             \
+        }                                       \
+    } while (0)
+
 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
@@ -4642,67 +4649,68 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Index";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_mvpcontrol(arg, cpu_env);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_mvpconf0(arg, cpu_env);
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_mvpconf1(arg, cpu_env);
             rn = "MVPConf1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 1:
         switch (sel) {
         case 0:
+            CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
             gen_helper_mfc0_random(arg, cpu_env);
             rn = "Random";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 2:
@@ -4722,42 +4730,42 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcstatus(arg, cpu_env);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcbind(arg, cpu_env);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcrestart(arg, cpu_env);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tchalt(arg, cpu_env);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tccontext(arg, cpu_env);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcschedule(arg, cpu_env);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcschefback(arg, cpu_env);
             rn = "TCScheFBack";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 3:
@@ -4777,7 +4785,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 4:
@@ -4790,20 +4798,16 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //            gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
-            goto die;
+            goto cp0_unimplemented;
 //            break;
         case 2:
-            if (ctx->ulri) {
-                tcg_gen_ld32s_tl(arg, cpu_env,
-                                 offsetof(CPUMIPSState,
-                                          active_tc.CP0_UserLocal));
-                rn = "UserLocal";
-            } else {
-                tcg_gen_movi_tl(arg, 0);
-            }
+            CP0_CHECK(ctx->ulri);
+            tcg_gen_ld32s_tl(arg, cpu_env,
+                             offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+            rn = "UserLocal";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 5:
@@ -4818,7 +4822,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "PageGrain";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 6:
@@ -4853,7 +4857,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSConf4";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 7:
@@ -4864,7 +4868,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "HWREna";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 8:
@@ -4875,25 +4879,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "BadVAddr";
             break;
         case 1:
-            if (ctx->bi) {
-                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
-                                              active_tc.CP0_BadInstr));
-                rn = "BadInstr";
-            } else {
-                gen_mfc0_unimplemented(ctx, arg);
-            }
+            CP0_CHECK(ctx->bi);
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstr));
+            rn = "BadInstr";
             break;
         case 2:
-            if (ctx->bp) {
-                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
-                                              active_tc.CP0_BadInstrP));
-                rn = "BadInstrP";
-            } else {
-                gen_mfc0_unimplemented(ctx, arg);
-            }
+            CP0_CHECK(ctx->bp);
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstrP));
+            rn = "BadInstrP";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 9:
@@ -4913,7 +4911,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 10:
@@ -4924,7 +4922,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 11:
@@ -4935,7 +4933,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 12:
@@ -4960,7 +4958,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSMap";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
        }
         break;
     case 13:
@@ -4970,7 +4968,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Cause";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
        }
         break;
     case 14:
@@ -4981,7 +4979,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 15:
@@ -4996,7 +4994,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EBase";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
        }
         break;
     case 16:
@@ -5035,7 +5033,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Config7";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 17:
@@ -5045,7 +5043,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "LLAddr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 18:
@@ -5055,7 +5053,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 19:
@@ -5065,7 +5063,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 20:
@@ -5079,18 +5077,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
 #endif
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 21:
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
         switch (sel) {
         case 0:
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
             rn = "Framemask";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 22:
@@ -5120,7 +5119,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "TraceBPC";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 24:
@@ -5132,7 +5131,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 25:
@@ -5170,7 +5169,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Performance7";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 26:
@@ -5184,7 +5183,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "CacheErr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 28:
@@ -5204,7 +5203,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DataLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 29:
@@ -5224,7 +5223,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DataHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 30:
@@ -5235,7 +5234,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "ErrorEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 31:
@@ -5246,29 +5245,26 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DESAVE";
             break;
         case 2 ... 7:
-            if (ctx->kscrexist & (1 << sel)) {
-                tcg_gen_ld_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
-                tcg_gen_ext32s_tl(arg, arg);
-                rn = "KScratch";
-            } else {
-                gen_mfc0_unimplemented(ctx, arg);
-            }
+            CP0_CHECK(ctx->kscrexist & (1 << sel));
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            tcg_gen_ext32s_tl(arg, arg);
+            rn = "KScratch";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     default:
-       goto die;
+       goto cp0_unimplemented;
     }
     (void)rn; /* avoid a compiler warning */
     LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
     return;
 
-die:
+cp0_unimplemented:
     LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
-    generate_exception(ctx, EXCP_RI);
+    gen_mfc0_unimplemented(ctx, arg);
 }
 
 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
@@ -5289,22 +5285,22 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Index";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_mvpcontrol(cpu_env, arg);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             /* ignored */
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             /* ignored */
             rn = "MVPConf1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 1:
@@ -5314,42 +5310,42 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Random";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpecontrol(cpu_env, arg);
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpeconf0(cpu_env, arg);
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpeconf1(cpu_env, arg);
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_yqmask(cpu_env, arg);
             rn = "YQMask";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpeopt(cpu_env, arg);
             rn = "VPEOpt";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 2:
@@ -5359,42 +5355,42 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcstatus(cpu_env, arg);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcbind(cpu_env, arg);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcrestart(cpu_env, arg);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tchalt(cpu_env, arg);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tccontext(cpu_env, arg);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcschedule(cpu_env, arg);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcschefback(cpu_env, arg);
             rn = "TCScheFBack";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 3:
@@ -5404,7 +5400,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 4:
@@ -5416,17 +5412,16 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //            gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
-            goto die;
+            goto cp0_unimplemented;
 //            break;
         case 2:
-            if (ctx->ulri) {
-                tcg_gen_st_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
-                rn = "UserLocal";
-            }
+            CP0_CHECK(ctx->ulri);
+            tcg_gen_st_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+            rn = "UserLocal";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 5:
@@ -5441,7 +5436,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "PageGrain";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 6:
@@ -5476,7 +5471,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSConf4";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 7:
@@ -5488,7 +5483,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "HWREna";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 8:
@@ -5506,7 +5501,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "BadInstrP";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 9:
@@ -5517,7 +5512,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 10:
@@ -5527,7 +5522,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 11:
@@ -5538,7 +5533,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 12:
@@ -5573,7 +5568,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSMap";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 13:
@@ -5584,7 +5579,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Cause";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 14:
@@ -5594,7 +5589,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 15:
@@ -5609,7 +5604,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EBase";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 16:
@@ -5656,7 +5651,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         default:
             rn = "Invalid config selector";
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 17:
@@ -5666,7 +5661,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "LLAddr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 18:
@@ -5676,7 +5671,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 19:
@@ -5686,7 +5681,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 20:
@@ -5699,18 +5694,19 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
 #endif
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 21:
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
         switch (sel) {
         case 0:
             gen_helper_mtc0_framemask(cpu_env, arg);
             rn = "Framemask";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 22:
@@ -5753,7 +5749,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "TraceBPC";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 24:
@@ -5764,7 +5760,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 25:
@@ -5802,7 +5798,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Performance7";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
        break;
     case 26:
@@ -5816,7 +5812,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "CacheErr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
        break;
     case 28:
@@ -5836,7 +5832,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DataLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 29:
@@ -5857,7 +5853,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         default:
             rn = "invalid sel";
-            goto die;
+            goto cp0_unimplemented;
         }
        break;
     case 30:
@@ -5867,7 +5863,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "ErrorEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 31:
@@ -5878,20 +5874,19 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DESAVE";
             break;
         case 2 ... 7:
-            if (ctx->kscrexist & (1 << sel)) {
-                tcg_gen_st_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
-                rn = "KScratch";
-            }
+            CP0_CHECK(ctx->kscrexist & (1 << sel));
+            tcg_gen_st_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            rn = "KScratch";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         /* Stop translation as we may have switched the execution mode */
         ctx->bstate = BS_STOP;
         break;
     default:
-       goto die;
+       goto cp0_unimplemented;
     }
     (void)rn; /* avoid a compiler warning */
     LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
@@ -5902,9 +5897,8 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
     }
     return;
 
-die:
+cp0_unimplemented:
     LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
-    generate_exception(ctx, EXCP_RI);
 }
 
 #if defined(TARGET_MIPS64)
@@ -5923,67 +5917,68 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Index";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_mvpcontrol(arg, cpu_env);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_mvpconf0(arg, cpu_env);
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_mvpconf1(arg, cpu_env);
             rn = "MVPConf1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 1:
         switch (sel) {
         case 0:
+            CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
             gen_helper_mfc0_random(arg, cpu_env);
             rn = "Random";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 2:
@@ -5993,42 +5988,42 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcstatus(arg, cpu_env);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mfc0_tcbind(arg, cpu_env);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_dmfc0_tcrestart(arg, cpu_env);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_dmfc0_tchalt(arg, cpu_env);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_dmfc0_tccontext(arg, cpu_env);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_dmfc0_tcschedule(arg, cpu_env);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_dmfc0_tcschefback(arg, cpu_env);
             rn = "TCScheFBack";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 3:
@@ -6038,7 +6033,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 4:
@@ -6050,19 +6045,16 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //            gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
-            goto die;
+            goto cp0_unimplemented;
 //            break;
         case 2:
-            if (ctx->ulri) {
-                tcg_gen_ld_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
-                rn = "UserLocal";
-            } else {
-                tcg_gen_movi_tl(arg, 0);
-            }
+            CP0_CHECK(ctx->ulri);
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+            rn = "UserLocal";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 5:
@@ -6077,7 +6069,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "PageGrain";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 6:
@@ -6112,7 +6104,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSConf4";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 7:
@@ -6123,7 +6115,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "HWREna";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 8:
@@ -6133,25 +6125,19 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "BadVAddr";
             break;
         case 1:
-            if (ctx->bi) {
-                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
-                                              active_tc.CP0_BadInstr));
-                rn = "BadInstr";
-            } else {
-                gen_mfc0_unimplemented(ctx, arg);
-            }
+            CP0_CHECK(ctx->bi);
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstr));
+            rn = "BadInstr";
             break;
         case 2:
-            if (ctx->bp) {
-                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
-                                              active_tc.CP0_BadInstrP));
-                rn = "BadInstrP";
-            } else {
-                gen_mfc0_unimplemented(ctx, arg);
-            }
+            CP0_CHECK(ctx->bp);
+            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
+                                          active_tc.CP0_BadInstrP));
+            rn = "BadInstrP";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 9:
@@ -6171,7 +6157,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 10:
@@ -6181,7 +6167,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 11:
@@ -6192,7 +6178,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 12:
@@ -6217,7 +6203,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSMap";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 13:
@@ -6227,7 +6213,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Cause";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 14:
@@ -6237,7 +6223,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 15:
@@ -6252,7 +6238,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EBase";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 16:
@@ -6291,7 +6277,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Config7";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 17:
@@ -6301,7 +6287,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "LLAddr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 18:
@@ -6311,7 +6297,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 19:
@@ -6321,7 +6307,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 20:
@@ -6332,18 +6318,19 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "XContext";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 21:
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
         switch (sel) {
         case 0:
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
             rn = "Framemask";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 22:
@@ -6373,7 +6360,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "TraceBPC";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 24:
@@ -6384,7 +6371,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 25:
@@ -6422,7 +6409,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Performance7";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 26:
@@ -6437,7 +6424,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "CacheErr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 28:
@@ -6457,7 +6444,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DataLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 29:
@@ -6477,7 +6464,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DataHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 30:
@@ -6487,7 +6474,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "ErrorEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 31:
@@ -6498,28 +6485,25 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DESAVE";
             break;
         case 2 ... 7:
-            if (ctx->kscrexist & (1 << sel)) {
-                tcg_gen_ld_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
-                rn = "KScratch";
-            } else {
-                gen_mfc0_unimplemented(ctx, arg);
-            }
+            CP0_CHECK(ctx->kscrexist & (1 << sel));
+            tcg_gen_ld_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            rn = "KScratch";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     default:
-        goto die;
+        goto cp0_unimplemented;
     }
     (void)rn; /* avoid a compiler warning */
     LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
     return;
 
-die:
+cp0_unimplemented:
     LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
-    generate_exception(ctx, EXCP_RI);
+    gen_mfc0_unimplemented(ctx, arg);
 }
 
 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
@@ -6540,22 +6524,22 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Index";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_mvpcontrol(cpu_env, arg);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             /* ignored */
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             /* ignored */
             rn = "MVPConf1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 1:
@@ -6565,42 +6549,42 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Random";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpecontrol(cpu_env, arg);
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpeconf0(cpu_env, arg);
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpeconf1(cpu_env, arg);
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_yqmask(cpu_env, arg);
             rn = "YQMask";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_vpeopt(cpu_env, arg);
             rn = "VPEOpt";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 2:
@@ -6610,42 +6594,42 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcstatus(cpu_env, arg);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcbind(cpu_env, arg);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcrestart(cpu_env, arg);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tchalt(cpu_env, arg);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tccontext(cpu_env, arg);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcschedule(cpu_env, arg);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(ctx, ASE_MT);
+            CP0_CHECK(ctx->insn_flags & ASE_MT);
             gen_helper_mtc0_tcschefback(cpu_env, arg);
             rn = "TCScheFBack";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 3:
@@ -6655,7 +6639,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryLo1";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 4:
@@ -6667,17 +6651,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //           gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
-            goto die;
+            goto cp0_unimplemented;
 //           break;
         case 2:
-            if (ctx->ulri) {
-                tcg_gen_st_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
-                rn = "UserLocal";
-            }
+            CP0_CHECK(ctx->ulri);
+            tcg_gen_st_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+            rn = "UserLocal";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 5:
@@ -6692,7 +6675,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "PageGrain";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 6:
@@ -6727,7 +6710,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSConf4";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 7:
@@ -6739,7 +6722,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "HWREna";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 8:
@@ -6757,7 +6740,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "BadInstrP";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 9:
@@ -6768,7 +6751,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         /* Stop translation as we may have switched the execution mode */
         ctx->bstate = BS_STOP;
@@ -6780,7 +6763,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EntryHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 11:
@@ -6791,7 +6774,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         /* 6,7 are implementation dependent */
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         /* Stop translation as we may have switched the execution mode */
         ctx->bstate = BS_STOP;
@@ -6828,7 +6811,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "SRSMap";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 13:
@@ -6849,7 +6832,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Cause";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 14:
@@ -6859,7 +6842,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 15:
@@ -6874,7 +6857,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "EBase";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 16:
@@ -6912,7 +6895,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         /* 6,7 are implementation dependent */
         default:
             rn = "Invalid config selector";
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 17:
@@ -6922,7 +6905,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "LLAddr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 18:
@@ -6932,7 +6915,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 19:
@@ -6942,7 +6925,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "WatchHi";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 20:
@@ -6953,18 +6936,19 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "XContext";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 21:
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
         switch (sel) {
         case 0:
             gen_helper_mtc0_framemask(cpu_env, arg);
             rn = "Framemask";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 22:
@@ -7005,7 +6989,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "TraceBPC";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 24:
@@ -7016,7 +7000,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 25:
@@ -7054,7 +7038,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "Performance7";
 //            break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 26:
@@ -7068,7 +7052,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "CacheErr";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 28:
@@ -7088,7 +7072,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DataLo";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 29:
@@ -7109,7 +7093,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             break;
         default:
             rn = "invalid sel";
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 30:
@@ -7119,7 +7103,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "ErrorEPC";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         break;
     case 31:
@@ -7130,20 +7114,19 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             rn = "DESAVE";
             break;
         case 2 ... 7:
-            if (ctx->kscrexist & (1 << sel)) {
-                tcg_gen_st_tl(arg, cpu_env,
-                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
-                rn = "KScratch";
-            }
+            CP0_CHECK(ctx->kscrexist & (1 << sel));
+            tcg_gen_st_tl(arg, cpu_env,
+                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
+            rn = "KScratch";
             break;
         default:
-            goto die;
+            goto cp0_unimplemented;
         }
         /* Stop translation as we may have switched the execution mode */
         ctx->bstate = BS_STOP;
         break;
     default:
-        goto die;
+        goto cp0_unimplemented;
     }
     (void)rn; /* avoid a compiler warning */
     LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
@@ -7154,9 +7137,8 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
     }
     return;
 
-die:
+cp0_unimplemented:
     LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
-    generate_exception(ctx, EXCP_RI);
 }
 #endif /* TARGET_MIPS64 */
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU
  2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
                   ` (4 preceding siblings ...)
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register Leon Alrae
@ 2014-07-14 16:19 ` Leon Alrae
  2014-10-20 14:23   ` Yongbok Kim
  5 siblings, 1 reply; 14+ messages in thread
From: Leon Alrae @ 2014-07-14 16:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: yongbok.kim, cristian.cuna, leon.alrae, aurelien


Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/translate_init.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index bcfc46a..0b70d05 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -519,7 +519,7 @@ static const mips_def_t mips_defs[] =
     },
     {
         /* A generic CPU supporting MIPS64 Release 6 ISA.
-           FIXME: It does not support all the MIPS64R6 features yet.
+           FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
                   Eventually this should be replaced by a real CPU model. */
         .name = "MIPS64R6-generic",
         .CP0_PRid = 0x00010000,
@@ -530,12 +530,19 @@ static const mips_def_t mips_defs[] =
                        (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
                        (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
         .CP0_Config2 = MIPS_CONFIG2,
-        .CP0_Config3 = MIPS_CONFIG3,
+        .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
+                       (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
+        .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
+                       (3 << CP0C4_IE) | (1 << CP0C4_M),
+        .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI),
         .CP0_LLAddr_rw_bitmask = 0,
         .CP0_LLAddr_shift = 0,
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x30D8FFFF,
+        .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
+                         (1U << CP0PG_RIE),
+        .CP0_PageGrain_rw_bitmask = 0,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
                     (0x0 << FCR0_REV),
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI Leon Alrae
@ 2014-10-16 14:32   ` Yongbok Kim
  0 siblings, 0 replies; 14+ messages in thread
From: Yongbok Kim @ 2014-10-16 14:32 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

Please update message body as it also adds dm{f,t}c0 for config{4,5}.
See the comment below.

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok

On 14/07/2014 17:19, Leon Alrae wrote:
> SDBBP instruction Reserved Instruction control. The purpose of this field is
> to restrict availability of SDBBP to kernel mode operation.
>
> If the bit is set then SDBBP instruction can only be executed in kernel mode.
> User execution of SDBBP will cause a Reserved Instruction exception.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h       |   11 +++++++++--
>   target-mips/translate.c |   24 +++++++++++++++++++++++-
>   2 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 23bb22c..2a762d2 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -410,6 +410,7 @@ struct CPUMIPSState {
>   #define CP0C5_CV         29
>   #define CP0C5_EVA        28
>   #define CP0C5_MSAEn      27
> +#define CP0C5_SBRI       6
>   #define CP0C5_UFR        2
>   #define CP0C5_NFExists   0
>       int32_t CP0_Config6;
> @@ -461,7 +462,7 @@ struct CPUMIPSState {
>   #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
>       uint32_t hflags;    /* CPU State */
>       /* TMASK defines different execution modes */
> -#define MIPS_HFLAG_TMASK  0xC07FF
> +#define MIPS_HFLAG_TMASK  0x2C07FF
>   #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
>       /* The KSU flags must be the lowest bits in hflags. The flag order
>          must be the same as defined for CP0 Status. This allows to use
> @@ -504,6 +505,7 @@ struct CPUMIPSState {
>   #define MIPS_HFLAG_DSPR2 0x80000  /* Enable access to MIPS DSPR2 resources. */
>       /* Extra flag about HWREna register. */
>   #define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
> +#define MIPS_HFLAG_SBRI  0x200000 /* R6 SDBBP causes RI excpt. in user mode */

also in supervisor mode. :)

>       target_ulong btarget;        /* Jump / branch target               */
>       target_ulong bcond;          /* Branch condition (if needed)       */
>   
> @@ -759,7 +761,8 @@ static inline void compute_hflags(CPUMIPSState *env)
>   {
>       env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
>                        MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
> -                     MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2);
> +                     MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
> +                     MIPS_HFLAG_SBRI);
>       if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
>           !(env->CP0_Status & (1 << CP0St_ERL)) &&
>           !(env->hflags & MIPS_HFLAG_DM)) {
> @@ -795,6 +798,10 @@ static inline void compute_hflags(CPUMIPSState *env)
>       if (env->CP0_Status & (1 << CP0St_FR)) {
>           env->hflags |= MIPS_HFLAG_F64;
>       }
> +    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
> +        (env->CP0_Config5 & (1 << CP0C5_SBRI))) {
> +        env->hflags |= MIPS_HFLAG_SBRI;
> +    }
>       if (env->insn_flags & ASE_DSPR2) {
>           /* Enables access MIPS DSP resources, now our cpu is DSP ASER2,
>              so enable to access DSPR2 resources. */
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index b931574..d0f695a 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -6273,6 +6273,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
>               rn = "Config3";
>               break;
> +        case 4:
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
> +            rn = "Config4";
> +            break;
> +        case 5:
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
> +            rn = "Config5";
> +            break;
>          /* 6,7 are implementation dependent */
>           case 6:
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
> @@ -6891,6 +6899,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               /* ignored */
>               rn = "Config3";
>               break;
> +        case 4:
> +            /* currently ignored */
> +            rn = "Config4";
> +            break;
> +        case 5:
> +            gen_helper_mtc0_config5(cpu_env, arg);
> +            rn = "Config5";
> +            /* Stop translation as we may have switched the execution mode */
> +            ctx->bstate = BS_STOP;
> +            break;
>           /* 6,7 are implementation dependent */
>           default:
>               rn = "Invalid config selector";
> @@ -15886,7 +15904,11 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
>           }
>           break;
>       case R6_OPC_SDBBP:
> -        generate_exception(ctx, EXCP_DBp);
> +        if (ctx->hflags & MIPS_HFLAG_SBRI) {
> +            generate_exception(ctx, EXCP_RI);
> +        } else {
> +            generate_exception(ctx, EXCP_DBp);
> +        }
>           break;
>   #if defined(TARGET_MIPS64)
>       case OPC_DLSA:

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0 Leon Alrae
@ 2014-10-17  9:58   ` Yongbok Kim
  0 siblings, 0 replies; 14+ messages in thread
From: Yongbok Kim @ 2014-10-17  9:58 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok

On 14/07/2014 17:19, Leon Alrae wrote:
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h |    3 ++-
>   1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index a35ab9d..b981ec7 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -789,7 +789,8 @@ static inline void compute_hflags(CPUMIPSState *env)
>           }
>       }
>   #endif
> -    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
> +    if (((env->CP0_Status & (1 << CP0St_CU0)) &&
> +         !(env->insn_flags & ISA_MIPS32R6)) ||
>           !(env->hflags & MIPS_HFLAG_KSU)) {
>           env->hflags |= MIPS_HFLAG_CP0;
>       }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers Leon Alrae
@ 2014-10-20 10:19   ` Yongbok Kim
  2014-10-21 13:54     ` Leon Alrae
  0 siblings, 1 reply; 14+ messages in thread
From: Yongbok Kim @ 2014-10-20 10:19 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel@nongnu.org; +Cc: aurelien@aurel32.net

[-- Attachment #1: Type: text/plain, Size: 5848 bytes --]

On 14/07/2014 17:19, Leon Alrae wrote:
> In Release 6 not all the values are allowed to be written to a register.
> If the value is not valid or unsupported then it should stay unchanged.
>
> For pre-R6 the existing behaviour has been changed only for CP0_Index register
> as the current implementation does not seem to be correct - it looks like it
> tries to limit the input value but the limit is higher than the actual
> number of tlb entries.
>
> Signed-off-by: Leon Alrae<leon.alrae@imgtec.com>
> ---
>   target-mips/op_helper.c |   63 ++++++++++++++++++++++++++++++++++------------
>   1 files changed, 46 insertions(+), 17 deletions(-)
>
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 431f3a1..4be435c 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -959,14 +959,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
>   
>   void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
>   {
> -    int num = 1;
> -    unsigned int tmp = env->tlb->nb_tlb;
> -
> -    do {
> -        tmp >>= 1;
> -        num <<= 1;
> -    } while (tmp);
> -    env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
> +    uint32_t index_p = env->CP0_Index & 0x80000000;
> +    uint32_t tlb_index = arg1 & 0x7fffffff;
> +    if (tlb_index < env->tlb->nb_tlb) {
> +        if (env->insn_flags & ISA_MIPS32R6) {
> +            index_p |= arg1 & 0x80000000;
> +        }
> +        env->CP0_Index = index_p | tlb_index;
> +    }

Agree to restrict index for pre R6 as well. It is UNDEFINED and software 
shouldn't rely on the undefined behaviour.

>   }
>   
>   void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
> @@ -1294,8 +1294,13 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
>   
>   void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
>   {
> -    /* 1k pages not implemented */

This comment is still valid but it is appeared several times in the code 
already.
Agreed to remove the comment here.

> -    env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
> +    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
> +    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
> +        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
> +         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
> +         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
> +        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
> +    }
>   }
>   
>   void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
> @@ -1309,7 +1314,13 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
>   
>   void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
>   {
> -    env->CP0_Wired = arg1 % env->tlb->nb_tlb;
> +    if (env->insn_flags & ISA_MIPS32R6) {
> +        if (arg1 < env->tlb->nb_tlb) {
> +            env->CP0_Wired = arg1;

Wired field should be compared with Limit field (and as a result, number 
of entries in the TLB).

> +        }
> +    } else {
> +        env->CP0_Wired = arg1 % env->tlb->nb_tlb;
> +    }
>   }
>   
>   void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
> @@ -1368,11 +1379,14 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
>       }
>   
>       /* 1k pages not implemented */
> -    val = arg1 & mask;
>   #if defined(TARGET_MIPS64)
> -    val &= env->SEGMask;
> +    if ((env->insn_flags & ISA_MIPS32R6) && extract64(arg1, 62, 2) == 0x2) {
> +        mask &= ~(0x3ull << 62);

If Config0_AT = 1, R field is restricted for 1 as well.

> +    }
> +    mask &= env->SEGMask;
>   #endif
>       old = env->CP0_EntryHi;
> +    val = (arg1 & mask) | (old & ~mask);
>       env->CP0_EntryHi = val;
>       if (env->CP0_Config3 & (1 << CP0C3_MT)) {
>           sync_c0_entryhi(env, env->current_tc);
> @@ -1402,6 +1416,13 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
>       uint32_t val, old;
>       uint32_t mask = env->CP0_Status_rw_bitmask;
>   
> +    if (env->insn_flags & ISA_MIPS32R6) {
> +        if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) {
> +            mask &= ~(3 << CP0St_KSU);
> +        }
> +        mask &= ~(0x00180000 & arg1);
> +    }
> +
>       val = arg1 & mask;
>       old = env->CP0_Status;
>       env->CP0_Status = (env->CP0_Status & ~mask) | val;
> @@ -1457,6 +1478,9 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
>       if (cpu->insn_flags & ISA_MIPS32R2) {
>           mask |= 1 << CP0Ca_DC;
>       }
> +    if (cpu->insn_flags & ISA_MIPS32R6) {
> +        mask &= ~((1 << CP0Ca_WP) & arg1);
> +    }
>   
>       cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask);
>   
> @@ -2381,8 +2405,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
>           }
>           break;
>       case 25:
> -        if (arg1 & 0xffffff00)
> +        if (env->insn_flags & ISA_MIPS32R6 || arg1 & 0xffffff00) {
>               return;
> +        }
>           env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
>                        ((arg1 & 0x1) << 23);
>           break;
> @@ -2398,9 +2423,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
>                        ((arg1 & 0x4) << 22);
>           break;
>       case 31:
> -        if (arg1 & 0x007c0000)
> -            return;
> -        env->active_fpu.fcr31 = arg1;
> +        if (env->insn_flags & ISA_MIPS32R6) {
> +            uint32_t mask = 0xfefc0000;
> +            env->active_fpu.fcr31 = (arg1 & ~mask) |
> +                (env->active_fpu.fcr31 & mask);
> +        } else if (!(arg1 & 0x007c0000)) {
> +            env->active_fpu.fcr31 = arg1;
> +        }
>           break;
>       default:
>           return;


Regards,
Yongbok


[-- Attachment #2: Type: text/html, Size: 7019 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register Leon Alrae
@ 2014-10-20 10:49   ` Yongbok Kim
  0 siblings, 0 replies; 14+ messages in thread
From: Yongbok Kim @ 2014-10-20 10:49 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

On 14/07/2014 17:19, Leon Alrae wrote:
> Release 6 limits the number of cases where software can cause UNDEFINED or
> UNPREDICTABLE behaviour. In this case, when accessing reserved / unimplemented
> CP0 register, writes are ignored and reads return 0.
>
> In pre-R6 the behaviour is not specified, but generating RI exception is not
> what the real HW does.
>
> Additionally, remove CP0 Random register as it became reserved in Release 6.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/translate.c |  546 +++++++++++++++++++++++------------------------
>   1 files changed, 264 insertions(+), 282 deletions(-)
>
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 4ed81fe..cd20f35 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -4627,6 +4627,13 @@ static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
>       }
>   }
>   
> +#define CP0_CHECK(c)                            \
> +    do {                                        \
> +        if (!(c)) {                             \
> +            goto cp0_unimplemented;             \
> +        }                                       \
> +    } while (0)
> +
>   static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>   {
>       const char *rn = "invalid";
> @@ -4642,67 +4649,68 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Index";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_mvpcontrol(arg, cpu_env);
>               rn = "MVPControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_mvpconf0(arg, cpu_env);
>               rn = "MVPConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_mvpconf1(arg, cpu_env);
>               rn = "MVPConf1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 1:
>           switch (sel) {
>           case 0:
> +            CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
>               gen_helper_mfc0_random(arg, cpu_env);
>               rn = "Random";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
>               rn = "VPEControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
>               rn = "VPEConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
>               rn = "VPEConf1";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
>               rn = "YQMask";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
>               rn = "VPESchedule";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
>               rn = "VPEScheFBack";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
>               rn = "VPEOpt";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 2:
> @@ -4722,42 +4730,42 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo0";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcstatus(arg, cpu_env);
>               rn = "TCStatus";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcbind(arg, cpu_env);
>               rn = "TCBind";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcrestart(arg, cpu_env);
>               rn = "TCRestart";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tchalt(arg, cpu_env);
>               rn = "TCHalt";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tccontext(arg, cpu_env);
>               rn = "TCContext";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcschedule(arg, cpu_env);
>               rn = "TCSchedule";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcschefback(arg, cpu_env);
>               rn = "TCScheFBack";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 3:
> @@ -4777,7 +4785,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 4:
> @@ -4790,20 +4798,16 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           case 1:
>   //            gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
>               rn = "ContextConfig";
> -            goto die;
> +            goto cp0_unimplemented;
>   //            break;
>           case 2:
> -            if (ctx->ulri) {
> -                tcg_gen_ld32s_tl(arg, cpu_env,
> -                                 offsetof(CPUMIPSState,
> -                                          active_tc.CP0_UserLocal));
> -                rn = "UserLocal";
> -            } else {
> -                tcg_gen_movi_tl(arg, 0);
> -            }
> +            CP0_CHECK(ctx->ulri);
> +            tcg_gen_ld32s_tl(arg, cpu_env,
> +                             offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> +            rn = "UserLocal";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 5:
> @@ -4818,7 +4822,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "PageGrain";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 6:
> @@ -4853,7 +4857,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSConf4";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 7:
> @@ -4864,7 +4868,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "HWREna";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 8:
> @@ -4875,25 +4879,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "BadVAddr";
>               break;
>           case 1:
> -            if (ctx->bi) {
> -                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> -                                              active_tc.CP0_BadInstr));
> -                rn = "BadInstr";
> -            } else {
> -                gen_mfc0_unimplemented(ctx, arg);
> -            }
> +            CP0_CHECK(ctx->bi);
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstr));
> +            rn = "BadInstr";
>               break;
>           case 2:
> -            if (ctx->bp) {
> -                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> -                                              active_tc.CP0_BadInstrP));
> -                rn = "BadInstrP";
> -            } else {
> -                gen_mfc0_unimplemented(ctx, arg);
> -            }
> +            CP0_CHECK(ctx->bp);
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstrP));
> +            rn = "BadInstrP";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 9:
> @@ -4913,7 +4911,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 10:
> @@ -4924,7 +4922,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 11:
> @@ -4935,7 +4933,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 12:
> @@ -4960,7 +4958,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSMap";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>          }
>           break;
>       case 13:
> @@ -4970,7 +4968,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Cause";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>          }
>           break;
>       case 14:
> @@ -4981,7 +4979,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 15:
> @@ -4996,7 +4994,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EBase";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>          }
>           break;
>       case 16:
> @@ -5035,7 +5033,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Config7";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 17:
> @@ -5045,7 +5043,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "LLAddr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 18:
> @@ -5055,7 +5053,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 19:
> @@ -5065,7 +5063,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 20:
> @@ -5079,18 +5077,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>   #endif
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 21:
>          /* Officially reserved, but sel 0 is used for R1x000 framemask */
> +        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
>           switch (sel) {
>           case 0:
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
>               rn = "Framemask";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 22:
> @@ -5120,7 +5119,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "TraceBPC";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 24:
> @@ -5132,7 +5131,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 25:
> @@ -5170,7 +5169,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Performance7";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 26:
> @@ -5184,7 +5183,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "CacheErr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 28:
> @@ -5204,7 +5203,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DataLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 29:
> @@ -5224,7 +5223,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DataHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 30:
> @@ -5235,7 +5234,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "ErrorEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 31:
> @@ -5246,29 +5245,26 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DESAVE";
>               break;
>           case 2 ... 7:
> -            if (ctx->kscrexist & (1 << sel)) {
> -                tcg_gen_ld_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> -                tcg_gen_ext32s_tl(arg, arg);
> -                rn = "KScratch";
> -            } else {
> -                gen_mfc0_unimplemented(ctx, arg);
> -            }
> +            CP0_CHECK(ctx->kscrexist & (1 << sel));
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            tcg_gen_ext32s_tl(arg, arg);
> +            rn = "KScratch";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       default:
> -       goto die;
> +       goto cp0_unimplemented;
>       }
>       (void)rn; /* avoid a compiler warning */
>       LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
>       return;
>   
> -die:
> +cp0_unimplemented:
>       LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
> -    generate_exception(ctx, EXCP_RI);
> +    gen_mfc0_unimplemented(ctx, arg);
>   }
>   
>   static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
> @@ -5289,22 +5285,22 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Index";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_mvpcontrol(cpu_env, arg);
>               rn = "MVPControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               /* ignored */
>               rn = "MVPConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               /* ignored */
>               rn = "MVPConf1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 1:
> @@ -5314,42 +5310,42 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Random";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpecontrol(cpu_env, arg);
>               rn = "VPEControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpeconf0(cpu_env, arg);
>               rn = "VPEConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpeconf1(cpu_env, arg);
>               rn = "VPEConf1";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_yqmask(cpu_env, arg);
>               rn = "YQMask";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
>               rn = "VPESchedule";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
>               rn = "VPEScheFBack";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpeopt(cpu_env, arg);
>               rn = "VPEOpt";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 2:
> @@ -5359,42 +5355,42 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo0";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcstatus(cpu_env, arg);
>               rn = "TCStatus";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcbind(cpu_env, arg);
>               rn = "TCBind";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcrestart(cpu_env, arg);
>               rn = "TCRestart";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tchalt(cpu_env, arg);
>               rn = "TCHalt";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tccontext(cpu_env, arg);
>               rn = "TCContext";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcschedule(cpu_env, arg);
>               rn = "TCSchedule";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcschefback(cpu_env, arg);
>               rn = "TCScheFBack";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 3:
> @@ -5404,7 +5400,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 4:
> @@ -5416,17 +5412,16 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           case 1:
>   //            gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
>               rn = "ContextConfig";
> -            goto die;
> +            goto cp0_unimplemented;
>   //            break;
>           case 2:
> -            if (ctx->ulri) {
> -                tcg_gen_st_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> -                rn = "UserLocal";
> -            }
> +            CP0_CHECK(ctx->ulri);
> +            tcg_gen_st_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> +            rn = "UserLocal";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 5:
> @@ -5441,7 +5436,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "PageGrain";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 6:
> @@ -5476,7 +5471,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSConf4";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 7:
> @@ -5488,7 +5483,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "HWREna";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 8:
> @@ -5506,7 +5501,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "BadInstrP";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 9:
> @@ -5517,7 +5512,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 10:
> @@ -5527,7 +5522,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 11:
> @@ -5538,7 +5533,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 12:
> @@ -5573,7 +5568,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSMap";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 13:
> @@ -5584,7 +5579,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Cause";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 14:
> @@ -5594,7 +5589,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 15:
> @@ -5609,7 +5604,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EBase";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 16:
> @@ -5656,7 +5651,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           default:
>               rn = "Invalid config selector";
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 17:
> @@ -5666,7 +5661,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "LLAddr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 18:
> @@ -5676,7 +5671,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 19:
> @@ -5686,7 +5681,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 20:
> @@ -5699,18 +5694,19 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>   #endif
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 21:
>          /* Officially reserved, but sel 0 is used for R1x000 framemask */
> +        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
>           switch (sel) {
>           case 0:
>               gen_helper_mtc0_framemask(cpu_env, arg);
>               rn = "Framemask";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 22:
> @@ -5753,7 +5749,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "TraceBPC";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 24:
> @@ -5764,7 +5760,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 25:
> @@ -5802,7 +5798,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Performance7";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>          break;
>       case 26:
> @@ -5816,7 +5812,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "CacheErr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>          break;
>       case 28:
> @@ -5836,7 +5832,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DataLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 29:
> @@ -5857,7 +5853,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           default:
>               rn = "invalid sel";
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>          break;
>       case 30:
> @@ -5867,7 +5863,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "ErrorEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 31:
> @@ -5878,20 +5874,19 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DESAVE";
>               break;
>           case 2 ... 7:
> -            if (ctx->kscrexist & (1 << sel)) {
> -                tcg_gen_st_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> -                rn = "KScratch";
> -            }
> +            CP0_CHECK(ctx->kscrexist & (1 << sel));
> +            tcg_gen_st_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            rn = "KScratch";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           /* Stop translation as we may have switched the execution mode */
>           ctx->bstate = BS_STOP;
>           break;
>       default:
> -       goto die;
> +       goto cp0_unimplemented;
>       }
>       (void)rn; /* avoid a compiler warning */
>       LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
> @@ -5902,9 +5897,8 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>       }
>       return;
>   
> -die:
> +cp0_unimplemented:
>       LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
> -    generate_exception(ctx, EXCP_RI);
>   }
>   
>   #if defined(TARGET_MIPS64)
> @@ -5923,67 +5917,68 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Index";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_mvpcontrol(arg, cpu_env);
>               rn = "MVPControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_mvpconf0(arg, cpu_env);
>               rn = "MVPConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_mvpconf1(arg, cpu_env);
>               rn = "MVPConf1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 1:
>           switch (sel) {
>           case 0:
> +            CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
>               gen_helper_mfc0_random(arg, cpu_env);
>               rn = "Random";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
>               rn = "VPEControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
>               rn = "VPEConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
>               rn = "VPEConf1";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
>               rn = "YQMask";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
>               rn = "VPESchedule";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
>               rn = "VPEScheFBack";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
>               rn = "VPEOpt";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 2:
> @@ -5993,42 +5988,42 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo0";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcstatus(arg, cpu_env);
>               rn = "TCStatus";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mfc0_tcbind(arg, cpu_env);
>               rn = "TCBind";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_dmfc0_tcrestart(arg, cpu_env);
>               rn = "TCRestart";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_dmfc0_tchalt(arg, cpu_env);
>               rn = "TCHalt";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_dmfc0_tccontext(arg, cpu_env);
>               rn = "TCContext";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_dmfc0_tcschedule(arg, cpu_env);
>               rn = "TCSchedule";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_dmfc0_tcschefback(arg, cpu_env);
>               rn = "TCScheFBack";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 3:
> @@ -6038,7 +6033,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 4:
> @@ -6050,19 +6045,16 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           case 1:
>   //            gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
>               rn = "ContextConfig";
> -            goto die;
> +            goto cp0_unimplemented;
>   //            break;
>           case 2:
> -            if (ctx->ulri) {
> -                tcg_gen_ld_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> -                rn = "UserLocal";
> -            } else {
> -                tcg_gen_movi_tl(arg, 0);
> -            }
> +            CP0_CHECK(ctx->ulri);
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> +            rn = "UserLocal";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 5:
> @@ -6077,7 +6069,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "PageGrain";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 6:
> @@ -6112,7 +6104,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSConf4";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 7:
> @@ -6123,7 +6115,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "HWREna";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 8:
> @@ -6133,25 +6125,19 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "BadVAddr";
>               break;
>           case 1:
> -            if (ctx->bi) {
> -                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> -                                              active_tc.CP0_BadInstr));
> -                rn = "BadInstr";
> -            } else {
> -                gen_mfc0_unimplemented(ctx, arg);
> -            }
> +            CP0_CHECK(ctx->bi);
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstr));
> +            rn = "BadInstr";
>               break;
>           case 2:
> -            if (ctx->bp) {
> -                gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> -                                              active_tc.CP0_BadInstrP));
> -                rn = "BadInstrP";
> -            } else {
> -                gen_mfc0_unimplemented(ctx, arg);
> -            }
> +            CP0_CHECK(ctx->bp);
> +            gen_mfc0_load32(arg, offsetof(CPUMIPSState,
> +                                          active_tc.CP0_BadInstrP));
> +            rn = "BadInstrP";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 9:
> @@ -6171,7 +6157,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 10:
> @@ -6181,7 +6167,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 11:
> @@ -6192,7 +6178,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 12:
> @@ -6217,7 +6203,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSMap";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 13:
> @@ -6227,7 +6213,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Cause";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 14:
> @@ -6237,7 +6223,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 15:
> @@ -6252,7 +6238,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EBase";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 16:
> @@ -6291,7 +6277,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Config7";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 17:
> @@ -6301,7 +6287,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "LLAddr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 18:
> @@ -6311,7 +6297,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 19:
> @@ -6321,7 +6307,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 20:
> @@ -6332,18 +6318,19 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "XContext";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 21:
>          /* Officially reserved, but sel 0 is used for R1x000 framemask */
> +        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
>           switch (sel) {
>           case 0:
>               gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
>               rn = "Framemask";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 22:
> @@ -6373,7 +6360,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "TraceBPC";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 24:
> @@ -6384,7 +6371,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 25:
> @@ -6422,7 +6409,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Performance7";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 26:
> @@ -6437,7 +6424,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "CacheErr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 28:
> @@ -6457,7 +6444,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DataLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 29:
> @@ -6477,7 +6464,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DataHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 30:
> @@ -6487,7 +6474,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "ErrorEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 31:
> @@ -6498,28 +6485,25 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DESAVE";
>               break;
>           case 2 ... 7:
> -            if (ctx->kscrexist & (1 << sel)) {
> -                tcg_gen_ld_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> -                rn = "KScratch";
> -            } else {
> -                gen_mfc0_unimplemented(ctx, arg);
> -            }
> +            CP0_CHECK(ctx->kscrexist & (1 << sel));
> +            tcg_gen_ld_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            rn = "KScratch";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       default:
> -        goto die;
> +        goto cp0_unimplemented;
>       }
>       (void)rn; /* avoid a compiler warning */
>       LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
>       return;
>   
> -die:
> +cp0_unimplemented:
>       LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
> -    generate_exception(ctx, EXCP_RI);
> +    gen_mfc0_unimplemented(ctx, arg);
>   }
>   
>   static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
> @@ -6540,22 +6524,22 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Index";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_mvpcontrol(cpu_env, arg);
>               rn = "MVPControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               /* ignored */
>               rn = "MVPConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               /* ignored */
>               rn = "MVPConf1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 1:
> @@ -6565,42 +6549,42 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Random";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpecontrol(cpu_env, arg);
>               rn = "VPEControl";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpeconf0(cpu_env, arg);
>               rn = "VPEConf0";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpeconf1(cpu_env, arg);
>               rn = "VPEConf1";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_yqmask(cpu_env, arg);
>               rn = "YQMask";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
>               rn = "VPESchedule";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
>               rn = "VPEScheFBack";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_vpeopt(cpu_env, arg);
>               rn = "VPEOpt";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 2:
> @@ -6610,42 +6594,42 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo0";
>               break;
>           case 1:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcstatus(cpu_env, arg);
>               rn = "TCStatus";
>               break;
>           case 2:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcbind(cpu_env, arg);
>               rn = "TCBind";
>               break;
>           case 3:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcrestart(cpu_env, arg);
>               rn = "TCRestart";
>               break;
>           case 4:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tchalt(cpu_env, arg);
>               rn = "TCHalt";
>               break;
>           case 5:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tccontext(cpu_env, arg);
>               rn = "TCContext";
>               break;
>           case 6:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcschedule(cpu_env, arg);
>               rn = "TCSchedule";
>               break;
>           case 7:
> -            check_insn(ctx, ASE_MT);
> +            CP0_CHECK(ctx->insn_flags & ASE_MT);
>               gen_helper_mtc0_tcschefback(cpu_env, arg);
>               rn = "TCScheFBack";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 3:
> @@ -6655,7 +6639,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryLo1";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 4:
> @@ -6667,17 +6651,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           case 1:
>   //           gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
>               rn = "ContextConfig";
> -            goto die;
> +            goto cp0_unimplemented;
>   //           break;
>           case 2:
> -            if (ctx->ulri) {
> -                tcg_gen_st_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> -                rn = "UserLocal";
> -            }
> +            CP0_CHECK(ctx->ulri);
> +            tcg_gen_st_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
> +            rn = "UserLocal";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 5:
> @@ -6692,7 +6675,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "PageGrain";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 6:
> @@ -6727,7 +6710,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSConf4";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 7:
> @@ -6739,7 +6722,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "HWREna";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 8:
> @@ -6757,7 +6740,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "BadInstrP";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 9:
> @@ -6768,7 +6751,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           /* Stop translation as we may have switched the execution mode */
>           ctx->bstate = BS_STOP;
> @@ -6780,7 +6763,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EntryHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 11:
> @@ -6791,7 +6774,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           /* 6,7 are implementation dependent */
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           /* Stop translation as we may have switched the execution mode */
>           ctx->bstate = BS_STOP;
> @@ -6828,7 +6811,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "SRSMap";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 13:
> @@ -6849,7 +6832,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Cause";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 14:
> @@ -6859,7 +6842,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 15:
> @@ -6874,7 +6857,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "EBase";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 16:
> @@ -6912,7 +6895,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>           /* 6,7 are implementation dependent */
>           default:
>               rn = "Invalid config selector";
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 17:
> @@ -6922,7 +6905,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "LLAddr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 18:
> @@ -6932,7 +6915,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 19:
> @@ -6942,7 +6925,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "WatchHi";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 20:
> @@ -6953,18 +6936,19 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "XContext";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 21:
>          /* Officially reserved, but sel 0 is used for R1x000 framemask */
> +        CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
>           switch (sel) {
>           case 0:
>               gen_helper_mtc0_framemask(cpu_env, arg);
>               rn = "Framemask";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 22:
> @@ -7005,7 +6989,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "TraceBPC";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 24:
> @@ -7016,7 +7000,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 25:
> @@ -7054,7 +7038,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "Performance7";
>   //            break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 26:
> @@ -7068,7 +7052,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "CacheErr";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 28:
> @@ -7088,7 +7072,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DataLo";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 29:
> @@ -7109,7 +7093,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               break;
>           default:
>               rn = "invalid sel";
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 30:
> @@ -7119,7 +7103,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "ErrorEPC";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           break;
>       case 31:
> @@ -7130,20 +7114,19 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>               rn = "DESAVE";
>               break;
>           case 2 ... 7:
> -            if (ctx->kscrexist & (1 << sel)) {
> -                tcg_gen_st_tl(arg, cpu_env,
> -                              offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> -                rn = "KScratch";
> -            }
> +            CP0_CHECK(ctx->kscrexist & (1 << sel));
> +            tcg_gen_st_tl(arg, cpu_env,
> +                          offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
> +            rn = "KScratch";
>               break;
>           default:
> -            goto die;
> +            goto cp0_unimplemented;
>           }
>           /* Stop translation as we may have switched the execution mode */
>           ctx->bstate = BS_STOP;
>           break;
>       default:
> -        goto die;
> +        goto cp0_unimplemented;
>       }
>       (void)rn; /* avoid a compiler warning */
>       LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
> @@ -7154,9 +7137,8 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>       }
>       return;
>   
> -die:
> +cp0_unimplemented:
>       LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
> -    generate_exception(ctx, EXCP_RI);
>   }
>   #endif /* TARGET_MIPS64 */
>   

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot Leon Alrae
@ 2014-10-20 11:10   ` Yongbok Kim
  0 siblings, 0 replies; 14+ messages in thread
From: Yongbok Kim @ 2014-10-20 11:10 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

On 14/07/2014 17:19, Leon Alrae wrote:
> When conditional compact branch is encountered decode one more instruction in
> current translation block - that will be forbidden slot. Instruction in
> forbidden slot will be executed only if conditional compact branch is not taken.
>
> Any control transfer instruction (CTI) which are branches, jumps, ERET,
> DERET, WAIT and PAUSE will generate RI exception if executed in forbidden or
> delay slot.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h       |    5 ++-
>   target-mips/translate.c |   89 +++++++++++++++++++++++++++++++---------------
>   2 files changed, 63 insertions(+), 31 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 2a762d2..a35ab9d 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -462,7 +462,7 @@ struct CPUMIPSState {
>   #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
>       uint32_t hflags;    /* CPU State */
>       /* TMASK defines different execution modes */
> -#define MIPS_HFLAG_TMASK  0x2C07FF
> +#define MIPS_HFLAG_TMASK  0x6C07FF
>   #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
>       /* The KSU flags must be the lowest bits in hflags. The flag order
>          must be the same as defined for CP0 Status. This allows to use
> @@ -488,7 +488,7 @@ struct CPUMIPSState {
>        * the delay slot, record what type of branch it is so that we can
>        * resume translation properly.  It might be possible to reduce
>        * this from three bits to two.  */
> -#define MIPS_HFLAG_BMASK_BASE  0x03800
> +#define MIPS_HFLAG_BMASK_BASE  0x403800
>   #define MIPS_HFLAG_B      0x00800 /* Unconditional branch               */
>   #define MIPS_HFLAG_BC     0x01000 /* Conditional branch                 */
>   #define MIPS_HFLAG_BL     0x01800 /* Likely branch                      */
> @@ -506,6 +506,7 @@ struct CPUMIPSState {
>       /* Extra flag about HWREna register. */
>   #define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
>   #define MIPS_HFLAG_SBRI  0x200000 /* R6 SDBBP causes RI excpt. in user mode */
> +#define MIPS_HFLAG_FBNSLOT 0x400000 /* Forbidden slot                   */
>       target_ulong btarget;        /* Jump / branch target               */
>       target_ulong bcond;          /* Branch condition (if needed)       */
>   
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index d0f695a..4ed81fe 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -7686,12 +7686,20 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
>       case OPC_ERET:
>           opn = "eret";
>           check_insn(ctx, ISA_MIPS2);
> +        if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
> +            MIPS_DEBUG("CTI in delay / forbidden slot");
> +            goto die;
> +        }
>           gen_helper_eret(cpu_env);
>           ctx->bstate = BS_EXCP;
>           break;
>       case OPC_DERET:
>           opn = "deret";
>           check_insn(ctx, ISA_MIPS32);
> +        if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
> +            MIPS_DEBUG("CTI in delay / forbidden slot");
> +            goto die;
> +        }
>           if (!(ctx->hflags & MIPS_HFLAG_DM)) {
>               MIPS_INVAL(opn);
>               generate_exception(ctx, EXCP_RI);
> @@ -7703,6 +7711,10 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
>       case OPC_WAIT:
>           opn = "wait";
>           check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
> +        if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
> +            MIPS_DEBUG("CTI in delay / forbidden slot");
> +            goto die;
> +        }
>           /* If we get an exception, we want to restart at next instruction */
>           ctx->pc += 4;
>           save_cpu_state(ctx, 1);
> @@ -7729,6 +7741,12 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
>       const char *opn = "cp1 cond branch";
>       TCGv_i32 t0 = tcg_temp_new_i32();
>   
> +    if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
> +        MIPS_DEBUG("CTI in delay / forbidden slot");
> +        generate_exception(ctx, EXCP_RI);
> +        goto out;
> +    }
> +
>       if (cc != 0)
>           check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
>   
> @@ -10299,6 +10317,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes)
>           save_cpu_state(ctx, 0);
>           /* FIXME: Need to clear can_do_io.  */
>           switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
> +        case MIPS_HFLAG_FBNSLOT:
> +            MIPS_DEBUG("forbidden slot");
> +            gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
> +            break;
>           case MIPS_HFLAG_B:
>               /* unconditional branch */
>               MIPS_DEBUG("unconditional branch");
> @@ -15711,56 +15733,56 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
>           gen_branch(ctx, 4);
>       } else {
>           /* Conditional compact branch */
> -        int l1 = gen_new_label();
> +        int fs = gen_new_label();
>           save_cpu_state(ctx, 0);
>   
>           switch (opc) {
>           case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
>               if (rs == 0 && rt != 0) {
>                   /* OPC_BLEZALC */
> -                tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
>               } else if (rs != 0 && rt != 0 && rs == rt) {
>                   /* OPC_BGEZALC */
> -                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
>               } else {
>                   /* OPC_BGEUC */
> -                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
> +                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
>               }
>               break;
>           case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
>               if (rs == 0 && rt != 0) {
>                   /* OPC_BGTZALC */
> -                tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
>               } else if (rs != 0 && rt != 0 && rs == rt) {
>                   /* OPC_BLTZALC */
> -                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
>               } else {
>                   /* OPC_BLTUC */
> -                tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
> +                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
>               }
>               break;
>           case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
>               if (rs == 0 && rt != 0) {
>                   /* OPC_BLEZC */
> -                tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
>               } else if (rs != 0 && rt != 0 && rs == rt) {
>                   /* OPC_BGEZC */
> -                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
>               } else {
>                   /* OPC_BGEC */
> -                tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
> +                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
>               }
>               break;
>           case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
>               if (rs == 0 && rt != 0) {
>                   /* OPC_BGTZC */
> -                tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
>               } else if (rs != 0 && rt != 0 && rs == rt) {
>                   /* OPC_BLTZC */
> -                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
> +                tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
>               } else {
>                   /* OPC_BLTC */
> -                tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
> +                tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
>               }
>               break;
>           case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
> @@ -15789,10 +15811,10 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
>                   tcg_gen_or_tl(t4, t4, input_overflow);
>                   if (opc == OPC_BOVC) {
>                       /* OPC_BOVC */
> -                    tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1);
> +                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
>                   } else {
>                       /* OPC_BNVC */
> -                    tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1);
> +                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
>                   }
>                   tcg_temp_free(input_overflow);
>                   tcg_temp_free(t4);
> @@ -15802,27 +15824,27 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
>                   /* OPC_BEQZALC, OPC_BNEZALC */
>                   if (opc == OPC_BEQZALC) {
>                       /* OPC_BEQZALC */
> -                    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
> +                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
>                   } else {
>                       /* OPC_BNEZALC */
> -                    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
> +                    tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
>                   }
>               } else {
>                   /* OPC_BEQC, OPC_BNEC */
>                   if (opc == OPC_BEQC) {
>                       /* OPC_BEQC */
> -                    tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
> +                    tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
>                   } else {
>                       /* OPC_BNEC */
> -                    tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
> +                    tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
>                   }
>               }
>               break;
>           case OPC_BEQZC:
> -            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
> +            tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
>               break;
>           case OPC_BNEZC:
> -            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
> +            tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
>               break;
>           default:
>               MIPS_INVAL("Compact conditional branch/jump");
> @@ -15831,12 +15853,11 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
>           }
>   
>           /* Generating branch here as compact branches don't have delay slot */
> -        /* TODO: implement forbidden slot */
> -        gen_goto_tb(ctx, 1, ctx->pc + 4);
> -        gen_set_label(l1);
> -        gen_goto_tb(ctx, 0, ctx->btarget);
> +        gen_goto_tb(ctx, 1, ctx->btarget);
> +        gen_set_label(fs);
> +
> +        ctx->hflags |= MIPS_HFLAG_FBNSLOT;
>           MIPS_DEBUG("Compact conditional branch");
> -        ctx->bstate = BS_BRANCH;
>       }
>   
>   out:
> @@ -16054,6 +16075,16 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
>       op1 = MASK_SPECIAL(ctx->opcode);
>       switch (op1) {
>       case OPC_SLL:          /* Shift with immediate */
> +        if (sa == 5 && rd == 0 &&
> +            rs == 0 && rt == 0) { /* PAUSE */
> +            if (ctx->insn_flags & ISA_MIPS32R6 &&
> +                ctx->hflags & MIPS_HFLAG_BMASK) {
> +                MIPS_DEBUG("CTI in delay / forbidden slot");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +        }
> +        /* Fallthrough */
>       case OPC_SRA:
>           gen_shift_imm(ctx, op1, rd, rt, sa);
>           break;
> @@ -17647,7 +17678,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>       int num_insns;
>       int max_insns;
>       int insn_bytes;
> -    int is_delay;
> +    int is_slot;
>   
>       if (search_pc)
>           qemu_log("search pc %d\n", search_pc);
> @@ -17712,7 +17743,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>           if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
>               gen_io_start();
>   
> -        is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
> +        is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
>           if (!(ctx.hflags & MIPS_HFLAG_M16)) {
>               ctx.opcode = cpu_ldl_code(env, ctx.pc);
>               insn_bytes = 4;
> @@ -17729,7 +17760,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>               break;
>           }
>   
> -        if (is_delay) {
> +        if (is_slot) {
>               gen_branch(&ctx, insn_bytes);
>           }
>           ctx.pc += insn_bytes;


Comments on 4155 , 7839 and 15616  are also required changes to indicate 
it might be delay or forbidden slot.

Otherwise,
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU
  2014-07-14 16:19 ` [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU Leon Alrae
@ 2014-10-20 14:23   ` Yongbok Kim
  0 siblings, 0 replies; 14+ messages in thread
From: Yongbok Kim @ 2014-10-20 14:23 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

On 14/07/2014 17:19, Leon Alrae wrote:
> Signed-off-by: Leon Alrae<leon.alrae@imgtec.com>
> ---
>   target-mips/translate_init.c |   11 +++++++++--
>   1 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
> index bcfc46a..0b70d05 100644
> --- a/target-mips/translate_init.c
> +++ b/target-mips/translate_init.c
> @@ -519,7 +519,7 @@ static const mips_def_t mips_defs[] =
>       },
>       {
>           /* A generic CPU supporting MIPS64 Release 6 ISA.
> -           FIXME: It does not support all the MIPS64R6 features yet.
> +           FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
>                     Eventually this should be replaced by a real CPU model. */
>           .name = "MIPS64R6-generic",
>           .CP0_PRid = 0x00010000,
> @@ -530,12 +530,19 @@ static const mips_def_t mips_defs[] =
>                          (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
>                          (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
>           .CP0_Config2 = MIPS_CONFIG2,
> -        .CP0_Config3 = MIPS_CONFIG3,
> +        .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
> +                       (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
> +        .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
> +                       (3 << CP0C4_IE) | (1 << CP0C4_M),
> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI),
>           .CP0_LLAddr_rw_bitmask = 0,
>           .CP0_LLAddr_shift = 0,
>           .SYNCI_Step = 32,
>           .CCRes = 2,
>           .CP0_Status_rw_bitmask = 0x30D8FFFF,
> +        .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
> +                         (1U << CP0PG_RIE),
> +        .CP0_PageGrain_rw_bitmask = 0,
>           .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
>                       (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
>                       (0x0 << FCR0_REV),

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers
  2014-10-20 10:19   ` Yongbok Kim
@ 2014-10-21 13:54     ` Leon Alrae
  0 siblings, 0 replies; 14+ messages in thread
From: Leon Alrae @ 2014-10-21 13:54 UTC (permalink / raw)
  To: Yongbok Kim, qemu-devel@nongnu.org; +Cc: aurelien@aurel32.net

On 20/10/2014 11:19, Yongbok Kim wrote:
>>  void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
>>  {
>> -    env->CP0_Wired = arg1 % env->tlb->nb_tlb;
>> +    if (env->insn_flags & ISA_MIPS32R6) {
>> +        if (arg1 < env->tlb->nb_tlb) {
>> +            env->CP0_Wired = arg1;
> 
> Wired field should be compared with Limit field (and as a result, number
> of entries in the TLB).

>From spec's point of view the implementation is correct. It supports
"Limit = 0" - maximum number of wired entries is equal to the number of
TLB entries minus one. Obviously we will have to add Limit field once we
decide to support Limit > 0.

> 
>> +        }
>> +    } else {
>> +        env->CP0_Wired = arg1 % env->tlb->nb_tlb;
>> +    }
>>  }
>>  
>>  void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
>> @@ -1368,11 +1379,14 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
>>      }
>>  
>>      /* 1k pages not implemented */
>> -    val = arg1 & mask;
>>  #if defined(TARGET_MIPS64)
>> -    val &= env->SEGMask;
>> +    if ((env->insn_flags & ISA_MIPS32R6) && extract64(arg1, 62, 2) == 0x2) {
>> +        mask &= ~(0x3ull << 62);
> 
> If Config0_AT = 1, R field is restricted for 1 as well.

Good spot, thanks.

Regards,
Leon

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-10-21 13:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-14 16:19 [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features Leon Alrae
2014-07-14 16:19 ` [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI Leon Alrae
2014-10-16 14:32   ` Yongbok Kim
2014-07-14 16:19 ` [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot Leon Alrae
2014-10-20 11:10   ` Yongbok Kim
2014-07-14 16:19 ` [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0 Leon Alrae
2014-10-17  9:58   ` Yongbok Kim
2014-07-14 16:19 ` [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers Leon Alrae
2014-10-20 10:19   ` Yongbok Kim
2014-10-21 13:54     ` Leon Alrae
2014-07-14 16:19 ` [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register Leon Alrae
2014-10-20 10:49   ` Yongbok Kim
2014-07-14 16:19 ` [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU Leon Alrae
2014-10-20 14:23   ` Yongbok Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).