aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-08-09 20:49:12 -0700
committeriximeow <me@iximeow.net>2020-08-09 20:49:12 -0700
commit6248d3c5f7dd196acdfce5c0da1608fed81b43cd (patch)
treeb38ed1edaf50708b5e9774a29a9ae09ec1b50481 /src
parent8f857a2fcbdfc7315cd09c0a4ac372b3ec92b538 (diff)
inaugural 0.1.0 release!0.1.0
add doc comments for public items, record changelog, and lets ship this!!
Diffstat (limited to 'src')
-rw-r--r--src/long_mode/mod.rs44
-rw-r--r--src/protected_mode/mod.rs39
2 files changed, 56 insertions, 27 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 23213ec..f328c72 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -19,16 +19,6 @@ pub struct RegSpec {
bank: RegisterBank
}
-impl RegSpec {
- pub fn num(&self) -> u8 {
- self.num
- }
-
- pub fn class(&self) -> RegisterClass {
- RegisterClass { kind: self.bank }
- }
-}
-
use core::hash::Hash;
use core::hash::Hasher;
impl Hash for RegSpec {
@@ -70,6 +60,16 @@ pub enum ConditionCode {
#[allow(non_snake_case)]
impl RegSpec {
+ pub fn num(&self) -> u8 {
+ self.num
+ }
+
+ pub fn class(&self) -> RegisterClass {
+ RegisterClass { kind: self.bank }
+ }
+
+ /// return a human-friendly name for this register. the returned name is the same as would be
+ /// used to render this register in an instruction.
pub fn name(&self) -> &'static str {
display::regspec_label(self)
}
@@ -465,6 +465,10 @@ impl Operand {
}
}
+ /// return the width of this operand, in bytes. register widths are determined by the
+ /// register's class.
+ ///
+ /// TODO: /!\ MEMORY WIDTHS ARE ALWAYS REPORTED AS 8 /!\
pub fn width(&self) -> u8 {
match self {
Operand::Nothing => {
@@ -555,10 +559,12 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[
];
impl RegisterClass {
+ /// return a human-friendly name for this register class
pub fn name(&self) -> &'static str {
REGISTER_CLASS_NAMES[self.kind as usize]
}
+ /// return the size of this register class, in bytes
pub fn width(&self) -> u8 {
match self.kind {
RegisterBank::Q => 8,
@@ -3185,15 +3191,22 @@ impl Instruction {
self.opcode
}
+ /// get the `Operand` at the provided index.
+ ///
+ /// panics if the index is `>= 4`.
pub fn operand(&self, i: u8) -> Operand {
assert!(i < 4);
Operand::from_spec(self, self.operands[i as usize])
}
+ /// get the number of operands in this instruction. useful in iterating an instruction's
+ /// operands generically.
pub fn operand_count(&self) -> u8 {
self.operand_count
}
+ /// check if operand `i` is an actual operand or not. will be `false` for `i >=
+ /// inst.operand_count()`.
pub fn operand_present(&self, i: u8) -> bool {
assert!(i < 4);
if i >= self.operand_count {
@@ -3207,6 +3220,8 @@ impl Instruction {
}
}
+ /// build a new instruction representing nothing in particular. this is primarily useful as a
+ /// default to pass to `decode_into`.
pub fn invalid() -> Instruction {
Instruction {
prefixes: Prefixes::new(0),
@@ -3657,7 +3672,7 @@ enum OperandCode {
DX_AL = OperandCodeBuilder::new().special_case(47).bits(),
MOVQ_f30f = OperandCodeBuilder::new().special_case(48).bits(),
- Unsupported = OperandCodeBuilder::new().special_case(49).bits(),
+// Unsupported = OperandCodeBuilder::new().special_case(49).bits(),
ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().special_case(40).bits(),
ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().special_case(41).bits(),
@@ -6431,9 +6446,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = OperandSpec::ImmU8;
instruction.operand_count = 1;
}
+ /*
OperandCode::Unsupported => {
return Err(DecodeError::IncompleteDecoder);
}
+ */
OperandCode::Iw_Ib => {
instruction.disp = read_num(&mut bytes_iter, 2)? as u64;
instruction.imm = read_num(&mut bytes_iter, 1)? as u64;
@@ -7446,7 +7463,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[1] = OperandSpec::Deref;
instruction.operand_count = 2;
}
- // TODO: two memory operands! this is wrong!!!
OperandCode::Yb_Xb => {
instruction.operands[0] = OperandSpec::Deref_rdi;
instruction.operands[1] = OperandSpec::Deref_rsi;
@@ -8655,12 +8671,10 @@ fn imm_width_from_prefixes_64(interpretation: SizeCode, prefixes: Prefixes) -> u
if prefixes.rex().w() || !prefixes.operand_size() { 4 } else { 2 }
},
SizeCode::vq => {
- // TODO: this should be address_size
- // but i'm not sure if that breaks other instructions rn
if prefixes.operand_size() {
2
} else {
- 8 // TODO: this 8 should be arch width.
+ 8
}
},
SizeCode::vqp => {
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index cb19a15..315cb58 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -19,16 +19,6 @@ pub struct RegSpec {
bank: RegisterBank
}
-impl RegSpec {
- pub fn num(&self) -> u8 {
- self.num
- }
-
- pub fn class(&self) -> RegisterClass {
- RegisterClass { kind: self.bank }
- }
-}
-
use core::hash::Hash;
use core::hash::Hasher;
impl Hash for RegSpec {
@@ -70,6 +60,16 @@ pub enum ConditionCode {
#[allow(non_snake_case)]
impl RegSpec {
+ pub fn num(&self) -> u8 {
+ self.num
+ }
+
+ pub fn class(&self) -> RegisterClass {
+ RegisterClass { kind: self.bank }
+ }
+
+ /// return a human-friendly name for this register. the returned name is the same as would be
+ /// used to render this register in an instruction.
pub fn name(&self) -> &'static str {
display::regspec_label(self)
}
@@ -270,6 +270,7 @@ impl RegSpec {
RegSpec { bank: RegisterBank::MM, num: 0 }
}
+ /// return the size of this register, in bytes
#[inline]
pub fn width(&self) -> u8 {
self.class().width()
@@ -427,6 +428,10 @@ impl Operand {
}
}
+ /// return the width of this operand, in bytes. register widths are determined by the
+ /// register's class.
+ ///
+ /// TODO: /!\ MEMORY WIDTHS ARE ALWAYS REPORTED AS 8 /!\
pub fn width(&self) -> u8 {
match self {
Operand::Nothing => {
@@ -3133,15 +3138,22 @@ impl Instruction {
self.opcode
}
+ /// get the `Operand` at the provided index.
+ ///
+ /// panics if the index is `>= 4`.
pub fn operand(&self, i: u8) -> Operand {
assert!(i < 4);
Operand::from_spec(self, self.operands[i as usize])
}
+ /// get the number of operands in this instruction. useful in iterating an instruction's
+ /// operands generically.
pub fn operand_count(&self) -> u8 {
self.operand_count
}
+ /// check if operand `i` is an actual operand or not. will be `false` for `i >=
+ /// inst.operand_count()`.
pub fn operand_present(&self, i: u8) -> bool {
assert!(i < 4);
if i >= self.operand_count {
@@ -3155,6 +3167,8 @@ impl Instruction {
}
}
+ /// build a new instruction representing nothing in particular. this is primarily useful as a
+ /// default to pass to `decode_into`.
pub fn invalid() -> Instruction {
Instruction {
prefixes: Prefixes::new(0),
@@ -3583,7 +3597,7 @@ enum OperandCode {
DX_AL = OperandCodeBuilder::new().special_case(47).bits(),
MOVQ_f30f = OperandCodeBuilder::new().special_case(48).bits(),
- Unsupported = OperandCodeBuilder::new().special_case(49).bits(),
+// Unsupported = OperandCodeBuilder::new().special_case(49).bits(),
ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().special_case(40).bits(),
ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().special_case(41).bits(),
@@ -6390,9 +6404,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = OperandSpec::ImmU8;
instruction.operand_count = 1;
}
+ /*
OperandCode::Unsupported => {
return Err(DecodeError::IncompleteDecoder);
}
+ */
OperandCode::Iw_Ib => {
instruction.disp = read_num(&mut bytes_iter, 2)?;
instruction.imm = read_num(&mut bytes_iter, 1)?;
@@ -7328,7 +7344,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[1] = OperandSpec::Deref;
instruction.operand_count = 2;
}
- // TODO: two memory operands! this is wrong!!!
OperandCode::Yb_Xb => {
instruction.operands[0] = OperandSpec::Deref_edi;
instruction.operands[1] = OperandSpec::Deref_esi;