1use anyhow::{anyhow, bail, Result};
7use libafl::prelude::CmpValues;
8use raw_cstr::AsRawCstr;
9use simics::api::{
10 get_interface, read_phys_memory, sys::instruction_handle_t, Access, ConfObject,
11 CpuInstructionQueryInterface, CpuInstrumentationSubscribeInterface, CycleInterface,
12 IntRegisterInterface, ProcessorInfoV2Interface,
13};
14use std::{ffi::CStr, mem::size_of, slice::from_raw_parts};
15use yaxpeax_arch::{Decoder, U8Reader};
16use yaxpeax_arm::armv7::{InstDecoder, Instruction, Opcode, Operand, RegShiftStyle, ShiftStyle};
17
18use crate::{
19 tracer::{CmpExpr, CmpExprShift, CmpType, CmpValue, TraceEntry},
20 traits::TracerDisassembler,
21};
22
23use super::ArchitectureOperations;
24
25pub(crate) struct ARMArchitectureOperations {
26 cpu: *mut ConfObject,
27 disassembler: Disassembler,
28 int_register: IntRegisterInterface,
29 processor_info_v2: ProcessorInfoV2Interface,
30 cpu_instruction_query: CpuInstructionQueryInterface,
31 cpu_instrumentation_subscribe: CpuInstrumentationSubscribeInterface,
32 cycle: CycleInterface,
33}
34
35impl ArchitectureOperations for ARMArchitectureOperations {
36 const INDEX_SELECTOR_REGISTER: &'static str = "r10";
37
38 const ARGUMENT_REGISTER_0: &'static str = "r9";
39
40 const ARGUMENT_REGISTER_1: &'static str = "r8";
41
42 const ARGUMENT_REGISTER_2: &'static str = "r7";
43
44 fn new(cpu: *mut ConfObject) -> Result<Self> {
45 let mut processor_info_v2: ProcessorInfoV2Interface = get_interface(cpu)?;
46
47 let arch = unsafe { CStr::from_ptr(processor_info_v2.architecture()?) }
48 .to_str()?
49 .to_string();
50
51 if arch == "arm" || arch == "armv7" || arch == "armv6" || arch == "armv5" || arch == "arm32"
52 {
53 Ok(Self {
54 cpu,
55 disassembler: Disassembler::new(),
56 int_register: get_interface(cpu)?,
57 processor_info_v2,
58 cpu_instruction_query: get_interface(cpu)?,
59 cpu_instrumentation_subscribe: get_interface(cpu)?,
60 cycle: get_interface(cpu)?,
61 })
62 } else {
63 bail!("Architecture {} is not arm", arch);
64 }
65 }
66
67 fn new_unchecked(cpu: *mut ConfObject) -> Result<Self>
68 where
69 Self: Sized,
70 {
71 Ok(Self {
72 cpu,
73 disassembler: Disassembler::new(),
74 int_register: get_interface(cpu)?,
75 processor_info_v2: get_interface(cpu)?,
76 cpu_instruction_query: get_interface(cpu)?,
77 cpu_instrumentation_subscribe: get_interface(cpu)?,
78 cycle: get_interface(cpu)?,
79 })
80 }
81
82 fn cpu(&self) -> *mut ConfObject {
83 self.cpu
84 }
85
86 fn disassembler(&mut self) -> &mut dyn TracerDisassembler {
87 &mut self.disassembler
88 }
89
90 fn int_register(&mut self) -> &mut IntRegisterInterface {
91 &mut self.int_register
92 }
93
94 fn processor_info_v2(&mut self) -> &mut ProcessorInfoV2Interface {
95 &mut self.processor_info_v2
96 }
97
98 fn cpu_instruction_query(&mut self) -> &mut CpuInstructionQueryInterface {
99 &mut self.cpu_instruction_query
100 }
101
102 fn cpu_instrumentation_subscribe(&mut self) -> &mut CpuInstrumentationSubscribeInterface {
103 &mut self.cpu_instrumentation_subscribe
104 }
105
106 fn cycle(&mut self) -> &mut CycleInterface {
107 &mut self.cycle
108 }
109
110 fn trace_pc(&mut self, instruction_query: *mut instruction_handle_t) -> Result<TraceEntry> {
111 let instruction_bytes = self
112 .cpu_instruction_query
113 .get_instruction_bytes(instruction_query)?;
114
115 self.disassembler.disassemble(unsafe {
116 from_raw_parts(instruction_bytes.data, instruction_bytes.size)
117 })?;
118
119 if self.disassembler.last_was_call()
120 || self.disassembler.last_was_control_flow()
121 || self.disassembler.last_was_ret()
122 {
123 Ok(TraceEntry::builder()
124 .edge(self.processor_info_v2.get_program_counter()?)
125 .build())
126 } else {
127 Ok(TraceEntry::default())
128 }
129 }
130
131 fn trace_cmp(&mut self, instruction_query: *mut instruction_handle_t) -> Result<TraceEntry> {
132 let instruction_bytes = self
133 .cpu_instruction_query
134 .get_instruction_bytes(instruction_query)?;
135 self.disassembler.disassemble(unsafe {
136 from_raw_parts(instruction_bytes.data, instruction_bytes.size)
137 })?;
138
139 let pc = self.processor_info_v2.get_program_counter()?;
140
141 let mut cmp_values = Vec::new();
142
143 for expr in self.disassembler.cmp() {
144 if let Ok(value) = self.simplify(&expr) {
145 cmp_values.push(value);
146 }
147 }
148
149 let cmp_value = if let (Some(l), Some(r)) = (cmp_values.first(), cmp_values.get(1)) {
150 match (l, r) {
151 (CmpValue::U8(l), CmpValue::U8(r)) => Some(CmpValues::U8((*l, *r))),
152 (CmpValue::I8(l), CmpValue::I8(r)) => Some(CmpValues::U8((
153 u8::from_le_bytes(l.to_le_bytes()),
154 u8::from_le_bytes(r.to_le_bytes()),
155 ))),
156 (CmpValue::U16(l), CmpValue::U16(r)) => Some(CmpValues::U16((*l, *r))),
157 (CmpValue::I16(l), CmpValue::I16(r)) => Some(CmpValues::U16((
158 u16::from_le_bytes(l.to_le_bytes()),
159 u16::from_le_bytes(r.to_le_bytes()),
160 ))),
161 (CmpValue::U32(l), CmpValue::U32(r)) => Some(CmpValues::U32((*l, *r))),
162 (CmpValue::I32(l), CmpValue::I32(r)) => Some(CmpValues::U32((
163 u32::from_le_bytes(l.to_le_bytes()),
164 u32::from_le_bytes(r.to_le_bytes()),
165 ))),
166 (CmpValue::U64(l), CmpValue::U64(r)) => Some(CmpValues::U64((*l, *r))),
167 (CmpValue::I64(l), CmpValue::I64(r)) => Some(CmpValues::U64((
168 u64::from_le_bytes(l.to_le_bytes()),
169 u64::from_le_bytes(r.to_le_bytes()),
170 ))),
171 (CmpValue::Expr(_), CmpValue::Expr(_)) => None,
172 _ => None,
173 }
174 } else {
175 None
176 };
177
178 Ok(TraceEntry::builder()
179 .cmp((
180 pc,
181 self.disassembler.cmp_type(),
182 cmp_value.ok_or_else(|| anyhow!("No cmp value available"))?,
183 ))
184 .build())
185 }
186}
187
188impl ARMArchitectureOperations {
189 fn simplify(&mut self, expr: &CmpExpr) -> Result<CmpValue> {
190 match expr {
191 CmpExpr::Deref((b, _)) => {
192 let v = self.simplify(b)?;
193 match v {
194 CmpValue::U64(a) => {
195 let address = self
196 .processor_info_v2
197 .logical_to_physical(a, Access::Sim_Access_Read)?;
198 Ok(CmpValue::U64(read_phys_memory(
199 self.cpu,
200 address.address,
201 size_of::<u64>() as i32,
202 )?))
203 }
204 CmpValue::U32(a) => {
205 let address = self
206 .processor_info_v2
207 .logical_to_physical(a as u64, Access::Sim_Access_Read)?;
208 Ok(CmpValue::U64(read_phys_memory(
209 self.cpu,
210 address.address,
211 size_of::<u32>() as i32,
212 )?))
213 }
214 _ => bail!("Invalid dereference size {:?}", v),
215 }
216 }
217 CmpExpr::Reg((n, _)) => {
218 let regno = self.int_register.get_number(n.as_raw_cstr()?)?;
219 let value = self.int_register.read(regno)?;
220 if self.processor_info_v2.get_logical_address_width()? as u32 / u8::BITS == 8 {
221 Ok(CmpValue::U64(value))
222 } else {
223 Ok(CmpValue::U32(value as u32))
224 }
225 }
226 CmpExpr::Add((l, r)) => {
227 let lv = self.simplify(l)?;
228 let rv = self.simplify(r)?;
229
230 match (lv, rv) {
231 (CmpValue::U8(lu), CmpValue::U8(ru)) => Ok(CmpValue::U8(lu.wrapping_add(ru))),
232 (CmpValue::U8(lu), CmpValue::I8(ru)) => {
233 Ok(CmpValue::U8(lu.wrapping_add_signed(ru)))
234 }
235 (CmpValue::U8(lu), CmpValue::U16(ru)) => {
236 Ok(CmpValue::U8((lu as u16).wrapping_add(ru) as u8))
237 }
238 (CmpValue::U8(lu), CmpValue::I16(ru)) => {
239 Ok(CmpValue::U8((lu as u16).wrapping_add_signed(ru) as u8))
240 }
241 (CmpValue::U8(lu), CmpValue::U32(ru)) => {
242 Ok(CmpValue::U8((lu as u32).wrapping_add(ru) as u8))
243 }
244 (CmpValue::U8(lu), CmpValue::I32(ru)) => {
245 Ok(CmpValue::U8((lu as u32).wrapping_add_signed(ru) as u8))
246 }
247 (CmpValue::U8(lu), CmpValue::U64(ru)) => {
248 Ok(CmpValue::U8((lu as u64).wrapping_add(ru) as u8))
249 }
250 (CmpValue::U8(lu), CmpValue::I64(ru)) => {
251 Ok(CmpValue::U8((lu as u64).wrapping_add_signed(ru) as u8))
252 }
253 (CmpValue::I8(lu), CmpValue::U8(ru)) => {
254 Ok(CmpValue::I8(lu.wrapping_add_unsigned(ru)))
255 }
256 (CmpValue::I8(lu), CmpValue::I8(ru)) => Ok(CmpValue::I8(lu.wrapping_add(ru))),
257 (CmpValue::I8(lu), CmpValue::U16(ru)) => {
258 Ok(CmpValue::I8((lu as i16).wrapping_add_unsigned(ru) as i8))
259 }
260 (CmpValue::I8(lu), CmpValue::I16(ru)) => {
261 Ok(CmpValue::I8((lu as i16).wrapping_add(ru) as i8))
262 }
263 (CmpValue::I8(lu), CmpValue::U32(ru)) => {
264 Ok(CmpValue::I8((lu as i32).wrapping_add_unsigned(ru) as i8))
265 }
266 (CmpValue::I8(lu), CmpValue::I32(ru)) => {
267 Ok(CmpValue::I8((lu as i32).wrapping_add(ru) as i8))
268 }
269 (CmpValue::I8(lu), CmpValue::U64(ru)) => {
270 Ok(CmpValue::I8((lu as i64).wrapping_add_unsigned(ru) as i8))
271 }
272 (CmpValue::I8(lu), CmpValue::I64(ru)) => {
273 Ok(CmpValue::I8((lu as i64).wrapping_add(ru) as i8))
274 }
275 (CmpValue::U16(lu), CmpValue::U8(ru)) => {
276 Ok(CmpValue::U16(lu.wrapping_add(ru as u16)))
277 }
278 (CmpValue::U16(lu), CmpValue::I8(ru)) => {
279 Ok(CmpValue::U16(lu.wrapping_add_signed(ru as i16)))
280 }
281 (CmpValue::U16(lu), CmpValue::U16(ru)) => {
282 Ok(CmpValue::U16(lu.wrapping_add(ru)))
283 }
284 (CmpValue::U16(lu), CmpValue::I16(ru)) => {
285 Ok(CmpValue::U16(lu.wrapping_add_signed(ru)))
286 }
287 (CmpValue::U16(lu), CmpValue::U32(ru)) => {
288 Ok(CmpValue::U16((lu as u32).wrapping_add(ru) as u16))
289 }
290 (CmpValue::U16(lu), CmpValue::I32(ru)) => {
291 Ok(CmpValue::U16((lu as u32).wrapping_add_signed(ru) as u16))
292 }
293 (CmpValue::U16(lu), CmpValue::U64(ru)) => {
294 Ok(CmpValue::U16((lu as u64).wrapping_add(ru) as u16))
295 }
296 (CmpValue::U16(lu), CmpValue::I64(ru)) => {
297 Ok(CmpValue::U16((lu as u64).wrapping_add_signed(ru) as u16))
298 }
299 (CmpValue::I16(lu), CmpValue::U8(ru)) => {
300 Ok(CmpValue::I16(lu.wrapping_add_unsigned(ru as u16)))
301 }
302 (CmpValue::I16(lu), CmpValue::I8(ru)) => {
303 Ok(CmpValue::I16(lu.wrapping_add(ru as i16)))
304 }
305 (CmpValue::I16(lu), CmpValue::U16(ru)) => {
306 Ok(CmpValue::I16(lu.wrapping_add_unsigned(ru)))
307 }
308 (CmpValue::I16(lu), CmpValue::I16(ru)) => {
309 Ok(CmpValue::I16(lu.wrapping_add(ru)))
310 }
311 (CmpValue::I16(lu), CmpValue::U32(ru)) => {
312 Ok(CmpValue::I16((lu as i32).wrapping_add_unsigned(ru) as i16))
313 }
314 (CmpValue::I16(lu), CmpValue::I32(ru)) => {
315 Ok(CmpValue::I16((lu as i32).wrapping_add(ru) as i16))
316 }
317 (CmpValue::I16(lu), CmpValue::U64(ru)) => {
318 Ok(CmpValue::I16((lu as i64).wrapping_add_unsigned(ru) as i16))
319 }
320 (CmpValue::I16(lu), CmpValue::I64(ru)) => {
321 Ok(CmpValue::I16((lu as i64).wrapping_add(ru) as i16))
322 }
323 (CmpValue::U32(lu), CmpValue::U8(ru)) => {
324 Ok(CmpValue::U32(lu.wrapping_add(ru as u32)))
325 }
326 (CmpValue::U32(lu), CmpValue::I8(ru)) => {
327 Ok(CmpValue::U32(lu.wrapping_add_signed(ru as i32)))
328 }
329 (CmpValue::U32(lu), CmpValue::U16(ru)) => {
330 Ok(CmpValue::U32(lu.wrapping_add(ru as u32)))
331 }
332 (CmpValue::U32(lu), CmpValue::I16(ru)) => {
333 Ok(CmpValue::U32(lu.wrapping_add_signed(ru as i32)))
334 }
335 (CmpValue::U32(lu), CmpValue::U32(ru)) => {
336 Ok(CmpValue::U32(lu.wrapping_add(ru)))
337 }
338 (CmpValue::U32(lu), CmpValue::I32(ru)) => {
339 Ok(CmpValue::U32(lu.wrapping_add_signed(ru)))
340 }
341 (CmpValue::U32(lu), CmpValue::U64(ru)) => {
342 Ok(CmpValue::U32((lu as u64).wrapping_add(ru) as u32))
343 }
344 (CmpValue::U32(lu), CmpValue::I64(ru)) => {
345 Ok(CmpValue::U32((lu as u64).wrapping_add_signed(ru) as u32))
346 }
347 (CmpValue::I32(lu), CmpValue::U8(ru)) => {
348 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru as u32)))
349 }
350 (CmpValue::I32(lu), CmpValue::I8(ru)) => {
351 Ok(CmpValue::I32(lu.wrapping_add(ru as i32)))
352 }
353 (CmpValue::I32(lu), CmpValue::U16(ru)) => {
354 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru as u32)))
355 }
356 (CmpValue::I32(lu), CmpValue::I16(ru)) => {
357 Ok(CmpValue::I32(lu.wrapping_add(ru as i32)))
358 }
359 (CmpValue::I32(lu), CmpValue::U32(ru)) => {
360 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru)))
361 }
362 (CmpValue::I32(lu), CmpValue::I32(ru)) => {
363 Ok(CmpValue::I32(lu.wrapping_add(ru)))
364 }
365 (CmpValue::I32(lu), CmpValue::U64(ru)) => {
366 Ok(CmpValue::I32((lu as i64).wrapping_add_unsigned(ru) as i32))
367 }
368 (CmpValue::I32(lu), CmpValue::I64(ru)) => {
369 Ok(CmpValue::I32((lu as i64).wrapping_add(ru) as i32))
370 }
371 (CmpValue::U64(lu), CmpValue::U8(ru)) => {
372 Ok(CmpValue::U64(lu.wrapping_add(ru as u64)))
373 }
374 (CmpValue::U64(lu), CmpValue::I8(ru)) => {
375 Ok(CmpValue::U64(lu.wrapping_add_signed(ru as i64)))
376 }
377 (CmpValue::U64(lu), CmpValue::U16(ru)) => {
378 Ok(CmpValue::U64(lu.wrapping_add(ru as u64)))
379 }
380 (CmpValue::U64(lu), CmpValue::I16(ru)) => {
381 Ok(CmpValue::U64(lu.wrapping_add_signed(ru as i64)))
382 }
383 (CmpValue::U64(lu), CmpValue::U32(ru)) => {
384 Ok(CmpValue::U64(lu.wrapping_add(ru as u64)))
385 }
386 (CmpValue::U64(lu), CmpValue::I32(ru)) => {
387 Ok(CmpValue::U64(lu.wrapping_add_signed(ru as i64)))
388 }
389 (CmpValue::U64(lu), CmpValue::U64(ru)) => {
390 Ok(CmpValue::U64(lu.wrapping_add(ru)))
391 }
392 (CmpValue::U64(lu), CmpValue::I64(ru)) => {
393 Ok(CmpValue::U64(lu.wrapping_add_signed(ru)))
394 }
395 (CmpValue::I64(lu), CmpValue::U8(ru)) => {
396 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
397 }
398 (CmpValue::I64(lu), CmpValue::I8(ru)) => {
399 Ok(CmpValue::I64(lu.wrapping_add(ru as i64)))
400 }
401 (CmpValue::I64(lu), CmpValue::U16(ru)) => {
402 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
403 }
404 (CmpValue::I64(lu), CmpValue::I16(ru)) => {
405 Ok(CmpValue::I64(lu.wrapping_add(ru as i64)))
406 }
407 (CmpValue::I64(lu), CmpValue::U32(ru)) => {
408 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
409 }
410 (CmpValue::I64(lu), CmpValue::I32(ru)) => {
411 Ok(CmpValue::I64(lu.wrapping_add(ru as i64)))
412 }
413 (CmpValue::I64(lu), CmpValue::U64(ru)) => {
414 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru)))
415 }
416 (CmpValue::I64(lu), CmpValue::I64(ru)) => {
417 Ok(CmpValue::I64(lu.wrapping_add(ru)))
418 }
419 _ => bail!("Cannot multiply non-integral types"),
420 }
421 }
422 CmpExpr::Sub((l, r)) => {
423 let lv = self.simplify(l)?;
424 let rv = self.simplify(r)?;
425
426 match (lv, rv) {
427 (CmpValue::U8(lu), CmpValue::U8(ru)) => Ok(CmpValue::U8(lu.wrapping_sub(ru))),
428 (CmpValue::U8(lu), CmpValue::I8(ru)) => {
429 Ok(CmpValue::U8(lu.wrapping_add_signed(-ru)))
430 }
431 (CmpValue::U8(lu), CmpValue::U16(ru)) => {
432 Ok(CmpValue::U8((lu as u16).wrapping_sub(ru) as u8))
433 }
434 (CmpValue::U8(lu), CmpValue::I16(ru)) => {
435 Ok(CmpValue::U8((lu as u16).wrapping_add_signed(-ru) as u8))
436 }
437 (CmpValue::U8(lu), CmpValue::U32(ru)) => {
438 Ok(CmpValue::U8((lu as u32).wrapping_sub(ru) as u8))
439 }
440 (CmpValue::U8(lu), CmpValue::I32(ru)) => {
441 Ok(CmpValue::U8((lu as u32).wrapping_add_signed(-ru) as u8))
442 }
443 (CmpValue::U8(lu), CmpValue::U64(ru)) => {
444 Ok(CmpValue::U8((lu as u64).wrapping_sub(ru) as u8))
445 }
446 (CmpValue::U8(lu), CmpValue::I64(ru)) => {
447 Ok(CmpValue::U8((lu as u64).wrapping_add_signed(-ru) as u8))
448 }
449 (CmpValue::I8(lu), CmpValue::U8(ru)) => {
450 Ok(CmpValue::I8(lu.wrapping_add_unsigned(ru)))
451 }
452 (CmpValue::I8(lu), CmpValue::I8(ru)) => Ok(CmpValue::I8(lu.wrapping_sub(ru))),
453 (CmpValue::I8(lu), CmpValue::U16(ru)) => {
454 Ok(CmpValue::I8((lu as i16).wrapping_add_unsigned(ru) as i8))
455 }
456 (CmpValue::I8(lu), CmpValue::I16(ru)) => {
457 Ok(CmpValue::I8((lu as i16).wrapping_sub(ru) as i8))
458 }
459 (CmpValue::I8(lu), CmpValue::U32(ru)) => {
460 Ok(CmpValue::I8((lu as i32).wrapping_add_unsigned(ru) as i8))
461 }
462 (CmpValue::I8(lu), CmpValue::I32(ru)) => {
463 Ok(CmpValue::I8((lu as i32).wrapping_sub(ru) as i8))
464 }
465 (CmpValue::I8(lu), CmpValue::U64(ru)) => {
466 Ok(CmpValue::I8((lu as i64).wrapping_add_unsigned(ru) as i8))
467 }
468 (CmpValue::I8(lu), CmpValue::I64(ru)) => {
469 Ok(CmpValue::I8((lu as i64).wrapping_sub(ru) as i8))
470 }
471 (CmpValue::U16(lu), CmpValue::U8(ru)) => {
472 Ok(CmpValue::U16(lu.wrapping_sub(ru as u16)))
473 }
474 (CmpValue::U16(lu), CmpValue::I8(ru)) => {
475 Ok(CmpValue::U16(lu.wrapping_add_signed(-ru as i16)))
476 }
477 (CmpValue::U16(lu), CmpValue::U16(ru)) => {
478 Ok(CmpValue::U16(lu.wrapping_sub(ru)))
479 }
480 (CmpValue::U16(lu), CmpValue::I16(ru)) => {
481 Ok(CmpValue::U16(lu.wrapping_add_signed(-ru)))
482 }
483 (CmpValue::U16(lu), CmpValue::U32(ru)) => {
484 Ok(CmpValue::U16((lu as u32).wrapping_sub(ru) as u16))
485 }
486 (CmpValue::U16(lu), CmpValue::I32(ru)) => {
487 Ok(CmpValue::U16((lu as u32).wrapping_add_signed(-ru) as u16))
488 }
489 (CmpValue::U16(lu), CmpValue::U64(ru)) => {
490 Ok(CmpValue::U16((lu as u64).wrapping_sub(ru) as u16))
491 }
492 (CmpValue::U16(lu), CmpValue::I64(ru)) => {
493 Ok(CmpValue::U16((lu as u64).wrapping_add_signed(-ru) as u16))
494 }
495 (CmpValue::I16(lu), CmpValue::U8(ru)) => {
496 Ok(CmpValue::I16(lu.wrapping_add_unsigned(ru as u16)))
497 }
498 (CmpValue::I16(lu), CmpValue::I8(ru)) => {
499 Ok(CmpValue::I16(lu.wrapping_sub(ru as i16)))
500 }
501 (CmpValue::I16(lu), CmpValue::U16(ru)) => {
502 Ok(CmpValue::I16(lu.wrapping_add_unsigned(ru)))
503 }
504 (CmpValue::I16(lu), CmpValue::I16(ru)) => {
505 Ok(CmpValue::I16(lu.wrapping_sub(ru)))
506 }
507 (CmpValue::I16(lu), CmpValue::U32(ru)) => {
508 Ok(CmpValue::I16((lu as i32).wrapping_add_unsigned(ru) as i16))
509 }
510 (CmpValue::I16(lu), CmpValue::I32(ru)) => {
511 Ok(CmpValue::I16((lu as i32).wrapping_sub(ru) as i16))
512 }
513 (CmpValue::I16(lu), CmpValue::U64(ru)) => {
514 Ok(CmpValue::I16((lu as i64).wrapping_add_unsigned(ru) as i16))
515 }
516 (CmpValue::I16(lu), CmpValue::I64(ru)) => {
517 Ok(CmpValue::I16((lu as i64).wrapping_sub(ru) as i16))
518 }
519 (CmpValue::U32(lu), CmpValue::U8(ru)) => {
520 Ok(CmpValue::U32(lu.wrapping_sub(ru as u32)))
521 }
522 (CmpValue::U32(lu), CmpValue::I8(ru)) => {
523 Ok(CmpValue::U32(lu.wrapping_add_signed(-ru as i32)))
524 }
525 (CmpValue::U32(lu), CmpValue::U16(ru)) => {
526 Ok(CmpValue::U32(lu.wrapping_sub(ru as u32)))
527 }
528 (CmpValue::U32(lu), CmpValue::I16(ru)) => {
529 Ok(CmpValue::U32(lu.wrapping_add_signed(-ru as i32)))
530 }
531 (CmpValue::U32(lu), CmpValue::U32(ru)) => {
532 Ok(CmpValue::U32(lu.wrapping_sub(ru)))
533 }
534 (CmpValue::U32(lu), CmpValue::I32(ru)) => {
535 Ok(CmpValue::U32(lu.wrapping_add_signed(-ru)))
536 }
537 (CmpValue::U32(lu), CmpValue::U64(ru)) => {
538 Ok(CmpValue::U32((lu as u64).wrapping_sub(ru) as u32))
539 }
540 (CmpValue::U32(lu), CmpValue::I64(ru)) => {
541 Ok(CmpValue::U32((lu as u64).wrapping_add_signed(-ru) as u32))
542 }
543 (CmpValue::I32(lu), CmpValue::U8(ru)) => {
544 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru as u32)))
545 }
546 (CmpValue::I32(lu), CmpValue::I8(ru)) => {
547 Ok(CmpValue::I32(lu.wrapping_sub(ru as i32)))
548 }
549 (CmpValue::I32(lu), CmpValue::U16(ru)) => {
550 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru as u32)))
551 }
552 (CmpValue::I32(lu), CmpValue::I16(ru)) => {
553 Ok(CmpValue::I32(lu.wrapping_sub(ru as i32)))
554 }
555 (CmpValue::I32(lu), CmpValue::U32(ru)) => {
556 Ok(CmpValue::I32(lu.wrapping_add_unsigned(ru)))
557 }
558 (CmpValue::I32(lu), CmpValue::I32(ru)) => {
559 Ok(CmpValue::I32(lu.wrapping_sub(ru)))
560 }
561 (CmpValue::I32(lu), CmpValue::U64(ru)) => {
562 Ok(CmpValue::I32((lu as i64).wrapping_add_unsigned(ru) as i32))
563 }
564 (CmpValue::I32(lu), CmpValue::I64(ru)) => {
565 Ok(CmpValue::I32((lu as i64).wrapping_sub(ru) as i32))
566 }
567 (CmpValue::U64(lu), CmpValue::U8(ru)) => {
568 Ok(CmpValue::U64(lu.wrapping_sub(ru as u64)))
569 }
570 (CmpValue::U64(lu), CmpValue::I8(ru)) => {
571 Ok(CmpValue::U64(lu.wrapping_add_signed(-ru as i64)))
572 }
573 (CmpValue::U64(lu), CmpValue::U16(ru)) => {
574 Ok(CmpValue::U64(lu.wrapping_sub(ru as u64)))
575 }
576 (CmpValue::U64(lu), CmpValue::I16(ru)) => {
577 Ok(CmpValue::U64(lu.wrapping_add_signed(-ru as i64)))
578 }
579 (CmpValue::U64(lu), CmpValue::U32(ru)) => {
580 Ok(CmpValue::U64(lu.wrapping_sub(ru as u64)))
581 }
582 (CmpValue::U64(lu), CmpValue::I32(ru)) => {
583 Ok(CmpValue::U64(lu.wrapping_add_signed(-ru as i64)))
584 }
585 (CmpValue::U64(lu), CmpValue::U64(ru)) => {
586 Ok(CmpValue::U64(lu.wrapping_sub(ru)))
587 }
588 (CmpValue::U64(lu), CmpValue::I64(ru)) => {
589 Ok(CmpValue::U64(lu.wrapping_add_signed(-ru)))
590 }
591 (CmpValue::I64(lu), CmpValue::U8(ru)) => {
592 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
593 }
594 (CmpValue::I64(lu), CmpValue::I8(ru)) => {
595 Ok(CmpValue::I64(lu.wrapping_sub(ru as i64)))
596 }
597 (CmpValue::I64(lu), CmpValue::U16(ru)) => {
598 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
599 }
600 (CmpValue::I64(lu), CmpValue::I16(ru)) => {
601 Ok(CmpValue::I64(lu.wrapping_sub(ru as i64)))
602 }
603 (CmpValue::I64(lu), CmpValue::U32(ru)) => {
604 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru as u64)))
605 }
606 (CmpValue::I64(lu), CmpValue::I32(ru)) => {
607 Ok(CmpValue::I64(lu.wrapping_sub(ru as i64)))
608 }
609 (CmpValue::I64(lu), CmpValue::U64(ru)) => {
610 Ok(CmpValue::I64(lu.wrapping_add_unsigned(ru)))
611 }
612 (CmpValue::I64(lu), CmpValue::I64(ru)) => {
613 Ok(CmpValue::I64(lu.wrapping_sub(ru)))
614 }
615 _ => bail!("Cannot multiply non-integral types"),
616 }
617 }
618 CmpExpr::Shift((shiftee, shifter, typ)) => {
619 let shiftee = self.simplify(shiftee)?;
620 let shifter = self.simplify(shifter)?;
621
622 match (shiftee, shifter) {
623 (CmpValue::U8(lu), CmpValue::U8(ru)) => match typ {
624 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ru as u32))),
625 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
626 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
627 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ru as u32))),
628 },
629 (CmpValue::U8(lu), CmpValue::I8(ri)) => {
630 let ru = ri as u8;
631 match typ {
632 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ru as u32))),
633 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
634 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
635 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ru as u32))),
636 }
637 }
638 (CmpValue::U8(lu), CmpValue::U16(ru)) => match typ {
639 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ru as u32))),
640 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
641 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
642 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ru as u32))),
643 },
644 (CmpValue::U8(lu), CmpValue::I16(ri)) => match typ {
645 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ri as u32))),
646 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ri as u32))),
647 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ri as u32))),
648 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ri as u32))),
649 },
650 (CmpValue::U8(lu), CmpValue::U32(ru)) => match typ {
651 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ru))),
652 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ru))),
653 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ru))),
654 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ru))),
655 },
656 (CmpValue::U8(lu), CmpValue::I32(ri)) => match typ {
657 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ri as u32))),
658 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ri as u32))),
659 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ri as u32))),
660 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ri as u32))),
661 },
662 (CmpValue::U8(lu), CmpValue::U64(ru)) => match typ {
663 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ru as u32))),
664 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
665 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ru as u32))),
666 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ru as u32))),
667 },
668 (CmpValue::U8(lu), CmpValue::I64(ri)) => match typ {
669 CmpExprShift::Lsl => Ok(CmpValue::U8(lu.wrapping_shl(ri as u32))),
670 CmpExprShift::Lsr => Ok(CmpValue::U8(lu.wrapping_shr(ri as u32))),
671 CmpExprShift::Asr => Ok(CmpValue::U8(lu.wrapping_shr(ri as u32))),
672 CmpExprShift::Ror => Ok(CmpValue::U8(lu.rotate_right(ri as u32))),
673 },
674 (CmpValue::I8(li), CmpValue::U8(ru)) => match typ {
675 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ru as u32))),
676 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ru as u32))),
677 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ru as u32))),
678 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ru as u32))),
679 },
680 (CmpValue::I8(li), CmpValue::I8(ri)) => match typ {
681 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ri as u32))),
682 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
683 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
684 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ri as u32))),
685 },
686 (CmpValue::I8(li), CmpValue::U16(ru)) => match typ {
687 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ru as u32))),
688 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ru as u32))),
689 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ru as u32))),
690 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ru as u32))),
691 },
692 (CmpValue::I8(li), CmpValue::I16(ri)) => match typ {
693 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ri as u32))),
694 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
695 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
696 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ri as u32))),
697 },
698 (CmpValue::I8(li), CmpValue::U32(ru)) => match typ {
699 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ru))),
700 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ru))),
701 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ru))),
702 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ru))),
703 },
704 (CmpValue::I8(li), CmpValue::I32(ri)) => match typ {
705 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ri as u32))),
706 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
707 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
708 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ri as u32))),
709 },
710 (CmpValue::I8(li), CmpValue::U64(ru)) => match typ {
711 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ru as u32))),
712 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ru as u32))),
713 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ru as u32))),
714 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ru as u32))),
715 },
716 (CmpValue::I8(li), CmpValue::I64(ri)) => match typ {
717 CmpExprShift::Lsl => Ok(CmpValue::I8(li.wrapping_shl(ri as u32))),
718 CmpExprShift::Lsr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
719 CmpExprShift::Asr => Ok(CmpValue::I8(li.wrapping_shr(ri as u32))),
720 CmpExprShift::Ror => Ok(CmpValue::I8(li.rotate_right(ri as u32))),
721 },
722 (CmpValue::U16(lu), CmpValue::U8(ru)) => match typ {
723 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ru as u32))),
724 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ru as u32))),
725 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ru as u32))),
726 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ru as u32))),
727 },
728 (CmpValue::U16(lu), CmpValue::I8(ri)) => match typ {
729 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ri as u32))),
730 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
731 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
732 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ri as u32))),
733 },
734 (CmpValue::U16(lu), CmpValue::U16(ru)) => match typ {
735 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ru as u32))),
736 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ru as u32))),
737 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ru as u32))),
738 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ru as u32))),
739 },
740 (CmpValue::U16(lu), CmpValue::I16(ri)) => match typ {
741 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ri as u32))),
742 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
743 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
744 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ri as u32))),
745 },
746 (CmpValue::U16(lu), CmpValue::U32(ru)) => match typ {
747 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ru))),
748 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ru))),
749 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ru))),
750 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ru))),
751 },
752 (CmpValue::U16(lu), CmpValue::I32(ri)) => match typ {
753 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ri as u32))),
754 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
755 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
756 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ri as u32))),
757 },
758 (CmpValue::U16(lu), CmpValue::U64(ru)) => match typ {
759 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ru as u32))),
760 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ru as u32))),
761 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ru as u32))),
762 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ru as u32))),
763 },
764 (CmpValue::U16(lu), CmpValue::I64(ri)) => match typ {
765 CmpExprShift::Lsl => Ok(CmpValue::U16(lu.wrapping_shl(ri as u32))),
766 CmpExprShift::Lsr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
767 CmpExprShift::Asr => Ok(CmpValue::U16(lu.wrapping_shr(ri as u32))),
768 CmpExprShift::Ror => Ok(CmpValue::U16(lu.rotate_right(ri as u32))),
769 },
770 (CmpValue::I16(li), CmpValue::U8(ru)) => match typ {
771 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ru as u32))),
772 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ru as u32))),
773 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ru as u32))),
774 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ru as u32))),
775 },
776 (CmpValue::I16(li), CmpValue::I8(ri)) => match typ {
777 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ri as u32))),
778 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
779 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
780 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ri as u32))),
781 },
782 (CmpValue::I16(li), CmpValue::U16(ru)) => match typ {
783 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ru as u32))),
784 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ru as u32))),
785 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ru as u32))),
786 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ru as u32))),
787 },
788 (CmpValue::I16(li), CmpValue::I16(ri)) => match typ {
789 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ri as u32))),
790 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
791 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
792 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ri as u32))),
793 },
794 (CmpValue::I16(li), CmpValue::U32(ru)) => match typ {
795 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ru))),
796 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ru))),
797 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ru))),
798 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ru))),
799 },
800 (CmpValue::I16(li), CmpValue::I32(ri)) => match typ {
801 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ri as u32))),
802 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
803 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
804 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ri as u32))),
805 },
806 (CmpValue::I16(li), CmpValue::U64(ru)) => match typ {
807 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ru as u32))),
808 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ru as u32))),
809 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ru as u32))),
810 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ru as u32))),
811 },
812 (CmpValue::I16(li), CmpValue::I64(ri)) => match typ {
813 CmpExprShift::Lsl => Ok(CmpValue::I16(li.wrapping_shl(ri as u32))),
814 CmpExprShift::Lsr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
815 CmpExprShift::Asr => Ok(CmpValue::I16(li.wrapping_shr(ri as u32))),
816 CmpExprShift::Ror => Ok(CmpValue::I16(li.rotate_right(ri as u32))),
817 },
818 (CmpValue::U32(lu), CmpValue::U8(ru)) => match typ {
819 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ru as u32))),
820 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ru as u32))),
821 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ru as u32))),
822 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ru as u32))),
823 },
824 (CmpValue::U32(lu), CmpValue::I8(ri)) => match typ {
825 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ri as u32))),
826 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
827 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
828 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ri as u32))),
829 },
830 (CmpValue::U32(lu), CmpValue::U16(ru)) => match typ {
831 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ru as u32))),
832 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ru as u32))),
833 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ru as u32))),
834 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ru as u32))),
835 },
836 (CmpValue::U32(lu), CmpValue::I16(ri)) => match typ {
837 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ri as u32))),
838 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
839 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
840 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ri as u32))),
841 },
842 (CmpValue::U32(lu), CmpValue::U32(ru)) => match typ {
843 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ru))),
844 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ru))),
845 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ru))),
846 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ru))),
847 },
848 (CmpValue::U32(lu), CmpValue::I32(ri)) => match typ {
849 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ri as u32))),
850 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
851 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
852 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ri as u32))),
853 },
854 (CmpValue::U32(lu), CmpValue::U64(ru)) => match typ {
855 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ru as u32))),
856 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ru as u32))),
857 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ru as u32))),
858 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ru as u32))),
859 },
860 (CmpValue::U32(lu), CmpValue::I64(ri)) => match typ {
861 CmpExprShift::Lsl => Ok(CmpValue::U32(lu.wrapping_shl(ri as u32))),
862 CmpExprShift::Lsr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
863 CmpExprShift::Asr => Ok(CmpValue::U32(lu.wrapping_shr(ri as u32))),
864 CmpExprShift::Ror => Ok(CmpValue::U32(lu.rotate_right(ri as u32))),
865 },
866 (CmpValue::I32(li), CmpValue::U8(ru)) => match typ {
867 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ru as u32))),
868 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ru as u32))),
869 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ru as u32))),
870 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ru as u32))),
871 },
872 (CmpValue::I32(li), CmpValue::I8(ri)) => match typ {
873 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ri as u32))),
874 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
875 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
876 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ri as u32))),
877 },
878 (CmpValue::I32(li), CmpValue::U16(ru)) => match typ {
879 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ru as u32))),
880 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ru as u32))),
881 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ru as u32))),
882 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ru as u32))),
883 },
884 (CmpValue::I32(li), CmpValue::I16(ri)) => match typ {
885 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ri as u32))),
886 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
887 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
888 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ri as u32))),
889 },
890 (CmpValue::I32(li), CmpValue::U32(ru)) => match typ {
891 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ru))),
892 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ru))),
893 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ru))),
894 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ru))),
895 },
896 (CmpValue::I32(li), CmpValue::I32(ri)) => match typ {
897 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ri as u32))),
898 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
899 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
900 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ri as u32))),
901 },
902 (CmpValue::I32(li), CmpValue::U64(ru)) => match typ {
903 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ru as u32))),
904 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ru as u32))),
905 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ru as u32))),
906 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ru as u32))),
907 },
908 (CmpValue::I32(li), CmpValue::I64(ri)) => match typ {
909 CmpExprShift::Lsl => Ok(CmpValue::I32(li.wrapping_shl(ri as u32))),
910 CmpExprShift::Lsr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
911 CmpExprShift::Asr => Ok(CmpValue::I32(li.wrapping_shr(ri as u32))),
912 CmpExprShift::Ror => Ok(CmpValue::I32(li.rotate_right(ri as u32))),
913 },
914 (CmpValue::U64(lu), CmpValue::U8(ru)) => match typ {
915 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ru as u32))),
916 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ru as u32))),
917 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ru as u32))),
918 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ru as u32))),
919 },
920 (CmpValue::U64(lu), CmpValue::I8(ri)) => match typ {
921 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ri as u32))),
922 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
923 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
924 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ri as u32))),
925 },
926 (CmpValue::U64(lu), CmpValue::U16(ru)) => match typ {
927 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ru as u32))),
928 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ru as u32))),
929 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ru as u32))),
930 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ru as u32))),
931 },
932 (CmpValue::U64(lu), CmpValue::I16(ri)) => match typ {
933 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ri as u32))),
934 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
935 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
936 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ri as u32))),
937 },
938 (CmpValue::U64(lu), CmpValue::U32(ru)) => match typ {
939 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ru))),
940 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ru))),
941 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ru))),
942 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ru))),
943 },
944 (CmpValue::U64(lu), CmpValue::I32(ri)) => match typ {
945 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ri as u32))),
946 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
947 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
948 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ri as u32))),
949 },
950 (CmpValue::U64(lu), CmpValue::U64(ru)) => match typ {
951 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ru as u32))),
952 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ru as u32))),
953 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ru as u32))),
954 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ru as u32))),
955 },
956 (CmpValue::U64(lu), CmpValue::I64(ri)) => match typ {
957 CmpExprShift::Lsl => Ok(CmpValue::U64(lu.wrapping_shl(ri as u32))),
958 CmpExprShift::Lsr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
959 CmpExprShift::Asr => Ok(CmpValue::U64(lu.wrapping_shr(ri as u32))),
960 CmpExprShift::Ror => Ok(CmpValue::U64(lu.rotate_right(ri as u32))),
961 },
962 (CmpValue::I64(li), CmpValue::U8(ru)) => match typ {
963 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ru as u32))),
964 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ru as u32))),
965 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ru as u32))),
966 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ru as u32))),
967 },
968 (CmpValue::I64(li), CmpValue::I8(ri)) => match typ {
969 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ri as u32))),
970 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
971 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
972 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ri as u32))),
973 },
974 (CmpValue::I64(li), CmpValue::U16(ru)) => match typ {
975 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ru as u32))),
976 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ru as u32))),
977 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ru as u32))),
978 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ru as u32))),
979 },
980 (CmpValue::I64(li), CmpValue::I16(ri)) => match typ {
981 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ri as u32))),
982 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
983 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
984 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ri as u32))),
985 },
986 (CmpValue::I64(li), CmpValue::U32(ru)) => match typ {
987 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ru))),
988 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ru))),
989 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ru))),
990 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ru))),
991 },
992 (CmpValue::I64(li), CmpValue::I32(ri)) => match typ {
993 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ri as u32))),
994 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
995 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
996 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ri as u32))),
997 },
998 (CmpValue::I64(li), CmpValue::U64(ru)) => match typ {
999 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ru as u32))),
1000 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ru as u32))),
1001 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ru as u32))),
1002 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ru as u32))),
1003 },
1004 (CmpValue::I64(li), CmpValue::I64(ri)) => match typ {
1005 CmpExprShift::Lsl => Ok(CmpValue::I64(li.wrapping_shl(ri as u32))),
1006 CmpExprShift::Lsr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
1007 CmpExprShift::Asr => Ok(CmpValue::I64(li.wrapping_shr(ri as u32))),
1008 CmpExprShift::Ror => Ok(CmpValue::I64(li.rotate_right(ri as u32))),
1009 },
1010 _ => {
1011 bail!("Cannot shift non-integral types");
1012 }
1013 }
1014 }
1015 CmpExpr::I16(i) => Ok(CmpValue::I16(*i)),
1016 CmpExpr::U32(u) => Ok(CmpValue::U32(*u)),
1017 CmpExpr::I32(i) => Ok(CmpValue::I32(*i)),
1018 _ => bail!("Unsupported expression {:?}", expr),
1019 }
1020 }
1021}
1022
1023pub(crate) struct Disassembler {
1024 decoder: InstDecoder,
1025 last: Option<Instruction>,
1026}
1027
1028impl Disassembler {
1029 pub fn new() -> Self {
1030 Self {
1031 decoder: InstDecoder::default(),
1032 last: None,
1033 }
1034 }
1035}
1036
1037impl Default for Disassembler {
1038 fn default() -> Self {
1039 Self::new()
1040 }
1041}
1042
1043impl TracerDisassembler for Disassembler {
1044 fn disassemble(&mut self, bytes: &[u8]) -> Result<()> {
1045 let mut r = U8Reader::new(bytes);
1046
1047 if let Ok(insn) = self.decoder.decode(&mut r) {
1048 self.last = Some(insn);
1049 } else {
1050 bail!("Could not disassemble {:?}", bytes);
1051 }
1052
1053 Ok(())
1054 }
1055
1056 fn disassemble_to_string(&mut self, bytes: &[u8]) -> Result<String> {
1057 let mut r = U8Reader::new(bytes);
1058
1059 if let Ok(insn) = self.decoder.decode(&mut r) {
1060 Ok(insn.to_string())
1061 } else {
1062 bail!("Could not disassemble {:?}", bytes);
1063 }
1064 }
1065
1066 fn last_was_control_flow(&self) -> bool {
1067 if let Some(last) = self.last.as_ref() {
1068 return matches!(last.opcode, Opcode::B);
1071 }
1072
1073 false
1074 }
1075
1076 fn last_was_call(&self) -> bool {
1081 if let Some(last) = self.last.as_ref() {
1082 return matches!(last.opcode, Opcode::BL | Opcode::BLX);
1083 }
1084
1085 false
1086 }
1087
1088 fn last_was_ret(&self) -> bool {
1090 if let Some(last) = self.last.as_ref() {
1091 if (last.opcode == Opcode::POP
1092 && last.operands.iter().any(|o| match o {
1093 Operand::Reg(r) => r.number() == 15,
1094 Operand::RegList(l) => l & (1 << 15) != 0,
1095 _ => false,
1096 }))
1097 || (last.opcode == Opcode::MOV
1098 && last
1099 .operands
1100 .first()
1101 .is_some_and(|f| matches!(f, Operand::Reg(r) if r.number() == 15)))
1102 {
1103 true
1104 } else {
1105 last.opcode == Opcode::BX
1106 }
1107 } else {
1108 false
1109 }
1110 }
1111
1112 fn last_was_cmp(&self) -> bool {
1113 if let Some(last) = self.last.as_ref() {
1114 return matches!(
1115 last.opcode,
1116 Opcode::CMN | Opcode::CMP | Opcode::TST | Opcode::TEQ
1117 );
1118 }
1119
1120 false
1121 }
1122
1123 fn cmp(&self) -> Vec<CmpExpr> {
1124 let mut cmp_exprs = Vec::new();
1125 if self.last_was_cmp() {
1126 if let Some(last) = self.last.as_ref() {
1127 for operand in &last.operands {
1128 match operand {
1129 Operand::Reg(r) => {
1130 cmp_exprs.push(CmpExpr::Reg((format!("r{}", r.number()), 0)));
1131 }
1132 Operand::RegWBack(r, _w) => {
1133 cmp_exprs.push(CmpExpr::Reg((format!("r{}", r.number()), 0)));
1134 }
1135 Operand::RegList(l) => {
1136 for i in 0..16 {
1137 if l & (1 << i) != 0 {
1138 cmp_exprs.push(CmpExpr::Reg((format!("r{}", i), 0)));
1139 }
1140 }
1141 }
1142 Operand::RegDeref(r) => {
1143 cmp_exprs.push(CmpExpr::Deref((
1144 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1145 None,
1146 )));
1147 }
1148 Operand::RegShift(rs) => match rs.into_shift() {
1149 RegShiftStyle::RegImm(r) => {
1150 let reg = r.shiftee();
1151 let imm = r.imm();
1152 let typ = match r.stype() {
1153 ShiftStyle::LSL => CmpExprShift::Lsl,
1154 ShiftStyle::LSR => CmpExprShift::Lsr,
1155 ShiftStyle::ASR => CmpExprShift::Asr,
1156 ShiftStyle::ROR => CmpExprShift::Ror,
1157 };
1158 cmp_exprs.push(CmpExpr::Shift((
1159 Box::new(CmpExpr::Reg((format!("r{}", reg.number()), 0))),
1160 Box::new(CmpExpr::U8(imm)),
1161 typ,
1162 )));
1163 }
1164 RegShiftStyle::RegReg(r) => {
1165 let shiftee = r.shiftee();
1166 let by = r.shifter();
1167 let typ = match r.stype() {
1168 ShiftStyle::LSL => CmpExprShift::Lsl,
1169 ShiftStyle::LSR => CmpExprShift::Lsr,
1170 ShiftStyle::ASR => CmpExprShift::Asr,
1171 ShiftStyle::ROR => CmpExprShift::Ror,
1172 };
1173 cmp_exprs.push(CmpExpr::Shift((
1174 Box::new(CmpExpr::Reg((format!("r{}", shiftee.number()), 0))),
1175 Box::new(CmpExpr::Reg((format!("r{}", by.number()), 0))),
1176 typ,
1177 )));
1178 }
1179 },
1180 Operand::RegDerefPostindexRegShift(r, _, _, _) => {
1181 cmp_exprs.push(CmpExpr::Deref((
1182 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1183 None,
1184 )));
1185 }
1186 Operand::RegDerefPreindexRegShift(r, rs, a, _) => match rs.into_shift() {
1187 RegShiftStyle::RegImm(ri) => {
1188 let reg = ri.shiftee();
1189 let imm = ri.imm();
1190 let typ = match ri.stype() {
1191 ShiftStyle::LSL => CmpExprShift::Lsl,
1192 ShiftStyle::LSR => CmpExprShift::Lsr,
1193 ShiftStyle::ASR => CmpExprShift::Asr,
1194 ShiftStyle::ROR => CmpExprShift::Ror,
1195 };
1196 cmp_exprs.push(CmpExpr::Deref((
1197 Box::new(CmpExpr::Add((
1198 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1199 Box::new(CmpExpr::Shift((
1200 Box::new(CmpExpr::Reg((
1201 format!("r{}", reg.number()),
1202 0,
1203 ))),
1204 Box::new(CmpExpr::U8(imm)),
1205 typ,
1206 ))),
1207 ))),
1208 None,
1209 )));
1210 }
1211 RegShiftStyle::RegReg(ri) => {
1212 let shiftee = ri.shiftee();
1213 let by = ri.shifter();
1214 let typ = match ri.stype() {
1215 ShiftStyle::LSL => CmpExprShift::Lsl,
1216 ShiftStyle::LSR => CmpExprShift::Lsr,
1217 ShiftStyle::ASR => CmpExprShift::Asr,
1218 ShiftStyle::ROR => CmpExprShift::Ror,
1219 };
1220 cmp_exprs.push(CmpExpr::Deref((
1221 if *a {
1222 Box::new(CmpExpr::Add((
1223 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1224 Box::new(CmpExpr::Shift((
1225 Box::new(CmpExpr::Reg((
1226 format!("r{}", shiftee.number()),
1227 0,
1228 ))),
1229 Box::new(CmpExpr::Reg((
1230 format!("r{}", by.number()),
1231 0,
1232 ))),
1233 typ,
1234 ))),
1235 )))
1236 } else {
1237 Box::new(CmpExpr::Sub((
1238 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1239 Box::new(CmpExpr::Shift((
1240 Box::new(CmpExpr::Reg((
1241 format!("r{}", shiftee.number()),
1242 0,
1243 ))),
1244 Box::new(CmpExpr::Reg((
1245 format!("r{}", by.number()),
1246 0,
1247 ))),
1248 typ,
1249 ))),
1250 )))
1251 },
1252 None,
1253 )));
1254 }
1255 },
1256 Operand::RegDerefPostindexOffset(r, _, _, _) => {
1257 cmp_exprs.push(CmpExpr::Deref((
1258 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1259 None,
1260 )));
1261 }
1262 Operand::RegDerefPreindexOffset(r, i, a, _) => {
1263 cmp_exprs.push(CmpExpr::Deref((
1264 if *a {
1265 Box::new(CmpExpr::Add((
1266 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1267 Box::new(CmpExpr::U16(*i)),
1268 )))
1269 } else {
1270 Box::new(CmpExpr::Sub((
1271 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1272 Box::new(CmpExpr::U16(*i)),
1273 )))
1274 },
1275 None,
1276 )))
1277 }
1278 Operand::RegDerefPostindexReg(r, _, _, _) => {
1279 cmp_exprs.push(CmpExpr::Deref((
1280 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1281 None,
1282 )));
1283 }
1284 Operand::RegDerefPreindexReg(r, i, a, _) => {
1285 cmp_exprs.push(CmpExpr::Deref((
1286 if *a {
1287 Box::new(CmpExpr::Add((
1288 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1289 Box::new(CmpExpr::Reg((format!("r{}", i.number()), 0))),
1290 )))
1291 } else {
1292 Box::new(CmpExpr::Sub((
1293 Box::new(CmpExpr::Reg((format!("r{}", r.number()), 0))),
1294 Box::new(CmpExpr::Reg((format!("r{}", i.number()), 0))),
1295 )))
1296 },
1297 None,
1298 )))
1299 }
1300 Operand::Imm12(i) => {
1301 cmp_exprs.push(CmpExpr::U16(*i));
1302 }
1303 Operand::Imm32(i) => {
1304 cmp_exprs.push(CmpExpr::U32(*i));
1305 }
1306 _ => {}
1307 }
1308 }
1309 }
1310 }
1311
1312 cmp_exprs
1313 }
1314
1315 fn cmp_type(&self) -> Vec<CmpType> {
1317 if self.last_was_cmp() {
1318 if let Some(last) = self.last.as_ref() {
1319 return match last.opcode {
1320 Opcode::CMP => vec![CmpType::Equal, CmpType::Lesser, CmpType::Greater],
1321 Opcode::CMN => vec![CmpType::Equal, CmpType::Lesser, CmpType::Greater],
1322 Opcode::TST => vec![CmpType::Equal, CmpType::Lesser, CmpType::Greater],
1323 Opcode::TEQ => vec![CmpType::Equal],
1324 _ => vec![],
1325 };
1326 }
1327 }
1328
1329 vec![]
1330 }
1331}