]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement repe scas.
authorJeremy Fitzhardinge <jeremy@valgrind.org>
Tue, 14 Oct 2003 22:17:19 +0000 (22:17 +0000)
committerJeremy Fitzhardinge <jeremy@valgrind.org>
Tue, 14 Oct 2003 22:17:19 +0000 (22:17 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1929

coregrind/vg_to_ucode.c

index ef147558292e23356b81e8ea8ba987b8dee187ca..6369250eafae4540e3e36148acc797bc0569528e 100644 (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 */