Re: [Qemu-devel] [PATCH v2 4/4] target-mips: add user-mode FR switch support for MIPS32r5

2014-02-07 Thread Eric Johnson
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

2014-01-24 Thread Petar Jovanovic
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) |
-