aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/long_mode/display.rs66
-rw-r--r--src/long_mode/mod.rs385
2 files changed, 215 insertions, 236 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 181ea14..b1aeee2 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -360,7 +360,6 @@ const MNEMONICS: &[&'static str] = &[
"sub",
"xor",
"cmp",
-
"rol",
"ror",
"rcl",
@@ -369,13 +368,20 @@ const MNEMONICS: &[&'static str] = &[
"shr",
"sal",
"sar",
-
- "invalid",
- "xadd",
- "bt",
- "bts",
"btc",
"btr",
+ "bts",
+ "cmpxchg",
+ "cmpxchg8b",
+ "cmpxchg16b",
+ "dec",
+ "inc",
+ "neg",
+ "not",
+ "xadd",
+ "xchg",
+ "invalid",
+ "bt",
"bsf",
"bsr",
"tzcnt",
@@ -420,8 +426,8 @@ const MNEMONICS: &[&'static str] = &[
"movsx",
"movsxd",
"shrd",
- "inc",
- "dec",
+// "inc",
+// "dec",
"hlt",
"call",
"callf",
@@ -435,7 +441,7 @@ const MNEMONICS: &[&'static str] = &[
"prefetch0",
"prefetch1",
"prefetch2",
- "xchg",
+// "xchg",
"popf",
"int",
"into",
@@ -503,9 +509,9 @@ const MNEMONICS: &[&'static str] = &[
"div",
"idiv",
"mul",
- "neg",
- "not",
- "cmpxchg",
+// "neg",
+// "not",
+// "cmpxchg",
"seto",
"setno",
"setb",
@@ -590,6 +596,7 @@ const MNEMONICS: &[&'static str] = &[
"movdq2q",
"rsqrtss",
"rcpss",
+
"andn",
"bextr",
"blsi",
@@ -620,10 +627,13 @@ const MNEMONICS: &[&'static str] = &[
"enclu",
"rdpkru",
"wrpkru",
+
"rdpru",
"clzero",
+
"rdseed",
"rdrand",
+
"addps",
"addpd",
"andnps",
@@ -764,6 +774,7 @@ const MNEMONICS: &[&'static str] = &[
"vmwrite",
"xorps",
"xorpd",
+
"vmovddup",
"vpshuflw",
"vpshufhw",
@@ -772,6 +783,7 @@ const MNEMONICS: &[&'static str] = &[
"vaddsubps",
"vcvtpd2dq",
"vlddqu",
+
"vcomisd",
"vcomiss",
"vucomisd",
@@ -1114,6 +1126,7 @@ const MNEMONICS: &[&'static str] = &[
"vzeroall",
"vldmxcsr",
"vstmxcsr",
+
"pclmulqdq",
"aeskeygenassist",
"aesimc",
@@ -1194,6 +1207,7 @@ const MNEMONICS: &[&'static str] = &[
"phaddw",
"hsubpd",
"haddpd",
+
"sha1rnds4",
"sha1nexte",
"sha1msg1",
@@ -1201,6 +1215,7 @@ const MNEMONICS: &[&'static str] = &[
"sha256rnds2",
"sha256msg1",
"sha256msg2",
+
"lzcnt",
"clgi",
"stgi",
@@ -1212,15 +1227,20 @@ const MNEMONICS: &[&'static str] = &[
"invlpga",
"invlpgb",
"tlbsync",
+
"movbe",
+
"adcx",
"adox",
+
"prefetchw",
+
"rdpid",
- "cmpxchg8b",
- "cmpxchg16b",
+// "cmpxchg8b",
+// "cmpxchg16b",
"vmptrld",
"vmptrst",
+
"bzhi",
"mulx",
"shlx",
@@ -1235,10 +1255,12 @@ const MNEMONICS: &[&'static str] = &[
"xsavec64",
"xsaves",
"xsaves64",
+
"rdfsbase",
"rdgsbase",
"wrfsbase",
"wrgsbase",
+
"crc32",
"salc",
"xlat",
@@ -1335,12 +1357,17 @@ const MNEMONICS: &[&'static str] = &[
"fxtract",
"fyl2x",
"fyl2xp1",
+
"loopnz",
"loopz",
"loop",
"jrcxz",
+
+ // started shipping in Tremont, 2020 sept 23
"movdir64b",
"movdiri",
+
+ // started shipping in Tiger Lake, 2020 sept 2
"aesdec128kl",
"aesdec256kl",
"aesdecwide128kl",
@@ -1360,8 +1387,8 @@ const MNEMONICS: &[&'static str] = &[
"femms",
"pi2fw",
"pi2fd",
- "pi2iw",
- "pi2id",
+ "pf2iw",
+ "pf2id",
"pmulhrw",
"pfcmpge",
"pfmin",
@@ -1388,7 +1415,7 @@ const MNEMONICS: &[&'static str] = &[
"enqcmd",
"enqcmds",
- // INVPCID,
+ // INVPCID
"invept",
"invvpid",
"invpcid",
@@ -1715,8 +1742,6 @@ const MNEMONICS: &[&'static str] = &[
"bndldx",
"bndstx",
-
-
"vgf2p8affineqb",
"vgf2p8affineinvqb",
"vpshrdq",
@@ -1805,6 +1830,7 @@ const MNEMONICS: &[&'static str] = &[
"vpandnq",
"vpandd",
"vpandq",
+
"psmash",
"pvalidate",
"rmpadjust",
@@ -1814,7 +1840,7 @@ const MNEMONICS: &[&'static str] = &[
impl Opcode {
fn name(&self) -> &'static str {
unsafe {
- MNEMONICS.get_kinda_unchecked(*self as usize)
+ MNEMONICS.get_kinda_unchecked((*self as usize) & 0xfff)
}
}
}
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 61c6f10..8772882 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -1068,33 +1068,14 @@ const XSAVE: [Opcode; 10] = [
#[non_exhaustive]
#[repr(u32)]
pub enum Opcode {
-ADD = 0x1000,
-ADC = 0x1001,
-AND = 0x1002,
-BTC = 0x1003,
-BTR = 0x1004,
-BTS = 0x1005,
-CMPXCHG = 0x1006,
-CMPXCHG8B = 0x1007,
-CMPXCHG16B = 0x1008,
-DEC = 0x1009,
-INC = 0x100a,
-NEG = 0x100b,
-NOT = 0x100c,
-OR = 0x100d,
-SBB = 0x100e,
-SUB = 0x100f,
-XOR = 0x1010,
-XADD = 0x1011,
-XCHG = 0x1012,
-// ADD = 0,
-// OR,
-// ADC,
-// SBB,
-// AND,
-// SUB,
-// XOR,
- CMP,
+ ADD = 0x1000,
+ OR = 0x1001,
+ ADC = 0x1002,
+ SBB = 0x1003,
+ AND = 0x1004,
+ SUB = 0x1005,
+ XOR = 0x1006,
+ CMP = 7,
ROL = 8,
ROR,
RCL,
@@ -1102,8 +1083,20 @@ XCHG = 0x1012,
SHL,
SHR,
SAL,
- SAR,
- Invalid = 16,
+ SAR = 0x0f,
+ BTC = 0x1010,
+ BTR = 0x1011,
+ BTS = 0x1012,
+ CMPXCHG = 0x1013,
+ CMPXCHG8B = 0x1014,
+ CMPXCHG16B = 0x1015,
+ DEC = 0x1016,
+ INC = 0x1017,
+ NEG = 0x1018,
+ NOT = 0x1019,
+ XADD = 0x101a,
+ XCHG = 0x101b,
+ Invalid = 0x1c,
// XADD,
BT,
// BTS,
@@ -5269,7 +5262,7 @@ enum OperandCode {
AL_DX = OperandCodeBuilder::new().operand_case(OperandCase::AL_DX).bits(),
DX_AX = OperandCodeBuilder::new().operand_case(OperandCase::DX_AX).bits(),
DX_AL = OperandCodeBuilder::new().operand_case(OperandCase::DX_AL).bits(),
- MOVQ_f30f = OperandCodeBuilder::new().operand_case(OperandCase::MOVQ_f30f).bits(),
+ MOVQ_f30f = OperandCodeBuilder::new().read_E().operand_case(OperandCase::MOVQ_f30f).bits(),
// Unsupported = OperandCodeBuilder::new().operand_case(49).bits(),
@@ -5285,7 +5278,7 @@ enum OperandCode {
// ModRM_0x660f38 = OperandCodeBuilder::new().read_modrm().operand_case(49).bits(),
// ModRM_0xf20f38 = OperandCodeBuilder::new().read_modrm().operand_case(50).bits(),
// ModRM_0xf30f38 = OperandCodeBuilder::new().read_modrm().operand_case(51).bits(),
- ModRM_0xf30f38d8 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38d8).bits(),
+ ModRM_0xf30f38d8 = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38d8).bits(),
ModRM_0xf30f38dc = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38dc).bits(),
ModRM_0xf30f38dd = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38dd).bits(),
ModRM_0xf30f38de = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38de).bits(),
@@ -5454,18 +5447,18 @@ enum OperandCode {
Zv_Ivq_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 5).bits(),
Zv_Ivq_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 6).bits(),
Zv_Ivq_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 7).bits(),
- Gv_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gv_Eb).bits(),
- Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gv_Ew).bits(),
- Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gv_Ew_LSL).bits(),
- Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gdq_Ed).bits(),
+ Gv_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gv_Eb).bits(),
+ Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gv_Ew).bits(),
+ Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(),
+ Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gdq_Ed).bits(),
Gd_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gd_Ed).bits(),
Md_Gd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Md_Gd).bits(),
// Edq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(49).bits(),
- Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gdq_Ev).bits(),
- Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Mdq_Gdq).bits(),
- G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_E_xmm_Ib).bits(),
- G_E_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_E_xmm_Ub).bits(),
- G_U_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_U_xmm_Ub).bits(),
+ Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gdq_Ev).bits(),
+ Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Mdq_Gdq).bits(),
+ G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_E_xmm_Ib).bits(),
+ G_E_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_E_xmm_Ub).bits(),
+ G_U_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_U_xmm_Ub).bits(),
AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AL_Ob).bits(),
AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AL_Xb).bits(),
AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AX_Ov).bits(),
@@ -5511,9 +5504,9 @@ enum OperandCode {
Ev_Gv_CL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Ev_Gv_CL).bits(),
G_mm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_mm_U_mm).bits(),
G_Mq_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_Mq_mm).bits(),
- G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_mm_Ew_Ib).bits(),
- G_E_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_E_q).bits(),
- E_G_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::E_G_q).bits(),
+ G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_mm_Ew_Ib).bits(),
+ G_E_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_E_q).bits(),
+ E_G_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::E_G_q).bits(),
CVT_AA = OperandCodeBuilder::new().operand_case(OperandCase::CVT_AA).bits(),
CVT_DA = OperandCodeBuilder::new().operand_case(OperandCase::CVT_DA).bits(),
Rq_Cq_0 = OperandCodeBuilder::new().operand_case(OperandCase::Rq_Cq_0).bits(),
@@ -5528,22 +5521,22 @@ enum OperandCode {
DX_Xv = OperandCodeBuilder::new().operand_case(OperandCase::DX_Xv).bits(),
AH = OperandCodeBuilder::new().operand_case(OperandCase::AH).bits(),
AX_Xv = OperandCodeBuilder::new().operand_case(OperandCase::AX_Xv).bits(),
- Ew_Sw = OperandCodeBuilder::new().operand_case(OperandCase::Ew_Sw).bits(),
+ Ew_Sw = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ew_Sw).bits(),
Fw = OperandCodeBuilder::new().operand_case(OperandCase::Fw).bits(),
I_1 = OperandCodeBuilder::new().operand_case(OperandCase::I_1).bits(),
Iw = OperandCodeBuilder::new().operand_case(OperandCase::Iw).bits(),
Iw_Ib = OperandCodeBuilder::new().operand_case(OperandCase::Iw_Ib).bits(),
Ob_AL = OperandCodeBuilder::new().operand_case(OperandCase::Ob_AL).bits(),
Ov_AX = OperandCodeBuilder::new().operand_case(OperandCase::Ov_AX).bits(),
- Sw_Ew = OperandCodeBuilder::new().operand_case(OperandCase::Sw_Ew).bits(),
+ Sw_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Sw_Ew).read_E().bits(),
Yb_AL = OperandCodeBuilder::new().operand_case(OperandCase::Yb_AL).bits(),
Yb_Xb = OperandCodeBuilder::new().operand_case(OperandCase::Yb_Xb).bits(),
Yv_AX = OperandCodeBuilder::new().operand_case(OperandCase::Yv_AX).bits(),
- INV_Gv_M = OperandCodeBuilder::new().operand_case(OperandCase::INV_Gv_M).bits(),
- PMOVX_G_E_xmm = OperandCodeBuilder::new().operand_case(OperandCase::PMOVX_G_E_xmm).bits(),
- PMOVX_E_G_xmm = OperandCodeBuilder::new().operand_case(OperandCase::PMOVX_E_G_xmm).bits(),
- G_Ev_xmm_Ib = OperandCodeBuilder::new().operand_case(OperandCase::G_Ev_xmm_Ib).bits(),
- G_E_mm_Ib = OperandCodeBuilder::new().operand_case(OperandCase::G_E_mm_Ib).bits(),
+ INV_Gv_M = OperandCodeBuilder::new().read_E().operand_case(OperandCase::INV_Gv_M).bits(),
+ PMOVX_G_E_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_G_E_xmm).bits(),
+ PMOVX_E_G_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_E_G_xmm).bits(),
+ G_Ev_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_Ev_xmm_Ib).bits(),
+ G_E_mm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_mm_Ib).bits(),
}
fn base_opcode_map(v: u8) -> Opcode {
@@ -6941,6 +6934,7 @@ fn read_with_annotations<
});
}
prefixes.rex_from(0);
+ prefixes.rb_size = RegisterBank::B;
}
if words.offset() >= 15 {
return Err(DecodeError::TooLong);
@@ -7182,6 +7176,7 @@ fn read_operands<
InnerDescription::Number("1-byte immediate", instruction.imm as i64)
.with_id(words.offset() as u32 * 8),
);
+ instruction.operands[0] = OperandSpec::ImmI8;
} else {
instruction.imm =
read_imm_signed(words, 4)? as u64;
@@ -7676,13 +7671,8 @@ fn read_operands<
}
OperandCase::Gv_Eb => {
let w = instruction.prefixes.rb_size();
- instruction.mem_size = 1;
- let bank = instruction.prefixes.vqp_size();
- let modrm = read_modrm(words)?;
- instruction.operands[1] = read_E(words, instruction, modrm, w, sink)?;
- instruction.regs[0] =
- RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank);
+ instruction.operands[1] = mem_oper;
sink.record(
modrm_start as u32 + 3,
modrm_start as u32 + 5,
@@ -7691,18 +7681,16 @@ fn read_operands<
);
if instruction.operands[1] == OperandSpec::RegMMM {
instruction.mem_size = 0;
+ instruction.regs[1].bank = w;
+ } else {
+ instruction.mem_size = 1;
}
instruction.operand_count = 2;
}
OperandCase::Gv_Ew => {
let w = RegisterBank::W;
- instruction.mem_size = 2;
- let bank = instruction.prefixes.vqp_size();
- let modrm = read_modrm(words)?;
- instruction.operands[1] = read_E(words, instruction, modrm, w, sink)?;
- instruction.regs[0] =
- RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank);
+ instruction.operands[1] = mem_oper;
sink.record(
modrm_start as u32 + 3,
modrm_start as u32 + 5,
@@ -7711,16 +7699,21 @@ fn read_operands<
);
if instruction.operands[1] == OperandSpec::RegMMM {
instruction.mem_size = 0;
+ instruction.regs[1].bank = w;
+ } else {
+ instruction.mem_size = 2;
}
instruction.operand_count = 2;
},
OperandCase::Gdq_Ed => {
- let modrm = read_modrm(words)?;
- instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?;
- instruction.mem_size = 4;
- instruction.regs[0] =
- RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q);
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].bank = RegisterBank::Q;
+ if mem_oper == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::D;
+ } else {
+ instruction.mem_size = 4;
+ }
sink.record(
modrm_start as u32 + 3,
modrm_start as u32 + 5,
@@ -7745,28 +7738,31 @@ fn read_operands<
instruction.mem_size = 16;
}
},
- op @ OperandCase::G_M_xmm |
- op @ OperandCase::G_E_xmm => {
+ OperandCase::G_M_xmm => {
instruction.regs[0].bank = RegisterBank::X;
if instruction.operands[1] == OperandSpec::RegMMM {
- if op == OperandCase::G_M_xmm {
- sink.record(
- modrm_start + 6,
- modrm_start + 7,
- InnerDescription::Misc("mod bits 0b11 are illegal for this opcode")
- .with_id(modrm_start as u32 - 8)
- );
- return Err(DecodeError::InvalidOperand);
- } else {
- sink.record(
- modrm_start + 6,
- modrm_start + 7,
- InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to xmm")
- .with_id(modrm_start as u32 + 1)
- );
- // fix the register to XMM
- instruction.regs[1].bank = RegisterBank::X;
- }
+ sink.record(
+ modrm_start + 6,
+ modrm_start + 7,
+ InnerDescription::Misc("mod bits 0b11 are illegal for this opcode")
+ .with_id(modrm_start as u32 - 8)
+ );
+ return Err(DecodeError::InvalidOperand);
+ }
+ instruction.mem_size = 16;
+
+ }
+ OperandCase::G_E_xmm => {
+ instruction.regs[0].bank = RegisterBank::X;
+ if instruction.operands[1] == OperandSpec::RegMMM {
+ sink.record(
+ modrm_start + 6,
+ modrm_start + 7,
+ InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to xmm")
+ .with_id(modrm_start as u32 + 1)
+ );
+ // fix the register to XMM
+ instruction.regs[1].bank = RegisterBank::X;
} else {
if instruction.opcode == Opcode::MOVDDUP {
instruction.mem_size = 8;
@@ -7776,11 +7772,8 @@ fn read_operands<
}
},
OperandCase::G_E_xmm_Ib => {
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X);
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].bank = RegisterBank::X;
sink.record(
modrm_start as u32 + 3,
modrm_start as u32 + 5,
@@ -7803,6 +7796,8 @@ fn read_operands<
} else {
instruction.mem_size = 16;
}
+ } else {
+ instruction.regs[1].bank = RegisterBank::X;
}
instruction.operands[2] = OperandSpec::ImmI8;
instruction.operand_count = 3;
@@ -7975,25 +7970,24 @@ fn read_operands<
}
},
OperandCase::G_E_mm_Ib => {
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E_mm(words, instruction, modrm, sink)?;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM);
+ instruction.operands[1] = mem_oper;
instruction.imm =
read_num(words, 1)? as u8 as u64;
+ instruction.regs[0].bank = RegisterBank::MM;
+ instruction.regs[0].num &= 0b0111;
if instruction.operands[1] != OperandSpec::RegMMM {
instruction.mem_size = 8;
+ } else {
+ instruction.regs[1].num &= 0b0111;
+ instruction.regs[1].bank = RegisterBank::MM;
+ instruction.mem_size = 0;
}
instruction.operands[2] = OperandSpec::ImmI8;
instruction.operand_count = 3;
}
OperandCase::G_Ev_xmm_Ib => {
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X);
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].bank = RegisterBank::X;
instruction.imm =
read_num(words, 1)? as u8 as u64;
if instruction.operands[1] != OperandSpec::RegMMM {
@@ -8008,17 +8002,16 @@ fn read_operands<
Opcode::PINSRD => 4,
_ => 8,
};
+ } else {
+ instruction.regs[1].bank = RegisterBank::X;
}
instruction.operands[2] = OperandSpec::ImmI8;
instruction.operand_count = 3;
}
OperandCase::PMOVX_E_G_xmm => {
- let modrm = read_modrm(words)?;
-
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X);
+ instruction.regs[0].bank = RegisterBank::X;
instruction.operands[1] = OperandSpec::RegRRR;
- instruction.operands[0] = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = mem_oper;
if instruction.operands[0] != OperandSpec::RegMMM {
if [].contains(&instruction.opcode) {
instruction.mem_size = 2;
@@ -8026,18 +8019,16 @@ fn read_operands<
instruction.mem_size = 8;
}
} else {
+ instruction.regs[1].bank = RegisterBank::X;
if instruction.opcode == Opcode::MOVLPD || instruction.opcode == Opcode::MOVHPD || instruction.opcode == Opcode::MOVHPS {
return Err(DecodeError::InvalidOperand);
}
}
}
OperandCase::PMOVX_G_E_xmm => {
- let modrm = read_modrm(words)?;
-
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X);
+ instruction.regs[0].bank = RegisterBank::X;
instruction.operands[0] = OperandSpec::RegRRR;
- instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[1] = mem_oper;
if instruction.operands[1] != OperandSpec::RegMMM {
if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) {
instruction.mem_size = 2;
@@ -8047,21 +8038,20 @@ fn read_operands<
instruction.mem_size = 8;
}
} else {
+ instruction.regs[1].bank = RegisterBank::X;
if instruction.opcode == Opcode::MOVLPD || instruction.opcode == Opcode::MOVHPD {
return Err(DecodeError::InvalidOperand);
}
}
}
OperandCase::INV_Gv_M => {
- let modrm = read_modrm(words)?;
- if modrm >= 0xc0 {
+ if mem_oper == OperandSpec::RegMMM {
return Err(DecodeError::InvalidOperand);
}
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q);
+ instruction.regs[0].bank = RegisterBank::Q;
instruction.operands[0] = OperandSpec::RegRRR;
- instruction.operands[1] = read_M(words, instruction, modrm, sink)?;
+ instruction.operands[1] = mem_oper;
if [Opcode::LFS, Opcode::LGS, Opcode::LSS].contains(&instruction.opcode) {
if instruction.prefixes.rex_unchecked().w() {
instruction.mem_size = 10;
@@ -8075,14 +8065,12 @@ fn read_operands<
}
}
OperandCase::G_U_xmm_Ub => {
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[1] = mem_oper;
if instruction.operands[1] != OperandSpec::RegMMM {
return Err(DecodeError::InvalidOperand);
}
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::D);
+ instruction.regs[0].bank = RegisterBank::D;
+ instruction.regs[1].bank = RegisterBank::X;
instruction.imm =
read_num(words, 1)? as u8 as u64;
instruction.operands[2] = OperandSpec::ImmU8;
@@ -8166,11 +8154,11 @@ fn read_operands<
};
}
OperandCase::G_E_xmm_Ub => {
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X);
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].bank = RegisterBank::X;
+ if mem_oper == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::X;
+ }
instruction.imm =
read_num(words, 1)? as u8 as u64;
if instruction.operands[1] != OperandSpec::RegMMM {
@@ -8261,11 +8249,9 @@ fn read_operands<
instruction.operand_count = 3;
}
OperandCase::G_mm_Ew_Ib => {
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM);
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].bank = RegisterBank::MM;
+ instruction.regs[0].num &= 0b0111;
if instruction.operands[1] == OperandSpec::RegMMM {
instruction.regs[1].bank = RegisterBank::D;
} else {
@@ -8299,37 +8285,26 @@ fn read_operands<
instruction.regs[1].num &= 0b111;
},
OperandCase::Gv_Ew_LSL => {
- let opwidth = bank_from_prefixes_64(SizeCode::vqp, instruction.prefixes);
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::W, sink)?;
+ instruction.operands[1] = mem_oper;
// lsl is weird. the full register width is written, but only the low 16 bits are used.
if instruction.operands[1] == OperandSpec::RegMMM {
instruction.regs[1].bank = RegisterBank::D;
} else {
instruction.mem_size = 2;
}
- instruction.regs[0] =
- RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), opwidth);
+ instruction.regs[0].bank = instruction.prefixes.vqp_size();
},
OperandCase::Gdq_Ev => {
- let bank = bank_from_prefixes_64(SizeCode::vqp, instruction.prefixes);
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = read_E(words, instruction, modrm, bank, sink)?;
+ instruction.operands[1] = mem_oper;
// `opwidth` can be 2, 4, or 8 here. if opwidth is 2, the first operand is a dword.
// if opwidth is 4, both registers are dwords. and if opwidth is 8, both registers are
// qword.
if instruction.operands[1] != OperandSpec::RegMMM {
instruction.mem_size = 4;
}
- let regbank = if bank == RegisterBank::W {
- RegisterBank::D
- } else {
- bank
+ if instruction.regs[0].bank == RegisterBank::W {
+ instruction.regs[0].bank = RegisterBank::D;
};
- instruction.regs[0] =
- RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), regbank);
instruction.operand_count = 2;
},
op @ OperandCase::AL_Ob |
@@ -8416,17 +8391,14 @@ fn read_operands<
}
OperandCase::Mdq_Gdq => {
let bank = if instruction.prefixes.rex_unchecked().w() { RegisterBank::Q } else { RegisterBank::D };
- let modrm = read_modrm(words)?;
-
- instruction.operands[1] = instruction.operands[0];
- instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?;
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operands[0] = mem_oper;
if instruction.operands[0] == OperandSpec::RegMMM {
return Err(DecodeError::InvalidOperand);
} else {
- instruction.mem_size = bank as u8
+ instruction.mem_size = bank as u8;
}
- instruction.regs[0] =
- RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank);
+ instruction.regs[0].bank = bank;
instruction.operand_count = 2;
}
@@ -8445,15 +8417,14 @@ fn read_operands<
return Err(DecodeError::InvalidOpcode);
}
- let modrm = read_modrm(words)?;
-
- instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::Q, sink)?;
+ instruction.operands[0] = mem_oper;
instruction.operands[1] = OperandSpec::RegRRR;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q);
+ instruction.regs[0].bank = RegisterBank::Q;
instruction.operand_count = 2;
if instruction.operands[0] != OperandSpec::RegMMM {
instruction.mem_size = 8;
+ } else {
+ instruction.regs[1].bank = RegisterBank::Q;
}
}
OperandCase::G_E_q => {
@@ -8461,15 +8432,14 @@ fn read_operands<
return Err(DecodeError::InvalidOpcode);
}
- let modrm = read_modrm(words)?;
-
instruction.operands[0] = OperandSpec::RegRRR;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q);
- instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::Q, sink)?;
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].bank = RegisterBank::Q;
instruction.operand_count = 2;
if instruction.operands[1] != OperandSpec::RegMMM {
instruction.mem_size = 8;
+ } else {
+ instruction.regs[1].bank = RegisterBank::Q;
}
}
OperandCase::G_Mq_mm => {
@@ -8493,24 +8463,25 @@ fn read_operands<
//
// anyway, there are two operands, and the primary concern here is "what are they?".
instruction.operand_count = 2;
- let modrm = read_modrm(words)?;
- instruction.regs[0] =
- RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X);
- instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.regs[0].bank = RegisterBank::X;
+ instruction.operands[1] = mem_oper;
if instruction.prefixes.rex_unchecked().w() {
let op = instruction.operands[0];
instruction.operands[0] = instruction.operands[1];
instruction.operands[1] = op;
- instruction.regs[1].bank = RegisterBank::Q;
instruction.regs[0].bank = RegisterBank::MM;
instruction.regs[0].num &= 0b111;
instruction.opcode = Opcode::MOVD;
- }
- if instruction.operands[1] != OperandSpec::RegMMM {
- if instruction.prefixes.rex_unchecked().w() {
+ if instruction.operands[1] != OperandSpec::RegMMM {
instruction.mem_size = 4;
} else {
+ instruction.regs[1].bank = RegisterBank::Q;
+ }
+ } else {
+ if instruction.operands[1] != OperandSpec::RegMMM {
instruction.mem_size = 8;
+ } else {
+ instruction.regs[1].bank = RegisterBank::X;
}
}
}
@@ -8966,43 +8937,35 @@ fn read_operands<
instruction.operands[1] = OperandSpec::ImmU8;
},
OperandCase::ModRM_0xf30f38d8 => {
- let modrm = read_modrm(words)?;
- let r = (modrm >> 3) & 7;
+ instruction.operand_count = 1;
+ let r = instruction.regs[0].num & 0b111;
+ if mem_oper == OperandSpec::RegMMM {
+ return Err(DecodeError::InvalidOperand);
+ }
+
match r {
0b000 => {
- if modrm >= 0b11_000_000 {
- return Err(DecodeError::InvalidOperand);
- }
instruction.mem_size = 48;
instruction.opcode = Opcode::AESENCWIDE128KL;
- instruction.operands[0] = read_M(words, instruction, modrm, sink)?;
+ instruction.operands[0] = mem_oper;
return Ok(());
}
0b001 => {
- if modrm >= 0b11_000_000 {
- return Err(DecodeError::InvalidOperand);
- }
instruction.mem_size = 48;
instruction.opcode = Opcode::AESDECWIDE128KL;
- instruction.operands[0] = read_M(words, instruction, modrm, sink)?;
+ instruction.operands[0] = mem_oper;
return Ok(());
}
0b010 => {
- if modrm >= 0b11_000_000 {
- return Err(DecodeError::InvalidOperand);
- }
instruction.mem_size = 64;
instruction.opcode = Opcode::AESENCWIDE256KL;
- instruction.operands[0] = read_M(words, instruction, modrm, sink)?;
+ instruction.operands[0] = mem_oper;
return Ok(());
}
0b011 => {
- if modrm >= 0b11_000_000 {
- return Err(DecodeError::InvalidOperand);
- }
instruction.mem_size = 64;
instruction.opcode = Opcode::AESDECWIDE256KL;
- instruction.operands[0] = read_M(words, instruction, modrm, sink)?;
+ instruction.operands[0] = mem_oper;
return Ok(());
}
_ => {
@@ -9388,60 +9351,50 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::X;
}
OperandCase::Ew_Sw => {
- let modrm = read_modrm(words)?;
-
// check r
- if ((modrm >> 3) & 7) > 5 {
+ let r = instruction.regs[0].num;
+ if r > 5 {
// return Err(()); //Err("Invalid r".to_owned());
return Err(DecodeError::InvalidOperand);
}
- instruction.regs[0] =
- RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 };
+ instruction.regs[0].bank = RegisterBank::S;
instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operands[0] = mem_oper;
instruction.operand_count = 2;
- let mod_bits = modrm >> 6;
- if mod_bits == 0b11 {
- instruction.regs[1] =
- RegSpec { bank: RegisterBank::W, num: modrm & 7};
- instruction.operands[0] = OperandSpec::RegMMM;
+ if mem_oper == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::W;
} else {
- instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?;
instruction.mem_size = 2;
}
},
OperandCase::Sw_Ew => {
- let modrm = read_modrm(words)?;
-
// check r
- if ((modrm >> 3) & 7) > 5 {
- // return Err(()); // Err("Invalid r".to_owned());
+ let r = instruction.regs[0].num;
+ if r > 5 {
+ // return Err(()); //Err("Invalid r".to_owned());
return Err(DecodeError::InvalidOperand);
}
- instruction.regs[0] =
- RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 };
-
// quoth the manual:
// ```
// The MOV instruction cannot be used to load the CS register. Attempting to do so
// results in an invalid opcode excep-tion (#UD). To load the CS register, use the far
// JMP, CALL, or RET instruction.
// ```
- if instruction.regs[0].num == 1 {
+ if r == 1 {
return Err(DecodeError::InvalidOperand);
}
+
+ instruction.regs[0].bank = RegisterBank::S;
instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
instruction.operand_count = 2;
- let mod_bits = modrm >> 6;
- if mod_bits == 0b11 {
- instruction.regs[1] =
- RegSpec { bank: RegisterBank::W, num: modrm & 7};
- instruction.operands[1] = OperandSpec::RegMMM;
+ if mem_oper == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::W;
} else {
- instruction.operands[1] = read_M(words, instruction, modrm, sink)?;
instruction.mem_size = 2;
}
},