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::And { rd, rn, op2 } => {
247 let rd_bits = reg_to_bits(rd);
248 let rn_bits = reg_to_bits(rn);
249 let (op2_bits, i_flag) = encode_operand2(op2);
250
251 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
253 }
254
255 ArmOp::Orr { rd, rn, op2 } => {
256 let rd_bits = reg_to_bits(rd);
257 let rn_bits = reg_to_bits(rn);
258 let (op2_bits, i_flag) = encode_operand2(op2);
259
260 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
262 }
263
264 ArmOp::Eor { rd, rn, op2 } => {
265 let rd_bits = reg_to_bits(rd);
266 let rn_bits = reg_to_bits(rn);
267 let (op2_bits, i_flag) = encode_operand2(op2);
268
269 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
271 }
272
273 ArmOp::Lsl { rd, rn, shift } => {
275 let rd_bits = reg_to_bits(rd);
276 let rn_bits = reg_to_bits(rn);
277 let shift_bits = *shift & 0x1F;
278
279 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
281 }
282
283 ArmOp::Lsr { rd, rn, shift } => {
284 let rd_bits = reg_to_bits(rd);
285 let rn_bits = reg_to_bits(rn);
286 let shift_bits = *shift & 0x1F;
287
288 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
290 }
291
292 ArmOp::Asr { rd, rn, shift } => {
293 let rd_bits = reg_to_bits(rd);
294 let rn_bits = reg_to_bits(rn);
295 let shift_bits = *shift & 0x1F;
296
297 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
299 }
300
301 ArmOp::Ror { rd, rn, shift } => {
302 let rd_bits = reg_to_bits(rd);
303 let rn_bits = reg_to_bits(rn);
304 let shift_bits = *shift & 0x1F;
305
306 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
308 }
309
310 ArmOp::LslReg { rd, rn, rm } => {
313 let rd_bits = reg_to_bits(rd);
314 let rn_bits = reg_to_bits(rn);
315 let rm_bits = reg_to_bits(rm);
316 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
317 }
318 ArmOp::LsrReg { rd, rn, rm } => {
319 let rd_bits = reg_to_bits(rd);
320 let rn_bits = reg_to_bits(rn);
321 let rm_bits = reg_to_bits(rm);
322 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
323 }
324 ArmOp::AsrReg { rd, rn, rm } => {
325 let rd_bits = reg_to_bits(rd);
326 let rn_bits = reg_to_bits(rn);
327 let rm_bits = reg_to_bits(rm);
328 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
329 }
330 ArmOp::RorReg { rd, rn, rm } => {
331 let rd_bits = reg_to_bits(rd);
332 let rn_bits = reg_to_bits(rn);
333 let rm_bits = reg_to_bits(rm);
334 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
335 }
336
337 ArmOp::Rsb { rd, rn, imm } => {
339 let rd_bits = reg_to_bits(rd);
340 let rn_bits = reg_to_bits(rn);
341 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
344 }
345
346 ArmOp::Clz { rd, rm } => {
348 let rd_bits = reg_to_bits(rd);
349 let rm_bits = reg_to_bits(rm);
350
351 0xE16F0F10 | (rd_bits << 12) | rm_bits
354 }
355
356 ArmOp::Rbit { rd, rm } => {
357 let rd_bits = reg_to_bits(rd);
358 let rm_bits = reg_to_bits(rm);
359
360 0xE6FF0F30 | (rd_bits << 12) | rm_bits
363 }
364
365 ArmOp::Sxtb { rd, rm } => {
366 let rd_bits = reg_to_bits(rd);
367 let rm_bits = reg_to_bits(rm);
368
369 0xE6AF0070 | (rd_bits << 12) | rm_bits
372 }
373
374 ArmOp::Sxth { rd, rm } => {
375 let rd_bits = reg_to_bits(rd);
376 let rm_bits = reg_to_bits(rm);
377
378 0xE6BF0070 | (rd_bits << 12) | rm_bits
381 }
382
383 ArmOp::Mov { rd, op2 } => {
385 let rd_bits = reg_to_bits(rd);
386 let (op2_bits, i_flag) = encode_operand2(op2);
387
388 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
390 }
391
392 ArmOp::Mvn { rd, op2 } => {
393 let rd_bits = reg_to_bits(rd);
394 let (op2_bits, i_flag) = encode_operand2(op2);
395
396 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
398 }
399
400 ArmOp::Movw { rd, imm16 } => {
403 let rd_bits = reg_to_bits(rd);
404 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
405 let imm12 = (*imm16 as u32) & 0xFFF;
406 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
407 }
408
409 ArmOp::Movt { rd, imm16 } => {
412 let rd_bits = reg_to_bits(rd);
413 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
414 let imm12 = (*imm16 as u32) & 0xFFF;
415 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
416 }
417
418 ArmOp::MovwSym { rd, addend, .. } => {
421 let rd_bits = reg_to_bits(rd);
422 let v = (*addend as u32) & 0xffff;
423 0xE3000000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
424 }
425 ArmOp::MovtSym { rd, addend, .. } => {
426 let rd_bits = reg_to_bits(rd);
427 let v = ((*addend as u32) >> 16) & 0xffff;
428 0xE3400000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
429 }
430
431 ArmOp::Cmp { rn, op2 } => {
433 let rn_bits = reg_to_bits(rn);
434 let (op2_bits, i_flag) = encode_operand2(op2);
435
436 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
438 }
439
440 ArmOp::Cmn { rn, op2 } => {
442 let rn_bits = reg_to_bits(rn);
443 let (op2_bits, i_flag) = encode_operand2(op2);
444
445 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
447 }
448
449 ArmOp::Ldr { rd, addr } => {
451 let rd_bits = reg_to_bits(rd);
452 let (base_bits, offset_bits) = encode_mem_addr(addr);
453
454 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
457 }
458
459 ArmOp::Str { rd, addr } => {
460 let rd_bits = reg_to_bits(rd);
461 let (base_bits, offset_bits) = encode_mem_addr(addr);
462
463 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
465 }
466
467 ArmOp::Ldrb { rd, addr } => {
469 let rd_bits = reg_to_bits(rd);
470 let (base_bits, offset_bits) = encode_mem_addr(addr);
471 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
473 }
474
475 ArmOp::Ldrsb { rd, addr } => {
476 let rd_bits = reg_to_bits(rd);
477 let (base_bits, offset_bits) = encode_mem_addr(addr);
478 let offset_val = offset_bits & 0xFF;
481 let imm4h = (offset_val >> 4) & 0xF;
482 let imm4l = offset_val & 0xF;
483 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
484 }
485
486 ArmOp::Ldrh { rd, addr } => {
487 let rd_bits = reg_to_bits(rd);
488 let (base_bits, offset_bits) = encode_mem_addr(addr);
489 let offset_val = offset_bits & 0xFF;
491 let imm4h = (offset_val >> 4) & 0xF;
492 let imm4l = offset_val & 0xF;
493 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
494 }
495
496 ArmOp::Ldrsh { rd, addr } => {
497 let rd_bits = reg_to_bits(rd);
498 let (base_bits, offset_bits) = encode_mem_addr(addr);
499 let offset_val = offset_bits & 0xFF;
501 let imm4h = (offset_val >> 4) & 0xF;
502 let imm4l = offset_val & 0xF;
503 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
504 }
505
506 ArmOp::Strb { rd, addr } => {
508 let rd_bits = reg_to_bits(rd);
509 let (base_bits, offset_bits) = encode_mem_addr(addr);
510 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
512 }
513
514 ArmOp::Strh { rd, addr } => {
515 let rd_bits = reg_to_bits(rd);
516 let (base_bits, offset_bits) = encode_mem_addr(addr);
517 let offset_val = offset_bits & 0xFF;
519 let imm4h = (offset_val >> 4) & 0xF;
520 let imm4l = offset_val & 0xF;
521 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
522 }
523
524 ArmOp::MemorySize { rd } => {
526 let rd_bits = reg_to_bits(rd);
527 0xE1A00820 | (rd_bits << 12) | 0x0A }
532
533 ArmOp::MemoryGrow { rd, .. } => {
534 let rd_bits = reg_to_bits(rd);
535 0xE3E00000 | (rd_bits << 12) }
538
539 ArmOp::Label { .. } => {
541 return Ok(Vec::new());
542 }
543
544 ArmOp::B { label: _ } => {
546 0xEA000000
549 }
550
551 ArmOp::Bcc { cond, label: _ } => {
553 use synth_synthesis::Condition;
554 let cond_bits: u32 = match cond {
555 Condition::EQ => 0x0,
556 Condition::NE => 0x1,
557 Condition::HS => 0x2,
558 Condition::LO => 0x3,
559 Condition::HI => 0x8,
560 Condition::LS => 0x9,
561 Condition::GE => 0xA,
562 Condition::LT => 0xB,
563 Condition::GT => 0xC,
564 Condition::LE => 0xD,
565 };
566 (cond_bits << 28) | 0x0A000000
568 }
569
570 ArmOp::Bhs { label: _ } => {
572 0x2A000000 }
575
576 ArmOp::Blo { label: _ } => {
578 0x3A000000 }
581
582 ArmOp::BOffset { offset } => {
586 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
596 0xEA000000 | offset_bits
597 }
598
599 ArmOp::BCondOffset { cond, offset } => {
601 use synth_synthesis::Condition;
602 let cond_bits: u32 = match cond {
603 Condition::EQ => 0x0,
604 Condition::NE => 0x1,
605 Condition::HS => 0x2,
606 Condition::LO => 0x3,
607 Condition::HI => 0x8,
608 Condition::LS => 0x9,
609 Condition::GE => 0xA,
610 Condition::LT => 0xB,
611 Condition::GT => 0xC,
612 Condition::LE => 0xD,
613 };
614 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
618 (cond_bits << 28) | 0x0A000000 | offset_bits
619 }
620
621 ArmOp::Bl { label: _ } => {
622 0xEB000000
624 }
625
626 ArmOp::Bx { rm } => {
627 let rm_bits = reg_to_bits(rm);
628
629 0xE12FFF10 | rm_bits
631 }
632
633 ArmOp::Blx { rm } => {
634 let rm_bits = reg_to_bits(rm);
635
636 0xE12FFF30 | rm_bits
638 }
639
640 ArmOp::Push { regs } => {
641 let mut reg_list: u32 = 0;
643 for r in regs {
644 reg_list |= 1 << reg_to_bits(r);
645 }
646 0xE92D0000 | reg_list
647 }
648
649 ArmOp::Pop { regs } => {
650 let mut reg_list: u32 = 0;
652 for r in regs {
653 reg_list |= 1 << reg_to_bits(r);
654 }
655 0xE8BD0000 | reg_list
656 }
657
658 ArmOp::Nop => {
659 0xE1A00000
661 }
662
663 ArmOp::Udf { imm } => {
664 let imm8 = *imm as u32;
667 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
668 }
669
670 ArmOp::Popcnt { .. } => {
673 0xE1A00000 }
677
678 ArmOp::SetCond { .. } => {
679 0xE1A00000 }
683
684 ArmOp::SelectMove { .. } => {
685 0xE1A00000 }
689
690 ArmOp::Select { .. } => {
691 0xE1A00000 }
695
696 ArmOp::LocalGet { .. } => {
697 0xE1A00000 }
701
702 ArmOp::LocalSet { .. } => {
703 0xE1A00000 }
707
708 ArmOp::LocalTee { .. } => {
709 0xE1A00000 }
713
714 ArmOp::GlobalGet { .. } => {
715 0xE1A00000 }
719
720 ArmOp::GlobalSet { .. } => {
721 0xE1A00000 }
725
726 ArmOp::BrTable { .. } => {
727 0xE1A00000 }
731
732 ArmOp::Call { .. } => {
733 0xE1A00000 }
737
738 ArmOp::CallIndirect { .. } => {
739 0xE1A00000 }
743
744 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)?,
781 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
782 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
783 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
784 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
785 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
786 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
787
788 ArmOp::F32Ceil { sd, sm } => {
791 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
793 ArmOp::F32Floor { sd, sm } => {
794 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
796 ArmOp::F32Trunc { sd, sm } => {
797 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
799 ArmOp::F32Nearest { sd, sm } => {
800 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
802 ArmOp::F32Min { sd, sn, sm } => {
803 return self.encode_arm_f32_minmax(sd, sn, sm, true);
804 }
805 ArmOp::F32Max { sd, sn, sm } => {
806 return self.encode_arm_f32_minmax(sd, sn, sm, false);
807 }
808 ArmOp::F32Copysign { sd, sn, sm } => {
809 return self.encode_arm_f32_copysign(sd, sn, sm);
810 }
811
812 ArmOp::F32Eq { rd, sn, sm } => {
814 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
816 ArmOp::F32Ne { rd, sn, sm } => {
817 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
819 ArmOp::F32Lt { rd, sn, sm } => {
820 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
822 ArmOp::F32Le { rd, sn, sm } => {
823 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
825 ArmOp::F32Gt { rd, sn, sm } => {
826 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
828 ArmOp::F32Ge { rd, sn, sm } => {
829 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
831
832 ArmOp::F32Const { sd, value } => {
834 return self.encode_arm_f32_const(sd, *value);
835 }
836
837 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
838 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
839
840 ArmOp::F32ConvertI32S { sd, rm } => {
842 return self.encode_arm_f32_convert_i32(sd, rm, true);
843 }
844 ArmOp::F32ConvertI32U { sd, rm } => {
845 return self.encode_arm_f32_convert_i32(sd, rm, false);
846 }
847 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
848 return Err(synth_core::Error::synthesis(
849 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
850 ));
851 }
852 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
853 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
854 ArmOp::I32TruncF32S { rd, sm } => {
855 return self.encode_arm_i32_trunc_f32(rd, sm, true);
856 }
857 ArmOp::I32TruncF32U { rd, sm } => {
858 return self.encode_arm_i32_trunc_f32(rd, sm, false);
859 }
860
861 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
864 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
865 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
866 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
867 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
868 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
869 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
870
871 ArmOp::F64Ceil { dd, dm } => {
874 return self.encode_arm_f64_rounding(dd, dm, 0b01);
875 }
876 ArmOp::F64Floor { dd, dm } => {
877 return self.encode_arm_f64_rounding(dd, dm, 0b10);
878 }
879 ArmOp::F64Trunc { dd, dm } => {
880 return self.encode_arm_f64_rounding(dd, dm, 0b11);
881 }
882 ArmOp::F64Nearest { dd, dm } => {
883 return self.encode_arm_f64_rounding(dd, dm, 0b00);
884 }
885 ArmOp::F64Min { dd, dn, dm } => {
886 return self.encode_arm_f64_minmax(dd, dn, dm, true);
887 }
888 ArmOp::F64Max { dd, dn, dm } => {
889 return self.encode_arm_f64_minmax(dd, dn, dm, false);
890 }
891 ArmOp::F64Copysign { dd, dn, dm } => {
892 return self.encode_arm_f64_copysign(dd, dn, dm);
893 }
894
895 ArmOp::F64Eq { rd, dn, dm } => {
897 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
898 }
899 ArmOp::F64Ne { rd, dn, dm } => {
900 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
901 }
902 ArmOp::F64Lt { rd, dn, dm } => {
903 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
904 }
905 ArmOp::F64Le { rd, dn, dm } => {
906 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
907 }
908 ArmOp::F64Gt { rd, dn, dm } => {
909 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
910 }
911 ArmOp::F64Ge { rd, dn, dm } => {
912 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
913 }
914
915 ArmOp::F64Const { dd, value } => {
916 return self.encode_arm_f64_const(dd, *value);
917 }
918
919 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
920 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
921
922 ArmOp::F64ConvertI32S { dd, rm } => {
923 return self.encode_arm_f64_convert_i32(dd, rm, true);
924 }
925 ArmOp::F64ConvertI32U { dd, rm } => {
926 return self.encode_arm_f64_convert_i32(dd, rm, false);
927 }
928 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
929 return Err(synth_core::Error::synthesis(
930 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
931 ));
932 }
933 ArmOp::F64PromoteF32 { dd, sm } => {
934 return self.encode_arm_f64_promote_f32(dd, sm);
935 }
936 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
937 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
938 }
939 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
940 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
941 }
942 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
943 return Err(synth_core::Error::synthesis(
944 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
945 ));
946 }
947 ArmOp::I32TruncF64S { rd, dm } => {
948 return self.encode_arm_i32_trunc_f64(rd, dm, true);
949 }
950 ArmOp::I32TruncF64U { rd, dm } => {
951 return self.encode_arm_i32_trunc_f64(rd, dm, false);
952 }
953 ArmOp::I64SetCond { .. }
955 | ArmOp::I64SetCondZ { .. }
956 | ArmOp::I64Mul { .. }
957 | ArmOp::I64Shl { .. }
958 | ArmOp::I64ShrS { .. }
959 | ArmOp::I64ShrU { .. }
960 | ArmOp::I64Rotl { .. }
961 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
965 | ArmOp::MveStore { .. }
966 | ArmOp::MveConst { .. }
967 | ArmOp::MveAnd { .. }
968 | ArmOp::MveOrr { .. }
969 | ArmOp::MveEor { .. }
970 | ArmOp::MveMvn { .. }
971 | ArmOp::MveBic { .. }
972 | ArmOp::MveAddI { .. }
973 | ArmOp::MveSubI { .. }
974 | ArmOp::MveMulI { .. }
975 | ArmOp::MveNegI { .. }
976 | ArmOp::MveCmpEqI { .. }
977 | ArmOp::MveCmpNeI { .. }
978 | ArmOp::MveCmpLtS { .. }
979 | ArmOp::MveCmpLtU { .. }
980 | ArmOp::MveCmpGtS { .. }
981 | ArmOp::MveCmpGtU { .. }
982 | ArmOp::MveCmpLeS { .. }
983 | ArmOp::MveCmpLeU { .. }
984 | ArmOp::MveCmpGeS { .. }
985 | ArmOp::MveCmpGeU { .. }
986 | ArmOp::MveDup { .. }
987 | ArmOp::MveExtractLane { .. }
988 | ArmOp::MveInsertLane { .. }
989 | ArmOp::MveAddF32 { .. }
990 | ArmOp::MveSubF32 { .. }
991 | ArmOp::MveMulF32 { .. }
992 | ArmOp::MveNegF32 { .. }
993 | ArmOp::MveAbsF32 { .. }
994 | ArmOp::MveCmpEqF32 { .. }
995 | ArmOp::MveCmpNeF32 { .. }
996 | ArmOp::MveCmpLtF32 { .. }
997 | ArmOp::MveCmpLeF32 { .. }
998 | ArmOp::MveCmpGtF32 { .. }
999 | ArmOp::MveCmpGeF32 { .. }
1000 | ArmOp::MveDupF32 { .. }
1001 | ArmOp::MveExtractLaneF32 { .. }
1002 | ArmOp::MveReplaceLaneF32 { .. }
1003 | ArmOp::MveDivF32 { .. }
1004 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
1006
1007 Ok(instr.to_le_bytes().to_vec())
1009 }
1010
1011 fn encode_arm_f32_compare(
1015 &self,
1016 rd: &Reg,
1017 sn: &VfpReg,
1018 sm: &VfpReg,
1019 cond_code: u32,
1020 ) -> Result<Vec<u8>> {
1021 let mut bytes = Vec::new();
1022
1023 let sn_num = vfp_sreg_to_num(sn)?;
1025 let sm_num = vfp_sreg_to_num(sm)?;
1026 let (vd, d) = encode_sreg(sn_num);
1027 let (vm, m) = encode_sreg(sm_num);
1028 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1029 bytes.extend_from_slice(&vcmp.to_le_bytes());
1030
1031 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1033
1034 let rd_bits = reg_to_bits(rd);
1036 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1037 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1038
1039 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1041 bytes.extend_from_slice(&mov_one.to_le_bytes());
1042
1043 Ok(bytes)
1044 }
1045
1046 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1048 let mut bytes = Vec::new();
1049 let bits = value.to_bits();
1050
1051 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1056 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1057 bytes.extend_from_slice(&movw.to_le_bytes());
1058
1059 let hi16 = (bits >> 16) & 0xFFFF;
1061 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1062 bytes.extend_from_slice(&movt.to_le_bytes());
1063
1064 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1066 bytes.extend_from_slice(&vmov.to_le_bytes());
1067
1068 Ok(bytes)
1069 }
1070
1071 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1073 let mut bytes = Vec::new();
1074
1075 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1077 bytes.extend_from_slice(&vmov.to_le_bytes());
1078
1079 let sd_num = vfp_sreg_to_num(sd)?;
1082 let (vd, d) = encode_sreg(sd_num);
1083 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1085 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1086 bytes.extend_from_slice(&vcvt.to_le_bytes());
1087
1088 Ok(bytes)
1089 }
1090
1091 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1103 let mut bytes = Vec::new();
1104 let sm_num = vfp_sreg_to_num(sm)?;
1105 let sd_num = vfp_sreg_to_num(sd)?;
1106 let (vd_s, d_s) = encode_sreg(sd_num);
1107 let (vm_s, m_s) = encode_sreg(sm_num);
1108
1109 if mode == 0b11 {
1110 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1113 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1114 } else {
1115 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1120 bytes.extend_from_slice(&vmrs.to_le_bytes());
1121
1122 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1125 bytes.extend_from_slice(&bic.to_le_bytes());
1126
1127 if mode != 0 {
1129 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1131 bytes.extend_from_slice(&orr.to_le_bytes());
1132 }
1133
1134 let vmsr = 0xEEE10A10 | (rt << 12);
1136 bytes.extend_from_slice(&vmsr.to_le_bytes());
1137
1138 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1140 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1141
1142 bytes.extend_from_slice(&vmrs.to_le_bytes());
1144 bytes.extend_from_slice(&bic.to_le_bytes());
1145 bytes.extend_from_slice(&vmsr.to_le_bytes());
1146 }
1147
1148 let (vd2, d2) = encode_sreg(sd_num);
1150 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1151 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1152
1153 Ok(bytes)
1154 }
1155
1156 fn encode_arm_f32_minmax(
1158 &self,
1159 sd: &VfpReg,
1160 sn: &VfpReg,
1161 sm: &VfpReg,
1162 is_min: bool,
1163 ) -> Result<Vec<u8>> {
1164 let mut bytes = Vec::new();
1165 let sn_num = vfp_sreg_to_num(sn)?;
1166 let sm_num = vfp_sreg_to_num(sm)?;
1167 let sd_num = vfp_sreg_to_num(sd)?;
1168
1169 let (vd, d) = encode_sreg(sd_num);
1171 let (vn, n) = encode_sreg(sn_num);
1172 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1173 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1174
1175 let (vm, m) = encode_sreg(sm_num);
1177 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1178 bytes.extend_from_slice(&vcmp.to_le_bytes());
1179
1180 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1182
1183 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1186
1187 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1189 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1190
1191 Ok(bytes)
1192 }
1193
1194 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1196 let mut bytes = Vec::new();
1197
1198 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1200 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1201
1202 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1204 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1205
1206 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1210 bytes.extend_from_slice(&and_sign.to_le_bytes());
1211
1212 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1215 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1216
1217 let orr = 0xE1800000u32 | 12;
1220 bytes.extend_from_slice(&orr.to_le_bytes());
1221
1222 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1224 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1225
1226 Ok(bytes)
1227 }
1228
1229 fn encode_arm_f64_compare(
1231 &self,
1232 rd: &Reg,
1233 dn: &VfpReg,
1234 dm: &VfpReg,
1235 cond_code: u32,
1236 ) -> Result<Vec<u8>> {
1237 let mut bytes = Vec::new();
1238
1239 let dn_num = vfp_dreg_to_num(dn)?;
1241 let dm_num = vfp_dreg_to_num(dm)?;
1242 let (vd, d) = encode_dreg(dn_num);
1243 let (vm, m) = encode_dreg(dm_num);
1244 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1245 bytes.extend_from_slice(&vcmp.to_le_bytes());
1246
1247 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1249
1250 let rd_bits = reg_to_bits(rd);
1252 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1253 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1254
1255 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1257 bytes.extend_from_slice(&mov_one.to_le_bytes());
1258
1259 Ok(bytes)
1260 }
1261
1262 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1264 let mut bytes = Vec::new();
1265 let bits = value.to_bits();
1266 let lo32 = bits as u32;
1267 let hi32 = (bits >> 32) as u32;
1268
1269 let lo16 = lo32 & 0xFFFF;
1271 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1272 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1273 let hi16 = (lo32 >> 16) & 0xFFFF;
1274 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1275 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1276
1277 let lo16 = hi32 & 0xFFFF;
1279 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1280 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1281 let hi16 = (hi32 >> 16) & 0xFFFF;
1282 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1283 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1284
1285 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1287 bytes.extend_from_slice(&vmov.to_le_bytes());
1288
1289 Ok(bytes)
1290 }
1291
1292 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1294 let mut bytes = Vec::new();
1295
1296 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1298 bytes.extend_from_slice(&vmov.to_le_bytes());
1299
1300 let dd_num = vfp_dreg_to_num(dd)?;
1303 let (vd, d) = encode_dreg(dd_num);
1304 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1305 let vcvt = base | (d << 22) | (vd << 12);
1307 bytes.extend_from_slice(&vcvt.to_le_bytes());
1308
1309 Ok(bytes)
1310 }
1311
1312 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1314 let dd_num = vfp_dreg_to_num(dd)?;
1315 let sm_num = vfp_sreg_to_num(sm)?;
1316 let (vd, d) = encode_dreg(dd_num);
1317 let (vm, m) = encode_sreg(sm_num);
1318
1319 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1321 Ok(vcvt.to_le_bytes().to_vec())
1322 }
1323
1324 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1326 let mut bytes = Vec::new();
1327 let dm_num = vfp_dreg_to_num(dm)?;
1328 let (vm, m) = encode_dreg(dm_num);
1329
1330 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1333 let vcvt = base | (m << 5) | vm;
1334 bytes.extend_from_slice(&vcvt.to_le_bytes());
1335
1336 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1338 bytes.extend_from_slice(&vmov.to_le_bytes());
1339
1340 Ok(bytes)
1341 }
1342
1343 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1351 let mut bytes = Vec::new();
1352 let dm_num = vfp_dreg_to_num(dm)?;
1353 let dd_num = vfp_dreg_to_num(dd)?;
1354 let (vm, m) = encode_dreg(dm_num);
1355 let (vd, d) = encode_dreg(dd_num);
1356
1357 if mode == 0b11 {
1358 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1360 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1361 } else {
1362 let rt: u32 = 12;
1364
1365 let vmrs = 0xEEF10A10 | (rt << 12);
1367 bytes.extend_from_slice(&vmrs.to_le_bytes());
1368
1369 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1371 bytes.extend_from_slice(&bic.to_le_bytes());
1372
1373 if mode != 0 {
1375 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1376 bytes.extend_from_slice(&orr.to_le_bytes());
1377 }
1378
1379 let vmsr = 0xEEE10A10 | (rt << 12);
1381 bytes.extend_from_slice(&vmsr.to_le_bytes());
1382
1383 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1385 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1386
1387 bytes.extend_from_slice(&vmrs.to_le_bytes());
1389 bytes.extend_from_slice(&bic.to_le_bytes());
1390 bytes.extend_from_slice(&vmsr.to_le_bytes());
1391 }
1392
1393 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1395 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1396
1397 Ok(bytes)
1398 }
1399
1400 fn encode_arm_f64_minmax(
1402 &self,
1403 dd: &VfpReg,
1404 dn: &VfpReg,
1405 dm: &VfpReg,
1406 is_min: bool,
1407 ) -> Result<Vec<u8>> {
1408 let mut bytes = Vec::new();
1409 let dn_num = vfp_dreg_to_num(dn)?;
1410 let dm_num = vfp_dreg_to_num(dm)?;
1411 let dd_num = vfp_dreg_to_num(dd)?;
1412
1413 let (vd, d) = encode_dreg(dd_num);
1415 let (vn, n) = encode_dreg(dn_num);
1416 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1417 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1418
1419 let (vm, m) = encode_dreg(dm_num);
1421 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1422 bytes.extend_from_slice(&vcmp.to_le_bytes());
1423
1424 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1426
1427 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1428 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1429 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1430
1431 Ok(bytes)
1432 }
1433
1434 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1436 let mut bytes = Vec::new();
1437
1438 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1440 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1441
1442 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1445 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1446
1447 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1449 bytes.extend_from_slice(&and_sign.to_le_bytes());
1450
1451 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1453 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1454
1455 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1457 bytes.extend_from_slice(&orr.to_le_bytes());
1458
1459 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1461 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1462
1463 Ok(bytes)
1464 }
1465
1466 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1468 let mut bytes = Vec::new();
1469
1470 let sm_num = vfp_sreg_to_num(sm)?;
1473 let (vd, d) = encode_sreg(sm_num);
1474 let (vm, m) = encode_sreg(sm_num);
1475 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1476 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1477 bytes.extend_from_slice(&vcvt.to_le_bytes());
1478
1479 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1481 bytes.extend_from_slice(&vmov.to_le_bytes());
1482
1483 Ok(bytes)
1484 }
1485
1486 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1488 match op {
1491 ArmOp::Add { rd, rn, op2 } => {
1493 let rd_bits = reg_to_bits(rd) as u16;
1494 let rn_bits = reg_to_bits(rn) as u16;
1495
1496 if let Operand2::Reg(rm) = op2 {
1497 let rm_bits = reg_to_bits(rm) as u16;
1498 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1506 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1508 Ok(instr.to_le_bytes().to_vec())
1509 } else {
1510 self.encode_thumb32_add_reg_raw(
1512 rd_bits as u32,
1513 rn_bits as u32,
1514 rm_bits as u32,
1515 )
1516 }
1517 } else if let Operand2::Imm(imm) = op2 {
1518 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1519 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1521 Ok(instr.to_le_bytes().to_vec())
1522 } else {
1523 self.encode_thumb32_add(rd, rn, *imm as u32)
1525 }
1526 } else {
1527 self.encode_thumb32_add(rd, rn, 0)
1529 }
1530 }
1531
1532 ArmOp::Sub { rd, rn, op2 } => {
1533 let rd_bits = reg_to_bits(rd) as u16;
1534 let rn_bits = reg_to_bits(rn) as u16;
1535
1536 if let Operand2::Reg(rm) = op2 {
1537 let rm_bits = reg_to_bits(rm) as u16;
1538 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1540 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1542 Ok(instr.to_le_bytes().to_vec())
1543 } else {
1544 self.encode_thumb32_sub_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 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1555 Ok(instr.to_le_bytes().to_vec())
1556 } else {
1557 self.encode_thumb32_sub(rd, rn, *imm as u32)
1558 }
1559 } else {
1560 self.encode_thumb32_sub(rd, rn, 0)
1561 }
1562 }
1563
1564 ArmOp::Mov { rd, op2 } => {
1565 let rd_bits = reg_to_bits(rd) as u16;
1566
1567 if let Operand2::Imm(imm) = op2 {
1568 if *imm <= 255 && rd_bits < 8 {
1569 let imm_bits = (*imm as u16) & 0xFF;
1571 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1572 Ok(instr.to_le_bytes().to_vec())
1573 } else {
1574 self.encode_thumb32_movw(rd, *imm as u32)
1576 }
1577 } else if let Operand2::Reg(rm) = op2 {
1578 let rm_bits = reg_to_bits(rm) as u16;
1579 let d_bit = (rd_bits >> 3) & 1;
1582 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1583 Ok(instr.to_le_bytes().to_vec())
1584 } else {
1585 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1587 }
1588 }
1589
1590 ArmOp::Push { regs } => {
1591 let mut reg_list: u16 = 0;
1595 let mut need_32bit = false;
1596 for r in regs {
1597 let bit = reg_to_bits(r);
1598 if bit >= 8 && *r != Reg::LR {
1599 need_32bit = true;
1600 }
1601 reg_list |= 1 << bit;
1602 }
1603 if !need_32bit {
1604 let m_bit = if reg_list & (1 << 14) != 0 {
1606 1u16
1607 } else {
1608 0u16
1609 };
1610 let low_regs = reg_list & 0xFF;
1611 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1612 Ok(instr.to_le_bytes().to_vec())
1613 } else {
1614 let hw1: u16 = 0xE92D;
1616 let hw2: u16 = reg_list;
1617 let mut bytes = hw1.to_le_bytes().to_vec();
1618 bytes.extend_from_slice(&hw2.to_le_bytes());
1619 Ok(bytes)
1620 }
1621 }
1622
1623 ArmOp::Pop { regs } => {
1624 let mut reg_list: u16 = 0;
1628 let mut need_32bit = false;
1629 for r in regs {
1630 let bit = reg_to_bits(r);
1631 if bit >= 8 && *r != Reg::PC {
1632 need_32bit = true;
1633 }
1634 reg_list |= 1 << bit;
1635 }
1636 if !need_32bit {
1637 let p_bit = if reg_list & (1 << 15) != 0 {
1639 1u16
1640 } else {
1641 0u16
1642 };
1643 let low_regs = reg_list & 0xFF;
1644 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1645 Ok(instr.to_le_bytes().to_vec())
1646 } else {
1647 let hw1: u16 = 0xE8BD;
1649 let hw2: u16 = reg_list;
1650 let mut bytes = hw1.to_le_bytes().to_vec();
1651 bytes.extend_from_slice(&hw2.to_le_bytes());
1652 Ok(bytes)
1653 }
1654 }
1655
1656 ArmOp::Nop => {
1657 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1659 }
1660
1661 ArmOp::Udf { imm } => {
1662 let instr: u16 = 0xDE00 | (*imm as u16);
1665 let bytes = instr.to_le_bytes().to_vec();
1666 encoding_contracts::verify_thumb16(&bytes);
1667 Ok(bytes)
1668 }
1669
1670 ArmOp::Adds { rd, rn, op2 } => {
1673 let rd_bits = reg_to_bits(rd) as u16;
1674 let rn_bits = reg_to_bits(rn) as u16;
1675
1676 if let Operand2::Reg(rm) = op2 {
1677 let rm_bits = reg_to_bits(rm) as u16;
1678 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1683 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1685 Ok(instr.to_le_bytes().to_vec())
1686 } else {
1687 self.encode_thumb32_adds_reg_raw(
1688 rd_bits as u32,
1689 rn_bits as u32,
1690 rm_bits as u32,
1691 )
1692 }
1693 } else {
1694 self.encode_thumb32_adds(rd, rn, 0)
1696 }
1697 }
1698
1699 ArmOp::Adc { rd, rn, op2 } => {
1702 let rd_bits = reg_to_bits(rd);
1703 let rn_bits = reg_to_bits(rn);
1704
1705 if let Operand2::Reg(rm) = op2 {
1706 let rm_bits = reg_to_bits(rm);
1707 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1709 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1710
1711 let mut bytes = hw1.to_le_bytes().to_vec();
1712 bytes.extend_from_slice(&hw2.to_le_bytes());
1713 Ok(bytes)
1714 } else {
1715 let hw1: u16 = (0xF140 | rn_bits) as u16;
1717 let hw2: u16 = (rd_bits << 8) as u16;
1718 let mut bytes = hw1.to_le_bytes().to_vec();
1719 bytes.extend_from_slice(&hw2.to_le_bytes());
1720 Ok(bytes)
1721 }
1722 }
1723
1724 ArmOp::Subs { rd, rn, op2 } => {
1726 let rd_bits = reg_to_bits(rd) as u16;
1727 let rn_bits = reg_to_bits(rn) as u16;
1728
1729 if let Operand2::Reg(rm) = op2 {
1730 let rm_bits = reg_to_bits(rm) as u16;
1731 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1735 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1737 Ok(instr.to_le_bytes().to_vec())
1738 } else {
1739 self.encode_thumb32_subs_reg_raw(
1740 rd_bits as u32,
1741 rn_bits as u32,
1742 rm_bits as u32,
1743 )
1744 }
1745 } else {
1746 self.encode_thumb32_subs(rd, rn, 0)
1748 }
1749 }
1750
1751 ArmOp::Sbc { rd, rn, op2 } => {
1754 let rd_bits = reg_to_bits(rd);
1755 let rn_bits = reg_to_bits(rn);
1756
1757 if let Operand2::Reg(rm) = op2 {
1758 let rm_bits = reg_to_bits(rm);
1759 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1761 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1762
1763 let mut bytes = hw1.to_le_bytes().to_vec();
1764 bytes.extend_from_slice(&hw2.to_le_bytes());
1765 Ok(bytes)
1766 } else {
1767 let hw1: u16 = (0xF160 | rn_bits) as u16;
1769 let hw2: u16 = (rd_bits << 8) as u16;
1770 let mut bytes = hw1.to_le_bytes().to_vec();
1771 bytes.extend_from_slice(&hw2.to_le_bytes());
1772 Ok(bytes)
1773 }
1774 }
1775
1776 ArmOp::Sdiv { rd, rn, rm } => {
1780 let rd_bits = reg_to_bits(rd);
1781 let rn_bits = reg_to_bits(rn);
1782 let rm_bits = reg_to_bits(rm);
1783 reg_bits_checked(rd_bits)?;
1784 reg_bits_checked(rn_bits)?;
1785 reg_bits_checked(rm_bits)?;
1786
1787 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1791 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1792
1793 let mut bytes = hw1.to_le_bytes().to_vec();
1795 bytes.extend_from_slice(&hw2.to_le_bytes());
1796 encoding_contracts::verify_thumb32(&bytes);
1797 Ok(bytes)
1798 }
1799
1800 ArmOp::Udiv { rd, rn, rm } => {
1802 let rd_bits = reg_to_bits(rd);
1803 let rn_bits = reg_to_bits(rn);
1804 let rm_bits = reg_to_bits(rm);
1805 reg_bits_checked(rd_bits)?;
1806 reg_bits_checked(rn_bits)?;
1807 reg_bits_checked(rm_bits)?;
1808
1809 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1811 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1812
1813 let mut bytes = hw1.to_le_bytes().to_vec();
1814 bytes.extend_from_slice(&hw2.to_le_bytes());
1815 encoding_contracts::verify_thumb32(&bytes);
1816 Ok(bytes)
1817 }
1818
1819 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
1820 let rdlo_bits = reg_to_bits(rdlo);
1821 let rdhi_bits = reg_to_bits(rdhi);
1822 let rn_bits = reg_to_bits(rn);
1823 let rm_bits = reg_to_bits(rm);
1824 reg_bits_checked(rdlo_bits)?;
1825 reg_bits_checked(rdhi_bits)?;
1826 reg_bits_checked(rn_bits)?;
1827 reg_bits_checked(rm_bits)?;
1828
1829 let hw1: u16 = (0xFBA0 | rn_bits) as u16;
1831 let hw2: u16 = ((rdlo_bits << 12) | (rdhi_bits << 8) | rm_bits) as u16;
1832
1833 let mut bytes = hw1.to_le_bytes().to_vec();
1834 bytes.extend_from_slice(&hw2.to_le_bytes());
1835 encoding_contracts::verify_thumb32(&bytes);
1836 Ok(bytes)
1837 }
1838
1839 ArmOp::Mul { rd, rn, rm } => {
1841 let rd_bits = reg_to_bits(rd);
1842 let rn_bits = reg_to_bits(rn);
1843 let rm_bits = reg_to_bits(rm);
1844
1845 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1848 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1849
1850 let mut bytes = hw1.to_le_bytes().to_vec();
1851 bytes.extend_from_slice(&hw2.to_le_bytes());
1852 Ok(bytes)
1853 }
1854
1855 ArmOp::Mls { rd, rn, rm, ra } => {
1857 let rd_bits = reg_to_bits(rd);
1858 let rn_bits = reg_to_bits(rn);
1859 let rm_bits = reg_to_bits(rm);
1860 let ra_bits = reg_to_bits(ra);
1861
1862 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1865 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | 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 Ok(bytes)
1870 }
1871
1872 ArmOp::And { rd, rn, op2 } => {
1874 if let Operand2::Reg(rm) = op2 {
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 = (0xEA00 | rn_bits) as u16;
1881 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1882
1883 let mut bytes = hw1.to_le_bytes().to_vec();
1884 bytes.extend_from_slice(&hw2.to_le_bytes());
1885 Ok(bytes)
1886 } else if let Operand2::Imm(imm) = op2 {
1887 let rd_bits = reg_to_bits(rd);
1888 let rn_bits = reg_to_bits(rn);
1889 let imm_val = *imm as u32;
1890
1891 let i_bit = (imm_val >> 11) & 1;
1893 let imm3 = (imm_val >> 8) & 0x7;
1894 let imm8 = imm_val & 0xFF;
1895
1896 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1897 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1898
1899 let mut bytes = hw1.to_le_bytes().to_vec();
1900 bytes.extend_from_slice(&hw2.to_le_bytes());
1901 Ok(bytes)
1902 } else {
1903 let instr: u16 = 0xBF00;
1905 Ok(instr.to_le_bytes().to_vec())
1906 }
1907 }
1908
1909 ArmOp::Orr { rd, rn, op2 } => {
1911 if let Operand2::Reg(rm) = op2 {
1912 let rd_bits = reg_to_bits(rd);
1913 let rn_bits = reg_to_bits(rn);
1914 let rm_bits = reg_to_bits(rm);
1915
1916 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1918 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1919
1920 let mut bytes = hw1.to_le_bytes().to_vec();
1921 bytes.extend_from_slice(&hw2.to_le_bytes());
1922 Ok(bytes)
1923 } else if let Operand2::Imm(imm) = op2 {
1924 let imm_val = *imm as u32;
1929 if imm_val > 0xFF {
1930 return Err(synth_core::Error::synthesis(
1931 "ORR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1932 ));
1933 }
1934 let rd_bits = reg_to_bits(rd);
1935 let rn_bits = reg_to_bits(rn);
1936 let hw1: u16 = (0xF040 | rn_bits) as u16;
1937 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
1938 let mut bytes = hw1.to_le_bytes().to_vec();
1939 bytes.extend_from_slice(&hw2.to_le_bytes());
1940 Ok(bytes)
1941 } else {
1942 let instr: u16 = 0xBF00;
1943 Ok(instr.to_le_bytes().to_vec())
1944 }
1945 }
1946
1947 ArmOp::Eor { rd, rn, op2 } => {
1949 if let Operand2::Reg(rm) = op2 {
1950 let rd_bits = reg_to_bits(rd);
1951 let rn_bits = reg_to_bits(rn);
1952 let rm_bits = reg_to_bits(rm);
1953
1954 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1956 let hw2: u16 = ((rd_bits << 8) | rm_bits) 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 if let Operand2::Imm(imm) = op2 {
1962 let imm_val = *imm as u32;
1966 if imm_val > 0xFF {
1967 return Err(synth_core::Error::synthesis(
1968 "EOR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1969 ));
1970 }
1971 let rd_bits = reg_to_bits(rd);
1972 let rn_bits = reg_to_bits(rn);
1973 let hw1: u16 = (0xF080 | rn_bits) as u16;
1974 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
1975 let mut bytes = hw1.to_le_bytes().to_vec();
1976 bytes.extend_from_slice(&hw2.to_le_bytes());
1977 Ok(bytes)
1978 } else {
1979 let instr: u16 = 0xBF00;
1980 Ok(instr.to_le_bytes().to_vec())
1981 }
1982 }
1983
1984 ArmOp::Lsl { rd, rn, shift } => {
1986 let rd_bits = reg_to_bits(rd) as u16;
1987 let rn_bits = reg_to_bits(rn) as u16;
1988 let shift_bits = (*shift as u16) & 0x1F;
1989
1990 if rd_bits < 8 && rn_bits < 8 {
1991 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1993 Ok(instr.to_le_bytes().to_vec())
1994 } else {
1995 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1998 }
1999
2000 ArmOp::Lsr { rd, rn, shift } => {
2001 let rd_bits = reg_to_bits(rd) as u16;
2002 let rn_bits = reg_to_bits(rn) as u16;
2003 let shift_bits = (*shift as u16) & 0x1F;
2004
2005 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2006 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2008 Ok(instr.to_le_bytes().to_vec())
2009 } else {
2010 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
2012 }
2013
2014 ArmOp::Asr { rd, rn, shift } => {
2015 let rd_bits = reg_to_bits(rd) as u16;
2016 let rn_bits = reg_to_bits(rn) as u16;
2017 let shift_bits = (*shift as u16) & 0x1F;
2018
2019 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2020 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2022 Ok(instr.to_le_bytes().to_vec())
2023 } else {
2024 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
2026 }
2027
2028 ArmOp::Ror { rd, rn, shift } => {
2029 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
2032
2033 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
2037 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
2038 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
2039 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
2040
2041 ArmOp::Rsb { rd, rn, imm } => {
2044 let rd_bits = reg_to_bits(rd);
2045 let rn_bits = reg_to_bits(rn);
2046 let imm_val = *imm;
2047
2048 let i_bit = (imm_val >> 11) & 1;
2049 let imm3 = (imm_val >> 8) & 0x7;
2050 let imm8 = imm_val & 0xFF;
2051
2052 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2054 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2056
2057 let mut bytes = hw1.to_le_bytes().to_vec();
2058 bytes.extend_from_slice(&hw2.to_le_bytes());
2059 Ok(bytes)
2060 }
2061
2062 ArmOp::Clz { rd, rm } => {
2064 let rd_bits = reg_to_bits(rd);
2065 let rm_bits = reg_to_bits(rm);
2066
2067 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2070 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2071
2072 let mut bytes = hw1.to_le_bytes().to_vec();
2073 bytes.extend_from_slice(&hw2.to_le_bytes());
2074 Ok(bytes)
2075 }
2076
2077 ArmOp::Rbit { rd, rm } => {
2079 let rd_bits = reg_to_bits(rd);
2080 let rm_bits = reg_to_bits(rm);
2081
2082 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2085 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2086
2087 let mut bytes = hw1.to_le_bytes().to_vec();
2088 bytes.extend_from_slice(&hw2.to_le_bytes());
2089 Ok(bytes)
2090 }
2091
2092 ArmOp::Sxtb { rd, rm } => {
2094 let rd_bits = reg_to_bits(rd) as u16;
2095 let rm_bits = reg_to_bits(rm) as u16;
2096
2097 if rd_bits < 8 && rm_bits < 8 {
2098 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2100 Ok(instr.to_le_bytes().to_vec())
2101 } else {
2102 let rd_bits32 = rd_bits as u32;
2105 let rm_bits32 = rm_bits as u32;
2106 let hw1: u16 = 0xFA4F;
2107 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2108 let mut bytes = hw1.to_le_bytes().to_vec();
2109 bytes.extend_from_slice(&hw2.to_le_bytes());
2110 Ok(bytes)
2111 }
2112 }
2113
2114 ArmOp::Sxth { rd, rm } => {
2116 let rd_bits = reg_to_bits(rd) as u16;
2117 let rm_bits = reg_to_bits(rm) as u16;
2118
2119 if rd_bits < 8 && rm_bits < 8 {
2120 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2122 Ok(instr.to_le_bytes().to_vec())
2123 } else {
2124 let rd_bits32 = rd_bits as u32;
2127 let rm_bits32 = rm_bits as u32;
2128 let hw1: u16 = 0xFA0F;
2129 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2130 let mut bytes = hw1.to_le_bytes().to_vec();
2131 bytes.extend_from_slice(&hw2.to_le_bytes());
2132 Ok(bytes)
2133 }
2134 }
2135
2136 ArmOp::Cmp { rn, op2 } => {
2138 let rn_bits = reg_to_bits(rn) as u16;
2139
2140 if let Operand2::Imm(imm) = op2 {
2141 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2144 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2146 Ok(instr.to_le_bytes().to_vec())
2147 } else {
2148 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2149 }
2150 } else if let Operand2::Reg(rm) = op2 {
2151 let rm_bits = reg_to_bits(rm) as u16;
2152 if rn_bits < 8 && rm_bits < 8 {
2153 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2155 Ok(instr.to_le_bytes().to_vec())
2156 } else {
2157 let n_bit = (rn_bits >> 3) & 1;
2159 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2160 Ok(instr.to_le_bytes().to_vec())
2161 }
2162 } else {
2163 let instr: u16 = 0xBF00;
2164 Ok(instr.to_le_bytes().to_vec())
2165 }
2166 }
2167
2168 ArmOp::Cmn { rn, op2 } => {
2171 let rn_bits = reg_to_bits(rn) as u16;
2172
2173 if let Operand2::Imm(imm) = op2 {
2174 if *imm >= 0 && *imm <= 255 {
2177 let imm8 = *imm as u16 & 0xFF;
2178 let hw1: u16 = 0xF110 | rn_bits;
2179 let hw2: u16 = 0x0F00 | imm8;
2180 let mut bytes = hw1.to_le_bytes().to_vec();
2181 bytes.extend_from_slice(&hw2.to_le_bytes());
2182 Ok(bytes)
2183 } else {
2184 Ok(vec![0xBF, 0x00])
2186 }
2187 } else if let Operand2::Reg(rm) = op2 {
2188 let rm_bits = reg_to_bits(rm) as u16;
2189 if rn_bits < 8 && rm_bits < 8 {
2195 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2197 Ok(instr.to_le_bytes().to_vec())
2198 } else {
2199 let hw1: u16 = 0xEB10 | rn_bits;
2200 let hw2: u16 = 0x0F00 | rm_bits;
2201 let mut bytes = hw1.to_le_bytes().to_vec();
2202 bytes.extend_from_slice(&hw2.to_le_bytes());
2203 Ok(bytes)
2204 }
2205 } else {
2206 Ok(vec![0xBF, 0x00])
2207 }
2208 }
2209
2210 ArmOp::Ldr { rd, addr } => {
2212 let rd_bits = reg_to_bits(rd);
2213 let base_bits = reg_to_bits(&addr.base);
2214
2215 if let Some(offset_reg) = &addr.offset_reg {
2217 let rm_bits = reg_to_bits(offset_reg);
2218
2219 if addr.offset != 0 {
2221 let scratch = Reg::R12;
2224 let mut bytes =
2225 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2226 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2227 return Ok(bytes);
2228 }
2229
2230 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2233 let instr: u16 = 0x5800
2235 | ((rm_bits as u16) << 6)
2236 | ((base_bits as u16) << 3)
2237 | (rd_bits as u16);
2238 return Ok(instr.to_le_bytes().to_vec());
2239 }
2240
2241 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2243 }
2244
2245 let offset = addr.offset as u32;
2247
2248 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2249 let imm5 = (offset >> 2) as u16;
2251 let instr: u16 =
2252 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2253 Ok(instr.to_le_bytes().to_vec())
2254 } else {
2255 self.encode_thumb32_ldr(rd, &addr.base, offset)
2256 }
2257 }
2258
2259 ArmOp::Str { rd, addr } => {
2261 let rd_bits = reg_to_bits(rd);
2262 let base_bits = reg_to_bits(&addr.base);
2263
2264 if let Some(offset_reg) = &addr.offset_reg {
2266 let rm_bits = reg_to_bits(offset_reg);
2267
2268 if addr.offset != 0 {
2270 let scratch = Reg::R12;
2273 let mut bytes =
2274 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2275 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2276 return Ok(bytes);
2277 }
2278
2279 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2282 let instr: u16 = 0x5000
2284 | ((rm_bits as u16) << 6)
2285 | ((base_bits as u16) << 3)
2286 | (rd_bits as u16);
2287 return Ok(instr.to_le_bytes().to_vec());
2288 }
2289
2290 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2292 }
2293
2294 let offset = addr.offset as u32;
2296
2297 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2298 let imm5 = (offset >> 2) as u16;
2300 let instr: u16 =
2301 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2302 Ok(instr.to_le_bytes().to_vec())
2303 } else {
2304 self.encode_thumb32_str(rd, &addr.base, offset)
2305 }
2306 }
2307
2308 ArmOp::Ldrb { rd, addr } => {
2310 let rd_bits = reg_to_bits(rd);
2311 let base_bits = reg_to_bits(&addr.base);
2312
2313 if let Some(offset_reg) = &addr.offset_reg {
2314 if addr.offset != 0 {
2315 let scratch = Reg::R12;
2316 let mut bytes =
2317 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2318 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2319 return Ok(bytes);
2320 }
2321 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2322 }
2323
2324 let offset = addr.offset as u32;
2325 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2326 let instr: u16 = 0x7800
2328 | ((offset as u16) << 6)
2329 | ((base_bits as u16) << 3)
2330 | (rd_bits as u16);
2331 Ok(instr.to_le_bytes().to_vec())
2332 } else {
2333 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2334 }
2335 }
2336
2337 ArmOp::Ldrsb { rd, addr } => {
2339 let rd_bits = reg_to_bits(rd);
2340 let base_bits = reg_to_bits(&addr.base);
2341
2342 if let Some(offset_reg) = &addr.offset_reg {
2343 if addr.offset != 0 {
2344 let scratch = Reg::R12;
2345 let mut bytes =
2346 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2347 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2348 return Ok(bytes);
2349 }
2350 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2351 }
2352
2353 let offset = addr.offset as u32;
2354 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2357 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2359 } else {
2360 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2361 }
2362 }
2363
2364 ArmOp::Ldrh { rd, addr } => {
2366 let rd_bits = reg_to_bits(rd);
2367 let base_bits = reg_to_bits(&addr.base);
2368
2369 if let Some(offset_reg) = &addr.offset_reg {
2370 if addr.offset != 0 {
2371 let scratch = Reg::R12;
2372 let mut bytes =
2373 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2374 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2375 return Ok(bytes);
2376 }
2377 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2378 }
2379
2380 let offset = addr.offset as u32;
2381 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2382 let imm5 = (offset >> 1) as u16;
2384 let instr: u16 =
2385 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2386 Ok(instr.to_le_bytes().to_vec())
2387 } else {
2388 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2389 }
2390 }
2391
2392 ArmOp::Ldrsh { rd, addr } => {
2394 if let Some(offset_reg) = &addr.offset_reg {
2395 if addr.offset != 0 {
2396 let scratch = Reg::R12;
2397 let mut bytes =
2398 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2399 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2400 return Ok(bytes);
2401 }
2402 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2403 }
2404
2405 let offset = addr.offset as u32;
2406 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2407 }
2408
2409 ArmOp::Strb { rd, addr } => {
2411 let rd_bits = reg_to_bits(rd);
2412 let base_bits = reg_to_bits(&addr.base);
2413
2414 if let Some(offset_reg) = &addr.offset_reg {
2415 if addr.offset != 0 {
2416 let scratch = Reg::R12;
2417 let mut bytes =
2418 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2419 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2420 return Ok(bytes);
2421 }
2422 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2423 }
2424
2425 let offset = addr.offset as u32;
2426 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2427 let instr: u16 = 0x7000
2429 | ((offset as u16) << 6)
2430 | ((base_bits as u16) << 3)
2431 | (rd_bits as u16);
2432 Ok(instr.to_le_bytes().to_vec())
2433 } else {
2434 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2435 }
2436 }
2437
2438 ArmOp::Strh { rd, addr } => {
2440 let rd_bits = reg_to_bits(rd);
2441 let base_bits = reg_to_bits(&addr.base);
2442
2443 if let Some(offset_reg) = &addr.offset_reg {
2444 if addr.offset != 0 {
2445 let scratch = Reg::R12;
2446 let mut bytes =
2447 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2448 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2449 return Ok(bytes);
2450 }
2451 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2452 }
2453
2454 let offset = addr.offset as u32;
2455 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2456 let imm5 = (offset >> 1) as u16;
2458 let instr: u16 =
2459 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2460 Ok(instr.to_le_bytes().to_vec())
2461 } else {
2462 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2463 }
2464 }
2465
2466 ArmOp::MemorySize { rd } => {
2468 let rd_bits = reg_to_bits(rd);
2471 let r10_bits = reg_to_bits(&Reg::R10);
2472 if rd_bits < 8 && r10_bits < 8 {
2473 let instr: u16 =
2474 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2475 Ok(instr.to_le_bytes().to_vec())
2476 } else {
2477 let imm5: u32 = 16;
2479 let imm3 = (imm5 >> 2) & 0x7;
2480 let imm2 = imm5 & 0x3;
2481 let hw1: u16 = 0xEA4F;
2482 let hw2: u16 =
2483 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2484 let mut bytes = hw1.to_le_bytes().to_vec();
2485 bytes.extend_from_slice(&hw2.to_le_bytes());
2486 Ok(bytes)
2487 }
2488 }
2489
2490 ArmOp::MemoryGrow { rd, .. } => {
2492 let rd_bits = reg_to_bits(rd);
2496 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2499 bytes.extend_from_slice(&hw2.to_le_bytes());
2500 Ok(bytes)
2501 }
2502
2503 ArmOp::Bx { rm } => {
2505 let rm_bits = reg_to_bits(rm) as u16;
2506 let instr: u16 = 0x4700 | (rm_bits << 3);
2508 Ok(instr.to_le_bytes().to_vec())
2509 }
2510
2511 ArmOp::Blx { rm } => {
2514 let rm_bits = reg_to_bits(rm) as u16;
2515 let instr: u16 = 0x4780 | (rm_bits << 3);
2516 Ok(instr.to_le_bytes().to_vec())
2517 }
2518
2519 ArmOp::CallIndirect {
2523 rd: _,
2524 type_idx: _,
2525 table_index_reg,
2526 } => {
2527 let idx_reg = reg_to_bits(table_index_reg);
2528 let mut bytes = Vec::new();
2529
2530 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2546 bytes.extend_from_slice(&hw1.to_le_bytes());
2547 bytes.extend_from_slice(&hw2.to_le_bytes());
2548
2549 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2555 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2556
2557 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2561
2562 Ok(bytes)
2563 }
2564
2565 ArmOp::Label { .. } => Ok(Vec::new()),
2567
2568 ArmOp::Bcc { cond, label: _ } => {
2570 use synth_synthesis::Condition;
2571 let cond_bits: u16 = match cond {
2572 Condition::EQ => 0x0,
2573 Condition::NE => 0x1,
2574 Condition::HS => 0x2,
2575 Condition::LO => 0x3,
2576 Condition::HI => 0x8,
2577 Condition::LS => 0x9,
2578 Condition::GE => 0xA,
2579 Condition::LT => 0xB,
2580 Condition::GT => 0xC,
2581 Condition::LE => 0xD,
2582 };
2583 let instr: u16 = 0xD000 | (cond_bits << 8);
2585 Ok(instr.to_le_bytes().to_vec())
2586 }
2587
2588 ArmOp::B { label: _ } => {
2590 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2594 }
2595
2596 ArmOp::Bhs { label: _ } => {
2599 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2603 }
2604
2605 ArmOp::Blo { label: _ } => {
2608 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2612 }
2613
2614 ArmOp::BOffset { offset } => {
2617 let halfword_offset = *offset;
2620
2621 if (-1024..=1022).contains(&halfword_offset) {
2624 let imm11 = (halfword_offset as u16) & 0x7FF;
2626 let instr: u16 = 0xE000 | imm11;
2627 Ok(instr.to_le_bytes().to_vec())
2628 } else {
2629 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2645 let uoffset = signed_offset as u32;
2646 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;
2654 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2655
2656 let mut bytes = hw1.to_le_bytes().to_vec();
2657 bytes.extend_from_slice(&hw2.to_le_bytes());
2658 Ok(bytes)
2659 }
2660 }
2661
2662 ArmOp::BCondOffset { cond, offset } => {
2664 use synth_synthesis::Condition;
2665 let cond_bits: u16 = match cond {
2666 Condition::EQ => 0x0,
2667 Condition::NE => 0x1,
2668 Condition::HS => 0x2,
2669 Condition::LO => 0x3,
2670 Condition::HI => 0x8,
2671 Condition::LS => 0x9,
2672 Condition::GE => 0xA,
2673 Condition::LT => 0xB,
2674 Condition::GT => 0xC,
2675 Condition::LE => 0xD,
2676 };
2677
2678 let halfword_offset = *offset;
2681
2682 if (-128..=127).contains(&halfword_offset) {
2685 let imm8 = (halfword_offset as u16) & 0xFF;
2686 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2687 Ok(instr.to_le_bytes().to_vec())
2688 } else {
2689 let offset = halfword_offset >> 1;
2693 let s = if offset < 0 { 1u32 } else { 0u32 };
2694 let imm6 = ((offset >> 11) as u32) & 0x3F;
2695 let imm11 = (offset as u32) & 0x7FF;
2696 let j1 = if s == 1 { 1 } else { 0 };
2697 let j2 = if s == 1 { 1 } else { 0 };
2698
2699 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2700 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2701
2702 let mut bytes = hw1.to_le_bytes().to_vec();
2703 bytes.extend_from_slice(&hw2.to_le_bytes());
2704 Ok(bytes)
2705 }
2706 }
2707
2708 ArmOp::Bl { label: _ } => {
2709 let hw1: u16 = 0xF7FF;
2724 let hw2: u16 = 0xFFFE;
2725 let mut bytes = hw1.to_le_bytes().to_vec();
2726 bytes.extend_from_slice(&hw2.to_le_bytes());
2727 Ok(bytes)
2728 }
2729
2730 ArmOp::Mvn { rd, op2 } => {
2732 if let Operand2::Reg(rm) = op2 {
2733 let rd_bits = reg_to_bits(rd) as u16;
2734 let rm_bits = reg_to_bits(rm) as u16;
2735
2736 if rd_bits < 8 && rm_bits < 8 {
2737 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2739 Ok(instr.to_le_bytes().to_vec())
2740 } else {
2741 let hw1: u16 = 0xEA6F_u16;
2743 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2744 let mut bytes = hw1.to_le_bytes().to_vec();
2745 bytes.extend_from_slice(&hw2.to_le_bytes());
2746 Ok(bytes)
2747 }
2748 } else {
2749 let instr: u16 = 0xBF00;
2750 Ok(instr.to_le_bytes().to_vec())
2751 }
2752 }
2753
2754 ArmOp::Movw { rd, imm16 } => {
2756 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2757 }
2758
2759 ArmOp::Movt { rd, imm16 } => {
2761 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2762 }
2763
2764 ArmOp::MovwSym { rd, addend, .. } => {
2769 self.encode_thumb32_movw_raw(reg_to_bits(rd), (*addend as u32) & 0xffff)
2770 }
2771 ArmOp::MovtSym { rd, addend, .. } => {
2772 self.encode_thumb32_movt_raw(reg_to_bits(rd), ((*addend as u32) >> 16) & 0xffff)
2773 }
2774
2775 ArmOp::SetCond { rd, cond } => {
2781 let rd_bits = reg_to_bits(rd) as u16;
2782
2783 use synth_synthesis::Condition;
2785 let cond_bits: u16 = match cond {
2786 Condition::EQ => 0x0,
2787 Condition::NE => 0x1,
2788 Condition::LT => 0xB,
2789 Condition::LE => 0xD,
2790 Condition::GT => 0xC,
2791 Condition::GE => 0xA,
2792 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2797
2798 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2803 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2804
2805 let mut bytes = ite_instr.to_le_bytes().to_vec();
2816 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2817 if rd_bits <= 7 {
2818 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2820 } else {
2821 let hw1: u16 = 0xF04F;
2823 let hw2: u16 = (rd_bits << 8) | imm;
2824 bytes.extend_from_slice(&hw1.to_le_bytes());
2825 bytes.extend_from_slice(&hw2.to_le_bytes());
2826 }
2827 };
2828 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2831 }
2832
2833 ArmOp::I64SetCond {
2838 rd,
2839 rn_lo,
2840 rn_hi,
2841 rm_lo,
2842 rm_hi,
2843 cond,
2844 } => {
2845 use synth_synthesis::Condition;
2846 let rd_bits = reg_to_bits(rd) as u16;
2847 let mut bytes = Vec::new();
2848
2849 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2851 rm: &synth_synthesis::Reg|
2852 -> Vec<u8> {
2853 let rn_bits = reg_to_bits(rn) as u16;
2854 let rm_bits = reg_to_bits(rm) as u16;
2855 if rn_bits < 8 && rm_bits < 8 {
2856 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2857 instr.to_le_bytes().to_vec()
2858 } else {
2859 let n_bit = (rn_bits >> 3) & 1;
2860 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2861 instr.to_le_bytes().to_vec()
2862 }
2863 };
2864
2865 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2867 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2868 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2869 ite_instr.to_le_bytes().to_vec()
2870 };
2871
2872 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2874 let mut b = encode_ite(cond_bits);
2875 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2876 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2877 b.extend_from_slice(&mov_one.to_le_bytes());
2878 b.extend_from_slice(&mov_zero.to_le_bytes());
2879 b
2880 };
2881
2882 match cond {
2883 Condition::EQ | Condition::NE => {
2884 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2886
2887 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2890
2891 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2893
2894 let cond_bits: u16 = match cond {
2896 Condition::EQ => 0x0,
2897 Condition::NE => 0x1,
2898 _ => unreachable!(),
2899 };
2900 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2901 }
2902
2903 Condition::LT => {
2904 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2906
2907 let rn_hi_bits = reg_to_bits(rn_hi);
2910 let rm_hi_bits = reg_to_bits(rm_hi);
2911 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2912 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2913 bytes.extend_from_slice(&hw1.to_le_bytes());
2914 bytes.extend_from_slice(&hw2.to_le_bytes());
2915
2916 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2919
2920 Condition::GT => {
2921 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2924
2925 let rm_hi_bits = reg_to_bits(rm_hi);
2927 let rn_hi_bits = reg_to_bits(rn_hi);
2928 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2929 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2930 bytes.extend_from_slice(&hw1.to_le_bytes());
2931 bytes.extend_from_slice(&hw2.to_le_bytes());
2932
2933 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2936
2937 Condition::LE => {
2938 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2942
2943 let rm_hi_bits = reg_to_bits(rm_hi);
2945 let rn_hi_bits = reg_to_bits(rn_hi);
2946 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2947 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2948 bytes.extend_from_slice(&hw1.to_le_bytes());
2949 bytes.extend_from_slice(&hw2.to_le_bytes());
2950
2951 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2954
2955 Condition::GE => {
2956 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2959
2960 let rn_hi_bits = reg_to_bits(rn_hi);
2962 let rm_hi_bits = reg_to_bits(rm_hi);
2963 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2964 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2965 bytes.extend_from_slice(&hw1.to_le_bytes());
2966 bytes.extend_from_slice(&hw2.to_le_bytes());
2967
2968 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2971
2972 Condition::LO => {
2974 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2976 let rn_hi_bits = reg_to_bits(rn_hi);
2977 let rm_hi_bits = reg_to_bits(rm_hi);
2978 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2979 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2980 bytes.extend_from_slice(&hw1.to_le_bytes());
2981 bytes.extend_from_slice(&hw2.to_le_bytes());
2982 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2984
2985 Condition::HI => {
2986 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2988 let rm_hi_bits = reg_to_bits(rm_hi);
2989 let rn_hi_bits = reg_to_bits(rn_hi);
2990 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2991 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2992 bytes.extend_from_slice(&hw1.to_le_bytes());
2993 bytes.extend_from_slice(&hw2.to_le_bytes());
2994 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2996
2997 Condition::LS => {
2998 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3000 let rm_hi_bits = reg_to_bits(rm_hi);
3001 let rn_hi_bits = reg_to_bits(rn_hi);
3002 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3003 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3004 bytes.extend_from_slice(&hw1.to_le_bytes());
3005 bytes.extend_from_slice(&hw2.to_le_bytes());
3006 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3008
3009 Condition::HS => {
3010 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3012 let rn_hi_bits = reg_to_bits(rn_hi);
3013 let rm_hi_bits = reg_to_bits(rm_hi);
3014 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3015 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3016 bytes.extend_from_slice(&hw1.to_le_bytes());
3017 bytes.extend_from_slice(&hw2.to_le_bytes());
3018 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3020 }
3021
3022 Ok(bytes)
3023 }
3024
3025 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
3028 let rd_bits = reg_to_bits(rd);
3029 let rn_lo_bits = reg_to_bits(rn_lo);
3030 let rn_hi_bits = reg_to_bits(rn_hi);
3031 let mut bytes = Vec::new();
3032
3033 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3035 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3036 bytes.extend_from_slice(&hw1.to_le_bytes());
3037 bytes.extend_from_slice(&hw2.to_le_bytes());
3038
3039 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3041 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3042
3043 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3046 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3047 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3048 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3049 bytes.extend_from_slice(&mov_one.to_le_bytes());
3050 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3051
3052 Ok(bytes)
3053 }
3054
3055 ArmOp::I64Mul {
3059 rd_lo,
3060 rd_hi,
3061 rn_lo,
3062 rn_hi,
3063 rm_lo,
3064 rm_hi,
3065 } => {
3066 let rd_lo_bits = reg_to_bits(rd_lo);
3067 let rd_hi_bits = reg_to_bits(rd_hi);
3068 let rn_lo_bits = reg_to_bits(rn_lo);
3069 let rn_hi_bits = reg_to_bits(rn_hi);
3070 let rm_lo_bits = reg_to_bits(rm_lo);
3071 let rm_hi_bits = reg_to_bits(rm_hi);
3072 let r12: u32 = 12; let mut bytes = Vec::new();
3074
3075 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3078 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3079 bytes.extend_from_slice(&hw1.to_le_bytes());
3080 bytes.extend_from_slice(&hw2.to_le_bytes());
3081
3082 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3085 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3086 bytes.extend_from_slice(&hw1.to_le_bytes());
3087 bytes.extend_from_slice(&hw2.to_le_bytes());
3088
3089 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3092 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3093 bytes.extend_from_slice(&hw1.to_le_bytes());
3094 bytes.extend_from_slice(&hw2.to_le_bytes());
3095
3096 let d_bit = (rd_hi_bits >> 3) & 1;
3099 let add_instr: u16 =
3100 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3101 bytes.extend_from_slice(&add_instr.to_le_bytes());
3102
3103 Ok(bytes)
3104 }
3105
3106 ArmOp::I64Shl {
3109 rd_lo,
3110 rd_hi,
3111 rn_lo,
3112 rn_hi,
3113 rm_lo,
3114 rm_hi,
3115 } => {
3116 let rd_lo_bits = reg_to_bits(rd_lo);
3117 let rd_hi_bits = reg_to_bits(rd_hi);
3118 let rn_lo_bits = reg_to_bits(rn_lo);
3119 let rn_hi_bits = reg_to_bits(rn_hi);
3120 let rm_lo_bits = reg_to_bits(rm_lo);
3121 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3123
3124 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3126 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3127 bytes.extend_from_slice(&hw1.to_le_bytes());
3128 bytes.extend_from_slice(&hw2.to_le_bytes());
3129
3130 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3132 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3133 bytes.extend_from_slice(&hw1.to_le_bytes());
3134 bytes.extend_from_slice(&hw2.to_le_bytes());
3135
3136 let bpl: u16 = 0xD50A;
3138 bytes.extend_from_slice(&bpl.to_le_bytes());
3139
3140 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3143 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3144 bytes.extend_from_slice(&hw1.to_le_bytes());
3145 bytes.extend_from_slice(&hw2.to_le_bytes());
3146
3147 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3149 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3150 bytes.extend_from_slice(&hw1.to_le_bytes());
3151 bytes.extend_from_slice(&hw2.to_le_bytes());
3152
3153 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3155 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3156 bytes.extend_from_slice(&hw1.to_le_bytes());
3157 bytes.extend_from_slice(&hw2.to_le_bytes());
3158
3159 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3161 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3162 bytes.extend_from_slice(&hw1.to_le_bytes());
3163 bytes.extend_from_slice(&hw2.to_le_bytes());
3164
3165 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3167 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3168 bytes.extend_from_slice(&hw1.to_le_bytes());
3169 bytes.extend_from_slice(&hw2.to_le_bytes());
3170
3171 let b_done: u16 = 0xE002;
3173 bytes.extend_from_slice(&b_done.to_le_bytes());
3174
3175 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3178 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3179 bytes.extend_from_slice(&hw1.to_le_bytes());
3180 bytes.extend_from_slice(&hw2.to_le_bytes());
3181
3182 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3184 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3185
3186 Ok(bytes) }
3188
3189 ArmOp::I64ShrU {
3191 rd_lo,
3192 rd_hi,
3193 rn_lo,
3194 rn_hi,
3195 rm_lo,
3196 rm_hi,
3197 } => {
3198 let rd_lo_bits = reg_to_bits(rd_lo);
3199 let rd_hi_bits = reg_to_bits(rd_hi);
3200 let rn_lo_bits = reg_to_bits(rn_lo);
3201 let rn_hi_bits = reg_to_bits(rn_hi);
3202 let rm_lo_bits = reg_to_bits(rm_lo);
3203 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3205
3206 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3208 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3209 bytes.extend_from_slice(&hw1.to_le_bytes());
3210 bytes.extend_from_slice(&hw2.to_le_bytes());
3211
3212 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3214 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3215 bytes.extend_from_slice(&hw1.to_le_bytes());
3216 bytes.extend_from_slice(&hw2.to_le_bytes());
3217
3218 let bpl: u16 = 0xD50A;
3220 bytes.extend_from_slice(&bpl.to_le_bytes());
3221
3222 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3225 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3226 bytes.extend_from_slice(&hw1.to_le_bytes());
3227 bytes.extend_from_slice(&hw2.to_le_bytes());
3228
3229 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3231 let hw2: u16 = (0xF000 | (rm_hi_bits << 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 = (0xFA20 | rn_lo_bits) as u16;
3237 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3238 bytes.extend_from_slice(&hw1.to_le_bytes());
3239 bytes.extend_from_slice(&hw2.to_le_bytes());
3240
3241 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3243 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3244 bytes.extend_from_slice(&hw1.to_le_bytes());
3245 bytes.extend_from_slice(&hw2.to_le_bytes());
3246
3247 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3249 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3250 bytes.extend_from_slice(&hw1.to_le_bytes());
3251 bytes.extend_from_slice(&hw2.to_le_bytes());
3252
3253 let b_done: u16 = 0xE002;
3255 bytes.extend_from_slice(&b_done.to_le_bytes());
3256
3257 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3260 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3261 bytes.extend_from_slice(&hw1.to_le_bytes());
3262 bytes.extend_from_slice(&hw2.to_le_bytes());
3263
3264 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3266 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3267
3268 Ok(bytes) }
3270
3271 ArmOp::I64ShrS {
3273 rd_lo,
3274 rd_hi,
3275 rn_lo,
3276 rn_hi,
3277 rm_lo,
3278 rm_hi,
3279 } => {
3280 let rd_lo_bits = reg_to_bits(rd_lo);
3281 let rd_hi_bits = reg_to_bits(rd_hi);
3282 let rn_lo_bits = reg_to_bits(rn_lo);
3283 let rn_hi_bits = reg_to_bits(rn_hi);
3284 let rm_lo_bits = reg_to_bits(rm_lo);
3285 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3287
3288 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3290 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3291 bytes.extend_from_slice(&hw1.to_le_bytes());
3292 bytes.extend_from_slice(&hw2.to_le_bytes());
3293
3294 let hw1: u16 = (0xF1B0 | 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 bpl: u16 = 0xD50A;
3302 bytes.extend_from_slice(&bpl.to_le_bytes());
3303
3304 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3307 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3308 bytes.extend_from_slice(&hw1.to_le_bytes());
3309 bytes.extend_from_slice(&hw2.to_le_bytes());
3310
3311 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3313 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3314 bytes.extend_from_slice(&hw1.to_le_bytes());
3315 bytes.extend_from_slice(&hw2.to_le_bytes());
3316
3317 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3319 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3320 bytes.extend_from_slice(&hw1.to_le_bytes());
3321 bytes.extend_from_slice(&hw2.to_le_bytes());
3322
3323 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3325 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3326 bytes.extend_from_slice(&hw1.to_le_bytes());
3327 bytes.extend_from_slice(&hw2.to_le_bytes());
3328
3329 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3331 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3332 bytes.extend_from_slice(&hw1.to_le_bytes());
3333 bytes.extend_from_slice(&hw2.to_le_bytes());
3334
3335 let b_done: u16 = 0xE003;
3337 bytes.extend_from_slice(&b_done.to_le_bytes());
3338
3339 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3342 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3343 bytes.extend_from_slice(&hw1.to_le_bytes());
3344 bytes.extend_from_slice(&hw2.to_le_bytes());
3345
3346 let hw1: u16 = 0xEA4F;
3350 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3351 bytes.extend_from_slice(&hw1.to_le_bytes());
3352 bytes.extend_from_slice(&hw2.to_le_bytes());
3353
3354 Ok(bytes) }
3356
3357 ArmOp::I64Rotl {
3362 rdlo,
3363 rdhi,
3364 rnlo,
3365 rnhi,
3366 shift,
3367 } => {
3368 let rd_lo_bits = reg_to_bits(rdlo);
3369 let rd_hi_bits = reg_to_bits(rdhi);
3370 let rn_lo_bits = reg_to_bits(rnlo);
3371 let rn_hi_bits = reg_to_bits(rnhi);
3372 let shift_bits = reg_to_bits(shift);
3373 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3377
3378 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3380
3381 let hw1: u16 = (0xF000 | shift_bits) as u16;
3383 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3384 bytes.extend_from_slice(&hw1.to_le_bytes());
3385 bytes.extend_from_slice(&hw2.to_le_bytes());
3386
3387 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3389 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3390 bytes.extend_from_slice(&hw1.to_le_bytes());
3391 bytes.extend_from_slice(&hw2.to_le_bytes());
3392
3393 let bpl: u16 = 0xD50E;
3395 bytes.extend_from_slice(&bpl.to_le_bytes());
3396
3397 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3400 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3401 bytes.extend_from_slice(&hw1.to_le_bytes());
3402 bytes.extend_from_slice(&hw2.to_le_bytes());
3403
3404 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3406 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3407 bytes.extend_from_slice(&hw1.to_le_bytes());
3408 bytes.extend_from_slice(&hw2.to_le_bytes());
3409
3410 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3412 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3413 bytes.extend_from_slice(&hw1.to_le_bytes());
3414 bytes.extend_from_slice(&hw2.to_le_bytes());
3415
3416 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3418 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3419 bytes.extend_from_slice(&hw1.to_le_bytes());
3420 bytes.extend_from_slice(&hw2.to_le_bytes());
3421
3422 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3424 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3425 bytes.extend_from_slice(&hw1.to_le_bytes());
3426 bytes.extend_from_slice(&hw2.to_le_bytes());
3427
3428 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3430 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3431 bytes.extend_from_slice(&hw1.to_le_bytes());
3432 bytes.extend_from_slice(&hw2.to_le_bytes());
3433
3434 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3436 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3437 bytes.extend_from_slice(&hw1.to_le_bytes());
3438 bytes.extend_from_slice(&hw2.to_le_bytes());
3439
3440 let b_done: u16 = 0xE00E;
3442 bytes.extend_from_slice(&b_done.to_le_bytes());
3443
3444 let hw1: u16 = (0xF1C0 | r3) as u16;
3448 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3449 bytes.extend_from_slice(&hw1.to_le_bytes());
3450 bytes.extend_from_slice(&hw2.to_le_bytes());
3451
3452 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3454 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3455 bytes.extend_from_slice(&hw1.to_le_bytes());
3456 bytes.extend_from_slice(&hw2.to_le_bytes());
3457
3458 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3460 let hw2: u16 = (0xF000 | (r4 << 8) | r4) 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_lo_bits) as u16;
3466 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) 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 = (0xEA40 | shift_bits) as u16;
3472 let hw2: u16 = ((shift_bits << 8) | r12) 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 = (0xFA00 | rn_hi_bits) as u16;
3478 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) 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 = (0xEA40 | rd_lo_bits) as u16;
3484 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3485 bytes.extend_from_slice(&hw1.to_le_bytes());
3486 bytes.extend_from_slice(&hw2.to_le_bytes());
3487
3488 let d_bit = (rd_hi_bits >> 3) & 1;
3490 let mov_instr: u16 =
3491 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3492 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3493
3494 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3496
3497 Ok(bytes) }
3499
3500 ArmOp::I64Rotr {
3505 rdlo,
3506 rdhi,
3507 rnlo,
3508 rnhi,
3509 shift,
3510 } => {
3511 let rd_lo_bits = reg_to_bits(rdlo);
3512 let rd_hi_bits = reg_to_bits(rdhi);
3513 let rn_lo_bits = reg_to_bits(rnlo);
3514 let rn_hi_bits = reg_to_bits(rnhi);
3515 let shift_bits = reg_to_bits(shift);
3516 let r12: u32 = 12;
3517 let r3: u32 = 3;
3518 let r4: u32 = 4;
3519 let mut bytes = Vec::new();
3520
3521 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3523
3524 let hw1: u16 = (0xF000 | shift_bits) as u16;
3526 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3527 bytes.extend_from_slice(&hw1.to_le_bytes());
3528 bytes.extend_from_slice(&hw2.to_le_bytes());
3529
3530 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3532 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3533 bytes.extend_from_slice(&hw1.to_le_bytes());
3534 bytes.extend_from_slice(&hw2.to_le_bytes());
3535
3536 let bpl: u16 = 0xD50E;
3538 bytes.extend_from_slice(&bpl.to_le_bytes());
3539
3540 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3543 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3544 bytes.extend_from_slice(&hw1.to_le_bytes());
3545 bytes.extend_from_slice(&hw2.to_le_bytes());
3546
3547 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3549 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3550 bytes.extend_from_slice(&hw1.to_le_bytes());
3551 bytes.extend_from_slice(&hw2.to_le_bytes());
3552
3553 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3555 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3556 bytes.extend_from_slice(&hw1.to_le_bytes());
3557 bytes.extend_from_slice(&hw2.to_le_bytes());
3558
3559 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3561 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3562 bytes.extend_from_slice(&hw1.to_le_bytes());
3563 bytes.extend_from_slice(&hw2.to_le_bytes());
3564
3565 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3567 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3568 bytes.extend_from_slice(&hw1.to_le_bytes());
3569 bytes.extend_from_slice(&hw2.to_le_bytes());
3570
3571 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3573 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3574 bytes.extend_from_slice(&hw1.to_le_bytes());
3575 bytes.extend_from_slice(&hw2.to_le_bytes());
3576
3577 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3579 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3580 bytes.extend_from_slice(&hw1.to_le_bytes());
3581 bytes.extend_from_slice(&hw2.to_le_bytes());
3582
3583 let b_done: u16 = 0xE00E;
3585 bytes.extend_from_slice(&b_done.to_le_bytes());
3586
3587 let hw1: u16 = (0xF1C0 | r3) as u16;
3590 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3591 bytes.extend_from_slice(&hw1.to_le_bytes());
3592 bytes.extend_from_slice(&hw2.to_le_bytes());
3593
3594 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3596 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3597 bytes.extend_from_slice(&hw1.to_le_bytes());
3598 bytes.extend_from_slice(&hw2.to_le_bytes());
3599
3600 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3602 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3603 bytes.extend_from_slice(&hw1.to_le_bytes());
3604 bytes.extend_from_slice(&hw2.to_le_bytes());
3605
3606 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3608 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3609 bytes.extend_from_slice(&hw1.to_le_bytes());
3610 bytes.extend_from_slice(&hw2.to_le_bytes());
3611
3612 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3614 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3615 bytes.extend_from_slice(&hw1.to_le_bytes());
3616 bytes.extend_from_slice(&hw2.to_le_bytes());
3617
3618 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3620 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3621 bytes.extend_from_slice(&hw1.to_le_bytes());
3622 bytes.extend_from_slice(&hw2.to_le_bytes());
3623
3624 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3626 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3627 bytes.extend_from_slice(&hw1.to_le_bytes());
3628 bytes.extend_from_slice(&hw2.to_le_bytes());
3629
3630 let d_bit = (rd_lo_bits >> 3) & 1;
3632 let mov_instr: u16 =
3633 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3634 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3635
3636 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3638
3639 Ok(bytes) }
3641
3642 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3656 let rd_bits = reg_to_bits(rd);
3657 let rn_lo_bits = reg_to_bits(rnlo);
3658 let rn_hi_bits = reg_to_bits(rnhi);
3659 let mut bytes = Vec::new();
3660
3661 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3663 let hw2: u16 = 0x0F00;
3664 bytes.extend_from_slice(&hw1.to_le_bytes());
3665 bytes.extend_from_slice(&hw2.to_le_bytes());
3666
3667 let beq: u16 = 0xD003;
3670 bytes.extend_from_slice(&beq.to_le_bytes());
3671
3672 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3675 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3676 bytes.extend_from_slice(&hw1.to_le_bytes());
3677 bytes.extend_from_slice(&hw2.to_le_bytes());
3678
3679 let b_done: u16 = 0xE004;
3682 bytes.extend_from_slice(&b_done.to_le_bytes());
3683
3684 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3686
3687 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3691 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3692 bytes.extend_from_slice(&hw1.to_le_bytes());
3693 bytes.extend_from_slice(&hw2.to_le_bytes());
3694
3695 let hw1: u16 = (0xF100 | rd_bits) as u16;
3697 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3698 bytes.extend_from_slice(&hw1.to_le_bytes());
3699 bytes.extend_from_slice(&hw2.to_le_bytes());
3700
3701 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3705 bytes.extend_from_slice(&mov0.to_le_bytes());
3706
3707 Ok(bytes)
3708 }
3709
3710 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3726 let rd_bits = reg_to_bits(rd);
3727 let rn_lo_bits = reg_to_bits(rnlo);
3728 let rn_hi_bits = reg_to_bits(rnhi);
3729 let mut bytes = Vec::new();
3730
3731 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3733 let hw2: u16 = 0x0F00;
3734 bytes.extend_from_slice(&hw1.to_le_bytes());
3735 bytes.extend_from_slice(&hw2.to_le_bytes());
3736
3737 let beq: u16 = 0xD005;
3740 bytes.extend_from_slice(&beq.to_le_bytes());
3741
3742 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3745 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3746 bytes.extend_from_slice(&hw1.to_le_bytes());
3747 bytes.extend_from_slice(&hw2.to_le_bytes());
3748
3749 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3752 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3753 bytes.extend_from_slice(&hw1.to_le_bytes());
3754 bytes.extend_from_slice(&hw2.to_le_bytes());
3755
3756 let b_done: u16 = 0xE006;
3759 bytes.extend_from_slice(&b_done.to_le_bytes());
3760
3761 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3763
3764 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3768 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3769 bytes.extend_from_slice(&hw1.to_le_bytes());
3770 bytes.extend_from_slice(&hw2.to_le_bytes());
3771
3772 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3775 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3776 bytes.extend_from_slice(&hw1.to_le_bytes());
3777 bytes.extend_from_slice(&hw2.to_le_bytes());
3778
3779 let hw1: u16 = (0xF100 | rd_bits) as u16;
3781 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3782 bytes.extend_from_slice(&hw1.to_le_bytes());
3783 bytes.extend_from_slice(&hw2.to_le_bytes());
3784
3785 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3788 bytes.extend_from_slice(&mov0.to_le_bytes());
3789
3790 Ok(bytes)
3791 }
3792
3793 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3797 let rd_bits = reg_to_bits(rd);
3798 let rn_lo_bits = reg_to_bits(rnlo);
3799 let rn_hi_bits = reg_to_bits(rnhi);
3800 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3803
3804 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3806
3807 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3817 bytes.extend_from_slice(&mov.to_le_bytes());
3818
3819 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3822 bytes.extend_from_slice(&mov.to_le_bytes());
3823
3824 let hw1: u16 = 0xEA4F;
3828 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3829 bytes.extend_from_slice(&hw1.to_le_bytes());
3830 bytes.extend_from_slice(&hw2.to_le_bytes());
3831
3832 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3835 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3836 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3838 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3839
3840 let hw1: u16 = (0xEA00 | r12) as u16;
3842 let hw2: u16 = ((r12 << 8) | r3) as u16;
3843 bytes.extend_from_slice(&hw1.to_le_bytes());
3844 bytes.extend_from_slice(&hw2.to_le_bytes());
3845
3846 let hw1: u16 = (0xEBA0 | 4) as u16;
3848 let hw2: u16 = ((4 << 8) | r12) as u16;
3849 bytes.extend_from_slice(&hw1.to_le_bytes());
3850 bytes.extend_from_slice(&hw2.to_le_bytes());
3851
3852 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3856 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3857 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3859 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3860
3861 let hw1: u16 = (0xEA00 | 4) as u16;
3863 let hw2: u16 = ((r12 << 8) | r3) as u16;
3864 bytes.extend_from_slice(&hw1.to_le_bytes());
3865 bytes.extend_from_slice(&hw2.to_le_bytes());
3866
3867 let hw1: u16 = 0xEA4F;
3869 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3870 bytes.extend_from_slice(&hw1.to_le_bytes());
3871 bytes.extend_from_slice(&hw2.to_le_bytes());
3872
3873 let hw1: u16 = (0xEA00 | 4) as u16;
3875 let hw2: u16 = ((4 << 8) | r3) as u16;
3876 bytes.extend_from_slice(&hw1.to_le_bytes());
3877 bytes.extend_from_slice(&hw2.to_le_bytes());
3878
3879 let hw1: u16 = (0xEB00 | 4) as u16;
3881 let hw2: u16 = ((4 << 8) | r12) as u16;
3882 bytes.extend_from_slice(&hw1.to_le_bytes());
3883 bytes.extend_from_slice(&hw2.to_le_bytes());
3884
3885 let hw1: u16 = 0xEA4F;
3890 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3891 bytes.extend_from_slice(&hw1.to_le_bytes());
3892 bytes.extend_from_slice(&hw2.to_le_bytes());
3893
3894 let hw1: u16 = (0xEB00 | 4) as u16;
3896 let hw2: u16 = ((4 << 8) | r12) as u16;
3897 bytes.extend_from_slice(&hw1.to_le_bytes());
3898 bytes.extend_from_slice(&hw2.to_le_bytes());
3899
3900 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3905 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3906 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3908 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3909
3910 let hw1: u16 = (0xEA00 | 4) as u16;
3912 let hw2: u16 = ((4 << 8) | r3) as u16;
3913 bytes.extend_from_slice(&hw1.to_le_bytes());
3914 bytes.extend_from_slice(&hw2.to_le_bytes());
3915
3916 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3920 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3921 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3923 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3924
3925 let hw1: u16 = (0xFB00 | 4) as u16;
3928 let hw2: u16 = (0xF000 | (4 << 8) | r3) 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 = 0xEA4F;
3935 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3936 bytes.extend_from_slice(&hw1.to_le_bytes());
3937 bytes.extend_from_slice(&hw2.to_le_bytes());
3938
3939 let hw1: u16 = 0xEA4F;
3942 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3943 bytes.extend_from_slice(&hw1.to_le_bytes());
3944 bytes.extend_from_slice(&hw2.to_le_bytes());
3945
3946 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3948 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3949 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3950 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3951
3952 let hw1: u16 = (0xEA00 | r12) as u16;
3953 let hw2: u16 = ((r12 << 8) | r3) as u16;
3954 bytes.extend_from_slice(&hw1.to_le_bytes());
3955 bytes.extend_from_slice(&hw2.to_le_bytes());
3956
3957 let hw1: u16 = (0xEBA0 | 5) as u16;
3958 let hw2: u16 = ((5 << 8) | r12) as u16;
3959 bytes.extend_from_slice(&hw1.to_le_bytes());
3960 bytes.extend_from_slice(&hw2.to_le_bytes());
3961
3962 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3964 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3965 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3966 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3967
3968 let hw1: u16 = (0xEA00 | 5) as u16;
3969 let hw2: u16 = ((r12 << 8) | r3) as u16;
3970 bytes.extend_from_slice(&hw1.to_le_bytes());
3971 bytes.extend_from_slice(&hw2.to_le_bytes());
3972
3973 let hw1: u16 = 0xEA4F;
3974 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3975 bytes.extend_from_slice(&hw1.to_le_bytes());
3976 bytes.extend_from_slice(&hw2.to_le_bytes());
3977
3978 let hw1: u16 = (0xEA00 | 5) as u16;
3979 let hw2: u16 = ((5 << 8) | r3) as u16;
3980 bytes.extend_from_slice(&hw1.to_le_bytes());
3981 bytes.extend_from_slice(&hw2.to_le_bytes());
3982
3983 let hw1: u16 = (0xEB00 | 5) as u16;
3984 let hw2: u16 = ((5 << 8) | r12) as u16;
3985 bytes.extend_from_slice(&hw1.to_le_bytes());
3986 bytes.extend_from_slice(&hw2.to_le_bytes());
3987
3988 let hw1: u16 = 0xEA4F;
3991 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3992 bytes.extend_from_slice(&hw1.to_le_bytes());
3993 bytes.extend_from_slice(&hw2.to_le_bytes());
3994
3995 let hw1: u16 = (0xEB00 | 5) as u16;
3996 let hw2: u16 = ((5 << 8) | r12) as u16;
3997 bytes.extend_from_slice(&hw1.to_le_bytes());
3998 bytes.extend_from_slice(&hw2.to_le_bytes());
3999
4000 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4002 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4003 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4004 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4005
4006 let hw1: u16 = (0xEA00 | 5) as u16;
4007 let hw2: u16 = ((5 << 8) | r3) as u16;
4008 bytes.extend_from_slice(&hw1.to_le_bytes());
4009 bytes.extend_from_slice(&hw2.to_le_bytes());
4010
4011 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4013 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4014 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4015 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4016
4017 let hw1: u16 = (0xFB00 | 5) as u16;
4020 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
4021 bytes.extend_from_slice(&hw1.to_le_bytes());
4022 bytes.extend_from_slice(&hw2.to_le_bytes());
4023
4024 let hw1: u16 = 0xEA4F;
4027 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
4028 bytes.extend_from_slice(&hw1.to_le_bytes());
4029 bytes.extend_from_slice(&hw2.to_le_bytes());
4030
4031 let rd_bits_u16 = rd_bits as u16;
4034 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4035 bytes.extend_from_slice(&instr.to_le_bytes());
4036
4037 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4039
4040 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4042 bytes.extend_from_slice(&mov0.to_le_bytes());
4043
4044 Ok(bytes)
4045 }
4046
4047 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4050 let rdlo_bits = reg_to_bits(rdlo);
4051 let rdhi_bits = reg_to_bits(rdhi);
4052 let rnlo_bits = reg_to_bits(rnlo);
4053 let mut bytes = Vec::new();
4054
4055 let hw1: u16 = 0xFA4F_u16;
4058 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4059 bytes.extend_from_slice(&hw1.to_le_bytes());
4060 bytes.extend_from_slice(&hw2.to_le_bytes());
4061
4062 let hw1: u16 = 0xEA4F;
4067 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4068 bytes.extend_from_slice(&hw1.to_le_bytes());
4069 bytes.extend_from_slice(&hw2.to_le_bytes());
4070
4071 Ok(bytes)
4072 }
4073
4074 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4077 let rdlo_bits = reg_to_bits(rdlo);
4078 let rdhi_bits = reg_to_bits(rdhi);
4079 let rnlo_bits = reg_to_bits(rnlo);
4080 let mut bytes = Vec::new();
4081
4082 let hw1: u16 = 0xFA0F_u16;
4085 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4086 bytes.extend_from_slice(&hw1.to_le_bytes());
4087 bytes.extend_from_slice(&hw2.to_le_bytes());
4088
4089 let hw1: u16 = 0xEA4F;
4091 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4092 bytes.extend_from_slice(&hw1.to_le_bytes());
4093 bytes.extend_from_slice(&hw2.to_le_bytes());
4094
4095 Ok(bytes)
4096 }
4097
4098 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4101 let rdlo_bits = reg_to_bits(rdlo);
4102 let rdhi_bits = reg_to_bits(rdhi);
4103 let rnlo_bits = reg_to_bits(rnlo);
4104 let mut bytes = Vec::new();
4105
4106 if rdlo_bits != rnlo_bits {
4108 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4110 let mov: u16 = 0x4600
4111 | (d_bit << 7)
4112 | ((rnlo_bits as u16) << 3)
4113 | ((rdlo_bits & 0x7) as u16);
4114 bytes.extend_from_slice(&mov.to_le_bytes());
4115 }
4116
4117 let hw1: u16 = 0xEA4F;
4119 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4120 bytes.extend_from_slice(&hw1.to_le_bytes());
4121 bytes.extend_from_slice(&hw2.to_le_bytes());
4122
4123 Ok(bytes)
4124 }
4125
4126 ArmOp::SelectMove { rd, rm, cond } => {
4129 let rd_bits = reg_to_bits(rd) as u16;
4130 let rm_bits = reg_to_bits(rm) as u16;
4131
4132 use synth_synthesis::Condition;
4134 let cond_bits: u16 = match cond {
4135 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, };
4146
4147 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4150
4151 let d_bit = (rd_bits >> 3) & 1;
4154 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4155
4156 let mut bytes = it_instr.to_le_bytes().to_vec();
4158 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4159 Ok(bytes)
4160 }
4161
4162 ArmOp::Popcnt { rd, rm } => {
4173 let mut bytes = Vec::new();
4174
4175 if rd != rm {
4177 let rd_bits = reg_to_bits(rd) as u16;
4178 let rm_bits = reg_to_bits(rm) as u16;
4179 let d_bit = (rd_bits >> 3) & 1;
4181 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4182 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4183 }
4184
4185 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4188 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4189
4190 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4193
4194 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4196
4197 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4199 reg_to_bits(rd),
4200 reg_to_bits(rd),
4201 11,
4202 )?);
4203
4204 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4207 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4208
4209 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4211 11,
4212 reg_to_bits(rd),
4213 12,
4214 )?);
4215
4216 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4218 reg_to_bits(rd),
4219 reg_to_bits(rd),
4220 2,
4221 )?);
4222
4223 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4225 reg_to_bits(rd),
4226 reg_to_bits(rd),
4227 12,
4228 )?);
4229
4230 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4232 reg_to_bits(rd),
4233 reg_to_bits(rd),
4234 11,
4235 )?);
4236
4237 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4240
4241 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4243 reg_to_bits(rd),
4244 reg_to_bits(rd),
4245 11,
4246 )?);
4247
4248 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4250 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4251
4252 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4254 reg_to_bits(rd),
4255 reg_to_bits(rd),
4256 12,
4257 )?);
4258
4259 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4262
4263 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4265 reg_to_bits(rd),
4266 reg_to_bits(rd),
4267 11,
4268 )?);
4269
4270 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4273
4274 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4276 reg_to_bits(rd),
4277 reg_to_bits(rd),
4278 11,
4279 )?);
4280
4281 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4284 reg_to_bits(rd),
4285 reg_to_bits(rd),
4286 0x3F,
4287 )?);
4288
4289 Ok(bytes)
4290 }
4291
4292 ArmOp::I64DivU {
4297 rdlo: _,
4298 rdhi: _,
4299 rnlo: _,
4300 rnhi: _,
4301 rmlo: _,
4302 rmhi: _,
4303 } => {
4304 let mut bytes = Vec::new();
4305
4306 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4310
4311 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());
4322 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4323
4324 let loop_start = bytes.len();
4326
4327 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4338 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());
4347 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4348 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4352 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4353
4354 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4359 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4360 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());
4391 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4392 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4395
4396 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4400 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4401
4402 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4405 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4406 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4407
4408 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4416
4417 Ok(bytes)
4418 }
4419
4420 ArmOp::I64DivS {
4425 rdlo: _,
4426 rdhi: _,
4427 rnlo: _,
4428 rnhi: _,
4429 rmlo: _,
4430 rmhi: _,
4431 } => {
4432 let mut bytes = Vec::new();
4433
4434 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4436 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4437
4438 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4441 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4442
4443 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());
4456
4457 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());
4467
4468 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4471 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4472 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4474 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4475 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4477 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4478
4479 let loop_start = bytes.len();
4480
4481 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4485 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());
4491 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4494
4495 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4499 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());
4512 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4514
4515 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4518
4519 let branch_offset_bytes = bytes.len() - loop_start + 4;
4520 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4521 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4522 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4523
4524 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());
4531 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());
4539
4540 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4542 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4543
4544 Ok(bytes)
4545 }
4546
4547 ArmOp::I64RemU {
4552 rdlo: _,
4553 rdhi: _,
4554 rnlo: _,
4555 rnhi: _,
4556 rmlo: _,
4557 rmhi: _,
4558 } => {
4559 let mut bytes = Vec::new();
4560
4561 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4563 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4564
4565 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4567 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4568 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4570 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4571 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4573 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4574
4575 let loop_start = bytes.len();
4576
4577 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4581 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());
4587 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4590
4591 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4595 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());
4608 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4610
4611 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4614
4615 let branch_offset_bytes = bytes.len() - loop_start + 4;
4616 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4617 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4618 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4619
4620 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4626 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4627
4628 Ok(bytes)
4629 }
4630
4631 ArmOp::I64RemS {
4636 rdlo: _,
4637 rdhi: _,
4638 rnlo: _,
4639 rnhi: _,
4640 rmlo: _,
4641 rmhi: _,
4642 } => {
4643 let mut bytes = Vec::new();
4644
4645 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4647 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4648
4649 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());
4663
4664 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());
4674
4675 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4678 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4679 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4681 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4682 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4684 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4685
4686 let loop_start = bytes.len();
4687
4688 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4692 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());
4698 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4701
4702 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4706 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());
4719 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4721
4722 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4725
4726 let branch_offset_bytes = bytes.len() - loop_start + 4;
4727 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4728 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4729 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4730
4731 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());
4738 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());
4746
4747 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4749 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4750
4751 Ok(bytes)
4752 }
4753
4754 ArmOp::F32Add { sd, sn, sm } => {
4757 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4758 }
4759 ArmOp::F32Sub { sd, sn, sm } => {
4760 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4761 }
4762 ArmOp::F32Mul { sd, sn, sm } => {
4763 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4764 }
4765 ArmOp::F32Div { sd, sn, sm } => {
4766 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4767 }
4768 ArmOp::F32Abs { sd, sm } => {
4769 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4770 }
4771 ArmOp::F32Neg { sd, sm } => {
4772 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4773 }
4774 ArmOp::F32Sqrt { sd, sm } => {
4775 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4776 }
4777
4778 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4781 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4782 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4783 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4784 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4785 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4786 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4787
4788 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4790 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4791 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4792 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4793 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4794 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4795
4796 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4797
4798 ArmOp::F32Load { sd, addr } => {
4799 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4800 }
4801 ArmOp::F32Store { sd, addr } => {
4802 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4803 }
4804
4805 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4806 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4807 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4808 Err(synth_core::Error::synthesis(
4809 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4810 ))
4811 }
4812 ArmOp::F32ReinterpretI32 { sd, rm } => {
4813 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4814 }
4815 ArmOp::I32ReinterpretF32 { rd, sm } => {
4816 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4817 }
4818 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4819 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4820
4821 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4824 0xEE300B00, dd, dn, dm,
4825 )?)),
4826 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4827 0xEE300B40, dd, dn, dm,
4828 )?)),
4829 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4830 0xEE200B00, dd, dn, dm,
4831 )?)),
4832 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4833 0xEE800B00, dd, dn, dm,
4834 )?)),
4835 ArmOp::F64Abs { dd, dm } => {
4836 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4837 }
4838 ArmOp::F64Neg { dd, dm } => {
4839 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4840 }
4841 ArmOp::F64Sqrt { dd, dm } => {
4842 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4843 }
4844
4845 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4848 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4849 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4850 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4851 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4852 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4853 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4854
4855 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4857 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4858 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4859 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4860 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4861 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4862
4863 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4864
4865 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4866 0xED900B00, dd, addr,
4867 )?)),
4868 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4869 0xED800B00, dd, addr,
4870 )?)),
4871
4872 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4873 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4874 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4875 Err(synth_core::Error::synthesis(
4876 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4877 ))
4878 }
4879 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4880 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4881 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4882 )),
4883 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4884 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4885 )),
4886 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4887 Err(synth_core::Error::synthesis(
4888 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4889 ))
4890 }
4891 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4892 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4893
4894 ArmOp::I64Add {
4898 rdlo,
4899 rdhi,
4900 rnlo,
4901 rnhi,
4902 rmlo,
4903 rmhi,
4904 } => {
4905 let mut bytes = Vec::new();
4906 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4908 rd: *rdlo,
4909 rn: *rnlo,
4910 op2: Operand2::Reg(*rmlo),
4911 })?);
4912 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4914 rd: *rdhi,
4915 rn: *rnhi,
4916 op2: Operand2::Reg(*rmhi),
4917 })?);
4918 Ok(bytes)
4919 }
4920
4921 ArmOp::I64Sub {
4923 rdlo,
4924 rdhi,
4925 rnlo,
4926 rnhi,
4927 rmlo,
4928 rmhi,
4929 } => {
4930 let mut bytes = Vec::new();
4931 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4933 rd: *rdlo,
4934 rn: *rnlo,
4935 op2: Operand2::Reg(*rmlo),
4936 })?);
4937 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4939 rd: *rdhi,
4940 rn: *rnhi,
4941 op2: Operand2::Reg(*rmhi),
4942 })?);
4943 Ok(bytes)
4944 }
4945
4946 ArmOp::I64And {
4948 rdlo,
4949 rdhi,
4950 rnlo,
4951 rnhi,
4952 rmlo,
4953 rmhi,
4954 } => {
4955 let mut bytes = Vec::new();
4956 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4957 rd: *rdlo,
4958 rn: *rnlo,
4959 op2: Operand2::Reg(*rmlo),
4960 })?);
4961 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4962 rd: *rdhi,
4963 rn: *rnhi,
4964 op2: Operand2::Reg(*rmhi),
4965 })?);
4966 Ok(bytes)
4967 }
4968
4969 ArmOp::I64Or {
4971 rdlo,
4972 rdhi,
4973 rnlo,
4974 rnhi,
4975 rmlo,
4976 rmhi,
4977 } => {
4978 let mut bytes = Vec::new();
4979 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4980 rd: *rdlo,
4981 rn: *rnlo,
4982 op2: Operand2::Reg(*rmlo),
4983 })?);
4984 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4985 rd: *rdhi,
4986 rn: *rnhi,
4987 op2: Operand2::Reg(*rmhi),
4988 })?);
4989 Ok(bytes)
4990 }
4991
4992 ArmOp::I64Xor {
4994 rdlo,
4995 rdhi,
4996 rnlo,
4997 rnhi,
4998 rmlo,
4999 rmhi,
5000 } => {
5001 let mut bytes = Vec::new();
5002 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5003 rd: *rdlo,
5004 rn: *rnlo,
5005 op2: Operand2::Reg(*rmlo),
5006 })?);
5007 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5008 rd: *rdhi,
5009 rn: *rnhi,
5010 op2: Operand2::Reg(*rmhi),
5011 })?);
5012 Ok(bytes)
5013 }
5014
5015 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
5017 rd: *rd,
5018 rn_lo: *rnlo,
5019 rn_hi: *rnhi,
5020 }),
5021
5022 ArmOp::I64Eq {
5024 rd,
5025 rnlo,
5026 rnhi,
5027 rmlo,
5028 rmhi,
5029 } => self.encode_thumb(&ArmOp::I64SetCond {
5030 rd: *rd,
5031 rn_lo: *rnlo,
5032 rn_hi: *rnhi,
5033 rm_lo: *rmlo,
5034 rm_hi: *rmhi,
5035 cond: synth_synthesis::Condition::EQ,
5036 }),
5037
5038 ArmOp::I64Ne {
5039 rd,
5040 rnlo,
5041 rnhi,
5042 rmlo,
5043 rmhi,
5044 } => self.encode_thumb(&ArmOp::I64SetCond {
5045 rd: *rd,
5046 rn_lo: *rnlo,
5047 rn_hi: *rnhi,
5048 rm_lo: *rmlo,
5049 rm_hi: *rmhi,
5050 cond: synth_synthesis::Condition::NE,
5051 }),
5052
5053 ArmOp::I64LtS {
5054 rd,
5055 rnlo,
5056 rnhi,
5057 rmlo,
5058 rmhi,
5059 } => self.encode_thumb(&ArmOp::I64SetCond {
5060 rd: *rd,
5061 rn_lo: *rnlo,
5062 rn_hi: *rnhi,
5063 rm_lo: *rmlo,
5064 rm_hi: *rmhi,
5065 cond: synth_synthesis::Condition::LT,
5066 }),
5067
5068 ArmOp::I64LtU {
5069 rd,
5070 rnlo,
5071 rnhi,
5072 rmlo,
5073 rmhi,
5074 } => self.encode_thumb(&ArmOp::I64SetCond {
5075 rd: *rd,
5076 rn_lo: *rnlo,
5077 rn_hi: *rnhi,
5078 rm_lo: *rmlo,
5079 rm_hi: *rmhi,
5080 cond: synth_synthesis::Condition::LO,
5081 }),
5082
5083 ArmOp::I64LeS {
5084 rd,
5085 rnlo,
5086 rnhi,
5087 rmlo,
5088 rmhi,
5089 } => self.encode_thumb(&ArmOp::I64SetCond {
5090 rd: *rd,
5091 rn_lo: *rnlo,
5092 rn_hi: *rnhi,
5093 rm_lo: *rmlo,
5094 rm_hi: *rmhi,
5095 cond: synth_synthesis::Condition::LE,
5096 }),
5097
5098 ArmOp::I64LeU {
5099 rd,
5100 rnlo,
5101 rnhi,
5102 rmlo,
5103 rmhi,
5104 } => self.encode_thumb(&ArmOp::I64SetCond {
5105 rd: *rd,
5106 rn_lo: *rnlo,
5107 rn_hi: *rnhi,
5108 rm_lo: *rmlo,
5109 rm_hi: *rmhi,
5110 cond: synth_synthesis::Condition::LS,
5111 }),
5112
5113 ArmOp::I64GtS {
5114 rd,
5115 rnlo,
5116 rnhi,
5117 rmlo,
5118 rmhi,
5119 } => self.encode_thumb(&ArmOp::I64SetCond {
5120 rd: *rd,
5121 rn_lo: *rnlo,
5122 rn_hi: *rnhi,
5123 rm_lo: *rmlo,
5124 rm_hi: *rmhi,
5125 cond: synth_synthesis::Condition::GT,
5126 }),
5127
5128 ArmOp::I64GtU {
5129 rd,
5130 rnlo,
5131 rnhi,
5132 rmlo,
5133 rmhi,
5134 } => self.encode_thumb(&ArmOp::I64SetCond {
5135 rd: *rd,
5136 rn_lo: *rnlo,
5137 rn_hi: *rnhi,
5138 rm_lo: *rmlo,
5139 rm_hi: *rmhi,
5140 cond: synth_synthesis::Condition::HI,
5141 }),
5142
5143 ArmOp::I64GeS {
5144 rd,
5145 rnlo,
5146 rnhi,
5147 rmlo,
5148 rmhi,
5149 } => self.encode_thumb(&ArmOp::I64SetCond {
5150 rd: *rd,
5151 rn_lo: *rnlo,
5152 rn_hi: *rnhi,
5153 rm_lo: *rmlo,
5154 rm_hi: *rmhi,
5155 cond: synth_synthesis::Condition::GE,
5156 }),
5157
5158 ArmOp::I64GeU {
5159 rd,
5160 rnlo,
5161 rnhi,
5162 rmlo,
5163 rmhi,
5164 } => self.encode_thumb(&ArmOp::I64SetCond {
5165 rd: *rd,
5166 rn_lo: *rnlo,
5167 rn_hi: *rnhi,
5168 rm_lo: *rmlo,
5169 rm_hi: *rmhi,
5170 cond: synth_synthesis::Condition::HS,
5171 }),
5172
5173 ArmOp::I64Const { rdlo, rdhi, value } => {
5175 let lo32 = *value as u32;
5176 let hi32 = (*value >> 32) as u32;
5177 let mut bytes = Vec::new();
5178 bytes.extend_from_slice(
5180 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5181 );
5182 if lo32 > 0xFFFF {
5183 bytes.extend_from_slice(
5184 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5185 );
5186 }
5187 bytes.extend_from_slice(
5189 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5190 );
5191 if hi32 > 0xFFFF {
5192 bytes.extend_from_slice(
5193 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5194 );
5195 }
5196 Ok(bytes)
5197 }
5198
5199 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5201 let mut bytes = Vec::new();
5202 let offset = if addr.offset < 0 {
5203 0u32
5204 } else {
5205 addr.offset as u32
5206 };
5207 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5208 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5209 rdhi,
5210 &addr.base,
5211 offset.wrapping_add(4),
5212 )?);
5213 Ok(bytes)
5214 }
5215
5216 ArmOp::I64Str { rdlo, rdhi, addr } => {
5218 let mut bytes = Vec::new();
5219 let offset = if addr.offset < 0 {
5220 0u32
5221 } else {
5222 addr.offset as u32
5223 };
5224 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5225 bytes.extend_from_slice(&self.encode_thumb32_str(
5226 rdhi,
5227 &addr.base,
5228 offset.wrapping_add(4),
5229 )?);
5230 Ok(bytes)
5231 }
5232
5233 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5235 let mut bytes = Vec::new();
5236 if rdlo != rn {
5237 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5239 rd: *rdlo,
5240 op2: Operand2::Reg(*rn),
5241 })?);
5242 }
5243 bytes.extend_from_slice(
5245 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5247 Ok(bytes)
5248 }
5249
5250 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5252 let mut bytes = Vec::new();
5253 if rdlo != rn {
5254 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5256 rd: *rdlo,
5257 op2: Operand2::Reg(*rn),
5258 })?);
5259 }
5260 let rdhi_bits = reg_to_bits(rdhi) as u16;
5262 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5263 bytes.extend_from_slice(&instr.to_le_bytes());
5264 Ok(bytes)
5265 }
5266
5267 ArmOp::I32WrapI64 { rd, rnlo } => {
5269 if rd == rnlo {
5270 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5273 } else {
5274 self.encode_thumb(&ArmOp::Mov {
5276 rd: *rd,
5277 op2: Operand2::Reg(*rnlo),
5278 })
5279 }
5280 }
5281
5282 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5284 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5285 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5286 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5287 0xEF000150, qd, qn, qm,
5288 ))),
5289 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5290 0xEF200150, qd, qn, qm,
5291 ))),
5292 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5293 0xFF000150, qd, qn, qm,
5294 ))),
5295 ArmOp::MveMvn { qd, qm } => {
5296 let qd_enc = qreg_to_num(qd);
5298 let qm_enc = qreg_to_num(qm);
5299 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5300 Ok(vfp_to_thumb_bytes(instr))
5301 }
5302 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5303 0xEF100150, qd, qn, qm,
5304 ))),
5305 ArmOp::MveAddI { qd, qn, qm, size } => {
5306 let sz = mve_size_bits(size);
5307 let base: u32 = 0xEF000840 | (sz << 20);
5308 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5309 }
5310 ArmOp::MveSubI { qd, qn, qm, size } => {
5311 let sz = mve_size_bits(size);
5312 let base: u32 = 0xFF000840 | (sz << 20);
5313 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5314 }
5315 ArmOp::MveMulI { qd, qn, qm, size } => {
5316 let sz = mve_size_bits(size);
5317 let base: u32 = 0xEF000950 | (sz << 20);
5318 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5319 }
5320 ArmOp::MveNegI { qd, qm, size } => {
5321 let sz = mve_size_bits(size);
5322 let qd_enc = qreg_to_num(qd);
5324 let qm_enc = qreg_to_num(qm);
5325 let base: u32 = 0xFFB103C0 | (sz << 18);
5326 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5327 Ok(vfp_to_thumb_bytes(instr))
5328 }
5329 ArmOp::MveDup { qd, rn, size } => {
5330 let sz = mve_size_bits(size);
5331 let qd_enc = qreg_to_num(qd);
5332 let rn_bits = reg_to_bits(rn);
5333 let be = match sz {
5336 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5340 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5341 Ok(vfp_to_thumb_bytes(instr))
5342 }
5343 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5344 let qn_enc = qreg_to_num(qn);
5345 let rd_bits = reg_to_bits(rd);
5346 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5349 let lane_in_d = (*lane as u32) & 1;
5350 let _sz = mve_size_bits(size);
5351 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5353 Ok(vfp_to_thumb_bytes(instr))
5354 }
5355 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5356 let qd_enc = qreg_to_num(qd);
5357 let rn_bits = reg_to_bits(rn);
5358 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5359 let lane_in_d = (*lane as u32) & 1;
5360 let _sz = mve_size_bits(size);
5361 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5363 Ok(vfp_to_thumb_bytes(instr))
5364 }
5365
5366 ArmOp::MveCmpEqI { qd, qn, qm, size }
5368 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5369 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5370 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5371 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5372 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5373 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5374 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5375 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5376 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5377 let sz = mve_size_bits(size);
5380 let base: u32 = 0xEF000840 | (sz << 20);
5381 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5382 }
5383
5384 ArmOp::MveAddF32 { qd, qn, qm } => {
5386 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5388 }
5389 ArmOp::MveSubF32 { qd, qn, qm } => {
5390 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5392 }
5393 ArmOp::MveMulF32 { qd, qn, qm } => {
5394 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5396 }
5397 ArmOp::MveNegF32 { qd, qm } => {
5398 let qd_enc = qreg_to_num(qd);
5399 let qm_enc = qreg_to_num(qm);
5400 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5402 Ok(vfp_to_thumb_bytes(instr))
5403 }
5404 ArmOp::MveAbsF32 { qd, qm } => {
5405 let qd_enc = qreg_to_num(qd);
5406 let qm_enc = qreg_to_num(qm);
5407 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5409 Ok(vfp_to_thumb_bytes(instr))
5410 }
5411 ArmOp::MveCmpEqF32 { qd, qn, qm }
5412 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5413 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5414 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5415 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5416 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5417 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5419 }
5420 ArmOp::MveDupF32 { qd, rn } => {
5421 let qd_enc = qreg_to_num(qd);
5422 let rn_bits = reg_to_bits(rn);
5423 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5425 Ok(vfp_to_thumb_bytes(instr))
5426 }
5427 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5428 let qn_enc = qreg_to_num(qn);
5429 let rd_bits = reg_to_bits(rd);
5430 let s_num = qn_enc * 4 + (*lane as u32);
5432 let (vn, n) = encode_sreg(s_num);
5433 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5434 Ok(vfp_to_thumb_bytes(instr))
5435 }
5436 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5437 let qd_enc = qreg_to_num(qd);
5438 let rn_bits = reg_to_bits(rn);
5439 let s_num = qd_enc * 4 + (*lane as u32);
5441 let (vn, n) = encode_sreg(s_num);
5442 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5443 Ok(vfp_to_thumb_bytes(instr))
5444 }
5445 ArmOp::MveDivF32 { qd, qn, qm } => {
5446 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5448 }
5449 ArmOp::MveSqrtF32 { qd, qm } => {
5450 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5452 }
5453
5454 _ => {
5456 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5458 }
5459 }
5460 }
5461
5462 fn encode_thumb_f32_compare(
5466 &self,
5467 rd: &Reg,
5468 sn: &VfpReg,
5469 sm: &VfpReg,
5470 cond_code: u32,
5471 ) -> Result<Vec<u8>> {
5472 let mut bytes = Vec::new();
5473 let rd_bits = reg_to_bits(rd);
5474
5475 let sn_num = vfp_sreg_to_num(sn)?;
5477 let sm_num = vfp_sreg_to_num(sm)?;
5478 let (vd, d) = encode_sreg(sn_num);
5479 let (vm, m) = encode_sreg(sm_num);
5480 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5481 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5482
5483 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5485
5486 if rd_bits < 8 {
5488 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5489 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5490 } else {
5491 let hw1: u16 = 0xF04F;
5493 let hw2: u16 = (rd_bits as u16) << 8;
5494 bytes.extend_from_slice(&hw1.to_le_bytes());
5495 bytes.extend_from_slice(&hw2.to_le_bytes());
5496 }
5497
5498 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5502 bytes.extend_from_slice(&it.to_le_bytes());
5503
5504 if rd_bits < 8 {
5506 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5507 bytes.extend_from_slice(&mov_one.to_le_bytes());
5508 } else {
5509 let hw1: u16 = 0xF04F;
5511 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5512 bytes.extend_from_slice(&hw1.to_le_bytes());
5513 bytes.extend_from_slice(&hw2.to_le_bytes());
5514 }
5515
5516 Ok(bytes)
5517 }
5518
5519 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5521 let mut bytes = Vec::new();
5522 let bits = value.to_bits();
5523 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5528 let imm4 = (lo16 >> 12) & 0xF;
5529 let i_bit = (lo16 >> 11) & 1;
5530 let imm3 = (lo16 >> 8) & 0x7;
5531 let imm8 = lo16 & 0xFF;
5532 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5533 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5534 bytes.extend_from_slice(&hw1.to_le_bytes());
5535 bytes.extend_from_slice(&hw2.to_le_bytes());
5536
5537 let hi16 = (bits >> 16) & 0xFFFF;
5539 let imm4 = (hi16 >> 12) & 0xF;
5540 let i_bit = (hi16 >> 11) & 1;
5541 let imm3 = (hi16 >> 8) & 0x7;
5542 let imm8 = hi16 & 0xFF;
5543 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5544 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5545 bytes.extend_from_slice(&hw1.to_le_bytes());
5546 bytes.extend_from_slice(&hw2.to_le_bytes());
5547
5548 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5550 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5551
5552 Ok(bytes)
5553 }
5554
5555 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5557 let mut bytes = Vec::new();
5558
5559 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5561 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5562
5563 let sd_num = vfp_sreg_to_num(sd)?;
5565 let (vd, d) = encode_sreg(sd_num);
5566 let (vm, m) = encode_sreg(sd_num);
5567 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5568 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5569 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5570
5571 Ok(bytes)
5572 }
5573
5574 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5582 let mut bytes = Vec::new();
5583 let sm_num = vfp_sreg_to_num(sm)?;
5584 let sd_num = vfp_sreg_to_num(sd)?;
5585 let (vd_s, d_s) = encode_sreg(sd_num);
5586 let (vm_s, m_s) = encode_sreg(sm_num);
5587
5588 if mode == 0b11 {
5589 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5591 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5592 } else {
5593 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5598 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5599
5600 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5606 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5607 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5608
5609 if mode != 0 {
5611 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5613 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5614 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5615 }
5616
5617 let vmsr = 0xEEE10A10 | (rt << 12);
5619 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5620
5621 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5623 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5624
5625 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5627 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5628 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5629 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5630 }
5631
5632 let (vd2, d2) = encode_sreg(sd_num);
5634 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5635 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5636
5637 Ok(bytes)
5638 }
5639
5640 fn encode_thumb_f32_minmax(
5642 &self,
5643 sd: &VfpReg,
5644 sn: &VfpReg,
5645 sm: &VfpReg,
5646 is_min: bool,
5647 ) -> Result<Vec<u8>> {
5648 let mut bytes = Vec::new();
5649 let sn_num = vfp_sreg_to_num(sn)?;
5650 let sm_num = vfp_sreg_to_num(sm)?;
5651 let sd_num = vfp_sreg_to_num(sd)?;
5652
5653 let (vd, d) = encode_sreg(sd_num);
5655 let (vn, n) = encode_sreg(sn_num);
5656 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5657 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5658
5659 let (vm, m) = encode_sreg(sm_num);
5661 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5662 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5663
5664 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5666
5667 let cond: u16 = if is_min { 0xC } else { 0x4 };
5669 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5670 bytes.extend_from_slice(&it.to_le_bytes());
5671
5672 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5674 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5675
5676 Ok(bytes)
5677 }
5678
5679 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5681 let mut bytes = Vec::new();
5682
5683 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5685 false,
5686 sm,
5687 &Reg::R12,
5688 )?));
5689
5690 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5692 false,
5693 sn,
5694 &Reg::R0,
5695 )?));
5696
5697 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5709 bytes.extend_from_slice(&hw2.to_le_bytes());
5710
5711 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5715 bytes.extend_from_slice(&hw2.to_le_bytes());
5716
5717 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5721 bytes.extend_from_slice(&hw2.to_le_bytes());
5722
5723 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5725 true,
5726 sd,
5727 &Reg::R0,
5728 )?));
5729
5730 Ok(bytes)
5731 }
5732
5733 fn encode_thumb_f64_compare(
5735 &self,
5736 rd: &Reg,
5737 dn: &VfpReg,
5738 dm: &VfpReg,
5739 cond_code: u32,
5740 ) -> Result<Vec<u8>> {
5741 let mut bytes = Vec::new();
5742 let rd_bits = reg_to_bits(rd);
5743
5744 let dn_num = vfp_dreg_to_num(dn)?;
5746 let dm_num = vfp_dreg_to_num(dm)?;
5747 let (vd, d) = encode_dreg(dn_num);
5748 let (vm, m) = encode_dreg(dm_num);
5749 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5750 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5751
5752 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5754
5755 if rd_bits < 8 {
5757 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5758 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5759 } else {
5760 let hw1: u16 = 0xF04F;
5761 let hw2: u16 = (rd_bits as u16) << 8;
5762 bytes.extend_from_slice(&hw1.to_le_bytes());
5763 bytes.extend_from_slice(&hw2.to_le_bytes());
5764 }
5765
5766 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5768 bytes.extend_from_slice(&it.to_le_bytes());
5769
5770 if rd_bits < 8 {
5772 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5773 bytes.extend_from_slice(&mov_one.to_le_bytes());
5774 } else {
5775 let hw1: u16 = 0xF04F;
5776 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5777 bytes.extend_from_slice(&hw1.to_le_bytes());
5778 bytes.extend_from_slice(&hw2.to_le_bytes());
5779 }
5780
5781 Ok(bytes)
5782 }
5783
5784 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5786 let mut bytes = Vec::new();
5787 let bits = value.to_bits();
5788 let lo32 = bits as u32;
5789 let hi32 = (bits >> 32) as u32;
5790
5791 let lo16 = lo32 & 0xFFFF;
5793 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5794
5795 let hi16 = (lo32 >> 16) & 0xFFFF;
5797 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5798
5799 let lo16 = hi32 & 0xFFFF;
5801 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5802
5803 let hi16 = (hi32 >> 16) & 0xFFFF;
5805 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5806
5807 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5809 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5810
5811 Ok(bytes)
5812 }
5813
5814 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5816 let mut bytes = Vec::new();
5817
5818 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5820 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5821
5822 let dd_num = vfp_dreg_to_num(dd)?;
5824 let (vd, d) = encode_dreg(dd_num);
5825 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5826 let vcvt = base | (d << 22) | (vd << 12);
5827 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5828
5829 Ok(bytes)
5830 }
5831
5832 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5834 let dd_num = vfp_dreg_to_num(dd)?;
5835 let sm_num = vfp_sreg_to_num(sm)?;
5836 let (vd, d) = encode_dreg(dd_num);
5837 let (vm, m) = encode_sreg(sm_num);
5838
5839 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5840 Ok(vfp_to_thumb_bytes(vcvt))
5841 }
5842
5843 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5845 let mut bytes = Vec::new();
5846 let dm_num = vfp_dreg_to_num(dm)?;
5847 let (vm, m) = encode_dreg(dm_num);
5848
5849 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5851 let vcvt = base | (m << 5) | vm;
5852 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5853
5854 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5856 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5857
5858 Ok(bytes)
5859 }
5860
5861 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5865 let mut bytes = Vec::new();
5866 let dm_num = vfp_dreg_to_num(dm)?;
5867 let dd_num = vfp_dreg_to_num(dd)?;
5868 let (vm, m) = encode_dreg(dm_num);
5869 let (vd, d) = encode_dreg(dd_num);
5870
5871 if mode == 0b11 {
5872 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5874 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5875 } else {
5876 let rt: u32 = 12;
5877
5878 let vmrs = 0xEEF10A10 | (rt << 12);
5880 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5881
5882 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5884 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5885 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5886 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5887
5888 if mode != 0 {
5890 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5891 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5892 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5893 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5894 }
5895
5896 let vmsr = 0xEEE10A10 | (rt << 12);
5898 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5899
5900 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5902 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5903
5904 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5906 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5907 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5908 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5909 }
5910
5911 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5913 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5914
5915 Ok(bytes)
5916 }
5917
5918 fn encode_thumb_f64_minmax(
5920 &self,
5921 dd: &VfpReg,
5922 dn: &VfpReg,
5923 dm: &VfpReg,
5924 is_min: bool,
5925 ) -> Result<Vec<u8>> {
5926 let mut bytes = Vec::new();
5927 let dn_num = vfp_dreg_to_num(dn)?;
5928 let dm_num = vfp_dreg_to_num(dm)?;
5929 let dd_num = vfp_dreg_to_num(dd)?;
5930
5931 let (vd, d) = encode_dreg(dd_num);
5933 let (vn, n) = encode_dreg(dn_num);
5934 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5935 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5936
5937 let (vm, m) = encode_dreg(dm_num);
5939 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5940 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5941
5942 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5944
5945 let cond: u16 = if is_min { 0xC } else { 0x4 };
5947 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5948 bytes.extend_from_slice(&it.to_le_bytes());
5949
5950 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5952 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5953
5954 Ok(bytes)
5955 }
5956
5957 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5959 let mut bytes = Vec::new();
5960
5961 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5963 false,
5964 dm,
5965 &Reg::R0,
5966 &Reg::R12,
5967 )?));
5968
5969 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5971 false,
5972 dn,
5973 &Reg::R1,
5974 &Reg::R2,
5975 )?));
5976
5977 let hw1: u16 = 0xF000 | 12;
5979 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5980 bytes.extend_from_slice(&hw1.to_le_bytes());
5981 bytes.extend_from_slice(&hw2.to_le_bytes());
5982
5983 let hw1: u16 = 0xF020 | 2;
5985 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5986 bytes.extend_from_slice(&hw1.to_le_bytes());
5987 bytes.extend_from_slice(&hw2.to_le_bytes());
5988
5989 let hw1: u16 = 0xEA40 | 2;
5991 let hw2: u16 = (2 << 8) | 12;
5992 bytes.extend_from_slice(&hw1.to_le_bytes());
5993 bytes.extend_from_slice(&hw2.to_le_bytes());
5994
5995 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5997 true,
5998 dd,
5999 &Reg::R1,
6000 &Reg::R2,
6001 )?));
6002
6003 Ok(bytes)
6004 }
6005
6006 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6008 let mut bytes = Vec::new();
6009
6010 let sm_num = vfp_sreg_to_num(sm)?;
6011 let (vd, d) = encode_sreg(sm_num);
6012 let (vm, m) = encode_sreg(sm_num);
6013 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6014 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6015 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6016
6017 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6019 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6020
6021 Ok(bytes)
6022 }
6023
6024 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6028 let rd_bits = reg_to_bits(rd);
6029 let rn_bits = reg_to_bits(rn);
6030
6031 let i_bit = (imm >> 11) & 1;
6033 let imm3 = (imm >> 8) & 0x7;
6034 let imm8 = imm & 0xFF;
6035
6036 let hw1_base = if imm <= 0xFF {
6037 0xF100
6041 } else if imm <= 0xFFF {
6042 0xF200
6046 } else {
6047 return Err(synth_core::Error::synthesis(
6048 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6049 ));
6050 };
6051
6052 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6053 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6054
6055 let mut bytes = hw1.to_le_bytes().to_vec();
6056 bytes.extend_from_slice(&hw2.to_le_bytes());
6057 Ok(bytes)
6058 }
6059
6060 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6062 let rd_bits = reg_to_bits(rd);
6063 let rn_bits = reg_to_bits(rn);
6064
6065 let i_bit = (imm >> 11) & 1;
6066 let imm3 = (imm >> 8) & 0x7;
6067 let imm8 = imm & 0xFF;
6068
6069 let hw1_base = if imm <= 0xFF {
6070 0xF1A0
6073 } else if imm <= 0xFFF {
6074 0xF2A0
6077 } else {
6078 return Err(synth_core::Error::synthesis(
6079 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6080 ));
6081 };
6082
6083 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6084 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6085
6086 let mut bytes = hw1.to_le_bytes().to_vec();
6087 bytes.extend_from_slice(&hw2.to_le_bytes());
6088 Ok(bytes)
6089 }
6090
6091 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6093 let rd_bits = reg_to_bits(rd);
6094 let rn_bits = reg_to_bits(rn);
6095
6096 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6099 synth_core::Error::synthesis(
6100 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6101 )
6102 })?;
6103 let i_bit = (field >> 11) & 1;
6104 let imm3 = (field >> 8) & 0x7;
6105 let imm8 = field & 0xFF;
6106
6107 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6110 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6111
6112 let mut bytes = hw1.to_le_bytes().to_vec();
6113 bytes.extend_from_slice(&hw2.to_le_bytes());
6114 Ok(bytes)
6115 }
6116
6117 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6119 let rd_bits = reg_to_bits(rd);
6120 let rn_bits = reg_to_bits(rn);
6121
6122 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6125 synth_core::Error::synthesis(
6126 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6127 )
6128 })?;
6129 let i_bit = (field >> 11) & 1;
6130 let imm3 = (field >> 8) & 0x7;
6131 let imm8 = field & 0xFF;
6132
6133 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6136 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6137
6138 let mut bytes = hw1.to_le_bytes().to_vec();
6139 bytes.extend_from_slice(&hw2.to_le_bytes());
6140 Ok(bytes)
6141 }
6142
6143 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6152 let rd_bits = reg_to_bits(rd);
6153 reg_bits_checked(rd_bits)?;
6154 let imm16 = imm & 0xFFFF;
6155
6156 let imm4 = (imm16 >> 12) & 0xF;
6159 let i_bit = (imm16 >> 11) & 1;
6160 let imm3 = (imm16 >> 8) & 0x7;
6161 let imm8 = imm16 & 0xFF;
6162
6163 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6164 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6165
6166 let mut bytes = hw1.to_le_bytes().to_vec();
6167 bytes.extend_from_slice(&hw2.to_le_bytes());
6168 encoding_contracts::verify_thumb32(&bytes);
6169 Ok(bytes)
6170 }
6171
6172 fn encode_thumb32_shift(
6180 &self,
6181 rd: &Reg,
6182 rm: &Reg,
6183 shift: u32,
6184 shift_type: u8,
6185 ) -> Result<Vec<u8>> {
6186 let rd_bits = reg_to_bits(rd);
6187 let rm_bits = reg_to_bits(rm);
6188 reg_bits_checked(rd_bits)?;
6189 reg_bits_checked(rm_bits)?;
6190 let imm5 = shift & 0x1F;
6191 let imm2 = imm5 & 0x3;
6192 let imm3 = (imm5 >> 2) & 0x7;
6193
6194 let hw1: u16 = 0xEA4F;
6197 let hw2: u16 =
6198 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6199 as u16;
6200
6201 let mut bytes = hw1.to_le_bytes().to_vec();
6202 bytes.extend_from_slice(&hw2.to_le_bytes());
6203 Ok(bytes)
6204 }
6205
6206 fn encode_thumb32_shift_reg(
6210 &self,
6211 rd: &Reg,
6212 rn: &Reg,
6213 rm: &Reg,
6214 shift_type: u8,
6215 ) -> Result<Vec<u8>> {
6216 let rd_bits = reg_to_bits(rd);
6217 let rn_bits = reg_to_bits(rn);
6218 let rm_bits = reg_to_bits(rm);
6219
6220 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6222 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6224
6225 let mut bytes = hw1.to_le_bytes().to_vec();
6226 bytes.extend_from_slice(&hw2.to_le_bytes());
6227 Ok(bytes)
6228 }
6229
6230 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6232 let rn_bits = reg_to_bits(rn);
6233
6234 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6238 synth_core::Error::synthesis(
6239 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6240 )
6241 })?;
6242 let i_bit = (field >> 11) & 1;
6243 let imm3 = (field >> 8) & 0x7;
6244 let imm8 = field & 0xFF;
6245
6246 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6248 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6249
6250 let mut bytes = hw1.to_le_bytes().to_vec();
6251 bytes.extend_from_slice(&hw2.to_le_bytes());
6252 Ok(bytes)
6253 }
6254
6255 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6257 let rd_bits = reg_to_bits(rd);
6258 let base_bits = reg_to_bits(base);
6259
6260 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6262 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6263
6264 let mut bytes = hw1.to_le_bytes().to_vec();
6265 bytes.extend_from_slice(&hw2.to_le_bytes());
6266 Ok(bytes)
6267 }
6268
6269 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6271 let rd_bits = reg_to_bits(rd);
6272 let base_bits = reg_to_bits(base);
6273
6274 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6276 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6277
6278 let mut bytes = hw1.to_le_bytes().to_vec();
6279 bytes.extend_from_slice(&hw2.to_le_bytes());
6280 Ok(bytes)
6281 }
6282
6283 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6285 let rd_bits = reg_to_bits(rd);
6286 let base_bits = reg_to_bits(base);
6287 let rm_bits = reg_to_bits(offset_reg);
6288
6289 let hw1: u16 = (0xF850 | base_bits) as u16;
6293 let hw2: u16 = ((rd_bits << 12) | rm_bits) 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_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6302 let rd_bits = reg_to_bits(rd);
6303 let base_bits = reg_to_bits(base);
6304 let rm_bits = reg_to_bits(offset_reg);
6305
6306 let hw1: u16 = (0xF840 | base_bits) as u16;
6310 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6311
6312 let mut bytes = hw1.to_le_bytes().to_vec();
6313 bytes.extend_from_slice(&hw2.to_le_bytes());
6314 Ok(bytes)
6315 }
6316
6317 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6321 let rd_bits = reg_to_bits(rd);
6322 let base_bits = reg_to_bits(base);
6323 let hw1: u16 = (0xF890 | base_bits) as u16;
6325 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6326 let mut bytes = hw1.to_le_bytes().to_vec();
6327 bytes.extend_from_slice(&hw2.to_le_bytes());
6328 Ok(bytes)
6329 }
6330
6331 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6333 let rd_bits = reg_to_bits(rd);
6334 let base_bits = reg_to_bits(base);
6335 let rm_bits = reg_to_bits(offset_reg);
6336 let hw1: u16 = (0xF810 | base_bits) as u16;
6338 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6339 let mut bytes = hw1.to_le_bytes().to_vec();
6340 bytes.extend_from_slice(&hw2.to_le_bytes());
6341 Ok(bytes)
6342 }
6343
6344 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6346 let rd_bits = reg_to_bits(rd);
6347 let base_bits = reg_to_bits(base);
6348 let hw1: u16 = (0xF990 | base_bits) as u16;
6350 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6351 let mut bytes = hw1.to_le_bytes().to_vec();
6352 bytes.extend_from_slice(&hw2.to_le_bytes());
6353 Ok(bytes)
6354 }
6355
6356 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6358 let rd_bits = reg_to_bits(rd);
6359 let base_bits = reg_to_bits(base);
6360 let rm_bits = reg_to_bits(offset_reg);
6361 let hw1: u16 = (0xF910 | base_bits) as u16;
6363 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6364 let mut bytes = hw1.to_le_bytes().to_vec();
6365 bytes.extend_from_slice(&hw2.to_le_bytes());
6366 Ok(bytes)
6367 }
6368
6369 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6371 let rd_bits = reg_to_bits(rd);
6372 let base_bits = reg_to_bits(base);
6373 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6375 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6376 let mut bytes = hw1.to_le_bytes().to_vec();
6377 bytes.extend_from_slice(&hw2.to_le_bytes());
6378 Ok(bytes)
6379 }
6380
6381 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6383 let rd_bits = reg_to_bits(rd);
6384 let base_bits = reg_to_bits(base);
6385 let rm_bits = reg_to_bits(offset_reg);
6386 let hw1: u16 = (0xF830 | base_bits) as u16;
6388 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6389 let mut bytes = hw1.to_le_bytes().to_vec();
6390 bytes.extend_from_slice(&hw2.to_le_bytes());
6391 Ok(bytes)
6392 }
6393
6394 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6396 let rd_bits = reg_to_bits(rd);
6397 let base_bits = reg_to_bits(base);
6398 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6400 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6401 let mut bytes = hw1.to_le_bytes().to_vec();
6402 bytes.extend_from_slice(&hw2.to_le_bytes());
6403 Ok(bytes)
6404 }
6405
6406 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6408 let rd_bits = reg_to_bits(rd);
6409 let base_bits = reg_to_bits(base);
6410 let rm_bits = reg_to_bits(offset_reg);
6411 let hw1: u16 = (0xF930 | base_bits) as u16;
6413 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6414 let mut bytes = hw1.to_le_bytes().to_vec();
6415 bytes.extend_from_slice(&hw2.to_le_bytes());
6416 Ok(bytes)
6417 }
6418
6419 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6421 let rd_bits = reg_to_bits(rd);
6422 let base_bits = reg_to_bits(base);
6423 let hw1: u16 = (0xF880 | base_bits) as u16;
6425 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6426 let mut bytes = hw1.to_le_bytes().to_vec();
6427 bytes.extend_from_slice(&hw2.to_le_bytes());
6428 Ok(bytes)
6429 }
6430
6431 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6433 let rd_bits = reg_to_bits(rd);
6434 let base_bits = reg_to_bits(base);
6435 let rm_bits = reg_to_bits(offset_reg);
6436 let hw1: u16 = (0xF800 | base_bits) as u16;
6438 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6439 let mut bytes = hw1.to_le_bytes().to_vec();
6440 bytes.extend_from_slice(&hw2.to_le_bytes());
6441 Ok(bytes)
6442 }
6443
6444 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6446 let rd_bits = reg_to_bits(rd);
6447 let base_bits = reg_to_bits(base);
6448 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6450 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6451 let mut bytes = hw1.to_le_bytes().to_vec();
6452 bytes.extend_from_slice(&hw2.to_le_bytes());
6453 Ok(bytes)
6454 }
6455
6456 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6458 let rd_bits = reg_to_bits(rd);
6459 let base_bits = reg_to_bits(base);
6460 let rm_bits = reg_to_bits(offset_reg);
6461 let hw1: u16 = (0xF820 | base_bits) as u16;
6463 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6464 let mut bytes = hw1.to_le_bytes().to_vec();
6465 bytes.extend_from_slice(&hw2.to_le_bytes());
6466 Ok(bytes)
6467 }
6468
6469 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6471 let rd_bits = reg_to_bits(rd);
6472 let rn_bits = reg_to_bits(rn);
6473
6474 if imm <= 0xFFF {
6480 let i_bit = (imm >> 11) & 1;
6481 let imm3 = (imm >> 8) & 0x7;
6482 let imm8 = imm & 0xFF;
6483
6484 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6485 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6486
6487 let mut bytes = hw1.to_le_bytes().to_vec();
6488 bytes.extend_from_slice(&hw2.to_le_bytes());
6489 Ok(bytes)
6490 } else {
6491 Err(synth_core::Error::synthesis(
6494 "ADD immediate too large for single instruction",
6495 ))
6496 }
6497 }
6498
6499 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6509 reg_bits_checked(rd)?;
6510 encoding_contracts::verify_imm16(imm16);
6511 let imm16 = imm16 & 0xFFFF;
6514 let imm4 = (imm16 >> 12) & 0xF;
6515 let i_bit = (imm16 >> 11) & 1;
6516 let imm3 = (imm16 >> 8) & 0x7;
6517 let imm8 = imm16 & 0xFF;
6518
6519 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6520 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6521
6522 let mut bytes = hw1.to_le_bytes().to_vec();
6523 bytes.extend_from_slice(&hw2.to_le_bytes());
6524 encoding_contracts::verify_thumb32(&bytes);
6525 Ok(bytes)
6526 }
6527
6528 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6536 reg_bits_checked(rd)?;
6537 encoding_contracts::verify_imm16(imm16);
6538 let imm16 = imm16 & 0xFFFF;
6541 let imm4 = (imm16 >> 12) & 0xF;
6542 let i_bit = (imm16 >> 11) & 1;
6543 let imm3 = (imm16 >> 8) & 0x7;
6544 let imm8 = imm16 & 0xFF;
6545
6546 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6547 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6548
6549 let mut bytes = hw1.to_le_bytes().to_vec();
6550 bytes.extend_from_slice(&hw2.to_le_bytes());
6551 encoding_contracts::verify_thumb32(&bytes);
6552 Ok(bytes)
6553 }
6554
6555 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6557 let imm5 = shift & 0x1F;
6560 let imm2 = imm5 & 0x3;
6561 let imm3 = (imm5 >> 2) & 0x7;
6562
6563 let hw1: u16 = 0xEA4F;
6564 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6565
6566 let mut bytes = hw1.to_le_bytes().to_vec();
6567 bytes.extend_from_slice(&hw2.to_le_bytes());
6568 Ok(bytes)
6569 }
6570
6571 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6573 let hw1: u16 = (0xEA00 | rn) as u16;
6576 let hw2: u16 = ((rd << 8) | rm) as u16;
6577
6578 let mut bytes = hw1.to_le_bytes().to_vec();
6579 bytes.extend_from_slice(&hw2.to_le_bytes());
6580 Ok(bytes)
6581 }
6582
6583 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6585 let i_bit = (imm >> 11) & 1;
6589 let imm3 = (imm >> 8) & 0x7;
6590 let imm8 = imm & 0xFF;
6591
6592 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6593 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6594
6595 let mut bytes = hw1.to_le_bytes().to_vec();
6596 bytes.extend_from_slice(&hw2.to_le_bytes());
6597 Ok(bytes)
6598 }
6599
6600 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6602 let hw1: u16 = (0xEBA0 | rn) as u16;
6605 let hw2: u16 = ((rd << 8) | rm) as u16;
6606
6607 let mut bytes = hw1.to_le_bytes().to_vec();
6608 bytes.extend_from_slice(&hw2.to_le_bytes());
6609 Ok(bytes)
6610 }
6611
6612 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6614 let hw1: u16 = (0xEB00 | rn) as u16;
6617 let hw2: u16 = ((rd << 8) | rm) as u16;
6618
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_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6628 let hw1: u16 = (0xEB10 | rn) as u16;
6630 let hw2: u16 = ((rd << 8) | rm) as u16;
6631 let mut bytes = hw1.to_le_bytes().to_vec();
6632 bytes.extend_from_slice(&hw2.to_le_bytes());
6633 Ok(bytes)
6634 }
6635
6636 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6639 let hw1: u16 = (0xEBB0 | rn) as u16;
6641 let hw2: u16 = ((rd << 8) | rm) as u16;
6642 let mut bytes = hw1.to_le_bytes().to_vec();
6643 bytes.extend_from_slice(&hw2.to_le_bytes());
6644 Ok(bytes)
6645 }
6646
6647 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6649 let mut code = Vec::new();
6650
6651 for op in ops {
6652 let encoded = self.encode(op)?;
6653 code.extend_from_slice(&encoded);
6654 }
6655
6656 Ok(code)
6657 }
6658}
6659
6660fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6668 if value <= 0xFF {
6670 return Some(value);
6671 }
6672 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6676 return Some(0x100 | b0);
6677 }
6678 if value == (b1 << 24) | (b1 << 8) {
6680 return Some(0x200 | b1);
6681 }
6682 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6684 return Some(0x300 | b0);
6685 }
6686 for rot in 8..=31u32 {
6690 let unrot = value.rotate_left(rot);
6691 if (0x80..=0xFF).contains(&unrot) {
6692 return Some((rot << 7) | (unrot & 0x7F));
6693 }
6694 }
6695 None
6696}
6697
6698fn reg_to_bits(reg: &Reg) -> u32 {
6699 match reg {
6700 Reg::R0 => 0,
6701 Reg::R1 => 1,
6702 Reg::R2 => 2,
6703 Reg::R3 => 3,
6704 Reg::R4 => 4,
6705 Reg::R5 => 5,
6706 Reg::R6 => 6,
6707 Reg::R7 => 7,
6708 Reg::R8 => 8,
6709 Reg::R9 => 9,
6710 Reg::R10 => 10,
6711 Reg::R11 => 11,
6712 Reg::R12 => 12,
6713 Reg::SP => 13,
6714 Reg::LR => 14,
6715 Reg::PC => 15,
6716 }
6717}
6718
6719fn reg_bits_checked(bits: u32) -> Result<()> {
6727 if bits > 14 {
6728 return Err(synth_core::Error::synthesis(format!(
6729 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6730 )));
6731 }
6732 Ok(())
6733}
6734
6735fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6738 if val == 0 {
6739 return Some((0, 1));
6740 }
6741 for rot in 0..16u32 {
6742 let shift = rot * 2;
6743 let unrotated = val.rotate_left(shift);
6745 if unrotated <= 0xFF {
6746 return Some(((rot << 8) | unrotated, 1));
6748 }
6749 }
6750 None
6751}
6752
6753fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6758 match op2 {
6759 Operand2::Imm(val) => {
6760 let uval = *val as u32;
6761 if let Some(encoded) = try_encode_rotated_imm(uval) {
6763 encoded
6764 } else {
6765 let imm = uval & 0xFF;
6770 (imm, 1)
6771 }
6772 }
6773
6774 Operand2::Reg(reg) => {
6775 let reg_bits = reg_to_bits(reg);
6776 (reg_bits, 0) }
6778
6779 Operand2::RegShift {
6780 rm,
6781 shift: _,
6782 amount,
6783 } => {
6784 let rm_bits = reg_to_bits(rm);
6786 let shift_bits = (*amount & 0x1F) << 7;
6787 (shift_bits | rm_bits, 0)
6788 }
6789 }
6790}
6791
6792fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6794 let base_bits = reg_to_bits(&addr.base);
6795 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6797}
6798
6799fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6801 match reg {
6802 VfpReg::S0 => Ok(0),
6803 VfpReg::S1 => Ok(1),
6804 VfpReg::S2 => Ok(2),
6805 VfpReg::S3 => Ok(3),
6806 VfpReg::S4 => Ok(4),
6807 VfpReg::S5 => Ok(5),
6808 VfpReg::S6 => Ok(6),
6809 VfpReg::S7 => Ok(7),
6810 VfpReg::S8 => Ok(8),
6811 VfpReg::S9 => Ok(9),
6812 VfpReg::S10 => Ok(10),
6813 VfpReg::S11 => Ok(11),
6814 VfpReg::S12 => Ok(12),
6815 VfpReg::S13 => Ok(13),
6816 VfpReg::S14 => Ok(14),
6817 VfpReg::S15 => Ok(15),
6818 VfpReg::S16 => Ok(16),
6819 VfpReg::S17 => Ok(17),
6820 VfpReg::S18 => Ok(18),
6821 VfpReg::S19 => Ok(19),
6822 VfpReg::S20 => Ok(20),
6823 VfpReg::S21 => Ok(21),
6824 VfpReg::S22 => Ok(22),
6825 VfpReg::S23 => Ok(23),
6826 VfpReg::S24 => Ok(24),
6827 VfpReg::S25 => Ok(25),
6828 VfpReg::S26 => Ok(26),
6829 VfpReg::S27 => Ok(27),
6830 VfpReg::S28 => Ok(28),
6831 VfpReg::S29 => Ok(29),
6832 VfpReg::S30 => Ok(30),
6833 VfpReg::S31 => Ok(31),
6834 _ => Err(synth_core::Error::SynthesisError(
6836 "D-register not supported in single-precision VFP encoding".to_string(),
6837 )),
6838 }
6839}
6840
6841fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6843 match reg {
6844 VfpReg::D0 => Ok(0),
6845 VfpReg::D1 => Ok(1),
6846 VfpReg::D2 => Ok(2),
6847 VfpReg::D3 => Ok(3),
6848 VfpReg::D4 => Ok(4),
6849 VfpReg::D5 => Ok(5),
6850 VfpReg::D6 => Ok(6),
6851 VfpReg::D7 => Ok(7),
6852 VfpReg::D8 => Ok(8),
6853 VfpReg::D9 => Ok(9),
6854 VfpReg::D10 => Ok(10),
6855 VfpReg::D11 => Ok(11),
6856 VfpReg::D12 => Ok(12),
6857 VfpReg::D13 => Ok(13),
6858 VfpReg::D14 => Ok(14),
6859 VfpReg::D15 => Ok(15),
6860 _ => Err(synth_core::Error::SynthesisError(
6862 "S-register not supported in double-precision VFP encoding".to_string(),
6863 )),
6864 }
6865}
6866
6867fn encode_sreg(s: u32) -> (u32, u32) {
6871 (s >> 1, s & 1)
6872}
6873
6874fn encode_dreg(d: u32) -> (u32, u32) {
6878 (d & 0xF, (d >> 4) & 1)
6879}
6880
6881fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6887 let sd_num = vfp_sreg_to_num(sd)?;
6888 let sn_num = vfp_sreg_to_num(sn)?;
6889 let sm_num = vfp_sreg_to_num(sm)?;
6890 let (vd, d) = encode_sreg(sd_num);
6891 let (vn, n) = encode_sreg(sn_num);
6892 let (vm, m) = encode_sreg(sm_num);
6893
6894 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6895}
6896
6897fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6900 let sd_num = vfp_sreg_to_num(sd)?;
6901 let sm_num = vfp_sreg_to_num(sm)?;
6902 let (vd, d) = encode_sreg(sd_num);
6903 let (vm, m) = encode_sreg(sm_num);
6904
6905 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6906}
6907
6908fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6912 let sd_num = vfp_sreg_to_num(sd)?;
6913 let (vd, d) = encode_sreg(sd_num);
6914 let rn = reg_to_bits(&addr.base);
6915
6916 let offset = addr.offset;
6917 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6918 let abs_offset = offset.unsigned_abs();
6919 let imm8 = (abs_offset / 4) & 0xFF;
6920
6921 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6922}
6923
6924fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6928 let s_num = vfp_sreg_to_num(sreg)?;
6929 let (vn, n) = encode_sreg(s_num);
6930 let rt = reg_to_bits(core);
6931
6932 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6933 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6934}
6935
6936fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6940 let dd_num = vfp_dreg_to_num(dd)?;
6941 let dn_num = vfp_dreg_to_num(dn)?;
6942 let dm_num = vfp_dreg_to_num(dm)?;
6943 let (vd, d) = encode_dreg(dd_num);
6944 let (vn, n) = encode_dreg(dn_num);
6945 let (vm, m) = encode_dreg(dm_num);
6946
6947 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6948}
6949
6950fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6952 let dd_num = vfp_dreg_to_num(dd)?;
6953 let dm_num = vfp_dreg_to_num(dm)?;
6954 let (vd, d) = encode_dreg(dd_num);
6955 let (vm, m) = encode_dreg(dm_num);
6956
6957 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6958}
6959
6960fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6963 let dd_num = vfp_dreg_to_num(dd)?;
6964 let (vd, d) = encode_dreg(dd_num);
6965 let rn = reg_to_bits(&addr.base);
6966
6967 let offset = addr.offset;
6968 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6969 let abs_offset = offset.unsigned_abs();
6970 let imm8 = (abs_offset / 4) & 0xFF;
6971
6972 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6973}
6974
6975fn encode_vmov_core_dreg(
6979 to_dreg: bool,
6980 dreg: &VfpReg,
6981 core_lo: &Reg,
6982 core_hi: &Reg,
6983) -> Result<u32> {
6984 let d_num = vfp_dreg_to_num(dreg)?;
6985 let (vm, m) = encode_dreg(d_num);
6986 let rt = reg_to_bits(core_lo);
6987 let rt2 = reg_to_bits(core_hi);
6988
6989 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6990 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6991}
6992
6993fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6995 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6996 let hw2 = (instr & 0xFFFF) as u16;
6997 let mut bytes = hw1.to_le_bytes().to_vec();
6998 bytes.extend_from_slice(&hw2.to_le_bytes());
6999 bytes
7000}
7001
7002fn qreg_to_num(reg: &QReg) -> u32 {
7008 match reg {
7009 QReg::Q0 => 0,
7010 QReg::Q1 => 1,
7011 QReg::Q2 => 2,
7012 QReg::Q3 => 3,
7013 QReg::Q4 => 4,
7014 QReg::Q5 => 5,
7015 QReg::Q6 => 6,
7016 QReg::Q7 => 7,
7017 }
7018}
7019
7020fn mve_size_bits(size: &MveSize) -> u32 {
7022 match size {
7023 MveSize::S8 => 0b00,
7024 MveSize::S16 => 0b01,
7025 MveSize::S32 => 0b10,
7026 }
7027}
7028
7029fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7033 let d = qreg_to_num(qd) * 2;
7034 let n = qreg_to_num(qn) * 2;
7035 let m = qreg_to_num(qm) * 2;
7036
7037 let vd = d & 0xF;
7042 let d_bit = (d >> 4) & 1;
7043 let vn = n & 0xF;
7044 let n_bit = (n >> 4) & 1;
7045 let vm = m & 0xF;
7046 let m_bit = (m >> 4) & 1;
7047
7048 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7049}
7050
7051fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7053 encode_mve_3reg(base, qd, qn, qm)
7054}
7055
7056fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7059 let qd_enc = qreg_to_num(qd) * 2;
7060 let rn = reg_to_bits(&addr.base);
7061 let offset = addr.offset;
7062 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7063 let abs_offset = offset.unsigned_abs();
7064 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7068 | (u_bit << 23)
7069 | ((qd_enc >> 4) << 22)
7070 | (rn << 16)
7071 | ((qd_enc & 0xF) << 12)
7072 | (imm7 & 0x7F)
7073}
7074
7075fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7077 let qd_enc = qreg_to_num(qd) * 2;
7078 let rn = reg_to_bits(&addr.base);
7079 let offset = addr.offset;
7080 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7081 let abs_offset = offset.unsigned_abs();
7082 let imm7 = (abs_offset / 4) & 0x7F;
7083
7084 0xED000E80
7085 | (u_bit << 23)
7086 | ((qd_enc >> 4) << 22)
7087 | (rn << 16)
7088 | ((qd_enc & 0xF) << 12)
7089 | (imm7 & 0x7F)
7090}
7091
7092impl ArmEncoder {
7093 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7095 let mut result = Vec::new();
7096 let qd_num = qreg_to_num(qd);
7097
7098 for i in 0..4 {
7100 let word = u32::from_le_bytes([
7101 bytes[i * 4],
7102 bytes[i * 4 + 1],
7103 bytes[i * 4 + 2],
7104 bytes[i * 4 + 3],
7105 ]);
7106 let lo16 = word & 0xFFFF;
7107 let hi16 = (word >> 16) & 0xFFFF;
7108
7109 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7111 if hi16 != 0 {
7113 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7114 }
7115
7116 let s_num = qd_num * 4 + i as u32;
7118 let (vn, n) = encode_sreg(s_num);
7119 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7120 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7121 }
7122
7123 Ok(result)
7124 }
7125
7126 fn encode_thumb_mve_lane_wise_f32_binop(
7128 &self,
7129 qd: &QReg,
7130 qn: &QReg,
7131 qm: &QReg,
7132 vfp_base: u32,
7133 ) -> Result<Vec<u8>> {
7134 let mut result = Vec::new();
7135 let qd_num = qreg_to_num(qd);
7136 let qn_num = qreg_to_num(qn);
7137 let qm_num = qreg_to_num(qm);
7138
7139 for i in 0..4u32 {
7141 let sd = qd_num * 4 + i;
7142 let sn = qn_num * 4 + i;
7143 let sm = qm_num * 4 + i;
7144
7145 let (vd, d) = encode_sreg(sd);
7146 let (vn, n) = encode_sreg(sn);
7147 let (vm, m) = encode_sreg(sm);
7148
7149 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7150 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7151 }
7152
7153 Ok(result)
7154 }
7155
7156 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7158 let mut result = Vec::new();
7159 let qd_num = qreg_to_num(qd);
7160 let qm_num = qreg_to_num(qm);
7161
7162 for i in 0..4u32 {
7164 let sd = qd_num * 4 + i;
7165 let sm = qm_num * 4 + i;
7166
7167 let (vd, d) = encode_sreg(sd);
7168 let (vm, m) = encode_sreg(sm);
7169
7170 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7171 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7172 }
7173
7174 Ok(result)
7175 }
7176}
7177
7178#[cfg(test)]
7179mod tests {
7180 use super::*;
7181
7182 #[test]
7183 fn test_encoder_creation() {
7184 let encoder_arm = ArmEncoder::new_arm32();
7185 assert!(!encoder_arm.thumb_mode);
7186
7187 let encoder_thumb = ArmEncoder::new_thumb2();
7188 assert!(encoder_thumb.thumb_mode);
7189 }
7190
7191 #[test]
7198 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7199 use synth_synthesis::{ArmOp, Condition, Reg};
7200 let enc = ArmEncoder::new_thumb2();
7201 let hi = enc
7203 .encode(&ArmOp::SetCond {
7204 rd: Reg::R12,
7205 cond: Condition::NE,
7206 })
7207 .unwrap();
7208 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7209 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7211 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7212 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7213 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7214 let lo = enc
7216 .encode(&ArmOp::SetCond {
7217 rd: Reg::R0,
7218 cond: Condition::NE,
7219 })
7220 .unwrap();
7221 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7222 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7223 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7224 }
7225
7226 #[test]
7230 fn test_encode_umull_209b() {
7231 use synth_synthesis::{ArmOp, Reg};
7232 let op = ArmOp::Umull {
7233 rdlo: Reg::R4,
7234 rdhi: Reg::R5,
7235 rn: Reg::R0,
7236 rm: Reg::R3,
7237 };
7238 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7240 assert_eq!(
7241 t,
7242 vec![0xA0, 0xFB, 0x03, 0x45],
7243 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7244 );
7245 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7247 assert_eq!(
7248 a,
7249 0xE085_4390u32.to_le_bytes().to_vec(),
7250 "umull (A32): {a:02x?}"
7251 );
7252 }
7253
7254 #[test]
7261 fn test_encode_arm32_indexed_load_keeps_index_206() {
7262 use synth_synthesis::{ArmOp, MemAddr, Reg};
7263 let enc = ArmEncoder::new_arm32();
7264 let bytes = enc
7266 .encode(&ArmOp::Ldr {
7267 rd: Reg::R0,
7268 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7269 })
7270 .unwrap();
7271 assert_eq!(
7272 bytes.len(),
7273 8,
7274 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7275 );
7276 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7277 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7278 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7280 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7282 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7284 }
7285
7286 #[test]
7293 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7294 let encoder = ArmEncoder::new_thumb2();
7295
7296 let code = encoder
7298 .encode(&ArmOp::Add {
7299 rd: Reg::R12,
7300 rn: Reg::R12,
7301 op2: Operand2::Reg(Reg::R0),
7302 })
7303 .unwrap();
7304 assert_eq!(
7306 code,
7307 vec![0x0C, 0xEB, 0x00, 0x0C],
7308 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7309 );
7310 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7312
7313 let lo = encoder
7315 .encode(&ArmOp::Add {
7316 rd: Reg::R1,
7317 rn: Reg::R2,
7318 op2: Operand2::Reg(Reg::R3),
7319 })
7320 .unwrap();
7321 assert_eq!(
7322 lo.len(),
7323 2,
7324 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7325 );
7326 }
7327
7328 #[test]
7331 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7332 let encoder = ArmEncoder::new_thumb2();
7333
7334 let adds = encoder
7336 .encode(&ArmOp::Adds {
7337 rd: Reg::R10,
7338 rn: Reg::R10,
7339 op2: Operand2::Reg(Reg::R8),
7340 })
7341 .unwrap();
7342 assert_eq!(
7343 adds,
7344 vec![0x1A, 0xEB, 0x08, 0x0A],
7345 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7346 );
7347
7348 let subs = encoder
7350 .encode(&ArmOp::Subs {
7351 rd: Reg::R10,
7352 rn: Reg::R10,
7353 op2: Operand2::Reg(Reg::R8),
7354 })
7355 .unwrap();
7356 assert_eq!(
7357 subs,
7358 vec![0xBA, 0xEB, 0x08, 0x0A],
7359 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7360 );
7361 }
7362
7363 #[test]
7366 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7367 let encoder = ArmEncoder::new_thumb2();
7368
7369 let cmn = encoder
7371 .encode(&ArmOp::Cmn {
7372 rn: Reg::R10,
7373 op2: Operand2::Reg(Reg::R8),
7374 })
7375 .unwrap();
7376 assert_eq!(
7377 cmn,
7378 vec![0x1A, 0xEB, 0x08, 0x0F],
7379 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7380 );
7381
7382 let lo = encoder
7384 .encode(&ArmOp::Cmn {
7385 rn: Reg::R1,
7386 op2: Operand2::Reg(Reg::R2),
7387 })
7388 .unwrap();
7389 assert_eq!(
7390 lo.len(),
7391 2,
7392 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7393 );
7394 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7395 }
7396
7397 #[test]
7401 fn test_encode_pc_operand_returns_err_not_panic_185() {
7402 let encoder = ArmEncoder::new_thumb2();
7403 for op in [
7404 ArmOp::Sdiv {
7405 rd: Reg::PC,
7406 rn: Reg::R0,
7407 rm: Reg::R1,
7408 },
7409 ArmOp::Udiv {
7410 rd: Reg::R0,
7411 rn: Reg::PC,
7412 rm: Reg::R1,
7413 },
7414 ArmOp::Sdiv {
7415 rd: Reg::R0,
7416 rn: Reg::R1,
7417 rm: Reg::PC,
7418 },
7419 ] {
7420 let r = encoder.encode(&op);
7421 assert!(
7422 r.is_err(),
7423 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7424 );
7425 }
7426 assert!(
7428 encoder
7429 .encode(&ArmOp::Sdiv {
7430 rd: Reg::R0,
7431 rn: Reg::R1,
7432 rm: Reg::R2
7433 })
7434 .is_ok()
7435 );
7436 }
7437
7438 #[test]
7439 fn test_encode_nop_arm32() {
7440 let encoder = ArmEncoder::new_arm32();
7441 let code = encoder.encode(&ArmOp::Nop).unwrap();
7442
7443 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7446
7447 #[test]
7448 fn test_encode_nop_thumb() {
7449 let encoder = ArmEncoder::new_thumb2();
7450 let code = encoder.encode(&ArmOp::Nop).unwrap();
7451
7452 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7455
7456 #[test]
7457 fn test_encode_mov_immediate_arm32() {
7458 let encoder = ArmEncoder::new_arm32();
7459 let op = ArmOp::Mov {
7460 rd: Reg::R0,
7461 op2: Operand2::Imm(42),
7462 };
7463
7464 let code = encoder.encode(&op).unwrap();
7465 assert_eq!(code.len(), 4);
7466
7467 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7469 assert_eq!(instr & 0x0E000000, 0x02000000); }
7471
7472 #[test]
7473 fn test_encode_add_registers_arm32() {
7474 let encoder = ArmEncoder::new_arm32();
7475 let op = ArmOp::Add {
7476 rd: Reg::R0,
7477 rn: Reg::R1,
7478 op2: Operand2::Reg(Reg::R2),
7479 };
7480
7481 let code = encoder.encode(&op).unwrap();
7482 assert_eq!(code.len(), 4);
7483
7484 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7485 assert_eq!(instr & 0x0FE00000, 0x00800000);
7487 }
7488
7489 #[test]
7490 fn test_encode_ldr_arm32() {
7491 let encoder = ArmEncoder::new_arm32();
7492 let op = ArmOp::Ldr {
7493 rd: Reg::R0,
7494 addr: MemAddr::imm(Reg::R1, 4),
7495 };
7496
7497 let code = encoder.encode(&op).unwrap();
7498 assert_eq!(code.len(), 4);
7499
7500 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7501 assert_eq!(instr & 0x00100000, 0x00100000);
7503 }
7504
7505 #[test]
7506 fn test_encode_str_arm32() {
7507 let encoder = ArmEncoder::new_arm32();
7508 let op = ArmOp::Str {
7509 rd: Reg::R0,
7510 addr: MemAddr::imm(Reg::SP, 0),
7511 };
7512
7513 let code = encoder.encode(&op).unwrap();
7514 assert_eq!(code.len(), 4);
7515 }
7516
7517 #[test]
7518 fn test_encode_branch_arm32() {
7519 let encoder = ArmEncoder::new_arm32();
7520 let op = ArmOp::Bl {
7521 label: "main".to_string(),
7522 };
7523
7524 let code = encoder.encode(&op).unwrap();
7525 assert_eq!(code.len(), 4);
7526
7527 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7528 assert_eq!(instr & 0x0F000000, 0x0B000000);
7530 }
7531
7532 #[test]
7542 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7543 let encoder = ArmEncoder::new_thumb2();
7544 let op = ArmOp::Bl {
7545 label: "callee".to_string(),
7546 };
7547
7548 let code = encoder.encode(&op).unwrap();
7549 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7550
7551 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7552 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7553 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7554 assert_eq!(
7555 hw2, 0xFFFE,
7556 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7557 );
7558 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7559 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7560 }
7561
7562 #[test]
7563 fn test_encode_sequence() {
7564 let encoder = ArmEncoder::new_arm32();
7565 let ops = vec![
7566 ArmOp::Mov {
7567 rd: Reg::R0,
7568 op2: Operand2::Imm(42),
7569 },
7570 ArmOp::Mov {
7571 rd: Reg::R1,
7572 op2: Operand2::Imm(10),
7573 },
7574 ArmOp::Add {
7575 rd: Reg::R2,
7576 rn: Reg::R0,
7577 op2: Operand2::Reg(Reg::R1),
7578 },
7579 ];
7580
7581 let code = encoder.encode_sequence(&ops).unwrap();
7582 assert_eq!(code.len(), 12); }
7584
7585 #[test]
7586 fn test_reg_to_bits() {
7587 assert_eq!(reg_to_bits(&Reg::R0), 0);
7588 assert_eq!(reg_to_bits(&Reg::R7), 7);
7589 assert_eq!(reg_to_bits(&Reg::SP), 13);
7590 assert_eq!(reg_to_bits(&Reg::LR), 14);
7591 assert_eq!(reg_to_bits(&Reg::PC), 15);
7592 }
7593
7594 #[test]
7595 fn test_encode_bitwise_operations() {
7596 let encoder = ArmEncoder::new_arm32();
7597
7598 let and_op = ArmOp::And {
7599 rd: Reg::R0,
7600 rn: Reg::R1,
7601 op2: Operand2::Reg(Reg::R2),
7602 };
7603 let and_code = encoder.encode(&and_op).unwrap();
7604 assert_eq!(and_code.len(), 4);
7605
7606 let orr_op = ArmOp::Orr {
7607 rd: Reg::R0,
7608 rn: Reg::R1,
7609 op2: Operand2::Reg(Reg::R2),
7610 };
7611 let orr_code = encoder.encode(&orr_op).unwrap();
7612 assert_eq!(orr_code.len(), 4);
7613
7614 let eor_op = ArmOp::Eor {
7615 rd: Reg::R0,
7616 rn: Reg::R1,
7617 op2: Operand2::Reg(Reg::R2),
7618 };
7619 let eor_code = encoder.encode(&eor_op).unwrap();
7620 assert_eq!(eor_code.len(), 4);
7621 }
7622
7623 #[test]
7626 fn test_encode_sdiv_thumb2() {
7627 let encoder = ArmEncoder::new_thumb2();
7628 let op = ArmOp::Sdiv {
7629 rd: Reg::R0,
7630 rn: Reg::R1,
7631 rm: Reg::R2,
7632 };
7633
7634 let code = encoder.encode(&op).unwrap();
7635 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7642 assert_eq!(code[1], 0xFB);
7643 assert_eq!(code[2], 0xF2);
7644 assert_eq!(code[3], 0xF0);
7645 }
7646
7647 #[test]
7648 fn test_encode_udiv_thumb2() {
7649 let encoder = ArmEncoder::new_thumb2();
7650 let op = ArmOp::Udiv {
7651 rd: Reg::R0,
7652 rn: Reg::R1,
7653 rm: Reg::R2,
7654 };
7655
7656 let code = encoder.encode(&op).unwrap();
7657 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7662 assert_eq!(code[1], 0xFB);
7663 assert_eq!(code[2], 0xF2);
7664 assert_eq!(code[3], 0xF0);
7665 }
7666
7667 #[test]
7668 fn test_encode_mul_thumb2() {
7669 let encoder = ArmEncoder::new_thumb2();
7670 let op = ArmOp::Mul {
7671 rd: Reg::R0,
7672 rn: Reg::R1,
7673 rm: Reg::R2,
7674 };
7675
7676 let code = encoder.encode(&op).unwrap();
7677 assert_eq!(code.len(), 4); }
7679
7680 #[test]
7681 fn test_encode_and_thumb2() {
7682 let encoder = ArmEncoder::new_thumb2();
7683 let op = ArmOp::And {
7684 rd: Reg::R0,
7685 rn: Reg::R1,
7686 op2: Operand2::Reg(Reg::R2),
7687 };
7688
7689 let code = encoder.encode(&op).unwrap();
7690 assert_eq!(code.len(), 4); }
7692
7693 #[test]
7694 fn test_encode_lsl_thumb2_low_regs() {
7695 let encoder = ArmEncoder::new_thumb2();
7696 let op = ArmOp::Lsl {
7697 rd: Reg::R0,
7698 rn: Reg::R1,
7699 shift: 5,
7700 };
7701
7702 let code = encoder.encode(&op).unwrap();
7703 assert_eq!(code.len(), 2); }
7705
7706 #[test]
7707 fn test_encode_clz_thumb2() {
7708 let encoder = ArmEncoder::new_thumb2();
7709 let op = ArmOp::Clz {
7710 rd: Reg::R0,
7711 rm: Reg::R1,
7712 };
7713
7714 let code = encoder.encode(&op).unwrap();
7715 assert_eq!(code.len(), 4); }
7717
7718 #[test]
7719 fn test_encode_bx_thumb2() {
7720 let encoder = ArmEncoder::new_thumb2();
7721 let op = ArmOp::Bx { rm: Reg::LR };
7722
7723 let code = encoder.encode(&op).unwrap();
7724 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7728 }
7729
7730 #[test]
7735 fn test_encode_f32_abs_arm32() {
7736 let encoder = ArmEncoder::new_arm32();
7737 let op = ArmOp::F32Abs {
7738 sd: VfpReg::S0,
7739 sm: VfpReg::S2,
7740 };
7741 let code = encoder.encode(&op).unwrap();
7742 assert_eq!(code.len(), 4); }
7744
7745 #[test]
7746 fn test_encode_f32_neg_arm32() {
7747 let encoder = ArmEncoder::new_arm32();
7748 let op = ArmOp::F32Neg {
7749 sd: VfpReg::S0,
7750 sm: VfpReg::S2,
7751 };
7752 let code = encoder.encode(&op).unwrap();
7753 assert_eq!(code.len(), 4);
7754 }
7755
7756 #[test]
7757 fn test_encode_f32_sqrt_arm32() {
7758 let encoder = ArmEncoder::new_arm32();
7759 let op = ArmOp::F32Sqrt {
7760 sd: VfpReg::S0,
7761 sm: VfpReg::S2,
7762 };
7763 let code = encoder.encode(&op).unwrap();
7764 assert_eq!(code.len(), 4);
7765 }
7766
7767 #[test]
7768 fn test_encode_f32_ceil_arm32() {
7769 let encoder = ArmEncoder::new_arm32();
7770 let op = ArmOp::F32Ceil {
7771 sd: VfpReg::S0,
7772 sm: VfpReg::S2,
7773 };
7774 let code = encoder.encode(&op).unwrap();
7775 assert_eq!(code.len(), 36);
7777 }
7778
7779 #[test]
7780 fn test_encode_f32_floor_thumb2() {
7781 let encoder = ArmEncoder::new_thumb2();
7782 let op = ArmOp::F32Floor {
7783 sd: VfpReg::S0,
7784 sm: VfpReg::S2,
7785 };
7786 let code = encoder.encode(&op).unwrap();
7787 assert_eq!(code.len(), 36);
7789 }
7790
7791 #[test]
7792 fn test_encode_f32_min_arm32() {
7793 let encoder = ArmEncoder::new_arm32();
7794 let op = ArmOp::F32Min {
7795 sd: VfpReg::S0,
7796 sn: VfpReg::S2,
7797 sm: VfpReg::S4,
7798 };
7799 let code = encoder.encode(&op).unwrap();
7800 assert_eq!(code.len(), 16); }
7802
7803 #[test]
7804 fn test_encode_f32_max_thumb2() {
7805 let encoder = ArmEncoder::new_thumb2();
7806 let op = ArmOp::F32Max {
7807 sd: VfpReg::S0,
7808 sn: VfpReg::S2,
7809 sm: VfpReg::S4,
7810 };
7811 let code = encoder.encode(&op).unwrap();
7812 assert_eq!(code.len(), 18);
7814 }
7815
7816 #[test]
7817 fn test_encode_f32_copysign_arm32() {
7818 let encoder = ArmEncoder::new_arm32();
7819 let op = ArmOp::F32Copysign {
7820 sd: VfpReg::S0,
7821 sn: VfpReg::S2,
7822 sm: VfpReg::S4,
7823 };
7824 let code = encoder.encode(&op).unwrap();
7825 assert_eq!(code.len(), 24);
7827 }
7828
7829 #[test]
7834 fn test_encode_f64_add_arm32() {
7835 let encoder = ArmEncoder::new_arm32();
7836 let op = ArmOp::F64Add {
7837 dd: VfpReg::D0,
7838 dn: VfpReg::D1,
7839 dm: VfpReg::D2,
7840 };
7841 let code = encoder.encode(&op).unwrap();
7842 assert_eq!(code.len(), 4);
7843 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7845 assert_eq!((instr >> 8) & 0xF, 0xB); }
7847
7848 #[test]
7849 fn test_encode_f64_sub_thumb2() {
7850 let encoder = ArmEncoder::new_thumb2();
7851 let op = ArmOp::F64Sub {
7852 dd: VfpReg::D0,
7853 dn: VfpReg::D1,
7854 dm: VfpReg::D2,
7855 };
7856 let code = encoder.encode(&op).unwrap();
7857 assert_eq!(code.len(), 4); }
7859
7860 #[test]
7861 fn test_encode_f64_mul_arm32() {
7862 let encoder = ArmEncoder::new_arm32();
7863 let op = ArmOp::F64Mul {
7864 dd: VfpReg::D0,
7865 dn: VfpReg::D1,
7866 dm: VfpReg::D2,
7867 };
7868 let code = encoder.encode(&op).unwrap();
7869 assert_eq!(code.len(), 4);
7870 }
7871
7872 #[test]
7873 fn test_encode_f64_div_arm32() {
7874 let encoder = ArmEncoder::new_arm32();
7875 let op = ArmOp::F64Div {
7876 dd: VfpReg::D0,
7877 dn: VfpReg::D1,
7878 dm: VfpReg::D2,
7879 };
7880 let code = encoder.encode(&op).unwrap();
7881 assert_eq!(code.len(), 4);
7882 }
7883
7884 #[test]
7885 fn test_encode_f64_abs_arm32() {
7886 let encoder = ArmEncoder::new_arm32();
7887 let op = ArmOp::F64Abs {
7888 dd: VfpReg::D0,
7889 dm: VfpReg::D2,
7890 };
7891 let code = encoder.encode(&op).unwrap();
7892 assert_eq!(code.len(), 4);
7893 }
7894
7895 #[test]
7896 fn test_encode_f64_neg_arm32() {
7897 let encoder = ArmEncoder::new_arm32();
7898 let op = ArmOp::F64Neg {
7899 dd: VfpReg::D0,
7900 dm: VfpReg::D2,
7901 };
7902 let code = encoder.encode(&op).unwrap();
7903 assert_eq!(code.len(), 4);
7904 }
7905
7906 #[test]
7907 fn test_encode_f64_sqrt_arm32() {
7908 let encoder = ArmEncoder::new_arm32();
7909 let op = ArmOp::F64Sqrt {
7910 dd: VfpReg::D0,
7911 dm: VfpReg::D2,
7912 };
7913 let code = encoder.encode(&op).unwrap();
7914 assert_eq!(code.len(), 4);
7915 }
7916
7917 #[test]
7918 fn test_encode_f64_load_arm32() {
7919 let encoder = ArmEncoder::new_arm32();
7920 let op = ArmOp::F64Load {
7921 dd: VfpReg::D0,
7922 addr: MemAddr::imm(Reg::R0, 8),
7923 };
7924 let code = encoder.encode(&op).unwrap();
7925 assert_eq!(code.len(), 4);
7926 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7927 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7930
7931 #[test]
7932 fn test_encode_f64_store_thumb2() {
7933 let encoder = ArmEncoder::new_thumb2();
7934 let op = ArmOp::F64Store {
7935 dd: VfpReg::D0,
7936 addr: MemAddr::imm(Reg::SP, 0),
7937 };
7938 let code = encoder.encode(&op).unwrap();
7939 assert_eq!(code.len(), 4);
7940 }
7941
7942 #[test]
7943 fn test_encode_f64_compare_arm32() {
7944 let encoder = ArmEncoder::new_arm32();
7945 let op = ArmOp::F64Eq {
7946 rd: Reg::R0,
7947 dn: VfpReg::D0,
7948 dm: VfpReg::D1,
7949 };
7950 let code = encoder.encode(&op).unwrap();
7951 assert_eq!(code.len(), 16); }
7953
7954 #[test]
7955 fn test_encode_f64_compare_thumb2() {
7956 let encoder = ArmEncoder::new_thumb2();
7957 let op = ArmOp::F64Lt {
7958 rd: Reg::R0,
7959 dn: VfpReg::D0,
7960 dm: VfpReg::D1,
7961 };
7962 let code = encoder.encode(&op).unwrap();
7963 assert_eq!(code.len(), 14);
7965 }
7966
7967 #[test]
7968 fn test_encode_f64_const_arm32() {
7969 let encoder = ArmEncoder::new_arm32();
7970 let op = ArmOp::F64Const {
7971 dd: VfpReg::D0,
7972 value: 3.125,
7973 };
7974 let code = encoder.encode(&op).unwrap();
7975 assert_eq!(code.len(), 20);
7977 }
7978
7979 #[test]
7980 fn test_encode_f64_const_thumb2() {
7981 let encoder = ArmEncoder::new_thumb2();
7982 let op = ArmOp::F64Const {
7983 dd: VfpReg::D0,
7984 value: 2.5,
7985 };
7986 let code = encoder.encode(&op).unwrap();
7987 assert_eq!(code.len(), 20);
7989 }
7990
7991 #[test]
7992 fn test_encode_f64_convert_i32s_arm32() {
7993 let encoder = ArmEncoder::new_arm32();
7994 let op = ArmOp::F64ConvertI32S {
7995 dd: VfpReg::D0,
7996 rm: Reg::R0,
7997 };
7998 let code = encoder.encode(&op).unwrap();
7999 assert_eq!(code.len(), 8);
8001 }
8002
8003 #[test]
8004 fn test_encode_f64_promote_f32_arm32() {
8005 let encoder = ArmEncoder::new_arm32();
8006 let op = ArmOp::F64PromoteF32 {
8007 dd: VfpReg::D0,
8008 sm: VfpReg::S0,
8009 };
8010 let code = encoder.encode(&op).unwrap();
8011 assert_eq!(code.len(), 4); }
8013
8014 #[test]
8015 fn test_encode_f64_promote_f32_thumb2() {
8016 let encoder = ArmEncoder::new_thumb2();
8017 let op = ArmOp::F64PromoteF32 {
8018 dd: VfpReg::D0,
8019 sm: VfpReg::S0,
8020 };
8021 let code = encoder.encode(&op).unwrap();
8022 assert_eq!(code.len(), 4);
8023 }
8024
8025 #[test]
8026 fn test_encode_i32_trunc_f64s_arm32() {
8027 let encoder = ArmEncoder::new_arm32();
8028 let op = ArmOp::I32TruncF64S {
8029 rd: Reg::R0,
8030 dm: VfpReg::D0,
8031 };
8032 let code = encoder.encode(&op).unwrap();
8033 assert_eq!(code.len(), 8);
8035 }
8036
8037 #[test]
8038 fn test_encode_f64_reinterpret_i64_arm32() {
8039 let encoder = ArmEncoder::new_arm32();
8040 let op = ArmOp::F64ReinterpretI64 {
8041 dd: VfpReg::D0,
8042 rmlo: Reg::R0,
8043 rmhi: Reg::R1,
8044 };
8045 let code = encoder.encode(&op).unwrap();
8046 assert_eq!(code.len(), 4); }
8048
8049 #[test]
8050 fn test_encode_i64_reinterpret_f64_thumb2() {
8051 let encoder = ArmEncoder::new_thumb2();
8052 let op = ArmOp::I64ReinterpretF64 {
8053 rdlo: Reg::R0,
8054 rdhi: Reg::R1,
8055 dm: VfpReg::D0,
8056 };
8057 let code = encoder.encode(&op).unwrap();
8058 assert_eq!(code.len(), 4);
8059 }
8060
8061 #[test]
8062 fn test_encode_f64_trunc_thumb2() {
8063 let encoder = ArmEncoder::new_thumb2();
8064 let op = ArmOp::F64Trunc {
8065 dd: VfpReg::D0,
8066 dm: VfpReg::D1,
8067 };
8068 let code = encoder.encode(&op).unwrap();
8069 assert_eq!(code.len(), 8);
8071 }
8072
8073 #[test]
8074 fn test_encode_f64_min_arm32() {
8075 let encoder = ArmEncoder::new_arm32();
8076 let op = ArmOp::F64Min {
8077 dd: VfpReg::D0,
8078 dn: VfpReg::D1,
8079 dm: VfpReg::D2,
8080 };
8081 let code = encoder.encode(&op).unwrap();
8082 assert_eq!(code.len(), 16);
8084 }
8085
8086 #[test]
8087 fn test_f64_cp11_encoding() {
8088 let encoder = ArmEncoder::new_arm32();
8090
8091 let code = encoder
8093 .encode(&ArmOp::F64Add {
8094 dd: VfpReg::D0,
8095 dn: VfpReg::D0,
8096 dm: VfpReg::D0,
8097 })
8098 .unwrap();
8099 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8100 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8101
8102 let code = encoder
8104 .encode(&ArmOp::F32Add {
8105 sd: VfpReg::S0,
8106 sn: VfpReg::S0,
8107 sm: VfpReg::S0,
8108 })
8109 .unwrap();
8110 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8111 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8112 }
8113
8114 #[test]
8115 fn test_dreg_encoding_higher_registers() {
8116 let encoder = ArmEncoder::new_arm32();
8117
8118 let op = ArmOp::F64Add {
8120 dd: VfpReg::D15,
8121 dn: VfpReg::D14,
8122 dm: VfpReg::D13,
8123 };
8124 let code = encoder.encode(&op).unwrap();
8125 assert_eq!(code.len(), 4);
8126
8127 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8129 assert_eq!((instr >> 8) & 0xF, 0xB); }
8131
8132 #[test]
8137 fn test_encode_label_emits_no_bytes() {
8138 let encoder = ArmEncoder::new_thumb2();
8139 let op = ArmOp::Label {
8140 name: ".Lblock_end_0".to_string(),
8141 };
8142 let code = encoder.encode(&op).unwrap();
8143 assert!(code.is_empty(), "Label should emit zero bytes");
8144
8145 let encoder32 = ArmEncoder::new_arm32();
8146 let code32 = encoder32.encode(&op).unwrap();
8147 assert!(
8148 code32.is_empty(),
8149 "Label should emit zero bytes in ARM32 too"
8150 );
8151 }
8152
8153 #[test]
8154 fn test_encode_bcc_eq_thumb2() {
8155 use synth_synthesis::Condition;
8156 let encoder = ArmEncoder::new_thumb2();
8157 let op = ArmOp::Bcc {
8158 cond: Condition::EQ,
8159 label: "target".to_string(),
8160 };
8161 let code = encoder.encode(&op).unwrap();
8162 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8166 }
8167
8168 #[test]
8169 fn test_encode_bcc_ne_thumb2() {
8170 use synth_synthesis::Condition;
8171 let encoder = ArmEncoder::new_thumb2();
8172 let op = ArmOp::Bcc {
8173 cond: Condition::NE,
8174 label: "target".to_string(),
8175 };
8176 let code = encoder.encode(&op).unwrap();
8177 assert_eq!(code.len(), 2);
8178
8179 assert_eq!(code, vec![0x00, 0xD1]);
8181 }
8182
8183 #[test]
8184 fn test_encode_bcc_arm32() {
8185 use synth_synthesis::Condition;
8186 let encoder = ArmEncoder::new_arm32();
8187 let op = ArmOp::Bcc {
8188 cond: Condition::EQ,
8189 label: "target".to_string(),
8190 };
8191 let code = encoder.encode(&op).unwrap();
8192 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8195 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8199
8200 #[test]
8201 fn test_encode_udf_thumb2() {
8202 let encoder = ArmEncoder::new_thumb2();
8203 let op = ArmOp::Udf { imm: 0 };
8204 let code = encoder.encode(&op).unwrap();
8205 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8209 }
8210
8211 #[test]
8212 fn test_encode_nop_thumb2() {
8213 let encoder = ArmEncoder::new_thumb2();
8214 let op = ArmOp::Nop;
8215 let code = encoder.encode(&op).unwrap();
8216 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8220 }
8221
8222 #[test]
8227 fn test_encode_i64_add_thumb2() {
8228 let encoder = ArmEncoder::new_thumb2();
8229 let op = ArmOp::I64Add {
8230 rdlo: Reg::R0,
8231 rdhi: Reg::R1,
8232 rnlo: Reg::R0,
8233 rnhi: Reg::R1,
8234 rmlo: Reg::R2,
8235 rmhi: Reg::R3,
8236 };
8237 let code = encoder.encode(&op).unwrap();
8238 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8240 }
8241
8242 #[test]
8243 fn test_encode_i64_sub_thumb2() {
8244 let encoder = ArmEncoder::new_thumb2();
8245 let op = ArmOp::I64Sub {
8246 rdlo: Reg::R0,
8247 rdhi: Reg::R1,
8248 rnlo: Reg::R0,
8249 rnhi: Reg::R1,
8250 rmlo: Reg::R2,
8251 rmhi: Reg::R3,
8252 };
8253 let code = encoder.encode(&op).unwrap();
8254 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8256 }
8257
8258 #[test]
8259 fn test_encode_i64_and_thumb2() {
8260 let encoder = ArmEncoder::new_thumb2();
8261 let op = ArmOp::I64And {
8262 rdlo: Reg::R0,
8263 rdhi: Reg::R1,
8264 rnlo: Reg::R0,
8265 rnhi: Reg::R1,
8266 rmlo: Reg::R2,
8267 rmhi: Reg::R3,
8268 };
8269 let code = encoder.encode(&op).unwrap();
8270 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8272 }
8273
8274 #[test]
8275 fn test_encode_i64_or_thumb2() {
8276 let encoder = ArmEncoder::new_thumb2();
8277 let op = ArmOp::I64Or {
8278 rdlo: Reg::R0,
8279 rdhi: Reg::R1,
8280 rnlo: Reg::R0,
8281 rnhi: Reg::R1,
8282 rmlo: Reg::R2,
8283 rmhi: Reg::R3,
8284 };
8285 let code = encoder.encode(&op).unwrap();
8286 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8287 }
8288
8289 #[test]
8290 fn test_encode_i64_xor_thumb2() {
8291 let encoder = ArmEncoder::new_thumb2();
8292 let op = ArmOp::I64Xor {
8293 rdlo: Reg::R0,
8294 rdhi: Reg::R1,
8295 rnlo: Reg::R0,
8296 rnhi: Reg::R1,
8297 rmlo: Reg::R2,
8298 rmhi: Reg::R3,
8299 };
8300 let code = encoder.encode(&op).unwrap();
8301 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8302 }
8303
8304 #[test]
8305 fn test_encode_i64_const_small_thumb2() {
8306 let encoder = ArmEncoder::new_thumb2();
8307 let op = ArmOp::I64Const {
8309 rdlo: Reg::R0,
8310 rdhi: Reg::R1,
8311 value: 42,
8312 };
8313 let code = encoder.encode(&op).unwrap();
8314 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8316 }
8317
8318 #[test]
8319 fn test_encode_i64_const_large_thumb2() {
8320 let encoder = ArmEncoder::new_thumb2();
8321 let op = ArmOp::I64Const {
8323 rdlo: Reg::R0,
8324 rdhi: Reg::R1,
8325 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8326 };
8327 let code = encoder.encode(&op).unwrap();
8328 assert_eq!(
8330 code.len(),
8331 16,
8332 "I64Const with large value should be 16 bytes"
8333 );
8334 }
8335
8336 #[test]
8337 fn test_encode_i64_extend_i32_s_thumb2() {
8338 let encoder = ArmEncoder::new_thumb2();
8339 let op = ArmOp::I64ExtendI32S {
8340 rdlo: Reg::R0,
8341 rdhi: Reg::R1,
8342 rn: Reg::R0,
8343 };
8344 let code = encoder.encode(&op).unwrap();
8345 assert_eq!(
8347 code.len(),
8348 4,
8349 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8350 );
8351 }
8352
8353 #[test]
8354 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8355 let encoder = ArmEncoder::new_thumb2();
8356 let op = ArmOp::I64ExtendI32S {
8357 rdlo: Reg::R0,
8358 rdhi: Reg::R1,
8359 rn: Reg::R2,
8360 };
8361 let code = encoder.encode(&op).unwrap();
8362 assert!(
8364 code.len() >= 6,
8365 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8366 );
8367 }
8368
8369 #[test]
8370 fn test_encode_i64_extend_i32_u_thumb2() {
8371 let encoder = ArmEncoder::new_thumb2();
8372 let op = ArmOp::I64ExtendI32U {
8373 rdlo: Reg::R0,
8374 rdhi: Reg::R1,
8375 rn: Reg::R0,
8376 };
8377 let code = encoder.encode(&op).unwrap();
8378 assert_eq!(
8380 code.len(),
8381 2,
8382 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8383 );
8384 }
8385
8386 #[test]
8387 fn test_encode_i32_wrap_i64_nop_thumb2() {
8388 let encoder = ArmEncoder::new_thumb2();
8389 let op = ArmOp::I32WrapI64 {
8391 rd: Reg::R0,
8392 rnlo: Reg::R0,
8393 };
8394 let code = encoder.encode(&op).unwrap();
8395 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8396 assert_eq!(code, vec![0x00, 0xBF]); }
8398
8399 #[test]
8400 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8401 let encoder = ArmEncoder::new_thumb2();
8402 let op = ArmOp::I32WrapI64 {
8403 rd: Reg::R2,
8404 rnlo: Reg::R0,
8405 };
8406 let code = encoder.encode(&op).unwrap();
8407 assert!(
8409 code.len() >= 2,
8410 "I32WrapI64 diff reg should emit at least 2 bytes"
8411 );
8412 }
8413
8414 #[test]
8415 fn test_encode_i64_eqz_thumb2() {
8416 let encoder = ArmEncoder::new_thumb2();
8417 let op = ArmOp::I64Eqz {
8418 rd: Reg::R0,
8419 rnlo: Reg::R0,
8420 rnhi: Reg::R1,
8421 };
8422 let code = encoder.encode(&op).unwrap();
8423 assert!(
8425 code.len() >= 6,
8426 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8427 );
8428 }
8429
8430 #[test]
8431 fn test_encode_i64_eq_thumb2() {
8432 let encoder = ArmEncoder::new_thumb2();
8433 let op = ArmOp::I64Eq {
8434 rd: Reg::R0,
8435 rnlo: Reg::R0,
8436 rnhi: Reg::R1,
8437 rmlo: Reg::R2,
8438 rmhi: Reg::R3,
8439 };
8440 let code = encoder.encode(&op).unwrap();
8441 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8443 }
8444
8445 #[test]
8446 fn test_encode_i64_ldr_thumb2() {
8447 let encoder = ArmEncoder::new_thumb2();
8448 let op = ArmOp::I64Ldr {
8449 rdlo: Reg::R0,
8450 rdhi: Reg::R1,
8451 addr: MemAddr::imm(Reg::SP, 0),
8452 };
8453 let code = encoder.encode(&op).unwrap();
8454 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8456 }
8457
8458 #[test]
8459 fn test_encode_i64_str_thumb2() {
8460 let encoder = ArmEncoder::new_thumb2();
8461 let op = ArmOp::I64Str {
8462 rdlo: Reg::R0,
8463 rdhi: Reg::R1,
8464 addr: MemAddr::imm(Reg::SP, 0),
8465 };
8466 let code = encoder.encode(&op).unwrap();
8467 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8469 }
8470
8471 #[test]
8472 fn test_encode_i64_all_comparisons_thumb2() {
8473 let encoder = ArmEncoder::new_thumb2();
8474
8475 let ops = vec![
8476 ArmOp::I64Ne {
8477 rd: Reg::R0,
8478 rnlo: Reg::R0,
8479 rnhi: Reg::R1,
8480 rmlo: Reg::R2,
8481 rmhi: Reg::R3,
8482 },
8483 ArmOp::I64LtS {
8484 rd: Reg::R0,
8485 rnlo: Reg::R0,
8486 rnhi: Reg::R1,
8487 rmlo: Reg::R2,
8488 rmhi: Reg::R3,
8489 },
8490 ArmOp::I64LtU {
8491 rd: Reg::R0,
8492 rnlo: Reg::R0,
8493 rnhi: Reg::R1,
8494 rmlo: Reg::R2,
8495 rmhi: Reg::R3,
8496 },
8497 ArmOp::I64LeS {
8498 rd: Reg::R0,
8499 rnlo: Reg::R0,
8500 rnhi: Reg::R1,
8501 rmlo: Reg::R2,
8502 rmhi: Reg::R3,
8503 },
8504 ArmOp::I64LeU {
8505 rd: Reg::R0,
8506 rnlo: Reg::R0,
8507 rnhi: Reg::R1,
8508 rmlo: Reg::R2,
8509 rmhi: Reg::R3,
8510 },
8511 ArmOp::I64GtS {
8512 rd: Reg::R0,
8513 rnlo: Reg::R0,
8514 rnhi: Reg::R1,
8515 rmlo: Reg::R2,
8516 rmhi: Reg::R3,
8517 },
8518 ArmOp::I64GtU {
8519 rd: Reg::R0,
8520 rnlo: Reg::R0,
8521 rnhi: Reg::R1,
8522 rmlo: Reg::R2,
8523 rmhi: Reg::R3,
8524 },
8525 ArmOp::I64GeS {
8526 rd: Reg::R0,
8527 rnlo: Reg::R0,
8528 rnhi: Reg::R1,
8529 rmlo: Reg::R2,
8530 rmhi: Reg::R3,
8531 },
8532 ArmOp::I64GeU {
8533 rd: Reg::R0,
8534 rnlo: Reg::R0,
8535 rnhi: Reg::R1,
8536 rmlo: Reg::R2,
8537 rmhi: Reg::R3,
8538 },
8539 ];
8540
8541 for op in &ops {
8542 let code = encoder.encode(op).unwrap();
8543 assert!(
8544 code.len() >= 8,
8545 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8546 op,
8547 code.len()
8548 );
8549 }
8550 }
8551
8552 #[test]
8553 fn test_encode_i64_const_zero_thumb2() {
8554 let encoder = ArmEncoder::new_thumb2();
8555 let op = ArmOp::I64Const {
8556 rdlo: Reg::R0,
8557 rdhi: Reg::R1,
8558 value: 0,
8559 };
8560 let code = encoder.encode(&op).unwrap();
8561 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8563 }
8564
8565 #[test]
8566 fn test_encode_i64_const_negative_one_thumb2() {
8567 let encoder = ArmEncoder::new_thumb2();
8568 let op = ArmOp::I64Const {
8569 rdlo: Reg::R0,
8570 rdhi: Reg::R1,
8571 value: -1, };
8573 let code = encoder.encode(&op).unwrap();
8574 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8576 }
8577
8578 #[test]
8583 fn test_encode_ldrb_arm32() {
8584 let encoder = ArmEncoder::new_arm32();
8585 let op = ArmOp::Ldrb {
8586 rd: Reg::R0,
8587 addr: MemAddr::imm(Reg::R1, 4),
8588 };
8589 let code = encoder.encode(&op).unwrap();
8590 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8591 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8593 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8594 }
8595
8596 #[test]
8597 fn test_encode_strb_arm32() {
8598 let encoder = ArmEncoder::new_arm32();
8599 let op = ArmOp::Strb {
8600 rd: Reg::R0,
8601 addr: MemAddr::imm(Reg::R1, 0),
8602 };
8603 let code = encoder.encode(&op).unwrap();
8604 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8605 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8607 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8608 }
8609
8610 #[test]
8611 fn test_encode_ldrh_arm32() {
8612 let encoder = ArmEncoder::new_arm32();
8613 let op = ArmOp::Ldrh {
8614 rd: Reg::R0,
8615 addr: MemAddr::imm(Reg::R1, 2),
8616 };
8617 let code = encoder.encode(&op).unwrap();
8618 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8619 }
8620
8621 #[test]
8622 fn test_encode_strh_arm32() {
8623 let encoder = ArmEncoder::new_arm32();
8624 let op = ArmOp::Strh {
8625 rd: Reg::R0,
8626 addr: MemAddr::imm(Reg::R1, 0),
8627 };
8628 let code = encoder.encode(&op).unwrap();
8629 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8630 }
8631
8632 #[test]
8633 fn test_encode_ldrsb_arm32() {
8634 let encoder = ArmEncoder::new_arm32();
8635 let op = ArmOp::Ldrsb {
8636 rd: Reg::R0,
8637 addr: MemAddr::imm(Reg::R1, 0),
8638 };
8639 let code = encoder.encode(&op).unwrap();
8640 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8641 }
8642
8643 #[test]
8644 fn test_encode_ldrsh_arm32() {
8645 let encoder = ArmEncoder::new_arm32();
8646 let op = ArmOp::Ldrsh {
8647 rd: Reg::R0,
8648 addr: MemAddr::imm(Reg::R1, 0),
8649 };
8650 let code = encoder.encode(&op).unwrap();
8651 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8652 }
8653
8654 #[test]
8655 fn test_encode_ldrb_thumb2_16bit() {
8656 let encoder = ArmEncoder::new_thumb2();
8657 let op = ArmOp::Ldrb {
8658 rd: Reg::R0,
8659 addr: MemAddr::imm(Reg::R1, 4),
8660 };
8661 let code = encoder.encode(&op).unwrap();
8662 assert_eq!(
8664 code.len(),
8665 2,
8666 "Thumb-2 LDRB with small offset should be 16-bit"
8667 );
8668 }
8669
8670 #[test]
8671 fn test_encode_ldrb_thumb2_32bit() {
8672 let encoder = ArmEncoder::new_thumb2();
8673 let op = ArmOp::Ldrb {
8674 rd: Reg::R0,
8675 addr: MemAddr::imm(Reg::R1, 100), };
8677 let code = encoder.encode(&op).unwrap();
8678 assert_eq!(
8679 code.len(),
8680 4,
8681 "Thumb-2 LDRB with large offset should be 32-bit"
8682 );
8683 }
8684
8685 #[test]
8686 fn test_encode_strb_thumb2_16bit() {
8687 let encoder = ArmEncoder::new_thumb2();
8688 let op = ArmOp::Strb {
8689 rd: Reg::R0,
8690 addr: MemAddr::imm(Reg::R1, 10),
8691 };
8692 let code = encoder.encode(&op).unwrap();
8693 assert_eq!(
8694 code.len(),
8695 2,
8696 "Thumb-2 STRB with small offset should be 16-bit"
8697 );
8698 }
8699
8700 #[test]
8701 fn test_encode_ldrh_thumb2_16bit() {
8702 let encoder = ArmEncoder::new_thumb2();
8703 let op = ArmOp::Ldrh {
8704 rd: Reg::R0,
8705 addr: MemAddr::imm(Reg::R1, 4), };
8707 let code = encoder.encode(&op).unwrap();
8708 assert_eq!(
8709 code.len(),
8710 2,
8711 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8712 );
8713 }
8714
8715 #[test]
8716 fn test_encode_strh_thumb2_16bit() {
8717 let encoder = ArmEncoder::new_thumb2();
8718 let op = ArmOp::Strh {
8719 rd: Reg::R0,
8720 addr: MemAddr::imm(Reg::R1, 4),
8721 };
8722 let code = encoder.encode(&op).unwrap();
8723 assert_eq!(
8724 code.len(),
8725 2,
8726 "Thumb-2 STRH with small aligned offset should be 16-bit"
8727 );
8728 }
8729
8730 #[test]
8731 fn test_encode_ldrsb_thumb2() {
8732 let encoder = ArmEncoder::new_thumb2();
8733 let op = ArmOp::Ldrsb {
8734 rd: Reg::R0,
8735 addr: MemAddr::imm(Reg::R1, 0),
8736 };
8737 let code = encoder.encode(&op).unwrap();
8738 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8740 }
8741
8742 #[test]
8743 fn test_encode_ldrsh_thumb2() {
8744 let encoder = ArmEncoder::new_thumb2();
8745 let op = ArmOp::Ldrsh {
8746 rd: Reg::R0,
8747 addr: MemAddr::imm(Reg::R1, 0),
8748 };
8749 let code = encoder.encode(&op).unwrap();
8750 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8751 }
8752
8753 #[test]
8754 fn test_encode_memory_size_thumb2() {
8755 let encoder = ArmEncoder::new_thumb2();
8756 let op = ArmOp::MemorySize { rd: Reg::R0 };
8757 let code = encoder.encode(&op).unwrap();
8758 assert!(!code.is_empty(), "MemorySize should produce code");
8760 }
8761
8762 #[test]
8763 fn test_encode_memory_grow_thumb2() {
8764 let encoder = ArmEncoder::new_thumb2();
8765 let op = ArmOp::MemoryGrow {
8766 rd: Reg::R0,
8767 rn: Reg::R0,
8768 };
8769 let code = encoder.encode(&op).unwrap();
8770 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8771 }
8772
8773 #[test]
8774 fn test_encode_subword_reg_offset_thumb2() {
8775 let encoder = ArmEncoder::new_thumb2();
8776
8777 let op = ArmOp::Ldrb {
8779 rd: Reg::R0,
8780 addr: MemAddr::reg(Reg::R1, Reg::R2),
8781 };
8782 let code = encoder.encode(&op).unwrap();
8783 assert_eq!(
8784 code.len(),
8785 4,
8786 "Thumb-2 LDRB with reg offset should be 32-bit"
8787 );
8788
8789 let op = ArmOp::Strb {
8791 rd: Reg::R0,
8792 addr: MemAddr::reg(Reg::R1, Reg::R2),
8793 };
8794 let code = encoder.encode(&op).unwrap();
8795 assert_eq!(
8796 code.len(),
8797 4,
8798 "Thumb-2 STRB with reg offset should be 32-bit"
8799 );
8800
8801 let op = ArmOp::Ldrh {
8803 rd: Reg::R0,
8804 addr: MemAddr::reg(Reg::R1, Reg::R2),
8805 };
8806 let code = encoder.encode(&op).unwrap();
8807 assert_eq!(
8808 code.len(),
8809 4,
8810 "Thumb-2 LDRH with reg offset should be 32-bit"
8811 );
8812
8813 let op = ArmOp::Strh {
8815 rd: Reg::R0,
8816 addr: MemAddr::reg(Reg::R1, Reg::R2),
8817 };
8818 let code = encoder.encode(&op).unwrap();
8819 assert_eq!(
8820 code.len(),
8821 4,
8822 "Thumb-2 STRH with reg offset should be 32-bit"
8823 );
8824 }
8825
8826 #[test]
8827 fn test_encode_subword_reg_imm_offset_thumb2() {
8828 let encoder = ArmEncoder::new_thumb2();
8829
8830 let op = ArmOp::Ldrb {
8832 rd: Reg::R0,
8833 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8834 };
8835 let code = encoder.encode(&op).unwrap();
8836 assert_eq!(
8838 code.len(),
8839 8,
8840 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8841 );
8842 }
8843
8844 #[test]
8849 fn test_encode_mve_addi32_thumb2() {
8850 let encoder = ArmEncoder::new_thumb2();
8851 let op = ArmOp::MveAddI {
8852 qd: QReg::Q0,
8853 qn: QReg::Q1,
8854 qm: QReg::Q2,
8855 size: MveSize::S32,
8856 };
8857 let code = encoder.encode(&op).unwrap();
8858 assert_eq!(
8859 code.len(),
8860 4,
8861 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8862 );
8863 }
8864
8865 #[test]
8866 fn test_encode_mve_subi16_thumb2() {
8867 let encoder = ArmEncoder::new_thumb2();
8868 let op = ArmOp::MveSubI {
8869 qd: QReg::Q0,
8870 qn: QReg::Q1,
8871 qm: QReg::Q2,
8872 size: MveSize::S16,
8873 };
8874 let code = encoder.encode(&op).unwrap();
8875 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8876 }
8877
8878 #[test]
8879 fn test_encode_mve_muli8_thumb2() {
8880 let encoder = ArmEncoder::new_thumb2();
8881 let op = ArmOp::MveMulI {
8882 qd: QReg::Q0,
8883 qn: QReg::Q1,
8884 qm: QReg::Q2,
8885 size: MveSize::S8,
8886 };
8887 let code = encoder.encode(&op).unwrap();
8888 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8889 }
8890
8891 #[test]
8892 fn test_encode_mve_bitwise_thumb2() {
8893 let encoder = ArmEncoder::new_thumb2();
8894
8895 let ops = vec![
8896 ArmOp::MveAnd {
8897 qd: QReg::Q0,
8898 qn: QReg::Q1,
8899 qm: QReg::Q2,
8900 },
8901 ArmOp::MveOrr {
8902 qd: QReg::Q0,
8903 qn: QReg::Q1,
8904 qm: QReg::Q2,
8905 },
8906 ArmOp::MveEor {
8907 qd: QReg::Q0,
8908 qn: QReg::Q1,
8909 qm: QReg::Q2,
8910 },
8911 ArmOp::MveBic {
8912 qd: QReg::Q0,
8913 qn: QReg::Q1,
8914 qm: QReg::Q2,
8915 },
8916 ];
8917 for op in ops {
8918 let code = encoder.encode(&op).unwrap();
8919 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8920 }
8921 }
8922
8923 #[test]
8924 fn test_encode_mve_mvn_thumb2() {
8925 let encoder = ArmEncoder::new_thumb2();
8926 let op = ArmOp::MveMvn {
8927 qd: QReg::Q0,
8928 qm: QReg::Q1,
8929 };
8930 let code = encoder.encode(&op).unwrap();
8931 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8932 }
8933
8934 #[test]
8935 fn test_encode_mve_load_store_thumb2() {
8936 let encoder = ArmEncoder::new_thumb2();
8937
8938 let load = ArmOp::MveLoad {
8939 qd: QReg::Q0,
8940 addr: MemAddr::imm(Reg::R0, 16),
8941 };
8942 let code = encoder.encode(&load).unwrap();
8943 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8944
8945 let store = ArmOp::MveStore {
8946 qd: QReg::Q1,
8947 addr: MemAddr::imm(Reg::R1, 0),
8948 };
8949 let code = encoder.encode(&store).unwrap();
8950 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8951 }
8952
8953 #[test]
8954 fn test_encode_mve_const_thumb2() {
8955 let encoder = ArmEncoder::new_thumb2();
8956 let op = ArmOp::MveConst {
8957 qd: QReg::Q0,
8958 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8959 };
8960 let code = encoder.encode(&op).unwrap();
8961 assert!(
8964 code.len() >= 24,
8965 "MVE const should produce multiple instructions"
8966 );
8967 }
8968
8969 #[test]
8970 fn test_encode_mve_dup_thumb2() {
8971 let encoder = ArmEncoder::new_thumb2();
8972 let op = ArmOp::MveDup {
8973 qd: QReg::Q0,
8974 rn: Reg::R0,
8975 size: MveSize::S32,
8976 };
8977 let code = encoder.encode(&op).unwrap();
8978 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8979 }
8980
8981 #[test]
8982 fn test_encode_mve_extract_lane_thumb2() {
8983 let encoder = ArmEncoder::new_thumb2();
8984 let op = ArmOp::MveExtractLane {
8985 rd: Reg::R0,
8986 qn: QReg::Q1,
8987 lane: 2,
8988 size: MveSize::S32,
8989 };
8990 let code = encoder.encode(&op).unwrap();
8991 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8992 }
8993
8994 #[test]
8995 fn test_encode_mve_insert_lane_thumb2() {
8996 let encoder = ArmEncoder::new_thumb2();
8997 let op = ArmOp::MveInsertLane {
8998 qd: QReg::Q0,
8999 rn: Reg::R1,
9000 lane: 3,
9001 size: MveSize::S32,
9002 };
9003 let code = encoder.encode(&op).unwrap();
9004 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9005 }
9006
9007 #[test]
9008 fn test_encode_mve_addf32_thumb2() {
9009 let encoder = ArmEncoder::new_thumb2();
9010 let op = ArmOp::MveAddF32 {
9011 qd: QReg::Q0,
9012 qn: QReg::Q1,
9013 qm: QReg::Q2,
9014 };
9015 let code = encoder.encode(&op).unwrap();
9016 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9017 }
9018
9019 #[test]
9020 fn test_encode_mve_divf32_thumb2() {
9021 let encoder = ArmEncoder::new_thumb2();
9022 let op = ArmOp::MveDivF32 {
9023 qd: QReg::Q0,
9024 qn: QReg::Q1,
9025 qm: QReg::Q2,
9026 };
9027 let code = encoder.encode(&op).unwrap();
9028 assert_eq!(
9030 code.len(),
9031 16,
9032 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9033 );
9034 }
9035
9036 #[test]
9037 fn test_encode_mve_sqrtf32_thumb2() {
9038 let encoder = ArmEncoder::new_thumb2();
9039 let op = ArmOp::MveSqrtF32 {
9040 qd: QReg::Q0,
9041 qm: QReg::Q1,
9042 };
9043 let code = encoder.encode(&op).unwrap();
9044 assert_eq!(
9046 code.len(),
9047 16,
9048 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9049 );
9050 }
9051
9052 #[test]
9053 fn test_encode_mve_negf32_thumb2() {
9054 let encoder = ArmEncoder::new_thumb2();
9055 let op = ArmOp::MveNegF32 {
9056 qd: QReg::Q0,
9057 qm: QReg::Q1,
9058 };
9059 let code = encoder.encode(&op).unwrap();
9060 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9061 }
9062
9063 #[test]
9064 fn test_encode_mve_absf32_thumb2() {
9065 let encoder = ArmEncoder::new_thumb2();
9066 let op = ArmOp::MveAbsF32 {
9067 qd: QReg::Q0,
9068 qm: QReg::Q1,
9069 };
9070 let code = encoder.encode(&op).unwrap();
9071 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9072 }
9073
9074 #[test]
9089 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9090 let encoder = ArmEncoder::new_thumb2();
9091 let op = ArmOp::And {
9092 rd: Reg::R2,
9093 rn: Reg::R0,
9094 op2: Operand2::Imm(0x7e),
9095 };
9096 let code = encoder.encode(&op).unwrap();
9097 assert_eq!(
9098 code,
9099 vec![0x00, 0xf0, 0x7e, 0x02],
9100 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9101 );
9102 }
9103
9104 #[test]
9111 fn try_thumb_expand_imm_encodes_modified_immediates() {
9112 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9114 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);
9122 assert_eq!(try_thumb_expand_imm(0x12345), None);
9123 }
9124
9125 #[test]
9130 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9131 let encoder = ArmEncoder::new_thumb2();
9132 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9134 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9135 assert!(
9137 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9138 "cmp #0x101 must error, not compare the wrong constant"
9139 );
9140 assert!(
9141 encoder
9142 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9143 .is_err()
9144 );
9145 assert!(
9146 encoder
9147 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9148 .is_err()
9149 );
9150 assert!(
9152 encoder
9153 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9154 .is_ok()
9155 );
9156 }
9157
9158 #[test]
9165 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9166 let encoder = ArmEncoder::new_thumb2();
9167 assert_eq!(
9169 encoder
9170 .encode(&ArmOp::Add {
9171 rd: Reg::SP,
9172 rn: Reg::SP,
9173 op2: Operand2::Imm(256),
9174 })
9175 .unwrap(),
9176 vec![0x0d, 0xf2, 0x00, 0x1d],
9177 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9178 );
9179 assert_eq!(
9181 encoder
9182 .encode(&ArmOp::Sub {
9183 rd: Reg::SP,
9184 rn: Reg::SP,
9185 op2: Operand2::Imm(256),
9186 })
9187 .unwrap(),
9188 vec![0xad, 0xf2, 0x00, 0x1d],
9189 );
9190 assert!(
9192 encoder
9193 .encode(&ArmOp::Add {
9194 rd: Reg::SP,
9195 rn: Reg::SP,
9196 op2: Operand2::Imm(5000),
9197 })
9198 .is_err(),
9199 "add #5000 must error (no single ADDW), not mis-encode"
9200 );
9201 }
9202
9203 #[test]
9207 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9208 let encoder = ArmEncoder::new_thumb2();
9209 assert_eq!(
9211 encoder
9212 .encode(&ArmOp::Orr {
9213 rd: Reg::R2,
9214 rn: Reg::R0,
9215 op2: Operand2::Imm(0x7e),
9216 })
9217 .unwrap(),
9218 vec![0x40, 0xf0, 0x7e, 0x02],
9219 );
9220 assert_eq!(
9222 encoder
9223 .encode(&ArmOp::Eor {
9224 rd: Reg::R2,
9225 rn: Reg::R0,
9226 op2: Operand2::Imm(0x7e),
9227 })
9228 .unwrap(),
9229 vec![0x80, 0xf0, 0x7e, 0x02],
9230 );
9231 assert!(
9233 encoder
9234 .encode(&ArmOp::Orr {
9235 rd: Reg::R2,
9236 rn: Reg::R0,
9237 op2: Operand2::Imm(0x140),
9238 })
9239 .is_err(),
9240 "ORR #0x140 must error, not emit a NOP"
9241 );
9242 }
9243
9244 #[test]
9245 fn test_encode_mve_different_qregs() {
9246 let encoder = ArmEncoder::new_thumb2();
9247
9248 let op1 = ArmOp::MveAddI {
9250 qd: QReg::Q0,
9251 qn: QReg::Q0,
9252 qm: QReg::Q0,
9253 size: MveSize::S32,
9254 };
9255 let op2 = ArmOp::MveAddI {
9256 qd: QReg::Q3,
9257 qn: QReg::Q5,
9258 qm: QReg::Q7,
9259 size: MveSize::S32,
9260 };
9261 let code1 = encoder.encode(&op1).unwrap();
9262 let code2 = encoder.encode(&op2).unwrap();
9263 assert_ne!(
9264 code1, code2,
9265 "Different Q-registers should produce different encodings"
9266 );
9267 }
9268
9269 #[test]
9270 fn test_encode_mve_arm32_nop() {
9271 let encoder = ArmEncoder::new_arm32();
9273 let op = ArmOp::MveAddI {
9274 qd: QReg::Q0,
9275 qn: QReg::Q1,
9276 qm: QReg::Q2,
9277 size: MveSize::S32,
9278 };
9279 let code = encoder.encode(&op).unwrap();
9280 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9281 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9283 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9284 }
9285}