|
From: <sv...@va...> - 2006-02-03 22:54:22
|
Author: sewardj
Date: 2006-02-03 22:54:17 +0000 (Fri, 03 Feb 2006)
New Revision: 1564
Log:
Followup to r1562: fixes for x86
Modified:
trunk/priv/guest-x86/toIR.c
trunk/priv/host-x86/isel.c
trunk/pub/libvex_ir.h
Modified: trunk/priv/guest-x86/toIR.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-x86/toIR.c 2006-02-03 19:12:17 UTC (rev 1563)
+++ trunk/priv/guest-x86/toIR.c 2006-02-03 22:54:17 UTC (rev 1564)
@@ -630,6 +630,11 @@
return IRExpr_Binop(op, a1, a2);
}
=20
+static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
+{
+ return IRExpr_Triop(op, a1, a2, a3);
+}
+
static IRExpr* mkexpr ( IRTemp tmp )
{
return IRExpr_Tmp(tmp);
@@ -3181,7 +3186,12 @@
return binop( Iop_And32, get_fpround(), mkU32(3) );
}
=20
+static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
+{
+ return mkU32(Irrm_NEAREST);
+}
=20
+
/* --------- Get/set FP register tag bytes. --------- */
=20
/* Given i, and some expression e, generate 'ST_TAG(i) =3D e'. */
@@ -3317,13 +3327,15 @@
DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
if (dbl) {
put_ST_UNCHECKED(0,=20
- binop( op,=20
+ triop( op,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),=20
loadLE(Ity_F64,mkexpr(addr))
));
} else {
put_ST_UNCHECKED(0,=20
- binop( op,=20
+ triop( op,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),=20
unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
));
@@ -3341,13 +3353,15 @@
DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
if (dbl) {
put_ST_UNCHECKED(0,=20
- binop( op,=20
+ triop( op,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
loadLE(Ity_F64,mkexpr(addr)),
get_ST(0)
));
} else {
put_ST_UNCHECKED(0,=20
- binop( op,=20
+ triop( op,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
get_ST(0)
));
@@ -3366,7 +3380,10 @@
(Int)st_src, (Int)st_dst );
put_ST_UNCHECKED(=20
st_dst,=20
- binop(op, get_ST(st_dst), get_ST(st_src) )=20
+ triop( op,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(st_dst),=20
+ get_ST(st_src) )=20
);
if (pop_after)
fp_pop();
@@ -3383,7 +3400,10 @@
(Int)st_src, (Int)st_dst );
put_ST_UNCHECKED(=20
st_dst,=20
- binop(op, get_ST(st_src), get_ST(st_dst) )=20
+ triop( op,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(st_src),=20
+ get_ST(st_dst) )=20
);
if (pop_after)
fp_pop();
@@ -3876,19 +3896,28 @@
=20
case 0xF0: /* F2XM1 */
DIP("f2xm1\n");
- put_ST_UNCHECKED(0, unop(Iop_2xm1F64, get_ST(0)));
+ put_ST_UNCHECKED(0,=20
+ binop(Iop_2xm1F64,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
break;
=20
case 0xF1: /* FYL2X */
DIP("fyl2x\n");
- put_ST_UNCHECKED(1, binop(Iop_Yl2xF64,
- get_ST(1), get_ST(0)));
+ put_ST_UNCHECKED(1,=20
+ triop(Iop_Yl2xF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(1),=20
+ get_ST(0)));
fp_pop();
break;
=20
case 0xF2: /* FPTAN */
DIP("ftan\n");
- put_ST_UNCHECKED(0, unop(Iop_TanF64, get_ST(0)));
+ put_ST_UNCHECKED(0,=20
+ binop(Iop_TanF64,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
fp_push();
put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
clear_C2(); /* HACK */
@@ -3896,12 +3925,15 @@
=20
case 0xF3: /* FPATAN */
DIP("fpatan\n");
- put_ST_UNCHECKED(1, binop(Iop_AtanF64,
- get_ST(1), get_ST(0)));
+ put_ST_UNCHECKED(1,=20
+ triop(Iop_AtanF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(1),=20
+ get_ST(0)));
fp_pop();
break;
=20
- case 0xF4: {
+ case 0xF4: { /* FXTRACT */
IRTemp argF =3D newTemp(Ity_F64);
IRTemp sigF =3D newTemp(Ity_F64);
IRTemp expF =3D newTemp(Ity_F64);
@@ -3968,23 +4000,35 @@
=20
case 0xF9: /* FYL2XP1 */
DIP("fyl2xp1\n");
- put_ST_UNCHECKED(1, binop(Iop_Yl2xp1F64,
- get_ST(1), get_ST(0)));
+ put_ST_UNCHECKED(1,=20
+ triop(Iop_Yl2xp1F64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(1),=20
+ get_ST(0)));
fp_pop();
break;
=20
case 0xFA: /* FSQRT */
DIP("fsqrt\n");
- put_ST_UNCHECKED(0, unop(Iop_SqrtF64, get_ST(0)));
+ put_ST_UNCHECKED(0,=20
+ binop(Iop_SqrtF64,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
break;
=20
case 0xFB: { /* FSINCOS */
IRTemp a1 =3D newTemp(Ity_F64);
assign( a1, get_ST(0) );
DIP("fsincos\n");
- put_ST_UNCHECKED(0, unop(Iop_SinF64, mkexpr(a1)));
+ put_ST_UNCHECKED(0,=20
+ binop(Iop_SinF64,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1)));
fp_push();
- put_ST(0, unop(Iop_CosF64, mkexpr(a1)));
+ put_ST(0,=20
+ binop(Iop_CosF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1)));
clear_C2(); /* HACK */
break;
}
@@ -3997,19 +4041,28 @@
=20
case 0xFD: /* FSCALE */
DIP("fscale\n");
- put_ST_UNCHECKED(0, binop(Iop_ScaleF64,
- get_ST(0), get_ST(1)));
+ put_ST_UNCHECKED(0,=20
+ triop(Iop_ScaleF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0),=20
+ get_ST(1)));
break;
=20
case 0xFE: /* FSIN */
DIP("fsin\n");
- put_ST_UNCHECKED(0, unop(Iop_SinF64, get_ST(0)));
+ put_ST_UNCHECKED(0,=20
+ binop(Iop_SinF64,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
clear_C2(); /* HACK */
break;
=20
case 0xFF: /* FCOS */
DIP("fcos\n");
- put_ST_UNCHECKED(0, unop(Iop_CosF64, get_ST(0)));
+ put_ST_UNCHECKED(0,=20
+ binop(Iop_CosF64,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
clear_C2(); /* HACK */
break;
=20
@@ -4095,7 +4148,8 @@
=20
do_fop_m32:
put_ST_UNCHECKED(0,=20
- binop(fop,=20
+ triop(fop,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),
unop(Iop_I32toF64,
loadLE(Ity_I32, mkexpr(addr)))));
@@ -4103,7 +4157,8 @@
=20
do_foprev_m32:
put_ST_UNCHECKED(0,=20
- binop(fop,=20
+ triop(fop,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
unop(Iop_I32toF64,
loadLE(Ity_I32, mkexpr(addr))),
get_ST(0)));
@@ -4741,7 +4796,7 @@
get_ST(0),
unop(Iop_I32toF64,=20
unop(Iop_16Sto32,
- loadLE(Ity_I16,mkexpr(addr)))=
)),
+ loadLE(Ity_I16,mkexpr(addr=
))))),
mkU8(8)),
mkU32(0x4500)
));
@@ -4770,7 +4825,8 @@
=20
do_fop_m16:
put_ST_UNCHECKED(0,=20
- binop(fop,=20
+ triop(fop,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),
unop(Iop_I32toF64,
unop(Iop_16Sto32,=20
@@ -4779,7 +4835,8 @@
=20
do_foprev_m16:
put_ST_UNCHECKED(0,=20
- binop(fop,=20
+ triop(fop,=20
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
unop(Iop_I32toF64,
unop(Iop_16Sto32,=20
loadLE(Ity_I16, mkexpr(addr)))),
Modified: trunk/priv/host-x86/isel.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-x86/isel.c 2006-02-03 19:12:17 UTC (rev 1563)
+++ trunk/priv/host-x86/isel.c 2006-02-03 22:54:17 UTC (rev 1564)
@@ -661,14 +661,14 @@
static HReg do_sse_Not128 ( ISelEnv* env, HReg src )
{
HReg dst =3D newVRegV(env);
- /* Set dst to zero. Not strictly necessary, but the idea of doing
- a FP comparison on whatever junk happens to be floating around
- in it is just too scary. */
+ /* Set dst to zero. If dst contains a NaN then all hell might
+ break loose after the comparison. So, first zero it. */
addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));
/* And now make it all 1s ... */
addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));
/* Finally, xor 'src' into it. */
addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));
+ /* Doesn't that just totally suck? */
return dst;
}
=20
@@ -2604,17 +2604,36 @@
return res;
}
=20
- if (e->tag =3D=3D Iex_Binop) {
+ if (e->tag =3D=3D Iex_Triop) {
X86FpOp fpop =3D Xfp_INVALID;
- switch (e->Iex.Binop.op) {
+ switch (e->Iex.Triop.op) {
case Iop_AddF64: fpop =3D Xfp_ADD; break;
case Iop_SubF64: fpop =3D Xfp_SUB; break;
case Iop_MulF64: fpop =3D Xfp_MUL; break;
case Iop_DivF64: fpop =3D Xfp_DIV; break;
case Iop_ScaleF64: fpop =3D Xfp_SCALE; break;
- case Iop_AtanF64: fpop =3D Xfp_ATAN; break;
case Iop_Yl2xF64: fpop =3D Xfp_YL2X; break;
case Iop_Yl2xp1F64: fpop =3D Xfp_YL2XP1; break;
+ case Iop_AtanF64: fpop =3D Xfp_ATAN; break;
+ default: break;
+ }
+ if (fpop !=3D Xfp_INVALID) {
+ HReg res =3D newVRegF(env);
+ HReg srcL =3D iselDblExpr(env, e->Iex.Triop.arg2);
+ HReg srcR =3D iselDblExpr(env, e->Iex.Triop.arg3);
+ /* XXXROUNDINGFIXME */
+ /* set roundingmode here */
+ addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
+ if (fpop !=3D Xfp_ADD && fpop !=3D Xfp_SUB=20
+ && fpop !=3D Xfp_MUL && fpop !=3D Xfp_DIV)
+ roundToF64(env, res);
+ return res;
+ }
+ }
+
+ if (e->tag =3D=3D Iex_Binop) {
+ X86FpOp fpop =3D Xfp_INVALID;
+ switch (e->Iex.Binop.op) {
case Iop_PRemF64: fpop =3D Xfp_PREM; break;
case Iop_PRem1F64: fpop =3D Xfp_PREM1; break;
default: break;
@@ -2671,21 +2690,21 @@
return dst;
}
=20
- if (e->tag =3D=3D Iex_Unop) {
+ if (e->tag =3D=3D Iex_Binop) {
X86FpOp fpop =3D Xfp_INVALID;
- switch (e->Iex.Unop.op) {
- case Iop_NegF64: fpop =3D Xfp_NEG; break;
- case Iop_AbsF64: fpop =3D Xfp_ABS; break;
- case Iop_SqrtF64: fpop =3D Xfp_SQRT; break;
+ switch (e->Iex.Binop.op) {
case Iop_SinF64: fpop =3D Xfp_SIN; break;
case Iop_CosF64: fpop =3D Xfp_COS; break;
case Iop_TanF64: fpop =3D Xfp_TAN; break;
case Iop_2xm1F64: fpop =3D Xfp_2XM1; break;
+ case Iop_SqrtF64: fpop =3D Xfp_SQRT; break;
default: break;
}
if (fpop !=3D Xfp_INVALID) {
HReg res =3D newVRegF(env);
- HReg src =3D iselDblExpr(env, e->Iex.Unop.arg);
+ HReg src =3D iselDblExpr(env, e->Iex.Binop.arg2);
+ /* XXXROUNDINGFIXME */
+ /* set roundingmode here */
addInstr(env, X86Instr_FpUnary(fpop,src,res));
if (fpop !=3D Xfp_SQRT
&& fpop !=3D Xfp_NEG && fpop !=3D Xfp_ABS)
@@ -2695,7 +2714,24 @@
}
=20
if (e->tag =3D=3D Iex_Unop) {
+ X86FpOp fpop =3D Xfp_INVALID;
switch (e->Iex.Unop.op) {
+ case Iop_NegF64: fpop =3D Xfp_NEG; break;
+ case Iop_AbsF64: fpop =3D Xfp_ABS; break;
+ default: break;
+ }
+ if (fpop !=3D Xfp_INVALID) {
+ HReg res =3D newVRegF(env);
+ HReg src =3D iselDblExpr(env, e->Iex.Unop.arg);
+ addInstr(env, X86Instr_FpUnary(fpop,src,res));
+ if (fpop !=3D Xfp_NEG && fpop !=3D Xfp_ABS)
+ roundToF64(env, res);
+ return res;
+ }
+ }
+
+ if (e->tag =3D=3D Iex_Unop) {
+ switch (e->Iex.Unop.op) {
case Iop_I32toF64: {
HReg dst =3D newVRegF(env);
HReg ri =3D iselIntExpr_R(env, e->Iex.Unop.arg);
Modified: trunk/pub/libvex_ir.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/pub/libvex_ir.h 2006-02-03 19:12:17 UTC (rev 1563)
+++ trunk/pub/libvex_ir.h 2006-02-03 22:54:17 UTC (rev 1564)
@@ -658,9 +658,16 @@
=20
=20
/* Encoding of IEEE754-specified rounding modes. This is the same as
- the encoding used by Intel IA32 to indicate x87 rounding mode. */
+ the encoding used by Intel IA32 to indicate x87 rounding mode.
+ Note, various front and back ends rely on the actual numerical
+ values of these, so do not change them. */
typedef
- enum { Irrm_NEAREST=3D0, Irrm_NegINF=3D1, Irrm_PosINF=3D2, Irrm_ZERO=3D=
3 }
+ enum {=20
+ Irrm_NEAREST =3D 0,=20
+ Irrm_NegINF =3D 1,=20
+ Irrm_PosINF =3D 2,=20
+ Irrm_ZERO =3D 3=20
+ }
IRRoundingMode;
=20
/* Floating point comparison result values, as created by Iop_CmpF64.
|