return IRExpr_Binop(op, a1, a2);
}
+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);
return binop( Iop_And32, get_fpround(), mkU32(3) );
}
+static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
+{
+ return mkU32(Irrm_NEAREST);
+}
+
/* --------- Get/set FP register tag bytes. --------- */
DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
if (dbl) {
put_ST_UNCHECKED(0,
- binop( op,
+ triop( op,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),
loadLE(Ity_F64,mkexpr(addr))
));
} else {
put_ST_UNCHECKED(0,
- binop( op,
+ triop( op,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),
unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
));
DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
if (dbl) {
put_ST_UNCHECKED(0,
- binop( op,
+ triop( op,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
loadLE(Ity_F64,mkexpr(addr)),
get_ST(0)
));
} else {
put_ST_UNCHECKED(0,
- binop( op,
+ triop( op,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
get_ST(0)
));
(Int)st_src, (Int)st_dst );
put_ST_UNCHECKED(
st_dst,
- binop(op, get_ST(st_dst), get_ST(st_src) )
+ triop( op,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(st_dst),
+ get_ST(st_src) )
);
if (pop_after)
fp_pop();
(Int)st_src, (Int)st_dst );
put_ST_UNCHECKED(
st_dst,
- binop(op, get_ST(st_src), get_ST(st_dst) )
+ triop( op,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(st_src),
+ get_ST(st_dst) )
);
if (pop_after)
fp_pop();
case 0xF0: /* F2XM1 */
DIP("f2xm1\n");
- put_ST_UNCHECKED(0, unop(Iop_2xm1F64, get_ST(0)));
+ put_ST_UNCHECKED(0,
+ binop(Iop_2xm1F64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
break;
case 0xF1: /* FYL2X */
DIP("fyl2x\n");
- put_ST_UNCHECKED(1, binop(Iop_Yl2xF64,
- get_ST(1), get_ST(0)));
+ put_ST_UNCHECKED(1,
+ triop(Iop_Yl2xF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(1),
+ get_ST(0)));
fp_pop();
break;
case 0xF2: /* FPTAN */
DIP("ftan\n");
- put_ST_UNCHECKED(0, unop(Iop_TanF64, get_ST(0)));
+ put_ST_UNCHECKED(0,
+ binop(Iop_TanF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
fp_push();
put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
clear_C2(); /* HACK */
case 0xF3: /* FPATAN */
DIP("fpatan\n");
- put_ST_UNCHECKED(1, binop(Iop_AtanF64,
- get_ST(1), get_ST(0)));
+ put_ST_UNCHECKED(1,
+ triop(Iop_AtanF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(1),
+ get_ST(0)));
fp_pop();
break;
- case 0xF4: {
+ case 0xF4: { /* FXTRACT */
IRTemp argF = newTemp(Ity_F64);
IRTemp sigF = newTemp(Ity_F64);
IRTemp expF = newTemp(Ity_F64);
case 0xF9: /* FYL2XP1 */
DIP("fyl2xp1\n");
- put_ST_UNCHECKED(1, binop(Iop_Yl2xp1F64,
- get_ST(1), get_ST(0)));
+ put_ST_UNCHECKED(1,
+ triop(Iop_Yl2xp1F64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(1),
+ get_ST(0)));
fp_pop();
break;
case 0xFA: /* FSQRT */
DIP("fsqrt\n");
- put_ST_UNCHECKED(0, unop(Iop_SqrtF64, get_ST(0)));
+ put_ST_UNCHECKED(0,
+ binop(Iop_SqrtF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
break;
case 0xFB: { /* FSINCOS */
IRTemp a1 = newTemp(Ity_F64);
assign( a1, get_ST(0) );
DIP("fsincos\n");
- put_ST_UNCHECKED(0, unop(Iop_SinF64, mkexpr(a1)));
+ put_ST_UNCHECKED(0,
+ binop(Iop_SinF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1)));
fp_push();
- put_ST(0, unop(Iop_CosF64, mkexpr(a1)));
+ put_ST(0,
+ binop(Iop_CosF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1)));
clear_C2(); /* HACK */
break;
}
case 0xFD: /* FSCALE */
DIP("fscale\n");
- put_ST_UNCHECKED(0, binop(Iop_ScaleF64,
- get_ST(0), get_ST(1)));
+ put_ST_UNCHECKED(0,
+ triop(Iop_ScaleF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0),
+ get_ST(1)));
break;
case 0xFE: /* FSIN */
DIP("fsin\n");
- put_ST_UNCHECKED(0, unop(Iop_SinF64, get_ST(0)));
+ put_ST_UNCHECKED(0,
+ binop(Iop_SinF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
clear_C2(); /* HACK */
break;
case 0xFF: /* FCOS */
DIP("fcos\n");
- put_ST_UNCHECKED(0, unop(Iop_CosF64, get_ST(0)));
+ put_ST_UNCHECKED(0,
+ binop(Iop_CosF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ get_ST(0)));
clear_C2(); /* HACK */
break;
do_fop_m32:
put_ST_UNCHECKED(0,
- binop(fop,
+ triop(fop,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),
unop(Iop_I32toF64,
loadLE(Ity_I32, mkexpr(addr)))));
do_foprev_m32:
put_ST_UNCHECKED(0,
- binop(fop,
+ triop(fop,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
unop(Iop_I32toF64,
loadLE(Ity_I32, mkexpr(addr))),
get_ST(0)));
get_ST(0),
unop(Iop_I32toF64,
unop(Iop_16Sto32,
- loadLE(Ity_I16,mkexpr(addr))))),
+ loadLE(Ity_I16,mkexpr(addr))))),
mkU8(8)),
mkU32(0x4500)
));
do_fop_m16:
put_ST_UNCHECKED(0,
- binop(fop,
+ triop(fop,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
get_ST(0),
unop(Iop_I32toF64,
unop(Iop_16Sto32,
do_foprev_m16:
put_ST_UNCHECKED(0,
- binop(fop,
+ triop(fop,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
unop(Iop_I32toF64,
unop(Iop_16Sto32,
loadLE(Ity_I16, mkexpr(addr)))),
static HReg do_sse_Not128 ( ISelEnv* env, HReg src )
{
HReg dst = 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;
}
return res;
}
- if (e->tag == Iex_Binop) {
+ if (e->tag == Iex_Triop) {
X86FpOp fpop = Xfp_INVALID;
- switch (e->Iex.Binop.op) {
+ switch (e->Iex.Triop.op) {
case Iop_AddF64: fpop = Xfp_ADD; break;
case Iop_SubF64: fpop = Xfp_SUB; break;
case Iop_MulF64: fpop = Xfp_MUL; break;
case Iop_DivF64: fpop = Xfp_DIV; break;
case Iop_ScaleF64: fpop = Xfp_SCALE; break;
- case Iop_AtanF64: fpop = Xfp_ATAN; break;
case Iop_Yl2xF64: fpop = Xfp_YL2X; break;
case Iop_Yl2xp1F64: fpop = Xfp_YL2XP1; break;
+ case Iop_AtanF64: fpop = Xfp_ATAN; break;
+ default: break;
+ }
+ if (fpop != Xfp_INVALID) {
+ HReg res = newVRegF(env);
+ HReg srcL = iselDblExpr(env, e->Iex.Triop.arg2);
+ HReg srcR = iselDblExpr(env, e->Iex.Triop.arg3);
+ /* XXXROUNDINGFIXME */
+ /* set roundingmode here */
+ addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
+ if (fpop != Xfp_ADD && fpop != Xfp_SUB
+ && fpop != Xfp_MUL && fpop != Xfp_DIV)
+ roundToF64(env, res);
+ return res;
+ }
+ }
+
+ if (e->tag == Iex_Binop) {
+ X86FpOp fpop = Xfp_INVALID;
+ switch (e->Iex.Binop.op) {
case Iop_PRemF64: fpop = Xfp_PREM; break;
case Iop_PRem1F64: fpop = Xfp_PREM1; break;
default: break;
return dst;
}
- if (e->tag == Iex_Unop) {
+ if (e->tag == Iex_Binop) {
X86FpOp fpop = Xfp_INVALID;
- switch (e->Iex.Unop.op) {
- case Iop_NegF64: fpop = Xfp_NEG; break;
- case Iop_AbsF64: fpop = Xfp_ABS; break;
- case Iop_SqrtF64: fpop = Xfp_SQRT; break;
+ switch (e->Iex.Binop.op) {
case Iop_SinF64: fpop = Xfp_SIN; break;
case Iop_CosF64: fpop = Xfp_COS; break;
case Iop_TanF64: fpop = Xfp_TAN; break;
case Iop_2xm1F64: fpop = Xfp_2XM1; break;
+ case Iop_SqrtF64: fpop = Xfp_SQRT; break;
default: break;
}
if (fpop != Xfp_INVALID) {
HReg res = newVRegF(env);
- HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+ HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+ /* XXXROUNDINGFIXME */
+ /* set roundingmode here */
addInstr(env, X86Instr_FpUnary(fpop,src,res));
if (fpop != Xfp_SQRT
&& fpop != Xfp_NEG && fpop != Xfp_ABS)
}
}
+ if (e->tag == Iex_Unop) {
+ X86FpOp fpop = Xfp_INVALID;
+ switch (e->Iex.Unop.op) {
+ case Iop_NegF64: fpop = Xfp_NEG; break;
+ case Iop_AbsF64: fpop = Xfp_ABS; break;
+ default: break;
+ }
+ if (fpop != Xfp_INVALID) {
+ HReg res = newVRegF(env);
+ HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+ addInstr(env, X86Instr_FpUnary(fpop,src,res));
+ if (fpop != Xfp_NEG && fpop != Xfp_ABS)
+ roundToF64(env, res);
+ return res;
+ }
+ }
+
if (e->tag == Iex_Unop) {
switch (e->Iex.Unop.op) {
case Iop_I32toF64: {