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