From 798785fddfca1eab5ad6bb47812de727b650f679 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 26 Jul 2020 12:28:49 -0700 Subject: make read_num more amenable to inlining deduplicate and move displacement reading make Invalid discriminant 0 to simplify "is invalid" checks (test reg, reg instead of cmp reg, imm) pad out Prefixes to 32-bits (theory being that prefix copying is now one mov instead of two) --- src/long_mode/mod.rs | 72 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index f5d8ecf..3b2ba5f 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -566,6 +566,7 @@ const XSAVE: [Opcode; 10] = [ #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Opcode { + Invalid = 0, ADD = 1, OR = 2, ADC = 3, @@ -574,7 +575,6 @@ pub enum Opcode { XOR = 6, SUB = 7, CMP = 8, - Invalid, XADD, BT, BTS, @@ -3047,6 +3047,7 @@ pub struct Prefixes { bits: u8, rex: PrefixRex, segment: Segment, + _pad: u8, } #[derive(Debug, Copy, Clone)] @@ -3080,6 +3081,7 @@ impl Prefixes { bits: bits, rex: PrefixRex { bits: 0 }, segment: Segment::DS, + _pad: 0, } } #[inline] @@ -4893,18 +4895,23 @@ fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, m let sibbyte = bytes_iter.next().ok_or(DecodeError::ExhaustedInput)?; *length += 1; - let op_spec = if (sibbyte & 7) == 0b101 { - let disp = if modbits == 0b00 { + let disp = if modbits == 0b00 { + if (sibbyte & 7) == 0b101 { *length += 4; read_num(bytes_iter, 4)? as i32 - } else if modbits == 0b01 { - *length += 1; - read_num(bytes_iter, 1)? as i8 as i32 } else { - *length += 4; - read_num(bytes_iter, 4)? as i32 - }; + 0 + } + } else if modbits == 0b01 { + *length += 1; + read_num(bytes_iter, 1)? as i8 as i32 + } else { + *length += 4; + read_num(bytes_iter, 4)? as i32 + }; + instr.disp = disp as u32 as u64; + let op_spec = if (sibbyte & 7) == 0b101 { if ((sibbyte >> 3) & 7) == 0b100 { if modbits == 0b00 && !instr.prefixes.rex().x() { instr.disp = disp as u32 as u64; @@ -4960,16 +4967,6 @@ fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, m } else { instr.modrm_mmm = RegSpec::from_parts(sibbyte & 7, instr.prefixes.rex().b(), addr_width); - let disp = if modbits == 0b00 { - 0 - } else if modbits == 0b01 { - *length += 1; - read_num(bytes_iter, 1)? as i8 as i32 - } else { - *length += 4; - read_num(bytes_iter, 4)? as i32 - }; - if ((sibbyte >> 3) & 7) == 0b100 { if instr.prefixes.rex().x() { let reg = RegSpec::from_parts(0b100, true, addr_width); @@ -7352,15 +7349,36 @@ fn decode_one<'b, T: IntoIterator>(decoder: &InstDecoder, bytes: T, ins #[inline] fn read_num>(bytes: &mut T, width: u8) -> Result { - let mut result = 0u64; - let mut idx = 0; - loop { - if idx == width { - return Ok(result); + match width { + 1 => { bytes.next().map(|x| x as u64).ok_or(DecodeError::ExhaustedInput) } + 2 => { + bytes.next().and_then(|b0| { + bytes.next().map(|b1| u16::from_le_bytes([b0, b1]) as u64) + }).ok_or(DecodeError::ExhaustedInput) + } + 4 => { + bytes.next() + .and_then(|b0| bytes.next().map(|b1| (b0, b1))) + .and_then(|(b0, b1)| bytes.next().map(|b2| (b0, b1, b2))) + .and_then(|(b0, b1, b2)| bytes.next().map(|b3| u32::from_le_bytes([b0, b1, b2, b3]) as u64)) + .ok_or(DecodeError::ExhaustedInput) + } + 8 => { + bytes.next() + .and_then(|b0| bytes.next().map(|b1| (b0, b1))) + .and_then(|(b0, b1)| bytes.next().map(|b2| (b0, b1, b2))) + .and_then(|(b0, b1, b2)| bytes.next().map(|b3| (b0, b1, b2, b3))) + .and_then(|(b0, b1, b2, b3)| bytes.next().map(|b4| (b0, b1, b2, b3, b4))) + .and_then(|(b0, b1, b2, b3, b4)| bytes.next().map(|b5| (b0, b1, b2, b3, b4, b5))) + .and_then(|(b0, b1, b2, b3, b4, b5)| bytes.next().map(|b6| (b0, b1, b2, b3, b4, b5, b6))) + .and_then(|(b0, b1, b2, b3, b4, b5, b6)| { + bytes.next().map(|b7| u64::from_le_bytes([b0, b1, b2, b3, b4, b5, b6, b7]) as u64) + }) + .ok_or(DecodeError::ExhaustedInput) + } + _ => { + panic!("unsupported read size"); } - let byte = bytes.next().ok_or(DecodeError::ExhaustedInput)?; - result |= (byte as u64) << (idx * 8); - idx += 1; } } -- cgit v1.1