target-mips: extend selected CP0 registers to 64-bits in MIPS32

Extend EntryLo0, EntryLo1, LLAddr and TagLo from 32 to 64 bits in MIPS32.

Introduce gen_move_low32() function which moves low 32 bits from 64-bit
temp to GPR; it sign extends 32-bit value on MIPS64 and truncates on
MIPS32.

Backports commit 284b731a6ae47b9ebabb9613e753c4d83cf75dd3 from qemu
This commit is contained in:
Leon Alrae 2018-02-13 13:44:52 -05:00 committed by Lioncash
parent 907bb26e5f
commit 95ed79d9c2
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 52 additions and 31 deletions

View file

@ -35,7 +35,7 @@ struct r4k_tlb_t {
uint_fast16_t RI0:1;
uint_fast16_t RI1:1;
uint_fast16_t EHINV:1;
target_ulong PFN[2];
uint64_t PFN[2];
};
#if !defined(CONFIG_USER_ONLY)
@ -226,7 +226,7 @@ struct CPUMIPSState {
uint32_t SEGBITS;
uint32_t PABITS;
target_ulong SEGMask;
target_ulong PAMask;
uint64_t PAMask;
int32_t msair;
#define MSAIR_ProcID 8
@ -274,8 +274,8 @@ struct CPUMIPSState {
#define CP0VPEOpt_DWX2 2
#define CP0VPEOpt_DWX1 1
#define CP0VPEOpt_DWX0 0
target_ulong CP0_EntryLo0;
target_ulong CP0_EntryLo1;
uint64_t CP0_EntryLo0;
uint64_t CP0_EntryLo1;
#if defined(TARGET_MIPS64)
# define CP0EnLo_RI 63
# define CP0EnLo_XI 62
@ -473,11 +473,11 @@ struct CPUMIPSState {
int32_t CP0_Config6;
int32_t CP0_Config7;
/* XXX: Maybe make LLAddr per-TC? */
target_ulong lladdr;
uint64_t lladdr;
target_ulong llval;
target_ulong llnewval;
target_ulong llreg;
target_ulong CP0_LLAddr_rw_bitmask;
uint64_t CP0_LLAddr_rw_bitmask;
int CP0_LLAddr_shift;
target_ulong CP0_WatchLo[8];
int32_t CP0_WatchHi[8];
@ -504,7 +504,7 @@ struct CPUMIPSState {
#define CP0DB_DSS 0
target_ulong CP0_DEPC;
int32_t CP0_Performance0;
int32_t CP0_TagLo;
uint64_t CP0_TagLo;
int32_t CP0_DataLo;
int32_t CP0_TagHi;
int32_t CP0_DataHi;

View file

@ -2004,12 +2004,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask;
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
((target_ulong)tlb->RI0 << CP0EnLo_RI) |
((target_ulong)tlb->XI0 << CP0EnLo_XI) |
((uint64_t)tlb->RI0 << CP0EnLo_RI) |
((uint64_t)tlb->XI0 << CP0EnLo_XI) |
(tlb->C0 << 3) | (tlb->PFN[0] >> 6);
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
((target_ulong)tlb->RI1 << CP0EnLo_RI) |
((target_ulong)tlb->XI1 << CP0EnLo_XI) |
((uint64_t)tlb->RI1 << CP0EnLo_RI) |
((uint64_t)tlb->XI1 << CP0EnLo_XI) |
(tlb->C1 << 3) | (tlb->PFN[1] >> 6);
}
}

View file

@ -4892,6 +4892,15 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
#ifndef CONFIG_USER_ONLY
/* CP0 (MMU and control) */
static inline void gen_move_low32(TCGContext *s, TCGv ret, TCGv_i64 arg)
{
#if defined(TARGET_MIPS64)
tcg_gen_ext32s_tl(s, ret, arg);
#else
tcg_gen_trunc_i64_tl(s, ret, arg);
#endif
}
static inline void gen_mfc0_load32 (DisasContext *ctx, TCGv arg, target_ulong off)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
@ -5026,17 +5035,21 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 2:
switch (sel) {
case 0:
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
{
TCGv_i64 tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_i64(tcg_ctx, tmp, tcg_ctx->cpu_env,
offsetof(CPUMIPSState, CP0_EntryLo0));
#if defined(TARGET_MIPS64)
if (ctx->rxi) {
/* Move RI/XI fields to bits 31:30 */
TCGv tmp = tcg_temp_new(tcg_ctx);
tcg_gen_shri_tl(tcg_ctx, tmp, arg, CP0EnLo_XI);
tcg_gen_deposit_tl(tcg_ctx, arg, arg, tmp, 30, 2);
tcg_temp_free(tcg_ctx, tmp);
}
if (ctx->rxi) {
/* Move RI/XI fields to bits 31:30 */
tcg_gen_shri_tl(tcg_ctx, arg, tmp, CP0EnLo_XI);
tcg_gen_deposit_tl(tcg_ctx, tmp, tmp, arg, 30, 2);
}
#endif
tcg_gen_ext32s_tl(tcg_ctx, arg, arg);
gen_move_low32(tcg_ctx, arg, tmp);
tcg_temp_free_i64(tcg_ctx, tmp);
}
rn = "EntryLo0";
break;
case 1:
@ -5081,17 +5094,20 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 3:
switch (sel) {
case 0:
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
{
TCGv_i64 tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_i64(tcg_ctx, tmp, tcg_ctx->cpu_env,
offsetof(CPUMIPSState, CP0_EntryLo1));
#if defined(TARGET_MIPS64)
if (ctx->rxi) {
/* Move RI/XI fields to bits 31:30 */
TCGv tmp = tcg_temp_new(tcg_ctx);
tcg_gen_shri_tl(tcg_ctx, tmp, arg, CP0EnLo_XI);
tcg_gen_deposit_tl(tcg_ctx, arg, arg, tmp, 30, 2);
tcg_temp_free(tcg_ctx, tmp);
}
if (ctx->rxi) {
/* Move RI/XI fields to bits 31:30 */
tcg_gen_shri_tl(tcg_ctx, arg, tmp, CP0EnLo_XI);
tcg_gen_deposit_tl(tcg_ctx, tmp, tmp, arg, 30, 2);
}
#endif
tcg_gen_ext32s_tl(tcg_ctx, arg, arg);
gen_move_low32(tcg_ctx, arg, tmp);
tcg_temp_free_i64(tcg_ctx, tmp);
}
rn = "EntryLo1";
break;
default:
@ -5500,7 +5516,12 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 2:
case 4:
case 6:
gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_TagLo));
{
TCGv_i64 tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_i64(tcg_ctx, tmp, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
gen_move_low32(tcg_ctx, arg, tmp);
tcg_temp_free_i64(tcg_ctx, tmp);
}
rn = "TagLo";
break;
case 1:
@ -19772,7 +19793,7 @@ void cpu_state_reset(CPUMIPSState *env)
}
#endif
env->PABITS = env->cpu_model->PABITS;
env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;