diff options
author | iximeow <me@iximeow.net> | 2019-01-05 15:26:46 -0800 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 |
commit | d8efc7b6fca3e1c6a9ebf0ada6759a927c12558f (patch) | |
tree | bcb09ad2413fdb2620492d31dd26c04c41a80af7 /src/lib.rs | |
parent | a2fdcc2106024e7e9b1b119c9de50242706c9424 (diff) |
add more test cases, fix movzx support, add 0xf6 opcodes
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 143 |
1 files changed, 137 insertions, 6 deletions
@@ -224,6 +224,9 @@ impl fmt::Display for Opcode { &Opcode::DIV => write!(f, "{}", "div"), &Opcode::IDIV => write!(f, "{}", "idiv"), &Opcode::CMPXCHG => write!(f, "{}", "cmpxchg"), + &Opcode::MOVZX_b => write!(f, "{}", "movzx"), + &Opcode::MOVZX_w => write!(f, "{}", "movzx"), + &Opcode::MOVSX => write!(f, "{}", "movsx"), &Opcode::Invalid => write!(f, "{}", "invalid") } } @@ -231,6 +234,9 @@ impl fmt::Display for Opcode { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Opcode { + MOVZX_b, + MOVZX_w, + MOVSX, SAR, SAL, SHR, @@ -427,12 +433,42 @@ impl fmt::Display for Instruction { write!(f, " {}", x) } }; - match &self.operands[1] { - &Operand::Nothing => { - return Ok(()); + match self.opcode { + Opcode::MOVZX_b => { + match &self.operands[1] { + &Operand::Nothing => { + return Ok(()); + }, + x @ &Operand::Register(_) => { + write!(f, ", {}", x) + } + x @ _ => { + write!(f, ", byte {}", x) + } + } }, - x @ &_ => { - write!(f, ", {}", x) + Opcode::MOVZX_w => { + match &self.operands[1] { + &Operand::Nothing => { + return Ok(()); + }, + x @ &Operand::Register(_) => { + write!(f, ", {}", x) + } + x @ _ => { + write!(f, ", word {}", x) + } + } + }, + _ => { + match &self.operands[1] { + &Operand::Nothing => { + return Ok(()); + }, + x @ &_ => { + write!(f, ", {}", x) + } + } } } } @@ -440,6 +476,7 @@ impl fmt::Display for Instruction { #[derive(Copy, Clone, Debug)] pub enum OperandCode { + ModRM_0xf6, ModRM_0xf7, Gv_Ev_Iv, Gb_Eb_Ib, @@ -478,6 +515,8 @@ pub enum OperandCode { Ew_Sw, Fw, Gb_Eb, + Gv_Eb, + Gv_Ew, Gv_Ev, Gv_M, I_3, @@ -704,6 +743,16 @@ fn read_opcode_0f_map(bytes_iter: &mut Iterator<Item=&u8>, instruction: &mut Ins instruction.opcode = Opcode::CMPXCHG; Ok(OperandCode::Ev_Gv) } + 0xb6 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOVZX_b; + Ok(OperandCode::Gv_Eb) + }, + 0xb7 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOVZX_w; + Ok(OperandCode::Gv_Ew) + } _ => { Err(format!("Unknown opcode: 0f{:x}", b)) } @@ -1192,7 +1241,11 @@ fn read_opcode(bytes_iter: &mut Iterator<Item=&u8>, instruction: &mut Instructio instruction.opcode = Opcode::HLT; return Ok(OperandCode::Nothing); }, - 0xf6 => { }, + 0xf6 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::Invalid; + return Ok(OperandCode::ModRM_0xf6); + }, 0xf7 => { instruction.prefixes = prefixes; instruction.opcode = Opcode::Invalid; @@ -1581,6 +1634,48 @@ fn read_operands( Err(reason) => Err(reason) } }, + OperandCode::ModRM_0xf6 => { + let opwidth = 1; + let modrm = bytes_iter.next().unwrap(); + let (mod_bits, r, m) = octets_of(*modrm); + match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) { + Ok(()) => { }, + Err(reason) => { return Err(reason); } + }; + match r { + 0 | 1 => { + instruction.opcode = Opcode::TEST; + match read_imm_signed(bytes_iter, 1, opwidth) { + Ok(imm) => { + instruction.operands[1] = imm; + }, + Err(reason) => { return Err(reason); } + } + }, + 2 => { + instruction.opcode = Opcode::NOT; + }, + 3 => { + instruction.opcode = Opcode::NEG; + }, + 4 => { + instruction.opcode = Opcode::MUL; + }, + 5 => { + instruction.opcode = Opcode::IMUL; + }, + 6 => { + instruction.opcode = Opcode::DIV; + }, + 7 => { + instruction.opcode = Opcode::IDIV; + }, + _ => { + unsafe { unreachable_unchecked(); } + } + } + Ok(()) + }, OperandCode::ModRM_0xf7 => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); let modrm = bytes_iter.next().unwrap(); @@ -1743,6 +1838,42 @@ fn read_operands( Err(reason) => Err(reason) } }, + OperandCode::Gv_Eb => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); + // TODO: ... + let modrm = bytes_iter.next().unwrap(); + let (mod_bits, r, m) = octets_of(*modrm); + + match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1]) { + Ok(()) => { + instruction.operands[0] = + Operand::Register(RegSpec { + num: r, + bank: width_to_gp_reg_bank(opwidth) + }); + Ok(()) + }, + Err(reason) => Err(reason) + } + }, + OperandCode::Gv_Ew => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); + // TODO: ... + let modrm = bytes_iter.next().unwrap(); + let (mod_bits, r, m) = octets_of(*modrm); + + match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[1]) { + Ok(()) => { + instruction.operands[0] = + Operand::Register(RegSpec { + num: r + if instruction.prefixes.rex().b() { 0b1000 } else { 0 }, + bank: width_to_gp_reg_bank(opwidth) + }); + Ok(()) + }, + Err(reason) => Err(reason) + } + }, // TODO: verify M OperandCode::Gv_Ev | OperandCode::Gv_M => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); |