1use crate::term::{BV, Bool};
8use synth_synthesis::rules::{ArmOp, Operand2, Reg, VfpReg};
9
10pub struct ArmState {
14 pub registers: Vec<BV>,
16 pub flags: ConditionFlags,
18 pub vfp_registers: Vec<BV>,
20 pub memory: Vec<BV>,
22 pub locals: Vec<BV>,
24 pub globals: Vec<BV>,
26}
27
28pub struct ConditionFlags {
30 pub n: Bool, pub z: Bool, pub c: Bool, pub v: Bool, }
35
36impl ArmState {
37 pub fn new_symbolic() -> Self {
39 let registers = (0..16)
40 .map(|i| BV::new_const(format!("r{}", i), 32))
41 .collect();
42
43 let flags = ConditionFlags {
44 n: Bool::new_const("flag_n"),
45 z: Bool::new_const("flag_z"),
46 c: Bool::new_const("flag_c"),
47 v: Bool::new_const("flag_v"),
48 };
49
50 let memory = (0..256)
51 .map(|i| BV::new_const(format!("mem_{}", i), 32))
52 .collect();
53
54 let locals = (0..32)
55 .map(|i| BV::new_const(format!("local_{}", i), 32))
56 .collect();
57
58 let globals = (0..16)
59 .map(|i| BV::new_const(format!("global_{}", i), 32))
60 .collect();
61
62 let vfp_registers = (0..48)
63 .map(|i| BV::new_const(format!("vfp_{}", i), 32))
64 .collect();
65
66 Self {
67 registers,
68 flags,
69 vfp_registers,
70 memory,
71 locals,
72 globals,
73 }
74 }
75
76 pub fn get_reg(&self, reg: &Reg) -> &BV {
78 let index = reg_to_index(reg);
79 &self.registers[index]
80 }
81
82 pub fn set_reg(&mut self, reg: &Reg, value: BV) {
84 let index = reg_to_index(reg);
85 self.registers[index] = value;
86 }
87
88 pub fn get_vfp_reg(&self, reg: &VfpReg) -> &BV {
90 let index = vfp_reg_to_index(reg);
91 &self.vfp_registers[index]
92 }
93
94 pub fn set_vfp_reg(&mut self, reg: &VfpReg, value: BV) {
96 let index = vfp_reg_to_index(reg);
97 self.vfp_registers[index] = value;
98 }
99}
100
101fn reg_to_index(reg: &Reg) -> usize {
103 match reg {
104 Reg::R0 => 0,
105 Reg::R1 => 1,
106 Reg::R2 => 2,
107 Reg::R3 => 3,
108 Reg::R4 => 4,
109 Reg::R5 => 5,
110 Reg::R6 => 6,
111 Reg::R7 => 7,
112 Reg::R8 => 8,
113 Reg::R9 => 9,
114 Reg::R10 => 10,
115 Reg::R11 => 11,
116 Reg::R12 => 12,
117 Reg::SP => 13,
118 Reg::LR => 14,
119 Reg::PC => 15,
120 }
121}
122
123fn vfp_reg_to_index(reg: &VfpReg) -> usize {
125 match reg {
126 VfpReg::S0 => 0,
128 VfpReg::S1 => 1,
129 VfpReg::S2 => 2,
130 VfpReg::S3 => 3,
131 VfpReg::S4 => 4,
132 VfpReg::S5 => 5,
133 VfpReg::S6 => 6,
134 VfpReg::S7 => 7,
135 VfpReg::S8 => 8,
136 VfpReg::S9 => 9,
137 VfpReg::S10 => 10,
138 VfpReg::S11 => 11,
139 VfpReg::S12 => 12,
140 VfpReg::S13 => 13,
141 VfpReg::S14 => 14,
142 VfpReg::S15 => 15,
143 VfpReg::S16 => 16,
144 VfpReg::S17 => 17,
145 VfpReg::S18 => 18,
146 VfpReg::S19 => 19,
147 VfpReg::S20 => 20,
148 VfpReg::S21 => 21,
149 VfpReg::S22 => 22,
150 VfpReg::S23 => 23,
151 VfpReg::S24 => 24,
152 VfpReg::S25 => 25,
153 VfpReg::S26 => 26,
154 VfpReg::S27 => 27,
155 VfpReg::S28 => 28,
156 VfpReg::S29 => 29,
157 VfpReg::S30 => 30,
158 VfpReg::S31 => 31,
159 VfpReg::D0 => 32,
163 VfpReg::D1 => 33,
164 VfpReg::D2 => 34,
165 VfpReg::D3 => 35,
166 VfpReg::D4 => 36,
167 VfpReg::D5 => 37,
168 VfpReg::D6 => 38,
169 VfpReg::D7 => 39,
170 VfpReg::D8 => 40,
171 VfpReg::D9 => 41,
172 VfpReg::D10 => 42,
173 VfpReg::D11 => 43,
174 VfpReg::D12 => 44,
175 VfpReg::D13 => 45,
176 VfpReg::D14 => 46,
177 VfpReg::D15 => 47,
178 }
179}
180
181pub struct ArmSemantics;
185
186impl Default for ArmSemantics {
187 fn default() -> Self {
188 Self::new()
189 }
190}
191
192impl ArmSemantics {
193 pub fn new() -> Self {
195 Self
196 }
197
198 pub fn encode_op(&self, op: &ArmOp, state: &mut ArmState) {
202 match op {
203 ArmOp::Add { rd, rn, op2 } => {
204 let rn_val = state.get_reg(rn).clone();
205 let op2_val = self.evaluate_operand2(op2, state);
206 let result = rn_val.bvadd(&op2_val);
207 state.set_reg(rd, result);
208 }
209
210 ArmOp::Sub { rd, rn, op2 } => {
211 let rn_val = state.get_reg(rn).clone();
212 let op2_val = self.evaluate_operand2(op2, state);
213 let result = rn_val.bvsub(&op2_val);
214 state.set_reg(rd, result);
215 }
216
217 ArmOp::Mul { rd, rn, rm } => {
218 let rn_val = state.get_reg(rn).clone();
219 let rm_val = state.get_reg(rm).clone();
220 let result = rn_val.bvmul(&rm_val);
221 state.set_reg(rd, result);
222 }
223
224 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
225 let rn64 = state.get_reg(rn).zero_ext(32);
227 let rm64 = state.get_reg(rm).zero_ext(32);
228 let prod = rn64.bvmul(&rm64);
229 state.set_reg(rdlo, prod.extract(31, 0));
230 state.set_reg(rdhi, prod.extract(63, 32));
231 }
232
233 ArmOp::Sdiv { rd, rn, rm } => {
234 let rn_val = state.get_reg(rn).clone();
235 let rm_val = state.get_reg(rm).clone();
236 let result = rn_val.bvsdiv(&rm_val);
237 state.set_reg(rd, result);
238 }
239
240 ArmOp::Udiv { rd, rn, rm } => {
241 let rn_val = state.get_reg(rn).clone();
242 let rm_val = state.get_reg(rm).clone();
243 let result = rn_val.bvudiv(&rm_val);
244 state.set_reg(rd, result);
245 }
246
247 ArmOp::Mls { rd, rn, rm, ra } => {
248 let rn_val = state.get_reg(rn).clone();
251 let rm_val = state.get_reg(rm).clone();
252 let ra_val = state.get_reg(ra).clone();
253 let product = rn_val.bvmul(&rm_val);
254 let result = ra_val.bvsub(&product);
255 state.set_reg(rd, result);
256 }
257
258 ArmOp::And { rd, rn, op2 } => {
259 let rn_val = state.get_reg(rn).clone();
260 let op2_val = self.evaluate_operand2(op2, state);
261 let result = rn_val.bvand(&op2_val);
262 state.set_reg(rd, result);
263 }
264
265 ArmOp::Orr { rd, rn, op2 } => {
266 let rn_val = state.get_reg(rn).clone();
267 let op2_val = self.evaluate_operand2(op2, state);
268 let result = rn_val.bvor(&op2_val);
269 state.set_reg(rd, result);
270 }
271
272 ArmOp::Eor { rd, rn, op2 } => {
273 let rn_val = state.get_reg(rn).clone();
274 let op2_val = self.evaluate_operand2(op2, state);
275 let result = rn_val.bvxor(&op2_val);
276 state.set_reg(rd, result);
277 }
278
279 ArmOp::Lsl { rd, rn, shift } => {
280 let rn_val = state.get_reg(rn).clone();
281 let shift_val = BV::from_i64(*shift as i64, 32);
282 let result = rn_val.bvshl(&shift_val);
283 state.set_reg(rd, result);
284 }
285
286 ArmOp::Lsr { rd, rn, shift } => {
287 let rn_val = state.get_reg(rn).clone();
288 let shift_val = BV::from_i64(*shift as i64, 32);
289 let result = rn_val.bvlshr(&shift_val);
290 state.set_reg(rd, result);
291 }
292
293 ArmOp::Asr { rd, rn, shift } => {
294 let rn_val = state.get_reg(rn).clone();
295 let shift_val = BV::from_i64(*shift as i64, 32);
296 let result = rn_val.bvashr(&shift_val);
297 state.set_reg(rd, result);
298 }
299
300 ArmOp::Ror { rd, rn, shift } => {
301 let rn_val = state.get_reg(rn).clone();
304 let shift_val = BV::from_i64(*shift as i64, 32);
305 let result = rn_val.bvrotr(&shift_val);
306 state.set_reg(rd, result);
307 }
308
309 ArmOp::Mov { rd, op2 } => {
310 let op2_val = self.evaluate_operand2(op2, state);
311 state.set_reg(rd, op2_val);
312 }
313
314 ArmOp::Mvn { rd, op2 } => {
315 let op2_val = self.evaluate_operand2(op2, state);
316 let result = op2_val.bvnot();
317 state.set_reg(rd, result);
318 }
319
320 ArmOp::Cmp { rn, op2 } => {
321 let rn_val = state.get_reg(rn).clone();
324 let op2_val = self.evaluate_operand2(op2, state);
325
326 let result = rn_val.bvsub(&op2_val);
328
329 self.update_flags_sub(state, &rn_val, &op2_val, &result);
331 }
332
333 ArmOp::Clz { rd, rm } => {
334 let input = state.get_reg(rm).clone();
337 let result = self.encode_clz(&input);
338 state.set_reg(rd, result);
339 }
340
341 ArmOp::Rbit { rd, rm } => {
342 let input = state.get_reg(rm).clone();
345 let result = self.encode_rbit(&input);
346 state.set_reg(rd, result);
347 }
348
349 ArmOp::Popcnt { rd, rm } => {
350 let input = state.get_reg(rm).clone();
353 let result = self.encode_popcnt(&input);
354 state.set_reg(rd, result);
355 }
356
357 ArmOp::Nop => {
358 }
360
361 ArmOp::SetCond { rd, cond } => {
362 let cond_result = self.evaluate_condition(cond, &state.flags);
365 let result = self.bool_to_bv32(&cond_result);
366 state.set_reg(rd, result);
367 }
368
369 ArmOp::Select {
370 rd,
371 rval1,
372 rval2,
373 rcond,
374 } => {
375 let val1 = state.get_reg(rval1).clone();
378 let val2 = state.get_reg(rval2).clone();
379 let cond = state.get_reg(rcond).clone();
380 let zero = BV::from_i64(0, 32);
381 let cond_bool = cond.eq(&zero).not(); let result = cond_bool.ite(&val1, &val2);
383 state.set_reg(rd, result);
384 }
385
386 ArmOp::Ldr { rd, addr: _ } => {
388 let result = BV::new_const(format!("load_{:?}", rd), 32);
391 state.set_reg(rd, result);
392 }
393
394 ArmOp::Str { rd: _, addr: _ } => {
395 }
398
399 ArmOp::B { label: _ } => {
401 }
404
405 ArmOp::Bl { label: _ } => {
406 }
408
409 ArmOp::Bx { rm: _ } => {
410 }
412
413 ArmOp::LocalGet { rd, index } => {
415 let value = state
417 .locals
418 .get(*index as usize)
419 .cloned()
420 .unwrap_or_else(|| BV::new_const(format!("local_{}", index), 32));
421 state.set_reg(rd, value);
422 }
423
424 ArmOp::LocalSet { rs, index } => {
425 let value = state.get_reg(rs).clone();
427 if let Some(local) = state.locals.get_mut(*index as usize) {
428 *local = value;
429 }
430 }
431
432 ArmOp::LocalTee { rd, rs, index } => {
433 let value = state.get_reg(rs).clone();
435 if let Some(local) = state.locals.get_mut(*index as usize) {
436 *local = value.clone();
437 }
438 state.set_reg(rd, value);
439 }
440
441 ArmOp::GlobalGet { rd, index } => {
442 let value = state
444 .globals
445 .get(*index as usize)
446 .cloned()
447 .unwrap_or_else(|| BV::new_const(format!("global_{}", index), 32));
448 state.set_reg(rd, value);
449 }
450
451 ArmOp::GlobalSet { rs, index } => {
452 let value = state.get_reg(rs).clone();
454 if let Some(global) = state.globals.get_mut(*index as usize) {
455 *global = value;
456 }
457 }
458
459 ArmOp::BrTable {
460 rd,
461 index_reg,
462 targets,
463 default,
464 } => {
465 let _index = state.get_reg(index_reg).clone();
468 let result = BV::new_const(format!("br_table_{}_{}", targets.len(), default), 32);
469 state.set_reg(rd, result);
470 }
471
472 ArmOp::Call { rd, func_idx } => {
473 let result = BV::new_const(format!("call_{}", func_idx), 32);
475 state.set_reg(rd, result);
476 }
477
478 ArmOp::CallIndirect {
479 rd,
480 type_idx,
481 table_index_reg,
482 table_size: _,
485 } => {
486 let _table_index = state.get_reg(table_index_reg).clone();
488 let result = BV::new_const(format!("call_indirect_{}", type_idx), 32);
489 state.set_reg(rd, result);
490 }
491
492 ArmOp::I64Const { rdlo, rdhi, value } => {
498 let low32 = (*value as u32) as i64;
500 let high32 = *value >> 32;
501 state.set_reg(rdlo, BV::from_i64(low32, 32));
502 state.set_reg(rdhi, BV::from_i64(high32, 32));
503 }
504
505 ArmOp::I64Add {
506 rdlo,
507 rdhi,
508 rnlo,
509 rnhi,
510 rmlo,
511 rmhi,
512 } => {
513 let n_low = state.get_reg(rnlo).clone();
518 let m_low = state.get_reg(rmlo).clone();
519 let n_high = state.get_reg(rnhi).clone();
520 let m_high = state.get_reg(rmhi).clone();
521
522 let result_low = n_low.bvadd(&m_low);
524 state.set_reg(rdlo, result_low.clone());
525
526 let carry = result_low.bvult(&n_low);
529 let carry_bv = carry.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
530
531 let high_sum = n_high.bvadd(&m_high);
533 let result_high = high_sum.bvadd(&carry_bv);
534 state.set_reg(rdhi, result_high);
535 }
536
537 ArmOp::I64Eqz { rd, rnlo, rnhi } => {
538 let zero = BV::from_i64(0, 32);
541 let low_zero = state.get_reg(rnlo).eq(&zero);
542 let high_zero = state.get_reg(rnhi).eq(&zero);
543 let both_zero = Bool::and(&[&low_zero, &high_zero]);
544 let result = self.bool_to_bv32(&both_zero);
545 state.set_reg(rd, result);
546 }
547
548 ArmOp::I32WrapI64 { rd, rnlo } => {
549 let low_val = state.get_reg(rnlo).clone();
551 state.set_reg(rd, low_val);
552 }
553
554 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
555 let value = state.get_reg(rn).clone();
557 state.set_reg(rdlo, value.clone());
558
559 let sign_bit = value.extract(31, 31); let all_ones = BV::from_i64(-1, 32);
562 let zero = BV::from_i64(0, 32);
563 let high_val = sign_bit.eq(BV::from_i64(1, 1)).ite(&all_ones, &zero);
565 state.set_reg(rdhi, high_val);
566 }
567
568 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
569 let value = state.get_reg(rn).clone();
571 state.set_reg(rdlo, value);
572 state.set_reg(rdhi, BV::from_i64(0, 32));
574 }
575
576 ArmOp::I64Sub {
577 rdlo,
578 rdhi,
579 rnlo,
580 rnhi,
581 rmlo,
582 rmhi,
583 } => {
584 let n_low = state.get_reg(rnlo).clone();
589 let m_low = state.get_reg(rmlo).clone();
590 let n_high = state.get_reg(rnhi).clone();
591 let m_high = state.get_reg(rmhi).clone();
592
593 let result_low = n_low.bvsub(&m_low);
595 state.set_reg(rdlo, result_low.clone());
596
597 let borrow = n_low.bvult(&m_low);
599 let borrow_bv = borrow.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
600
601 let high_diff = n_high.bvsub(&m_high);
603 let result_high = high_diff.bvsub(&borrow_bv);
604 state.set_reg(rdhi, result_high);
605 }
606
607 ArmOp::I64Mul {
608 rd_lo,
609 rd_hi,
610 rn_lo,
611 rn_hi,
612 rm_lo,
613 rm_hi,
614 } => {
615 let a_lo = state.get_reg(rn_lo).clone();
621 let a_hi = state.get_reg(rn_hi).clone();
622 let b_lo = state.get_reg(rm_lo).clone();
623 let b_hi = state.get_reg(rm_hi).clone();
624
625 let lo_lo = a_lo.bvmul(&b_lo);
628 state.set_reg(rd_lo, lo_lo.clone());
629
630 let hi_lo = a_hi.bvmul(&b_lo); let lo_hi = a_lo.bvmul(&b_hi); let hi_sum = hi_lo.bvadd(&lo_hi);
644 state.set_reg(rd_hi, hi_sum);
645
646 }
652
653 ArmOp::I64DivS { rdlo, rdhi, .. } => {
660 state.set_reg(rdlo, BV::new_const("i64_divs_lo", 32));
664 state.set_reg(rdhi, BV::new_const("i64_divs_hi", 32));
665 }
666
667 ArmOp::I64DivU { rdlo, rdhi, .. } => {
668 state.set_reg(rdlo, BV::new_const("i64_divu_lo", 32));
672 state.set_reg(rdhi, BV::new_const("i64_divu_hi", 32));
673 }
674
675 ArmOp::I64RemS { rdlo, rdhi, .. } => {
676 state.set_reg(rdlo, BV::new_const("i64_rems_lo", 32));
680 state.set_reg(rdhi, BV::new_const("i64_rems_hi", 32));
681 }
682
683 ArmOp::I64RemU { rdlo, rdhi, .. } => {
684 state.set_reg(rdlo, BV::new_const("i64_remu_lo", 32));
688 state.set_reg(rdhi, BV::new_const("i64_remu_hi", 32));
689 }
690
691 ArmOp::I64And {
692 rdlo,
693 rdhi,
694 rnlo,
695 rnhi,
696 rmlo,
697 rmhi,
698 } => {
699 let n_low = state.get_reg(rnlo).clone();
700 let m_low = state.get_reg(rmlo).clone();
701 state.set_reg(rdlo, n_low.bvand(&m_low));
702
703 let n_high = state.get_reg(rnhi).clone();
704 let m_high = state.get_reg(rmhi).clone();
705 state.set_reg(rdhi, n_high.bvand(&m_high));
706 }
707
708 ArmOp::I64Or {
709 rdlo,
710 rdhi,
711 rnlo,
712 rnhi,
713 rmlo,
714 rmhi,
715 } => {
716 let n_low = state.get_reg(rnlo).clone();
717 let m_low = state.get_reg(rmlo).clone();
718 state.set_reg(rdlo, n_low.bvor(&m_low));
719
720 let n_high = state.get_reg(rnhi).clone();
721 let m_high = state.get_reg(rmhi).clone();
722 state.set_reg(rdhi, n_high.bvor(&m_high));
723 }
724
725 ArmOp::I64Xor {
726 rdlo,
727 rdhi,
728 rnlo,
729 rnhi,
730 rmlo,
731 rmhi,
732 } => {
733 let n_low = state.get_reg(rnlo).clone();
734 let m_low = state.get_reg(rmlo).clone();
735 state.set_reg(rdlo, n_low.bvxor(&m_low));
736
737 let n_high = state.get_reg(rnhi).clone();
738 let m_high = state.get_reg(rmhi).clone();
739 state.set_reg(rdhi, n_high.bvxor(&m_high));
740 }
741
742 ArmOp::I64Eq {
743 rd,
744 rnlo,
745 rnhi,
746 rmlo,
747 rmhi,
748 } => {
749 let n_low = state.get_reg(rnlo).clone();
750 let m_low = state.get_reg(rmlo).clone();
751 let n_high = state.get_reg(rnhi).clone();
752 let m_high = state.get_reg(rmhi).clone();
753
754 let low_eq = n_low.eq(&m_low);
755 let high_eq = n_high.eq(&m_high);
756 let both_eq = Bool::and(&[&low_eq, &high_eq]);
757 let result = self.bool_to_bv32(&both_eq);
758 state.set_reg(rd, result);
759 }
760
761 ArmOp::I64LtS {
762 rd,
763 rnlo,
764 rnhi,
765 rmlo,
766 rmhi,
767 } => {
768 let n_low = state.get_reg(rnlo).clone();
771 let m_low = state.get_reg(rmlo).clone();
772 let n_high = state.get_reg(rnhi).clone();
773 let m_high = state.get_reg(rmhi).clone();
774
775 let high_lt = n_high.bvslt(&m_high);
777 let high_eq = n_high.eq(&m_high);
778
779 let low_lt = n_low.bvult(&m_low);
781
782 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
784 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
785 let result = self.bool_to_bv32(&result_bool);
786 state.set_reg(rd, result);
787 }
788
789 ArmOp::I64LtU {
790 rd,
791 rnlo,
792 rnhi,
793 rmlo,
794 rmhi,
795 } => {
796 let n_low = state.get_reg(rnlo).clone();
799 let m_low = state.get_reg(rmlo).clone();
800 let n_high = state.get_reg(rnhi).clone();
801 let m_high = state.get_reg(rmhi).clone();
802
803 let high_lt = n_high.bvult(&m_high);
805 let high_eq = n_high.eq(&m_high);
806
807 let low_lt = n_low.bvult(&m_low);
809
810 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
812 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
813 let result = self.bool_to_bv32(&result_bool);
814 state.set_reg(rd, result);
815 }
816
817 ArmOp::I64Ne {
818 rd,
819 rnlo,
820 rnhi,
821 rmlo,
822 rmhi,
823 } => {
824 let n_low = state.get_reg(rnlo).clone();
826 let m_low = state.get_reg(rmlo).clone();
827 let n_high = state.get_reg(rnhi).clone();
828 let m_high = state.get_reg(rmhi).clone();
829
830 let low_eq = n_low.eq(&m_low);
831 let high_eq = n_high.eq(&m_high);
832 let both_eq = Bool::and(&[&low_eq, &high_eq]);
833 let not_eq = both_eq.not();
834 let result = self.bool_to_bv32(¬_eq);
835 state.set_reg(rd, result);
836 }
837
838 ArmOp::I64LeS {
839 rd,
840 rnlo,
841 rnhi,
842 rmlo,
843 rmhi,
844 } => {
845 let n_low = state.get_reg(rnlo).clone();
848 let m_low = state.get_reg(rmlo).clone();
849 let n_high = state.get_reg(rnhi).clone();
850 let m_high = state.get_reg(rmhi).clone();
851
852 let high_lt = n_high.bvslt(&m_high);
853 let high_eq = n_high.eq(&m_high);
854 let low_le = n_low.bvule(&m_low); let eq_and_le = Bool::and(&[&high_eq, &low_le]);
857 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
858 let result = self.bool_to_bv32(&result_bool);
859 state.set_reg(rd, result);
860 }
861
862 ArmOp::I64LeU {
863 rd,
864 rnlo,
865 rnhi,
866 rmlo,
867 rmhi,
868 } => {
869 let n_low = state.get_reg(rnlo).clone();
871 let m_low = state.get_reg(rmlo).clone();
872 let n_high = state.get_reg(rnhi).clone();
873 let m_high = state.get_reg(rmhi).clone();
874
875 let high_lt = n_high.bvult(&m_high);
876 let high_eq = n_high.eq(&m_high);
877 let low_le = n_low.bvule(&m_low);
878
879 let eq_and_le = Bool::and(&[&high_eq, &low_le]);
880 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
881 let result = self.bool_to_bv32(&result_bool);
882 state.set_reg(rd, result);
883 }
884
885 ArmOp::I64GtS {
886 rd,
887 rnlo,
888 rnhi,
889 rmlo,
890 rmhi,
891 } => {
892 let n_low = state.get_reg(rnlo).clone();
895 let m_low = state.get_reg(rmlo).clone();
896 let n_high = state.get_reg(rnhi).clone();
897 let m_high = state.get_reg(rmhi).clone();
898
899 let high_gt = n_high.bvsgt(&m_high);
900 let high_eq = n_high.eq(&m_high);
901 let low_gt = n_low.bvugt(&m_low); let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
904 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
905 let result = self.bool_to_bv32(&result_bool);
906 state.set_reg(rd, result);
907 }
908
909 ArmOp::I64GtU {
910 rd,
911 rnlo,
912 rnhi,
913 rmlo,
914 rmhi,
915 } => {
916 let n_low = state.get_reg(rnlo).clone();
918 let m_low = state.get_reg(rmlo).clone();
919 let n_high = state.get_reg(rnhi).clone();
920 let m_high = state.get_reg(rmhi).clone();
921
922 let high_gt = n_high.bvugt(&m_high);
923 let high_eq = n_high.eq(&m_high);
924 let low_gt = n_low.bvugt(&m_low);
925
926 let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
927 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
928 let result = self.bool_to_bv32(&result_bool);
929 state.set_reg(rd, result);
930 }
931
932 ArmOp::I64GeS {
933 rd,
934 rnlo,
935 rnhi,
936 rmlo,
937 rmhi,
938 } => {
939 let n_low = state.get_reg(rnlo).clone();
942 let m_low = state.get_reg(rmlo).clone();
943 let n_high = state.get_reg(rnhi).clone();
944 let m_high = state.get_reg(rmhi).clone();
945
946 let high_lt = n_high.bvslt(&m_high);
947 let high_eq = n_high.eq(&m_high);
948 let low_lt = n_low.bvult(&m_low);
949
950 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
951 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
952 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
954 state.set_reg(rd, result);
955 }
956
957 ArmOp::I64GeU {
958 rd,
959 rnlo,
960 rnhi,
961 rmlo,
962 rmhi,
963 } => {
964 let n_low = state.get_reg(rnlo).clone();
967 let m_low = state.get_reg(rmlo).clone();
968 let n_high = state.get_reg(rnhi).clone();
969 let m_high = state.get_reg(rmhi).clone();
970
971 let high_lt = n_high.bvult(&m_high);
972 let high_eq = n_high.eq(&m_high);
973 let low_lt = n_low.bvult(&m_low);
974
975 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
976 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
977 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
979 state.set_reg(rd, result);
980 }
981
982 ArmOp::I64Shl {
986 rd_lo,
987 rd_hi,
988 rn_lo,
989 rn_hi,
990 rm_lo,
991 rm_hi: _,
992 } => {
993 let n_lo = state.get_reg(rn_lo).clone();
996 let n_hi = state.get_reg(rn_hi).clone();
997 let shift_amt = state.get_reg(rm_lo).clone();
998
999 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1001
1002 let shift_32 = BV::from_i64(32, 32);
1005 let is_large = shift_mod.bvuge(&shift_32); let result_lo_small = n_lo.bvshl(&shift_mod);
1011 let shift_complement = shift_32.bvsub(&shift_mod);
1012 let bits_to_high = n_lo.bvlshr(&shift_complement);
1013 let result_hi_small = n_hi.bvshl(&shift_mod).bvor(&bits_to_high);
1014
1015 let zero = BV::from_i64(0, 32);
1019 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1020 let result_lo_large = zero.clone();
1021 let result_hi_large = n_lo.bvshl(&shift_minus_32);
1022
1023 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1025 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1026
1027 state.set_reg(rd_lo, result_lo);
1028 state.set_reg(rd_hi, result_hi);
1029 }
1030
1031 ArmOp::I64ShrU {
1032 rd_lo,
1033 rd_hi,
1034 rn_lo,
1035 rn_hi,
1036 rm_lo,
1037 rm_hi: _,
1038 } => {
1039 let n_lo = state.get_reg(rn_lo).clone();
1041 let n_hi = state.get_reg(rn_hi).clone();
1042 let shift_amt = state.get_reg(rm_lo).clone();
1043
1044 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1045 let shift_32 = BV::from_i64(32, 32);
1046 let is_large = shift_mod.bvuge(&shift_32);
1047
1048 let result_hi_small = n_hi.bvlshr(&shift_mod);
1052 let shift_complement = shift_32.bvsub(&shift_mod);
1053 let bits_to_low = n_hi.bvshl(&shift_complement);
1054 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1055
1056 let zero = BV::from_i64(0, 32);
1060 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1061 let result_hi_large = zero.clone();
1062 let result_lo_large = n_hi.bvlshr(&shift_minus_32);
1063
1064 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1065 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1066
1067 state.set_reg(rd_lo, result_lo);
1068 state.set_reg(rd_hi, result_hi);
1069 }
1070
1071 ArmOp::I64ShrS {
1072 rd_lo,
1073 rd_hi,
1074 rn_lo,
1075 rn_hi,
1076 rm_lo,
1077 rm_hi: _,
1078 } => {
1079 let n_lo = state.get_reg(rn_lo).clone();
1081 let n_hi = state.get_reg(rn_hi).clone();
1082 let shift_amt = state.get_reg(rm_lo).clone();
1083
1084 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1085 let shift_32 = BV::from_i64(32, 32);
1086 let is_large = shift_mod.bvuge(&shift_32);
1087
1088 let result_hi_small = n_hi.bvashr(&shift_mod);
1092 let shift_complement = shift_32.bvsub(&shift_mod);
1093 let bits_to_low = n_hi.bvshl(&shift_complement);
1094 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1095
1096 let shift_31 = BV::from_i64(31, 32);
1100 let result_hi_large = n_hi.bvashr(&shift_31);
1101 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1102 let result_lo_large = n_hi.bvashr(&shift_minus_32);
1103
1104 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1105 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1106
1107 state.set_reg(rd_lo, result_lo);
1108 state.set_reg(rd_hi, result_hi);
1109 }
1110
1111 ArmOp::I64Rotl {
1115 rdlo,
1116 rdhi,
1117 rnlo,
1118 rnhi,
1119 shift,
1120 } => {
1121 let n_lo = state.get_reg(rnlo).clone();
1124 let n_hi = state.get_reg(rnhi).clone();
1125 let shift_amt = state.get_reg(shift).clone();
1126
1127 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1129 let shift_32 = BV::from_i64(32, 32);
1130 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1136
1137 let lo_shifted_left = n_lo.bvshl(&shift_mod);
1138 let hi_bits_to_lo = n_hi.bvlshr(&shift_complement);
1139 let result_lo_small = lo_shifted_left.bvor(&hi_bits_to_lo);
1140
1141 let hi_shifted_left = n_hi.bvshl(&shift_mod);
1142 let lo_bits_to_hi = n_lo.bvlshr(&shift_complement);
1143 let result_hi_small = hi_shifted_left.bvor(&lo_bits_to_hi);
1144
1145 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1148 let complement_large = shift_32.bvsub(&shift_minus_32);
1149
1150 let hi_shifted_left_large = n_hi.bvshl(&shift_minus_32);
1151 let lo_bits_to_hi_large = n_lo.bvlshr(&complement_large);
1152 let result_lo_large = hi_shifted_left_large.bvor(&lo_bits_to_hi_large);
1153
1154 let lo_shifted_left_large = n_lo.bvshl(&shift_minus_32);
1155 let hi_bits_to_lo_large = n_hi.bvlshr(&complement_large);
1156 let result_hi_large = lo_shifted_left_large.bvor(&hi_bits_to_lo_large);
1157
1158 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1160 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1161
1162 state.set_reg(rdlo, result_lo);
1163 state.set_reg(rdhi, result_hi);
1164 }
1165
1166 ArmOp::I64Rotr {
1167 rdlo,
1168 rdhi,
1169 rnlo,
1170 rnhi,
1171 shift,
1172 } => {
1173 let n_lo = state.get_reg(rnlo).clone();
1176 let n_hi = state.get_reg(rnhi).clone();
1177 let shift_amt = state.get_reg(shift).clone();
1178
1179 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1181 let shift_32 = BV::from_i64(32, 32);
1182 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1188
1189 let lo_shifted_right = n_lo.bvlshr(&shift_mod);
1190 let hi_bits_to_lo = n_hi.bvshl(&shift_complement);
1191 let result_lo_small = lo_shifted_right.bvor(&hi_bits_to_lo);
1192
1193 let hi_shifted_right = n_hi.bvlshr(&shift_mod);
1194 let lo_bits_to_hi = n_lo.bvshl(&shift_complement);
1195 let result_hi_small = hi_shifted_right.bvor(&lo_bits_to_hi);
1196
1197 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1200 let complement_large = shift_32.bvsub(&shift_minus_32);
1201
1202 let hi_shifted_right_large = n_hi.bvlshr(&shift_minus_32);
1203 let lo_bits_to_hi_large = n_lo.bvshl(&complement_large);
1204 let result_lo_large = hi_shifted_right_large.bvor(&lo_bits_to_hi_large);
1205
1206 let lo_shifted_right_large = n_lo.bvlshr(&shift_minus_32);
1207 let hi_bits_to_lo_large = n_hi.bvshl(&complement_large);
1208 let result_hi_large = lo_shifted_right_large.bvor(&hi_bits_to_lo_large);
1209
1210 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1212 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1213
1214 state.set_reg(rdlo, result_lo);
1215 state.set_reg(rdhi, result_hi);
1216 }
1217
1218 ArmOp::I64Clz { rd, rnlo, rnhi } => {
1219 let n_lo = state.get_reg(rnlo).clone();
1223 let n_hi = state.get_reg(rnhi).clone();
1224
1225 let hi_clz = self.encode_clz(&n_hi);
1226 let lo_clz = self.encode_clz(&n_lo);
1227
1228 let thirty_two = BV::from_i64(32, 32);
1230 let hi_is_zero = hi_clz.eq(&thirty_two);
1231 let result = hi_is_zero.ite(
1232 thirty_two.bvadd(&lo_clz), &hi_clz, );
1235 state.set_reg(rd, result);
1236 }
1237
1238 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
1239 let n_lo = state.get_reg(rnlo).clone();
1243 let n_hi = state.get_reg(rnhi).clone();
1244
1245 let lo_ctz = self.encode_ctz(&n_lo);
1246 let hi_ctz = self.encode_ctz(&n_hi);
1247
1248 let thirty_two = BV::from_i64(32, 32);
1250 let lo_is_zero = lo_ctz.eq(&thirty_two);
1251 let result = lo_is_zero.ite(
1252 thirty_two.bvadd(&hi_ctz), &lo_ctz, );
1255 state.set_reg(rd, result);
1256 }
1257
1258 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
1259 let n_lo = state.get_reg(rnlo).clone();
1262 let n_hi = state.get_reg(rnhi).clone();
1263
1264 let lo_popcnt = self.encode_popcnt(&n_lo);
1265 let hi_popcnt = self.encode_popcnt(&n_hi);
1266
1267 let result = lo_popcnt.bvadd(&hi_popcnt);
1268 state.set_reg(rd, result);
1269 }
1270
1271 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
1275 let result_lo = BV::new_const(format!("i64load_lo_{:?}", addr), 32);
1279 let result_hi = BV::new_const(format!("i64load_hi_{:?}", addr), 32);
1280 state.set_reg(rdlo, result_lo);
1281 state.set_reg(rdhi, result_hi);
1282 }
1283
1284 ArmOp::I64Str {
1285 rdlo: _,
1286 rdhi: _,
1287 addr: _,
1288 } => {
1289 }
1294
1295 ArmOp::F32Const { sd, value } => {
1304 let bits = value.to_bits() as i64;
1307 let bv_val = BV::from_i64(bits, 32);
1308 state.set_vfp_reg(sd, bv_val);
1309 }
1310
1311 ArmOp::F32Add { sd, sn, sm } => {
1313 let result = BV::new_const(format!("f32_add_{:?}_{:?}", sn, sm), 32);
1317 state.set_vfp_reg(sd, result);
1318 }
1319
1320 ArmOp::F32Sub { sd, sn, sm } => {
1321 let result = BV::new_const(format!("f32_sub_{:?}_{:?}", sn, sm), 32);
1323 state.set_vfp_reg(sd, result);
1324 }
1325
1326 ArmOp::F32Mul { sd, sn, sm } => {
1327 let result = BV::new_const(format!("f32_mul_{:?}_{:?}", sn, sm), 32);
1329 state.set_vfp_reg(sd, result);
1330 }
1331
1332 ArmOp::F32Div { sd, sn, sm } => {
1333 let result = BV::new_const(format!("f32_div_{:?}_{:?}", sn, sm), 32);
1335 state.set_vfp_reg(sd, result);
1336 }
1337
1338 ArmOp::F32Abs { sd, sm } => {
1340 let val = state.get_vfp_reg(sm).clone();
1343 let mask = BV::from_u64(0x7FFFFFFF, 32); let result = val.bvand(&mask);
1345 state.set_vfp_reg(sd, result);
1346 }
1347
1348 ArmOp::F32Neg { sd, sm } => {
1349 let val = state.get_vfp_reg(sm).clone();
1352 let mask = BV::from_u64(0x80000000, 32); let result = val.bvxor(&mask);
1354 state.set_vfp_reg(sd, result);
1355 }
1356
1357 ArmOp::F32Sqrt { sd, sm } => {
1358 let result = BV::new_const(format!("f32_sqrt_{:?}", sm), 32);
1361 state.set_vfp_reg(sd, result);
1362 }
1363
1364 ArmOp::F32Min { sd, sn, sm } => {
1365 let result = BV::new_const(format!("f32_min_{:?}_{:?}", sn, sm), 32);
1369 state.set_vfp_reg(sd, result);
1370 }
1371
1372 ArmOp::F32Max { sd, sn, sm } => {
1373 let result = BV::new_const(format!("f32_max_{:?}_{:?}", sn, sm), 32);
1377 state.set_vfp_reg(sd, result);
1378 }
1379
1380 ArmOp::F32Copysign { sd, sn, sm } => {
1381 let val_n = state.get_vfp_reg(sn).clone();
1384 let val_m = state.get_vfp_reg(sm).clone();
1385
1386 let mag_mask = BV::from_u64(0x7FFFFFFF, 32);
1388 let magnitude = val_n.bvand(&mag_mask);
1389
1390 let sign_mask = BV::from_u64(0x80000000, 32);
1392 let sign = val_m.bvand(&sign_mask);
1393
1394 let result = magnitude.bvor(&sign);
1396 state.set_vfp_reg(sd, result);
1397 }
1398
1399 ArmOp::F32Load { sd, addr } => {
1400 let result = BV::new_const(format!("f32_load_{:?}", addr), 32);
1403 state.set_vfp_reg(sd, result);
1404 }
1405
1406 ArmOp::F32Eq { rd, sn, sm } => {
1408 let result = BV::new_const(format!("f32_eq_{:?}_{:?}", sn, sm), 32);
1411 state.set_reg(rd, result);
1412 }
1413
1414 ArmOp::F32Ne { rd, sn, sm } => {
1415 let result = BV::new_const(format!("f32_ne_{:?}_{:?}", sn, sm), 32);
1417 state.set_reg(rd, result);
1418 }
1419
1420 ArmOp::F32Lt { rd, sn, sm } => {
1421 let result = BV::new_const(format!("f32_lt_{:?}_{:?}", sn, sm), 32);
1423 state.set_reg(rd, result);
1424 }
1425
1426 ArmOp::F32Le { rd, sn, sm } => {
1427 let result = BV::new_const(format!("f32_le_{:?}_{:?}", sn, sm), 32);
1429 state.set_reg(rd, result);
1430 }
1431
1432 ArmOp::F32Gt { rd, sn, sm } => {
1433 let result = BV::new_const(format!("f32_gt_{:?}_{:?}", sn, sm), 32);
1435 state.set_reg(rd, result);
1436 }
1437
1438 ArmOp::F32Ge { rd, sn, sm } => {
1439 let result = BV::new_const(format!("f32_ge_{:?}_{:?}", sn, sm), 32);
1441 state.set_reg(rd, result);
1442 }
1443
1444 ArmOp::F32Store { sd, addr } => {
1445 let _val = state.get_vfp_reg(sd);
1450 let _addr_str = format!("{:?}", addr);
1451 }
1453
1454 ArmOp::F32Ceil { sd, sm } => {
1456 let result = BV::new_const(format!("f32_ceil_{:?}", sm), 32);
1459 state.set_vfp_reg(sd, result);
1460 }
1461
1462 ArmOp::F32Floor { sd, sm } => {
1463 let result = BV::new_const(format!("f32_floor_{:?}", sm), 32);
1466 state.set_vfp_reg(sd, result);
1467 }
1468
1469 ArmOp::F32Trunc { sd, sm } => {
1470 let result = BV::new_const(format!("f32_trunc_{:?}", sm), 32);
1473 state.set_vfp_reg(sd, result);
1474 }
1475
1476 ArmOp::F32Nearest { sd, sm } => {
1477 let result = BV::new_const(format!("f32_nearest_{:?}", sm), 32);
1480 state.set_vfp_reg(sd, result);
1481 }
1482
1483 ArmOp::F32ConvertI32S { sd, rm } => {
1485 let int_val = state.get_reg(rm);
1487 let result = BV::new_const(format!("f32_convert_i32s_{:?}", int_val), 32);
1488 state.set_vfp_reg(sd, result);
1489 }
1490
1491 ArmOp::F32ConvertI32U { sd, rm } => {
1492 let int_val = state.get_reg(rm);
1494 let result = BV::new_const(format!("f32_convert_i32u_{:?}", int_val), 32);
1495 state.set_vfp_reg(sd, result);
1496 }
1497
1498 ArmOp::F32ConvertI64S { sd, rmlo, rmhi } => {
1499 let lo = state.get_reg(rmlo);
1501 let hi = state.get_reg(rmhi);
1502 let result = BV::new_const(format!("f32_convert_i64s_{:?}_{:?}", lo, hi), 32);
1503 state.set_vfp_reg(sd, result);
1504 }
1505
1506 ArmOp::F32ConvertI64U { sd, rmlo, rmhi } => {
1507 let lo = state.get_reg(rmlo);
1509 let hi = state.get_reg(rmhi);
1510 let result = BV::new_const(format!("f32_convert_i64u_{:?}_{:?}", lo, hi), 32);
1511 state.set_vfp_reg(sd, result);
1512 }
1513
1514 ArmOp::F32ReinterpretI32 { sd, rm } => {
1516 let bits = state.get_reg(rm).clone();
1519 state.set_vfp_reg(sd, bits);
1520 }
1521
1522 ArmOp::I32ReinterpretF32 { rd, sm } => {
1523 let bits = state.get_vfp_reg(sm).clone();
1526 state.set_reg(rd, bits);
1527 }
1528
1529 ArmOp::F64Add { dd, dn, dm } => {
1535 let result = BV::new_const(format!("f64_add_{:?}_{:?}", dn, dm), 64);
1539 state.set_vfp_reg(dd, result);
1540 }
1541
1542 ArmOp::F64Sub { dd, dn, dm } => {
1543 let result = BV::new_const(format!("f64_sub_{:?}_{:?}", dn, dm), 64);
1545 state.set_vfp_reg(dd, result);
1546 }
1547
1548 ArmOp::F64Mul { dd, dn, dm } => {
1549 let result = BV::new_const(format!("f64_mul_{:?}_{:?}", dn, dm), 64);
1551 state.set_vfp_reg(dd, result);
1552 }
1553
1554 ArmOp::F64Div { dd, dn, dm } => {
1555 let result = BV::new_const(format!("f64_div_{:?}_{:?}", dn, dm), 64);
1557 state.set_vfp_reg(dd, result);
1558 }
1559
1560 ArmOp::F64Abs { dd, dm } => {
1562 let val = state.get_vfp_reg(dm).clone();
1565 let mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64); let result = val.bvand(&mask);
1567 state.set_vfp_reg(dd, result);
1568 }
1569
1570 ArmOp::F64Neg { dd, dm } => {
1571 let val = state.get_vfp_reg(dm).clone();
1574 let mask = BV::from_u64(0x8000000000000000, 64); let result = val.bvxor(&mask);
1576 state.set_vfp_reg(dd, result);
1577 }
1578
1579 ArmOp::F64Sqrt { dd, dm } => {
1580 let result = BV::new_const(format!("f64_sqrt_{:?}", dm), 64);
1583 state.set_vfp_reg(dd, result);
1584 }
1585
1586 ArmOp::F64Min { dd, dn, dm } => {
1587 let result = BV::new_const(format!("f64_min_{:?}_{:?}", dn, dm), 64);
1591 state.set_vfp_reg(dd, result);
1592 }
1593
1594 ArmOp::F64Max { dd, dn, dm } => {
1595 let result = BV::new_const(format!("f64_max_{:?}_{:?}", dn, dm), 64);
1599 state.set_vfp_reg(dd, result);
1600 }
1601
1602 ArmOp::F64Copysign { dd, dn, dm } => {
1603 let val_n = state.get_vfp_reg(dn).clone();
1606 let val_m = state.get_vfp_reg(dm).clone();
1607
1608 let mag_mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64);
1610 let magnitude = val_n.bvand(&mag_mask);
1611
1612 let sign_mask = BV::from_u64(0x8000000000000000, 64);
1614 let sign = val_m.bvand(&sign_mask);
1615
1616 let result = magnitude.bvor(&sign);
1618 state.set_vfp_reg(dd, result);
1619 }
1620
1621 ArmOp::F64Ceil { dd, dm } => {
1623 let result = BV::new_const(format!("f64_ceil_{:?}", dm), 64);
1625 state.set_vfp_reg(dd, result);
1626 }
1627
1628 ArmOp::F64Floor { dd, dm } => {
1629 let result = BV::new_const(format!("f64_floor_{:?}", dm), 64);
1631 state.set_vfp_reg(dd, result);
1632 }
1633
1634 ArmOp::F64Trunc { dd, dm } => {
1635 let result = BV::new_const(format!("f64_trunc_{:?}", dm), 64);
1637 state.set_vfp_reg(dd, result);
1638 }
1639
1640 ArmOp::F64Nearest { dd, dm } => {
1641 let result = BV::new_const(format!("f64_nearest_{:?}", dm), 64);
1643 state.set_vfp_reg(dd, result);
1644 }
1645
1646 ArmOp::F64Load { dd, addr } => {
1648 let result = BV::new_const(format!("f64_load_{:?}", addr), 64);
1651 state.set_vfp_reg(dd, result);
1652 }
1653
1654 ArmOp::F64Store { dd: _, addr: _ } => {
1655 }
1659
1660 ArmOp::F64Const { dd, value } => {
1661 let bits = value.to_bits() as i64;
1663 let result = BV::from_i64(bits, 64);
1664 state.set_vfp_reg(dd, result);
1665 }
1666
1667 ArmOp::F64Eq { rd, dn, dm } => {
1669 let result = BV::new_const(format!("f64_eq_{:?}_{:?}", dn, dm), 32);
1672 state.set_reg(rd, result);
1673 }
1674
1675 ArmOp::F64Ne { rd, dn, dm } => {
1676 let result = BV::new_const(format!("f64_ne_{:?}_{:?}", dn, dm), 32);
1678 state.set_reg(rd, result);
1679 }
1680
1681 ArmOp::F64Lt { rd, dn, dm } => {
1682 let result = BV::new_const(format!("f64_lt_{:?}_{:?}", dn, dm), 32);
1684 state.set_reg(rd, result);
1685 }
1686
1687 ArmOp::F64Le { rd, dn, dm } => {
1688 let result = BV::new_const(format!("f64_le_{:?}_{:?}", dn, dm), 32);
1690 state.set_reg(rd, result);
1691 }
1692
1693 ArmOp::F64Gt { rd, dn, dm } => {
1694 let result = BV::new_const(format!("f64_gt_{:?}_{:?}", dn, dm), 32);
1696 state.set_reg(rd, result);
1697 }
1698
1699 ArmOp::F64Ge { rd, dn, dm } => {
1700 let result = BV::new_const(format!("f64_ge_{:?}_{:?}", dn, dm), 32);
1702 state.set_reg(rd, result);
1703 }
1704
1705 ArmOp::F64ConvertI32S { dd, rm } => {
1707 let result = BV::new_const(format!("f64_convert_i32s_{:?}", rm), 64);
1710 state.set_vfp_reg(dd, result);
1711 }
1712
1713 ArmOp::F64ConvertI32U { dd, rm } => {
1714 let result = BV::new_const(format!("f64_convert_i32u_{:?}", rm), 64);
1717 state.set_vfp_reg(dd, result);
1718 }
1719
1720 ArmOp::F64ConvertI64S {
1721 dd,
1722 rmlo: _,
1723 rmhi: _,
1724 } => {
1725 let result = BV::new_const("f64_convert_i64s_result", 64);
1728 state.set_vfp_reg(dd, result);
1729 }
1730
1731 ArmOp::F64ConvertI64U {
1732 dd,
1733 rmlo: _,
1734 rmhi: _,
1735 } => {
1736 let result = BV::new_const("f64_convert_i64u_result", 64);
1739 state.set_vfp_reg(dd, result);
1740 }
1741
1742 ArmOp::F64PromoteF32 { dd, sm } => {
1743 let result = BV::new_const(format!("f64_promote_f32_{:?}", sm), 64);
1746 state.set_vfp_reg(dd, result);
1747 }
1748
1749 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
1750 let lo = state.get_reg(rmlo).clone();
1753 let hi = state.get_reg(rmhi).clone();
1754
1755 let lo_64 = lo.zero_ext(32); let hi_64 = hi.zero_ext(32);
1758 let shift_32 = BV::from_u64(32, 64);
1759 let hi_shifted = hi_64.bvshl(&shift_32);
1760 let result = hi_shifted.bvor(&lo_64);
1761
1762 state.set_vfp_reg(dd, result);
1763 }
1764
1765 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
1766 let bits = state.get_vfp_reg(dm).clone();
1769
1770 let lo = bits.extract(31, 0);
1772 state.set_reg(rdlo, lo);
1773
1774 let hi = bits.extract(63, 32);
1776 state.set_reg(rdhi, hi);
1777 }
1778
1779 ArmOp::I64TruncF64S {
1780 rdlo: _,
1781 rdhi: _,
1782 dm: _,
1783 } => {
1784 }
1788
1789 ArmOp::I64TruncF64U {
1790 rdlo: _,
1791 rdhi: _,
1792 dm: _,
1793 } => {
1794 }
1798
1799 ArmOp::I32TruncF64S { rd, dm } => {
1800 let result = BV::new_const(format!("i32_trunc_f64s_{:?}", dm), 32);
1803 state.set_reg(rd, result);
1804 }
1805
1806 ArmOp::I32TruncF64U { rd, dm } => {
1807 let result = BV::new_const(format!("i32_trunc_f64u_{:?}", dm), 32);
1810 state.set_reg(rd, result);
1811 }
1812
1813 _ => {
1814 }
1816 }
1817 }
1818
1819 fn evaluate_operand2(&self, op2: &Operand2, state: &ArmState) -> BV {
1821 match op2 {
1822 Operand2::Imm(value) => BV::from_i64(*value as i64, 32),
1823 Operand2::Reg(reg) => state.get_reg(reg).clone(),
1824 Operand2::RegShift { rm, shift, amount } => {
1825 let reg_val = state.get_reg(rm).clone();
1826 let shift_amount = BV::from_i64(*amount as i64, 32);
1827
1828 match shift {
1829 synth_synthesis::ShiftType::LSL => reg_val.bvshl(&shift_amount),
1830 synth_synthesis::ShiftType::LSR => reg_val.bvlshr(&shift_amount),
1831 synth_synthesis::ShiftType::ASR => reg_val.bvashr(&shift_amount),
1832 synth_synthesis::ShiftType::ROR => reg_val.bvrotr(&shift_amount),
1833 }
1834 }
1835 }
1836 }
1837
1838 pub fn extract_result(&self, state: &ArmState, reg: &Reg) -> BV {
1840 state.get_reg(reg).clone()
1841 }
1842
1843 fn encode_clz(&self, input: &BV) -> BV {
1848 let zero = BV::from_i64(0, 32);
1849
1850 let all_zero = input.eq(&zero);
1852 let result_if_zero = BV::from_i64(32, 32);
1853
1854 let mut count = BV::from_i64(0, 32);
1856 let mut remaining = input.clone();
1857
1858 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1860 let top_16 = remaining.bvand(&mask_16);
1861 let top_16_zero = top_16.eq(&zero);
1862
1863 count = top_16_zero.ite(count.bvadd(BV::from_i64(16, 32)), &count);
1864 remaining = top_16_zero.ite(remaining.bvshl(BV::from_i64(16, 32)), &remaining);
1865
1866 let mask_8 = BV::from_u64(0xFF000000, 32);
1868 let top_8 = remaining.bvand(&mask_8);
1869 let top_8_zero = top_8.eq(&zero);
1870
1871 count = top_8_zero.ite(count.bvadd(BV::from_i64(8, 32)), &count);
1872 remaining = top_8_zero.ite(remaining.bvshl(BV::from_i64(8, 32)), &remaining);
1873
1874 let mask_4 = BV::from_u64(0xF0000000, 32);
1876 let top_4 = remaining.bvand(&mask_4);
1877 let top_4_zero = top_4.eq(&zero);
1878
1879 count = top_4_zero.ite(count.bvadd(BV::from_i64(4, 32)), &count);
1880 remaining = top_4_zero.ite(remaining.bvshl(BV::from_i64(4, 32)), &remaining);
1881
1882 let mask_2 = BV::from_u64(0xC0000000, 32);
1884 let top_2 = remaining.bvand(&mask_2);
1885 let top_2_zero = top_2.eq(&zero);
1886
1887 count = top_2_zero.ite(count.bvadd(BV::from_i64(2, 32)), &count);
1888 remaining = top_2_zero.ite(remaining.bvshl(BV::from_i64(2, 32)), &remaining);
1889
1890 let mask_1 = BV::from_u64(0x80000000, 32);
1892 let top_1 = remaining.bvand(&mask_1);
1893 let top_1_zero = top_1.eq(&zero);
1894
1895 count = top_1_zero.ite(count.bvadd(BV::from_i64(1, 32)), &count);
1896
1897 all_zero.ite(&result_if_zero, &count)
1899 }
1900
1901 fn encode_ctz(&self, input: &BV) -> BV {
1907 let reversed = self.encode_rbit(input);
1909 self.encode_clz(&reversed)
1910 }
1911
1912 fn encode_rbit(&self, input: &BV) -> BV {
1917 let mut result = input.clone();
1919
1920 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1922 let top_16 = result.bvand(&mask_16).bvlshr(BV::from_i64(16, 32));
1923 let bottom_16 = result.bvshl(BV::from_i64(16, 32));
1924 result = top_16.bvor(&bottom_16);
1925
1926 let mask_8_top = BV::from_u64(0xFF00FF00, 32);
1928 let mask_8_bottom = BV::from_u64(0x00FF00FF, 32);
1929 let top_8 = result.bvand(&mask_8_top).bvlshr(BV::from_i64(8, 32));
1930 let bottom_8 = result.bvand(&mask_8_bottom).bvshl(BV::from_i64(8, 32));
1931 result = top_8.bvor(&bottom_8);
1932
1933 let mask_4_top = BV::from_u64(0xF0F0F0F0, 32);
1935 let mask_4_bottom = BV::from_u64(0x0F0F0F0F, 32);
1936 let top_4 = result.bvand(&mask_4_top).bvlshr(BV::from_i64(4, 32));
1937 let bottom_4 = result.bvand(&mask_4_bottom).bvshl(BV::from_i64(4, 32));
1938 result = top_4.bvor(&bottom_4);
1939
1940 let mask_2_top = BV::from_u64(0xCCCCCCCC, 32);
1942 let mask_2_bottom = BV::from_u64(0x33333333, 32);
1943 let top_2 = result.bvand(&mask_2_top).bvlshr(BV::from_i64(2, 32));
1944 let bottom_2 = result.bvand(&mask_2_bottom).bvshl(BV::from_i64(2, 32));
1945 result = top_2.bvor(&bottom_2);
1946
1947 let mask_1_top = BV::from_u64(0xAAAAAAAA, 32);
1949 let mask_1_bottom = BV::from_u64(0x55555555, 32);
1950 let top_1 = result.bvand(&mask_1_top).bvlshr(BV::from_i64(1, 32));
1951 let bottom_1 = result.bvand(&mask_1_bottom).bvshl(BV::from_i64(1, 32));
1952 result = top_1.bvor(&bottom_1);
1953
1954 result
1955 }
1956
1957 fn update_flags_sub(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
1969 let zero = BV::from_i64(0, 32);
1970
1971 let sign_bit = result.extract(31, 31);
1973 let one_bit = BV::from_i64(1, 1);
1974 state.flags.n = sign_bit.eq(&one_bit);
1975
1976 state.flags.z = result.eq(&zero);
1978
1979 state.flags.c = a.bvuge(b);
1983
1984 let a_sign = a.extract(31, 31);
1990 let b_sign = b.extract(31, 31);
1991 let r_sign = result.extract(31, 31);
1992
1993 let signs_differ = a_sign.eq(&b_sign).not(); let result_sign_wrong = a_sign.eq(&r_sign).not(); state.flags.v = Bool::and(&[&signs_differ, &result_sign_wrong]);
1996 }
1997
1998 #[allow(dead_code)]
2004 fn update_flags_add(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
2005 let zero = BV::from_i64(0, 32);
2006
2007 let sign_bit = result.extract(31, 31);
2009 let one_bit = BV::from_i64(1, 1);
2010 state.flags.n = sign_bit.eq(&one_bit);
2011
2012 state.flags.z = result.eq(&zero);
2014
2015 state.flags.c = result.bvult(a);
2019
2020 let a_sign = a.extract(31, 31);
2026 let b_sign = b.extract(31, 31);
2027 let r_sign = result.extract(31, 31);
2028
2029 let signs_same = a_sign.eq(&b_sign); let result_sign_wrong = a_sign.eq(&r_sign).not(); state.flags.v = Bool::and(&[&signs_same, &result_sign_wrong]);
2032 }
2033
2034 fn evaluate_condition(
2048 &self,
2049 cond: &synth_synthesis::rules::Condition,
2050 flags: &ConditionFlags,
2051 ) -> Bool {
2052 use synth_synthesis::rules::Condition;
2053
2054 match cond {
2055 Condition::EQ => flags.z.clone(),
2056 Condition::NE => flags.z.not(),
2057 Condition::LT => {
2058 flags.n.eq(&flags.v).not()
2060 }
2061 Condition::LE => {
2062 let n_ne_v = flags.n.eq(&flags.v).not();
2064 Bool::or(&[&flags.z, &n_ne_v])
2065 }
2066 Condition::GT => {
2067 let z_zero = flags.z.not();
2069 let n_eq_v = flags.n.eq(&flags.v);
2070 Bool::and(&[&z_zero, &n_eq_v])
2071 }
2072 Condition::GE => {
2073 flags.n.eq(&flags.v)
2075 }
2076 Condition::LO => {
2077 flags.c.not()
2079 }
2080 Condition::LS => {
2081 let c_zero = flags.c.not();
2083 Bool::or(&[&flags.z, &c_zero])
2084 }
2085 Condition::HI => {
2086 let z_zero = flags.z.not();
2088 Bool::and(&[&flags.c, &z_zero])
2089 }
2090 Condition::HS => {
2091 flags.c.clone()
2093 }
2094 }
2095 }
2096
2097 fn bool_to_bv32(&self, cond: &Bool) -> BV {
2099 let zero = BV::from_i64(0, 32);
2100 let one = BV::from_i64(1, 32);
2101 cond.ite(&one, &zero)
2102 }
2103
2104 fn encode_popcnt(&self, input: &BV) -> BV {
2109 let mut x = input.clone();
2110
2111 let mask1 = BV::from_u64(0x55555555, 32);
2113 let masked = x.bvand(&mask1);
2114 let shifted = x.bvlshr(BV::from_i64(1, 32));
2115 let shifted_masked = shifted.bvand(&mask1);
2116 x = masked.bvadd(&shifted_masked);
2117
2118 let mask2 = BV::from_u64(0x33333333, 32);
2120 let masked = x.bvand(&mask2);
2121 let shifted = x.bvlshr(BV::from_i64(2, 32));
2122 let shifted_masked = shifted.bvand(&mask2);
2123 x = masked.bvadd(&shifted_masked);
2124
2125 let mask3 = BV::from_u64(0x0F0F0F0F, 32);
2127 let masked = x.bvand(&mask3);
2128 let shifted = x.bvlshr(BV::from_i64(4, 32));
2129 let shifted_masked = shifted.bvand(&mask3);
2130 x = masked.bvadd(&shifted_masked);
2131
2132 let multiplier = BV::from_u64(0x01010101, 32);
2134 x = x.bvmul(&multiplier);
2135 x = x.bvlshr(BV::from_i64(24, 32));
2136
2137 x
2138 }
2139}
2140
2141#[cfg(test)]
2142mod tests {
2143 use super::*;
2144 use crate::with_verification_context;
2145
2146 #[test]
2147 fn test_arm_add_semantics() {
2148 with_verification_context(|| {
2149 let encoder = ArmSemantics::new();
2150 let mut state = ArmState::new_symbolic();
2151
2152 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2154 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2155
2156 let op = ArmOp::Add {
2158 rd: Reg::R0,
2159 rn: Reg::R1,
2160 op2: Operand2::Reg(Reg::R2),
2161 };
2162
2163 encoder.encode_op(&op, &mut state);
2164
2165 let result = state.get_reg(&Reg::R0).simplify();
2167 assert_eq!(result.as_i64(), Some(30));
2168 });
2169 }
2170
2171 #[test]
2172 fn test_arm_sub_semantics() {
2173 with_verification_context(|| {
2174 let encoder = ArmSemantics::new();
2175 let mut state = ArmState::new_symbolic();
2176
2177 state.set_reg(&Reg::R1, BV::from_i64(50, 32));
2178 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2179
2180 let op = ArmOp::Sub {
2181 rd: Reg::R0,
2182 rn: Reg::R1,
2183 op2: Operand2::Reg(Reg::R2),
2184 };
2185
2186 encoder.encode_op(&op, &mut state);
2187
2188 let result = state.get_reg(&Reg::R0);
2189 assert_eq!(result.simplify().as_i64(), Some(30));
2190 });
2191 }
2192
2193 #[test]
2194 fn test_arm_mov_immediate() {
2195 with_verification_context(|| {
2196 let encoder = ArmSemantics::new();
2197 let mut state = ArmState::new_symbolic();
2198
2199 let op = ArmOp::Mov {
2200 rd: Reg::R0,
2201 op2: Operand2::Imm(42),
2202 };
2203
2204 encoder.encode_op(&op, &mut state);
2205
2206 let result = state.get_reg(&Reg::R0);
2207 assert_eq!(result.simplify().as_i64(), Some(42));
2208 });
2209 }
2210
2211 #[test]
2212 fn test_arm_bitwise_ops() {
2213 with_verification_context(|| {
2214 let encoder = ArmSemantics::new();
2215 let mut state = ArmState::new_symbolic();
2216
2217 state.set_reg(&Reg::R1, BV::from_i64(0b1010, 32));
2218 state.set_reg(&Reg::R2, BV::from_i64(0b1100, 32));
2219
2220 let and_op = ArmOp::And {
2222 rd: Reg::R0,
2223 rn: Reg::R1,
2224 op2: Operand2::Reg(Reg::R2),
2225 };
2226 encoder.encode_op(&and_op, &mut state);
2227 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1000));
2228
2229 let orr_op = ArmOp::Orr {
2231 rd: Reg::R0,
2232 rn: Reg::R1,
2233 op2: Operand2::Reg(Reg::R2),
2234 };
2235 encoder.encode_op(&orr_op, &mut state);
2236 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1110));
2237
2238 let eor_op = ArmOp::Eor {
2240 rd: Reg::R0,
2241 rn: Reg::R1,
2242 op2: Operand2::Reg(Reg::R2),
2243 };
2244 encoder.encode_op(&eor_op, &mut state);
2245 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b0110));
2246 });
2247 }
2248
2249 #[test]
2250 fn test_arm_mls() {
2251 with_verification_context(|| {
2254 let encoder = ArmSemantics::new();
2255 let mut state = ArmState::new_symbolic();
2256
2257 state.set_reg(&Reg::R0, BV::from_i64(17, 32)); state.set_reg(&Reg::R1, BV::from_i64(3, 32)); state.set_reg(&Reg::R2, BV::from_i64(5, 32)); let mls_op = ArmOp::Mls {
2264 rd: Reg::R3,
2265 rn: Reg::R1,
2266 rm: Reg::R2,
2267 ra: Reg::R0,
2268 };
2269 encoder.encode_op(&mls_op, &mut state);
2270 assert_eq!(
2271 state.get_reg(&Reg::R3).simplify().as_i64(),
2272 Some(2),
2273 "MLS: 17 - 3*5 = 2"
2274 );
2275
2276 state.set_reg(&Reg::R0, BV::from_i64(100, 32));
2278 state.set_reg(&Reg::R1, BV::from_i64(7, 32));
2279 state.set_reg(&Reg::R2, BV::from_i64(3, 32));
2280
2281 let mls_op2 = ArmOp::Mls {
2282 rd: Reg::R3,
2283 rn: Reg::R1,
2284 rm: Reg::R2,
2285 ra: Reg::R0,
2286 };
2287 encoder.encode_op(&mls_op2, &mut state);
2288 assert_eq!(
2289 state.get_reg(&Reg::R3).simplify().as_i64(),
2290 Some(79),
2291 "MLS: 100 - 7*3 = 79"
2292 );
2293
2294 state.set_reg(&Reg::R0, BV::from_i64(-17, 32));
2296 state.set_reg(&Reg::R1, BV::from_i64(3, 32));
2297 state.set_reg(&Reg::R2, BV::from_i64(5, 32));
2298
2299 let mls_op3 = ArmOp::Mls {
2300 rd: Reg::R3,
2301 rn: Reg::R1,
2302 rm: Reg::R2,
2303 ra: Reg::R0,
2304 };
2305 encoder.encode_op(&mls_op3, &mut state);
2306 let result = state.get_reg(&Reg::R3).simplify().as_i64();
2308 let signed_result = result.map(|v| (v as i32) as i64);
2309 assert_eq!(signed_result, Some(-32), "MLS: -17 - 3*5 = -32");
2310 });
2311 }
2312
2313 #[test]
2314 fn test_arm_shift_ops() {
2315 with_verification_context(|| {
2316 let encoder = ArmSemantics::new();
2317 let mut state = ArmState::new_symbolic();
2318
2319 state.set_reg(&Reg::R1, BV::from_i64(8, 32));
2320
2321 let lsl_op = ArmOp::Lsl {
2323 rd: Reg::R0,
2324 rn: Reg::R1,
2325 shift: 2,
2326 };
2327 encoder.encode_op(&lsl_op, &mut state);
2328 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(32));
2329
2330 let lsr_op = ArmOp::Lsr {
2332 rd: Reg::R0,
2333 rn: Reg::R1,
2334 shift: 2,
2335 };
2336 encoder.encode_op(&lsr_op, &mut state);
2337 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(2));
2338 });
2339 }
2340
2341 #[test]
2342 fn test_arm_ror_comprehensive() {
2343 with_verification_context(|| {
2344 let encoder = ArmSemantics::new();
2345 let mut state = ArmState::new_symbolic();
2346
2347 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2350 let ror_op = ArmOp::Ror {
2351 rd: Reg::R0,
2352 rn: Reg::R1,
2353 shift: 8,
2354 };
2355 encoder.encode_op(&ror_op, &mut state);
2356 assert_eq!(
2358 state.get_reg(&Reg::R0).simplify().as_i64(),
2359 Some(0x78123456),
2360 "ROR by 8"
2361 );
2362
2363 let ror_op_16 = ArmOp::Ror {
2365 rd: Reg::R0,
2366 rn: Reg::R1,
2367 shift: 16,
2368 };
2369 encoder.encode_op(&ror_op_16, &mut state);
2370 assert_eq!(
2372 state.get_reg(&Reg::R0).simplify().as_i64(),
2373 Some(0x56781234),
2374 "ROR by 16"
2375 );
2376
2377 let ror_op_0 = ArmOp::Ror {
2379 rd: Reg::R0,
2380 rn: Reg::R1,
2381 shift: 0,
2382 };
2383 encoder.encode_op(&ror_op_0, &mut state);
2384 assert_eq!(
2385 state.get_reg(&Reg::R0).simplify().as_i64(),
2386 Some(0x12345678),
2387 "ROR by 0"
2388 );
2389
2390 let ror_op_32 = ArmOp::Ror {
2392 rd: Reg::R0,
2393 rn: Reg::R1,
2394 shift: 32,
2395 };
2396 encoder.encode_op(&ror_op_32, &mut state);
2397 assert_eq!(
2398 state.get_reg(&Reg::R0).simplify().as_i64(),
2399 Some(0x12345678),
2400 "ROR by 32"
2401 );
2402
2403 state.set_reg(&Reg::R1, BV::from_u64(0xABCDEF01, 32));
2405 let ror_op_4 = ArmOp::Ror {
2406 rd: Reg::R0,
2407 rn: Reg::R1,
2408 shift: 4,
2409 };
2410 encoder.encode_op(&ror_op_4, &mut state);
2411 assert_eq!(
2413 state.get_reg(&Reg::R0).simplify().as_i64(),
2414 Some(0x1ABCDEF0),
2415 "ROR by 4"
2416 );
2417
2418 state.set_reg(&Reg::R1, BV::from_u64(0x80000001, 32));
2420 let ror_op_1 = ArmOp::Ror {
2421 rd: Reg::R0,
2422 rn: Reg::R1,
2423 shift: 1,
2424 };
2425 encoder.encode_op(&ror_op_1, &mut state);
2426 let result = state.get_reg(&Reg::R0).simplify().as_i64();
2428 let signed_result = result.map(|v| (v as i32) as i64);
2429 assert_eq!(
2430 signed_result,
2431 Some(0xC0000000_u32 as i32 as i64),
2432 "ROR by 1"
2433 );
2434 });
2435 }
2436
2437 #[test]
2438 fn test_arm_clz_comprehensive() {
2439 with_verification_context(|| {
2440 let encoder = ArmSemantics::new();
2441 let mut state = ArmState::new_symbolic();
2442
2443 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2445 let clz_op = ArmOp::Clz {
2446 rd: Reg::R0,
2447 rm: Reg::R1,
2448 };
2449 encoder.encode_op(&clz_op, &mut state);
2450 assert_eq!(
2451 state.get_reg(&Reg::R0).simplify().as_i64(),
2452 Some(32),
2453 "CLZ(0) should be 32"
2454 );
2455
2456 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2458 encoder.encode_op(&clz_op, &mut state);
2459 assert_eq!(
2460 state.get_reg(&Reg::R0).simplify().as_i64(),
2461 Some(31),
2462 "CLZ(1) should be 31"
2463 );
2464
2465 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2467 encoder.encode_op(&clz_op, &mut state);
2468 assert_eq!(
2469 state.get_reg(&Reg::R0).simplify().as_i64(),
2470 Some(0),
2471 "CLZ(0x80000000) should be 0"
2472 );
2473
2474 state.set_reg(&Reg::R1, BV::from_u64(0x00FF0000, 32));
2476 encoder.encode_op(&clz_op, &mut state);
2477 assert_eq!(
2478 state.get_reg(&Reg::R0).simplify().as_i64(),
2479 Some(8),
2480 "CLZ(0x00FF0000) should be 8"
2481 );
2482
2483 state.set_reg(&Reg::R1, BV::from_u64(0x00001000, 32));
2485 encoder.encode_op(&clz_op, &mut state);
2486 assert_eq!(
2487 state.get_reg(&Reg::R0).simplify().as_i64(),
2488 Some(19),
2489 "CLZ(0x00001000) should be 19"
2490 );
2491
2492 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2494 encoder.encode_op(&clz_op, &mut state);
2495 assert_eq!(
2496 state.get_reg(&Reg::R0).simplify().as_i64(),
2497 Some(0),
2498 "CLZ(0xFFFFFFFF) should be 0"
2499 );
2500 });
2501 }
2502
2503 #[test]
2504 fn test_arm_rbit_comprehensive() {
2505 with_verification_context(|| {
2506 let encoder = ArmSemantics::new();
2507 let mut state = ArmState::new_symbolic();
2508
2509 let rbit_op = ArmOp::Rbit {
2510 rd: Reg::R0,
2511 rm: Reg::R1,
2512 };
2513
2514 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2516 encoder.encode_op(&rbit_op, &mut state);
2517 assert_eq!(
2518 state.get_reg(&Reg::R0).simplify().as_i64(),
2519 Some(0),
2520 "RBIT(0) should be 0"
2521 );
2522
2523 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2525 encoder.encode_op(&rbit_op, &mut state);
2526 assert_eq!(
2527 state.get_reg(&Reg::R0).simplify().as_u64(),
2528 Some(0x80000000),
2529 "RBIT(1) should be 0x80000000"
2530 );
2531
2532 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2534 encoder.encode_op(&rbit_op, &mut state);
2535 assert_eq!(
2536 state.get_reg(&Reg::R0).simplify().as_i64(),
2537 Some(1),
2538 "RBIT(0x80000000) should be 1"
2539 );
2540
2541 state.set_reg(&Reg::R1, BV::from_u64(0xFF000000, 32));
2543 encoder.encode_op(&rbit_op, &mut state);
2544 assert_eq!(
2545 state.get_reg(&Reg::R0).simplify().as_u64(),
2546 Some(0x000000FF),
2547 "RBIT(0xFF000000) should be 0x000000FF"
2548 );
2549
2550 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2552 encoder.encode_op(&rbit_op, &mut state);
2553 assert_eq!(
2555 state.get_reg(&Reg::R0).simplify().as_u64(),
2556 Some(0x1E6A2C48),
2557 "RBIT(0x12345678) should be 0x1E6A2C48"
2558 );
2559
2560 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2562 encoder.encode_op(&rbit_op, &mut state);
2563 assert_eq!(
2564 state.get_reg(&Reg::R0).simplify().as_u64(),
2565 Some(0xFFFFFFFF),
2566 "RBIT(0xFFFFFFFF) should be 0xFFFFFFFF"
2567 );
2568 });
2569 }
2570
2571 #[test]
2572 fn test_arm_cmp_flags() {
2573 with_verification_context(|| {
2576 let encoder = ArmSemantics::new();
2577 let mut state = ArmState::new_symbolic();
2578
2579 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2582 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2583
2584 let cmp_op = ArmOp::Cmp {
2585 rn: Reg::R0,
2586 op2: Operand2::Reg(Reg::R1),
2587 };
2588 encoder.encode_op(&cmp_op, &mut state);
2589
2590 assert_eq!(
2591 state.flags.z.simplify().as_bool(),
2592 Some(true),
2593 "Z flag should be set (equal)"
2594 );
2595 assert_eq!(
2596 state.flags.n.simplify().as_bool(),
2597 Some(false),
2598 "N flag should be clear (non-negative)"
2599 );
2600 assert_eq!(
2601 state.flags.c.simplify().as_bool(),
2602 Some(true),
2603 "C flag should be set (no borrow)"
2604 );
2605 assert_eq!(
2606 state.flags.v.simplify().as_bool(),
2607 Some(false),
2608 "V flag should be clear (no overflow)"
2609 );
2610
2611 state.set_reg(&Reg::R0, BV::from_i64(20, 32));
2614 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2615 encoder.encode_op(&cmp_op, &mut state);
2616
2617 assert_eq!(
2618 state.flags.z.simplify().as_bool(),
2619 Some(false),
2620 "Z flag should be clear (not equal)"
2621 );
2622 assert_eq!(
2623 state.flags.n.simplify().as_bool(),
2624 Some(false),
2625 "N flag should be clear (positive result)"
2626 );
2627 assert_eq!(
2628 state.flags.c.simplify().as_bool(),
2629 Some(true),
2630 "C flag should be set (no borrow)"
2631 );
2632 assert_eq!(
2633 state.flags.v.simplify().as_bool(),
2634 Some(false),
2635 "V flag should be clear (no overflow)"
2636 );
2637
2638 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2642 state.set_reg(&Reg::R1, BV::from_i64(20, 32));
2643 encoder.encode_op(&cmp_op, &mut state);
2644
2645 assert_eq!(
2646 state.flags.z.simplify().as_bool(),
2647 Some(false),
2648 "Z flag should be clear"
2649 );
2650 assert_eq!(
2651 state.flags.n.simplify().as_bool(),
2652 Some(true),
2653 "N flag should be set (negative result)"
2654 );
2655 assert_eq!(
2656 state.flags.c.simplify().as_bool(),
2657 Some(false),
2658 "C flag should be clear (borrow occurred)"
2659 );
2660 assert_eq!(
2661 state.flags.v.simplify().as_bool(),
2662 Some(false),
2663 "V flag should be clear"
2664 );
2665
2666 state.set_reg(&Reg::R0, BV::from_i64(0x7FFFFFFF, 32));
2671 state.set_reg(&Reg::R1, BV::from_i64(-2147483648i64, 32)); encoder.encode_op(&cmp_op, &mut state);
2673
2674 assert_eq!(
2675 state.flags.z.simplify().as_bool(),
2676 Some(false),
2677 "Z flag should be clear"
2678 );
2679 assert_eq!(
2680 state.flags.n.simplify().as_bool(),
2681 Some(true),
2682 "N flag should be set (wrapped result)"
2683 );
2684 assert_eq!(
2685 state.flags.c.simplify().as_bool(),
2686 Some(false),
2687 "C flag should be clear"
2688 );
2689 assert_eq!(
2690 state.flags.v.simplify().as_bool(),
2691 Some(true),
2692 "V flag should be set (overflow)"
2693 );
2694
2695 state.set_reg(&Reg::R0, BV::from_i64(0, 32));
2697 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2698 encoder.encode_op(&cmp_op, &mut state);
2699
2700 assert_eq!(
2701 state.flags.z.simplify().as_bool(),
2702 Some(true),
2703 "Z flag should be set (0 - 0 = 0)"
2704 );
2705 assert_eq!(
2706 state.flags.n.simplify().as_bool(),
2707 Some(false),
2708 "N flag should be clear"
2709 );
2710 assert_eq!(
2711 state.flags.c.simplify().as_bool(),
2712 Some(true),
2713 "C flag should be set"
2714 );
2715 assert_eq!(
2716 state.flags.v.simplify().as_bool(),
2717 Some(false),
2718 "V flag should be clear"
2719 );
2720 });
2721 }
2722
2723 #[test]
2724 fn test_arm_flags_all_combinations() {
2725 with_verification_context(|| {
2728 let encoder = ArmSemantics::new();
2729 let mut state = ArmState::new_symbolic();
2730
2731 let cmp_op = ArmOp::Cmp {
2732 rn: Reg::R0,
2733 op2: Operand2::Reg(Reg::R1),
2734 };
2735
2736 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2747 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2748 encoder.encode_op(&cmp_op, &mut state);
2749
2750 let n = state.flags.n.simplify().as_bool().unwrap();
2751 let z = state.flags.z.simplify().as_bool().unwrap();
2752 let v = state.flags.v.simplify().as_bool().unwrap();
2753
2754 assert!(!z, "Not equal");
2755 assert!(n != v, "5 < 10 signed (N != V)");
2756
2757 state.set_reg(&Reg::R0, BV::from_i64(-5, 32));
2759 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2760 encoder.encode_op(&cmp_op, &mut state);
2761
2762 let n = state.flags.n.simplify().as_bool().unwrap();
2763 let v = state.flags.v.simplify().as_bool().unwrap();
2764 assert!(n != v, "-5 < 10 signed (N != V)");
2765 });
2766 }
2767
2768 #[test]
2769 fn test_arm_setcond_eq() {
2770 with_verification_context(|| {
2771 let encoder = ArmSemantics::new();
2772 let mut state = ArmState::new_symbolic();
2773
2774 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2776 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2777
2778 let cmp_op = ArmOp::Cmp {
2780 rn: Reg::R0,
2781 op2: Operand2::Reg(Reg::R1),
2782 };
2783 encoder.encode_op(&cmp_op, &mut state);
2784
2785 let setcond_op = ArmOp::SetCond {
2787 rd: Reg::R0,
2788 cond: synth_synthesis::Condition::EQ,
2789 };
2790 encoder.encode_op(&setcond_op, &mut state);
2791
2792 assert_eq!(
2793 state.get_reg(&Reg::R0).simplify().as_i64(),
2794 Some(1),
2795 "EQ condition (10 == 10) should return 1"
2796 );
2797
2798 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2800 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2801
2802 encoder.encode_op(&cmp_op, &mut state);
2803
2804 let setcond_ne = ArmOp::SetCond {
2805 rd: Reg::R0,
2806 cond: synth_synthesis::Condition::NE,
2807 };
2808 encoder.encode_op(&setcond_ne, &mut state);
2809
2810 assert_eq!(
2811 state.get_reg(&Reg::R0).simplify().as_i64(),
2812 Some(1),
2813 "NE condition (10 != 5) should return 1"
2814 );
2815 });
2816 }
2817
2818 #[test]
2819 fn test_arm_setcond_signed() {
2820 with_verification_context(|| {
2821 let encoder = ArmSemantics::new();
2822 let mut state = ArmState::new_symbolic();
2823
2824 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2826 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2827
2828 let cmp_op = ArmOp::Cmp {
2829 rn: Reg::R0,
2830 op2: Operand2::Reg(Reg::R1),
2831 };
2832 encoder.encode_op(&cmp_op, &mut state);
2833
2834 let setcond_lt = ArmOp::SetCond {
2835 rd: Reg::R0,
2836 cond: synth_synthesis::Condition::LT,
2837 };
2838 encoder.encode_op(&setcond_lt, &mut state);
2839
2840 assert_eq!(
2841 state.get_reg(&Reg::R0).simplify().as_i64(),
2842 Some(1),
2843 "LT signed (5 < 10) should return 1"
2844 );
2845
2846 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2848 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2849
2850 encoder.encode_op(&cmp_op, &mut state);
2851
2852 let setcond_ge = ArmOp::SetCond {
2853 rd: Reg::R0,
2854 cond: synth_synthesis::Condition::GE,
2855 };
2856 encoder.encode_op(&setcond_ge, &mut state);
2857
2858 assert_eq!(
2859 state.get_reg(&Reg::R0).simplify().as_i64(),
2860 Some(1),
2861 "GE signed (10 >= 5) should return 1"
2862 );
2863
2864 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2866 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2867
2868 encoder.encode_op(&cmp_op, &mut state);
2869
2870 let setcond_gt = ArmOp::SetCond {
2871 rd: Reg::R0,
2872 cond: synth_synthesis::Condition::GT,
2873 };
2874 encoder.encode_op(&setcond_gt, &mut state);
2875
2876 assert_eq!(
2877 state.get_reg(&Reg::R0).simplify().as_i64(),
2878 Some(1),
2879 "GT signed (10 > 5) should return 1"
2880 );
2881
2882 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2884 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2885
2886 encoder.encode_op(&cmp_op, &mut state);
2887
2888 let setcond_le = ArmOp::SetCond {
2889 rd: Reg::R0,
2890 cond: synth_synthesis::Condition::LE,
2891 };
2892 encoder.encode_op(&setcond_le, &mut state);
2893
2894 assert_eq!(
2895 state.get_reg(&Reg::R0).simplify().as_i64(),
2896 Some(1),
2897 "LE signed (5 <= 10) should return 1"
2898 );
2899 });
2900 }
2901
2902 #[test]
2903 fn test_arm_setcond_unsigned() {
2904 with_verification_context(|| {
2905 let encoder = ArmSemantics::new();
2906 let mut state = ArmState::new_symbolic();
2907
2908 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2910 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2911
2912 let cmp_op = ArmOp::Cmp {
2913 rn: Reg::R0,
2914 op2: Operand2::Reg(Reg::R1),
2915 };
2916 encoder.encode_op(&cmp_op, &mut state);
2917
2918 let setcond_lo = ArmOp::SetCond {
2919 rd: Reg::R0,
2920 cond: synth_synthesis::Condition::LO,
2921 };
2922 encoder.encode_op(&setcond_lo, &mut state);
2923
2924 assert_eq!(
2925 state.get_reg(&Reg::R0).simplify().as_i64(),
2926 Some(1),
2927 "LO unsigned (5 < 10) should return 1"
2928 );
2929
2930 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2932 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2933
2934 encoder.encode_op(&cmp_op, &mut state);
2935
2936 let setcond_hs = ArmOp::SetCond {
2937 rd: Reg::R0,
2938 cond: synth_synthesis::Condition::HS,
2939 };
2940 encoder.encode_op(&setcond_hs, &mut state);
2941
2942 assert_eq!(
2943 state.get_reg(&Reg::R0).simplify().as_i64(),
2944 Some(1),
2945 "HS unsigned (10 >= 5) should return 1"
2946 );
2947
2948 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2950 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2951
2952 encoder.encode_op(&cmp_op, &mut state);
2953
2954 let setcond_hi = ArmOp::SetCond {
2955 rd: Reg::R0,
2956 cond: synth_synthesis::Condition::HI,
2957 };
2958 encoder.encode_op(&setcond_hi, &mut state);
2959
2960 assert_eq!(
2961 state.get_reg(&Reg::R0).simplify().as_i64(),
2962 Some(1),
2963 "HI unsigned (10 > 5) should return 1"
2964 );
2965
2966 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2968 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2969
2970 encoder.encode_op(&cmp_op, &mut state);
2971
2972 let setcond_ls = ArmOp::SetCond {
2973 rd: Reg::R0,
2974 cond: synth_synthesis::Condition::LS,
2975 };
2976 encoder.encode_op(&setcond_ls, &mut state);
2977
2978 assert_eq!(
2979 state.get_reg(&Reg::R0).simplify().as_i64(),
2980 Some(1),
2981 "LS unsigned (5 <= 10) should return 1"
2982 );
2983 });
2984 }
2985}