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: _,
488 table_byte_offset: _,
489 null_check: _,
490 } => {
491 let _table_index = state.get_reg(table_index_reg).clone();
493 let result = BV::new_const(format!("call_indirect_{}", type_idx), 32);
494 state.set_reg(rd, result);
495 }
496
497 ArmOp::I64Const { rdlo, rdhi, value } => {
503 let low32 = (*value as u32) as i64;
505 let high32 = *value >> 32;
506 state.set_reg(rdlo, BV::from_i64(low32, 32));
507 state.set_reg(rdhi, BV::from_i64(high32, 32));
508 }
509
510 ArmOp::I64Add {
511 rdlo,
512 rdhi,
513 rnlo,
514 rnhi,
515 rmlo,
516 rmhi,
517 } => {
518 let n_low = state.get_reg(rnlo).clone();
523 let m_low = state.get_reg(rmlo).clone();
524 let n_high = state.get_reg(rnhi).clone();
525 let m_high = state.get_reg(rmhi).clone();
526
527 let result_low = n_low.bvadd(&m_low);
529 state.set_reg(rdlo, result_low.clone());
530
531 let carry = result_low.bvult(&n_low);
534 let carry_bv = carry.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
535
536 let high_sum = n_high.bvadd(&m_high);
538 let result_high = high_sum.bvadd(&carry_bv);
539 state.set_reg(rdhi, result_high);
540 }
541
542 ArmOp::I64Eqz { rd, rnlo, rnhi } => {
543 let zero = BV::from_i64(0, 32);
546 let low_zero = state.get_reg(rnlo).eq(&zero);
547 let high_zero = state.get_reg(rnhi).eq(&zero);
548 let both_zero = Bool::and(&[&low_zero, &high_zero]);
549 let result = self.bool_to_bv32(&both_zero);
550 state.set_reg(rd, result);
551 }
552
553 ArmOp::I32WrapI64 { rd, rnlo } => {
554 let low_val = state.get_reg(rnlo).clone();
556 state.set_reg(rd, low_val);
557 }
558
559 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
560 let value = state.get_reg(rn).clone();
562 state.set_reg(rdlo, value.clone());
563
564 let sign_bit = value.extract(31, 31); let all_ones = BV::from_i64(-1, 32);
567 let zero = BV::from_i64(0, 32);
568 let high_val = sign_bit.eq(BV::from_i64(1, 1)).ite(&all_ones, &zero);
570 state.set_reg(rdhi, high_val);
571 }
572
573 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
574 let value = state.get_reg(rn).clone();
576 state.set_reg(rdlo, value);
577 state.set_reg(rdhi, BV::from_i64(0, 32));
579 }
580
581 ArmOp::I64Sub {
582 rdlo,
583 rdhi,
584 rnlo,
585 rnhi,
586 rmlo,
587 rmhi,
588 } => {
589 let n_low = state.get_reg(rnlo).clone();
594 let m_low = state.get_reg(rmlo).clone();
595 let n_high = state.get_reg(rnhi).clone();
596 let m_high = state.get_reg(rmhi).clone();
597
598 let result_low = n_low.bvsub(&m_low);
600 state.set_reg(rdlo, result_low.clone());
601
602 let borrow = n_low.bvult(&m_low);
604 let borrow_bv = borrow.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
605
606 let high_diff = n_high.bvsub(&m_high);
608 let result_high = high_diff.bvsub(&borrow_bv);
609 state.set_reg(rdhi, result_high);
610 }
611
612 ArmOp::I64Mul {
613 rd_lo,
614 rd_hi,
615 rn_lo,
616 rn_hi,
617 rm_lo,
618 rm_hi,
619 } => {
620 let a_lo = state.get_reg(rn_lo).clone();
626 let a_hi = state.get_reg(rn_hi).clone();
627 let b_lo = state.get_reg(rm_lo).clone();
628 let b_hi = state.get_reg(rm_hi).clone();
629
630 let lo_lo = a_lo.bvmul(&b_lo);
633 state.set_reg(rd_lo, lo_lo.clone());
634
635 let hi_lo = a_hi.bvmul(&b_lo); let lo_hi = a_lo.bvmul(&b_hi); let hi_sum = hi_lo.bvadd(&lo_hi);
649 state.set_reg(rd_hi, hi_sum);
650
651 }
657
658 ArmOp::I64DivS { rdlo, rdhi, .. } => {
665 state.set_reg(rdlo, BV::new_const("i64_divs_lo", 32));
669 state.set_reg(rdhi, BV::new_const("i64_divs_hi", 32));
670 }
671
672 ArmOp::I64DivU { rdlo, rdhi, .. } => {
673 state.set_reg(rdlo, BV::new_const("i64_divu_lo", 32));
677 state.set_reg(rdhi, BV::new_const("i64_divu_hi", 32));
678 }
679
680 ArmOp::I64RemS { rdlo, rdhi, .. } => {
681 state.set_reg(rdlo, BV::new_const("i64_rems_lo", 32));
685 state.set_reg(rdhi, BV::new_const("i64_rems_hi", 32));
686 }
687
688 ArmOp::I64RemU { rdlo, rdhi, .. } => {
689 state.set_reg(rdlo, BV::new_const("i64_remu_lo", 32));
693 state.set_reg(rdhi, BV::new_const("i64_remu_hi", 32));
694 }
695
696 ArmOp::I64And {
697 rdlo,
698 rdhi,
699 rnlo,
700 rnhi,
701 rmlo,
702 rmhi,
703 } => {
704 let n_low = state.get_reg(rnlo).clone();
705 let m_low = state.get_reg(rmlo).clone();
706 state.set_reg(rdlo, n_low.bvand(&m_low));
707
708 let n_high = state.get_reg(rnhi).clone();
709 let m_high = state.get_reg(rmhi).clone();
710 state.set_reg(rdhi, n_high.bvand(&m_high));
711 }
712
713 ArmOp::I64Or {
714 rdlo,
715 rdhi,
716 rnlo,
717 rnhi,
718 rmlo,
719 rmhi,
720 } => {
721 let n_low = state.get_reg(rnlo).clone();
722 let m_low = state.get_reg(rmlo).clone();
723 state.set_reg(rdlo, n_low.bvor(&m_low));
724
725 let n_high = state.get_reg(rnhi).clone();
726 let m_high = state.get_reg(rmhi).clone();
727 state.set_reg(rdhi, n_high.bvor(&m_high));
728 }
729
730 ArmOp::I64Xor {
731 rdlo,
732 rdhi,
733 rnlo,
734 rnhi,
735 rmlo,
736 rmhi,
737 } => {
738 let n_low = state.get_reg(rnlo).clone();
739 let m_low = state.get_reg(rmlo).clone();
740 state.set_reg(rdlo, n_low.bvxor(&m_low));
741
742 let n_high = state.get_reg(rnhi).clone();
743 let m_high = state.get_reg(rmhi).clone();
744 state.set_reg(rdhi, n_high.bvxor(&m_high));
745 }
746
747 ArmOp::I64Eq {
748 rd,
749 rnlo,
750 rnhi,
751 rmlo,
752 rmhi,
753 } => {
754 let n_low = state.get_reg(rnlo).clone();
755 let m_low = state.get_reg(rmlo).clone();
756 let n_high = state.get_reg(rnhi).clone();
757 let m_high = state.get_reg(rmhi).clone();
758
759 let low_eq = n_low.eq(&m_low);
760 let high_eq = n_high.eq(&m_high);
761 let both_eq = Bool::and(&[&low_eq, &high_eq]);
762 let result = self.bool_to_bv32(&both_eq);
763 state.set_reg(rd, result);
764 }
765
766 ArmOp::I64LtS {
767 rd,
768 rnlo,
769 rnhi,
770 rmlo,
771 rmhi,
772 } => {
773 let n_low = state.get_reg(rnlo).clone();
776 let m_low = state.get_reg(rmlo).clone();
777 let n_high = state.get_reg(rnhi).clone();
778 let m_high = state.get_reg(rmhi).clone();
779
780 let high_lt = n_high.bvslt(&m_high);
782 let high_eq = n_high.eq(&m_high);
783
784 let low_lt = n_low.bvult(&m_low);
786
787 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
789 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
790 let result = self.bool_to_bv32(&result_bool);
791 state.set_reg(rd, result);
792 }
793
794 ArmOp::I64LtU {
795 rd,
796 rnlo,
797 rnhi,
798 rmlo,
799 rmhi,
800 } => {
801 let n_low = state.get_reg(rnlo).clone();
804 let m_low = state.get_reg(rmlo).clone();
805 let n_high = state.get_reg(rnhi).clone();
806 let m_high = state.get_reg(rmhi).clone();
807
808 let high_lt = n_high.bvult(&m_high);
810 let high_eq = n_high.eq(&m_high);
811
812 let low_lt = n_low.bvult(&m_low);
814
815 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
817 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
818 let result = self.bool_to_bv32(&result_bool);
819 state.set_reg(rd, result);
820 }
821
822 ArmOp::I64Ne {
823 rd,
824 rnlo,
825 rnhi,
826 rmlo,
827 rmhi,
828 } => {
829 let n_low = state.get_reg(rnlo).clone();
831 let m_low = state.get_reg(rmlo).clone();
832 let n_high = state.get_reg(rnhi).clone();
833 let m_high = state.get_reg(rmhi).clone();
834
835 let low_eq = n_low.eq(&m_low);
836 let high_eq = n_high.eq(&m_high);
837 let both_eq = Bool::and(&[&low_eq, &high_eq]);
838 let not_eq = both_eq.not();
839 let result = self.bool_to_bv32(¬_eq);
840 state.set_reg(rd, result);
841 }
842
843 ArmOp::I64LeS {
844 rd,
845 rnlo,
846 rnhi,
847 rmlo,
848 rmhi,
849 } => {
850 let n_low = state.get_reg(rnlo).clone();
853 let m_low = state.get_reg(rmlo).clone();
854 let n_high = state.get_reg(rnhi).clone();
855 let m_high = state.get_reg(rmhi).clone();
856
857 let high_lt = n_high.bvslt(&m_high);
858 let high_eq = n_high.eq(&m_high);
859 let low_le = n_low.bvule(&m_low); let eq_and_le = Bool::and(&[&high_eq, &low_le]);
862 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
863 let result = self.bool_to_bv32(&result_bool);
864 state.set_reg(rd, result);
865 }
866
867 ArmOp::I64LeU {
868 rd,
869 rnlo,
870 rnhi,
871 rmlo,
872 rmhi,
873 } => {
874 let n_low = state.get_reg(rnlo).clone();
876 let m_low = state.get_reg(rmlo).clone();
877 let n_high = state.get_reg(rnhi).clone();
878 let m_high = state.get_reg(rmhi).clone();
879
880 let high_lt = n_high.bvult(&m_high);
881 let high_eq = n_high.eq(&m_high);
882 let low_le = n_low.bvule(&m_low);
883
884 let eq_and_le = Bool::and(&[&high_eq, &low_le]);
885 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
886 let result = self.bool_to_bv32(&result_bool);
887 state.set_reg(rd, result);
888 }
889
890 ArmOp::I64GtS {
891 rd,
892 rnlo,
893 rnhi,
894 rmlo,
895 rmhi,
896 } => {
897 let n_low = state.get_reg(rnlo).clone();
900 let m_low = state.get_reg(rmlo).clone();
901 let n_high = state.get_reg(rnhi).clone();
902 let m_high = state.get_reg(rmhi).clone();
903
904 let high_gt = n_high.bvsgt(&m_high);
905 let high_eq = n_high.eq(&m_high);
906 let low_gt = n_low.bvugt(&m_low); let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
909 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
910 let result = self.bool_to_bv32(&result_bool);
911 state.set_reg(rd, result);
912 }
913
914 ArmOp::I64GtU {
915 rd,
916 rnlo,
917 rnhi,
918 rmlo,
919 rmhi,
920 } => {
921 let n_low = state.get_reg(rnlo).clone();
923 let m_low = state.get_reg(rmlo).clone();
924 let n_high = state.get_reg(rnhi).clone();
925 let m_high = state.get_reg(rmhi).clone();
926
927 let high_gt = n_high.bvugt(&m_high);
928 let high_eq = n_high.eq(&m_high);
929 let low_gt = n_low.bvugt(&m_low);
930
931 let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
932 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
933 let result = self.bool_to_bv32(&result_bool);
934 state.set_reg(rd, result);
935 }
936
937 ArmOp::I64GeS {
938 rd,
939 rnlo,
940 rnhi,
941 rmlo,
942 rmhi,
943 } => {
944 let n_low = state.get_reg(rnlo).clone();
947 let m_low = state.get_reg(rmlo).clone();
948 let n_high = state.get_reg(rnhi).clone();
949 let m_high = state.get_reg(rmhi).clone();
950
951 let high_lt = n_high.bvslt(&m_high);
952 let high_eq = n_high.eq(&m_high);
953 let low_lt = n_low.bvult(&m_low);
954
955 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
956 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
957 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
959 state.set_reg(rd, result);
960 }
961
962 ArmOp::I64GeU {
963 rd,
964 rnlo,
965 rnhi,
966 rmlo,
967 rmhi,
968 } => {
969 let n_low = state.get_reg(rnlo).clone();
972 let m_low = state.get_reg(rmlo).clone();
973 let n_high = state.get_reg(rnhi).clone();
974 let m_high = state.get_reg(rmhi).clone();
975
976 let high_lt = n_high.bvult(&m_high);
977 let high_eq = n_high.eq(&m_high);
978 let low_lt = n_low.bvult(&m_low);
979
980 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
981 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
982 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
984 state.set_reg(rd, result);
985 }
986
987 ArmOp::I64Shl {
991 rd_lo,
992 rd_hi,
993 rn_lo,
994 rn_hi,
995 rm_lo,
996 rm_hi: _,
997 } => {
998 let n_lo = state.get_reg(rn_lo).clone();
1001 let n_hi = state.get_reg(rn_hi).clone();
1002 let shift_amt = state.get_reg(rm_lo).clone();
1003
1004 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1006
1007 let shift_32 = BV::from_i64(32, 32);
1010 let is_large = shift_mod.bvuge(&shift_32); let result_lo_small = n_lo.bvshl(&shift_mod);
1016 let shift_complement = shift_32.bvsub(&shift_mod);
1017 let bits_to_high = n_lo.bvlshr(&shift_complement);
1018 let result_hi_small = n_hi.bvshl(&shift_mod).bvor(&bits_to_high);
1019
1020 let zero = BV::from_i64(0, 32);
1024 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1025 let result_lo_large = zero.clone();
1026 let result_hi_large = n_lo.bvshl(&shift_minus_32);
1027
1028 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1030 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1031
1032 state.set_reg(rd_lo, result_lo);
1033 state.set_reg(rd_hi, result_hi);
1034 }
1035
1036 ArmOp::I64ShrU {
1037 rd_lo,
1038 rd_hi,
1039 rn_lo,
1040 rn_hi,
1041 rm_lo,
1042 rm_hi: _,
1043 } => {
1044 let n_lo = state.get_reg(rn_lo).clone();
1046 let n_hi = state.get_reg(rn_hi).clone();
1047 let shift_amt = state.get_reg(rm_lo).clone();
1048
1049 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1050 let shift_32 = BV::from_i64(32, 32);
1051 let is_large = shift_mod.bvuge(&shift_32);
1052
1053 let result_hi_small = n_hi.bvlshr(&shift_mod);
1057 let shift_complement = shift_32.bvsub(&shift_mod);
1058 let bits_to_low = n_hi.bvshl(&shift_complement);
1059 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1060
1061 let zero = BV::from_i64(0, 32);
1065 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1066 let result_hi_large = zero.clone();
1067 let result_lo_large = n_hi.bvlshr(&shift_minus_32);
1068
1069 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1070 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1071
1072 state.set_reg(rd_lo, result_lo);
1073 state.set_reg(rd_hi, result_hi);
1074 }
1075
1076 ArmOp::I64ShrS {
1077 rd_lo,
1078 rd_hi,
1079 rn_lo,
1080 rn_hi,
1081 rm_lo,
1082 rm_hi: _,
1083 } => {
1084 let n_lo = state.get_reg(rn_lo).clone();
1086 let n_hi = state.get_reg(rn_hi).clone();
1087 let shift_amt = state.get_reg(rm_lo).clone();
1088
1089 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1090 let shift_32 = BV::from_i64(32, 32);
1091 let is_large = shift_mod.bvuge(&shift_32);
1092
1093 let result_hi_small = n_hi.bvashr(&shift_mod);
1097 let shift_complement = shift_32.bvsub(&shift_mod);
1098 let bits_to_low = n_hi.bvshl(&shift_complement);
1099 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1100
1101 let shift_31 = BV::from_i64(31, 32);
1105 let result_hi_large = n_hi.bvashr(&shift_31);
1106 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1107 let result_lo_large = n_hi.bvashr(&shift_minus_32);
1108
1109 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1110 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1111
1112 state.set_reg(rd_lo, result_lo);
1113 state.set_reg(rd_hi, result_hi);
1114 }
1115
1116 ArmOp::I64Rotl {
1120 rdlo,
1121 rdhi,
1122 rnlo,
1123 rnhi,
1124 shift,
1125 } => {
1126 let n_lo = state.get_reg(rnlo).clone();
1129 let n_hi = state.get_reg(rnhi).clone();
1130 let shift_amt = state.get_reg(shift).clone();
1131
1132 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1134 let shift_32 = BV::from_i64(32, 32);
1135 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1141
1142 let lo_shifted_left = n_lo.bvshl(&shift_mod);
1143 let hi_bits_to_lo = n_hi.bvlshr(&shift_complement);
1144 let result_lo_small = lo_shifted_left.bvor(&hi_bits_to_lo);
1145
1146 let hi_shifted_left = n_hi.bvshl(&shift_mod);
1147 let lo_bits_to_hi = n_lo.bvlshr(&shift_complement);
1148 let result_hi_small = hi_shifted_left.bvor(&lo_bits_to_hi);
1149
1150 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1153 let complement_large = shift_32.bvsub(&shift_minus_32);
1154
1155 let hi_shifted_left_large = n_hi.bvshl(&shift_minus_32);
1156 let lo_bits_to_hi_large = n_lo.bvlshr(&complement_large);
1157 let result_lo_large = hi_shifted_left_large.bvor(&lo_bits_to_hi_large);
1158
1159 let lo_shifted_left_large = n_lo.bvshl(&shift_minus_32);
1160 let hi_bits_to_lo_large = n_hi.bvlshr(&complement_large);
1161 let result_hi_large = lo_shifted_left_large.bvor(&hi_bits_to_lo_large);
1162
1163 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1165 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1166
1167 state.set_reg(rdlo, result_lo);
1168 state.set_reg(rdhi, result_hi);
1169 }
1170
1171 ArmOp::I64Rotr {
1172 rdlo,
1173 rdhi,
1174 rnlo,
1175 rnhi,
1176 shift,
1177 } => {
1178 let n_lo = state.get_reg(rnlo).clone();
1181 let n_hi = state.get_reg(rnhi).clone();
1182 let shift_amt = state.get_reg(shift).clone();
1183
1184 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1186 let shift_32 = BV::from_i64(32, 32);
1187 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1193
1194 let lo_shifted_right = n_lo.bvlshr(&shift_mod);
1195 let hi_bits_to_lo = n_hi.bvshl(&shift_complement);
1196 let result_lo_small = lo_shifted_right.bvor(&hi_bits_to_lo);
1197
1198 let hi_shifted_right = n_hi.bvlshr(&shift_mod);
1199 let lo_bits_to_hi = n_lo.bvshl(&shift_complement);
1200 let result_hi_small = hi_shifted_right.bvor(&lo_bits_to_hi);
1201
1202 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1205 let complement_large = shift_32.bvsub(&shift_minus_32);
1206
1207 let hi_shifted_right_large = n_hi.bvlshr(&shift_minus_32);
1208 let lo_bits_to_hi_large = n_lo.bvshl(&complement_large);
1209 let result_lo_large = hi_shifted_right_large.bvor(&lo_bits_to_hi_large);
1210
1211 let lo_shifted_right_large = n_lo.bvlshr(&shift_minus_32);
1212 let hi_bits_to_lo_large = n_hi.bvshl(&complement_large);
1213 let result_hi_large = lo_shifted_right_large.bvor(&hi_bits_to_lo_large);
1214
1215 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1217 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1218
1219 state.set_reg(rdlo, result_lo);
1220 state.set_reg(rdhi, result_hi);
1221 }
1222
1223 ArmOp::I64Clz { rd, rnlo, rnhi } => {
1224 let n_lo = state.get_reg(rnlo).clone();
1228 let n_hi = state.get_reg(rnhi).clone();
1229
1230 let hi_clz = self.encode_clz(&n_hi);
1231 let lo_clz = self.encode_clz(&n_lo);
1232
1233 let thirty_two = BV::from_i64(32, 32);
1235 let hi_is_zero = hi_clz.eq(&thirty_two);
1236 let result = hi_is_zero.ite(
1237 thirty_two.bvadd(&lo_clz), &hi_clz, );
1240 state.set_reg(rd, result);
1241 }
1242
1243 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
1244 let n_lo = state.get_reg(rnlo).clone();
1248 let n_hi = state.get_reg(rnhi).clone();
1249
1250 let lo_ctz = self.encode_ctz(&n_lo);
1251 let hi_ctz = self.encode_ctz(&n_hi);
1252
1253 let thirty_two = BV::from_i64(32, 32);
1255 let lo_is_zero = lo_ctz.eq(&thirty_two);
1256 let result = lo_is_zero.ite(
1257 thirty_two.bvadd(&hi_ctz), &lo_ctz, );
1260 state.set_reg(rd, result);
1261 }
1262
1263 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
1264 let n_lo = state.get_reg(rnlo).clone();
1267 let n_hi = state.get_reg(rnhi).clone();
1268
1269 let lo_popcnt = self.encode_popcnt(&n_lo);
1270 let hi_popcnt = self.encode_popcnt(&n_hi);
1271
1272 let result = lo_popcnt.bvadd(&hi_popcnt);
1273 state.set_reg(rd, result);
1274 }
1275
1276 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
1280 let result_lo = BV::new_const(format!("i64load_lo_{:?}", addr), 32);
1284 let result_hi = BV::new_const(format!("i64load_hi_{:?}", addr), 32);
1285 state.set_reg(rdlo, result_lo);
1286 state.set_reg(rdhi, result_hi);
1287 }
1288
1289 ArmOp::I64Str {
1290 rdlo: _,
1291 rdhi: _,
1292 addr: _,
1293 } => {
1294 }
1299
1300 ArmOp::F32Const { sd, value } => {
1309 let bits = value.to_bits() as i64;
1312 let bv_val = BV::from_i64(bits, 32);
1313 state.set_vfp_reg(sd, bv_val);
1314 }
1315
1316 ArmOp::F32Add { sd, sn, sm } => {
1318 let result = BV::new_const(format!("f32_add_{:?}_{:?}", sn, sm), 32);
1322 state.set_vfp_reg(sd, result);
1323 }
1324
1325 ArmOp::F32Sub { sd, sn, sm } => {
1326 let result = BV::new_const(format!("f32_sub_{:?}_{:?}", sn, sm), 32);
1328 state.set_vfp_reg(sd, result);
1329 }
1330
1331 ArmOp::F32Mul { sd, sn, sm } => {
1332 let result = BV::new_const(format!("f32_mul_{:?}_{:?}", sn, sm), 32);
1334 state.set_vfp_reg(sd, result);
1335 }
1336
1337 ArmOp::F32Div { sd, sn, sm } => {
1338 let result = BV::new_const(format!("f32_div_{:?}_{:?}", sn, sm), 32);
1340 state.set_vfp_reg(sd, result);
1341 }
1342
1343 ArmOp::F32Abs { sd, sm } => {
1345 let val = state.get_vfp_reg(sm).clone();
1348 let mask = BV::from_u64(0x7FFFFFFF, 32); let result = val.bvand(&mask);
1350 state.set_vfp_reg(sd, result);
1351 }
1352
1353 ArmOp::F32Neg { sd, sm } => {
1354 let val = state.get_vfp_reg(sm).clone();
1357 let mask = BV::from_u64(0x80000000, 32); let result = val.bvxor(&mask);
1359 state.set_vfp_reg(sd, result);
1360 }
1361
1362 ArmOp::F32Sqrt { sd, sm } => {
1363 let result = BV::new_const(format!("f32_sqrt_{:?}", sm), 32);
1366 state.set_vfp_reg(sd, result);
1367 }
1368
1369 ArmOp::F32Min { sd, sn, sm } => {
1370 let result = BV::new_const(format!("f32_min_{:?}_{:?}", sn, sm), 32);
1374 state.set_vfp_reg(sd, result);
1375 }
1376
1377 ArmOp::F32Max { sd, sn, sm } => {
1378 let result = BV::new_const(format!("f32_max_{:?}_{:?}", sn, sm), 32);
1382 state.set_vfp_reg(sd, result);
1383 }
1384
1385 ArmOp::F32Copysign { sd, sn, sm } => {
1386 let val_n = state.get_vfp_reg(sn).clone();
1389 let val_m = state.get_vfp_reg(sm).clone();
1390
1391 let mag_mask = BV::from_u64(0x7FFFFFFF, 32);
1393 let magnitude = val_n.bvand(&mag_mask);
1394
1395 let sign_mask = BV::from_u64(0x80000000, 32);
1397 let sign = val_m.bvand(&sign_mask);
1398
1399 let result = magnitude.bvor(&sign);
1401 state.set_vfp_reg(sd, result);
1402 }
1403
1404 ArmOp::F32Load { sd, addr } => {
1405 let result = BV::new_const(format!("f32_load_{:?}", addr), 32);
1408 state.set_vfp_reg(sd, result);
1409 }
1410
1411 ArmOp::F32Eq { rd, sn, sm } => {
1413 let result = BV::new_const(format!("f32_eq_{:?}_{:?}", sn, sm), 32);
1416 state.set_reg(rd, result);
1417 }
1418
1419 ArmOp::F32Ne { rd, sn, sm } => {
1420 let result = BV::new_const(format!("f32_ne_{:?}_{:?}", sn, sm), 32);
1422 state.set_reg(rd, result);
1423 }
1424
1425 ArmOp::F32Lt { rd, sn, sm } => {
1426 let result = BV::new_const(format!("f32_lt_{:?}_{:?}", sn, sm), 32);
1428 state.set_reg(rd, result);
1429 }
1430
1431 ArmOp::F32Le { rd, sn, sm } => {
1432 let result = BV::new_const(format!("f32_le_{:?}_{:?}", sn, sm), 32);
1434 state.set_reg(rd, result);
1435 }
1436
1437 ArmOp::F32Gt { rd, sn, sm } => {
1438 let result = BV::new_const(format!("f32_gt_{:?}_{:?}", sn, sm), 32);
1440 state.set_reg(rd, result);
1441 }
1442
1443 ArmOp::F32Ge { rd, sn, sm } => {
1444 let result = BV::new_const(format!("f32_ge_{:?}_{:?}", sn, sm), 32);
1446 state.set_reg(rd, result);
1447 }
1448
1449 ArmOp::F32Store { sd, addr } => {
1450 let _val = state.get_vfp_reg(sd);
1455 let _addr_str = format!("{:?}", addr);
1456 }
1458
1459 ArmOp::F32Ceil { sd, sm } => {
1461 let result = BV::new_const(format!("f32_ceil_{:?}", sm), 32);
1464 state.set_vfp_reg(sd, result);
1465 }
1466
1467 ArmOp::F32Floor { sd, sm } => {
1468 let result = BV::new_const(format!("f32_floor_{:?}", sm), 32);
1471 state.set_vfp_reg(sd, result);
1472 }
1473
1474 ArmOp::F32Trunc { sd, sm } => {
1475 let result = BV::new_const(format!("f32_trunc_{:?}", sm), 32);
1478 state.set_vfp_reg(sd, result);
1479 }
1480
1481 ArmOp::F32Nearest { sd, sm } => {
1482 let result = BV::new_const(format!("f32_nearest_{:?}", sm), 32);
1485 state.set_vfp_reg(sd, result);
1486 }
1487
1488 ArmOp::F32ConvertI32S { sd, rm } => {
1490 let int_val = state.get_reg(rm);
1492 let result = BV::new_const(format!("f32_convert_i32s_{:?}", int_val), 32);
1493 state.set_vfp_reg(sd, result);
1494 }
1495
1496 ArmOp::F32ConvertI32U { sd, rm } => {
1497 let int_val = state.get_reg(rm);
1499 let result = BV::new_const(format!("f32_convert_i32u_{:?}", int_val), 32);
1500 state.set_vfp_reg(sd, result);
1501 }
1502
1503 ArmOp::F32ConvertI64S { sd, rmlo, rmhi } => {
1504 let lo = state.get_reg(rmlo);
1506 let hi = state.get_reg(rmhi);
1507 let result = BV::new_const(format!("f32_convert_i64s_{:?}_{:?}", lo, hi), 32);
1508 state.set_vfp_reg(sd, result);
1509 }
1510
1511 ArmOp::F32ConvertI64U { sd, rmlo, rmhi } => {
1512 let lo = state.get_reg(rmlo);
1514 let hi = state.get_reg(rmhi);
1515 let result = BV::new_const(format!("f32_convert_i64u_{:?}_{:?}", lo, hi), 32);
1516 state.set_vfp_reg(sd, result);
1517 }
1518
1519 ArmOp::F32ReinterpretI32 { sd, rm } => {
1521 let bits = state.get_reg(rm).clone();
1524 state.set_vfp_reg(sd, bits);
1525 }
1526
1527 ArmOp::I32ReinterpretF32 { rd, sm } => {
1528 let bits = state.get_vfp_reg(sm).clone();
1531 state.set_reg(rd, bits);
1532 }
1533
1534 ArmOp::F64Add { dd, dn, dm } => {
1540 let result = BV::new_const(format!("f64_add_{:?}_{:?}", dn, dm), 64);
1544 state.set_vfp_reg(dd, result);
1545 }
1546
1547 ArmOp::F64Sub { dd, dn, dm } => {
1548 let result = BV::new_const(format!("f64_sub_{:?}_{:?}", dn, dm), 64);
1550 state.set_vfp_reg(dd, result);
1551 }
1552
1553 ArmOp::F64Mul { dd, dn, dm } => {
1554 let result = BV::new_const(format!("f64_mul_{:?}_{:?}", dn, dm), 64);
1556 state.set_vfp_reg(dd, result);
1557 }
1558
1559 ArmOp::F64Div { dd, dn, dm } => {
1560 let result = BV::new_const(format!("f64_div_{:?}_{:?}", dn, dm), 64);
1562 state.set_vfp_reg(dd, result);
1563 }
1564
1565 ArmOp::F64Abs { dd, dm } => {
1567 let val = state.get_vfp_reg(dm).clone();
1570 let mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64); let result = val.bvand(&mask);
1572 state.set_vfp_reg(dd, result);
1573 }
1574
1575 ArmOp::F64Neg { dd, dm } => {
1576 let val = state.get_vfp_reg(dm).clone();
1579 let mask = BV::from_u64(0x8000000000000000, 64); let result = val.bvxor(&mask);
1581 state.set_vfp_reg(dd, result);
1582 }
1583
1584 ArmOp::F64Sqrt { dd, dm } => {
1585 let result = BV::new_const(format!("f64_sqrt_{:?}", dm), 64);
1588 state.set_vfp_reg(dd, result);
1589 }
1590
1591 ArmOp::F64Min { dd, dn, dm } => {
1592 let result = BV::new_const(format!("f64_min_{:?}_{:?}", dn, dm), 64);
1596 state.set_vfp_reg(dd, result);
1597 }
1598
1599 ArmOp::F64Max { dd, dn, dm } => {
1600 let result = BV::new_const(format!("f64_max_{:?}_{:?}", dn, dm), 64);
1604 state.set_vfp_reg(dd, result);
1605 }
1606
1607 ArmOp::F64Copysign { dd, dn, dm } => {
1608 let val_n = state.get_vfp_reg(dn).clone();
1611 let val_m = state.get_vfp_reg(dm).clone();
1612
1613 let mag_mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64);
1615 let magnitude = val_n.bvand(&mag_mask);
1616
1617 let sign_mask = BV::from_u64(0x8000000000000000, 64);
1619 let sign = val_m.bvand(&sign_mask);
1620
1621 let result = magnitude.bvor(&sign);
1623 state.set_vfp_reg(dd, result);
1624 }
1625
1626 ArmOp::F64Ceil { dd, dm } => {
1628 let result = BV::new_const(format!("f64_ceil_{:?}", dm), 64);
1630 state.set_vfp_reg(dd, result);
1631 }
1632
1633 ArmOp::F64Floor { dd, dm } => {
1634 let result = BV::new_const(format!("f64_floor_{:?}", dm), 64);
1636 state.set_vfp_reg(dd, result);
1637 }
1638
1639 ArmOp::F64Trunc { dd, dm } => {
1640 let result = BV::new_const(format!("f64_trunc_{:?}", dm), 64);
1642 state.set_vfp_reg(dd, result);
1643 }
1644
1645 ArmOp::F64Nearest { dd, dm } => {
1646 let result = BV::new_const(format!("f64_nearest_{:?}", dm), 64);
1648 state.set_vfp_reg(dd, result);
1649 }
1650
1651 ArmOp::F64Load { dd, addr } => {
1653 let result = BV::new_const(format!("f64_load_{:?}", addr), 64);
1656 state.set_vfp_reg(dd, result);
1657 }
1658
1659 ArmOp::F64Store { dd: _, addr: _ } => {
1660 }
1664
1665 ArmOp::F64Const { dd, value } => {
1666 let bits = value.to_bits() as i64;
1668 let result = BV::from_i64(bits, 64);
1669 state.set_vfp_reg(dd, result);
1670 }
1671
1672 ArmOp::F64Eq { rd, dn, dm } => {
1674 let result = BV::new_const(format!("f64_eq_{:?}_{:?}", dn, dm), 32);
1677 state.set_reg(rd, result);
1678 }
1679
1680 ArmOp::F64Ne { rd, dn, dm } => {
1681 let result = BV::new_const(format!("f64_ne_{:?}_{:?}", dn, dm), 32);
1683 state.set_reg(rd, result);
1684 }
1685
1686 ArmOp::F64Lt { rd, dn, dm } => {
1687 let result = BV::new_const(format!("f64_lt_{:?}_{:?}", dn, dm), 32);
1689 state.set_reg(rd, result);
1690 }
1691
1692 ArmOp::F64Le { rd, dn, dm } => {
1693 let result = BV::new_const(format!("f64_le_{:?}_{:?}", dn, dm), 32);
1695 state.set_reg(rd, result);
1696 }
1697
1698 ArmOp::F64Gt { rd, dn, dm } => {
1699 let result = BV::new_const(format!("f64_gt_{:?}_{:?}", dn, dm), 32);
1701 state.set_reg(rd, result);
1702 }
1703
1704 ArmOp::F64Ge { rd, dn, dm } => {
1705 let result = BV::new_const(format!("f64_ge_{:?}_{:?}", dn, dm), 32);
1707 state.set_reg(rd, result);
1708 }
1709
1710 ArmOp::F64ConvertI32S { dd, rm } => {
1712 let result = BV::new_const(format!("f64_convert_i32s_{:?}", rm), 64);
1715 state.set_vfp_reg(dd, result);
1716 }
1717
1718 ArmOp::F64ConvertI32U { dd, rm } => {
1719 let result = BV::new_const(format!("f64_convert_i32u_{:?}", rm), 64);
1722 state.set_vfp_reg(dd, result);
1723 }
1724
1725 ArmOp::F64ConvertI64S {
1726 dd,
1727 rmlo: _,
1728 rmhi: _,
1729 } => {
1730 let result = BV::new_const("f64_convert_i64s_result", 64);
1733 state.set_vfp_reg(dd, result);
1734 }
1735
1736 ArmOp::F64ConvertI64U {
1737 dd,
1738 rmlo: _,
1739 rmhi: _,
1740 } => {
1741 let result = BV::new_const("f64_convert_i64u_result", 64);
1744 state.set_vfp_reg(dd, result);
1745 }
1746
1747 ArmOp::F64PromoteF32 { dd, sm } => {
1748 let result = BV::new_const(format!("f64_promote_f32_{:?}", sm), 64);
1751 state.set_vfp_reg(dd, result);
1752 }
1753
1754 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
1755 let lo = state.get_reg(rmlo).clone();
1758 let hi = state.get_reg(rmhi).clone();
1759
1760 let lo_64 = lo.zero_ext(32); let hi_64 = hi.zero_ext(32);
1763 let shift_32 = BV::from_u64(32, 64);
1764 let hi_shifted = hi_64.bvshl(&shift_32);
1765 let result = hi_shifted.bvor(&lo_64);
1766
1767 state.set_vfp_reg(dd, result);
1768 }
1769
1770 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
1771 let bits = state.get_vfp_reg(dm).clone();
1774
1775 let lo = bits.extract(31, 0);
1777 state.set_reg(rdlo, lo);
1778
1779 let hi = bits.extract(63, 32);
1781 state.set_reg(rdhi, hi);
1782 }
1783
1784 ArmOp::I64TruncF64S {
1785 rdlo: _,
1786 rdhi: _,
1787 dm: _,
1788 } => {
1789 }
1793
1794 ArmOp::I64TruncF64U {
1795 rdlo: _,
1796 rdhi: _,
1797 dm: _,
1798 } => {
1799 }
1803
1804 ArmOp::I32TruncF64S { rd, dm } => {
1805 let result = BV::new_const(format!("i32_trunc_f64s_{:?}", dm), 32);
1808 state.set_reg(rd, result);
1809 }
1810
1811 ArmOp::I32TruncF64U { rd, dm } => {
1812 let result = BV::new_const(format!("i32_trunc_f64u_{:?}", dm), 32);
1815 state.set_reg(rd, result);
1816 }
1817
1818 _ => {
1819 }
1821 }
1822 }
1823
1824 fn evaluate_operand2(&self, op2: &Operand2, state: &ArmState) -> BV {
1826 match op2 {
1827 Operand2::Imm(value) => BV::from_i64(*value as i64, 32),
1828 Operand2::Reg(reg) => state.get_reg(reg).clone(),
1829 Operand2::RegShift { rm, shift, amount } => {
1830 let reg_val = state.get_reg(rm).clone();
1831 let shift_amount = BV::from_i64(*amount as i64, 32);
1832
1833 match shift {
1834 synth_synthesis::ShiftType::LSL => reg_val.bvshl(&shift_amount),
1835 synth_synthesis::ShiftType::LSR => reg_val.bvlshr(&shift_amount),
1836 synth_synthesis::ShiftType::ASR => reg_val.bvashr(&shift_amount),
1837 synth_synthesis::ShiftType::ROR => reg_val.bvrotr(&shift_amount),
1838 }
1839 }
1840 }
1841 }
1842
1843 pub fn extract_result(&self, state: &ArmState, reg: &Reg) -> BV {
1845 state.get_reg(reg).clone()
1846 }
1847
1848 fn encode_clz(&self, input: &BV) -> BV {
1853 let zero = BV::from_i64(0, 32);
1854
1855 let all_zero = input.eq(&zero);
1857 let result_if_zero = BV::from_i64(32, 32);
1858
1859 let mut count = BV::from_i64(0, 32);
1861 let mut remaining = input.clone();
1862
1863 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1865 let top_16 = remaining.bvand(&mask_16);
1866 let top_16_zero = top_16.eq(&zero);
1867
1868 count = top_16_zero.ite(count.bvadd(BV::from_i64(16, 32)), &count);
1869 remaining = top_16_zero.ite(remaining.bvshl(BV::from_i64(16, 32)), &remaining);
1870
1871 let mask_8 = BV::from_u64(0xFF000000, 32);
1873 let top_8 = remaining.bvand(&mask_8);
1874 let top_8_zero = top_8.eq(&zero);
1875
1876 count = top_8_zero.ite(count.bvadd(BV::from_i64(8, 32)), &count);
1877 remaining = top_8_zero.ite(remaining.bvshl(BV::from_i64(8, 32)), &remaining);
1878
1879 let mask_4 = BV::from_u64(0xF0000000, 32);
1881 let top_4 = remaining.bvand(&mask_4);
1882 let top_4_zero = top_4.eq(&zero);
1883
1884 count = top_4_zero.ite(count.bvadd(BV::from_i64(4, 32)), &count);
1885 remaining = top_4_zero.ite(remaining.bvshl(BV::from_i64(4, 32)), &remaining);
1886
1887 let mask_2 = BV::from_u64(0xC0000000, 32);
1889 let top_2 = remaining.bvand(&mask_2);
1890 let top_2_zero = top_2.eq(&zero);
1891
1892 count = top_2_zero.ite(count.bvadd(BV::from_i64(2, 32)), &count);
1893 remaining = top_2_zero.ite(remaining.bvshl(BV::from_i64(2, 32)), &remaining);
1894
1895 let mask_1 = BV::from_u64(0x80000000, 32);
1897 let top_1 = remaining.bvand(&mask_1);
1898 let top_1_zero = top_1.eq(&zero);
1899
1900 count = top_1_zero.ite(count.bvadd(BV::from_i64(1, 32)), &count);
1901
1902 all_zero.ite(&result_if_zero, &count)
1904 }
1905
1906 fn encode_ctz(&self, input: &BV) -> BV {
1912 let reversed = self.encode_rbit(input);
1914 self.encode_clz(&reversed)
1915 }
1916
1917 fn encode_rbit(&self, input: &BV) -> BV {
1922 let mut result = input.clone();
1924
1925 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1927 let top_16 = result.bvand(&mask_16).bvlshr(BV::from_i64(16, 32));
1928 let bottom_16 = result.bvshl(BV::from_i64(16, 32));
1929 result = top_16.bvor(&bottom_16);
1930
1931 let mask_8_top = BV::from_u64(0xFF00FF00, 32);
1933 let mask_8_bottom = BV::from_u64(0x00FF00FF, 32);
1934 let top_8 = result.bvand(&mask_8_top).bvlshr(BV::from_i64(8, 32));
1935 let bottom_8 = result.bvand(&mask_8_bottom).bvshl(BV::from_i64(8, 32));
1936 result = top_8.bvor(&bottom_8);
1937
1938 let mask_4_top = BV::from_u64(0xF0F0F0F0, 32);
1940 let mask_4_bottom = BV::from_u64(0x0F0F0F0F, 32);
1941 let top_4 = result.bvand(&mask_4_top).bvlshr(BV::from_i64(4, 32));
1942 let bottom_4 = result.bvand(&mask_4_bottom).bvshl(BV::from_i64(4, 32));
1943 result = top_4.bvor(&bottom_4);
1944
1945 let mask_2_top = BV::from_u64(0xCCCCCCCC, 32);
1947 let mask_2_bottom = BV::from_u64(0x33333333, 32);
1948 let top_2 = result.bvand(&mask_2_top).bvlshr(BV::from_i64(2, 32));
1949 let bottom_2 = result.bvand(&mask_2_bottom).bvshl(BV::from_i64(2, 32));
1950 result = top_2.bvor(&bottom_2);
1951
1952 let mask_1_top = BV::from_u64(0xAAAAAAAA, 32);
1954 let mask_1_bottom = BV::from_u64(0x55555555, 32);
1955 let top_1 = result.bvand(&mask_1_top).bvlshr(BV::from_i64(1, 32));
1956 let bottom_1 = result.bvand(&mask_1_bottom).bvshl(BV::from_i64(1, 32));
1957 result = top_1.bvor(&bottom_1);
1958
1959 result
1960 }
1961
1962 fn update_flags_sub(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
1974 let zero = BV::from_i64(0, 32);
1975
1976 let sign_bit = result.extract(31, 31);
1978 let one_bit = BV::from_i64(1, 1);
1979 state.flags.n = sign_bit.eq(&one_bit);
1980
1981 state.flags.z = result.eq(&zero);
1983
1984 state.flags.c = a.bvuge(b);
1988
1989 let a_sign = a.extract(31, 31);
1995 let b_sign = b.extract(31, 31);
1996 let r_sign = result.extract(31, 31);
1997
1998 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]);
2001 }
2002
2003 #[allow(dead_code)]
2009 fn update_flags_add(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
2010 let zero = BV::from_i64(0, 32);
2011
2012 let sign_bit = result.extract(31, 31);
2014 let one_bit = BV::from_i64(1, 1);
2015 state.flags.n = sign_bit.eq(&one_bit);
2016
2017 state.flags.z = result.eq(&zero);
2019
2020 state.flags.c = result.bvult(a);
2024
2025 let a_sign = a.extract(31, 31);
2031 let b_sign = b.extract(31, 31);
2032 let r_sign = result.extract(31, 31);
2033
2034 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]);
2037 }
2038
2039 fn evaluate_condition(
2053 &self,
2054 cond: &synth_synthesis::rules::Condition,
2055 flags: &ConditionFlags,
2056 ) -> Bool {
2057 use synth_synthesis::rules::Condition;
2058
2059 match cond {
2060 Condition::EQ => flags.z.clone(),
2061 Condition::NE => flags.z.not(),
2062 Condition::LT => {
2063 flags.n.eq(&flags.v).not()
2065 }
2066 Condition::LE => {
2067 let n_ne_v = flags.n.eq(&flags.v).not();
2069 Bool::or(&[&flags.z, &n_ne_v])
2070 }
2071 Condition::GT => {
2072 let z_zero = flags.z.not();
2074 let n_eq_v = flags.n.eq(&flags.v);
2075 Bool::and(&[&z_zero, &n_eq_v])
2076 }
2077 Condition::GE => {
2078 flags.n.eq(&flags.v)
2080 }
2081 Condition::LO => {
2082 flags.c.not()
2084 }
2085 Condition::LS => {
2086 let c_zero = flags.c.not();
2088 Bool::or(&[&flags.z, &c_zero])
2089 }
2090 Condition::HI => {
2091 let z_zero = flags.z.not();
2093 Bool::and(&[&flags.c, &z_zero])
2094 }
2095 Condition::HS => {
2096 flags.c.clone()
2098 }
2099 }
2100 }
2101
2102 fn bool_to_bv32(&self, cond: &Bool) -> BV {
2104 let zero = BV::from_i64(0, 32);
2105 let one = BV::from_i64(1, 32);
2106 cond.ite(&one, &zero)
2107 }
2108
2109 fn encode_popcnt(&self, input: &BV) -> BV {
2114 let mut x = input.clone();
2115
2116 let mask1 = BV::from_u64(0x55555555, 32);
2118 let masked = x.bvand(&mask1);
2119 let shifted = x.bvlshr(BV::from_i64(1, 32));
2120 let shifted_masked = shifted.bvand(&mask1);
2121 x = masked.bvadd(&shifted_masked);
2122
2123 let mask2 = BV::from_u64(0x33333333, 32);
2125 let masked = x.bvand(&mask2);
2126 let shifted = x.bvlshr(BV::from_i64(2, 32));
2127 let shifted_masked = shifted.bvand(&mask2);
2128 x = masked.bvadd(&shifted_masked);
2129
2130 let mask3 = BV::from_u64(0x0F0F0F0F, 32);
2132 let masked = x.bvand(&mask3);
2133 let shifted = x.bvlshr(BV::from_i64(4, 32));
2134 let shifted_masked = shifted.bvand(&mask3);
2135 x = masked.bvadd(&shifted_masked);
2136
2137 let multiplier = BV::from_u64(0x01010101, 32);
2139 x = x.bvmul(&multiplier);
2140 x = x.bvlshr(BV::from_i64(24, 32));
2141
2142 x
2143 }
2144}
2145
2146#[cfg(test)]
2147mod tests {
2148 use super::*;
2149 use crate::with_verification_context;
2150
2151 #[test]
2152 fn test_arm_add_semantics() {
2153 with_verification_context(|| {
2154 let encoder = ArmSemantics::new();
2155 let mut state = ArmState::new_symbolic();
2156
2157 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2159 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2160
2161 let op = ArmOp::Add {
2163 rd: Reg::R0,
2164 rn: Reg::R1,
2165 op2: Operand2::Reg(Reg::R2),
2166 };
2167
2168 encoder.encode_op(&op, &mut state);
2169
2170 let result = state.get_reg(&Reg::R0).simplify();
2172 assert_eq!(result.as_i64(), Some(30));
2173 });
2174 }
2175
2176 #[test]
2177 fn test_arm_sub_semantics() {
2178 with_verification_context(|| {
2179 let encoder = ArmSemantics::new();
2180 let mut state = ArmState::new_symbolic();
2181
2182 state.set_reg(&Reg::R1, BV::from_i64(50, 32));
2183 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2184
2185 let op = ArmOp::Sub {
2186 rd: Reg::R0,
2187 rn: Reg::R1,
2188 op2: Operand2::Reg(Reg::R2),
2189 };
2190
2191 encoder.encode_op(&op, &mut state);
2192
2193 let result = state.get_reg(&Reg::R0);
2194 assert_eq!(result.simplify().as_i64(), Some(30));
2195 });
2196 }
2197
2198 #[test]
2199 fn test_arm_mov_immediate() {
2200 with_verification_context(|| {
2201 let encoder = ArmSemantics::new();
2202 let mut state = ArmState::new_symbolic();
2203
2204 let op = ArmOp::Mov {
2205 rd: Reg::R0,
2206 op2: Operand2::Imm(42),
2207 };
2208
2209 encoder.encode_op(&op, &mut state);
2210
2211 let result = state.get_reg(&Reg::R0);
2212 assert_eq!(result.simplify().as_i64(), Some(42));
2213 });
2214 }
2215
2216 #[test]
2217 fn test_arm_bitwise_ops() {
2218 with_verification_context(|| {
2219 let encoder = ArmSemantics::new();
2220 let mut state = ArmState::new_symbolic();
2221
2222 state.set_reg(&Reg::R1, BV::from_i64(0b1010, 32));
2223 state.set_reg(&Reg::R2, BV::from_i64(0b1100, 32));
2224
2225 let and_op = ArmOp::And {
2227 rd: Reg::R0,
2228 rn: Reg::R1,
2229 op2: Operand2::Reg(Reg::R2),
2230 };
2231 encoder.encode_op(&and_op, &mut state);
2232 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1000));
2233
2234 let orr_op = ArmOp::Orr {
2236 rd: Reg::R0,
2237 rn: Reg::R1,
2238 op2: Operand2::Reg(Reg::R2),
2239 };
2240 encoder.encode_op(&orr_op, &mut state);
2241 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1110));
2242
2243 let eor_op = ArmOp::Eor {
2245 rd: Reg::R0,
2246 rn: Reg::R1,
2247 op2: Operand2::Reg(Reg::R2),
2248 };
2249 encoder.encode_op(&eor_op, &mut state);
2250 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b0110));
2251 });
2252 }
2253
2254 #[test]
2255 fn test_arm_mls() {
2256 with_verification_context(|| {
2259 let encoder = ArmSemantics::new();
2260 let mut state = ArmState::new_symbolic();
2261
2262 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 {
2269 rd: Reg::R3,
2270 rn: Reg::R1,
2271 rm: Reg::R2,
2272 ra: Reg::R0,
2273 };
2274 encoder.encode_op(&mls_op, &mut state);
2275 assert_eq!(
2276 state.get_reg(&Reg::R3).simplify().as_i64(),
2277 Some(2),
2278 "MLS: 17 - 3*5 = 2"
2279 );
2280
2281 state.set_reg(&Reg::R0, BV::from_i64(100, 32));
2283 state.set_reg(&Reg::R1, BV::from_i64(7, 32));
2284 state.set_reg(&Reg::R2, BV::from_i64(3, 32));
2285
2286 let mls_op2 = ArmOp::Mls {
2287 rd: Reg::R3,
2288 rn: Reg::R1,
2289 rm: Reg::R2,
2290 ra: Reg::R0,
2291 };
2292 encoder.encode_op(&mls_op2, &mut state);
2293 assert_eq!(
2294 state.get_reg(&Reg::R3).simplify().as_i64(),
2295 Some(79),
2296 "MLS: 100 - 7*3 = 79"
2297 );
2298
2299 state.set_reg(&Reg::R0, BV::from_i64(-17, 32));
2301 state.set_reg(&Reg::R1, BV::from_i64(3, 32));
2302 state.set_reg(&Reg::R2, BV::from_i64(5, 32));
2303
2304 let mls_op3 = ArmOp::Mls {
2305 rd: Reg::R3,
2306 rn: Reg::R1,
2307 rm: Reg::R2,
2308 ra: Reg::R0,
2309 };
2310 encoder.encode_op(&mls_op3, &mut state);
2311 let result = state.get_reg(&Reg::R3).simplify().as_i64();
2313 let signed_result = result.map(|v| (v as i32) as i64);
2314 assert_eq!(signed_result, Some(-32), "MLS: -17 - 3*5 = -32");
2315 });
2316 }
2317
2318 #[test]
2319 fn test_arm_shift_ops() {
2320 with_verification_context(|| {
2321 let encoder = ArmSemantics::new();
2322 let mut state = ArmState::new_symbolic();
2323
2324 state.set_reg(&Reg::R1, BV::from_i64(8, 32));
2325
2326 let lsl_op = ArmOp::Lsl {
2328 rd: Reg::R0,
2329 rn: Reg::R1,
2330 shift: 2,
2331 };
2332 encoder.encode_op(&lsl_op, &mut state);
2333 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(32));
2334
2335 let lsr_op = ArmOp::Lsr {
2337 rd: Reg::R0,
2338 rn: Reg::R1,
2339 shift: 2,
2340 };
2341 encoder.encode_op(&lsr_op, &mut state);
2342 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(2));
2343 });
2344 }
2345
2346 #[test]
2347 fn test_arm_ror_comprehensive() {
2348 with_verification_context(|| {
2349 let encoder = ArmSemantics::new();
2350 let mut state = ArmState::new_symbolic();
2351
2352 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2355 let ror_op = ArmOp::Ror {
2356 rd: Reg::R0,
2357 rn: Reg::R1,
2358 shift: 8,
2359 };
2360 encoder.encode_op(&ror_op, &mut state);
2361 assert_eq!(
2363 state.get_reg(&Reg::R0).simplify().as_i64(),
2364 Some(0x78123456),
2365 "ROR by 8"
2366 );
2367
2368 let ror_op_16 = ArmOp::Ror {
2370 rd: Reg::R0,
2371 rn: Reg::R1,
2372 shift: 16,
2373 };
2374 encoder.encode_op(&ror_op_16, &mut state);
2375 assert_eq!(
2377 state.get_reg(&Reg::R0).simplify().as_i64(),
2378 Some(0x56781234),
2379 "ROR by 16"
2380 );
2381
2382 let ror_op_0 = ArmOp::Ror {
2384 rd: Reg::R0,
2385 rn: Reg::R1,
2386 shift: 0,
2387 };
2388 encoder.encode_op(&ror_op_0, &mut state);
2389 assert_eq!(
2390 state.get_reg(&Reg::R0).simplify().as_i64(),
2391 Some(0x12345678),
2392 "ROR by 0"
2393 );
2394
2395 let ror_op_32 = ArmOp::Ror {
2397 rd: Reg::R0,
2398 rn: Reg::R1,
2399 shift: 32,
2400 };
2401 encoder.encode_op(&ror_op_32, &mut state);
2402 assert_eq!(
2403 state.get_reg(&Reg::R0).simplify().as_i64(),
2404 Some(0x12345678),
2405 "ROR by 32"
2406 );
2407
2408 state.set_reg(&Reg::R1, BV::from_u64(0xABCDEF01, 32));
2410 let ror_op_4 = ArmOp::Ror {
2411 rd: Reg::R0,
2412 rn: Reg::R1,
2413 shift: 4,
2414 };
2415 encoder.encode_op(&ror_op_4, &mut state);
2416 assert_eq!(
2418 state.get_reg(&Reg::R0).simplify().as_i64(),
2419 Some(0x1ABCDEF0),
2420 "ROR by 4"
2421 );
2422
2423 state.set_reg(&Reg::R1, BV::from_u64(0x80000001, 32));
2425 let ror_op_1 = ArmOp::Ror {
2426 rd: Reg::R0,
2427 rn: Reg::R1,
2428 shift: 1,
2429 };
2430 encoder.encode_op(&ror_op_1, &mut state);
2431 let result = state.get_reg(&Reg::R0).simplify().as_i64();
2433 let signed_result = result.map(|v| (v as i32) as i64);
2434 assert_eq!(
2435 signed_result,
2436 Some(0xC0000000_u32 as i32 as i64),
2437 "ROR by 1"
2438 );
2439 });
2440 }
2441
2442 #[test]
2443 fn test_arm_clz_comprehensive() {
2444 with_verification_context(|| {
2445 let encoder = ArmSemantics::new();
2446 let mut state = ArmState::new_symbolic();
2447
2448 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2450 let clz_op = ArmOp::Clz {
2451 rd: Reg::R0,
2452 rm: Reg::R1,
2453 };
2454 encoder.encode_op(&clz_op, &mut state);
2455 assert_eq!(
2456 state.get_reg(&Reg::R0).simplify().as_i64(),
2457 Some(32),
2458 "CLZ(0) should be 32"
2459 );
2460
2461 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2463 encoder.encode_op(&clz_op, &mut state);
2464 assert_eq!(
2465 state.get_reg(&Reg::R0).simplify().as_i64(),
2466 Some(31),
2467 "CLZ(1) should be 31"
2468 );
2469
2470 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2472 encoder.encode_op(&clz_op, &mut state);
2473 assert_eq!(
2474 state.get_reg(&Reg::R0).simplify().as_i64(),
2475 Some(0),
2476 "CLZ(0x80000000) should be 0"
2477 );
2478
2479 state.set_reg(&Reg::R1, BV::from_u64(0x00FF0000, 32));
2481 encoder.encode_op(&clz_op, &mut state);
2482 assert_eq!(
2483 state.get_reg(&Reg::R0).simplify().as_i64(),
2484 Some(8),
2485 "CLZ(0x00FF0000) should be 8"
2486 );
2487
2488 state.set_reg(&Reg::R1, BV::from_u64(0x00001000, 32));
2490 encoder.encode_op(&clz_op, &mut state);
2491 assert_eq!(
2492 state.get_reg(&Reg::R0).simplify().as_i64(),
2493 Some(19),
2494 "CLZ(0x00001000) should be 19"
2495 );
2496
2497 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2499 encoder.encode_op(&clz_op, &mut state);
2500 assert_eq!(
2501 state.get_reg(&Reg::R0).simplify().as_i64(),
2502 Some(0),
2503 "CLZ(0xFFFFFFFF) should be 0"
2504 );
2505 });
2506 }
2507
2508 #[test]
2509 fn test_arm_rbit_comprehensive() {
2510 with_verification_context(|| {
2511 let encoder = ArmSemantics::new();
2512 let mut state = ArmState::new_symbolic();
2513
2514 let rbit_op = ArmOp::Rbit {
2515 rd: Reg::R0,
2516 rm: Reg::R1,
2517 };
2518
2519 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2521 encoder.encode_op(&rbit_op, &mut state);
2522 assert_eq!(
2523 state.get_reg(&Reg::R0).simplify().as_i64(),
2524 Some(0),
2525 "RBIT(0) should be 0"
2526 );
2527
2528 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2530 encoder.encode_op(&rbit_op, &mut state);
2531 assert_eq!(
2532 state.get_reg(&Reg::R0).simplify().as_u64(),
2533 Some(0x80000000),
2534 "RBIT(1) should be 0x80000000"
2535 );
2536
2537 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2539 encoder.encode_op(&rbit_op, &mut state);
2540 assert_eq!(
2541 state.get_reg(&Reg::R0).simplify().as_i64(),
2542 Some(1),
2543 "RBIT(0x80000000) should be 1"
2544 );
2545
2546 state.set_reg(&Reg::R1, BV::from_u64(0xFF000000, 32));
2548 encoder.encode_op(&rbit_op, &mut state);
2549 assert_eq!(
2550 state.get_reg(&Reg::R0).simplify().as_u64(),
2551 Some(0x000000FF),
2552 "RBIT(0xFF000000) should be 0x000000FF"
2553 );
2554
2555 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2557 encoder.encode_op(&rbit_op, &mut state);
2558 assert_eq!(
2560 state.get_reg(&Reg::R0).simplify().as_u64(),
2561 Some(0x1E6A2C48),
2562 "RBIT(0x12345678) should be 0x1E6A2C48"
2563 );
2564
2565 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2567 encoder.encode_op(&rbit_op, &mut state);
2568 assert_eq!(
2569 state.get_reg(&Reg::R0).simplify().as_u64(),
2570 Some(0xFFFFFFFF),
2571 "RBIT(0xFFFFFFFF) should be 0xFFFFFFFF"
2572 );
2573 });
2574 }
2575
2576 #[test]
2577 fn test_arm_cmp_flags() {
2578 with_verification_context(|| {
2581 let encoder = ArmSemantics::new();
2582 let mut state = ArmState::new_symbolic();
2583
2584 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2587 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2588
2589 let cmp_op = ArmOp::Cmp {
2590 rn: Reg::R0,
2591 op2: Operand2::Reg(Reg::R1),
2592 };
2593 encoder.encode_op(&cmp_op, &mut state);
2594
2595 assert_eq!(
2596 state.flags.z.simplify().as_bool(),
2597 Some(true),
2598 "Z flag should be set (equal)"
2599 );
2600 assert_eq!(
2601 state.flags.n.simplify().as_bool(),
2602 Some(false),
2603 "N flag should be clear (non-negative)"
2604 );
2605 assert_eq!(
2606 state.flags.c.simplify().as_bool(),
2607 Some(true),
2608 "C flag should be set (no borrow)"
2609 );
2610 assert_eq!(
2611 state.flags.v.simplify().as_bool(),
2612 Some(false),
2613 "V flag should be clear (no overflow)"
2614 );
2615
2616 state.set_reg(&Reg::R0, BV::from_i64(20, 32));
2619 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2620 encoder.encode_op(&cmp_op, &mut state);
2621
2622 assert_eq!(
2623 state.flags.z.simplify().as_bool(),
2624 Some(false),
2625 "Z flag should be clear (not equal)"
2626 );
2627 assert_eq!(
2628 state.flags.n.simplify().as_bool(),
2629 Some(false),
2630 "N flag should be clear (positive result)"
2631 );
2632 assert_eq!(
2633 state.flags.c.simplify().as_bool(),
2634 Some(true),
2635 "C flag should be set (no borrow)"
2636 );
2637 assert_eq!(
2638 state.flags.v.simplify().as_bool(),
2639 Some(false),
2640 "V flag should be clear (no overflow)"
2641 );
2642
2643 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2647 state.set_reg(&Reg::R1, BV::from_i64(20, 32));
2648 encoder.encode_op(&cmp_op, &mut state);
2649
2650 assert_eq!(
2651 state.flags.z.simplify().as_bool(),
2652 Some(false),
2653 "Z flag should be clear"
2654 );
2655 assert_eq!(
2656 state.flags.n.simplify().as_bool(),
2657 Some(true),
2658 "N flag should be set (negative result)"
2659 );
2660 assert_eq!(
2661 state.flags.c.simplify().as_bool(),
2662 Some(false),
2663 "C flag should be clear (borrow occurred)"
2664 );
2665 assert_eq!(
2666 state.flags.v.simplify().as_bool(),
2667 Some(false),
2668 "V flag should be clear"
2669 );
2670
2671 state.set_reg(&Reg::R0, BV::from_i64(0x7FFFFFFF, 32));
2676 state.set_reg(&Reg::R1, BV::from_i64(-2147483648i64, 32)); encoder.encode_op(&cmp_op, &mut state);
2678
2679 assert_eq!(
2680 state.flags.z.simplify().as_bool(),
2681 Some(false),
2682 "Z flag should be clear"
2683 );
2684 assert_eq!(
2685 state.flags.n.simplify().as_bool(),
2686 Some(true),
2687 "N flag should be set (wrapped result)"
2688 );
2689 assert_eq!(
2690 state.flags.c.simplify().as_bool(),
2691 Some(false),
2692 "C flag should be clear"
2693 );
2694 assert_eq!(
2695 state.flags.v.simplify().as_bool(),
2696 Some(true),
2697 "V flag should be set (overflow)"
2698 );
2699
2700 state.set_reg(&Reg::R0, BV::from_i64(0, 32));
2702 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2703 encoder.encode_op(&cmp_op, &mut state);
2704
2705 assert_eq!(
2706 state.flags.z.simplify().as_bool(),
2707 Some(true),
2708 "Z flag should be set (0 - 0 = 0)"
2709 );
2710 assert_eq!(
2711 state.flags.n.simplify().as_bool(),
2712 Some(false),
2713 "N flag should be clear"
2714 );
2715 assert_eq!(
2716 state.flags.c.simplify().as_bool(),
2717 Some(true),
2718 "C flag should be set"
2719 );
2720 assert_eq!(
2721 state.flags.v.simplify().as_bool(),
2722 Some(false),
2723 "V flag should be clear"
2724 );
2725 });
2726 }
2727
2728 #[test]
2729 fn test_arm_flags_all_combinations() {
2730 with_verification_context(|| {
2733 let encoder = ArmSemantics::new();
2734 let mut state = ArmState::new_symbolic();
2735
2736 let cmp_op = ArmOp::Cmp {
2737 rn: Reg::R0,
2738 op2: Operand2::Reg(Reg::R1),
2739 };
2740
2741 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2752 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2753 encoder.encode_op(&cmp_op, &mut state);
2754
2755 let n = state.flags.n.simplify().as_bool().unwrap();
2756 let z = state.flags.z.simplify().as_bool().unwrap();
2757 let v = state.flags.v.simplify().as_bool().unwrap();
2758
2759 assert!(!z, "Not equal");
2760 assert!(n != v, "5 < 10 signed (N != V)");
2761
2762 state.set_reg(&Reg::R0, BV::from_i64(-5, 32));
2764 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2765 encoder.encode_op(&cmp_op, &mut state);
2766
2767 let n = state.flags.n.simplify().as_bool().unwrap();
2768 let v = state.flags.v.simplify().as_bool().unwrap();
2769 assert!(n != v, "-5 < 10 signed (N != V)");
2770 });
2771 }
2772
2773 #[test]
2774 fn test_arm_setcond_eq() {
2775 with_verification_context(|| {
2776 let encoder = ArmSemantics::new();
2777 let mut state = ArmState::new_symbolic();
2778
2779 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2781 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2782
2783 let cmp_op = ArmOp::Cmp {
2785 rn: Reg::R0,
2786 op2: Operand2::Reg(Reg::R1),
2787 };
2788 encoder.encode_op(&cmp_op, &mut state);
2789
2790 let setcond_op = ArmOp::SetCond {
2792 rd: Reg::R0,
2793 cond: synth_synthesis::Condition::EQ,
2794 };
2795 encoder.encode_op(&setcond_op, &mut state);
2796
2797 assert_eq!(
2798 state.get_reg(&Reg::R0).simplify().as_i64(),
2799 Some(1),
2800 "EQ condition (10 == 10) should return 1"
2801 );
2802
2803 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2805 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2806
2807 encoder.encode_op(&cmp_op, &mut state);
2808
2809 let setcond_ne = ArmOp::SetCond {
2810 rd: Reg::R0,
2811 cond: synth_synthesis::Condition::NE,
2812 };
2813 encoder.encode_op(&setcond_ne, &mut state);
2814
2815 assert_eq!(
2816 state.get_reg(&Reg::R0).simplify().as_i64(),
2817 Some(1),
2818 "NE condition (10 != 5) should return 1"
2819 );
2820 });
2821 }
2822
2823 #[test]
2824 fn test_arm_setcond_signed() {
2825 with_verification_context(|| {
2826 let encoder = ArmSemantics::new();
2827 let mut state = ArmState::new_symbolic();
2828
2829 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2831 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2832
2833 let cmp_op = ArmOp::Cmp {
2834 rn: Reg::R0,
2835 op2: Operand2::Reg(Reg::R1),
2836 };
2837 encoder.encode_op(&cmp_op, &mut state);
2838
2839 let setcond_lt = ArmOp::SetCond {
2840 rd: Reg::R0,
2841 cond: synth_synthesis::Condition::LT,
2842 };
2843 encoder.encode_op(&setcond_lt, &mut state);
2844
2845 assert_eq!(
2846 state.get_reg(&Reg::R0).simplify().as_i64(),
2847 Some(1),
2848 "LT signed (5 < 10) should return 1"
2849 );
2850
2851 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2853 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2854
2855 encoder.encode_op(&cmp_op, &mut state);
2856
2857 let setcond_ge = ArmOp::SetCond {
2858 rd: Reg::R0,
2859 cond: synth_synthesis::Condition::GE,
2860 };
2861 encoder.encode_op(&setcond_ge, &mut state);
2862
2863 assert_eq!(
2864 state.get_reg(&Reg::R0).simplify().as_i64(),
2865 Some(1),
2866 "GE signed (10 >= 5) should return 1"
2867 );
2868
2869 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2871 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2872
2873 encoder.encode_op(&cmp_op, &mut state);
2874
2875 let setcond_gt = ArmOp::SetCond {
2876 rd: Reg::R0,
2877 cond: synth_synthesis::Condition::GT,
2878 };
2879 encoder.encode_op(&setcond_gt, &mut state);
2880
2881 assert_eq!(
2882 state.get_reg(&Reg::R0).simplify().as_i64(),
2883 Some(1),
2884 "GT signed (10 > 5) should return 1"
2885 );
2886
2887 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2889 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2890
2891 encoder.encode_op(&cmp_op, &mut state);
2892
2893 let setcond_le = ArmOp::SetCond {
2894 rd: Reg::R0,
2895 cond: synth_synthesis::Condition::LE,
2896 };
2897 encoder.encode_op(&setcond_le, &mut state);
2898
2899 assert_eq!(
2900 state.get_reg(&Reg::R0).simplify().as_i64(),
2901 Some(1),
2902 "LE signed (5 <= 10) should return 1"
2903 );
2904 });
2905 }
2906
2907 #[test]
2908 fn test_arm_setcond_unsigned() {
2909 with_verification_context(|| {
2910 let encoder = ArmSemantics::new();
2911 let mut state = ArmState::new_symbolic();
2912
2913 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2915 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2916
2917 let cmp_op = ArmOp::Cmp {
2918 rn: Reg::R0,
2919 op2: Operand2::Reg(Reg::R1),
2920 };
2921 encoder.encode_op(&cmp_op, &mut state);
2922
2923 let setcond_lo = ArmOp::SetCond {
2924 rd: Reg::R0,
2925 cond: synth_synthesis::Condition::LO,
2926 };
2927 encoder.encode_op(&setcond_lo, &mut state);
2928
2929 assert_eq!(
2930 state.get_reg(&Reg::R0).simplify().as_i64(),
2931 Some(1),
2932 "LO unsigned (5 < 10) should return 1"
2933 );
2934
2935 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2937 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2938
2939 encoder.encode_op(&cmp_op, &mut state);
2940
2941 let setcond_hs = ArmOp::SetCond {
2942 rd: Reg::R0,
2943 cond: synth_synthesis::Condition::HS,
2944 };
2945 encoder.encode_op(&setcond_hs, &mut state);
2946
2947 assert_eq!(
2948 state.get_reg(&Reg::R0).simplify().as_i64(),
2949 Some(1),
2950 "HS unsigned (10 >= 5) should return 1"
2951 );
2952
2953 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2955 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2956
2957 encoder.encode_op(&cmp_op, &mut state);
2958
2959 let setcond_hi = ArmOp::SetCond {
2960 rd: Reg::R0,
2961 cond: synth_synthesis::Condition::HI,
2962 };
2963 encoder.encode_op(&setcond_hi, &mut state);
2964
2965 assert_eq!(
2966 state.get_reg(&Reg::R0).simplify().as_i64(),
2967 Some(1),
2968 "HI unsigned (10 > 5) should return 1"
2969 );
2970
2971 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2973 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2974
2975 encoder.encode_op(&cmp_op, &mut state);
2976
2977 let setcond_ls = ArmOp::SetCond {
2978 rd: Reg::R0,
2979 cond: synth_synthesis::Condition::LS,
2980 };
2981 encoder.encode_op(&setcond_ls, &mut state);
2982
2983 assert_eq!(
2984 state.get_reg(&Reg::R0).simplify().as_i64(),
2985 Some(1),
2986 "LS unsigned (5 <= 10) should return 1"
2987 );
2988 });
2989 }
2990}