return IRExpr_Tmp(tmp);
}
-static IRExpr* mkU8 ( UInt i )
+static IRExpr* mkU8 ( ULong i )
{
vassert(i < 256);
- return IRExpr_Const(IRConst_U8(i));
+ return IRExpr_Const(IRConst_U8( (UChar)i ));
}
//.. static IRExpr* mkU16 ( UInt i )
//.. vassert(i < 65536);
//.. return IRExpr_Const(IRConst_U16(i));
//.. }
-//..
-//.. static IRExpr* mkU32 ( UInt i )
-//.. {
-//.. return IRExpr_Const(IRConst_U32(i));
-//.. }
+
+static IRExpr* mkU32 ( ULong i )
+{
+ vassert(i < 0x100000000ULL);
+ return IRExpr_Const(IRConst_U32( (UInt)i ));
+}
static IRExpr* mkU64 ( ULong i )
{
return IRExpr_Const(IRConst_U64(i));
}
+static IRExpr* mkU ( IRType ty, ULong i )
+{
+ switch (ty) {
+ case Ity_I8: return mkU8(i);
+ // case Ity_I16: return mkU16(i);
+ case Ity_I32: return mkU32(i);
+ case Ity_I64: return mkU64(i);
+ default: vpanic("mkU(amd64)");
+ }
+}
+
/*------------------------------------------------------------*/
/*--- Debugging output ---*/
}
/* Fetch a byte from the guest insn stream. */
-static UChar getIByte ( UInt delta )
+static UChar getIByte ( ULong delta )
{
return guest_code[delta];
}
static ULong getUChar ( UInt delta )
{
- UInt v = guest_code[delta+0];
+ ULong v = guest_code[delta+0];
return v & 0xFF;
}
//.. d |= ((*eip++) << 8);
//.. return extend_s_16to32(d);
//.. }
-//..
-//.. static UInt getSDisp ( Int size, UInt delta )
-//.. {
-//.. switch (size) {
-//.. case 4: return getUDisp32(delta);
-//.. case 2: return getSDisp16(delta);
-//.. case 1: return getSDisp8(delta);
-//.. default: vpanic("getSDisp(x86)");
-//.. }
-//.. return 0; /*notreached*/
-//.. }
+
+/* Note: because AMD64 doesn't allow 64-bit literals, it is an error
+ if this is called with size==8. Should not happen. */
+static ULong getSDisp ( Int size, UInt delta )
+{
+ switch (size) {
+ case 4: return getSDisp32(delta);
+ // case 2: return getSDisp16(delta);
+ case 1: return getSDisp8(delta);
+ default: vpanic("getSDisp(amd64)");
+ }
+}
+
+static ULong mkSzMask ( Int sz )
+{
+ switch (sz) {
+ case 1: return 0xFFULL;
+ case 2: return 0xFFFFULL;
+ case 4: return 0xFFFFFFFFULL;
+ case 8: return 0xFFFFFFFFFFFFFFFFULL;
+ default: vpanic("mkSzMask(amd64)");
+ }
+}
+
+static Int imin ( Int a, Int b )
+{
+ return (a < b) ? a : b;
+}
/*------------------------------------------------------------*/
typedef UInt Prefix;
-#define PFX_ASO (1<<0) /* address-size override present (0x67) */
-#define PFX_66 (1<<1) /* operand-size override-to-16 present (0x66) */
-#define PFX_REX (1<<2) /* REX byte present (0x40 to 0x4F) */
-#define PFX_REXW (1<<3) /* REX W bit, if REX present, else 0 */
-#define PFX_REXR (1<<4) /* REX R bit, if REX present, else 0 */
-#define PFX_REXX (1<<5) /* REX X bit, if REX present, else 0 */
-#define PFX_REXB (1<<6) /* REX B bit, if REX present, else 0 */
-#define PFX_LOCK (1<<7) /* bus LOCK prefix present (0xF0) */
-#define PFX_F2 (1<<8) /* REP/REPE/REPZ prefix present (0xF2) */
-#define PFX_F3 (1<<9) /* REPNE/REPNZ prefix present (0xF3) */
-#define PFX_CS (1<<10) /* CS segment prefix present (0x2E) */
-#define PFX_DS (1<<11) /* DS segment prefix present (0x3E) */
-#define PFX_ES (1<<12) /* ES segment prefix present (0x26) */
-#define PFX_FS (1<<13) /* FS segment prefix present (0x64) */
-#define PFX_GS (1<<14) /* GS segment prefix present (0x65) */
-#define PFX_SS (1<<15) /* SS segment prefix present (0x36) */
+#define PFX_ASO (1<<0) /* address-size override present (0x67) */
+#define PFX_66 (1<<1) /* operand-size override-to-16 present (0x66) */
+#define PFX_REX (1<<2) /* REX byte present (0x40 to 0x4F) */
+#define PFX_REXW (1<<3) /* REX W bit, if REX present, else 0 */
+#define PFX_REXR (1<<4) /* REX R bit, if REX present, else 0 */
+#define PFX_REXX (1<<5) /* REX X bit, if REX present, else 0 */
+#define PFX_REXB (1<<6) /* REX B bit, if REX present, else 0 */
+#define PFX_LOCK (1<<7) /* bus LOCK prefix present (0xF0) */
+#define PFX_F2 (1<<8) /* REP/REPE/REPZ prefix present (0xF2) */
+#define PFX_F3 (1<<9) /* REPNE/REPNZ prefix present (0xF3) */
+#define PFX_CS (1<<10) /* CS segment prefix present (0x2E) */
+#define PFX_DS (1<<11) /* DS segment prefix present (0x3E) */
+#define PFX_ES (1<<12) /* ES segment prefix present (0x26) */
+#define PFX_FS (1<<13) /* FS segment prefix present (0x64) */
+#define PFX_GS (1<<14) /* GS segment prefix present (0x65) */
+#define PFX_SS (1<<15) /* SS segment prefix present (0x36) */
+
+#define PFX_EMPTY 0x31410000
static Bool IS_VALID_PFX ( Prefix pfx ) {
- return (pfx & 0xFFFF0000) == 0x31410000;
+ return (pfx & 0xFFFF0000) == PFX_EMPTY;
}
static Bool haveREX ( Prefix pfx ) {
return (pfx & PFX_REXB) ? 1 : 0;
}
+/* Check a prefix doesn't have F2 or F3 set in it, since usually that
+ completely changes what instruction it really is. */
+static Bool haveF2orF3 ( Prefix pfx ) {
+ pfx &= 0x0000FFFF;
+ return (pfx & (PFX_F2|PFX_F3)) > 0;
+}
/*------------------------------------------------------------*/
/*--- For dealing with integer registers. ---*/
return haveREX(pfx) ? getRX(pfx,RegX) : 0;
}
-static IRType szToITy ( UInt n )
+static IRType szToITy ( Int n )
{
switch (n) {
case 1: return Ity_I8;
/* Simplistic function, just gets the offset of one of the 16 integer
registers. No consideration of the complexities of REX bytes. */
-static UInt integerGuestReg64Offset ( UInt reg )
+static Int integerGuestReg64Offset ( UInt reg )
{
switch (reg) {
case R_RAX: return OFFB_RAX;
//.. vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I16);
//.. stmt( IRStmt_Put( xmmGuestRegLane16offset(xmmreg,laneno), e ) );
//.. }
-//..
-//.. static void storeLE ( IRExpr* addr, IRExpr* data )
-//.. {
-//.. stmt( IRStmt_STle(addr,data) );
-//.. }
-//..
-//.. static IRExpr* mkU ( IRType ty, UInt i )
-//.. {
-//.. if (ty == Ity_I8) return mkU8(i);
-//.. if (ty == Ity_I16) return mkU16(i);
-//.. if (ty == Ity_I32) return mkU32(i);
-//.. /* If this panics, it usually means you passed a size (1,2,4)
-//.. value as the IRType, rather than a real IRType. */
-//.. vpanic("mkU(x86)");
-//.. }
-//..
+
+static void storeLE ( IRExpr* addr, IRExpr* data )
+{
+ stmt( IRStmt_STle(addr,data) );
+}
+
//.. static IRExpr* mkV128 ( UShort mask )
//.. {
//.. return IRExpr_Const(IRConst_V128(mask));
static IROp mkSizedOp ( IRType ty, IROp op8 )
{
- Int adj;
- vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
vassert(op8 == Iop_Add8 || op8 == Iop_Sub8
|| op8 == Iop_Mul8
|| op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
|| op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
|| op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8
|| op8 == Iop_Not8 );
- adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
- return adj + op8;
+ switch (ty) {
+ case Ity_I8: return 0 +op8;
+ case Ity_I16: return 1 +op8;
+ case Ity_I32: return 2 +op8;
+ case Ity_I64: return 3 +op8;
+ default: vpanic("mkSizedOp(amd64)");
+ }
}
//.. static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd )
//.. call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
//.. return call;
//.. }
-//..
-//.. /* Build IR to calculate some particular condition from stored
-//.. CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression ::
-//.. Ity_Bit. */
-//.. static IRExpr* mk_x86g_calculate_condition ( X86Condcode cond )
-//.. {
-//.. IRExpr** args
-//.. = mkIRExprVec_5( mkU32(cond),
-//.. IRExpr_Get(OFFB_CC_OP, Ity_I32),
-//.. IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
-//.. IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
-//.. IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
-//.. IRExpr* call
-//.. = mkIRExprCCall(
-//.. Ity_I32,
-//.. 0/*regparm*/,
-//.. "x86g_calculate_condition", &x86g_calculate_condition,
-//.. args
-//.. );
-//.. /* Exclude the requested condition, OP and NDEP from definedness
-//.. checking. We're only interested in DEP1 and DEP2. */
-//.. call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
-//.. return unop(Iop_32to1, call);
-//.. }
+
+/* Build IR to calculate some particular condition from stored
+ CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression ::
+ Ity_Bit. */
+static IRExpr* mk_amd64g_calculate_condition ( AMD64Condcode cond )
+{
+ IRExpr** args
+ = mkIRExprVec_5( mkU64(cond),
+ IRExpr_Get(OFFB_CC_OP, Ity_I64),
+ IRExpr_Get(OFFB_CC_DEP1, Ity_I64),
+ IRExpr_Get(OFFB_CC_DEP2, Ity_I64),
+ IRExpr_Get(OFFB_CC_NDEP, Ity_I64) );
+ IRExpr* call
+ = mkIRExprCCall(
+ Ity_I64,
+ 0/*regparm*/,
+ "amd64g_calculate_condition", &amd64g_calculate_condition,
+ args
+ );
+ /* Exclude the requested condition, OP and NDEP from definedness
+ checking. We're only interested in DEP1 and DEP2. */
+ call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
+ return unop(Iop_32to1, unop(Iop_64to32, call));
+}
/* Build IR to calculate just the carry flag from stored
CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: Ity_I64. */
return op8 == Iop_Add8 || op8 == Iop_Sub8;
}
-//.. static Bool isLogic ( IROp op8 )
-//.. {
-//.. return op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8;
-//.. }
+static Bool isLogic ( IROp op8 )
+{
+ return op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8;
+}
/* U-widen 8/16/32/64 bit int expr to 64. */
static IRExpr* widenUto64 ( IRExpr* e )
//.. stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) ));
//.. stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));
//.. }
-//..
-//..
-//.. /* -------------- Condition codes. -------------- */
-//..
-//.. /* Condition codes, using the Intel encoding. */
-//..
-//.. static Char* name_X86Condcode ( X86Condcode cond )
-//.. {
-//.. switch (cond) {
-//.. case X86CondO: return "o";
-//.. case X86CondNO: return "no";
-//.. case X86CondB: return "b";
-//.. case X86CondNB: return "nb";
-//.. case X86CondZ: return "z";
-//.. case X86CondNZ: return "nz";
-//.. case X86CondBE: return "be";
-//.. case X86CondNBE: return "nbe";
-//.. case X86CondS: return "s";
-//.. case X86CondNS: return "ns";
-//.. case X86CondP: return "p";
-//.. case X86CondNP: return "np";
-//.. case X86CondL: return "l";
-//.. case X86CondNL: return "nl";
-//.. case X86CondLE: return "le";
-//.. case X86CondNLE: return "nle";
-//.. case X86CondAlways: return "ALWAYS";
-//.. default: vpanic("name_X86Condcode");
-//.. }
-//.. }
-//..
+
+
+/* -------------- Condition codes. -------------- */
+
+/* Condition codes, using the AMD encoding. */
+
+static Char* name_AMD64Condcode ( AMD64Condcode cond )
+{
+ switch (cond) {
+ case AMD64CondO: return "o";
+ case AMD64CondNO: return "no";
+ case AMD64CondB: return "b";
+ case AMD64CondNB: return "nb";
+ case AMD64CondZ: return "z";
+ case AMD64CondNZ: return "nz";
+ case AMD64CondBE: return "be";
+ case AMD64CondNBE: return "nbe";
+ case AMD64CondS: return "s";
+ case AMD64CondNS: return "ns";
+ case AMD64CondP: return "p";
+ case AMD64CondNP: return "np";
+ case AMD64CondL: return "l";
+ case AMD64CondNL: return "nl";
+ case AMD64CondLE: return "le";
+ case AMD64CondNLE: return "nle";
+ case AMD64CondAlways: return "ALWAYS";
+ default: vpanic("name_AMD64Condcode");
+ }
+}
+
//.. static
//.. X86Condcode positiveIse_X86Condcode ( X86Condcode cond,
//.. Bool* needInvert )
}
-//.. /* -------------- Helpers for disassembly printing. -------------- */
-//..
-//.. static HChar* nameGrp1 ( Int opc_aux )
-//.. {
-//.. static HChar* grp1_names[8]
-//.. = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
-//.. if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(x86)");
-//.. return grp1_names[opc_aux];
-//.. }
-//..
+/* -------------- Helpers for disassembly printing. -------------- */
+
+static HChar* nameGrp1 ( Int opc_aux )
+{
+ static HChar* grp1_names[8]
+ = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
+ if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(amd64)");
+ return grp1_names[opc_aux];
+}
+
//.. static HChar* nameGrp2 ( Int opc_aux )
//.. {
//.. static HChar* grp2_names[8]
static void jmp_treg( IRJumpKind kind, IRTemp t )
{
- irbb->next = mkexpr(t);
+ irbb->next = mkexpr(t);
irbb->jumpkind = kind;
}
ULong d = getSDisp32(delta);
DIS(buf, "%s0x%llx(%s)", sorbTxt(pfx), d, nameIRegB(pfx,8,rm));
*len = 5;
- vpanic("disAMode(amd64):untested amode: 3");
return disAMode_copy2tmp(
handleSegOverride(pfx,
binop(Iop_Add64,getIRegB(pfx,8,rm),mkU64(d))));
binop(Iop_Add64, mkU64(guest_rip_curr_instr),
mkU64(d))));
}
-#if 0
+
case 0x04: {
/* SIB, with no displacement. Special cases:
- -- %esp cannot act as an index value.
- If index_r indicates %esp, zero is used for the index.
- -- when mod is zero and base indicates EBP, base is instead
- a 32-bit literal.
+ -- %rsp cannot act as an index value.
+ If index_r indicates %rsp, zero is used for the index.
+ -- when mod is zero and base indicates RBP or R13, base is
+ instead a 32-bit sign-extended literal.
It's all madness, I tell you. Extract %index, %base and
scale from the SIB byte. The value denoted is then:
- | %index == %ESP && %base == %EBP
+ | %index == %RSP && (%base == %RBP || %base == %R13)
= d32 following SIB byte
- | %index == %ESP && %base != %EBP
+ | %index == %RSP && !(%base == %RBP || %base == %R13)
= %base
- | %index != %ESP && %base == %EBP
+ | %index != %RSP && (%base == %RBP || %base == %R13)
= d32 following SIB byte + (%index << scale)
- | %index != %ESP && %base != %ESP
+ | %index != %RSP && !(%base == %RBP || %base == %R13)
= %base + (%index << scale)
*/
UChar sib = getIByte(delta);
UChar scale = (sib >> 6) & 3;
UChar index_r = (sib >> 3) & 7;
UChar base_r = sib & 7;
+ /* correct since #(R13) == 8 + #(RBP) */
+ Bool base_is_BPor13 = base_r == R_RBP;
+ Bool index_is_SP = index_r == R_RSP && 0==getRexX(pfx);
delta++;
- if (index_r != R_ESP && base_r != R_EBP) {
- DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb),
- nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
+ if ((!index_is_SP) && (!base_is_BPor13)) {
+ DIS(buf, "%s(%s,%s,%d)", sorbTxt(pfx),
+ nameIRegB(pfx,8,base_r),
+ nameIRegX(pfx,8,index_r), 1<<scale);
*len = 2;
- vpanic("disAMode(amd64):untested amode: 5");
return
disAMode_copy2tmp(
- handleSegOverride(sorb,
- binop(Iop_Add32,
- getIReg(4,base_r),
- binop(Iop_Shl32, getIReg(4,index_r),
+ handleSegOverride(pfx,
+ binop(Iop_Add64,
+ getIRegB(pfx,8,base_r),
+ binop(Iop_Shl64, getIRegX(pfx,8,index_r),
mkU8(scale)))));
}
- if (index_r != R_ESP && base_r == R_EBP) {
- UInt d = getUDisp32(delta);
- DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d,
- nameIReg(4,index_r), 1<<scale);
+ if ((!index_is_SP) && base_is_BPor13) {
+ ULong d = getSDisp32(delta);
+ DIS(buf, "%s0x%llx(,%s,%d)", sorbTxt(pfx), d,
+ nameIRegX(pfx,8,index_r), 1<<scale);
*len = 6;
vpanic("disAMode(amd64):untested amode: 6");
return
disAMode_copy2tmp(
- handleSegOverride(sorb,
- binop(Iop_Add32,
- binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale)),
- mkU32(d))));
+ handleSegOverride(pfx,
+ binop(Iop_Add64,
+ binop(Iop_Shl64, getIRegX(pfx,8,index_r),
+ mkU8(scale)),
+ mkU64(d))));
}
- if (index_r == R_ESP && base_r != R_EBP) {
- DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r));
+ if (index_is_SP && (!base_is_BPor13)) {
+ DIS(buf, "%s(%s,,)", sorbTxt(pfx), nameIRegB(pfx,8,base_r));
*len = 2;
vpanic("disAMode(amd64):untested amode: 7");
return disAMode_copy2tmp(
- handleSegOverride(sorb, getIReg(4,base_r)));
+ handleSegOverride(pfx, getIRegB(pfx,8,base_r)));
}
- if (index_r == R_ESP && base_r == R_EBP) {
- UInt d = getUDisp32(delta);
- DIS(buf, "%s0x%x()", sorbTxt(sorb), d);
+ if (index_is_SP && base_is_BPor13) {
+ ULong d = getSDisp32(delta);
+ DIS(buf, "%s0x%llx()", sorbTxt(pfx), d);
*len = 6;
vpanic("disAMode(x86):untested amode: 8");
return disAMode_copy2tmp(
- handleSegOverride(sorb, mkU32(d)));
+ handleSegOverride(pfx, mkU64(d)));
}
vassert(0);
}
-#endif
-#if 0
+
/* SIB, with 8-bit displacement. Special cases:
-- %esp cannot act as an index value.
If index_r indicates %esp, zero is used for the index.
UChar scale = (sib >> 6) & 3;
UChar index_r = (sib >> 3) & 7;
UChar base_r = sib & 7;
- UInt d = getSDisp8(delta+1);
+ ULong d = getSDisp8(delta+1);
- if (index_r == R_ESP) {
- DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
+ if (index_r == R_RSP && 0==getRexX(pfx)) {
+ DIS(buf, "%s%lld(%s,,)", sorbTxt(pfx),
+ d, nameIRegB(pfx,8,base_r));
*len = 3;
vpanic("disAMode(amd64):untested amode: 9");
return disAMode_copy2tmp(
- handleSegOverride(sorb,
- binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
+ handleSegOverride(pfx,
+ binop(Iop_Add64, getIRegB(pfx,8,base_r), mkU64(d)) ));
} else {
- DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d,
- nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
+ DIS(buf, "%s%lld(%s,%s,%d)", sorbTxt(pfx), d,
+ nameIRegB(pfx,8,base_r),
+ nameIRegX(pfx,8,index_r), 1<<scale);
*len = 3;
- vpanic("disAMode(amd64):untested amode: 10");
return
disAMode_copy2tmp(
- handleSegOverride(sorb,
- binop(Iop_Add32,
- binop(Iop_Add32,
- getIReg(4,base_r),
- binop(Iop_Shl32,
- getIReg(4,index_r), mkU8(scale))),
- mkU32(d))));
+ handleSegOverride(pfx,
+ binop(Iop_Add64,
+ binop(Iop_Add64,
+ getIRegB(pfx,8,base_r),
+ binop(Iop_Shl64,
+ getIRegX(pfx,8,index_r), mkU8(scale))),
+ mkU64(d))));
}
- vassert(0);
+ vassert(0); /*NOTREACHED*/
}
-#endif
+
/* SIB, with 32-bit displacement. Special cases:
-- %rsp cannot act as an index value.
If index_r indicates %rsp, zero is used for the index.
getIRegX(pfx,8,index_r), mkU8(scale))),
mkU64(d))));
}
- vassert(0);
+ vassert(0); /*NOTREACHED*/
}
+ default:
+ vpanic("disAMode(amd64)");
+ return 0; /*notreached*/
+ }
+}
+
-//////////////////////////////////////////////////////
-#if 0
- case 0x04: /* SIB, with no displacement. */
- case 0x0C: /* SIB, with 8-bit displacement. */
- case 0x14: /* SIB, with 32-bit displacement. */
- /* The AMD documentation for SIB amodes is much more
- understandable than the Intel documentation. Hence a more
- understandable piece of code here. */
- { HChar base_txt[50];
- IRExpr* ea = NULL;
- IRExpr* base = NULL;
- UChar sib = getIByte(delta);
- UChar sib_scale = (sib >> 6) & 3;
- UChar sib_index = (sib >> 3) & 7;
- UChar sib_base = sib & 7;
- UChar modrm_mod = (mod_reg_rm >> 3) & 3;
- UChar rex_b = haveREX(pfx) ? getRX(pfx,RegB) : 0;
- UChar rex_x = haveREX(pfx) ? getRX(pfx,RegX) : 0;
- vassert(sib_scale <= 3);
- vassert(sib_index <= 7);
- vassert(sib_base <= 7);
- vassert(modrm_mod <= 2); /* mod==11b should have been ruled out by now */
- vassert(rex_b <= 1);
- vassert(rex_x <= 1);
- delta++;
- *len = 2;
+/* Figure out the number of (insn-stream) bytes constituting the amode
+ beginning at delta. Is useful for getting hold of literals beyond
+ the end of the amode before it has been disassembled. */
- /* First off, compute a value for the "base" field
- reference, as per Table A-16 on page 402. This can be
- computed from sib_base, modrm_mod and rex_b. */
- base_txt[0] = 0;
- if (sib_base != 5) {
- /* Simple case, base = %reg. */
- base = getIReg64((rex_b << 3) | sib_base);
- DIS(base_txt, "%s(%s,", sorbTxt(pfx),
- nameIReg64((rex_b << 3) | sib_base));
- }
- else
- if (sib_base == 5 && modrm_mod == 0) {
- /* base = signed-widen(32-bit literal) */
- ULong d = getSDisp32(delta);
- delta += 4;
- *len += 4;
- base = mkU64(d);
- DIS(base_txt, "%s%lld(,", sorbTxt(pfx), d);
- }
- else
- if (sib_base == 5 && modrm_mod == 1) {
- /* base = %rbp/%r13 + signed-widen(8-bit literal) */
- ULong d = getSDisp8(delta);
- delta += 1;
- *len += 1;
- base = binop(Iop_Add64,
- getIReg64(rex_b==0 ? R_RBP : R_R13),
- mkU64(d));
- DIS(base_txt, "%s%lld(%s", sorbTxt(pfx),
- d, rex_b==0 ? "%rbp" : "%r13");
- }
- else
- if (sib_base == 5 && modrm_mod == 2) {
- /* base = %rbp/%r13 + signed-widen(32-bit literal) */
- ULong d = getSDisp32(delta);
- delta += 4;
- *len += 4;
- base = binop(Iop_Add64,
- getIReg64(rex_b==0 ? R_RBP : R_R13),
- mkU64(d));
- DIS(base_txt, "%s%lld(%s", sorbTxt(pfx),
- d, rex_b==0 ? "%rbp" : "%r13");
- }
- else
- vassert(0); /*NOTREACHED*/
-
- /* So base/base_txt now hold/show the base part. Now add to that
- the scaled index component. This depends on sib_scale, sib_index
- and rex_x. */
- if (rex_x == 0 && sib_index == 4) {
- /* we just use base as it is */
- ea = base;
- DIS(buf, "%s)", base_txt);
- } else {
- ea = binop(Iop_Add64,
- base,
- binop(Iop_Shl64,
- getIReg64((rex_x << 3) | sib_index),
- mkU8(sib_scale)));
- DIS(buf, "%s%s,%d)", base_txt,
- nameIReg64((rex_x << 3) | sib_index), 1<<sib_scale);
- }
-
- /* and that's it (!) */
- return
- disAMode_copy2tmp(handleSegOverride(pfx, ea));
+static UInt lengthAMode ( Prefix pfx, UInt delta )
+{
+ UChar mod_reg_rm = getIByte(delta);
+ delta++;
+
+ /* squeeze out the reg field from mod_reg_rm, since a 256-entry
+ jump table seems a bit excessive.
+ */
+ mod_reg_rm &= 0xC7; /* is now XX000YYY */
+ mod_reg_rm |= (mod_reg_rm >> 3); /* is now XX0XXYYY */
+ mod_reg_rm &= 0x1F; /* is now 000XXYYY */
+ switch (mod_reg_rm) {
+
+ /* REX.B==0: (%rax) .. (%rdi), not including (%rsp) or (%rbp).
+ REX.B==1: (%r8) .. (%r15), not including (%r12) or (%r13).
+ */
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
+ vassert(0);
+ return 1;
+
+ /* REX.B==0: d8(%rax) ... d8(%rdi), not including d8(%rsp)
+ REX.B==1: d8(%r8) ... d8(%r15), not including d8(%r12)
+ */
+ case 0x08: case 0x09: case 0x0A: case 0x0B:
+ /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
+ vassert(0);
+ return 2;
+
+ /* REX.B==0: d32(%rax) ... d32(%rdi), not including d32(%rsp)
+ REX.B==1: d32(%r8) ... d32(%r15), not including d32(%r12)
+ */
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ /* ! 14 */ case 0x15: case 0x16: case 0x17:
+ vassert(0);
+ return 5;
+
+ /* REX.B==0: a register, %rax .. %rdi. This shouldn't happen. */
+ /* REX.B==1: a register, %r8 .. %r16. This shouldn't happen. */
+ /* Not an address, but still handled. */
+ case 0x18: case 0x19: case 0x1A: case 0x1B:
+ case 0x1C: case 0x1D: case 0x1E: case 0x1F:
+ return 1;
+
+ /* RIP + disp32. */
+ case 0x05:
+ vassert(0);
+ return 5;
+
+ case 0x04: {
+ /* SIB, with no displacement. */
+ UChar sib = getIByte(delta);
+ UChar base_r = sib & 7;
+ /* correct since #(R13) == 8 + #(RBP) */
+ Bool base_is_BPor13 = base_r == R_RBP;
+
+ if (base_is_BPor13) {
+ vassert(0);
+ return 6;
+ } else {
+ vassert(0);
+ return 2;
}
-#endif
+ }
+
+ /* SIB, with 8-bit displacement. */
+ case 0x0C:
+ return 3;
+
+ /* SIB, with 32-bit displacement. */
+ case 0x14:
+ return 6;
+
default:
- vex_printf("mod_reg_rm = 0x%x\n", (Int)mod_reg_rm);
- vpanic("disAMode(amd64)");
+ vpanic("lengthAMode(amd64)");
return 0; /*notreached*/
}
}
}
if (epartIsReg(rm)) {
- vassert(0);
+ vassert(0); /* awaiting test case */
/* Specially handle XOR reg,reg, because that doesn't really
depend on reg, and doing the obvious thing potentially
generates a spurious value check failure due to the bogus
assign( src, getIRegB(pfx,size,eregOfRM(rm)) );
if (addSubCarry && op8 == Iop_Add8) {
+ vassert(0); /* awaiting test case */
helper_ADC( size, dst1, dst0, src );
putIRegB(pfx, size, gregOfRM(rm), mkexpr(dst1));
} else
if (addSubCarry && op8 == Iop_Sub8) {
+ vassert(0); /* awaiting test case */
helper_SBB( size, dst1, dst0, src );
putIRegB(pfx, size, gregOfRM(rm), mkexpr(dst1));
} else {
+ vassert(0); /* awaiting test case */
assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
if (isAddSub(op8))
setFlags_DEP1_DEP2(op8, dst0, src, ty);
assign( src, loadLE(szToITy(size), mkexpr(addr)) );
if (addSubCarry && op8 == Iop_Add8) {
+ vassert(0); /* awaiting test case */
helper_ADC( size, dst1, dst0, src );
putIRegR(pfx, size, gregOfRM(rm), mkexpr(dst1));
} else
if (addSubCarry && op8 == Iop_Sub8) {
+ vassert(0); /* awaiting test case */
helper_SBB( size, dst1, dst0, src );
putIRegR(pfx, size, gregOfRM(rm), mkexpr(dst1));
} else {
DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
dis_buf,nameIRegR(pfx,size,gregOfRM(rm)));
- vex_printf("len = %d\n", len);
return len+delta0;
}
}
-//.. /* Handle binary integer instructions of the form
-//.. op G, E meaning
-//.. op reg, reg-or-mem
-//.. Is passed the a ptr to the modRM byte, the actual operation, and the
-//.. data size. Returns the address advanced completely over this
-//.. instruction.
-//..
-//.. G(src) is reg.
-//.. E(dst) is reg-or-mem
-//..
-//.. If E is reg, --> GET %E, tmp
-//.. OP %G, tmp
-//.. PUT tmp, %E
-//..
-//.. If E is mem, --> (getAddr E) -> tmpa
-//.. LD (tmpa), tmpv
-//.. OP %G, tmpv
-//.. ST tmpv, (tmpa)
-//.. */
-//.. static
-//.. UInt dis_op2_G_E ( UChar sorb,
-//.. Bool addSubCarry,
-//.. IROp op8,
-//.. Bool keep,
-//.. Int size,
-//.. UInt delta0,
-//.. Char* t_x86opc )
-//.. {
-//.. HChar dis_buf[50];
-//.. Int len;
-//.. IRType ty = szToITy(size);
-//.. IRTemp dst1 = newTemp(ty);
-//.. IRTemp src = newTemp(ty);
-//.. IRTemp dst0 = newTemp(ty);
-//.. UChar rm = getIByte(delta0);
-//.. IRTemp addr = IRTemp_INVALID;
-//..
-//.. /* addSubCarry == True indicates the intended operation is
-//.. add-with-carry or subtract-with-borrow. */
-//.. if (addSubCarry) {
-//.. vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
-//.. vassert(keep);
-//.. }
-//..
-//.. if (epartIsReg(rm)) {
-//.. /* Specially handle XOR reg,reg, because that doesn't really
-//.. depend on reg, and doing the obvious thing potentially
-//.. generates a spurious value check failure due to the bogus
-//.. dependency. */
-//.. if (op8 == Iop_Xor8 && gregOfRM(rm) == eregOfRM(rm)) {
-//.. codegen_XOR_reg_with_itself ( size, gregOfRM(rm) );
-//.. return 1+delta0;
-//.. }
-//.. assign(dst0, getIReg(size,eregOfRM(rm)));
-//.. assign(src, getIReg(size,gregOfRM(rm)));
-//..
-//.. if (addSubCarry && op8 == Iop_Add8) {
-//.. helper_ADC( size, dst1, dst0, src );
-//.. putIReg(size, eregOfRM(rm), mkexpr(dst1));
-//.. } else
-//.. if (addSubCarry && op8 == Iop_Sub8) {
-//.. helper_SBB( size, dst1, dst0, src );
-//.. putIReg(size, eregOfRM(rm), mkexpr(dst1));
-//.. } else {
-//.. assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
-//.. if (isAddSub(op8))
-//.. setFlags_DEP1_DEP2(op8, dst0, src, ty);
-//.. else
-//.. setFlags_DEP1(op8, dst1, ty);
-//.. if (keep)
-//.. putIReg(size, eregOfRM(rm), mkexpr(dst1));
-//.. }
-//..
-//.. DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
-//.. nameIReg(size,gregOfRM(rm)),
-//.. nameIReg(size,eregOfRM(rm)));
-//.. return 1+delta0;
-//.. }
-//..
-//.. /* E refers to memory */
-//.. {
-//.. addr = disAMode ( &len, sorb, delta0, dis_buf);
-//.. assign(dst0, loadLE(ty,mkexpr(addr)));
-//.. assign(src, getIReg(size,gregOfRM(rm)));
-//..
-//.. if (addSubCarry && op8 == Iop_Add8) {
-//.. helper_ADC( size, dst1, dst0, src );
-//.. storeLE(mkexpr(addr), mkexpr(dst1));
-//.. } else
-//.. if (addSubCarry && op8 == Iop_Sub8) {
-//.. helper_SBB( size, dst1, dst0, src );
-//.. storeLE(mkexpr(addr), mkexpr(dst1));
-//.. } else {
-//.. assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
-//.. if (isAddSub(op8))
-//.. setFlags_DEP1_DEP2(op8, dst0, src, ty);
-//.. else
-//.. setFlags_DEP1(op8, dst1, ty);
-//.. if (keep)
-//.. storeLE(mkexpr(addr), mkexpr(dst1));
-//.. }
-//..
-//.. DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
-//.. nameIReg(size,gregOfRM(rm)), dis_buf);
-//.. return len+delta0;
-//.. }
-//.. }
-//..
-//..
+/* Handle binary integer instructions of the form
+ op G, E meaning
+ op reg, reg-or-mem
+ Is passed the a ptr to the modRM byte, the actual operation, and the
+ data size. Returns the address advanced completely over this
+ instruction.
+
+ G(src) is reg.
+ E(dst) is reg-or-mem
+
+ If E is reg, --> GET %E, tmp
+ OP %G, tmp
+ PUT tmp, %E
+
+ If E is mem, --> (getAddr E) -> tmpa
+ LD (tmpa), tmpv
+ OP %G, tmpv
+ ST tmpv, (tmpa)
+*/
+static
+UInt dis_op2_G_E ( Prefix pfx,
+ Bool addSubCarry,
+ IROp op8,
+ Bool keep,
+ Int size,
+ ULong delta0,
+ Char* t_amd64opc )
+{
+ HChar dis_buf[50];
+ Int len;
+ IRType ty = szToITy(size);
+ IRTemp dst1 = newTemp(ty);
+ IRTemp src = newTemp(ty);
+ IRTemp dst0 = newTemp(ty);
+ UChar rm = getIByte(delta0);
+ IRTemp addr = IRTemp_INVALID;
+
+ /* addSubCarry == True indicates the intended operation is
+ add-with-carry or subtract-with-borrow. */
+ if (addSubCarry) {
+ vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
+ vassert(keep);
+ }
+
+ if (epartIsReg(rm)) {
+ /* Specially handle XOR reg,reg, because that doesn't really
+ depend on reg, and doing the obvious thing potentially
+ generates a spurious value check failure due to the bogus
+ dependency. */
+ if (op8 == Iop_Xor8 && gregOfRM(rm) == eregOfRM(rm)
+ && getRexR(pfx) == getRexB(pfx)) {
+ codegen_XOR_reg_with_itself ( pfx, size, gregOfRM(rm) );
+ return 1+delta0;
+ }
+ assign(dst0, getIRegB(pfx,size,eregOfRM(rm)));
+ assign(src, getIRegR(pfx,size,gregOfRM(rm)));
+
+ if (addSubCarry && op8 == Iop_Add8) {
+ vassert(0); /* awaiting test case */
+ helper_ADC( size, dst1, dst0, src );
+ putIRegB(pfx, size, eregOfRM(rm), mkexpr(dst1));
+ } else
+ if (addSubCarry && op8 == Iop_Sub8) {
+ vassert(0); /* awaiting test case */
+ helper_SBB( size, dst1, dst0, src );
+ putIRegB(pfx, size, eregOfRM(rm), mkexpr(dst1));
+ } else {
+ assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+ if (isAddSub(op8))
+ setFlags_DEP1_DEP2(op8, dst0, src, ty);
+ else
+ setFlags_DEP1(op8, dst1, ty);
+ if (keep)
+ putIRegB(pfx, size, eregOfRM(rm), mkexpr(dst1));
+ }
+
+ DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
+ nameIRegR(pfx,size,gregOfRM(rm)),
+ nameIRegB(pfx,size,eregOfRM(rm)));
+ return 1+delta0;
+ }
+
+ /* E refers to memory */
+ {
+ addr = disAMode ( &len, pfx, delta0, dis_buf);
+ assign(dst0, loadLE(ty,mkexpr(addr)));
+ assign(src, getIRegR(pfx,size,gregOfRM(rm)));
+
+ if (addSubCarry && op8 == Iop_Add8) {
+ vassert(0); /* awaiting test case */
+ helper_ADC( size, dst1, dst0, src );
+ storeLE(mkexpr(addr), mkexpr(dst1));
+ } else
+ if (addSubCarry && op8 == Iop_Sub8) {
+ vassert(0); /* awaiting test case */
+ helper_SBB( size, dst1, dst0, src );
+ storeLE(mkexpr(addr), mkexpr(dst1));
+ } else {
+ assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+ if (isAddSub(op8))
+ setFlags_DEP1_DEP2(op8, dst0, src, ty);
+ else
+ setFlags_DEP1(op8, dst1, ty);
+ if (keep)
+ storeLE(mkexpr(addr), mkexpr(dst1));
+ }
+
+ DIP("%s%c %s,%s\n", t_amd64opc, nameISize(size),
+ nameIRegR(pfx,size,gregOfRM(rm)), dis_buf);
+ return len+delta0;
+ }
+}
+
+
//.. /* Handle move instructions of the form
//.. mov E, G meaning
//.. mov reg-or-mem, reg
//.. return len+delta0;
//.. }
//.. }
-//..
-//..
-//.. /* op $immediate, AL/AX/EAX. */
-//.. static
-//.. UInt dis_op_imm_A ( Int size,
-//.. IROp op8,
-//.. Bool keep,
-//.. UInt delta,
-//.. Char* t_x86opc )
-//.. {
-//.. IRType ty = szToITy(size);
-//.. IRTemp dst0 = newTemp(ty);
-//.. IRTemp src = newTemp(ty);
-//.. IRTemp dst1 = newTemp(ty);
-//.. UInt lit = getUDisp(size,delta);
-//.. assign(dst0, getIReg(size,R_EAX));
-//.. assign(src, mkU(ty,lit));
-//.. assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
-//.. if (isAddSub(op8))
-//.. setFlags_DEP1_DEP2(op8, dst0, src, ty);
-//.. else
-//.. if (isLogic(op8))
-//.. setFlags_DEP1(op8, dst1, ty);
-//.. else
-//.. vpanic("dis_op_imm_A(x86,guest)");
-//..
-//.. if (keep)
-//.. putIReg(size, R_EAX, mkexpr(dst1));
-//..
-//.. DIP("%s%c $0x%x, %s\n", t_x86opc, nameISize(size),
-//.. lit, nameIReg(size,R_EAX));
-//.. return delta+size;
-//.. }
-//..
-//..
+
+
+/* op $immediate, AL/AX/EAX/RAX. */
+static
+UInt dis_op_imm_A ( Int size,
+ IROp op8,
+ Bool keep,
+ ULong delta,
+ Char* t_amd64opc )
+{
+ Int size4 = imin(size,4);
+ IRType ty = szToITy(size);
+ IRTemp dst0 = newTemp(ty);
+ IRTemp src = newTemp(ty);
+ IRTemp dst1 = newTemp(ty);
+ ULong lit = getSDisp(size4,delta);
+ assign(dst0, getIRegR(PFX_EMPTY,size,R_RAX));
+ assign(src, mkU(ty,lit & mkSzMask(size)));
+ assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
+ if (isAddSub(op8))
+ setFlags_DEP1_DEP2(op8, dst0, src, ty);
+ else
+ if (isLogic(op8))
+ setFlags_DEP1(op8, dst1, ty);
+ else
+ vpanic("dis_op_imm_A(amd64)");
+
+ if (keep)
+ putIRegR(PFX_EMPTY, size, R_RAX, mkexpr(dst1));
+
+ DIP("%s%c $%lld, %s\n", t_amd64opc, nameISize(size),
+ lit, nameIRegR(PFX_EMPTY,size,R_RAX));
+ return delta+size4;
+}
+
+
//.. /* Sign- and Zero-extending moves. */
//.. static
//.. UInt dis_movx_E_G ( UChar sorb,
//.. default: vpanic("codegen_div(x86)");
//.. }
//.. }
-//..
-//..
-//.. static
-//.. UInt dis_Grp1 ( UChar sorb,
-//.. UInt delta, UChar modrm,
-//.. Int am_sz, Int d_sz, Int sz, UInt d32 )
-//.. {
-//.. Int len;
-//.. HChar dis_buf[50];
-//.. IRType ty = szToITy(sz);
-//.. IRTemp dst1 = newTemp(ty);
-//.. IRTemp src = newTemp(ty);
-//.. IRTemp dst0 = newTemp(ty);
-//.. IRTemp addr = IRTemp_INVALID;
-//.. IROp op8 = Iop_INVALID;
-//.. UInt mask = sz==1 ? 0xFF : (sz==2 ? 0xFFFF : 0xFFFFFFFF);
-//..
-//.. switch (gregOfRM(modrm)) {
-//.. case 0: op8 = Iop_Add8; break; case 1: op8 = Iop_Or8; break;
-//.. case 2: break; // ADC
-//.. case 3: break; // SBB
-//.. case 4: op8 = Iop_And8; break; case 5: op8 = Iop_Sub8; break;
-//.. case 6: op8 = Iop_Xor8; break; case 7: op8 = Iop_Sub8; break;
-//.. default: vpanic("dis_Grp1: unhandled case");
-//.. }
-//..
-//.. if (epartIsReg(modrm)) {
-//.. vassert(am_sz == 1);
-//..
-//.. assign(dst0, getIReg(sz,eregOfRM(modrm)));
-//.. assign(src, mkU(ty,d32 & mask));
-//..
-//.. if (gregOfRM(modrm) == 2 /* ADC */) {
-//.. helper_ADC( sz, dst1, dst0, src );
-//.. } else
-//.. if (gregOfRM(modrm) == 3 /* SBB */) {
-//.. helper_SBB( sz, dst1, dst0, src );
-//.. } else {
-//.. assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
-//.. if (isAddSub(op8))
-//.. setFlags_DEP1_DEP2(op8, dst0, src, ty);
-//.. else
-//.. setFlags_DEP1(op8, dst1, ty);
-//.. }
-//..
-//.. if (gregOfRM(modrm) < 7)
-//.. putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
-//..
-//.. delta += (am_sz + d_sz);
-//.. DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32,
-//.. nameIReg(sz,eregOfRM(modrm)));
-//.. } else {
-//.. addr = disAMode ( &len, sorb, delta, dis_buf);
-//..
-//.. assign(dst0, loadLE(ty,mkexpr(addr)));
-//.. assign(src, mkU(ty,d32 & mask));
-//..
-//.. if (gregOfRM(modrm) == 2 /* ADC */) {
-//.. helper_ADC( sz, dst1, dst0, src );
-//.. } else
-//.. if (gregOfRM(modrm) == 3 /* SBB */) {
-//.. helper_SBB( sz, dst1, dst0, src );
-//.. } else {
-//.. assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
-//.. if (isAddSub(op8))
-//.. setFlags_DEP1_DEP2(op8, dst0, src, ty);
-//.. else
-//.. setFlags_DEP1(op8, dst1, ty);
-//.. }
-//..
-//.. if (gregOfRM(modrm) < 7)
-//.. storeLE(mkexpr(addr), mkexpr(dst1));
-//..
-//.. delta += (len+d_sz);
-//.. DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
-//.. d32, dis_buf);
-//.. }
-//.. return delta;
-//.. }
-//..
-//..
+
+static
+UInt dis_Grp1 ( Prefix pfx,
+ UInt delta, UChar modrm,
+ Int am_sz, Int d_sz, Int sz, ULong d32 )
+{
+ Int len;
+ HChar dis_buf[50];
+ IRType ty = szToITy(sz);
+ IRTemp dst1 = newTemp(ty);
+ IRTemp src = newTemp(ty);
+ IRTemp dst0 = newTemp(ty);
+ IRTemp addr = IRTemp_INVALID;
+ IROp op8 = Iop_INVALID;
+ ULong mask = mkSzMask(sz);
+
+ switch (gregOfRM(modrm)) {
+ case 0: op8 = Iop_Add8; break; case 1: op8 = Iop_Or8; break;
+ case 2: break; // ADC
+ case 3: break; // SBB
+ case 4: op8 = Iop_And8; break; case 5: op8 = Iop_Sub8; break;
+ case 6: op8 = Iop_Xor8; break; case 7: op8 = Iop_Sub8; break;
+ default: vpanic("dis_Grp1(amd64): unhandled case");
+ }
+
+ if (epartIsReg(modrm)) {
+ vassert(am_sz == 1);
+
+ assign(dst0, getIRegB(pfx,sz,eregOfRM(modrm)));
+ assign(src, mkU(ty,d32 & mask));
+
+ if (gregOfRM(modrm) == 2 /* ADC */) {
+ vassert(0); /* awaiting test case */
+ helper_ADC( sz, dst1, dst0, src );
+ } else
+ if (gregOfRM(modrm) == 3 /* SBB */) {
+ vassert(0); /* awaiting test case */
+ helper_SBB( sz, dst1, dst0, src );
+ } else {
+ assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+ if (isAddSub(op8))
+ setFlags_DEP1_DEP2(op8, dst0, src, ty);
+ else
+ setFlags_DEP1(op8, dst1, ty);
+ }
+
+ if (gregOfRM(modrm) < 7)
+ putIRegB(pfx, sz, eregOfRM(modrm), mkexpr(dst1));
+
+ delta += (am_sz + d_sz);
+ DIP("%s%c $0x%llx, %s\n",
+ nameGrp1(gregOfRM(modrm)), nameISize(sz), d32,
+ nameIRegB(pfx,sz,eregOfRM(modrm)));
+ } else {
+ addr = disAMode ( &len, pfx, delta, dis_buf);
+
+ assign(dst0, loadLE(ty,mkexpr(addr)));
+ assign(src, mkU(ty,d32 & mask));
+
+ if (gregOfRM(modrm) == 2 /* ADC */) {
+ vassert(0); /* awaiting test case */
+ helper_ADC( sz, dst1, dst0, src );
+ } else
+ if (gregOfRM(modrm) == 3 /* SBB */) {
+ vassert(0); /* awaiting test case */
+ helper_SBB( sz, dst1, dst0, src );
+ } else {
+ assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+ if (isAddSub(op8))
+ setFlags_DEP1_DEP2(op8, dst0, src, ty);
+ else
+ setFlags_DEP1(op8, dst1, ty);
+ }
+
+ if (gregOfRM(modrm) < 7)
+ storeLE(mkexpr(addr), mkexpr(dst1));
+
+ delta += (len+d_sz);
+ DIP("%s%c $0x%llx, %s\n",
+ nameGrp1(gregOfRM(modrm)), nameISize(sz),
+ d32, dis_buf);
+ }
+ return delta;
+}
+
+
//.. /* Group 2 extended opcodes. shift_expr must be an 8-bit typed
//.. expression. */
//..
//.. //--
//.. //-- return eip0;
//.. //-- }
-//..
-//..
-//.. /* Handle conditional move instructions of the form
-//.. cmovcc E(reg-or-mem), G(reg)
-//..
-//.. E(src) is reg-or-mem
-//.. G(dst) is reg.
-//..
-//.. If E is reg, --> GET %E, tmps
-//.. GET %G, tmpd
-//.. CMOVcc tmps, tmpd
-//.. PUT tmpd, %G
-//..
-//.. If E is mem --> (getAddr E) -> tmpa
-//.. LD (tmpa), tmps
-//.. GET %G, tmpd
-//.. CMOVcc tmps, tmpd
-//.. PUT tmpd, %G
-//.. */
-//.. static
-//.. UInt dis_cmov_E_G ( UChar sorb,
-//.. Int sz,
-//.. X86Condcode cond,
-//.. UInt delta0 )
-//.. {
-//.. UChar rm = getIByte(delta0);
-//.. HChar dis_buf[50];
-//.. Int len;
-//..
-//.. IRType ty = szToITy(sz);
-//.. IRTemp tmps = newTemp(ty);
-//.. IRTemp tmpd = newTemp(ty);
-//..
-//.. if (epartIsReg(rm)) {
-//.. assign( tmps, getIReg(sz, eregOfRM(rm)) );
-//.. assign( tmpd, getIReg(sz, gregOfRM(rm)) );
-//..
-//.. putIReg(sz, gregOfRM(rm),
-//.. IRExpr_Mux0X( unop(Iop_1Uto8,
-//.. mk_x86g_calculate_condition(cond)),
-//.. mkexpr(tmpd),
-//.. mkexpr(tmps) )
-//.. );
-//.. DIP("cmov%c%s %s,%s\n", nameISize(sz),
-//.. name_X86Condcode(cond),
-//.. nameIReg(sz,eregOfRM(rm)),
-//.. nameIReg(sz,gregOfRM(rm)));
-//.. return 1+delta0;
-//.. }
-//..
-//.. /* E refers to memory */
-//.. {
-//.. IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
-//.. assign( tmps, loadLE(ty, mkexpr(addr)) );
-//.. assign( tmpd, getIReg(sz, gregOfRM(rm)) );
-//..
-//.. putIReg(sz, gregOfRM(rm),
-//.. IRExpr_Mux0X( unop(Iop_1Uto8,
-//.. mk_x86g_calculate_condition(cond)),
-//.. mkexpr(tmpd),
-//.. mkexpr(tmps) )
-//.. );
-//..
-//.. DIP("cmov%c%s %s,%s\n", nameISize(sz),
-//.. name_X86Condcode(cond),
-//.. dis_buf,
-//.. nameIReg(sz,gregOfRM(rm)));
-//.. return len+delta0;
-//.. }
-//.. }
-//..
-//..
+
+
+/* Handle conditional move instructions of the form
+ cmovcc E(reg-or-mem), G(reg)
+
+ E(src) is reg-or-mem
+ G(dst) is reg.
+
+ If E is reg, --> GET %E, tmps
+ GET %G, tmpd
+ CMOVcc tmps, tmpd
+ PUT tmpd, %G
+
+ If E is mem --> (getAddr E) -> tmpa
+ LD (tmpa), tmps
+ GET %G, tmpd
+ CMOVcc tmps, tmpd
+ PUT tmpd, %G
+*/
+static
+ULong dis_cmov_E_G ( Prefix pfx,
+ Int sz,
+ AMD64Condcode cond,
+ ULong delta0 )
+{
+ UChar rm = getIByte(delta0);
+ HChar dis_buf[50];
+ Int len;
+
+ IRType ty = szToITy(sz);
+ IRTemp tmps = newTemp(ty);
+ IRTemp tmpd = newTemp(ty);
+
+ if (epartIsReg(rm)) {
+ assign( tmps, getIRegB(pfx, sz, eregOfRM(rm)) );
+ assign( tmpd, getIRegR(pfx, sz, gregOfRM(rm)) );
+
+ putIRegR( pfx, sz,
+ gregOfRM(rm),
+ IRExpr_Mux0X( unop(Iop_1Uto8,
+ mk_amd64g_calculate_condition(cond)),
+ mkexpr(tmpd),
+ mkexpr(tmps) )
+ );
+ DIP("cmov%c%s %s,%s\n", nameISize(sz),
+ name_AMD64Condcode(cond),
+ nameIRegB(pfx,sz,eregOfRM(rm)),
+ nameIRegR(pfx,sz,gregOfRM(rm)));
+ return 1+delta0;
+ }
+
+ /* E refers to memory */
+ {
+ IRTemp addr = disAMode ( &len, pfx, delta0, dis_buf );
+ vassert(0); /* awaiting test case */
+ assign( tmps, loadLE(ty, mkexpr(addr)) );
+ assign( tmpd, getIRegR(pfx, sz, gregOfRM(rm)) );
+
+ putIRegR( pfx, sz,
+ gregOfRM(rm),
+ IRExpr_Mux0X( unop(Iop_1Uto8,
+ mk_amd64g_calculate_condition(cond)),
+ mkexpr(tmpd),
+ mkexpr(tmps) )
+ );
+
+ DIP("cmov%c%s %s,%s\n", nameISize(sz),
+ name_AMD64Condcode(cond),
+ dis_buf,
+ nameIRegR(pfx,sz,gregOfRM(rm)));
+ return len+delta0;
+ }
+}
+
+
//.. static
//.. UInt dis_xadd_G_E ( UChar sorb, Int sz, UInt delta0 )
//.. {
IRTemp addr, t0, t1, t2, t3, t4, t5, t6;
Int alen;
UChar opc, modrm, abyte, pre;
- UInt d32;
+ ULong d64;
HChar dis_buf[50];
Int am_sz, d_sz, n, n_prefixes;
DisResult whatNext = Dis_Continue;
conflict REX.W takes precedence. */
Int sz = 4;
- /* pfx holds the summary of prefixes, and REX, seen. */
- Prefix pfx = 0x31410000;
+ /* pfx holds the summary of prefixes. */
+ Prefix pfx = PFX_EMPTY;
/* If we don't set *size properly, this causes bbToIR_X86Instr to
assert. */
not_a_prefix:
/* Dump invalid combinations */
- if (pfx & PFX_ASO) goto decode_failure; /* don't support address-size override */
+ if (pfx & PFX_ASO)
+ goto decode_failure; /* don't support address-size override */
n = 0;
if (pfx & PFX_F2) n++;
if (pfx & PFX_F3) n++;
- if (n > 1) goto decode_failure; /* can't have both */
+ if (n > 1)
+ goto decode_failure; /* can't have both */
n = 0;
if (pfx & PFX_CS) n++;
if (pfx & PFX_FS) n++;
if (pfx & PFX_GS) n++;
if (pfx & PFX_SS) n++;
- if (n > 1) goto decode_failure; /* multiple seg overrides == illegal */
+ if (n > 1)
+ goto decode_failure; /* multiple seg overrides == illegal */
/* Set up sz. */
sz = 4;
//.. DIP("ret %d\n", d32);
//.. break;
case 0xC3: /* RET */
+ if (haveF2orF3(pfx)) goto decode_failure;
dis_ret(0);
whatNext = Dis_StopHere;
DIP("ret\n");
break;
-//.. case 0xE8: /* CALL J4 */
-//.. d32 = getUDisp32(delta); delta += 4;
-//.. d32 += (guest_eip_bbstart+delta);
-//.. /* (guest_eip_bbstart+delta) == return-to addr, d32 == call-to addr */
-//.. if (d32 == guest_eip_bbstart+delta && getIByte(delta) >= 0x58
-//.. && getIByte(delta) <= 0x5F) {
-//.. /* Specially treat the position-independent-code idiom
-//.. call X
-//.. X: popl %reg
-//.. as
-//.. movl %eip, %reg.
-//.. since this generates better code, but for no other reason. */
-//.. Int archReg = getIByte(delta) - 0x58;
-//.. /* vex_printf("-- fPIC thingy\n"); */
-//.. putIReg(4, archReg, mkU32(guest_eip_bbstart+delta));
-//.. delta++; /* Step over the POP */
-//.. DIP("call 0x%x ; popl %s\n",d32,nameIReg(4,archReg));
-//.. } else {
-//.. /* The normal sequence for a call. */
-//.. t1 = newTemp(Ity_I32);
-//.. assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
-//.. putIReg(4, R_ESP, mkexpr(t1));
-//.. storeLE( mkexpr(t1), mkU32(guest_eip_bbstart+delta));
-//.. if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
-//.. /* follow into the call target. */
-//.. whatNext = Dis_Resteer;
-//.. *whereNext = d32;
-//.. } else {
-//.. jmp_lit(Ijk_Call,d32);
-//.. whatNext = Dis_StopHere;
-//.. }
-//.. DIP("call 0x%x\n",d32);
-//.. }
-//.. break;
-//..
+ case 0xE8: /* CALL J4 */
+ if (haveF2orF3(pfx)) goto decode_failure;
+ d64 = getSDisp32(delta); delta += 4;
+ d64 += (guest_rip_bbstart+delta);
+ /* (guest_rip_bbstart+delta) == return-to addr, d64 == call-to addr */
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
+ putIReg64(R_RSP, mkexpr(t1));
+ storeLE( mkexpr(t1), mkU64(guest_rip_bbstart+delta));
+ if (resteerOK && resteerOkFn((Addr64)d64)) {
+ /* follow into the call target. */
+ whatNext = Dis_Resteer;
+ *whereNext = d64;
+ } else {
+ jmp_lit(Ijk_Call,d64);
+ whatNext = Dis_StopHere;
+ }
+ DIP("call 0x%llx\n",d64);
+ break;
+
//.. //-- case 0xC8: /* ENTER */
//.. //-- d32 = getUDisp16(eip); eip += 2;
//.. //-- abyte = getIByte(delta); delta++;
//.. //-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
//.. //-- DIP(opc == 0xD4 ? "aam\n" : "aad\n");
//.. //-- break;
-//..
-//.. /* ------------------------ CWD/CDQ -------------------- */
-//..
-//.. case 0x98: /* CBW */
-//.. if (sz == 4) {
-//.. putIReg(4, R_EAX, unop(Iop_16Sto32, getIReg(2, R_EAX)));
-//.. DIP("cwde\n");
-//.. } else {
-//.. vassert(sz == 2);
-//.. putIReg(2, R_EAX, unop(Iop_8Sto16, getIReg(1, R_EAX)));
-//.. DIP("cbw\n");
-//.. }
-//.. break;
-//..
-//.. case 0x99: /* CWD/CDQ */
-//.. ty = szToITy(sz);
-//.. putIReg(sz, R_EDX,
-//.. binop(mkSizedOp(ty,Iop_Sar8),
-//.. getIReg(sz, R_EAX),
-//.. mkU8(sz == 2 ? 15 : 31)) );
-//.. DIP(sz == 2 ? "cwdq\n" : "cdqq\n");
-//.. break;
-//..
+
+ /* ------------------------ CWD/CDQ -------------------- */
+
+ case 0x98: /* CBW */
+ if (haveF2orF3(pfx)) goto decode_failure;
+ if (sz == 8) {
+ putIRegR( PFX_EMPTY, 8, R_RAX,
+ unop(Iop_32Sto64, getIRegR(PFX_EMPTY, 4, R_RAX)) );
+ DIP("cdqe\n");
+ } else
+ if (sz == 4) {
+ putIRegR( PFX_EMPTY, 4, R_RAX,
+ unop(Iop_16Sto32, getIRegR(PFX_EMPTY, 2, R_RAX)) );
+ DIP("cwde\n");
+ } else
+ if (sz == 2) {
+ vassert(sz == 2);
+ putIRegR( PFX_EMPTY, 2, R_RAX,
+ unop(Iop_8Sto16, getIRegR(PFX_EMPTY, 1, R_RAX)));
+ DIP("cbw\n");
+ }
+ else
+ goto decode_failure;
+
+ case 0x99: /* CWD/CDQ/CQO */
+ if (haveF2orF3(pfx)) goto decode_failure;
+ vassert(sz == 2 || sz == 4 || sz == 8);
+ ty = szToITy(sz);
+ putIRegR( PFX_EMPTY, sz, R_RDX,
+ binop(mkSizedOp(ty,Iop_Sar8),
+ getIRegR(PFX_EMPTY, sz, R_RAX),
+ mkU8(sz == 2 ? 15 : (sz == 4 ? 31 : 64))) );
+ DIP(sz == 2 ? "cwd\n" : (sz == 4 ? "cdq\n" : "cqo\n"));
+ break;
+
//.. /* ------------------------ FPU ops -------------------- */
//..
//.. case 0x9E: /* SAHF */
//.. case 0x24: /* AND Ib, AL */
//.. delta = dis_op_imm_A( 1, Iop_And8, True, delta, "and" );
//.. break;
-//.. case 0x25: /* AND Iv, eAX */
-//.. delta = dis_op_imm_A( sz, Iop_And8, True, delta, "and" );
-//.. break;
-//..
+ case 0x25: /* AND Iv, eAX */
+ if (haveF2orF3(pfx)) goto decode_failure;
+ delta = dis_op_imm_A( sz, Iop_And8, True, delta, "and" );
+ break;
+
//.. case 0x2C: /* SUB Ib, AL */
//.. delta = dis_op_imm_A(1, Iop_Sub8, True, delta, "sub" );
//.. break;
//.. delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, 1, delta, "add" );
//.. break;
case 0x03: /* ADD Ev,Gv */
- vex_printf("delta1 = %lld\n", delta);
+ if (haveF2orF3(pfx)) goto decode_failure;
delta = dis_op2_E_G ( pfx, False, Iop_Add8, True, sz, delta, "add" );
- vex_printf("delta2 = %lld\n", delta);
break;
//.. case 0x0A: /* OR Eb,Gb */
//.. case 0x00: /* ADD Gb,Eb */
//.. delta = dis_op2_G_E ( sorb, False, Iop_Add8, True, 1, delta, "add" );
//.. break;
-//.. case 0x01: /* ADD Gv,Ev */
-//.. delta = dis_op2_G_E ( sorb, False, Iop_Add8, True, sz, delta, "add" );
-//.. break;
-//..
+ case 0x01: /* ADD Gv,Ev */
+ delta = dis_op2_G_E ( pfx, False, Iop_Add8, True, sz, delta, "add" );
+ break;
+
//.. case 0x08: /* OR Gb,Eb */
//.. delta = dis_op2_G_E ( sorb, False, Iop_Or8, True, 1, delta, "or" );
//.. break;
//.. case 0x20: /* AND Gb,Eb */
//.. delta = dis_op2_G_E ( sorb, False, Iop_And8, True, 1, delta, "and" );
//.. break;
-//.. case 0x21: /* AND Gv,Ev */
-//.. delta = dis_op2_G_E ( sorb, False, Iop_And8, True, sz, delta, "and" );
-//.. break;
+ case 0x21: /* AND Gv,Ev */
+ delta = dis_op2_G_E ( pfx, False, Iop_And8, True, sz, delta, "and" );
+ break;
//..
//.. case 0x28: /* SUB Gb,Eb */
//.. delta = dis_op2_G_E ( sorb, False, Iop_Sub8, True, 1, delta, "sub" );
//.. //-- DIP("out %%eax/%%ax/%%al, (%%dx)\n");
//.. //-- }
//.. //-- break;
-//..
-//.. /* ------------------------ (Grp1 extensions) ---------- */
-//..
-//.. case 0x80: /* Grp1 Ib,Eb */
-//.. modrm = getIByte(delta);
-//.. am_sz = lengthAMode(delta);
-//.. sz = 1;
-//.. d_sz = 1;
-//.. d32 = getUChar(delta + am_sz);
-//.. delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
-//.. break;
-//..
-//.. case 0x81: /* Grp1 Iv,Ev */
-//.. modrm = getIByte(delta);
-//.. am_sz = lengthAMode(delta);
-//.. d_sz = sz;
-//.. d32 = getUDisp(d_sz, delta + am_sz);
-//.. delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
-//.. break;
-//..
-//.. case 0x83: /* Grp1 Ib,Ev */
-//.. modrm = getIByte(delta);
-//.. am_sz = lengthAMode(delta);
-//.. d_sz = 1;
-//.. d32 = getSDisp8(delta + am_sz);
-//.. delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
-//.. break;
-//..
+
+ /* ------------------------ (Grp1 extensions) ---------- */
+
+ case 0x80: /* Grp1 Ib,Eb */
+ modrm = getIByte(delta);
+ am_sz = lengthAMode(pfx,delta);
+ sz = 1;
+ d_sz = 1;
+ d64 = getSDisp8(delta + am_sz);
+ delta = dis_Grp1 ( pfx, delta, modrm, am_sz, d_sz, sz, d64 );
+ break;
+
+ case 0x81: /* Grp1 Iv,Ev */
+ if (haveF2orF3(pfx)) goto decode_failure;
+ modrm = getIByte(delta);
+ am_sz = lengthAMode(pfx,delta);
+ d_sz = imin(sz,4);
+ d64 = getSDisp(d_sz, delta + am_sz);
+ delta = dis_Grp1 ( pfx, delta, modrm, am_sz, d_sz, sz, d64 );
+ break;
+
+ case 0x83: /* Grp1 Ib,Ev */
+ if (haveF2orF3(pfx)) goto decode_failure;
+ modrm = getIByte(delta);
+ am_sz = lengthAMode(pfx,delta);
+ d_sz = 1;
+ d64 = getSDisp8(delta + am_sz);
+ delta = dis_Grp1 ( pfx, delta, modrm, am_sz, d_sz, sz, d64 );
+ break;
+
//.. /* ------------------------ (Grp2 extensions) ---------- */
//..
//.. case 0xC0: /* Grp2 Ib,Eb */
//.. case 0xFF: /* Grp5 Ev */
//.. delta = dis_Grp5 ( sorb, sz, delta, &whatNext );
//.. break;
-//..
-//.. /* ------------------------ Escapes to 2-byte opcodes -- */
-//..
-//.. case 0x0F: {
-//.. opc = getIByte(delta); delta++;
-//.. switch (opc) {
-//..
+
+ /* ------------------------ Escapes to 2-byte opcodes -- */
+
+ case 0x0F: {
+ opc = getIByte(delta); delta++;
+ switch (opc) {
+
//.. //-- /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
//.. //--
//.. //-- case 0xBA: /* Grp8 Ib,Ev */
//.. case 0xBB: /* BTC Gv,Ev */
//.. delta = dis_bt_G_E ( sorb, sz, delta, BtOpComp );
//.. break;
-//..
-//.. /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
-//..
-//.. case 0x40:
-//.. case 0x41:
-//.. case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
-//.. case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
-//.. case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
-//.. case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
-//.. case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
-//.. case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
-//.. case 0x48: /* CMOVSb (cmov negative) */
-//.. case 0x49: /* CMOVSb (cmov not negative) */
-//.. case 0x4A: /* CMOVP (cmov parity even) */
-//.. case 0x4B: /* CMOVNP (cmov parity odd) */
-//.. case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
-//.. case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
-//.. case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
-//.. case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
-//.. delta = dis_cmov_E_G(sorb, sz, (X86Condcode)(opc - 0x40), delta);
-//.. break;
-//..
+
+ /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
+
+ case 0x40:
+ case 0x41:
+ case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
+ case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
+ case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
+ case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
+ case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
+ case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
+ case 0x48: /* CMOVSb (cmov negative) */
+ case 0x49: /* CMOVSb (cmov not negative) */
+ case 0x4A: /* CMOVP (cmov parity even) */
+ case 0x4B: /* CMOVNP (cmov parity odd) */
+ case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
+ case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
+ case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
+ case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
+ delta = dis_cmov_E_G(pfx, sz, (AMD64Condcode)(opc - 0x40), delta);
+ break;
+
//.. /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
//..
//.. case 0xB0: /* CMPXCHG Gb,Eb */
//.. do_EMMS_preamble();
//.. DIP("emms\n");
//.. break;
-//..
-//.. /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
-//..
-//.. default:
-//.. goto decode_failure;
-//.. } /* switch (opc) for the 2-byte opcodes */
-//.. goto decode_success;
-//.. } /* case 0x0F: of primary opcode */
+
+ /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
+
+ default:
+ goto decode_failure;
+ } /* switch (opc) for the 2-byte opcodes */
+ goto decode_success;
+ } /* case 0x0F: of primary opcode */
/* ------------------------ ??? ------------------------ */
decode_success:
/* All decode successes end up here. */
DIP("\n");
- vex_printf("AA %lld\n", delta);
- vex_printf("BB %lld\n", delta_start);
*size = delta - delta_start;
return whatNext;
}