aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-05-25 07:52:41 -0700
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commitb6ace85e557fc69f155b60890929452ac5ef0fb9 (patch)
tree187380b9bddc8c502bf962e640574ed58f0e8c57
parent153e8b77d364893a460a7d779347febae36e5b5a (diff)
more serde friendliness, cli, cld, clc, sti, std, stc support
-rw-r--r--src/display.rs12
-rw-r--r--src/lib.rs61
2 files changed, 71 insertions, 2 deletions
diff --git a/src/display.rs b/src/display.rs
index b500992..50375f2 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -174,6 +174,12 @@ impl <T: std::fmt::Write> Colorize<T> for Operand {
impl fmt::Display for Opcode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
+ &Opcode::STI => write!(f, "{}", "sti"),
+ &Opcode::STD => write!(f, "{}", "std"),
+ &Opcode::STC => write!(f, "{}", "stc"),
+ &Opcode::CLI => write!(f, "{}", "cli"),
+ &Opcode::CLD => write!(f, "{}", "cld"),
+ &Opcode::CLC => write!(f, "{}", "clc"),
&Opcode::SLDT => write!(f, "{}", "sldt"),
&Opcode::STR => write!(f, "{}", "str"),
&Opcode::LLDT => write!(f, "{}", "lldt"),
@@ -393,6 +399,12 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) }
/* Data transfer */
+ Opcode::CLC |
+ Opcode::CLI |
+ Opcode::CLD |
+ Opcode::STC |
+ Opcode::STI |
+ Opcode::STD |
Opcode::MOV |
Opcode::CBW |
Opcode::CDW |
diff --git a/src/lib.rs b/src/lib.rs
index 8057114..234735f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,6 +18,13 @@ use std::hint::unreachable_unchecked;
use yaxpeax_arch::{Arch, ColorSettings, Decodable, LengthedInstruction};
+#[cfg(feature="use-serde")]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
+pub struct RegSpec {
+ pub num: u8,
+ pub bank: RegisterBank
+}
+#[cfg(not(feature="use-serde"))]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct RegSpec {
pub num: u8,
@@ -165,6 +172,15 @@ pub enum Operand {
Nothing
}
+#[cfg(feature="use-serde")]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
+pub enum RegisterBank {
+ Q, D, W, B, rB, // Quadword, Dword, Word, Byte
+ CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ...
+ X, Y, Z, // XMM, YMM, ZMM
+ ST, MM, // ST, MM regs (x87, mmx)
+}
+#[cfg(not(feature="use-serde"))]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum RegisterBank {
Q, D, W, B, rB, // Quadword, Dword, Word, Byte
@@ -329,6 +345,12 @@ pub enum Opcode {
LTR,
VERR,
VERW,
+ CLC,
+ STC,
+ CLI,
+ STI,
+ CLD,
+ STD,
JMPE,
Invalid
}
@@ -340,13 +362,18 @@ pub struct Instruction {
pub length: u8
}
+// 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
+// which themselves are bounded, but their #[derive] require T to
+// implement these traits.
#[cfg(feature="use-serde")]
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Hash, Eq, PartialEq, Debug, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
pub struct x86_64;
#[cfg(not(feature="use-serde"))]
-#[derive(Debug)]
+#[derive(Hash, Eq, PartialEq, Debug)]
#[allow(non_camel_case_types)]
pub struct x86_64;
@@ -1420,6 +1447,36 @@ fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instr
instruction.opcode = Opcode::Invalid;
return Ok(OperandCode::ModRM_0xf7);
},
+ 0xf8 => {
+ instruction.prefixes = prefixes;
+ instruction.opcode = Opcode::CLC;
+ return Ok(OperandCode::Nothing);
+ }
+ 0xf9 => {
+ instruction.prefixes = prefixes;
+ instruction.opcode = Opcode::STC;
+ return Ok(OperandCode::Nothing);
+ }
+ 0xfa => {
+ instruction.prefixes = prefixes;
+ instruction.opcode = Opcode::CLI;
+ return Ok(OperandCode::Nothing);
+ }
+ 0xfb => {
+ instruction.prefixes = prefixes;
+ instruction.opcode = Opcode::STI;
+ return Ok(OperandCode::Nothing);
+ }
+ 0xfc => {
+ instruction.prefixes = prefixes;
+ instruction.opcode = Opcode::CLD;
+ return Ok(OperandCode::Nothing);
+ }
+ 0xfd => {
+ instruction.prefixes = prefixes;
+ instruction.opcode = Opcode::STD;
+ return Ok(OperandCode::Nothing);
+ }
0xfe => {
instruction.prefixes = prefixes;
instruction.opcode = Opcode::Invalid;