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 type_check: _,
493 } => {
494 let _table_index = state.get_reg(table_index_reg).clone();
496 let result = BV::new_const(format!("call_indirect_{}", type_idx), 32);
497 state.set_reg(rd, result);
498 }
499
500 ArmOp::I64Const { rdlo, rdhi, value } => {
506 let low32 = (*value as u32) as i64;
508 let high32 = *value >> 32;
509 state.set_reg(rdlo, BV::from_i64(low32, 32));
510 state.set_reg(rdhi, BV::from_i64(high32, 32));
511 }
512
513 ArmOp::I64Add {
514 rdlo,
515 rdhi,
516 rnlo,
517 rnhi,
518 rmlo,
519 rmhi,
520 } => {
521 let n_low = state.get_reg(rnlo).clone();
526 let m_low = state.get_reg(rmlo).clone();
527 let n_high = state.get_reg(rnhi).clone();
528 let m_high = state.get_reg(rmhi).clone();
529
530 let result_low = n_low.bvadd(&m_low);
532 state.set_reg(rdlo, result_low.clone());
533
534 let carry = result_low.bvult(&n_low);
537 let carry_bv = carry.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
538
539 let high_sum = n_high.bvadd(&m_high);
541 let result_high = high_sum.bvadd(&carry_bv);
542 state.set_reg(rdhi, result_high);
543 }
544
545 ArmOp::I64Eqz { rd, rnlo, rnhi } => {
546 let zero = BV::from_i64(0, 32);
549 let low_zero = state.get_reg(rnlo).eq(&zero);
550 let high_zero = state.get_reg(rnhi).eq(&zero);
551 let both_zero = Bool::and(&[&low_zero, &high_zero]);
552 let result = self.bool_to_bv32(&both_zero);
553 state.set_reg(rd, result);
554 }
555
556 ArmOp::I32WrapI64 { rd, rnlo } => {
557 let low_val = state.get_reg(rnlo).clone();
559 state.set_reg(rd, low_val);
560 }
561
562 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
563 let value = state.get_reg(rn).clone();
565 state.set_reg(rdlo, value.clone());
566
567 let sign_bit = value.extract(31, 31); let all_ones = BV::from_i64(-1, 32);
570 let zero = BV::from_i64(0, 32);
571 let high_val = sign_bit.eq(BV::from_i64(1, 1)).ite(&all_ones, &zero);
573 state.set_reg(rdhi, high_val);
574 }
575
576 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
577 let value = state.get_reg(rn).clone();
579 state.set_reg(rdlo, value);
580 state.set_reg(rdhi, BV::from_i64(0, 32));
582 }
583
584 ArmOp::I64Sub {
585 rdlo,
586 rdhi,
587 rnlo,
588 rnhi,
589 rmlo,
590 rmhi,
591 } => {
592 let n_low = state.get_reg(rnlo).clone();
597 let m_low = state.get_reg(rmlo).clone();
598 let n_high = state.get_reg(rnhi).clone();
599 let m_high = state.get_reg(rmhi).clone();
600
601 let result_low = n_low.bvsub(&m_low);
603 state.set_reg(rdlo, result_low.clone());
604
605 let borrow = n_low.bvult(&m_low);
607 let borrow_bv = borrow.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
608
609 let high_diff = n_high.bvsub(&m_high);
611 let result_high = high_diff.bvsub(&borrow_bv);
612 state.set_reg(rdhi, result_high);
613 }
614
615 ArmOp::I64Mul {
616 rd_lo,
617 rd_hi,
618 rn_lo,
619 rn_hi,
620 rm_lo,
621 rm_hi,
622 } => {
623 let a_lo = state.get_reg(rn_lo).clone();
629 let a_hi = state.get_reg(rn_hi).clone();
630 let b_lo = state.get_reg(rm_lo).clone();
631 let b_hi = state.get_reg(rm_hi).clone();
632
633 let lo_lo = a_lo.bvmul(&b_lo);
636 state.set_reg(rd_lo, lo_lo.clone());
637
638 let hi_lo = a_hi.bvmul(&b_lo); let lo_hi = a_lo.bvmul(&b_hi); let hi_sum = hi_lo.bvadd(&lo_hi);
652 state.set_reg(rd_hi, hi_sum);
653
654 }
660
661 ArmOp::I64DivS { rdlo, rdhi, .. } => {
668 state.set_reg(rdlo, BV::new_const("i64_divs_lo", 32));
672 state.set_reg(rdhi, BV::new_const("i64_divs_hi", 32));
673 }
674
675 ArmOp::I64DivU { rdlo, rdhi, .. } => {
676 state.set_reg(rdlo, BV::new_const("i64_divu_lo", 32));
680 state.set_reg(rdhi, BV::new_const("i64_divu_hi", 32));
681 }
682
683 ArmOp::I64RemS { rdlo, rdhi, .. } => {
684 state.set_reg(rdlo, BV::new_const("i64_rems_lo", 32));
688 state.set_reg(rdhi, BV::new_const("i64_rems_hi", 32));
689 }
690
691 ArmOp::I64RemU { rdlo, rdhi, .. } => {
692 state.set_reg(rdlo, BV::new_const("i64_remu_lo", 32));
696 state.set_reg(rdhi, BV::new_const("i64_remu_hi", 32));
697 }
698
699 ArmOp::I64And {
700 rdlo,
701 rdhi,
702 rnlo,
703 rnhi,
704 rmlo,
705 rmhi,
706 } => {
707 let n_low = state.get_reg(rnlo).clone();
708 let m_low = state.get_reg(rmlo).clone();
709 state.set_reg(rdlo, n_low.bvand(&m_low));
710
711 let n_high = state.get_reg(rnhi).clone();
712 let m_high = state.get_reg(rmhi).clone();
713 state.set_reg(rdhi, n_high.bvand(&m_high));
714 }
715
716 ArmOp::I64Or {
717 rdlo,
718 rdhi,
719 rnlo,
720 rnhi,
721 rmlo,
722 rmhi,
723 } => {
724 let n_low = state.get_reg(rnlo).clone();
725 let m_low = state.get_reg(rmlo).clone();
726 state.set_reg(rdlo, n_low.bvor(&m_low));
727
728 let n_high = state.get_reg(rnhi).clone();
729 let m_high = state.get_reg(rmhi).clone();
730 state.set_reg(rdhi, n_high.bvor(&m_high));
731 }
732
733 ArmOp::I64Xor {
734 rdlo,
735 rdhi,
736 rnlo,
737 rnhi,
738 rmlo,
739 rmhi,
740 } => {
741 let n_low = state.get_reg(rnlo).clone();
742 let m_low = state.get_reg(rmlo).clone();
743 state.set_reg(rdlo, n_low.bvxor(&m_low));
744
745 let n_high = state.get_reg(rnhi).clone();
746 let m_high = state.get_reg(rmhi).clone();
747 state.set_reg(rdhi, n_high.bvxor(&m_high));
748 }
749
750 ArmOp::I64Eq {
751 rd,
752 rnlo,
753 rnhi,
754 rmlo,
755 rmhi,
756 } => {
757 let n_low = state.get_reg(rnlo).clone();
758 let m_low = state.get_reg(rmlo).clone();
759 let n_high = state.get_reg(rnhi).clone();
760 let m_high = state.get_reg(rmhi).clone();
761
762 let low_eq = n_low.eq(&m_low);
763 let high_eq = n_high.eq(&m_high);
764 let both_eq = Bool::and(&[&low_eq, &high_eq]);
765 let result = self.bool_to_bv32(&both_eq);
766 state.set_reg(rd, result);
767 }
768
769 ArmOp::I64LtS {
770 rd,
771 rnlo,
772 rnhi,
773 rmlo,
774 rmhi,
775 } => {
776 let n_low = state.get_reg(rnlo).clone();
779 let m_low = state.get_reg(rmlo).clone();
780 let n_high = state.get_reg(rnhi).clone();
781 let m_high = state.get_reg(rmhi).clone();
782
783 let high_lt = n_high.bvslt(&m_high);
785 let high_eq = n_high.eq(&m_high);
786
787 let low_lt = n_low.bvult(&m_low);
789
790 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
792 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
793 let result = self.bool_to_bv32(&result_bool);
794 state.set_reg(rd, result);
795 }
796
797 ArmOp::I64LtU {
798 rd,
799 rnlo,
800 rnhi,
801 rmlo,
802 rmhi,
803 } => {
804 let n_low = state.get_reg(rnlo).clone();
807 let m_low = state.get_reg(rmlo).clone();
808 let n_high = state.get_reg(rnhi).clone();
809 let m_high = state.get_reg(rmhi).clone();
810
811 let high_lt = n_high.bvult(&m_high);
813 let high_eq = n_high.eq(&m_high);
814
815 let low_lt = n_low.bvult(&m_low);
817
818 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
820 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
821 let result = self.bool_to_bv32(&result_bool);
822 state.set_reg(rd, result);
823 }
824
825 ArmOp::I64Ne {
826 rd,
827 rnlo,
828 rnhi,
829 rmlo,
830 rmhi,
831 } => {
832 let n_low = state.get_reg(rnlo).clone();
834 let m_low = state.get_reg(rmlo).clone();
835 let n_high = state.get_reg(rnhi).clone();
836 let m_high = state.get_reg(rmhi).clone();
837
838 let low_eq = n_low.eq(&m_low);
839 let high_eq = n_high.eq(&m_high);
840 let both_eq = Bool::and(&[&low_eq, &high_eq]);
841 let not_eq = both_eq.not();
842 let result = self.bool_to_bv32(¬_eq);
843 state.set_reg(rd, result);
844 }
845
846 ArmOp::I64LeS {
847 rd,
848 rnlo,
849 rnhi,
850 rmlo,
851 rmhi,
852 } => {
853 let n_low = state.get_reg(rnlo).clone();
856 let m_low = state.get_reg(rmlo).clone();
857 let n_high = state.get_reg(rnhi).clone();
858 let m_high = state.get_reg(rmhi).clone();
859
860 let high_lt = n_high.bvslt(&m_high);
861 let high_eq = n_high.eq(&m_high);
862 let low_le = n_low.bvule(&m_low); let eq_and_le = Bool::and(&[&high_eq, &low_le]);
865 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
866 let result = self.bool_to_bv32(&result_bool);
867 state.set_reg(rd, result);
868 }
869
870 ArmOp::I64LeU {
871 rd,
872 rnlo,
873 rnhi,
874 rmlo,
875 rmhi,
876 } => {
877 let n_low = state.get_reg(rnlo).clone();
879 let m_low = state.get_reg(rmlo).clone();
880 let n_high = state.get_reg(rnhi).clone();
881 let m_high = state.get_reg(rmhi).clone();
882
883 let high_lt = n_high.bvult(&m_high);
884 let high_eq = n_high.eq(&m_high);
885 let low_le = n_low.bvule(&m_low);
886
887 let eq_and_le = Bool::and(&[&high_eq, &low_le]);
888 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
889 let result = self.bool_to_bv32(&result_bool);
890 state.set_reg(rd, result);
891 }
892
893 ArmOp::I64GtS {
894 rd,
895 rnlo,
896 rnhi,
897 rmlo,
898 rmhi,
899 } => {
900 let n_low = state.get_reg(rnlo).clone();
903 let m_low = state.get_reg(rmlo).clone();
904 let n_high = state.get_reg(rnhi).clone();
905 let m_high = state.get_reg(rmhi).clone();
906
907 let high_gt = n_high.bvsgt(&m_high);
908 let high_eq = n_high.eq(&m_high);
909 let low_gt = n_low.bvugt(&m_low); let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
912 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
913 let result = self.bool_to_bv32(&result_bool);
914 state.set_reg(rd, result);
915 }
916
917 ArmOp::I64GtU {
918 rd,
919 rnlo,
920 rnhi,
921 rmlo,
922 rmhi,
923 } => {
924 let n_low = state.get_reg(rnlo).clone();
926 let m_low = state.get_reg(rmlo).clone();
927 let n_high = state.get_reg(rnhi).clone();
928 let m_high = state.get_reg(rmhi).clone();
929
930 let high_gt = n_high.bvugt(&m_high);
931 let high_eq = n_high.eq(&m_high);
932 let low_gt = n_low.bvugt(&m_low);
933
934 let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
935 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
936 let result = self.bool_to_bv32(&result_bool);
937 state.set_reg(rd, result);
938 }
939
940 ArmOp::I64GeS {
941 rd,
942 rnlo,
943 rnhi,
944 rmlo,
945 rmhi,
946 } => {
947 let n_low = state.get_reg(rnlo).clone();
950 let m_low = state.get_reg(rmlo).clone();
951 let n_high = state.get_reg(rnhi).clone();
952 let m_high = state.get_reg(rmhi).clone();
953
954 let high_lt = n_high.bvslt(&m_high);
955 let high_eq = n_high.eq(&m_high);
956 let low_lt = n_low.bvult(&m_low);
957
958 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
959 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
960 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
962 state.set_reg(rd, result);
963 }
964
965 ArmOp::I64GeU {
966 rd,
967 rnlo,
968 rnhi,
969 rmlo,
970 rmhi,
971 } => {
972 let n_low = state.get_reg(rnlo).clone();
975 let m_low = state.get_reg(rmlo).clone();
976 let n_high = state.get_reg(rnhi).clone();
977 let m_high = state.get_reg(rmhi).clone();
978
979 let high_lt = n_high.bvult(&m_high);
980 let high_eq = n_high.eq(&m_high);
981 let low_lt = n_low.bvult(&m_low);
982
983 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
984 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
985 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
987 state.set_reg(rd, result);
988 }
989
990 ArmOp::I64Shl {
994 rd_lo,
995 rd_hi,
996 rn_lo,
997 rn_hi,
998 rm_lo,
999 rm_hi: _,
1000 } => {
1001 let n_lo = state.get_reg(rn_lo).clone();
1004 let n_hi = state.get_reg(rn_hi).clone();
1005 let shift_amt = state.get_reg(rm_lo).clone();
1006
1007 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1009
1010 let shift_32 = BV::from_i64(32, 32);
1013 let is_large = shift_mod.bvuge(&shift_32); let result_lo_small = n_lo.bvshl(&shift_mod);
1019 let shift_complement = shift_32.bvsub(&shift_mod);
1020 let bits_to_high = n_lo.bvlshr(&shift_complement);
1021 let result_hi_small = n_hi.bvshl(&shift_mod).bvor(&bits_to_high);
1022
1023 let zero = BV::from_i64(0, 32);
1027 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1028 let result_lo_large = zero.clone();
1029 let result_hi_large = n_lo.bvshl(&shift_minus_32);
1030
1031 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1033 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1034
1035 state.set_reg(rd_lo, result_lo);
1036 state.set_reg(rd_hi, result_hi);
1037 }
1038
1039 ArmOp::I64ShrU {
1040 rd_lo,
1041 rd_hi,
1042 rn_lo,
1043 rn_hi,
1044 rm_lo,
1045 rm_hi: _,
1046 } => {
1047 let n_lo = state.get_reg(rn_lo).clone();
1049 let n_hi = state.get_reg(rn_hi).clone();
1050 let shift_amt = state.get_reg(rm_lo).clone();
1051
1052 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1053 let shift_32 = BV::from_i64(32, 32);
1054 let is_large = shift_mod.bvuge(&shift_32);
1055
1056 let result_hi_small = n_hi.bvlshr(&shift_mod);
1060 let shift_complement = shift_32.bvsub(&shift_mod);
1061 let bits_to_low = n_hi.bvshl(&shift_complement);
1062 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1063
1064 let zero = BV::from_i64(0, 32);
1068 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1069 let result_hi_large = zero.clone();
1070 let result_lo_large = n_hi.bvlshr(&shift_minus_32);
1071
1072 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1073 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1074
1075 state.set_reg(rd_lo, result_lo);
1076 state.set_reg(rd_hi, result_hi);
1077 }
1078
1079 ArmOp::I64ShrS {
1080 rd_lo,
1081 rd_hi,
1082 rn_lo,
1083 rn_hi,
1084 rm_lo,
1085 rm_hi: _,
1086 } => {
1087 let n_lo = state.get_reg(rn_lo).clone();
1089 let n_hi = state.get_reg(rn_hi).clone();
1090 let shift_amt = state.get_reg(rm_lo).clone();
1091
1092 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1093 let shift_32 = BV::from_i64(32, 32);
1094 let is_large = shift_mod.bvuge(&shift_32);
1095
1096 let result_hi_small = n_hi.bvashr(&shift_mod);
1100 let shift_complement = shift_32.bvsub(&shift_mod);
1101 let bits_to_low = n_hi.bvshl(&shift_complement);
1102 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1103
1104 let shift_31 = BV::from_i64(31, 32);
1108 let result_hi_large = n_hi.bvashr(&shift_31);
1109 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1110 let result_lo_large = n_hi.bvashr(&shift_minus_32);
1111
1112 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1113 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1114
1115 state.set_reg(rd_lo, result_lo);
1116 state.set_reg(rd_hi, result_hi);
1117 }
1118
1119 ArmOp::I64Rotl {
1123 rdlo,
1124 rdhi,
1125 rnlo,
1126 rnhi,
1127 shift,
1128 } => {
1129 let n_lo = state.get_reg(rnlo).clone();
1132 let n_hi = state.get_reg(rnhi).clone();
1133 let shift_amt = state.get_reg(shift).clone();
1134
1135 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1137 let shift_32 = BV::from_i64(32, 32);
1138 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1144
1145 let lo_shifted_left = n_lo.bvshl(&shift_mod);
1146 let hi_bits_to_lo = n_hi.bvlshr(&shift_complement);
1147 let result_lo_small = lo_shifted_left.bvor(&hi_bits_to_lo);
1148
1149 let hi_shifted_left = n_hi.bvshl(&shift_mod);
1150 let lo_bits_to_hi = n_lo.bvlshr(&shift_complement);
1151 let result_hi_small = hi_shifted_left.bvor(&lo_bits_to_hi);
1152
1153 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1156 let complement_large = shift_32.bvsub(&shift_minus_32);
1157
1158 let hi_shifted_left_large = n_hi.bvshl(&shift_minus_32);
1159 let lo_bits_to_hi_large = n_lo.bvlshr(&complement_large);
1160 let result_lo_large = hi_shifted_left_large.bvor(&lo_bits_to_hi_large);
1161
1162 let lo_shifted_left_large = n_lo.bvshl(&shift_minus_32);
1163 let hi_bits_to_lo_large = n_hi.bvlshr(&complement_large);
1164 let result_hi_large = lo_shifted_left_large.bvor(&hi_bits_to_lo_large);
1165
1166 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1168 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1169
1170 state.set_reg(rdlo, result_lo);
1171 state.set_reg(rdhi, result_hi);
1172 }
1173
1174 ArmOp::I64Rotr {
1175 rdlo,
1176 rdhi,
1177 rnlo,
1178 rnhi,
1179 shift,
1180 } => {
1181 let n_lo = state.get_reg(rnlo).clone();
1184 let n_hi = state.get_reg(rnhi).clone();
1185 let shift_amt = state.get_reg(shift).clone();
1186
1187 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1189 let shift_32 = BV::from_i64(32, 32);
1190 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1196
1197 let lo_shifted_right = n_lo.bvlshr(&shift_mod);
1198 let hi_bits_to_lo = n_hi.bvshl(&shift_complement);
1199 let result_lo_small = lo_shifted_right.bvor(&hi_bits_to_lo);
1200
1201 let hi_shifted_right = n_hi.bvlshr(&shift_mod);
1202 let lo_bits_to_hi = n_lo.bvshl(&shift_complement);
1203 let result_hi_small = hi_shifted_right.bvor(&lo_bits_to_hi);
1204
1205 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1208 let complement_large = shift_32.bvsub(&shift_minus_32);
1209
1210 let hi_shifted_right_large = n_hi.bvlshr(&shift_minus_32);
1211 let lo_bits_to_hi_large = n_lo.bvshl(&complement_large);
1212 let result_lo_large = hi_shifted_right_large.bvor(&lo_bits_to_hi_large);
1213
1214 let lo_shifted_right_large = n_lo.bvlshr(&shift_minus_32);
1215 let hi_bits_to_lo_large = n_hi.bvshl(&complement_large);
1216 let result_hi_large = lo_shifted_right_large.bvor(&hi_bits_to_lo_large);
1217
1218 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1220 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1221
1222 state.set_reg(rdlo, result_lo);
1223 state.set_reg(rdhi, result_hi);
1224 }
1225
1226 ArmOp::I64Clz { rd, rnlo, rnhi } => {
1227 let n_lo = state.get_reg(rnlo).clone();
1231 let n_hi = state.get_reg(rnhi).clone();
1232
1233 let hi_clz = self.encode_clz(&n_hi);
1234 let lo_clz = self.encode_clz(&n_lo);
1235
1236 let thirty_two = BV::from_i64(32, 32);
1238 let hi_is_zero = hi_clz.eq(&thirty_two);
1239 let result = hi_is_zero.ite(
1240 thirty_two.bvadd(&lo_clz), &hi_clz, );
1243 state.set_reg(rd, result);
1244 }
1245
1246 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
1247 let n_lo = state.get_reg(rnlo).clone();
1251 let n_hi = state.get_reg(rnhi).clone();
1252
1253 let lo_ctz = self.encode_ctz(&n_lo);
1254 let hi_ctz = self.encode_ctz(&n_hi);
1255
1256 let thirty_two = BV::from_i64(32, 32);
1258 let lo_is_zero = lo_ctz.eq(&thirty_two);
1259 let result = lo_is_zero.ite(
1260 thirty_two.bvadd(&hi_ctz), &lo_ctz, );
1263 state.set_reg(rd, result);
1264 }
1265
1266 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
1267 let n_lo = state.get_reg(rnlo).clone();
1270 let n_hi = state.get_reg(rnhi).clone();
1271
1272 let lo_popcnt = self.encode_popcnt(&n_lo);
1273 let hi_popcnt = self.encode_popcnt(&n_hi);
1274
1275 let result = lo_popcnt.bvadd(&hi_popcnt);
1276 state.set_reg(rd, result);
1277 }
1278
1279 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
1283 let result_lo = BV::new_const(format!("i64load_lo_{:?}", addr), 32);
1287 let result_hi = BV::new_const(format!("i64load_hi_{:?}", addr), 32);
1288 state.set_reg(rdlo, result_lo);
1289 state.set_reg(rdhi, result_hi);
1290 }
1291
1292 ArmOp::I64Str {
1293 rdlo: _,
1294 rdhi: _,
1295 addr: _,
1296 } => {
1297 }
1302
1303 ArmOp::F32Const { sd, value } => {
1312 let bits = value.to_bits() as i64;
1315 let bv_val = BV::from_i64(bits, 32);
1316 state.set_vfp_reg(sd, bv_val);
1317 }
1318
1319 ArmOp::F32Add { sd, sn, sm } => {
1321 let result = BV::new_const(format!("f32_add_{:?}_{:?}", sn, sm), 32);
1325 state.set_vfp_reg(sd, result);
1326 }
1327
1328 ArmOp::F32Sub { sd, sn, sm } => {
1329 let result = BV::new_const(format!("f32_sub_{:?}_{:?}", sn, sm), 32);
1331 state.set_vfp_reg(sd, result);
1332 }
1333
1334 ArmOp::F32Mul { sd, sn, sm } => {
1335 let result = BV::new_const(format!("f32_mul_{:?}_{:?}", sn, sm), 32);
1337 state.set_vfp_reg(sd, result);
1338 }
1339
1340 ArmOp::F32Div { sd, sn, sm } => {
1341 let result = BV::new_const(format!("f32_div_{:?}_{:?}", sn, sm), 32);
1343 state.set_vfp_reg(sd, result);
1344 }
1345
1346 ArmOp::F32Abs { sd, sm } => {
1348 let val = state.get_vfp_reg(sm).clone();
1351 let mask = BV::from_u64(0x7FFFFFFF, 32); let result = val.bvand(&mask);
1353 state.set_vfp_reg(sd, result);
1354 }
1355
1356 ArmOp::F32Neg { sd, sm } => {
1357 let val = state.get_vfp_reg(sm).clone();
1360 let mask = BV::from_u64(0x80000000, 32); let result = val.bvxor(&mask);
1362 state.set_vfp_reg(sd, result);
1363 }
1364
1365 ArmOp::F32Sqrt { sd, sm } => {
1366 let result = BV::new_const(format!("f32_sqrt_{:?}", sm), 32);
1369 state.set_vfp_reg(sd, result);
1370 }
1371
1372 ArmOp::F32Min { sd, sn, sm } => {
1373 let result = BV::new_const(format!("f32_min_{:?}_{:?}", sn, sm), 32);
1377 state.set_vfp_reg(sd, result);
1378 }
1379
1380 ArmOp::F32Max { sd, sn, sm } => {
1381 let result = BV::new_const(format!("f32_max_{:?}_{:?}", sn, sm), 32);
1385 state.set_vfp_reg(sd, result);
1386 }
1387
1388 ArmOp::F32Copysign { sd, sn, sm } => {
1389 let val_n = state.get_vfp_reg(sn).clone();
1392 let val_m = state.get_vfp_reg(sm).clone();
1393
1394 let mag_mask = BV::from_u64(0x7FFFFFFF, 32);
1396 let magnitude = val_n.bvand(&mag_mask);
1397
1398 let sign_mask = BV::from_u64(0x80000000, 32);
1400 let sign = val_m.bvand(&sign_mask);
1401
1402 let result = magnitude.bvor(&sign);
1404 state.set_vfp_reg(sd, result);
1405 }
1406
1407 ArmOp::F32Load { sd, addr } => {
1408 let result = BV::new_const(format!("f32_load_{:?}", addr), 32);
1411 state.set_vfp_reg(sd, result);
1412 }
1413
1414 ArmOp::F32Eq { rd, sn, sm } => {
1416 let result = BV::new_const(format!("f32_eq_{:?}_{:?}", sn, sm), 32);
1419 state.set_reg(rd, result);
1420 }
1421
1422 ArmOp::F32Ne { rd, sn, sm } => {
1423 let result = BV::new_const(format!("f32_ne_{:?}_{:?}", sn, sm), 32);
1425 state.set_reg(rd, result);
1426 }
1427
1428 ArmOp::F32Lt { rd, sn, sm } => {
1429 let result = BV::new_const(format!("f32_lt_{:?}_{:?}", sn, sm), 32);
1431 state.set_reg(rd, result);
1432 }
1433
1434 ArmOp::F32Le { rd, sn, sm } => {
1435 let result = BV::new_const(format!("f32_le_{:?}_{:?}", sn, sm), 32);
1437 state.set_reg(rd, result);
1438 }
1439
1440 ArmOp::F32Gt { rd, sn, sm } => {
1441 let result = BV::new_const(format!("f32_gt_{:?}_{:?}", sn, sm), 32);
1443 state.set_reg(rd, result);
1444 }
1445
1446 ArmOp::F32Ge { rd, sn, sm } => {
1447 let result = BV::new_const(format!("f32_ge_{:?}_{:?}", sn, sm), 32);
1449 state.set_reg(rd, result);
1450 }
1451
1452 ArmOp::F32Store { sd, addr } => {
1453 let _val = state.get_vfp_reg(sd);
1458 let _addr_str = format!("{:?}", addr);
1459 }
1461
1462 ArmOp::F32Ceil { sd, sm } => {
1464 let result = BV::new_const(format!("f32_ceil_{:?}", sm), 32);
1467 state.set_vfp_reg(sd, result);
1468 }
1469
1470 ArmOp::F32Floor { sd, sm } => {
1471 let result = BV::new_const(format!("f32_floor_{:?}", sm), 32);
1474 state.set_vfp_reg(sd, result);
1475 }
1476
1477 ArmOp::F32Trunc { sd, sm } => {
1478 let result = BV::new_const(format!("f32_trunc_{:?}", sm), 32);
1481 state.set_vfp_reg(sd, result);
1482 }
1483
1484 ArmOp::F32Nearest { sd, sm } => {
1485 let result = BV::new_const(format!("f32_nearest_{:?}", sm), 32);
1488 state.set_vfp_reg(sd, result);
1489 }
1490
1491 ArmOp::F32ConvertI32S { sd, rm } => {
1493 let int_val = state.get_reg(rm);
1495 let result = BV::new_const(format!("f32_convert_i32s_{:?}", int_val), 32);
1496 state.set_vfp_reg(sd, result);
1497 }
1498
1499 ArmOp::F32ConvertI32U { sd, rm } => {
1500 let int_val = state.get_reg(rm);
1502 let result = BV::new_const(format!("f32_convert_i32u_{:?}", int_val), 32);
1503 state.set_vfp_reg(sd, result);
1504 }
1505
1506 ArmOp::F32ConvertI64S { sd, rmlo, rmhi } => {
1507 let lo = state.get_reg(rmlo);
1509 let hi = state.get_reg(rmhi);
1510 let result = BV::new_const(format!("f32_convert_i64s_{:?}_{:?}", lo, hi), 32);
1511 state.set_vfp_reg(sd, result);
1512 }
1513
1514 ArmOp::F32ConvertI64U { sd, rmlo, rmhi } => {
1515 let lo = state.get_reg(rmlo);
1517 let hi = state.get_reg(rmhi);
1518 let result = BV::new_const(format!("f32_convert_i64u_{:?}_{:?}", lo, hi), 32);
1519 state.set_vfp_reg(sd, result);
1520 }
1521
1522 ArmOp::F32ReinterpretI32 { sd, rm } => {
1524 let bits = state.get_reg(rm).clone();
1527 state.set_vfp_reg(sd, bits);
1528 }
1529
1530 ArmOp::I32ReinterpretF32 { rd, sm } => {
1531 let bits = state.get_vfp_reg(sm).clone();
1534 state.set_reg(rd, bits);
1535 }
1536
1537 ArmOp::F64Add { dd, dn, dm } => {
1543 let result = BV::new_const(format!("f64_add_{:?}_{:?}", dn, dm), 64);
1547 state.set_vfp_reg(dd, result);
1548 }
1549
1550 ArmOp::F64Sub { dd, dn, dm } => {
1551 let result = BV::new_const(format!("f64_sub_{:?}_{:?}", dn, dm), 64);
1553 state.set_vfp_reg(dd, result);
1554 }
1555
1556 ArmOp::F64Mul { dd, dn, dm } => {
1557 let result = BV::new_const(format!("f64_mul_{:?}_{:?}", dn, dm), 64);
1559 state.set_vfp_reg(dd, result);
1560 }
1561
1562 ArmOp::F64Div { dd, dn, dm } => {
1563 let result = BV::new_const(format!("f64_div_{:?}_{:?}", dn, dm), 64);
1565 state.set_vfp_reg(dd, result);
1566 }
1567
1568 ArmOp::F64Abs { dd, dm } => {
1570 let val = state.get_vfp_reg(dm).clone();
1573 let mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64); let result = val.bvand(&mask);
1575 state.set_vfp_reg(dd, result);
1576 }
1577
1578 ArmOp::F64Neg { dd, dm } => {
1579 let val = state.get_vfp_reg(dm).clone();
1582 let mask = BV::from_u64(0x8000000000000000, 64); let result = val.bvxor(&mask);
1584 state.set_vfp_reg(dd, result);
1585 }
1586
1587 ArmOp::F64Sqrt { dd, dm } => {
1588 let result = BV::new_const(format!("f64_sqrt_{:?}", dm), 64);
1591 state.set_vfp_reg(dd, result);
1592 }
1593
1594 ArmOp::F64Min { dd, dn, dm } => {
1595 let result = BV::new_const(format!("f64_min_{:?}_{:?}", dn, dm), 64);
1599 state.set_vfp_reg(dd, result);
1600 }
1601
1602 ArmOp::F64Max { dd, dn, dm } => {
1603 let result = BV::new_const(format!("f64_max_{:?}_{:?}", dn, dm), 64);
1607 state.set_vfp_reg(dd, result);
1608 }
1609
1610 ArmOp::F64Copysign { dd, dn, dm } => {
1611 let val_n = state.get_vfp_reg(dn).clone();
1614 let val_m = state.get_vfp_reg(dm).clone();
1615
1616 let mag_mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64);
1618 let magnitude = val_n.bvand(&mag_mask);
1619
1620 let sign_mask = BV::from_u64(0x8000000000000000, 64);
1622 let sign = val_m.bvand(&sign_mask);
1623
1624 let result = magnitude.bvor(&sign);
1626 state.set_vfp_reg(dd, result);
1627 }
1628
1629 ArmOp::F64Ceil { dd, dm } => {
1631 let result = BV::new_const(format!("f64_ceil_{:?}", dm), 64);
1633 state.set_vfp_reg(dd, result);
1634 }
1635
1636 ArmOp::F64Floor { dd, dm } => {
1637 let result = BV::new_const(format!("f64_floor_{:?}", dm), 64);
1639 state.set_vfp_reg(dd, result);
1640 }
1641
1642 ArmOp::F64Trunc { dd, dm } => {
1643 let result = BV::new_const(format!("f64_trunc_{:?}", dm), 64);
1645 state.set_vfp_reg(dd, result);
1646 }
1647
1648 ArmOp::F64Nearest { dd, dm } => {
1649 let result = BV::new_const(format!("f64_nearest_{:?}", dm), 64);
1651 state.set_vfp_reg(dd, result);
1652 }
1653
1654 ArmOp::F64Load { dd, addr } => {
1656 let result = BV::new_const(format!("f64_load_{:?}", addr), 64);
1659 state.set_vfp_reg(dd, result);
1660 }
1661
1662 ArmOp::F64Store { dd: _, addr: _ } => {
1663 }
1667
1668 ArmOp::F64Const { dd, value } => {
1669 let bits = value.to_bits() as i64;
1671 let result = BV::from_i64(bits, 64);
1672 state.set_vfp_reg(dd, result);
1673 }
1674
1675 ArmOp::F64Eq { rd, dn, dm } => {
1677 let result = BV::new_const(format!("f64_eq_{:?}_{:?}", dn, dm), 32);
1680 state.set_reg(rd, result);
1681 }
1682
1683 ArmOp::F64Ne { rd, dn, dm } => {
1684 let result = BV::new_const(format!("f64_ne_{:?}_{:?}", dn, dm), 32);
1686 state.set_reg(rd, result);
1687 }
1688
1689 ArmOp::F64Lt { rd, dn, dm } => {
1690 let result = BV::new_const(format!("f64_lt_{:?}_{:?}", dn, dm), 32);
1692 state.set_reg(rd, result);
1693 }
1694
1695 ArmOp::F64Le { rd, dn, dm } => {
1696 let result = BV::new_const(format!("f64_le_{:?}_{:?}", dn, dm), 32);
1698 state.set_reg(rd, result);
1699 }
1700
1701 ArmOp::F64Gt { rd, dn, dm } => {
1702 let result = BV::new_const(format!("f64_gt_{:?}_{:?}", dn, dm), 32);
1704 state.set_reg(rd, result);
1705 }
1706
1707 ArmOp::F64Ge { rd, dn, dm } => {
1708 let result = BV::new_const(format!("f64_ge_{:?}_{:?}", dn, dm), 32);
1710 state.set_reg(rd, result);
1711 }
1712
1713 ArmOp::F64ConvertI32S { dd, rm } => {
1715 let result = BV::new_const(format!("f64_convert_i32s_{:?}", rm), 64);
1718 state.set_vfp_reg(dd, result);
1719 }
1720
1721 ArmOp::F64ConvertI32U { dd, rm } => {
1722 let result = BV::new_const(format!("f64_convert_i32u_{:?}", rm), 64);
1725 state.set_vfp_reg(dd, result);
1726 }
1727
1728 ArmOp::F64ConvertI64S {
1729 dd,
1730 rmlo: _,
1731 rmhi: _,
1732 } => {
1733 let result = BV::new_const("f64_convert_i64s_result", 64);
1736 state.set_vfp_reg(dd, result);
1737 }
1738
1739 ArmOp::F64ConvertI64U {
1740 dd,
1741 rmlo: _,
1742 rmhi: _,
1743 } => {
1744 let result = BV::new_const("f64_convert_i64u_result", 64);
1747 state.set_vfp_reg(dd, result);
1748 }
1749
1750 ArmOp::F64PromoteF32 { dd, sm } => {
1751 let result = BV::new_const(format!("f64_promote_f32_{:?}", sm), 64);
1754 state.set_vfp_reg(dd, result);
1755 }
1756
1757 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
1758 let lo = state.get_reg(rmlo).clone();
1761 let hi = state.get_reg(rmhi).clone();
1762
1763 let lo_64 = lo.zero_ext(32); let hi_64 = hi.zero_ext(32);
1766 let shift_32 = BV::from_u64(32, 64);
1767 let hi_shifted = hi_64.bvshl(&shift_32);
1768 let result = hi_shifted.bvor(&lo_64);
1769
1770 state.set_vfp_reg(dd, result);
1771 }
1772
1773 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
1774 let bits = state.get_vfp_reg(dm).clone();
1777
1778 let lo = bits.extract(31, 0);
1780 state.set_reg(rdlo, lo);
1781
1782 let hi = bits.extract(63, 32);
1784 state.set_reg(rdhi, hi);
1785 }
1786
1787 ArmOp::I64TruncF64S {
1788 rdlo: _,
1789 rdhi: _,
1790 dm: _,
1791 } => {
1792 }
1796
1797 ArmOp::I64TruncF64U {
1798 rdlo: _,
1799 rdhi: _,
1800 dm: _,
1801 } => {
1802 }
1806
1807 ArmOp::I32TruncF64S { rd, dm } => {
1808 let result = BV::new_const(format!("i32_trunc_f64s_{:?}", dm), 32);
1811 state.set_reg(rd, result);
1812 }
1813
1814 ArmOp::I32TruncF64U { rd, dm } => {
1815 let result = BV::new_const(format!("i32_trunc_f64u_{:?}", dm), 32);
1818 state.set_reg(rd, result);
1819 }
1820
1821 _ => {
1822 }
1824 }
1825 }
1826
1827 fn evaluate_operand2(&self, op2: &Operand2, state: &ArmState) -> BV {
1829 match op2 {
1830 Operand2::Imm(value) => BV::from_i64(*value as i64, 32),
1831 Operand2::Reg(reg) => state.get_reg(reg).clone(),
1832 Operand2::RegShift { rm, shift, amount } => {
1833 let reg_val = state.get_reg(rm).clone();
1834 let shift_amount = BV::from_i64(*amount as i64, 32);
1835
1836 match shift {
1837 synth_synthesis::ShiftType::LSL => reg_val.bvshl(&shift_amount),
1838 synth_synthesis::ShiftType::LSR => reg_val.bvlshr(&shift_amount),
1839 synth_synthesis::ShiftType::ASR => reg_val.bvashr(&shift_amount),
1840 synth_synthesis::ShiftType::ROR => reg_val.bvrotr(&shift_amount),
1841 }
1842 }
1843 }
1844 }
1845
1846 pub fn extract_result(&self, state: &ArmState, reg: &Reg) -> BV {
1848 state.get_reg(reg).clone()
1849 }
1850
1851 fn encode_clz(&self, input: &BV) -> BV {
1856 let zero = BV::from_i64(0, 32);
1857
1858 let all_zero = input.eq(&zero);
1860 let result_if_zero = BV::from_i64(32, 32);
1861
1862 let mut count = BV::from_i64(0, 32);
1864 let mut remaining = input.clone();
1865
1866 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1868 let top_16 = remaining.bvand(&mask_16);
1869 let top_16_zero = top_16.eq(&zero);
1870
1871 count = top_16_zero.ite(count.bvadd(BV::from_i64(16, 32)), &count);
1872 remaining = top_16_zero.ite(remaining.bvshl(BV::from_i64(16, 32)), &remaining);
1873
1874 let mask_8 = BV::from_u64(0xFF000000, 32);
1876 let top_8 = remaining.bvand(&mask_8);
1877 let top_8_zero = top_8.eq(&zero);
1878
1879 count = top_8_zero.ite(count.bvadd(BV::from_i64(8, 32)), &count);
1880 remaining = top_8_zero.ite(remaining.bvshl(BV::from_i64(8, 32)), &remaining);
1881
1882 let mask_4 = BV::from_u64(0xF0000000, 32);
1884 let top_4 = remaining.bvand(&mask_4);
1885 let top_4_zero = top_4.eq(&zero);
1886
1887 count = top_4_zero.ite(count.bvadd(BV::from_i64(4, 32)), &count);
1888 remaining = top_4_zero.ite(remaining.bvshl(BV::from_i64(4, 32)), &remaining);
1889
1890 let mask_2 = BV::from_u64(0xC0000000, 32);
1892 let top_2 = remaining.bvand(&mask_2);
1893 let top_2_zero = top_2.eq(&zero);
1894
1895 count = top_2_zero.ite(count.bvadd(BV::from_i64(2, 32)), &count);
1896 remaining = top_2_zero.ite(remaining.bvshl(BV::from_i64(2, 32)), &remaining);
1897
1898 let mask_1 = BV::from_u64(0x80000000, 32);
1900 let top_1 = remaining.bvand(&mask_1);
1901 let top_1_zero = top_1.eq(&zero);
1902
1903 count = top_1_zero.ite(count.bvadd(BV::from_i64(1, 32)), &count);
1904
1905 all_zero.ite(&result_if_zero, &count)
1907 }
1908
1909 fn encode_ctz(&self, input: &BV) -> BV {
1915 let reversed = self.encode_rbit(input);
1917 self.encode_clz(&reversed)
1918 }
1919
1920 fn encode_rbit(&self, input: &BV) -> BV {
1925 let mut result = input.clone();
1927
1928 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1930 let top_16 = result.bvand(&mask_16).bvlshr(BV::from_i64(16, 32));
1931 let bottom_16 = result.bvshl(BV::from_i64(16, 32));
1932 result = top_16.bvor(&bottom_16);
1933
1934 let mask_8_top = BV::from_u64(0xFF00FF00, 32);
1936 let mask_8_bottom = BV::from_u64(0x00FF00FF, 32);
1937 let top_8 = result.bvand(&mask_8_top).bvlshr(BV::from_i64(8, 32));
1938 let bottom_8 = result.bvand(&mask_8_bottom).bvshl(BV::from_i64(8, 32));
1939 result = top_8.bvor(&bottom_8);
1940
1941 let mask_4_top = BV::from_u64(0xF0F0F0F0, 32);
1943 let mask_4_bottom = BV::from_u64(0x0F0F0F0F, 32);
1944 let top_4 = result.bvand(&mask_4_top).bvlshr(BV::from_i64(4, 32));
1945 let bottom_4 = result.bvand(&mask_4_bottom).bvshl(BV::from_i64(4, 32));
1946 result = top_4.bvor(&bottom_4);
1947
1948 let mask_2_top = BV::from_u64(0xCCCCCCCC, 32);
1950 let mask_2_bottom = BV::from_u64(0x33333333, 32);
1951 let top_2 = result.bvand(&mask_2_top).bvlshr(BV::from_i64(2, 32));
1952 let bottom_2 = result.bvand(&mask_2_bottom).bvshl(BV::from_i64(2, 32));
1953 result = top_2.bvor(&bottom_2);
1954
1955 let mask_1_top = BV::from_u64(0xAAAAAAAA, 32);
1957 let mask_1_bottom = BV::from_u64(0x55555555, 32);
1958 let top_1 = result.bvand(&mask_1_top).bvlshr(BV::from_i64(1, 32));
1959 let bottom_1 = result.bvand(&mask_1_bottom).bvshl(BV::from_i64(1, 32));
1960 result = top_1.bvor(&bottom_1);
1961
1962 result
1963 }
1964
1965 fn update_flags_sub(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
1977 let zero = BV::from_i64(0, 32);
1978
1979 let sign_bit = result.extract(31, 31);
1981 let one_bit = BV::from_i64(1, 1);
1982 state.flags.n = sign_bit.eq(&one_bit);
1983
1984 state.flags.z = result.eq(&zero);
1986
1987 state.flags.c = a.bvuge(b);
1991
1992 let a_sign = a.extract(31, 31);
1998 let b_sign = b.extract(31, 31);
1999 let r_sign = result.extract(31, 31);
2000
2001 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]);
2004 }
2005
2006 #[allow(dead_code)]
2012 fn update_flags_add(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
2013 let zero = BV::from_i64(0, 32);
2014
2015 let sign_bit = result.extract(31, 31);
2017 let one_bit = BV::from_i64(1, 1);
2018 state.flags.n = sign_bit.eq(&one_bit);
2019
2020 state.flags.z = result.eq(&zero);
2022
2023 state.flags.c = result.bvult(a);
2027
2028 let a_sign = a.extract(31, 31);
2034 let b_sign = b.extract(31, 31);
2035 let r_sign = result.extract(31, 31);
2036
2037 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]);
2040 }
2041
2042 fn evaluate_condition(
2056 &self,
2057 cond: &synth_synthesis::rules::Condition,
2058 flags: &ConditionFlags,
2059 ) -> Bool {
2060 use synth_synthesis::rules::Condition;
2061
2062 match cond {
2063 Condition::EQ => flags.z.clone(),
2064 Condition::NE => flags.z.not(),
2065 Condition::LT => {
2066 flags.n.eq(&flags.v).not()
2068 }
2069 Condition::LE => {
2070 let n_ne_v = flags.n.eq(&flags.v).not();
2072 Bool::or(&[&flags.z, &n_ne_v])
2073 }
2074 Condition::GT => {
2075 let z_zero = flags.z.not();
2077 let n_eq_v = flags.n.eq(&flags.v);
2078 Bool::and(&[&z_zero, &n_eq_v])
2079 }
2080 Condition::GE => {
2081 flags.n.eq(&flags.v)
2083 }
2084 Condition::LO => {
2085 flags.c.not()
2087 }
2088 Condition::LS => {
2089 let c_zero = flags.c.not();
2091 Bool::or(&[&flags.z, &c_zero])
2092 }
2093 Condition::HI => {
2094 let z_zero = flags.z.not();
2096 Bool::and(&[&flags.c, &z_zero])
2097 }
2098 Condition::HS => {
2099 flags.c.clone()
2101 }
2102 }
2103 }
2104
2105 fn bool_to_bv32(&self, cond: &Bool) -> BV {
2107 let zero = BV::from_i64(0, 32);
2108 let one = BV::from_i64(1, 32);
2109 cond.ite(&one, &zero)
2110 }
2111
2112 fn encode_popcnt(&self, input: &BV) -> BV {
2117 let mut x = input.clone();
2118
2119 let mask1 = BV::from_u64(0x55555555, 32);
2121 let masked = x.bvand(&mask1);
2122 let shifted = x.bvlshr(BV::from_i64(1, 32));
2123 let shifted_masked = shifted.bvand(&mask1);
2124 x = masked.bvadd(&shifted_masked);
2125
2126 let mask2 = BV::from_u64(0x33333333, 32);
2128 let masked = x.bvand(&mask2);
2129 let shifted = x.bvlshr(BV::from_i64(2, 32));
2130 let shifted_masked = shifted.bvand(&mask2);
2131 x = masked.bvadd(&shifted_masked);
2132
2133 let mask3 = BV::from_u64(0x0F0F0F0F, 32);
2135 let masked = x.bvand(&mask3);
2136 let shifted = x.bvlshr(BV::from_i64(4, 32));
2137 let shifted_masked = shifted.bvand(&mask3);
2138 x = masked.bvadd(&shifted_masked);
2139
2140 let multiplier = BV::from_u64(0x01010101, 32);
2142 x = x.bvmul(&multiplier);
2143 x = x.bvlshr(BV::from_i64(24, 32));
2144
2145 x
2146 }
2147}
2148
2149#[cfg(test)]
2150mod tests {
2151 use super::*;
2152 use crate::with_verification_context;
2153
2154 #[test]
2155 fn test_arm_add_semantics() {
2156 with_verification_context(|| {
2157 let encoder = ArmSemantics::new();
2158 let mut state = ArmState::new_symbolic();
2159
2160 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2162 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2163
2164 let op = ArmOp::Add {
2166 rd: Reg::R0,
2167 rn: Reg::R1,
2168 op2: Operand2::Reg(Reg::R2),
2169 };
2170
2171 encoder.encode_op(&op, &mut state);
2172
2173 let result = state.get_reg(&Reg::R0).simplify();
2175 assert_eq!(result.as_i64(), Some(30));
2176 });
2177 }
2178
2179 #[test]
2180 fn test_arm_sub_semantics() {
2181 with_verification_context(|| {
2182 let encoder = ArmSemantics::new();
2183 let mut state = ArmState::new_symbolic();
2184
2185 state.set_reg(&Reg::R1, BV::from_i64(50, 32));
2186 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2187
2188 let op = ArmOp::Sub {
2189 rd: Reg::R0,
2190 rn: Reg::R1,
2191 op2: Operand2::Reg(Reg::R2),
2192 };
2193
2194 encoder.encode_op(&op, &mut state);
2195
2196 let result = state.get_reg(&Reg::R0);
2197 assert_eq!(result.simplify().as_i64(), Some(30));
2198 });
2199 }
2200
2201 #[test]
2202 fn test_arm_mov_immediate() {
2203 with_verification_context(|| {
2204 let encoder = ArmSemantics::new();
2205 let mut state = ArmState::new_symbolic();
2206
2207 let op = ArmOp::Mov {
2208 rd: Reg::R0,
2209 op2: Operand2::Imm(42),
2210 };
2211
2212 encoder.encode_op(&op, &mut state);
2213
2214 let result = state.get_reg(&Reg::R0);
2215 assert_eq!(result.simplify().as_i64(), Some(42));
2216 });
2217 }
2218
2219 #[test]
2220 fn test_arm_bitwise_ops() {
2221 with_verification_context(|| {
2222 let encoder = ArmSemantics::new();
2223 let mut state = ArmState::new_symbolic();
2224
2225 state.set_reg(&Reg::R1, BV::from_i64(0b1010, 32));
2226 state.set_reg(&Reg::R2, BV::from_i64(0b1100, 32));
2227
2228 let and_op = ArmOp::And {
2230 rd: Reg::R0,
2231 rn: Reg::R1,
2232 op2: Operand2::Reg(Reg::R2),
2233 };
2234 encoder.encode_op(&and_op, &mut state);
2235 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1000));
2236
2237 let orr_op = ArmOp::Orr {
2239 rd: Reg::R0,
2240 rn: Reg::R1,
2241 op2: Operand2::Reg(Reg::R2),
2242 };
2243 encoder.encode_op(&orr_op, &mut state);
2244 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1110));
2245
2246 let eor_op = ArmOp::Eor {
2248 rd: Reg::R0,
2249 rn: Reg::R1,
2250 op2: Operand2::Reg(Reg::R2),
2251 };
2252 encoder.encode_op(&eor_op, &mut state);
2253 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b0110));
2254 });
2255 }
2256
2257 #[test]
2258 fn test_arm_mls() {
2259 with_verification_context(|| {
2262 let encoder = ArmSemantics::new();
2263 let mut state = ArmState::new_symbolic();
2264
2265 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 {
2272 rd: Reg::R3,
2273 rn: Reg::R1,
2274 rm: Reg::R2,
2275 ra: Reg::R0,
2276 };
2277 encoder.encode_op(&mls_op, &mut state);
2278 assert_eq!(
2279 state.get_reg(&Reg::R3).simplify().as_i64(),
2280 Some(2),
2281 "MLS: 17 - 3*5 = 2"
2282 );
2283
2284 state.set_reg(&Reg::R0, BV::from_i64(100, 32));
2286 state.set_reg(&Reg::R1, BV::from_i64(7, 32));
2287 state.set_reg(&Reg::R2, BV::from_i64(3, 32));
2288
2289 let mls_op2 = ArmOp::Mls {
2290 rd: Reg::R3,
2291 rn: Reg::R1,
2292 rm: Reg::R2,
2293 ra: Reg::R0,
2294 };
2295 encoder.encode_op(&mls_op2, &mut state);
2296 assert_eq!(
2297 state.get_reg(&Reg::R3).simplify().as_i64(),
2298 Some(79),
2299 "MLS: 100 - 7*3 = 79"
2300 );
2301
2302 state.set_reg(&Reg::R0, BV::from_i64(-17, 32));
2304 state.set_reg(&Reg::R1, BV::from_i64(3, 32));
2305 state.set_reg(&Reg::R2, BV::from_i64(5, 32));
2306
2307 let mls_op3 = ArmOp::Mls {
2308 rd: Reg::R3,
2309 rn: Reg::R1,
2310 rm: Reg::R2,
2311 ra: Reg::R0,
2312 };
2313 encoder.encode_op(&mls_op3, &mut state);
2314 let result = state.get_reg(&Reg::R3).simplify().as_i64();
2316 let signed_result = result.map(|v| (v as i32) as i64);
2317 assert_eq!(signed_result, Some(-32), "MLS: -17 - 3*5 = -32");
2318 });
2319 }
2320
2321 #[test]
2322 fn test_arm_shift_ops() {
2323 with_verification_context(|| {
2324 let encoder = ArmSemantics::new();
2325 let mut state = ArmState::new_symbolic();
2326
2327 state.set_reg(&Reg::R1, BV::from_i64(8, 32));
2328
2329 let lsl_op = ArmOp::Lsl {
2331 rd: Reg::R0,
2332 rn: Reg::R1,
2333 shift: 2,
2334 };
2335 encoder.encode_op(&lsl_op, &mut state);
2336 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(32));
2337
2338 let lsr_op = ArmOp::Lsr {
2340 rd: Reg::R0,
2341 rn: Reg::R1,
2342 shift: 2,
2343 };
2344 encoder.encode_op(&lsr_op, &mut state);
2345 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(2));
2346 });
2347 }
2348
2349 #[test]
2350 fn test_arm_ror_comprehensive() {
2351 with_verification_context(|| {
2352 let encoder = ArmSemantics::new();
2353 let mut state = ArmState::new_symbolic();
2354
2355 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2358 let ror_op = ArmOp::Ror {
2359 rd: Reg::R0,
2360 rn: Reg::R1,
2361 shift: 8,
2362 };
2363 encoder.encode_op(&ror_op, &mut state);
2364 assert_eq!(
2366 state.get_reg(&Reg::R0).simplify().as_i64(),
2367 Some(0x78123456),
2368 "ROR by 8"
2369 );
2370
2371 let ror_op_16 = ArmOp::Ror {
2373 rd: Reg::R0,
2374 rn: Reg::R1,
2375 shift: 16,
2376 };
2377 encoder.encode_op(&ror_op_16, &mut state);
2378 assert_eq!(
2380 state.get_reg(&Reg::R0).simplify().as_i64(),
2381 Some(0x56781234),
2382 "ROR by 16"
2383 );
2384
2385 let ror_op_0 = ArmOp::Ror {
2387 rd: Reg::R0,
2388 rn: Reg::R1,
2389 shift: 0,
2390 };
2391 encoder.encode_op(&ror_op_0, &mut state);
2392 assert_eq!(
2393 state.get_reg(&Reg::R0).simplify().as_i64(),
2394 Some(0x12345678),
2395 "ROR by 0"
2396 );
2397
2398 let ror_op_32 = ArmOp::Ror {
2400 rd: Reg::R0,
2401 rn: Reg::R1,
2402 shift: 32,
2403 };
2404 encoder.encode_op(&ror_op_32, &mut state);
2405 assert_eq!(
2406 state.get_reg(&Reg::R0).simplify().as_i64(),
2407 Some(0x12345678),
2408 "ROR by 32"
2409 );
2410
2411 state.set_reg(&Reg::R1, BV::from_u64(0xABCDEF01, 32));
2413 let ror_op_4 = ArmOp::Ror {
2414 rd: Reg::R0,
2415 rn: Reg::R1,
2416 shift: 4,
2417 };
2418 encoder.encode_op(&ror_op_4, &mut state);
2419 assert_eq!(
2421 state.get_reg(&Reg::R0).simplify().as_i64(),
2422 Some(0x1ABCDEF0),
2423 "ROR by 4"
2424 );
2425
2426 state.set_reg(&Reg::R1, BV::from_u64(0x80000001, 32));
2428 let ror_op_1 = ArmOp::Ror {
2429 rd: Reg::R0,
2430 rn: Reg::R1,
2431 shift: 1,
2432 };
2433 encoder.encode_op(&ror_op_1, &mut state);
2434 let result = state.get_reg(&Reg::R0).simplify().as_i64();
2436 let signed_result = result.map(|v| (v as i32) as i64);
2437 assert_eq!(
2438 signed_result,
2439 Some(0xC0000000_u32 as i32 as i64),
2440 "ROR by 1"
2441 );
2442 });
2443 }
2444
2445 #[test]
2446 fn test_arm_clz_comprehensive() {
2447 with_verification_context(|| {
2448 let encoder = ArmSemantics::new();
2449 let mut state = ArmState::new_symbolic();
2450
2451 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2453 let clz_op = ArmOp::Clz {
2454 rd: Reg::R0,
2455 rm: Reg::R1,
2456 };
2457 encoder.encode_op(&clz_op, &mut state);
2458 assert_eq!(
2459 state.get_reg(&Reg::R0).simplify().as_i64(),
2460 Some(32),
2461 "CLZ(0) should be 32"
2462 );
2463
2464 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2466 encoder.encode_op(&clz_op, &mut state);
2467 assert_eq!(
2468 state.get_reg(&Reg::R0).simplify().as_i64(),
2469 Some(31),
2470 "CLZ(1) should be 31"
2471 );
2472
2473 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2475 encoder.encode_op(&clz_op, &mut state);
2476 assert_eq!(
2477 state.get_reg(&Reg::R0).simplify().as_i64(),
2478 Some(0),
2479 "CLZ(0x80000000) should be 0"
2480 );
2481
2482 state.set_reg(&Reg::R1, BV::from_u64(0x00FF0000, 32));
2484 encoder.encode_op(&clz_op, &mut state);
2485 assert_eq!(
2486 state.get_reg(&Reg::R0).simplify().as_i64(),
2487 Some(8),
2488 "CLZ(0x00FF0000) should be 8"
2489 );
2490
2491 state.set_reg(&Reg::R1, BV::from_u64(0x00001000, 32));
2493 encoder.encode_op(&clz_op, &mut state);
2494 assert_eq!(
2495 state.get_reg(&Reg::R0).simplify().as_i64(),
2496 Some(19),
2497 "CLZ(0x00001000) should be 19"
2498 );
2499
2500 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2502 encoder.encode_op(&clz_op, &mut state);
2503 assert_eq!(
2504 state.get_reg(&Reg::R0).simplify().as_i64(),
2505 Some(0),
2506 "CLZ(0xFFFFFFFF) should be 0"
2507 );
2508 });
2509 }
2510
2511 #[test]
2512 fn test_arm_rbit_comprehensive() {
2513 with_verification_context(|| {
2514 let encoder = ArmSemantics::new();
2515 let mut state = ArmState::new_symbolic();
2516
2517 let rbit_op = ArmOp::Rbit {
2518 rd: Reg::R0,
2519 rm: Reg::R1,
2520 };
2521
2522 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2524 encoder.encode_op(&rbit_op, &mut state);
2525 assert_eq!(
2526 state.get_reg(&Reg::R0).simplify().as_i64(),
2527 Some(0),
2528 "RBIT(0) should be 0"
2529 );
2530
2531 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2533 encoder.encode_op(&rbit_op, &mut state);
2534 assert_eq!(
2535 state.get_reg(&Reg::R0).simplify().as_u64(),
2536 Some(0x80000000),
2537 "RBIT(1) should be 0x80000000"
2538 );
2539
2540 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2542 encoder.encode_op(&rbit_op, &mut state);
2543 assert_eq!(
2544 state.get_reg(&Reg::R0).simplify().as_i64(),
2545 Some(1),
2546 "RBIT(0x80000000) should be 1"
2547 );
2548
2549 state.set_reg(&Reg::R1, BV::from_u64(0xFF000000, 32));
2551 encoder.encode_op(&rbit_op, &mut state);
2552 assert_eq!(
2553 state.get_reg(&Reg::R0).simplify().as_u64(),
2554 Some(0x000000FF),
2555 "RBIT(0xFF000000) should be 0x000000FF"
2556 );
2557
2558 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2560 encoder.encode_op(&rbit_op, &mut state);
2561 assert_eq!(
2563 state.get_reg(&Reg::R0).simplify().as_u64(),
2564 Some(0x1E6A2C48),
2565 "RBIT(0x12345678) should be 0x1E6A2C48"
2566 );
2567
2568 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2570 encoder.encode_op(&rbit_op, &mut state);
2571 assert_eq!(
2572 state.get_reg(&Reg::R0).simplify().as_u64(),
2573 Some(0xFFFFFFFF),
2574 "RBIT(0xFFFFFFFF) should be 0xFFFFFFFF"
2575 );
2576 });
2577 }
2578
2579 #[test]
2580 fn test_arm_cmp_flags() {
2581 with_verification_context(|| {
2584 let encoder = ArmSemantics::new();
2585 let mut state = ArmState::new_symbolic();
2586
2587 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2590 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2591
2592 let cmp_op = ArmOp::Cmp {
2593 rn: Reg::R0,
2594 op2: Operand2::Reg(Reg::R1),
2595 };
2596 encoder.encode_op(&cmp_op, &mut state);
2597
2598 assert_eq!(
2599 state.flags.z.simplify().as_bool(),
2600 Some(true),
2601 "Z flag should be set (equal)"
2602 );
2603 assert_eq!(
2604 state.flags.n.simplify().as_bool(),
2605 Some(false),
2606 "N flag should be clear (non-negative)"
2607 );
2608 assert_eq!(
2609 state.flags.c.simplify().as_bool(),
2610 Some(true),
2611 "C flag should be set (no borrow)"
2612 );
2613 assert_eq!(
2614 state.flags.v.simplify().as_bool(),
2615 Some(false),
2616 "V flag should be clear (no overflow)"
2617 );
2618
2619 state.set_reg(&Reg::R0, BV::from_i64(20, 32));
2622 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2623 encoder.encode_op(&cmp_op, &mut state);
2624
2625 assert_eq!(
2626 state.flags.z.simplify().as_bool(),
2627 Some(false),
2628 "Z flag should be clear (not equal)"
2629 );
2630 assert_eq!(
2631 state.flags.n.simplify().as_bool(),
2632 Some(false),
2633 "N flag should be clear (positive result)"
2634 );
2635 assert_eq!(
2636 state.flags.c.simplify().as_bool(),
2637 Some(true),
2638 "C flag should be set (no borrow)"
2639 );
2640 assert_eq!(
2641 state.flags.v.simplify().as_bool(),
2642 Some(false),
2643 "V flag should be clear (no overflow)"
2644 );
2645
2646 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2650 state.set_reg(&Reg::R1, BV::from_i64(20, 32));
2651 encoder.encode_op(&cmp_op, &mut state);
2652
2653 assert_eq!(
2654 state.flags.z.simplify().as_bool(),
2655 Some(false),
2656 "Z flag should be clear"
2657 );
2658 assert_eq!(
2659 state.flags.n.simplify().as_bool(),
2660 Some(true),
2661 "N flag should be set (negative result)"
2662 );
2663 assert_eq!(
2664 state.flags.c.simplify().as_bool(),
2665 Some(false),
2666 "C flag should be clear (borrow occurred)"
2667 );
2668 assert_eq!(
2669 state.flags.v.simplify().as_bool(),
2670 Some(false),
2671 "V flag should be clear"
2672 );
2673
2674 state.set_reg(&Reg::R0, BV::from_i64(0x7FFFFFFF, 32));
2679 state.set_reg(&Reg::R1, BV::from_i64(-2147483648i64, 32)); encoder.encode_op(&cmp_op, &mut state);
2681
2682 assert_eq!(
2683 state.flags.z.simplify().as_bool(),
2684 Some(false),
2685 "Z flag should be clear"
2686 );
2687 assert_eq!(
2688 state.flags.n.simplify().as_bool(),
2689 Some(true),
2690 "N flag should be set (wrapped result)"
2691 );
2692 assert_eq!(
2693 state.flags.c.simplify().as_bool(),
2694 Some(false),
2695 "C flag should be clear"
2696 );
2697 assert_eq!(
2698 state.flags.v.simplify().as_bool(),
2699 Some(true),
2700 "V flag should be set (overflow)"
2701 );
2702
2703 state.set_reg(&Reg::R0, BV::from_i64(0, 32));
2705 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2706 encoder.encode_op(&cmp_op, &mut state);
2707
2708 assert_eq!(
2709 state.flags.z.simplify().as_bool(),
2710 Some(true),
2711 "Z flag should be set (0 - 0 = 0)"
2712 );
2713 assert_eq!(
2714 state.flags.n.simplify().as_bool(),
2715 Some(false),
2716 "N flag should be clear"
2717 );
2718 assert_eq!(
2719 state.flags.c.simplify().as_bool(),
2720 Some(true),
2721 "C flag should be set"
2722 );
2723 assert_eq!(
2724 state.flags.v.simplify().as_bool(),
2725 Some(false),
2726 "V flag should be clear"
2727 );
2728 });
2729 }
2730
2731 #[test]
2732 fn test_arm_flags_all_combinations() {
2733 with_verification_context(|| {
2736 let encoder = ArmSemantics::new();
2737 let mut state = ArmState::new_symbolic();
2738
2739 let cmp_op = ArmOp::Cmp {
2740 rn: Reg::R0,
2741 op2: Operand2::Reg(Reg::R1),
2742 };
2743
2744 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2755 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2756 encoder.encode_op(&cmp_op, &mut state);
2757
2758 let n = state.flags.n.simplify().as_bool().unwrap();
2759 let z = state.flags.z.simplify().as_bool().unwrap();
2760 let v = state.flags.v.simplify().as_bool().unwrap();
2761
2762 assert!(!z, "Not equal");
2763 assert!(n != v, "5 < 10 signed (N != V)");
2764
2765 state.set_reg(&Reg::R0, BV::from_i64(-5, 32));
2767 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2768 encoder.encode_op(&cmp_op, &mut state);
2769
2770 let n = state.flags.n.simplify().as_bool().unwrap();
2771 let v = state.flags.v.simplify().as_bool().unwrap();
2772 assert!(n != v, "-5 < 10 signed (N != V)");
2773 });
2774 }
2775
2776 #[test]
2777 fn test_arm_setcond_eq() {
2778 with_verification_context(|| {
2779 let encoder = ArmSemantics::new();
2780 let mut state = ArmState::new_symbolic();
2781
2782 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2784 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2785
2786 let cmp_op = ArmOp::Cmp {
2788 rn: Reg::R0,
2789 op2: Operand2::Reg(Reg::R1),
2790 };
2791 encoder.encode_op(&cmp_op, &mut state);
2792
2793 let setcond_op = ArmOp::SetCond {
2795 rd: Reg::R0,
2796 cond: synth_synthesis::Condition::EQ,
2797 };
2798 encoder.encode_op(&setcond_op, &mut state);
2799
2800 assert_eq!(
2801 state.get_reg(&Reg::R0).simplify().as_i64(),
2802 Some(1),
2803 "EQ condition (10 == 10) should return 1"
2804 );
2805
2806 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2808 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2809
2810 encoder.encode_op(&cmp_op, &mut state);
2811
2812 let setcond_ne = ArmOp::SetCond {
2813 rd: Reg::R0,
2814 cond: synth_synthesis::Condition::NE,
2815 };
2816 encoder.encode_op(&setcond_ne, &mut state);
2817
2818 assert_eq!(
2819 state.get_reg(&Reg::R0).simplify().as_i64(),
2820 Some(1),
2821 "NE condition (10 != 5) should return 1"
2822 );
2823 });
2824 }
2825
2826 #[test]
2827 fn test_arm_setcond_signed() {
2828 with_verification_context(|| {
2829 let encoder = ArmSemantics::new();
2830 let mut state = ArmState::new_symbolic();
2831
2832 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2834 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2835
2836 let cmp_op = ArmOp::Cmp {
2837 rn: Reg::R0,
2838 op2: Operand2::Reg(Reg::R1),
2839 };
2840 encoder.encode_op(&cmp_op, &mut state);
2841
2842 let setcond_lt = ArmOp::SetCond {
2843 rd: Reg::R0,
2844 cond: synth_synthesis::Condition::LT,
2845 };
2846 encoder.encode_op(&setcond_lt, &mut state);
2847
2848 assert_eq!(
2849 state.get_reg(&Reg::R0).simplify().as_i64(),
2850 Some(1),
2851 "LT signed (5 < 10) should return 1"
2852 );
2853
2854 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2856 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2857
2858 encoder.encode_op(&cmp_op, &mut state);
2859
2860 let setcond_ge = ArmOp::SetCond {
2861 rd: Reg::R0,
2862 cond: synth_synthesis::Condition::GE,
2863 };
2864 encoder.encode_op(&setcond_ge, &mut state);
2865
2866 assert_eq!(
2867 state.get_reg(&Reg::R0).simplify().as_i64(),
2868 Some(1),
2869 "GE signed (10 >= 5) should return 1"
2870 );
2871
2872 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2874 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2875
2876 encoder.encode_op(&cmp_op, &mut state);
2877
2878 let setcond_gt = ArmOp::SetCond {
2879 rd: Reg::R0,
2880 cond: synth_synthesis::Condition::GT,
2881 };
2882 encoder.encode_op(&setcond_gt, &mut state);
2883
2884 assert_eq!(
2885 state.get_reg(&Reg::R0).simplify().as_i64(),
2886 Some(1),
2887 "GT signed (10 > 5) should return 1"
2888 );
2889
2890 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2892 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2893
2894 encoder.encode_op(&cmp_op, &mut state);
2895
2896 let setcond_le = ArmOp::SetCond {
2897 rd: Reg::R0,
2898 cond: synth_synthesis::Condition::LE,
2899 };
2900 encoder.encode_op(&setcond_le, &mut state);
2901
2902 assert_eq!(
2903 state.get_reg(&Reg::R0).simplify().as_i64(),
2904 Some(1),
2905 "LE signed (5 <= 10) should return 1"
2906 );
2907 });
2908 }
2909
2910 #[test]
2911 fn test_arm_setcond_unsigned() {
2912 with_verification_context(|| {
2913 let encoder = ArmSemantics::new();
2914 let mut state = ArmState::new_symbolic();
2915
2916 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2918 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2919
2920 let cmp_op = ArmOp::Cmp {
2921 rn: Reg::R0,
2922 op2: Operand2::Reg(Reg::R1),
2923 };
2924 encoder.encode_op(&cmp_op, &mut state);
2925
2926 let setcond_lo = ArmOp::SetCond {
2927 rd: Reg::R0,
2928 cond: synth_synthesis::Condition::LO,
2929 };
2930 encoder.encode_op(&setcond_lo, &mut state);
2931
2932 assert_eq!(
2933 state.get_reg(&Reg::R0).simplify().as_i64(),
2934 Some(1),
2935 "LO unsigned (5 < 10) should return 1"
2936 );
2937
2938 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2940 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2941
2942 encoder.encode_op(&cmp_op, &mut state);
2943
2944 let setcond_hs = ArmOp::SetCond {
2945 rd: Reg::R0,
2946 cond: synth_synthesis::Condition::HS,
2947 };
2948 encoder.encode_op(&setcond_hs, &mut state);
2949
2950 assert_eq!(
2951 state.get_reg(&Reg::R0).simplify().as_i64(),
2952 Some(1),
2953 "HS unsigned (10 >= 5) should return 1"
2954 );
2955
2956 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2958 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2959
2960 encoder.encode_op(&cmp_op, &mut state);
2961
2962 let setcond_hi = ArmOp::SetCond {
2963 rd: Reg::R0,
2964 cond: synth_synthesis::Condition::HI,
2965 };
2966 encoder.encode_op(&setcond_hi, &mut state);
2967
2968 assert_eq!(
2969 state.get_reg(&Reg::R0).simplify().as_i64(),
2970 Some(1),
2971 "HI unsigned (10 > 5) should return 1"
2972 );
2973
2974 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2976 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2977
2978 encoder.encode_op(&cmp_op, &mut state);
2979
2980 let setcond_ls = ArmOp::SetCond {
2981 rd: Reg::R0,
2982 cond: synth_synthesis::Condition::LS,
2983 };
2984 encoder.encode_op(&setcond_ls, &mut state);
2985
2986 assert_eq!(
2987 state.get_reg(&Reg::R0).simplify().as_i64(),
2988 Some(1),
2989 "LS unsigned (5 <= 10) should return 1"
2990 );
2991 });
2992 }
2993}