1use synth_core::Result;
6use synth_core::target::FPUPrecision;
7use synth_synthesis::contracts::encoding as encoding_contracts;
8use synth_synthesis::{ArmOp, MemAddr, MveSize, Operand2, QReg, Reg, VfpReg};
9
10pub struct ArmEncoder {
12 thumb_mode: bool,
14 #[allow(dead_code)]
16 fpu: Option<FPUPrecision>,
17}
18
19impl ArmEncoder {
20 pub fn new_arm32() -> Self {
22 Self {
23 thumb_mode: false,
24 fpu: None,
25 }
26 }
27
28 pub fn new_thumb2() -> Self {
30 Self {
31 thumb_mode: true,
32 fpu: None,
33 }
34 }
35
36 pub fn new_thumb2_with_fpu(fpu: Option<FPUPrecision>) -> Self {
38 Self {
39 thumb_mode: true,
40 fpu,
41 }
42 }
43
44 pub fn encode(&self, op: &ArmOp) -> Result<Vec<u8>> {
46 if self.thumb_mode {
47 self.encode_thumb(op)
48 } else {
49 self.encode_arm(op)
50 }
51 }
52
53 fn encode_arm_reg_offset_mem(&self, op: &ArmOp) -> Result<Option<Vec<u8>>> {
61 use synth_synthesis::Reg;
62 let addr = match op {
63 ArmOp::Ldr { addr, .. }
64 | ArmOp::Str { addr, .. }
65 | ArmOp::Ldrb { addr, .. }
66 | ArmOp::Strb { addr, .. }
67 | ArmOp::Ldrh { addr, .. }
68 | ArmOp::Strh { addr, .. }
69 | ArmOp::Ldrsb { addr, .. }
70 | ArmOp::Ldrsh { addr, .. } => addr,
71 _ => return Ok(None),
72 };
73 let Some(rm) = addr.offset_reg else {
74 return Ok(None);
75 };
76 let ip = Reg::R12;
77 let add: u32 = 0xE0800000
79 | (reg_to_bits(&addr.base) << 16)
80 | (reg_to_bits(&ip) << 12)
81 | reg_to_bits(&rm);
82 let mut bytes = add.to_le_bytes().to_vec();
83 let imm_addr = MemAddr::imm(ip, addr.offset);
86 let imm_op = match op {
87 ArmOp::Ldr { rd, .. } => ArmOp::Ldr {
88 rd: *rd,
89 addr: imm_addr,
90 },
91 ArmOp::Str { rd, .. } => ArmOp::Str {
92 rd: *rd,
93 addr: imm_addr,
94 },
95 ArmOp::Ldrb { rd, .. } => ArmOp::Ldrb {
96 rd: *rd,
97 addr: imm_addr,
98 },
99 ArmOp::Strb { rd, .. } => ArmOp::Strb {
100 rd: *rd,
101 addr: imm_addr,
102 },
103 ArmOp::Ldrh { rd, .. } => ArmOp::Ldrh {
104 rd: *rd,
105 addr: imm_addr,
106 },
107 ArmOp::Strh { rd, .. } => ArmOp::Strh {
108 rd: *rd,
109 addr: imm_addr,
110 },
111 ArmOp::Ldrsb { rd, .. } => ArmOp::Ldrsb {
112 rd: *rd,
113 addr: imm_addr,
114 },
115 ArmOp::Ldrsh { rd, .. } => ArmOp::Ldrsh {
116 rd: *rd,
117 addr: imm_addr,
118 },
119 _ => unreachable!(),
120 };
121 bytes.extend(self.encode_arm(&imm_op)?);
122 Ok(Some(bytes))
123 }
124
125 fn encode_arm(&self, op: &ArmOp) -> Result<Vec<u8>> {
126 if let Some(bytes) = self.encode_arm_reg_offset_mem(op)? {
133 return Ok(bytes);
134 }
135 let instr: u32 = match op {
136 ArmOp::Add { rd, rn, op2 } => {
138 let rd_bits = reg_to_bits(rd);
139 let rn_bits = reg_to_bits(rn);
140 let (op2_bits, i_flag) = encode_operand2(op2);
141
142 0xE0800000 | (i_flag << 25)
145 | (rn_bits << 16)
146 | (rd_bits << 12)
147 | op2_bits
148 }
149
150 ArmOp::Sub { rd, rn, op2 } => {
151 let rd_bits = reg_to_bits(rd);
152 let rn_bits = reg_to_bits(rn);
153 let (op2_bits, i_flag) = encode_operand2(op2);
154
155 0xE0400000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
157 }
158
159 ArmOp::Adds { rd, rn, op2 } => {
161 let rd_bits = reg_to_bits(rd);
162 let rn_bits = reg_to_bits(rn);
163 let (op2_bits, i_flag) = encode_operand2(op2);
164
165 0xE0900000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
167 }
168
169 ArmOp::Adc { rd, rn, op2 } => {
170 let rd_bits = reg_to_bits(rd);
171 let rn_bits = reg_to_bits(rn);
172 let (op2_bits, i_flag) = encode_operand2(op2);
173
174 0xE0A00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
176 }
177
178 ArmOp::Subs { rd, rn, op2 } => {
179 let rd_bits = reg_to_bits(rd);
180 let rn_bits = reg_to_bits(rn);
181 let (op2_bits, i_flag) = encode_operand2(op2);
182
183 0xE0500000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
185 }
186
187 ArmOp::Sbc { rd, rn, op2 } => {
188 let rd_bits = reg_to_bits(rd);
189 let rn_bits = reg_to_bits(rn);
190 let (op2_bits, i_flag) = encode_operand2(op2);
191
192 0xE0C00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
194 }
195
196 ArmOp::Mul { rd, rn, rm } => {
197 let rd_bits = reg_to_bits(rd);
198 let rn_bits = reg_to_bits(rn);
199 let rm_bits = reg_to_bits(rm);
200
201 0xE0000090 | (rd_bits << 16) | (rn_bits << 8) | rm_bits
203 }
204
205 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
206 let rdlo_bits = reg_to_bits(rdlo);
207 let rdhi_bits = reg_to_bits(rdhi);
208 let rn_bits = reg_to_bits(rn);
209 let rm_bits = reg_to_bits(rm);
210
211 0xE0800090 | (rdhi_bits << 16) | (rdlo_bits << 12) | (rm_bits << 8) | rn_bits
213 }
214
215 ArmOp::Sdiv { rd, rn, rm } => {
216 let rd_bits = reg_to_bits(rd);
217 let rn_bits = reg_to_bits(rn);
218 let rm_bits = reg_to_bits(rm);
219
220 0xE710F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
223 }
224
225 ArmOp::Udiv { rd, rn, rm } => {
226 let rd_bits = reg_to_bits(rd);
227 let rn_bits = reg_to_bits(rn);
228 let rm_bits = reg_to_bits(rm);
229
230 0xE730F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
233 }
234
235 ArmOp::Mls { rd, rn, rm, ra } => {
236 let rd_bits = reg_to_bits(rd);
237 let rn_bits = reg_to_bits(rn);
238 let rm_bits = reg_to_bits(rm);
239 let ra_bits = reg_to_bits(ra);
240
241 0xE0600090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
244 }
245
246 ArmOp::Mla { rd, rn, rm, ra } => {
247 let rd_bits = reg_to_bits(rd);
248 let rn_bits = reg_to_bits(rn);
249 let rm_bits = reg_to_bits(rm);
250 let ra_bits = reg_to_bits(ra);
251
252 0xE0200090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
255 }
256
257 ArmOp::And { rd, rn, op2 } => {
258 let rd_bits = reg_to_bits(rd);
259 let rn_bits = reg_to_bits(rn);
260 let (op2_bits, i_flag) = encode_operand2(op2);
261
262 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
264 }
265
266 ArmOp::Orr { rd, rn, op2 } => {
267 let rd_bits = reg_to_bits(rd);
268 let rn_bits = reg_to_bits(rn);
269 let (op2_bits, i_flag) = encode_operand2(op2);
270
271 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
273 }
274
275 ArmOp::Eor { rd, rn, op2 } => {
276 let rd_bits = reg_to_bits(rd);
277 let rn_bits = reg_to_bits(rn);
278 let (op2_bits, i_flag) = encode_operand2(op2);
279
280 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
282 }
283
284 ArmOp::Lsl { rd, rn, shift } => {
286 let rd_bits = reg_to_bits(rd);
287 let rn_bits = reg_to_bits(rn);
288 let shift_bits = *shift & 0x1F;
289
290 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
292 }
293
294 ArmOp::Lsr { rd, rn, shift } => {
295 let rd_bits = reg_to_bits(rd);
296 let rn_bits = reg_to_bits(rn);
297 let shift_bits = *shift & 0x1F;
298
299 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
301 }
302
303 ArmOp::Asr { rd, rn, shift } => {
304 let rd_bits = reg_to_bits(rd);
305 let rn_bits = reg_to_bits(rn);
306 let shift_bits = *shift & 0x1F;
307
308 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
310 }
311
312 ArmOp::Ror { rd, rn, shift } => {
313 let rd_bits = reg_to_bits(rd);
314 let rn_bits = reg_to_bits(rn);
315 let shift_bits = *shift & 0x1F;
316
317 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
319 }
320
321 ArmOp::LslReg { rd, rn, rm } => {
324 let rd_bits = reg_to_bits(rd);
325 let rn_bits = reg_to_bits(rn);
326 let rm_bits = reg_to_bits(rm);
327 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
328 }
329 ArmOp::LsrReg { rd, rn, rm } => {
330 let rd_bits = reg_to_bits(rd);
331 let rn_bits = reg_to_bits(rn);
332 let rm_bits = reg_to_bits(rm);
333 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
334 }
335 ArmOp::AsrReg { rd, rn, rm } => {
336 let rd_bits = reg_to_bits(rd);
337 let rn_bits = reg_to_bits(rn);
338 let rm_bits = reg_to_bits(rm);
339 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
340 }
341 ArmOp::RorReg { rd, rn, rm } => {
342 let rd_bits = reg_to_bits(rd);
343 let rn_bits = reg_to_bits(rn);
344 let rm_bits = reg_to_bits(rm);
345 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
346 }
347
348 ArmOp::Rsb { rd, rn, imm } => {
350 let rd_bits = reg_to_bits(rd);
351 let rn_bits = reg_to_bits(rn);
352 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
355 }
356
357 ArmOp::Clz { rd, rm } => {
359 let rd_bits = reg_to_bits(rd);
360 let rm_bits = reg_to_bits(rm);
361
362 0xE16F0F10 | (rd_bits << 12) | rm_bits
365 }
366
367 ArmOp::Rbit { rd, rm } => {
368 let rd_bits = reg_to_bits(rd);
369 let rm_bits = reg_to_bits(rm);
370
371 0xE6FF0F30 | (rd_bits << 12) | rm_bits
374 }
375
376 ArmOp::Sxtb { rd, rm } => {
377 let rd_bits = reg_to_bits(rd);
378 let rm_bits = reg_to_bits(rm);
379
380 0xE6AF0070 | (rd_bits << 12) | rm_bits
383 }
384
385 ArmOp::Sxth { rd, rm } => {
386 let rd_bits = reg_to_bits(rd);
387 let rm_bits = reg_to_bits(rm);
388
389 0xE6BF0070 | (rd_bits << 12) | rm_bits
392 }
393
394 ArmOp::Mov { rd, op2 } => {
396 let rd_bits = reg_to_bits(rd);
397 let (op2_bits, i_flag) = encode_operand2(op2);
398
399 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
401 }
402
403 ArmOp::Mvn { rd, op2 } => {
404 let rd_bits = reg_to_bits(rd);
405 let (op2_bits, i_flag) = encode_operand2(op2);
406
407 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
409 }
410
411 ArmOp::Movw { rd, imm16 } => {
414 let rd_bits = reg_to_bits(rd);
415 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
416 let imm12 = (*imm16 as u32) & 0xFFF;
417 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
418 }
419
420 ArmOp::Movt { rd, imm16 } => {
423 let rd_bits = reg_to_bits(rd);
424 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
425 let imm12 = (*imm16 as u32) & 0xFFF;
426 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
427 }
428
429 ArmOp::MovwSym { rd, addend, .. } => {
432 let rd_bits = reg_to_bits(rd);
433 let v = (*addend as u32) & 0xffff;
434 0xE3000000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
435 }
436 ArmOp::MovtSym { rd, addend, .. } => {
437 let rd_bits = reg_to_bits(rd);
438 let v = ((*addend as u32) >> 16) & 0xffff;
439 0xE3400000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
440 }
441
442 ArmOp::Cmp { rn, op2 } => {
444 let rn_bits = reg_to_bits(rn);
445 let (op2_bits, i_flag) = encode_operand2(op2);
446
447 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
449 }
450
451 ArmOp::Cmn { rn, op2 } => {
453 let rn_bits = reg_to_bits(rn);
454 let (op2_bits, i_flag) = encode_operand2(op2);
455
456 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
458 }
459
460 ArmOp::Ldr { rd, addr } => {
462 let rd_bits = reg_to_bits(rd);
463 let (base_bits, offset_bits) = encode_mem_addr(addr);
464
465 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
468 }
469
470 ArmOp::Str { rd, addr } => {
471 let rd_bits = reg_to_bits(rd);
472 let (base_bits, offset_bits) = encode_mem_addr(addr);
473
474 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
476 }
477
478 ArmOp::Ldrb { rd, addr } => {
480 let rd_bits = reg_to_bits(rd);
481 let (base_bits, offset_bits) = encode_mem_addr(addr);
482 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
484 }
485
486 ArmOp::Ldrsb { 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;
492 let imm4h = (offset_val >> 4) & 0xF;
493 let imm4l = offset_val & 0xF;
494 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
495 }
496
497 ArmOp::Ldrh { rd, addr } => {
498 let rd_bits = reg_to_bits(rd);
499 let (base_bits, offset_bits) = encode_mem_addr(addr);
500 let offset_val = offset_bits & 0xFF;
502 let imm4h = (offset_val >> 4) & 0xF;
503 let imm4l = offset_val & 0xF;
504 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
505 }
506
507 ArmOp::Ldrsh { rd, addr } => {
508 let rd_bits = reg_to_bits(rd);
509 let (base_bits, offset_bits) = encode_mem_addr(addr);
510 let offset_val = offset_bits & 0xFF;
512 let imm4h = (offset_val >> 4) & 0xF;
513 let imm4l = offset_val & 0xF;
514 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
515 }
516
517 ArmOp::Strb { rd, addr } => {
519 let rd_bits = reg_to_bits(rd);
520 let (base_bits, offset_bits) = encode_mem_addr(addr);
521 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
523 }
524
525 ArmOp::Strh { rd, addr } => {
526 let rd_bits = reg_to_bits(rd);
527 let (base_bits, offset_bits) = encode_mem_addr(addr);
528 let offset_val = offset_bits & 0xFF;
530 let imm4h = (offset_val >> 4) & 0xF;
531 let imm4l = offset_val & 0xF;
532 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
533 }
534
535 ArmOp::MemorySize { rd } => {
537 let rd_bits = reg_to_bits(rd);
538 0xE1A00820 | (rd_bits << 12) | 0x0A }
543
544 ArmOp::MemoryGrow { rd, .. } => {
545 let rd_bits = reg_to_bits(rd);
546 0xE3E00000 | (rd_bits << 12) }
549
550 ArmOp::Label { .. } => {
552 return Ok(Vec::new());
553 }
554
555 ArmOp::B { label: _ } => {
557 0xEA000000
560 }
561
562 ArmOp::Bcc { cond, label: _ } => {
564 use synth_synthesis::Condition;
565 let cond_bits: u32 = match cond {
566 Condition::EQ => 0x0,
567 Condition::NE => 0x1,
568 Condition::HS => 0x2,
569 Condition::LO => 0x3,
570 Condition::HI => 0x8,
571 Condition::LS => 0x9,
572 Condition::GE => 0xA,
573 Condition::LT => 0xB,
574 Condition::GT => 0xC,
575 Condition::LE => 0xD,
576 };
577 (cond_bits << 28) | 0x0A000000
579 }
580
581 ArmOp::Bhs { label: _ } => {
583 0x2A000000 }
586
587 ArmOp::Blo { label: _ } => {
589 0x3A000000 }
592
593 ArmOp::BOffset { offset } => {
597 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
607 0xEA000000 | offset_bits
608 }
609
610 ArmOp::BCondOffset { cond, offset } => {
612 use synth_synthesis::Condition;
613 let cond_bits: u32 = match cond {
614 Condition::EQ => 0x0,
615 Condition::NE => 0x1,
616 Condition::HS => 0x2,
617 Condition::LO => 0x3,
618 Condition::HI => 0x8,
619 Condition::LS => 0x9,
620 Condition::GE => 0xA,
621 Condition::LT => 0xB,
622 Condition::GT => 0xC,
623 Condition::LE => 0xD,
624 };
625 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
629 (cond_bits << 28) | 0x0A000000 | offset_bits
630 }
631
632 ArmOp::Bl { label: _ } => {
633 0xEB000000
635 }
636
637 ArmOp::Bx { rm } => {
638 let rm_bits = reg_to_bits(rm);
639
640 0xE12FFF10 | rm_bits
642 }
643
644 ArmOp::Blx { rm } => {
645 let rm_bits = reg_to_bits(rm);
646
647 0xE12FFF30 | rm_bits
649 }
650
651 ArmOp::Push { regs } => {
652 let mut reg_list: u32 = 0;
654 for r in regs {
655 reg_list |= 1 << reg_to_bits(r);
656 }
657 0xE92D0000 | reg_list
658 }
659
660 ArmOp::Pop { regs } => {
661 let mut reg_list: u32 = 0;
663 for r in regs {
664 reg_list |= 1 << reg_to_bits(r);
665 }
666 0xE8BD0000 | reg_list
667 }
668
669 ArmOp::Nop => {
670 0xE1A00000
672 }
673
674 ArmOp::Udf { imm } => {
675 let imm8 = *imm as u32;
678 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
679 }
680
681 ArmOp::Popcnt { .. } => {
684 0xE1A00000 }
688
689 ArmOp::SetCond { .. } => {
690 0xE1A00000 }
694
695 ArmOp::SelectMove { .. } => {
696 0xE1A00000 }
700
701 ArmOp::Select { .. } => {
702 0xE1A00000 }
706
707 ArmOp::LocalGet { .. } => {
708 0xE1A00000 }
712
713 ArmOp::LocalSet { .. } => {
714 0xE1A00000 }
718
719 ArmOp::LocalTee { .. } => {
720 0xE1A00000 }
724
725 ArmOp::GlobalGet { .. } => {
726 0xE1A00000 }
730
731 ArmOp::GlobalSet { .. } => {
732 0xE1A00000 }
736
737 ArmOp::BrTable { .. } => {
738 0xE1A00000 }
742
743 ArmOp::Call { .. } => {
744 0xE1A00000 }
748
749 ArmOp::CallIndirect { .. } => {
750 0xE1A00000 }
754
755 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)?,
792 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
793 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
794 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
795 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
796 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
797 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
798
799 ArmOp::F32Ceil { sd, sm } => {
802 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
804 ArmOp::F32Floor { sd, sm } => {
805 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
807 ArmOp::F32Trunc { sd, sm } => {
808 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
810 ArmOp::F32Nearest { sd, sm } => {
811 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
813 ArmOp::F32Min { sd, sn, sm } => {
814 return self.encode_arm_f32_minmax(sd, sn, sm, true);
815 }
816 ArmOp::F32Max { sd, sn, sm } => {
817 return self.encode_arm_f32_minmax(sd, sn, sm, false);
818 }
819 ArmOp::F32Copysign { sd, sn, sm } => {
820 return self.encode_arm_f32_copysign(sd, sn, sm);
821 }
822
823 ArmOp::F32Eq { rd, sn, sm } => {
825 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
827 ArmOp::F32Ne { rd, sn, sm } => {
828 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
830 ArmOp::F32Lt { rd, sn, sm } => {
831 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
833 ArmOp::F32Le { rd, sn, sm } => {
834 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
836 ArmOp::F32Gt { rd, sn, sm } => {
837 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
839 ArmOp::F32Ge { rd, sn, sm } => {
840 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
842
843 ArmOp::F32Const { sd, value } => {
845 return self.encode_arm_f32_const(sd, *value);
846 }
847
848 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
849 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
850
851 ArmOp::F32ConvertI32S { sd, rm } => {
853 return self.encode_arm_f32_convert_i32(sd, rm, true);
854 }
855 ArmOp::F32ConvertI32U { sd, rm } => {
856 return self.encode_arm_f32_convert_i32(sd, rm, false);
857 }
858 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
859 return Err(synth_core::Error::synthesis(
860 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
861 ));
862 }
863 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
864 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
865 ArmOp::I32TruncF32S { rd, sm } => {
866 return self.encode_arm_i32_trunc_f32(rd, sm, true);
867 }
868 ArmOp::I32TruncF32U { rd, sm } => {
869 return self.encode_arm_i32_trunc_f32(rd, sm, false);
870 }
871
872 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
875 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
876 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
877 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
878 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
879 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
880 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
881
882 ArmOp::F64Ceil { dd, dm } => {
885 return self.encode_arm_f64_rounding(dd, dm, 0b01);
886 }
887 ArmOp::F64Floor { dd, dm } => {
888 return self.encode_arm_f64_rounding(dd, dm, 0b10);
889 }
890 ArmOp::F64Trunc { dd, dm } => {
891 return self.encode_arm_f64_rounding(dd, dm, 0b11);
892 }
893 ArmOp::F64Nearest { dd, dm } => {
894 return self.encode_arm_f64_rounding(dd, dm, 0b00);
895 }
896 ArmOp::F64Min { dd, dn, dm } => {
897 return self.encode_arm_f64_minmax(dd, dn, dm, true);
898 }
899 ArmOp::F64Max { dd, dn, dm } => {
900 return self.encode_arm_f64_minmax(dd, dn, dm, false);
901 }
902 ArmOp::F64Copysign { dd, dn, dm } => {
903 return self.encode_arm_f64_copysign(dd, dn, dm);
904 }
905
906 ArmOp::F64Eq { rd, dn, dm } => {
908 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
909 }
910 ArmOp::F64Ne { rd, dn, dm } => {
911 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
912 }
913 ArmOp::F64Lt { rd, dn, dm } => {
914 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
915 }
916 ArmOp::F64Le { rd, dn, dm } => {
917 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
918 }
919 ArmOp::F64Gt { rd, dn, dm } => {
920 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
921 }
922 ArmOp::F64Ge { rd, dn, dm } => {
923 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
924 }
925
926 ArmOp::F64Const { dd, value } => {
927 return self.encode_arm_f64_const(dd, *value);
928 }
929
930 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
931 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
932
933 ArmOp::F64ConvertI32S { dd, rm } => {
934 return self.encode_arm_f64_convert_i32(dd, rm, true);
935 }
936 ArmOp::F64ConvertI32U { dd, rm } => {
937 return self.encode_arm_f64_convert_i32(dd, rm, false);
938 }
939 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
940 return Err(synth_core::Error::synthesis(
941 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
942 ));
943 }
944 ArmOp::F64PromoteF32 { dd, sm } => {
945 return self.encode_arm_f64_promote_f32(dd, sm);
946 }
947 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
948 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
949 }
950 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
951 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
952 }
953 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
954 return Err(synth_core::Error::synthesis(
955 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
956 ));
957 }
958 ArmOp::I32TruncF64S { rd, dm } => {
959 return self.encode_arm_i32_trunc_f64(rd, dm, true);
960 }
961 ArmOp::I32TruncF64U { rd, dm } => {
962 return self.encode_arm_i32_trunc_f64(rd, dm, false);
963 }
964 ArmOp::I64SetCond { .. }
966 | ArmOp::I64SetCondZ { .. }
967 | ArmOp::I64Mul { .. }
968 | ArmOp::I64Shl { .. }
969 | ArmOp::I64ShrS { .. }
970 | ArmOp::I64ShrU { .. }
971 | ArmOp::I64Rotl { .. }
972 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
976 | ArmOp::MveStore { .. }
977 | ArmOp::MveConst { .. }
978 | ArmOp::MveAnd { .. }
979 | ArmOp::MveOrr { .. }
980 | ArmOp::MveEor { .. }
981 | ArmOp::MveMvn { .. }
982 | ArmOp::MveBic { .. }
983 | ArmOp::MveAddI { .. }
984 | ArmOp::MveSubI { .. }
985 | ArmOp::MveMulI { .. }
986 | ArmOp::MveNegI { .. }
987 | ArmOp::MveCmpEqI { .. }
988 | ArmOp::MveCmpNeI { .. }
989 | ArmOp::MveCmpLtS { .. }
990 | ArmOp::MveCmpLtU { .. }
991 | ArmOp::MveCmpGtS { .. }
992 | ArmOp::MveCmpGtU { .. }
993 | ArmOp::MveCmpLeS { .. }
994 | ArmOp::MveCmpLeU { .. }
995 | ArmOp::MveCmpGeS { .. }
996 | ArmOp::MveCmpGeU { .. }
997 | ArmOp::MveDup { .. }
998 | ArmOp::MveExtractLane { .. }
999 | ArmOp::MveInsertLane { .. }
1000 | ArmOp::MveAddF32 { .. }
1001 | ArmOp::MveSubF32 { .. }
1002 | ArmOp::MveMulF32 { .. }
1003 | ArmOp::MveNegF32 { .. }
1004 | ArmOp::MveAbsF32 { .. }
1005 | ArmOp::MveCmpEqF32 { .. }
1006 | ArmOp::MveCmpNeF32 { .. }
1007 | ArmOp::MveCmpLtF32 { .. }
1008 | ArmOp::MveCmpLeF32 { .. }
1009 | ArmOp::MveCmpGtF32 { .. }
1010 | ArmOp::MveCmpGeF32 { .. }
1011 | ArmOp::MveDupF32 { .. }
1012 | ArmOp::MveExtractLaneF32 { .. }
1013 | ArmOp::MveReplaceLaneF32 { .. }
1014 | ArmOp::MveDivF32 { .. }
1015 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
1017
1018 Ok(instr.to_le_bytes().to_vec())
1020 }
1021
1022 fn encode_arm_f32_compare(
1026 &self,
1027 rd: &Reg,
1028 sn: &VfpReg,
1029 sm: &VfpReg,
1030 cond_code: u32,
1031 ) -> Result<Vec<u8>> {
1032 let mut bytes = Vec::new();
1033
1034 let sn_num = vfp_sreg_to_num(sn)?;
1036 let sm_num = vfp_sreg_to_num(sm)?;
1037 let (vd, d) = encode_sreg(sn_num);
1038 let (vm, m) = encode_sreg(sm_num);
1039 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1040 bytes.extend_from_slice(&vcmp.to_le_bytes());
1041
1042 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1044
1045 let rd_bits = reg_to_bits(rd);
1047 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1048 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1049
1050 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1052 bytes.extend_from_slice(&mov_one.to_le_bytes());
1053
1054 Ok(bytes)
1055 }
1056
1057 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1059 let mut bytes = Vec::new();
1060 let bits = value.to_bits();
1061
1062 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1067 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1068 bytes.extend_from_slice(&movw.to_le_bytes());
1069
1070 let hi16 = (bits >> 16) & 0xFFFF;
1072 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1073 bytes.extend_from_slice(&movt.to_le_bytes());
1074
1075 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1077 bytes.extend_from_slice(&vmov.to_le_bytes());
1078
1079 Ok(bytes)
1080 }
1081
1082 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1084 let mut bytes = Vec::new();
1085
1086 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1088 bytes.extend_from_slice(&vmov.to_le_bytes());
1089
1090 let sd_num = vfp_sreg_to_num(sd)?;
1093 let (vd, d) = encode_sreg(sd_num);
1094 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1096 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1097 bytes.extend_from_slice(&vcvt.to_le_bytes());
1098
1099 Ok(bytes)
1100 }
1101
1102 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1114 let mut bytes = Vec::new();
1115 let sm_num = vfp_sreg_to_num(sm)?;
1116 let sd_num = vfp_sreg_to_num(sd)?;
1117 let (vd_s, d_s) = encode_sreg(sd_num);
1118 let (vm_s, m_s) = encode_sreg(sm_num);
1119
1120 if mode == 0b11 {
1121 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1124 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1125 } else {
1126 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1131 bytes.extend_from_slice(&vmrs.to_le_bytes());
1132
1133 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1136 bytes.extend_from_slice(&bic.to_le_bytes());
1137
1138 if mode != 0 {
1140 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1142 bytes.extend_from_slice(&orr.to_le_bytes());
1143 }
1144
1145 let vmsr = 0xEEE10A10 | (rt << 12);
1147 bytes.extend_from_slice(&vmsr.to_le_bytes());
1148
1149 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1151 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1152
1153 bytes.extend_from_slice(&vmrs.to_le_bytes());
1155 bytes.extend_from_slice(&bic.to_le_bytes());
1156 bytes.extend_from_slice(&vmsr.to_le_bytes());
1157 }
1158
1159 let (vd2, d2) = encode_sreg(sd_num);
1161 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1162 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1163
1164 Ok(bytes)
1165 }
1166
1167 fn encode_arm_f32_minmax(
1169 &self,
1170 sd: &VfpReg,
1171 sn: &VfpReg,
1172 sm: &VfpReg,
1173 is_min: bool,
1174 ) -> Result<Vec<u8>> {
1175 let mut bytes = Vec::new();
1176 let sn_num = vfp_sreg_to_num(sn)?;
1177 let sm_num = vfp_sreg_to_num(sm)?;
1178 let sd_num = vfp_sreg_to_num(sd)?;
1179
1180 let (vd, d) = encode_sreg(sd_num);
1182 let (vn, n) = encode_sreg(sn_num);
1183 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1184 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1185
1186 let (vm, m) = encode_sreg(sm_num);
1188 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1189 bytes.extend_from_slice(&vcmp.to_le_bytes());
1190
1191 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1193
1194 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1197
1198 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1200 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1201
1202 Ok(bytes)
1203 }
1204
1205 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1207 let mut bytes = Vec::new();
1208
1209 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1211 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1212
1213 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1215 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1216
1217 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1221 bytes.extend_from_slice(&and_sign.to_le_bytes());
1222
1223 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1226 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1227
1228 let orr = 0xE1800000u32 | 12;
1231 bytes.extend_from_slice(&orr.to_le_bytes());
1232
1233 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1235 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1236
1237 Ok(bytes)
1238 }
1239
1240 fn encode_arm_f64_compare(
1242 &self,
1243 rd: &Reg,
1244 dn: &VfpReg,
1245 dm: &VfpReg,
1246 cond_code: u32,
1247 ) -> Result<Vec<u8>> {
1248 let mut bytes = Vec::new();
1249
1250 let dn_num = vfp_dreg_to_num(dn)?;
1252 let dm_num = vfp_dreg_to_num(dm)?;
1253 let (vd, d) = encode_dreg(dn_num);
1254 let (vm, m) = encode_dreg(dm_num);
1255 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1256 bytes.extend_from_slice(&vcmp.to_le_bytes());
1257
1258 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1260
1261 let rd_bits = reg_to_bits(rd);
1263 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1264 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1265
1266 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1268 bytes.extend_from_slice(&mov_one.to_le_bytes());
1269
1270 Ok(bytes)
1271 }
1272
1273 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1275 let mut bytes = Vec::new();
1276 let bits = value.to_bits();
1277 let lo32 = bits as u32;
1278 let hi32 = (bits >> 32) as u32;
1279
1280 let lo16 = lo32 & 0xFFFF;
1282 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1283 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1284 let hi16 = (lo32 >> 16) & 0xFFFF;
1285 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1286 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1287
1288 let lo16 = hi32 & 0xFFFF;
1290 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1291 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1292 let hi16 = (hi32 >> 16) & 0xFFFF;
1293 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1294 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1295
1296 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1298 bytes.extend_from_slice(&vmov.to_le_bytes());
1299
1300 Ok(bytes)
1301 }
1302
1303 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1305 let mut bytes = Vec::new();
1306
1307 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1309 bytes.extend_from_slice(&vmov.to_le_bytes());
1310
1311 let dd_num = vfp_dreg_to_num(dd)?;
1314 let (vd, d) = encode_dreg(dd_num);
1315 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1316 let vcvt = base | (d << 22) | (vd << 12);
1318 bytes.extend_from_slice(&vcvt.to_le_bytes());
1319
1320 Ok(bytes)
1321 }
1322
1323 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1325 let dd_num = vfp_dreg_to_num(dd)?;
1326 let sm_num = vfp_sreg_to_num(sm)?;
1327 let (vd, d) = encode_dreg(dd_num);
1328 let (vm, m) = encode_sreg(sm_num);
1329
1330 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1332 Ok(vcvt.to_le_bytes().to_vec())
1333 }
1334
1335 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1337 let mut bytes = Vec::new();
1338 let dm_num = vfp_dreg_to_num(dm)?;
1339 let (vm, m) = encode_dreg(dm_num);
1340
1341 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1344 let vcvt = base | (m << 5) | vm;
1345 bytes.extend_from_slice(&vcvt.to_le_bytes());
1346
1347 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1349 bytes.extend_from_slice(&vmov.to_le_bytes());
1350
1351 Ok(bytes)
1352 }
1353
1354 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1362 let mut bytes = Vec::new();
1363 let dm_num = vfp_dreg_to_num(dm)?;
1364 let dd_num = vfp_dreg_to_num(dd)?;
1365 let (vm, m) = encode_dreg(dm_num);
1366 let (vd, d) = encode_dreg(dd_num);
1367
1368 if mode == 0b11 {
1369 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1371 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1372 } else {
1373 let rt: u32 = 12;
1375
1376 let vmrs = 0xEEF10A10 | (rt << 12);
1378 bytes.extend_from_slice(&vmrs.to_le_bytes());
1379
1380 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1382 bytes.extend_from_slice(&bic.to_le_bytes());
1383
1384 if mode != 0 {
1386 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1387 bytes.extend_from_slice(&orr.to_le_bytes());
1388 }
1389
1390 let vmsr = 0xEEE10A10 | (rt << 12);
1392 bytes.extend_from_slice(&vmsr.to_le_bytes());
1393
1394 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1396 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1397
1398 bytes.extend_from_slice(&vmrs.to_le_bytes());
1400 bytes.extend_from_slice(&bic.to_le_bytes());
1401 bytes.extend_from_slice(&vmsr.to_le_bytes());
1402 }
1403
1404 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1406 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1407
1408 Ok(bytes)
1409 }
1410
1411 fn encode_arm_f64_minmax(
1413 &self,
1414 dd: &VfpReg,
1415 dn: &VfpReg,
1416 dm: &VfpReg,
1417 is_min: bool,
1418 ) -> Result<Vec<u8>> {
1419 let mut bytes = Vec::new();
1420 let dn_num = vfp_dreg_to_num(dn)?;
1421 let dm_num = vfp_dreg_to_num(dm)?;
1422 let dd_num = vfp_dreg_to_num(dd)?;
1423
1424 let (vd, d) = encode_dreg(dd_num);
1426 let (vn, n) = encode_dreg(dn_num);
1427 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1428 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1429
1430 let (vm, m) = encode_dreg(dm_num);
1432 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1433 bytes.extend_from_slice(&vcmp.to_le_bytes());
1434
1435 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1437
1438 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1439 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1440 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1441
1442 Ok(bytes)
1443 }
1444
1445 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1447 let mut bytes = Vec::new();
1448
1449 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1451 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1452
1453 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1456 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1457
1458 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1460 bytes.extend_from_slice(&and_sign.to_le_bytes());
1461
1462 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1464 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1465
1466 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1468 bytes.extend_from_slice(&orr.to_le_bytes());
1469
1470 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1472 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1473
1474 Ok(bytes)
1475 }
1476
1477 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1479 let mut bytes = Vec::new();
1480
1481 let sm_num = vfp_sreg_to_num(sm)?;
1484 let (vd, d) = encode_sreg(sm_num);
1485 let (vm, m) = encode_sreg(sm_num);
1486 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1487 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1488 bytes.extend_from_slice(&vcvt.to_le_bytes());
1489
1490 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1492 bytes.extend_from_slice(&vmov.to_le_bytes());
1493
1494 Ok(bytes)
1495 }
1496
1497 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1499 match op {
1502 ArmOp::Add { rd, rn, op2 } => {
1504 let rd_bits = reg_to_bits(rd) as u16;
1505 let rn_bits = reg_to_bits(rn) as u16;
1506
1507 if let Operand2::Reg(rm) = op2 {
1508 let rm_bits = reg_to_bits(rm) as u16;
1509 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1517 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1519 Ok(instr.to_le_bytes().to_vec())
1520 } else {
1521 self.encode_thumb32_add_reg_raw(
1523 rd_bits as u32,
1524 rn_bits as u32,
1525 rm_bits as u32,
1526 )
1527 }
1528 } else if let Operand2::Imm(imm) = op2 {
1529 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1530 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1532 Ok(instr.to_le_bytes().to_vec())
1533 } else {
1534 self.encode_thumb32_add(rd, rn, *imm as u32)
1536 }
1537 } else {
1538 self.encode_thumb32_add(rd, rn, 0)
1540 }
1541 }
1542
1543 ArmOp::Sub { rd, rn, op2 } => {
1544 let rd_bits = reg_to_bits(rd) as u16;
1545 let rn_bits = reg_to_bits(rn) as u16;
1546
1547 if let Operand2::Reg(rm) = op2 {
1548 let rm_bits = reg_to_bits(rm) as u16;
1549 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1551 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1553 Ok(instr.to_le_bytes().to_vec())
1554 } else {
1555 self.encode_thumb32_sub_reg_raw(
1557 rd_bits as u32,
1558 rn_bits as u32,
1559 rm_bits as u32,
1560 )
1561 }
1562 } else if let Operand2::Imm(imm) = op2 {
1563 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1564 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1566 Ok(instr.to_le_bytes().to_vec())
1567 } else {
1568 self.encode_thumb32_sub(rd, rn, *imm as u32)
1569 }
1570 } else {
1571 self.encode_thumb32_sub(rd, rn, 0)
1572 }
1573 }
1574
1575 ArmOp::Mov { rd, op2 } => {
1576 let rd_bits = reg_to_bits(rd) as u16;
1577
1578 if let Operand2::Imm(imm) = op2 {
1579 if *imm <= 255 && rd_bits < 8 {
1580 let imm_bits = (*imm as u16) & 0xFF;
1582 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1583 Ok(instr.to_le_bytes().to_vec())
1584 } else {
1585 self.encode_thumb32_movw(rd, *imm as u32)
1587 }
1588 } else if let Operand2::Reg(rm) = op2 {
1589 let rm_bits = reg_to_bits(rm) as u16;
1590 let d_bit = (rd_bits >> 3) & 1;
1593 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1594 Ok(instr.to_le_bytes().to_vec())
1595 } else {
1596 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1598 }
1599 }
1600
1601 ArmOp::Push { regs } => {
1602 let mut reg_list: u16 = 0;
1606 let mut need_32bit = false;
1607 for r in regs {
1608 let bit = reg_to_bits(r);
1609 if bit >= 8 && *r != Reg::LR {
1610 need_32bit = true;
1611 }
1612 reg_list |= 1 << bit;
1613 }
1614 if !need_32bit {
1615 let m_bit = if reg_list & (1 << 14) != 0 {
1617 1u16
1618 } else {
1619 0u16
1620 };
1621 let low_regs = reg_list & 0xFF;
1622 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1623 Ok(instr.to_le_bytes().to_vec())
1624 } else {
1625 let hw1: u16 = 0xE92D;
1627 let hw2: u16 = reg_list;
1628 let mut bytes = hw1.to_le_bytes().to_vec();
1629 bytes.extend_from_slice(&hw2.to_le_bytes());
1630 Ok(bytes)
1631 }
1632 }
1633
1634 ArmOp::Pop { regs } => {
1635 let mut reg_list: u16 = 0;
1639 let mut need_32bit = false;
1640 for r in regs {
1641 let bit = reg_to_bits(r);
1642 if bit >= 8 && *r != Reg::PC {
1643 need_32bit = true;
1644 }
1645 reg_list |= 1 << bit;
1646 }
1647 if !need_32bit {
1648 let p_bit = if reg_list & (1 << 15) != 0 {
1650 1u16
1651 } else {
1652 0u16
1653 };
1654 let low_regs = reg_list & 0xFF;
1655 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1656 Ok(instr.to_le_bytes().to_vec())
1657 } else {
1658 let hw1: u16 = 0xE8BD;
1660 let hw2: u16 = reg_list;
1661 let mut bytes = hw1.to_le_bytes().to_vec();
1662 bytes.extend_from_slice(&hw2.to_le_bytes());
1663 Ok(bytes)
1664 }
1665 }
1666
1667 ArmOp::Nop => {
1668 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1670 }
1671
1672 ArmOp::Udf { imm } => {
1673 let instr: u16 = 0xDE00 | (*imm as u16);
1676 let bytes = instr.to_le_bytes().to_vec();
1677 encoding_contracts::verify_thumb16(&bytes);
1678 Ok(bytes)
1679 }
1680
1681 ArmOp::Adds { rd, rn, op2 } => {
1684 let rd_bits = reg_to_bits(rd) as u16;
1685 let rn_bits = reg_to_bits(rn) as u16;
1686
1687 if let Operand2::Reg(rm) = op2 {
1688 let rm_bits = reg_to_bits(rm) as u16;
1689 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1694 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1696 Ok(instr.to_le_bytes().to_vec())
1697 } else {
1698 self.encode_thumb32_adds_reg_raw(
1699 rd_bits as u32,
1700 rn_bits as u32,
1701 rm_bits as u32,
1702 )
1703 }
1704 } else {
1705 self.encode_thumb32_adds(rd, rn, 0)
1707 }
1708 }
1709
1710 ArmOp::Adc { rd, rn, op2 } => {
1713 let rd_bits = reg_to_bits(rd);
1714 let rn_bits = reg_to_bits(rn);
1715
1716 if let Operand2::Reg(rm) = op2 {
1717 let rm_bits = reg_to_bits(rm);
1718 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1720 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1721
1722 let mut bytes = hw1.to_le_bytes().to_vec();
1723 bytes.extend_from_slice(&hw2.to_le_bytes());
1724 Ok(bytes)
1725 } else {
1726 let hw1: u16 = (0xF140 | rn_bits) as u16;
1728 let hw2: u16 = (rd_bits << 8) as u16;
1729 let mut bytes = hw1.to_le_bytes().to_vec();
1730 bytes.extend_from_slice(&hw2.to_le_bytes());
1731 Ok(bytes)
1732 }
1733 }
1734
1735 ArmOp::Subs { rd, rn, op2 } => {
1737 let rd_bits = reg_to_bits(rd) as u16;
1738 let rn_bits = reg_to_bits(rn) as u16;
1739
1740 if let Operand2::Reg(rm) = op2 {
1741 let rm_bits = reg_to_bits(rm) as u16;
1742 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1746 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1748 Ok(instr.to_le_bytes().to_vec())
1749 } else {
1750 self.encode_thumb32_subs_reg_raw(
1751 rd_bits as u32,
1752 rn_bits as u32,
1753 rm_bits as u32,
1754 )
1755 }
1756 } else {
1757 self.encode_thumb32_subs(rd, rn, 0)
1759 }
1760 }
1761
1762 ArmOp::Sbc { rd, rn, op2 } => {
1765 let rd_bits = reg_to_bits(rd);
1766 let rn_bits = reg_to_bits(rn);
1767
1768 if let Operand2::Reg(rm) = op2 {
1769 let rm_bits = reg_to_bits(rm);
1770 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1772 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1773
1774 let mut bytes = hw1.to_le_bytes().to_vec();
1775 bytes.extend_from_slice(&hw2.to_le_bytes());
1776 Ok(bytes)
1777 } else {
1778 let hw1: u16 = (0xF160 | rn_bits) as u16;
1780 let hw2: u16 = (rd_bits << 8) as u16;
1781 let mut bytes = hw1.to_le_bytes().to_vec();
1782 bytes.extend_from_slice(&hw2.to_le_bytes());
1783 Ok(bytes)
1784 }
1785 }
1786
1787 ArmOp::Sdiv { rd, rn, rm } => {
1791 let rd_bits = reg_to_bits(rd);
1792 let rn_bits = reg_to_bits(rn);
1793 let rm_bits = reg_to_bits(rm);
1794 reg_bits_checked(rd_bits)?;
1795 reg_bits_checked(rn_bits)?;
1796 reg_bits_checked(rm_bits)?;
1797
1798 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1802 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1803
1804 let mut bytes = hw1.to_le_bytes().to_vec();
1806 bytes.extend_from_slice(&hw2.to_le_bytes());
1807 encoding_contracts::verify_thumb32(&bytes);
1808 Ok(bytes)
1809 }
1810
1811 ArmOp::Udiv { rd, rn, rm } => {
1813 let rd_bits = reg_to_bits(rd);
1814 let rn_bits = reg_to_bits(rn);
1815 let rm_bits = reg_to_bits(rm);
1816 reg_bits_checked(rd_bits)?;
1817 reg_bits_checked(rn_bits)?;
1818 reg_bits_checked(rm_bits)?;
1819
1820 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1822 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1823
1824 let mut bytes = hw1.to_le_bytes().to_vec();
1825 bytes.extend_from_slice(&hw2.to_le_bytes());
1826 encoding_contracts::verify_thumb32(&bytes);
1827 Ok(bytes)
1828 }
1829
1830 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
1831 let rdlo_bits = reg_to_bits(rdlo);
1832 let rdhi_bits = reg_to_bits(rdhi);
1833 let rn_bits = reg_to_bits(rn);
1834 let rm_bits = reg_to_bits(rm);
1835 reg_bits_checked(rdlo_bits)?;
1836 reg_bits_checked(rdhi_bits)?;
1837 reg_bits_checked(rn_bits)?;
1838 reg_bits_checked(rm_bits)?;
1839
1840 let hw1: u16 = (0xFBA0 | rn_bits) as u16;
1842 let hw2: u16 = ((rdlo_bits << 12) | (rdhi_bits << 8) | rm_bits) as u16;
1843
1844 let mut bytes = hw1.to_le_bytes().to_vec();
1845 bytes.extend_from_slice(&hw2.to_le_bytes());
1846 encoding_contracts::verify_thumb32(&bytes);
1847 Ok(bytes)
1848 }
1849
1850 ArmOp::Mul { rd, rn, rm } => {
1852 let rd_bits = reg_to_bits(rd);
1853 let rn_bits = reg_to_bits(rn);
1854 let rm_bits = reg_to_bits(rm);
1855
1856 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1859 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1860
1861 let mut bytes = hw1.to_le_bytes().to_vec();
1862 bytes.extend_from_slice(&hw2.to_le_bytes());
1863 Ok(bytes)
1864 }
1865
1866 ArmOp::Mls { rd, rn, rm, ra } => {
1868 let rd_bits = reg_to_bits(rd);
1869 let rn_bits = reg_to_bits(rn);
1870 let rm_bits = reg_to_bits(rm);
1871 let ra_bits = reg_to_bits(ra);
1872
1873 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1876 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1877
1878 let mut bytes = hw1.to_le_bytes().to_vec();
1879 bytes.extend_from_slice(&hw2.to_le_bytes());
1880 Ok(bytes)
1881 }
1882
1883 ArmOp::Mla { rd, rn, rm, ra } => {
1884 let rd_bits = reg_to_bits(rd);
1885 let rn_bits = reg_to_bits(rn);
1886 let rm_bits = reg_to_bits(rm);
1887 let ra_bits = reg_to_bits(ra);
1888
1889 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1892 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | rm_bits) as u16;
1893
1894 let mut bytes = hw1.to_le_bytes().to_vec();
1895 bytes.extend_from_slice(&hw2.to_le_bytes());
1896 Ok(bytes)
1897 }
1898
1899 ArmOp::And { rd, rn, op2 } => {
1901 if let Operand2::Reg(rm) = op2 {
1902 let rd_bits = reg_to_bits(rd);
1903 let rn_bits = reg_to_bits(rn);
1904 let rm_bits = reg_to_bits(rm);
1905
1906 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1908 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1909
1910 let mut bytes = hw1.to_le_bytes().to_vec();
1911 bytes.extend_from_slice(&hw2.to_le_bytes());
1912 Ok(bytes)
1913 } else if let Operand2::Imm(imm) = op2 {
1914 let rd_bits = reg_to_bits(rd);
1915 let rn_bits = reg_to_bits(rn);
1916
1917 let field = try_thumb_expand_imm(*imm as u32).ok_or_else(|| {
1924 synth_core::Error::synthesis(
1925 "AND immediate is not a valid ThumbExpandImm — materialize into a register",
1926 )
1927 })?;
1928 let i_bit = (field >> 11) & 1;
1929 let imm3 = (field >> 8) & 0x7;
1930 let imm8 = field & 0xFF;
1931
1932 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1933 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1934
1935 let mut bytes = hw1.to_le_bytes().to_vec();
1936 bytes.extend_from_slice(&hw2.to_le_bytes());
1937 Ok(bytes)
1938 } else {
1939 let instr: u16 = 0xBF00;
1941 Ok(instr.to_le_bytes().to_vec())
1942 }
1943 }
1944
1945 ArmOp::Orr { rd, rn, op2 } => {
1947 if let Operand2::Reg(rm) = op2 {
1948 let rd_bits = reg_to_bits(rd);
1949 let rn_bits = reg_to_bits(rn);
1950 let rm_bits = reg_to_bits(rm);
1951
1952 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1954 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1955
1956 let mut bytes = hw1.to_le_bytes().to_vec();
1957 bytes.extend_from_slice(&hw2.to_le_bytes());
1958 Ok(bytes)
1959 } else if let Operand2::Imm(imm) = op2 {
1960 let imm_val = *imm as u32;
1965 if imm_val > 0xFF {
1966 return Err(synth_core::Error::synthesis(
1967 "ORR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1968 ));
1969 }
1970 let rd_bits = reg_to_bits(rd);
1971 let rn_bits = reg_to_bits(rn);
1972 let hw1: u16 = (0xF040 | rn_bits) as u16;
1973 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
1974 let mut bytes = hw1.to_le_bytes().to_vec();
1975 bytes.extend_from_slice(&hw2.to_le_bytes());
1976 Ok(bytes)
1977 } else {
1978 let instr: u16 = 0xBF00;
1979 Ok(instr.to_le_bytes().to_vec())
1980 }
1981 }
1982
1983 ArmOp::Eor { rd, rn, op2 } => {
1985 if let Operand2::Reg(rm) = op2 {
1986 let rd_bits = reg_to_bits(rd);
1987 let rn_bits = reg_to_bits(rn);
1988 let rm_bits = reg_to_bits(rm);
1989
1990 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1992 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1993
1994 let mut bytes = hw1.to_le_bytes().to_vec();
1995 bytes.extend_from_slice(&hw2.to_le_bytes());
1996 Ok(bytes)
1997 } else if let Operand2::Imm(imm) = op2 {
1998 let imm_val = *imm as u32;
2002 if imm_val > 0xFF {
2003 return Err(synth_core::Error::synthesis(
2004 "EOR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
2005 ));
2006 }
2007 let rd_bits = reg_to_bits(rd);
2008 let rn_bits = reg_to_bits(rn);
2009 let hw1: u16 = (0xF080 | rn_bits) as u16;
2010 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
2011 let mut bytes = hw1.to_le_bytes().to_vec();
2012 bytes.extend_from_slice(&hw2.to_le_bytes());
2013 Ok(bytes)
2014 } else {
2015 let instr: u16 = 0xBF00;
2016 Ok(instr.to_le_bytes().to_vec())
2017 }
2018 }
2019
2020 ArmOp::Lsl { rd, rn, shift } => {
2022 let rd_bits = reg_to_bits(rd) as u16;
2023 let rn_bits = reg_to_bits(rn) as u16;
2024 let shift_bits = (*shift as u16) & 0x1F;
2025
2026 if rd_bits < 8 && rn_bits < 8 {
2027 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2029 Ok(instr.to_le_bytes().to_vec())
2030 } else {
2031 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
2034 }
2035
2036 ArmOp::Lsr { rd, rn, shift } => {
2037 let rd_bits = reg_to_bits(rd) as u16;
2038 let rn_bits = reg_to_bits(rn) as u16;
2039 let shift_bits = (*shift as u16) & 0x1F;
2040
2041 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2042 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2044 Ok(instr.to_le_bytes().to_vec())
2045 } else {
2046 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
2048 }
2049
2050 ArmOp::Asr { rd, rn, shift } => {
2051 let rd_bits = reg_to_bits(rd) as u16;
2052 let rn_bits = reg_to_bits(rn) as u16;
2053 let shift_bits = (*shift as u16) & 0x1F;
2054
2055 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2056 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2058 Ok(instr.to_le_bytes().to_vec())
2059 } else {
2060 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
2062 }
2063
2064 ArmOp::Ror { rd, rn, shift } => {
2065 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
2068
2069 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
2073 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
2074 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
2075 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
2076
2077 ArmOp::Rsb { rd, rn, imm } => {
2080 let rd_bits = reg_to_bits(rd);
2081 let rn_bits = reg_to_bits(rn);
2082 let imm_val = *imm;
2083
2084 let i_bit = (imm_val >> 11) & 1;
2085 let imm3 = (imm_val >> 8) & 0x7;
2086 let imm8 = imm_val & 0xFF;
2087
2088 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2090 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2092
2093 let mut bytes = hw1.to_le_bytes().to_vec();
2094 bytes.extend_from_slice(&hw2.to_le_bytes());
2095 Ok(bytes)
2096 }
2097
2098 ArmOp::Clz { rd, rm } => {
2100 let rd_bits = reg_to_bits(rd);
2101 let rm_bits = reg_to_bits(rm);
2102
2103 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2106 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2107
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 ArmOp::Rbit { rd, rm } => {
2115 let rd_bits = reg_to_bits(rd);
2116 let rm_bits = reg_to_bits(rm);
2117
2118 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2121 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2122
2123 let mut bytes = hw1.to_le_bytes().to_vec();
2124 bytes.extend_from_slice(&hw2.to_le_bytes());
2125 Ok(bytes)
2126 }
2127
2128 ArmOp::Sxtb { rd, rm } => {
2130 let rd_bits = reg_to_bits(rd) as u16;
2131 let rm_bits = reg_to_bits(rm) as u16;
2132
2133 if rd_bits < 8 && rm_bits < 8 {
2134 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2136 Ok(instr.to_le_bytes().to_vec())
2137 } else {
2138 let rd_bits32 = rd_bits as u32;
2141 let rm_bits32 = rm_bits as u32;
2142 let hw1: u16 = 0xFA4F;
2143 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2144 let mut bytes = hw1.to_le_bytes().to_vec();
2145 bytes.extend_from_slice(&hw2.to_le_bytes());
2146 Ok(bytes)
2147 }
2148 }
2149
2150 ArmOp::Sxth { rd, rm } => {
2152 let rd_bits = reg_to_bits(rd) as u16;
2153 let rm_bits = reg_to_bits(rm) as u16;
2154
2155 if rd_bits < 8 && rm_bits < 8 {
2156 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2158 Ok(instr.to_le_bytes().to_vec())
2159 } else {
2160 let rd_bits32 = rd_bits as u32;
2163 let rm_bits32 = rm_bits as u32;
2164 let hw1: u16 = 0xFA0F;
2165 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2166 let mut bytes = hw1.to_le_bytes().to_vec();
2167 bytes.extend_from_slice(&hw2.to_le_bytes());
2168 Ok(bytes)
2169 }
2170 }
2171
2172 ArmOp::Cmp { rn, op2 } => {
2174 let rn_bits = reg_to_bits(rn) as u16;
2175
2176 if let Operand2::Imm(imm) = op2 {
2177 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2180 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2182 Ok(instr.to_le_bytes().to_vec())
2183 } else {
2184 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2185 }
2186 } else if let Operand2::Reg(rm) = op2 {
2187 let rm_bits = reg_to_bits(rm) as u16;
2188 if rn_bits < 8 && rm_bits < 8 {
2189 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2191 Ok(instr.to_le_bytes().to_vec())
2192 } else {
2193 let n_bit = (rn_bits >> 3) & 1;
2195 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2196 Ok(instr.to_le_bytes().to_vec())
2197 }
2198 } else {
2199 let instr: u16 = 0xBF00;
2200 Ok(instr.to_le_bytes().to_vec())
2201 }
2202 }
2203
2204 ArmOp::Cmn { rn, op2 } => {
2207 let rn_bits = reg_to_bits(rn) as u16;
2208
2209 if let Operand2::Imm(imm) = op2 {
2210 let field = try_thumb_expand_imm(*imm as u32).ok_or_else(|| {
2216 synth_core::Error::synthesis(
2217 "CMN immediate is not a valid ThumbExpandImm — materialize into a register",
2218 )
2219 })?;
2220 let i_bit = (field >> 11) & 1;
2221 let imm3 = (field >> 8) & 0x7;
2222 let imm8 = field & 0xFF;
2223 let hw1: u16 = (0xF110 | (i_bit << 10) as u16) | rn_bits;
2224 let hw2: u16 = (imm3 << 12) as u16 | 0x0F00 | imm8 as u16;
2225 let mut bytes = hw1.to_le_bytes().to_vec();
2226 bytes.extend_from_slice(&hw2.to_le_bytes());
2227 Ok(bytes)
2228 } else if let Operand2::Reg(rm) = op2 {
2229 let rm_bits = reg_to_bits(rm) as u16;
2230 if rn_bits < 8 && rm_bits < 8 {
2236 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2238 Ok(instr.to_le_bytes().to_vec())
2239 } else {
2240 let hw1: u16 = 0xEB10 | rn_bits;
2241 let hw2: u16 = 0x0F00 | rm_bits;
2242 let mut bytes = hw1.to_le_bytes().to_vec();
2243 bytes.extend_from_slice(&hw2.to_le_bytes());
2244 Ok(bytes)
2245 }
2246 } else {
2247 Ok(vec![0xBF, 0x00])
2248 }
2249 }
2250
2251 ArmOp::Ldr { rd, addr } => {
2253 let rd_bits = reg_to_bits(rd);
2254 let base_bits = reg_to_bits(&addr.base);
2255
2256 if let Some(offset_reg) = &addr.offset_reg {
2258 let rm_bits = reg_to_bits(offset_reg);
2259
2260 if addr.offset != 0 {
2262 let scratch = Reg::R12;
2265 let mut bytes =
2266 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2267 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2268 return Ok(bytes);
2269 }
2270
2271 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2274 let instr: u16 = 0x5800
2276 | ((rm_bits as u16) << 6)
2277 | ((base_bits as u16) << 3)
2278 | (rd_bits as u16);
2279 return Ok(instr.to_le_bytes().to_vec());
2280 }
2281
2282 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2284 }
2285
2286 let offset = addr.offset as u32;
2288
2289 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2290 let imm5 = (offset >> 2) as u16;
2292 let instr: u16 =
2293 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2294 Ok(instr.to_le_bytes().to_vec())
2295 } else {
2296 self.encode_thumb32_ldr(rd, &addr.base, offset)
2297 }
2298 }
2299
2300 ArmOp::Str { rd, addr } => {
2302 let rd_bits = reg_to_bits(rd);
2303 let base_bits = reg_to_bits(&addr.base);
2304
2305 if let Some(offset_reg) = &addr.offset_reg {
2307 let rm_bits = reg_to_bits(offset_reg);
2308
2309 if addr.offset != 0 {
2311 let scratch = Reg::R12;
2314 let mut bytes =
2315 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2316 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2317 return Ok(bytes);
2318 }
2319
2320 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2323 let instr: u16 = 0x5000
2325 | ((rm_bits as u16) << 6)
2326 | ((base_bits as u16) << 3)
2327 | (rd_bits as u16);
2328 return Ok(instr.to_le_bytes().to_vec());
2329 }
2330
2331 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2333 }
2334
2335 let offset = addr.offset as u32;
2337
2338 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2339 let imm5 = (offset >> 2) as u16;
2341 let instr: u16 =
2342 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2343 Ok(instr.to_le_bytes().to_vec())
2344 } else {
2345 self.encode_thumb32_str(rd, &addr.base, offset)
2346 }
2347 }
2348
2349 ArmOp::Ldrb { rd, addr } => {
2351 let rd_bits = reg_to_bits(rd);
2352 let base_bits = reg_to_bits(&addr.base);
2353
2354 if let Some(offset_reg) = &addr.offset_reg {
2355 if addr.offset != 0 {
2356 let scratch = Reg::R12;
2357 let mut bytes =
2358 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2359 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2360 return Ok(bytes);
2361 }
2362 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2363 }
2364
2365 let offset = addr.offset as u32;
2366 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2367 let instr: u16 = 0x7800
2369 | ((offset as u16) << 6)
2370 | ((base_bits as u16) << 3)
2371 | (rd_bits as u16);
2372 Ok(instr.to_le_bytes().to_vec())
2373 } else {
2374 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2375 }
2376 }
2377
2378 ArmOp::Ldrsb { rd, addr } => {
2380 let rd_bits = reg_to_bits(rd);
2381 let base_bits = reg_to_bits(&addr.base);
2382
2383 if let Some(offset_reg) = &addr.offset_reg {
2384 if addr.offset != 0 {
2385 let scratch = Reg::R12;
2386 let mut bytes =
2387 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2388 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2389 return Ok(bytes);
2390 }
2391 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2392 }
2393
2394 let offset = addr.offset as u32;
2395 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2398 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2400 } else {
2401 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2402 }
2403 }
2404
2405 ArmOp::Ldrh { rd, addr } => {
2407 let rd_bits = reg_to_bits(rd);
2408 let base_bits = reg_to_bits(&addr.base);
2409
2410 if let Some(offset_reg) = &addr.offset_reg {
2411 if addr.offset != 0 {
2412 let scratch = Reg::R12;
2413 let mut bytes =
2414 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2415 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2416 return Ok(bytes);
2417 }
2418 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2419 }
2420
2421 let offset = addr.offset as u32;
2422 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2423 let imm5 = (offset >> 1) as u16;
2425 let instr: u16 =
2426 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2427 Ok(instr.to_le_bytes().to_vec())
2428 } else {
2429 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2430 }
2431 }
2432
2433 ArmOp::Ldrsh { rd, addr } => {
2435 if let Some(offset_reg) = &addr.offset_reg {
2436 if addr.offset != 0 {
2437 let scratch = Reg::R12;
2438 let mut bytes =
2439 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2440 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2441 return Ok(bytes);
2442 }
2443 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2444 }
2445
2446 let offset = addr.offset as u32;
2447 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2448 }
2449
2450 ArmOp::Strb { rd, addr } => {
2452 let rd_bits = reg_to_bits(rd);
2453 let base_bits = reg_to_bits(&addr.base);
2454
2455 if let Some(offset_reg) = &addr.offset_reg {
2456 if addr.offset != 0 {
2457 let scratch = Reg::R12;
2458 let mut bytes =
2459 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2460 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2461 return Ok(bytes);
2462 }
2463 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2464 }
2465
2466 let offset = addr.offset as u32;
2467 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2468 let instr: u16 = 0x7000
2470 | ((offset as u16) << 6)
2471 | ((base_bits as u16) << 3)
2472 | (rd_bits as u16);
2473 Ok(instr.to_le_bytes().to_vec())
2474 } else {
2475 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2476 }
2477 }
2478
2479 ArmOp::Strh { rd, addr } => {
2481 let rd_bits = reg_to_bits(rd);
2482 let base_bits = reg_to_bits(&addr.base);
2483
2484 if let Some(offset_reg) = &addr.offset_reg {
2485 if addr.offset != 0 {
2486 let scratch = Reg::R12;
2487 let mut bytes =
2488 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2489 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2490 return Ok(bytes);
2491 }
2492 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2493 }
2494
2495 let offset = addr.offset as u32;
2496 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2497 let imm5 = (offset >> 1) as u16;
2499 let instr: u16 =
2500 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2501 Ok(instr.to_le_bytes().to_vec())
2502 } else {
2503 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2504 }
2505 }
2506
2507 ArmOp::MemorySize { rd } => {
2509 let rd_bits = reg_to_bits(rd);
2512 let r10_bits = reg_to_bits(&Reg::R10);
2513 if rd_bits < 8 && r10_bits < 8 {
2514 let instr: u16 =
2515 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2516 Ok(instr.to_le_bytes().to_vec())
2517 } else {
2518 let imm5: u32 = 16;
2520 let imm3 = (imm5 >> 2) & 0x7;
2521 let imm2 = imm5 & 0x3;
2522 let hw1: u16 = 0xEA4F;
2523 let hw2: u16 =
2524 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2525 let mut bytes = hw1.to_le_bytes().to_vec();
2526 bytes.extend_from_slice(&hw2.to_le_bytes());
2527 Ok(bytes)
2528 }
2529 }
2530
2531 ArmOp::MemoryGrow { rd, .. } => {
2533 let rd_bits = reg_to_bits(rd);
2537 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2540 bytes.extend_from_slice(&hw2.to_le_bytes());
2541 Ok(bytes)
2542 }
2543
2544 ArmOp::Bx { rm } => {
2546 let rm_bits = reg_to_bits(rm) as u16;
2547 let instr: u16 = 0x4700 | (rm_bits << 3);
2549 Ok(instr.to_le_bytes().to_vec())
2550 }
2551
2552 ArmOp::Blx { rm } => {
2555 let rm_bits = reg_to_bits(rm) as u16;
2556 let instr: u16 = 0x4780 | (rm_bits << 3);
2557 Ok(instr.to_le_bytes().to_vec())
2558 }
2559
2560 ArmOp::CallIndirect {
2564 rd: _,
2565 type_idx: _,
2566 table_index_reg,
2567 } => {
2568 let idx_reg = reg_to_bits(table_index_reg);
2569 let mut bytes = Vec::new();
2570
2571 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2587 bytes.extend_from_slice(&hw1.to_le_bytes());
2588 bytes.extend_from_slice(&hw2.to_le_bytes());
2589
2590 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2596 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2597
2598 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2602
2603 Ok(bytes)
2604 }
2605
2606 ArmOp::Label { .. } => Ok(Vec::new()),
2608
2609 ArmOp::Bcc { cond, label: _ } => {
2611 use synth_synthesis::Condition;
2612 let cond_bits: u16 = match cond {
2613 Condition::EQ => 0x0,
2614 Condition::NE => 0x1,
2615 Condition::HS => 0x2,
2616 Condition::LO => 0x3,
2617 Condition::HI => 0x8,
2618 Condition::LS => 0x9,
2619 Condition::GE => 0xA,
2620 Condition::LT => 0xB,
2621 Condition::GT => 0xC,
2622 Condition::LE => 0xD,
2623 };
2624 let instr: u16 = 0xD000 | (cond_bits << 8);
2626 Ok(instr.to_le_bytes().to_vec())
2627 }
2628
2629 ArmOp::B { label: _ } => {
2631 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2635 }
2636
2637 ArmOp::Bhs { label: _ } => {
2640 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2644 }
2645
2646 ArmOp::Blo { label: _ } => {
2649 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2653 }
2654
2655 ArmOp::BOffset { offset } => {
2658 let halfword_offset = *offset;
2661
2662 if (-1024..=1022).contains(&halfword_offset) {
2665 let imm11 = (halfword_offset as u16) & 0x7FF;
2667 let instr: u16 = 0xE000 | imm11;
2668 Ok(instr.to_le_bytes().to_vec())
2669 } else {
2670 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2686 let uoffset = signed_offset as u32;
2687 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;
2695 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2696
2697 let mut bytes = hw1.to_le_bytes().to_vec();
2698 bytes.extend_from_slice(&hw2.to_le_bytes());
2699 Ok(bytes)
2700 }
2701 }
2702
2703 ArmOp::BCondOffset { cond, offset } => {
2705 use synth_synthesis::Condition;
2706 let cond_bits: u16 = match cond {
2707 Condition::EQ => 0x0,
2708 Condition::NE => 0x1,
2709 Condition::HS => 0x2,
2710 Condition::LO => 0x3,
2711 Condition::HI => 0x8,
2712 Condition::LS => 0x9,
2713 Condition::GE => 0xA,
2714 Condition::LT => 0xB,
2715 Condition::GT => 0xC,
2716 Condition::LE => 0xD,
2717 };
2718
2719 let halfword_offset = *offset;
2722
2723 if (-128..=127).contains(&halfword_offset) {
2726 let imm8 = (halfword_offset as u16) & 0xFF;
2727 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2728 Ok(instr.to_le_bytes().to_vec())
2729 } else {
2730 let offset = halfword_offset >> 1;
2734 let s = if offset < 0 { 1u32 } else { 0u32 };
2735 let imm6 = ((offset >> 11) as u32) & 0x3F;
2736 let imm11 = (offset as u32) & 0x7FF;
2737 let j1 = if s == 1 { 1 } else { 0 };
2738 let j2 = if s == 1 { 1 } else { 0 };
2739
2740 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2741 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2742
2743 let mut bytes = hw1.to_le_bytes().to_vec();
2744 bytes.extend_from_slice(&hw2.to_le_bytes());
2745 Ok(bytes)
2746 }
2747 }
2748
2749 ArmOp::Bl { label: _ } => {
2750 let hw1: u16 = 0xF7FF;
2765 let hw2: u16 = 0xFFFE;
2766 let mut bytes = hw1.to_le_bytes().to_vec();
2767 bytes.extend_from_slice(&hw2.to_le_bytes());
2768 Ok(bytes)
2769 }
2770
2771 ArmOp::Mvn { rd, op2 } => {
2773 if let Operand2::Reg(rm) = op2 {
2774 let rd_bits = reg_to_bits(rd) as u16;
2775 let rm_bits = reg_to_bits(rm) as u16;
2776
2777 if rd_bits < 8 && rm_bits < 8 {
2778 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2780 Ok(instr.to_le_bytes().to_vec())
2781 } else {
2782 let hw1: u16 = 0xEA6F_u16;
2784 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2785 let mut bytes = hw1.to_le_bytes().to_vec();
2786 bytes.extend_from_slice(&hw2.to_le_bytes());
2787 Ok(bytes)
2788 }
2789 } else {
2790 let instr: u16 = 0xBF00;
2791 Ok(instr.to_le_bytes().to_vec())
2792 }
2793 }
2794
2795 ArmOp::Movw { rd, imm16 } => {
2797 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2798 }
2799
2800 ArmOp::Movt { rd, imm16 } => {
2802 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2803 }
2804
2805 ArmOp::MovwSym { rd, addend, .. } => {
2810 self.encode_thumb32_movw_raw(reg_to_bits(rd), (*addend as u32) & 0xffff)
2811 }
2812 ArmOp::MovtSym { rd, addend, .. } => {
2813 self.encode_thumb32_movt_raw(reg_to_bits(rd), ((*addend as u32) >> 16) & 0xffff)
2814 }
2815
2816 ArmOp::SetCond { rd, cond } => {
2822 let rd_bits = reg_to_bits(rd) as u16;
2823
2824 use synth_synthesis::Condition;
2826 let cond_bits: u16 = match cond {
2827 Condition::EQ => 0x0,
2828 Condition::NE => 0x1,
2829 Condition::LT => 0xB,
2830 Condition::LE => 0xD,
2831 Condition::GT => 0xC,
2832 Condition::GE => 0xA,
2833 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2838
2839 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2844 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2845
2846 let mut bytes = ite_instr.to_le_bytes().to_vec();
2857 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2858 if rd_bits <= 7 {
2859 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2861 } else {
2862 let hw1: u16 = 0xF04F;
2864 let hw2: u16 = (rd_bits << 8) | imm;
2865 bytes.extend_from_slice(&hw1.to_le_bytes());
2866 bytes.extend_from_slice(&hw2.to_le_bytes());
2867 }
2868 };
2869 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2872 }
2873
2874 ArmOp::I64SetCond {
2879 rd,
2880 rn_lo,
2881 rn_hi,
2882 rm_lo,
2883 rm_hi,
2884 cond,
2885 } => {
2886 use synth_synthesis::Condition;
2887 let rd_bits = reg_to_bits(rd) as u16;
2888 let mut bytes = Vec::new();
2889
2890 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2892 rm: &synth_synthesis::Reg|
2893 -> Vec<u8> {
2894 let rn_bits = reg_to_bits(rn) as u16;
2895 let rm_bits = reg_to_bits(rm) as u16;
2896 if rn_bits < 8 && rm_bits < 8 {
2897 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2898 instr.to_le_bytes().to_vec()
2899 } else {
2900 let n_bit = (rn_bits >> 3) & 1;
2901 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2902 instr.to_le_bytes().to_vec()
2903 }
2904 };
2905
2906 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2908 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2909 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2910 ite_instr.to_le_bytes().to_vec()
2911 };
2912
2913 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2915 let mut b = encode_ite(cond_bits);
2916 if rd_bits < 8 {
2917 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2918 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2919 b.extend_from_slice(&mov_one.to_le_bytes());
2920 b.extend_from_slice(&mov_zero.to_le_bytes());
2921 } else {
2922 for imm in [1u16, 0u16] {
2930 let hw1: u16 = 0xF04F;
2931 let hw2: u16 = (rd_bits << 8) | imm;
2932 b.extend_from_slice(&hw1.to_le_bytes());
2933 b.extend_from_slice(&hw2.to_le_bytes());
2934 }
2935 }
2936 b
2937 };
2938
2939 match cond {
2940 Condition::EQ | Condition::NE => {
2941 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2943
2944 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2947
2948 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2950
2951 let cond_bits: u16 = match cond {
2953 Condition::EQ => 0x0,
2954 Condition::NE => 0x1,
2955 _ => unreachable!(),
2956 };
2957 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2958 }
2959
2960 Condition::LT => {
2961 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2963
2964 let rn_hi_bits = reg_to_bits(rn_hi);
2967 let rm_hi_bits = reg_to_bits(rm_hi);
2968 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2969 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2970 bytes.extend_from_slice(&hw1.to_le_bytes());
2971 bytes.extend_from_slice(&hw2.to_le_bytes());
2972
2973 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2976
2977 Condition::GT => {
2978 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2981
2982 let rm_hi_bits = reg_to_bits(rm_hi);
2984 let rn_hi_bits = reg_to_bits(rn_hi);
2985 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2986 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2987 bytes.extend_from_slice(&hw1.to_le_bytes());
2988 bytes.extend_from_slice(&hw2.to_le_bytes());
2989
2990 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2993
2994 Condition::LE => {
2995 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2999
3000 let rm_hi_bits = reg_to_bits(rm_hi);
3002 let rn_hi_bits = reg_to_bits(rn_hi);
3003 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3004 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3005 bytes.extend_from_slice(&hw1.to_le_bytes());
3006 bytes.extend_from_slice(&hw2.to_le_bytes());
3007
3008 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3011
3012 Condition::GE => {
3013 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3016
3017 let rn_hi_bits = reg_to_bits(rn_hi);
3019 let rm_hi_bits = reg_to_bits(rm_hi);
3020 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3021 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3022 bytes.extend_from_slice(&hw1.to_le_bytes());
3023 bytes.extend_from_slice(&hw2.to_le_bytes());
3024
3025 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3028
3029 Condition::LO => {
3031 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3033 let rn_hi_bits = reg_to_bits(rn_hi);
3034 let rm_hi_bits = reg_to_bits(rm_hi);
3035 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3036 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3037 bytes.extend_from_slice(&hw1.to_le_bytes());
3038 bytes.extend_from_slice(&hw2.to_le_bytes());
3039 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3041
3042 Condition::HI => {
3043 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3045 let rm_hi_bits = reg_to_bits(rm_hi);
3046 let rn_hi_bits = reg_to_bits(rn_hi);
3047 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3048 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3049 bytes.extend_from_slice(&hw1.to_le_bytes());
3050 bytes.extend_from_slice(&hw2.to_le_bytes());
3051 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3053
3054 Condition::LS => {
3055 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3057 let rm_hi_bits = reg_to_bits(rm_hi);
3058 let rn_hi_bits = reg_to_bits(rn_hi);
3059 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3060 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3061 bytes.extend_from_slice(&hw1.to_le_bytes());
3062 bytes.extend_from_slice(&hw2.to_le_bytes());
3063 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3065
3066 Condition::HS => {
3067 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3069 let rn_hi_bits = reg_to_bits(rn_hi);
3070 let rm_hi_bits = reg_to_bits(rm_hi);
3071 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3072 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3073 bytes.extend_from_slice(&hw1.to_le_bytes());
3074 bytes.extend_from_slice(&hw2.to_le_bytes());
3075 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3077 }
3078
3079 Ok(bytes)
3080 }
3081
3082 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
3085 let rd_bits = reg_to_bits(rd);
3086 let rn_lo_bits = reg_to_bits(rn_lo);
3087 let rn_hi_bits = reg_to_bits(rn_hi);
3088 let mut bytes = Vec::new();
3089
3090 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3092 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3093 bytes.extend_from_slice(&hw1.to_le_bytes());
3094 bytes.extend_from_slice(&hw2.to_le_bytes());
3095
3096 if rd_bits < 8 {
3101 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3102 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3103 } else {
3104 let hw1: u16 = 0xF1B0 | (rd_bits as u16);
3105 let hw2: u16 = 0x0F00;
3106 bytes.extend_from_slice(&hw1.to_le_bytes());
3107 bytes.extend_from_slice(&hw2.to_le_bytes());
3108 }
3109
3110 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3114 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3115 if rd_bits < 8 {
3116 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3117 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3118 bytes.extend_from_slice(&mov_one.to_le_bytes());
3119 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3120 } else {
3121 for imm in [1u16, 0u16] {
3122 let hw1: u16 = 0xF04F;
3123 let hw2: u16 = ((rd_bits as u16) << 8) | imm;
3124 bytes.extend_from_slice(&hw1.to_le_bytes());
3125 bytes.extend_from_slice(&hw2.to_le_bytes());
3126 }
3127 }
3128
3129 Ok(bytes)
3130 }
3131
3132 ArmOp::I64Mul {
3136 rd_lo,
3137 rd_hi,
3138 rn_lo,
3139 rn_hi,
3140 rm_lo,
3141 rm_hi,
3142 } => {
3143 let rd_lo_bits = reg_to_bits(rd_lo);
3144 let rd_hi_bits = reg_to_bits(rd_hi);
3145 let rn_lo_bits = reg_to_bits(rn_lo);
3146 let rn_hi_bits = reg_to_bits(rn_hi);
3147 let rm_lo_bits = reg_to_bits(rm_lo);
3148 let rm_hi_bits = reg_to_bits(rm_hi);
3149 let r12: u32 = 12; let mut bytes = Vec::new();
3151
3152 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3155 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_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 = (0xFB00 | rn_hi_bits) as u16;
3162 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3163 bytes.extend_from_slice(&hw1.to_le_bytes());
3164 bytes.extend_from_slice(&hw2.to_le_bytes());
3165
3166 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3169 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3170 bytes.extend_from_slice(&hw1.to_le_bytes());
3171 bytes.extend_from_slice(&hw2.to_le_bytes());
3172
3173 let d_bit = (rd_hi_bits >> 3) & 1;
3176 let add_instr: u16 =
3177 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3178 bytes.extend_from_slice(&add_instr.to_le_bytes());
3179
3180 Ok(bytes)
3181 }
3182
3183 ArmOp::I64Shl {
3186 rd_lo,
3187 rd_hi,
3188 rn_lo,
3189 rn_hi,
3190 rm_lo,
3191 rm_hi,
3192 } => {
3193 let rd_lo_bits = reg_to_bits(rd_lo);
3194 let rd_hi_bits = reg_to_bits(rd_hi);
3195 let rn_lo_bits = reg_to_bits(rn_lo);
3196 let rn_hi_bits = reg_to_bits(rn_hi);
3197 let rm_lo_bits = reg_to_bits(rm_lo);
3198 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3200
3201 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3203 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3204 bytes.extend_from_slice(&hw1.to_le_bytes());
3205 bytes.extend_from_slice(&hw2.to_le_bytes());
3206
3207 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3209 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3210 bytes.extend_from_slice(&hw1.to_le_bytes());
3211 bytes.extend_from_slice(&hw2.to_le_bytes());
3212
3213 let bpl: u16 = 0xD50A;
3215 bytes.extend_from_slice(&bpl.to_le_bytes());
3216
3217 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3220 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3221 bytes.extend_from_slice(&hw1.to_le_bytes());
3222 bytes.extend_from_slice(&hw2.to_le_bytes());
3223
3224 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3226 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3227 bytes.extend_from_slice(&hw1.to_le_bytes());
3228 bytes.extend_from_slice(&hw2.to_le_bytes());
3229
3230 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3232 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3233 bytes.extend_from_slice(&hw1.to_le_bytes());
3234 bytes.extend_from_slice(&hw2.to_le_bytes());
3235
3236 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3238 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3239 bytes.extend_from_slice(&hw1.to_le_bytes());
3240 bytes.extend_from_slice(&hw2.to_le_bytes());
3241
3242 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3244 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3245 bytes.extend_from_slice(&hw1.to_le_bytes());
3246 bytes.extend_from_slice(&hw2.to_le_bytes());
3247
3248 let b_done: u16 = 0xE002;
3250 bytes.extend_from_slice(&b_done.to_le_bytes());
3251
3252 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3255 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3256 bytes.extend_from_slice(&hw1.to_le_bytes());
3257 bytes.extend_from_slice(&hw2.to_le_bytes());
3258
3259 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3261 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3262
3263 Ok(bytes) }
3265
3266 ArmOp::I64ShrU {
3268 rd_lo,
3269 rd_hi,
3270 rn_lo,
3271 rn_hi,
3272 rm_lo,
3273 rm_hi,
3274 } => {
3275 let rd_lo_bits = reg_to_bits(rd_lo);
3276 let rd_hi_bits = reg_to_bits(rd_hi);
3277 let rn_lo_bits = reg_to_bits(rn_lo);
3278 let rn_hi_bits = reg_to_bits(rn_hi);
3279 let rm_lo_bits = reg_to_bits(rm_lo);
3280 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3282
3283 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3285 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3286 bytes.extend_from_slice(&hw1.to_le_bytes());
3287 bytes.extend_from_slice(&hw2.to_le_bytes());
3288
3289 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3291 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3292 bytes.extend_from_slice(&hw1.to_le_bytes());
3293 bytes.extend_from_slice(&hw2.to_le_bytes());
3294
3295 let bpl: u16 = 0xD50A;
3297 bytes.extend_from_slice(&bpl.to_le_bytes());
3298
3299 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3302 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3303 bytes.extend_from_slice(&hw1.to_le_bytes());
3304 bytes.extend_from_slice(&hw2.to_le_bytes());
3305
3306 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3308 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3309 bytes.extend_from_slice(&hw1.to_le_bytes());
3310 bytes.extend_from_slice(&hw2.to_le_bytes());
3311
3312 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3314 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3315 bytes.extend_from_slice(&hw1.to_le_bytes());
3316 bytes.extend_from_slice(&hw2.to_le_bytes());
3317
3318 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3320 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3321 bytes.extend_from_slice(&hw1.to_le_bytes());
3322 bytes.extend_from_slice(&hw2.to_le_bytes());
3323
3324 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3326 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3327 bytes.extend_from_slice(&hw1.to_le_bytes());
3328 bytes.extend_from_slice(&hw2.to_le_bytes());
3329
3330 let b_done: u16 = 0xE002;
3332 bytes.extend_from_slice(&b_done.to_le_bytes());
3333
3334 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3337 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3338 bytes.extend_from_slice(&hw1.to_le_bytes());
3339 bytes.extend_from_slice(&hw2.to_le_bytes());
3340
3341 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3343 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3344
3345 Ok(bytes) }
3347
3348 ArmOp::I64ShrS {
3350 rd_lo,
3351 rd_hi,
3352 rn_lo,
3353 rn_hi,
3354 rm_lo,
3355 rm_hi,
3356 } => {
3357 let rd_lo_bits = reg_to_bits(rd_lo);
3358 let rd_hi_bits = reg_to_bits(rd_hi);
3359 let rn_lo_bits = reg_to_bits(rn_lo);
3360 let rn_hi_bits = reg_to_bits(rn_hi);
3361 let rm_lo_bits = reg_to_bits(rm_lo);
3362 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3364
3365 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3367 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3368 bytes.extend_from_slice(&hw1.to_le_bytes());
3369 bytes.extend_from_slice(&hw2.to_le_bytes());
3370
3371 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3373 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3374 bytes.extend_from_slice(&hw1.to_le_bytes());
3375 bytes.extend_from_slice(&hw2.to_le_bytes());
3376
3377 let bpl: u16 = 0xD50A;
3379 bytes.extend_from_slice(&bpl.to_le_bytes());
3380
3381 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3384 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3385 bytes.extend_from_slice(&hw1.to_le_bytes());
3386 bytes.extend_from_slice(&hw2.to_le_bytes());
3387
3388 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3390 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3391 bytes.extend_from_slice(&hw1.to_le_bytes());
3392 bytes.extend_from_slice(&hw2.to_le_bytes());
3393
3394 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3396 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3397 bytes.extend_from_slice(&hw1.to_le_bytes());
3398 bytes.extend_from_slice(&hw2.to_le_bytes());
3399
3400 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3402 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3403 bytes.extend_from_slice(&hw1.to_le_bytes());
3404 bytes.extend_from_slice(&hw2.to_le_bytes());
3405
3406 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3408 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3409 bytes.extend_from_slice(&hw1.to_le_bytes());
3410 bytes.extend_from_slice(&hw2.to_le_bytes());
3411
3412 let b_done: u16 = 0xE003;
3414 bytes.extend_from_slice(&b_done.to_le_bytes());
3415
3416 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3419 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3420 bytes.extend_from_slice(&hw1.to_le_bytes());
3421 bytes.extend_from_slice(&hw2.to_le_bytes());
3422
3423 let hw1: u16 = 0xEA4F;
3427 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3428 bytes.extend_from_slice(&hw1.to_le_bytes());
3429 bytes.extend_from_slice(&hw2.to_le_bytes());
3430
3431 Ok(bytes) }
3433
3434 ArmOp::I64Rotl {
3439 rdlo,
3440 rdhi,
3441 rnlo,
3442 rnhi,
3443 shift,
3444 } => {
3445 let rd_lo_bits = reg_to_bits(rdlo);
3446 let rd_hi_bits = reg_to_bits(rdhi);
3447 let rn_lo_bits = reg_to_bits(rnlo);
3448 let rn_hi_bits = reg_to_bits(rnhi);
3449 let shift_bits = reg_to_bits(shift);
3450 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3454
3455 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3457
3458 let hw1: u16 = (0xF000 | shift_bits) as u16;
3460 let hw2: u16 = ((shift_bits << 8) | 0x3F) 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 = (0xF1B0 | shift_bits) as u16;
3466 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3467 bytes.extend_from_slice(&hw1.to_le_bytes());
3468 bytes.extend_from_slice(&hw2.to_le_bytes());
3469
3470 let bpl: u16 = 0xD50E;
3472 bytes.extend_from_slice(&bpl.to_le_bytes());
3473
3474 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3477 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3478 bytes.extend_from_slice(&hw1.to_le_bytes());
3479 bytes.extend_from_slice(&hw2.to_le_bytes());
3480
3481 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3483 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3484 bytes.extend_from_slice(&hw1.to_le_bytes());
3485 bytes.extend_from_slice(&hw2.to_le_bytes());
3486
3487 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3489 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3490 bytes.extend_from_slice(&hw1.to_le_bytes());
3491 bytes.extend_from_slice(&hw2.to_le_bytes());
3492
3493 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3495 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3496 bytes.extend_from_slice(&hw1.to_le_bytes());
3497 bytes.extend_from_slice(&hw2.to_le_bytes());
3498
3499 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3501 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3502 bytes.extend_from_slice(&hw1.to_le_bytes());
3503 bytes.extend_from_slice(&hw2.to_le_bytes());
3504
3505 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3507 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3508 bytes.extend_from_slice(&hw1.to_le_bytes());
3509 bytes.extend_from_slice(&hw2.to_le_bytes());
3510
3511 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3513 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3514 bytes.extend_from_slice(&hw1.to_le_bytes());
3515 bytes.extend_from_slice(&hw2.to_le_bytes());
3516
3517 let b_done: u16 = 0xE00E;
3519 bytes.extend_from_slice(&b_done.to_le_bytes());
3520
3521 let hw1: u16 = (0xF1C0 | r3) as u16;
3525 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3526 bytes.extend_from_slice(&hw1.to_le_bytes());
3527 bytes.extend_from_slice(&hw2.to_le_bytes());
3528
3529 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3531 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3532 bytes.extend_from_slice(&hw1.to_le_bytes());
3533 bytes.extend_from_slice(&hw2.to_le_bytes());
3534
3535 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3537 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3538 bytes.extend_from_slice(&hw1.to_le_bytes());
3539 bytes.extend_from_slice(&hw2.to_le_bytes());
3540
3541 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3543 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) 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 = (0xEA40 | shift_bits) as u16;
3549 let hw2: u16 = ((shift_bits << 8) | r12) 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_hi_bits) as u16;
3555 let hw2: u16 = (0xF000 | (rd_lo_bits << 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 = (0xEA40 | rd_lo_bits) as u16;
3561 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3562 bytes.extend_from_slice(&hw1.to_le_bytes());
3563 bytes.extend_from_slice(&hw2.to_le_bytes());
3564
3565 let d_bit = (rd_hi_bits >> 3) & 1;
3567 let mov_instr: u16 =
3568 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3569 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3570
3571 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3573
3574 Ok(bytes) }
3576
3577 ArmOp::I64Rotr {
3582 rdlo,
3583 rdhi,
3584 rnlo,
3585 rnhi,
3586 shift,
3587 } => {
3588 let rd_lo_bits = reg_to_bits(rdlo);
3589 let rd_hi_bits = reg_to_bits(rdhi);
3590 let rn_lo_bits = reg_to_bits(rnlo);
3591 let rn_hi_bits = reg_to_bits(rnhi);
3592 let shift_bits = reg_to_bits(shift);
3593 let r12: u32 = 12;
3594 let r3: u32 = 3;
3595 let r4: u32 = 4;
3596 let mut bytes = Vec::new();
3597
3598 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3600
3601 let hw1: u16 = (0xF000 | shift_bits) as u16;
3603 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3604 bytes.extend_from_slice(&hw1.to_le_bytes());
3605 bytes.extend_from_slice(&hw2.to_le_bytes());
3606
3607 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3609 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3610 bytes.extend_from_slice(&hw1.to_le_bytes());
3611 bytes.extend_from_slice(&hw2.to_le_bytes());
3612
3613 let bpl: u16 = 0xD50E;
3615 bytes.extend_from_slice(&bpl.to_le_bytes());
3616
3617 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3620 let hw2: u16 = ((r3 << 8) | 0x20) 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 = (0xFA00 | rn_hi_bits) as u16;
3626 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3627 bytes.extend_from_slice(&hw1.to_le_bytes());
3628 bytes.extend_from_slice(&hw2.to_le_bytes());
3629
3630 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3632 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3633 bytes.extend_from_slice(&hw1.to_le_bytes());
3634 bytes.extend_from_slice(&hw2.to_le_bytes());
3635
3636 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3638 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3639 bytes.extend_from_slice(&hw1.to_le_bytes());
3640 bytes.extend_from_slice(&hw2.to_le_bytes());
3641
3642 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3644 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3645 bytes.extend_from_slice(&hw1.to_le_bytes());
3646 bytes.extend_from_slice(&hw2.to_le_bytes());
3647
3648 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3650 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3651 bytes.extend_from_slice(&hw1.to_le_bytes());
3652 bytes.extend_from_slice(&hw2.to_le_bytes());
3653
3654 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3656 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3657 bytes.extend_from_slice(&hw1.to_le_bytes());
3658 bytes.extend_from_slice(&hw2.to_le_bytes());
3659
3660 let b_done: u16 = 0xE00E;
3662 bytes.extend_from_slice(&b_done.to_le_bytes());
3663
3664 let hw1: u16 = (0xF1C0 | r3) as u16;
3667 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3668 bytes.extend_from_slice(&hw1.to_le_bytes());
3669 bytes.extend_from_slice(&hw2.to_le_bytes());
3670
3671 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3673 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3674 bytes.extend_from_slice(&hw1.to_le_bytes());
3675 bytes.extend_from_slice(&hw2.to_le_bytes());
3676
3677 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3679 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3680 bytes.extend_from_slice(&hw1.to_le_bytes());
3681 bytes.extend_from_slice(&hw2.to_le_bytes());
3682
3683 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3685 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3686 bytes.extend_from_slice(&hw1.to_le_bytes());
3687 bytes.extend_from_slice(&hw2.to_le_bytes());
3688
3689 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3691 let hw2: u16 = ((shift_bits << 8) | r12) 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 = (0xFA20 | rn_lo_bits) as u16;
3697 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3698 bytes.extend_from_slice(&hw1.to_le_bytes());
3699 bytes.extend_from_slice(&hw2.to_le_bytes());
3700
3701 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3703 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3704 bytes.extend_from_slice(&hw1.to_le_bytes());
3705 bytes.extend_from_slice(&hw2.to_le_bytes());
3706
3707 let d_bit = (rd_lo_bits >> 3) & 1;
3709 let mov_instr: u16 =
3710 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3711 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3712
3713 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3715
3716 Ok(bytes) }
3718
3719 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3733 let rd_bits = reg_to_bits(rd);
3734 let rn_lo_bits = reg_to_bits(rnlo);
3735 let rn_hi_bits = reg_to_bits(rnhi);
3736 let mut bytes = Vec::new();
3737
3738 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3740 let hw2: u16 = 0x0F00;
3741 bytes.extend_from_slice(&hw1.to_le_bytes());
3742 bytes.extend_from_slice(&hw2.to_le_bytes());
3743
3744 let beq: u16 = 0xD003;
3747 bytes.extend_from_slice(&beq.to_le_bytes());
3748
3749 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3752 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_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 = 0xE004;
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 = (0xFAB0 | rn_lo_bits) as u16;
3768 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_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 = (0xF100 | rd_bits) as u16;
3774 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3775 bytes.extend_from_slice(&hw1.to_le_bytes());
3776 bytes.extend_from_slice(&hw2.to_le_bytes());
3777
3778 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3782 bytes.extend_from_slice(&mov0.to_le_bytes());
3783
3784 Ok(bytes)
3785 }
3786
3787 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3803 let rd_bits = reg_to_bits(rd);
3804 let rn_lo_bits = reg_to_bits(rnlo);
3805 let rn_hi_bits = reg_to_bits(rnhi);
3806 let mut bytes = Vec::new();
3807
3808 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3810 let hw2: u16 = 0x0F00;
3811 bytes.extend_from_slice(&hw1.to_le_bytes());
3812 bytes.extend_from_slice(&hw2.to_le_bytes());
3813
3814 let beq: u16 = 0xD005;
3817 bytes.extend_from_slice(&beq.to_le_bytes());
3818
3819 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3822 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3823 bytes.extend_from_slice(&hw1.to_le_bytes());
3824 bytes.extend_from_slice(&hw2.to_le_bytes());
3825
3826 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3829 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3830 bytes.extend_from_slice(&hw1.to_le_bytes());
3831 bytes.extend_from_slice(&hw2.to_le_bytes());
3832
3833 let b_done: u16 = 0xE006;
3836 bytes.extend_from_slice(&b_done.to_le_bytes());
3837
3838 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3840
3841 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3845 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3846 bytes.extend_from_slice(&hw1.to_le_bytes());
3847 bytes.extend_from_slice(&hw2.to_le_bytes());
3848
3849 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3852 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3853 bytes.extend_from_slice(&hw1.to_le_bytes());
3854 bytes.extend_from_slice(&hw2.to_le_bytes());
3855
3856 let hw1: u16 = (0xF100 | rd_bits) as u16;
3858 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3859 bytes.extend_from_slice(&hw1.to_le_bytes());
3860 bytes.extend_from_slice(&hw2.to_le_bytes());
3861
3862 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3865 bytes.extend_from_slice(&mov0.to_le_bytes());
3866
3867 Ok(bytes)
3868 }
3869
3870 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3874 let rd_bits = reg_to_bits(rd);
3875 let rn_lo_bits = reg_to_bits(rnlo);
3876 let rn_hi_bits = reg_to_bits(rnhi);
3877 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3880
3881 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3883
3884 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3894 bytes.extend_from_slice(&mov.to_le_bytes());
3895
3896 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3899 bytes.extend_from_slice(&mov.to_le_bytes());
3900
3901 let hw1: u16 = 0xEA4F;
3905 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3906 bytes.extend_from_slice(&hw1.to_le_bytes());
3907 bytes.extend_from_slice(&hw2.to_le_bytes());
3908
3909 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3912 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3913 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3915 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3916
3917 let hw1: u16 = (0xEA00 | r12) as u16;
3919 let hw2: u16 = ((r12 << 8) | r3) as u16;
3920 bytes.extend_from_slice(&hw1.to_le_bytes());
3921 bytes.extend_from_slice(&hw2.to_le_bytes());
3922
3923 let hw1: u16 = (0xEBA0 | 4) as u16;
3925 let hw2: u16 = ((4 << 8) | r12) as u16;
3926 bytes.extend_from_slice(&hw1.to_le_bytes());
3927 bytes.extend_from_slice(&hw2.to_le_bytes());
3928
3929 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3933 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3934 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3936 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3937
3938 let hw1: u16 = (0xEA00 | 4) as u16;
3940 let hw2: u16 = ((r12 << 8) | r3) as u16;
3941 bytes.extend_from_slice(&hw1.to_le_bytes());
3942 bytes.extend_from_slice(&hw2.to_le_bytes());
3943
3944 let hw1: u16 = 0xEA4F;
3946 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3947 bytes.extend_from_slice(&hw1.to_le_bytes());
3948 bytes.extend_from_slice(&hw2.to_le_bytes());
3949
3950 let hw1: u16 = (0xEA00 | 4) as u16;
3952 let hw2: u16 = ((4 << 8) | r3) as u16;
3953 bytes.extend_from_slice(&hw1.to_le_bytes());
3954 bytes.extend_from_slice(&hw2.to_le_bytes());
3955
3956 let hw1: u16 = (0xEB00 | 4) as u16;
3958 let hw2: u16 = ((4 << 8) | r12) as u16;
3959 bytes.extend_from_slice(&hw1.to_le_bytes());
3960 bytes.extend_from_slice(&hw2.to_le_bytes());
3961
3962 let hw1: u16 = 0xEA4F;
3967 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3968 bytes.extend_from_slice(&hw1.to_le_bytes());
3969 bytes.extend_from_slice(&hw2.to_le_bytes());
3970
3971 let hw1: u16 = (0xEB00 | 4) as u16;
3973 let hw2: u16 = ((4 << 8) | r12) as u16;
3974 bytes.extend_from_slice(&hw1.to_le_bytes());
3975 bytes.extend_from_slice(&hw2.to_le_bytes());
3976
3977 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3982 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3983 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3985 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3986
3987 let hw1: u16 = (0xEA00 | 4) as u16;
3989 let hw2: u16 = ((4 << 8) | r3) as u16;
3990 bytes.extend_from_slice(&hw1.to_le_bytes());
3991 bytes.extend_from_slice(&hw2.to_le_bytes());
3992
3993 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3997 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3998 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4000 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4001
4002 let hw1: u16 = (0xFB00 | 4) as u16;
4005 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
4006 bytes.extend_from_slice(&hw1.to_le_bytes());
4007 bytes.extend_from_slice(&hw2.to_le_bytes());
4008
4009 let hw1: u16 = 0xEA4F;
4012 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
4013 bytes.extend_from_slice(&hw1.to_le_bytes());
4014 bytes.extend_from_slice(&hw2.to_le_bytes());
4015
4016 let hw1: u16 = 0xEA4F;
4019 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
4020 bytes.extend_from_slice(&hw1.to_le_bytes());
4021 bytes.extend_from_slice(&hw2.to_le_bytes());
4022
4023 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
4025 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
4026 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
4027 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
4028
4029 let hw1: u16 = (0xEA00 | r12) as u16;
4030 let hw2: u16 = ((r12 << 8) | r3) as u16;
4031 bytes.extend_from_slice(&hw1.to_le_bytes());
4032 bytes.extend_from_slice(&hw2.to_le_bytes());
4033
4034 let hw1: u16 = (0xEBA0 | 5) as u16;
4035 let hw2: u16 = ((5 << 8) | r12) as u16;
4036 bytes.extend_from_slice(&hw1.to_le_bytes());
4037 bytes.extend_from_slice(&hw2.to_le_bytes());
4038
4039 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
4041 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4042 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
4043 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4044
4045 let hw1: u16 = (0xEA00 | 5) as u16;
4046 let hw2: u16 = ((r12 << 8) | r3) as u16;
4047 bytes.extend_from_slice(&hw1.to_le_bytes());
4048 bytes.extend_from_slice(&hw2.to_le_bytes());
4049
4050 let hw1: u16 = 0xEA4F;
4051 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
4052 bytes.extend_from_slice(&hw1.to_le_bytes());
4053 bytes.extend_from_slice(&hw2.to_le_bytes());
4054
4055 let hw1: u16 = (0xEA00 | 5) as u16;
4056 let hw2: u16 = ((5 << 8) | r3) as u16;
4057 bytes.extend_from_slice(&hw1.to_le_bytes());
4058 bytes.extend_from_slice(&hw2.to_le_bytes());
4059
4060 let hw1: u16 = (0xEB00 | 5) as u16;
4061 let hw2: u16 = ((5 << 8) | r12) as u16;
4062 bytes.extend_from_slice(&hw1.to_le_bytes());
4063 bytes.extend_from_slice(&hw2.to_le_bytes());
4064
4065 let hw1: u16 = 0xEA4F;
4068 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
4069 bytes.extend_from_slice(&hw1.to_le_bytes());
4070 bytes.extend_from_slice(&hw2.to_le_bytes());
4071
4072 let hw1: u16 = (0xEB00 | 5) as u16;
4073 let hw2: u16 = ((5 << 8) | r12) as u16;
4074 bytes.extend_from_slice(&hw1.to_le_bytes());
4075 bytes.extend_from_slice(&hw2.to_le_bytes());
4076
4077 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4079 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4080 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4081 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4082
4083 let hw1: u16 = (0xEA00 | 5) as u16;
4084 let hw2: u16 = ((5 << 8) | r3) as u16;
4085 bytes.extend_from_slice(&hw1.to_le_bytes());
4086 bytes.extend_from_slice(&hw2.to_le_bytes());
4087
4088 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4090 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4091 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4092 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4093
4094 let hw1: u16 = (0xFB00 | 5) as u16;
4097 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
4098 bytes.extend_from_slice(&hw1.to_le_bytes());
4099 bytes.extend_from_slice(&hw2.to_le_bytes());
4100
4101 let hw1: u16 = 0xEA4F;
4104 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
4105 bytes.extend_from_slice(&hw1.to_le_bytes());
4106 bytes.extend_from_slice(&hw2.to_le_bytes());
4107
4108 let rd_bits_u16 = rd_bits as u16;
4111 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4112 bytes.extend_from_slice(&instr.to_le_bytes());
4113
4114 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4116
4117 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4119 bytes.extend_from_slice(&mov0.to_le_bytes());
4120
4121 Ok(bytes)
4122 }
4123
4124 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4127 let rdlo_bits = reg_to_bits(rdlo);
4128 let rdhi_bits = reg_to_bits(rdhi);
4129 let rnlo_bits = reg_to_bits(rnlo);
4130 let mut bytes = Vec::new();
4131
4132 let hw1: u16 = 0xFA4F_u16;
4135 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4136 bytes.extend_from_slice(&hw1.to_le_bytes());
4137 bytes.extend_from_slice(&hw2.to_le_bytes());
4138
4139 let hw1: u16 = 0xEA4F;
4144 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4145 bytes.extend_from_slice(&hw1.to_le_bytes());
4146 bytes.extend_from_slice(&hw2.to_le_bytes());
4147
4148 Ok(bytes)
4149 }
4150
4151 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4154 let rdlo_bits = reg_to_bits(rdlo);
4155 let rdhi_bits = reg_to_bits(rdhi);
4156 let rnlo_bits = reg_to_bits(rnlo);
4157 let mut bytes = Vec::new();
4158
4159 let hw1: u16 = 0xFA0F_u16;
4162 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4163 bytes.extend_from_slice(&hw1.to_le_bytes());
4164 bytes.extend_from_slice(&hw2.to_le_bytes());
4165
4166 let hw1: u16 = 0xEA4F;
4168 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4169 bytes.extend_from_slice(&hw1.to_le_bytes());
4170 bytes.extend_from_slice(&hw2.to_le_bytes());
4171
4172 Ok(bytes)
4173 }
4174
4175 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4178 let rdlo_bits = reg_to_bits(rdlo);
4179 let rdhi_bits = reg_to_bits(rdhi);
4180 let rnlo_bits = reg_to_bits(rnlo);
4181 let mut bytes = Vec::new();
4182
4183 if rdlo_bits != rnlo_bits {
4185 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4187 let mov: u16 = 0x4600
4188 | (d_bit << 7)
4189 | ((rnlo_bits as u16) << 3)
4190 | ((rdlo_bits & 0x7) as u16);
4191 bytes.extend_from_slice(&mov.to_le_bytes());
4192 }
4193
4194 let hw1: u16 = 0xEA4F;
4196 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4197 bytes.extend_from_slice(&hw1.to_le_bytes());
4198 bytes.extend_from_slice(&hw2.to_le_bytes());
4199
4200 Ok(bytes)
4201 }
4202
4203 ArmOp::SelectMove { rd, rm, cond } => {
4206 let rd_bits = reg_to_bits(rd) as u16;
4207 let rm_bits = reg_to_bits(rm) as u16;
4208
4209 use synth_synthesis::Condition;
4211 let cond_bits: u16 = match cond {
4212 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, };
4223
4224 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4227
4228 let d_bit = (rd_bits >> 3) & 1;
4231 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4232
4233 let mut bytes = it_instr.to_le_bytes().to_vec();
4235 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4236 Ok(bytes)
4237 }
4238
4239 ArmOp::Popcnt { rd, rm } => {
4250 let mut bytes = Vec::new();
4251
4252 if rd != rm {
4254 let rd_bits = reg_to_bits(rd) as u16;
4255 let rm_bits = reg_to_bits(rm) as u16;
4256 let d_bit = (rd_bits >> 3) & 1;
4258 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4259 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4260 }
4261
4262 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4265 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4266
4267 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4270
4271 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4273
4274 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4276 reg_to_bits(rd),
4277 reg_to_bits(rd),
4278 11,
4279 )?);
4280
4281 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4284 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4285
4286 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4288 11,
4289 reg_to_bits(rd),
4290 12,
4291 )?);
4292
4293 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4295 reg_to_bits(rd),
4296 reg_to_bits(rd),
4297 2,
4298 )?);
4299
4300 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4302 reg_to_bits(rd),
4303 reg_to_bits(rd),
4304 12,
4305 )?);
4306
4307 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4309 reg_to_bits(rd),
4310 reg_to_bits(rd),
4311 11,
4312 )?);
4313
4314 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4317
4318 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4320 reg_to_bits(rd),
4321 reg_to_bits(rd),
4322 11,
4323 )?);
4324
4325 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4327 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4328
4329 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4331 reg_to_bits(rd),
4332 reg_to_bits(rd),
4333 12,
4334 )?);
4335
4336 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4339
4340 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4342 reg_to_bits(rd),
4343 reg_to_bits(rd),
4344 11,
4345 )?);
4346
4347 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4350
4351 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4353 reg_to_bits(rd),
4354 reg_to_bits(rd),
4355 11,
4356 )?);
4357
4358 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4361 reg_to_bits(rd),
4362 reg_to_bits(rd),
4363 0x3F,
4364 )?);
4365
4366 Ok(bytes)
4367 }
4368
4369 ArmOp::I64DivU {
4374 rdlo: _,
4375 rdhi: _,
4376 rnlo: _,
4377 rnhi: _,
4378 rmlo: _,
4379 rmhi: _,
4380 } => {
4381 let mut bytes = Vec::new();
4382
4383 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4387
4388 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());
4399 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4400
4401 let loop_start = bytes.len();
4403
4404 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4415 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());
4424 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4425 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4429 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4430
4431 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4436 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4437 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());
4468 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4469 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4472
4473 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4477 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4478
4479 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4482 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4483 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4484
4485 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4493
4494 Ok(bytes)
4495 }
4496
4497 ArmOp::I64DivS {
4502 rdlo: _,
4503 rdhi: _,
4504 rnlo: _,
4505 rnhi: _,
4506 rmlo: _,
4507 rmhi: _,
4508 } => {
4509 let mut bytes = Vec::new();
4510
4511 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4513 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4514
4515 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4518 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4519
4520 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());
4533
4534 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());
4544
4545 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4548 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4549 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4551 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4552 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4554 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4555
4556 let loop_start = bytes.len();
4557
4558 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4562 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());
4568 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4571
4572 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4576 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());
4589 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4591
4592 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4595
4596 let branch_offset_bytes = bytes.len() - loop_start + 4;
4597 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4598 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4599 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4600
4601 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());
4608 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());
4616
4617 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4619 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4620
4621 Ok(bytes)
4622 }
4623
4624 ArmOp::I64RemU {
4629 rdlo: _,
4630 rdhi: _,
4631 rnlo: _,
4632 rnhi: _,
4633 rmlo: _,
4634 rmhi: _,
4635 } => {
4636 let mut bytes = Vec::new();
4637
4638 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4640 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4641
4642 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4644 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4645 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4647 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4648 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4650 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4651
4652 let loop_start = bytes.len();
4653
4654 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4658 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());
4664 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4667
4668 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4672 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());
4685 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4687
4688 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4691
4692 let branch_offset_bytes = bytes.len() - loop_start + 4;
4693 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4694 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4695 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4696
4697 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4703 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4704
4705 Ok(bytes)
4706 }
4707
4708 ArmOp::I64RemS {
4713 rdlo: _,
4714 rdhi: _,
4715 rnlo: _,
4716 rnhi: _,
4717 rmlo: _,
4718 rmhi: _,
4719 } => {
4720 let mut bytes = Vec::new();
4721
4722 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4724 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4725
4726 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());
4740
4741 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());
4751
4752 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4755 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4756 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4758 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4759 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4761 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4762
4763 let loop_start = bytes.len();
4764
4765 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4769 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());
4775 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4778
4779 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4783 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());
4796 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4798
4799 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4802
4803 let branch_offset_bytes = bytes.len() - loop_start + 4;
4804 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4805 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4806 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4807
4808 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());
4815 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());
4823
4824 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4826 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4827
4828 Ok(bytes)
4829 }
4830
4831 ArmOp::F32Add { sd, sn, sm } => {
4834 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4835 }
4836 ArmOp::F32Sub { sd, sn, sm } => {
4837 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4838 }
4839 ArmOp::F32Mul { sd, sn, sm } => {
4840 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4841 }
4842 ArmOp::F32Div { sd, sn, sm } => {
4843 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4844 }
4845 ArmOp::F32Abs { sd, sm } => {
4846 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4847 }
4848 ArmOp::F32Neg { sd, sm } => {
4849 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4850 }
4851 ArmOp::F32Sqrt { sd, sm } => {
4852 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4853 }
4854
4855 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4858 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4859 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4860 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4861 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4862 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4863 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4864
4865 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4867 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4868 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4869 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4870 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4871 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4872
4873 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4874
4875 ArmOp::F32Load { sd, addr } => {
4876 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4877 }
4878 ArmOp::F32Store { sd, addr } => {
4879 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4880 }
4881
4882 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4883 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4884 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4885 Err(synth_core::Error::synthesis(
4886 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4887 ))
4888 }
4889 ArmOp::F32ReinterpretI32 { sd, rm } => {
4890 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4891 }
4892 ArmOp::I32ReinterpretF32 { rd, sm } => {
4893 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4894 }
4895 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4896 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4897
4898 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4901 0xEE300B00, dd, dn, dm,
4902 )?)),
4903 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4904 0xEE300B40, dd, dn, dm,
4905 )?)),
4906 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4907 0xEE200B00, dd, dn, dm,
4908 )?)),
4909 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4910 0xEE800B00, dd, dn, dm,
4911 )?)),
4912 ArmOp::F64Abs { dd, dm } => {
4913 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4914 }
4915 ArmOp::F64Neg { dd, dm } => {
4916 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4917 }
4918 ArmOp::F64Sqrt { dd, dm } => {
4919 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4920 }
4921
4922 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4925 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4926 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4927 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4928 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4929 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4930 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4931
4932 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4934 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4935 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4936 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4937 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4938 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4939
4940 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4941
4942 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4943 0xED900B00, dd, addr,
4944 )?)),
4945 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4946 0xED800B00, dd, addr,
4947 )?)),
4948
4949 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4950 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4951 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4952 Err(synth_core::Error::synthesis(
4953 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4954 ))
4955 }
4956 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4957 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4958 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4959 )),
4960 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4961 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4962 )),
4963 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4964 Err(synth_core::Error::synthesis(
4965 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4966 ))
4967 }
4968 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4969 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4970
4971 ArmOp::I64Add {
4975 rdlo,
4976 rdhi,
4977 rnlo,
4978 rnhi,
4979 rmlo,
4980 rmhi,
4981 } => {
4982 let mut bytes = Vec::new();
4983 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4985 rd: *rdlo,
4986 rn: *rnlo,
4987 op2: Operand2::Reg(*rmlo),
4988 })?);
4989 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4991 rd: *rdhi,
4992 rn: *rnhi,
4993 op2: Operand2::Reg(*rmhi),
4994 })?);
4995 Ok(bytes)
4996 }
4997
4998 ArmOp::I64Sub {
5000 rdlo,
5001 rdhi,
5002 rnlo,
5003 rnhi,
5004 rmlo,
5005 rmhi,
5006 } => {
5007 let mut bytes = Vec::new();
5008 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
5010 rd: *rdlo,
5011 rn: *rnlo,
5012 op2: Operand2::Reg(*rmlo),
5013 })?);
5014 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
5016 rd: *rdhi,
5017 rn: *rnhi,
5018 op2: Operand2::Reg(*rmhi),
5019 })?);
5020 Ok(bytes)
5021 }
5022
5023 ArmOp::I64And {
5025 rdlo,
5026 rdhi,
5027 rnlo,
5028 rnhi,
5029 rmlo,
5030 rmhi,
5031 } => {
5032 let mut bytes = Vec::new();
5033 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5034 rd: *rdlo,
5035 rn: *rnlo,
5036 op2: Operand2::Reg(*rmlo),
5037 })?);
5038 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5039 rd: *rdhi,
5040 rn: *rnhi,
5041 op2: Operand2::Reg(*rmhi),
5042 })?);
5043 Ok(bytes)
5044 }
5045
5046 ArmOp::I64Or {
5048 rdlo,
5049 rdhi,
5050 rnlo,
5051 rnhi,
5052 rmlo,
5053 rmhi,
5054 } => {
5055 let mut bytes = Vec::new();
5056 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5057 rd: *rdlo,
5058 rn: *rnlo,
5059 op2: Operand2::Reg(*rmlo),
5060 })?);
5061 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5062 rd: *rdhi,
5063 rn: *rnhi,
5064 op2: Operand2::Reg(*rmhi),
5065 })?);
5066 Ok(bytes)
5067 }
5068
5069 ArmOp::I64Xor {
5071 rdlo,
5072 rdhi,
5073 rnlo,
5074 rnhi,
5075 rmlo,
5076 rmhi,
5077 } => {
5078 let mut bytes = Vec::new();
5079 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5080 rd: *rdlo,
5081 rn: *rnlo,
5082 op2: Operand2::Reg(*rmlo),
5083 })?);
5084 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5085 rd: *rdhi,
5086 rn: *rnhi,
5087 op2: Operand2::Reg(*rmhi),
5088 })?);
5089 Ok(bytes)
5090 }
5091
5092 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
5094 rd: *rd,
5095 rn_lo: *rnlo,
5096 rn_hi: *rnhi,
5097 }),
5098
5099 ArmOp::I64Eq {
5101 rd,
5102 rnlo,
5103 rnhi,
5104 rmlo,
5105 rmhi,
5106 } => self.encode_thumb(&ArmOp::I64SetCond {
5107 rd: *rd,
5108 rn_lo: *rnlo,
5109 rn_hi: *rnhi,
5110 rm_lo: *rmlo,
5111 rm_hi: *rmhi,
5112 cond: synth_synthesis::Condition::EQ,
5113 }),
5114
5115 ArmOp::I64Ne {
5116 rd,
5117 rnlo,
5118 rnhi,
5119 rmlo,
5120 rmhi,
5121 } => self.encode_thumb(&ArmOp::I64SetCond {
5122 rd: *rd,
5123 rn_lo: *rnlo,
5124 rn_hi: *rnhi,
5125 rm_lo: *rmlo,
5126 rm_hi: *rmhi,
5127 cond: synth_synthesis::Condition::NE,
5128 }),
5129
5130 ArmOp::I64LtS {
5131 rd,
5132 rnlo,
5133 rnhi,
5134 rmlo,
5135 rmhi,
5136 } => self.encode_thumb(&ArmOp::I64SetCond {
5137 rd: *rd,
5138 rn_lo: *rnlo,
5139 rn_hi: *rnhi,
5140 rm_lo: *rmlo,
5141 rm_hi: *rmhi,
5142 cond: synth_synthesis::Condition::LT,
5143 }),
5144
5145 ArmOp::I64LtU {
5146 rd,
5147 rnlo,
5148 rnhi,
5149 rmlo,
5150 rmhi,
5151 } => self.encode_thumb(&ArmOp::I64SetCond {
5152 rd: *rd,
5153 rn_lo: *rnlo,
5154 rn_hi: *rnhi,
5155 rm_lo: *rmlo,
5156 rm_hi: *rmhi,
5157 cond: synth_synthesis::Condition::LO,
5158 }),
5159
5160 ArmOp::I64LeS {
5161 rd,
5162 rnlo,
5163 rnhi,
5164 rmlo,
5165 rmhi,
5166 } => self.encode_thumb(&ArmOp::I64SetCond {
5167 rd: *rd,
5168 rn_lo: *rnlo,
5169 rn_hi: *rnhi,
5170 rm_lo: *rmlo,
5171 rm_hi: *rmhi,
5172 cond: synth_synthesis::Condition::LE,
5173 }),
5174
5175 ArmOp::I64LeU {
5176 rd,
5177 rnlo,
5178 rnhi,
5179 rmlo,
5180 rmhi,
5181 } => self.encode_thumb(&ArmOp::I64SetCond {
5182 rd: *rd,
5183 rn_lo: *rnlo,
5184 rn_hi: *rnhi,
5185 rm_lo: *rmlo,
5186 rm_hi: *rmhi,
5187 cond: synth_synthesis::Condition::LS,
5188 }),
5189
5190 ArmOp::I64GtS {
5191 rd,
5192 rnlo,
5193 rnhi,
5194 rmlo,
5195 rmhi,
5196 } => self.encode_thumb(&ArmOp::I64SetCond {
5197 rd: *rd,
5198 rn_lo: *rnlo,
5199 rn_hi: *rnhi,
5200 rm_lo: *rmlo,
5201 rm_hi: *rmhi,
5202 cond: synth_synthesis::Condition::GT,
5203 }),
5204
5205 ArmOp::I64GtU {
5206 rd,
5207 rnlo,
5208 rnhi,
5209 rmlo,
5210 rmhi,
5211 } => self.encode_thumb(&ArmOp::I64SetCond {
5212 rd: *rd,
5213 rn_lo: *rnlo,
5214 rn_hi: *rnhi,
5215 rm_lo: *rmlo,
5216 rm_hi: *rmhi,
5217 cond: synth_synthesis::Condition::HI,
5218 }),
5219
5220 ArmOp::I64GeS {
5221 rd,
5222 rnlo,
5223 rnhi,
5224 rmlo,
5225 rmhi,
5226 } => self.encode_thumb(&ArmOp::I64SetCond {
5227 rd: *rd,
5228 rn_lo: *rnlo,
5229 rn_hi: *rnhi,
5230 rm_lo: *rmlo,
5231 rm_hi: *rmhi,
5232 cond: synth_synthesis::Condition::GE,
5233 }),
5234
5235 ArmOp::I64GeU {
5236 rd,
5237 rnlo,
5238 rnhi,
5239 rmlo,
5240 rmhi,
5241 } => self.encode_thumb(&ArmOp::I64SetCond {
5242 rd: *rd,
5243 rn_lo: *rnlo,
5244 rn_hi: *rnhi,
5245 rm_lo: *rmlo,
5246 rm_hi: *rmhi,
5247 cond: synth_synthesis::Condition::HS,
5248 }),
5249
5250 ArmOp::I64Const { rdlo, rdhi, value } => {
5252 let lo32 = *value as u32;
5253 let hi32 = (*value >> 32) as u32;
5254 let mut bytes = Vec::new();
5255 bytes.extend_from_slice(
5257 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5258 );
5259 if lo32 > 0xFFFF {
5260 bytes.extend_from_slice(
5261 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5262 );
5263 }
5264 bytes.extend_from_slice(
5266 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5267 );
5268 if hi32 > 0xFFFF {
5269 bytes.extend_from_slice(
5270 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5271 );
5272 }
5273 Ok(bytes)
5274 }
5275
5276 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5278 let mut bytes = Vec::new();
5279 let offset = if addr.offset < 0 {
5280 0u32
5281 } else {
5282 addr.offset as u32
5283 };
5284 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5285 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5286 rdhi,
5287 &addr.base,
5288 offset.wrapping_add(4),
5289 )?);
5290 Ok(bytes)
5291 }
5292
5293 ArmOp::I64Str { rdlo, rdhi, addr } => {
5295 let mut bytes = Vec::new();
5296 let offset = if addr.offset < 0 {
5297 0u32
5298 } else {
5299 addr.offset as u32
5300 };
5301 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5302 bytes.extend_from_slice(&self.encode_thumb32_str(
5303 rdhi,
5304 &addr.base,
5305 offset.wrapping_add(4),
5306 )?);
5307 Ok(bytes)
5308 }
5309
5310 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5312 let mut bytes = Vec::new();
5313 if rdlo != rn {
5314 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5316 rd: *rdlo,
5317 op2: Operand2::Reg(*rn),
5318 })?);
5319 }
5320 bytes.extend_from_slice(
5322 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5324 Ok(bytes)
5325 }
5326
5327 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5329 let mut bytes = Vec::new();
5330 if rdlo != rn {
5331 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5333 rd: *rdlo,
5334 op2: Operand2::Reg(*rn),
5335 })?);
5336 }
5337 let rdhi_bits = reg_to_bits(rdhi) as u16;
5339 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5340 bytes.extend_from_slice(&instr.to_le_bytes());
5341 Ok(bytes)
5342 }
5343
5344 ArmOp::I32WrapI64 { rd, rnlo } => {
5346 if rd == rnlo {
5347 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5350 } else {
5351 self.encode_thumb(&ArmOp::Mov {
5353 rd: *rd,
5354 op2: Operand2::Reg(*rnlo),
5355 })
5356 }
5357 }
5358
5359 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5361 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5362 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5363 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5364 0xEF000150, qd, qn, qm,
5365 ))),
5366 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5367 0xEF200150, qd, qn, qm,
5368 ))),
5369 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5370 0xFF000150, qd, qn, qm,
5371 ))),
5372 ArmOp::MveMvn { qd, qm } => {
5373 let qd_enc = qreg_to_num(qd);
5375 let qm_enc = qreg_to_num(qm);
5376 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5377 Ok(vfp_to_thumb_bytes(instr))
5378 }
5379 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5380 0xEF100150, qd, qn, qm,
5381 ))),
5382 ArmOp::MveAddI { qd, qn, qm, size } => {
5383 let sz = mve_size_bits(size);
5384 let base: u32 = 0xEF000840 | (sz << 20);
5385 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5386 }
5387 ArmOp::MveSubI { qd, qn, qm, size } => {
5388 let sz = mve_size_bits(size);
5389 let base: u32 = 0xFF000840 | (sz << 20);
5390 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5391 }
5392 ArmOp::MveMulI { qd, qn, qm, size } => {
5393 let sz = mve_size_bits(size);
5394 let base: u32 = 0xEF000950 | (sz << 20);
5395 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5396 }
5397 ArmOp::MveNegI { qd, qm, size } => {
5398 let sz = mve_size_bits(size);
5399 let qd_enc = qreg_to_num(qd);
5401 let qm_enc = qreg_to_num(qm);
5402 let base: u32 = 0xFFB103C0 | (sz << 18);
5403 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5404 Ok(vfp_to_thumb_bytes(instr))
5405 }
5406 ArmOp::MveDup { qd, rn, size } => {
5407 let sz = mve_size_bits(size);
5408 let qd_enc = qreg_to_num(qd);
5409 let rn_bits = reg_to_bits(rn);
5410 let be = match sz {
5413 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5417 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5418 Ok(vfp_to_thumb_bytes(instr))
5419 }
5420 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5421 let qn_enc = qreg_to_num(qn);
5422 let rd_bits = reg_to_bits(rd);
5423 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5426 let lane_in_d = (*lane as u32) & 1;
5427 let _sz = mve_size_bits(size);
5428 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5430 Ok(vfp_to_thumb_bytes(instr))
5431 }
5432 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5433 let qd_enc = qreg_to_num(qd);
5434 let rn_bits = reg_to_bits(rn);
5435 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5436 let lane_in_d = (*lane as u32) & 1;
5437 let _sz = mve_size_bits(size);
5438 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5440 Ok(vfp_to_thumb_bytes(instr))
5441 }
5442
5443 ArmOp::MveCmpEqI { qd, qn, qm, size }
5445 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5446 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5447 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5448 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5449 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5450 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5451 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5452 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5453 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5454 let sz = mve_size_bits(size);
5457 let base: u32 = 0xEF000840 | (sz << 20);
5458 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5459 }
5460
5461 ArmOp::MveAddF32 { qd, qn, qm } => {
5463 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5465 }
5466 ArmOp::MveSubF32 { qd, qn, qm } => {
5467 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5469 }
5470 ArmOp::MveMulF32 { qd, qn, qm } => {
5471 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5473 }
5474 ArmOp::MveNegF32 { qd, qm } => {
5475 let qd_enc = qreg_to_num(qd);
5476 let qm_enc = qreg_to_num(qm);
5477 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5479 Ok(vfp_to_thumb_bytes(instr))
5480 }
5481 ArmOp::MveAbsF32 { qd, qm } => {
5482 let qd_enc = qreg_to_num(qd);
5483 let qm_enc = qreg_to_num(qm);
5484 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5486 Ok(vfp_to_thumb_bytes(instr))
5487 }
5488 ArmOp::MveCmpEqF32 { qd, qn, qm }
5489 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5490 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5491 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5492 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5493 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5494 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5496 }
5497 ArmOp::MveDupF32 { qd, rn } => {
5498 let qd_enc = qreg_to_num(qd);
5499 let rn_bits = reg_to_bits(rn);
5500 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5502 Ok(vfp_to_thumb_bytes(instr))
5503 }
5504 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5505 let qn_enc = qreg_to_num(qn);
5506 let rd_bits = reg_to_bits(rd);
5507 let s_num = qn_enc * 4 + (*lane as u32);
5509 let (vn, n) = encode_sreg(s_num);
5510 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5511 Ok(vfp_to_thumb_bytes(instr))
5512 }
5513 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5514 let qd_enc = qreg_to_num(qd);
5515 let rn_bits = reg_to_bits(rn);
5516 let s_num = qd_enc * 4 + (*lane as u32);
5518 let (vn, n) = encode_sreg(s_num);
5519 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5520 Ok(vfp_to_thumb_bytes(instr))
5521 }
5522 ArmOp::MveDivF32 { qd, qn, qm } => {
5523 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5525 }
5526 ArmOp::MveSqrtF32 { qd, qm } => {
5527 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5529 }
5530
5531 _ => {
5533 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5535 }
5536 }
5537 }
5538
5539 fn encode_thumb_f32_compare(
5543 &self,
5544 rd: &Reg,
5545 sn: &VfpReg,
5546 sm: &VfpReg,
5547 cond_code: u32,
5548 ) -> Result<Vec<u8>> {
5549 let mut bytes = Vec::new();
5550 let rd_bits = reg_to_bits(rd);
5551
5552 let sn_num = vfp_sreg_to_num(sn)?;
5554 let sm_num = vfp_sreg_to_num(sm)?;
5555 let (vd, d) = encode_sreg(sn_num);
5556 let (vm, m) = encode_sreg(sm_num);
5557 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5558 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5559
5560 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5562
5563 if rd_bits < 8 {
5565 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5566 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5567 } else {
5568 let hw1: u16 = 0xF04F;
5570 let hw2: u16 = (rd_bits as u16) << 8;
5571 bytes.extend_from_slice(&hw1.to_le_bytes());
5572 bytes.extend_from_slice(&hw2.to_le_bytes());
5573 }
5574
5575 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5579 bytes.extend_from_slice(&it.to_le_bytes());
5580
5581 if rd_bits < 8 {
5583 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5584 bytes.extend_from_slice(&mov_one.to_le_bytes());
5585 } else {
5586 let hw1: u16 = 0xF04F;
5588 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5589 bytes.extend_from_slice(&hw1.to_le_bytes());
5590 bytes.extend_from_slice(&hw2.to_le_bytes());
5591 }
5592
5593 Ok(bytes)
5594 }
5595
5596 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5598 let mut bytes = Vec::new();
5599 let bits = value.to_bits();
5600 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5605 let imm4 = (lo16 >> 12) & 0xF;
5606 let i_bit = (lo16 >> 11) & 1;
5607 let imm3 = (lo16 >> 8) & 0x7;
5608 let imm8 = lo16 & 0xFF;
5609 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5610 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5611 bytes.extend_from_slice(&hw1.to_le_bytes());
5612 bytes.extend_from_slice(&hw2.to_le_bytes());
5613
5614 let hi16 = (bits >> 16) & 0xFFFF;
5616 let imm4 = (hi16 >> 12) & 0xF;
5617 let i_bit = (hi16 >> 11) & 1;
5618 let imm3 = (hi16 >> 8) & 0x7;
5619 let imm8 = hi16 & 0xFF;
5620 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5621 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5622 bytes.extend_from_slice(&hw1.to_le_bytes());
5623 bytes.extend_from_slice(&hw2.to_le_bytes());
5624
5625 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5627 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5628
5629 Ok(bytes)
5630 }
5631
5632 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5634 let mut bytes = Vec::new();
5635
5636 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5638 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5639
5640 let sd_num = vfp_sreg_to_num(sd)?;
5642 let (vd, d) = encode_sreg(sd_num);
5643 let (vm, m) = encode_sreg(sd_num);
5644 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5645 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5646 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5647
5648 Ok(bytes)
5649 }
5650
5651 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5659 let mut bytes = Vec::new();
5660 let sm_num = vfp_sreg_to_num(sm)?;
5661 let sd_num = vfp_sreg_to_num(sd)?;
5662 let (vd_s, d_s) = encode_sreg(sd_num);
5663 let (vm_s, m_s) = encode_sreg(sm_num);
5664
5665 if mode == 0b11 {
5666 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5668 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5669 } else {
5670 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5675 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5676
5677 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5683 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5684 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5685
5686 if mode != 0 {
5688 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5690 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5691 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5692 }
5693
5694 let vmsr = 0xEEE10A10 | (rt << 12);
5696 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5697
5698 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5700 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5701
5702 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5704 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5705 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5706 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5707 }
5708
5709 let (vd2, d2) = encode_sreg(sd_num);
5711 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5712 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5713
5714 Ok(bytes)
5715 }
5716
5717 fn encode_thumb_f32_minmax(
5719 &self,
5720 sd: &VfpReg,
5721 sn: &VfpReg,
5722 sm: &VfpReg,
5723 is_min: bool,
5724 ) -> Result<Vec<u8>> {
5725 let mut bytes = Vec::new();
5726 let sn_num = vfp_sreg_to_num(sn)?;
5727 let sm_num = vfp_sreg_to_num(sm)?;
5728 let sd_num = vfp_sreg_to_num(sd)?;
5729
5730 let (vd, d) = encode_sreg(sd_num);
5732 let (vn, n) = encode_sreg(sn_num);
5733 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5734 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5735
5736 let (vm, m) = encode_sreg(sm_num);
5738 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5739 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5740
5741 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5743
5744 let cond: u16 = if is_min { 0xC } else { 0x4 };
5746 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5747 bytes.extend_from_slice(&it.to_le_bytes());
5748
5749 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5751 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5752
5753 Ok(bytes)
5754 }
5755
5756 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5758 let mut bytes = Vec::new();
5759
5760 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5762 false,
5763 sm,
5764 &Reg::R12,
5765 )?));
5766
5767 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5769 false,
5770 sn,
5771 &Reg::R0,
5772 )?));
5773
5774 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5786 bytes.extend_from_slice(&hw2.to_le_bytes());
5787
5788 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5792 bytes.extend_from_slice(&hw2.to_le_bytes());
5793
5794 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5798 bytes.extend_from_slice(&hw2.to_le_bytes());
5799
5800 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5802 true,
5803 sd,
5804 &Reg::R0,
5805 )?));
5806
5807 Ok(bytes)
5808 }
5809
5810 fn encode_thumb_f64_compare(
5812 &self,
5813 rd: &Reg,
5814 dn: &VfpReg,
5815 dm: &VfpReg,
5816 cond_code: u32,
5817 ) -> Result<Vec<u8>> {
5818 let mut bytes = Vec::new();
5819 let rd_bits = reg_to_bits(rd);
5820
5821 let dn_num = vfp_dreg_to_num(dn)?;
5823 let dm_num = vfp_dreg_to_num(dm)?;
5824 let (vd, d) = encode_dreg(dn_num);
5825 let (vm, m) = encode_dreg(dm_num);
5826 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5827 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5828
5829 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5831
5832 if rd_bits < 8 {
5834 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5835 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5836 } else {
5837 let hw1: u16 = 0xF04F;
5838 let hw2: u16 = (rd_bits as u16) << 8;
5839 bytes.extend_from_slice(&hw1.to_le_bytes());
5840 bytes.extend_from_slice(&hw2.to_le_bytes());
5841 }
5842
5843 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5845 bytes.extend_from_slice(&it.to_le_bytes());
5846
5847 if rd_bits < 8 {
5849 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5850 bytes.extend_from_slice(&mov_one.to_le_bytes());
5851 } else {
5852 let hw1: u16 = 0xF04F;
5853 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5854 bytes.extend_from_slice(&hw1.to_le_bytes());
5855 bytes.extend_from_slice(&hw2.to_le_bytes());
5856 }
5857
5858 Ok(bytes)
5859 }
5860
5861 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5863 let mut bytes = Vec::new();
5864 let bits = value.to_bits();
5865 let lo32 = bits as u32;
5866 let hi32 = (bits >> 32) as u32;
5867
5868 let lo16 = lo32 & 0xFFFF;
5870 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5871
5872 let hi16 = (lo32 >> 16) & 0xFFFF;
5874 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5875
5876 let lo16 = hi32 & 0xFFFF;
5878 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5879
5880 let hi16 = (hi32 >> 16) & 0xFFFF;
5882 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5883
5884 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5886 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5887
5888 Ok(bytes)
5889 }
5890
5891 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5893 let mut bytes = Vec::new();
5894
5895 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5897 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5898
5899 let dd_num = vfp_dreg_to_num(dd)?;
5901 let (vd, d) = encode_dreg(dd_num);
5902 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5903 let vcvt = base | (d << 22) | (vd << 12);
5904 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5905
5906 Ok(bytes)
5907 }
5908
5909 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5911 let dd_num = vfp_dreg_to_num(dd)?;
5912 let sm_num = vfp_sreg_to_num(sm)?;
5913 let (vd, d) = encode_dreg(dd_num);
5914 let (vm, m) = encode_sreg(sm_num);
5915
5916 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5917 Ok(vfp_to_thumb_bytes(vcvt))
5918 }
5919
5920 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5922 let mut bytes = Vec::new();
5923 let dm_num = vfp_dreg_to_num(dm)?;
5924 let (vm, m) = encode_dreg(dm_num);
5925
5926 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5928 let vcvt = base | (m << 5) | vm;
5929 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5930
5931 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5933 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5934
5935 Ok(bytes)
5936 }
5937
5938 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5942 let mut bytes = Vec::new();
5943 let dm_num = vfp_dreg_to_num(dm)?;
5944 let dd_num = vfp_dreg_to_num(dd)?;
5945 let (vm, m) = encode_dreg(dm_num);
5946 let (vd, d) = encode_dreg(dd_num);
5947
5948 if mode == 0b11 {
5949 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5951 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5952 } else {
5953 let rt: u32 = 12;
5954
5955 let vmrs = 0xEEF10A10 | (rt << 12);
5957 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5958
5959 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5961 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5962 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5963 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5964
5965 if mode != 0 {
5967 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5968 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5969 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5970 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5971 }
5972
5973 let vmsr = 0xEEE10A10 | (rt << 12);
5975 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5976
5977 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5979 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5980
5981 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5983 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5984 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5985 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5986 }
5987
5988 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5990 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5991
5992 Ok(bytes)
5993 }
5994
5995 fn encode_thumb_f64_minmax(
5997 &self,
5998 dd: &VfpReg,
5999 dn: &VfpReg,
6000 dm: &VfpReg,
6001 is_min: bool,
6002 ) -> Result<Vec<u8>> {
6003 let mut bytes = Vec::new();
6004 let dn_num = vfp_dreg_to_num(dn)?;
6005 let dm_num = vfp_dreg_to_num(dm)?;
6006 let dd_num = vfp_dreg_to_num(dd)?;
6007
6008 let (vd, d) = encode_dreg(dd_num);
6010 let (vn, n) = encode_dreg(dn_num);
6011 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
6012 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
6013
6014 let (vm, m) = encode_dreg(dm_num);
6016 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
6017 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
6018
6019 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
6021
6022 let cond: u16 = if is_min { 0xC } else { 0x4 };
6024 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
6025 bytes.extend_from_slice(&it.to_le_bytes());
6026
6027 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
6029 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
6030
6031 Ok(bytes)
6032 }
6033
6034 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
6036 let mut bytes = Vec::new();
6037
6038 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6040 false,
6041 dm,
6042 &Reg::R0,
6043 &Reg::R12,
6044 )?));
6045
6046 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6048 false,
6049 dn,
6050 &Reg::R1,
6051 &Reg::R2,
6052 )?));
6053
6054 let hw1: u16 = 0xF000 | 12;
6056 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
6057 bytes.extend_from_slice(&hw1.to_le_bytes());
6058 bytes.extend_from_slice(&hw2.to_le_bytes());
6059
6060 let hw1: u16 = 0xF020 | 2;
6062 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
6063 bytes.extend_from_slice(&hw1.to_le_bytes());
6064 bytes.extend_from_slice(&hw2.to_le_bytes());
6065
6066 let hw1: u16 = 0xEA40 | 2;
6068 let hw2: u16 = (2 << 8) | 12;
6069 bytes.extend_from_slice(&hw1.to_le_bytes());
6070 bytes.extend_from_slice(&hw2.to_le_bytes());
6071
6072 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6074 true,
6075 dd,
6076 &Reg::R1,
6077 &Reg::R2,
6078 )?));
6079
6080 Ok(bytes)
6081 }
6082
6083 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6085 let mut bytes = Vec::new();
6086
6087 let sm_num = vfp_sreg_to_num(sm)?;
6088 let (vd, d) = encode_sreg(sm_num);
6089 let (vm, m) = encode_sreg(sm_num);
6090 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6091 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6092 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6093
6094 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6096 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6097
6098 Ok(bytes)
6099 }
6100
6101 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6105 let rd_bits = reg_to_bits(rd);
6106 let rn_bits = reg_to_bits(rn);
6107
6108 let i_bit = (imm >> 11) & 1;
6110 let imm3 = (imm >> 8) & 0x7;
6111 let imm8 = imm & 0xFF;
6112
6113 let hw1_base = if imm <= 0xFF {
6114 0xF100
6118 } else if imm <= 0xFFF {
6119 0xF200
6123 } else {
6124 return Err(synth_core::Error::synthesis(
6125 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6126 ));
6127 };
6128
6129 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6130 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6131
6132 let mut bytes = hw1.to_le_bytes().to_vec();
6133 bytes.extend_from_slice(&hw2.to_le_bytes());
6134 Ok(bytes)
6135 }
6136
6137 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6139 let rd_bits = reg_to_bits(rd);
6140 let rn_bits = reg_to_bits(rn);
6141
6142 let i_bit = (imm >> 11) & 1;
6143 let imm3 = (imm >> 8) & 0x7;
6144 let imm8 = imm & 0xFF;
6145
6146 let hw1_base = if imm <= 0xFF {
6147 0xF1A0
6150 } else if imm <= 0xFFF {
6151 0xF2A0
6154 } else {
6155 return Err(synth_core::Error::synthesis(
6156 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6157 ));
6158 };
6159
6160 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6161 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6162
6163 let mut bytes = hw1.to_le_bytes().to_vec();
6164 bytes.extend_from_slice(&hw2.to_le_bytes());
6165 Ok(bytes)
6166 }
6167
6168 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6170 let rd_bits = reg_to_bits(rd);
6171 let rn_bits = reg_to_bits(rn);
6172
6173 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6176 synth_core::Error::synthesis(
6177 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6178 )
6179 })?;
6180 let i_bit = (field >> 11) & 1;
6181 let imm3 = (field >> 8) & 0x7;
6182 let imm8 = field & 0xFF;
6183
6184 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6187 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6188
6189 let mut bytes = hw1.to_le_bytes().to_vec();
6190 bytes.extend_from_slice(&hw2.to_le_bytes());
6191 Ok(bytes)
6192 }
6193
6194 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6196 let rd_bits = reg_to_bits(rd);
6197 let rn_bits = reg_to_bits(rn);
6198
6199 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6202 synth_core::Error::synthesis(
6203 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6204 )
6205 })?;
6206 let i_bit = (field >> 11) & 1;
6207 let imm3 = (field >> 8) & 0x7;
6208 let imm8 = field & 0xFF;
6209
6210 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6213 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6214
6215 let mut bytes = hw1.to_le_bytes().to_vec();
6216 bytes.extend_from_slice(&hw2.to_le_bytes());
6217 Ok(bytes)
6218 }
6219
6220 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6229 let rd_bits = reg_to_bits(rd);
6230 reg_bits_checked(rd_bits)?;
6231 let imm16 = imm & 0xFFFF;
6232
6233 let imm4 = (imm16 >> 12) & 0xF;
6236 let i_bit = (imm16 >> 11) & 1;
6237 let imm3 = (imm16 >> 8) & 0x7;
6238 let imm8 = imm16 & 0xFF;
6239
6240 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6241 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6242
6243 let mut bytes = hw1.to_le_bytes().to_vec();
6244 bytes.extend_from_slice(&hw2.to_le_bytes());
6245 encoding_contracts::verify_thumb32(&bytes);
6246 Ok(bytes)
6247 }
6248
6249 fn encode_thumb32_shift(
6257 &self,
6258 rd: &Reg,
6259 rm: &Reg,
6260 shift: u32,
6261 shift_type: u8,
6262 ) -> Result<Vec<u8>> {
6263 let rd_bits = reg_to_bits(rd);
6264 let rm_bits = reg_to_bits(rm);
6265 reg_bits_checked(rd_bits)?;
6266 reg_bits_checked(rm_bits)?;
6267 let imm5 = shift & 0x1F;
6268 let imm2 = imm5 & 0x3;
6269 let imm3 = (imm5 >> 2) & 0x7;
6270
6271 let hw1: u16 = 0xEA4F;
6274 let hw2: u16 =
6275 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6276 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_shift_reg(
6287 &self,
6288 rd: &Reg,
6289 rn: &Reg,
6290 rm: &Reg,
6291 shift_type: u8,
6292 ) -> Result<Vec<u8>> {
6293 let rd_bits = reg_to_bits(rd);
6294 let rn_bits = reg_to_bits(rn);
6295 let rm_bits = reg_to_bits(rm);
6296
6297 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6299 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6301
6302 let mut bytes = hw1.to_le_bytes().to_vec();
6303 bytes.extend_from_slice(&hw2.to_le_bytes());
6304 Ok(bytes)
6305 }
6306
6307 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6309 let rn_bits = reg_to_bits(rn);
6310
6311 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6315 synth_core::Error::synthesis(
6316 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6317 )
6318 })?;
6319 let i_bit = (field >> 11) & 1;
6320 let imm3 = (field >> 8) & 0x7;
6321 let imm8 = field & 0xFF;
6322
6323 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6325 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6326
6327 let mut bytes = hw1.to_le_bytes().to_vec();
6328 bytes.extend_from_slice(&hw2.to_le_bytes());
6329 Ok(bytes)
6330 }
6331
6332 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6334 let rd_bits = reg_to_bits(rd);
6335 let base_bits = reg_to_bits(base);
6336
6337 check_ldst_imm12(offset)?;
6339 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6340 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6341
6342 let mut bytes = hw1.to_le_bytes().to_vec();
6343 bytes.extend_from_slice(&hw2.to_le_bytes());
6344 Ok(bytes)
6345 }
6346
6347 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6349 let rd_bits = reg_to_bits(rd);
6350 let base_bits = reg_to_bits(base);
6351
6352 check_ldst_imm12(offset)?;
6354 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6355 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6356
6357 let mut bytes = hw1.to_le_bytes().to_vec();
6358 bytes.extend_from_slice(&hw2.to_le_bytes());
6359 Ok(bytes)
6360 }
6361
6362 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6364 let rd_bits = reg_to_bits(rd);
6365 let base_bits = reg_to_bits(base);
6366 let rm_bits = reg_to_bits(offset_reg);
6367
6368 let hw1: u16 = (0xF850 | base_bits) as u16;
6372 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6373
6374 let mut bytes = hw1.to_le_bytes().to_vec();
6375 bytes.extend_from_slice(&hw2.to_le_bytes());
6376 Ok(bytes)
6377 }
6378
6379 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6381 let rd_bits = reg_to_bits(rd);
6382 let base_bits = reg_to_bits(base);
6383 let rm_bits = reg_to_bits(offset_reg);
6384
6385 let hw1: u16 = (0xF840 | base_bits) as u16;
6389 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6390
6391 let mut bytes = hw1.to_le_bytes().to_vec();
6392 bytes.extend_from_slice(&hw2.to_le_bytes());
6393 Ok(bytes)
6394 }
6395
6396 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6400 let rd_bits = reg_to_bits(rd);
6401 let base_bits = reg_to_bits(base);
6402 check_ldst_imm12(offset)?;
6404 let hw1: u16 = (0xF890 | base_bits) as u16;
6405 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6406 let mut bytes = hw1.to_le_bytes().to_vec();
6407 bytes.extend_from_slice(&hw2.to_le_bytes());
6408 Ok(bytes)
6409 }
6410
6411 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6413 let rd_bits = reg_to_bits(rd);
6414 let base_bits = reg_to_bits(base);
6415 let rm_bits = reg_to_bits(offset_reg);
6416 let hw1: u16 = (0xF810 | base_bits) as u16;
6418 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6419 let mut bytes = hw1.to_le_bytes().to_vec();
6420 bytes.extend_from_slice(&hw2.to_le_bytes());
6421 Ok(bytes)
6422 }
6423
6424 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6426 let rd_bits = reg_to_bits(rd);
6427 let base_bits = reg_to_bits(base);
6428 check_ldst_imm12(offset)?;
6430 let hw1: u16 = (0xF990 | base_bits) as u16;
6431 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6432 let mut bytes = hw1.to_le_bytes().to_vec();
6433 bytes.extend_from_slice(&hw2.to_le_bytes());
6434 Ok(bytes)
6435 }
6436
6437 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6439 let rd_bits = reg_to_bits(rd);
6440 let base_bits = reg_to_bits(base);
6441 let rm_bits = reg_to_bits(offset_reg);
6442 let hw1: u16 = (0xF910 | base_bits) as u16;
6444 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6445 let mut bytes = hw1.to_le_bytes().to_vec();
6446 bytes.extend_from_slice(&hw2.to_le_bytes());
6447 Ok(bytes)
6448 }
6449
6450 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6452 let rd_bits = reg_to_bits(rd);
6453 let base_bits = reg_to_bits(base);
6454 check_ldst_imm12(offset)?;
6456 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6457 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6458 let mut bytes = hw1.to_le_bytes().to_vec();
6459 bytes.extend_from_slice(&hw2.to_le_bytes());
6460 Ok(bytes)
6461 }
6462
6463 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6465 let rd_bits = reg_to_bits(rd);
6466 let base_bits = reg_to_bits(base);
6467 let rm_bits = reg_to_bits(offset_reg);
6468 let hw1: u16 = (0xF830 | base_bits) as u16;
6470 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6471 let mut bytes = hw1.to_le_bytes().to_vec();
6472 bytes.extend_from_slice(&hw2.to_le_bytes());
6473 Ok(bytes)
6474 }
6475
6476 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6478 let rd_bits = reg_to_bits(rd);
6479 let base_bits = reg_to_bits(base);
6480 check_ldst_imm12(offset)?;
6482 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6483 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6484 let mut bytes = hw1.to_le_bytes().to_vec();
6485 bytes.extend_from_slice(&hw2.to_le_bytes());
6486 Ok(bytes)
6487 }
6488
6489 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6491 let rd_bits = reg_to_bits(rd);
6492 let base_bits = reg_to_bits(base);
6493 let rm_bits = reg_to_bits(offset_reg);
6494 let hw1: u16 = (0xF930 | base_bits) as u16;
6496 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6497 let mut bytes = hw1.to_le_bytes().to_vec();
6498 bytes.extend_from_slice(&hw2.to_le_bytes());
6499 Ok(bytes)
6500 }
6501
6502 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6504 let rd_bits = reg_to_bits(rd);
6505 let base_bits = reg_to_bits(base);
6506 check_ldst_imm12(offset)?;
6508 let hw1: u16 = (0xF880 | base_bits) as u16;
6509 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6510 let mut bytes = hw1.to_le_bytes().to_vec();
6511 bytes.extend_from_slice(&hw2.to_le_bytes());
6512 Ok(bytes)
6513 }
6514
6515 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6517 let rd_bits = reg_to_bits(rd);
6518 let base_bits = reg_to_bits(base);
6519 let rm_bits = reg_to_bits(offset_reg);
6520 let hw1: u16 = (0xF800 | base_bits) as u16;
6522 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6523 let mut bytes = hw1.to_le_bytes().to_vec();
6524 bytes.extend_from_slice(&hw2.to_le_bytes());
6525 Ok(bytes)
6526 }
6527
6528 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6530 let rd_bits = reg_to_bits(rd);
6531 let base_bits = reg_to_bits(base);
6532 check_ldst_imm12(offset)?;
6534 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6535 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6536 let mut bytes = hw1.to_le_bytes().to_vec();
6537 bytes.extend_from_slice(&hw2.to_le_bytes());
6538 Ok(bytes)
6539 }
6540
6541 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6543 let rd_bits = reg_to_bits(rd);
6544 let base_bits = reg_to_bits(base);
6545 let rm_bits = reg_to_bits(offset_reg);
6546 let hw1: u16 = (0xF820 | base_bits) as u16;
6548 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6549 let mut bytes = hw1.to_le_bytes().to_vec();
6550 bytes.extend_from_slice(&hw2.to_le_bytes());
6551 Ok(bytes)
6552 }
6553
6554 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6556 let rd_bits = reg_to_bits(rd);
6557 let rn_bits = reg_to_bits(rn);
6558
6559 if imm <= 0xFFF {
6565 let i_bit = (imm >> 11) & 1;
6566 let imm3 = (imm >> 8) & 0x7;
6567 let imm8 = imm & 0xFF;
6568
6569 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6570 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6571
6572 let mut bytes = hw1.to_le_bytes().to_vec();
6573 bytes.extend_from_slice(&hw2.to_le_bytes());
6574 Ok(bytes)
6575 } else {
6576 Err(synth_core::Error::synthesis(
6579 "ADD immediate too large for single instruction",
6580 ))
6581 }
6582 }
6583
6584 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6594 reg_bits_checked(rd)?;
6595 encoding_contracts::verify_imm16(imm16);
6596 let imm16 = imm16 & 0xFFFF;
6599 let imm4 = (imm16 >> 12) & 0xF;
6600 let i_bit = (imm16 >> 11) & 1;
6601 let imm3 = (imm16 >> 8) & 0x7;
6602 let imm8 = imm16 & 0xFF;
6603
6604 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6605 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6606
6607 let mut bytes = hw1.to_le_bytes().to_vec();
6608 bytes.extend_from_slice(&hw2.to_le_bytes());
6609 encoding_contracts::verify_thumb32(&bytes);
6610 Ok(bytes)
6611 }
6612
6613 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6621 reg_bits_checked(rd)?;
6622 encoding_contracts::verify_imm16(imm16);
6623 let imm16 = imm16 & 0xFFFF;
6626 let imm4 = (imm16 >> 12) & 0xF;
6627 let i_bit = (imm16 >> 11) & 1;
6628 let imm3 = (imm16 >> 8) & 0x7;
6629 let imm8 = imm16 & 0xFF;
6630
6631 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6632 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6633
6634 let mut bytes = hw1.to_le_bytes().to_vec();
6635 bytes.extend_from_slice(&hw2.to_le_bytes());
6636 encoding_contracts::verify_thumb32(&bytes);
6637 Ok(bytes)
6638 }
6639
6640 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6642 let imm5 = shift & 0x1F;
6645 let imm2 = imm5 & 0x3;
6646 let imm3 = (imm5 >> 2) & 0x7;
6647
6648 let hw1: u16 = 0xEA4F;
6649 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6650
6651 let mut bytes = hw1.to_le_bytes().to_vec();
6652 bytes.extend_from_slice(&hw2.to_le_bytes());
6653 Ok(bytes)
6654 }
6655
6656 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6658 let hw1: u16 = (0xEA00 | rn) as u16;
6661 let hw2: u16 = ((rd << 8) | rm) as u16;
6662
6663 let mut bytes = hw1.to_le_bytes().to_vec();
6664 bytes.extend_from_slice(&hw2.to_le_bytes());
6665 Ok(bytes)
6666 }
6667
6668 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6670 let i_bit = (imm >> 11) & 1;
6674 let imm3 = (imm >> 8) & 0x7;
6675 let imm8 = imm & 0xFF;
6676
6677 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6678 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6679
6680 let mut bytes = hw1.to_le_bytes().to_vec();
6681 bytes.extend_from_slice(&hw2.to_le_bytes());
6682 Ok(bytes)
6683 }
6684
6685 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6687 let hw1: u16 = (0xEBA0 | rn) as u16;
6690 let hw2: u16 = ((rd << 8) | rm) as u16;
6691
6692 let mut bytes = hw1.to_le_bytes().to_vec();
6693 bytes.extend_from_slice(&hw2.to_le_bytes());
6694 Ok(bytes)
6695 }
6696
6697 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6699 let hw1: u16 = (0xEB00 | rn) as u16;
6702 let hw2: u16 = ((rd << 8) | rm) as u16;
6703
6704 let mut bytes = hw1.to_le_bytes().to_vec();
6705 bytes.extend_from_slice(&hw2.to_le_bytes());
6706 Ok(bytes)
6707 }
6708
6709 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6713 let hw1: u16 = (0xEB10 | rn) as u16;
6715 let hw2: u16 = ((rd << 8) | rm) as u16;
6716 let mut bytes = hw1.to_le_bytes().to_vec();
6717 bytes.extend_from_slice(&hw2.to_le_bytes());
6718 Ok(bytes)
6719 }
6720
6721 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6724 let hw1: u16 = (0xEBB0 | rn) as u16;
6726 let hw2: u16 = ((rd << 8) | rm) as u16;
6727 let mut bytes = hw1.to_le_bytes().to_vec();
6728 bytes.extend_from_slice(&hw2.to_le_bytes());
6729 Ok(bytes)
6730 }
6731
6732 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6734 let mut code = Vec::new();
6735
6736 for op in ops {
6737 let encoded = self.encode(op)?;
6738 code.extend_from_slice(&encoded);
6739 }
6740
6741 Ok(code)
6742 }
6743}
6744
6745fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6753 if value <= 0xFF {
6755 return Some(value);
6756 }
6757 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6761 return Some(0x100 | b0);
6762 }
6763 if value == (b1 << 24) | (b1 << 8) {
6765 return Some(0x200 | b1);
6766 }
6767 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6769 return Some(0x300 | b0);
6770 }
6771 for rot in 8..=31u32 {
6775 let unrot = value.rotate_left(rot);
6776 if (0x80..=0xFF).contains(&unrot) {
6777 return Some((rot << 7) | (unrot & 0x7F));
6778 }
6779 }
6780 None
6781}
6782
6783fn check_ldst_imm12(offset: u32) -> Result<()> {
6789 if offset > 0xFFF {
6790 Err(synth_core::Error::synthesis(
6791 "load/store immediate offset > 0xFFF (4095) — materialize the offset into a register",
6792 ))
6793 } else {
6794 Ok(())
6795 }
6796}
6797
6798fn reg_to_bits(reg: &Reg) -> u32 {
6799 match reg {
6800 Reg::R0 => 0,
6801 Reg::R1 => 1,
6802 Reg::R2 => 2,
6803 Reg::R3 => 3,
6804 Reg::R4 => 4,
6805 Reg::R5 => 5,
6806 Reg::R6 => 6,
6807 Reg::R7 => 7,
6808 Reg::R8 => 8,
6809 Reg::R9 => 9,
6810 Reg::R10 => 10,
6811 Reg::R11 => 11,
6812 Reg::R12 => 12,
6813 Reg::SP => 13,
6814 Reg::LR => 14,
6815 Reg::PC => 15,
6816 }
6817}
6818
6819fn reg_bits_checked(bits: u32) -> Result<()> {
6827 if bits > 14 {
6828 return Err(synth_core::Error::synthesis(format!(
6829 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6830 )));
6831 }
6832 Ok(())
6833}
6834
6835fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6838 if val == 0 {
6839 return Some((0, 1));
6840 }
6841 for rot in 0..16u32 {
6842 let shift = rot * 2;
6843 let unrotated = val.rotate_left(shift);
6845 if unrotated <= 0xFF {
6846 return Some(((rot << 8) | unrotated, 1));
6848 }
6849 }
6850 None
6851}
6852
6853fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6858 match op2 {
6859 Operand2::Imm(val) => {
6860 let uval = *val as u32;
6861 if let Some(encoded) = try_encode_rotated_imm(uval) {
6863 encoded
6864 } else {
6865 let imm = uval & 0xFF;
6870 (imm, 1)
6871 }
6872 }
6873
6874 Operand2::Reg(reg) => {
6875 let reg_bits = reg_to_bits(reg);
6876 (reg_bits, 0) }
6878
6879 Operand2::RegShift {
6880 rm,
6881 shift: _,
6882 amount,
6883 } => {
6884 let rm_bits = reg_to_bits(rm);
6886 let shift_bits = (*amount & 0x1F) << 7;
6887 (shift_bits | rm_bits, 0)
6888 }
6889 }
6890}
6891
6892fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6894 let base_bits = reg_to_bits(&addr.base);
6895 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6897}
6898
6899fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6901 match reg {
6902 VfpReg::S0 => Ok(0),
6903 VfpReg::S1 => Ok(1),
6904 VfpReg::S2 => Ok(2),
6905 VfpReg::S3 => Ok(3),
6906 VfpReg::S4 => Ok(4),
6907 VfpReg::S5 => Ok(5),
6908 VfpReg::S6 => Ok(6),
6909 VfpReg::S7 => Ok(7),
6910 VfpReg::S8 => Ok(8),
6911 VfpReg::S9 => Ok(9),
6912 VfpReg::S10 => Ok(10),
6913 VfpReg::S11 => Ok(11),
6914 VfpReg::S12 => Ok(12),
6915 VfpReg::S13 => Ok(13),
6916 VfpReg::S14 => Ok(14),
6917 VfpReg::S15 => Ok(15),
6918 VfpReg::S16 => Ok(16),
6919 VfpReg::S17 => Ok(17),
6920 VfpReg::S18 => Ok(18),
6921 VfpReg::S19 => Ok(19),
6922 VfpReg::S20 => Ok(20),
6923 VfpReg::S21 => Ok(21),
6924 VfpReg::S22 => Ok(22),
6925 VfpReg::S23 => Ok(23),
6926 VfpReg::S24 => Ok(24),
6927 VfpReg::S25 => Ok(25),
6928 VfpReg::S26 => Ok(26),
6929 VfpReg::S27 => Ok(27),
6930 VfpReg::S28 => Ok(28),
6931 VfpReg::S29 => Ok(29),
6932 VfpReg::S30 => Ok(30),
6933 VfpReg::S31 => Ok(31),
6934 _ => Err(synth_core::Error::SynthesisError(
6936 "D-register not supported in single-precision VFP encoding".to_string(),
6937 )),
6938 }
6939}
6940
6941fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6943 match reg {
6944 VfpReg::D0 => Ok(0),
6945 VfpReg::D1 => Ok(1),
6946 VfpReg::D2 => Ok(2),
6947 VfpReg::D3 => Ok(3),
6948 VfpReg::D4 => Ok(4),
6949 VfpReg::D5 => Ok(5),
6950 VfpReg::D6 => Ok(6),
6951 VfpReg::D7 => Ok(7),
6952 VfpReg::D8 => Ok(8),
6953 VfpReg::D9 => Ok(9),
6954 VfpReg::D10 => Ok(10),
6955 VfpReg::D11 => Ok(11),
6956 VfpReg::D12 => Ok(12),
6957 VfpReg::D13 => Ok(13),
6958 VfpReg::D14 => Ok(14),
6959 VfpReg::D15 => Ok(15),
6960 _ => Err(synth_core::Error::SynthesisError(
6962 "S-register not supported in double-precision VFP encoding".to_string(),
6963 )),
6964 }
6965}
6966
6967fn encode_sreg(s: u32) -> (u32, u32) {
6971 (s >> 1, s & 1)
6972}
6973
6974fn encode_dreg(d: u32) -> (u32, u32) {
6978 (d & 0xF, (d >> 4) & 1)
6979}
6980
6981fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6987 let sd_num = vfp_sreg_to_num(sd)?;
6988 let sn_num = vfp_sreg_to_num(sn)?;
6989 let sm_num = vfp_sreg_to_num(sm)?;
6990 let (vd, d) = encode_sreg(sd_num);
6991 let (vn, n) = encode_sreg(sn_num);
6992 let (vm, m) = encode_sreg(sm_num);
6993
6994 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6995}
6996
6997fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
7000 let sd_num = vfp_sreg_to_num(sd)?;
7001 let sm_num = vfp_sreg_to_num(sm)?;
7002 let (vd, d) = encode_sreg(sd_num);
7003 let (vm, m) = encode_sreg(sm_num);
7004
7005 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7006}
7007
7008fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7012 let sd_num = vfp_sreg_to_num(sd)?;
7013 let (vd, d) = encode_sreg(sd_num);
7014 let rn = reg_to_bits(&addr.base);
7015
7016 let offset = addr.offset;
7017 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7018 let abs_offset = offset.unsigned_abs();
7019 let imm8 = (abs_offset / 4) & 0xFF;
7020
7021 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7022}
7023
7024fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
7028 let s_num = vfp_sreg_to_num(sreg)?;
7029 let (vn, n) = encode_sreg(s_num);
7030 let rt = reg_to_bits(core);
7031
7032 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
7033 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
7034}
7035
7036fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
7040 let dd_num = vfp_dreg_to_num(dd)?;
7041 let dn_num = vfp_dreg_to_num(dn)?;
7042 let dm_num = vfp_dreg_to_num(dm)?;
7043 let (vd, d) = encode_dreg(dd_num);
7044 let (vn, n) = encode_dreg(dn_num);
7045 let (vm, m) = encode_dreg(dm_num);
7046
7047 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7048}
7049
7050fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
7052 let dd_num = vfp_dreg_to_num(dd)?;
7053 let dm_num = vfp_dreg_to_num(dm)?;
7054 let (vd, d) = encode_dreg(dd_num);
7055 let (vm, m) = encode_dreg(dm_num);
7056
7057 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7058}
7059
7060fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7063 let dd_num = vfp_dreg_to_num(dd)?;
7064 let (vd, d) = encode_dreg(dd_num);
7065 let rn = reg_to_bits(&addr.base);
7066
7067 let offset = addr.offset;
7068 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7069 let abs_offset = offset.unsigned_abs();
7070 let imm8 = (abs_offset / 4) & 0xFF;
7071
7072 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7073}
7074
7075fn encode_vmov_core_dreg(
7079 to_dreg: bool,
7080 dreg: &VfpReg,
7081 core_lo: &Reg,
7082 core_hi: &Reg,
7083) -> Result<u32> {
7084 let d_num = vfp_dreg_to_num(dreg)?;
7085 let (vm, m) = encode_dreg(d_num);
7086 let rt = reg_to_bits(core_lo);
7087 let rt2 = reg_to_bits(core_hi);
7088
7089 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
7090 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
7091}
7092
7093fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
7095 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
7096 let hw2 = (instr & 0xFFFF) as u16;
7097 let mut bytes = hw1.to_le_bytes().to_vec();
7098 bytes.extend_from_slice(&hw2.to_le_bytes());
7099 bytes
7100}
7101
7102fn qreg_to_num(reg: &QReg) -> u32 {
7108 match reg {
7109 QReg::Q0 => 0,
7110 QReg::Q1 => 1,
7111 QReg::Q2 => 2,
7112 QReg::Q3 => 3,
7113 QReg::Q4 => 4,
7114 QReg::Q5 => 5,
7115 QReg::Q6 => 6,
7116 QReg::Q7 => 7,
7117 }
7118}
7119
7120fn mve_size_bits(size: &MveSize) -> u32 {
7122 match size {
7123 MveSize::S8 => 0b00,
7124 MveSize::S16 => 0b01,
7125 MveSize::S32 => 0b10,
7126 }
7127}
7128
7129fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7133 let d = qreg_to_num(qd) * 2;
7134 let n = qreg_to_num(qn) * 2;
7135 let m = qreg_to_num(qm) * 2;
7136
7137 let vd = d & 0xF;
7142 let d_bit = (d >> 4) & 1;
7143 let vn = n & 0xF;
7144 let n_bit = (n >> 4) & 1;
7145 let vm = m & 0xF;
7146 let m_bit = (m >> 4) & 1;
7147
7148 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7149}
7150
7151fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7153 encode_mve_3reg(base, qd, qn, qm)
7154}
7155
7156fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7159 let qd_enc = qreg_to_num(qd) * 2;
7160 let rn = reg_to_bits(&addr.base);
7161 let offset = addr.offset;
7162 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7163 let abs_offset = offset.unsigned_abs();
7164 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7168 | (u_bit << 23)
7169 | ((qd_enc >> 4) << 22)
7170 | (rn << 16)
7171 | ((qd_enc & 0xF) << 12)
7172 | (imm7 & 0x7F)
7173}
7174
7175fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7177 let qd_enc = qreg_to_num(qd) * 2;
7178 let rn = reg_to_bits(&addr.base);
7179 let offset = addr.offset;
7180 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7181 let abs_offset = offset.unsigned_abs();
7182 let imm7 = (abs_offset / 4) & 0x7F;
7183
7184 0xED000E80
7185 | (u_bit << 23)
7186 | ((qd_enc >> 4) << 22)
7187 | (rn << 16)
7188 | ((qd_enc & 0xF) << 12)
7189 | (imm7 & 0x7F)
7190}
7191
7192impl ArmEncoder {
7193 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7195 let mut result = Vec::new();
7196 let qd_num = qreg_to_num(qd);
7197
7198 for i in 0..4 {
7200 let word = u32::from_le_bytes([
7201 bytes[i * 4],
7202 bytes[i * 4 + 1],
7203 bytes[i * 4 + 2],
7204 bytes[i * 4 + 3],
7205 ]);
7206 let lo16 = word & 0xFFFF;
7207 let hi16 = (word >> 16) & 0xFFFF;
7208
7209 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7211 if hi16 != 0 {
7213 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7214 }
7215
7216 let s_num = qd_num * 4 + i as u32;
7218 let (vn, n) = encode_sreg(s_num);
7219 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7220 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7221 }
7222
7223 Ok(result)
7224 }
7225
7226 fn encode_thumb_mve_lane_wise_f32_binop(
7228 &self,
7229 qd: &QReg,
7230 qn: &QReg,
7231 qm: &QReg,
7232 vfp_base: u32,
7233 ) -> Result<Vec<u8>> {
7234 let mut result = Vec::new();
7235 let qd_num = qreg_to_num(qd);
7236 let qn_num = qreg_to_num(qn);
7237 let qm_num = qreg_to_num(qm);
7238
7239 for i in 0..4u32 {
7241 let sd = qd_num * 4 + i;
7242 let sn = qn_num * 4 + i;
7243 let sm = qm_num * 4 + i;
7244
7245 let (vd, d) = encode_sreg(sd);
7246 let (vn, n) = encode_sreg(sn);
7247 let (vm, m) = encode_sreg(sm);
7248
7249 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7250 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7251 }
7252
7253 Ok(result)
7254 }
7255
7256 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7258 let mut result = Vec::new();
7259 let qd_num = qreg_to_num(qd);
7260 let qm_num = qreg_to_num(qm);
7261
7262 for i in 0..4u32 {
7264 let sd = qd_num * 4 + i;
7265 let sm = qm_num * 4 + i;
7266
7267 let (vd, d) = encode_sreg(sd);
7268 let (vm, m) = encode_sreg(sm);
7269
7270 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7271 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7272 }
7273
7274 Ok(result)
7275 }
7276}
7277
7278#[cfg(test)]
7279mod tests {
7280 use super::*;
7281
7282 #[test]
7283 fn test_encoder_creation() {
7284 let encoder_arm = ArmEncoder::new_arm32();
7285 assert!(!encoder_arm.thumb_mode);
7286
7287 let encoder_thumb = ArmEncoder::new_thumb2();
7288 assert!(encoder_thumb.thumb_mode);
7289 }
7290
7291 #[test]
7303 fn test_encode_i64setcond_high_reg_uses_mov_w_311() {
7304 use synth_synthesis::{ArmOp, Condition, Reg};
7305 let enc = ArmEncoder::new_thumb2();
7306 let bytes = enc
7307 .encode(&ArmOp::I64SetCond {
7308 rd: Reg::R8,
7309 rn_lo: Reg::R2,
7310 rn_hi: Reg::R3,
7311 rm_lo: Reg::R6,
7312 rm_hi: Reg::R7,
7313 cond: Condition::EQ,
7314 })
7315 .unwrap();
7316 let halfwords: Vec<u16> = bytes
7319 .chunks(2)
7320 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7321 .collect();
7322 assert!(
7323 halfwords.iter().filter(|&&h| h == 0xF04F).count() == 2,
7324 "high rd must use two MOV.W (T2) encodings, got {halfwords:04x?}"
7325 );
7326 assert!(
7327 !halfwords.contains(&0x2801) && !halfwords.contains(&0x2800),
7328 "no transmuted 16-bit CMP imm: {halfwords:04x?}"
7329 );
7330
7331 let bytes_z = enc
7332 .encode(&ArmOp::I64SetCondZ {
7333 rd: Reg::R8,
7334 rn_lo: Reg::R2,
7335 rn_hi: Reg::R3,
7336 })
7337 .unwrap();
7338 let hw_z: Vec<u16> = bytes_z
7339 .chunks(2)
7340 .map(|c| u16::from_le_bytes([c[0], c[1]]))
7341 .collect();
7342 assert!(
7343 hw_z.iter().filter(|&&h| h == 0xF04F).count() == 2,
7344 "SetCondZ high rd MOV.W: {hw_z:04x?}"
7345 );
7346 assert!(
7348 hw_z.contains(&(0xF1B0 | 8)),
7349 "SetCondZ high rd must use CMP.W: {hw_z:04x?}"
7350 );
7351 }
7352
7353 #[test]
7354 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7355 use synth_synthesis::{ArmOp, Condition, Reg};
7356 let enc = ArmEncoder::new_thumb2();
7357 let hi = enc
7359 .encode(&ArmOp::SetCond {
7360 rd: Reg::R12,
7361 cond: Condition::NE,
7362 })
7363 .unwrap();
7364 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7365 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7367 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7368 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7369 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7370 let lo = enc
7372 .encode(&ArmOp::SetCond {
7373 rd: Reg::R0,
7374 cond: Condition::NE,
7375 })
7376 .unwrap();
7377 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7378 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7379 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7380 }
7381
7382 #[test]
7386 fn test_encode_umull_209b() {
7387 use synth_synthesis::{ArmOp, Reg};
7388 let op = ArmOp::Umull {
7389 rdlo: Reg::R4,
7390 rdhi: Reg::R5,
7391 rn: Reg::R0,
7392 rm: Reg::R3,
7393 };
7394 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7396 assert_eq!(
7397 t,
7398 vec![0xA0, 0xFB, 0x03, 0x45],
7399 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7400 );
7401 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7403 assert_eq!(
7404 a,
7405 0xE085_4390u32.to_le_bytes().to_vec(),
7406 "umull (A32): {a:02x?}"
7407 );
7408 }
7409
7410 #[test]
7417 fn test_encode_arm32_indexed_load_keeps_index_206() {
7418 use synth_synthesis::{ArmOp, MemAddr, Reg};
7419 let enc = ArmEncoder::new_arm32();
7420 let bytes = enc
7422 .encode(&ArmOp::Ldr {
7423 rd: Reg::R0,
7424 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7425 })
7426 .unwrap();
7427 assert_eq!(
7428 bytes.len(),
7429 8,
7430 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7431 );
7432 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7433 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7434 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7436 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7438 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7440 }
7441
7442 #[test]
7449 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7450 let encoder = ArmEncoder::new_thumb2();
7451
7452 let code = encoder
7454 .encode(&ArmOp::Add {
7455 rd: Reg::R12,
7456 rn: Reg::R12,
7457 op2: Operand2::Reg(Reg::R0),
7458 })
7459 .unwrap();
7460 assert_eq!(
7462 code,
7463 vec![0x0C, 0xEB, 0x00, 0x0C],
7464 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7465 );
7466 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7468
7469 let lo = encoder
7471 .encode(&ArmOp::Add {
7472 rd: Reg::R1,
7473 rn: Reg::R2,
7474 op2: Operand2::Reg(Reg::R3),
7475 })
7476 .unwrap();
7477 assert_eq!(
7478 lo.len(),
7479 2,
7480 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7481 );
7482 }
7483
7484 #[test]
7487 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7488 let encoder = ArmEncoder::new_thumb2();
7489
7490 let adds = encoder
7492 .encode(&ArmOp::Adds {
7493 rd: Reg::R10,
7494 rn: Reg::R10,
7495 op2: Operand2::Reg(Reg::R8),
7496 })
7497 .unwrap();
7498 assert_eq!(
7499 adds,
7500 vec![0x1A, 0xEB, 0x08, 0x0A],
7501 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7502 );
7503
7504 let subs = encoder
7506 .encode(&ArmOp::Subs {
7507 rd: Reg::R10,
7508 rn: Reg::R10,
7509 op2: Operand2::Reg(Reg::R8),
7510 })
7511 .unwrap();
7512 assert_eq!(
7513 subs,
7514 vec![0xBA, 0xEB, 0x08, 0x0A],
7515 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7516 );
7517 }
7518
7519 #[test]
7522 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7523 let encoder = ArmEncoder::new_thumb2();
7524
7525 let cmn = encoder
7527 .encode(&ArmOp::Cmn {
7528 rn: Reg::R10,
7529 op2: Operand2::Reg(Reg::R8),
7530 })
7531 .unwrap();
7532 assert_eq!(
7533 cmn,
7534 vec![0x1A, 0xEB, 0x08, 0x0F],
7535 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7536 );
7537
7538 let lo = encoder
7540 .encode(&ArmOp::Cmn {
7541 rn: Reg::R1,
7542 op2: Operand2::Reg(Reg::R2),
7543 })
7544 .unwrap();
7545 assert_eq!(
7546 lo.len(),
7547 2,
7548 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7549 );
7550 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7551 }
7552
7553 #[test]
7557 fn test_encode_pc_operand_returns_err_not_panic_185() {
7558 let encoder = ArmEncoder::new_thumb2();
7559 for op in [
7560 ArmOp::Sdiv {
7561 rd: Reg::PC,
7562 rn: Reg::R0,
7563 rm: Reg::R1,
7564 },
7565 ArmOp::Udiv {
7566 rd: Reg::R0,
7567 rn: Reg::PC,
7568 rm: Reg::R1,
7569 },
7570 ArmOp::Sdiv {
7571 rd: Reg::R0,
7572 rn: Reg::R1,
7573 rm: Reg::PC,
7574 },
7575 ] {
7576 let r = encoder.encode(&op);
7577 assert!(
7578 r.is_err(),
7579 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7580 );
7581 }
7582 assert!(
7584 encoder
7585 .encode(&ArmOp::Sdiv {
7586 rd: Reg::R0,
7587 rn: Reg::R1,
7588 rm: Reg::R2
7589 })
7590 .is_ok()
7591 );
7592 }
7593
7594 #[test]
7595 fn test_encode_nop_arm32() {
7596 let encoder = ArmEncoder::new_arm32();
7597 let code = encoder.encode(&ArmOp::Nop).unwrap();
7598
7599 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7602
7603 #[test]
7604 fn test_encode_nop_thumb() {
7605 let encoder = ArmEncoder::new_thumb2();
7606 let code = encoder.encode(&ArmOp::Nop).unwrap();
7607
7608 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7611
7612 #[test]
7613 fn test_encode_mov_immediate_arm32() {
7614 let encoder = ArmEncoder::new_arm32();
7615 let op = ArmOp::Mov {
7616 rd: Reg::R0,
7617 op2: Operand2::Imm(42),
7618 };
7619
7620 let code = encoder.encode(&op).unwrap();
7621 assert_eq!(code.len(), 4);
7622
7623 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7625 assert_eq!(instr & 0x0E000000, 0x02000000); }
7627
7628 #[test]
7629 fn test_encode_add_registers_arm32() {
7630 let encoder = ArmEncoder::new_arm32();
7631 let op = ArmOp::Add {
7632 rd: Reg::R0,
7633 rn: Reg::R1,
7634 op2: Operand2::Reg(Reg::R2),
7635 };
7636
7637 let code = encoder.encode(&op).unwrap();
7638 assert_eq!(code.len(), 4);
7639
7640 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7641 assert_eq!(instr & 0x0FE00000, 0x00800000);
7643 }
7644
7645 #[test]
7646 fn test_encode_ldr_arm32() {
7647 let encoder = ArmEncoder::new_arm32();
7648 let op = ArmOp::Ldr {
7649 rd: Reg::R0,
7650 addr: MemAddr::imm(Reg::R1, 4),
7651 };
7652
7653 let code = encoder.encode(&op).unwrap();
7654 assert_eq!(code.len(), 4);
7655
7656 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7657 assert_eq!(instr & 0x00100000, 0x00100000);
7659 }
7660
7661 #[test]
7662 fn test_encode_str_arm32() {
7663 let encoder = ArmEncoder::new_arm32();
7664 let op = ArmOp::Str {
7665 rd: Reg::R0,
7666 addr: MemAddr::imm(Reg::SP, 0),
7667 };
7668
7669 let code = encoder.encode(&op).unwrap();
7670 assert_eq!(code.len(), 4);
7671 }
7672
7673 #[test]
7674 fn test_encode_branch_arm32() {
7675 let encoder = ArmEncoder::new_arm32();
7676 let op = ArmOp::Bl {
7677 label: "main".to_string(),
7678 };
7679
7680 let code = encoder.encode(&op).unwrap();
7681 assert_eq!(code.len(), 4);
7682
7683 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7684 assert_eq!(instr & 0x0F000000, 0x0B000000);
7686 }
7687
7688 #[test]
7698 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7699 let encoder = ArmEncoder::new_thumb2();
7700 let op = ArmOp::Bl {
7701 label: "callee".to_string(),
7702 };
7703
7704 let code = encoder.encode(&op).unwrap();
7705 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7706
7707 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7708 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7709 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7710 assert_eq!(
7711 hw2, 0xFFFE,
7712 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7713 );
7714 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7715 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7716 }
7717
7718 #[test]
7719 fn test_encode_sequence() {
7720 let encoder = ArmEncoder::new_arm32();
7721 let ops = vec![
7722 ArmOp::Mov {
7723 rd: Reg::R0,
7724 op2: Operand2::Imm(42),
7725 },
7726 ArmOp::Mov {
7727 rd: Reg::R1,
7728 op2: Operand2::Imm(10),
7729 },
7730 ArmOp::Add {
7731 rd: Reg::R2,
7732 rn: Reg::R0,
7733 op2: Operand2::Reg(Reg::R1),
7734 },
7735 ];
7736
7737 let code = encoder.encode_sequence(&ops).unwrap();
7738 assert_eq!(code.len(), 12); }
7740
7741 #[test]
7742 fn test_reg_to_bits() {
7743 assert_eq!(reg_to_bits(&Reg::R0), 0);
7744 assert_eq!(reg_to_bits(&Reg::R7), 7);
7745 assert_eq!(reg_to_bits(&Reg::SP), 13);
7746 assert_eq!(reg_to_bits(&Reg::LR), 14);
7747 assert_eq!(reg_to_bits(&Reg::PC), 15);
7748 }
7749
7750 #[test]
7751 fn test_encode_bitwise_operations() {
7752 let encoder = ArmEncoder::new_arm32();
7753
7754 let and_op = ArmOp::And {
7755 rd: Reg::R0,
7756 rn: Reg::R1,
7757 op2: Operand2::Reg(Reg::R2),
7758 };
7759 let and_code = encoder.encode(&and_op).unwrap();
7760 assert_eq!(and_code.len(), 4);
7761
7762 let orr_op = ArmOp::Orr {
7763 rd: Reg::R0,
7764 rn: Reg::R1,
7765 op2: Operand2::Reg(Reg::R2),
7766 };
7767 let orr_code = encoder.encode(&orr_op).unwrap();
7768 assert_eq!(orr_code.len(), 4);
7769
7770 let eor_op = ArmOp::Eor {
7771 rd: Reg::R0,
7772 rn: Reg::R1,
7773 op2: Operand2::Reg(Reg::R2),
7774 };
7775 let eor_code = encoder.encode(&eor_op).unwrap();
7776 assert_eq!(eor_code.len(), 4);
7777 }
7778
7779 #[test]
7782 fn test_encode_sdiv_thumb2() {
7783 let encoder = ArmEncoder::new_thumb2();
7784 let op = ArmOp::Sdiv {
7785 rd: Reg::R0,
7786 rn: Reg::R1,
7787 rm: Reg::R2,
7788 };
7789
7790 let code = encoder.encode(&op).unwrap();
7791 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7798 assert_eq!(code[1], 0xFB);
7799 assert_eq!(code[2], 0xF2);
7800 assert_eq!(code[3], 0xF0);
7801 }
7802
7803 #[test]
7804 fn test_encode_udiv_thumb2() {
7805 let encoder = ArmEncoder::new_thumb2();
7806 let op = ArmOp::Udiv {
7807 rd: Reg::R0,
7808 rn: Reg::R1,
7809 rm: Reg::R2,
7810 };
7811
7812 let code = encoder.encode(&op).unwrap();
7813 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7818 assert_eq!(code[1], 0xFB);
7819 assert_eq!(code[2], 0xF2);
7820 assert_eq!(code[3], 0xF0);
7821 }
7822
7823 #[test]
7824 fn test_encode_mul_thumb2() {
7825 let encoder = ArmEncoder::new_thumb2();
7826 let op = ArmOp::Mul {
7827 rd: Reg::R0,
7828 rn: Reg::R1,
7829 rm: Reg::R2,
7830 };
7831
7832 let code = encoder.encode(&op).unwrap();
7833 assert_eq!(code.len(), 4); }
7835
7836 #[test]
7837 fn test_encode_and_thumb2() {
7838 let encoder = ArmEncoder::new_thumb2();
7839 let op = ArmOp::And {
7840 rd: Reg::R0,
7841 rn: Reg::R1,
7842 op2: Operand2::Reg(Reg::R2),
7843 };
7844
7845 let code = encoder.encode(&op).unwrap();
7846 assert_eq!(code.len(), 4); }
7848
7849 #[test]
7850 fn test_encode_lsl_thumb2_low_regs() {
7851 let encoder = ArmEncoder::new_thumb2();
7852 let op = ArmOp::Lsl {
7853 rd: Reg::R0,
7854 rn: Reg::R1,
7855 shift: 5,
7856 };
7857
7858 let code = encoder.encode(&op).unwrap();
7859 assert_eq!(code.len(), 2); }
7861
7862 #[test]
7863 fn test_encode_clz_thumb2() {
7864 let encoder = ArmEncoder::new_thumb2();
7865 let op = ArmOp::Clz {
7866 rd: Reg::R0,
7867 rm: Reg::R1,
7868 };
7869
7870 let code = encoder.encode(&op).unwrap();
7871 assert_eq!(code.len(), 4); }
7873
7874 #[test]
7875 fn test_encode_bx_thumb2() {
7876 let encoder = ArmEncoder::new_thumb2();
7877 let op = ArmOp::Bx { rm: Reg::LR };
7878
7879 let code = encoder.encode(&op).unwrap();
7880 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7884 }
7885
7886 #[test]
7891 fn test_encode_f32_abs_arm32() {
7892 let encoder = ArmEncoder::new_arm32();
7893 let op = ArmOp::F32Abs {
7894 sd: VfpReg::S0,
7895 sm: VfpReg::S2,
7896 };
7897 let code = encoder.encode(&op).unwrap();
7898 assert_eq!(code.len(), 4); }
7900
7901 #[test]
7902 fn test_encode_f32_neg_arm32() {
7903 let encoder = ArmEncoder::new_arm32();
7904 let op = ArmOp::F32Neg {
7905 sd: VfpReg::S0,
7906 sm: VfpReg::S2,
7907 };
7908 let code = encoder.encode(&op).unwrap();
7909 assert_eq!(code.len(), 4);
7910 }
7911
7912 #[test]
7913 fn test_encode_f32_sqrt_arm32() {
7914 let encoder = ArmEncoder::new_arm32();
7915 let op = ArmOp::F32Sqrt {
7916 sd: VfpReg::S0,
7917 sm: VfpReg::S2,
7918 };
7919 let code = encoder.encode(&op).unwrap();
7920 assert_eq!(code.len(), 4);
7921 }
7922
7923 #[test]
7924 fn test_encode_f32_ceil_arm32() {
7925 let encoder = ArmEncoder::new_arm32();
7926 let op = ArmOp::F32Ceil {
7927 sd: VfpReg::S0,
7928 sm: VfpReg::S2,
7929 };
7930 let code = encoder.encode(&op).unwrap();
7931 assert_eq!(code.len(), 36);
7933 }
7934
7935 #[test]
7936 fn test_encode_f32_floor_thumb2() {
7937 let encoder = ArmEncoder::new_thumb2();
7938 let op = ArmOp::F32Floor {
7939 sd: VfpReg::S0,
7940 sm: VfpReg::S2,
7941 };
7942 let code = encoder.encode(&op).unwrap();
7943 assert_eq!(code.len(), 36);
7945 }
7946
7947 #[test]
7948 fn test_encode_f32_min_arm32() {
7949 let encoder = ArmEncoder::new_arm32();
7950 let op = ArmOp::F32Min {
7951 sd: VfpReg::S0,
7952 sn: VfpReg::S2,
7953 sm: VfpReg::S4,
7954 };
7955 let code = encoder.encode(&op).unwrap();
7956 assert_eq!(code.len(), 16); }
7958
7959 #[test]
7960 fn test_encode_f32_max_thumb2() {
7961 let encoder = ArmEncoder::new_thumb2();
7962 let op = ArmOp::F32Max {
7963 sd: VfpReg::S0,
7964 sn: VfpReg::S2,
7965 sm: VfpReg::S4,
7966 };
7967 let code = encoder.encode(&op).unwrap();
7968 assert_eq!(code.len(), 18);
7970 }
7971
7972 #[test]
7973 fn test_encode_f32_copysign_arm32() {
7974 let encoder = ArmEncoder::new_arm32();
7975 let op = ArmOp::F32Copysign {
7976 sd: VfpReg::S0,
7977 sn: VfpReg::S2,
7978 sm: VfpReg::S4,
7979 };
7980 let code = encoder.encode(&op).unwrap();
7981 assert_eq!(code.len(), 24);
7983 }
7984
7985 #[test]
7990 fn test_encode_f64_add_arm32() {
7991 let encoder = ArmEncoder::new_arm32();
7992 let op = ArmOp::F64Add {
7993 dd: VfpReg::D0,
7994 dn: VfpReg::D1,
7995 dm: VfpReg::D2,
7996 };
7997 let code = encoder.encode(&op).unwrap();
7998 assert_eq!(code.len(), 4);
7999 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8001 assert_eq!((instr >> 8) & 0xF, 0xB); }
8003
8004 #[test]
8005 fn test_encode_f64_sub_thumb2() {
8006 let encoder = ArmEncoder::new_thumb2();
8007 let op = ArmOp::F64Sub {
8008 dd: VfpReg::D0,
8009 dn: VfpReg::D1,
8010 dm: VfpReg::D2,
8011 };
8012 let code = encoder.encode(&op).unwrap();
8013 assert_eq!(code.len(), 4); }
8015
8016 #[test]
8017 fn test_encode_f64_mul_arm32() {
8018 let encoder = ArmEncoder::new_arm32();
8019 let op = ArmOp::F64Mul {
8020 dd: VfpReg::D0,
8021 dn: VfpReg::D1,
8022 dm: VfpReg::D2,
8023 };
8024 let code = encoder.encode(&op).unwrap();
8025 assert_eq!(code.len(), 4);
8026 }
8027
8028 #[test]
8029 fn test_encode_f64_div_arm32() {
8030 let encoder = ArmEncoder::new_arm32();
8031 let op = ArmOp::F64Div {
8032 dd: VfpReg::D0,
8033 dn: VfpReg::D1,
8034 dm: VfpReg::D2,
8035 };
8036 let code = encoder.encode(&op).unwrap();
8037 assert_eq!(code.len(), 4);
8038 }
8039
8040 #[test]
8041 fn test_encode_f64_abs_arm32() {
8042 let encoder = ArmEncoder::new_arm32();
8043 let op = ArmOp::F64Abs {
8044 dd: VfpReg::D0,
8045 dm: VfpReg::D2,
8046 };
8047 let code = encoder.encode(&op).unwrap();
8048 assert_eq!(code.len(), 4);
8049 }
8050
8051 #[test]
8052 fn test_encode_f64_neg_arm32() {
8053 let encoder = ArmEncoder::new_arm32();
8054 let op = ArmOp::F64Neg {
8055 dd: VfpReg::D0,
8056 dm: VfpReg::D2,
8057 };
8058 let code = encoder.encode(&op).unwrap();
8059 assert_eq!(code.len(), 4);
8060 }
8061
8062 #[test]
8063 fn test_encode_f64_sqrt_arm32() {
8064 let encoder = ArmEncoder::new_arm32();
8065 let op = ArmOp::F64Sqrt {
8066 dd: VfpReg::D0,
8067 dm: VfpReg::D2,
8068 };
8069 let code = encoder.encode(&op).unwrap();
8070 assert_eq!(code.len(), 4);
8071 }
8072
8073 #[test]
8074 fn test_encode_f64_load_arm32() {
8075 let encoder = ArmEncoder::new_arm32();
8076 let op = ArmOp::F64Load {
8077 dd: VfpReg::D0,
8078 addr: MemAddr::imm(Reg::R0, 8),
8079 };
8080 let code = encoder.encode(&op).unwrap();
8081 assert_eq!(code.len(), 4);
8082 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8083 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
8086
8087 #[test]
8088 fn test_encode_f64_store_thumb2() {
8089 let encoder = ArmEncoder::new_thumb2();
8090 let op = ArmOp::F64Store {
8091 dd: VfpReg::D0,
8092 addr: MemAddr::imm(Reg::SP, 0),
8093 };
8094 let code = encoder.encode(&op).unwrap();
8095 assert_eq!(code.len(), 4);
8096 }
8097
8098 #[test]
8099 fn test_encode_f64_compare_arm32() {
8100 let encoder = ArmEncoder::new_arm32();
8101 let op = ArmOp::F64Eq {
8102 rd: Reg::R0,
8103 dn: VfpReg::D0,
8104 dm: VfpReg::D1,
8105 };
8106 let code = encoder.encode(&op).unwrap();
8107 assert_eq!(code.len(), 16); }
8109
8110 #[test]
8111 fn test_encode_f64_compare_thumb2() {
8112 let encoder = ArmEncoder::new_thumb2();
8113 let op = ArmOp::F64Lt {
8114 rd: Reg::R0,
8115 dn: VfpReg::D0,
8116 dm: VfpReg::D1,
8117 };
8118 let code = encoder.encode(&op).unwrap();
8119 assert_eq!(code.len(), 14);
8121 }
8122
8123 #[test]
8124 fn test_encode_f64_const_arm32() {
8125 let encoder = ArmEncoder::new_arm32();
8126 let op = ArmOp::F64Const {
8127 dd: VfpReg::D0,
8128 value: 3.125,
8129 };
8130 let code = encoder.encode(&op).unwrap();
8131 assert_eq!(code.len(), 20);
8133 }
8134
8135 #[test]
8136 fn test_encode_f64_const_thumb2() {
8137 let encoder = ArmEncoder::new_thumb2();
8138 let op = ArmOp::F64Const {
8139 dd: VfpReg::D0,
8140 value: 2.5,
8141 };
8142 let code = encoder.encode(&op).unwrap();
8143 assert_eq!(code.len(), 20);
8145 }
8146
8147 #[test]
8148 fn test_encode_f64_convert_i32s_arm32() {
8149 let encoder = ArmEncoder::new_arm32();
8150 let op = ArmOp::F64ConvertI32S {
8151 dd: VfpReg::D0,
8152 rm: Reg::R0,
8153 };
8154 let code = encoder.encode(&op).unwrap();
8155 assert_eq!(code.len(), 8);
8157 }
8158
8159 #[test]
8160 fn test_encode_f64_promote_f32_arm32() {
8161 let encoder = ArmEncoder::new_arm32();
8162 let op = ArmOp::F64PromoteF32 {
8163 dd: VfpReg::D0,
8164 sm: VfpReg::S0,
8165 };
8166 let code = encoder.encode(&op).unwrap();
8167 assert_eq!(code.len(), 4); }
8169
8170 #[test]
8171 fn test_encode_f64_promote_f32_thumb2() {
8172 let encoder = ArmEncoder::new_thumb2();
8173 let op = ArmOp::F64PromoteF32 {
8174 dd: VfpReg::D0,
8175 sm: VfpReg::S0,
8176 };
8177 let code = encoder.encode(&op).unwrap();
8178 assert_eq!(code.len(), 4);
8179 }
8180
8181 #[test]
8182 fn test_encode_i32_trunc_f64s_arm32() {
8183 let encoder = ArmEncoder::new_arm32();
8184 let op = ArmOp::I32TruncF64S {
8185 rd: Reg::R0,
8186 dm: VfpReg::D0,
8187 };
8188 let code = encoder.encode(&op).unwrap();
8189 assert_eq!(code.len(), 8);
8191 }
8192
8193 #[test]
8194 fn test_encode_f64_reinterpret_i64_arm32() {
8195 let encoder = ArmEncoder::new_arm32();
8196 let op = ArmOp::F64ReinterpretI64 {
8197 dd: VfpReg::D0,
8198 rmlo: Reg::R0,
8199 rmhi: Reg::R1,
8200 };
8201 let code = encoder.encode(&op).unwrap();
8202 assert_eq!(code.len(), 4); }
8204
8205 #[test]
8206 fn test_encode_i64_reinterpret_f64_thumb2() {
8207 let encoder = ArmEncoder::new_thumb2();
8208 let op = ArmOp::I64ReinterpretF64 {
8209 rdlo: Reg::R0,
8210 rdhi: Reg::R1,
8211 dm: VfpReg::D0,
8212 };
8213 let code = encoder.encode(&op).unwrap();
8214 assert_eq!(code.len(), 4);
8215 }
8216
8217 #[test]
8218 fn test_encode_f64_trunc_thumb2() {
8219 let encoder = ArmEncoder::new_thumb2();
8220 let op = ArmOp::F64Trunc {
8221 dd: VfpReg::D0,
8222 dm: VfpReg::D1,
8223 };
8224 let code = encoder.encode(&op).unwrap();
8225 assert_eq!(code.len(), 8);
8227 }
8228
8229 #[test]
8230 fn test_encode_f64_min_arm32() {
8231 let encoder = ArmEncoder::new_arm32();
8232 let op = ArmOp::F64Min {
8233 dd: VfpReg::D0,
8234 dn: VfpReg::D1,
8235 dm: VfpReg::D2,
8236 };
8237 let code = encoder.encode(&op).unwrap();
8238 assert_eq!(code.len(), 16);
8240 }
8241
8242 #[test]
8243 fn test_f64_cp11_encoding() {
8244 let encoder = ArmEncoder::new_arm32();
8246
8247 let code = encoder
8249 .encode(&ArmOp::F64Add {
8250 dd: VfpReg::D0,
8251 dn: VfpReg::D0,
8252 dm: VfpReg::D0,
8253 })
8254 .unwrap();
8255 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8256 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8257
8258 let code = encoder
8260 .encode(&ArmOp::F32Add {
8261 sd: VfpReg::S0,
8262 sn: VfpReg::S0,
8263 sm: VfpReg::S0,
8264 })
8265 .unwrap();
8266 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8267 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8268 }
8269
8270 #[test]
8271 fn test_dreg_encoding_higher_registers() {
8272 let encoder = ArmEncoder::new_arm32();
8273
8274 let op = ArmOp::F64Add {
8276 dd: VfpReg::D15,
8277 dn: VfpReg::D14,
8278 dm: VfpReg::D13,
8279 };
8280 let code = encoder.encode(&op).unwrap();
8281 assert_eq!(code.len(), 4);
8282
8283 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8285 assert_eq!((instr >> 8) & 0xF, 0xB); }
8287
8288 #[test]
8293 fn test_encode_label_emits_no_bytes() {
8294 let encoder = ArmEncoder::new_thumb2();
8295 let op = ArmOp::Label {
8296 name: ".Lblock_end_0".to_string(),
8297 };
8298 let code = encoder.encode(&op).unwrap();
8299 assert!(code.is_empty(), "Label should emit zero bytes");
8300
8301 let encoder32 = ArmEncoder::new_arm32();
8302 let code32 = encoder32.encode(&op).unwrap();
8303 assert!(
8304 code32.is_empty(),
8305 "Label should emit zero bytes in ARM32 too"
8306 );
8307 }
8308
8309 #[test]
8310 fn test_encode_bcc_eq_thumb2() {
8311 use synth_synthesis::Condition;
8312 let encoder = ArmEncoder::new_thumb2();
8313 let op = ArmOp::Bcc {
8314 cond: Condition::EQ,
8315 label: "target".to_string(),
8316 };
8317 let code = encoder.encode(&op).unwrap();
8318 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8322 }
8323
8324 #[test]
8325 fn test_encode_bcc_ne_thumb2() {
8326 use synth_synthesis::Condition;
8327 let encoder = ArmEncoder::new_thumb2();
8328 let op = ArmOp::Bcc {
8329 cond: Condition::NE,
8330 label: "target".to_string(),
8331 };
8332 let code = encoder.encode(&op).unwrap();
8333 assert_eq!(code.len(), 2);
8334
8335 assert_eq!(code, vec![0x00, 0xD1]);
8337 }
8338
8339 #[test]
8340 fn test_encode_bcc_arm32() {
8341 use synth_synthesis::Condition;
8342 let encoder = ArmEncoder::new_arm32();
8343 let op = ArmOp::Bcc {
8344 cond: Condition::EQ,
8345 label: "target".to_string(),
8346 };
8347 let code = encoder.encode(&op).unwrap();
8348 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8351 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8355
8356 #[test]
8357 fn test_encode_udf_thumb2() {
8358 let encoder = ArmEncoder::new_thumb2();
8359 let op = ArmOp::Udf { imm: 0 };
8360 let code = encoder.encode(&op).unwrap();
8361 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8365 }
8366
8367 #[test]
8368 fn test_encode_nop_thumb2() {
8369 let encoder = ArmEncoder::new_thumb2();
8370 let op = ArmOp::Nop;
8371 let code = encoder.encode(&op).unwrap();
8372 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8376 }
8377
8378 #[test]
8383 fn test_encode_i64_add_thumb2() {
8384 let encoder = ArmEncoder::new_thumb2();
8385 let op = ArmOp::I64Add {
8386 rdlo: Reg::R0,
8387 rdhi: Reg::R1,
8388 rnlo: Reg::R0,
8389 rnhi: Reg::R1,
8390 rmlo: Reg::R2,
8391 rmhi: Reg::R3,
8392 };
8393 let code = encoder.encode(&op).unwrap();
8394 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8396 }
8397
8398 #[test]
8399 fn test_encode_i64_sub_thumb2() {
8400 let encoder = ArmEncoder::new_thumb2();
8401 let op = ArmOp::I64Sub {
8402 rdlo: Reg::R0,
8403 rdhi: Reg::R1,
8404 rnlo: Reg::R0,
8405 rnhi: Reg::R1,
8406 rmlo: Reg::R2,
8407 rmhi: Reg::R3,
8408 };
8409 let code = encoder.encode(&op).unwrap();
8410 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8412 }
8413
8414 #[test]
8415 fn test_encode_i64_and_thumb2() {
8416 let encoder = ArmEncoder::new_thumb2();
8417 let op = ArmOp::I64And {
8418 rdlo: Reg::R0,
8419 rdhi: Reg::R1,
8420 rnlo: Reg::R0,
8421 rnhi: Reg::R1,
8422 rmlo: Reg::R2,
8423 rmhi: Reg::R3,
8424 };
8425 let code = encoder.encode(&op).unwrap();
8426 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8428 }
8429
8430 #[test]
8431 fn test_encode_i64_or_thumb2() {
8432 let encoder = ArmEncoder::new_thumb2();
8433 let op = ArmOp::I64Or {
8434 rdlo: Reg::R0,
8435 rdhi: Reg::R1,
8436 rnlo: Reg::R0,
8437 rnhi: Reg::R1,
8438 rmlo: Reg::R2,
8439 rmhi: Reg::R3,
8440 };
8441 let code = encoder.encode(&op).unwrap();
8442 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8443 }
8444
8445 #[test]
8446 fn test_encode_i64_xor_thumb2() {
8447 let encoder = ArmEncoder::new_thumb2();
8448 let op = ArmOp::I64Xor {
8449 rdlo: Reg::R0,
8450 rdhi: Reg::R1,
8451 rnlo: Reg::R0,
8452 rnhi: Reg::R1,
8453 rmlo: Reg::R2,
8454 rmhi: Reg::R3,
8455 };
8456 let code = encoder.encode(&op).unwrap();
8457 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8458 }
8459
8460 #[test]
8461 fn test_encode_i64_const_small_thumb2() {
8462 let encoder = ArmEncoder::new_thumb2();
8463 let op = ArmOp::I64Const {
8465 rdlo: Reg::R0,
8466 rdhi: Reg::R1,
8467 value: 42,
8468 };
8469 let code = encoder.encode(&op).unwrap();
8470 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8472 }
8473
8474 #[test]
8475 fn test_encode_i64_const_large_thumb2() {
8476 let encoder = ArmEncoder::new_thumb2();
8477 let op = ArmOp::I64Const {
8479 rdlo: Reg::R0,
8480 rdhi: Reg::R1,
8481 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8482 };
8483 let code = encoder.encode(&op).unwrap();
8484 assert_eq!(
8486 code.len(),
8487 16,
8488 "I64Const with large value should be 16 bytes"
8489 );
8490 }
8491
8492 #[test]
8493 fn test_encode_i64_extend_i32_s_thumb2() {
8494 let encoder = ArmEncoder::new_thumb2();
8495 let op = ArmOp::I64ExtendI32S {
8496 rdlo: Reg::R0,
8497 rdhi: Reg::R1,
8498 rn: Reg::R0,
8499 };
8500 let code = encoder.encode(&op).unwrap();
8501 assert_eq!(
8503 code.len(),
8504 4,
8505 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8506 );
8507 }
8508
8509 #[test]
8510 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8511 let encoder = ArmEncoder::new_thumb2();
8512 let op = ArmOp::I64ExtendI32S {
8513 rdlo: Reg::R0,
8514 rdhi: Reg::R1,
8515 rn: Reg::R2,
8516 };
8517 let code = encoder.encode(&op).unwrap();
8518 assert!(
8520 code.len() >= 6,
8521 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8522 );
8523 }
8524
8525 #[test]
8526 fn test_encode_i64_extend_i32_u_thumb2() {
8527 let encoder = ArmEncoder::new_thumb2();
8528 let op = ArmOp::I64ExtendI32U {
8529 rdlo: Reg::R0,
8530 rdhi: Reg::R1,
8531 rn: Reg::R0,
8532 };
8533 let code = encoder.encode(&op).unwrap();
8534 assert_eq!(
8536 code.len(),
8537 2,
8538 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8539 );
8540 }
8541
8542 #[test]
8543 fn test_encode_i32_wrap_i64_nop_thumb2() {
8544 let encoder = ArmEncoder::new_thumb2();
8545 let op = ArmOp::I32WrapI64 {
8547 rd: Reg::R0,
8548 rnlo: Reg::R0,
8549 };
8550 let code = encoder.encode(&op).unwrap();
8551 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8552 assert_eq!(code, vec![0x00, 0xBF]); }
8554
8555 #[test]
8556 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8557 let encoder = ArmEncoder::new_thumb2();
8558 let op = ArmOp::I32WrapI64 {
8559 rd: Reg::R2,
8560 rnlo: Reg::R0,
8561 };
8562 let code = encoder.encode(&op).unwrap();
8563 assert!(
8565 code.len() >= 2,
8566 "I32WrapI64 diff reg should emit at least 2 bytes"
8567 );
8568 }
8569
8570 #[test]
8571 fn test_encode_i64_eqz_thumb2() {
8572 let encoder = ArmEncoder::new_thumb2();
8573 let op = ArmOp::I64Eqz {
8574 rd: Reg::R0,
8575 rnlo: Reg::R0,
8576 rnhi: Reg::R1,
8577 };
8578 let code = encoder.encode(&op).unwrap();
8579 assert!(
8581 code.len() >= 6,
8582 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8583 );
8584 }
8585
8586 #[test]
8587 fn test_encode_i64_eq_thumb2() {
8588 let encoder = ArmEncoder::new_thumb2();
8589 let op = ArmOp::I64Eq {
8590 rd: Reg::R0,
8591 rnlo: Reg::R0,
8592 rnhi: Reg::R1,
8593 rmlo: Reg::R2,
8594 rmhi: Reg::R3,
8595 };
8596 let code = encoder.encode(&op).unwrap();
8597 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8599 }
8600
8601 #[test]
8602 fn test_encode_i64_ldr_thumb2() {
8603 let encoder = ArmEncoder::new_thumb2();
8604 let op = ArmOp::I64Ldr {
8605 rdlo: Reg::R0,
8606 rdhi: Reg::R1,
8607 addr: MemAddr::imm(Reg::SP, 0),
8608 };
8609 let code = encoder.encode(&op).unwrap();
8610 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8612 }
8613
8614 #[test]
8615 fn test_encode_i64_str_thumb2() {
8616 let encoder = ArmEncoder::new_thumb2();
8617 let op = ArmOp::I64Str {
8618 rdlo: Reg::R0,
8619 rdhi: Reg::R1,
8620 addr: MemAddr::imm(Reg::SP, 0),
8621 };
8622 let code = encoder.encode(&op).unwrap();
8623 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8625 }
8626
8627 #[test]
8628 fn test_encode_i64_all_comparisons_thumb2() {
8629 let encoder = ArmEncoder::new_thumb2();
8630
8631 let ops = vec![
8632 ArmOp::I64Ne {
8633 rd: Reg::R0,
8634 rnlo: Reg::R0,
8635 rnhi: Reg::R1,
8636 rmlo: Reg::R2,
8637 rmhi: Reg::R3,
8638 },
8639 ArmOp::I64LtS {
8640 rd: Reg::R0,
8641 rnlo: Reg::R0,
8642 rnhi: Reg::R1,
8643 rmlo: Reg::R2,
8644 rmhi: Reg::R3,
8645 },
8646 ArmOp::I64LtU {
8647 rd: Reg::R0,
8648 rnlo: Reg::R0,
8649 rnhi: Reg::R1,
8650 rmlo: Reg::R2,
8651 rmhi: Reg::R3,
8652 },
8653 ArmOp::I64LeS {
8654 rd: Reg::R0,
8655 rnlo: Reg::R0,
8656 rnhi: Reg::R1,
8657 rmlo: Reg::R2,
8658 rmhi: Reg::R3,
8659 },
8660 ArmOp::I64LeU {
8661 rd: Reg::R0,
8662 rnlo: Reg::R0,
8663 rnhi: Reg::R1,
8664 rmlo: Reg::R2,
8665 rmhi: Reg::R3,
8666 },
8667 ArmOp::I64GtS {
8668 rd: Reg::R0,
8669 rnlo: Reg::R0,
8670 rnhi: Reg::R1,
8671 rmlo: Reg::R2,
8672 rmhi: Reg::R3,
8673 },
8674 ArmOp::I64GtU {
8675 rd: Reg::R0,
8676 rnlo: Reg::R0,
8677 rnhi: Reg::R1,
8678 rmlo: Reg::R2,
8679 rmhi: Reg::R3,
8680 },
8681 ArmOp::I64GeS {
8682 rd: Reg::R0,
8683 rnlo: Reg::R0,
8684 rnhi: Reg::R1,
8685 rmlo: Reg::R2,
8686 rmhi: Reg::R3,
8687 },
8688 ArmOp::I64GeU {
8689 rd: Reg::R0,
8690 rnlo: Reg::R0,
8691 rnhi: Reg::R1,
8692 rmlo: Reg::R2,
8693 rmhi: Reg::R3,
8694 },
8695 ];
8696
8697 for op in &ops {
8698 let code = encoder.encode(op).unwrap();
8699 assert!(
8700 code.len() >= 8,
8701 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8702 op,
8703 code.len()
8704 );
8705 }
8706 }
8707
8708 #[test]
8709 fn test_encode_i64_const_zero_thumb2() {
8710 let encoder = ArmEncoder::new_thumb2();
8711 let op = ArmOp::I64Const {
8712 rdlo: Reg::R0,
8713 rdhi: Reg::R1,
8714 value: 0,
8715 };
8716 let code = encoder.encode(&op).unwrap();
8717 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8719 }
8720
8721 #[test]
8722 fn test_encode_i64_const_negative_one_thumb2() {
8723 let encoder = ArmEncoder::new_thumb2();
8724 let op = ArmOp::I64Const {
8725 rdlo: Reg::R0,
8726 rdhi: Reg::R1,
8727 value: -1, };
8729 let code = encoder.encode(&op).unwrap();
8730 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8732 }
8733
8734 #[test]
8739 fn test_encode_ldrb_arm32() {
8740 let encoder = ArmEncoder::new_arm32();
8741 let op = ArmOp::Ldrb {
8742 rd: Reg::R0,
8743 addr: MemAddr::imm(Reg::R1, 4),
8744 };
8745 let code = encoder.encode(&op).unwrap();
8746 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8747 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8749 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8750 }
8751
8752 #[test]
8753 fn test_encode_strb_arm32() {
8754 let encoder = ArmEncoder::new_arm32();
8755 let op = ArmOp::Strb {
8756 rd: Reg::R0,
8757 addr: MemAddr::imm(Reg::R1, 0),
8758 };
8759 let code = encoder.encode(&op).unwrap();
8760 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8761 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8763 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8764 }
8765
8766 #[test]
8767 fn test_encode_ldrh_arm32() {
8768 let encoder = ArmEncoder::new_arm32();
8769 let op = ArmOp::Ldrh {
8770 rd: Reg::R0,
8771 addr: MemAddr::imm(Reg::R1, 2),
8772 };
8773 let code = encoder.encode(&op).unwrap();
8774 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8775 }
8776
8777 #[test]
8778 fn test_encode_strh_arm32() {
8779 let encoder = ArmEncoder::new_arm32();
8780 let op = ArmOp::Strh {
8781 rd: Reg::R0,
8782 addr: MemAddr::imm(Reg::R1, 0),
8783 };
8784 let code = encoder.encode(&op).unwrap();
8785 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8786 }
8787
8788 #[test]
8789 fn test_encode_ldrsb_arm32() {
8790 let encoder = ArmEncoder::new_arm32();
8791 let op = ArmOp::Ldrsb {
8792 rd: Reg::R0,
8793 addr: MemAddr::imm(Reg::R1, 0),
8794 };
8795 let code = encoder.encode(&op).unwrap();
8796 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8797 }
8798
8799 #[test]
8800 fn test_encode_ldrsh_arm32() {
8801 let encoder = ArmEncoder::new_arm32();
8802 let op = ArmOp::Ldrsh {
8803 rd: Reg::R0,
8804 addr: MemAddr::imm(Reg::R1, 0),
8805 };
8806 let code = encoder.encode(&op).unwrap();
8807 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8808 }
8809
8810 #[test]
8811 fn test_encode_ldrb_thumb2_16bit() {
8812 let encoder = ArmEncoder::new_thumb2();
8813 let op = ArmOp::Ldrb {
8814 rd: Reg::R0,
8815 addr: MemAddr::imm(Reg::R1, 4),
8816 };
8817 let code = encoder.encode(&op).unwrap();
8818 assert_eq!(
8820 code.len(),
8821 2,
8822 "Thumb-2 LDRB with small offset should be 16-bit"
8823 );
8824 }
8825
8826 #[test]
8827 fn test_encode_ldrb_thumb2_32bit() {
8828 let encoder = ArmEncoder::new_thumb2();
8829 let op = ArmOp::Ldrb {
8830 rd: Reg::R0,
8831 addr: MemAddr::imm(Reg::R1, 100), };
8833 let code = encoder.encode(&op).unwrap();
8834 assert_eq!(
8835 code.len(),
8836 4,
8837 "Thumb-2 LDRB with large offset should be 32-bit"
8838 );
8839 }
8840
8841 #[test]
8842 fn test_encode_strb_thumb2_16bit() {
8843 let encoder = ArmEncoder::new_thumb2();
8844 let op = ArmOp::Strb {
8845 rd: Reg::R0,
8846 addr: MemAddr::imm(Reg::R1, 10),
8847 };
8848 let code = encoder.encode(&op).unwrap();
8849 assert_eq!(
8850 code.len(),
8851 2,
8852 "Thumb-2 STRB with small offset should be 16-bit"
8853 );
8854 }
8855
8856 #[test]
8857 fn test_encode_ldrh_thumb2_16bit() {
8858 let encoder = ArmEncoder::new_thumb2();
8859 let op = ArmOp::Ldrh {
8860 rd: Reg::R0,
8861 addr: MemAddr::imm(Reg::R1, 4), };
8863 let code = encoder.encode(&op).unwrap();
8864 assert_eq!(
8865 code.len(),
8866 2,
8867 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8868 );
8869 }
8870
8871 #[test]
8872 fn test_encode_strh_thumb2_16bit() {
8873 let encoder = ArmEncoder::new_thumb2();
8874 let op = ArmOp::Strh {
8875 rd: Reg::R0,
8876 addr: MemAddr::imm(Reg::R1, 4),
8877 };
8878 let code = encoder.encode(&op).unwrap();
8879 assert_eq!(
8880 code.len(),
8881 2,
8882 "Thumb-2 STRH with small aligned offset should be 16-bit"
8883 );
8884 }
8885
8886 #[test]
8887 fn test_encode_ldrsb_thumb2() {
8888 let encoder = ArmEncoder::new_thumb2();
8889 let op = ArmOp::Ldrsb {
8890 rd: Reg::R0,
8891 addr: MemAddr::imm(Reg::R1, 0),
8892 };
8893 let code = encoder.encode(&op).unwrap();
8894 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8896 }
8897
8898 #[test]
8899 fn test_encode_ldrsh_thumb2() {
8900 let encoder = ArmEncoder::new_thumb2();
8901 let op = ArmOp::Ldrsh {
8902 rd: Reg::R0,
8903 addr: MemAddr::imm(Reg::R1, 0),
8904 };
8905 let code = encoder.encode(&op).unwrap();
8906 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8907 }
8908
8909 #[test]
8910 fn test_encode_memory_size_thumb2() {
8911 let encoder = ArmEncoder::new_thumb2();
8912 let op = ArmOp::MemorySize { rd: Reg::R0 };
8913 let code = encoder.encode(&op).unwrap();
8914 assert!(!code.is_empty(), "MemorySize should produce code");
8916 }
8917
8918 #[test]
8919 fn test_encode_memory_grow_thumb2() {
8920 let encoder = ArmEncoder::new_thumb2();
8921 let op = ArmOp::MemoryGrow {
8922 rd: Reg::R0,
8923 rn: Reg::R0,
8924 };
8925 let code = encoder.encode(&op).unwrap();
8926 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8927 }
8928
8929 #[test]
8930 fn test_encode_subword_reg_offset_thumb2() {
8931 let encoder = ArmEncoder::new_thumb2();
8932
8933 let op = ArmOp::Ldrb {
8935 rd: Reg::R0,
8936 addr: MemAddr::reg(Reg::R1, Reg::R2),
8937 };
8938 let code = encoder.encode(&op).unwrap();
8939 assert_eq!(
8940 code.len(),
8941 4,
8942 "Thumb-2 LDRB with reg offset should be 32-bit"
8943 );
8944
8945 let op = ArmOp::Strb {
8947 rd: Reg::R0,
8948 addr: MemAddr::reg(Reg::R1, Reg::R2),
8949 };
8950 let code = encoder.encode(&op).unwrap();
8951 assert_eq!(
8952 code.len(),
8953 4,
8954 "Thumb-2 STRB with reg offset should be 32-bit"
8955 );
8956
8957 let op = ArmOp::Ldrh {
8959 rd: Reg::R0,
8960 addr: MemAddr::reg(Reg::R1, Reg::R2),
8961 };
8962 let code = encoder.encode(&op).unwrap();
8963 assert_eq!(
8964 code.len(),
8965 4,
8966 "Thumb-2 LDRH with reg offset should be 32-bit"
8967 );
8968
8969 let op = ArmOp::Strh {
8971 rd: Reg::R0,
8972 addr: MemAddr::reg(Reg::R1, Reg::R2),
8973 };
8974 let code = encoder.encode(&op).unwrap();
8975 assert_eq!(
8976 code.len(),
8977 4,
8978 "Thumb-2 STRH with reg offset should be 32-bit"
8979 );
8980 }
8981
8982 #[test]
8983 fn test_encode_subword_reg_imm_offset_thumb2() {
8984 let encoder = ArmEncoder::new_thumb2();
8985
8986 let op = ArmOp::Ldrb {
8988 rd: Reg::R0,
8989 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8990 };
8991 let code = encoder.encode(&op).unwrap();
8992 assert_eq!(
8994 code.len(),
8995 8,
8996 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8997 );
8998 }
8999
9000 #[test]
9005 fn test_encode_mve_addi32_thumb2() {
9006 let encoder = ArmEncoder::new_thumb2();
9007 let op = ArmOp::MveAddI {
9008 qd: QReg::Q0,
9009 qn: QReg::Q1,
9010 qm: QReg::Q2,
9011 size: MveSize::S32,
9012 };
9013 let code = encoder.encode(&op).unwrap();
9014 assert_eq!(
9015 code.len(),
9016 4,
9017 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
9018 );
9019 }
9020
9021 #[test]
9022 fn test_encode_mve_subi16_thumb2() {
9023 let encoder = ArmEncoder::new_thumb2();
9024 let op = ArmOp::MveSubI {
9025 qd: QReg::Q0,
9026 qn: QReg::Q1,
9027 qm: QReg::Q2,
9028 size: MveSize::S16,
9029 };
9030 let code = encoder.encode(&op).unwrap();
9031 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
9032 }
9033
9034 #[test]
9035 fn test_encode_mve_muli8_thumb2() {
9036 let encoder = ArmEncoder::new_thumb2();
9037 let op = ArmOp::MveMulI {
9038 qd: QReg::Q0,
9039 qn: QReg::Q1,
9040 qm: QReg::Q2,
9041 size: MveSize::S8,
9042 };
9043 let code = encoder.encode(&op).unwrap();
9044 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
9045 }
9046
9047 #[test]
9048 fn test_encode_mve_bitwise_thumb2() {
9049 let encoder = ArmEncoder::new_thumb2();
9050
9051 let ops = vec![
9052 ArmOp::MveAnd {
9053 qd: QReg::Q0,
9054 qn: QReg::Q1,
9055 qm: QReg::Q2,
9056 },
9057 ArmOp::MveOrr {
9058 qd: QReg::Q0,
9059 qn: QReg::Q1,
9060 qm: QReg::Q2,
9061 },
9062 ArmOp::MveEor {
9063 qd: QReg::Q0,
9064 qn: QReg::Q1,
9065 qm: QReg::Q2,
9066 },
9067 ArmOp::MveBic {
9068 qd: QReg::Q0,
9069 qn: QReg::Q1,
9070 qm: QReg::Q2,
9071 },
9072 ];
9073 for op in ops {
9074 let code = encoder.encode(&op).unwrap();
9075 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
9076 }
9077 }
9078
9079 #[test]
9080 fn test_encode_mve_mvn_thumb2() {
9081 let encoder = ArmEncoder::new_thumb2();
9082 let op = ArmOp::MveMvn {
9083 qd: QReg::Q0,
9084 qm: QReg::Q1,
9085 };
9086 let code = encoder.encode(&op).unwrap();
9087 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
9088 }
9089
9090 #[test]
9091 fn test_encode_mve_load_store_thumb2() {
9092 let encoder = ArmEncoder::new_thumb2();
9093
9094 let load = ArmOp::MveLoad {
9095 qd: QReg::Q0,
9096 addr: MemAddr::imm(Reg::R0, 16),
9097 };
9098 let code = encoder.encode(&load).unwrap();
9099 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
9100
9101 let store = ArmOp::MveStore {
9102 qd: QReg::Q1,
9103 addr: MemAddr::imm(Reg::R1, 0),
9104 };
9105 let code = encoder.encode(&store).unwrap();
9106 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
9107 }
9108
9109 #[test]
9110 fn test_encode_mve_const_thumb2() {
9111 let encoder = ArmEncoder::new_thumb2();
9112 let op = ArmOp::MveConst {
9113 qd: QReg::Q0,
9114 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
9115 };
9116 let code = encoder.encode(&op).unwrap();
9117 assert!(
9120 code.len() >= 24,
9121 "MVE const should produce multiple instructions"
9122 );
9123 }
9124
9125 #[test]
9126 fn test_encode_mve_dup_thumb2() {
9127 let encoder = ArmEncoder::new_thumb2();
9128 let op = ArmOp::MveDup {
9129 qd: QReg::Q0,
9130 rn: Reg::R0,
9131 size: MveSize::S32,
9132 };
9133 let code = encoder.encode(&op).unwrap();
9134 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
9135 }
9136
9137 #[test]
9138 fn test_encode_mve_extract_lane_thumb2() {
9139 let encoder = ArmEncoder::new_thumb2();
9140 let op = ArmOp::MveExtractLane {
9141 rd: Reg::R0,
9142 qn: QReg::Q1,
9143 lane: 2,
9144 size: MveSize::S32,
9145 };
9146 let code = encoder.encode(&op).unwrap();
9147 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
9148 }
9149
9150 #[test]
9151 fn test_encode_mve_insert_lane_thumb2() {
9152 let encoder = ArmEncoder::new_thumb2();
9153 let op = ArmOp::MveInsertLane {
9154 qd: QReg::Q0,
9155 rn: Reg::R1,
9156 lane: 3,
9157 size: MveSize::S32,
9158 };
9159 let code = encoder.encode(&op).unwrap();
9160 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9161 }
9162
9163 #[test]
9164 fn test_encode_mve_addf32_thumb2() {
9165 let encoder = ArmEncoder::new_thumb2();
9166 let op = ArmOp::MveAddF32 {
9167 qd: QReg::Q0,
9168 qn: QReg::Q1,
9169 qm: QReg::Q2,
9170 };
9171 let code = encoder.encode(&op).unwrap();
9172 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9173 }
9174
9175 #[test]
9176 fn test_encode_mve_divf32_thumb2() {
9177 let encoder = ArmEncoder::new_thumb2();
9178 let op = ArmOp::MveDivF32 {
9179 qd: QReg::Q0,
9180 qn: QReg::Q1,
9181 qm: QReg::Q2,
9182 };
9183 let code = encoder.encode(&op).unwrap();
9184 assert_eq!(
9186 code.len(),
9187 16,
9188 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9189 );
9190 }
9191
9192 #[test]
9193 fn test_encode_mve_sqrtf32_thumb2() {
9194 let encoder = ArmEncoder::new_thumb2();
9195 let op = ArmOp::MveSqrtF32 {
9196 qd: QReg::Q0,
9197 qm: QReg::Q1,
9198 };
9199 let code = encoder.encode(&op).unwrap();
9200 assert_eq!(
9202 code.len(),
9203 16,
9204 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9205 );
9206 }
9207
9208 #[test]
9209 fn test_encode_mve_negf32_thumb2() {
9210 let encoder = ArmEncoder::new_thumb2();
9211 let op = ArmOp::MveNegF32 {
9212 qd: QReg::Q0,
9213 qm: QReg::Q1,
9214 };
9215 let code = encoder.encode(&op).unwrap();
9216 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9217 }
9218
9219 #[test]
9220 fn test_encode_mve_absf32_thumb2() {
9221 let encoder = ArmEncoder::new_thumb2();
9222 let op = ArmOp::MveAbsF32 {
9223 qd: QReg::Q0,
9224 qm: QReg::Q1,
9225 };
9226 let code = encoder.encode(&op).unwrap();
9227 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9228 }
9229
9230 #[test]
9245 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9246 let encoder = ArmEncoder::new_thumb2();
9247 let op = ArmOp::And {
9248 rd: Reg::R2,
9249 rn: Reg::R0,
9250 op2: Operand2::Imm(0x7e),
9251 };
9252 let code = encoder.encode(&op).unwrap();
9253 assert_eq!(
9254 code,
9255 vec![0x00, 0xf0, 0x7e, 0x02],
9256 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9257 );
9258 }
9259
9260 #[test]
9267 fn try_thumb_expand_imm_encodes_modified_immediates() {
9268 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9270 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);
9278 assert_eq!(try_thumb_expand_imm(0x12345), None);
9279 }
9280
9281 #[test]
9286 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9287 let encoder = ArmEncoder::new_thumb2();
9288 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9290 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9291 assert!(
9293 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9294 "cmp #0x101 must error, not compare the wrong constant"
9295 );
9296 assert!(
9297 encoder
9298 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9299 .is_err()
9300 );
9301 assert!(
9302 encoder
9303 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9304 .is_err()
9305 );
9306 assert!(
9308 encoder
9309 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9310 .is_ok()
9311 );
9312 }
9313
9314 #[test]
9317 fn mla_thumb2_encodes_correctly() {
9318 let encoder = ArmEncoder::new_thumb2();
9319 let code = encoder
9320 .encode(&ArmOp::Mla {
9321 rd: Reg::R2,
9322 rn: Reg::R3,
9323 rm: Reg::R4,
9324 ra: Reg::R8,
9325 })
9326 .unwrap();
9327 assert_eq!(code, vec![0x03, 0xfb, 0x04, 0x82]);
9329 }
9330
9331 #[test]
9336 fn ldst_imm12_offset_errors_when_out_of_range() {
9337 let encoder = ArmEncoder::new_thumb2();
9338 assert!(
9340 encoder
9341 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0xFFF)
9342 .is_ok()
9343 );
9344 assert!(
9346 encoder
9347 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0x1000)
9348 .is_err(),
9349 "ldr offset 4096 must error, not wrap to 0"
9350 );
9351 assert!(
9352 encoder
9353 .encode_thumb32_str(&Reg::R0, &Reg::R1, 0x1000)
9354 .is_err()
9355 );
9356 assert!(
9357 encoder
9358 .encode_thumb32_ldrb_imm(&Reg::R0, &Reg::R1, 5000)
9359 .is_err()
9360 );
9361 assert!(
9362 encoder
9363 .encode_thumb32_strh_imm(&Reg::R0, &Reg::R1, 5000)
9364 .is_err()
9365 );
9366 }
9367
9368 #[test]
9375 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9376 let encoder = ArmEncoder::new_thumb2();
9377 assert_eq!(
9379 encoder
9380 .encode(&ArmOp::Add {
9381 rd: Reg::SP,
9382 rn: Reg::SP,
9383 op2: Operand2::Imm(256),
9384 })
9385 .unwrap(),
9386 vec![0x0d, 0xf2, 0x00, 0x1d],
9387 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9388 );
9389 assert_eq!(
9391 encoder
9392 .encode(&ArmOp::Sub {
9393 rd: Reg::SP,
9394 rn: Reg::SP,
9395 op2: Operand2::Imm(256),
9396 })
9397 .unwrap(),
9398 vec![0xad, 0xf2, 0x00, 0x1d],
9399 );
9400 assert!(
9402 encoder
9403 .encode(&ArmOp::Add {
9404 rd: Reg::SP,
9405 rn: Reg::SP,
9406 op2: Operand2::Imm(5000),
9407 })
9408 .is_err(),
9409 "add #5000 must error (no single ADDW), not mis-encode"
9410 );
9411 }
9412
9413 #[test]
9418 fn and_cmn_immediate_thumb_expand_else_error() {
9419 let encoder = ArmEncoder::new_thumb2();
9420 assert_eq!(
9422 encoder
9423 .encode(&ArmOp::And {
9424 rd: Reg::R2,
9425 rn: Reg::R0,
9426 op2: Operand2::Imm(0x7e),
9427 })
9428 .unwrap(),
9429 vec![0x00, 0xf0, 0x7e, 0x02],
9430 );
9431 assert!(
9433 encoder
9434 .encode(&ArmOp::And {
9435 rd: Reg::R2,
9436 rn: Reg::R0,
9437 op2: Operand2::Imm(0xff00ff00u32 as i32),
9438 })
9439 .is_ok()
9440 );
9441 assert!(
9443 encoder
9444 .encode(&ArmOp::And {
9445 rd: Reg::R2,
9446 rn: Reg::R0,
9447 op2: Operand2::Imm(0x101),
9448 })
9449 .is_err()
9450 );
9451 assert!(
9452 encoder
9453 .encode(&ArmOp::Cmn {
9454 rn: Reg::R0,
9455 op2: Operand2::Imm(0x101),
9456 })
9457 .is_err(),
9458 "CMN #0x101 must error, not emit a NOP"
9459 );
9460 }
9461
9462 #[test]
9466 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9467 let encoder = ArmEncoder::new_thumb2();
9468 assert_eq!(
9470 encoder
9471 .encode(&ArmOp::Orr {
9472 rd: Reg::R2,
9473 rn: Reg::R0,
9474 op2: Operand2::Imm(0x7e),
9475 })
9476 .unwrap(),
9477 vec![0x40, 0xf0, 0x7e, 0x02],
9478 );
9479 assert_eq!(
9481 encoder
9482 .encode(&ArmOp::Eor {
9483 rd: Reg::R2,
9484 rn: Reg::R0,
9485 op2: Operand2::Imm(0x7e),
9486 })
9487 .unwrap(),
9488 vec![0x80, 0xf0, 0x7e, 0x02],
9489 );
9490 assert!(
9492 encoder
9493 .encode(&ArmOp::Orr {
9494 rd: Reg::R2,
9495 rn: Reg::R0,
9496 op2: Operand2::Imm(0x140),
9497 })
9498 .is_err(),
9499 "ORR #0x140 must error, not emit a NOP"
9500 );
9501 }
9502
9503 #[test]
9504 fn test_encode_mve_different_qregs() {
9505 let encoder = ArmEncoder::new_thumb2();
9506
9507 let op1 = ArmOp::MveAddI {
9509 qd: QReg::Q0,
9510 qn: QReg::Q0,
9511 qm: QReg::Q0,
9512 size: MveSize::S32,
9513 };
9514 let op2 = ArmOp::MveAddI {
9515 qd: QReg::Q3,
9516 qn: QReg::Q5,
9517 qm: QReg::Q7,
9518 size: MveSize::S32,
9519 };
9520 let code1 = encoder.encode(&op1).unwrap();
9521 let code2 = encoder.encode(&op2).unwrap();
9522 assert_ne!(
9523 code1, code2,
9524 "Different Q-registers should produce different encodings"
9525 );
9526 }
9527
9528 #[test]
9529 fn test_encode_mve_arm32_nop() {
9530 let encoder = ArmEncoder::new_arm32();
9532 let op = ArmOp::MveAddI {
9533 qd: QReg::Q0,
9534 qn: QReg::Q1,
9535 qm: QReg::Q2,
9536 size: MveSize::S32,
9537 };
9538 let code = encoder.encode(&op).unwrap();
9539 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9540 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9542 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9543 }
9544}