diff --git a/src/operands.rs b/src/operands.rs index 0918aad..e157246 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -7,7 +7,10 @@ use crate::register::SegmentRegister; use crate::{disasm::DisasmError, register::Register}; use core::fmt; -use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Shl, Shr, Sub}; +use std::{ + cmp::Ordering, + ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Shl, Shr, Sub}, +}; pub type Byte = u8; // b pub type IByte = i8; // used for displacements of memory access @@ -15,7 +18,7 @@ pub type Word = u16; // w or v pub type IWord = i16; // used for displacement of memory access pub type DWord = u32; -#[derive(Debug, Clone, Ord, Eq, PartialEq, PartialOrd, Copy)] +#[derive(Debug, Clone, Eq, PartialEq, Copy)] /// Universal type to encode either Byte- or Word-sized immediate operands. /// Mostly used to: /// - Encode immediates, where instructions exist for both widths. @@ -106,6 +109,23 @@ impl ImmediateOperand { } } +impl PartialOrd for ImmediateOperand { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ImmediateOperand { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (ImmediateOperand::Byte(a), ImmediateOperand::Byte(b)) => a.cmp(b), + (ImmediateOperand::Word(a), ImmediateOperand::Word(b)) => a.cmp(b), + (ImmediateOperand::Byte(a), ImmediateOperand::Word(b)) => (*a as Word).cmp(b), + (ImmediateOperand::Word(a), ImmediateOperand::Byte(b)) => a.cmp(&(*b as Word)), + } + } +} + impl From> for ImmediateOperand { fn from(bits: Vec) -> Self { if bits.len() == 8 { @@ -681,6 +701,19 @@ impl std::fmt::Display for Pointer32 { mod tests { use super::*; + #[test] + fn ord() { + let b1 = ImmediateOperand::Byte(1); + let b5 = ImmediateOperand::Byte(5); + let w1 = ImmediateOperand::Word(1); + let w10 = ImmediateOperand::Word(10); + + assert_eq!(b1 < b5, true); + assert_eq!(w1 < w10, true); + assert_eq!(b1 < w10, true); + assert_eq!(w1 < b5, true); + } + #[test] fn add_byte_byte() { let a = ImmediateOperand::Byte(5);