diff options
author | Leon Alrae <leon.alrae@imgtec.com> | 2014-07-11 16:11:35 +0100 |
---|---|---|
committer | Leon Alrae <leon.alrae@imgtec.com> | 2014-11-03 11:48:34 +0000 |
commit | f31b035a9f10dc9b57f01c426110af845d453ce2 (patch) | |
tree | ed772e97f451b594713583a7ce103dbe76638fef /target-mips | |
parent | ba801af429aaa68f6cc03842c8b6be81a6ede65a (diff) |
target-mips: correctly handle access to unimplemented CP0 register
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>
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/translate.c | 538 |
1 files changed, 260 insertions, 278 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c index a383a5ce4a..9a8f5c93f4 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4584,6 +4584,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"; @@ -4599,67 +4606,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: @@ -4679,42 +4687,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: @@ -4734,7 +4742,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: @@ -4747,20 +4755,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: @@ -4775,7 +4779,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: @@ -4810,7 +4814,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: @@ -4821,7 +4825,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: @@ -4832,23 +4836,17 @@ 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, CP0_BadInstr)); - rn = "BadInstr"; - } else { - gen_mfc0_unimplemented(ctx, arg); - } + CP0_CHECK(ctx->bi); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr)); + rn = "BadInstr"; break; case 2: - if (ctx->bp) { - gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); - rn = "BadInstrP"; - } else { - gen_mfc0_unimplemented(ctx, arg); - } + CP0_CHECK(ctx->bp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); + rn = "BadInstrP"; break; default: - goto die; + goto cp0_unimplemented; } break; case 9: @@ -4868,7 +4866,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: @@ -4879,7 +4877,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: @@ -4890,7 +4888,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: @@ -4915,7 +4913,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: @@ -4925,7 +4923,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: @@ -4936,7 +4934,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: @@ -4951,7 +4949,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: @@ -4990,7 +4988,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: @@ -5000,7 +4998,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: @@ -5010,7 +5008,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: @@ -5020,7 +5018,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: @@ -5034,18 +5032,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: @@ -5075,7 +5074,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: @@ -5087,7 +5086,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: @@ -5125,7 +5124,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: @@ -5139,7 +5138,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: @@ -5159,7 +5158,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: @@ -5179,7 +5178,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: @@ -5190,7 +5189,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: @@ -5201,29 +5200,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) @@ -5244,22 +5240,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: @@ -5269,42 +5265,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: @@ -5314,42 +5310,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: @@ -5359,7 +5355,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: @@ -5371,17 +5367,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: @@ -5396,7 +5391,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: @@ -5431,7 +5426,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: @@ -5443,7 +5438,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: @@ -5461,7 +5456,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: @@ -5472,7 +5467,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: @@ -5482,7 +5477,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: @@ -5493,7 +5488,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: @@ -5528,7 +5523,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: @@ -5539,7 +5534,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: @@ -5549,7 +5544,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: @@ -5564,7 +5559,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: @@ -5611,7 +5606,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: @@ -5621,7 +5616,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: @@ -5631,7 +5626,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: @@ -5641,7 +5636,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: @@ -5654,18 +5649,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: @@ -5708,7 +5704,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: @@ -5719,7 +5715,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: @@ -5757,7 +5753,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: @@ -5771,7 +5767,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: @@ -5791,7 +5787,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: @@ -5812,7 +5808,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: @@ -5822,7 +5818,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: @@ -5833,20 +5829,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); @@ -5857,9 +5852,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) @@ -5878,67 +5872,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: @@ -5948,42 +5943,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: @@ -5993,7 +5988,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: @@ -6005,19 +6000,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: @@ -6032,7 +6024,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: @@ -6067,7 +6059,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: @@ -6078,7 +6070,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: @@ -6088,23 +6080,17 @@ 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, CP0_BadInstr)); - rn = "BadInstr"; - } else { - gen_mfc0_unimplemented(ctx, arg); - } + CP0_CHECK(ctx->bi); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr)); + rn = "BadInstr"; break; case 2: - if (ctx->bp) { - gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); - rn = "BadInstrP"; - } else { - gen_mfc0_unimplemented(ctx, arg); - } + CP0_CHECK(ctx->bp); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); + rn = "BadInstrP"; break; default: - goto die; + goto cp0_unimplemented; } break; case 9: @@ -6124,7 +6110,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: @@ -6134,7 +6120,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: @@ -6145,7 +6131,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: @@ -6170,7 +6156,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: @@ -6180,7 +6166,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: @@ -6190,7 +6176,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: @@ -6205,7 +6191,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: @@ -6244,7 +6230,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: @@ -6254,7 +6240,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: @@ -6264,7 +6250,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: @@ -6274,7 +6260,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: @@ -6285,18 +6271,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: @@ -6326,7 +6313,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: @@ -6337,7 +6324,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: @@ -6375,7 +6362,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: @@ -6390,7 +6377,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: @@ -6410,7 +6397,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: @@ -6430,7 +6417,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: @@ -6440,7 +6427,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: @@ -6451,28 +6438,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) @@ -6493,22 +6477,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: @@ -6518,42 +6502,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: @@ -6563,42 +6547,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: @@ -6608,7 +6592,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: @@ -6620,17 +6604,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: @@ -6645,7 +6628,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: @@ -6680,7 +6663,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: @@ -6692,7 +6675,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: @@ -6710,7 +6693,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: @@ -6721,7 +6704,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; @@ -6733,7 +6716,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: @@ -6744,7 +6727,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; @@ -6781,7 +6764,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: @@ -6802,7 +6785,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: @@ -6812,7 +6795,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: @@ -6827,7 +6810,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: @@ -6865,7 +6848,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: @@ -6875,7 +6858,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: @@ -6885,7 +6868,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: @@ -6895,7 +6878,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: @@ -6906,18 +6889,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: @@ -6958,7 +6942,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: @@ -6969,7 +6953,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: @@ -7007,7 +6991,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: @@ -7021,7 +7005,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: @@ -7041,7 +7025,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: @@ -7062,7 +7046,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: @@ -7072,7 +7056,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: @@ -7083,20 +7067,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); @@ -7107,9 +7090,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 */ |