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