aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode/mod.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-07-26 12:28:49 -0700
committeriximeow <me@iximeow.net>2020-07-26 12:28:49 -0700
commit798785fddfca1eab5ad6bb47812de727b650f679 (patch)
treee83f39a9fd62e6a0f0d2b766e09ae76c593f6399 /src/long_mode/mod.rs
parent259237ceda8a1900231a7f006701bc5c9bc7f0ba (diff)
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)
Diffstat (limited to 'src/long_mode/mod.rs')
-rw-r--r--src/long_mode/mod.rs72
1 files 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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<Item=u8>>(decoder: &InstDecoder, bytes: T, ins
#[inline]
fn read_num<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<u64, DecodeError> {
- 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;
}
}