qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Combined MIPS fixes


From: Daniel Jacobowitz
Subject: [Qemu-devel] Combined MIPS fixes
Date: Sun, 5 Nov 2006 10:36:16 -0500
User-agent: Mutt/1.5.13 (2006-08-11)

A grab-bag of fixes:

  - Report FP registers for the MIPS gdb stub
  - Implement the set_thread_area syscall for MIPS user emulation
  - Implement the set_tid_address syscall for user emulation
  - Correct 64-bit / 32-bit issues in do_socketcallwrapper
  - Emulate rdhwr for MIPS usermode
  - Correct double-precision cvt opcodes
  - Save the PC before generating a CpU exception

The user mode fixes let me emulate NPTL single-threaded binaries.  The CpU
fix prevents random crashes and corruption in hard float binaries in system
emulation mode.  And the cvt fixes correct most of the failures running
the GCC testsuite in user emulation.

This is enough to run debian-installer inside of qemu, if you are very
very patient.

--- gdbstub.c   (revision 153966)
+++ gdbstub.c   (local)
@@ -532,11 +532,37 @@ static int cpu_gdb_read_registers(CPUSta
     *(uint32_t *)ptr = tswapl(env->PC);
     ptr += 4;
 
+#ifdef MIPS_USES_FPU
+    for (i = 0; i < 32; i++)
+      {
+        *(uint32_t *)ptr = tswapl(FPR_W (env, i));
+        ptr += 4;
+      }
+
+    *(uint32_t *)ptr = tswapl(env->fcr31);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->fcr0);
+    ptr += 4;
+#endif
+
     /* 32 FP registers, fsr, fir, fp.  Not yet implemented.  */
+    /* what's 'fp' mean here?  */
 
     return ptr - mem_buf;
 }
 
+/* convert MIPS rounding mode in FCR31 to IEEE library */
+static unsigned int ieee_rm[] = 
+  {
+    float_round_nearest_even,
+    float_round_to_zero,
+    float_round_up,
+    float_round_down
+  };
+#define RESTORE_ROUNDING_MODE \
+    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
+
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
 {
     int i;
@@ -566,6 +592,28 @@ static void cpu_gdb_write_registers(CPUS
 
     env->PC = tswapl(*(uint32_t *)ptr);
     ptr += 4;
+
+#ifdef MIPS_USES_FPU
+    for (i = 0; i < 32; i++)
+      {
+       FPR_W (env, i) = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
+      }
+
+    env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
+    ptr += 4;
+
+    env->fcr0 = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    /* set rounding mode */
+    RESTORE_ROUNDING_MODE;
+
+#ifndef CONFIG_SOFTFLOAT
+    /* no floating point exception for native float */
+    SET_FP_ENABLE(env->fcr31, 0);
+#endif
+#endif
 }
 #elif defined (TARGET_SH4)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
--- linux-user/main.c   (revision 153966)
+++ linux-user/main.c   (local)
@@ -1297,6 +1297,7 @@ static const uint8_t mips_syscall_args[]
        MIPS_SYS(sys_add_key    , 5)
        MIPS_SYS(sys_request_key        , 4)
        MIPS_SYS(sys_keyctl     , 5)
+       MIPS_SYS(sys_set_thread_area, 1)
 };
 
 #undef MIPS_SYS
--- linux-user/mips/syscall_nr.h        (revision 153966)
+++ linux-user/mips/syscall_nr.h        (local)
@@ -285,4 +285,4 @@
 #define TARGET_NR_add_key                      (TARGET_NR_Linux + 280)
 #define TARGET_NR_request_key          (TARGET_NR_Linux + 281)
 #define TARGET_NR_keyctl                       (TARGET_NR_Linux + 282)
