From: Julian Seward Date: Wed, 11 May 2005 02:13:42 +0000 (+0000) Subject: Lots more SSE2 instructions. X-Git-Tag: svn/VALGRIND_3_0_1^2~154 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7d29fc2ab8d404cd5695d3b5f0fdac5b08003bd6;p=thirdparty%2Fvalgrind.git Lots more SSE2 instructions. git-svn-id: svn://svn.valgrind.org/vex/trunk@1180 --- diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index 12629c09fc..fd19a71d37 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -9260,20 +9260,13 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* ---------------------------------------------------- */ -//.. /* --- end of the SSE decoder. --- */ -//.. /* ---------------------------------------------------- */ -//.. -//.. /* ---------------------------------------------------- */ -//.. /* --- start of the SSE2 decoder. --- */ -//.. /* ---------------------------------------------------- */ -//.. -//.. /* Skip parts of the decoder which don't apply given the stated -//.. guest subarchitecture. */ -//.. if (subarch == VexSubArchX86_sse0 || subarch == VexSubArchX86_sse1) -//.. goto after_sse_decoders; -//.. -//.. insn = (UChar*)&guest_code[delta]; + /* ---------------------------------------------------- */ + /* --- end of the SSE decoder. --- */ + /* ---------------------------------------------------- */ + + /* ---------------------------------------------------- */ + /* --- start of the SSE2 decoder. --- */ + /* ---------------------------------------------------- */ /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */ if (have66noF2noF3(pfx) && sz == 2 @@ -9388,67 +9381,79 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in -//.. xmm(G) */ -//.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5B) { -//.. IRTemp argV = newTemp(Ity_V128); -//.. IRTemp rmode = newTemp(Ity_I32); -//.. -//.. modrm = getUChar(delta+2); -//.. if (epartIsReg(modrm)) { -//.. assign( argV, getXMMReg(eregOfRM(modrm)) ); -//.. delta += 2+1; -//.. DIP("cvtdq2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); -//.. delta += 2+alen; -//.. DIP("cvtdq2ps %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. assign( rmode, get_sse_roundingmode() ); -//.. breakup128to32s( argV, &t3, &t2, &t1, &t0 ); -//.. -#if 0 /* stop gcc multi-line comment warning */ -/.. # define CVT(_t) binop( Iop_F64toF32, \ -/.. mkexpr(rmode), \ -/.. unop(Iop_I32toF64,mkexpr(_t))) -#endif /* stop gcc multi-line comment warning */ -//.. -//.. putXMMRegLane32F( gregOfRM(modrm), 3, CVT(t3) ); -//.. putXMMRegLane32F( gregOfRM(modrm), 2, CVT(t2) ); -//.. putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) ); -//.. putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) ); -//.. -//.. # undef CVT -//.. -//.. goto decode_success; -//.. } - - /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in - lo half xmm(G), and zero upper half */ - if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0xE6) { + /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in + xmm(G) */ + if (haveNo66noF2noF3(pfx) && sz == 4 + && insn[0] == 0x0F && insn[1] == 0x5B) { IRTemp argV = newTemp(Ity_V128); IRTemp rmode = newTemp(Ity_I32); - if (sz != 4) goto decode_failure; modrm = getUChar(delta+2); if (epartIsReg(modrm)) { assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) ); delta += 2+1; - DIP("cvtpd2dq %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), + DIP("cvtdq2ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), nameXMMReg(gregOfRexRM(pfx,modrm))); } else { addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); - assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); + assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); delta += 2+alen; - DIP("cvtpd2dq %s,%s\n", dis_buf, + DIP("cvtdq2ps %s,%s\n", dis_buf, nameXMMReg(gregOfRexRM(pfx,modrm)) ); } assign( rmode, get_sse_roundingmode() ); + breakup128to32s( argV, &t3, &t2, &t1, &t0 ); + +# define CVT(_t) binop( Iop_F64toF32, \ + mkexpr(rmode), \ + unop(Iop_I32toF64,mkexpr(_t))) + + putXMMRegLane32F( gregOfRexRM(pfx,modrm), 3, CVT(t3) ); + putXMMRegLane32F( gregOfRexRM(pfx,modrm), 2, CVT(t2) ); + putXMMRegLane32F( gregOfRexRM(pfx,modrm), 1, CVT(t1) ); + putXMMRegLane32F( gregOfRexRM(pfx,modrm), 0, CVT(t0) ); + +# undef CVT + + goto decode_success; + } + + /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in + lo half xmm(G), and zero upper half, rounding towards zero */ + /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in + lo half xmm(G), according to prevailing rounding mode, and zero + upper half */ + if ( ( (haveF2no66noF3(pfx) && sz == 4) + || (have66noF2noF3(pfx) && sz == 2) + ) + && insn[0] == 0x0F && insn[1] == 0xE6) { + IRTemp argV = newTemp(Ity_V128); + IRTemp rmode = newTemp(Ity_I32); + Bool r2zero = toBool(sz == 2); + + modrm = getUChar(delta+2); + if (epartIsReg(modrm)) { + assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) ); + delta += 2+1; + DIP("cvt%spd2dq %s,%s\n", r2zero ? "t" : "", + nameXMMReg(eregOfRexRM(pfx,modrm)), + nameXMMReg(gregOfRexRM(pfx,modrm))); + } else { + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); + delta += 2+alen; + DIP("cvt%spd2dq %s,%s\n", r2zero ? "t" : "", + dis_buf, + nameXMMReg(gregOfRexRM(pfx,modrm)) ); + } + + if (r2zero) { + assign(rmode, mkU32((UInt)Irrm_ZERO) ); + } else { + assign( rmode, get_sse_roundingmode() ); + } + t0 = newTemp(Ity_F64); t1 = newTemp(Ity_F64); assign( t0, unop(Iop_ReinterpI64asF64, @@ -9470,213 +9475,229 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x -//.. I32 in mmx, according to prevailing SSE rounding mode */ -//.. /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x -//.. I32 in mmx, rounding towards zero */ -//.. if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) { -//.. IRTemp dst64 = newTemp(Ity_I64); -//.. IRTemp rmode = newTemp(Ity_I32); -//.. IRTemp f64lo = newTemp(Ity_F64); -//.. IRTemp f64hi = newTemp(Ity_F64); -//.. Bool r2zero = insn[1] == 0x2C; -//.. -//.. do_MMX_preamble(); -//.. modrm = getUChar(delta+2); -//.. -//.. if (epartIsReg(modrm)) { -//.. delta += 2+1; -//.. assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0)); -//.. assign(f64hi, getXMMRegLane64F(eregOfRM(modrm), 1)); -//.. DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "", -//.. nameXMMReg(eregOfRM(modrm)), -//.. nameMMXReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign(f64lo, loadLE(Ity_F64, mkexpr(addr))); -//.. assign(f64hi, loadLE(Ity_F64, binop( Iop_Add32, -//.. mkexpr(addr), -//.. mkU32(8) ))); -//.. delta += 2+alen; -//.. DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "", -//.. dis_buf, -//.. nameMMXReg(gregOfRM(modrm))); -//.. } -//.. -//.. if (r2zero) { -//.. assign(rmode, mkU32((UInt)Irrm_ZERO) ); -//.. } else { -//.. assign( rmode, get_sse_roundingmode() ); -//.. } -//.. -//.. assign( -//.. dst64, -//.. binop( Iop_32HLto64, -//.. binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64hi) ), -//.. binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64lo) ) -//.. ) -//.. ); -//.. -//.. putMMXReg(gregOfRM(modrm), mkexpr(dst64)); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in -//.. lo half xmm(G), and zero upper half */ -//.. /* Note, this is practically identical to CVTPD2DQ. It would have -//.. been nicer to merge them together, but the insn[] offsets differ -//.. by one. */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5A) { -//.. IRTemp argV = newTemp(Ity_V128); -//.. IRTemp rmode = newTemp(Ity_I32); -//.. -//.. modrm = getUChar(delta+2); -//.. if (epartIsReg(modrm)) { -//.. assign( argV, getXMMReg(eregOfRM(modrm)) ); -//.. delta += 2+1; -//.. DIP("cvtpd2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); -//.. delta += 2+alen; -//.. DIP("cvtpd2ps %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. assign( rmode, get_sse_roundingmode() ); -//.. t0 = newTemp(Ity_F64); -//.. t1 = newTemp(Ity_F64); -//.. assign( t0, unop(Iop_ReinterpI64asF64, -//.. unop(Iop_128to64, mkexpr(argV))) ); -//.. assign( t1, unop(Iop_ReinterpI64asF64, -//.. unop(Iop_128HIto64, mkexpr(argV))) ); -//.. -#if 0 /* stop gcc multi-line comment warning */ -/.. # define CVT(_t) binop( Iop_F64toF32, \ -/.. mkexpr(rmode), \ -/.. mkexpr(_t) ) -#endif /* stop gcc multi-line comment warning */ -//.. -//.. putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) ); -//.. putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) ); -//.. putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) ); -//.. putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) ); -//.. -//.. # undef CVT -//.. -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in -//.. xmm(G) */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x2A) { -//.. IRTemp arg64 = newTemp(Ity_I64); -//.. -//.. modrm = getUChar(delta+2); -//.. do_MMX_preamble(); -//.. if (epartIsReg(modrm)) { -//.. assign( arg64, getMMXReg(eregOfRM(modrm)) ); -//.. delta += 2+1; -//.. DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign( arg64, loadLE(Ity_I64, mkexpr(addr)) ); -//.. delta += 2+alen; -//.. DIP("cvtpi2pd %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. putXMMRegLane64F( -//.. gregOfRM(modrm), 0, -//.. unop(Iop_I32toF64, unop(Iop_64to32, mkexpr(arg64)) ) -//.. ); -//.. -//.. putXMMRegLane64F( -//.. gregOfRM(modrm), 1, -//.. unop(Iop_I32toF64, unop(Iop_64HIto32, mkexpr(arg64)) ) -//.. ); -//.. -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in -//.. xmm(G) */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5B) { -//.. IRTemp argV = newTemp(Ity_V128); -//.. IRTemp rmode = newTemp(Ity_I32); -//.. -//.. modrm = getUChar(delta+2); -//.. if (epartIsReg(modrm)) { -//.. assign( argV, getXMMReg(eregOfRM(modrm)) ); -//.. delta += 2+1; -//.. DIP("cvtps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); -//.. delta += 2+alen; -//.. DIP("cvtps2dq %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. assign( rmode, get_sse_roundingmode() ); -//.. breakup128to32s( argV, &t3, &t2, &t1, &t0 ); -//.. -//.. /* This is less than ideal. If it turns out to be a performance -//.. bottleneck it can be improved. */ -#if 0 /* stop gcc multi-line comment warning */ -/.. # define CVT(_t) \ -/.. binop( Iop_F64toI32, \ -/.. mkexpr(rmode), \ -/.. unop( Iop_F32toF64, \ -/.. unop( Iop_ReinterpI32asF32, mkexpr(_t))) ) -#endif /* stop gcc multi-line comment warning */ -//.. -//.. putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) ); -//.. putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) ); -//.. putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) ); -//.. putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) ); -//.. -//.. # undef CVT -//.. -//.. goto decode_success; -//.. } -//.. -//.. /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x -//.. F64 in xmm(G). */ -//.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5A) { -//.. IRTemp f32lo = newTemp(Ity_F32); -//.. IRTemp f32hi = newTemp(Ity_F32); -//.. -//.. modrm = getUChar(delta+2); -//.. if (epartIsReg(modrm)) { -//.. assign( f32lo, getXMMRegLane32F(eregOfRM(modrm), 0) ); -//.. assign( f32hi, getXMMRegLane32F(eregOfRM(modrm), 1) ); -//.. delta += 2+1; -//.. DIP("cvtps2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) ); -//.. assign( f32hi, loadLE(Ity_F32, -//.. binop(Iop_Add32,mkexpr(addr),mkU32(4))) ); -//.. delta += 2+alen; -//.. DIP("cvtps2pd %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. putXMMRegLane64F( gregOfRM(modrm), 1, -//.. unop(Iop_F32toF64, mkexpr(f32hi)) ); -//.. putXMMRegLane64F( gregOfRM(modrm), 0, -//.. unop(Iop_F32toF64, mkexpr(f32lo)) ); -//.. -//.. goto decode_success; -//.. } -//.. -//.. /* F2 0F 2D = CVTSD2SI -- convert F64 in mem/low half xmm to -//.. I32 in ireg, according to prevailing SSE rounding mode */ + /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x + I32 in mmx, according to prevailing SSE rounding mode */ + /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x + I32 in mmx, rounding towards zero */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) { + IRTemp dst64 = newTemp(Ity_I64); + IRTemp rmode = newTemp(Ity_I32); + IRTemp f64lo = newTemp(Ity_F64); + IRTemp f64hi = newTemp(Ity_F64); + Bool r2zero = insn[1] == 0x2C; + + do_MMX_preamble(); + modrm = getUChar(delta+2); + + if (epartIsReg(modrm)) { + delta += 2+1; + assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0)); + assign(f64hi, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 1)); + DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "", + nameXMMReg(eregOfRexRM(pfx,modrm)), + nameMMXReg(gregLO3ofRM(modrm))); + } else { + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + assign(f64lo, loadLE(Ity_F64, mkexpr(addr))); + assign(f64hi, loadLE(Ity_F64, binop( Iop_Add64, + mkexpr(addr), + mkU64(8) ))); + delta += 2+alen; + DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "", + dis_buf, + nameMMXReg(gregLO3ofRM(modrm))); + } + + if (r2zero) { + assign(rmode, mkU32((UInt)Irrm_ZERO) ); + } else { + assign( rmode, get_sse_roundingmode() ); + } + + assign( + dst64, + binop( Iop_32HLto64, + binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64hi) ), + binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64lo) ) + ) + ); + + putMMXReg(gregLO3ofRM(modrm), mkexpr(dst64)); + goto decode_success; + } + + /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in + lo half xmm(G), rounding according to prevailing SSE rounding + mode, and zero upper half */ + /* Note, this is practically identical to CVTPD2DQ. It would have + been nicer to merge them together, but the insn[] offsets differ + by one. */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x5A) { + IRTemp argV = newTemp(Ity_V128); + IRTemp rmode = newTemp(Ity_I32); + + modrm = getUChar(delta+2); + if (epartIsReg(modrm)) { + assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) ); + delta += 2+1; + DIP("cvtpd2ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), + nameXMMReg(gregOfRexRM(pfx,modrm))); + } else { + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); + delta += 2+alen; + DIP("cvtpd2ps %s,%s\n", dis_buf, + nameXMMReg(gregOfRexRM(pfx,modrm)) ); + } + + assign( rmode, get_sse_roundingmode() ); + t0 = newTemp(Ity_F64); + t1 = newTemp(Ity_F64); + assign( t0, unop(Iop_ReinterpI64asF64, + unop(Iop_V128to64, mkexpr(argV))) ); + assign( t1, unop(Iop_ReinterpI64asF64, + unop(Iop_V128HIto64, mkexpr(argV))) ); + +# define CVT(_t) binop( Iop_F64toF32, \ + mkexpr(rmode), \ + mkexpr(_t) ) + + putXMMRegLane32( gregOfRexRM(pfx,modrm), 3, mkU32(0) ); + putXMMRegLane32( gregOfRexRM(pfx,modrm), 2, mkU32(0) ); + putXMMRegLane32F( gregOfRexRM(pfx,modrm), 1, CVT(t1) ); + putXMMRegLane32F( gregOfRexRM(pfx,modrm), 0, CVT(t0) ); + +# undef CVT + + goto decode_success; + } + + /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in + xmm(G) */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x2A) { + IRTemp arg64 = newTemp(Ity_I64); + + modrm = getUChar(delta+2); + do_MMX_preamble(); + if (epartIsReg(modrm)) { + assign( arg64, getMMXReg(eregLO3ofRM(modrm)) ); + delta += 2+1; + DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregLO3ofRM(modrm)), + nameXMMReg(gregOfRexRM(pfx,modrm))); + } else { + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + assign( arg64, loadLE(Ity_I64, mkexpr(addr)) ); + delta += 2+alen; + DIP("cvtpi2pd %s,%s\n", dis_buf, + nameXMMReg(gregOfRexRM(pfx,modrm)) ); + } + + putXMMRegLane64F( + gregOfRexRM(pfx,modrm), 0, + unop(Iop_I32toF64, unop(Iop_64to32, mkexpr(arg64)) ) + ); + + putXMMRegLane64F( + gregOfRexRM(pfx,modrm), 1, + unop(Iop_I32toF64, unop(Iop_64HIto32, mkexpr(arg64)) ) + ); + + goto decode_success; + } + + /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in + xmm(G), rounding towards zero */ + /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in + xmm(G), as per the prevailing rounding mode */ + if ( ( (have66noF2noF3(pfx) && sz == 2) + || (haveF3no66noF2(pfx) && sz == 4) + ) + && insn[0] == 0x0F && insn[1] == 0x5B) { + IRTemp argV = newTemp(Ity_V128); + IRTemp rmode = newTemp(Ity_I32); + Bool r2zero = toBool(sz == 4); + + modrm = getUChar(delta+2); + if (epartIsReg(modrm)) { + assign( argV, getXMMReg(eregOfRexRM(pfx,modrm)) ); + delta += 2+1; + DIP("cvtps2dq %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), + nameXMMReg(gregOfRexRM(pfx,modrm))); + } else { + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); + delta += 2+alen; + DIP("cvtps2dq %s,%s\n", dis_buf, + nameXMMReg(gregOfRexRM(pfx,modrm)) ); + } + + if (r2zero) { + assign( rmode, mkU32((UInt)Irrm_ZERO) ); + } else { + assign( rmode, get_sse_roundingmode() ); + } + + breakup128to32s( argV, &t3, &t2, &t1, &t0 ); + + /* This is less than ideal. If it turns out to be a performance + bottleneck it can be improved. */ +# define CVT(_t) \ + binop( Iop_F64toI32, \ + mkexpr(rmode), \ + unop( Iop_F32toF64, \ + unop( Iop_ReinterpI32asF32, mkexpr(_t))) ) + + putXMMRegLane32( gregOfRexRM(pfx,modrm), 3, CVT(t3) ); + putXMMRegLane32( gregOfRexRM(pfx,modrm), 2, CVT(t2) ); + putXMMRegLane32( gregOfRexRM(pfx,modrm), 1, CVT(t1) ); + putXMMRegLane32( gregOfRexRM(pfx,modrm), 0, CVT(t0) ); + +# undef CVT + + goto decode_success; + } + + /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x + F64 in xmm(G). */ + if (haveNo66noF2noF3(pfx) && sz == 4 + && insn[0] == 0x0F && insn[1] == 0x5A) { + IRTemp f32lo = newTemp(Ity_F32); + IRTemp f32hi = newTemp(Ity_F32); + + modrm = getUChar(delta+2); + if (epartIsReg(modrm)) { + assign( f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0) ); + assign( f32hi, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 1) ); + delta += 2+1; + DIP("cvtps2pd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)), + nameXMMReg(gregOfRexRM(pfx,modrm))); + } else { + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) ); + assign( f32hi, loadLE(Ity_F32, + binop(Iop_Add64,mkexpr(addr),mkU64(4))) ); + delta += 2+alen; + DIP("cvtps2pd %s,%s\n", dis_buf, + nameXMMReg(gregOfRexRM(pfx,modrm)) ); + } + + putXMMRegLane64F( gregOfRexRM(pfx,modrm), 1, + unop(Iop_F32toF64, mkexpr(f32hi)) ); + putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0, + unop(Iop_F32toF64, mkexpr(f32lo)) ); + + goto decode_success; + } + + /* F2 0F 2D = CVTSD2SI + when sz==4 -- convert F64 in mem/low half xmm to I32 in ireg, + according to prevailing SSE rounding mode + when sz==8 -- convert F64 in mem/low half xmm to I64 in ireg, + according to prevailing SSE rounding mode + */ /* F2 0F 2C = CVTTSD2SI when sz==4 -- convert F64 in mem/low half xmm to I32 in ireg, truncating towards zero @@ -9685,7 +9706,7 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, */ if (haveF2no66noF3(pfx) && insn[0] == 0x0F - && ( /* insn[1] == 0x2D || */ insn[1] == 0x2C)) { + && (insn[1] == 0x2D || insn[1] == 0x2C)) { IRTemp rmode = newTemp(Ity_I32); IRTemp f64lo = newTemp(Ity_F64); Bool r2zero = toBool(insn[1] == 0x2C); @@ -9835,100 +9856,12 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in -//.. lo half xmm(G), and zero upper half, rounding towards zero */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE6) { -//.. IRTemp argV = newTemp(Ity_V128); -//.. IRTemp rmode = newTemp(Ity_I32); -//.. -//.. modrm = getUChar(delta+2); -//.. if (epartIsReg(modrm)) { -//.. assign( argV, getXMMReg(eregOfRM(modrm)) ); -//.. delta += 2+1; -//.. DIP("cvttpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); -//.. delta += 2+alen; -//.. DIP("cvttpd2dq %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. assign( rmode, mkU32((UInt)Irrm_ZERO) ); -//.. -//.. t0 = newTemp(Ity_F64); -//.. t1 = newTemp(Ity_F64); -//.. assign( t0, unop(Iop_ReinterpI64asF64, -//.. unop(Iop_128to64, mkexpr(argV))) ); -//.. assign( t1, unop(Iop_ReinterpI64asF64, -//.. unop(Iop_128HIto64, mkexpr(argV))) ); -//.. -#if 0 /* stop gcc multi-line comment warning */ -/.. # define CVT(_t) binop( Iop_F64toI32, \ -/.. mkexpr(rmode), \ -/.. mkexpr(_t) ) -#endif /* stop gcc multi-line comment warning */ -//.. -//.. putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) ); -//.. putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) ); -//.. putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) ); -//.. putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) ); -//.. -//.. # undef CVT -//.. -//.. goto decode_success; -//.. } -//.. -//.. /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in -//.. xmm(G), rounding towards zero */ -//.. if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5B) { -//.. IRTemp argV = newTemp(Ity_V128); -//.. IRTemp rmode = newTemp(Ity_I32); -//.. vassert(sz == 4); -//.. -//.. modrm = getUChar(delta+3); -//.. if (epartIsReg(modrm)) { -//.. assign( argV, getXMMReg(eregOfRM(modrm)) ); -//.. delta += 3+1; -//.. DIP("cvttps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)), -//.. nameXMMReg(gregOfRM(modrm))); -//.. } else { -//.. addr = disAMode ( &alen, sorb, delta+3, dis_buf ); -//.. assign( argV, loadLE(Ity_V128, mkexpr(addr)) ); -//.. delta += 3+alen; -//.. DIP("cvttps2dq %s,%s\n", dis_buf, -//.. nameXMMReg(gregOfRM(modrm)) ); -//.. } -//.. -//.. assign( rmode, mkU32((UInt)Irrm_ZERO) ); -//.. breakup128to32s( argV, &t3, &t2, &t1, &t0 ); -//.. -//.. /* This is less than ideal. If it turns out to be a performance -//.. bottleneck it can be improved. */ -#if 0 /* stop gcc multi-line comment warning */ -/.. # define CVT(_t) \ -/.. binop( Iop_F64toI32, \ -/.. mkexpr(rmode), \ -/.. unop( Iop_F32toF64, \ -/.. unop( Iop_ReinterpI32asF32, mkexpr(_t))) ) -#endif /* stop gcc multi-line comment warning */ -//.. -//.. putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) ); -//.. putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) ); -//.. putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) ); -//.. putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) ); -//.. -//.. # undef CVT -//.. -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5E) { -//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "divpd", Iop_Div64Fx2 ); -//.. goto decode_success; -//.. } + /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x5E) { + delta = dis_SSE_E_to_G_all( pfx, delta+2, "divpd", Iop_Div64Fx2 ); + goto decode_success; + } /* F2 0F 5E = DIVSD -- div 64F0x2 from R/M to R */ if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x5E) { @@ -9937,25 +9870,26 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 0F AE /5 = LFENCE -- flush pending operations to memory */ -//.. /* 0F AE /6 = MFENCE -- flush pending operations to memory */ -//.. if (insn[0] == 0x0F && insn[1] == 0xAE -//.. && epartIsReg(insn[2]) -//.. && (gregOfRM(insn[2]) == 5 || gregOfRM(insn[2]) == 6)) { -//.. vassert(sz == 4); -//.. delta += 3; -//.. /* Insert a memory fence. It's sometimes important that these -//.. are carried through to the generated code. */ -//.. stmt( IRStmt_MFence() ); -//.. DIP("%sfence\n", gregOfRM(insn[2])==5 ? "l" : "m"); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5F) { -//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxpd", Iop_Max64Fx2 ); -//.. goto decode_success; -//.. } + /* 0F AE /5 = LFENCE -- flush pending operations to memory */ + /* 0F AE /6 = MFENCE -- flush pending operations to memory */ + if (haveNo66noF2noF3(pfx) && sz == 4 + && insn[0] == 0x0F && insn[1] == 0xAE + && epartIsReg(insn[2]) + && (gregLO3ofRM(insn[2]) == 5 || gregLO3ofRM(insn[2]) == 6)) { + delta += 3; + /* Insert a memory fence. It's sometimes important that these + are carried through to the generated code. */ + stmt( IRStmt_MFence() ); + DIP("%sfence\n", gregLO3ofRM(insn[2])==5 ? "l" : "m"); + goto decode_success; + } + + /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x5F) { + delta = dis_SSE_E_to_G_all( pfx, delta+2, "maxpd", Iop_Max64Fx2 ); + goto decode_success; + } /* F2 0F 5F = MAXSD -- max 64F0x2 from R/M to R */ if (haveF2no66noF3(pfx) && sz == 4 @@ -9964,11 +9898,12 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5D) { -//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "minpd", Iop_Min64Fx2 ); -//.. goto decode_success; -//.. } + /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x5D) { + delta = dis_SSE_E_to_G_all( pfx, delta+2, "minpd", Iop_Min64Fx2 ); + goto decode_success; + } /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */ if (haveF2no66noF3(pfx) && sz == 4 @@ -10591,40 +10526,45 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 66 0F FD = PADDW */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFD) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "paddw", Iop_Add16x8, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F EC = PADDSB */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEC) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "paddsb", Iop_QAdd8Sx16, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F ED = PADDSW */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xED) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "paddsw", Iop_QAdd16Sx8, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F DC = PADDUSB */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDC) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "paddusb", Iop_QAdd8Ux16, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F DD = PADDUSW */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDD) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "paddusw", Iop_QAdd16Ux8, False ); -//.. goto decode_success; -//.. } + /* 66 0F FD = PADDW */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xFD) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "paddw", Iop_Add16x8, False ); + goto decode_success; + } + + /* 66 0F EC = PADDSB */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xEC) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "paddsb", Iop_QAdd8Sx16, False ); + goto decode_success; + } + + /* 66 0F ED = PADDSW */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xED) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "paddsw", Iop_QAdd16Sx8, False ); + goto decode_success; + } + + /* 66 0F DC = PADDUSB */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xDC) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "paddusb", Iop_QAdd8Ux16, False ); + goto decode_success; + } + + /* 66 0F DD = PADDUSW */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xDD) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "paddusw", Iop_QAdd16Ux8, False ); + goto decode_success; + } /* 66 0F DB = PAND */ if (have66noF2noF3(pfx) && sz == 2 @@ -10633,67 +10573,76 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 66 0F DF = PANDN */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDF) { -//.. delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "pandn", Iop_And128 ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F E0 = PAVGB */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE0) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pavgb", Iop_Avg8Ux16, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F E3 = PAVGW */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE3) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pavgw", Iop_Avg16Ux8, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 74 = PCMPEQB */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x74) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pcmpeqb", Iop_CmpEQ8x16, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 76 = PCMPEQD */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x76) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pcmpeqd", Iop_CmpEQ32x4, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 75 = PCMPEQW */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x75) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pcmpeqw", Iop_CmpEQ16x8, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 64 = PCMPGTB */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x64) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pcmpgtb", Iop_CmpGT8Sx16, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 66 = PCMPGTD */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x66) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pcmpgtd", Iop_CmpGT32Sx4, False ); -//.. goto decode_success; -//.. } -//.. -//.. /* 66 0F 65 = PCMPGTW */ -//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x65) { -//.. delta = dis_SSEint_E_to_G( sorb, delta+2, -//.. "pcmpgtw", Iop_CmpGT16Sx8, False ); -//.. goto decode_success; -//.. } + /* 66 0F DF = PANDN */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xDF) { + delta = dis_SSE_E_to_G_all_invG( pfx, delta+2, "pandn", Iop_AndV128 ); + goto decode_success; + } + + /* 66 0F E0 = PAVGB */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xE0) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pavgb", Iop_Avg8Ux16, False ); + goto decode_success; + } + + /* 66 0F E3 = PAVGW */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0xE3) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pavgw", Iop_Avg16Ux8, False ); + goto decode_success; + } + + /* 66 0F 74 = PCMPEQB */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x74) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pcmpeqb", Iop_CmpEQ8x16, False ); + goto decode_success; + } + + /* 66 0F 76 = PCMPEQD */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x76) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pcmpeqd", Iop_CmpEQ32x4, False ); + goto decode_success; + } + + /* 66 0F 75 = PCMPEQW */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x75) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pcmpeqw", Iop_CmpEQ16x8, False ); + goto decode_success; + } + + /* 66 0F 64 = PCMPGTB */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x64) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pcmpgtb", Iop_CmpGT8Sx16, False ); + goto decode_success; + } + + /* 66 0F 66 = PCMPGTD */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x66) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pcmpgtd", Iop_CmpGT32Sx4, False ); + goto decode_success; + } + + /* 66 0F 65 = PCMPGTW */ + if (have66noF2noF3(pfx) && sz == 2 + && insn[0] == 0x0F && insn[1] == 0x65) { + delta = dis_SSEint_E_to_G( pfx, delta+2, + "pcmpgtw", Iop_CmpGT16Sx8, False ); + goto decode_success; + } /* 66 0F C5 = PEXTRW -- extract 16-bit field from xmm(E) and put zero-extend of it in ireg(G). */ diff --git a/VEX/priv/host-amd64/hdefs.c b/VEX/priv/host-amd64/hdefs.c index 697f51eb8c..bf5a697e0e 100644 --- a/VEX/priv/host-amd64/hdefs.c +++ b/VEX/priv/host-amd64/hdefs.c @@ -607,10 +607,10 @@ HChar* showAMD64SseOp ( AMD64SseOp op ) { case Asse_ADD16: return "paddw"; case Asse_ADD32: return "paddd"; case Asse_ADD64: return "paddq"; -//.. case Xsse_QADD8U: return "paddusb"; -//.. case Xsse_QADD16U: return "paddusw"; -//.. case Xsse_QADD8S: return "paddsb"; -//.. case Xsse_QADD16S: return "paddsw"; + case Asse_QADD8U: return "paddusb"; + case Asse_QADD16U: return "paddusw"; + case Asse_QADD8S: return "paddsb"; + case Asse_QADD16S: return "paddsw"; case Asse_SUB8: return "psubb"; case Asse_SUB16: return "psubw"; case Asse_SUB32: return "psubd"; @@ -622,18 +622,18 @@ HChar* showAMD64SseOp ( AMD64SseOp op ) { case Asse_MUL16: return "pmullw"; case Asse_MULHI16U: return "pmulhuw"; case Asse_MULHI16S: return "pmulhw"; -//.. case Xsse_AVG8U: return "pavgb"; -//.. case Xsse_AVG16U: return "pavgw"; + case Asse_AVG8U: return "pavgb"; + case Asse_AVG16U: return "pavgw"; case Asse_MAX16S: return "pmaxw"; case Asse_MAX8U: return "pmaxub"; case Asse_MIN16S: return "pminw"; case Asse_MIN8U: return "pminub"; -//.. case Xsse_CMPEQ8: return "pcmpeqb"; -//.. case Xsse_CMPEQ16: return "pcmpeqw"; + case Asse_CMPEQ8: return "pcmpeqb"; + case Asse_CMPEQ16: return "pcmpeqw"; case Asse_CMPEQ32: return "pcmpeqd"; -//.. case Xsse_CMPGT8S: return "pcmpgtb"; -//.. case Xsse_CMPGT16S: return "pcmpgtw"; -//.. case Xsse_CMPGT32S: return "pcmpgtd"; + case Asse_CMPGT8S: return "pcmpgtb"; + case Asse_CMPGT16S: return "pcmpgtw"; + case Asse_CMPGT32S: return "pcmpgtd"; case Asse_SHL16: return "psllw"; case Asse_SHL32: return "pslld"; case Asse_SHL64: return "psllq"; @@ -3222,9 +3222,9 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i ) *p++ = 0x0F; switch (i->Ain.Sse64Fx2.op) { case Asse_ADDF: *p++ = 0x58; break; -//.. case Xsse_DIVF: *p++ = 0x5E; break; -//.. case Xsse_MAXF: *p++ = 0x5F; break; -//.. case Xsse_MINF: *p++ = 0x5D; break; + case Asse_DIVF: *p++ = 0x5E; break; + case Asse_MAXF: *p++ = 0x5F; break; + case Asse_MINF: *p++ = 0x5D; break; case Asse_MULF: *p++ = 0x59; break; //.. case Xsse_RCPF: *p++ = 0x53; break; //.. case Xsse_RSQRTF: *p++ = 0x52; break; @@ -3314,21 +3314,21 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i ) case Asse_PACKSSW: XX(0x66); XX(rex); XX(0x0F); XX(0x63); break; case Asse_PACKUSW: XX(0x66); XX(rex); XX(0x0F); XX(0x67); break; case Asse_ADD8: XX(0x66); XX(rex); XX(0x0F); XX(0xFC); break; -//.. case Xsse_ADD16: XX(0x66); XX(rex); XX(0x0F); XX(0xFD); break; + case Asse_ADD16: XX(0x66); XX(rex); XX(0x0F); XX(0xFD); break; case Asse_ADD32: XX(0x66); XX(rex); XX(0x0F); XX(0xFE); break; case Asse_ADD64: XX(0x66); XX(rex); XX(0x0F); XX(0xD4); break; -//.. case Xsse_QADD8S: XX(0x66); XX(rex); XX(0x0F); XX(0xEC); break; -//.. case Xsse_QADD16S: XX(0x66); XX(rex); XX(0x0F); XX(0xED); break; -//.. case Xsse_QADD8U: XX(0x66); XX(rex); XX(0x0F); XX(0xDC); break; -//.. case Xsse_QADD16U: XX(0x66); XX(rex); XX(0x0F); XX(0xDD); break; -//.. case Xsse_AVG8U: XX(0x66); XX(rex); XX(0x0F); XX(0xE0); break; -//.. case Xsse_AVG16U: XX(0x66); XX(rex); XX(0x0F); XX(0xE3); break; -//.. case Xsse_CMPEQ8: XX(0x66); XX(rex); XX(0x0F); XX(0x74); break; -//.. case Xsse_CMPEQ16: XX(0x66); XX(rex); XX(0x0F); XX(0x75); break; + case Asse_QADD8S: XX(0x66); XX(rex); XX(0x0F); XX(0xEC); break; + case Asse_QADD16S: XX(0x66); XX(rex); XX(0x0F); XX(0xED); break; + case Asse_QADD8U: XX(0x66); XX(rex); XX(0x0F); XX(0xDC); break; + case Asse_QADD16U: XX(0x66); XX(rex); XX(0x0F); XX(0xDD); break; + case Asse_AVG8U: XX(0x66); XX(rex); XX(0x0F); XX(0xE0); break; + case Asse_AVG16U: XX(0x66); XX(rex); XX(0x0F); XX(0xE3); break; + case Asse_CMPEQ8: XX(0x66); XX(rex); XX(0x0F); XX(0x74); break; + case Asse_CMPEQ16: XX(0x66); XX(rex); XX(0x0F); XX(0x75); break; case Asse_CMPEQ32: XX(0x66); XX(rex); XX(0x0F); XX(0x76); break; -//.. case Xsse_CMPGT8S: XX(0x66); XX(rex); XX(0x0F); XX(0x64); break; -//.. case Xsse_CMPGT16S: XX(0x66); XX(rex); XX(0x0F); XX(0x65); break; -//.. case Xsse_CMPGT32S: XX(0x66); XX(rex); XX(0x0F); XX(0x66); break; + case Asse_CMPGT8S: XX(0x66); XX(rex); XX(0x0F); XX(0x64); break; + case Asse_CMPGT16S: XX(0x66); XX(rex); XX(0x0F); XX(0x65); break; + case Asse_CMPGT32S: XX(0x66); XX(rex); XX(0x0F); XX(0x66); break; case Asse_MAX16S: XX(0x66); XX(rex); XX(0x0F); XX(0xEE); break; case Asse_MAX8U: XX(0x66); XX(rex); XX(0x0F); XX(0xDE); break; case Asse_MIN16S: XX(0x66); XX(rex); XX(0x0F); XX(0xEA); break; diff --git a/VEX/priv/host-amd64/hdefs.h b/VEX/priv/host-amd64/hdefs.h index 0455063618..b1e40bc9b1 100644 --- a/VEX/priv/host-amd64/hdefs.h +++ b/VEX/priv/host-amd64/hdefs.h @@ -324,22 +324,21 @@ typedef Asse_AND, Asse_OR, Asse_XOR, Asse_ANDN, //.. /* Integer binary */ Asse_ADD8, Asse_ADD16, Asse_ADD32, Asse_ADD64, -//.. Xsse_QADD8U, Xsse_QADD16U, -//.. Xsse_QADD8S, Xsse_QADD16S, + Asse_QADD8U, Asse_QADD16U, + Asse_QADD8S, Asse_QADD16S, Asse_SUB8, Asse_SUB16, Asse_SUB32, Asse_SUB64, Asse_QSUB8U, Asse_QSUB16U, Asse_QSUB8S, Asse_QSUB16S, Asse_MUL16, Asse_MULHI16U, Asse_MULHI16S, -//.. Xsse_AVG8U, Xsse_AVG16U, + Asse_AVG8U, Asse_AVG16U, Asse_MAX16S, Asse_MAX8U, Asse_MIN16S, Asse_MIN8U, -//.. Xsse_CMPEQ8, Xsse_CMPEQ16, - Asse_CMPEQ32, -//.. Xsse_CMPGT8S, Xsse_CMPGT16S, Xsse_CMPGT32S, + Asse_CMPEQ8, Asse_CMPEQ16, Asse_CMPEQ32, + Asse_CMPGT8S, Asse_CMPGT16S, Asse_CMPGT32S, Asse_SHL16, Asse_SHL32, Asse_SHL64, Asse_SHR16, Asse_SHR32, Asse_SHR64, Asse_SAR16, Asse_SAR32, diff --git a/VEX/priv/host-amd64/isel.c b/VEX/priv/host-amd64/isel.c index 1c82befe6f..1bc7d684cf 100644 --- a/VEX/priv/host-amd64/isel.c +++ b/VEX/priv/host-amd64/isel.c @@ -2634,20 +2634,17 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ) return res; } -//.. if (e->tag == Iex_Unop -//.. && e->Iex.Unop.op == Iop_ReinterpI32asF32) { -//.. /* Given an I32, produce an IEEE754 float with the same bit -//.. pattern. */ -//.. HReg dst = newVRegF(env); -//.. X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg); -//.. /* paranoia */ -//.. addInstr(env, X86Instr_Push(rmi)); -//.. addInstr(env, X86Instr_FpLdSt( -//.. True/*load*/, 4, dst, -//.. X86AMode_IR(0, hregX86_ESP()))); -//.. add_to_esp(env, 4); -//.. return dst; -//.. } + if (e->tag == Iex_Unop + && e->Iex.Unop.op == Iop_ReinterpI32asF32) { + /* Given an I32, produce an IEEE754 float with the same bit + pattern. */ + HReg dst = newVRegV(env); + HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); + AMD64AMode* m4_rsp = AMD64AMode_IR(-4, hregAMD64_RSP()); + addInstr(env, AMD64Instr_Store(4, src, m4_rsp)); + addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 4, dst, m4_rsp )); + return dst; + } ppIRExpr(e); vpanic("iselFltExpr_wrk"); @@ -3320,9 +3317,9 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ) case Iop_CmpLT64Fx2: op = Asse_CMPLTF; goto do_64Fx2; case Iop_CmpLE64Fx2: op = Asse_CMPLEF; goto do_64Fx2; case Iop_Add64Fx2: op = Asse_ADDF; goto do_64Fx2; -//.. case Iop_Div64Fx2: op = Xsse_DIVF; goto do_64Fx2; -//.. case Iop_Max64Fx2: op = Xsse_MAXF; goto do_64Fx2; -//.. case Iop_Min64Fx2: op = Xsse_MINF; goto do_64Fx2; + case Iop_Div64Fx2: op = Asse_DIVF; goto do_64Fx2; + case Iop_Max64Fx2: op = Asse_MAXF; goto do_64Fx2; + case Iop_Min64Fx2: op = Asse_MINF; goto do_64Fx2; case Iop_Mul64Fx2: op = Asse_MULF; goto do_64Fx2; case Iop_Sub64Fx2: op = Asse_SUBF; goto do_64Fx2; do_64Fx2: @@ -3400,21 +3397,21 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ) case Iop_OrV128: op = Asse_OR; goto do_SseReRg; case Iop_XorV128: op = Asse_XOR; goto do_SseReRg; case Iop_Add8x16: op = Asse_ADD8; goto do_SseReRg; -//.. case Iop_Add16x8: op = Xsse_ADD16; goto do_SseReRg; + case Iop_Add16x8: op = Asse_ADD16; goto do_SseReRg; case Iop_Add32x4: op = Asse_ADD32; goto do_SseReRg; case Iop_Add64x2: op = Asse_ADD64; goto do_SseReRg; -//.. case Iop_QAdd8Sx16: op = Xsse_QADD8S; goto do_SseReRg; -//.. case Iop_QAdd16Sx8: op = Xsse_QADD16S; goto do_SseReRg; -//.. case Iop_QAdd8Ux16: op = Xsse_QADD8U; goto do_SseReRg; -//.. case Iop_QAdd16Ux8: op = Xsse_QADD16U; goto do_SseReRg; -//.. case Iop_Avg8Ux16: op = Xsse_AVG8U; goto do_SseReRg; -//.. case Iop_Avg16Ux8: op = Xsse_AVG16U; goto do_SseReRg; -//.. case Iop_CmpEQ8x16: op = Xsse_CMPEQ8; goto do_SseReRg; -//.. case Iop_CmpEQ16x8: op = Xsse_CMPEQ16; goto do_SseReRg; -//.. case Iop_CmpEQ32x4: op = Xsse_CMPEQ32; goto do_SseReRg; -//.. case Iop_CmpGT8Sx16: op = Xsse_CMPGT8S; goto do_SseReRg; -//.. case Iop_CmpGT16Sx8: op = Xsse_CMPGT16S; goto do_SseReRg; -//.. case Iop_CmpGT32Sx4: op = Xsse_CMPGT32S; goto do_SseReRg; + case Iop_QAdd8Sx16: op = Asse_QADD8S; goto do_SseReRg; + case Iop_QAdd16Sx8: op = Asse_QADD16S; goto do_SseReRg; + case Iop_QAdd8Ux16: op = Asse_QADD8U; goto do_SseReRg; + case Iop_QAdd16Ux8: op = Asse_QADD16U; goto do_SseReRg; + case Iop_Avg8Ux16: op = Asse_AVG8U; goto do_SseReRg; + case Iop_Avg16Ux8: op = Asse_AVG16U; goto do_SseReRg; + case Iop_CmpEQ8x16: op = Asse_CMPEQ8; goto do_SseReRg; + case Iop_CmpEQ16x8: op = Asse_CMPEQ16; goto do_SseReRg; + case Iop_CmpEQ32x4: op = Asse_CMPEQ32; goto do_SseReRg; + case Iop_CmpGT8Sx16: op = Asse_CMPGT8S; goto do_SseReRg; + case Iop_CmpGT16Sx8: op = Asse_CMPGT16S; goto do_SseReRg; + case Iop_CmpGT32Sx4: op = Asse_CMPGT32S; goto do_SseReRg; case Iop_Max16Sx8: op = Asse_MAX16S; goto do_SseReRg; case Iop_Max8Ux16: op = Asse_MAX8U; goto do_SseReRg; case Iop_Min16Sx8: op = Asse_MIN16S; goto do_SseReRg;