From 4a9cd8ec0bf189dc7900e52c7676779a803bbc34 Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Sat, 17 Feb 2018 14:37:41 -0500 Subject: [PATCH] target-mips: add PC, XNP reg numbers to RDHWR Add Performance Counter (4) and XNP (5) register numbers to RDHWR. Add check_hwrena() to simplify access control checkings. Add RDHWR support to microMIPS R6. Backports commit b00c72180c36510bf9b124e190bd520e3b7e1358 from qemu --- qemu/header_gen.py | 2 ++ qemu/mips.h | 2 ++ qemu/mips64.h | 2 ++ qemu/mips64el.h | 2 ++ qemu/mipsel.h | 2 ++ qemu/target-mips/cpu.h | 1 + qemu/target-mips/helper.h | 2 ++ qemu/target-mips/op_helper.c | 64 ++++++++++++++++++++---------------- qemu/target-mips/translate.c | 28 ++++++++++++++-- 9 files changed, 73 insertions(+), 32 deletions(-) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 27444464..fc396c1a 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3701,6 +3701,8 @@ mips_symbols = ( 'helper_rdhwr_synci_step', 'helper_rdhwr_cc', 'helper_rdhwr_ccres', + 'helper_rdhwr_performance', + 'helper_rdhwr_xnp', 'helper_pmon', 'helper_wait', 'mips_cpu_do_unaligned_access', diff --git a/qemu/mips.h b/qemu/mips.h index bfb03cdd..7a28b5f2 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -3648,6 +3648,8 @@ #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips #define helper_rdhwr_cc helper_rdhwr_cc_mips #define helper_rdhwr_ccres helper_rdhwr_ccres_mips +#define helper_rdhwr_performance helper_rdhwr_performance_mips +#define helper_rdhwr_xnp helper_rdhwr_xnp_mips #define helper_pmon helper_pmon_mips #define helper_wait helper_wait_mips #define mips_cpu_do_unaligned_access mips_cpu_do_unaligned_access_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 298f847b..ccc32ec5 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -3648,6 +3648,8 @@ #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips64 #define helper_rdhwr_cc helper_rdhwr_cc_mips64 #define helper_rdhwr_ccres helper_rdhwr_ccres_mips64 +#define helper_rdhwr_performance helper_rdhwr_performance_mips64 +#define helper_rdhwr_xnp helper_rdhwr_xnp_mips64 #define helper_pmon helper_pmon_mips64 #define helper_wait helper_wait_mips64 #define mips_cpu_do_unaligned_access mips_cpu_do_unaligned_access_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index f05e9ff7..dc116ad8 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -3648,6 +3648,8 @@ #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips64el #define helper_rdhwr_cc helper_rdhwr_cc_mips64el #define helper_rdhwr_ccres helper_rdhwr_ccres_mips64el +#define helper_rdhwr_performance helper_rdhwr_performance_mips64el +#define helper_rdhwr_xnp helper_rdhwr_xnp_mips64el #define helper_pmon helper_pmon_mips64el #define helper_wait helper_wait_mips64el #define mips_cpu_do_unaligned_access mips_cpu_do_unaligned_access_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 2c065d55..e03d9767 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -3648,6 +3648,8 @@ #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mipsel #define helper_rdhwr_cc helper_rdhwr_cc_mipsel #define helper_rdhwr_ccres helper_rdhwr_ccres_mipsel +#define helper_rdhwr_performance helper_rdhwr_performance_mipsel +#define helper_rdhwr_xnp helper_rdhwr_xnp_mipsel #define helper_pmon helper_pmon_mipsel #define helper_wait helper_wait_mipsel #define mips_cpu_do_unaligned_access mips_cpu_do_unaligned_access_mipsel diff --git a/qemu/target-mips/cpu.h b/qemu/target-mips/cpu.h index a59b560e..426ef0c0 100644 --- a/qemu/target-mips/cpu.h +++ b/qemu/target-mips/cpu.h @@ -470,6 +470,7 @@ struct CPUMIPSState { #define CP0C5_CV 29 #define CP0C5_EVA 28 #define CP0C5_MSAEn 27 +#define CP0C5_XNP 13 #define CP0C5_UFE 9 #define CP0C5_FRE 8 #define CP0C5_SBRI 6 diff --git a/qemu/target-mips/helper.h b/qemu/target-mips/helper.h index 0bbdac24..34df721a 100644 --- a/qemu/target-mips/helper.h +++ b/qemu/target-mips/helper.h @@ -358,6 +358,8 @@ DEF_HELPER_1(rdhwr_cpunum, tl, env) DEF_HELPER_1(rdhwr_synci_step, tl, env) DEF_HELPER_1(rdhwr_cc, tl, env) DEF_HELPER_1(rdhwr_ccres, tl, env) +DEF_HELPER_1(rdhwr_performance, tl, env) +DEF_HELPER_1(rdhwr_xnp, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) diff --git a/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index b74bc1cf..e505fd98 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.c @@ -1356,6 +1356,13 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = 0x0000000F; + if ((env->CP0_Config1 & (1 << CP0C1_PC)) && + (env->insn_flags & ISA_MIPS32R6)) { + mask |= (1 << 4); + } + if (env->insn_flags & ISA_MIPS32R6) { + mask |= (1 << 5); + } if (env->CP0_Config3 & (1 << CP0C3_ULRI)) { mask |= (1 << 29); @@ -2192,53 +2199,52 @@ void helper_deret(CPUMIPSState *env) } #endif /* !CONFIG_USER_ONLY */ +static inline void check_hwrena(CPUMIPSState *env, int reg) +{ + if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) { + return; + } + do_raise_exception(env, EXCP_RI, GETPC()); +} + target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 0))) - return env->CP0_EBase & 0x3ff; - else - do_raise_exception(env, EXCP_RI, GETPC()); - - return 0; + check_hwrena(env, 0); + return env->CP0_EBase & 0x3ff; } target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 1))) - return env->SYNCI_Step; - else - do_raise_exception(env, EXCP_RI, GETPC()); - - return 0; + check_hwrena(env, 1); + return env->SYNCI_Step; } target_ulong helper_rdhwr_cc(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 2))) { + check_hwrena(env, 2); #ifdef CONFIG_USER_ONLY - return env->CP0_Count; + return env->CP0_Count; #else - return (int32_t)cpu_mips_get_count(env); + return (int32_t)cpu_mips_get_count(env); #endif - } else { - do_raise_exception(env, EXCP_RI, GETPC()); - } - - return 0; } target_ulong helper_rdhwr_ccres(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 3))) - return env->CCRes; - else - do_raise_exception(env, EXCP_RI, GETPC()); + check_hwrena(env, 3); + return env->CCRes; +} - return 0; +target_ulong helper_rdhwr_performance(CPUMIPSState *env) +{ + check_hwrena(env, 4); + return env->CP0_Performance0; +} + +target_ulong helper_rdhwr_xnp(CPUMIPSState *env) +{ + check_hwrena(env, 5); + return (env->CP0_Config5 >> CP0C5_XNP) & 1; } void helper_pmon(CPUMIPSState *env, int function) diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 9aa3496e..43df91a6 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -10436,7 +10436,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, } } -static void gen_rdhwr(DisasContext *ctx, int rt, int rd) +static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGv t0; @@ -10465,6 +10465,22 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) gen_helper_rdhwr_ccres(tcg_ctx, t0, tcg_ctx->cpu_env); gen_store_gpr(tcg_ctx, t0, rt); break; + case 4: + check_insn(ctx, ISA_MIPS32R6); + if (sel != 0) { + /* Performance counter registers are not implemented other than + * control register 0. + */ + generate_exception(ctx, EXCP_RI); + } + gen_helper_rdhwr_performance(tcg_ctx, t0, tcg_ctx->cpu_env); + gen_store_gpr(tcg_ctx, t0, rt); + break; + case 5: + check_insn(ctx, ISA_MIPS32R6); + gen_helper_rdhwr_xnp(tcg_ctx, t0, tcg_ctx->cpu_env); + gen_store_gpr(tcg_ctx, t0, rt); + break; case 29: #if defined(CONFIG_USER_ONLY) tcg_gen_ld_tl(tcg_ctx, t0, tcg_ctx->cpu_env, @@ -12087,6 +12103,7 @@ enum { ROTR = 0x3, SELEQZ = 0x5, SELNEZ = 0x6, + R6_RDHWR = 0x7, SLLV = 0x0, SRLV = 0x1, @@ -13044,7 +13061,8 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) gen_cl(ctx, mips32_op, rt, rs); break; case RDHWR: - gen_rdhwr(ctx, rt, rs); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, 0); break; case WSBH: gen_bshfl(ctx, OPC_WSBH, rs, rt); @@ -13596,6 +13614,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn(ctx, ISA_MIPS32R6); gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); break; + case R6_RDHWR: + check_insn(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; default: goto pool32a_invalid; } @@ -17866,7 +17888,7 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) break; #endif case OPC_RDHWR: - gen_rdhwr(ctx, rt, rd); + gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3)); break; case OPC_FORK: check_insn(ctx, ASE_MT);