[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible valu
From: |
Leon Alrae |
Subject: |
[Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers |
Date: |
Mon, 14 Jul 2014 17:19:53 +0100 |
In Release 6 not all the values are allowed to be written to a register.
If the value is not valid or unsupported then it should stay unchanged.
For pre-R6 the existing behaviour has been changed only for CP0_Index register
as the current implementation does not seem to be correct - it looks like it
tries to limit the input value but the limit is higher than the actual
number of tlb entries.
Signed-off-by: Leon Alrae <address@hidden>
---
target-mips/op_helper.c | 63 ++++++++++++++++++++++++++++++++++------------
1 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 431f3a1..4be435c 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -959,14 +959,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env,
uint32_t sel)
void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
{
- int num = 1;
- unsigned int tmp = env->tlb->nb_tlb;
-
- do {
- tmp >>= 1;
- num <<= 1;
- } while (tmp);
- env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
+ uint32_t index_p = env->CP0_Index & 0x80000000;
+ uint32_t tlb_index = arg1 & 0x7fffffff;
+ if (tlb_index < env->tlb->nb_tlb) {
+ if (env->insn_flags & ISA_MIPS32R6) {
+ index_p |= arg1 & 0x80000000;
+ }
+ env->CP0_Index = index_p | tlb_index;
+ }
}
void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
@@ -1294,8 +1294,13 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong
arg1)
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
{
- /* 1k pages not implemented */
- env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
+ uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
+ if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
+ (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
+ mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
+ mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
+ env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
+ }
}
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
@@ -1309,7 +1314,13 @@ void helper_mtc0_pagegrain(CPUMIPSState *env,
target_ulong arg1)
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
{
- env->CP0_Wired = arg1 % env->tlb->nb_tlb;
+ if (env->insn_flags & ISA_MIPS32R6) {
+ if (arg1 < env->tlb->nb_tlb) {
+ env->CP0_Wired = arg1;
+ }
+ } else {
+ env->CP0_Wired = arg1 % env->tlb->nb_tlb;
+ }
}
void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
@@ -1368,11 +1379,14 @@ void helper_mtc0_entryhi(CPUMIPSState *env,
target_ulong arg1)
}
/* 1k pages not implemented */
- val = arg1 & mask;
#if defined(TARGET_MIPS64)
- val &= env->SEGMask;
+ if ((env->insn_flags & ISA_MIPS32R6) && extract64(arg1, 62, 2) == 0x2) {
+ mask &= ~(0x3ull << 62);
+ }
+ mask &= env->SEGMask;
#endif
old = env->CP0_EntryHi;
+ val = (arg1 & mask) | (old & ~mask);
env->CP0_EntryHi = val;
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
sync_c0_entryhi(env, env->current_tc);
@@ -1402,6 +1416,13 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong
arg1)
uint32_t val, old;
uint32_t mask = env->CP0_Status_rw_bitmask;
+ if (env->insn_flags & ISA_MIPS32R6) {
+ if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) {
+ mask &= ~(3 << CP0St_KSU);
+ }
+ mask &= ~(0x00180000 & arg1);
+ }
+
val = arg1 & mask;
old = env->CP0_Status;
env->CP0_Status = (env->CP0_Status & ~mask) | val;
@@ -1457,6 +1478,9 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong
arg1)
if (cpu->insn_flags & ISA_MIPS32R2) {
mask |= 1 << CP0Ca_DC;
}
+ if (cpu->insn_flags & ISA_MIPS32R6) {
+ mask &= ~((1 << CP0Ca_WP) & arg1);
+ }
cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask);
@@ -2381,8 +2405,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1,
uint32_t fs, uint32_t rt)
}
break;
case 25:
- if (arg1 & 0xffffff00)
+ if (env->insn_flags & ISA_MIPS32R6 || arg1 & 0xffffff00) {
return;
+ }
env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1
& 0xfe) << 24) |
((arg1 & 0x1) << 23);
break;
@@ -2398,9 +2423,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1,
uint32_t fs, uint32_t rt)
((arg1 & 0x4) << 22);
break;
case 31:
- if (arg1 & 0x007c0000)
- return;
- env->active_fpu.fcr31 = arg1;
+ if (env->insn_flags & ISA_MIPS32R6) {
+ uint32_t mask = 0xfefc0000;
+ env->active_fpu.fcr31 = (arg1 & ~mask) |
+ (env->active_fpu.fcr31 & mask);
+ } else if (!(arg1 & 0x007c0000)) {
+ env->active_fpu.fcr31 = arg1;
+ }
break;
default:
return;
--
1.7.5.4
- [Qemu-devel] [PATCH 0/6] target-mips: implement new MIPS64 Release 6 features, Leon Alrae, 2014/07/14
- [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI, Leon Alrae, 2014/07/14
- [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot, Leon Alrae, 2014/07/14
- [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0, Leon Alrae, 2014/07/14
- [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers,
Leon Alrae <=
- [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register, Leon Alrae, 2014/07/14
- [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU, Leon Alrae, 2014/07/14