disarmv7/arch/
condition.rs1use crate::ArchError;
5
6#[derive(Debug, Clone, PartialEq)]
7pub enum Condition {
9 Eq,
11 Ne,
13 Cs,
15 Cc,
17 Mi,
19 Pl,
21 Vs,
23 Vc,
25 Hi,
27 Ls,
29 Ge,
31 Lt,
33 Gt,
35 Le,
37 None,
39}
40
41#[derive(Debug, Clone, PartialEq)]
42pub struct ITCondition {
47 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}