-
+#define TARGET_NR_set_thread_area      (TARGET_NR_Linux + 283)
--- linux-user/syscall.c        (revision 153966)
+++ linux-user/syscall.c        (local)
@@ -161,6 +161,9 @@ _syscall3(int,sys_rt_sigqueueinfo,int,pi
 #ifdef __NR_exit_group
 _syscall1(int,exit_group,int,error_code)
 #endif
+#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
+_syscall1(int,set_tid_address,int *,tidptr)
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -837,7 +840,7 @@ static long do_sendrecvmsg(int fd, targe
     return ret;
 }
 
-static long do_socketcall(int num, target_ulong vptr)
+static long do_socketcall(int num, target_phys_addr_t vptr)
 {
     long ret;
     const int n = sizeof(target_ulong);
@@ -1067,7 +1070,7 @@ static long do_socketcallwrapper(int num
     tputl(args+4, arg5);
     tputl(args+5, arg6);
 
-    return do_socketcall(num, (target_ulong) args);
+    return do_socketcall(num, (target_phys_addr_t) (long) args);
 }
 
 #define N_SHM_REGIONS  32
@@ -3823,6 +3826,15 @@ long do_syscall(void *cpu_env, int num, 
 #endif
 #ifdef TARGET_NR_set_thread_area
     case TARGET_NR_set_thread_area:
+#ifdef TARGET_MIPS
+      ((CPUMIPSState *) cpu_env)->tls_value = arg1;
+      ret = 0;
+      break;
+#else
+      goto unimplemented_nowarn;
+#endif
+#endif
+#ifdef TARGET_NR_get_thread_area
     case TARGET_NR_get_thread_area:
         goto unimplemented_nowarn;
 #endif
@@ -3830,10 +3842,17 @@ long do_syscall(void *cpu_env, int num, 
     case TARGET_NR_getdomainname:
         goto unimplemented_nowarn;
 #endif
+
+#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
+    case TARGET_NR_set_tid_address:
+      ret = get_errno(set_tid_address((int *) arg1));
+      break;
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
-#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || 
defined(TARGET_NR_getdomainname)
+#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || 
defined(TARGET_NR_getdomainname)
     unimplemented_nowarn:
 #endif
         ret = -ENOSYS;
--- target-mips/cpu.h   (revision 153966)
+++ target-mips/cpu.h   (local)
@@ -211,6 +211,10 @@ struct CPUMIPSState {
 
     int halted; /* TRUE if the CPU is in suspend state */
 
+#if defined(CONFIG_USER_ONLY)
+    target_ulong tls_value;
+#endif
+
     CPU_COMMON
 };
 
--- target-mips/op.c    (revision 153966)
+++ target-mips/op.c    (local)
@@ -799,7 +799,7 @@ FLOAT_OP(cvtd, w)
 }
 FLOAT_OP(cvts, d)
 {
-    FST2 = float64_to_float32(WT0, &env->fp_status);
+    FST2 = float64_to_float32(FDT0, &env->fp_status);
     DEBUG_FPU_STATE();
     RETURN();
 }
@@ -1085,6 +1085,13 @@ void op_tlbr (void)
 #endif
 
 /* Specials */
+#if defined (CONFIG_USER_ONLY)
+void op_tls_value (void)
+{
+  T0 = env->tls_value;
+}
+#endif
+
 void op_pmon (void)
 {
     CALL_FROM_TB1(do_pmon, PARAM1);
--- target-mips/translate.c     (revision 153966)
+++ target-mips/translate.c     (local)
@@ -1791,7 +1791,7 @@ static void gen_farith (DisasContext *ct
         break;
     case FOP(32, 17): /* cvt.s.d */
         CHECK_FR(ctx, fs | fd);
-        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
         gen_op_float_cvts_d();
         GEN_STORE_FTN_FREG(fd, WT2);
         opn = "cvt.s.d";
@@ -1812,7 +1812,7 @@ static void gen_farith (DisasContext *ct
         break;
     case FOP(36, 17): /* cvt.w.d */
         CHECK_FR(ctx, fs | fd);
-        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
         gen_op_float_cvtw_d();
         GEN_STORE_FTN_FREG(fd, WT2);
         opn = "cvt.w.d";
@@ -2089,6 +2089,7 @@ static void decode_opc (DisasContext *ct
     case 0x39: /* SWC1 */
     case 0x3D: /* SDC1 */
 #if defined(MIPS_USES_FPU)
+        save_cpu_state(ctx, 1);
         gen_op_cp1_enabled();
         gen_flt_ldst(ctx, op, rt, rs, imm);
 #else
@@ -2098,6 +2099,7 @@ static void decode_opc (DisasContext *ct
 
     case 0x11:          /* CP1 opcode */
 #if defined(MIPS_USES_FPU)
+        save_cpu_state(ctx, 1);
         gen_op_cp1_enabled();
         op1 = ((ctx->opcode >> 21) & 0x1F);
         switch (op1) {
@@ -2141,6 +2143,17 @@ static void decode_opc (DisasContext *ct
         generate_exception_err(ctx, EXCP_CpU, 3);
         break;
 
+#if defined (CONFIG_USER_ONLY)
+    case 0x1F:
+      if (ctx->opcode == 0x7c03e83b) /* rdhwr   v1,$29 */
+       {
+         gen_op_tls_value ();
+         gen_op_store_T0_gpr_gpr3 ();
+         break;
+       }
+      /* Fall through to RI.  */
+#endif
+
 #if defined (TARGET_MIPS64)
     case 0x18 ... 0x1B:
     case 0x27:

-- 
Daniel Jacobowitz
CodeSourcery




reply via email to

[Prev in Thread] Current Thread [Next in Thread]