disarmv7/arch/
condition.rs

1//! Defines the [`Condition`] codes that are defined in the Armv7-m instruction
2//! set..
3
4use crate::ArchError;
5
6#[derive(Debug, Clone, PartialEq)]
7/// Derived from section A7.3
8pub enum Condition {
9    /// Exactly equal to, z == 1
10    Eq,
11    /// Not equal to, z == 0
12    Ne,
13    /// Carry set, C == 1
14    Cs,
15    /// Carry clear, C == 0
16    Cc,
17    /// Minus, negative N == 1
18    Mi,
19    /// Plus, positive or zero, N >= 0
20    Pl,
21    /// Overflow, V  == 1
22    Vs,
23    /// Not Overflow, V == 0
24    Vc,
25    /// Unsigned higher, C == 1 && z == 0
26    Hi,
27    /// Unsigned lower, C == 0 && z == 1
28    Ls,
29    /// Signed greater or equal, N == V
30    Ge,
31    /// Signed less than, N != V
32    Lt,
33    /// Signed greater than, Z == 0 && N == V
34    Gt,
35    /// Signed less than or equal, Z == 1 && N!=V
36    Le,
37    /// Unconditional
38    None,
39}
40
41#[derive(Debug, Clone, PartialEq)]
42/// If then Else block
43///
44/// This type defines how to [`Parse`](ITCondition::from)
45/// the condition vector from a base [`Condition`] and a mask.
46pub struct ITCondition {
47    /// The conditions that need to be satisfied for
48    /// the next few instructions to be executed.
49    ///
50    /// i.e. to execute instruction `i` the condition
51    /// `conditions[i]` must evaluate to true.
52    pub conditions: Vec<Condition>,
53}
54
55impl Condition {
56    fn invert(&self) -> Self {
57        match self {
58            Self::Eq => Self::Ne,
59            Self::Ne => Self::Eq,
60            Self::Cs => Self::Cc,
61            Self::Cc => Self::Cs,
62            Self::Mi => Self::Pl,
63            Self::Pl => Self::Mi,
64            Self::Vs => Self::Vc,
65            Self::Vc => Self::Vs,
66            Self::Hi => Self::Ls,
67            Self::Ls => Self::Hi,
68            Self::Ge => Self::Lt,
69            Self::Lt => Self::Ge,
70            Self::Gt => Self::Le,
71            Self::Le => Self::Gt,
72            Self::None => Self::None,
73        }
74    }
75}
76
77impl From<(Condition, u8)> for ITCondition {
78    fn from(value: (Condition, u8)) -> Self {
79        let mask = value.1;
80        let cond = value.0;
81
82        let condition_code: u8 = cond.clone().into();
83        let condition = condition_code & 0b1;
84        if mask == 0b1000 {
85            return Self {
86                conditions: vec![cond],
87            };
88        }
89        let x = {
90            if (mask & 0b1000) >> 3 == condition {
91                cond.clone()
92            } else {
93                cond.invert()
94            }
95        };
96        if mask & 0b111 == 0b100 {
97            return Self {
98                conditions: vec![cond, x],
99            };
100        }
101
102        let y = {
103            if (mask & 0b100) >> 2 == condition {
104                cond.clone()
105            } else {
106                cond.invert()
107            }
108        };
109
110        if mask & 0b11 == 0b10 {
111            return Self {
112                conditions: vec![cond, x, y],
113            };
114        }
115
116        let z = {
117            if (mask & 0b10) >> 1 == condition {
118                cond.clone()
119            } else {
120                cond.invert()
121            }
122        };
123        Self {
124            conditions: vec![cond, x, y, z],
125        }
126    }
127}
128
129impl From<ITCondition> for Vec<Condition> {
130    fn from(val: ITCondition) -> Self {
131        val.conditions
132    }
133}
134
135impl TryFrom<u8> for Condition {
136    type Error = ArchError;
137
138    fn try_from(value: u8) -> Result<Self, Self::Error> {
139        Ok(match value {
140            0b0 => Self::Eq,
141            0b1 => Self::Ne,
142            0b10 => Self::Cs,
143            0b11 => Self::Cc,
144            0b100 => Self::Mi,
145            0b101 => Self::Pl,
146            0b110 => Self::Vs,
147            0b111 => Self::Vc,
148            0b1000 => Self::Hi,
149            0b1001 => Self::Ls,
150            0b1010 => Self::Ge,
151            0b1011 => Self::Lt,
152            0b1100 => Self::Gt,
153            0b1101 => Self::Le,
154            0b1110 => Self::None,
155            _ => return Err(ArchError::InvalidCondition),
156        })
157    }
158}
159
160impl From<Condition> for u8 {
161    fn from(value: Condition) -> Self {
162        match value {
163            Condition::Eq => 0,
164            Condition::Ne => 0b1,
165            Condition::Cs => 0b10,
166            Condition::Cc => 0b11,
167            Condition::Mi => 0b100,
168            Condition::Pl => 0b101,
169            Condition::Vs => 0b110,
170            Condition::Vc => 0b111,
171            Condition::Hi => 0b1000,
172            Condition::Ls => 0b1001,
173            Condition::Ge => 0b1010,
174            Condition::Lt => 0b1011,
175            Condition::Gt => 0b1100,
176            Condition::Le => 0b1101,
177            Condition::None => 0b1110,
178        }
179    }
180}
181impl TryFrom<u16> for Condition {
182    type Error = ArchError;
183
184    fn try_from(value: u16) -> Result<Self, Self::Error> {
185        Self::try_from(value as u8)
186    }
187}