Skip to contentSkip to conversation

linux-user: Fix support MIPS o32 FP64 mode

PATCH New YunQiang Su 1 participant 1 message Dec 19, 2017

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 linux-user: Fix support MIPS o32 FP64 mode

MIPS o32 has a mode called FP64, who has 32 64Bit FPU registers. To use it:
add PR_GET_FP_MODE and PR_SET_FP_MODE options for prctl set CP0St_FR when binary as EF_MIPS_FP64

https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking

---
 linux-user/main.c    |  3 +++
 linux-user/syscall.c | 24 +++++++++++++++++++++
 target/mips/cpu.c    | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 target/mips/cpu.h    |  9 ++++++++
 4 files changed, 95 insertions(+)
linux-user/main.c +3 -0
index 2fd2a143ed..f2b02a99a2 100644
@@ -4750,6 +4750,9 @@ int main(int argc, char **argv, char **envp)
             }
             restore_snan_bit_mode(env);
         }
+        if ((info->elf_flags & EF_MIPS_FP64) != 0) {
+            env->CP0_Status |= (1 << CP0St_FR);
+        }
     }
 #elif defined(TARGET_NIOS2)
     {
linux-user/syscall.c +24 -0
index 11c9116c4a..664dacda33 100644
@@ -10530,6 +10530,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
              * need. */
             ret = -TARGET_EINVAL;
             break;
+#ifdef TARGET_MIPS
+        case PR_GET_FP_MODE:
+        {
+            CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
+            ret = 0;
+            if (env->CP0_Status & (1 << CP0St_FR)) {
+                ret |= PR_FP_MODE_FR;
+            }
+            if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
+                ret |= PR_FP_MODE_FRE;
+            }
+            break;
+        }
+        case PR_SET_FP_MODE:
+        {
+            CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
+            ret = mips_prctl_set_fp_mode(env, arg2);
+            if (ret < 0) {
+                ret = -TARGET_EOPNOTSUPP;
+                goto fail;
+            }
+            break;
+        }
+#endif
         default:
             /* Most prctl options have no pointer arguments */
             ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
target/mips/cpu.c +59 -0

63 lines not on this page · raw message

target/mips/cpu.h +9 -0
index 7f8ba5ff3e..b5d9aac6d0 100644
@@ -769,4 +769,13 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
                             MIPS_HFLAG_HWRENA_ULR);
 }
 
+/* prctl interface.  */
+#if defined(CONFIG_USER_ONLY)
+#define PR_SET_FP_MODE 45
+#define PR_GET_FP_MODE 46
+#define PR_FP_MODE_FR  (1 << 0)
+#define PR_FP_MODE_FRE (1 << 1)
+abi_long mips_prctl_set_fp_mode(CPUMIPSState *env, abi_long arg2);
+#endif
+
 #endif /* MIPS_CPU_H */
Signature · 1 line
2.15.1