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
This commit is contained in:
Yongbok Kim 2018-02-17 14:37:41 -05:00 committed by Lioncash
parent 3b000e4eb3
commit 4a9cd8ec0b
No known key found for this signature in database
GPG Key ID: 4E3C3CC1031BA9C7
9 changed files with 73 additions and 32 deletions

View File

@ -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',

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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);