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