qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] More PPC emulation fixes
@ 2005-03-02 23:04 J. Mayer
  2005-03-03 11:49 ` J. Mayer
  0 siblings, 1 reply; 10+ messages in thread
From: J. Mayer @ 2005-03-02 23:04 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2639 bytes --]

Here's a new patch that fixes the last (!) bug in PPC fixed point
operations and most FPU bugs.

Apply and enjoy.

More infos about this patch:

I did test exhaustively all arithmetic, logical and compare operations
for fixed point and floating points computation with large ranges of
operands then compared the result with the ones I got from a real G3.

The bugs I found which are fixed with this patch are:
- srawi did set the overflow bit in XER register
  in some case when used with a 0 shift. 
  Then, I now do no computation if shift is 0.
- I did forget to generate FP_UNAVAILABLE 
  exception when trying to use lfd, lfs, stfd 
  and stfs instructions when FPU is not
  enabled. This lead to random 
  crashes or bad computations under Linux.
- operands for fsel where interverted.
- fres major opcode was false.
- conversion from float to int has been 
  improved.
- floating points operations applied on single
  operands where false: PPC specifies that 
  the cast to single should be done only on 
  the computation result. Then I removed all
  micro-ops for single float operands and 
  now  just use frsp after computation.
- multiply-and-add/sub-and-negate
  operations have been fixed for special 
  operands (NaN, infinite, ...)
- estimated single operation (ie fres, frsqrte)
  have been fixed for special operands
- absolute values computation have been 
  fixed.
- I also removed unusefull tb_flush & 
  tlb_flush which are not needed anymore
  now that tb flags are set properly.

There still are some things to improve:
- some computations on single operands 
  may have a difference on the last 
  significant bit of the mantissa. This only 
  appears when a multiplication is involved, 
  ie for fmuls, fmadds, fmsubs, fnmadds and 
  fnmsubs. All other operations give exactly 
  the same result as a real G3. As PPC specs 
  talks about multiply computation with 105 
  bits mantissa intermediary results, I may 
  have to use long doubles to fix this issue 
  (not tried). But I really think the current
  results may not hurt anyone.
- No flags are managed for floating-point 
  computations, except for compare 
  instructions. This does not seem to be 
  important for the glibc but is a potential 
  problem for other OSes.

With this patch, Debian Sarge is now able to install. It need OHW
patches to reboot and go on running the installer. I'll released a
second 0.4 preview with fixes for this (and more...) soon.
However, one need to run "expert" installation, or the installer will go
into an infinite loop trying to probe the link on the NE2k device.

-- 
J. Mayer <l_indien@magic.fr>
Never organized

[-- Attachment #2: ppc_fixes.diff --]
[-- Type: text/x-patch, Size: 25153 bytes --]

Index: target-ppc/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/exec.h,v
retrieving revision 1.9
diff -u -d -w -B -b -d -p -r1.9 exec.h
--- target-ppc/exec.h	3 Jan 2005 23:42:39 -0000	1.9
+++ target-ppc/exec.h	2 Mar 2005 21:51:07 -0000
@@ -32,9 +32,6 @@ register uint32_t T2 asm(AREG3);
 #define FT0 (env->ft0)
 #define FT1 (env->ft1)
 #define FT2 (env->ft2)
-#define FTS0 ((float)env->ft0)
-#define FTS1 ((float)env->ft1)
-#define FTS2 ((float)env->ft2)
 
 #if defined (DEBUG_OP)
 #define RETURN() __asm__ __volatile__("nop");
@@ -137,17 +134,12 @@ void do_fctiw (void);
 void do_fctiwz (void);
 void do_fnmadd (void);
 void do_fnmsub (void);
-void do_fnmadds (void);
-void do_fnmsubs (void);
 void do_fsqrt (void);
-void do_fsqrts (void);
 void do_fres (void);
-void do_fsqrte (void);
+void do_frsqrte (void);
 void do_fsel (void);
 void do_fcmpu (void);
 void do_fcmpo (void);
-void do_fabs (void);
-void do_fnabs (void);
 
 void do_check_reservation (void);
 void do_icbi (void);
Index: target-ppc/helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/helper.c,v
retrieving revision 1.21
diff -u -d -w -B -b -d -p -r1.21 helper.c
--- target-ppc/helper.c	15 Feb 2005 23:06:19 -0000	1.21
+++ target-ppc/helper.c	2 Mar 2005 21:51:07 -0000
@@ -809,6 +809,7 @@ void do_interrupt (CPUState *env)
         msr |= 0x00010000;
         goto store_current;
     case EXCP_NO_FP:
+        msr &= ~0xFFFF0000;
         goto store_current;
     case EXCP_DECR:
         if (msr_ee == 0) {
@@ -854,7 +855,6 @@ void do_interrupt (CPUState *env)
         return;
     case EXCP_RFI:
         /* Restore user-mode state */
-	tb_flush(env);
 #if defined (DEBUG_EXCEPTIONS)
 	if (msr_pr == 1)
 	    printf("Return from exception => 0x%08x\n", (uint32_t)env->nip);
@@ -887,7 +888,6 @@ void do_interrupt (CPUState *env)
     env->nip = excp << 8;
     env->exception_index = EXCP_NONE;
     /* Invalidate all TLB as we may have changed translation mode */
-    tlb_flush(env, 1);
     /* ensure that no TB jump will be modified as
        the program flow was changed */
 #ifdef __sparc__
Index: target-ppc/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/op.c,v
retrieving revision 1.15
diff -u -d -w -B -b -d -p -r1.15 op.c
--- target-ppc/op.c	15 Feb 2005 23:06:19 -0000	1.15
+++ target-ppc/op.c	2 Mar 2005 21:51:07 -0000
@@ -32,10 +32,6 @@
 #define FT1 (env->ft1)
 #define FT2 (env->ft2)
 
-#define FTS0 ((float)env->ft0)
-#define FTS1 ((float)env->ft1)
-#define FTS2 ((float)env->ft2)
-
 #define PPC_OP(name) void glue(op_, name)(void)
 
 #define REG 0
@@ -1204,13 +1200,6 @@ PPC_OP(fadd)
     RETURN();
 }
 
-/* fadds - fadds. */
-PPC_OP(fadds)
-{
-    FT0 = FTS0 + FTS1;
-    RETURN();
-}
-
 /* fsub - fsub. */
 PPC_OP(fsub)
 {
@@ -1218,13 +1207,6 @@ PPC_OP(fsub)
     RETURN();
 }
 
-/* fsubs - fsubs. */
-PPC_OP(fsubs)
-{
-    FT0 = FTS0 - FTS1;
-    RETURN();
-}
-
 /* fmul - fmul. */
 PPC_OP(fmul)
 {
@@ -1232,24 +1214,11 @@ PPC_OP(fmul)
     RETURN();
 }
 
-/* fmuls - fmuls. */
-PPC_OP(fmuls)
-{
-    FT0 = FTS0 * FTS1;
-    RETURN();
-}
-
 /* fdiv - fdiv. */
+void do_fdiv (void);
 PPC_OP(fdiv)
 {
-    FT0 /= FT1;
-    RETURN();
-}
-
-/* fdivs - fdivs. */
-PPC_OP(fdivs)
-{
-    FT0 = FTS0 / FTS1;
+    do_fdiv();
     RETURN();
 }
 
@@ -1260,13 +1229,6 @@ PPC_OP(fsqrt)
     RETURN();
 }
 
-/* fsqrts - fsqrts. */
-PPC_OP(fsqrts)
-{
-    do_fsqrts();
-    RETURN();
-}
-
 /* fres - fres. */
 PPC_OP(fres)
 {
@@ -1277,7 +1239,7 @@ PPC_OP(fres)
 /* frsqrte  - frsqrte. */
 PPC_OP(frsqrte)
 {
-    do_fsqrte();
+    do_frsqrte();
     RETURN();
 }
 
@@ -1296,13 +1258,6 @@ PPC_OP(fmadd)
     RETURN();
 }
 
-/* fmadds - fmadds. */
-PPC_OP(fmadds)
-{
-    FT0 = (FTS0 * FTS1) + FTS2;
-    RETURN();
-}
-
 /* fmsub - fmsub. */
 PPC_OP(fmsub)
 {
@@ -1310,13 +1265,6 @@ PPC_OP(fmsub)
     RETURN();
 }
 
-/* fmsubs - fmsubs. */
-PPC_OP(fmsubs)
-{
-    FT0 = (FTS0 * FTS1) - FTS2;
-    RETURN();
-}
-
 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
 PPC_OP(fnmadd)
 {
@@ -1324,13 +1272,6 @@ PPC_OP(fnmadd)
     RETURN();
 }
 
-/* fnmadds - fnmadds. */
-PPC_OP(fnmadds)
-{
-    do_fnmadds();
-    RETURN();
-}
-
 /* fnmsub - fnmsub. */
 PPC_OP(fnmsub)
 {
@@ -1338,13 +1279,6 @@ PPC_OP(fnmsub)
     RETURN();
 }
 
-/* fnmsubs - fnmsubs. */
-PPC_OP(fnmsubs)
-{
-    do_fnmsubs();
-    RETURN();
-}
-
 /***                     Floating-Point round & convert                    ***/
 /* frsp - frsp. */
 PPC_OP(frsp)
@@ -1385,6 +1319,7 @@ PPC_OP(fcmpo)
 
 /***                         Floating-point move                           ***/
 /* fabs */
+void do_fabs (void);
 PPC_OP(fabs)
 {
     do_fabs();
@@ -1392,6 +1327,7 @@ PPC_OP(fabs)
 }
 
 /* fnabs */
+void do_fnabs (void);
 PPC_OP(fnabs)
 {
     do_fnabs();
Index: target-ppc/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/op_helper.c,v
retrieving revision 1.11
diff -u -d -w -B -b -d -p -r1.11 op_helper.c
--- target-ppc/op_helper.c	15 Feb 2005 23:06:19 -0000	1.11
+++ target-ppc/op_helper.c	2 Mar 2005 21:51:07 -0000
@@ -249,16 +249,25 @@ void do_fctiw (void)
     union {
         double d;
         uint64_t i;
-    } *p = (void *)&FT1;
+    } p;
 
-    if (FT0 > (double)0x7FFFFFFF)
-        p->i = 0x7FFFFFFFULL << 32;
-    else if (FT0 < -(double)0x80000000)
-        p->i = 0x80000000ULL << 32;
-    else
-        p->i = 0;
-    p->i |= (uint32_t)FT0;
-    FT0 = p->d;
+    /* XXX: higher bits are not supposed to be significant.
+     *      to make tests easier, return the same as a real PPC 750 (aka G3)
+     */
+    p.d = FT0;
+    if (FT0 > (double)0x7FFFFFFF) {
+        p.i = 0x7FFFFFFFULL;
+        //        env->fpscr |= 1 << 17;
+    } else if (FT0 < -(double)0x80000000) {
+        p.i = 0x80000000ULL;
+        //        env->fpscr |= 1 << 17;
+    } else if (p.i & 0x8000000000000000ULL) {
+        p.i = 0x100000000ULL | (uint32_t)FT0;
+    } else {
+        p.i = (uint32_t)FT0;
+    }
+    p.i |= 0xFFF80000ULL << 32;
+    FT0 = p.d;
 }
 
 void do_fctiwz (void)
@@ -266,39 +275,50 @@ void do_fctiwz (void)
     union {
         double d;
         uint64_t i;
-    } *p = (void *)&FT1;
+    } p;
     int cround = fegetround();
 
+    /* XXX: higher bits are not supposed to be significant.
+     *      to make tests easier, return the same as a real PPC 750 (aka G3)
+     */
+    p.d = FT0;
     fesetround(FE_TOWARDZERO);
-    if (FT0 > (double)0x7FFFFFFF)
-        p->i = 0x7FFFFFFFULL << 32;
-    else if (FT0 < -(double)0x80000000)
-        p->i = 0x80000000ULL << 32;
-    else
-        p->i = 0;
-    p->i |= (uint32_t)FT0;
-    FT0 = p->d;
+    if (FT0 > (double)0x7FFFFFFF) {
+        p.i = 0x7FFFFFFFULL;
+        //        env->fpscr |= 1 << 17;
+    } else if (FT0 < -(double)0x80000000) {
+        p.i = 0x80000000ULL;
+        //        env->fpscr |= 1 << 17;
+    } else if (p.i & 0x8000000000000000ULL) {
+        p.i = 0x100000000ULL | (uint32_t)FT0;
+    } else {
+        p.i = (uint32_t)FT0;
+    }
+    p.i |= 0xFFF80000ULL << 32;
+    FT0 = p.d;
     fesetround(cround);
 }
 
 void do_fnmadd (void)
 {
-    FT0 = -((FT0 * FT1) + FT2);
+    FT0 = (FT0 * FT1) + FT2;
+    if (!isnan(FT0))
+        FT0 = -FT0;
 }
 
 void do_fnmsub (void)
 {
-    FT0 = -((FT0 * FT1) - FT2);
-}
-
-void do_fnmadds (void)
-{
-    FT0 = -((FTS0 * FTS1) + FTS2);
+    FT0 = (FT0 * FT1) - FT2;
+    if (!isnan(FT0))
+        FT0 = -FT0;
 }
 
-void do_fnmsubs (void)
+void do_fdiv (void)
 {
-    FT0 = -((FTS0 * FTS1) - FTS2);
+    if (FT0 == -0.0 && FT1 == -0.0)
+        FT0 = 0.0 / 0.0;
+    else
+        FT0 /= FT1;
 }
 
 void do_fsqrt (void)
@@ -306,27 +326,65 @@ void do_fsqrt (void)
     FT0 = sqrt(FT0);
 }
 
-void do_fsqrts (void)
-{
-    FT0 = (float)sqrt((float)FT0);
-}
-
 void do_fres (void)
 {
-    FT0 = 1.0 / FT0;
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    if (isnormal(FT0)) {
+        FT0 = (float)(1.0 / FT0);
+    } else {
+        p.d = FT0;
+        if (p.i == 0x8000000000000000ULL) {
+            p.i = 0xFFF0000000000000ULL;
+        } else if (p.i == 0x0000000000000000ULL) {
+            p.i = 0x7FF0000000000000ULL;
+        } else if (isnan(FT0)) {
+            p.i = 0x7FF8000000000000ULL;
+        } else if (FT0 < 0.0) {
+            p.i = 0x8000000000000000ULL;
+        } else {
+            p.i = 0x0000000000000000ULL;
+        }
+        FT0 = p.d;
+    }
 }
 
-void do_fsqrte (void)
+void do_frsqrte (void)
 {
-    FT0 = 1.0 / sqrt(FT0);
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    if (isnormal(FT0) && FT0 > 0.0) {
+        FT0 = (float)(1.0 / sqrt(FT0));
+    } else {
+        p.d = FT0;
+        if (p.i == 0x8000000000000000ULL) {
+            p.i = 0xFFF0000000000000ULL;
+        } else if (p.i == 0x0000000000000000ULL) {
+            p.i = 0x7FF0000000000000ULL;
+        } else if (isnan(FT0)) {
+            if (!(p.i & 0x0008000000000000ULL))
+                p.i |= 0x000FFFFFFFFFFFFFULL;
+        } else if (FT0 < 0) {
+            p.i = 0x7FF8000000000000ULL;
+        } else {
+            p.i = 0x0000000000000000ULL;
+        }
+        FT0 = p.d;
+    }
 }
 
 void do_fsel (void)
 {
     if (FT0 >= 0)
-        FT0 = FT2;
-    else
         FT0 = FT1;
+    else
+        FT0 = FT2;
 }
 
 void do_fcmpu (void)
@@ -371,12 +429,26 @@ void do_fcmpo (void)
 
 void do_fabs (void)
 {
-    FT0 = fabsl(FT0);
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.d = FT0;
+    p.i &= ~0x8000000000000000ULL;
+    FT0 = p.d;
 }
 
 void do_fnabs (void)
 {
-    FT0 = -fabsl(FT0);
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.d = FT0;
+    p.i |= 0x8000000000000000ULL;
+    FT0 = p.d;
 }
 
 /* Instruction cache invalidation helper */
Index: target-ppc/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/translate.c,v
retrieving revision 1.27
diff -u -d -w -B -b -d -p -r1.27 translate.c
--- target-ppc/translate.c	15 Feb 2005 23:06:19 -0000	1.27
+++ target-ppc/translate.c	2 Mar 2005 21:51:08 -0000
@@ -740,6 +740,7 @@ __GEN_LOGICAL2(sraw, 0x18, 0x18);
 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rS(ctx->opcode));
+    if (SH(ctx->opcode) != 0)
     gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
     if (Rc(ctx->opcode) != 0)
         gen_op_set_Rc0();
@@ -749,7 +750,7 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x0
 __GEN_LOGICAL2(srw, 0x18, 0x10);
 
 /***                       Floating-Point arithmetic                       ***/
-#define _GEN_FLOAT_ACB(name, op1, op2)                                        \
+#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat)                           \
 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT)                   \
 {                                                                             \
     if (!ctx->fpu_enabled) {                                                  \
@@ -760,17 +761,20 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x0
     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
     gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
     gen_op_load_fpr_FT2(rB(ctx->opcode));                                     \
-    gen_op_f##name();                                                         \
+    gen_op_f##op();                                                           \
+    if (isfloat) {                                                            \
+        gen_op_frsp();                                                        \
+    }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
     if (Rc(ctx->opcode))                                                      \
         gen_op_set_Rc1();                                                     \
 }
 
 #define GEN_FLOAT_ACB(name, op2)                                              \
-_GEN_FLOAT_ACB(name, 0x3F, op2);                                              \
-_GEN_FLOAT_ACB(name##s, 0x3B, op2);
+_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0);                                     \
+_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1);
 
-#define _GEN_FLOAT_AB(name, op1, op2, inval)                                  \
+#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat)                     \
 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
 {                                                                             \
     if (!ctx->fpu_enabled) {                                                  \
@@ -780,16 +784,19 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inv
     gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
     gen_op_load_fpr_FT1(rB(ctx->opcode));                                     \
-    gen_op_f##name();                                                         \
+    gen_op_f##op();                                                           \
+    if (isfloat) {                                                            \
+        gen_op_frsp();                                                        \
+    }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
     if (Rc(ctx->opcode))                                                      \
         gen_op_set_Rc1();                                                     \
 }
 #define GEN_FLOAT_AB(name, op2, inval)                                        \
-_GEN_FLOAT_AB(name, 0x3F, op2, inval);                                        \
-_GEN_FLOAT_AB(name##s, 0x3B, op2, inval);
+_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0);                               \
+_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
 
-#define _GEN_FLOAT_AC(name, op1, op2, inval)                                  \
+#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat)                     \
 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
 {                                                                             \
     if (!ctx->fpu_enabled) {                                                  \
@@ -799,14 +806,17 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inv
     gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
     gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
-    gen_op_f##name();                                                         \
+    gen_op_f##op();                                                           \
+    if (isfloat) {                                                            \
+        gen_op_frsp();                                                        \
+    }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
     if (Rc(ctx->opcode))                                                      \
         gen_op_set_Rc1();                                                     \
 }
 #define GEN_FLOAT_AC(name, op2, inval)                                        \
-_GEN_FLOAT_AC(name, 0x3F, op2, inval);                                        \
-_GEN_FLOAT_AC(name##s, 0x3B, op2, inval);
+_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0);                               \
+_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
 
 #define GEN_FLOAT_B(name, op2, op3)                                           \
 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT)                   \
@@ -823,8 +833,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x0
         gen_op_set_Rc1();                                                     \
 }
 
-#define GEN_FLOAT_BS(name, op2)                                               \
-GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                  \
+#define GEN_FLOAT_BS(name, op1, op2)                                          \
+GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                   \
 {                                                                             \
     if (!ctx->fpu_enabled) {                                                  \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
@@ -840,24 +850,24 @@ GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x
 
 /* fadd - fadds */
 GEN_FLOAT_AB(add, 0x15, 0x000007C0);
-/* fdiv */
+/* fdiv - fdivs */
 GEN_FLOAT_AB(div, 0x12, 0x000007C0);
-/* fmul */
+/* fmul - fmuls */
 GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
 
 /* fres */
-GEN_FLOAT_BS(res, 0x18);
+GEN_FLOAT_BS(res, 0x3B, 0x18);
 
 /* frsqrte */
-GEN_FLOAT_BS(rsqrte, 0x1A);
+GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A);
 
 /* fsel */
-_GEN_FLOAT_ACB(sel, 0x3F, 0x17);
-/* fsub */
+_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0);
+/* fsub - fsubs */
 GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
 /* Optional: */
 /* fsqrt */
-GEN_FLOAT_BS(sqrt, 0x16);
+GEN_FLOAT_BS(sqrt, 0x3F, 0x16);
 
 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
 {
@@ -867,20 +877,21 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x
     }
     gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rB(ctx->opcode));
-    gen_op_fsqrts();
+    gen_op_fsqrt();
+    gen_op_frsp();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
     if (Rc(ctx->opcode))
         gen_op_set_Rc1();
 }
 
 /***                     Floating-Point multiply-and-add                   ***/
-/* fmadd */
+/* fmadd - fmadds */
 GEN_FLOAT_ACB(madd, 0x1D);
-/* fmsub */
+/* fmsub - fmsubs */
 GEN_FLOAT_ACB(msub, 0x1C);
-/* fnmadd */
+/* fnmadd - fnmadds */
 GEN_FLOAT_ACB(nmadd, 0x1F);
-/* fnmsub */
+/* fnmsub - fnmsubs */
 GEN_FLOAT_ACB(nmsub, 0x1E);
 
 /***                     Floating-Point round & convert                    ***/
@@ -1426,6 +1437,10 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03
 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)               \
 {                                                                             \
     uint32_t simm = SIMM(ctx->opcode);                                        \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0) {                                               \
         gen_op_set_T0(simm);                                                  \
     } else {                                                                  \
@@ -1441,6 +1456,10 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0
 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
 {                                                                             \
     uint32_t simm = SIMM(ctx->opcode);                                        \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0 ||                                               \
         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
         RET_INVAL(ctx);                                                       \
@@ -1457,6 +1476,10 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF
 #define GEN_LDUXF(width, opc)                                                 \
 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
 {                                                                             \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0 ||                                               \
         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
         RET_INVAL(ctx);                                                       \
@@ -1473,6 +1496,10 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, op
 #define GEN_LDXF(width, opc2, opc3)                                           \
 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)           \
 {                                                                             \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0) {                                               \
         gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
     } else {                                                                  \
@@ -1501,6 +1528,10 @@ GEN_LDFS(fs, 0x10);
 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)              \
 {                                                                             \
     uint32_t simm = SIMM(ctx->opcode);                                        \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0) {                                               \
         gen_op_set_T0(simm);                                                  \
     } else {                                                                  \
@@ -1516,6 +1547,10 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 
 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
 {                                                                             \
     uint32_t simm = SIMM(ctx->opcode);                                        \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0) {                                               \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
@@ -1531,6 +1566,10 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xF
 #define GEN_STUXF(width, opc)                                                 \
 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
 {                                                                             \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0) {                                               \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
@@ -1546,6 +1585,10 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, o
 #define GEN_STXF(width, opc2, opc3)                                           \
 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)          \
 {                                                                             \
+    if (!ctx->fpu_enabled) {                                                  \
+        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        return;                                                               \
+    }                                                                         \
     if (rA(ctx->opcode) == 0) {                                               \
         gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
     } else {                                                                  \

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2005-03-08 16:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-02 23:04 [Qemu-devel] More PPC emulation fixes J. Mayer
2005-03-03 11:49 ` J. Mayer
2005-03-04 10:31   ` J. Mayer
2005-03-07 17:52   ` Thayne Harbaugh
2005-03-07 18:26     ` Asko Kauppi
2005-03-07 18:43       ` Thayne Harbaugh
2005-03-08 14:51         ` J. Mayer
2005-03-08 14:51     ` J. Mayer
2005-03-08 15:05       ` Thayne Harbaugh
2005-03-08 15:59         ` Asko Kauppi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).