Skip to main content

qcode/value/insn/
unop.rs

1use std::fmt::{Display, Formatter};
2
3use crate::value::{LocalValueId, insn::mnemonic::MnemonicKind};
4use smallvec::smallvec;
5
6use super::mnemonic::Args;
7
8#[non_exhaustive]
9#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
10pub enum Unop {
11    IntNegate,
12    IntNot,
13    FloatNegate,
14    FloatAbs,
15    FloatSqrt,
16    FloatCeil,
17    FloatFloor,
18    FloatRound,
19}
20
21impl Unop {
22    /// Evaluates the integer variants of this operation on a raw bit pattern.
23    ///
24    /// Returns `None` for float variants, which are not pure integer operations.
25    /// `size` is the operand width in bytes; the result is masked to `size` bytes.
26    pub fn eval_int(&self, value: u128, size: usize) -> Option<u128> {
27        use super::bits::mask_for_size;
28        let mask = mask_for_size(size);
29        let v = value & mask;
30        match self {
31            Unop::IntNegate => Some(v.wrapping_neg() & mask),
32            Unop::IntNot => Some(!v & mask),
33            _ => None,
34        }
35    }
36}
37
38impl Display for Unop {
39    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40        let s = match self {
41            Unop::IntNegate => "-",
42            Unop::IntNot => "~",
43            Unop::FloatNegate => "f-",
44            Unop::FloatAbs => "abs",
45            Unop::FloatSqrt => "sqrt",
46            Unop::FloatCeil => "ceil",
47            Unop::FloatFloor => "floor",
48            Unop::FloatRound => "round",
49        };
50
51        write!(f, "{}", s)
52    }
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
56pub struct Unary {
57    pub op: Unop,
58    pub src: LocalValueId,
59}
60
61impl MnemonicKind for Unary {
62    fn opcode(&self) -> &'static str {
63        "unop"
64    }
65
66    fn args(&self) -> Args {
67        smallvec![self.src]
68    }
69}
70
71// TODO: add tests for all the different unop variants similar to the ones in flags.rs and casting.rs