1use synth_core::Result;
6use synth_core::target::FPUPrecision;
7use synth_synthesis::contracts::encoding as encoding_contracts;
8use synth_synthesis::{ArmOp, MemAddr, MveSize, Operand2, QReg, Reg, VfpReg};
9
10pub struct ArmEncoder {
12 thumb_mode: bool,
14 #[allow(dead_code)]
16 fpu: Option<FPUPrecision>,
17}
18
19impl ArmEncoder {
20 pub fn new_arm32() -> Self {
22 Self {
23 thumb_mode: false,
24 fpu: None,
25 }
26 }
27
28 pub fn new_thumb2() -> Self {
30 Self {
31 thumb_mode: true,
32 fpu: None,
33 }
34 }
35
36 pub fn new_thumb2_with_fpu(fpu: Option<FPUPrecision>) -> Self {
38 Self {
39 thumb_mode: true,
40 fpu,
41 }
42 }
43
44 pub fn encode(&self, op: &ArmOp) -> Result<Vec<u8>> {
46 if self.thumb_mode {
47 self.encode_thumb(op)
48 } else {
49 self.encode_arm(op)
50 }
51 }
52
53 fn encode_arm_reg_offset_mem(&self, op: &ArmOp) -> Result<Option<Vec<u8>>> {
61 use synth_synthesis::Reg;
62 let addr = match op {
63 ArmOp::Ldr { addr, .. }
64 | ArmOp::Str { addr, .. }
65 | ArmOp::Ldrb { addr, .. }
66 | ArmOp::Strb { addr, .. }
67 | ArmOp::Ldrh { addr, .. }
68 | ArmOp::Strh { addr, .. }
69 | ArmOp::Ldrsb { addr, .. }
70 | ArmOp::Ldrsh { addr, .. } => addr,
71 _ => return Ok(None),
72 };
73 let Some(rm) = addr.offset_reg else {
74 return Ok(None);
75 };
76 let ip = Reg::R12;
77 let add: u32 = 0xE0800000
79 | (reg_to_bits(&addr.base) << 16)
80 | (reg_to_bits(&ip) << 12)
81 | reg_to_bits(&rm);
82 let mut bytes = add.to_le_bytes().to_vec();
83 let imm_addr = MemAddr::imm(ip, addr.offset);
86 let imm_op = match op {
87 ArmOp::Ldr { rd, .. } => ArmOp::Ldr {
88 rd: *rd,
89 addr: imm_addr,
90 },
91 ArmOp::Str { rd, .. } => ArmOp::Str {
92 rd: *rd,
93 addr: imm_addr,
94 },
95 ArmOp::Ldrb { rd, .. } => ArmOp::Ldrb {
96 rd: *rd,
97 addr: imm_addr,
98 },
99 ArmOp::Strb { rd, .. } => ArmOp::Strb {
100 rd: *rd,
101 addr: imm_addr,
102 },
103 ArmOp::Ldrh { rd, .. } => ArmOp::Ldrh {
104 rd: *rd,
105 addr: imm_addr,
106 },
107 ArmOp::Strh { rd, .. } => ArmOp::Strh {
108 rd: *rd,
109 addr: imm_addr,
110 },
111 ArmOp::Ldrsb { rd, .. } => ArmOp::Ldrsb {
112 rd: *rd,
113 addr: imm_addr,
114 },
115 ArmOp::Ldrsh { rd, .. } => ArmOp::Ldrsh {
116 rd: *rd,
117 addr: imm_addr,
118 },
119 _ => unreachable!(),
120 };
121 bytes.extend(self.encode_arm(&imm_op)?);
122 Ok(Some(bytes))
123 }
124
125 fn encode_arm(&self, op: &ArmOp) -> Result<Vec<u8>> {
126 if let Some(bytes) = self.encode_arm_reg_offset_mem(op)? {
133 return Ok(bytes);
134 }
135 let instr: u32 = match op {
136 ArmOp::Add { rd, rn, op2 } => {
138 let rd_bits = reg_to_bits(rd);
139 let rn_bits = reg_to_bits(rn);
140 let (op2_bits, i_flag) = encode_operand2(op2);
141
142 0xE0800000 | (i_flag << 25)
145 | (rn_bits << 16)
146 | (rd_bits << 12)
147 | op2_bits
148 }
149
150 ArmOp::Sub { rd, rn, op2 } => {
151 let rd_bits = reg_to_bits(rd);
152 let rn_bits = reg_to_bits(rn);
153 let (op2_bits, i_flag) = encode_operand2(op2);
154
155 0xE0400000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
157 }
158
159 ArmOp::Adds { rd, rn, op2 } => {
161 let rd_bits = reg_to_bits(rd);
162 let rn_bits = reg_to_bits(rn);
163 let (op2_bits, i_flag) = encode_operand2(op2);
164
165 0xE0900000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
167 }
168
169 ArmOp::Adc { rd, rn, op2 } => {
170 let rd_bits = reg_to_bits(rd);
171 let rn_bits = reg_to_bits(rn);
172 let (op2_bits, i_flag) = encode_operand2(op2);
173
174 0xE0A00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
176 }
177
178 ArmOp::Subs { rd, rn, op2 } => {
179 let rd_bits = reg_to_bits(rd);
180 let rn_bits = reg_to_bits(rn);
181 let (op2_bits, i_flag) = encode_operand2(op2);
182
183 0xE0500000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
185 }
186
187 ArmOp::Sbc { rd, rn, op2 } => {
188 let rd_bits = reg_to_bits(rd);
189 let rn_bits = reg_to_bits(rn);
190 let (op2_bits, i_flag) = encode_operand2(op2);
191
192 0xE0C00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
194 }
195
196 ArmOp::Mul { rd, rn, rm } => {
197 let rd_bits = reg_to_bits(rd);
198 let rn_bits = reg_to_bits(rn);
199 let rm_bits = reg_to_bits(rm);
200
201 0xE0000090 | (rd_bits << 16) | (rn_bits << 8) | rm_bits
203 }
204
205 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
206 let rdlo_bits = reg_to_bits(rdlo);
207 let rdhi_bits = reg_to_bits(rdhi);
208 let rn_bits = reg_to_bits(rn);
209 let rm_bits = reg_to_bits(rm);
210
211 0xE0800090 | (rdhi_bits << 16) | (rdlo_bits << 12) | (rm_bits << 8) | rn_bits
213 }
214
215 ArmOp::Sdiv { rd, rn, rm } => {
216 let rd_bits = reg_to_bits(rd);
217 let rn_bits = reg_to_bits(rn);
218 let rm_bits = reg_to_bits(rm);
219
220 0xE710F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
223 }
224
225 ArmOp::Udiv { rd, rn, rm } => {
226 let rd_bits = reg_to_bits(rd);
227 let rn_bits = reg_to_bits(rn);
228 let rm_bits = reg_to_bits(rm);
229
230 0xE730F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
233 }
234
235 ArmOp::Mls { rd, rn, rm, ra } => {
236 let rd_bits = reg_to_bits(rd);
237 let rn_bits = reg_to_bits(rn);
238 let rm_bits = reg_to_bits(rm);
239 let ra_bits = reg_to_bits(ra);
240
241 0xE0600090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
244 }
245
246 ArmOp::Mla { rd, rn, rm, ra } => {
247 let rd_bits = reg_to_bits(rd);
248 let rn_bits = reg_to_bits(rn);
249 let rm_bits = reg_to_bits(rm);
250 let ra_bits = reg_to_bits(ra);
251
252 0xE0200090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
255 }
256
257 ArmOp::And { rd, rn, op2 } => {
258 let rd_bits = reg_to_bits(rd);
259 let rn_bits = reg_to_bits(rn);
260 let (op2_bits, i_flag) = encode_operand2(op2);
261
262 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
264 }
265
266 ArmOp::Orr { rd, rn, op2 } => {
267 let rd_bits = reg_to_bits(rd);
268 let rn_bits = reg_to_bits(rn);
269 let (op2_bits, i_flag) = encode_operand2(op2);
270
271 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
273 }
274
275 ArmOp::Eor { rd, rn, op2 } => {
276 let rd_bits = reg_to_bits(rd);
277 let rn_bits = reg_to_bits(rn);
278 let (op2_bits, i_flag) = encode_operand2(op2);
279
280 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
282 }
283
284 ArmOp::Lsl { rd, rn, shift } => {
286 let rd_bits = reg_to_bits(rd);
287 let rn_bits = reg_to_bits(rn);
288 let shift_bits = *shift & 0x1F;
289
290 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
292 }
293
294 ArmOp::Lsr { rd, rn, shift } => {
295 let rd_bits = reg_to_bits(rd);
296 let rn_bits = reg_to_bits(rn);
297 let shift_bits = *shift & 0x1F;
298
299 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
301 }
302
303 ArmOp::Asr { rd, rn, shift } => {
304 let rd_bits = reg_to_bits(rd);
305 let rn_bits = reg_to_bits(rn);
306 let shift_bits = *shift & 0x1F;
307
308 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
310 }
311
312 ArmOp::Ror { rd, rn, shift } => {
313 let rd_bits = reg_to_bits(rd);
314 let rn_bits = reg_to_bits(rn);
315 let shift_bits = *shift & 0x1F;
316
317 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
319 }
320
321 ArmOp::LslReg { rd, rn, rm } => {
324 let rd_bits = reg_to_bits(rd);
325 let rn_bits = reg_to_bits(rn);
326 let rm_bits = reg_to_bits(rm);
327 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
328 }
329 ArmOp::LsrReg { rd, rn, rm } => {
330 let rd_bits = reg_to_bits(rd);
331 let rn_bits = reg_to_bits(rn);
332 let rm_bits = reg_to_bits(rm);
333 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
334 }
335 ArmOp::AsrReg { rd, rn, rm } => {
336 let rd_bits = reg_to_bits(rd);
337 let rn_bits = reg_to_bits(rn);
338 let rm_bits = reg_to_bits(rm);
339 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
340 }
341 ArmOp::RorReg { rd, rn, rm } => {
342 let rd_bits = reg_to_bits(rd);
343 let rn_bits = reg_to_bits(rn);
344 let rm_bits = reg_to_bits(rm);
345 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
346 }
347
348 ArmOp::Rsb { rd, rn, imm } => {
350 let rd_bits = reg_to_bits(rd);
351 let rn_bits = reg_to_bits(rn);
352 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
355 }
356
357 ArmOp::Clz { rd, rm } => {
359 let rd_bits = reg_to_bits(rd);
360 let rm_bits = reg_to_bits(rm);
361
362 0xE16F0F10 | (rd_bits << 12) | rm_bits
365 }
366
367 ArmOp::Rbit { rd, rm } => {
368 let rd_bits = reg_to_bits(rd);
369 let rm_bits = reg_to_bits(rm);
370
371 0xE6FF0F30 | (rd_bits << 12) | rm_bits
374 }
375
376 ArmOp::Sxtb { rd, rm } => {
377 let rd_bits = reg_to_bits(rd);
378 let rm_bits = reg_to_bits(rm);
379
380 0xE6AF0070 | (rd_bits << 12) | rm_bits
383 }
384
385 ArmOp::Sxth { rd, rm } => {
386 let rd_bits = reg_to_bits(rd);
387 let rm_bits = reg_to_bits(rm);
388
389 0xE6BF0070 | (rd_bits << 12) | rm_bits
392 }
393
394 ArmOp::Mov { rd, op2 } => {
396 let rd_bits = reg_to_bits(rd);
397 let (op2_bits, i_flag) = encode_operand2(op2);
398
399 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
401 }
402
403 ArmOp::Mvn { rd, op2 } => {
404 let rd_bits = reg_to_bits(rd);
405 let (op2_bits, i_flag) = encode_operand2(op2);
406
407 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
409 }
410
411 ArmOp::Movw { rd, imm16 } => {
414 let rd_bits = reg_to_bits(rd);
415 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
416 let imm12 = (*imm16 as u32) & 0xFFF;
417 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
418 }
419
420 ArmOp::Movt { rd, imm16 } => {
423 let rd_bits = reg_to_bits(rd);
424 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
425 let imm12 = (*imm16 as u32) & 0xFFF;
426 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
427 }
428
429 ArmOp::MovwSym { rd, addend, .. } => {
432 let rd_bits = reg_to_bits(rd);
433 let v = (*addend as u32) & 0xffff;
434 0xE3000000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
435 }
436 ArmOp::MovtSym { rd, addend, .. } => {
437 let rd_bits = reg_to_bits(rd);
438 let v = ((*addend as u32) >> 16) & 0xffff;
439 0xE3400000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
440 }
441
442 ArmOp::LdrSym { .. } => {
446 return Err(synth_core::Error::synthesis(
447 "LdrSym (literal-pool address load) is Thumb-2-only",
448 ));
449 }
450
451 ArmOp::Cmp { rn, op2 } => {
453 let rn_bits = reg_to_bits(rn);
454 let (op2_bits, i_flag) = encode_operand2(op2);
455
456 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
458 }
459
460 ArmOp::Cmn { rn, op2 } => {
462 let rn_bits = reg_to_bits(rn);
463 let (op2_bits, i_flag) = encode_operand2(op2);
464
465 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
467 }
468
469 ArmOp::Ldr { rd, addr } => {
471 let rd_bits = reg_to_bits(rd);
472 let (base_bits, offset_bits) = encode_mem_addr(addr);
473
474 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
477 }
478
479 ArmOp::Str { rd, addr } => {
480 let rd_bits = reg_to_bits(rd);
481 let (base_bits, offset_bits) = encode_mem_addr(addr);
482
483 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
485 }
486
487 ArmOp::Ldrb { rd, addr } => {
489 let rd_bits = reg_to_bits(rd);
490 let (base_bits, offset_bits) = encode_mem_addr(addr);
491 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
493 }
494
495 ArmOp::Ldrsb { rd, addr } => {
496 let rd_bits = reg_to_bits(rd);
497 let (base_bits, offset_bits) = encode_mem_addr(addr);
498 let offset_val = offset_bits & 0xFF;
501 let imm4h = (offset_val >> 4) & 0xF;
502 let imm4l = offset_val & 0xF;
503 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
504 }
505
506 ArmOp::Ldrh { rd, addr } => {
507 let rd_bits = reg_to_bits(rd);
508 let (base_bits, offset_bits) = encode_mem_addr(addr);
509 let offset_val = offset_bits & 0xFF;
511 let imm4h = (offset_val >> 4) & 0xF;
512 let imm4l = offset_val & 0xF;
513 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
514 }
515
516 ArmOp::Ldrsh { rd, addr } => {
517 let rd_bits = reg_to_bits(rd);
518 let (base_bits, offset_bits) = encode_mem_addr(addr);
519 let offset_val = offset_bits & 0xFF;
521 let imm4h = (offset_val >> 4) & 0xF;
522 let imm4l = offset_val & 0xF;
523 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
524 }
525
526 ArmOp::Strb { rd, addr } => {
528 let rd_bits = reg_to_bits(rd);
529 let (base_bits, offset_bits) = encode_mem_addr(addr);
530 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
532 }
533
534 ArmOp::Strh { rd, addr } => {
535 let rd_bits = reg_to_bits(rd);
536 let (base_bits, offset_bits) = encode_mem_addr(addr);
537 let offset_val = offset_bits & 0xFF;
539 let imm4h = (offset_val >> 4) & 0xF;
540 let imm4l = offset_val & 0xF;
541 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
542 }
543
544 ArmOp::MemorySize { rd } => {
546 let rd_bits = reg_to_bits(rd);
547 0xE1A00820 | (rd_bits << 12) | 0x0A }
552
553 ArmOp::MemoryGrow { rd, .. } => {
554 let rd_bits = reg_to_bits(rd);
555 0xE3E00000 | (rd_bits << 12) }
558
559 ArmOp::Label { .. } => {
561 return Ok(Vec::new());
562 }
563
564 ArmOp::B { label: _ } => {
566 0xEA000000
569 }
570
571 ArmOp::Bcc { cond, label: _ } => {
573 use synth_synthesis::Condition;
574 let cond_bits: u32 = match cond {
575 Condition::EQ => 0x0,
576 Condition::NE => 0x1,
577 Condition::HS => 0x2,
578 Condition::LO => 0x3,
579 Condition::HI => 0x8,
580 Condition::LS => 0x9,
581 Condition::GE => 0xA,
582 Condition::LT => 0xB,
583 Condition::GT => 0xC,
584 Condition::LE => 0xD,
585 };
586 (cond_bits << 28) | 0x0A000000
588 }
589
590 ArmOp::Bhs { label: _ } => {
592 0x2A000000 }
595
596 ArmOp::Blo { label: _ } => {
598 0x3A000000 }
601
602 ArmOp::BOffset { offset } => {
606 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
616 0xEA000000 | offset_bits
617 }
618
619 ArmOp::BCondOffset { cond, offset } => {
621 use synth_synthesis::Condition;
622 let cond_bits: u32 = match cond {
623 Condition::EQ => 0x0,
624 Condition::NE => 0x1,
625 Condition::HS => 0x2,
626 Condition::LO => 0x3,
627 Condition::HI => 0x8,
628 Condition::LS => 0x9,
629 Condition::GE => 0xA,
630 Condition::LT => 0xB,
631 Condition::GT => 0xC,
632 Condition::LE => 0xD,
633 };
634 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
638 (cond_bits << 28) | 0x0A000000 | offset_bits
639 }
640
641 ArmOp::Bl { label: _ } => {
642 0xEB000000
644 }
645
646 ArmOp::Bx { rm } => {
647 let rm_bits = reg_to_bits(rm);
648
649 0xE12FFF10 | rm_bits
651 }
652
653 ArmOp::Blx { rm } => {
654 let rm_bits = reg_to_bits(rm);
655
656 0xE12FFF30 | rm_bits
658 }
659
660 ArmOp::Push { regs } => {
661 let mut reg_list: u32 = 0;
663 for r in regs {
664 reg_list |= 1 << reg_to_bits(r);
665 }
666 0xE92D0000 | reg_list
667 }
668
669 ArmOp::Pop { regs } => {
670 let mut reg_list: u32 = 0;
672 for r in regs {
673 reg_list |= 1 << reg_to_bits(r);
674 }
675 0xE8BD0000 | reg_list
676 }
677
678 ArmOp::Nop => {
679 0xE1A00000
681 }
682
683 ArmOp::Udf { imm } => {
684 let imm8 = *imm as u32;
687 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
688 }
689
690 ArmOp::Popcnt { .. } => {
693 0xE1A00000 }
697
698 ArmOp::SetCond { .. } => {
699 0xE1A00000 }
703
704 ArmOp::SelectMove { .. } => {
705 0xE1A00000 }
709
710 ArmOp::Select { .. } => {
711 0xE1A00000 }
715
716 ArmOp::LocalGet { .. } => {
717 0xE1A00000 }
721
722 ArmOp::LocalSet { .. } => {
723 0xE1A00000 }
727
728 ArmOp::LocalTee { .. } => {
729 0xE1A00000 }
733
734 ArmOp::GlobalGet { .. } => {
735 0xE1A00000 }
739
740 ArmOp::GlobalSet { .. } => {
741 0xE1A00000 }
745
746 ArmOp::BrTable { .. } => {
747 0xE1A00000 }
751
752 ArmOp::Call { .. } => {
753 0xE1A00000 }
757
758 ArmOp::CallIndirect { .. } => {
759 0xE1A00000 }
763
764 ArmOp::I64Add { .. } => 0xE1A00000, ArmOp::I64Sub { .. } => 0xE1A00000, ArmOp::I64DivS { .. } => 0xE1A00000, ArmOp::I64DivU { .. } => 0xE1A00000, ArmOp::I64RemS { .. } => 0xE1A00000, ArmOp::I64RemU { .. } => 0xE1A00000, ArmOp::I64Clz { .. } => 0xE1A00000, ArmOp::I64Ctz { .. } => 0xE1A00000, ArmOp::I64Popcnt { .. } => 0xE1A00000, ArmOp::I64And { .. } => 0xE1A00000, ArmOp::I64Or { .. } => 0xE1A00000, ArmOp::I64Xor { .. } => 0xE1A00000, ArmOp::I64Eqz { .. } => 0xE1A00000, ArmOp::I64Eq { .. } => 0xE1A00000, ArmOp::I64Ne { .. } => 0xE1A00000, ArmOp::I64LtS { .. } => 0xE1A00000, ArmOp::I64LtU { .. } => 0xE1A00000, ArmOp::I64LeS { .. } => 0xE1A00000, ArmOp::I64LeU { .. } => 0xE1A00000, ArmOp::I64GtS { .. } => 0xE1A00000, ArmOp::I64GtU { .. } => 0xE1A00000, ArmOp::I64GeS { .. } => 0xE1A00000, ArmOp::I64GeU { .. } => 0xE1A00000, ArmOp::I64Const { .. } => 0xE1A00000, ArmOp::I64Ldr { .. } => 0xE1A00000, ArmOp::I64Str { .. } => 0xE1A00000, ArmOp::I64ExtendI32S { .. } => 0xE1A00000, ArmOp::I64ExtendI32U { .. } => 0xE1A00000, ArmOp::I64Extend8S { .. } => 0xE1A00000, ArmOp::I64Extend16S { .. } => 0xE1A00000, ArmOp::I64Extend32S { .. } => 0xE1A00000, ArmOp::I32WrapI64 { .. } => 0xE1A00000, ArmOp::F32Add { sd, sn, sm } => encode_vfp_3reg(0xEE300A00, sd, sn, sm)?,
801 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
802 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
803 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
804 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
805 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
806 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
807
808 ArmOp::F32Ceil { sd, sm } => {
811 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
813 ArmOp::F32Floor { sd, sm } => {
814 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
816 ArmOp::F32Trunc { sd, sm } => {
817 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
819 ArmOp::F32Nearest { sd, sm } => {
820 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
822 ArmOp::F32Min { sd, sn, sm } => {
823 return self.encode_arm_f32_minmax(sd, sn, sm, true);
824 }
825 ArmOp::F32Max { sd, sn, sm } => {
826 return self.encode_arm_f32_minmax(sd, sn, sm, false);
827 }
828 ArmOp::F32Copysign { sd, sn, sm } => {
829 return self.encode_arm_f32_copysign(sd, sn, sm);
830 }
831
832 ArmOp::F32Eq { rd, sn, sm } => {
834 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
836 ArmOp::F32Ne { rd, sn, sm } => {
837 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
839 ArmOp::F32Lt { rd, sn, sm } => {
840 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
842 ArmOp::F32Le { rd, sn, sm } => {
843 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
845 ArmOp::F32Gt { rd, sn, sm } => {
846 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
848 ArmOp::F32Ge { rd, sn, sm } => {
849 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
851
852 ArmOp::F32Const { sd, value } => {
854 return self.encode_arm_f32_const(sd, *value);
855 }
856
857 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
858 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
859
860 ArmOp::F32ConvertI32S { sd, rm } => {
862 return self.encode_arm_f32_convert_i32(sd, rm, true);
863 }
864 ArmOp::F32ConvertI32U { sd, rm } => {
865 return self.encode_arm_f32_convert_i32(sd, rm, false);
866 }
867 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
868 return Err(synth_core::Error::synthesis(
869 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
870 ));
871 }
872 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
873 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
874 ArmOp::I32TruncF32S { rd, sm } => {
875 return self.encode_arm_i32_trunc_f32(rd, sm, true);
876 }
877 ArmOp::I32TruncF32U { rd, sm } => {
878 return self.encode_arm_i32_trunc_f32(rd, sm, false);
879 }
880
881 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
884 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
885 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
886 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
887 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
888 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
889 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
890
891 ArmOp::F64Ceil { dd, dm } => {
894 return self.encode_arm_f64_rounding(dd, dm, 0b01);
895 }
896 ArmOp::F64Floor { dd, dm } => {
897 return self.encode_arm_f64_rounding(dd, dm, 0b10);
898 }
899 ArmOp::F64Trunc { dd, dm } => {
900 return self.encode_arm_f64_rounding(dd, dm, 0b11);
901 }
902 ArmOp::F64Nearest { dd, dm } => {
903 return self.encode_arm_f64_rounding(dd, dm, 0b00);
904 }
905 ArmOp::F64Min { dd, dn, dm } => {
906 return self.encode_arm_f64_minmax(dd, dn, dm, true);
907 }
908 ArmOp::F64Max { dd, dn, dm } => {
909 return self.encode_arm_f64_minmax(dd, dn, dm, false);
910 }
911 ArmOp::F64Copysign { dd, dn, dm } => {
912 return self.encode_arm_f64_copysign(dd, dn, dm);
913 }
914
915 ArmOp::F64Eq { rd, dn, dm } => {
917 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
918 }
919 ArmOp::F64Ne { rd, dn, dm } => {
920 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
921 }
922 ArmOp::F64Lt { rd, dn, dm } => {
923 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
924 }
925 ArmOp::F64Le { rd, dn, dm } => {
926 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
927 }
928 ArmOp::F64Gt { rd, dn, dm } => {
929 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
930 }
931 ArmOp::F64Ge { rd, dn, dm } => {
932 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
933 }
934
935 ArmOp::F64Const { dd, value } => {
936 return self.encode_arm_f64_const(dd, *value);
937 }
938
939 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
940 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
941
942 ArmOp::F64ConvertI32S { dd, rm } => {
943 return self.encode_arm_f64_convert_i32(dd, rm, true);
944 }
945 ArmOp::F64ConvertI32U { dd, rm } => {
946 return self.encode_arm_f64_convert_i32(dd, rm, false);
947 }
948 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
949 return Err(synth_core::Error::synthesis(
950 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
951 ));
952 }
953 ArmOp::F64PromoteF32 { dd, sm } => {
954 return self.encode_arm_f64_promote_f32(dd, sm);
955 }
956 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
957 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
958 }
959 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
960 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
961 }
962 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
963 return Err(synth_core::Error::synthesis(
964 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
965 ));
966 }
967 ArmOp::I32TruncF64S { rd, dm } => {
968 return self.encode_arm_i32_trunc_f64(rd, dm, true);
969 }
970 ArmOp::I32TruncF64U { rd, dm } => {
971 return self.encode_arm_i32_trunc_f64(rd, dm, false);
972 }
973 ArmOp::I64SetCond { .. }
975 | ArmOp::I64SetCondZ { .. }
976 | ArmOp::I64Mul { .. }
977 | ArmOp::I64Shl { .. }
978 | ArmOp::I64ShrS { .. }
979 | ArmOp::I64ShrU { .. }
980 | ArmOp::I64Rotl { .. }
981 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
985 | ArmOp::MveStore { .. }
986 | ArmOp::MveConst { .. }
987 | ArmOp::MveAnd { .. }
988 | ArmOp::MveOrr { .. }
989 | ArmOp::MveEor { .. }
990 | ArmOp::MveMvn { .. }
991 | ArmOp::MveBic { .. }
992 | ArmOp::MveAddI { .. }
993 | ArmOp::MveSubI { .. }
994 | ArmOp::MveMulI { .. }
995 | ArmOp::MveNegI { .. }
996 | ArmOp::MveCmpEqI { .. }
997 | ArmOp::MveCmpNeI { .. }
998 | ArmOp::MveCmpLtS { .. }
999 | ArmOp::MveCmpLtU { .. }
1000 | ArmOp::MveCmpGtS { .. }
1001 | ArmOp::MveCmpGtU { .. }
1002 | ArmOp::MveCmpLeS { .. }
1003 | ArmOp::MveCmpLeU { .. }
1004 | ArmOp::MveCmpGeS { .. }
1005 | ArmOp::MveCmpGeU { .. }
1006 | ArmOp::MveDup { .. }
1007 | ArmOp::MveExtractLane { .. }
1008 | ArmOp::MveInsertLane { .. }
1009 | ArmOp::MveAddF32 { .. }
1010 | ArmOp::MveSubF32 { .. }
1011 | ArmOp::MveMulF32 { .. }
1012 | ArmOp::MveNegF32 { .. }
1013 | ArmOp::MveAbsF32 { .. }
1014 | ArmOp::MveCmpEqF32 { .. }
1015 | ArmOp::MveCmpNeF32 { .. }
1016 | ArmOp::MveCmpLtF32 { .. }
1017 | ArmOp::MveCmpLeF32 { .. }
1018 | ArmOp::MveCmpGtF32 { .. }
1019 | ArmOp::MveCmpGeF32 { .. }
1020 | ArmOp::MveDupF32 { .. }
1021 | ArmOp::MveExtractLaneF32 { .. }
1022 | ArmOp::MveReplaceLaneF32 { .. }
1023 | ArmOp::MveDivF32 { .. }
1024 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
1026
1027 Ok(instr.to_le_bytes().to_vec())
1029 }
1030
1031 fn encode_arm_f32_compare(
1035 &self,
1036 rd: &Reg,
1037 sn: &VfpReg,
1038 sm: &VfpReg,
1039 cond_code: u32,
1040 ) -> Result<Vec<u8>> {
1041 let mut bytes = Vec::new();
1042
1043 let sn_num = vfp_sreg_to_num(sn)?;
1045 let sm_num = vfp_sreg_to_num(sm)?;
1046 let (vd, d) = encode_sreg(sn_num);
1047 let (vm, m) = encode_sreg(sm_num);
1048 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1049 bytes.extend_from_slice(&vcmp.to_le_bytes());
1050
1051 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1053
1054 let rd_bits = reg_to_bits(rd);
1056 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1057 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1058
1059 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1061 bytes.extend_from_slice(&mov_one.to_le_bytes());
1062
1063 Ok(bytes)
1064 }
1065
1066 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1068 let mut bytes = Vec::new();
1069 let bits = value.to_bits();
1070
1071 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1076 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1077 bytes.extend_from_slice(&movw.to_le_bytes());
1078
1079 let hi16 = (bits >> 16) & 0xFFFF;
1081 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1082 bytes.extend_from_slice(&movt.to_le_bytes());
1083
1084 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1086 bytes.extend_from_slice(&vmov.to_le_bytes());
1087
1088 Ok(bytes)
1089 }
1090
1091 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1093 let mut bytes = Vec::new();
1094
1095 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1097 bytes.extend_from_slice(&vmov.to_le_bytes());
1098
1099 let sd_num = vfp_sreg_to_num(sd)?;
1102 let (vd, d) = encode_sreg(sd_num);
1103 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1105 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1106 bytes.extend_from_slice(&vcvt.to_le_bytes());
1107
1108 Ok(bytes)
1109 }
1110
1111 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1123 let mut bytes = Vec::new();
1124 let sm_num = vfp_sreg_to_num(sm)?;
1125 let sd_num = vfp_sreg_to_num(sd)?;
1126 let (vd_s, d_s) = encode_sreg(sd_num);
1127 let (vm_s, m_s) = encode_sreg(sm_num);
1128
1129 if mode == 0b11 {
1130 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1133 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1134 } else {
1135 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1140 bytes.extend_from_slice(&vmrs.to_le_bytes());
1141
1142 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1145 bytes.extend_from_slice(&bic.to_le_bytes());
1146
1147 if mode != 0 {
1149 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1151 bytes.extend_from_slice(&orr.to_le_bytes());
1152 }
1153
1154 let vmsr = 0xEEE10A10 | (rt << 12);
1156 bytes.extend_from_slice(&vmsr.to_le_bytes());
1157
1158 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1160 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1161
1162 bytes.extend_from_slice(&vmrs.to_le_bytes());
1164 bytes.extend_from_slice(&bic.to_le_bytes());
1165 bytes.extend_from_slice(&vmsr.to_le_bytes());
1166 }
1167
1168 let (vd2, d2) = encode_sreg(sd_num);
1170 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1171 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1172
1173 Ok(bytes)
1174 }
1175
1176 fn encode_arm_f32_minmax(
1178 &self,
1179 sd: &VfpReg,
1180 sn: &VfpReg,
1181 sm: &VfpReg,
1182 is_min: bool,
1183 ) -> Result<Vec<u8>> {
1184 let mut bytes = Vec::new();
1185 let sn_num = vfp_sreg_to_num(sn)?;
1186 let sm_num = vfp_sreg_to_num(sm)?;
1187 let sd_num = vfp_sreg_to_num(sd)?;
1188
1189 let (vd, d) = encode_sreg(sd_num);
1191 let (vn, n) = encode_sreg(sn_num);
1192 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1193 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1194
1195 let (vm, m) = encode_sreg(sm_num);
1197 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1198 bytes.extend_from_slice(&vcmp.to_le_bytes());
1199
1200 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1202
1203 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1206
1207 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1209 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1210
1211 Ok(bytes)
1212 }
1213
1214 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1216 let mut bytes = Vec::new();
1217
1218 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1220 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1221
1222 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1224 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1225
1226 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1230 bytes.extend_from_slice(&and_sign.to_le_bytes());
1231
1232 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1235 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1236
1237 let orr = 0xE1800000u32 | 12;
1240 bytes.extend_from_slice(&orr.to_le_bytes());
1241
1242 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1244 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1245
1246 Ok(bytes)
1247 }
1248
1249 fn encode_arm_f64_compare(
1251 &self,
1252 rd: &Reg,
1253 dn: &VfpReg,
1254 dm: &VfpReg,
1255 cond_code: u32,
1256 ) -> Result<Vec<u8>> {
1257 let mut bytes = Vec::new();
1258
1259 let dn_num = vfp_dreg_to_num(dn)?;
1261 let dm_num = vfp_dreg_to_num(dm)?;
1262 let (vd, d) = encode_dreg(dn_num);
1263 let (vm, m) = encode_dreg(dm_num);
1264 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1265 bytes.extend_from_slice(&vcmp.to_le_bytes());
1266
1267 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1269
1270 let rd_bits = reg_to_bits(rd);
1272 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1273 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1274
1275 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1277 bytes.extend_from_slice(&mov_one.to_le_bytes());
1278
1279 Ok(bytes)
1280 }
1281
1282 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1284 let mut bytes = Vec::new();
1285 let bits = value.to_bits();
1286 let lo32 = bits as u32;
1287 let hi32 = (bits >> 32) as u32;
1288
1289 let lo16 = lo32 & 0xFFFF;
1291 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1292 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1293 let hi16 = (lo32 >> 16) & 0xFFFF;
1294 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1295 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1296
1297 let lo16 = hi32 & 0xFFFF;
1299 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1300 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1301 let hi16 = (hi32 >> 16) & 0xFFFF;
1302 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1303 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1304
1305 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1307 bytes.extend_from_slice(&vmov.to_le_bytes());
1308
1309 Ok(bytes)
1310 }
1311
1312 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1314 let mut bytes = Vec::new();
1315
1316 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1318 bytes.extend_from_slice(&vmov.to_le_bytes());
1319
1320 let dd_num = vfp_dreg_to_num(dd)?;
1323 let (vd, d) = encode_dreg(dd_num);
1324 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1325 let vcvt = base | (d << 22) | (vd << 12);
1327 bytes.extend_from_slice(&vcvt.to_le_bytes());
1328
1329 Ok(bytes)
1330 }
1331
1332 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1334 let dd_num = vfp_dreg_to_num(dd)?;
1335 let sm_num = vfp_sreg_to_num(sm)?;
1336 let (vd, d) = encode_dreg(dd_num);
1337 let (vm, m) = encode_sreg(sm_num);
1338
1339 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1341 Ok(vcvt.to_le_bytes().to_vec())
1342 }
1343
1344 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1346 let mut bytes = Vec::new();
1347 let dm_num = vfp_dreg_to_num(dm)?;
1348 let (vm, m) = encode_dreg(dm_num);
1349
1350 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1353 let vcvt = base | (m << 5) | vm;
1354 bytes.extend_from_slice(&vcvt.to_le_bytes());
1355
1356 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1358 bytes.extend_from_slice(&vmov.to_le_bytes());
1359
1360 Ok(bytes)
1361 }
1362
1363 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1371 let mut bytes = Vec::new();
1372 let dm_num = vfp_dreg_to_num(dm)?;
1373 let dd_num = vfp_dreg_to_num(dd)?;
1374 let (vm, m) = encode_dreg(dm_num);
1375 let (vd, d) = encode_dreg(dd_num);
1376
1377 if mode == 0b11 {
1378 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1380 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1381 } else {
1382 let rt: u32 = 12;
1384
1385 let vmrs = 0xEEF10A10 | (rt << 12);
1387 bytes.extend_from_slice(&vmrs.to_le_bytes());
1388
1389 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1391 bytes.extend_from_slice(&bic.to_le_bytes());
1392
1393 if mode != 0 {
1395 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1396 bytes.extend_from_slice(&orr.to_le_bytes());
1397 }
1398
1399 let vmsr = 0xEEE10A10 | (rt << 12);
1401 bytes.extend_from_slice(&vmsr.to_le_bytes());
1402
1403 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1405 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1406
1407 bytes.extend_from_slice(&vmrs.to_le_bytes());
1409 bytes.extend_from_slice(&bic.to_le_bytes());
1410 bytes.extend_from_slice(&vmsr.to_le_bytes());
1411 }
1412
1413 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1415 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1416
1417 Ok(bytes)
1418 }
1419
1420 fn encode_arm_f64_minmax(
1422 &self,
1423 dd: &VfpReg,
1424 dn: &VfpReg,
1425 dm: &VfpReg,
1426 is_min: bool,
1427 ) -> Result<Vec<u8>> {
1428 let mut bytes = Vec::new();
1429 let dn_num = vfp_dreg_to_num(dn)?;
1430 let dm_num = vfp_dreg_to_num(dm)?;
1431 let dd_num = vfp_dreg_to_num(dd)?;
1432
1433 let (vd, d) = encode_dreg(dd_num);
1435 let (vn, n) = encode_dreg(dn_num);
1436 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1437 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1438
1439 let (vm, m) = encode_dreg(dm_num);
1441 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1442 bytes.extend_from_slice(&vcmp.to_le_bytes());
1443
1444 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1446
1447 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1448 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1449 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1450
1451 Ok(bytes)
1452 }
1453
1454 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1456 let mut bytes = Vec::new();
1457
1458 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1460 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1461
1462 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1465 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1466
1467 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1469 bytes.extend_from_slice(&and_sign.to_le_bytes());
1470
1471 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1473 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1474
1475 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1477 bytes.extend_from_slice(&orr.to_le_bytes());
1478
1479 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1481 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1482
1483 Ok(bytes)
1484 }
1485
1486 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1488 let mut bytes = Vec::new();
1489
1490 let sm_num = vfp_sreg_to_num(sm)?;
1493 let (vd, d) = encode_sreg(sm_num);
1494 let (vm, m) = encode_sreg(sm_num);
1495 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1496 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1497 bytes.extend_from_slice(&vcvt.to_le_bytes());
1498
1499 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1501 bytes.extend_from_slice(&vmov.to_le_bytes());
1502
1503 Ok(bytes)
1504 }
1505
1506 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1508 match op {
1511 ArmOp::Add { rd, rn, op2 } => {
1513 let rd_bits = reg_to_bits(rd) as u16;
1514 let rn_bits = reg_to_bits(rn) as u16;
1515
1516 if let Operand2::Reg(rm) = op2 {
1517 let rm_bits = reg_to_bits(rm) as u16;
1518 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1526 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1528 Ok(instr.to_le_bytes().to_vec())
1529 } else {
1530 self.encode_thumb32_add_reg_raw(
1532 rd_bits as u32,
1533 rn_bits as u32,
1534 rm_bits as u32,
1535 )
1536 }
1537 } else if let Operand2::Imm(imm) = op2 {
1538 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1539 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1541 Ok(instr.to_le_bytes().to_vec())
1542 } else {
1543 self.encode_thumb32_add(rd, rn, *imm as u32)
1545 }
1546 } else {
1547 self.encode_thumb32_add(rd, rn, 0)
1549 }
1550 }
1551
1552 ArmOp::Sub { rd, rn, op2 } => {
1553 let rd_bits = reg_to_bits(rd) as u16;
1554 let rn_bits = reg_to_bits(rn) as u16;
1555
1556 if let Operand2::Reg(rm) = op2 {
1557 let rm_bits = reg_to_bits(rm) as u16;
1558 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1560 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1562 Ok(instr.to_le_bytes().to_vec())
1563 } else {
1564 self.encode_thumb32_sub_reg_raw(
1566 rd_bits as u32,
1567 rn_bits as u32,
1568 rm_bits as u32,
1569 )
1570 }
1571 } else if let Operand2::Imm(imm) = op2 {
1572 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1573 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1575 Ok(instr.to_le_bytes().to_vec())
1576 } else {
1577 self.encode_thumb32_sub(rd, rn, *imm as u32)
1578 }
1579 } else {
1580 self.encode_thumb32_sub(rd, rn, 0)
1581 }
1582 }
1583
1584 ArmOp::Mov { rd, op2 } => {
1585 let rd_bits = reg_to_bits(rd) as u16;
1586
1587 if let Operand2::Imm(imm) = op2 {
1588 if *imm <= 255 && rd_bits < 8 {
1589 let imm_bits = (*imm as u16) & 0xFF;
1591 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1592 Ok(instr.to_le_bytes().to_vec())
1593 } else {
1594 self.encode_thumb32_movw(rd, *imm as u32)
1596 }
1597 } else if let Operand2::Reg(rm) = op2 {
1598 let rm_bits = reg_to_bits(rm) as u16;
1599 let d_bit = (rd_bits >> 3) & 1;
1602 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1603 Ok(instr.to_le_bytes().to_vec())
1604 } else {
1605 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1607 }
1608 }
1609
1610 ArmOp::Push { regs } => {
1611 let mut reg_list: u16 = 0;
1615 let mut need_32bit = false;
1616 for r in regs {
1617 let bit = reg_to_bits(r);
1618 if bit >= 8 && *r != Reg::LR {
1619 need_32bit = true;
1620 }
1621 reg_list |= 1 << bit;
1622 }
1623 if !need_32bit {
1624 let m_bit = if reg_list & (1 << 14) != 0 {
1626 1u16
1627 } else {
1628 0u16
1629 };
1630 let low_regs = reg_list & 0xFF;
1631 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1632 Ok(instr.to_le_bytes().to_vec())
1633 } else {
1634 let hw1: u16 = 0xE92D;
1636 let hw2: u16 = reg_list;
1637 let mut bytes = hw1.to_le_bytes().to_vec();
1638 bytes.extend_from_slice(&hw2.to_le_bytes());
1639 Ok(bytes)
1640 }
1641 }
1642
1643 ArmOp::Pop { regs } => {
1644 let mut reg_list: u16 = 0;
1648 let mut need_32bit = false;
1649 for r in regs {
1650 let bit = reg_to_bits(r);
1651 if bit >= 8 && *r != Reg::PC {
1652 need_32bit = true;
1653 }
1654 reg_list |= 1 << bit;
1655 }
1656 if !need_32bit {
1657 let p_bit = if reg_list & (1 << 15) != 0 {
1659 1u16
1660 } else {
1661 0u16
1662 };
1663 let low_regs = reg_list & 0xFF;
1664 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1665 Ok(instr.to_le_bytes().to_vec())
1666 } else {
1667 let hw1: u16 = 0xE8BD;
1669 let hw2: u16 = reg_list;
1670 let mut bytes = hw1.to_le_bytes().to_vec();
1671 bytes.extend_from_slice(&hw2.to_le_bytes());
1672 Ok(bytes)
1673 }
1674 }
1675
1676 ArmOp::Nop => {
1677 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1679 }
1680
1681 ArmOp::Udf { imm } => {
1682 let instr: u16 = 0xDE00 | (*imm as u16);
1685 let bytes = instr.to_le_bytes().to_vec();
1686 encoding_contracts::verify_thumb16(&bytes);
1687 Ok(bytes)
1688 }
1689
1690 ArmOp::Adds { rd, rn, op2 } => {
1693 let rd_bits = reg_to_bits(rd) as u16;
1694 let rn_bits = reg_to_bits(rn) as u16;
1695
1696 if let Operand2::Reg(rm) = op2 {
1697 let rm_bits = reg_to_bits(rm) as u16;
1698 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1703 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1705 Ok(instr.to_le_bytes().to_vec())
1706 } else {
1707 self.encode_thumb32_adds_reg_raw(
1708 rd_bits as u32,
1709 rn_bits as u32,
1710 rm_bits as u32,
1711 )
1712 }
1713 } else {
1714 self.encode_thumb32_adds(rd, rn, 0)
1716 }
1717 }
1718
1719 ArmOp::Adc { rd, rn, op2 } => {
1722 let rd_bits = reg_to_bits(rd);
1723 let rn_bits = reg_to_bits(rn);
1724
1725 if let Operand2::Reg(rm) = op2 {
1726 let rm_bits = reg_to_bits(rm);
1727 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1729 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1730
1731 let mut bytes = hw1.to_le_bytes().to_vec();
1732 bytes.extend_from_slice(&hw2.to_le_bytes());
1733 Ok(bytes)
1734 } else {
1735 let hw1: u16 = (0xF140 | rn_bits) as u16;
1737 let hw2: u16 = (rd_bits << 8) as u16;
1738 let mut bytes = hw1.to_le_bytes().to_vec();
1739 bytes.extend_from_slice(&hw2.to_le_bytes());
1740 Ok(bytes)
1741 }
1742 }
1743
1744 ArmOp::Subs { rd, rn, op2 } => {
1746 let rd_bits = reg_to_bits(rd) as u16;
1747 let rn_bits = reg_to_bits(rn) as u16;
1748
1749 if let Operand2::Reg(rm) = op2 {
1750 let rm_bits = reg_to_bits(rm) as u16;
1751 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1755 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1757 Ok(instr.to_le_bytes().to_vec())
1758 } else {
1759 self.encode_thumb32_subs_reg_raw(
1760 rd_bits as u32,
1761 rn_bits as u32,
1762 rm_bits as u32,
1763 )
1764 }
1765 } else {
1766 self.encode_thumb32_subs(rd, rn, 0)
1768 }
1769 }
1770
1771 ArmOp::Sbc { rd, rn, op2 } => {
1774 let rd_bits = reg_to_bits(rd);
1775 let rn_bits = reg_to_bits(rn);
1776
1777 if let Operand2::Reg(rm) = op2 {
1778 let rm_bits = reg_to_bits(rm);
1779 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1781 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1782
1783 let mut bytes = hw1.to_le_bytes().to_vec();
1784 bytes.extend_from_slice(&hw2.to_le_bytes());
1785 Ok(bytes)
1786 } else {
1787 let hw1: u16 = (0xF160 | rn_bits) as u16;
1789 let hw2: u16 = (rd_bits << 8) as u16;
1790 let mut bytes = hw1.to_le_bytes().to_vec();
1791 bytes.extend_from_slice(&hw2.to_le_bytes());
1792 Ok(bytes)
1793 }
1794 }
1795
1796 ArmOp::Sdiv { rd, rn, rm } => {
1800 let rd_bits = reg_to_bits(rd);
1801 let rn_bits = reg_to_bits(rn);
1802 let rm_bits = reg_to_bits(rm);
1803 reg_bits_checked(rd_bits)?;
1804 reg_bits_checked(rn_bits)?;
1805 reg_bits_checked(rm_bits)?;
1806
1807 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1811 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1812
1813 let mut bytes = hw1.to_le_bytes().to_vec();
1815 bytes.extend_from_slice(&hw2.to_le_bytes());
1816 encoding_contracts::verify_thumb32(&bytes);
1817 Ok(bytes)
1818 }
1819
1820 ArmOp::Udiv { rd, rn, rm } => {
1822 let rd_bits = reg_to_bits(rd);
1823 let rn_bits = reg_to_bits(rn);
1824 let rm_bits = reg_to_bits(rm);
1825 reg_bits_checked(rd_bits)?;
1826 reg_bits_checked(rn_bits)?;
1827 reg_bits_checked(rm_bits)?;
1828
1829 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1831 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1832
1833 let mut bytes = hw1.to_le_bytes().to_vec();
1834 bytes.extend_from_slice(&hw2.to_le_bytes());
1835 encoding_contracts::verify_thumb32(&bytes);
1836 Ok(bytes)
1837 }
1838
1839 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
1840 let rdlo_bits = reg_to_bits(rdlo);
1841 let rdhi_bits = reg_to_bits(rdhi);
1842 let rn_bits = reg_to_bits(rn);
1843 let rm_bits = reg_to_bits(rm);
1844 reg_bits_checked(rdlo_bits)?;
1845 reg_bits_checked(rdhi_bits)?;
1846 reg_bits_checked(rn_bits)?;
1847 reg_bits_checked(rm_bits)?;
1848
1849 let hw1: u16 = (0xFBA0 | rn_bits) as u16;
1851 let hw2: u16 = ((rdlo_bits << 12) | (rdhi_bits << 8) | rm_bits) as u16;
1852
1853 let mut bytes = hw1.to_le_bytes().to_vec();
1854 bytes.extend_from_slice(&hw2.to_le_bytes());
1855 encoding_contracts::verify_thumb32(&bytes);
1856 Ok(bytes)
1857 }
1858
1859 ArmOp::Mul { rd, rn, rm } => {
1861 let rd_bits = reg_to_bits(rd);
1862 let rn_bits = reg_to_bits(rn);
1863 let rm_bits = reg_to_bits(rm);
1864
1865 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1868 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1869
1870 let mut bytes = hw1.to_le_bytes().to_vec();
1871 bytes.extend_from_slice(&hw2.to_le_bytes());
1872 Ok(bytes)
1873 }
1874
1875 ArmOp::Mls { rd, rn, rm, ra } => {
1877 let rd_bits = reg_to_bits(rd);
1878 let rn_bits = reg_to_bits(rn);
1879 let rm_bits = reg_to_bits(rm);
1880 let ra_bits = reg_to_bits(ra);
1881
1882 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1885 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1886
1887 let mut bytes = hw1.to_le_bytes().to_vec();
1888 bytes.extend_from_slice(&hw2.to_le_bytes());
1889 Ok(bytes)
1890 }
1891
1892 ArmOp::Mla { rd, rn, rm, ra } => {
1893 let rd_bits = reg_to_bits(rd);
1894 let rn_bits = reg_to_bits(rn);
1895 let rm_bits = reg_to_bits(rm);
1896 let ra_bits = reg_to_bits(ra);
1897
1898 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1901 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | rm_bits) as u16;
1902
1903 let mut bytes = hw1.to_le_bytes().to_vec();
1904 bytes.extend_from_slice(&hw2.to_le_bytes());
1905 Ok(bytes)
1906 }
1907
1908 ArmOp::And { rd, rn, op2 } => {
1910 if let Operand2::Reg(rm) = op2 {
1911 let rd_bits = reg_to_bits(rd);
1912 let rn_bits = reg_to_bits(rn);
1913 let rm_bits = reg_to_bits(rm);
1914
1915 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1917 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1918
1919 let mut bytes = hw1.to_le_bytes().to_vec();
1920 bytes.extend_from_slice(&hw2.to_le_bytes());
1921 Ok(bytes)
1922 } else if let Operand2::Imm(imm) = op2 {
1923 let rd_bits = reg_to_bits(rd);
1924 let rn_bits = reg_to_bits(rn);
1925
1926 let field = try_thumb_expand_imm(*imm as u32).ok_or_else(|| {
1933 synth_core::Error::synthesis(
1934 "AND immediate is not a valid ThumbExpandImm — materialize into a register",
1935 )
1936 })?;
1937 let i_bit = (field >> 11) & 1;
1938 let imm3 = (field >> 8) & 0x7;
1939 let imm8 = field & 0xFF;
1940
1941 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1942 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1943
1944 let mut bytes = hw1.to_le_bytes().to_vec();
1945 bytes.extend_from_slice(&hw2.to_le_bytes());
1946 Ok(bytes)
1947 } else {
1948 let instr: u16 = 0xBF00;
1950 Ok(instr.to_le_bytes().to_vec())
1951 }
1952 }
1953
1954 ArmOp::Orr { rd, rn, op2 } => {
1956 if let Operand2::Reg(rm) = op2 {
1957 let rd_bits = reg_to_bits(rd);
1958 let rn_bits = reg_to_bits(rn);
1959 let rm_bits = reg_to_bits(rm);
1960
1961 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1963 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1964
1965 let mut bytes = hw1.to_le_bytes().to_vec();
1966 bytes.extend_from_slice(&hw2.to_le_bytes());
1967 Ok(bytes)
1968 } else if let Operand2::Imm(imm) = op2 {
1969 let imm_val = *imm as u32;
1974 if imm_val > 0xFF {
1975 return Err(synth_core::Error::synthesis(
1976 "ORR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1977 ));
1978 }
1979 let rd_bits = reg_to_bits(rd);
1980 let rn_bits = reg_to_bits(rn);
1981 let hw1: u16 = (0xF040 | rn_bits) as u16;
1982 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
1983 let mut bytes = hw1.to_le_bytes().to_vec();
1984 bytes.extend_from_slice(&hw2.to_le_bytes());
1985 Ok(bytes)
1986 } else {
1987 let instr: u16 = 0xBF00;
1988 Ok(instr.to_le_bytes().to_vec())
1989 }
1990 }
1991
1992 ArmOp::Eor { rd, rn, op2 } => {
1994 if let Operand2::Reg(rm) = op2 {
1995 let rd_bits = reg_to_bits(rd);
1996 let rn_bits = reg_to_bits(rn);
1997 let rm_bits = reg_to_bits(rm);
1998
1999 let hw1: u16 = (0xEA80 | rn_bits) as u16;
2001 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
2002
2003 let mut bytes = hw1.to_le_bytes().to_vec();
2004 bytes.extend_from_slice(&hw2.to_le_bytes());
2005 Ok(bytes)
2006 } else if let Operand2::Imm(imm) = op2 {
2007 let imm_val = *imm as u32;
2011 if imm_val > 0xFF {
2012 return Err(synth_core::Error::synthesis(
2013 "EOR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
2014 ));
2015 }
2016 let rd_bits = reg_to_bits(rd);
2017 let rn_bits = reg_to_bits(rn);
2018 let hw1: u16 = (0xF080 | rn_bits) as u16;
2019 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
2020 let mut bytes = hw1.to_le_bytes().to_vec();
2021 bytes.extend_from_slice(&hw2.to_le_bytes());
2022 Ok(bytes)
2023 } else {
2024 let instr: u16 = 0xBF00;
2025 Ok(instr.to_le_bytes().to_vec())
2026 }
2027 }
2028
2029 ArmOp::Lsl { rd, rn, shift } => {
2031 let rd_bits = reg_to_bits(rd) as u16;
2032 let rn_bits = reg_to_bits(rn) as u16;
2033 let shift_bits = (*shift as u16) & 0x1F;
2034
2035 if rd_bits < 8 && rn_bits < 8 {
2036 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2038 Ok(instr.to_le_bytes().to_vec())
2039 } else {
2040 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
2043 }
2044
2045 ArmOp::Lsr { rd, rn, shift } => {
2046 let rd_bits = reg_to_bits(rd) as u16;
2047 let rn_bits = reg_to_bits(rn) as u16;
2048 let shift_bits = (*shift as u16) & 0x1F;
2049
2050 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2051 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2053 Ok(instr.to_le_bytes().to_vec())
2054 } else {
2055 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
2057 }
2058
2059 ArmOp::Asr { rd, rn, shift } => {
2060 let rd_bits = reg_to_bits(rd) as u16;
2061 let rn_bits = reg_to_bits(rn) as u16;
2062 let shift_bits = (*shift as u16) & 0x1F;
2063
2064 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2065 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2067 Ok(instr.to_le_bytes().to_vec())
2068 } else {
2069 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
2071 }
2072
2073 ArmOp::Ror { rd, rn, shift } => {
2074 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
2077
2078 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
2082 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
2083 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
2084 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
2085
2086 ArmOp::Rsb { rd, rn, imm } => {
2089 let rd_bits = reg_to_bits(rd);
2090 let rn_bits = reg_to_bits(rn);
2091 let imm_val = *imm;
2092
2093 let i_bit = (imm_val >> 11) & 1;
2094 let imm3 = (imm_val >> 8) & 0x7;
2095 let imm8 = imm_val & 0xFF;
2096
2097 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2099 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2101
2102 let mut bytes = hw1.to_le_bytes().to_vec();
2103 bytes.extend_from_slice(&hw2.to_le_bytes());
2104 Ok(bytes)
2105 }
2106
2107 ArmOp::Clz { rd, rm } => {
2109 let rd_bits = reg_to_bits(rd);
2110 let rm_bits = reg_to_bits(rm);
2111
2112 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2115 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2116
2117 let mut bytes = hw1.to_le_bytes().to_vec();
2118 bytes.extend_from_slice(&hw2.to_le_bytes());
2119 Ok(bytes)
2120 }
2121
2122 ArmOp::Rbit { rd, rm } => {
2124 let rd_bits = reg_to_bits(rd);
2125 let rm_bits = reg_to_bits(rm);
2126
2127 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2130 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2131
2132 let mut bytes = hw1.to_le_bytes().to_vec();
2133 bytes.extend_from_slice(&hw2.to_le_bytes());
2134 Ok(bytes)
2135 }
2136
2137 ArmOp::Sxtb { rd, rm } => {
2139 let rd_bits = reg_to_bits(rd) as u16;
2140 let rm_bits = reg_to_bits(rm) as u16;
2141
2142 if rd_bits < 8 && rm_bits < 8 {
2143 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2145 Ok(instr.to_le_bytes().to_vec())
2146 } else {
2147 let rd_bits32 = rd_bits as u32;
2150 let rm_bits32 = rm_bits as u32;
2151 let hw1: u16 = 0xFA4F;
2152 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2153 let mut bytes = hw1.to_le_bytes().to_vec();
2154 bytes.extend_from_slice(&hw2.to_le_bytes());
2155 Ok(bytes)
2156 }
2157 }
2158
2159 ArmOp::Sxth { rd, rm } => {
2161 let rd_bits = reg_to_bits(rd) as u16;
2162 let rm_bits = reg_to_bits(rm) as u16;
2163
2164 if rd_bits < 8 && rm_bits < 8 {
2165 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2167 Ok(instr.to_le_bytes().to_vec())
2168 } else {
2169 let rd_bits32 = rd_bits as u32;
2172 let rm_bits32 = rm_bits as u32;
2173 let hw1: u16 = 0xFA0F;
2174 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2175 let mut bytes = hw1.to_le_bytes().to_vec();
2176 bytes.extend_from_slice(&hw2.to_le_bytes());
2177 Ok(bytes)
2178 }
2179 }
2180
2181 ArmOp::Cmp { rn, op2 } => {
2183 let rn_bits = reg_to_bits(rn) as u16;
2184
2185 if let Operand2::Imm(imm) = op2 {
2186 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2189 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2191 Ok(instr.to_le_bytes().to_vec())
2192 } else {
2193 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2194 }
2195 } else if let Operand2::Reg(rm) = op2 {
2196 let rm_bits = reg_to_bits(rm) as u16;
2197 if rn_bits < 8 && rm_bits < 8 {
2198 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2200 Ok(instr.to_le_bytes().to_vec())
2201 } else {
2202 let n_bit = (rn_bits >> 3) & 1;
2204 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2205 Ok(instr.to_le_bytes().to_vec())
2206 }
2207 } else {
2208 let instr: u16 = 0xBF00;
2209 Ok(instr.to_le_bytes().to_vec())
2210 }
2211 }
2212
2213 ArmOp::Cmn { rn, op2 } => {
2216 let rn_bits = reg_to_bits(rn) as u16;
2217
2218 if let Operand2::Imm(imm) = op2 {
2219 let field = try_thumb_expand_imm(*imm as u32).ok_or_else(|| {
2225 synth_core::Error::synthesis(
2226 "CMN immediate is not a valid ThumbExpandImm — materialize into a register",
2227 )
2228 })?;
2229 let i_bit = (field >> 11) & 1;
2230 let imm3 = (field >> 8) & 0x7;
2231 let imm8 = field & 0xFF;
2232 let hw1: u16 = (0xF110 | (i_bit << 10) as u16) | rn_bits;
2233 let hw2: u16 = (imm3 << 12) as u16 | 0x0F00 | imm8 as u16;
2234 let mut bytes = hw1.to_le_bytes().to_vec();
2235 bytes.extend_from_slice(&hw2.to_le_bytes());
2236 Ok(bytes)
2237 } else if let Operand2::Reg(rm) = op2 {
2238 let rm_bits = reg_to_bits(rm) as u16;
2239 if rn_bits < 8 && rm_bits < 8 {
2245 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2247 Ok(instr.to_le_bytes().to_vec())
2248 } else {
2249 let hw1: u16 = 0xEB10 | rn_bits;
2250 let hw2: u16 = 0x0F00 | rm_bits;
2251 let mut bytes = hw1.to_le_bytes().to_vec();
2252 bytes.extend_from_slice(&hw2.to_le_bytes());
2253 Ok(bytes)
2254 }
2255 } else {
2256 Ok(vec![0xBF, 0x00])
2257 }
2258 }
2259
2260 ArmOp::Ldr { rd, addr } => {
2262 let rd_bits = reg_to_bits(rd);
2263 let base_bits = reg_to_bits(&addr.base);
2264
2265 if let Some(offset_reg) = &addr.offset_reg {
2267 let rm_bits = reg_to_bits(offset_reg);
2268
2269 if addr.offset != 0 {
2271 let scratch = Reg::R12;
2274 let mut bytes =
2275 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2276 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2277 return Ok(bytes);
2278 }
2279
2280 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2283 let instr: u16 = 0x5800
2285 | ((rm_bits as u16) << 6)
2286 | ((base_bits as u16) << 3)
2287 | (rd_bits as u16);
2288 return Ok(instr.to_le_bytes().to_vec());
2289 }
2290
2291 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2293 }
2294
2295 let offset = addr.offset as u32;
2297
2298 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2299 let imm5 = (offset >> 2) as u16;
2301 let instr: u16 =
2302 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2303 Ok(instr.to_le_bytes().to_vec())
2304 } else {
2305 self.encode_thumb32_ldr(rd, &addr.base, offset)
2306 }
2307 }
2308
2309 ArmOp::Str { rd, addr } => {
2311 let rd_bits = reg_to_bits(rd);
2312 let base_bits = reg_to_bits(&addr.base);
2313
2314 if let Some(offset_reg) = &addr.offset_reg {
2316 let rm_bits = reg_to_bits(offset_reg);
2317
2318 if addr.offset != 0 {
2320 let scratch = Reg::R12;
2323 let mut bytes =
2324 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2325 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2326 return Ok(bytes);
2327 }
2328
2329 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2332 let instr: u16 = 0x5000
2334 | ((rm_bits as u16) << 6)
2335 | ((base_bits as u16) << 3)
2336 | (rd_bits as u16);
2337 return Ok(instr.to_le_bytes().to_vec());
2338 }
2339
2340 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2342 }
2343
2344 let offset = addr.offset as u32;
2346
2347 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2348 let imm5 = (offset >> 2) as u16;
2350 let instr: u16 =
2351 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2352 Ok(instr.to_le_bytes().to_vec())
2353 } else {
2354 self.encode_thumb32_str(rd, &addr.base, offset)
2355 }
2356 }
2357
2358 ArmOp::Ldrb { rd, addr } => {
2360 let rd_bits = reg_to_bits(rd);
2361 let base_bits = reg_to_bits(&addr.base);
2362
2363 if let Some(offset_reg) = &addr.offset_reg {
2364 if addr.offset != 0 {
2365 let scratch = Reg::R12;
2366 let mut bytes =
2367 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2368 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2369 return Ok(bytes);
2370 }
2371 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2372 }
2373
2374 let offset = addr.offset as u32;
2375 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2376 let instr: u16 = 0x7800
2378 | ((offset as u16) << 6)
2379 | ((base_bits as u16) << 3)
2380 | (rd_bits as u16);
2381 Ok(instr.to_le_bytes().to_vec())
2382 } else {
2383 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2384 }
2385 }
2386
2387 ArmOp::Ldrsb { rd, addr } => {
2389 let rd_bits = reg_to_bits(rd);
2390 let base_bits = reg_to_bits(&addr.base);
2391
2392 if let Some(offset_reg) = &addr.offset_reg {
2393 if addr.offset != 0 {
2394 let scratch = Reg::R12;
2395 let mut bytes =
2396 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2397 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2398 return Ok(bytes);
2399 }
2400 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2401 }
2402
2403 let offset = addr.offset as u32;
2404 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2407 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2409 } else {
2410 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2411 }
2412 }
2413
2414 ArmOp::Ldrh { rd, addr } => {
2416 let rd_bits = reg_to_bits(rd);
2417 let base_bits = reg_to_bits(&addr.base);
2418
2419 if let Some(offset_reg) = &addr.offset_reg {
2420 if addr.offset != 0 {
2421 let scratch = Reg::R12;
2422 let mut bytes =
2423 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2424 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2425 return Ok(bytes);
2426 }
2427 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2428 }
2429
2430 let offset = addr.offset as u32;
2431 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2432 let imm5 = (offset >> 1) as u16;
2434 let instr: u16 =
2435 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2436 Ok(instr.to_le_bytes().to_vec())
2437 } else {
2438 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2439 }
2440 }
2441
2442 ArmOp::Ldrsh { rd, addr } => {
2444 if let Some(offset_reg) = &addr.offset_reg {
2445 if addr.offset != 0 {
2446 let scratch = Reg::R12;
2447 let mut bytes =
2448 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2449 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2450 return Ok(bytes);
2451 }
2452 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2453 }
2454
2455 let offset = addr.offset as u32;
2456 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2457 }
2458
2459 ArmOp::Strb { rd, addr } => {
2461 let rd_bits = reg_to_bits(rd);
2462 let base_bits = reg_to_bits(&addr.base);
2463
2464 if let Some(offset_reg) = &addr.offset_reg {
2465 if addr.offset != 0 {
2466 let scratch = Reg::R12;
2467 let mut bytes =
2468 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2469 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2470 return Ok(bytes);
2471 }
2472 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2473 }
2474
2475 let offset = addr.offset as u32;
2476 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2477 let instr: u16 = 0x7000
2479 | ((offset as u16) << 6)
2480 | ((base_bits as u16) << 3)
2481 | (rd_bits as u16);
2482 Ok(instr.to_le_bytes().to_vec())
2483 } else {
2484 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2485 }
2486 }
2487
2488 ArmOp::Strh { rd, addr } => {
2490 let rd_bits = reg_to_bits(rd);
2491 let base_bits = reg_to_bits(&addr.base);
2492
2493 if let Some(offset_reg) = &addr.offset_reg {
2494 if addr.offset != 0 {
2495 let scratch = Reg::R12;
2496 let mut bytes =
2497 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2498 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2499 return Ok(bytes);
2500 }
2501 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2502 }
2503
2504 let offset = addr.offset as u32;
2505 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2506 let imm5 = (offset >> 1) as u16;
2508 let instr: u16 =
2509 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2510 Ok(instr.to_le_bytes().to_vec())
2511 } else {
2512 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2513 }
2514 }
2515
2516 ArmOp::MemorySize { rd } => {
2518 let rd_bits = reg_to_bits(rd);
2521 let r10_bits = reg_to_bits(&Reg::R10);
2522 if rd_bits < 8 && r10_bits < 8 {
2523 let instr: u16 =
2524 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2525 Ok(instr.to_le_bytes().to_vec())
2526 } else {
2527 let imm5: u32 = 16;
2529 let imm3 = (imm5 >> 2) & 0x7;
2530 let imm2 = imm5 & 0x3;
2531 let hw1: u16 = 0xEA4F;
2532 let hw2: u16 =
2533 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2534 let mut bytes = hw1.to_le_bytes().to_vec();
2535 bytes.extend_from_slice(&hw2.to_le_bytes());
2536 Ok(bytes)
2537 }
2538 }
2539
2540 ArmOp::MemoryGrow { rd, .. } => {
2542 let rd_bits = reg_to_bits(rd);
2546 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2549 bytes.extend_from_slice(&hw2.to_le_bytes());
2550 Ok(bytes)
2551 }
2552
2553 ArmOp::Bx { rm } => {
2555 let rm_bits = reg_to_bits(rm) as u16;
2556 let instr: u16 = 0x4700 | (rm_bits << 3);
2558 Ok(instr.to_le_bytes().to_vec())
2559 }
2560
2561 ArmOp::Blx { rm } => {
2564 let rm_bits = reg_to_bits(rm) as u16;
2565 let instr: u16 = 0x4780 | (rm_bits << 3);
2566 Ok(instr.to_le_bytes().to_vec())
2567 }
2568
2569 ArmOp::CallIndirect {
2573 rd: _,
2574 type_idx: _,
2575 table_index_reg,
2576 } => {
2577 let idx_reg = reg_to_bits(table_index_reg);
2578 let mut bytes = Vec::new();
2579
2580 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2596 bytes.extend_from_slice(&hw1.to_le_bytes());
2597 bytes.extend_from_slice(&hw2.to_le_bytes());
2598
2599 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2605 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2606
2607 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2611
2612 Ok(bytes)
2613 }
2614
2615 ArmOp::Label { .. } => Ok(Vec::new()),
2617
2618 ArmOp::Bcc { cond, label: _ } => {
2620 use synth_synthesis::Condition;
2621 let cond_bits: u16 = match cond {
2622 Condition::EQ => 0x0,
2623 Condition::NE => 0x1,
2624 Condition::HS => 0x2,
2625 Condition::LO => 0x3,
2626 Condition::HI => 0x8,
2627 Condition::LS => 0x9,
2628 Condition::GE => 0xA,
2629 Condition::LT => 0xB,
2630 Condition::GT => 0xC,
2631 Condition::LE => 0xD,
2632 };
2633 let instr: u16 = 0xD000 | (cond_bits << 8);
2635 Ok(instr.to_le_bytes().to_vec())
2636 }
2637
2638 ArmOp::B { label: _ } => {
2640 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2644 }
2645
2646 ArmOp::Bhs { label: _ } => {
2649 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2653 }
2654
2655 ArmOp::Blo { label: _ } => {
2658 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2662 }
2663
2664 ArmOp::BOffset { offset } => {
2667 let halfword_offset = *offset;
2670
2671 if (-1024..=1022).contains(&halfword_offset) {
2674 let imm11 = (halfword_offset as u16) & 0x7FF;
2676 let instr: u16 = 0xE000 | imm11;
2677 Ok(instr.to_le_bytes().to_vec())
2678 } else {
2679 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2695 let uoffset = signed_offset as u32;
2696 let imm10 = (uoffset >> 12) & 0x3FF; let imm11 = (uoffset >> 1) & 0x7FF; let i1 = (uoffset >> 23) & 1; let i2 = (uoffset >> 22) & 1; let j1 = (!(i1 ^ s)) & 1; let j2 = (!(i2 ^ s)) & 1; let hw1: u16 = (0xF000 | (s << 10) | imm10) as u16;
2704 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2705
2706 let mut bytes = hw1.to_le_bytes().to_vec();
2707 bytes.extend_from_slice(&hw2.to_le_bytes());
2708 Ok(bytes)
2709 }
2710 }
2711
2712 ArmOp::BCondOffset { cond, offset } => {
2714 use synth_synthesis::Condition;
2715 let cond_bits: u16 = match cond {
2716 Condition::EQ => 0x0,
2717 Condition::NE => 0x1,
2718 Condition::HS => 0x2,
2719 Condition::LO => 0x3,
2720 Condition::HI => 0x8,
2721 Condition::LS => 0x9,
2722 Condition::GE => 0xA,
2723 Condition::LT => 0xB,
2724 Condition::GT => 0xC,
2725 Condition::LE => 0xD,
2726 };
2727
2728 let halfword_offset = *offset;
2731
2732 if (-128..=127).contains(&halfword_offset) {
2735 let imm8 = (halfword_offset as u16) & 0xFF;
2736 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2737 Ok(instr.to_le_bytes().to_vec())
2738 } else {
2739 let offset = halfword_offset >> 1;
2743 let s = if offset < 0 { 1u32 } else { 0u32 };
2744 let imm6 = ((offset >> 11) as u32) & 0x3F;
2745 let imm11 = (offset as u32) & 0x7FF;
2746 let j1 = if s == 1 { 1 } else { 0 };
2747 let j2 = if s == 1 { 1 } else { 0 };
2748
2749 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2750 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2751
2752 let mut bytes = hw1.to_le_bytes().to_vec();
2753 bytes.extend_from_slice(&hw2.to_le_bytes());
2754 Ok(bytes)
2755 }
2756 }
2757
2758 ArmOp::Bl { label: _ } => {
2759 let hw1: u16 = 0xF7FF;
2774 let hw2: u16 = 0xFFFE;
2775 let mut bytes = hw1.to_le_bytes().to_vec();
2776 bytes.extend_from_slice(&hw2.to_le_bytes());
2777 Ok(bytes)
2778 }
2779
2780 ArmOp::Mvn { rd, op2 } => {
2782 if let Operand2::Reg(rm) = op2 {
2783 let rd_bits = reg_to_bits(rd) as u16;
2784 let rm_bits = reg_to_bits(rm) as u16;
2785
2786 if rd_bits < 8 && rm_bits < 8 {
2787 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2789 Ok(instr.to_le_bytes().to_vec())
2790 } else {
2791 let hw1: u16 = 0xEA6F_u16;
2793 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2794 let mut bytes = hw1.to_le_bytes().to_vec();
2795 bytes.extend_from_slice(&hw2.to_le_bytes());
2796 Ok(bytes)
2797 }
2798 } else {
2799 let instr: u16 = 0xBF00;
2800 Ok(instr.to_le_bytes().to_vec())
2801 }
2802 }
2803
2804 ArmOp::Movw { rd, imm16 } => {
2806 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2807 }
2808
2809 ArmOp::Movt { rd, imm16 } => {
2811 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2812 }
2813
2814 ArmOp::MovwSym { rd, addend, .. } => {
2819 self.encode_thumb32_movw_raw(reg_to_bits(rd), (*addend as u32) & 0xffff)
2820 }
2821 ArmOp::MovtSym { rd, addend, .. } => {
2822 self.encode_thumb32_movt_raw(reg_to_bits(rd), ((*addend as u32) >> 16) & 0xffff)
2823 }
2824
2825 ArmOp::LdrSym { rd, .. } => {
2833 let rt = reg_to_bits(rd) as u16;
2834 let hw1: u16 = 0xF8DF; let hw2: u16 = rt << 12; let mut bytes = Vec::with_capacity(4);
2837 bytes.extend_from_slice(&hw1.to_le_bytes());
2838 bytes.extend_from_slice(&hw2.to_le_bytes());
2839 Ok(bytes)
2840 }
2841
2842 ArmOp::SetCond { rd, cond } => {
2848 let rd_bits = reg_to_bits(rd) as u16;
2849
2850 use synth_synthesis::Condition;
2852 let cond_bits: u16 = match cond {
2853 Condition::EQ => 0x0,
2854 Condition::NE => 0x1,
2855 Condition::LT => 0xB,
2856 Condition::LE => 0xD,
2857 Condition::GT => 0xC,
2858 Condition::GE => 0xA,
2859 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2864
2865 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2870 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2871
2872 let mut bytes = ite_instr.to_le_bytes().to_vec();
2883 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2884 if rd_bits <= 7 {
2885 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2887 } else {
2888 let hw1: u16 = 0xF04F;
2890 let hw2: u16 = (rd_bits << 8) | imm;
2891 bytes.extend_from_slice(&hw1.to_le_bytes());
2892 bytes.extend_from_slice(&hw2.to_le_bytes());
2893 }
2894 };
2895 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2898 }
2899
2900 ArmOp::I64SetCond {
2905 rd,
2906 rn_lo,
2907 rn_hi,
2908 rm_lo,
2909 rm_hi,
2910 cond,
2911 } => {
2912 use synth_synthesis::Condition;
2913 let rd_bits = reg_to_bits(rd) as u16;
2914 let mut bytes = Vec::new();
2915
2916 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2918 rm: &synth_synthesis::Reg|
2919 -> Vec<u8> {
2920 let rn_bits = reg_to_bits(rn) as u16;
2921 let rm_bits = reg_to_bits(rm) as u16;
2922 if rn_bits < 8 && rm_bits < 8 {
2923 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2924 instr.to_le_bytes().to_vec()
2925 } else {
2926 let n_bit = (rn_bits >> 3) & 1;
2927 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2928 instr.to_le_bytes().to_vec()
2929 }
2930 };
2931
2932 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2934 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2935 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2936 ite_instr.to_le_bytes().to_vec()
2937 };
2938
2939 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2941 let mut b = encode_ite(cond_bits);
2942 if rd_bits < 8 {
2943 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2944 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2945 b.extend_from_slice(&mov_one.to_le_bytes());
2946 b.extend_from_slice(&mov_zero.to_le_bytes());
2947 } else {
2948 for imm in [1u16, 0u16] {
2956 let hw1: u16 = 0xF04F;
2957 let hw2: u16 = (rd_bits << 8) | imm;
2958 b.extend_from_slice(&hw1.to_le_bytes());
2959 b.extend_from_slice(&hw2.to_le_bytes());
2960 }
2961 }
2962 b
2963 };
2964
2965 match cond {
2966 Condition::EQ | Condition::NE => {
2967 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2969
2970 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2973
2974 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2976
2977 let cond_bits: u16 = match cond {
2979 Condition::EQ => 0x0,
2980 Condition::NE => 0x1,
2981 _ => unreachable!(),
2982 };
2983 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2984 }
2985
2986 Condition::LT => {
2987 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2989
2990 let rn_hi_bits = reg_to_bits(rn_hi);
2993 let rm_hi_bits = reg_to_bits(rm_hi);
2994 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2995 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2996 bytes.extend_from_slice(&hw1.to_le_bytes());
2997 bytes.extend_from_slice(&hw2.to_le_bytes());
2998
2999 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
3002
3003 Condition::GT => {
3004 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3007
3008 let rm_hi_bits = reg_to_bits(rm_hi);
3010 let rn_hi_bits = reg_to_bits(rn_hi);
3011 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3012 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3013 bytes.extend_from_slice(&hw1.to_le_bytes());
3014 bytes.extend_from_slice(&hw2.to_le_bytes());
3015
3016 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
3019
3020 Condition::LE => {
3021 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3025
3026 let rm_hi_bits = reg_to_bits(rm_hi);
3028 let rn_hi_bits = reg_to_bits(rn_hi);
3029 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3030 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3031 bytes.extend_from_slice(&hw1.to_le_bytes());
3032 bytes.extend_from_slice(&hw2.to_le_bytes());
3033
3034 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3037
3038 Condition::GE => {
3039 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3042
3043 let rn_hi_bits = reg_to_bits(rn_hi);
3045 let rm_hi_bits = reg_to_bits(rm_hi);
3046 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3047 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3048 bytes.extend_from_slice(&hw1.to_le_bytes());
3049 bytes.extend_from_slice(&hw2.to_le_bytes());
3050
3051 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3054
3055 Condition::LO => {
3057 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3059 let rn_hi_bits = reg_to_bits(rn_hi);
3060 let rm_hi_bits = reg_to_bits(rm_hi);
3061 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3062 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3063 bytes.extend_from_slice(&hw1.to_le_bytes());
3064 bytes.extend_from_slice(&hw2.to_le_bytes());
3065 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3067
3068 Condition::HI => {
3069 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3071 let rm_hi_bits = reg_to_bits(rm_hi);
3072 let rn_hi_bits = reg_to_bits(rn_hi);
3073 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3074 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3075 bytes.extend_from_slice(&hw1.to_le_bytes());
3076 bytes.extend_from_slice(&hw2.to_le_bytes());
3077 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3079
3080 Condition::LS => {
3081 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3083 let rm_hi_bits = reg_to_bits(rm_hi);
3084 let rn_hi_bits = reg_to_bits(rn_hi);
3085 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3086 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3087 bytes.extend_from_slice(&hw1.to_le_bytes());
3088 bytes.extend_from_slice(&hw2.to_le_bytes());
3089 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3091
3092 Condition::HS => {
3093 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3095 let rn_hi_bits = reg_to_bits(rn_hi);
3096 let rm_hi_bits = reg_to_bits(rm_hi);
3097 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3098 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3099 bytes.extend_from_slice(&hw1.to_le_bytes());
3100 bytes.extend_from_slice(&hw2.to_le_bytes());
3101 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3103 }
3104
3105 Ok(bytes)
3106 }
3107
3108 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
3111 let rd_bits = reg_to_bits(rd);
3112 let rn_lo_bits = reg_to_bits(rn_lo);
3113 let rn_hi_bits = reg_to_bits(rn_hi);
3114 let mut bytes = Vec::new();
3115
3116 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3118 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3119 bytes.extend_from_slice(&hw1.to_le_bytes());
3120 bytes.extend_from_slice(&hw2.to_le_bytes());
3121
3122 if rd_bits < 8 {
3127 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3128 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3129 } else {
3130 let hw1: u16 = 0xF1B0 | (rd_bits as u16);
3131 let hw2: u16 = 0x0F00;
3132 bytes.extend_from_slice(&hw1.to_le_bytes());
3133 bytes.extend_from_slice(&hw2.to_le_bytes());
3134 }
3135
3136 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3140 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3141 if rd_bits < 8 {
3142 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3143 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3144 bytes.extend_from_slice(&mov_one.to_le_bytes());
3145 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3146 } else {
3147 for imm in [1u16, 0u16] {
3148 let hw1: u16 = 0xF04F;
3149 let hw2: u16 = ((rd_bits as u16) << 8) | imm;
3150 bytes.extend_from_slice(&hw1.to_le_bytes());
3151 bytes.extend_from_slice(&hw2.to_le_bytes());
3152 }
3153 }
3154
3155 Ok(bytes)
3156 }
3157
3158 ArmOp::I64Mul {
3162 rd_lo,
3163 rd_hi,
3164 rn_lo,
3165 rn_hi,
3166 rm_lo,
3167 rm_hi,
3168 } => {
3169 let rd_lo_bits = reg_to_bits(rd_lo);
3170 let rd_hi_bits = reg_to_bits(rd_hi);
3171 let rn_lo_bits = reg_to_bits(rn_lo);
3172 let rn_hi_bits = reg_to_bits(rn_hi);
3173 let rm_lo_bits = reg_to_bits(rm_lo);
3174 let rm_hi_bits = reg_to_bits(rm_hi);
3175 let r12: u32 = 12; let mut bytes = Vec::new();
3177
3178 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3181 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3182 bytes.extend_from_slice(&hw1.to_le_bytes());
3183 bytes.extend_from_slice(&hw2.to_le_bytes());
3184
3185 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3188 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3189 bytes.extend_from_slice(&hw1.to_le_bytes());
3190 bytes.extend_from_slice(&hw2.to_le_bytes());
3191
3192 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3195 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3196 bytes.extend_from_slice(&hw1.to_le_bytes());
3197 bytes.extend_from_slice(&hw2.to_le_bytes());
3198
3199 let d_bit = (rd_hi_bits >> 3) & 1;
3202 let add_instr: u16 =
3203 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3204 bytes.extend_from_slice(&add_instr.to_le_bytes());
3205
3206 Ok(bytes)
3207 }
3208
3209 ArmOp::I64Shl {
3212 rd_lo,
3213 rd_hi,
3214 rn_lo,
3215 rn_hi,
3216 rm_lo,
3217 rm_hi,
3218 } => {
3219 let rd_lo_bits = reg_to_bits(rd_lo);
3220 let rd_hi_bits = reg_to_bits(rd_hi);
3221 let rn_lo_bits = reg_to_bits(rn_lo);
3222 let rn_hi_bits = reg_to_bits(rn_hi);
3223 let rm_lo_bits = reg_to_bits(rm_lo);
3224 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3226
3227 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3229 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3230 bytes.extend_from_slice(&hw1.to_le_bytes());
3231 bytes.extend_from_slice(&hw2.to_le_bytes());
3232
3233 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3235 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3236 bytes.extend_from_slice(&hw1.to_le_bytes());
3237 bytes.extend_from_slice(&hw2.to_le_bytes());
3238
3239 let bpl: u16 = 0xD50A;
3241 bytes.extend_from_slice(&bpl.to_le_bytes());
3242
3243 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3246 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3247 bytes.extend_from_slice(&hw1.to_le_bytes());
3248 bytes.extend_from_slice(&hw2.to_le_bytes());
3249
3250 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3252 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3253 bytes.extend_from_slice(&hw1.to_le_bytes());
3254 bytes.extend_from_slice(&hw2.to_le_bytes());
3255
3256 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3258 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3259 bytes.extend_from_slice(&hw1.to_le_bytes());
3260 bytes.extend_from_slice(&hw2.to_le_bytes());
3261
3262 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3264 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3265 bytes.extend_from_slice(&hw1.to_le_bytes());
3266 bytes.extend_from_slice(&hw2.to_le_bytes());
3267
3268 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3270 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3271 bytes.extend_from_slice(&hw1.to_le_bytes());
3272 bytes.extend_from_slice(&hw2.to_le_bytes());
3273
3274 let b_done: u16 = 0xE002;
3276 bytes.extend_from_slice(&b_done.to_le_bytes());
3277
3278 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3281 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3282 bytes.extend_from_slice(&hw1.to_le_bytes());
3283 bytes.extend_from_slice(&hw2.to_le_bytes());
3284
3285 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3287 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3288
3289 Ok(bytes) }
3291
3292 ArmOp::I64ShrU {
3294 rd_lo,
3295 rd_hi,
3296 rn_lo,
3297 rn_hi,
3298 rm_lo,
3299 rm_hi,
3300 } => {
3301 let rd_lo_bits = reg_to_bits(rd_lo);
3302 let rd_hi_bits = reg_to_bits(rd_hi);
3303 let rn_lo_bits = reg_to_bits(rn_lo);
3304 let rn_hi_bits = reg_to_bits(rn_hi);
3305 let rm_lo_bits = reg_to_bits(rm_lo);
3306 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3308
3309 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3311 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3312 bytes.extend_from_slice(&hw1.to_le_bytes());
3313 bytes.extend_from_slice(&hw2.to_le_bytes());
3314
3315 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3317 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3318 bytes.extend_from_slice(&hw1.to_le_bytes());
3319 bytes.extend_from_slice(&hw2.to_le_bytes());
3320
3321 let bpl: u16 = 0xD50A;
3323 bytes.extend_from_slice(&bpl.to_le_bytes());
3324
3325 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3328 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3329 bytes.extend_from_slice(&hw1.to_le_bytes());
3330 bytes.extend_from_slice(&hw2.to_le_bytes());
3331
3332 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3334 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3335 bytes.extend_from_slice(&hw1.to_le_bytes());
3336 bytes.extend_from_slice(&hw2.to_le_bytes());
3337
3338 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3340 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3341 bytes.extend_from_slice(&hw1.to_le_bytes());
3342 bytes.extend_from_slice(&hw2.to_le_bytes());
3343
3344 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3346 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3347 bytes.extend_from_slice(&hw1.to_le_bytes());
3348 bytes.extend_from_slice(&hw2.to_le_bytes());
3349
3350 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3352 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3353 bytes.extend_from_slice(&hw1.to_le_bytes());
3354 bytes.extend_from_slice(&hw2.to_le_bytes());
3355
3356 let b_done: u16 = 0xE002;
3358 bytes.extend_from_slice(&b_done.to_le_bytes());
3359
3360 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3363 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3364 bytes.extend_from_slice(&hw1.to_le_bytes());
3365 bytes.extend_from_slice(&hw2.to_le_bytes());
3366
3367 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3369 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3370
3371 Ok(bytes) }
3373
3374 ArmOp::I64ShrS {
3376 rd_lo,
3377 rd_hi,
3378 rn_lo,
3379 rn_hi,
3380 rm_lo,
3381 rm_hi,
3382 } => {
3383 let rd_lo_bits = reg_to_bits(rd_lo);
3384 let rd_hi_bits = reg_to_bits(rd_hi);
3385 let rn_lo_bits = reg_to_bits(rn_lo);
3386 let rn_hi_bits = reg_to_bits(rn_hi);
3387 let rm_lo_bits = reg_to_bits(rm_lo);
3388 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3390
3391 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3393 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3394 bytes.extend_from_slice(&hw1.to_le_bytes());
3395 bytes.extend_from_slice(&hw2.to_le_bytes());
3396
3397 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3399 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3400 bytes.extend_from_slice(&hw1.to_le_bytes());
3401 bytes.extend_from_slice(&hw2.to_le_bytes());
3402
3403 let bpl: u16 = 0xD50A;
3405 bytes.extend_from_slice(&bpl.to_le_bytes());
3406
3407 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3410 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3411 bytes.extend_from_slice(&hw1.to_le_bytes());
3412 bytes.extend_from_slice(&hw2.to_le_bytes());
3413
3414 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3416 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3417 bytes.extend_from_slice(&hw1.to_le_bytes());
3418 bytes.extend_from_slice(&hw2.to_le_bytes());
3419
3420 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3422 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3423 bytes.extend_from_slice(&hw1.to_le_bytes());
3424 bytes.extend_from_slice(&hw2.to_le_bytes());
3425
3426 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3428 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3429 bytes.extend_from_slice(&hw1.to_le_bytes());
3430 bytes.extend_from_slice(&hw2.to_le_bytes());
3431
3432 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3434 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3435 bytes.extend_from_slice(&hw1.to_le_bytes());
3436 bytes.extend_from_slice(&hw2.to_le_bytes());
3437
3438 let b_done: u16 = 0xE003;
3440 bytes.extend_from_slice(&b_done.to_le_bytes());
3441
3442 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3445 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3446 bytes.extend_from_slice(&hw1.to_le_bytes());
3447 bytes.extend_from_slice(&hw2.to_le_bytes());
3448
3449 let hw1: u16 = 0xEA4F;
3453 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3454 bytes.extend_from_slice(&hw1.to_le_bytes());
3455 bytes.extend_from_slice(&hw2.to_le_bytes());
3456
3457 Ok(bytes) }
3459
3460 ArmOp::I64Rotl {
3465 rdlo,
3466 rdhi,
3467 rnlo,
3468 rnhi,
3469 shift,
3470 } => {
3471 let rd_lo_bits = reg_to_bits(rdlo);
3472 let rd_hi_bits = reg_to_bits(rdhi);
3473 let rn_lo_bits = reg_to_bits(rnlo);
3474 let rn_hi_bits = reg_to_bits(rnhi);
3475 let shift_bits = reg_to_bits(shift);
3476 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3480
3481 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3483
3484 let hw1: u16 = (0xF000 | shift_bits) as u16;
3486 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3487 bytes.extend_from_slice(&hw1.to_le_bytes());
3488 bytes.extend_from_slice(&hw2.to_le_bytes());
3489
3490 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3492 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3493 bytes.extend_from_slice(&hw1.to_le_bytes());
3494 bytes.extend_from_slice(&hw2.to_le_bytes());
3495
3496 let bpl: u16 = 0xD50E;
3498 bytes.extend_from_slice(&bpl.to_le_bytes());
3499
3500 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3503 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3504 bytes.extend_from_slice(&hw1.to_le_bytes());
3505 bytes.extend_from_slice(&hw2.to_le_bytes());
3506
3507 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3509 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3510 bytes.extend_from_slice(&hw1.to_le_bytes());
3511 bytes.extend_from_slice(&hw2.to_le_bytes());
3512
3513 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3515 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3516 bytes.extend_from_slice(&hw1.to_le_bytes());
3517 bytes.extend_from_slice(&hw2.to_le_bytes());
3518
3519 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3521 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3522 bytes.extend_from_slice(&hw1.to_le_bytes());
3523 bytes.extend_from_slice(&hw2.to_le_bytes());
3524
3525 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3527 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3528 bytes.extend_from_slice(&hw1.to_le_bytes());
3529 bytes.extend_from_slice(&hw2.to_le_bytes());
3530
3531 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3533 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3534 bytes.extend_from_slice(&hw1.to_le_bytes());
3535 bytes.extend_from_slice(&hw2.to_le_bytes());
3536
3537 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3539 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3540 bytes.extend_from_slice(&hw1.to_le_bytes());
3541 bytes.extend_from_slice(&hw2.to_le_bytes());
3542
3543 let b_done: u16 = 0xE00E;
3545 bytes.extend_from_slice(&b_done.to_le_bytes());
3546
3547 let hw1: u16 = (0xF1C0 | r3) as u16;
3551 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3552 bytes.extend_from_slice(&hw1.to_le_bytes());
3553 bytes.extend_from_slice(&hw2.to_le_bytes());
3554
3555 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3557 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3558 bytes.extend_from_slice(&hw1.to_le_bytes());
3559 bytes.extend_from_slice(&hw2.to_le_bytes());
3560
3561 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3563 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3564 bytes.extend_from_slice(&hw1.to_le_bytes());
3565 bytes.extend_from_slice(&hw2.to_le_bytes());
3566
3567 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3569 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3570 bytes.extend_from_slice(&hw1.to_le_bytes());
3571 bytes.extend_from_slice(&hw2.to_le_bytes());
3572
3573 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3575 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3576 bytes.extend_from_slice(&hw1.to_le_bytes());
3577 bytes.extend_from_slice(&hw2.to_le_bytes());
3578
3579 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3581 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3582 bytes.extend_from_slice(&hw1.to_le_bytes());
3583 bytes.extend_from_slice(&hw2.to_le_bytes());
3584
3585 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3587 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3588 bytes.extend_from_slice(&hw1.to_le_bytes());
3589 bytes.extend_from_slice(&hw2.to_le_bytes());
3590
3591 let d_bit = (rd_hi_bits >> 3) & 1;
3593 let mov_instr: u16 =
3594 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3595 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3596
3597 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3599
3600 Ok(bytes) }
3602
3603 ArmOp::I64Rotr {
3608 rdlo,
3609 rdhi,
3610 rnlo,
3611 rnhi,
3612 shift,
3613 } => {
3614 let rd_lo_bits = reg_to_bits(rdlo);
3615 let rd_hi_bits = reg_to_bits(rdhi);
3616 let rn_lo_bits = reg_to_bits(rnlo);
3617 let rn_hi_bits = reg_to_bits(rnhi);
3618 let shift_bits = reg_to_bits(shift);
3619 let r12: u32 = 12;
3620 let r3: u32 = 3;
3621 let r4: u32 = 4;
3622 let mut bytes = Vec::new();
3623
3624 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3626
3627 let hw1: u16 = (0xF000 | shift_bits) as u16;
3629 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3630 bytes.extend_from_slice(&hw1.to_le_bytes());
3631 bytes.extend_from_slice(&hw2.to_le_bytes());
3632
3633 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3635 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3636 bytes.extend_from_slice(&hw1.to_le_bytes());
3637 bytes.extend_from_slice(&hw2.to_le_bytes());
3638
3639 let bpl: u16 = 0xD50E;
3641 bytes.extend_from_slice(&bpl.to_le_bytes());
3642
3643 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3646 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3647 bytes.extend_from_slice(&hw1.to_le_bytes());
3648 bytes.extend_from_slice(&hw2.to_le_bytes());
3649
3650 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3652 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3653 bytes.extend_from_slice(&hw1.to_le_bytes());
3654 bytes.extend_from_slice(&hw2.to_le_bytes());
3655
3656 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3658 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3659 bytes.extend_from_slice(&hw1.to_le_bytes());
3660 bytes.extend_from_slice(&hw2.to_le_bytes());
3661
3662 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3664 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3665 bytes.extend_from_slice(&hw1.to_le_bytes());
3666 bytes.extend_from_slice(&hw2.to_le_bytes());
3667
3668 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3670 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3671 bytes.extend_from_slice(&hw1.to_le_bytes());
3672 bytes.extend_from_slice(&hw2.to_le_bytes());
3673
3674 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3676 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3677 bytes.extend_from_slice(&hw1.to_le_bytes());
3678 bytes.extend_from_slice(&hw2.to_le_bytes());
3679
3680 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3682 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3683 bytes.extend_from_slice(&hw1.to_le_bytes());
3684 bytes.extend_from_slice(&hw2.to_le_bytes());
3685
3686 let b_done: u16 = 0xE00E;
3688 bytes.extend_from_slice(&b_done.to_le_bytes());
3689
3690 let hw1: u16 = (0xF1C0 | r3) as u16;
3693 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3694 bytes.extend_from_slice(&hw1.to_le_bytes());
3695 bytes.extend_from_slice(&hw2.to_le_bytes());
3696
3697 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3699 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3700 bytes.extend_from_slice(&hw1.to_le_bytes());
3701 bytes.extend_from_slice(&hw2.to_le_bytes());
3702
3703 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3705 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3706 bytes.extend_from_slice(&hw1.to_le_bytes());
3707 bytes.extend_from_slice(&hw2.to_le_bytes());
3708
3709 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3711 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3712 bytes.extend_from_slice(&hw1.to_le_bytes());
3713 bytes.extend_from_slice(&hw2.to_le_bytes());
3714
3715 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3717 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3718 bytes.extend_from_slice(&hw1.to_le_bytes());
3719 bytes.extend_from_slice(&hw2.to_le_bytes());
3720
3721 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3723 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3724 bytes.extend_from_slice(&hw1.to_le_bytes());
3725 bytes.extend_from_slice(&hw2.to_le_bytes());
3726
3727 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3729 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3730 bytes.extend_from_slice(&hw1.to_le_bytes());
3731 bytes.extend_from_slice(&hw2.to_le_bytes());
3732
3733 let d_bit = (rd_lo_bits >> 3) & 1;
3735 let mov_instr: u16 =
3736 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3737 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3738
3739 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3741
3742 Ok(bytes) }
3744
3745 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3759 let rd_bits = reg_to_bits(rd);
3760 let rn_lo_bits = reg_to_bits(rnlo);
3761 let rn_hi_bits = reg_to_bits(rnhi);
3762 let mut bytes = Vec::new();
3763
3764 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3766 let hw2: u16 = 0x0F00;
3767 bytes.extend_from_slice(&hw1.to_le_bytes());
3768 bytes.extend_from_slice(&hw2.to_le_bytes());
3769
3770 let beq: u16 = 0xD003;
3773 bytes.extend_from_slice(&beq.to_le_bytes());
3774
3775 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3778 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3779 bytes.extend_from_slice(&hw1.to_le_bytes());
3780 bytes.extend_from_slice(&hw2.to_le_bytes());
3781
3782 let b_done: u16 = 0xE004;
3785 bytes.extend_from_slice(&b_done.to_le_bytes());
3786
3787 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3789
3790 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3794 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3795 bytes.extend_from_slice(&hw1.to_le_bytes());
3796 bytes.extend_from_slice(&hw2.to_le_bytes());
3797
3798 let hw1: u16 = (0xF100 | rd_bits) as u16;
3800 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3801 bytes.extend_from_slice(&hw1.to_le_bytes());
3802 bytes.extend_from_slice(&hw2.to_le_bytes());
3803
3804 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3808 bytes.extend_from_slice(&mov0.to_le_bytes());
3809
3810 Ok(bytes)
3811 }
3812
3813 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3829 let rd_bits = reg_to_bits(rd);
3830 let rn_lo_bits = reg_to_bits(rnlo);
3831 let rn_hi_bits = reg_to_bits(rnhi);
3832 let mut bytes = Vec::new();
3833
3834 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3836 let hw2: u16 = 0x0F00;
3837 bytes.extend_from_slice(&hw1.to_le_bytes());
3838 bytes.extend_from_slice(&hw2.to_le_bytes());
3839
3840 let beq: u16 = 0xD005;
3843 bytes.extend_from_slice(&beq.to_le_bytes());
3844
3845 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3848 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3849 bytes.extend_from_slice(&hw1.to_le_bytes());
3850 bytes.extend_from_slice(&hw2.to_le_bytes());
3851
3852 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3855 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3856 bytes.extend_from_slice(&hw1.to_le_bytes());
3857 bytes.extend_from_slice(&hw2.to_le_bytes());
3858
3859 let b_done: u16 = 0xE006;
3862 bytes.extend_from_slice(&b_done.to_le_bytes());
3863
3864 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3866
3867 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3871 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3872 bytes.extend_from_slice(&hw1.to_le_bytes());
3873 bytes.extend_from_slice(&hw2.to_le_bytes());
3874
3875 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3878 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3879 bytes.extend_from_slice(&hw1.to_le_bytes());
3880 bytes.extend_from_slice(&hw2.to_le_bytes());
3881
3882 let hw1: u16 = (0xF100 | rd_bits) as u16;
3884 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3885 bytes.extend_from_slice(&hw1.to_le_bytes());
3886 bytes.extend_from_slice(&hw2.to_le_bytes());
3887
3888 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3891 bytes.extend_from_slice(&mov0.to_le_bytes());
3892
3893 Ok(bytes)
3894 }
3895
3896 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3900 let rd_bits = reg_to_bits(rd);
3901 let rn_lo_bits = reg_to_bits(rnlo);
3902 let rn_hi_bits = reg_to_bits(rnhi);
3903 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3906
3907 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3909
3910 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3920 bytes.extend_from_slice(&mov.to_le_bytes());
3921
3922 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3925 bytes.extend_from_slice(&mov.to_le_bytes());
3926
3927 let hw1: u16 = 0xEA4F;
3931 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3932 bytes.extend_from_slice(&hw1.to_le_bytes());
3933 bytes.extend_from_slice(&hw2.to_le_bytes());
3934
3935 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3938 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3939 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3941 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3942
3943 let hw1: u16 = (0xEA00 | r12) as u16;
3945 let hw2: u16 = ((r12 << 8) | r3) as u16;
3946 bytes.extend_from_slice(&hw1.to_le_bytes());
3947 bytes.extend_from_slice(&hw2.to_le_bytes());
3948
3949 let hw1: u16 = (0xEBA0 | 4) as u16;
3951 let hw2: u16 = ((4 << 8) | r12) as u16;
3952 bytes.extend_from_slice(&hw1.to_le_bytes());
3953 bytes.extend_from_slice(&hw2.to_le_bytes());
3954
3955 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3959 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3960 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3962 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3963
3964 let hw1: u16 = (0xEA00 | 4) as u16;
3966 let hw2: u16 = ((r12 << 8) | r3) as u16;
3967 bytes.extend_from_slice(&hw1.to_le_bytes());
3968 bytes.extend_from_slice(&hw2.to_le_bytes());
3969
3970 let hw1: u16 = 0xEA4F;
3972 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3973 bytes.extend_from_slice(&hw1.to_le_bytes());
3974 bytes.extend_from_slice(&hw2.to_le_bytes());
3975
3976 let hw1: u16 = (0xEA00 | 4) as u16;
3978 let hw2: u16 = ((4 << 8) | r3) as u16;
3979 bytes.extend_from_slice(&hw1.to_le_bytes());
3980 bytes.extend_from_slice(&hw2.to_le_bytes());
3981
3982 let hw1: u16 = (0xEB00 | 4) as u16;
3984 let hw2: u16 = ((4 << 8) | r12) as u16;
3985 bytes.extend_from_slice(&hw1.to_le_bytes());
3986 bytes.extend_from_slice(&hw2.to_le_bytes());
3987
3988 let hw1: u16 = 0xEA4F;
3993 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3994 bytes.extend_from_slice(&hw1.to_le_bytes());
3995 bytes.extend_from_slice(&hw2.to_le_bytes());
3996
3997 let hw1: u16 = (0xEB00 | 4) as u16;
3999 let hw2: u16 = ((4 << 8) | r12) as u16;
4000 bytes.extend_from_slice(&hw1.to_le_bytes());
4001 bytes.extend_from_slice(&hw2.to_le_bytes());
4002
4003 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4008 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4009 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4011 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4012
4013 let hw1: u16 = (0xEA00 | 4) as u16;
4015 let hw2: u16 = ((4 << 8) | r3) as u16;
4016 bytes.extend_from_slice(&hw1.to_le_bytes());
4017 bytes.extend_from_slice(&hw2.to_le_bytes());
4018
4019 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4023 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4024 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4026 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4027
4028 let hw1: u16 = (0xFB00 | 4) as u16;
4031 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
4032 bytes.extend_from_slice(&hw1.to_le_bytes());
4033 bytes.extend_from_slice(&hw2.to_le_bytes());
4034
4035 let hw1: u16 = 0xEA4F;
4038 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
4039 bytes.extend_from_slice(&hw1.to_le_bytes());
4040 bytes.extend_from_slice(&hw2.to_le_bytes());
4041
4042 let hw1: u16 = 0xEA4F;
4045 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
4046 bytes.extend_from_slice(&hw1.to_le_bytes());
4047 bytes.extend_from_slice(&hw2.to_le_bytes());
4048
4049 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
4051 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
4052 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
4053 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
4054
4055 let hw1: u16 = (0xEA00 | r12) as u16;
4056 let hw2: u16 = ((r12 << 8) | r3) as u16;
4057 bytes.extend_from_slice(&hw1.to_le_bytes());
4058 bytes.extend_from_slice(&hw2.to_le_bytes());
4059
4060 let hw1: u16 = (0xEBA0 | 5) as u16;
4061 let hw2: u16 = ((5 << 8) | r12) as u16;
4062 bytes.extend_from_slice(&hw1.to_le_bytes());
4063 bytes.extend_from_slice(&hw2.to_le_bytes());
4064
4065 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
4067 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4068 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
4069 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4070
4071 let hw1: u16 = (0xEA00 | 5) as u16;
4072 let hw2: u16 = ((r12 << 8) | r3) as u16;
4073 bytes.extend_from_slice(&hw1.to_le_bytes());
4074 bytes.extend_from_slice(&hw2.to_le_bytes());
4075
4076 let hw1: u16 = 0xEA4F;
4077 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
4078 bytes.extend_from_slice(&hw1.to_le_bytes());
4079 bytes.extend_from_slice(&hw2.to_le_bytes());
4080
4081 let hw1: u16 = (0xEA00 | 5) as u16;
4082 let hw2: u16 = ((5 << 8) | r3) as u16;
4083 bytes.extend_from_slice(&hw1.to_le_bytes());
4084 bytes.extend_from_slice(&hw2.to_le_bytes());
4085
4086 let hw1: u16 = (0xEB00 | 5) as u16;
4087 let hw2: u16 = ((5 << 8) | r12) as u16;
4088 bytes.extend_from_slice(&hw1.to_le_bytes());
4089 bytes.extend_from_slice(&hw2.to_le_bytes());
4090
4091 let hw1: u16 = 0xEA4F;
4094 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
4095 bytes.extend_from_slice(&hw1.to_le_bytes());
4096 bytes.extend_from_slice(&hw2.to_le_bytes());
4097
4098 let hw1: u16 = (0xEB00 | 5) as u16;
4099 let hw2: u16 = ((5 << 8) | r12) as u16;
4100 bytes.extend_from_slice(&hw1.to_le_bytes());
4101 bytes.extend_from_slice(&hw2.to_le_bytes());
4102
4103 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4105 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4106 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4107 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4108
4109 let hw1: u16 = (0xEA00 | 5) as u16;
4110 let hw2: u16 = ((5 << 8) | r3) as u16;
4111 bytes.extend_from_slice(&hw1.to_le_bytes());
4112 bytes.extend_from_slice(&hw2.to_le_bytes());
4113
4114 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4116 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4117 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4118 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4119
4120 let hw1: u16 = (0xFB00 | 5) as u16;
4123 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
4124 bytes.extend_from_slice(&hw1.to_le_bytes());
4125 bytes.extend_from_slice(&hw2.to_le_bytes());
4126
4127 let hw1: u16 = 0xEA4F;
4130 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
4131 bytes.extend_from_slice(&hw1.to_le_bytes());
4132 bytes.extend_from_slice(&hw2.to_le_bytes());
4133
4134 let rd_bits_u16 = rd_bits as u16;
4137 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4138 bytes.extend_from_slice(&instr.to_le_bytes());
4139
4140 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4142
4143 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4145 bytes.extend_from_slice(&mov0.to_le_bytes());
4146
4147 Ok(bytes)
4148 }
4149
4150 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4153 let rdlo_bits = reg_to_bits(rdlo);
4154 let rdhi_bits = reg_to_bits(rdhi);
4155 let rnlo_bits = reg_to_bits(rnlo);
4156 let mut bytes = Vec::new();
4157
4158 let hw1: u16 = 0xFA4F_u16;
4161 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4162 bytes.extend_from_slice(&hw1.to_le_bytes());
4163 bytes.extend_from_slice(&hw2.to_le_bytes());
4164
4165 let hw1: u16 = 0xEA4F;
4170 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4171 bytes.extend_from_slice(&hw1.to_le_bytes());
4172 bytes.extend_from_slice(&hw2.to_le_bytes());
4173
4174 Ok(bytes)
4175 }
4176
4177 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4180 let rdlo_bits = reg_to_bits(rdlo);
4181 let rdhi_bits = reg_to_bits(rdhi);
4182 let rnlo_bits = reg_to_bits(rnlo);
4183 let mut bytes = Vec::new();
4184
4185 let hw1: u16 = 0xFA0F_u16;
4188 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4189 bytes.extend_from_slice(&hw1.to_le_bytes());
4190 bytes.extend_from_slice(&hw2.to_le_bytes());
4191
4192 let hw1: u16 = 0xEA4F;
4194 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4195 bytes.extend_from_slice(&hw1.to_le_bytes());
4196 bytes.extend_from_slice(&hw2.to_le_bytes());
4197
4198 Ok(bytes)
4199 }
4200
4201 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4204 let rdlo_bits = reg_to_bits(rdlo);
4205 let rdhi_bits = reg_to_bits(rdhi);
4206 let rnlo_bits = reg_to_bits(rnlo);
4207 let mut bytes = Vec::new();
4208
4209 if rdlo_bits != rnlo_bits {
4211 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4213 let mov: u16 = 0x4600
4214 | (d_bit << 7)
4215 | ((rnlo_bits as u16) << 3)
4216 | ((rdlo_bits & 0x7) as u16);
4217 bytes.extend_from_slice(&mov.to_le_bytes());
4218 }
4219
4220 let hw1: u16 = 0xEA4F;
4222 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4223 bytes.extend_from_slice(&hw1.to_le_bytes());
4224 bytes.extend_from_slice(&hw2.to_le_bytes());
4225
4226 Ok(bytes)
4227 }
4228
4229 ArmOp::SelectMove { rd, rm, cond } => {
4232 let rd_bits = reg_to_bits(rd) as u16;
4233 let rm_bits = reg_to_bits(rm) as u16;
4234
4235 use synth_synthesis::Condition;
4237 let cond_bits: u16 = match cond {
4238 Condition::EQ => 0x0, Condition::NE => 0x1, Condition::HS => 0x2, Condition::LO => 0x3, Condition::HI => 0x8, Condition::LS => 0x9, Condition::GE => 0xA, Condition::LT => 0xB, Condition::GT => 0xC, Condition::LE => 0xD, };
4249
4250 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4253
4254 let d_bit = (rd_bits >> 3) & 1;
4257 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4258
4259 let mut bytes = it_instr.to_le_bytes().to_vec();
4261 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4262 Ok(bytes)
4263 }
4264
4265 ArmOp::Popcnt { rd, rm } => {
4276 let mut bytes = Vec::new();
4277
4278 if rd != rm {
4280 let rd_bits = reg_to_bits(rd) as u16;
4281 let rm_bits = reg_to_bits(rm) as u16;
4282 let d_bit = (rd_bits >> 3) & 1;
4284 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4285 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4286 }
4287
4288 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4291 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4292
4293 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4296
4297 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4299
4300 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4302 reg_to_bits(rd),
4303 reg_to_bits(rd),
4304 11,
4305 )?);
4306
4307 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4310 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4311
4312 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4314 11,
4315 reg_to_bits(rd),
4316 12,
4317 )?);
4318
4319 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4321 reg_to_bits(rd),
4322 reg_to_bits(rd),
4323 2,
4324 )?);
4325
4326 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4328 reg_to_bits(rd),
4329 reg_to_bits(rd),
4330 12,
4331 )?);
4332
4333 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4335 reg_to_bits(rd),
4336 reg_to_bits(rd),
4337 11,
4338 )?);
4339
4340 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4343
4344 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4346 reg_to_bits(rd),
4347 reg_to_bits(rd),
4348 11,
4349 )?);
4350
4351 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4353 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4354
4355 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4357 reg_to_bits(rd),
4358 reg_to_bits(rd),
4359 12,
4360 )?);
4361
4362 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4365
4366 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4368 reg_to_bits(rd),
4369 reg_to_bits(rd),
4370 11,
4371 )?);
4372
4373 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4376
4377 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4379 reg_to_bits(rd),
4380 reg_to_bits(rd),
4381 11,
4382 )?);
4383
4384 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4387 reg_to_bits(rd),
4388 reg_to_bits(rd),
4389 0x3F,
4390 )?);
4391
4392 Ok(bytes)
4393 }
4394
4395 ArmOp::I64DivU {
4400 rdlo: _,
4401 rdhi: _,
4402 rnlo: _,
4403 rnhi: _,
4404 rmlo: _,
4405 rmhi: _,
4406 } => {
4407 let mut bytes = Vec::new();
4408
4409 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4413
4414 bytes.extend_from_slice(&0x2400u16.to_le_bytes()); bytes.extend_from_slice(&0x2500u16.to_le_bytes()); bytes.extend_from_slice(&0x2600u16.to_le_bytes()); bytes.extend_from_slice(&0x2700u16.to_le_bytes()); bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4425 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4426
4427 let loop_start = bytes.len();
4429
4430 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4441 bytes.extend_from_slice(&0x75D4u16.to_le_bytes()); bytes.extend_from_slice(&0x0064u16.to_le_bytes()); bytes.extend_from_slice(&0x007Fu16.to_le_bytes()); bytes.extend_from_slice(&0xEA47u16.to_le_bytes());
4450 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4451 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4455 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4456
4457 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4462 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4463 bytes.extend_from_slice(&0x0040u16.to_le_bytes()); bytes.extend_from_slice(&0x429Fu16.to_le_bytes()); bytes.extend_from_slice(&0xD802u16.to_le_bytes()); bytes.extend_from_slice(&0xD306u16.to_le_bytes()); bytes.extend_from_slice(&0x4296u16.to_le_bytes()); bytes.extend_from_slice(&0xD304u16.to_le_bytes()); bytes.extend_from_slice(&0x1AB6u16.to_le_bytes()); bytes.extend_from_slice(&0xEB67u16.to_le_bytes());
4494 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4495 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4498
4499 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4503 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4504
4505 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4508 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4509 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4510
4511 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4519
4520 Ok(bytes)
4521 }
4522
4523 ArmOp::I64DivS {
4528 rdlo: _,
4529 rdhi: _,
4530 rnlo: _,
4531 rnhi: _,
4532 rmlo: _,
4533 rmhi: _,
4534 } => {
4535 let mut bytes = Vec::new();
4536
4537 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4539 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4540
4541 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4544 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4545
4546 bytes.extend_from_slice(&0x4209u16.to_le_bytes()); bytes.extend_from_slice(&0xD504u16.to_le_bytes()); bytes.extend_from_slice(&0x43C0u16.to_le_bytes()); bytes.extend_from_slice(&0x43C9u16.to_le_bytes()); bytes.extend_from_slice(&0x1C40u16.to_le_bytes()); bytes.extend_from_slice(&0xF141u16.to_le_bytes()); bytes.extend_from_slice(&0x0100u16.to_le_bytes());
4559
4560 bytes.extend_from_slice(&0x421Bu16.to_le_bytes()); bytes.extend_from_slice(&0xD504u16.to_le_bytes()); bytes.extend_from_slice(&0x43D2u16.to_le_bytes()); bytes.extend_from_slice(&0x43DBu16.to_le_bytes()); bytes.extend_from_slice(&0x1C52u16.to_le_bytes()); bytes.extend_from_slice(&0xF143u16.to_le_bytes()); bytes.extend_from_slice(&0x0300u16.to_le_bytes());
4570
4571 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4574 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4575 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4577 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4578 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4580 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4581
4582 let loop_start = bytes.len();
4583
4584 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4588 bytes.extend_from_slice(&0x0064u16.to_le_bytes()); bytes.extend_from_slice(&0x007Fu16.to_le_bytes()); bytes.extend_from_slice(&0xEA47u16.to_le_bytes()); bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4594 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4597
4598 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4602 bytes.extend_from_slice(&0x0040u16.to_le_bytes()); bytes.extend_from_slice(&0x429Fu16.to_le_bytes()); bytes.extend_from_slice(&0xD802u16.to_le_bytes()); bytes.extend_from_slice(&0xD306u16.to_le_bytes()); bytes.extend_from_slice(&0x4296u16.to_le_bytes()); bytes.extend_from_slice(&0xD304u16.to_le_bytes()); bytes.extend_from_slice(&0x1AB6u16.to_le_bytes()); bytes.extend_from_slice(&0xEB67u16.to_le_bytes()); bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4615 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4617
4618 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4621
4622 let branch_offset_bytes = bytes.len() - loop_start + 4;
4623 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4624 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4625 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4626
4627 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xF1B9u16.to_le_bytes()); bytes.extend_from_slice(&0x0F00u16.to_le_bytes());
4634 bytes.extend_from_slice(&0xD504u16.to_le_bytes()); bytes.extend_from_slice(&0x43C0u16.to_le_bytes()); bytes.extend_from_slice(&0x43C9u16.to_le_bytes()); bytes.extend_from_slice(&0x1C40u16.to_le_bytes()); bytes.extend_from_slice(&0xF141u16.to_le_bytes()); bytes.extend_from_slice(&0x0100u16.to_le_bytes());
4642
4643 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4645 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4646
4647 Ok(bytes)
4648 }
4649
4650 ArmOp::I64RemU {
4655 rdlo: _,
4656 rdhi: _,
4657 rnlo: _,
4658 rnhi: _,
4659 rmlo: _,
4660 rmhi: _,
4661 } => {
4662 let mut bytes = Vec::new();
4663
4664 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4666 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4667
4668 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4670 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4671 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4673 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4674 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4676 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4677
4678 let loop_start = bytes.len();
4679
4680 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4684 bytes.extend_from_slice(&0x0064u16.to_le_bytes()); bytes.extend_from_slice(&0x007Fu16.to_le_bytes()); bytes.extend_from_slice(&0xEA47u16.to_le_bytes()); bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4690 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4693
4694 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4698 bytes.extend_from_slice(&0x0040u16.to_le_bytes()); bytes.extend_from_slice(&0x429Fu16.to_le_bytes()); bytes.extend_from_slice(&0xD802u16.to_le_bytes()); bytes.extend_from_slice(&0xD306u16.to_le_bytes()); bytes.extend_from_slice(&0x4296u16.to_le_bytes()); bytes.extend_from_slice(&0xD304u16.to_le_bytes()); bytes.extend_from_slice(&0x1AB6u16.to_le_bytes()); bytes.extend_from_slice(&0xEB67u16.to_le_bytes()); bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4711 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4713
4714 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4717
4718 let branch_offset_bytes = bytes.len() - loop_start + 4;
4719 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4720 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4721 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4722
4723 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4729 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4730
4731 Ok(bytes)
4732 }
4733
4734 ArmOp::I64RemS {
4739 rdlo: _,
4740 rdhi: _,
4741 rnlo: _,
4742 rnhi: _,
4743 rmlo: _,
4744 rmhi: _,
4745 } => {
4746 let mut bytes = Vec::new();
4747
4748 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4750 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4751
4752 bytes.extend_from_slice(&0x4689u16.to_le_bytes()); bytes.extend_from_slice(&0x4209u16.to_le_bytes()); bytes.extend_from_slice(&0xD504u16.to_le_bytes()); bytes.extend_from_slice(&0x43C0u16.to_le_bytes()); bytes.extend_from_slice(&0x43C9u16.to_le_bytes()); bytes.extend_from_slice(&0x1C40u16.to_le_bytes()); bytes.extend_from_slice(&0xF141u16.to_le_bytes()); bytes.extend_from_slice(&0x0100u16.to_le_bytes());
4766
4767 bytes.extend_from_slice(&0x421Bu16.to_le_bytes()); bytes.extend_from_slice(&0xD504u16.to_le_bytes()); bytes.extend_from_slice(&0x43D2u16.to_le_bytes()); bytes.extend_from_slice(&0x43DBu16.to_le_bytes()); bytes.extend_from_slice(&0x1C52u16.to_le_bytes()); bytes.extend_from_slice(&0xF143u16.to_le_bytes()); bytes.extend_from_slice(&0x0300u16.to_le_bytes());
4777
4778 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4781 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4782 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4784 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4785 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4787 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4788
4789 let loop_start = bytes.len();
4790
4791 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4795 bytes.extend_from_slice(&0x0064u16.to_le_bytes()); bytes.extend_from_slice(&0x007Fu16.to_le_bytes()); bytes.extend_from_slice(&0xEA47u16.to_le_bytes()); bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4801 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4804
4805 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4809 bytes.extend_from_slice(&0x0040u16.to_le_bytes()); bytes.extend_from_slice(&0x429Fu16.to_le_bytes()); bytes.extend_from_slice(&0xD802u16.to_le_bytes()); bytes.extend_from_slice(&0xD306u16.to_le_bytes()); bytes.extend_from_slice(&0x4296u16.to_le_bytes()); bytes.extend_from_slice(&0xD304u16.to_le_bytes()); bytes.extend_from_slice(&0x1AB6u16.to_le_bytes()); bytes.extend_from_slice(&0xEB67u16.to_le_bytes()); bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4822 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4824
4825 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4828
4829 let branch_offset_bytes = bytes.len() - loop_start + 4;
4830 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4831 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4832 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4833
4834 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xF1B9u16.to_le_bytes()); bytes.extend_from_slice(&0x0F00u16.to_le_bytes());
4841 bytes.extend_from_slice(&0xD504u16.to_le_bytes()); bytes.extend_from_slice(&0x43C0u16.to_le_bytes()); bytes.extend_from_slice(&0x43C9u16.to_le_bytes()); bytes.extend_from_slice(&0x1C40u16.to_le_bytes()); bytes.extend_from_slice(&0xF141u16.to_le_bytes()); bytes.extend_from_slice(&0x0100u16.to_le_bytes());
4849
4850 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4852 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4853
4854 Ok(bytes)
4855 }
4856
4857 ArmOp::F32Add { sd, sn, sm } => {
4860 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4861 }
4862 ArmOp::F32Sub { sd, sn, sm } => {
4863 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4864 }
4865 ArmOp::F32Mul { sd, sn, sm } => {
4866 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4867 }
4868 ArmOp::F32Div { sd, sn, sm } => {
4869 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4870 }
4871 ArmOp::F32Abs { sd, sm } => {
4872 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4873 }
4874 ArmOp::F32Neg { sd, sm } => {
4875 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4876 }
4877 ArmOp::F32Sqrt { sd, sm } => {
4878 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4879 }
4880
4881 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4884 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4885 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4886 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4887 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4888 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4889 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4890
4891 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4893 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4894 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4895 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4896 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4897 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4898
4899 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4900
4901 ArmOp::F32Load { sd, addr } => {
4902 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4903 }
4904 ArmOp::F32Store { sd, addr } => {
4905 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4906 }
4907
4908 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4909 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4910 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4911 Err(synth_core::Error::synthesis(
4912 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4913 ))
4914 }
4915 ArmOp::F32ReinterpretI32 { sd, rm } => {
4916 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4917 }
4918 ArmOp::I32ReinterpretF32 { rd, sm } => {
4919 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4920 }
4921 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4922 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4923
4924 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4927 0xEE300B00, dd, dn, dm,
4928 )?)),
4929 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4930 0xEE300B40, dd, dn, dm,
4931 )?)),
4932 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4933 0xEE200B00, dd, dn, dm,
4934 )?)),
4935 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4936 0xEE800B00, dd, dn, dm,
4937 )?)),
4938 ArmOp::F64Abs { dd, dm } => {
4939 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4940 }
4941 ArmOp::F64Neg { dd, dm } => {
4942 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4943 }
4944 ArmOp::F64Sqrt { dd, dm } => {
4945 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4946 }
4947
4948 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4951 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4952 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4953 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4954 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4955 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4956 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4957
4958 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4960 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4961 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4962 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4963 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4964 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4965
4966 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4967
4968 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4969 0xED900B00, dd, addr,
4970 )?)),
4971 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4972 0xED800B00, dd, addr,
4973 )?)),
4974
4975 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4976 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4977 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4978 Err(synth_core::Error::synthesis(
4979 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4980 ))
4981 }
4982 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4983 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4984 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4985 )),
4986 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4987 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4988 )),
4989 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4990 Err(synth_core::Error::synthesis(
4991 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4992 ))
4993 }
4994 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4995 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4996
4997 ArmOp::I64Add {
5001 rdlo,
5002 rdhi,
5003 rnlo,
5004 rnhi,
5005 rmlo,
5006 rmhi,
5007 } => {
5008 let mut bytes = Vec::new();
5009 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
5011 rd: *rdlo,
5012 rn: *rnlo,
5013 op2: Operand2::Reg(*rmlo),
5014 })?);
5015 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
5017 rd: *rdhi,
5018 rn: *rnhi,
5019 op2: Operand2::Reg(*rmhi),
5020 })?);
5021 Ok(bytes)
5022 }
5023
5024 ArmOp::I64Sub {
5026 rdlo,
5027 rdhi,
5028 rnlo,
5029 rnhi,
5030 rmlo,
5031 rmhi,
5032 } => {
5033 let mut bytes = Vec::new();
5034 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
5036 rd: *rdlo,
5037 rn: *rnlo,
5038 op2: Operand2::Reg(*rmlo),
5039 })?);
5040 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
5042 rd: *rdhi,
5043 rn: *rnhi,
5044 op2: Operand2::Reg(*rmhi),
5045 })?);
5046 Ok(bytes)
5047 }
5048
5049 ArmOp::I64And {
5051 rdlo,
5052 rdhi,
5053 rnlo,
5054 rnhi,
5055 rmlo,
5056 rmhi,
5057 } => {
5058 let mut bytes = Vec::new();
5059 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5060 rd: *rdlo,
5061 rn: *rnlo,
5062 op2: Operand2::Reg(*rmlo),
5063 })?);
5064 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5065 rd: *rdhi,
5066 rn: *rnhi,
5067 op2: Operand2::Reg(*rmhi),
5068 })?);
5069 Ok(bytes)
5070 }
5071
5072 ArmOp::I64Or {
5074 rdlo,
5075 rdhi,
5076 rnlo,
5077 rnhi,
5078 rmlo,
5079 rmhi,
5080 } => {
5081 let mut bytes = Vec::new();
5082 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5083 rd: *rdlo,
5084 rn: *rnlo,
5085 op2: Operand2::Reg(*rmlo),
5086 })?);
5087 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5088 rd: *rdhi,
5089 rn: *rnhi,
5090 op2: Operand2::Reg(*rmhi),
5091 })?);
5092 Ok(bytes)
5093 }
5094
5095 ArmOp::I64Xor {
5097 rdlo,
5098 rdhi,
5099 rnlo,
5100 rnhi,
5101 rmlo,
5102 rmhi,
5103 } => {
5104 let mut bytes = Vec::new();
5105 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5106 rd: *rdlo,
5107 rn: *rnlo,
5108 op2: Operand2::Reg(*rmlo),
5109 })?);
5110 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5111 rd: *rdhi,
5112 rn: *rnhi,
5113 op2: Operand2::Reg(*rmhi),
5114 })?);
5115 Ok(bytes)
5116 }
5117
5118 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
5120 rd: *rd,
5121 rn_lo: *rnlo,
5122 rn_hi: *rnhi,
5123 }),
5124
5125 ArmOp::I64Eq {
5127 rd,
5128 rnlo,
5129 rnhi,
5130 rmlo,
5131 rmhi,
5132 } => self.encode_thumb(&ArmOp::I64SetCond {
5133 rd: *rd,
5134 rn_lo: *rnlo,
5135 rn_hi: *rnhi,
5136 rm_lo: *rmlo,
5137 rm_hi: *rmhi,
5138 cond: synth_synthesis::Condition::EQ,
5139 }),
5140
5141 ArmOp::I64Ne {
5142 rd,
5143 rnlo,
5144 rnhi,
5145 rmlo,
5146 rmhi,
5147 } => self.encode_thumb(&ArmOp::I64SetCond {
5148 rd: *rd,
5149 rn_lo: *rnlo,
5150 rn_hi: *rnhi,
5151 rm_lo: *rmlo,
5152 rm_hi: *rmhi,
5153 cond: synth_synthesis::Condition::NE,
5154 }),
5155
5156 ArmOp::I64LtS {
5157 rd,
5158 rnlo,
5159 rnhi,
5160 rmlo,
5161 rmhi,
5162 } => self.encode_thumb(&ArmOp::I64SetCond {
5163 rd: *rd,
5164 rn_lo: *rnlo,
5165 rn_hi: *rnhi,
5166 rm_lo: *rmlo,
5167 rm_hi: *rmhi,
5168 cond: synth_synthesis::Condition::LT,
5169 }),
5170
5171 ArmOp::I64LtU {
5172 rd,
5173 rnlo,
5174 rnhi,
5175 rmlo,
5176 rmhi,
5177 } => self.encode_thumb(&ArmOp::I64SetCond {
5178 rd: *rd,
5179 rn_lo: *rnlo,
5180 rn_hi: *rnhi,
5181 rm_lo: *rmlo,
5182 rm_hi: *rmhi,
5183 cond: synth_synthesis::Condition::LO,
5184 }),
5185
5186 ArmOp::I64LeS {
5187 rd,
5188 rnlo,
5189 rnhi,
5190 rmlo,
5191 rmhi,
5192 } => self.encode_thumb(&ArmOp::I64SetCond {
5193 rd: *rd,
5194 rn_lo: *rnlo,
5195 rn_hi: *rnhi,
5196 rm_lo: *rmlo,
5197 rm_hi: *rmhi,
5198 cond: synth_synthesis::Condition::LE,
5199 }),
5200
5201 ArmOp::I64LeU {
5202 rd,
5203 rnlo,
5204 rnhi,
5205 rmlo,
5206 rmhi,
5207 } => self.encode_thumb(&ArmOp::I64SetCond {
5208 rd: *rd,
5209 rn_lo: *rnlo,
5210 rn_hi: *rnhi,
5211 rm_lo: *rmlo,
5212 rm_hi: *rmhi,
5213 cond: synth_synthesis::Condition::LS,
5214 }),
5215
5216 ArmOp::I64GtS {
5217 rd,
5218 rnlo,
5219 rnhi,
5220 rmlo,
5221 rmhi,
5222 } => self.encode_thumb(&ArmOp::I64SetCond {
5223 rd: *rd,
5224 rn_lo: *rnlo,
5225 rn_hi: *rnhi,
5226 rm_lo: *rmlo,
5227 rm_hi: *rmhi,
5228 cond: synth_synthesis::Condition::GT,
5229 }),
5230
5231 ArmOp::I64GtU {
5232 rd,
5233 rnlo,
5234 rnhi,
5235 rmlo,
5236 rmhi,
5237 } => self.encode_thumb(&ArmOp::I64SetCond {
5238 rd: *rd,
5239 rn_lo: *rnlo,
5240 rn_hi: *rnhi,
5241 rm_lo: *rmlo,
5242 rm_hi: *rmhi,
5243 cond: synth_synthesis::Condition::HI,
5244 }),
5245
5246 ArmOp::I64GeS {
5247 rd,
5248 rnlo,
5249 rnhi,
5250 rmlo,
5251 rmhi,
5252 } => self.encode_thumb(&ArmOp::I64SetCond {
5253 rd: *rd,
5254 rn_lo: *rnlo,
5255 rn_hi: *rnhi,
5256 rm_lo: *rmlo,
5257 rm_hi: *rmhi,
5258 cond: synth_synthesis::Condition::GE,
5259 }),
5260
5261 ArmOp::I64GeU {
5262 rd,
5263 rnlo,
5264 rnhi,
5265 rmlo,
5266 rmhi,
5267 } => self.encode_thumb(&ArmOp::I64SetCond {
5268 rd: *rd,
5269 rn_lo: *rnlo,
5270 rn_hi: *rnhi,
5271 rm_lo: *rmlo,
5272 rm_hi: *rmhi,
5273 cond: synth_synthesis::Condition::HS,
5274 }),
5275
5276 ArmOp::I64Const { rdlo, rdhi, value } => {
5278 let lo32 = *value as u32;
5279 let hi32 = (*value >> 32) as u32;
5280 let mut bytes = Vec::new();
5281 bytes.extend_from_slice(
5283 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5284 );
5285 if lo32 > 0xFFFF {
5286 bytes.extend_from_slice(
5287 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5288 );
5289 }
5290 bytes.extend_from_slice(
5292 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5293 );
5294 if hi32 > 0xFFFF {
5295 bytes.extend_from_slice(
5296 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5297 );
5298 }
5299 Ok(bytes)
5300 }
5301
5302 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5304 let mut bytes = Vec::new();
5305 let offset = if addr.offset < 0 {
5306 0u32
5307 } else {
5308 addr.offset as u32
5309 };
5310 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5311 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5312 rdhi,
5313 &addr.base,
5314 offset.wrapping_add(4),
5315 )?);
5316 Ok(bytes)
5317 }
5318
5319 ArmOp::I64Str { rdlo, rdhi, addr } => {
5321 let mut bytes = Vec::new();
5322 let offset = if addr.offset < 0 {
5323 0u32
5324 } else {
5325 addr.offset as u32
5326 };
5327 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5328 bytes.extend_from_slice(&self.encode_thumb32_str(
5329 rdhi,
5330 &addr.base,
5331 offset.wrapping_add(4),
5332 )?);
5333 Ok(bytes)
5334 }
5335
5336 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5338 let mut bytes = Vec::new();
5339 if rdlo != rn {
5340 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5342 rd: *rdlo,
5343 op2: Operand2::Reg(*rn),
5344 })?);
5345 }
5346 bytes.extend_from_slice(
5348 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5350 Ok(bytes)
5351 }
5352
5353 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5355 let mut bytes = Vec::new();
5356 if rdlo != rn {
5357 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5359 rd: *rdlo,
5360 op2: Operand2::Reg(*rn),
5361 })?);
5362 }
5363 let rdhi_bits = reg_to_bits(rdhi) as u16;
5365 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5366 bytes.extend_from_slice(&instr.to_le_bytes());
5367 Ok(bytes)
5368 }
5369
5370 ArmOp::I32WrapI64 { rd, rnlo } => {
5372 if rd == rnlo {
5373 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5376 } else {
5377 self.encode_thumb(&ArmOp::Mov {
5379 rd: *rd,
5380 op2: Operand2::Reg(*rnlo),
5381 })
5382 }
5383 }
5384
5385 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5387 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5388 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5389 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5390 0xEF000150, qd, qn, qm,
5391 ))),
5392 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5393 0xEF200150, qd, qn, qm,
5394 ))),
5395 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5396 0xFF000150, qd, qn, qm,
5397 ))),
5398 ArmOp::MveMvn { qd, qm } => {
5399 let qd_enc = qreg_to_num(qd);
5401 let qm_enc = qreg_to_num(qm);
5402 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5403 Ok(vfp_to_thumb_bytes(instr))
5404 }
5405 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5406 0xEF100150, qd, qn, qm,
5407 ))),
5408 ArmOp::MveAddI { qd, qn, qm, size } => {
5409 let sz = mve_size_bits(size);
5410 let base: u32 = 0xEF000840 | (sz << 20);
5411 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5412 }
5413 ArmOp::MveSubI { qd, qn, qm, size } => {
5414 let sz = mve_size_bits(size);
5415 let base: u32 = 0xFF000840 | (sz << 20);
5416 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5417 }
5418 ArmOp::MveMulI { qd, qn, qm, size } => {
5419 let sz = mve_size_bits(size);
5420 let base: u32 = 0xEF000950 | (sz << 20);
5421 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5422 }
5423 ArmOp::MveNegI { qd, qm, size } => {
5424 let sz = mve_size_bits(size);
5425 let qd_enc = qreg_to_num(qd);
5427 let qm_enc = qreg_to_num(qm);
5428 let base: u32 = 0xFFB103C0 | (sz << 18);
5429 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5430 Ok(vfp_to_thumb_bytes(instr))
5431 }
5432 ArmOp::MveDup { qd, rn, size } => {
5433 let sz = mve_size_bits(size);
5434 let qd_enc = qreg_to_num(qd);
5435 let rn_bits = reg_to_bits(rn);
5436 let be = match sz {
5439 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5443 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5444 Ok(vfp_to_thumb_bytes(instr))
5445 }
5446 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5447 let qn_enc = qreg_to_num(qn);
5448 let rd_bits = reg_to_bits(rd);
5449 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5452 let lane_in_d = (*lane as u32) & 1;
5453 let _sz = mve_size_bits(size);
5454 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5456 Ok(vfp_to_thumb_bytes(instr))
5457 }
5458 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5459 let qd_enc = qreg_to_num(qd);
5460 let rn_bits = reg_to_bits(rn);
5461 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5462 let lane_in_d = (*lane as u32) & 1;
5463 let _sz = mve_size_bits(size);
5464 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5466 Ok(vfp_to_thumb_bytes(instr))
5467 }
5468
5469 ArmOp::MveCmpEqI { qd, qn, qm, size }
5471 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5472 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5473 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5474 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5475 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5476 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5477 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5478 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5479 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5480 let sz = mve_size_bits(size);
5483 let base: u32 = 0xEF000840 | (sz << 20);
5484 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5485 }
5486
5487 ArmOp::MveAddF32 { qd, qn, qm } => {
5489 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5491 }
5492 ArmOp::MveSubF32 { qd, qn, qm } => {
5493 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5495 }
5496 ArmOp::MveMulF32 { qd, qn, qm } => {
5497 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5499 }
5500 ArmOp::MveNegF32 { qd, qm } => {
5501 let qd_enc = qreg_to_num(qd);
5502 let qm_enc = qreg_to_num(qm);
5503 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5505 Ok(vfp_to_thumb_bytes(instr))
5506 }
5507 ArmOp::MveAbsF32 { qd, qm } => {
5508 let qd_enc = qreg_to_num(qd);
5509 let qm_enc = qreg_to_num(qm);
5510 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5512 Ok(vfp_to_thumb_bytes(instr))
5513 }
5514 ArmOp::MveCmpEqF32 { qd, qn, qm }
5515 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5516 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5517 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5518 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5519 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5520 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5522 }
5523 ArmOp::MveDupF32 { qd, rn } => {
5524 let qd_enc = qreg_to_num(qd);
5525 let rn_bits = reg_to_bits(rn);
5526 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5528 Ok(vfp_to_thumb_bytes(instr))
5529 }
5530 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5531 let qn_enc = qreg_to_num(qn);
5532 let rd_bits = reg_to_bits(rd);
5533 let s_num = qn_enc * 4 + (*lane as u32);
5535 let (vn, n) = encode_sreg(s_num);
5536 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5537 Ok(vfp_to_thumb_bytes(instr))
5538 }
5539 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5540 let qd_enc = qreg_to_num(qd);
5541 let rn_bits = reg_to_bits(rn);
5542 let s_num = qd_enc * 4 + (*lane as u32);
5544 let (vn, n) = encode_sreg(s_num);
5545 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5546 Ok(vfp_to_thumb_bytes(instr))
5547 }
5548 ArmOp::MveDivF32 { qd, qn, qm } => {
5549 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5551 }
5552 ArmOp::MveSqrtF32 { qd, qm } => {
5553 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5555 }
5556
5557 _ => {
5559 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5561 }
5562 }
5563 }
5564
5565 fn encode_thumb_f32_compare(
5569 &self,
5570 rd: &Reg,
5571 sn: &VfpReg,
5572 sm: &VfpReg,
5573 cond_code: u32,
5574 ) -> Result<Vec<u8>> {
5575 let mut bytes = Vec::new();
5576 let rd_bits = reg_to_bits(rd);
5577
5578 let sn_num = vfp_sreg_to_num(sn)?;
5580 let sm_num = vfp_sreg_to_num(sm)?;
5581 let (vd, d) = encode_sreg(sn_num);
5582 let (vm, m) = encode_sreg(sm_num);
5583 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5584 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5585
5586 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5588
5589 if rd_bits < 8 {
5591 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5592 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5593 } else {
5594 let hw1: u16 = 0xF04F;
5596 let hw2: u16 = (rd_bits as u16) << 8;
5597 bytes.extend_from_slice(&hw1.to_le_bytes());
5598 bytes.extend_from_slice(&hw2.to_le_bytes());
5599 }
5600
5601 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5605 bytes.extend_from_slice(&it.to_le_bytes());
5606
5607 if rd_bits < 8 {
5609 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5610 bytes.extend_from_slice(&mov_one.to_le_bytes());
5611 } else {
5612 let hw1: u16 = 0xF04F;
5614 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5615 bytes.extend_from_slice(&hw1.to_le_bytes());
5616 bytes.extend_from_slice(&hw2.to_le_bytes());
5617 }
5618
5619 Ok(bytes)
5620 }
5621
5622 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5624 let mut bytes = Vec::new();
5625 let bits = value.to_bits();
5626 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5631 let imm4 = (lo16 >> 12) & 0xF;
5632 let i_bit = (lo16 >> 11) & 1;
5633 let imm3 = (lo16 >> 8) & 0x7;
5634 let imm8 = lo16 & 0xFF;
5635 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5636 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5637 bytes.extend_from_slice(&hw1.to_le_bytes());
5638 bytes.extend_from_slice(&hw2.to_le_bytes());
5639
5640 let hi16 = (bits >> 16) & 0xFFFF;
5642 let imm4 = (hi16 >> 12) & 0xF;
5643 let i_bit = (hi16 >> 11) & 1;
5644 let imm3 = (hi16 >> 8) & 0x7;
5645 let imm8 = hi16 & 0xFF;
5646 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5647 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5648 bytes.extend_from_slice(&hw1.to_le_bytes());
5649 bytes.extend_from_slice(&hw2.to_le_bytes());
5650
5651 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5653 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5654
5655 Ok(bytes)
5656 }
5657
5658 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5660 let mut bytes = Vec::new();
5661
5662 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5664 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5665
5666 let sd_num = vfp_sreg_to_num(sd)?;
5668 let (vd, d) = encode_sreg(sd_num);
5669 let (vm, m) = encode_sreg(sd_num);
5670 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5671 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5672 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5673
5674 Ok(bytes)
5675 }
5676
5677 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5685 let mut bytes = Vec::new();
5686 let sm_num = vfp_sreg_to_num(sm)?;
5687 let sd_num = vfp_sreg_to_num(sd)?;
5688 let (vd_s, d_s) = encode_sreg(sd_num);
5689 let (vm_s, m_s) = encode_sreg(sm_num);
5690
5691 if mode == 0b11 {
5692 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5694 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5695 } else {
5696 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5701 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5702
5703 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5709 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5710 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5711
5712 if mode != 0 {
5714 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5716 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5717 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5718 }
5719
5720 let vmsr = 0xEEE10A10 | (rt << 12);
5722 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5723
5724 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5726 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5727
5728 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5730 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5731 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5732 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5733 }
5734
5735 let (vd2, d2) = encode_sreg(sd_num);
5737 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5738 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5739
5740 Ok(bytes)
5741 }
5742
5743 fn encode_thumb_f32_minmax(
5745 &self,
5746 sd: &VfpReg,
5747 sn: &VfpReg,
5748 sm: &VfpReg,
5749 is_min: bool,
5750 ) -> Result<Vec<u8>> {
5751 let mut bytes = Vec::new();
5752 let sn_num = vfp_sreg_to_num(sn)?;
5753 let sm_num = vfp_sreg_to_num(sm)?;
5754 let sd_num = vfp_sreg_to_num(sd)?;
5755
5756 let (vd, d) = encode_sreg(sd_num);
5758 let (vn, n) = encode_sreg(sn_num);
5759 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5760 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5761
5762 let (vm, m) = encode_sreg(sm_num);
5764 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5765 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5766
5767 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5769
5770 let cond: u16 = if is_min { 0xC } else { 0x4 };
5772 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5773 bytes.extend_from_slice(&it.to_le_bytes());
5774
5775 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5777 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5778
5779 Ok(bytes)
5780 }
5781
5782 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5784 let mut bytes = Vec::new();
5785
5786 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5788 false,
5789 sm,
5790 &Reg::R12,
5791 )?));
5792
5793 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5795 false,
5796 sn,
5797 &Reg::R0,
5798 )?));
5799
5800 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5812 bytes.extend_from_slice(&hw2.to_le_bytes());
5813
5814 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5818 bytes.extend_from_slice(&hw2.to_le_bytes());
5819
5820 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5824 bytes.extend_from_slice(&hw2.to_le_bytes());
5825
5826 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5828 true,
5829 sd,
5830 &Reg::R0,
5831 )?));
5832
5833 Ok(bytes)
5834 }
5835
5836 fn encode_thumb_f64_compare(
5838 &self,
5839 rd: &Reg,
5840 dn: &VfpReg,
5841 dm: &VfpReg,
5842 cond_code: u32,
5843 ) -> Result<Vec<u8>> {
5844 let mut bytes = Vec::new();
5845 let rd_bits = reg_to_bits(rd);
5846
5847 let dn_num = vfp_dreg_to_num(dn)?;
5849 let dm_num = vfp_dreg_to_num(dm)?;
5850 let (vd, d) = encode_dreg(dn_num);
5851 let (vm, m) = encode_dreg(dm_num);
5852 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5853 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5854
5855 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5857
5858 if rd_bits < 8 {
5860 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5861 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5862 } else {
5863 let hw1: u16 = 0xF04F;
5864 let hw2: u16 = (rd_bits as u16) << 8;
5865 bytes.extend_from_slice(&hw1.to_le_bytes());
5866 bytes.extend_from_slice(&hw2.to_le_bytes());
5867 }
5868
5869 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5871 bytes.extend_from_slice(&it.to_le_bytes());
5872
5873 if rd_bits < 8 {
5875 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5876 bytes.extend_from_slice(&mov_one.to_le_bytes());
5877 } else {
5878 let hw1: u16 = 0xF04F;
5879 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5880 bytes.extend_from_slice(&hw1.to_le_bytes());
5881 bytes.extend_from_slice(&hw2.to_le_bytes());
5882 }
5883
5884 Ok(bytes)
5885 }
5886
5887 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5889 let mut bytes = Vec::new();
5890 let bits = value.to_bits();
5891 let lo32 = bits as u32;
5892 let hi32 = (bits >> 32) as u32;
5893
5894 let lo16 = lo32 & 0xFFFF;
5896 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5897
5898 let hi16 = (lo32 >> 16) & 0xFFFF;
5900 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5901
5902 let lo16 = hi32 & 0xFFFF;
5904 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5905
5906 let hi16 = (hi32 >> 16) & 0xFFFF;
5908 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5909
5910 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5912 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5913
5914 Ok(bytes)
5915 }
5916
5917 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5919 let mut bytes = Vec::new();
5920
5921 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5923 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5924
5925 let dd_num = vfp_dreg_to_num(dd)?;
5927 let (vd, d) = encode_dreg(dd_num);
5928 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5929 let vcvt = base | (d << 22) | (vd << 12);
5930 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5931
5932 Ok(bytes)
5933 }
5934
5935 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5937 let dd_num = vfp_dreg_to_num(dd)?;
5938 let sm_num = vfp_sreg_to_num(sm)?;
5939 let (vd, d) = encode_dreg(dd_num);
5940 let (vm, m) = encode_sreg(sm_num);
5941
5942 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5943 Ok(vfp_to_thumb_bytes(vcvt))
5944 }
5945
5946 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5948 let mut bytes = Vec::new();
5949 let dm_num = vfp_dreg_to_num(dm)?;
5950 let (vm, m) = encode_dreg(dm_num);
5951
5952 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5954 let vcvt = base | (m << 5) | vm;
5955 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5956
5957 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5959 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5960
5961 Ok(bytes)
5962 }
5963
5964 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5968 let mut bytes = Vec::new();
5969 let dm_num = vfp_dreg_to_num(dm)?;
5970 let dd_num = vfp_dreg_to_num(dd)?;
5971 let (vm, m) = encode_dreg(dm_num);
5972 let (vd, d) = encode_dreg(dd_num);
5973
5974 if mode == 0b11 {
5975 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5977 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5978 } else {
5979 let rt: u32 = 12;
5980
5981 let vmrs = 0xEEF10A10 | (rt << 12);
5983 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5984
5985 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5987 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5988 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5989 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5990
5991 if mode != 0 {
5993 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5994 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5995 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5996 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5997 }
5998
5999 let vmsr = 0xEEE10A10 | (rt << 12);
6001 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
6002
6003 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
6005 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
6006
6007 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
6009 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
6010 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
6011 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
6012 }
6013
6014 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
6016 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
6017
6018 Ok(bytes)
6019 }
6020
6021 fn encode_thumb_f64_minmax(
6023 &self,
6024 dd: &VfpReg,
6025 dn: &VfpReg,
6026 dm: &VfpReg,
6027 is_min: bool,
6028 ) -> Result<Vec<u8>> {
6029 let mut bytes = Vec::new();
6030 let dn_num = vfp_dreg_to_num(dn)?;
6031 let dm_num = vfp_dreg_to_num(dm)?;
6032 let dd_num = vfp_dreg_to_num(dd)?;
6033
6034 let (vd, d) = encode_dreg(dd_num);
6036 let (vn, n) = encode_dreg(dn_num);
6037 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
6038 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
6039
6040 let (vm, m) = encode_dreg(dm_num);
6042 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
6043 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
6044
6045 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
6047
6048 let cond: u16 = if is_min { 0xC } else { 0x4 };
6050 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
6051 bytes.extend_from_slice(&it.to_le_bytes());
6052
6053 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
6055 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
6056
6057 Ok(bytes)
6058 }
6059
6060 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
6062 let mut bytes = Vec::new();
6063
6064 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6066 false,
6067 dm,
6068 &Reg::R0,
6069 &Reg::R12,
6070 )?));
6071
6072 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6074 false,
6075 dn,
6076 &Reg::R1,
6077 &Reg::R2,
6078 )?));
6079
6080 let hw1: u16 = 0xF000 | 12;
6082 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
6083 bytes.extend_from_slice(&hw1.to_le_bytes());
6084 bytes.extend_from_slice(&hw2.to_le_bytes());
6085
6086 let hw1: u16 = 0xF020 | 2;
6088 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
6089 bytes.extend_from_slice(&hw1.to_le_bytes());
6090 bytes.extend_from_slice(&hw2.to_le_bytes());
6091
6092 let hw1: u16 = 0xEA40 | 2;
6094 let hw2: u16 = (2 << 8) | 12;
6095 bytes.extend_from_slice(&hw1.to_le_bytes());
6096 bytes.extend_from_slice(&hw2.to_le_bytes());
6097
6098 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6100 true,
6101 dd,
6102 &Reg::R1,
6103 &Reg::R2,
6104 )?));
6105
6106 Ok(bytes)
6107 }
6108
6109 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6111 let mut bytes = Vec::new();
6112
6113 let sm_num = vfp_sreg_to_num(sm)?;
6114 let (vd, d) = encode_sreg(sm_num);
6115 let (vm, m) = encode_sreg(sm_num);
6116 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6117 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6118 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6119
6120 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6122 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6123
6124 Ok(bytes)
6125 }
6126
6127 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6131 let rd_bits = reg_to_bits(rd);
6132 let rn_bits = reg_to_bits(rn);
6133
6134 let i_bit = (imm >> 11) & 1;
6136 let imm3 = (imm >> 8) & 0x7;
6137 let imm8 = imm & 0xFF;
6138
6139 let hw1_base = if imm <= 0xFF {
6140 0xF100
6144 } else if imm <= 0xFFF {
6145 0xF200
6149 } else {
6150 return Err(synth_core::Error::synthesis(
6151 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6152 ));
6153 };
6154
6155 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6156 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6157
6158 let mut bytes = hw1.to_le_bytes().to_vec();
6159 bytes.extend_from_slice(&hw2.to_le_bytes());
6160 Ok(bytes)
6161 }
6162
6163 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6165 let rd_bits = reg_to_bits(rd);
6166 let rn_bits = reg_to_bits(rn);
6167
6168 let i_bit = (imm >> 11) & 1;
6169 let imm3 = (imm >> 8) & 0x7;
6170 let imm8 = imm & 0xFF;
6171
6172 let hw1_base = if imm <= 0xFF {
6173 0xF1A0
6176 } else if imm <= 0xFFF {
6177 0xF2A0
6180 } else {
6181 return Err(synth_core::Error::synthesis(
6182 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6183 ));
6184 };
6185
6186 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6187 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6188
6189 let mut bytes = hw1.to_le_bytes().to_vec();
6190 bytes.extend_from_slice(&hw2.to_le_bytes());
6191 Ok(bytes)
6192 }
6193
6194 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6196 let rd_bits = reg_to_bits(rd);
6197 let rn_bits = reg_to_bits(rn);
6198
6199 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6202 synth_core::Error::synthesis(
6203 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6204 )
6205 })?;
6206 let i_bit = (field >> 11) & 1;
6207 let imm3 = (field >> 8) & 0x7;
6208 let imm8 = field & 0xFF;
6209
6210 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6213 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6214
6215 let mut bytes = hw1.to_le_bytes().to_vec();
6216 bytes.extend_from_slice(&hw2.to_le_bytes());
6217 Ok(bytes)
6218 }
6219
6220 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6222 let rd_bits = reg_to_bits(rd);
6223 let rn_bits = reg_to_bits(rn);
6224
6225 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6228 synth_core::Error::synthesis(
6229 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6230 )
6231 })?;
6232 let i_bit = (field >> 11) & 1;
6233 let imm3 = (field >> 8) & 0x7;
6234 let imm8 = field & 0xFF;
6235
6236 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6239 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6240
6241 let mut bytes = hw1.to_le_bytes().to_vec();
6242 bytes.extend_from_slice(&hw2.to_le_bytes());
6243 Ok(bytes)
6244 }
6245
6246 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6255 let rd_bits = reg_to_bits(rd);
6256 reg_bits_checked(rd_bits)?;
6257 let imm16 = imm & 0xFFFF;
6258
6259 let imm4 = (imm16 >> 12) & 0xF;
6262 let i_bit = (imm16 >> 11) & 1;
6263 let imm3 = (imm16 >> 8) & 0x7;
6264 let imm8 = imm16 & 0xFF;
6265
6266 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6267 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6268
6269 let mut bytes = hw1.to_le_bytes().to_vec();
6270 bytes.extend_from_slice(&hw2.to_le_bytes());
6271 encoding_contracts::verify_thumb32(&bytes);
6272 Ok(bytes)
6273 }
6274
6275 fn encode_thumb32_shift(
6283 &self,
6284 rd: &Reg,
6285 rm: &Reg,
6286 shift: u32,
6287 shift_type: u8,
6288 ) -> Result<Vec<u8>> {
6289 let rd_bits = reg_to_bits(rd);
6290 let rm_bits = reg_to_bits(rm);
6291 reg_bits_checked(rd_bits)?;
6292 reg_bits_checked(rm_bits)?;
6293 let imm5 = shift & 0x1F;
6294 let imm2 = imm5 & 0x3;
6295 let imm3 = (imm5 >> 2) & 0x7;
6296
6297 let hw1: u16 = 0xEA4F;
6300 let hw2: u16 =
6301 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6302 as u16;
6303
6304 let mut bytes = hw1.to_le_bytes().to_vec();
6305 bytes.extend_from_slice(&hw2.to_le_bytes());
6306 Ok(bytes)
6307 }
6308
6309 fn encode_thumb32_shift_reg(
6313 &self,
6314 rd: &Reg,
6315 rn: &Reg,
6316 rm: &Reg,
6317 shift_type: u8,
6318 ) -> Result<Vec<u8>> {
6319 let rd_bits = reg_to_bits(rd);
6320 let rn_bits = reg_to_bits(rn);
6321 let rm_bits = reg_to_bits(rm);
6322
6323 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6325 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6327
6328 let mut bytes = hw1.to_le_bytes().to_vec();
6329 bytes.extend_from_slice(&hw2.to_le_bytes());
6330 Ok(bytes)
6331 }
6332
6333 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6335 let rn_bits = reg_to_bits(rn);
6336
6337 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6341 synth_core::Error::synthesis(
6342 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6343 )
6344 })?;
6345 let i_bit = (field >> 11) & 1;
6346 let imm3 = (field >> 8) & 0x7;
6347 let imm8 = field & 0xFF;
6348
6349 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6351 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6352
6353 let mut bytes = hw1.to_le_bytes().to_vec();
6354 bytes.extend_from_slice(&hw2.to_le_bytes());
6355 Ok(bytes)
6356 }
6357
6358 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6360 let rd_bits = reg_to_bits(rd);
6361 let base_bits = reg_to_bits(base);
6362
6363 check_ldst_imm12(offset)?;
6365 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6366 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6367
6368 let mut bytes = hw1.to_le_bytes().to_vec();
6369 bytes.extend_from_slice(&hw2.to_le_bytes());
6370 Ok(bytes)
6371 }
6372
6373 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6375 let rd_bits = reg_to_bits(rd);
6376 let base_bits = reg_to_bits(base);
6377
6378 check_ldst_imm12(offset)?;
6380 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6381 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6382
6383 let mut bytes = hw1.to_le_bytes().to_vec();
6384 bytes.extend_from_slice(&hw2.to_le_bytes());
6385 Ok(bytes)
6386 }
6387
6388 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6390 let rd_bits = reg_to_bits(rd);
6391 let base_bits = reg_to_bits(base);
6392 let rm_bits = reg_to_bits(offset_reg);
6393
6394 let hw1: u16 = (0xF850 | base_bits) as u16;
6398 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6399
6400 let mut bytes = hw1.to_le_bytes().to_vec();
6401 bytes.extend_from_slice(&hw2.to_le_bytes());
6402 Ok(bytes)
6403 }
6404
6405 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6407 let rd_bits = reg_to_bits(rd);
6408 let base_bits = reg_to_bits(base);
6409 let rm_bits = reg_to_bits(offset_reg);
6410
6411 let hw1: u16 = (0xF840 | base_bits) as u16;
6415 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6416
6417 let mut bytes = hw1.to_le_bytes().to_vec();
6418 bytes.extend_from_slice(&hw2.to_le_bytes());
6419 Ok(bytes)
6420 }
6421
6422 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6426 let rd_bits = reg_to_bits(rd);
6427 let base_bits = reg_to_bits(base);
6428 check_ldst_imm12(offset)?;
6430 let hw1: u16 = (0xF890 | base_bits) as u16;
6431 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6432 let mut bytes = hw1.to_le_bytes().to_vec();
6433 bytes.extend_from_slice(&hw2.to_le_bytes());
6434 Ok(bytes)
6435 }
6436
6437 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6439 let rd_bits = reg_to_bits(rd);
6440 let base_bits = reg_to_bits(base);
6441 let rm_bits = reg_to_bits(offset_reg);
6442 let hw1: u16 = (0xF810 | base_bits) as u16;
6444 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6445 let mut bytes = hw1.to_le_bytes().to_vec();
6446 bytes.extend_from_slice(&hw2.to_le_bytes());
6447 Ok(bytes)
6448 }
6449
6450 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6452 let rd_bits = reg_to_bits(rd);
6453 let base_bits = reg_to_bits(base);
6454 check_ldst_imm12(offset)?;
6456 let hw1: u16 = (0xF990 | base_bits) as u16;
6457 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6458 let mut bytes = hw1.to_le_bytes().to_vec();
6459 bytes.extend_from_slice(&hw2.to_le_bytes());
6460 Ok(bytes)
6461 }
6462
6463 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6465 let rd_bits = reg_to_bits(rd);
6466 let base_bits = reg_to_bits(base);
6467 let rm_bits = reg_to_bits(offset_reg);
6468 let hw1: u16 = (0xF910 | base_bits) as u16;
6470 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6471 let mut bytes = hw1.to_le_bytes().to_vec();
6472 bytes.extend_from_slice(&hw2.to_le_bytes());
6473 Ok(bytes)
6474 }
6475
6476 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6478 let rd_bits = reg_to_bits(rd);
6479 let base_bits = reg_to_bits(base);
6480 check_ldst_imm12(offset)?;
6482 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6483 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6484 let mut bytes = hw1.to_le_bytes().to_vec();
6485 bytes.extend_from_slice(&hw2.to_le_bytes());
6486 Ok(bytes)
6487 }
6488
6489 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6491 let rd_bits = reg_to_bits(rd);
6492 let base_bits = reg_to_bits(base);
6493 let rm_bits = reg_to_bits(offset_reg);
6494 let hw1: u16 = (0xF830 | base_bits) as u16;
6496 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6497 let mut bytes = hw1.to_le_bytes().to_vec();
6498 bytes.extend_from_slice(&hw2.to_le_bytes());
6499 Ok(bytes)
6500 }
6501
6502 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6504 let rd_bits = reg_to_bits(rd);
6505 let base_bits = reg_to_bits(base);
6506 check_ldst_imm12(offset)?;
6508 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6509 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6510 let mut bytes = hw1.to_le_bytes().to_vec();
6511 bytes.extend_from_slice(&hw2.to_le_bytes());
6512 Ok(bytes)
6513 }
6514
6515 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6517 let rd_bits = reg_to_bits(rd);
6518 let base_bits = reg_to_bits(base);
6519 let rm_bits = reg_to_bits(offset_reg);
6520 let hw1: u16 = (0xF930 | base_bits) as u16;
6522 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6523 let mut bytes = hw1.to_le_bytes().to_vec();
6524 bytes.extend_from_slice(&hw2.to_le_bytes());
6525 Ok(bytes)
6526 }
6527
6528 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6530 let rd_bits = reg_to_bits(rd);
6531 let base_bits = reg_to_bits(base);
6532 check_ldst_imm12(offset)?;
6534 let hw1: u16 = (0xF880 | base_bits) as u16;
6535 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6536 let mut bytes = hw1.to_le_bytes().to_vec();
6537 bytes.extend_from_slice(&hw2.to_le_bytes());
6538 Ok(bytes)
6539 }
6540
6541 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6543 let rd_bits = reg_to_bits(rd);
6544 let base_bits = reg_to_bits(base);
6545 let rm_bits = reg_to_bits(offset_reg);
6546 let hw1: u16 = (0xF800 | base_bits) as u16;
6548 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6549 let mut bytes = hw1.to_le_bytes().to_vec();
6550 bytes.extend_from_slice(&hw2.to_le_bytes());
6551 Ok(bytes)
6552 }
6553
6554 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6556 let rd_bits = reg_to_bits(rd);
6557 let base_bits = reg_to_bits(base);
6558 check_ldst_imm12(offset)?;
6560 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6561 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6562 let mut bytes = hw1.to_le_bytes().to_vec();
6563 bytes.extend_from_slice(&hw2.to_le_bytes());
6564 Ok(bytes)
6565 }
6566
6567 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6569 let rd_bits = reg_to_bits(rd);
6570 let base_bits = reg_to_bits(base);
6571 let rm_bits = reg_to_bits(offset_reg);
6572 let hw1: u16 = (0xF820 | base_bits) as u16;
6574 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6575 let mut bytes = hw1.to_le_bytes().to_vec();
6576 bytes.extend_from_slice(&hw2.to_le_bytes());
6577 Ok(bytes)
6578 }
6579
6580 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6582 let rd_bits = reg_to_bits(rd);
6583 let rn_bits = reg_to_bits(rn);
6584
6585 if imm <= 0xFFF {
6591 let i_bit = (imm >> 11) & 1;
6592 let imm3 = (imm >> 8) & 0x7;
6593 let imm8 = imm & 0xFF;
6594
6595 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6596 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6597
6598 let mut bytes = hw1.to_le_bytes().to_vec();
6599 bytes.extend_from_slice(&hw2.to_le_bytes());
6600 Ok(bytes)
6601 } else {
6602 let scratch: u32 = if rd_bits == rn_bits {
6616 12 } else {
6618 rd_bits };
6620 if scratch == rn_bits {
6628 return Err(synth_core::Error::synthesis(format!(
6629 "ADD #imm: cannot lower #{imm:#x} for Rd==Rn==R12 — no free scratch \
6630 register (R12 is the reserved encoder scratch and aliases Rn here)"
6631 )));
6632 }
6633
6634 let lo16 = imm & 0xFFFF;
6635 let hi16 = (imm >> 16) & 0xFFFF;
6636
6637 let mut bytes = self.encode_thumb32_movw_raw(scratch, lo16)?;
6638 if hi16 != 0 {
6639 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(scratch, hi16)?);
6640 }
6641 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(rd_bits, rn_bits, scratch)?);
6642 Ok(bytes)
6643 }
6644 }
6645
6646 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6656 reg_bits_checked(rd)?;
6657 encoding_contracts::verify_imm16(imm16);
6658 let imm16 = imm16 & 0xFFFF;
6661 let imm4 = (imm16 >> 12) & 0xF;
6662 let i_bit = (imm16 >> 11) & 1;
6663 let imm3 = (imm16 >> 8) & 0x7;
6664 let imm8 = imm16 & 0xFF;
6665
6666 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6667 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6668
6669 let mut bytes = hw1.to_le_bytes().to_vec();
6670 bytes.extend_from_slice(&hw2.to_le_bytes());
6671 encoding_contracts::verify_thumb32(&bytes);
6672 Ok(bytes)
6673 }
6674
6675 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6683 reg_bits_checked(rd)?;
6684 encoding_contracts::verify_imm16(imm16);
6685 let imm16 = imm16 & 0xFFFF;
6688 let imm4 = (imm16 >> 12) & 0xF;
6689 let i_bit = (imm16 >> 11) & 1;
6690 let imm3 = (imm16 >> 8) & 0x7;
6691 let imm8 = imm16 & 0xFF;
6692
6693 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6694 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6695
6696 let mut bytes = hw1.to_le_bytes().to_vec();
6697 bytes.extend_from_slice(&hw2.to_le_bytes());
6698 encoding_contracts::verify_thumb32(&bytes);
6699 Ok(bytes)
6700 }
6701
6702 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6704 let imm5 = shift & 0x1F;
6707 let imm2 = imm5 & 0x3;
6708 let imm3 = (imm5 >> 2) & 0x7;
6709
6710 let hw1: u16 = 0xEA4F;
6711 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6712
6713 let mut bytes = hw1.to_le_bytes().to_vec();
6714 bytes.extend_from_slice(&hw2.to_le_bytes());
6715 Ok(bytes)
6716 }
6717
6718 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6720 let hw1: u16 = (0xEA00 | rn) as u16;
6723 let hw2: u16 = ((rd << 8) | rm) as u16;
6724
6725 let mut bytes = hw1.to_le_bytes().to_vec();
6726 bytes.extend_from_slice(&hw2.to_le_bytes());
6727 Ok(bytes)
6728 }
6729
6730 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6732 let i_bit = (imm >> 11) & 1;
6736 let imm3 = (imm >> 8) & 0x7;
6737 let imm8 = imm & 0xFF;
6738
6739 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6740 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6741
6742 let mut bytes = hw1.to_le_bytes().to_vec();
6743 bytes.extend_from_slice(&hw2.to_le_bytes());
6744 Ok(bytes)
6745 }
6746
6747 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6749 let hw1: u16 = (0xEBA0 | rn) as u16;
6752 let hw2: u16 = ((rd << 8) | rm) as u16;
6753
6754 let mut bytes = hw1.to_le_bytes().to_vec();
6755 bytes.extend_from_slice(&hw2.to_le_bytes());
6756 Ok(bytes)
6757 }
6758
6759 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6761 let hw1: u16 = (0xEB00 | rn) as u16;
6764 let hw2: u16 = ((rd << 8) | rm) as u16;
6765
6766 let mut bytes = hw1.to_le_bytes().to_vec();
6767 bytes.extend_from_slice(&hw2.to_le_bytes());
6768 Ok(bytes)
6769 }
6770
6771 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6775 let hw1: u16 = (0xEB10 | rn) as u16;
6777 let hw2: u16 = ((rd << 8) | rm) as u16;
6778 let mut bytes = hw1.to_le_bytes().to_vec();
6779 bytes.extend_from_slice(&hw2.to_le_bytes());
6780 Ok(bytes)
6781 }
6782
6783 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6786 let hw1: u16 = (0xEBB0 | rn) as u16;
6788 let hw2: u16 = ((rd << 8) | rm) as u16;
6789 let mut bytes = hw1.to_le_bytes().to_vec();
6790 bytes.extend_from_slice(&hw2.to_le_bytes());
6791 Ok(bytes)
6792 }
6793
6794 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6796 let mut code = Vec::new();
6797
6798 for op in ops {
6799 let encoded = self.encode(op)?;
6800 code.extend_from_slice(&encoded);
6801 }
6802
6803 Ok(code)
6804 }
6805}
6806
6807fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6815 if value <= 0xFF {
6817 return Some(value);
6818 }
6819 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6823 return Some(0x100 | b0);
6824 }
6825 if value == (b1 << 24) | (b1 << 8) {
6827 return Some(0x200 | b1);
6828 }
6829 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6831 return Some(0x300 | b0);
6832 }
6833 for rot in 8..=31u32 {
6837 let unrot = value.rotate_left(rot);
6838 if (0x80..=0xFF).contains(&unrot) {
6839 return Some((rot << 7) | (unrot & 0x7F));
6840 }
6841 }
6842 None
6843}
6844
6845fn check_ldst_imm12(offset: u32) -> Result<()> {
6851 if offset > 0xFFF {
6852 Err(synth_core::Error::synthesis(
6853 "load/store immediate offset > 0xFFF (4095) — materialize the offset into a register",
6854 ))
6855 } else {
6856 Ok(())
6857 }
6858}
6859
6860fn reg_to_bits(reg: &Reg) -> u32 {
6861 match reg {
6862 Reg::R0 => 0,
6863 Reg::R1 => 1,
6864 Reg::R2 => 2,
6865 Reg::R3 => 3,
6866 Reg::R4 => 4,
6867 Reg::R5 => 5,
6868 Reg::R6 => 6,
6869 Reg::R7 => 7,
6870 Reg::R8 => 8,
6871 Reg::R9 => 9,
6872 Reg::R10 => 10,
6873 Reg::R11 => 11,
6874 Reg::R12 => 12,
6875 Reg::SP => 13,
6876 Reg::LR => 14,
6877 Reg::PC => 15,
6878 }
6879}
6880
6881fn reg_bits_checked(bits: u32) -> Result<()> {
6889 if bits > 14 {
6890 return Err(synth_core::Error::synthesis(format!(
6891 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6892 )));
6893 }
6894 Ok(())
6895}
6896
6897fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6900 if val == 0 {
6901 return Some((0, 1));
6902 }
6903 for rot in 0..16u32 {
6904 let shift = rot * 2;
6905 let unrotated = val.rotate_left(shift);
6907 if unrotated <= 0xFF {
6908 return Some(((rot << 8) | unrotated, 1));
6910 }
6911 }
6912 None
6913}
6914
6915fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6920 match op2 {
6921 Operand2::Imm(val) => {
6922 let uval = *val as u32;
6923 if let Some(encoded) = try_encode_rotated_imm(uval) {
6925 encoded
6926 } else {
6927 let imm = uval & 0xFF;
6932 (imm, 1)
6933 }
6934 }
6935
6936 Operand2::Reg(reg) => {
6937 let reg_bits = reg_to_bits(reg);
6938 (reg_bits, 0) }
6940
6941 Operand2::RegShift {
6942 rm,
6943 shift: _,
6944 amount,
6945 } => {
6946 let rm_bits = reg_to_bits(rm);
6948 let shift_bits = (*amount & 0x1F) << 7;
6949 (shift_bits | rm_bits, 0)
6950 }
6951 }
6952}
6953
6954fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6956 let base_bits = reg_to_bits(&addr.base);
6957 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6959}
6960
6961fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6963 match reg {
6964 VfpReg::S0 => Ok(0),
6965 VfpReg::S1 => Ok(1),
6966 VfpReg::S2 => Ok(2),
6967 VfpReg::S3 => Ok(3),
6968 VfpReg::S4 => Ok(4),
6969 VfpReg::S5 => Ok(5),
6970 VfpReg::S6 => Ok(6),
6971 VfpReg::S7 => Ok(7),
6972 VfpReg::S8 => Ok(8),
6973 VfpReg::S9 => Ok(9),
6974 VfpReg::S10 => Ok(10),
6975 VfpReg::S11 => Ok(11),
6976 VfpReg::S12 => Ok(12),
6977 VfpReg::S13 => Ok(13),
6978 VfpReg::S14 => Ok(14),
6979 VfpReg::S15 => Ok(15),
6980 VfpReg::S16 => Ok(16),
6981 VfpReg::S17 => Ok(17),
6982 VfpReg::S18 => Ok(18),
6983 VfpReg::S19 => Ok(19),
6984 VfpReg::S20 => Ok(20),
6985 VfpReg::S21 => Ok(21),
6986 VfpReg::S22 => Ok(22),
6987 VfpReg::S23 => Ok(23),
6988 VfpReg::S24 => Ok(24),
6989 VfpReg::S25 => Ok(25),
6990 VfpReg::S26 => Ok(26),
6991 VfpReg::S27 => Ok(27),
6992 VfpReg::S28 => Ok(28),
6993 VfpReg::S29 => Ok(29),
6994 VfpReg::S30 => Ok(30),
6995 VfpReg::S31 => Ok(31),
6996 _ => Err(synth_core::Error::SynthesisError(
6998 "D-register not supported in single-precision VFP encoding".to_string(),
6999 )),
7000 }
7001}
7002
7003fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
7005 match reg {
7006 VfpReg::D0 => Ok(0),
7007 VfpReg::D1 => Ok(1),
7008 VfpReg::D2 => Ok(2),
7009 VfpReg::D3 => Ok(3),
7010 VfpReg::D4 => Ok(4),
7011 VfpReg::D5 => Ok(5),
7012 VfpReg::D6 => Ok(6),
7013 VfpReg::D7 => Ok(7),
7014 VfpReg::D8 => Ok(8),
7015 VfpReg::D9 => Ok(9),
7016 VfpReg::D10 => Ok(10),
7017 VfpReg::D11 => Ok(11),
7018 VfpReg::D12 => Ok(12),
7019 VfpReg::D13 => Ok(13),
7020 VfpReg::D14 => Ok(14),
7021 VfpReg::D15 => Ok(15),
7022 _ => Err(synth_core::Error::SynthesisError(
7024 "S-register not supported in double-precision VFP encoding".to_string(),
7025 )),
7026 }
7027}
7028
7029fn encode_sreg(s: u32) -> (u32, u32) {
7033 (s >> 1, s & 1)
7034}
7035
7036fn encode_dreg(d: u32) -> (u32, u32) {
7040 (d & 0xF, (d >> 4) & 1)
7041}
7042
7043fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
7049 let sd_num = vfp_sreg_to_num(sd)?;
7050 let sn_num = vfp_sreg_to_num(sn)?;
7051 let sm_num = vfp_sreg_to_num(sm)?;
7052 let (vd, d) = encode_sreg(sd_num);
7053 let (vn, n) = encode_sreg(sn_num);
7054 let (vm, m) = encode_sreg(sm_num);
7055
7056 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7057}
7058
7059fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
7062 let sd_num = vfp_sreg_to_num(sd)?;
7063 let sm_num = vfp_sreg_to_num(sm)?;
7064 let (vd, d) = encode_sreg(sd_num);
7065 let (vm, m) = encode_sreg(sm_num);
7066
7067 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7068}
7069
7070fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7074 let sd_num = vfp_sreg_to_num(sd)?;
7075 let (vd, d) = encode_sreg(sd_num);
7076 let rn = reg_to_bits(&addr.base);
7077
7078 let offset = addr.offset;
7079 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7080 let abs_offset = offset.unsigned_abs();
7081 let imm8 = (abs_offset / 4) & 0xFF;
7082
7083 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7084}
7085
7086fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
7090 let s_num = vfp_sreg_to_num(sreg)?;
7091 let (vn, n) = encode_sreg(s_num);
7092 let rt = reg_to_bits(core);
7093
7094 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
7095 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
7096}
7097
7098fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
7102 let dd_num = vfp_dreg_to_num(dd)?;
7103 let dn_num = vfp_dreg_to_num(dn)?;
7104 let dm_num = vfp_dreg_to_num(dm)?;
7105 let (vd, d) = encode_dreg(dd_num);
7106 let (vn, n) = encode_dreg(dn_num);
7107 let (vm, m) = encode_dreg(dm_num);
7108
7109 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7110}
7111
7112fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
7114 let dd_num = vfp_dreg_to_num(dd)?;
7115 let dm_num = vfp_dreg_to_num(dm)?;
7116 let (vd, d) = encode_dreg(dd_num);
7117 let (vm, m) = encode_dreg(dm_num);
7118
7119 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7120}
7121
7122fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7125 let dd_num = vfp_dreg_to_num(dd)?;
7126 let (vd, d) = encode_dreg(dd_num);
7127 let rn = reg_to_bits(&addr.base);
7128
7129 let offset = addr.offset;
7130 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7131 let abs_offset = offset.unsigned_abs();
7132 let imm8 = (abs_offset / 4) & 0xFF;
7133
7134 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7135}
7136
7137fn encode_vmov_core_dreg(
7141 to_dreg: bool,
7142 dreg: &VfpReg,
7143 core_lo: &Reg,
7144 core_hi: &Reg,
7145) -> Result<u32> {
7146 let d_num = vfp_dreg_to_num(dreg)?;
7147 let (vm, m) = encode_dreg(d_num);
7148 let rt = reg_to_bits(core_lo);
7149 let rt2 = reg_to_bits(core_hi);
7150
7151 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
7152 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
7153}
7154
7155fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
7157 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
7158 let hw2 = (instr & 0xFFFF) as u16;
7159 let mut bytes = hw1.to_le_bytes().to_vec();
7160 bytes.extend_from_slice(&hw2.to_le_bytes());
7161 bytes
7162}
7163
7164fn qreg_to_num(reg: &QReg) -> u32 {
7170 match reg {
7171 QReg::Q0 => 0,
7172 QReg::Q1 => 1,
7173 QReg::Q2 => 2,
7174 QReg::Q3 => 3,
7175 QReg::Q4 => 4,
7176 QReg::Q5 => 5,
7177 QReg::Q6 => 6,
7178 QReg::Q7 => 7,
7179 }
7180}
7181
7182fn mve_size_bits(size: &MveSize) -> u32 {
7184 match size {
7185 MveSize::S8 => 0b00,
7186 MveSize::S16 => 0b01,
7187 MveSize::S32 => 0b10,
7188 }
7189}
7190
7191fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7195 let d = qreg_to_num(qd) * 2;
7196 let n = qreg_to_num(qn) * 2;
7197 let m = qreg_to_num(qm) * 2;
7198
7199 let vd = d & 0xF;
7204 let d_bit = (d >> 4) & 1;
7205 let vn = n & 0xF;
7206 let n_bit = (n >> 4) & 1;
7207 let vm = m & 0xF;
7208 let m_bit = (m >> 4) & 1;
7209
7210 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7211}
7212
7213fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7215 encode_mve_3reg(base, qd, qn, qm)
7216}
7217
7218fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7221 let qd_enc = qreg_to_num(qd) * 2;
7222 let rn = reg_to_bits(&addr.base);
7223 let offset = addr.offset;
7224 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7225 let abs_offset = offset.unsigned_abs();
7226 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7230 | (u_bit << 23)
7231 | ((qd_enc >> 4) << 22)
7232 | (rn << 16)
7233 | ((qd_enc & 0xF) << 12)
7234 | (imm7 & 0x7F)
7235}
7236
7237fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7239 let qd_enc = qreg_to_num(qd) * 2;
7240 let rn = reg_to_bits(&addr.base);
7241 let offset = addr.offset;
7242 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7243 let abs_offset = offset.unsigned_abs();
7244 let imm7 = (abs_offset / 4) & 0x7F;
7245
7246 0xED000E80
7247 | (u_bit << 23)
7248 | ((qd_enc >> 4) << 22)
7249 | (rn << 16)
7250 | ((qd_enc & 0xF) << 12)
7251 | (imm7 & 0x7F)
7252}
7253
7254impl ArmEncoder {
7255 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7257 let mut result = Vec::new();
7258 let qd_num = qreg_to_num(qd);
7259
7260 for i in 0..4 {
7262 let word = u32::from_le_bytes([
7263 bytes[i * 4],
7264 bytes[i * 4 + 1],
7265 bytes[i * 4 + 2],
7266 bytes[i * 4 + 3],
7267 ]);
7268 let lo16 = word & 0xFFFF;
7269 let hi16 = (word >> 16) & 0xFFFF;
7270
7271 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7273 if hi16 != 0 {
7275 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7276 }
7277
7278 let s_num = qd_num * 4 + i as u32;
7280 let (vn, n) = encode_sreg(s_num);
7281 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7282 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7283 }
7284
7285 Ok(result)
7286 }
7287
7288 fn encode_thumb_mve_lane_wise_f32_binop(
7290 &self,
7291 qd: &QReg,
7292 qn: &QReg,
7293 qm: &QReg,
7294 vfp_base: u32,
7295 ) -> Result<Vec<u8>> {
7296 let mut result = Vec::new();
7297 let qd_num = qreg_to_num(qd);
7298 let qn_num = qreg_to_num(qn);
7299 let qm_num = qreg_to_num(qm);
7300
7301 for i in 0..4u32 {
7303 let sd = qd_num * 4 + i;
7304 let sn = qn_num * 4 + i;
7305 let sm = qm_num * 4 + i;
7306
7307 let (vd, d) = encode_sreg(sd);
7308 let (vn, n) = encode_sreg(sn);
7309 let (vm, m) = encode_sreg(sm);
7310
7311 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7312 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7313 }
7314
7315 Ok(result)
7316 }
7317
7318 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7320 let mut result = Vec::new();
7321 let qd_num = qreg_to_num(qd);
7322 let qm_num = qreg_to_num(qm);
7323
7324 for i in 0..4u32 {
7326 let sd = qd_num * 4 + i;
7327 let sm = qm_num * 4 + i;
7328
7329 let (vd, d) = encode_sreg(sd);
7330 let (vm, m) = encode_sreg(sm);
7331
7332 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7333 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7334 }
7335
7336 Ok(result)
7337 }
7338}
7339
7340#[cfg(test)]
7341mod tests {
7342 use super::*;
7343
7344 #[test]
7345 fn test_encoder_creation() {
7346 let encoder_arm = ArmEncoder::new_arm32();
7347 assert!(!encoder_arm.thumb_mode);
7348
7349 let encoder_thumb = ArmEncoder::new_thumb2();
7350 assert!(encoder_thumb.thumb_mode);
7351 }
7352
7353 #[test]
7365 fn test_encode_i64setcond_high_reg_uses_mov_w_311() {
7366 use synth_synthesis::{ArmOp, Condition, Reg};
7367 let enc = ArmEncoder::new_thumb2();
7368 let bytes = enc
7369 .encode(&ArmOp::I64SetCond {
7370 rd: Reg::R8,
7371 rn_lo: Reg::R2,
7372 rn_hi: Reg::R3,
7373 rm_lo: Reg::R6,
7374 rm_hi: Reg::R7,
7375 cond: Condition::EQ,
7376 })
7377 .unwrap();
7378 let halfwords: Vec<u16> = bytes
7381 .chunks(2)
7382 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7383 .collect();
7384 assert!(
7385 halfwords.iter().filter(|&&h| h == 0xF04F).count() == 2,
7386 "high rd must use two MOV.W (T2) encodings, got {halfwords:04x?}"
7387 );
7388 assert!(
7389 !halfwords.contains(&0x2801) && !halfwords.contains(&0x2800),
7390 "no transmuted 16-bit CMP imm: {halfwords:04x?}"
7391 );
7392
7393 let bytes_z = enc
7394 .encode(&ArmOp::I64SetCondZ {
7395 rd: Reg::R8,
7396 rn_lo: Reg::R2,
7397 rn_hi: Reg::R3,
7398 })
7399 .unwrap();
7400 let hw_z: Vec<u16> = bytes_z
7401 .chunks(2)
7402 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7403 .collect();
7404 assert!(
7405 hw_z.iter().filter(|&&h| h == 0xF04F).count() == 2,
7406 "SetCondZ high rd MOV.W: {hw_z:04x?}"
7407 );
7408 assert!(
7410 hw_z.contains(&(0xF1B0 | 8)),
7411 "SetCondZ high rd must use CMP.W: {hw_z:04x?}"
7412 );
7413 }
7414
7415 #[test]
7416 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7417 use synth_synthesis::{ArmOp, Condition, Reg};
7418 let enc = ArmEncoder::new_thumb2();
7419 let hi = enc
7421 .encode(&ArmOp::SetCond {
7422 rd: Reg::R12,
7423 cond: Condition::NE,
7424 })
7425 .unwrap();
7426 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7427 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7429 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7430 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7431 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7432 let lo = enc
7434 .encode(&ArmOp::SetCond {
7435 rd: Reg::R0,
7436 cond: Condition::NE,
7437 })
7438 .unwrap();
7439 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7440 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7441 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7442 }
7443
7444 #[test]
7448 fn test_encode_umull_209b() {
7449 use synth_synthesis::{ArmOp, Reg};
7450 let op = ArmOp::Umull {
7451 rdlo: Reg::R4,
7452 rdhi: Reg::R5,
7453 rn: Reg::R0,
7454 rm: Reg::R3,
7455 };
7456 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7458 assert_eq!(
7459 t,
7460 vec![0xA0, 0xFB, 0x03, 0x45],
7461 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7462 );
7463 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7465 assert_eq!(
7466 a,
7467 0xE085_4390u32.to_le_bytes().to_vec(),
7468 "umull (A32): {a:02x?}"
7469 );
7470 }
7471
7472 #[test]
7479 fn test_encode_arm32_indexed_load_keeps_index_206() {
7480 use synth_synthesis::{ArmOp, MemAddr, Reg};
7481 let enc = ArmEncoder::new_arm32();
7482 let bytes = enc
7484 .encode(&ArmOp::Ldr {
7485 rd: Reg::R0,
7486 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7487 })
7488 .unwrap();
7489 assert_eq!(
7490 bytes.len(),
7491 8,
7492 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7493 );
7494 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7495 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7496 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7498 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7500 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7502 }
7503
7504 #[test]
7511 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7512 let encoder = ArmEncoder::new_thumb2();
7513
7514 let code = encoder
7516 .encode(&ArmOp::Add {
7517 rd: Reg::R12,
7518 rn: Reg::R12,
7519 op2: Operand2::Reg(Reg::R0),
7520 })
7521 .unwrap();
7522 assert_eq!(
7524 code,
7525 vec![0x0C, 0xEB, 0x00, 0x0C],
7526 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7527 );
7528 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7530
7531 let lo = encoder
7533 .encode(&ArmOp::Add {
7534 rd: Reg::R1,
7535 rn: Reg::R2,
7536 op2: Operand2::Reg(Reg::R3),
7537 })
7538 .unwrap();
7539 assert_eq!(
7540 lo.len(),
7541 2,
7542 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7543 );
7544 }
7545
7546 #[test]
7549 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7550 let encoder = ArmEncoder::new_thumb2();
7551
7552 let adds = encoder
7554 .encode(&ArmOp::Adds {
7555 rd: Reg::R10,
7556 rn: Reg::R10,
7557 op2: Operand2::Reg(Reg::R8),
7558 })
7559 .unwrap();
7560 assert_eq!(
7561 adds,
7562 vec![0x1A, 0xEB, 0x08, 0x0A],
7563 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7564 );
7565
7566 let subs = encoder
7568 .encode(&ArmOp::Subs {
7569 rd: Reg::R10,
7570 rn: Reg::R10,
7571 op2: Operand2::Reg(Reg::R8),
7572 })
7573 .unwrap();
7574 assert_eq!(
7575 subs,
7576 vec![0xBA, 0xEB, 0x08, 0x0A],
7577 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7578 );
7579 }
7580
7581 #[test]
7584 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7585 let encoder = ArmEncoder::new_thumb2();
7586
7587 let cmn = encoder
7589 .encode(&ArmOp::Cmn {
7590 rn: Reg::R10,
7591 op2: Operand2::Reg(Reg::R8),
7592 })
7593 .unwrap();
7594 assert_eq!(
7595 cmn,
7596 vec![0x1A, 0xEB, 0x08, 0x0F],
7597 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7598 );
7599
7600 let lo = encoder
7602 .encode(&ArmOp::Cmn {
7603 rn: Reg::R1,
7604 op2: Operand2::Reg(Reg::R2),
7605 })
7606 .unwrap();
7607 assert_eq!(
7608 lo.len(),
7609 2,
7610 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7611 );
7612 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7613 }
7614
7615 #[test]
7619 fn test_encode_pc_operand_returns_err_not_panic_185() {
7620 let encoder = ArmEncoder::new_thumb2();
7621 for op in [
7622 ArmOp::Sdiv {
7623 rd: Reg::PC,
7624 rn: Reg::R0,
7625 rm: Reg::R1,
7626 },
7627 ArmOp::Udiv {
7628 rd: Reg::R0,
7629 rn: Reg::PC,
7630 rm: Reg::R1,
7631 },
7632 ArmOp::Sdiv {
7633 rd: Reg::R0,
7634 rn: Reg::R1,
7635 rm: Reg::PC,
7636 },
7637 ] {
7638 let r = encoder.encode(&op);
7639 assert!(
7640 r.is_err(),
7641 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7642 );
7643 }
7644 assert!(
7646 encoder
7647 .encode(&ArmOp::Sdiv {
7648 rd: Reg::R0,
7649 rn: Reg::R1,
7650 rm: Reg::R2
7651 })
7652 .is_ok()
7653 );
7654 }
7655
7656 #[test]
7657 fn test_encode_nop_arm32() {
7658 let encoder = ArmEncoder::new_arm32();
7659 let code = encoder.encode(&ArmOp::Nop).unwrap();
7660
7661 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7664
7665 #[test]
7666 fn test_encode_nop_thumb() {
7667 let encoder = ArmEncoder::new_thumb2();
7668 let code = encoder.encode(&ArmOp::Nop).unwrap();
7669
7670 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7673
7674 #[test]
7675 fn test_encode_mov_immediate_arm32() {
7676 let encoder = ArmEncoder::new_arm32();
7677 let op = ArmOp::Mov {
7678 rd: Reg::R0,
7679 op2: Operand2::Imm(42),
7680 };
7681
7682 let code = encoder.encode(&op).unwrap();
7683 assert_eq!(code.len(), 4);
7684
7685 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7687 assert_eq!(instr & 0x0E000000, 0x02000000); }
7689
7690 #[test]
7691 fn test_encode_add_registers_arm32() {
7692 let encoder = ArmEncoder::new_arm32();
7693 let op = ArmOp::Add {
7694 rd: Reg::R0,
7695 rn: Reg::R1,
7696 op2: Operand2::Reg(Reg::R2),
7697 };
7698
7699 let code = encoder.encode(&op).unwrap();
7700 assert_eq!(code.len(), 4);
7701
7702 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7703 assert_eq!(instr & 0x0FE00000, 0x00800000);
7705 }
7706
7707 #[test]
7711 fn test_encode_add_imm_large_350() {
7712 let enc = ArmEncoder::new_thumb2();
7713
7714 let small = enc
7716 .encode_thumb32_add_imm(&Reg::R0, &Reg::R1, 0x123)
7717 .unwrap();
7718 assert_eq!(small.len(), 4, "small imm must stay a single instruction");
7719
7720 fn movx_imm16(b: &[u8]) -> u32 {
7722 let hw1 = u16::from_le_bytes([b[0], b[1]]) as u32;
7723 let hw2 = u16::from_le_bytes([b[2], b[3]]) as u32;
7724 let imm4 = hw1 & 0xF;
7725 let i = (hw1 >> 10) & 1;
7726 let imm3 = (hw2 >> 12) & 0x7;
7727 let imm8 = hw2 & 0xFF;
7728 (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8
7729 }
7730 fn movx_rd(b: &[u8]) -> u32 {
7731 (u16::from_le_bytes([b[2], b[3]]) as u32 >> 8) & 0xF
7732 }
7733
7734 let seq = enc
7737 .encode_thumb32_add_imm(&Reg::R12, &Reg::R0, 70000)
7738 .unwrap();
7739 assert_eq!(seq.len(), 12, "MOVW + MOVT + ADD = 12 bytes");
7740 assert_eq!(u16::from_le_bytes([seq[0], seq[1]]) & 0xFBF0, 0xF240);
7742 assert_eq!(movx_rd(&seq[0..4]), 12);
7743 assert_eq!(movx_imm16(&seq[0..4]), 0x1170);
7744 assert_eq!(u16::from_le_bytes([seq[4], seq[5]]) & 0xFBF0, 0xF2C0);
7746 assert_eq!(movx_rd(&seq[4..8]), 12);
7747 assert_eq!(movx_imm16(&seq[4..8]), 0x0001);
7748 let add1 = u16::from_le_bytes([seq[8], seq[9]]) as u32;
7750 let add2 = u16::from_le_bytes([seq[10], seq[11]]) as u32;
7751 assert_eq!(add1 & 0xFFF0, 0xEB00);
7752 assert_eq!(add1 & 0xF, 0); assert_eq!((add2 >> 8) & 0xF, 12); assert_eq!(add2 & 0xF, 12); assert_eq!(
7757 (movx_imm16(&seq[4..8]) << 16) | movx_imm16(&seq[0..4]),
7758 70000
7759 );
7760
7761 let seq16 = enc
7763 .encode_thumb32_add_imm(&Reg::R3, &Reg::R0, 0xABCD)
7764 .unwrap();
7765 assert_eq!(seq16.len(), 8, "imm <= 0xFFFF skips MOVT");
7766 assert_eq!(movx_imm16(&seq16[0..4]), 0xABCD);
7767 assert_eq!(movx_rd(&seq16[0..4]), 3); let inplace = enc
7772 .encode_thumb32_add_imm(&Reg::R5, &Reg::R5, 0x12345)
7773 .unwrap();
7774 assert_eq!(inplace.len(), 12);
7775 assert_eq!(movx_rd(&inplace[0..4]), 12, "rd==rn must use R12 scratch");
7776 assert_eq!(
7777 (movx_imm16(&inplace[4..8]) << 16) | movx_imm16(&inplace[0..4]),
7778 0x12345
7779 );
7780 let ip_add2 = u16::from_le_bytes([inplace[10], inplace[11]]) as u32;
7782 assert_eq!(ip_add2 & 0xF, 12);
7783 assert_eq!((ip_add2 >> 8) & 0xF, 5);
7784 }
7785
7786 #[test]
7794 fn test_encode_add_imm_large_rd_rn_r12_errs_not_panics_350() {
7795 let enc = ArmEncoder::new_thumb2();
7796 let r = enc.encode_thumb32_add_imm(&Reg::R12, &Reg::R12, 70000);
7798 assert!(
7799 r.is_err(),
7800 "rd==rn==R12 with out-of-range imm must Err (no free scratch), got {r:?}"
7801 );
7802 let small = enc.encode_thumb32_add_imm(&Reg::R12, &Reg::R12, 0x10);
7806 assert!(small.is_ok(), "small imm needs no scratch, must stay Ok");
7807 }
7808
7809 #[test]
7810 fn test_encode_ldr_arm32() {
7811 let encoder = ArmEncoder::new_arm32();
7812 let op = ArmOp::Ldr {
7813 rd: Reg::R0,
7814 addr: MemAddr::imm(Reg::R1, 4),
7815 };
7816
7817 let code = encoder.encode(&op).unwrap();
7818 assert_eq!(code.len(), 4);
7819
7820 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7821 assert_eq!(instr & 0x00100000, 0x00100000);
7823 }
7824
7825 #[test]
7826 fn test_encode_str_arm32() {
7827 let encoder = ArmEncoder::new_arm32();
7828 let op = ArmOp::Str {
7829 rd: Reg::R0,
7830 addr: MemAddr::imm(Reg::SP, 0),
7831 };
7832
7833 let code = encoder.encode(&op).unwrap();
7834 assert_eq!(code.len(), 4);
7835 }
7836
7837 #[test]
7838 fn test_encode_branch_arm32() {
7839 let encoder = ArmEncoder::new_arm32();
7840 let op = ArmOp::Bl {
7841 label: "main".to_string(),
7842 };
7843
7844 let code = encoder.encode(&op).unwrap();
7845 assert_eq!(code.len(), 4);
7846
7847 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7848 assert_eq!(instr & 0x0F000000, 0x0B000000);
7850 }
7851
7852 #[test]
7862 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7863 let encoder = ArmEncoder::new_thumb2();
7864 let op = ArmOp::Bl {
7865 label: "callee".to_string(),
7866 };
7867
7868 let code = encoder.encode(&op).unwrap();
7869 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7870
7871 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7872 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7873 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7874 assert_eq!(
7875 hw2, 0xFFFE,
7876 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7877 );
7878 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7879 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7880 }
7881
7882 #[test]
7883 fn test_encode_sequence() {
7884 let encoder = ArmEncoder::new_arm32();
7885 let ops = vec![
7886 ArmOp::Mov {
7887 rd: Reg::R0,
7888 op2: Operand2::Imm(42),
7889 },
7890 ArmOp::Mov {
7891 rd: Reg::R1,
7892 op2: Operand2::Imm(10),
7893 },
7894 ArmOp::Add {
7895 rd: Reg::R2,
7896 rn: Reg::R0,
7897 op2: Operand2::Reg(Reg::R1),
7898 },
7899 ];
7900
7901 let code = encoder.encode_sequence(&ops).unwrap();
7902 assert_eq!(code.len(), 12); }
7904
7905 #[test]
7906 fn test_reg_to_bits() {
7907 assert_eq!(reg_to_bits(&Reg::R0), 0);
7908 assert_eq!(reg_to_bits(&Reg::R7), 7);
7909 assert_eq!(reg_to_bits(&Reg::SP), 13);
7910 assert_eq!(reg_to_bits(&Reg::LR), 14);
7911 assert_eq!(reg_to_bits(&Reg::PC), 15);
7912 }
7913
7914 #[test]
7915 fn test_encode_bitwise_operations() {
7916 let encoder = ArmEncoder::new_arm32();
7917
7918 let and_op = ArmOp::And {
7919 rd: Reg::R0,
7920 rn: Reg::R1,
7921 op2: Operand2::Reg(Reg::R2),
7922 };
7923 let and_code = encoder.encode(&and_op).unwrap();
7924 assert_eq!(and_code.len(), 4);
7925
7926 let orr_op = ArmOp::Orr {
7927 rd: Reg::R0,
7928 rn: Reg::R1,
7929 op2: Operand2::Reg(Reg::R2),
7930 };
7931 let orr_code = encoder.encode(&orr_op).unwrap();
7932 assert_eq!(orr_code.len(), 4);
7933
7934 let eor_op = ArmOp::Eor {
7935 rd: Reg::R0,
7936 rn: Reg::R1,
7937 op2: Operand2::Reg(Reg::R2),
7938 };
7939 let eor_code = encoder.encode(&eor_op).unwrap();
7940 assert_eq!(eor_code.len(), 4);
7941 }
7942
7943 #[test]
7946 fn test_encode_sdiv_thumb2() {
7947 let encoder = ArmEncoder::new_thumb2();
7948 let op = ArmOp::Sdiv {
7949 rd: Reg::R0,
7950 rn: Reg::R1,
7951 rm: Reg::R2,
7952 };
7953
7954 let code = encoder.encode(&op).unwrap();
7955 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7962 assert_eq!(code[1], 0xFB);
7963 assert_eq!(code[2], 0xF2);
7964 assert_eq!(code[3], 0xF0);
7965 }
7966
7967 #[test]
7968 fn test_encode_udiv_thumb2() {
7969 let encoder = ArmEncoder::new_thumb2();
7970 let op = ArmOp::Udiv {
7971 rd: Reg::R0,
7972 rn: Reg::R1,
7973 rm: Reg::R2,
7974 };
7975
7976 let code = encoder.encode(&op).unwrap();
7977 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7982 assert_eq!(code[1], 0xFB);
7983 assert_eq!(code[2], 0xF2);
7984 assert_eq!(code[3], 0xF0);
7985 }
7986
7987 #[test]
7988 fn test_encode_mul_thumb2() {
7989 let encoder = ArmEncoder::new_thumb2();
7990 let op = ArmOp::Mul {
7991 rd: Reg::R0,
7992 rn: Reg::R1,
7993 rm: Reg::R2,
7994 };
7995
7996 let code = encoder.encode(&op).unwrap();
7997 assert_eq!(code.len(), 4); }
7999
8000 #[test]
8001 fn test_encode_and_thumb2() {
8002 let encoder = ArmEncoder::new_thumb2();
8003 let op = ArmOp::And {
8004 rd: Reg::R0,
8005 rn: Reg::R1,
8006 op2: Operand2::Reg(Reg::R2),
8007 };
8008
8009 let code = encoder.encode(&op).unwrap();
8010 assert_eq!(code.len(), 4); }
8012
8013 #[test]
8014 fn test_encode_lsl_thumb2_low_regs() {
8015 let encoder = ArmEncoder::new_thumb2();
8016 let op = ArmOp::Lsl {
8017 rd: Reg::R0,
8018 rn: Reg::R1,
8019 shift: 5,
8020 };
8021
8022 let code = encoder.encode(&op).unwrap();
8023 assert_eq!(code.len(), 2); }
8025
8026 #[test]
8027 fn test_encode_clz_thumb2() {
8028 let encoder = ArmEncoder::new_thumb2();
8029 let op = ArmOp::Clz {
8030 rd: Reg::R0,
8031 rm: Reg::R1,
8032 };
8033
8034 let code = encoder.encode(&op).unwrap();
8035 assert_eq!(code.len(), 4); }
8037
8038 #[test]
8039 fn test_encode_bx_thumb2() {
8040 let encoder = ArmEncoder::new_thumb2();
8041 let op = ArmOp::Bx { rm: Reg::LR };
8042
8043 let code = encoder.encode(&op).unwrap();
8044 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
8048 }
8049
8050 #[test]
8055 fn test_encode_f32_abs_arm32() {
8056 let encoder = ArmEncoder::new_arm32();
8057 let op = ArmOp::F32Abs {
8058 sd: VfpReg::S0,
8059 sm: VfpReg::S2,
8060 };
8061 let code = encoder.encode(&op).unwrap();
8062 assert_eq!(code.len(), 4); }
8064
8065 #[test]
8066 fn test_encode_f32_neg_arm32() {
8067 let encoder = ArmEncoder::new_arm32();
8068 let op = ArmOp::F32Neg {
8069 sd: VfpReg::S0,
8070 sm: VfpReg::S2,
8071 };
8072 let code = encoder.encode(&op).unwrap();
8073 assert_eq!(code.len(), 4);
8074 }
8075
8076 #[test]
8077 fn test_encode_f32_sqrt_arm32() {
8078 let encoder = ArmEncoder::new_arm32();
8079 let op = ArmOp::F32Sqrt {
8080 sd: VfpReg::S0,
8081 sm: VfpReg::S2,
8082 };
8083 let code = encoder.encode(&op).unwrap();
8084 assert_eq!(code.len(), 4);
8085 }
8086
8087 #[test]
8088 fn test_encode_f32_ceil_arm32() {
8089 let encoder = ArmEncoder::new_arm32();
8090 let op = ArmOp::F32Ceil {
8091 sd: VfpReg::S0,
8092 sm: VfpReg::S2,
8093 };
8094 let code = encoder.encode(&op).unwrap();
8095 assert_eq!(code.len(), 36);
8097 }
8098
8099 #[test]
8100 fn test_encode_f32_floor_thumb2() {
8101 let encoder = ArmEncoder::new_thumb2();
8102 let op = ArmOp::F32Floor {
8103 sd: VfpReg::S0,
8104 sm: VfpReg::S2,
8105 };
8106 let code = encoder.encode(&op).unwrap();
8107 assert_eq!(code.len(), 36);
8109 }
8110
8111 #[test]
8112 fn test_encode_f32_min_arm32() {
8113 let encoder = ArmEncoder::new_arm32();
8114 let op = ArmOp::F32Min {
8115 sd: VfpReg::S0,
8116 sn: VfpReg::S2,
8117 sm: VfpReg::S4,
8118 };
8119 let code = encoder.encode(&op).unwrap();
8120 assert_eq!(code.len(), 16); }
8122
8123 #[test]
8124 fn test_encode_f32_max_thumb2() {
8125 let encoder = ArmEncoder::new_thumb2();
8126 let op = ArmOp::F32Max {
8127 sd: VfpReg::S0,
8128 sn: VfpReg::S2,
8129 sm: VfpReg::S4,
8130 };
8131 let code = encoder.encode(&op).unwrap();
8132 assert_eq!(code.len(), 18);
8134 }
8135
8136 #[test]
8137 fn test_encode_f32_copysign_arm32() {
8138 let encoder = ArmEncoder::new_arm32();
8139 let op = ArmOp::F32Copysign {
8140 sd: VfpReg::S0,
8141 sn: VfpReg::S2,
8142 sm: VfpReg::S4,
8143 };
8144 let code = encoder.encode(&op).unwrap();
8145 assert_eq!(code.len(), 24);
8147 }
8148
8149 #[test]
8154 fn test_encode_f64_add_arm32() {
8155 let encoder = ArmEncoder::new_arm32();
8156 let op = ArmOp::F64Add {
8157 dd: VfpReg::D0,
8158 dn: VfpReg::D1,
8159 dm: VfpReg::D2,
8160 };
8161 let code = encoder.encode(&op).unwrap();
8162 assert_eq!(code.len(), 4);
8163 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8165 assert_eq!((instr >> 8) & 0xF, 0xB); }
8167
8168 #[test]
8169 fn test_encode_f64_sub_thumb2() {
8170 let encoder = ArmEncoder::new_thumb2();
8171 let op = ArmOp::F64Sub {
8172 dd: VfpReg::D0,
8173 dn: VfpReg::D1,
8174 dm: VfpReg::D2,
8175 };
8176 let code = encoder.encode(&op).unwrap();
8177 assert_eq!(code.len(), 4); }
8179
8180 #[test]
8181 fn test_encode_f64_mul_arm32() {
8182 let encoder = ArmEncoder::new_arm32();
8183 let op = ArmOp::F64Mul {
8184 dd: VfpReg::D0,
8185 dn: VfpReg::D1,
8186 dm: VfpReg::D2,
8187 };
8188 let code = encoder.encode(&op).unwrap();
8189 assert_eq!(code.len(), 4);
8190 }
8191
8192 #[test]
8193 fn test_encode_f64_div_arm32() {
8194 let encoder = ArmEncoder::new_arm32();
8195 let op = ArmOp::F64Div {
8196 dd: VfpReg::D0,
8197 dn: VfpReg::D1,
8198 dm: VfpReg::D2,
8199 };
8200 let code = encoder.encode(&op).unwrap();
8201 assert_eq!(code.len(), 4);
8202 }
8203
8204 #[test]
8205 fn test_encode_f64_abs_arm32() {
8206 let encoder = ArmEncoder::new_arm32();
8207 let op = ArmOp::F64Abs {
8208 dd: VfpReg::D0,
8209 dm: VfpReg::D2,
8210 };
8211 let code = encoder.encode(&op).unwrap();
8212 assert_eq!(code.len(), 4);
8213 }
8214
8215 #[test]
8216 fn test_encode_f64_neg_arm32() {
8217 let encoder = ArmEncoder::new_arm32();
8218 let op = ArmOp::F64Neg {
8219 dd: VfpReg::D0,
8220 dm: VfpReg::D2,
8221 };
8222 let code = encoder.encode(&op).unwrap();
8223 assert_eq!(code.len(), 4);
8224 }
8225
8226 #[test]
8227 fn test_encode_f64_sqrt_arm32() {
8228 let encoder = ArmEncoder::new_arm32();
8229 let op = ArmOp::F64Sqrt {
8230 dd: VfpReg::D0,
8231 dm: VfpReg::D2,
8232 };
8233 let code = encoder.encode(&op).unwrap();
8234 assert_eq!(code.len(), 4);
8235 }
8236
8237 #[test]
8238 fn test_encode_f64_load_arm32() {
8239 let encoder = ArmEncoder::new_arm32();
8240 let op = ArmOp::F64Load {
8241 dd: VfpReg::D0,
8242 addr: MemAddr::imm(Reg::R0, 8),
8243 };
8244 let code = encoder.encode(&op).unwrap();
8245 assert_eq!(code.len(), 4);
8246 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8247 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
8250
8251 #[test]
8252 fn test_encode_f64_store_thumb2() {
8253 let encoder = ArmEncoder::new_thumb2();
8254 let op = ArmOp::F64Store {
8255 dd: VfpReg::D0,
8256 addr: MemAddr::imm(Reg::SP, 0),
8257 };
8258 let code = encoder.encode(&op).unwrap();
8259 assert_eq!(code.len(), 4);
8260 }
8261
8262 #[test]
8263 fn test_encode_f64_compare_arm32() {
8264 let encoder = ArmEncoder::new_arm32();
8265 let op = ArmOp::F64Eq {
8266 rd: Reg::R0,
8267 dn: VfpReg::D0,
8268 dm: VfpReg::D1,
8269 };
8270 let code = encoder.encode(&op).unwrap();
8271 assert_eq!(code.len(), 16); }
8273
8274 #[test]
8275 fn test_encode_f64_compare_thumb2() {
8276 let encoder = ArmEncoder::new_thumb2();
8277 let op = ArmOp::F64Lt {
8278 rd: Reg::R0,
8279 dn: VfpReg::D0,
8280 dm: VfpReg::D1,
8281 };
8282 let code = encoder.encode(&op).unwrap();
8283 assert_eq!(code.len(), 14);
8285 }
8286
8287 #[test]
8288 fn test_encode_f64_const_arm32() {
8289 let encoder = ArmEncoder::new_arm32();
8290 let op = ArmOp::F64Const {
8291 dd: VfpReg::D0,
8292 value: 3.125,
8293 };
8294 let code = encoder.encode(&op).unwrap();
8295 assert_eq!(code.len(), 20);
8297 }
8298
8299 #[test]
8300 fn test_encode_f64_const_thumb2() {
8301 let encoder = ArmEncoder::new_thumb2();
8302 let op = ArmOp::F64Const {
8303 dd: VfpReg::D0,
8304 value: 2.5,
8305 };
8306 let code = encoder.encode(&op).unwrap();
8307 assert_eq!(code.len(), 20);
8309 }
8310
8311 #[test]
8312 fn test_encode_f64_convert_i32s_arm32() {
8313 let encoder = ArmEncoder::new_arm32();
8314 let op = ArmOp::F64ConvertI32S {
8315 dd: VfpReg::D0,
8316 rm: Reg::R0,
8317 };
8318 let code = encoder.encode(&op).unwrap();
8319 assert_eq!(code.len(), 8);
8321 }
8322
8323 #[test]
8324 fn test_encode_f64_promote_f32_arm32() {
8325 let encoder = ArmEncoder::new_arm32();
8326 let op = ArmOp::F64PromoteF32 {
8327 dd: VfpReg::D0,
8328 sm: VfpReg::S0,
8329 };
8330 let code = encoder.encode(&op).unwrap();
8331 assert_eq!(code.len(), 4); }
8333
8334 #[test]
8335 fn test_encode_f64_promote_f32_thumb2() {
8336 let encoder = ArmEncoder::new_thumb2();
8337 let op = ArmOp::F64PromoteF32 {
8338 dd: VfpReg::D0,
8339 sm: VfpReg::S0,
8340 };
8341 let code = encoder.encode(&op).unwrap();
8342 assert_eq!(code.len(), 4);
8343 }
8344
8345 #[test]
8346 fn test_encode_i32_trunc_f64s_arm32() {
8347 let encoder = ArmEncoder::new_arm32();
8348 let op = ArmOp::I32TruncF64S {
8349 rd: Reg::R0,
8350 dm: VfpReg::D0,
8351 };
8352 let code = encoder.encode(&op).unwrap();
8353 assert_eq!(code.len(), 8);
8355 }
8356
8357 #[test]
8358 fn test_encode_f64_reinterpret_i64_arm32() {
8359 let encoder = ArmEncoder::new_arm32();
8360 let op = ArmOp::F64ReinterpretI64 {
8361 dd: VfpReg::D0,
8362 rmlo: Reg::R0,
8363 rmhi: Reg::R1,
8364 };
8365 let code = encoder.encode(&op).unwrap();
8366 assert_eq!(code.len(), 4); }
8368
8369 #[test]
8370 fn test_encode_i64_reinterpret_f64_thumb2() {
8371 let encoder = ArmEncoder::new_thumb2();
8372 let op = ArmOp::I64ReinterpretF64 {
8373 rdlo: Reg::R0,
8374 rdhi: Reg::R1,
8375 dm: VfpReg::D0,
8376 };
8377 let code = encoder.encode(&op).unwrap();
8378 assert_eq!(code.len(), 4);
8379 }
8380
8381 #[test]
8382 fn test_encode_f64_trunc_thumb2() {
8383 let encoder = ArmEncoder::new_thumb2();
8384 let op = ArmOp::F64Trunc {
8385 dd: VfpReg::D0,
8386 dm: VfpReg::D1,
8387 };
8388 let code = encoder.encode(&op).unwrap();
8389 assert_eq!(code.len(), 8);
8391 }
8392
8393 #[test]
8394 fn test_encode_f64_min_arm32() {
8395 let encoder = ArmEncoder::new_arm32();
8396 let op = ArmOp::F64Min {
8397 dd: VfpReg::D0,
8398 dn: VfpReg::D1,
8399 dm: VfpReg::D2,
8400 };
8401 let code = encoder.encode(&op).unwrap();
8402 assert_eq!(code.len(), 16);
8404 }
8405
8406 #[test]
8407 fn test_f64_cp11_encoding() {
8408 let encoder = ArmEncoder::new_arm32();
8410
8411 let code = encoder
8413 .encode(&ArmOp::F64Add {
8414 dd: VfpReg::D0,
8415 dn: VfpReg::D0,
8416 dm: VfpReg::D0,
8417 })
8418 .unwrap();
8419 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8420 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8421
8422 let code = encoder
8424 .encode(&ArmOp::F32Add {
8425 sd: VfpReg::S0,
8426 sn: VfpReg::S0,
8427 sm: VfpReg::S0,
8428 })
8429 .unwrap();
8430 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8431 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8432 }
8433
8434 #[test]
8435 fn test_dreg_encoding_higher_registers() {
8436 let encoder = ArmEncoder::new_arm32();
8437
8438 let op = ArmOp::F64Add {
8440 dd: VfpReg::D15,
8441 dn: VfpReg::D14,
8442 dm: VfpReg::D13,
8443 };
8444 let code = encoder.encode(&op).unwrap();
8445 assert_eq!(code.len(), 4);
8446
8447 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8449 assert_eq!((instr >> 8) & 0xF, 0xB); }
8451
8452 #[test]
8457 fn test_encode_label_emits_no_bytes() {
8458 let encoder = ArmEncoder::new_thumb2();
8459 let op = ArmOp::Label {
8460 name: ".Lblock_end_0".to_string(),
8461 };
8462 let code = encoder.encode(&op).unwrap();
8463 assert!(code.is_empty(), "Label should emit zero bytes");
8464
8465 let encoder32 = ArmEncoder::new_arm32();
8466 let code32 = encoder32.encode(&op).unwrap();
8467 assert!(
8468 code32.is_empty(),
8469 "Label should emit zero bytes in ARM32 too"
8470 );
8471 }
8472
8473 #[test]
8474 fn test_encode_bcc_eq_thumb2() {
8475 use synth_synthesis::Condition;
8476 let encoder = ArmEncoder::new_thumb2();
8477 let op = ArmOp::Bcc {
8478 cond: Condition::EQ,
8479 label: "target".to_string(),
8480 };
8481 let code = encoder.encode(&op).unwrap();
8482 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8486 }
8487
8488 #[test]
8489 fn test_encode_bcc_ne_thumb2() {
8490 use synth_synthesis::Condition;
8491 let encoder = ArmEncoder::new_thumb2();
8492 let op = ArmOp::Bcc {
8493 cond: Condition::NE,
8494 label: "target".to_string(),
8495 };
8496 let code = encoder.encode(&op).unwrap();
8497 assert_eq!(code.len(), 2);
8498
8499 assert_eq!(code, vec![0x00, 0xD1]);
8501 }
8502
8503 #[test]
8504 fn test_encode_bcc_arm32() {
8505 use synth_synthesis::Condition;
8506 let encoder = ArmEncoder::new_arm32();
8507 let op = ArmOp::Bcc {
8508 cond: Condition::EQ,
8509 label: "target".to_string(),
8510 };
8511 let code = encoder.encode(&op).unwrap();
8512 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8515 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8519
8520 #[test]
8521 fn test_encode_udf_thumb2() {
8522 let encoder = ArmEncoder::new_thumb2();
8523 let op = ArmOp::Udf { imm: 0 };
8524 let code = encoder.encode(&op).unwrap();
8525 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8529 }
8530
8531 #[test]
8532 fn test_encode_nop_thumb2() {
8533 let encoder = ArmEncoder::new_thumb2();
8534 let op = ArmOp::Nop;
8535 let code = encoder.encode(&op).unwrap();
8536 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8540 }
8541
8542 #[test]
8547 fn test_encode_i64_add_thumb2() {
8548 let encoder = ArmEncoder::new_thumb2();
8549 let op = ArmOp::I64Add {
8550 rdlo: Reg::R0,
8551 rdhi: Reg::R1,
8552 rnlo: Reg::R0,
8553 rnhi: Reg::R1,
8554 rmlo: Reg::R2,
8555 rmhi: Reg::R3,
8556 };
8557 let code = encoder.encode(&op).unwrap();
8558 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8560 }
8561
8562 #[test]
8563 fn test_encode_i64_sub_thumb2() {
8564 let encoder = ArmEncoder::new_thumb2();
8565 let op = ArmOp::I64Sub {
8566 rdlo: Reg::R0,
8567 rdhi: Reg::R1,
8568 rnlo: Reg::R0,
8569 rnhi: Reg::R1,
8570 rmlo: Reg::R2,
8571 rmhi: Reg::R3,
8572 };
8573 let code = encoder.encode(&op).unwrap();
8574 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8576 }
8577
8578 #[test]
8579 fn test_encode_i64_and_thumb2() {
8580 let encoder = ArmEncoder::new_thumb2();
8581 let op = ArmOp::I64And {
8582 rdlo: Reg::R0,
8583 rdhi: Reg::R1,
8584 rnlo: Reg::R0,
8585 rnhi: Reg::R1,
8586 rmlo: Reg::R2,
8587 rmhi: Reg::R3,
8588 };
8589 let code = encoder.encode(&op).unwrap();
8590 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8592 }
8593
8594 #[test]
8595 fn test_encode_i64_or_thumb2() {
8596 let encoder = ArmEncoder::new_thumb2();
8597 let op = ArmOp::I64Or {
8598 rdlo: Reg::R0,
8599 rdhi: Reg::R1,
8600 rnlo: Reg::R0,
8601 rnhi: Reg::R1,
8602 rmlo: Reg::R2,
8603 rmhi: Reg::R3,
8604 };
8605 let code = encoder.encode(&op).unwrap();
8606 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8607 }
8608
8609 #[test]
8610 fn test_encode_i64_xor_thumb2() {
8611 let encoder = ArmEncoder::new_thumb2();
8612 let op = ArmOp::I64Xor {
8613 rdlo: Reg::R0,
8614 rdhi: Reg::R1,
8615 rnlo: Reg::R0,
8616 rnhi: Reg::R1,
8617 rmlo: Reg::R2,
8618 rmhi: Reg::R3,
8619 };
8620 let code = encoder.encode(&op).unwrap();
8621 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8622 }
8623
8624 #[test]
8625 fn test_encode_i64_const_small_thumb2() {
8626 let encoder = ArmEncoder::new_thumb2();
8627 let op = ArmOp::I64Const {
8629 rdlo: Reg::R0,
8630 rdhi: Reg::R1,
8631 value: 42,
8632 };
8633 let code = encoder.encode(&op).unwrap();
8634 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8636 }
8637
8638 #[test]
8639 fn test_encode_i64_const_large_thumb2() {
8640 let encoder = ArmEncoder::new_thumb2();
8641 let op = ArmOp::I64Const {
8643 rdlo: Reg::R0,
8644 rdhi: Reg::R1,
8645 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8646 };
8647 let code = encoder.encode(&op).unwrap();
8648 assert_eq!(
8650 code.len(),
8651 16,
8652 "I64Const with large value should be 16 bytes"
8653 );
8654 }
8655
8656 #[test]
8657 fn test_encode_i64_extend_i32_s_thumb2() {
8658 let encoder = ArmEncoder::new_thumb2();
8659 let op = ArmOp::I64ExtendI32S {
8660 rdlo: Reg::R0,
8661 rdhi: Reg::R1,
8662 rn: Reg::R0,
8663 };
8664 let code = encoder.encode(&op).unwrap();
8665 assert_eq!(
8667 code.len(),
8668 4,
8669 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8670 );
8671 }
8672
8673 #[test]
8674 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8675 let encoder = ArmEncoder::new_thumb2();
8676 let op = ArmOp::I64ExtendI32S {
8677 rdlo: Reg::R0,
8678 rdhi: Reg::R1,
8679 rn: Reg::R2,
8680 };
8681 let code = encoder.encode(&op).unwrap();
8682 assert!(
8684 code.len() >= 6,
8685 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8686 );
8687 }
8688
8689 #[test]
8690 fn test_encode_i64_extend_i32_u_thumb2() {
8691 let encoder = ArmEncoder::new_thumb2();
8692 let op = ArmOp::I64ExtendI32U {
8693 rdlo: Reg::R0,
8694 rdhi: Reg::R1,
8695 rn: Reg::R0,
8696 };
8697 let code = encoder.encode(&op).unwrap();
8698 assert_eq!(
8700 code.len(),
8701 2,
8702 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8703 );
8704 }
8705
8706 #[test]
8707 fn test_encode_i32_wrap_i64_nop_thumb2() {
8708 let encoder = ArmEncoder::new_thumb2();
8709 let op = ArmOp::I32WrapI64 {
8711 rd: Reg::R0,
8712 rnlo: Reg::R0,
8713 };
8714 let code = encoder.encode(&op).unwrap();
8715 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8716 assert_eq!(code, vec![0x00, 0xBF]); }
8718
8719 #[test]
8720 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8721 let encoder = ArmEncoder::new_thumb2();
8722 let op = ArmOp::I32WrapI64 {
8723 rd: Reg::R2,
8724 rnlo: Reg::R0,
8725 };
8726 let code = encoder.encode(&op).unwrap();
8727 assert!(
8729 code.len() >= 2,
8730 "I32WrapI64 diff reg should emit at least 2 bytes"
8731 );
8732 }
8733
8734 #[test]
8735 fn test_encode_i64_eqz_thumb2() {
8736 let encoder = ArmEncoder::new_thumb2();
8737 let op = ArmOp::I64Eqz {
8738 rd: Reg::R0,
8739 rnlo: Reg::R0,
8740 rnhi: Reg::R1,
8741 };
8742 let code = encoder.encode(&op).unwrap();
8743 assert!(
8745 code.len() >= 6,
8746 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8747 );
8748 }
8749
8750 #[test]
8751 fn test_encode_i64_eq_thumb2() {
8752 let encoder = ArmEncoder::new_thumb2();
8753 let op = ArmOp::I64Eq {
8754 rd: Reg::R0,
8755 rnlo: Reg::R0,
8756 rnhi: Reg::R1,
8757 rmlo: Reg::R2,
8758 rmhi: Reg::R3,
8759 };
8760 let code = encoder.encode(&op).unwrap();
8761 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8763 }
8764
8765 #[test]
8766 fn test_encode_i64_ldr_thumb2() {
8767 let encoder = ArmEncoder::new_thumb2();
8768 let op = ArmOp::I64Ldr {
8769 rdlo: Reg::R0,
8770 rdhi: Reg::R1,
8771 addr: MemAddr::imm(Reg::SP, 0),
8772 };
8773 let code = encoder.encode(&op).unwrap();
8774 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8776 }
8777
8778 #[test]
8779 fn test_encode_i64_str_thumb2() {
8780 let encoder = ArmEncoder::new_thumb2();
8781 let op = ArmOp::I64Str {
8782 rdlo: Reg::R0,
8783 rdhi: Reg::R1,
8784 addr: MemAddr::imm(Reg::SP, 0),
8785 };
8786 let code = encoder.encode(&op).unwrap();
8787 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8789 }
8790
8791 #[test]
8792 fn test_encode_i64_all_comparisons_thumb2() {
8793 let encoder = ArmEncoder::new_thumb2();
8794
8795 let ops = vec![
8796 ArmOp::I64Ne {
8797 rd: Reg::R0,
8798 rnlo: Reg::R0,
8799 rnhi: Reg::R1,
8800 rmlo: Reg::R2,
8801 rmhi: Reg::R3,
8802 },
8803 ArmOp::I64LtS {
8804 rd: Reg::R0,
8805 rnlo: Reg::R0,
8806 rnhi: Reg::R1,
8807 rmlo: Reg::R2,
8808 rmhi: Reg::R3,
8809 },
8810 ArmOp::I64LtU {
8811 rd: Reg::R0,
8812 rnlo: Reg::R0,
8813 rnhi: Reg::R1,
8814 rmlo: Reg::R2,
8815 rmhi: Reg::R3,
8816 },
8817 ArmOp::I64LeS {
8818 rd: Reg::R0,
8819 rnlo: Reg::R0,
8820 rnhi: Reg::R1,
8821 rmlo: Reg::R2,
8822 rmhi: Reg::R3,
8823 },
8824 ArmOp::I64LeU {
8825 rd: Reg::R0,
8826 rnlo: Reg::R0,
8827 rnhi: Reg::R1,
8828 rmlo: Reg::R2,
8829 rmhi: Reg::R3,
8830 },
8831 ArmOp::I64GtS {
8832 rd: Reg::R0,
8833 rnlo: Reg::R0,
8834 rnhi: Reg::R1,
8835 rmlo: Reg::R2,
8836 rmhi: Reg::R3,
8837 },
8838 ArmOp::I64GtU {
8839 rd: Reg::R0,
8840 rnlo: Reg::R0,
8841 rnhi: Reg::R1,
8842 rmlo: Reg::R2,
8843 rmhi: Reg::R3,
8844 },
8845 ArmOp::I64GeS {
8846 rd: Reg::R0,
8847 rnlo: Reg::R0,
8848 rnhi: Reg::R1,
8849 rmlo: Reg::R2,
8850 rmhi: Reg::R3,
8851 },
8852 ArmOp::I64GeU {
8853 rd: Reg::R0,
8854 rnlo: Reg::R0,
8855 rnhi: Reg::R1,
8856 rmlo: Reg::R2,
8857 rmhi: Reg::R3,
8858 },
8859 ];
8860
8861 for op in &ops {
8862 let code = encoder.encode(op).unwrap();
8863 assert!(
8864 code.len() >= 8,
8865 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8866 op,
8867 code.len()
8868 );
8869 }
8870 }
8871
8872 #[test]
8873 fn test_encode_i64_const_zero_thumb2() {
8874 let encoder = ArmEncoder::new_thumb2();
8875 let op = ArmOp::I64Const {
8876 rdlo: Reg::R0,
8877 rdhi: Reg::R1,
8878 value: 0,
8879 };
8880 let code = encoder.encode(&op).unwrap();
8881 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8883 }
8884
8885 #[test]
8886 fn test_encode_i64_const_negative_one_thumb2() {
8887 let encoder = ArmEncoder::new_thumb2();
8888 let op = ArmOp::I64Const {
8889 rdlo: Reg::R0,
8890 rdhi: Reg::R1,
8891 value: -1, };
8893 let code = encoder.encode(&op).unwrap();
8894 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8896 }
8897
8898 #[test]
8903 fn test_encode_ldrb_arm32() {
8904 let encoder = ArmEncoder::new_arm32();
8905 let op = ArmOp::Ldrb {
8906 rd: Reg::R0,
8907 addr: MemAddr::imm(Reg::R1, 4),
8908 };
8909 let code = encoder.encode(&op).unwrap();
8910 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8911 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8913 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8914 }
8915
8916 #[test]
8917 fn test_encode_strb_arm32() {
8918 let encoder = ArmEncoder::new_arm32();
8919 let op = ArmOp::Strb {
8920 rd: Reg::R0,
8921 addr: MemAddr::imm(Reg::R1, 0),
8922 };
8923 let code = encoder.encode(&op).unwrap();
8924 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8925 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8927 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8928 }
8929
8930 #[test]
8931 fn test_encode_ldrh_arm32() {
8932 let encoder = ArmEncoder::new_arm32();
8933 let op = ArmOp::Ldrh {
8934 rd: Reg::R0,
8935 addr: MemAddr::imm(Reg::R1, 2),
8936 };
8937 let code = encoder.encode(&op).unwrap();
8938 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8939 }
8940
8941 #[test]
8942 fn test_encode_strh_arm32() {
8943 let encoder = ArmEncoder::new_arm32();
8944 let op = ArmOp::Strh {
8945 rd: Reg::R0,
8946 addr: MemAddr::imm(Reg::R1, 0),
8947 };
8948 let code = encoder.encode(&op).unwrap();
8949 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8950 }
8951
8952 #[test]
8953 fn test_encode_ldrsb_arm32() {
8954 let encoder = ArmEncoder::new_arm32();
8955 let op = ArmOp::Ldrsb {
8956 rd: Reg::R0,
8957 addr: MemAddr::imm(Reg::R1, 0),
8958 };
8959 let code = encoder.encode(&op).unwrap();
8960 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8961 }
8962
8963 #[test]
8964 fn test_encode_ldrsh_arm32() {
8965 let encoder = ArmEncoder::new_arm32();
8966 let op = ArmOp::Ldrsh {
8967 rd: Reg::R0,
8968 addr: MemAddr::imm(Reg::R1, 0),
8969 };
8970 let code = encoder.encode(&op).unwrap();
8971 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8972 }
8973
8974 #[test]
8975 fn test_encode_ldrb_thumb2_16bit() {
8976 let encoder = ArmEncoder::new_thumb2();
8977 let op = ArmOp::Ldrb {
8978 rd: Reg::R0,
8979 addr: MemAddr::imm(Reg::R1, 4),
8980 };
8981 let code = encoder.encode(&op).unwrap();
8982 assert_eq!(
8984 code.len(),
8985 2,
8986 "Thumb-2 LDRB with small offset should be 16-bit"
8987 );
8988 }
8989
8990 #[test]
8991 fn test_encode_ldrb_thumb2_32bit() {
8992 let encoder = ArmEncoder::new_thumb2();
8993 let op = ArmOp::Ldrb {
8994 rd: Reg::R0,
8995 addr: MemAddr::imm(Reg::R1, 100), };
8997 let code = encoder.encode(&op).unwrap();
8998 assert_eq!(
8999 code.len(),
9000 4,
9001 "Thumb-2 LDRB with large offset should be 32-bit"
9002 );
9003 }
9004
9005 #[test]
9006 fn test_encode_strb_thumb2_16bit() {
9007 let encoder = ArmEncoder::new_thumb2();
9008 let op = ArmOp::Strb {
9009 rd: Reg::R0,
9010 addr: MemAddr::imm(Reg::R1, 10),
9011 };
9012 let code = encoder.encode(&op).unwrap();
9013 assert_eq!(
9014 code.len(),
9015 2,
9016 "Thumb-2 STRB with small offset should be 16-bit"
9017 );
9018 }
9019
9020 #[test]
9021 fn test_encode_ldrh_thumb2_16bit() {
9022 let encoder = ArmEncoder::new_thumb2();
9023 let op = ArmOp::Ldrh {
9024 rd: Reg::R0,
9025 addr: MemAddr::imm(Reg::R1, 4), };
9027 let code = encoder.encode(&op).unwrap();
9028 assert_eq!(
9029 code.len(),
9030 2,
9031 "Thumb-2 LDRH with small aligned offset should be 16-bit"
9032 );
9033 }
9034
9035 #[test]
9036 fn test_encode_strh_thumb2_16bit() {
9037 let encoder = ArmEncoder::new_thumb2();
9038 let op = ArmOp::Strh {
9039 rd: Reg::R0,
9040 addr: MemAddr::imm(Reg::R1, 4),
9041 };
9042 let code = encoder.encode(&op).unwrap();
9043 assert_eq!(
9044 code.len(),
9045 2,
9046 "Thumb-2 STRH with small aligned offset should be 16-bit"
9047 );
9048 }
9049
9050 #[test]
9051 fn test_encode_ldrsb_thumb2() {
9052 let encoder = ArmEncoder::new_thumb2();
9053 let op = ArmOp::Ldrsb {
9054 rd: Reg::R0,
9055 addr: MemAddr::imm(Reg::R1, 0),
9056 };
9057 let code = encoder.encode(&op).unwrap();
9058 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
9060 }
9061
9062 #[test]
9063 fn test_encode_ldrsh_thumb2() {
9064 let encoder = ArmEncoder::new_thumb2();
9065 let op = ArmOp::Ldrsh {
9066 rd: Reg::R0,
9067 addr: MemAddr::imm(Reg::R1, 0),
9068 };
9069 let code = encoder.encode(&op).unwrap();
9070 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
9071 }
9072
9073 #[test]
9074 fn test_encode_memory_size_thumb2() {
9075 let encoder = ArmEncoder::new_thumb2();
9076 let op = ArmOp::MemorySize { rd: Reg::R0 };
9077 let code = encoder.encode(&op).unwrap();
9078 assert!(!code.is_empty(), "MemorySize should produce code");
9080 }
9081
9082 #[test]
9083 fn test_encode_memory_grow_thumb2() {
9084 let encoder = ArmEncoder::new_thumb2();
9085 let op = ArmOp::MemoryGrow {
9086 rd: Reg::R0,
9087 rn: Reg::R0,
9088 };
9089 let code = encoder.encode(&op).unwrap();
9090 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
9091 }
9092
9093 #[test]
9094 fn test_encode_subword_reg_offset_thumb2() {
9095 let encoder = ArmEncoder::new_thumb2();
9096
9097 let op = ArmOp::Ldrb {
9099 rd: Reg::R0,
9100 addr: MemAddr::reg(Reg::R1, Reg::R2),
9101 };
9102 let code = encoder.encode(&op).unwrap();
9103 assert_eq!(
9104 code.len(),
9105 4,
9106 "Thumb-2 LDRB with reg offset should be 32-bit"
9107 );
9108
9109 let op = ArmOp::Strb {
9111 rd: Reg::R0,
9112 addr: MemAddr::reg(Reg::R1, Reg::R2),
9113 };
9114 let code = encoder.encode(&op).unwrap();
9115 assert_eq!(
9116 code.len(),
9117 4,
9118 "Thumb-2 STRB with reg offset should be 32-bit"
9119 );
9120
9121 let op = ArmOp::Ldrh {
9123 rd: Reg::R0,
9124 addr: MemAddr::reg(Reg::R1, Reg::R2),
9125 };
9126 let code = encoder.encode(&op).unwrap();
9127 assert_eq!(
9128 code.len(),
9129 4,
9130 "Thumb-2 LDRH with reg offset should be 32-bit"
9131 );
9132
9133 let op = ArmOp::Strh {
9135 rd: Reg::R0,
9136 addr: MemAddr::reg(Reg::R1, Reg::R2),
9137 };
9138 let code = encoder.encode(&op).unwrap();
9139 assert_eq!(
9140 code.len(),
9141 4,
9142 "Thumb-2 STRH with reg offset should be 32-bit"
9143 );
9144 }
9145
9146 #[test]
9147 fn test_encode_subword_reg_imm_offset_thumb2() {
9148 let encoder = ArmEncoder::new_thumb2();
9149
9150 let op = ArmOp::Ldrb {
9152 rd: Reg::R0,
9153 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
9154 };
9155 let code = encoder.encode(&op).unwrap();
9156 assert_eq!(
9158 code.len(),
9159 8,
9160 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
9161 );
9162 }
9163
9164 #[test]
9169 fn test_encode_mve_addi32_thumb2() {
9170 let encoder = ArmEncoder::new_thumb2();
9171 let op = ArmOp::MveAddI {
9172 qd: QReg::Q0,
9173 qn: QReg::Q1,
9174 qm: QReg::Q2,
9175 size: MveSize::S32,
9176 };
9177 let code = encoder.encode(&op).unwrap();
9178 assert_eq!(
9179 code.len(),
9180 4,
9181 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
9182 );
9183 }
9184
9185 #[test]
9186 fn test_encode_mve_subi16_thumb2() {
9187 let encoder = ArmEncoder::new_thumb2();
9188 let op = ArmOp::MveSubI {
9189 qd: QReg::Q0,
9190 qn: QReg::Q1,
9191 qm: QReg::Q2,
9192 size: MveSize::S16,
9193 };
9194 let code = encoder.encode(&op).unwrap();
9195 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
9196 }
9197
9198 #[test]
9199 fn test_encode_mve_muli8_thumb2() {
9200 let encoder = ArmEncoder::new_thumb2();
9201 let op = ArmOp::MveMulI {
9202 qd: QReg::Q0,
9203 qn: QReg::Q1,
9204 qm: QReg::Q2,
9205 size: MveSize::S8,
9206 };
9207 let code = encoder.encode(&op).unwrap();
9208 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
9209 }
9210
9211 #[test]
9212 fn test_encode_mve_bitwise_thumb2() {
9213 let encoder = ArmEncoder::new_thumb2();
9214
9215 let ops = vec![
9216 ArmOp::MveAnd {
9217 qd: QReg::Q0,
9218 qn: QReg::Q1,
9219 qm: QReg::Q2,
9220 },
9221 ArmOp::MveOrr {
9222 qd: QReg::Q0,
9223 qn: QReg::Q1,
9224 qm: QReg::Q2,
9225 },
9226 ArmOp::MveEor {
9227 qd: QReg::Q0,
9228 qn: QReg::Q1,
9229 qm: QReg::Q2,
9230 },
9231 ArmOp::MveBic {
9232 qd: QReg::Q0,
9233 qn: QReg::Q1,
9234 qm: QReg::Q2,
9235 },
9236 ];
9237 for op in ops {
9238 let code = encoder.encode(&op).unwrap();
9239 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
9240 }
9241 }
9242
9243 #[test]
9244 fn test_encode_mve_mvn_thumb2() {
9245 let encoder = ArmEncoder::new_thumb2();
9246 let op = ArmOp::MveMvn {
9247 qd: QReg::Q0,
9248 qm: QReg::Q1,
9249 };
9250 let code = encoder.encode(&op).unwrap();
9251 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
9252 }
9253
9254 #[test]
9255 fn test_encode_mve_load_store_thumb2() {
9256 let encoder = ArmEncoder::new_thumb2();
9257
9258 let load = ArmOp::MveLoad {
9259 qd: QReg::Q0,
9260 addr: MemAddr::imm(Reg::R0, 16),
9261 };
9262 let code = encoder.encode(&load).unwrap();
9263 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
9264
9265 let store = ArmOp::MveStore {
9266 qd: QReg::Q1,
9267 addr: MemAddr::imm(Reg::R1, 0),
9268 };
9269 let code = encoder.encode(&store).unwrap();
9270 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
9271 }
9272
9273 #[test]
9274 fn test_encode_mve_const_thumb2() {
9275 let encoder = ArmEncoder::new_thumb2();
9276 let op = ArmOp::MveConst {
9277 qd: QReg::Q0,
9278 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
9279 };
9280 let code = encoder.encode(&op).unwrap();
9281 assert!(
9284 code.len() >= 24,
9285 "MVE const should produce multiple instructions"
9286 );
9287 }
9288
9289 #[test]
9290 fn test_encode_mve_dup_thumb2() {
9291 let encoder = ArmEncoder::new_thumb2();
9292 let op = ArmOp::MveDup {
9293 qd: QReg::Q0,
9294 rn: Reg::R0,
9295 size: MveSize::S32,
9296 };
9297 let code = encoder.encode(&op).unwrap();
9298 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
9299 }
9300
9301 #[test]
9302 fn test_encode_mve_extract_lane_thumb2() {
9303 let encoder = ArmEncoder::new_thumb2();
9304 let op = ArmOp::MveExtractLane {
9305 rd: Reg::R0,
9306 qn: QReg::Q1,
9307 lane: 2,
9308 size: MveSize::S32,
9309 };
9310 let code = encoder.encode(&op).unwrap();
9311 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
9312 }
9313
9314 #[test]
9315 fn test_encode_mve_insert_lane_thumb2() {
9316 let encoder = ArmEncoder::new_thumb2();
9317 let op = ArmOp::MveInsertLane {
9318 qd: QReg::Q0,
9319 rn: Reg::R1,
9320 lane: 3,
9321 size: MveSize::S32,
9322 };
9323 let code = encoder.encode(&op).unwrap();
9324 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9325 }
9326
9327 #[test]
9328 fn test_encode_mve_addf32_thumb2() {
9329 let encoder = ArmEncoder::new_thumb2();
9330 let op = ArmOp::MveAddF32 {
9331 qd: QReg::Q0,
9332 qn: QReg::Q1,
9333 qm: QReg::Q2,
9334 };
9335 let code = encoder.encode(&op).unwrap();
9336 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9337 }
9338
9339 #[test]
9340 fn test_encode_mve_divf32_thumb2() {
9341 let encoder = ArmEncoder::new_thumb2();
9342 let op = ArmOp::MveDivF32 {
9343 qd: QReg::Q0,
9344 qn: QReg::Q1,
9345 qm: QReg::Q2,
9346 };
9347 let code = encoder.encode(&op).unwrap();
9348 assert_eq!(
9350 code.len(),
9351 16,
9352 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9353 );
9354 }
9355
9356 #[test]
9357 fn test_encode_mve_sqrtf32_thumb2() {
9358 let encoder = ArmEncoder::new_thumb2();
9359 let op = ArmOp::MveSqrtF32 {
9360 qd: QReg::Q0,
9361 qm: QReg::Q1,
9362 };
9363 let code = encoder.encode(&op).unwrap();
9364 assert_eq!(
9366 code.len(),
9367 16,
9368 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9369 );
9370 }
9371
9372 #[test]
9373 fn test_encode_mve_negf32_thumb2() {
9374 let encoder = ArmEncoder::new_thumb2();
9375 let op = ArmOp::MveNegF32 {
9376 qd: QReg::Q0,
9377 qm: QReg::Q1,
9378 };
9379 let code = encoder.encode(&op).unwrap();
9380 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9381 }
9382
9383 #[test]
9384 fn test_encode_mve_absf32_thumb2() {
9385 let encoder = ArmEncoder::new_thumb2();
9386 let op = ArmOp::MveAbsF32 {
9387 qd: QReg::Q0,
9388 qm: QReg::Q1,
9389 };
9390 let code = encoder.encode(&op).unwrap();
9391 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9392 }
9393
9394 #[test]
9409 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9410 let encoder = ArmEncoder::new_thumb2();
9411 let op = ArmOp::And {
9412 rd: Reg::R2,
9413 rn: Reg::R0,
9414 op2: Operand2::Imm(0x7e),
9415 };
9416 let code = encoder.encode(&op).unwrap();
9417 assert_eq!(
9418 code,
9419 vec![0x00, 0xf0, 0x7e, 0x02],
9420 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9421 );
9422 }
9423
9424 #[test]
9431 fn try_thumb_expand_imm_encodes_modified_immediates() {
9432 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9434 assert_eq!(try_thumb_expand_imm(0x0001_0001), Some(0x101)); assert_eq!(try_thumb_expand_imm(0xff00_ff00), Some(0x2ff)); assert_eq!(try_thumb_expand_imm(0xffff_ffff), Some(0x3ff)); assert_eq!(try_thumb_expand_imm(0x100), Some(0xf80)); assert_eq!(try_thumb_expand_imm(0x8000_0000), Some(0x400)); assert_eq!(try_thumb_expand_imm(1000), Some(0xf7a)); assert_eq!(try_thumb_expand_imm(0x101), None);
9442 assert_eq!(try_thumb_expand_imm(0x12345), None);
9443 }
9444
9445 #[test]
9450 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9451 let encoder = ArmEncoder::new_thumb2();
9452 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9454 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9455 assert!(
9457 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9458 "cmp #0x101 must error, not compare the wrong constant"
9459 );
9460 assert!(
9461 encoder
9462 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9463 .is_err()
9464 );
9465 assert!(
9466 encoder
9467 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9468 .is_err()
9469 );
9470 assert!(
9472 encoder
9473 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9474 .is_ok()
9475 );
9476 }
9477
9478 #[test]
9481 fn mla_thumb2_encodes_correctly() {
9482 let encoder = ArmEncoder::new_thumb2();
9483 let code = encoder
9484 .encode(&ArmOp::Mla {
9485 rd: Reg::R2,
9486 rn: Reg::R3,
9487 rm: Reg::R4,
9488 ra: Reg::R8,
9489 })
9490 .unwrap();
9491 assert_eq!(code, vec![0x03, 0xfb, 0x04, 0x82]);
9493 }
9494
9495 #[test]
9500 fn ldst_imm12_offset_errors_when_out_of_range() {
9501 let encoder = ArmEncoder::new_thumb2();
9502 assert!(
9504 encoder
9505 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0xFFF)
9506 .is_ok()
9507 );
9508 assert!(
9510 encoder
9511 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0x1000)
9512 .is_err(),
9513 "ldr offset 4096 must error, not wrap to 0"
9514 );
9515 assert!(
9516 encoder
9517 .encode_thumb32_str(&Reg::R0, &Reg::R1, 0x1000)
9518 .is_err()
9519 );
9520 assert!(
9521 encoder
9522 .encode_thumb32_ldrb_imm(&Reg::R0, &Reg::R1, 5000)
9523 .is_err()
9524 );
9525 assert!(
9526 encoder
9527 .encode_thumb32_strh_imm(&Reg::R0, &Reg::R1, 5000)
9528 .is_err()
9529 );
9530 }
9531
9532 #[test]
9539 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9540 let encoder = ArmEncoder::new_thumb2();
9541 assert_eq!(
9543 encoder
9544 .encode(&ArmOp::Add {
9545 rd: Reg::SP,
9546 rn: Reg::SP,
9547 op2: Operand2::Imm(256),
9548 })
9549 .unwrap(),
9550 vec![0x0d, 0xf2, 0x00, 0x1d],
9551 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9552 );
9553 assert_eq!(
9555 encoder
9556 .encode(&ArmOp::Sub {
9557 rd: Reg::SP,
9558 rn: Reg::SP,
9559 op2: Operand2::Imm(256),
9560 })
9561 .unwrap(),
9562 vec![0xad, 0xf2, 0x00, 0x1d],
9563 );
9564 assert!(
9566 encoder
9567 .encode(&ArmOp::Add {
9568 rd: Reg::SP,
9569 rn: Reg::SP,
9570 op2: Operand2::Imm(5000),
9571 })
9572 .is_err(),
9573 "add #5000 must error (no single ADDW), not mis-encode"
9574 );
9575 }
9576
9577 #[test]
9582 fn and_cmn_immediate_thumb_expand_else_error() {
9583 let encoder = ArmEncoder::new_thumb2();
9584 assert_eq!(
9586 encoder
9587 .encode(&ArmOp::And {
9588 rd: Reg::R2,
9589 rn: Reg::R0,
9590 op2: Operand2::Imm(0x7e),
9591 })
9592 .unwrap(),
9593 vec![0x00, 0xf0, 0x7e, 0x02],
9594 );
9595 assert!(
9597 encoder
9598 .encode(&ArmOp::And {
9599 rd: Reg::R2,
9600 rn: Reg::R0,
9601 op2: Operand2::Imm(0xff00ff00u32 as i32),
9602 })
9603 .is_ok()
9604 );
9605 assert!(
9607 encoder
9608 .encode(&ArmOp::And {
9609 rd: Reg::R2,
9610 rn: Reg::R0,
9611 op2: Operand2::Imm(0x101),
9612 })
9613 .is_err()
9614 );
9615 assert!(
9616 encoder
9617 .encode(&ArmOp::Cmn {
9618 rn: Reg::R0,
9619 op2: Operand2::Imm(0x101),
9620 })
9621 .is_err(),
9622 "CMN #0x101 must error, not emit a NOP"
9623 );
9624 }
9625
9626 #[test]
9630 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9631 let encoder = ArmEncoder::new_thumb2();
9632 assert_eq!(
9634 encoder
9635 .encode(&ArmOp::Orr {
9636 rd: Reg::R2,
9637 rn: Reg::R0,
9638 op2: Operand2::Imm(0x7e),
9639 })
9640 .unwrap(),
9641 vec![0x40, 0xf0, 0x7e, 0x02],
9642 );
9643 assert_eq!(
9645 encoder
9646 .encode(&ArmOp::Eor {
9647 rd: Reg::R2,
9648 rn: Reg::R0,
9649 op2: Operand2::Imm(0x7e),
9650 })
9651 .unwrap(),
9652 vec![0x80, 0xf0, 0x7e, 0x02],
9653 );
9654 assert!(
9656 encoder
9657 .encode(&ArmOp::Orr {
9658 rd: Reg::R2,
9659 rn: Reg::R0,
9660 op2: Operand2::Imm(0x140),
9661 })
9662 .is_err(),
9663 "ORR #0x140 must error, not emit a NOP"
9664 );
9665 }
9666
9667 #[test]
9668 fn test_encode_mve_different_qregs() {
9669 let encoder = ArmEncoder::new_thumb2();
9670
9671 let op1 = ArmOp::MveAddI {
9673 qd: QReg::Q0,
9674 qn: QReg::Q0,
9675 qm: QReg::Q0,
9676 size: MveSize::S32,
9677 };
9678 let op2 = ArmOp::MveAddI {
9679 qd: QReg::Q3,
9680 qn: QReg::Q5,
9681 qm: QReg::Q7,
9682 size: MveSize::S32,
9683 };
9684 let code1 = encoder.encode(&op1).unwrap();
9685 let code2 = encoder.encode(&op2).unwrap();
9686 assert_ne!(
9687 code1, code2,
9688 "Different Q-registers should produce different encodings"
9689 );
9690 }
9691
9692 #[test]
9693 fn test_encode_mve_arm32_nop() {
9694 let encoder = ArmEncoder::new_arm32();
9696 let op = ArmOp::MveAddI {
9697 qd: QReg::Q0,
9698 qn: QReg::Q1,
9699 qm: QReg::Q2,
9700 size: MveSize::S32,
9701 };
9702 let code = encoder.encode(&op).unwrap();
9703 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9704 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9706 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9707 }
9708}