From: "J. Mayer" <l_indien@magic.fr>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] PPC floating point fixes
Date: Sat, 19 Feb 2005 13:20:16 +0100 [thread overview]
Message-ID: <1108815616.21864.4627.camel@rapid> (raw)
[-- Attachment #1: Type: text/plain, Size: 548 bytes --]
I did some systematic tests on PPC FPU emulation.
Then, I found some bugs:
- single-precision operations are to be done in double precision, then
rounded to single precision.
- Make fctiw & fctiwz return the values a real G3 does
- Sign was false for fabs/fnabs whith +/- 0.0 operand
- fsel operands were interverted
- fres major opcode is 0x3B, not 0x3F
It also appears that most FPU flags are wrong, even when flag updates
are explicitely wanted (using '.' opcode) so more fixes will come soon.
--
J. Mayer <l_indien@magic.fr>
Never organized
[-- Attachment #2: ppc_float_fixes.diff --]
[-- Type: text/x-patch, Size: 7440 bytes --]
Index: 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
--- exec.h 3 Jan 2005 23:42:39 -0000 1.9
+++ exec.h 18 Feb 2005 21:12:08 -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");
@@ -146,8 +143,6 @@ void do_fsqrte (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: 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
--- op.c 15 Feb 2005 23:06:19 -0000 1.15
+++ op.c 18 Feb 2005 21:12:09 -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
@@ -1207,7 +1203,7 @@ PPC_OP(fadd)
/* fadds - fadds. */
PPC_OP(fadds)
{
- FT0 = FTS0 + FTS1;
+ FT0 = (float)(FT0 + FT1);
RETURN();
}
@@ -1221,7 +1217,7 @@ PPC_OP(fsub)
/* fsubs - fsubs. */
PPC_OP(fsubs)
{
- FT0 = FTS0 - FTS1;
+ FT0 = (float)(FT0 - FT1);
RETURN();
}
@@ -1235,21 +1231,23 @@ PPC_OP(fmul)
/* fmuls - fmuls. */
PPC_OP(fmuls)
{
- FT0 = FTS0 * FTS1;
+ FT0 = (float)(FT0 * FT1);
RETURN();
}
/* fdiv - fdiv. */
+void do_fdiv (void);
PPC_OP(fdiv)
{
- FT0 /= FT1;
+ do_fdiv();
RETURN();
}
/* fdivs - fdivs. */
+void do_fdivs (void);
PPC_OP(fdivs)
{
- FT0 = FTS0 / FTS1;
+ do_fdivs();
RETURN();
}
@@ -1299,7 +1297,7 @@ PPC_OP(fmadd)
/* fmadds - fmadds. */
PPC_OP(fmadds)
{
- FT0 = (FTS0 * FTS1) + FTS2;
+ FT0 = (float)((FT0 * FT1) + FT2);
RETURN();
}
@@ -1313,7 +1311,7 @@ PPC_OP(fmsub)
/* fmsubs - fmsubs. */
PPC_OP(fmsubs)
{
- FT0 = (FTS0 * FTS1) - FTS2;
+ FT0 = (float)((FT0 * FT1) - FT2);
RETURN();
}
@@ -1385,6 +1382,7 @@ PPC_OP(fcmpo)
/*** Floating-point move ***/
/* fabs */
+void do_fabs (void);
PPC_OP(fabs)
{
do_fabs();
@@ -1392,6 +1390,7 @@ PPC_OP(fabs)
}
/* fnabs */
+void do_fnabs (void);
PPC_OP(fnabs)
{
do_fnabs();
Index: 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
--- op_helper.c 15 Feb 2005 23:06:19 -0000 1.11
+++ op_helper.c 18 Feb 2005 21:12:09 -0000
@@ -249,16 +249,21 @@ void do_fctiw (void)
union {
double d;
uint64_t i;
- } *p = (void *)&FT1;
+ } p;
+ /* XXX: higher bits are not supposed to be significant.
+ * to make tests easier, return the same as a real PPC 750 (aka G3)
+ */
+ p.i = 0xFFF80000ULL << 32;
if (FT0 > (double)0x7FFFFFFF)
- p->i = 0x7FFFFFFFULL << 32;
+ p.i |= 0x7FFFFFFFULL;
else if (FT0 < -(double)0x80000000)
- p->i = 0x80000000ULL << 32;
+ p.i |= 0x80000000ULL;
+ else if (FT0 < 0.0 || FT0 == -0.0)
+ p.i |= 0x100000000ULL | (uint32_t)FT0;
else
- p->i = 0;
- p->i |= (uint32_t)FT0;
- FT0 = p->d;
+ p.i |= (uint32_t)FT0;
+ FT0 = p.d;
}
void do_fctiwz (void)
@@ -266,18 +271,23 @@ 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.i = 0xFFF80000ULL << 32;
fesetround(FE_TOWARDZERO);
if (FT0 > (double)0x7FFFFFFF)
- p->i = 0x7FFFFFFFULL << 32;
+ p.i |= 0x7FFFFFFFULL;
else if (FT0 < -(double)0x80000000)
- p->i = 0x80000000ULL << 32;
+ p.i |= 0x80000000ULL;
+ else if (FT0 < 0.0 || FT0 == -0.0)
+ p.i |= 0x100000000ULL | (uint32_t)FT0;
else
- p->i = 0;
- p->i |= (uint32_t)FT0;
- FT0 = p->d;
+ p.i |= (uint32_t)FT0;
+ FT0 = p.d;
fesetround(cround);
}
@@ -293,12 +303,28 @@ void do_fnmsub (void)
void do_fnmadds (void)
{
- FT0 = -((FTS0 * FTS1) + FTS2);
+ FT0 = (float)(-((FT0 * FT1) + FT2));
}
void do_fnmsubs (void)
{
- FT0 = -((FTS0 * FTS1) - FTS2);
+ FT0 = (float)(-((FT0 * FT1) - FT2));
+}
+
+void do_fdiv (void)
+{
+ if (FT0 == -0.0 && FT1 == -0.0)
+ FT0 = 0.0 / 0.0;
+ else
+ FT0 /= FT1;
+}
+
+void do_fdivs (void)
+{
+ if (FT0 == -0.0 && FT1 == -0.0)
+ FT0 = (float)(0.0 / 0.0);
+ else
+ FT0 = (float)(FT0 / FT1);
}
void do_fsqrt (void)
@@ -308,12 +334,12 @@ void do_fsqrt (void)
void do_fsqrts (void)
{
- FT0 = (float)sqrt((float)FT0);
+ FT0 = (float)sqrt(FT0);
}
void do_fres (void)
{
- FT0 = 1.0 / FT0;
+ FT0 = (float)(1.0 / FT0);
}
void do_fsqrte (void)
@@ -324,9 +350,9 @@ void do_fsqrte (void)
void do_fsel (void)
{
if (FT0 >= 0)
- FT0 = FT2;
- else
FT0 = FT1;
+ else
+ FT0 = FT2;
}
void do_fcmpu (void)
@@ -371,12 +397,18 @@ void do_fcmpo (void)
void do_fabs (void)
{
- FT0 = fabsl(FT0);
+ if (FT0 == -0.0)
+ FT0 = +0.0;
+ else if (FT0 < 0.0)
+ FT0 = -FT0;
}
void do_fnabs (void)
{
- FT0 = -fabsl(FT0);
+ if (FT0 == +0.0)
+ FT0 = -0.0;
+ else if (FT0 >= +0.0)
+ FT0 = -FT0;
}
/* Instruction cache invalidation helper */
Index: 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
--- translate.c 15 Feb 2005 23:06:19 -0000 1.27
+++ translate.c 18 Feb 2005 21:12:10 -0000
@@ -823,8 +823,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); \
@@ -846,10 +846,10 @@ GEN_FLOAT_AB(div, 0x12, 0x000007C0);
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);
@@ -857,7 +857,7 @@ _GEN_FLOAT_ACB(sel, 0x3F, 0x17);
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)
{
reply other threads:[~2005-02-19 12:51 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1108815616.21864.4627.camel@rapid \
--to=l_indien@magic.fr \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).