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: _,
487 table_byte_offset: _,
488 } => {
489 let _table_index = state.get_reg(table_index_reg).clone();
491 let result = BV::new_const(format!("call_indirect_{}", type_idx), 32);
492 state.set_reg(rd, result);
493 }
494
495 ArmOp::I64Const { rdlo, rdhi, value } => {
501 let low32 = (*value as u32) as i64;
503 let high32 = *value >> 32;
504 state.set_reg(rdlo, BV::from_i64(low32, 32));
505 state.set_reg(rdhi, BV::from_i64(high32, 32));
506 }
507
508 ArmOp::I64Add {
509 rdlo,
510 rdhi,
511 rnlo,
512 rnhi,
513 rmlo,
514 rmhi,
515 } => {
516 let n_low = state.get_reg(rnlo).clone();
521 let m_low = state.get_reg(rmlo).clone();
522 let n_high = state.get_reg(rnhi).clone();
523 let m_high = state.get_reg(rmhi).clone();
524
525 let result_low = n_low.bvadd(&m_low);
527 state.set_reg(rdlo, result_low.clone());
528
529 let carry = result_low.bvult(&n_low);
532 let carry_bv = carry.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
533
534 let high_sum = n_high.bvadd(&m_high);
536 let result_high = high_sum.bvadd(&carry_bv);
537 state.set_reg(rdhi, result_high);
538 }
539
540 ArmOp::I64Eqz { rd, rnlo, rnhi } => {
541 let zero = BV::from_i64(0, 32);
544 let low_zero = state.get_reg(rnlo).eq(&zero);
545 let high_zero = state.get_reg(rnhi).eq(&zero);
546 let both_zero = Bool::and(&[&low_zero, &high_zero]);
547 let result = self.bool_to_bv32(&both_zero);
548 state.set_reg(rd, result);
549 }
550
551 ArmOp::I32WrapI64 { rd, rnlo } => {
552 let low_val = state.get_reg(rnlo).clone();
554 state.set_reg(rd, low_val);
555 }
556
557 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
558 let value = state.get_reg(rn).clone();
560 state.set_reg(rdlo, value.clone());
561
562 let sign_bit = value.extract(31, 31); let all_ones = BV::from_i64(-1, 32);
565 let zero = BV::from_i64(0, 32);
566 let high_val = sign_bit.eq(BV::from_i64(1, 1)).ite(&all_ones, &zero);
568 state.set_reg(rdhi, high_val);
569 }
570
571 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
572 let value = state.get_reg(rn).clone();
574 state.set_reg(rdlo, value);
575 state.set_reg(rdhi, BV::from_i64(0, 32));
577 }
578
579 ArmOp::I64Sub {
580 rdlo,
581 rdhi,
582 rnlo,
583 rnhi,
584 rmlo,
585 rmhi,
586 } => {
587 let n_low = state.get_reg(rnlo).clone();
592 let m_low = state.get_reg(rmlo).clone();
593 let n_high = state.get_reg(rnhi).clone();
594 let m_high = state.get_reg(rmhi).clone();
595
596 let result_low = n_low.bvsub(&m_low);
598 state.set_reg(rdlo, result_low.clone());
599
600 let borrow = n_low.bvult(&m_low);
602 let borrow_bv = borrow.ite(BV::from_i64(1, 32), BV::from_i64(0, 32));
603
604 let high_diff = n_high.bvsub(&m_high);
606 let result_high = high_diff.bvsub(&borrow_bv);
607 state.set_reg(rdhi, result_high);
608 }
609
610 ArmOp::I64Mul {
611 rd_lo,
612 rd_hi,
613 rn_lo,
614 rn_hi,
615 rm_lo,
616 rm_hi,
617 } => {
618 let a_lo = state.get_reg(rn_lo).clone();
624 let a_hi = state.get_reg(rn_hi).clone();
625 let b_lo = state.get_reg(rm_lo).clone();
626 let b_hi = state.get_reg(rm_hi).clone();
627
628 let lo_lo = a_lo.bvmul(&b_lo);
631 state.set_reg(rd_lo, lo_lo.clone());
632
633 let hi_lo = a_hi.bvmul(&b_lo); let lo_hi = a_lo.bvmul(&b_hi); let hi_sum = hi_lo.bvadd(&lo_hi);
647 state.set_reg(rd_hi, hi_sum);
648
649 }
655
656 ArmOp::I64DivS { rdlo, rdhi, .. } => {
663 state.set_reg(rdlo, BV::new_const("i64_divs_lo", 32));
667 state.set_reg(rdhi, BV::new_const("i64_divs_hi", 32));
668 }
669
670 ArmOp::I64DivU { rdlo, rdhi, .. } => {
671 state.set_reg(rdlo, BV::new_const("i64_divu_lo", 32));
675 state.set_reg(rdhi, BV::new_const("i64_divu_hi", 32));
676 }
677
678 ArmOp::I64RemS { rdlo, rdhi, .. } => {
679 state.set_reg(rdlo, BV::new_const("i64_rems_lo", 32));
683 state.set_reg(rdhi, BV::new_const("i64_rems_hi", 32));
684 }
685
686 ArmOp::I64RemU { rdlo, rdhi, .. } => {
687 state.set_reg(rdlo, BV::new_const("i64_remu_lo", 32));
691 state.set_reg(rdhi, BV::new_const("i64_remu_hi", 32));
692 }
693
694 ArmOp::I64And {
695 rdlo,
696 rdhi,
697 rnlo,
698 rnhi,
699 rmlo,
700 rmhi,
701 } => {
702 let n_low = state.get_reg(rnlo).clone();
703 let m_low = state.get_reg(rmlo).clone();
704 state.set_reg(rdlo, n_low.bvand(&m_low));
705
706 let n_high = state.get_reg(rnhi).clone();
707 let m_high = state.get_reg(rmhi).clone();
708 state.set_reg(rdhi, n_high.bvand(&m_high));
709 }
710
711 ArmOp::I64Or {
712 rdlo,
713 rdhi,
714 rnlo,
715 rnhi,
716 rmlo,
717 rmhi,
718 } => {
719 let n_low = state.get_reg(rnlo).clone();
720 let m_low = state.get_reg(rmlo).clone();
721 state.set_reg(rdlo, n_low.bvor(&m_low));
722
723 let n_high = state.get_reg(rnhi).clone();
724 let m_high = state.get_reg(rmhi).clone();
725 state.set_reg(rdhi, n_high.bvor(&m_high));
726 }
727
728 ArmOp::I64Xor {
729 rdlo,
730 rdhi,
731 rnlo,
732 rnhi,
733 rmlo,
734 rmhi,
735 } => {
736 let n_low = state.get_reg(rnlo).clone();
737 let m_low = state.get_reg(rmlo).clone();
738 state.set_reg(rdlo, n_low.bvxor(&m_low));
739
740 let n_high = state.get_reg(rnhi).clone();
741 let m_high = state.get_reg(rmhi).clone();
742 state.set_reg(rdhi, n_high.bvxor(&m_high));
743 }
744
745 ArmOp::I64Eq {
746 rd,
747 rnlo,
748 rnhi,
749 rmlo,
750 rmhi,
751 } => {
752 let n_low = state.get_reg(rnlo).clone();
753 let m_low = state.get_reg(rmlo).clone();
754 let n_high = state.get_reg(rnhi).clone();
755 let m_high = state.get_reg(rmhi).clone();
756
757 let low_eq = n_low.eq(&m_low);
758 let high_eq = n_high.eq(&m_high);
759 let both_eq = Bool::and(&[&low_eq, &high_eq]);
760 let result = self.bool_to_bv32(&both_eq);
761 state.set_reg(rd, result);
762 }
763
764 ArmOp::I64LtS {
765 rd,
766 rnlo,
767 rnhi,
768 rmlo,
769 rmhi,
770 } => {
771 let n_low = state.get_reg(rnlo).clone();
774 let m_low = state.get_reg(rmlo).clone();
775 let n_high = state.get_reg(rnhi).clone();
776 let m_high = state.get_reg(rmhi).clone();
777
778 let high_lt = n_high.bvslt(&m_high);
780 let high_eq = n_high.eq(&m_high);
781
782 let low_lt = n_low.bvult(&m_low);
784
785 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
787 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
788 let result = self.bool_to_bv32(&result_bool);
789 state.set_reg(rd, result);
790 }
791
792 ArmOp::I64LtU {
793 rd,
794 rnlo,
795 rnhi,
796 rmlo,
797 rmhi,
798 } => {
799 let n_low = state.get_reg(rnlo).clone();
802 let m_low = state.get_reg(rmlo).clone();
803 let n_high = state.get_reg(rnhi).clone();
804 let m_high = state.get_reg(rmhi).clone();
805
806 let high_lt = n_high.bvult(&m_high);
808 let high_eq = n_high.eq(&m_high);
809
810 let low_lt = n_low.bvult(&m_low);
812
813 let eq_and_low = Bool::and(&[&high_eq, &low_lt]);
815 let result_bool = Bool::or(&[&high_lt, &eq_and_low]);
816 let result = self.bool_to_bv32(&result_bool);
817 state.set_reg(rd, result);
818 }
819
820 ArmOp::I64Ne {
821 rd,
822 rnlo,
823 rnhi,
824 rmlo,
825 rmhi,
826 } => {
827 let n_low = state.get_reg(rnlo).clone();
829 let m_low = state.get_reg(rmlo).clone();
830 let n_high = state.get_reg(rnhi).clone();
831 let m_high = state.get_reg(rmhi).clone();
832
833 let low_eq = n_low.eq(&m_low);
834 let high_eq = n_high.eq(&m_high);
835 let both_eq = Bool::and(&[&low_eq, &high_eq]);
836 let not_eq = both_eq.not();
837 let result = self.bool_to_bv32(¬_eq);
838 state.set_reg(rd, result);
839 }
840
841 ArmOp::I64LeS {
842 rd,
843 rnlo,
844 rnhi,
845 rmlo,
846 rmhi,
847 } => {
848 let n_low = state.get_reg(rnlo).clone();
851 let m_low = state.get_reg(rmlo).clone();
852 let n_high = state.get_reg(rnhi).clone();
853 let m_high = state.get_reg(rmhi).clone();
854
855 let high_lt = n_high.bvslt(&m_high);
856 let high_eq = n_high.eq(&m_high);
857 let low_le = n_low.bvule(&m_low); let eq_and_le = Bool::and(&[&high_eq, &low_le]);
860 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
861 let result = self.bool_to_bv32(&result_bool);
862 state.set_reg(rd, result);
863 }
864
865 ArmOp::I64LeU {
866 rd,
867 rnlo,
868 rnhi,
869 rmlo,
870 rmhi,
871 } => {
872 let n_low = state.get_reg(rnlo).clone();
874 let m_low = state.get_reg(rmlo).clone();
875 let n_high = state.get_reg(rnhi).clone();
876 let m_high = state.get_reg(rmhi).clone();
877
878 let high_lt = n_high.bvult(&m_high);
879 let high_eq = n_high.eq(&m_high);
880 let low_le = n_low.bvule(&m_low);
881
882 let eq_and_le = Bool::and(&[&high_eq, &low_le]);
883 let result_bool = Bool::or(&[&high_lt, &eq_and_le]);
884 let result = self.bool_to_bv32(&result_bool);
885 state.set_reg(rd, result);
886 }
887
888 ArmOp::I64GtS {
889 rd,
890 rnlo,
891 rnhi,
892 rmlo,
893 rmhi,
894 } => {
895 let n_low = state.get_reg(rnlo).clone();
898 let m_low = state.get_reg(rmlo).clone();
899 let n_high = state.get_reg(rnhi).clone();
900 let m_high = state.get_reg(rmhi).clone();
901
902 let high_gt = n_high.bvsgt(&m_high);
903 let high_eq = n_high.eq(&m_high);
904 let low_gt = n_low.bvugt(&m_low); let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
907 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
908 let result = self.bool_to_bv32(&result_bool);
909 state.set_reg(rd, result);
910 }
911
912 ArmOp::I64GtU {
913 rd,
914 rnlo,
915 rnhi,
916 rmlo,
917 rmhi,
918 } => {
919 let n_low = state.get_reg(rnlo).clone();
921 let m_low = state.get_reg(rmlo).clone();
922 let n_high = state.get_reg(rnhi).clone();
923 let m_high = state.get_reg(rmhi).clone();
924
925 let high_gt = n_high.bvugt(&m_high);
926 let high_eq = n_high.eq(&m_high);
927 let low_gt = n_low.bvugt(&m_low);
928
929 let eq_and_gt = Bool::and(&[&high_eq, &low_gt]);
930 let result_bool = Bool::or(&[&high_gt, &eq_and_gt]);
931 let result = self.bool_to_bv32(&result_bool);
932 state.set_reg(rd, result);
933 }
934
935 ArmOp::I64GeS {
936 rd,
937 rnlo,
938 rnhi,
939 rmlo,
940 rmhi,
941 } => {
942 let n_low = state.get_reg(rnlo).clone();
945 let m_low = state.get_reg(rmlo).clone();
946 let n_high = state.get_reg(rnhi).clone();
947 let m_high = state.get_reg(rmhi).clone();
948
949 let high_lt = n_high.bvslt(&m_high);
950 let high_eq = n_high.eq(&m_high);
951 let low_lt = n_low.bvult(&m_low);
952
953 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
954 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
955 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
957 state.set_reg(rd, result);
958 }
959
960 ArmOp::I64GeU {
961 rd,
962 rnlo,
963 rnhi,
964 rmlo,
965 rmhi,
966 } => {
967 let n_low = state.get_reg(rnlo).clone();
970 let m_low = state.get_reg(rmlo).clone();
971 let n_high = state.get_reg(rnhi).clone();
972 let m_high = state.get_reg(rmhi).clone();
973
974 let high_lt = n_high.bvult(&m_high);
975 let high_eq = n_high.eq(&m_high);
976 let low_lt = n_low.bvult(&m_low);
977
978 let eq_and_lt = Bool::and(&[&high_eq, &low_lt]);
979 let lt_bool = Bool::or(&[&high_lt, &eq_and_lt]);
980 let result_bool = lt_bool.not(); let result = self.bool_to_bv32(&result_bool);
982 state.set_reg(rd, result);
983 }
984
985 ArmOp::I64Shl {
989 rd_lo,
990 rd_hi,
991 rn_lo,
992 rn_hi,
993 rm_lo,
994 rm_hi: _,
995 } => {
996 let n_lo = state.get_reg(rn_lo).clone();
999 let n_hi = state.get_reg(rn_hi).clone();
1000 let shift_amt = state.get_reg(rm_lo).clone();
1001
1002 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1004
1005 let shift_32 = BV::from_i64(32, 32);
1008 let is_large = shift_mod.bvuge(&shift_32); let result_lo_small = n_lo.bvshl(&shift_mod);
1014 let shift_complement = shift_32.bvsub(&shift_mod);
1015 let bits_to_high = n_lo.bvlshr(&shift_complement);
1016 let result_hi_small = n_hi.bvshl(&shift_mod).bvor(&bits_to_high);
1017
1018 let zero = BV::from_i64(0, 32);
1022 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1023 let result_lo_large = zero.clone();
1024 let result_hi_large = n_lo.bvshl(&shift_minus_32);
1025
1026 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1028 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1029
1030 state.set_reg(rd_lo, result_lo);
1031 state.set_reg(rd_hi, result_hi);
1032 }
1033
1034 ArmOp::I64ShrU {
1035 rd_lo,
1036 rd_hi,
1037 rn_lo,
1038 rn_hi,
1039 rm_lo,
1040 rm_hi: _,
1041 } => {
1042 let n_lo = state.get_reg(rn_lo).clone();
1044 let n_hi = state.get_reg(rn_hi).clone();
1045 let shift_amt = state.get_reg(rm_lo).clone();
1046
1047 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1048 let shift_32 = BV::from_i64(32, 32);
1049 let is_large = shift_mod.bvuge(&shift_32);
1050
1051 let result_hi_small = n_hi.bvlshr(&shift_mod);
1055 let shift_complement = shift_32.bvsub(&shift_mod);
1056 let bits_to_low = n_hi.bvshl(&shift_complement);
1057 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1058
1059 let zero = BV::from_i64(0, 32);
1063 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1064 let result_hi_large = zero.clone();
1065 let result_lo_large = n_hi.bvlshr(&shift_minus_32);
1066
1067 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1068 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1069
1070 state.set_reg(rd_lo, result_lo);
1071 state.set_reg(rd_hi, result_hi);
1072 }
1073
1074 ArmOp::I64ShrS {
1075 rd_lo,
1076 rd_hi,
1077 rn_lo,
1078 rn_hi,
1079 rm_lo,
1080 rm_hi: _,
1081 } => {
1082 let n_lo = state.get_reg(rn_lo).clone();
1084 let n_hi = state.get_reg(rn_hi).clone();
1085 let shift_amt = state.get_reg(rm_lo).clone();
1086
1087 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1088 let shift_32 = BV::from_i64(32, 32);
1089 let is_large = shift_mod.bvuge(&shift_32);
1090
1091 let result_hi_small = n_hi.bvashr(&shift_mod);
1095 let shift_complement = shift_32.bvsub(&shift_mod);
1096 let bits_to_low = n_hi.bvshl(&shift_complement);
1097 let result_lo_small = n_lo.bvlshr(&shift_mod).bvor(&bits_to_low);
1098
1099 let shift_31 = BV::from_i64(31, 32);
1103 let result_hi_large = n_hi.bvashr(&shift_31);
1104 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1105 let result_lo_large = n_hi.bvashr(&shift_minus_32);
1106
1107 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1108 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1109
1110 state.set_reg(rd_lo, result_lo);
1111 state.set_reg(rd_hi, result_hi);
1112 }
1113
1114 ArmOp::I64Rotl {
1118 rdlo,
1119 rdhi,
1120 rnlo,
1121 rnhi,
1122 shift,
1123 } => {
1124 let n_lo = state.get_reg(rnlo).clone();
1127 let n_hi = state.get_reg(rnhi).clone();
1128 let shift_amt = state.get_reg(shift).clone();
1129
1130 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1132 let shift_32 = BV::from_i64(32, 32);
1133 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1139
1140 let lo_shifted_left = n_lo.bvshl(&shift_mod);
1141 let hi_bits_to_lo = n_hi.bvlshr(&shift_complement);
1142 let result_lo_small = lo_shifted_left.bvor(&hi_bits_to_lo);
1143
1144 let hi_shifted_left = n_hi.bvshl(&shift_mod);
1145 let lo_bits_to_hi = n_lo.bvlshr(&shift_complement);
1146 let result_hi_small = hi_shifted_left.bvor(&lo_bits_to_hi);
1147
1148 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1151 let complement_large = shift_32.bvsub(&shift_minus_32);
1152
1153 let hi_shifted_left_large = n_hi.bvshl(&shift_minus_32);
1154 let lo_bits_to_hi_large = n_lo.bvlshr(&complement_large);
1155 let result_lo_large = hi_shifted_left_large.bvor(&lo_bits_to_hi_large);
1156
1157 let lo_shifted_left_large = n_lo.bvshl(&shift_minus_32);
1158 let hi_bits_to_lo_large = n_hi.bvlshr(&complement_large);
1159 let result_hi_large = lo_shifted_left_large.bvor(&hi_bits_to_lo_large);
1160
1161 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1163 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1164
1165 state.set_reg(rdlo, result_lo);
1166 state.set_reg(rdhi, result_hi);
1167 }
1168
1169 ArmOp::I64Rotr {
1170 rdlo,
1171 rdhi,
1172 rnlo,
1173 rnhi,
1174 shift,
1175 } => {
1176 let n_lo = state.get_reg(rnlo).clone();
1179 let n_hi = state.get_reg(rnhi).clone();
1180 let shift_amt = state.get_reg(shift).clone();
1181
1182 let shift_mod = shift_amt.bvand(BV::from_i64(63, 32));
1184 let shift_32 = BV::from_i64(32, 32);
1185 let is_large = shift_mod.bvuge(&shift_32); let shift_complement = shift_32.bvsub(&shift_mod);
1191
1192 let lo_shifted_right = n_lo.bvlshr(&shift_mod);
1193 let hi_bits_to_lo = n_hi.bvshl(&shift_complement);
1194 let result_lo_small = lo_shifted_right.bvor(&hi_bits_to_lo);
1195
1196 let hi_shifted_right = n_hi.bvlshr(&shift_mod);
1197 let lo_bits_to_hi = n_lo.bvshl(&shift_complement);
1198 let result_hi_small = hi_shifted_right.bvor(&lo_bits_to_hi);
1199
1200 let shift_minus_32 = shift_mod.bvsub(&shift_32);
1203 let complement_large = shift_32.bvsub(&shift_minus_32);
1204
1205 let hi_shifted_right_large = n_hi.bvlshr(&shift_minus_32);
1206 let lo_bits_to_hi_large = n_lo.bvshl(&complement_large);
1207 let result_lo_large = hi_shifted_right_large.bvor(&lo_bits_to_hi_large);
1208
1209 let lo_shifted_right_large = n_lo.bvlshr(&shift_minus_32);
1210 let hi_bits_to_lo_large = n_hi.bvshl(&complement_large);
1211 let result_hi_large = lo_shifted_right_large.bvor(&hi_bits_to_lo_large);
1212
1213 let result_lo = is_large.ite(&result_lo_large, &result_lo_small);
1215 let result_hi = is_large.ite(&result_hi_large, &result_hi_small);
1216
1217 state.set_reg(rdlo, result_lo);
1218 state.set_reg(rdhi, result_hi);
1219 }
1220
1221 ArmOp::I64Clz { rd, rnlo, rnhi } => {
1222 let n_lo = state.get_reg(rnlo).clone();
1226 let n_hi = state.get_reg(rnhi).clone();
1227
1228 let hi_clz = self.encode_clz(&n_hi);
1229 let lo_clz = self.encode_clz(&n_lo);
1230
1231 let thirty_two = BV::from_i64(32, 32);
1233 let hi_is_zero = hi_clz.eq(&thirty_two);
1234 let result = hi_is_zero.ite(
1235 thirty_two.bvadd(&lo_clz), &hi_clz, );
1238 state.set_reg(rd, result);
1239 }
1240
1241 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
1242 let n_lo = state.get_reg(rnlo).clone();
1246 let n_hi = state.get_reg(rnhi).clone();
1247
1248 let lo_ctz = self.encode_ctz(&n_lo);
1249 let hi_ctz = self.encode_ctz(&n_hi);
1250
1251 let thirty_two = BV::from_i64(32, 32);
1253 let lo_is_zero = lo_ctz.eq(&thirty_two);
1254 let result = lo_is_zero.ite(
1255 thirty_two.bvadd(&hi_ctz), &lo_ctz, );
1258 state.set_reg(rd, result);
1259 }
1260
1261 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
1262 let n_lo = state.get_reg(rnlo).clone();
1265 let n_hi = state.get_reg(rnhi).clone();
1266
1267 let lo_popcnt = self.encode_popcnt(&n_lo);
1268 let hi_popcnt = self.encode_popcnt(&n_hi);
1269
1270 let result = lo_popcnt.bvadd(&hi_popcnt);
1271 state.set_reg(rd, result);
1272 }
1273
1274 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
1278 let result_lo = BV::new_const(format!("i64load_lo_{:?}", addr), 32);
1282 let result_hi = BV::new_const(format!("i64load_hi_{:?}", addr), 32);
1283 state.set_reg(rdlo, result_lo);
1284 state.set_reg(rdhi, result_hi);
1285 }
1286
1287 ArmOp::I64Str {
1288 rdlo: _,
1289 rdhi: _,
1290 addr: _,
1291 } => {
1292 }
1297
1298 ArmOp::F32Const { sd, value } => {
1307 let bits = value.to_bits() as i64;
1310 let bv_val = BV::from_i64(bits, 32);
1311 state.set_vfp_reg(sd, bv_val);
1312 }
1313
1314 ArmOp::F32Add { sd, sn, sm } => {
1316 let result = BV::new_const(format!("f32_add_{:?}_{:?}", sn, sm), 32);
1320 state.set_vfp_reg(sd, result);
1321 }
1322
1323 ArmOp::F32Sub { sd, sn, sm } => {
1324 let result = BV::new_const(format!("f32_sub_{:?}_{:?}", sn, sm), 32);
1326 state.set_vfp_reg(sd, result);
1327 }
1328
1329 ArmOp::F32Mul { sd, sn, sm } => {
1330 let result = BV::new_const(format!("f32_mul_{:?}_{:?}", sn, sm), 32);
1332 state.set_vfp_reg(sd, result);
1333 }
1334
1335 ArmOp::F32Div { sd, sn, sm } => {
1336 let result = BV::new_const(format!("f32_div_{:?}_{:?}", sn, sm), 32);
1338 state.set_vfp_reg(sd, result);
1339 }
1340
1341 ArmOp::F32Abs { sd, sm } => {
1343 let val = state.get_vfp_reg(sm).clone();
1346 let mask = BV::from_u64(0x7FFFFFFF, 32); let result = val.bvand(&mask);
1348 state.set_vfp_reg(sd, result);
1349 }
1350
1351 ArmOp::F32Neg { sd, sm } => {
1352 let val = state.get_vfp_reg(sm).clone();
1355 let mask = BV::from_u64(0x80000000, 32); let result = val.bvxor(&mask);
1357 state.set_vfp_reg(sd, result);
1358 }
1359
1360 ArmOp::F32Sqrt { sd, sm } => {
1361 let result = BV::new_const(format!("f32_sqrt_{:?}", sm), 32);
1364 state.set_vfp_reg(sd, result);
1365 }
1366
1367 ArmOp::F32Min { sd, sn, sm } => {
1368 let result = BV::new_const(format!("f32_min_{:?}_{:?}", sn, sm), 32);
1372 state.set_vfp_reg(sd, result);
1373 }
1374
1375 ArmOp::F32Max { sd, sn, sm } => {
1376 let result = BV::new_const(format!("f32_max_{:?}_{:?}", sn, sm), 32);
1380 state.set_vfp_reg(sd, result);
1381 }
1382
1383 ArmOp::F32Copysign { sd, sn, sm } => {
1384 let val_n = state.get_vfp_reg(sn).clone();
1387 let val_m = state.get_vfp_reg(sm).clone();
1388
1389 let mag_mask = BV::from_u64(0x7FFFFFFF, 32);
1391 let magnitude = val_n.bvand(&mag_mask);
1392
1393 let sign_mask = BV::from_u64(0x80000000, 32);
1395 let sign = val_m.bvand(&sign_mask);
1396
1397 let result = magnitude.bvor(&sign);
1399 state.set_vfp_reg(sd, result);
1400 }
1401
1402 ArmOp::F32Load { sd, addr } => {
1403 let result = BV::new_const(format!("f32_load_{:?}", addr), 32);
1406 state.set_vfp_reg(sd, result);
1407 }
1408
1409 ArmOp::F32Eq { rd, sn, sm } => {
1411 let result = BV::new_const(format!("f32_eq_{:?}_{:?}", sn, sm), 32);
1414 state.set_reg(rd, result);
1415 }
1416
1417 ArmOp::F32Ne { rd, sn, sm } => {
1418 let result = BV::new_const(format!("f32_ne_{:?}_{:?}", sn, sm), 32);
1420 state.set_reg(rd, result);
1421 }
1422
1423 ArmOp::F32Lt { rd, sn, sm } => {
1424 let result = BV::new_const(format!("f32_lt_{:?}_{:?}", sn, sm), 32);
1426 state.set_reg(rd, result);
1427 }
1428
1429 ArmOp::F32Le { rd, sn, sm } => {
1430 let result = BV::new_const(format!("f32_le_{:?}_{:?}", sn, sm), 32);
1432 state.set_reg(rd, result);
1433 }
1434
1435 ArmOp::F32Gt { rd, sn, sm } => {
1436 let result = BV::new_const(format!("f32_gt_{:?}_{:?}", sn, sm), 32);
1438 state.set_reg(rd, result);
1439 }
1440
1441 ArmOp::F32Ge { rd, sn, sm } => {
1442 let result = BV::new_const(format!("f32_ge_{:?}_{:?}", sn, sm), 32);
1444 state.set_reg(rd, result);
1445 }
1446
1447 ArmOp::F32Store { sd, addr } => {
1448 let _val = state.get_vfp_reg(sd);
1453 let _addr_str = format!("{:?}", addr);
1454 }
1456
1457 ArmOp::F32Ceil { sd, sm } => {
1459 let result = BV::new_const(format!("f32_ceil_{:?}", sm), 32);
1462 state.set_vfp_reg(sd, result);
1463 }
1464
1465 ArmOp::F32Floor { sd, sm } => {
1466 let result = BV::new_const(format!("f32_floor_{:?}", sm), 32);
1469 state.set_vfp_reg(sd, result);
1470 }
1471
1472 ArmOp::F32Trunc { sd, sm } => {
1473 let result = BV::new_const(format!("f32_trunc_{:?}", sm), 32);
1476 state.set_vfp_reg(sd, result);
1477 }
1478
1479 ArmOp::F32Nearest { sd, sm } => {
1480 let result = BV::new_const(format!("f32_nearest_{:?}", sm), 32);
1483 state.set_vfp_reg(sd, result);
1484 }
1485
1486 ArmOp::F32ConvertI32S { sd, rm } => {
1488 let int_val = state.get_reg(rm);
1490 let result = BV::new_const(format!("f32_convert_i32s_{:?}", int_val), 32);
1491 state.set_vfp_reg(sd, result);
1492 }
1493
1494 ArmOp::F32ConvertI32U { sd, rm } => {
1495 let int_val = state.get_reg(rm);
1497 let result = BV::new_const(format!("f32_convert_i32u_{:?}", int_val), 32);
1498 state.set_vfp_reg(sd, result);
1499 }
1500
1501 ArmOp::F32ConvertI64S { sd, rmlo, rmhi } => {
1502 let lo = state.get_reg(rmlo);
1504 let hi = state.get_reg(rmhi);
1505 let result = BV::new_const(format!("f32_convert_i64s_{:?}_{:?}", lo, hi), 32);
1506 state.set_vfp_reg(sd, result);
1507 }
1508
1509 ArmOp::F32ConvertI64U { sd, rmlo, rmhi } => {
1510 let lo = state.get_reg(rmlo);
1512 let hi = state.get_reg(rmhi);
1513 let result = BV::new_const(format!("f32_convert_i64u_{:?}_{:?}", lo, hi), 32);
1514 state.set_vfp_reg(sd, result);
1515 }
1516
1517 ArmOp::F32ReinterpretI32 { sd, rm } => {
1519 let bits = state.get_reg(rm).clone();
1522 state.set_vfp_reg(sd, bits);
1523 }
1524
1525 ArmOp::I32ReinterpretF32 { rd, sm } => {
1526 let bits = state.get_vfp_reg(sm).clone();
1529 state.set_reg(rd, bits);
1530 }
1531
1532 ArmOp::F64Add { dd, dn, dm } => {
1538 let result = BV::new_const(format!("f64_add_{:?}_{:?}", dn, dm), 64);
1542 state.set_vfp_reg(dd, result);
1543 }
1544
1545 ArmOp::F64Sub { dd, dn, dm } => {
1546 let result = BV::new_const(format!("f64_sub_{:?}_{:?}", dn, dm), 64);
1548 state.set_vfp_reg(dd, result);
1549 }
1550
1551 ArmOp::F64Mul { dd, dn, dm } => {
1552 let result = BV::new_const(format!("f64_mul_{:?}_{:?}", dn, dm), 64);
1554 state.set_vfp_reg(dd, result);
1555 }
1556
1557 ArmOp::F64Div { dd, dn, dm } => {
1558 let result = BV::new_const(format!("f64_div_{:?}_{:?}", dn, dm), 64);
1560 state.set_vfp_reg(dd, result);
1561 }
1562
1563 ArmOp::F64Abs { dd, dm } => {
1565 let val = state.get_vfp_reg(dm).clone();
1568 let mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64); let result = val.bvand(&mask);
1570 state.set_vfp_reg(dd, result);
1571 }
1572
1573 ArmOp::F64Neg { dd, dm } => {
1574 let val = state.get_vfp_reg(dm).clone();
1577 let mask = BV::from_u64(0x8000000000000000, 64); let result = val.bvxor(&mask);
1579 state.set_vfp_reg(dd, result);
1580 }
1581
1582 ArmOp::F64Sqrt { dd, dm } => {
1583 let result = BV::new_const(format!("f64_sqrt_{:?}", dm), 64);
1586 state.set_vfp_reg(dd, result);
1587 }
1588
1589 ArmOp::F64Min { dd, dn, dm } => {
1590 let result = BV::new_const(format!("f64_min_{:?}_{:?}", dn, dm), 64);
1594 state.set_vfp_reg(dd, result);
1595 }
1596
1597 ArmOp::F64Max { dd, dn, dm } => {
1598 let result = BV::new_const(format!("f64_max_{:?}_{:?}", dn, dm), 64);
1602 state.set_vfp_reg(dd, result);
1603 }
1604
1605 ArmOp::F64Copysign { dd, dn, dm } => {
1606 let val_n = state.get_vfp_reg(dn).clone();
1609 let val_m = state.get_vfp_reg(dm).clone();
1610
1611 let mag_mask = BV::from_u64(0x7FFFFFFFFFFFFFFF, 64);
1613 let magnitude = val_n.bvand(&mag_mask);
1614
1615 let sign_mask = BV::from_u64(0x8000000000000000, 64);
1617 let sign = val_m.bvand(&sign_mask);
1618
1619 let result = magnitude.bvor(&sign);
1621 state.set_vfp_reg(dd, result);
1622 }
1623
1624 ArmOp::F64Ceil { dd, dm } => {
1626 let result = BV::new_const(format!("f64_ceil_{:?}", dm), 64);
1628 state.set_vfp_reg(dd, result);
1629 }
1630
1631 ArmOp::F64Floor { dd, dm } => {
1632 let result = BV::new_const(format!("f64_floor_{:?}", dm), 64);
1634 state.set_vfp_reg(dd, result);
1635 }
1636
1637 ArmOp::F64Trunc { dd, dm } => {
1638 let result = BV::new_const(format!("f64_trunc_{:?}", dm), 64);
1640 state.set_vfp_reg(dd, result);
1641 }
1642
1643 ArmOp::F64Nearest { dd, dm } => {
1644 let result = BV::new_const(format!("f64_nearest_{:?}", dm), 64);
1646 state.set_vfp_reg(dd, result);
1647 }
1648
1649 ArmOp::F64Load { dd, addr } => {
1651 let result = BV::new_const(format!("f64_load_{:?}", addr), 64);
1654 state.set_vfp_reg(dd, result);
1655 }
1656
1657 ArmOp::F64Store { dd: _, addr: _ } => {
1658 }
1662
1663 ArmOp::F64Const { dd, value } => {
1664 let bits = value.to_bits() as i64;
1666 let result = BV::from_i64(bits, 64);
1667 state.set_vfp_reg(dd, result);
1668 }
1669
1670 ArmOp::F64Eq { rd, dn, dm } => {
1672 let result = BV::new_const(format!("f64_eq_{:?}_{:?}", dn, dm), 32);
1675 state.set_reg(rd, result);
1676 }
1677
1678 ArmOp::F64Ne { rd, dn, dm } => {
1679 let result = BV::new_const(format!("f64_ne_{:?}_{:?}", dn, dm), 32);
1681 state.set_reg(rd, result);
1682 }
1683
1684 ArmOp::F64Lt { rd, dn, dm } => {
1685 let result = BV::new_const(format!("f64_lt_{:?}_{:?}", dn, dm), 32);
1687 state.set_reg(rd, result);
1688 }
1689
1690 ArmOp::F64Le { rd, dn, dm } => {
1691 let result = BV::new_const(format!("f64_le_{:?}_{:?}", dn, dm), 32);
1693 state.set_reg(rd, result);
1694 }
1695
1696 ArmOp::F64Gt { rd, dn, dm } => {
1697 let result = BV::new_const(format!("f64_gt_{:?}_{:?}", dn, dm), 32);
1699 state.set_reg(rd, result);
1700 }
1701
1702 ArmOp::F64Ge { rd, dn, dm } => {
1703 let result = BV::new_const(format!("f64_ge_{:?}_{:?}", dn, dm), 32);
1705 state.set_reg(rd, result);
1706 }
1707
1708 ArmOp::F64ConvertI32S { dd, rm } => {
1710 let result = BV::new_const(format!("f64_convert_i32s_{:?}", rm), 64);
1713 state.set_vfp_reg(dd, result);
1714 }
1715
1716 ArmOp::F64ConvertI32U { dd, rm } => {
1717 let result = BV::new_const(format!("f64_convert_i32u_{:?}", rm), 64);
1720 state.set_vfp_reg(dd, result);
1721 }
1722
1723 ArmOp::F64ConvertI64S {
1724 dd,
1725 rmlo: _,
1726 rmhi: _,
1727 } => {
1728 let result = BV::new_const("f64_convert_i64s_result", 64);
1731 state.set_vfp_reg(dd, result);
1732 }
1733
1734 ArmOp::F64ConvertI64U {
1735 dd,
1736 rmlo: _,
1737 rmhi: _,
1738 } => {
1739 let result = BV::new_const("f64_convert_i64u_result", 64);
1742 state.set_vfp_reg(dd, result);
1743 }
1744
1745 ArmOp::F64PromoteF32 { dd, sm } => {
1746 let result = BV::new_const(format!("f64_promote_f32_{:?}", sm), 64);
1749 state.set_vfp_reg(dd, result);
1750 }
1751
1752 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
1753 let lo = state.get_reg(rmlo).clone();
1756 let hi = state.get_reg(rmhi).clone();
1757
1758 let lo_64 = lo.zero_ext(32); let hi_64 = hi.zero_ext(32);
1761 let shift_32 = BV::from_u64(32, 64);
1762 let hi_shifted = hi_64.bvshl(&shift_32);
1763 let result = hi_shifted.bvor(&lo_64);
1764
1765 state.set_vfp_reg(dd, result);
1766 }
1767
1768 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
1769 let bits = state.get_vfp_reg(dm).clone();
1772
1773 let lo = bits.extract(31, 0);
1775 state.set_reg(rdlo, lo);
1776
1777 let hi = bits.extract(63, 32);
1779 state.set_reg(rdhi, hi);
1780 }
1781
1782 ArmOp::I64TruncF64S {
1783 rdlo: _,
1784 rdhi: _,
1785 dm: _,
1786 } => {
1787 }
1791
1792 ArmOp::I64TruncF64U {
1793 rdlo: _,
1794 rdhi: _,
1795 dm: _,
1796 } => {
1797 }
1801
1802 ArmOp::I32TruncF64S { rd, dm } => {
1803 let result = BV::new_const(format!("i32_trunc_f64s_{:?}", dm), 32);
1806 state.set_reg(rd, result);
1807 }
1808
1809 ArmOp::I32TruncF64U { rd, dm } => {
1810 let result = BV::new_const(format!("i32_trunc_f64u_{:?}", dm), 32);
1813 state.set_reg(rd, result);
1814 }
1815
1816 _ => {
1817 }
1819 }
1820 }
1821
1822 fn evaluate_operand2(&self, op2: &Operand2, state: &ArmState) -> BV {
1824 match op2 {
1825 Operand2::Imm(value) => BV::from_i64(*value as i64, 32),
1826 Operand2::Reg(reg) => state.get_reg(reg).clone(),
1827 Operand2::RegShift { rm, shift, amount } => {
1828 let reg_val = state.get_reg(rm).clone();
1829 let shift_amount = BV::from_i64(*amount as i64, 32);
1830
1831 match shift {
1832 synth_synthesis::ShiftType::LSL => reg_val.bvshl(&shift_amount),
1833 synth_synthesis::ShiftType::LSR => reg_val.bvlshr(&shift_amount),
1834 synth_synthesis::ShiftType::ASR => reg_val.bvashr(&shift_amount),
1835 synth_synthesis::ShiftType::ROR => reg_val.bvrotr(&shift_amount),
1836 }
1837 }
1838 }
1839 }
1840
1841 pub fn extract_result(&self, state: &ArmState, reg: &Reg) -> BV {
1843 state.get_reg(reg).clone()
1844 }
1845
1846 fn encode_clz(&self, input: &BV) -> BV {
1851 let zero = BV::from_i64(0, 32);
1852
1853 let all_zero = input.eq(&zero);
1855 let result_if_zero = BV::from_i64(32, 32);
1856
1857 let mut count = BV::from_i64(0, 32);
1859 let mut remaining = input.clone();
1860
1861 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1863 let top_16 = remaining.bvand(&mask_16);
1864 let top_16_zero = top_16.eq(&zero);
1865
1866 count = top_16_zero.ite(count.bvadd(BV::from_i64(16, 32)), &count);
1867 remaining = top_16_zero.ite(remaining.bvshl(BV::from_i64(16, 32)), &remaining);
1868
1869 let mask_8 = BV::from_u64(0xFF000000, 32);
1871 let top_8 = remaining.bvand(&mask_8);
1872 let top_8_zero = top_8.eq(&zero);
1873
1874 count = top_8_zero.ite(count.bvadd(BV::from_i64(8, 32)), &count);
1875 remaining = top_8_zero.ite(remaining.bvshl(BV::from_i64(8, 32)), &remaining);
1876
1877 let mask_4 = BV::from_u64(0xF0000000, 32);
1879 let top_4 = remaining.bvand(&mask_4);
1880 let top_4_zero = top_4.eq(&zero);
1881
1882 count = top_4_zero.ite(count.bvadd(BV::from_i64(4, 32)), &count);
1883 remaining = top_4_zero.ite(remaining.bvshl(BV::from_i64(4, 32)), &remaining);
1884
1885 let mask_2 = BV::from_u64(0xC0000000, 32);
1887 let top_2 = remaining.bvand(&mask_2);
1888 let top_2_zero = top_2.eq(&zero);
1889
1890 count = top_2_zero.ite(count.bvadd(BV::from_i64(2, 32)), &count);
1891 remaining = top_2_zero.ite(remaining.bvshl(BV::from_i64(2, 32)), &remaining);
1892
1893 let mask_1 = BV::from_u64(0x80000000, 32);
1895 let top_1 = remaining.bvand(&mask_1);
1896 let top_1_zero = top_1.eq(&zero);
1897
1898 count = top_1_zero.ite(count.bvadd(BV::from_i64(1, 32)), &count);
1899
1900 all_zero.ite(&result_if_zero, &count)
1902 }
1903
1904 fn encode_ctz(&self, input: &BV) -> BV {
1910 let reversed = self.encode_rbit(input);
1912 self.encode_clz(&reversed)
1913 }
1914
1915 fn encode_rbit(&self, input: &BV) -> BV {
1920 let mut result = input.clone();
1922
1923 let mask_16 = BV::from_u64(0xFFFF0000, 32);
1925 let top_16 = result.bvand(&mask_16).bvlshr(BV::from_i64(16, 32));
1926 let bottom_16 = result.bvshl(BV::from_i64(16, 32));
1927 result = top_16.bvor(&bottom_16);
1928
1929 let mask_8_top = BV::from_u64(0xFF00FF00, 32);
1931 let mask_8_bottom = BV::from_u64(0x00FF00FF, 32);
1932 let top_8 = result.bvand(&mask_8_top).bvlshr(BV::from_i64(8, 32));
1933 let bottom_8 = result.bvand(&mask_8_bottom).bvshl(BV::from_i64(8, 32));
1934 result = top_8.bvor(&bottom_8);
1935
1936 let mask_4_top = BV::from_u64(0xF0F0F0F0, 32);
1938 let mask_4_bottom = BV::from_u64(0x0F0F0F0F, 32);
1939 let top_4 = result.bvand(&mask_4_top).bvlshr(BV::from_i64(4, 32));
1940 let bottom_4 = result.bvand(&mask_4_bottom).bvshl(BV::from_i64(4, 32));
1941 result = top_4.bvor(&bottom_4);
1942
1943 let mask_2_top = BV::from_u64(0xCCCCCCCC, 32);
1945 let mask_2_bottom = BV::from_u64(0x33333333, 32);
1946 let top_2 = result.bvand(&mask_2_top).bvlshr(BV::from_i64(2, 32));
1947 let bottom_2 = result.bvand(&mask_2_bottom).bvshl(BV::from_i64(2, 32));
1948 result = top_2.bvor(&bottom_2);
1949
1950 let mask_1_top = BV::from_u64(0xAAAAAAAA, 32);
1952 let mask_1_bottom = BV::from_u64(0x55555555, 32);
1953 let top_1 = result.bvand(&mask_1_top).bvlshr(BV::from_i64(1, 32));
1954 let bottom_1 = result.bvand(&mask_1_bottom).bvshl(BV::from_i64(1, 32));
1955 result = top_1.bvor(&bottom_1);
1956
1957 result
1958 }
1959
1960 fn update_flags_sub(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
1972 let zero = BV::from_i64(0, 32);
1973
1974 let sign_bit = result.extract(31, 31);
1976 let one_bit = BV::from_i64(1, 1);
1977 state.flags.n = sign_bit.eq(&one_bit);
1978
1979 state.flags.z = result.eq(&zero);
1981
1982 state.flags.c = a.bvuge(b);
1986
1987 let a_sign = a.extract(31, 31);
1993 let b_sign = b.extract(31, 31);
1994 let r_sign = result.extract(31, 31);
1995
1996 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]);
1999 }
2000
2001 #[allow(dead_code)]
2007 fn update_flags_add(&self, state: &mut ArmState, a: &BV, b: &BV, result: &BV) {
2008 let zero = BV::from_i64(0, 32);
2009
2010 let sign_bit = result.extract(31, 31);
2012 let one_bit = BV::from_i64(1, 1);
2013 state.flags.n = sign_bit.eq(&one_bit);
2014
2015 state.flags.z = result.eq(&zero);
2017
2018 state.flags.c = result.bvult(a);
2022
2023 let a_sign = a.extract(31, 31);
2029 let b_sign = b.extract(31, 31);
2030 let r_sign = result.extract(31, 31);
2031
2032 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]);
2035 }
2036
2037 fn evaluate_condition(
2051 &self,
2052 cond: &synth_synthesis::rules::Condition,
2053 flags: &ConditionFlags,
2054 ) -> Bool {
2055 use synth_synthesis::rules::Condition;
2056
2057 match cond {
2058 Condition::EQ => flags.z.clone(),
2059 Condition::NE => flags.z.not(),
2060 Condition::LT => {
2061 flags.n.eq(&flags.v).not()
2063 }
2064 Condition::LE => {
2065 let n_ne_v = flags.n.eq(&flags.v).not();
2067 Bool::or(&[&flags.z, &n_ne_v])
2068 }
2069 Condition::GT => {
2070 let z_zero = flags.z.not();
2072 let n_eq_v = flags.n.eq(&flags.v);
2073 Bool::and(&[&z_zero, &n_eq_v])
2074 }
2075 Condition::GE => {
2076 flags.n.eq(&flags.v)
2078 }
2079 Condition::LO => {
2080 flags.c.not()
2082 }
2083 Condition::LS => {
2084 let c_zero = flags.c.not();
2086 Bool::or(&[&flags.z, &c_zero])
2087 }
2088 Condition::HI => {
2089 let z_zero = flags.z.not();
2091 Bool::and(&[&flags.c, &z_zero])
2092 }
2093 Condition::HS => {
2094 flags.c.clone()
2096 }
2097 }
2098 }
2099
2100 fn bool_to_bv32(&self, cond: &Bool) -> BV {
2102 let zero = BV::from_i64(0, 32);
2103 let one = BV::from_i64(1, 32);
2104 cond.ite(&one, &zero)
2105 }
2106
2107 fn encode_popcnt(&self, input: &BV) -> BV {
2112 let mut x = input.clone();
2113
2114 let mask1 = BV::from_u64(0x55555555, 32);
2116 let masked = x.bvand(&mask1);
2117 let shifted = x.bvlshr(BV::from_i64(1, 32));
2118 let shifted_masked = shifted.bvand(&mask1);
2119 x = masked.bvadd(&shifted_masked);
2120
2121 let mask2 = BV::from_u64(0x33333333, 32);
2123 let masked = x.bvand(&mask2);
2124 let shifted = x.bvlshr(BV::from_i64(2, 32));
2125 let shifted_masked = shifted.bvand(&mask2);
2126 x = masked.bvadd(&shifted_masked);
2127
2128 let mask3 = BV::from_u64(0x0F0F0F0F, 32);
2130 let masked = x.bvand(&mask3);
2131 let shifted = x.bvlshr(BV::from_i64(4, 32));
2132 let shifted_masked = shifted.bvand(&mask3);
2133 x = masked.bvadd(&shifted_masked);
2134
2135 let multiplier = BV::from_u64(0x01010101, 32);
2137 x = x.bvmul(&multiplier);
2138 x = x.bvlshr(BV::from_i64(24, 32));
2139
2140 x
2141 }
2142}
2143
2144#[cfg(test)]
2145mod tests {
2146 use super::*;
2147 use crate::with_verification_context;
2148
2149 #[test]
2150 fn test_arm_add_semantics() {
2151 with_verification_context(|| {
2152 let encoder = ArmSemantics::new();
2153 let mut state = ArmState::new_symbolic();
2154
2155 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2157 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2158
2159 let op = ArmOp::Add {
2161 rd: Reg::R0,
2162 rn: Reg::R1,
2163 op2: Operand2::Reg(Reg::R2),
2164 };
2165
2166 encoder.encode_op(&op, &mut state);
2167
2168 let result = state.get_reg(&Reg::R0).simplify();
2170 assert_eq!(result.as_i64(), Some(30));
2171 });
2172 }
2173
2174 #[test]
2175 fn test_arm_sub_semantics() {
2176 with_verification_context(|| {
2177 let encoder = ArmSemantics::new();
2178 let mut state = ArmState::new_symbolic();
2179
2180 state.set_reg(&Reg::R1, BV::from_i64(50, 32));
2181 state.set_reg(&Reg::R2, BV::from_i64(20, 32));
2182
2183 let op = ArmOp::Sub {
2184 rd: Reg::R0,
2185 rn: Reg::R1,
2186 op2: Operand2::Reg(Reg::R2),
2187 };
2188
2189 encoder.encode_op(&op, &mut state);
2190
2191 let result = state.get_reg(&Reg::R0);
2192 assert_eq!(result.simplify().as_i64(), Some(30));
2193 });
2194 }
2195
2196 #[test]
2197 fn test_arm_mov_immediate() {
2198 with_verification_context(|| {
2199 let encoder = ArmSemantics::new();
2200 let mut state = ArmState::new_symbolic();
2201
2202 let op = ArmOp::Mov {
2203 rd: Reg::R0,
2204 op2: Operand2::Imm(42),
2205 };
2206
2207 encoder.encode_op(&op, &mut state);
2208
2209 let result = state.get_reg(&Reg::R0);
2210 assert_eq!(result.simplify().as_i64(), Some(42));
2211 });
2212 }
2213
2214 #[test]
2215 fn test_arm_bitwise_ops() {
2216 with_verification_context(|| {
2217 let encoder = ArmSemantics::new();
2218 let mut state = ArmState::new_symbolic();
2219
2220 state.set_reg(&Reg::R1, BV::from_i64(0b1010, 32));
2221 state.set_reg(&Reg::R2, BV::from_i64(0b1100, 32));
2222
2223 let and_op = ArmOp::And {
2225 rd: Reg::R0,
2226 rn: Reg::R1,
2227 op2: Operand2::Reg(Reg::R2),
2228 };
2229 encoder.encode_op(&and_op, &mut state);
2230 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1000));
2231
2232 let orr_op = ArmOp::Orr {
2234 rd: Reg::R0,
2235 rn: Reg::R1,
2236 op2: Operand2::Reg(Reg::R2),
2237 };
2238 encoder.encode_op(&orr_op, &mut state);
2239 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b1110));
2240
2241 let eor_op = ArmOp::Eor {
2243 rd: Reg::R0,
2244 rn: Reg::R1,
2245 op2: Operand2::Reg(Reg::R2),
2246 };
2247 encoder.encode_op(&eor_op, &mut state);
2248 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(0b0110));
2249 });
2250 }
2251
2252 #[test]
2253 fn test_arm_mls() {
2254 with_verification_context(|| {
2257 let encoder = ArmSemantics::new();
2258 let mut state = ArmState::new_symbolic();
2259
2260 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 {
2267 rd: Reg::R3,
2268 rn: Reg::R1,
2269 rm: Reg::R2,
2270 ra: Reg::R0,
2271 };
2272 encoder.encode_op(&mls_op, &mut state);
2273 assert_eq!(
2274 state.get_reg(&Reg::R3).simplify().as_i64(),
2275 Some(2),
2276 "MLS: 17 - 3*5 = 2"
2277 );
2278
2279 state.set_reg(&Reg::R0, BV::from_i64(100, 32));
2281 state.set_reg(&Reg::R1, BV::from_i64(7, 32));
2282 state.set_reg(&Reg::R2, BV::from_i64(3, 32));
2283
2284 let mls_op2 = ArmOp::Mls {
2285 rd: Reg::R3,
2286 rn: Reg::R1,
2287 rm: Reg::R2,
2288 ra: Reg::R0,
2289 };
2290 encoder.encode_op(&mls_op2, &mut state);
2291 assert_eq!(
2292 state.get_reg(&Reg::R3).simplify().as_i64(),
2293 Some(79),
2294 "MLS: 100 - 7*3 = 79"
2295 );
2296
2297 state.set_reg(&Reg::R0, BV::from_i64(-17, 32));
2299 state.set_reg(&Reg::R1, BV::from_i64(3, 32));
2300 state.set_reg(&Reg::R2, BV::from_i64(5, 32));
2301
2302 let mls_op3 = ArmOp::Mls {
2303 rd: Reg::R3,
2304 rn: Reg::R1,
2305 rm: Reg::R2,
2306 ra: Reg::R0,
2307 };
2308 encoder.encode_op(&mls_op3, &mut state);
2309 let result = state.get_reg(&Reg::R3).simplify().as_i64();
2311 let signed_result = result.map(|v| (v as i32) as i64);
2312 assert_eq!(signed_result, Some(-32), "MLS: -17 - 3*5 = -32");
2313 });
2314 }
2315
2316 #[test]
2317 fn test_arm_shift_ops() {
2318 with_verification_context(|| {
2319 let encoder = ArmSemantics::new();
2320 let mut state = ArmState::new_symbolic();
2321
2322 state.set_reg(&Reg::R1, BV::from_i64(8, 32));
2323
2324 let lsl_op = ArmOp::Lsl {
2326 rd: Reg::R0,
2327 rn: Reg::R1,
2328 shift: 2,
2329 };
2330 encoder.encode_op(&lsl_op, &mut state);
2331 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(32));
2332
2333 let lsr_op = ArmOp::Lsr {
2335 rd: Reg::R0,
2336 rn: Reg::R1,
2337 shift: 2,
2338 };
2339 encoder.encode_op(&lsr_op, &mut state);
2340 assert_eq!(state.get_reg(&Reg::R0).simplify().as_i64(), Some(2));
2341 });
2342 }
2343
2344 #[test]
2345 fn test_arm_ror_comprehensive() {
2346 with_verification_context(|| {
2347 let encoder = ArmSemantics::new();
2348 let mut state = ArmState::new_symbolic();
2349
2350 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2353 let ror_op = ArmOp::Ror {
2354 rd: Reg::R0,
2355 rn: Reg::R1,
2356 shift: 8,
2357 };
2358 encoder.encode_op(&ror_op, &mut state);
2359 assert_eq!(
2361 state.get_reg(&Reg::R0).simplify().as_i64(),
2362 Some(0x78123456),
2363 "ROR by 8"
2364 );
2365
2366 let ror_op_16 = ArmOp::Ror {
2368 rd: Reg::R0,
2369 rn: Reg::R1,
2370 shift: 16,
2371 };
2372 encoder.encode_op(&ror_op_16, &mut state);
2373 assert_eq!(
2375 state.get_reg(&Reg::R0).simplify().as_i64(),
2376 Some(0x56781234),
2377 "ROR by 16"
2378 );
2379
2380 let ror_op_0 = ArmOp::Ror {
2382 rd: Reg::R0,
2383 rn: Reg::R1,
2384 shift: 0,
2385 };
2386 encoder.encode_op(&ror_op_0, &mut state);
2387 assert_eq!(
2388 state.get_reg(&Reg::R0).simplify().as_i64(),
2389 Some(0x12345678),
2390 "ROR by 0"
2391 );
2392
2393 let ror_op_32 = ArmOp::Ror {
2395 rd: Reg::R0,
2396 rn: Reg::R1,
2397 shift: 32,
2398 };
2399 encoder.encode_op(&ror_op_32, &mut state);
2400 assert_eq!(
2401 state.get_reg(&Reg::R0).simplify().as_i64(),
2402 Some(0x12345678),
2403 "ROR by 32"
2404 );
2405
2406 state.set_reg(&Reg::R1, BV::from_u64(0xABCDEF01, 32));
2408 let ror_op_4 = ArmOp::Ror {
2409 rd: Reg::R0,
2410 rn: Reg::R1,
2411 shift: 4,
2412 };
2413 encoder.encode_op(&ror_op_4, &mut state);
2414 assert_eq!(
2416 state.get_reg(&Reg::R0).simplify().as_i64(),
2417 Some(0x1ABCDEF0),
2418 "ROR by 4"
2419 );
2420
2421 state.set_reg(&Reg::R1, BV::from_u64(0x80000001, 32));
2423 let ror_op_1 = ArmOp::Ror {
2424 rd: Reg::R0,
2425 rn: Reg::R1,
2426 shift: 1,
2427 };
2428 encoder.encode_op(&ror_op_1, &mut state);
2429 let result = state.get_reg(&Reg::R0).simplify().as_i64();
2431 let signed_result = result.map(|v| (v as i32) as i64);
2432 assert_eq!(
2433 signed_result,
2434 Some(0xC0000000_u32 as i32 as i64),
2435 "ROR by 1"
2436 );
2437 });
2438 }
2439
2440 #[test]
2441 fn test_arm_clz_comprehensive() {
2442 with_verification_context(|| {
2443 let encoder = ArmSemantics::new();
2444 let mut state = ArmState::new_symbolic();
2445
2446 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2448 let clz_op = ArmOp::Clz {
2449 rd: Reg::R0,
2450 rm: Reg::R1,
2451 };
2452 encoder.encode_op(&clz_op, &mut state);
2453 assert_eq!(
2454 state.get_reg(&Reg::R0).simplify().as_i64(),
2455 Some(32),
2456 "CLZ(0) should be 32"
2457 );
2458
2459 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2461 encoder.encode_op(&clz_op, &mut state);
2462 assert_eq!(
2463 state.get_reg(&Reg::R0).simplify().as_i64(),
2464 Some(31),
2465 "CLZ(1) should be 31"
2466 );
2467
2468 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2470 encoder.encode_op(&clz_op, &mut state);
2471 assert_eq!(
2472 state.get_reg(&Reg::R0).simplify().as_i64(),
2473 Some(0),
2474 "CLZ(0x80000000) should be 0"
2475 );
2476
2477 state.set_reg(&Reg::R1, BV::from_u64(0x00FF0000, 32));
2479 encoder.encode_op(&clz_op, &mut state);
2480 assert_eq!(
2481 state.get_reg(&Reg::R0).simplify().as_i64(),
2482 Some(8),
2483 "CLZ(0x00FF0000) should be 8"
2484 );
2485
2486 state.set_reg(&Reg::R1, BV::from_u64(0x00001000, 32));
2488 encoder.encode_op(&clz_op, &mut state);
2489 assert_eq!(
2490 state.get_reg(&Reg::R0).simplify().as_i64(),
2491 Some(19),
2492 "CLZ(0x00001000) should be 19"
2493 );
2494
2495 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2497 encoder.encode_op(&clz_op, &mut state);
2498 assert_eq!(
2499 state.get_reg(&Reg::R0).simplify().as_i64(),
2500 Some(0),
2501 "CLZ(0xFFFFFFFF) should be 0"
2502 );
2503 });
2504 }
2505
2506 #[test]
2507 fn test_arm_rbit_comprehensive() {
2508 with_verification_context(|| {
2509 let encoder = ArmSemantics::new();
2510 let mut state = ArmState::new_symbolic();
2511
2512 let rbit_op = ArmOp::Rbit {
2513 rd: Reg::R0,
2514 rm: Reg::R1,
2515 };
2516
2517 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2519 encoder.encode_op(&rbit_op, &mut state);
2520 assert_eq!(
2521 state.get_reg(&Reg::R0).simplify().as_i64(),
2522 Some(0),
2523 "RBIT(0) should be 0"
2524 );
2525
2526 state.set_reg(&Reg::R1, BV::from_i64(1, 32));
2528 encoder.encode_op(&rbit_op, &mut state);
2529 assert_eq!(
2530 state.get_reg(&Reg::R0).simplify().as_u64(),
2531 Some(0x80000000),
2532 "RBIT(1) should be 0x80000000"
2533 );
2534
2535 state.set_reg(&Reg::R1, BV::from_u64(0x80000000, 32));
2537 encoder.encode_op(&rbit_op, &mut state);
2538 assert_eq!(
2539 state.get_reg(&Reg::R0).simplify().as_i64(),
2540 Some(1),
2541 "RBIT(0x80000000) should be 1"
2542 );
2543
2544 state.set_reg(&Reg::R1, BV::from_u64(0xFF000000, 32));
2546 encoder.encode_op(&rbit_op, &mut state);
2547 assert_eq!(
2548 state.get_reg(&Reg::R0).simplify().as_u64(),
2549 Some(0x000000FF),
2550 "RBIT(0xFF000000) should be 0x000000FF"
2551 );
2552
2553 state.set_reg(&Reg::R1, BV::from_u64(0x12345678, 32));
2555 encoder.encode_op(&rbit_op, &mut state);
2556 assert_eq!(
2558 state.get_reg(&Reg::R0).simplify().as_u64(),
2559 Some(0x1E6A2C48),
2560 "RBIT(0x12345678) should be 0x1E6A2C48"
2561 );
2562
2563 state.set_reg(&Reg::R1, BV::from_u64(0xFFFFFFFF, 32));
2565 encoder.encode_op(&rbit_op, &mut state);
2566 assert_eq!(
2567 state.get_reg(&Reg::R0).simplify().as_u64(),
2568 Some(0xFFFFFFFF),
2569 "RBIT(0xFFFFFFFF) should be 0xFFFFFFFF"
2570 );
2571 });
2572 }
2573
2574 #[test]
2575 fn test_arm_cmp_flags() {
2576 with_verification_context(|| {
2579 let encoder = ArmSemantics::new();
2580 let mut state = ArmState::new_symbolic();
2581
2582 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2585 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2586
2587 let cmp_op = ArmOp::Cmp {
2588 rn: Reg::R0,
2589 op2: Operand2::Reg(Reg::R1),
2590 };
2591 encoder.encode_op(&cmp_op, &mut state);
2592
2593 assert_eq!(
2594 state.flags.z.simplify().as_bool(),
2595 Some(true),
2596 "Z flag should be set (equal)"
2597 );
2598 assert_eq!(
2599 state.flags.n.simplify().as_bool(),
2600 Some(false),
2601 "N flag should be clear (non-negative)"
2602 );
2603 assert_eq!(
2604 state.flags.c.simplify().as_bool(),
2605 Some(true),
2606 "C flag should be set (no borrow)"
2607 );
2608 assert_eq!(
2609 state.flags.v.simplify().as_bool(),
2610 Some(false),
2611 "V flag should be clear (no overflow)"
2612 );
2613
2614 state.set_reg(&Reg::R0, BV::from_i64(20, 32));
2617 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2618 encoder.encode_op(&cmp_op, &mut state);
2619
2620 assert_eq!(
2621 state.flags.z.simplify().as_bool(),
2622 Some(false),
2623 "Z flag should be clear (not equal)"
2624 );
2625 assert_eq!(
2626 state.flags.n.simplify().as_bool(),
2627 Some(false),
2628 "N flag should be clear (positive result)"
2629 );
2630 assert_eq!(
2631 state.flags.c.simplify().as_bool(),
2632 Some(true),
2633 "C flag should be set (no borrow)"
2634 );
2635 assert_eq!(
2636 state.flags.v.simplify().as_bool(),
2637 Some(false),
2638 "V flag should be clear (no overflow)"
2639 );
2640
2641 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2645 state.set_reg(&Reg::R1, BV::from_i64(20, 32));
2646 encoder.encode_op(&cmp_op, &mut state);
2647
2648 assert_eq!(
2649 state.flags.z.simplify().as_bool(),
2650 Some(false),
2651 "Z flag should be clear"
2652 );
2653 assert_eq!(
2654 state.flags.n.simplify().as_bool(),
2655 Some(true),
2656 "N flag should be set (negative result)"
2657 );
2658 assert_eq!(
2659 state.flags.c.simplify().as_bool(),
2660 Some(false),
2661 "C flag should be clear (borrow occurred)"
2662 );
2663 assert_eq!(
2664 state.flags.v.simplify().as_bool(),
2665 Some(false),
2666 "V flag should be clear"
2667 );
2668
2669 state.set_reg(&Reg::R0, BV::from_i64(0x7FFFFFFF, 32));
2674 state.set_reg(&Reg::R1, BV::from_i64(-2147483648i64, 32)); encoder.encode_op(&cmp_op, &mut state);
2676
2677 assert_eq!(
2678 state.flags.z.simplify().as_bool(),
2679 Some(false),
2680 "Z flag should be clear"
2681 );
2682 assert_eq!(
2683 state.flags.n.simplify().as_bool(),
2684 Some(true),
2685 "N flag should be set (wrapped result)"
2686 );
2687 assert_eq!(
2688 state.flags.c.simplify().as_bool(),
2689 Some(false),
2690 "C flag should be clear"
2691 );
2692 assert_eq!(
2693 state.flags.v.simplify().as_bool(),
2694 Some(true),
2695 "V flag should be set (overflow)"
2696 );
2697
2698 state.set_reg(&Reg::R0, BV::from_i64(0, 32));
2700 state.set_reg(&Reg::R1, BV::from_i64(0, 32));
2701 encoder.encode_op(&cmp_op, &mut state);
2702
2703 assert_eq!(
2704 state.flags.z.simplify().as_bool(),
2705 Some(true),
2706 "Z flag should be set (0 - 0 = 0)"
2707 );
2708 assert_eq!(
2709 state.flags.n.simplify().as_bool(),
2710 Some(false),
2711 "N flag should be clear"
2712 );
2713 assert_eq!(
2714 state.flags.c.simplify().as_bool(),
2715 Some(true),
2716 "C flag should be set"
2717 );
2718 assert_eq!(
2719 state.flags.v.simplify().as_bool(),
2720 Some(false),
2721 "V flag should be clear"
2722 );
2723 });
2724 }
2725
2726 #[test]
2727 fn test_arm_flags_all_combinations() {
2728 with_verification_context(|| {
2731 let encoder = ArmSemantics::new();
2732 let mut state = ArmState::new_symbolic();
2733
2734 let cmp_op = ArmOp::Cmp {
2735 rn: Reg::R0,
2736 op2: Operand2::Reg(Reg::R1),
2737 };
2738
2739 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2750 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2751 encoder.encode_op(&cmp_op, &mut state);
2752
2753 let n = state.flags.n.simplify().as_bool().unwrap();
2754 let z = state.flags.z.simplify().as_bool().unwrap();
2755 let v = state.flags.v.simplify().as_bool().unwrap();
2756
2757 assert!(!z, "Not equal");
2758 assert!(n != v, "5 < 10 signed (N != V)");
2759
2760 state.set_reg(&Reg::R0, BV::from_i64(-5, 32));
2762 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2763 encoder.encode_op(&cmp_op, &mut state);
2764
2765 let n = state.flags.n.simplify().as_bool().unwrap();
2766 let v = state.flags.v.simplify().as_bool().unwrap();
2767 assert!(n != v, "-5 < 10 signed (N != V)");
2768 });
2769 }
2770
2771 #[test]
2772 fn test_arm_setcond_eq() {
2773 with_verification_context(|| {
2774 let encoder = ArmSemantics::new();
2775 let mut state = ArmState::new_symbolic();
2776
2777 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2779 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2780
2781 let cmp_op = ArmOp::Cmp {
2783 rn: Reg::R0,
2784 op2: Operand2::Reg(Reg::R1),
2785 };
2786 encoder.encode_op(&cmp_op, &mut state);
2787
2788 let setcond_op = ArmOp::SetCond {
2790 rd: Reg::R0,
2791 cond: synth_synthesis::Condition::EQ,
2792 };
2793 encoder.encode_op(&setcond_op, &mut state);
2794
2795 assert_eq!(
2796 state.get_reg(&Reg::R0).simplify().as_i64(),
2797 Some(1),
2798 "EQ condition (10 == 10) should return 1"
2799 );
2800
2801 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2803 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2804
2805 encoder.encode_op(&cmp_op, &mut state);
2806
2807 let setcond_ne = ArmOp::SetCond {
2808 rd: Reg::R0,
2809 cond: synth_synthesis::Condition::NE,
2810 };
2811 encoder.encode_op(&setcond_ne, &mut state);
2812
2813 assert_eq!(
2814 state.get_reg(&Reg::R0).simplify().as_i64(),
2815 Some(1),
2816 "NE condition (10 != 5) should return 1"
2817 );
2818 });
2819 }
2820
2821 #[test]
2822 fn test_arm_setcond_signed() {
2823 with_verification_context(|| {
2824 let encoder = ArmSemantics::new();
2825 let mut state = ArmState::new_symbolic();
2826
2827 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2829 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2830
2831 let cmp_op = ArmOp::Cmp {
2832 rn: Reg::R0,
2833 op2: Operand2::Reg(Reg::R1),
2834 };
2835 encoder.encode_op(&cmp_op, &mut state);
2836
2837 let setcond_lt = ArmOp::SetCond {
2838 rd: Reg::R0,
2839 cond: synth_synthesis::Condition::LT,
2840 };
2841 encoder.encode_op(&setcond_lt, &mut state);
2842
2843 assert_eq!(
2844 state.get_reg(&Reg::R0).simplify().as_i64(),
2845 Some(1),
2846 "LT signed (5 < 10) should return 1"
2847 );
2848
2849 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2851 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2852
2853 encoder.encode_op(&cmp_op, &mut state);
2854
2855 let setcond_ge = ArmOp::SetCond {
2856 rd: Reg::R0,
2857 cond: synth_synthesis::Condition::GE,
2858 };
2859 encoder.encode_op(&setcond_ge, &mut state);
2860
2861 assert_eq!(
2862 state.get_reg(&Reg::R0).simplify().as_i64(),
2863 Some(1),
2864 "GE signed (10 >= 5) should return 1"
2865 );
2866
2867 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2869 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2870
2871 encoder.encode_op(&cmp_op, &mut state);
2872
2873 let setcond_gt = ArmOp::SetCond {
2874 rd: Reg::R0,
2875 cond: synth_synthesis::Condition::GT,
2876 };
2877 encoder.encode_op(&setcond_gt, &mut state);
2878
2879 assert_eq!(
2880 state.get_reg(&Reg::R0).simplify().as_i64(),
2881 Some(1),
2882 "GT signed (10 > 5) should return 1"
2883 );
2884
2885 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2887 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2888
2889 encoder.encode_op(&cmp_op, &mut state);
2890
2891 let setcond_le = ArmOp::SetCond {
2892 rd: Reg::R0,
2893 cond: synth_synthesis::Condition::LE,
2894 };
2895 encoder.encode_op(&setcond_le, &mut state);
2896
2897 assert_eq!(
2898 state.get_reg(&Reg::R0).simplify().as_i64(),
2899 Some(1),
2900 "LE signed (5 <= 10) should return 1"
2901 );
2902 });
2903 }
2904
2905 #[test]
2906 fn test_arm_setcond_unsigned() {
2907 with_verification_context(|| {
2908 let encoder = ArmSemantics::new();
2909 let mut state = ArmState::new_symbolic();
2910
2911 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2913 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2914
2915 let cmp_op = ArmOp::Cmp {
2916 rn: Reg::R0,
2917 op2: Operand2::Reg(Reg::R1),
2918 };
2919 encoder.encode_op(&cmp_op, &mut state);
2920
2921 let setcond_lo = ArmOp::SetCond {
2922 rd: Reg::R0,
2923 cond: synth_synthesis::Condition::LO,
2924 };
2925 encoder.encode_op(&setcond_lo, &mut state);
2926
2927 assert_eq!(
2928 state.get_reg(&Reg::R0).simplify().as_i64(),
2929 Some(1),
2930 "LO unsigned (5 < 10) should return 1"
2931 );
2932
2933 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2935 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2936
2937 encoder.encode_op(&cmp_op, &mut state);
2938
2939 let setcond_hs = ArmOp::SetCond {
2940 rd: Reg::R0,
2941 cond: synth_synthesis::Condition::HS,
2942 };
2943 encoder.encode_op(&setcond_hs, &mut state);
2944
2945 assert_eq!(
2946 state.get_reg(&Reg::R0).simplify().as_i64(),
2947 Some(1),
2948 "HS unsigned (10 >= 5) should return 1"
2949 );
2950
2951 state.set_reg(&Reg::R0, BV::from_i64(10, 32));
2953 state.set_reg(&Reg::R1, BV::from_i64(5, 32));
2954
2955 encoder.encode_op(&cmp_op, &mut state);
2956
2957 let setcond_hi = ArmOp::SetCond {
2958 rd: Reg::R0,
2959 cond: synth_synthesis::Condition::HI,
2960 };
2961 encoder.encode_op(&setcond_hi, &mut state);
2962
2963 assert_eq!(
2964 state.get_reg(&Reg::R0).simplify().as_i64(),
2965 Some(1),
2966 "HI unsigned (10 > 5) should return 1"
2967 );
2968
2969 state.set_reg(&Reg::R0, BV::from_i64(5, 32));
2971 state.set_reg(&Reg::R1, BV::from_i64(10, 32));
2972
2973 encoder.encode_op(&cmp_op, &mut state);
2974
2975 let setcond_ls = ArmOp::SetCond {
2976 rd: Reg::R0,
2977 cond: synth_synthesis::Condition::LS,
2978 };
2979 encoder.encode_op(&setcond_ls, &mut state);
2980
2981 assert_eq!(
2982 state.get_reg(&Reg::R0).simplify().as_i64(),
2983 Some(1),
2984 "LS unsigned (5 <= 10) should return 1"
2985 );
2986 });
2987 }
2988}