Re: [Qemu-devel] [PATCH v2 4/4] target-mips: add user-mode FR switch support for MIPS32r5
Reviewed-by: Eric Johnson From: qemu-devel-bounces+eric.johnson=imgtec@nongnu.org [qemu-devel-bounces+eric.johnson=imgtec@nongnu.org] on behalf of Petar Jovanovic [petar.jovano...@rt-rk.com] Sent: Friday, January 24, 2014 8:18 AM To: qemu-devel@nongnu.org Cc: Petar Jovanovic; aurel...@aurel32.net Subject: [Qemu-devel] [PATCH v2 4/4] target-mips: add user-mode FR switch support for MIPS32r5 From: Petar Jovanovic Description of UFR feature: Required in MIPS32r5 if floating point is implemented and user-mode FR switching is supported. The UFR register allows user-mode to clear StatusFR by executing a CTC1 to UFR with GPR[0] as input, and read StatusFR by executing a CFC1 to UFR. helper_ctc1 has been extended with an additional parameter rt to check requirements for UFR feature. Definition of mips32r5-generic has been modified to include support for UFR. Signed-off-by: Petar Jovanovic --- target-mips/helper.h |2 +- target-mips/op_helper.c | 41 ++--- target-mips/translate.c | 14 -- target-mips/translate_init.c |9 + 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index b82f8e8..8c7921a 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -179,7 +179,7 @@ DEF_HELPER_2(yield, tl, env, tl) /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) -DEF_HELPER_3(ctc1, void, env, tl, i32) +DEF_HELPER_4(ctc1, void, env, tl, i32, i32) DEF_HELPER_2(float_cvtd_s, i64, env, i32) DEF_HELPER_2(float_cvtd_w, i64, env, i32) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index eaf4d26..2ef6633 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2199,12 +2199,23 @@ static inline void restore_flush_mode(CPUMIPSState *env) target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) { -target_ulong arg1; +target_ulong arg1 = 0; switch (reg) { case 0: arg1 = (int32_t)env->active_fpu.fcr0; break; +case 1: +/* UFR Support - Read Status FR */ +if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) { +if (env->CP0_Config5 & (1 << CP0C5_UFR)) { +arg1 = (int32_t) + ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); +} else { +helper_raise_exception(env, EXCP_RI); +} +} +break; case 25: arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1); break; @@ -,9 +2233,33 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) return arg1; } -void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg) +void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) { -switch(reg) { +switch (fs) { +case 1: +/* UFR Alias - Reset Status FR */ +if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { +return; +} +if (env->CP0_Config5 & (1 << CP0C5_UFR)) { +env->CP0_Status &= ~(1 << CP0St_FR); +compute_hflags(env); +} else { +helper_raise_exception(env, EXCP_RI); +} +break; +case 4: +/* UNFR Alias - Set Status FR */ +if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { +return; +} +if (env->CP0_Config5 & (1 << CP0C5_UFR)) { +env->CP0_Status |= (1 << CP0St_FR); +compute_hflags(env); +} else { +helper_raise_exception(env, EXCP_RI); +} +break; case 25: if (arg1 & 0xff00) return; diff --git a/target-mips/translate.c b/target-mips/translate.c index 02a90cb..083f6ab 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6818,7 +6818,12 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ -gen_helper_0e1i(ctc1, t0, rd); +{ +TCGv_i32 fs_tmp = tcg_const_i32(rd); + +gen_helper_0e2i(ctc1, t0, fs_tmp, rt); +tcg_temp_free_i32(fs_tmp); +} break; /* COP2: Not implemented. */ case 4: @@ -7254,7 +7259,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) break; case OPC_CTC1: gen_load_gpr(t0, rt); -gen_helper_0e1i(ctc1, t0, fs); +{ +TCGv_i32 fs_tmp = tcg_const_i32(fs); + +gen_helper_0e2i(ctc1, t0, fs_tmp, rt); +tcg_temp_free_i32(fs_tmp); +} opn = "ctc1"; break; #if
[Qemu-devel] [PATCH v2 4/4] target-mips: add user-mode FR switch support for MIPS32r5
From: Petar Jovanovic Description of UFR feature: Required in MIPS32r5 if floating point is implemented and user-mode FR switching is supported. The UFR register allows user-mode to clear StatusFR by executing a CTC1 to UFR with GPR[0] as input, and read StatusFR by executing a CFC1 to UFR. helper_ctc1 has been extended with an additional parameter rt to check requirements for UFR feature. Definition of mips32r5-generic has been modified to include support for UFR. Signed-off-by: Petar Jovanovic --- target-mips/helper.h |2 +- target-mips/op_helper.c | 41 ++--- target-mips/translate.c | 14 -- target-mips/translate_init.c |9 + 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index b82f8e8..8c7921a 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -179,7 +179,7 @@ DEF_HELPER_2(yield, tl, env, tl) /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) -DEF_HELPER_3(ctc1, void, env, tl, i32) +DEF_HELPER_4(ctc1, void, env, tl, i32, i32) DEF_HELPER_2(float_cvtd_s, i64, env, i32) DEF_HELPER_2(float_cvtd_w, i64, env, i32) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index eaf4d26..2ef6633 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2199,12 +2199,23 @@ static inline void restore_flush_mode(CPUMIPSState *env) target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) { -target_ulong arg1; +target_ulong arg1 = 0; switch (reg) { case 0: arg1 = (int32_t)env->active_fpu.fcr0; break; +case 1: +/* UFR Support - Read Status FR */ +if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) { +if (env->CP0_Config5 & (1 << CP0C5_UFR)) { +arg1 = (int32_t) + ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); +} else { +helper_raise_exception(env, EXCP_RI); +} +} +break; case 25: arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1); break; @@ -,9 +2233,33 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) return arg1; } -void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg) +void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) { -switch(reg) { +switch (fs) { +case 1: +/* UFR Alias - Reset Status FR */ +if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { +return; +} +if (env->CP0_Config5 & (1 << CP0C5_UFR)) { +env->CP0_Status &= ~(1 << CP0St_FR); +compute_hflags(env); +} else { +helper_raise_exception(env, EXCP_RI); +} +break; +case 4: +/* UNFR Alias - Set Status FR */ +if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { +return; +} +if (env->CP0_Config5 & (1 << CP0C5_UFR)) { +env->CP0_Status |= (1 << CP0St_FR); +compute_hflags(env); +} else { +helper_raise_exception(env, EXCP_RI); +} +break; case 25: if (arg1 & 0xff00) return; diff --git a/target-mips/translate.c b/target-mips/translate.c index 02a90cb..083f6ab 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6818,7 +6818,12 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ -gen_helper_0e1i(ctc1, t0, rd); +{ +TCGv_i32 fs_tmp = tcg_const_i32(rd); + +gen_helper_0e2i(ctc1, t0, fs_tmp, rt); +tcg_temp_free_i32(fs_tmp); +} break; /* COP2: Not implemented. */ case 4: @@ -7254,7 +7259,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) break; case OPC_CTC1: gen_load_gpr(t0, rt); -gen_helper_0e1i(ctc1, t0, fs); +{ +TCGv_i32 fs_tmp = tcg_const_i32(fs); + +gen_helper_0e2i(ctc1, t0, fs_tmp, rt); +tcg_temp_free_i32(fs_tmp); +} opn = "ctc1"; break; #if defined(TARGET_MIPS64) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 3d4dc88..29d39e2 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -358,18 +358,19 @@ static const mips_def_t mips_defs[] = .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_M), .CP0_Config4 = MIPS_CONFIG4 | (1 << CP0C4_M), .CP0_Config4_rw_bitmask = 0, -.CP0_Config5 = MIPS_CONFIG5, +.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR), .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) | (1 << CP0C5_CV) | (0 << CP0C5_EVA) | -