aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2023-02-12 10:28:44 -0800
committeriximeow <me@iximeow.net>2023-07-04 19:01:38 -0700
commitb0dcdbd1e084ab6d0d38b2106d9a424789b14f03 (patch)
tree2bb3a8899c511a7d11a5e6cf9d745efc87ac718b
parent94a13e0c3aae6a4e2ebcc943510ccb06f401bb31 (diff)
begin project to hoist all read_E (perf better again! 50.21cpi)
-rw-r--r--src/long_mode/mod.rs267
1 files changed, 101 insertions, 166 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 69e4733..e6bb2fc 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -4820,7 +4820,7 @@ impl PrefixRex {
}
}
-#[derive(Debug)]
+#[derive(Debug, Copy, Clone)]
struct OperandCodeBuilder {
bits: u16
}
@@ -4876,21 +4876,20 @@ impl OperandCodeBuilder {
self
}
- const fn op0_is_rrr_and_embedded_instructions(mut self) -> Self {
+ // deny ModRM `mod=11`
+ const fn deny_regmmm(mut self) -> Self {
self.bits |= 0x2000;
self
}
+ const fn denies_regmmm(&self) -> bool {
+ self.bits & 0x2000 != 0
+ }
const fn set_embedded_instructions(mut self) -> Self {
self.bits |= 0x4000;
self
}
- #[allow(unused)]
- const fn op0_is_rrr(&self) -> bool {
- self.bits & 0x2000 != 0
- }
-
fn has_embedded_instructions(&self) -> bool {
self.bits & 0x4000 != 0
}
@@ -4959,11 +4958,6 @@ impl OperandCodeBuilder {
(self.bits & 0x0800) != 0
}
- #[allow(unused)]
- const fn has_mem_reg(&self) -> bool {
- (self.bits & 0x0400) != 0
- }
-
const fn has_reg_mem(&self) -> bool {
(self.bits & 0x0400) == 0
}
@@ -5161,7 +5155,6 @@ enum OperandCase {
G_Ev_xmm_Ib,
G_E_mm_Ib,
MOVDIR64B,
- M_Gv,
ModRM_0x0f00,
ModRM_0x0f01,
ModRM_0x0f0d,
@@ -5245,7 +5238,7 @@ enum OperandCode {
ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0f00).bits(),
ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0f01).bits(),
ModRM_0x0f0d = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f0d).bits(),
- ModRM_0x0f0f = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0f0f).bits(), // 3dnow
+ ModRM_0x0f0f = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f0f).bits(), // 3dnow
ModRM_0x0fae = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0fae).bits(),
ModRM_0x0fba = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0fba).bits(),
// ModRM_0xf30fae = OperandCodeBuilder::new().read_modrm().operand_case(46).bits(),
@@ -5278,7 +5271,6 @@ enum OperandCode {
// xmmword?
ModRM_0x0f12 = OperandCodeBuilder::new()
.read_modrm()
- .op0_is_rrr_and_embedded_instructions()
.read_E()
.reg_mem()
.operand_case(OperandCase::ModRM_0x0f12)
@@ -5286,7 +5278,6 @@ enum OperandCode {
// xmmword?
ModRM_0x0f16 = OperandCodeBuilder::new()
.read_modrm()
- .op0_is_rrr_and_embedded_instructions()
.read_E()
.reg_mem()
.operand_case(OperandCase::ModRM_0x0f16)
@@ -5423,66 +5414,66 @@ 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().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().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(),
- AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().byte_operands().operand_case(OperandCase::AL_Ibs).bits(),
- AX_Ivd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AX_Ivd).bits(),
-
- Eb_Gb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(),
- Ev_Gv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(),
- Gb_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().reg_mem().operand_case(OperandCase::Internal).bits(),
- Gv_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().operand_case(OperandCase::Internal).bits(),
- Gv_M = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().operand_case(OperandCase::Gv_M).bits(),
- MOVDIR64B = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::MOVDIR64B).bits(),
- M_Gv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::M_Gv).bits(),
- Gv_Ev_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Ib).bits(),
- Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Iv).bits(),
- Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(OperandCase::Rv_Gmm_Ib).bits(),
+ Gv_Eb = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Eb).bits(),
+ Gv_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew).bits(),
+ Gv_Ew_LSL = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(),
+ Gdq_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gdq_Ed).bits(),
+ Gd_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gd_Ed).bits(),
+ Md_Gd = OperandCodeBuilder::new().read_E().deny_regmmm().operand_case(OperandCase::Md_Gd).bits(),
+// Edq_Gdq = OperandCodeBuilder::new().read_E().operand_case(49).bits(),
+ Gdq_Ev = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gdq_Ev).bits(),
+ Mdq_Gdq = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Mdq_Gdq).bits(),
+ G_E_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_xmm_Ib).bits(),
+ G_E_xmm_Ub = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_xmm_Ub).bits(),
+ G_U_xmm_Ub = OperandCodeBuilder::new().read_E().deny_regmmm().operand_case(OperandCase::G_U_xmm_Ub).bits(),
+ AL_Ob = OperandCodeBuilder::new().operand_case(OperandCase::AL_Ob).bits(),
+ AL_Xb = OperandCodeBuilder::new().operand_case(OperandCase::AL_Xb).bits(),
+ AX_Ov = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ov).bits(),
+ AL_Ibs = OperandCodeBuilder::new().byte_operands().operand_case(OperandCase::AL_Ibs).bits(),
+ AX_Ivd = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ivd).bits(),
+
+ Eb_Gb = OperandCodeBuilder::new().read_E().byte_operands().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(),
+ Ev_Gv = OperandCodeBuilder::new().read_E().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(),
+ Gb_Eb = OperandCodeBuilder::new().read_E().byte_operands().only_modrm_operands().reg_mem().operand_case(OperandCase::Internal).bits(),
+ Gv_Ev = OperandCodeBuilder::new().read_E().only_modrm_operands().reg_mem().operand_case(OperandCase::Internal).bits(),
+ Gv_M = OperandCodeBuilder::new().read_E().only_modrm_operands().reg_mem().deny_regmmm().operand_case(OperandCase::Gv_M).bits(),
+ MOVDIR64B = OperandCodeBuilder::new().read_E().reg_mem().deny_regmmm().operand_case(OperandCase::MOVDIR64B).bits(),
+ M_Gv = OperandCodeBuilder::new().read_E().mem_reg().deny_regmmm().operand_case(OperandCase::Internal).bits(),
+ Gv_Ev_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Ib).bits(),
+ Gv_Ev_Iv = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Iv).bits(),
+ Rv_Gmm_Ib = OperandCodeBuilder::new().read_modrm().read_E().reg_mem().operand_case(OperandCase::Rv_Gmm_Ib).bits(),
// gap, 0x9a
- G_xmm_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_xmm_E_mm).bits(),
- G_xmm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_xmm_U_mm).bits(),
- U_mm_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::U_mm_G_xmm).bits(),
- G_xmm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_xmm_Edq).bits(),
- G_xmm_Eq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_xmm_Eq).bits(),
- G_mm_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_mm_E_xmm).bits(),
- Gd_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Gd_U_xmm).bits(),
- Gv_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Gv_E_xmm).bits(),
+ G_xmm_E_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_E_mm).bits(),
+ G_xmm_U_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_U_mm).bits(),
+ U_mm_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::U_mm_G_xmm).bits(),
+ G_xmm_Edq = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Edq).bits(),
+ G_xmm_Eq = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Eq).bits(),
+ G_mm_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_E_xmm).bits(),
+ Gd_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_U_xmm).bits(),
+ Gv_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_E_xmm).bits(),
//= 0x816f, // mirror G_xmm_Edq, but also read an immediate
- G_xmm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ew_Ib).bits(),
- G_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_U_xmm).bits(),
- G_M_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_M_xmm).bits(),
- G_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_E_xmm).bits(),
- E_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::E_G_xmm).bits(),
- G_Ed_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_Ed_xmm).bits(),
- Ed_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::Ed_G_xmm).bits(),
- M_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::M_G_xmm).bits(),
- G_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_E_mm).bits(),
- G_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_U_mm).bits(),
- E_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::E_G_mm).bits(),
- Edq_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::Edq_G_mm).bits(),
- Edq_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::Edq_G_xmm).bits(),
- G_mm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::G_mm_Edq).bits(),
- G_mm_E = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(OperandCase::G_mm_E).bits(),
- Ev_Gv_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Ev_Gv_Ib).bits(),
- 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().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(),
+ G_xmm_Ew_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ew_Ib).bits(),
+ G_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_U_xmm).bits(),
+ G_M_xmm = OperandCodeBuilder::new().read_E().reg_mem().deny_regmmm().operand_case(OperandCase::G_M_xmm).bits(),
+ G_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_E_xmm).bits(),
+ E_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::E_G_xmm).bits(),
+ G_Ed_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_Ed_xmm).bits(),
+ Ed_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Ed_G_xmm).bits(),
+ M_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().deny_regmmm().operand_case(OperandCase::M_G_xmm).bits(),
+ G_E_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_E_mm).bits(),
+ G_U_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_U_mm).bits(),
+ E_G_mm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::E_G_mm).bits(),
+ Edq_G_mm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Edq_G_mm).bits(),
+ Edq_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Edq_G_xmm).bits(),
+ G_mm_Edq = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::G_mm_Edq).bits(),
+ G_mm_E = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::G_mm_E).bits(),
+ Ev_Gv_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Ev_Gv_Ib).bits(),
+ Ev_Gv_CL = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Ev_Gv_CL).bits(),
+ G_mm_U_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_U_mm).bits(),
+ G_Mq_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_Mq_mm).bits(),
+ G_mm_Ew_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_mm_Ew_Ib).bits(),
+ G_E_q = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_q).bits(),
+ E_G_q = OperandCodeBuilder::new().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(),
@@ -5508,7 +5499,7 @@ enum OperandCode {
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().read_E().operand_case(OperandCase::INV_Gv_M).bits(),
+ INV_Gv_M = OperandCodeBuilder::new().read_E().deny_regmmm().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(),
@@ -5855,18 +5846,6 @@ pub(self) fn read_E<
}
}
#[allow(non_snake_case)]
-pub(self) fn read_E_mm<
- T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
- S: DescriptionSink<FieldDescription>,
->(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result<OperandSpec, DecodeError> {
- if modrm >= 0b11000000 {
- instr.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };
- Ok(OperandSpec::RegMMM)
- } else {
- read_M(words, instr, modrm, sink)
- }
-}
-#[allow(non_snake_case)]
pub(self) fn read_E_st<
T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
S: DescriptionSink<FieldDescription>,
@@ -6874,34 +6853,27 @@ fn read_operands<
let opcode_start = modrm_start - 8;
if operand_code.is_only_modrm_operands() {
+ let bank;
// cool! we can precompute width and know we need to read_E.
- let bank = if !operand_code.has_byte_operands() {
+ if !operand_code.has_byte_operands() {
// further, this is an vdq E
- let bank = self.vqp_size();
- instruction.regs[0].bank = bank;
+ bank = self.vqp_size();
instruction.mem_size = bank as u8;
- bank
} else {
- let bank = self.rb_size();
- instruction.regs[0].bank = bank;
+ bank = self.rb_size();
instruction.mem_size = 1;
- bank
};
- let r = if instruction.prefixes.rex_unchecked().r() { 0b1000 } else { 0 };
let modrm = read_modrm(words)?;
- instruction.regs[0].num = ((modrm >> 3) & 7) + r;
- sink.record(
- modrm_start + 3,
- modrm_start + 5,
- InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0])
- .with_id(modrm_start + 1)
- );
- if instruction.prefixes.rex_unchecked().r() {
+ instruction.regs[0].bank = bank;
+ instruction.regs[0].num = ((modrm >> 3) & 7) + if instruction.prefixes.rex_unchecked().r() { 0b1000 } else { 0 };
+
+ // for some encodings, the rrr field selects an opcode, not an operand
+ if operand_code.bits() != OperandCode::ModRM_0xc1_Ev_Ib as u16 && operand_code.bits() != OperandCode::ModRM_0xff_Ev as u16 {
sink.record(
modrm_start + 3,
modrm_start + 5,
- InnerDescription::Misc("rex.r bit adds 0b1000 to register number")
- .with_id(modrm_start + 1)
+ InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0])
+ .with_id(modrm_start + 3)
);
}
@@ -6912,23 +6884,18 @@ fn read_operands<
InnerDescription::Misc("mmm field is a register number (mod bits: 11)")
.with_id(modrm_start + 0)
);
- // special-case here to handle `lea`. there *is* an `M_Gv` but it's only for a
- // reversed-operands `movbe` and fairly unlikely. that case is handled in
- // `unlikely_operands`. TODO: maybe this could just be a bit in `operand_code` for
- // "memory-only mmm"?
- if operand_code.bits() == (OperandCode::Gv_M as u16) {
+ if operand_code.denies_regmmm() {
return Err(DecodeError::InvalidOperand);
}
read_modrm_reg(instruction, words, modrm, bank, sink)?
} else {
read_M(words, instruction, modrm, sink)?
};
-
instruction.operands[1] = mem_oper;
if !operand_code.has_reg_mem() {
instruction.operands[0] = mem_oper;
instruction.operands[1] = OperandSpec::RegRRR;
- };
+ }
return Ok(());
}
@@ -6995,11 +6962,18 @@ fn read_operands<
InnerDescription::Misc("mmm field is a register number (mod bits: 11)")
.with_id(modrm_start + 0)
);
+ if operand_code.denies_regmmm() {
+ return Err(DecodeError::InvalidOperand);
+ }
read_modrm_reg(instruction, words, modrm, bank, sink)?
} else {
read_M(words, instruction, modrm, sink)?
};
instruction.operands[1] = mem_oper;
+ if !operand_code.has_reg_mem() {
+ instruction.operands[0] = mem_oper;
+ instruction.operands[1] = OperandSpec::RegRRR;
+ }
}
if let Some(z_operand_code) = operand_code.get_embedded_instructions() {
@@ -7417,7 +7391,6 @@ fn read_operands<
let numwidth = if opwidth == 8 { 4 } else { opwidth };
instruction.imm = read_imm_signed(words, numwidth)? as u64;
instruction.operands[1] = match opwidth {
- 1 => OperandSpec::ImmI8,
2 => OperandSpec::ImmI16,
4 => OperandSpec::ImmI32,
8 => OperandSpec::ImmI64,
@@ -7581,15 +7554,6 @@ fn read_operands<
},
OperandCase::G_M_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 are illegal for this opcode")
- .with_id(modrm_start as u32 - 8)
- );
- return Err(DecodeError::InvalidOperand);
- }
instruction.mem_size = 16;
}
@@ -7886,10 +7850,6 @@ fn read_operands<
}
}
OperandCase::INV_Gv_M => {
- if mem_oper == OperandSpec::RegMMM {
- return Err(DecodeError::InvalidOperand);
- }
-
instruction.regs[0].bank = RegisterBank::Q;
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = mem_oper;
@@ -7907,9 +7867,6 @@ fn read_operands<
}
OperandCase::G_U_xmm_Ub => {
instruction.operands[1] = mem_oper;
- if instruction.operands[1] != OperandSpec::RegMMM {
- return Err(DecodeError::InvalidOperand);
- }
instruction.regs[0].bank = RegisterBank::D;
instruction.regs[1].bank = RegisterBank::X;
instruction.imm =
@@ -8018,9 +7975,6 @@ fn read_operands<
}
OperandCase::Md_Gd => {
instruction.regs[0].bank = RegisterBank::D;
- if mem_oper == OperandSpec::RegMMM {
- return Err(DecodeError::InvalidOperand);
- }
instruction.operands[1] = instruction.operands[0];
instruction.operands[0] = mem_oper;
}
@@ -8042,10 +7996,10 @@ fn read_operands<
}
*/
OperandCase::G_U_xmm => {
- instruction.regs[0].bank = RegisterBank::X;
if mem_oper != OperandSpec::RegMMM {
return Err(DecodeError::InvalidOperand);
}
+ instruction.regs[0].bank = RegisterBank::X;
instruction.regs[1].bank = RegisterBank::X;
},
OperandCase::Gv_Ev_Ib => {
@@ -8350,12 +8304,14 @@ fn read_operands<
// 3dnow instructions are WILD, the opcode is encoded as an imm8 trailing the
// instruction.
- let modrm = read_modrm(words)?;
- instruction.operands[1] = read_E_mm(words, instruction, modrm, sink)?;
- instruction.operands[0] = OperandSpec::RegRRR;
- instruction.regs[0] = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 };
+ instruction.operands[1] = mem_oper;
+ instruction.regs[0].num &= 0b0111;
+ instruction.regs[0].bank = RegisterBank::MM;
if instruction.operands[1] != OperandSpec::RegMMM {
instruction.mem_size = 8;
+ } else {
+ instruction.regs[1].num &= 0b0111;
+ instruction.regs[1].bank = RegisterBank::MM;
}
let opcode = read_modrm(words)?;
@@ -9176,18 +9132,12 @@ fn read_operands<
}
}
OperandCase::M_G_xmm => {
- instruction.operands[1] = instruction.operands[0];
- instruction.operands[0] = mem_oper;
- if instruction.operands[0] == OperandSpec::RegMMM {
- return Err(DecodeError::InvalidOperand);
+ if instruction.opcode == Opcode::MOVNTSS {
+ instruction.mem_size = 4;
+ } else if instruction.opcode == Opcode::MOVNTPD || instruction.opcode == Opcode::MOVNTDQ || instruction.opcode == Opcode::MOVNTPS {
+ instruction.mem_size = 16;
} else {
- if instruction.opcode == Opcode::MOVNTSS {
- instruction.mem_size = 4;
- } else if instruction.opcode == Opcode::MOVNTPD || instruction.opcode == Opcode::MOVNTDQ || instruction.opcode == Opcode::MOVNTPS {
- instruction.mem_size = 16;
- } else {
- instruction.mem_size = 8;
- }
+ instruction.mem_size = 8;
}
instruction.regs[0].bank = RegisterBank::X;
}
@@ -10192,13 +10142,9 @@ fn read_operands<
return decode_x87(words, instruction, operand_code.operand_case_handler_index(), sink);
}
OperandCase::MOVDIR64B => {
- // at this point we've done a read as if it was Gv_M (`lea` operands). because the
- // first operand is actually a memory address, and this is the only x86 instruction
- // other than movs to have two memory operands, the first operand has to be sized by
- // address-size, not operand-size.
- if let OperandSpec::RegMMM = instruction.operands[1] {
- return Err(DecodeError::InvalidOperand);
- }
+ // because the first operand is actually a memory address, and this is the only x86
+ // instruction other than movs to have two memory operands, the first operand has to be
+ // sized by address-size, not operand-size.
instruction.mem_size = 64;
if instruction.prefixes.address_size() {
instruction.regs[0].bank = RegisterBank::D;
@@ -10206,17 +10152,6 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::Q;
};
}
- OperandCase::M_Gv => {
- // `lea` operands (`Gv_M`) opportunistically reject a register form of `mmm` early, but
- // leaves `M_Gv` to test memory-ness of the `mmm` operand directly. also, swap
- // operands.
- if let OperandSpec::RegMMM = instruction.operands[1] {
- return Err(DecodeError::InvalidOperand);
- }
- let temp = instruction.operands[1];
- instruction.operands[1] = instruction.operands[0];
- instruction.operands[0] = temp;
- }
};
Ok(())
}