From 61bced70146df4a94830723da06c3a5b1aa0da34 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Thu, 3 Aug 2006 15:03:19 +0000 Subject: [PATCH] Handle all SSE3 instructions except monitor and mwait. 64-bit equivalents to follow soon. git-svn-id: svn://svn.valgrind.org/vex/trunk@1635 --- VEX/priv/guest-x86/toIR.c | 183 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 7ac9f455f0..e349cd0cf5 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -4274,6 +4274,13 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) loadLE(Ity_I32, mkexpr(addr)))); break; + case 1: /* FISTTPL m32 (SSE3) */ + DIP("fisttpl %s\n", dis_buf); + storeLE( mkexpr(addr), + binop(Iop_F64toI32, mkU32(Irrm_ZERO), get_ST(0)) ); + fp_pop(); + break; + case 2: /* FIST m32 */ DIP("fistl %s\n", dis_buf); storeLE( mkexpr(addr), @@ -4576,6 +4583,13 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) put_ST(0, loadLE(Ity_F64, mkexpr(addr))); break; + case 1: /* FISTTPQ m64 (SSE3) */ + DIP("fistppll %s\n", dis_buf); + storeLE( mkexpr(addr), + binop(Iop_F64toI64, mkU32(Irrm_ZERO), get_ST(0)) ); + fp_pop(); + break; + case 2: /* FST double-real */ DIP("fstl %s\n", dis_buf); storeLE(mkexpr(addr), get_ST(0)); @@ -4939,6 +4953,13 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) loadLE(Ity_I16, mkexpr(addr))))); break; + case 1: /* FISTTPS m16 (SSE3) */ + DIP("fisttps %s\n", dis_buf); + storeLE( mkexpr(addr), + binop(Iop_F64toI16, mkU32(Irrm_ZERO), get_ST(0)) ); + fp_pop(); + break; + case 2: /* FIST m16 */ DIP("fistp %s\n", dis_buf); storeLE( mkexpr(addr), @@ -10603,6 +10624,31 @@ DisResult disInstr_X86_WRK ( goto decode_success; } + /* F2 0F 12 = MOVDDUP -- move from E (mem or xmm) to G (xmm), + duplicating some lanes (0:1:0:1). */ + if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x12) { + IRTemp sV = newTemp(Ity_V128); + IRTemp d0 = newTemp(Ity_I64); + + modrm = insn[3]; + if (epartIsReg(modrm)) { + assign( sV, getXMMReg( eregOfRM(modrm)) ); + DIP("movddup %s,%s\n", nameXMMReg(eregOfRM(modrm)), + nameXMMReg(gregOfRM(modrm))); + delta += 3+1; + assign ( d0, unop(Iop_V128to64, mkexpr(sV)) ); + } else { + addr = disAMode ( &alen, sorb, delta+3, dis_buf ); + assign( d0, loadLE(Ity_I64, mkexpr(addr)) ); + DIP("movddup %s,%s\n", dis_buf, + nameXMMReg(gregOfRM(modrm))); + delta += 3+alen; + } + + putXMMReg( gregOfRM(modrm), binop(Iop_64HLtoV128,mkexpr(d0),mkexpr(d0)) ); + goto decode_success; + } + /* F2 0F D0 = ADDSUBPS -- 32x4 +/-/+/- from E (mem or xmm) to G (xmm). */ if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xD0) { IRTemp a3, a2, a1, a0, s3, s2, s1, s0; @@ -10638,6 +10684,143 @@ DisResult disInstr_X86_WRK ( goto decode_success; } + /* 66 0F D0 = ADDSUBPD -- 64x4 +/- from E (mem or xmm) to G (xmm). */ + if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD0) { + IRTemp eV = newTemp(Ity_V128); + IRTemp gV = newTemp(Ity_V128); + IRTemp addV = newTemp(Ity_V128); + IRTemp subV = newTemp(Ity_V128); + IRTemp a1 = newTemp(Ity_I64); + IRTemp s0 = newTemp(Ity_I64); + + modrm = insn[2]; + if (epartIsReg(modrm)) { + assign( eV, getXMMReg( eregOfRM(modrm)) ); + DIP("addsubpd %s,%s\n", nameXMMReg(eregOfRM(modrm)), + nameXMMReg(gregOfRM(modrm))); + delta += 2+1; + } else { + addr = disAMode ( &alen, sorb, delta+2, dis_buf ); + assign( eV, loadLE(Ity_V128, mkexpr(addr)) ); + DIP("addsubpd %s,%s\n", dis_buf, + nameXMMReg(gregOfRM(modrm))); + delta += 2+alen; + } + + assign( gV, getXMMReg(gregOfRM(modrm)) ); + + assign( addV, binop(Iop_Add64Fx2, mkexpr(gV), mkexpr(eV)) ); + assign( subV, binop(Iop_Sub64Fx2, mkexpr(gV), mkexpr(eV)) ); + + assign( a1, unop(Iop_V128HIto64, mkexpr(addV) )); + assign( s0, unop(Iop_V128to64, mkexpr(subV) )); + + putXMMReg( gregOfRM(modrm), + binop(Iop_64HLtoV128, mkexpr(a1), mkexpr(s0)) ); + goto decode_success; + } + + /* F2 0F 7D = HSUBPS -- 32x4 sub across from E (mem or xmm) to G (xmm). */ + /* F2 0F 7C = HADDPS -- 32x4 add across from E (mem or xmm) to G (xmm). */ + if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F + && (insn[2] == 0x7C || insn[2] == 0x7D)) { + IRTemp e3, e2, e1, e0, g3, g2, g1, g0; + IRTemp eV = newTemp(Ity_V128); + IRTemp gV = newTemp(Ity_V128); + IRTemp leftV = newTemp(Ity_V128); + IRTemp rightV = newTemp(Ity_V128); + Bool isAdd = insn[2] == 0x7C; + HChar* str = isAdd ? "add" : "sub"; + e3 = e2 = e1 = e0 = g3 = g2 = g1 = g0 = IRTemp_INVALID; + + modrm = insn[3]; + if (epartIsReg(modrm)) { + assign( eV, getXMMReg( eregOfRM(modrm)) ); + DIP("h%sps %s,%s\n", str, nameXMMReg(eregOfRM(modrm)), + nameXMMReg(gregOfRM(modrm))); + delta += 3+1; + } else { + addr = disAMode ( &alen, sorb, delta+3, dis_buf ); + assign( eV, loadLE(Ity_V128, mkexpr(addr)) ); + DIP("h%sps %s,%s\n", str, dis_buf, + nameXMMReg(gregOfRM(modrm))); + delta += 3+alen; + } + + assign( gV, getXMMReg(gregOfRM(modrm)) ); + + breakup128to32s( eV, &e3, &e2, &e1, &e0 ); + breakup128to32s( gV, &g3, &g2, &g1, &g0 ); + + assign( leftV, mk128from32s( e2, e0, g2, g0 ) ); + assign( rightV, mk128from32s( e3, e1, g3, g1 ) ); + + putXMMReg( gregOfRM(modrm), + binop(isAdd ? Iop_Add32Fx4 : Iop_Sub32Fx4, + mkexpr(leftV), mkexpr(rightV) ) ); + goto decode_success; + } + + /* 66 0F 7D = HSUBPD -- 64x2 sub across from E (mem or xmm) to G (xmm). */ + /* 66 0F 7C = HADDPD -- 64x2 add across from E (mem or xmm) to G (xmm). */ + if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x7C || insn[1] == 0x7D)) { + IRTemp e1 = newTemp(Ity_I64); + IRTemp e0 = newTemp(Ity_I64); + IRTemp g1 = newTemp(Ity_I64); + IRTemp g0 = newTemp(Ity_I64); + IRTemp eV = newTemp(Ity_V128); + IRTemp gV = newTemp(Ity_V128); + IRTemp leftV = newTemp(Ity_V128); + IRTemp rightV = newTemp(Ity_V128); + Bool isAdd = insn[1] == 0x7C; + HChar* str = isAdd ? "add" : "sub"; + + modrm = insn[2]; + if (epartIsReg(modrm)) { + assign( eV, getXMMReg( eregOfRM(modrm)) ); + DIP("h%spd %s,%s\n", str, nameXMMReg(eregOfRM(modrm)), + nameXMMReg(gregOfRM(modrm))); + delta += 2+1; + } else { + addr = disAMode ( &alen, sorb, delta+2, dis_buf ); + assign( eV, loadLE(Ity_V128, mkexpr(addr)) ); + DIP("h%spd %s,%s\n", str, dis_buf, + nameXMMReg(gregOfRM(modrm))); + delta += 2+alen; + } + + assign( gV, getXMMReg(gregOfRM(modrm)) ); + + assign( e1, unop(Iop_V128HIto64, mkexpr(eV) )); + assign( e0, unop(Iop_V128to64, mkexpr(eV) )); + assign( g1, unop(Iop_V128HIto64, mkexpr(gV) )); + assign( g0, unop(Iop_V128to64, mkexpr(gV) )); + + assign( leftV, binop(Iop_64HLtoV128, mkexpr(e0),mkexpr(g0)) ); + assign( rightV, binop(Iop_64HLtoV128, mkexpr(e1),mkexpr(g1)) ); + + putXMMReg( gregOfRM(modrm), + binop(isAdd ? Iop_Add64Fx2 : Iop_Sub64Fx2, + mkexpr(leftV), mkexpr(rightV) ) ); + goto decode_success; + } + + /* F2 0F F0 = LDDQU -- move from E (mem or xmm) to G (xmm). */ + if (sz == 4 && insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xF0) { + modrm = getIByte(delta+3); + if (epartIsReg(modrm)) { + goto decode_failure; + } else { + addr = disAMode ( &alen, sorb, delta+3, dis_buf ); + putXMMReg( gregOfRM(modrm), + loadLE(Ity_V128, mkexpr(addr)) ); + DIP("lddqu %s,%s\n", dis_buf, + nameXMMReg(gregOfRM(modrm))); + delta += 3+alen; + } + goto decode_success; + } + /* ---------------------------------------------------- */ /* --- end of the SSE3 decoder. --- */ /* ---------------------------------------------------- */ -- 2.47.2