Implement repe scas.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1929
This commit is contained in:
Jeremy Fitzhardinge 2003-10-14 22:17:19 +00:00
parent 8f0884bbb6
commit d4fea78014

View File

@ -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<sz>. 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<sz>. 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<sz> */
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 */