and describe FP instructions.
*/
-/* ST(0) = ST(0) `op` mem64(addr) (when dbl==True)
+/* ST(0) = ST(0) `op` mem64/32(addr)
Need to check ST(0)'s tag on read, but not on write.
*/
static
{
DIP("f%s%c %s", op_txt, dbl?'l':'s', dis_buf);
if (dbl) {
- put_ST_UNCHECKED(0, binop(op, get_ST(0), loadLE(Ity_F64,mkexpr(addr))));
+ put_ST_UNCHECKED(0,
+ binop( op,
+ get_ST(0),
+ loadLE(Ity_F64,mkexpr(addr))
+ ));
} else {
- put_ST_UNCHECKED(0, binop(op, get_ST(0),
- unop(Iop_F32toF64,loadLE(Ity_F32,mkexpr(addr)))));
+ put_ST_UNCHECKED(0,
+ binop( op,
+ get_ST(0),
+ unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
+ ));
+ }
+}
+
+
+/* ST(0) = mem64/32(addr) `op` ST(0)
+ Need to check ST(0)'s tag on read, but not on write.
+*/
+static
+void fp_do_oprev_mem_ST_0 ( IRTemp addr, UChar* op_txt, UChar* dis_buf,
+ IROp op, Bool dbl )
+{
+ DIP("f%s%c %s", op_txt, dbl?'l':'s', dis_buf);
+ if (dbl) {
+ put_ST_UNCHECKED(0,
+ binop( op,
+ loadLE(Ity_F64,mkexpr(addr)),
+ get_ST(0)
+ ));
+ } else {
+ put_ST_UNCHECKED(0,
+ binop( op,
+ unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
+ get_ST(0)
+ ));
}
}
switch (gregOfRM(modrm)) {
+ case 0: /* FADD single-real */
+ fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False );
+ break;
+
case 1: /* FMUL single-real */
fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
break;
fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
break;
+ case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
+ fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
+ break;
+
case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
break;
+ case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
+ fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
+ break;
+
+ case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
+ fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
+ break;
+
default:
goto decode_fail;
}
delta++;
switch (modrm) {
+ case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
+ r_src = (UInt)modrm - 0xC8;
+ DIP("fcmovz %%st(%d), %%st(0)", r_src);
+ put_ST_UNCHECKED(0,
+ IRExpr_Mux0X(
+ unop(Iop_1Uto8,calculate_condition(CondZ)),
+ get_ST(0), get_ST(r_src)) );
+ break;
+
case 0xE9: /* FUCOMPP %st(0),%st(1) */
DIP("fucompp %%st(0),%%st(1)\n");
put_C320( binop(Iop_Shl32,
fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True );
break;
+ case 5: /* FSUBR double-real */
+ fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True );
+ break;
+
case 6: /* FDIV double-real */
fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True );
break;
delta++;
switch (modrm) {
+ case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
+ fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
+ break;
+
case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
break;
fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, True );
break;
+ case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
+ fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, True );
+ break;
+
case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
break;