|
From: <sv...@va...> - 2005-08-24 17:39:28
|
Author: sewardj
Date: 2005-08-24 18:39:26 +0100 (Wed, 24 Aug 2005)
New Revision: 1358
Log:
Merge r1343 (x86 LOOP{,E,NE} implementation)
Modified:
branches/VEX_3_0_BRANCH/priv/guest-x86/toIR.c
Modified: branches/VEX_3_0_BRANCH/priv/guest-x86/toIR.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/VEX_3_0_BRANCH/priv/guest-x86/toIR.c 2005-08-24 17:36:20 UTC=
(rev 1357)
+++ branches/VEX_3_0_BRANCH/priv/guest-x86/toIR.c 2005-08-24 17:39:26 UTC=
(rev 1358)
@@ -666,7 +666,17 @@
vpanic("mkWidenOp(x86,guest)");
}
=20
+static IRExpr* mkAnd1 ( IRExpr* x, IRExpr* y )
+{
+ vassert(typeOfIRExpr(irbb->tyenv,x) =3D=3D Ity_I1);
+ vassert(typeOfIRExpr(irbb->tyenv,y) =3D=3D Ity_I1);
+ return unop(Iop_32to1,=20
+ binop(Iop_And32,=20
+ unop(Iop_1Uto32,x),=20
+ unop(Iop_1Uto32,y)));
+}
=20
+
/*------------------------------------------------------------*/
/*--- Helpers for %eflags. ---*/
/*------------------------------------------------------------*/
@@ -10543,9 +10553,8 @@
break;
=20
case 0xE3: /* JECXZ or perhaps JCXZ, depending on OSO ? Intel
- manual says it depends on address size override,
- which doesn't sound right to me. */
- vassert(sz=3D=3D4); /* possibly also OK for sz=3D=3D2 */
+ manual says it depends on address size override. */
+ if (sz !=3D 4) goto decode_failure;
d32 =3D (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
delta++;
ty =3D szToITy(sz);
@@ -10560,28 +10569,48 @@
DIP("j%sz 0x%x\n", nameIReg(sz, R_ECX), d32);
break;
=20
-//-- case 0xE0: /* LOOPNE disp8 */
-//-- case 0xE1: /* LOOPE disp8 */
-//-- case 0xE2: /* LOOP disp8 */
-//-- /* Again, the docs say this uses ECX/CX as a count depending =
on
-//-- the address size override, not the operand one. Since we
-//-- don't handle address size overrides, I guess that means
-//-- ECX. */
-//-- d32 =3D (eip+1) + getSDisp8(eip); eip++;
-//-- t1 =3D newTemp(cb);
-//-- uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, t1);
-//-- uInstr1(cb, DEC, 4, TempReg, t1);
-//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ECX);
-//-- uInstr2(cb, JIFZ, 4, TempReg, t1, Literal, 0);
-//-- uLiteral(cb, eip);
-//-- if (opc =3D=3D 0xE0 || opc =3D=3D 0xE1) { /* LOOPE/LOOPNE *=
/
-//-- jcc_lit(cb, eip, (opc =3D=3D 0xE1 ? CondNZ : CondZ));
-//-- }
-//-- jmp_lit(cb, d32);
-//-- whatNext =3D Dis_StopHere;
-//-- DIP("loop 0x%x\n", d32);
-//-- break;
+ case 0xE0: /* LOOPNE disp8: decrement count, jump if count !=3D 0 && =
ZF=3D=3D0 */
+ case 0xE1: /* LOOPE disp8: decrement count, jump if count !=3D 0 && =
ZF=3D=3D1 */
+ case 0xE2: /* LOOP disp8: decrement count, jump if count !=3D 0 */
+ { /* Again, the docs say this uses ECX/CX as a count depending on
+ the address size override, not the operand one. Since we
+ don't handle address size overrides, I guess that means
+ ECX. */
+ IRExpr* zbit =3D NULL;
+ IRExpr* count =3D NULL;
+ IRExpr* cond =3D NULL;
+ HChar* xtra =3D NULL;
=20
+ if (sz !=3D 4) goto decode_failure;
+ d32 =3D (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
+ delta++;
+ putIReg(4, R_ECX, binop(Iop_Sub32, getIReg(4,R_ECX), mkU32(1)));
+
+ count =3D getIReg(4,R_ECX);
+ cond =3D binop(Iop_CmpNE32, count, mkU32(0));
+ switch (opc) {
+ case 0xE2:=20
+ xtra =3D "";=20
+ break;
+ case 0xE1:=20
+ xtra =3D "e";=20
+ zbit =3D mk_x86g_calculate_condition( X86CondZ );
+ cond =3D mkAnd1(cond, zbit);
+ break;
+ case 0xE0:=20
+ xtra =3D "ne";
+ zbit =3D mk_x86g_calculate_condition( X86CondNZ );
+ cond =3D mkAnd1(cond, zbit);
+ break;
+ default:
+ vassert(0);
+ }
+ stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U32(d32)) );
+
+ DIP("loop%s 0x%x\n", xtra, d32);
+ break;
+ }
+
/* ------------------------ IMUL ----------------------- */
=20
case 0x69: /* IMUL Iv, Ev, Gv */
|