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 let imm_val = *imm as u32;
1917
1918 let i_bit = (imm_val >> 11) & 1;
1920 let imm3 = (imm_val >> 8) & 0x7;
1921 let imm8 = imm_val & 0xFF;
1922
1923 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1924 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1925
1926 let mut bytes = hw1.to_le_bytes().to_vec();
1927 bytes.extend_from_slice(&hw2.to_le_bytes());
1928 Ok(bytes)
1929 } else {
1930 let instr: u16 = 0xBF00;
1932 Ok(instr.to_le_bytes().to_vec())
1933 }
1934 }
1935
1936 ArmOp::Orr { rd, rn, op2 } => {
1938 if let Operand2::Reg(rm) = op2 {
1939 let rd_bits = reg_to_bits(rd);
1940 let rn_bits = reg_to_bits(rn);
1941 let rm_bits = reg_to_bits(rm);
1942
1943 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1945 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1946
1947 let mut bytes = hw1.to_le_bytes().to_vec();
1948 bytes.extend_from_slice(&hw2.to_le_bytes());
1949 Ok(bytes)
1950 } else if let Operand2::Imm(imm) = op2 {
1951 let imm_val = *imm as u32;
1956 if imm_val > 0xFF {
1957 return Err(synth_core::Error::synthesis(
1958 "ORR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1959 ));
1960 }
1961 let rd_bits = reg_to_bits(rd);
1962 let rn_bits = reg_to_bits(rn);
1963 let hw1: u16 = (0xF040 | rn_bits) as u16;
1964 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
1965 let mut bytes = hw1.to_le_bytes().to_vec();
1966 bytes.extend_from_slice(&hw2.to_le_bytes());
1967 Ok(bytes)
1968 } else {
1969 let instr: u16 = 0xBF00;
1970 Ok(instr.to_le_bytes().to_vec())
1971 }
1972 }
1973
1974 ArmOp::Eor { rd, rn, op2 } => {
1976 if let Operand2::Reg(rm) = op2 {
1977 let rd_bits = reg_to_bits(rd);
1978 let rn_bits = reg_to_bits(rn);
1979 let rm_bits = reg_to_bits(rm);
1980
1981 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1983 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1984
1985 let mut bytes = hw1.to_le_bytes().to_vec();
1986 bytes.extend_from_slice(&hw2.to_le_bytes());
1987 Ok(bytes)
1988 } else if let Operand2::Imm(imm) = op2 {
1989 let imm_val = *imm as u32;
1993 if imm_val > 0xFF {
1994 return Err(synth_core::Error::synthesis(
1995 "EOR immediate > 0xFF requires ThumbExpandImm (not yet implemented)",
1996 ));
1997 }
1998 let rd_bits = reg_to_bits(rd);
1999 let rn_bits = reg_to_bits(rn);
2000 let hw1: u16 = (0xF080 | rn_bits) as u16;
2001 let hw2: u16 = ((rd_bits << 8) | (imm_val & 0xFF)) as u16;
2002 let mut bytes = hw1.to_le_bytes().to_vec();
2003 bytes.extend_from_slice(&hw2.to_le_bytes());
2004 Ok(bytes)
2005 } else {
2006 let instr: u16 = 0xBF00;
2007 Ok(instr.to_le_bytes().to_vec())
2008 }
2009 }
2010
2011 ArmOp::Lsl { rd, rn, shift } => {
2013 let rd_bits = reg_to_bits(rd) as u16;
2014 let rn_bits = reg_to_bits(rn) as u16;
2015 let shift_bits = (*shift as u16) & 0x1F;
2016
2017 if rd_bits < 8 && rn_bits < 8 {
2018 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2020 Ok(instr.to_le_bytes().to_vec())
2021 } else {
2022 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
2025 }
2026
2027 ArmOp::Lsr { rd, rn, shift } => {
2028 let rd_bits = reg_to_bits(rd) as u16;
2029 let rn_bits = reg_to_bits(rn) as u16;
2030 let shift_bits = (*shift as u16) & 0x1F;
2031
2032 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2033 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2035 Ok(instr.to_le_bytes().to_vec())
2036 } else {
2037 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
2039 }
2040
2041 ArmOp::Asr { rd, rn, shift } => {
2042 let rd_bits = reg_to_bits(rd) as u16;
2043 let rn_bits = reg_to_bits(rn) as u16;
2044 let shift_bits = (*shift as u16) & 0x1F;
2045
2046 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
2047 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
2049 Ok(instr.to_le_bytes().to_vec())
2050 } else {
2051 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
2053 }
2054
2055 ArmOp::Ror { rd, rn, shift } => {
2056 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
2059
2060 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
2064 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
2065 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
2066 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
2067
2068 ArmOp::Rsb { rd, rn, imm } => {
2071 let rd_bits = reg_to_bits(rd);
2072 let rn_bits = reg_to_bits(rn);
2073 let imm_val = *imm;
2074
2075 let i_bit = (imm_val >> 11) & 1;
2076 let imm3 = (imm_val >> 8) & 0x7;
2077 let imm8 = imm_val & 0xFF;
2078
2079 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2081 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2083
2084 let mut bytes = hw1.to_le_bytes().to_vec();
2085 bytes.extend_from_slice(&hw2.to_le_bytes());
2086 Ok(bytes)
2087 }
2088
2089 ArmOp::Clz { rd, rm } => {
2091 let rd_bits = reg_to_bits(rd);
2092 let rm_bits = reg_to_bits(rm);
2093
2094 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2097 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2098
2099 let mut bytes = hw1.to_le_bytes().to_vec();
2100 bytes.extend_from_slice(&hw2.to_le_bytes());
2101 Ok(bytes)
2102 }
2103
2104 ArmOp::Rbit { rd, rm } => {
2106 let rd_bits = reg_to_bits(rd);
2107 let rm_bits = reg_to_bits(rm);
2108
2109 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2112 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2113
2114 let mut bytes = hw1.to_le_bytes().to_vec();
2115 bytes.extend_from_slice(&hw2.to_le_bytes());
2116 Ok(bytes)
2117 }
2118
2119 ArmOp::Sxtb { rd, rm } => {
2121 let rd_bits = reg_to_bits(rd) as u16;
2122 let rm_bits = reg_to_bits(rm) as u16;
2123
2124 if rd_bits < 8 && rm_bits < 8 {
2125 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2127 Ok(instr.to_le_bytes().to_vec())
2128 } else {
2129 let rd_bits32 = rd_bits as u32;
2132 let rm_bits32 = rm_bits as u32;
2133 let hw1: u16 = 0xFA4F;
2134 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2135 let mut bytes = hw1.to_le_bytes().to_vec();
2136 bytes.extend_from_slice(&hw2.to_le_bytes());
2137 Ok(bytes)
2138 }
2139 }
2140
2141 ArmOp::Sxth { rd, rm } => {
2143 let rd_bits = reg_to_bits(rd) as u16;
2144 let rm_bits = reg_to_bits(rm) as u16;
2145
2146 if rd_bits < 8 && rm_bits < 8 {
2147 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2149 Ok(instr.to_le_bytes().to_vec())
2150 } else {
2151 let rd_bits32 = rd_bits as u32;
2154 let rm_bits32 = rm_bits as u32;
2155 let hw1: u16 = 0xFA0F;
2156 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2157 let mut bytes = hw1.to_le_bytes().to_vec();
2158 bytes.extend_from_slice(&hw2.to_le_bytes());
2159 Ok(bytes)
2160 }
2161 }
2162
2163 ArmOp::Cmp { rn, op2 } => {
2165 let rn_bits = reg_to_bits(rn) as u16;
2166
2167 if let Operand2::Imm(imm) = op2 {
2168 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2171 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2173 Ok(instr.to_le_bytes().to_vec())
2174 } else {
2175 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2176 }
2177 } else if let Operand2::Reg(rm) = op2 {
2178 let rm_bits = reg_to_bits(rm) as u16;
2179 if rn_bits < 8 && rm_bits < 8 {
2180 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2182 Ok(instr.to_le_bytes().to_vec())
2183 } else {
2184 let n_bit = (rn_bits >> 3) & 1;
2186 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2187 Ok(instr.to_le_bytes().to_vec())
2188 }
2189 } else {
2190 let instr: u16 = 0xBF00;
2191 Ok(instr.to_le_bytes().to_vec())
2192 }
2193 }
2194
2195 ArmOp::Cmn { rn, op2 } => {
2198 let rn_bits = reg_to_bits(rn) as u16;
2199
2200 if let Operand2::Imm(imm) = op2 {
2201 if *imm >= 0 && *imm <= 255 {
2204 let imm8 = *imm as u16 & 0xFF;
2205 let hw1: u16 = 0xF110 | rn_bits;
2206 let hw2: u16 = 0x0F00 | imm8;
2207 let mut bytes = hw1.to_le_bytes().to_vec();
2208 bytes.extend_from_slice(&hw2.to_le_bytes());
2209 Ok(bytes)
2210 } else {
2211 Ok(vec![0xBF, 0x00])
2213 }
2214 } else if let Operand2::Reg(rm) = op2 {
2215 let rm_bits = reg_to_bits(rm) as u16;
2216 if rn_bits < 8 && rm_bits < 8 {
2222 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2224 Ok(instr.to_le_bytes().to_vec())
2225 } else {
2226 let hw1: u16 = 0xEB10 | rn_bits;
2227 let hw2: u16 = 0x0F00 | rm_bits;
2228 let mut bytes = hw1.to_le_bytes().to_vec();
2229 bytes.extend_from_slice(&hw2.to_le_bytes());
2230 Ok(bytes)
2231 }
2232 } else {
2233 Ok(vec![0xBF, 0x00])
2234 }
2235 }
2236
2237 ArmOp::Ldr { rd, addr } => {
2239 let rd_bits = reg_to_bits(rd);
2240 let base_bits = reg_to_bits(&addr.base);
2241
2242 if let Some(offset_reg) = &addr.offset_reg {
2244 let rm_bits = reg_to_bits(offset_reg);
2245
2246 if addr.offset != 0 {
2248 let scratch = Reg::R12;
2251 let mut bytes =
2252 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2253 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2254 return Ok(bytes);
2255 }
2256
2257 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2260 let instr: u16 = 0x5800
2262 | ((rm_bits as u16) << 6)
2263 | ((base_bits as u16) << 3)
2264 | (rd_bits as u16);
2265 return Ok(instr.to_le_bytes().to_vec());
2266 }
2267
2268 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2270 }
2271
2272 let offset = addr.offset as u32;
2274
2275 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2276 let imm5 = (offset >> 2) as u16;
2278 let instr: u16 =
2279 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2280 Ok(instr.to_le_bytes().to_vec())
2281 } else {
2282 self.encode_thumb32_ldr(rd, &addr.base, offset)
2283 }
2284 }
2285
2286 ArmOp::Str { rd, addr } => {
2288 let rd_bits = reg_to_bits(rd);
2289 let base_bits = reg_to_bits(&addr.base);
2290
2291 if let Some(offset_reg) = &addr.offset_reg {
2293 let rm_bits = reg_to_bits(offset_reg);
2294
2295 if addr.offset != 0 {
2297 let scratch = Reg::R12;
2300 let mut bytes =
2301 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2302 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2303 return Ok(bytes);
2304 }
2305
2306 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2309 let instr: u16 = 0x5000
2311 | ((rm_bits as u16) << 6)
2312 | ((base_bits as u16) << 3)
2313 | (rd_bits as u16);
2314 return Ok(instr.to_le_bytes().to_vec());
2315 }
2316
2317 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2319 }
2320
2321 let offset = addr.offset as u32;
2323
2324 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2325 let imm5 = (offset >> 2) as u16;
2327 let instr: u16 =
2328 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2329 Ok(instr.to_le_bytes().to_vec())
2330 } else {
2331 self.encode_thumb32_str(rd, &addr.base, offset)
2332 }
2333 }
2334
2335 ArmOp::Ldrb { rd, addr } => {
2337 let rd_bits = reg_to_bits(rd);
2338 let base_bits = reg_to_bits(&addr.base);
2339
2340 if let Some(offset_reg) = &addr.offset_reg {
2341 if addr.offset != 0 {
2342 let scratch = Reg::R12;
2343 let mut bytes =
2344 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2345 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2346 return Ok(bytes);
2347 }
2348 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2349 }
2350
2351 let offset = addr.offset as u32;
2352 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2353 let instr: u16 = 0x7800
2355 | ((offset as u16) << 6)
2356 | ((base_bits as u16) << 3)
2357 | (rd_bits as u16);
2358 Ok(instr.to_le_bytes().to_vec())
2359 } else {
2360 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2361 }
2362 }
2363
2364 ArmOp::Ldrsb { rd, addr } => {
2366 let rd_bits = reg_to_bits(rd);
2367 let base_bits = reg_to_bits(&addr.base);
2368
2369 if let Some(offset_reg) = &addr.offset_reg {
2370 if addr.offset != 0 {
2371 let scratch = Reg::R12;
2372 let mut bytes =
2373 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2374 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2375 return Ok(bytes);
2376 }
2377 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2378 }
2379
2380 let offset = addr.offset as u32;
2381 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2384 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2386 } else {
2387 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2388 }
2389 }
2390
2391 ArmOp::Ldrh { rd, addr } => {
2393 let rd_bits = reg_to_bits(rd);
2394 let base_bits = reg_to_bits(&addr.base);
2395
2396 if let Some(offset_reg) = &addr.offset_reg {
2397 if addr.offset != 0 {
2398 let scratch = Reg::R12;
2399 let mut bytes =
2400 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2401 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2402 return Ok(bytes);
2403 }
2404 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2405 }
2406
2407 let offset = addr.offset as u32;
2408 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2409 let imm5 = (offset >> 1) as u16;
2411 let instr: u16 =
2412 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2413 Ok(instr.to_le_bytes().to_vec())
2414 } else {
2415 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2416 }
2417 }
2418
2419 ArmOp::Ldrsh { rd, addr } => {
2421 if let Some(offset_reg) = &addr.offset_reg {
2422 if addr.offset != 0 {
2423 let scratch = Reg::R12;
2424 let mut bytes =
2425 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2426 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2427 return Ok(bytes);
2428 }
2429 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2430 }
2431
2432 let offset = addr.offset as u32;
2433 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2434 }
2435
2436 ArmOp::Strb { rd, addr } => {
2438 let rd_bits = reg_to_bits(rd);
2439 let base_bits = reg_to_bits(&addr.base);
2440
2441 if let Some(offset_reg) = &addr.offset_reg {
2442 if addr.offset != 0 {
2443 let scratch = Reg::R12;
2444 let mut bytes =
2445 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2446 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2447 return Ok(bytes);
2448 }
2449 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2450 }
2451
2452 let offset = addr.offset as u32;
2453 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2454 let instr: u16 = 0x7000
2456 | ((offset as u16) << 6)
2457 | ((base_bits as u16) << 3)
2458 | (rd_bits as u16);
2459 Ok(instr.to_le_bytes().to_vec())
2460 } else {
2461 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2462 }
2463 }
2464
2465 ArmOp::Strh { rd, addr } => {
2467 let rd_bits = reg_to_bits(rd);
2468 let base_bits = reg_to_bits(&addr.base);
2469
2470 if let Some(offset_reg) = &addr.offset_reg {
2471 if addr.offset != 0 {
2472 let scratch = Reg::R12;
2473 let mut bytes =
2474 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2475 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2476 return Ok(bytes);
2477 }
2478 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2479 }
2480
2481 let offset = addr.offset as u32;
2482 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2483 let imm5 = (offset >> 1) as u16;
2485 let instr: u16 =
2486 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2487 Ok(instr.to_le_bytes().to_vec())
2488 } else {
2489 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2490 }
2491 }
2492
2493 ArmOp::MemorySize { rd } => {
2495 let rd_bits = reg_to_bits(rd);
2498 let r10_bits = reg_to_bits(&Reg::R10);
2499 if rd_bits < 8 && r10_bits < 8 {
2500 let instr: u16 =
2501 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2502 Ok(instr.to_le_bytes().to_vec())
2503 } else {
2504 let imm5: u32 = 16;
2506 let imm3 = (imm5 >> 2) & 0x7;
2507 let imm2 = imm5 & 0x3;
2508 let hw1: u16 = 0xEA4F;
2509 let hw2: u16 =
2510 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2511 let mut bytes = hw1.to_le_bytes().to_vec();
2512 bytes.extend_from_slice(&hw2.to_le_bytes());
2513 Ok(bytes)
2514 }
2515 }
2516
2517 ArmOp::MemoryGrow { rd, .. } => {
2519 let rd_bits = reg_to_bits(rd);
2523 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2526 bytes.extend_from_slice(&hw2.to_le_bytes());
2527 Ok(bytes)
2528 }
2529
2530 ArmOp::Bx { rm } => {
2532 let rm_bits = reg_to_bits(rm) as u16;
2533 let instr: u16 = 0x4700 | (rm_bits << 3);
2535 Ok(instr.to_le_bytes().to_vec())
2536 }
2537
2538 ArmOp::Blx { rm } => {
2541 let rm_bits = reg_to_bits(rm) as u16;
2542 let instr: u16 = 0x4780 | (rm_bits << 3);
2543 Ok(instr.to_le_bytes().to_vec())
2544 }
2545
2546 ArmOp::CallIndirect {
2550 rd: _,
2551 type_idx: _,
2552 table_index_reg,
2553 } => {
2554 let idx_reg = reg_to_bits(table_index_reg);
2555 let mut bytes = Vec::new();
2556
2557 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2573 bytes.extend_from_slice(&hw1.to_le_bytes());
2574 bytes.extend_from_slice(&hw2.to_le_bytes());
2575
2576 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2582 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2583
2584 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2588
2589 Ok(bytes)
2590 }
2591
2592 ArmOp::Label { .. } => Ok(Vec::new()),
2594
2595 ArmOp::Bcc { cond, label: _ } => {
2597 use synth_synthesis::Condition;
2598 let cond_bits: u16 = match cond {
2599 Condition::EQ => 0x0,
2600 Condition::NE => 0x1,
2601 Condition::HS => 0x2,
2602 Condition::LO => 0x3,
2603 Condition::HI => 0x8,
2604 Condition::LS => 0x9,
2605 Condition::GE => 0xA,
2606 Condition::LT => 0xB,
2607 Condition::GT => 0xC,
2608 Condition::LE => 0xD,
2609 };
2610 let instr: u16 = 0xD000 | (cond_bits << 8);
2612 Ok(instr.to_le_bytes().to_vec())
2613 }
2614
2615 ArmOp::B { label: _ } => {
2617 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2621 }
2622
2623 ArmOp::Bhs { label: _ } => {
2626 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2630 }
2631
2632 ArmOp::Blo { label: _ } => {
2635 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2639 }
2640
2641 ArmOp::BOffset { offset } => {
2644 let halfword_offset = *offset;
2647
2648 if (-1024..=1022).contains(&halfword_offset) {
2651 let imm11 = (halfword_offset as u16) & 0x7FF;
2653 let instr: u16 = 0xE000 | imm11;
2654 Ok(instr.to_le_bytes().to_vec())
2655 } else {
2656 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2672 let uoffset = signed_offset as u32;
2673 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;
2681 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2682
2683 let mut bytes = hw1.to_le_bytes().to_vec();
2684 bytes.extend_from_slice(&hw2.to_le_bytes());
2685 Ok(bytes)
2686 }
2687 }
2688
2689 ArmOp::BCondOffset { cond, offset } => {
2691 use synth_synthesis::Condition;
2692 let cond_bits: u16 = match cond {
2693 Condition::EQ => 0x0,
2694 Condition::NE => 0x1,
2695 Condition::HS => 0x2,
2696 Condition::LO => 0x3,
2697 Condition::HI => 0x8,
2698 Condition::LS => 0x9,
2699 Condition::GE => 0xA,
2700 Condition::LT => 0xB,
2701 Condition::GT => 0xC,
2702 Condition::LE => 0xD,
2703 };
2704
2705 let halfword_offset = *offset;
2708
2709 if (-128..=127).contains(&halfword_offset) {
2712 let imm8 = (halfword_offset as u16) & 0xFF;
2713 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2714 Ok(instr.to_le_bytes().to_vec())
2715 } else {
2716 let offset = halfword_offset >> 1;
2720 let s = if offset < 0 { 1u32 } else { 0u32 };
2721 let imm6 = ((offset >> 11) as u32) & 0x3F;
2722 let imm11 = (offset as u32) & 0x7FF;
2723 let j1 = if s == 1 { 1 } else { 0 };
2724 let j2 = if s == 1 { 1 } else { 0 };
2725
2726 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2727 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2728
2729 let mut bytes = hw1.to_le_bytes().to_vec();
2730 bytes.extend_from_slice(&hw2.to_le_bytes());
2731 Ok(bytes)
2732 }
2733 }
2734
2735 ArmOp::Bl { label: _ } => {
2736 let hw1: u16 = 0xF7FF;
2751 let hw2: u16 = 0xFFFE;
2752 let mut bytes = hw1.to_le_bytes().to_vec();
2753 bytes.extend_from_slice(&hw2.to_le_bytes());
2754 Ok(bytes)
2755 }
2756
2757 ArmOp::Mvn { rd, op2 } => {
2759 if let Operand2::Reg(rm) = op2 {
2760 let rd_bits = reg_to_bits(rd) as u16;
2761 let rm_bits = reg_to_bits(rm) as u16;
2762
2763 if rd_bits < 8 && rm_bits < 8 {
2764 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2766 Ok(instr.to_le_bytes().to_vec())
2767 } else {
2768 let hw1: u16 = 0xEA6F_u16;
2770 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2771 let mut bytes = hw1.to_le_bytes().to_vec();
2772 bytes.extend_from_slice(&hw2.to_le_bytes());
2773 Ok(bytes)
2774 }
2775 } else {
2776 let instr: u16 = 0xBF00;
2777 Ok(instr.to_le_bytes().to_vec())
2778 }
2779 }
2780
2781 ArmOp::Movw { rd, imm16 } => {
2783 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2784 }
2785
2786 ArmOp::Movt { rd, imm16 } => {
2788 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2789 }
2790
2791 ArmOp::MovwSym { rd, addend, .. } => {
2796 self.encode_thumb32_movw_raw(reg_to_bits(rd), (*addend as u32) & 0xffff)
2797 }
2798 ArmOp::MovtSym { rd, addend, .. } => {
2799 self.encode_thumb32_movt_raw(reg_to_bits(rd), ((*addend as u32) >> 16) & 0xffff)
2800 }
2801
2802 ArmOp::SetCond { rd, cond } => {
2808 let rd_bits = reg_to_bits(rd) as u16;
2809
2810 use synth_synthesis::Condition;
2812 let cond_bits: u16 = match cond {
2813 Condition::EQ => 0x0,
2814 Condition::NE => 0x1,
2815 Condition::LT => 0xB,
2816 Condition::LE => 0xD,
2817 Condition::GT => 0xC,
2818 Condition::GE => 0xA,
2819 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2824
2825 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2830 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2831
2832 let mut bytes = ite_instr.to_le_bytes().to_vec();
2843 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2844 if rd_bits <= 7 {
2845 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2847 } else {
2848 let hw1: u16 = 0xF04F;
2850 let hw2: u16 = (rd_bits << 8) | imm;
2851 bytes.extend_from_slice(&hw1.to_le_bytes());
2852 bytes.extend_from_slice(&hw2.to_le_bytes());
2853 }
2854 };
2855 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2858 }
2859
2860 ArmOp::I64SetCond {
2865 rd,
2866 rn_lo,
2867 rn_hi,
2868 rm_lo,
2869 rm_hi,
2870 cond,
2871 } => {
2872 use synth_synthesis::Condition;
2873 let rd_bits = reg_to_bits(rd) as u16;
2874 let mut bytes = Vec::new();
2875
2876 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2878 rm: &synth_synthesis::Reg|
2879 -> Vec<u8> {
2880 let rn_bits = reg_to_bits(rn) as u16;
2881 let rm_bits = reg_to_bits(rm) as u16;
2882 if rn_bits < 8 && rm_bits < 8 {
2883 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2884 instr.to_le_bytes().to_vec()
2885 } else {
2886 let n_bit = (rn_bits >> 3) & 1;
2887 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2888 instr.to_le_bytes().to_vec()
2889 }
2890 };
2891
2892 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2894 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2895 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2896 ite_instr.to_le_bytes().to_vec()
2897 };
2898
2899 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2901 let mut b = encode_ite(cond_bits);
2902 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2903 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2904 b.extend_from_slice(&mov_one.to_le_bytes());
2905 b.extend_from_slice(&mov_zero.to_le_bytes());
2906 b
2907 };
2908
2909 match cond {
2910 Condition::EQ | Condition::NE => {
2911 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2913
2914 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2917
2918 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2920
2921 let cond_bits: u16 = match cond {
2923 Condition::EQ => 0x0,
2924 Condition::NE => 0x1,
2925 _ => unreachable!(),
2926 };
2927 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2928 }
2929
2930 Condition::LT => {
2931 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2933
2934 let rn_hi_bits = reg_to_bits(rn_hi);
2937 let rm_hi_bits = reg_to_bits(rm_hi);
2938 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2939 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2940 bytes.extend_from_slice(&hw1.to_le_bytes());
2941 bytes.extend_from_slice(&hw2.to_le_bytes());
2942
2943 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2946
2947 Condition::GT => {
2948 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2951
2952 let rm_hi_bits = reg_to_bits(rm_hi);
2954 let rn_hi_bits = reg_to_bits(rn_hi);
2955 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2956 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2957 bytes.extend_from_slice(&hw1.to_le_bytes());
2958 bytes.extend_from_slice(&hw2.to_le_bytes());
2959
2960 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2963
2964 Condition::LE => {
2965 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2969
2970 let rm_hi_bits = reg_to_bits(rm_hi);
2972 let rn_hi_bits = reg_to_bits(rn_hi);
2973 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2974 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2975 bytes.extend_from_slice(&hw1.to_le_bytes());
2976 bytes.extend_from_slice(&hw2.to_le_bytes());
2977
2978 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2981
2982 Condition::GE => {
2983 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2986
2987 let rn_hi_bits = reg_to_bits(rn_hi);
2989 let rm_hi_bits = reg_to_bits(rm_hi);
2990 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2991 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2992 bytes.extend_from_slice(&hw1.to_le_bytes());
2993 bytes.extend_from_slice(&hw2.to_le_bytes());
2994
2995 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2998
2999 Condition::LO => {
3001 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3003 let rn_hi_bits = reg_to_bits(rn_hi);
3004 let rm_hi_bits = reg_to_bits(rm_hi);
3005 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3006 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3007 bytes.extend_from_slice(&hw1.to_le_bytes());
3008 bytes.extend_from_slice(&hw2.to_le_bytes());
3009 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3011
3012 Condition::HI => {
3013 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3015 let rm_hi_bits = reg_to_bits(rm_hi);
3016 let rn_hi_bits = reg_to_bits(rn_hi);
3017 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3018 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3019 bytes.extend_from_slice(&hw1.to_le_bytes());
3020 bytes.extend_from_slice(&hw2.to_le_bytes());
3021 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
3023
3024 Condition::LS => {
3025 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
3027 let rm_hi_bits = reg_to_bits(rm_hi);
3028 let rn_hi_bits = reg_to_bits(rn_hi);
3029 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
3030 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
3031 bytes.extend_from_slice(&hw1.to_le_bytes());
3032 bytes.extend_from_slice(&hw2.to_le_bytes());
3033 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3035
3036 Condition::HS => {
3037 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
3039 let rn_hi_bits = reg_to_bits(rn_hi);
3040 let rm_hi_bits = reg_to_bits(rm_hi);
3041 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
3042 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
3043 bytes.extend_from_slice(&hw1.to_le_bytes());
3044 bytes.extend_from_slice(&hw2.to_le_bytes());
3045 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
3047 }
3048
3049 Ok(bytes)
3050 }
3051
3052 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
3055 let rd_bits = reg_to_bits(rd);
3056 let rn_lo_bits = reg_to_bits(rn_lo);
3057 let rn_hi_bits = reg_to_bits(rn_hi);
3058 let mut bytes = Vec::new();
3059
3060 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3062 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3063 bytes.extend_from_slice(&hw1.to_le_bytes());
3064 bytes.extend_from_slice(&hw2.to_le_bytes());
3065
3066 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3068 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3069
3070 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3073 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3074 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3075 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3076 bytes.extend_from_slice(&mov_one.to_le_bytes());
3077 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3078
3079 Ok(bytes)
3080 }
3081
3082 ArmOp::I64Mul {
3086 rd_lo,
3087 rd_hi,
3088 rn_lo,
3089 rn_hi,
3090 rm_lo,
3091 rm_hi,
3092 } => {
3093 let rd_lo_bits = reg_to_bits(rd_lo);
3094 let rd_hi_bits = reg_to_bits(rd_hi);
3095 let rn_lo_bits = reg_to_bits(rn_lo);
3096 let rn_hi_bits = reg_to_bits(rn_hi);
3097 let rm_lo_bits = reg_to_bits(rm_lo);
3098 let rm_hi_bits = reg_to_bits(rm_hi);
3099 let r12: u32 = 12; let mut bytes = Vec::new();
3101
3102 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3105 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3106 bytes.extend_from_slice(&hw1.to_le_bytes());
3107 bytes.extend_from_slice(&hw2.to_le_bytes());
3108
3109 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3112 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3113 bytes.extend_from_slice(&hw1.to_le_bytes());
3114 bytes.extend_from_slice(&hw2.to_le_bytes());
3115
3116 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3119 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3120 bytes.extend_from_slice(&hw1.to_le_bytes());
3121 bytes.extend_from_slice(&hw2.to_le_bytes());
3122
3123 let d_bit = (rd_hi_bits >> 3) & 1;
3126 let add_instr: u16 =
3127 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3128 bytes.extend_from_slice(&add_instr.to_le_bytes());
3129
3130 Ok(bytes)
3131 }
3132
3133 ArmOp::I64Shl {
3136 rd_lo,
3137 rd_hi,
3138 rn_lo,
3139 rn_hi,
3140 rm_lo,
3141 rm_hi,
3142 } => {
3143 let rd_lo_bits = reg_to_bits(rd_lo);
3144 let rd_hi_bits = reg_to_bits(rd_hi);
3145 let rn_lo_bits = reg_to_bits(rn_lo);
3146 let rn_hi_bits = reg_to_bits(rn_hi);
3147 let rm_lo_bits = reg_to_bits(rm_lo);
3148 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3150
3151 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3153 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3154 bytes.extend_from_slice(&hw1.to_le_bytes());
3155 bytes.extend_from_slice(&hw2.to_le_bytes());
3156
3157 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3159 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3160 bytes.extend_from_slice(&hw1.to_le_bytes());
3161 bytes.extend_from_slice(&hw2.to_le_bytes());
3162
3163 let bpl: u16 = 0xD50A;
3165 bytes.extend_from_slice(&bpl.to_le_bytes());
3166
3167 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3170 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3171 bytes.extend_from_slice(&hw1.to_le_bytes());
3172 bytes.extend_from_slice(&hw2.to_le_bytes());
3173
3174 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3176 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3177 bytes.extend_from_slice(&hw1.to_le_bytes());
3178 bytes.extend_from_slice(&hw2.to_le_bytes());
3179
3180 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3182 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3183 bytes.extend_from_slice(&hw1.to_le_bytes());
3184 bytes.extend_from_slice(&hw2.to_le_bytes());
3185
3186 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3188 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3189 bytes.extend_from_slice(&hw1.to_le_bytes());
3190 bytes.extend_from_slice(&hw2.to_le_bytes());
3191
3192 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3194 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3195 bytes.extend_from_slice(&hw1.to_le_bytes());
3196 bytes.extend_from_slice(&hw2.to_le_bytes());
3197
3198 let b_done: u16 = 0xE002;
3200 bytes.extend_from_slice(&b_done.to_le_bytes());
3201
3202 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3205 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3206 bytes.extend_from_slice(&hw1.to_le_bytes());
3207 bytes.extend_from_slice(&hw2.to_le_bytes());
3208
3209 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3211 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3212
3213 Ok(bytes) }
3215
3216 ArmOp::I64ShrU {
3218 rd_lo,
3219 rd_hi,
3220 rn_lo,
3221 rn_hi,
3222 rm_lo,
3223 rm_hi,
3224 } => {
3225 let rd_lo_bits = reg_to_bits(rd_lo);
3226 let rd_hi_bits = reg_to_bits(rd_hi);
3227 let rn_lo_bits = reg_to_bits(rn_lo);
3228 let rn_hi_bits = reg_to_bits(rn_hi);
3229 let rm_lo_bits = reg_to_bits(rm_lo);
3230 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3232
3233 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3235 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3236 bytes.extend_from_slice(&hw1.to_le_bytes());
3237 bytes.extend_from_slice(&hw2.to_le_bytes());
3238
3239 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3241 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3242 bytes.extend_from_slice(&hw1.to_le_bytes());
3243 bytes.extend_from_slice(&hw2.to_le_bytes());
3244
3245 let bpl: u16 = 0xD50A;
3247 bytes.extend_from_slice(&bpl.to_le_bytes());
3248
3249 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3252 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3253 bytes.extend_from_slice(&hw1.to_le_bytes());
3254 bytes.extend_from_slice(&hw2.to_le_bytes());
3255
3256 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3258 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3259 bytes.extend_from_slice(&hw1.to_le_bytes());
3260 bytes.extend_from_slice(&hw2.to_le_bytes());
3261
3262 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3264 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3265 bytes.extend_from_slice(&hw1.to_le_bytes());
3266 bytes.extend_from_slice(&hw2.to_le_bytes());
3267
3268 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3270 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3271 bytes.extend_from_slice(&hw1.to_le_bytes());
3272 bytes.extend_from_slice(&hw2.to_le_bytes());
3273
3274 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3276 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3277 bytes.extend_from_slice(&hw1.to_le_bytes());
3278 bytes.extend_from_slice(&hw2.to_le_bytes());
3279
3280 let b_done: u16 = 0xE002;
3282 bytes.extend_from_slice(&b_done.to_le_bytes());
3283
3284 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3287 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3288 bytes.extend_from_slice(&hw1.to_le_bytes());
3289 bytes.extend_from_slice(&hw2.to_le_bytes());
3290
3291 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3293 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3294
3295 Ok(bytes) }
3297
3298 ArmOp::I64ShrS {
3300 rd_lo,
3301 rd_hi,
3302 rn_lo,
3303 rn_hi,
3304 rm_lo,
3305 rm_hi,
3306 } => {
3307 let rd_lo_bits = reg_to_bits(rd_lo);
3308 let rd_hi_bits = reg_to_bits(rd_hi);
3309 let rn_lo_bits = reg_to_bits(rn_lo);
3310 let rn_hi_bits = reg_to_bits(rn_hi);
3311 let rm_lo_bits = reg_to_bits(rm_lo);
3312 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3314
3315 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3317 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3318 bytes.extend_from_slice(&hw1.to_le_bytes());
3319 bytes.extend_from_slice(&hw2.to_le_bytes());
3320
3321 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3323 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3324 bytes.extend_from_slice(&hw1.to_le_bytes());
3325 bytes.extend_from_slice(&hw2.to_le_bytes());
3326
3327 let bpl: u16 = 0xD50A;
3329 bytes.extend_from_slice(&bpl.to_le_bytes());
3330
3331 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3334 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3335 bytes.extend_from_slice(&hw1.to_le_bytes());
3336 bytes.extend_from_slice(&hw2.to_le_bytes());
3337
3338 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3340 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3341 bytes.extend_from_slice(&hw1.to_le_bytes());
3342 bytes.extend_from_slice(&hw2.to_le_bytes());
3343
3344 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3346 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3347 bytes.extend_from_slice(&hw1.to_le_bytes());
3348 bytes.extend_from_slice(&hw2.to_le_bytes());
3349
3350 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3352 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3353 bytes.extend_from_slice(&hw1.to_le_bytes());
3354 bytes.extend_from_slice(&hw2.to_le_bytes());
3355
3356 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3358 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3359 bytes.extend_from_slice(&hw1.to_le_bytes());
3360 bytes.extend_from_slice(&hw2.to_le_bytes());
3361
3362 let b_done: u16 = 0xE003;
3364 bytes.extend_from_slice(&b_done.to_le_bytes());
3365
3366 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3369 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3370 bytes.extend_from_slice(&hw1.to_le_bytes());
3371 bytes.extend_from_slice(&hw2.to_le_bytes());
3372
3373 let hw1: u16 = 0xEA4F;
3377 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3378 bytes.extend_from_slice(&hw1.to_le_bytes());
3379 bytes.extend_from_slice(&hw2.to_le_bytes());
3380
3381 Ok(bytes) }
3383
3384 ArmOp::I64Rotl {
3389 rdlo,
3390 rdhi,
3391 rnlo,
3392 rnhi,
3393 shift,
3394 } => {
3395 let rd_lo_bits = reg_to_bits(rdlo);
3396 let rd_hi_bits = reg_to_bits(rdhi);
3397 let rn_lo_bits = reg_to_bits(rnlo);
3398 let rn_hi_bits = reg_to_bits(rnhi);
3399 let shift_bits = reg_to_bits(shift);
3400 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3404
3405 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3407
3408 let hw1: u16 = (0xF000 | shift_bits) as u16;
3410 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3411 bytes.extend_from_slice(&hw1.to_le_bytes());
3412 bytes.extend_from_slice(&hw2.to_le_bytes());
3413
3414 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3416 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3417 bytes.extend_from_slice(&hw1.to_le_bytes());
3418 bytes.extend_from_slice(&hw2.to_le_bytes());
3419
3420 let bpl: u16 = 0xD50E;
3422 bytes.extend_from_slice(&bpl.to_le_bytes());
3423
3424 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3427 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3428 bytes.extend_from_slice(&hw1.to_le_bytes());
3429 bytes.extend_from_slice(&hw2.to_le_bytes());
3430
3431 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3433 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3434 bytes.extend_from_slice(&hw1.to_le_bytes());
3435 bytes.extend_from_slice(&hw2.to_le_bytes());
3436
3437 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3439 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3440 bytes.extend_from_slice(&hw1.to_le_bytes());
3441 bytes.extend_from_slice(&hw2.to_le_bytes());
3442
3443 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3445 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3446 bytes.extend_from_slice(&hw1.to_le_bytes());
3447 bytes.extend_from_slice(&hw2.to_le_bytes());
3448
3449 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3451 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3452 bytes.extend_from_slice(&hw1.to_le_bytes());
3453 bytes.extend_from_slice(&hw2.to_le_bytes());
3454
3455 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3457 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3458 bytes.extend_from_slice(&hw1.to_le_bytes());
3459 bytes.extend_from_slice(&hw2.to_le_bytes());
3460
3461 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3463 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3464 bytes.extend_from_slice(&hw1.to_le_bytes());
3465 bytes.extend_from_slice(&hw2.to_le_bytes());
3466
3467 let b_done: u16 = 0xE00E;
3469 bytes.extend_from_slice(&b_done.to_le_bytes());
3470
3471 let hw1: u16 = (0xF1C0 | r3) as u16;
3475 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3476 bytes.extend_from_slice(&hw1.to_le_bytes());
3477 bytes.extend_from_slice(&hw2.to_le_bytes());
3478
3479 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3481 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3482 bytes.extend_from_slice(&hw1.to_le_bytes());
3483 bytes.extend_from_slice(&hw2.to_le_bytes());
3484
3485 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3487 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3488 bytes.extend_from_slice(&hw1.to_le_bytes());
3489 bytes.extend_from_slice(&hw2.to_le_bytes());
3490
3491 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3493 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3494 bytes.extend_from_slice(&hw1.to_le_bytes());
3495 bytes.extend_from_slice(&hw2.to_le_bytes());
3496
3497 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3499 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3500 bytes.extend_from_slice(&hw1.to_le_bytes());
3501 bytes.extend_from_slice(&hw2.to_le_bytes());
3502
3503 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3505 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3506 bytes.extend_from_slice(&hw1.to_le_bytes());
3507 bytes.extend_from_slice(&hw2.to_le_bytes());
3508
3509 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3511 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3512 bytes.extend_from_slice(&hw1.to_le_bytes());
3513 bytes.extend_from_slice(&hw2.to_le_bytes());
3514
3515 let d_bit = (rd_hi_bits >> 3) & 1;
3517 let mov_instr: u16 =
3518 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3519 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3520
3521 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3523
3524 Ok(bytes) }
3526
3527 ArmOp::I64Rotr {
3532 rdlo,
3533 rdhi,
3534 rnlo,
3535 rnhi,
3536 shift,
3537 } => {
3538 let rd_lo_bits = reg_to_bits(rdlo);
3539 let rd_hi_bits = reg_to_bits(rdhi);
3540 let rn_lo_bits = reg_to_bits(rnlo);
3541 let rn_hi_bits = reg_to_bits(rnhi);
3542 let shift_bits = reg_to_bits(shift);
3543 let r12: u32 = 12;
3544 let r3: u32 = 3;
3545 let r4: u32 = 4;
3546 let mut bytes = Vec::new();
3547
3548 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3550
3551 let hw1: u16 = (0xF000 | shift_bits) as u16;
3553 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3554 bytes.extend_from_slice(&hw1.to_le_bytes());
3555 bytes.extend_from_slice(&hw2.to_le_bytes());
3556
3557 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3559 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3560 bytes.extend_from_slice(&hw1.to_le_bytes());
3561 bytes.extend_from_slice(&hw2.to_le_bytes());
3562
3563 let bpl: u16 = 0xD50E;
3565 bytes.extend_from_slice(&bpl.to_le_bytes());
3566
3567 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3570 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3571 bytes.extend_from_slice(&hw1.to_le_bytes());
3572 bytes.extend_from_slice(&hw2.to_le_bytes());
3573
3574 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3576 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3577 bytes.extend_from_slice(&hw1.to_le_bytes());
3578 bytes.extend_from_slice(&hw2.to_le_bytes());
3579
3580 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3582 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3583 bytes.extend_from_slice(&hw1.to_le_bytes());
3584 bytes.extend_from_slice(&hw2.to_le_bytes());
3585
3586 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3588 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3589 bytes.extend_from_slice(&hw1.to_le_bytes());
3590 bytes.extend_from_slice(&hw2.to_le_bytes());
3591
3592 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3594 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3595 bytes.extend_from_slice(&hw1.to_le_bytes());
3596 bytes.extend_from_slice(&hw2.to_le_bytes());
3597
3598 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3600 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3601 bytes.extend_from_slice(&hw1.to_le_bytes());
3602 bytes.extend_from_slice(&hw2.to_le_bytes());
3603
3604 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3606 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3607 bytes.extend_from_slice(&hw1.to_le_bytes());
3608 bytes.extend_from_slice(&hw2.to_le_bytes());
3609
3610 let b_done: u16 = 0xE00E;
3612 bytes.extend_from_slice(&b_done.to_le_bytes());
3613
3614 let hw1: u16 = (0xF1C0 | r3) as u16;
3617 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3618 bytes.extend_from_slice(&hw1.to_le_bytes());
3619 bytes.extend_from_slice(&hw2.to_le_bytes());
3620
3621 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3623 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3624 bytes.extend_from_slice(&hw1.to_le_bytes());
3625 bytes.extend_from_slice(&hw2.to_le_bytes());
3626
3627 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3629 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3630 bytes.extend_from_slice(&hw1.to_le_bytes());
3631 bytes.extend_from_slice(&hw2.to_le_bytes());
3632
3633 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3635 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3636 bytes.extend_from_slice(&hw1.to_le_bytes());
3637 bytes.extend_from_slice(&hw2.to_le_bytes());
3638
3639 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3641 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3642 bytes.extend_from_slice(&hw1.to_le_bytes());
3643 bytes.extend_from_slice(&hw2.to_le_bytes());
3644
3645 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3647 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3648 bytes.extend_from_slice(&hw1.to_le_bytes());
3649 bytes.extend_from_slice(&hw2.to_le_bytes());
3650
3651 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3653 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3654 bytes.extend_from_slice(&hw1.to_le_bytes());
3655 bytes.extend_from_slice(&hw2.to_le_bytes());
3656
3657 let d_bit = (rd_lo_bits >> 3) & 1;
3659 let mov_instr: u16 =
3660 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3661 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3662
3663 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3665
3666 Ok(bytes) }
3668
3669 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3683 let rd_bits = reg_to_bits(rd);
3684 let rn_lo_bits = reg_to_bits(rnlo);
3685 let rn_hi_bits = reg_to_bits(rnhi);
3686 let mut bytes = Vec::new();
3687
3688 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3690 let hw2: u16 = 0x0F00;
3691 bytes.extend_from_slice(&hw1.to_le_bytes());
3692 bytes.extend_from_slice(&hw2.to_le_bytes());
3693
3694 let beq: u16 = 0xD003;
3697 bytes.extend_from_slice(&beq.to_le_bytes());
3698
3699 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3702 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3703 bytes.extend_from_slice(&hw1.to_le_bytes());
3704 bytes.extend_from_slice(&hw2.to_le_bytes());
3705
3706 let b_done: u16 = 0xE004;
3709 bytes.extend_from_slice(&b_done.to_le_bytes());
3710
3711 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3713
3714 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3718 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3719 bytes.extend_from_slice(&hw1.to_le_bytes());
3720 bytes.extend_from_slice(&hw2.to_le_bytes());
3721
3722 let hw1: u16 = (0xF100 | rd_bits) as u16;
3724 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3725 bytes.extend_from_slice(&hw1.to_le_bytes());
3726 bytes.extend_from_slice(&hw2.to_le_bytes());
3727
3728 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3732 bytes.extend_from_slice(&mov0.to_le_bytes());
3733
3734 Ok(bytes)
3735 }
3736
3737 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3753 let rd_bits = reg_to_bits(rd);
3754 let rn_lo_bits = reg_to_bits(rnlo);
3755 let rn_hi_bits = reg_to_bits(rnhi);
3756 let mut bytes = Vec::new();
3757
3758 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3760 let hw2: u16 = 0x0F00;
3761 bytes.extend_from_slice(&hw1.to_le_bytes());
3762 bytes.extend_from_slice(&hw2.to_le_bytes());
3763
3764 let beq: u16 = 0xD005;
3767 bytes.extend_from_slice(&beq.to_le_bytes());
3768
3769 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3772 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3773 bytes.extend_from_slice(&hw1.to_le_bytes());
3774 bytes.extend_from_slice(&hw2.to_le_bytes());
3775
3776 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3779 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3780 bytes.extend_from_slice(&hw1.to_le_bytes());
3781 bytes.extend_from_slice(&hw2.to_le_bytes());
3782
3783 let b_done: u16 = 0xE006;
3786 bytes.extend_from_slice(&b_done.to_le_bytes());
3787
3788 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3790
3791 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3795 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3796 bytes.extend_from_slice(&hw1.to_le_bytes());
3797 bytes.extend_from_slice(&hw2.to_le_bytes());
3798
3799 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3802 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3803 bytes.extend_from_slice(&hw1.to_le_bytes());
3804 bytes.extend_from_slice(&hw2.to_le_bytes());
3805
3806 let hw1: u16 = (0xF100 | rd_bits) as u16;
3808 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3809 bytes.extend_from_slice(&hw1.to_le_bytes());
3810 bytes.extend_from_slice(&hw2.to_le_bytes());
3811
3812 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3815 bytes.extend_from_slice(&mov0.to_le_bytes());
3816
3817 Ok(bytes)
3818 }
3819
3820 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3824 let rd_bits = reg_to_bits(rd);
3825 let rn_lo_bits = reg_to_bits(rnlo);
3826 let rn_hi_bits = reg_to_bits(rnhi);
3827 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3830
3831 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3833
3834 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3844 bytes.extend_from_slice(&mov.to_le_bytes());
3845
3846 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3849 bytes.extend_from_slice(&mov.to_le_bytes());
3850
3851 let hw1: u16 = 0xEA4F;
3855 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3856 bytes.extend_from_slice(&hw1.to_le_bytes());
3857 bytes.extend_from_slice(&hw2.to_le_bytes());
3858
3859 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3862 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3863 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3865 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3866
3867 let hw1: u16 = (0xEA00 | r12) as u16;
3869 let hw2: u16 = ((r12 << 8) | r3) as u16;
3870 bytes.extend_from_slice(&hw1.to_le_bytes());
3871 bytes.extend_from_slice(&hw2.to_le_bytes());
3872
3873 let hw1: u16 = (0xEBA0 | 4) as u16;
3875 let hw2: u16 = ((4 << 8) | r12) as u16;
3876 bytes.extend_from_slice(&hw1.to_le_bytes());
3877 bytes.extend_from_slice(&hw2.to_le_bytes());
3878
3879 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3883 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3884 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3886 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3887
3888 let hw1: u16 = (0xEA00 | 4) as u16;
3890 let hw2: u16 = ((r12 << 8) | r3) as u16;
3891 bytes.extend_from_slice(&hw1.to_le_bytes());
3892 bytes.extend_from_slice(&hw2.to_le_bytes());
3893
3894 let hw1: u16 = 0xEA4F;
3896 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3897 bytes.extend_from_slice(&hw1.to_le_bytes());
3898 bytes.extend_from_slice(&hw2.to_le_bytes());
3899
3900 let hw1: u16 = (0xEA00 | 4) as u16;
3902 let hw2: u16 = ((4 << 8) | r3) as u16;
3903 bytes.extend_from_slice(&hw1.to_le_bytes());
3904 bytes.extend_from_slice(&hw2.to_le_bytes());
3905
3906 let hw1: u16 = (0xEB00 | 4) as u16;
3908 let hw2: u16 = ((4 << 8) | r12) as u16;
3909 bytes.extend_from_slice(&hw1.to_le_bytes());
3910 bytes.extend_from_slice(&hw2.to_le_bytes());
3911
3912 let hw1: u16 = 0xEA4F;
3917 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3918 bytes.extend_from_slice(&hw1.to_le_bytes());
3919 bytes.extend_from_slice(&hw2.to_le_bytes());
3920
3921 let hw1: u16 = (0xEB00 | 4) as u16;
3923 let hw2: u16 = ((4 << 8) | r12) as u16;
3924 bytes.extend_from_slice(&hw1.to_le_bytes());
3925 bytes.extend_from_slice(&hw2.to_le_bytes());
3926
3927 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3932 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3933 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3935 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3936
3937 let hw1: u16 = (0xEA00 | 4) as u16;
3939 let hw2: u16 = ((4 << 8) | r3) as u16;
3940 bytes.extend_from_slice(&hw1.to_le_bytes());
3941 bytes.extend_from_slice(&hw2.to_le_bytes());
3942
3943 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3947 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3948 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3950 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3951
3952 let hw1: u16 = (0xFB00 | 4) as u16;
3955 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3956 bytes.extend_from_slice(&hw1.to_le_bytes());
3957 bytes.extend_from_slice(&hw2.to_le_bytes());
3958
3959 let hw1: u16 = 0xEA4F;
3962 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3963 bytes.extend_from_slice(&hw1.to_le_bytes());
3964 bytes.extend_from_slice(&hw2.to_le_bytes());
3965
3966 let hw1: u16 = 0xEA4F;
3969 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3970 bytes.extend_from_slice(&hw1.to_le_bytes());
3971 bytes.extend_from_slice(&hw2.to_le_bytes());
3972
3973 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3975 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3976 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3977 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3978
3979 let hw1: u16 = (0xEA00 | r12) as u16;
3980 let hw2: u16 = ((r12 << 8) | r3) as u16;
3981 bytes.extend_from_slice(&hw1.to_le_bytes());
3982 bytes.extend_from_slice(&hw2.to_le_bytes());
3983
3984 let hw1: u16 = (0xEBA0 | 5) as u16;
3985 let hw2: u16 = ((5 << 8) | r12) as u16;
3986 bytes.extend_from_slice(&hw1.to_le_bytes());
3987 bytes.extend_from_slice(&hw2.to_le_bytes());
3988
3989 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3991 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3992 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3993 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3994
3995 let hw1: u16 = (0xEA00 | 5) as u16;
3996 let hw2: u16 = ((r12 << 8) | r3) as u16;
3997 bytes.extend_from_slice(&hw1.to_le_bytes());
3998 bytes.extend_from_slice(&hw2.to_le_bytes());
3999
4000 let hw1: u16 = 0xEA4F;
4001 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
4002 bytes.extend_from_slice(&hw1.to_le_bytes());
4003 bytes.extend_from_slice(&hw2.to_le_bytes());
4004
4005 let hw1: u16 = (0xEA00 | 5) as u16;
4006 let hw2: u16 = ((5 << 8) | r3) as u16;
4007 bytes.extend_from_slice(&hw1.to_le_bytes());
4008 bytes.extend_from_slice(&hw2.to_le_bytes());
4009
4010 let hw1: u16 = (0xEB00 | 5) as u16;
4011 let hw2: u16 = ((5 << 8) | r12) as u16;
4012 bytes.extend_from_slice(&hw1.to_le_bytes());
4013 bytes.extend_from_slice(&hw2.to_le_bytes());
4014
4015 let hw1: u16 = 0xEA4F;
4018 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
4019 bytes.extend_from_slice(&hw1.to_le_bytes());
4020 bytes.extend_from_slice(&hw2.to_le_bytes());
4021
4022 let hw1: u16 = (0xEB00 | 5) as u16;
4023 let hw2: u16 = ((5 << 8) | r12) as u16;
4024 bytes.extend_from_slice(&hw1.to_le_bytes());
4025 bytes.extend_from_slice(&hw2.to_le_bytes());
4026
4027 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
4029 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4030 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
4031 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
4032
4033 let hw1: u16 = (0xEA00 | 5) as u16;
4034 let hw2: u16 = ((5 << 8) | r3) as u16;
4035 bytes.extend_from_slice(&hw1.to_le_bytes());
4036 bytes.extend_from_slice(&hw2.to_le_bytes());
4037
4038 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
4040 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4041 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
4042 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
4043
4044 let hw1: u16 = (0xFB00 | 5) as u16;
4047 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
4048 bytes.extend_from_slice(&hw1.to_le_bytes());
4049 bytes.extend_from_slice(&hw2.to_le_bytes());
4050
4051 let hw1: u16 = 0xEA4F;
4054 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
4055 bytes.extend_from_slice(&hw1.to_le_bytes());
4056 bytes.extend_from_slice(&hw2.to_le_bytes());
4057
4058 let rd_bits_u16 = rd_bits as u16;
4061 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4062 bytes.extend_from_slice(&instr.to_le_bytes());
4063
4064 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4066
4067 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4069 bytes.extend_from_slice(&mov0.to_le_bytes());
4070
4071 Ok(bytes)
4072 }
4073
4074 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4077 let rdlo_bits = reg_to_bits(rdlo);
4078 let rdhi_bits = reg_to_bits(rdhi);
4079 let rnlo_bits = reg_to_bits(rnlo);
4080 let mut bytes = Vec::new();
4081
4082 let hw1: u16 = 0xFA4F_u16;
4085 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4086 bytes.extend_from_slice(&hw1.to_le_bytes());
4087 bytes.extend_from_slice(&hw2.to_le_bytes());
4088
4089 let hw1: u16 = 0xEA4F;
4094 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4095 bytes.extend_from_slice(&hw1.to_le_bytes());
4096 bytes.extend_from_slice(&hw2.to_le_bytes());
4097
4098 Ok(bytes)
4099 }
4100
4101 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4104 let rdlo_bits = reg_to_bits(rdlo);
4105 let rdhi_bits = reg_to_bits(rdhi);
4106 let rnlo_bits = reg_to_bits(rnlo);
4107 let mut bytes = Vec::new();
4108
4109 let hw1: u16 = 0xFA0F_u16;
4112 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4113 bytes.extend_from_slice(&hw1.to_le_bytes());
4114 bytes.extend_from_slice(&hw2.to_le_bytes());
4115
4116 let hw1: u16 = 0xEA4F;
4118 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4119 bytes.extend_from_slice(&hw1.to_le_bytes());
4120 bytes.extend_from_slice(&hw2.to_le_bytes());
4121
4122 Ok(bytes)
4123 }
4124
4125 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4128 let rdlo_bits = reg_to_bits(rdlo);
4129 let rdhi_bits = reg_to_bits(rdhi);
4130 let rnlo_bits = reg_to_bits(rnlo);
4131 let mut bytes = Vec::new();
4132
4133 if rdlo_bits != rnlo_bits {
4135 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4137 let mov: u16 = 0x4600
4138 | (d_bit << 7)
4139 | ((rnlo_bits as u16) << 3)
4140 | ((rdlo_bits & 0x7) as u16);
4141 bytes.extend_from_slice(&mov.to_le_bytes());
4142 }
4143
4144 let hw1: u16 = 0xEA4F;
4146 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4147 bytes.extend_from_slice(&hw1.to_le_bytes());
4148 bytes.extend_from_slice(&hw2.to_le_bytes());
4149
4150 Ok(bytes)
4151 }
4152
4153 ArmOp::SelectMove { rd, rm, cond } => {
4156 let rd_bits = reg_to_bits(rd) as u16;
4157 let rm_bits = reg_to_bits(rm) as u16;
4158
4159 use synth_synthesis::Condition;
4161 let cond_bits: u16 = match cond {
4162 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, };
4173
4174 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4177
4178 let d_bit = (rd_bits >> 3) & 1;
4181 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4182
4183 let mut bytes = it_instr.to_le_bytes().to_vec();
4185 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4186 Ok(bytes)
4187 }
4188
4189 ArmOp::Popcnt { rd, rm } => {
4200 let mut bytes = Vec::new();
4201
4202 if rd != rm {
4204 let rd_bits = reg_to_bits(rd) as u16;
4205 let rm_bits = reg_to_bits(rm) as u16;
4206 let d_bit = (rd_bits >> 3) & 1;
4208 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4209 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4210 }
4211
4212 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4215 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4216
4217 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4220
4221 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4223
4224 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4226 reg_to_bits(rd),
4227 reg_to_bits(rd),
4228 11,
4229 )?);
4230
4231 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4234 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4235
4236 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4238 11,
4239 reg_to_bits(rd),
4240 12,
4241 )?);
4242
4243 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4245 reg_to_bits(rd),
4246 reg_to_bits(rd),
4247 2,
4248 )?);
4249
4250 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4252 reg_to_bits(rd),
4253 reg_to_bits(rd),
4254 12,
4255 )?);
4256
4257 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4259 reg_to_bits(rd),
4260 reg_to_bits(rd),
4261 11,
4262 )?);
4263
4264 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4267
4268 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4270 reg_to_bits(rd),
4271 reg_to_bits(rd),
4272 11,
4273 )?);
4274
4275 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4277 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4278
4279 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4281 reg_to_bits(rd),
4282 reg_to_bits(rd),
4283 12,
4284 )?);
4285
4286 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4289
4290 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4292 reg_to_bits(rd),
4293 reg_to_bits(rd),
4294 11,
4295 )?);
4296
4297 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4300
4301 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4303 reg_to_bits(rd),
4304 reg_to_bits(rd),
4305 11,
4306 )?);
4307
4308 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4311 reg_to_bits(rd),
4312 reg_to_bits(rd),
4313 0x3F,
4314 )?);
4315
4316 Ok(bytes)
4317 }
4318
4319 ArmOp::I64DivU {
4324 rdlo: _,
4325 rdhi: _,
4326 rnlo: _,
4327 rnhi: _,
4328 rmlo: _,
4329 rmhi: _,
4330 } => {
4331 let mut bytes = Vec::new();
4332
4333 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4337
4338 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());
4349 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4350
4351 let loop_start = bytes.len();
4353
4354 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4365 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());
4374 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4375 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4379 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4380
4381 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4386 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4387 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());
4418 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4419 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4422
4423 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4427 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4428
4429 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4432 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4433 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4434
4435 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4443
4444 Ok(bytes)
4445 }
4446
4447 ArmOp::I64DivS {
4452 rdlo: _,
4453 rdhi: _,
4454 rnlo: _,
4455 rnhi: _,
4456 rmlo: _,
4457 rmhi: _,
4458 } => {
4459 let mut bytes = Vec::new();
4460
4461 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4463 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4464
4465 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4468 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4469
4470 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());
4483
4484 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());
4494
4495 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4498 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4499 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4501 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4502 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4504 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4505
4506 let loop_start = bytes.len();
4507
4508 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4512 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());
4518 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4521
4522 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4526 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());
4539 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4541
4542 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4545
4546 let branch_offset_bytes = bytes.len() - loop_start + 4;
4547 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4548 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4549 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4550
4551 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());
4558 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());
4566
4567 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4569 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4570
4571 Ok(bytes)
4572 }
4573
4574 ArmOp::I64RemU {
4579 rdlo: _,
4580 rdhi: _,
4581 rnlo: _,
4582 rnhi: _,
4583 rmlo: _,
4584 rmhi: _,
4585 } => {
4586 let mut bytes = Vec::new();
4587
4588 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4590 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4591
4592 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4594 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4595 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4597 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4598 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4600 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4601
4602 let loop_start = bytes.len();
4603
4604 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4608 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());
4614 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4617
4618 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4622 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());
4635 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4637
4638 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4641
4642 let branch_offset_bytes = bytes.len() - loop_start + 4;
4643 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4644 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4645 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4646
4647 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4653 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4654
4655 Ok(bytes)
4656 }
4657
4658 ArmOp::I64RemS {
4663 rdlo: _,
4664 rdhi: _,
4665 rnlo: _,
4666 rnhi: _,
4667 rmlo: _,
4668 rmhi: _,
4669 } => {
4670 let mut bytes = Vec::new();
4671
4672 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4674 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4675
4676 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());
4690
4691 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());
4701
4702 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4705 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4706 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4708 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4709 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4711 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4712
4713 let loop_start = bytes.len();
4714
4715 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4719 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());
4725 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4728
4729 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4733 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());
4746 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4748
4749 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4752
4753 let branch_offset_bytes = bytes.len() - loop_start + 4;
4754 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4755 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4756 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4757
4758 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());
4765 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());
4773
4774 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4776 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4777
4778 Ok(bytes)
4779 }
4780
4781 ArmOp::F32Add { sd, sn, sm } => {
4784 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4785 }
4786 ArmOp::F32Sub { sd, sn, sm } => {
4787 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4788 }
4789 ArmOp::F32Mul { sd, sn, sm } => {
4790 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4791 }
4792 ArmOp::F32Div { sd, sn, sm } => {
4793 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4794 }
4795 ArmOp::F32Abs { sd, sm } => {
4796 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4797 }
4798 ArmOp::F32Neg { sd, sm } => {
4799 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4800 }
4801 ArmOp::F32Sqrt { sd, sm } => {
4802 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4803 }
4804
4805 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4808 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4809 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4810 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4811 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4812 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4813 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4814
4815 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4817 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4818 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4819 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4820 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4821 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4822
4823 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4824
4825 ArmOp::F32Load { sd, addr } => {
4826 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4827 }
4828 ArmOp::F32Store { sd, addr } => {
4829 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4830 }
4831
4832 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4833 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4834 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4835 Err(synth_core::Error::synthesis(
4836 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4837 ))
4838 }
4839 ArmOp::F32ReinterpretI32 { sd, rm } => {
4840 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4841 }
4842 ArmOp::I32ReinterpretF32 { rd, sm } => {
4843 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4844 }
4845 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4846 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4847
4848 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4851 0xEE300B00, dd, dn, dm,
4852 )?)),
4853 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4854 0xEE300B40, dd, dn, dm,
4855 )?)),
4856 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4857 0xEE200B00, dd, dn, dm,
4858 )?)),
4859 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4860 0xEE800B00, dd, dn, dm,
4861 )?)),
4862 ArmOp::F64Abs { dd, dm } => {
4863 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4864 }
4865 ArmOp::F64Neg { dd, dm } => {
4866 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4867 }
4868 ArmOp::F64Sqrt { dd, dm } => {
4869 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4870 }
4871
4872 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4875 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4876 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4877 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4878 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4879 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4880 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4881
4882 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4884 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4885 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4886 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4887 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4888 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4889
4890 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4891
4892 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4893 0xED900B00, dd, addr,
4894 )?)),
4895 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4896 0xED800B00, dd, addr,
4897 )?)),
4898
4899 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4900 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4901 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4902 Err(synth_core::Error::synthesis(
4903 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4904 ))
4905 }
4906 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4907 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4908 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4909 )),
4910 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4911 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4912 )),
4913 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4914 Err(synth_core::Error::synthesis(
4915 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4916 ))
4917 }
4918 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4919 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4920
4921 ArmOp::I64Add {
4925 rdlo,
4926 rdhi,
4927 rnlo,
4928 rnhi,
4929 rmlo,
4930 rmhi,
4931 } => {
4932 let mut bytes = Vec::new();
4933 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4935 rd: *rdlo,
4936 rn: *rnlo,
4937 op2: Operand2::Reg(*rmlo),
4938 })?);
4939 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4941 rd: *rdhi,
4942 rn: *rnhi,
4943 op2: Operand2::Reg(*rmhi),
4944 })?);
4945 Ok(bytes)
4946 }
4947
4948 ArmOp::I64Sub {
4950 rdlo,
4951 rdhi,
4952 rnlo,
4953 rnhi,
4954 rmlo,
4955 rmhi,
4956 } => {
4957 let mut bytes = Vec::new();
4958 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4960 rd: *rdlo,
4961 rn: *rnlo,
4962 op2: Operand2::Reg(*rmlo),
4963 })?);
4964 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4966 rd: *rdhi,
4967 rn: *rnhi,
4968 op2: Operand2::Reg(*rmhi),
4969 })?);
4970 Ok(bytes)
4971 }
4972
4973 ArmOp::I64And {
4975 rdlo,
4976 rdhi,
4977 rnlo,
4978 rnhi,
4979 rmlo,
4980 rmhi,
4981 } => {
4982 let mut bytes = Vec::new();
4983 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4984 rd: *rdlo,
4985 rn: *rnlo,
4986 op2: Operand2::Reg(*rmlo),
4987 })?);
4988 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4989 rd: *rdhi,
4990 rn: *rnhi,
4991 op2: Operand2::Reg(*rmhi),
4992 })?);
4993 Ok(bytes)
4994 }
4995
4996 ArmOp::I64Or {
4998 rdlo,
4999 rdhi,
5000 rnlo,
5001 rnhi,
5002 rmlo,
5003 rmhi,
5004 } => {
5005 let mut bytes = Vec::new();
5006 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5007 rd: *rdlo,
5008 rn: *rnlo,
5009 op2: Operand2::Reg(*rmlo),
5010 })?);
5011 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
5012 rd: *rdhi,
5013 rn: *rnhi,
5014 op2: Operand2::Reg(*rmhi),
5015 })?);
5016 Ok(bytes)
5017 }
5018
5019 ArmOp::I64Xor {
5021 rdlo,
5022 rdhi,
5023 rnlo,
5024 rnhi,
5025 rmlo,
5026 rmhi,
5027 } => {
5028 let mut bytes = Vec::new();
5029 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5030 rd: *rdlo,
5031 rn: *rnlo,
5032 op2: Operand2::Reg(*rmlo),
5033 })?);
5034 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
5035 rd: *rdhi,
5036 rn: *rnhi,
5037 op2: Operand2::Reg(*rmhi),
5038 })?);
5039 Ok(bytes)
5040 }
5041
5042 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
5044 rd: *rd,
5045 rn_lo: *rnlo,
5046 rn_hi: *rnhi,
5047 }),
5048
5049 ArmOp::I64Eq {
5051 rd,
5052 rnlo,
5053 rnhi,
5054 rmlo,
5055 rmhi,
5056 } => self.encode_thumb(&ArmOp::I64SetCond {
5057 rd: *rd,
5058 rn_lo: *rnlo,
5059 rn_hi: *rnhi,
5060 rm_lo: *rmlo,
5061 rm_hi: *rmhi,
5062 cond: synth_synthesis::Condition::EQ,
5063 }),
5064
5065 ArmOp::I64Ne {
5066 rd,
5067 rnlo,
5068 rnhi,
5069 rmlo,
5070 rmhi,
5071 } => self.encode_thumb(&ArmOp::I64SetCond {
5072 rd: *rd,
5073 rn_lo: *rnlo,
5074 rn_hi: *rnhi,
5075 rm_lo: *rmlo,
5076 rm_hi: *rmhi,
5077 cond: synth_synthesis::Condition::NE,
5078 }),
5079
5080 ArmOp::I64LtS {
5081 rd,
5082 rnlo,
5083 rnhi,
5084 rmlo,
5085 rmhi,
5086 } => self.encode_thumb(&ArmOp::I64SetCond {
5087 rd: *rd,
5088 rn_lo: *rnlo,
5089 rn_hi: *rnhi,
5090 rm_lo: *rmlo,
5091 rm_hi: *rmhi,
5092 cond: synth_synthesis::Condition::LT,
5093 }),
5094
5095 ArmOp::I64LtU {
5096 rd,
5097 rnlo,
5098 rnhi,
5099 rmlo,
5100 rmhi,
5101 } => self.encode_thumb(&ArmOp::I64SetCond {
5102 rd: *rd,
5103 rn_lo: *rnlo,
5104 rn_hi: *rnhi,
5105 rm_lo: *rmlo,
5106 rm_hi: *rmhi,
5107 cond: synth_synthesis::Condition::LO,
5108 }),
5109
5110 ArmOp::I64LeS {
5111 rd,
5112 rnlo,
5113 rnhi,
5114 rmlo,
5115 rmhi,
5116 } => self.encode_thumb(&ArmOp::I64SetCond {
5117 rd: *rd,
5118 rn_lo: *rnlo,
5119 rn_hi: *rnhi,
5120 rm_lo: *rmlo,
5121 rm_hi: *rmhi,
5122 cond: synth_synthesis::Condition::LE,
5123 }),
5124
5125 ArmOp::I64LeU {
5126 rd,
5127 rnlo,
5128 rnhi,
5129 rmlo,
5130 rmhi,
5131 } => self.encode_thumb(&ArmOp::I64SetCond {
5132 rd: *rd,
5133 rn_lo: *rnlo,
5134 rn_hi: *rnhi,
5135 rm_lo: *rmlo,
5136 rm_hi: *rmhi,
5137 cond: synth_synthesis::Condition::LS,
5138 }),
5139
5140 ArmOp::I64GtS {
5141 rd,
5142 rnlo,
5143 rnhi,
5144 rmlo,
5145 rmhi,
5146 } => self.encode_thumb(&ArmOp::I64SetCond {
5147 rd: *rd,
5148 rn_lo: *rnlo,
5149 rn_hi: *rnhi,
5150 rm_lo: *rmlo,
5151 rm_hi: *rmhi,
5152 cond: synth_synthesis::Condition::GT,
5153 }),
5154
5155 ArmOp::I64GtU {
5156 rd,
5157 rnlo,
5158 rnhi,
5159 rmlo,
5160 rmhi,
5161 } => self.encode_thumb(&ArmOp::I64SetCond {
5162 rd: *rd,
5163 rn_lo: *rnlo,
5164 rn_hi: *rnhi,
5165 rm_lo: *rmlo,
5166 rm_hi: *rmhi,
5167 cond: synth_synthesis::Condition::HI,
5168 }),
5169
5170 ArmOp::I64GeS {
5171 rd,
5172 rnlo,
5173 rnhi,
5174 rmlo,
5175 rmhi,
5176 } => self.encode_thumb(&ArmOp::I64SetCond {
5177 rd: *rd,
5178 rn_lo: *rnlo,
5179 rn_hi: *rnhi,
5180 rm_lo: *rmlo,
5181 rm_hi: *rmhi,
5182 cond: synth_synthesis::Condition::GE,
5183 }),
5184
5185 ArmOp::I64GeU {
5186 rd,
5187 rnlo,
5188 rnhi,
5189 rmlo,
5190 rmhi,
5191 } => self.encode_thumb(&ArmOp::I64SetCond {
5192 rd: *rd,
5193 rn_lo: *rnlo,
5194 rn_hi: *rnhi,
5195 rm_lo: *rmlo,
5196 rm_hi: *rmhi,
5197 cond: synth_synthesis::Condition::HS,
5198 }),
5199
5200 ArmOp::I64Const { rdlo, rdhi, value } => {
5202 let lo32 = *value as u32;
5203 let hi32 = (*value >> 32) as u32;
5204 let mut bytes = Vec::new();
5205 bytes.extend_from_slice(
5207 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5208 );
5209 if lo32 > 0xFFFF {
5210 bytes.extend_from_slice(
5211 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5212 );
5213 }
5214 bytes.extend_from_slice(
5216 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5217 );
5218 if hi32 > 0xFFFF {
5219 bytes.extend_from_slice(
5220 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5221 );
5222 }
5223 Ok(bytes)
5224 }
5225
5226 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5228 let mut bytes = Vec::new();
5229 let offset = if addr.offset < 0 {
5230 0u32
5231 } else {
5232 addr.offset as u32
5233 };
5234 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5235 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5236 rdhi,
5237 &addr.base,
5238 offset.wrapping_add(4),
5239 )?);
5240 Ok(bytes)
5241 }
5242
5243 ArmOp::I64Str { rdlo, rdhi, addr } => {
5245 let mut bytes = Vec::new();
5246 let offset = if addr.offset < 0 {
5247 0u32
5248 } else {
5249 addr.offset as u32
5250 };
5251 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5252 bytes.extend_from_slice(&self.encode_thumb32_str(
5253 rdhi,
5254 &addr.base,
5255 offset.wrapping_add(4),
5256 )?);
5257 Ok(bytes)
5258 }
5259
5260 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5262 let mut bytes = Vec::new();
5263 if rdlo != rn {
5264 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5266 rd: *rdlo,
5267 op2: Operand2::Reg(*rn),
5268 })?);
5269 }
5270 bytes.extend_from_slice(
5272 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5274 Ok(bytes)
5275 }
5276
5277 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5279 let mut bytes = Vec::new();
5280 if rdlo != rn {
5281 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5283 rd: *rdlo,
5284 op2: Operand2::Reg(*rn),
5285 })?);
5286 }
5287 let rdhi_bits = reg_to_bits(rdhi) as u16;
5289 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5290 bytes.extend_from_slice(&instr.to_le_bytes());
5291 Ok(bytes)
5292 }
5293
5294 ArmOp::I32WrapI64 { rd, rnlo } => {
5296 if rd == rnlo {
5297 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5300 } else {
5301 self.encode_thumb(&ArmOp::Mov {
5303 rd: *rd,
5304 op2: Operand2::Reg(*rnlo),
5305 })
5306 }
5307 }
5308
5309 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5311 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5312 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5313 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5314 0xEF000150, qd, qn, qm,
5315 ))),
5316 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5317 0xEF200150, qd, qn, qm,
5318 ))),
5319 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5320 0xFF000150, qd, qn, qm,
5321 ))),
5322 ArmOp::MveMvn { qd, qm } => {
5323 let qd_enc = qreg_to_num(qd);
5325 let qm_enc = qreg_to_num(qm);
5326 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5327 Ok(vfp_to_thumb_bytes(instr))
5328 }
5329 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5330 0xEF100150, qd, qn, qm,
5331 ))),
5332 ArmOp::MveAddI { qd, qn, qm, size } => {
5333 let sz = mve_size_bits(size);
5334 let base: u32 = 0xEF000840 | (sz << 20);
5335 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5336 }
5337 ArmOp::MveSubI { qd, qn, qm, size } => {
5338 let sz = mve_size_bits(size);
5339 let base: u32 = 0xFF000840 | (sz << 20);
5340 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5341 }
5342 ArmOp::MveMulI { qd, qn, qm, size } => {
5343 let sz = mve_size_bits(size);
5344 let base: u32 = 0xEF000950 | (sz << 20);
5345 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5346 }
5347 ArmOp::MveNegI { qd, qm, size } => {
5348 let sz = mve_size_bits(size);
5349 let qd_enc = qreg_to_num(qd);
5351 let qm_enc = qreg_to_num(qm);
5352 let base: u32 = 0xFFB103C0 | (sz << 18);
5353 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5354 Ok(vfp_to_thumb_bytes(instr))
5355 }
5356 ArmOp::MveDup { qd, rn, size } => {
5357 let sz = mve_size_bits(size);
5358 let qd_enc = qreg_to_num(qd);
5359 let rn_bits = reg_to_bits(rn);
5360 let be = match sz {
5363 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5367 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5368 Ok(vfp_to_thumb_bytes(instr))
5369 }
5370 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5371 let qn_enc = qreg_to_num(qn);
5372 let rd_bits = reg_to_bits(rd);
5373 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5376 let lane_in_d = (*lane as u32) & 1;
5377 let _sz = mve_size_bits(size);
5378 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5380 Ok(vfp_to_thumb_bytes(instr))
5381 }
5382 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5383 let qd_enc = qreg_to_num(qd);
5384 let rn_bits = reg_to_bits(rn);
5385 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5386 let lane_in_d = (*lane as u32) & 1;
5387 let _sz = mve_size_bits(size);
5388 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5390 Ok(vfp_to_thumb_bytes(instr))
5391 }
5392
5393 ArmOp::MveCmpEqI { qd, qn, qm, size }
5395 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5396 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5397 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5398 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5399 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5400 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5401 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5402 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5403 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5404 let sz = mve_size_bits(size);
5407 let base: u32 = 0xEF000840 | (sz << 20);
5408 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5409 }
5410
5411 ArmOp::MveAddF32 { qd, qn, qm } => {
5413 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5415 }
5416 ArmOp::MveSubF32 { qd, qn, qm } => {
5417 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5419 }
5420 ArmOp::MveMulF32 { qd, qn, qm } => {
5421 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5423 }
5424 ArmOp::MveNegF32 { qd, qm } => {
5425 let qd_enc = qreg_to_num(qd);
5426 let qm_enc = qreg_to_num(qm);
5427 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5429 Ok(vfp_to_thumb_bytes(instr))
5430 }
5431 ArmOp::MveAbsF32 { qd, qm } => {
5432 let qd_enc = qreg_to_num(qd);
5433 let qm_enc = qreg_to_num(qm);
5434 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5436 Ok(vfp_to_thumb_bytes(instr))
5437 }
5438 ArmOp::MveCmpEqF32 { qd, qn, qm }
5439 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5440 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5441 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5442 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5443 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5444 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5446 }
5447 ArmOp::MveDupF32 { qd, rn } => {
5448 let qd_enc = qreg_to_num(qd);
5449 let rn_bits = reg_to_bits(rn);
5450 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5452 Ok(vfp_to_thumb_bytes(instr))
5453 }
5454 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5455 let qn_enc = qreg_to_num(qn);
5456 let rd_bits = reg_to_bits(rd);
5457 let s_num = qn_enc * 4 + (*lane as u32);
5459 let (vn, n) = encode_sreg(s_num);
5460 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5461 Ok(vfp_to_thumb_bytes(instr))
5462 }
5463 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5464 let qd_enc = qreg_to_num(qd);
5465 let rn_bits = reg_to_bits(rn);
5466 let s_num = qd_enc * 4 + (*lane as u32);
5468 let (vn, n) = encode_sreg(s_num);
5469 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5470 Ok(vfp_to_thumb_bytes(instr))
5471 }
5472 ArmOp::MveDivF32 { qd, qn, qm } => {
5473 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5475 }
5476 ArmOp::MveSqrtF32 { qd, qm } => {
5477 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5479 }
5480
5481 _ => {
5483 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5485 }
5486 }
5487 }
5488
5489 fn encode_thumb_f32_compare(
5493 &self,
5494 rd: &Reg,
5495 sn: &VfpReg,
5496 sm: &VfpReg,
5497 cond_code: u32,
5498 ) -> Result<Vec<u8>> {
5499 let mut bytes = Vec::new();
5500 let rd_bits = reg_to_bits(rd);
5501
5502 let sn_num = vfp_sreg_to_num(sn)?;
5504 let sm_num = vfp_sreg_to_num(sm)?;
5505 let (vd, d) = encode_sreg(sn_num);
5506 let (vm, m) = encode_sreg(sm_num);
5507 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5508 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5509
5510 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5512
5513 if rd_bits < 8 {
5515 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5516 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5517 } else {
5518 let hw1: u16 = 0xF04F;
5520 let hw2: u16 = (rd_bits as u16) << 8;
5521 bytes.extend_from_slice(&hw1.to_le_bytes());
5522 bytes.extend_from_slice(&hw2.to_le_bytes());
5523 }
5524
5525 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5529 bytes.extend_from_slice(&it.to_le_bytes());
5530
5531 if rd_bits < 8 {
5533 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5534 bytes.extend_from_slice(&mov_one.to_le_bytes());
5535 } else {
5536 let hw1: u16 = 0xF04F;
5538 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5539 bytes.extend_from_slice(&hw1.to_le_bytes());
5540 bytes.extend_from_slice(&hw2.to_le_bytes());
5541 }
5542
5543 Ok(bytes)
5544 }
5545
5546 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5548 let mut bytes = Vec::new();
5549 let bits = value.to_bits();
5550 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5555 let imm4 = (lo16 >> 12) & 0xF;
5556 let i_bit = (lo16 >> 11) & 1;
5557 let imm3 = (lo16 >> 8) & 0x7;
5558 let imm8 = lo16 & 0xFF;
5559 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5560 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5561 bytes.extend_from_slice(&hw1.to_le_bytes());
5562 bytes.extend_from_slice(&hw2.to_le_bytes());
5563
5564 let hi16 = (bits >> 16) & 0xFFFF;
5566 let imm4 = (hi16 >> 12) & 0xF;
5567 let i_bit = (hi16 >> 11) & 1;
5568 let imm3 = (hi16 >> 8) & 0x7;
5569 let imm8 = hi16 & 0xFF;
5570 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5571 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5572 bytes.extend_from_slice(&hw1.to_le_bytes());
5573 bytes.extend_from_slice(&hw2.to_le_bytes());
5574
5575 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5577 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5578
5579 Ok(bytes)
5580 }
5581
5582 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5584 let mut bytes = Vec::new();
5585
5586 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5588 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5589
5590 let sd_num = vfp_sreg_to_num(sd)?;
5592 let (vd, d) = encode_sreg(sd_num);
5593 let (vm, m) = encode_sreg(sd_num);
5594 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5595 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5596 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5597
5598 Ok(bytes)
5599 }
5600
5601 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5609 let mut bytes = Vec::new();
5610 let sm_num = vfp_sreg_to_num(sm)?;
5611 let sd_num = vfp_sreg_to_num(sd)?;
5612 let (vd_s, d_s) = encode_sreg(sd_num);
5613 let (vm_s, m_s) = encode_sreg(sm_num);
5614
5615 if mode == 0b11 {
5616 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5618 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5619 } else {
5620 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5625 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5626
5627 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5633 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5634 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5635
5636 if mode != 0 {
5638 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5640 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5641 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5642 }
5643
5644 let vmsr = 0xEEE10A10 | (rt << 12);
5646 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5647
5648 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5650 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5651
5652 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5654 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5655 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5656 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5657 }
5658
5659 let (vd2, d2) = encode_sreg(sd_num);
5661 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5662 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5663
5664 Ok(bytes)
5665 }
5666
5667 fn encode_thumb_f32_minmax(
5669 &self,
5670 sd: &VfpReg,
5671 sn: &VfpReg,
5672 sm: &VfpReg,
5673 is_min: bool,
5674 ) -> Result<Vec<u8>> {
5675 let mut bytes = Vec::new();
5676 let sn_num = vfp_sreg_to_num(sn)?;
5677 let sm_num = vfp_sreg_to_num(sm)?;
5678 let sd_num = vfp_sreg_to_num(sd)?;
5679
5680 let (vd, d) = encode_sreg(sd_num);
5682 let (vn, n) = encode_sreg(sn_num);
5683 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5684 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5685
5686 let (vm, m) = encode_sreg(sm_num);
5688 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5689 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5690
5691 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5693
5694 let cond: u16 = if is_min { 0xC } else { 0x4 };
5696 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5697 bytes.extend_from_slice(&it.to_le_bytes());
5698
5699 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5701 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5702
5703 Ok(bytes)
5704 }
5705
5706 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5708 let mut bytes = Vec::new();
5709
5710 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5712 false,
5713 sm,
5714 &Reg::R12,
5715 )?));
5716
5717 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5719 false,
5720 sn,
5721 &Reg::R0,
5722 )?));
5723
5724 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5736 bytes.extend_from_slice(&hw2.to_le_bytes());
5737
5738 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5742 bytes.extend_from_slice(&hw2.to_le_bytes());
5743
5744 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5748 bytes.extend_from_slice(&hw2.to_le_bytes());
5749
5750 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5752 true,
5753 sd,
5754 &Reg::R0,
5755 )?));
5756
5757 Ok(bytes)
5758 }
5759
5760 fn encode_thumb_f64_compare(
5762 &self,
5763 rd: &Reg,
5764 dn: &VfpReg,
5765 dm: &VfpReg,
5766 cond_code: u32,
5767 ) -> Result<Vec<u8>> {
5768 let mut bytes = Vec::new();
5769 let rd_bits = reg_to_bits(rd);
5770
5771 let dn_num = vfp_dreg_to_num(dn)?;
5773 let dm_num = vfp_dreg_to_num(dm)?;
5774 let (vd, d) = encode_dreg(dn_num);
5775 let (vm, m) = encode_dreg(dm_num);
5776 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5777 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5778
5779 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5781
5782 if rd_bits < 8 {
5784 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5785 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5786 } else {
5787 let hw1: u16 = 0xF04F;
5788 let hw2: u16 = (rd_bits as u16) << 8;
5789 bytes.extend_from_slice(&hw1.to_le_bytes());
5790 bytes.extend_from_slice(&hw2.to_le_bytes());
5791 }
5792
5793 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5795 bytes.extend_from_slice(&it.to_le_bytes());
5796
5797 if rd_bits < 8 {
5799 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5800 bytes.extend_from_slice(&mov_one.to_le_bytes());
5801 } else {
5802 let hw1: u16 = 0xF04F;
5803 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5804 bytes.extend_from_slice(&hw1.to_le_bytes());
5805 bytes.extend_from_slice(&hw2.to_le_bytes());
5806 }
5807
5808 Ok(bytes)
5809 }
5810
5811 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5813 let mut bytes = Vec::new();
5814 let bits = value.to_bits();
5815 let lo32 = bits as u32;
5816 let hi32 = (bits >> 32) as u32;
5817
5818 let lo16 = lo32 & 0xFFFF;
5820 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5821
5822 let hi16 = (lo32 >> 16) & 0xFFFF;
5824 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5825
5826 let lo16 = hi32 & 0xFFFF;
5828 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5829
5830 let hi16 = (hi32 >> 16) & 0xFFFF;
5832 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5833
5834 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5836 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5837
5838 Ok(bytes)
5839 }
5840
5841 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5843 let mut bytes = Vec::new();
5844
5845 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5847 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5848
5849 let dd_num = vfp_dreg_to_num(dd)?;
5851 let (vd, d) = encode_dreg(dd_num);
5852 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5853 let vcvt = base | (d << 22) | (vd << 12);
5854 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5855
5856 Ok(bytes)
5857 }
5858
5859 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5861 let dd_num = vfp_dreg_to_num(dd)?;
5862 let sm_num = vfp_sreg_to_num(sm)?;
5863 let (vd, d) = encode_dreg(dd_num);
5864 let (vm, m) = encode_sreg(sm_num);
5865
5866 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5867 Ok(vfp_to_thumb_bytes(vcvt))
5868 }
5869
5870 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5872 let mut bytes = Vec::new();
5873 let dm_num = vfp_dreg_to_num(dm)?;
5874 let (vm, m) = encode_dreg(dm_num);
5875
5876 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5878 let vcvt = base | (m << 5) | vm;
5879 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5880
5881 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5883 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5884
5885 Ok(bytes)
5886 }
5887
5888 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5892 let mut bytes = Vec::new();
5893 let dm_num = vfp_dreg_to_num(dm)?;
5894 let dd_num = vfp_dreg_to_num(dd)?;
5895 let (vm, m) = encode_dreg(dm_num);
5896 let (vd, d) = encode_dreg(dd_num);
5897
5898 if mode == 0b11 {
5899 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5901 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5902 } else {
5903 let rt: u32 = 12;
5904
5905 let vmrs = 0xEEF10A10 | (rt << 12);
5907 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5908
5909 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5911 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5912 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5913 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5914
5915 if mode != 0 {
5917 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5918 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5919 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5920 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5921 }
5922
5923 let vmsr = 0xEEE10A10 | (rt << 12);
5925 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5926
5927 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5929 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5930
5931 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5933 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5934 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5935 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5936 }
5937
5938 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5940 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5941
5942 Ok(bytes)
5943 }
5944
5945 fn encode_thumb_f64_minmax(
5947 &self,
5948 dd: &VfpReg,
5949 dn: &VfpReg,
5950 dm: &VfpReg,
5951 is_min: bool,
5952 ) -> Result<Vec<u8>> {
5953 let mut bytes = Vec::new();
5954 let dn_num = vfp_dreg_to_num(dn)?;
5955 let dm_num = vfp_dreg_to_num(dm)?;
5956 let dd_num = vfp_dreg_to_num(dd)?;
5957
5958 let (vd, d) = encode_dreg(dd_num);
5960 let (vn, n) = encode_dreg(dn_num);
5961 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5962 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5963
5964 let (vm, m) = encode_dreg(dm_num);
5966 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5967 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5968
5969 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5971
5972 let cond: u16 = if is_min { 0xC } else { 0x4 };
5974 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5975 bytes.extend_from_slice(&it.to_le_bytes());
5976
5977 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5979 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5980
5981 Ok(bytes)
5982 }
5983
5984 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5986 let mut bytes = Vec::new();
5987
5988 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5990 false,
5991 dm,
5992 &Reg::R0,
5993 &Reg::R12,
5994 )?));
5995
5996 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5998 false,
5999 dn,
6000 &Reg::R1,
6001 &Reg::R2,
6002 )?));
6003
6004 let hw1: u16 = 0xF000 | 12;
6006 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
6007 bytes.extend_from_slice(&hw1.to_le_bytes());
6008 bytes.extend_from_slice(&hw2.to_le_bytes());
6009
6010 let hw1: u16 = 0xF020 | 2;
6012 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
6013 bytes.extend_from_slice(&hw1.to_le_bytes());
6014 bytes.extend_from_slice(&hw2.to_le_bytes());
6015
6016 let hw1: u16 = 0xEA40 | 2;
6018 let hw2: u16 = (2 << 8) | 12;
6019 bytes.extend_from_slice(&hw1.to_le_bytes());
6020 bytes.extend_from_slice(&hw2.to_le_bytes());
6021
6022 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
6024 true,
6025 dd,
6026 &Reg::R1,
6027 &Reg::R2,
6028 )?));
6029
6030 Ok(bytes)
6031 }
6032
6033 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
6035 let mut bytes = Vec::new();
6036
6037 let sm_num = vfp_sreg_to_num(sm)?;
6038 let (vd, d) = encode_sreg(sm_num);
6039 let (vm, m) = encode_sreg(sm_num);
6040 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
6041 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
6042 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
6043
6044 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
6046 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6047
6048 Ok(bytes)
6049 }
6050
6051 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6055 let rd_bits = reg_to_bits(rd);
6056 let rn_bits = reg_to_bits(rn);
6057
6058 let i_bit = (imm >> 11) & 1;
6060 let imm3 = (imm >> 8) & 0x7;
6061 let imm8 = imm & 0xFF;
6062
6063 let hw1_base = if imm <= 0xFF {
6064 0xF100
6068 } else if imm <= 0xFFF {
6069 0xF200
6073 } else {
6074 return Err(synth_core::Error::synthesis(
6075 "ADD immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6076 ));
6077 };
6078
6079 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6080 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6081
6082 let mut bytes = hw1.to_le_bytes().to_vec();
6083 bytes.extend_from_slice(&hw2.to_le_bytes());
6084 Ok(bytes)
6085 }
6086
6087 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6089 let rd_bits = reg_to_bits(rd);
6090 let rn_bits = reg_to_bits(rn);
6091
6092 let i_bit = (imm >> 11) & 1;
6093 let imm3 = (imm >> 8) & 0x7;
6094 let imm8 = imm & 0xFF;
6095
6096 let hw1_base = if imm <= 0xFF {
6097 0xF1A0
6100 } else if imm <= 0xFFF {
6101 0xF2A0
6104 } else {
6105 return Err(synth_core::Error::synthesis(
6106 "SUB immediate > 0xFFF (4095) requires a multi-instruction sequence (not supported)",
6107 ));
6108 };
6109
6110 let hw1: u16 = (hw1_base | (i_bit << 10) | rn_bits) as u16;
6111 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6112
6113 let mut bytes = hw1.to_le_bytes().to_vec();
6114 bytes.extend_from_slice(&hw2.to_le_bytes());
6115 Ok(bytes)
6116 }
6117
6118 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6120 let rd_bits = reg_to_bits(rd);
6121 let rn_bits = reg_to_bits(rn);
6122
6123 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6126 synth_core::Error::synthesis(
6127 "ADDS immediate is not a valid ThumbExpandImm — materialize into a register",
6128 )
6129 })?;
6130 let i_bit = (field >> 11) & 1;
6131 let imm3 = (field >> 8) & 0x7;
6132 let imm8 = field & 0xFF;
6133
6134 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6137 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6138
6139 let mut bytes = hw1.to_le_bytes().to_vec();
6140 bytes.extend_from_slice(&hw2.to_le_bytes());
6141 Ok(bytes)
6142 }
6143
6144 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6146 let rd_bits = reg_to_bits(rd);
6147 let rn_bits = reg_to_bits(rn);
6148
6149 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6152 synth_core::Error::synthesis(
6153 "SUBS immediate is not a valid ThumbExpandImm — materialize into a register",
6154 )
6155 })?;
6156 let i_bit = (field >> 11) & 1;
6157 let imm3 = (field >> 8) & 0x7;
6158 let imm8 = field & 0xFF;
6159
6160 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6163 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6164
6165 let mut bytes = hw1.to_le_bytes().to_vec();
6166 bytes.extend_from_slice(&hw2.to_le_bytes());
6167 Ok(bytes)
6168 }
6169
6170 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6179 let rd_bits = reg_to_bits(rd);
6180 reg_bits_checked(rd_bits)?;
6181 let imm16 = imm & 0xFFFF;
6182
6183 let imm4 = (imm16 >> 12) & 0xF;
6186 let i_bit = (imm16 >> 11) & 1;
6187 let imm3 = (imm16 >> 8) & 0x7;
6188 let imm8 = imm16 & 0xFF;
6189
6190 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6191 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6192
6193 let mut bytes = hw1.to_le_bytes().to_vec();
6194 bytes.extend_from_slice(&hw2.to_le_bytes());
6195 encoding_contracts::verify_thumb32(&bytes);
6196 Ok(bytes)
6197 }
6198
6199 fn encode_thumb32_shift(
6207 &self,
6208 rd: &Reg,
6209 rm: &Reg,
6210 shift: u32,
6211 shift_type: u8,
6212 ) -> Result<Vec<u8>> {
6213 let rd_bits = reg_to_bits(rd);
6214 let rm_bits = reg_to_bits(rm);
6215 reg_bits_checked(rd_bits)?;
6216 reg_bits_checked(rm_bits)?;
6217 let imm5 = shift & 0x1F;
6218 let imm2 = imm5 & 0x3;
6219 let imm3 = (imm5 >> 2) & 0x7;
6220
6221 let hw1: u16 = 0xEA4F;
6224 let hw2: u16 =
6225 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6226 as u16;
6227
6228 let mut bytes = hw1.to_le_bytes().to_vec();
6229 bytes.extend_from_slice(&hw2.to_le_bytes());
6230 Ok(bytes)
6231 }
6232
6233 fn encode_thumb32_shift_reg(
6237 &self,
6238 rd: &Reg,
6239 rn: &Reg,
6240 rm: &Reg,
6241 shift_type: u8,
6242 ) -> Result<Vec<u8>> {
6243 let rd_bits = reg_to_bits(rd);
6244 let rn_bits = reg_to_bits(rn);
6245 let rm_bits = reg_to_bits(rm);
6246
6247 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6249 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6251
6252 let mut bytes = hw1.to_le_bytes().to_vec();
6253 bytes.extend_from_slice(&hw2.to_le_bytes());
6254 Ok(bytes)
6255 }
6256
6257 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6259 let rn_bits = reg_to_bits(rn);
6260
6261 let field = try_thumb_expand_imm(imm).ok_or_else(|| {
6265 synth_core::Error::synthesis(
6266 "CMP immediate is not a valid ThumbExpandImm — materialize into a register",
6267 )
6268 })?;
6269 let i_bit = (field >> 11) & 1;
6270 let imm3 = (field >> 8) & 0x7;
6271 let imm8 = field & 0xFF;
6272
6273 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6275 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6276
6277 let mut bytes = hw1.to_le_bytes().to_vec();
6278 bytes.extend_from_slice(&hw2.to_le_bytes());
6279 Ok(bytes)
6280 }
6281
6282 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6284 let rd_bits = reg_to_bits(rd);
6285 let base_bits = reg_to_bits(base);
6286
6287 check_ldst_imm12(offset)?;
6289 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6290 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6291
6292 let mut bytes = hw1.to_le_bytes().to_vec();
6293 bytes.extend_from_slice(&hw2.to_le_bytes());
6294 Ok(bytes)
6295 }
6296
6297 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6299 let rd_bits = reg_to_bits(rd);
6300 let base_bits = reg_to_bits(base);
6301
6302 check_ldst_imm12(offset)?;
6304 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6305 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6306
6307 let mut bytes = hw1.to_le_bytes().to_vec();
6308 bytes.extend_from_slice(&hw2.to_le_bytes());
6309 Ok(bytes)
6310 }
6311
6312 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6314 let rd_bits = reg_to_bits(rd);
6315 let base_bits = reg_to_bits(base);
6316 let rm_bits = reg_to_bits(offset_reg);
6317
6318 let hw1: u16 = (0xF850 | base_bits) as u16;
6322 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6323
6324 let mut bytes = hw1.to_le_bytes().to_vec();
6325 bytes.extend_from_slice(&hw2.to_le_bytes());
6326 Ok(bytes)
6327 }
6328
6329 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6331 let rd_bits = reg_to_bits(rd);
6332 let base_bits = reg_to_bits(base);
6333 let rm_bits = reg_to_bits(offset_reg);
6334
6335 let hw1: u16 = (0xF840 | base_bits) as u16;
6339 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6340
6341 let mut bytes = hw1.to_le_bytes().to_vec();
6342 bytes.extend_from_slice(&hw2.to_le_bytes());
6343 Ok(bytes)
6344 }
6345
6346 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6350 let rd_bits = reg_to_bits(rd);
6351 let base_bits = reg_to_bits(base);
6352 check_ldst_imm12(offset)?;
6354 let hw1: u16 = (0xF890 | base_bits) as u16;
6355 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6356 let mut bytes = hw1.to_le_bytes().to_vec();
6357 bytes.extend_from_slice(&hw2.to_le_bytes());
6358 Ok(bytes)
6359 }
6360
6361 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6363 let rd_bits = reg_to_bits(rd);
6364 let base_bits = reg_to_bits(base);
6365 let rm_bits = reg_to_bits(offset_reg);
6366 let hw1: u16 = (0xF810 | base_bits) as u16;
6368 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6369 let mut bytes = hw1.to_le_bytes().to_vec();
6370 bytes.extend_from_slice(&hw2.to_le_bytes());
6371 Ok(bytes)
6372 }
6373
6374 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6376 let rd_bits = reg_to_bits(rd);
6377 let base_bits = reg_to_bits(base);
6378 check_ldst_imm12(offset)?;
6380 let hw1: u16 = (0xF990 | base_bits) as u16;
6381 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6382 let mut bytes = hw1.to_le_bytes().to_vec();
6383 bytes.extend_from_slice(&hw2.to_le_bytes());
6384 Ok(bytes)
6385 }
6386
6387 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6389 let rd_bits = reg_to_bits(rd);
6390 let base_bits = reg_to_bits(base);
6391 let rm_bits = reg_to_bits(offset_reg);
6392 let hw1: u16 = (0xF910 | base_bits) as u16;
6394 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6395 let mut bytes = hw1.to_le_bytes().to_vec();
6396 bytes.extend_from_slice(&hw2.to_le_bytes());
6397 Ok(bytes)
6398 }
6399
6400 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6402 let rd_bits = reg_to_bits(rd);
6403 let base_bits = reg_to_bits(base);
6404 check_ldst_imm12(offset)?;
6406 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6407 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6408 let mut bytes = hw1.to_le_bytes().to_vec();
6409 bytes.extend_from_slice(&hw2.to_le_bytes());
6410 Ok(bytes)
6411 }
6412
6413 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6415 let rd_bits = reg_to_bits(rd);
6416 let base_bits = reg_to_bits(base);
6417 let rm_bits = reg_to_bits(offset_reg);
6418 let hw1: u16 = (0xF830 | base_bits) as u16;
6420 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6421 let mut bytes = hw1.to_le_bytes().to_vec();
6422 bytes.extend_from_slice(&hw2.to_le_bytes());
6423 Ok(bytes)
6424 }
6425
6426 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6428 let rd_bits = reg_to_bits(rd);
6429 let base_bits = reg_to_bits(base);
6430 check_ldst_imm12(offset)?;
6432 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6433 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6434 let mut bytes = hw1.to_le_bytes().to_vec();
6435 bytes.extend_from_slice(&hw2.to_le_bytes());
6436 Ok(bytes)
6437 }
6438
6439 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6441 let rd_bits = reg_to_bits(rd);
6442 let base_bits = reg_to_bits(base);
6443 let rm_bits = reg_to_bits(offset_reg);
6444 let hw1: u16 = (0xF930 | base_bits) as u16;
6446 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6447 let mut bytes = hw1.to_le_bytes().to_vec();
6448 bytes.extend_from_slice(&hw2.to_le_bytes());
6449 Ok(bytes)
6450 }
6451
6452 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6454 let rd_bits = reg_to_bits(rd);
6455 let base_bits = reg_to_bits(base);
6456 check_ldst_imm12(offset)?;
6458 let hw1: u16 = (0xF880 | base_bits) as u16;
6459 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6460 let mut bytes = hw1.to_le_bytes().to_vec();
6461 bytes.extend_from_slice(&hw2.to_le_bytes());
6462 Ok(bytes)
6463 }
6464
6465 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6467 let rd_bits = reg_to_bits(rd);
6468 let base_bits = reg_to_bits(base);
6469 let rm_bits = reg_to_bits(offset_reg);
6470 let hw1: u16 = (0xF800 | base_bits) as u16;
6472 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6473 let mut bytes = hw1.to_le_bytes().to_vec();
6474 bytes.extend_from_slice(&hw2.to_le_bytes());
6475 Ok(bytes)
6476 }
6477
6478 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6480 let rd_bits = reg_to_bits(rd);
6481 let base_bits = reg_to_bits(base);
6482 check_ldst_imm12(offset)?;
6484 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6485 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6486 let mut bytes = hw1.to_le_bytes().to_vec();
6487 bytes.extend_from_slice(&hw2.to_le_bytes());
6488 Ok(bytes)
6489 }
6490
6491 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6493 let rd_bits = reg_to_bits(rd);
6494 let base_bits = reg_to_bits(base);
6495 let rm_bits = reg_to_bits(offset_reg);
6496 let hw1: u16 = (0xF820 | base_bits) as u16;
6498 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6499 let mut bytes = hw1.to_le_bytes().to_vec();
6500 bytes.extend_from_slice(&hw2.to_le_bytes());
6501 Ok(bytes)
6502 }
6503
6504 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6506 let rd_bits = reg_to_bits(rd);
6507 let rn_bits = reg_to_bits(rn);
6508
6509 if imm <= 0xFFF {
6515 let i_bit = (imm >> 11) & 1;
6516 let imm3 = (imm >> 8) & 0x7;
6517 let imm8 = imm & 0xFF;
6518
6519 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6520 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6521
6522 let mut bytes = hw1.to_le_bytes().to_vec();
6523 bytes.extend_from_slice(&hw2.to_le_bytes());
6524 Ok(bytes)
6525 } else {
6526 Err(synth_core::Error::synthesis(
6529 "ADD immediate too large for single instruction",
6530 ))
6531 }
6532 }
6533
6534 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6544 reg_bits_checked(rd)?;
6545 encoding_contracts::verify_imm16(imm16);
6546 let imm16 = imm16 & 0xFFFF;
6549 let imm4 = (imm16 >> 12) & 0xF;
6550 let i_bit = (imm16 >> 11) & 1;
6551 let imm3 = (imm16 >> 8) & 0x7;
6552 let imm8 = imm16 & 0xFF;
6553
6554 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6555 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6556
6557 let mut bytes = hw1.to_le_bytes().to_vec();
6558 bytes.extend_from_slice(&hw2.to_le_bytes());
6559 encoding_contracts::verify_thumb32(&bytes);
6560 Ok(bytes)
6561 }
6562
6563 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6571 reg_bits_checked(rd)?;
6572 encoding_contracts::verify_imm16(imm16);
6573 let imm16 = imm16 & 0xFFFF;
6576 let imm4 = (imm16 >> 12) & 0xF;
6577 let i_bit = (imm16 >> 11) & 1;
6578 let imm3 = (imm16 >> 8) & 0x7;
6579 let imm8 = imm16 & 0xFF;
6580
6581 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6582 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6583
6584 let mut bytes = hw1.to_le_bytes().to_vec();
6585 bytes.extend_from_slice(&hw2.to_le_bytes());
6586 encoding_contracts::verify_thumb32(&bytes);
6587 Ok(bytes)
6588 }
6589
6590 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6592 let imm5 = shift & 0x1F;
6595 let imm2 = imm5 & 0x3;
6596 let imm3 = (imm5 >> 2) & 0x7;
6597
6598 let hw1: u16 = 0xEA4F;
6599 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6600
6601 let mut bytes = hw1.to_le_bytes().to_vec();
6602 bytes.extend_from_slice(&hw2.to_le_bytes());
6603 Ok(bytes)
6604 }
6605
6606 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6608 let hw1: u16 = (0xEA00 | rn) as u16;
6611 let hw2: u16 = ((rd << 8) | rm) as u16;
6612
6613 let mut bytes = hw1.to_le_bytes().to_vec();
6614 bytes.extend_from_slice(&hw2.to_le_bytes());
6615 Ok(bytes)
6616 }
6617
6618 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6620 let i_bit = (imm >> 11) & 1;
6624 let imm3 = (imm >> 8) & 0x7;
6625 let imm8 = imm & 0xFF;
6626
6627 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6628 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6629
6630 let mut bytes = hw1.to_le_bytes().to_vec();
6631 bytes.extend_from_slice(&hw2.to_le_bytes());
6632 Ok(bytes)
6633 }
6634
6635 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6637 let hw1: u16 = (0xEBA0 | rn) as u16;
6640 let hw2: u16 = ((rd << 8) | rm) as u16;
6641
6642 let mut bytes = hw1.to_le_bytes().to_vec();
6643 bytes.extend_from_slice(&hw2.to_le_bytes());
6644 Ok(bytes)
6645 }
6646
6647 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6649 let hw1: u16 = (0xEB00 | rn) as u16;
6652 let hw2: u16 = ((rd << 8) | rm) as u16;
6653
6654 let mut bytes = hw1.to_le_bytes().to_vec();
6655 bytes.extend_from_slice(&hw2.to_le_bytes());
6656 Ok(bytes)
6657 }
6658
6659 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6663 let hw1: u16 = (0xEB10 | rn) as u16;
6665 let hw2: u16 = ((rd << 8) | rm) as u16;
6666 let mut bytes = hw1.to_le_bytes().to_vec();
6667 bytes.extend_from_slice(&hw2.to_le_bytes());
6668 Ok(bytes)
6669 }
6670
6671 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6674 let hw1: u16 = (0xEBB0 | rn) as u16;
6676 let hw2: u16 = ((rd << 8) | rm) as u16;
6677 let mut bytes = hw1.to_le_bytes().to_vec();
6678 bytes.extend_from_slice(&hw2.to_le_bytes());
6679 Ok(bytes)
6680 }
6681
6682 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6684 let mut code = Vec::new();
6685
6686 for op in ops {
6687 let encoded = self.encode(op)?;
6688 code.extend_from_slice(&encoded);
6689 }
6690
6691 Ok(code)
6692 }
6693}
6694
6695fn try_thumb_expand_imm(value: u32) -> Option<u32> {
6703 if value <= 0xFF {
6705 return Some(value);
6706 }
6707 let b0 = value & 0xFF; let b1 = (value >> 8) & 0xFF; if value == (b0 << 16) | b0 {
6711 return Some(0x100 | b0);
6712 }
6713 if value == (b1 << 24) | (b1 << 8) {
6715 return Some(0x200 | b1);
6716 }
6717 if value == (b0 << 24) | (b0 << 16) | (b0 << 8) | b0 {
6719 return Some(0x300 | b0);
6720 }
6721 for rot in 8..=31u32 {
6725 let unrot = value.rotate_left(rot);
6726 if (0x80..=0xFF).contains(&unrot) {
6727 return Some((rot << 7) | (unrot & 0x7F));
6728 }
6729 }
6730 None
6731}
6732
6733fn check_ldst_imm12(offset: u32) -> Result<()> {
6739 if offset > 0xFFF {
6740 Err(synth_core::Error::synthesis(
6741 "load/store immediate offset > 0xFFF (4095) — materialize the offset into a register",
6742 ))
6743 } else {
6744 Ok(())
6745 }
6746}
6747
6748fn reg_to_bits(reg: &Reg) -> u32 {
6749 match reg {
6750 Reg::R0 => 0,
6751 Reg::R1 => 1,
6752 Reg::R2 => 2,
6753 Reg::R3 => 3,
6754 Reg::R4 => 4,
6755 Reg::R5 => 5,
6756 Reg::R6 => 6,
6757 Reg::R7 => 7,
6758 Reg::R8 => 8,
6759 Reg::R9 => 9,
6760 Reg::R10 => 10,
6761 Reg::R11 => 11,
6762 Reg::R12 => 12,
6763 Reg::SP => 13,
6764 Reg::LR => 14,
6765 Reg::PC => 15,
6766 }
6767}
6768
6769fn reg_bits_checked(bits: u32) -> Result<()> {
6777 if bits > 14 {
6778 return Err(synth_core::Error::synthesis(format!(
6779 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6780 )));
6781 }
6782 Ok(())
6783}
6784
6785fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6788 if val == 0 {
6789 return Some((0, 1));
6790 }
6791 for rot in 0..16u32 {
6792 let shift = rot * 2;
6793 let unrotated = val.rotate_left(shift);
6795 if unrotated <= 0xFF {
6796 return Some(((rot << 8) | unrotated, 1));
6798 }
6799 }
6800 None
6801}
6802
6803fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6808 match op2 {
6809 Operand2::Imm(val) => {
6810 let uval = *val as u32;
6811 if let Some(encoded) = try_encode_rotated_imm(uval) {
6813 encoded
6814 } else {
6815 let imm = uval & 0xFF;
6820 (imm, 1)
6821 }
6822 }
6823
6824 Operand2::Reg(reg) => {
6825 let reg_bits = reg_to_bits(reg);
6826 (reg_bits, 0) }
6828
6829 Operand2::RegShift {
6830 rm,
6831 shift: _,
6832 amount,
6833 } => {
6834 let rm_bits = reg_to_bits(rm);
6836 let shift_bits = (*amount & 0x1F) << 7;
6837 (shift_bits | rm_bits, 0)
6838 }
6839 }
6840}
6841
6842fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6844 let base_bits = reg_to_bits(&addr.base);
6845 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6847}
6848
6849fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6851 match reg {
6852 VfpReg::S0 => Ok(0),
6853 VfpReg::S1 => Ok(1),
6854 VfpReg::S2 => Ok(2),
6855 VfpReg::S3 => Ok(3),
6856 VfpReg::S4 => Ok(4),
6857 VfpReg::S5 => Ok(5),
6858 VfpReg::S6 => Ok(6),
6859 VfpReg::S7 => Ok(7),
6860 VfpReg::S8 => Ok(8),
6861 VfpReg::S9 => Ok(9),
6862 VfpReg::S10 => Ok(10),
6863 VfpReg::S11 => Ok(11),
6864 VfpReg::S12 => Ok(12),
6865 VfpReg::S13 => Ok(13),
6866 VfpReg::S14 => Ok(14),
6867 VfpReg::S15 => Ok(15),
6868 VfpReg::S16 => Ok(16),
6869 VfpReg::S17 => Ok(17),
6870 VfpReg::S18 => Ok(18),
6871 VfpReg::S19 => Ok(19),
6872 VfpReg::S20 => Ok(20),
6873 VfpReg::S21 => Ok(21),
6874 VfpReg::S22 => Ok(22),
6875 VfpReg::S23 => Ok(23),
6876 VfpReg::S24 => Ok(24),
6877 VfpReg::S25 => Ok(25),
6878 VfpReg::S26 => Ok(26),
6879 VfpReg::S27 => Ok(27),
6880 VfpReg::S28 => Ok(28),
6881 VfpReg::S29 => Ok(29),
6882 VfpReg::S30 => Ok(30),
6883 VfpReg::S31 => Ok(31),
6884 _ => Err(synth_core::Error::SynthesisError(
6886 "D-register not supported in single-precision VFP encoding".to_string(),
6887 )),
6888 }
6889}
6890
6891fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6893 match reg {
6894 VfpReg::D0 => Ok(0),
6895 VfpReg::D1 => Ok(1),
6896 VfpReg::D2 => Ok(2),
6897 VfpReg::D3 => Ok(3),
6898 VfpReg::D4 => Ok(4),
6899 VfpReg::D5 => Ok(5),
6900 VfpReg::D6 => Ok(6),
6901 VfpReg::D7 => Ok(7),
6902 VfpReg::D8 => Ok(8),
6903 VfpReg::D9 => Ok(9),
6904 VfpReg::D10 => Ok(10),
6905 VfpReg::D11 => Ok(11),
6906 VfpReg::D12 => Ok(12),
6907 VfpReg::D13 => Ok(13),
6908 VfpReg::D14 => Ok(14),
6909 VfpReg::D15 => Ok(15),
6910 _ => Err(synth_core::Error::SynthesisError(
6912 "S-register not supported in double-precision VFP encoding".to_string(),
6913 )),
6914 }
6915}
6916
6917fn encode_sreg(s: u32) -> (u32, u32) {
6921 (s >> 1, s & 1)
6922}
6923
6924fn encode_dreg(d: u32) -> (u32, u32) {
6928 (d & 0xF, (d >> 4) & 1)
6929}
6930
6931fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6937 let sd_num = vfp_sreg_to_num(sd)?;
6938 let sn_num = vfp_sreg_to_num(sn)?;
6939 let sm_num = vfp_sreg_to_num(sm)?;
6940 let (vd, d) = encode_sreg(sd_num);
6941 let (vn, n) = encode_sreg(sn_num);
6942 let (vm, m) = encode_sreg(sm_num);
6943
6944 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6945}
6946
6947fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6950 let sd_num = vfp_sreg_to_num(sd)?;
6951 let sm_num = vfp_sreg_to_num(sm)?;
6952 let (vd, d) = encode_sreg(sd_num);
6953 let (vm, m) = encode_sreg(sm_num);
6954
6955 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6956}
6957
6958fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6962 let sd_num = vfp_sreg_to_num(sd)?;
6963 let (vd, d) = encode_sreg(sd_num);
6964 let rn = reg_to_bits(&addr.base);
6965
6966 let offset = addr.offset;
6967 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6968 let abs_offset = offset.unsigned_abs();
6969 let imm8 = (abs_offset / 4) & 0xFF;
6970
6971 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6972}
6973
6974fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6978 let s_num = vfp_sreg_to_num(sreg)?;
6979 let (vn, n) = encode_sreg(s_num);
6980 let rt = reg_to_bits(core);
6981
6982 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6983 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6984}
6985
6986fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6990 let dd_num = vfp_dreg_to_num(dd)?;
6991 let dn_num = vfp_dreg_to_num(dn)?;
6992 let dm_num = vfp_dreg_to_num(dm)?;
6993 let (vd, d) = encode_dreg(dd_num);
6994 let (vn, n) = encode_dreg(dn_num);
6995 let (vm, m) = encode_dreg(dm_num);
6996
6997 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6998}
6999
7000fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
7002 let dd_num = vfp_dreg_to_num(dd)?;
7003 let dm_num = vfp_dreg_to_num(dm)?;
7004 let (vd, d) = encode_dreg(dd_num);
7005 let (vm, m) = encode_dreg(dm_num);
7006
7007 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
7008}
7009
7010fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
7013 let dd_num = vfp_dreg_to_num(dd)?;
7014 let (vd, d) = encode_dreg(dd_num);
7015 let rn = reg_to_bits(&addr.base);
7016
7017 let offset = addr.offset;
7018 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7019 let abs_offset = offset.unsigned_abs();
7020 let imm8 = (abs_offset / 4) & 0xFF;
7021
7022 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
7023}
7024
7025fn encode_vmov_core_dreg(
7029 to_dreg: bool,
7030 dreg: &VfpReg,
7031 core_lo: &Reg,
7032 core_hi: &Reg,
7033) -> Result<u32> {
7034 let d_num = vfp_dreg_to_num(dreg)?;
7035 let (vm, m) = encode_dreg(d_num);
7036 let rt = reg_to_bits(core_lo);
7037 let rt2 = reg_to_bits(core_hi);
7038
7039 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
7040 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
7041}
7042
7043fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
7045 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
7046 let hw2 = (instr & 0xFFFF) as u16;
7047 let mut bytes = hw1.to_le_bytes().to_vec();
7048 bytes.extend_from_slice(&hw2.to_le_bytes());
7049 bytes
7050}
7051
7052fn qreg_to_num(reg: &QReg) -> u32 {
7058 match reg {
7059 QReg::Q0 => 0,
7060 QReg::Q1 => 1,
7061 QReg::Q2 => 2,
7062 QReg::Q3 => 3,
7063 QReg::Q4 => 4,
7064 QReg::Q5 => 5,
7065 QReg::Q6 => 6,
7066 QReg::Q7 => 7,
7067 }
7068}
7069
7070fn mve_size_bits(size: &MveSize) -> u32 {
7072 match size {
7073 MveSize::S8 => 0b00,
7074 MveSize::S16 => 0b01,
7075 MveSize::S32 => 0b10,
7076 }
7077}
7078
7079fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7083 let d = qreg_to_num(qd) * 2;
7084 let n = qreg_to_num(qn) * 2;
7085 let m = qreg_to_num(qm) * 2;
7086
7087 let vd = d & 0xF;
7092 let d_bit = (d >> 4) & 1;
7093 let vn = n & 0xF;
7094 let n_bit = (n >> 4) & 1;
7095 let vm = m & 0xF;
7096 let m_bit = (m >> 4) & 1;
7097
7098 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
7099}
7100
7101fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
7103 encode_mve_3reg(base, qd, qn, qm)
7104}
7105
7106fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
7109 let qd_enc = qreg_to_num(qd) * 2;
7110 let rn = reg_to_bits(&addr.base);
7111 let offset = addr.offset;
7112 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7113 let abs_offset = offset.unsigned_abs();
7114 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
7118 | (u_bit << 23)
7119 | ((qd_enc >> 4) << 22)
7120 | (rn << 16)
7121 | ((qd_enc & 0xF) << 12)
7122 | (imm7 & 0x7F)
7123}
7124
7125fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
7127 let qd_enc = qreg_to_num(qd) * 2;
7128 let rn = reg_to_bits(&addr.base);
7129 let offset = addr.offset;
7130 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
7131 let abs_offset = offset.unsigned_abs();
7132 let imm7 = (abs_offset / 4) & 0x7F;
7133
7134 0xED000E80
7135 | (u_bit << 23)
7136 | ((qd_enc >> 4) << 22)
7137 | (rn << 16)
7138 | ((qd_enc & 0xF) << 12)
7139 | (imm7 & 0x7F)
7140}
7141
7142impl ArmEncoder {
7143 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
7145 let mut result = Vec::new();
7146 let qd_num = qreg_to_num(qd);
7147
7148 for i in 0..4 {
7150 let word = u32::from_le_bytes([
7151 bytes[i * 4],
7152 bytes[i * 4 + 1],
7153 bytes[i * 4 + 2],
7154 bytes[i * 4 + 3],
7155 ]);
7156 let lo16 = word & 0xFFFF;
7157 let hi16 = (word >> 16) & 0xFFFF;
7158
7159 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
7161 if hi16 != 0 {
7163 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
7164 }
7165
7166 let s_num = qd_num * 4 + i as u32;
7168 let (vn, n) = encode_sreg(s_num);
7169 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
7170 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
7171 }
7172
7173 Ok(result)
7174 }
7175
7176 fn encode_thumb_mve_lane_wise_f32_binop(
7178 &self,
7179 qd: &QReg,
7180 qn: &QReg,
7181 qm: &QReg,
7182 vfp_base: u32,
7183 ) -> Result<Vec<u8>> {
7184 let mut result = Vec::new();
7185 let qd_num = qreg_to_num(qd);
7186 let qn_num = qreg_to_num(qn);
7187 let qm_num = qreg_to_num(qm);
7188
7189 for i in 0..4u32 {
7191 let sd = qd_num * 4 + i;
7192 let sn = qn_num * 4 + i;
7193 let sm = qm_num * 4 + i;
7194
7195 let (vd, d) = encode_sreg(sd);
7196 let (vn, n) = encode_sreg(sn);
7197 let (vm, m) = encode_sreg(sm);
7198
7199 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7200 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7201 }
7202
7203 Ok(result)
7204 }
7205
7206 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7208 let mut result = Vec::new();
7209 let qd_num = qreg_to_num(qd);
7210 let qm_num = qreg_to_num(qm);
7211
7212 for i in 0..4u32 {
7214 let sd = qd_num * 4 + i;
7215 let sm = qm_num * 4 + i;
7216
7217 let (vd, d) = encode_sreg(sd);
7218 let (vm, m) = encode_sreg(sm);
7219
7220 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7221 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7222 }
7223
7224 Ok(result)
7225 }
7226}
7227
7228#[cfg(test)]
7229mod tests {
7230 use super::*;
7231
7232 #[test]
7233 fn test_encoder_creation() {
7234 let encoder_arm = ArmEncoder::new_arm32();
7235 assert!(!encoder_arm.thumb_mode);
7236
7237 let encoder_thumb = ArmEncoder::new_thumb2();
7238 assert!(encoder_thumb.thumb_mode);
7239 }
7240
7241 #[test]
7248 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7249 use synth_synthesis::{ArmOp, Condition, Reg};
7250 let enc = ArmEncoder::new_thumb2();
7251 let hi = enc
7253 .encode(&ArmOp::SetCond {
7254 rd: Reg::R12,
7255 cond: Condition::NE,
7256 })
7257 .unwrap();
7258 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7259 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7261 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7262 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7263 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7264 let lo = enc
7266 .encode(&ArmOp::SetCond {
7267 rd: Reg::R0,
7268 cond: Condition::NE,
7269 })
7270 .unwrap();
7271 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7272 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7273 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7274 }
7275
7276 #[test]
7280 fn test_encode_umull_209b() {
7281 use synth_synthesis::{ArmOp, Reg};
7282 let op = ArmOp::Umull {
7283 rdlo: Reg::R4,
7284 rdhi: Reg::R5,
7285 rn: Reg::R0,
7286 rm: Reg::R3,
7287 };
7288 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7290 assert_eq!(
7291 t,
7292 vec![0xA0, 0xFB, 0x03, 0x45],
7293 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7294 );
7295 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7297 assert_eq!(
7298 a,
7299 0xE085_4390u32.to_le_bytes().to_vec(),
7300 "umull (A32): {a:02x?}"
7301 );
7302 }
7303
7304 #[test]
7311 fn test_encode_arm32_indexed_load_keeps_index_206() {
7312 use synth_synthesis::{ArmOp, MemAddr, Reg};
7313 let enc = ArmEncoder::new_arm32();
7314 let bytes = enc
7316 .encode(&ArmOp::Ldr {
7317 rd: Reg::R0,
7318 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7319 })
7320 .unwrap();
7321 assert_eq!(
7322 bytes.len(),
7323 8,
7324 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7325 );
7326 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7327 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7328 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7330 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7332 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7334 }
7335
7336 #[test]
7343 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7344 let encoder = ArmEncoder::new_thumb2();
7345
7346 let code = encoder
7348 .encode(&ArmOp::Add {
7349 rd: Reg::R12,
7350 rn: Reg::R12,
7351 op2: Operand2::Reg(Reg::R0),
7352 })
7353 .unwrap();
7354 assert_eq!(
7356 code,
7357 vec![0x0C, 0xEB, 0x00, 0x0C],
7358 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7359 );
7360 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7362
7363 let lo = encoder
7365 .encode(&ArmOp::Add {
7366 rd: Reg::R1,
7367 rn: Reg::R2,
7368 op2: Operand2::Reg(Reg::R3),
7369 })
7370 .unwrap();
7371 assert_eq!(
7372 lo.len(),
7373 2,
7374 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7375 );
7376 }
7377
7378 #[test]
7381 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7382 let encoder = ArmEncoder::new_thumb2();
7383
7384 let adds = encoder
7386 .encode(&ArmOp::Adds {
7387 rd: Reg::R10,
7388 rn: Reg::R10,
7389 op2: Operand2::Reg(Reg::R8),
7390 })
7391 .unwrap();
7392 assert_eq!(
7393 adds,
7394 vec![0x1A, 0xEB, 0x08, 0x0A],
7395 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7396 );
7397
7398 let subs = encoder
7400 .encode(&ArmOp::Subs {
7401 rd: Reg::R10,
7402 rn: Reg::R10,
7403 op2: Operand2::Reg(Reg::R8),
7404 })
7405 .unwrap();
7406 assert_eq!(
7407 subs,
7408 vec![0xBA, 0xEB, 0x08, 0x0A],
7409 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7410 );
7411 }
7412
7413 #[test]
7416 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7417 let encoder = ArmEncoder::new_thumb2();
7418
7419 let cmn = encoder
7421 .encode(&ArmOp::Cmn {
7422 rn: Reg::R10,
7423 op2: Operand2::Reg(Reg::R8),
7424 })
7425 .unwrap();
7426 assert_eq!(
7427 cmn,
7428 vec![0x1A, 0xEB, 0x08, 0x0F],
7429 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7430 );
7431
7432 let lo = encoder
7434 .encode(&ArmOp::Cmn {
7435 rn: Reg::R1,
7436 op2: Operand2::Reg(Reg::R2),
7437 })
7438 .unwrap();
7439 assert_eq!(
7440 lo.len(),
7441 2,
7442 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7443 );
7444 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7445 }
7446
7447 #[test]
7451 fn test_encode_pc_operand_returns_err_not_panic_185() {
7452 let encoder = ArmEncoder::new_thumb2();
7453 for op in [
7454 ArmOp::Sdiv {
7455 rd: Reg::PC,
7456 rn: Reg::R0,
7457 rm: Reg::R1,
7458 },
7459 ArmOp::Udiv {
7460 rd: Reg::R0,
7461 rn: Reg::PC,
7462 rm: Reg::R1,
7463 },
7464 ArmOp::Sdiv {
7465 rd: Reg::R0,
7466 rn: Reg::R1,
7467 rm: Reg::PC,
7468 },
7469 ] {
7470 let r = encoder.encode(&op);
7471 assert!(
7472 r.is_err(),
7473 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7474 );
7475 }
7476 assert!(
7478 encoder
7479 .encode(&ArmOp::Sdiv {
7480 rd: Reg::R0,
7481 rn: Reg::R1,
7482 rm: Reg::R2
7483 })
7484 .is_ok()
7485 );
7486 }
7487
7488 #[test]
7489 fn test_encode_nop_arm32() {
7490 let encoder = ArmEncoder::new_arm32();
7491 let code = encoder.encode(&ArmOp::Nop).unwrap();
7492
7493 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7496
7497 #[test]
7498 fn test_encode_nop_thumb() {
7499 let encoder = ArmEncoder::new_thumb2();
7500 let code = encoder.encode(&ArmOp::Nop).unwrap();
7501
7502 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7505
7506 #[test]
7507 fn test_encode_mov_immediate_arm32() {
7508 let encoder = ArmEncoder::new_arm32();
7509 let op = ArmOp::Mov {
7510 rd: Reg::R0,
7511 op2: Operand2::Imm(42),
7512 };
7513
7514 let code = encoder.encode(&op).unwrap();
7515 assert_eq!(code.len(), 4);
7516
7517 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7519 assert_eq!(instr & 0x0E000000, 0x02000000); }
7521
7522 #[test]
7523 fn test_encode_add_registers_arm32() {
7524 let encoder = ArmEncoder::new_arm32();
7525 let op = ArmOp::Add {
7526 rd: Reg::R0,
7527 rn: Reg::R1,
7528 op2: Operand2::Reg(Reg::R2),
7529 };
7530
7531 let code = encoder.encode(&op).unwrap();
7532 assert_eq!(code.len(), 4);
7533
7534 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7535 assert_eq!(instr & 0x0FE00000, 0x00800000);
7537 }
7538
7539 #[test]
7540 fn test_encode_ldr_arm32() {
7541 let encoder = ArmEncoder::new_arm32();
7542 let op = ArmOp::Ldr {
7543 rd: Reg::R0,
7544 addr: MemAddr::imm(Reg::R1, 4),
7545 };
7546
7547 let code = encoder.encode(&op).unwrap();
7548 assert_eq!(code.len(), 4);
7549
7550 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7551 assert_eq!(instr & 0x00100000, 0x00100000);
7553 }
7554
7555 #[test]
7556 fn test_encode_str_arm32() {
7557 let encoder = ArmEncoder::new_arm32();
7558 let op = ArmOp::Str {
7559 rd: Reg::R0,
7560 addr: MemAddr::imm(Reg::SP, 0),
7561 };
7562
7563 let code = encoder.encode(&op).unwrap();
7564 assert_eq!(code.len(), 4);
7565 }
7566
7567 #[test]
7568 fn test_encode_branch_arm32() {
7569 let encoder = ArmEncoder::new_arm32();
7570 let op = ArmOp::Bl {
7571 label: "main".to_string(),
7572 };
7573
7574 let code = encoder.encode(&op).unwrap();
7575 assert_eq!(code.len(), 4);
7576
7577 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7578 assert_eq!(instr & 0x0F000000, 0x0B000000);
7580 }
7581
7582 #[test]
7592 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7593 let encoder = ArmEncoder::new_thumb2();
7594 let op = ArmOp::Bl {
7595 label: "callee".to_string(),
7596 };
7597
7598 let code = encoder.encode(&op).unwrap();
7599 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7600
7601 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7602 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7603 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7604 assert_eq!(
7605 hw2, 0xFFFE,
7606 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7607 );
7608 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7609 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7610 }
7611
7612 #[test]
7613 fn test_encode_sequence() {
7614 let encoder = ArmEncoder::new_arm32();
7615 let ops = vec![
7616 ArmOp::Mov {
7617 rd: Reg::R0,
7618 op2: Operand2::Imm(42),
7619 },
7620 ArmOp::Mov {
7621 rd: Reg::R1,
7622 op2: Operand2::Imm(10),
7623 },
7624 ArmOp::Add {
7625 rd: Reg::R2,
7626 rn: Reg::R0,
7627 op2: Operand2::Reg(Reg::R1),
7628 },
7629 ];
7630
7631 let code = encoder.encode_sequence(&ops).unwrap();
7632 assert_eq!(code.len(), 12); }
7634
7635 #[test]
7636 fn test_reg_to_bits() {
7637 assert_eq!(reg_to_bits(&Reg::R0), 0);
7638 assert_eq!(reg_to_bits(&Reg::R7), 7);
7639 assert_eq!(reg_to_bits(&Reg::SP), 13);
7640 assert_eq!(reg_to_bits(&Reg::LR), 14);
7641 assert_eq!(reg_to_bits(&Reg::PC), 15);
7642 }
7643
7644 #[test]
7645 fn test_encode_bitwise_operations() {
7646 let encoder = ArmEncoder::new_arm32();
7647
7648 let and_op = ArmOp::And {
7649 rd: Reg::R0,
7650 rn: Reg::R1,
7651 op2: Operand2::Reg(Reg::R2),
7652 };
7653 let and_code = encoder.encode(&and_op).unwrap();
7654 assert_eq!(and_code.len(), 4);
7655
7656 let orr_op = ArmOp::Orr {
7657 rd: Reg::R0,
7658 rn: Reg::R1,
7659 op2: Operand2::Reg(Reg::R2),
7660 };
7661 let orr_code = encoder.encode(&orr_op).unwrap();
7662 assert_eq!(orr_code.len(), 4);
7663
7664 let eor_op = ArmOp::Eor {
7665 rd: Reg::R0,
7666 rn: Reg::R1,
7667 op2: Operand2::Reg(Reg::R2),
7668 };
7669 let eor_code = encoder.encode(&eor_op).unwrap();
7670 assert_eq!(eor_code.len(), 4);
7671 }
7672
7673 #[test]
7676 fn test_encode_sdiv_thumb2() {
7677 let encoder = ArmEncoder::new_thumb2();
7678 let op = ArmOp::Sdiv {
7679 rd: Reg::R0,
7680 rn: Reg::R1,
7681 rm: Reg::R2,
7682 };
7683
7684 let code = encoder.encode(&op).unwrap();
7685 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7692 assert_eq!(code[1], 0xFB);
7693 assert_eq!(code[2], 0xF2);
7694 assert_eq!(code[3], 0xF0);
7695 }
7696
7697 #[test]
7698 fn test_encode_udiv_thumb2() {
7699 let encoder = ArmEncoder::new_thumb2();
7700 let op = ArmOp::Udiv {
7701 rd: Reg::R0,
7702 rn: Reg::R1,
7703 rm: Reg::R2,
7704 };
7705
7706 let code = encoder.encode(&op).unwrap();
7707 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7712 assert_eq!(code[1], 0xFB);
7713 assert_eq!(code[2], 0xF2);
7714 assert_eq!(code[3], 0xF0);
7715 }
7716
7717 #[test]
7718 fn test_encode_mul_thumb2() {
7719 let encoder = ArmEncoder::new_thumb2();
7720 let op = ArmOp::Mul {
7721 rd: Reg::R0,
7722 rn: Reg::R1,
7723 rm: Reg::R2,
7724 };
7725
7726 let code = encoder.encode(&op).unwrap();
7727 assert_eq!(code.len(), 4); }
7729
7730 #[test]
7731 fn test_encode_and_thumb2() {
7732 let encoder = ArmEncoder::new_thumb2();
7733 let op = ArmOp::And {
7734 rd: Reg::R0,
7735 rn: Reg::R1,
7736 op2: Operand2::Reg(Reg::R2),
7737 };
7738
7739 let code = encoder.encode(&op).unwrap();
7740 assert_eq!(code.len(), 4); }
7742
7743 #[test]
7744 fn test_encode_lsl_thumb2_low_regs() {
7745 let encoder = ArmEncoder::new_thumb2();
7746 let op = ArmOp::Lsl {
7747 rd: Reg::R0,
7748 rn: Reg::R1,
7749 shift: 5,
7750 };
7751
7752 let code = encoder.encode(&op).unwrap();
7753 assert_eq!(code.len(), 2); }
7755
7756 #[test]
7757 fn test_encode_clz_thumb2() {
7758 let encoder = ArmEncoder::new_thumb2();
7759 let op = ArmOp::Clz {
7760 rd: Reg::R0,
7761 rm: Reg::R1,
7762 };
7763
7764 let code = encoder.encode(&op).unwrap();
7765 assert_eq!(code.len(), 4); }
7767
7768 #[test]
7769 fn test_encode_bx_thumb2() {
7770 let encoder = ArmEncoder::new_thumb2();
7771 let op = ArmOp::Bx { rm: Reg::LR };
7772
7773 let code = encoder.encode(&op).unwrap();
7774 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7778 }
7779
7780 #[test]
7785 fn test_encode_f32_abs_arm32() {
7786 let encoder = ArmEncoder::new_arm32();
7787 let op = ArmOp::F32Abs {
7788 sd: VfpReg::S0,
7789 sm: VfpReg::S2,
7790 };
7791 let code = encoder.encode(&op).unwrap();
7792 assert_eq!(code.len(), 4); }
7794
7795 #[test]
7796 fn test_encode_f32_neg_arm32() {
7797 let encoder = ArmEncoder::new_arm32();
7798 let op = ArmOp::F32Neg {
7799 sd: VfpReg::S0,
7800 sm: VfpReg::S2,
7801 };
7802 let code = encoder.encode(&op).unwrap();
7803 assert_eq!(code.len(), 4);
7804 }
7805
7806 #[test]
7807 fn test_encode_f32_sqrt_arm32() {
7808 let encoder = ArmEncoder::new_arm32();
7809 let op = ArmOp::F32Sqrt {
7810 sd: VfpReg::S0,
7811 sm: VfpReg::S2,
7812 };
7813 let code = encoder.encode(&op).unwrap();
7814 assert_eq!(code.len(), 4);
7815 }
7816
7817 #[test]
7818 fn test_encode_f32_ceil_arm32() {
7819 let encoder = ArmEncoder::new_arm32();
7820 let op = ArmOp::F32Ceil {
7821 sd: VfpReg::S0,
7822 sm: VfpReg::S2,
7823 };
7824 let code = encoder.encode(&op).unwrap();
7825 assert_eq!(code.len(), 36);
7827 }
7828
7829 #[test]
7830 fn test_encode_f32_floor_thumb2() {
7831 let encoder = ArmEncoder::new_thumb2();
7832 let op = ArmOp::F32Floor {
7833 sd: VfpReg::S0,
7834 sm: VfpReg::S2,
7835 };
7836 let code = encoder.encode(&op).unwrap();
7837 assert_eq!(code.len(), 36);
7839 }
7840
7841 #[test]
7842 fn test_encode_f32_min_arm32() {
7843 let encoder = ArmEncoder::new_arm32();
7844 let op = ArmOp::F32Min {
7845 sd: VfpReg::S0,
7846 sn: VfpReg::S2,
7847 sm: VfpReg::S4,
7848 };
7849 let code = encoder.encode(&op).unwrap();
7850 assert_eq!(code.len(), 16); }
7852
7853 #[test]
7854 fn test_encode_f32_max_thumb2() {
7855 let encoder = ArmEncoder::new_thumb2();
7856 let op = ArmOp::F32Max {
7857 sd: VfpReg::S0,
7858 sn: VfpReg::S2,
7859 sm: VfpReg::S4,
7860 };
7861 let code = encoder.encode(&op).unwrap();
7862 assert_eq!(code.len(), 18);
7864 }
7865
7866 #[test]
7867 fn test_encode_f32_copysign_arm32() {
7868 let encoder = ArmEncoder::new_arm32();
7869 let op = ArmOp::F32Copysign {
7870 sd: VfpReg::S0,
7871 sn: VfpReg::S2,
7872 sm: VfpReg::S4,
7873 };
7874 let code = encoder.encode(&op).unwrap();
7875 assert_eq!(code.len(), 24);
7877 }
7878
7879 #[test]
7884 fn test_encode_f64_add_arm32() {
7885 let encoder = ArmEncoder::new_arm32();
7886 let op = ArmOp::F64Add {
7887 dd: VfpReg::D0,
7888 dn: VfpReg::D1,
7889 dm: VfpReg::D2,
7890 };
7891 let code = encoder.encode(&op).unwrap();
7892 assert_eq!(code.len(), 4);
7893 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7895 assert_eq!((instr >> 8) & 0xF, 0xB); }
7897
7898 #[test]
7899 fn test_encode_f64_sub_thumb2() {
7900 let encoder = ArmEncoder::new_thumb2();
7901 let op = ArmOp::F64Sub {
7902 dd: VfpReg::D0,
7903 dn: VfpReg::D1,
7904 dm: VfpReg::D2,
7905 };
7906 let code = encoder.encode(&op).unwrap();
7907 assert_eq!(code.len(), 4); }
7909
7910 #[test]
7911 fn test_encode_f64_mul_arm32() {
7912 let encoder = ArmEncoder::new_arm32();
7913 let op = ArmOp::F64Mul {
7914 dd: VfpReg::D0,
7915 dn: VfpReg::D1,
7916 dm: VfpReg::D2,
7917 };
7918 let code = encoder.encode(&op).unwrap();
7919 assert_eq!(code.len(), 4);
7920 }
7921
7922 #[test]
7923 fn test_encode_f64_div_arm32() {
7924 let encoder = ArmEncoder::new_arm32();
7925 let op = ArmOp::F64Div {
7926 dd: VfpReg::D0,
7927 dn: VfpReg::D1,
7928 dm: VfpReg::D2,
7929 };
7930 let code = encoder.encode(&op).unwrap();
7931 assert_eq!(code.len(), 4);
7932 }
7933
7934 #[test]
7935 fn test_encode_f64_abs_arm32() {
7936 let encoder = ArmEncoder::new_arm32();
7937 let op = ArmOp::F64Abs {
7938 dd: VfpReg::D0,
7939 dm: VfpReg::D2,
7940 };
7941 let code = encoder.encode(&op).unwrap();
7942 assert_eq!(code.len(), 4);
7943 }
7944
7945 #[test]
7946 fn test_encode_f64_neg_arm32() {
7947 let encoder = ArmEncoder::new_arm32();
7948 let op = ArmOp::F64Neg {
7949 dd: VfpReg::D0,
7950 dm: VfpReg::D2,
7951 };
7952 let code = encoder.encode(&op).unwrap();
7953 assert_eq!(code.len(), 4);
7954 }
7955
7956 #[test]
7957 fn test_encode_f64_sqrt_arm32() {
7958 let encoder = ArmEncoder::new_arm32();
7959 let op = ArmOp::F64Sqrt {
7960 dd: VfpReg::D0,
7961 dm: VfpReg::D2,
7962 };
7963 let code = encoder.encode(&op).unwrap();
7964 assert_eq!(code.len(), 4);
7965 }
7966
7967 #[test]
7968 fn test_encode_f64_load_arm32() {
7969 let encoder = ArmEncoder::new_arm32();
7970 let op = ArmOp::F64Load {
7971 dd: VfpReg::D0,
7972 addr: MemAddr::imm(Reg::R0, 8),
7973 };
7974 let code = encoder.encode(&op).unwrap();
7975 assert_eq!(code.len(), 4);
7976 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7977 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7980
7981 #[test]
7982 fn test_encode_f64_store_thumb2() {
7983 let encoder = ArmEncoder::new_thumb2();
7984 let op = ArmOp::F64Store {
7985 dd: VfpReg::D0,
7986 addr: MemAddr::imm(Reg::SP, 0),
7987 };
7988 let code = encoder.encode(&op).unwrap();
7989 assert_eq!(code.len(), 4);
7990 }
7991
7992 #[test]
7993 fn test_encode_f64_compare_arm32() {
7994 let encoder = ArmEncoder::new_arm32();
7995 let op = ArmOp::F64Eq {
7996 rd: Reg::R0,
7997 dn: VfpReg::D0,
7998 dm: VfpReg::D1,
7999 };
8000 let code = encoder.encode(&op).unwrap();
8001 assert_eq!(code.len(), 16); }
8003
8004 #[test]
8005 fn test_encode_f64_compare_thumb2() {
8006 let encoder = ArmEncoder::new_thumb2();
8007 let op = ArmOp::F64Lt {
8008 rd: Reg::R0,
8009 dn: VfpReg::D0,
8010 dm: VfpReg::D1,
8011 };
8012 let code = encoder.encode(&op).unwrap();
8013 assert_eq!(code.len(), 14);
8015 }
8016
8017 #[test]
8018 fn test_encode_f64_const_arm32() {
8019 let encoder = ArmEncoder::new_arm32();
8020 let op = ArmOp::F64Const {
8021 dd: VfpReg::D0,
8022 value: 3.125,
8023 };
8024 let code = encoder.encode(&op).unwrap();
8025 assert_eq!(code.len(), 20);
8027 }
8028
8029 #[test]
8030 fn test_encode_f64_const_thumb2() {
8031 let encoder = ArmEncoder::new_thumb2();
8032 let op = ArmOp::F64Const {
8033 dd: VfpReg::D0,
8034 value: 2.5,
8035 };
8036 let code = encoder.encode(&op).unwrap();
8037 assert_eq!(code.len(), 20);
8039 }
8040
8041 #[test]
8042 fn test_encode_f64_convert_i32s_arm32() {
8043 let encoder = ArmEncoder::new_arm32();
8044 let op = ArmOp::F64ConvertI32S {
8045 dd: VfpReg::D0,
8046 rm: Reg::R0,
8047 };
8048 let code = encoder.encode(&op).unwrap();
8049 assert_eq!(code.len(), 8);
8051 }
8052
8053 #[test]
8054 fn test_encode_f64_promote_f32_arm32() {
8055 let encoder = ArmEncoder::new_arm32();
8056 let op = ArmOp::F64PromoteF32 {
8057 dd: VfpReg::D0,
8058 sm: VfpReg::S0,
8059 };
8060 let code = encoder.encode(&op).unwrap();
8061 assert_eq!(code.len(), 4); }
8063
8064 #[test]
8065 fn test_encode_f64_promote_f32_thumb2() {
8066 let encoder = ArmEncoder::new_thumb2();
8067 let op = ArmOp::F64PromoteF32 {
8068 dd: VfpReg::D0,
8069 sm: VfpReg::S0,
8070 };
8071 let code = encoder.encode(&op).unwrap();
8072 assert_eq!(code.len(), 4);
8073 }
8074
8075 #[test]
8076 fn test_encode_i32_trunc_f64s_arm32() {
8077 let encoder = ArmEncoder::new_arm32();
8078 let op = ArmOp::I32TruncF64S {
8079 rd: Reg::R0,
8080 dm: VfpReg::D0,
8081 };
8082 let code = encoder.encode(&op).unwrap();
8083 assert_eq!(code.len(), 8);
8085 }
8086
8087 #[test]
8088 fn test_encode_f64_reinterpret_i64_arm32() {
8089 let encoder = ArmEncoder::new_arm32();
8090 let op = ArmOp::F64ReinterpretI64 {
8091 dd: VfpReg::D0,
8092 rmlo: Reg::R0,
8093 rmhi: Reg::R1,
8094 };
8095 let code = encoder.encode(&op).unwrap();
8096 assert_eq!(code.len(), 4); }
8098
8099 #[test]
8100 fn test_encode_i64_reinterpret_f64_thumb2() {
8101 let encoder = ArmEncoder::new_thumb2();
8102 let op = ArmOp::I64ReinterpretF64 {
8103 rdlo: Reg::R0,
8104 rdhi: Reg::R1,
8105 dm: VfpReg::D0,
8106 };
8107 let code = encoder.encode(&op).unwrap();
8108 assert_eq!(code.len(), 4);
8109 }
8110
8111 #[test]
8112 fn test_encode_f64_trunc_thumb2() {
8113 let encoder = ArmEncoder::new_thumb2();
8114 let op = ArmOp::F64Trunc {
8115 dd: VfpReg::D0,
8116 dm: VfpReg::D1,
8117 };
8118 let code = encoder.encode(&op).unwrap();
8119 assert_eq!(code.len(), 8);
8121 }
8122
8123 #[test]
8124 fn test_encode_f64_min_arm32() {
8125 let encoder = ArmEncoder::new_arm32();
8126 let op = ArmOp::F64Min {
8127 dd: VfpReg::D0,
8128 dn: VfpReg::D1,
8129 dm: VfpReg::D2,
8130 };
8131 let code = encoder.encode(&op).unwrap();
8132 assert_eq!(code.len(), 16);
8134 }
8135
8136 #[test]
8137 fn test_f64_cp11_encoding() {
8138 let encoder = ArmEncoder::new_arm32();
8140
8141 let code = encoder
8143 .encode(&ArmOp::F64Add {
8144 dd: VfpReg::D0,
8145 dn: VfpReg::D0,
8146 dm: VfpReg::D0,
8147 })
8148 .unwrap();
8149 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8150 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
8151
8152 let code = encoder
8154 .encode(&ArmOp::F32Add {
8155 sd: VfpReg::S0,
8156 sn: VfpReg::S0,
8157 sm: VfpReg::S0,
8158 })
8159 .unwrap();
8160 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8161 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
8162 }
8163
8164 #[test]
8165 fn test_dreg_encoding_higher_registers() {
8166 let encoder = ArmEncoder::new_arm32();
8167
8168 let op = ArmOp::F64Add {
8170 dd: VfpReg::D15,
8171 dn: VfpReg::D14,
8172 dm: VfpReg::D13,
8173 };
8174 let code = encoder.encode(&op).unwrap();
8175 assert_eq!(code.len(), 4);
8176
8177 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8179 assert_eq!((instr >> 8) & 0xF, 0xB); }
8181
8182 #[test]
8187 fn test_encode_label_emits_no_bytes() {
8188 let encoder = ArmEncoder::new_thumb2();
8189 let op = ArmOp::Label {
8190 name: ".Lblock_end_0".to_string(),
8191 };
8192 let code = encoder.encode(&op).unwrap();
8193 assert!(code.is_empty(), "Label should emit zero bytes");
8194
8195 let encoder32 = ArmEncoder::new_arm32();
8196 let code32 = encoder32.encode(&op).unwrap();
8197 assert!(
8198 code32.is_empty(),
8199 "Label should emit zero bytes in ARM32 too"
8200 );
8201 }
8202
8203 #[test]
8204 fn test_encode_bcc_eq_thumb2() {
8205 use synth_synthesis::Condition;
8206 let encoder = ArmEncoder::new_thumb2();
8207 let op = ArmOp::Bcc {
8208 cond: Condition::EQ,
8209 label: "target".to_string(),
8210 };
8211 let code = encoder.encode(&op).unwrap();
8212 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8216 }
8217
8218 #[test]
8219 fn test_encode_bcc_ne_thumb2() {
8220 use synth_synthesis::Condition;
8221 let encoder = ArmEncoder::new_thumb2();
8222 let op = ArmOp::Bcc {
8223 cond: Condition::NE,
8224 label: "target".to_string(),
8225 };
8226 let code = encoder.encode(&op).unwrap();
8227 assert_eq!(code.len(), 2);
8228
8229 assert_eq!(code, vec![0x00, 0xD1]);
8231 }
8232
8233 #[test]
8234 fn test_encode_bcc_arm32() {
8235 use synth_synthesis::Condition;
8236 let encoder = ArmEncoder::new_arm32();
8237 let op = ArmOp::Bcc {
8238 cond: Condition::EQ,
8239 label: "target".to_string(),
8240 };
8241 let code = encoder.encode(&op).unwrap();
8242 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8245 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8249
8250 #[test]
8251 fn test_encode_udf_thumb2() {
8252 let encoder = ArmEncoder::new_thumb2();
8253 let op = ArmOp::Udf { imm: 0 };
8254 let code = encoder.encode(&op).unwrap();
8255 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8259 }
8260
8261 #[test]
8262 fn test_encode_nop_thumb2() {
8263 let encoder = ArmEncoder::new_thumb2();
8264 let op = ArmOp::Nop;
8265 let code = encoder.encode(&op).unwrap();
8266 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8270 }
8271
8272 #[test]
8277 fn test_encode_i64_add_thumb2() {
8278 let encoder = ArmEncoder::new_thumb2();
8279 let op = ArmOp::I64Add {
8280 rdlo: Reg::R0,
8281 rdhi: Reg::R1,
8282 rnlo: Reg::R0,
8283 rnhi: Reg::R1,
8284 rmlo: Reg::R2,
8285 rmhi: Reg::R3,
8286 };
8287 let code = encoder.encode(&op).unwrap();
8288 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8290 }
8291
8292 #[test]
8293 fn test_encode_i64_sub_thumb2() {
8294 let encoder = ArmEncoder::new_thumb2();
8295 let op = ArmOp::I64Sub {
8296 rdlo: Reg::R0,
8297 rdhi: Reg::R1,
8298 rnlo: Reg::R0,
8299 rnhi: Reg::R1,
8300 rmlo: Reg::R2,
8301 rmhi: Reg::R3,
8302 };
8303 let code = encoder.encode(&op).unwrap();
8304 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8306 }
8307
8308 #[test]
8309 fn test_encode_i64_and_thumb2() {
8310 let encoder = ArmEncoder::new_thumb2();
8311 let op = ArmOp::I64And {
8312 rdlo: Reg::R0,
8313 rdhi: Reg::R1,
8314 rnlo: Reg::R0,
8315 rnhi: Reg::R1,
8316 rmlo: Reg::R2,
8317 rmhi: Reg::R3,
8318 };
8319 let code = encoder.encode(&op).unwrap();
8320 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8322 }
8323
8324 #[test]
8325 fn test_encode_i64_or_thumb2() {
8326 let encoder = ArmEncoder::new_thumb2();
8327 let op = ArmOp::I64Or {
8328 rdlo: Reg::R0,
8329 rdhi: Reg::R1,
8330 rnlo: Reg::R0,
8331 rnhi: Reg::R1,
8332 rmlo: Reg::R2,
8333 rmhi: Reg::R3,
8334 };
8335 let code = encoder.encode(&op).unwrap();
8336 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8337 }
8338
8339 #[test]
8340 fn test_encode_i64_xor_thumb2() {
8341 let encoder = ArmEncoder::new_thumb2();
8342 let op = ArmOp::I64Xor {
8343 rdlo: Reg::R0,
8344 rdhi: Reg::R1,
8345 rnlo: Reg::R0,
8346 rnhi: Reg::R1,
8347 rmlo: Reg::R2,
8348 rmhi: Reg::R3,
8349 };
8350 let code = encoder.encode(&op).unwrap();
8351 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8352 }
8353
8354 #[test]
8355 fn test_encode_i64_const_small_thumb2() {
8356 let encoder = ArmEncoder::new_thumb2();
8357 let op = ArmOp::I64Const {
8359 rdlo: Reg::R0,
8360 rdhi: Reg::R1,
8361 value: 42,
8362 };
8363 let code = encoder.encode(&op).unwrap();
8364 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8366 }
8367
8368 #[test]
8369 fn test_encode_i64_const_large_thumb2() {
8370 let encoder = ArmEncoder::new_thumb2();
8371 let op = ArmOp::I64Const {
8373 rdlo: Reg::R0,
8374 rdhi: Reg::R1,
8375 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8376 };
8377 let code = encoder.encode(&op).unwrap();
8378 assert_eq!(
8380 code.len(),
8381 16,
8382 "I64Const with large value should be 16 bytes"
8383 );
8384 }
8385
8386 #[test]
8387 fn test_encode_i64_extend_i32_s_thumb2() {
8388 let encoder = ArmEncoder::new_thumb2();
8389 let op = ArmOp::I64ExtendI32S {
8390 rdlo: Reg::R0,
8391 rdhi: Reg::R1,
8392 rn: Reg::R0,
8393 };
8394 let code = encoder.encode(&op).unwrap();
8395 assert_eq!(
8397 code.len(),
8398 4,
8399 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8400 );
8401 }
8402
8403 #[test]
8404 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8405 let encoder = ArmEncoder::new_thumb2();
8406 let op = ArmOp::I64ExtendI32S {
8407 rdlo: Reg::R0,
8408 rdhi: Reg::R1,
8409 rn: Reg::R2,
8410 };
8411 let code = encoder.encode(&op).unwrap();
8412 assert!(
8414 code.len() >= 6,
8415 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8416 );
8417 }
8418
8419 #[test]
8420 fn test_encode_i64_extend_i32_u_thumb2() {
8421 let encoder = ArmEncoder::new_thumb2();
8422 let op = ArmOp::I64ExtendI32U {
8423 rdlo: Reg::R0,
8424 rdhi: Reg::R1,
8425 rn: Reg::R0,
8426 };
8427 let code = encoder.encode(&op).unwrap();
8428 assert_eq!(
8430 code.len(),
8431 2,
8432 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8433 );
8434 }
8435
8436 #[test]
8437 fn test_encode_i32_wrap_i64_nop_thumb2() {
8438 let encoder = ArmEncoder::new_thumb2();
8439 let op = ArmOp::I32WrapI64 {
8441 rd: Reg::R0,
8442 rnlo: Reg::R0,
8443 };
8444 let code = encoder.encode(&op).unwrap();
8445 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8446 assert_eq!(code, vec![0x00, 0xBF]); }
8448
8449 #[test]
8450 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8451 let encoder = ArmEncoder::new_thumb2();
8452 let op = ArmOp::I32WrapI64 {
8453 rd: Reg::R2,
8454 rnlo: Reg::R0,
8455 };
8456 let code = encoder.encode(&op).unwrap();
8457 assert!(
8459 code.len() >= 2,
8460 "I32WrapI64 diff reg should emit at least 2 bytes"
8461 );
8462 }
8463
8464 #[test]
8465 fn test_encode_i64_eqz_thumb2() {
8466 let encoder = ArmEncoder::new_thumb2();
8467 let op = ArmOp::I64Eqz {
8468 rd: Reg::R0,
8469 rnlo: Reg::R0,
8470 rnhi: Reg::R1,
8471 };
8472 let code = encoder.encode(&op).unwrap();
8473 assert!(
8475 code.len() >= 6,
8476 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8477 );
8478 }
8479
8480 #[test]
8481 fn test_encode_i64_eq_thumb2() {
8482 let encoder = ArmEncoder::new_thumb2();
8483 let op = ArmOp::I64Eq {
8484 rd: Reg::R0,
8485 rnlo: Reg::R0,
8486 rnhi: Reg::R1,
8487 rmlo: Reg::R2,
8488 rmhi: Reg::R3,
8489 };
8490 let code = encoder.encode(&op).unwrap();
8491 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8493 }
8494
8495 #[test]
8496 fn test_encode_i64_ldr_thumb2() {
8497 let encoder = ArmEncoder::new_thumb2();
8498 let op = ArmOp::I64Ldr {
8499 rdlo: Reg::R0,
8500 rdhi: Reg::R1,
8501 addr: MemAddr::imm(Reg::SP, 0),
8502 };
8503 let code = encoder.encode(&op).unwrap();
8504 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8506 }
8507
8508 #[test]
8509 fn test_encode_i64_str_thumb2() {
8510 let encoder = ArmEncoder::new_thumb2();
8511 let op = ArmOp::I64Str {
8512 rdlo: Reg::R0,
8513 rdhi: Reg::R1,
8514 addr: MemAddr::imm(Reg::SP, 0),
8515 };
8516 let code = encoder.encode(&op).unwrap();
8517 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8519 }
8520
8521 #[test]
8522 fn test_encode_i64_all_comparisons_thumb2() {
8523 let encoder = ArmEncoder::new_thumb2();
8524
8525 let ops = vec![
8526 ArmOp::I64Ne {
8527 rd: Reg::R0,
8528 rnlo: Reg::R0,
8529 rnhi: Reg::R1,
8530 rmlo: Reg::R2,
8531 rmhi: Reg::R3,
8532 },
8533 ArmOp::I64LtS {
8534 rd: Reg::R0,
8535 rnlo: Reg::R0,
8536 rnhi: Reg::R1,
8537 rmlo: Reg::R2,
8538 rmhi: Reg::R3,
8539 },
8540 ArmOp::I64LtU {
8541 rd: Reg::R0,
8542 rnlo: Reg::R0,
8543 rnhi: Reg::R1,
8544 rmlo: Reg::R2,
8545 rmhi: Reg::R3,
8546 },
8547 ArmOp::I64LeS {
8548 rd: Reg::R0,
8549 rnlo: Reg::R0,
8550 rnhi: Reg::R1,
8551 rmlo: Reg::R2,
8552 rmhi: Reg::R3,
8553 },
8554 ArmOp::I64LeU {
8555 rd: Reg::R0,
8556 rnlo: Reg::R0,
8557 rnhi: Reg::R1,
8558 rmlo: Reg::R2,
8559 rmhi: Reg::R3,
8560 },
8561 ArmOp::I64GtS {
8562 rd: Reg::R0,
8563 rnlo: Reg::R0,
8564 rnhi: Reg::R1,
8565 rmlo: Reg::R2,
8566 rmhi: Reg::R3,
8567 },
8568 ArmOp::I64GtU {
8569 rd: Reg::R0,
8570 rnlo: Reg::R0,
8571 rnhi: Reg::R1,
8572 rmlo: Reg::R2,
8573 rmhi: Reg::R3,
8574 },
8575 ArmOp::I64GeS {
8576 rd: Reg::R0,
8577 rnlo: Reg::R0,
8578 rnhi: Reg::R1,
8579 rmlo: Reg::R2,
8580 rmhi: Reg::R3,
8581 },
8582 ArmOp::I64GeU {
8583 rd: Reg::R0,
8584 rnlo: Reg::R0,
8585 rnhi: Reg::R1,
8586 rmlo: Reg::R2,
8587 rmhi: Reg::R3,
8588 },
8589 ];
8590
8591 for op in &ops {
8592 let code = encoder.encode(op).unwrap();
8593 assert!(
8594 code.len() >= 8,
8595 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8596 op,
8597 code.len()
8598 );
8599 }
8600 }
8601
8602 #[test]
8603 fn test_encode_i64_const_zero_thumb2() {
8604 let encoder = ArmEncoder::new_thumb2();
8605 let op = ArmOp::I64Const {
8606 rdlo: Reg::R0,
8607 rdhi: Reg::R1,
8608 value: 0,
8609 };
8610 let code = encoder.encode(&op).unwrap();
8611 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8613 }
8614
8615 #[test]
8616 fn test_encode_i64_const_negative_one_thumb2() {
8617 let encoder = ArmEncoder::new_thumb2();
8618 let op = ArmOp::I64Const {
8619 rdlo: Reg::R0,
8620 rdhi: Reg::R1,
8621 value: -1, };
8623 let code = encoder.encode(&op).unwrap();
8624 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8626 }
8627
8628 #[test]
8633 fn test_encode_ldrb_arm32() {
8634 let encoder = ArmEncoder::new_arm32();
8635 let op = ArmOp::Ldrb {
8636 rd: Reg::R0,
8637 addr: MemAddr::imm(Reg::R1, 4),
8638 };
8639 let code = encoder.encode(&op).unwrap();
8640 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8641 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8643 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8644 }
8645
8646 #[test]
8647 fn test_encode_strb_arm32() {
8648 let encoder = ArmEncoder::new_arm32();
8649 let op = ArmOp::Strb {
8650 rd: Reg::R0,
8651 addr: MemAddr::imm(Reg::R1, 0),
8652 };
8653 let code = encoder.encode(&op).unwrap();
8654 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8655 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8657 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8658 }
8659
8660 #[test]
8661 fn test_encode_ldrh_arm32() {
8662 let encoder = ArmEncoder::new_arm32();
8663 let op = ArmOp::Ldrh {
8664 rd: Reg::R0,
8665 addr: MemAddr::imm(Reg::R1, 2),
8666 };
8667 let code = encoder.encode(&op).unwrap();
8668 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8669 }
8670
8671 #[test]
8672 fn test_encode_strh_arm32() {
8673 let encoder = ArmEncoder::new_arm32();
8674 let op = ArmOp::Strh {
8675 rd: Reg::R0,
8676 addr: MemAddr::imm(Reg::R1, 0),
8677 };
8678 let code = encoder.encode(&op).unwrap();
8679 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8680 }
8681
8682 #[test]
8683 fn test_encode_ldrsb_arm32() {
8684 let encoder = ArmEncoder::new_arm32();
8685 let op = ArmOp::Ldrsb {
8686 rd: Reg::R0,
8687 addr: MemAddr::imm(Reg::R1, 0),
8688 };
8689 let code = encoder.encode(&op).unwrap();
8690 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8691 }
8692
8693 #[test]
8694 fn test_encode_ldrsh_arm32() {
8695 let encoder = ArmEncoder::new_arm32();
8696 let op = ArmOp::Ldrsh {
8697 rd: Reg::R0,
8698 addr: MemAddr::imm(Reg::R1, 0),
8699 };
8700 let code = encoder.encode(&op).unwrap();
8701 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8702 }
8703
8704 #[test]
8705 fn test_encode_ldrb_thumb2_16bit() {
8706 let encoder = ArmEncoder::new_thumb2();
8707 let op = ArmOp::Ldrb {
8708 rd: Reg::R0,
8709 addr: MemAddr::imm(Reg::R1, 4),
8710 };
8711 let code = encoder.encode(&op).unwrap();
8712 assert_eq!(
8714 code.len(),
8715 2,
8716 "Thumb-2 LDRB with small offset should be 16-bit"
8717 );
8718 }
8719
8720 #[test]
8721 fn test_encode_ldrb_thumb2_32bit() {
8722 let encoder = ArmEncoder::new_thumb2();
8723 let op = ArmOp::Ldrb {
8724 rd: Reg::R0,
8725 addr: MemAddr::imm(Reg::R1, 100), };
8727 let code = encoder.encode(&op).unwrap();
8728 assert_eq!(
8729 code.len(),
8730 4,
8731 "Thumb-2 LDRB with large offset should be 32-bit"
8732 );
8733 }
8734
8735 #[test]
8736 fn test_encode_strb_thumb2_16bit() {
8737 let encoder = ArmEncoder::new_thumb2();
8738 let op = ArmOp::Strb {
8739 rd: Reg::R0,
8740 addr: MemAddr::imm(Reg::R1, 10),
8741 };
8742 let code = encoder.encode(&op).unwrap();
8743 assert_eq!(
8744 code.len(),
8745 2,
8746 "Thumb-2 STRB with small offset should be 16-bit"
8747 );
8748 }
8749
8750 #[test]
8751 fn test_encode_ldrh_thumb2_16bit() {
8752 let encoder = ArmEncoder::new_thumb2();
8753 let op = ArmOp::Ldrh {
8754 rd: Reg::R0,
8755 addr: MemAddr::imm(Reg::R1, 4), };
8757 let code = encoder.encode(&op).unwrap();
8758 assert_eq!(
8759 code.len(),
8760 2,
8761 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8762 );
8763 }
8764
8765 #[test]
8766 fn test_encode_strh_thumb2_16bit() {
8767 let encoder = ArmEncoder::new_thumb2();
8768 let op = ArmOp::Strh {
8769 rd: Reg::R0,
8770 addr: MemAddr::imm(Reg::R1, 4),
8771 };
8772 let code = encoder.encode(&op).unwrap();
8773 assert_eq!(
8774 code.len(),
8775 2,
8776 "Thumb-2 STRH with small aligned offset should be 16-bit"
8777 );
8778 }
8779
8780 #[test]
8781 fn test_encode_ldrsb_thumb2() {
8782 let encoder = ArmEncoder::new_thumb2();
8783 let op = ArmOp::Ldrsb {
8784 rd: Reg::R0,
8785 addr: MemAddr::imm(Reg::R1, 0),
8786 };
8787 let code = encoder.encode(&op).unwrap();
8788 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8790 }
8791
8792 #[test]
8793 fn test_encode_ldrsh_thumb2() {
8794 let encoder = ArmEncoder::new_thumb2();
8795 let op = ArmOp::Ldrsh {
8796 rd: Reg::R0,
8797 addr: MemAddr::imm(Reg::R1, 0),
8798 };
8799 let code = encoder.encode(&op).unwrap();
8800 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8801 }
8802
8803 #[test]
8804 fn test_encode_memory_size_thumb2() {
8805 let encoder = ArmEncoder::new_thumb2();
8806 let op = ArmOp::MemorySize { rd: Reg::R0 };
8807 let code = encoder.encode(&op).unwrap();
8808 assert!(!code.is_empty(), "MemorySize should produce code");
8810 }
8811
8812 #[test]
8813 fn test_encode_memory_grow_thumb2() {
8814 let encoder = ArmEncoder::new_thumb2();
8815 let op = ArmOp::MemoryGrow {
8816 rd: Reg::R0,
8817 rn: Reg::R0,
8818 };
8819 let code = encoder.encode(&op).unwrap();
8820 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8821 }
8822
8823 #[test]
8824 fn test_encode_subword_reg_offset_thumb2() {
8825 let encoder = ArmEncoder::new_thumb2();
8826
8827 let op = ArmOp::Ldrb {
8829 rd: Reg::R0,
8830 addr: MemAddr::reg(Reg::R1, Reg::R2),
8831 };
8832 let code = encoder.encode(&op).unwrap();
8833 assert_eq!(
8834 code.len(),
8835 4,
8836 "Thumb-2 LDRB with reg offset should be 32-bit"
8837 );
8838
8839 let op = ArmOp::Strb {
8841 rd: Reg::R0,
8842 addr: MemAddr::reg(Reg::R1, Reg::R2),
8843 };
8844 let code = encoder.encode(&op).unwrap();
8845 assert_eq!(
8846 code.len(),
8847 4,
8848 "Thumb-2 STRB with reg offset should be 32-bit"
8849 );
8850
8851 let op = ArmOp::Ldrh {
8853 rd: Reg::R0,
8854 addr: MemAddr::reg(Reg::R1, Reg::R2),
8855 };
8856 let code = encoder.encode(&op).unwrap();
8857 assert_eq!(
8858 code.len(),
8859 4,
8860 "Thumb-2 LDRH with reg offset should be 32-bit"
8861 );
8862
8863 let op = ArmOp::Strh {
8865 rd: Reg::R0,
8866 addr: MemAddr::reg(Reg::R1, Reg::R2),
8867 };
8868 let code = encoder.encode(&op).unwrap();
8869 assert_eq!(
8870 code.len(),
8871 4,
8872 "Thumb-2 STRH with reg offset should be 32-bit"
8873 );
8874 }
8875
8876 #[test]
8877 fn test_encode_subword_reg_imm_offset_thumb2() {
8878 let encoder = ArmEncoder::new_thumb2();
8879
8880 let op = ArmOp::Ldrb {
8882 rd: Reg::R0,
8883 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8884 };
8885 let code = encoder.encode(&op).unwrap();
8886 assert_eq!(
8888 code.len(),
8889 8,
8890 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8891 );
8892 }
8893
8894 #[test]
8899 fn test_encode_mve_addi32_thumb2() {
8900 let encoder = ArmEncoder::new_thumb2();
8901 let op = ArmOp::MveAddI {
8902 qd: QReg::Q0,
8903 qn: QReg::Q1,
8904 qm: QReg::Q2,
8905 size: MveSize::S32,
8906 };
8907 let code = encoder.encode(&op).unwrap();
8908 assert_eq!(
8909 code.len(),
8910 4,
8911 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8912 );
8913 }
8914
8915 #[test]
8916 fn test_encode_mve_subi16_thumb2() {
8917 let encoder = ArmEncoder::new_thumb2();
8918 let op = ArmOp::MveSubI {
8919 qd: QReg::Q0,
8920 qn: QReg::Q1,
8921 qm: QReg::Q2,
8922 size: MveSize::S16,
8923 };
8924 let code = encoder.encode(&op).unwrap();
8925 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8926 }
8927
8928 #[test]
8929 fn test_encode_mve_muli8_thumb2() {
8930 let encoder = ArmEncoder::new_thumb2();
8931 let op = ArmOp::MveMulI {
8932 qd: QReg::Q0,
8933 qn: QReg::Q1,
8934 qm: QReg::Q2,
8935 size: MveSize::S8,
8936 };
8937 let code = encoder.encode(&op).unwrap();
8938 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8939 }
8940
8941 #[test]
8942 fn test_encode_mve_bitwise_thumb2() {
8943 let encoder = ArmEncoder::new_thumb2();
8944
8945 let ops = vec![
8946 ArmOp::MveAnd {
8947 qd: QReg::Q0,
8948 qn: QReg::Q1,
8949 qm: QReg::Q2,
8950 },
8951 ArmOp::MveOrr {
8952 qd: QReg::Q0,
8953 qn: QReg::Q1,
8954 qm: QReg::Q2,
8955 },
8956 ArmOp::MveEor {
8957 qd: QReg::Q0,
8958 qn: QReg::Q1,
8959 qm: QReg::Q2,
8960 },
8961 ArmOp::MveBic {
8962 qd: QReg::Q0,
8963 qn: QReg::Q1,
8964 qm: QReg::Q2,
8965 },
8966 ];
8967 for op in ops {
8968 let code = encoder.encode(&op).unwrap();
8969 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8970 }
8971 }
8972
8973 #[test]
8974 fn test_encode_mve_mvn_thumb2() {
8975 let encoder = ArmEncoder::new_thumb2();
8976 let op = ArmOp::MveMvn {
8977 qd: QReg::Q0,
8978 qm: QReg::Q1,
8979 };
8980 let code = encoder.encode(&op).unwrap();
8981 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8982 }
8983
8984 #[test]
8985 fn test_encode_mve_load_store_thumb2() {
8986 let encoder = ArmEncoder::new_thumb2();
8987
8988 let load = ArmOp::MveLoad {
8989 qd: QReg::Q0,
8990 addr: MemAddr::imm(Reg::R0, 16),
8991 };
8992 let code = encoder.encode(&load).unwrap();
8993 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8994
8995 let store = ArmOp::MveStore {
8996 qd: QReg::Q1,
8997 addr: MemAddr::imm(Reg::R1, 0),
8998 };
8999 let code = encoder.encode(&store).unwrap();
9000 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
9001 }
9002
9003 #[test]
9004 fn test_encode_mve_const_thumb2() {
9005 let encoder = ArmEncoder::new_thumb2();
9006 let op = ArmOp::MveConst {
9007 qd: QReg::Q0,
9008 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
9009 };
9010 let code = encoder.encode(&op).unwrap();
9011 assert!(
9014 code.len() >= 24,
9015 "MVE const should produce multiple instructions"
9016 );
9017 }
9018
9019 #[test]
9020 fn test_encode_mve_dup_thumb2() {
9021 let encoder = ArmEncoder::new_thumb2();
9022 let op = ArmOp::MveDup {
9023 qd: QReg::Q0,
9024 rn: Reg::R0,
9025 size: MveSize::S32,
9026 };
9027 let code = encoder.encode(&op).unwrap();
9028 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
9029 }
9030
9031 #[test]
9032 fn test_encode_mve_extract_lane_thumb2() {
9033 let encoder = ArmEncoder::new_thumb2();
9034 let op = ArmOp::MveExtractLane {
9035 rd: Reg::R0,
9036 qn: QReg::Q1,
9037 lane: 2,
9038 size: MveSize::S32,
9039 };
9040 let code = encoder.encode(&op).unwrap();
9041 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
9042 }
9043
9044 #[test]
9045 fn test_encode_mve_insert_lane_thumb2() {
9046 let encoder = ArmEncoder::new_thumb2();
9047 let op = ArmOp::MveInsertLane {
9048 qd: QReg::Q0,
9049 rn: Reg::R1,
9050 lane: 3,
9051 size: MveSize::S32,
9052 };
9053 let code = encoder.encode(&op).unwrap();
9054 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
9055 }
9056
9057 #[test]
9058 fn test_encode_mve_addf32_thumb2() {
9059 let encoder = ArmEncoder::new_thumb2();
9060 let op = ArmOp::MveAddF32 {
9061 qd: QReg::Q0,
9062 qn: QReg::Q1,
9063 qm: QReg::Q2,
9064 };
9065 let code = encoder.encode(&op).unwrap();
9066 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
9067 }
9068
9069 #[test]
9070 fn test_encode_mve_divf32_thumb2() {
9071 let encoder = ArmEncoder::new_thumb2();
9072 let op = ArmOp::MveDivF32 {
9073 qd: QReg::Q0,
9074 qn: QReg::Q1,
9075 qm: QReg::Q2,
9076 };
9077 let code = encoder.encode(&op).unwrap();
9078 assert_eq!(
9080 code.len(),
9081 16,
9082 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
9083 );
9084 }
9085
9086 #[test]
9087 fn test_encode_mve_sqrtf32_thumb2() {
9088 let encoder = ArmEncoder::new_thumb2();
9089 let op = ArmOp::MveSqrtF32 {
9090 qd: QReg::Q0,
9091 qm: QReg::Q1,
9092 };
9093 let code = encoder.encode(&op).unwrap();
9094 assert_eq!(
9096 code.len(),
9097 16,
9098 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
9099 );
9100 }
9101
9102 #[test]
9103 fn test_encode_mve_negf32_thumb2() {
9104 let encoder = ArmEncoder::new_thumb2();
9105 let op = ArmOp::MveNegF32 {
9106 qd: QReg::Q0,
9107 qm: QReg::Q1,
9108 };
9109 let code = encoder.encode(&op).unwrap();
9110 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
9111 }
9112
9113 #[test]
9114 fn test_encode_mve_absf32_thumb2() {
9115 let encoder = ArmEncoder::new_thumb2();
9116 let op = ArmOp::MveAbsF32 {
9117 qd: QReg::Q0,
9118 qm: QReg::Q1,
9119 };
9120 let code = encoder.encode(&op).unwrap();
9121 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
9122 }
9123
9124 #[test]
9139 fn and_immediate_encodes_correctly_in_byte_range_documents_fold_bound() {
9140 let encoder = ArmEncoder::new_thumb2();
9141 let op = ArmOp::And {
9142 rd: Reg::R2,
9143 rn: Reg::R0,
9144 op2: Operand2::Imm(0x7e),
9145 };
9146 let code = encoder.encode(&op).unwrap();
9147 assert_eq!(
9148 code,
9149 vec![0x00, 0xf0, 0x7e, 0x02],
9150 "and r2, r0, #0x7e must encode to the canonical AND.W T1 (imm8=0x7e)"
9151 );
9152 }
9153
9154 #[test]
9161 fn try_thumb_expand_imm_encodes_modified_immediates() {
9162 assert_eq!(try_thumb_expand_imm(0x7e), Some(0x07e)); assert_eq!(try_thumb_expand_imm(0xff), Some(0x0ff));
9164 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);
9172 assert_eq!(try_thumb_expand_imm(0x12345), None);
9173 }
9174
9175 #[test]
9180 fn cmp_adds_subs_immediate_error_on_non_modified_imm() {
9181 let encoder = ArmEncoder::new_thumb2();
9182 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 0xff).is_ok());
9184 assert!(encoder.encode_thumb32_cmp_imm(&Reg::R0, 1000).is_ok());
9185 assert!(
9187 encoder.encode_thumb32_cmp_imm(&Reg::R0, 0x101).is_err(),
9188 "cmp #0x101 must error, not compare the wrong constant"
9189 );
9190 assert!(
9191 encoder
9192 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x101)
9193 .is_err()
9194 );
9195 assert!(
9196 encoder
9197 .encode_thumb32_subs(&Reg::R0, &Reg::R0, 0x101)
9198 .is_err()
9199 );
9200 assert!(
9202 encoder
9203 .encode_thumb32_adds(&Reg::R0, &Reg::R0, 0x80)
9204 .is_ok()
9205 );
9206 }
9207
9208 #[test]
9211 fn mla_thumb2_encodes_correctly() {
9212 let encoder = ArmEncoder::new_thumb2();
9213 let code = encoder
9214 .encode(&ArmOp::Mla {
9215 rd: Reg::R2,
9216 rn: Reg::R3,
9217 rm: Reg::R4,
9218 ra: Reg::R8,
9219 })
9220 .unwrap();
9221 assert_eq!(code, vec![0x03, 0xfb, 0x04, 0x82]);
9223 }
9224
9225 #[test]
9230 fn ldst_imm12_offset_errors_when_out_of_range() {
9231 let encoder = ArmEncoder::new_thumb2();
9232 assert!(
9234 encoder
9235 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0xFFF)
9236 .is_ok()
9237 );
9238 assert!(
9240 encoder
9241 .encode_thumb32_ldr(&Reg::R0, &Reg::R1, 0x1000)
9242 .is_err(),
9243 "ldr offset 4096 must error, not wrap to 0"
9244 );
9245 assert!(
9246 encoder
9247 .encode_thumb32_str(&Reg::R0, &Reg::R1, 0x1000)
9248 .is_err()
9249 );
9250 assert!(
9251 encoder
9252 .encode_thumb32_ldrb_imm(&Reg::R0, &Reg::R1, 5000)
9253 .is_err()
9254 );
9255 assert!(
9256 encoder
9257 .encode_thumb32_strh_imm(&Reg::R0, &Reg::R1, 5000)
9258 .is_err()
9259 );
9260 }
9261
9262 #[test]
9269 fn add_sub_large_immediate_use_addw_subw_not_misencoded() {
9270 let encoder = ArmEncoder::new_thumb2();
9271 assert_eq!(
9273 encoder
9274 .encode(&ArmOp::Add {
9275 rd: Reg::SP,
9276 rn: Reg::SP,
9277 op2: Operand2::Imm(256),
9278 })
9279 .unwrap(),
9280 vec![0x0d, 0xf2, 0x00, 0x1d],
9281 "add sp,sp,#256 must be ADDW (plain imm12), not a mis-encoded ADD.W"
9282 );
9283 assert_eq!(
9285 encoder
9286 .encode(&ArmOp::Sub {
9287 rd: Reg::SP,
9288 rn: Reg::SP,
9289 op2: Operand2::Imm(256),
9290 })
9291 .unwrap(),
9292 vec![0xad, 0xf2, 0x00, 0x1d],
9293 );
9294 assert!(
9296 encoder
9297 .encode(&ArmOp::Add {
9298 rd: Reg::SP,
9299 rn: Reg::SP,
9300 op2: Operand2::Imm(5000),
9301 })
9302 .is_err(),
9303 "add #5000 must error (no single ADDW), not mis-encode"
9304 );
9305 }
9306
9307 #[test]
9311 fn orr_eor_immediate_encode_in_byte_range_else_error() {
9312 let encoder = ArmEncoder::new_thumb2();
9313 assert_eq!(
9315 encoder
9316 .encode(&ArmOp::Orr {
9317 rd: Reg::R2,
9318 rn: Reg::R0,
9319 op2: Operand2::Imm(0x7e),
9320 })
9321 .unwrap(),
9322 vec![0x40, 0xf0, 0x7e, 0x02],
9323 );
9324 assert_eq!(
9326 encoder
9327 .encode(&ArmOp::Eor {
9328 rd: Reg::R2,
9329 rn: Reg::R0,
9330 op2: Operand2::Imm(0x7e),
9331 })
9332 .unwrap(),
9333 vec![0x80, 0xf0, 0x7e, 0x02],
9334 );
9335 assert!(
9337 encoder
9338 .encode(&ArmOp::Orr {
9339 rd: Reg::R2,
9340 rn: Reg::R0,
9341 op2: Operand2::Imm(0x140),
9342 })
9343 .is_err(),
9344 "ORR #0x140 must error, not emit a NOP"
9345 );
9346 }
9347
9348 #[test]
9349 fn test_encode_mve_different_qregs() {
9350 let encoder = ArmEncoder::new_thumb2();
9351
9352 let op1 = ArmOp::MveAddI {
9354 qd: QReg::Q0,
9355 qn: QReg::Q0,
9356 qm: QReg::Q0,
9357 size: MveSize::S32,
9358 };
9359 let op2 = ArmOp::MveAddI {
9360 qd: QReg::Q3,
9361 qn: QReg::Q5,
9362 qm: QReg::Q7,
9363 size: MveSize::S32,
9364 };
9365 let code1 = encoder.encode(&op1).unwrap();
9366 let code2 = encoder.encode(&op2).unwrap();
9367 assert_ne!(
9368 code1, code2,
9369 "Different Q-registers should produce different encodings"
9370 );
9371 }
9372
9373 #[test]
9374 fn test_encode_mve_arm32_nop() {
9375 let encoder = ArmEncoder::new_arm32();
9377 let op = ArmOp::MveAddI {
9378 qd: QReg::Q0,
9379 qn: QReg::Q1,
9380 qm: QReg::Q2,
9381 size: MveSize::S32,
9382 };
9383 let code = encoder.encode(&op).unwrap();
9384 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
9385 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
9387 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
9388 }
9389}