UChar second_byte,
UChar third_byte,
UChar fourth_byte,
- Int ireg )
+ Int ireg,
+ Bool reads_ireg )
{
VG_(new_emit)(True, uses_sflags, sets_sflags);
VG_(emitB) ( first_byte );
fourth_byte |= (ireg & 7); /* patch in our ireg */
VG_(emitB) ( fourth_byte );
if (dis)
- VG_(printf)("\n\t\tsse-reg-to-xmmreg--0x%x:0x%x:0x%x:0x%x-(%s)\n",
- (UInt)first_byte, (UInt)second_byte,
- (UInt)third_byte, (UInt)fourth_byte,
- nameIReg(4,ireg) );
+ VG_(printf)(
+ reads_ireg
+ ? "\n\t\tireg-to-ssereg--0x%x:0x%x:0x%x:0x%x-(%s)\n"
+ : "\n\t\tssereg-to-ireg--0x%x:0x%x:0x%x:0x%x-(%s)\n",
+ (UInt)first_byte, (UInt)second_byte,
+ (UInt)third_byte, (UInt)fourth_byte,
+ nameIReg(4,ireg)
+ );
}
static void emit_SSE4 ( FlagSet uses_sflags,
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == Lit16);
vg_assert(u->tag3 == RealReg);
- vg_assert(!anyFlagUse(u));
if (!(*sselive)) {
emit_get_sse_state();
*sselive = True;
break;
case SSE3g_RegRd:
+ case SSE3g_RegWr:
vg_assert(u->size == 4);
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == Lit16);
u->val1 & 0xFF,
(u->val2 >> 8) & 0xFF,
u->val2 & 0xFF,
- u->val3 );
+ u->val3,
+ u->opcode==SSE3g_RegRd ? True : False );
break;
case SSE4:
UChar opc2,
UChar opc3 )
{
+ UChar dis_buf[50];
UChar modrm = getUChar(eip);
if (epartIsReg(modrm)) {
/* Completely internal SSE insn. */
nameXMMReg(gregOfRM(modrm)) );
eip++;
} else {
- VG_(core_panic)("dis_SSE3_reg_or_mem: mem");
+ UInt pair = disAMode ( cb, sorb, eip, dis?dis_buf:NULL );
+ Int tmpa = LOW24(pair);
+ eip += HI8(pair);
+ uInstr3(cb, SSE3a_MemRd, sz,
+ Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
+ Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm),
+ TempReg, tmpa);
+ if (dis)
+ VG_(printf)("%s %s, %s\n",
+ name,
+ dis_buf,
+ nameXMMReg(gregOfRM(modrm)));
}
return eip;
}
goto decode_success;
}
- /* CVTSI2SS -- convert int reg to low 4 bytes of XMM reg. */
- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
+ /* CVTTSD2SI -- convert a double-precision float value in memory or
+ xmm reg to int and put it in an ireg. */
+ if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x2C) {
+ vg_assert(sz == 4);
+ modrm = insn[3];
+ if (epartIsReg(modrm)) {
+ /* We're moving a value in an xmm reg to an ireg. */
+ eip += 4;
+ t1 = newTemp(cb);
+ uInstr3(cb, SSE3g_RegWr, 4,
+ Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+ Lit16, (((UShort)insn[2]) << 8) | (UShort)modrm,
+ TempReg, t1 );
+ uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
+ if (dis)
+ VG_(printf)("cvttsd2si %s, %s\n",
+ nameXMMReg(eregOfRM(modrm)),
+ nameIReg(4,gregOfRM(modrm)) );
+ } else {
+#if 0
+ /* So, we're reading memory and writing an ireg. This calls
+ for the ultra-horrible SSE3ag_MemRd_RegWr uinstr. */
+ t1 = newTemp(cb); /* t1 holds value on its way to ireg */
+ pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL );
+ t2 = LOW24(pair); /* t2 holds addr */
+ eip += 3+HI8(pair);
+ uInstr2(cb, SSE3ag_MemRd_RegWr, 8,
+ TempReg, t2, /* address */
+ TempReg, t1 /* dest */);
+ uLiteral(cb, (((UInt)insn[0]) << 16)
+ | (((UInt)insn[1]) << 8)
+ | ((UInt)insn[2]) );
+ uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
+ /* PRINTING CODE */
+#endif
+ VG_(core_panic)("CVTTSD2SI mem");
+ }
+ goto decode_success;
+ }
+
+ /* CVTSI2SS -- convert int reg, or int value in memory, to low 4
+ bytes of XMM reg. */
+ /* CVTSI2SD -- convert int reg, or int value in memory, to low 8
+ bytes of XMM reg. */
+ if ((insn[0] == 0xF3 /*CVTSI2SS*/ || insn[0] == 0xF2 /* CVTSI2SD*/)
+ && insn[1] == 0x0F && insn[2] == 0x2A) {
+ Char* s_or_d = insn[0]==0xF3 ? "s" : "d";
vg_assert(sz == 4);
modrm = insn[3];
t1 = newTemp(cb);
TempReg, t1 );
eip += 4;
if (dis)
- VG_(printf)("cvtsi2ss %s, %s\n", nameIReg(4,eregOfRM(modrm)),
- nameXMMReg(gregOfRM(modrm)));
+ VG_(printf)("cvtsi2s%s %s, %s\n", s_or_d,
+ nameIReg(4,eregOfRM(modrm)),
+ nameXMMReg(gregOfRM(modrm)));
} else {
pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL );
t2 = LOW24(pair);
Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3],
TempReg, t1 );
if (dis)
- VG_(printf)("cvtsi2ss %s, %s\n", dis_buf,
- nameXMMReg(gregOfRM(modrm)));
+ VG_(printf)("cvtsi2s%s %s, %s\n", s_or_d,
+ dis_buf,
+ nameXMMReg(gregOfRM(modrm)));
}
goto decode_success;
}
goto decode_success;
}
+ /* CVTSD2SS -- convert one single double. to float. */
+ if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
+ vg_assert(sz == 4);
+ eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "cvtsd2ss",
+ insn[0], insn[1], insn[2] );
+ goto decode_success;
+ }
+
/* SHUFPS */
if (insn[0] == 0x0F && insn[1] == 0xC6) {
vg_assert(sz == 4);
goto decode_success;
}
+ /* DIVSD */
+ if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5E) {
+ vg_assert(sz == 4);
+ eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "divsd",
+ insn[0], insn[1], insn[2] );
+ goto decode_success;
+ }
+
+ /* ADDSD */
+ if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
+ vg_assert(sz == 4);
+ eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "addsd",
+ insn[0], insn[1], insn[2] );
+ goto decode_success;
+ }
+
/* ADDPS */
if (insn[0] == 0x0F && insn[1] == 0x58) {
vg_assert(sz == 4);
goto decode_success;
}
+ /* COMISD (src)xmmreg-or-mem, (dst)xmmreg */
+ if (sz == 2
+ && insn[0] == 0x0F && insn[1] == 0x2F) {
+ eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 8, "comisd",
+ 0x66, insn[0], insn[1] );
+ vg_assert(LAST_UINSTR(cb).opcode == SSE3a_MemRd
+ || LAST_UINSTR(cb).opcode == SSE4);
+ uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+ goto decode_success;
+ }
+
/* MOVSD -- move 8 bytes of XMM reg to/from XMM reg or mem. */
if (insn[0] == 0xF2
&& insn[1] == 0x0F
case SSE2a_MemWr: return LIT0 && SZ416 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
case SSE2a_MemRd: return LIT0 && SZ416 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
case SSE3a_MemWr: return LIT0 && SZsse && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
- case SSE3a_MemRd: return LIT0 && SZsse && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
+ case SSE3a_MemRd: return LIT0 && SZsse && CCf && Ls1 && Ls2 && TR3 && XOTHER;
case SSE3g_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
+ case SSE3g_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
case SSE3: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER;
case SSE4: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER;
default:
case SSE2a_MemWr: return "SSE2a_MWr";
case SSE2a_MemRd: return "SSE2a_MRd";
case SSE3g_RegRd: return "SSE3g_RRd";
+ case SSE3g_RegWr: return "SSE3g_RWr";
case SSE3: return "SSE3";
case SSE4: return "SSE4";
case SSE3a_MemWr: return "SSE3a_MWr";
break;
case SSE3g_RegRd:
+ case SSE3g_RegWr:
VG_(printf)("0x%x:0x%x:0x%x:0x%x",
(u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
(u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
case SSE3a_MemWr:
case SSE3a_MemRd:
case SSE2a_MemWr:
- case SSE2a_MemRd: RD(3);
+ case SSE2a_MemRd: RD(3); break;
+
+ case SSE3g_RegWr: WR(3); break;
case MMX2_RegRd: RD(2); break;
case MMX2_RegWr: WR(2); break;
case MMX2_RegRd: case MMX2_RegWr:
case SSE2a_MemWr: case SSE2a_MemRd:
case SSE3a_MemWr: case SSE3a_MemRd:
- case SSE3g_RegRd:
+ case SSE3g_RegRd: case SSE3g_RegWr:
case SSE4: case SSE3:
case WIDEN:
/* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
UChar* final_code;
UCodeBlock* cb;
Bool notrace_until_done;
- Int notrace_until_limit = 0;
+ Int notrace_until_limit = 15000;
VGP_PUSHCC(VgpTranslate);
debugging_translation