From 5c86aaf06d0f638d3fc1d302ef4d401b0222bee1 Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 29 Nov 2019 16:50:18 -0800 Subject: support imul, >2 operands, and 4-bit register bank --- src/display.rs | 113 +++++++++++++++++++++++++++++---------------------------- src/lib.rs | 33 +++++++++++++++-- test/test.rs | 4 ++ 3 files changed, 91 insertions(+), 59 deletions(-) diff --git a/src/display.rs b/src/display.rs index 0694265..1c5792e 100644 --- a/src/display.rs +++ b/src/display.rs @@ -706,75 +706,78 @@ impl ShowContextual], T> for Instructi x.colorize(colors, out)?; } }; - match self.opcode { - Opcode::MOVSX_b | - Opcode::MOVZX_b => { - match context.and_then(|xs| xs[1].as_ref()) { - Some(s) => { write!(out, ", {}", s) } - None => { - match &self.operands[1] { - &OperandSpec::Nothing => { - unreachable!(); - }, - &OperandSpec::RegMMM => { - write!(out, ", ")?; - } - x @ _ => { - write!(out, ", byte ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; + for i in 1..4 { + match self.opcode { + Opcode::MOVSX_b | + Opcode::MOVZX_b => { + match context.and_then(|xs| xs[i].as_ref()) { + Some(s) => { write!(out, ", {}", s)? } + None => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + &OperandSpec::RegMMM => { + write!(out, ", ")?; + } + x @ _ => { + write!(out, ", byte ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } } } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? } - let x = Operand::from_spec(self, self.operands[1]); - x.colorize(colors, out) } - } - }, - Opcode::MOVSX_w | - Opcode::MOVZX_w => { - match context.and_then(|xs| xs[1].as_ref()) { - Some(s) => { write!(out, ", {}", s) } - None => { - match &self.operands[1] { - &OperandSpec::Nothing => { - unreachable!(); - }, - &OperandSpec::RegMMM => { - write!(out, ", ")?; - } - _ => { - write!(out, ", word ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; + }, + Opcode::MOVSX_w | + Opcode::MOVZX_w => { + match context.and_then(|xs| xs[i].as_ref()) { + Some(s) => { write!(out, ", {}", s)? } + None => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + &OperandSpec::RegMMM => { + write!(out, ", ")?; + } + _ => { + write!(out, ", word ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } } } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? } - let x = Operand::from_spec(self, self.operands[1]); - x.colorize(colors, out) } - } - }, - _ => { - match context.and_then(|xs| xs[1].as_ref()) { - Some(s) => { write!(out, ", {}", s) } - None => { - match &self.operands[1] { - &OperandSpec::Nothing => { - return Ok(()); - }, - _ => { - write!(out, ", ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; + }, + _ => { + match context.and_then(|xs| xs[i].as_ref()) { + Some(s) => { write!(out, ", {}", s)? } + None => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + _ => { + write!(out, ", ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? } - let x = Operand::from_spec(self, self.operands[1]); - x.colorize(colors, out) } } } } } } + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 705966c..d507f3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1522,7 +1522,6 @@ fn read_opcode_f20f_map>(bytes_iter: &mut T, length: &mut u Some(record) } None => { - unsafe { unreachable_unchecked(); } None } } @@ -1810,7 +1809,6 @@ fn read_opcode_f30f_map>(bytes_iter: &mut T, length: &mut u Some(record) } None => { - unsafe { unreachable_unchecked(); } None } } @@ -2139,7 +2137,6 @@ fn read_opcode_0f_map>(bytes_iter: &mut T, length: &mut u8) Some(record) } None => { - unsafe { unreachable_unchecked(); } None } } @@ -2806,7 +2803,11 @@ pub fn read_operands>(mut bytes_iter: T, instruction: &mut } } else { opwidth = 1; - bank = RegisterBank::B; + if instruction.prefixes.rex().present() { + bank = RegisterBank::rB; + } else { + bank = RegisterBank::B; + } }; modrm = read_modrm(&mut bytes_iter, instruction, length)?; instruction.modrm_rrr = @@ -3017,6 +3018,7 @@ pub fn read_operands>(mut bytes_iter: T, instruction: &mut instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; bytes_read = numwidth; instruction.operands[1] = match opwidth { + 1 => OperandSpec::ImmI8, 2 => OperandSpec::ImmI16, 4 => OperandSpec::ImmI32, 8 => OperandSpec::ImmI64, @@ -3192,6 +3194,29 @@ pub fn read_operands>(mut bytes_iter: T, instruction: &mut instruction.operand_count = 1; instruction.operands[0] = OperandSpec::ImmI32; } + OperandCode::Gb_Eb_Ib => { + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = + read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCode::Gv_Ev_Iv => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let numwidth = if opwidth == 8 { 4 } else { opwidth }; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = + read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; + instruction.operands[2] = match opwidth { + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 3; + } OperandCode::Nothing => { instruction.operand_count = 0; } diff --git a/test/test.rs b/test/test.rs index 3182503..b88e470 100644 --- a/test/test.rs +++ b/test/test.rs @@ -88,6 +88,9 @@ fn test_system() { fn test_arithmetic() { test_display(&[0x81, 0xec, 0x10, 0x03, 0x00, 0x00], "sub esp, 0x310"); test_display(&[0x0f, 0xaf, 0xc2], "imul eax, edx"); + test_display(&[0x4b, 0x69, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65], "imul rax, [r11 + 0x6f], 0x656c706d"); + test_display(&[0x4b, 0x6b, 0x43, 0x6f, 0x6d], "imul al, [r11 + 0x6f], 0x6d"); + test_display(&[0x4f, 0x4e, 0x00, 0xcc], "add spl, r9b"); } #[test] @@ -188,6 +191,7 @@ fn test_control_flow() { #[test] fn test_test_cmp() { + test_display(&[0xf6, 0x05, 0x2c, 0x9b, 0xff, 0xff, 0x01], "test [rip - 0x64d4], 0x1"); test_display(&[0x48, 0x3d, 0x01, 0xf0, 0xff, 0xff], "cmp rax, -0xfff"); test_display(&[0x3d, 0x01, 0xf0, 0xff, 0xff], "cmp eax, -0xfff"); test_display(&[0x48, 0x83, 0xf8, 0xff], "cmp rax, -0x1"); -- cgit v1.1