From: Julian Seward Date: Fri, 4 Apr 2003 20:40:34 +0000 (+0000) Subject: Implement MMX movd where the src is an mmxreg and the dst is an ireg or X-Git-Tag: svn/VALGRIND_2_0_0~247 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3ca7f606319de7f91bbe74976e486541597365b0;p=thirdparty%2Fvalgrind.git Implement MMX movd where the src is an mmxreg and the dst is an ireg or memory. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1507 --- diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c index 1a1fc120f8..8621d7996e 100644 --- a/coregrind/vg_from_ucode.c +++ b/coregrind/vg_from_ucode.c @@ -1413,7 +1413,26 @@ static void emit_MMX2_reg_to_mmxreg ( FlagSet uses_sflags, 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) ); } @@ -2715,6 +2734,15 @@ static void synth_MMX2_reg_to_mmxreg ( Bool uses_flags, Bool sets_flags, 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 ) @@ -3477,6 +3505,7 @@ static void emitUInstr ( UCodeBlock* cb, Int i, 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); @@ -3506,6 +3535,21 @@ static void emitUInstr ( UCodeBlock* cb, Int i, 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); diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index cbfd51d381..82a52bd88b 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -4829,6 +4829,37 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) 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); diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index c99e53ecf1..57302b4d9d 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -550,8 +550,9 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) 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); @@ -859,6 +860,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc ) 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); @@ -992,6 +994,7 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) (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 ); @@ -1157,6 +1160,7 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites ) 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: @@ -1308,7 +1312,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u ) 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: diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c index 1833e720dd..a90f9e3357 100644 --- a/memcheck/mc_translate.c +++ b/memcheck/mc_translate.c @@ -1097,9 +1097,13 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in ) 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: