|
From: <sv...@va...> - 2006-08-28 13:30:51
|
Author: sewardj
Date: 2006-08-28 14:30:48 +0100 (Mon, 28 Aug 2006)
New Revision: 1649
Log:
Merge r1639 (amd64->IR: 0xF0 0x48 0xF 0xC7 (cmpxchg8b))
Modified:
branches/VEX_3_2_BRANCH/priv/guest-amd64/toIR.c
Modified: branches/VEX_3_2_BRANCH/priv/guest-amd64/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_2_BRANCH/priv/guest-amd64/toIR.c 2006-08-28 13:28:48 U=
TC (rev 1648)
+++ branches/VEX_3_2_BRANCH/priv/guest-amd64/toIR.c 2006-08-28 13:30:48 U=
TC (rev 1649)
@@ -7136,9 +7136,10 @@
//.. //--=20
=20
static
-ULong dis_cmpxchg_G_E ( Prefix pfx,
- Int size,=20
- Long delta0 )
+ULong dis_cmpxchg_G_E ( /*OUT*/Bool* ok,
+ Prefix pfx,
+ Int size,=20
+ Long delta0 )
{
HChar dis_buf[50];
Int len;
@@ -7154,7 +7155,9 @@
UChar rm =3D getUChar(delta0);
=20
if (epartIsReg(rm)) {
- vassert(0); /* awaiting test case */
+ *ok =3D False;
+ return delta0;
+ /* awaiting test case */
assign( dest, getIRegE(size, pfx, rm) );
delta0++;
DIP("cmpxchg%c %s,%s\n", nameISize(size),
@@ -7182,10 +7185,126 @@
storeLE( mkexpr(addr), mkexpr(dest2) );
}
=20
+ *ok =3D True;
return delta0;
}
=20
+static
+ULong dis_cmpxchg8b ( /*OUT*/Bool* ok,
+ Prefix pfx,
+ Int sz,=20
+ Long delta0 )
+{
+ HChar dis_buf[50];
+ Int len;
=20
+ IRType ty =3D szToITy(sz);
+ IRTemp eq =3D newTemp(Ity_I8);
+ IRTemp olda =3D newTemp(ty);
+ IRTemp oldb =3D newTemp(ty);
+ IRTemp oldc =3D newTemp(ty);
+ IRTemp oldd =3D newTemp(ty);
+ IRTemp newa =3D newTemp(Ity_I64);
+ IRTemp newd =3D newTemp(Ity_I64);
+ IRTemp oldml =3D newTemp(ty);
+ IRTemp oldmh =3D newTemp(ty);
+ IRTemp newml =3D newTemp(ty);
+ IRTemp newmh =3D newTemp(ty);
+ IRTemp addr =3D IRTemp_INVALID;
+ IRTemp oldrf =3D newTemp(Ity_I64);
+ IRTemp newrf =3D newTemp(Ity_I64);
+ UChar rm =3D getUChar(delta0);
+ vassert(sz =3D=3D 4 || sz =3D=3D 8); /* guaranteed by caller */
+
+ if (epartIsReg(rm)) {
+ *ok =3D False;
+ return delta0;
+ }
+
+ addr =3D disAMode ( &len, pfx, delta0, dis_buf, 0 );
+ delta0 +=3D len;
+ DIP("cmpxchg%s %s\n", sz =3D=3D 4 ? "8" : "16", dis_buf);
+
+ if (sz =3D=3D 4) {
+ assign( olda, getIReg32( R_RAX ) );
+ assign( oldb, getIReg32( R_RBX ) );
+ assign( oldc, getIReg32( R_RCX ) );
+ assign( oldd, getIReg32( R_RDX ) );
+ assign( oldml, loadLE( Ity_I32, mkexpr(addr) ));
+ assign( oldmh, loadLE( Ity_I32,=20
+ binop(Iop_Add64,mkexpr(addr),mkU64(4)) ));
+ assign(eq,=20
+ unop(Iop_1Uto8,
+ binop(Iop_CmpEQ32,=20
+ binop(Iop_Or32,
+ binop(Iop_Xor32,mkexpr(olda),mkexpr(oldml)),
+ binop(Iop_Xor32,mkexpr(oldd),mkexpr(oldmh))),
+ mkU32(0))));
+ assign( newml, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldml),mkexpr(oldb))=
);
+ assign( newmh, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldmh),mkexpr(oldc))=
);
+ assign( newa, IRExpr_Mux0X(mkexpr(eq),
+ unop(Iop_32Uto64,mkexpr(oldml)),
+ getIRegRAX(8)) );
+ assign( newd, IRExpr_Mux0X(mkexpr(eq),
+ unop(Iop_32Uto64,mkexpr(oldmh)),
+ getIRegRDX(8)) );
+
+ storeLE( mkexpr(addr), mkexpr(newml) );
+ storeLE( binop(Iop_Add64,mkexpr(addr),mkU64(4)),
+ mkexpr(newmh) );
+ putIRegRAX( 8, mkexpr(newa) );
+ putIRegRDX( 8, mkexpr(newd) );
+ } else {
+ assign( olda, getIReg64( R_RAX ) );
+ assign( oldb, getIReg64( R_RBX ) );
+ assign( oldc, getIReg64( R_RCX ) );
+ assign( oldd, getIReg64( R_RDX ) );
+ assign( oldml, loadLE( Ity_I64, mkexpr(addr) ));
+ assign( oldmh, loadLE( Ity_I64,=20
+ binop(Iop_Add64,mkexpr(addr),mkU64(8)) ));
+ assign(eq,=20
+ unop(Iop_1Uto8,
+ binop(Iop_CmpEQ64,=20
+ binop(Iop_Or64,
+ binop(Iop_Xor64,mkexpr(olda),mkexpr(oldml)),
+ binop(Iop_Xor64,mkexpr(oldd),mkexpr(oldmh))),
+ mkU64(0))));
+ assign( newml, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldml),mkexpr(oldb))=
);
+ assign( newmh, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldmh),mkexpr(oldc))=
);
+ assign( newa, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldml),mkexpr(olda))=
);
+ assign( newd, IRExpr_Mux0X(mkexpr(eq),mkexpr(oldmh),mkexpr(oldd))=
);
+
+ storeLE( mkexpr(addr), mkexpr(newml) );
+ storeLE( binop(Iop_Add64,mkexpr(addr),mkU64(8)),
+ mkexpr(newmh) );
+ putIRegRAX( 8, mkexpr(newa) );
+ putIRegRDX( 8, mkexpr(newd) );
+ }
+
+ /* And set the flags. Z is set if original d:a =3D=3D mem, else
+ cleared. All others unchanged. (This is different from normal
+ cmpxchg which just sets them according to SUB.). */
+ assign( oldrf, binop(Iop_And64,=20
+ mk_amd64g_calculate_rflags_all(),
+ mkU64(~AMD64G_CC_MASK_Z)) );
+ assign( newrf,
+ binop(Iop_Or64,
+ mkexpr(oldrf),
+ binop(Iop_Shl64,=20
+ binop(Iop_And64, unop(Iop_8Uto64, mkexpr(eq)), mkU64(1)),
+ mkU8(AMD64G_CC_SHIFT_Z))
+ ));
+ stmt( IRStmt_Put( OFFB_CC_OP, mkU64(AMD64G_CC_OP_COPY) ));
+ stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
+ stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(newrf) ));
+ /* Set NDEP even though it isn't used. This makes redundant-PUT
+ elimination of previous stores to this field work better. */
+ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
+
+ *ok =3D True;
+ return delta0;
+}
+
//.. //-- static
//.. //-- Addr dis_cmpxchg8b ( UCodeBlock* cb,=20
//.. //-- UChar sorb,
@@ -13750,14 +13869,22 @@
//.. case 0xB0: /* CMPXCHG Gb,Eb */
//.. delta =3D dis_cmpxchg_G_E ( sorb, 1, delta );
//.. break;
- case 0xB1: /* CMPXCHG Gv,Ev */
+ case 0xB1: { /* CMPXCHG Gv,Ev (allowed in 16,32,64 bit) */
+ Bool ok =3D True;
if (haveF2orF3(pfx)) goto decode_failure;
- delta =3D dis_cmpxchg_G_E ( pfx, sz, delta );
+ if (sz !=3D 2 && sz !=3D 4 && sz !=3D 8) goto decode_failure;
+ delta =3D dis_cmpxchg_G_E ( &ok, pfx, sz, delta );
+ if (!ok) goto decode_failure;
break;
-//.. //-- case 0xC7: /* CMPXCHG8B Gv */
-//.. //-- eip =3D dis_cmpxchg8b ( cb, sorb, eip );
-//.. //-- break;
-//.. //--=20
+ }
+ case 0xC7: { /* CMPXCHG8B Ev, CMPXCHG16B Ev */
+ Bool ok =3D True;
+ if (have66orF2orF3(pfx)) goto decode_failure;
+ if (sz !=3D 4 && sz !=3D 8) goto decode_failure;
+ delta =3D dis_cmpxchg8b ( &ok, pfx, sz, delta );
+ break;
+ }
+
/* =3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- CPUID -=3D-=3D-=3D-=3D-=3D=
-=3D-=3D-=3D-=3D-=3D-=3D */
=20
case 0xA2: { /* CPUID */
|