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::Uxtb { rd, rm } => {
395 let rd_bits = reg_to_bits(rd);
396 let rm_bits = reg_to_bits(rm);
397 0xE6EF0070 | (rd_bits << 12) | rm_bits
399 }
400
401 ArmOp::Uxth { rd, rm } => {
402 let rd_bits = reg_to_bits(rd);
403 let rm_bits = reg_to_bits(rm);
404 0xE6FF0070 | (rd_bits << 12) | rm_bits
406 }
407
408 ArmOp::Mov { rd, op2 } => {
410 let rd_bits = reg_to_bits(rd);
411 let (op2_bits, i_flag) = encode_operand2(op2)?;
412
413 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
415 }
416
417 ArmOp::Mvn { rd, op2 } => {
418 let rd_bits = reg_to_bits(rd);
419 let (op2_bits, i_flag) = encode_operand2(op2)?;
420
421 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
423 }
424
425 ArmOp::Movw { rd, imm16 } => {
428 let rd_bits = reg_to_bits(rd);
429 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
430 let imm12 = (*imm16 as u32) & 0xFFF;
431 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
432 }
433
434 ArmOp::Movt { rd, imm16 } => {
437 let rd_bits = reg_to_bits(rd);
438 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
439 let imm12 = (*imm16 as u32) & 0xFFF;
440 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
441 }
442
443 ArmOp::MovwSym { rd, addend, .. } => {
446 let rd_bits = reg_to_bits(rd);
447 let v = (*addend as u32) & 0xffff;
448 0xE3000000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
449 }
450 ArmOp::MovtSym { rd, addend, .. } => {
451 let rd_bits = reg_to_bits(rd);
452 let v = ((*addend as u32) >> 16) & 0xffff;
453 0xE3400000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
454 }
455
456 ArmOp::LdrSym { .. } => {
460 return Err(synth_core::Error::synthesis(
461 "LdrSym (literal-pool address load) is Thumb-2-only",
462 ));
463 }
464
465 ArmOp::Cmp { rn, op2 } => {
467 let rn_bits = reg_to_bits(rn);
468 let (op2_bits, i_flag) = encode_operand2(op2)?;
469
470 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
472 }
473
474 ArmOp::Cmn { rn, op2 } => {
476 let rn_bits = reg_to_bits(rn);
477 let (op2_bits, i_flag) = encode_operand2(op2)?;
478
479 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
481 }
482
483 ArmOp::Ldr { rd, addr } => {
485 let rd_bits = reg_to_bits(rd);
486 let (base_bits, offset_bits) = encode_mem_addr(addr);
487
488 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
491 }
492
493 ArmOp::Str { rd, addr } => {
494 let rd_bits = reg_to_bits(rd);
495 let (base_bits, offset_bits) = encode_mem_addr(addr);
496
497 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
499 }
500
501 ArmOp::Ldrb { rd, addr } => {
503 let rd_bits = reg_to_bits(rd);
504 let (base_bits, offset_bits) = encode_mem_addr(addr);
505 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
507 }
508
509 ArmOp::Ldrsb { rd, addr } => {
510 let rd_bits = reg_to_bits(rd);
511 let (base_bits, offset_bits) = encode_mem_addr(addr);
512 let offset_val = offset_bits & 0xFF;
515 let imm4h = (offset_val >> 4) & 0xF;
516 let imm4l = offset_val & 0xF;
517 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
518 }
519
520 ArmOp::Ldrh { rd, addr } => {
521 let rd_bits = reg_to_bits(rd);
522 let (base_bits, offset_bits) = encode_mem_addr(addr);
523 let offset_val = offset_bits & 0xFF;
525 let imm4h = (offset_val >> 4) & 0xF;
526 let imm4l = offset_val & 0xF;
527 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
528 }
529
530 ArmOp::Ldrsh { rd, addr } => {
531 let rd_bits = reg_to_bits(rd);
532 let (base_bits, offset_bits) = encode_mem_addr(addr);
533 let offset_val = offset_bits & 0xFF;
535 let imm4h = (offset_val >> 4) & 0xF;
536 let imm4l = offset_val & 0xF;
537 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
538 }
539
540 ArmOp::Strb { rd, addr } => {
542 let rd_bits = reg_to_bits(rd);
543 let (base_bits, offset_bits) = encode_mem_addr(addr);
544 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
546 }
547
548 ArmOp::Strh { rd, addr } => {
549 let rd_bits = reg_to_bits(rd);
550 let (base_bits, offset_bits) = encode_mem_addr(addr);
551 let offset_val = offset_bits & 0xFF;
553 let imm4h = (offset_val >> 4) & 0xF;
554 let imm4l = offset_val & 0xF;
555 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
556 }
557
558 ArmOp::MemorySize { rd } => {
560 let rd_bits = reg_to_bits(rd);
561 0xE1A00820 | (rd_bits << 12) | 0x0A }
566
567 ArmOp::MemoryGrow { rd, .. } => {
568 let rd_bits = reg_to_bits(rd);
569 0xE3E00000 | (rd_bits << 12) }
572
573 ArmOp::Label { .. } => {
575 return Ok(Vec::new());
576 }
577
578 ArmOp::B { label: _ } => {
580 0xEA000000
583 }
584
585 ArmOp::Bcc { cond, label: _ } => {
587 use synth_synthesis::Condition;
588 let cond_bits: u32 = match cond {
589 Condition::EQ => 0x0,
590 Condition::NE => 0x1,
591 Condition::HS => 0x2,
592 Condition::LO => 0x3,
593 Condition::HI => 0x8,
594 Condition::LS => 0x9,
595 Condition::GE => 0xA,
596 Condition::LT => 0xB,
597 Condition::GT => 0xC,
598 Condition::LE => 0xD,
599 };
600 (cond_bits << 28) | 0x0A000000
602 }
603
604 ArmOp::Bhs { label: _ } => {
606 0x2A000000 }
609
610 ArmOp::Blo { label: _ } => {
612 0x3A000000 }
615
616 ArmOp::BOffset { offset } => {
620 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
630 0xEA000000 | offset_bits
631 }
632
633 ArmOp::BCondOffset { cond, offset } => {
635 use synth_synthesis::Condition;
636 let cond_bits: u32 = match cond {
637 Condition::EQ => 0x0,
638 Condition::NE => 0x1,
639 Condition::HS => 0x2,
640 Condition::LO => 0x3,
641 Condition::HI => 0x8,
642 Condition::LS => 0x9,
643 Condition::GE => 0xA,
644 Condition::LT => 0xB,
645 Condition::GT => 0xC,
646 Condition::LE => 0xD,
647 };
648 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
652 (cond_bits << 28) | 0x0A000000 | offset_bits
653 }
654
655 ArmOp::Bl { label: _ } => {
656 0xEB000000
658 }
659
660 ArmOp::Bx { rm } => {
661 let rm_bits = reg_to_bits(rm);
662
663 0xE12FFF10 | rm_bits
665 }
666
667 ArmOp::Blx { rm } => {
668 let rm_bits = reg_to_bits(rm);
669
670 0xE12FFF30 | rm_bits
672 }
673
674 ArmOp::Push { regs } => {
675 let mut reg_list: u32 = 0;
677 for r in regs {
678 reg_list |= 1 << reg_to_bits(r);
679 }
680 0xE92D0000 | reg_list
681 }
682
683 ArmOp::Pop { regs } => {
684 let mut reg_list: u32 = 0;
686 for r in regs {
687 reg_list |= 1 << reg_to_bits(r);
688 }
689 0xE8BD0000 | reg_list
690 }
691
692 ArmOp::Nop => {
693 0xE1A00000
695 }
696
697 ArmOp::Udf { imm } => {
698 let imm8 = *imm as u32;
701 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
702 }
703
704 ArmOp::Popcnt { .. } => {
707 0xE1A00000 }
711
712 ArmOp::SetCond { .. } => {
713 0xE1A00000 }
717
718 ArmOp::SelectMove { .. } => {
719 0xE1A00000 }
723
724 ArmOp::Select { .. } => {
725 0xE1A00000 }
729
730 ArmOp::LocalGet { .. } => {
731 0xE1A00000 }
735
736 ArmOp::LocalSet { .. } => {
737 0xE1A00000 }
741
742 ArmOp::LocalTee { .. } => {
743 0xE1A00000 }
747
748 ArmOp::GlobalGet { .. } => {
749 0xE1A00000 }
753
754 ArmOp::GlobalSet { .. } => {
755 0xE1A00000 }
759
760 ArmOp::BrTable { .. } => {
761 0xE1A00000 }
765
766 ArmOp::Call { .. } => {
767 0xE1A00000 }
771
772 ArmOp::CallIndirect { .. } => {
773 0xE1A00000 }
777
778 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)?,
815 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
816 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
817 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
818 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
819 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
820 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
821
822 ArmOp::F32Ceil { sd, sm } => {
825 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
827 ArmOp::F32Floor { sd, sm } => {
828 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
830 ArmOp::F32Trunc { sd, sm } => {
831 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
833 ArmOp::F32Nearest { sd, sm } => {
834 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
836 ArmOp::F32Min { sd, sn, sm } => {
837 return self.encode_arm_f32_minmax(sd, sn, sm, true);
838 }
839 ArmOp::F32Max { sd, sn, sm } => {
840 return self.encode_arm_f32_minmax(sd, sn, sm, false);
841 }
842 ArmOp::F32Copysign { sd, sn, sm } => {
843 return self.encode_arm_f32_copysign(sd, sn, sm);
844 }
845
846 ArmOp::F32Eq { rd, sn, sm } => {
848 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
850 ArmOp::F32Ne { rd, sn, sm } => {
851 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
853 ArmOp::F32Lt { rd, sn, sm } => {
854 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
856 ArmOp::F32Le { rd, sn, sm } => {
857 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
859 ArmOp::F32Gt { rd, sn, sm } => {
860 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
862 ArmOp::F32Ge { rd, sn, sm } => {
863 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
865
866 ArmOp::F32Const { sd, value } => {
868 return self.encode_arm_f32_const(sd, *value);
869 }
870
871 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
872 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
873
874 ArmOp::F32ConvertI32S { sd, rm } => {
876 return self.encode_arm_f32_convert_i32(sd, rm, true);
877 }
878 ArmOp::F32ConvertI32U { sd, rm } => {
879 return self.encode_arm_f32_convert_i32(sd, rm, false);
880 }
881 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
882 return Err(synth_core::Error::synthesis(
883 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
884 ));
885 }
886 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
887 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
888 ArmOp::I32TruncF32S { rd, sm } => {
889 return self.encode_arm_i32_trunc_f32(rd, sm, true);
890 }
891 ArmOp::I32TruncF32U { rd, sm } => {
892 return self.encode_arm_i32_trunc_f32(rd, sm, false);
893 }
894
895 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
898 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
899 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
900 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
901 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
902 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
903 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
904
905 ArmOp::F64Ceil { dd, dm } => {
908 return self.encode_arm_f64_rounding(dd, dm, 0b01);
909 }
910 ArmOp::F64Floor { dd, dm } => {
911 return self.encode_arm_f64_rounding(dd, dm, 0b10);
912 }
913 ArmOp::F64Trunc { dd, dm } => {
914 return self.encode_arm_f64_rounding(dd, dm, 0b11);
915 }
916 ArmOp::F64Nearest { dd, dm } => {
917 return self.encode_arm_f64_rounding(dd, dm, 0b00);
918 }
919 ArmOp::F64Min { dd, dn, dm } => {
920 return self.encode_arm_f64_minmax(dd, dn, dm, true);
921 }
922 ArmOp::F64Max { dd, dn, dm } => {
923 return self.encode_arm_f64_minmax(dd, dn, dm, false);
924 }
925 ArmOp::F64Copysign { dd, dn, dm } => {
926 return self.encode_arm_f64_copysign(dd, dn, dm);
927 }
928
929 ArmOp::F64Eq { rd, dn, dm } => {
931 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
932 }
933 ArmOp::F64Ne { rd, dn, dm } => {
934 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
935 }
936 ArmOp::F64Lt { rd, dn, dm } => {
937 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
938 }
939 ArmOp::F64Le { rd, dn, dm } => {
940 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
941 }
942 ArmOp::F64Gt { rd, dn, dm } => {
943 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
944 }
945 ArmOp::F64Ge { rd, dn, dm } => {
946 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
947 }
948
949 ArmOp::F64Const { dd, value } => {
950 return self.encode_arm_f64_const(dd, *value);
951 }
952
953 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
954 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
955
956 ArmOp::F64ConvertI32S { dd, rm } => {
957 return self.encode_arm_f64_convert_i32(dd, rm, true);
958 }
959 ArmOp::F64ConvertI32U { dd, rm } => {
960 return self.encode_arm_f64_convert_i32(dd, rm, false);
961 }
962 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
963 return Err(synth_core::Error::synthesis(
964 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
965 ));
966 }
967 ArmOp::F64PromoteF32 { dd, sm } => {
968 return self.encode_arm_f64_promote_f32(dd, sm);
969 }
970 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
971 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
972 }
973 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
974 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
975 }
976 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
977 return Err(synth_core::Error::synthesis(
978 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
979 ));
980 }
981 ArmOp::I32TruncF64S { rd, dm } => {
982 return self.encode_arm_i32_trunc_f64(rd, dm, true);
983 }
984 ArmOp::I32TruncF64U { rd, dm } => {
985 return self.encode_arm_i32_trunc_f64(rd, dm, false);
986 }
987 ArmOp::I64SetCond { .. }
989 | ArmOp::I64SetCondZ { .. }
990 | ArmOp::I64Mul { .. }
991 | ArmOp::I64Shl { .. }
992 | ArmOp::I64ShrS { .. }
993 | ArmOp::I64ShrU { .. }
994 | ArmOp::I64Rotl { .. }
995 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
999 | ArmOp::MveStore { .. }
1000 | ArmOp::MveConst { .. }
1001 | ArmOp::MveAnd { .. }
1002 | ArmOp::MveOrr { .. }
1003 | ArmOp::MveEor { .. }
1004 | ArmOp::MveMvn { .. }
1005 | ArmOp::MveBic { .. }
1006 | ArmOp::MveAddI { .. }
1007 | ArmOp::MveSubI { .. }
1008 | ArmOp::MveMulI { .. }
1009 | ArmOp::MveNegI { .. }
1010 | ArmOp::MveCmpEqI { .. }
1011 | ArmOp::MveCmpNeI { .. }
1012 | ArmOp::MveCmpLtS { .. }
1013 | ArmOp::MveCmpLtU { .. }
1014 | ArmOp::MveCmpGtS { .. }
1015 | ArmOp::MveCmpGtU { .. }
1016 | ArmOp::MveCmpLeS { .. }
1017 | ArmOp::MveCmpLeU { .. }
1018 | ArmOp::MveCmpGeS { .. }
1019 | ArmOp::MveCmpGeU { .. }
1020 | ArmOp::MveDup { .. }
1021 | ArmOp::MveExtractLane { .. }
1022 | ArmOp::MveInsertLane { .. }
1023 | ArmOp::MveAddF32 { .. }
1024 | ArmOp::MveSubF32 { .. }
1025 | ArmOp::MveMulF32 { .. }
1026 | ArmOp::MveNegF32 { .. }
1027 | ArmOp::MveAbsF32 { .. }
1028 | ArmOp::MveCmpEqF32 { .. }
1029 | ArmOp::MveCmpNeF32 { .. }
1030 | ArmOp::MveCmpLtF32 { .. }
1031 | ArmOp::MveCmpLeF32 { .. }
1032 | ArmOp::MveCmpGtF32 { .. }
1033 | ArmOp::MveCmpGeF32 { .. }
1034 | ArmOp::MveDupF32 { .. }
1035 | ArmOp::MveExtractLaneF32 { .. }
1036 | ArmOp::MveReplaceLaneF32 { .. }
1037 | ArmOp::MveDivF32 { .. }
1038 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
1040
1041 Ok(instr.to_le_bytes().to_vec())
1043 }
1044
1045 fn encode_arm_f32_compare(
1049 &self,
1050 rd: &Reg,
1051 sn: &VfpReg,
1052 sm: &VfpReg,
1053 cond_code: u32,
1054 ) -> Result<Vec<u8>> {
1055 let mut bytes = Vec::new();
1056
1057 let sn_num = vfp_sreg_to_num(sn)?;
1059 let sm_num = vfp_sreg_to_num(sm)?;
1060 let (vd, d) = encode_sreg(sn_num);
1061 let (vm, m) = encode_sreg(sm_num);
1062 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1063 bytes.extend_from_slice(&vcmp.to_le_bytes());
1064
1065 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1067
1068 let rd_bits = reg_to_bits(rd);
1070 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1071 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1072
1073 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1075 bytes.extend_from_slice(&mov_one.to_le_bytes());
1076
1077 Ok(bytes)
1078 }
1079
1080 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1082 let mut bytes = Vec::new();
1083 let bits = value.to_bits();
1084
1085 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1090 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1091 bytes.extend_from_slice(&movw.to_le_bytes());
1092
1093 let hi16 = (bits >> 16) & 0xFFFF;
1095 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1096 bytes.extend_from_slice(&movt.to_le_bytes());
1097
1098 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1100 bytes.extend_from_slice(&vmov.to_le_bytes());
1101
1102 Ok(bytes)
1103 }
1104
1105 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1107 let mut bytes = Vec::new();
1108
1109 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1111 bytes.extend_from_slice(&vmov.to_le_bytes());
1112
1113 let sd_num = vfp_sreg_to_num(sd)?;
1116 let (vd, d) = encode_sreg(sd_num);
1117 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1119 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1120 bytes.extend_from_slice(&vcvt.to_le_bytes());
1121
1122 Ok(bytes)
1123 }
1124
1125 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1137 let mut bytes = Vec::new();
1138 let sm_num = vfp_sreg_to_num(sm)?;
1139 let sd_num = vfp_sreg_to_num(sd)?;
1140 let (vd_s, d_s) = encode_sreg(sd_num);
1141 let (vm_s, m_s) = encode_sreg(sm_num);
1142
1143 if mode == 0b11 {
1144 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1147 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1148 } else {
1149 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1154 bytes.extend_from_slice(&vmrs.to_le_bytes());
1155
1156 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1159 bytes.extend_from_slice(&bic.to_le_bytes());
1160
1161 if mode != 0 {
1163 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1165 bytes.extend_from_slice(&orr.to_le_bytes());
1166 }
1167
1168 let vmsr = 0xEEE10A10 | (rt << 12);
1170 bytes.extend_from_slice(&vmsr.to_le_bytes());
1171
1172 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1174 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1175
1176 bytes.extend_from_slice(&vmrs.to_le_bytes());
1178 bytes.extend_from_slice(&bic.to_le_bytes());
1179 bytes.extend_from_slice(&vmsr.to_le_bytes());
1180 }
1181
1182 let (vd2, d2) = encode_sreg(sd_num);
1184 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1185 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1186
1187 Ok(bytes)
1188 }
1189
1190 fn encode_arm_f32_minmax(
1192 &self,
1193 sd: &VfpReg,
1194 sn: &VfpReg,
1195 sm: &VfpReg,
1196 is_min: bool,
1197 ) -> Result<Vec<u8>> {
1198 let mut bytes = Vec::new();
1199 let sn_num = vfp_sreg_to_num(sn)?;
1200 let sm_num = vfp_sreg_to_num(sm)?;
1201 let sd_num = vfp_sreg_to_num(sd)?;
1202
1203 let (vd, d) = encode_sreg(sd_num);
1205 let (vn, n) = encode_sreg(sn_num);
1206 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1207 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1208
1209 let (vm, m) = encode_sreg(sm_num);
1211 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1212 bytes.extend_from_slice(&vcmp.to_le_bytes());
1213
1214 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1216
1217 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1220
1221 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1223 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1224
1225 Ok(bytes)
1226 }
1227
1228 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1230 let mut bytes = Vec::new();
1231
1232 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1234 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1235
1236 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1238 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1239
1240 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1244 bytes.extend_from_slice(&and_sign.to_le_bytes());
1245
1246 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1249 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1250
1251 let orr = 0xE1800000u32 | 12;
1254 bytes.extend_from_slice(&orr.to_le_bytes());
1255
1256 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1258 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1259
1260 Ok(bytes)
1261 }
1262
1263 fn encode_arm_f64_compare(
1265 &self,
1266 rd: &Reg,
1267 dn: &VfpReg,
1268 dm: &VfpReg,
1269 cond_code: u32,
1270 ) -> Result<Vec<u8>> {
1271 let mut bytes = Vec::new();
1272
1273 let dn_num = vfp_dreg_to_num(dn)?;
1275 let dm_num = vfp_dreg_to_num(dm)?;
1276 let (vd, d) = encode_dreg(dn_num);
1277 let (vm, m) = encode_dreg(dm_num);
1278 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1279 bytes.extend_from_slice(&vcmp.to_le_bytes());
1280
1281 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1283
1284 let rd_bits = reg_to_bits(rd);
1286 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1287 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1288
1289 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1291 bytes.extend_from_slice(&mov_one.to_le_bytes());
1292
1293 Ok(bytes)
1294 }
1295
1296 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1298 let mut bytes = Vec::new();
1299 let bits = value.to_bits();
1300 let lo32 = bits as u32;
1301 let hi32 = (bits >> 32) as u32;
1302
1303 let lo16 = lo32 & 0xFFFF;
1305 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1306 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1307 let hi16 = (lo32 >> 16) & 0xFFFF;
1308 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1309 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1310
1311 let lo16 = hi32 & 0xFFFF;
1313 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1314 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1315 let hi16 = (hi32 >> 16) & 0xFFFF;
1316 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1317 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1318
1319 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1321 bytes.extend_from_slice(&vmov.to_le_bytes());
1322
1323 Ok(bytes)
1324 }
1325
1326 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1328 let mut bytes = Vec::new();
1329
1330 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1332 bytes.extend_from_slice(&vmov.to_le_bytes());
1333
1334 let dd_num = vfp_dreg_to_num(dd)?;
1337 let (vd, d) = encode_dreg(dd_num);
1338 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1339 let vcvt = base | (d << 22) | (vd << 12);
1341 bytes.extend_from_slice(&vcvt.to_le_bytes());
1342
1343 Ok(bytes)
1344 }
1345
1346 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1348 let dd_num = vfp_dreg_to_num(dd)?;
1349 let sm_num = vfp_sreg_to_num(sm)?;
1350 let (vd, d) = encode_dreg(dd_num);
1351 let (vm, m) = encode_sreg(sm_num);
1352
1353 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1355 Ok(vcvt.to_le_bytes().to_vec())
1356 }
1357
1358 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1360 let mut bytes = Vec::new();
1361 let dm_num = vfp_dreg_to_num(dm)?;
1362 let (vm, m) = encode_dreg(dm_num);
1363
1364 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1367 let vcvt = base | (m << 5) | vm;
1368 bytes.extend_from_slice(&vcvt.to_le_bytes());
1369
1370 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1372 bytes.extend_from_slice(&vmov.to_le_bytes());
1373
1374 Ok(bytes)
1375 }
1376
1377 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1385 let mut bytes = Vec::new();
1386 let dm_num = vfp_dreg_to_num(dm)?;
1387 let dd_num = vfp_dreg_to_num(dd)?;
1388 let (vm, m) = encode_dreg(dm_num);
1389 let (vd, d) = encode_dreg(dd_num);
1390
1391 if mode == 0b11 {
1392 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1394 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1395 } else {
1396 let rt: u32 = 12;
1398
1399 let vmrs = 0xEEF10A10 | (rt << 12);
1401 bytes.extend_from_slice(&vmrs.to_le_bytes());
1402
1403 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1405 bytes.extend_from_slice(&bic.to_le_bytes());
1406
1407 if mode != 0 {
1409 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1410 bytes.extend_from_slice(&orr.to_le_bytes());
1411 }
1412
1413 let vmsr = 0xEEE10A10 | (rt << 12);
1415 bytes.extend_from_slice(&vmsr.to_le_bytes());
1416
1417 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1419 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1420
1421 bytes.extend_from_slice(&vmrs.to_le_bytes());
1423 bytes.extend_from_slice(&bic.to_le_bytes());
1424 bytes.extend_from_slice(&vmsr.to_le_bytes());
1425 }
1426
1427 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1429 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1430
1431 Ok(bytes)
1432 }
1433
1434 fn encode_arm_f64_minmax(
1436 &self,
1437 dd: &VfpReg,
1438 dn: &VfpReg,
1439 dm: &VfpReg,
1440 is_min: bool,
1441 ) -> Result<Vec<u8>> {
1442 let mut bytes = Vec::new();
1443 let dn_num = vfp_dreg_to_num(dn)?;
1444 let dm_num = vfp_dreg_to_num(dm)?;
1445 let dd_num = vfp_dreg_to_num(dd)?;
1446
1447 let (vd, d) = encode_dreg(dd_num);
1449 let (vn, n) = encode_dreg(dn_num);
1450 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1451 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1452
1453 let (vm, m) = encode_dreg(dm_num);
1455 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1456 bytes.extend_from_slice(&vcmp.to_le_bytes());
1457
1458 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1460
1461 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1462 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1463 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1464
1465 Ok(bytes)
1466 }
1467
1468 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1470 let mut bytes = Vec::new();
1471
1472 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1474 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1475
1476 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1479 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1480
1481 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1483 bytes.extend_from_slice(&and_sign.to_le_bytes());
1484
1485 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1487 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1488
1489 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1491 bytes.extend_from_slice(&orr.to_le_bytes());
1492
1493 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1495 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1496
1497 Ok(bytes)
1498 }
1499
1500 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1502 let mut bytes = Vec::new();
1503
1504 let sm_num = vfp_sreg_to_num(sm)?;
1507 let (vd, d) = encode_sreg(sm_num);
1508 let (vm, m) = encode_sreg(sm_num);
1509 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1510 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1511 bytes.extend_from_slice(&vcvt.to_le_bytes());
1512
1513 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1515 bytes.extend_from_slice(&vmov.to_le_bytes());
1516
1517 Ok(bytes)
1518 }
1519
1520 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1522 match op {
1525 ArmOp::Add { rd, rn, op2 } => {
1527 let rd_bits = reg_to_bits(rd) as u16;
1528 let rn_bits = reg_to_bits(rn) as u16;
1529
1530 if let Operand2::Reg(rm) = op2 {
1531 let rm_bits = reg_to_bits(rm) as u16;
1532 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1540 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1542 Ok(instr.to_le_bytes().to_vec())
1543 } else {
1544 self.encode_thumb32_add_reg_raw(
1546 rd_bits as u32,
1547 rn_bits as u32,
1548 rm_bits as u32,
1549 )
1550 }
1551 } else if let Operand2::Imm(imm) = op2 {
1552 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1553 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1555 Ok(instr.to_le_bytes().to_vec())
1556 } else {
1557 self.encode_thumb32_add(rd, rn, *imm as u32)
1559 }
1560 } else {
1561 self.encode_thumb32_add(rd, rn, 0)
1563 }
1564 }
1565
1566 ArmOp::Sub { rd, rn, op2 } => {
1567 let rd_bits = reg_to_bits(rd) as u16;
1568 let rn_bits = reg_to_bits(rn) as u16;
1569
1570 if let Operand2::Reg(rm) = op2 {
1571 let rm_bits = reg_to_bits(rm) as u16;
1572 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1574 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1576 Ok(instr.to_le_bytes().to_vec())
1577 } else {
1578 self.encode_thumb32_sub_reg_raw(
1580 rd_bits as u32,
1581 rn_bits as u32,
1582 rm_bits as u32,
1583 )
1584 }
1585 } else if let Operand2::Imm(imm) = op2 {
1586 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1587 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1589 Ok(instr.to_le_bytes().to_vec())
1590 } else {
1591 self.encode_thumb32_sub(rd, rn, *imm as u32)
1592 }
1593 } else {
1594 self.encode_thumb32_sub(rd, rn, 0)
1595 }
1596 }
1597
1598 ArmOp::Mov { rd, op2 } => {
1599 let rd_bits = reg_to_bits(rd) as u16;
1600
1601 if let Operand2::Imm(imm) = op2 {
1602 if *imm <= 255 && rd_bits < 8 {
1603 let imm_bits = (*imm as u16) & 0xFF;
1605 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1606 Ok(instr.to_le_bytes().to_vec())
1607 } else {
1608 self.encode_thumb32_movw(rd, *imm as u32)
1610 }
1611 } else if let Operand2::Reg(rm) = op2 {
1612 let rm_bits = reg_to_bits(rm) as u16;
1613 let d_bit = (rd_bits >> 3) & 1;
1616 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1617 Ok(instr.to_le_bytes().to_vec())
1618 } else {
1619 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1621 }
1622 }
1623
1624 ArmOp::Push { regs } => {
1625 let mut reg_list: u16 = 0;
1629 let mut need_32bit = false;
1630 for r in regs {
1631 let bit = reg_to_bits(r);
1632 if bit >= 8 && *r != Reg::LR {
1633 need_32bit = true;
1634 }
1635 reg_list |= 1 << bit;
1636 }
1637 if !need_32bit {
1638 let m_bit = if reg_list & (1 << 14) != 0 {
1640 1u16
1641 } else {
1642 0u16
1643 };
1644 let low_regs = reg_list & 0xFF;
1645 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1646 Ok(instr.to_le_bytes().to_vec())
1647 } else {
1648 let hw1: u16 = 0xE92D;
1650 let hw2: u16 = reg_list;
1651 let mut bytes = hw1.to_le_bytes().to_vec();
1652 bytes.extend_from_slice(&hw2.to_le_bytes());
1653 Ok(bytes)
1654 }
1655 }
1656
1657 ArmOp::Pop { regs } => {
1658 let mut reg_list: u16 = 0;
1662 let mut need_32bit = false;
1663 for r in regs {
1664 let bit = reg_to_bits(r);
1665 if bit >= 8 && *r != Reg::PC {
1666 need_32bit = true;
1667 }
1668 reg_list |= 1 << bit;
1669 }
1670 if !need_32bit {
1671 let p_bit = if reg_list & (1 << 15) != 0 {
1673 1u16
1674 } else {
1675 0u16
1676 };
1677 let low_regs = reg_list & 0xFF;
1678 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1679 Ok(instr.to_le_bytes().to_vec())
1680 } else {
1681 let hw1: u16 = 0xE8BD;
1683 let hw2: u16 = reg_list;
1684 let mut bytes = hw1.to_le_bytes().to_vec();
1685 bytes.extend_from_slice(&hw2.to_le_bytes());
1686 Ok(bytes)
1687 }
1688 }
1689
1690 ArmOp::Nop => {
1691 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1693 }
1694
1695 ArmOp::Udf { imm } => {
1696 let instr: u16 = 0xDE00 | (*imm as u16);
1699 let bytes = instr.to_le_bytes().to_vec();
1700 encoding_contracts::verify_thumb16(&bytes);
1701 Ok(bytes)
1702 }
1703
1704 ArmOp::Adds { rd, rn, op2 } => {
1707 let rd_bits = reg_to_bits(rd) as u16;
1708 let rn_bits = reg_to_bits(rn) as u16;
1709
1710 if let Operand2::Reg(rm) = op2 {
1711 let rm_bits = reg_to_bits(rm) as u16;
1712 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1717 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1719 Ok(instr.to_le_bytes().to_vec())
1720 } else {
1721 self.encode_thumb32_adds_reg_raw(
1722 rd_bits as u32,
1723 rn_bits as u32,
1724 rm_bits as u32,
1725 )
1726 }
1727 } else {
1728 self.encode_thumb32_adds(rd, rn, 0)
1730 }
1731 }
1732
1733 ArmOp::Adc { rd, rn, op2 } => {
1736 let rd_bits = reg_to_bits(rd);
1737 let rn_bits = reg_to_bits(rn);
1738
1739 if let Operand2::Reg(rm) = op2 {
1740 let rm_bits = reg_to_bits(rm);
1741 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1743 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1744
1745 let mut bytes = hw1.to_le_bytes().to_vec();
1746 bytes.extend_from_slice(&hw2.to_le_bytes());
1747 Ok(bytes)
1748 } else {
1749 let hw1: u16 = (0xF140 | rn_bits) as u16;
1751 let hw2: u16 = (rd_bits << 8) as u16;
1752 let mut bytes = hw1.to_le_bytes().to_vec();
1753 bytes.extend_from_slice(&hw2.to_le_bytes());
1754 Ok(bytes)
1755 }
1756 }
1757
1758 ArmOp::Subs { rd, rn, op2 } => {
1760 let rd_bits = reg_to_bits(rd) as u16;
1761 let rn_bits = reg_to_bits(rn) as u16;
1762
1763 if let Operand2::Reg(rm) = op2 {
1764 let rm_bits = reg_to_bits(rm) as u16;
1765 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1769 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1771 Ok(instr.to_le_bytes().to_vec())
1772 } else {
1773 self.encode_thumb32_subs_reg_raw(
1774 rd_bits as u32,
1775 rn_bits as u32,
1776 rm_bits as u32,
1777 )
1778 }
1779 } else {
1780 self.encode_thumb32_subs(rd, rn, 0)
1782 }
1783 }
1784
1785 ArmOp::Sbc { rd, rn, op2 } => {
1788 let rd_bits = reg_to_bits(rd);
1789 let rn_bits = reg_to_bits(rn);
1790
1791 if let Operand2::Reg(rm) = op2 {
1792 let rm_bits = reg_to_bits(rm);
1793 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1795 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1796
1797 let mut bytes = hw1.to_le_bytes().to_vec();
1798 bytes.extend_from_slice(&hw2.to_le_bytes());
1799 Ok(bytes)
1800 } else {
1801 let hw1: u16 = (0xF160 | rn_bits) as u16;
1803 let hw2: u16 = (rd_bits << 8) as u16;
1804 let mut bytes = hw1.to_le_bytes().to_vec();
1805 bytes.extend_from_slice(&hw2.to_le_bytes());
1806 Ok(bytes)
1807 }
1808 }
1809
1810 ArmOp::Sdiv { rd, rn, rm } => {
1814 let rd_bits = reg_to_bits(rd);
1815 let rn_bits = reg_to_bits(rn);
1816 let rm_bits = reg_to_bits(rm);
1817 reg_bits_checked(rd_bits)?;
1818 reg_bits_checked(rn_bits)?;
1819 reg_bits_checked(rm_bits)?;
1820
1821 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1825 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1826
1827 let mut bytes = hw1.to_le_bytes().to_vec();
1829 bytes.extend_from_slice(&hw2.to_le_bytes());
1830 encoding_contracts::verify_thumb32(&bytes);
1831 Ok(bytes)
1832 }
1833
1834 ArmOp::Udiv { rd, rn, rm } => {
1836 let rd_bits = reg_to_bits(rd);
1837 let rn_bits = reg_to_bits(rn);
1838 let rm_bits = reg_to_bits(rm);
1839 reg_bits_checked(rd_bits)?;
1840 reg_bits_checked(rn_bits)?;
1841 reg_bits_checked(rm_bits)?;
1842
1843 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1845 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1846
1847 let mut bytes = hw1.to_le_bytes().to_vec();
1848 bytes.extend_from_slice(&hw2.to_le_bytes());
1849 encoding_contracts::verify_thumb32(&bytes);
1850 Ok(bytes)
1851 }
1852
1853 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
1854 let rdlo_bits = reg_to_bits(rdlo);
1855 let rdhi_bits = reg_to_bits(rdhi);
1856 let rn_bits = reg_to_bits(rn);
1857 let rm_bits = reg_to_bits(rm);
1858 reg_bits_checked(rdlo_bits)?;
1859 reg_bits_checked(rdhi_bits)?;
1860 reg_bits_checked(rn_bits)?;
1861 reg_bits_checked(rm_bits)?;
1862
1863 let hw1: u16 = (0xFBA0 | rn_bits) as u16;
1865 let hw2: u16 = ((rdlo_bits << 12) | (rdhi_bits << 8) | rm_bits) as u16;
1866
1867 let mut bytes = hw1.to_le_bytes().to_vec();
1868 bytes.extend_from_slice(&hw2.to_le_bytes());
1869 encoding_contracts::verify_thumb32(&bytes);
1870 Ok(bytes)
1871 }
1872
1873 ArmOp::Mul { rd, rn, rm } => {
1875 let rd_bits = reg_to_bits(rd);
1876 let rn_bits = reg_to_bits(rn);
1877 let rm_bits = reg_to_bits(rm);
1878
1879 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1882 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1883
1884 let mut bytes = hw1.to_le_bytes().to_vec();
1885 bytes.extend_from_slice(&hw2.to_le_bytes());
1886 Ok(bytes)
1887 }
1888
1889 ArmOp::Mls { rd, rn, rm, ra } => {
1891 let rd_bits = reg_to_bits(rd);
1892 let rn_bits = reg_to_bits(rn);
1893 let rm_bits = reg_to_bits(rm);
1894 let ra_bits = reg_to_bits(ra);
1895
1896 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1899 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1900
1901 let mut bytes = hw1.to_le_bytes().to_vec();
1902 bytes.extend_from_slice(&hw2.to_le_bytes());
1903 Ok(bytes)
1904 }
1905
1906 ArmOp::Mla { rd, rn, rm, ra } => {
1907 let rd_bits = reg_to_bits(rd);
1908 let rn_bits = reg_to_bits(rn);
1909 let rm_bits = reg_to_bits(rm);
1910 let ra_bits = reg_to_bits(ra);
1911
1912 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1915 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | rm_bits) as u16;
1916
1917 let mut bytes = hw1.to_le_bytes().to_vec();
1918 bytes.extend_from_slice(&hw2.to_le_bytes());
1919 Ok(bytes)
1920 }
1921
1922 ArmOp::And { rd, rn, op2 } => {
1924 if let Operand2::Reg(rm) = op2 {
1925 let rd_bits = reg_to_bits(rd);
1926 let rn_bits = reg_to_bits(rn);
1927 let rm_bits = reg_to_bits(rm);
1928
1929 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1931 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1932
1933 let mut bytes = hw1.to_le_bytes().to_vec();
1934 bytes.extend_from_slice(&hw2.to_le_bytes());
1935 Ok(bytes)
1936 } else if let Operand2::Imm(imm) = op2 {
1937 let rd_bits = reg_to_bits(rd);
1938 let rn_bits = reg_to_bits(rn);
1939
1940 let field = try_thumb_expand_imm(*imm as u32).ok_or_else(|| {
1947 synth_core::Error::synthesis(
1948 "AND immediate is not a valid ThumbExpandImm — materialize into a register",
1949 )
1950 })?;
1951 let i_bit = (field >> 11) & 1;
1952 let imm3 = (field >> 8) & 0x7;
1953 let imm8 = field & 0xFF;
1954
1955 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1956 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1957
1958 let mut bytes = hw1.to_le_bytes().to_vec();
1959 bytes.extend_from_slice(&hw2.to_le_bytes());
1960 Ok(bytes)
1961 } else {
1962 let instr: u16 = 0xBF00;
1964 Ok(instr.to_le_bytes().to_vec())
1965 }
1966 }
1967
1968 ArmOp::Orr { rd, rn, op2 } => {
1970 if let Operand2::Reg(rm) = op2 {
1971 let rd_bits = reg_to_bits(rd);
1972 let rn_bits = reg_to_bits(rn);
1973 let rm_bits = reg_to_bits(rm);
1974
1975 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1977 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1978
1979 let mut bytes = hw1.to_le_bytes().to_vec();
1980 bytes.extend_from_slice(&hw2.to_le_bytes());
1981 Ok(bytes)
1982 } else if let Operand2::Imm(imm) = op2 {
1983 let imm_val = *imm as u32;
1988 if imm_val > 0xFF {
1989 return Err(synth_core::Error::synthesis(
1990 "ORR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1991 ));
1992 }
1993 let rd_bits = reg_to_bits(rd);
1994 let rn_bits = reg_to_bits(rn);
1995 let hw1: u16 = (0xF040 | rn_bits) as u16;
1996 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
1997 let mut bytes = hw1.to_le_bytes().to_vec();
1998 bytes.extend_from_slice(&hw2.to_le_bytes());
1999 Ok(bytes)
2000 } else {
2001 let instr: u16 = 0xBF00;
2002 Ok(instr.to_le_bytes().to_vec())
2003 }
2004 }
2005
2006 ArmOp::Eor { rd, rn, op2 } => {
2008 if let Operand2::Reg(rm) = op2 {
2009 let rd_bits = reg_to_bits(rd);
2010 let rn_bits = reg_to_bits(rn);
2011 let rm_bits = reg_to_bits(rm);
2012
2013 let hw1: u16 = (0xEA80 | rn_bits) as u16;
2015 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
2016
2017 let mut bytes = hw1.to_le_bytes().to_vec();
2018 bytes.extend_from_slice(&hw2.to_le_bytes());
2019 Ok(bytes)
2020 } else if let Operand2::Imm(imm) = op2 {
2021 let imm_val = *imm as u32;
2025 if imm_val > 0xFF {
2026 return Err(synth_core::Error::synthesis(
2027 "EOR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
2028 ));
2029 }
2030 let rd_bits = reg_to_bits(rd);
2031 let rn_bits = reg_to_bits(rn);
2032 let hw1: u16 = (0xF080 | rn_bits) as u16;
2033 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
2034 let mut bytes = hw1.to_le_bytes().to_vec();
2035 bytes.extend_from_slice(&hw2.to_le_bytes());
2036 Ok(bytes)
2037 } else {
2038 let instr: u16 = 0xBF00;
2039 Ok(instr.to_le_bytes().to_vec())
2040 }
2041 }
2042
2043 ArmOp::Lsl { rd, rn, shift } => {
2045 let rd_bits = reg_to_bits(rd) as u16;
2046 let rn_bits = reg_to_bits(rn) as u16;
2047 let shift_bits = (*shift as u16) & 0x1F;
2048
2049 if rd_bits < 8 && rn_bits < 8 {
2050 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2052 Ok(instr.to_le_bytes().to_vec())
2053 } else {
2054 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
2057 }
2058
2059 ArmOp::Lsr { 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 = 0x0800 | (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, 0b01) }
2071 }
2072
2073 ArmOp::Asr { rd, rn, shift } => {
2074 let rd_bits = reg_to_bits(rd) as u16;
2075 let rn_bits = reg_to_bits(rn) as u16;
2076 let shift_bits = (*shift as u16) & 0x1F;
2077
2078 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2079 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2081 Ok(instr.to_le_bytes().to_vec())
2082 } else {
2083 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
2085 }
2086
2087 ArmOp::Ror { rd, rn, shift } => {
2088 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
2091
2092 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
2096 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
2097 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
2098 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
2099
2100 ArmOp::Rsb { rd, rn, imm } => {
2103 let rd_bits = reg_to_bits(rd);
2104 let rn_bits = reg_to_bits(rn);
2105 let imm_val = *imm;
2106
2107 let i_bit = (imm_val >> 11) & 1;
2108 let imm3 = (imm_val >> 8) & 0x7;
2109 let imm8 = imm_val & 0xFF;
2110
2111 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2113 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2115
2116 let mut bytes = hw1.to_le_bytes().to_vec();
2117 bytes.extend_from_slice(&hw2.to_le_bytes());
2118 Ok(bytes)
2119 }
2120
2121 ArmOp::Clz { rd, rm } => {
2123 let rd_bits = reg_to_bits(rd);
2124 let rm_bits = reg_to_bits(rm);
2125
2126 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2129 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2130
2131 let mut bytes = hw1.to_le_bytes().to_vec();
2132 bytes.extend_from_slice(&hw2.to_le_bytes());
2133 Ok(bytes)
2134 }
2135
2136 ArmOp::Rbit { rd, rm } => {
2138 let rd_bits = reg_to_bits(rd);
2139 let rm_bits = reg_to_bits(rm);
2140
2141 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2144 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2145
2146 let mut bytes = hw1.to_le_bytes().to_vec();
2147 bytes.extend_from_slice(&hw2.to_le_bytes());
2148 Ok(bytes)
2149 }
2150
2151 ArmOp::Sxtb { rd, rm } => {
2153 let rd_bits = reg_to_bits(rd) as u16;
2154 let rm_bits = reg_to_bits(rm) as u16;
2155
2156 if rd_bits < 8 && rm_bits < 8 {
2157 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2159 Ok(instr.to_le_bytes().to_vec())
2160 } else {
2161 let rd_bits32 = rd_bits as u32;
2164 let rm_bits32 = rm_bits as u32;
2165 let hw1: u16 = 0xFA4F;
2166 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2167 let mut bytes = hw1.to_le_bytes().to_vec();
2168 bytes.extend_from_slice(&hw2.to_le_bytes());
2169 Ok(bytes)
2170 }
2171 }
2172
2173 ArmOp::Sxth { rd, rm } => {
2175 let rd_bits = reg_to_bits(rd) as u16;
2176 let rm_bits = reg_to_bits(rm) as u16;
2177
2178 if rd_bits < 8 && rm_bits < 8 {
2179 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2181 Ok(instr.to_le_bytes().to_vec())
2182 } else {
2183 let rd_bits32 = rd_bits as u32;
2186 let rm_bits32 = rm_bits as u32;
2187 let hw1: u16 = 0xFA0F;
2188 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2189 let mut bytes = hw1.to_le_bytes().to_vec();
2190 bytes.extend_from_slice(&hw2.to_le_bytes());
2191 Ok(bytes)
2192 }
2193 }
2194
2195 ArmOp::Uxtb { rd, rm } => {
2197 let rd_bits = reg_to_bits(rd) as u16;
2198 let rm_bits = reg_to_bits(rm) as u16;
2199 if rd_bits < 8 && rm_bits < 8 {
2200 let instr: u16 = 0xB2C0 | (rm_bits << 3) | rd_bits;
2202 Ok(instr.to_le_bytes().to_vec())
2203 } else {
2204 let hw1: u16 = 0xFA5F;
2206 let hw2: u16 = (0xF080 | ((rd_bits as u32) << 8) | rm_bits as u32) as u16;
2207 let mut bytes = hw1.to_le_bytes().to_vec();
2208 bytes.extend_from_slice(&hw2.to_le_bytes());
2209 Ok(bytes)
2210 }
2211 }
2212
2213 ArmOp::Uxth { rd, rm } => {
2215 let rd_bits = reg_to_bits(rd) as u16;
2216 let rm_bits = reg_to_bits(rm) as u16;
2217 if rd_bits < 8 && rm_bits < 8 {
2218 let instr: u16 = 0xB280 | (rm_bits << 3) | rd_bits;
2220 Ok(instr.to_le_bytes().to_vec())
2221 } else {
2222 let hw1: u16 = 0xFA1F;
2224 let hw2: u16 = (0xF080 | ((rd_bits as u32) << 8) | rm_bits as u32) as u16;
2225 let mut bytes = hw1.to_le_bytes().to_vec();
2226 bytes.extend_from_slice(&hw2.to_le_bytes());
2227 Ok(bytes)
2228 }
2229 }
2230
2231 ArmOp::Cmp { rn, op2 } => {
2233 let rn_bits = reg_to_bits(rn) as u16;
2234
2235 if let Operand2::Imm(imm) = op2 {
2236 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2239 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2241 Ok(instr.to_le_bytes().to_vec())
2242 } else {
2243 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2244 }
2245 } else if let Operand2::Reg(rm) = op2 {
2246 let rm_bits = reg_to_bits(rm) as u16;
2247 if rn_bits < 8 && rm_bits < 8 {
2248 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2250 Ok(instr.to_le_bytes().to_vec())
2251 } else {
2252 let n_bit = (rn_bits >> 3) & 1;
2254 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2255 Ok(instr.to_le_bytes().to_vec())
2256 }
2257 } else {
2258 let instr: u16 = 0xBF00;
2259 Ok(instr.to_le_bytes().to_vec())
2260 }
2261 }
2262
2263 ArmOp::Cmn { rn, op2 } => {
2266 let rn_bits = reg_to_bits(rn) as u16;
2267
2268 if let Operand2::Imm(imm) = op2 {
2269 let field = try_thumb_expand_imm(*imm as u32).ok_or_else(|| {
2275 synth_core::Error::synthesis(
2276 "CMN immediate is not a valid ThumbExpandImm — materialize into a register",
2277 )
2278 })?;
2279 let i_bit = (field >> 11) & 1;
2280 let imm3 = (field >> 8) & 0x7;
2281 let imm8 = field & 0xFF;
2282 let hw1: u16 = (0xF110 | (i_bit << 10) as u16) | rn_bits;
2283 let hw2: u16 = (imm3 << 12) as u16 | 0x0F00 | imm8 as u16;
2284 let mut bytes = hw1.to_le_bytes().to_vec();
2285 bytes.extend_from_slice(&hw2.to_le_bytes());
2286 Ok(bytes)
2287 } else if let Operand2::Reg(rm) = op2 {
2288 let rm_bits = reg_to_bits(rm) as u16;
2289 if rn_bits < 8 && rm_bits < 8 {
2295 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2297 Ok(instr.to_le_bytes().to_vec())
2298 } else {
2299 let hw1: u16 = 0xEB10 | rn_bits;
2300 let hw2: u16 = 0x0F00 | rm_bits;
2301 let mut bytes = hw1.to_le_bytes().to_vec();
2302 bytes.extend_from_slice(&hw2.to_le_bytes());
2303 Ok(bytes)
2304 }
2305 } else {
2306 Ok(vec![0xBF, 0x00])
2307 }
2308 }
2309
2310 ArmOp::Ldr { rd, addr } => {
2312 let rd_bits = reg_to_bits(rd);
2313 let base_bits = reg_to_bits(&addr.base);
2314
2315 if let Some(offset_reg) = &addr.offset_reg {
2317 let rm_bits = reg_to_bits(offset_reg);
2318
2319 if addr.offset != 0 {
2321 let scratch = Reg::R12;
2324 let mut bytes =
2325 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2326 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2327 return Ok(bytes);
2328 }
2329
2330 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2333 let instr: u16 = 0x5800
2335 | ((rm_bits as u16) << 6)
2336 | ((base_bits as u16) << 3)
2337 | (rd_bits as u16);
2338 return Ok(instr.to_le_bytes().to_vec());
2339 }
2340
2341 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2343 }
2344
2345 let offset = addr.offset as u32;
2347
2348 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2349 let imm5 = (offset >> 2) as u16;
2351 let instr: u16 =
2352 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2353 Ok(instr.to_le_bytes().to_vec())
2354 } else {
2355 self.encode_thumb32_ldr(rd, &addr.base, offset)
2356 }
2357 }
2358
2359 ArmOp::Str { rd, addr } => {
2361 let rd_bits = reg_to_bits(rd);
2362 let base_bits = reg_to_bits(&addr.base);
2363
2364 if let Some(offset_reg) = &addr.offset_reg {
2366 let rm_bits = reg_to_bits(offset_reg);
2367
2368 if addr.offset != 0 {
2370 let scratch = Reg::R12;
2373 let mut bytes =
2374 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2375 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2376 return Ok(bytes);
2377 }
2378
2379 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2382 let instr: u16 = 0x5000
2384 | ((rm_bits as u16) << 6)
2385 | ((base_bits as u16) << 3)
2386 | (rd_bits as u16);
2387 return Ok(instr.to_le_bytes().to_vec());
2388 }
2389
2390 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2392 }
2393
2394 let offset = addr.offset as u32;
2396
2397 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2398 let imm5 = (offset >> 2) as u16;
2400 let instr: u16 =
2401 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2402 Ok(instr.to_le_bytes().to_vec())
2403 } else {
2404 self.encode_thumb32_str(rd, &addr.base, offset)
2405 }
2406 }
2407
2408 ArmOp::Ldrb { rd, addr } => {
2410 let rd_bits = reg_to_bits(rd);
2411 let base_bits = reg_to_bits(&addr.base);
2412
2413 if let Some(offset_reg) = &addr.offset_reg {
2414 if addr.offset != 0 {
2415 let scratch = Reg::R12;
2416 let mut bytes =
2417 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2418 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2419 return Ok(bytes);
2420 }
2421 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2422 }
2423
2424 let offset = addr.offset as u32;
2425 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2426 let instr: u16 = 0x7800
2428 | ((offset as u16) << 6)
2429 | ((base_bits as u16) << 3)
2430 | (rd_bits as u16);
2431 Ok(instr.to_le_bytes().to_vec())
2432 } else {
2433 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2434 }
2435 }
2436
2437 ArmOp::Ldrsb { rd, addr } => {
2439 let rd_bits = reg_to_bits(rd);
2440 let base_bits = reg_to_bits(&addr.base);
2441
2442 if let Some(offset_reg) = &addr.offset_reg {
2443 if addr.offset != 0 {
2444 let scratch = Reg::R12;
2445 let mut bytes =
2446 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2447 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2448 return Ok(bytes);
2449 }
2450 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2451 }
2452
2453 let offset = addr.offset as u32;
2454 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2457 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2459 } else {
2460 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2461 }
2462 }
2463
2464 ArmOp::Ldrh { rd, addr } => {
2466 let rd_bits = reg_to_bits(rd);
2467 let base_bits = reg_to_bits(&addr.base);
2468
2469 if let Some(offset_reg) = &addr.offset_reg {
2470 if addr.offset != 0 {
2471 let scratch = Reg::R12;
2472 let mut bytes =
2473 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2474 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2475 return Ok(bytes);
2476 }
2477 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2478 }
2479
2480 let offset = addr.offset as u32;
2481 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2482 let imm5 = (offset >> 1) as u16;
2484 let instr: u16 =
2485 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2486 Ok(instr.to_le_bytes().to_vec())
2487 } else {
2488 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2489 }
2490 }
2491
2492 ArmOp::Ldrsh { rd, addr } => {
2494 if let Some(offset_reg) = &addr.offset_reg {
2495 if addr.offset != 0 {
2496 let scratch = Reg::R12;
2497 let mut bytes =
2498 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2499 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2500 return Ok(bytes);
2501 }
2502 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2503 }
2504
2505 let offset = addr.offset as u32;
2506 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2507 }
2508
2509 ArmOp::Strb { rd, addr } => {
2511 let rd_bits = reg_to_bits(rd);
2512 let base_bits = reg_to_bits(&addr.base);
2513
2514 if let Some(offset_reg) = &addr.offset_reg {
2515 if addr.offset != 0 {
2516 let scratch = Reg::R12;
2517 let mut bytes =
2518 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2519 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2520 return Ok(bytes);
2521 }
2522 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2523 }
2524
2525 let offset = addr.offset as u32;
2526 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2527 let instr: u16 = 0x7000
2529 | ((offset as u16) << 6)
2530 | ((base_bits as u16) << 3)
2531 | (rd_bits as u16);
2532 Ok(instr.to_le_bytes().to_vec())
2533 } else {
2534 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2535 }
2536 }
2537
2538 ArmOp::Strh { rd, addr } => {
2540 let rd_bits = reg_to_bits(rd);
2541 let base_bits = reg_to_bits(&addr.base);
2542
2543 if let Some(offset_reg) = &addr.offset_reg {
2544 if addr.offset != 0 {
2545 let scratch = Reg::R12;
2546 let mut bytes =
2547 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2548 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2549 return Ok(bytes);
2550 }
2551 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2552 }
2553
2554 let offset = addr.offset as u32;
2555 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2556 let imm5 = (offset >> 1) as u16;
2558 let instr: u16 =
2559 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2560 Ok(instr.to_le_bytes().to_vec())
2561 } else {
2562 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2563 }
2564 }
2565
2566 ArmOp::MemorySize { rd } => {
2568 let rd_bits = reg_to_bits(rd);
2571 let r10_bits = reg_to_bits(&Reg::R10);
2572 if rd_bits < 8 && r10_bits < 8 {
2573 let instr: u16 =
2574 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2575 Ok(instr.to_le_bytes().to_vec())
2576 } else {
2577 let imm5: u32 = 16;
2579 let imm3 = (imm5 >> 2) & 0x7;
2580 let imm2 = imm5 & 0x3;
2581 let hw1: u16 = 0xEA4F;
2582 let hw2: u16 =
2583 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2584 let mut bytes = hw1.to_le_bytes().to_vec();
2585 bytes.extend_from_slice(&hw2.to_le_bytes());
2586 Ok(bytes)
2587 }
2588 }
2589
2590 ArmOp::MemoryGrow { rd, .. } => {
2592 let rd_bits = reg_to_bits(rd);
2596 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2599 bytes.extend_from_slice(&hw2.to_le_bytes());
2600 Ok(bytes)
2601 }
2602
2603 ArmOp::Bx { rm } => {
2605 let rm_bits = reg_to_bits(rm) as u16;
2606 let instr: u16 = 0x4700 | (rm_bits << 3);
2608 Ok(instr.to_le_bytes().to_vec())
2609 }
2610
2611 ArmOp::Blx { rm } => {
2614 let rm_bits = reg_to_bits(rm) as u16;
2615 let instr: u16 = 0x4780 | (rm_bits << 3);
2616 Ok(instr.to_le_bytes().to_vec())
2617 }
2618
2619 ArmOp::CallIndirect {
2623 rd: _,
2624 type_idx: _,
2625 table_index_reg,
2626 } => {
2627 let idx_reg = reg_to_bits(table_index_reg);
2628 let mut bytes = Vec::new();
2629
2630 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2646 bytes.extend_from_slice(&hw1.to_le_bytes());
2647 bytes.extend_from_slice(&hw2.to_le_bytes());
2648
2649 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2655 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2656
2657 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2661
2662 Ok(bytes)
2663 }
2664
2665 ArmOp::Label { .. } => Ok(Vec::new()),
2667
2668 ArmOp::Bcc { cond, label: _ } => {
2670 use synth_synthesis::Condition;
2671 let cond_bits: u16 = match cond {
2672 Condition::EQ => 0x0,
2673 Condition::NE => 0x1,
2674 Condition::HS => 0x2,
2675 Condition::LO => 0x3,
2676 Condition::HI => 0x8,
2677 Condition::LS => 0x9,
2678 Condition::GE => 0xA,
2679 Condition::LT => 0xB,
2680 Condition::GT => 0xC,
2681 Condition::LE => 0xD,
2682 };
2683 let instr: u16 = 0xD000 | (cond_bits << 8);
2685 Ok(instr.to_le_bytes().to_vec())
2686 }
2687
2688 ArmOp::B { label: _ } => {
2690 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2694 }
2695
2696 ArmOp::Bhs { label: _ } => {
2699 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2703 }
2704
2705 ArmOp::Blo { label: _ } => {
2708 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2712 }
2713
2714 ArmOp::BOffset { offset } => {
2717 let halfword_offset = *offset;
2720
2721 if (-1024..=1022).contains(&halfword_offset) {
2724 let imm11 = (halfword_offset as u16) & 0x7FF;
2726 let instr: u16 = 0xE000 | imm11;
2727 Ok(instr.to_le_bytes().to_vec())
2728 } else {
2729 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2745 let uoffset = signed_offset as u32;
2746 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;
2754 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2755
2756 let mut bytes = hw1.to_le_bytes().to_vec();
2757 bytes.extend_from_slice(&hw2.to_le_bytes());
2758 Ok(bytes)
2759 }
2760 }
2761
2762 ArmOp::BCondOffset { cond, offset } => {
2764 use synth_synthesis::Condition;
2765 let cond_bits: u16 = match cond {
2766 Condition::EQ => 0x0,
2767 Condition::NE => 0x1,
2768 Condition::HS => 0x2,
2769 Condition::LO => 0x3,
2770 Condition::HI => 0x8,
2771 Condition::LS => 0x9,
2772 Condition::GE => 0xA,
2773 Condition::LT => 0xB,
2774 Condition::GT => 0xC,
2775 Condition::LE => 0xD,
2776 };
2777
2778 let halfword_offset = *offset;
2781
2782 if (-128..=127).contains(&halfword_offset) {
2785 let imm8 = (halfword_offset as u16) & 0xFF;
2786 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2787 Ok(instr.to_le_bytes().to_vec())
2788 } else {
2789 let offset = halfword_offset >> 1;
2793 let s = if offset < 0 { 1u32 } else { 0u32 };
2794 let imm6 = ((offset >> 11) as u32) & 0x3F;
2795 let imm11 = (offset as u32) & 0x7FF;
2796 let j1 = if s == 1 { 1 } else { 0 };
2797 let j2 = if s == 1 { 1 } else { 0 };
2798
2799 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2800 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2801
2802 let mut bytes = hw1.to_le_bytes().to_vec();
2803 bytes.extend_from_slice(&hw2.to_le_bytes());
2804 Ok(bytes)
2805 }
2806 }
2807
2808 ArmOp::Bl { label: _ } => {
2809 let hw1: u16 = 0xF7FF;
2824 let hw2: u16 = 0xFFFE;
2825 let mut bytes = hw1.to_le_bytes().to_vec();
2826 bytes.extend_from_slice(&hw2.to_le_bytes());
2827 Ok(bytes)
2828 }
2829
2830 ArmOp::Mvn { rd, op2 } => {
2832 if let Operand2::Reg(rm) = op2 {
2833 let rd_bits = reg_to_bits(rd) as u16;
2834 let rm_bits = reg_to_bits(rm) as u16;
2835
2836 if rd_bits < 8 && rm_bits < 8 {
2837 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2839 Ok(instr.to_le_bytes().to_vec())
2840 } else {
2841 let hw1: u16 = 0xEA6F_u16;
2843 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2844 let mut bytes = hw1.to_le_bytes().to_vec();
2845 bytes.extend_from_slice(&hw2.to_le_bytes());
2846 Ok(bytes)
2847 }
2848 } else {
2849 let instr: u16 = 0xBF00;
2850 Ok(instr.to_le_bytes().to_vec())
2851 }
2852 }
2853
2854 ArmOp::Movw { rd, imm16 } => {
2856 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2857 }
2858
2859 ArmOp::Movt { rd, imm16 } => {
2861 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2862 }
2863
2864 ArmOp::MovwSym { rd, addend, .. } => {
2869 self.encode_thumb32_movw_raw(reg_to_bits(rd), (*addend as u32) & 0xffff)
2870 }
2871 ArmOp::MovtSym { rd, addend, .. } => {
2872 self.encode_thumb32_movt_raw(reg_to_bits(rd), ((*addend as u32) >> 16) & 0xffff)
2873 }
2874
2875 ArmOp::LdrSym { rd, .. } => {
2883 let rt = reg_to_bits(rd) as u16;
2884 let hw1: u16 = 0xF8DF; let hw2: u16 = rt << 12; let mut bytes = Vec::with_capacity(4);
2887 bytes.extend_from_slice(&hw1.to_le_bytes());
2888 bytes.extend_from_slice(&hw2.to_le_bytes());
2889 Ok(bytes)
2890 }
2891
2892 ArmOp::SetCond { rd, cond } => {
2898 let rd_bits = reg_to_bits(rd) as u16;
2899
2900 use synth_synthesis::Condition;
2902 let cond_bits: u16 = match cond {
2903 Condition::EQ => 0x0,
2904 Condition::NE => 0x1,
2905 Condition::LT => 0xB,
2906 Condition::LE => 0xD,
2907 Condition::GT => 0xC,
2908 Condition::GE => 0xA,
2909 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2914
2915 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2920 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2921
2922 let mut bytes = ite_instr.to_le_bytes().to_vec();
2933 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2934 if rd_bits <= 7 {
2935 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2937 } else {
2938 let hw1: u16 = 0xF04F;
2940 let hw2: u16 = (rd_bits << 8) | imm;
2941 bytes.extend_from_slice(&hw1.to_le_bytes());
2942 bytes.extend_from_slice(&hw2.to_le_bytes());
2943 }
2944 };
2945 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2948 }
2949
2950 ArmOp::I64SetCond {
2955 rd,
2956 rn_lo,
2957 rn_hi,
2958 rm_lo,
2959 rm_hi,
2960 cond,
2961 } => {
2962 use synth_synthesis::Condition;
2963 let rd_bits = reg_to_bits(rd) as u16;
2964 let mut bytes = Vec::new();
2965
2966 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2968 rm: &synth_synthesis::Reg|
2969 -> Vec<u8> {
2970 let rn_bits = reg_to_bits(rn) as u16;
2971 let rm_bits = reg_to_bits(rm) as u16;
2972 if rn_bits < 8 && rm_bits < 8 {
2973 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2974 instr.to_le_bytes().to_vec()
2975 } else {
2976 let n_bit = (rn_bits >> 3) & 1;
2977 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2978 instr.to_le_bytes().to_vec()
2979 }
2980 };
2981
2982 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2984 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2985 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2986 ite_instr.to_le_bytes().to_vec()
2987 };
2988
2989 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2991 let mut b = encode_ite(cond_bits);
2992 if rd_bits < 8 {
2993 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2994 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2995 b.extend_from_slice(&mov_one.to_le_bytes());
2996 b.extend_from_slice(&mov_zero.to_le_bytes());
2997 } else {
2998 for imm in [1u16, 0u16] {
3006 let hw1: u16 = 0xF04F;
3007 let hw2: u16 = (rd_bits << 8) | imm;
3008 b.extend_from_slice(&hw1.to_le_bytes());
3009 b.extend_from_slice(&hw2.to_le_bytes());
3010 }
3011 }
3012 b
3013 };
3014
3015 match cond {
3016 Condition::EQ | Condition::NE => {
3017 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3019
3020 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
3023
3024 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
3026
3027 let cond_bits: u16 = match cond {
3029 Condition::EQ => 0x0,
3030 Condition::NE => 0x1,
3031 _ => unreachable!(),
3032 };
3033 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
3034 }
3035
3036 Condition::LT => {
3037 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3039
3040 let rn_hi_bits = reg_to_bits(rn_hi);
3043 let rm_hi_bits = reg_to_bits(rm_hi);
3044 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3045 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3046 bytes.extend_from_slice(&hw1.to_le_bytes());
3047 bytes.extend_from_slice(&hw2.to_le_bytes());
3048
3049 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
3052
3053 Condition::GT => {
3054 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3057
3058 let rm_hi_bits = reg_to_bits(rm_hi);
3060 let rn_hi_bits = reg_to_bits(rn_hi);
3061 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3062 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3063 bytes.extend_from_slice(&hw1.to_le_bytes());
3064 bytes.extend_from_slice(&hw2.to_le_bytes());
3065
3066 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
3069
3070 Condition::LE => {
3071 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3075
3076 let rm_hi_bits = reg_to_bits(rm_hi);
3078 let rn_hi_bits = reg_to_bits(rn_hi);
3079 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3080 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3081 bytes.extend_from_slice(&hw1.to_le_bytes());
3082 bytes.extend_from_slice(&hw2.to_le_bytes());
3083
3084 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3087
3088 Condition::GE => {
3089 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3092
3093 let rn_hi_bits = reg_to_bits(rn_hi);
3095 let rm_hi_bits = reg_to_bits(rm_hi);
3096 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3097 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3098 bytes.extend_from_slice(&hw1.to_le_bytes());
3099 bytes.extend_from_slice(&hw2.to_le_bytes());
3100
3101 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3104
3105 Condition::LO => {
3107 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3109 let rn_hi_bits = reg_to_bits(rn_hi);
3110 let rm_hi_bits = reg_to_bits(rm_hi);
3111 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3112 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3113 bytes.extend_from_slice(&hw1.to_le_bytes());
3114 bytes.extend_from_slice(&hw2.to_le_bytes());
3115 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3117
3118 Condition::HI => {
3119 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3121 let rm_hi_bits = reg_to_bits(rm_hi);
3122 let rn_hi_bits = reg_to_bits(rn_hi);
3123 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3124 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3125 bytes.extend_from_slice(&hw1.to_le_bytes());
3126 bytes.extend_from_slice(&hw2.to_le_bytes());
3127 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3129
3130 Condition::LS => {
3131 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3133 let rm_hi_bits = reg_to_bits(rm_hi);
3134 let rn_hi_bits = reg_to_bits(rn_hi);
3135 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3136 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3137 bytes.extend_from_slice(&hw1.to_le_bytes());
3138 bytes.extend_from_slice(&hw2.to_le_bytes());
3139 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3141
3142 Condition::HS => {
3143 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3145 let rn_hi_bits = reg_to_bits(rn_hi);
3146 let rm_hi_bits = reg_to_bits(rm_hi);
3147 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3148 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3149 bytes.extend_from_slice(&hw1.to_le_bytes());
3150 bytes.extend_from_slice(&hw2.to_le_bytes());
3151 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3153 }
3154
3155 Ok(bytes)
3156 }
3157
3158 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
3161 let rd_bits = reg_to_bits(rd);
3162 let rn_lo_bits = reg_to_bits(rn_lo);
3163 let rn_hi_bits = reg_to_bits(rn_hi);
3164 let mut bytes = Vec::new();
3165
3166 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3168 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3169 bytes.extend_from_slice(&hw1.to_le_bytes());
3170 bytes.extend_from_slice(&hw2.to_le_bytes());
3171
3172 if rd_bits < 8 {
3177 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3178 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3179 } else {
3180 let hw1: u16 = 0xF1B0 | (rd_bits as u16);
3181 let hw2: u16 = 0x0F00;
3182 bytes.extend_from_slice(&hw1.to_le_bytes());
3183 bytes.extend_from_slice(&hw2.to_le_bytes());
3184 }
3185
3186 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3190 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3191 if rd_bits < 8 {
3192 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3193 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3194 bytes.extend_from_slice(&mov_one.to_le_bytes());
3195 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3196 } else {
3197 for imm in [1u16, 0u16] {
3198 let hw1: u16 = 0xF04F;
3199 let hw2: u16 = ((rd_bits as u16) << 8) | imm;
3200 bytes.extend_from_slice(&hw1.to_le_bytes());
3201 bytes.extend_from_slice(&hw2.to_le_bytes());
3202 }
3203 }
3204
3205 Ok(bytes)
3206 }
3207
3208 ArmOp::I64Mul {
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);
3225 let r12: u32 = 12; let mut bytes = Vec::new();
3227
3228 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3231 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3232 bytes.extend_from_slice(&hw1.to_le_bytes());
3233 bytes.extend_from_slice(&hw2.to_le_bytes());
3234
3235 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3238 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3239 bytes.extend_from_slice(&hw1.to_le_bytes());
3240 bytes.extend_from_slice(&hw2.to_le_bytes());
3241
3242 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3245 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3246 bytes.extend_from_slice(&hw1.to_le_bytes());
3247 bytes.extend_from_slice(&hw2.to_le_bytes());
3248
3249 let d_bit = (rd_hi_bits >> 3) & 1;
3252 let add_instr: u16 =
3253 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3254 bytes.extend_from_slice(&add_instr.to_le_bytes());
3255
3256 Ok(bytes)
3257 }
3258
3259 ArmOp::I64Shl {
3262 rd_lo,
3263 rd_hi,
3264 rn_lo,
3265 rn_hi,
3266 rm_lo,
3267 rm_hi,
3268 } => {
3269 let rd_lo_bits = reg_to_bits(rd_lo);
3270 let rd_hi_bits = reg_to_bits(rd_hi);
3271 let rn_lo_bits = reg_to_bits(rn_lo);
3272 let rn_hi_bits = reg_to_bits(rn_hi);
3273 let rm_lo_bits = reg_to_bits(rm_lo);
3274 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3276
3277 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3279 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3280 bytes.extend_from_slice(&hw1.to_le_bytes());
3281 bytes.extend_from_slice(&hw2.to_le_bytes());
3282
3283 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3285 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3286 bytes.extend_from_slice(&hw1.to_le_bytes());
3287 bytes.extend_from_slice(&hw2.to_le_bytes());
3288
3289 let bpl: u16 = 0xD50A;
3291 bytes.extend_from_slice(&bpl.to_le_bytes());
3292
3293 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3296 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3297 bytes.extend_from_slice(&hw1.to_le_bytes());
3298 bytes.extend_from_slice(&hw2.to_le_bytes());
3299
3300 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3302 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3303 bytes.extend_from_slice(&hw1.to_le_bytes());
3304 bytes.extend_from_slice(&hw2.to_le_bytes());
3305
3306 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3308 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3309 bytes.extend_from_slice(&hw1.to_le_bytes());
3310 bytes.extend_from_slice(&hw2.to_le_bytes());
3311
3312 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3314 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3315 bytes.extend_from_slice(&hw1.to_le_bytes());
3316 bytes.extend_from_slice(&hw2.to_le_bytes());
3317
3318 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3320 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3321 bytes.extend_from_slice(&hw1.to_le_bytes());
3322 bytes.extend_from_slice(&hw2.to_le_bytes());
3323
3324 let b_done: u16 = 0xE002;
3326 bytes.extend_from_slice(&b_done.to_le_bytes());
3327
3328 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3331 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3332 bytes.extend_from_slice(&hw1.to_le_bytes());
3333 bytes.extend_from_slice(&hw2.to_le_bytes());
3334
3335 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3337 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3338
3339 Ok(bytes) }
3341
3342 ArmOp::I64ShrU {
3344 rd_lo,
3345 rd_hi,
3346 rn_lo,
3347 rn_hi,
3348 rm_lo,
3349 rm_hi,
3350 } => {
3351 let rd_lo_bits = reg_to_bits(rd_lo);
3352 let rd_hi_bits = reg_to_bits(rd_hi);
3353 let rn_lo_bits = reg_to_bits(rn_lo);
3354 let rn_hi_bits = reg_to_bits(rn_hi);
3355 let rm_lo_bits = reg_to_bits(rm_lo);
3356 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3358
3359 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3361 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3362 bytes.extend_from_slice(&hw1.to_le_bytes());
3363 bytes.extend_from_slice(&hw2.to_le_bytes());
3364
3365 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3367 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3368 bytes.extend_from_slice(&hw1.to_le_bytes());
3369 bytes.extend_from_slice(&hw2.to_le_bytes());
3370
3371 let bpl: u16 = 0xD50A;
3373 bytes.extend_from_slice(&bpl.to_le_bytes());
3374
3375 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3378 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3379 bytes.extend_from_slice(&hw1.to_le_bytes());
3380 bytes.extend_from_slice(&hw2.to_le_bytes());
3381
3382 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3384 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3385 bytes.extend_from_slice(&hw1.to_le_bytes());
3386 bytes.extend_from_slice(&hw2.to_le_bytes());
3387
3388 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3390 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3391 bytes.extend_from_slice(&hw1.to_le_bytes());
3392 bytes.extend_from_slice(&hw2.to_le_bytes());
3393
3394 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3396 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3397 bytes.extend_from_slice(&hw1.to_le_bytes());
3398 bytes.extend_from_slice(&hw2.to_le_bytes());
3399
3400 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3402 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3403 bytes.extend_from_slice(&hw1.to_le_bytes());
3404 bytes.extend_from_slice(&hw2.to_le_bytes());
3405
3406 let b_done: u16 = 0xE002;
3408 bytes.extend_from_slice(&b_done.to_le_bytes());
3409
3410 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3413 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3414 bytes.extend_from_slice(&hw1.to_le_bytes());
3415 bytes.extend_from_slice(&hw2.to_le_bytes());
3416
3417 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3419 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3420
3421 Ok(bytes) }
3423
3424 ArmOp::I64ShrS {
3426 rd_lo,
3427 rd_hi,
3428 rn_lo,
3429 rn_hi,
3430 rm_lo,
3431 rm_hi,
3432 } => {
3433 let rd_lo_bits = reg_to_bits(rd_lo);
3434 let rd_hi_bits = reg_to_bits(rd_hi);
3435 let rn_lo_bits = reg_to_bits(rn_lo);
3436 let rn_hi_bits = reg_to_bits(rn_hi);
3437 let rm_lo_bits = reg_to_bits(rm_lo);
3438 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3440
3441 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3443 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3444 bytes.extend_from_slice(&hw1.to_le_bytes());
3445 bytes.extend_from_slice(&hw2.to_le_bytes());
3446
3447 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3449 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3450 bytes.extend_from_slice(&hw1.to_le_bytes());
3451 bytes.extend_from_slice(&hw2.to_le_bytes());
3452
3453 let bpl: u16 = 0xD50A;
3455 bytes.extend_from_slice(&bpl.to_le_bytes());
3456
3457 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3460 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3461 bytes.extend_from_slice(&hw1.to_le_bytes());
3462 bytes.extend_from_slice(&hw2.to_le_bytes());
3463
3464 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3466 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3467 bytes.extend_from_slice(&hw1.to_le_bytes());
3468 bytes.extend_from_slice(&hw2.to_le_bytes());
3469
3470 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3472 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3473 bytes.extend_from_slice(&hw1.to_le_bytes());
3474 bytes.extend_from_slice(&hw2.to_le_bytes());
3475
3476 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3478 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3479 bytes.extend_from_slice(&hw1.to_le_bytes());
3480 bytes.extend_from_slice(&hw2.to_le_bytes());
3481
3482 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3484 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3485 bytes.extend_from_slice(&hw1.to_le_bytes());
3486 bytes.extend_from_slice(&hw2.to_le_bytes());
3487
3488 let b_done: u16 = 0xE003;
3490 bytes.extend_from_slice(&b_done.to_le_bytes());
3491
3492 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3495 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3496 bytes.extend_from_slice(&hw1.to_le_bytes());
3497 bytes.extend_from_slice(&hw2.to_le_bytes());
3498
3499 let hw1: u16 = 0xEA4F;
3503 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3504 bytes.extend_from_slice(&hw1.to_le_bytes());
3505 bytes.extend_from_slice(&hw2.to_le_bytes());
3506
3507 Ok(bytes) }
3509
3510 ArmOp::I64Rotl {
3515 rdlo,
3516 rdhi,
3517 rnlo,
3518 rnhi,
3519 shift,
3520 } => {
3521 let rd_lo_bits = reg_to_bits(rdlo);
3522 let rd_hi_bits = reg_to_bits(rdhi);
3523 let rn_lo_bits = reg_to_bits(rnlo);
3524 let rn_hi_bits = reg_to_bits(rnhi);
3525 let shift_bits = reg_to_bits(shift);
3526 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3530
3531 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3533
3534 let hw1: u16 = (0xF000 | shift_bits) as u16;
3536 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3537 bytes.extend_from_slice(&hw1.to_le_bytes());
3538 bytes.extend_from_slice(&hw2.to_le_bytes());
3539
3540 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3542 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3543 bytes.extend_from_slice(&hw1.to_le_bytes());
3544 bytes.extend_from_slice(&hw2.to_le_bytes());
3545
3546 let bpl: u16 = 0xD50E;
3548 bytes.extend_from_slice(&bpl.to_le_bytes());
3549
3550 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3553 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3554 bytes.extend_from_slice(&hw1.to_le_bytes());
3555 bytes.extend_from_slice(&hw2.to_le_bytes());
3556
3557 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3559 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3560 bytes.extend_from_slice(&hw1.to_le_bytes());
3561 bytes.extend_from_slice(&hw2.to_le_bytes());
3562
3563 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3565 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3566 bytes.extend_from_slice(&hw1.to_le_bytes());
3567 bytes.extend_from_slice(&hw2.to_le_bytes());
3568
3569 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3571 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3572 bytes.extend_from_slice(&hw1.to_le_bytes());
3573 bytes.extend_from_slice(&hw2.to_le_bytes());
3574
3575 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3577 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3578 bytes.extend_from_slice(&hw1.to_le_bytes());
3579 bytes.extend_from_slice(&hw2.to_le_bytes());
3580
3581 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3583 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3584 bytes.extend_from_slice(&hw1.to_le_bytes());
3585 bytes.extend_from_slice(&hw2.to_le_bytes());
3586
3587 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3589 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3590 bytes.extend_from_slice(&hw1.to_le_bytes());
3591 bytes.extend_from_slice(&hw2.to_le_bytes());
3592
3593 let b_done: u16 = 0xE00E;
3595 bytes.extend_from_slice(&b_done.to_le_bytes());
3596
3597 let hw1: u16 = (0xF1C0 | r3) as u16;
3601 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3602 bytes.extend_from_slice(&hw1.to_le_bytes());
3603 bytes.extend_from_slice(&hw2.to_le_bytes());
3604
3605 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3607 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3608 bytes.extend_from_slice(&hw1.to_le_bytes());
3609 bytes.extend_from_slice(&hw2.to_le_bytes());
3610
3611 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3613 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3614 bytes.extend_from_slice(&hw1.to_le_bytes());
3615 bytes.extend_from_slice(&hw2.to_le_bytes());
3616
3617 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3619 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3620 bytes.extend_from_slice(&hw1.to_le_bytes());
3621 bytes.extend_from_slice(&hw2.to_le_bytes());
3622
3623 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3625 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3626 bytes.extend_from_slice(&hw1.to_le_bytes());
3627 bytes.extend_from_slice(&hw2.to_le_bytes());
3628
3629 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3631 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3632 bytes.extend_from_slice(&hw1.to_le_bytes());
3633 bytes.extend_from_slice(&hw2.to_le_bytes());
3634
3635 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3637 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3638 bytes.extend_from_slice(&hw1.to_le_bytes());
3639 bytes.extend_from_slice(&hw2.to_le_bytes());
3640
3641 let d_bit = (rd_hi_bits >> 3) & 1;
3643 let mov_instr: u16 =
3644 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3645 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3646
3647 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3649
3650 Ok(bytes) }
3652
3653 ArmOp::I64Rotr {
3658 rdlo,
3659 rdhi,
3660 rnlo,
3661 rnhi,
3662 shift,
3663 } => {
3664 let rd_lo_bits = reg_to_bits(rdlo);
3665 let rd_hi_bits = reg_to_bits(rdhi);
3666 let rn_lo_bits = reg_to_bits(rnlo);
3667 let rn_hi_bits = reg_to_bits(rnhi);
3668 let shift_bits = reg_to_bits(shift);
3669 let r12: u32 = 12;
3670 let r3: u32 = 3;
3671 let r4: u32 = 4;
3672 let mut bytes = Vec::new();
3673
3674 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3676
3677 let hw1: u16 = (0xF000 | shift_bits) as u16;
3679 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3680 bytes.extend_from_slice(&hw1.to_le_bytes());
3681 bytes.extend_from_slice(&hw2.to_le_bytes());
3682
3683 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3685 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3686 bytes.extend_from_slice(&hw1.to_le_bytes());
3687 bytes.extend_from_slice(&hw2.to_le_bytes());
3688
3689 let bpl: u16 = 0xD50E;
3691 bytes.extend_from_slice(&bpl.to_le_bytes());
3692
3693 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3696 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3697 bytes.extend_from_slice(&hw1.to_le_bytes());
3698 bytes.extend_from_slice(&hw2.to_le_bytes());
3699
3700 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3702 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3703 bytes.extend_from_slice(&hw1.to_le_bytes());
3704 bytes.extend_from_slice(&hw2.to_le_bytes());
3705
3706 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3708 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3709 bytes.extend_from_slice(&hw1.to_le_bytes());
3710 bytes.extend_from_slice(&hw2.to_le_bytes());
3711
3712 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3714 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3715 bytes.extend_from_slice(&hw1.to_le_bytes());
3716 bytes.extend_from_slice(&hw2.to_le_bytes());
3717
3718 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3720 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3721 bytes.extend_from_slice(&hw1.to_le_bytes());
3722 bytes.extend_from_slice(&hw2.to_le_bytes());
3723
3724 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3726 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3727 bytes.extend_from_slice(&hw1.to_le_bytes());
3728 bytes.extend_from_slice(&hw2.to_le_bytes());
3729
3730 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3732 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3733 bytes.extend_from_slice(&hw1.to_le_bytes());
3734 bytes.extend_from_slice(&hw2.to_le_bytes());
3735
3736 let b_done: u16 = 0xE00E;
3738 bytes.extend_from_slice(&b_done.to_le_bytes());
3739
3740 let hw1: u16 = (0xF1C0 | r3) as u16;
3743 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3744 bytes.extend_from_slice(&hw1.to_le_bytes());
3745 bytes.extend_from_slice(&hw2.to_le_bytes());
3746
3747 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3749 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3750 bytes.extend_from_slice(&hw1.to_le_bytes());
3751 bytes.extend_from_slice(&hw2.to_le_bytes());
3752
3753 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3755 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3756 bytes.extend_from_slice(&hw1.to_le_bytes());
3757 bytes.extend_from_slice(&hw2.to_le_bytes());
3758
3759 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3761 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3762 bytes.extend_from_slice(&hw1.to_le_bytes());
3763 bytes.extend_from_slice(&hw2.to_le_bytes());
3764
3765 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3767 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3768 bytes.extend_from_slice(&hw1.to_le_bytes());
3769 bytes.extend_from_slice(&hw2.to_le_bytes());
3770
3771 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3773 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3774 bytes.extend_from_slice(&hw1.to_le_bytes());
3775 bytes.extend_from_slice(&hw2.to_le_bytes());
3776
3777 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3779 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3780 bytes.extend_from_slice(&hw1.to_le_bytes());
3781 bytes.extend_from_slice(&hw2.to_le_bytes());
3782
3783 let d_bit = (rd_lo_bits >> 3) & 1;
3785 let mov_instr: u16 =
3786 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3787 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3788
3789 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3791
3792 Ok(bytes) }
3794
3795 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3809 let rd_bits = reg_to_bits(rd);
3810 let rn_lo_bits = reg_to_bits(rnlo);
3811 let rn_hi_bits = reg_to_bits(rnhi);
3812 let mut bytes = Vec::new();
3813
3814 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3816 let hw2: u16 = 0x0F00;
3817 bytes.extend_from_slice(&hw1.to_le_bytes());
3818 bytes.extend_from_slice(&hw2.to_le_bytes());
3819
3820 let beq: u16 = 0xD003;
3823 bytes.extend_from_slice(&beq.to_le_bytes());
3824
3825 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3828 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3829 bytes.extend_from_slice(&hw1.to_le_bytes());
3830 bytes.extend_from_slice(&hw2.to_le_bytes());
3831
3832 let b_done: u16 = 0xE004;
3835 bytes.extend_from_slice(&b_done.to_le_bytes());
3836
3837 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3839
3840 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3844 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3845 bytes.extend_from_slice(&hw1.to_le_bytes());
3846 bytes.extend_from_slice(&hw2.to_le_bytes());
3847
3848 let hw1: u16 = (0xF100 | rd_bits) as u16;
3850 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3851 bytes.extend_from_slice(&hw1.to_le_bytes());
3852 bytes.extend_from_slice(&hw2.to_le_bytes());
3853
3854 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3858 bytes.extend_from_slice(&mov0.to_le_bytes());
3859
3860 Ok(bytes)
3861 }
3862
3863 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3879 let rd_bits = reg_to_bits(rd);
3880 let rn_lo_bits = reg_to_bits(rnlo);
3881 let rn_hi_bits = reg_to_bits(rnhi);
3882 let mut bytes = Vec::new();
3883
3884 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3886 let hw2: u16 = 0x0F00;
3887 bytes.extend_from_slice(&hw1.to_le_bytes());
3888 bytes.extend_from_slice(&hw2.to_le_bytes());
3889
3890 let beq: u16 = 0xD005;
3893 bytes.extend_from_slice(&beq.to_le_bytes());
3894
3895 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3898 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3899 bytes.extend_from_slice(&hw1.to_le_bytes());
3900 bytes.extend_from_slice(&hw2.to_le_bytes());
3901
3902 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3905 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3906 bytes.extend_from_slice(&hw1.to_le_bytes());
3907 bytes.extend_from_slice(&hw2.to_le_bytes());
3908
3909 let b_done: u16 = 0xE006;
3912 bytes.extend_from_slice(&b_done.to_le_bytes());
3913
3914 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3916
3917 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3921 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3922 bytes.extend_from_slice(&hw1.to_le_bytes());
3923 bytes.extend_from_slice(&hw2.to_le_bytes());
3924
3925 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3928 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3929 bytes.extend_from_slice(&hw1.to_le_bytes());
3930 bytes.extend_from_slice(&hw2.to_le_bytes());
3931
3932 let hw1: u16 = (0xF100 | rd_bits) as u16;
3934 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3935 bytes.extend_from_slice(&hw1.to_le_bytes());
3936 bytes.extend_from_slice(&hw2.to_le_bytes());
3937
3938 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3941 bytes.extend_from_slice(&mov0.to_le_bytes());
3942
3943 Ok(bytes)
3944 }
3945
3946 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3950 let rd_bits = reg_to_bits(rd);
3951 let rn_lo_bits = reg_to_bits(rnlo);
3952 let rn_hi_bits = reg_to_bits(rnhi);
3953 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3956
3957 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3959
3960 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3970 bytes.extend_from_slice(&mov.to_le_bytes());
3971
3972 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3975 bytes.extend_from_slice(&mov.to_le_bytes());
3976
3977 let hw1: u16 = 0xEA4F;
3981 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3982 bytes.extend_from_slice(&hw1.to_le_bytes());
3983 bytes.extend_from_slice(&hw2.to_le_bytes());
3984
3985 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3988 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3989 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3991 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3992
3993 let hw1: u16 = (0xEA00 | r12) as u16;
3995 let hw2: u16 = ((r12 << 8) | r3) as u16;
3996 bytes.extend_from_slice(&hw1.to_le_bytes());
3997 bytes.extend_from_slice(&hw2.to_le_bytes());
3998
3999 let hw1: u16 = (0xEBA0 | 4) as u16;
4001 let hw2: u16 = ((4 << 8) | r12) as u16;
4002 bytes.extend_from_slice(&hw1.to_le_bytes());
4003 bytes.extend_from_slice(&hw2.to_le_bytes());
4004
4005 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
4009 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4010 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
4012 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4013
4014 let hw1: u16 = (0xEA00 | 4) as u16;
4016 let hw2: u16 = ((r12 << 8) | r3) as u16;
4017 bytes.extend_from_slice(&hw1.to_le_bytes());
4018 bytes.extend_from_slice(&hw2.to_le_bytes());
4019
4020 let hw1: u16 = 0xEA4F;
4022 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
4023 bytes.extend_from_slice(&hw1.to_le_bytes());
4024 bytes.extend_from_slice(&hw2.to_le_bytes());
4025
4026 let hw1: u16 = (0xEA00 | 4) as u16;
4028 let hw2: u16 = ((4 << 8) | r3) as u16;
4029 bytes.extend_from_slice(&hw1.to_le_bytes());
4030 bytes.extend_from_slice(&hw2.to_le_bytes());
4031
4032 let hw1: u16 = (0xEB00 | 4) as u16;
4034 let hw2: u16 = ((4 << 8) | r12) as u16;
4035 bytes.extend_from_slice(&hw1.to_le_bytes());
4036 bytes.extend_from_slice(&hw2.to_le_bytes());
4037
4038 let hw1: u16 = 0xEA4F;
4043 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
4044 bytes.extend_from_slice(&hw1.to_le_bytes());
4045 bytes.extend_from_slice(&hw2.to_le_bytes());
4046
4047 let hw1: u16 = (0xEB00 | 4) as u16;
4049 let hw2: u16 = ((4 << 8) | r12) as u16;
4050 bytes.extend_from_slice(&hw1.to_le_bytes());
4051 bytes.extend_from_slice(&hw2.to_le_bytes());
4052
4053 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4058 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4059 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4061 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4062
4063 let hw1: u16 = (0xEA00 | 4) as u16;
4065 let hw2: u16 = ((4 << 8) | r3) as u16;
4066 bytes.extend_from_slice(&hw1.to_le_bytes());
4067 bytes.extend_from_slice(&hw2.to_le_bytes());
4068
4069 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4073 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4074 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4076 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4077
4078 let hw1: u16 = (0xFB00 | 4) as u16;
4081 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
4082 bytes.extend_from_slice(&hw1.to_le_bytes());
4083 bytes.extend_from_slice(&hw2.to_le_bytes());
4084
4085 let hw1: u16 = 0xEA4F;
4088 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
4089 bytes.extend_from_slice(&hw1.to_le_bytes());
4090 bytes.extend_from_slice(&hw2.to_le_bytes());
4091
4092 let hw1: u16 = 0xEA4F;
4095 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
4096 bytes.extend_from_slice(&hw1.to_le_bytes());
4097 bytes.extend_from_slice(&hw2.to_le_bytes());
4098
4099 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
4101 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
4102 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
4103 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
4104
4105 let hw1: u16 = (0xEA00 | r12) as u16;
4106 let hw2: u16 = ((r12 << 8) | r3) as u16;
4107 bytes.extend_from_slice(&hw1.to_le_bytes());
4108 bytes.extend_from_slice(&hw2.to_le_bytes());
4109
4110 let hw1: u16 = (0xEBA0 | 5) as u16;
4111 let hw2: u16 = ((5 << 8) | r12) as u16;
4112 bytes.extend_from_slice(&hw1.to_le_bytes());
4113 bytes.extend_from_slice(&hw2.to_le_bytes());
4114
4115 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
4117 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4118 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
4119 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4120
4121 let hw1: u16 = (0xEA00 | 5) as u16;
4122 let hw2: u16 = ((r12 << 8) | r3) as u16;
4123 bytes.extend_from_slice(&hw1.to_le_bytes());
4124 bytes.extend_from_slice(&hw2.to_le_bytes());
4125
4126 let hw1: u16 = 0xEA4F;
4127 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
4128 bytes.extend_from_slice(&hw1.to_le_bytes());
4129 bytes.extend_from_slice(&hw2.to_le_bytes());
4130
4131 let hw1: u16 = (0xEA00 | 5) as u16;
4132 let hw2: u16 = ((5 << 8) | r3) as u16;
4133 bytes.extend_from_slice(&hw1.to_le_bytes());
4134 bytes.extend_from_slice(&hw2.to_le_bytes());
4135
4136 let hw1: u16 = (0xEB00 | 5) as u16;
4137 let hw2: u16 = ((5 << 8) | r12) as u16;
4138 bytes.extend_from_slice(&hw1.to_le_bytes());
4139 bytes.extend_from_slice(&hw2.to_le_bytes());
4140
4141 let hw1: u16 = 0xEA4F;
4144 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
4145 bytes.extend_from_slice(&hw1.to_le_bytes());
4146 bytes.extend_from_slice(&hw2.to_le_bytes());
4147
4148 let hw1: u16 = (0xEB00 | 5) as u16;
4149 let hw2: u16 = ((5 << 8) | r12) as u16;
4150 bytes.extend_from_slice(&hw1.to_le_bytes());
4151 bytes.extend_from_slice(&hw2.to_le_bytes());
4152
4153 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4155 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4156 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4157 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4158
4159 let hw1: u16 = (0xEA00 | 5) as u16;
4160 let hw2: u16 = ((5 << 8) | r3) as u16;
4161 bytes.extend_from_slice(&hw1.to_le_bytes());
4162 bytes.extend_from_slice(&hw2.to_le_bytes());
4163
4164 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4166 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4167 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4168 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4169
4170 let hw1: u16 = (0xFB00 | 5) as u16;
4173 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
4174 bytes.extend_from_slice(&hw1.to_le_bytes());
4175 bytes.extend_from_slice(&hw2.to_le_bytes());
4176
4177 let hw1: u16 = 0xEA4F;
4180 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
4181 bytes.extend_from_slice(&hw1.to_le_bytes());
4182 bytes.extend_from_slice(&hw2.to_le_bytes());
4183
4184 let rd_bits_u16 = rd_bits as u16;
4187 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4188 bytes.extend_from_slice(&instr.to_le_bytes());
4189
4190 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4192
4193 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4195 bytes.extend_from_slice(&mov0.to_le_bytes());
4196
4197 Ok(bytes)
4198 }
4199
4200 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4203 let rdlo_bits = reg_to_bits(rdlo);
4204 let rdhi_bits = reg_to_bits(rdhi);
4205 let rnlo_bits = reg_to_bits(rnlo);
4206 let mut bytes = Vec::new();
4207
4208 let hw1: u16 = 0xFA4F_u16;
4211 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4212 bytes.extend_from_slice(&hw1.to_le_bytes());
4213 bytes.extend_from_slice(&hw2.to_le_bytes());
4214
4215 let hw1: u16 = 0xEA4F;
4220 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4221 bytes.extend_from_slice(&hw1.to_le_bytes());
4222 bytes.extend_from_slice(&hw2.to_le_bytes());
4223
4224 Ok(bytes)
4225 }
4226
4227 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4230 let rdlo_bits = reg_to_bits(rdlo);
4231 let rdhi_bits = reg_to_bits(rdhi);
4232 let rnlo_bits = reg_to_bits(rnlo);
4233 let mut bytes = Vec::new();
4234
4235 let hw1: u16 = 0xFA0F_u16;
4238 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4239 bytes.extend_from_slice(&hw1.to_le_bytes());
4240 bytes.extend_from_slice(&hw2.to_le_bytes());
4241
4242 let hw1: u16 = 0xEA4F;
4244 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4245 bytes.extend_from_slice(&hw1.to_le_bytes());
4246 bytes.extend_from_slice(&hw2.to_le_bytes());
4247
4248 Ok(bytes)
4249 }
4250
4251 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4254 let rdlo_bits = reg_to_bits(rdlo);
4255 let rdhi_bits = reg_to_bits(rdhi);
4256 let rnlo_bits = reg_to_bits(rnlo);
4257 let mut bytes = Vec::new();
4258
4259 if rdlo_bits != rnlo_bits {
4261 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4263 let mov: u16 = 0x4600
4264 | (d_bit << 7)
4265 | ((rnlo_bits as u16) << 3)
4266 | ((rdlo_bits & 0x7) as u16);
4267 bytes.extend_from_slice(&mov.to_le_bytes());
4268 }
4269
4270 let hw1: u16 = 0xEA4F;
4272 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4273 bytes.extend_from_slice(&hw1.to_le_bytes());
4274 bytes.extend_from_slice(&hw2.to_le_bytes());
4275
4276 Ok(bytes)
4277 }
4278
4279 ArmOp::SelectMove { rd, rm, cond } => {
4282 let rd_bits = reg_to_bits(rd) as u16;
4283 let rm_bits = reg_to_bits(rm) as u16;
4284
4285 use synth_synthesis::Condition;
4287 let cond_bits: u16 = match cond {
4288 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, };
4299
4300 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4303
4304 let d_bit = (rd_bits >> 3) & 1;
4307 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4308
4309 let mut bytes = it_instr.to_le_bytes().to_vec();
4311 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4312 Ok(bytes)
4313 }
4314
4315 ArmOp::Popcnt { rd, rm } => {
4326 let mut bytes = Vec::new();
4327
4328 if rd != rm {
4330 let rd_bits = reg_to_bits(rd) as u16;
4331 let rm_bits = reg_to_bits(rm) as u16;
4332 let d_bit = (rd_bits >> 3) & 1;
4334 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4335 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4336 }
4337
4338 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4341 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4342
4343 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4346
4347 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4349
4350 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4352 reg_to_bits(rd),
4353 reg_to_bits(rd),
4354 11,
4355 )?);
4356
4357 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4360 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4361
4362 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4364 11,
4365 reg_to_bits(rd),
4366 12,
4367 )?);
4368
4369 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4371 reg_to_bits(rd),
4372 reg_to_bits(rd),
4373 2,
4374 )?);
4375
4376 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4378 reg_to_bits(rd),
4379 reg_to_bits(rd),
4380 12,
4381 )?);
4382
4383 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4385 reg_to_bits(rd),
4386 reg_to_bits(rd),
4387 11,
4388 )?);
4389
4390 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4393
4394 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4396 reg_to_bits(rd),
4397 reg_to_bits(rd),
4398 11,
4399 )?);
4400
4401 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4403 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4404
4405 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4407 reg_to_bits(rd),
4408 reg_to_bits(rd),
4409 12,
4410 )?);
4411
4412 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4415
4416 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4418 reg_to_bits(rd),
4419 reg_to_bits(rd),
4420 11,
4421 )?);
4422
4423 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4426
4427 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4429 reg_to_bits(rd),
4430 reg_to_bits(rd),
4431 11,
4432 )?);
4433
4434 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4437 reg_to_bits(rd),
4438 reg_to_bits(rd),
4439 0x3F,
4440 )?);
4441
4442 Ok(bytes)
4443 }
4444
4445 ArmOp::I64DivU {
4450 rdlo: _,
4451 rdhi: _,
4452 rnlo: _,
4453 rnhi: _,
4454 rmlo: _,
4455 rmhi: _,
4456 } => {
4457 let mut bytes = Vec::new();
4458
4459 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4463
4464 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());
4475 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4476
4477 let loop_start = bytes.len();
4479
4480 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4491 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());
4500 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4501 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4505 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4506
4507 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4512 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4513 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());
4544 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4545 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4548
4549 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4553 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4554
4555 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4558 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4559 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4560
4561 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4569
4570 Ok(bytes)
4571 }
4572
4573 ArmOp::I64DivS {
4578 rdlo: _,
4579 rdhi: _,
4580 rnlo: _,
4581 rnhi: _,
4582 rmlo: _,
4583 rmhi: _,
4584 } => {
4585 let mut bytes = Vec::new();
4586
4587 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4589 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4590
4591 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4594 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4595
4596 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());
4609
4610 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());
4620
4621 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4624 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4625 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4627 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4628 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4630 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4631
4632 let loop_start = bytes.len();
4633
4634 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4638 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());
4644 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4647
4648 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4652 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());
4665 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4667
4668 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4671
4672 let branch_offset_bytes = bytes.len() - loop_start + 4;
4673 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4674 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4675 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4676
4677 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());
4684 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());
4692
4693 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4695 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4696
4697 Ok(bytes)
4698 }
4699
4700 ArmOp::I64RemU {
4705 rdlo: _,
4706 rdhi: _,
4707 rnlo: _,
4708 rnhi: _,
4709 rmlo: _,
4710 rmhi: _,
4711 } => {
4712 let mut bytes = Vec::new();
4713
4714 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4716 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4717
4718 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4720 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4721 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4723 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4724 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4726 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4727
4728 let loop_start = bytes.len();
4729
4730 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4734 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());
4740 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4743
4744 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4748 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());
4761 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4763
4764 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4767
4768 let branch_offset_bytes = bytes.len() - loop_start + 4;
4769 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4770 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4771 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4772
4773 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4779 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4780
4781 Ok(bytes)
4782 }
4783
4784 ArmOp::I64RemS {
4789 rdlo: _,
4790 rdhi: _,
4791 rnlo: _,
4792 rnhi: _,
4793 rmlo: _,
4794 rmhi: _,
4795 } => {
4796 let mut bytes = Vec::new();
4797
4798 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4800 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4801
4802 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());
4816
4817 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());
4827
4828 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4831 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4832 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4834 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4835 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4837 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4838
4839 let loop_start = bytes.len();
4840
4841 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4845 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());
4851 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4854
4855 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4859 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());
4872 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4874
4875 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4878
4879 let branch_offset_bytes = bytes.len() - loop_start + 4;
4880 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4881 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4882 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4883
4884 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());
4891 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());
4899
4900 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4902 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4903
4904 Ok(bytes)
4905 }
4906
4907 ArmOp::F32Add { sd, sn, sm } => {
4910 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4911 }
4912 ArmOp::F32Sub { sd, sn, sm } => {
4913 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4914 }
4915 ArmOp::F32Mul { sd, sn, sm } => {
4916 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4917 }
4918 ArmOp::F32Div { sd, sn, sm } => {
4919 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4920 }
4921 ArmOp::F32Abs { sd, sm } => {
4922 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4923 }
4924 ArmOp::F32Neg { sd, sm } => {
4925 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4926 }
4927 ArmOp::F32Sqrt { sd, sm } => {
4928 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4929 }
4930
4931 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4934 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4935 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4936 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4937 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4938 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4939 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4940
4941 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4943 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4944 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4945 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4946 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4947 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4948
4949 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4950
4951 ArmOp::F32Load { sd, addr } => {
4952 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4953 }
4954 ArmOp::F32Store { sd, addr } => {
4955 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4956 }
4957
4958 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4959 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4960 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4961 Err(synth_core::Error::synthesis(
4962 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4963 ))
4964 }
4965 ArmOp::F32ReinterpretI32 { sd, rm } => {
4966 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4967 }
4968 ArmOp::I32ReinterpretF32 { rd, sm } => {
4969 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4970 }
4971 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4972 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4973
4974 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4977 0xEE300B00, dd, dn, dm,
4978 )?)),
4979 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4980 0xEE300B40, dd, dn, dm,
4981 )?)),
4982 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4983 0xEE200B00, dd, dn, dm,
4984 )?)),
4985 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4986 0xEE800B00, dd, dn, dm,
4987 )?)),
4988 ArmOp::F64Abs { dd, dm } => {
4989 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4990 }
4991 ArmOp::F64Neg { dd, dm } => {
4992 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4993 }
4994 ArmOp::F64Sqrt { dd, dm } => {
4995 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4996 }
4997
4998 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
5001 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
5002 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
5003 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
5004 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
5005 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
5006 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
5007
5008 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
5010 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
5011 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
5012 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
5013 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
5014 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
5015
5016 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
5017
5018 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
5019 0xED900B00, dd, addr,
5020 )?)),
5021 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
5022 0xED800B00, dd, addr,
5023 )?)),
5024
5025 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
5026 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
5027 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
5028 Err(synth_core::Error::synthesis(
5029 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
5030 ))
5031 }
5032 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
5033 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
5034 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
5035 )),
5036 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
5037 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
5038 )),
5039 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
5040 Err(synth_core::Error::synthesis(
5041 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
5042 ))
5043 }
5044 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
5045 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
5046
5047 ArmOp::I64Add {
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::Adds {
5061 rd: *rdlo,
5062 rn: *rnlo,
5063 op2: Operand2::Reg(*rmlo),
5064 })?);
5065 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
5067 rd: *rdhi,
5068 rn: *rnhi,
5069 op2: Operand2::Reg(*rmhi),
5070 })?);
5071 Ok(bytes)
5072 }
5073
5074 ArmOp::I64Sub {
5076 rdlo,
5077 rdhi,
5078 rnlo,
5079 rnhi,
5080 rmlo,
5081 rmhi,
5082 } => {
5083 let mut bytes = Vec::new();
5084 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
5086 rd: *rdlo,
5087 rn: *rnlo,
5088 op2: Operand2::Reg(*rmlo),
5089 })?);
5090 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
5092 rd: *rdhi,
5093 rn: *rnhi,
5094 op2: Operand2::Reg(*rmhi),
5095 })?);
5096 Ok(bytes)
5097 }
5098
5099 ArmOp::I64And {
5101 rdlo,
5102 rdhi,
5103 rnlo,
5104 rnhi,
5105 rmlo,
5106 rmhi,
5107 } => {
5108 let mut bytes = Vec::new();
5109 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5110 rd: *rdlo,
5111 rn: *rnlo,
5112 op2: Operand2::Reg(*rmlo),
5113 })?);
5114 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5115 rd: *rdhi,
5116 rn: *rnhi,
5117 op2: Operand2::Reg(*rmhi),
5118 })?);
5119 Ok(bytes)
5120 }
5121
5122 ArmOp::I64Or {
5124 rdlo,
5125 rdhi,
5126 rnlo,
5127 rnhi,
5128 rmlo,
5129 rmhi,
5130 } => {
5131 let mut bytes = Vec::new();
5132 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5133 rd: *rdlo,
5134 rn: *rnlo,
5135 op2: Operand2::Reg(*rmlo),
5136 })?);
5137 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5138 rd: *rdhi,
5139 rn: *rnhi,
5140 op2: Operand2::Reg(*rmhi),
5141 })?);
5142 Ok(bytes)
5143 }
5144
5145 ArmOp::I64Xor {
5147 rdlo,
5148 rdhi,
5149 rnlo,
5150 rnhi,
5151 rmlo,
5152 rmhi,
5153 } => {
5154 let mut bytes = Vec::new();
5155 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5156 rd: *rdlo,
5157 rn: *rnlo,
5158 op2: Operand2::Reg(*rmlo),
5159 })?);
5160 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5161 rd: *rdhi,
5162 rn: *rnhi,
5163 op2: Operand2::Reg(*rmhi),
5164 })?);
5165 Ok(bytes)
5166 }
5167
5168 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
5170 rd: *rd,
5171 rn_lo: *rnlo,
5172 rn_hi: *rnhi,
5173 }),
5174
5175 ArmOp::I64Eq {
5177 rd,
5178 rnlo,
5179 rnhi,
5180 rmlo,
5181 rmhi,
5182 } => self.encode_thumb(&ArmOp::I64SetCond {
5183 rd: *rd,
5184 rn_lo: *rnlo,
5185 rn_hi: *rnhi,
5186 rm_lo: *rmlo,
5187 rm_hi: *rmhi,
5188 cond: synth_synthesis::Condition::EQ,
5189 }),
5190
5191 ArmOp::I64Ne {
5192 rd,
5193 rnlo,
5194 rnhi,
5195 rmlo,
5196 rmhi,
5197 } => self.encode_thumb(&ArmOp::I64SetCond {
5198 rd: *rd,
5199 rn_lo: *rnlo,
5200 rn_hi: *rnhi,
5201 rm_lo: *rmlo,
5202 rm_hi: *rmhi,
5203 cond: synth_synthesis::Condition::NE,
5204 }),
5205
5206 ArmOp::I64LtS {
5207 rd,
5208 rnlo,
5209 rnhi,
5210 rmlo,
5211 rmhi,
5212 } => self.encode_thumb(&ArmOp::I64SetCond {
5213 rd: *rd,
5214 rn_lo: *rnlo,
5215 rn_hi: *rnhi,
5216 rm_lo: *rmlo,
5217 rm_hi: *rmhi,
5218 cond: synth_synthesis::Condition::LT,
5219 }),
5220
5221 ArmOp::I64LtU {
5222 rd,
5223 rnlo,
5224 rnhi,
5225 rmlo,
5226 rmhi,
5227 } => self.encode_thumb(&ArmOp::I64SetCond {
5228 rd: *rd,
5229 rn_lo: *rnlo,
5230 rn_hi: *rnhi,
5231 rm_lo: *rmlo,
5232 rm_hi: *rmhi,
5233 cond: synth_synthesis::Condition::LO,
5234 }),
5235
5236 ArmOp::I64LeS {
5237 rd,
5238 rnlo,
5239 rnhi,
5240 rmlo,
5241 rmhi,
5242 } => self.encode_thumb(&ArmOp::I64SetCond {
5243 rd: *rd,
5244 rn_lo: *rnlo,
5245 rn_hi: *rnhi,
5246 rm_lo: *rmlo,
5247 rm_hi: *rmhi,
5248 cond: synth_synthesis::Condition::LE,
5249 }),
5250
5251 ArmOp::I64LeU {
5252 rd,
5253 rnlo,
5254 rnhi,
5255 rmlo,
5256 rmhi,
5257 } => self.encode_thumb(&ArmOp::I64SetCond {
5258 rd: *rd,
5259 rn_lo: *rnlo,
5260 rn_hi: *rnhi,
5261 rm_lo: *rmlo,
5262 rm_hi: *rmhi,
5263 cond: synth_synthesis::Condition::LS,
5264 }),
5265
5266 ArmOp::I64GtS {
5267 rd,
5268 rnlo,
5269 rnhi,
5270 rmlo,
5271 rmhi,
5272 } => self.encode_thumb(&ArmOp::I64SetCond {
5273 rd: *rd,
5274 rn_lo: *rnlo,
5275 rn_hi: *rnhi,
5276 rm_lo: *rmlo,
5277 rm_hi: *rmhi,
5278 cond: synth_synthesis::Condition::GT,
5279 }),
5280
5281 ArmOp::I64GtU {
5282 rd,
5283 rnlo,
5284 rnhi,
5285 rmlo,
5286 rmhi,
5287 } => self.encode_thumb(&ArmOp::I64SetCond {
5288 rd: *rd,
5289 rn_lo: *rnlo,
5290 rn_hi: *rnhi,
5291 rm_lo: *rmlo,
5292 rm_hi: *rmhi,
5293 cond: synth_synthesis::Condition::HI,
5294 }),
5295
5296 ArmOp::I64GeS {
5297 rd,
5298 rnlo,
5299 rnhi,
5300 rmlo,
5301 rmhi,
5302 } => self.encode_thumb(&ArmOp::I64SetCond {
5303 rd: *rd,
5304 rn_lo: *rnlo,
5305 rn_hi: *rnhi,
5306 rm_lo: *rmlo,
5307 rm_hi: *rmhi,
5308 cond: synth_synthesis::Condition::GE,
5309 }),
5310
5311 ArmOp::I64GeU {
5312 rd,
5313 rnlo,
5314 rnhi,
5315 rmlo,
5316 rmhi,
5317 } => self.encode_thumb(&ArmOp::I64SetCond {
5318 rd: *rd,
5319 rn_lo: *rnlo,
5320 rn_hi: *rnhi,
5321 rm_lo: *rmlo,
5322 rm_hi: *rmhi,
5323 cond: synth_synthesis::Condition::HS,
5324 }),
5325
5326 ArmOp::I64Const { rdlo, rdhi, value } => {
5328 let lo32 = *value as u32;
5329 let hi32 = (*value >> 32) as u32;
5330 let mut bytes = Vec::new();
5331 bytes.extend_from_slice(
5333 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5334 );
5335 if lo32 > 0xFFFF {
5336 bytes.extend_from_slice(
5337 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5338 );
5339 }
5340 bytes.extend_from_slice(
5342 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5343 );
5344 if hi32 > 0xFFFF {
5345 bytes.extend_from_slice(
5346 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5347 );
5348 }
5349 Ok(bytes)
5350 }
5351
5352 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5354 let mut bytes = Vec::new();
5355 let (base, offset) = self.i64_effective_base(&mut bytes, addr)?;
5366 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &base, offset)?);
5367 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5368 rdhi,
5369 &base,
5370 offset.wrapping_add(4),
5371 )?);
5372 Ok(bytes)
5373 }
5374
5375 ArmOp::I64Str { rdlo, rdhi, addr } => {
5377 let mut bytes = Vec::new();
5378 let (base, offset) = self.i64_effective_base(&mut bytes, addr)?;
5381 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &base, offset)?);
5382 bytes.extend_from_slice(&self.encode_thumb32_str(
5383 rdhi,
5384 &base,
5385 offset.wrapping_add(4),
5386 )?);
5387 Ok(bytes)
5388 }
5389
5390 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5392 let mut bytes = Vec::new();
5393 if rdlo != rn {
5394 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5396 rd: *rdlo,
5397 op2: Operand2::Reg(*rn),
5398 })?);
5399 }
5400 bytes.extend_from_slice(
5402 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5404 Ok(bytes)
5405 }
5406
5407 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5409 let mut bytes = Vec::new();
5410 if rdlo != rn {
5411 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5413 rd: *rdlo,
5414 op2: Operand2::Reg(*rn),
5415 })?);
5416 }
5417 let rdhi_bits = reg_to_bits(rdhi) as u16;
5419 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5420 bytes.extend_from_slice(&instr.to_le_bytes());
5421 Ok(bytes)
5422 }
5423
5424 ArmOp::I32WrapI64 { rd, rnlo } => {
5426 if rd == rnlo {
5427 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5430 } else {
5431 self.encode_thumb(&ArmOp::Mov {
5433 rd: *rd,
5434 op2: Operand2::Reg(*rnlo),
5435 })
5436 }
5437 }
5438
5439 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5441 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5442 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5443 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5444 0xEF000150, qd, qn, qm,
5445 ))),
5446 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5447 0xEF200150, qd, qn, qm,
5448 ))),
5449 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5450 0xFF000150, qd, qn, qm,
5451 ))),
5452 ArmOp::MveMvn { qd, qm } => {
5453 let qd_enc = qreg_to_num(qd);
5455 let qm_enc = qreg_to_num(qm);
5456 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5457 Ok(vfp_to_thumb_bytes(instr))
5458 }
5459 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5460 0xEF100150, qd, qn, qm,
5461 ))),
5462 ArmOp::MveAddI { qd, qn, qm, size } => {
5463 let sz = mve_size_bits(size);
5464 let base: u32 = 0xEF000840 | (sz << 20);
5465 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5466 }
5467 ArmOp::MveSubI { qd, qn, qm, size } => {
5468 let sz = mve_size_bits(size);
5469 let base: u32 = 0xFF000840 | (sz << 20);
5470 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5471 }
5472 ArmOp::MveMulI { qd, qn, qm, size } => {
5473 let sz = mve_size_bits(size);
5474 let base: u32 = 0xEF000950 | (sz << 20);
5475 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5476 }
5477 ArmOp::MveNegI { qd, qm, size } => {
5478 let sz = mve_size_bits(size);
5479 let qd_enc = qreg_to_num(qd);
5481 let qm_enc = qreg_to_num(qm);
5482 let base: u32 = 0xFFB103C0 | (sz << 18);
5483 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5484 Ok(vfp_to_thumb_bytes(instr))
5485 }
5486 ArmOp::MveDup { qd, rn, size } => {
5487 let sz = mve_size_bits(size);
5488 let qd_enc = qreg_to_num(qd);
5489 let rn_bits = reg_to_bits(rn);
5490 let be = match sz {
5493 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5497 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5498 Ok(vfp_to_thumb_bytes(instr))
5499 }
5500 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5501 let qn_enc = qreg_to_num(qn);
5502 let rd_bits = reg_to_bits(rd);
5503 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5506 let lane_in_d = (*lane as u32) & 1;
5507 let _sz = mve_size_bits(size);
5508 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5510 Ok(vfp_to_thumb_bytes(instr))
5511 }
5512 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5513 let qd_enc = qreg_to_num(qd);
5514 let rn_bits = reg_to_bits(rn);
5515 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5516 let lane_in_d = (*lane as u32) & 1;
5517 let _sz = mve_size_bits(size);
5518 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5520 Ok(vfp_to_thumb_bytes(instr))
5521 }
5522
5523 ArmOp::MveCmpEqI { qd, qn, qm, size }
5525 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5526 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5527 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5528 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5529 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5530 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5531 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5532 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5533 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5534 let sz = mve_size_bits(size);
5537 let base: u32 = 0xEF000840 | (sz << 20);
5538 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5539 }
5540
5541 ArmOp::MveAddF32 { qd, qn, qm } => {
5543 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5545 }
5546 ArmOp::MveSubF32 { qd, qn, qm } => {
5547 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5549 }
5550 ArmOp::MveMulF32 { qd, qn, qm } => {
5551 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5553 }
5554 ArmOp::MveNegF32 { qd, qm } => {
5555 let qd_enc = qreg_to_num(qd);
5556 let qm_enc = qreg_to_num(qm);
5557 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5559 Ok(vfp_to_thumb_bytes(instr))
5560 }
5561 ArmOp::MveAbsF32 { qd, qm } => {
5562 let qd_enc = qreg_to_num(qd);
5563 let qm_enc = qreg_to_num(qm);
5564 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5566 Ok(vfp_to_thumb_bytes(instr))
5567 }
5568 ArmOp::MveCmpEqF32 { qd, qn, qm }
5569 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5570 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5571 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5572 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5573 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5574 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5576 }
5577 ArmOp::MveDupF32 { qd, rn } => {
5578 let qd_enc = qreg_to_num(qd);
5579 let rn_bits = reg_to_bits(rn);
5580 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5582 Ok(vfp_to_thumb_bytes(instr))
5583 }
5584 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5585 let qn_enc = qreg_to_num(qn);
5586 let rd_bits = reg_to_bits(rd);
5587 let s_num = qn_enc * 4 + (*lane as u32);
5589 let (vn, n) = encode_sreg(s_num);
5590 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5591 Ok(vfp_to_thumb_bytes(instr))
5592 }
5593 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5594 let qd_enc = qreg_to_num(qd);
5595 let rn_bits = reg_to_bits(rn);
5596 let s_num = qd_enc * 4 + (*lane as u32);
5598 let (vn, n) = encode_sreg(s_num);
5599 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5600 Ok(vfp_to_thumb_bytes(instr))
5601 }
5602 ArmOp::MveDivF32 { qd, qn, qm } => {
5603 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5605 }
5606 ArmOp::MveSqrtF32 { qd, qm } => {
5607 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5609 }
5610
5611 _ => {
5613 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5615 }
5616 }
5617 }
5618
5619 fn encode_thumb_f32_compare(
5623 &self,
5624 rd: &Reg,
5625 sn: &VfpReg,
5626 sm: &VfpReg,
5627 cond_code: u32,
5628 ) -> Result<Vec<u8>> {
5629 let mut bytes = Vec::new();
5630 let rd_bits = reg_to_bits(rd);
5631
5632 let sn_num = vfp_sreg_to_num(sn)?;
5634 let sm_num = vfp_sreg_to_num(sm)?;
5635 let (vd, d) = encode_sreg(sn_num);
5636 let (vm, m) = encode_sreg(sm_num);
5637 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5638 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5639
5640 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5642
5643 if rd_bits < 8 {
5645 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5646 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5647 } else {
5648 let hw1: u16 = 0xF04F;
5650 let hw2: u16 = (rd_bits as u16) << 8;
5651 bytes.extend_from_slice(&hw1.to_le_bytes());
5652 bytes.extend_from_slice(&hw2.to_le_bytes());
5653 }
5654
5655 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5659 bytes.extend_from_slice(&it.to_le_bytes());
5660
5661 if rd_bits < 8 {
5663 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5664 bytes.extend_from_slice(&mov_one.to_le_bytes());
5665 } else {
5666 let hw1: u16 = 0xF04F;
5668 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5669 bytes.extend_from_slice(&hw1.to_le_bytes());
5670 bytes.extend_from_slice(&hw2.to_le_bytes());
5671 }
5672
5673 Ok(bytes)
5674 }
5675
5676 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5678 let mut bytes = Vec::new();
5679 let bits = value.to_bits();
5680 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5685 let imm4 = (lo16 >> 12) & 0xF;
5686 let i_bit = (lo16 >> 11) & 1;
5687 let imm3 = (lo16 >> 8) & 0x7;
5688 let imm8 = lo16 & 0xFF;
5689 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5690 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5691 bytes.extend_from_slice(&hw1.to_le_bytes());
5692 bytes.extend_from_slice(&hw2.to_le_bytes());
5693
5694 let hi16 = (bits >> 16) & 0xFFFF;
5696 let imm4 = (hi16 >> 12) & 0xF;
5697 let i_bit = (hi16 >> 11) & 1;
5698 let imm3 = (hi16 >> 8) & 0x7;
5699 let imm8 = hi16 & 0xFF;
5700 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5701 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5702 bytes.extend_from_slice(&hw1.to_le_bytes());
5703 bytes.extend_from_slice(&hw2.to_le_bytes());
5704
5705 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5707 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5708
5709 Ok(bytes)
5710 }
5711
5712 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5714 let mut bytes = Vec::new();
5715
5716 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5718 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5719
5720 let sd_num = vfp_sreg_to_num(sd)?;
5722 let (vd, d) = encode_sreg(sd_num);
5723 let (vm, m) = encode_sreg(sd_num);
5724 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5725 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5726 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5727
5728 Ok(bytes)
5729 }
5730
5731 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5739 let mut bytes = Vec::new();
5740 let sm_num = vfp_sreg_to_num(sm)?;
5741 let sd_num = vfp_sreg_to_num(sd)?;
5742 let (vd_s, d_s) = encode_sreg(sd_num);
5743 let (vm_s, m_s) = encode_sreg(sm_num);
5744
5745 if mode == 0b11 {
5746 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5748 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5749 } else {
5750 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5755 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5756
5757 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5763 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5764 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5765
5766 if mode != 0 {
5768 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5770 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5771 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5772 }
5773
5774 let vmsr = 0xEEE10A10 | (rt << 12);
5776 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5777
5778 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5780 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5781
5782 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5784 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5785 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5786 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5787 }
5788
5789 let (vd2, d2) = encode_sreg(sd_num);
5791 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5792 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5793
5794 Ok(bytes)
5795 }
5796
5797 fn encode_thumb_f32_minmax(
5799 &self,
5800 sd: &VfpReg,
5801 sn: &VfpReg,
5802 sm: &VfpReg,
5803 is_min: bool,
5804 ) -> Result<Vec<u8>> {
5805 let mut bytes = Vec::new();
5806 let sn_num = vfp_sreg_to_num(sn)?;
5807 let sm_num = vfp_sreg_to_num(sm)?;
5808 let sd_num = vfp_sreg_to_num(sd)?;
5809
5810 let (vd, d) = encode_sreg(sd_num);
5812 let (vn, n) = encode_sreg(sn_num);
5813 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5814 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5815
5816 let (vm, m) = encode_sreg(sm_num);
5818 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5819 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5820
5821 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5823
5824 let cond: u16 = if is_min { 0xC } else { 0x4 };
5826 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5827 bytes.extend_from_slice(&it.to_le_bytes());
5828
5829 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5831 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5832
5833 Ok(bytes)
5834 }
5835
5836 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5838 let mut bytes = Vec::new();
5839
5840 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5842 false,
5843 sm,
5844 &Reg::R12,
5845 )?));
5846
5847 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5849 false,
5850 sn,
5851 &Reg::R0,
5852 )?));
5853
5854 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5866 bytes.extend_from_slice(&hw2.to_le_bytes());
5867
5868 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5872 bytes.extend_from_slice(&hw2.to_le_bytes());
5873
5874 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5878 bytes.extend_from_slice(&hw2.to_le_bytes());
5879
5880 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5882 true,
5883 sd,
5884 &Reg::R0,
5885 )?));
5886
5887 Ok(bytes)
5888 }
5889
5890 fn encode_thumb_f64_compare(
5892 &self,
5893 rd: &Reg,
5894 dn: &VfpReg,
5895 dm: &VfpReg,
5896 cond_code: u32,
5897 ) -> Result<Vec<u8>> {
5898 let mut bytes = Vec::new();
5899 let rd_bits = reg_to_bits(rd);
5900
5901 let dn_num = vfp_dreg_to_num(dn)?;
5903 let dm_num = vfp_dreg_to_num(dm)?;
5904 let (vd, d) = encode_dreg(dn_num);
5905 let (vm, m) = encode_dreg(dm_num);
5906 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5907 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5908
5909 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5911
5912 if rd_bits < 8 {
5914 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5915 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5916 } else {
5917 let hw1: u16 = 0xF04F;
5918 let hw2: u16 = (rd_bits as u16) << 8;
5919 bytes.extend_from_slice(&hw1.to_le_bytes());
5920 bytes.extend_from_slice(&hw2.to_le_bytes());
5921 }
5922
5923 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5925 bytes.extend_from_slice(&it.to_le_bytes());
5926
5927 if rd_bits < 8 {
5929 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5930 bytes.extend_from_slice(&mov_one.to_le_bytes());
5931 } else {
5932 let hw1: u16 = 0xF04F;
5933 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5934 bytes.extend_from_slice(&hw1.to_le_bytes());
5935 bytes.extend_from_slice(&hw2.to_le_bytes());
5936 }
5937
5938 Ok(bytes)
5939 }
5940
5941 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5943 let mut bytes = Vec::new();
5944 let bits = value.to_bits();
5945 let lo32 = bits as u32;
5946 let hi32 = (bits >> 32) as u32;
5947
5948 let lo16 = lo32 & 0xFFFF;
5950 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5951
5952 let hi16 = (lo32 >> 16) & 0xFFFF;
5954 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5955
5956 let lo16 = hi32 & 0xFFFF;
5958 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5959
5960 let hi16 = (hi32 >> 16) & 0xFFFF;
5962 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5963
5964 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5966 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5967
5968 Ok(bytes)
5969 }
5970
5971 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5973 let mut bytes = Vec::new();
5974
5975 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5977 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5978
5979 let dd_num = vfp_dreg_to_num(dd)?;
5981 let (vd, d) = encode_dreg(dd_num);
5982 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5983 let vcvt = base | (d << 22) | (vd << 12);
5984 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5985
5986 Ok(bytes)
5987 }
5988
5989 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5991 let dd_num = vfp_dreg_to_num(dd)?;
5992 let sm_num = vfp_sreg_to_num(sm)?;
5993 let (vd, d) = encode_dreg(dd_num);
5994 let (vm, m) = encode_sreg(sm_num);
5995
5996 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5997 Ok(vfp_to_thumb_bytes(vcvt))
5998 }
5999
6000 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6002 let mut bytes = Vec::new();
6003 let dm_num = vfp_dreg_to_num(dm)?;
6004 let (vm, m) = encode_dreg(dm_num);
6005
6006 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
6008 let vcvt = base | (m << 5) | vm;
6009 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6010
6011 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
6013 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6014
6015 Ok(bytes)
6016 }
6017
6018 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
6022 let mut bytes = Vec::new();
6023 let dm_num = vfp_dreg_to_num(dm)?;
6024 let dd_num = vfp_dreg_to_num(dd)?;
6025 let (vm, m) = encode_dreg(dm_num);
6026 let (vd, d) = encode_dreg(dd_num);
6027
6028 if mode == 0b11 {
6029 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
6031 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
6032 } else {
6033 let rt: u32 = 12;
6034
6035 let vmrs = 0xEEF10A10 | (rt << 12);
6037 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
6038
6039 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
6041 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
6042 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
6043 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
6044
6045 if mode != 0 {
6047 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
6048 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
6049 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
6050 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
6051 }
6052
6053 let vmsr = 0xEEE10A10 | (rt << 12);
6055 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
6056
6057 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
6059 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
6060
6061 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
6063 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
6064 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
6065 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
6066 }
6067
6068 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
6070 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
6071
6072 Ok(bytes)
6073 }
6074
6075 fn encode_thumb_f64_minmax(
6077 &self,
6078 dd: &VfpReg,
6079 dn: &VfpReg,
6080 dm: &VfpReg,
6081 is_min: bool,
6082 ) -> Result<Vec<u8>> {
6083 let mut bytes = Vec::new();
6084 let dn_num = vfp_dreg_to_num(dn)?;
6085 let dm_num = vfp_dreg_to_num(dm)?;
6086 let dd_num = vfp_dreg_to_num(dd)?;
6087
6088 let (vd, d) = encode_dreg(dd_num);
6090 let (vn, n) = encode_dreg(dn_num);
6091 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
6092 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
6093
6094 let (vm, m) = encode_dreg(dm_num);
6096 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
6097 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
6098
6099 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
6101
6102 let cond: u16 = if is_min { 0xC } else { 0x4 };
6104 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
6105 bytes.extend_from_slice(&it.to_le_bytes());
6106
6107 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
6109 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
6110
6111 Ok(bytes)
6112 }
6113
6114 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
6116 let mut bytes = Vec::new();
6117
6118 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6120 false,
6121 dm,
6122 &Reg::R0,
6123 &Reg::R12,
6124 )?));
6125
6126 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6128 false,
6129 dn,
6130 &Reg::R1,
6131 &Reg::R2,
6132 )?));
6133
6134 let hw1: u16 = 0xF000 | 12;
6136 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
6137 bytes.extend_from_slice(&hw1.to_le_bytes());
6138 bytes.extend_from_slice(&hw2.to_le_bytes());
6139
6140 let hw1: u16 = 0xF020 | 2;
6142 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
6143 bytes.extend_from_slice(&hw1.to_le_bytes());
6144 bytes.extend_from_slice(&hw2.to_le_bytes());
6145
6146 let hw1: u16 = 0xEA40 | 2;
6148 let hw2: u16 = (2 << 8) | 12;
6149 bytes.extend_from_slice(&hw1.to_le_bytes());
6150 bytes.extend_from_slice(&hw2.to_le_bytes());
6151
6152 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6154 true,
6155 dd,
6156 &Reg::R1,
6157 &Reg::R2,
6158 )?));
6159
6160 Ok(bytes)
6161 }
6162
6163 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6165 let mut bytes = Vec::new();
6166
6167 let sm_num = vfp_sreg_to_num(sm)?;
6168 let (vd, d) = encode_sreg(sm_num);
6169 let (vm, m) = encode_sreg(sm_num);
6170 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6171 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6172 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6173
6174 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6176 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6177
6178 Ok(bytes)
6179 }
6180
6181 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6185 let rd_bits = reg_to_bits(rd);
6186 let rn_bits = reg_to_bits(rn);
6187
6188 let i_bit = (imm >> 11) & 1;
6190 let imm3 = (imm >> 8) & 0x7;
6191 let imm8 = imm & 0xFF;
6192
6193 let hw1_base = if imm <= 0xFF {
6194 0xF100
6198 } else if imm <= 0xFFF {
6199 0xF200
6203 } else {
6204 return Err(synth_core::Error::synthesis(
6205 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6206 ));
6207 };
6208
6209 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6210 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6211
6212 let mut bytes = hw1.to_le_bytes().to_vec();
6213 bytes.extend_from_slice(&hw2.to_le_bytes());
6214 Ok(bytes)
6215 }
6216
6217 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6219 let rd_bits = reg_to_bits(rd);
6220 let rn_bits = reg_to_bits(rn);
6221
6222 let i_bit = (imm >> 11) & 1;
6223 let imm3 = (imm >> 8) & 0x7;
6224 let imm8 = imm & 0xFF;
6225
6226 let hw1_base = if imm <= 0xFF {
6227 0xF1A0
6230 } else if imm <= 0xFFF {
6231 0xF2A0
6234 } else {
6235 return Err(synth_core::Error::synthesis(
6236 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6237 ));
6238 };
6239
6240 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6241 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6242
6243 let mut bytes = hw1.to_le_bytes().to_vec();
6244 bytes.extend_from_slice(&hw2.to_le_bytes());
6245 Ok(bytes)
6246 }
6247
6248 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6250 let rd_bits = reg_to_bits(rd);
6251 let rn_bits = reg_to_bits(rn);
6252
6253 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6256 synth_core::Error::synthesis(
6257 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6258 )
6259 })?;
6260 let i_bit = (field >> 11) & 1;
6261 let imm3 = (field >> 8) & 0x7;
6262 let imm8 = field & 0xFF;
6263
6264 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6267 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6268
6269 let mut bytes = hw1.to_le_bytes().to_vec();
6270 bytes.extend_from_slice(&hw2.to_le_bytes());
6271 Ok(bytes)
6272 }
6273
6274 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6276 let rd_bits = reg_to_bits(rd);
6277 let rn_bits = reg_to_bits(rn);
6278
6279 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6282 synth_core::Error::synthesis(
6283 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6284 )
6285 })?;
6286 let i_bit = (field >> 11) & 1;
6287 let imm3 = (field >> 8) & 0x7;
6288 let imm8 = field & 0xFF;
6289
6290 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6293 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6294
6295 let mut bytes = hw1.to_le_bytes().to_vec();
6296 bytes.extend_from_slice(&hw2.to_le_bytes());
6297 Ok(bytes)
6298 }
6299
6300 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6309 let rd_bits = reg_to_bits(rd);
6310 reg_bits_checked(rd_bits)?;
6311 let imm16 = imm & 0xFFFF;
6312
6313 let imm4 = (imm16 >> 12) & 0xF;
6316 let i_bit = (imm16 >> 11) & 1;
6317 let imm3 = (imm16 >> 8) & 0x7;
6318 let imm8 = imm16 & 0xFF;
6319
6320 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6321 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6322
6323 let mut bytes = hw1.to_le_bytes().to_vec();
6324 bytes.extend_from_slice(&hw2.to_le_bytes());
6325 encoding_contracts::verify_thumb32(&bytes);
6326 Ok(bytes)
6327 }
6328
6329 fn encode_thumb32_shift(
6337 &self,
6338 rd: &Reg,
6339 rm: &Reg,
6340 shift: u32,
6341 shift_type: u8,
6342 ) -> Result<Vec<u8>> {
6343 let rd_bits = reg_to_bits(rd);
6344 let rm_bits = reg_to_bits(rm);
6345 reg_bits_checked(rd_bits)?;
6346 reg_bits_checked(rm_bits)?;
6347 let imm5 = shift & 0x1F;
6348 let imm2 = imm5 & 0x3;
6349 let imm3 = (imm5 >> 2) & 0x7;
6350
6351 let hw1: u16 = 0xEA4F;
6354 let hw2: u16 =
6355 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6356 as u16;
6357
6358 let mut bytes = hw1.to_le_bytes().to_vec();
6359 bytes.extend_from_slice(&hw2.to_le_bytes());
6360 Ok(bytes)
6361 }
6362
6363 fn encode_thumb32_shift_reg(
6367 &self,
6368 rd: &Reg,
6369 rn: &Reg,
6370 rm: &Reg,
6371 shift_type: u8,
6372 ) -> Result<Vec<u8>> {
6373 let rd_bits = reg_to_bits(rd);
6374 let rn_bits = reg_to_bits(rn);
6375 let rm_bits = reg_to_bits(rm);
6376
6377 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6379 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6381
6382 let mut bytes = hw1.to_le_bytes().to_vec();
6383 bytes.extend_from_slice(&hw2.to_le_bytes());
6384 Ok(bytes)
6385 }
6386
6387 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6389 let rn_bits = reg_to_bits(rn);
6390
6391 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6395 synth_core::Error::synthesis(
6396 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6397 )
6398 })?;
6399 let i_bit = (field >> 11) & 1;
6400 let imm3 = (field >> 8) & 0x7;
6401 let imm8 = field & 0xFF;
6402
6403 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6405 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6406
6407 let mut bytes = hw1.to_le_bytes().to_vec();
6408 bytes.extend_from_slice(&hw2.to_le_bytes());
6409 Ok(bytes)
6410 }
6411
6412 fn i64_effective_base(&self, bytes: &mut Vec<u8>, addr: &MemAddr) -> Result<(Reg, u32)> {
6434 let offset = if addr.offset < 0 {
6435 0u32
6436 } else {
6437 addr.offset as u32
6438 };
6439 match addr.offset_reg {
6440 Some(idx) => {
6441 let ip = Reg::R12;
6442 if offset.wrapping_add(4) > 0xFFF {
6443 bytes.extend_from_slice(&self.encode_thumb32_add_imm(&ip, &idx, offset)?);
6447 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
6449 reg_to_bits(&ip),
6450 reg_to_bits(&ip),
6451 reg_to_bits(&addr.base),
6452 )?);
6453 Ok((ip, 0))
6454 } else {
6455 let hw1: u16 = 0xEB00 | reg_to_bits(&addr.base) as u16;
6457 let hw2: u16 = 0x0C00 | reg_to_bits(&idx) as u16;
6458 bytes.extend_from_slice(&hw1.to_le_bytes());
6459 bytes.extend_from_slice(&hw2.to_le_bytes());
6460 Ok((ip, offset))
6461 }
6462 }
6463 None => Ok((addr.base, offset)),
6464 }
6465 }
6466
6467 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6469 let rd_bits = reg_to_bits(rd);
6470 let base_bits = reg_to_bits(base);
6471
6472 check_ldst_imm12(offset)?;
6474 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6475 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6476
6477 let mut bytes = hw1.to_le_bytes().to_vec();
6478 bytes.extend_from_slice(&hw2.to_le_bytes());
6479 Ok(bytes)
6480 }
6481
6482 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6484 let rd_bits = reg_to_bits(rd);
6485 let base_bits = reg_to_bits(base);
6486
6487 check_ldst_imm12(offset)?;
6489 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6490 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6491
6492 let mut bytes = hw1.to_le_bytes().to_vec();
6493 bytes.extend_from_slice(&hw2.to_le_bytes());
6494 Ok(bytes)
6495 }
6496
6497 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6499 let rd_bits = reg_to_bits(rd);
6500 let base_bits = reg_to_bits(base);
6501 let rm_bits = reg_to_bits(offset_reg);
6502
6503 let hw1: u16 = (0xF850 | base_bits) as u16;
6507 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6508
6509 let mut bytes = hw1.to_le_bytes().to_vec();
6510 bytes.extend_from_slice(&hw2.to_le_bytes());
6511 Ok(bytes)
6512 }
6513
6514 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6516 let rd_bits = reg_to_bits(rd);
6517 let base_bits = reg_to_bits(base);
6518 let rm_bits = reg_to_bits(offset_reg);
6519
6520 let hw1: u16 = (0xF840 | base_bits) as u16;
6524 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6525
6526 let mut bytes = hw1.to_le_bytes().to_vec();
6527 bytes.extend_from_slice(&hw2.to_le_bytes());
6528 Ok(bytes)
6529 }
6530
6531 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6535 let rd_bits = reg_to_bits(rd);
6536 let base_bits = reg_to_bits(base);
6537 check_ldst_imm12(offset)?;
6539 let hw1: u16 = (0xF890 | base_bits) as u16;
6540 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6541 let mut bytes = hw1.to_le_bytes().to_vec();
6542 bytes.extend_from_slice(&hw2.to_le_bytes());
6543 Ok(bytes)
6544 }
6545
6546 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6548 let rd_bits = reg_to_bits(rd);
6549 let base_bits = reg_to_bits(base);
6550 let rm_bits = reg_to_bits(offset_reg);
6551 let hw1: u16 = (0xF810 | base_bits) as u16;
6553 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6554 let mut bytes = hw1.to_le_bytes().to_vec();
6555 bytes.extend_from_slice(&hw2.to_le_bytes());
6556 Ok(bytes)
6557 }
6558
6559 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6561 let rd_bits = reg_to_bits(rd);
6562 let base_bits = reg_to_bits(base);
6563 check_ldst_imm12(offset)?;
6565 let hw1: u16 = (0xF990 | base_bits) as u16;
6566 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6567 let mut bytes = hw1.to_le_bytes().to_vec();
6568 bytes.extend_from_slice(&hw2.to_le_bytes());
6569 Ok(bytes)
6570 }
6571
6572 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6574 let rd_bits = reg_to_bits(rd);
6575 let base_bits = reg_to_bits(base);
6576 let rm_bits = reg_to_bits(offset_reg);
6577 let hw1: u16 = (0xF910 | base_bits) as u16;
6579 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6580 let mut bytes = hw1.to_le_bytes().to_vec();
6581 bytes.extend_from_slice(&hw2.to_le_bytes());
6582 Ok(bytes)
6583 }
6584
6585 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6587 let rd_bits = reg_to_bits(rd);
6588 let base_bits = reg_to_bits(base);
6589 check_ldst_imm12(offset)?;
6591 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6592 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6593 let mut bytes = hw1.to_le_bytes().to_vec();
6594 bytes.extend_from_slice(&hw2.to_le_bytes());
6595 Ok(bytes)
6596 }
6597
6598 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6600 let rd_bits = reg_to_bits(rd);
6601 let base_bits = reg_to_bits(base);
6602 let rm_bits = reg_to_bits(offset_reg);
6603 let hw1: u16 = (0xF830 | base_bits) as u16;
6605 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6606 let mut bytes = hw1.to_le_bytes().to_vec();
6607 bytes.extend_from_slice(&hw2.to_le_bytes());
6608 Ok(bytes)
6609 }
6610
6611 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6613 let rd_bits = reg_to_bits(rd);
6614 let base_bits = reg_to_bits(base);
6615 check_ldst_imm12(offset)?;
6617 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6618 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6619 let mut bytes = hw1.to_le_bytes().to_vec();
6620 bytes.extend_from_slice(&hw2.to_le_bytes());
6621 Ok(bytes)
6622 }
6623
6624 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6626 let rd_bits = reg_to_bits(rd);
6627 let base_bits = reg_to_bits(base);
6628 let rm_bits = reg_to_bits(offset_reg);
6629 let hw1: u16 = (0xF930 | base_bits) as u16;
6631 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6632 let mut bytes = hw1.to_le_bytes().to_vec();
6633 bytes.extend_from_slice(&hw2.to_le_bytes());
6634 Ok(bytes)
6635 }
6636
6637 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6639 let rd_bits = reg_to_bits(rd);
6640 let base_bits = reg_to_bits(base);
6641 check_ldst_imm12(offset)?;
6643 let hw1: u16 = (0xF880 | base_bits) as u16;
6644 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6645 let mut bytes = hw1.to_le_bytes().to_vec();
6646 bytes.extend_from_slice(&hw2.to_le_bytes());
6647 Ok(bytes)
6648 }
6649
6650 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6652 let rd_bits = reg_to_bits(rd);
6653 let base_bits = reg_to_bits(base);
6654 let rm_bits = reg_to_bits(offset_reg);
6655 let hw1: u16 = (0xF800 | base_bits) as u16;
6657 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6658 let mut bytes = hw1.to_le_bytes().to_vec();
6659 bytes.extend_from_slice(&hw2.to_le_bytes());
6660 Ok(bytes)
6661 }
6662
6663 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6665 let rd_bits = reg_to_bits(rd);
6666 let base_bits = reg_to_bits(base);
6667 check_ldst_imm12(offset)?;
6669 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6670 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6671 let mut bytes = hw1.to_le_bytes().to_vec();
6672 bytes.extend_from_slice(&hw2.to_le_bytes());
6673 Ok(bytes)
6674 }
6675
6676 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6678 let rd_bits = reg_to_bits(rd);
6679 let base_bits = reg_to_bits(base);
6680 let rm_bits = reg_to_bits(offset_reg);
6681 let hw1: u16 = (0xF820 | base_bits) as u16;
6683 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6684 let mut bytes = hw1.to_le_bytes().to_vec();
6685 bytes.extend_from_slice(&hw2.to_le_bytes());
6686 Ok(bytes)
6687 }
6688
6689 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6691 let rd_bits = reg_to_bits(rd);
6692 let rn_bits = reg_to_bits(rn);
6693
6694 if imm <= 0xFFF {
6700 let i_bit = (imm >> 11) & 1;
6701 let imm3 = (imm >> 8) & 0x7;
6702 let imm8 = imm & 0xFF;
6703
6704 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6705 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6706
6707 let mut bytes = hw1.to_le_bytes().to_vec();
6708 bytes.extend_from_slice(&hw2.to_le_bytes());
6709 Ok(bytes)
6710 } else {
6711 let scratch: u32 = if rd_bits == rn_bits {
6725 12 } else {
6727 rd_bits };
6729 if scratch == rn_bits {
6737 return Err(synth_core::Error::synthesis(format!(
6738 "ADD #imm: cannot lower #{imm:#x} for Rd==Rn==R12 — no free scratch \
6739 register (R12 is the reserved encoder scratch and aliases Rn here)"
6740 )));
6741 }
6742
6743 let lo16 = imm & 0xFFFF;
6744 let hi16 = (imm >> 16) & 0xFFFF;
6745
6746 let mut bytes = self.encode_thumb32_movw_raw(scratch, lo16)?;
6747 if hi16 != 0 {
6748 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(scratch, hi16)?);
6749 }
6750 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(rd_bits, rn_bits, scratch)?);
6751 Ok(bytes)
6752 }
6753 }
6754
6755 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6765 reg_bits_checked(rd)?;
6766 encoding_contracts::verify_imm16(imm16);
6767 let imm16 = imm16 & 0xFFFF;
6770 let imm4 = (imm16 >> 12) & 0xF;
6771 let i_bit = (imm16 >> 11) & 1;
6772 let imm3 = (imm16 >> 8) & 0x7;
6773 let imm8 = imm16 & 0xFF;
6774
6775 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6776 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6777
6778 let mut bytes = hw1.to_le_bytes().to_vec();
6779 bytes.extend_from_slice(&hw2.to_le_bytes());
6780 encoding_contracts::verify_thumb32(&bytes);
6781 Ok(bytes)
6782 }
6783
6784 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6792 reg_bits_checked(rd)?;
6793 encoding_contracts::verify_imm16(imm16);
6794 let imm16 = imm16 & 0xFFFF;
6797 let imm4 = (imm16 >> 12) & 0xF;
6798 let i_bit = (imm16 >> 11) & 1;
6799 let imm3 = (imm16 >> 8) & 0x7;
6800 let imm8 = imm16 & 0xFF;
6801
6802 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6803 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6804
6805 let mut bytes = hw1.to_le_bytes().to_vec();
6806 bytes.extend_from_slice(&hw2.to_le_bytes());
6807 encoding_contracts::verify_thumb32(&bytes);
6808 Ok(bytes)
6809 }
6810
6811 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6813 let imm5 = shift & 0x1F;
6816 let imm2 = imm5 & 0x3;
6817 let imm3 = (imm5 >> 2) & 0x7;
6818
6819 let hw1: u16 = 0xEA4F;
6820 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6821
6822 let mut bytes = hw1.to_le_bytes().to_vec();
6823 bytes.extend_from_slice(&hw2.to_le_bytes());
6824 Ok(bytes)
6825 }
6826
6827 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6829 let hw1: u16 = (0xEA00 | rn) as u16;
6832 let hw2: u16 = ((rd << 8) | rm) as u16;
6833
6834 let mut bytes = hw1.to_le_bytes().to_vec();
6835 bytes.extend_from_slice(&hw2.to_le_bytes());
6836 Ok(bytes)
6837 }
6838
6839 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6841 let i_bit = (imm >> 11) & 1;
6845 let imm3 = (imm >> 8) & 0x7;
6846 let imm8 = imm & 0xFF;
6847
6848 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6849 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6850
6851 let mut bytes = hw1.to_le_bytes().to_vec();
6852 bytes.extend_from_slice(&hw2.to_le_bytes());
6853 Ok(bytes)
6854 }
6855
6856 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6858 let hw1: u16 = (0xEBA0 | rn) as u16;
6861 let hw2: u16 = ((rd << 8) | rm) as u16;
6862
6863 let mut bytes = hw1.to_le_bytes().to_vec();
6864 bytes.extend_from_slice(&hw2.to_le_bytes());
6865 Ok(bytes)
6866 }
6867
6868 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6870 let hw1: u16 = (0xEB00 | rn) as u16;
6873 let hw2: u16 = ((rd << 8) | rm) as u16;
6874
6875 let mut bytes = hw1.to_le_bytes().to_vec();
6876 bytes.extend_from_slice(&hw2.to_le_bytes());
6877 Ok(bytes)
6878 }
6879
6880 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6884 let hw1: u16 = (0xEB10 | rn) as u16;
6886 let hw2: u16 = ((rd << 8) | rm) as u16;
6887 let mut bytes = hw1.to_le_bytes().to_vec();
6888 bytes.extend_from_slice(&hw2.to_le_bytes());
6889 Ok(bytes)
6890 }
6891
6892 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6895 let hw1: u16 = (0xEBB0 | rn) as u16;
6897 let hw2: u16 = ((rd << 8) | rm) as u16;
6898 let mut bytes = hw1.to_le_bytes().to_vec();
6899 bytes.extend_from_slice(&hw2.to_le_bytes());
6900 Ok(bytes)
6901 }
6902
6903 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6905 let mut code = Vec::new();
6906
6907 for op in ops {
6908 let encoded = self.encode(op)?;
6909 code.extend_from_slice(&encoded);
6910 }
6911
6912 Ok(code)
6913 }
6914}
6915
6916fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6924 if value <= 0xFF {
6926 return Some(value);
6927 }
6928 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6932 return Some(0x100 | b0);
6933 }
6934 if value == (b1 << 24) | (b1 << 8) {
6936 return Some(0x200 | b1);
6937 }
6938 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6940 return Some(0x300 | b0);
6941 }
6942 for rot in 8..=31u32 {
6946 let unrot = value.rotate_left(rot);
6947 if (0x80..=0xFF).contains(&unrot) {
6948 return Some((rot << 7) | (unrot & 0x7F));
6949 }
6950 }
6951 None
6952}
6953
6954fn check_ldst_imm12(offset: u32) -> Result<()> {
6960 if offset > 0xFFF {
6961 Err(synth_core::Error::synthesis(
6962 "load/store immediate offset > 0xFFF (4095) — materialize the offset into a register",
6963 ))
6964 } else {
6965 Ok(())
6966 }
6967}
6968
6969fn reg_to_bits(reg: &Reg) -> u32 {
6970 match reg {
6971 Reg::R0 => 0,
6972 Reg::R1 => 1,
6973 Reg::R2 => 2,
6974 Reg::R3 => 3,
6975 Reg::R4 => 4,
6976 Reg::R5 => 5,
6977 Reg::R6 => 6,
6978 Reg::R7 => 7,
6979 Reg::R8 => 8,
6980 Reg::R9 => 9,
6981 Reg::R10 => 10,
6982 Reg::R11 => 11,
6983 Reg::R12 => 12,
6984 Reg::SP => 13,
6985 Reg::LR => 14,
6986 Reg::PC => 15,
6987 }
6988}
6989
6990fn reg_bits_checked(bits: u32) -> Result<()> {
6998 if bits > 14 {
6999 return Err(synth_core::Error::synthesis(format!(
7000 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
7001 )));
7002 }
7003 Ok(())
7004}
7005
7006fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
7009 if val == 0 {
7010 return Some((0, 1));
7011 }
7012 for rot in 0..16u32 {
7013 let shift = rot * 2;
7014 let unrotated = val.rotate_left(shift);
7016 if unrotated <= 0xFF {
7017 return Some(((rot << 8) | unrotated, 1));
7019 }
7020 }
7021 None
7022}
7023
7024fn encode_operand2(op2: &Operand2) -> Result<(u32, u32)> {
7029 match op2 {
7030 Operand2::Imm(val) => {
7031 let uval = *val as u32;
7032 if let Some(encoded) = try_encode_rotated_imm(uval) {
7034 Ok(encoded)
7035 } else {
7036 Err(synth_core::Error::synthesis(format!(
7045 "encode_operand2: immediate {uval:#x} ({val}) is not an ARM32 \
7046 rotated immediate — the selector must materialize large \
7047 constants via MOVW/MOVT"
7048 )))
7049 }
7050 }
7051
7052 Operand2::Reg(reg) => {
7053 let reg_bits = reg_to_bits(reg);
7054 Ok((reg_bits, 0)) }
7056
7057 Operand2::RegShift {
7058 rm,
7059 shift: _,
7060 amount,
7061 } => {
7062 let rm_bits = reg_to_bits(rm);
7064 let shift_bits = (*amount & 0x1F) << 7;
7065 Ok((shift_bits | rm_bits, 0))
7066 }
7067 }
7068}
7069
7070fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
7072 let base_bits = reg_to_bits(&addr.base);
7073 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
7075}
7076
7077fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
7079 match reg {
7080 VfpReg::S0 => Ok(0),
7081 VfpReg::S1 => Ok(1),
7082 VfpReg::S2 => Ok(2),
7083 VfpReg::S3 => Ok(3),
7084 VfpReg::S4 => Ok(4),
7085 VfpReg::S5 => Ok(5),
7086 VfpReg::S6 => Ok(6),
7087 VfpReg::S7 => Ok(7),
7088 VfpReg::S8 => Ok(8),
7089 VfpReg::S9 => Ok(9),
7090 VfpReg::S10 => Ok(10),
7091 VfpReg::S11 => Ok(11),
7092 VfpReg::S12 => Ok(12),
7093 VfpReg::S13 => Ok(13),
7094 VfpReg::S14 => Ok(14),
7095 VfpReg::S15 => Ok(15),
7096 VfpReg::S16 => Ok(16),
7097 VfpReg::S17 => Ok(17),
7098 VfpReg::S18 => Ok(18),
7099 VfpReg::S19 => Ok(19),
7100 VfpReg::S20 => Ok(20),
7101 VfpReg::S21 => Ok(21),
7102 VfpReg::S22 => Ok(22),
7103 VfpReg::S23 => Ok(23),
7104 VfpReg::S24 => Ok(24),
7105 VfpReg::S25 => Ok(25),
7106 VfpReg::S26 => Ok(26),
7107 VfpReg::S27 => Ok(27),
7108 VfpReg::S28 => Ok(28),
7109 VfpReg::S29 => Ok(29),
7110 VfpReg::S30 => Ok(30),
7111 VfpReg::S31 => Ok(31),
7112 _ => Err(synth_core::Error::SynthesisError(
7114 "D-register not supported in single-precision VFP encoding".to_string(),
7115 )),
7116 }
7117}
7118
7119fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
7121 match reg {
7122 VfpReg::D0 => Ok(0),
7123 VfpReg::D1 => Ok(1),
7124 VfpReg::D2 => Ok(2),
7125 VfpReg::D3 => Ok(3),
7126 VfpReg::D4 => Ok(4),
7127 VfpReg::D5 => Ok(5),
7128 VfpReg::D6 => Ok(6),
7129 VfpReg::D7 => Ok(7),
7130 VfpReg::D8 => Ok(8),
7131 VfpReg::D9 => Ok(9),
7132 VfpReg::D10 => Ok(10),
7133 VfpReg::D11 => Ok(11),
7134 VfpReg::D12 => Ok(12),
7135 VfpReg::D13 => Ok(13),
7136 VfpReg::D14 => Ok(14),
7137 VfpReg::D15 => Ok(15),
7138 _ => Err(synth_core::Error::SynthesisError(
7140 "S-register not supported in double-precision VFP encoding".to_string(),
7141 )),
7142 }
7143}
7144
7145fn encode_sreg(s: u32) -> (u32, u32) {
7149 (s >> 1, s & 1)
7150}
7151
7152fn encode_dreg(d: u32) -> (u32, u32) {
7156 (d & 0xF, (d >> 4) & 1)
7157}
7158
7159fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
7165 let sd_num = vfp_sreg_to_num(sd)?;
7166 let sn_num = vfp_sreg_to_num(sn)?;
7167 let sm_num = vfp_sreg_to_num(sm)?;
7168 let (vd, d) = encode_sreg(sd_num);
7169 let (vn, n) = encode_sreg(sn_num);
7170 let (vm, m) = encode_sreg(sm_num);
7171
7172 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7173}
7174
7175fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
7178 let sd_num = vfp_sreg_to_num(sd)?;
7179 let sm_num = vfp_sreg_to_num(sm)?;
7180 let (vd, d) = encode_sreg(sd_num);
7181 let (vm, m) = encode_sreg(sm_num);
7182
7183 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7184}
7185
7186fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7190 let sd_num = vfp_sreg_to_num(sd)?;
7191 let (vd, d) = encode_sreg(sd_num);
7192 let rn = reg_to_bits(&addr.base);
7193
7194 let offset = addr.offset;
7195 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7196 let abs_offset = offset.unsigned_abs();
7197 let imm8 = (abs_offset / 4) & 0xFF;
7198
7199 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7200}
7201
7202fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
7206 let s_num = vfp_sreg_to_num(sreg)?;
7207 let (vn, n) = encode_sreg(s_num);
7208 let rt = reg_to_bits(core);
7209
7210 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
7211 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
7212}
7213
7214fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
7218 let dd_num = vfp_dreg_to_num(dd)?;
7219 let dn_num = vfp_dreg_to_num(dn)?;
7220 let dm_num = vfp_dreg_to_num(dm)?;
7221 let (vd, d) = encode_dreg(dd_num);
7222 let (vn, n) = encode_dreg(dn_num);
7223 let (vm, m) = encode_dreg(dm_num);
7224
7225 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7226}
7227
7228fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
7230 let dd_num = vfp_dreg_to_num(dd)?;
7231 let dm_num = vfp_dreg_to_num(dm)?;
7232 let (vd, d) = encode_dreg(dd_num);
7233 let (vm, m) = encode_dreg(dm_num);
7234
7235 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7236}
7237
7238fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7241 let dd_num = vfp_dreg_to_num(dd)?;
7242 let (vd, d) = encode_dreg(dd_num);
7243 let rn = reg_to_bits(&addr.base);
7244
7245 let offset = addr.offset;
7246 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7247 let abs_offset = offset.unsigned_abs();
7248 let imm8 = (abs_offset / 4) & 0xFF;
7249
7250 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7251}
7252
7253fn encode_vmov_core_dreg(
7257 to_dreg: bool,
7258 dreg: &VfpReg,
7259 core_lo: &Reg,
7260 core_hi: &Reg,
7261) -> Result<u32> {
7262 let d_num = vfp_dreg_to_num(dreg)?;
7263 let (vm, m) = encode_dreg(d_num);
7264 let rt = reg_to_bits(core_lo);
7265 let rt2 = reg_to_bits(core_hi);
7266
7267 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
7268 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
7269}
7270
7271fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
7273 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
7274 let hw2 = (instr & 0xFFFF) as u16;
7275 let mut bytes = hw1.to_le_bytes().to_vec();
7276 bytes.extend_from_slice(&hw2.to_le_bytes());
7277 bytes
7278}
7279
7280fn qreg_to_num(reg: &QReg) -> u32 {
7286 match reg {
7287 QReg::Q0 => 0,
7288 QReg::Q1 => 1,
7289 QReg::Q2 => 2,
7290 QReg::Q3 => 3,
7291 QReg::Q4 => 4,
7292 QReg::Q5 => 5,
7293 QReg::Q6 => 6,
7294 QReg::Q7 => 7,
7295 }
7296}
7297
7298fn mve_size_bits(size: &MveSize) -> u32 {
7300 match size {
7301 MveSize::S8 => 0b00,
7302 MveSize::S16 => 0b01,
7303 MveSize::S32 => 0b10,
7304 }
7305}
7306
7307fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7311 let d = qreg_to_num(qd) * 2;
7312 let n = qreg_to_num(qn) * 2;
7313 let m = qreg_to_num(qm) * 2;
7314
7315 let vd = d & 0xF;
7320 let d_bit = (d >> 4) & 1;
7321 let vn = n & 0xF;
7322 let n_bit = (n >> 4) & 1;
7323 let vm = m & 0xF;
7324 let m_bit = (m >> 4) & 1;
7325
7326 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7327}
7328
7329fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7331 encode_mve_3reg(base, qd, qn, qm)
7332}
7333
7334fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7337 let qd_enc = qreg_to_num(qd) * 2;
7338 let rn = reg_to_bits(&addr.base);
7339 let offset = addr.offset;
7340 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7341 let abs_offset = offset.unsigned_abs();
7342 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7346 | (u_bit << 23)
7347 | ((qd_enc >> 4) << 22)
7348 | (rn << 16)
7349 | ((qd_enc & 0xF) << 12)
7350 | (imm7 & 0x7F)
7351}
7352
7353fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7355 let qd_enc = qreg_to_num(qd) * 2;
7356 let rn = reg_to_bits(&addr.base);
7357 let offset = addr.offset;
7358 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7359 let abs_offset = offset.unsigned_abs();
7360 let imm7 = (abs_offset / 4) & 0x7F;
7361
7362 0xED000E80
7363 | (u_bit << 23)
7364 | ((qd_enc >> 4) << 22)
7365 | (rn << 16)
7366 | ((qd_enc & 0xF) << 12)
7367 | (imm7 & 0x7F)
7368}
7369
7370impl ArmEncoder {
7371 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7373 let mut result = Vec::new();
7374 let qd_num = qreg_to_num(qd);
7375
7376 for i in 0..4 {
7378 let word = u32::from_le_bytes([
7379 bytes[i * 4],
7380 bytes[i * 4 + 1],
7381 bytes[i * 4 + 2],
7382 bytes[i * 4 + 3],
7383 ]);
7384 let lo16 = word & 0xFFFF;
7385 let hi16 = (word >> 16) & 0xFFFF;
7386
7387 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7389 if hi16 != 0 {
7391 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7392 }
7393
7394 let s_num = qd_num * 4 + i as u32;
7396 let (vn, n) = encode_sreg(s_num);
7397 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7398 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7399 }
7400
7401 Ok(result)
7402 }
7403
7404 fn encode_thumb_mve_lane_wise_f32_binop(
7406 &self,
7407 qd: &QReg,
7408 qn: &QReg,
7409 qm: &QReg,
7410 vfp_base: u32,
7411 ) -> Result<Vec<u8>> {
7412 let mut result = Vec::new();
7413 let qd_num = qreg_to_num(qd);
7414 let qn_num = qreg_to_num(qn);
7415 let qm_num = qreg_to_num(qm);
7416
7417 for i in 0..4u32 {
7419 let sd = qd_num * 4 + i;
7420 let sn = qn_num * 4 + i;
7421 let sm = qm_num * 4 + i;
7422
7423 let (vd, d) = encode_sreg(sd);
7424 let (vn, n) = encode_sreg(sn);
7425 let (vm, m) = encode_sreg(sm);
7426
7427 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7428 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7429 }
7430
7431 Ok(result)
7432 }
7433
7434 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7436 let mut result = Vec::new();
7437 let qd_num = qreg_to_num(qd);
7438 let qm_num = qreg_to_num(qm);
7439
7440 for i in 0..4u32 {
7442 let sd = qd_num * 4 + i;
7443 let sm = qm_num * 4 + i;
7444
7445 let (vd, d) = encode_sreg(sd);
7446 let (vm, m) = encode_sreg(sm);
7447
7448 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7449 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7450 }
7451
7452 Ok(result)
7453 }
7454}
7455
7456#[cfg(test)]
7457mod tests {
7458 use super::*;
7459
7460 #[test]
7461 fn test_encoder_creation() {
7462 let encoder_arm = ArmEncoder::new_arm32();
7463 assert!(!encoder_arm.thumb_mode);
7464
7465 let encoder_thumb = ArmEncoder::new_thumb2();
7466 assert!(encoder_thumb.thumb_mode);
7467 }
7468
7469 #[test]
7481 fn test_encode_i64setcond_high_reg_uses_mov_w_311() {
7482 use synth_synthesis::{ArmOp, Condition, Reg};
7483 let enc = ArmEncoder::new_thumb2();
7484 let bytes = enc
7485 .encode(&ArmOp::I64SetCond {
7486 rd: Reg::R8,
7487 rn_lo: Reg::R2,
7488 rn_hi: Reg::R3,
7489 rm_lo: Reg::R6,
7490 rm_hi: Reg::R7,
7491 cond: Condition::EQ,
7492 })
7493 .unwrap();
7494 let halfwords: Vec<u16> = bytes
7497 .chunks(2)
7498 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7499 .collect();
7500 assert!(
7501 halfwords.iter().filter(|&&h| h == 0xF04F).count() == 2,
7502 "high rd must use two MOV.W (T2) encodings, got {halfwords:04x?}"
7503 );
7504 assert!(
7505 !halfwords.contains(&0x2801) && !halfwords.contains(&0x2800),
7506 "no transmuted 16-bit CMP imm: {halfwords:04x?}"
7507 );
7508
7509 let bytes_z = enc
7510 .encode(&ArmOp::I64SetCondZ {
7511 rd: Reg::R8,
7512 rn_lo: Reg::R2,
7513 rn_hi: Reg::R3,
7514 })
7515 .unwrap();
7516 let hw_z: Vec<u16> = bytes_z
7517 .chunks(2)
7518 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7519 .collect();
7520 assert!(
7521 hw_z.iter().filter(|&&h| h == 0xF04F).count() == 2,
7522 "SetCondZ high rd MOV.W: {hw_z:04x?}"
7523 );
7524 assert!(
7526 hw_z.contains(&(0xF1B0 | 8)),
7527 "SetCondZ high rd must use CMP.W: {hw_z:04x?}"
7528 );
7529 }
7530
7531 #[test]
7532 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7533 use synth_synthesis::{ArmOp, Condition, Reg};
7534 let enc = ArmEncoder::new_thumb2();
7535 let hi = enc
7537 .encode(&ArmOp::SetCond {
7538 rd: Reg::R12,
7539 cond: Condition::NE,
7540 })
7541 .unwrap();
7542 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7543 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7545 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7546 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7547 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7548 let lo = enc
7550 .encode(&ArmOp::SetCond {
7551 rd: Reg::R0,
7552 cond: Condition::NE,
7553 })
7554 .unwrap();
7555 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7556 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7557 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7558 }
7559
7560 #[test]
7564 fn test_encode_umull_209b() {
7565 use synth_synthesis::{ArmOp, Reg};
7566 let op = ArmOp::Umull {
7567 rdlo: Reg::R4,
7568 rdhi: Reg::R5,
7569 rn: Reg::R0,
7570 rm: Reg::R3,
7571 };
7572 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7574 assert_eq!(
7575 t,
7576 vec![0xA0, 0xFB, 0x03, 0x45],
7577 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7578 );
7579 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7581 assert_eq!(
7582 a,
7583 0xE085_4390u32.to_le_bytes().to_vec(),
7584 "umull (A32): {a:02x?}"
7585 );
7586 }
7587
7588 #[test]
7595 fn test_encode_arm32_indexed_load_keeps_index_206() {
7596 use synth_synthesis::{ArmOp, MemAddr, Reg};
7597 let enc = ArmEncoder::new_arm32();
7598 let bytes = enc
7600 .encode(&ArmOp::Ldr {
7601 rd: Reg::R0,
7602 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7603 })
7604 .unwrap();
7605 assert_eq!(
7606 bytes.len(),
7607 8,
7608 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7609 );
7610 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7611 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7612 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7614 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7616 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7618 }
7619
7620 #[test]
7627 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7628 let encoder = ArmEncoder::new_thumb2();
7629
7630 let code = encoder
7632 .encode(&ArmOp::Add {
7633 rd: Reg::R12,
7634 rn: Reg::R12,
7635 op2: Operand2::Reg(Reg::R0),
7636 })
7637 .unwrap();
7638 assert_eq!(
7640 code,
7641 vec![0x0C, 0xEB, 0x00, 0x0C],
7642 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7643 );
7644 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7646
7647 let lo = encoder
7649 .encode(&ArmOp::Add {
7650 rd: Reg::R1,
7651 rn: Reg::R2,
7652 op2: Operand2::Reg(Reg::R3),
7653 })
7654 .unwrap();
7655 assert_eq!(
7656 lo.len(),
7657 2,
7658 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7659 );
7660 }
7661
7662 #[test]
7665 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7666 let encoder = ArmEncoder::new_thumb2();
7667
7668 let adds = encoder
7670 .encode(&ArmOp::Adds {
7671 rd: Reg::R10,
7672 rn: Reg::R10,
7673 op2: Operand2::Reg(Reg::R8),
7674 })
7675 .unwrap();
7676 assert_eq!(
7677 adds,
7678 vec![0x1A, 0xEB, 0x08, 0x0A],
7679 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7680 );
7681
7682 let subs = encoder
7684 .encode(&ArmOp::Subs {
7685 rd: Reg::R10,
7686 rn: Reg::R10,
7687 op2: Operand2::Reg(Reg::R8),
7688 })
7689 .unwrap();
7690 assert_eq!(
7691 subs,
7692 vec![0xBA, 0xEB, 0x08, 0x0A],
7693 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7694 );
7695 }
7696
7697 #[test]
7700 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7701 let encoder = ArmEncoder::new_thumb2();
7702
7703 let cmn = encoder
7705 .encode(&ArmOp::Cmn {
7706 rn: Reg::R10,
7707 op2: Operand2::Reg(Reg::R8),
7708 })
7709 .unwrap();
7710 assert_eq!(
7711 cmn,
7712 vec![0x1A, 0xEB, 0x08, 0x0F],
7713 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7714 );
7715
7716 let lo = encoder
7718 .encode(&ArmOp::Cmn {
7719 rn: Reg::R1,
7720 op2: Operand2::Reg(Reg::R2),
7721 })
7722 .unwrap();
7723 assert_eq!(
7724 lo.len(),
7725 2,
7726 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7727 );
7728 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7729 }
7730
7731 #[test]
7735 fn test_encode_pc_operand_returns_err_not_panic_185() {
7736 let encoder = ArmEncoder::new_thumb2();
7737 for op in [
7738 ArmOp::Sdiv {
7739 rd: Reg::PC,
7740 rn: Reg::R0,
7741 rm: Reg::R1,
7742 },
7743 ArmOp::Udiv {
7744 rd: Reg::R0,
7745 rn: Reg::PC,
7746 rm: Reg::R1,
7747 },
7748 ArmOp::Sdiv {
7749 rd: Reg::R0,
7750 rn: Reg::R1,
7751 rm: Reg::PC,
7752 },
7753 ] {
7754 let r = encoder.encode(&op);
7755 assert!(
7756 r.is_err(),
7757 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7758 );
7759 }
7760 assert!(
7762 encoder
7763 .encode(&ArmOp::Sdiv {
7764 rd: Reg::R0,
7765 rn: Reg::R1,
7766 rm: Reg::R2
7767 })
7768 .is_ok()
7769 );
7770 }
7771
7772 #[test]
7773 fn test_encode_nop_arm32() {
7774 let encoder = ArmEncoder::new_arm32();
7775 let code = encoder.encode(&ArmOp::Nop).unwrap();
7776
7777 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7780
7781 #[test]
7782 fn test_encode_nop_thumb() {
7783 let encoder = ArmEncoder::new_thumb2();
7784 let code = encoder.encode(&ArmOp::Nop).unwrap();
7785
7786 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7789
7790 #[test]
7791 fn test_encode_mov_immediate_arm32() {
7792 let encoder = ArmEncoder::new_arm32();
7793 let op = ArmOp::Mov {
7794 rd: Reg::R0,
7795 op2: Operand2::Imm(42),
7796 };
7797
7798 let code = encoder.encode(&op).unwrap();
7799 assert_eq!(code.len(), 4);
7800
7801 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7803 assert_eq!(instr & 0x0E000000, 0x02000000); }
7805
7806 #[test]
7807 fn test_encode_add_registers_arm32() {
7808 let encoder = ArmEncoder::new_arm32();
7809 let op = ArmOp::Add {
7810 rd: Reg::R0,
7811 rn: Reg::R1,
7812 op2: Operand2::Reg(Reg::R2),
7813 };
7814
7815 let code = encoder.encode(&op).unwrap();
7816 assert_eq!(code.len(), 4);
7817
7818 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7819 assert_eq!(instr & 0x0FE00000, 0x00800000);
7821 }
7822
7823 #[test]
7827 fn test_encode_add_imm_large_350() {
7828 let enc = ArmEncoder::new_thumb2();
7829
7830 let small = enc
7832 .encode_thumb32_add_imm(&Reg::R0, &Reg::R1, 0x123)
7833 .unwrap();
7834 assert_eq!(small.len(), 4, "small imm must stay a single instruction");
7835
7836 fn movx_imm16(b: &[u8]) -> u32 {
7838 let hw1 = u16::from_le_bytes([b[0], b[1]]) as u32;
7839 let hw2 = u16::from_le_bytes([b[2], b[3]]) as u32;
7840 let imm4 = hw1 & 0xF;
7841 let i = (hw1 >> 10) & 1;
7842 let imm3 = (hw2 >> 12) & 0x7;
7843 let imm8 = hw2 & 0xFF;
7844 (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8
7845 }
7846 fn movx_rd(b: &[u8]) -> u32 {
7847 (u16::from_le_bytes([b[2], b[3]]) as u32 >> 8) & 0xF
7848 }
7849
7850 let seq = enc
7853 .encode_thumb32_add_imm(&Reg::R12, &Reg::R0, 70000)
7854 .unwrap();
7855 assert_eq!(seq.len(), 12, "MOVW + MOVT + ADD = 12 bytes");
7856 assert_eq!(u16::from_le_bytes([seq[0], seq[1]]) & 0xFBF0, 0xF240);
7858 assert_eq!(movx_rd(&seq[0..4]), 12);
7859 assert_eq!(movx_imm16(&seq[0..4]), 0x1170);
7860 assert_eq!(u16::from_le_bytes([seq[4], seq[5]]) & 0xFBF0, 0xF2C0);
7862 assert_eq!(movx_rd(&seq[4..8]), 12);
7863 assert_eq!(movx_imm16(&seq[4..8]), 0x0001);
7864 let add1 = u16::from_le_bytes([seq[8], seq[9]]) as u32;
7866 let add2 = u16::from_le_bytes([seq[10], seq[11]]) as u32;
7867 assert_eq!(add1 & 0xFFF0, 0xEB00);
7868 assert_eq!(add1 & 0xF, 0); assert_eq!((add2 >> 8) & 0xF, 12); assert_eq!(add2 & 0xF, 12); assert_eq!(
7873 (movx_imm16(&seq[4..8]) << 16) | movx_imm16(&seq[0..4]),
7874 70000
7875 );
7876
7877 let seq16 = enc
7879 .encode_thumb32_add_imm(&Reg::R3, &Reg::R0, 0xABCD)
7880 .unwrap();
7881 assert_eq!(seq16.len(), 8, "imm <= 0xFFFF skips MOVT");
7882 assert_eq!(movx_imm16(&seq16[0..4]), 0xABCD);
7883 assert_eq!(movx_rd(&seq16[0..4]), 3); let inplace = enc
7888 .encode_thumb32_add_imm(&Reg::R5, &Reg::R5, 0x12345)
7889 .unwrap();
7890 assert_eq!(inplace.len(), 12);
7891 assert_eq!(movx_rd(&inplace[0..4]), 12, "rd==rn must use R12 scratch");
7892 assert_eq!(
7893 (movx_imm16(&inplace[4..8]) << 16) | movx_imm16(&inplace[0..4]),
7894 0x12345
7895 );
7896 let ip_add2 = u16::from_le_bytes([inplace[10], inplace[11]]) as u32;
7898 assert_eq!(ip_add2 & 0xF, 12);
7899 assert_eq!((ip_add2 >> 8) & 0xF, 5);
7900 }
7901
7902 #[test]
7910 fn test_encode_add_imm_large_rd_rn_r12_errs_not_panics_350() {
7911 let enc = ArmEncoder::new_thumb2();
7912 let r = enc.encode_thumb32_add_imm(&Reg::R12, &Reg::R12, 70000);
7914 assert!(
7915 r.is_err(),
7916 "rd==rn==R12 with out-of-range imm must Err (no free scratch), got {r:?}"
7917 );
7918 let small = enc.encode_thumb32_add_imm(&Reg::R12, &Reg::R12, 0x10);
7922 assert!(small.is_ok(), "small imm needs no scratch, must stay Ok");
7923 }
7924
7925 #[test]
7934 fn test_encode_operand2_non_rotatable_imm_errs_not_masks_378() {
7935 let enc = ArmEncoder::new_arm32();
7936 let bad = enc.encode(&ArmOp::Add {
7937 rd: Reg::R0,
7938 rn: Reg::R1,
7939 op2: Operand2::Imm(0x1FF),
7940 });
7941 assert!(
7942 bad.is_err(),
7943 "non-rotatable ARM32 immediate 0x1FF must Err (was silently masked \
7944 to 0xFF), got {bad:?}"
7945 );
7946 let ok = enc.encode(&ArmOp::Add {
7948 rd: Reg::R0,
7949 rn: Reg::R1,
7950 op2: Operand2::Imm(0xFF),
7951 });
7952 assert!(
7953 ok.is_ok(),
7954 "0xFF is a valid rotated immediate, must stay Ok"
7955 );
7956 }
7957
7958 #[test]
7959 fn test_encode_ldr_arm32() {
7960 let encoder = ArmEncoder::new_arm32();
7961 let op = ArmOp::Ldr {
7962 rd: Reg::R0,
7963 addr: MemAddr::imm(Reg::R1, 4),
7964 };
7965
7966 let code = encoder.encode(&op).unwrap();
7967 assert_eq!(code.len(), 4);
7968
7969 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7970 assert_eq!(instr & 0x00100000, 0x00100000);
7972 }
7973
7974 #[test]
7975 fn test_encode_str_arm32() {
7976 let encoder = ArmEncoder::new_arm32();
7977 let op = ArmOp::Str {
7978 rd: Reg::R0,
7979 addr: MemAddr::imm(Reg::SP, 0),
7980 };
7981
7982 let code = encoder.encode(&op).unwrap();
7983 assert_eq!(code.len(), 4);
7984 }
7985
7986 #[test]
7987 fn test_encode_branch_arm32() {
7988 let encoder = ArmEncoder::new_arm32();
7989 let op = ArmOp::Bl {
7990 label: "main".to_string(),
7991 };
7992
7993 let code = encoder.encode(&op).unwrap();
7994 assert_eq!(code.len(), 4);
7995
7996 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7997 assert_eq!(instr & 0x0F000000, 0x0B000000);
7999 }
8000
8001 #[test]
8011 fn test_encode_thumb_bl_placeholder_addend_167_174() {
8012 let encoder = ArmEncoder::new_thumb2();
8013 let op = ArmOp::Bl {
8014 label: "callee".to_string(),
8015 };
8016
8017 let code = encoder.encode(&op).unwrap();
8018 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
8019
8020 let hw1 = u16::from_le_bytes([code[0], code[1]]);
8021 let hw2 = u16::from_le_bytes([code[2], code[3]]);
8022 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
8023 assert_eq!(
8024 hw2, 0xFFFE,
8025 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
8026 );
8027 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
8028 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
8029 }
8030
8031 #[test]
8032 fn test_encode_sequence() {
8033 let encoder = ArmEncoder::new_arm32();
8034 let ops = vec![
8035 ArmOp::Mov {
8036 rd: Reg::R0,
8037 op2: Operand2::Imm(42),
8038 },
8039 ArmOp::Mov {
8040 rd: Reg::R1,
8041 op2: Operand2::Imm(10),
8042 },
8043 ArmOp::Add {
8044 rd: Reg::R2,
8045 rn: Reg::R0,
8046 op2: Operand2::Reg(Reg::R1),
8047 },
8048 ];
8049
8050 let code = encoder.encode_sequence(&ops).unwrap();
8051 assert_eq!(code.len(), 12); }
8053
8054 #[test]
8055 fn test_reg_to_bits() {
8056 assert_eq!(reg_to_bits(&Reg::R0), 0);
8057 assert_eq!(reg_to_bits(&Reg::R7), 7);
8058 assert_eq!(reg_to_bits(&Reg::SP), 13);
8059 assert_eq!(reg_to_bits(&Reg::LR), 14);
8060 assert_eq!(reg_to_bits(&Reg::PC), 15);
8061 }
8062
8063 #[test]
8064 fn test_encode_bitwise_operations() {
8065 let encoder = ArmEncoder::new_arm32();
8066
8067 let and_op = ArmOp::And {
8068 rd: Reg::R0,
8069 rn: Reg::R1,
8070 op2: Operand2::Reg(Reg::R2),
8071 };
8072 let and_code = encoder.encode(&and_op).unwrap();
8073 assert_eq!(and_code.len(), 4);
8074
8075 let orr_op = ArmOp::Orr {
8076 rd: Reg::R0,
8077 rn: Reg::R1,
8078 op2: Operand2::Reg(Reg::R2),
8079 };
8080 let orr_code = encoder.encode(&orr_op).unwrap();
8081 assert_eq!(orr_code.len(), 4);
8082
8083 let eor_op = ArmOp::Eor {
8084 rd: Reg::R0,
8085 rn: Reg::R1,
8086 op2: Operand2::Reg(Reg::R2),
8087 };
8088 let eor_code = encoder.encode(&eor_op).unwrap();
8089 assert_eq!(eor_code.len(), 4);
8090 }
8091
8092 #[test]
8095 fn test_encode_sdiv_thumb2() {
8096 let encoder = ArmEncoder::new_thumb2();
8097 let op = ArmOp::Sdiv {
8098 rd: Reg::R0,
8099 rn: Reg::R1,
8100 rm: Reg::R2,
8101 };
8102
8103 let code = encoder.encode(&op).unwrap();
8104 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
8111 assert_eq!(code[1], 0xFB);
8112 assert_eq!(code[2], 0xF2);
8113 assert_eq!(code[3], 0xF0);
8114 }
8115
8116 #[test]
8117 fn test_encode_udiv_thumb2() {
8118 let encoder = ArmEncoder::new_thumb2();
8119 let op = ArmOp::Udiv {
8120 rd: Reg::R0,
8121 rn: Reg::R1,
8122 rm: Reg::R2,
8123 };
8124
8125 let code = encoder.encode(&op).unwrap();
8126 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
8131 assert_eq!(code[1], 0xFB);
8132 assert_eq!(code[2], 0xF2);
8133 assert_eq!(code[3], 0xF0);
8134 }
8135
8136 #[test]
8137 fn test_encode_mul_thumb2() {
8138 let encoder = ArmEncoder::new_thumb2();
8139 let op = ArmOp::Mul {
8140 rd: Reg::R0,
8141 rn: Reg::R1,
8142 rm: Reg::R2,
8143 };
8144
8145 let code = encoder.encode(&op).unwrap();
8146 assert_eq!(code.len(), 4); }
8148
8149 #[test]
8150 fn test_encode_and_thumb2() {
8151 let encoder = ArmEncoder::new_thumb2();
8152 let op = ArmOp::And {
8153 rd: Reg::R0,
8154 rn: Reg::R1,
8155 op2: Operand2::Reg(Reg::R2),
8156 };
8157
8158 let code = encoder.encode(&op).unwrap();
8159 assert_eq!(code.len(), 4); }
8161
8162 #[test]
8163 fn test_encode_lsl_thumb2_low_regs() {
8164 let encoder = ArmEncoder::new_thumb2();
8165 let op = ArmOp::Lsl {
8166 rd: Reg::R0,
8167 rn: Reg::R1,
8168 shift: 5,
8169 };
8170
8171 let code = encoder.encode(&op).unwrap();
8172 assert_eq!(code.len(), 2); }
8174
8175 #[test]
8176 fn test_encode_clz_thumb2() {
8177 let encoder = ArmEncoder::new_thumb2();
8178 let op = ArmOp::Clz {
8179 rd: Reg::R0,
8180 rm: Reg::R1,
8181 };
8182
8183 let code = encoder.encode(&op).unwrap();
8184 assert_eq!(code.len(), 4); }
8186
8187 #[test]
8188 fn test_encode_bx_thumb2() {
8189 let encoder = ArmEncoder::new_thumb2();
8190 let op = ArmOp::Bx { rm: Reg::LR };
8191
8192 let code = encoder.encode(&op).unwrap();
8193 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
8197 }
8198
8199 #[test]
8204 fn test_encode_f32_abs_arm32() {
8205 let encoder = ArmEncoder::new_arm32();
8206 let op = ArmOp::F32Abs {
8207 sd: VfpReg::S0,
8208 sm: VfpReg::S2,
8209 };
8210 let code = encoder.encode(&op).unwrap();
8211 assert_eq!(code.len(), 4); }
8213
8214 #[test]
8215 fn test_encode_f32_neg_arm32() {
8216 let encoder = ArmEncoder::new_arm32();
8217 let op = ArmOp::F32Neg {
8218 sd: VfpReg::S0,
8219 sm: VfpReg::S2,
8220 };
8221 let code = encoder.encode(&op).unwrap();
8222 assert_eq!(code.len(), 4);
8223 }
8224
8225 #[test]
8226 fn test_encode_f32_sqrt_arm32() {
8227 let encoder = ArmEncoder::new_arm32();
8228 let op = ArmOp::F32Sqrt {
8229 sd: VfpReg::S0,
8230 sm: VfpReg::S2,
8231 };
8232 let code = encoder.encode(&op).unwrap();
8233 assert_eq!(code.len(), 4);
8234 }
8235
8236 #[test]
8237 fn test_encode_f32_ceil_arm32() {
8238 let encoder = ArmEncoder::new_arm32();
8239 let op = ArmOp::F32Ceil {
8240 sd: VfpReg::S0,
8241 sm: VfpReg::S2,
8242 };
8243 let code = encoder.encode(&op).unwrap();
8244 assert_eq!(code.len(), 36);
8246 }
8247
8248 #[test]
8249 fn test_encode_f32_floor_thumb2() {
8250 let encoder = ArmEncoder::new_thumb2();
8251 let op = ArmOp::F32Floor {
8252 sd: VfpReg::S0,
8253 sm: VfpReg::S2,
8254 };
8255 let code = encoder.encode(&op).unwrap();
8256 assert_eq!(code.len(), 36);
8258 }
8259
8260 #[test]
8261 fn test_encode_f32_min_arm32() {
8262 let encoder = ArmEncoder::new_arm32();
8263 let op = ArmOp::F32Min {
8264 sd: VfpReg::S0,
8265 sn: VfpReg::S2,
8266 sm: VfpReg::S4,
8267 };
8268 let code = encoder.encode(&op).unwrap();
8269 assert_eq!(code.len(), 16); }
8271
8272 #[test]
8273 fn test_encode_f32_max_thumb2() {
8274 let encoder = ArmEncoder::new_thumb2();
8275 let op = ArmOp::F32Max {
8276 sd: VfpReg::S0,
8277 sn: VfpReg::S2,
8278 sm: VfpReg::S4,
8279 };
8280 let code = encoder.encode(&op).unwrap();
8281 assert_eq!(code.len(), 18);
8283 }
8284
8285 #[test]
8286 fn test_encode_f32_copysign_arm32() {
8287 let encoder = ArmEncoder::new_arm32();
8288 let op = ArmOp::F32Copysign {
8289 sd: VfpReg::S0,
8290 sn: VfpReg::S2,
8291 sm: VfpReg::S4,
8292 };
8293 let code = encoder.encode(&op).unwrap();
8294 assert_eq!(code.len(), 24);
8296 }
8297
8298 #[test]
8303 fn test_encode_f64_add_arm32() {
8304 let encoder = ArmEncoder::new_arm32();
8305 let op = ArmOp::F64Add {
8306 dd: VfpReg::D0,
8307 dn: VfpReg::D1,
8308 dm: VfpReg::D2,
8309 };
8310 let code = encoder.encode(&op).unwrap();
8311 assert_eq!(code.len(), 4);
8312 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8314 assert_eq!((instr >> 8) & 0xF, 0xB); }
8316
8317 #[test]
8318 fn test_encode_f64_sub_thumb2() {
8319 let encoder = ArmEncoder::new_thumb2();
8320 let op = ArmOp::F64Sub {
8321 dd: VfpReg::D0,
8322 dn: VfpReg::D1,
8323 dm: VfpReg::D2,
8324 };
8325 let code = encoder.encode(&op).unwrap();
8326 assert_eq!(code.len(), 4); }
8328
8329 #[test]
8330 fn test_encode_f64_mul_arm32() {
8331 let encoder = ArmEncoder::new_arm32();
8332 let op = ArmOp::F64Mul {
8333 dd: VfpReg::D0,
8334 dn: VfpReg::D1,
8335 dm: VfpReg::D2,
8336 };
8337 let code = encoder.encode(&op).unwrap();
8338 assert_eq!(code.len(), 4);
8339 }
8340
8341 #[test]
8342 fn test_encode_f64_div_arm32() {
8343 let encoder = ArmEncoder::new_arm32();
8344 let op = ArmOp::F64Div {
8345 dd: VfpReg::D0,
8346 dn: VfpReg::D1,
8347 dm: VfpReg::D2,
8348 };
8349 let code = encoder.encode(&op).unwrap();
8350 assert_eq!(code.len(), 4);
8351 }
8352
8353 #[test]
8354 fn test_encode_f64_abs_arm32() {
8355 let encoder = ArmEncoder::new_arm32();
8356 let op = ArmOp::F64Abs {
8357 dd: VfpReg::D0,
8358 dm: VfpReg::D2,
8359 };
8360 let code = encoder.encode(&op).unwrap();
8361 assert_eq!(code.len(), 4);
8362 }
8363
8364 #[test]
8365 fn test_encode_f64_neg_arm32() {
8366 let encoder = ArmEncoder::new_arm32();
8367 let op = ArmOp::F64Neg {
8368 dd: VfpReg::D0,
8369 dm: VfpReg::D2,
8370 };
8371 let code = encoder.encode(&op).unwrap();
8372 assert_eq!(code.len(), 4);
8373 }
8374
8375 #[test]
8376 fn test_encode_f64_sqrt_arm32() {
8377 let encoder = ArmEncoder::new_arm32();
8378 let op = ArmOp::F64Sqrt {
8379 dd: VfpReg::D0,
8380 dm: VfpReg::D2,
8381 };
8382 let code = encoder.encode(&op).unwrap();
8383 assert_eq!(code.len(), 4);
8384 }
8385
8386 #[test]
8387 fn test_encode_f64_load_arm32() {
8388 let encoder = ArmEncoder::new_arm32();
8389 let op = ArmOp::F64Load {
8390 dd: VfpReg::D0,
8391 addr: MemAddr::imm(Reg::R0, 8),
8392 };
8393 let code = encoder.encode(&op).unwrap();
8394 assert_eq!(code.len(), 4);
8395 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8396 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
8399
8400 #[test]
8401 fn test_encode_f64_store_thumb2() {
8402 let encoder = ArmEncoder::new_thumb2();
8403 let op = ArmOp::F64Store {
8404 dd: VfpReg::D0,
8405 addr: MemAddr::imm(Reg::SP, 0),
8406 };
8407 let code = encoder.encode(&op).unwrap();
8408 assert_eq!(code.len(), 4);
8409 }
8410
8411 #[test]
8412 fn test_encode_f64_compare_arm32() {
8413 let encoder = ArmEncoder::new_arm32();
8414 let op = ArmOp::F64Eq {
8415 rd: Reg::R0,
8416 dn: VfpReg::D0,
8417 dm: VfpReg::D1,
8418 };
8419 let code = encoder.encode(&op).unwrap();
8420 assert_eq!(code.len(), 16); }
8422
8423 #[test]
8424 fn test_encode_f64_compare_thumb2() {
8425 let encoder = ArmEncoder::new_thumb2();
8426 let op = ArmOp::F64Lt {
8427 rd: Reg::R0,
8428 dn: VfpReg::D0,
8429 dm: VfpReg::D1,
8430 };
8431 let code = encoder.encode(&op).unwrap();
8432 assert_eq!(code.len(), 14);
8434 }
8435
8436 #[test]
8437 fn test_encode_f64_const_arm32() {
8438 let encoder = ArmEncoder::new_arm32();
8439 let op = ArmOp::F64Const {
8440 dd: VfpReg::D0,
8441 value: 3.125,
8442 };
8443 let code = encoder.encode(&op).unwrap();
8444 assert_eq!(code.len(), 20);
8446 }
8447
8448 #[test]
8449 fn test_encode_f64_const_thumb2() {
8450 let encoder = ArmEncoder::new_thumb2();
8451 let op = ArmOp::F64Const {
8452 dd: VfpReg::D0,
8453 value: 2.5,
8454 };
8455 let code = encoder.encode(&op).unwrap();
8456 assert_eq!(code.len(), 20);
8458 }
8459
8460 #[test]
8461 fn test_encode_f64_convert_i32s_arm32() {
8462 let encoder = ArmEncoder::new_arm32();
8463 let op = ArmOp::F64ConvertI32S {
8464 dd: VfpReg::D0,
8465 rm: Reg::R0,
8466 };
8467 let code = encoder.encode(&op).unwrap();
8468 assert_eq!(code.len(), 8);
8470 }
8471
8472 #[test]
8473 fn test_encode_f64_promote_f32_arm32() {
8474 let encoder = ArmEncoder::new_arm32();
8475 let op = ArmOp::F64PromoteF32 {
8476 dd: VfpReg::D0,
8477 sm: VfpReg::S0,
8478 };
8479 let code = encoder.encode(&op).unwrap();
8480 assert_eq!(code.len(), 4); }
8482
8483 #[test]
8484 fn test_encode_f64_promote_f32_thumb2() {
8485 let encoder = ArmEncoder::new_thumb2();
8486 let op = ArmOp::F64PromoteF32 {
8487 dd: VfpReg::D0,
8488 sm: VfpReg::S0,
8489 };
8490 let code = encoder.encode(&op).unwrap();
8491 assert_eq!(code.len(), 4);
8492 }
8493
8494 #[test]
8495 fn test_encode_i32_trunc_f64s_arm32() {
8496 let encoder = ArmEncoder::new_arm32();
8497 let op = ArmOp::I32TruncF64S {
8498 rd: Reg::R0,
8499 dm: VfpReg::D0,
8500 };
8501 let code = encoder.encode(&op).unwrap();
8502 assert_eq!(code.len(), 8);
8504 }
8505
8506 #[test]
8507 fn test_encode_f64_reinterpret_i64_arm32() {
8508 let encoder = ArmEncoder::new_arm32();
8509 let op = ArmOp::F64ReinterpretI64 {
8510 dd: VfpReg::D0,
8511 rmlo: Reg::R0,
8512 rmhi: Reg::R1,
8513 };
8514 let code = encoder.encode(&op).unwrap();
8515 assert_eq!(code.len(), 4); }
8517
8518 #[test]
8519 fn test_encode_i64_reinterpret_f64_thumb2() {
8520 let encoder = ArmEncoder::new_thumb2();
8521 let op = ArmOp::I64ReinterpretF64 {
8522 rdlo: Reg::R0,
8523 rdhi: Reg::R1,
8524 dm: VfpReg::D0,
8525 };
8526 let code = encoder.encode(&op).unwrap();
8527 assert_eq!(code.len(), 4);
8528 }
8529
8530 #[test]
8531 fn test_encode_f64_trunc_thumb2() {
8532 let encoder = ArmEncoder::new_thumb2();
8533 let op = ArmOp::F64Trunc {
8534 dd: VfpReg::D0,
8535 dm: VfpReg::D1,
8536 };
8537 let code = encoder.encode(&op).unwrap();
8538 assert_eq!(code.len(), 8);
8540 }
8541
8542 #[test]
8543 fn test_encode_f64_min_arm32() {
8544 let encoder = ArmEncoder::new_arm32();
8545 let op = ArmOp::F64Min {
8546 dd: VfpReg::D0,
8547 dn: VfpReg::D1,
8548 dm: VfpReg::D2,
8549 };
8550 let code = encoder.encode(&op).unwrap();
8551 assert_eq!(code.len(), 16);
8553 }
8554
8555 #[test]
8556 fn test_f64_cp11_encoding() {
8557 let encoder = ArmEncoder::new_arm32();
8559
8560 let code = encoder
8562 .encode(&ArmOp::F64Add {
8563 dd: VfpReg::D0,
8564 dn: VfpReg::D0,
8565 dm: VfpReg::D0,
8566 })
8567 .unwrap();
8568 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8569 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8570
8571 let code = encoder
8573 .encode(&ArmOp::F32Add {
8574 sd: VfpReg::S0,
8575 sn: VfpReg::S0,
8576 sm: VfpReg::S0,
8577 })
8578 .unwrap();
8579 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8580 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8581 }
8582
8583 #[test]
8584 fn test_dreg_encoding_higher_registers() {
8585 let encoder = ArmEncoder::new_arm32();
8586
8587 let op = ArmOp::F64Add {
8589 dd: VfpReg::D15,
8590 dn: VfpReg::D14,
8591 dm: VfpReg::D13,
8592 };
8593 let code = encoder.encode(&op).unwrap();
8594 assert_eq!(code.len(), 4);
8595
8596 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8598 assert_eq!((instr >> 8) & 0xF, 0xB); }
8600
8601 #[test]
8606 fn test_encode_label_emits_no_bytes() {
8607 let encoder = ArmEncoder::new_thumb2();
8608 let op = ArmOp::Label {
8609 name: ".Lblock_end_0".to_string(),
8610 };
8611 let code = encoder.encode(&op).unwrap();
8612 assert!(code.is_empty(), "Label should emit zero bytes");
8613
8614 let encoder32 = ArmEncoder::new_arm32();
8615 let code32 = encoder32.encode(&op).unwrap();
8616 assert!(
8617 code32.is_empty(),
8618 "Label should emit zero bytes in ARM32 too"
8619 );
8620 }
8621
8622 #[test]
8623 fn test_encode_bcc_eq_thumb2() {
8624 use synth_synthesis::Condition;
8625 let encoder = ArmEncoder::new_thumb2();
8626 let op = ArmOp::Bcc {
8627 cond: Condition::EQ,
8628 label: "target".to_string(),
8629 };
8630 let code = encoder.encode(&op).unwrap();
8631 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8635 }
8636
8637 #[test]
8638 fn test_encode_bcc_ne_thumb2() {
8639 use synth_synthesis::Condition;
8640 let encoder = ArmEncoder::new_thumb2();
8641 let op = ArmOp::Bcc {
8642 cond: Condition::NE,
8643 label: "target".to_string(),
8644 };
8645 let code = encoder.encode(&op).unwrap();
8646 assert_eq!(code.len(), 2);
8647
8648 assert_eq!(code, vec![0x00, 0xD1]);
8650 }
8651
8652 #[test]
8653 fn test_encode_bcc_arm32() {
8654 use synth_synthesis::Condition;
8655 let encoder = ArmEncoder::new_arm32();
8656 let op = ArmOp::Bcc {
8657 cond: Condition::EQ,
8658 label: "target".to_string(),
8659 };
8660 let code = encoder.encode(&op).unwrap();
8661 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8664 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8668
8669 #[test]
8670 fn test_encode_udf_thumb2() {
8671 let encoder = ArmEncoder::new_thumb2();
8672 let op = ArmOp::Udf { imm: 0 };
8673 let code = encoder.encode(&op).unwrap();
8674 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8678 }
8679
8680 #[test]
8681 fn test_encode_nop_thumb2() {
8682 let encoder = ArmEncoder::new_thumb2();
8683 let op = ArmOp::Nop;
8684 let code = encoder.encode(&op).unwrap();
8685 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8689 }
8690
8691 #[test]
8696 fn test_encode_i64_add_thumb2() {
8697 let encoder = ArmEncoder::new_thumb2();
8698 let op = ArmOp::I64Add {
8699 rdlo: Reg::R0,
8700 rdhi: Reg::R1,
8701 rnlo: Reg::R0,
8702 rnhi: Reg::R1,
8703 rmlo: Reg::R2,
8704 rmhi: Reg::R3,
8705 };
8706 let code = encoder.encode(&op).unwrap();
8707 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8709 }
8710
8711 #[test]
8712 fn test_encode_i64_sub_thumb2() {
8713 let encoder = ArmEncoder::new_thumb2();
8714 let op = ArmOp::I64Sub {
8715 rdlo: Reg::R0,
8716 rdhi: Reg::R1,
8717 rnlo: Reg::R0,
8718 rnhi: Reg::R1,
8719 rmlo: Reg::R2,
8720 rmhi: Reg::R3,
8721 };
8722 let code = encoder.encode(&op).unwrap();
8723 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8725 }
8726
8727 #[test]
8728 fn test_encode_i64_and_thumb2() {
8729 let encoder = ArmEncoder::new_thumb2();
8730 let op = ArmOp::I64And {
8731 rdlo: Reg::R0,
8732 rdhi: Reg::R1,
8733 rnlo: Reg::R0,
8734 rnhi: Reg::R1,
8735 rmlo: Reg::R2,
8736 rmhi: Reg::R3,
8737 };
8738 let code = encoder.encode(&op).unwrap();
8739 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8741 }
8742
8743 #[test]
8744 fn test_encode_i64_or_thumb2() {
8745 let encoder = ArmEncoder::new_thumb2();
8746 let op = ArmOp::I64Or {
8747 rdlo: Reg::R0,
8748 rdhi: Reg::R1,
8749 rnlo: Reg::R0,
8750 rnhi: Reg::R1,
8751 rmlo: Reg::R2,
8752 rmhi: Reg::R3,
8753 };
8754 let code = encoder.encode(&op).unwrap();
8755 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8756 }
8757
8758 #[test]
8759 fn test_encode_i64_xor_thumb2() {
8760 let encoder = ArmEncoder::new_thumb2();
8761 let op = ArmOp::I64Xor {
8762 rdlo: Reg::R0,
8763 rdhi: Reg::R1,
8764 rnlo: Reg::R0,
8765 rnhi: Reg::R1,
8766 rmlo: Reg::R2,
8767 rmhi: Reg::R3,
8768 };
8769 let code = encoder.encode(&op).unwrap();
8770 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8771 }
8772
8773 #[test]
8774 fn test_encode_i64_const_small_thumb2() {
8775 let encoder = ArmEncoder::new_thumb2();
8776 let op = ArmOp::I64Const {
8778 rdlo: Reg::R0,
8779 rdhi: Reg::R1,
8780 value: 42,
8781 };
8782 let code = encoder.encode(&op).unwrap();
8783 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8785 }
8786
8787 #[test]
8788 fn test_encode_i64_const_large_thumb2() {
8789 let encoder = ArmEncoder::new_thumb2();
8790 let op = ArmOp::I64Const {
8792 rdlo: Reg::R0,
8793 rdhi: Reg::R1,
8794 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8795 };
8796 let code = encoder.encode(&op).unwrap();
8797 assert_eq!(
8799 code.len(),
8800 16,
8801 "I64Const with large value should be 16 bytes"
8802 );
8803 }
8804
8805 #[test]
8806 fn test_encode_i64_extend_i32_s_thumb2() {
8807 let encoder = ArmEncoder::new_thumb2();
8808 let op = ArmOp::I64ExtendI32S {
8809 rdlo: Reg::R0,
8810 rdhi: Reg::R1,
8811 rn: Reg::R0,
8812 };
8813 let code = encoder.encode(&op).unwrap();
8814 assert_eq!(
8816 code.len(),
8817 4,
8818 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8819 );
8820 }
8821
8822 #[test]
8823 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8824 let encoder = ArmEncoder::new_thumb2();
8825 let op = ArmOp::I64ExtendI32S {
8826 rdlo: Reg::R0,
8827 rdhi: Reg::R1,
8828 rn: Reg::R2,
8829 };
8830 let code = encoder.encode(&op).unwrap();
8831 assert!(
8833 code.len() >= 6,
8834 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8835 );
8836 }
8837
8838 #[test]
8839 fn test_encode_i64_extend_i32_u_thumb2() {
8840 let encoder = ArmEncoder::new_thumb2();
8841 let op = ArmOp::I64ExtendI32U {
8842 rdlo: Reg::R0,
8843 rdhi: Reg::R1,
8844 rn: Reg::R0,
8845 };
8846 let code = encoder.encode(&op).unwrap();
8847 assert_eq!(
8849 code.len(),
8850 2,
8851 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8852 );
8853 }
8854
8855 #[test]
8856 fn test_encode_i32_wrap_i64_nop_thumb2() {
8857 let encoder = ArmEncoder::new_thumb2();
8858 let op = ArmOp::I32WrapI64 {
8860 rd: Reg::R0,
8861 rnlo: Reg::R0,
8862 };
8863 let code = encoder.encode(&op).unwrap();
8864 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8865 assert_eq!(code, vec![0x00, 0xBF]); }
8867
8868 #[test]
8869 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8870 let encoder = ArmEncoder::new_thumb2();
8871 let op = ArmOp::I32WrapI64 {
8872 rd: Reg::R2,
8873 rnlo: Reg::R0,
8874 };
8875 let code = encoder.encode(&op).unwrap();
8876 assert!(
8878 code.len() >= 2,
8879 "I32WrapI64 diff reg should emit at least 2 bytes"
8880 );
8881 }
8882
8883 #[test]
8884 fn test_encode_i64_eqz_thumb2() {
8885 let encoder = ArmEncoder::new_thumb2();
8886 let op = ArmOp::I64Eqz {
8887 rd: Reg::R0,
8888 rnlo: Reg::R0,
8889 rnhi: Reg::R1,
8890 };
8891 let code = encoder.encode(&op).unwrap();
8892 assert!(
8894 code.len() >= 6,
8895 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8896 );
8897 }
8898
8899 #[test]
8900 fn test_encode_i64_eq_thumb2() {
8901 let encoder = ArmEncoder::new_thumb2();
8902 let op = ArmOp::I64Eq {
8903 rd: Reg::R0,
8904 rnlo: Reg::R0,
8905 rnhi: Reg::R1,
8906 rmlo: Reg::R2,
8907 rmhi: Reg::R3,
8908 };
8909 let code = encoder.encode(&op).unwrap();
8910 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8912 }
8913
8914 #[test]
8915 fn test_encode_i64_ldr_thumb2() {
8916 let encoder = ArmEncoder::new_thumb2();
8917 let op = ArmOp::I64Ldr {
8918 rdlo: Reg::R0,
8919 rdhi: Reg::R1,
8920 addr: MemAddr::imm(Reg::SP, 0),
8921 };
8922 let code = encoder.encode(&op).unwrap();
8923 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8925 }
8926
8927 #[test]
8928 fn test_372_i64_ldr_indexed_materializes_address() {
8929 let encoder = ArmEncoder::new_thumb2();
8934 let indexed = encoder
8935 .encode(&ArmOp::I64Ldr {
8936 rdlo: Reg::R0,
8937 rdhi: Reg::R1,
8938 addr: MemAddr::reg_imm(Reg::R11, Reg::R0, 0),
8939 })
8940 .unwrap();
8941 assert_eq!(
8943 &indexed[0..4],
8944 &[0x0b, 0xeb, 0x00, 0x0c],
8945 "indexed I64Ldr must start with ADD.W ip, base, index"
8946 );
8947 let frame = encoder
8948 .encode(&ArmOp::I64Ldr {
8949 rdlo: Reg::R0,
8950 rdhi: Reg::R1,
8951 addr: MemAddr::imm(Reg::SP, 8),
8952 })
8953 .unwrap();
8954 assert_ne!(
8956 &frame[0..2],
8957 &[0x0b, 0xeb],
8958 "frame (non-indexed) I64Ldr must NOT emit an ADD.W"
8959 );
8960 }
8961
8962 #[test]
8963 fn test_382_i64_ldst_large_offset_materializes_not_skips() {
8964 let encoder = ArmEncoder::new_thumb2();
8970 let ld = encoder
8973 .encode(&ArmOp::I64Ldr {
8974 rdlo: Reg::R0,
8975 rdhi: Reg::R1,
8976 addr: MemAddr::reg_imm(Reg::R11, Reg::R0, 5000),
8977 })
8978 .expect("large-offset i64.load must lower, not skip");
8979 assert_eq!(ld.len(), 20, "expected MOVW + 2×ADD + 2×LDR");
8981 assert_ne!(
8984 &ld[0..2],
8985 &[0x0b, 0xeb],
8986 "must materialize the large offset"
8987 );
8988 assert_eq!(
8990 &ld[4..20],
8991 &[
8992 0x00, 0xeb, 0x0c, 0x0c, 0x0c, 0xeb, 0x0b, 0x0c, 0xdc, 0xf8, 0x00, 0x00, 0xdc, 0xf8, 0x04, 0x10, ],
8997 "large-offset i64.load must fold offset into ip and access [ip,#0]/[ip,#4]"
8998 );
8999
9000 let st = encoder
9002 .encode(&ArmOp::I64Str {
9003 rdlo: Reg::R2,
9004 rdhi: Reg::R3,
9005 addr: MemAddr::reg_imm(Reg::R11, Reg::R0, 5000),
9006 })
9007 .expect("large-offset i64.store must lower, not skip");
9008 assert_eq!(st.len(), 20);
9009 assert_eq!(
9010 &st[4..20],
9011 &[
9012 0x00, 0xeb, 0x0c, 0x0c, 0x0c, 0xeb, 0x0b, 0x0c, 0xcc, 0xf8, 0x00, 0x20, 0xcc, 0xf8, 0x04, 0x30, ],
9017 "large-offset i64.store must fold offset into ip and access [ip,#0]/[ip,#4]"
9018 );
9019
9020 let small = encoder
9024 .encode(&ArmOp::I64Ldr {
9025 rdlo: Reg::R0,
9026 rdhi: Reg::R1,
9027 addr: MemAddr::reg_imm(Reg::R11, Reg::R0, 8),
9028 })
9029 .unwrap();
9030 assert_eq!(
9031 &small[0..4],
9032 &[0x0b, 0xeb, 0x00, 0x0c],
9033 "small-offset indexed i64 must keep the single ADD.W ip, fp, r0"
9034 );
9035 assert_eq!(small.len(), 12, "ADD.W + 2×LDR.W (offset folded in imm12)");
9036 }
9037
9038 #[test]
9039 fn test_encode_i64_str_thumb2() {
9040 let encoder = ArmEncoder::new_thumb2();
9041 let op = ArmOp::I64Str {
9042 rdlo: Reg::R0,
9043 rdhi: Reg::R1,
9044 addr: MemAddr::imm(Reg::SP, 0),
9045 };
9046 let code = encoder.encode(&op).unwrap();
9047 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
9049 }
9050
9051 #[test]
9052 fn test_encode_i64_all_comparisons_thumb2() {
9053 let encoder = ArmEncoder::new_thumb2();
9054
9055 let ops = vec![
9056 ArmOp::I64Ne {
9057 rd: Reg::R0,
9058 rnlo: Reg::R0,
9059 rnhi: Reg::R1,
9060 rmlo: Reg::R2,
9061 rmhi: Reg::R3,
9062 },
9063 ArmOp::I64LtS {
9064 rd: Reg::R0,
9065 rnlo: Reg::R0,
9066 rnhi: Reg::R1,
9067 rmlo: Reg::R2,
9068 rmhi: Reg::R3,
9069 },
9070 ArmOp::I64LtU {
9071 rd: Reg::R0,
9072 rnlo: Reg::R0,
9073 rnhi: Reg::R1,
9074 rmlo: Reg::R2,
9075 rmhi: Reg::R3,
9076 },
9077 ArmOp::I64LeS {
9078 rd: Reg::R0,
9079 rnlo: Reg::R0,
9080 rnhi: Reg::R1,
9081 rmlo: Reg::R2,
9082 rmhi: Reg::R3,
9083 },
9084 ArmOp::I64LeU {
9085 rd: Reg::R0,
9086 rnlo: Reg::R0,
9087 rnhi: Reg::R1,
9088 rmlo: Reg::R2,
9089 rmhi: Reg::R3,
9090 },
9091 ArmOp::I64GtS {
9092 rd: Reg::R0,
9093 rnlo: Reg::R0,
9094 rnhi: Reg::R1,
9095 rmlo: Reg::R2,
9096 rmhi: Reg::R3,
9097 },
9098 ArmOp::I64GtU {
9099 rd: Reg::R0,
9100 rnlo: Reg::R0,
9101 rnhi: Reg::R1,
9102 rmlo: Reg::R2,
9103 rmhi: Reg::R3,
9104 },
9105 ArmOp::I64GeS {
9106 rd: Reg::R0,
9107 rnlo: Reg::R0,
9108 rnhi: Reg::R1,
9109 rmlo: Reg::R2,
9110 rmhi: Reg::R3,
9111 },
9112 ArmOp::I64GeU {
9113 rd: Reg::R0,
9114 rnlo: Reg::R0,
9115 rnhi: Reg::R1,
9116 rmlo: Reg::R2,
9117 rmhi: Reg::R3,
9118 },
9119 ];
9120
9121 for op in &ops {
9122 let code = encoder.encode(op).unwrap();
9123 assert!(
9124 code.len() >= 8,
9125 "i64 comparison {:?} should emit at least 8 bytes, got {}",
9126 op,
9127 code.len()
9128 );
9129 }
9130 }
9131
9132 #[test]
9133 fn test_encode_i64_const_zero_thumb2() {
9134 let encoder = ArmEncoder::new_thumb2();
9135 let op = ArmOp::I64Const {
9136 rdlo: Reg::R0,
9137 rdhi: Reg::R1,
9138 value: 0,
9139 };
9140 let code = encoder.encode(&op).unwrap();
9141 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
9143 }
9144
9145 #[test]
9146 fn test_encode_i64_const_negative_one_thumb2() {
9147 let encoder = ArmEncoder::new_thumb2();
9148 let op = ArmOp::I64Const {
9149 rdlo: Reg::R0,
9150 rdhi: Reg::R1,
9151 value: -1, };
9153 let code = encoder.encode(&op).unwrap();
9154 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
9156 }
9157
9158 #[test]
9163 fn test_encode_ldrb_arm32() {
9164 let encoder = ArmEncoder::new_arm32();
9165 let op = ArmOp::Ldrb {
9166 rd: Reg::R0,
9167 addr: MemAddr::imm(Reg::R1, 4),
9168 };
9169 let code = encoder.encode(&op).unwrap();
9170 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
9171 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9173 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
9174 }
9175
9176 #[test]
9177 fn test_encode_strb_arm32() {
9178 let encoder = ArmEncoder::new_arm32();
9179 let op = ArmOp::Strb {
9180 rd: Reg::R0,
9181 addr: MemAddr::imm(Reg::R1, 0),
9182 };
9183 let code = encoder.encode(&op).unwrap();
9184 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
9185 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9187 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
9188 }
9189
9190 #[test]
9191 fn test_encode_ldrh_arm32() {
9192 let encoder = ArmEncoder::new_arm32();
9193 let op = ArmOp::Ldrh {
9194 rd: Reg::R0,
9195 addr: MemAddr::imm(Reg::R1, 2),
9196 };
9197 let code = encoder.encode(&op).unwrap();
9198 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
9199 }
9200
9201 #[test]
9202 fn test_encode_strh_arm32() {
9203 let encoder = ArmEncoder::new_arm32();
9204 let op = ArmOp::Strh {
9205 rd: Reg::R0,
9206 addr: MemAddr::imm(Reg::R1, 0),
9207 };
9208 let code = encoder.encode(&op).unwrap();
9209 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
9210 }
9211
9212 #[test]
9213 fn test_encode_ldrsb_arm32() {
9214 let encoder = ArmEncoder::new_arm32();
9215 let op = ArmOp::Ldrsb {
9216 rd: Reg::R0,
9217 addr: MemAddr::imm(Reg::R1, 0),
9218 };
9219 let code = encoder.encode(&op).unwrap();
9220 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
9221 }
9222
9223 #[test]
9224 fn test_encode_ldrsh_arm32() {
9225 let encoder = ArmEncoder::new_arm32();
9226 let op = ArmOp::Ldrsh {
9227 rd: Reg::R0,
9228 addr: MemAddr::imm(Reg::R1, 0),
9229 };
9230 let code = encoder.encode(&op).unwrap();
9231 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
9232 }
9233
9234 #[test]
9235 fn test_encode_ldrb_thumb2_16bit() {
9236 let encoder = ArmEncoder::new_thumb2();
9237 let op = ArmOp::Ldrb {
9238 rd: Reg::R0,
9239 addr: MemAddr::imm(Reg::R1, 4),
9240 };
9241 let code = encoder.encode(&op).unwrap();
9242 assert_eq!(
9244 code.len(),
9245 2,
9246 "Thumb-2 LDRB with small offset should be 16-bit"
9247 );
9248 }
9249
9250 #[test]
9251 fn test_encode_ldrb_thumb2_32bit() {
9252 let encoder = ArmEncoder::new_thumb2();
9253 let op = ArmOp::Ldrb {
9254 rd: Reg::R0,
9255 addr: MemAddr::imm(Reg::R1, 100), };
9257 let code = encoder.encode(&op).unwrap();
9258 assert_eq!(
9259 code.len(),
9260 4,
9261 "Thumb-2 LDRB with large offset should be 32-bit"
9262 );
9263 }
9264
9265 #[test]
9266 fn test_encode_strb_thumb2_16bit() {
9267 let encoder = ArmEncoder::new_thumb2();
9268 let op = ArmOp::Strb {
9269 rd: Reg::R0,
9270 addr: MemAddr::imm(Reg::R1, 10),
9271 };
9272 let code = encoder.encode(&op).unwrap();
9273 assert_eq!(
9274 code.len(),
9275 2,
9276 "Thumb-2 STRB with small offset should be 16-bit"
9277 );
9278 }
9279
9280 #[test]
9281 fn test_encode_ldrh_thumb2_16bit() {
9282 let encoder = ArmEncoder::new_thumb2();
9283 let op = ArmOp::Ldrh {
9284 rd: Reg::R0,
9285 addr: MemAddr::imm(Reg::R1, 4), };
9287 let code = encoder.encode(&op).unwrap();
9288 assert_eq!(
9289 code.len(),
9290 2,
9291 "Thumb-2 LDRH with small aligned offset should be 16-bit"
9292 );
9293 }
9294
9295 #[test]
9296 fn test_encode_strh_thumb2_16bit() {
9297 let encoder = ArmEncoder::new_thumb2();
9298 let op = ArmOp::Strh {
9299 rd: Reg::R0,
9300 addr: MemAddr::imm(Reg::R1, 4),
9301 };
9302 let code = encoder.encode(&op).unwrap();
9303 assert_eq!(
9304 code.len(),
9305 2,
9306 "Thumb-2 STRH with small aligned offset should be 16-bit"
9307 );
9308 }
9309
9310 #[test]
9311 fn test_encode_ldrsb_thumb2() {
9312 let encoder = ArmEncoder::new_thumb2();
9313 let op = ArmOp::Ldrsb {
9314 rd: Reg::R0,
9315 addr: MemAddr::imm(Reg::R1, 0),
9316 };
9317 let code = encoder.encode(&op).unwrap();
9318 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
9320 }
9321
9322 #[test]
9323 fn test_encode_ldrsh_thumb2() {
9324 let encoder = ArmEncoder::new_thumb2();
9325 let op = ArmOp::Ldrsh {
9326 rd: Reg::R0,
9327 addr: MemAddr::imm(Reg::R1, 0),
9328 };
9329 let code = encoder.encode(&op).unwrap();
9330 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
9331 }
9332
9333 #[test]
9334 fn test_encode_memory_size_thumb2() {
9335 let encoder = ArmEncoder::new_thumb2();
9336 let op = ArmOp::MemorySize { rd: Reg::R0 };
9337 let code = encoder.encode(&op).unwrap();
9338 assert!(!code.is_empty(), "MemorySize should produce code");
9340 }
9341
9342 #[test]
9343 fn test_encode_memory_grow_thumb2() {
9344 let encoder = ArmEncoder::new_thumb2();
9345 let op = ArmOp::MemoryGrow {
9346 rd: Reg::R0,
9347 rn: Reg::R0,
9348 };
9349 let code = encoder.encode(&op).unwrap();
9350 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
9351 }
9352
9353 #[test]
9354 fn test_encode_subword_reg_offset_thumb2() {
9355 let encoder = ArmEncoder::new_thumb2();
9356
9357 let op = ArmOp::Ldrb {
9359 rd: Reg::R0,
9360 addr: MemAddr::reg(Reg::R1, Reg::R2),
9361 };
9362 let code = encoder.encode(&op).unwrap();
9363 assert_eq!(
9364 code.len(),
9365 4,
9366 "Thumb-2 LDRB with reg offset should be 32-bit"
9367 );
9368
9369 let op = ArmOp::Strb {
9371 rd: Reg::R0,
9372 addr: MemAddr::reg(Reg::R1, Reg::R2),
9373 };
9374 let code = encoder.encode(&op).unwrap();
9375 assert_eq!(
9376 code.len(),
9377 4,
9378 "Thumb-2 STRB with reg offset should be 32-bit"
9379 );
9380
9381 let op = ArmOp::Ldrh {
9383 rd: Reg::R0,
9384 addr: MemAddr::reg(Reg::R1, Reg::R2),
9385 };
9386 let code = encoder.encode(&op).unwrap();
9387 assert_eq!(
9388 code.len(),
9389 4,
9390 "Thumb-2 LDRH with reg offset should be 32-bit"
9391 );
9392
9393 let op = ArmOp::Strh {
9395 rd: Reg::R0,
9396 addr: MemAddr::reg(Reg::R1, Reg::R2),
9397 };
9398 let code = encoder.encode(&op).unwrap();
9399 assert_eq!(
9400 code.len(),
9401 4,
9402 "Thumb-2 STRH with reg offset should be 32-bit"
9403 );
9404 }
9405
9406 #[test]
9407 fn test_encode_subword_reg_imm_offset_thumb2() {
9408 let encoder = ArmEncoder::new_thumb2();
9409
9410 let op = ArmOp::Ldrb {
9412 rd: Reg::R0,
9413 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
9414 };
9415 let code = encoder.encode(&op).unwrap();
9416 assert_eq!(
9418 code.len(),
9419 8,
9420 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
9421 );
9422 }
9423
9424 #[test]
9429 fn test_encode_mve_addi32_thumb2() {
9430 let encoder = ArmEncoder::new_thumb2();
9431 let op = ArmOp::MveAddI {
9432 qd: QReg::Q0,
9433 qn: QReg::Q1,
9434 qm: QReg::Q2,
9435 size: MveSize::S32,
9436 };
9437 let code = encoder.encode(&op).unwrap();
9438 assert_eq!(
9439 code.len(),
9440 4,
9441 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
9442 );
9443 }
9444
9445 #[test]
9446 fn test_encode_mve_subi16_thumb2() {
9447 let encoder = ArmEncoder::new_thumb2();
9448 let op = ArmOp::MveSubI {
9449 qd: QReg::Q0,
9450 qn: QReg::Q1,
9451 qm: QReg::Q2,
9452 size: MveSize::S16,
9453 };
9454 let code = encoder.encode(&op).unwrap();
9455 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
9456 }
9457
9458 #[test]
9459 fn test_encode_mve_muli8_thumb2() {
9460 let encoder = ArmEncoder::new_thumb2();
9461 let op = ArmOp::MveMulI {
9462 qd: QReg::Q0,
9463 qn: QReg::Q1,
9464 qm: QReg::Q2,
9465 size: MveSize::S8,
9466 };
9467 let code = encoder.encode(&op).unwrap();
9468 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
9469 }
9470
9471 #[test]
9472 fn test_encode_mve_bitwise_thumb2() {
9473 let encoder = ArmEncoder::new_thumb2();
9474
9475 let ops = vec![
9476 ArmOp::MveAnd {
9477 qd: QReg::Q0,
9478 qn: QReg::Q1,
9479 qm: QReg::Q2,
9480 },
9481 ArmOp::MveOrr {
9482 qd: QReg::Q0,
9483 qn: QReg::Q1,
9484 qm: QReg::Q2,
9485 },
9486 ArmOp::MveEor {
9487 qd: QReg::Q0,
9488 qn: QReg::Q1,
9489 qm: QReg::Q2,
9490 },
9491 ArmOp::MveBic {
9492 qd: QReg::Q0,
9493 qn: QReg::Q1,
9494 qm: QReg::Q2,
9495 },
9496 ];
9497 for op in ops {
9498 let code = encoder.encode(&op).unwrap();
9499 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
9500 }
9501 }
9502
9503 #[test]
9504 fn test_encode_mve_mvn_thumb2() {
9505 let encoder = ArmEncoder::new_thumb2();
9506 let op = ArmOp::MveMvn {
9507 qd: QReg::Q0,
9508 qm: QReg::Q1,
9509 };
9510 let code = encoder.encode(&op).unwrap();
9511 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
9512 }
9513
9514 #[test]
9515 fn test_encode_mve_load_store_thumb2() {
9516 let encoder = ArmEncoder::new_thumb2();
9517
9518 let load = ArmOp::MveLoad {
9519 qd: QReg::Q0,
9520 addr: MemAddr::imm(Reg::R0, 16),
9521 };
9522 let code = encoder.encode(&load).unwrap();
9523 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
9524
9525 let store = ArmOp::MveStore {
9526 qd: QReg::Q1,
9527 addr: MemAddr::imm(Reg::R1, 0),
9528 };
9529 let code = encoder.encode(&store).unwrap();
9530 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
9531 }
9532
9533 #[test]
9534 fn test_encode_mve_const_thumb2() {
9535 let encoder = ArmEncoder::new_thumb2();
9536 let op = ArmOp::MveConst {
9537 qd: QReg::Q0,
9538 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
9539 };
9540 let code = encoder.encode(&op).unwrap();
9541 assert!(
9544 code.len() >= 24,
9545 "MVE const should produce multiple instructions"
9546 );
9547 }
9548
9549 #[test]
9550 fn test_encode_mve_dup_thumb2() {
9551 let encoder = ArmEncoder::new_thumb2();
9552 let op = ArmOp::MveDup {
9553 qd: QReg::Q0,
9554 rn: Reg::R0,
9555 size: MveSize::S32,
9556 };
9557 let code = encoder.encode(&op).unwrap();
9558 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
9559 }
9560
9561 #[test]
9562 fn test_encode_mve_extract_lane_thumb2() {
9563 let encoder = ArmEncoder::new_thumb2();
9564 let op = ArmOp::MveExtractLane {
9565 rd: Reg::R0,
9566 qn: QReg::Q1,
9567 lane: 2,
9568 size: MveSize::S32,
9569 };
9570 let code = encoder.encode(&op).unwrap();
9571 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
9572 }
9573
9574 #[test]
9575 fn test_encode_mve_insert_lane_thumb2() {
9576 let encoder = ArmEncoder::new_thumb2();
9577 let op = ArmOp::MveInsertLane {
9578 qd: QReg::Q0,
9579 rn: Reg::R1,
9580 lane: 3,
9581 size: MveSize::S32,
9582 };
9583 let code = encoder.encode(&op).unwrap();
9584 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9585 }
9586
9587 #[test]
9588 fn test_encode_mve_addf32_thumb2() {
9589 let encoder = ArmEncoder::new_thumb2();
9590 let op = ArmOp::MveAddF32 {
9591 qd: QReg::Q0,
9592 qn: QReg::Q1,
9593 qm: QReg::Q2,
9594 };
9595 let code = encoder.encode(&op).unwrap();
9596 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9597 }
9598
9599 #[test]
9600 fn test_encode_mve_divf32_thumb2() {
9601 let encoder = ArmEncoder::new_thumb2();
9602 let op = ArmOp::MveDivF32 {
9603 qd: QReg::Q0,
9604 qn: QReg::Q1,
9605 qm: QReg::Q2,
9606 };
9607 let code = encoder.encode(&op).unwrap();
9608 assert_eq!(
9610 code.len(),
9611 16,
9612 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9613 );
9614 }
9615
9616 #[test]
9617 fn test_encode_mve_sqrtf32_thumb2() {
9618 let encoder = ArmEncoder::new_thumb2();
9619 let op = ArmOp::MveSqrtF32 {
9620 qd: QReg::Q0,
9621 qm: QReg::Q1,
9622 };
9623 let code = encoder.encode(&op).unwrap();
9624 assert_eq!(
9626 code.len(),
9627 16,
9628 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9629 );
9630 }
9631
9632 #[test]
9633 fn test_encode_mve_negf32_thumb2() {
9634 let encoder = ArmEncoder::new_thumb2();
9635 let op = ArmOp::MveNegF32 {
9636 qd: QReg::Q0,
9637 qm: QReg::Q1,
9638 };
9639 let code = encoder.encode(&op).unwrap();
9640 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9641 }
9642
9643 #[test]
9644 fn test_encode_mve_absf32_thumb2() {
9645 let encoder = ArmEncoder::new_thumb2();
9646 let op = ArmOp::MveAbsF32 {
9647 qd: QReg::Q0,
9648 qm: QReg::Q1,
9649 };
9650 let code = encoder.encode(&op).unwrap();
9651 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9652 }
9653
9654 #[test]
9669 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9670 let encoder = ArmEncoder::new_thumb2();
9671 let op = ArmOp::And {
9672 rd: Reg::R2,
9673 rn: Reg::R0,
9674 op2: Operand2::Imm(0x7e),
9675 };
9676 let code = encoder.encode(&op).unwrap();
9677 assert_eq!(
9678 code,
9679 vec![0x00, 0xf0, 0x7e, 0x02],
9680 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9681 );
9682 }
9683
9684 #[test]
9691 fn try_thumb_expand_imm_encodes_modified_immediates() {
9692 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9694 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);
9702 assert_eq!(try_thumb_expand_imm(0x12345), None);
9703 }
9704
9705 #[test]
9710 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9711 let encoder = ArmEncoder::new_thumb2();
9712 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9714 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9715 assert!(
9717 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9718 "cmp #0x101 must error, not compare the wrong constant"
9719 );
9720 assert!(
9721 encoder
9722 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9723 .is_err()
9724 );
9725 assert!(
9726 encoder
9727 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9728 .is_err()
9729 );
9730 assert!(
9732 encoder
9733 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9734 .is_ok()
9735 );
9736 }
9737
9738 #[test]
9741 fn mla_thumb2_encodes_correctly() {
9742 let encoder = ArmEncoder::new_thumb2();
9743 let code = encoder
9744 .encode(&ArmOp::Mla {
9745 rd: Reg::R2,
9746 rn: Reg::R3,
9747 rm: Reg::R4,
9748 ra: Reg::R8,
9749 })
9750 .unwrap();
9751 assert_eq!(code, vec![0x03, 0xfb, 0x04, 0x82]);
9753 }
9754
9755 #[test]
9760 fn ldst_imm12_offset_errors_when_out_of_range() {
9761 let encoder = ArmEncoder::new_thumb2();
9762 assert!(
9764 encoder
9765 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0xFFF)
9766 .is_ok()
9767 );
9768 assert!(
9770 encoder
9771 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0x1000)
9772 .is_err(),
9773 "ldr offset 4096 must error, not wrap to 0"
9774 );
9775 assert!(
9776 encoder
9777 .encode_thumb32_str(&Reg::R0, &Reg::R1, 0x1000)
9778 .is_err()
9779 );
9780 assert!(
9781 encoder
9782 .encode_thumb32_ldrb_imm(&Reg::R0, &Reg::R1, 5000)
9783 .is_err()
9784 );
9785 assert!(
9786 encoder
9787 .encode_thumb32_strh_imm(&Reg::R0, &Reg::R1, 5000)
9788 .is_err()
9789 );
9790 }
9791
9792 #[test]
9799 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9800 let encoder = ArmEncoder::new_thumb2();
9801 assert_eq!(
9803 encoder
9804 .encode(&ArmOp::Add {
9805 rd: Reg::SP,
9806 rn: Reg::SP,
9807 op2: Operand2::Imm(256),
9808 })
9809 .unwrap(),
9810 vec![0x0d, 0xf2, 0x00, 0x1d],
9811 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9812 );
9813 assert_eq!(
9815 encoder
9816 .encode(&ArmOp::Sub {
9817 rd: Reg::SP,
9818 rn: Reg::SP,
9819 op2: Operand2::Imm(256),
9820 })
9821 .unwrap(),
9822 vec![0xad, 0xf2, 0x00, 0x1d],
9823 );
9824 assert!(
9826 encoder
9827 .encode(&ArmOp::Add {
9828 rd: Reg::SP,
9829 rn: Reg::SP,
9830 op2: Operand2::Imm(5000),
9831 })
9832 .is_err(),
9833 "add #5000 must error (no single ADDW), not mis-encode"
9834 );
9835 }
9836
9837 #[test]
9842 fn and_cmn_immediate_thumb_expand_else_error() {
9843 let encoder = ArmEncoder::new_thumb2();
9844 assert_eq!(
9846 encoder
9847 .encode(&ArmOp::And {
9848 rd: Reg::R2,
9849 rn: Reg::R0,
9850 op2: Operand2::Imm(0x7e),
9851 })
9852 .unwrap(),
9853 vec![0x00, 0xf0, 0x7e, 0x02],
9854 );
9855 assert!(
9857 encoder
9858 .encode(&ArmOp::And {
9859 rd: Reg::R2,
9860 rn: Reg::R0,
9861 op2: Operand2::Imm(0xff00ff00u32 as i32),
9862 })
9863 .is_ok()
9864 );
9865 assert!(
9867 encoder
9868 .encode(&ArmOp::And {
9869 rd: Reg::R2,
9870 rn: Reg::R0,
9871 op2: Operand2::Imm(0x101),
9872 })
9873 .is_err()
9874 );
9875 assert!(
9876 encoder
9877 .encode(&ArmOp::Cmn {
9878 rn: Reg::R0,
9879 op2: Operand2::Imm(0x101),
9880 })
9881 .is_err(),
9882 "CMN #0x101 must error, not emit a NOP"
9883 );
9884 }
9885
9886 #[test]
9890 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9891 let encoder = ArmEncoder::new_thumb2();
9892 assert_eq!(
9894 encoder
9895 .encode(&ArmOp::Orr {
9896 rd: Reg::R2,
9897 rn: Reg::R0,
9898 op2: Operand2::Imm(0x7e),
9899 })
9900 .unwrap(),
9901 vec![0x40, 0xf0, 0x7e, 0x02],
9902 );
9903 assert_eq!(
9905 encoder
9906 .encode(&ArmOp::Eor {
9907 rd: Reg::R2,
9908 rn: Reg::R0,
9909 op2: Operand2::Imm(0x7e),
9910 })
9911 .unwrap(),
9912 vec![0x80, 0xf0, 0x7e, 0x02],
9913 );
9914 assert!(
9916 encoder
9917 .encode(&ArmOp::Orr {
9918 rd: Reg::R2,
9919 rn: Reg::R0,
9920 op2: Operand2::Imm(0x140),
9921 })
9922 .is_err(),
9923 "ORR #0x140 must error, not emit a NOP"
9924 );
9925 }
9926
9927 #[test]
9928 fn test_encode_mve_different_qregs() {
9929 let encoder = ArmEncoder::new_thumb2();
9930
9931 let op1 = ArmOp::MveAddI {
9933 qd: QReg::Q0,
9934 qn: QReg::Q0,
9935 qm: QReg::Q0,
9936 size: MveSize::S32,
9937 };
9938 let op2 = ArmOp::MveAddI {
9939 qd: QReg::Q3,
9940 qn: QReg::Q5,
9941 qm: QReg::Q7,
9942 size: MveSize::S32,
9943 };
9944 let code1 = encoder.encode(&op1).unwrap();
9945 let code2 = encoder.encode(&op2).unwrap();
9946 assert_ne!(
9947 code1, code2,
9948 "Different Q-registers should produce different encodings"
9949 );
9950 }
9951
9952 #[test]
9953 fn test_encode_mve_arm32_nop() {
9954 let encoder = ArmEncoder::new_arm32();
9956 let op = ArmOp::MveAddI {
9957 qd: QReg::Q0,
9958 qn: QReg::Q1,
9959 qm: QReg::Q2,
9960 size: MveSize::S32,
9961 };
9962 let code = encoder.encode(&op).unwrap();
9963 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9964 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9966 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9967 }
9968}