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.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Leon Alrae 2015-06-09 17:14:13 +01:00
parent b435f3f3d1
commit 284b731a6a
4 changed files with 63 additions and 42 deletions

View file

@ -34,7 +34,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)
@ -225,7 +225,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
@ -273,8 +273,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
@ -472,11 +472,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];
@ -503,7 +503,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

@ -142,8 +142,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
v->RI0 = (flags >> 13) & 1;
v->XI1 = (flags >> 12) & 1;
v->XI0 = (flags >> 11) & 1;
qemu_get_betls(f, &v->PFN[0]);
qemu_get_betls(f, &v->PFN[1]);
qemu_get_be64s(f, &v->PFN[0]);
qemu_get_be64s(f, &v->PFN[1]);
return 0;
}
@ -169,8 +169,8 @@ static void put_tlb(QEMUFile *f, void *pv, size_t size)
qemu_put_be32s(f, &v->PageMask);
qemu_put_8s(f, &v->ASID);
qemu_put_be16s(f, &flags);
qemu_put_betls(f, &v->PFN[0]);
qemu_put_betls(f, &v->PFN[1]);
qemu_put_be64s(f, &v->PFN[0]);
qemu_put_be64s(f, &v->PFN[1]);
}
const VMStateInfo vmstate_info_tlb = {
@ -201,8 +201,8 @@ const VMStateDescription vmstate_tlb = {
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
.version_id = 6,
.minimum_version_id = 6,
.version_id = 7,
.minimum_version_id = 7,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
/* Active TC */
@ -237,8 +237,8 @@ const VMStateDescription vmstate_mips_cpu = {
VMSTATE_UINTTL(env.CP0_VPESchedule, MIPSCPU),
VMSTATE_UINTTL(env.CP0_VPEScheFBack, MIPSCPU),
VMSTATE_INT32(env.CP0_VPEOpt, MIPSCPU),
VMSTATE_UINTTL(env.CP0_EntryLo0, MIPSCPU),
VMSTATE_UINTTL(env.CP0_EntryLo1, MIPSCPU),
VMSTATE_UINT64(env.CP0_EntryLo0, MIPSCPU),
VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU),
VMSTATE_UINTTL(env.CP0_Context, MIPSCPU),
VMSTATE_INT32(env.CP0_PageMask, MIPSCPU),
VMSTATE_INT32(env.CP0_PageGrain, MIPSCPU),
@ -269,7 +269,7 @@ const VMStateDescription vmstate_mips_cpu = {
VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
VMSTATE_UINTTL(env.lladdr, MIPSCPU),
VMSTATE_UINT64(env.lladdr, MIPSCPU),
VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
@ -277,7 +277,7 @@ const VMStateDescription vmstate_mips_cpu = {
VMSTATE_INT32(env.CP0_Debug, MIPSCPU),
VMSTATE_UINTTL(env.CP0_DEPC, MIPSCPU),
VMSTATE_INT32(env.CP0_Performance0, MIPSCPU),
VMSTATE_INT32(env.CP0_TagLo, MIPSCPU),
VMSTATE_UINT64(env.CP0_TagLo, MIPSCPU),
VMSTATE_INT32(env.CP0_DataLo, MIPSCPU),
VMSTATE_INT32(env.CP0_TagHi, MIPSCPU),
VMSTATE_INT32(env.CP0_DataHi, MIPSCPU),

View file

@ -1997,12 +1997,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

@ -4833,6 +4833,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(TCGv ret, TCGv_i64 arg)
{
#if defined(TARGET_MIPS64)
tcg_gen_ext32s_tl(ret, arg);
#else
tcg_gen_trunc_i64_tl(ret, arg);
#endif
}
static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
{
TCGv_i32 t0 = tcg_temp_new_i32();
@ -4961,17 +4970,20 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 2:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
{
TCGv_i64 tmp = tcg_temp_new_i64();
tcg_gen_ld_i64(tmp, 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_gen_shri_tl(tmp, arg, CP0EnLo_XI);
tcg_gen_deposit_tl(arg, arg, tmp, 30, 2);
tcg_temp_free(tmp);
}
if (ctx->rxi) {
/* Move RI/XI fields to bits 31:30 */
tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
}
#endif
tcg_gen_ext32s_tl(arg, arg);
gen_move_low32(arg, tmp);
tcg_temp_free_i64(tmp);
}
rn = "EntryLo0";
break;
case 1:
@ -5016,17 +5028,20 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 3:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
{
TCGv_i64 tmp = tcg_temp_new_i64();
tcg_gen_ld_i64(tmp, 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_gen_shri_tl(tmp, arg, CP0EnLo_XI);
tcg_gen_deposit_tl(arg, arg, tmp, 30, 2);
tcg_temp_free(tmp);
}
if (ctx->rxi) {
/* Move RI/XI fields to bits 31:30 */
tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
}
#endif
tcg_gen_ext32s_tl(arg, arg);
gen_move_low32(arg, tmp);
tcg_temp_free_i64(tmp);
}
rn = "EntryLo1";
break;
default:
@ -5436,7 +5451,12 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 2:
case 4:
case 6:
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
{
TCGv_i64 tmp = tcg_temp_new_i64();
tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
gen_move_low32(arg, tmp);
tcg_temp_free_i64(tmp);
}
rn = "TagLo";
break;
case 1:
@ -19423,7 +19443,8 @@ void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
PRIx64 "\n",
env->CP0_Config0, env->CP0_Config1, env->lladdr);
cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
env->CP0_Config2, env->CP0_Config3);
@ -19557,7 +19578,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;