return grp5_names[opc_aux];
}
-//.. //-- static Char* nameGrp8 ( Int opc_aux )
-//.. //-- {
-//.. //-- static Char* grp8_names[8]
-//.. //-- = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
-//.. //-- if (opc_aux < 4 || opc_aux > 7) VG_(core_panic)("nameGrp8");
-//.. //-- return grp8_names[opc_aux];
-//.. //-- }
-//..
+static HChar* nameGrp8 ( Int opc_aux )
+{
+ static HChar* grp8_names[8]
+ = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
+ if (opc_aux < 4 || opc_aux > 7) vpanic("nameGrp8(amd64)");
+ return grp8_names[opc_aux];
+}
+
//.. static HChar* nameSReg ( UInt sreg )
//.. {
//.. switch (sreg) {
}
+/* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
+static
+ULong dis_Grp8_Imm ( Prefix pfx,
+ ULong delta, UChar modrm,
+ Int am_sz, Int sz, ULong src_val,
+ Bool* decode_OK )
+{
+ /* src_val denotes a d8.
+ And delta on entry points at the modrm byte. */
+
+ IRType ty = szToITy(sz);
+ IRTemp t2 = newTemp(Ity_I64);
+ IRTemp t2m = newTemp(Ity_I64);
+ IRTemp t_addr = IRTemp_INVALID;
+ HChar dis_buf[50];
+ ULong mask;
-//.. //-- /* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
-//.. //-- static
-//.. //-- Addr dis_Grp8_BT ( UCodeBlock* cb,
-//.. //-- UChar sorb,
-//.. //-- Addr eip, UChar modrm,
-//.. //-- Int am_sz, Int sz, UInt src_val )
-//.. //-- {
-#if 0 /* stop gcc multi-line comment warning */
-/.. # define MODIFY_t2_AND_SET_CARRY_FLAG \
-/.. /* t2 is the value to be op'd on. Copy to t_fetched, then \
-/.. modify t2, if non-BT. */ \
-/.. uInstr2(cb, MOV, 4, TempReg, t2, TempReg, t_fetched); \
-/.. uInstr2(cb, MOV, sz, Literal, 0, TempReg, t_mask); \
-/.. uLiteral(cb, v_mask); \
-/.. switch (gregOfRM(modrm)) { \
-/.. case 4: /* BT */ break; \
-/.. case 5: /* BTS */ \
-/.. uInstr2(cb, OR, sz, TempReg, t_mask, TempReg, t2); break; \
-/.. case 6: /* BTR */ \
-/.. uInstr2(cb, AND, sz, TempReg, t_mask, TempReg, t2); break; \
-/.. case 7: /* BTC */ \
-/.. uInstr2(cb, XOR, sz, TempReg, t_mask, TempReg, t2); break; \
-/.. } \
-/.. /* Copy relevant bit from t_fetched into carry flag. */ \
-/.. uInstr2(cb, SHR, sz, Literal, 0, TempReg, t_fetched); \
-/.. uLiteral(cb, src_val); \
-/.. uInstr2(cb, MOV, sz, Literal, 0, TempReg, t_mask); \
-/.. uLiteral(cb, 1); \
-/.. uInstr2(cb, AND, sz, TempReg, t_mask, TempReg, t_fetched); \
-/.. uInstr1(cb, NEG, sz, TempReg, t_fetched); \
-/.. setFlagsFromUOpcode(cb, NEG);
-#endif /* stop gcc multi-line comment warning */
-//..
-//..
-//-- /* src_val denotes a d8.
-//-- And eip on entry points at the modrm byte. */
-//-- Int t1, t2, t_fetched, t_mask;
-//-- UInt pair;
-//-- HChar dis_buf[50];
-//-- UInt v_mask;
-//--
-//-- /* There is no 1-byte form of this instruction, AFAICS. */
-//-- vg_assert(sz == 2 || sz == 4);
-//--
-//-- /* 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. */
-//-- switch (sz) {
-//-- case 2: src_val &= 15; break;
-//-- case 4: src_val &= 31; break;
-//-- default: VG_(core_panic)("dis_Grp8_BT: invalid size");
-//-- }
-//--
-//-- /* Invent a mask suitable for the operation. */
-//--
-//-- switch (gregOfRM(modrm)) {
-//-- case 4: /* BT */ v_mask = 0; break;
-//-- case 5: /* BTS */ v_mask = 1 << src_val; break;
-//-- case 6: /* BTR */ v_mask = ~(1 << src_val); break;
-//-- case 7: /* BTC */ v_mask = 1 << src_val; break;
-//-- /* If this needs to be extended, probably simplest to make a
-//-- new function to handle the other cases (0 .. 3). The
-//-- Intel docs do however not indicate any use for 0 .. 3, so
-//-- we don't expect this to happen. */
-//-- default: VG_(core_panic)("dis_Grp8_BT");
-//-- }
-//-- /* Probably excessively paranoid. */
-//-- if (sz == 2)
-//-- v_mask &= 0x0000FFFF;
-//--
-//-- t1 = INVALID_TEMPREG;
-//-- t_fetched = newTemp(cb);
-//-- t_mask = newTemp(cb);
-//--
-//-- if (epartIsReg(modrm)) {
-//-- vg_assert(am_sz == 1);
-//-- t2 = newTemp(cb);
-//--
-//-- /* Fetch the value to be tested and modified. */
-//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t2);
-//-- /* Do it! */
-//-- MODIFY_t2_AND_SET_CARRY_FLAG;
-//-- /* Dump the result back, if non-BT. */
-//-- if (gregOfRM(modrm) != 4 /* BT */)
-//-- uInstr2(cb, PUT, sz, TempReg, t2, ArchReg, eregOfRM(modrm));
-//--
-//-- eip += (am_sz + 1);
-//-- DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
-//-- src_val, nameIReg(sz,eregOfRM(modrm)));
-//-- } else {
-//-- pair = disAMode ( cb, sorb, eip, dis_buf);
-//-- t1 = LOW24(pair);
-//-- t2 = newTemp(cb);
-//-- eip += HI8(pair);
-//-- eip += 1;
-//--
-//-- /* Fetch the value to be tested and modified. */
-//-- uInstr2(cb, LOAD, sz, TempReg, t1, TempReg, t2);
-//-- /* Do it! */
-//-- MODIFY_t2_AND_SET_CARRY_FLAG;
-//-- /* Dump the result back, if non-BT. */
-//-- if (gregOfRM(modrm) != 4 /* BT */) {
-//-- uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
-//-- }
-//-- DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
-//-- src_val, dis_buf);
-//-- }
-//-- return eip;
-//--
-//-- # undef MODIFY_t2_AND_SET_CARRY_FLAG
-//-- }
+ /* we're optimists :-) */
+ *decode_OK = True;
+
+ /* 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. */
+ switch (sz) {
+ case 2: src_val &= 15; break;
+ case 4: src_val &= 31; break;
+ default: *decode_OK = False; return delta;
+ }
+
+ /* Invent a mask suitable for the operation. */
+ switch (gregLO3ofRM(modrm)) {
+ case 4: /* BT */ mask = 0; break;
+ case 5: /* BTS */ mask = 1 << src_val; break;
+ case 6: /* BTR */ mask = ~(1 << src_val); break;
+ case 7: /* BTC */ mask = 1 << src_val; break;
+ /* If this needs to be extended, probably simplest to make a
+ new function to handle the other cases (0 .. 3). The
+ Intel docs do however not indicate any use for 0 .. 3, so
+ we don't expect this to happen. */
+ default: *decode_OK = False; return delta;
+ }
+
+ /* Fetch the value to be tested and modified into t2, which is
+ 64-bits wide regardless of sz. */
+ if (epartIsReg(modrm)) {
+ vassert(am_sz == 1);
+ assign( t2, widenUto64(getIRegE(sz, pfx, modrm)) );
+ delta += (am_sz + 1);
+ DIP("%s%c $0x%llx, %s\n", nameGrp8(gregLO3ofRM(modrm)),
+ nameISize(sz),
+ src_val, nameIRegE(sz,pfx,modrm));
+ } else {
+ Int len;
+ t_addr = disAMode ( &len, pfx, delta, dis_buf, 1 );
+ delta += (len+1);
+ assign( t2, widenUto64(loadLE(ty, mkexpr(t_addr))) );
+ DIP("%s%c $0x%llx, %s\n", nameGrp8(gregLO3ofRM(modrm)),
+ nameISize(sz),
+ src_val, dis_buf);
+ }
+ /* Copy relevant bit from t2 into the carry flag. */
+ /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
+ 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,
+ binop(Iop_And64,
+ binop(Iop_Shr64, mkexpr(t2), mkU8(src_val)),
+ mkU64(1))
+ ));
+
+ /* Compute the new value into t2m, if non-BT. */
+ switch (gregLO3ofRM(modrm)) {
+ case 4: /* BT */
+ break;
+ case 5: /* BTS */
+ assign( t2m, binop(Iop_Or64, mkU64(mask), mkexpr(t2)) );
+ break;
+ case 6: /* BTR */
+ assign( t2m, binop(Iop_And64, mkU64(mask), mkexpr(t2)) );
+ break;
+ case 7: /* BTC */
+ assign( t2m, binop(Iop_Xor64, mkU64(mask), mkexpr(t2)) );
+ break;
+ default:
+ vassert(0);
+ }
+
+ /* Write the result back, if non-BT. */
+ if (gregLO3ofRM(modrm) != 4 /* BT */) {
+ if (epartIsReg(modrm)) {
+ putIRegE(sz, pfx, modrm, narrowTo(ty, mkexpr(t2m)));
+ } else {
+ storeLE(mkexpr(t_addr), narrowTo(ty, mkexpr(t2m)));
+ }
+ }
+
+ return delta;
+}
/* Signed/unsigned widening multiply. Generate IR to multiply the
opc = getUChar(delta); delta++;
switch (opc) {
-//.. //-- /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
-//.. //--
-//.. //-- case 0xBA: /* Grp8 Ib,Ev */
-//.. //-- modrm = getUChar(eip);
-//.. //-- am_sz = lengthAMode(eip);
-//.. //-- d32 = getSDisp8(eip + am_sz);
-//.. //-- eip = dis_Grp8_BT ( cb, sorb, eip, modrm, am_sz, sz, d32 );
-//.. //-- break;
-//..
+ /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
+
+ case 0xBA: { /* Grp8 Ib,Ev */
+ Bool decode_OK = False;
+ if (haveF2orF3(pfx)) goto decode_failure;
+ modrm = getUChar(delta);
+ am_sz = lengthAMode(pfx,delta);
+ d64 = getSDisp8(delta + am_sz);
+ delta = dis_Grp8_Imm ( pfx, delta, modrm, am_sz, sz, d64,
+ &decode_OK );
+ if (!decode_OK)
+ goto decode_failure;
+ break;
+ }
+
//.. /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
//..
//.. case 0xBC: /* BSF Gv,Ev */