1use synth_core::Result;
6use synth_core::target::FPUPrecision;
7use synth_synthesis::contracts::encoding as encoding_contracts;
8use synth_synthesis::{ArmOp, MemAddr, MveSize, Operand2, QReg, Reg, VfpReg};
9
10pub struct ArmEncoder {
12 thumb_mode: bool,
14 #[allow(dead_code)]
16 fpu: Option<FPUPrecision>,
17}
18
19impl ArmEncoder {
20 pub fn new_arm32() -> Self {
22 Self {
23 thumb_mode: false,
24 fpu: None,
25 }
26 }
27
28 pub fn new_thumb2() -> Self {
30 Self {
31 thumb_mode: true,
32 fpu: None,
33 }
34 }
35
36 pub fn new_thumb2_with_fpu(fpu: Option<FPUPrecision>) -> Self {
38 Self {
39 thumb_mode: true,
40 fpu,
41 }
42 }
43
44 pub fn encode(&self, op: &ArmOp) -> Result<Vec<u8>> {
46 if self.thumb_mode {
47 self.encode_thumb(op)
48 } else {
49 self.encode_arm(op)
50 }
51 }
52
53 fn encode_arm_reg_offset_mem(&self, op: &ArmOp) -> Result<Option<Vec<u8>>> {
61 use synth_synthesis::Reg;
62 let addr = match op {
63 ArmOp::Ldr { addr, .. }
64 | ArmOp::Str { addr, .. }
65 | ArmOp::Ldrb { addr, .. }
66 | ArmOp::Strb { addr, .. }
67 | ArmOp::Ldrh { addr, .. }
68 | ArmOp::Strh { addr, .. }
69 | ArmOp::Ldrsb { addr, .. }
70 | ArmOp::Ldrsh { addr, .. } => addr,
71 _ => return Ok(None),
72 };
73 let Some(rm) = addr.offset_reg else {
74 return Ok(None);
75 };
76 let ip = Reg::R12;
77 let add: u32 = 0xE0800000
79 | (reg_to_bits(&addr.base) << 16)
80 | (reg_to_bits(&ip) << 12)
81 | reg_to_bits(&rm);
82 let mut bytes = add.to_le_bytes().to_vec();
83 let imm_addr = MemAddr::imm(ip, addr.offset);
86 let imm_op = match op {
87 ArmOp::Ldr { rd, .. } => ArmOp::Ldr {
88 rd: *rd,
89 addr: imm_addr,
90 },
91 ArmOp::Str { rd, .. } => ArmOp::Str {
92 rd: *rd,
93 addr: imm_addr,
94 },
95 ArmOp::Ldrb { rd, .. } => ArmOp::Ldrb {
96 rd: *rd,
97 addr: imm_addr,
98 },
99 ArmOp::Strb { rd, .. } => ArmOp::Strb {
100 rd: *rd,
101 addr: imm_addr,
102 },
103 ArmOp::Ldrh { rd, .. } => ArmOp::Ldrh {
104 rd: *rd,
105 addr: imm_addr,
106 },
107 ArmOp::Strh { rd, .. } => ArmOp::Strh {
108 rd: *rd,
109 addr: imm_addr,
110 },
111 ArmOp::Ldrsb { rd, .. } => ArmOp::Ldrsb {
112 rd: *rd,
113 addr: imm_addr,
114 },
115 ArmOp::Ldrsh { rd, .. } => ArmOp::Ldrsh {
116 rd: *rd,
117 addr: imm_addr,
118 },
119 _ => unreachable!(),
120 };
121 bytes.extend(self.encode_arm(&imm_op)?);
122 Ok(Some(bytes))
123 }
124
125 fn encode_arm(&self, op: &ArmOp) -> Result<Vec<u8>> {
126 if let Some(bytes) = self.encode_arm_reg_offset_mem(op)? {
133 return Ok(bytes);
134 }
135 let instr: u32 = match op {
136 ArmOp::Add { rd, rn, op2 } => {
138 let rd_bits = reg_to_bits(rd);
139 let rn_bits = reg_to_bits(rn);
140 let (op2_bits, i_flag) = encode_operand2(op2);
141
142 0xE0800000 | (i_flag << 25)
145 | (rn_bits << 16)
146 | (rd_bits << 12)
147 | op2_bits
148 }
149
150 ArmOp::Sub { rd, rn, op2 } => {
151 let rd_bits = reg_to_bits(rd);
152 let rn_bits = reg_to_bits(rn);
153 let (op2_bits, i_flag) = encode_operand2(op2);
154
155 0xE0400000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
157 }
158
159 ArmOp::Adds { rd, rn, op2 } => {
161 let rd_bits = reg_to_bits(rd);
162 let rn_bits = reg_to_bits(rn);
163 let (op2_bits, i_flag) = encode_operand2(op2);
164
165 0xE0900000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
167 }
168
169 ArmOp::Adc { rd, rn, op2 } => {
170 let rd_bits = reg_to_bits(rd);
171 let rn_bits = reg_to_bits(rn);
172 let (op2_bits, i_flag) = encode_operand2(op2);
173
174 0xE0A00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
176 }
177
178 ArmOp::Subs { rd, rn, op2 } => {
179 let rd_bits = reg_to_bits(rd);
180 let rn_bits = reg_to_bits(rn);
181 let (op2_bits, i_flag) = encode_operand2(op2);
182
183 0xE0500000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
185 }
186
187 ArmOp::Sbc { rd, rn, op2 } => {
188 let rd_bits = reg_to_bits(rd);
189 let rn_bits = reg_to_bits(rn);
190 let (op2_bits, i_flag) = encode_operand2(op2);
191
192 0xE0C00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
194 }
195
196 ArmOp::Mul { rd, rn, rm } => {
197 let rd_bits = reg_to_bits(rd);
198 let rn_bits = reg_to_bits(rn);
199 let rm_bits = reg_to_bits(rm);
200
201 0xE0000090 | (rd_bits << 16) | (rn_bits << 8) | rm_bits
203 }
204
205 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
206 let rdlo_bits = reg_to_bits(rdlo);
207 let rdhi_bits = reg_to_bits(rdhi);
208 let rn_bits = reg_to_bits(rn);
209 let rm_bits = reg_to_bits(rm);
210
211 0xE0800090 | (rdhi_bits << 16) | (rdlo_bits << 12) | (rm_bits << 8) | rn_bits
213 }
214
215 ArmOp::Sdiv { rd, rn, rm } => {
216 let rd_bits = reg_to_bits(rd);
217 let rn_bits = reg_to_bits(rn);
218 let rm_bits = reg_to_bits(rm);
219
220 0xE710F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
223 }
224
225 ArmOp::Udiv { rd, rn, rm } => {
226 let rd_bits = reg_to_bits(rd);
227 let rn_bits = reg_to_bits(rn);
228 let rm_bits = reg_to_bits(rm);
229
230 0xE730F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
233 }
234
235 ArmOp::Mls { rd, rn, rm, ra } => {
236 let rd_bits = reg_to_bits(rd);
237 let rn_bits = reg_to_bits(rn);
238 let rm_bits = reg_to_bits(rm);
239 let ra_bits = reg_to_bits(ra);
240
241 0xE0600090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
244 }
245
246 ArmOp::And { rd, rn, op2 } => {
247 let rd_bits = reg_to_bits(rd);
248 let rn_bits = reg_to_bits(rn);
249 let (op2_bits, i_flag) = encode_operand2(op2);
250
251 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
253 }
254
255 ArmOp::Orr { rd, rn, op2 } => {
256 let rd_bits = reg_to_bits(rd);
257 let rn_bits = reg_to_bits(rn);
258 let (op2_bits, i_flag) = encode_operand2(op2);
259
260 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
262 }
263
264 ArmOp::Eor { rd, rn, op2 } => {
265 let rd_bits = reg_to_bits(rd);
266 let rn_bits = reg_to_bits(rn);
267 let (op2_bits, i_flag) = encode_operand2(op2);
268
269 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
271 }
272
273 ArmOp::Lsl { rd, rn, shift } => {
275 let rd_bits = reg_to_bits(rd);
276 let rn_bits = reg_to_bits(rn);
277 let shift_bits = *shift & 0x1F;
278
279 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
281 }
282
283 ArmOp::Lsr { rd, rn, shift } => {
284 let rd_bits = reg_to_bits(rd);
285 let rn_bits = reg_to_bits(rn);
286 let shift_bits = *shift & 0x1F;
287
288 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
290 }
291
292 ArmOp::Asr { rd, rn, shift } => {
293 let rd_bits = reg_to_bits(rd);
294 let rn_bits = reg_to_bits(rn);
295 let shift_bits = *shift & 0x1F;
296
297 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
299 }
300
301 ArmOp::Ror { rd, rn, shift } => {
302 let rd_bits = reg_to_bits(rd);
303 let rn_bits = reg_to_bits(rn);
304 let shift_bits = *shift & 0x1F;
305
306 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
308 }
309
310 ArmOp::LslReg { rd, rn, rm } => {
313 let rd_bits = reg_to_bits(rd);
314 let rn_bits = reg_to_bits(rn);
315 let rm_bits = reg_to_bits(rm);
316 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
317 }
318 ArmOp::LsrReg { rd, rn, rm } => {
319 let rd_bits = reg_to_bits(rd);
320 let rn_bits = reg_to_bits(rn);
321 let rm_bits = reg_to_bits(rm);
322 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
323 }
324 ArmOp::AsrReg { rd, rn, rm } => {
325 let rd_bits = reg_to_bits(rd);
326 let rn_bits = reg_to_bits(rn);
327 let rm_bits = reg_to_bits(rm);
328 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
329 }
330 ArmOp::RorReg { rd, rn, rm } => {
331 let rd_bits = reg_to_bits(rd);
332 let rn_bits = reg_to_bits(rn);
333 let rm_bits = reg_to_bits(rm);
334 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
335 }
336
337 ArmOp::Rsb { rd, rn, imm } => {
339 let rd_bits = reg_to_bits(rd);
340 let rn_bits = reg_to_bits(rn);
341 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
344 }
345
346 ArmOp::Clz { rd, rm } => {
348 let rd_bits = reg_to_bits(rd);
349 let rm_bits = reg_to_bits(rm);
350
351 0xE16F0F10 | (rd_bits << 12) | rm_bits
354 }
355
356 ArmOp::Rbit { rd, rm } => {
357 let rd_bits = reg_to_bits(rd);
358 let rm_bits = reg_to_bits(rm);
359
360 0xE6FF0F30 | (rd_bits << 12) | rm_bits
363 }
364
365 ArmOp::Sxtb { rd, rm } => {
366 let rd_bits = reg_to_bits(rd);
367 let rm_bits = reg_to_bits(rm);
368
369 0xE6AF0070 | (rd_bits << 12) | rm_bits
372 }
373
374 ArmOp::Sxth { rd, rm } => {
375 let rd_bits = reg_to_bits(rd);
376 let rm_bits = reg_to_bits(rm);
377
378 0xE6BF0070 | (rd_bits << 12) | rm_bits
381 }
382
383 ArmOp::Mov { rd, op2 } => {
385 let rd_bits = reg_to_bits(rd);
386 let (op2_bits, i_flag) = encode_operand2(op2);
387
388 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
390 }
391
392 ArmOp::Mvn { rd, op2 } => {
393 let rd_bits = reg_to_bits(rd);
394 let (op2_bits, i_flag) = encode_operand2(op2);
395
396 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
398 }
399
400 ArmOp::Movw { rd, imm16 } => {
403 let rd_bits = reg_to_bits(rd);
404 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
405 let imm12 = (*imm16 as u32) & 0xFFF;
406 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
407 }
408
409 ArmOp::Movt { rd, imm16 } => {
412 let rd_bits = reg_to_bits(rd);
413 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
414 let imm12 = (*imm16 as u32) & 0xFFF;
415 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
416 }
417
418 ArmOp::MovwSym { rd, addend, .. } => {
421 let rd_bits = reg_to_bits(rd);
422 let v = (*addend as u32) & 0xffff;
423 0xE3000000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
424 }
425 ArmOp::MovtSym { rd, addend, .. } => {
426 let rd_bits = reg_to_bits(rd);
427 let v = ((*addend as u32) >> 16) & 0xffff;
428 0xE3400000 | (((v >> 12) & 0xF) << 16) | (rd_bits << 12) | (v & 0xFFF)
429 }
430
431 ArmOp::Cmp { rn, op2 } => {
433 let rn_bits = reg_to_bits(rn);
434 let (op2_bits, i_flag) = encode_operand2(op2);
435
436 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
438 }
439
440 ArmOp::Cmn { rn, op2 } => {
442 let rn_bits = reg_to_bits(rn);
443 let (op2_bits, i_flag) = encode_operand2(op2);
444
445 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
447 }
448
449 ArmOp::Ldr { rd, addr } => {
451 let rd_bits = reg_to_bits(rd);
452 let (base_bits, offset_bits) = encode_mem_addr(addr);
453
454 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
457 }
458
459 ArmOp::Str { rd, addr } => {
460 let rd_bits = reg_to_bits(rd);
461 let (base_bits, offset_bits) = encode_mem_addr(addr);
462
463 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
465 }
466
467 ArmOp::Ldrb { rd, addr } => {
469 let rd_bits = reg_to_bits(rd);
470 let (base_bits, offset_bits) = encode_mem_addr(addr);
471 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
473 }
474
475 ArmOp::Ldrsb { rd, addr } => {
476 let rd_bits = reg_to_bits(rd);
477 let (base_bits, offset_bits) = encode_mem_addr(addr);
478 let offset_val = offset_bits & 0xFF;
481 let imm4h = (offset_val >> 4) & 0xF;
482 let imm4l = offset_val & 0xF;
483 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
484 }
485
486 ArmOp::Ldrh { rd, addr } => {
487 let rd_bits = reg_to_bits(rd);
488 let (base_bits, offset_bits) = encode_mem_addr(addr);
489 let offset_val = offset_bits & 0xFF;
491 let imm4h = (offset_val >> 4) & 0xF;
492 let imm4l = offset_val & 0xF;
493 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
494 }
495
496 ArmOp::Ldrsh { rd, addr } => {
497 let rd_bits = reg_to_bits(rd);
498 let (base_bits, offset_bits) = encode_mem_addr(addr);
499 let offset_val = offset_bits & 0xFF;
501 let imm4h = (offset_val >> 4) & 0xF;
502 let imm4l = offset_val & 0xF;
503 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
504 }
505
506 ArmOp::Strb { rd, addr } => {
508 let rd_bits = reg_to_bits(rd);
509 let (base_bits, offset_bits) = encode_mem_addr(addr);
510 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
512 }
513
514 ArmOp::Strh { rd, addr } => {
515 let rd_bits = reg_to_bits(rd);
516 let (base_bits, offset_bits) = encode_mem_addr(addr);
517 let offset_val = offset_bits & 0xFF;
519 let imm4h = (offset_val >> 4) & 0xF;
520 let imm4l = offset_val & 0xF;
521 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
522 }
523
524 ArmOp::MemorySize { rd } => {
526 let rd_bits = reg_to_bits(rd);
527 0xE1A00820 | (rd_bits << 12) | 0x0A }
532
533 ArmOp::MemoryGrow { rd, .. } => {
534 let rd_bits = reg_to_bits(rd);
535 0xE3E00000 | (rd_bits << 12) }
538
539 ArmOp::Label { .. } => {
541 return Ok(Vec::new());
542 }
543
544 ArmOp::B { label: _ } => {
546 0xEA000000
549 }
550
551 ArmOp::Bcc { cond, label: _ } => {
553 use synth_synthesis::Condition;
554 let cond_bits: u32 = match cond {
555 Condition::EQ => 0x0,
556 Condition::NE => 0x1,
557 Condition::HS => 0x2,
558 Condition::LO => 0x3,
559 Condition::HI => 0x8,
560 Condition::LS => 0x9,
561 Condition::GE => 0xA,
562 Condition::LT => 0xB,
563 Condition::GT => 0xC,
564 Condition::LE => 0xD,
565 };
566 (cond_bits << 28) | 0x0A000000
568 }
569
570 ArmOp::Bhs { label: _ } => {
572 0x2A000000 }
575
576 ArmOp::Blo { label: _ } => {
578 0x3A000000 }
581
582 ArmOp::BOffset { offset } => {
586 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
596 0xEA000000 | offset_bits
597 }
598
599 ArmOp::BCondOffset { cond, offset } => {
601 use synth_synthesis::Condition;
602 let cond_bits: u32 = match cond {
603 Condition::EQ => 0x0,
604 Condition::NE => 0x1,
605 Condition::HS => 0x2,
606 Condition::LO => 0x3,
607 Condition::HI => 0x8,
608 Condition::LS => 0x9,
609 Condition::GE => 0xA,
610 Condition::LT => 0xB,
611 Condition::GT => 0xC,
612 Condition::LE => 0xD,
613 };
614 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
618 (cond_bits << 28) | 0x0A000000 | offset_bits
619 }
620
621 ArmOp::Bl { label: _ } => {
622 0xEB000000
624 }
625
626 ArmOp::Bx { rm } => {
627 let rm_bits = reg_to_bits(rm);
628
629 0xE12FFF10 | rm_bits
631 }
632
633 ArmOp::Blx { rm } => {
634 let rm_bits = reg_to_bits(rm);
635
636 0xE12FFF30 | rm_bits
638 }
639
640 ArmOp::Push { regs } => {
641 let mut reg_list: u32 = 0;
643 for r in regs {
644 reg_list |= 1 << reg_to_bits(r);
645 }
646 0xE92D0000 | reg_list
647 }
648
649 ArmOp::Pop { regs } => {
650 let mut reg_list: u32 = 0;
652 for r in regs {
653 reg_list |= 1 << reg_to_bits(r);
654 }
655 0xE8BD0000 | reg_list
656 }
657
658 ArmOp::Nop => {
659 0xE1A00000
661 }
662
663 ArmOp::Udf { imm } => {
664 let imm8 = *imm as u32;
667 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
668 }
669
670 ArmOp::Popcnt { .. } => {
673 0xE1A00000 }
677
678 ArmOp::SetCond { .. } => {
679 0xE1A00000 }
683
684 ArmOp::SelectMove { .. } => {
685 0xE1A00000 }
689
690 ArmOp::Select { .. } => {
691 0xE1A00000 }
695
696 ArmOp::LocalGet { .. } => {
697 0xE1A00000 }
701
702 ArmOp::LocalSet { .. } => {
703 0xE1A00000 }
707
708 ArmOp::LocalTee { .. } => {
709 0xE1A00000 }
713
714 ArmOp::GlobalGet { .. } => {
715 0xE1A00000 }
719
720 ArmOp::GlobalSet { .. } => {
721 0xE1A00000 }
725
726 ArmOp::BrTable { .. } => {
727 0xE1A00000 }
731
732 ArmOp::Call { .. } => {
733 0xE1A00000 }
737
738 ArmOp::CallIndirect { .. } => {
739 0xE1A00000 }
743
744 ArmOp::I64Add { .. } => 0xE1A00000, ArmOp::I64Sub { .. } => 0xE1A00000, ArmOp::I64DivS { .. } => 0xE1A00000, ArmOp::I64DivU { .. } => 0xE1A00000, ArmOp::I64RemS { .. } => 0xE1A00000, ArmOp::I64RemU { .. } => 0xE1A00000, ArmOp::I64Clz { .. } => 0xE1A00000, ArmOp::I64Ctz { .. } => 0xE1A00000, ArmOp::I64Popcnt { .. } => 0xE1A00000, ArmOp::I64And { .. } => 0xE1A00000, ArmOp::I64Or { .. } => 0xE1A00000, ArmOp::I64Xor { .. } => 0xE1A00000, ArmOp::I64Eqz { .. } => 0xE1A00000, ArmOp::I64Eq { .. } => 0xE1A00000, ArmOp::I64Ne { .. } => 0xE1A00000, ArmOp::I64LtS { .. } => 0xE1A00000, ArmOp::I64LtU { .. } => 0xE1A00000, ArmOp::I64LeS { .. } => 0xE1A00000, ArmOp::I64LeU { .. } => 0xE1A00000, ArmOp::I64GtS { .. } => 0xE1A00000, ArmOp::I64GtU { .. } => 0xE1A00000, ArmOp::I64GeS { .. } => 0xE1A00000, ArmOp::I64GeU { .. } => 0xE1A00000, ArmOp::I64Const { .. } => 0xE1A00000, ArmOp::I64Ldr { .. } => 0xE1A00000, ArmOp::I64Str { .. } => 0xE1A00000, ArmOp::I64ExtendI32S { .. } => 0xE1A00000, ArmOp::I64ExtendI32U { .. } => 0xE1A00000, ArmOp::I64Extend8S { .. } => 0xE1A00000, ArmOp::I64Extend16S { .. } => 0xE1A00000, ArmOp::I64Extend32S { .. } => 0xE1A00000, ArmOp::I32WrapI64 { .. } => 0xE1A00000, ArmOp::F32Add { sd, sn, sm } => encode_vfp_3reg(0xEE300A00, sd, sn, sm)?,
781 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
782 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
783 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
784 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
785 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
786 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
787
788 ArmOp::F32Ceil { sd, sm } => {
791 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
793 ArmOp::F32Floor { sd, sm } => {
794 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
796 ArmOp::F32Trunc { sd, sm } => {
797 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
799 ArmOp::F32Nearest { sd, sm } => {
800 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
802 ArmOp::F32Min { sd, sn, sm } => {
803 return self.encode_arm_f32_minmax(sd, sn, sm, true);
804 }
805 ArmOp::F32Max { sd, sn, sm } => {
806 return self.encode_arm_f32_minmax(sd, sn, sm, false);
807 }
808 ArmOp::F32Copysign { sd, sn, sm } => {
809 return self.encode_arm_f32_copysign(sd, sn, sm);
810 }
811
812 ArmOp::F32Eq { rd, sn, sm } => {
814 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
816 ArmOp::F32Ne { rd, sn, sm } => {
817 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
819 ArmOp::F32Lt { rd, sn, sm } => {
820 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
822 ArmOp::F32Le { rd, sn, sm } => {
823 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
825 ArmOp::F32Gt { rd, sn, sm } => {
826 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
828 ArmOp::F32Ge { rd, sn, sm } => {
829 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
831
832 ArmOp::F32Const { sd, value } => {
834 return self.encode_arm_f32_const(sd, *value);
835 }
836
837 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
838 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
839
840 ArmOp::F32ConvertI32S { sd, rm } => {
842 return self.encode_arm_f32_convert_i32(sd, rm, true);
843 }
844 ArmOp::F32ConvertI32U { sd, rm } => {
845 return self.encode_arm_f32_convert_i32(sd, rm, false);
846 }
847 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
848 return Err(synth_core::Error::synthesis(
849 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
850 ));
851 }
852 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
853 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
854 ArmOp::I32TruncF32S { rd, sm } => {
855 return self.encode_arm_i32_trunc_f32(rd, sm, true);
856 }
857 ArmOp::I32TruncF32U { rd, sm } => {
858 return self.encode_arm_i32_trunc_f32(rd, sm, false);
859 }
860
861 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
864 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
865 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
866 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
867 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
868 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
869 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
870
871 ArmOp::F64Ceil { dd, dm } => {
874 return self.encode_arm_f64_rounding(dd, dm, 0b01);
875 }
876 ArmOp::F64Floor { dd, dm } => {
877 return self.encode_arm_f64_rounding(dd, dm, 0b10);
878 }
879 ArmOp::F64Trunc { dd, dm } => {
880 return self.encode_arm_f64_rounding(dd, dm, 0b11);
881 }
882 ArmOp::F64Nearest { dd, dm } => {
883 return self.encode_arm_f64_rounding(dd, dm, 0b00);
884 }
885 ArmOp::F64Min { dd, dn, dm } => {
886 return self.encode_arm_f64_minmax(dd, dn, dm, true);
887 }
888 ArmOp::F64Max { dd, dn, dm } => {
889 return self.encode_arm_f64_minmax(dd, dn, dm, false);
890 }
891 ArmOp::F64Copysign { dd, dn, dm } => {
892 return self.encode_arm_f64_copysign(dd, dn, dm);
893 }
894
895 ArmOp::F64Eq { rd, dn, dm } => {
897 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
898 }
899 ArmOp::F64Ne { rd, dn, dm } => {
900 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
901 }
902 ArmOp::F64Lt { rd, dn, dm } => {
903 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
904 }
905 ArmOp::F64Le { rd, dn, dm } => {
906 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
907 }
908 ArmOp::F64Gt { rd, dn, dm } => {
909 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
910 }
911 ArmOp::F64Ge { rd, dn, dm } => {
912 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
913 }
914
915 ArmOp::F64Const { dd, value } => {
916 return self.encode_arm_f64_const(dd, *value);
917 }
918
919 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
920 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
921
922 ArmOp::F64ConvertI32S { dd, rm } => {
923 return self.encode_arm_f64_convert_i32(dd, rm, true);
924 }
925 ArmOp::F64ConvertI32U { dd, rm } => {
926 return self.encode_arm_f64_convert_i32(dd, rm, false);
927 }
928 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
929 return Err(synth_core::Error::synthesis(
930 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
931 ));
932 }
933 ArmOp::F64PromoteF32 { dd, sm } => {
934 return self.encode_arm_f64_promote_f32(dd, sm);
935 }
936 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
937 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
938 }
939 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
940 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
941 }
942 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
943 return Err(synth_core::Error::synthesis(
944 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
945 ));
946 }
947 ArmOp::I32TruncF64S { rd, dm } => {
948 return self.encode_arm_i32_trunc_f64(rd, dm, true);
949 }
950 ArmOp::I32TruncF64U { rd, dm } => {
951 return self.encode_arm_i32_trunc_f64(rd, dm, false);
952 }
953 ArmOp::I64SetCond { .. }
955 | ArmOp::I64SetCondZ { .. }
956 | ArmOp::I64Mul { .. }
957 | ArmOp::I64Shl { .. }
958 | ArmOp::I64ShrS { .. }
959 | ArmOp::I64ShrU { .. }
960 | ArmOp::I64Rotl { .. }
961 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
965 | ArmOp::MveStore { .. }
966 | ArmOp::MveConst { .. }
967 | ArmOp::MveAnd { .. }
968 | ArmOp::MveOrr { .. }
969 | ArmOp::MveEor { .. }
970 | ArmOp::MveMvn { .. }
971 | ArmOp::MveBic { .. }
972 | ArmOp::MveAddI { .. }
973 | ArmOp::MveSubI { .. }
974 | ArmOp::MveMulI { .. }
975 | ArmOp::MveNegI { .. }
976 | ArmOp::MveCmpEqI { .. }
977 | ArmOp::MveCmpNeI { .. }
978 | ArmOp::MveCmpLtS { .. }
979 | ArmOp::MveCmpLtU { .. }
980 | ArmOp::MveCmpGtS { .. }
981 | ArmOp::MveCmpGtU { .. }
982 | ArmOp::MveCmpLeS { .. }
983 | ArmOp::MveCmpLeU { .. }
984 | ArmOp::MveCmpGeS { .. }
985 | ArmOp::MveCmpGeU { .. }
986 | ArmOp::MveDup { .. }
987 | ArmOp::MveExtractLane { .. }
988 | ArmOp::MveInsertLane { .. }
989 | ArmOp::MveAddF32 { .. }
990 | ArmOp::MveSubF32 { .. }
991 | ArmOp::MveMulF32 { .. }
992 | ArmOp::MveNegF32 { .. }
993 | ArmOp::MveAbsF32 { .. }
994 | ArmOp::MveCmpEqF32 { .. }
995 | ArmOp::MveCmpNeF32 { .. }
996 | ArmOp::MveCmpLtF32 { .. }
997 | ArmOp::MveCmpLeF32 { .. }
998 | ArmOp::MveCmpGtF32 { .. }
999 | ArmOp::MveCmpGeF32 { .. }
1000 | ArmOp::MveDupF32 { .. }
1001 | ArmOp::MveExtractLaneF32 { .. }
1002 | ArmOp::MveReplaceLaneF32 { .. }
1003 | ArmOp::MveDivF32 { .. }
1004 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
1006
1007 Ok(instr.to_le_bytes().to_vec())
1009 }
1010
1011 fn encode_arm_f32_compare(
1015 &self,
1016 rd: &Reg,
1017 sn: &VfpReg,
1018 sm: &VfpReg,
1019 cond_code: u32,
1020 ) -> Result<Vec<u8>> {
1021 let mut bytes = Vec::new();
1022
1023 let sn_num = vfp_sreg_to_num(sn)?;
1025 let sm_num = vfp_sreg_to_num(sm)?;
1026 let (vd, d) = encode_sreg(sn_num);
1027 let (vm, m) = encode_sreg(sm_num);
1028 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1029 bytes.extend_from_slice(&vcmp.to_le_bytes());
1030
1031 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1033
1034 let rd_bits = reg_to_bits(rd);
1036 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1037 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1038
1039 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1041 bytes.extend_from_slice(&mov_one.to_le_bytes());
1042
1043 Ok(bytes)
1044 }
1045
1046 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1048 let mut bytes = Vec::new();
1049 let bits = value.to_bits();
1050
1051 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1056 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1057 bytes.extend_from_slice(&movw.to_le_bytes());
1058
1059 let hi16 = (bits >> 16) & 0xFFFF;
1061 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1062 bytes.extend_from_slice(&movt.to_le_bytes());
1063
1064 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1066 bytes.extend_from_slice(&vmov.to_le_bytes());
1067
1068 Ok(bytes)
1069 }
1070
1071 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1073 let mut bytes = Vec::new();
1074
1075 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1077 bytes.extend_from_slice(&vmov.to_le_bytes());
1078
1079 let sd_num = vfp_sreg_to_num(sd)?;
1082 let (vd, d) = encode_sreg(sd_num);
1083 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1085 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1086 bytes.extend_from_slice(&vcvt.to_le_bytes());
1087
1088 Ok(bytes)
1089 }
1090
1091 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1103 let mut bytes = Vec::new();
1104 let sm_num = vfp_sreg_to_num(sm)?;
1105 let sd_num = vfp_sreg_to_num(sd)?;
1106 let (vd_s, d_s) = encode_sreg(sd_num);
1107 let (vm_s, m_s) = encode_sreg(sm_num);
1108
1109 if mode == 0b11 {
1110 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1113 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1114 } else {
1115 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1120 bytes.extend_from_slice(&vmrs.to_le_bytes());
1121
1122 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1125 bytes.extend_from_slice(&bic.to_le_bytes());
1126
1127 if mode != 0 {
1129 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1131 bytes.extend_from_slice(&orr.to_le_bytes());
1132 }
1133
1134 let vmsr = 0xEEE10A10 | (rt << 12);
1136 bytes.extend_from_slice(&vmsr.to_le_bytes());
1137
1138 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1140 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1141
1142 bytes.extend_from_slice(&vmrs.to_le_bytes());
1144 bytes.extend_from_slice(&bic.to_le_bytes());
1145 bytes.extend_from_slice(&vmsr.to_le_bytes());
1146 }
1147
1148 let (vd2, d2) = encode_sreg(sd_num);
1150 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1151 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1152
1153 Ok(bytes)
1154 }
1155
1156 fn encode_arm_f32_minmax(
1158 &self,
1159 sd: &VfpReg,
1160 sn: &VfpReg,
1161 sm: &VfpReg,
1162 is_min: bool,
1163 ) -> Result<Vec<u8>> {
1164 let mut bytes = Vec::new();
1165 let sn_num = vfp_sreg_to_num(sn)?;
1166 let sm_num = vfp_sreg_to_num(sm)?;
1167 let sd_num = vfp_sreg_to_num(sd)?;
1168
1169 let (vd, d) = encode_sreg(sd_num);
1171 let (vn, n) = encode_sreg(sn_num);
1172 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1173 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1174
1175 let (vm, m) = encode_sreg(sm_num);
1177 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1178 bytes.extend_from_slice(&vcmp.to_le_bytes());
1179
1180 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1182
1183 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1186
1187 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1189 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1190
1191 Ok(bytes)
1192 }
1193
1194 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1196 let mut bytes = Vec::new();
1197
1198 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1200 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1201
1202 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1204 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1205
1206 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1210 bytes.extend_from_slice(&and_sign.to_le_bytes());
1211
1212 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1215 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1216
1217 let orr = 0xE1800000u32 | 12;
1220 bytes.extend_from_slice(&orr.to_le_bytes());
1221
1222 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1224 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1225
1226 Ok(bytes)
1227 }
1228
1229 fn encode_arm_f64_compare(
1231 &self,
1232 rd: &Reg,
1233 dn: &VfpReg,
1234 dm: &VfpReg,
1235 cond_code: u32,
1236 ) -> Result<Vec<u8>> {
1237 let mut bytes = Vec::new();
1238
1239 let dn_num = vfp_dreg_to_num(dn)?;
1241 let dm_num = vfp_dreg_to_num(dm)?;
1242 let (vd, d) = encode_dreg(dn_num);
1243 let (vm, m) = encode_dreg(dm_num);
1244 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1245 bytes.extend_from_slice(&vcmp.to_le_bytes());
1246
1247 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1249
1250 let rd_bits = reg_to_bits(rd);
1252 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1253 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1254
1255 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1257 bytes.extend_from_slice(&mov_one.to_le_bytes());
1258
1259 Ok(bytes)
1260 }
1261
1262 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1264 let mut bytes = Vec::new();
1265 let bits = value.to_bits();
1266 let lo32 = bits as u32;
1267 let hi32 = (bits >> 32) as u32;
1268
1269 let lo16 = lo32 & 0xFFFF;
1271 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1272 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1273 let hi16 = (lo32 >> 16) & 0xFFFF;
1274 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1275 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1276
1277 let lo16 = hi32 & 0xFFFF;
1279 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1280 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1281 let hi16 = (hi32 >> 16) & 0xFFFF;
1282 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1283 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1284
1285 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1287 bytes.extend_from_slice(&vmov.to_le_bytes());
1288
1289 Ok(bytes)
1290 }
1291
1292 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1294 let mut bytes = Vec::new();
1295
1296 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1298 bytes.extend_from_slice(&vmov.to_le_bytes());
1299
1300 let dd_num = vfp_dreg_to_num(dd)?;
1303 let (vd, d) = encode_dreg(dd_num);
1304 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1305 let vcvt = base | (d << 22) | (vd << 12);
1307 bytes.extend_from_slice(&vcvt.to_le_bytes());
1308
1309 Ok(bytes)
1310 }
1311
1312 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1314 let dd_num = vfp_dreg_to_num(dd)?;
1315 let sm_num = vfp_sreg_to_num(sm)?;
1316 let (vd, d) = encode_dreg(dd_num);
1317 let (vm, m) = encode_sreg(sm_num);
1318
1319 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1321 Ok(vcvt.to_le_bytes().to_vec())
1322 }
1323
1324 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1326 let mut bytes = Vec::new();
1327 let dm_num = vfp_dreg_to_num(dm)?;
1328 let (vm, m) = encode_dreg(dm_num);
1329
1330 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1333 let vcvt = base | (m << 5) | vm;
1334 bytes.extend_from_slice(&vcvt.to_le_bytes());
1335
1336 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1338 bytes.extend_from_slice(&vmov.to_le_bytes());
1339
1340 Ok(bytes)
1341 }
1342
1343 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1351 let mut bytes = Vec::new();
1352 let dm_num = vfp_dreg_to_num(dm)?;
1353 let dd_num = vfp_dreg_to_num(dd)?;
1354 let (vm, m) = encode_dreg(dm_num);
1355 let (vd, d) = encode_dreg(dd_num);
1356
1357 if mode == 0b11 {
1358 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1360 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1361 } else {
1362 let rt: u32 = 12;
1364
1365 let vmrs = 0xEEF10A10 | (rt << 12);
1367 bytes.extend_from_slice(&vmrs.to_le_bytes());
1368
1369 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1371 bytes.extend_from_slice(&bic.to_le_bytes());
1372
1373 if mode != 0 {
1375 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1376 bytes.extend_from_slice(&orr.to_le_bytes());
1377 }
1378
1379 let vmsr = 0xEEE10A10 | (rt << 12);
1381 bytes.extend_from_slice(&vmsr.to_le_bytes());
1382
1383 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1385 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1386
1387 bytes.extend_from_slice(&vmrs.to_le_bytes());
1389 bytes.extend_from_slice(&bic.to_le_bytes());
1390 bytes.extend_from_slice(&vmsr.to_le_bytes());
1391 }
1392
1393 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1395 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1396
1397 Ok(bytes)
1398 }
1399
1400 fn encode_arm_f64_minmax(
1402 &self,
1403 dd: &VfpReg,
1404 dn: &VfpReg,
1405 dm: &VfpReg,
1406 is_min: bool,
1407 ) -> Result<Vec<u8>> {
1408 let mut bytes = Vec::new();
1409 let dn_num = vfp_dreg_to_num(dn)?;
1410 let dm_num = vfp_dreg_to_num(dm)?;
1411 let dd_num = vfp_dreg_to_num(dd)?;
1412
1413 let (vd, d) = encode_dreg(dd_num);
1415 let (vn, n) = encode_dreg(dn_num);
1416 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1417 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1418
1419 let (vm, m) = encode_dreg(dm_num);
1421 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1422 bytes.extend_from_slice(&vcmp.to_le_bytes());
1423
1424 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1426
1427 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1428 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1429 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1430
1431 Ok(bytes)
1432 }
1433
1434 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1436 let mut bytes = Vec::new();
1437
1438 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1440 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1441
1442 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1445 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1446
1447 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1449 bytes.extend_from_slice(&and_sign.to_le_bytes());
1450
1451 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1453 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1454
1455 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1457 bytes.extend_from_slice(&orr.to_le_bytes());
1458
1459 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1461 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1462
1463 Ok(bytes)
1464 }
1465
1466 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1468 let mut bytes = Vec::new();
1469
1470 let sm_num = vfp_sreg_to_num(sm)?;
1473 let (vd, d) = encode_sreg(sm_num);
1474 let (vm, m) = encode_sreg(sm_num);
1475 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1476 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1477 bytes.extend_from_slice(&vcvt.to_le_bytes());
1478
1479 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1481 bytes.extend_from_slice(&vmov.to_le_bytes());
1482
1483 Ok(bytes)
1484 }
1485
1486 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1488 match op {
1491 ArmOp::Add { rd, rn, op2 } => {
1493 let rd_bits = reg_to_bits(rd) as u16;
1494 let rn_bits = reg_to_bits(rn) as u16;
1495
1496 if let Operand2::Reg(rm) = op2 {
1497 let rm_bits = reg_to_bits(rm) as u16;
1498 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1506 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1508 Ok(instr.to_le_bytes().to_vec())
1509 } else {
1510 self.encode_thumb32_add_reg_raw(
1512 rd_bits as u32,
1513 rn_bits as u32,
1514 rm_bits as u32,
1515 )
1516 }
1517 } else if let Operand2::Imm(imm) = op2 {
1518 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1519 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1521 Ok(instr.to_le_bytes().to_vec())
1522 } else {
1523 self.encode_thumb32_add(rd, rn, *imm as u32)
1525 }
1526 } else {
1527 self.encode_thumb32_add(rd, rn, 0)
1529 }
1530 }
1531
1532 ArmOp::Sub { rd, rn, op2 } => {
1533 let rd_bits = reg_to_bits(rd) as u16;
1534 let rn_bits = reg_to_bits(rn) as u16;
1535
1536 if let Operand2::Reg(rm) = op2 {
1537 let rm_bits = reg_to_bits(rm) as u16;
1538 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1540 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1542 Ok(instr.to_le_bytes().to_vec())
1543 } else {
1544 self.encode_thumb32_sub_reg_raw(
1546 rd_bits as u32,
1547 rn_bits as u32,
1548 rm_bits as u32,
1549 )
1550 }
1551 } else if let Operand2::Imm(imm) = op2 {
1552 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1553 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1555 Ok(instr.to_le_bytes().to_vec())
1556 } else {
1557 self.encode_thumb32_sub(rd, rn, *imm as u32)
1558 }
1559 } else {
1560 self.encode_thumb32_sub(rd, rn, 0)
1561 }
1562 }
1563
1564 ArmOp::Mov { rd, op2 } => {
1565 let rd_bits = reg_to_bits(rd) as u16;
1566
1567 if let Operand2::Imm(imm) = op2 {
1568 if *imm <= 255 && rd_bits < 8 {
1569 let imm_bits = (*imm as u16) & 0xFF;
1571 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1572 Ok(instr.to_le_bytes().to_vec())
1573 } else {
1574 self.encode_thumb32_movw(rd, *imm as u32)
1576 }
1577 } else if let Operand2::Reg(rm) = op2 {
1578 let rm_bits = reg_to_bits(rm) as u16;
1579 let d_bit = (rd_bits >> 3) & 1;
1582 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1583 Ok(instr.to_le_bytes().to_vec())
1584 } else {
1585 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1587 }
1588 }
1589
1590 ArmOp::Push { regs } => {
1591 let mut reg_list: u16 = 0;
1595 let mut need_32bit = false;
1596 for r in regs {
1597 let bit = reg_to_bits(r);
1598 if bit >= 8 && *r != Reg::LR {
1599 need_32bit = true;
1600 }
1601 reg_list |= 1 << bit;
1602 }
1603 if !need_32bit {
1604 let m_bit = if reg_list & (1 << 14) != 0 {
1606 1u16
1607 } else {
1608 0u16
1609 };
1610 let low_regs = reg_list & 0xFF;
1611 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1612 Ok(instr.to_le_bytes().to_vec())
1613 } else {
1614 let hw1: u16 = 0xE92D;
1616 let hw2: u16 = reg_list;
1617 let mut bytes = hw1.to_le_bytes().to_vec();
1618 bytes.extend_from_slice(&hw2.to_le_bytes());
1619 Ok(bytes)
1620 }
1621 }
1622
1623 ArmOp::Pop { regs } => {
1624 let mut reg_list: u16 = 0;
1628 let mut need_32bit = false;
1629 for r in regs {
1630 let bit = reg_to_bits(r);
1631 if bit >= 8 && *r != Reg::PC {
1632 need_32bit = true;
1633 }
1634 reg_list |= 1 << bit;
1635 }
1636 if !need_32bit {
1637 let p_bit = if reg_list & (1 << 15) != 0 {
1639 1u16
1640 } else {
1641 0u16
1642 };
1643 let low_regs = reg_list & 0xFF;
1644 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1645 Ok(instr.to_le_bytes().to_vec())
1646 } else {
1647 let hw1: u16 = 0xE8BD;
1649 let hw2: u16 = reg_list;
1650 let mut bytes = hw1.to_le_bytes().to_vec();
1651 bytes.extend_from_slice(&hw2.to_le_bytes());
1652 Ok(bytes)
1653 }
1654 }
1655
1656 ArmOp::Nop => {
1657 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1659 }
1660
1661 ArmOp::Udf { imm } => {
1662 let instr: u16 = 0xDE00 | (*imm as u16);
1665 let bytes = instr.to_le_bytes().to_vec();
1666 encoding_contracts::verify_thumb16(&bytes);
1667 Ok(bytes)
1668 }
1669
1670 ArmOp::Adds { rd, rn, op2 } => {
1673 let rd_bits = reg_to_bits(rd) as u16;
1674 let rn_bits = reg_to_bits(rn) as u16;
1675
1676 if let Operand2::Reg(rm) = op2 {
1677 let rm_bits = reg_to_bits(rm) as u16;
1678 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1683 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1685 Ok(instr.to_le_bytes().to_vec())
1686 } else {
1687 self.encode_thumb32_adds_reg_raw(
1688 rd_bits as u32,
1689 rn_bits as u32,
1690 rm_bits as u32,
1691 )
1692 }
1693 } else {
1694 self.encode_thumb32_adds(rd, rn, 0)
1696 }
1697 }
1698
1699 ArmOp::Adc { rd, rn, op2 } => {
1702 let rd_bits = reg_to_bits(rd);
1703 let rn_bits = reg_to_bits(rn);
1704
1705 if let Operand2::Reg(rm) = op2 {
1706 let rm_bits = reg_to_bits(rm);
1707 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1709 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1710
1711 let mut bytes = hw1.to_le_bytes().to_vec();
1712 bytes.extend_from_slice(&hw2.to_le_bytes());
1713 Ok(bytes)
1714 } else {
1715 let hw1: u16 = (0xF140 | rn_bits) as u16;
1717 let hw2: u16 = (rd_bits << 8) as u16;
1718 let mut bytes = hw1.to_le_bytes().to_vec();
1719 bytes.extend_from_slice(&hw2.to_le_bytes());
1720 Ok(bytes)
1721 }
1722 }
1723
1724 ArmOp::Subs { rd, rn, op2 } => {
1726 let rd_bits = reg_to_bits(rd) as u16;
1727 let rn_bits = reg_to_bits(rn) as u16;
1728
1729 if let Operand2::Reg(rm) = op2 {
1730 let rm_bits = reg_to_bits(rm) as u16;
1731 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1735 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1737 Ok(instr.to_le_bytes().to_vec())
1738 } else {
1739 self.encode_thumb32_subs_reg_raw(
1740 rd_bits as u32,
1741 rn_bits as u32,
1742 rm_bits as u32,
1743 )
1744 }
1745 } else {
1746 self.encode_thumb32_subs(rd, rn, 0)
1748 }
1749 }
1750
1751 ArmOp::Sbc { rd, rn, op2 } => {
1754 let rd_bits = reg_to_bits(rd);
1755 let rn_bits = reg_to_bits(rn);
1756
1757 if let Operand2::Reg(rm) = op2 {
1758 let rm_bits = reg_to_bits(rm);
1759 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1761 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1762
1763 let mut bytes = hw1.to_le_bytes().to_vec();
1764 bytes.extend_from_slice(&hw2.to_le_bytes());
1765 Ok(bytes)
1766 } else {
1767 let hw1: u16 = (0xF160 | rn_bits) as u16;
1769 let hw2: u16 = (rd_bits << 8) as u16;
1770 let mut bytes = hw1.to_le_bytes().to_vec();
1771 bytes.extend_from_slice(&hw2.to_le_bytes());
1772 Ok(bytes)
1773 }
1774 }
1775
1776 ArmOp::Sdiv { rd, rn, rm } => {
1780 let rd_bits = reg_to_bits(rd);
1781 let rn_bits = reg_to_bits(rn);
1782 let rm_bits = reg_to_bits(rm);
1783 reg_bits_checked(rd_bits)?;
1784 reg_bits_checked(rn_bits)?;
1785 reg_bits_checked(rm_bits)?;
1786
1787 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1791 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1792
1793 let mut bytes = hw1.to_le_bytes().to_vec();
1795 bytes.extend_from_slice(&hw2.to_le_bytes());
1796 encoding_contracts::verify_thumb32(&bytes);
1797 Ok(bytes)
1798 }
1799
1800 ArmOp::Udiv { rd, rn, rm } => {
1802 let rd_bits = reg_to_bits(rd);
1803 let rn_bits = reg_to_bits(rn);
1804 let rm_bits = reg_to_bits(rm);
1805 reg_bits_checked(rd_bits)?;
1806 reg_bits_checked(rn_bits)?;
1807 reg_bits_checked(rm_bits)?;
1808
1809 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1811 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1812
1813 let mut bytes = hw1.to_le_bytes().to_vec();
1814 bytes.extend_from_slice(&hw2.to_le_bytes());
1815 encoding_contracts::verify_thumb32(&bytes);
1816 Ok(bytes)
1817 }
1818
1819 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
1820 let rdlo_bits = reg_to_bits(rdlo);
1821 let rdhi_bits = reg_to_bits(rdhi);
1822 let rn_bits = reg_to_bits(rn);
1823 let rm_bits = reg_to_bits(rm);
1824 reg_bits_checked(rdlo_bits)?;
1825 reg_bits_checked(rdhi_bits)?;
1826 reg_bits_checked(rn_bits)?;
1827 reg_bits_checked(rm_bits)?;
1828
1829 let hw1: u16 = (0xFBA0 | rn_bits) as u16;
1831 let hw2: u16 = ((rdlo_bits << 12) | (rdhi_bits << 8) | rm_bits) as u16;
1832
1833 let mut bytes = hw1.to_le_bytes().to_vec();
1834 bytes.extend_from_slice(&hw2.to_le_bytes());
1835 encoding_contracts::verify_thumb32(&bytes);
1836 Ok(bytes)
1837 }
1838
1839 ArmOp::Mul { rd, rn, rm } => {
1841 let rd_bits = reg_to_bits(rd);
1842 let rn_bits = reg_to_bits(rn);
1843 let rm_bits = reg_to_bits(rm);
1844
1845 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1848 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1849
1850 let mut bytes = hw1.to_le_bytes().to_vec();
1851 bytes.extend_from_slice(&hw2.to_le_bytes());
1852 Ok(bytes)
1853 }
1854
1855 ArmOp::Mls { rd, rn, rm, ra } => {
1857 let rd_bits = reg_to_bits(rd);
1858 let rn_bits = reg_to_bits(rn);
1859 let rm_bits = reg_to_bits(rm);
1860 let ra_bits = reg_to_bits(ra);
1861
1862 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1865 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1866
1867 let mut bytes = hw1.to_le_bytes().to_vec();
1868 bytes.extend_from_slice(&hw2.to_le_bytes());
1869 Ok(bytes)
1870 }
1871
1872 ArmOp::And { rd, rn, op2 } => {
1874 if let Operand2::Reg(rm) = op2 {
1875 let rd_bits = reg_to_bits(rd);
1876 let rn_bits = reg_to_bits(rn);
1877 let rm_bits = reg_to_bits(rm);
1878
1879 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1881 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1882
1883 let mut bytes = hw1.to_le_bytes().to_vec();
1884 bytes.extend_from_slice(&hw2.to_le_bytes());
1885 Ok(bytes)
1886 } else if let Operand2::Imm(imm) = op2 {
1887 let rd_bits = reg_to_bits(rd);
1888 let rn_bits = reg_to_bits(rn);
1889 let imm_val = *imm as u32;
1890
1891 let i_bit = (imm_val >> 11) & 1;
1893 let imm3 = (imm_val >> 8) & 0x7;
1894 let imm8 = imm_val & 0xFF;
1895
1896 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1897 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1898
1899 let mut bytes = hw1.to_le_bytes().to_vec();
1900 bytes.extend_from_slice(&hw2.to_le_bytes());
1901 Ok(bytes)
1902 } else {
1903 let instr: u16 = 0xBF00;
1905 Ok(instr.to_le_bytes().to_vec())
1906 }
1907 }
1908
1909 ArmOp::Orr { rd, rn, op2 } => {
1911 if let Operand2::Reg(rm) = op2 {
1912 let rd_bits = reg_to_bits(rd);
1913 let rn_bits = reg_to_bits(rn);
1914 let rm_bits = reg_to_bits(rm);
1915
1916 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1918 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1919
1920 let mut bytes = hw1.to_le_bytes().to_vec();
1921 bytes.extend_from_slice(&hw2.to_le_bytes());
1922 Ok(bytes)
1923 } else {
1924 let instr: u16 = 0xBF00;
1925 Ok(instr.to_le_bytes().to_vec())
1926 }
1927 }
1928
1929 ArmOp::Eor { rd, rn, op2 } => {
1931 if let Operand2::Reg(rm) = op2 {
1932 let rd_bits = reg_to_bits(rd);
1933 let rn_bits = reg_to_bits(rn);
1934 let rm_bits = reg_to_bits(rm);
1935
1936 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1938 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1939
1940 let mut bytes = hw1.to_le_bytes().to_vec();
1941 bytes.extend_from_slice(&hw2.to_le_bytes());
1942 Ok(bytes)
1943 } else {
1944 let instr: u16 = 0xBF00;
1945 Ok(instr.to_le_bytes().to_vec())
1946 }
1947 }
1948
1949 ArmOp::Lsl { rd, rn, shift } => {
1951 let rd_bits = reg_to_bits(rd) as u16;
1952 let rn_bits = reg_to_bits(rn) as u16;
1953 let shift_bits = (*shift as u16) & 0x1F;
1954
1955 if rd_bits < 8 && rn_bits < 8 {
1956 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1958 Ok(instr.to_le_bytes().to_vec())
1959 } else {
1960 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1963 }
1964
1965 ArmOp::Lsr { rd, rn, shift } => {
1966 let rd_bits = reg_to_bits(rd) as u16;
1967 let rn_bits = reg_to_bits(rn) as u16;
1968 let shift_bits = (*shift as u16) & 0x1F;
1969
1970 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1971 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1973 Ok(instr.to_le_bytes().to_vec())
1974 } else {
1975 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
1977 }
1978
1979 ArmOp::Asr { rd, rn, shift } => {
1980 let rd_bits = reg_to_bits(rd) as u16;
1981 let rn_bits = reg_to_bits(rn) as u16;
1982 let shift_bits = (*shift as u16) & 0x1F;
1983
1984 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1985 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1987 Ok(instr.to_le_bytes().to_vec())
1988 } else {
1989 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
1991 }
1992
1993 ArmOp::Ror { rd, rn, shift } => {
1994 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
1997
1998 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
2002 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
2003 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
2004 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
2005
2006 ArmOp::Rsb { rd, rn, imm } => {
2009 let rd_bits = reg_to_bits(rd);
2010 let rn_bits = reg_to_bits(rn);
2011 let imm_val = *imm;
2012
2013 let i_bit = (imm_val >> 11) & 1;
2014 let imm3 = (imm_val >> 8) & 0x7;
2015 let imm8 = imm_val & 0xFF;
2016
2017 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2019 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2021
2022 let mut bytes = hw1.to_le_bytes().to_vec();
2023 bytes.extend_from_slice(&hw2.to_le_bytes());
2024 Ok(bytes)
2025 }
2026
2027 ArmOp::Clz { rd, rm } => {
2029 let rd_bits = reg_to_bits(rd);
2030 let rm_bits = reg_to_bits(rm);
2031
2032 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2035 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2036
2037 let mut bytes = hw1.to_le_bytes().to_vec();
2038 bytes.extend_from_slice(&hw2.to_le_bytes());
2039 Ok(bytes)
2040 }
2041
2042 ArmOp::Rbit { rd, rm } => {
2044 let rd_bits = reg_to_bits(rd);
2045 let rm_bits = reg_to_bits(rm);
2046
2047 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2050 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2051
2052 let mut bytes = hw1.to_le_bytes().to_vec();
2053 bytes.extend_from_slice(&hw2.to_le_bytes());
2054 Ok(bytes)
2055 }
2056
2057 ArmOp::Sxtb { rd, rm } => {
2059 let rd_bits = reg_to_bits(rd) as u16;
2060 let rm_bits = reg_to_bits(rm) as u16;
2061
2062 if rd_bits < 8 && rm_bits < 8 {
2063 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2065 Ok(instr.to_le_bytes().to_vec())
2066 } else {
2067 let rd_bits32 = rd_bits as u32;
2070 let rm_bits32 = rm_bits as u32;
2071 let hw1: u16 = 0xFA4F;
2072 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2073 let mut bytes = hw1.to_le_bytes().to_vec();
2074 bytes.extend_from_slice(&hw2.to_le_bytes());
2075 Ok(bytes)
2076 }
2077 }
2078
2079 ArmOp::Sxth { rd, rm } => {
2081 let rd_bits = reg_to_bits(rd) as u16;
2082 let rm_bits = reg_to_bits(rm) as u16;
2083
2084 if rd_bits < 8 && rm_bits < 8 {
2085 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2087 Ok(instr.to_le_bytes().to_vec())
2088 } else {
2089 let rd_bits32 = rd_bits as u32;
2092 let rm_bits32 = rm_bits as u32;
2093 let hw1: u16 = 0xFA0F;
2094 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2095 let mut bytes = hw1.to_le_bytes().to_vec();
2096 bytes.extend_from_slice(&hw2.to_le_bytes());
2097 Ok(bytes)
2098 }
2099 }
2100
2101 ArmOp::Cmp { rn, op2 } => {
2103 let rn_bits = reg_to_bits(rn) as u16;
2104
2105 if let Operand2::Imm(imm) = op2 {
2106 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2109 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2111 Ok(instr.to_le_bytes().to_vec())
2112 } else {
2113 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2114 }
2115 } else if let Operand2::Reg(rm) = op2 {
2116 let rm_bits = reg_to_bits(rm) as u16;
2117 if rn_bits < 8 && rm_bits < 8 {
2118 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2120 Ok(instr.to_le_bytes().to_vec())
2121 } else {
2122 let n_bit = (rn_bits >> 3) & 1;
2124 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2125 Ok(instr.to_le_bytes().to_vec())
2126 }
2127 } else {
2128 let instr: u16 = 0xBF00;
2129 Ok(instr.to_le_bytes().to_vec())
2130 }
2131 }
2132
2133 ArmOp::Cmn { rn, op2 } => {
2136 let rn_bits = reg_to_bits(rn) as u16;
2137
2138 if let Operand2::Imm(imm) = op2 {
2139 if *imm >= 0 && *imm <= 255 {
2142 let imm8 = *imm as u16 & 0xFF;
2143 let hw1: u16 = 0xF110 | rn_bits;
2144 let hw2: u16 = 0x0F00 | imm8;
2145 let mut bytes = hw1.to_le_bytes().to_vec();
2146 bytes.extend_from_slice(&hw2.to_le_bytes());
2147 Ok(bytes)
2148 } else {
2149 Ok(vec![0xBF, 0x00])
2151 }
2152 } else if let Operand2::Reg(rm) = op2 {
2153 let rm_bits = reg_to_bits(rm) as u16;
2154 if rn_bits < 8 && rm_bits < 8 {
2160 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2162 Ok(instr.to_le_bytes().to_vec())
2163 } else {
2164 let hw1: u16 = 0xEB10 | rn_bits;
2165 let hw2: u16 = 0x0F00 | rm_bits;
2166 let mut bytes = hw1.to_le_bytes().to_vec();
2167 bytes.extend_from_slice(&hw2.to_le_bytes());
2168 Ok(bytes)
2169 }
2170 } else {
2171 Ok(vec![0xBF, 0x00])
2172 }
2173 }
2174
2175 ArmOp::Ldr { rd, addr } => {
2177 let rd_bits = reg_to_bits(rd);
2178 let base_bits = reg_to_bits(&addr.base);
2179
2180 if let Some(offset_reg) = &addr.offset_reg {
2182 let rm_bits = reg_to_bits(offset_reg);
2183
2184 if addr.offset != 0 {
2186 let scratch = Reg::R12;
2189 let mut bytes =
2190 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2191 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2192 return Ok(bytes);
2193 }
2194
2195 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2198 let instr: u16 = 0x5800
2200 | ((rm_bits as u16) << 6)
2201 | ((base_bits as u16) << 3)
2202 | (rd_bits as u16);
2203 return Ok(instr.to_le_bytes().to_vec());
2204 }
2205
2206 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2208 }
2209
2210 let offset = addr.offset as u32;
2212
2213 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2214 let imm5 = (offset >> 2) as u16;
2216 let instr: u16 =
2217 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2218 Ok(instr.to_le_bytes().to_vec())
2219 } else {
2220 self.encode_thumb32_ldr(rd, &addr.base, offset)
2221 }
2222 }
2223
2224 ArmOp::Str { rd, addr } => {
2226 let rd_bits = reg_to_bits(rd);
2227 let base_bits = reg_to_bits(&addr.base);
2228
2229 if let Some(offset_reg) = &addr.offset_reg {
2231 let rm_bits = reg_to_bits(offset_reg);
2232
2233 if addr.offset != 0 {
2235 let scratch = Reg::R12;
2238 let mut bytes =
2239 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2240 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2241 return Ok(bytes);
2242 }
2243
2244 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2247 let instr: u16 = 0x5000
2249 | ((rm_bits as u16) << 6)
2250 | ((base_bits as u16) << 3)
2251 | (rd_bits as u16);
2252 return Ok(instr.to_le_bytes().to_vec());
2253 }
2254
2255 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2257 }
2258
2259 let offset = addr.offset as u32;
2261
2262 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2263 let imm5 = (offset >> 2) as u16;
2265 let instr: u16 =
2266 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2267 Ok(instr.to_le_bytes().to_vec())
2268 } else {
2269 self.encode_thumb32_str(rd, &addr.base, offset)
2270 }
2271 }
2272
2273 ArmOp::Ldrb { rd, addr } => {
2275 let rd_bits = reg_to_bits(rd);
2276 let base_bits = reg_to_bits(&addr.base);
2277
2278 if let Some(offset_reg) = &addr.offset_reg {
2279 if addr.offset != 0 {
2280 let scratch = Reg::R12;
2281 let mut bytes =
2282 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2283 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2284 return Ok(bytes);
2285 }
2286 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2287 }
2288
2289 let offset = addr.offset as u32;
2290 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2291 let instr: u16 = 0x7800
2293 | ((offset as u16) << 6)
2294 | ((base_bits as u16) << 3)
2295 | (rd_bits as u16);
2296 Ok(instr.to_le_bytes().to_vec())
2297 } else {
2298 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2299 }
2300 }
2301
2302 ArmOp::Ldrsb { rd, addr } => {
2304 let rd_bits = reg_to_bits(rd);
2305 let base_bits = reg_to_bits(&addr.base);
2306
2307 if let Some(offset_reg) = &addr.offset_reg {
2308 if addr.offset != 0 {
2309 let scratch = Reg::R12;
2310 let mut bytes =
2311 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2312 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2313 return Ok(bytes);
2314 }
2315 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2316 }
2317
2318 let offset = addr.offset as u32;
2319 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2322 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2324 } else {
2325 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2326 }
2327 }
2328
2329 ArmOp::Ldrh { rd, addr } => {
2331 let rd_bits = reg_to_bits(rd);
2332 let base_bits = reg_to_bits(&addr.base);
2333
2334 if let Some(offset_reg) = &addr.offset_reg {
2335 if addr.offset != 0 {
2336 let scratch = Reg::R12;
2337 let mut bytes =
2338 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2339 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2340 return Ok(bytes);
2341 }
2342 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2343 }
2344
2345 let offset = addr.offset as u32;
2346 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2347 let imm5 = (offset >> 1) as u16;
2349 let instr: u16 =
2350 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2351 Ok(instr.to_le_bytes().to_vec())
2352 } else {
2353 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2354 }
2355 }
2356
2357 ArmOp::Ldrsh { rd, addr } => {
2359 if let Some(offset_reg) = &addr.offset_reg {
2360 if addr.offset != 0 {
2361 let scratch = Reg::R12;
2362 let mut bytes =
2363 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2364 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2365 return Ok(bytes);
2366 }
2367 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2368 }
2369
2370 let offset = addr.offset as u32;
2371 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2372 }
2373
2374 ArmOp::Strb { rd, addr } => {
2376 let rd_bits = reg_to_bits(rd);
2377 let base_bits = reg_to_bits(&addr.base);
2378
2379 if let Some(offset_reg) = &addr.offset_reg {
2380 if addr.offset != 0 {
2381 let scratch = Reg::R12;
2382 let mut bytes =
2383 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2384 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2385 return Ok(bytes);
2386 }
2387 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2388 }
2389
2390 let offset = addr.offset as u32;
2391 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2392 let instr: u16 = 0x7000
2394 | ((offset as u16) << 6)
2395 | ((base_bits as u16) << 3)
2396 | (rd_bits as u16);
2397 Ok(instr.to_le_bytes().to_vec())
2398 } else {
2399 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2400 }
2401 }
2402
2403 ArmOp::Strh { rd, addr } => {
2405 let rd_bits = reg_to_bits(rd);
2406 let base_bits = reg_to_bits(&addr.base);
2407
2408 if let Some(offset_reg) = &addr.offset_reg {
2409 if addr.offset != 0 {
2410 let scratch = Reg::R12;
2411 let mut bytes =
2412 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2413 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2414 return Ok(bytes);
2415 }
2416 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2417 }
2418
2419 let offset = addr.offset as u32;
2420 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2421 let imm5 = (offset >> 1) as u16;
2423 let instr: u16 =
2424 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2425 Ok(instr.to_le_bytes().to_vec())
2426 } else {
2427 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2428 }
2429 }
2430
2431 ArmOp::MemorySize { rd } => {
2433 let rd_bits = reg_to_bits(rd);
2436 let r10_bits = reg_to_bits(&Reg::R10);
2437 if rd_bits < 8 && r10_bits < 8 {
2438 let instr: u16 =
2439 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2440 Ok(instr.to_le_bytes().to_vec())
2441 } else {
2442 let imm5: u32 = 16;
2444 let imm3 = (imm5 >> 2) & 0x7;
2445 let imm2 = imm5 & 0x3;
2446 let hw1: u16 = 0xEA4F;
2447 let hw2: u16 =
2448 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2449 let mut bytes = hw1.to_le_bytes().to_vec();
2450 bytes.extend_from_slice(&hw2.to_le_bytes());
2451 Ok(bytes)
2452 }
2453 }
2454
2455 ArmOp::MemoryGrow { rd, .. } => {
2457 let rd_bits = reg_to_bits(rd);
2461 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2464 bytes.extend_from_slice(&hw2.to_le_bytes());
2465 Ok(bytes)
2466 }
2467
2468 ArmOp::Bx { rm } => {
2470 let rm_bits = reg_to_bits(rm) as u16;
2471 let instr: u16 = 0x4700 | (rm_bits << 3);
2473 Ok(instr.to_le_bytes().to_vec())
2474 }
2475
2476 ArmOp::Blx { rm } => {
2479 let rm_bits = reg_to_bits(rm) as u16;
2480 let instr: u16 = 0x4780 | (rm_bits << 3);
2481 Ok(instr.to_le_bytes().to_vec())
2482 }
2483
2484 ArmOp::CallIndirect {
2488 rd: _,
2489 type_idx: _,
2490 table_index_reg,
2491 } => {
2492 let idx_reg = reg_to_bits(table_index_reg);
2493 let mut bytes = Vec::new();
2494
2495 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2511 bytes.extend_from_slice(&hw1.to_le_bytes());
2512 bytes.extend_from_slice(&hw2.to_le_bytes());
2513
2514 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2520 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2521
2522 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2526
2527 Ok(bytes)
2528 }
2529
2530 ArmOp::Label { .. } => Ok(Vec::new()),
2532
2533 ArmOp::Bcc { cond, label: _ } => {
2535 use synth_synthesis::Condition;
2536 let cond_bits: u16 = match cond {
2537 Condition::EQ => 0x0,
2538 Condition::NE => 0x1,
2539 Condition::HS => 0x2,
2540 Condition::LO => 0x3,
2541 Condition::HI => 0x8,
2542 Condition::LS => 0x9,
2543 Condition::GE => 0xA,
2544 Condition::LT => 0xB,
2545 Condition::GT => 0xC,
2546 Condition::LE => 0xD,
2547 };
2548 let instr: u16 = 0xD000 | (cond_bits << 8);
2550 Ok(instr.to_le_bytes().to_vec())
2551 }
2552
2553 ArmOp::B { label: _ } => {
2555 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2559 }
2560
2561 ArmOp::Bhs { label: _ } => {
2564 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2568 }
2569
2570 ArmOp::Blo { label: _ } => {
2573 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2577 }
2578
2579 ArmOp::BOffset { offset } => {
2582 let halfword_offset = *offset;
2585
2586 if (-1024..=1022).contains(&halfword_offset) {
2589 let imm11 = (halfword_offset as u16) & 0x7FF;
2591 let instr: u16 = 0xE000 | imm11;
2592 Ok(instr.to_le_bytes().to_vec())
2593 } else {
2594 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2610 let uoffset = signed_offset as u32;
2611 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;
2619 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2620
2621 let mut bytes = hw1.to_le_bytes().to_vec();
2622 bytes.extend_from_slice(&hw2.to_le_bytes());
2623 Ok(bytes)
2624 }
2625 }
2626
2627 ArmOp::BCondOffset { cond, offset } => {
2629 use synth_synthesis::Condition;
2630 let cond_bits: u16 = match cond {
2631 Condition::EQ => 0x0,
2632 Condition::NE => 0x1,
2633 Condition::HS => 0x2,
2634 Condition::LO => 0x3,
2635 Condition::HI => 0x8,
2636 Condition::LS => 0x9,
2637 Condition::GE => 0xA,
2638 Condition::LT => 0xB,
2639 Condition::GT => 0xC,
2640 Condition::LE => 0xD,
2641 };
2642
2643 let halfword_offset = *offset;
2646
2647 if (-128..=127).contains(&halfword_offset) {
2650 let imm8 = (halfword_offset as u16) & 0xFF;
2651 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2652 Ok(instr.to_le_bytes().to_vec())
2653 } else {
2654 let offset = halfword_offset >> 1;
2658 let s = if offset < 0 { 1u32 } else { 0u32 };
2659 let imm6 = ((offset >> 11) as u32) & 0x3F;
2660 let imm11 = (offset as u32) & 0x7FF;
2661 let j1 = if s == 1 { 1 } else { 0 };
2662 let j2 = if s == 1 { 1 } else { 0 };
2663
2664 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2665 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2666
2667 let mut bytes = hw1.to_le_bytes().to_vec();
2668 bytes.extend_from_slice(&hw2.to_le_bytes());
2669 Ok(bytes)
2670 }
2671 }
2672
2673 ArmOp::Bl { label: _ } => {
2674 let hw1: u16 = 0xF7FF;
2689 let hw2: u16 = 0xFFFE;
2690 let mut bytes = hw1.to_le_bytes().to_vec();
2691 bytes.extend_from_slice(&hw2.to_le_bytes());
2692 Ok(bytes)
2693 }
2694
2695 ArmOp::Mvn { rd, op2 } => {
2697 if let Operand2::Reg(rm) = op2 {
2698 let rd_bits = reg_to_bits(rd) as u16;
2699 let rm_bits = reg_to_bits(rm) as u16;
2700
2701 if rd_bits < 8 && rm_bits < 8 {
2702 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2704 Ok(instr.to_le_bytes().to_vec())
2705 } else {
2706 let hw1: u16 = 0xEA6F_u16;
2708 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2709 let mut bytes = hw1.to_le_bytes().to_vec();
2710 bytes.extend_from_slice(&hw2.to_le_bytes());
2711 Ok(bytes)
2712 }
2713 } else {
2714 let instr: u16 = 0xBF00;
2715 Ok(instr.to_le_bytes().to_vec())
2716 }
2717 }
2718
2719 ArmOp::Movw { rd, imm16 } => {
2721 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2722 }
2723
2724 ArmOp::Movt { rd, imm16 } => {
2726 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2727 }
2728
2729 ArmOp::MovwSym { rd, addend, .. } => {
2734 self.encode_thumb32_movw_raw(reg_to_bits(rd), (*addend as u32) & 0xffff)
2735 }
2736 ArmOp::MovtSym { rd, addend, .. } => {
2737 self.encode_thumb32_movt_raw(reg_to_bits(rd), ((*addend as u32) >> 16) & 0xffff)
2738 }
2739
2740 ArmOp::SetCond { rd, cond } => {
2746 let rd_bits = reg_to_bits(rd) as u16;
2747
2748 use synth_synthesis::Condition;
2750 let cond_bits: u16 = match cond {
2751 Condition::EQ => 0x0,
2752 Condition::NE => 0x1,
2753 Condition::LT => 0xB,
2754 Condition::LE => 0xD,
2755 Condition::GT => 0xC,
2756 Condition::GE => 0xA,
2757 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2762
2763 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2768 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2769
2770 let mut bytes = ite_instr.to_le_bytes().to_vec();
2781 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2782 if rd_bits <= 7 {
2783 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2785 } else {
2786 let hw1: u16 = 0xF04F;
2788 let hw2: u16 = (rd_bits << 8) | imm;
2789 bytes.extend_from_slice(&hw1.to_le_bytes());
2790 bytes.extend_from_slice(&hw2.to_le_bytes());
2791 }
2792 };
2793 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2796 }
2797
2798 ArmOp::I64SetCond {
2803 rd,
2804 rn_lo,
2805 rn_hi,
2806 rm_lo,
2807 rm_hi,
2808 cond,
2809 } => {
2810 use synth_synthesis::Condition;
2811 let rd_bits = reg_to_bits(rd) as u16;
2812 let mut bytes = Vec::new();
2813
2814 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2816 rm: &synth_synthesis::Reg|
2817 -> Vec<u8> {
2818 let rn_bits = reg_to_bits(rn) as u16;
2819 let rm_bits = reg_to_bits(rm) as u16;
2820 if rn_bits < 8 && rm_bits < 8 {
2821 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2822 instr.to_le_bytes().to_vec()
2823 } else {
2824 let n_bit = (rn_bits >> 3) & 1;
2825 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2826 instr.to_le_bytes().to_vec()
2827 }
2828 };
2829
2830 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2832 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2833 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2834 ite_instr.to_le_bytes().to_vec()
2835 };
2836
2837 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2839 let mut b = encode_ite(cond_bits);
2840 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2841 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2842 b.extend_from_slice(&mov_one.to_le_bytes());
2843 b.extend_from_slice(&mov_zero.to_le_bytes());
2844 b
2845 };
2846
2847 match cond {
2848 Condition::EQ | Condition::NE => {
2849 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2851
2852 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2855
2856 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2858
2859 let cond_bits: u16 = match cond {
2861 Condition::EQ => 0x0,
2862 Condition::NE => 0x1,
2863 _ => unreachable!(),
2864 };
2865 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2866 }
2867
2868 Condition::LT => {
2869 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2871
2872 let rn_hi_bits = reg_to_bits(rn_hi);
2875 let rm_hi_bits = reg_to_bits(rm_hi);
2876 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2877 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2878 bytes.extend_from_slice(&hw1.to_le_bytes());
2879 bytes.extend_from_slice(&hw2.to_le_bytes());
2880
2881 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2884
2885 Condition::GT => {
2886 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2889
2890 let rm_hi_bits = reg_to_bits(rm_hi);
2892 let rn_hi_bits = reg_to_bits(rn_hi);
2893 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2894 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2895 bytes.extend_from_slice(&hw1.to_le_bytes());
2896 bytes.extend_from_slice(&hw2.to_le_bytes());
2897
2898 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2901
2902 Condition::LE => {
2903 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2907
2908 let rm_hi_bits = reg_to_bits(rm_hi);
2910 let rn_hi_bits = reg_to_bits(rn_hi);
2911 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2912 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2913 bytes.extend_from_slice(&hw1.to_le_bytes());
2914 bytes.extend_from_slice(&hw2.to_le_bytes());
2915
2916 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2919
2920 Condition::GE => {
2921 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2924
2925 let rn_hi_bits = reg_to_bits(rn_hi);
2927 let rm_hi_bits = reg_to_bits(rm_hi);
2928 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2929 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2930 bytes.extend_from_slice(&hw1.to_le_bytes());
2931 bytes.extend_from_slice(&hw2.to_le_bytes());
2932
2933 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2936
2937 Condition::LO => {
2939 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2941 let rn_hi_bits = reg_to_bits(rn_hi);
2942 let rm_hi_bits = reg_to_bits(rm_hi);
2943 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2944 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2945 bytes.extend_from_slice(&hw1.to_le_bytes());
2946 bytes.extend_from_slice(&hw2.to_le_bytes());
2947 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2949
2950 Condition::HI => {
2951 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2953 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 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2961
2962 Condition::LS => {
2963 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2965 let rm_hi_bits = reg_to_bits(rm_hi);
2966 let rn_hi_bits = reg_to_bits(rn_hi);
2967 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2968 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2969 bytes.extend_from_slice(&hw1.to_le_bytes());
2970 bytes.extend_from_slice(&hw2.to_le_bytes());
2971 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2973
2974 Condition::HS => {
2975 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2977 let rn_hi_bits = reg_to_bits(rn_hi);
2978 let rm_hi_bits = reg_to_bits(rm_hi);
2979 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2980 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2981 bytes.extend_from_slice(&hw1.to_le_bytes());
2982 bytes.extend_from_slice(&hw2.to_le_bytes());
2983 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2985 }
2986
2987 Ok(bytes)
2988 }
2989
2990 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2993 let rd_bits = reg_to_bits(rd);
2994 let rn_lo_bits = reg_to_bits(rn_lo);
2995 let rn_hi_bits = reg_to_bits(rn_hi);
2996 let mut bytes = Vec::new();
2997
2998 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
3000 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
3001 bytes.extend_from_slice(&hw1.to_le_bytes());
3002 bytes.extend_from_slice(&hw2.to_le_bytes());
3003
3004 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
3006 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
3007
3008 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
3011 bytes.extend_from_slice(&ite_instr.to_le_bytes());
3012 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
3013 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
3014 bytes.extend_from_slice(&mov_one.to_le_bytes());
3015 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3016
3017 Ok(bytes)
3018 }
3019
3020 ArmOp::I64Mul {
3024 rd_lo,
3025 rd_hi,
3026 rn_lo,
3027 rn_hi,
3028 rm_lo,
3029 rm_hi,
3030 } => {
3031 let rd_lo_bits = reg_to_bits(rd_lo);
3032 let rd_hi_bits = reg_to_bits(rd_hi);
3033 let rn_lo_bits = reg_to_bits(rn_lo);
3034 let rn_hi_bits = reg_to_bits(rn_hi);
3035 let rm_lo_bits = reg_to_bits(rm_lo);
3036 let rm_hi_bits = reg_to_bits(rm_hi);
3037 let r12: u32 = 12; let mut bytes = Vec::new();
3039
3040 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3043 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3044 bytes.extend_from_slice(&hw1.to_le_bytes());
3045 bytes.extend_from_slice(&hw2.to_le_bytes());
3046
3047 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3050 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3051 bytes.extend_from_slice(&hw1.to_le_bytes());
3052 bytes.extend_from_slice(&hw2.to_le_bytes());
3053
3054 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3057 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3058 bytes.extend_from_slice(&hw1.to_le_bytes());
3059 bytes.extend_from_slice(&hw2.to_le_bytes());
3060
3061 let d_bit = (rd_hi_bits >> 3) & 1;
3064 let add_instr: u16 =
3065 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3066 bytes.extend_from_slice(&add_instr.to_le_bytes());
3067
3068 Ok(bytes)
3069 }
3070
3071 ArmOp::I64Shl {
3074 rd_lo,
3075 rd_hi,
3076 rn_lo,
3077 rn_hi,
3078 rm_lo,
3079 rm_hi,
3080 } => {
3081 let rd_lo_bits = reg_to_bits(rd_lo);
3082 let rd_hi_bits = reg_to_bits(rd_hi);
3083 let rn_lo_bits = reg_to_bits(rn_lo);
3084 let rn_hi_bits = reg_to_bits(rn_hi);
3085 let rm_lo_bits = reg_to_bits(rm_lo);
3086 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3088
3089 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3091 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3092 bytes.extend_from_slice(&hw1.to_le_bytes());
3093 bytes.extend_from_slice(&hw2.to_le_bytes());
3094
3095 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3097 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3098 bytes.extend_from_slice(&hw1.to_le_bytes());
3099 bytes.extend_from_slice(&hw2.to_le_bytes());
3100
3101 let bpl: u16 = 0xD50A;
3103 bytes.extend_from_slice(&bpl.to_le_bytes());
3104
3105 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3108 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3109 bytes.extend_from_slice(&hw1.to_le_bytes());
3110 bytes.extend_from_slice(&hw2.to_le_bytes());
3111
3112 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3114 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3115 bytes.extend_from_slice(&hw1.to_le_bytes());
3116 bytes.extend_from_slice(&hw2.to_le_bytes());
3117
3118 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3120 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3121 bytes.extend_from_slice(&hw1.to_le_bytes());
3122 bytes.extend_from_slice(&hw2.to_le_bytes());
3123
3124 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3126 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3127 bytes.extend_from_slice(&hw1.to_le_bytes());
3128 bytes.extend_from_slice(&hw2.to_le_bytes());
3129
3130 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3132 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3133 bytes.extend_from_slice(&hw1.to_le_bytes());
3134 bytes.extend_from_slice(&hw2.to_le_bytes());
3135
3136 let b_done: u16 = 0xE002;
3138 bytes.extend_from_slice(&b_done.to_le_bytes());
3139
3140 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3143 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3144 bytes.extend_from_slice(&hw1.to_le_bytes());
3145 bytes.extend_from_slice(&hw2.to_le_bytes());
3146
3147 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3149 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3150
3151 Ok(bytes) }
3153
3154 ArmOp::I64ShrU {
3156 rd_lo,
3157 rd_hi,
3158 rn_lo,
3159 rn_hi,
3160 rm_lo,
3161 rm_hi,
3162 } => {
3163 let rd_lo_bits = reg_to_bits(rd_lo);
3164 let rd_hi_bits = reg_to_bits(rd_hi);
3165 let rn_lo_bits = reg_to_bits(rn_lo);
3166 let rn_hi_bits = reg_to_bits(rn_hi);
3167 let rm_lo_bits = reg_to_bits(rm_lo);
3168 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3170
3171 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3173 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3174 bytes.extend_from_slice(&hw1.to_le_bytes());
3175 bytes.extend_from_slice(&hw2.to_le_bytes());
3176
3177 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3179 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3180 bytes.extend_from_slice(&hw1.to_le_bytes());
3181 bytes.extend_from_slice(&hw2.to_le_bytes());
3182
3183 let bpl: u16 = 0xD50A;
3185 bytes.extend_from_slice(&bpl.to_le_bytes());
3186
3187 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3190 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3191 bytes.extend_from_slice(&hw1.to_le_bytes());
3192 bytes.extend_from_slice(&hw2.to_le_bytes());
3193
3194 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3196 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3197 bytes.extend_from_slice(&hw1.to_le_bytes());
3198 bytes.extend_from_slice(&hw2.to_le_bytes());
3199
3200 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3202 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3203 bytes.extend_from_slice(&hw1.to_le_bytes());
3204 bytes.extend_from_slice(&hw2.to_le_bytes());
3205
3206 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3208 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3209 bytes.extend_from_slice(&hw1.to_le_bytes());
3210 bytes.extend_from_slice(&hw2.to_le_bytes());
3211
3212 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3214 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3215 bytes.extend_from_slice(&hw1.to_le_bytes());
3216 bytes.extend_from_slice(&hw2.to_le_bytes());
3217
3218 let b_done: u16 = 0xE002;
3220 bytes.extend_from_slice(&b_done.to_le_bytes());
3221
3222 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3225 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3226 bytes.extend_from_slice(&hw1.to_le_bytes());
3227 bytes.extend_from_slice(&hw2.to_le_bytes());
3228
3229 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3231 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3232
3233 Ok(bytes) }
3235
3236 ArmOp::I64ShrS {
3238 rd_lo,
3239 rd_hi,
3240 rn_lo,
3241 rn_hi,
3242 rm_lo,
3243 rm_hi,
3244 } => {
3245 let rd_lo_bits = reg_to_bits(rd_lo);
3246 let rd_hi_bits = reg_to_bits(rd_hi);
3247 let rn_lo_bits = reg_to_bits(rn_lo);
3248 let rn_hi_bits = reg_to_bits(rn_hi);
3249 let rm_lo_bits = reg_to_bits(rm_lo);
3250 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3252
3253 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3255 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3256 bytes.extend_from_slice(&hw1.to_le_bytes());
3257 bytes.extend_from_slice(&hw2.to_le_bytes());
3258
3259 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3261 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3262 bytes.extend_from_slice(&hw1.to_le_bytes());
3263 bytes.extend_from_slice(&hw2.to_le_bytes());
3264
3265 let bpl: u16 = 0xD50A;
3267 bytes.extend_from_slice(&bpl.to_le_bytes());
3268
3269 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3272 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3273 bytes.extend_from_slice(&hw1.to_le_bytes());
3274 bytes.extend_from_slice(&hw2.to_le_bytes());
3275
3276 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3278 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3279 bytes.extend_from_slice(&hw1.to_le_bytes());
3280 bytes.extend_from_slice(&hw2.to_le_bytes());
3281
3282 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3284 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3285 bytes.extend_from_slice(&hw1.to_le_bytes());
3286 bytes.extend_from_slice(&hw2.to_le_bytes());
3287
3288 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3290 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3291 bytes.extend_from_slice(&hw1.to_le_bytes());
3292 bytes.extend_from_slice(&hw2.to_le_bytes());
3293
3294 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3296 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3297 bytes.extend_from_slice(&hw1.to_le_bytes());
3298 bytes.extend_from_slice(&hw2.to_le_bytes());
3299
3300 let b_done: u16 = 0xE003;
3302 bytes.extend_from_slice(&b_done.to_le_bytes());
3303
3304 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3307 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3308 bytes.extend_from_slice(&hw1.to_le_bytes());
3309 bytes.extend_from_slice(&hw2.to_le_bytes());
3310
3311 let hw1: u16 = 0xEA4F;
3315 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3316 bytes.extend_from_slice(&hw1.to_le_bytes());
3317 bytes.extend_from_slice(&hw2.to_le_bytes());
3318
3319 Ok(bytes) }
3321
3322 ArmOp::I64Rotl {
3327 rdlo,
3328 rdhi,
3329 rnlo,
3330 rnhi,
3331 shift,
3332 } => {
3333 let rd_lo_bits = reg_to_bits(rdlo);
3334 let rd_hi_bits = reg_to_bits(rdhi);
3335 let rn_lo_bits = reg_to_bits(rnlo);
3336 let rn_hi_bits = reg_to_bits(rnhi);
3337 let shift_bits = reg_to_bits(shift);
3338 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3342
3343 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3345
3346 let hw1: u16 = (0xF000 | shift_bits) as u16;
3348 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3349 bytes.extend_from_slice(&hw1.to_le_bytes());
3350 bytes.extend_from_slice(&hw2.to_le_bytes());
3351
3352 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3354 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3355 bytes.extend_from_slice(&hw1.to_le_bytes());
3356 bytes.extend_from_slice(&hw2.to_le_bytes());
3357
3358 let bpl: u16 = 0xD50E;
3360 bytes.extend_from_slice(&bpl.to_le_bytes());
3361
3362 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3365 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3366 bytes.extend_from_slice(&hw1.to_le_bytes());
3367 bytes.extend_from_slice(&hw2.to_le_bytes());
3368
3369 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3371 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3372 bytes.extend_from_slice(&hw1.to_le_bytes());
3373 bytes.extend_from_slice(&hw2.to_le_bytes());
3374
3375 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3377 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3378 bytes.extend_from_slice(&hw1.to_le_bytes());
3379 bytes.extend_from_slice(&hw2.to_le_bytes());
3380
3381 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3383 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3384 bytes.extend_from_slice(&hw1.to_le_bytes());
3385 bytes.extend_from_slice(&hw2.to_le_bytes());
3386
3387 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3389 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3390 bytes.extend_from_slice(&hw1.to_le_bytes());
3391 bytes.extend_from_slice(&hw2.to_le_bytes());
3392
3393 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3395 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3396 bytes.extend_from_slice(&hw1.to_le_bytes());
3397 bytes.extend_from_slice(&hw2.to_le_bytes());
3398
3399 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3401 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3402 bytes.extend_from_slice(&hw1.to_le_bytes());
3403 bytes.extend_from_slice(&hw2.to_le_bytes());
3404
3405 let b_done: u16 = 0xE00E;
3407 bytes.extend_from_slice(&b_done.to_le_bytes());
3408
3409 let hw1: u16 = (0xF1C0 | r3) as u16;
3413 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3414 bytes.extend_from_slice(&hw1.to_le_bytes());
3415 bytes.extend_from_slice(&hw2.to_le_bytes());
3416
3417 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3419 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3420 bytes.extend_from_slice(&hw1.to_le_bytes());
3421 bytes.extend_from_slice(&hw2.to_le_bytes());
3422
3423 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3425 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3426 bytes.extend_from_slice(&hw1.to_le_bytes());
3427 bytes.extend_from_slice(&hw2.to_le_bytes());
3428
3429 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3431 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3432 bytes.extend_from_slice(&hw1.to_le_bytes());
3433 bytes.extend_from_slice(&hw2.to_le_bytes());
3434
3435 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3437 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3438 bytes.extend_from_slice(&hw1.to_le_bytes());
3439 bytes.extend_from_slice(&hw2.to_le_bytes());
3440
3441 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3443 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3444 bytes.extend_from_slice(&hw1.to_le_bytes());
3445 bytes.extend_from_slice(&hw2.to_le_bytes());
3446
3447 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3449 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3450 bytes.extend_from_slice(&hw1.to_le_bytes());
3451 bytes.extend_from_slice(&hw2.to_le_bytes());
3452
3453 let d_bit = (rd_hi_bits >> 3) & 1;
3455 let mov_instr: u16 =
3456 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3457 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3458
3459 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3461
3462 Ok(bytes) }
3464
3465 ArmOp::I64Rotr {
3470 rdlo,
3471 rdhi,
3472 rnlo,
3473 rnhi,
3474 shift,
3475 } => {
3476 let rd_lo_bits = reg_to_bits(rdlo);
3477 let rd_hi_bits = reg_to_bits(rdhi);
3478 let rn_lo_bits = reg_to_bits(rnlo);
3479 let rn_hi_bits = reg_to_bits(rnhi);
3480 let shift_bits = reg_to_bits(shift);
3481 let r12: u32 = 12;
3482 let r3: u32 = 3;
3483 let r4: u32 = 4;
3484 let mut bytes = Vec::new();
3485
3486 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3488
3489 let hw1: u16 = (0xF000 | shift_bits) as u16;
3491 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3492 bytes.extend_from_slice(&hw1.to_le_bytes());
3493 bytes.extend_from_slice(&hw2.to_le_bytes());
3494
3495 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3497 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3498 bytes.extend_from_slice(&hw1.to_le_bytes());
3499 bytes.extend_from_slice(&hw2.to_le_bytes());
3500
3501 let bpl: u16 = 0xD50E;
3503 bytes.extend_from_slice(&bpl.to_le_bytes());
3504
3505 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3508 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3509 bytes.extend_from_slice(&hw1.to_le_bytes());
3510 bytes.extend_from_slice(&hw2.to_le_bytes());
3511
3512 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3514 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3515 bytes.extend_from_slice(&hw1.to_le_bytes());
3516 bytes.extend_from_slice(&hw2.to_le_bytes());
3517
3518 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3520 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3521 bytes.extend_from_slice(&hw1.to_le_bytes());
3522 bytes.extend_from_slice(&hw2.to_le_bytes());
3523
3524 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3526 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3527 bytes.extend_from_slice(&hw1.to_le_bytes());
3528 bytes.extend_from_slice(&hw2.to_le_bytes());
3529
3530 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3532 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3533 bytes.extend_from_slice(&hw1.to_le_bytes());
3534 bytes.extend_from_slice(&hw2.to_le_bytes());
3535
3536 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3538 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3539 bytes.extend_from_slice(&hw1.to_le_bytes());
3540 bytes.extend_from_slice(&hw2.to_le_bytes());
3541
3542 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3544 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3545 bytes.extend_from_slice(&hw1.to_le_bytes());
3546 bytes.extend_from_slice(&hw2.to_le_bytes());
3547
3548 let b_done: u16 = 0xE00E;
3550 bytes.extend_from_slice(&b_done.to_le_bytes());
3551
3552 let hw1: u16 = (0xF1C0 | r3) as u16;
3555 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3556 bytes.extend_from_slice(&hw1.to_le_bytes());
3557 bytes.extend_from_slice(&hw2.to_le_bytes());
3558
3559 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3561 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3562 bytes.extend_from_slice(&hw1.to_le_bytes());
3563 bytes.extend_from_slice(&hw2.to_le_bytes());
3564
3565 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3567 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3568 bytes.extend_from_slice(&hw1.to_le_bytes());
3569 bytes.extend_from_slice(&hw2.to_le_bytes());
3570
3571 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3573 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3574 bytes.extend_from_slice(&hw1.to_le_bytes());
3575 bytes.extend_from_slice(&hw2.to_le_bytes());
3576
3577 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3579 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3580 bytes.extend_from_slice(&hw1.to_le_bytes());
3581 bytes.extend_from_slice(&hw2.to_le_bytes());
3582
3583 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3585 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3586 bytes.extend_from_slice(&hw1.to_le_bytes());
3587 bytes.extend_from_slice(&hw2.to_le_bytes());
3588
3589 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3591 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3592 bytes.extend_from_slice(&hw1.to_le_bytes());
3593 bytes.extend_from_slice(&hw2.to_le_bytes());
3594
3595 let d_bit = (rd_lo_bits >> 3) & 1;
3597 let mov_instr: u16 =
3598 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3599 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3600
3601 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3603
3604 Ok(bytes) }
3606
3607 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3621 let rd_bits = reg_to_bits(rd);
3622 let rn_lo_bits = reg_to_bits(rnlo);
3623 let rn_hi_bits = reg_to_bits(rnhi);
3624 let mut bytes = Vec::new();
3625
3626 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3628 let hw2: u16 = 0x0F00;
3629 bytes.extend_from_slice(&hw1.to_le_bytes());
3630 bytes.extend_from_slice(&hw2.to_le_bytes());
3631
3632 let beq: u16 = 0xD003;
3635 bytes.extend_from_slice(&beq.to_le_bytes());
3636
3637 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3640 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3641 bytes.extend_from_slice(&hw1.to_le_bytes());
3642 bytes.extend_from_slice(&hw2.to_le_bytes());
3643
3644 let b_done: u16 = 0xE004;
3647 bytes.extend_from_slice(&b_done.to_le_bytes());
3648
3649 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3651
3652 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3656 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3657 bytes.extend_from_slice(&hw1.to_le_bytes());
3658 bytes.extend_from_slice(&hw2.to_le_bytes());
3659
3660 let hw1: u16 = (0xF100 | rd_bits) as u16;
3662 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3663 bytes.extend_from_slice(&hw1.to_le_bytes());
3664 bytes.extend_from_slice(&hw2.to_le_bytes());
3665
3666 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3670 bytes.extend_from_slice(&mov0.to_le_bytes());
3671
3672 Ok(bytes)
3673 }
3674
3675 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3691 let rd_bits = reg_to_bits(rd);
3692 let rn_lo_bits = reg_to_bits(rnlo);
3693 let rn_hi_bits = reg_to_bits(rnhi);
3694 let mut bytes = Vec::new();
3695
3696 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3698 let hw2: u16 = 0x0F00;
3699 bytes.extend_from_slice(&hw1.to_le_bytes());
3700 bytes.extend_from_slice(&hw2.to_le_bytes());
3701
3702 let beq: u16 = 0xD005;
3705 bytes.extend_from_slice(&beq.to_le_bytes());
3706
3707 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3710 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3711 bytes.extend_from_slice(&hw1.to_le_bytes());
3712 bytes.extend_from_slice(&hw2.to_le_bytes());
3713
3714 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3717 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3718 bytes.extend_from_slice(&hw1.to_le_bytes());
3719 bytes.extend_from_slice(&hw2.to_le_bytes());
3720
3721 let b_done: u16 = 0xE006;
3724 bytes.extend_from_slice(&b_done.to_le_bytes());
3725
3726 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3728
3729 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3733 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3734 bytes.extend_from_slice(&hw1.to_le_bytes());
3735 bytes.extend_from_slice(&hw2.to_le_bytes());
3736
3737 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3740 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3741 bytes.extend_from_slice(&hw1.to_le_bytes());
3742 bytes.extend_from_slice(&hw2.to_le_bytes());
3743
3744 let hw1: u16 = (0xF100 | rd_bits) as u16;
3746 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3747 bytes.extend_from_slice(&hw1.to_le_bytes());
3748 bytes.extend_from_slice(&hw2.to_le_bytes());
3749
3750 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3753 bytes.extend_from_slice(&mov0.to_le_bytes());
3754
3755 Ok(bytes)
3756 }
3757
3758 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3762 let rd_bits = reg_to_bits(rd);
3763 let rn_lo_bits = reg_to_bits(rnlo);
3764 let rn_hi_bits = reg_to_bits(rnhi);
3765 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3768
3769 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3771
3772 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3782 bytes.extend_from_slice(&mov.to_le_bytes());
3783
3784 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3787 bytes.extend_from_slice(&mov.to_le_bytes());
3788
3789 let hw1: u16 = 0xEA4F;
3793 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3794 bytes.extend_from_slice(&hw1.to_le_bytes());
3795 bytes.extend_from_slice(&hw2.to_le_bytes());
3796
3797 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3800 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3801 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3803 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3804
3805 let hw1: u16 = (0xEA00 | r12) as u16;
3807 let hw2: u16 = ((r12 << 8) | r3) as u16;
3808 bytes.extend_from_slice(&hw1.to_le_bytes());
3809 bytes.extend_from_slice(&hw2.to_le_bytes());
3810
3811 let hw1: u16 = (0xEBA0 | 4) as u16;
3813 let hw2: u16 = ((4 << 8) | r12) as u16;
3814 bytes.extend_from_slice(&hw1.to_le_bytes());
3815 bytes.extend_from_slice(&hw2.to_le_bytes());
3816
3817 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3821 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3822 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3824 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3825
3826 let hw1: u16 = (0xEA00 | 4) as u16;
3828 let hw2: u16 = ((r12 << 8) | r3) as u16;
3829 bytes.extend_from_slice(&hw1.to_le_bytes());
3830 bytes.extend_from_slice(&hw2.to_le_bytes());
3831
3832 let hw1: u16 = 0xEA4F;
3834 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3835 bytes.extend_from_slice(&hw1.to_le_bytes());
3836 bytes.extend_from_slice(&hw2.to_le_bytes());
3837
3838 let hw1: u16 = (0xEA00 | 4) as u16;
3840 let hw2: u16 = ((4 << 8) | r3) as u16;
3841 bytes.extend_from_slice(&hw1.to_le_bytes());
3842 bytes.extend_from_slice(&hw2.to_le_bytes());
3843
3844 let hw1: u16 = (0xEB00 | 4) as u16;
3846 let hw2: u16 = ((4 << 8) | r12) as u16;
3847 bytes.extend_from_slice(&hw1.to_le_bytes());
3848 bytes.extend_from_slice(&hw2.to_le_bytes());
3849
3850 let hw1: u16 = 0xEA4F;
3855 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3856 bytes.extend_from_slice(&hw1.to_le_bytes());
3857 bytes.extend_from_slice(&hw2.to_le_bytes());
3858
3859 let hw1: u16 = (0xEB00 | 4) as u16;
3861 let hw2: u16 = ((4 << 8) | r12) as u16;
3862 bytes.extend_from_slice(&hw1.to_le_bytes());
3863 bytes.extend_from_slice(&hw2.to_le_bytes());
3864
3865 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3870 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3871 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3873 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3874
3875 let hw1: u16 = (0xEA00 | 4) as u16;
3877 let hw2: u16 = ((4 << 8) | r3) as u16;
3878 bytes.extend_from_slice(&hw1.to_le_bytes());
3879 bytes.extend_from_slice(&hw2.to_le_bytes());
3880
3881 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3885 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3886 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3888 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3889
3890 let hw1: u16 = (0xFB00 | 4) as u16;
3893 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3894 bytes.extend_from_slice(&hw1.to_le_bytes());
3895 bytes.extend_from_slice(&hw2.to_le_bytes());
3896
3897 let hw1: u16 = 0xEA4F;
3900 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3901 bytes.extend_from_slice(&hw1.to_le_bytes());
3902 bytes.extend_from_slice(&hw2.to_le_bytes());
3903
3904 let hw1: u16 = 0xEA4F;
3907 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3908 bytes.extend_from_slice(&hw1.to_le_bytes());
3909 bytes.extend_from_slice(&hw2.to_le_bytes());
3910
3911 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3913 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3914 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3915 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3916
3917 let hw1: u16 = (0xEA00 | r12) as u16;
3918 let hw2: u16 = ((r12 << 8) | r3) as u16;
3919 bytes.extend_from_slice(&hw1.to_le_bytes());
3920 bytes.extend_from_slice(&hw2.to_le_bytes());
3921
3922 let hw1: u16 = (0xEBA0 | 5) as u16;
3923 let hw2: u16 = ((5 << 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(&0xF243u16.to_le_bytes());
3929 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3930 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3931 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3932
3933 let hw1: u16 = (0xEA00 | 5) as u16;
3934 let hw2: u16 = ((r12 << 8) | r3) as u16;
3935 bytes.extend_from_slice(&hw1.to_le_bytes());
3936 bytes.extend_from_slice(&hw2.to_le_bytes());
3937
3938 let hw1: u16 = 0xEA4F;
3939 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3940 bytes.extend_from_slice(&hw1.to_le_bytes());
3941 bytes.extend_from_slice(&hw2.to_le_bytes());
3942
3943 let hw1: u16 = (0xEA00 | 5) as u16;
3944 let hw2: u16 = ((5 << 8) | r3) as u16;
3945 bytes.extend_from_slice(&hw1.to_le_bytes());
3946 bytes.extend_from_slice(&hw2.to_le_bytes());
3947
3948 let hw1: u16 = (0xEB00 | 5) as u16;
3949 let hw2: u16 = ((5 << 8) | r12) as u16;
3950 bytes.extend_from_slice(&hw1.to_le_bytes());
3951 bytes.extend_from_slice(&hw2.to_le_bytes());
3952
3953 let hw1: u16 = 0xEA4F;
3956 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3957 bytes.extend_from_slice(&hw1.to_le_bytes());
3958 bytes.extend_from_slice(&hw2.to_le_bytes());
3959
3960 let hw1: u16 = (0xEB00 | 5) as u16;
3961 let hw2: u16 = ((5 << 8) | r12) as u16;
3962 bytes.extend_from_slice(&hw1.to_le_bytes());
3963 bytes.extend_from_slice(&hw2.to_le_bytes());
3964
3965 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3967 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3968 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3969 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3970
3971 let hw1: u16 = (0xEA00 | 5) as u16;
3972 let hw2: u16 = ((5 << 8) | r3) as u16;
3973 bytes.extend_from_slice(&hw1.to_le_bytes());
3974 bytes.extend_from_slice(&hw2.to_le_bytes());
3975
3976 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3978 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3979 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3980 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3981
3982 let hw1: u16 = (0xFB00 | 5) as u16;
3985 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3986 bytes.extend_from_slice(&hw1.to_le_bytes());
3987 bytes.extend_from_slice(&hw2.to_le_bytes());
3988
3989 let hw1: u16 = 0xEA4F;
3992 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3993 bytes.extend_from_slice(&hw1.to_le_bytes());
3994 bytes.extend_from_slice(&hw2.to_le_bytes());
3995
3996 let rd_bits_u16 = rd_bits as u16;
3999 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
4000 bytes.extend_from_slice(&instr.to_le_bytes());
4001
4002 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
4004
4005 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
4007 bytes.extend_from_slice(&mov0.to_le_bytes());
4008
4009 Ok(bytes)
4010 }
4011
4012 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
4015 let rdlo_bits = reg_to_bits(rdlo);
4016 let rdhi_bits = reg_to_bits(rdhi);
4017 let rnlo_bits = reg_to_bits(rnlo);
4018 let mut bytes = Vec::new();
4019
4020 let hw1: u16 = 0xFA4F_u16;
4023 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4024 bytes.extend_from_slice(&hw1.to_le_bytes());
4025 bytes.extend_from_slice(&hw2.to_le_bytes());
4026
4027 let hw1: u16 = 0xEA4F;
4032 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4033 bytes.extend_from_slice(&hw1.to_le_bytes());
4034 bytes.extend_from_slice(&hw2.to_le_bytes());
4035
4036 Ok(bytes)
4037 }
4038
4039 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4042 let rdlo_bits = reg_to_bits(rdlo);
4043 let rdhi_bits = reg_to_bits(rdhi);
4044 let rnlo_bits = reg_to_bits(rnlo);
4045 let mut bytes = Vec::new();
4046
4047 let hw1: u16 = 0xFA0F_u16;
4050 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4051 bytes.extend_from_slice(&hw1.to_le_bytes());
4052 bytes.extend_from_slice(&hw2.to_le_bytes());
4053
4054 let hw1: u16 = 0xEA4F;
4056 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4057 bytes.extend_from_slice(&hw1.to_le_bytes());
4058 bytes.extend_from_slice(&hw2.to_le_bytes());
4059
4060 Ok(bytes)
4061 }
4062
4063 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4066 let rdlo_bits = reg_to_bits(rdlo);
4067 let rdhi_bits = reg_to_bits(rdhi);
4068 let rnlo_bits = reg_to_bits(rnlo);
4069 let mut bytes = Vec::new();
4070
4071 if rdlo_bits != rnlo_bits {
4073 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4075 let mov: u16 = 0x4600
4076 | (d_bit << 7)
4077 | ((rnlo_bits as u16) << 3)
4078 | ((rdlo_bits & 0x7) as u16);
4079 bytes.extend_from_slice(&mov.to_le_bytes());
4080 }
4081
4082 let hw1: u16 = 0xEA4F;
4084 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4085 bytes.extend_from_slice(&hw1.to_le_bytes());
4086 bytes.extend_from_slice(&hw2.to_le_bytes());
4087
4088 Ok(bytes)
4089 }
4090
4091 ArmOp::SelectMove { rd, rm, cond } => {
4094 let rd_bits = reg_to_bits(rd) as u16;
4095 let rm_bits = reg_to_bits(rm) as u16;
4096
4097 use synth_synthesis::Condition;
4099 let cond_bits: u16 = match cond {
4100 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, };
4111
4112 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4115
4116 let d_bit = (rd_bits >> 3) & 1;
4119 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4120
4121 let mut bytes = it_instr.to_le_bytes().to_vec();
4123 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4124 Ok(bytes)
4125 }
4126
4127 ArmOp::Popcnt { rd, rm } => {
4138 let mut bytes = Vec::new();
4139
4140 if rd != rm {
4142 let rd_bits = reg_to_bits(rd) as u16;
4143 let rm_bits = reg_to_bits(rm) as u16;
4144 let d_bit = (rd_bits >> 3) & 1;
4146 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4147 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4148 }
4149
4150 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4153 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4154
4155 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4158
4159 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4161
4162 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4164 reg_to_bits(rd),
4165 reg_to_bits(rd),
4166 11,
4167 )?);
4168
4169 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4172 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4173
4174 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4176 11,
4177 reg_to_bits(rd),
4178 12,
4179 )?);
4180
4181 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4183 reg_to_bits(rd),
4184 reg_to_bits(rd),
4185 2,
4186 )?);
4187
4188 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4190 reg_to_bits(rd),
4191 reg_to_bits(rd),
4192 12,
4193 )?);
4194
4195 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4197 reg_to_bits(rd),
4198 reg_to_bits(rd),
4199 11,
4200 )?);
4201
4202 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4205
4206 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4208 reg_to_bits(rd),
4209 reg_to_bits(rd),
4210 11,
4211 )?);
4212
4213 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4215 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4216
4217 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4219 reg_to_bits(rd),
4220 reg_to_bits(rd),
4221 12,
4222 )?);
4223
4224 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4227
4228 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4230 reg_to_bits(rd),
4231 reg_to_bits(rd),
4232 11,
4233 )?);
4234
4235 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4238
4239 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4241 reg_to_bits(rd),
4242 reg_to_bits(rd),
4243 11,
4244 )?);
4245
4246 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4249 reg_to_bits(rd),
4250 reg_to_bits(rd),
4251 0x3F,
4252 )?);
4253
4254 Ok(bytes)
4255 }
4256
4257 ArmOp::I64DivU {
4262 rdlo: _,
4263 rdhi: _,
4264 rnlo: _,
4265 rnhi: _,
4266 rmlo: _,
4267 rmhi: _,
4268 } => {
4269 let mut bytes = Vec::new();
4270
4271 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4275
4276 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());
4287 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4288
4289 let loop_start = bytes.len();
4291
4292 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4303 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());
4312 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4313 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4317 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4318
4319 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4324 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4325 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());
4356 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4357 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4360
4361 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4365 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4366
4367 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4370 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4371 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4372
4373 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4381
4382 Ok(bytes)
4383 }
4384
4385 ArmOp::I64DivS {
4390 rdlo: _,
4391 rdhi: _,
4392 rnlo: _,
4393 rnhi: _,
4394 rmlo: _,
4395 rmhi: _,
4396 } => {
4397 let mut bytes = Vec::new();
4398
4399 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4401 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4402
4403 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4406 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4407
4408 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());
4421
4422 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());
4432
4433 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4436 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4437 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4439 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4440 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4442 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4443
4444 let loop_start = bytes.len();
4445
4446 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4450 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());
4456 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4459
4460 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4464 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());
4477 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4479
4480 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4483
4484 let branch_offset_bytes = bytes.len() - loop_start + 4;
4485 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4486 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4487 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4488
4489 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());
4496 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());
4504
4505 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4507 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4508
4509 Ok(bytes)
4510 }
4511
4512 ArmOp::I64RemU {
4517 rdlo: _,
4518 rdhi: _,
4519 rnlo: _,
4520 rnhi: _,
4521 rmlo: _,
4522 rmhi: _,
4523 } => {
4524 let mut bytes = Vec::new();
4525
4526 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4528 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4529
4530 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4532 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4533 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4535 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4536 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4538 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4539
4540 let loop_start = bytes.len();
4541
4542 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4546 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());
4552 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4555
4556 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4560 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());
4573 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4575
4576 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4579
4580 let branch_offset_bytes = bytes.len() - loop_start + 4;
4581 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4582 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4583 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4584
4585 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4591 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4592
4593 Ok(bytes)
4594 }
4595
4596 ArmOp::I64RemS {
4601 rdlo: _,
4602 rdhi: _,
4603 rnlo: _,
4604 rnhi: _,
4605 rmlo: _,
4606 rmhi: _,
4607 } => {
4608 let mut bytes = Vec::new();
4609
4610 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4612 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4613
4614 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());
4628
4629 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());
4639
4640 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4643 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4644 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4646 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4647 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4649 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4650
4651 let loop_start = bytes.len();
4652
4653 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4657 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());
4663 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4666
4667 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4671 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());
4684 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4686
4687 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4690
4691 let branch_offset_bytes = bytes.len() - loop_start + 4;
4692 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4693 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4694 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4695
4696 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());
4703 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());
4711
4712 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4714 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4715
4716 Ok(bytes)
4717 }
4718
4719 ArmOp::F32Add { sd, sn, sm } => {
4722 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4723 }
4724 ArmOp::F32Sub { sd, sn, sm } => {
4725 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4726 }
4727 ArmOp::F32Mul { sd, sn, sm } => {
4728 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4729 }
4730 ArmOp::F32Div { sd, sn, sm } => {
4731 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4732 }
4733 ArmOp::F32Abs { sd, sm } => {
4734 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4735 }
4736 ArmOp::F32Neg { sd, sm } => {
4737 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4738 }
4739 ArmOp::F32Sqrt { sd, sm } => {
4740 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4741 }
4742
4743 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4746 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4747 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4748 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4749 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4750 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4751 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4752
4753 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4755 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4756 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4757 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4758 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4759 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4760
4761 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4762
4763 ArmOp::F32Load { sd, addr } => {
4764 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4765 }
4766 ArmOp::F32Store { sd, addr } => {
4767 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4768 }
4769
4770 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4771 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4772 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4773 Err(synth_core::Error::synthesis(
4774 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4775 ))
4776 }
4777 ArmOp::F32ReinterpretI32 { sd, rm } => {
4778 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4779 }
4780 ArmOp::I32ReinterpretF32 { rd, sm } => {
4781 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4782 }
4783 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4784 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4785
4786 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4789 0xEE300B00, dd, dn, dm,
4790 )?)),
4791 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4792 0xEE300B40, dd, dn, dm,
4793 )?)),
4794 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4795 0xEE200B00, dd, dn, dm,
4796 )?)),
4797 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4798 0xEE800B00, dd, dn, dm,
4799 )?)),
4800 ArmOp::F64Abs { dd, dm } => {
4801 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4802 }
4803 ArmOp::F64Neg { dd, dm } => {
4804 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4805 }
4806 ArmOp::F64Sqrt { dd, dm } => {
4807 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4808 }
4809
4810 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4813 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4814 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4815 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4816 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4817 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4818 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4819
4820 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4822 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4823 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4824 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4825 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4826 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4827
4828 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4829
4830 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4831 0xED900B00, dd, addr,
4832 )?)),
4833 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4834 0xED800B00, dd, addr,
4835 )?)),
4836
4837 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4838 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4839 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4840 Err(synth_core::Error::synthesis(
4841 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4842 ))
4843 }
4844 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4845 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4846 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4847 )),
4848 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4849 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4850 )),
4851 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4852 Err(synth_core::Error::synthesis(
4853 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4854 ))
4855 }
4856 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4857 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4858
4859 ArmOp::I64Add {
4863 rdlo,
4864 rdhi,
4865 rnlo,
4866 rnhi,
4867 rmlo,
4868 rmhi,
4869 } => {
4870 let mut bytes = Vec::new();
4871 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4873 rd: *rdlo,
4874 rn: *rnlo,
4875 op2: Operand2::Reg(*rmlo),
4876 })?);
4877 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4879 rd: *rdhi,
4880 rn: *rnhi,
4881 op2: Operand2::Reg(*rmhi),
4882 })?);
4883 Ok(bytes)
4884 }
4885
4886 ArmOp::I64Sub {
4888 rdlo,
4889 rdhi,
4890 rnlo,
4891 rnhi,
4892 rmlo,
4893 rmhi,
4894 } => {
4895 let mut bytes = Vec::new();
4896 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4898 rd: *rdlo,
4899 rn: *rnlo,
4900 op2: Operand2::Reg(*rmlo),
4901 })?);
4902 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4904 rd: *rdhi,
4905 rn: *rnhi,
4906 op2: Operand2::Reg(*rmhi),
4907 })?);
4908 Ok(bytes)
4909 }
4910
4911 ArmOp::I64And {
4913 rdlo,
4914 rdhi,
4915 rnlo,
4916 rnhi,
4917 rmlo,
4918 rmhi,
4919 } => {
4920 let mut bytes = Vec::new();
4921 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4922 rd: *rdlo,
4923 rn: *rnlo,
4924 op2: Operand2::Reg(*rmlo),
4925 })?);
4926 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4927 rd: *rdhi,
4928 rn: *rnhi,
4929 op2: Operand2::Reg(*rmhi),
4930 })?);
4931 Ok(bytes)
4932 }
4933
4934 ArmOp::I64Or {
4936 rdlo,
4937 rdhi,
4938 rnlo,
4939 rnhi,
4940 rmlo,
4941 rmhi,
4942 } => {
4943 let mut bytes = Vec::new();
4944 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4945 rd: *rdlo,
4946 rn: *rnlo,
4947 op2: Operand2::Reg(*rmlo),
4948 })?);
4949 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4950 rd: *rdhi,
4951 rn: *rnhi,
4952 op2: Operand2::Reg(*rmhi),
4953 })?);
4954 Ok(bytes)
4955 }
4956
4957 ArmOp::I64Xor {
4959 rdlo,
4960 rdhi,
4961 rnlo,
4962 rnhi,
4963 rmlo,
4964 rmhi,
4965 } => {
4966 let mut bytes = Vec::new();
4967 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4968 rd: *rdlo,
4969 rn: *rnlo,
4970 op2: Operand2::Reg(*rmlo),
4971 })?);
4972 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4973 rd: *rdhi,
4974 rn: *rnhi,
4975 op2: Operand2::Reg(*rmhi),
4976 })?);
4977 Ok(bytes)
4978 }
4979
4980 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4982 rd: *rd,
4983 rn_lo: *rnlo,
4984 rn_hi: *rnhi,
4985 }),
4986
4987 ArmOp::I64Eq {
4989 rd,
4990 rnlo,
4991 rnhi,
4992 rmlo,
4993 rmhi,
4994 } => self.encode_thumb(&ArmOp::I64SetCond {
4995 rd: *rd,
4996 rn_lo: *rnlo,
4997 rn_hi: *rnhi,
4998 rm_lo: *rmlo,
4999 rm_hi: *rmhi,
5000 cond: synth_synthesis::Condition::EQ,
5001 }),
5002
5003 ArmOp::I64Ne {
5004 rd,
5005 rnlo,
5006 rnhi,
5007 rmlo,
5008 rmhi,
5009 } => self.encode_thumb(&ArmOp::I64SetCond {
5010 rd: *rd,
5011 rn_lo: *rnlo,
5012 rn_hi: *rnhi,
5013 rm_lo: *rmlo,
5014 rm_hi: *rmhi,
5015 cond: synth_synthesis::Condition::NE,
5016 }),
5017
5018 ArmOp::I64LtS {
5019 rd,
5020 rnlo,
5021 rnhi,
5022 rmlo,
5023 rmhi,
5024 } => self.encode_thumb(&ArmOp::I64SetCond {
5025 rd: *rd,
5026 rn_lo: *rnlo,
5027 rn_hi: *rnhi,
5028 rm_lo: *rmlo,
5029 rm_hi: *rmhi,
5030 cond: synth_synthesis::Condition::LT,
5031 }),
5032
5033 ArmOp::I64LtU {
5034 rd,
5035 rnlo,
5036 rnhi,
5037 rmlo,
5038 rmhi,
5039 } => self.encode_thumb(&ArmOp::I64SetCond {
5040 rd: *rd,
5041 rn_lo: *rnlo,
5042 rn_hi: *rnhi,
5043 rm_lo: *rmlo,
5044 rm_hi: *rmhi,
5045 cond: synth_synthesis::Condition::LO,
5046 }),
5047
5048 ArmOp::I64LeS {
5049 rd,
5050 rnlo,
5051 rnhi,
5052 rmlo,
5053 rmhi,
5054 } => self.encode_thumb(&ArmOp::I64SetCond {
5055 rd: *rd,
5056 rn_lo: *rnlo,
5057 rn_hi: *rnhi,
5058 rm_lo: *rmlo,
5059 rm_hi: *rmhi,
5060 cond: synth_synthesis::Condition::LE,
5061 }),
5062
5063 ArmOp::I64LeU {
5064 rd,
5065 rnlo,
5066 rnhi,
5067 rmlo,
5068 rmhi,
5069 } => self.encode_thumb(&ArmOp::I64SetCond {
5070 rd: *rd,
5071 rn_lo: *rnlo,
5072 rn_hi: *rnhi,
5073 rm_lo: *rmlo,
5074 rm_hi: *rmhi,
5075 cond: synth_synthesis::Condition::LS,
5076 }),
5077
5078 ArmOp::I64GtS {
5079 rd,
5080 rnlo,
5081 rnhi,
5082 rmlo,
5083 rmhi,
5084 } => self.encode_thumb(&ArmOp::I64SetCond {
5085 rd: *rd,
5086 rn_lo: *rnlo,
5087 rn_hi: *rnhi,
5088 rm_lo: *rmlo,
5089 rm_hi: *rmhi,
5090 cond: synth_synthesis::Condition::GT,
5091 }),
5092
5093 ArmOp::I64GtU {
5094 rd,
5095 rnlo,
5096 rnhi,
5097 rmlo,
5098 rmhi,
5099 } => self.encode_thumb(&ArmOp::I64SetCond {
5100 rd: *rd,
5101 rn_lo: *rnlo,
5102 rn_hi: *rnhi,
5103 rm_lo: *rmlo,
5104 rm_hi: *rmhi,
5105 cond: synth_synthesis::Condition::HI,
5106 }),
5107
5108 ArmOp::I64GeS {
5109 rd,
5110 rnlo,
5111 rnhi,
5112 rmlo,
5113 rmhi,
5114 } => self.encode_thumb(&ArmOp::I64SetCond {
5115 rd: *rd,
5116 rn_lo: *rnlo,
5117 rn_hi: *rnhi,
5118 rm_lo: *rmlo,
5119 rm_hi: *rmhi,
5120 cond: synth_synthesis::Condition::GE,
5121 }),
5122
5123 ArmOp::I64GeU {
5124 rd,
5125 rnlo,
5126 rnhi,
5127 rmlo,
5128 rmhi,
5129 } => self.encode_thumb(&ArmOp::I64SetCond {
5130 rd: *rd,
5131 rn_lo: *rnlo,
5132 rn_hi: *rnhi,
5133 rm_lo: *rmlo,
5134 rm_hi: *rmhi,
5135 cond: synth_synthesis::Condition::HS,
5136 }),
5137
5138 ArmOp::I64Const { rdlo, rdhi, value } => {
5140 let lo32 = *value as u32;
5141 let hi32 = (*value >> 32) as u32;
5142 let mut bytes = Vec::new();
5143 bytes.extend_from_slice(
5145 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5146 );
5147 if lo32 > 0xFFFF {
5148 bytes.extend_from_slice(
5149 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5150 );
5151 }
5152 bytes.extend_from_slice(
5154 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5155 );
5156 if hi32 > 0xFFFF {
5157 bytes.extend_from_slice(
5158 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5159 );
5160 }
5161 Ok(bytes)
5162 }
5163
5164 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5166 let mut bytes = Vec::new();
5167 let offset = if addr.offset < 0 {
5168 0u32
5169 } else {
5170 addr.offset as u32
5171 };
5172 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5173 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5174 rdhi,
5175 &addr.base,
5176 offset.wrapping_add(4),
5177 )?);
5178 Ok(bytes)
5179 }
5180
5181 ArmOp::I64Str { rdlo, rdhi, addr } => {
5183 let mut bytes = Vec::new();
5184 let offset = if addr.offset < 0 {
5185 0u32
5186 } else {
5187 addr.offset as u32
5188 };
5189 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5190 bytes.extend_from_slice(&self.encode_thumb32_str(
5191 rdhi,
5192 &addr.base,
5193 offset.wrapping_add(4),
5194 )?);
5195 Ok(bytes)
5196 }
5197
5198 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5200 let mut bytes = Vec::new();
5201 if rdlo != rn {
5202 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5204 rd: *rdlo,
5205 op2: Operand2::Reg(*rn),
5206 })?);
5207 }
5208 bytes.extend_from_slice(
5210 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5212 Ok(bytes)
5213 }
5214
5215 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5217 let mut bytes = Vec::new();
5218 if rdlo != rn {
5219 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5221 rd: *rdlo,
5222 op2: Operand2::Reg(*rn),
5223 })?);
5224 }
5225 let rdhi_bits = reg_to_bits(rdhi) as u16;
5227 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5228 bytes.extend_from_slice(&instr.to_le_bytes());
5229 Ok(bytes)
5230 }
5231
5232 ArmOp::I32WrapI64 { rd, rnlo } => {
5234 if rd == rnlo {
5235 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5238 } else {
5239 self.encode_thumb(&ArmOp::Mov {
5241 rd: *rd,
5242 op2: Operand2::Reg(*rnlo),
5243 })
5244 }
5245 }
5246
5247 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5249 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5250 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5251 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5252 0xEF000150, qd, qn, qm,
5253 ))),
5254 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5255 0xEF200150, qd, qn, qm,
5256 ))),
5257 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5258 0xFF000150, qd, qn, qm,
5259 ))),
5260 ArmOp::MveMvn { qd, qm } => {
5261 let qd_enc = qreg_to_num(qd);
5263 let qm_enc = qreg_to_num(qm);
5264 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5265 Ok(vfp_to_thumb_bytes(instr))
5266 }
5267 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5268 0xEF100150, qd, qn, qm,
5269 ))),
5270 ArmOp::MveAddI { qd, qn, qm, size } => {
5271 let sz = mve_size_bits(size);
5272 let base: u32 = 0xEF000840 | (sz << 20);
5273 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5274 }
5275 ArmOp::MveSubI { qd, qn, qm, size } => {
5276 let sz = mve_size_bits(size);
5277 let base: u32 = 0xFF000840 | (sz << 20);
5278 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5279 }
5280 ArmOp::MveMulI { qd, qn, qm, size } => {
5281 let sz = mve_size_bits(size);
5282 let base: u32 = 0xEF000950 | (sz << 20);
5283 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5284 }
5285 ArmOp::MveNegI { qd, qm, size } => {
5286 let sz = mve_size_bits(size);
5287 let qd_enc = qreg_to_num(qd);
5289 let qm_enc = qreg_to_num(qm);
5290 let base: u32 = 0xFFB103C0 | (sz << 18);
5291 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5292 Ok(vfp_to_thumb_bytes(instr))
5293 }
5294 ArmOp::MveDup { qd, rn, size } => {
5295 let sz = mve_size_bits(size);
5296 let qd_enc = qreg_to_num(qd);
5297 let rn_bits = reg_to_bits(rn);
5298 let be = match sz {
5301 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5305 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5306 Ok(vfp_to_thumb_bytes(instr))
5307 }
5308 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5309 let qn_enc = qreg_to_num(qn);
5310 let rd_bits = reg_to_bits(rd);
5311 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5314 let lane_in_d = (*lane as u32) & 1;
5315 let _sz = mve_size_bits(size);
5316 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5318 Ok(vfp_to_thumb_bytes(instr))
5319 }
5320 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5321 let qd_enc = qreg_to_num(qd);
5322 let rn_bits = reg_to_bits(rn);
5323 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5324 let lane_in_d = (*lane as u32) & 1;
5325 let _sz = mve_size_bits(size);
5326 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5328 Ok(vfp_to_thumb_bytes(instr))
5329 }
5330
5331 ArmOp::MveCmpEqI { qd, qn, qm, size }
5333 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5334 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5335 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5336 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5337 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5338 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5339 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5340 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5341 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5342 let sz = mve_size_bits(size);
5345 let base: u32 = 0xEF000840 | (sz << 20);
5346 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5347 }
5348
5349 ArmOp::MveAddF32 { qd, qn, qm } => {
5351 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5353 }
5354 ArmOp::MveSubF32 { qd, qn, qm } => {
5355 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5357 }
5358 ArmOp::MveMulF32 { qd, qn, qm } => {
5359 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5361 }
5362 ArmOp::MveNegF32 { qd, qm } => {
5363 let qd_enc = qreg_to_num(qd);
5364 let qm_enc = qreg_to_num(qm);
5365 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5367 Ok(vfp_to_thumb_bytes(instr))
5368 }
5369 ArmOp::MveAbsF32 { qd, qm } => {
5370 let qd_enc = qreg_to_num(qd);
5371 let qm_enc = qreg_to_num(qm);
5372 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5374 Ok(vfp_to_thumb_bytes(instr))
5375 }
5376 ArmOp::MveCmpEqF32 { qd, qn, qm }
5377 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5378 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5379 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5380 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5381 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5382 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5384 }
5385 ArmOp::MveDupF32 { qd, rn } => {
5386 let qd_enc = qreg_to_num(qd);
5387 let rn_bits = reg_to_bits(rn);
5388 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5390 Ok(vfp_to_thumb_bytes(instr))
5391 }
5392 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5393 let qn_enc = qreg_to_num(qn);
5394 let rd_bits = reg_to_bits(rd);
5395 let s_num = qn_enc * 4 + (*lane as u32);
5397 let (vn, n) = encode_sreg(s_num);
5398 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5399 Ok(vfp_to_thumb_bytes(instr))
5400 }
5401 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5402 let qd_enc = qreg_to_num(qd);
5403 let rn_bits = reg_to_bits(rn);
5404 let s_num = qd_enc * 4 + (*lane as u32);
5406 let (vn, n) = encode_sreg(s_num);
5407 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5408 Ok(vfp_to_thumb_bytes(instr))
5409 }
5410 ArmOp::MveDivF32 { qd, qn, qm } => {
5411 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5413 }
5414 ArmOp::MveSqrtF32 { qd, qm } => {
5415 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5417 }
5418
5419 _ => {
5421 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5423 }
5424 }
5425 }
5426
5427 fn encode_thumb_f32_compare(
5431 &self,
5432 rd: &Reg,
5433 sn: &VfpReg,
5434 sm: &VfpReg,
5435 cond_code: u32,
5436 ) -> Result<Vec<u8>> {
5437 let mut bytes = Vec::new();
5438 let rd_bits = reg_to_bits(rd);
5439
5440 let sn_num = vfp_sreg_to_num(sn)?;
5442 let sm_num = vfp_sreg_to_num(sm)?;
5443 let (vd, d) = encode_sreg(sn_num);
5444 let (vm, m) = encode_sreg(sm_num);
5445 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5446 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5447
5448 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5450
5451 if rd_bits < 8 {
5453 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5454 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5455 } else {
5456 let hw1: u16 = 0xF04F;
5458 let hw2: u16 = (rd_bits as u16) << 8;
5459 bytes.extend_from_slice(&hw1.to_le_bytes());
5460 bytes.extend_from_slice(&hw2.to_le_bytes());
5461 }
5462
5463 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5467 bytes.extend_from_slice(&it.to_le_bytes());
5468
5469 if rd_bits < 8 {
5471 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5472 bytes.extend_from_slice(&mov_one.to_le_bytes());
5473 } else {
5474 let hw1: u16 = 0xF04F;
5476 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5477 bytes.extend_from_slice(&hw1.to_le_bytes());
5478 bytes.extend_from_slice(&hw2.to_le_bytes());
5479 }
5480
5481 Ok(bytes)
5482 }
5483
5484 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5486 let mut bytes = Vec::new();
5487 let bits = value.to_bits();
5488 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5493 let imm4 = (lo16 >> 12) & 0xF;
5494 let i_bit = (lo16 >> 11) & 1;
5495 let imm3 = (lo16 >> 8) & 0x7;
5496 let imm8 = lo16 & 0xFF;
5497 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5498 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5499 bytes.extend_from_slice(&hw1.to_le_bytes());
5500 bytes.extend_from_slice(&hw2.to_le_bytes());
5501
5502 let hi16 = (bits >> 16) & 0xFFFF;
5504 let imm4 = (hi16 >> 12) & 0xF;
5505 let i_bit = (hi16 >> 11) & 1;
5506 let imm3 = (hi16 >> 8) & 0x7;
5507 let imm8 = hi16 & 0xFF;
5508 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5509 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5510 bytes.extend_from_slice(&hw1.to_le_bytes());
5511 bytes.extend_from_slice(&hw2.to_le_bytes());
5512
5513 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5515 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5516
5517 Ok(bytes)
5518 }
5519
5520 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5522 let mut bytes = Vec::new();
5523
5524 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5526 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5527
5528 let sd_num = vfp_sreg_to_num(sd)?;
5530 let (vd, d) = encode_sreg(sd_num);
5531 let (vm, m) = encode_sreg(sd_num);
5532 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5533 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5534 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5535
5536 Ok(bytes)
5537 }
5538
5539 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5547 let mut bytes = Vec::new();
5548 let sm_num = vfp_sreg_to_num(sm)?;
5549 let sd_num = vfp_sreg_to_num(sd)?;
5550 let (vd_s, d_s) = encode_sreg(sd_num);
5551 let (vm_s, m_s) = encode_sreg(sm_num);
5552
5553 if mode == 0b11 {
5554 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5556 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5557 } else {
5558 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5563 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5564
5565 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5571 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5572 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5573
5574 if mode != 0 {
5576 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5578 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5579 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5580 }
5581
5582 let vmsr = 0xEEE10A10 | (rt << 12);
5584 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5585
5586 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5588 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5589
5590 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5592 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5593 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5594 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5595 }
5596
5597 let (vd2, d2) = encode_sreg(sd_num);
5599 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5600 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5601
5602 Ok(bytes)
5603 }
5604
5605 fn encode_thumb_f32_minmax(
5607 &self,
5608 sd: &VfpReg,
5609 sn: &VfpReg,
5610 sm: &VfpReg,
5611 is_min: bool,
5612 ) -> Result<Vec<u8>> {
5613 let mut bytes = Vec::new();
5614 let sn_num = vfp_sreg_to_num(sn)?;
5615 let sm_num = vfp_sreg_to_num(sm)?;
5616 let sd_num = vfp_sreg_to_num(sd)?;
5617
5618 let (vd, d) = encode_sreg(sd_num);
5620 let (vn, n) = encode_sreg(sn_num);
5621 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5622 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5623
5624 let (vm, m) = encode_sreg(sm_num);
5626 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5627 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5628
5629 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5631
5632 let cond: u16 = if is_min { 0xC } else { 0x4 };
5634 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5635 bytes.extend_from_slice(&it.to_le_bytes());
5636
5637 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5639 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5640
5641 Ok(bytes)
5642 }
5643
5644 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5646 let mut bytes = Vec::new();
5647
5648 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5650 false,
5651 sm,
5652 &Reg::R12,
5653 )?));
5654
5655 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5657 false,
5658 sn,
5659 &Reg::R0,
5660 )?));
5661
5662 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5674 bytes.extend_from_slice(&hw2.to_le_bytes());
5675
5676 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5680 bytes.extend_from_slice(&hw2.to_le_bytes());
5681
5682 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5686 bytes.extend_from_slice(&hw2.to_le_bytes());
5687
5688 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5690 true,
5691 sd,
5692 &Reg::R0,
5693 )?));
5694
5695 Ok(bytes)
5696 }
5697
5698 fn encode_thumb_f64_compare(
5700 &self,
5701 rd: &Reg,
5702 dn: &VfpReg,
5703 dm: &VfpReg,
5704 cond_code: u32,
5705 ) -> Result<Vec<u8>> {
5706 let mut bytes = Vec::new();
5707 let rd_bits = reg_to_bits(rd);
5708
5709 let dn_num = vfp_dreg_to_num(dn)?;
5711 let dm_num = vfp_dreg_to_num(dm)?;
5712 let (vd, d) = encode_dreg(dn_num);
5713 let (vm, m) = encode_dreg(dm_num);
5714 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5715 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5716
5717 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5719
5720 if rd_bits < 8 {
5722 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5723 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5724 } else {
5725 let hw1: u16 = 0xF04F;
5726 let hw2: u16 = (rd_bits as u16) << 8;
5727 bytes.extend_from_slice(&hw1.to_le_bytes());
5728 bytes.extend_from_slice(&hw2.to_le_bytes());
5729 }
5730
5731 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5733 bytes.extend_from_slice(&it.to_le_bytes());
5734
5735 if rd_bits < 8 {
5737 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5738 bytes.extend_from_slice(&mov_one.to_le_bytes());
5739 } else {
5740 let hw1: u16 = 0xF04F;
5741 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5742 bytes.extend_from_slice(&hw1.to_le_bytes());
5743 bytes.extend_from_slice(&hw2.to_le_bytes());
5744 }
5745
5746 Ok(bytes)
5747 }
5748
5749 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5751 let mut bytes = Vec::new();
5752 let bits = value.to_bits();
5753 let lo32 = bits as u32;
5754 let hi32 = (bits >> 32) as u32;
5755
5756 let lo16 = lo32 & 0xFFFF;
5758 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5759
5760 let hi16 = (lo32 >> 16) & 0xFFFF;
5762 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5763
5764 let lo16 = hi32 & 0xFFFF;
5766 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5767
5768 let hi16 = (hi32 >> 16) & 0xFFFF;
5770 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5771
5772 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5774 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5775
5776 Ok(bytes)
5777 }
5778
5779 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5781 let mut bytes = Vec::new();
5782
5783 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5785 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5786
5787 let dd_num = vfp_dreg_to_num(dd)?;
5789 let (vd, d) = encode_dreg(dd_num);
5790 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5791 let vcvt = base | (d << 22) | (vd << 12);
5792 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5793
5794 Ok(bytes)
5795 }
5796
5797 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5799 let dd_num = vfp_dreg_to_num(dd)?;
5800 let sm_num = vfp_sreg_to_num(sm)?;
5801 let (vd, d) = encode_dreg(dd_num);
5802 let (vm, m) = encode_sreg(sm_num);
5803
5804 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5805 Ok(vfp_to_thumb_bytes(vcvt))
5806 }
5807
5808 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5810 let mut bytes = Vec::new();
5811 let dm_num = vfp_dreg_to_num(dm)?;
5812 let (vm, m) = encode_dreg(dm_num);
5813
5814 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5816 let vcvt = base | (m << 5) | vm;
5817 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5818
5819 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5821 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5822
5823 Ok(bytes)
5824 }
5825
5826 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5830 let mut bytes = Vec::new();
5831 let dm_num = vfp_dreg_to_num(dm)?;
5832 let dd_num = vfp_dreg_to_num(dd)?;
5833 let (vm, m) = encode_dreg(dm_num);
5834 let (vd, d) = encode_dreg(dd_num);
5835
5836 if mode == 0b11 {
5837 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5839 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5840 } else {
5841 let rt: u32 = 12;
5842
5843 let vmrs = 0xEEF10A10 | (rt << 12);
5845 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5846
5847 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5849 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5850 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5851 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5852
5853 if mode != 0 {
5855 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5856 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5857 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5858 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5859 }
5860
5861 let vmsr = 0xEEE10A10 | (rt << 12);
5863 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5864
5865 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5867 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5868
5869 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5871 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5872 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5873 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5874 }
5875
5876 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5878 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5879
5880 Ok(bytes)
5881 }
5882
5883 fn encode_thumb_f64_minmax(
5885 &self,
5886 dd: &VfpReg,
5887 dn: &VfpReg,
5888 dm: &VfpReg,
5889 is_min: bool,
5890 ) -> Result<Vec<u8>> {
5891 let mut bytes = Vec::new();
5892 let dn_num = vfp_dreg_to_num(dn)?;
5893 let dm_num = vfp_dreg_to_num(dm)?;
5894 let dd_num = vfp_dreg_to_num(dd)?;
5895
5896 let (vd, d) = encode_dreg(dd_num);
5898 let (vn, n) = encode_dreg(dn_num);
5899 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5900 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5901
5902 let (vm, m) = encode_dreg(dm_num);
5904 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5905 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5906
5907 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5909
5910 let cond: u16 = if is_min { 0xC } else { 0x4 };
5912 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5913 bytes.extend_from_slice(&it.to_le_bytes());
5914
5915 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5917 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5918
5919 Ok(bytes)
5920 }
5921
5922 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5924 let mut bytes = Vec::new();
5925
5926 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5928 false,
5929 dm,
5930 &Reg::R0,
5931 &Reg::R12,
5932 )?));
5933
5934 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5936 false,
5937 dn,
5938 &Reg::R1,
5939 &Reg::R2,
5940 )?));
5941
5942 let hw1: u16 = 0xF000 | 12;
5944 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5945 bytes.extend_from_slice(&hw1.to_le_bytes());
5946 bytes.extend_from_slice(&hw2.to_le_bytes());
5947
5948 let hw1: u16 = 0xF020 | 2;
5950 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5951 bytes.extend_from_slice(&hw1.to_le_bytes());
5952 bytes.extend_from_slice(&hw2.to_le_bytes());
5953
5954 let hw1: u16 = 0xEA40 | 2;
5956 let hw2: u16 = (2 << 8) | 12;
5957 bytes.extend_from_slice(&hw1.to_le_bytes());
5958 bytes.extend_from_slice(&hw2.to_le_bytes());
5959
5960 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5962 true,
5963 dd,
5964 &Reg::R1,
5965 &Reg::R2,
5966 )?));
5967
5968 Ok(bytes)
5969 }
5970
5971 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5973 let mut bytes = Vec::new();
5974
5975 let sm_num = vfp_sreg_to_num(sm)?;
5976 let (vd, d) = encode_sreg(sm_num);
5977 let (vm, m) = encode_sreg(sm_num);
5978 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5979 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5980 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5981
5982 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5984 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5985
5986 Ok(bytes)
5987 }
5988
5989 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5993 let rd_bits = reg_to_bits(rd);
5994 let rn_bits = reg_to_bits(rn);
5995
5996 let i_bit = (imm >> 11) & 1;
6000 let imm3 = (imm >> 8) & 0x7;
6001 let imm8 = imm & 0xFF;
6002
6003 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6004 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6005
6006 let mut bytes = hw1.to_le_bytes().to_vec();
6007 bytes.extend_from_slice(&hw2.to_le_bytes());
6008 Ok(bytes)
6009 }
6010
6011 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6013 let rd_bits = reg_to_bits(rd);
6014 let rn_bits = reg_to_bits(rn);
6015
6016 let i_bit = (imm >> 11) & 1;
6017 let imm3 = (imm >> 8) & 0x7;
6018 let imm8 = imm & 0xFF;
6019
6020 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
6021 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6022
6023 let mut bytes = hw1.to_le_bytes().to_vec();
6024 bytes.extend_from_slice(&hw2.to_le_bytes());
6025 Ok(bytes)
6026 }
6027
6028 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6030 let rd_bits = reg_to_bits(rd);
6031 let rn_bits = reg_to_bits(rn);
6032
6033 let i_bit = (imm >> 11) & 1;
6034 let imm3 = (imm >> 8) & 0x7;
6035 let imm8 = imm & 0xFF;
6036
6037 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6040 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6041
6042 let mut bytes = hw1.to_le_bytes().to_vec();
6043 bytes.extend_from_slice(&hw2.to_le_bytes());
6044 Ok(bytes)
6045 }
6046
6047 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6049 let rd_bits = reg_to_bits(rd);
6050 let rn_bits = reg_to_bits(rn);
6051
6052 let i_bit = (imm >> 11) & 1;
6053 let imm3 = (imm >> 8) & 0x7;
6054 let imm8 = imm & 0xFF;
6055
6056 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6059 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6060
6061 let mut bytes = hw1.to_le_bytes().to_vec();
6062 bytes.extend_from_slice(&hw2.to_le_bytes());
6063 Ok(bytes)
6064 }
6065
6066 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6075 let rd_bits = reg_to_bits(rd);
6076 reg_bits_checked(rd_bits)?;
6077 let imm16 = imm & 0xFFFF;
6078
6079 let imm4 = (imm16 >> 12) & 0xF;
6082 let i_bit = (imm16 >> 11) & 1;
6083 let imm3 = (imm16 >> 8) & 0x7;
6084 let imm8 = imm16 & 0xFF;
6085
6086 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6087 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6088
6089 let mut bytes = hw1.to_le_bytes().to_vec();
6090 bytes.extend_from_slice(&hw2.to_le_bytes());
6091 encoding_contracts::verify_thumb32(&bytes);
6092 Ok(bytes)
6093 }
6094
6095 fn encode_thumb32_shift(
6103 &self,
6104 rd: &Reg,
6105 rm: &Reg,
6106 shift: u32,
6107 shift_type: u8,
6108 ) -> Result<Vec<u8>> {
6109 let rd_bits = reg_to_bits(rd);
6110 let rm_bits = reg_to_bits(rm);
6111 reg_bits_checked(rd_bits)?;
6112 reg_bits_checked(rm_bits)?;
6113 let imm5 = shift & 0x1F;
6114 let imm2 = imm5 & 0x3;
6115 let imm3 = (imm5 >> 2) & 0x7;
6116
6117 let hw1: u16 = 0xEA4F;
6120 let hw2: u16 =
6121 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6122 as u16;
6123
6124 let mut bytes = hw1.to_le_bytes().to_vec();
6125 bytes.extend_from_slice(&hw2.to_le_bytes());
6126 Ok(bytes)
6127 }
6128
6129 fn encode_thumb32_shift_reg(
6133 &self,
6134 rd: &Reg,
6135 rn: &Reg,
6136 rm: &Reg,
6137 shift_type: u8,
6138 ) -> Result<Vec<u8>> {
6139 let rd_bits = reg_to_bits(rd);
6140 let rn_bits = reg_to_bits(rn);
6141 let rm_bits = reg_to_bits(rm);
6142
6143 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6145 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6147
6148 let mut bytes = hw1.to_le_bytes().to_vec();
6149 bytes.extend_from_slice(&hw2.to_le_bytes());
6150 Ok(bytes)
6151 }
6152
6153 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6155 let rn_bits = reg_to_bits(rn);
6156
6157 let i_bit = (imm >> 11) & 1;
6158 let imm3 = (imm >> 8) & 0x7;
6159 let imm8 = imm & 0xFF;
6160
6161 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6163 let hw2: u16 = ((imm3 << 12) | 0x0F00 | 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_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6172 let rd_bits = reg_to_bits(rd);
6173 let base_bits = reg_to_bits(base);
6174
6175 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6177 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6178
6179 let mut bytes = hw1.to_le_bytes().to_vec();
6180 bytes.extend_from_slice(&hw2.to_le_bytes());
6181 Ok(bytes)
6182 }
6183
6184 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6186 let rd_bits = reg_to_bits(rd);
6187 let base_bits = reg_to_bits(base);
6188
6189 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6191 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6192
6193 let mut bytes = hw1.to_le_bytes().to_vec();
6194 bytes.extend_from_slice(&hw2.to_le_bytes());
6195 Ok(bytes)
6196 }
6197
6198 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6200 let rd_bits = reg_to_bits(rd);
6201 let base_bits = reg_to_bits(base);
6202 let rm_bits = reg_to_bits(offset_reg);
6203
6204 let hw1: u16 = (0xF850 | base_bits) as u16;
6208 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6209
6210 let mut bytes = hw1.to_le_bytes().to_vec();
6211 bytes.extend_from_slice(&hw2.to_le_bytes());
6212 Ok(bytes)
6213 }
6214
6215 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6217 let rd_bits = reg_to_bits(rd);
6218 let base_bits = reg_to_bits(base);
6219 let rm_bits = reg_to_bits(offset_reg);
6220
6221 let hw1: u16 = (0xF840 | base_bits) as u16;
6225 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6226
6227 let mut bytes = hw1.to_le_bytes().to_vec();
6228 bytes.extend_from_slice(&hw2.to_le_bytes());
6229 Ok(bytes)
6230 }
6231
6232 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6236 let rd_bits = reg_to_bits(rd);
6237 let base_bits = reg_to_bits(base);
6238 let hw1: u16 = (0xF890 | base_bits) as u16;
6240 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6241 let mut bytes = hw1.to_le_bytes().to_vec();
6242 bytes.extend_from_slice(&hw2.to_le_bytes());
6243 Ok(bytes)
6244 }
6245
6246 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6248 let rd_bits = reg_to_bits(rd);
6249 let base_bits = reg_to_bits(base);
6250 let rm_bits = reg_to_bits(offset_reg);
6251 let hw1: u16 = (0xF810 | base_bits) as u16;
6253 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6254 let mut bytes = hw1.to_le_bytes().to_vec();
6255 bytes.extend_from_slice(&hw2.to_le_bytes());
6256 Ok(bytes)
6257 }
6258
6259 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6261 let rd_bits = reg_to_bits(rd);
6262 let base_bits = reg_to_bits(base);
6263 let hw1: u16 = (0xF990 | base_bits) as u16;
6265 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6266 let mut bytes = hw1.to_le_bytes().to_vec();
6267 bytes.extend_from_slice(&hw2.to_le_bytes());
6268 Ok(bytes)
6269 }
6270
6271 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6273 let rd_bits = reg_to_bits(rd);
6274 let base_bits = reg_to_bits(base);
6275 let rm_bits = reg_to_bits(offset_reg);
6276 let hw1: u16 = (0xF910 | base_bits) as u16;
6278 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6279 let mut bytes = hw1.to_le_bytes().to_vec();
6280 bytes.extend_from_slice(&hw2.to_le_bytes());
6281 Ok(bytes)
6282 }
6283
6284 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6286 let rd_bits = reg_to_bits(rd);
6287 let base_bits = reg_to_bits(base);
6288 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6290 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6291 let mut bytes = hw1.to_le_bytes().to_vec();
6292 bytes.extend_from_slice(&hw2.to_le_bytes());
6293 Ok(bytes)
6294 }
6295
6296 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6298 let rd_bits = reg_to_bits(rd);
6299 let base_bits = reg_to_bits(base);
6300 let rm_bits = reg_to_bits(offset_reg);
6301 let hw1: u16 = (0xF830 | base_bits) as u16;
6303 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6304 let mut bytes = hw1.to_le_bytes().to_vec();
6305 bytes.extend_from_slice(&hw2.to_le_bytes());
6306 Ok(bytes)
6307 }
6308
6309 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6311 let rd_bits = reg_to_bits(rd);
6312 let base_bits = reg_to_bits(base);
6313 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6315 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6316 let mut bytes = hw1.to_le_bytes().to_vec();
6317 bytes.extend_from_slice(&hw2.to_le_bytes());
6318 Ok(bytes)
6319 }
6320
6321 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6323 let rd_bits = reg_to_bits(rd);
6324 let base_bits = reg_to_bits(base);
6325 let rm_bits = reg_to_bits(offset_reg);
6326 let hw1: u16 = (0xF930 | base_bits) as u16;
6328 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6329 let mut bytes = hw1.to_le_bytes().to_vec();
6330 bytes.extend_from_slice(&hw2.to_le_bytes());
6331 Ok(bytes)
6332 }
6333
6334 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6336 let rd_bits = reg_to_bits(rd);
6337 let base_bits = reg_to_bits(base);
6338 let hw1: u16 = (0xF880 | base_bits) as u16;
6340 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
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_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6348 let rd_bits = reg_to_bits(rd);
6349 let base_bits = reg_to_bits(base);
6350 let rm_bits = reg_to_bits(offset_reg);
6351 let hw1: u16 = (0xF800 | base_bits) as u16;
6353 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6354 let mut bytes = hw1.to_le_bytes().to_vec();
6355 bytes.extend_from_slice(&hw2.to_le_bytes());
6356 Ok(bytes)
6357 }
6358
6359 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6361 let rd_bits = reg_to_bits(rd);
6362 let base_bits = reg_to_bits(base);
6363 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6365 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6366 let mut bytes = hw1.to_le_bytes().to_vec();
6367 bytes.extend_from_slice(&hw2.to_le_bytes());
6368 Ok(bytes)
6369 }
6370
6371 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6373 let rd_bits = reg_to_bits(rd);
6374 let base_bits = reg_to_bits(base);
6375 let rm_bits = reg_to_bits(offset_reg);
6376 let hw1: u16 = (0xF820 | base_bits) as u16;
6378 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6379 let mut bytes = hw1.to_le_bytes().to_vec();
6380 bytes.extend_from_slice(&hw2.to_le_bytes());
6381 Ok(bytes)
6382 }
6383
6384 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6386 let rd_bits = reg_to_bits(rd);
6387 let rn_bits = reg_to_bits(rn);
6388
6389 if imm <= 0xFFF {
6395 let i_bit = (imm >> 11) & 1;
6396 let imm3 = (imm >> 8) & 0x7;
6397 let imm8 = imm & 0xFF;
6398
6399 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6400 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6401
6402 let mut bytes = hw1.to_le_bytes().to_vec();
6403 bytes.extend_from_slice(&hw2.to_le_bytes());
6404 Ok(bytes)
6405 } else {
6406 Err(synth_core::Error::synthesis(
6409 "ADD immediate too large for single instruction",
6410 ))
6411 }
6412 }
6413
6414 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6424 reg_bits_checked(rd)?;
6425 encoding_contracts::verify_imm16(imm16);
6426 let imm16 = imm16 & 0xFFFF;
6429 let imm4 = (imm16 >> 12) & 0xF;
6430 let i_bit = (imm16 >> 11) & 1;
6431 let imm3 = (imm16 >> 8) & 0x7;
6432 let imm8 = imm16 & 0xFF;
6433
6434 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6435 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6436
6437 let mut bytes = hw1.to_le_bytes().to_vec();
6438 bytes.extend_from_slice(&hw2.to_le_bytes());
6439 encoding_contracts::verify_thumb32(&bytes);
6440 Ok(bytes)
6441 }
6442
6443 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6451 reg_bits_checked(rd)?;
6452 encoding_contracts::verify_imm16(imm16);
6453 let imm16 = imm16 & 0xFFFF;
6456 let imm4 = (imm16 >> 12) & 0xF;
6457 let i_bit = (imm16 >> 11) & 1;
6458 let imm3 = (imm16 >> 8) & 0x7;
6459 let imm8 = imm16 & 0xFF;
6460
6461 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6462 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6463
6464 let mut bytes = hw1.to_le_bytes().to_vec();
6465 bytes.extend_from_slice(&hw2.to_le_bytes());
6466 encoding_contracts::verify_thumb32(&bytes);
6467 Ok(bytes)
6468 }
6469
6470 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6472 let imm5 = shift & 0x1F;
6475 let imm2 = imm5 & 0x3;
6476 let imm3 = (imm5 >> 2) & 0x7;
6477
6478 let hw1: u16 = 0xEA4F;
6479 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6480
6481 let mut bytes = hw1.to_le_bytes().to_vec();
6482 bytes.extend_from_slice(&hw2.to_le_bytes());
6483 Ok(bytes)
6484 }
6485
6486 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6488 let hw1: u16 = (0xEA00 | rn) as u16;
6491 let hw2: u16 = ((rd << 8) | rm) as u16;
6492
6493 let mut bytes = hw1.to_le_bytes().to_vec();
6494 bytes.extend_from_slice(&hw2.to_le_bytes());
6495 Ok(bytes)
6496 }
6497
6498 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6500 let i_bit = (imm >> 11) & 1;
6504 let imm3 = (imm >> 8) & 0x7;
6505 let imm8 = imm & 0xFF;
6506
6507 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6508 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6509
6510 let mut bytes = hw1.to_le_bytes().to_vec();
6511 bytes.extend_from_slice(&hw2.to_le_bytes());
6512 Ok(bytes)
6513 }
6514
6515 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6517 let hw1: u16 = (0xEBA0 | rn) as u16;
6520 let hw2: u16 = ((rd << 8) | rm) 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 }
6526
6527 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6529 let hw1: u16 = (0xEB00 | rn) as u16;
6532 let hw2: u16 = ((rd << 8) | rm) as u16;
6533
6534 let mut bytes = hw1.to_le_bytes().to_vec();
6535 bytes.extend_from_slice(&hw2.to_le_bytes());
6536 Ok(bytes)
6537 }
6538
6539 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6543 let hw1: u16 = (0xEB10 | rn) as u16;
6545 let hw2: u16 = ((rd << 8) | rm) as u16;
6546 let mut bytes = hw1.to_le_bytes().to_vec();
6547 bytes.extend_from_slice(&hw2.to_le_bytes());
6548 Ok(bytes)
6549 }
6550
6551 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6554 let hw1: u16 = (0xEBB0 | rn) as u16;
6556 let hw2: u16 = ((rd << 8) | rm) as u16;
6557 let mut bytes = hw1.to_le_bytes().to_vec();
6558 bytes.extend_from_slice(&hw2.to_le_bytes());
6559 Ok(bytes)
6560 }
6561
6562 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6564 let mut code = Vec::new();
6565
6566 for op in ops {
6567 let encoded = self.encode(op)?;
6568 code.extend_from_slice(&encoded);
6569 }
6570
6571 Ok(code)
6572 }
6573}
6574
6575fn reg_to_bits(reg: &Reg) -> u32 {
6577 match reg {
6578 Reg::R0 => 0,
6579 Reg::R1 => 1,
6580 Reg::R2 => 2,
6581 Reg::R3 => 3,
6582 Reg::R4 => 4,
6583 Reg::R5 => 5,
6584 Reg::R6 => 6,
6585 Reg::R7 => 7,
6586 Reg::R8 => 8,
6587 Reg::R9 => 9,
6588 Reg::R10 => 10,
6589 Reg::R11 => 11,
6590 Reg::R12 => 12,
6591 Reg::SP => 13,
6592 Reg::LR => 14,
6593 Reg::PC => 15,
6594 }
6595}
6596
6597fn reg_bits_checked(bits: u32) -> Result<()> {
6605 if bits > 14 {
6606 return Err(synth_core::Error::synthesis(format!(
6607 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6608 )));
6609 }
6610 Ok(())
6611}
6612
6613fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6616 if val == 0 {
6617 return Some((0, 1));
6618 }
6619 for rot in 0..16u32 {
6620 let shift = rot * 2;
6621 let unrotated = val.rotate_left(shift);
6623 if unrotated <= 0xFF {
6624 return Some(((rot << 8) | unrotated, 1));
6626 }
6627 }
6628 None
6629}
6630
6631fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6636 match op2 {
6637 Operand2::Imm(val) => {
6638 let uval = *val as u32;
6639 if let Some(encoded) = try_encode_rotated_imm(uval) {
6641 encoded
6642 } else {
6643 let imm = uval & 0xFF;
6648 (imm, 1)
6649 }
6650 }
6651
6652 Operand2::Reg(reg) => {
6653 let reg_bits = reg_to_bits(reg);
6654 (reg_bits, 0) }
6656
6657 Operand2::RegShift {
6658 rm,
6659 shift: _,
6660 amount,
6661 } => {
6662 let rm_bits = reg_to_bits(rm);
6664 let shift_bits = (*amount & 0x1F) << 7;
6665 (shift_bits | rm_bits, 0)
6666 }
6667 }
6668}
6669
6670fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6672 let base_bits = reg_to_bits(&addr.base);
6673 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6675}
6676
6677fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6679 match reg {
6680 VfpReg::S0 => Ok(0),
6681 VfpReg::S1 => Ok(1),
6682 VfpReg::S2 => Ok(2),
6683 VfpReg::S3 => Ok(3),
6684 VfpReg::S4 => Ok(4),
6685 VfpReg::S5 => Ok(5),
6686 VfpReg::S6 => Ok(6),
6687 VfpReg::S7 => Ok(7),
6688 VfpReg::S8 => Ok(8),
6689 VfpReg::S9 => Ok(9),
6690 VfpReg::S10 => Ok(10),
6691 VfpReg::S11 => Ok(11),
6692 VfpReg::S12 => Ok(12),
6693 VfpReg::S13 => Ok(13),
6694 VfpReg::S14 => Ok(14),
6695 VfpReg::S15 => Ok(15),
6696 VfpReg::S16 => Ok(16),
6697 VfpReg::S17 => Ok(17),
6698 VfpReg::S18 => Ok(18),
6699 VfpReg::S19 => Ok(19),
6700 VfpReg::S20 => Ok(20),
6701 VfpReg::S21 => Ok(21),
6702 VfpReg::S22 => Ok(22),
6703 VfpReg::S23 => Ok(23),
6704 VfpReg::S24 => Ok(24),
6705 VfpReg::S25 => Ok(25),
6706 VfpReg::S26 => Ok(26),
6707 VfpReg::S27 => Ok(27),
6708 VfpReg::S28 => Ok(28),
6709 VfpReg::S29 => Ok(29),
6710 VfpReg::S30 => Ok(30),
6711 VfpReg::S31 => Ok(31),
6712 _ => Err(synth_core::Error::SynthesisError(
6714 "D-register not supported in single-precision VFP encoding".to_string(),
6715 )),
6716 }
6717}
6718
6719fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6721 match reg {
6722 VfpReg::D0 => Ok(0),
6723 VfpReg::D1 => Ok(1),
6724 VfpReg::D2 => Ok(2),
6725 VfpReg::D3 => Ok(3),
6726 VfpReg::D4 => Ok(4),
6727 VfpReg::D5 => Ok(5),
6728 VfpReg::D6 => Ok(6),
6729 VfpReg::D7 => Ok(7),
6730 VfpReg::D8 => Ok(8),
6731 VfpReg::D9 => Ok(9),
6732 VfpReg::D10 => Ok(10),
6733 VfpReg::D11 => Ok(11),
6734 VfpReg::D12 => Ok(12),
6735 VfpReg::D13 => Ok(13),
6736 VfpReg::D14 => Ok(14),
6737 VfpReg::D15 => Ok(15),
6738 _ => Err(synth_core::Error::SynthesisError(
6740 "S-register not supported in double-precision VFP encoding".to_string(),
6741 )),
6742 }
6743}
6744
6745fn encode_sreg(s: u32) -> (u32, u32) {
6749 (s >> 1, s & 1)
6750}
6751
6752fn encode_dreg(d: u32) -> (u32, u32) {
6756 (d & 0xF, (d >> 4) & 1)
6757}
6758
6759fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6765 let sd_num = vfp_sreg_to_num(sd)?;
6766 let sn_num = vfp_sreg_to_num(sn)?;
6767 let sm_num = vfp_sreg_to_num(sm)?;
6768 let (vd, d) = encode_sreg(sd_num);
6769 let (vn, n) = encode_sreg(sn_num);
6770 let (vm, m) = encode_sreg(sm_num);
6771
6772 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6773}
6774
6775fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6778 let sd_num = vfp_sreg_to_num(sd)?;
6779 let sm_num = vfp_sreg_to_num(sm)?;
6780 let (vd, d) = encode_sreg(sd_num);
6781 let (vm, m) = encode_sreg(sm_num);
6782
6783 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6784}
6785
6786fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6790 let sd_num = vfp_sreg_to_num(sd)?;
6791 let (vd, d) = encode_sreg(sd_num);
6792 let rn = reg_to_bits(&addr.base);
6793
6794 let offset = addr.offset;
6795 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6796 let abs_offset = offset.unsigned_abs();
6797 let imm8 = (abs_offset / 4) & 0xFF;
6798
6799 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6800}
6801
6802fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6806 let s_num = vfp_sreg_to_num(sreg)?;
6807 let (vn, n) = encode_sreg(s_num);
6808 let rt = reg_to_bits(core);
6809
6810 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6811 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6812}
6813
6814fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6818 let dd_num = vfp_dreg_to_num(dd)?;
6819 let dn_num = vfp_dreg_to_num(dn)?;
6820 let dm_num = vfp_dreg_to_num(dm)?;
6821 let (vd, d) = encode_dreg(dd_num);
6822 let (vn, n) = encode_dreg(dn_num);
6823 let (vm, m) = encode_dreg(dm_num);
6824
6825 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6826}
6827
6828fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6830 let dd_num = vfp_dreg_to_num(dd)?;
6831 let dm_num = vfp_dreg_to_num(dm)?;
6832 let (vd, d) = encode_dreg(dd_num);
6833 let (vm, m) = encode_dreg(dm_num);
6834
6835 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6836}
6837
6838fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6841 let dd_num = vfp_dreg_to_num(dd)?;
6842 let (vd, d) = encode_dreg(dd_num);
6843 let rn = reg_to_bits(&addr.base);
6844
6845 let offset = addr.offset;
6846 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6847 let abs_offset = offset.unsigned_abs();
6848 let imm8 = (abs_offset / 4) & 0xFF;
6849
6850 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6851}
6852
6853fn encode_vmov_core_dreg(
6857 to_dreg: bool,
6858 dreg: &VfpReg,
6859 core_lo: &Reg,
6860 core_hi: &Reg,
6861) -> Result<u32> {
6862 let d_num = vfp_dreg_to_num(dreg)?;
6863 let (vm, m) = encode_dreg(d_num);
6864 let rt = reg_to_bits(core_lo);
6865 let rt2 = reg_to_bits(core_hi);
6866
6867 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6868 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6869}
6870
6871fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6873 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6874 let hw2 = (instr & 0xFFFF) as u16;
6875 let mut bytes = hw1.to_le_bytes().to_vec();
6876 bytes.extend_from_slice(&hw2.to_le_bytes());
6877 bytes
6878}
6879
6880fn qreg_to_num(reg: &QReg) -> u32 {
6886 match reg {
6887 QReg::Q0 => 0,
6888 QReg::Q1 => 1,
6889 QReg::Q2 => 2,
6890 QReg::Q3 => 3,
6891 QReg::Q4 => 4,
6892 QReg::Q5 => 5,
6893 QReg::Q6 => 6,
6894 QReg::Q7 => 7,
6895 }
6896}
6897
6898fn mve_size_bits(size: &MveSize) -> u32 {
6900 match size {
6901 MveSize::S8 => 0b00,
6902 MveSize::S16 => 0b01,
6903 MveSize::S32 => 0b10,
6904 }
6905}
6906
6907fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6911 let d = qreg_to_num(qd) * 2;
6912 let n = qreg_to_num(qn) * 2;
6913 let m = qreg_to_num(qm) * 2;
6914
6915 let vd = d & 0xF;
6920 let d_bit = (d >> 4) & 1;
6921 let vn = n & 0xF;
6922 let n_bit = (n >> 4) & 1;
6923 let vm = m & 0xF;
6924 let m_bit = (m >> 4) & 1;
6925
6926 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6927}
6928
6929fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6931 encode_mve_3reg(base, qd, qn, qm)
6932}
6933
6934fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6937 let qd_enc = qreg_to_num(qd) * 2;
6938 let rn = reg_to_bits(&addr.base);
6939 let offset = addr.offset;
6940 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6941 let abs_offset = offset.unsigned_abs();
6942 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6946 | (u_bit << 23)
6947 | ((qd_enc >> 4) << 22)
6948 | (rn << 16)
6949 | ((qd_enc & 0xF) << 12)
6950 | (imm7 & 0x7F)
6951}
6952
6953fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6955 let qd_enc = qreg_to_num(qd) * 2;
6956 let rn = reg_to_bits(&addr.base);
6957 let offset = addr.offset;
6958 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6959 let abs_offset = offset.unsigned_abs();
6960 let imm7 = (abs_offset / 4) & 0x7F;
6961
6962 0xED000E80
6963 | (u_bit << 23)
6964 | ((qd_enc >> 4) << 22)
6965 | (rn << 16)
6966 | ((qd_enc & 0xF) << 12)
6967 | (imm7 & 0x7F)
6968}
6969
6970impl ArmEncoder {
6971 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6973 let mut result = Vec::new();
6974 let qd_num = qreg_to_num(qd);
6975
6976 for i in 0..4 {
6978 let word = u32::from_le_bytes([
6979 bytes[i * 4],
6980 bytes[i * 4 + 1],
6981 bytes[i * 4 + 2],
6982 bytes[i * 4 + 3],
6983 ]);
6984 let lo16 = word & 0xFFFF;
6985 let hi16 = (word >> 16) & 0xFFFF;
6986
6987 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6989 if hi16 != 0 {
6991 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6992 }
6993
6994 let s_num = qd_num * 4 + i as u32;
6996 let (vn, n) = encode_sreg(s_num);
6997 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6998 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6999 }
7000
7001 Ok(result)
7002 }
7003
7004 fn encode_thumb_mve_lane_wise_f32_binop(
7006 &self,
7007 qd: &QReg,
7008 qn: &QReg,
7009 qm: &QReg,
7010 vfp_base: u32,
7011 ) -> Result<Vec<u8>> {
7012 let mut result = Vec::new();
7013 let qd_num = qreg_to_num(qd);
7014 let qn_num = qreg_to_num(qn);
7015 let qm_num = qreg_to_num(qm);
7016
7017 for i in 0..4u32 {
7019 let sd = qd_num * 4 + i;
7020 let sn = qn_num * 4 + i;
7021 let sm = qm_num * 4 + i;
7022
7023 let (vd, d) = encode_sreg(sd);
7024 let (vn, n) = encode_sreg(sn);
7025 let (vm, m) = encode_sreg(sm);
7026
7027 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7028 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7029 }
7030
7031 Ok(result)
7032 }
7033
7034 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7036 let mut result = Vec::new();
7037 let qd_num = qreg_to_num(qd);
7038 let qm_num = qreg_to_num(qm);
7039
7040 for i in 0..4u32 {
7042 let sd = qd_num * 4 + i;
7043 let sm = qm_num * 4 + i;
7044
7045 let (vd, d) = encode_sreg(sd);
7046 let (vm, m) = encode_sreg(sm);
7047
7048 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7049 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7050 }
7051
7052 Ok(result)
7053 }
7054}
7055
7056#[cfg(test)]
7057mod tests {
7058 use super::*;
7059
7060 #[test]
7061 fn test_encoder_creation() {
7062 let encoder_arm = ArmEncoder::new_arm32();
7063 assert!(!encoder_arm.thumb_mode);
7064
7065 let encoder_thumb = ArmEncoder::new_thumb2();
7066 assert!(encoder_thumb.thumb_mode);
7067 }
7068
7069 #[test]
7076 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7077 use synth_synthesis::{ArmOp, Condition, Reg};
7078 let enc = ArmEncoder::new_thumb2();
7079 let hi = enc
7081 .encode(&ArmOp::SetCond {
7082 rd: Reg::R12,
7083 cond: Condition::NE,
7084 })
7085 .unwrap();
7086 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7087 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7089 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7090 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7091 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7092 let lo = enc
7094 .encode(&ArmOp::SetCond {
7095 rd: Reg::R0,
7096 cond: Condition::NE,
7097 })
7098 .unwrap();
7099 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7100 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7101 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7102 }
7103
7104 #[test]
7108 fn test_encode_umull_209b() {
7109 use synth_synthesis::{ArmOp, Reg};
7110 let op = ArmOp::Umull {
7111 rdlo: Reg::R4,
7112 rdhi: Reg::R5,
7113 rn: Reg::R0,
7114 rm: Reg::R3,
7115 };
7116 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7118 assert_eq!(
7119 t,
7120 vec![0xA0, 0xFB, 0x03, 0x45],
7121 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7122 );
7123 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7125 assert_eq!(
7126 a,
7127 0xE085_4390u32.to_le_bytes().to_vec(),
7128 "umull (A32): {a:02x?}"
7129 );
7130 }
7131
7132 #[test]
7139 fn test_encode_arm32_indexed_load_keeps_index_206() {
7140 use synth_synthesis::{ArmOp, MemAddr, Reg};
7141 let enc = ArmEncoder::new_arm32();
7142 let bytes = enc
7144 .encode(&ArmOp::Ldr {
7145 rd: Reg::R0,
7146 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7147 })
7148 .unwrap();
7149 assert_eq!(
7150 bytes.len(),
7151 8,
7152 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7153 );
7154 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7155 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7156 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7158 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7160 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7162 }
7163
7164 #[test]
7171 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7172 let encoder = ArmEncoder::new_thumb2();
7173
7174 let code = encoder
7176 .encode(&ArmOp::Add {
7177 rd: Reg::R12,
7178 rn: Reg::R12,
7179 op2: Operand2::Reg(Reg::R0),
7180 })
7181 .unwrap();
7182 assert_eq!(
7184 code,
7185 vec![0x0C, 0xEB, 0x00, 0x0C],
7186 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7187 );
7188 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7190
7191 let lo = encoder
7193 .encode(&ArmOp::Add {
7194 rd: Reg::R1,
7195 rn: Reg::R2,
7196 op2: Operand2::Reg(Reg::R3),
7197 })
7198 .unwrap();
7199 assert_eq!(
7200 lo.len(),
7201 2,
7202 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7203 );
7204 }
7205
7206 #[test]
7209 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7210 let encoder = ArmEncoder::new_thumb2();
7211
7212 let adds = encoder
7214 .encode(&ArmOp::Adds {
7215 rd: Reg::R10,
7216 rn: Reg::R10,
7217 op2: Operand2::Reg(Reg::R8),
7218 })
7219 .unwrap();
7220 assert_eq!(
7221 adds,
7222 vec![0x1A, 0xEB, 0x08, 0x0A],
7223 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7224 );
7225
7226 let subs = encoder
7228 .encode(&ArmOp::Subs {
7229 rd: Reg::R10,
7230 rn: Reg::R10,
7231 op2: Operand2::Reg(Reg::R8),
7232 })
7233 .unwrap();
7234 assert_eq!(
7235 subs,
7236 vec![0xBA, 0xEB, 0x08, 0x0A],
7237 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7238 );
7239 }
7240
7241 #[test]
7244 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7245 let encoder = ArmEncoder::new_thumb2();
7246
7247 let cmn = encoder
7249 .encode(&ArmOp::Cmn {
7250 rn: Reg::R10,
7251 op2: Operand2::Reg(Reg::R8),
7252 })
7253 .unwrap();
7254 assert_eq!(
7255 cmn,
7256 vec![0x1A, 0xEB, 0x08, 0x0F],
7257 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7258 );
7259
7260 let lo = encoder
7262 .encode(&ArmOp::Cmn {
7263 rn: Reg::R1,
7264 op2: Operand2::Reg(Reg::R2),
7265 })
7266 .unwrap();
7267 assert_eq!(
7268 lo.len(),
7269 2,
7270 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7271 );
7272 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7273 }
7274
7275 #[test]
7279 fn test_encode_pc_operand_returns_err_not_panic_185() {
7280 let encoder = ArmEncoder::new_thumb2();
7281 for op in [
7282 ArmOp::Sdiv {
7283 rd: Reg::PC,
7284 rn: Reg::R0,
7285 rm: Reg::R1,
7286 },
7287 ArmOp::Udiv {
7288 rd: Reg::R0,
7289 rn: Reg::PC,
7290 rm: Reg::R1,
7291 },
7292 ArmOp::Sdiv {
7293 rd: Reg::R0,
7294 rn: Reg::R1,
7295 rm: Reg::PC,
7296 },
7297 ] {
7298 let r = encoder.encode(&op);
7299 assert!(
7300 r.is_err(),
7301 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7302 );
7303 }
7304 assert!(
7306 encoder
7307 .encode(&ArmOp::Sdiv {
7308 rd: Reg::R0,
7309 rn: Reg::R1,
7310 rm: Reg::R2
7311 })
7312 .is_ok()
7313 );
7314 }
7315
7316 #[test]
7317 fn test_encode_nop_arm32() {
7318 let encoder = ArmEncoder::new_arm32();
7319 let code = encoder.encode(&ArmOp::Nop).unwrap();
7320
7321 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7324
7325 #[test]
7326 fn test_encode_nop_thumb() {
7327 let encoder = ArmEncoder::new_thumb2();
7328 let code = encoder.encode(&ArmOp::Nop).unwrap();
7329
7330 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7333
7334 #[test]
7335 fn test_encode_mov_immediate_arm32() {
7336 let encoder = ArmEncoder::new_arm32();
7337 let op = ArmOp::Mov {
7338 rd: Reg::R0,
7339 op2: Operand2::Imm(42),
7340 };
7341
7342 let code = encoder.encode(&op).unwrap();
7343 assert_eq!(code.len(), 4);
7344
7345 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7347 assert_eq!(instr & 0x0E000000, 0x02000000); }
7349
7350 #[test]
7351 fn test_encode_add_registers_arm32() {
7352 let encoder = ArmEncoder::new_arm32();
7353 let op = ArmOp::Add {
7354 rd: Reg::R0,
7355 rn: Reg::R1,
7356 op2: Operand2::Reg(Reg::R2),
7357 };
7358
7359 let code = encoder.encode(&op).unwrap();
7360 assert_eq!(code.len(), 4);
7361
7362 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7363 assert_eq!(instr & 0x0FE00000, 0x00800000);
7365 }
7366
7367 #[test]
7368 fn test_encode_ldr_arm32() {
7369 let encoder = ArmEncoder::new_arm32();
7370 let op = ArmOp::Ldr {
7371 rd: Reg::R0,
7372 addr: MemAddr::imm(Reg::R1, 4),
7373 };
7374
7375 let code = encoder.encode(&op).unwrap();
7376 assert_eq!(code.len(), 4);
7377
7378 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7379 assert_eq!(instr & 0x00100000, 0x00100000);
7381 }
7382
7383 #[test]
7384 fn test_encode_str_arm32() {
7385 let encoder = ArmEncoder::new_arm32();
7386 let op = ArmOp::Str {
7387 rd: Reg::R0,
7388 addr: MemAddr::imm(Reg::SP, 0),
7389 };
7390
7391 let code = encoder.encode(&op).unwrap();
7392 assert_eq!(code.len(), 4);
7393 }
7394
7395 #[test]
7396 fn test_encode_branch_arm32() {
7397 let encoder = ArmEncoder::new_arm32();
7398 let op = ArmOp::Bl {
7399 label: "main".to_string(),
7400 };
7401
7402 let code = encoder.encode(&op).unwrap();
7403 assert_eq!(code.len(), 4);
7404
7405 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7406 assert_eq!(instr & 0x0F000000, 0x0B000000);
7408 }
7409
7410 #[test]
7420 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7421 let encoder = ArmEncoder::new_thumb2();
7422 let op = ArmOp::Bl {
7423 label: "callee".to_string(),
7424 };
7425
7426 let code = encoder.encode(&op).unwrap();
7427 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7428
7429 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7430 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7431 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7432 assert_eq!(
7433 hw2, 0xFFFE,
7434 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7435 );
7436 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7437 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7438 }
7439
7440 #[test]
7441 fn test_encode_sequence() {
7442 let encoder = ArmEncoder::new_arm32();
7443 let ops = vec![
7444 ArmOp::Mov {
7445 rd: Reg::R0,
7446 op2: Operand2::Imm(42),
7447 },
7448 ArmOp::Mov {
7449 rd: Reg::R1,
7450 op2: Operand2::Imm(10),
7451 },
7452 ArmOp::Add {
7453 rd: Reg::R2,
7454 rn: Reg::R0,
7455 op2: Operand2::Reg(Reg::R1),
7456 },
7457 ];
7458
7459 let code = encoder.encode_sequence(&ops).unwrap();
7460 assert_eq!(code.len(), 12); }
7462
7463 #[test]
7464 fn test_reg_to_bits() {
7465 assert_eq!(reg_to_bits(&Reg::R0), 0);
7466 assert_eq!(reg_to_bits(&Reg::R7), 7);
7467 assert_eq!(reg_to_bits(&Reg::SP), 13);
7468 assert_eq!(reg_to_bits(&Reg::LR), 14);
7469 assert_eq!(reg_to_bits(&Reg::PC), 15);
7470 }
7471
7472 #[test]
7473 fn test_encode_bitwise_operations() {
7474 let encoder = ArmEncoder::new_arm32();
7475
7476 let and_op = ArmOp::And {
7477 rd: Reg::R0,
7478 rn: Reg::R1,
7479 op2: Operand2::Reg(Reg::R2),
7480 };
7481 let and_code = encoder.encode(&and_op).unwrap();
7482 assert_eq!(and_code.len(), 4);
7483
7484 let orr_op = ArmOp::Orr {
7485 rd: Reg::R0,
7486 rn: Reg::R1,
7487 op2: Operand2::Reg(Reg::R2),
7488 };
7489 let orr_code = encoder.encode(&orr_op).unwrap();
7490 assert_eq!(orr_code.len(), 4);
7491
7492 let eor_op = ArmOp::Eor {
7493 rd: Reg::R0,
7494 rn: Reg::R1,
7495 op2: Operand2::Reg(Reg::R2),
7496 };
7497 let eor_code = encoder.encode(&eor_op).unwrap();
7498 assert_eq!(eor_code.len(), 4);
7499 }
7500
7501 #[test]
7504 fn test_encode_sdiv_thumb2() {
7505 let encoder = ArmEncoder::new_thumb2();
7506 let op = ArmOp::Sdiv {
7507 rd: Reg::R0,
7508 rn: Reg::R1,
7509 rm: Reg::R2,
7510 };
7511
7512 let code = encoder.encode(&op).unwrap();
7513 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7520 assert_eq!(code[1], 0xFB);
7521 assert_eq!(code[2], 0xF2);
7522 assert_eq!(code[3], 0xF0);
7523 }
7524
7525 #[test]
7526 fn test_encode_udiv_thumb2() {
7527 let encoder = ArmEncoder::new_thumb2();
7528 let op = ArmOp::Udiv {
7529 rd: Reg::R0,
7530 rn: Reg::R1,
7531 rm: Reg::R2,
7532 };
7533
7534 let code = encoder.encode(&op).unwrap();
7535 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7540 assert_eq!(code[1], 0xFB);
7541 assert_eq!(code[2], 0xF2);
7542 assert_eq!(code[3], 0xF0);
7543 }
7544
7545 #[test]
7546 fn test_encode_mul_thumb2() {
7547 let encoder = ArmEncoder::new_thumb2();
7548 let op = ArmOp::Mul {
7549 rd: Reg::R0,
7550 rn: Reg::R1,
7551 rm: Reg::R2,
7552 };
7553
7554 let code = encoder.encode(&op).unwrap();
7555 assert_eq!(code.len(), 4); }
7557
7558 #[test]
7559 fn test_encode_and_thumb2() {
7560 let encoder = ArmEncoder::new_thumb2();
7561 let op = ArmOp::And {
7562 rd: Reg::R0,
7563 rn: Reg::R1,
7564 op2: Operand2::Reg(Reg::R2),
7565 };
7566
7567 let code = encoder.encode(&op).unwrap();
7568 assert_eq!(code.len(), 4); }
7570
7571 #[test]
7572 fn test_encode_lsl_thumb2_low_regs() {
7573 let encoder = ArmEncoder::new_thumb2();
7574 let op = ArmOp::Lsl {
7575 rd: Reg::R0,
7576 rn: Reg::R1,
7577 shift: 5,
7578 };
7579
7580 let code = encoder.encode(&op).unwrap();
7581 assert_eq!(code.len(), 2); }
7583
7584 #[test]
7585 fn test_encode_clz_thumb2() {
7586 let encoder = ArmEncoder::new_thumb2();
7587 let op = ArmOp::Clz {
7588 rd: Reg::R0,
7589 rm: Reg::R1,
7590 };
7591
7592 let code = encoder.encode(&op).unwrap();
7593 assert_eq!(code.len(), 4); }
7595
7596 #[test]
7597 fn test_encode_bx_thumb2() {
7598 let encoder = ArmEncoder::new_thumb2();
7599 let op = ArmOp::Bx { rm: Reg::LR };
7600
7601 let code = encoder.encode(&op).unwrap();
7602 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7606 }
7607
7608 #[test]
7613 fn test_encode_f32_abs_arm32() {
7614 let encoder = ArmEncoder::new_arm32();
7615 let op = ArmOp::F32Abs {
7616 sd: VfpReg::S0,
7617 sm: VfpReg::S2,
7618 };
7619 let code = encoder.encode(&op).unwrap();
7620 assert_eq!(code.len(), 4); }
7622
7623 #[test]
7624 fn test_encode_f32_neg_arm32() {
7625 let encoder = ArmEncoder::new_arm32();
7626 let op = ArmOp::F32Neg {
7627 sd: VfpReg::S0,
7628 sm: VfpReg::S2,
7629 };
7630 let code = encoder.encode(&op).unwrap();
7631 assert_eq!(code.len(), 4);
7632 }
7633
7634 #[test]
7635 fn test_encode_f32_sqrt_arm32() {
7636 let encoder = ArmEncoder::new_arm32();
7637 let op = ArmOp::F32Sqrt {
7638 sd: VfpReg::S0,
7639 sm: VfpReg::S2,
7640 };
7641 let code = encoder.encode(&op).unwrap();
7642 assert_eq!(code.len(), 4);
7643 }
7644
7645 #[test]
7646 fn test_encode_f32_ceil_arm32() {
7647 let encoder = ArmEncoder::new_arm32();
7648 let op = ArmOp::F32Ceil {
7649 sd: VfpReg::S0,
7650 sm: VfpReg::S2,
7651 };
7652 let code = encoder.encode(&op).unwrap();
7653 assert_eq!(code.len(), 36);
7655 }
7656
7657 #[test]
7658 fn test_encode_f32_floor_thumb2() {
7659 let encoder = ArmEncoder::new_thumb2();
7660 let op = ArmOp::F32Floor {
7661 sd: VfpReg::S0,
7662 sm: VfpReg::S2,
7663 };
7664 let code = encoder.encode(&op).unwrap();
7665 assert_eq!(code.len(), 36);
7667 }
7668
7669 #[test]
7670 fn test_encode_f32_min_arm32() {
7671 let encoder = ArmEncoder::new_arm32();
7672 let op = ArmOp::F32Min {
7673 sd: VfpReg::S0,
7674 sn: VfpReg::S2,
7675 sm: VfpReg::S4,
7676 };
7677 let code = encoder.encode(&op).unwrap();
7678 assert_eq!(code.len(), 16); }
7680
7681 #[test]
7682 fn test_encode_f32_max_thumb2() {
7683 let encoder = ArmEncoder::new_thumb2();
7684 let op = ArmOp::F32Max {
7685 sd: VfpReg::S0,
7686 sn: VfpReg::S2,
7687 sm: VfpReg::S4,
7688 };
7689 let code = encoder.encode(&op).unwrap();
7690 assert_eq!(code.len(), 18);
7692 }
7693
7694 #[test]
7695 fn test_encode_f32_copysign_arm32() {
7696 let encoder = ArmEncoder::new_arm32();
7697 let op = ArmOp::F32Copysign {
7698 sd: VfpReg::S0,
7699 sn: VfpReg::S2,
7700 sm: VfpReg::S4,
7701 };
7702 let code = encoder.encode(&op).unwrap();
7703 assert_eq!(code.len(), 24);
7705 }
7706
7707 #[test]
7712 fn test_encode_f64_add_arm32() {
7713 let encoder = ArmEncoder::new_arm32();
7714 let op = ArmOp::F64Add {
7715 dd: VfpReg::D0,
7716 dn: VfpReg::D1,
7717 dm: VfpReg::D2,
7718 };
7719 let code = encoder.encode(&op).unwrap();
7720 assert_eq!(code.len(), 4);
7721 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7723 assert_eq!((instr >> 8) & 0xF, 0xB); }
7725
7726 #[test]
7727 fn test_encode_f64_sub_thumb2() {
7728 let encoder = ArmEncoder::new_thumb2();
7729 let op = ArmOp::F64Sub {
7730 dd: VfpReg::D0,
7731 dn: VfpReg::D1,
7732 dm: VfpReg::D2,
7733 };
7734 let code = encoder.encode(&op).unwrap();
7735 assert_eq!(code.len(), 4); }
7737
7738 #[test]
7739 fn test_encode_f64_mul_arm32() {
7740 let encoder = ArmEncoder::new_arm32();
7741 let op = ArmOp::F64Mul {
7742 dd: VfpReg::D0,
7743 dn: VfpReg::D1,
7744 dm: VfpReg::D2,
7745 };
7746 let code = encoder.encode(&op).unwrap();
7747 assert_eq!(code.len(), 4);
7748 }
7749
7750 #[test]
7751 fn test_encode_f64_div_arm32() {
7752 let encoder = ArmEncoder::new_arm32();
7753 let op = ArmOp::F64Div {
7754 dd: VfpReg::D0,
7755 dn: VfpReg::D1,
7756 dm: VfpReg::D2,
7757 };
7758 let code = encoder.encode(&op).unwrap();
7759 assert_eq!(code.len(), 4);
7760 }
7761
7762 #[test]
7763 fn test_encode_f64_abs_arm32() {
7764 let encoder = ArmEncoder::new_arm32();
7765 let op = ArmOp::F64Abs {
7766 dd: VfpReg::D0,
7767 dm: VfpReg::D2,
7768 };
7769 let code = encoder.encode(&op).unwrap();
7770 assert_eq!(code.len(), 4);
7771 }
7772
7773 #[test]
7774 fn test_encode_f64_neg_arm32() {
7775 let encoder = ArmEncoder::new_arm32();
7776 let op = ArmOp::F64Neg {
7777 dd: VfpReg::D0,
7778 dm: VfpReg::D2,
7779 };
7780 let code = encoder.encode(&op).unwrap();
7781 assert_eq!(code.len(), 4);
7782 }
7783
7784 #[test]
7785 fn test_encode_f64_sqrt_arm32() {
7786 let encoder = ArmEncoder::new_arm32();
7787 let op = ArmOp::F64Sqrt {
7788 dd: VfpReg::D0,
7789 dm: VfpReg::D2,
7790 };
7791 let code = encoder.encode(&op).unwrap();
7792 assert_eq!(code.len(), 4);
7793 }
7794
7795 #[test]
7796 fn test_encode_f64_load_arm32() {
7797 let encoder = ArmEncoder::new_arm32();
7798 let op = ArmOp::F64Load {
7799 dd: VfpReg::D0,
7800 addr: MemAddr::imm(Reg::R0, 8),
7801 };
7802 let code = encoder.encode(&op).unwrap();
7803 assert_eq!(code.len(), 4);
7804 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7805 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7808
7809 #[test]
7810 fn test_encode_f64_store_thumb2() {
7811 let encoder = ArmEncoder::new_thumb2();
7812 let op = ArmOp::F64Store {
7813 dd: VfpReg::D0,
7814 addr: MemAddr::imm(Reg::SP, 0),
7815 };
7816 let code = encoder.encode(&op).unwrap();
7817 assert_eq!(code.len(), 4);
7818 }
7819
7820 #[test]
7821 fn test_encode_f64_compare_arm32() {
7822 let encoder = ArmEncoder::new_arm32();
7823 let op = ArmOp::F64Eq {
7824 rd: Reg::R0,
7825 dn: VfpReg::D0,
7826 dm: VfpReg::D1,
7827 };
7828 let code = encoder.encode(&op).unwrap();
7829 assert_eq!(code.len(), 16); }
7831
7832 #[test]
7833 fn test_encode_f64_compare_thumb2() {
7834 let encoder = ArmEncoder::new_thumb2();
7835 let op = ArmOp::F64Lt {
7836 rd: Reg::R0,
7837 dn: VfpReg::D0,
7838 dm: VfpReg::D1,
7839 };
7840 let code = encoder.encode(&op).unwrap();
7841 assert_eq!(code.len(), 14);
7843 }
7844
7845 #[test]
7846 fn test_encode_f64_const_arm32() {
7847 let encoder = ArmEncoder::new_arm32();
7848 let op = ArmOp::F64Const {
7849 dd: VfpReg::D0,
7850 value: 3.125,
7851 };
7852 let code = encoder.encode(&op).unwrap();
7853 assert_eq!(code.len(), 20);
7855 }
7856
7857 #[test]
7858 fn test_encode_f64_const_thumb2() {
7859 let encoder = ArmEncoder::new_thumb2();
7860 let op = ArmOp::F64Const {
7861 dd: VfpReg::D0,
7862 value: 2.5,
7863 };
7864 let code = encoder.encode(&op).unwrap();
7865 assert_eq!(code.len(), 20);
7867 }
7868
7869 #[test]
7870 fn test_encode_f64_convert_i32s_arm32() {
7871 let encoder = ArmEncoder::new_arm32();
7872 let op = ArmOp::F64ConvertI32S {
7873 dd: VfpReg::D0,
7874 rm: Reg::R0,
7875 };
7876 let code = encoder.encode(&op).unwrap();
7877 assert_eq!(code.len(), 8);
7879 }
7880
7881 #[test]
7882 fn test_encode_f64_promote_f32_arm32() {
7883 let encoder = ArmEncoder::new_arm32();
7884 let op = ArmOp::F64PromoteF32 {
7885 dd: VfpReg::D0,
7886 sm: VfpReg::S0,
7887 };
7888 let code = encoder.encode(&op).unwrap();
7889 assert_eq!(code.len(), 4); }
7891
7892 #[test]
7893 fn test_encode_f64_promote_f32_thumb2() {
7894 let encoder = ArmEncoder::new_thumb2();
7895 let op = ArmOp::F64PromoteF32 {
7896 dd: VfpReg::D0,
7897 sm: VfpReg::S0,
7898 };
7899 let code = encoder.encode(&op).unwrap();
7900 assert_eq!(code.len(), 4);
7901 }
7902
7903 #[test]
7904 fn test_encode_i32_trunc_f64s_arm32() {
7905 let encoder = ArmEncoder::new_arm32();
7906 let op = ArmOp::I32TruncF64S {
7907 rd: Reg::R0,
7908 dm: VfpReg::D0,
7909 };
7910 let code = encoder.encode(&op).unwrap();
7911 assert_eq!(code.len(), 8);
7913 }
7914
7915 #[test]
7916 fn test_encode_f64_reinterpret_i64_arm32() {
7917 let encoder = ArmEncoder::new_arm32();
7918 let op = ArmOp::F64ReinterpretI64 {
7919 dd: VfpReg::D0,
7920 rmlo: Reg::R0,
7921 rmhi: Reg::R1,
7922 };
7923 let code = encoder.encode(&op).unwrap();
7924 assert_eq!(code.len(), 4); }
7926
7927 #[test]
7928 fn test_encode_i64_reinterpret_f64_thumb2() {
7929 let encoder = ArmEncoder::new_thumb2();
7930 let op = ArmOp::I64ReinterpretF64 {
7931 rdlo: Reg::R0,
7932 rdhi: Reg::R1,
7933 dm: VfpReg::D0,
7934 };
7935 let code = encoder.encode(&op).unwrap();
7936 assert_eq!(code.len(), 4);
7937 }
7938
7939 #[test]
7940 fn test_encode_f64_trunc_thumb2() {
7941 let encoder = ArmEncoder::new_thumb2();
7942 let op = ArmOp::F64Trunc {
7943 dd: VfpReg::D0,
7944 dm: VfpReg::D1,
7945 };
7946 let code = encoder.encode(&op).unwrap();
7947 assert_eq!(code.len(), 8);
7949 }
7950
7951 #[test]
7952 fn test_encode_f64_min_arm32() {
7953 let encoder = ArmEncoder::new_arm32();
7954 let op = ArmOp::F64Min {
7955 dd: VfpReg::D0,
7956 dn: VfpReg::D1,
7957 dm: VfpReg::D2,
7958 };
7959 let code = encoder.encode(&op).unwrap();
7960 assert_eq!(code.len(), 16);
7962 }
7963
7964 #[test]
7965 fn test_f64_cp11_encoding() {
7966 let encoder = ArmEncoder::new_arm32();
7968
7969 let code = encoder
7971 .encode(&ArmOp::F64Add {
7972 dd: VfpReg::D0,
7973 dn: VfpReg::D0,
7974 dm: VfpReg::D0,
7975 })
7976 .unwrap();
7977 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7978 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7979
7980 let code = encoder
7982 .encode(&ArmOp::F32Add {
7983 sd: VfpReg::S0,
7984 sn: VfpReg::S0,
7985 sm: VfpReg::S0,
7986 })
7987 .unwrap();
7988 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7989 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7990 }
7991
7992 #[test]
7993 fn test_dreg_encoding_higher_registers() {
7994 let encoder = ArmEncoder::new_arm32();
7995
7996 let op = ArmOp::F64Add {
7998 dd: VfpReg::D15,
7999 dn: VfpReg::D14,
8000 dm: VfpReg::D13,
8001 };
8002 let code = encoder.encode(&op).unwrap();
8003 assert_eq!(code.len(), 4);
8004
8005 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8007 assert_eq!((instr >> 8) & 0xF, 0xB); }
8009
8010 #[test]
8015 fn test_encode_label_emits_no_bytes() {
8016 let encoder = ArmEncoder::new_thumb2();
8017 let op = ArmOp::Label {
8018 name: ".Lblock_end_0".to_string(),
8019 };
8020 let code = encoder.encode(&op).unwrap();
8021 assert!(code.is_empty(), "Label should emit zero bytes");
8022
8023 let encoder32 = ArmEncoder::new_arm32();
8024 let code32 = encoder32.encode(&op).unwrap();
8025 assert!(
8026 code32.is_empty(),
8027 "Label should emit zero bytes in ARM32 too"
8028 );
8029 }
8030
8031 #[test]
8032 fn test_encode_bcc_eq_thumb2() {
8033 use synth_synthesis::Condition;
8034 let encoder = ArmEncoder::new_thumb2();
8035 let op = ArmOp::Bcc {
8036 cond: Condition::EQ,
8037 label: "target".to_string(),
8038 };
8039 let code = encoder.encode(&op).unwrap();
8040 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8044 }
8045
8046 #[test]
8047 fn test_encode_bcc_ne_thumb2() {
8048 use synth_synthesis::Condition;
8049 let encoder = ArmEncoder::new_thumb2();
8050 let op = ArmOp::Bcc {
8051 cond: Condition::NE,
8052 label: "target".to_string(),
8053 };
8054 let code = encoder.encode(&op).unwrap();
8055 assert_eq!(code.len(), 2);
8056
8057 assert_eq!(code, vec![0x00, 0xD1]);
8059 }
8060
8061 #[test]
8062 fn test_encode_bcc_arm32() {
8063 use synth_synthesis::Condition;
8064 let encoder = ArmEncoder::new_arm32();
8065 let op = ArmOp::Bcc {
8066 cond: Condition::EQ,
8067 label: "target".to_string(),
8068 };
8069 let code = encoder.encode(&op).unwrap();
8070 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8073 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8077
8078 #[test]
8079 fn test_encode_udf_thumb2() {
8080 let encoder = ArmEncoder::new_thumb2();
8081 let op = ArmOp::Udf { imm: 0 };
8082 let code = encoder.encode(&op).unwrap();
8083 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8087 }
8088
8089 #[test]
8090 fn test_encode_nop_thumb2() {
8091 let encoder = ArmEncoder::new_thumb2();
8092 let op = ArmOp::Nop;
8093 let code = encoder.encode(&op).unwrap();
8094 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8098 }
8099
8100 #[test]
8105 fn test_encode_i64_add_thumb2() {
8106 let encoder = ArmEncoder::new_thumb2();
8107 let op = ArmOp::I64Add {
8108 rdlo: Reg::R0,
8109 rdhi: Reg::R1,
8110 rnlo: Reg::R0,
8111 rnhi: Reg::R1,
8112 rmlo: Reg::R2,
8113 rmhi: Reg::R3,
8114 };
8115 let code = encoder.encode(&op).unwrap();
8116 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8118 }
8119
8120 #[test]
8121 fn test_encode_i64_sub_thumb2() {
8122 let encoder = ArmEncoder::new_thumb2();
8123 let op = ArmOp::I64Sub {
8124 rdlo: Reg::R0,
8125 rdhi: Reg::R1,
8126 rnlo: Reg::R0,
8127 rnhi: Reg::R1,
8128 rmlo: Reg::R2,
8129 rmhi: Reg::R3,
8130 };
8131 let code = encoder.encode(&op).unwrap();
8132 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8134 }
8135
8136 #[test]
8137 fn test_encode_i64_and_thumb2() {
8138 let encoder = ArmEncoder::new_thumb2();
8139 let op = ArmOp::I64And {
8140 rdlo: Reg::R0,
8141 rdhi: Reg::R1,
8142 rnlo: Reg::R0,
8143 rnhi: Reg::R1,
8144 rmlo: Reg::R2,
8145 rmhi: Reg::R3,
8146 };
8147 let code = encoder.encode(&op).unwrap();
8148 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8150 }
8151
8152 #[test]
8153 fn test_encode_i64_or_thumb2() {
8154 let encoder = ArmEncoder::new_thumb2();
8155 let op = ArmOp::I64Or {
8156 rdlo: Reg::R0,
8157 rdhi: Reg::R1,
8158 rnlo: Reg::R0,
8159 rnhi: Reg::R1,
8160 rmlo: Reg::R2,
8161 rmhi: Reg::R3,
8162 };
8163 let code = encoder.encode(&op).unwrap();
8164 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8165 }
8166
8167 #[test]
8168 fn test_encode_i64_xor_thumb2() {
8169 let encoder = ArmEncoder::new_thumb2();
8170 let op = ArmOp::I64Xor {
8171 rdlo: Reg::R0,
8172 rdhi: Reg::R1,
8173 rnlo: Reg::R0,
8174 rnhi: Reg::R1,
8175 rmlo: Reg::R2,
8176 rmhi: Reg::R3,
8177 };
8178 let code = encoder.encode(&op).unwrap();
8179 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8180 }
8181
8182 #[test]
8183 fn test_encode_i64_const_small_thumb2() {
8184 let encoder = ArmEncoder::new_thumb2();
8185 let op = ArmOp::I64Const {
8187 rdlo: Reg::R0,
8188 rdhi: Reg::R1,
8189 value: 42,
8190 };
8191 let code = encoder.encode(&op).unwrap();
8192 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8194 }
8195
8196 #[test]
8197 fn test_encode_i64_const_large_thumb2() {
8198 let encoder = ArmEncoder::new_thumb2();
8199 let op = ArmOp::I64Const {
8201 rdlo: Reg::R0,
8202 rdhi: Reg::R1,
8203 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8204 };
8205 let code = encoder.encode(&op).unwrap();
8206 assert_eq!(
8208 code.len(),
8209 16,
8210 "I64Const with large value should be 16 bytes"
8211 );
8212 }
8213
8214 #[test]
8215 fn test_encode_i64_extend_i32_s_thumb2() {
8216 let encoder = ArmEncoder::new_thumb2();
8217 let op = ArmOp::I64ExtendI32S {
8218 rdlo: Reg::R0,
8219 rdhi: Reg::R1,
8220 rn: Reg::R0,
8221 };
8222 let code = encoder.encode(&op).unwrap();
8223 assert_eq!(
8225 code.len(),
8226 4,
8227 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8228 );
8229 }
8230
8231 #[test]
8232 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8233 let encoder = ArmEncoder::new_thumb2();
8234 let op = ArmOp::I64ExtendI32S {
8235 rdlo: Reg::R0,
8236 rdhi: Reg::R1,
8237 rn: Reg::R2,
8238 };
8239 let code = encoder.encode(&op).unwrap();
8240 assert!(
8242 code.len() >= 6,
8243 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8244 );
8245 }
8246
8247 #[test]
8248 fn test_encode_i64_extend_i32_u_thumb2() {
8249 let encoder = ArmEncoder::new_thumb2();
8250 let op = ArmOp::I64ExtendI32U {
8251 rdlo: Reg::R0,
8252 rdhi: Reg::R1,
8253 rn: Reg::R0,
8254 };
8255 let code = encoder.encode(&op).unwrap();
8256 assert_eq!(
8258 code.len(),
8259 2,
8260 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8261 );
8262 }
8263
8264 #[test]
8265 fn test_encode_i32_wrap_i64_nop_thumb2() {
8266 let encoder = ArmEncoder::new_thumb2();
8267 let op = ArmOp::I32WrapI64 {
8269 rd: Reg::R0,
8270 rnlo: Reg::R0,
8271 };
8272 let code = encoder.encode(&op).unwrap();
8273 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8274 assert_eq!(code, vec![0x00, 0xBF]); }
8276
8277 #[test]
8278 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8279 let encoder = ArmEncoder::new_thumb2();
8280 let op = ArmOp::I32WrapI64 {
8281 rd: Reg::R2,
8282 rnlo: Reg::R0,
8283 };
8284 let code = encoder.encode(&op).unwrap();
8285 assert!(
8287 code.len() >= 2,
8288 "I32WrapI64 diff reg should emit at least 2 bytes"
8289 );
8290 }
8291
8292 #[test]
8293 fn test_encode_i64_eqz_thumb2() {
8294 let encoder = ArmEncoder::new_thumb2();
8295 let op = ArmOp::I64Eqz {
8296 rd: Reg::R0,
8297 rnlo: Reg::R0,
8298 rnhi: Reg::R1,
8299 };
8300 let code = encoder.encode(&op).unwrap();
8301 assert!(
8303 code.len() >= 6,
8304 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8305 );
8306 }
8307
8308 #[test]
8309 fn test_encode_i64_eq_thumb2() {
8310 let encoder = ArmEncoder::new_thumb2();
8311 let op = ArmOp::I64Eq {
8312 rd: Reg::R0,
8313 rnlo: Reg::R0,
8314 rnhi: Reg::R1,
8315 rmlo: Reg::R2,
8316 rmhi: Reg::R3,
8317 };
8318 let code = encoder.encode(&op).unwrap();
8319 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8321 }
8322
8323 #[test]
8324 fn test_encode_i64_ldr_thumb2() {
8325 let encoder = ArmEncoder::new_thumb2();
8326 let op = ArmOp::I64Ldr {
8327 rdlo: Reg::R0,
8328 rdhi: Reg::R1,
8329 addr: MemAddr::imm(Reg::SP, 0),
8330 };
8331 let code = encoder.encode(&op).unwrap();
8332 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8334 }
8335
8336 #[test]
8337 fn test_encode_i64_str_thumb2() {
8338 let encoder = ArmEncoder::new_thumb2();
8339 let op = ArmOp::I64Str {
8340 rdlo: Reg::R0,
8341 rdhi: Reg::R1,
8342 addr: MemAddr::imm(Reg::SP, 0),
8343 };
8344 let code = encoder.encode(&op).unwrap();
8345 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8347 }
8348
8349 #[test]
8350 fn test_encode_i64_all_comparisons_thumb2() {
8351 let encoder = ArmEncoder::new_thumb2();
8352
8353 let ops = vec![
8354 ArmOp::I64Ne {
8355 rd: Reg::R0,
8356 rnlo: Reg::R0,
8357 rnhi: Reg::R1,
8358 rmlo: Reg::R2,
8359 rmhi: Reg::R3,
8360 },
8361 ArmOp::I64LtS {
8362 rd: Reg::R0,
8363 rnlo: Reg::R0,
8364 rnhi: Reg::R1,
8365 rmlo: Reg::R2,
8366 rmhi: Reg::R3,
8367 },
8368 ArmOp::I64LtU {
8369 rd: Reg::R0,
8370 rnlo: Reg::R0,
8371 rnhi: Reg::R1,
8372 rmlo: Reg::R2,
8373 rmhi: Reg::R3,
8374 },
8375 ArmOp::I64LeS {
8376 rd: Reg::R0,
8377 rnlo: Reg::R0,
8378 rnhi: Reg::R1,
8379 rmlo: Reg::R2,
8380 rmhi: Reg::R3,
8381 },
8382 ArmOp::I64LeU {
8383 rd: Reg::R0,
8384 rnlo: Reg::R0,
8385 rnhi: Reg::R1,
8386 rmlo: Reg::R2,
8387 rmhi: Reg::R3,
8388 },
8389 ArmOp::I64GtS {
8390 rd: Reg::R0,
8391 rnlo: Reg::R0,
8392 rnhi: Reg::R1,
8393 rmlo: Reg::R2,
8394 rmhi: Reg::R3,
8395 },
8396 ArmOp::I64GtU {
8397 rd: Reg::R0,
8398 rnlo: Reg::R0,
8399 rnhi: Reg::R1,
8400 rmlo: Reg::R2,
8401 rmhi: Reg::R3,
8402 },
8403 ArmOp::I64GeS {
8404 rd: Reg::R0,
8405 rnlo: Reg::R0,
8406 rnhi: Reg::R1,
8407 rmlo: Reg::R2,
8408 rmhi: Reg::R3,
8409 },
8410 ArmOp::I64GeU {
8411 rd: Reg::R0,
8412 rnlo: Reg::R0,
8413 rnhi: Reg::R1,
8414 rmlo: Reg::R2,
8415 rmhi: Reg::R3,
8416 },
8417 ];
8418
8419 for op in &ops {
8420 let code = encoder.encode(op).unwrap();
8421 assert!(
8422 code.len() >= 8,
8423 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8424 op,
8425 code.len()
8426 );
8427 }
8428 }
8429
8430 #[test]
8431 fn test_encode_i64_const_zero_thumb2() {
8432 let encoder = ArmEncoder::new_thumb2();
8433 let op = ArmOp::I64Const {
8434 rdlo: Reg::R0,
8435 rdhi: Reg::R1,
8436 value: 0,
8437 };
8438 let code = encoder.encode(&op).unwrap();
8439 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8441 }
8442
8443 #[test]
8444 fn test_encode_i64_const_negative_one_thumb2() {
8445 let encoder = ArmEncoder::new_thumb2();
8446 let op = ArmOp::I64Const {
8447 rdlo: Reg::R0,
8448 rdhi: Reg::R1,
8449 value: -1, };
8451 let code = encoder.encode(&op).unwrap();
8452 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8454 }
8455
8456 #[test]
8461 fn test_encode_ldrb_arm32() {
8462 let encoder = ArmEncoder::new_arm32();
8463 let op = ArmOp::Ldrb {
8464 rd: Reg::R0,
8465 addr: MemAddr::imm(Reg::R1, 4),
8466 };
8467 let code = encoder.encode(&op).unwrap();
8468 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8469 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8471 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8472 }
8473
8474 #[test]
8475 fn test_encode_strb_arm32() {
8476 let encoder = ArmEncoder::new_arm32();
8477 let op = ArmOp::Strb {
8478 rd: Reg::R0,
8479 addr: MemAddr::imm(Reg::R1, 0),
8480 };
8481 let code = encoder.encode(&op).unwrap();
8482 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8483 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8485 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8486 }
8487
8488 #[test]
8489 fn test_encode_ldrh_arm32() {
8490 let encoder = ArmEncoder::new_arm32();
8491 let op = ArmOp::Ldrh {
8492 rd: Reg::R0,
8493 addr: MemAddr::imm(Reg::R1, 2),
8494 };
8495 let code = encoder.encode(&op).unwrap();
8496 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8497 }
8498
8499 #[test]
8500 fn test_encode_strh_arm32() {
8501 let encoder = ArmEncoder::new_arm32();
8502 let op = ArmOp::Strh {
8503 rd: Reg::R0,
8504 addr: MemAddr::imm(Reg::R1, 0),
8505 };
8506 let code = encoder.encode(&op).unwrap();
8507 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8508 }
8509
8510 #[test]
8511 fn test_encode_ldrsb_arm32() {
8512 let encoder = ArmEncoder::new_arm32();
8513 let op = ArmOp::Ldrsb {
8514 rd: Reg::R0,
8515 addr: MemAddr::imm(Reg::R1, 0),
8516 };
8517 let code = encoder.encode(&op).unwrap();
8518 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8519 }
8520
8521 #[test]
8522 fn test_encode_ldrsh_arm32() {
8523 let encoder = ArmEncoder::new_arm32();
8524 let op = ArmOp::Ldrsh {
8525 rd: Reg::R0,
8526 addr: MemAddr::imm(Reg::R1, 0),
8527 };
8528 let code = encoder.encode(&op).unwrap();
8529 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8530 }
8531
8532 #[test]
8533 fn test_encode_ldrb_thumb2_16bit() {
8534 let encoder = ArmEncoder::new_thumb2();
8535 let op = ArmOp::Ldrb {
8536 rd: Reg::R0,
8537 addr: MemAddr::imm(Reg::R1, 4),
8538 };
8539 let code = encoder.encode(&op).unwrap();
8540 assert_eq!(
8542 code.len(),
8543 2,
8544 "Thumb-2 LDRB with small offset should be 16-bit"
8545 );
8546 }
8547
8548 #[test]
8549 fn test_encode_ldrb_thumb2_32bit() {
8550 let encoder = ArmEncoder::new_thumb2();
8551 let op = ArmOp::Ldrb {
8552 rd: Reg::R0,
8553 addr: MemAddr::imm(Reg::R1, 100), };
8555 let code = encoder.encode(&op).unwrap();
8556 assert_eq!(
8557 code.len(),
8558 4,
8559 "Thumb-2 LDRB with large offset should be 32-bit"
8560 );
8561 }
8562
8563 #[test]
8564 fn test_encode_strb_thumb2_16bit() {
8565 let encoder = ArmEncoder::new_thumb2();
8566 let op = ArmOp::Strb {
8567 rd: Reg::R0,
8568 addr: MemAddr::imm(Reg::R1, 10),
8569 };
8570 let code = encoder.encode(&op).unwrap();
8571 assert_eq!(
8572 code.len(),
8573 2,
8574 "Thumb-2 STRB with small offset should be 16-bit"
8575 );
8576 }
8577
8578 #[test]
8579 fn test_encode_ldrh_thumb2_16bit() {
8580 let encoder = ArmEncoder::new_thumb2();
8581 let op = ArmOp::Ldrh {
8582 rd: Reg::R0,
8583 addr: MemAddr::imm(Reg::R1, 4), };
8585 let code = encoder.encode(&op).unwrap();
8586 assert_eq!(
8587 code.len(),
8588 2,
8589 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8590 );
8591 }
8592
8593 #[test]
8594 fn test_encode_strh_thumb2_16bit() {
8595 let encoder = ArmEncoder::new_thumb2();
8596 let op = ArmOp::Strh {
8597 rd: Reg::R0,
8598 addr: MemAddr::imm(Reg::R1, 4),
8599 };
8600 let code = encoder.encode(&op).unwrap();
8601 assert_eq!(
8602 code.len(),
8603 2,
8604 "Thumb-2 STRH with small aligned offset should be 16-bit"
8605 );
8606 }
8607
8608 #[test]
8609 fn test_encode_ldrsb_thumb2() {
8610 let encoder = ArmEncoder::new_thumb2();
8611 let op = ArmOp::Ldrsb {
8612 rd: Reg::R0,
8613 addr: MemAddr::imm(Reg::R1, 0),
8614 };
8615 let code = encoder.encode(&op).unwrap();
8616 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8618 }
8619
8620 #[test]
8621 fn test_encode_ldrsh_thumb2() {
8622 let encoder = ArmEncoder::new_thumb2();
8623 let op = ArmOp::Ldrsh {
8624 rd: Reg::R0,
8625 addr: MemAddr::imm(Reg::R1, 0),
8626 };
8627 let code = encoder.encode(&op).unwrap();
8628 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8629 }
8630
8631 #[test]
8632 fn test_encode_memory_size_thumb2() {
8633 let encoder = ArmEncoder::new_thumb2();
8634 let op = ArmOp::MemorySize { rd: Reg::R0 };
8635 let code = encoder.encode(&op).unwrap();
8636 assert!(!code.is_empty(), "MemorySize should produce code");
8638 }
8639
8640 #[test]
8641 fn test_encode_memory_grow_thumb2() {
8642 let encoder = ArmEncoder::new_thumb2();
8643 let op = ArmOp::MemoryGrow {
8644 rd: Reg::R0,
8645 rn: Reg::R0,
8646 };
8647 let code = encoder.encode(&op).unwrap();
8648 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8649 }
8650
8651 #[test]
8652 fn test_encode_subword_reg_offset_thumb2() {
8653 let encoder = ArmEncoder::new_thumb2();
8654
8655 let op = ArmOp::Ldrb {
8657 rd: Reg::R0,
8658 addr: MemAddr::reg(Reg::R1, Reg::R2),
8659 };
8660 let code = encoder.encode(&op).unwrap();
8661 assert_eq!(
8662 code.len(),
8663 4,
8664 "Thumb-2 LDRB with reg offset should be 32-bit"
8665 );
8666
8667 let op = ArmOp::Strb {
8669 rd: Reg::R0,
8670 addr: MemAddr::reg(Reg::R1, Reg::R2),
8671 };
8672 let code = encoder.encode(&op).unwrap();
8673 assert_eq!(
8674 code.len(),
8675 4,
8676 "Thumb-2 STRB with reg offset should be 32-bit"
8677 );
8678
8679 let op = ArmOp::Ldrh {
8681 rd: Reg::R0,
8682 addr: MemAddr::reg(Reg::R1, Reg::R2),
8683 };
8684 let code = encoder.encode(&op).unwrap();
8685 assert_eq!(
8686 code.len(),
8687 4,
8688 "Thumb-2 LDRH with reg offset should be 32-bit"
8689 );
8690
8691 let op = ArmOp::Strh {
8693 rd: Reg::R0,
8694 addr: MemAddr::reg(Reg::R1, Reg::R2),
8695 };
8696 let code = encoder.encode(&op).unwrap();
8697 assert_eq!(
8698 code.len(),
8699 4,
8700 "Thumb-2 STRH with reg offset should be 32-bit"
8701 );
8702 }
8703
8704 #[test]
8705 fn test_encode_subword_reg_imm_offset_thumb2() {
8706 let encoder = ArmEncoder::new_thumb2();
8707
8708 let op = ArmOp::Ldrb {
8710 rd: Reg::R0,
8711 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8712 };
8713 let code = encoder.encode(&op).unwrap();
8714 assert_eq!(
8716 code.len(),
8717 8,
8718 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8719 );
8720 }
8721
8722 #[test]
8727 fn test_encode_mve_addi32_thumb2() {
8728 let encoder = ArmEncoder::new_thumb2();
8729 let op = ArmOp::MveAddI {
8730 qd: QReg::Q0,
8731 qn: QReg::Q1,
8732 qm: QReg::Q2,
8733 size: MveSize::S32,
8734 };
8735 let code = encoder.encode(&op).unwrap();
8736 assert_eq!(
8737 code.len(),
8738 4,
8739 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8740 );
8741 }
8742
8743 #[test]
8744 fn test_encode_mve_subi16_thumb2() {
8745 let encoder = ArmEncoder::new_thumb2();
8746 let op = ArmOp::MveSubI {
8747 qd: QReg::Q0,
8748 qn: QReg::Q1,
8749 qm: QReg::Q2,
8750 size: MveSize::S16,
8751 };
8752 let code = encoder.encode(&op).unwrap();
8753 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8754 }
8755
8756 #[test]
8757 fn test_encode_mve_muli8_thumb2() {
8758 let encoder = ArmEncoder::new_thumb2();
8759 let op = ArmOp::MveMulI {
8760 qd: QReg::Q0,
8761 qn: QReg::Q1,
8762 qm: QReg::Q2,
8763 size: MveSize::S8,
8764 };
8765 let code = encoder.encode(&op).unwrap();
8766 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8767 }
8768
8769 #[test]
8770 fn test_encode_mve_bitwise_thumb2() {
8771 let encoder = ArmEncoder::new_thumb2();
8772
8773 let ops = vec![
8774 ArmOp::MveAnd {
8775 qd: QReg::Q0,
8776 qn: QReg::Q1,
8777 qm: QReg::Q2,
8778 },
8779 ArmOp::MveOrr {
8780 qd: QReg::Q0,
8781 qn: QReg::Q1,
8782 qm: QReg::Q2,
8783 },
8784 ArmOp::MveEor {
8785 qd: QReg::Q0,
8786 qn: QReg::Q1,
8787 qm: QReg::Q2,
8788 },
8789 ArmOp::MveBic {
8790 qd: QReg::Q0,
8791 qn: QReg::Q1,
8792 qm: QReg::Q2,
8793 },
8794 ];
8795 for op in ops {
8796 let code = encoder.encode(&op).unwrap();
8797 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8798 }
8799 }
8800
8801 #[test]
8802 fn test_encode_mve_mvn_thumb2() {
8803 let encoder = ArmEncoder::new_thumb2();
8804 let op = ArmOp::MveMvn {
8805 qd: QReg::Q0,
8806 qm: QReg::Q1,
8807 };
8808 let code = encoder.encode(&op).unwrap();
8809 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8810 }
8811
8812 #[test]
8813 fn test_encode_mve_load_store_thumb2() {
8814 let encoder = ArmEncoder::new_thumb2();
8815
8816 let load = ArmOp::MveLoad {
8817 qd: QReg::Q0,
8818 addr: MemAddr::imm(Reg::R0, 16),
8819 };
8820 let code = encoder.encode(&load).unwrap();
8821 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8822
8823 let store = ArmOp::MveStore {
8824 qd: QReg::Q1,
8825 addr: MemAddr::imm(Reg::R1, 0),
8826 };
8827 let code = encoder.encode(&store).unwrap();
8828 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8829 }
8830
8831 #[test]
8832 fn test_encode_mve_const_thumb2() {
8833 let encoder = ArmEncoder::new_thumb2();
8834 let op = ArmOp::MveConst {
8835 qd: QReg::Q0,
8836 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8837 };
8838 let code = encoder.encode(&op).unwrap();
8839 assert!(
8842 code.len() >= 24,
8843 "MVE const should produce multiple instructions"
8844 );
8845 }
8846
8847 #[test]
8848 fn test_encode_mve_dup_thumb2() {
8849 let encoder = ArmEncoder::new_thumb2();
8850 let op = ArmOp::MveDup {
8851 qd: QReg::Q0,
8852 rn: Reg::R0,
8853 size: MveSize::S32,
8854 };
8855 let code = encoder.encode(&op).unwrap();
8856 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8857 }
8858
8859 #[test]
8860 fn test_encode_mve_extract_lane_thumb2() {
8861 let encoder = ArmEncoder::new_thumb2();
8862 let op = ArmOp::MveExtractLane {
8863 rd: Reg::R0,
8864 qn: QReg::Q1,
8865 lane: 2,
8866 size: MveSize::S32,
8867 };
8868 let code = encoder.encode(&op).unwrap();
8869 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8870 }
8871
8872 #[test]
8873 fn test_encode_mve_insert_lane_thumb2() {
8874 let encoder = ArmEncoder::new_thumb2();
8875 let op = ArmOp::MveInsertLane {
8876 qd: QReg::Q0,
8877 rn: Reg::R1,
8878 lane: 3,
8879 size: MveSize::S32,
8880 };
8881 let code = encoder.encode(&op).unwrap();
8882 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8883 }
8884
8885 #[test]
8886 fn test_encode_mve_addf32_thumb2() {
8887 let encoder = ArmEncoder::new_thumb2();
8888 let op = ArmOp::MveAddF32 {
8889 qd: QReg::Q0,
8890 qn: QReg::Q1,
8891 qm: QReg::Q2,
8892 };
8893 let code = encoder.encode(&op).unwrap();
8894 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8895 }
8896
8897 #[test]
8898 fn test_encode_mve_divf32_thumb2() {
8899 let encoder = ArmEncoder::new_thumb2();
8900 let op = ArmOp::MveDivF32 {
8901 qd: QReg::Q0,
8902 qn: QReg::Q1,
8903 qm: QReg::Q2,
8904 };
8905 let code = encoder.encode(&op).unwrap();
8906 assert_eq!(
8908 code.len(),
8909 16,
8910 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8911 );
8912 }
8913
8914 #[test]
8915 fn test_encode_mve_sqrtf32_thumb2() {
8916 let encoder = ArmEncoder::new_thumb2();
8917 let op = ArmOp::MveSqrtF32 {
8918 qd: QReg::Q0,
8919 qm: QReg::Q1,
8920 };
8921 let code = encoder.encode(&op).unwrap();
8922 assert_eq!(
8924 code.len(),
8925 16,
8926 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8927 );
8928 }
8929
8930 #[test]
8931 fn test_encode_mve_negf32_thumb2() {
8932 let encoder = ArmEncoder::new_thumb2();
8933 let op = ArmOp::MveNegF32 {
8934 qd: QReg::Q0,
8935 qm: QReg::Q1,
8936 };
8937 let code = encoder.encode(&op).unwrap();
8938 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8939 }
8940
8941 #[test]
8942 fn test_encode_mve_absf32_thumb2() {
8943 let encoder = ArmEncoder::new_thumb2();
8944 let op = ArmOp::MveAbsF32 {
8945 qd: QReg::Q0,
8946 qm: QReg::Q1,
8947 };
8948 let code = encoder.encode(&op).unwrap();
8949 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8950 }
8951
8952 #[test]
8953 fn test_encode_mve_different_qregs() {
8954 let encoder = ArmEncoder::new_thumb2();
8955
8956 let op1 = ArmOp::MveAddI {
8958 qd: QReg::Q0,
8959 qn: QReg::Q0,
8960 qm: QReg::Q0,
8961 size: MveSize::S32,
8962 };
8963 let op2 = ArmOp::MveAddI {
8964 qd: QReg::Q3,
8965 qn: QReg::Q5,
8966 qm: QReg::Q7,
8967 size: MveSize::S32,
8968 };
8969 let code1 = encoder.encode(&op1).unwrap();
8970 let code2 = encoder.encode(&op2).unwrap();
8971 assert_ne!(
8972 code1, code2,
8973 "Different Q-registers should produce different encodings"
8974 );
8975 }
8976
8977 #[test]
8978 fn test_encode_mve_arm32_nop() {
8979 let encoder = ArmEncoder::new_arm32();
8981 let op = ArmOp::MveAddI {
8982 qd: QReg::Q0,
8983 qn: QReg::Q1,
8984 qm: QReg::Q2,
8985 size: MveSize::S32,
8986 };
8987 let code = encoder.encode(&op).unwrap();
8988 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8989 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8991 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8992 }
8993}