to get the C3210 flag values. */
assign( a1, get_ST(0) );
assign( a2, get_ST(1) );
- put_ST_UNCHECKED(0, binop(Iop_PRem1F64,
- mkexpr(a1), mkexpr(a2)));
- put_C3210( binop(Iop_PRem1C3210F64, mkexpr(a1), mkexpr(a2)) );
+ put_ST_UNCHECKED(0,
+ triop(Iop_PRem1F64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1),
+ mkexpr(a2)));
+ put_C3210(
+ triop(Iop_PRem1C3210F64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1),
+ mkexpr(a2)) );
break;
}
to get the C3210 flag values. */
assign( a1, get_ST(0) );
assign( a2, get_ST(1) );
- put_ST_UNCHECKED(0, binop(Iop_PRemF64,
- mkexpr(a1), mkexpr(a2)));
- put_C3210( binop(Iop_PRemC3210F64, mkexpr(a1), mkexpr(a2)) );
+ put_ST_UNCHECKED(0,
+ triop(Iop_PRemF64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1),
+ mkexpr(a2)));
+ put_C3210(
+ triop(Iop_PRemC3210F64,
+ get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+ mkexpr(a1),
+ mkexpr(a2)) );
break;
}
break;
}
+ /* --------- TERNARY OP --------- */
+ case Iex_Triop: {
+ /* C3210 flags following FPU partial remainder (fprem), both
+ IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
+ if (e->Iex.Triop.op == Iop_PRemC3210F64
+ || e->Iex.Triop.op == Iop_PRem1C3210F64) {
+ HReg junk = newVRegF(env);
+ HReg dst = newVRegI(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(
+ e->Iex.Binop.op==Iop_PRemC3210F64
+ ? Xfp_PREM : Xfp_PREM1,
+ srcL,srcR,junk
+ ));
+ /* The previous pseudo-insn will have left the FPU's C3210
+ flags set correctly. So bag them. */
+ addInstr(env, X86Instr_FpStSW_AX());
+ addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
+ addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));
+ return dst;
+ }
+
+ break;
+ }
+
/* --------- BINARY OP --------- */
case Iex_Binop: {
X86AluOp aluOp;
return dst;
}
- /* C3210 flags following FPU partial remainder (fprem), both
- IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
- if (e->Iex.Binop.op == Iop_PRemC3210F64
- || e->Iex.Binop.op == Iop_PRem1C3210F64) {
- HReg junk = newVRegF(env);
- HReg dst = newVRegI(env);
- HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);
- HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);
- addInstr(env, X86Instr_FpBinary(
- e->Iex.Binop.op==Iop_PRemC3210F64
- ? Xfp_PREM : Xfp_PREM1,
- srcL,srcR,junk
- ));
- /* The previous pseudo-insn will have left the FPU's C3210
- flags set correctly. So bag them. */
- addInstr(env, X86Instr_FpStSW_AX());
- addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
- addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));
- return dst;
- }
-
break;
}
case Iop_Yl2xF64: fpop = Xfp_YL2X; break;
case Iop_Yl2xp1F64: fpop = Xfp_YL2XP1; break;
case Iop_AtanF64: fpop = Xfp_ATAN; break;
+ case Iop_PRemF64: fpop = Xfp_PREM; break;
+ case Iop_PRem1F64: fpop = Xfp_PREM1; break;
default: break;
}
if (fpop != Xfp_INVALID) {
}
}
- 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;
- }
- if (fpop != Xfp_INVALID) {
- HReg res = newVRegF(env);
- HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);
- HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);
- 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 && e->Iex.Binop.op == Iop_RoundF64toInt) {
HReg rf = iselDblExpr(env, e->Iex.Binop.arg2);
HReg dst = newVRegF(env);