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 } => {
483 let _table_index = state.get_reg(table_index_reg).clone();
485 let result = BV::new_const(format!("call_indirect_{}", type_idx), 32);
486 state.set_reg(rd, result);
487 }
488
489 ArmOp::I64Const { rdlo, rdhi, value } => {
495 let low32 = (*value as u32) as i64;
497 let high32 = *value >> 32;
498 state.set_reg(rdlo, BV::from_i64(low32, 32));
499 state.set_reg(rdhi, BV::from_i64(high32, 32));
500 }
501
502 ArmOp::I64Add {
503 rdlo,
504 rdhi,
505 rnlo,
506 rnhi,
507 rmlo,
508 rmhi,
509 } => {
510 let n_low = state.get_reg(rnlo).clone();
515 let m_low = state.get_reg(rmlo).clone();
516 let n_high = state.get_reg(rnhi).clone();
517 let m_high = state.get_reg(rmhi).clone();
518
519 let result_low = n_low.bvadd(&m_low);
521 state.set_reg(rdlo, result_low.clone());
522
523 let carry = result_low.bvult(&n_low);
526 let carry_bv = carry.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
527
528 let high_sum = n_high.bvadd(&m_high);
530 let result_high = high_sum.bvadd(&carry_bv);
531 state.set_reg(rdhi, result_high);
532 }
533
534 ArmOp::I64Eqz { rd, rnlo, rnhi } => {
535 let zero = BV::from_i64(0, 32);
538 let low_zero = state.get_reg(rnlo).eq(&zero);
539 let high_zero = state.get_reg(rnhi).eq(&zero);
540 let both_zero = Bool::and(&[&low_zero, &high_zero]);
541 let result = self.bool_to_bv32(&both_zero);
542 state.set_reg(rd, result);
543 }
544
545 ArmOp::I32WrapI64 { rd, rnlo } => {
546 let low_val = state.get_reg(rnlo).clone();
548 state.set_reg(rd, low_val);
549 }
550
551 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
552 let value = state.get_reg(rn).clone();
554 state.set_reg(rdlo, value.clone());
555
556 let sign_bit = value.extract(31, 31); let all_ones = BV::from_i64(-1, 32);
559 let zero = BV::from_i64(0, 32);
560 let high_val = sign_bit.eq(BV::from_i64(1, 1)).ite(&all_ones, &zero);
562 state.set_reg(rdhi, high_val);
563 }
564
565 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
566 let value = state.get_reg(rn).clone();
568 state.set_reg(rdlo, value);
569 state.set_reg(rdhi, BV::from_i64(0, 32));
571 }
572
573 ArmOp::I64Sub {
574 rdlo,
575 rdhi,
576 rnlo,
577 rnhi,
578 rmlo,
579 rmhi,
580 } => {
581 let n_low = state.get_reg(rnlo).clone();
586 let m_low = state.get_reg(rmlo).clone();
587 let n_high = state.get_reg(rnhi).clone();
588 let m_high = state.get_reg(rmhi).clone();
589
590 let result_low = n_low.bvsub(&m_low);
592 state.set_reg(rdlo, result_low.clone());
593
594 let borrow = n_low.bvult(&m_low);
596 let borrow_bv = borrow.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
597
598 let high_diff = n_high.bvsub(&m_high);
600 let result_high = high_diff.bvsub(&borrow_bv);
601 state.set_reg(rdhi, result_high);
602 }
603
604 ArmOp::I64Mul {
605 rd_lo,
606 rd_hi,
607 rn_lo,
608 rn_hi,
609 rm_lo,
610 rm_hi,
611 } => {
612 let a_lo = state.get_reg(rn_lo).clone();
618 let a_hi = state.get_reg(rn_hi).clone();
619 let b_lo = state.get_reg(rm_lo).clone();
620 let b_hi = state.get_reg(rm_hi).clone();
621
622 let lo_lo = a_lo.bvmul(&b_lo);
625 state.set_reg(rd_lo, lo_lo.clone());
626
627 let hi_lo = a_hi.bvmul(&b_lo); let lo_hi = a_lo.bvmul(&b_hi); let hi_sum = hi_lo.bvadd(&lo_hi);
641 state.set_reg(rd_hi, hi_sum);
642
643 }
649
650 ArmOp::I64DivS { rdlo, rdhi, .. } => {
657 state.set_reg(rdlo, BV::new_const("i64_divs_lo", 32));
661 state.set_reg(rdhi, BV::new_const("i64_divs_hi", 32));
662 }
663
664 ArmOp::I64DivU { rdlo, rdhi, .. } => {
665 state.set_reg(rdlo, BV::new_const("i64_divu_lo", 32));
669 state.set_reg(rdhi, BV::new_const("i64_divu_hi", 32));
670 }
671
672 ArmOp::I64RemS { rdlo, rdhi, .. } => {
673 state.set_reg(rdlo, BV::new_const("i64_rems_lo", 32));
677 state.set_reg(rdhi, BV::new_const("i64_rems_hi", 32));
678 }
679
680 ArmOp::I64RemU { rdlo, rdhi, .. } => {
681 state.set_reg(rdlo, BV::new_const("i64_remu_lo", 32));
685 state.set_reg(rdhi, BV::new_const("i64_remu_hi", 32));
686 }
687
688 ArmOp::I64And {
689 rdlo,
690 rdhi,
691 rnlo,
692 rnhi,
693 rmlo,
694 rmhi,
695 } => {
696 let n_low = state.get_reg(rnlo).clone();
697 let m_low = state.get_reg(rmlo).clone();
698 state.set_reg(rdlo, n_low.bvand(&m_low));
699
700 let n_high = state.get_reg(rnhi).clone();
701 let m_high = state.get_reg(rmhi).clone();
702 state.set_reg(rdhi, n_high.bvand(&m_high));
703 }
704
705 ArmOp::I64Or {
706 rdlo,
707 rdhi,
708 rnlo,
709 rnhi,
710 rmlo,
711 rmhi,
712 } => {
713 let n_low = state.get_reg(rnlo).clone();
714 let m_low = state.get_reg(rmlo).clone();
715 state.set_reg(rdlo, n_low.bvor(&m_low));
716
717 let n_high = state.get_reg(rnhi).clone();
718 let m_high = state.get_reg(rmhi).clone();
719 state.set_reg(rdhi, n_high.bvor(&m_high));
720 }
721
722 ArmOp::I64Xor {
723 rdlo,
724 rdhi,
725 rnlo,
726 rnhi,
727 rmlo,
728 rmhi,
729 } => {
730 let n_low = state.get_reg(rnlo).clone();
731 let m_low = state.get_reg(rmlo).clone();
732 state.set_reg(rdlo, n_low.bvxor(&m_low));
733
734 let n_high = state.get_reg(rnhi).clone();
735 let m_high = state.get_reg(rmhi).clone();
736 state.set_reg(rdhi, n_high.bvxor(&m_high));
737 }
738
739 ArmOp::I64Eq {
740 rd,
741 rnlo,
742 rnhi,
743 rmlo,
744 rmhi,
745 } => {
746 let n_low = state.get_reg(rnlo).clone();
747 let m_low = state.get_reg(rmlo).clone();
748 let n_high = state.get_reg(rnhi).clone();
749 let m_high = state.get_reg(rmhi).clone();
750
751 let low_eq = n_low.eq(&m_low);
752 let high_eq = n_high.eq(&m_high);
753 let both_eq = Bool::and(&[&low_eq, &high_eq]);
754 let result = self.bool_to_bv32(&both_eq);
755 state.set_reg(rd, result);
756 }
757
758 ArmOp::I64LtS {
759 rd,
760 rnlo,
761 rnhi,
762 rmlo,
763 rmhi,
764 } => {
765 let n_low = state.get_reg(rnlo).clone();
768 let m_low = state.get_reg(rmlo).clone();
769 let n_high = state.get_reg(rnhi).clone();
770 let m_high = state.get_reg(rmhi).clone();
771
772 let high_lt = n_high.bvslt(&m_high);
774 let high_eq = n_high.eq(&m_high);
775
776 let low_lt = n_low.bvult(&m_low);
778
779 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
781 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
782 let result = self.bool_to_bv32(&result_bool);
783 state.set_reg(rd, result);
784 }
785
786 ArmOp::I64LtU {
787 rd,
788 rnlo,
789 rnhi,
790 rmlo,
791 rmhi,
792 } => {
793 let n_low = state.get_reg(rnlo).clone();
796 let m_low = state.get_reg(rmlo).clone();
797 let n_high = state.get_reg(rnhi).clone();
798 let m_high = state.get_reg(rmhi).clone();
799
800 let high_lt = n_high.bvult(&m_high);
802 let high_eq = n_high.eq(&m_high);
803
804 let low_lt = n_low.bvult(&m_low);
806
807 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
809 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
810 let result = self.bool_to_bv32(&result_bool);
811 state.set_reg(rd, result);
812 }
813
814 ArmOp::I64Ne {
815 rd,
816 rnlo,
817 rnhi,
818 rmlo,
819 rmhi,
820 } => {
821 let n_low = state.get_reg(rnlo).clone();
823 let m_low = state.get_reg(rmlo).clone();
824 let n_high = state.get_reg(rnhi).clone();
825 let m_high = state.get_reg(rmhi).clone();
826
827 let low_eq = n_low.eq(&m_low);
828 let high_eq = n_high.eq(&m_high);
829 let both_eq = Bool::and(&[&low_eq, &high_eq]);
830 let not_eq = both_eq.not();
831 let result = self.bool_to_bv32(¬_eq);
832 state.set_reg(rd, result);
833 }
834
835 ArmOp::I64LeS {
836 rd,
837 rnlo,
838 rnhi,
839 rmlo,
840 rmhi,
841 } => {
842 let n_low = state.get_reg(rnlo).clone();
845 let m_low = state.get_reg(rmlo).clone();
846 let n_high = state.get_reg(rnhi).clone();
847 let m_high = state.get_reg(rmhi).clone();
848
849 let high_lt = n_high.bvslt(&m_high);
850 let high_eq = n_high.eq(&m_high);
851 let low_le = n_low.bvule(&m_low); let eq_and_le = Bool::and(&[&high_eq, &low_le]);
854 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
855 let result = self.bool_to_bv32(&result_bool);
856 state.set_reg(rd, result);
857 }
858
859 ArmOp::I64LeU {
860 rd,
861 rnlo,
862 rnhi,
863 rmlo,
864 rmhi,
865 } => {
866 let n_low = state.get_reg(rnlo).clone();
868 let m_low = state.get_reg(rmlo).clone();
869 let n_high = state.get_reg(rnhi).clone();
870 let m_high = state.get_reg(rmhi).clone();
871
872 let high_lt = n_high.bvult(&m_high);
873 let high_eq = n_high.eq(&m_high);
874 let low_le = n_low.bvule(&m_low);
875
876 let eq_and_le = Bool::and(&[&high_eq, &low_le]);
877 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
878 let result = self.bool_to_bv32(&result_bool);
879 state.set_reg(rd, result);
880 }
881
882 ArmOp::I64GtS {
883 rd,
884 rnlo,
885 rnhi,
886 rmlo,
887 rmhi,
888 } => {
889 let n_low = state.get_reg(rnlo).clone();
892 let m_low = state.get_reg(rmlo).clone();
893 let n_high = state.get_reg(rnhi).clone();
894 let m_high = state.get_reg(rmhi).clone();
895
896 let high_gt = n_high.bvsgt(&m_high);
897 let high_eq = n_high.eq(&m_high);
898 let low_gt = n_low.bvugt(&m_low); let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
901 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
902 let result = self.bool_to_bv32(&result_bool);
903 state.set_reg(rd, result);
904 }
905
906 ArmOp::I64GtU {
907 rd,
908 rnlo,
909 rnhi,
910 rmlo,
911 rmhi,
912 } => {
913 let n_low = state.get_reg(rnlo).clone();
915 let m_low = state.get_reg(rmlo).clone();
916 let n_high = state.get_reg(rnhi).clone();
917 let m_high = state.get_reg(rmhi).clone();
918
919 let high_gt = n_high.bvugt(&m_high);
920 let high_eq = n_high.eq(&m_high);
921 let low_gt = n_low.bvugt(&m_low);
922
923 let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
924 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
925 let result = self.bool_to_bv32(&result_bool);
926 state.set_reg(rd, result);
927 }
928
929 ArmOp::I64GeS {
930 rd,
931 rnlo,
932 rnhi,
933 rmlo,
934 rmhi,
935 } => {
936 let n_low = state.get_reg(rnlo).clone();
939 let m_low = state.get_reg(rmlo).clone();
940 let n_high = state.get_reg(rnhi).clone();
941 let m_high = state.get_reg(rmhi).clone();
942
943 let high_lt = n_high.bvslt(&m_high);
944 let high_eq = n_high.eq(&m_high);
945 let low_lt = n_low.bvult(&m_low);
946
947 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
948 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
949 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
951 state.set_reg(rd, result);
952 }
953
954 ArmOp::I64GeU {
955 rd,
956 rnlo,
957 rnhi,
958 rmlo,
959 rmhi,
960 } => {
961 let n_low = state.get_reg(rnlo).clone();
964 let m_low = state.get_reg(rmlo).clone();
965 let n_high = state.get_reg(rnhi).clone();
966 let m_high = state.get_reg(rmhi).clone();
967
968 let high_lt = n_high.bvult(&m_high);
969 let high_eq = n_high.eq(&m_high);
970 let low_lt = n_low.bvult(&m_low);
971
972 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
973 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
974 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
976 state.set_reg(rd, result);
977 }
978
979 ArmOp::I64Shl {
983 rd_lo,
984 rd_hi,
985 rn_lo,
986 rn_hi,
987 rm_lo,
988 rm_hi: _,
989 } => {
990 let n_lo = state.get_reg(rn_lo).clone();
993 let n_hi = state.get_reg(rn_hi).clone();
994 let shift_amt = state.get_reg(rm_lo).clone();
995
996 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
998
999 let shift_32 = BV::from_i64(32, 32);
1002 let is_large = shift_mod.bvuge(&shift_32); let result_lo_small = n_lo.bvshl(&shift_mod);
1008 let shift_complement = shift_32.bvsub(&shift_mod);
1009 let bits_to_high = n_lo.bvlshr(&shift_complement);
1010 let result_hi_small = n_hi.bvshl(&shift_mod).bvor(&bits_to_high);
1011
1012 let zero = BV::from_i64(0, 32);
1016 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1017 let result_lo_large = zero.clone();
1018 let result_hi_large = n_lo.bvshl(&shift_minus_32);
1019
1020 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1022 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1023
1024 state.set_reg(rd_lo, result_lo);
1025 state.set_reg(rd_hi, result_hi);
1026 }
1027
1028 ArmOp::I64ShrU {
1029 rd_lo,
1030 rd_hi,
1031 rn_lo,
1032 rn_hi,
1033 rm_lo,
1034 rm_hi: _,
1035 } => {
1036 let n_lo = state.get_reg(rn_lo).clone();
1038 let n_hi = state.get_reg(rn_hi).clone();
1039 let shift_amt = state.get_reg(rm_lo).clone();
1040
1041 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1042 let shift_32 = BV::from_i64(32, 32);
1043 let is_large = shift_mod.bvuge(&shift_32);
1044
1045 let result_hi_small = n_hi.bvlshr(&shift_mod);
1049 let shift_complement = shift_32.bvsub(&shift_mod);
1050 let bits_to_low = n_hi.bvshl(&shift_complement);
1051 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1052
1053 let zero = BV::from_i64(0, 32);
1057 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1058 let result_hi_large = zero.clone();
1059 let result_lo_large = n_hi.bvlshr(&shift_minus_32);
1060
1061 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1062 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1063
1064 state.set_reg(rd_lo, result_lo);
1065 state.set_reg(rd_hi, result_hi);
1066 }
1067
1068 ArmOp::I64ShrS {
1069 rd_lo,
1070 rd_hi,
1071 rn_lo,
1072 rn_hi,
1073 rm_lo,
1074 rm_hi: _,
1075 } => {
1076 let n_lo = state.get_reg(rn_lo).clone();
1078 let n_hi = state.get_reg(rn_hi).clone();
1079 let shift_amt = state.get_reg(rm_lo).clone();
1080
1081 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1082 let shift_32 = BV::from_i64(32, 32);
1083 let is_large = shift_mod.bvuge(&shift_32);
1084
1085 let result_hi_small = n_hi.bvashr(&shift_mod);
1089 let shift_complement = shift_32.bvsub(&shift_mod);
1090 let bits_to_low = n_hi.bvshl(&shift_complement);
1091 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1092
1093 let shift_31 = BV::from_i64(31, 32);
1097 let result_hi_large = n_hi.bvashr(&shift_31);
1098 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1099 let result_lo_large = n_hi.bvashr(&shift_minus_32);
1100
1101 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1102 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1103
1104 state.set_reg(rd_lo, result_lo);
1105 state.set_reg(rd_hi, result_hi);
1106 }
1107
1108 ArmOp::I64Rotl {
1112 rdlo,
1113 rdhi,
1114 rnlo,
1115 rnhi,
1116 shift,
1117 } => {
1118 let n_lo = state.get_reg(rnlo).clone();
1121 let n_hi = state.get_reg(rnhi).clone();
1122 let shift_amt = state.get_reg(shift).clone();
1123
1124 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1126 let shift_32 = BV::from_i64(32, 32);
1127 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1133
1134 let lo_shifted_left = n_lo.bvshl(&shift_mod);
1135 let hi_bits_to_lo = n_hi.bvlshr(&shift_complement);
1136 let result_lo_small = lo_shifted_left.bvor(&hi_bits_to_lo);
1137
1138 let hi_shifted_left = n_hi.bvshl(&shift_mod);
1139 let lo_bits_to_hi = n_lo.bvlshr(&shift_complement);
1140 let result_hi_small = hi_shifted_left.bvor(&lo_bits_to_hi);
1141
1142 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1145 let complement_large = shift_32.bvsub(&shift_minus_32);
1146
1147 let hi_shifted_left_large = n_hi.bvshl(&shift_minus_32);
1148 let lo_bits_to_hi_large = n_lo.bvlshr(&complement_large);
1149 let result_lo_large = hi_shifted_left_large.bvor(&lo_bits_to_hi_large);
1150
1151 let lo_shifted_left_large = n_lo.bvshl(&shift_minus_32);
1152 let hi_bits_to_lo_large = n_hi.bvlshr(&complement_large);
1153 let result_hi_large = lo_shifted_left_large.bvor(&hi_bits_to_lo_large);
1154
1155 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1157 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1158
1159 state.set_reg(rdlo, result_lo);
1160 state.set_reg(rdhi, result_hi);
1161 }
1162
1163 ArmOp::I64Rotr {
1164 rdlo,
1165 rdhi,
1166 rnlo,
1167 rnhi,
1168 shift,
1169 } => {
1170 let n_lo = state.get_reg(rnlo).clone();
1173 let n_hi = state.get_reg(rnhi).clone();
1174 let shift_amt = state.get_reg(shift).clone();
1175
1176 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1178 let shift_32 = BV::from_i64(32, 32);
1179 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1185
1186 let lo_shifted_right = n_lo.bvlshr(&shift_mod);
1187 let hi_bits_to_lo = n_hi.bvshl(&shift_complement);
1188 let result_lo_small = lo_shifted_right.bvor(&hi_bits_to_lo);
1189
1190 let hi_shifted_right = n_hi.bvlshr(&shift_mod);
1191 let lo_bits_to_hi = n_lo.bvshl(&shift_complement);
1192 let result_hi_small = hi_shifted_right.bvor(&lo_bits_to_hi);
1193
1194 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1197 let complement_large = shift_32.bvsub(&shift_minus_32);
1198
1199 let hi_shifted_right_large = n_hi.bvlshr(&shift_minus_32);
1200 let lo_bits_to_hi_large = n_lo.bvshl(&complement_large);
1201 let result_lo_large = hi_shifted_right_large.bvor(&lo_bits_to_hi_large);
1202
1203 let lo_shifted_right_large = n_lo.bvlshr(&shift_minus_32);
1204 let hi_bits_to_lo_large = n_hi.bvshl(&complement_large);
1205 let result_hi_large = lo_shifted_right_large.bvor(&hi_bits_to_lo_large);
1206
1207 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1209 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1210
1211 state.set_reg(rdlo, result_lo);
1212 state.set_reg(rdhi, result_hi);
1213 }
1214
1215 ArmOp::I64Clz { rd, rnlo, rnhi } => {
1216 let n_lo = state.get_reg(rnlo).clone();
1220 let n_hi = state.get_reg(rnhi).clone();
1221
1222 let hi_clz = self.encode_clz(&n_hi);
1223 let lo_clz = self.encode_clz(&n_lo);
1224
1225 let thirty_two = BV::from_i64(32, 32);
1227 let hi_is_zero = hi_clz.eq(&thirty_two);
1228 let result = hi_is_zero.ite(
1229 thirty_two.bvadd(&lo_clz), &hi_clz, );
1232 state.set_reg(rd, result);
1233 }
1234
1235 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
1236 let n_lo = state.get_reg(rnlo).clone();
1240 let n_hi = state.get_reg(rnhi).clone();
1241
1242 let lo_ctz = self.encode_ctz(&n_lo);
1243 let hi_ctz = self.encode_ctz(&n_hi);
1244
1245 let thirty_two = BV::from_i64(32, 32);
1247 let lo_is_zero = lo_ctz.eq(&thirty_two);
1248 let result = lo_is_zero.ite(
1249 thirty_two.bvadd(&hi_ctz), &lo_ctz, );
1252 state.set_reg(rd, result);
1253 }
1254
1255 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
1256 let n_lo = state.get_reg(rnlo).clone();
1259 let n_hi = state.get_reg(rnhi).clone();
1260
1261 let lo_popcnt = self.encode_popcnt(&n_lo);
1262 let hi_popcnt = self.encode_popcnt(&n_hi);
1263
1264 let result = lo_popcnt.bvadd(&hi_popcnt);
1265 state.set_reg(rd, result);
1266 }
1267
1268 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
1272 let result_lo = BV::new_const(format!("i64load_lo_{:?}", addr), 32);
1276 let result_hi = BV::new_const(format!("i64load_hi_{:?}", addr), 32);
1277 state.set_reg(rdlo, result_lo);
1278 state.set_reg(rdhi, result_hi);
1279 }
1280
1281 ArmOp::I64Str {
1282 rdlo: _,
1283 rdhi: _,
1284 addr: _,
1285 } => {
1286 }
1291
1292 ArmOp::F32Const { sd, value } => {
1301 let bits = value.to_bits() as i64;
1304 let bv_val = BV::from_i64(bits, 32);
1305 state.set_vfp_reg(sd, bv_val);
1306 }
1307
1308 ArmOp::F32Add { sd, sn, sm } => {
1310 let result = BV::new_const(format!("f32_add_{:?}_{:?}", sn, sm), 32);
1314 state.set_vfp_reg(sd, result);
1315 }
1316
1317 ArmOp::F32Sub { sd, sn, sm } => {
1318 let result = BV::new_const(format!("f32_sub_{:?}_{:?}", sn, sm), 32);
1320 state.set_vfp_reg(sd, result);
1321 }
1322
1323 ArmOp::F32Mul { sd, sn, sm } => {
1324 let result = BV::new_const(format!("f32_mul_{:?}_{:?}", sn, sm), 32);
1326 state.set_vfp_reg(sd, result);
1327 }
1328
1329 ArmOp::F32Div { sd, sn, sm } => {
1330 let result = BV::new_const(format!("f32_div_{:?}_{:?}", sn, sm), 32);
1332 state.set_vfp_reg(sd, result);
1333 }
1334
1335 ArmOp::F32Abs { sd, sm } => {
1337 let val = state.get_vfp_reg(sm).clone();
1340 let mask = BV::from_u64(0x7FFFFFFF, 32); let result = val.bvand(&mask);
1342 state.set_vfp_reg(sd, result);
1343 }
1344
1345 ArmOp::F32Neg { sd, sm } => {
1346 let val = state.get_vfp_reg(sm).clone();
1349 let mask = BV::from_u64(0x80000000, 32); let result = val.bvxor(&mask);
1351 state.set_vfp_reg(sd, result);
1352 }
1353
1354 ArmOp::F32Sqrt { sd, sm } => {
1355 let result = BV::new_const(format!("f32_sqrt_{:?}", sm), 32);
1358 state.set_vfp_reg(sd, result);
1359 }
1360
1361 ArmOp::F32Min { sd, sn, sm } => {
1362 let result = BV::new_const(format!("f32_min_{:?}_{:?}", sn, sm), 32);
1366 state.set_vfp_reg(sd, result);
1367 }
1368
1369 ArmOp::F32Max { sd, sn, sm } => {
1370 let result = BV::new_const(format!("f32_max_{:?}_{:?}", sn, sm), 32);
1374 state.set_vfp_reg(sd, result);
1375 }
1376
1377 ArmOp::F32Copysign { sd, sn, sm } => {
1378 let val_n = state.get_vfp_reg(sn).clone();
1381 let val_m = state.get_vfp_reg(sm).clone();
1382
1383 let mag_mask = BV::from_u64(0x7FFFFFFF, 32);
1385 let magnitude = val_n.bvand(&mag_mask);
1386
1387 let sign_mask = BV::from_u64(0x80000000, 32);
1389 let sign = val_m.bvand(&sign_mask);
1390
1391 let result = magnitude.bvor(&sign);
1393 state.set_vfp_reg(sd, result);
1394 }
1395
1396 ArmOp::F32Load { sd, addr } => {
1397 let result = BV::new_const(format!("f32_load_{:?}", addr), 32);
1400 state.set_vfp_reg(sd, result);
1401 }
1402
1403 ArmOp::F32Eq { rd, sn, sm } => {
1405 let result = BV::new_const(format!("f32_eq_{:?}_{:?}", sn, sm), 32);
1408 state.set_reg(rd, result);
1409 }
1410
1411 ArmOp::F32Ne { rd, sn, sm } => {
1412 let result = BV::new_const(format!("f32_ne_{:?}_{:?}", sn, sm), 32);
1414 state.set_reg(rd, result);
1415 }
1416
1417 ArmOp::F32Lt { rd, sn, sm } => {
1418 let result = BV::new_const(format!("f32_lt_{:?}_{:?}", sn, sm), 32);
1420 state.set_reg(rd, result);
1421 }
1422
1423 ArmOp::F32Le { rd, sn, sm } => {
1424 let result = BV::new_const(format!("f32_le_{:?}_{:?}", sn, sm), 32);
1426 state.set_reg(rd, result);
1427 }
1428
1429 ArmOp::F32Gt { rd, sn, sm } => {
1430 let result = BV::new_const(format!("f32_gt_{:?}_{:?}", sn, sm), 32);
1432 state.set_reg(rd, result);
1433 }
1434
1435 ArmOp::F32Ge { rd, sn, sm } => {
1436 let result = BV::new_const(format!("f32_ge_{:?}_{:?}", sn, sm), 32);
1438 state.set_reg(rd, result);
1439 }
1440
1441 ArmOp::F32Store { sd, addr } => {
1442 let _val = state.get_vfp_reg(sd);
1447 let _addr_str = format!("{:?}", addr);
1448 }
1450
1451 ArmOp::F32Ceil { sd, sm } => {
1453 let result = BV::new_const(format!("f32_ceil_{:?}", sm), 32);
1456 state.set_vfp_reg(sd, result);
1457 }
1458
1459 ArmOp::F32Floor { sd, sm } => {
1460 let result = BV::new_const(format!("f32_floor_{:?}", sm), 32);
1463 state.set_vfp_reg(sd, result);
1464 }
1465
1466 ArmOp::F32Trunc { sd, sm } => {
1467 let result = BV::new_const(format!("f32_trunc_{:?}", sm), 32);
1470 state.set_vfp_reg(sd, result);
1471 }
1472
1473 ArmOp::F32Nearest { sd, sm } => {
1474 let result = BV::new_const(format!("f32_nearest_{:?}", sm), 32);
1477 state.set_vfp_reg(sd, result);
1478 }
1479
1480 ArmOp::F32ConvertI32S { sd, rm } => {
1482 let int_val = state.get_reg(rm);
1484 let result = BV::new_const(format!("f32_convert_i32s_{:?}", int_val), 32);
1485 state.set_vfp_reg(sd, result);
1486 }
1487
1488 ArmOp::F32ConvertI32U { sd, rm } => {
1489 let int_val = state.get_reg(rm);
1491 let result = BV::new_const(format!("f32_convert_i32u_{:?}", int_val), 32);
1492 state.set_vfp_reg(sd, result);
1493 }
1494
1495 ArmOp::F32ConvertI64S { sd, rmlo, rmhi } => {
1496 let lo = state.get_reg(rmlo);
1498 let hi = state.get_reg(rmhi);
1499 let result = BV::new_const(format!("f32_convert_i64s_{:?}_{:?}", lo, hi), 32);
1500 state.set_vfp_reg(sd, result);
1501 }
1502
1503 ArmOp::F32ConvertI64U { 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_i64u_{:?}_{:?}", lo, hi), 32);
1508 state.set_vfp_reg(sd, result);
1509 }
1510
1511 ArmOp::F32ReinterpretI32 { sd, rm } => {
1513 let bits = state.get_reg(rm).clone();
1516 state.set_vfp_reg(sd, bits);
1517 }
1518
1519 ArmOp::I32ReinterpretF32 { rd, sm } => {
1520 let bits = state.get_vfp_reg(sm).clone();
1523 state.set_reg(rd, bits);
1524 }
1525
1526 ArmOp::F64Add { dd, dn, dm } => {
1532 let result = BV::new_const(format!("f64_add_{:?}_{:?}", dn, dm), 64);
1536 state.set_vfp_reg(dd, result);
1537 }
1538
1539 ArmOp::F64Sub { dd, dn, dm } => {
1540 let result = BV::new_const(format!("f64_sub_{:?}_{:?}", dn, dm), 64);
1542 state.set_vfp_reg(dd, result);
1543 }
1544
1545 ArmOp::F64Mul { dd, dn, dm } => {
1546 let result = BV::new_const(format!("f64_mul_{:?}_{:?}", dn, dm), 64);
1548 state.set_vfp_reg(dd, result);
1549 }
1550
1551 ArmOp::F64Div { dd, dn, dm } => {
1552 let result = BV::new_const(format!("f64_div_{:?}_{:?}", dn, dm), 64);
1554 state.set_vfp_reg(dd, result);
1555 }
1556
1557 ArmOp::F64Abs { dd, dm } => {
1559 let val = state.get_vfp_reg(dm).clone();
1562 let mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64); let result = val.bvand(&mask);
1564 state.set_vfp_reg(dd, result);
1565 }
1566
1567 ArmOp::F64Neg { dd, dm } => {
1568 let val = state.get_vfp_reg(dm).clone();
1571 let mask = BV::from_u64(0x8000000000000000, 64); let result = val.bvxor(&mask);
1573 state.set_vfp_reg(dd, result);
1574 }
1575
1576 ArmOp::F64Sqrt { dd, dm } => {
1577 let result = BV::new_const(format!("f64_sqrt_{:?}", dm), 64);
1580 state.set_vfp_reg(dd, result);
1581 }
1582
1583 ArmOp::F64Min { dd, dn, dm } => {
1584 let result = BV::new_const(format!("f64_min_{:?}_{:?}", dn, dm), 64);
1588 state.set_vfp_reg(dd, result);
1589 }
1590
1591 ArmOp::F64Max { dd, dn, dm } => {
1592 let result = BV::new_const(format!("f64_max_{:?}_{:?}", dn, dm), 64);
1596 state.set_vfp_reg(dd, result);
1597 }
1598
1599 ArmOp::F64Copysign { dd, dn, dm } => {
1600 let val_n = state.get_vfp_reg(dn).clone();
1603 let val_m = state.get_vfp_reg(dm).clone();
1604
1605 let mag_mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64);
1607 let magnitude = val_n.bvand(&mag_mask);
1608
1609 let sign_mask = BV::from_u64(0x8000000000000000, 64);
1611 let sign = val_m.bvand(&sign_mask);
1612
1613 let result = magnitude.bvor(&sign);
1615 state.set_vfp_reg(dd, result);
1616 }
1617
1618 ArmOp::F64Ceil { dd, dm } => {
1620 let result = BV::new_const(format!("f64_ceil_{:?}", dm), 64);
1622 state.set_vfp_reg(dd, result);
1623 }
1624
1625 ArmOp::F64Floor { dd, dm } => {
1626 let result = BV::new_const(format!("f64_floor_{:?}", dm), 64);
1628 state.set_vfp_reg(dd, result);
1629 }
1630
1631 ArmOp::F64Trunc { dd, dm } => {
1632 let result = BV::new_const(format!("f64_trunc_{:?}", dm), 64);
1634 state.set_vfp_reg(dd, result);
1635 }
1636
1637 ArmOp::F64Nearest { dd, dm } => {
1638 let result = BV::new_const(format!("f64_nearest_{:?}", dm), 64);
1640 state.set_vfp_reg(dd, result);
1641 }
1642
1643 ArmOp::F64Load { dd, addr } => {
1645 let result = BV::new_const(format!("f64_load_{:?}", addr), 64);
1648 state.set_vfp_reg(dd, result);
1649 }
1650
1651 ArmOp::F64Store { dd: _, addr: _ } => {
1652 }
1656
1657 ArmOp::F64Const { dd, value } => {
1658 let bits = value.to_bits() as i64;
1660 let result = BV::from_i64(bits, 64);
1661 state.set_vfp_reg(dd, result);
1662 }
1663
1664 ArmOp::F64Eq { rd, dn, dm } => {
1666 let result = BV::new_const(format!("f64_eq_{:?}_{:?}", dn, dm), 32);
1669 state.set_reg(rd, result);
1670 }
1671
1672 ArmOp::F64Ne { rd, dn, dm } => {
1673 let result = BV::new_const(format!("f64_ne_{:?}_{:?}", dn, dm), 32);
1675 state.set_reg(rd, result);
1676 }
1677
1678 ArmOp::F64Lt { rd, dn, dm } => {
1679 let result = BV::new_const(format!("f64_lt_{:?}_{:?}", dn, dm), 32);
1681 state.set_reg(rd, result);
1682 }
1683
1684 ArmOp::F64Le { rd, dn, dm } => {
1685 let result = BV::new_const(format!("f64_le_{:?}_{:?}", dn, dm), 32);
1687 state.set_reg(rd, result);
1688 }
1689
1690 ArmOp::F64Gt { rd, dn, dm } => {
1691 let result = BV::new_const(format!("f64_gt_{:?}_{:?}", dn, dm), 32);
1693 state.set_reg(rd, result);
1694 }
1695
1696 ArmOp::F64Ge { rd, dn, dm } => {
1697 let result = BV::new_const(format!("f64_ge_{:?}_{:?}", dn, dm), 32);
1699 state.set_reg(rd, result);
1700 }
1701
1702 ArmOp::F64ConvertI32S { dd, rm } => {
1704 let result = BV::new_const(format!("f64_convert_i32s_{:?}", rm), 64);
1707 state.set_vfp_reg(dd, result);
1708 }
1709
1710 ArmOp::F64ConvertI32U { dd, rm } => {
1711 let result = BV::new_const(format!("f64_convert_i32u_{:?}", rm), 64);
1714 state.set_vfp_reg(dd, result);
1715 }
1716
1717 ArmOp::F64ConvertI64S {
1718 dd,
1719 rmlo: _,
1720 rmhi: _,
1721 } => {
1722 let result = BV::new_const("f64_convert_i64s_result", 64);
1725 state.set_vfp_reg(dd, result);
1726 }
1727
1728 ArmOp::F64ConvertI64U {
1729 dd,
1730 rmlo: _,
1731 rmhi: _,
1732 } => {
1733 let result = BV::new_const("f64_convert_i64u_result", 64);
1736 state.set_vfp_reg(dd, result);
1737 }
1738
1739 ArmOp::F64PromoteF32 { dd, sm } => {
1740 let result = BV::new_const(format!("f64_promote_f32_{:?}", sm), 64);
1743 state.set_vfp_reg(dd, result);
1744 }
1745
1746 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
1747 let lo = state.get_reg(rmlo).clone();
1750 let hi = state.get_reg(rmhi).clone();
1751
1752 let lo_64 = lo.zero_ext(32); let hi_64 = hi.zero_ext(32);
1755 let shift_32 = BV::from_u64(32, 64);
1756 let hi_shifted = hi_64.bvshl(&shift_32);
1757 let result = hi_shifted.bvor(&lo_64);
1758
1759 state.set_vfp_reg(dd, result);
1760 }
1761
1762 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
1763 let bits = state.get_vfp_reg(dm).clone();
1766
1767 let lo = bits.extract(31, 0);
1769 state.set_reg(rdlo, lo);
1770
1771 let hi = bits.extract(63, 32);
1773 state.set_reg(rdhi, hi);
1774 }
1775
1776 ArmOp::I64TruncF64S {
1777 rdlo: _,
1778 rdhi: _,
1779 dm: _,
1780 } => {
1781 }
1785
1786 ArmOp::I64TruncF64U {
1787 rdlo: _,
1788 rdhi: _,
1789 dm: _,
1790 } => {
1791 }
1795
1796 ArmOp::I32TruncF64S { rd, dm } => {
1797 let result = BV::new_const(format!("i32_trunc_f64s_{:?}", dm), 32);
1800 state.set_reg(rd, result);
1801 }
1802
1803 ArmOp::I32TruncF64U { rd, dm } => {
1804 let result = BV::new_const(format!("i32_trunc_f64u_{:?}", dm), 32);
1807 state.set_reg(rd, result);
1808 }
1809
1810 _ => {
1811 }
1813 }
1814 }
1815
1816 fn evaluate_operand2(&self, op2: &Operand2, state: &ArmState) -> BV {
1818 match op2 {
1819 Operand2::Imm(value) => BV::from_i64(*value as i64, 32),
1820 Operand2::Reg(reg) => state.get_reg(reg).clone(),
1821 Operand2::RegShift { rm, shift, amount } => {
1822 let reg_val = state.get_reg(rm).clone();
1823 let shift_amount = BV::from_i64(*amount as i64, 32);
1824
1825 match shift {
1826 synth_synthesis::ShiftType::LSL => reg_val.bvshl(&shift_amount),
1827 synth_synthesis::ShiftType::LSR => reg_val.bvlshr(&shift_amount),
1828 synth_synthesis::ShiftType::ASR => reg_val.bvashr(&shift_amount),
1829 synth_synthesis::ShiftType::ROR => reg_val.bvrotr(&shift_amount),
1830 }
1831 }
1832 }
1833 }
1834
1835 pub fn extract_result(&self, state: &ArmState, reg: &Reg) -> BV {
1837 state.get_reg(reg).clone()
1838 }
1839
1840 fn encode_clz(&self, input: &BV) -> BV {
1845 let zero = BV::from_i64(0, 32);
1846
1847 let all_zero = input.eq(&zero);
1849 let result_if_zero = BV::from_i64(32, 32);
1850
1851 let mut count = BV::from_i64(0, 32);
1853 let mut remaining = input.clone();
1854
1855 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1857 let top_16 = remaining.bvand(&mask_16);
1858 let top_16_zero = top_16.eq(&zero);
1859
1860 count = top_16_zero.ite(count.bvadd(BV::from_i64(16, 32)), &count);
1861 remaining = top_16_zero.ite(remaining.bvshl(BV::from_i64(16, 32)), &remaining);
1862
1863 let mask_8 = BV::from_u64(0xFF000000, 32);
1865 let top_8 = remaining.bvand(&mask_8);
1866 let top_8_zero = top_8.eq(&zero);
1867
1868 count = top_8_zero.ite(count.bvadd(BV::from_i64(8, 32)), &count);
1869 remaining = top_8_zero.ite(remaining.bvshl(BV::from_i64(8, 32)), &remaining);
1870
1871 let mask_4 = BV::from_u64(0xF0000000, 32);
1873 let top_4 = remaining.bvand(&mask_4);
1874 let top_4_zero = top_4.eq(&zero);
1875
1876 count = top_4_zero.ite(count.bvadd(BV::from_i64(4, 32)), &count);
1877 remaining = top_4_zero.ite(remaining.bvshl(BV::from_i64(4, 32)), &remaining);
1878
1879 let mask_2 = BV::from_u64(0xC0000000, 32);
1881 let top_2 = remaining.bvand(&mask_2);
1882 let top_2_zero = top_2.eq(&zero);
1883
1884 count = top_2_zero.ite(count.bvadd(BV::from_i64(2, 32)), &count);
1885 remaining = top_2_zero.ite(remaining.bvshl(BV::from_i64(2, 32)), &remaining);
1886
1887 let mask_1 = BV::from_u64(0x80000000, 32);
1889 let top_1 = remaining.bvand(&mask_1);
1890 let top_1_zero = top_1.eq(&zero);
1891
1892 count = top_1_zero.ite(count.bvadd(BV::from_i64(1, 32)), &count);
1893
1894 all_zero.ite(&result_if_zero, &count)
1896 }
1897
1898 fn encode_ctz(&self, input: &BV) -> BV {
1904 let reversed = self.encode_rbit(input);
1906 self.encode_clz(&reversed)
1907 }
1908
1909 fn encode_rbit(&self, input: &BV) -> BV {
1914 let mut result = input.clone();
1916
1917 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1919 let top_16 = result.bvand(&mask_16).bvlshr(BV::from_i64(16, 32));
1920 let bottom_16 = result.bvshl(BV::from_i64(16, 32));
1921 result = top_16.bvor(&bottom_16);
1922
1923 let mask_8_top = BV::from_u64(0xFF00FF00, 32);
1925 let mask_8_bottom = BV::from_u64(0x00FF00FF, 32);
1926 let top_8 = result.bvand(&mask_8_top).bvlshr(BV::from_i64(8, 32));
1927 let bottom_8 = result.bvand(&mask_8_bottom).bvshl(BV::from_i64(8, 32));
1928 result = top_8.bvor(&bottom_8);
1929
1930 let mask_4_top = BV::from_u64(0xF0F0F0F0, 32);
1932 let mask_4_bottom = BV::from_u64(0x0F0F0F0F, 32);
1933 let top_4 = result.bvand(&mask_4_top).bvlshr(BV::from_i64(4, 32));
1934 let bottom_4 = result.bvand(&mask_4_bottom).bvshl(BV::from_i64(4, 32));
1935 result = top_4.bvor(&bottom_4);
1936
1937 let mask_2_top = BV::from_u64(0xCCCCCCCC, 32);
1939 let mask_2_bottom = BV::from_u64(0x33333333, 32);
1940 let top_2 = result.bvand(&mask_2_top).bvlshr(BV::from_i64(2, 32));
1941 let bottom_2 = result.bvand(&mask_2_bottom).bvshl(BV::from_i64(2, 32));
1942 result = top_2.bvor(&bottom_2);
1943
1944 let mask_1_top = BV::from_u64(0xAAAAAAAA, 32);
1946 let mask_1_bottom = BV::from_u64(0x55555555, 32);
1947 let top_1 = result.bvand(&mask_1_top).bvlshr(BV::from_i64(1, 32));
1948 let bottom_1 = result.bvand(&mask_1_bottom).bvshl(BV::from_i64(1, 32));
1949 result = top_1.bvor(&bottom_1);
1950
1951 result
1952 }
1953
1954 fn update_flags_sub(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
1966 let zero = BV::from_i64(0, 32);
1967
1968 let sign_bit = result.extract(31, 31);
1970 let one_bit = BV::from_i64(1, 1);
1971 state.flags.n = sign_bit.eq(&one_bit);
1972
1973 state.flags.z = result.eq(&zero);
1975
1976 state.flags.c = a.bvuge(b);
1980
1981 let a_sign = a.extract(31, 31);
1987 let b_sign = b.extract(31, 31);
1988 let r_sign = result.extract(31, 31);
1989
1990 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]);
1993 }
1994
1995 #[allow(dead_code)]
2001 fn update_flags_add(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
2002 let zero = BV::from_i64(0, 32);
2003
2004 let sign_bit = result.extract(31, 31);
2006 let one_bit = BV::from_i64(1, 1);
2007 state.flags.n = sign_bit.eq(&one_bit);
2008
2009 state.flags.z = result.eq(&zero);
2011
2012 state.flags.c = result.bvult(a);
2016
2017 let a_sign = a.extract(31, 31);
2023 let b_sign = b.extract(31, 31);
2024 let r_sign = result.extract(31, 31);
2025
2026 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]);
2029 }
2030
2031 fn evaluate_condition(
2045 &self,
2046 cond: &synth_synthesis::rules::Condition,
2047 flags: &ConditionFlags,
2048 ) -> Bool {
2049 use synth_synthesis::rules::Condition;
2050
2051 match cond {
2052 Condition::EQ => flags.z.clone(),
2053 Condition::NE => flags.z.not(),
2054 Condition::LT => {
2055 flags.n.eq(&flags.v).not()
2057 }
2058 Condition::LE => {
2059 let n_ne_v = flags.n.eq(&flags.v).not();
2061 Bool::or(&[&flags.z, &n_ne_v])
2062 }
2063 Condition::GT => {
2064 let z_zero = flags.z.not();
2066 let n_eq_v = flags.n.eq(&flags.v);
2067 Bool::and(&[&z_zero, &n_eq_v])
2068 }
2069 Condition::GE => {
2070 flags.n.eq(&flags.v)
2072 }
2073 Condition::LO => {
2074 flags.c.not()
2076 }
2077 Condition::LS => {
2078 let c_zero = flags.c.not();
2080 Bool::or(&[&flags.z, &c_zero])
2081 }
2082 Condition::HI => {
2083 let z_zero = flags.z.not();
2085 Bool::and(&[&flags.c, &z_zero])
2086 }
2087 Condition::HS => {
2088 flags.c.clone()
2090 }
2091 }
2092 }
2093
2094 fn bool_to_bv32(&self, cond: &Bool) -> BV {
2096 let zero = BV::from_i64(0, 32);
2097 let one = BV::from_i64(1, 32);
2098 cond.ite(&one, &zero)
2099 }
2100
2101 fn encode_popcnt(&self, input: &BV) -> BV {
2106 let mut x = input.clone();
2107
2108 let mask1 = BV::from_u64(0x55555555, 32);
2110 let masked = x.bvand(&mask1);
2111 let shifted = x.bvlshr(BV::from_i64(1, 32));
2112 let shifted_masked = shifted.bvand(&mask1);
2113 x = masked.bvadd(&shifted_masked);
2114
2115 let mask2 = BV::from_u64(0x33333333, 32);
2117 let masked = x.bvand(&mask2);
2118 let shifted = x.bvlshr(BV::from_i64(2, 32));
2119 let shifted_masked = shifted.bvand(&mask2);
2120 x = masked.bvadd(&shifted_masked);
2121
2122 let mask3 = BV::from_u64(0x0F0F0F0F, 32);
2124 let masked = x.bvand(&mask3);
2125 let shifted = x.bvlshr(BV::from_i64(4, 32));
2126 let shifted_masked = shifted.bvand(&mask3);
2127 x = masked.bvadd(&shifted_masked);
2128
2129 let multiplier = BV::from_u64(0x01010101, 32);
2131 x = x.bvmul(&multiplier);
2132 x = x.bvlshr(BV::from_i64(24, 32));
2133
2134 x
2135 }
2136}
2137
2138#[cfg(test)]
2139mod tests {
2140 use super::*;
2141 use crate::with_verification_context;
2142
2143 #[test]
2144 fn test_arm_add_semantics() {
2145 with_verification_context(|| {
2146 let encoder = ArmSemantics::new();
2147 let mut state = ArmState::new_symbolic();
2148
2149 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2151 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2152
2153 let op = ArmOp::Add {
2155 rd: Reg::R0,
2156 rn: Reg::R1,
2157 op2: Operand2::Reg(Reg::R2),
2158 };
2159
2160 encoder.encode_op(&op, &mut state);
2161
2162 let result = state.get_reg(&Reg::R0).simplify();
2164 assert_eq!(result.as_i64(), Some(30));
2165 });
2166 }
2167
2168 #[test]
2169 fn test_arm_sub_semantics() {
2170 with_verification_context(|| {
2171 let encoder = ArmSemantics::new();
2172 let mut state = ArmState::new_symbolic();
2173
2174 state.set_reg(&Reg::R1, BV::from_i64(50, 32));
2175 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2176
2177 let op = ArmOp::Sub {
2178 rd: Reg::R0,
2179 rn: Reg::R1,
2180 op2: Operand2::Reg(Reg::R2),
2181 };
2182
2183 encoder.encode_op(&op, &mut state);
2184
2185 let result = state.get_reg(&Reg::R0);
2186 assert_eq!(result.simplify().as_i64(), Some(30));
2187 });
2188 }
2189
2190 #[test]
2191 fn test_arm_mov_immediate() {
2192 with_verification_context(|| {
2193 let encoder = ArmSemantics::new();
2194 let mut state = ArmState::new_symbolic();
2195
2196 let op = ArmOp::Mov {
2197 rd: Reg::R0,
2198 op2: Operand2::Imm(42),
2199 };
2200
2201 encoder.encode_op(&op, &mut state);
2202
2203 let result = state.get_reg(&Reg::R0);
2204 assert_eq!(result.simplify().as_i64(), Some(42));
2205 });
2206 }
2207
2208 #[test]
2209 fn test_arm_bitwise_ops() {
2210 with_verification_context(|| {
2211 let encoder = ArmSemantics::new();
2212 let mut state = ArmState::new_symbolic();
2213
2214 state.set_reg(&Reg::R1, BV::from_i64(0b1010, 32));
2215 state.set_reg(&Reg::R2, BV::from_i64(0b1100, 32));
2216
2217 let and_op = ArmOp::And {
2219 rd: Reg::R0,
2220 rn: Reg::R1,
2221 op2: Operand2::Reg(Reg::R2),
2222 };
2223 encoder.encode_op(&and_op, &mut state);
2224 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1000));
2225
2226 let orr_op = ArmOp::Orr {
2228 rd: Reg::R0,
2229 rn: Reg::R1,
2230 op2: Operand2::Reg(Reg::R2),
2231 };
2232 encoder.encode_op(&orr_op, &mut state);
2233 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1110));
2234
2235 let eor_op = ArmOp::Eor {
2237 rd: Reg::R0,
2238 rn: Reg::R1,
2239 op2: Operand2::Reg(Reg::R2),
2240 };
2241 encoder.encode_op(&eor_op, &mut state);
2242 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b0110));
2243 });
2244 }
2245
2246 #[test]
2247 fn test_arm_mls() {
2248 with_verification_context(|| {
2251 let encoder = ArmSemantics::new();
2252 let mut state = ArmState::new_symbolic();
2253
2254 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 {
2261 rd: Reg::R3,
2262 rn: Reg::R1,
2263 rm: Reg::R2,
2264 ra: Reg::R0,
2265 };
2266 encoder.encode_op(&mls_op, &mut state);
2267 assert_eq!(
2268 state.get_reg(&Reg::R3).simplify().as_i64(),
2269 Some(2),
2270 "MLS: 17 - 3*5 = 2"
2271 );
2272
2273 state.set_reg(&Reg::R0, BV::from_i64(100, 32));
2275 state.set_reg(&Reg::R1, BV::from_i64(7, 32));
2276 state.set_reg(&Reg::R2, BV::from_i64(3, 32));
2277
2278 let mls_op2 = ArmOp::Mls {
2279 rd: Reg::R3,
2280 rn: Reg::R1,
2281 rm: Reg::R2,
2282 ra: Reg::R0,
2283 };
2284 encoder.encode_op(&mls_op2, &mut state);
2285 assert_eq!(
2286 state.get_reg(&Reg::R3).simplify().as_i64(),
2287 Some(79),
2288 "MLS: 100 - 7*3 = 79"
2289 );
2290
2291 state.set_reg(&Reg::R0, BV::from_i64(-17, 32));
2293 state.set_reg(&Reg::R1, BV::from_i64(3, 32));
2294 state.set_reg(&Reg::R2, BV::from_i64(5, 32));
2295
2296 let mls_op3 = ArmOp::Mls {
2297 rd: Reg::R3,
2298 rn: Reg::R1,
2299 rm: Reg::R2,
2300 ra: Reg::R0,
2301 };
2302 encoder.encode_op(&mls_op3, &mut state);
2303 let result = state.get_reg(&Reg::R3).simplify().as_i64();
2305 let signed_result = result.map(|v| (v as i32) as i64);
2306 assert_eq!(signed_result, Some(-32), "MLS: -17 - 3*5 = -32");
2307 });
2308 }
2309
2310 #[test]
2311 fn test_arm_shift_ops() {
2312 with_verification_context(|| {
2313 let encoder = ArmSemantics::new();
2314 let mut state = ArmState::new_symbolic();
2315
2316 state.set_reg(&Reg::R1, BV::from_i64(8, 32));
2317
2318 let lsl_op = ArmOp::Lsl {
2320 rd: Reg::R0,
2321 rn: Reg::R1,
2322 shift: 2,
2323 };
2324 encoder.encode_op(&lsl_op, &mut state);
2325 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(32));
2326
2327 let lsr_op = ArmOp::Lsr {
2329 rd: Reg::R0,
2330 rn: Reg::R1,
2331 shift: 2,
2332 };
2333 encoder.encode_op(&lsr_op, &mut state);
2334 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(2));
2335 });
2336 }
2337
2338 #[test]
2339 fn test_arm_ror_comprehensive() {
2340 with_verification_context(|| {
2341 let encoder = ArmSemantics::new();
2342 let mut state = ArmState::new_symbolic();
2343
2344 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2347 let ror_op = ArmOp::Ror {
2348 rd: Reg::R0,
2349 rn: Reg::R1,
2350 shift: 8,
2351 };
2352 encoder.encode_op(&ror_op, &mut state);
2353 assert_eq!(
2355 state.get_reg(&Reg::R0).simplify().as_i64(),
2356 Some(0x78123456),
2357 "ROR by 8"
2358 );
2359
2360 let ror_op_16 = ArmOp::Ror {
2362 rd: Reg::R0,
2363 rn: Reg::R1,
2364 shift: 16,
2365 };
2366 encoder.encode_op(&ror_op_16, &mut state);
2367 assert_eq!(
2369 state.get_reg(&Reg::R0).simplify().as_i64(),
2370 Some(0x56781234),
2371 "ROR by 16"
2372 );
2373
2374 let ror_op_0 = ArmOp::Ror {
2376 rd: Reg::R0,
2377 rn: Reg::R1,
2378 shift: 0,
2379 };
2380 encoder.encode_op(&ror_op_0, &mut state);
2381 assert_eq!(
2382 state.get_reg(&Reg::R0).simplify().as_i64(),
2383 Some(0x12345678),
2384 "ROR by 0"
2385 );
2386
2387 let ror_op_32 = ArmOp::Ror {
2389 rd: Reg::R0,
2390 rn: Reg::R1,
2391 shift: 32,
2392 };
2393 encoder.encode_op(&ror_op_32, &mut state);
2394 assert_eq!(
2395 state.get_reg(&Reg::R0).simplify().as_i64(),
2396 Some(0x12345678),
2397 "ROR by 32"
2398 );
2399
2400 state.set_reg(&Reg::R1, BV::from_u64(0xABCDEF01, 32));
2402 let ror_op_4 = ArmOp::Ror {
2403 rd: Reg::R0,
2404 rn: Reg::R1,
2405 shift: 4,
2406 };
2407 encoder.encode_op(&ror_op_4, &mut state);
2408 assert_eq!(
2410 state.get_reg(&Reg::R0).simplify().as_i64(),
2411 Some(0x1ABCDEF0),
2412 "ROR by 4"
2413 );
2414
2415 state.set_reg(&Reg::R1, BV::from_u64(0x80000001, 32));
2417 let ror_op_1 = ArmOp::Ror {
2418 rd: Reg::R0,
2419 rn: Reg::R1,
2420 shift: 1,
2421 };
2422 encoder.encode_op(&ror_op_1, &mut state);
2423 let result = state.get_reg(&Reg::R0).simplify().as_i64();
2425 let signed_result = result.map(|v| (v as i32) as i64);
2426 assert_eq!(
2427 signed_result,
2428 Some(0xC0000000_u32 as i32 as i64),
2429 "ROR by 1"
2430 );
2431 });
2432 }
2433
2434 #[test]
2435 fn test_arm_clz_comprehensive() {
2436 with_verification_context(|| {
2437 let encoder = ArmSemantics::new();
2438 let mut state = ArmState::new_symbolic();
2439
2440 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2442 let clz_op = ArmOp::Clz {
2443 rd: Reg::R0,
2444 rm: Reg::R1,
2445 };
2446 encoder.encode_op(&clz_op, &mut state);
2447 assert_eq!(
2448 state.get_reg(&Reg::R0).simplify().as_i64(),
2449 Some(32),
2450 "CLZ(0) should be 32"
2451 );
2452
2453 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2455 encoder.encode_op(&clz_op, &mut state);
2456 assert_eq!(
2457 state.get_reg(&Reg::R0).simplify().as_i64(),
2458 Some(31),
2459 "CLZ(1) should be 31"
2460 );
2461
2462 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2464 encoder.encode_op(&clz_op, &mut state);
2465 assert_eq!(
2466 state.get_reg(&Reg::R0).simplify().as_i64(),
2467 Some(0),
2468 "CLZ(0x80000000) should be 0"
2469 );
2470
2471 state.set_reg(&Reg::R1, BV::from_u64(0x00FF0000, 32));
2473 encoder.encode_op(&clz_op, &mut state);
2474 assert_eq!(
2475 state.get_reg(&Reg::R0).simplify().as_i64(),
2476 Some(8),
2477 "CLZ(0x00FF0000) should be 8"
2478 );
2479
2480 state.set_reg(&Reg::R1, BV::from_u64(0x00001000, 32));
2482 encoder.encode_op(&clz_op, &mut state);
2483 assert_eq!(
2484 state.get_reg(&Reg::R0).simplify().as_i64(),
2485 Some(19),
2486 "CLZ(0x00001000) should be 19"
2487 );
2488
2489 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2491 encoder.encode_op(&clz_op, &mut state);
2492 assert_eq!(
2493 state.get_reg(&Reg::R0).simplify().as_i64(),
2494 Some(0),
2495 "CLZ(0xFFFFFFFF) should be 0"
2496 );
2497 });
2498 }
2499
2500 #[test]
2501 fn test_arm_rbit_comprehensive() {
2502 with_verification_context(|| {
2503 let encoder = ArmSemantics::new();
2504 let mut state = ArmState::new_symbolic();
2505
2506 let rbit_op = ArmOp::Rbit {
2507 rd: Reg::R0,
2508 rm: Reg::R1,
2509 };
2510
2511 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2513 encoder.encode_op(&rbit_op, &mut state);
2514 assert_eq!(
2515 state.get_reg(&Reg::R0).simplify().as_i64(),
2516 Some(0),
2517 "RBIT(0) should be 0"
2518 );
2519
2520 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2522 encoder.encode_op(&rbit_op, &mut state);
2523 assert_eq!(
2524 state.get_reg(&Reg::R0).simplify().as_u64(),
2525 Some(0x80000000),
2526 "RBIT(1) should be 0x80000000"
2527 );
2528
2529 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2531 encoder.encode_op(&rbit_op, &mut state);
2532 assert_eq!(
2533 state.get_reg(&Reg::R0).simplify().as_i64(),
2534 Some(1),
2535 "RBIT(0x80000000) should be 1"
2536 );
2537
2538 state.set_reg(&Reg::R1, BV::from_u64(0xFF000000, 32));
2540 encoder.encode_op(&rbit_op, &mut state);
2541 assert_eq!(
2542 state.get_reg(&Reg::R0).simplify().as_u64(),
2543 Some(0x000000FF),
2544 "RBIT(0xFF000000) should be 0x000000FF"
2545 );
2546
2547 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2549 encoder.encode_op(&rbit_op, &mut state);
2550 assert_eq!(
2552 state.get_reg(&Reg::R0).simplify().as_u64(),
2553 Some(0x1E6A2C48),
2554 "RBIT(0x12345678) should be 0x1E6A2C48"
2555 );
2556
2557 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2559 encoder.encode_op(&rbit_op, &mut state);
2560 assert_eq!(
2561 state.get_reg(&Reg::R0).simplify().as_u64(),
2562 Some(0xFFFFFFFF),
2563 "RBIT(0xFFFFFFFF) should be 0xFFFFFFFF"
2564 );
2565 });
2566 }
2567
2568 #[test]
2569 fn test_arm_cmp_flags() {
2570 with_verification_context(|| {
2573 let encoder = ArmSemantics::new();
2574 let mut state = ArmState::new_symbolic();
2575
2576 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2579 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2580
2581 let cmp_op = ArmOp::Cmp {
2582 rn: Reg::R0,
2583 op2: Operand2::Reg(Reg::R1),
2584 };
2585 encoder.encode_op(&cmp_op, &mut state);
2586
2587 assert_eq!(
2588 state.flags.z.simplify().as_bool(),
2589 Some(true),
2590 "Z flag should be set (equal)"
2591 );
2592 assert_eq!(
2593 state.flags.n.simplify().as_bool(),
2594 Some(false),
2595 "N flag should be clear (non-negative)"
2596 );
2597 assert_eq!(
2598 state.flags.c.simplify().as_bool(),
2599 Some(true),
2600 "C flag should be set (no borrow)"
2601 );
2602 assert_eq!(
2603 state.flags.v.simplify().as_bool(),
2604 Some(false),
2605 "V flag should be clear (no overflow)"
2606 );
2607
2608 state.set_reg(&Reg::R0, BV::from_i64(20, 32));
2611 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2612 encoder.encode_op(&cmp_op, &mut state);
2613
2614 assert_eq!(
2615 state.flags.z.simplify().as_bool(),
2616 Some(false),
2617 "Z flag should be clear (not equal)"
2618 );
2619 assert_eq!(
2620 state.flags.n.simplify().as_bool(),
2621 Some(false),
2622 "N flag should be clear (positive result)"
2623 );
2624 assert_eq!(
2625 state.flags.c.simplify().as_bool(),
2626 Some(true),
2627 "C flag should be set (no borrow)"
2628 );
2629 assert_eq!(
2630 state.flags.v.simplify().as_bool(),
2631 Some(false),
2632 "V flag should be clear (no overflow)"
2633 );
2634
2635 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2639 state.set_reg(&Reg::R1, BV::from_i64(20, 32));
2640 encoder.encode_op(&cmp_op, &mut state);
2641
2642 assert_eq!(
2643 state.flags.z.simplify().as_bool(),
2644 Some(false),
2645 "Z flag should be clear"
2646 );
2647 assert_eq!(
2648 state.flags.n.simplify().as_bool(),
2649 Some(true),
2650 "N flag should be set (negative result)"
2651 );
2652 assert_eq!(
2653 state.flags.c.simplify().as_bool(),
2654 Some(false),
2655 "C flag should be clear (borrow occurred)"
2656 );
2657 assert_eq!(
2658 state.flags.v.simplify().as_bool(),
2659 Some(false),
2660 "V flag should be clear"
2661 );
2662
2663 state.set_reg(&Reg::R0, BV::from_i64(0x7FFFFFFF, 32));
2668 state.set_reg(&Reg::R1, BV::from_i64(-2147483648i64, 32)); encoder.encode_op(&cmp_op, &mut state);
2670
2671 assert_eq!(
2672 state.flags.z.simplify().as_bool(),
2673 Some(false),
2674 "Z flag should be clear"
2675 );
2676 assert_eq!(
2677 state.flags.n.simplify().as_bool(),
2678 Some(true),
2679 "N flag should be set (wrapped result)"
2680 );
2681 assert_eq!(
2682 state.flags.c.simplify().as_bool(),
2683 Some(false),
2684 "C flag should be clear"
2685 );
2686 assert_eq!(
2687 state.flags.v.simplify().as_bool(),
2688 Some(true),
2689 "V flag should be set (overflow)"
2690 );
2691
2692 state.set_reg(&Reg::R0, BV::from_i64(0, 32));
2694 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2695 encoder.encode_op(&cmp_op, &mut state);
2696
2697 assert_eq!(
2698 state.flags.z.simplify().as_bool(),
2699 Some(true),
2700 "Z flag should be set (0 - 0 = 0)"
2701 );
2702 assert_eq!(
2703 state.flags.n.simplify().as_bool(),
2704 Some(false),
2705 "N flag should be clear"
2706 );
2707 assert_eq!(
2708 state.flags.c.simplify().as_bool(),
2709 Some(true),
2710 "C flag should be set"
2711 );
2712 assert_eq!(
2713 state.flags.v.simplify().as_bool(),
2714 Some(false),
2715 "V flag should be clear"
2716 );
2717 });
2718 }
2719
2720 #[test]
2721 fn test_arm_flags_all_combinations() {
2722 with_verification_context(|| {
2725 let encoder = ArmSemantics::new();
2726 let mut state = ArmState::new_symbolic();
2727
2728 let cmp_op = ArmOp::Cmp {
2729 rn: Reg::R0,
2730 op2: Operand2::Reg(Reg::R1),
2731 };
2732
2733 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2744 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2745 encoder.encode_op(&cmp_op, &mut state);
2746
2747 let n = state.flags.n.simplify().as_bool().unwrap();
2748 let z = state.flags.z.simplify().as_bool().unwrap();
2749 let v = state.flags.v.simplify().as_bool().unwrap();
2750
2751 assert!(!z, "Not equal");
2752 assert!(n != v, "5 < 10 signed (N != V)");
2753
2754 state.set_reg(&Reg::R0, BV::from_i64(-5, 32));
2756 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2757 encoder.encode_op(&cmp_op, &mut state);
2758
2759 let n = state.flags.n.simplify().as_bool().unwrap();
2760 let v = state.flags.v.simplify().as_bool().unwrap();
2761 assert!(n != v, "-5 < 10 signed (N != V)");
2762 });
2763 }
2764
2765 #[test]
2766 fn test_arm_setcond_eq() {
2767 with_verification_context(|| {
2768 let encoder = ArmSemantics::new();
2769 let mut state = ArmState::new_symbolic();
2770
2771 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2773 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2774
2775 let cmp_op = ArmOp::Cmp {
2777 rn: Reg::R0,
2778 op2: Operand2::Reg(Reg::R1),
2779 };
2780 encoder.encode_op(&cmp_op, &mut state);
2781
2782 let setcond_op = ArmOp::SetCond {
2784 rd: Reg::R0,
2785 cond: synth_synthesis::Condition::EQ,
2786 };
2787 encoder.encode_op(&setcond_op, &mut state);
2788
2789 assert_eq!(
2790 state.get_reg(&Reg::R0).simplify().as_i64(),
2791 Some(1),
2792 "EQ condition (10 == 10) should return 1"
2793 );
2794
2795 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2797 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2798
2799 encoder.encode_op(&cmp_op, &mut state);
2800
2801 let setcond_ne = ArmOp::SetCond {
2802 rd: Reg::R0,
2803 cond: synth_synthesis::Condition::NE,
2804 };
2805 encoder.encode_op(&setcond_ne, &mut state);
2806
2807 assert_eq!(
2808 state.get_reg(&Reg::R0).simplify().as_i64(),
2809 Some(1),
2810 "NE condition (10 != 5) should return 1"
2811 );
2812 });
2813 }
2814
2815 #[test]
2816 fn test_arm_setcond_signed() {
2817 with_verification_context(|| {
2818 let encoder = ArmSemantics::new();
2819 let mut state = ArmState::new_symbolic();
2820
2821 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2823 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2824
2825 let cmp_op = ArmOp::Cmp {
2826 rn: Reg::R0,
2827 op2: Operand2::Reg(Reg::R1),
2828 };
2829 encoder.encode_op(&cmp_op, &mut state);
2830
2831 let setcond_lt = ArmOp::SetCond {
2832 rd: Reg::R0,
2833 cond: synth_synthesis::Condition::LT,
2834 };
2835 encoder.encode_op(&setcond_lt, &mut state);
2836
2837 assert_eq!(
2838 state.get_reg(&Reg::R0).simplify().as_i64(),
2839 Some(1),
2840 "LT signed (5 < 10) should return 1"
2841 );
2842
2843 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2845 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2846
2847 encoder.encode_op(&cmp_op, &mut state);
2848
2849 let setcond_ge = ArmOp::SetCond {
2850 rd: Reg::R0,
2851 cond: synth_synthesis::Condition::GE,
2852 };
2853 encoder.encode_op(&setcond_ge, &mut state);
2854
2855 assert_eq!(
2856 state.get_reg(&Reg::R0).simplify().as_i64(),
2857 Some(1),
2858 "GE signed (10 >= 5) should return 1"
2859 );
2860
2861 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2863 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2864
2865 encoder.encode_op(&cmp_op, &mut state);
2866
2867 let setcond_gt = ArmOp::SetCond {
2868 rd: Reg::R0,
2869 cond: synth_synthesis::Condition::GT,
2870 };
2871 encoder.encode_op(&setcond_gt, &mut state);
2872
2873 assert_eq!(
2874 state.get_reg(&Reg::R0).simplify().as_i64(),
2875 Some(1),
2876 "GT signed (10 > 5) should return 1"
2877 );
2878
2879 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2881 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2882
2883 encoder.encode_op(&cmp_op, &mut state);
2884
2885 let setcond_le = ArmOp::SetCond {
2886 rd: Reg::R0,
2887 cond: synth_synthesis::Condition::LE,
2888 };
2889 encoder.encode_op(&setcond_le, &mut state);
2890
2891 assert_eq!(
2892 state.get_reg(&Reg::R0).simplify().as_i64(),
2893 Some(1),
2894 "LE signed (5 <= 10) should return 1"
2895 );
2896 });
2897 }
2898
2899 #[test]
2900 fn test_arm_setcond_unsigned() {
2901 with_verification_context(|| {
2902 let encoder = ArmSemantics::new();
2903 let mut state = ArmState::new_symbolic();
2904
2905 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2907 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2908
2909 let cmp_op = ArmOp::Cmp {
2910 rn: Reg::R0,
2911 op2: Operand2::Reg(Reg::R1),
2912 };
2913 encoder.encode_op(&cmp_op, &mut state);
2914
2915 let setcond_lo = ArmOp::SetCond {
2916 rd: Reg::R0,
2917 cond: synth_synthesis::Condition::LO,
2918 };
2919 encoder.encode_op(&setcond_lo, &mut state);
2920
2921 assert_eq!(
2922 state.get_reg(&Reg::R0).simplify().as_i64(),
2923 Some(1),
2924 "LO unsigned (5 < 10) should return 1"
2925 );
2926
2927 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2929 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2930
2931 encoder.encode_op(&cmp_op, &mut state);
2932
2933 let setcond_hs = ArmOp::SetCond {
2934 rd: Reg::R0,
2935 cond: synth_synthesis::Condition::HS,
2936 };
2937 encoder.encode_op(&setcond_hs, &mut state);
2938
2939 assert_eq!(
2940 state.get_reg(&Reg::R0).simplify().as_i64(),
2941 Some(1),
2942 "HS unsigned (10 >= 5) should return 1"
2943 );
2944
2945 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2947 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2948
2949 encoder.encode_op(&cmp_op, &mut state);
2950
2951 let setcond_hi = ArmOp::SetCond {
2952 rd: Reg::R0,
2953 cond: synth_synthesis::Condition::HI,
2954 };
2955 encoder.encode_op(&setcond_hi, &mut state);
2956
2957 assert_eq!(
2958 state.get_reg(&Reg::R0).simplify().as_i64(),
2959 Some(1),
2960 "HI unsigned (10 > 5) should return 1"
2961 );
2962
2963 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2965 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2966
2967 encoder.encode_op(&cmp_op, &mut state);
2968
2969 let setcond_ls = ArmOp::SetCond {
2970 rd: Reg::R0,
2971 cond: synth_synthesis::Condition::LS,
2972 };
2973 encoder.encode_op(&setcond_ls, &mut state);
2974
2975 assert_eq!(
2976 state.get_reg(&Reg::R0).simplify().as_i64(),
2977 Some(1),
2978 "LS unsigned (5 <= 10) should return 1"
2979 );
2980 });
2981 }
2982}