mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-12 05:05:41 +00:00
target-mips: make ITC Configuration Tags accessible to the CPU
Add CP0.ErrCtl register with WST, SPR and ITC bits. In 34K and interAptiv processors these bits are used to enable CACHE instruction access to different arrays. When WST=0, SPR=0 and ITC=1 the CACHE instruction will access ITC tag values. Generally we do not model caches and we have been treating the CACHE instruction as NOP. But since CACHE can operate on ITC Tags new MIPS_HFLAG_ITC_CACHE hflag is introduced to generate the helper only when CACHE is in the ITC Access mode. Backports commit 0d74a222c27e26fc40f4f6120c61c3f9ceaa3776 from qemu
This commit is contained in:
parent
a338e9c855
commit
8fadc55db3
|
@ -3559,6 +3559,7 @@ mips_symbols = (
|
|||
'helper_biadd',
|
||||
'helper_bitrev',
|
||||
'helper_bitswap',
|
||||
'helper_cache',
|
||||
'helper_cfc1',
|
||||
'helper_cmp_d_eq',
|
||||
'helper_cmp_d_f',
|
||||
|
@ -4122,6 +4123,7 @@ mips_symbols = (
|
|||
'helper_mtc0_datalo',
|
||||
'helper_mtc0_debug',
|
||||
'helper_mtc0_ebase',
|
||||
'helper_mtc0_errctl',
|
||||
'helper_mtc0_entryhi',
|
||||
'helper_mtc0_entrylo0',
|
||||
'helper_mtc0_entrylo1',
|
||||
|
|
|
@ -3495,6 +3495,7 @@
|
|||
#define helper_biadd helper_biadd_mips
|
||||
#define helper_bitrev helper_bitrev_mips
|
||||
#define helper_bitswap helper_bitswap_mips
|
||||
#define helper_cache helper_cache_mips
|
||||
#define helper_cfc1 helper_cfc1_mips
|
||||
#define helper_cmp_d_eq helper_cmp_d_eq_mips
|
||||
#define helper_cmp_d_f helper_cmp_d_f_mips
|
||||
|
@ -4058,6 +4059,7 @@
|
|||
#define helper_mtc0_datalo helper_mtc0_datalo_mips
|
||||
#define helper_mtc0_debug helper_mtc0_debug_mips
|
||||
#define helper_mtc0_ebase helper_mtc0_ebase_mips
|
||||
#define helper_mtc0_errctl helper_mtc0_errctl_mips
|
||||
#define helper_mtc0_entryhi helper_mtc0_entryhi_mips
|
||||
#define helper_mtc0_entrylo0 helper_mtc0_entrylo0_mips
|
||||
#define helper_mtc0_entrylo1 helper_mtc0_entrylo1_mips
|
||||
|
|
|
@ -3495,6 +3495,7 @@
|
|||
#define helper_biadd helper_biadd_mips64
|
||||
#define helper_bitrev helper_bitrev_mips64
|
||||
#define helper_bitswap helper_bitswap_mips64
|
||||
#define helper_cache helper_cache_mips64
|
||||
#define helper_cfc1 helper_cfc1_mips64
|
||||
#define helper_cmp_d_eq helper_cmp_d_eq_mips64
|
||||
#define helper_cmp_d_f helper_cmp_d_f_mips64
|
||||
|
@ -4058,6 +4059,7 @@
|
|||
#define helper_mtc0_datalo helper_mtc0_datalo_mips64
|
||||
#define helper_mtc0_debug helper_mtc0_debug_mips64
|
||||
#define helper_mtc0_ebase helper_mtc0_ebase_mips64
|
||||
#define helper_mtc0_errctl helper_mtc0_errctl_mips64
|
||||
#define helper_mtc0_entryhi helper_mtc0_entryhi_mips64
|
||||
#define helper_mtc0_entrylo0 helper_mtc0_entrylo0_mips64
|
||||
#define helper_mtc0_entrylo1 helper_mtc0_entrylo1_mips64
|
||||
|
|
|
@ -3495,6 +3495,7 @@
|
|||
#define helper_biadd helper_biadd_mips64el
|
||||
#define helper_bitrev helper_bitrev_mips64el
|
||||
#define helper_bitswap helper_bitswap_mips64el
|
||||
#define helper_cache helper_cache_mips64el
|
||||
#define helper_cfc1 helper_cfc1_mips64el
|
||||
#define helper_cmp_d_eq helper_cmp_d_eq_mips64el
|
||||
#define helper_cmp_d_f helper_cmp_d_f_mips64el
|
||||
|
@ -4058,6 +4059,7 @@
|
|||
#define helper_mtc0_datalo helper_mtc0_datalo_mips64el
|
||||
#define helper_mtc0_debug helper_mtc0_debug_mips64el
|
||||
#define helper_mtc0_ebase helper_mtc0_ebase_mips64el
|
||||
#define helper_mtc0_errctl helper_mtc0_errctl_mips64el
|
||||
#define helper_mtc0_entryhi helper_mtc0_entryhi_mips64el
|
||||
#define helper_mtc0_entrylo0 helper_mtc0_entrylo0_mips64el
|
||||
#define helper_mtc0_entrylo1 helper_mtc0_entrylo1_mips64el
|
||||
|
|
|
@ -3495,6 +3495,7 @@
|
|||
#define helper_biadd helper_biadd_mipsel
|
||||
#define helper_bitrev helper_bitrev_mipsel
|
||||
#define helper_bitswap helper_bitswap_mipsel
|
||||
#define helper_cache helper_cache_mipsel
|
||||
#define helper_cfc1 helper_cfc1_mipsel
|
||||
#define helper_cmp_d_eq helper_cmp_d_eq_mipsel
|
||||
#define helper_cmp_d_f helper_cmp_d_f_mipsel
|
||||
|
@ -4058,6 +4059,7 @@
|
|||
#define helper_mtc0_datalo helper_mtc0_datalo_mipsel
|
||||
#define helper_mtc0_debug helper_mtc0_debug_mipsel
|
||||
#define helper_mtc0_ebase helper_mtc0_ebase_mipsel
|
||||
#define helper_mtc0_errctl helper_mtc0_errctl_mipsel
|
||||
#define helper_mtc0_entryhi helper_mtc0_entryhi_mipsel
|
||||
#define helper_mtc0_entrylo0 helper_mtc0_entrylo0_mipsel
|
||||
#define helper_mtc0_entrylo1 helper_mtc0_entrylo1_mipsel
|
||||
|
|
|
@ -533,6 +533,10 @@ struct CPUMIPSState {
|
|||
#define CP0DB_DSS 0
|
||||
target_ulong CP0_DEPC;
|
||||
int32_t CP0_Performance0;
|
||||
int32_t CP0_ErrCtl;
|
||||
#define CP0EC_WST 29
|
||||
#define CP0EC_SPR 28
|
||||
#define CP0EC_ITC 26
|
||||
uint64_t CP0_TagLo;
|
||||
int32_t CP0_DataLo;
|
||||
int32_t CP0_TagHi;
|
||||
|
@ -548,7 +552,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 0x75807FF
|
||||
#define MIPS_HFLAG_TMASK 0xF5807FF
|
||||
#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
|
||||
|
@ -597,6 +601,7 @@ struct CPUMIPSState {
|
|||
#define MIPS_HFLAG_MSA 0x1000000
|
||||
#define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */
|
||||
#define MIPS_HFLAG_ELPA 0x4000000
|
||||
#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */
|
||||
target_ulong btarget; /* Jump / branch target */
|
||||
target_ulong bcond; /* Branch condition (if needed) */
|
||||
|
||||
|
@ -621,6 +626,7 @@ struct CPUMIPSState {
|
|||
//void *irq[8];
|
||||
//QEMUTimer *timer; /* Internal timer */
|
||||
target_ulong exception_base; /* ExceptionBase input to the core */
|
||||
MemoryRegion *itc_tag; /* ITC Configuration Tags */
|
||||
|
||||
// Unicorn engine
|
||||
struct uc_struct *uc;
|
||||
|
|
|
@ -150,6 +150,7 @@ DEF_HELPER_2(mtc0_framemask, void, env, tl)
|
|||
DEF_HELPER_2(mtc0_debug, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_debug, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_performance0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_errctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_taglo, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_datalo, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_taghi, void, env, tl)
|
||||
|
@ -950,3 +951,6 @@ MSALDST_PROTO(h)
|
|||
MSALDST_PROTO(w)
|
||||
MSALDST_PROTO(d)
|
||||
#undef MSALDST_PROTO
|
||||
|
||||
DEF_HELPER_3(cache, void, env, tl, i32)
|
||||
|
||||
|
|
|
@ -1666,9 +1666,31 @@ void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
|
|||
env->CP0_Performance0 = arg1 & 0x000007ff;
|
||||
}
|
||||
|
||||
void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
int32_t wst = arg1 & (1 << CP0EC_WST);
|
||||
int32_t spr = arg1 & (1 << CP0EC_SPR);
|
||||
int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0;
|
||||
|
||||
env->CP0_ErrCtl = wst | spr | itc;
|
||||
|
||||
if (itc && !wst && !spr) {
|
||||
env->hflags |= MIPS_HFLAG_ITC_CACHE;
|
||||
} else {
|
||||
env->hflags &= ~MIPS_HFLAG_ITC_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
env->CP0_TagLo = arg1 & 0xFFFFFCF6;
|
||||
if (env->hflags & MIPS_HFLAG_ITC_CACHE) {
|
||||
/* If CACHE instruction is configured for ITC tags then make all
|
||||
CP0.TagLo bits writable. The actual write to ITC Configuration
|
||||
Tag will take care of the read-only bits. */
|
||||
env->CP0_TagLo = arg1;
|
||||
} else {
|
||||
env->CP0_TagLo = arg1 & 0xFFFFFCF6;
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
|
||||
|
@ -4146,6 +4168,21 @@ MSA_ST_DF(DF_WORD, w, cpu_stl_data)
|
|||
MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data)
|
||||
#endif
|
||||
|
||||
void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
target_ulong index = addr & 0x1fffffff;
|
||||
if (op == 9) {
|
||||
/* Index Store Tag */
|
||||
memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo,
|
||||
8, MEMTXATTRS_UNSPECIFIED);
|
||||
} else if (op == 5) {
|
||||
/* Index Load Tag */
|
||||
memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo,
|
||||
8, MEMTXATTRS_UNSPECIFIED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETPC())
|
||||
|
|
|
@ -5680,8 +5680,14 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
}
|
||||
break;
|
||||
case 26:
|
||||
tcg_gen_movi_tl(tcg_ctx, arg, 0); /* unimplemented */
|
||||
rn = "ECC";
|
||||
switch (sel) {
|
||||
case 0:
|
||||
gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_ErrCtl));
|
||||
rn = "ErrCtl";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
switch (sel) {
|
||||
|
@ -6345,8 +6351,15 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
}
|
||||
break;
|
||||
case 26:
|
||||
/* ignored */
|
||||
rn = "ECC";
|
||||
switch (sel) {
|
||||
case 0:
|
||||
gen_helper_mtc0_errctl(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
ctx->bstate = BS_STOP;
|
||||
rn = "ErrCtl";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
switch (sel) {
|
||||
|
@ -6975,8 +6988,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
}
|
||||
break;
|
||||
case 26:
|
||||
tcg_gen_movi_tl(tcg_ctx, arg, 0); /* unimplemented */
|
||||
rn = "ECC";
|
||||
switch (sel) {
|
||||
case 0:
|
||||
gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_ErrCtl));
|
||||
rn = "ErrCtl";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
switch (sel) {
|
||||
|
@ -7628,8 +7647,15 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
}
|
||||
break;
|
||||
case 26:
|
||||
/* ignored */
|
||||
rn = "ECC";
|
||||
switch (sel) {
|
||||
case 0:
|
||||
gen_helper_mtc0_errctl(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
ctx->bstate = BS_STOP;
|
||||
rn = "ErrCtl";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
switch (sel) {
|
||||
|
@ -11542,6 +11568,16 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm,
|
|||
tcg_temp_free(tcg_ctx, t0);
|
||||
}
|
||||
|
||||
static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
|
||||
int16_t offset)
|
||||
{
|
||||
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||
TCGv_i32 t0 = tcg_const_i32(tcg_ctx, op);
|
||||
TCGv t1 = tcg_temp_new(tcg_ctx);
|
||||
gen_base_offset_addr(ctx, t1, base, offset);
|
||||
gen_helper_cache(tcg_ctx, tcg_ctx->cpu_env, t1, t0);
|
||||
}
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
static void decode_i64_mips16 (DisasContext *ctx,
|
||||
int ry, int funct, int16_t offset,
|
||||
|
@ -14122,7 +14158,9 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
|
|||
switch (minor) {
|
||||
case CACHE:
|
||||
check_cp0_enabled(ctx);
|
||||
/* Treat as no-op. */
|
||||
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
||||
gen_cache_operation(ctx, rt, rs, imm);
|
||||
}
|
||||
break;
|
||||
case LWC2:
|
||||
case SWC2:
|
||||
|
@ -17646,7 +17684,9 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
|
|||
break;
|
||||
case R6_OPC_CACHE:
|
||||
check_cp0_enabled(ctx);
|
||||
/* Treat as NOP. */
|
||||
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
||||
gen_cache_operation(ctx, rt, rs, imm);
|
||||
}
|
||||
break;
|
||||
case R6_OPC_SC:
|
||||
gen_st_cond(ctx, op1, rt, rs, imm);
|
||||
|
@ -19793,7 +19833,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
|||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
check_cp0_enabled(ctx);
|
||||
check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
|
||||
/* Treat as NOP. */
|
||||
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
||||
gen_cache_operation(ctx, rt, rs, imm);
|
||||
}
|
||||
break;
|
||||
case OPC_PREF:
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
|
|
Loading…
Reference in a new issue