From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55320) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XjR32-00038h-VP for qemu-devel@nongnu.org; Wed, 29 Oct 2014 07:04:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XjR2w-0007F8-85 for qemu-devel@nongnu.org; Wed, 29 Oct 2014 07:04:16 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:53189) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XjR2v-0007F4-Vq for qemu-devel@nongnu.org; Wed, 29 Oct 2014 07:04:10 -0400 Message-ID: <5450C9A6.7070208@imgtec.com> Date: Wed, 29 Oct 2014 11:04:06 +0000 From: Yongbok Kim MIME-Version: 1.0 References: <1414154549-2102-1-git-send-email-leon.alrae@imgtec.com> <1414154549-2102-14-git-send-email-leon.alrae@imgtec.com> In-Reply-To: <1414154549-2102-14-git-send-email-leon.alrae@imgtec.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v3 13/15] target-mips: add restrictions for possible values in registers List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Leon Alrae , qemu-devel@nongnu.org Cc: aurelien@aurel32.net On 24/10/2014 13:42, Leon Alrae wrote: > 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 > --- > target-mips/op_helper.c | 70 +++++++++++++++++++++++++++++++++++++------------ > 1 file changed, 53 insertions(+), 17 deletions(-) > > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 6c87a1f..c6de86e 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,21 @@ 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) { > + int entryhi_r = extract64(arg1, 62, 2); > + int config0_at = extract32(env->CP0_Config0, 13, 2); > + bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0; > + if ((entryhi_r == 2) || > + (entryhi_r == 1 && (no_supervisor || config0_at == 1))) { > + /* skip EntryHi.R field if new value is reserved */ > + 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 +1423,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 +1485,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); > > @@ -2391,8 +2422,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; > @@ -2408,9 +2440,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; Reviewed-by: Yongbok Kim Regards, Yongbok