aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-11-29 16:50:18 -0800
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commit5c86aaf06d0f638d3fc1d302ef4d401b0222bee1 (patch)
treecac7d1294fca70707ea6fac3ff472fe93796edca /src
parent324c58fee142e0ea987d1d23a7e25142dde803d0 (diff)
support imul, >2 operands, and 4-bit register bank
Diffstat (limited to 'src')
-rw-r--r--src/display.rs113
-rw-r--r--src/lib.rs33
2 files changed, 87 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 <T: std::fmt::Write> ShowContextual<u64, [Option<String>], 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<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u
Some(record)
}
None => {
- unsafe { unreachable_unchecked(); }
None
}
}
@@ -1810,7 +1809,6 @@ fn read_opcode_f30f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u
Some(record)
}
None => {
- unsafe { unreachable_unchecked(); }
None
}
}
@@ -2139,7 +2137,6 @@ fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u8)
Some(record)
}
None => {
- unsafe { unreachable_unchecked(); }
None
}
}
@@ -2806,7 +2803,11 @@ pub fn read_operands<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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;
}