aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-10-20 15:23:20 -0700
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commite5d46b89d95a0e1c1c3a7e112a9b36bb82163b2d (patch)
tree1487c25cfd9b0f7a2ee5268a81c51f8136c00b9d
parent779a7b827ff4493ff6c7cf8fdd60b88f3592a786 (diff)
make Instruction smaller
this breaks all of how Operand are used, but its faster, so its impossible to say,
-rw-r--r--src/display.rs42
-rw-r--r--src/lib.rs708
2 files changed, 475 insertions, 275 deletions
diff --git a/src/display.rs b/src/display.rs
index fc3f1bd..e70734d 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -6,7 +6,7 @@ use std::fmt;
use yaxpeax_arch::{Colorize, ColorSettings, ShowContextual, YaxColors};
use yaxpeax_arch::display::*;
-use ::{RegSpec, RegisterBank, Opcode, Operand, Instruction, Segment, PrefixRex};
+use ::{RegSpec, RegisterBank, Opcode, Operand, Instruction, Segment, PrefixRex, OperandSpec};
impl fmt::Display for PrefixRex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -690,17 +690,18 @@ impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instructi
Some(s) => { write!(out, " {}", s)?; },
None => {
match self.operands[0] {
- Operand::Nothing => {
+ OperandSpec::Nothing => {
return Ok(());
},
- ref x @ _ => {
+ _ => {
write!(out, " ")?;
if let Some(prefix) = self.segment_override_for_op(0) {
write!(out, "{}:", prefix)?;
}
- x.colorize(colors, out)?;
}
}
+ let x = Operand::from_spec(self, self.operands[0]);
+ x.colorize(colors, out)?;
}
};
match self.opcode {
@@ -710,24 +711,21 @@ impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instructi
Some(s) => { write!(out, ", {}", s) }
None => {
match &self.operands[1] {
- &Operand::Nothing => {
- return Ok(());
+ &OperandSpec::Nothing => {
+ unreachable!();
},
- x @ &Operand::Register(_) => {
+ &OperandSpec::RegMMM => {
write!(out, ", ")?;
- if let Some(prefix) = self.segment_override_for_op(1) {
- write!(out, "{}:", prefix)?;
- }
- x.colorize(colors, out)
}
x @ _ => {
write!(out, ", byte ")?;
if let Some(prefix) = self.segment_override_for_op(1) {
write!(out, "{}:", prefix)?;
}
- x.colorize(colors, out)
}
}
+ let x = Operand::from_spec(self, self.operands[1]);
+ x.colorize(colors, out)
}
}
},
@@ -737,24 +735,21 @@ impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instructi
Some(s) => { write!(out, ", {}", s) }
None => {
match &self.operands[1] {
- &Operand::Nothing => {
- return Ok(());
+ &OperandSpec::Nothing => {
+ unreachable!();
},
- x @ &Operand::Register(_) => {
+ &OperandSpec::RegMMM => {
write!(out, ", ")?;
- if let Some(prefix) = self.segment_override_for_op(1) {
- write!(out, "{}:", prefix)?;
- }
- x.colorize(colors, out)
}
- x @ _ => {
+ _ => {
write!(out, ", word ")?;
if let Some(prefix) = self.segment_override_for_op(1) {
write!(out, "{}:", prefix)?;
}
- x.colorize(colors, out)
}
}
+ let x = Operand::from_spec(self, self.operands[1]);
+ x.colorize(colors, out)
}
}
},
@@ -763,14 +758,15 @@ impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instructi
Some(s) => { write!(out, ", {}", s) }
None => {
match &self.operands[1] {
- &Operand::Nothing => {
+ &OperandSpec::Nothing => {
return Ok(());
},
- x @ _ => {
+ _ => {
write!(out, ", ")?;
if let Some(prefix) = self.segment_override_for_op(1) {
write!(out, "{}:", prefix)?;
}
+ let x = Operand::from_spec(self, self.operands[1]);
x.colorize(colors, out)
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 3ea29b6..fa22629 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -202,7 +202,114 @@ pub enum Operand {
Nothing,
}
+impl OperandSpec {
+ pub fn is_memory(&self) -> bool {
+ match self {
+ OperandSpec::Disp |
+ OperandSpec::Deref |
+ OperandSpec::RegDisp |
+ OperandSpec::RegScale |
+ OperandSpec::RegIndexBase |
+ OperandSpec::RegIndexBaseDisp |
+ OperandSpec::RegScaleDisp |
+ OperandSpec::RegIndexBaseScale |
+ OperandSpec::RegIndexBaseScaleDisp => {
+ true
+ },
+ OperandSpec::Imm |
+ OperandSpec::RegRRR |
+ OperandSpec::RegMMM |
+ OperandSpec::Nothing => {
+ false
+ }
+ }
+ }
+}
impl Operand {
+ fn from_spec(inst: &Instruction, spec: OperandSpec) -> Operand {
+ match spec {
+ OperandSpec::Nothing => {
+ Operand::Nothing
+ }
+ // the register in modrm_rrr
+ OperandSpec::RegRRR => {
+ Operand::Register(inst.modrm_rrr)
+ }
+ // the register in modrm_mmm (eg modrm mod bits were 11)
+ OperandSpec::RegMMM => {
+ Operand::Register(inst.modrm_mmm)
+ }
+ OperandSpec::Imm => {
+ match inst.imm {
+ ImmediateKind::ImmediateI8(i) => Operand::ImmediateI8(i),
+ ImmediateKind::ImmediateU8(i) => Operand::ImmediateU8(i),
+ ImmediateKind::ImmediateI16(i) => Operand::ImmediateI16(i),
+ ImmediateKind::ImmediateU16(i) => Operand::ImmediateU16(i),
+ ImmediateKind::ImmediateI32(i) => Operand::ImmediateI32(i),
+ ImmediateKind::ImmediateU32(i) => Operand::ImmediateU32(i),
+ ImmediateKind::ImmediateI64(i) => Operand::ImmediateI64(i),
+ ImmediateKind::ImmediateU64(i) => Operand::ImmediateU64(i),
+ }
+ }
+ OperandSpec::Disp => {
+ match inst.disp {
+ DisplacementKind::DisplacementU32(d) => Operand::DisplacementU32(d),
+ DisplacementKind::DisplacementI32(_) => {
+ panic!("invalid state, signed displacement isn't available except for complex memory modes");
+ }
+ DisplacementKind::DisplacementU64(d) => Operand::DisplacementU64(d),
+ }
+ }
+ OperandSpec::Deref => {
+ Operand::RegDeref(inst.modrm_mmm)
+ }
+ OperandSpec::RegDisp => {
+ let disp = match inst.disp {
+ DisplacementKind::DisplacementI32(d) => d,
+ _ => {
+ unreachable!("unsigned displacement isn't available in complex memory modes");
+ }
+ };
+ Operand::RegDisp(inst.modrm_mmm, disp)
+ }
+ OperandSpec::RegScale => {
+ Operand::RegScale(inst.sib_index, inst.scale)
+ }
+ OperandSpec::RegIndexBase => {
+ Operand::RegIndexBase(inst.sib_index, inst.modrm_mmm)
+ }
+ OperandSpec::RegIndexBaseDisp => {
+ let disp = match inst.disp {
+ DisplacementKind::DisplacementI32(d) => d,
+ _ => {
+ unreachable!("unsigned displacement isn't available in complex memory modes");
+ }
+ };
+ Operand::RegIndexBaseDisp(inst.sib_index, inst.modrm_mmm, disp)
+ }
+ OperandSpec::RegScaleDisp => {
+ let disp = match inst.disp {
+ DisplacementKind::DisplacementI32(d) => d,
+ _ => {
+ unreachable!("unsigned displacement isn't available in complex memory modes");
+ }
+ };
+ Operand::RegScaleDisp(inst.sib_index, inst.scale, disp)
+ }
+ OperandSpec::RegIndexBaseScale => {
+ Operand::RegIndexBaseScale(inst.sib_index, inst.modrm_mmm, inst.scale)
+ }
+ OperandSpec::RegIndexBaseScaleDisp => {
+ let disp = match inst.disp {
+ DisplacementKind::DisplacementI32(d) => d,
+ _ => {
+ unreachable!("unsigned displacement isn't available in complex memory modes");
+ }
+ };
+ Operand::RegIndexBaseScaleDisp(inst.sib_index, inst.modrm_mmm, inst.scale, disp)
+ }
+ }
+ }
pub fn is_memory(&self) -> bool {
match self {
Operand::DisplacementU32(_) |
@@ -244,9 +351,10 @@ impl Operand {
#[test]
fn operand_size() {
+ assert_eq!(std::mem::size_of::<OperandSpec>(), 1);
assert_eq!(std::mem::size_of::<RegSpec>(), 2);
assert_eq!(std::mem::size_of::<Prefixes>(), 4);
- assert_eq!(std::mem::size_of::<Operand>(), 3);
+ // assert_eq!(std::mem::size_of::<Instruction>(), 3);
}
#[allow(non_camel_case_types)]
@@ -495,11 +603,56 @@ pub enum Opcode {
#[derive(Debug)]
pub struct Instruction {
pub prefixes: Prefixes,
+ modrm_rrr: RegSpec,
+ modrm_mmm: RegSpec, // doubles as sib_base
+ sib_index: RegSpec,
+ scale: u8,
+ disp: DisplacementKind,
+ imm: ImmediateKind,
+ operand_count: u8,
+ operands: [OperandSpec; 4],
pub opcode: Opcode,
- pub operands: [Operand; 2],
pub length: u8
}
+#[derive(Debug, Copy, Clone)]
+enum DisplacementKind {
+ DisplacementU32(u32),
+ DisplacementI32(i32),
+ DisplacementU64(u64),
+}
+
+#[derive(Debug, Copy, Clone)]
+enum ImmediateKind {
+ ImmediateI8(i8),
+ ImmediateU8(u8),
+ ImmediateI16(i16),
+ ImmediateU16(u16),
+ ImmediateI32(i32),
+ ImmediateU32(u32),
+ ImmediateI64(i64),
+ ImmediateU64(u64),
+}
+
+#[derive(Debug, Copy, Clone)]
+enum OperandSpec {
+ Nothing,
+ // the register in modrm_rrr
+ RegRRR,
+ // the register in modrm_mmm (eg modrm mod bits were 11)
+ RegMMM,
+ Imm,
+ Disp,
+ Deref,
+ RegDisp,
+ RegScale,
+ RegIndexBase,
+ RegIndexBaseDisp,
+ RegScaleDisp,
+ RegIndexBaseScale,
+ RegIndexBaseScaleDisp
+}
+
// the Hash, Eq, and PartialEq impls here are possibly misleading.
// They exist because downstream some structs are spelled like
// Foo<T> for T == x86_64. This is only to access associated types
@@ -549,7 +702,14 @@ impl Instruction {
Instruction {
prefixes: Prefixes::new(0),
opcode: Opcode::Invalid,
- operands: [Operand::Nothing, Operand::Nothing],
+ modrm_rrr: RegSpec::rax(),
+ modrm_mmm: RegSpec::rax(), // doubles as sib_base
+ sib_index: RegSpec::rax(),
+ scale: 0,
+ disp: DisplacementKind::DisplacementU32(0),
+ imm: ImmediateKind::ImmediateI8(0),
+ operand_count: 0,
+ operands: [OperandSpec::Nothing; 4],
length: 0
}
}
@@ -2109,7 +2269,8 @@ fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction,
#[allow(non_snake_case)]
fn read_modrm_reg<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, result: usize, reg_bank: RegisterBank) -> Result<(), ()> {
- instr.operands[result] = Operand::Register(RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank));
+ instr.modrm_mmm = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank);
+ instr.operands[result] = OperandSpec::RegMMM;
Ok(())
}
@@ -2134,51 +2295,57 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m
if ((sibbyte >> 3) & 7) == 0b100 {
if modbits == 0b00 && !instr.prefixes.rex().x() {
- Operand::DisplacementU32(disp as u32)
+ instr.disp = DisplacementKind::DisplacementU32(disp as u32);
+
+ OperandSpec::RegDisp
} else {
let reg = RegSpec::gp_from_parts(0b100, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present());
+ instr.modrm_mmm = reg;
if disp == 0 {
- Operand::RegDeref(reg)
+ OperandSpec::Deref
} else {
- Operand::RegDisp(reg, disp as i32)
+ instr.disp = DisplacementKind::DisplacementI32(disp);
+ OperandSpec::RegDisp
}
}
} else {
- let base_reg = RegSpec::gp_from_parts(5, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());
+ instr.modrm_mmm = RegSpec::gp_from_parts(5, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());
- let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present());
+ instr.sib_index = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present());
+ instr.disp = DisplacementKind::DisplacementI32(disp);
let scale = 1u8 << (sibbyte >> 6);
+ instr.scale = scale;
match (scale, modbits, disp) {
(0, 0b00, 0) => {
- Operand::RegDeref(index_reg)
+ OperandSpec::Deref
},
(0, 0b00, _) => {
- Operand::RegDisp(index_reg, disp as i32)
+ OperandSpec::RegDisp
},
(0, _, 0) => {
- Operand::RegIndexBase(base_reg, index_reg)
+ OperandSpec::RegIndexBase
},
(0, _, _) => {
- Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32)
+ OperandSpec::RegIndexBaseDisp
},
(_, 0b00, 0) => {
- Operand::RegScale(index_reg, scale)
+ OperandSpec::RegScale
},
(_, 0b00, _) => {
- Operand::RegScaleDisp(index_reg, scale, disp as i32)
+ OperandSpec::RegScaleDisp
},
(_, _, 0) => {
- Operand::RegIndexBaseScale(base_reg, index_reg, scale)
+ OperandSpec::RegIndexBaseScale
},
(_, _, _) => {
- Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32)
+ OperandSpec::RegIndexBaseScaleDisp
}
}
}
} else {
- let base_reg = RegSpec::gp_from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());
+ instr.modrm_mmm = RegSpec::gp_from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());
let disp = if modbits == 0b00 {
0
@@ -2187,28 +2354,29 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m
} else {
read_num(bytes_iter, 4, &mut instr.length)? as i32
};
+ instr.disp = DisplacementKind::DisplacementI32(disp);
if ((sibbyte >> 3) & 7) == 0b100 {
if disp == 0 {
- Operand::RegDeref(base_reg)
+ OperandSpec::Deref
} else {
- Operand::RegDisp(base_reg, disp as i32)
+ OperandSpec::RegDisp
}
} else {
- let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present());
+ instr.sib_index = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present());
let scale = 1u8 << (sibbyte >> 6);
+ instr.scale = scale;
if disp == 0 {
if scale == 0 {
- Operand::RegIndexBase(base_reg, index_reg)
+ OperandSpec::RegIndexBase
} else {
- Operand::RegIndexBaseScale(base_reg, index_reg, scale)
+ OperandSpec::RegIndexBaseScale
}
} else {
if scale == 0 {
-
- Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32)
+ OperandSpec::RegIndexBaseDisp
} else {
- Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32)
+ OperandSpec::RegIndexBaseScaleDisp
}
}
}
@@ -2229,23 +2397,24 @@ fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, mod
// println!("scale: {:b}, index: {:b}, base: {:b}", ss, index, base);
} else if mmm == 5 && modbits == 0b00 {
- let disp = read_num(bytes_iter, 4, &mut instr.length)?;
- Operand::RegDisp(
- if addr_width == 8 { RegSpec::rip() } else { RegSpec::eip() },
- disp as i32
- )
+ let disp = read_num(bytes_iter, 4, &mut instr.length)? as i32;
+ instr.modrm_mmm =
+ if addr_width == 8 { RegSpec::rip() } else { RegSpec::eip() };
+ instr.disp = DisplacementKind::DisplacementI32(disp);
+ OperandSpec::RegDisp
} else {
- let reg = RegSpec::gp_from_parts(mmm, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());
+ instr.modrm_mmm = RegSpec::gp_from_parts(mmm, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());
if modbits == 0b00 {
- Operand::RegDeref(reg)
+ OperandSpec::Deref
} else {
let disp = if modbits == 0b01 {
read_num(bytes_iter, 1, &mut instr.length)? as i8 as i32
} else {
read_num(bytes_iter, 4, &mut instr.length)? as i32
};
- Operand::RegDisp(reg, disp)
+ instr.disp = DisplacementKind::DisplacementI32(disp);
+ OperandSpec::RegDisp
}
};
Ok(())
@@ -2364,35 +2533,43 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);
read_E(&mut bytes_iter, instruction, modrm, 1, opwidth)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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;
} 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)?;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
- instruction.operands[1] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ instruction.modrm_rrr =
+ RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present());
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
} else if operand_code == OperandCode::Jbs {
// TODO: arch width (8 in 64, 4 in 32, 2 in 16)
- instruction.operands = [
- read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length)?,
- Operand::Nothing
- ];
+ instruction.imm =
+ read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length)?;
+ instruction.operands[0] = OperandSpec::Imm;
+ instruction.operand_count = 1;
} else if operand_code == OperandCode::Gb_Eb {
let opwidth = 1;
let modrm = read_modrm(&mut bytes_iter, instruction)?;
read_E(&mut bytes_iter, instruction, modrm, 1, opwidth)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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;
} else if operand_code == OperandCode::Eb_Gb {
let opwidth = 1;
let modrm = read_modrm(&mut bytes_iter, instruction)?;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
- instruction.operands[1] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ instruction.modrm_rrr =
+ RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present());
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
} else {
match operand_code {
/*
@@ -2451,6 +2628,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
}
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
+ instruction.operand_count = 1;
},
op @ OperandCode::AL_Ob |
op @ OperandCode::AX_Ov => {
@@ -2467,14 +2645,16 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// stupid RCT thing:
let addr_width = if prefixes.address_size() { 2 } else { 4 };
let imm = read_num(&mut bytes_iter, addr_width, &mut instruction.length)?;
- instruction.operands = [
- Operand::Register(RegSpec::gp_from_parts(0, prefixes.rex().b(), opwidth, prefixes.rex().present())),
- if prefixes.address_size() {
- Operand::DisplacementU32(imm as u32)
- } else {
- Operand::DisplacementU64(imm)
- }
- ];
+ instruction.modrm_rrr =
+ RegSpec::gp_from_parts(0, prefixes.rex().b(), opwidth, prefixes.rex().present());
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.disp = if prefixes.address_size() {
+ DisplacementKind::DisplacementU32(imm as u32)
+ } else {
+ DisplacementKind::DisplacementU64(imm)
+ };
+ instruction.operands[1] = OperandSpec::Disp;
+ instruction.operand_count = 2;
}
op @ OperandCode::Ob_AL |
op @ OperandCode::Ov_AX => {
@@ -2491,14 +2671,16 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// stupid RCT thing:
let addr_width = if prefixes.address_size() { 2 } else { 4 };
let imm = read_num(&mut bytes_iter, addr_width, &mut instruction.length)?;
- instruction.operands = [
- if prefixes.address_size() {
- Operand::DisplacementU32(imm as u32)
- } else {
- Operand::DisplacementU64(imm)
- },
- Operand::Register(RegSpec::gp_from_parts(0, prefixes.rex().b(), opwidth, prefixes.rex().present()))
- ];
+ instruction.disp = if prefixes.address_size() {
+ DisplacementKind::DisplacementU32(imm as u32)
+ } else {
+ DisplacementKind::DisplacementU64(imm)
+ };
+ instruction.operands[0] = OperandSpec::Disp;
+ instruction.modrm_rrr =
+ RegSpec::gp_from_parts(0, prefixes.rex().b(), opwidth, prefixes.rex().present());
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
}
op @ OperandCode::ModRM_0x80_Eb_Ib |
op @ OperandCode::ModRM_0x81_Ev_Ivs => {
@@ -2514,9 +2696,10 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
let modrm = read_modrm(&mut bytes_iter, instruction)?;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
- let imm = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length)?;
+ instruction.imm = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length)?;
instruction.opcode = base_opcode_map((modrm >> 3) & 7);
- instruction.operands[1] = imm;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
op @ OperandCode::ModRM_0xc0_Eb_Ib |
op @ OperandCode::ModRM_0xc1_Ev_Ib => {
@@ -2534,7 +2717,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
let num = read_num(&mut bytes_iter, 1, &mut instruction.length)? as i8;
instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();
- instruction.operands[1] = Operand::ImmediateI8(num);
+ instruction.imm = ImmediateKind::ImmediateI8(num);
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
op @ OperandCode::ModRM_0xc6_Eb_Ib |
op @ OperandCode::ModRM_0xc7_Ev_Iv => {
@@ -2556,7 +2741,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
instruction.opcode = Opcode::MOV;
- instruction.operands[1] = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length)?;
+ instruction.imm = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length)?;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
op @ OperandCode::ModRM_0xd0_Eb_1 |
op @ OperandCode::ModRM_0xd1_Ev_1 => {
@@ -2573,7 +2760,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();
- instruction.operands[1] = Operand::ImmediateI8(1);
+ instruction.imm = ImmediateKind::ImmediateI8(1);
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
OperandCode::ModRM_0xd3_Ev_CL => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes);
@@ -2583,7 +2772,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
let opcode = BITWISE_OPCODE_MAP[r as usize].clone();
instruction.opcode = opcode;
- instruction.operands[1] = Operand::Register(RegSpec::cl());
+ instruction.modrm_rrr = RegSpec::cl();
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
}
op @ OperandCode::ModRM_0xf6 |
op @ OperandCode::ModRM_0xf7 => {
@@ -2598,11 +2789,14 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
};
let modrm = read_modrm(&mut bytes_iter, instruction)?;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
+ instruction.operand_count = 1;
match ((modrm >> 3) & 7) {
0 | 1 => {
instruction.opcode = Opcode::TEST;
let numwidth = if opwidth == 8 { 4 } else { opwidth };
- instruction.operands[1] = read_imm_signed(&mut bytes_iter, numwidth, opwidth, &mut instruction.length)?;
+ instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, opwidth, &mut instruction.length)?;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
2 => {
instruction.opcode = Opcode::NOT;
@@ -2642,7 +2836,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
Opcode::Invalid,
Opcode::Invalid
][((modrm >> 3) & 7) as usize];
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
}
OperandCode::ModRM_0xff_Ev => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes);
@@ -2660,14 +2854,14 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
Opcode::Invalid
][((modrm >> 3) & 7) as usize];
instruction.opcode = opcode;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
}
OperandCode::Ev => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes);
let modrm = read_modrm(&mut bytes_iter, instruction)?;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
},
OperandCode::Gb_Eb_Ib => {
let opwidth = 1;
@@ -2679,28 +2873,36 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// TODO
panic!("oh no, a mul!");
// read_E(&mut bytes_iter, instruction, modrm, opwidth, &mut ext[0])?;
+ /*
instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts(r, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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)?;
read_E(&mut bytes_iter, instruction, modrm, 1, opwidth)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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_Ew => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes);
let modrm = read_modrm(&mut bytes_iter, instruction)?;
read_E(&mut bytes_iter, instruction, modrm, 1, 2)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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::Ew_Sw => {
let opwidth = 2;
@@ -2711,13 +2913,16 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
return Err(()); //Err("Invalid r".to_owned());
}
- instruction.operands[1] =
- Operand::Register(RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 });
+ 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.operands[0] =
- Operand::Register(RegSpec { bank: RegisterBank::W, num: modrm & 7});
+ instruction.modrm_mmm =
+ RegSpec { bank: RegisterBank::W, num: modrm & 7};
+ instruction.operands[0] = OperandSpec::RegMMM;
} else {
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
}
@@ -2731,15 +2936,18 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
return Err(()); // Err("Invalid r".to_owned());
}
- instruction.operands[0] =
- Operand::Register(RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 });
+ 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.operands[1] =
- Operand::Register(RegSpec { bank: RegisterBank::W, num: modrm & 7});
+ instruction.modrm_mmm =
+ RegSpec { bank: RegisterBank::W, num: modrm & 7};
+ instruction.operands[1] = OperandSpec::RegMMM;
} else {
- read_E(&mut bytes_iter, instruction, modrm, 1, opwidth)?;
+ read_M(&mut bytes_iter, instruction, modrm, 1)?;
}
},
OperandCode::Gdq_Ed => {
@@ -2748,8 +2956,10 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);
read_E(&mut bytes_iter, instruction, modrm, 1, 4 /* opwidth */)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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_M => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes);
@@ -2757,8 +2967,10 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);
read_E(&mut bytes_iter, instruction, modrm, 1, opwidth)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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);
@@ -2770,28 +2982,34 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
// TODO
panic!("oh no, a mul!");
// read_E(&mut bytes_iter, instruction, modrm, opwidth, &mut ext[0])?;
+ /*
instruction.operands[0] =
- Operand::Register(RegSpec::gp_from_parts(r, prefixes.rex().r(), opwidth, prefixes.rex().present()));
+ 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)?;
// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);
read_E_xmm(&mut bytes_iter, instruction, modrm, 0)?;
- instruction.operands[1] =
- Operand::Register(RegSpec::from_parts((modrm >> 3) & 7, prefixes.rex().r(), RegisterBank::X));
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7, prefixes.rex().r(), RegisterBank::X);
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
},
OperandCode::G_E_xmm => {
let modrm = read_modrm(&mut bytes_iter, instruction)?;
// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);
read_E_xmm(&mut bytes_iter, instruction, modrm, 1)?;
- instruction.operands[0] =
- Operand::Register(RegSpec::from_parts((modrm >> 3) & 7, prefixes.rex().r(), RegisterBank::X));
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7, prefixes.rex().r(), RegisterBank::X);
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operand_count = 2;
},
op @ OperandCode::Zv_Ivq_R0 |
op @ OperandCode::Zv_Ivq_R1 |
@@ -2803,26 +3021,33 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
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.operands = [
- Operand::Register(RegSpec::gp_from_parts(reg, prefixes.rex().b(), opwidth, prefixes.rex().present())),
- read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length)?
- ];
+ 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] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
OperandCode::AL_Ib => {
- let opwidth = 1;
- let numwidth = 1;
- instruction.operands = [
- Operand::Register(RegSpec::al()),
- read_imm_signed(&mut bytes_iter, numwidth, opwidth, &mut instruction.length)?
- ];
+ instruction.modrm_rrr =
+ RegSpec::al();
+ instruction.imm =
+ read_imm_signed(&mut bytes_iter, 1, 1, &mut instruction.length)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
}
OperandCode::AX_Ivd => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, prefixes);
let numwidth = if opwidth == 8 { 4 } else { opwidth };
- instruction.operands = [
- Operand::Register(RegSpec::gp_from_parts(0, false, opwidth, false)),
- read_imm_signed(&mut bytes_iter, numwidth, opwidth, &mut instruction.length)?
- ];
+ instruction.modrm_rrr =
+ RegSpec::gp_from_parts(0, false, opwidth, false);
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.imm =
+ read_imm_signed(&mut bytes_iter, numwidth, opwidth, &mut instruction.length)?;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
}
op @ OperandCode::Zb_Ib_R0 |
op @ OperandCode::Zb_Ib_R1 |
@@ -2833,29 +3058,31 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
op @ OperandCode::Zb_Ib_R6 |
op @ OperandCode::Zb_Ib_R7 => {
let reg = (op as u8) - (OperandCode::Zb_Ib_R0 as u8);
- instruction.operands = [
- Operand::Register(RegSpec::gp_from_parts(reg, prefixes.rex().b(), 1, prefixes.rex().present())),
- read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length)?
- ];
+ 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::Imm;
+ instruction.operand_count = 2;
},
OperandCode::Iw => {
- instruction.operands = [
- read_imm_unsigned(&mut bytes_iter, 2, &mut instruction.length)?,
- Operand::Nothing
- ];
+ instruction.imm =
+ read_imm_unsigned(&mut bytes_iter, 2, &mut instruction.length)?;
+ instruction.operands[0] = OperandSpec::Imm;
+ instruction.operand_count = 1;
}
OperandCode::Ibs => {
- instruction.operands = [
- read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length)?,
- Operand::Nothing
- ];
+ instruction.imm =
+ read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length)?;
+ instruction.operands[0] = OperandSpec::Imm;
+ instruction.operand_count = 1;
},
OperandCode::Ivs => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vd, prefixes);
- instruction.operands = [
- read_imm_unsigned(&mut bytes_iter, opwidth, &mut instruction.length)?,
- Operand::Nothing
- ];
+ instruction.imm =
+ read_imm_unsigned(&mut bytes_iter, opwidth, &mut instruction.length)?;
+ instruction.operands[0] = OperandSpec::Imm;
+ instruction.operand_count = 1;
},
OperandCode::ModRM_0x83_Ev_Ibs => {
let modrm = read_modrm(&mut bytes_iter, instruction)?;
@@ -2863,7 +3090,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
instruction.opcode = base_opcode_map((modrm >> 3) & 7);
- instruction.operands[1] = read_imm_signed(&mut bytes_iter, 1, opwidth, &mut instruction.length)?;
+ instruction.imm = read_imm_signed(&mut bytes_iter, 1, opwidth, &mut instruction.length)?;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
},
op @ OperandCode::Zv_R0 |
op @ OperandCode::Zv_R1 |
@@ -2875,44 +3104,42 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
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.operands = [Operand::Register(
+ instruction.modrm_rrr =
RegSpec::gp_from_parts(
reg, prefixes.rex().b(), opwidth, prefixes.rex().present()
- )
- ), Operand::Nothing];
+ );
+ instruction.operand_count = 1;
+ instruction.operands[0] = OperandSpec::RegRRR;
},
OperandCode::Jvds => {
let offset = read_num(&mut bytes_iter, 4, &mut instruction.length)?;
- instruction.operands = [Operand::ImmediateI32(offset as i32), Operand::Nothing];
+ instruction.imm = ImmediateKind::ImmediateI32(offset as i32);
+ instruction.operand_count = 1;
+ instruction.operands[0] = OperandSpec::Imm;
}
OperandCode::ModRM_0x0f00 => {
+ instruction.operand_count = 1;
let modrm = read_modrm(&mut bytes_iter, instruction)?;
let r = (modrm >> 3) & 7;
if r == 0 {
instruction.opcode = Opcode::SLDT;
- instruction.operands[1] = Operand::Nothing;
} else if r == 1 {
instruction.opcode = Opcode::STR;
- instruction.operands[1] = Operand::Nothing;
} else if r == 2 {
instruction.opcode = Opcode::LLDT;
- instruction.operands[1] = Operand::Nothing;
} else if r == 3 {
instruction.opcode = Opcode::LTR;
- instruction.operands[1] = Operand::Nothing;
} else if r == 4 {
instruction.opcode = Opcode::VERR;
- instruction.operands[1] = Operand::Nothing;
} else if r == 5 {
instruction.opcode = Opcode::VERW;
- instruction.operands[1] = Operand::Nothing;
} else if r == 6 {
instruction.opcode = Opcode::JMPE;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
+ instruction.operand_count = 0;
return Ok(());
} else if r == 7 {
instruction.opcode = Opcode::Invalid;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
+ instruction.operand_count = 0;
return Ok(());
} else {
unreachable!("r <= 8");
@@ -2930,7 +3157,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
panic!("Unsupported instruction: 0x0f01 with modrm: 11 000 ___");
} else {
instruction.opcode = Opcode::SGDT;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
}
} else if r == 1 {
@@ -2939,10 +3166,10 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
if mod_bits == 0b11 {
// TOOD: MONITOR
instruction.opcode = Opcode::NOP;
- instruction.operands[0] = Operand::Nothing;
+ instruction.operand_count = 0;
} else {
instruction.opcode = Opcode::SIDT;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
}
} else if r == 2 {
@@ -2951,10 +3178,10 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
if mod_bits == 0b11 {
// TOOD: XGETBV
instruction.opcode = Opcode::NOP;
- instruction.operands[0] = Operand::Nothing;
+ instruction.operand_count = 0;
} else {
instruction.opcode = Opcode::LGDT;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
}
} else if r == 3 {
@@ -2963,23 +3190,23 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
if mod_bits == 0b11 {
// TOOD: VMRUN
instruction.opcode = Opcode::NOP;
- instruction.operands[0] = Operand::Nothing;
+ instruction.operand_count = 0;
} else {
instruction.opcode = Opcode::LIDT;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
}
} else if r == 4 {
// TODO: this permits storing only to word-size registers
// spec suggets this might do something different for f.ex rdi?
instruction.opcode = Opcode::SMSW;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, 2)?;
} else if r == 5 {
panic!("Unsupported instruction: 0x0f01 with modrm: __ 101 ___");
} else if r == 6 {
instruction.opcode = Opcode::LMSW;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, 2)?;
} else if r == 7 {
let mod_bits = modrm >> 6;
@@ -2987,17 +3214,17 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
if mod_bits == 0b11 {
if m == 1 {
instruction.opcode = Opcode::SWAPGS;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
+ instruction.operand_count = 0;
} else if m == 2 {
instruction.opcode = Opcode::RDTSCP;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
+ instruction.operand_count = 0;
} else {
// panic!("Unsupported instruction: 0x0f01 with modrm: 11 110 r >= 2");
return Err(()); // Err("unsupported 0x0f01 variant".to_string())
}
} else {
instruction.opcode = Opcode::INVLPG;
- instruction.operands[1] = Operand::Nothing;
+ instruction.operand_count = 1;
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
}
} else {
@@ -3008,81 +3235,44 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
let modrm = read_modrm(&mut bytes_iter, instruction)?;
let r = (modrm >> 3) & 7;
let mod_bits = modrm >> 6;
- match r {
- 0 => {
- if mod_bits == 0b11 {
- return Err(()); // Err("Invalid mod bits".to_owned())
- } else {
- instruction.opcode = Opcode::FXSAVE;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 1 => {
- if mod_bits == 0b11 {
- return Err(()); // Err("Invalid mod bits".to_owned());
- } else {
- instruction.opcode = Opcode::FXRSTOR;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 2 => {
- if mod_bits == 0b11 {
- return Err(()); // Err("Invalid mod bits".to_owned());
- } else {
- instruction.opcode = Opcode::LDMXCSR;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 3 => {
- if mod_bits == 0b11 {
- return Err(()); //Err("Invalid mod bits".to_owned());
- } else {
- instruction.opcode = Opcode::STMXCSR;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 4 => {
- if mod_bits == 0b11 {
- return Err(()); //Err("Invalid mod bits".to_owned());
- } else {
- instruction.opcode = Opcode::XSAVE;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 5 => {
- if mod_bits == 0b11 {
- instruction.opcode = Opcode::LFENCE;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
- } else {
- instruction.opcode = Opcode::XSTOR;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 6 => {
- if mod_bits == 0b11 {
- instruction.opcode = Opcode::MFENCE;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
- return Ok(());
- } else {
- // TODO: radare reports this, but i'm not sure?
- instruction.opcode = Opcode::XSAVEOPT;
- instruction.operands[1] = Operand::Nothing;
- }
- }
- 7 => {
- if mod_bits == 0b11 {
- instruction.opcode = Opcode::SFENCE;
- instruction.operands = [Operand::Nothing, Operand::Nothing];
- return Ok(());
- } else {
- // TODO: radare reports this, but i'm not sure?
- instruction.opcode = Opcode::CLFLUSH;
- instruction.operands[1] = Operand::Nothing;
- }
+
+ // all the 0b11 instructions are err or no-operands
+ if mod_bits == 0b11 {
+ instruction.operand_count = 0;
+ match r {
+ // invalid rrr for 0x0fae, mod: 11
+ 0 | 1 | 2 | 3 | 4 => {
+ return Err(());
+ },
+ 5 => {
+ instruction.opcode = Opcode::LFENCE
+ },
+ 6 => {
+ instruction.opcode = Opcode::MFENCE
+ },
+ 7 => {
+ instruction.opcode = Opcode::SFENCE
+ },
+ _ => { unsafe { unreachable_unchecked() } /* r <=7 */ }
}
- _ => { unreachable!("r < 6"); }
- }
- read_E(&mut bytes_iter, instruction, modrm, 0, 8)?;
+ Ok(())
+ } else {
+ instruction.operand_count = 1;
+ instruction.opcode = [
+ Opcode::FXSAVE,
+ Opcode::FXRSTOR,
+ Opcode::LDMXCSR,
+ Opcode::STMXCSR,
+ Opcode::XSAVE,
+ Opcode::XSTOR,
+ // TODO: radare reports this, but i'm not sure?
+ Opcode::XSAVEOPT,
+ // TODO: radare reports this, but i'm not sure?
+ Opcode::CLFLUSH,
+ Opcode::Invalid,
+ ][r as usize];
+ read_M(&mut bytes_iter, instruction, modrm, 0)
+ }?;
}
OperandCode::ModRM_0x0fba => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vq, prefixes);
@@ -3112,7 +3302,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
read_E(&mut bytes_iter, instruction, modrm, 0, opwidth)?;
- instruction.operands[1] = read_imm_signed(&mut bytes_iter, 1, 1, &mut instruction.length)?;
+ instruction.imm = read_imm_signed(&mut bytes_iter, 1, 1, &mut instruction.length)?;
+ instruction.operands[1] = OperandSpec::Imm;
+ instruction.operand_count = 2;
}
op @ OperandCode::Rq_Cq_0 |
@@ -3131,10 +3323,13 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
if prefixes.rex().b() {
m += 0b1000;
}
- instruction.operands = [
- Operand::Register(RegSpec { bank: RegisterBank::Q, num: m }),
- Operand::Register(RegSpec { bank: bank, num: r })
- ];
+ 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::Cq_Rq_0 |
op @ OperandCode::Dq_Rq_0 => {
@@ -3152,25 +3347,34 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
if prefixes.rex().b() {
m += 0b1000;
}
- instruction.operands = [
- Operand::Register(RegSpec { bank: bank, num: r }),
- Operand::Register(RegSpec { bank: RegisterBank::Q, num: m })
- ];
+ instruction.modrm_rrr =
+ 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.operand_count = 2;
}
OperandCode::FS => {
- instruction.operands = [Operand::Register(RegSpec::fs()), Operand::Nothing];
+ instruction.modrm_rrr = RegSpec::fs();
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operand_count = 1;
}
OperandCode::GS => {
- instruction.operands = [Operand::Register(RegSpec::fs()), Operand::Nothing];
+ instruction.modrm_rrr = RegSpec::gs();
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operand_count = 1;
}
OperandCode::I_3 => {
- instruction.operands = [Operand::ImmediateU8(3), Operand::Nothing];
+ instruction.imm = ImmediateKind::ImmediateU8(3);
+ instruction.operands[0] = OperandSpec::Imm;
+ instruction.operand_count = 1;
}
OperandCode::Nothing => {
- instruction.operands = [Operand::Nothing, Operand::Nothing];
+ instruction.operand_count = 0;
}
_ => {
- instruction.operands = [Operand::Nothing, Operand::Nothing];
+ instruction.operand_count = 0;
instruction.opcode = Opcode::Invalid;
return Err(()); // Err(format!("unsupported operand code: {:?}", operand_code));
// unsafe { unreachable_unchecked(); }
@@ -3231,16 +3435,16 @@ fn read_num<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) ->
}
#[inline]
-fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<Operand, ()> {
+fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<ImmediateKind, ()> {
match width {
2 => {
- Ok(Operand::ImmediateU16(read_num(bytes, 2, length)? as u16))
+ Ok(ImmediateKind::ImmediateU16(read_num(bytes, 2, length)? as u16))
},
4 => {
- Ok(Operand::ImmediateU32(read_num(bytes, 4, length)? as u32))
+ Ok(ImmediateKind::ImmediateU32(read_num(bytes, 4, length)? as u32))
},
8 => {
- Ok(Operand::ImmediateU64(read_num(bytes, 8, length)? as u64))
+ Ok(ImmediateKind::ImmediateU64(read_num(bytes, 8, length)? as u64))
},
_ => {
unsafe { unreachable_unchecked(); }
@@ -3249,7 +3453,7 @@ fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8)
}
#[inline]
-fn read_imm_signed<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8, extend_to: u8, length: &mut u8) -> Result<Operand, ()> {
+fn read_imm_signed<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8, extend_to: u8, length: &mut u8) -> Result<ImmediateKind, ()> {
let num = match num_width {
1 => read_num(bytes, 1, length)? as i8 as i64,
2 => read_num(bytes, 2, length)? as i16 as i64,
@@ -3259,28 +3463,28 @@ fn read_imm_signed<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8, extend_to
};
match extend_to {
- 1 => Ok(Operand::ImmediateI8(num as i8)),
- 2 => Ok(Operand::ImmediateI16(num as i16)),
- 4 => Ok(Operand::ImmediateI32(num as i32)),
- 8 => Ok(Operand::ImmediateI64(num as i64)),
+ 1 => Ok(ImmediateKind::ImmediateI8(num as i8)),
+ 2 => Ok(ImmediateKind::ImmediateI16(num as i16)),
+ 4 => Ok(ImmediateKind::ImmediateI32(num as i32)),
+ 8 => Ok(ImmediateKind::ImmediateI64(num as i64)),
_ => { unsafe { unreachable_unchecked() } }
}
}
#[inline]
-fn read_imm_unsigned<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<Operand, ()> {
+fn read_imm_unsigned<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<ImmediateKind, ()> {
match width {
1 => {
- Ok(Operand::ImmediateU8(read_num(bytes, 1, length)? as u8))
+ Ok(ImmediateKind::ImmediateU8(read_num(bytes, 1, length)? as u8))
},
2 => {
- Ok(Operand::ImmediateU16(read_num(bytes, 2, length)? as u16))
+ Ok(ImmediateKind::ImmediateU16(read_num(bytes, 2, length)? as u16))
},
4 => {
- Ok(Operand::ImmediateU32(read_num(bytes, 4, length)? as u32))
+ Ok(ImmediateKind::ImmediateU32(read_num(bytes, 4, length)? as u32))
},
8 => {
- Ok(Operand::ImmediateU64(read_num(bytes, 4, length)? as u64))
+ Ok(ImmediateKind::ImmediateU64(read_num(bytes, 4, length)? as u64))
}
_ => {
unsafe { unreachable_unchecked(); }