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 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2917 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2918 b.extend_from_slice(&mov_one.to_le_bytes());
2919 b.extend_from_slice(&mov_zero.to_le_bytes());
2920 b
2921 };
2922
2923 match cond {
2924 Condition::EQ | Condition::NE => {
2925 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2927
2928 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2931
2932 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2934
2935 let cond_bits: u16 = match cond {
2937 Condition::EQ => 0x0,
2938 Condition::NE => 0x1,
2939 _ => unreachable!(),
2940 };
2941 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2942 }
2943
2944 Condition::LT => {
2945 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2947
2948 let rn_hi_bits = reg_to_bits(rn_hi);
2951 let rm_hi_bits = reg_to_bits(rm_hi);
2952 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2953 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2954 bytes.extend_from_slice(&hw1.to_le_bytes());
2955 bytes.extend_from_slice(&hw2.to_le_bytes());
2956
2957 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2960
2961 Condition::GT => {
2962 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2965
2966 let rm_hi_bits = reg_to_bits(rm_hi);
2968 let rn_hi_bits = reg_to_bits(rn_hi);
2969 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2970 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2971 bytes.extend_from_slice(&hw1.to_le_bytes());
2972 bytes.extend_from_slice(&hw2.to_le_bytes());
2973
2974 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2977
2978 Condition::LE => {
2979 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2983
2984 let rm_hi_bits = reg_to_bits(rm_hi);
2986 let rn_hi_bits = reg_to_bits(rn_hi);
2987 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2988 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2989 bytes.extend_from_slice(&hw1.to_le_bytes());
2990 bytes.extend_from_slice(&hw2.to_le_bytes());
2991
2992 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2995
2996 Condition::GE => {
2997 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3000
3001 let rn_hi_bits = reg_to_bits(rn_hi);
3003 let rm_hi_bits = reg_to_bits(rm_hi);
3004 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3005 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3006 bytes.extend_from_slice(&hw1.to_le_bytes());
3007 bytes.extend_from_slice(&hw2.to_le_bytes());
3008
3009 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
3012
3013 Condition::LO => {
3015 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3017 let rn_hi_bits = reg_to_bits(rn_hi);
3018 let rm_hi_bits = reg_to_bits(rm_hi);
3019 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3020 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3021 bytes.extend_from_slice(&hw1.to_le_bytes());
3022 bytes.extend_from_slice(&hw2.to_le_bytes());
3023 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3025
3026 Condition::HI => {
3027 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3029 let rm_hi_bits = reg_to_bits(rm_hi);
3030 let rn_hi_bits = reg_to_bits(rn_hi);
3031 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3032 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3033 bytes.extend_from_slice(&hw1.to_le_bytes());
3034 bytes.extend_from_slice(&hw2.to_le_bytes());
3035 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3037
3038 Condition::LS => {
3039 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3041 let rm_hi_bits = reg_to_bits(rm_hi);
3042 let rn_hi_bits = reg_to_bits(rn_hi);
3043 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3044 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3045 bytes.extend_from_slice(&hw1.to_le_bytes());
3046 bytes.extend_from_slice(&hw2.to_le_bytes());
3047 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3049
3050 Condition::HS => {
3051 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3053 let rn_hi_bits = reg_to_bits(rn_hi);
3054 let rm_hi_bits = reg_to_bits(rm_hi);
3055 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3056 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3057 bytes.extend_from_slice(&hw1.to_le_bytes());
3058 bytes.extend_from_slice(&hw2.to_le_bytes());
3059 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3061 }
3062
3063 Ok(bytes)
3064 }
3065
3066 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
3069 let rd_bits = reg_to_bits(rd);
3070 let rn_lo_bits = reg_to_bits(rn_lo);
3071 let rn_hi_bits = reg_to_bits(rn_hi);
3072 let mut bytes = Vec::new();
3073
3074 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3076 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3077 bytes.extend_from_slice(&hw1.to_le_bytes());
3078 bytes.extend_from_slice(&hw2.to_le_bytes());
3079
3080 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3082 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3083
3084 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3087 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3088 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3089 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3090 bytes.extend_from_slice(&mov_one.to_le_bytes());
3091 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3092
3093 Ok(bytes)
3094 }
3095
3096 ArmOp::I64Mul {
3100 rd_lo,
3101 rd_hi,
3102 rn_lo,
3103 rn_hi,
3104 rm_lo,
3105 rm_hi,
3106 } => {
3107 let rd_lo_bits = reg_to_bits(rd_lo);
3108 let rd_hi_bits = reg_to_bits(rd_hi);
3109 let rn_lo_bits = reg_to_bits(rn_lo);
3110 let rn_hi_bits = reg_to_bits(rn_hi);
3111 let rm_lo_bits = reg_to_bits(rm_lo);
3112 let rm_hi_bits = reg_to_bits(rm_hi);
3113 let r12: u32 = 12; let mut bytes = Vec::new();
3115
3116 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3119 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3120 bytes.extend_from_slice(&hw1.to_le_bytes());
3121 bytes.extend_from_slice(&hw2.to_le_bytes());
3122
3123 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3126 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3127 bytes.extend_from_slice(&hw1.to_le_bytes());
3128 bytes.extend_from_slice(&hw2.to_le_bytes());
3129
3130 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3133 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3134 bytes.extend_from_slice(&hw1.to_le_bytes());
3135 bytes.extend_from_slice(&hw2.to_le_bytes());
3136
3137 let d_bit = (rd_hi_bits >> 3) & 1;
3140 let add_instr: u16 =
3141 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3142 bytes.extend_from_slice(&add_instr.to_le_bytes());
3143
3144 Ok(bytes)
3145 }
3146
3147 ArmOp::I64Shl {
3150 rd_lo,
3151 rd_hi,
3152 rn_lo,
3153 rn_hi,
3154 rm_lo,
3155 rm_hi,
3156 } => {
3157 let rd_lo_bits = reg_to_bits(rd_lo);
3158 let rd_hi_bits = reg_to_bits(rd_hi);
3159 let rn_lo_bits = reg_to_bits(rn_lo);
3160 let rn_hi_bits = reg_to_bits(rn_hi);
3161 let rm_lo_bits = reg_to_bits(rm_lo);
3162 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3164
3165 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3167 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3168 bytes.extend_from_slice(&hw1.to_le_bytes());
3169 bytes.extend_from_slice(&hw2.to_le_bytes());
3170
3171 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3173 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3174 bytes.extend_from_slice(&hw1.to_le_bytes());
3175 bytes.extend_from_slice(&hw2.to_le_bytes());
3176
3177 let bpl: u16 = 0xD50A;
3179 bytes.extend_from_slice(&bpl.to_le_bytes());
3180
3181 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3184 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3185 bytes.extend_from_slice(&hw1.to_le_bytes());
3186 bytes.extend_from_slice(&hw2.to_le_bytes());
3187
3188 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3190 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3191 bytes.extend_from_slice(&hw1.to_le_bytes());
3192 bytes.extend_from_slice(&hw2.to_le_bytes());
3193
3194 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3196 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3197 bytes.extend_from_slice(&hw1.to_le_bytes());
3198 bytes.extend_from_slice(&hw2.to_le_bytes());
3199
3200 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3202 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3203 bytes.extend_from_slice(&hw1.to_le_bytes());
3204 bytes.extend_from_slice(&hw2.to_le_bytes());
3205
3206 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3208 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3209 bytes.extend_from_slice(&hw1.to_le_bytes());
3210 bytes.extend_from_slice(&hw2.to_le_bytes());
3211
3212 let b_done: u16 = 0xE002;
3214 bytes.extend_from_slice(&b_done.to_le_bytes());
3215
3216 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3219 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3220 bytes.extend_from_slice(&hw1.to_le_bytes());
3221 bytes.extend_from_slice(&hw2.to_le_bytes());
3222
3223 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3225 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3226
3227 Ok(bytes) }
3229
3230 ArmOp::I64ShrU {
3232 rd_lo,
3233 rd_hi,
3234 rn_lo,
3235 rn_hi,
3236 rm_lo,
3237 rm_hi,
3238 } => {
3239 let rd_lo_bits = reg_to_bits(rd_lo);
3240 let rd_hi_bits = reg_to_bits(rd_hi);
3241 let rn_lo_bits = reg_to_bits(rn_lo);
3242 let rn_hi_bits = reg_to_bits(rn_hi);
3243 let rm_lo_bits = reg_to_bits(rm_lo);
3244 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3246
3247 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3249 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3250 bytes.extend_from_slice(&hw1.to_le_bytes());
3251 bytes.extend_from_slice(&hw2.to_le_bytes());
3252
3253 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3255 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3256 bytes.extend_from_slice(&hw1.to_le_bytes());
3257 bytes.extend_from_slice(&hw2.to_le_bytes());
3258
3259 let bpl: u16 = 0xD50A;
3261 bytes.extend_from_slice(&bpl.to_le_bytes());
3262
3263 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3266 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3267 bytes.extend_from_slice(&hw1.to_le_bytes());
3268 bytes.extend_from_slice(&hw2.to_le_bytes());
3269
3270 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3272 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3273 bytes.extend_from_slice(&hw1.to_le_bytes());
3274 bytes.extend_from_slice(&hw2.to_le_bytes());
3275
3276 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3278 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3279 bytes.extend_from_slice(&hw1.to_le_bytes());
3280 bytes.extend_from_slice(&hw2.to_le_bytes());
3281
3282 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3284 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3285 bytes.extend_from_slice(&hw1.to_le_bytes());
3286 bytes.extend_from_slice(&hw2.to_le_bytes());
3287
3288 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3290 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3291 bytes.extend_from_slice(&hw1.to_le_bytes());
3292 bytes.extend_from_slice(&hw2.to_le_bytes());
3293
3294 let b_done: u16 = 0xE002;
3296 bytes.extend_from_slice(&b_done.to_le_bytes());
3297
3298 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3301 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3302 bytes.extend_from_slice(&hw1.to_le_bytes());
3303 bytes.extend_from_slice(&hw2.to_le_bytes());
3304
3305 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3307 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3308
3309 Ok(bytes) }
3311
3312 ArmOp::I64ShrS {
3314 rd_lo,
3315 rd_hi,
3316 rn_lo,
3317 rn_hi,
3318 rm_lo,
3319 rm_hi,
3320 } => {
3321 let rd_lo_bits = reg_to_bits(rd_lo);
3322 let rd_hi_bits = reg_to_bits(rd_hi);
3323 let rn_lo_bits = reg_to_bits(rn_lo);
3324 let rn_hi_bits = reg_to_bits(rn_hi);
3325 let rm_lo_bits = reg_to_bits(rm_lo);
3326 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3328
3329 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3331 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3332 bytes.extend_from_slice(&hw1.to_le_bytes());
3333 bytes.extend_from_slice(&hw2.to_le_bytes());
3334
3335 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3337 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3338 bytes.extend_from_slice(&hw1.to_le_bytes());
3339 bytes.extend_from_slice(&hw2.to_le_bytes());
3340
3341 let bpl: u16 = 0xD50A;
3343 bytes.extend_from_slice(&bpl.to_le_bytes());
3344
3345 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3348 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3349 bytes.extend_from_slice(&hw1.to_le_bytes());
3350 bytes.extend_from_slice(&hw2.to_le_bytes());
3351
3352 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3354 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3355 bytes.extend_from_slice(&hw1.to_le_bytes());
3356 bytes.extend_from_slice(&hw2.to_le_bytes());
3357
3358 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3360 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3361 bytes.extend_from_slice(&hw1.to_le_bytes());
3362 bytes.extend_from_slice(&hw2.to_le_bytes());
3363
3364 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3366 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3367 bytes.extend_from_slice(&hw1.to_le_bytes());
3368 bytes.extend_from_slice(&hw2.to_le_bytes());
3369
3370 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3372 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3373 bytes.extend_from_slice(&hw1.to_le_bytes());
3374 bytes.extend_from_slice(&hw2.to_le_bytes());
3375
3376 let b_done: u16 = 0xE003;
3378 bytes.extend_from_slice(&b_done.to_le_bytes());
3379
3380 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3383 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3384 bytes.extend_from_slice(&hw1.to_le_bytes());
3385 bytes.extend_from_slice(&hw2.to_le_bytes());
3386
3387 let hw1: u16 = 0xEA4F;
3391 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3392 bytes.extend_from_slice(&hw1.to_le_bytes());
3393 bytes.extend_from_slice(&hw2.to_le_bytes());
3394
3395 Ok(bytes) }
3397
3398 ArmOp::I64Rotl {
3403 rdlo,
3404 rdhi,
3405 rnlo,
3406 rnhi,
3407 shift,
3408 } => {
3409 let rd_lo_bits = reg_to_bits(rdlo);
3410 let rd_hi_bits = reg_to_bits(rdhi);
3411 let rn_lo_bits = reg_to_bits(rnlo);
3412 let rn_hi_bits = reg_to_bits(rnhi);
3413 let shift_bits = reg_to_bits(shift);
3414 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3418
3419 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3421
3422 let hw1: u16 = (0xF000 | shift_bits) as u16;
3424 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3425 bytes.extend_from_slice(&hw1.to_le_bytes());
3426 bytes.extend_from_slice(&hw2.to_le_bytes());
3427
3428 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3430 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3431 bytes.extend_from_slice(&hw1.to_le_bytes());
3432 bytes.extend_from_slice(&hw2.to_le_bytes());
3433
3434 let bpl: u16 = 0xD50E;
3436 bytes.extend_from_slice(&bpl.to_le_bytes());
3437
3438 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3441 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3442 bytes.extend_from_slice(&hw1.to_le_bytes());
3443 bytes.extend_from_slice(&hw2.to_le_bytes());
3444
3445 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3447 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3448 bytes.extend_from_slice(&hw1.to_le_bytes());
3449 bytes.extend_from_slice(&hw2.to_le_bytes());
3450
3451 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3453 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3454 bytes.extend_from_slice(&hw1.to_le_bytes());
3455 bytes.extend_from_slice(&hw2.to_le_bytes());
3456
3457 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3459 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3460 bytes.extend_from_slice(&hw1.to_le_bytes());
3461 bytes.extend_from_slice(&hw2.to_le_bytes());
3462
3463 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3465 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3466 bytes.extend_from_slice(&hw1.to_le_bytes());
3467 bytes.extend_from_slice(&hw2.to_le_bytes());
3468
3469 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3471 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3472 bytes.extend_from_slice(&hw1.to_le_bytes());
3473 bytes.extend_from_slice(&hw2.to_le_bytes());
3474
3475 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3477 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3478 bytes.extend_from_slice(&hw1.to_le_bytes());
3479 bytes.extend_from_slice(&hw2.to_le_bytes());
3480
3481 let b_done: u16 = 0xE00E;
3483 bytes.extend_from_slice(&b_done.to_le_bytes());
3484
3485 let hw1: u16 = (0xF1C0 | r3) as u16;
3489 let hw2: u16 = ((r4 << 8) | 0x20) 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 = (0xFA20 | rn_hi_bits) as u16;
3495 let hw2: u16 = (0xF000 | (r12 << 8) | r4) 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 = (0xFA20 | rn_lo_bits) as u16;
3501 let hw2: u16 = (0xF000 | (r4 << 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 | (shift_bits << 8) | r3) 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 | shift_bits) as u16;
3513 let hw2: u16 = ((shift_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 hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3519 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3520 bytes.extend_from_slice(&hw1.to_le_bytes());
3521 bytes.extend_from_slice(&hw2.to_le_bytes());
3522
3523 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3525 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3526 bytes.extend_from_slice(&hw1.to_le_bytes());
3527 bytes.extend_from_slice(&hw2.to_le_bytes());
3528
3529 let d_bit = (rd_hi_bits >> 3) & 1;
3531 let mov_instr: u16 =
3532 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3533 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3534
3535 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3537
3538 Ok(bytes) }
3540
3541 ArmOp::I64Rotr {
3546 rdlo,
3547 rdhi,
3548 rnlo,
3549 rnhi,
3550 shift,
3551 } => {
3552 let rd_lo_bits = reg_to_bits(rdlo);
3553 let rd_hi_bits = reg_to_bits(rdhi);
3554 let rn_lo_bits = reg_to_bits(rnlo);
3555 let rn_hi_bits = reg_to_bits(rnhi);
3556 let shift_bits = reg_to_bits(shift);
3557 let r12: u32 = 12;
3558 let r3: u32 = 3;
3559 let r4: u32 = 4;
3560 let mut bytes = Vec::new();
3561
3562 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3564
3565 let hw1: u16 = (0xF000 | shift_bits) as u16;
3567 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3568 bytes.extend_from_slice(&hw1.to_le_bytes());
3569 bytes.extend_from_slice(&hw2.to_le_bytes());
3570
3571 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3573 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3574 bytes.extend_from_slice(&hw1.to_le_bytes());
3575 bytes.extend_from_slice(&hw2.to_le_bytes());
3576
3577 let bpl: u16 = 0xD50E;
3579 bytes.extend_from_slice(&bpl.to_le_bytes());
3580
3581 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3584 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3585 bytes.extend_from_slice(&hw1.to_le_bytes());
3586 bytes.extend_from_slice(&hw2.to_le_bytes());
3587
3588 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3590 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3591 bytes.extend_from_slice(&hw1.to_le_bytes());
3592 bytes.extend_from_slice(&hw2.to_le_bytes());
3593
3594 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3596 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3597 bytes.extend_from_slice(&hw1.to_le_bytes());
3598 bytes.extend_from_slice(&hw2.to_le_bytes());
3599
3600 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3602 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3603 bytes.extend_from_slice(&hw1.to_le_bytes());
3604 bytes.extend_from_slice(&hw2.to_le_bytes());
3605
3606 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3608 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3609 bytes.extend_from_slice(&hw1.to_le_bytes());
3610 bytes.extend_from_slice(&hw2.to_le_bytes());
3611
3612 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3614 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3615 bytes.extend_from_slice(&hw1.to_le_bytes());
3616 bytes.extend_from_slice(&hw2.to_le_bytes());
3617
3618 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3620 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3621 bytes.extend_from_slice(&hw1.to_le_bytes());
3622 bytes.extend_from_slice(&hw2.to_le_bytes());
3623
3624 let b_done: u16 = 0xE00E;
3626 bytes.extend_from_slice(&b_done.to_le_bytes());
3627
3628 let hw1: u16 = (0xF1C0 | r3) as u16;
3631 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3632 bytes.extend_from_slice(&hw1.to_le_bytes());
3633 bytes.extend_from_slice(&hw2.to_le_bytes());
3634
3635 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3637 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3638 bytes.extend_from_slice(&hw1.to_le_bytes());
3639 bytes.extend_from_slice(&hw2.to_le_bytes());
3640
3641 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3643 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3644 bytes.extend_from_slice(&hw1.to_le_bytes());
3645 bytes.extend_from_slice(&hw2.to_le_bytes());
3646
3647 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3649 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3650 bytes.extend_from_slice(&hw1.to_le_bytes());
3651 bytes.extend_from_slice(&hw2.to_le_bytes());
3652
3653 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3655 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3656 bytes.extend_from_slice(&hw1.to_le_bytes());
3657 bytes.extend_from_slice(&hw2.to_le_bytes());
3658
3659 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3661 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3662 bytes.extend_from_slice(&hw1.to_le_bytes());
3663 bytes.extend_from_slice(&hw2.to_le_bytes());
3664
3665 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3667 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3668 bytes.extend_from_slice(&hw1.to_le_bytes());
3669 bytes.extend_from_slice(&hw2.to_le_bytes());
3670
3671 let d_bit = (rd_lo_bits >> 3) & 1;
3673 let mov_instr: u16 =
3674 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3675 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3676
3677 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3679
3680 Ok(bytes) }
3682
3683 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3697 let rd_bits = reg_to_bits(rd);
3698 let rn_lo_bits = reg_to_bits(rnlo);
3699 let rn_hi_bits = reg_to_bits(rnhi);
3700 let mut bytes = Vec::new();
3701
3702 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3704 let hw2: u16 = 0x0F00;
3705 bytes.extend_from_slice(&hw1.to_le_bytes());
3706 bytes.extend_from_slice(&hw2.to_le_bytes());
3707
3708 let beq: u16 = 0xD003;
3711 bytes.extend_from_slice(&beq.to_le_bytes());
3712
3713 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3716 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3717 bytes.extend_from_slice(&hw1.to_le_bytes());
3718 bytes.extend_from_slice(&hw2.to_le_bytes());
3719
3720 let b_done: u16 = 0xE004;
3723 bytes.extend_from_slice(&b_done.to_le_bytes());
3724
3725 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3727
3728 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3732 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3733 bytes.extend_from_slice(&hw1.to_le_bytes());
3734 bytes.extend_from_slice(&hw2.to_le_bytes());
3735
3736 let hw1: u16 = (0xF100 | rd_bits) as u16;
3738 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3739 bytes.extend_from_slice(&hw1.to_le_bytes());
3740 bytes.extend_from_slice(&hw2.to_le_bytes());
3741
3742 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3746 bytes.extend_from_slice(&mov0.to_le_bytes());
3747
3748 Ok(bytes)
3749 }
3750
3751 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3767 let rd_bits = reg_to_bits(rd);
3768 let rn_lo_bits = reg_to_bits(rnlo);
3769 let rn_hi_bits = reg_to_bits(rnhi);
3770 let mut bytes = Vec::new();
3771
3772 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3774 let hw2: u16 = 0x0F00;
3775 bytes.extend_from_slice(&hw1.to_le_bytes());
3776 bytes.extend_from_slice(&hw2.to_le_bytes());
3777
3778 let beq: u16 = 0xD005;
3781 bytes.extend_from_slice(&beq.to_le_bytes());
3782
3783 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3786 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3787 bytes.extend_from_slice(&hw1.to_le_bytes());
3788 bytes.extend_from_slice(&hw2.to_le_bytes());
3789
3790 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3793 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3794 bytes.extend_from_slice(&hw1.to_le_bytes());
3795 bytes.extend_from_slice(&hw2.to_le_bytes());
3796
3797 let b_done: u16 = 0xE006;
3800 bytes.extend_from_slice(&b_done.to_le_bytes());
3801
3802 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3804
3805 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3809 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3810 bytes.extend_from_slice(&hw1.to_le_bytes());
3811 bytes.extend_from_slice(&hw2.to_le_bytes());
3812
3813 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3816 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3817 bytes.extend_from_slice(&hw1.to_le_bytes());
3818 bytes.extend_from_slice(&hw2.to_le_bytes());
3819
3820 let hw1: u16 = (0xF100 | rd_bits) as u16;
3822 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3823 bytes.extend_from_slice(&hw1.to_le_bytes());
3824 bytes.extend_from_slice(&hw2.to_le_bytes());
3825
3826 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3829 bytes.extend_from_slice(&mov0.to_le_bytes());
3830
3831 Ok(bytes)
3832 }
3833
3834 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3838 let rd_bits = reg_to_bits(rd);
3839 let rn_lo_bits = reg_to_bits(rnlo);
3840 let rn_hi_bits = reg_to_bits(rnhi);
3841 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3844
3845 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3847
3848 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3858 bytes.extend_from_slice(&mov.to_le_bytes());
3859
3860 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3863 bytes.extend_from_slice(&mov.to_le_bytes());
3864
3865 let hw1: u16 = 0xEA4F;
3869 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3870 bytes.extend_from_slice(&hw1.to_le_bytes());
3871 bytes.extend_from_slice(&hw2.to_le_bytes());
3872
3873 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3876 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3877 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3879 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3880
3881 let hw1: u16 = (0xEA00 | r12) as u16;
3883 let hw2: u16 = ((r12 << 8) | r3) as u16;
3884 bytes.extend_from_slice(&hw1.to_le_bytes());
3885 bytes.extend_from_slice(&hw2.to_le_bytes());
3886
3887 let hw1: u16 = (0xEBA0 | 4) as u16;
3889 let hw2: u16 = ((4 << 8) | r12) as u16;
3890 bytes.extend_from_slice(&hw1.to_le_bytes());
3891 bytes.extend_from_slice(&hw2.to_le_bytes());
3892
3893 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3897 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3898 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3900 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3901
3902 let hw1: u16 = (0xEA00 | 4) as u16;
3904 let hw2: u16 = ((r12 << 8) | r3) as u16;
3905 bytes.extend_from_slice(&hw1.to_le_bytes());
3906 bytes.extend_from_slice(&hw2.to_le_bytes());
3907
3908 let hw1: u16 = 0xEA4F;
3910 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3911 bytes.extend_from_slice(&hw1.to_le_bytes());
3912 bytes.extend_from_slice(&hw2.to_le_bytes());
3913
3914 let hw1: u16 = (0xEA00 | 4) as u16;
3916 let hw2: u16 = ((4 << 8) | r3) as u16;
3917 bytes.extend_from_slice(&hw1.to_le_bytes());
3918 bytes.extend_from_slice(&hw2.to_le_bytes());
3919
3920 let hw1: u16 = (0xEB00 | 4) as u16;
3922 let hw2: u16 = ((4 << 8) | r12) as u16;
3923 bytes.extend_from_slice(&hw1.to_le_bytes());
3924 bytes.extend_from_slice(&hw2.to_le_bytes());
3925
3926 let hw1: u16 = 0xEA4F;
3931 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3932 bytes.extend_from_slice(&hw1.to_le_bytes());
3933 bytes.extend_from_slice(&hw2.to_le_bytes());
3934
3935 let hw1: u16 = (0xEB00 | 4) as u16;
3937 let hw2: u16 = ((4 << 8) | r12) as u16;
3938 bytes.extend_from_slice(&hw1.to_le_bytes());
3939 bytes.extend_from_slice(&hw2.to_le_bytes());
3940
3941 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3946 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3947 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3949 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3950
3951 let hw1: u16 = (0xEA00 | 4) as u16;
3953 let hw2: u16 = ((4 << 8) | r3) as u16;
3954 bytes.extend_from_slice(&hw1.to_le_bytes());
3955 bytes.extend_from_slice(&hw2.to_le_bytes());
3956
3957 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3961 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3962 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3964 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3965
3966 let hw1: u16 = (0xFB00 | 4) as u16;
3969 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3970 bytes.extend_from_slice(&hw1.to_le_bytes());
3971 bytes.extend_from_slice(&hw2.to_le_bytes());
3972
3973 let hw1: u16 = 0xEA4F;
3976 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3977 bytes.extend_from_slice(&hw1.to_le_bytes());
3978 bytes.extend_from_slice(&hw2.to_le_bytes());
3979
3980 let hw1: u16 = 0xEA4F;
3983 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3984 bytes.extend_from_slice(&hw1.to_le_bytes());
3985 bytes.extend_from_slice(&hw2.to_le_bytes());
3986
3987 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3989 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3990 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3991 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3992
3993 let hw1: u16 = (0xEA00 | r12) as u16;
3994 let hw2: u16 = ((r12 << 8) | r3) as u16;
3995 bytes.extend_from_slice(&hw1.to_le_bytes());
3996 bytes.extend_from_slice(&hw2.to_le_bytes());
3997
3998 let hw1: u16 = (0xEBA0 | 5) as u16;
3999 let hw2: u16 = ((5 << 8) | r12) as u16;
4000 bytes.extend_from_slice(&hw1.to_le_bytes());
4001 bytes.extend_from_slice(&hw2.to_le_bytes());
4002
4003 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
4005 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4006 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
4007 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
4008
4009 let hw1: u16 = (0xEA00 | 5) as u16;
4010 let hw2: u16 = ((r12 << 8) | r3) as u16;
4011 bytes.extend_from_slice(&hw1.to_le_bytes());
4012 bytes.extend_from_slice(&hw2.to_le_bytes());
4013
4014 let hw1: u16 = 0xEA4F;
4015 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
4016 bytes.extend_from_slice(&hw1.to_le_bytes());
4017 bytes.extend_from_slice(&hw2.to_le_bytes());
4018
4019 let hw1: u16 = (0xEA00 | 5) as u16;
4020 let hw2: u16 = ((5 << 8) | r3) as u16;
4021 bytes.extend_from_slice(&hw1.to_le_bytes());
4022 bytes.extend_from_slice(&hw2.to_le_bytes());
4023
4024 let hw1: u16 = (0xEB00 | 5) as u16;
4025 let hw2: u16 = ((5 << 8) | r12) as u16;
4026 bytes.extend_from_slice(&hw1.to_le_bytes());
4027 bytes.extend_from_slice(&hw2.to_le_bytes());
4028
4029 let hw1: u16 = 0xEA4F;
4032 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
4033 bytes.extend_from_slice(&hw1.to_le_bytes());
4034 bytes.extend_from_slice(&hw2.to_le_bytes());
4035
4036 let hw1: u16 = (0xEB00 | 5) as u16;
4037 let hw2: u16 = ((5 << 8) | r12) as u16;
4038 bytes.extend_from_slice(&hw1.to_le_bytes());
4039 bytes.extend_from_slice(&hw2.to_le_bytes());
4040
4041 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4043 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4044 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4045 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4046
4047 let hw1: u16 = (0xEA00 | 5) as u16;
4048 let hw2: u16 = ((5 << 8) | r3) as u16;
4049 bytes.extend_from_slice(&hw1.to_le_bytes());
4050 bytes.extend_from_slice(&hw2.to_le_bytes());
4051
4052 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4054 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4055 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4056 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4057
4058 let hw1: u16 = (0xFB00 | 5) as u16;
4061 let hw2: u16 = (0xF000 | (5 << 8) | r3) 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 = (0x6000 | (5 << 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 rd_bits_u16 = rd_bits as u16;
4075 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4076 bytes.extend_from_slice(&instr.to_le_bytes());
4077
4078 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4080
4081 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4083 bytes.extend_from_slice(&mov0.to_le_bytes());
4084
4085 Ok(bytes)
4086 }
4087
4088 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4091 let rdlo_bits = reg_to_bits(rdlo);
4092 let rdhi_bits = reg_to_bits(rdhi);
4093 let rnlo_bits = reg_to_bits(rnlo);
4094 let mut bytes = Vec::new();
4095
4096 let hw1: u16 = 0xFA4F_u16;
4099 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4100 bytes.extend_from_slice(&hw1.to_le_bytes());
4101 bytes.extend_from_slice(&hw2.to_le_bytes());
4102
4103 let hw1: u16 = 0xEA4F;
4108 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4109 bytes.extend_from_slice(&hw1.to_le_bytes());
4110 bytes.extend_from_slice(&hw2.to_le_bytes());
4111
4112 Ok(bytes)
4113 }
4114
4115 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4118 let rdlo_bits = reg_to_bits(rdlo);
4119 let rdhi_bits = reg_to_bits(rdhi);
4120 let rnlo_bits = reg_to_bits(rnlo);
4121 let mut bytes = Vec::new();
4122
4123 let hw1: u16 = 0xFA0F_u16;
4126 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4127 bytes.extend_from_slice(&hw1.to_le_bytes());
4128 bytes.extend_from_slice(&hw2.to_le_bytes());
4129
4130 let hw1: u16 = 0xEA4F;
4132 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4133 bytes.extend_from_slice(&hw1.to_le_bytes());
4134 bytes.extend_from_slice(&hw2.to_le_bytes());
4135
4136 Ok(bytes)
4137 }
4138
4139 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4142 let rdlo_bits = reg_to_bits(rdlo);
4143 let rdhi_bits = reg_to_bits(rdhi);
4144 let rnlo_bits = reg_to_bits(rnlo);
4145 let mut bytes = Vec::new();
4146
4147 if rdlo_bits != rnlo_bits {
4149 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4151 let mov: u16 = 0x4600
4152 | (d_bit << 7)
4153 | ((rnlo_bits as u16) << 3)
4154 | ((rdlo_bits & 0x7) as u16);
4155 bytes.extend_from_slice(&mov.to_le_bytes());
4156 }
4157
4158 let hw1: u16 = 0xEA4F;
4160 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4161 bytes.extend_from_slice(&hw1.to_le_bytes());
4162 bytes.extend_from_slice(&hw2.to_le_bytes());
4163
4164 Ok(bytes)
4165 }
4166
4167 ArmOp::SelectMove { rd, rm, cond } => {
4170 let rd_bits = reg_to_bits(rd) as u16;
4171 let rm_bits = reg_to_bits(rm) as u16;
4172
4173 use synth_synthesis::Condition;
4175 let cond_bits: u16 = match cond {
4176 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, };
4187
4188 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4191
4192 let d_bit = (rd_bits >> 3) & 1;
4195 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4196
4197 let mut bytes = it_instr.to_le_bytes().to_vec();
4199 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4200 Ok(bytes)
4201 }
4202
4203 ArmOp::Popcnt { rd, rm } => {
4214 let mut bytes = Vec::new();
4215
4216 if rd != rm {
4218 let rd_bits = reg_to_bits(rd) as u16;
4219 let rm_bits = reg_to_bits(rm) as u16;
4220 let d_bit = (rd_bits >> 3) & 1;
4222 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4223 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4224 }
4225
4226 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4229 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4230
4231 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4234
4235 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4237
4238 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4240 reg_to_bits(rd),
4241 reg_to_bits(rd),
4242 11,
4243 )?);
4244
4245 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4248 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4249
4250 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4252 11,
4253 reg_to_bits(rd),
4254 12,
4255 )?);
4256
4257 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4259 reg_to_bits(rd),
4260 reg_to_bits(rd),
4261 2,
4262 )?);
4263
4264 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4266 reg_to_bits(rd),
4267 reg_to_bits(rd),
4268 12,
4269 )?);
4270
4271 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4273 reg_to_bits(rd),
4274 reg_to_bits(rd),
4275 11,
4276 )?);
4277
4278 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4281
4282 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4284 reg_to_bits(rd),
4285 reg_to_bits(rd),
4286 11,
4287 )?);
4288
4289 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4291 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4292
4293 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4295 reg_to_bits(rd),
4296 reg_to_bits(rd),
4297 12,
4298 )?);
4299
4300 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4303
4304 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4306 reg_to_bits(rd),
4307 reg_to_bits(rd),
4308 11,
4309 )?);
4310
4311 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4314
4315 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4317 reg_to_bits(rd),
4318 reg_to_bits(rd),
4319 11,
4320 )?);
4321
4322 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4325 reg_to_bits(rd),
4326 reg_to_bits(rd),
4327 0x3F,
4328 )?);
4329
4330 Ok(bytes)
4331 }
4332
4333 ArmOp::I64DivU {
4338 rdlo: _,
4339 rdhi: _,
4340 rnlo: _,
4341 rnhi: _,
4342 rmlo: _,
4343 rmhi: _,
4344 } => {
4345 let mut bytes = Vec::new();
4346
4347 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4351
4352 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());
4363 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4364
4365 let loop_start = bytes.len();
4367
4368 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4379 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());
4388 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4389 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4393 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4394
4395 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4400 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4401 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());
4432 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4433 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4436
4437 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4441 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4442
4443 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4446 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4447 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4448
4449 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4457
4458 Ok(bytes)
4459 }
4460
4461 ArmOp::I64DivS {
4466 rdlo: _,
4467 rdhi: _,
4468 rnlo: _,
4469 rnhi: _,
4470 rmlo: _,
4471 rmhi: _,
4472 } => {
4473 let mut bytes = Vec::new();
4474
4475 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4477 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4478
4479 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4482 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4483
4484 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());
4497
4498 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());
4508
4509 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4512 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4513 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4515 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4516 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4518 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4519
4520 let loop_start = bytes.len();
4521
4522 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4526 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());
4532 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4535
4536 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4540 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());
4553 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4555
4556 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4559
4560 let branch_offset_bytes = bytes.len() - loop_start + 4;
4561 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4562 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4563 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4564
4565 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());
4572 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());
4580
4581 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4583 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4584
4585 Ok(bytes)
4586 }
4587
4588 ArmOp::I64RemU {
4593 rdlo: _,
4594 rdhi: _,
4595 rnlo: _,
4596 rnhi: _,
4597 rmlo: _,
4598 rmhi: _,
4599 } => {
4600 let mut bytes = Vec::new();
4601
4602 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4604 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4605
4606 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4608 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4609 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4611 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4612 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4614 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4615
4616 let loop_start = bytes.len();
4617
4618 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4622 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());
4628 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4631
4632 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4636 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());
4649 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4651
4652 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4655
4656 let branch_offset_bytes = bytes.len() - loop_start + 4;
4657 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4658 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4659 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4660
4661 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4667 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4668
4669 Ok(bytes)
4670 }
4671
4672 ArmOp::I64RemS {
4677 rdlo: _,
4678 rdhi: _,
4679 rnlo: _,
4680 rnhi: _,
4681 rmlo: _,
4682 rmhi: _,
4683 } => {
4684 let mut bytes = Vec::new();
4685
4686 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4688 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4689
4690 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());
4704
4705 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());
4715
4716 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4719 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4720 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4722 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4723 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4725 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4726
4727 let loop_start = bytes.len();
4728
4729 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4733 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());
4739 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4742
4743 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4747 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());
4760 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4762
4763 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4766
4767 let branch_offset_bytes = bytes.len() - loop_start + 4;
4768 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4769 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4770 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4771
4772 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());
4779 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());
4787
4788 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4790 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4791
4792 Ok(bytes)
4793 }
4794
4795 ArmOp::F32Add { sd, sn, sm } => {
4798 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4799 }
4800 ArmOp::F32Sub { sd, sn, sm } => {
4801 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4802 }
4803 ArmOp::F32Mul { sd, sn, sm } => {
4804 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4805 }
4806 ArmOp::F32Div { sd, sn, sm } => {
4807 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4808 }
4809 ArmOp::F32Abs { sd, sm } => {
4810 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4811 }
4812 ArmOp::F32Neg { sd, sm } => {
4813 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4814 }
4815 ArmOp::F32Sqrt { sd, sm } => {
4816 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4817 }
4818
4819 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4822 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4823 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4824 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4825 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4826 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4827 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4828
4829 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4831 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4832 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4833 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4834 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4835 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4836
4837 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4838
4839 ArmOp::F32Load { sd, addr } => {
4840 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4841 }
4842 ArmOp::F32Store { sd, addr } => {
4843 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4844 }
4845
4846 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4847 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4848 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4849 Err(synth_core::Error::synthesis(
4850 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4851 ))
4852 }
4853 ArmOp::F32ReinterpretI32 { sd, rm } => {
4854 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4855 }
4856 ArmOp::I32ReinterpretF32 { rd, sm } => {
4857 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4858 }
4859 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4860 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4861
4862 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4865 0xEE300B00, dd, dn, dm,
4866 )?)),
4867 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4868 0xEE300B40, dd, dn, dm,
4869 )?)),
4870 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4871 0xEE200B00, dd, dn, dm,
4872 )?)),
4873 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4874 0xEE800B00, dd, dn, dm,
4875 )?)),
4876 ArmOp::F64Abs { dd, dm } => {
4877 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4878 }
4879 ArmOp::F64Neg { dd, dm } => {
4880 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4881 }
4882 ArmOp::F64Sqrt { dd, dm } => {
4883 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4884 }
4885
4886 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4889 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4890 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4891 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4892 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4893 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4894 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4895
4896 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4898 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4899 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4900 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4901 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4902 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4903
4904 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4905
4906 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4907 0xED900B00, dd, addr,
4908 )?)),
4909 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4910 0xED800B00, dd, addr,
4911 )?)),
4912
4913 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4914 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4915 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4916 Err(synth_core::Error::synthesis(
4917 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4918 ))
4919 }
4920 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4921 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4922 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4923 )),
4924 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4925 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4926 )),
4927 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4928 Err(synth_core::Error::synthesis(
4929 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4930 ))
4931 }
4932 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4933 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4934
4935 ArmOp::I64Add {
4939 rdlo,
4940 rdhi,
4941 rnlo,
4942 rnhi,
4943 rmlo,
4944 rmhi,
4945 } => {
4946 let mut bytes = Vec::new();
4947 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4949 rd: *rdlo,
4950 rn: *rnlo,
4951 op2: Operand2::Reg(*rmlo),
4952 })?);
4953 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4955 rd: *rdhi,
4956 rn: *rnhi,
4957 op2: Operand2::Reg(*rmhi),
4958 })?);
4959 Ok(bytes)
4960 }
4961
4962 ArmOp::I64Sub {
4964 rdlo,
4965 rdhi,
4966 rnlo,
4967 rnhi,
4968 rmlo,
4969 rmhi,
4970 } => {
4971 let mut bytes = Vec::new();
4972 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4974 rd: *rdlo,
4975 rn: *rnlo,
4976 op2: Operand2::Reg(*rmlo),
4977 })?);
4978 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4980 rd: *rdhi,
4981 rn: *rnhi,
4982 op2: Operand2::Reg(*rmhi),
4983 })?);
4984 Ok(bytes)
4985 }
4986
4987 ArmOp::I64And {
4989 rdlo,
4990 rdhi,
4991 rnlo,
4992 rnhi,
4993 rmlo,
4994 rmhi,
4995 } => {
4996 let mut bytes = Vec::new();
4997 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4998 rd: *rdlo,
4999 rn: *rnlo,
5000 op2: Operand2::Reg(*rmlo),
5001 })?);
5002 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
5003 rd: *rdhi,
5004 rn: *rnhi,
5005 op2: Operand2::Reg(*rmhi),
5006 })?);
5007 Ok(bytes)
5008 }
5009
5010 ArmOp::I64Or {
5012 rdlo,
5013 rdhi,
5014 rnlo,
5015 rnhi,
5016 rmlo,
5017 rmhi,
5018 } => {
5019 let mut bytes = Vec::new();
5020 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5021 rd: *rdlo,
5022 rn: *rnlo,
5023 op2: Operand2::Reg(*rmlo),
5024 })?);
5025 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5026 rd: *rdhi,
5027 rn: *rnhi,
5028 op2: Operand2::Reg(*rmhi),
5029 })?);
5030 Ok(bytes)
5031 }
5032
5033 ArmOp::I64Xor {
5035 rdlo,
5036 rdhi,
5037 rnlo,
5038 rnhi,
5039 rmlo,
5040 rmhi,
5041 } => {
5042 let mut bytes = Vec::new();
5043 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5044 rd: *rdlo,
5045 rn: *rnlo,
5046 op2: Operand2::Reg(*rmlo),
5047 })?);
5048 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5049 rd: *rdhi,
5050 rn: *rnhi,
5051 op2: Operand2::Reg(*rmhi),
5052 })?);
5053 Ok(bytes)
5054 }
5055
5056 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
5058 rd: *rd,
5059 rn_lo: *rnlo,
5060 rn_hi: *rnhi,
5061 }),
5062
5063 ArmOp::I64Eq {
5065 rd,
5066 rnlo,
5067 rnhi,
5068 rmlo,
5069 rmhi,
5070 } => self.encode_thumb(&ArmOp::I64SetCond {
5071 rd: *rd,
5072 rn_lo: *rnlo,
5073 rn_hi: *rnhi,
5074 rm_lo: *rmlo,
5075 rm_hi: *rmhi,
5076 cond: synth_synthesis::Condition::EQ,
5077 }),
5078
5079 ArmOp::I64Ne {
5080 rd,
5081 rnlo,
5082 rnhi,
5083 rmlo,
5084 rmhi,
5085 } => self.encode_thumb(&ArmOp::I64SetCond {
5086 rd: *rd,
5087 rn_lo: *rnlo,
5088 rn_hi: *rnhi,
5089 rm_lo: *rmlo,
5090 rm_hi: *rmhi,
5091 cond: synth_synthesis::Condition::NE,
5092 }),
5093
5094 ArmOp::I64LtS {
5095 rd,
5096 rnlo,
5097 rnhi,
5098 rmlo,
5099 rmhi,
5100 } => self.encode_thumb(&ArmOp::I64SetCond {
5101 rd: *rd,
5102 rn_lo: *rnlo,
5103 rn_hi: *rnhi,
5104 rm_lo: *rmlo,
5105 rm_hi: *rmhi,
5106 cond: synth_synthesis::Condition::LT,
5107 }),
5108
5109 ArmOp::I64LtU {
5110 rd,
5111 rnlo,
5112 rnhi,
5113 rmlo,
5114 rmhi,
5115 } => self.encode_thumb(&ArmOp::I64SetCond {
5116 rd: *rd,
5117 rn_lo: *rnlo,
5118 rn_hi: *rnhi,
5119 rm_lo: *rmlo,
5120 rm_hi: *rmhi,
5121 cond: synth_synthesis::Condition::LO,
5122 }),
5123
5124 ArmOp::I64LeS {
5125 rd,
5126 rnlo,
5127 rnhi,
5128 rmlo,
5129 rmhi,
5130 } => self.encode_thumb(&ArmOp::I64SetCond {
5131 rd: *rd,
5132 rn_lo: *rnlo,
5133 rn_hi: *rnhi,
5134 rm_lo: *rmlo,
5135 rm_hi: *rmhi,
5136 cond: synth_synthesis::Condition::LE,
5137 }),
5138
5139 ArmOp::I64LeU {
5140 rd,
5141 rnlo,
5142 rnhi,
5143 rmlo,
5144 rmhi,
5145 } => self.encode_thumb(&ArmOp::I64SetCond {
5146 rd: *rd,
5147 rn_lo: *rnlo,
5148 rn_hi: *rnhi,
5149 rm_lo: *rmlo,
5150 rm_hi: *rmhi,
5151 cond: synth_synthesis::Condition::LS,
5152 }),
5153
5154 ArmOp::I64GtS {
5155 rd,
5156 rnlo,
5157 rnhi,
5158 rmlo,
5159 rmhi,
5160 } => self.encode_thumb(&ArmOp::I64SetCond {
5161 rd: *rd,
5162 rn_lo: *rnlo,
5163 rn_hi: *rnhi,
5164 rm_lo: *rmlo,
5165 rm_hi: *rmhi,
5166 cond: synth_synthesis::Condition::GT,
5167 }),
5168
5169 ArmOp::I64GtU {
5170 rd,
5171 rnlo,
5172 rnhi,
5173 rmlo,
5174 rmhi,
5175 } => self.encode_thumb(&ArmOp::I64SetCond {
5176 rd: *rd,
5177 rn_lo: *rnlo,
5178 rn_hi: *rnhi,
5179 rm_lo: *rmlo,
5180 rm_hi: *rmhi,
5181 cond: synth_synthesis::Condition::HI,
5182 }),
5183
5184 ArmOp::I64GeS {
5185 rd,
5186 rnlo,
5187 rnhi,
5188 rmlo,
5189 rmhi,
5190 } => self.encode_thumb(&ArmOp::I64SetCond {
5191 rd: *rd,
5192 rn_lo: *rnlo,
5193 rn_hi: *rnhi,
5194 rm_lo: *rmlo,
5195 rm_hi: *rmhi,
5196 cond: synth_synthesis::Condition::GE,
5197 }),
5198
5199 ArmOp::I64GeU {
5200 rd,
5201 rnlo,
5202 rnhi,
5203 rmlo,
5204 rmhi,
5205 } => self.encode_thumb(&ArmOp::I64SetCond {
5206 rd: *rd,
5207 rn_lo: *rnlo,
5208 rn_hi: *rnhi,
5209 rm_lo: *rmlo,
5210 rm_hi: *rmhi,
5211 cond: synth_synthesis::Condition::HS,
5212 }),
5213
5214 ArmOp::I64Const { rdlo, rdhi, value } => {
5216 let lo32 = *value as u32;
5217 let hi32 = (*value >> 32) as u32;
5218 let mut bytes = Vec::new();
5219 bytes.extend_from_slice(
5221 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5222 );
5223 if lo32 > 0xFFFF {
5224 bytes.extend_from_slice(
5225 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5226 );
5227 }
5228 bytes.extend_from_slice(
5230 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5231 );
5232 if hi32 > 0xFFFF {
5233 bytes.extend_from_slice(
5234 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5235 );
5236 }
5237 Ok(bytes)
5238 }
5239
5240 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5242 let mut bytes = Vec::new();
5243 let offset = if addr.offset < 0 {
5244 0u32
5245 } else {
5246 addr.offset as u32
5247 };
5248 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5249 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5250 rdhi,
5251 &addr.base,
5252 offset.wrapping_add(4),
5253 )?);
5254 Ok(bytes)
5255 }
5256
5257 ArmOp::I64Str { rdlo, rdhi, addr } => {
5259 let mut bytes = Vec::new();
5260 let offset = if addr.offset < 0 {
5261 0u32
5262 } else {
5263 addr.offset as u32
5264 };
5265 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5266 bytes.extend_from_slice(&self.encode_thumb32_str(
5267 rdhi,
5268 &addr.base,
5269 offset.wrapping_add(4),
5270 )?);
5271 Ok(bytes)
5272 }
5273
5274 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5276 let mut bytes = Vec::new();
5277 if rdlo != rn {
5278 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5280 rd: *rdlo,
5281 op2: Operand2::Reg(*rn),
5282 })?);
5283 }
5284 bytes.extend_from_slice(
5286 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5288 Ok(bytes)
5289 }
5290
5291 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5293 let mut bytes = Vec::new();
5294 if rdlo != rn {
5295 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5297 rd: *rdlo,
5298 op2: Operand2::Reg(*rn),
5299 })?);
5300 }
5301 let rdhi_bits = reg_to_bits(rdhi) as u16;
5303 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5304 bytes.extend_from_slice(&instr.to_le_bytes());
5305 Ok(bytes)
5306 }
5307
5308 ArmOp::I32WrapI64 { rd, rnlo } => {
5310 if rd == rnlo {
5311 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5314 } else {
5315 self.encode_thumb(&ArmOp::Mov {
5317 rd: *rd,
5318 op2: Operand2::Reg(*rnlo),
5319 })
5320 }
5321 }
5322
5323 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5325 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5326 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5327 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5328 0xEF000150, qd, qn, qm,
5329 ))),
5330 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5331 0xEF200150, qd, qn, qm,
5332 ))),
5333 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5334 0xFF000150, qd, qn, qm,
5335 ))),
5336 ArmOp::MveMvn { qd, qm } => {
5337 let qd_enc = qreg_to_num(qd);
5339 let qm_enc = qreg_to_num(qm);
5340 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5341 Ok(vfp_to_thumb_bytes(instr))
5342 }
5343 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5344 0xEF100150, qd, qn, qm,
5345 ))),
5346 ArmOp::MveAddI { qd, qn, qm, size } => {
5347 let sz = mve_size_bits(size);
5348 let base: u32 = 0xEF000840 | (sz << 20);
5349 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5350 }
5351 ArmOp::MveSubI { qd, qn, qm, size } => {
5352 let sz = mve_size_bits(size);
5353 let base: u32 = 0xFF000840 | (sz << 20);
5354 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5355 }
5356 ArmOp::MveMulI { qd, qn, qm, size } => {
5357 let sz = mve_size_bits(size);
5358 let base: u32 = 0xEF000950 | (sz << 20);
5359 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5360 }
5361 ArmOp::MveNegI { qd, qm, size } => {
5362 let sz = mve_size_bits(size);
5363 let qd_enc = qreg_to_num(qd);
5365 let qm_enc = qreg_to_num(qm);
5366 let base: u32 = 0xFFB103C0 | (sz << 18);
5367 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5368 Ok(vfp_to_thumb_bytes(instr))
5369 }
5370 ArmOp::MveDup { qd, rn, size } => {
5371 let sz = mve_size_bits(size);
5372 let qd_enc = qreg_to_num(qd);
5373 let rn_bits = reg_to_bits(rn);
5374 let be = match sz {
5377 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5381 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5382 Ok(vfp_to_thumb_bytes(instr))
5383 }
5384 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5385 let qn_enc = qreg_to_num(qn);
5386 let rd_bits = reg_to_bits(rd);
5387 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5390 let lane_in_d = (*lane as u32) & 1;
5391 let _sz = mve_size_bits(size);
5392 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5394 Ok(vfp_to_thumb_bytes(instr))
5395 }
5396 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5397 let qd_enc = qreg_to_num(qd);
5398 let rn_bits = reg_to_bits(rn);
5399 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5400 let lane_in_d = (*lane as u32) & 1;
5401 let _sz = mve_size_bits(size);
5402 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5404 Ok(vfp_to_thumb_bytes(instr))
5405 }
5406
5407 ArmOp::MveCmpEqI { qd, qn, qm, size }
5409 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5410 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5411 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5412 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5413 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5414 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5415 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5416 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5417 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5418 let sz = mve_size_bits(size);
5421 let base: u32 = 0xEF000840 | (sz << 20);
5422 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5423 }
5424
5425 ArmOp::MveAddF32 { qd, qn, qm } => {
5427 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5429 }
5430 ArmOp::MveSubF32 { qd, qn, qm } => {
5431 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5433 }
5434 ArmOp::MveMulF32 { qd, qn, qm } => {
5435 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5437 }
5438 ArmOp::MveNegF32 { qd, qm } => {
5439 let qd_enc = qreg_to_num(qd);
5440 let qm_enc = qreg_to_num(qm);
5441 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5443 Ok(vfp_to_thumb_bytes(instr))
5444 }
5445 ArmOp::MveAbsF32 { qd, qm } => {
5446 let qd_enc = qreg_to_num(qd);
5447 let qm_enc = qreg_to_num(qm);
5448 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5450 Ok(vfp_to_thumb_bytes(instr))
5451 }
5452 ArmOp::MveCmpEqF32 { qd, qn, qm }
5453 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5454 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5455 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5456 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5457 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5458 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5460 }
5461 ArmOp::MveDupF32 { qd, rn } => {
5462 let qd_enc = qreg_to_num(qd);
5463 let rn_bits = reg_to_bits(rn);
5464 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5466 Ok(vfp_to_thumb_bytes(instr))
5467 }
5468 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5469 let qn_enc = qreg_to_num(qn);
5470 let rd_bits = reg_to_bits(rd);
5471 let s_num = qn_enc * 4 + (*lane as u32);
5473 let (vn, n) = encode_sreg(s_num);
5474 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5475 Ok(vfp_to_thumb_bytes(instr))
5476 }
5477 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5478 let qd_enc = qreg_to_num(qd);
5479 let rn_bits = reg_to_bits(rn);
5480 let s_num = qd_enc * 4 + (*lane as u32);
5482 let (vn, n) = encode_sreg(s_num);
5483 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5484 Ok(vfp_to_thumb_bytes(instr))
5485 }
5486 ArmOp::MveDivF32 { qd, qn, qm } => {
5487 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5489 }
5490 ArmOp::MveSqrtF32 { qd, qm } => {
5491 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5493 }
5494
5495 _ => {
5497 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5499 }
5500 }
5501 }
5502
5503 fn encode_thumb_f32_compare(
5507 &self,
5508 rd: &Reg,
5509 sn: &VfpReg,
5510 sm: &VfpReg,
5511 cond_code: u32,
5512 ) -> Result<Vec<u8>> {
5513 let mut bytes = Vec::new();
5514 let rd_bits = reg_to_bits(rd);
5515
5516 let sn_num = vfp_sreg_to_num(sn)?;
5518 let sm_num = vfp_sreg_to_num(sm)?;
5519 let (vd, d) = encode_sreg(sn_num);
5520 let (vm, m) = encode_sreg(sm_num);
5521 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5522 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5523
5524 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5526
5527 if rd_bits < 8 {
5529 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5530 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5531 } else {
5532 let hw1: u16 = 0xF04F;
5534 let hw2: u16 = (rd_bits as u16) << 8;
5535 bytes.extend_from_slice(&hw1.to_le_bytes());
5536 bytes.extend_from_slice(&hw2.to_le_bytes());
5537 }
5538
5539 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5543 bytes.extend_from_slice(&it.to_le_bytes());
5544
5545 if rd_bits < 8 {
5547 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5548 bytes.extend_from_slice(&mov_one.to_le_bytes());
5549 } else {
5550 let hw1: u16 = 0xF04F;
5552 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5553 bytes.extend_from_slice(&hw1.to_le_bytes());
5554 bytes.extend_from_slice(&hw2.to_le_bytes());
5555 }
5556
5557 Ok(bytes)
5558 }
5559
5560 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5562 let mut bytes = Vec::new();
5563 let bits = value.to_bits();
5564 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5569 let imm4 = (lo16 >> 12) & 0xF;
5570 let i_bit = (lo16 >> 11) & 1;
5571 let imm3 = (lo16 >> 8) & 0x7;
5572 let imm8 = lo16 & 0xFF;
5573 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5574 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5575 bytes.extend_from_slice(&hw1.to_le_bytes());
5576 bytes.extend_from_slice(&hw2.to_le_bytes());
5577
5578 let hi16 = (bits >> 16) & 0xFFFF;
5580 let imm4 = (hi16 >> 12) & 0xF;
5581 let i_bit = (hi16 >> 11) & 1;
5582 let imm3 = (hi16 >> 8) & 0x7;
5583 let imm8 = hi16 & 0xFF;
5584 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5585 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5586 bytes.extend_from_slice(&hw1.to_le_bytes());
5587 bytes.extend_from_slice(&hw2.to_le_bytes());
5588
5589 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5591 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5592
5593 Ok(bytes)
5594 }
5595
5596 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5598 let mut bytes = Vec::new();
5599
5600 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5602 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5603
5604 let sd_num = vfp_sreg_to_num(sd)?;
5606 let (vd, d) = encode_sreg(sd_num);
5607 let (vm, m) = encode_sreg(sd_num);
5608 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5609 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5610 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5611
5612 Ok(bytes)
5613 }
5614
5615 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5623 let mut bytes = Vec::new();
5624 let sm_num = vfp_sreg_to_num(sm)?;
5625 let sd_num = vfp_sreg_to_num(sd)?;
5626 let (vd_s, d_s) = encode_sreg(sd_num);
5627 let (vm_s, m_s) = encode_sreg(sm_num);
5628
5629 if mode == 0b11 {
5630 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5632 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5633 } else {
5634 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5639 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5640
5641 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5647 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5648 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5649
5650 if mode != 0 {
5652 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5654 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5655 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5656 }
5657
5658 let vmsr = 0xEEE10A10 | (rt << 12);
5660 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5661
5662 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5664 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5665
5666 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5668 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5669 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5670 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5671 }
5672
5673 let (vd2, d2) = encode_sreg(sd_num);
5675 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5676 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5677
5678 Ok(bytes)
5679 }
5680
5681 fn encode_thumb_f32_minmax(
5683 &self,
5684 sd: &VfpReg,
5685 sn: &VfpReg,
5686 sm: &VfpReg,
5687 is_min: bool,
5688 ) -> Result<Vec<u8>> {
5689 let mut bytes = Vec::new();
5690 let sn_num = vfp_sreg_to_num(sn)?;
5691 let sm_num = vfp_sreg_to_num(sm)?;
5692 let sd_num = vfp_sreg_to_num(sd)?;
5693
5694 let (vd, d) = encode_sreg(sd_num);
5696 let (vn, n) = encode_sreg(sn_num);
5697 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5698 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5699
5700 let (vm, m) = encode_sreg(sm_num);
5702 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5703 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5704
5705 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5707
5708 let cond: u16 = if is_min { 0xC } else { 0x4 };
5710 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5711 bytes.extend_from_slice(&it.to_le_bytes());
5712
5713 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5715 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5716
5717 Ok(bytes)
5718 }
5719
5720 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5722 let mut bytes = Vec::new();
5723
5724 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5726 false,
5727 sm,
5728 &Reg::R12,
5729 )?));
5730
5731 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5733 false,
5734 sn,
5735 &Reg::R0,
5736 )?));
5737
5738 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5750 bytes.extend_from_slice(&hw2.to_le_bytes());
5751
5752 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5756 bytes.extend_from_slice(&hw2.to_le_bytes());
5757
5758 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5762 bytes.extend_from_slice(&hw2.to_le_bytes());
5763
5764 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5766 true,
5767 sd,
5768 &Reg::R0,
5769 )?));
5770
5771 Ok(bytes)
5772 }
5773
5774 fn encode_thumb_f64_compare(
5776 &self,
5777 rd: &Reg,
5778 dn: &VfpReg,
5779 dm: &VfpReg,
5780 cond_code: u32,
5781 ) -> Result<Vec<u8>> {
5782 let mut bytes = Vec::new();
5783 let rd_bits = reg_to_bits(rd);
5784
5785 let dn_num = vfp_dreg_to_num(dn)?;
5787 let dm_num = vfp_dreg_to_num(dm)?;
5788 let (vd, d) = encode_dreg(dn_num);
5789 let (vm, m) = encode_dreg(dm_num);
5790 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5791 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5792
5793 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5795
5796 if rd_bits < 8 {
5798 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5799 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5800 } else {
5801 let hw1: u16 = 0xF04F;
5802 let hw2: u16 = (rd_bits as u16) << 8;
5803 bytes.extend_from_slice(&hw1.to_le_bytes());
5804 bytes.extend_from_slice(&hw2.to_le_bytes());
5805 }
5806
5807 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5809 bytes.extend_from_slice(&it.to_le_bytes());
5810
5811 if rd_bits < 8 {
5813 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5814 bytes.extend_from_slice(&mov_one.to_le_bytes());
5815 } else {
5816 let hw1: u16 = 0xF04F;
5817 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5818 bytes.extend_from_slice(&hw1.to_le_bytes());
5819 bytes.extend_from_slice(&hw2.to_le_bytes());
5820 }
5821
5822 Ok(bytes)
5823 }
5824
5825 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5827 let mut bytes = Vec::new();
5828 let bits = value.to_bits();
5829 let lo32 = bits as u32;
5830 let hi32 = (bits >> 32) as u32;
5831
5832 let lo16 = lo32 & 0xFFFF;
5834 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5835
5836 let hi16 = (lo32 >> 16) & 0xFFFF;
5838 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5839
5840 let lo16 = hi32 & 0xFFFF;
5842 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5843
5844 let hi16 = (hi32 >> 16) & 0xFFFF;
5846 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5847
5848 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5850 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5851
5852 Ok(bytes)
5853 }
5854
5855 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5857 let mut bytes = Vec::new();
5858
5859 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5861 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5862
5863 let dd_num = vfp_dreg_to_num(dd)?;
5865 let (vd, d) = encode_dreg(dd_num);
5866 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5867 let vcvt = base | (d << 22) | (vd << 12);
5868 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5869
5870 Ok(bytes)
5871 }
5872
5873 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5875 let dd_num = vfp_dreg_to_num(dd)?;
5876 let sm_num = vfp_sreg_to_num(sm)?;
5877 let (vd, d) = encode_dreg(dd_num);
5878 let (vm, m) = encode_sreg(sm_num);
5879
5880 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5881 Ok(vfp_to_thumb_bytes(vcvt))
5882 }
5883
5884 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5886 let mut bytes = Vec::new();
5887 let dm_num = vfp_dreg_to_num(dm)?;
5888 let (vm, m) = encode_dreg(dm_num);
5889
5890 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5892 let vcvt = base | (m << 5) | vm;
5893 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5894
5895 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5897 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5898
5899 Ok(bytes)
5900 }
5901
5902 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5906 let mut bytes = Vec::new();
5907 let dm_num = vfp_dreg_to_num(dm)?;
5908 let dd_num = vfp_dreg_to_num(dd)?;
5909 let (vm, m) = encode_dreg(dm_num);
5910 let (vd, d) = encode_dreg(dd_num);
5911
5912 if mode == 0b11 {
5913 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5915 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5916 } else {
5917 let rt: u32 = 12;
5918
5919 let vmrs = 0xEEF10A10 | (rt << 12);
5921 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5922
5923 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5925 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5926 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5927 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5928
5929 if mode != 0 {
5931 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5932 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5933 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5934 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5935 }
5936
5937 let vmsr = 0xEEE10A10 | (rt << 12);
5939 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5940
5941 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5943 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5944
5945 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5947 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5948 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5949 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5950 }
5951
5952 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5954 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5955
5956 Ok(bytes)
5957 }
5958
5959 fn encode_thumb_f64_minmax(
5961 &self,
5962 dd: &VfpReg,
5963 dn: &VfpReg,
5964 dm: &VfpReg,
5965 is_min: bool,
5966 ) -> Result<Vec<u8>> {
5967 let mut bytes = Vec::new();
5968 let dn_num = vfp_dreg_to_num(dn)?;
5969 let dm_num = vfp_dreg_to_num(dm)?;
5970 let dd_num = vfp_dreg_to_num(dd)?;
5971
5972 let (vd, d) = encode_dreg(dd_num);
5974 let (vn, n) = encode_dreg(dn_num);
5975 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5976 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5977
5978 let (vm, m) = encode_dreg(dm_num);
5980 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5981 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5982
5983 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5985
5986 let cond: u16 = if is_min { 0xC } else { 0x4 };
5988 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5989 bytes.extend_from_slice(&it.to_le_bytes());
5990
5991 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5993 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5994
5995 Ok(bytes)
5996 }
5997
5998 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
6000 let mut bytes = Vec::new();
6001
6002 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6004 false,
6005 dm,
6006 &Reg::R0,
6007 &Reg::R12,
6008 )?));
6009
6010 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6012 false,
6013 dn,
6014 &Reg::R1,
6015 &Reg::R2,
6016 )?));
6017
6018 let hw1: u16 = 0xF000 | 12;
6020 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
6021 bytes.extend_from_slice(&hw1.to_le_bytes());
6022 bytes.extend_from_slice(&hw2.to_le_bytes());
6023
6024 let hw1: u16 = 0xF020 | 2;
6026 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
6027 bytes.extend_from_slice(&hw1.to_le_bytes());
6028 bytes.extend_from_slice(&hw2.to_le_bytes());
6029
6030 let hw1: u16 = 0xEA40 | 2;
6032 let hw2: u16 = (2 << 8) | 12;
6033 bytes.extend_from_slice(&hw1.to_le_bytes());
6034 bytes.extend_from_slice(&hw2.to_le_bytes());
6035
6036 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6038 true,
6039 dd,
6040 &Reg::R1,
6041 &Reg::R2,
6042 )?));
6043
6044 Ok(bytes)
6045 }
6046
6047 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6049 let mut bytes = Vec::new();
6050
6051 let sm_num = vfp_sreg_to_num(sm)?;
6052 let (vd, d) = encode_sreg(sm_num);
6053 let (vm, m) = encode_sreg(sm_num);
6054 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6055 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6056 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6057
6058 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6060 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6061
6062 Ok(bytes)
6063 }
6064
6065 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6069 let rd_bits = reg_to_bits(rd);
6070 let rn_bits = reg_to_bits(rn);
6071
6072 let i_bit = (imm >> 11) & 1;
6074 let imm3 = (imm >> 8) & 0x7;
6075 let imm8 = imm & 0xFF;
6076
6077 let hw1_base = if imm <= 0xFF {
6078 0xF100
6082 } else if imm <= 0xFFF {
6083 0xF200
6087 } else {
6088 return Err(synth_core::Error::synthesis(
6089 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6090 ));
6091 };
6092
6093 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6094 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6095
6096 let mut bytes = hw1.to_le_bytes().to_vec();
6097 bytes.extend_from_slice(&hw2.to_le_bytes());
6098 Ok(bytes)
6099 }
6100
6101 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6103 let rd_bits = reg_to_bits(rd);
6104 let rn_bits = reg_to_bits(rn);
6105
6106 let i_bit = (imm >> 11) & 1;
6107 let imm3 = (imm >> 8) & 0x7;
6108 let imm8 = imm & 0xFF;
6109
6110 let hw1_base = if imm <= 0xFF {
6111 0xF1A0
6114 } else if imm <= 0xFFF {
6115 0xF2A0
6118 } else {
6119 return Err(synth_core::Error::synthesis(
6120 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6121 ));
6122 };
6123
6124 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6125 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6126
6127 let mut bytes = hw1.to_le_bytes().to_vec();
6128 bytes.extend_from_slice(&hw2.to_le_bytes());
6129 Ok(bytes)
6130 }
6131
6132 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6134 let rd_bits = reg_to_bits(rd);
6135 let rn_bits = reg_to_bits(rn);
6136
6137 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6140 synth_core::Error::synthesis(
6141 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6142 )
6143 })?;
6144 let i_bit = (field >> 11) & 1;
6145 let imm3 = (field >> 8) & 0x7;
6146 let imm8 = field & 0xFF;
6147
6148 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6151 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6152
6153 let mut bytes = hw1.to_le_bytes().to_vec();
6154 bytes.extend_from_slice(&hw2.to_le_bytes());
6155 Ok(bytes)
6156 }
6157
6158 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6160 let rd_bits = reg_to_bits(rd);
6161 let rn_bits = reg_to_bits(rn);
6162
6163 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6166 synth_core::Error::synthesis(
6167 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6168 )
6169 })?;
6170 let i_bit = (field >> 11) & 1;
6171 let imm3 = (field >> 8) & 0x7;
6172 let imm8 = field & 0xFF;
6173
6174 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6177 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6178
6179 let mut bytes = hw1.to_le_bytes().to_vec();
6180 bytes.extend_from_slice(&hw2.to_le_bytes());
6181 Ok(bytes)
6182 }
6183
6184 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6193 let rd_bits = reg_to_bits(rd);
6194 reg_bits_checked(rd_bits)?;
6195 let imm16 = imm & 0xFFFF;
6196
6197 let imm4 = (imm16 >> 12) & 0xF;
6200 let i_bit = (imm16 >> 11) & 1;
6201 let imm3 = (imm16 >> 8) & 0x7;
6202 let imm8 = imm16 & 0xFF;
6203
6204 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6205 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6206
6207 let mut bytes = hw1.to_le_bytes().to_vec();
6208 bytes.extend_from_slice(&hw2.to_le_bytes());
6209 encoding_contracts::verify_thumb32(&bytes);
6210 Ok(bytes)
6211 }
6212
6213 fn encode_thumb32_shift(
6221 &self,
6222 rd: &Reg,
6223 rm: &Reg,
6224 shift: u32,
6225 shift_type: u8,
6226 ) -> Result<Vec<u8>> {
6227 let rd_bits = reg_to_bits(rd);
6228 let rm_bits = reg_to_bits(rm);
6229 reg_bits_checked(rd_bits)?;
6230 reg_bits_checked(rm_bits)?;
6231 let imm5 = shift & 0x1F;
6232 let imm2 = imm5 & 0x3;
6233 let imm3 = (imm5 >> 2) & 0x7;
6234
6235 let hw1: u16 = 0xEA4F;
6238 let hw2: u16 =
6239 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6240 as u16;
6241
6242 let mut bytes = hw1.to_le_bytes().to_vec();
6243 bytes.extend_from_slice(&hw2.to_le_bytes());
6244 Ok(bytes)
6245 }
6246
6247 fn encode_thumb32_shift_reg(
6251 &self,
6252 rd: &Reg,
6253 rn: &Reg,
6254 rm: &Reg,
6255 shift_type: u8,
6256 ) -> Result<Vec<u8>> {
6257 let rd_bits = reg_to_bits(rd);
6258 let rn_bits = reg_to_bits(rn);
6259 let rm_bits = reg_to_bits(rm);
6260
6261 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6263 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6265
6266 let mut bytes = hw1.to_le_bytes().to_vec();
6267 bytes.extend_from_slice(&hw2.to_le_bytes());
6268 Ok(bytes)
6269 }
6270
6271 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6273 let rn_bits = reg_to_bits(rn);
6274
6275 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6279 synth_core::Error::synthesis(
6280 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6281 )
6282 })?;
6283 let i_bit = (field >> 11) & 1;
6284 let imm3 = (field >> 8) & 0x7;
6285 let imm8 = field & 0xFF;
6286
6287 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6289 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6290
6291 let mut bytes = hw1.to_le_bytes().to_vec();
6292 bytes.extend_from_slice(&hw2.to_le_bytes());
6293 Ok(bytes)
6294 }
6295
6296 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6298 let rd_bits = reg_to_bits(rd);
6299 let base_bits = reg_to_bits(base);
6300
6301 check_ldst_imm12(offset)?;
6303 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6304 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6305
6306 let mut bytes = hw1.to_le_bytes().to_vec();
6307 bytes.extend_from_slice(&hw2.to_le_bytes());
6308 Ok(bytes)
6309 }
6310
6311 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6313 let rd_bits = reg_to_bits(rd);
6314 let base_bits = reg_to_bits(base);
6315
6316 check_ldst_imm12(offset)?;
6318 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6319 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6320
6321 let mut bytes = hw1.to_le_bytes().to_vec();
6322 bytes.extend_from_slice(&hw2.to_le_bytes());
6323 Ok(bytes)
6324 }
6325
6326 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6328 let rd_bits = reg_to_bits(rd);
6329 let base_bits = reg_to_bits(base);
6330 let rm_bits = reg_to_bits(offset_reg);
6331
6332 let hw1: u16 = (0xF850 | base_bits) as u16;
6336 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6337
6338 let mut bytes = hw1.to_le_bytes().to_vec();
6339 bytes.extend_from_slice(&hw2.to_le_bytes());
6340 Ok(bytes)
6341 }
6342
6343 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6345 let rd_bits = reg_to_bits(rd);
6346 let base_bits = reg_to_bits(base);
6347 let rm_bits = reg_to_bits(offset_reg);
6348
6349 let hw1: u16 = (0xF840 | base_bits) as u16;
6353 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6354
6355 let mut bytes = hw1.to_le_bytes().to_vec();
6356 bytes.extend_from_slice(&hw2.to_le_bytes());
6357 Ok(bytes)
6358 }
6359
6360 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6364 let rd_bits = reg_to_bits(rd);
6365 let base_bits = reg_to_bits(base);
6366 check_ldst_imm12(offset)?;
6368 let hw1: u16 = (0xF890 | base_bits) as u16;
6369 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6370 let mut bytes = hw1.to_le_bytes().to_vec();
6371 bytes.extend_from_slice(&hw2.to_le_bytes());
6372 Ok(bytes)
6373 }
6374
6375 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6377 let rd_bits = reg_to_bits(rd);
6378 let base_bits = reg_to_bits(base);
6379 let rm_bits = reg_to_bits(offset_reg);
6380 let hw1: u16 = (0xF810 | base_bits) as u16;
6382 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6383 let mut bytes = hw1.to_le_bytes().to_vec();
6384 bytes.extend_from_slice(&hw2.to_le_bytes());
6385 Ok(bytes)
6386 }
6387
6388 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6390 let rd_bits = reg_to_bits(rd);
6391 let base_bits = reg_to_bits(base);
6392 check_ldst_imm12(offset)?;
6394 let hw1: u16 = (0xF990 | base_bits) as u16;
6395 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6396 let mut bytes = hw1.to_le_bytes().to_vec();
6397 bytes.extend_from_slice(&hw2.to_le_bytes());
6398 Ok(bytes)
6399 }
6400
6401 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6403 let rd_bits = reg_to_bits(rd);
6404 let base_bits = reg_to_bits(base);
6405 let rm_bits = reg_to_bits(offset_reg);
6406 let hw1: u16 = (0xF910 | base_bits) as u16;
6408 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6409 let mut bytes = hw1.to_le_bytes().to_vec();
6410 bytes.extend_from_slice(&hw2.to_le_bytes());
6411 Ok(bytes)
6412 }
6413
6414 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6416 let rd_bits = reg_to_bits(rd);
6417 let base_bits = reg_to_bits(base);
6418 check_ldst_imm12(offset)?;
6420 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6421 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6422 let mut bytes = hw1.to_le_bytes().to_vec();
6423 bytes.extend_from_slice(&hw2.to_le_bytes());
6424 Ok(bytes)
6425 }
6426
6427 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6429 let rd_bits = reg_to_bits(rd);
6430 let base_bits = reg_to_bits(base);
6431 let rm_bits = reg_to_bits(offset_reg);
6432 let hw1: u16 = (0xF830 | base_bits) as u16;
6434 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6435 let mut bytes = hw1.to_le_bytes().to_vec();
6436 bytes.extend_from_slice(&hw2.to_le_bytes());
6437 Ok(bytes)
6438 }
6439
6440 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6442 let rd_bits = reg_to_bits(rd);
6443 let base_bits = reg_to_bits(base);
6444 check_ldst_imm12(offset)?;
6446 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6447 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6448 let mut bytes = hw1.to_le_bytes().to_vec();
6449 bytes.extend_from_slice(&hw2.to_le_bytes());
6450 Ok(bytes)
6451 }
6452
6453 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6455 let rd_bits = reg_to_bits(rd);
6456 let base_bits = reg_to_bits(base);
6457 let rm_bits = reg_to_bits(offset_reg);
6458 let hw1: u16 = (0xF930 | base_bits) as u16;
6460 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6461 let mut bytes = hw1.to_le_bytes().to_vec();
6462 bytes.extend_from_slice(&hw2.to_le_bytes());
6463 Ok(bytes)
6464 }
6465
6466 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6468 let rd_bits = reg_to_bits(rd);
6469 let base_bits = reg_to_bits(base);
6470 check_ldst_imm12(offset)?;
6472 let hw1: u16 = (0xF880 | base_bits) as u16;
6473 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6474 let mut bytes = hw1.to_le_bytes().to_vec();
6475 bytes.extend_from_slice(&hw2.to_le_bytes());
6476 Ok(bytes)
6477 }
6478
6479 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6481 let rd_bits = reg_to_bits(rd);
6482 let base_bits = reg_to_bits(base);
6483 let rm_bits = reg_to_bits(offset_reg);
6484 let hw1: u16 = (0xF800 | base_bits) as u16;
6486 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6487 let mut bytes = hw1.to_le_bytes().to_vec();
6488 bytes.extend_from_slice(&hw2.to_le_bytes());
6489 Ok(bytes)
6490 }
6491
6492 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6494 let rd_bits = reg_to_bits(rd);
6495 let base_bits = reg_to_bits(base);
6496 check_ldst_imm12(offset)?;
6498 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6499 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6500 let mut bytes = hw1.to_le_bytes().to_vec();
6501 bytes.extend_from_slice(&hw2.to_le_bytes());
6502 Ok(bytes)
6503 }
6504
6505 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6507 let rd_bits = reg_to_bits(rd);
6508 let base_bits = reg_to_bits(base);
6509 let rm_bits = reg_to_bits(offset_reg);
6510 let hw1: u16 = (0xF820 | base_bits) as u16;
6512 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6513 let mut bytes = hw1.to_le_bytes().to_vec();
6514 bytes.extend_from_slice(&hw2.to_le_bytes());
6515 Ok(bytes)
6516 }
6517
6518 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6520 let rd_bits = reg_to_bits(rd);
6521 let rn_bits = reg_to_bits(rn);
6522
6523 if imm <= 0xFFF {
6529 let i_bit = (imm >> 11) & 1;
6530 let imm3 = (imm >> 8) & 0x7;
6531 let imm8 = imm & 0xFF;
6532
6533 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6534 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6535
6536 let mut bytes = hw1.to_le_bytes().to_vec();
6537 bytes.extend_from_slice(&hw2.to_le_bytes());
6538 Ok(bytes)
6539 } else {
6540 Err(synth_core::Error::synthesis(
6543 "ADD immediate too large for single instruction",
6544 ))
6545 }
6546 }
6547
6548 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6558 reg_bits_checked(rd)?;
6559 encoding_contracts::verify_imm16(imm16);
6560 let imm16 = imm16 & 0xFFFF;
6563 let imm4 = (imm16 >> 12) & 0xF;
6564 let i_bit = (imm16 >> 11) & 1;
6565 let imm3 = (imm16 >> 8) & 0x7;
6566 let imm8 = imm16 & 0xFF;
6567
6568 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6569 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6570
6571 let mut bytes = hw1.to_le_bytes().to_vec();
6572 bytes.extend_from_slice(&hw2.to_le_bytes());
6573 encoding_contracts::verify_thumb32(&bytes);
6574 Ok(bytes)
6575 }
6576
6577 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6585 reg_bits_checked(rd)?;
6586 encoding_contracts::verify_imm16(imm16);
6587 let imm16 = imm16 & 0xFFFF;
6590 let imm4 = (imm16 >> 12) & 0xF;
6591 let i_bit = (imm16 >> 11) & 1;
6592 let imm3 = (imm16 >> 8) & 0x7;
6593 let imm8 = imm16 & 0xFF;
6594
6595 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6596 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6597
6598 let mut bytes = hw1.to_le_bytes().to_vec();
6599 bytes.extend_from_slice(&hw2.to_le_bytes());
6600 encoding_contracts::verify_thumb32(&bytes);
6601 Ok(bytes)
6602 }
6603
6604 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6606 let imm5 = shift & 0x1F;
6609 let imm2 = imm5 & 0x3;
6610 let imm3 = (imm5 >> 2) & 0x7;
6611
6612 let hw1: u16 = 0xEA4F;
6613 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6614
6615 let mut bytes = hw1.to_le_bytes().to_vec();
6616 bytes.extend_from_slice(&hw2.to_le_bytes());
6617 Ok(bytes)
6618 }
6619
6620 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6622 let hw1: u16 = (0xEA00 | rn) as u16;
6625 let hw2: u16 = ((rd << 8) | rm) as u16;
6626
6627 let mut bytes = hw1.to_le_bytes().to_vec();
6628 bytes.extend_from_slice(&hw2.to_le_bytes());
6629 Ok(bytes)
6630 }
6631
6632 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6634 let i_bit = (imm >> 11) & 1;
6638 let imm3 = (imm >> 8) & 0x7;
6639 let imm8 = imm & 0xFF;
6640
6641 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6642 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6643
6644 let mut bytes = hw1.to_le_bytes().to_vec();
6645 bytes.extend_from_slice(&hw2.to_le_bytes());
6646 Ok(bytes)
6647 }
6648
6649 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6651 let hw1: u16 = (0xEBA0 | rn) as u16;
6654 let hw2: u16 = ((rd << 8) | rm) as u16;
6655
6656 let mut bytes = hw1.to_le_bytes().to_vec();
6657 bytes.extend_from_slice(&hw2.to_le_bytes());
6658 Ok(bytes)
6659 }
6660
6661 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6663 let hw1: u16 = (0xEB00 | rn) as u16;
6666 let hw2: u16 = ((rd << 8) | rm) as u16;
6667
6668 let mut bytes = hw1.to_le_bytes().to_vec();
6669 bytes.extend_from_slice(&hw2.to_le_bytes());
6670 Ok(bytes)
6671 }
6672
6673 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6677 let hw1: u16 = (0xEB10 | rn) as u16;
6679 let hw2: u16 = ((rd << 8) | rm) as u16;
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_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6688 let hw1: u16 = (0xEBB0 | rn) as u16;
6690 let hw2: u16 = ((rd << 8) | rm) as u16;
6691 let mut bytes = hw1.to_le_bytes().to_vec();
6692 bytes.extend_from_slice(&hw2.to_le_bytes());
6693 Ok(bytes)
6694 }
6695
6696 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6698 let mut code = Vec::new();
6699
6700 for op in ops {
6701 let encoded = self.encode(op)?;
6702 code.extend_from_slice(&encoded);
6703 }
6704
6705 Ok(code)
6706 }
6707}
6708
6709fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6717 if value <= 0xFF {
6719 return Some(value);
6720 }
6721 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6725 return Some(0x100 | b0);
6726 }
6727 if value == (b1 << 24) | (b1 << 8) {
6729 return Some(0x200 | b1);
6730 }
6731 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6733 return Some(0x300 | b0);
6734 }
6735 for rot in 8..=31u32 {
6739 let unrot = value.rotate_left(rot);
6740 if (0x80..=0xFF).contains(&unrot) {
6741 return Some((rot << 7) | (unrot & 0x7F));
6742 }
6743 }
6744 None
6745}
6746
6747fn check_ldst_imm12(offset: u32) -> Result<()> {
6753 if offset > 0xFFF {
6754 Err(synth_core::Error::synthesis(
6755 "load/store immediate offset > 0xFFF (4095) — materialize the offset into a register",
6756 ))
6757 } else {
6758 Ok(())
6759 }
6760}
6761
6762fn reg_to_bits(reg: &Reg) -> u32 {
6763 match reg {
6764 Reg::R0 => 0,
6765 Reg::R1 => 1,
6766 Reg::R2 => 2,
6767 Reg::R3 => 3,
6768 Reg::R4 => 4,
6769 Reg::R5 => 5,
6770 Reg::R6 => 6,
6771 Reg::R7 => 7,
6772 Reg::R8 => 8,
6773 Reg::R9 => 9,
6774 Reg::R10 => 10,
6775 Reg::R11 => 11,
6776 Reg::R12 => 12,
6777 Reg::SP => 13,
6778 Reg::LR => 14,
6779 Reg::PC => 15,
6780 }
6781}
6782
6783fn reg_bits_checked(bits: u32) -> Result<()> {
6791 if bits > 14 {
6792 return Err(synth_core::Error::synthesis(format!(
6793 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6794 )));
6795 }
6796 Ok(())
6797}
6798
6799fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6802 if val == 0 {
6803 return Some((0, 1));
6804 }
6805 for rot in 0..16u32 {
6806 let shift = rot * 2;
6807 let unrotated = val.rotate_left(shift);
6809 if unrotated <= 0xFF {
6810 return Some(((rot << 8) | unrotated, 1));
6812 }
6813 }
6814 None
6815}
6816
6817fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6822 match op2 {
6823 Operand2::Imm(val) => {
6824 let uval = *val as u32;
6825 if let Some(encoded) = try_encode_rotated_imm(uval) {
6827 encoded
6828 } else {
6829 let imm = uval & 0xFF;
6834 (imm, 1)
6835 }
6836 }
6837
6838 Operand2::Reg(reg) => {
6839 let reg_bits = reg_to_bits(reg);
6840 (reg_bits, 0) }
6842
6843 Operand2::RegShift {
6844 rm,
6845 shift: _,
6846 amount,
6847 } => {
6848 let rm_bits = reg_to_bits(rm);
6850 let shift_bits = (*amount & 0x1F) << 7;
6851 (shift_bits | rm_bits, 0)
6852 }
6853 }
6854}
6855
6856fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6858 let base_bits = reg_to_bits(&addr.base);
6859 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6861}
6862
6863fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6865 match reg {
6866 VfpReg::S0 => Ok(0),
6867 VfpReg::S1 => Ok(1),
6868 VfpReg::S2 => Ok(2),
6869 VfpReg::S3 => Ok(3),
6870 VfpReg::S4 => Ok(4),
6871 VfpReg::S5 => Ok(5),
6872 VfpReg::S6 => Ok(6),
6873 VfpReg::S7 => Ok(7),
6874 VfpReg::S8 => Ok(8),
6875 VfpReg::S9 => Ok(9),
6876 VfpReg::S10 => Ok(10),
6877 VfpReg::S11 => Ok(11),
6878 VfpReg::S12 => Ok(12),
6879 VfpReg::S13 => Ok(13),
6880 VfpReg::S14 => Ok(14),
6881 VfpReg::S15 => Ok(15),
6882 VfpReg::S16 => Ok(16),
6883 VfpReg::S17 => Ok(17),
6884 VfpReg::S18 => Ok(18),
6885 VfpReg::S19 => Ok(19),
6886 VfpReg::S20 => Ok(20),
6887 VfpReg::S21 => Ok(21),
6888 VfpReg::S22 => Ok(22),
6889 VfpReg::S23 => Ok(23),
6890 VfpReg::S24 => Ok(24),
6891 VfpReg::S25 => Ok(25),
6892 VfpReg::S26 => Ok(26),
6893 VfpReg::S27 => Ok(27),
6894 VfpReg::S28 => Ok(28),
6895 VfpReg::S29 => Ok(29),
6896 VfpReg::S30 => Ok(30),
6897 VfpReg::S31 => Ok(31),
6898 _ => Err(synth_core::Error::SynthesisError(
6900 "D-register not supported in single-precision VFP encoding".to_string(),
6901 )),
6902 }
6903}
6904
6905fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6907 match reg {
6908 VfpReg::D0 => Ok(0),
6909 VfpReg::D1 => Ok(1),
6910 VfpReg::D2 => Ok(2),
6911 VfpReg::D3 => Ok(3),
6912 VfpReg::D4 => Ok(4),
6913 VfpReg::D5 => Ok(5),
6914 VfpReg::D6 => Ok(6),
6915 VfpReg::D7 => Ok(7),
6916 VfpReg::D8 => Ok(8),
6917 VfpReg::D9 => Ok(9),
6918 VfpReg::D10 => Ok(10),
6919 VfpReg::D11 => Ok(11),
6920 VfpReg::D12 => Ok(12),
6921 VfpReg::D13 => Ok(13),
6922 VfpReg::D14 => Ok(14),
6923 VfpReg::D15 => Ok(15),
6924 _ => Err(synth_core::Error::SynthesisError(
6926 "S-register not supported in double-precision VFP encoding".to_string(),
6927 )),
6928 }
6929}
6930
6931fn encode_sreg(s: u32) -> (u32, u32) {
6935 (s >> 1, s & 1)
6936}
6937
6938fn encode_dreg(d: u32) -> (u32, u32) {
6942 (d & 0xF, (d >> 4) & 1)
6943}
6944
6945fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6951 let sd_num = vfp_sreg_to_num(sd)?;
6952 let sn_num = vfp_sreg_to_num(sn)?;
6953 let sm_num = vfp_sreg_to_num(sm)?;
6954 let (vd, d) = encode_sreg(sd_num);
6955 let (vn, n) = encode_sreg(sn_num);
6956 let (vm, m) = encode_sreg(sm_num);
6957
6958 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6959}
6960
6961fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6964 let sd_num = vfp_sreg_to_num(sd)?;
6965 let sm_num = vfp_sreg_to_num(sm)?;
6966 let (vd, d) = encode_sreg(sd_num);
6967 let (vm, m) = encode_sreg(sm_num);
6968
6969 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6970}
6971
6972fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6976 let sd_num = vfp_sreg_to_num(sd)?;
6977 let (vd, d) = encode_sreg(sd_num);
6978 let rn = reg_to_bits(&addr.base);
6979
6980 let offset = addr.offset;
6981 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6982 let abs_offset = offset.unsigned_abs();
6983 let imm8 = (abs_offset / 4) & 0xFF;
6984
6985 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6986}
6987
6988fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6992 let s_num = vfp_sreg_to_num(sreg)?;
6993 let (vn, n) = encode_sreg(s_num);
6994 let rt = reg_to_bits(core);
6995
6996 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6997 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6998}
6999
7000fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
7004 let dd_num = vfp_dreg_to_num(dd)?;
7005 let dn_num = vfp_dreg_to_num(dn)?;
7006 let dm_num = vfp_dreg_to_num(dm)?;
7007 let (vd, d) = encode_dreg(dd_num);
7008 let (vn, n) = encode_dreg(dn_num);
7009 let (vm, m) = encode_dreg(dm_num);
7010
7011 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
7012}
7013
7014fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
7016 let dd_num = vfp_dreg_to_num(dd)?;
7017 let dm_num = vfp_dreg_to_num(dm)?;
7018 let (vd, d) = encode_dreg(dd_num);
7019 let (vm, m) = encode_dreg(dm_num);
7020
7021 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7022}
7023
7024fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7027 let dd_num = vfp_dreg_to_num(dd)?;
7028 let (vd, d) = encode_dreg(dd_num);
7029 let rn = reg_to_bits(&addr.base);
7030
7031 let offset = addr.offset;
7032 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7033 let abs_offset = offset.unsigned_abs();
7034 let imm8 = (abs_offset / 4) & 0xFF;
7035
7036 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7037}
7038
7039fn encode_vmov_core_dreg(
7043 to_dreg: bool,
7044 dreg: &VfpReg,
7045 core_lo: &Reg,
7046 core_hi: &Reg,
7047) -> Result<u32> {
7048 let d_num = vfp_dreg_to_num(dreg)?;
7049 let (vm, m) = encode_dreg(d_num);
7050 let rt = reg_to_bits(core_lo);
7051 let rt2 = reg_to_bits(core_hi);
7052
7053 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
7054 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
7055}
7056
7057fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
7059 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
7060 let hw2 = (instr & 0xFFFF) as u16;
7061 let mut bytes = hw1.to_le_bytes().to_vec();
7062 bytes.extend_from_slice(&hw2.to_le_bytes());
7063 bytes
7064}
7065
7066fn qreg_to_num(reg: &QReg) -> u32 {
7072 match reg {
7073 QReg::Q0 => 0,
7074 QReg::Q1 => 1,
7075 QReg::Q2 => 2,
7076 QReg::Q3 => 3,
7077 QReg::Q4 => 4,
7078 QReg::Q5 => 5,
7079 QReg::Q6 => 6,
7080 QReg::Q7 => 7,
7081 }
7082}
7083
7084fn mve_size_bits(size: &MveSize) -> u32 {
7086 match size {
7087 MveSize::S8 => 0b00,
7088 MveSize::S16 => 0b01,
7089 MveSize::S32 => 0b10,
7090 }
7091}
7092
7093fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7097 let d = qreg_to_num(qd) * 2;
7098 let n = qreg_to_num(qn) * 2;
7099 let m = qreg_to_num(qm) * 2;
7100
7101 let vd = d & 0xF;
7106 let d_bit = (d >> 4) & 1;
7107 let vn = n & 0xF;
7108 let n_bit = (n >> 4) & 1;
7109 let vm = m & 0xF;
7110 let m_bit = (m >> 4) & 1;
7111
7112 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7113}
7114
7115fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7117 encode_mve_3reg(base, qd, qn, qm)
7118}
7119
7120fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7123 let qd_enc = qreg_to_num(qd) * 2;
7124 let rn = reg_to_bits(&addr.base);
7125 let offset = addr.offset;
7126 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7127 let abs_offset = offset.unsigned_abs();
7128 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7132 | (u_bit << 23)
7133 | ((qd_enc >> 4) << 22)
7134 | (rn << 16)
7135 | ((qd_enc & 0xF) << 12)
7136 | (imm7 & 0x7F)
7137}
7138
7139fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7141 let qd_enc = qreg_to_num(qd) * 2;
7142 let rn = reg_to_bits(&addr.base);
7143 let offset = addr.offset;
7144 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7145 let abs_offset = offset.unsigned_abs();
7146 let imm7 = (abs_offset / 4) & 0x7F;
7147
7148 0xED000E80
7149 | (u_bit << 23)
7150 | ((qd_enc >> 4) << 22)
7151 | (rn << 16)
7152 | ((qd_enc & 0xF) << 12)
7153 | (imm7 & 0x7F)
7154}
7155
7156impl ArmEncoder {
7157 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7159 let mut result = Vec::new();
7160 let qd_num = qreg_to_num(qd);
7161
7162 for i in 0..4 {
7164 let word = u32::from_le_bytes([
7165 bytes[i * 4],
7166 bytes[i * 4 + 1],
7167 bytes[i * 4 + 2],
7168 bytes[i * 4 + 3],
7169 ]);
7170 let lo16 = word & 0xFFFF;
7171 let hi16 = (word >> 16) & 0xFFFF;
7172
7173 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7175 if hi16 != 0 {
7177 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7178 }
7179
7180 let s_num = qd_num * 4 + i as u32;
7182 let (vn, n) = encode_sreg(s_num);
7183 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7184 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7185 }
7186
7187 Ok(result)
7188 }
7189
7190 fn encode_thumb_mve_lane_wise_f32_binop(
7192 &self,
7193 qd: &QReg,
7194 qn: &QReg,
7195 qm: &QReg,
7196 vfp_base: u32,
7197 ) -> Result<Vec<u8>> {
7198 let mut result = Vec::new();
7199 let qd_num = qreg_to_num(qd);
7200 let qn_num = qreg_to_num(qn);
7201 let qm_num = qreg_to_num(qm);
7202
7203 for i in 0..4u32 {
7205 let sd = qd_num * 4 + i;
7206 let sn = qn_num * 4 + i;
7207 let sm = qm_num * 4 + i;
7208
7209 let (vd, d) = encode_sreg(sd);
7210 let (vn, n) = encode_sreg(sn);
7211 let (vm, m) = encode_sreg(sm);
7212
7213 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7214 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7215 }
7216
7217 Ok(result)
7218 }
7219
7220 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7222 let mut result = Vec::new();
7223 let qd_num = qreg_to_num(qd);
7224 let qm_num = qreg_to_num(qm);
7225
7226 for i in 0..4u32 {
7228 let sd = qd_num * 4 + i;
7229 let sm = qm_num * 4 + i;
7230
7231 let (vd, d) = encode_sreg(sd);
7232 let (vm, m) = encode_sreg(sm);
7233
7234 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7235 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7236 }
7237
7238 Ok(result)
7239 }
7240}
7241
7242#[cfg(test)]
7243mod tests {
7244 use super::*;
7245
7246 #[test]
7247 fn test_encoder_creation() {
7248 let encoder_arm = ArmEncoder::new_arm32();
7249 assert!(!encoder_arm.thumb_mode);
7250
7251 let encoder_thumb = ArmEncoder::new_thumb2();
7252 assert!(encoder_thumb.thumb_mode);
7253 }
7254
7255 #[test]
7262 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7263 use synth_synthesis::{ArmOp, Condition, Reg};
7264 let enc = ArmEncoder::new_thumb2();
7265 let hi = enc
7267 .encode(&ArmOp::SetCond {
7268 rd: Reg::R12,
7269 cond: Condition::NE,
7270 })
7271 .unwrap();
7272 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7273 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7275 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7276 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7277 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7278 let lo = enc
7280 .encode(&ArmOp::SetCond {
7281 rd: Reg::R0,
7282 cond: Condition::NE,
7283 })
7284 .unwrap();
7285 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7286 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7287 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7288 }
7289
7290 #[test]
7294 fn test_encode_umull_209b() {
7295 use synth_synthesis::{ArmOp, Reg};
7296 let op = ArmOp::Umull {
7297 rdlo: Reg::R4,
7298 rdhi: Reg::R5,
7299 rn: Reg::R0,
7300 rm: Reg::R3,
7301 };
7302 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7304 assert_eq!(
7305 t,
7306 vec![0xA0, 0xFB, 0x03, 0x45],
7307 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7308 );
7309 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7311 assert_eq!(
7312 a,
7313 0xE085_4390u32.to_le_bytes().to_vec(),
7314 "umull (A32): {a:02x?}"
7315 );
7316 }
7317
7318 #[test]
7325 fn test_encode_arm32_indexed_load_keeps_index_206() {
7326 use synth_synthesis::{ArmOp, MemAddr, Reg};
7327 let enc = ArmEncoder::new_arm32();
7328 let bytes = enc
7330 .encode(&ArmOp::Ldr {
7331 rd: Reg::R0,
7332 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7333 })
7334 .unwrap();
7335 assert_eq!(
7336 bytes.len(),
7337 8,
7338 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7339 );
7340 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7341 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7342 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7344 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7346 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7348 }
7349
7350 #[test]
7357 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7358 let encoder = ArmEncoder::new_thumb2();
7359
7360 let code = encoder
7362 .encode(&ArmOp::Add {
7363 rd: Reg::R12,
7364 rn: Reg::R12,
7365 op2: Operand2::Reg(Reg::R0),
7366 })
7367 .unwrap();
7368 assert_eq!(
7370 code,
7371 vec![0x0C, 0xEB, 0x00, 0x0C],
7372 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7373 );
7374 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7376
7377 let lo = encoder
7379 .encode(&ArmOp::Add {
7380 rd: Reg::R1,
7381 rn: Reg::R2,
7382 op2: Operand2::Reg(Reg::R3),
7383 })
7384 .unwrap();
7385 assert_eq!(
7386 lo.len(),
7387 2,
7388 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7389 );
7390 }
7391
7392 #[test]
7395 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7396 let encoder = ArmEncoder::new_thumb2();
7397
7398 let adds = encoder
7400 .encode(&ArmOp::Adds {
7401 rd: Reg::R10,
7402 rn: Reg::R10,
7403 op2: Operand2::Reg(Reg::R8),
7404 })
7405 .unwrap();
7406 assert_eq!(
7407 adds,
7408 vec![0x1A, 0xEB, 0x08, 0x0A],
7409 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7410 );
7411
7412 let subs = encoder
7414 .encode(&ArmOp::Subs {
7415 rd: Reg::R10,
7416 rn: Reg::R10,
7417 op2: Operand2::Reg(Reg::R8),
7418 })
7419 .unwrap();
7420 assert_eq!(
7421 subs,
7422 vec![0xBA, 0xEB, 0x08, 0x0A],
7423 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7424 );
7425 }
7426
7427 #[test]
7430 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7431 let encoder = ArmEncoder::new_thumb2();
7432
7433 let cmn = encoder
7435 .encode(&ArmOp::Cmn {
7436 rn: Reg::R10,
7437 op2: Operand2::Reg(Reg::R8),
7438 })
7439 .unwrap();
7440 assert_eq!(
7441 cmn,
7442 vec![0x1A, 0xEB, 0x08, 0x0F],
7443 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7444 );
7445
7446 let lo = encoder
7448 .encode(&ArmOp::Cmn {
7449 rn: Reg::R1,
7450 op2: Operand2::Reg(Reg::R2),
7451 })
7452 .unwrap();
7453 assert_eq!(
7454 lo.len(),
7455 2,
7456 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7457 );
7458 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7459 }
7460
7461 #[test]
7465 fn test_encode_pc_operand_returns_err_not_panic_185() {
7466 let encoder = ArmEncoder::new_thumb2();
7467 for op in [
7468 ArmOp::Sdiv {
7469 rd: Reg::PC,
7470 rn: Reg::R0,
7471 rm: Reg::R1,
7472 },
7473 ArmOp::Udiv {
7474 rd: Reg::R0,
7475 rn: Reg::PC,
7476 rm: Reg::R1,
7477 },
7478 ArmOp::Sdiv {
7479 rd: Reg::R0,
7480 rn: Reg::R1,
7481 rm: Reg::PC,
7482 },
7483 ] {
7484 let r = encoder.encode(&op);
7485 assert!(
7486 r.is_err(),
7487 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7488 );
7489 }
7490 assert!(
7492 encoder
7493 .encode(&ArmOp::Sdiv {
7494 rd: Reg::R0,
7495 rn: Reg::R1,
7496 rm: Reg::R2
7497 })
7498 .is_ok()
7499 );
7500 }
7501
7502 #[test]
7503 fn test_encode_nop_arm32() {
7504 let encoder = ArmEncoder::new_arm32();
7505 let code = encoder.encode(&ArmOp::Nop).unwrap();
7506
7507 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7510
7511 #[test]
7512 fn test_encode_nop_thumb() {
7513 let encoder = ArmEncoder::new_thumb2();
7514 let code = encoder.encode(&ArmOp::Nop).unwrap();
7515
7516 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7519
7520 #[test]
7521 fn test_encode_mov_immediate_arm32() {
7522 let encoder = ArmEncoder::new_arm32();
7523 let op = ArmOp::Mov {
7524 rd: Reg::R0,
7525 op2: Operand2::Imm(42),
7526 };
7527
7528 let code = encoder.encode(&op).unwrap();
7529 assert_eq!(code.len(), 4);
7530
7531 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7533 assert_eq!(instr & 0x0E000000, 0x02000000); }
7535
7536 #[test]
7537 fn test_encode_add_registers_arm32() {
7538 let encoder = ArmEncoder::new_arm32();
7539 let op = ArmOp::Add {
7540 rd: Reg::R0,
7541 rn: Reg::R1,
7542 op2: Operand2::Reg(Reg::R2),
7543 };
7544
7545 let code = encoder.encode(&op).unwrap();
7546 assert_eq!(code.len(), 4);
7547
7548 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7549 assert_eq!(instr & 0x0FE00000, 0x00800000);
7551 }
7552
7553 #[test]
7554 fn test_encode_ldr_arm32() {
7555 let encoder = ArmEncoder::new_arm32();
7556 let op = ArmOp::Ldr {
7557 rd: Reg::R0,
7558 addr: MemAddr::imm(Reg::R1, 4),
7559 };
7560
7561 let code = encoder.encode(&op).unwrap();
7562 assert_eq!(code.len(), 4);
7563
7564 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7565 assert_eq!(instr & 0x00100000, 0x00100000);
7567 }
7568
7569 #[test]
7570 fn test_encode_str_arm32() {
7571 let encoder = ArmEncoder::new_arm32();
7572 let op = ArmOp::Str {
7573 rd: Reg::R0,
7574 addr: MemAddr::imm(Reg::SP, 0),
7575 };
7576
7577 let code = encoder.encode(&op).unwrap();
7578 assert_eq!(code.len(), 4);
7579 }
7580
7581 #[test]
7582 fn test_encode_branch_arm32() {
7583 let encoder = ArmEncoder::new_arm32();
7584 let op = ArmOp::Bl {
7585 label: "main".to_string(),
7586 };
7587
7588 let code = encoder.encode(&op).unwrap();
7589 assert_eq!(code.len(), 4);
7590
7591 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7592 assert_eq!(instr & 0x0F000000, 0x0B000000);
7594 }
7595
7596 #[test]
7606 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7607 let encoder = ArmEncoder::new_thumb2();
7608 let op = ArmOp::Bl {
7609 label: "callee".to_string(),
7610 };
7611
7612 let code = encoder.encode(&op).unwrap();
7613 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7614
7615 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7616 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7617 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7618 assert_eq!(
7619 hw2, 0xFFFE,
7620 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7621 );
7622 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7623 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7624 }
7625
7626 #[test]
7627 fn test_encode_sequence() {
7628 let encoder = ArmEncoder::new_arm32();
7629 let ops = vec![
7630 ArmOp::Mov {
7631 rd: Reg::R0,
7632 op2: Operand2::Imm(42),
7633 },
7634 ArmOp::Mov {
7635 rd: Reg::R1,
7636 op2: Operand2::Imm(10),
7637 },
7638 ArmOp::Add {
7639 rd: Reg::R2,
7640 rn: Reg::R0,
7641 op2: Operand2::Reg(Reg::R1),
7642 },
7643 ];
7644
7645 let code = encoder.encode_sequence(&ops).unwrap();
7646 assert_eq!(code.len(), 12); }
7648
7649 #[test]
7650 fn test_reg_to_bits() {
7651 assert_eq!(reg_to_bits(&Reg::R0), 0);
7652 assert_eq!(reg_to_bits(&Reg::R7), 7);
7653 assert_eq!(reg_to_bits(&Reg::SP), 13);
7654 assert_eq!(reg_to_bits(&Reg::LR), 14);
7655 assert_eq!(reg_to_bits(&Reg::PC), 15);
7656 }
7657
7658 #[test]
7659 fn test_encode_bitwise_operations() {
7660 let encoder = ArmEncoder::new_arm32();
7661
7662 let and_op = ArmOp::And {
7663 rd: Reg::R0,
7664 rn: Reg::R1,
7665 op2: Operand2::Reg(Reg::R2),
7666 };
7667 let and_code = encoder.encode(&and_op).unwrap();
7668 assert_eq!(and_code.len(), 4);
7669
7670 let orr_op = ArmOp::Orr {
7671 rd: Reg::R0,
7672 rn: Reg::R1,
7673 op2: Operand2::Reg(Reg::R2),
7674 };
7675 let orr_code = encoder.encode(&orr_op).unwrap();
7676 assert_eq!(orr_code.len(), 4);
7677
7678 let eor_op = ArmOp::Eor {
7679 rd: Reg::R0,
7680 rn: Reg::R1,
7681 op2: Operand2::Reg(Reg::R2),
7682 };
7683 let eor_code = encoder.encode(&eor_op).unwrap();
7684 assert_eq!(eor_code.len(), 4);
7685 }
7686
7687 #[test]
7690 fn test_encode_sdiv_thumb2() {
7691 let encoder = ArmEncoder::new_thumb2();
7692 let op = ArmOp::Sdiv {
7693 rd: Reg::R0,
7694 rn: Reg::R1,
7695 rm: Reg::R2,
7696 };
7697
7698 let code = encoder.encode(&op).unwrap();
7699 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7706 assert_eq!(code[1], 0xFB);
7707 assert_eq!(code[2], 0xF2);
7708 assert_eq!(code[3], 0xF0);
7709 }
7710
7711 #[test]
7712 fn test_encode_udiv_thumb2() {
7713 let encoder = ArmEncoder::new_thumb2();
7714 let op = ArmOp::Udiv {
7715 rd: Reg::R0,
7716 rn: Reg::R1,
7717 rm: Reg::R2,
7718 };
7719
7720 let code = encoder.encode(&op).unwrap();
7721 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7726 assert_eq!(code[1], 0xFB);
7727 assert_eq!(code[2], 0xF2);
7728 assert_eq!(code[3], 0xF0);
7729 }
7730
7731 #[test]
7732 fn test_encode_mul_thumb2() {
7733 let encoder = ArmEncoder::new_thumb2();
7734 let op = ArmOp::Mul {
7735 rd: Reg::R0,
7736 rn: Reg::R1,
7737 rm: Reg::R2,
7738 };
7739
7740 let code = encoder.encode(&op).unwrap();
7741 assert_eq!(code.len(), 4); }
7743
7744 #[test]
7745 fn test_encode_and_thumb2() {
7746 let encoder = ArmEncoder::new_thumb2();
7747 let op = ArmOp::And {
7748 rd: Reg::R0,
7749 rn: Reg::R1,
7750 op2: Operand2::Reg(Reg::R2),
7751 };
7752
7753 let code = encoder.encode(&op).unwrap();
7754 assert_eq!(code.len(), 4); }
7756
7757 #[test]
7758 fn test_encode_lsl_thumb2_low_regs() {
7759 let encoder = ArmEncoder::new_thumb2();
7760 let op = ArmOp::Lsl {
7761 rd: Reg::R0,
7762 rn: Reg::R1,
7763 shift: 5,
7764 };
7765
7766 let code = encoder.encode(&op).unwrap();
7767 assert_eq!(code.len(), 2); }
7769
7770 #[test]
7771 fn test_encode_clz_thumb2() {
7772 let encoder = ArmEncoder::new_thumb2();
7773 let op = ArmOp::Clz {
7774 rd: Reg::R0,
7775 rm: Reg::R1,
7776 };
7777
7778 let code = encoder.encode(&op).unwrap();
7779 assert_eq!(code.len(), 4); }
7781
7782 #[test]
7783 fn test_encode_bx_thumb2() {
7784 let encoder = ArmEncoder::new_thumb2();
7785 let op = ArmOp::Bx { rm: Reg::LR };
7786
7787 let code = encoder.encode(&op).unwrap();
7788 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7792 }
7793
7794 #[test]
7799 fn test_encode_f32_abs_arm32() {
7800 let encoder = ArmEncoder::new_arm32();
7801 let op = ArmOp::F32Abs {
7802 sd: VfpReg::S0,
7803 sm: VfpReg::S2,
7804 };
7805 let code = encoder.encode(&op).unwrap();
7806 assert_eq!(code.len(), 4); }
7808
7809 #[test]
7810 fn test_encode_f32_neg_arm32() {
7811 let encoder = ArmEncoder::new_arm32();
7812 let op = ArmOp::F32Neg {
7813 sd: VfpReg::S0,
7814 sm: VfpReg::S2,
7815 };
7816 let code = encoder.encode(&op).unwrap();
7817 assert_eq!(code.len(), 4);
7818 }
7819
7820 #[test]
7821 fn test_encode_f32_sqrt_arm32() {
7822 let encoder = ArmEncoder::new_arm32();
7823 let op = ArmOp::F32Sqrt {
7824 sd: VfpReg::S0,
7825 sm: VfpReg::S2,
7826 };
7827 let code = encoder.encode(&op).unwrap();
7828 assert_eq!(code.len(), 4);
7829 }
7830
7831 #[test]
7832 fn test_encode_f32_ceil_arm32() {
7833 let encoder = ArmEncoder::new_arm32();
7834 let op = ArmOp::F32Ceil {
7835 sd: VfpReg::S0,
7836 sm: VfpReg::S2,
7837 };
7838 let code = encoder.encode(&op).unwrap();
7839 assert_eq!(code.len(), 36);
7841 }
7842
7843 #[test]
7844 fn test_encode_f32_floor_thumb2() {
7845 let encoder = ArmEncoder::new_thumb2();
7846 let op = ArmOp::F32Floor {
7847 sd: VfpReg::S0,
7848 sm: VfpReg::S2,
7849 };
7850 let code = encoder.encode(&op).unwrap();
7851 assert_eq!(code.len(), 36);
7853 }
7854
7855 #[test]
7856 fn test_encode_f32_min_arm32() {
7857 let encoder = ArmEncoder::new_arm32();
7858 let op = ArmOp::F32Min {
7859 sd: VfpReg::S0,
7860 sn: VfpReg::S2,
7861 sm: VfpReg::S4,
7862 };
7863 let code = encoder.encode(&op).unwrap();
7864 assert_eq!(code.len(), 16); }
7866
7867 #[test]
7868 fn test_encode_f32_max_thumb2() {
7869 let encoder = ArmEncoder::new_thumb2();
7870 let op = ArmOp::F32Max {
7871 sd: VfpReg::S0,
7872 sn: VfpReg::S2,
7873 sm: VfpReg::S4,
7874 };
7875 let code = encoder.encode(&op).unwrap();
7876 assert_eq!(code.len(), 18);
7878 }
7879
7880 #[test]
7881 fn test_encode_f32_copysign_arm32() {
7882 let encoder = ArmEncoder::new_arm32();
7883 let op = ArmOp::F32Copysign {
7884 sd: VfpReg::S0,
7885 sn: VfpReg::S2,
7886 sm: VfpReg::S4,
7887 };
7888 let code = encoder.encode(&op).unwrap();
7889 assert_eq!(code.len(), 24);
7891 }
7892
7893 #[test]
7898 fn test_encode_f64_add_arm32() {
7899 let encoder = ArmEncoder::new_arm32();
7900 let op = ArmOp::F64Add {
7901 dd: VfpReg::D0,
7902 dn: VfpReg::D1,
7903 dm: VfpReg::D2,
7904 };
7905 let code = encoder.encode(&op).unwrap();
7906 assert_eq!(code.len(), 4);
7907 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7909 assert_eq!((instr >> 8) & 0xF, 0xB); }
7911
7912 #[test]
7913 fn test_encode_f64_sub_thumb2() {
7914 let encoder = ArmEncoder::new_thumb2();
7915 let op = ArmOp::F64Sub {
7916 dd: VfpReg::D0,
7917 dn: VfpReg::D1,
7918 dm: VfpReg::D2,
7919 };
7920 let code = encoder.encode(&op).unwrap();
7921 assert_eq!(code.len(), 4); }
7923
7924 #[test]
7925 fn test_encode_f64_mul_arm32() {
7926 let encoder = ArmEncoder::new_arm32();
7927 let op = ArmOp::F64Mul {
7928 dd: VfpReg::D0,
7929 dn: VfpReg::D1,
7930 dm: VfpReg::D2,
7931 };
7932 let code = encoder.encode(&op).unwrap();
7933 assert_eq!(code.len(), 4);
7934 }
7935
7936 #[test]
7937 fn test_encode_f64_div_arm32() {
7938 let encoder = ArmEncoder::new_arm32();
7939 let op = ArmOp::F64Div {
7940 dd: VfpReg::D0,
7941 dn: VfpReg::D1,
7942 dm: VfpReg::D2,
7943 };
7944 let code = encoder.encode(&op).unwrap();
7945 assert_eq!(code.len(), 4);
7946 }
7947
7948 #[test]
7949 fn test_encode_f64_abs_arm32() {
7950 let encoder = ArmEncoder::new_arm32();
7951 let op = ArmOp::F64Abs {
7952 dd: VfpReg::D0,
7953 dm: VfpReg::D2,
7954 };
7955 let code = encoder.encode(&op).unwrap();
7956 assert_eq!(code.len(), 4);
7957 }
7958
7959 #[test]
7960 fn test_encode_f64_neg_arm32() {
7961 let encoder = ArmEncoder::new_arm32();
7962 let op = ArmOp::F64Neg {
7963 dd: VfpReg::D0,
7964 dm: VfpReg::D2,
7965 };
7966 let code = encoder.encode(&op).unwrap();
7967 assert_eq!(code.len(), 4);
7968 }
7969
7970 #[test]
7971 fn test_encode_f64_sqrt_arm32() {
7972 let encoder = ArmEncoder::new_arm32();
7973 let op = ArmOp::F64Sqrt {
7974 dd: VfpReg::D0,
7975 dm: VfpReg::D2,
7976 };
7977 let code = encoder.encode(&op).unwrap();
7978 assert_eq!(code.len(), 4);
7979 }
7980
7981 #[test]
7982 fn test_encode_f64_load_arm32() {
7983 let encoder = ArmEncoder::new_arm32();
7984 let op = ArmOp::F64Load {
7985 dd: VfpReg::D0,
7986 addr: MemAddr::imm(Reg::R0, 8),
7987 };
7988 let code = encoder.encode(&op).unwrap();
7989 assert_eq!(code.len(), 4);
7990 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7991 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7994
7995 #[test]
7996 fn test_encode_f64_store_thumb2() {
7997 let encoder = ArmEncoder::new_thumb2();
7998 let op = ArmOp::F64Store {
7999 dd: VfpReg::D0,
8000 addr: MemAddr::imm(Reg::SP, 0),
8001 };
8002 let code = encoder.encode(&op).unwrap();
8003 assert_eq!(code.len(), 4);
8004 }
8005
8006 #[test]
8007 fn test_encode_f64_compare_arm32() {
8008 let encoder = ArmEncoder::new_arm32();
8009 let op = ArmOp::F64Eq {
8010 rd: Reg::R0,
8011 dn: VfpReg::D0,
8012 dm: VfpReg::D1,
8013 };
8014 let code = encoder.encode(&op).unwrap();
8015 assert_eq!(code.len(), 16); }
8017
8018 #[test]
8019 fn test_encode_f64_compare_thumb2() {
8020 let encoder = ArmEncoder::new_thumb2();
8021 let op = ArmOp::F64Lt {
8022 rd: Reg::R0,
8023 dn: VfpReg::D0,
8024 dm: VfpReg::D1,
8025 };
8026 let code = encoder.encode(&op).unwrap();
8027 assert_eq!(code.len(), 14);
8029 }
8030
8031 #[test]
8032 fn test_encode_f64_const_arm32() {
8033 let encoder = ArmEncoder::new_arm32();
8034 let op = ArmOp::F64Const {
8035 dd: VfpReg::D0,
8036 value: 3.125,
8037 };
8038 let code = encoder.encode(&op).unwrap();
8039 assert_eq!(code.len(), 20);
8041 }
8042
8043 #[test]
8044 fn test_encode_f64_const_thumb2() {
8045 let encoder = ArmEncoder::new_thumb2();
8046 let op = ArmOp::F64Const {
8047 dd: VfpReg::D0,
8048 value: 2.5,
8049 };
8050 let code = encoder.encode(&op).unwrap();
8051 assert_eq!(code.len(), 20);
8053 }
8054
8055 #[test]
8056 fn test_encode_f64_convert_i32s_arm32() {
8057 let encoder = ArmEncoder::new_arm32();
8058 let op = ArmOp::F64ConvertI32S {
8059 dd: VfpReg::D0,
8060 rm: Reg::R0,
8061 };
8062 let code = encoder.encode(&op).unwrap();
8063 assert_eq!(code.len(), 8);
8065 }
8066
8067 #[test]
8068 fn test_encode_f64_promote_f32_arm32() {
8069 let encoder = ArmEncoder::new_arm32();
8070 let op = ArmOp::F64PromoteF32 {
8071 dd: VfpReg::D0,
8072 sm: VfpReg::S0,
8073 };
8074 let code = encoder.encode(&op).unwrap();
8075 assert_eq!(code.len(), 4); }
8077
8078 #[test]
8079 fn test_encode_f64_promote_f32_thumb2() {
8080 let encoder = ArmEncoder::new_thumb2();
8081 let op = ArmOp::F64PromoteF32 {
8082 dd: VfpReg::D0,
8083 sm: VfpReg::S0,
8084 };
8085 let code = encoder.encode(&op).unwrap();
8086 assert_eq!(code.len(), 4);
8087 }
8088
8089 #[test]
8090 fn test_encode_i32_trunc_f64s_arm32() {
8091 let encoder = ArmEncoder::new_arm32();
8092 let op = ArmOp::I32TruncF64S {
8093 rd: Reg::R0,
8094 dm: VfpReg::D0,
8095 };
8096 let code = encoder.encode(&op).unwrap();
8097 assert_eq!(code.len(), 8);
8099 }
8100
8101 #[test]
8102 fn test_encode_f64_reinterpret_i64_arm32() {
8103 let encoder = ArmEncoder::new_arm32();
8104 let op = ArmOp::F64ReinterpretI64 {
8105 dd: VfpReg::D0,
8106 rmlo: Reg::R0,
8107 rmhi: Reg::R1,
8108 };
8109 let code = encoder.encode(&op).unwrap();
8110 assert_eq!(code.len(), 4); }
8112
8113 #[test]
8114 fn test_encode_i64_reinterpret_f64_thumb2() {
8115 let encoder = ArmEncoder::new_thumb2();
8116 let op = ArmOp::I64ReinterpretF64 {
8117 rdlo: Reg::R0,
8118 rdhi: Reg::R1,
8119 dm: VfpReg::D0,
8120 };
8121 let code = encoder.encode(&op).unwrap();
8122 assert_eq!(code.len(), 4);
8123 }
8124
8125 #[test]
8126 fn test_encode_f64_trunc_thumb2() {
8127 let encoder = ArmEncoder::new_thumb2();
8128 let op = ArmOp::F64Trunc {
8129 dd: VfpReg::D0,
8130 dm: VfpReg::D1,
8131 };
8132 let code = encoder.encode(&op).unwrap();
8133 assert_eq!(code.len(), 8);
8135 }
8136
8137 #[test]
8138 fn test_encode_f64_min_arm32() {
8139 let encoder = ArmEncoder::new_arm32();
8140 let op = ArmOp::F64Min {
8141 dd: VfpReg::D0,
8142 dn: VfpReg::D1,
8143 dm: VfpReg::D2,
8144 };
8145 let code = encoder.encode(&op).unwrap();
8146 assert_eq!(code.len(), 16);
8148 }
8149
8150 #[test]
8151 fn test_f64_cp11_encoding() {
8152 let encoder = ArmEncoder::new_arm32();
8154
8155 let code = encoder
8157 .encode(&ArmOp::F64Add {
8158 dd: VfpReg::D0,
8159 dn: VfpReg::D0,
8160 dm: VfpReg::D0,
8161 })
8162 .unwrap();
8163 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8164 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8165
8166 let code = encoder
8168 .encode(&ArmOp::F32Add {
8169 sd: VfpReg::S0,
8170 sn: VfpReg::S0,
8171 sm: VfpReg::S0,
8172 })
8173 .unwrap();
8174 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8175 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8176 }
8177
8178 #[test]
8179 fn test_dreg_encoding_higher_registers() {
8180 let encoder = ArmEncoder::new_arm32();
8181
8182 let op = ArmOp::F64Add {
8184 dd: VfpReg::D15,
8185 dn: VfpReg::D14,
8186 dm: VfpReg::D13,
8187 };
8188 let code = encoder.encode(&op).unwrap();
8189 assert_eq!(code.len(), 4);
8190
8191 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8193 assert_eq!((instr >> 8) & 0xF, 0xB); }
8195
8196 #[test]
8201 fn test_encode_label_emits_no_bytes() {
8202 let encoder = ArmEncoder::new_thumb2();
8203 let op = ArmOp::Label {
8204 name: ".Lblock_end_0".to_string(),
8205 };
8206 let code = encoder.encode(&op).unwrap();
8207 assert!(code.is_empty(), "Label should emit zero bytes");
8208
8209 let encoder32 = ArmEncoder::new_arm32();
8210 let code32 = encoder32.encode(&op).unwrap();
8211 assert!(
8212 code32.is_empty(),
8213 "Label should emit zero bytes in ARM32 too"
8214 );
8215 }
8216
8217 #[test]
8218 fn test_encode_bcc_eq_thumb2() {
8219 use synth_synthesis::Condition;
8220 let encoder = ArmEncoder::new_thumb2();
8221 let op = ArmOp::Bcc {
8222 cond: Condition::EQ,
8223 label: "target".to_string(),
8224 };
8225 let code = encoder.encode(&op).unwrap();
8226 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8230 }
8231
8232 #[test]
8233 fn test_encode_bcc_ne_thumb2() {
8234 use synth_synthesis::Condition;
8235 let encoder = ArmEncoder::new_thumb2();
8236 let op = ArmOp::Bcc {
8237 cond: Condition::NE,
8238 label: "target".to_string(),
8239 };
8240 let code = encoder.encode(&op).unwrap();
8241 assert_eq!(code.len(), 2);
8242
8243 assert_eq!(code, vec![0x00, 0xD1]);
8245 }
8246
8247 #[test]
8248 fn test_encode_bcc_arm32() {
8249 use synth_synthesis::Condition;
8250 let encoder = ArmEncoder::new_arm32();
8251 let op = ArmOp::Bcc {
8252 cond: Condition::EQ,
8253 label: "target".to_string(),
8254 };
8255 let code = encoder.encode(&op).unwrap();
8256 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8259 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8263
8264 #[test]
8265 fn test_encode_udf_thumb2() {
8266 let encoder = ArmEncoder::new_thumb2();
8267 let op = ArmOp::Udf { imm: 0 };
8268 let code = encoder.encode(&op).unwrap();
8269 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8273 }
8274
8275 #[test]
8276 fn test_encode_nop_thumb2() {
8277 let encoder = ArmEncoder::new_thumb2();
8278 let op = ArmOp::Nop;
8279 let code = encoder.encode(&op).unwrap();
8280 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8284 }
8285
8286 #[test]
8291 fn test_encode_i64_add_thumb2() {
8292 let encoder = ArmEncoder::new_thumb2();
8293 let op = ArmOp::I64Add {
8294 rdlo: Reg::R0,
8295 rdhi: Reg::R1,
8296 rnlo: Reg::R0,
8297 rnhi: Reg::R1,
8298 rmlo: Reg::R2,
8299 rmhi: Reg::R3,
8300 };
8301 let code = encoder.encode(&op).unwrap();
8302 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8304 }
8305
8306 #[test]
8307 fn test_encode_i64_sub_thumb2() {
8308 let encoder = ArmEncoder::new_thumb2();
8309 let op = ArmOp::I64Sub {
8310 rdlo: Reg::R0,
8311 rdhi: Reg::R1,
8312 rnlo: Reg::R0,
8313 rnhi: Reg::R1,
8314 rmlo: Reg::R2,
8315 rmhi: Reg::R3,
8316 };
8317 let code = encoder.encode(&op).unwrap();
8318 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8320 }
8321
8322 #[test]
8323 fn test_encode_i64_and_thumb2() {
8324 let encoder = ArmEncoder::new_thumb2();
8325 let op = ArmOp::I64And {
8326 rdlo: Reg::R0,
8327 rdhi: Reg::R1,
8328 rnlo: Reg::R0,
8329 rnhi: Reg::R1,
8330 rmlo: Reg::R2,
8331 rmhi: Reg::R3,
8332 };
8333 let code = encoder.encode(&op).unwrap();
8334 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8336 }
8337
8338 #[test]
8339 fn test_encode_i64_or_thumb2() {
8340 let encoder = ArmEncoder::new_thumb2();
8341 let op = ArmOp::I64Or {
8342 rdlo: Reg::R0,
8343 rdhi: Reg::R1,
8344 rnlo: Reg::R0,
8345 rnhi: Reg::R1,
8346 rmlo: Reg::R2,
8347 rmhi: Reg::R3,
8348 };
8349 let code = encoder.encode(&op).unwrap();
8350 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8351 }
8352
8353 #[test]
8354 fn test_encode_i64_xor_thumb2() {
8355 let encoder = ArmEncoder::new_thumb2();
8356 let op = ArmOp::I64Xor {
8357 rdlo: Reg::R0,
8358 rdhi: Reg::R1,
8359 rnlo: Reg::R0,
8360 rnhi: Reg::R1,
8361 rmlo: Reg::R2,
8362 rmhi: Reg::R3,
8363 };
8364 let code = encoder.encode(&op).unwrap();
8365 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8366 }
8367
8368 #[test]
8369 fn test_encode_i64_const_small_thumb2() {
8370 let encoder = ArmEncoder::new_thumb2();
8371 let op = ArmOp::I64Const {
8373 rdlo: Reg::R0,
8374 rdhi: Reg::R1,
8375 value: 42,
8376 };
8377 let code = encoder.encode(&op).unwrap();
8378 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8380 }
8381
8382 #[test]
8383 fn test_encode_i64_const_large_thumb2() {
8384 let encoder = ArmEncoder::new_thumb2();
8385 let op = ArmOp::I64Const {
8387 rdlo: Reg::R0,
8388 rdhi: Reg::R1,
8389 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8390 };
8391 let code = encoder.encode(&op).unwrap();
8392 assert_eq!(
8394 code.len(),
8395 16,
8396 "I64Const with large value should be 16 bytes"
8397 );
8398 }
8399
8400 #[test]
8401 fn test_encode_i64_extend_i32_s_thumb2() {
8402 let encoder = ArmEncoder::new_thumb2();
8403 let op = ArmOp::I64ExtendI32S {
8404 rdlo: Reg::R0,
8405 rdhi: Reg::R1,
8406 rn: Reg::R0,
8407 };
8408 let code = encoder.encode(&op).unwrap();
8409 assert_eq!(
8411 code.len(),
8412 4,
8413 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8414 );
8415 }
8416
8417 #[test]
8418 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8419 let encoder = ArmEncoder::new_thumb2();
8420 let op = ArmOp::I64ExtendI32S {
8421 rdlo: Reg::R0,
8422 rdhi: Reg::R1,
8423 rn: Reg::R2,
8424 };
8425 let code = encoder.encode(&op).unwrap();
8426 assert!(
8428 code.len() >= 6,
8429 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8430 );
8431 }
8432
8433 #[test]
8434 fn test_encode_i64_extend_i32_u_thumb2() {
8435 let encoder = ArmEncoder::new_thumb2();
8436 let op = ArmOp::I64ExtendI32U {
8437 rdlo: Reg::R0,
8438 rdhi: Reg::R1,
8439 rn: Reg::R0,
8440 };
8441 let code = encoder.encode(&op).unwrap();
8442 assert_eq!(
8444 code.len(),
8445 2,
8446 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8447 );
8448 }
8449
8450 #[test]
8451 fn test_encode_i32_wrap_i64_nop_thumb2() {
8452 let encoder = ArmEncoder::new_thumb2();
8453 let op = ArmOp::I32WrapI64 {
8455 rd: Reg::R0,
8456 rnlo: Reg::R0,
8457 };
8458 let code = encoder.encode(&op).unwrap();
8459 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8460 assert_eq!(code, vec![0x00, 0xBF]); }
8462
8463 #[test]
8464 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8465 let encoder = ArmEncoder::new_thumb2();
8466 let op = ArmOp::I32WrapI64 {
8467 rd: Reg::R2,
8468 rnlo: Reg::R0,
8469 };
8470 let code = encoder.encode(&op).unwrap();
8471 assert!(
8473 code.len() >= 2,
8474 "I32WrapI64 diff reg should emit at least 2 bytes"
8475 );
8476 }
8477
8478 #[test]
8479 fn test_encode_i64_eqz_thumb2() {
8480 let encoder = ArmEncoder::new_thumb2();
8481 let op = ArmOp::I64Eqz {
8482 rd: Reg::R0,
8483 rnlo: Reg::R0,
8484 rnhi: Reg::R1,
8485 };
8486 let code = encoder.encode(&op).unwrap();
8487 assert!(
8489 code.len() >= 6,
8490 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8491 );
8492 }
8493
8494 #[test]
8495 fn test_encode_i64_eq_thumb2() {
8496 let encoder = ArmEncoder::new_thumb2();
8497 let op = ArmOp::I64Eq {
8498 rd: Reg::R0,
8499 rnlo: Reg::R0,
8500 rnhi: Reg::R1,
8501 rmlo: Reg::R2,
8502 rmhi: Reg::R3,
8503 };
8504 let code = encoder.encode(&op).unwrap();
8505 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8507 }
8508
8509 #[test]
8510 fn test_encode_i64_ldr_thumb2() {
8511 let encoder = ArmEncoder::new_thumb2();
8512 let op = ArmOp::I64Ldr {
8513 rdlo: Reg::R0,
8514 rdhi: Reg::R1,
8515 addr: MemAddr::imm(Reg::SP, 0),
8516 };
8517 let code = encoder.encode(&op).unwrap();
8518 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8520 }
8521
8522 #[test]
8523 fn test_encode_i64_str_thumb2() {
8524 let encoder = ArmEncoder::new_thumb2();
8525 let op = ArmOp::I64Str {
8526 rdlo: Reg::R0,
8527 rdhi: Reg::R1,
8528 addr: MemAddr::imm(Reg::SP, 0),
8529 };
8530 let code = encoder.encode(&op).unwrap();
8531 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8533 }
8534
8535 #[test]
8536 fn test_encode_i64_all_comparisons_thumb2() {
8537 let encoder = ArmEncoder::new_thumb2();
8538
8539 let ops = vec![
8540 ArmOp::I64Ne {
8541 rd: Reg::R0,
8542 rnlo: Reg::R0,
8543 rnhi: Reg::R1,
8544 rmlo: Reg::R2,
8545 rmhi: Reg::R3,
8546 },
8547 ArmOp::I64LtS {
8548 rd: Reg::R0,
8549 rnlo: Reg::R0,
8550 rnhi: Reg::R1,
8551 rmlo: Reg::R2,
8552 rmhi: Reg::R3,
8553 },
8554 ArmOp::I64LtU {
8555 rd: Reg::R0,
8556 rnlo: Reg::R0,
8557 rnhi: Reg::R1,
8558 rmlo: Reg::R2,
8559 rmhi: Reg::R3,
8560 },
8561 ArmOp::I64LeS {
8562 rd: Reg::R0,
8563 rnlo: Reg::R0,
8564 rnhi: Reg::R1,
8565 rmlo: Reg::R2,
8566 rmhi: Reg::R3,
8567 },
8568 ArmOp::I64LeU {
8569 rd: Reg::R0,
8570 rnlo: Reg::R0,
8571 rnhi: Reg::R1,
8572 rmlo: Reg::R2,
8573 rmhi: Reg::R3,
8574 },
8575 ArmOp::I64GtS {
8576 rd: Reg::R0,
8577 rnlo: Reg::R0,
8578 rnhi: Reg::R1,
8579 rmlo: Reg::R2,
8580 rmhi: Reg::R3,
8581 },
8582 ArmOp::I64GtU {
8583 rd: Reg::R0,
8584 rnlo: Reg::R0,
8585 rnhi: Reg::R1,
8586 rmlo: Reg::R2,
8587 rmhi: Reg::R3,
8588 },
8589 ArmOp::I64GeS {
8590 rd: Reg::R0,
8591 rnlo: Reg::R0,
8592 rnhi: Reg::R1,
8593 rmlo: Reg::R2,
8594 rmhi: Reg::R3,
8595 },
8596 ArmOp::I64GeU {
8597 rd: Reg::R0,
8598 rnlo: Reg::R0,
8599 rnhi: Reg::R1,
8600 rmlo: Reg::R2,
8601 rmhi: Reg::R3,
8602 },
8603 ];
8604
8605 for op in &ops {
8606 let code = encoder.encode(op).unwrap();
8607 assert!(
8608 code.len() >= 8,
8609 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8610 op,
8611 code.len()
8612 );
8613 }
8614 }
8615
8616 #[test]
8617 fn test_encode_i64_const_zero_thumb2() {
8618 let encoder = ArmEncoder::new_thumb2();
8619 let op = ArmOp::I64Const {
8620 rdlo: Reg::R0,
8621 rdhi: Reg::R1,
8622 value: 0,
8623 };
8624 let code = encoder.encode(&op).unwrap();
8625 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8627 }
8628
8629 #[test]
8630 fn test_encode_i64_const_negative_one_thumb2() {
8631 let encoder = ArmEncoder::new_thumb2();
8632 let op = ArmOp::I64Const {
8633 rdlo: Reg::R0,
8634 rdhi: Reg::R1,
8635 value: -1, };
8637 let code = encoder.encode(&op).unwrap();
8638 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8640 }
8641
8642 #[test]
8647 fn test_encode_ldrb_arm32() {
8648 let encoder = ArmEncoder::new_arm32();
8649 let op = ArmOp::Ldrb {
8650 rd: Reg::R0,
8651 addr: MemAddr::imm(Reg::R1, 4),
8652 };
8653 let code = encoder.encode(&op).unwrap();
8654 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8655 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8657 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8658 }
8659
8660 #[test]
8661 fn test_encode_strb_arm32() {
8662 let encoder = ArmEncoder::new_arm32();
8663 let op = ArmOp::Strb {
8664 rd: Reg::R0,
8665 addr: MemAddr::imm(Reg::R1, 0),
8666 };
8667 let code = encoder.encode(&op).unwrap();
8668 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8669 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8671 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8672 }
8673
8674 #[test]
8675 fn test_encode_ldrh_arm32() {
8676 let encoder = ArmEncoder::new_arm32();
8677 let op = ArmOp::Ldrh {
8678 rd: Reg::R0,
8679 addr: MemAddr::imm(Reg::R1, 2),
8680 };
8681 let code = encoder.encode(&op).unwrap();
8682 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8683 }
8684
8685 #[test]
8686 fn test_encode_strh_arm32() {
8687 let encoder = ArmEncoder::new_arm32();
8688 let op = ArmOp::Strh {
8689 rd: Reg::R0,
8690 addr: MemAddr::imm(Reg::R1, 0),
8691 };
8692 let code = encoder.encode(&op).unwrap();
8693 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8694 }
8695
8696 #[test]
8697 fn test_encode_ldrsb_arm32() {
8698 let encoder = ArmEncoder::new_arm32();
8699 let op = ArmOp::Ldrsb {
8700 rd: Reg::R0,
8701 addr: MemAddr::imm(Reg::R1, 0),
8702 };
8703 let code = encoder.encode(&op).unwrap();
8704 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8705 }
8706
8707 #[test]
8708 fn test_encode_ldrsh_arm32() {
8709 let encoder = ArmEncoder::new_arm32();
8710 let op = ArmOp::Ldrsh {
8711 rd: Reg::R0,
8712 addr: MemAddr::imm(Reg::R1, 0),
8713 };
8714 let code = encoder.encode(&op).unwrap();
8715 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8716 }
8717
8718 #[test]
8719 fn test_encode_ldrb_thumb2_16bit() {
8720 let encoder = ArmEncoder::new_thumb2();
8721 let op = ArmOp::Ldrb {
8722 rd: Reg::R0,
8723 addr: MemAddr::imm(Reg::R1, 4),
8724 };
8725 let code = encoder.encode(&op).unwrap();
8726 assert_eq!(
8728 code.len(),
8729 2,
8730 "Thumb-2 LDRB with small offset should be 16-bit"
8731 );
8732 }
8733
8734 #[test]
8735 fn test_encode_ldrb_thumb2_32bit() {
8736 let encoder = ArmEncoder::new_thumb2();
8737 let op = ArmOp::Ldrb {
8738 rd: Reg::R0,
8739 addr: MemAddr::imm(Reg::R1, 100), };
8741 let code = encoder.encode(&op).unwrap();
8742 assert_eq!(
8743 code.len(),
8744 4,
8745 "Thumb-2 LDRB with large offset should be 32-bit"
8746 );
8747 }
8748
8749 #[test]
8750 fn test_encode_strb_thumb2_16bit() {
8751 let encoder = ArmEncoder::new_thumb2();
8752 let op = ArmOp::Strb {
8753 rd: Reg::R0,
8754 addr: MemAddr::imm(Reg::R1, 10),
8755 };
8756 let code = encoder.encode(&op).unwrap();
8757 assert_eq!(
8758 code.len(),
8759 2,
8760 "Thumb-2 STRB with small offset should be 16-bit"
8761 );
8762 }
8763
8764 #[test]
8765 fn test_encode_ldrh_thumb2_16bit() {
8766 let encoder = ArmEncoder::new_thumb2();
8767 let op = ArmOp::Ldrh {
8768 rd: Reg::R0,
8769 addr: MemAddr::imm(Reg::R1, 4), };
8771 let code = encoder.encode(&op).unwrap();
8772 assert_eq!(
8773 code.len(),
8774 2,
8775 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8776 );
8777 }
8778
8779 #[test]
8780 fn test_encode_strh_thumb2_16bit() {
8781 let encoder = ArmEncoder::new_thumb2();
8782 let op = ArmOp::Strh {
8783 rd: Reg::R0,
8784 addr: MemAddr::imm(Reg::R1, 4),
8785 };
8786 let code = encoder.encode(&op).unwrap();
8787 assert_eq!(
8788 code.len(),
8789 2,
8790 "Thumb-2 STRH with small aligned offset should be 16-bit"
8791 );
8792 }
8793
8794 #[test]
8795 fn test_encode_ldrsb_thumb2() {
8796 let encoder = ArmEncoder::new_thumb2();
8797 let op = ArmOp::Ldrsb {
8798 rd: Reg::R0,
8799 addr: MemAddr::imm(Reg::R1, 0),
8800 };
8801 let code = encoder.encode(&op).unwrap();
8802 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8804 }
8805
8806 #[test]
8807 fn test_encode_ldrsh_thumb2() {
8808 let encoder = ArmEncoder::new_thumb2();
8809 let op = ArmOp::Ldrsh {
8810 rd: Reg::R0,
8811 addr: MemAddr::imm(Reg::R1, 0),
8812 };
8813 let code = encoder.encode(&op).unwrap();
8814 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8815 }
8816
8817 #[test]
8818 fn test_encode_memory_size_thumb2() {
8819 let encoder = ArmEncoder::new_thumb2();
8820 let op = ArmOp::MemorySize { rd: Reg::R0 };
8821 let code = encoder.encode(&op).unwrap();
8822 assert!(!code.is_empty(), "MemorySize should produce code");
8824 }
8825
8826 #[test]
8827 fn test_encode_memory_grow_thumb2() {
8828 let encoder = ArmEncoder::new_thumb2();
8829 let op = ArmOp::MemoryGrow {
8830 rd: Reg::R0,
8831 rn: Reg::R0,
8832 };
8833 let code = encoder.encode(&op).unwrap();
8834 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8835 }
8836
8837 #[test]
8838 fn test_encode_subword_reg_offset_thumb2() {
8839 let encoder = ArmEncoder::new_thumb2();
8840
8841 let op = ArmOp::Ldrb {
8843 rd: Reg::R0,
8844 addr: MemAddr::reg(Reg::R1, Reg::R2),
8845 };
8846 let code = encoder.encode(&op).unwrap();
8847 assert_eq!(
8848 code.len(),
8849 4,
8850 "Thumb-2 LDRB with reg offset should be 32-bit"
8851 );
8852
8853 let op = ArmOp::Strb {
8855 rd: Reg::R0,
8856 addr: MemAddr::reg(Reg::R1, Reg::R2),
8857 };
8858 let code = encoder.encode(&op).unwrap();
8859 assert_eq!(
8860 code.len(),
8861 4,
8862 "Thumb-2 STRB with reg offset should be 32-bit"
8863 );
8864
8865 let op = ArmOp::Ldrh {
8867 rd: Reg::R0,
8868 addr: MemAddr::reg(Reg::R1, Reg::R2),
8869 };
8870 let code = encoder.encode(&op).unwrap();
8871 assert_eq!(
8872 code.len(),
8873 4,
8874 "Thumb-2 LDRH with reg offset should be 32-bit"
8875 );
8876
8877 let op = ArmOp::Strh {
8879 rd: Reg::R0,
8880 addr: MemAddr::reg(Reg::R1, Reg::R2),
8881 };
8882 let code = encoder.encode(&op).unwrap();
8883 assert_eq!(
8884 code.len(),
8885 4,
8886 "Thumb-2 STRH with reg offset should be 32-bit"
8887 );
8888 }
8889
8890 #[test]
8891 fn test_encode_subword_reg_imm_offset_thumb2() {
8892 let encoder = ArmEncoder::new_thumb2();
8893
8894 let op = ArmOp::Ldrb {
8896 rd: Reg::R0,
8897 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8898 };
8899 let code = encoder.encode(&op).unwrap();
8900 assert_eq!(
8902 code.len(),
8903 8,
8904 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8905 );
8906 }
8907
8908 #[test]
8913 fn test_encode_mve_addi32_thumb2() {
8914 let encoder = ArmEncoder::new_thumb2();
8915 let op = ArmOp::MveAddI {
8916 qd: QReg::Q0,
8917 qn: QReg::Q1,
8918 qm: QReg::Q2,
8919 size: MveSize::S32,
8920 };
8921 let code = encoder.encode(&op).unwrap();
8922 assert_eq!(
8923 code.len(),
8924 4,
8925 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8926 );
8927 }
8928
8929 #[test]
8930 fn test_encode_mve_subi16_thumb2() {
8931 let encoder = ArmEncoder::new_thumb2();
8932 let op = ArmOp::MveSubI {
8933 qd: QReg::Q0,
8934 qn: QReg::Q1,
8935 qm: QReg::Q2,
8936 size: MveSize::S16,
8937 };
8938 let code = encoder.encode(&op).unwrap();
8939 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8940 }
8941
8942 #[test]
8943 fn test_encode_mve_muli8_thumb2() {
8944 let encoder = ArmEncoder::new_thumb2();
8945 let op = ArmOp::MveMulI {
8946 qd: QReg::Q0,
8947 qn: QReg::Q1,
8948 qm: QReg::Q2,
8949 size: MveSize::S8,
8950 };
8951 let code = encoder.encode(&op).unwrap();
8952 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8953 }
8954
8955 #[test]
8956 fn test_encode_mve_bitwise_thumb2() {
8957 let encoder = ArmEncoder::new_thumb2();
8958
8959 let ops = vec![
8960 ArmOp::MveAnd {
8961 qd: QReg::Q0,
8962 qn: QReg::Q1,
8963 qm: QReg::Q2,
8964 },
8965 ArmOp::MveOrr {
8966 qd: QReg::Q0,
8967 qn: QReg::Q1,
8968 qm: QReg::Q2,
8969 },
8970 ArmOp::MveEor {
8971 qd: QReg::Q0,
8972 qn: QReg::Q1,
8973 qm: QReg::Q2,
8974 },
8975 ArmOp::MveBic {
8976 qd: QReg::Q0,
8977 qn: QReg::Q1,
8978 qm: QReg::Q2,
8979 },
8980 ];
8981 for op in ops {
8982 let code = encoder.encode(&op).unwrap();
8983 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8984 }
8985 }
8986
8987 #[test]
8988 fn test_encode_mve_mvn_thumb2() {
8989 let encoder = ArmEncoder::new_thumb2();
8990 let op = ArmOp::MveMvn {
8991 qd: QReg::Q0,
8992 qm: QReg::Q1,
8993 };
8994 let code = encoder.encode(&op).unwrap();
8995 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8996 }
8997
8998 #[test]
8999 fn test_encode_mve_load_store_thumb2() {
9000 let encoder = ArmEncoder::new_thumb2();
9001
9002 let load = ArmOp::MveLoad {
9003 qd: QReg::Q0,
9004 addr: MemAddr::imm(Reg::R0, 16),
9005 };
9006 let code = encoder.encode(&load).unwrap();
9007 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
9008
9009 let store = ArmOp::MveStore {
9010 qd: QReg::Q1,
9011 addr: MemAddr::imm(Reg::R1, 0),
9012 };
9013 let code = encoder.encode(&store).unwrap();
9014 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
9015 }
9016
9017 #[test]
9018 fn test_encode_mve_const_thumb2() {
9019 let encoder = ArmEncoder::new_thumb2();
9020 let op = ArmOp::MveConst {
9021 qd: QReg::Q0,
9022 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
9023 };
9024 let code = encoder.encode(&op).unwrap();
9025 assert!(
9028 code.len() >= 24,
9029 "MVE const should produce multiple instructions"
9030 );
9031 }
9032
9033 #[test]
9034 fn test_encode_mve_dup_thumb2() {
9035 let encoder = ArmEncoder::new_thumb2();
9036 let op = ArmOp::MveDup {
9037 qd: QReg::Q0,
9038 rn: Reg::R0,
9039 size: MveSize::S32,
9040 };
9041 let code = encoder.encode(&op).unwrap();
9042 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
9043 }
9044
9045 #[test]
9046 fn test_encode_mve_extract_lane_thumb2() {
9047 let encoder = ArmEncoder::new_thumb2();
9048 let op = ArmOp::MveExtractLane {
9049 rd: Reg::R0,
9050 qn: QReg::Q1,
9051 lane: 2,
9052 size: MveSize::S32,
9053 };
9054 let code = encoder.encode(&op).unwrap();
9055 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
9056 }
9057
9058 #[test]
9059 fn test_encode_mve_insert_lane_thumb2() {
9060 let encoder = ArmEncoder::new_thumb2();
9061 let op = ArmOp::MveInsertLane {
9062 qd: QReg::Q0,
9063 rn: Reg::R1,
9064 lane: 3,
9065 size: MveSize::S32,
9066 };
9067 let code = encoder.encode(&op).unwrap();
9068 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9069 }
9070
9071 #[test]
9072 fn test_encode_mve_addf32_thumb2() {
9073 let encoder = ArmEncoder::new_thumb2();
9074 let op = ArmOp::MveAddF32 {
9075 qd: QReg::Q0,
9076 qn: QReg::Q1,
9077 qm: QReg::Q2,
9078 };
9079 let code = encoder.encode(&op).unwrap();
9080 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9081 }
9082
9083 #[test]
9084 fn test_encode_mve_divf32_thumb2() {
9085 let encoder = ArmEncoder::new_thumb2();
9086 let op = ArmOp::MveDivF32 {
9087 qd: QReg::Q0,
9088 qn: QReg::Q1,
9089 qm: QReg::Q2,
9090 };
9091 let code = encoder.encode(&op).unwrap();
9092 assert_eq!(
9094 code.len(),
9095 16,
9096 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9097 );
9098 }
9099
9100 #[test]
9101 fn test_encode_mve_sqrtf32_thumb2() {
9102 let encoder = ArmEncoder::new_thumb2();
9103 let op = ArmOp::MveSqrtF32 {
9104 qd: QReg::Q0,
9105 qm: QReg::Q1,
9106 };
9107 let code = encoder.encode(&op).unwrap();
9108 assert_eq!(
9110 code.len(),
9111 16,
9112 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9113 );
9114 }
9115
9116 #[test]
9117 fn test_encode_mve_negf32_thumb2() {
9118 let encoder = ArmEncoder::new_thumb2();
9119 let op = ArmOp::MveNegF32 {
9120 qd: QReg::Q0,
9121 qm: QReg::Q1,
9122 };
9123 let code = encoder.encode(&op).unwrap();
9124 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9125 }
9126
9127 #[test]
9128 fn test_encode_mve_absf32_thumb2() {
9129 let encoder = ArmEncoder::new_thumb2();
9130 let op = ArmOp::MveAbsF32 {
9131 qd: QReg::Q0,
9132 qm: QReg::Q1,
9133 };
9134 let code = encoder.encode(&op).unwrap();
9135 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9136 }
9137
9138 #[test]
9153 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9154 let encoder = ArmEncoder::new_thumb2();
9155 let op = ArmOp::And {
9156 rd: Reg::R2,
9157 rn: Reg::R0,
9158 op2: Operand2::Imm(0x7e),
9159 };
9160 let code = encoder.encode(&op).unwrap();
9161 assert_eq!(
9162 code,
9163 vec![0x00, 0xf0, 0x7e, 0x02],
9164 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9165 );
9166 }
9167
9168 #[test]
9175 fn try_thumb_expand_imm_encodes_modified_immediates() {
9176 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9178 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);
9186 assert_eq!(try_thumb_expand_imm(0x12345), None);
9187 }
9188
9189 #[test]
9194 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9195 let encoder = ArmEncoder::new_thumb2();
9196 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9198 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9199 assert!(
9201 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9202 "cmp #0x101 must error, not compare the wrong constant"
9203 );
9204 assert!(
9205 encoder
9206 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9207 .is_err()
9208 );
9209 assert!(
9210 encoder
9211 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9212 .is_err()
9213 );
9214 assert!(
9216 encoder
9217 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9218 .is_ok()
9219 );
9220 }
9221
9222 #[test]
9225 fn mla_thumb2_encodes_correctly() {
9226 let encoder = ArmEncoder::new_thumb2();
9227 let code = encoder
9228 .encode(&ArmOp::Mla {
9229 rd: Reg::R2,
9230 rn: Reg::R3,
9231 rm: Reg::R4,
9232 ra: Reg::R8,
9233 })
9234 .unwrap();
9235 assert_eq!(code, vec![0x03, 0xfb, 0x04, 0x82]);
9237 }
9238
9239 #[test]
9244 fn ldst_imm12_offset_errors_when_out_of_range() {
9245 let encoder = ArmEncoder::new_thumb2();
9246 assert!(
9248 encoder
9249 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0xFFF)
9250 .is_ok()
9251 );
9252 assert!(
9254 encoder
9255 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0x1000)
9256 .is_err(),
9257 "ldr offset 4096 must error, not wrap to 0"
9258 );
9259 assert!(
9260 encoder
9261 .encode_thumb32_str(&Reg::R0, &Reg::R1, 0x1000)
9262 .is_err()
9263 );
9264 assert!(
9265 encoder
9266 .encode_thumb32_ldrb_imm(&Reg::R0, &Reg::R1, 5000)
9267 .is_err()
9268 );
9269 assert!(
9270 encoder
9271 .encode_thumb32_strh_imm(&Reg::R0, &Reg::R1, 5000)
9272 .is_err()
9273 );
9274 }
9275
9276 #[test]
9283 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9284 let encoder = ArmEncoder::new_thumb2();
9285 assert_eq!(
9287 encoder
9288 .encode(&ArmOp::Add {
9289 rd: Reg::SP,
9290 rn: Reg::SP,
9291 op2: Operand2::Imm(256),
9292 })
9293 .unwrap(),
9294 vec![0x0d, 0xf2, 0x00, 0x1d],
9295 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9296 );
9297 assert_eq!(
9299 encoder
9300 .encode(&ArmOp::Sub {
9301 rd: Reg::SP,
9302 rn: Reg::SP,
9303 op2: Operand2::Imm(256),
9304 })
9305 .unwrap(),
9306 vec![0xad, 0xf2, 0x00, 0x1d],
9307 );
9308 assert!(
9310 encoder
9311 .encode(&ArmOp::Add {
9312 rd: Reg::SP,
9313 rn: Reg::SP,
9314 op2: Operand2::Imm(5000),
9315 })
9316 .is_err(),
9317 "add #5000 must error (no single ADDW), not mis-encode"
9318 );
9319 }
9320
9321 #[test]
9326 fn and_cmn_immediate_thumb_expand_else_error() {
9327 let encoder = ArmEncoder::new_thumb2();
9328 assert_eq!(
9330 encoder
9331 .encode(&ArmOp::And {
9332 rd: Reg::R2,
9333 rn: Reg::R0,
9334 op2: Operand2::Imm(0x7e),
9335 })
9336 .unwrap(),
9337 vec![0x00, 0xf0, 0x7e, 0x02],
9338 );
9339 assert!(
9341 encoder
9342 .encode(&ArmOp::And {
9343 rd: Reg::R2,
9344 rn: Reg::R0,
9345 op2: Operand2::Imm(0xff00ff00u32 as i32),
9346 })
9347 .is_ok()
9348 );
9349 assert!(
9351 encoder
9352 .encode(&ArmOp::And {
9353 rd: Reg::R2,
9354 rn: Reg::R0,
9355 op2: Operand2::Imm(0x101),
9356 })
9357 .is_err()
9358 );
9359 assert!(
9360 encoder
9361 .encode(&ArmOp::Cmn {
9362 rn: Reg::R0,
9363 op2: Operand2::Imm(0x101),
9364 })
9365 .is_err(),
9366 "CMN #0x101 must error, not emit a NOP"
9367 );
9368 }
9369
9370 #[test]
9374 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9375 let encoder = ArmEncoder::new_thumb2();
9376 assert_eq!(
9378 encoder
9379 .encode(&ArmOp::Orr {
9380 rd: Reg::R2,
9381 rn: Reg::R0,
9382 op2: Operand2::Imm(0x7e),
9383 })
9384 .unwrap(),
9385 vec![0x40, 0xf0, 0x7e, 0x02],
9386 );
9387 assert_eq!(
9389 encoder
9390 .encode(&ArmOp::Eor {
9391 rd: Reg::R2,
9392 rn: Reg::R0,
9393 op2: Operand2::Imm(0x7e),
9394 })
9395 .unwrap(),
9396 vec![0x80, 0xf0, 0x7e, 0x02],
9397 );
9398 assert!(
9400 encoder
9401 .encode(&ArmOp::Orr {
9402 rd: Reg::R2,
9403 rn: Reg::R0,
9404 op2: Operand2::Imm(0x140),
9405 })
9406 .is_err(),
9407 "ORR #0x140 must error, not emit a NOP"
9408 );
9409 }
9410
9411 #[test]
9412 fn test_encode_mve_different_qregs() {
9413 let encoder = ArmEncoder::new_thumb2();
9414
9415 let op1 = ArmOp::MveAddI {
9417 qd: QReg::Q0,
9418 qn: QReg::Q0,
9419 qm: QReg::Q0,
9420 size: MveSize::S32,
9421 };
9422 let op2 = ArmOp::MveAddI {
9423 qd: QReg::Q3,
9424 qn: QReg::Q5,
9425 qm: QReg::Q7,
9426 size: MveSize::S32,
9427 };
9428 let code1 = encoder.encode(&op1).unwrap();
9429 let code2 = encoder.encode(&op2).unwrap();
9430 assert_ne!(
9431 code1, code2,
9432 "Different Q-registers should produce different encodings"
9433 );
9434 }
9435
9436 #[test]
9437 fn test_encode_mve_arm32_nop() {
9438 let encoder = ArmEncoder::new_arm32();
9440 let op = ArmOp::MveAddI {
9441 qd: QReg::Q0,
9442 qn: QReg::Q1,
9443 qm: QReg::Q2,
9444 size: MveSize::S32,
9445 };
9446 let code = encoder.encode(&op).unwrap();
9447 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9448 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9450 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9451 }
9452}