memory.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1507
second_byte |= (ireg & 7); /* patch in our ireg */
VG_(emitB) ( second_byte );
if (dis)
- VG_(printf)("\n\t\tmmx2reg-to-mmxreg--0x%x:0x%x-(%s)\n",
+ VG_(printf)("\n\t\tmmx2:reg-to-mmxreg--0x%x:0x%x-(%s)\n",
+ (UInt)first_byte, (UInt)second_byte,
+ nameIReg(4,ireg) );
+}
+
+static void emit_MMX2_mmxreg_to_reg ( FlagSet uses_sflags,
+ FlagSet sets_sflags,
+ UChar first_byte,
+ UChar second_byte,
+ Int ireg )
+{
+ VG_(new_emit)(True, uses_sflags, sets_sflags);
+ VG_(emitB) ( 0x0F );
+ VG_(emitB) ( first_byte );
+ second_byte &= 0x38; /* mask out mod and rm fields */
+ second_byte |= 0xC0; /* set top two bits: mod = 11b */
+ second_byte |= (ireg & 7); /* patch in our ireg */
+ VG_(emitB) ( second_byte );
+ if (dis)
+ VG_(printf)("\n\t\tmmx2:mmxreg-to-reg--0x%x:0x%x-(%s)\n",
(UInt)first_byte, (UInt)second_byte,
nameIReg(4,ireg) );
}
first_byte, second_byte, ireg );
}
+static void synth_MMX2_mmxreg_to_reg ( Bool uses_flags, Bool sets_flags,
+ UChar first_byte,
+ UChar second_byte,
+ Int ireg )
+{
+ emit_MMX2_mmxreg_to_reg ( uses_flags, sets_flags,
+ first_byte, second_byte, ireg );
+}
+
static void synth_MMX2_no_mem ( Bool uses_flags, Bool sets_flags,
UChar first_byte,
UChar second_byte )
case MMX2_MemWr:
case MMX2_MemRd:
+ vg_assert(u->size == 4 || u->size == 8);
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == RealReg);
vg_assert(u->tag3 == NoValue);
u->val2 );
break;
+ case MMX2_RegWr:
+ vg_assert(u->tag1 == Lit16);
+ vg_assert(u->tag2 == RealReg);
+ vg_assert(u->tag3 == NoValue);
+ vg_assert(!anyFlagUse(u));
+ if (!(*fplive)) {
+ emit_get_fpu_state();
+ *fplive = True;
+ }
+ synth_MMX2_mmxreg_to_reg ( u->flags_r, u->flags_w,
+ (u->val1 >> 8) & 0xFF,
+ u->val1 & 0xFF,
+ u->val2 );
+ break;
+
case MMX1:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);
VG_(printf)("emms\n");
break;
+ case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
+ vg_assert(sz == 4);
+ modrm = getUChar(eip);
+ if (epartIsReg(modrm)) {
+ eip++;
+ t1 = newTemp(cb);
+ uInstr2(cb, MMX2_RegWr, 4,
+ Lit16,
+ (((UShort)(opc)) << 8) | ((UShort)modrm),
+ TempReg, t1 );
+ uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, eregOfRM(modrm));
+ if (dis)
+ VG_(printf)("movd %s, %s\n",
+ nameMMXReg(gregOfRM(modrm)),
+ nameIReg(4,eregOfRM(modrm)));
+ } else {
+ Int tmpa;
+ pair = disAMode ( cb, sorb, eip, dis?dis_buf:NULL );
+ tmpa = LOW24(pair);
+ eip += HI8(pair);
+ uInstr2(cb, MMX2_MemWr, 4,
+ Lit16,
+ (((UShort)(opc)) << 8) | ((UShort)modrm),
+ TempReg, tmpa);
+ if (dis)
+ VG_(printf)("movd %s, %s\n",
+ nameMMXReg(gregOfRM(modrm)),
+ dis_buf);
+ }
+ break;
+
case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
vg_assert(sz == 4);
modrm = getUChar(eip);
case MMX2: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
case MMX3: return LIT0 && SZ0 && CC0 && Ls1 && Ls1 && N3 && XOTHER;
case MMX2_MemRd: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER;
- case MMX2_MemWr: return LIT0 && SZ8 && CC0 && Ls1 && TR2 && N3 && XOTHER;
+ case MMX2_MemWr: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER;
case MMX2_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER;
+ case MMX2_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER;
default:
if (VG_(needs).extended_UCode)
return SK_(sane_XUInstr)(beforeRA, beforeLiveness, u);
case MMX2_MemRd: return "MMX2_MRd" ;
case MMX2_MemWr: return "MMX2_MWr" ;
case MMX2_RegRd: return "MMX2_RRd" ;
+ case MMX2_RegWr: return "MMX2_RWr" ;
default:
if (VG_(needs).extended_UCode)
return SK_(name_XUOpcode)(opc);
(u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
break;
+ case MMX2_RegWr:
case MMX2_RegRd:
VG_(printf)("\t0x%x:0x%x, ",
(u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
case LEA2: RD(1); RD(2); WR(3); break;
case MMX2_RegRd: RD(2); break;
+ case MMX2_RegWr: WR(2); break;
case MMX1: case MMX2: case MMX3:
case NOP: case FPU: case INCEIP: case CALLM_S: case CALLM_E:
case FPU: case FPU_R: case FPU_W:
case MMX1: case MMX2: case MMX3:
case MMX2_MemRd: case MMX2_MemWr:
- case MMX2_RegRd:
+ case MMX2_RegRd: case MMX2_RegWr:
case WIDEN:
/* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
case GETSEG: case PUTSEG:
VG_(copy_UInstr)(cb, u_in);
break;
+ /* The MMX register is assumed to be fully defined, so
+ that's what this register becomes. */
case MMX2_RegWr:
- VG_(skin_panic)(
- "I don't know how to instrument MMX2_RegWr (yet)");
+ sk_assert(u_in->tag2 == TempReg);
+ sk_assert(u_in->size == 4);
+ uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
+ VG_(copy_UInstr)(cb, u_in);
break;
default: