diff options
author | iximeow <me@iximeow.net> | 2019-10-20 23:45:13 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 |
commit | af41ce106280e3a50b2ad9e695e82f96cceff063 (patch) | |
tree | 86f0042e2e01dfe585d356e3d874eba9379dde6f | |
parent | 74fa418fa25e3a9416b0f11a7e67d3157ace3a5c (diff) |
evil bit hacks to shrink read_operands down
-rw-r--r-- | src/lib.rs | 643 |
1 files changed, 275 insertions, 368 deletions
@@ -843,12 +843,38 @@ impl PrefixRex { #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, PartialEq)] pub enum OperandCode { - Eb_Gb, - Ev_Gv, - Gb_Eb, - Gb_Eb_Ib, - Gv_Ev, - Gv_Ev_Iv, + Zv_R0 = 0x00, + Zv_R1 = 0x01, + Zv_R2 = 0x02, + Zv_R3 = 0x03, + Zv_R4 = 0x04, + Zv_R5 = 0x05, + Zv_R6 = 0x06, + Zv_R7 = 0x07, + Zv_AX_R0 = 0x08, + Zv_AX_R1 = 0x09, + Zv_AX_R2 = 0x0a, + Zv_AX_R3 = 0x0b, + Zv_AX_R4 = 0x0c, + Zv_AX_R5 = 0x0d, + Zv_AX_R6 = 0x0e, + Zv_AX_R7 = 0x0f, + Zb_Ib_R0 = 0x10, + Zb_Ib_R1 = 0x11, + Zb_Ib_R2 = 0x12, + Zb_Ib_R3 = 0x13, + Zb_Ib_R4 = 0x14, + Zb_Ib_R5 = 0x15, + Zb_Ib_R6 = 0x16, + Zb_Ib_R7 = 0x17, + Zv_Ivq_R0 = 0x18, + Zv_Ivq_R1 = 0x19, + Zv_Ivq_R2 = 0x1a, + Zv_Ivq_R3 = 0x1b, + Zv_Ivq_R4 = 0x1c, + Zv_Ivq_R5 = 0x1d, + Zv_Ivq_R6 = 0x1e, + Zv_Ivq_R7 = 0x1f, AL_Ib, AX_Ivd, ModRM_0x0f00, @@ -865,9 +891,6 @@ pub enum OperandCode { Dq_Rq_0, FS, GS, - Eb_R0, - ModRM_0xf6, - ModRM_0xf7, Yb_DX, Yv_DX, DX_Xb, @@ -880,23 +903,8 @@ pub enum OperandCode { AX_Ov, AX_Xv, DX_AX, - ModRM_0xc0_Eb_Ib, - ModRM_0xd0_Eb_1, - ModRM_0xd2_Eb_CL, - ModRM_0xfe_Eb, - ModRM_0x8f_Ev, - ModRM_0xc1_Ev_Ib, - ModRM_0xd1_Ev_1, - ModRM_0xd3_Ev_CL, - ModRM_0xff_Ev, - ModRM_0x80_Eb_Ib, - ModRM_0x81_Ev_Ivs, - ModRM_0x83_Ev_Ibs, - ModRM_0xc6_Eb_Ib, - ModRM_0xc7_Ev_Iv, E_G_xmm, Ev_Ivs, - Ev, Ew_Sw, Fw, Gv_Eb, @@ -904,7 +912,6 @@ pub enum OperandCode { Gdq_Ed, G_E_xmm, G_E_xmm_Ib, - Gv_M, I_3, Ib, Ibs, @@ -920,41 +927,38 @@ pub enum OperandCode { Yb_Xb, Yv_AX, Yv_Xv, - Zb_Ib_R0 = 200, - Zb_Ib_R1 = 201, - Zb_Ib_R2 = 202, - Zb_Ib_R3 = 203, - Zb_Ib_R4 = 204, - Zb_Ib_R5 = 205, - Zb_Ib_R6 = 206, - Zb_Ib_R7 = 207, - Zv_R0 = 208, - Zv_R1 = 209, - Zv_R2 = 210, - Zv_R3 = 211, - Zv_R4 = 212, - Zv_R5 = 213, - Zv_R6 = 214, - Zv_R7 = 215, - Zv_AX_R0 = 216, - Zv_AX_R1 = 217, - Zv_AX_R2 = 218, - Zv_AX_R3 = 219, - Zv_AX_R4 = 220, - Zv_AX_R5 = 221, - Zv_AX_R6 = 222, - Zv_AX_R7 = 223, - Zv_Ivq_R0 = 224, - Zv_Ivq_R1 = 225, - Zv_Ivq_R2 = 226, - Zv_Ivq_R3 = 227, - Zv_Ivq_R4 = 228, - Zv_Ivq_R5 = 229, - Zv_Ivq_R6 = 230, - Zv_Ivq_R7 = 231, Nothing, Implied, Unsupported, + + Eb_Gb = 0x80, + Ev_Gv = 0x81, + Gb_Eb = 0x82, + Gv_Ev = 0x83, + Gb_Eb_Ib = 0x84, + Gv_Ev_Iv = 0x85, + ModRM_0xc0_Eb_Ib = 0x86, + ModRM_0xc1_Ev_Ib = 0x87, + ModRM_0xd0_Eb_1 = 0x88, + ModRM_0xd1_Ev_1 = 0x89, + ModRM_0xd2_Eb_CL = 0x8a, + ModRM_0xd3_Ev_CL = 0x8b, + ModRM_0x80_Eb_Ib = 0x8c, + ModRM_0x83_Ev_Ibs = 0x8d, + // this would be Eb_Ivs, 0x8e + ModRM_0x81_Ev_Ivs = 0x8f, + ModRM_0xc6_Eb_Ib = 0x90, + ModRM_0xc7_Ev_Iv = 0x91, + ModRM_0xfe_Eb = 0x92, + ModRM_0x8f_Ev = 0x93, + // gap, 0x94 + ModRM_0xff_Ev = 0x95, + ModRM_0xf6 = 0x96, + ModRM_0xf7 = 0x97, + Eb_R0 = 0x98, + Ev = 0x99, + // gap, 0x9a + Gv_M = 0x9b, } fn base_opcode_map(v: u8) -> Opcode { @@ -2471,23 +2475,79 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins Ok(()) } pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, prefixes: Prefixes, operand_code: OperandCode) -> Result<(), ()> { - if operand_code == OperandCode::Gv_Ev { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; + if (operand_code as u8) < 0x20 { + let reg = (operand_code as u8) & 0x07; + let category = ((operand_code as u8) & 0x18) >> 3; + if category == 0 { + // these are Zv_R + let opwidth = imm_width_from_prefixes_64(SizeCode::vq, prefixes); + instruction.modrm_rrr = + RegSpec::gp_from_parts( + reg, prefixes.rex().b(), opwidth, prefixes.rex().present() + ); + instruction.operand_count = 1; + instruction.operands[0] = OperandSpec::RegRRR; + // Zv_AX are missing! + } else if category == 2 { + // these are Zb_Ib_R + instruction.modrm_rrr = + RegSpec::gp_from_parts(reg, prefixes.rex().b(), 1, prefixes.rex().present()); + instruction.imm = + read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length)?; + instruction.operands[1] = OperandSpec::ImmU8; + instruction.operand_count = 2; + } else { + // category == 3, Zv_Ivq_R + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); + instruction.modrm_rrr = + RegSpec::gp_from_parts(reg, prefixes.rex().b(), opwidth, prefixes.rex().present()); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.imm = + read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length)?; + instruction.operands[1] = match opwidth { + 1 => OperandSpec::ImmI8, + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 2; + } + return Ok(()); + } -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + let mut modrm = 0; + let mut opwidth = 0; + let mut mem_oper = OperandSpec::Nothing; + let mut bank = RegisterBank::Q; + let code_int = operand_code as u8; + if ((code_int) & 0x80) == 0x80 { + // cool! we can precompute opwidth and know we need to read_E. + if (code_int & 1) == 1 { + // further, this is an vdq E + opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); + if opwidth == 4 { + bank = RegisterBank::D; + } else if opwidth == 2 { + bank = RegisterBank::W; + } + } else { + opwidth = 1; + bank = RegisterBank::B; + }; + modrm = read_modrm(&mut bytes_iter, instruction)?; instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()); + RegSpec::from_parts((modrm >> 3) & 7, prefixes.rex().r(), bank); + + mem_oper = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + } + + if operand_code == OperandCode::Gv_Ev { + instruction.operands[1] = mem_oper; instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 2; } else if operand_code == OperandCode::Ev_Gv { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()); + instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } else if operand_code == OperandCode::Jbs { @@ -2497,21 +2557,11 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[0] = OperandSpec::ImmI8; instruction.operand_count = 1; } else if operand_code == OperandCode::Gb_Eb { - let opwidth = 1; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()); + instruction.operands[1] = mem_oper; instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 2; } else if operand_code == OperandCode::Eb_Gb { - let opwidth = 1; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()); + instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } else { @@ -2563,15 +2613,12 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Zv_AX, */ OperandCode::Eb_R0 => { - let opwidth = 1; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - if (modrm & 0b00111000) != 0 { instruction.opcode = Opcode::Invalid; return Err(()); // Err("Invalid modr/m for opcode 0xc6".to_owned()); } - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = mem_oper; instruction.operand_count = 1; }, op @ OperandCode::AL_Ob | @@ -2628,18 +2675,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } op @ OperandCode::ModRM_0x80_Eb_Ib | op @ OperandCode::ModRM_0x81_Ev_Ivs => { - let opwidth = match op { - OperandCode::ModRM_0x80_Eb_Ib => 1, - OperandCode::ModRM_0x81_Ev_Ivs => { - imm_width_from_prefixes_64(SizeCode::vqp, prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = mem_oper; instruction.imm = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, &mut instruction.length)? as u64; instruction.opcode = base_opcode_map((modrm >> 3) & 7); instruction.operands[1] = match opwidth { @@ -2651,45 +2687,14 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut }; instruction.operand_count = 2; }, - op @ OperandCode::ModRM_0xc0_Eb_Ib | - op @ OperandCode::ModRM_0xc1_Ev_Ib => { - let opwidth = match op { - OperandCode::ModRM_0xc0_Eb_Ib => 1, - OperandCode::ModRM_0xc1_Ev_Ib => { - imm_width_from_prefixes_64(SizeCode::vqp, prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - let num = read_num(&mut bytes_iter, 1, &mut instruction.length)?; - instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); - instruction.imm = num; - instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; - }, op @ OperandCode::ModRM_0xc6_Eb_Ib | op @ OperandCode::ModRM_0xc7_Ev_Iv => { - let opwidth = match op { - OperandCode::ModRM_0xc6_Eb_Ib => 1, - OperandCode::ModRM_0xc7_Ev_Iv => { - imm_width_from_prefixes_64(SizeCode::vqp, prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - if (modrm & 0b00111000) != 0 { instruction.opcode = Opcode::Invalid; return Err(()); // Err("Invalid modr/m for opcode 0xc7".to_string()); } - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = mem_oper; instruction.opcode = Opcode::MOV; instruction.imm = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, &mut instruction.length)? as u64; instruction.operands[1] = match opwidth { @@ -2701,50 +2706,35 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut }; 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 => { - let opwidth = match op { - OperandCode::ModRM_0xd0_Eb_1 => 1, - OperandCode::ModRM_0xd1_Ev_1 => { - imm_width_from_prefixes_64(SizeCode::vqp, prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + op @ OperandCode::ModRM_0xd1_Ev_1 | + op @ OperandCode::ModRM_0xd3_Ev_CL => { + instruction.operands[0] = mem_oper; instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); - instruction.imm = 1; - instruction.operands[1] = OperandSpec::ImmI8; + if let OperandCode::ModRM_0xd3_Ev_CL = op { + 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 => { + read_num(&mut bytes_iter, 1, &mut instruction.length)? + } + _ => { + // these are the _1 variants, everything else is unreachable + 1 + } + }; + instruction.imm = num; + instruction.operands[1] = OperandSpec::ImmI8; + } instruction.operand_count = 2; }, - OperandCode::ModRM_0xd3_Ev_CL => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; - let (mod_bits, r, m) = octets_of(modrm); - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - let opcode = BITWISE_OPCODE_MAP[r as usize].clone(); - instruction.opcode = opcode; - instruction.modrm_rrr = RegSpec::cl(); - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; - } op @ OperandCode::ModRM_0xf6 | op @ OperandCode::ModRM_0xf7 => { - let opwidth = match op { - OperandCode::ModRM_0xf6 => 1, - OperandCode::ModRM_0xf7 => { - imm_width_from_prefixes_64(SizeCode::vqp, prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = mem_oper; instruction.operand_count = 1; match ((modrm >> 3) & 7) { 0 | 1 => { @@ -2784,10 +2774,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } }, OperandCode::ModRM_0xfe_Eb => { - let opwidth = 1; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = mem_oper; instruction.opcode = [ Opcode::INC, Opcode::DEC, @@ -2801,10 +2788,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operand_count = 1; } OperandCode::ModRM_0xff_Ev => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = mem_oper; let opcode = [ Opcode::INC, Opcode::DEC, @@ -2818,39 +2802,11 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.opcode = opcode; instruction.operand_count = 1; } - OperandCode::Ev => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - instruction.operand_count = 1; - }, - OperandCode::Gb_Eb_Ib => { - let opwidth = 1; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - let (mod_bits, r, m) = octets_of(modrm); - - let mut ext = vec![Operand::Nothing; 2]; - - // TODO - panic!("oh no, a mul!"); -// read_E(&mut bytes_iter, instruction, modrm, opwidth, &mut ext[0])?; - /* - instruction.operands[0] = - RegSpec::gp_from_parts(r, prefixes.rex().r(), opwidth, prefixes.rex().present()); - read_imm_signed(&mut bytes_iter, 1, 1, &mut instruction.length).map(|imm| { - ext[1] = imm; - instruction.operands[1] = Operand::Many(ext); - })? - - instruction.operand_count = 3; - */ - } OperandCode::Gv_Eb => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); let modrm = read_modrm(&mut bytes_iter, instruction)?; - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 1)?; instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()); instruction.operands[0] = OperandSpec::RegRRR; @@ -2866,52 +2822,6 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 2; }, - OperandCode::Ew_Sw => { - let opwidth = 2; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - // check r - if ((modrm >> 3) & 7) > 5 { - return Err(()); //Err("Invalid r".to_owned()); - } - - instruction.modrm_rrr = - RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; - - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.modrm_mmm = - RegSpec { bank: RegisterBank::W, num: modrm & 7}; - instruction.operands[0] = OperandSpec::RegMMM; - } else { - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; - } - }, - OperandCode::Sw_Ew => { - let opwidth = 2; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - - // check r - if ((modrm >> 3) & 7) > 5 { - return Err(()); // Err("Invalid r".to_owned()); - } - - instruction.modrm_rrr = - RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operand_count = 2; - - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.modrm_mmm = - RegSpec { bank: RegisterBank::W, num: modrm & 7}; - instruction.operands[1] = OperandSpec::RegMMM; - } else { - instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm)?; - } - }, OperandCode::Gdq_Ed => { let opwidth = 8; let modrm = read_modrm(&mut bytes_iter, instruction)?; @@ -2923,36 +2833,17 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 2; }, + OperandCode::Ev => { + instruction.operands[0] = mem_oper; + instruction.operand_count = 1; + }, OperandCode::Gv_M => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[1] = mem_oper; instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 2; }, - OperandCode::Gv_Ev_Iv => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; - let (mod_bits, r, m) = octets_of(modrm); - - let mut ext = vec![Operand::Nothing; 2]; - - // TODO - panic!("oh no, a mul!"); -// read_E(&mut bytes_iter, instruction, modrm, opwidth, &mut ext[0])?; - /* - instruction.operands[0] = - RegSpec::gp_from_parts(r, prefixes.rex().r(), opwidth, prefixes.rex().present()); - read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length).map(|imm| { - ext[1] = imm; - instruction.operands[1] = Operand::Many(ext); - })? - */ - } OperandCode::E_G_xmm => { let modrm = read_modrm(&mut bytes_iter, instruction)?; @@ -2973,30 +2864,6 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 2; }, - op @ OperandCode::Zv_Ivq_R0 | - op @ OperandCode::Zv_Ivq_R1 | - op @ OperandCode::Zv_Ivq_R2 | - op @ OperandCode::Zv_Ivq_R3 | - op @ OperandCode::Zv_Ivq_R4 | - op @ OperandCode::Zv_Ivq_R5 | - op @ OperandCode::Zv_Ivq_R6 | - op @ OperandCode::Zv_Ivq_R7 => { - let reg = (op as u8) - (OperandCode::Zv_Ivq_R0 as u8); - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes); - instruction.modrm_rrr = - RegSpec::gp_from_parts(reg, prefixes.rex().b(), opwidth, prefixes.rex().present()); - instruction.operands[0] = OperandSpec::RegRRR; - instruction.imm = - read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length)?; - instruction.operands[1] = match opwidth { - 1 => OperandSpec::ImmI8, - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - }, OperandCode::AL_Ib => { instruction.modrm_rrr = RegSpec::al(); @@ -3023,28 +2890,6 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut }; instruction.operand_count = 2; } - op @ OperandCode::Zb_Ib_R0 | - op @ OperandCode::Zb_Ib_R1 | - op @ OperandCode::Zb_Ib_R2 | - op @ OperandCode::Zb_Ib_R3 | - op @ OperandCode::Zb_Ib_R4 | - op @ OperandCode::Zb_Ib_R5 | - op @ OperandCode::Zb_Ib_R6 | - op @ OperandCode::Zb_Ib_R7 => { - let reg = (op as u8) - (OperandCode::Zb_Ib_R0 as u8); - instruction.modrm_rrr = - RegSpec::gp_from_parts(reg, prefixes.rex().b(), 1, prefixes.rex().present()); - instruction.imm = - read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length)?; - instruction.operands[1] = OperandSpec::ImmU8; - instruction.operand_count = 2; - }, - OperandCode::Iw => { - instruction.imm = - read_imm_unsigned(&mut bytes_iter, 2, &mut instruction.length)?; - instruction.operands[0] = OperandSpec::ImmU16; - instruction.operand_count = 1; - } OperandCode::Ibs => { instruction.imm = read_imm_signed(&mut bytes_iter, 1, &mut instruction.length)? as u64; @@ -3080,29 +2925,109 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut }; instruction.operand_count = 2; }, - op @ OperandCode::Zv_R0 | - op @ OperandCode::Zv_R1 | - op @ OperandCode::Zv_R2 | - op @ OperandCode::Zv_R3 | - op @ OperandCode::Zv_R4 | - op @ OperandCode::Zv_R5 | - op @ OperandCode::Zv_R6 | - op @ OperandCode::Zv_R7 => { - let reg = (op as u8) - (OperandCode::Zv_R0 as u8); - let opwidth = imm_width_from_prefixes_64(SizeCode::vq, prefixes); - instruction.modrm_rrr = - RegSpec::gp_from_parts( - reg, prefixes.rex().b(), opwidth, prefixes.rex().present() - ); - instruction.operand_count = 1; - instruction.operands[0] = OperandSpec::RegRRR; - }, OperandCode::Jvds => { let offset = read_num(&mut bytes_iter, 4, &mut instruction.length)?; instruction.imm = offset; instruction.operand_count = 1; instruction.operands[0] = OperandSpec::ImmI32; } + OperandCode::Nothing => { + instruction.operand_count = 0; + } + _ => { + unlikely_operands(bytes_iter, instruction, prefixes, operand_code)?; + } + }; + } + + Ok(()) +} +fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, prefixes: Prefixes, operand_code: OperandCode) -> Result<(), ()> { + match operand_code { + OperandCode::Gb_Eb_Ib => { + let mut ext = vec![Operand::Nothing; 2]; + + // TODO + panic!("oh no, a mul!"); +// read_E(&mut bytes_iter, instruction, modrm, opwidth, &mut ext[0])?; + /* + instruction.operands[0] = + RegSpec::gp_from_parts(r, prefixes.rex().r(), opwidth, prefixes.rex().present()); + read_imm_signed(&mut bytes_iter, 1, 1, &mut instruction.length).map(|imm| { + ext[1] = imm; + instruction.operands[1] = Operand::Many(ext); + })? + + instruction.operand_count = 3; + */ + } + OperandCode::Ew_Sw => { + let opwidth = 2; + let modrm = read_modrm(&mut bytes_iter, instruction)?; + + // check r + if ((modrm >> 3) & 7) > 5 { + return Err(()); //Err("Invalid r".to_owned()); + } + + instruction.modrm_rrr = + RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + let mod_bits = modrm >> 6; + if mod_bits == 0b11 { + instruction.modrm_mmm = + RegSpec { bank: RegisterBank::W, num: modrm & 7}; + instruction.operands[0] = OperandSpec::RegMMM; + } else { + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + } + }, + OperandCode::Sw_Ew => { + let opwidth = 2; + let modrm = read_modrm(&mut bytes_iter, instruction)?; + + // check r + if ((modrm >> 3) & 7) > 5 { + return Err(()); // Err("Invalid r".to_owned()); + } + + instruction.modrm_rrr = + RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + let mod_bits = modrm >> 6; + if mod_bits == 0b11 { + instruction.modrm_mmm = + RegSpec { bank: RegisterBank::W, num: modrm & 7}; + instruction.operands[1] = OperandSpec::RegMMM; + } else { + instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm)?; + } + }, + OperandCode::Gv_Ev_Iv => { + let mut ext = vec![Operand::Nothing; 2]; + + // TODO + panic!("oh no, a mul!"); +// read_E(&mut bytes_iter, instruction, modrm, opwidth, &mut ext[0])?; + /* + instruction.operands[0] = + RegSpec::gp_from_parts(r, prefixes.rex().r(), opwidth, prefixes.rex().present()); + read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length).map(|imm| { + ext[1] = imm; + instruction.operands[1] = Operand::Many(ext); + })? + */ + } + OperandCode::Iw => { + instruction.imm = + read_imm_unsigned(&mut bytes_iter, 2, &mut instruction.length)?; + instruction.operands[0] = OperandSpec::ImmU16; + instruction.operand_count = 1; + } OperandCode::ModRM_0x0f00 => { instruction.operand_count = 1; let modrm = read_modrm(&mut bytes_iter, instruction)?; @@ -3291,38 +3216,25 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; } - op @ OperandCode::Rq_Cq_0 | - op @ OperandCode::Rq_Dq_0 => { - let bank = match op { - OperandCode::Rq_Cq_0 => RegisterBank::CR, - OperandCode::Rq_Dq_0 => RegisterBank::DR, - _ => unsafe { unreachable_unchecked() } - }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; - let mut m = modrm & 7; - let mut r = (modrm >> 3) & 7; - if prefixes.rex().r() { - r += 0b1000; - } - if prefixes.rex().b() { - m += 0b1000; - } - instruction.modrm_rrr = - RegSpec { bank: RegisterBank::Q, num: m }; - instruction.modrm_mmm = - RegSpec { bank: bank, num: r }; - instruction.operands[1] = OperandSpec::RegMMM; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operand_count = 2; - } + op @ OperandCode::Rq_Dq_0 | op @ OperandCode::Cq_Rq_0 | op @ OperandCode::Dq_Rq_0 => { let bank = match op { + OperandCode::Rq_Cq_0 | OperandCode::Cq_Rq_0 => RegisterBank::CR, + OperandCode::Rq_Dq_0 | OperandCode::Dq_Rq_0 => RegisterBank::DR, _ => unsafe { unreachable_unchecked() } }; + let (rrr, mmm) = match op { + OperandCode::Rq_Cq_0 | + OperandCode::Rq_Dq_0 => (1, 0), + OperandCode::Cq_Rq_0 | + OperandCode::Dq_Rq_0 => (0, 1), + _ => unsafe { unreachable_unchecked() } + }; + let modrm = read_modrm(&mut bytes_iter, instruction)?; let mut m = modrm & 7; let mut r = (modrm >> 3) & 7; @@ -3336,8 +3248,8 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut RegSpec { bank: bank, num: r }; instruction.modrm_mmm = RegSpec { bank: RegisterBank::Q, num: m }; - instruction.operands[1] = OperandSpec::RegMMM; - instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[mmm] = OperandSpec::RegMMM; + instruction.operands[rrr] = OperandSpec::RegRRR; instruction.operand_count = 2; } OperandCode::FS => { @@ -3355,9 +3267,6 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[0] = OperandSpec::ImmU8; instruction.operand_count = 1; } - OperandCode::Nothing => { - instruction.operand_count = 0; - } _ => { instruction.operand_count = 0; instruction.opcode = Opcode::Invalid; @@ -3365,8 +3274,6 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut // unsafe { unreachable_unchecked(); } } }; - } - Ok(()) } |