diff options
author | iximeow <me@iximeow.net> | 2020-08-09 00:16:07 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-08-09 01:39:01 -0700 |
commit | a3f848e3426175d9ac782c19de4855de260d76a9 (patch) | |
tree | 8feff0711a2e3fd3c4628a976a33c753fe89409b | |
parent | c1586163d7aafd3db8799c0883208e749d63e38e (diff) |
significantly reorganize what operands are unlikely
likely operands are now also required to have contiguous special cases
0..31. this is to avoid generating a massively sparse jump table for no
reason twice - once for unlikely_operands is quite enough as-is.
this will undoubtedly be a wildly annoying maintenance burden. if this
pans out (initial expiriments suggest it might) then maybe a macro will
do...
-rw-r--r-- | src/long_mode/mod.rs | 603 |
1 files changed, 317 insertions, 286 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index e6f2064..9d3b05a 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -3471,23 +3471,21 @@ impl OperandCodeBuilder { self.bits & 0x0200 != 0 } - // WHEN AN IMMEDIATE IS PRESENT, THERE ARE ONLY 0x1F ALLOWED SPECIAL CASES. + // WHEN AN IMMEDIATE IS PRESENT, THERE ARE ONLY 0x3F ALLOWED SPECIAL CASES. // WHEN NO IMMEDIATE IS PRESENT, THERE ARE 0xFF ALLOWED SPECIAL CASES. // SIZE IS DECIDED BY THE FOLLOWING TABLE: // 0: 1 BYTE - // 1: 2 BYTES - // 2: 4 BYTES - // 4: 8 BYTES + // 1: 4 BYTES const fn with_imm(mut self, only_imm: bool, size: u8) -> Self { self.bits |= 0x100; - self.bits |= (size as u16) << 5; + self.bits |= (size as u16) << 6; self.bits |= (only_imm as u16) << 7; self } fn has_imm(&self) -> Option<(bool, u8)> { if self.bits & 0x100 != 0 { - Some(((self.bits & 0x80) != 0, (self.bits as u8 >> 5) & 3)) + Some(((self.bits & 0x80) != 0, (self.bits as u8 >> 6) & 1)) } else { None } @@ -3513,59 +3511,34 @@ impl OperandCodeBuilder { #[repr(u16)] #[derive(Copy, Clone, Debug, PartialEq)] pub enum OperandCode { - Nothing = 0, - CVT_AA, - CVT_DA, - Rq_Cq_0, - Rq_Dq_0, - Cq_Rq_0, - Dq_Rq_0, - FS, - GS, - Yb_DX, - Yv_DX, - DX_Xb, - DX_Xv, - AH, - AX_Xv, - Ew_Sw, - Fw, - I_1, - I_3, - Ivs, - Iw, - Iw_Ib, - Ob_AL, - Ov_AX, - Sw_Ew, - Yb_AL, - Yb_Xb, - Yv_AX, - Ib = OperandCodeBuilder::new().with_imm(false, 0).special_case(0).bits(), - Ibs = OperandCodeBuilder::new().with_imm(true, 0).special_case(1).bits(), - Jvds = OperandCodeBuilder::new().with_imm(true, 2).special_case(0).bits(), + Ivs = OperandCodeBuilder::new().special_case(25).bits(), + I_3 = OperandCodeBuilder::new().special_case(27).bits(), + Nothing = OperandCodeBuilder::new().special_case(28).bits(), + Ib = OperandCodeBuilder::new().with_imm(false, 0).special_case(32).bits(), + Ibs = OperandCodeBuilder::new().with_imm(true, 0).special_case(33).bits(), + Jvds = OperandCodeBuilder::new().with_imm(true, 1).special_case(32).bits(), Yv_Xv = OperandCodeBuilder::new().special_case(50).bits(), - x87_d8 = OperandCodeBuilder::new().special_case(31).bits(), - x87_d9 = OperandCodeBuilder::new().special_case(32).bits(), - x87_da = OperandCodeBuilder::new().special_case(33).bits(), - x87_db = OperandCodeBuilder::new().special_case(34).bits(), - x87_dc = OperandCodeBuilder::new().special_case(35).bits(), - x87_dd = OperandCodeBuilder::new().special_case(36).bits(), - x87_de = OperandCodeBuilder::new().special_case(37).bits(), - x87_df = OperandCodeBuilder::new().special_case(38).bits(), + x87_d8 = OperandCodeBuilder::new().special_case(32).bits(), + x87_d9 = OperandCodeBuilder::new().special_case(33).bits(), + x87_da = OperandCodeBuilder::new().special_case(34).bits(), + x87_db = OperandCodeBuilder::new().special_case(35).bits(), + x87_dc = OperandCodeBuilder::new().special_case(36).bits(), + x87_dd = OperandCodeBuilder::new().special_case(37).bits(), + x87_de = OperandCodeBuilder::new().special_case(38).bits(), + x87_df = OperandCodeBuilder::new().special_case(39).bits(), Eb_R0 = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(20) + .operand_case(0) .bits(), - AL_Ib = OperandCodeBuilder::new().special_case(2).with_imm(false, 0).bits(), - AX_Ib = OperandCodeBuilder::new().special_case(3).with_imm(false, 0).bits(), - Ib_AL = OperandCodeBuilder::new().special_case(4).with_imm(false, 0).bits(), - Ib_AX = OperandCodeBuilder::new().special_case(5).with_imm(false, 0).bits(), + AL_Ib = OperandCodeBuilder::new().special_case(33).with_imm(false, 0).bits(), + AX_Ib = OperandCodeBuilder::new().special_case(34).with_imm(false, 0).bits(), + Ib_AL = OperandCodeBuilder::new().special_case(35).with_imm(false, 0).bits(), + Ib_AX = OperandCodeBuilder::new().special_case(36).with_imm(false, 0).bits(), AX_DX = OperandCodeBuilder::new().special_case(44).bits(), AL_DX = OperandCodeBuilder::new().special_case(45).bits(), DX_AX = OperandCodeBuilder::new().special_case(46).bits(), @@ -3574,37 +3547,37 @@ pub enum OperandCode { Unsupported = OperandCodeBuilder::new().special_case(49).bits(), - ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().special_case(0).bits(), - ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().special_case(1).bits(), - ModRM_0x0f0d = OperandCodeBuilder::new().read_modrm().special_case(2).bits(), - ModRM_0x0fae = OperandCodeBuilder::new().read_modrm().special_case(3).bits(), - ModRM_0x0fba = OperandCodeBuilder::new().read_modrm().special_case(4).bits(), - ModRM_0xf30fae = OperandCodeBuilder::new().read_modrm().special_case(6).bits(), - ModRM_0x660fae = OperandCodeBuilder::new().read_modrm().special_case(7).bits(), - ModRM_0xf30fc7 = OperandCodeBuilder::new().read_modrm().special_case(8).bits(), - ModRM_0x660f38 = OperandCodeBuilder::new().read_modrm().special_case(9).bits(), - ModRM_0xf20f38 = OperandCodeBuilder::new().read_modrm().special_case(24).bits(), - ModRM_0xf30f38 = OperandCodeBuilder::new().read_modrm().special_case(10).bits(), - ModRM_0x660f3a = OperandCodeBuilder::new().read_modrm().special_case(11).bits(), - ModRM_0x0f38 = OperandCodeBuilder::new().read_modrm().special_case(12).bits(), - ModRM_0x0f3a = OperandCodeBuilder::new().read_modrm().special_case(13).bits(), - ModRM_0x0f71 = OperandCodeBuilder::new().read_modrm().special_case(14).bits(), - ModRM_0x0f72 = OperandCodeBuilder::new().read_modrm().special_case(15).bits(), - ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(16).bits(), - ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(17).bits(), - ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(18).bits(), - ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(19).bits(), - ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(20).bits(), - ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(21).bits(), - ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(22).bits(), - ModRM_0x0fc7 = OperandCodeBuilder::new().read_modrm().special_case(23).bits(), + ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().special_case(40).bits(), + ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().special_case(41).bits(), + ModRM_0x0f0d = OperandCodeBuilder::new().read_modrm().special_case(42).bits(), + ModRM_0x0fae = OperandCodeBuilder::new().read_modrm().special_case(43).bits(), + ModRM_0x0fba = OperandCodeBuilder::new().read_modrm().special_case(44).bits(), + ModRM_0xf30fae = OperandCodeBuilder::new().read_modrm().special_case(46).bits(), + ModRM_0x660fae = OperandCodeBuilder::new().read_modrm().special_case(47).bits(), + ModRM_0xf30fc7 = OperandCodeBuilder::new().read_modrm().special_case(48).bits(), + ModRM_0x660f38 = OperandCodeBuilder::new().read_modrm().special_case(49).bits(), + ModRM_0xf20f38 = OperandCodeBuilder::new().read_modrm().special_case(50).bits(), + ModRM_0xf30f38 = OperandCodeBuilder::new().read_modrm().special_case(51).bits(), + ModRM_0x660f3a = OperandCodeBuilder::new().read_modrm().special_case(52).bits(), + ModRM_0x0f38 = OperandCodeBuilder::new().read_modrm().special_case(53).bits(), + ModRM_0x0f3a = OperandCodeBuilder::new().read_modrm().special_case(54).bits(), + ModRM_0x0f71 = OperandCodeBuilder::new().read_modrm().special_case(55).bits(), + ModRM_0x0f72 = OperandCodeBuilder::new().read_modrm().special_case(56).bits(), + ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(), + ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), + ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), + ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(), + ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(), + ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(), + ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(), + ModRM_0x0fc7 = OperandCodeBuilder::new().read_modrm().special_case(64).bits(), // xmmword? ModRM_0x0f12 = OperandCodeBuilder::new() .read_modrm() .op0_is_rrr_and_embedded_instructions() .read_E() .reg_mem() - .operand_case(0) + .operand_case(65) .bits(), // xmmword? ModRM_0x0f16 = OperandCodeBuilder::new() @@ -3612,7 +3585,7 @@ pub enum OperandCode { .op0_is_rrr_and_embedded_instructions() .read_E() .reg_mem() - .operand_case(1) + .operand_case(66) .bits(), // encode immediates? ModRM_0xc0_Eb_Ib = OperandCodeBuilder::new() @@ -3620,39 +3593,39 @@ pub enum OperandCode { .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(0) + .operand_case(5) .bits(), ModRM_0xc1_Ev_Ib = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(0) + .operand_case(6) .bits(), ModRM_0xd0_Eb_1 = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(1) + .operand_case(7) .bits(), ModRM_0xd1_Ev_1 = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(1) + .operand_case(8) .bits(), ModRM_0xd2_Eb_CL = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(2) + .operand_case(9) .bits(), ModRM_0xd3_Ev_CL = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(2) + .operand_case(10) .bits(), ModRM_0x80_Eb_Ib = OperandCodeBuilder::new() .read_modrm() @@ -3660,79 +3633,79 @@ pub enum OperandCode { .read_E() .with_imm(false, 0) .byte_operands() - .operand_case(3) + .operand_case(1) .bits(), ModRM_0x83_Ev_Ibs = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .with_imm(false, 0) - .operand_case(3) + .operand_case(26) .bits(), // this would be Eb_Ivs, 0x8e ModRM_0x81_Ev_Ivs = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(4) + .operand_case(2) .bits(), ModRM_0xc6_Eb_Ib = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(5) + .operand_case(3) .bits(), ModRM_0xc7_Ev_Iv = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(5) + .operand_case(4) .bits(), ModRM_0xfe_Eb = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(6) + .operand_case(13) .bits(), ModRM_0x8f_Ev = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(6) + .operand_case(30) .bits(), // gap, 0x94 ModRM_0xff_Ev = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(7) + .operand_case(14) .bits(), ModRM_0x0f18 = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(8) + .operand_case(58) .bits(), ModRM_0xf6 = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(9) + .operand_case(11) .bits(), ModRM_0xf7 = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(10) + .operand_case(12) .bits(), Ev = OperandCodeBuilder::new() .read_modrm() .set_embedded_instructions() .read_E() - .operand_case(11) + .operand_case(18) .bits(), Zv_R0 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 0).bits(), Zv_R1 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 1).bits(), @@ -3766,58 +3739,83 @@ pub 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(4).bits(), - Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(5).bits(), - Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(7).bits(), - Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(6).bits(), - Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(10).bits(), - Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(11).bits(), - G_E_mm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).reg_mem().operand_case(2).bits(), - G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(8).bits(), - AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(0).bits(), - AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(1).bits(), - AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(3).bits(), - AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().with_imm(false, 0).byte_operands().operand_case(0).bits(), - AX_Ivd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(9).bits(), + Gv_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(15).bits(), + Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(16).bits(), + Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(37).bits(), + Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(17).bits(), + Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(40).bits(), + Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(51).bits(), + G_E_mm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).reg_mem().operand_case(29).bits(), + G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(22).bits(), + AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(50).bits(), + AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(52).bits(), + AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(53).bits(), + AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().with_imm(false, 0).byte_operands().operand_case(23).bits(), + AX_Ivd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(24).bits(), Eb_Gb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().mem_reg().bits(), Ev_Gv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().mem_reg().bits(), Gb_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().reg_mem().bits(), Gv_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().bits(), Gv_M = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().operand_case(25).bits(), - Gb_Eb_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).byte_operands().reg_mem().operand_case(1).bits(), - Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(1).bits(), - Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(25).bits(), + Gb_Eb_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).byte_operands().reg_mem().operand_case(40).bits(), + Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(41).bits(), + Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(55).bits(), // gap, 0x9a - G_xmm_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(23).bits(), - G_xmm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(24).bits(), - U_mm_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(25).bits(), - G_xmm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(26).bits(), - G_xmm_Eq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(27).bits(), - G_mm_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(28).bits(), - Gd_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(29).bits(), - Gv_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(30).bits(), + G_xmm_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(53).bits(), + G_xmm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(54).bits(), + U_mm_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(55).bits(), + G_xmm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(56).bits(), + G_xmm_Eq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(57).bits(), + G_mm_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(58).bits(), + Gd_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(59).bits(), + Gv_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(60).bits(), //= 0x816f, // mirror G_xmm_Edq, but also read an immediate - G_xmm_Ed_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(31).bits(), - G_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(13).bits(), - G_M_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(10).bits(), - G_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(9).bits(), - E_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(11).bits(), - M_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(12).bits(), - G_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(14).bits(), - G_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(15).bits(), - E_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(16).bits(), - Edq_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(17).bits(), - Edq_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(18).bits(), - G_mm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(19).bits(), - G_mm_E = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(20).bits(), - Ev_Gv_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(21).bits(), - Ev_Gv_CL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(22).bits(), - G_mm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(32).bits(), - G_Md_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(33).bits(), - G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(20).bits(), - G_E_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(21).bits(), - E_G_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(22).bits(), + G_xmm_Ed_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(61).bits(), + G_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(62).bits(), + G_M_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(20).bits(), + G_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(21).bits(), + E_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(19).bits(), + M_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(63).bits(), + G_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(64).bits(), + G_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(65).bits(), + E_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(66).bits(), + Edq_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(67).bits(), + Edq_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(68).bits(), + G_mm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(69).bits(), + G_mm_E = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(70).bits(), + Ev_Gv_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(71).bits(), + Ev_Gv_CL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(72).bits(), + G_mm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(73).bits(), + G_Md_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(74).bits(), + G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(75).bits(), + G_E_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(76).bits(), + E_G_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(77).bits(), + CVT_AA = OperandCodeBuilder::new().special_case(77).bits(), + CVT_DA = OperandCodeBuilder::new().special_case(78).bits(), + Rq_Cq_0 = OperandCodeBuilder::new().special_case(79).bits(), + Rq_Dq_0 = OperandCodeBuilder::new().special_case(80).bits(), + Cq_Rq_0 = OperandCodeBuilder::new().special_case(81).bits(), + Dq_Rq_0 = OperandCodeBuilder::new().special_case(82).bits(), + FS = OperandCodeBuilder::new().special_case(83).bits(), + GS = OperandCodeBuilder::new().special_case(84).bits(), + Yb_DX = OperandCodeBuilder::new().special_case(85).bits(), + Yv_DX = OperandCodeBuilder::new().special_case(86).bits(), + DX_Xb = OperandCodeBuilder::new().special_case(87).bits(), + DX_Xv = OperandCodeBuilder::new().special_case(88).bits(), + AH = OperandCodeBuilder::new().special_case(89).bits(), + AX_Xv = OperandCodeBuilder::new().special_case(90).bits(), + Ew_Sw = OperandCodeBuilder::new().special_case(91).bits(), + Fw = OperandCodeBuilder::new().special_case(92).bits(), + I_1 = OperandCodeBuilder::new().special_case(93).bits(), + Iw = OperandCodeBuilder::new().special_case(94).bits(), + Iw_Ib = OperandCodeBuilder::new().special_case(95).bits(), + Ob_AL = OperandCodeBuilder::new().special_case(96).bits(), + Ov_AX = OperandCodeBuilder::new().special_case(97).bits(), + Sw_Ew = OperandCodeBuilder::new().special_case(98).bits(), + Yb_AL = OperandCodeBuilder::new().special_case(99).bits(), + Yb_Xb = OperandCodeBuilder::new().special_case(100).bits(), + Yv_AX = OperandCodeBuilder::new().special_case(101).bits(), } fn base_opcode_map(v: u8) -> Opcode { @@ -5649,10 +5647,44 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in } Ok(()) } +/* likely cases + OperandCode::Eb_R0 => 0 + _op @ OperandCode::ModRM_0x80_Eb_Ib => 1 + _op @ OperandCode::ModRM_0x81_Ev_Ivs => 2 + op @ OperandCode::ModRM_0xc6_Eb_Ib => 3 + op @ OperandCode::ModRM_0xc7_Ev_Iv => 4 + op @ OperandCode::ModRM_0xc0_Eb_Ib => 5 + op @ OperandCode::ModRM_0xc1_Ev_Ib => 6 + op @ OperandCode::ModRM_0xd0_Eb_1 => 7 + op @ OperandCode::ModRM_0xd1_Ev_1 => 8 + op @ OperandCode::ModRM_0xd2_Eb_CL => 9 + op @ OperandCode::ModRM_0xd3_Ev_CL => 10 + _op @ OperandCode::ModRM_0xf6 => 11 + _op @ OperandCode::ModRM_0xf7 => 12 + OperandCode::ModRM_0xfe_Eb => 13 + OperandCode::ModRM_0xff_Ev => 14 + OperandCode::Gv_Eb => 15 + OperandCode::Gv_Ew => 16 + OperandCode::Gdq_Ed => 17 + OperandCode::Ev => 18 + OperandCode::E_G_xmm => 19 + op @ OperandCode::G_M_xmm => 20 + op @ OperandCode::G_E_xmm => 21 + OperandCode::G_E_xmm_Ib => 22 + OperandCode::AL_Ibs => 23 + OperandCode::AX_Ivd => 24 + OperandCode::Ivs => 25 + OperandCode::ModRM_0x83_Ev_Ibs => 26 + OperandCode::I_3 => 27 + OperandCode::Nothing => 28 + OperandCode::G_E_mm_Ib => 29 + OperandCode::ModRM_0x8f_Ev => 30 + + */ #[inline(always)] fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), DecodeError> { - instruction.operand_count = 2; instruction.operands[0] = OperandSpec::RegRRR; + instruction.operand_count = 2; let operand_code = OperandCodeBuilder::from_bits(operand_code as u16); if operand_code.has_embedded_instructions() { match operand_code.get_embedded_instructions() { @@ -5683,7 +5715,6 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.imm = read_imm_unsigned(&mut bytes_iter, 1, length)?; instruction.operands[1] = OperandSpec::ImmU8; - instruction.operand_count = 2; } 3 => { // category == 3, Zv_Ivq_R @@ -5705,7 +5736,6 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, 8 => OperandSpec::ImmI64, _ => unsafe { unreachable_unchecked() } }; - instruction.operand_count = 2; } _ => { unreachable!("bad category"); @@ -5759,7 +5789,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, if let Some((only_imm, immsz)) = operand_code.has_imm() { instruction.imm = - read_imm_signed(&mut bytes_iter, 1 << immsz, length)? as u64; + read_imm_signed(&mut bytes_iter, 1 << (immsz * 2), length)? as u64; if only_imm { if immsz == 0 { instruction.operands[0] = OperandSpec::ImmI8; @@ -5777,9 +5807,9 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.operands[1] = OperandSpec::RegRRR; }; } else { - let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) }; - match operand_code { - OperandCode::Eb_R0 => { +// match operand_code { + match operand_code.special_case_handler_index() { + 0 => { // turns out xed cand capstone both permit nonzero rrr bits here. // if (modrm & 0b00111000) != 0 { // instruction.opcode = Opcode::Invalid; @@ -5789,12 +5819,12 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.operands[0] = mem_oper; instruction.operand_count = 1; }, - _op @ OperandCode::ModRM_0x80_Eb_Ib => { + 1 => { instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; } - _op @ OperandCode::ModRM_0x81_Ev_Ivs => { + 2 => { instruction.operands[0] = mem_oper; let numwidth = if opwidth == 8 { 4 } else { opwidth }; instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; @@ -5807,10 +5837,10 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, }; instruction.operand_count = 2; }, - op @ OperandCode::ModRM_0xc6_Eb_Ib | - op @ OperandCode::ModRM_0xc7_Ev_Iv => { + op @ 3 | + op @ 4 => { if modrm == 0xf8 { - if op == OperandCode::ModRM_0xc6_Eb_Ib { + if op == 3 { instruction.opcode = Opcode::XABORT; instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; instruction.operands[0] = OperandSpec::ImmI8; @@ -5846,24 +5876,24 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, }; instruction.operand_count = 2; }, - op @ OperandCode::ModRM_0xc0_Eb_Ib | - op @ OperandCode::ModRM_0xc1_Ev_Ib | - op @ OperandCode::ModRM_0xd0_Eb_1 | - op @ OperandCode::ModRM_0xd1_Ev_1 | - op @ OperandCode::ModRM_0xd2_Eb_CL | - op @ OperandCode::ModRM_0xd3_Ev_CL => { + op @ 5 | + op @ 6 | + op @ 7 | + op @ 8 | + op @ 9 | + op @ 10 => { instruction.operands[0] = mem_oper; instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); - if let OperandCode::ModRM_0xd3_Ev_CL = op { + if op == 10 { instruction.modrm_rrr = RegSpec::cl(); instruction.operands[1] = OperandSpec::RegRRR; - } else if let OperandCode::ModRM_0xd2_Eb_CL = op { + } else if op == 9 { instruction.modrm_rrr = RegSpec::cl(); instruction.operands[1] = OperandSpec::RegRRR; } else { let num = match op { - OperandCode::ModRM_0xc0_Eb_Ib | - OperandCode::ModRM_0xc1_Ev_Ib => { + 5 | + 6 => { *length += 1; read_num(&mut bytes_iter, 1)? } @@ -5877,8 +5907,8 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, } instruction.operand_count = 2; }, - _op @ OperandCode::ModRM_0xf6 | - _op @ OperandCode::ModRM_0xf7 => { + 11 | + 12 => { instruction.operands[0] = mem_oper; instruction.operand_count = 1; match (modrm >> 3) & 7 { @@ -5918,7 +5948,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, } } }, - OperandCode::ModRM_0xfe_Eb => { + 13 => { instruction.operands[0] = mem_oper; let r = (modrm >> 3) & 7; if r >= 2 { @@ -5930,18 +5960,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, ][r as usize]; instruction.operand_count = 1; } - OperandCode::ModRM_0x8f_Ev => { - instruction.operands[0] = mem_oper; - let r = (modrm >> 3) & 7; - if r >= 1 { - return Err(DecodeError::InvalidOpcode); - } - instruction.opcode = [ - Opcode::POP, - ][r as usize]; - instruction.operand_count = 1; - } - OperandCode::ModRM_0xff_Ev => { + 14 => { instruction.operands[0] = mem_oper; let r = (modrm >> 3) & 7; if r == 7 { @@ -5966,7 +5985,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.opcode = opcode; instruction.operand_count = 1; } - OperandCode::Gv_Eb => { + 15 => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); let modrm = read_modrm(&mut bytes_iter, length)?; @@ -5975,7 +5994,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); instruction.operand_count = 2; }, - OperandCode::Gv_Ew => { + 16 => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); let modrm = read_modrm(&mut bytes_iter, length)?; @@ -5984,20 +6003,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); instruction.operand_count = 2; }, - OperandCode::Gv_Ew_LSL => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, length)?; - - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; - // lsl is weird. the full register width is written, but only the low 16 bits are used. - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::D; - } - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); - instruction.operand_count = 2; - }, - OperandCode::Gdq_Ed => { + 17 => { let opwidth = 8; let modrm = read_modrm(&mut bytes_iter, length)?; @@ -6007,29 +6013,11 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); instruction.operand_count = 2; }, - OperandCode::Gdq_Ev => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, length)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - // `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. - let regwidth = if opwidth == 2 { - 4 - } else { - opwidth - }; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), regwidth, instruction.prefixes.rex().present()); - instruction.operand_count = 2; - }, - OperandCode::Ev => { + 18 => { instruction.operands[0] = mem_oper; instruction.operand_count = 1; }, - OperandCode::E_G_xmm => { + 19 => { instruction.modrm_rrr.bank = RegisterBank::X; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; @@ -6039,38 +6027,12 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.modrm_mmm.bank = RegisterBank::X; } }, - OperandCode::G_E_mm => { - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - } - instruction.operand_count = 2; - }, - OperandCode::G_U_mm => { - instruction.modrm_rrr.bank = RegisterBank::D; - if mem_oper != OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); - } - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - instruction.operand_count = 2; - }, - OperandCode::G_U_xmm => { - instruction.modrm_rrr.bank = RegisterBank::X; - if mem_oper != OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); - } - instruction.modrm_mmm.bank = RegisterBank::X; - instruction.operand_count = 2; - }, - op @ OperandCode::G_M_xmm | - op @ OperandCode::G_E_xmm => { + op @ 20 | + op @ 21 => { instruction.modrm_rrr.bank = RegisterBank::X; instruction.operand_count = 2; if instruction.operands[1] == OperandSpec::RegMMM { - if op == OperandCode::G_M_xmm { + if op == 20 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } else { @@ -6079,7 +6041,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, } } }, - OperandCode::G_E_xmm_Ib => { + 22 => { let modrm = read_modrm(&mut bytes_iter, length)?; instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; @@ -6091,37 +6053,13 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; }, - OperandCode::G_E_mm_Ib => { - instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::MM; - } - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - }, - OperandCode::G_mm_Ew_Ib => { - let modrm = read_modrm(&mut bytes_iter, length)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM); - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::D; - } - instruction.imm = - read_num(&mut bytes_iter, 1)? as u8 as u64; - *length += 1; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - } - OperandCode::AL_Ibs => { + 23 => { instruction.modrm_rrr = RegSpec::al(); instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; } - OperandCode::AX_Ivd => { + 24 => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); let numwidth = if opwidth == 8 { 4 } else { opwidth }; instruction.modrm_rrr = @@ -6136,7 +6074,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, }; instruction.operand_count = 2; } - OperandCode::Ivs => { + 25 => { let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); instruction.imm = read_imm_unsigned(&mut bytes_iter, opwidth, length)?; @@ -6148,12 +6086,60 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, }; instruction.operand_count = 1; }, - OperandCode::ModRM_0x83_Ev_Ibs => { + 26 => { instruction.operands[0] = mem_oper; instruction.opcode = base_opcode_map((modrm >> 3) & 7); instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; }, + 27 => { + instruction.imm = 3; + instruction.operands[0] = OperandSpec::ImmU8; + instruction.operand_count = 1; + } + 28 => { + instruction.operands[0] = OperandSpec::Nothing; + instruction.operand_count = 0; + return Ok(()); + }, + 29 => { + instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::MM; + } + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + }, + 30 => { + instruction.operands[0] = mem_oper; + let r = (modrm >> 3) & 7; + if r >= 1 { + return Err(DecodeError::InvalidOpcode); + } + instruction.opcode = [ + Opcode::POP, + ][r as usize]; + instruction.operand_count = 1; + } + _ => { + let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) }; + unlikely_operands(decoder, bytes_iter, instruction, operand_code, mem_oper, length)?; + } + }; + } + + Ok(()) +} +fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, length: &mut u8) -> Result<(), DecodeError> { + match operand_code { + OperandCode::G_U_xmm => { + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.modrm_mmm.bank = RegisterBank::X; + instruction.operand_count = 2; + }, OperandCode::Gb_Eb_Ib => { instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; @@ -6186,26 +6172,71 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction.vex_reg = RegSpec::cl(); instruction.operand_count = 3; } - OperandCode::I_3 => { - instruction.imm = 3; - instruction.operands[0] = OperandSpec::ImmU8; - instruction.operand_count = 1; + OperandCode::G_mm_Ew_Ib => { + let modrm = read_modrm(&mut bytes_iter, length)?; + +// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM); + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } + instruction.imm = + read_num(&mut bytes_iter, 1)? as u8 as u64; + *length += 1; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; } - OperandCode::Nothing => { - instruction.operands[0] = OperandSpec::Nothing; - instruction.operand_count = 0; - return Ok(()); + OperandCode::G_E_mm => { + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + } + instruction.operand_count = 2; }, - _ => { - unlikely_operands(decoder, bytes_iter, instruction, operand_code, mem_oper, length)?; - } - }; - } + OperandCode::G_U_mm => { + instruction.modrm_rrr.bank = RegisterBank::D; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + instruction.operand_count = 2; + }, + OperandCode::Gv_Ew_LSL => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let modrm = read_modrm(&mut bytes_iter, length)?; - Ok(()) -} -fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, length: &mut u8) -> Result<(), DecodeError> { - match operand_code { + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; + // lsl is weird. the full register width is written, but only the low 16 bits are used. + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } + instruction.modrm_rrr = + RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); + instruction.operand_count = 2; + }, + OperandCode::Gdq_Ev => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let modrm = read_modrm(&mut bytes_iter, length)?; + +// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + // `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. + let regwidth = if opwidth == 2 { + 4 + } else { + opwidth + }; + instruction.modrm_rrr = + RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), regwidth, instruction.prefixes.rex().present()); + instruction.operand_count = 2; + }, op @ OperandCode::AL_Ob | op @ OperandCode::AX_Ov => { let opwidth = match op { |