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 let base = self.i64_effective_base(&mut bytes, addr);
5320 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &base, offset)?);
5321 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5322 rdhi,
5323 &base,
5324 offset.wrapping_add(4),
5325 )?);
5326 Ok(bytes)
5327 }
5328
5329 ArmOp::I64Str { rdlo, rdhi, addr } => {
5331 let mut bytes = Vec::new();
5332 let offset = if addr.offset < 0 {
5333 0u32
5334 } else {
5335 addr.offset as u32
5336 };
5337 let base = self.i64_effective_base(&mut bytes, addr);
5339 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &base, offset)?);
5340 bytes.extend_from_slice(&self.encode_thumb32_str(
5341 rdhi,
5342 &base,
5343 offset.wrapping_add(4),
5344 )?);
5345 Ok(bytes)
5346 }
5347
5348 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5350 let mut bytes = Vec::new();
5351 if rdlo != rn {
5352 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5354 rd: *rdlo,
5355 op2: Operand2::Reg(*rn),
5356 })?);
5357 }
5358 bytes.extend_from_slice(
5360 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5362 Ok(bytes)
5363 }
5364
5365 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5367 let mut bytes = Vec::new();
5368 if rdlo != rn {
5369 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5371 rd: *rdlo,
5372 op2: Operand2::Reg(*rn),
5373 })?);
5374 }
5375 let rdhi_bits = reg_to_bits(rdhi) as u16;
5377 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5378 bytes.extend_from_slice(&instr.to_le_bytes());
5379 Ok(bytes)
5380 }
5381
5382 ArmOp::I32WrapI64 { rd, rnlo } => {
5384 if rd == rnlo {
5385 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5388 } else {
5389 self.encode_thumb(&ArmOp::Mov {
5391 rd: *rd,
5392 op2: Operand2::Reg(*rnlo),
5393 })
5394 }
5395 }
5396
5397 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5399 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5400 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5401 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5402 0xEF000150, qd, qn, qm,
5403 ))),
5404 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5405 0xEF200150, qd, qn, qm,
5406 ))),
5407 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5408 0xFF000150, qd, qn, qm,
5409 ))),
5410 ArmOp::MveMvn { qd, qm } => {
5411 let qd_enc = qreg_to_num(qd);
5413 let qm_enc = qreg_to_num(qm);
5414 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5415 Ok(vfp_to_thumb_bytes(instr))
5416 }
5417 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5418 0xEF100150, qd, qn, qm,
5419 ))),
5420 ArmOp::MveAddI { qd, qn, qm, size } => {
5421 let sz = mve_size_bits(size);
5422 let base: u32 = 0xEF000840 | (sz << 20);
5423 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5424 }
5425 ArmOp::MveSubI { qd, qn, qm, size } => {
5426 let sz = mve_size_bits(size);
5427 let base: u32 = 0xFF000840 | (sz << 20);
5428 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5429 }
5430 ArmOp::MveMulI { qd, qn, qm, size } => {
5431 let sz = mve_size_bits(size);
5432 let base: u32 = 0xEF000950 | (sz << 20);
5433 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5434 }
5435 ArmOp::MveNegI { qd, qm, size } => {
5436 let sz = mve_size_bits(size);
5437 let qd_enc = qreg_to_num(qd);
5439 let qm_enc = qreg_to_num(qm);
5440 let base: u32 = 0xFFB103C0 | (sz << 18);
5441 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5442 Ok(vfp_to_thumb_bytes(instr))
5443 }
5444 ArmOp::MveDup { qd, rn, size } => {
5445 let sz = mve_size_bits(size);
5446 let qd_enc = qreg_to_num(qd);
5447 let rn_bits = reg_to_bits(rn);
5448 let be = match sz {
5451 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5455 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5456 Ok(vfp_to_thumb_bytes(instr))
5457 }
5458 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5459 let qn_enc = qreg_to_num(qn);
5460 let rd_bits = reg_to_bits(rd);
5461 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5464 let lane_in_d = (*lane as u32) & 1;
5465 let _sz = mve_size_bits(size);
5466 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5468 Ok(vfp_to_thumb_bytes(instr))
5469 }
5470 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5471 let qd_enc = qreg_to_num(qd);
5472 let rn_bits = reg_to_bits(rn);
5473 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5474 let lane_in_d = (*lane as u32) & 1;
5475 let _sz = mve_size_bits(size);
5476 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5478 Ok(vfp_to_thumb_bytes(instr))
5479 }
5480
5481 ArmOp::MveCmpEqI { qd, qn, qm, size }
5483 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5484 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5485 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5486 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5487 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5488 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5489 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5490 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5491 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5492 let sz = mve_size_bits(size);
5495 let base: u32 = 0xEF000840 | (sz << 20);
5496 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5497 }
5498
5499 ArmOp::MveAddF32 { qd, qn, qm } => {
5501 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5503 }
5504 ArmOp::MveSubF32 { qd, qn, qm } => {
5505 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5507 }
5508 ArmOp::MveMulF32 { qd, qn, qm } => {
5509 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5511 }
5512 ArmOp::MveNegF32 { qd, qm } => {
5513 let qd_enc = qreg_to_num(qd);
5514 let qm_enc = qreg_to_num(qm);
5515 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5517 Ok(vfp_to_thumb_bytes(instr))
5518 }
5519 ArmOp::MveAbsF32 { qd, qm } => {
5520 let qd_enc = qreg_to_num(qd);
5521 let qm_enc = qreg_to_num(qm);
5522 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5524 Ok(vfp_to_thumb_bytes(instr))
5525 }
5526 ArmOp::MveCmpEqF32 { qd, qn, qm }
5527 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5528 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5529 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5530 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5531 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5532 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5534 }
5535 ArmOp::MveDupF32 { qd, rn } => {
5536 let qd_enc = qreg_to_num(qd);
5537 let rn_bits = reg_to_bits(rn);
5538 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5540 Ok(vfp_to_thumb_bytes(instr))
5541 }
5542 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5543 let qn_enc = qreg_to_num(qn);
5544 let rd_bits = reg_to_bits(rd);
5545 let s_num = qn_enc * 4 + (*lane as u32);
5547 let (vn, n) = encode_sreg(s_num);
5548 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5549 Ok(vfp_to_thumb_bytes(instr))
5550 }
5551 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5552 let qd_enc = qreg_to_num(qd);
5553 let rn_bits = reg_to_bits(rn);
5554 let s_num = qd_enc * 4 + (*lane as u32);
5556 let (vn, n) = encode_sreg(s_num);
5557 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5558 Ok(vfp_to_thumb_bytes(instr))
5559 }
5560 ArmOp::MveDivF32 { qd, qn, qm } => {
5561 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5563 }
5564 ArmOp::MveSqrtF32 { qd, qm } => {
5565 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5567 }
5568
5569 _ => {
5571 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5573 }
5574 }
5575 }
5576
5577 fn encode_thumb_f32_compare(
5581 &self,
5582 rd: &Reg,
5583 sn: &VfpReg,
5584 sm: &VfpReg,
5585 cond_code: u32,
5586 ) -> Result<Vec<u8>> {
5587 let mut bytes = Vec::new();
5588 let rd_bits = reg_to_bits(rd);
5589
5590 let sn_num = vfp_sreg_to_num(sn)?;
5592 let sm_num = vfp_sreg_to_num(sm)?;
5593 let (vd, d) = encode_sreg(sn_num);
5594 let (vm, m) = encode_sreg(sm_num);
5595 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5596 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5597
5598 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5600
5601 if rd_bits < 8 {
5603 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5604 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5605 } else {
5606 let hw1: u16 = 0xF04F;
5608 let hw2: u16 = (rd_bits as u16) << 8;
5609 bytes.extend_from_slice(&hw1.to_le_bytes());
5610 bytes.extend_from_slice(&hw2.to_le_bytes());
5611 }
5612
5613 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5617 bytes.extend_from_slice(&it.to_le_bytes());
5618
5619 if rd_bits < 8 {
5621 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5622 bytes.extend_from_slice(&mov_one.to_le_bytes());
5623 } else {
5624 let hw1: u16 = 0xF04F;
5626 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5627 bytes.extend_from_slice(&hw1.to_le_bytes());
5628 bytes.extend_from_slice(&hw2.to_le_bytes());
5629 }
5630
5631 Ok(bytes)
5632 }
5633
5634 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5636 let mut bytes = Vec::new();
5637 let bits = value.to_bits();
5638 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5643 let imm4 = (lo16 >> 12) & 0xF;
5644 let i_bit = (lo16 >> 11) & 1;
5645 let imm3 = (lo16 >> 8) & 0x7;
5646 let imm8 = lo16 & 0xFF;
5647 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5648 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5649 bytes.extend_from_slice(&hw1.to_le_bytes());
5650 bytes.extend_from_slice(&hw2.to_le_bytes());
5651
5652 let hi16 = (bits >> 16) & 0xFFFF;
5654 let imm4 = (hi16 >> 12) & 0xF;
5655 let i_bit = (hi16 >> 11) & 1;
5656 let imm3 = (hi16 >> 8) & 0x7;
5657 let imm8 = hi16 & 0xFF;
5658 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5659 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5660 bytes.extend_from_slice(&hw1.to_le_bytes());
5661 bytes.extend_from_slice(&hw2.to_le_bytes());
5662
5663 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5665 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5666
5667 Ok(bytes)
5668 }
5669
5670 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5672 let mut bytes = Vec::new();
5673
5674 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5676 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5677
5678 let sd_num = vfp_sreg_to_num(sd)?;
5680 let (vd, d) = encode_sreg(sd_num);
5681 let (vm, m) = encode_sreg(sd_num);
5682 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5683 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5684 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5685
5686 Ok(bytes)
5687 }
5688
5689 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5697 let mut bytes = Vec::new();
5698 let sm_num = vfp_sreg_to_num(sm)?;
5699 let sd_num = vfp_sreg_to_num(sd)?;
5700 let (vd_s, d_s) = encode_sreg(sd_num);
5701 let (vm_s, m_s) = encode_sreg(sm_num);
5702
5703 if mode == 0b11 {
5704 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5706 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5707 } else {
5708 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5713 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5714
5715 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5721 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5722 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5723
5724 if mode != 0 {
5726 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5728 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5729 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5730 }
5731
5732 let vmsr = 0xEEE10A10 | (rt << 12);
5734 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5735
5736 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5738 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5739
5740 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5742 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5743 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5744 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5745 }
5746
5747 let (vd2, d2) = encode_sreg(sd_num);
5749 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5750 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5751
5752 Ok(bytes)
5753 }
5754
5755 fn encode_thumb_f32_minmax(
5757 &self,
5758 sd: &VfpReg,
5759 sn: &VfpReg,
5760 sm: &VfpReg,
5761 is_min: bool,
5762 ) -> Result<Vec<u8>> {
5763 let mut bytes = Vec::new();
5764 let sn_num = vfp_sreg_to_num(sn)?;
5765 let sm_num = vfp_sreg_to_num(sm)?;
5766 let sd_num = vfp_sreg_to_num(sd)?;
5767
5768 let (vd, d) = encode_sreg(sd_num);
5770 let (vn, n) = encode_sreg(sn_num);
5771 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5772 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5773
5774 let (vm, m) = encode_sreg(sm_num);
5776 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5777 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5778
5779 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5781
5782 let cond: u16 = if is_min { 0xC } else { 0x4 };
5784 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5785 bytes.extend_from_slice(&it.to_le_bytes());
5786
5787 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5789 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5790
5791 Ok(bytes)
5792 }
5793
5794 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5796 let mut bytes = Vec::new();
5797
5798 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5800 false,
5801 sm,
5802 &Reg::R12,
5803 )?));
5804
5805 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5807 false,
5808 sn,
5809 &Reg::R0,
5810 )?));
5811
5812 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5824 bytes.extend_from_slice(&hw2.to_le_bytes());
5825
5826 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5830 bytes.extend_from_slice(&hw2.to_le_bytes());
5831
5832 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5836 bytes.extend_from_slice(&hw2.to_le_bytes());
5837
5838 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5840 true,
5841 sd,
5842 &Reg::R0,
5843 )?));
5844
5845 Ok(bytes)
5846 }
5847
5848 fn encode_thumb_f64_compare(
5850 &self,
5851 rd: &Reg,
5852 dn: &VfpReg,
5853 dm: &VfpReg,
5854 cond_code: u32,
5855 ) -> Result<Vec<u8>> {
5856 let mut bytes = Vec::new();
5857 let rd_bits = reg_to_bits(rd);
5858
5859 let dn_num = vfp_dreg_to_num(dn)?;
5861 let dm_num = vfp_dreg_to_num(dm)?;
5862 let (vd, d) = encode_dreg(dn_num);
5863 let (vm, m) = encode_dreg(dm_num);
5864 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5865 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5866
5867 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5869
5870 if rd_bits < 8 {
5872 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5873 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5874 } else {
5875 let hw1: u16 = 0xF04F;
5876 let hw2: u16 = (rd_bits as u16) << 8;
5877 bytes.extend_from_slice(&hw1.to_le_bytes());
5878 bytes.extend_from_slice(&hw2.to_le_bytes());
5879 }
5880
5881 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5883 bytes.extend_from_slice(&it.to_le_bytes());
5884
5885 if rd_bits < 8 {
5887 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5888 bytes.extend_from_slice(&mov_one.to_le_bytes());
5889 } else {
5890 let hw1: u16 = 0xF04F;
5891 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5892 bytes.extend_from_slice(&hw1.to_le_bytes());
5893 bytes.extend_from_slice(&hw2.to_le_bytes());
5894 }
5895
5896 Ok(bytes)
5897 }
5898
5899 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5901 let mut bytes = Vec::new();
5902 let bits = value.to_bits();
5903 let lo32 = bits as u32;
5904 let hi32 = (bits >> 32) as u32;
5905
5906 let lo16 = lo32 & 0xFFFF;
5908 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5909
5910 let hi16 = (lo32 >> 16) & 0xFFFF;
5912 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5913
5914 let lo16 = hi32 & 0xFFFF;
5916 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5917
5918 let hi16 = (hi32 >> 16) & 0xFFFF;
5920 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5921
5922 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5924 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5925
5926 Ok(bytes)
5927 }
5928
5929 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5931 let mut bytes = Vec::new();
5932
5933 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5935 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5936
5937 let dd_num = vfp_dreg_to_num(dd)?;
5939 let (vd, d) = encode_dreg(dd_num);
5940 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5941 let vcvt = base | (d << 22) | (vd << 12);
5942 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5943
5944 Ok(bytes)
5945 }
5946
5947 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5949 let dd_num = vfp_dreg_to_num(dd)?;
5950 let sm_num = vfp_sreg_to_num(sm)?;
5951 let (vd, d) = encode_dreg(dd_num);
5952 let (vm, m) = encode_sreg(sm_num);
5953
5954 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5955 Ok(vfp_to_thumb_bytes(vcvt))
5956 }
5957
5958 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5960 let mut bytes = Vec::new();
5961 let dm_num = vfp_dreg_to_num(dm)?;
5962 let (vm, m) = encode_dreg(dm_num);
5963
5964 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5966 let vcvt = base | (m << 5) | vm;
5967 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5968
5969 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5971 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5972
5973 Ok(bytes)
5974 }
5975
5976 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5980 let mut bytes = Vec::new();
5981 let dm_num = vfp_dreg_to_num(dm)?;
5982 let dd_num = vfp_dreg_to_num(dd)?;
5983 let (vm, m) = encode_dreg(dm_num);
5984 let (vd, d) = encode_dreg(dd_num);
5985
5986 if mode == 0b11 {
5987 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5989 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5990 } else {
5991 let rt: u32 = 12;
5992
5993 let vmrs = 0xEEF10A10 | (rt << 12);
5995 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5996
5997 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5999 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
6000 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
6001 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
6002
6003 if mode != 0 {
6005 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
6006 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
6007 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
6008 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
6009 }
6010
6011 let vmsr = 0xEEE10A10 | (rt << 12);
6013 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
6014
6015 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
6017 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
6018
6019 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
6021 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
6022 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
6023 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
6024 }
6025
6026 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
6028 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
6029
6030 Ok(bytes)
6031 }
6032
6033 fn encode_thumb_f64_minmax(
6035 &self,
6036 dd: &VfpReg,
6037 dn: &VfpReg,
6038 dm: &VfpReg,
6039 is_min: bool,
6040 ) -> Result<Vec<u8>> {
6041 let mut bytes = Vec::new();
6042 let dn_num = vfp_dreg_to_num(dn)?;
6043 let dm_num = vfp_dreg_to_num(dm)?;
6044 let dd_num = vfp_dreg_to_num(dd)?;
6045
6046 let (vd, d) = encode_dreg(dd_num);
6048 let (vn, n) = encode_dreg(dn_num);
6049 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
6050 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
6051
6052 let (vm, m) = encode_dreg(dm_num);
6054 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
6055 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
6056
6057 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
6059
6060 let cond: u16 = if is_min { 0xC } else { 0x4 };
6062 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
6063 bytes.extend_from_slice(&it.to_le_bytes());
6064
6065 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
6067 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
6068
6069 Ok(bytes)
6070 }
6071
6072 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
6074 let mut bytes = Vec::new();
6075
6076 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6078 false,
6079 dm,
6080 &Reg::R0,
6081 &Reg::R12,
6082 )?));
6083
6084 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6086 false,
6087 dn,
6088 &Reg::R1,
6089 &Reg::R2,
6090 )?));
6091
6092 let hw1: u16 = 0xF000 | 12;
6094 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
6095 bytes.extend_from_slice(&hw1.to_le_bytes());
6096 bytes.extend_from_slice(&hw2.to_le_bytes());
6097
6098 let hw1: u16 = 0xF020 | 2;
6100 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
6101 bytes.extend_from_slice(&hw1.to_le_bytes());
6102 bytes.extend_from_slice(&hw2.to_le_bytes());
6103
6104 let hw1: u16 = 0xEA40 | 2;
6106 let hw2: u16 = (2 << 8) | 12;
6107 bytes.extend_from_slice(&hw1.to_le_bytes());
6108 bytes.extend_from_slice(&hw2.to_le_bytes());
6109
6110 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6112 true,
6113 dd,
6114 &Reg::R1,
6115 &Reg::R2,
6116 )?));
6117
6118 Ok(bytes)
6119 }
6120
6121 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6123 let mut bytes = Vec::new();
6124
6125 let sm_num = vfp_sreg_to_num(sm)?;
6126 let (vd, d) = encode_sreg(sm_num);
6127 let (vm, m) = encode_sreg(sm_num);
6128 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6129 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6130 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6131
6132 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6134 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6135
6136 Ok(bytes)
6137 }
6138
6139 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6143 let rd_bits = reg_to_bits(rd);
6144 let rn_bits = reg_to_bits(rn);
6145
6146 let i_bit = (imm >> 11) & 1;
6148 let imm3 = (imm >> 8) & 0x7;
6149 let imm8 = imm & 0xFF;
6150
6151 let hw1_base = if imm <= 0xFF {
6152 0xF100
6156 } else if imm <= 0xFFF {
6157 0xF200
6161 } else {
6162 return Err(synth_core::Error::synthesis(
6163 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6164 ));
6165 };
6166
6167 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6168 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6169
6170 let mut bytes = hw1.to_le_bytes().to_vec();
6171 bytes.extend_from_slice(&hw2.to_le_bytes());
6172 Ok(bytes)
6173 }
6174
6175 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6177 let rd_bits = reg_to_bits(rd);
6178 let rn_bits = reg_to_bits(rn);
6179
6180 let i_bit = (imm >> 11) & 1;
6181 let imm3 = (imm >> 8) & 0x7;
6182 let imm8 = imm & 0xFF;
6183
6184 let hw1_base = if imm <= 0xFF {
6185 0xF1A0
6188 } else if imm <= 0xFFF {
6189 0xF2A0
6192 } else {
6193 return Err(synth_core::Error::synthesis(
6194 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6195 ));
6196 };
6197
6198 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6199 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6200
6201 let mut bytes = hw1.to_le_bytes().to_vec();
6202 bytes.extend_from_slice(&hw2.to_le_bytes());
6203 Ok(bytes)
6204 }
6205
6206 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6208 let rd_bits = reg_to_bits(rd);
6209 let rn_bits = reg_to_bits(rn);
6210
6211 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6214 synth_core::Error::synthesis(
6215 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6216 )
6217 })?;
6218 let i_bit = (field >> 11) & 1;
6219 let imm3 = (field >> 8) & 0x7;
6220 let imm8 = field & 0xFF;
6221
6222 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6225 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6226
6227 let mut bytes = hw1.to_le_bytes().to_vec();
6228 bytes.extend_from_slice(&hw2.to_le_bytes());
6229 Ok(bytes)
6230 }
6231
6232 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6234 let rd_bits = reg_to_bits(rd);
6235 let rn_bits = reg_to_bits(rn);
6236
6237 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6240 synth_core::Error::synthesis(
6241 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6242 )
6243 })?;
6244 let i_bit = (field >> 11) & 1;
6245 let imm3 = (field >> 8) & 0x7;
6246 let imm8 = field & 0xFF;
6247
6248 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6251 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6252
6253 let mut bytes = hw1.to_le_bytes().to_vec();
6254 bytes.extend_from_slice(&hw2.to_le_bytes());
6255 Ok(bytes)
6256 }
6257
6258 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6267 let rd_bits = reg_to_bits(rd);
6268 reg_bits_checked(rd_bits)?;
6269 let imm16 = imm & 0xFFFF;
6270
6271 let imm4 = (imm16 >> 12) & 0xF;
6274 let i_bit = (imm16 >> 11) & 1;
6275 let imm3 = (imm16 >> 8) & 0x7;
6276 let imm8 = imm16 & 0xFF;
6277
6278 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6279 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6280
6281 let mut bytes = hw1.to_le_bytes().to_vec();
6282 bytes.extend_from_slice(&hw2.to_le_bytes());
6283 encoding_contracts::verify_thumb32(&bytes);
6284 Ok(bytes)
6285 }
6286
6287 fn encode_thumb32_shift(
6295 &self,
6296 rd: &Reg,
6297 rm: &Reg,
6298 shift: u32,
6299 shift_type: u8,
6300 ) -> Result<Vec<u8>> {
6301 let rd_bits = reg_to_bits(rd);
6302 let rm_bits = reg_to_bits(rm);
6303 reg_bits_checked(rd_bits)?;
6304 reg_bits_checked(rm_bits)?;
6305 let imm5 = shift & 0x1F;
6306 let imm2 = imm5 & 0x3;
6307 let imm3 = (imm5 >> 2) & 0x7;
6308
6309 let hw1: u16 = 0xEA4F;
6312 let hw2: u16 =
6313 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6314 as u16;
6315
6316 let mut bytes = hw1.to_le_bytes().to_vec();
6317 bytes.extend_from_slice(&hw2.to_le_bytes());
6318 Ok(bytes)
6319 }
6320
6321 fn encode_thumb32_shift_reg(
6325 &self,
6326 rd: &Reg,
6327 rn: &Reg,
6328 rm: &Reg,
6329 shift_type: u8,
6330 ) -> Result<Vec<u8>> {
6331 let rd_bits = reg_to_bits(rd);
6332 let rn_bits = reg_to_bits(rn);
6333 let rm_bits = reg_to_bits(rm);
6334
6335 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6337 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6339
6340 let mut bytes = hw1.to_le_bytes().to_vec();
6341 bytes.extend_from_slice(&hw2.to_le_bytes());
6342 Ok(bytes)
6343 }
6344
6345 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6347 let rn_bits = reg_to_bits(rn);
6348
6349 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6353 synth_core::Error::synthesis(
6354 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6355 )
6356 })?;
6357 let i_bit = (field >> 11) & 1;
6358 let imm3 = (field >> 8) & 0x7;
6359 let imm8 = field & 0xFF;
6360
6361 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6363 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6364
6365 let mut bytes = hw1.to_le_bytes().to_vec();
6366 bytes.extend_from_slice(&hw2.to_le_bytes());
6367 Ok(bytes)
6368 }
6369
6370 fn i64_effective_base(&self, bytes: &mut Vec<u8>, addr: &MemAddr) -> Reg {
6379 match addr.offset_reg {
6380 Some(idx) => {
6381 let ip = Reg::R12;
6382 let hw1: u16 = 0xEB00 | reg_to_bits(&addr.base) as u16;
6384 let hw2: u16 = 0x0C00 | reg_to_bits(&idx) as u16;
6385 bytes.extend_from_slice(&hw1.to_le_bytes());
6386 bytes.extend_from_slice(&hw2.to_le_bytes());
6387 ip
6388 }
6389 None => addr.base,
6390 }
6391 }
6392
6393 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6395 let rd_bits = reg_to_bits(rd);
6396 let base_bits = reg_to_bits(base);
6397
6398 check_ldst_imm12(offset)?;
6400 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6401 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6402
6403 let mut bytes = hw1.to_le_bytes().to_vec();
6404 bytes.extend_from_slice(&hw2.to_le_bytes());
6405 Ok(bytes)
6406 }
6407
6408 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6410 let rd_bits = reg_to_bits(rd);
6411 let base_bits = reg_to_bits(base);
6412
6413 check_ldst_imm12(offset)?;
6415 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6416 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6417
6418 let mut bytes = hw1.to_le_bytes().to_vec();
6419 bytes.extend_from_slice(&hw2.to_le_bytes());
6420 Ok(bytes)
6421 }
6422
6423 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6425 let rd_bits = reg_to_bits(rd);
6426 let base_bits = reg_to_bits(base);
6427 let rm_bits = reg_to_bits(offset_reg);
6428
6429 let hw1: u16 = (0xF850 | base_bits) as u16;
6433 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6434
6435 let mut bytes = hw1.to_le_bytes().to_vec();
6436 bytes.extend_from_slice(&hw2.to_le_bytes());
6437 Ok(bytes)
6438 }
6439
6440 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6442 let rd_bits = reg_to_bits(rd);
6443 let base_bits = reg_to_bits(base);
6444 let rm_bits = reg_to_bits(offset_reg);
6445
6446 let hw1: u16 = (0xF840 | base_bits) as u16;
6450 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6451
6452 let mut bytes = hw1.to_le_bytes().to_vec();
6453 bytes.extend_from_slice(&hw2.to_le_bytes());
6454 Ok(bytes)
6455 }
6456
6457 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6461 let rd_bits = reg_to_bits(rd);
6462 let base_bits = reg_to_bits(base);
6463 check_ldst_imm12(offset)?;
6465 let hw1: u16 = (0xF890 | base_bits) as u16;
6466 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6467 let mut bytes = hw1.to_le_bytes().to_vec();
6468 bytes.extend_from_slice(&hw2.to_le_bytes());
6469 Ok(bytes)
6470 }
6471
6472 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6474 let rd_bits = reg_to_bits(rd);
6475 let base_bits = reg_to_bits(base);
6476 let rm_bits = reg_to_bits(offset_reg);
6477 let hw1: u16 = (0xF810 | base_bits) as u16;
6479 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6480 let mut bytes = hw1.to_le_bytes().to_vec();
6481 bytes.extend_from_slice(&hw2.to_le_bytes());
6482 Ok(bytes)
6483 }
6484
6485 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6487 let rd_bits = reg_to_bits(rd);
6488 let base_bits = reg_to_bits(base);
6489 check_ldst_imm12(offset)?;
6491 let hw1: u16 = (0xF990 | base_bits) as u16;
6492 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6493 let mut bytes = hw1.to_le_bytes().to_vec();
6494 bytes.extend_from_slice(&hw2.to_le_bytes());
6495 Ok(bytes)
6496 }
6497
6498 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6500 let rd_bits = reg_to_bits(rd);
6501 let base_bits = reg_to_bits(base);
6502 let rm_bits = reg_to_bits(offset_reg);
6503 let hw1: u16 = (0xF910 | base_bits) as u16;
6505 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6506 let mut bytes = hw1.to_le_bytes().to_vec();
6507 bytes.extend_from_slice(&hw2.to_le_bytes());
6508 Ok(bytes)
6509 }
6510
6511 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6513 let rd_bits = reg_to_bits(rd);
6514 let base_bits = reg_to_bits(base);
6515 check_ldst_imm12(offset)?;
6517 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6518 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6519 let mut bytes = hw1.to_le_bytes().to_vec();
6520 bytes.extend_from_slice(&hw2.to_le_bytes());
6521 Ok(bytes)
6522 }
6523
6524 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6526 let rd_bits = reg_to_bits(rd);
6527 let base_bits = reg_to_bits(base);
6528 let rm_bits = reg_to_bits(offset_reg);
6529 let hw1: u16 = (0xF830 | base_bits) as u16;
6531 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6532 let mut bytes = hw1.to_le_bytes().to_vec();
6533 bytes.extend_from_slice(&hw2.to_le_bytes());
6534 Ok(bytes)
6535 }
6536
6537 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6539 let rd_bits = reg_to_bits(rd);
6540 let base_bits = reg_to_bits(base);
6541 check_ldst_imm12(offset)?;
6543 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6544 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6545 let mut bytes = hw1.to_le_bytes().to_vec();
6546 bytes.extend_from_slice(&hw2.to_le_bytes());
6547 Ok(bytes)
6548 }
6549
6550 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6552 let rd_bits = reg_to_bits(rd);
6553 let base_bits = reg_to_bits(base);
6554 let rm_bits = reg_to_bits(offset_reg);
6555 let hw1: u16 = (0xF930 | base_bits) as u16;
6557 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6558 let mut bytes = hw1.to_le_bytes().to_vec();
6559 bytes.extend_from_slice(&hw2.to_le_bytes());
6560 Ok(bytes)
6561 }
6562
6563 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6565 let rd_bits = reg_to_bits(rd);
6566 let base_bits = reg_to_bits(base);
6567 check_ldst_imm12(offset)?;
6569 let hw1: u16 = (0xF880 | base_bits) as u16;
6570 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6571 let mut bytes = hw1.to_le_bytes().to_vec();
6572 bytes.extend_from_slice(&hw2.to_le_bytes());
6573 Ok(bytes)
6574 }
6575
6576 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6578 let rd_bits = reg_to_bits(rd);
6579 let base_bits = reg_to_bits(base);
6580 let rm_bits = reg_to_bits(offset_reg);
6581 let hw1: u16 = (0xF800 | base_bits) as u16;
6583 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6584 let mut bytes = hw1.to_le_bytes().to_vec();
6585 bytes.extend_from_slice(&hw2.to_le_bytes());
6586 Ok(bytes)
6587 }
6588
6589 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6591 let rd_bits = reg_to_bits(rd);
6592 let base_bits = reg_to_bits(base);
6593 check_ldst_imm12(offset)?;
6595 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6596 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6597 let mut bytes = hw1.to_le_bytes().to_vec();
6598 bytes.extend_from_slice(&hw2.to_le_bytes());
6599 Ok(bytes)
6600 }
6601
6602 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6604 let rd_bits = reg_to_bits(rd);
6605 let base_bits = reg_to_bits(base);
6606 let rm_bits = reg_to_bits(offset_reg);
6607 let hw1: u16 = (0xF820 | base_bits) as u16;
6609 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6610 let mut bytes = hw1.to_le_bytes().to_vec();
6611 bytes.extend_from_slice(&hw2.to_le_bytes());
6612 Ok(bytes)
6613 }
6614
6615 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6617 let rd_bits = reg_to_bits(rd);
6618 let rn_bits = reg_to_bits(rn);
6619
6620 if imm <= 0xFFF {
6626 let i_bit = (imm >> 11) & 1;
6627 let imm3 = (imm >> 8) & 0x7;
6628 let imm8 = imm & 0xFF;
6629
6630 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6631 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6632
6633 let mut bytes = hw1.to_le_bytes().to_vec();
6634 bytes.extend_from_slice(&hw2.to_le_bytes());
6635 Ok(bytes)
6636 } else {
6637 let scratch: u32 = if rd_bits == rn_bits {
6651 12 } else {
6653 rd_bits };
6655 if scratch == rn_bits {
6663 return Err(synth_core::Error::synthesis(format!(
6664 "ADD #imm: cannot lower #{imm:#x} for Rd==Rn==R12 — no free scratch \
6665 register (R12 is the reserved encoder scratch and aliases Rn here)"
6666 )));
6667 }
6668
6669 let lo16 = imm & 0xFFFF;
6670 let hi16 = (imm >> 16) & 0xFFFF;
6671
6672 let mut bytes = self.encode_thumb32_movw_raw(scratch, lo16)?;
6673 if hi16 != 0 {
6674 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(scratch, hi16)?);
6675 }
6676 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(rd_bits, rn_bits, scratch)?);
6677 Ok(bytes)
6678 }
6679 }
6680
6681 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6691 reg_bits_checked(rd)?;
6692 encoding_contracts::verify_imm16(imm16);
6693 let imm16 = imm16 & 0xFFFF;
6696 let imm4 = (imm16 >> 12) & 0xF;
6697 let i_bit = (imm16 >> 11) & 1;
6698 let imm3 = (imm16 >> 8) & 0x7;
6699 let imm8 = imm16 & 0xFF;
6700
6701 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6702 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6703
6704 let mut bytes = hw1.to_le_bytes().to_vec();
6705 bytes.extend_from_slice(&hw2.to_le_bytes());
6706 encoding_contracts::verify_thumb32(&bytes);
6707 Ok(bytes)
6708 }
6709
6710 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6718 reg_bits_checked(rd)?;
6719 encoding_contracts::verify_imm16(imm16);
6720 let imm16 = imm16 & 0xFFFF;
6723 let imm4 = (imm16 >> 12) & 0xF;
6724 let i_bit = (imm16 >> 11) & 1;
6725 let imm3 = (imm16 >> 8) & 0x7;
6726 let imm8 = imm16 & 0xFF;
6727
6728 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6729 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6730
6731 let mut bytes = hw1.to_le_bytes().to_vec();
6732 bytes.extend_from_slice(&hw2.to_le_bytes());
6733 encoding_contracts::verify_thumb32(&bytes);
6734 Ok(bytes)
6735 }
6736
6737 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6739 let imm5 = shift & 0x1F;
6742 let imm2 = imm5 & 0x3;
6743 let imm3 = (imm5 >> 2) & 0x7;
6744
6745 let hw1: u16 = 0xEA4F;
6746 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6747
6748 let mut bytes = hw1.to_le_bytes().to_vec();
6749 bytes.extend_from_slice(&hw2.to_le_bytes());
6750 Ok(bytes)
6751 }
6752
6753 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6755 let hw1: u16 = (0xEA00 | rn) as u16;
6758 let hw2: u16 = ((rd << 8) | rm) as u16;
6759
6760 let mut bytes = hw1.to_le_bytes().to_vec();
6761 bytes.extend_from_slice(&hw2.to_le_bytes());
6762 Ok(bytes)
6763 }
6764
6765 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6767 let i_bit = (imm >> 11) & 1;
6771 let imm3 = (imm >> 8) & 0x7;
6772 let imm8 = imm & 0xFF;
6773
6774 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6775 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6776
6777 let mut bytes = hw1.to_le_bytes().to_vec();
6778 bytes.extend_from_slice(&hw2.to_le_bytes());
6779 Ok(bytes)
6780 }
6781
6782 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6784 let hw1: u16 = (0xEBA0 | rn) as u16;
6787 let hw2: u16 = ((rd << 8) | rm) as u16;
6788
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 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6796 let hw1: u16 = (0xEB00 | rn) as u16;
6799 let hw2: u16 = ((rd << 8) | rm) as u16;
6800
6801 let mut bytes = hw1.to_le_bytes().to_vec();
6802 bytes.extend_from_slice(&hw2.to_le_bytes());
6803 Ok(bytes)
6804 }
6805
6806 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6810 let hw1: u16 = (0xEB10 | rn) as u16;
6812 let hw2: u16 = ((rd << 8) | rm) as u16;
6813 let mut bytes = hw1.to_le_bytes().to_vec();
6814 bytes.extend_from_slice(&hw2.to_le_bytes());
6815 Ok(bytes)
6816 }
6817
6818 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6821 let hw1: u16 = (0xEBB0 | rn) as u16;
6823 let hw2: u16 = ((rd << 8) | rm) as u16;
6824 let mut bytes = hw1.to_le_bytes().to_vec();
6825 bytes.extend_from_slice(&hw2.to_le_bytes());
6826 Ok(bytes)
6827 }
6828
6829 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6831 let mut code = Vec::new();
6832
6833 for op in ops {
6834 let encoded = self.encode(op)?;
6835 code.extend_from_slice(&encoded);
6836 }
6837
6838 Ok(code)
6839 }
6840}
6841
6842fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6850 if value <= 0xFF {
6852 return Some(value);
6853 }
6854 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6858 return Some(0x100 | b0);
6859 }
6860 if value == (b1 << 24) | (b1 << 8) {
6862 return Some(0x200 | b1);
6863 }
6864 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6866 return Some(0x300 | b0);
6867 }
6868 for rot in 8..=31u32 {
6872 let unrot = value.rotate_left(rot);
6873 if (0x80..=0xFF).contains(&unrot) {
6874 return Some((rot << 7) | (unrot & 0x7F));
6875 }
6876 }
6877 None
6878}
6879
6880fn check_ldst_imm12(offset: u32) -> Result<()> {
6886 if offset > 0xFFF {
6887 Err(synth_core::Error::synthesis(
6888 "load/store immediate offset > 0xFFF (4095) — materialize the offset into a register",
6889 ))
6890 } else {
6891 Ok(())
6892 }
6893}
6894
6895fn reg_to_bits(reg: &Reg) -> u32 {
6896 match reg {
6897 Reg::R0 => 0,
6898 Reg::R1 => 1,
6899 Reg::R2 => 2,
6900 Reg::R3 => 3,
6901 Reg::R4 => 4,
6902 Reg::R5 => 5,
6903 Reg::R6 => 6,
6904 Reg::R7 => 7,
6905 Reg::R8 => 8,
6906 Reg::R9 => 9,
6907 Reg::R10 => 10,
6908 Reg::R11 => 11,
6909 Reg::R12 => 12,
6910 Reg::SP => 13,
6911 Reg::LR => 14,
6912 Reg::PC => 15,
6913 }
6914}
6915
6916fn reg_bits_checked(bits: u32) -> Result<()> {
6924 if bits > 14 {
6925 return Err(synth_core::Error::synthesis(format!(
6926 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6927 )));
6928 }
6929 Ok(())
6930}
6931
6932fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6935 if val == 0 {
6936 return Some((0, 1));
6937 }
6938 for rot in 0..16u32 {
6939 let shift = rot * 2;
6940 let unrotated = val.rotate_left(shift);
6942 if unrotated <= 0xFF {
6943 return Some(((rot << 8) | unrotated, 1));
6945 }
6946 }
6947 None
6948}
6949
6950fn encode_operand2(op2: &Operand2) -> Result<(u32, u32)> {
6955 match op2 {
6956 Operand2::Imm(val) => {
6957 let uval = *val as u32;
6958 if let Some(encoded) = try_encode_rotated_imm(uval) {
6960 Ok(encoded)
6961 } else {
6962 Err(synth_core::Error::synthesis(format!(
6971 "encode_operand2: immediate {uval:#x} ({val}) is not an ARM32 \
6972 rotated immediate — the selector must materialize large \
6973 constants via MOVW/MOVT"
6974 )))
6975 }
6976 }
6977
6978 Operand2::Reg(reg) => {
6979 let reg_bits = reg_to_bits(reg);
6980 Ok((reg_bits, 0)) }
6982
6983 Operand2::RegShift {
6984 rm,
6985 shift: _,
6986 amount,
6987 } => {
6988 let rm_bits = reg_to_bits(rm);
6990 let shift_bits = (*amount & 0x1F) << 7;
6991 Ok((shift_bits | rm_bits, 0))
6992 }
6993 }
6994}
6995
6996fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6998 let base_bits = reg_to_bits(&addr.base);
6999 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
7001}
7002
7003fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
7005 match reg {
7006 VfpReg::S0 => Ok(0),
7007 VfpReg::S1 => Ok(1),
7008 VfpReg::S2 => Ok(2),
7009 VfpReg::S3 => Ok(3),
7010 VfpReg::S4 => Ok(4),
7011 VfpReg::S5 => Ok(5),
7012 VfpReg::S6 => Ok(6),
7013 VfpReg::S7 => Ok(7),
7014 VfpReg::S8 => Ok(8),
7015 VfpReg::S9 => Ok(9),
7016 VfpReg::S10 => Ok(10),
7017 VfpReg::S11 => Ok(11),
7018 VfpReg::S12 => Ok(12),
7019 VfpReg::S13 => Ok(13),
7020 VfpReg::S14 => Ok(14),
7021 VfpReg::S15 => Ok(15),
7022 VfpReg::S16 => Ok(16),
7023 VfpReg::S17 => Ok(17),
7024 VfpReg::S18 => Ok(18),
7025 VfpReg::S19 => Ok(19),
7026 VfpReg::S20 => Ok(20),
7027 VfpReg::S21 => Ok(21),
7028 VfpReg::S22 => Ok(22),
7029 VfpReg::S23 => Ok(23),
7030 VfpReg::S24 => Ok(24),
7031 VfpReg::S25 => Ok(25),
7032 VfpReg::S26 => Ok(26),
7033 VfpReg::S27 => Ok(27),
7034 VfpReg::S28 => Ok(28),
7035 VfpReg::S29 => Ok(29),
7036 VfpReg::S30 => Ok(30),
7037 VfpReg::S31 => Ok(31),
7038 _ => Err(synth_core::Error::SynthesisError(
7040 "D-register not supported in single-precision VFP encoding".to_string(),
7041 )),
7042 }
7043}
7044
7045fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
7047 match reg {
7048 VfpReg::D0 => Ok(0),
7049 VfpReg::D1 => Ok(1),
7050 VfpReg::D2 => Ok(2),
7051 VfpReg::D3 => Ok(3),
7052 VfpReg::D4 => Ok(4),
7053 VfpReg::D5 => Ok(5),
7054 VfpReg::D6 => Ok(6),
7055 VfpReg::D7 => Ok(7),
7056 VfpReg::D8 => Ok(8),
7057 VfpReg::D9 => Ok(9),
7058 VfpReg::D10 => Ok(10),
7059 VfpReg::D11 => Ok(11),
7060 VfpReg::D12 => Ok(12),
7061 VfpReg::D13 => Ok(13),
7062 VfpReg::D14 => Ok(14),
7063 VfpReg::D15 => Ok(15),
7064 _ => Err(synth_core::Error::SynthesisError(
7066 "S-register not supported in double-precision VFP encoding".to_string(),
7067 )),
7068 }
7069}
7070
7071fn encode_sreg(s: u32) -> (u32, u32) {
7075 (s >> 1, s & 1)
7076}
7077
7078fn encode_dreg(d: u32) -> (u32, u32) {
7082 (d & 0xF, (d >> 4) & 1)
7083}
7084
7085fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
7091 let sd_num = vfp_sreg_to_num(sd)?;
7092 let sn_num = vfp_sreg_to_num(sn)?;
7093 let sm_num = vfp_sreg_to_num(sm)?;
7094 let (vd, d) = encode_sreg(sd_num);
7095 let (vn, n) = encode_sreg(sn_num);
7096 let (vm, m) = encode_sreg(sm_num);
7097
7098 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7099}
7100
7101fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
7104 let sd_num = vfp_sreg_to_num(sd)?;
7105 let sm_num = vfp_sreg_to_num(sm)?;
7106 let (vd, d) = encode_sreg(sd_num);
7107 let (vm, m) = encode_sreg(sm_num);
7108
7109 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7110}
7111
7112fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7116 let sd_num = vfp_sreg_to_num(sd)?;
7117 let (vd, d) = encode_sreg(sd_num);
7118 let rn = reg_to_bits(&addr.base);
7119
7120 let offset = addr.offset;
7121 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7122 let abs_offset = offset.unsigned_abs();
7123 let imm8 = (abs_offset / 4) & 0xFF;
7124
7125 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7126}
7127
7128fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
7132 let s_num = vfp_sreg_to_num(sreg)?;
7133 let (vn, n) = encode_sreg(s_num);
7134 let rt = reg_to_bits(core);
7135
7136 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
7137 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
7138}
7139
7140fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
7144 let dd_num = vfp_dreg_to_num(dd)?;
7145 let dn_num = vfp_dreg_to_num(dn)?;
7146 let dm_num = vfp_dreg_to_num(dm)?;
7147 let (vd, d) = encode_dreg(dd_num);
7148 let (vn, n) = encode_dreg(dn_num);
7149 let (vm, m) = encode_dreg(dm_num);
7150
7151 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7152}
7153
7154fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
7156 let dd_num = vfp_dreg_to_num(dd)?;
7157 let dm_num = vfp_dreg_to_num(dm)?;
7158 let (vd, d) = encode_dreg(dd_num);
7159 let (vm, m) = encode_dreg(dm_num);
7160
7161 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7162}
7163
7164fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7167 let dd_num = vfp_dreg_to_num(dd)?;
7168 let (vd, d) = encode_dreg(dd_num);
7169 let rn = reg_to_bits(&addr.base);
7170
7171 let offset = addr.offset;
7172 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7173 let abs_offset = offset.unsigned_abs();
7174 let imm8 = (abs_offset / 4) & 0xFF;
7175
7176 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7177}
7178
7179fn encode_vmov_core_dreg(
7183 to_dreg: bool,
7184 dreg: &VfpReg,
7185 core_lo: &Reg,
7186 core_hi: &Reg,
7187) -> Result<u32> {
7188 let d_num = vfp_dreg_to_num(dreg)?;
7189 let (vm, m) = encode_dreg(d_num);
7190 let rt = reg_to_bits(core_lo);
7191 let rt2 = reg_to_bits(core_hi);
7192
7193 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
7194 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
7195}
7196
7197fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
7199 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
7200 let hw2 = (instr & 0xFFFF) as u16;
7201 let mut bytes = hw1.to_le_bytes().to_vec();
7202 bytes.extend_from_slice(&hw2.to_le_bytes());
7203 bytes
7204}
7205
7206fn qreg_to_num(reg: &QReg) -> u32 {
7212 match reg {
7213 QReg::Q0 => 0,
7214 QReg::Q1 => 1,
7215 QReg::Q2 => 2,
7216 QReg::Q3 => 3,
7217 QReg::Q4 => 4,
7218 QReg::Q5 => 5,
7219 QReg::Q6 => 6,
7220 QReg::Q7 => 7,
7221 }
7222}
7223
7224fn mve_size_bits(size: &MveSize) -> u32 {
7226 match size {
7227 MveSize::S8 => 0b00,
7228 MveSize::S16 => 0b01,
7229 MveSize::S32 => 0b10,
7230 }
7231}
7232
7233fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7237 let d = qreg_to_num(qd) * 2;
7238 let n = qreg_to_num(qn) * 2;
7239 let m = qreg_to_num(qm) * 2;
7240
7241 let vd = d & 0xF;
7246 let d_bit = (d >> 4) & 1;
7247 let vn = n & 0xF;
7248 let n_bit = (n >> 4) & 1;
7249 let vm = m & 0xF;
7250 let m_bit = (m >> 4) & 1;
7251
7252 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7253}
7254
7255fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7257 encode_mve_3reg(base, qd, qn, qm)
7258}
7259
7260fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7263 let qd_enc = qreg_to_num(qd) * 2;
7264 let rn = reg_to_bits(&addr.base);
7265 let offset = addr.offset;
7266 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7267 let abs_offset = offset.unsigned_abs();
7268 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7272 | (u_bit << 23)
7273 | ((qd_enc >> 4) << 22)
7274 | (rn << 16)
7275 | ((qd_enc & 0xF) << 12)
7276 | (imm7 & 0x7F)
7277}
7278
7279fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7281 let qd_enc = qreg_to_num(qd) * 2;
7282 let rn = reg_to_bits(&addr.base);
7283 let offset = addr.offset;
7284 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7285 let abs_offset = offset.unsigned_abs();
7286 let imm7 = (abs_offset / 4) & 0x7F;
7287
7288 0xED000E80
7289 | (u_bit << 23)
7290 | ((qd_enc >> 4) << 22)
7291 | (rn << 16)
7292 | ((qd_enc & 0xF) << 12)
7293 | (imm7 & 0x7F)
7294}
7295
7296impl ArmEncoder {
7297 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7299 let mut result = Vec::new();
7300 let qd_num = qreg_to_num(qd);
7301
7302 for i in 0..4 {
7304 let word = u32::from_le_bytes([
7305 bytes[i * 4],
7306 bytes[i * 4 + 1],
7307 bytes[i * 4 + 2],
7308 bytes[i * 4 + 3],
7309 ]);
7310 let lo16 = word & 0xFFFF;
7311 let hi16 = (word >> 16) & 0xFFFF;
7312
7313 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7315 if hi16 != 0 {
7317 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7318 }
7319
7320 let s_num = qd_num * 4 + i as u32;
7322 let (vn, n) = encode_sreg(s_num);
7323 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7324 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7325 }
7326
7327 Ok(result)
7328 }
7329
7330 fn encode_thumb_mve_lane_wise_f32_binop(
7332 &self,
7333 qd: &QReg,
7334 qn: &QReg,
7335 qm: &QReg,
7336 vfp_base: u32,
7337 ) -> Result<Vec<u8>> {
7338 let mut result = Vec::new();
7339 let qd_num = qreg_to_num(qd);
7340 let qn_num = qreg_to_num(qn);
7341 let qm_num = qreg_to_num(qm);
7342
7343 for i in 0..4u32 {
7345 let sd = qd_num * 4 + i;
7346 let sn = qn_num * 4 + i;
7347 let sm = qm_num * 4 + i;
7348
7349 let (vd, d) = encode_sreg(sd);
7350 let (vn, n) = encode_sreg(sn);
7351 let (vm, m) = encode_sreg(sm);
7352
7353 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7354 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7355 }
7356
7357 Ok(result)
7358 }
7359
7360 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7362 let mut result = Vec::new();
7363 let qd_num = qreg_to_num(qd);
7364 let qm_num = qreg_to_num(qm);
7365
7366 for i in 0..4u32 {
7368 let sd = qd_num * 4 + i;
7369 let sm = qm_num * 4 + i;
7370
7371 let (vd, d) = encode_sreg(sd);
7372 let (vm, m) = encode_sreg(sm);
7373
7374 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7375 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7376 }
7377
7378 Ok(result)
7379 }
7380}
7381
7382#[cfg(test)]
7383mod tests {
7384 use super::*;
7385
7386 #[test]
7387 fn test_encoder_creation() {
7388 let encoder_arm = ArmEncoder::new_arm32();
7389 assert!(!encoder_arm.thumb_mode);
7390
7391 let encoder_thumb = ArmEncoder::new_thumb2();
7392 assert!(encoder_thumb.thumb_mode);
7393 }
7394
7395 #[test]
7407 fn test_encode_i64setcond_high_reg_uses_mov_w_311() {
7408 use synth_synthesis::{ArmOp, Condition, Reg};
7409 let enc = ArmEncoder::new_thumb2();
7410 let bytes = enc
7411 .encode(&ArmOp::I64SetCond {
7412 rd: Reg::R8,
7413 rn_lo: Reg::R2,
7414 rn_hi: Reg::R3,
7415 rm_lo: Reg::R6,
7416 rm_hi: Reg::R7,
7417 cond: Condition::EQ,
7418 })
7419 .unwrap();
7420 let halfwords: Vec<u16> = bytes
7423 .chunks(2)
7424 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7425 .collect();
7426 assert!(
7427 halfwords.iter().filter(|&&h| h == 0xF04F).count() == 2,
7428 "high rd must use two MOV.W (T2) encodings, got {halfwords:04x?}"
7429 );
7430 assert!(
7431 !halfwords.contains(&0x2801) && !halfwords.contains(&0x2800),
7432 "no transmuted 16-bit CMP imm: {halfwords:04x?}"
7433 );
7434
7435 let bytes_z = enc
7436 .encode(&ArmOp::I64SetCondZ {
7437 rd: Reg::R8,
7438 rn_lo: Reg::R2,
7439 rn_hi: Reg::R3,
7440 })
7441 .unwrap();
7442 let hw_z: Vec<u16> = bytes_z
7443 .chunks(2)
7444 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7445 .collect();
7446 assert!(
7447 hw_z.iter().filter(|&&h| h == 0xF04F).count() == 2,
7448 "SetCondZ high rd MOV.W: {hw_z:04x?}"
7449 );
7450 assert!(
7452 hw_z.contains(&(0xF1B0 | 8)),
7453 "SetCondZ high rd must use CMP.W: {hw_z:04x?}"
7454 );
7455 }
7456
7457 #[test]
7458 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7459 use synth_synthesis::{ArmOp, Condition, Reg};
7460 let enc = ArmEncoder::new_thumb2();
7461 let hi = enc
7463 .encode(&ArmOp::SetCond {
7464 rd: Reg::R12,
7465 cond: Condition::NE,
7466 })
7467 .unwrap();
7468 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7469 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7471 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7472 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7473 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7474 let lo = enc
7476 .encode(&ArmOp::SetCond {
7477 rd: Reg::R0,
7478 cond: Condition::NE,
7479 })
7480 .unwrap();
7481 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7482 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7483 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7484 }
7485
7486 #[test]
7490 fn test_encode_umull_209b() {
7491 use synth_synthesis::{ArmOp, Reg};
7492 let op = ArmOp::Umull {
7493 rdlo: Reg::R4,
7494 rdhi: Reg::R5,
7495 rn: Reg::R0,
7496 rm: Reg::R3,
7497 };
7498 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7500 assert_eq!(
7501 t,
7502 vec![0xA0, 0xFB, 0x03, 0x45],
7503 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7504 );
7505 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7507 assert_eq!(
7508 a,
7509 0xE085_4390u32.to_le_bytes().to_vec(),
7510 "umull (A32): {a:02x?}"
7511 );
7512 }
7513
7514 #[test]
7521 fn test_encode_arm32_indexed_load_keeps_index_206() {
7522 use synth_synthesis::{ArmOp, MemAddr, Reg};
7523 let enc = ArmEncoder::new_arm32();
7524 let bytes = enc
7526 .encode(&ArmOp::Ldr {
7527 rd: Reg::R0,
7528 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7529 })
7530 .unwrap();
7531 assert_eq!(
7532 bytes.len(),
7533 8,
7534 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7535 );
7536 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7537 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7538 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7540 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7542 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7544 }
7545
7546 #[test]
7553 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7554 let encoder = ArmEncoder::new_thumb2();
7555
7556 let code = encoder
7558 .encode(&ArmOp::Add {
7559 rd: Reg::R12,
7560 rn: Reg::R12,
7561 op2: Operand2::Reg(Reg::R0),
7562 })
7563 .unwrap();
7564 assert_eq!(
7566 code,
7567 vec![0x0C, 0xEB, 0x00, 0x0C],
7568 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7569 );
7570 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7572
7573 let lo = encoder
7575 .encode(&ArmOp::Add {
7576 rd: Reg::R1,
7577 rn: Reg::R2,
7578 op2: Operand2::Reg(Reg::R3),
7579 })
7580 .unwrap();
7581 assert_eq!(
7582 lo.len(),
7583 2,
7584 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7585 );
7586 }
7587
7588 #[test]
7591 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7592 let encoder = ArmEncoder::new_thumb2();
7593
7594 let adds = encoder
7596 .encode(&ArmOp::Adds {
7597 rd: Reg::R10,
7598 rn: Reg::R10,
7599 op2: Operand2::Reg(Reg::R8),
7600 })
7601 .unwrap();
7602 assert_eq!(
7603 adds,
7604 vec![0x1A, 0xEB, 0x08, 0x0A],
7605 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7606 );
7607
7608 let subs = encoder
7610 .encode(&ArmOp::Subs {
7611 rd: Reg::R10,
7612 rn: Reg::R10,
7613 op2: Operand2::Reg(Reg::R8),
7614 })
7615 .unwrap();
7616 assert_eq!(
7617 subs,
7618 vec![0xBA, 0xEB, 0x08, 0x0A],
7619 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7620 );
7621 }
7622
7623 #[test]
7626 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7627 let encoder = ArmEncoder::new_thumb2();
7628
7629 let cmn = encoder
7631 .encode(&ArmOp::Cmn {
7632 rn: Reg::R10,
7633 op2: Operand2::Reg(Reg::R8),
7634 })
7635 .unwrap();
7636 assert_eq!(
7637 cmn,
7638 vec![0x1A, 0xEB, 0x08, 0x0F],
7639 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7640 );
7641
7642 let lo = encoder
7644 .encode(&ArmOp::Cmn {
7645 rn: Reg::R1,
7646 op2: Operand2::Reg(Reg::R2),
7647 })
7648 .unwrap();
7649 assert_eq!(
7650 lo.len(),
7651 2,
7652 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7653 );
7654 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7655 }
7656
7657 #[test]
7661 fn test_encode_pc_operand_returns_err_not_panic_185() {
7662 let encoder = ArmEncoder::new_thumb2();
7663 for op in [
7664 ArmOp::Sdiv {
7665 rd: Reg::PC,
7666 rn: Reg::R0,
7667 rm: Reg::R1,
7668 },
7669 ArmOp::Udiv {
7670 rd: Reg::R0,
7671 rn: Reg::PC,
7672 rm: Reg::R1,
7673 },
7674 ArmOp::Sdiv {
7675 rd: Reg::R0,
7676 rn: Reg::R1,
7677 rm: Reg::PC,
7678 },
7679 ] {
7680 let r = encoder.encode(&op);
7681 assert!(
7682 r.is_err(),
7683 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7684 );
7685 }
7686 assert!(
7688 encoder
7689 .encode(&ArmOp::Sdiv {
7690 rd: Reg::R0,
7691 rn: Reg::R1,
7692 rm: Reg::R2
7693 })
7694 .is_ok()
7695 );
7696 }
7697
7698 #[test]
7699 fn test_encode_nop_arm32() {
7700 let encoder = ArmEncoder::new_arm32();
7701 let code = encoder.encode(&ArmOp::Nop).unwrap();
7702
7703 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7706
7707 #[test]
7708 fn test_encode_nop_thumb() {
7709 let encoder = ArmEncoder::new_thumb2();
7710 let code = encoder.encode(&ArmOp::Nop).unwrap();
7711
7712 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7715
7716 #[test]
7717 fn test_encode_mov_immediate_arm32() {
7718 let encoder = ArmEncoder::new_arm32();
7719 let op = ArmOp::Mov {
7720 rd: Reg::R0,
7721 op2: Operand2::Imm(42),
7722 };
7723
7724 let code = encoder.encode(&op).unwrap();
7725 assert_eq!(code.len(), 4);
7726
7727 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7729 assert_eq!(instr & 0x0E000000, 0x02000000); }
7731
7732 #[test]
7733 fn test_encode_add_registers_arm32() {
7734 let encoder = ArmEncoder::new_arm32();
7735 let op = ArmOp::Add {
7736 rd: Reg::R0,
7737 rn: Reg::R1,
7738 op2: Operand2::Reg(Reg::R2),
7739 };
7740
7741 let code = encoder.encode(&op).unwrap();
7742 assert_eq!(code.len(), 4);
7743
7744 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7745 assert_eq!(instr & 0x0FE00000, 0x00800000);
7747 }
7748
7749 #[test]
7753 fn test_encode_add_imm_large_350() {
7754 let enc = ArmEncoder::new_thumb2();
7755
7756 let small = enc
7758 .encode_thumb32_add_imm(&Reg::R0, &Reg::R1, 0x123)
7759 .unwrap();
7760 assert_eq!(small.len(), 4, "small imm must stay a single instruction");
7761
7762 fn movx_imm16(b: &[u8]) -> u32 {
7764 let hw1 = u16::from_le_bytes([b[0], b[1]]) as u32;
7765 let hw2 = u16::from_le_bytes([b[2], b[3]]) as u32;
7766 let imm4 = hw1 & 0xF;
7767 let i = (hw1 >> 10) & 1;
7768 let imm3 = (hw2 >> 12) & 0x7;
7769 let imm8 = hw2 & 0xFF;
7770 (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8
7771 }
7772 fn movx_rd(b: &[u8]) -> u32 {
7773 (u16::from_le_bytes([b[2], b[3]]) as u32 >> 8) & 0xF
7774 }
7775
7776 let seq = enc
7779 .encode_thumb32_add_imm(&Reg::R12, &Reg::R0, 70000)
7780 .unwrap();
7781 assert_eq!(seq.len(), 12, "MOVW + MOVT + ADD = 12 bytes");
7782 assert_eq!(u16::from_le_bytes([seq[0], seq[1]]) & 0xFBF0, 0xF240);
7784 assert_eq!(movx_rd(&seq[0..4]), 12);
7785 assert_eq!(movx_imm16(&seq[0..4]), 0x1170);
7786 assert_eq!(u16::from_le_bytes([seq[4], seq[5]]) & 0xFBF0, 0xF2C0);
7788 assert_eq!(movx_rd(&seq[4..8]), 12);
7789 assert_eq!(movx_imm16(&seq[4..8]), 0x0001);
7790 let add1 = u16::from_le_bytes([seq[8], seq[9]]) as u32;
7792 let add2 = u16::from_le_bytes([seq[10], seq[11]]) as u32;
7793 assert_eq!(add1 & 0xFFF0, 0xEB00);
7794 assert_eq!(add1 & 0xF, 0); assert_eq!((add2 >> 8) & 0xF, 12); assert_eq!(add2 & 0xF, 12); assert_eq!(
7799 (movx_imm16(&seq[4..8]) << 16) | movx_imm16(&seq[0..4]),
7800 70000
7801 );
7802
7803 let seq16 = enc
7805 .encode_thumb32_add_imm(&Reg::R3, &Reg::R0, 0xABCD)
7806 .unwrap();
7807 assert_eq!(seq16.len(), 8, "imm <= 0xFFFF skips MOVT");
7808 assert_eq!(movx_imm16(&seq16[0..4]), 0xABCD);
7809 assert_eq!(movx_rd(&seq16[0..4]), 3); let inplace = enc
7814 .encode_thumb32_add_imm(&Reg::R5, &Reg::R5, 0x12345)
7815 .unwrap();
7816 assert_eq!(inplace.len(), 12);
7817 assert_eq!(movx_rd(&inplace[0..4]), 12, "rd==rn must use R12 scratch");
7818 assert_eq!(
7819 (movx_imm16(&inplace[4..8]) << 16) | movx_imm16(&inplace[0..4]),
7820 0x12345
7821 );
7822 let ip_add2 = u16::from_le_bytes([inplace[10], inplace[11]]) as u32;
7824 assert_eq!(ip_add2 & 0xF, 12);
7825 assert_eq!((ip_add2 >> 8) & 0xF, 5);
7826 }
7827
7828 #[test]
7836 fn test_encode_add_imm_large_rd_rn_r12_errs_not_panics_350() {
7837 let enc = ArmEncoder::new_thumb2();
7838 let r = enc.encode_thumb32_add_imm(&Reg::R12, &Reg::R12, 70000);
7840 assert!(
7841 r.is_err(),
7842 "rd==rn==R12 with out-of-range imm must Err (no free scratch), got {r:?}"
7843 );
7844 let small = enc.encode_thumb32_add_imm(&Reg::R12, &Reg::R12, 0x10);
7848 assert!(small.is_ok(), "small imm needs no scratch, must stay Ok");
7849 }
7850
7851 #[test]
7860 fn test_encode_operand2_non_rotatable_imm_errs_not_masks_378() {
7861 let enc = ArmEncoder::new_arm32();
7862 let bad = enc.encode(&ArmOp::Add {
7863 rd: Reg::R0,
7864 rn: Reg::R1,
7865 op2: Operand2::Imm(0x1FF),
7866 });
7867 assert!(
7868 bad.is_err(),
7869 "non-rotatable ARM32 immediate 0x1FF must Err (was silently masked \
7870 to 0xFF), got {bad:?}"
7871 );
7872 let ok = enc.encode(&ArmOp::Add {
7874 rd: Reg::R0,
7875 rn: Reg::R1,
7876 op2: Operand2::Imm(0xFF),
7877 });
7878 assert!(
7879 ok.is_ok(),
7880 "0xFF is a valid rotated immediate, must stay Ok"
7881 );
7882 }
7883
7884 #[test]
7885 fn test_encode_ldr_arm32() {
7886 let encoder = ArmEncoder::new_arm32();
7887 let op = ArmOp::Ldr {
7888 rd: Reg::R0,
7889 addr: MemAddr::imm(Reg::R1, 4),
7890 };
7891
7892 let code = encoder.encode(&op).unwrap();
7893 assert_eq!(code.len(), 4);
7894
7895 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7896 assert_eq!(instr & 0x00100000, 0x00100000);
7898 }
7899
7900 #[test]
7901 fn test_encode_str_arm32() {
7902 let encoder = ArmEncoder::new_arm32();
7903 let op = ArmOp::Str {
7904 rd: Reg::R0,
7905 addr: MemAddr::imm(Reg::SP, 0),
7906 };
7907
7908 let code = encoder.encode(&op).unwrap();
7909 assert_eq!(code.len(), 4);
7910 }
7911
7912 #[test]
7913 fn test_encode_branch_arm32() {
7914 let encoder = ArmEncoder::new_arm32();
7915 let op = ArmOp::Bl {
7916 label: "main".to_string(),
7917 };
7918
7919 let code = encoder.encode(&op).unwrap();
7920 assert_eq!(code.len(), 4);
7921
7922 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7923 assert_eq!(instr & 0x0F000000, 0x0B000000);
7925 }
7926
7927 #[test]
7937 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7938 let encoder = ArmEncoder::new_thumb2();
7939 let op = ArmOp::Bl {
7940 label: "callee".to_string(),
7941 };
7942
7943 let code = encoder.encode(&op).unwrap();
7944 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7945
7946 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7947 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7948 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7949 assert_eq!(
7950 hw2, 0xFFFE,
7951 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7952 );
7953 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7954 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7955 }
7956
7957 #[test]
7958 fn test_encode_sequence() {
7959 let encoder = ArmEncoder::new_arm32();
7960 let ops = vec![
7961 ArmOp::Mov {
7962 rd: Reg::R0,
7963 op2: Operand2::Imm(42),
7964 },
7965 ArmOp::Mov {
7966 rd: Reg::R1,
7967 op2: Operand2::Imm(10),
7968 },
7969 ArmOp::Add {
7970 rd: Reg::R2,
7971 rn: Reg::R0,
7972 op2: Operand2::Reg(Reg::R1),
7973 },
7974 ];
7975
7976 let code = encoder.encode_sequence(&ops).unwrap();
7977 assert_eq!(code.len(), 12); }
7979
7980 #[test]
7981 fn test_reg_to_bits() {
7982 assert_eq!(reg_to_bits(&Reg::R0), 0);
7983 assert_eq!(reg_to_bits(&Reg::R7), 7);
7984 assert_eq!(reg_to_bits(&Reg::SP), 13);
7985 assert_eq!(reg_to_bits(&Reg::LR), 14);
7986 assert_eq!(reg_to_bits(&Reg::PC), 15);
7987 }
7988
7989 #[test]
7990 fn test_encode_bitwise_operations() {
7991 let encoder = ArmEncoder::new_arm32();
7992
7993 let and_op = ArmOp::And {
7994 rd: Reg::R0,
7995 rn: Reg::R1,
7996 op2: Operand2::Reg(Reg::R2),
7997 };
7998 let and_code = encoder.encode(&and_op).unwrap();
7999 assert_eq!(and_code.len(), 4);
8000
8001 let orr_op = ArmOp::Orr {
8002 rd: Reg::R0,
8003 rn: Reg::R1,
8004 op2: Operand2::Reg(Reg::R2),
8005 };
8006 let orr_code = encoder.encode(&orr_op).unwrap();
8007 assert_eq!(orr_code.len(), 4);
8008
8009 let eor_op = ArmOp::Eor {
8010 rd: Reg::R0,
8011 rn: Reg::R1,
8012 op2: Operand2::Reg(Reg::R2),
8013 };
8014 let eor_code = encoder.encode(&eor_op).unwrap();
8015 assert_eq!(eor_code.len(), 4);
8016 }
8017
8018 #[test]
8021 fn test_encode_sdiv_thumb2() {
8022 let encoder = ArmEncoder::new_thumb2();
8023 let op = ArmOp::Sdiv {
8024 rd: Reg::R0,
8025 rn: Reg::R1,
8026 rm: Reg::R2,
8027 };
8028
8029 let code = encoder.encode(&op).unwrap();
8030 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
8037 assert_eq!(code[1], 0xFB);
8038 assert_eq!(code[2], 0xF2);
8039 assert_eq!(code[3], 0xF0);
8040 }
8041
8042 #[test]
8043 fn test_encode_udiv_thumb2() {
8044 let encoder = ArmEncoder::new_thumb2();
8045 let op = ArmOp::Udiv {
8046 rd: Reg::R0,
8047 rn: Reg::R1,
8048 rm: Reg::R2,
8049 };
8050
8051 let code = encoder.encode(&op).unwrap();
8052 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
8057 assert_eq!(code[1], 0xFB);
8058 assert_eq!(code[2], 0xF2);
8059 assert_eq!(code[3], 0xF0);
8060 }
8061
8062 #[test]
8063 fn test_encode_mul_thumb2() {
8064 let encoder = ArmEncoder::new_thumb2();
8065 let op = ArmOp::Mul {
8066 rd: Reg::R0,
8067 rn: Reg::R1,
8068 rm: Reg::R2,
8069 };
8070
8071 let code = encoder.encode(&op).unwrap();
8072 assert_eq!(code.len(), 4); }
8074
8075 #[test]
8076 fn test_encode_and_thumb2() {
8077 let encoder = ArmEncoder::new_thumb2();
8078 let op = ArmOp::And {
8079 rd: Reg::R0,
8080 rn: Reg::R1,
8081 op2: Operand2::Reg(Reg::R2),
8082 };
8083
8084 let code = encoder.encode(&op).unwrap();
8085 assert_eq!(code.len(), 4); }
8087
8088 #[test]
8089 fn test_encode_lsl_thumb2_low_regs() {
8090 let encoder = ArmEncoder::new_thumb2();
8091 let op = ArmOp::Lsl {
8092 rd: Reg::R0,
8093 rn: Reg::R1,
8094 shift: 5,
8095 };
8096
8097 let code = encoder.encode(&op).unwrap();
8098 assert_eq!(code.len(), 2); }
8100
8101 #[test]
8102 fn test_encode_clz_thumb2() {
8103 let encoder = ArmEncoder::new_thumb2();
8104 let op = ArmOp::Clz {
8105 rd: Reg::R0,
8106 rm: Reg::R1,
8107 };
8108
8109 let code = encoder.encode(&op).unwrap();
8110 assert_eq!(code.len(), 4); }
8112
8113 #[test]
8114 fn test_encode_bx_thumb2() {
8115 let encoder = ArmEncoder::new_thumb2();
8116 let op = ArmOp::Bx { rm: Reg::LR };
8117
8118 let code = encoder.encode(&op).unwrap();
8119 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
8123 }
8124
8125 #[test]
8130 fn test_encode_f32_abs_arm32() {
8131 let encoder = ArmEncoder::new_arm32();
8132 let op = ArmOp::F32Abs {
8133 sd: VfpReg::S0,
8134 sm: VfpReg::S2,
8135 };
8136 let code = encoder.encode(&op).unwrap();
8137 assert_eq!(code.len(), 4); }
8139
8140 #[test]
8141 fn test_encode_f32_neg_arm32() {
8142 let encoder = ArmEncoder::new_arm32();
8143 let op = ArmOp::F32Neg {
8144 sd: VfpReg::S0,
8145 sm: VfpReg::S2,
8146 };
8147 let code = encoder.encode(&op).unwrap();
8148 assert_eq!(code.len(), 4);
8149 }
8150
8151 #[test]
8152 fn test_encode_f32_sqrt_arm32() {
8153 let encoder = ArmEncoder::new_arm32();
8154 let op = ArmOp::F32Sqrt {
8155 sd: VfpReg::S0,
8156 sm: VfpReg::S2,
8157 };
8158 let code = encoder.encode(&op).unwrap();
8159 assert_eq!(code.len(), 4);
8160 }
8161
8162 #[test]
8163 fn test_encode_f32_ceil_arm32() {
8164 let encoder = ArmEncoder::new_arm32();
8165 let op = ArmOp::F32Ceil {
8166 sd: VfpReg::S0,
8167 sm: VfpReg::S2,
8168 };
8169 let code = encoder.encode(&op).unwrap();
8170 assert_eq!(code.len(), 36);
8172 }
8173
8174 #[test]
8175 fn test_encode_f32_floor_thumb2() {
8176 let encoder = ArmEncoder::new_thumb2();
8177 let op = ArmOp::F32Floor {
8178 sd: VfpReg::S0,
8179 sm: VfpReg::S2,
8180 };
8181 let code = encoder.encode(&op).unwrap();
8182 assert_eq!(code.len(), 36);
8184 }
8185
8186 #[test]
8187 fn test_encode_f32_min_arm32() {
8188 let encoder = ArmEncoder::new_arm32();
8189 let op = ArmOp::F32Min {
8190 sd: VfpReg::S0,
8191 sn: VfpReg::S2,
8192 sm: VfpReg::S4,
8193 };
8194 let code = encoder.encode(&op).unwrap();
8195 assert_eq!(code.len(), 16); }
8197
8198 #[test]
8199 fn test_encode_f32_max_thumb2() {
8200 let encoder = ArmEncoder::new_thumb2();
8201 let op = ArmOp::F32Max {
8202 sd: VfpReg::S0,
8203 sn: VfpReg::S2,
8204 sm: VfpReg::S4,
8205 };
8206 let code = encoder.encode(&op).unwrap();
8207 assert_eq!(code.len(), 18);
8209 }
8210
8211 #[test]
8212 fn test_encode_f32_copysign_arm32() {
8213 let encoder = ArmEncoder::new_arm32();
8214 let op = ArmOp::F32Copysign {
8215 sd: VfpReg::S0,
8216 sn: VfpReg::S2,
8217 sm: VfpReg::S4,
8218 };
8219 let code = encoder.encode(&op).unwrap();
8220 assert_eq!(code.len(), 24);
8222 }
8223
8224 #[test]
8229 fn test_encode_f64_add_arm32() {
8230 let encoder = ArmEncoder::new_arm32();
8231 let op = ArmOp::F64Add {
8232 dd: VfpReg::D0,
8233 dn: VfpReg::D1,
8234 dm: VfpReg::D2,
8235 };
8236 let code = encoder.encode(&op).unwrap();
8237 assert_eq!(code.len(), 4);
8238 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8240 assert_eq!((instr >> 8) & 0xF, 0xB); }
8242
8243 #[test]
8244 fn test_encode_f64_sub_thumb2() {
8245 let encoder = ArmEncoder::new_thumb2();
8246 let op = ArmOp::F64Sub {
8247 dd: VfpReg::D0,
8248 dn: VfpReg::D1,
8249 dm: VfpReg::D2,
8250 };
8251 let code = encoder.encode(&op).unwrap();
8252 assert_eq!(code.len(), 4); }
8254
8255 #[test]
8256 fn test_encode_f64_mul_arm32() {
8257 let encoder = ArmEncoder::new_arm32();
8258 let op = ArmOp::F64Mul {
8259 dd: VfpReg::D0,
8260 dn: VfpReg::D1,
8261 dm: VfpReg::D2,
8262 };
8263 let code = encoder.encode(&op).unwrap();
8264 assert_eq!(code.len(), 4);
8265 }
8266
8267 #[test]
8268 fn test_encode_f64_div_arm32() {
8269 let encoder = ArmEncoder::new_arm32();
8270 let op = ArmOp::F64Div {
8271 dd: VfpReg::D0,
8272 dn: VfpReg::D1,
8273 dm: VfpReg::D2,
8274 };
8275 let code = encoder.encode(&op).unwrap();
8276 assert_eq!(code.len(), 4);
8277 }
8278
8279 #[test]
8280 fn test_encode_f64_abs_arm32() {
8281 let encoder = ArmEncoder::new_arm32();
8282 let op = ArmOp::F64Abs {
8283 dd: VfpReg::D0,
8284 dm: VfpReg::D2,
8285 };
8286 let code = encoder.encode(&op).unwrap();
8287 assert_eq!(code.len(), 4);
8288 }
8289
8290 #[test]
8291 fn test_encode_f64_neg_arm32() {
8292 let encoder = ArmEncoder::new_arm32();
8293 let op = ArmOp::F64Neg {
8294 dd: VfpReg::D0,
8295 dm: VfpReg::D2,
8296 };
8297 let code = encoder.encode(&op).unwrap();
8298 assert_eq!(code.len(), 4);
8299 }
8300
8301 #[test]
8302 fn test_encode_f64_sqrt_arm32() {
8303 let encoder = ArmEncoder::new_arm32();
8304 let op = ArmOp::F64Sqrt {
8305 dd: VfpReg::D0,
8306 dm: VfpReg::D2,
8307 };
8308 let code = encoder.encode(&op).unwrap();
8309 assert_eq!(code.len(), 4);
8310 }
8311
8312 #[test]
8313 fn test_encode_f64_load_arm32() {
8314 let encoder = ArmEncoder::new_arm32();
8315 let op = ArmOp::F64Load {
8316 dd: VfpReg::D0,
8317 addr: MemAddr::imm(Reg::R0, 8),
8318 };
8319 let code = encoder.encode(&op).unwrap();
8320 assert_eq!(code.len(), 4);
8321 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8322 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
8325
8326 #[test]
8327 fn test_encode_f64_store_thumb2() {
8328 let encoder = ArmEncoder::new_thumb2();
8329 let op = ArmOp::F64Store {
8330 dd: VfpReg::D0,
8331 addr: MemAddr::imm(Reg::SP, 0),
8332 };
8333 let code = encoder.encode(&op).unwrap();
8334 assert_eq!(code.len(), 4);
8335 }
8336
8337 #[test]
8338 fn test_encode_f64_compare_arm32() {
8339 let encoder = ArmEncoder::new_arm32();
8340 let op = ArmOp::F64Eq {
8341 rd: Reg::R0,
8342 dn: VfpReg::D0,
8343 dm: VfpReg::D1,
8344 };
8345 let code = encoder.encode(&op).unwrap();
8346 assert_eq!(code.len(), 16); }
8348
8349 #[test]
8350 fn test_encode_f64_compare_thumb2() {
8351 let encoder = ArmEncoder::new_thumb2();
8352 let op = ArmOp::F64Lt {
8353 rd: Reg::R0,
8354 dn: VfpReg::D0,
8355 dm: VfpReg::D1,
8356 };
8357 let code = encoder.encode(&op).unwrap();
8358 assert_eq!(code.len(), 14);
8360 }
8361
8362 #[test]
8363 fn test_encode_f64_const_arm32() {
8364 let encoder = ArmEncoder::new_arm32();
8365 let op = ArmOp::F64Const {
8366 dd: VfpReg::D0,
8367 value: 3.125,
8368 };
8369 let code = encoder.encode(&op).unwrap();
8370 assert_eq!(code.len(), 20);
8372 }
8373
8374 #[test]
8375 fn test_encode_f64_const_thumb2() {
8376 let encoder = ArmEncoder::new_thumb2();
8377 let op = ArmOp::F64Const {
8378 dd: VfpReg::D0,
8379 value: 2.5,
8380 };
8381 let code = encoder.encode(&op).unwrap();
8382 assert_eq!(code.len(), 20);
8384 }
8385
8386 #[test]
8387 fn test_encode_f64_convert_i32s_arm32() {
8388 let encoder = ArmEncoder::new_arm32();
8389 let op = ArmOp::F64ConvertI32S {
8390 dd: VfpReg::D0,
8391 rm: Reg::R0,
8392 };
8393 let code = encoder.encode(&op).unwrap();
8394 assert_eq!(code.len(), 8);
8396 }
8397
8398 #[test]
8399 fn test_encode_f64_promote_f32_arm32() {
8400 let encoder = ArmEncoder::new_arm32();
8401 let op = ArmOp::F64PromoteF32 {
8402 dd: VfpReg::D0,
8403 sm: VfpReg::S0,
8404 };
8405 let code = encoder.encode(&op).unwrap();
8406 assert_eq!(code.len(), 4); }
8408
8409 #[test]
8410 fn test_encode_f64_promote_f32_thumb2() {
8411 let encoder = ArmEncoder::new_thumb2();
8412 let op = ArmOp::F64PromoteF32 {
8413 dd: VfpReg::D0,
8414 sm: VfpReg::S0,
8415 };
8416 let code = encoder.encode(&op).unwrap();
8417 assert_eq!(code.len(), 4);
8418 }
8419
8420 #[test]
8421 fn test_encode_i32_trunc_f64s_arm32() {
8422 let encoder = ArmEncoder::new_arm32();
8423 let op = ArmOp::I32TruncF64S {
8424 rd: Reg::R0,
8425 dm: VfpReg::D0,
8426 };
8427 let code = encoder.encode(&op).unwrap();
8428 assert_eq!(code.len(), 8);
8430 }
8431
8432 #[test]
8433 fn test_encode_f64_reinterpret_i64_arm32() {
8434 let encoder = ArmEncoder::new_arm32();
8435 let op = ArmOp::F64ReinterpretI64 {
8436 dd: VfpReg::D0,
8437 rmlo: Reg::R0,
8438 rmhi: Reg::R1,
8439 };
8440 let code = encoder.encode(&op).unwrap();
8441 assert_eq!(code.len(), 4); }
8443
8444 #[test]
8445 fn test_encode_i64_reinterpret_f64_thumb2() {
8446 let encoder = ArmEncoder::new_thumb2();
8447 let op = ArmOp::I64ReinterpretF64 {
8448 rdlo: Reg::R0,
8449 rdhi: Reg::R1,
8450 dm: VfpReg::D0,
8451 };
8452 let code = encoder.encode(&op).unwrap();
8453 assert_eq!(code.len(), 4);
8454 }
8455
8456 #[test]
8457 fn test_encode_f64_trunc_thumb2() {
8458 let encoder = ArmEncoder::new_thumb2();
8459 let op = ArmOp::F64Trunc {
8460 dd: VfpReg::D0,
8461 dm: VfpReg::D1,
8462 };
8463 let code = encoder.encode(&op).unwrap();
8464 assert_eq!(code.len(), 8);
8466 }
8467
8468 #[test]
8469 fn test_encode_f64_min_arm32() {
8470 let encoder = ArmEncoder::new_arm32();
8471 let op = ArmOp::F64Min {
8472 dd: VfpReg::D0,
8473 dn: VfpReg::D1,
8474 dm: VfpReg::D2,
8475 };
8476 let code = encoder.encode(&op).unwrap();
8477 assert_eq!(code.len(), 16);
8479 }
8480
8481 #[test]
8482 fn test_f64_cp11_encoding() {
8483 let encoder = ArmEncoder::new_arm32();
8485
8486 let code = encoder
8488 .encode(&ArmOp::F64Add {
8489 dd: VfpReg::D0,
8490 dn: VfpReg::D0,
8491 dm: VfpReg::D0,
8492 })
8493 .unwrap();
8494 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8495 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8496
8497 let code = encoder
8499 .encode(&ArmOp::F32Add {
8500 sd: VfpReg::S0,
8501 sn: VfpReg::S0,
8502 sm: VfpReg::S0,
8503 })
8504 .unwrap();
8505 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8506 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8507 }
8508
8509 #[test]
8510 fn test_dreg_encoding_higher_registers() {
8511 let encoder = ArmEncoder::new_arm32();
8512
8513 let op = ArmOp::F64Add {
8515 dd: VfpReg::D15,
8516 dn: VfpReg::D14,
8517 dm: VfpReg::D13,
8518 };
8519 let code = encoder.encode(&op).unwrap();
8520 assert_eq!(code.len(), 4);
8521
8522 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8524 assert_eq!((instr >> 8) & 0xF, 0xB); }
8526
8527 #[test]
8532 fn test_encode_label_emits_no_bytes() {
8533 let encoder = ArmEncoder::new_thumb2();
8534 let op = ArmOp::Label {
8535 name: ".Lblock_end_0".to_string(),
8536 };
8537 let code = encoder.encode(&op).unwrap();
8538 assert!(code.is_empty(), "Label should emit zero bytes");
8539
8540 let encoder32 = ArmEncoder::new_arm32();
8541 let code32 = encoder32.encode(&op).unwrap();
8542 assert!(
8543 code32.is_empty(),
8544 "Label should emit zero bytes in ARM32 too"
8545 );
8546 }
8547
8548 #[test]
8549 fn test_encode_bcc_eq_thumb2() {
8550 use synth_synthesis::Condition;
8551 let encoder = ArmEncoder::new_thumb2();
8552 let op = ArmOp::Bcc {
8553 cond: Condition::EQ,
8554 label: "target".to_string(),
8555 };
8556 let code = encoder.encode(&op).unwrap();
8557 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8561 }
8562
8563 #[test]
8564 fn test_encode_bcc_ne_thumb2() {
8565 use synth_synthesis::Condition;
8566 let encoder = ArmEncoder::new_thumb2();
8567 let op = ArmOp::Bcc {
8568 cond: Condition::NE,
8569 label: "target".to_string(),
8570 };
8571 let code = encoder.encode(&op).unwrap();
8572 assert_eq!(code.len(), 2);
8573
8574 assert_eq!(code, vec![0x00, 0xD1]);
8576 }
8577
8578 #[test]
8579 fn test_encode_bcc_arm32() {
8580 use synth_synthesis::Condition;
8581 let encoder = ArmEncoder::new_arm32();
8582 let op = ArmOp::Bcc {
8583 cond: Condition::EQ,
8584 label: "target".to_string(),
8585 };
8586 let code = encoder.encode(&op).unwrap();
8587 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8590 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8594
8595 #[test]
8596 fn test_encode_udf_thumb2() {
8597 let encoder = ArmEncoder::new_thumb2();
8598 let op = ArmOp::Udf { imm: 0 };
8599 let code = encoder.encode(&op).unwrap();
8600 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8604 }
8605
8606 #[test]
8607 fn test_encode_nop_thumb2() {
8608 let encoder = ArmEncoder::new_thumb2();
8609 let op = ArmOp::Nop;
8610 let code = encoder.encode(&op).unwrap();
8611 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8615 }
8616
8617 #[test]
8622 fn test_encode_i64_add_thumb2() {
8623 let encoder = ArmEncoder::new_thumb2();
8624 let op = ArmOp::I64Add {
8625 rdlo: Reg::R0,
8626 rdhi: Reg::R1,
8627 rnlo: Reg::R0,
8628 rnhi: Reg::R1,
8629 rmlo: Reg::R2,
8630 rmhi: Reg::R3,
8631 };
8632 let code = encoder.encode(&op).unwrap();
8633 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8635 }
8636
8637 #[test]
8638 fn test_encode_i64_sub_thumb2() {
8639 let encoder = ArmEncoder::new_thumb2();
8640 let op = ArmOp::I64Sub {
8641 rdlo: Reg::R0,
8642 rdhi: Reg::R1,
8643 rnlo: Reg::R0,
8644 rnhi: Reg::R1,
8645 rmlo: Reg::R2,
8646 rmhi: Reg::R3,
8647 };
8648 let code = encoder.encode(&op).unwrap();
8649 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8651 }
8652
8653 #[test]
8654 fn test_encode_i64_and_thumb2() {
8655 let encoder = ArmEncoder::new_thumb2();
8656 let op = ArmOp::I64And {
8657 rdlo: Reg::R0,
8658 rdhi: Reg::R1,
8659 rnlo: Reg::R0,
8660 rnhi: Reg::R1,
8661 rmlo: Reg::R2,
8662 rmhi: Reg::R3,
8663 };
8664 let code = encoder.encode(&op).unwrap();
8665 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8667 }
8668
8669 #[test]
8670 fn test_encode_i64_or_thumb2() {
8671 let encoder = ArmEncoder::new_thumb2();
8672 let op = ArmOp::I64Or {
8673 rdlo: Reg::R0,
8674 rdhi: Reg::R1,
8675 rnlo: Reg::R0,
8676 rnhi: Reg::R1,
8677 rmlo: Reg::R2,
8678 rmhi: Reg::R3,
8679 };
8680 let code = encoder.encode(&op).unwrap();
8681 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8682 }
8683
8684 #[test]
8685 fn test_encode_i64_xor_thumb2() {
8686 let encoder = ArmEncoder::new_thumb2();
8687 let op = ArmOp::I64Xor {
8688 rdlo: Reg::R0,
8689 rdhi: Reg::R1,
8690 rnlo: Reg::R0,
8691 rnhi: Reg::R1,
8692 rmlo: Reg::R2,
8693 rmhi: Reg::R3,
8694 };
8695 let code = encoder.encode(&op).unwrap();
8696 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8697 }
8698
8699 #[test]
8700 fn test_encode_i64_const_small_thumb2() {
8701 let encoder = ArmEncoder::new_thumb2();
8702 let op = ArmOp::I64Const {
8704 rdlo: Reg::R0,
8705 rdhi: Reg::R1,
8706 value: 42,
8707 };
8708 let code = encoder.encode(&op).unwrap();
8709 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8711 }
8712
8713 #[test]
8714 fn test_encode_i64_const_large_thumb2() {
8715 let encoder = ArmEncoder::new_thumb2();
8716 let op = ArmOp::I64Const {
8718 rdlo: Reg::R0,
8719 rdhi: Reg::R1,
8720 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8721 };
8722 let code = encoder.encode(&op).unwrap();
8723 assert_eq!(
8725 code.len(),
8726 16,
8727 "I64Const with large value should be 16 bytes"
8728 );
8729 }
8730
8731 #[test]
8732 fn test_encode_i64_extend_i32_s_thumb2() {
8733 let encoder = ArmEncoder::new_thumb2();
8734 let op = ArmOp::I64ExtendI32S {
8735 rdlo: Reg::R0,
8736 rdhi: Reg::R1,
8737 rn: Reg::R0,
8738 };
8739 let code = encoder.encode(&op).unwrap();
8740 assert_eq!(
8742 code.len(),
8743 4,
8744 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8745 );
8746 }
8747
8748 #[test]
8749 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8750 let encoder = ArmEncoder::new_thumb2();
8751 let op = ArmOp::I64ExtendI32S {
8752 rdlo: Reg::R0,
8753 rdhi: Reg::R1,
8754 rn: Reg::R2,
8755 };
8756 let code = encoder.encode(&op).unwrap();
8757 assert!(
8759 code.len() >= 6,
8760 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8761 );
8762 }
8763
8764 #[test]
8765 fn test_encode_i64_extend_i32_u_thumb2() {
8766 let encoder = ArmEncoder::new_thumb2();
8767 let op = ArmOp::I64ExtendI32U {
8768 rdlo: Reg::R0,
8769 rdhi: Reg::R1,
8770 rn: Reg::R0,
8771 };
8772 let code = encoder.encode(&op).unwrap();
8773 assert_eq!(
8775 code.len(),
8776 2,
8777 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8778 );
8779 }
8780
8781 #[test]
8782 fn test_encode_i32_wrap_i64_nop_thumb2() {
8783 let encoder = ArmEncoder::new_thumb2();
8784 let op = ArmOp::I32WrapI64 {
8786 rd: Reg::R0,
8787 rnlo: Reg::R0,
8788 };
8789 let code = encoder.encode(&op).unwrap();
8790 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8791 assert_eq!(code, vec![0x00, 0xBF]); }
8793
8794 #[test]
8795 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8796 let encoder = ArmEncoder::new_thumb2();
8797 let op = ArmOp::I32WrapI64 {
8798 rd: Reg::R2,
8799 rnlo: Reg::R0,
8800 };
8801 let code = encoder.encode(&op).unwrap();
8802 assert!(
8804 code.len() >= 2,
8805 "I32WrapI64 diff reg should emit at least 2 bytes"
8806 );
8807 }
8808
8809 #[test]
8810 fn test_encode_i64_eqz_thumb2() {
8811 let encoder = ArmEncoder::new_thumb2();
8812 let op = ArmOp::I64Eqz {
8813 rd: Reg::R0,
8814 rnlo: Reg::R0,
8815 rnhi: Reg::R1,
8816 };
8817 let code = encoder.encode(&op).unwrap();
8818 assert!(
8820 code.len() >= 6,
8821 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8822 );
8823 }
8824
8825 #[test]
8826 fn test_encode_i64_eq_thumb2() {
8827 let encoder = ArmEncoder::new_thumb2();
8828 let op = ArmOp::I64Eq {
8829 rd: Reg::R0,
8830 rnlo: Reg::R0,
8831 rnhi: Reg::R1,
8832 rmlo: Reg::R2,
8833 rmhi: Reg::R3,
8834 };
8835 let code = encoder.encode(&op).unwrap();
8836 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8838 }
8839
8840 #[test]
8841 fn test_encode_i64_ldr_thumb2() {
8842 let encoder = ArmEncoder::new_thumb2();
8843 let op = ArmOp::I64Ldr {
8844 rdlo: Reg::R0,
8845 rdhi: Reg::R1,
8846 addr: MemAddr::imm(Reg::SP, 0),
8847 };
8848 let code = encoder.encode(&op).unwrap();
8849 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8851 }
8852
8853 #[test]
8854 fn test_372_i64_ldr_indexed_materializes_address() {
8855 let encoder = ArmEncoder::new_thumb2();
8860 let indexed = encoder
8861 .encode(&ArmOp::I64Ldr {
8862 rdlo: Reg::R0,
8863 rdhi: Reg::R1,
8864 addr: MemAddr::reg_imm(Reg::R11, Reg::R0, 0),
8865 })
8866 .unwrap();
8867 assert_eq!(
8869 &indexed[0..4],
8870 &[0x0b, 0xeb, 0x00, 0x0c],
8871 "indexed I64Ldr must start with ADD.W ip, base, index"
8872 );
8873 let frame = encoder
8874 .encode(&ArmOp::I64Ldr {
8875 rdlo: Reg::R0,
8876 rdhi: Reg::R1,
8877 addr: MemAddr::imm(Reg::SP, 8),
8878 })
8879 .unwrap();
8880 assert_ne!(
8882 &frame[0..2],
8883 &[0x0b, 0xeb],
8884 "frame (non-indexed) I64Ldr must NOT emit an ADD.W"
8885 );
8886 }
8887
8888 #[test]
8889 fn test_encode_i64_str_thumb2() {
8890 let encoder = ArmEncoder::new_thumb2();
8891 let op = ArmOp::I64Str {
8892 rdlo: Reg::R0,
8893 rdhi: Reg::R1,
8894 addr: MemAddr::imm(Reg::SP, 0),
8895 };
8896 let code = encoder.encode(&op).unwrap();
8897 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8899 }
8900
8901 #[test]
8902 fn test_encode_i64_all_comparisons_thumb2() {
8903 let encoder = ArmEncoder::new_thumb2();
8904
8905 let ops = vec![
8906 ArmOp::I64Ne {
8907 rd: Reg::R0,
8908 rnlo: Reg::R0,
8909 rnhi: Reg::R1,
8910 rmlo: Reg::R2,
8911 rmhi: Reg::R3,
8912 },
8913 ArmOp::I64LtS {
8914 rd: Reg::R0,
8915 rnlo: Reg::R0,
8916 rnhi: Reg::R1,
8917 rmlo: Reg::R2,
8918 rmhi: Reg::R3,
8919 },
8920 ArmOp::I64LtU {
8921 rd: Reg::R0,
8922 rnlo: Reg::R0,
8923 rnhi: Reg::R1,
8924 rmlo: Reg::R2,
8925 rmhi: Reg::R3,
8926 },
8927 ArmOp::I64LeS {
8928 rd: Reg::R0,
8929 rnlo: Reg::R0,
8930 rnhi: Reg::R1,
8931 rmlo: Reg::R2,
8932 rmhi: Reg::R3,
8933 },
8934 ArmOp::I64LeU {
8935 rd: Reg::R0,
8936 rnlo: Reg::R0,
8937 rnhi: Reg::R1,
8938 rmlo: Reg::R2,
8939 rmhi: Reg::R3,
8940 },
8941 ArmOp::I64GtS {
8942 rd: Reg::R0,
8943 rnlo: Reg::R0,
8944 rnhi: Reg::R1,
8945 rmlo: Reg::R2,
8946 rmhi: Reg::R3,
8947 },
8948 ArmOp::I64GtU {
8949 rd: Reg::R0,
8950 rnlo: Reg::R0,
8951 rnhi: Reg::R1,
8952 rmlo: Reg::R2,
8953 rmhi: Reg::R3,
8954 },
8955 ArmOp::I64GeS {
8956 rd: Reg::R0,
8957 rnlo: Reg::R0,
8958 rnhi: Reg::R1,
8959 rmlo: Reg::R2,
8960 rmhi: Reg::R3,
8961 },
8962 ArmOp::I64GeU {
8963 rd: Reg::R0,
8964 rnlo: Reg::R0,
8965 rnhi: Reg::R1,
8966 rmlo: Reg::R2,
8967 rmhi: Reg::R3,
8968 },
8969 ];
8970
8971 for op in &ops {
8972 let code = encoder.encode(op).unwrap();
8973 assert!(
8974 code.len() >= 8,
8975 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8976 op,
8977 code.len()
8978 );
8979 }
8980 }
8981
8982 #[test]
8983 fn test_encode_i64_const_zero_thumb2() {
8984 let encoder = ArmEncoder::new_thumb2();
8985 let op = ArmOp::I64Const {
8986 rdlo: Reg::R0,
8987 rdhi: Reg::R1,
8988 value: 0,
8989 };
8990 let code = encoder.encode(&op).unwrap();
8991 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8993 }
8994
8995 #[test]
8996 fn test_encode_i64_const_negative_one_thumb2() {
8997 let encoder = ArmEncoder::new_thumb2();
8998 let op = ArmOp::I64Const {
8999 rdlo: Reg::R0,
9000 rdhi: Reg::R1,
9001 value: -1, };
9003 let code = encoder.encode(&op).unwrap();
9004 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
9006 }
9007
9008 #[test]
9013 fn test_encode_ldrb_arm32() {
9014 let encoder = ArmEncoder::new_arm32();
9015 let op = ArmOp::Ldrb {
9016 rd: Reg::R0,
9017 addr: MemAddr::imm(Reg::R1, 4),
9018 };
9019 let code = encoder.encode(&op).unwrap();
9020 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
9021 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9023 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
9024 }
9025
9026 #[test]
9027 fn test_encode_strb_arm32() {
9028 let encoder = ArmEncoder::new_arm32();
9029 let op = ArmOp::Strb {
9030 rd: Reg::R0,
9031 addr: MemAddr::imm(Reg::R1, 0),
9032 };
9033 let code = encoder.encode(&op).unwrap();
9034 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
9035 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9037 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
9038 }
9039
9040 #[test]
9041 fn test_encode_ldrh_arm32() {
9042 let encoder = ArmEncoder::new_arm32();
9043 let op = ArmOp::Ldrh {
9044 rd: Reg::R0,
9045 addr: MemAddr::imm(Reg::R1, 2),
9046 };
9047 let code = encoder.encode(&op).unwrap();
9048 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
9049 }
9050
9051 #[test]
9052 fn test_encode_strh_arm32() {
9053 let encoder = ArmEncoder::new_arm32();
9054 let op = ArmOp::Strh {
9055 rd: Reg::R0,
9056 addr: MemAddr::imm(Reg::R1, 0),
9057 };
9058 let code = encoder.encode(&op).unwrap();
9059 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
9060 }
9061
9062 #[test]
9063 fn test_encode_ldrsb_arm32() {
9064 let encoder = ArmEncoder::new_arm32();
9065 let op = ArmOp::Ldrsb {
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, "ARM32 LDRSB should be 4 bytes");
9071 }
9072
9073 #[test]
9074 fn test_encode_ldrsh_arm32() {
9075 let encoder = ArmEncoder::new_arm32();
9076 let op = ArmOp::Ldrsh {
9077 rd: Reg::R0,
9078 addr: MemAddr::imm(Reg::R1, 0),
9079 };
9080 let code = encoder.encode(&op).unwrap();
9081 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
9082 }
9083
9084 #[test]
9085 fn test_encode_ldrb_thumb2_16bit() {
9086 let encoder = ArmEncoder::new_thumb2();
9087 let op = ArmOp::Ldrb {
9088 rd: Reg::R0,
9089 addr: MemAddr::imm(Reg::R1, 4),
9090 };
9091 let code = encoder.encode(&op).unwrap();
9092 assert_eq!(
9094 code.len(),
9095 2,
9096 "Thumb-2 LDRB with small offset should be 16-bit"
9097 );
9098 }
9099
9100 #[test]
9101 fn test_encode_ldrb_thumb2_32bit() {
9102 let encoder = ArmEncoder::new_thumb2();
9103 let op = ArmOp::Ldrb {
9104 rd: Reg::R0,
9105 addr: MemAddr::imm(Reg::R1, 100), };
9107 let code = encoder.encode(&op).unwrap();
9108 assert_eq!(
9109 code.len(),
9110 4,
9111 "Thumb-2 LDRB with large offset should be 32-bit"
9112 );
9113 }
9114
9115 #[test]
9116 fn test_encode_strb_thumb2_16bit() {
9117 let encoder = ArmEncoder::new_thumb2();
9118 let op = ArmOp::Strb {
9119 rd: Reg::R0,
9120 addr: MemAddr::imm(Reg::R1, 10),
9121 };
9122 let code = encoder.encode(&op).unwrap();
9123 assert_eq!(
9124 code.len(),
9125 2,
9126 "Thumb-2 STRB with small offset should be 16-bit"
9127 );
9128 }
9129
9130 #[test]
9131 fn test_encode_ldrh_thumb2_16bit() {
9132 let encoder = ArmEncoder::new_thumb2();
9133 let op = ArmOp::Ldrh {
9134 rd: Reg::R0,
9135 addr: MemAddr::imm(Reg::R1, 4), };
9137 let code = encoder.encode(&op).unwrap();
9138 assert_eq!(
9139 code.len(),
9140 2,
9141 "Thumb-2 LDRH with small aligned offset should be 16-bit"
9142 );
9143 }
9144
9145 #[test]
9146 fn test_encode_strh_thumb2_16bit() {
9147 let encoder = ArmEncoder::new_thumb2();
9148 let op = ArmOp::Strh {
9149 rd: Reg::R0,
9150 addr: MemAddr::imm(Reg::R1, 4),
9151 };
9152 let code = encoder.encode(&op).unwrap();
9153 assert_eq!(
9154 code.len(),
9155 2,
9156 "Thumb-2 STRH with small aligned offset should be 16-bit"
9157 );
9158 }
9159
9160 #[test]
9161 fn test_encode_ldrsb_thumb2() {
9162 let encoder = ArmEncoder::new_thumb2();
9163 let op = ArmOp::Ldrsb {
9164 rd: Reg::R0,
9165 addr: MemAddr::imm(Reg::R1, 0),
9166 };
9167 let code = encoder.encode(&op).unwrap();
9168 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
9170 }
9171
9172 #[test]
9173 fn test_encode_ldrsh_thumb2() {
9174 let encoder = ArmEncoder::new_thumb2();
9175 let op = ArmOp::Ldrsh {
9176 rd: Reg::R0,
9177 addr: MemAddr::imm(Reg::R1, 0),
9178 };
9179 let code = encoder.encode(&op).unwrap();
9180 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
9181 }
9182
9183 #[test]
9184 fn test_encode_memory_size_thumb2() {
9185 let encoder = ArmEncoder::new_thumb2();
9186 let op = ArmOp::MemorySize { rd: Reg::R0 };
9187 let code = encoder.encode(&op).unwrap();
9188 assert!(!code.is_empty(), "MemorySize should produce code");
9190 }
9191
9192 #[test]
9193 fn test_encode_memory_grow_thumb2() {
9194 let encoder = ArmEncoder::new_thumb2();
9195 let op = ArmOp::MemoryGrow {
9196 rd: Reg::R0,
9197 rn: Reg::R0,
9198 };
9199 let code = encoder.encode(&op).unwrap();
9200 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
9201 }
9202
9203 #[test]
9204 fn test_encode_subword_reg_offset_thumb2() {
9205 let encoder = ArmEncoder::new_thumb2();
9206
9207 let op = ArmOp::Ldrb {
9209 rd: Reg::R0,
9210 addr: MemAddr::reg(Reg::R1, Reg::R2),
9211 };
9212 let code = encoder.encode(&op).unwrap();
9213 assert_eq!(
9214 code.len(),
9215 4,
9216 "Thumb-2 LDRB with reg offset should be 32-bit"
9217 );
9218
9219 let op = ArmOp::Strb {
9221 rd: Reg::R0,
9222 addr: MemAddr::reg(Reg::R1, Reg::R2),
9223 };
9224 let code = encoder.encode(&op).unwrap();
9225 assert_eq!(
9226 code.len(),
9227 4,
9228 "Thumb-2 STRB with reg offset should be 32-bit"
9229 );
9230
9231 let op = ArmOp::Ldrh {
9233 rd: Reg::R0,
9234 addr: MemAddr::reg(Reg::R1, Reg::R2),
9235 };
9236 let code = encoder.encode(&op).unwrap();
9237 assert_eq!(
9238 code.len(),
9239 4,
9240 "Thumb-2 LDRH with reg offset should be 32-bit"
9241 );
9242
9243 let op = ArmOp::Strh {
9245 rd: Reg::R0,
9246 addr: MemAddr::reg(Reg::R1, Reg::R2),
9247 };
9248 let code = encoder.encode(&op).unwrap();
9249 assert_eq!(
9250 code.len(),
9251 4,
9252 "Thumb-2 STRH with reg offset should be 32-bit"
9253 );
9254 }
9255
9256 #[test]
9257 fn test_encode_subword_reg_imm_offset_thumb2() {
9258 let encoder = ArmEncoder::new_thumb2();
9259
9260 let op = ArmOp::Ldrb {
9262 rd: Reg::R0,
9263 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
9264 };
9265 let code = encoder.encode(&op).unwrap();
9266 assert_eq!(
9268 code.len(),
9269 8,
9270 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
9271 );
9272 }
9273
9274 #[test]
9279 fn test_encode_mve_addi32_thumb2() {
9280 let encoder = ArmEncoder::new_thumb2();
9281 let op = ArmOp::MveAddI {
9282 qd: QReg::Q0,
9283 qn: QReg::Q1,
9284 qm: QReg::Q2,
9285 size: MveSize::S32,
9286 };
9287 let code = encoder.encode(&op).unwrap();
9288 assert_eq!(
9289 code.len(),
9290 4,
9291 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
9292 );
9293 }
9294
9295 #[test]
9296 fn test_encode_mve_subi16_thumb2() {
9297 let encoder = ArmEncoder::new_thumb2();
9298 let op = ArmOp::MveSubI {
9299 qd: QReg::Q0,
9300 qn: QReg::Q1,
9301 qm: QReg::Q2,
9302 size: MveSize::S16,
9303 };
9304 let code = encoder.encode(&op).unwrap();
9305 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
9306 }
9307
9308 #[test]
9309 fn test_encode_mve_muli8_thumb2() {
9310 let encoder = ArmEncoder::new_thumb2();
9311 let op = ArmOp::MveMulI {
9312 qd: QReg::Q0,
9313 qn: QReg::Q1,
9314 qm: QReg::Q2,
9315 size: MveSize::S8,
9316 };
9317 let code = encoder.encode(&op).unwrap();
9318 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
9319 }
9320
9321 #[test]
9322 fn test_encode_mve_bitwise_thumb2() {
9323 let encoder = ArmEncoder::new_thumb2();
9324
9325 let ops = vec![
9326 ArmOp::MveAnd {
9327 qd: QReg::Q0,
9328 qn: QReg::Q1,
9329 qm: QReg::Q2,
9330 },
9331 ArmOp::MveOrr {
9332 qd: QReg::Q0,
9333 qn: QReg::Q1,
9334 qm: QReg::Q2,
9335 },
9336 ArmOp::MveEor {
9337 qd: QReg::Q0,
9338 qn: QReg::Q1,
9339 qm: QReg::Q2,
9340 },
9341 ArmOp::MveBic {
9342 qd: QReg::Q0,
9343 qn: QReg::Q1,
9344 qm: QReg::Q2,
9345 },
9346 ];
9347 for op in ops {
9348 let code = encoder.encode(&op).unwrap();
9349 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
9350 }
9351 }
9352
9353 #[test]
9354 fn test_encode_mve_mvn_thumb2() {
9355 let encoder = ArmEncoder::new_thumb2();
9356 let op = ArmOp::MveMvn {
9357 qd: QReg::Q0,
9358 qm: QReg::Q1,
9359 };
9360 let code = encoder.encode(&op).unwrap();
9361 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
9362 }
9363
9364 #[test]
9365 fn test_encode_mve_load_store_thumb2() {
9366 let encoder = ArmEncoder::new_thumb2();
9367
9368 let load = ArmOp::MveLoad {
9369 qd: QReg::Q0,
9370 addr: MemAddr::imm(Reg::R0, 16),
9371 };
9372 let code = encoder.encode(&load).unwrap();
9373 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
9374
9375 let store = ArmOp::MveStore {
9376 qd: QReg::Q1,
9377 addr: MemAddr::imm(Reg::R1, 0),
9378 };
9379 let code = encoder.encode(&store).unwrap();
9380 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
9381 }
9382
9383 #[test]
9384 fn test_encode_mve_const_thumb2() {
9385 let encoder = ArmEncoder::new_thumb2();
9386 let op = ArmOp::MveConst {
9387 qd: QReg::Q0,
9388 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
9389 };
9390 let code = encoder.encode(&op).unwrap();
9391 assert!(
9394 code.len() >= 24,
9395 "MVE const should produce multiple instructions"
9396 );
9397 }
9398
9399 #[test]
9400 fn test_encode_mve_dup_thumb2() {
9401 let encoder = ArmEncoder::new_thumb2();
9402 let op = ArmOp::MveDup {
9403 qd: QReg::Q0,
9404 rn: Reg::R0,
9405 size: MveSize::S32,
9406 };
9407 let code = encoder.encode(&op).unwrap();
9408 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
9409 }
9410
9411 #[test]
9412 fn test_encode_mve_extract_lane_thumb2() {
9413 let encoder = ArmEncoder::new_thumb2();
9414 let op = ArmOp::MveExtractLane {
9415 rd: Reg::R0,
9416 qn: QReg::Q1,
9417 lane: 2,
9418 size: MveSize::S32,
9419 };
9420 let code = encoder.encode(&op).unwrap();
9421 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
9422 }
9423
9424 #[test]
9425 fn test_encode_mve_insert_lane_thumb2() {
9426 let encoder = ArmEncoder::new_thumb2();
9427 let op = ArmOp::MveInsertLane {
9428 qd: QReg::Q0,
9429 rn: Reg::R1,
9430 lane: 3,
9431 size: MveSize::S32,
9432 };
9433 let code = encoder.encode(&op).unwrap();
9434 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9435 }
9436
9437 #[test]
9438 fn test_encode_mve_addf32_thumb2() {
9439 let encoder = ArmEncoder::new_thumb2();
9440 let op = ArmOp::MveAddF32 {
9441 qd: QReg::Q0,
9442 qn: QReg::Q1,
9443 qm: QReg::Q2,
9444 };
9445 let code = encoder.encode(&op).unwrap();
9446 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9447 }
9448
9449 #[test]
9450 fn test_encode_mve_divf32_thumb2() {
9451 let encoder = ArmEncoder::new_thumb2();
9452 let op = ArmOp::MveDivF32 {
9453 qd: QReg::Q0,
9454 qn: QReg::Q1,
9455 qm: QReg::Q2,
9456 };
9457 let code = encoder.encode(&op).unwrap();
9458 assert_eq!(
9460 code.len(),
9461 16,
9462 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9463 );
9464 }
9465
9466 #[test]
9467 fn test_encode_mve_sqrtf32_thumb2() {
9468 let encoder = ArmEncoder::new_thumb2();
9469 let op = ArmOp::MveSqrtF32 {
9470 qd: QReg::Q0,
9471 qm: QReg::Q1,
9472 };
9473 let code = encoder.encode(&op).unwrap();
9474 assert_eq!(
9476 code.len(),
9477 16,
9478 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9479 );
9480 }
9481
9482 #[test]
9483 fn test_encode_mve_negf32_thumb2() {
9484 let encoder = ArmEncoder::new_thumb2();
9485 let op = ArmOp::MveNegF32 {
9486 qd: QReg::Q0,
9487 qm: QReg::Q1,
9488 };
9489 let code = encoder.encode(&op).unwrap();
9490 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9491 }
9492
9493 #[test]
9494 fn test_encode_mve_absf32_thumb2() {
9495 let encoder = ArmEncoder::new_thumb2();
9496 let op = ArmOp::MveAbsF32 {
9497 qd: QReg::Q0,
9498 qm: QReg::Q1,
9499 };
9500 let code = encoder.encode(&op).unwrap();
9501 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9502 }
9503
9504 #[test]
9519 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9520 let encoder = ArmEncoder::new_thumb2();
9521 let op = ArmOp::And {
9522 rd: Reg::R2,
9523 rn: Reg::R0,
9524 op2: Operand2::Imm(0x7e),
9525 };
9526 let code = encoder.encode(&op).unwrap();
9527 assert_eq!(
9528 code,
9529 vec![0x00, 0xf0, 0x7e, 0x02],
9530 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9531 );
9532 }
9533
9534 #[test]
9541 fn try_thumb_expand_imm_encodes_modified_immediates() {
9542 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9544 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);
9552 assert_eq!(try_thumb_expand_imm(0x12345), None);
9553 }
9554
9555 #[test]
9560 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9561 let encoder = ArmEncoder::new_thumb2();
9562 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9564 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9565 assert!(
9567 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9568 "cmp #0x101 must error, not compare the wrong constant"
9569 );
9570 assert!(
9571 encoder
9572 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9573 .is_err()
9574 );
9575 assert!(
9576 encoder
9577 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9578 .is_err()
9579 );
9580 assert!(
9582 encoder
9583 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9584 .is_ok()
9585 );
9586 }
9587
9588 #[test]
9591 fn mla_thumb2_encodes_correctly() {
9592 let encoder = ArmEncoder::new_thumb2();
9593 let code = encoder
9594 .encode(&ArmOp::Mla {
9595 rd: Reg::R2,
9596 rn: Reg::R3,
9597 rm: Reg::R4,
9598 ra: Reg::R8,
9599 })
9600 .unwrap();
9601 assert_eq!(code, vec![0x03, 0xfb, 0x04, 0x82]);
9603 }
9604
9605 #[test]
9610 fn ldst_imm12_offset_errors_when_out_of_range() {
9611 let encoder = ArmEncoder::new_thumb2();
9612 assert!(
9614 encoder
9615 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0xFFF)
9616 .is_ok()
9617 );
9618 assert!(
9620 encoder
9621 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0x1000)
9622 .is_err(),
9623 "ldr offset 4096 must error, not wrap to 0"
9624 );
9625 assert!(
9626 encoder
9627 .encode_thumb32_str(&Reg::R0, &Reg::R1, 0x1000)
9628 .is_err()
9629 );
9630 assert!(
9631 encoder
9632 .encode_thumb32_ldrb_imm(&Reg::R0, &Reg::R1, 5000)
9633 .is_err()
9634 );
9635 assert!(
9636 encoder
9637 .encode_thumb32_strh_imm(&Reg::R0, &Reg::R1, 5000)
9638 .is_err()
9639 );
9640 }
9641
9642 #[test]
9649 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9650 let encoder = ArmEncoder::new_thumb2();
9651 assert_eq!(
9653 encoder
9654 .encode(&ArmOp::Add {
9655 rd: Reg::SP,
9656 rn: Reg::SP,
9657 op2: Operand2::Imm(256),
9658 })
9659 .unwrap(),
9660 vec![0x0d, 0xf2, 0x00, 0x1d],
9661 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9662 );
9663 assert_eq!(
9665 encoder
9666 .encode(&ArmOp::Sub {
9667 rd: Reg::SP,
9668 rn: Reg::SP,
9669 op2: Operand2::Imm(256),
9670 })
9671 .unwrap(),
9672 vec![0xad, 0xf2, 0x00, 0x1d],
9673 );
9674 assert!(
9676 encoder
9677 .encode(&ArmOp::Add {
9678 rd: Reg::SP,
9679 rn: Reg::SP,
9680 op2: Operand2::Imm(5000),
9681 })
9682 .is_err(),
9683 "add #5000 must error (no single ADDW), not mis-encode"
9684 );
9685 }
9686
9687 #[test]
9692 fn and_cmn_immediate_thumb_expand_else_error() {
9693 let encoder = ArmEncoder::new_thumb2();
9694 assert_eq!(
9696 encoder
9697 .encode(&ArmOp::And {
9698 rd: Reg::R2,
9699 rn: Reg::R0,
9700 op2: Operand2::Imm(0x7e),
9701 })
9702 .unwrap(),
9703 vec![0x00, 0xf0, 0x7e, 0x02],
9704 );
9705 assert!(
9707 encoder
9708 .encode(&ArmOp::And {
9709 rd: Reg::R2,
9710 rn: Reg::R0,
9711 op2: Operand2::Imm(0xff00ff00u32 as i32),
9712 })
9713 .is_ok()
9714 );
9715 assert!(
9717 encoder
9718 .encode(&ArmOp::And {
9719 rd: Reg::R2,
9720 rn: Reg::R0,
9721 op2: Operand2::Imm(0x101),
9722 })
9723 .is_err()
9724 );
9725 assert!(
9726 encoder
9727 .encode(&ArmOp::Cmn {
9728 rn: Reg::R0,
9729 op2: Operand2::Imm(0x101),
9730 })
9731 .is_err(),
9732 "CMN #0x101 must error, not emit a NOP"
9733 );
9734 }
9735
9736 #[test]
9740 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9741 let encoder = ArmEncoder::new_thumb2();
9742 assert_eq!(
9744 encoder
9745 .encode(&ArmOp::Orr {
9746 rd: Reg::R2,
9747 rn: Reg::R0,
9748 op2: Operand2::Imm(0x7e),
9749 })
9750 .unwrap(),
9751 vec![0x40, 0xf0, 0x7e, 0x02],
9752 );
9753 assert_eq!(
9755 encoder
9756 .encode(&ArmOp::Eor {
9757 rd: Reg::R2,
9758 rn: Reg::R0,
9759 op2: Operand2::Imm(0x7e),
9760 })
9761 .unwrap(),
9762 vec![0x80, 0xf0, 0x7e, 0x02],
9763 );
9764 assert!(
9766 encoder
9767 .encode(&ArmOp::Orr {
9768 rd: Reg::R2,
9769 rn: Reg::R0,
9770 op2: Operand2::Imm(0x140),
9771 })
9772 .is_err(),
9773 "ORR #0x140 must error, not emit a NOP"
9774 );
9775 }
9776
9777 #[test]
9778 fn test_encode_mve_different_qregs() {
9779 let encoder = ArmEncoder::new_thumb2();
9780
9781 let op1 = ArmOp::MveAddI {
9783 qd: QReg::Q0,
9784 qn: QReg::Q0,
9785 qm: QReg::Q0,
9786 size: MveSize::S32,
9787 };
9788 let op2 = ArmOp::MveAddI {
9789 qd: QReg::Q3,
9790 qn: QReg::Q5,
9791 qm: QReg::Q7,
9792 size: MveSize::S32,
9793 };
9794 let code1 = encoder.encode(&op1).unwrap();
9795 let code2 = encoder.encode(&op2).unwrap();
9796 assert_ne!(
9797 code1, code2,
9798 "Different Q-registers should produce different encodings"
9799 );
9800 }
9801
9802 #[test]
9803 fn test_encode_mve_arm32_nop() {
9804 let encoder = ArmEncoder::new_arm32();
9806 let op = ArmOp::MveAddI {
9807 qd: QReg::Q0,
9808 qn: QReg::Q1,
9809 qm: QReg::Q2,
9810 size: MveSize::S32,
9811 };
9812 let code = encoder.encode(&op).unwrap();
9813 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9814 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9816 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9817 }
9818}