static Bool haveF2orF3 ( Prefix pfx ) {
return toBool((pfx & (PFX_F2|PFX_F3)) > 0);
}
+static Bool haveF2andF3 ( Prefix pfx ) {
+ return toBool((pfx & (PFX_F2|PFX_F3)) == (PFX_F2|PFX_F3));
+}
static Bool haveF2 ( Prefix pfx ) {
return toBool((pfx & PFX_F2) > 0);
}
static Bool haveASO ( Prefix pfx ) {
return toBool((pfx & PFX_ASO) > 0);
}
+static Bool haveLOCK ( Prefix pfx ) {
+ return toBool((pfx & PFX_LOCK) > 0);
+}
/* Return True iff pfx has 66 set and F2 and F3 clear */
static Bool have66noF2noF3 ( Prefix pfx )
mov reg, reg-or-mem
Is passed the a ptr to the modRM byte, and the data size. Returns
the address advanced completely over this instruction.
+ We have to decide here whether F2 or F3 are acceptable. F2 never is.
G(src) is reg.
E(dst) is reg-or-mem
ST tmpv, (tmpa)
*/
static
-ULong dis_mov_G_E ( VexAbiInfo* vbi,
- Prefix pfx,
- Int size,
- Long delta0 )
+ULong dis_mov_G_E ( VexAbiInfo* vbi,
+ Prefix pfx,
+ Int size,
+ Long delta0,
+ /*OUT*/Bool* ok )
{
- Int len;
+ Int len;
UChar rm = getUChar(delta0);
HChar dis_buf[50];
+ *ok = True;
+
if (epartIsReg(rm)) {
+ if (haveF2orF3(pfx)) { *ok = False; return delta0; }
putIRegE(size, pfx, rm, getIRegG(size, pfx, rm));
DIP("mov%c %s,%s\n", nameISize(size),
nameIRegG(size,pfx,rm),
/* E refers to memory */
{
+ if (haveF2(pfx)) { *ok = False; return delta0; }
+ /* F3(XRELEASE) is acceptable, though. */
IRTemp addr = disAMode ( &len, vbi, pfx, delta0, dis_buf, 0 );
storeLE( mkexpr(addr), getIRegG(size, pfx, rm) );
DIP("mov%c %s,%s\n", nameISize(size),
/* we're optimists :-) */
*decode_OK = True;
+ /* Check whether F2 or F3 are acceptable. */
+ if (epartIsReg(modrm)) {
+ /* F2 or F3 are not allowed in the register case. */
+ if (haveF2orF3(pfx)) {
+ *decode_OK = False;
+ return delta;
+ }
+ } else {
+ /* F2 or F3 (but not both) are allowable provided LOCK is also
+ present. */
+ if (haveF2orF3(pfx)) {
+ if (haveF2andF3(pfx) || !haveLOCK(pfx)) {
+ *decode_OK = False;
+ return delta;
+ }
+ }
+ }
+
/* Limit src_val -- the bit offset -- to something within a word.
The Intel docs say that literal offsets larger than a word are
masked in this way. */
}
-/* Group 3 extended opcodes. */
+/* Group 3 extended opcodes. We have to decide here whether F2 and F3
+ might be valid.*/
static
ULong dis_Grp3 ( VexAbiInfo* vbi,
Prefix pfx, Int sz, Long delta, Bool* decode_OK )
*decode_OK = True;
modrm = getUChar(delta);
if (epartIsReg(modrm)) {
+ /* F2/XACQ and F3/XREL are always invalid in the non-mem case. */
+ if (haveF2orF3(pfx)) goto unhandled;
switch (gregLO3ofRM(modrm)) {
case 0: { /* TEST */
delta++;
vpanic("Grp3(amd64,R)");
}
} else {
+ /* Decide if F2/XACQ or F3/XREL might be valid. */
+ Bool validF2orF3 = haveF2orF3(pfx) ? False : True;
+ if ((gregLO3ofRM(modrm) == 3/*NEG*/ || gregLO3ofRM(modrm) == 2/*NOT*/)
+ && haveF2orF3(pfx) && !haveF2andF3(pfx) && haveLOCK(pfx)) {
+ validF2orF3 = True;
+ }
+ if (!validF2orF3) goto unhandled;
+ /* */
addr = disAMode ( &len, vbi, pfx, delta, dis_buf,
/* we have to inform disAMode of any immediate
bytes used */
}
}
return delta;
+ unhandled:
+ *decode_OK = False;
+ return delta;
}
-/* Group 4 extended opcodes. */
+/* Group 4 extended opcodes. We have to decide here whether F2 and F3
+ might be valid. */
static
ULong dis_Grp4 ( VexAbiInfo* vbi,
Prefix pfx, Long delta, Bool* decode_OK )
modrm = getUChar(delta);
if (epartIsReg(modrm)) {
+ /* F2/XACQ and F3/XREL are always invalid in the non-mem case. */
+ if (haveF2orF3(pfx)) goto unhandled;
assign(t1, getIRegE(1, pfx, modrm));
switch (gregLO3ofRM(modrm)) {
case 0: /* INC */
DIP("%sb %s\n", nameGrp4(gregLO3ofRM(modrm)),
nameIRegE(1, pfx, modrm));
} else {
+ /* Decide if F2/XACQ or F3/XREL might be valid. */
+ Bool validF2orF3 = haveF2orF3(pfx) ? False : True;
+ if ((gregLO3ofRM(modrm) == 0/*INC*/ || gregLO3ofRM(modrm) == 1/*DEC*/)
+ && haveF2orF3(pfx) && !haveF2andF3(pfx) && haveLOCK(pfx)) {
+ validF2orF3 = True;
+ }
+ if (!validF2orF3) goto unhandled;
+ /* */
IRTemp addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
assign( t1, loadLE(ty, mkexpr(addr)) );
switch (gregLO3ofRM(modrm)) {
DIP("%sb %s\n", nameGrp4(gregLO3ofRM(modrm)), dis_buf);
}
return delta;
+ unhandled:
+ *decode_OK = False;
+ return delta;
}
-/* Group 5 extended opcodes. */
+/* Group 5 extended opcodes. We have to decide here whether F2 and F3
+ might be valid. */
static
ULong dis_Grp5 ( VexAbiInfo* vbi,
Prefix pfx, Int sz, Long delta,
modrm = getUChar(delta);
if (epartIsReg(modrm)) {
+ /* F2/XACQ and F3/XREL are always invalid in the non-mem case. */
+ if (haveF2orF3(pfx)) goto unhandledR;
assign(t1, getIRegE(sz,pfx,modrm));
switch (gregLO3ofRM(modrm)) {
case 0: /* INC */
showSz ? nameISize(sz) : ' ',
nameIRegE(sz, pfx, modrm));
} else {
+ /* Decide if F2/XACQ or F3/XREL might be valid. */
+ Bool validF2orF3 = haveF2orF3(pfx) ? False : True;
+ if ((gregLO3ofRM(modrm) == 0/*INC*/ || gregLO3ofRM(modrm) == 1/*DEC*/)
+ && haveF2orF3(pfx) && !haveF2andF3(pfx) && haveLOCK(pfx)) {
+ validF2orF3 = True;
+ }
+ if (!validF2orF3) goto unhandledM;
+ /* */
addr = disAMode ( &len, vbi, pfx, delta, dis_buf, 0 );
if (gregLO3ofRM(modrm) != 2 && gregLO3ofRM(modrm) != 4
&& gregLO3ofRM(modrm) != 6) {
static
ULong dis_bt_G_E ( VexAbiInfo* vbi,
- Prefix pfx, Int sz, Long delta, BtOp op )
+ Prefix pfx, Int sz, Long delta, BtOp op,
+ /*OUT*/Bool* decode_OK )
{
HChar dis_buf[50];
UChar modrm;
Int len;
IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0,
- t_addr1, t_rsp, t_mask, t_new;
+ t_addr1, t_rsp, t_mask, t_new;
vassert(sz == 2 || sz == 4 || sz == 8);
t_addr1 = newTemp(Ity_I64);
modrm = getUChar(delta);
+ *decode_OK = True;
+ if (epartIsReg(modrm)) {
+ /* F2 and F3 are never acceptable. */
+ if (haveF2orF3(pfx)) {
+ *decode_OK = False;
+ return delta;
+ }
+ } else {
+ /* F2 or F3 (but not both) are allowed, provided LOCK is also
+ present, and only for the BTC/BTS/BTR cases (not BT). */
+ if (haveF2orF3(pfx)) {
+ if (haveF2andF3(pfx) || !haveLOCK(pfx) || op == BtOpNone) {
+ *decode_OK = False;
+ return delta;
+ }
+ }
+ }
+
assign( t_bitno0, widenSto64(getIRegG(sz, pfx, modrm)) );
if (epartIsReg(modrm)) {
reg-mem, locked: use IRCAS
*/
+ /* Decide whether F2 or F3 are acceptable. Never for register
+ case, but for the memory case, one or the other is OK provided
+ LOCK is also present. */
+ if (epartIsReg(rm)) {
+ if (haveF2orF3(pfx)) {
+ *ok = False;
+ return delta0;
+ }
+ } else {
+ if (haveF2orF3(pfx)) {
+ if (haveF2andF3(pfx) || !haveLOCK(pfx)) {
+ *ok = False;
+ return delta0;
+ }
+ }
+ }
+
if (epartIsReg(rm)) {
/* case 1 */
assign( dest, getIRegE(size, pfx, rm) );
HChar dis_buf[50];
Long delta = deltaIN;
- UChar opc = getUChar(delta);
- delta++;
+ UChar opc = getUChar(delta); delta++;
+
+ /* delta now points at the modrm byte. In most of the cases that
+ follow, neither the F2 nor F3 prefixes are allowed. However,
+ for some basic arithmetic operations we have to allow F2/XACQ or
+ F3/XREL in the case where the destination is memory and the LOCK
+ prefix is also present. Do this check by looking at the modrm
+ byte but not advancing delta over it. */
+ /* By default, F2 and F3 are not allowed, so let's start off with
+ that setting. */
+ Bool validF2orF3 = haveF2orF3(pfx) ? False : True;
+ { UChar tmp_modrm = getUChar(delta);
+ switch (opc) {
+ case 0x00: /* ADD Gb,Eb */ case 0x01: /* ADD Gv,Ev */
+ case 0x08: /* OR Gb,Eb */ case 0x09: /* OR Gv,Ev */
+ case 0x10: /* ADC Gb,Eb */ case 0x11: /* ADC Gv,Ev */
+ case 0x18: /* SBB Gb,Eb */ case 0x19: /* SBB Gv,Ev */
+ case 0x20: /* AND Gb,Eb */ case 0x21: /* AND Gv,Ev */
+ case 0x28: /* SUB Gb,Eb */ case 0x29: /* SUB Gv,Ev */
+ case 0x30: /* XOR Gb,Eb */ case 0x31: /* XOR Gv,Ev */
+ if (!epartIsReg(tmp_modrm)
+ && haveF2orF3(pfx) && !haveF2andF3(pfx) && haveLOCK(pfx)) {
+ /* dst is mem, and we have F2 or F3 but not both */
+ validF2orF3 = True;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Now, in the switch below, for the opc values examined by the
+ switch above, use validF2orF3 rather than looking at pfx
+ directly. */
switch (opc) {
case 0x00: /* ADD Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Add8, True, 1, delta, "add" );
return delta;
case 0x01: /* ADD Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Add8, True, sz, delta, "add" );
return delta;
return delta;
case 0x08: /* OR Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Or8, True, 1, delta, "or" );
return delta;
case 0x09: /* OR Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Or8, True, sz, delta, "or" );
return delta;
return delta;
case 0x10: /* ADC Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, True, Iop_Add8, True, 1, delta, "adc" );
return delta;
case 0x11: /* ADC Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, True, Iop_Add8, True, sz, delta, "adc" );
return delta;
return delta;
case 0x18: /* SBB Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, True, Iop_Sub8, True, 1, delta, "sbb" );
return delta;
case 0x19: /* SBB Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, True, Iop_Sub8, True, sz, delta, "sbb" );
return delta;
return delta;
case 0x20: /* AND Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_And8, True, 1, delta, "and" );
return delta;
case 0x21: /* AND Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_And8, True, sz, delta, "and" );
return delta;
return delta;
case 0x28: /* SUB Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, True, 1, delta, "sub" );
return delta;
case 0x29: /* SUB Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Sub8, True, sz, delta, "sub" );
return delta;
if (haveF2orF3(pfx)) goto decode_failure;
delta = dis_op_imm_A(1, False, Iop_Sub8, True, delta, "sub" );
return delta;
-
case 0x2D: /* SUB Iv, eAX */
if (haveF2orF3(pfx)) goto decode_failure;
delta = dis_op_imm_A( sz, False, Iop_Sub8, True, delta, "sub" );
return delta;
case 0x30: /* XOR Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Xor8, True, 1, delta, "xor" );
return delta;
case 0x31: /* XOR Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ if (!validF2orF3) goto decode_failure;
delta = dis_op2_G_E ( vbi, pfx, False, Iop_Xor8, True, sz, delta, "xor" );
return delta;
}
case 0x80: /* Grp1 Ib,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
modrm = getUChar(delta);
+ /* Disallow F2/XACQ and F3/XREL for the non-mem case. Allow
+ just one for the mem case and also require LOCK in this case.
+ Note that this erroneously allows XACQ/XREL on CMP since we
+ don't check the subopcode here. No big deal. */
+ if (epartIsReg(modrm) && haveF2orF3(pfx))
+ goto decode_failure;
+ if (!epartIsReg(modrm) && haveF2andF3(pfx))
+ goto decode_failure;
+ if (!epartIsReg(modrm) && haveF2orF3(pfx) && !haveLOCK(pfx))
+ goto decode_failure;
am_sz = lengthAMode(pfx,delta);
sz = 1;
d_sz = 1;
return delta;
case 0x81: /* Grp1 Iv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
modrm = getUChar(delta);
+ /* Same comment as for case 0x80 just above. */
+ if (epartIsReg(modrm) && haveF2orF3(pfx))
+ goto decode_failure;
+ if (!epartIsReg(modrm) && haveF2andF3(pfx))
+ goto decode_failure;
+ if (!epartIsReg(modrm) && haveF2orF3(pfx) && !haveLOCK(pfx))
+ goto decode_failure;
am_sz = lengthAMode(pfx,delta);
d_sz = imin(sz,4);
d64 = getSDisp(d_sz, delta + am_sz);
return delta;
/* XCHG reg,mem automatically asserts LOCK# even without a LOCK
- prefix. Therefore, surround it with a IRStmt_MBE(Imbe_BusLock)
- and IRStmt_MBE(Imbe_BusUnlock) pair. But be careful; if it is
- used with an explicit LOCK prefix, we don't want to end up with
- two IRStmt_MBE(Imbe_BusLock)s -- one made here and one made by
- the generic LOCK logic at the top of disInstr. */
+ prefix. Therefore, generate CAS regardless of the presence or
+ otherwise of a LOCK prefix. */
case 0x86: /* XCHG Gb,Eb */
sz = 1;
/* Fall through ... */
case 0x87: /* XCHG Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
modrm = getUChar(delta);
+ /* Check whether F2 or F3 are allowable. For the mem case, one
+ or the othter but not both are. We don't care about the
+ presence of LOCK in this case -- XCHG is unusual in this
+ respect. */
+ if (haveF2orF3(pfx)) {
+ if (epartIsReg(modrm)) {
+ goto decode_failure;
+ } else {
+ if (haveF2andF3(pfx))
+ goto decode_failure;
+ }
+ }
ty = szToITy(sz);
t1 = newTemp(ty); t2 = newTemp(ty);
if (epartIsReg(modrm)) {
}
return delta;
- case 0x88: /* MOV Gb,Eb */
- if (haveF2orF3(pfx)) goto decode_failure;
- delta = dis_mov_G_E(vbi, pfx, 1, delta);
+ case 0x88: { /* MOV Gb,Eb */
+ /* We let dis_mov_G_E decide whether F3(XRELEASE) is allowable. */
+ Bool ok = True;
+ delta = dis_mov_G_E(vbi, pfx, 1, delta, &ok);
+ if (!ok) goto decode_failure;
return delta;
+ }
- case 0x89: /* MOV Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
- delta = dis_mov_G_E(vbi, pfx, sz, delta);
+ case 0x89: { /* MOV Gv,Ev */
+ /* We let dis_mov_G_E decide whether F3(XRELEASE) is allowable. */
+ Bool ok = True;
+ delta = dis_mov_G_E(vbi, pfx, sz, delta, &ok);
+ if (!ok) goto decode_failure;
return delta;
+ }
case 0x8A: /* MOV Eb,Gb */
if (haveF2orF3(pfx)) goto decode_failure;
maybe_do_Mov_I_E:
modrm = getUChar(delta);
if (gregLO3ofRM(modrm) == 0) {
- if (haveF2orF3(pfx)) goto decode_failure;
if (epartIsReg(modrm)) {
+ /* Neither F2 nor F3 are allowable. */
+ if (haveF2orF3(pfx)) goto decode_failure;
delta++; /* mod/rm byte */
d64 = getSDisp(imin(4,sz),delta);
delta += imin(4,sz);
(Long)d64,
nameIRegE(sz,pfx,modrm));
} else {
+ if (haveF2(pfx)) goto decode_failure;
+ /* F3(XRELEASE) is allowable here */
addr = disAMode ( &alen, vbi, pfx, delta, dis_buf,
/*xtra*/imin(4,sz) );
delta += alen;
case 0xF6: { /* Grp3 Eb */
Bool decode_OK = True;
- if (haveF2orF3(pfx)) goto decode_failure;
+ /* RM'd: if (haveF2orF3(pfx)) goto decode_failure; */
+ /* We now let dis_Grp3 itself decide if F2 and/or F3 are valid */
delta = dis_Grp3 ( vbi, pfx, 1, delta, &decode_OK );
if (!decode_OK) goto decode_failure;
return delta;
case 0xF7: { /* Grp3 Ev */
Bool decode_OK = True;
- if (haveF2orF3(pfx)) goto decode_failure;
+ /* RM'd: if (haveF2orF3(pfx)) goto decode_failure; */
+ /* We now let dis_Grp3 itself decide if F2 and/or F3 are valid */
delta = dis_Grp3 ( vbi, pfx, sz, delta, &decode_OK );
if (!decode_OK) goto decode_failure;
return delta;
case 0xFE: { /* Grp4 Eb */
Bool decode_OK = True;
- if (haveF2orF3(pfx)) goto decode_failure;
+ /* RM'd: if (haveF2orF3(pfx)) goto decode_failure; */
+ /* We now let dis_Grp4 itself decide if F2 and/or F3 are valid */
delta = dis_Grp4 ( vbi, pfx, delta, &decode_OK );
if (!decode_OK) goto decode_failure;
return delta;
case 0xFF: { /* Grp5 Ev */
Bool decode_OK = True;
- if (haveF2orF3(pfx)) goto decode_failure;
+ /* RM'd: if (haveF2orF3(pfx)) goto decode_failure; */
+ /* We now let dis_Grp5 itself decide if F2 and/or F3 are valid */
delta = dis_Grp5 ( vbi, pfx, sz, delta, dres, &decode_OK );
if (!decode_OK) goto decode_failure;
return delta;
return delta;
}
- case 0xA3: /* BT Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ case 0xA3: { /* BT Gv,Ev */
+ /* We let dis_bt_G_E decide whether F2 or F3 are allowable. */
+ Bool ok = True;
if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
- delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpNone );
+ delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpNone, &ok );
+ if (!ok) goto decode_failure;
return delta;
+ }
case 0xA4: /* SHLDv imm8,Gv,Ev */
modrm = getUChar(delta);
"%cl", True /* left */ );
return delta;
- case 0xAB: /* BTS Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ case 0xAB: { /* BTS Gv,Ev */
+ /* We let dis_bt_G_E decide whether F2 or F3 are allowable. */
+ Bool ok = True;
if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
- delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpSet );
+ delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpSet, &ok );
+ if (!ok) goto decode_failure;
return delta;
+ }
case 0xAC: /* SHRDv imm8,Gv,Ev */
modrm = getUChar(delta);
delta = dis_mul_E_G ( vbi, pfx, sz, delta );
return delta;
- case 0xB1: { /* CMPXCHG Gv,Ev (allowed in 16,32,64 bit) */
+ case 0xB0: { /* CMPXCHG Gb,Eb */
Bool ok = True;
- if (haveF2orF3(pfx)) goto decode_failure;
- if (sz != 2 && sz != 4 && sz != 8) goto decode_failure;
- delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, sz, delta );
+ /* We let dis_cmpxchg_G_E decide whether F2 or F3 are allowable. */
+ delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, 1, delta );
if (!ok) goto decode_failure;
return delta;
}
- case 0xB0: { /* CMPXCHG Gb,Eb */
+ case 0xB1: { /* CMPXCHG Gv,Ev (allowed in 16,32,64 bit) */
Bool ok = True;
- if (haveF2orF3(pfx)) goto decode_failure;
- delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, 1, delta );
+ /* We let dis_cmpxchg_G_E decide whether F2 or F3 are allowable. */
+ if (sz != 2 && sz != 4 && sz != 8) goto decode_failure;
+ delta = dis_cmpxchg_G_E ( &ok, vbi, pfx, sz, delta );
if (!ok) goto decode_failure;
return delta;
}
- case 0xB3: /* BTR Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ case 0xB3: { /* BTR Gv,Ev */
+ /* We let dis_bt_G_E decide whether F2 or F3 are allowable. */
+ Bool ok = True;
if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
- delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpReset );
+ delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpReset, &ok );
+ if (!ok) goto decode_failure;
return delta;
+ }
case 0xB6: /* MOVZXb Eb,Gv */
if (haveF2orF3(pfx)) goto decode_failure;
return delta;
case 0xBA: { /* Grp8 Ib,Ev */
+ /* We let dis_Grp8_Imm decide whether F2 or F3 are allowable. */
Bool decode_OK = False;
- if (haveF2orF3(pfx)) goto decode_failure;
modrm = getUChar(delta);
am_sz = lengthAMode(pfx,delta);
d64 = getSDisp8(delta + am_sz);
return delta;
}
- case 0xBB: /* BTC Gv,Ev */
- if (haveF2orF3(pfx)) goto decode_failure;
+ case 0xBB: { /* BTC Gv,Ev */
+ /* We let dis_bt_G_E decide whether F2 or F3 are allowable. */
+ Bool ok = False;
if (sz != 8 && sz != 4 && sz != 2) goto decode_failure;
- delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpComp );
+ delta = dis_bt_G_E ( vbi, pfx, sz, delta, BtOpComp, &ok );
+ if (!ok) goto decode_failure;
return delta;
+ }
case 0xBC: /* BSF Gv,Ev */
if (!haveF2orF3(pfx)
*expect_CAS = True;
/* Decode, and generate address. */
- if (have66orF2orF3(pfx)) goto decode_failure;
+ if (have66(pfx)) goto decode_failure;
if (sz != 4 && sz != 8) goto decode_failure;
if (sz == 8 && !(archinfo->hwcaps & VEX_HWCAPS_AMD64_CX16))
goto decode_failure;
modrm = getUChar(delta);
if (epartIsReg(modrm)) goto decode_failure;
if (gregLO3ofRM(modrm) != 1) goto decode_failure;
+ if (haveF2orF3(pfx)) {
+ /* Since the e-part is memory only, F2 or F3 (one or the
+ other) is acceptable if LOCK is also present. But only
+ for cmpxchg8b. */
+ if (sz == 8) goto decode_failure;
+ if (haveF2andF3(pfx) || !haveLOCK(pfx)) goto decode_failure;
+ }
+
addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
delta += alen;