From: Jeremy Fitzhardinge Date: Tue, 14 Oct 2003 22:17:19 +0000 (+0000) Subject: Implement repe scas. X-Git-Tag: svn/VALGRIND_2_1_0~131 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d4fea78014bc19e0d3104758bcee4c3d03abcd90;p=thirdparty%2Fvalgrind.git Implement repe scas. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1929 --- diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index ef14755829..6369250eaf 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -1900,7 +1900,7 @@ void codegen_REPNE_SCAS ( UCodeBlock* cb, Int sz, Addr eip, Addr eip_next ) uFlagsRWU(cb, FlagD, FlagsEmpty, FlagsEmpty); uInstr1(cb, POP, 4, TempReg, tv); - uInstr0(cb, CALLM_E, 0); + uInstr0(cb, CALLM_E, 0); if (sz == 4 || sz == 2) { uInstr2(cb, SHL, 4, Literal, 0, TempReg, tv); @@ -1917,6 +1917,56 @@ void codegen_REPNE_SCAS ( UCodeBlock* cb, Int sz, Addr eip, Addr eip_next ) uCond(cb, CondAlways); } +/* Template for REPE SCAS. Assumes this insn is the last one in + the basic block, and so emits a jump to the next insn. */ +static +void codegen_REPE_SCAS ( UCodeBlock* cb, Int sz, Addr eip, Addr eip_next ) +{ + Int ta /* EAX */, tc /* ECX */, td /* EDI */, tv; + ta = newTemp(cb); + tc = newTemp(cb); + tv = newTemp(cb); + td = newTemp(cb); + + uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, tc); + uInstr2(cb, JIFZ, 4, TempReg, tc, Literal, 0); + uLiteral(cb, eip_next); + uInstr1(cb, DEC, 4, TempReg, tc); + uInstr2(cb, PUT, 4, TempReg, tc, ArchReg, R_ECX); + + uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta); + uInstr2(cb, GET, 4, ArchReg, R_EDI, TempReg, td); + uInstr2(cb, LOAD, sz, TempReg, td, TempReg, tv); + /* next uinstr kills ta, but that's ok -- don't need it again */ + uInstr2(cb, SUB, sz, TempReg, tv, TempReg, ta); + setFlagsFromUOpcode(cb, SUB); + + uInstr0(cb, CALLM_S, 0); + uInstr2(cb, MOV, 4, Literal, 0, TempReg, tv); + uLiteral(cb, 0); + uInstr1(cb, PUSH, 4, TempReg, tv); + + uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_get_dirflag)); + uFlagsRWU(cb, FlagD, FlagsEmpty, FlagsEmpty); + + uInstr1(cb, POP, 4, TempReg, tv); + uInstr0(cb, CALLM_E, 0); + + if (sz == 4 || sz == 2) { + uInstr2(cb, SHL, 4, Literal, 0, TempReg, tv); + uLiteral(cb, sz/2); + } + uInstr2(cb, ADD, 4, TempReg, tv, TempReg, td); + uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI); + uInstr1(cb, JMP, 0, Literal, 0); + uLiteral(cb, eip); + uCond(cb, CondZ); + uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty); + uInstr1(cb, JMP, 0, Literal, 0); + uLiteral(cb, eip_next); + uCond(cb, CondAlways); +} + /* Template for REPE MOVS. Assumes this insn is the last one in the basic block, and so emits a jump to the next insn. */ @@ -5489,6 +5539,12 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) if (dis) VG_(printf)("scasb\n"); break; + case 0xAF: /* SCASl, no REP prefix */ + vg_assert(sorb == 0); + codegen_SCAS ( cb, sz ); + if (dis) VG_(printf)("scas;\n"); + break; + case 0xFC: /* CLD */ uInstr0(cb, CALLM_S, 0); uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLD)); @@ -5566,6 +5622,13 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) if (dis) VG_(printf)("repe stos%c\n", nameISize(sz)); } else + if (abyte == 0xAE || abyte == 0xAF) { /* REPE SCAS */ + if (abyte == 0xAE) sz = 1; + codegen_REPE_SCAS ( cb, sz, eip_orig, eip ); + *isEnd = True; + if (dis) VG_(printf)("repe scas%c\n", nameISize(sz)); + } + else if (abyte == 0x90) { /* REPE NOP (PAUSE) */ if (dis) VG_(printf)("repe nop (P4 pause)\n"); /* do nothing; apparently a hint to the P4 re spin-wait loop */