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::Sdiv { rd, rn, rm } => {
206 let rd_bits = reg_to_bits(rd);
207 let rn_bits = reg_to_bits(rn);
208 let rm_bits = reg_to_bits(rm);
209
210 0xE710F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
213 }
214
215 ArmOp::Udiv { 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 0xE730F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
223 }
224
225 ArmOp::Mls { rd, rn, rm, ra } => {
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 let ra_bits = reg_to_bits(ra);
230
231 0xE0600090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
234 }
235
236 ArmOp::And { rd, rn, op2 } => {
237 let rd_bits = reg_to_bits(rd);
238 let rn_bits = reg_to_bits(rn);
239 let (op2_bits, i_flag) = encode_operand2(op2);
240
241 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
243 }
244
245 ArmOp::Orr { rd, rn, op2 } => {
246 let rd_bits = reg_to_bits(rd);
247 let rn_bits = reg_to_bits(rn);
248 let (op2_bits, i_flag) = encode_operand2(op2);
249
250 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
252 }
253
254 ArmOp::Eor { rd, rn, op2 } => {
255 let rd_bits = reg_to_bits(rd);
256 let rn_bits = reg_to_bits(rn);
257 let (op2_bits, i_flag) = encode_operand2(op2);
258
259 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
261 }
262
263 ArmOp::Lsl { rd, rn, shift } => {
265 let rd_bits = reg_to_bits(rd);
266 let rn_bits = reg_to_bits(rn);
267 let shift_bits = *shift & 0x1F;
268
269 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
271 }
272
273 ArmOp::Lsr { rd, rn, shift } => {
274 let rd_bits = reg_to_bits(rd);
275 let rn_bits = reg_to_bits(rn);
276 let shift_bits = *shift & 0x1F;
277
278 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
280 }
281
282 ArmOp::Asr { rd, rn, shift } => {
283 let rd_bits = reg_to_bits(rd);
284 let rn_bits = reg_to_bits(rn);
285 let shift_bits = *shift & 0x1F;
286
287 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
289 }
290
291 ArmOp::Ror { rd, rn, shift } => {
292 let rd_bits = reg_to_bits(rd);
293 let rn_bits = reg_to_bits(rn);
294 let shift_bits = *shift & 0x1F;
295
296 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
298 }
299
300 ArmOp::LslReg { rd, rn, rm } => {
303 let rd_bits = reg_to_bits(rd);
304 let rn_bits = reg_to_bits(rn);
305 let rm_bits = reg_to_bits(rm);
306 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
307 }
308 ArmOp::LsrReg { rd, rn, rm } => {
309 let rd_bits = reg_to_bits(rd);
310 let rn_bits = reg_to_bits(rn);
311 let rm_bits = reg_to_bits(rm);
312 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
313 }
314 ArmOp::AsrReg { rd, rn, rm } => {
315 let rd_bits = reg_to_bits(rd);
316 let rn_bits = reg_to_bits(rn);
317 let rm_bits = reg_to_bits(rm);
318 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
319 }
320 ArmOp::RorReg { rd, rn, rm } => {
321 let rd_bits = reg_to_bits(rd);
322 let rn_bits = reg_to_bits(rn);
323 let rm_bits = reg_to_bits(rm);
324 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
325 }
326
327 ArmOp::Rsb { rd, rn, imm } => {
329 let rd_bits = reg_to_bits(rd);
330 let rn_bits = reg_to_bits(rn);
331 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
334 }
335
336 ArmOp::Clz { rd, rm } => {
338 let rd_bits = reg_to_bits(rd);
339 let rm_bits = reg_to_bits(rm);
340
341 0xE16F0F10 | (rd_bits << 12) | rm_bits
344 }
345
346 ArmOp::Rbit { rd, rm } => {
347 let rd_bits = reg_to_bits(rd);
348 let rm_bits = reg_to_bits(rm);
349
350 0xE6FF0F30 | (rd_bits << 12) | rm_bits
353 }
354
355 ArmOp::Sxtb { rd, rm } => {
356 let rd_bits = reg_to_bits(rd);
357 let rm_bits = reg_to_bits(rm);
358
359 0xE6AF0070 | (rd_bits << 12) | rm_bits
362 }
363
364 ArmOp::Sxth { rd, rm } => {
365 let rd_bits = reg_to_bits(rd);
366 let rm_bits = reg_to_bits(rm);
367
368 0xE6BF0070 | (rd_bits << 12) | rm_bits
371 }
372
373 ArmOp::Mov { rd, op2 } => {
375 let rd_bits = reg_to_bits(rd);
376 let (op2_bits, i_flag) = encode_operand2(op2);
377
378 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
380 }
381
382 ArmOp::Mvn { rd, op2 } => {
383 let rd_bits = reg_to_bits(rd);
384 let (op2_bits, i_flag) = encode_operand2(op2);
385
386 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
388 }
389
390 ArmOp::Movw { rd, imm16 } => {
393 let rd_bits = reg_to_bits(rd);
394 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
395 let imm12 = (*imm16 as u32) & 0xFFF;
396 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
397 }
398
399 ArmOp::Movt { rd, imm16 } => {
402 let rd_bits = reg_to_bits(rd);
403 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
404 let imm12 = (*imm16 as u32) & 0xFFF;
405 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
406 }
407
408 ArmOp::Cmp { rn, op2 } => {
410 let rn_bits = reg_to_bits(rn);
411 let (op2_bits, i_flag) = encode_operand2(op2);
412
413 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
415 }
416
417 ArmOp::Cmn { rn, op2 } => {
419 let rn_bits = reg_to_bits(rn);
420 let (op2_bits, i_flag) = encode_operand2(op2);
421
422 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
424 }
425
426 ArmOp::Ldr { rd, addr } => {
428 let rd_bits = reg_to_bits(rd);
429 let (base_bits, offset_bits) = encode_mem_addr(addr);
430
431 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
434 }
435
436 ArmOp::Str { rd, addr } => {
437 let rd_bits = reg_to_bits(rd);
438 let (base_bits, offset_bits) = encode_mem_addr(addr);
439
440 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
442 }
443
444 ArmOp::Ldrb { rd, addr } => {
446 let rd_bits = reg_to_bits(rd);
447 let (base_bits, offset_bits) = encode_mem_addr(addr);
448 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
450 }
451
452 ArmOp::Ldrsb { rd, addr } => {
453 let rd_bits = reg_to_bits(rd);
454 let (base_bits, offset_bits) = encode_mem_addr(addr);
455 let offset_val = offset_bits & 0xFF;
458 let imm4h = (offset_val >> 4) & 0xF;
459 let imm4l = offset_val & 0xF;
460 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
461 }
462
463 ArmOp::Ldrh { rd, addr } => {
464 let rd_bits = reg_to_bits(rd);
465 let (base_bits, offset_bits) = encode_mem_addr(addr);
466 let offset_val = offset_bits & 0xFF;
468 let imm4h = (offset_val >> 4) & 0xF;
469 let imm4l = offset_val & 0xF;
470 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
471 }
472
473 ArmOp::Ldrsh { rd, addr } => {
474 let rd_bits = reg_to_bits(rd);
475 let (base_bits, offset_bits) = encode_mem_addr(addr);
476 let offset_val = offset_bits & 0xFF;
478 let imm4h = (offset_val >> 4) & 0xF;
479 let imm4l = offset_val & 0xF;
480 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
481 }
482
483 ArmOp::Strb { rd, addr } => {
485 let rd_bits = reg_to_bits(rd);
486 let (base_bits, offset_bits) = encode_mem_addr(addr);
487 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
489 }
490
491 ArmOp::Strh { rd, addr } => {
492 let rd_bits = reg_to_bits(rd);
493 let (base_bits, offset_bits) = encode_mem_addr(addr);
494 let offset_val = offset_bits & 0xFF;
496 let imm4h = (offset_val >> 4) & 0xF;
497 let imm4l = offset_val & 0xF;
498 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
499 }
500
501 ArmOp::MemorySize { rd } => {
503 let rd_bits = reg_to_bits(rd);
504 0xE1A00820 | (rd_bits << 12) | 0x0A }
509
510 ArmOp::MemoryGrow { rd, .. } => {
511 let rd_bits = reg_to_bits(rd);
512 0xE3E00000 | (rd_bits << 12) }
515
516 ArmOp::Label { .. } => {
518 return Ok(Vec::new());
519 }
520
521 ArmOp::B { label: _ } => {
523 0xEA000000
526 }
527
528 ArmOp::Bcc { cond, label: _ } => {
530 use synth_synthesis::Condition;
531 let cond_bits: u32 = match cond {
532 Condition::EQ => 0x0,
533 Condition::NE => 0x1,
534 Condition::HS => 0x2,
535 Condition::LO => 0x3,
536 Condition::HI => 0x8,
537 Condition::LS => 0x9,
538 Condition::GE => 0xA,
539 Condition::LT => 0xB,
540 Condition::GT => 0xC,
541 Condition::LE => 0xD,
542 };
543 (cond_bits << 28) | 0x0A000000
545 }
546
547 ArmOp::Bhs { label: _ } => {
549 0x2A000000 }
552
553 ArmOp::Blo { label: _ } => {
555 0x3A000000 }
558
559 ArmOp::BOffset { offset } => {
563 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
573 0xEA000000 | offset_bits
574 }
575
576 ArmOp::BCondOffset { cond, offset } => {
578 use synth_synthesis::Condition;
579 let cond_bits: u32 = match cond {
580 Condition::EQ => 0x0,
581 Condition::NE => 0x1,
582 Condition::HS => 0x2,
583 Condition::LO => 0x3,
584 Condition::HI => 0x8,
585 Condition::LS => 0x9,
586 Condition::GE => 0xA,
587 Condition::LT => 0xB,
588 Condition::GT => 0xC,
589 Condition::LE => 0xD,
590 };
591 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
595 (cond_bits << 28) | 0x0A000000 | offset_bits
596 }
597
598 ArmOp::Bl { label: _ } => {
599 0xEB000000
601 }
602
603 ArmOp::Bx { rm } => {
604 let rm_bits = reg_to_bits(rm);
605
606 0xE12FFF10 | rm_bits
608 }
609
610 ArmOp::Blx { rm } => {
611 let rm_bits = reg_to_bits(rm);
612
613 0xE12FFF30 | rm_bits
615 }
616
617 ArmOp::Push { regs } => {
618 let mut reg_list: u32 = 0;
620 for r in regs {
621 reg_list |= 1 << reg_to_bits(r);
622 }
623 0xE92D0000 | reg_list
624 }
625
626 ArmOp::Pop { regs } => {
627 let mut reg_list: u32 = 0;
629 for r in regs {
630 reg_list |= 1 << reg_to_bits(r);
631 }
632 0xE8BD0000 | reg_list
633 }
634
635 ArmOp::Nop => {
636 0xE1A00000
638 }
639
640 ArmOp::Udf { imm } => {
641 let imm8 = *imm as u32;
644 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
645 }
646
647 ArmOp::Popcnt { .. } => {
650 0xE1A00000 }
654
655 ArmOp::SetCond { .. } => {
656 0xE1A00000 }
660
661 ArmOp::SelectMove { .. } => {
662 0xE1A00000 }
666
667 ArmOp::Select { .. } => {
668 0xE1A00000 }
672
673 ArmOp::LocalGet { .. } => {
674 0xE1A00000 }
678
679 ArmOp::LocalSet { .. } => {
680 0xE1A00000 }
684
685 ArmOp::LocalTee { .. } => {
686 0xE1A00000 }
690
691 ArmOp::GlobalGet { .. } => {
692 0xE1A00000 }
696
697 ArmOp::GlobalSet { .. } => {
698 0xE1A00000 }
702
703 ArmOp::BrTable { .. } => {
704 0xE1A00000 }
708
709 ArmOp::Call { .. } => {
710 0xE1A00000 }
714
715 ArmOp::CallIndirect { .. } => {
716 0xE1A00000 }
720
721 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)?,
758 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
759 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
760 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
761 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
762 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
763 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
764
765 ArmOp::F32Ceil { sd, sm } => {
768 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
770 ArmOp::F32Floor { sd, sm } => {
771 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
773 ArmOp::F32Trunc { sd, sm } => {
774 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
776 ArmOp::F32Nearest { sd, sm } => {
777 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
779 ArmOp::F32Min { sd, sn, sm } => {
780 return self.encode_arm_f32_minmax(sd, sn, sm, true);
781 }
782 ArmOp::F32Max { sd, sn, sm } => {
783 return self.encode_arm_f32_minmax(sd, sn, sm, false);
784 }
785 ArmOp::F32Copysign { sd, sn, sm } => {
786 return self.encode_arm_f32_copysign(sd, sn, sm);
787 }
788
789 ArmOp::F32Eq { rd, sn, sm } => {
791 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
793 ArmOp::F32Ne { rd, sn, sm } => {
794 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
796 ArmOp::F32Lt { rd, sn, sm } => {
797 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
799 ArmOp::F32Le { rd, sn, sm } => {
800 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
802 ArmOp::F32Gt { rd, sn, sm } => {
803 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
805 ArmOp::F32Ge { rd, sn, sm } => {
806 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
808
809 ArmOp::F32Const { sd, value } => {
811 return self.encode_arm_f32_const(sd, *value);
812 }
813
814 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
815 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
816
817 ArmOp::F32ConvertI32S { sd, rm } => {
819 return self.encode_arm_f32_convert_i32(sd, rm, true);
820 }
821 ArmOp::F32ConvertI32U { sd, rm } => {
822 return self.encode_arm_f32_convert_i32(sd, rm, false);
823 }
824 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
825 return Err(synth_core::Error::synthesis(
826 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
827 ));
828 }
829 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
830 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
831 ArmOp::I32TruncF32S { rd, sm } => {
832 return self.encode_arm_i32_trunc_f32(rd, sm, true);
833 }
834 ArmOp::I32TruncF32U { rd, sm } => {
835 return self.encode_arm_i32_trunc_f32(rd, sm, false);
836 }
837
838 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
841 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
842 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
843 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
844 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
845 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
846 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
847
848 ArmOp::F64Ceil { dd, dm } => {
851 return self.encode_arm_f64_rounding(dd, dm, 0b01);
852 }
853 ArmOp::F64Floor { dd, dm } => {
854 return self.encode_arm_f64_rounding(dd, dm, 0b10);
855 }
856 ArmOp::F64Trunc { dd, dm } => {
857 return self.encode_arm_f64_rounding(dd, dm, 0b11);
858 }
859 ArmOp::F64Nearest { dd, dm } => {
860 return self.encode_arm_f64_rounding(dd, dm, 0b00);
861 }
862 ArmOp::F64Min { dd, dn, dm } => {
863 return self.encode_arm_f64_minmax(dd, dn, dm, true);
864 }
865 ArmOp::F64Max { dd, dn, dm } => {
866 return self.encode_arm_f64_minmax(dd, dn, dm, false);
867 }
868 ArmOp::F64Copysign { dd, dn, dm } => {
869 return self.encode_arm_f64_copysign(dd, dn, dm);
870 }
871
872 ArmOp::F64Eq { rd, dn, dm } => {
874 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
875 }
876 ArmOp::F64Ne { rd, dn, dm } => {
877 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
878 }
879 ArmOp::F64Lt { rd, dn, dm } => {
880 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
881 }
882 ArmOp::F64Le { rd, dn, dm } => {
883 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
884 }
885 ArmOp::F64Gt { rd, dn, dm } => {
886 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
887 }
888 ArmOp::F64Ge { rd, dn, dm } => {
889 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
890 }
891
892 ArmOp::F64Const { dd, value } => {
893 return self.encode_arm_f64_const(dd, *value);
894 }
895
896 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
897 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
898
899 ArmOp::F64ConvertI32S { dd, rm } => {
900 return self.encode_arm_f64_convert_i32(dd, rm, true);
901 }
902 ArmOp::F64ConvertI32U { dd, rm } => {
903 return self.encode_arm_f64_convert_i32(dd, rm, false);
904 }
905 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
906 return Err(synth_core::Error::synthesis(
907 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
908 ));
909 }
910 ArmOp::F64PromoteF32 { dd, sm } => {
911 return self.encode_arm_f64_promote_f32(dd, sm);
912 }
913 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
914 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
915 }
916 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
917 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
918 }
919 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
920 return Err(synth_core::Error::synthesis(
921 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
922 ));
923 }
924 ArmOp::I32TruncF64S { rd, dm } => {
925 return self.encode_arm_i32_trunc_f64(rd, dm, true);
926 }
927 ArmOp::I32TruncF64U { rd, dm } => {
928 return self.encode_arm_i32_trunc_f64(rd, dm, false);
929 }
930 ArmOp::I64SetCond { .. }
932 | ArmOp::I64SetCondZ { .. }
933 | ArmOp::I64Mul { .. }
934 | ArmOp::I64Shl { .. }
935 | ArmOp::I64ShrS { .. }
936 | ArmOp::I64ShrU { .. }
937 | ArmOp::I64Rotl { .. }
938 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
942 | ArmOp::MveStore { .. }
943 | ArmOp::MveConst { .. }
944 | ArmOp::MveAnd { .. }
945 | ArmOp::MveOrr { .. }
946 | ArmOp::MveEor { .. }
947 | ArmOp::MveMvn { .. }
948 | ArmOp::MveBic { .. }
949 | ArmOp::MveAddI { .. }
950 | ArmOp::MveSubI { .. }
951 | ArmOp::MveMulI { .. }
952 | ArmOp::MveNegI { .. }
953 | ArmOp::MveCmpEqI { .. }
954 | ArmOp::MveCmpNeI { .. }
955 | ArmOp::MveCmpLtS { .. }
956 | ArmOp::MveCmpLtU { .. }
957 | ArmOp::MveCmpGtS { .. }
958 | ArmOp::MveCmpGtU { .. }
959 | ArmOp::MveCmpLeS { .. }
960 | ArmOp::MveCmpLeU { .. }
961 | ArmOp::MveCmpGeS { .. }
962 | ArmOp::MveCmpGeU { .. }
963 | ArmOp::MveDup { .. }
964 | ArmOp::MveExtractLane { .. }
965 | ArmOp::MveInsertLane { .. }
966 | ArmOp::MveAddF32 { .. }
967 | ArmOp::MveSubF32 { .. }
968 | ArmOp::MveMulF32 { .. }
969 | ArmOp::MveNegF32 { .. }
970 | ArmOp::MveAbsF32 { .. }
971 | ArmOp::MveCmpEqF32 { .. }
972 | ArmOp::MveCmpNeF32 { .. }
973 | ArmOp::MveCmpLtF32 { .. }
974 | ArmOp::MveCmpLeF32 { .. }
975 | ArmOp::MveCmpGtF32 { .. }
976 | ArmOp::MveCmpGeF32 { .. }
977 | ArmOp::MveDupF32 { .. }
978 | ArmOp::MveExtractLaneF32 { .. }
979 | ArmOp::MveReplaceLaneF32 { .. }
980 | ArmOp::MveDivF32 { .. }
981 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
983
984 Ok(instr.to_le_bytes().to_vec())
986 }
987
988 fn encode_arm_f32_compare(
992 &self,
993 rd: &Reg,
994 sn: &VfpReg,
995 sm: &VfpReg,
996 cond_code: u32,
997 ) -> Result<Vec<u8>> {
998 let mut bytes = Vec::new();
999
1000 let sn_num = vfp_sreg_to_num(sn)?;
1002 let sm_num = vfp_sreg_to_num(sm)?;
1003 let (vd, d) = encode_sreg(sn_num);
1004 let (vm, m) = encode_sreg(sm_num);
1005 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1006 bytes.extend_from_slice(&vcmp.to_le_bytes());
1007
1008 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1010
1011 let rd_bits = reg_to_bits(rd);
1013 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1014 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1015
1016 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1018 bytes.extend_from_slice(&mov_one.to_le_bytes());
1019
1020 Ok(bytes)
1021 }
1022
1023 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1025 let mut bytes = Vec::new();
1026 let bits = value.to_bits();
1027
1028 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1033 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1034 bytes.extend_from_slice(&movw.to_le_bytes());
1035
1036 let hi16 = (bits >> 16) & 0xFFFF;
1038 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1039 bytes.extend_from_slice(&movt.to_le_bytes());
1040
1041 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1043 bytes.extend_from_slice(&vmov.to_le_bytes());
1044
1045 Ok(bytes)
1046 }
1047
1048 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1050 let mut bytes = Vec::new();
1051
1052 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1054 bytes.extend_from_slice(&vmov.to_le_bytes());
1055
1056 let sd_num = vfp_sreg_to_num(sd)?;
1059 let (vd, d) = encode_sreg(sd_num);
1060 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1062 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1063 bytes.extend_from_slice(&vcvt.to_le_bytes());
1064
1065 Ok(bytes)
1066 }
1067
1068 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1080 let mut bytes = Vec::new();
1081 let sm_num = vfp_sreg_to_num(sm)?;
1082 let sd_num = vfp_sreg_to_num(sd)?;
1083 let (vd_s, d_s) = encode_sreg(sd_num);
1084 let (vm_s, m_s) = encode_sreg(sm_num);
1085
1086 if mode == 0b11 {
1087 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1090 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1091 } else {
1092 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1097 bytes.extend_from_slice(&vmrs.to_le_bytes());
1098
1099 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1102 bytes.extend_from_slice(&bic.to_le_bytes());
1103
1104 if mode != 0 {
1106 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1108 bytes.extend_from_slice(&orr.to_le_bytes());
1109 }
1110
1111 let vmsr = 0xEEE10A10 | (rt << 12);
1113 bytes.extend_from_slice(&vmsr.to_le_bytes());
1114
1115 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1117 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1118
1119 bytes.extend_from_slice(&vmrs.to_le_bytes());
1121 bytes.extend_from_slice(&bic.to_le_bytes());
1122 bytes.extend_from_slice(&vmsr.to_le_bytes());
1123 }
1124
1125 let (vd2, d2) = encode_sreg(sd_num);
1127 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1128 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1129
1130 Ok(bytes)
1131 }
1132
1133 fn encode_arm_f32_minmax(
1135 &self,
1136 sd: &VfpReg,
1137 sn: &VfpReg,
1138 sm: &VfpReg,
1139 is_min: bool,
1140 ) -> Result<Vec<u8>> {
1141 let mut bytes = Vec::new();
1142 let sn_num = vfp_sreg_to_num(sn)?;
1143 let sm_num = vfp_sreg_to_num(sm)?;
1144 let sd_num = vfp_sreg_to_num(sd)?;
1145
1146 let (vd, d) = encode_sreg(sd_num);
1148 let (vn, n) = encode_sreg(sn_num);
1149 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1150 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1151
1152 let (vm, m) = encode_sreg(sm_num);
1154 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1155 bytes.extend_from_slice(&vcmp.to_le_bytes());
1156
1157 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1159
1160 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1163
1164 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1166 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1167
1168 Ok(bytes)
1169 }
1170
1171 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1173 let mut bytes = Vec::new();
1174
1175 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1177 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1178
1179 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1181 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1182
1183 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1187 bytes.extend_from_slice(&and_sign.to_le_bytes());
1188
1189 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1192 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1193
1194 let orr = 0xE1800000u32 | 12;
1197 bytes.extend_from_slice(&orr.to_le_bytes());
1198
1199 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1201 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1202
1203 Ok(bytes)
1204 }
1205
1206 fn encode_arm_f64_compare(
1208 &self,
1209 rd: &Reg,
1210 dn: &VfpReg,
1211 dm: &VfpReg,
1212 cond_code: u32,
1213 ) -> Result<Vec<u8>> {
1214 let mut bytes = Vec::new();
1215
1216 let dn_num = vfp_dreg_to_num(dn)?;
1218 let dm_num = vfp_dreg_to_num(dm)?;
1219 let (vd, d) = encode_dreg(dn_num);
1220 let (vm, m) = encode_dreg(dm_num);
1221 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1222 bytes.extend_from_slice(&vcmp.to_le_bytes());
1223
1224 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1226
1227 let rd_bits = reg_to_bits(rd);
1229 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1230 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1231
1232 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1234 bytes.extend_from_slice(&mov_one.to_le_bytes());
1235
1236 Ok(bytes)
1237 }
1238
1239 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1241 let mut bytes = Vec::new();
1242 let bits = value.to_bits();
1243 let lo32 = bits as u32;
1244 let hi32 = (bits >> 32) as u32;
1245
1246 let lo16 = lo32 & 0xFFFF;
1248 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1249 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1250 let hi16 = (lo32 >> 16) & 0xFFFF;
1251 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1252 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1253
1254 let lo16 = hi32 & 0xFFFF;
1256 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1257 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1258 let hi16 = (hi32 >> 16) & 0xFFFF;
1259 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1260 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1261
1262 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1264 bytes.extend_from_slice(&vmov.to_le_bytes());
1265
1266 Ok(bytes)
1267 }
1268
1269 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1271 let mut bytes = Vec::new();
1272
1273 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1275 bytes.extend_from_slice(&vmov.to_le_bytes());
1276
1277 let dd_num = vfp_dreg_to_num(dd)?;
1280 let (vd, d) = encode_dreg(dd_num);
1281 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1282 let vcvt = base | (d << 22) | (vd << 12);
1284 bytes.extend_from_slice(&vcvt.to_le_bytes());
1285
1286 Ok(bytes)
1287 }
1288
1289 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1291 let dd_num = vfp_dreg_to_num(dd)?;
1292 let sm_num = vfp_sreg_to_num(sm)?;
1293 let (vd, d) = encode_dreg(dd_num);
1294 let (vm, m) = encode_sreg(sm_num);
1295
1296 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1298 Ok(vcvt.to_le_bytes().to_vec())
1299 }
1300
1301 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1303 let mut bytes = Vec::new();
1304 let dm_num = vfp_dreg_to_num(dm)?;
1305 let (vm, m) = encode_dreg(dm_num);
1306
1307 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1310 let vcvt = base | (m << 5) | vm;
1311 bytes.extend_from_slice(&vcvt.to_le_bytes());
1312
1313 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1315 bytes.extend_from_slice(&vmov.to_le_bytes());
1316
1317 Ok(bytes)
1318 }
1319
1320 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1328 let mut bytes = Vec::new();
1329 let dm_num = vfp_dreg_to_num(dm)?;
1330 let dd_num = vfp_dreg_to_num(dd)?;
1331 let (vm, m) = encode_dreg(dm_num);
1332 let (vd, d) = encode_dreg(dd_num);
1333
1334 if mode == 0b11 {
1335 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1337 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1338 } else {
1339 let rt: u32 = 12;
1341
1342 let vmrs = 0xEEF10A10 | (rt << 12);
1344 bytes.extend_from_slice(&vmrs.to_le_bytes());
1345
1346 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1348 bytes.extend_from_slice(&bic.to_le_bytes());
1349
1350 if mode != 0 {
1352 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1353 bytes.extend_from_slice(&orr.to_le_bytes());
1354 }
1355
1356 let vmsr = 0xEEE10A10 | (rt << 12);
1358 bytes.extend_from_slice(&vmsr.to_le_bytes());
1359
1360 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1362 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1363
1364 bytes.extend_from_slice(&vmrs.to_le_bytes());
1366 bytes.extend_from_slice(&bic.to_le_bytes());
1367 bytes.extend_from_slice(&vmsr.to_le_bytes());
1368 }
1369
1370 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1372 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1373
1374 Ok(bytes)
1375 }
1376
1377 fn encode_arm_f64_minmax(
1379 &self,
1380 dd: &VfpReg,
1381 dn: &VfpReg,
1382 dm: &VfpReg,
1383 is_min: bool,
1384 ) -> Result<Vec<u8>> {
1385 let mut bytes = Vec::new();
1386 let dn_num = vfp_dreg_to_num(dn)?;
1387 let dm_num = vfp_dreg_to_num(dm)?;
1388 let dd_num = vfp_dreg_to_num(dd)?;
1389
1390 let (vd, d) = encode_dreg(dd_num);
1392 let (vn, n) = encode_dreg(dn_num);
1393 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1394 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1395
1396 let (vm, m) = encode_dreg(dm_num);
1398 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1399 bytes.extend_from_slice(&vcmp.to_le_bytes());
1400
1401 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1403
1404 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1405 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1406 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1407
1408 Ok(bytes)
1409 }
1410
1411 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1413 let mut bytes = Vec::new();
1414
1415 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1417 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1418
1419 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1422 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1423
1424 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1426 bytes.extend_from_slice(&and_sign.to_le_bytes());
1427
1428 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1430 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1431
1432 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1434 bytes.extend_from_slice(&orr.to_le_bytes());
1435
1436 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1438 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1439
1440 Ok(bytes)
1441 }
1442
1443 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1445 let mut bytes = Vec::new();
1446
1447 let sm_num = vfp_sreg_to_num(sm)?;
1450 let (vd, d) = encode_sreg(sm_num);
1451 let (vm, m) = encode_sreg(sm_num);
1452 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1453 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1454 bytes.extend_from_slice(&vcvt.to_le_bytes());
1455
1456 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1458 bytes.extend_from_slice(&vmov.to_le_bytes());
1459
1460 Ok(bytes)
1461 }
1462
1463 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1465 match op {
1468 ArmOp::Add { rd, rn, op2 } => {
1470 let rd_bits = reg_to_bits(rd) as u16;
1471 let rn_bits = reg_to_bits(rn) as u16;
1472
1473 if let Operand2::Reg(rm) = op2 {
1474 let rm_bits = reg_to_bits(rm) as u16;
1475 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1483 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1485 Ok(instr.to_le_bytes().to_vec())
1486 } else {
1487 self.encode_thumb32_add_reg_raw(
1489 rd_bits as u32,
1490 rn_bits as u32,
1491 rm_bits as u32,
1492 )
1493 }
1494 } else if let Operand2::Imm(imm) = op2 {
1495 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1496 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1498 Ok(instr.to_le_bytes().to_vec())
1499 } else {
1500 self.encode_thumb32_add(rd, rn, *imm as u32)
1502 }
1503 } else {
1504 self.encode_thumb32_add(rd, rn, 0)
1506 }
1507 }
1508
1509 ArmOp::Sub { rd, rn, op2 } => {
1510 let rd_bits = reg_to_bits(rd) as u16;
1511 let rn_bits = reg_to_bits(rn) as u16;
1512
1513 if let Operand2::Reg(rm) = op2 {
1514 let rm_bits = reg_to_bits(rm) as u16;
1515 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1517 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1519 Ok(instr.to_le_bytes().to_vec())
1520 } else {
1521 self.encode_thumb32_sub_reg_raw(
1523 rd_bits as u32,
1524 rn_bits as u32,
1525 rm_bits as u32,
1526 )
1527 }
1528 } else if let Operand2::Imm(imm) = op2 {
1529 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1530 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1532 Ok(instr.to_le_bytes().to_vec())
1533 } else {
1534 self.encode_thumb32_sub(rd, rn, *imm as u32)
1535 }
1536 } else {
1537 self.encode_thumb32_sub(rd, rn, 0)
1538 }
1539 }
1540
1541 ArmOp::Mov { rd, op2 } => {
1542 let rd_bits = reg_to_bits(rd) as u16;
1543
1544 if let Operand2::Imm(imm) = op2 {
1545 if *imm <= 255 && rd_bits < 8 {
1546 let imm_bits = (*imm as u16) & 0xFF;
1548 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1549 Ok(instr.to_le_bytes().to_vec())
1550 } else {
1551 self.encode_thumb32_movw(rd, *imm as u32)
1553 }
1554 } else if let Operand2::Reg(rm) = op2 {
1555 let rm_bits = reg_to_bits(rm) as u16;
1556 let d_bit = (rd_bits >> 3) & 1;
1559 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1560 Ok(instr.to_le_bytes().to_vec())
1561 } else {
1562 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1564 }
1565 }
1566
1567 ArmOp::Push { regs } => {
1568 let mut reg_list: u16 = 0;
1572 let mut need_32bit = false;
1573 for r in regs {
1574 let bit = reg_to_bits(r);
1575 if bit >= 8 && *r != Reg::LR {
1576 need_32bit = true;
1577 }
1578 reg_list |= 1 << bit;
1579 }
1580 if !need_32bit {
1581 let m_bit = if reg_list & (1 << 14) != 0 {
1583 1u16
1584 } else {
1585 0u16
1586 };
1587 let low_regs = reg_list & 0xFF;
1588 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1589 Ok(instr.to_le_bytes().to_vec())
1590 } else {
1591 let hw1: u16 = 0xE92D;
1593 let hw2: u16 = reg_list;
1594 let mut bytes = hw1.to_le_bytes().to_vec();
1595 bytes.extend_from_slice(&hw2.to_le_bytes());
1596 Ok(bytes)
1597 }
1598 }
1599
1600 ArmOp::Pop { regs } => {
1601 let mut reg_list: u16 = 0;
1605 let mut need_32bit = false;
1606 for r in regs {
1607 let bit = reg_to_bits(r);
1608 if bit >= 8 && *r != Reg::PC {
1609 need_32bit = true;
1610 }
1611 reg_list |= 1 << bit;
1612 }
1613 if !need_32bit {
1614 let p_bit = if reg_list & (1 << 15) != 0 {
1616 1u16
1617 } else {
1618 0u16
1619 };
1620 let low_regs = reg_list & 0xFF;
1621 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1622 Ok(instr.to_le_bytes().to_vec())
1623 } else {
1624 let hw1: u16 = 0xE8BD;
1626 let hw2: u16 = reg_list;
1627 let mut bytes = hw1.to_le_bytes().to_vec();
1628 bytes.extend_from_slice(&hw2.to_le_bytes());
1629 Ok(bytes)
1630 }
1631 }
1632
1633 ArmOp::Nop => {
1634 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1636 }
1637
1638 ArmOp::Udf { imm } => {
1639 let instr: u16 = 0xDE00 | (*imm as u16);
1642 let bytes = instr.to_le_bytes().to_vec();
1643 encoding_contracts::verify_thumb16(&bytes);
1644 Ok(bytes)
1645 }
1646
1647 ArmOp::Adds { rd, rn, op2 } => {
1650 let rd_bits = reg_to_bits(rd) as u16;
1651 let rn_bits = reg_to_bits(rn) as u16;
1652
1653 if let Operand2::Reg(rm) = op2 {
1654 let rm_bits = reg_to_bits(rm) as u16;
1655 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1660 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1662 Ok(instr.to_le_bytes().to_vec())
1663 } else {
1664 self.encode_thumb32_adds_reg_raw(
1665 rd_bits as u32,
1666 rn_bits as u32,
1667 rm_bits as u32,
1668 )
1669 }
1670 } else {
1671 self.encode_thumb32_adds(rd, rn, 0)
1673 }
1674 }
1675
1676 ArmOp::Adc { rd, rn, op2 } => {
1679 let rd_bits = reg_to_bits(rd);
1680 let rn_bits = reg_to_bits(rn);
1681
1682 if let Operand2::Reg(rm) = op2 {
1683 let rm_bits = reg_to_bits(rm);
1684 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1686 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1687
1688 let mut bytes = hw1.to_le_bytes().to_vec();
1689 bytes.extend_from_slice(&hw2.to_le_bytes());
1690 Ok(bytes)
1691 } else {
1692 let hw1: u16 = (0xF140 | rn_bits) as u16;
1694 let hw2: u16 = (rd_bits << 8) as u16;
1695 let mut bytes = hw1.to_le_bytes().to_vec();
1696 bytes.extend_from_slice(&hw2.to_le_bytes());
1697 Ok(bytes)
1698 }
1699 }
1700
1701 ArmOp::Subs { rd, rn, op2 } => {
1703 let rd_bits = reg_to_bits(rd) as u16;
1704 let rn_bits = reg_to_bits(rn) as u16;
1705
1706 if let Operand2::Reg(rm) = op2 {
1707 let rm_bits = reg_to_bits(rm) as u16;
1708 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1712 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1714 Ok(instr.to_le_bytes().to_vec())
1715 } else {
1716 self.encode_thumb32_subs_reg_raw(
1717 rd_bits as u32,
1718 rn_bits as u32,
1719 rm_bits as u32,
1720 )
1721 }
1722 } else {
1723 self.encode_thumb32_subs(rd, rn, 0)
1725 }
1726 }
1727
1728 ArmOp::Sbc { rd, rn, op2 } => {
1731 let rd_bits = reg_to_bits(rd);
1732 let rn_bits = reg_to_bits(rn);
1733
1734 if let Operand2::Reg(rm) = op2 {
1735 let rm_bits = reg_to_bits(rm);
1736 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1738 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1739
1740 let mut bytes = hw1.to_le_bytes().to_vec();
1741 bytes.extend_from_slice(&hw2.to_le_bytes());
1742 Ok(bytes)
1743 } else {
1744 let hw1: u16 = (0xF160 | rn_bits) as u16;
1746 let hw2: u16 = (rd_bits << 8) as u16;
1747 let mut bytes = hw1.to_le_bytes().to_vec();
1748 bytes.extend_from_slice(&hw2.to_le_bytes());
1749 Ok(bytes)
1750 }
1751 }
1752
1753 ArmOp::Sdiv { rd, rn, rm } => {
1757 let rd_bits = reg_to_bits(rd);
1758 let rn_bits = reg_to_bits(rn);
1759 let rm_bits = reg_to_bits(rm);
1760 reg_bits_checked(rd_bits)?;
1761 reg_bits_checked(rn_bits)?;
1762 reg_bits_checked(rm_bits)?;
1763
1764 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1768 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1769
1770 let mut bytes = hw1.to_le_bytes().to_vec();
1772 bytes.extend_from_slice(&hw2.to_le_bytes());
1773 encoding_contracts::verify_thumb32(&bytes);
1774 Ok(bytes)
1775 }
1776
1777 ArmOp::Udiv { rd, rn, rm } => {
1779 let rd_bits = reg_to_bits(rd);
1780 let rn_bits = reg_to_bits(rn);
1781 let rm_bits = reg_to_bits(rm);
1782 reg_bits_checked(rd_bits)?;
1783 reg_bits_checked(rn_bits)?;
1784 reg_bits_checked(rm_bits)?;
1785
1786 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1788 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1789
1790 let mut bytes = hw1.to_le_bytes().to_vec();
1791 bytes.extend_from_slice(&hw2.to_le_bytes());
1792 encoding_contracts::verify_thumb32(&bytes);
1793 Ok(bytes)
1794 }
1795
1796 ArmOp::Mul { rd, rn, rm } => {
1798 let rd_bits = reg_to_bits(rd);
1799 let rn_bits = reg_to_bits(rn);
1800 let rm_bits = reg_to_bits(rm);
1801
1802 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1805 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1806
1807 let mut bytes = hw1.to_le_bytes().to_vec();
1808 bytes.extend_from_slice(&hw2.to_le_bytes());
1809 Ok(bytes)
1810 }
1811
1812 ArmOp::Mls { rd, rn, rm, ra } => {
1814 let rd_bits = reg_to_bits(rd);
1815 let rn_bits = reg_to_bits(rn);
1816 let rm_bits = reg_to_bits(rm);
1817 let ra_bits = reg_to_bits(ra);
1818
1819 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1822 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1823
1824 let mut bytes = hw1.to_le_bytes().to_vec();
1825 bytes.extend_from_slice(&hw2.to_le_bytes());
1826 Ok(bytes)
1827 }
1828
1829 ArmOp::And { rd, rn, op2 } => {
1831 if let Operand2::Reg(rm) = op2 {
1832 let rd_bits = reg_to_bits(rd);
1833 let rn_bits = reg_to_bits(rn);
1834 let rm_bits = reg_to_bits(rm);
1835
1836 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1838 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1839
1840 let mut bytes = hw1.to_le_bytes().to_vec();
1841 bytes.extend_from_slice(&hw2.to_le_bytes());
1842 Ok(bytes)
1843 } else if let Operand2::Imm(imm) = op2 {
1844 let rd_bits = reg_to_bits(rd);
1845 let rn_bits = reg_to_bits(rn);
1846 let imm_val = *imm as u32;
1847
1848 let i_bit = (imm_val >> 11) & 1;
1850 let imm3 = (imm_val >> 8) & 0x7;
1851 let imm8 = imm_val & 0xFF;
1852
1853 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1854 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1855
1856 let mut bytes = hw1.to_le_bytes().to_vec();
1857 bytes.extend_from_slice(&hw2.to_le_bytes());
1858 Ok(bytes)
1859 } else {
1860 let instr: u16 = 0xBF00;
1862 Ok(instr.to_le_bytes().to_vec())
1863 }
1864 }
1865
1866 ArmOp::Orr { rd, rn, op2 } => {
1868 if let Operand2::Reg(rm) = op2 {
1869 let rd_bits = reg_to_bits(rd);
1870 let rn_bits = reg_to_bits(rn);
1871 let rm_bits = reg_to_bits(rm);
1872
1873 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1875 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1876
1877 let mut bytes = hw1.to_le_bytes().to_vec();
1878 bytes.extend_from_slice(&hw2.to_le_bytes());
1879 Ok(bytes)
1880 } else {
1881 let instr: u16 = 0xBF00;
1882 Ok(instr.to_le_bytes().to_vec())
1883 }
1884 }
1885
1886 ArmOp::Eor { rd, rn, op2 } => {
1888 if let Operand2::Reg(rm) = op2 {
1889 let rd_bits = reg_to_bits(rd);
1890 let rn_bits = reg_to_bits(rn);
1891 let rm_bits = reg_to_bits(rm);
1892
1893 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1895 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1896
1897 let mut bytes = hw1.to_le_bytes().to_vec();
1898 bytes.extend_from_slice(&hw2.to_le_bytes());
1899 Ok(bytes)
1900 } else {
1901 let instr: u16 = 0xBF00;
1902 Ok(instr.to_le_bytes().to_vec())
1903 }
1904 }
1905
1906 ArmOp::Lsl { rd, rn, shift } => {
1908 let rd_bits = reg_to_bits(rd) as u16;
1909 let rn_bits = reg_to_bits(rn) as u16;
1910 let shift_bits = (*shift as u16) & 0x1F;
1911
1912 if rd_bits < 8 && rn_bits < 8 {
1913 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1915 Ok(instr.to_le_bytes().to_vec())
1916 } else {
1917 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1920 }
1921
1922 ArmOp::Lsr { rd, rn, shift } => {
1923 let rd_bits = reg_to_bits(rd) as u16;
1924 let rn_bits = reg_to_bits(rn) as u16;
1925 let shift_bits = (*shift as u16) & 0x1F;
1926
1927 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1928 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1930 Ok(instr.to_le_bytes().to_vec())
1931 } else {
1932 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
1934 }
1935
1936 ArmOp::Asr { rd, rn, shift } => {
1937 let rd_bits = reg_to_bits(rd) as u16;
1938 let rn_bits = reg_to_bits(rn) as u16;
1939 let shift_bits = (*shift as u16) & 0x1F;
1940
1941 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1942 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1944 Ok(instr.to_le_bytes().to_vec())
1945 } else {
1946 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
1948 }
1949
1950 ArmOp::Ror { rd, rn, shift } => {
1951 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
1954
1955 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
1959 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
1960 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
1961 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
1962
1963 ArmOp::Rsb { rd, rn, imm } => {
1966 let rd_bits = reg_to_bits(rd);
1967 let rn_bits = reg_to_bits(rn);
1968 let imm_val = *imm;
1969
1970 let i_bit = (imm_val >> 11) & 1;
1971 let imm3 = (imm_val >> 8) & 0x7;
1972 let imm8 = imm_val & 0xFF;
1973
1974 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
1976 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1978
1979 let mut bytes = hw1.to_le_bytes().to_vec();
1980 bytes.extend_from_slice(&hw2.to_le_bytes());
1981 Ok(bytes)
1982 }
1983
1984 ArmOp::Clz { rd, rm } => {
1986 let rd_bits = reg_to_bits(rd);
1987 let rm_bits = reg_to_bits(rm);
1988
1989 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
1992 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
1993
1994 let mut bytes = hw1.to_le_bytes().to_vec();
1995 bytes.extend_from_slice(&hw2.to_le_bytes());
1996 Ok(bytes)
1997 }
1998
1999 ArmOp::Rbit { rd, rm } => {
2001 let rd_bits = reg_to_bits(rd);
2002 let rm_bits = reg_to_bits(rm);
2003
2004 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2007 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2008
2009 let mut bytes = hw1.to_le_bytes().to_vec();
2010 bytes.extend_from_slice(&hw2.to_le_bytes());
2011 Ok(bytes)
2012 }
2013
2014 ArmOp::Sxtb { rd, rm } => {
2016 let rd_bits = reg_to_bits(rd) as u16;
2017 let rm_bits = reg_to_bits(rm) as u16;
2018
2019 if rd_bits < 8 && rm_bits < 8 {
2020 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2022 Ok(instr.to_le_bytes().to_vec())
2023 } else {
2024 let rd_bits32 = rd_bits as u32;
2027 let rm_bits32 = rm_bits as u32;
2028 let hw1: u16 = 0xFA4F;
2029 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2030 let mut bytes = hw1.to_le_bytes().to_vec();
2031 bytes.extend_from_slice(&hw2.to_le_bytes());
2032 Ok(bytes)
2033 }
2034 }
2035
2036 ArmOp::Sxth { rd, rm } => {
2038 let rd_bits = reg_to_bits(rd) as u16;
2039 let rm_bits = reg_to_bits(rm) as u16;
2040
2041 if rd_bits < 8 && rm_bits < 8 {
2042 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2044 Ok(instr.to_le_bytes().to_vec())
2045 } else {
2046 let rd_bits32 = rd_bits as u32;
2049 let rm_bits32 = rm_bits as u32;
2050 let hw1: u16 = 0xFA0F;
2051 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
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
2058 ArmOp::Cmp { rn, op2 } => {
2060 let rn_bits = reg_to_bits(rn) as u16;
2061
2062 if let Operand2::Imm(imm) = op2 {
2063 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2066 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2068 Ok(instr.to_le_bytes().to_vec())
2069 } else {
2070 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2071 }
2072 } else if let Operand2::Reg(rm) = op2 {
2073 let rm_bits = reg_to_bits(rm) as u16;
2074 if rn_bits < 8 && rm_bits < 8 {
2075 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2077 Ok(instr.to_le_bytes().to_vec())
2078 } else {
2079 let n_bit = (rn_bits >> 3) & 1;
2081 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2082 Ok(instr.to_le_bytes().to_vec())
2083 }
2084 } else {
2085 let instr: u16 = 0xBF00;
2086 Ok(instr.to_le_bytes().to_vec())
2087 }
2088 }
2089
2090 ArmOp::Cmn { rn, op2 } => {
2093 let rn_bits = reg_to_bits(rn) as u16;
2094
2095 if let Operand2::Imm(imm) = op2 {
2096 if *imm >= 0 && *imm <= 255 {
2099 let imm8 = *imm as u16 & 0xFF;
2100 let hw1: u16 = 0xF110 | rn_bits;
2101 let hw2: u16 = 0x0F00 | imm8;
2102 let mut bytes = hw1.to_le_bytes().to_vec();
2103 bytes.extend_from_slice(&hw2.to_le_bytes());
2104 Ok(bytes)
2105 } else {
2106 Ok(vec![0xBF, 0x00])
2108 }
2109 } else if let Operand2::Reg(rm) = op2 {
2110 let rm_bits = reg_to_bits(rm) as u16;
2111 if rn_bits < 8 && rm_bits < 8 {
2117 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2119 Ok(instr.to_le_bytes().to_vec())
2120 } else {
2121 let hw1: u16 = 0xEB10 | rn_bits;
2122 let hw2: u16 = 0x0F00 | rm_bits;
2123 let mut bytes = hw1.to_le_bytes().to_vec();
2124 bytes.extend_from_slice(&hw2.to_le_bytes());
2125 Ok(bytes)
2126 }
2127 } else {
2128 Ok(vec![0xBF, 0x00])
2129 }
2130 }
2131
2132 ArmOp::Ldr { rd, addr } => {
2134 let rd_bits = reg_to_bits(rd);
2135 let base_bits = reg_to_bits(&addr.base);
2136
2137 if let Some(offset_reg) = &addr.offset_reg {
2139 let rm_bits = reg_to_bits(offset_reg);
2140
2141 if addr.offset != 0 {
2143 let scratch = Reg::R12;
2146 let mut bytes =
2147 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2148 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2149 return Ok(bytes);
2150 }
2151
2152 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2155 let instr: u16 = 0x5800
2157 | ((rm_bits as u16) << 6)
2158 | ((base_bits as u16) << 3)
2159 | (rd_bits as u16);
2160 return Ok(instr.to_le_bytes().to_vec());
2161 }
2162
2163 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2165 }
2166
2167 let offset = addr.offset as u32;
2169
2170 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2171 let imm5 = (offset >> 2) as u16;
2173 let instr: u16 =
2174 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2175 Ok(instr.to_le_bytes().to_vec())
2176 } else {
2177 self.encode_thumb32_ldr(rd, &addr.base, offset)
2178 }
2179 }
2180
2181 ArmOp::Str { rd, addr } => {
2183 let rd_bits = reg_to_bits(rd);
2184 let base_bits = reg_to_bits(&addr.base);
2185
2186 if let Some(offset_reg) = &addr.offset_reg {
2188 let rm_bits = reg_to_bits(offset_reg);
2189
2190 if addr.offset != 0 {
2192 let scratch = Reg::R12;
2195 let mut bytes =
2196 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2197 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2198 return Ok(bytes);
2199 }
2200
2201 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2204 let instr: u16 = 0x5000
2206 | ((rm_bits as u16) << 6)
2207 | ((base_bits as u16) << 3)
2208 | (rd_bits as u16);
2209 return Ok(instr.to_le_bytes().to_vec());
2210 }
2211
2212 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2214 }
2215
2216 let offset = addr.offset as u32;
2218
2219 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2220 let imm5 = (offset >> 2) as u16;
2222 let instr: u16 =
2223 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2224 Ok(instr.to_le_bytes().to_vec())
2225 } else {
2226 self.encode_thumb32_str(rd, &addr.base, offset)
2227 }
2228 }
2229
2230 ArmOp::Ldrb { rd, addr } => {
2232 let rd_bits = reg_to_bits(rd);
2233 let base_bits = reg_to_bits(&addr.base);
2234
2235 if let Some(offset_reg) = &addr.offset_reg {
2236 if addr.offset != 0 {
2237 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_ldrb_reg(rd, &addr.base, &scratch)?);
2241 return Ok(bytes);
2242 }
2243 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2244 }
2245
2246 let offset = addr.offset as u32;
2247 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2248 let instr: u16 = 0x7800
2250 | ((offset as u16) << 6)
2251 | ((base_bits as u16) << 3)
2252 | (rd_bits as u16);
2253 Ok(instr.to_le_bytes().to_vec())
2254 } else {
2255 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2256 }
2257 }
2258
2259 ArmOp::Ldrsb { rd, addr } => {
2261 let rd_bits = reg_to_bits(rd);
2262 let base_bits = reg_to_bits(&addr.base);
2263
2264 if let Some(offset_reg) = &addr.offset_reg {
2265 if addr.offset != 0 {
2266 let scratch = Reg::R12;
2267 let mut bytes =
2268 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2269 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2270 return Ok(bytes);
2271 }
2272 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2273 }
2274
2275 let offset = addr.offset as u32;
2276 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2279 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2281 } else {
2282 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2283 }
2284 }
2285
2286 ArmOp::Ldrh { rd, addr } => {
2288 let rd_bits = reg_to_bits(rd);
2289 let base_bits = reg_to_bits(&addr.base);
2290
2291 if let Some(offset_reg) = &addr.offset_reg {
2292 if addr.offset != 0 {
2293 let scratch = Reg::R12;
2294 let mut bytes =
2295 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2296 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2297 return Ok(bytes);
2298 }
2299 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2300 }
2301
2302 let offset = addr.offset as u32;
2303 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2304 let imm5 = (offset >> 1) as u16;
2306 let instr: u16 =
2307 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2308 Ok(instr.to_le_bytes().to_vec())
2309 } else {
2310 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2311 }
2312 }
2313
2314 ArmOp::Ldrsh { rd, addr } => {
2316 if let Some(offset_reg) = &addr.offset_reg {
2317 if addr.offset != 0 {
2318 let scratch = Reg::R12;
2319 let mut bytes =
2320 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2321 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2322 return Ok(bytes);
2323 }
2324 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2325 }
2326
2327 let offset = addr.offset as u32;
2328 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2329 }
2330
2331 ArmOp::Strb { rd, addr } => {
2333 let rd_bits = reg_to_bits(rd);
2334 let base_bits = reg_to_bits(&addr.base);
2335
2336 if let Some(offset_reg) = &addr.offset_reg {
2337 if addr.offset != 0 {
2338 let scratch = Reg::R12;
2339 let mut bytes =
2340 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2341 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2342 return Ok(bytes);
2343 }
2344 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2345 }
2346
2347 let offset = addr.offset as u32;
2348 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2349 let instr: u16 = 0x7000
2351 | ((offset as u16) << 6)
2352 | ((base_bits as u16) << 3)
2353 | (rd_bits as u16);
2354 Ok(instr.to_le_bytes().to_vec())
2355 } else {
2356 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2357 }
2358 }
2359
2360 ArmOp::Strh { rd, addr } => {
2362 let rd_bits = reg_to_bits(rd);
2363 let base_bits = reg_to_bits(&addr.base);
2364
2365 if let Some(offset_reg) = &addr.offset_reg {
2366 if addr.offset != 0 {
2367 let scratch = Reg::R12;
2368 let mut bytes =
2369 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2370 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2371 return Ok(bytes);
2372 }
2373 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2374 }
2375
2376 let offset = addr.offset as u32;
2377 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2378 let imm5 = (offset >> 1) as u16;
2380 let instr: u16 =
2381 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2382 Ok(instr.to_le_bytes().to_vec())
2383 } else {
2384 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2385 }
2386 }
2387
2388 ArmOp::MemorySize { rd } => {
2390 let rd_bits = reg_to_bits(rd);
2393 let r10_bits = reg_to_bits(&Reg::R10);
2394 if rd_bits < 8 && r10_bits < 8 {
2395 let instr: u16 =
2396 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2397 Ok(instr.to_le_bytes().to_vec())
2398 } else {
2399 let imm5: u32 = 16;
2401 let imm3 = (imm5 >> 2) & 0x7;
2402 let imm2 = imm5 & 0x3;
2403 let hw1: u16 = 0xEA4F;
2404 let hw2: u16 =
2405 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2406 let mut bytes = hw1.to_le_bytes().to_vec();
2407 bytes.extend_from_slice(&hw2.to_le_bytes());
2408 Ok(bytes)
2409 }
2410 }
2411
2412 ArmOp::MemoryGrow { rd, .. } => {
2414 let rd_bits = reg_to_bits(rd);
2418 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2421 bytes.extend_from_slice(&hw2.to_le_bytes());
2422 Ok(bytes)
2423 }
2424
2425 ArmOp::Bx { rm } => {
2427 let rm_bits = reg_to_bits(rm) as u16;
2428 let instr: u16 = 0x4700 | (rm_bits << 3);
2430 Ok(instr.to_le_bytes().to_vec())
2431 }
2432
2433 ArmOp::Blx { rm } => {
2436 let rm_bits = reg_to_bits(rm) as u16;
2437 let instr: u16 = 0x4780 | (rm_bits << 3);
2438 Ok(instr.to_le_bytes().to_vec())
2439 }
2440
2441 ArmOp::CallIndirect {
2445 rd: _,
2446 type_idx: _,
2447 table_index_reg,
2448 } => {
2449 let idx_reg = reg_to_bits(table_index_reg);
2450 let mut bytes = Vec::new();
2451
2452 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2468 bytes.extend_from_slice(&hw1.to_le_bytes());
2469 bytes.extend_from_slice(&hw2.to_le_bytes());
2470
2471 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2477 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2478
2479 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2483
2484 Ok(bytes)
2485 }
2486
2487 ArmOp::Label { .. } => Ok(Vec::new()),
2489
2490 ArmOp::Bcc { cond, label: _ } => {
2492 use synth_synthesis::Condition;
2493 let cond_bits: u16 = match cond {
2494 Condition::EQ => 0x0,
2495 Condition::NE => 0x1,
2496 Condition::HS => 0x2,
2497 Condition::LO => 0x3,
2498 Condition::HI => 0x8,
2499 Condition::LS => 0x9,
2500 Condition::GE => 0xA,
2501 Condition::LT => 0xB,
2502 Condition::GT => 0xC,
2503 Condition::LE => 0xD,
2504 };
2505 let instr: u16 = 0xD000 | (cond_bits << 8);
2507 Ok(instr.to_le_bytes().to_vec())
2508 }
2509
2510 ArmOp::B { label: _ } => {
2512 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2516 }
2517
2518 ArmOp::Bhs { label: _ } => {
2521 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2525 }
2526
2527 ArmOp::Blo { label: _ } => {
2530 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2534 }
2535
2536 ArmOp::BOffset { offset } => {
2539 let halfword_offset = *offset;
2542
2543 if (-1024..=1022).contains(&halfword_offset) {
2546 let imm11 = (halfword_offset as u16) & 0x7FF;
2548 let instr: u16 = 0xE000 | imm11;
2549 Ok(instr.to_le_bytes().to_vec())
2550 } else {
2551 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2567 let uoffset = signed_offset as u32;
2568 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;
2576 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2577
2578 let mut bytes = hw1.to_le_bytes().to_vec();
2579 bytes.extend_from_slice(&hw2.to_le_bytes());
2580 Ok(bytes)
2581 }
2582 }
2583
2584 ArmOp::BCondOffset { cond, offset } => {
2586 use synth_synthesis::Condition;
2587 let cond_bits: u16 = match cond {
2588 Condition::EQ => 0x0,
2589 Condition::NE => 0x1,
2590 Condition::HS => 0x2,
2591 Condition::LO => 0x3,
2592 Condition::HI => 0x8,
2593 Condition::LS => 0x9,
2594 Condition::GE => 0xA,
2595 Condition::LT => 0xB,
2596 Condition::GT => 0xC,
2597 Condition::LE => 0xD,
2598 };
2599
2600 let halfword_offset = *offset;
2603
2604 if (-128..=127).contains(&halfword_offset) {
2607 let imm8 = (halfword_offset as u16) & 0xFF;
2608 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2609 Ok(instr.to_le_bytes().to_vec())
2610 } else {
2611 let offset = halfword_offset >> 1;
2615 let s = if offset < 0 { 1u32 } else { 0u32 };
2616 let imm6 = ((offset >> 11) as u32) & 0x3F;
2617 let imm11 = (offset as u32) & 0x7FF;
2618 let j1 = if s == 1 { 1 } else { 0 };
2619 let j2 = if s == 1 { 1 } else { 0 };
2620
2621 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2622 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2623
2624 let mut bytes = hw1.to_le_bytes().to_vec();
2625 bytes.extend_from_slice(&hw2.to_le_bytes());
2626 Ok(bytes)
2627 }
2628 }
2629
2630 ArmOp::Bl { label: _ } => {
2631 let hw1: u16 = 0xF7FF;
2646 let hw2: u16 = 0xFFFE;
2647 let mut bytes = hw1.to_le_bytes().to_vec();
2648 bytes.extend_from_slice(&hw2.to_le_bytes());
2649 Ok(bytes)
2650 }
2651
2652 ArmOp::Mvn { rd, op2 } => {
2654 if let Operand2::Reg(rm) = op2 {
2655 let rd_bits = reg_to_bits(rd) as u16;
2656 let rm_bits = reg_to_bits(rm) as u16;
2657
2658 if rd_bits < 8 && rm_bits < 8 {
2659 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2661 Ok(instr.to_le_bytes().to_vec())
2662 } else {
2663 let hw1: u16 = 0xEA6F_u16;
2665 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2666 let mut bytes = hw1.to_le_bytes().to_vec();
2667 bytes.extend_from_slice(&hw2.to_le_bytes());
2668 Ok(bytes)
2669 }
2670 } else {
2671 let instr: u16 = 0xBF00;
2672 Ok(instr.to_le_bytes().to_vec())
2673 }
2674 }
2675
2676 ArmOp::Movw { rd, imm16 } => {
2678 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2679 }
2680
2681 ArmOp::Movt { rd, imm16 } => {
2683 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2684 }
2685
2686 ArmOp::SetCond { rd, cond } => {
2692 let rd_bits = reg_to_bits(rd) as u16;
2693
2694 use synth_synthesis::Condition;
2696 let cond_bits: u16 = match cond {
2697 Condition::EQ => 0x0,
2698 Condition::NE => 0x1,
2699 Condition::LT => 0xB,
2700 Condition::LE => 0xD,
2701 Condition::GT => 0xC,
2702 Condition::GE => 0xA,
2703 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2708
2709 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2714 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2715
2716 let mut bytes = ite_instr.to_le_bytes().to_vec();
2727 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2728 if rd_bits <= 7 {
2729 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2731 } else {
2732 let hw1: u16 = 0xF04F;
2734 let hw2: u16 = (rd_bits << 8) | imm;
2735 bytes.extend_from_slice(&hw1.to_le_bytes());
2736 bytes.extend_from_slice(&hw2.to_le_bytes());
2737 }
2738 };
2739 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2742 }
2743
2744 ArmOp::I64SetCond {
2749 rd,
2750 rn_lo,
2751 rn_hi,
2752 rm_lo,
2753 rm_hi,
2754 cond,
2755 } => {
2756 use synth_synthesis::Condition;
2757 let rd_bits = reg_to_bits(rd) as u16;
2758 let mut bytes = Vec::new();
2759
2760 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2762 rm: &synth_synthesis::Reg|
2763 -> Vec<u8> {
2764 let rn_bits = reg_to_bits(rn) as u16;
2765 let rm_bits = reg_to_bits(rm) as u16;
2766 if rn_bits < 8 && rm_bits < 8 {
2767 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2768 instr.to_le_bytes().to_vec()
2769 } else {
2770 let n_bit = (rn_bits >> 3) & 1;
2771 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2772 instr.to_le_bytes().to_vec()
2773 }
2774 };
2775
2776 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2778 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2779 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2780 ite_instr.to_le_bytes().to_vec()
2781 };
2782
2783 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2785 let mut b = encode_ite(cond_bits);
2786 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2787 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2788 b.extend_from_slice(&mov_one.to_le_bytes());
2789 b.extend_from_slice(&mov_zero.to_le_bytes());
2790 b
2791 };
2792
2793 match cond {
2794 Condition::EQ | Condition::NE => {
2795 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2797
2798 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2801
2802 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2804
2805 let cond_bits: u16 = match cond {
2807 Condition::EQ => 0x0,
2808 Condition::NE => 0x1,
2809 _ => unreachable!(),
2810 };
2811 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2812 }
2813
2814 Condition::LT => {
2815 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2817
2818 let rn_hi_bits = reg_to_bits(rn_hi);
2821 let rm_hi_bits = reg_to_bits(rm_hi);
2822 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2823 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2824 bytes.extend_from_slice(&hw1.to_le_bytes());
2825 bytes.extend_from_slice(&hw2.to_le_bytes());
2826
2827 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2830
2831 Condition::GT => {
2832 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2835
2836 let rm_hi_bits = reg_to_bits(rm_hi);
2838 let rn_hi_bits = reg_to_bits(rn_hi);
2839 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2840 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2841 bytes.extend_from_slice(&hw1.to_le_bytes());
2842 bytes.extend_from_slice(&hw2.to_le_bytes());
2843
2844 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2847
2848 Condition::LE => {
2849 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2853
2854 let rm_hi_bits = reg_to_bits(rm_hi);
2856 let rn_hi_bits = reg_to_bits(rn_hi);
2857 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2858 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2859 bytes.extend_from_slice(&hw1.to_le_bytes());
2860 bytes.extend_from_slice(&hw2.to_le_bytes());
2861
2862 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2865
2866 Condition::GE => {
2867 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2870
2871 let rn_hi_bits = reg_to_bits(rn_hi);
2873 let rm_hi_bits = reg_to_bits(rm_hi);
2874 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2875 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2876 bytes.extend_from_slice(&hw1.to_le_bytes());
2877 bytes.extend_from_slice(&hw2.to_le_bytes());
2878
2879 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2882
2883 Condition::LO => {
2885 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2887 let rn_hi_bits = reg_to_bits(rn_hi);
2888 let rm_hi_bits = reg_to_bits(rm_hi);
2889 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2890 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2891 bytes.extend_from_slice(&hw1.to_le_bytes());
2892 bytes.extend_from_slice(&hw2.to_le_bytes());
2893 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2895
2896 Condition::HI => {
2897 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2899 let rm_hi_bits = reg_to_bits(rm_hi);
2900 let rn_hi_bits = reg_to_bits(rn_hi);
2901 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2902 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2903 bytes.extend_from_slice(&hw1.to_le_bytes());
2904 bytes.extend_from_slice(&hw2.to_le_bytes());
2905 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2907
2908 Condition::LS => {
2909 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2911 let rm_hi_bits = reg_to_bits(rm_hi);
2912 let rn_hi_bits = reg_to_bits(rn_hi);
2913 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2914 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2915 bytes.extend_from_slice(&hw1.to_le_bytes());
2916 bytes.extend_from_slice(&hw2.to_le_bytes());
2917 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2919
2920 Condition::HS => {
2921 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2923 let rn_hi_bits = reg_to_bits(rn_hi);
2924 let rm_hi_bits = reg_to_bits(rm_hi);
2925 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2926 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2927 bytes.extend_from_slice(&hw1.to_le_bytes());
2928 bytes.extend_from_slice(&hw2.to_le_bytes());
2929 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2931 }
2932
2933 Ok(bytes)
2934 }
2935
2936 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2939 let rd_bits = reg_to_bits(rd);
2940 let rn_lo_bits = reg_to_bits(rn_lo);
2941 let rn_hi_bits = reg_to_bits(rn_hi);
2942 let mut bytes = Vec::new();
2943
2944 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2946 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2947 bytes.extend_from_slice(&hw1.to_le_bytes());
2948 bytes.extend_from_slice(&hw2.to_le_bytes());
2949
2950 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2952 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2953
2954 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2957 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2958 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2959 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2960 bytes.extend_from_slice(&mov_one.to_le_bytes());
2961 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2962
2963 Ok(bytes)
2964 }
2965
2966 ArmOp::I64Mul {
2970 rd_lo,
2971 rd_hi,
2972 rn_lo,
2973 rn_hi,
2974 rm_lo,
2975 rm_hi,
2976 } => {
2977 let rd_lo_bits = reg_to_bits(rd_lo);
2978 let rd_hi_bits = reg_to_bits(rd_hi);
2979 let rn_lo_bits = reg_to_bits(rn_lo);
2980 let rn_hi_bits = reg_to_bits(rn_hi);
2981 let rm_lo_bits = reg_to_bits(rm_lo);
2982 let rm_hi_bits = reg_to_bits(rm_hi);
2983 let r12: u32 = 12; let mut bytes = Vec::new();
2985
2986 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2989 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2990 bytes.extend_from_slice(&hw1.to_le_bytes());
2991 bytes.extend_from_slice(&hw2.to_le_bytes());
2992
2993 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2996 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
2997 bytes.extend_from_slice(&hw1.to_le_bytes());
2998 bytes.extend_from_slice(&hw2.to_le_bytes());
2999
3000 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3003 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3004 bytes.extend_from_slice(&hw1.to_le_bytes());
3005 bytes.extend_from_slice(&hw2.to_le_bytes());
3006
3007 let d_bit = (rd_hi_bits >> 3) & 1;
3010 let add_instr: u16 =
3011 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3012 bytes.extend_from_slice(&add_instr.to_le_bytes());
3013
3014 Ok(bytes)
3015 }
3016
3017 ArmOp::I64Shl {
3020 rd_lo,
3021 rd_hi,
3022 rn_lo,
3023 rn_hi,
3024 rm_lo,
3025 rm_hi,
3026 } => {
3027 let rd_lo_bits = reg_to_bits(rd_lo);
3028 let rd_hi_bits = reg_to_bits(rd_hi);
3029 let rn_lo_bits = reg_to_bits(rn_lo);
3030 let rn_hi_bits = reg_to_bits(rn_hi);
3031 let rm_lo_bits = reg_to_bits(rm_lo);
3032 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3034
3035 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3037 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3038 bytes.extend_from_slice(&hw1.to_le_bytes());
3039 bytes.extend_from_slice(&hw2.to_le_bytes());
3040
3041 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3043 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3044 bytes.extend_from_slice(&hw1.to_le_bytes());
3045 bytes.extend_from_slice(&hw2.to_le_bytes());
3046
3047 let bpl: u16 = 0xD50A;
3049 bytes.extend_from_slice(&bpl.to_le_bytes());
3050
3051 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3054 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3055 bytes.extend_from_slice(&hw1.to_le_bytes());
3056 bytes.extend_from_slice(&hw2.to_le_bytes());
3057
3058 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3060 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3061 bytes.extend_from_slice(&hw1.to_le_bytes());
3062 bytes.extend_from_slice(&hw2.to_le_bytes());
3063
3064 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3066 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3067 bytes.extend_from_slice(&hw1.to_le_bytes());
3068 bytes.extend_from_slice(&hw2.to_le_bytes());
3069
3070 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3072 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3073 bytes.extend_from_slice(&hw1.to_le_bytes());
3074 bytes.extend_from_slice(&hw2.to_le_bytes());
3075
3076 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3078 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3079 bytes.extend_from_slice(&hw1.to_le_bytes());
3080 bytes.extend_from_slice(&hw2.to_le_bytes());
3081
3082 let b_done: u16 = 0xE002;
3084 bytes.extend_from_slice(&b_done.to_le_bytes());
3085
3086 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3089 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3090 bytes.extend_from_slice(&hw1.to_le_bytes());
3091 bytes.extend_from_slice(&hw2.to_le_bytes());
3092
3093 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3095 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3096
3097 Ok(bytes) }
3099
3100 ArmOp::I64ShrU {
3102 rd_lo,
3103 rd_hi,
3104 rn_lo,
3105 rn_hi,
3106 rm_lo,
3107 rm_hi,
3108 } => {
3109 let rd_lo_bits = reg_to_bits(rd_lo);
3110 let rd_hi_bits = reg_to_bits(rd_hi);
3111 let rn_lo_bits = reg_to_bits(rn_lo);
3112 let rn_hi_bits = reg_to_bits(rn_hi);
3113 let rm_lo_bits = reg_to_bits(rm_lo);
3114 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3116
3117 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3119 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3120 bytes.extend_from_slice(&hw1.to_le_bytes());
3121 bytes.extend_from_slice(&hw2.to_le_bytes());
3122
3123 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3125 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3126 bytes.extend_from_slice(&hw1.to_le_bytes());
3127 bytes.extend_from_slice(&hw2.to_le_bytes());
3128
3129 let bpl: u16 = 0xD50A;
3131 bytes.extend_from_slice(&bpl.to_le_bytes());
3132
3133 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3136 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3137 bytes.extend_from_slice(&hw1.to_le_bytes());
3138 bytes.extend_from_slice(&hw2.to_le_bytes());
3139
3140 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3142 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3143 bytes.extend_from_slice(&hw1.to_le_bytes());
3144 bytes.extend_from_slice(&hw2.to_le_bytes());
3145
3146 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3148 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3149 bytes.extend_from_slice(&hw1.to_le_bytes());
3150 bytes.extend_from_slice(&hw2.to_le_bytes());
3151
3152 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3154 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3155 bytes.extend_from_slice(&hw1.to_le_bytes());
3156 bytes.extend_from_slice(&hw2.to_le_bytes());
3157
3158 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3160 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3161 bytes.extend_from_slice(&hw1.to_le_bytes());
3162 bytes.extend_from_slice(&hw2.to_le_bytes());
3163
3164 let b_done: u16 = 0xE002;
3166 bytes.extend_from_slice(&b_done.to_le_bytes());
3167
3168 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3171 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3172 bytes.extend_from_slice(&hw1.to_le_bytes());
3173 bytes.extend_from_slice(&hw2.to_le_bytes());
3174
3175 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3177 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3178
3179 Ok(bytes) }
3181
3182 ArmOp::I64ShrS {
3184 rd_lo,
3185 rd_hi,
3186 rn_lo,
3187 rn_hi,
3188 rm_lo,
3189 rm_hi,
3190 } => {
3191 let rd_lo_bits = reg_to_bits(rd_lo);
3192 let rd_hi_bits = reg_to_bits(rd_hi);
3193 let rn_lo_bits = reg_to_bits(rn_lo);
3194 let rn_hi_bits = reg_to_bits(rn_hi);
3195 let rm_lo_bits = reg_to_bits(rm_lo);
3196 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3198
3199 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3201 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3202 bytes.extend_from_slice(&hw1.to_le_bytes());
3203 bytes.extend_from_slice(&hw2.to_le_bytes());
3204
3205 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3207 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3208 bytes.extend_from_slice(&hw1.to_le_bytes());
3209 bytes.extend_from_slice(&hw2.to_le_bytes());
3210
3211 let bpl: u16 = 0xD50A;
3213 bytes.extend_from_slice(&bpl.to_le_bytes());
3214
3215 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3218 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3219 bytes.extend_from_slice(&hw1.to_le_bytes());
3220 bytes.extend_from_slice(&hw2.to_le_bytes());
3221
3222 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3224 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3225 bytes.extend_from_slice(&hw1.to_le_bytes());
3226 bytes.extend_from_slice(&hw2.to_le_bytes());
3227
3228 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3230 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3231 bytes.extend_from_slice(&hw1.to_le_bytes());
3232 bytes.extend_from_slice(&hw2.to_le_bytes());
3233
3234 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3236 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3237 bytes.extend_from_slice(&hw1.to_le_bytes());
3238 bytes.extend_from_slice(&hw2.to_le_bytes());
3239
3240 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3242 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3243 bytes.extend_from_slice(&hw1.to_le_bytes());
3244 bytes.extend_from_slice(&hw2.to_le_bytes());
3245
3246 let b_done: u16 = 0xE003;
3248 bytes.extend_from_slice(&b_done.to_le_bytes());
3249
3250 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3253 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3254 bytes.extend_from_slice(&hw1.to_le_bytes());
3255 bytes.extend_from_slice(&hw2.to_le_bytes());
3256
3257 let hw1: u16 = 0xEA4F;
3261 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3262 bytes.extend_from_slice(&hw1.to_le_bytes());
3263 bytes.extend_from_slice(&hw2.to_le_bytes());
3264
3265 Ok(bytes) }
3267
3268 ArmOp::I64Rotl {
3273 rdlo,
3274 rdhi,
3275 rnlo,
3276 rnhi,
3277 shift,
3278 } => {
3279 let rd_lo_bits = reg_to_bits(rdlo);
3280 let rd_hi_bits = reg_to_bits(rdhi);
3281 let rn_lo_bits = reg_to_bits(rnlo);
3282 let rn_hi_bits = reg_to_bits(rnhi);
3283 let shift_bits = reg_to_bits(shift);
3284 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3288
3289 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3291
3292 let hw1: u16 = (0xF000 | shift_bits) as u16;
3294 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3295 bytes.extend_from_slice(&hw1.to_le_bytes());
3296 bytes.extend_from_slice(&hw2.to_le_bytes());
3297
3298 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3300 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3301 bytes.extend_from_slice(&hw1.to_le_bytes());
3302 bytes.extend_from_slice(&hw2.to_le_bytes());
3303
3304 let bpl: u16 = 0xD50E;
3306 bytes.extend_from_slice(&bpl.to_le_bytes());
3307
3308 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3311 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3312 bytes.extend_from_slice(&hw1.to_le_bytes());
3313 bytes.extend_from_slice(&hw2.to_le_bytes());
3314
3315 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3317 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3318 bytes.extend_from_slice(&hw1.to_le_bytes());
3319 bytes.extend_from_slice(&hw2.to_le_bytes());
3320
3321 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3323 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3324 bytes.extend_from_slice(&hw1.to_le_bytes());
3325 bytes.extend_from_slice(&hw2.to_le_bytes());
3326
3327 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3329 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3330 bytes.extend_from_slice(&hw1.to_le_bytes());
3331 bytes.extend_from_slice(&hw2.to_le_bytes());
3332
3333 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3335 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3336 bytes.extend_from_slice(&hw1.to_le_bytes());
3337 bytes.extend_from_slice(&hw2.to_le_bytes());
3338
3339 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3341 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3342 bytes.extend_from_slice(&hw1.to_le_bytes());
3343 bytes.extend_from_slice(&hw2.to_le_bytes());
3344
3345 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3347 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3348 bytes.extend_from_slice(&hw1.to_le_bytes());
3349 bytes.extend_from_slice(&hw2.to_le_bytes());
3350
3351 let b_done: u16 = 0xE00E;
3353 bytes.extend_from_slice(&b_done.to_le_bytes());
3354
3355 let hw1: u16 = (0xF1C0 | r3) as u16;
3359 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3360 bytes.extend_from_slice(&hw1.to_le_bytes());
3361 bytes.extend_from_slice(&hw2.to_le_bytes());
3362
3363 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3365 let hw2: u16 = (0xF000 | (r12 << 8) | r4) 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) | r4) 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 = (0xFA00 | rn_lo_bits) as u16;
3377 let hw2: u16 = (0xF000 | (shift_bits << 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 = (0xEA40 | shift_bits) as u16;
3383 let hw2: u16 = ((shift_bits << 8) | r12) 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 = (0xFA00 | rn_hi_bits) as u16;
3389 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) 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 = (0xEA40 | rd_lo_bits) as u16;
3395 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3396 bytes.extend_from_slice(&hw1.to_le_bytes());
3397 bytes.extend_from_slice(&hw2.to_le_bytes());
3398
3399 let d_bit = (rd_hi_bits >> 3) & 1;
3401 let mov_instr: u16 =
3402 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3403 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3404
3405 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3407
3408 Ok(bytes) }
3410
3411 ArmOp::I64Rotr {
3416 rdlo,
3417 rdhi,
3418 rnlo,
3419 rnhi,
3420 shift,
3421 } => {
3422 let rd_lo_bits = reg_to_bits(rdlo);
3423 let rd_hi_bits = reg_to_bits(rdhi);
3424 let rn_lo_bits = reg_to_bits(rnlo);
3425 let rn_hi_bits = reg_to_bits(rnhi);
3426 let shift_bits = reg_to_bits(shift);
3427 let r12: u32 = 12;
3428 let r3: u32 = 3;
3429 let r4: u32 = 4;
3430 let mut bytes = Vec::new();
3431
3432 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3434
3435 let hw1: u16 = (0xF000 | shift_bits) as u16;
3437 let hw2: u16 = ((shift_bits << 8) | 0x3F) 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 = (0xF1B0 | shift_bits) as u16;
3443 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3444 bytes.extend_from_slice(&hw1.to_le_bytes());
3445 bytes.extend_from_slice(&hw2.to_le_bytes());
3446
3447 let bpl: u16 = 0xD50E;
3449 bytes.extend_from_slice(&bpl.to_le_bytes());
3450
3451 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3454 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3455 bytes.extend_from_slice(&hw1.to_le_bytes());
3456 bytes.extend_from_slice(&hw2.to_le_bytes());
3457
3458 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3460 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3461 bytes.extend_from_slice(&hw1.to_le_bytes());
3462 bytes.extend_from_slice(&hw2.to_le_bytes());
3463
3464 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3466 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3467 bytes.extend_from_slice(&hw1.to_le_bytes());
3468 bytes.extend_from_slice(&hw2.to_le_bytes());
3469
3470 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3472 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3473 bytes.extend_from_slice(&hw1.to_le_bytes());
3474 bytes.extend_from_slice(&hw2.to_le_bytes());
3475
3476 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3478 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3479 bytes.extend_from_slice(&hw1.to_le_bytes());
3480 bytes.extend_from_slice(&hw2.to_le_bytes());
3481
3482 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3484 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3485 bytes.extend_from_slice(&hw1.to_le_bytes());
3486 bytes.extend_from_slice(&hw2.to_le_bytes());
3487
3488 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3490 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3491 bytes.extend_from_slice(&hw1.to_le_bytes());
3492 bytes.extend_from_slice(&hw2.to_le_bytes());
3493
3494 let b_done: u16 = 0xE00E;
3496 bytes.extend_from_slice(&b_done.to_le_bytes());
3497
3498 let hw1: u16 = (0xF1C0 | r3) as u16;
3501 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3502 bytes.extend_from_slice(&hw1.to_le_bytes());
3503 bytes.extend_from_slice(&hw2.to_le_bytes());
3504
3505 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3507 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3508 bytes.extend_from_slice(&hw1.to_le_bytes());
3509 bytes.extend_from_slice(&hw2.to_le_bytes());
3510
3511 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3513 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3514 bytes.extend_from_slice(&hw1.to_le_bytes());
3515 bytes.extend_from_slice(&hw2.to_le_bytes());
3516
3517 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3519 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3520 bytes.extend_from_slice(&hw1.to_le_bytes());
3521 bytes.extend_from_slice(&hw2.to_le_bytes());
3522
3523 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3525 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3526 bytes.extend_from_slice(&hw1.to_le_bytes());
3527 bytes.extend_from_slice(&hw2.to_le_bytes());
3528
3529 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3531 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3532 bytes.extend_from_slice(&hw1.to_le_bytes());
3533 bytes.extend_from_slice(&hw2.to_le_bytes());
3534
3535 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3537 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3538 bytes.extend_from_slice(&hw1.to_le_bytes());
3539 bytes.extend_from_slice(&hw2.to_le_bytes());
3540
3541 let d_bit = (rd_lo_bits >> 3) & 1;
3543 let mov_instr: u16 =
3544 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3545 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3546
3547 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3549
3550 Ok(bytes) }
3552
3553 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3567 let rd_bits = reg_to_bits(rd);
3568 let rn_lo_bits = reg_to_bits(rnlo);
3569 let rn_hi_bits = reg_to_bits(rnhi);
3570 let mut bytes = Vec::new();
3571
3572 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3574 let hw2: u16 = 0x0F00;
3575 bytes.extend_from_slice(&hw1.to_le_bytes());
3576 bytes.extend_from_slice(&hw2.to_le_bytes());
3577
3578 let beq: u16 = 0xD003;
3581 bytes.extend_from_slice(&beq.to_le_bytes());
3582
3583 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3586 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3587 bytes.extend_from_slice(&hw1.to_le_bytes());
3588 bytes.extend_from_slice(&hw2.to_le_bytes());
3589
3590 let b_done: u16 = 0xE004;
3593 bytes.extend_from_slice(&b_done.to_le_bytes());
3594
3595 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3597
3598 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3602 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3603 bytes.extend_from_slice(&hw1.to_le_bytes());
3604 bytes.extend_from_slice(&hw2.to_le_bytes());
3605
3606 let hw1: u16 = (0xF100 | rd_bits) as u16;
3608 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3609 bytes.extend_from_slice(&hw1.to_le_bytes());
3610 bytes.extend_from_slice(&hw2.to_le_bytes());
3611
3612 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3616 bytes.extend_from_slice(&mov0.to_le_bytes());
3617
3618 Ok(bytes)
3619 }
3620
3621 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3637 let rd_bits = reg_to_bits(rd);
3638 let rn_lo_bits = reg_to_bits(rnlo);
3639 let rn_hi_bits = reg_to_bits(rnhi);
3640 let mut bytes = Vec::new();
3641
3642 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3644 let hw2: u16 = 0x0F00;
3645 bytes.extend_from_slice(&hw1.to_le_bytes());
3646 bytes.extend_from_slice(&hw2.to_le_bytes());
3647
3648 let beq: u16 = 0xD005;
3651 bytes.extend_from_slice(&beq.to_le_bytes());
3652
3653 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3656 let hw2: u16 = (0xF0A0 | (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 = (0xFAB0 | rd_bits) as u16;
3663 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3664 bytes.extend_from_slice(&hw1.to_le_bytes());
3665 bytes.extend_from_slice(&hw2.to_le_bytes());
3666
3667 let b_done: u16 = 0xE006;
3670 bytes.extend_from_slice(&b_done.to_le_bytes());
3671
3672 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3674
3675 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3679 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3680 bytes.extend_from_slice(&hw1.to_le_bytes());
3681 bytes.extend_from_slice(&hw2.to_le_bytes());
3682
3683 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3686 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3687 bytes.extend_from_slice(&hw1.to_le_bytes());
3688 bytes.extend_from_slice(&hw2.to_le_bytes());
3689
3690 let hw1: u16 = (0xF100 | rd_bits) as u16;
3692 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3693 bytes.extend_from_slice(&hw1.to_le_bytes());
3694 bytes.extend_from_slice(&hw2.to_le_bytes());
3695
3696 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3699 bytes.extend_from_slice(&mov0.to_le_bytes());
3700
3701 Ok(bytes)
3702 }
3703
3704 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3708 let rd_bits = reg_to_bits(rd);
3709 let rn_lo_bits = reg_to_bits(rnlo);
3710 let rn_hi_bits = reg_to_bits(rnhi);
3711 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3714
3715 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3717
3718 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3728 bytes.extend_from_slice(&mov.to_le_bytes());
3729
3730 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3733 bytes.extend_from_slice(&mov.to_le_bytes());
3734
3735 let hw1: u16 = 0xEA4F;
3739 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3740 bytes.extend_from_slice(&hw1.to_le_bytes());
3741 bytes.extend_from_slice(&hw2.to_le_bytes());
3742
3743 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3746 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3747 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3749 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3750
3751 let hw1: u16 = (0xEA00 | r12) as u16;
3753 let hw2: u16 = ((r12 << 8) | r3) as u16;
3754 bytes.extend_from_slice(&hw1.to_le_bytes());
3755 bytes.extend_from_slice(&hw2.to_le_bytes());
3756
3757 let hw1: u16 = (0xEBA0 | 4) as u16;
3759 let hw2: u16 = ((4 << 8) | r12) as u16;
3760 bytes.extend_from_slice(&hw1.to_le_bytes());
3761 bytes.extend_from_slice(&hw2.to_le_bytes());
3762
3763 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3767 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3768 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3770 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3771
3772 let hw1: u16 = (0xEA00 | 4) as u16;
3774 let hw2: u16 = ((r12 << 8) | r3) as u16;
3775 bytes.extend_from_slice(&hw1.to_le_bytes());
3776 bytes.extend_from_slice(&hw2.to_le_bytes());
3777
3778 let hw1: u16 = 0xEA4F;
3780 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3781 bytes.extend_from_slice(&hw1.to_le_bytes());
3782 bytes.extend_from_slice(&hw2.to_le_bytes());
3783
3784 let hw1: u16 = (0xEA00 | 4) as u16;
3786 let hw2: u16 = ((4 << 8) | r3) as u16;
3787 bytes.extend_from_slice(&hw1.to_le_bytes());
3788 bytes.extend_from_slice(&hw2.to_le_bytes());
3789
3790 let hw1: u16 = (0xEB00 | 4) as u16;
3792 let hw2: u16 = ((4 << 8) | r12) as u16;
3793 bytes.extend_from_slice(&hw1.to_le_bytes());
3794 bytes.extend_from_slice(&hw2.to_le_bytes());
3795
3796 let hw1: u16 = 0xEA4F;
3801 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3802 bytes.extend_from_slice(&hw1.to_le_bytes());
3803 bytes.extend_from_slice(&hw2.to_le_bytes());
3804
3805 let hw1: u16 = (0xEB00 | 4) as u16;
3807 let hw2: u16 = ((4 << 8) | r12) as u16;
3808 bytes.extend_from_slice(&hw1.to_le_bytes());
3809 bytes.extend_from_slice(&hw2.to_le_bytes());
3810
3811 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3816 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3817 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3819 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3820
3821 let hw1: u16 = (0xEA00 | 4) as u16;
3823 let hw2: u16 = ((4 << 8) | r3) as u16;
3824 bytes.extend_from_slice(&hw1.to_le_bytes());
3825 bytes.extend_from_slice(&hw2.to_le_bytes());
3826
3827 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3831 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3832 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3834 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3835
3836 let hw1: u16 = (0xFB00 | 4) as u16;
3839 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3840 bytes.extend_from_slice(&hw1.to_le_bytes());
3841 bytes.extend_from_slice(&hw2.to_le_bytes());
3842
3843 let hw1: u16 = 0xEA4F;
3846 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) 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;
3853 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3854 bytes.extend_from_slice(&hw1.to_le_bytes());
3855 bytes.extend_from_slice(&hw2.to_le_bytes());
3856
3857 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3859 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3860 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3861 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3862
3863 let hw1: u16 = (0xEA00 | r12) as u16;
3864 let hw2: u16 = ((r12 << 8) | r3) as u16;
3865 bytes.extend_from_slice(&hw1.to_le_bytes());
3866 bytes.extend_from_slice(&hw2.to_le_bytes());
3867
3868 let hw1: u16 = (0xEBA0 | 5) as u16;
3869 let hw2: u16 = ((5 << 8) | r12) as u16;
3870 bytes.extend_from_slice(&hw1.to_le_bytes());
3871 bytes.extend_from_slice(&hw2.to_le_bytes());
3872
3873 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3875 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3876 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3877 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3878
3879 let hw1: u16 = (0xEA00 | 5) as u16;
3880 let hw2: u16 = ((r12 << 8) | r3) as u16;
3881 bytes.extend_from_slice(&hw1.to_le_bytes());
3882 bytes.extend_from_slice(&hw2.to_le_bytes());
3883
3884 let hw1: u16 = 0xEA4F;
3885 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3886 bytes.extend_from_slice(&hw1.to_le_bytes());
3887 bytes.extend_from_slice(&hw2.to_le_bytes());
3888
3889 let hw1: u16 = (0xEA00 | 5) as u16;
3890 let hw2: u16 = ((5 << 8) | r3) as u16;
3891 bytes.extend_from_slice(&hw1.to_le_bytes());
3892 bytes.extend_from_slice(&hw2.to_le_bytes());
3893
3894 let hw1: u16 = (0xEB00 | 5) as u16;
3895 let hw2: u16 = ((5 << 8) | r12) as u16;
3896 bytes.extend_from_slice(&hw1.to_le_bytes());
3897 bytes.extend_from_slice(&hw2.to_le_bytes());
3898
3899 let hw1: u16 = 0xEA4F;
3902 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3903 bytes.extend_from_slice(&hw1.to_le_bytes());
3904 bytes.extend_from_slice(&hw2.to_le_bytes());
3905
3906 let hw1: u16 = (0xEB00 | 5) as u16;
3907 let hw2: u16 = ((5 << 8) | r12) 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(&0xF640u16.to_le_bytes());
3913 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3914 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3915 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3916
3917 let hw1: u16 = (0xEA00 | 5) as u16;
3918 let hw2: u16 = ((5 << 8) | r3) as u16;
3919 bytes.extend_from_slice(&hw1.to_le_bytes());
3920 bytes.extend_from_slice(&hw2.to_le_bytes());
3921
3922 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3924 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3925 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3926 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3927
3928 let hw1: u16 = (0xFB00 | 5) as u16;
3931 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3932 bytes.extend_from_slice(&hw1.to_le_bytes());
3933 bytes.extend_from_slice(&hw2.to_le_bytes());
3934
3935 let hw1: u16 = 0xEA4F;
3938 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3939 bytes.extend_from_slice(&hw1.to_le_bytes());
3940 bytes.extend_from_slice(&hw2.to_le_bytes());
3941
3942 let rd_bits_u16 = rd_bits as u16;
3945 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3946 bytes.extend_from_slice(&instr.to_le_bytes());
3947
3948 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3950
3951 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3953 bytes.extend_from_slice(&mov0.to_le_bytes());
3954
3955 Ok(bytes)
3956 }
3957
3958 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3961 let rdlo_bits = reg_to_bits(rdlo);
3962 let rdhi_bits = reg_to_bits(rdhi);
3963 let rnlo_bits = reg_to_bits(rnlo);
3964 let mut bytes = Vec::new();
3965
3966 let hw1: u16 = 0xFA4F_u16;
3969 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3970 bytes.extend_from_slice(&hw1.to_le_bytes());
3971 bytes.extend_from_slice(&hw2.to_le_bytes());
3972
3973 let hw1: u16 = 0xEA4F;
3978 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3979 bytes.extend_from_slice(&hw1.to_le_bytes());
3980 bytes.extend_from_slice(&hw2.to_le_bytes());
3981
3982 Ok(bytes)
3983 }
3984
3985 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3988 let rdlo_bits = reg_to_bits(rdlo);
3989 let rdhi_bits = reg_to_bits(rdhi);
3990 let rnlo_bits = reg_to_bits(rnlo);
3991 let mut bytes = Vec::new();
3992
3993 let hw1: u16 = 0xFA0F_u16;
3996 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3997 bytes.extend_from_slice(&hw1.to_le_bytes());
3998 bytes.extend_from_slice(&hw2.to_le_bytes());
3999
4000 let hw1: u16 = 0xEA4F;
4002 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4003 bytes.extend_from_slice(&hw1.to_le_bytes());
4004 bytes.extend_from_slice(&hw2.to_le_bytes());
4005
4006 Ok(bytes)
4007 }
4008
4009 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4012 let rdlo_bits = reg_to_bits(rdlo);
4013 let rdhi_bits = reg_to_bits(rdhi);
4014 let rnlo_bits = reg_to_bits(rnlo);
4015 let mut bytes = Vec::new();
4016
4017 if rdlo_bits != rnlo_bits {
4019 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4021 let mov: u16 = 0x4600
4022 | (d_bit << 7)
4023 | ((rnlo_bits as u16) << 3)
4024 | ((rdlo_bits & 0x7) as u16);
4025 bytes.extend_from_slice(&mov.to_le_bytes());
4026 }
4027
4028 let hw1: u16 = 0xEA4F;
4030 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4031 bytes.extend_from_slice(&hw1.to_le_bytes());
4032 bytes.extend_from_slice(&hw2.to_le_bytes());
4033
4034 Ok(bytes)
4035 }
4036
4037 ArmOp::SelectMove { rd, rm, cond } => {
4040 let rd_bits = reg_to_bits(rd) as u16;
4041 let rm_bits = reg_to_bits(rm) as u16;
4042
4043 use synth_synthesis::Condition;
4045 let cond_bits: u16 = match cond {
4046 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, };
4057
4058 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4061
4062 let d_bit = (rd_bits >> 3) & 1;
4065 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4066
4067 let mut bytes = it_instr.to_le_bytes().to_vec();
4069 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4070 Ok(bytes)
4071 }
4072
4073 ArmOp::Popcnt { rd, rm } => {
4084 let mut bytes = Vec::new();
4085
4086 if rd != rm {
4088 let rd_bits = reg_to_bits(rd) as u16;
4089 let rm_bits = reg_to_bits(rm) as u16;
4090 let d_bit = (rd_bits >> 3) & 1;
4092 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4093 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4094 }
4095
4096 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4099 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4100
4101 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4104
4105 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4107
4108 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4110 reg_to_bits(rd),
4111 reg_to_bits(rd),
4112 11,
4113 )?);
4114
4115 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4118 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4119
4120 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4122 11,
4123 reg_to_bits(rd),
4124 12,
4125 )?);
4126
4127 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4129 reg_to_bits(rd),
4130 reg_to_bits(rd),
4131 2,
4132 )?);
4133
4134 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4136 reg_to_bits(rd),
4137 reg_to_bits(rd),
4138 12,
4139 )?);
4140
4141 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4143 reg_to_bits(rd),
4144 reg_to_bits(rd),
4145 11,
4146 )?);
4147
4148 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4151
4152 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4154 reg_to_bits(rd),
4155 reg_to_bits(rd),
4156 11,
4157 )?);
4158
4159 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4161 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4162
4163 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4165 reg_to_bits(rd),
4166 reg_to_bits(rd),
4167 12,
4168 )?);
4169
4170 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4173
4174 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4176 reg_to_bits(rd),
4177 reg_to_bits(rd),
4178 11,
4179 )?);
4180
4181 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4184
4185 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4187 reg_to_bits(rd),
4188 reg_to_bits(rd),
4189 11,
4190 )?);
4191
4192 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4195 reg_to_bits(rd),
4196 reg_to_bits(rd),
4197 0x3F,
4198 )?);
4199
4200 Ok(bytes)
4201 }
4202
4203 ArmOp::I64DivU {
4208 rdlo: _,
4209 rdhi: _,
4210 rnlo: _,
4211 rnhi: _,
4212 rmlo: _,
4213 rmhi: _,
4214 } => {
4215 let mut bytes = Vec::new();
4216
4217 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4221
4222 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());
4233 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4234
4235 let loop_start = bytes.len();
4237
4238 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4249 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());
4258 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4259 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4263 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4264
4265 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4270 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4271 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());
4302 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4303 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4306
4307 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4311 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4312
4313 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4316 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4317 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4318
4319 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4327
4328 Ok(bytes)
4329 }
4330
4331 ArmOp::I64DivS {
4336 rdlo: _,
4337 rdhi: _,
4338 rnlo: _,
4339 rnhi: _,
4340 rmlo: _,
4341 rmhi: _,
4342 } => {
4343 let mut bytes = Vec::new();
4344
4345 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4347 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4348
4349 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4352 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4353
4354 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());
4367
4368 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());
4378
4379 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4382 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4383 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4385 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4386 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4388 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4389
4390 let loop_start = bytes.len();
4391
4392 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4396 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());
4402 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4405
4406 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4410 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());
4423 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4425
4426 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4429
4430 let branch_offset_bytes = bytes.len() - loop_start + 4;
4431 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4432 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4433 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4434
4435 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xF1B9u16.to_le_bytes()); bytes.extend_from_slice(&0x0F00u16.to_le_bytes());
4442 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());
4450
4451 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4453 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4454
4455 Ok(bytes)
4456 }
4457
4458 ArmOp::I64RemU {
4463 rdlo: _,
4464 rdhi: _,
4465 rnlo: _,
4466 rnhi: _,
4467 rmlo: _,
4468 rmhi: _,
4469 } => {
4470 let mut bytes = Vec::new();
4471
4472 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4474 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4475
4476 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4478 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4479 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4481 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4482 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4484 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4485
4486 let loop_start = bytes.len();
4487
4488 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4492 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());
4498 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4501
4502 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4506 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());
4519 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4521
4522 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4525
4526 let branch_offset_bytes = bytes.len() - loop_start + 4;
4527 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4528 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4529 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4530
4531 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4537 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4538
4539 Ok(bytes)
4540 }
4541
4542 ArmOp::I64RemS {
4547 rdlo: _,
4548 rdhi: _,
4549 rnlo: _,
4550 rnhi: _,
4551 rmlo: _,
4552 rmhi: _,
4553 } => {
4554 let mut bytes = Vec::new();
4555
4556 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4558 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4559
4560 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());
4574
4575 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());
4585
4586 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4589 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4590 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4592 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4593 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4595 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4596
4597 let loop_start = bytes.len();
4598
4599 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4603 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());
4609 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4612
4613 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4617 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());
4630 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4632
4633 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4636
4637 let branch_offset_bytes = bytes.len() - loop_start + 4;
4638 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4639 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4640 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4641
4642 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());
4649 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());
4657
4658 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4660 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4661
4662 Ok(bytes)
4663 }
4664
4665 ArmOp::F32Add { sd, sn, sm } => {
4668 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4669 }
4670 ArmOp::F32Sub { sd, sn, sm } => {
4671 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4672 }
4673 ArmOp::F32Mul { sd, sn, sm } => {
4674 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4675 }
4676 ArmOp::F32Div { sd, sn, sm } => {
4677 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4678 }
4679 ArmOp::F32Abs { sd, sm } => {
4680 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4681 }
4682 ArmOp::F32Neg { sd, sm } => {
4683 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4684 }
4685 ArmOp::F32Sqrt { sd, sm } => {
4686 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4687 }
4688
4689 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4692 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4693 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4694 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4695 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4696 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4697 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4698
4699 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4701 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4702 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4703 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4704 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4705 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4706
4707 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4708
4709 ArmOp::F32Load { sd, addr } => {
4710 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4711 }
4712 ArmOp::F32Store { sd, addr } => {
4713 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4714 }
4715
4716 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4717 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4718 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4719 Err(synth_core::Error::synthesis(
4720 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4721 ))
4722 }
4723 ArmOp::F32ReinterpretI32 { sd, rm } => {
4724 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4725 }
4726 ArmOp::I32ReinterpretF32 { rd, sm } => {
4727 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4728 }
4729 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4730 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4731
4732 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4735 0xEE300B00, dd, dn, dm,
4736 )?)),
4737 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4738 0xEE300B40, dd, dn, dm,
4739 )?)),
4740 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4741 0xEE200B00, dd, dn, dm,
4742 )?)),
4743 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4744 0xEE800B00, dd, dn, dm,
4745 )?)),
4746 ArmOp::F64Abs { dd, dm } => {
4747 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4748 }
4749 ArmOp::F64Neg { dd, dm } => {
4750 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4751 }
4752 ArmOp::F64Sqrt { dd, dm } => {
4753 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4754 }
4755
4756 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4759 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4760 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4761 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4762 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4763 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4764 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4765
4766 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4768 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4769 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4770 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4771 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4772 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4773
4774 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4775
4776 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4777 0xED900B00, dd, addr,
4778 )?)),
4779 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4780 0xED800B00, dd, addr,
4781 )?)),
4782
4783 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4784 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4785 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4786 Err(synth_core::Error::synthesis(
4787 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4788 ))
4789 }
4790 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4791 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4792 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4793 )),
4794 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4795 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4796 )),
4797 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4798 Err(synth_core::Error::synthesis(
4799 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4800 ))
4801 }
4802 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4803 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4804
4805 ArmOp::I64Add {
4809 rdlo,
4810 rdhi,
4811 rnlo,
4812 rnhi,
4813 rmlo,
4814 rmhi,
4815 } => {
4816 let mut bytes = Vec::new();
4817 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4819 rd: *rdlo,
4820 rn: *rnlo,
4821 op2: Operand2::Reg(*rmlo),
4822 })?);
4823 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4825 rd: *rdhi,
4826 rn: *rnhi,
4827 op2: Operand2::Reg(*rmhi),
4828 })?);
4829 Ok(bytes)
4830 }
4831
4832 ArmOp::I64Sub {
4834 rdlo,
4835 rdhi,
4836 rnlo,
4837 rnhi,
4838 rmlo,
4839 rmhi,
4840 } => {
4841 let mut bytes = Vec::new();
4842 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4844 rd: *rdlo,
4845 rn: *rnlo,
4846 op2: Operand2::Reg(*rmlo),
4847 })?);
4848 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4850 rd: *rdhi,
4851 rn: *rnhi,
4852 op2: Operand2::Reg(*rmhi),
4853 })?);
4854 Ok(bytes)
4855 }
4856
4857 ArmOp::I64And {
4859 rdlo,
4860 rdhi,
4861 rnlo,
4862 rnhi,
4863 rmlo,
4864 rmhi,
4865 } => {
4866 let mut bytes = Vec::new();
4867 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4868 rd: *rdlo,
4869 rn: *rnlo,
4870 op2: Operand2::Reg(*rmlo),
4871 })?);
4872 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4873 rd: *rdhi,
4874 rn: *rnhi,
4875 op2: Operand2::Reg(*rmhi),
4876 })?);
4877 Ok(bytes)
4878 }
4879
4880 ArmOp::I64Or {
4882 rdlo,
4883 rdhi,
4884 rnlo,
4885 rnhi,
4886 rmlo,
4887 rmhi,
4888 } => {
4889 let mut bytes = Vec::new();
4890 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4891 rd: *rdlo,
4892 rn: *rnlo,
4893 op2: Operand2::Reg(*rmlo),
4894 })?);
4895 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4896 rd: *rdhi,
4897 rn: *rnhi,
4898 op2: Operand2::Reg(*rmhi),
4899 })?);
4900 Ok(bytes)
4901 }
4902
4903 ArmOp::I64Xor {
4905 rdlo,
4906 rdhi,
4907 rnlo,
4908 rnhi,
4909 rmlo,
4910 rmhi,
4911 } => {
4912 let mut bytes = Vec::new();
4913 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4914 rd: *rdlo,
4915 rn: *rnlo,
4916 op2: Operand2::Reg(*rmlo),
4917 })?);
4918 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4919 rd: *rdhi,
4920 rn: *rnhi,
4921 op2: Operand2::Reg(*rmhi),
4922 })?);
4923 Ok(bytes)
4924 }
4925
4926 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4928 rd: *rd,
4929 rn_lo: *rnlo,
4930 rn_hi: *rnhi,
4931 }),
4932
4933 ArmOp::I64Eq {
4935 rd,
4936 rnlo,
4937 rnhi,
4938 rmlo,
4939 rmhi,
4940 } => self.encode_thumb(&ArmOp::I64SetCond {
4941 rd: *rd,
4942 rn_lo: *rnlo,
4943 rn_hi: *rnhi,
4944 rm_lo: *rmlo,
4945 rm_hi: *rmhi,
4946 cond: synth_synthesis::Condition::EQ,
4947 }),
4948
4949 ArmOp::I64Ne {
4950 rd,
4951 rnlo,
4952 rnhi,
4953 rmlo,
4954 rmhi,
4955 } => self.encode_thumb(&ArmOp::I64SetCond {
4956 rd: *rd,
4957 rn_lo: *rnlo,
4958 rn_hi: *rnhi,
4959 rm_lo: *rmlo,
4960 rm_hi: *rmhi,
4961 cond: synth_synthesis::Condition::NE,
4962 }),
4963
4964 ArmOp::I64LtS {
4965 rd,
4966 rnlo,
4967 rnhi,
4968 rmlo,
4969 rmhi,
4970 } => self.encode_thumb(&ArmOp::I64SetCond {
4971 rd: *rd,
4972 rn_lo: *rnlo,
4973 rn_hi: *rnhi,
4974 rm_lo: *rmlo,
4975 rm_hi: *rmhi,
4976 cond: synth_synthesis::Condition::LT,
4977 }),
4978
4979 ArmOp::I64LtU {
4980 rd,
4981 rnlo,
4982 rnhi,
4983 rmlo,
4984 rmhi,
4985 } => self.encode_thumb(&ArmOp::I64SetCond {
4986 rd: *rd,
4987 rn_lo: *rnlo,
4988 rn_hi: *rnhi,
4989 rm_lo: *rmlo,
4990 rm_hi: *rmhi,
4991 cond: synth_synthesis::Condition::LO,
4992 }),
4993
4994 ArmOp::I64LeS {
4995 rd,
4996 rnlo,
4997 rnhi,
4998 rmlo,
4999 rmhi,
5000 } => self.encode_thumb(&ArmOp::I64SetCond {
5001 rd: *rd,
5002 rn_lo: *rnlo,
5003 rn_hi: *rnhi,
5004 rm_lo: *rmlo,
5005 rm_hi: *rmhi,
5006 cond: synth_synthesis::Condition::LE,
5007 }),
5008
5009 ArmOp::I64LeU {
5010 rd,
5011 rnlo,
5012 rnhi,
5013 rmlo,
5014 rmhi,
5015 } => self.encode_thumb(&ArmOp::I64SetCond {
5016 rd: *rd,
5017 rn_lo: *rnlo,
5018 rn_hi: *rnhi,
5019 rm_lo: *rmlo,
5020 rm_hi: *rmhi,
5021 cond: synth_synthesis::Condition::LS,
5022 }),
5023
5024 ArmOp::I64GtS {
5025 rd,
5026 rnlo,
5027 rnhi,
5028 rmlo,
5029 rmhi,
5030 } => self.encode_thumb(&ArmOp::I64SetCond {
5031 rd: *rd,
5032 rn_lo: *rnlo,
5033 rn_hi: *rnhi,
5034 rm_lo: *rmlo,
5035 rm_hi: *rmhi,
5036 cond: synth_synthesis::Condition::GT,
5037 }),
5038
5039 ArmOp::I64GtU {
5040 rd,
5041 rnlo,
5042 rnhi,
5043 rmlo,
5044 rmhi,
5045 } => self.encode_thumb(&ArmOp::I64SetCond {
5046 rd: *rd,
5047 rn_lo: *rnlo,
5048 rn_hi: *rnhi,
5049 rm_lo: *rmlo,
5050 rm_hi: *rmhi,
5051 cond: synth_synthesis::Condition::HI,
5052 }),
5053
5054 ArmOp::I64GeS {
5055 rd,
5056 rnlo,
5057 rnhi,
5058 rmlo,
5059 rmhi,
5060 } => self.encode_thumb(&ArmOp::I64SetCond {
5061 rd: *rd,
5062 rn_lo: *rnlo,
5063 rn_hi: *rnhi,
5064 rm_lo: *rmlo,
5065 rm_hi: *rmhi,
5066 cond: synth_synthesis::Condition::GE,
5067 }),
5068
5069 ArmOp::I64GeU {
5070 rd,
5071 rnlo,
5072 rnhi,
5073 rmlo,
5074 rmhi,
5075 } => self.encode_thumb(&ArmOp::I64SetCond {
5076 rd: *rd,
5077 rn_lo: *rnlo,
5078 rn_hi: *rnhi,
5079 rm_lo: *rmlo,
5080 rm_hi: *rmhi,
5081 cond: synth_synthesis::Condition::HS,
5082 }),
5083
5084 ArmOp::I64Const { rdlo, rdhi, value } => {
5086 let lo32 = *value as u32;
5087 let hi32 = (*value >> 32) as u32;
5088 let mut bytes = Vec::new();
5089 bytes.extend_from_slice(
5091 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5092 );
5093 if lo32 > 0xFFFF {
5094 bytes.extend_from_slice(
5095 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5096 );
5097 }
5098 bytes.extend_from_slice(
5100 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5101 );
5102 if hi32 > 0xFFFF {
5103 bytes.extend_from_slice(
5104 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5105 );
5106 }
5107 Ok(bytes)
5108 }
5109
5110 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5112 let mut bytes = Vec::new();
5113 let offset = if addr.offset < 0 {
5114 0u32
5115 } else {
5116 addr.offset as u32
5117 };
5118 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5119 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5120 rdhi,
5121 &addr.base,
5122 offset.wrapping_add(4),
5123 )?);
5124 Ok(bytes)
5125 }
5126
5127 ArmOp::I64Str { rdlo, rdhi, addr } => {
5129 let mut bytes = Vec::new();
5130 let offset = if addr.offset < 0 {
5131 0u32
5132 } else {
5133 addr.offset as u32
5134 };
5135 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5136 bytes.extend_from_slice(&self.encode_thumb32_str(
5137 rdhi,
5138 &addr.base,
5139 offset.wrapping_add(4),
5140 )?);
5141 Ok(bytes)
5142 }
5143
5144 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5146 let mut bytes = Vec::new();
5147 if rdlo != rn {
5148 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5150 rd: *rdlo,
5151 op2: Operand2::Reg(*rn),
5152 })?);
5153 }
5154 bytes.extend_from_slice(
5156 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5158 Ok(bytes)
5159 }
5160
5161 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5163 let mut bytes = Vec::new();
5164 if rdlo != rn {
5165 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5167 rd: *rdlo,
5168 op2: Operand2::Reg(*rn),
5169 })?);
5170 }
5171 let rdhi_bits = reg_to_bits(rdhi) as u16;
5173 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5174 bytes.extend_from_slice(&instr.to_le_bytes());
5175 Ok(bytes)
5176 }
5177
5178 ArmOp::I32WrapI64 { rd, rnlo } => {
5180 if rd == rnlo {
5181 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5184 } else {
5185 self.encode_thumb(&ArmOp::Mov {
5187 rd: *rd,
5188 op2: Operand2::Reg(*rnlo),
5189 })
5190 }
5191 }
5192
5193 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5195 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5196 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5197 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5198 0xEF000150, qd, qn, qm,
5199 ))),
5200 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5201 0xEF200150, qd, qn, qm,
5202 ))),
5203 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5204 0xFF000150, qd, qn, qm,
5205 ))),
5206 ArmOp::MveMvn { qd, qm } => {
5207 let qd_enc = qreg_to_num(qd);
5209 let qm_enc = qreg_to_num(qm);
5210 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5211 Ok(vfp_to_thumb_bytes(instr))
5212 }
5213 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5214 0xEF100150, qd, qn, qm,
5215 ))),
5216 ArmOp::MveAddI { qd, qn, qm, size } => {
5217 let sz = mve_size_bits(size);
5218 let base: u32 = 0xEF000840 | (sz << 20);
5219 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5220 }
5221 ArmOp::MveSubI { qd, qn, qm, size } => {
5222 let sz = mve_size_bits(size);
5223 let base: u32 = 0xFF000840 | (sz << 20);
5224 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5225 }
5226 ArmOp::MveMulI { qd, qn, qm, size } => {
5227 let sz = mve_size_bits(size);
5228 let base: u32 = 0xEF000950 | (sz << 20);
5229 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5230 }
5231 ArmOp::MveNegI { qd, qm, size } => {
5232 let sz = mve_size_bits(size);
5233 let qd_enc = qreg_to_num(qd);
5235 let qm_enc = qreg_to_num(qm);
5236 let base: u32 = 0xFFB103C0 | (sz << 18);
5237 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5238 Ok(vfp_to_thumb_bytes(instr))
5239 }
5240 ArmOp::MveDup { qd, rn, size } => {
5241 let sz = mve_size_bits(size);
5242 let qd_enc = qreg_to_num(qd);
5243 let rn_bits = reg_to_bits(rn);
5244 let be = match sz {
5247 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5251 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5252 Ok(vfp_to_thumb_bytes(instr))
5253 }
5254 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5255 let qn_enc = qreg_to_num(qn);
5256 let rd_bits = reg_to_bits(rd);
5257 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5260 let lane_in_d = (*lane as u32) & 1;
5261 let _sz = mve_size_bits(size);
5262 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5264 Ok(vfp_to_thumb_bytes(instr))
5265 }
5266 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5267 let qd_enc = qreg_to_num(qd);
5268 let rn_bits = reg_to_bits(rn);
5269 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5270 let lane_in_d = (*lane as u32) & 1;
5271 let _sz = mve_size_bits(size);
5272 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5274 Ok(vfp_to_thumb_bytes(instr))
5275 }
5276
5277 ArmOp::MveCmpEqI { qd, qn, qm, size }
5279 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5280 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5281 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5282 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5283 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5284 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5285 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5286 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5287 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5288 let sz = mve_size_bits(size);
5291 let base: u32 = 0xEF000840 | (sz << 20);
5292 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5293 }
5294
5295 ArmOp::MveAddF32 { qd, qn, qm } => {
5297 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5299 }
5300 ArmOp::MveSubF32 { qd, qn, qm } => {
5301 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5303 }
5304 ArmOp::MveMulF32 { qd, qn, qm } => {
5305 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5307 }
5308 ArmOp::MveNegF32 { qd, qm } => {
5309 let qd_enc = qreg_to_num(qd);
5310 let qm_enc = qreg_to_num(qm);
5311 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5313 Ok(vfp_to_thumb_bytes(instr))
5314 }
5315 ArmOp::MveAbsF32 { qd, qm } => {
5316 let qd_enc = qreg_to_num(qd);
5317 let qm_enc = qreg_to_num(qm);
5318 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5320 Ok(vfp_to_thumb_bytes(instr))
5321 }
5322 ArmOp::MveCmpEqF32 { qd, qn, qm }
5323 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5324 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5325 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5326 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5327 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5328 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5330 }
5331 ArmOp::MveDupF32 { qd, rn } => {
5332 let qd_enc = qreg_to_num(qd);
5333 let rn_bits = reg_to_bits(rn);
5334 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5336 Ok(vfp_to_thumb_bytes(instr))
5337 }
5338 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5339 let qn_enc = qreg_to_num(qn);
5340 let rd_bits = reg_to_bits(rd);
5341 let s_num = qn_enc * 4 + (*lane as u32);
5343 let (vn, n) = encode_sreg(s_num);
5344 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5345 Ok(vfp_to_thumb_bytes(instr))
5346 }
5347 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5348 let qd_enc = qreg_to_num(qd);
5349 let rn_bits = reg_to_bits(rn);
5350 let s_num = qd_enc * 4 + (*lane as u32);
5352 let (vn, n) = encode_sreg(s_num);
5353 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5354 Ok(vfp_to_thumb_bytes(instr))
5355 }
5356 ArmOp::MveDivF32 { qd, qn, qm } => {
5357 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5359 }
5360 ArmOp::MveSqrtF32 { qd, qm } => {
5361 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5363 }
5364
5365 _ => {
5367 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5369 }
5370 }
5371 }
5372
5373 fn encode_thumb_f32_compare(
5377 &self,
5378 rd: &Reg,
5379 sn: &VfpReg,
5380 sm: &VfpReg,
5381 cond_code: u32,
5382 ) -> Result<Vec<u8>> {
5383 let mut bytes = Vec::new();
5384 let rd_bits = reg_to_bits(rd);
5385
5386 let sn_num = vfp_sreg_to_num(sn)?;
5388 let sm_num = vfp_sreg_to_num(sm)?;
5389 let (vd, d) = encode_sreg(sn_num);
5390 let (vm, m) = encode_sreg(sm_num);
5391 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5392 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5393
5394 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5396
5397 if rd_bits < 8 {
5399 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5400 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5401 } else {
5402 let hw1: u16 = 0xF04F;
5404 let hw2: u16 = (rd_bits as u16) << 8;
5405 bytes.extend_from_slice(&hw1.to_le_bytes());
5406 bytes.extend_from_slice(&hw2.to_le_bytes());
5407 }
5408
5409 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5413 bytes.extend_from_slice(&it.to_le_bytes());
5414
5415 if rd_bits < 8 {
5417 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5418 bytes.extend_from_slice(&mov_one.to_le_bytes());
5419 } else {
5420 let hw1: u16 = 0xF04F;
5422 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5423 bytes.extend_from_slice(&hw1.to_le_bytes());
5424 bytes.extend_from_slice(&hw2.to_le_bytes());
5425 }
5426
5427 Ok(bytes)
5428 }
5429
5430 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5432 let mut bytes = Vec::new();
5433 let bits = value.to_bits();
5434 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5439 let imm4 = (lo16 >> 12) & 0xF;
5440 let i_bit = (lo16 >> 11) & 1;
5441 let imm3 = (lo16 >> 8) & 0x7;
5442 let imm8 = lo16 & 0xFF;
5443 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5444 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5445 bytes.extend_from_slice(&hw1.to_le_bytes());
5446 bytes.extend_from_slice(&hw2.to_le_bytes());
5447
5448 let hi16 = (bits >> 16) & 0xFFFF;
5450 let imm4 = (hi16 >> 12) & 0xF;
5451 let i_bit = (hi16 >> 11) & 1;
5452 let imm3 = (hi16 >> 8) & 0x7;
5453 let imm8 = hi16 & 0xFF;
5454 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5455 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5456 bytes.extend_from_slice(&hw1.to_le_bytes());
5457 bytes.extend_from_slice(&hw2.to_le_bytes());
5458
5459 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5461 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5462
5463 Ok(bytes)
5464 }
5465
5466 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5468 let mut bytes = Vec::new();
5469
5470 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5472 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5473
5474 let sd_num = vfp_sreg_to_num(sd)?;
5476 let (vd, d) = encode_sreg(sd_num);
5477 let (vm, m) = encode_sreg(sd_num);
5478 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5479 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5480 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5481
5482 Ok(bytes)
5483 }
5484
5485 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5493 let mut bytes = Vec::new();
5494 let sm_num = vfp_sreg_to_num(sm)?;
5495 let sd_num = vfp_sreg_to_num(sd)?;
5496 let (vd_s, d_s) = encode_sreg(sd_num);
5497 let (vm_s, m_s) = encode_sreg(sm_num);
5498
5499 if mode == 0b11 {
5500 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5502 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5503 } else {
5504 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5509 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5510
5511 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5517 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5518 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5519
5520 if mode != 0 {
5522 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5524 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5525 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5526 }
5527
5528 let vmsr = 0xEEE10A10 | (rt << 12);
5530 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5531
5532 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5534 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5535
5536 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5538 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5539 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5540 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5541 }
5542
5543 let (vd2, d2) = encode_sreg(sd_num);
5545 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5546 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5547
5548 Ok(bytes)
5549 }
5550
5551 fn encode_thumb_f32_minmax(
5553 &self,
5554 sd: &VfpReg,
5555 sn: &VfpReg,
5556 sm: &VfpReg,
5557 is_min: bool,
5558 ) -> Result<Vec<u8>> {
5559 let mut bytes = Vec::new();
5560 let sn_num = vfp_sreg_to_num(sn)?;
5561 let sm_num = vfp_sreg_to_num(sm)?;
5562 let sd_num = vfp_sreg_to_num(sd)?;
5563
5564 let (vd, d) = encode_sreg(sd_num);
5566 let (vn, n) = encode_sreg(sn_num);
5567 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5568 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5569
5570 let (vm, m) = encode_sreg(sm_num);
5572 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5573 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5574
5575 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5577
5578 let cond: u16 = if is_min { 0xC } else { 0x4 };
5580 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5581 bytes.extend_from_slice(&it.to_le_bytes());
5582
5583 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5585 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5586
5587 Ok(bytes)
5588 }
5589
5590 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5592 let mut bytes = Vec::new();
5593
5594 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5596 false,
5597 sm,
5598 &Reg::R12,
5599 )?));
5600
5601 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5603 false,
5604 sn,
5605 &Reg::R0,
5606 )?));
5607
5608 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5620 bytes.extend_from_slice(&hw2.to_le_bytes());
5621
5622 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5626 bytes.extend_from_slice(&hw2.to_le_bytes());
5627
5628 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5632 bytes.extend_from_slice(&hw2.to_le_bytes());
5633
5634 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5636 true,
5637 sd,
5638 &Reg::R0,
5639 )?));
5640
5641 Ok(bytes)
5642 }
5643
5644 fn encode_thumb_f64_compare(
5646 &self,
5647 rd: &Reg,
5648 dn: &VfpReg,
5649 dm: &VfpReg,
5650 cond_code: u32,
5651 ) -> Result<Vec<u8>> {
5652 let mut bytes = Vec::new();
5653 let rd_bits = reg_to_bits(rd);
5654
5655 let dn_num = vfp_dreg_to_num(dn)?;
5657 let dm_num = vfp_dreg_to_num(dm)?;
5658 let (vd, d) = encode_dreg(dn_num);
5659 let (vm, m) = encode_dreg(dm_num);
5660 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5661 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5662
5663 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5665
5666 if rd_bits < 8 {
5668 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5669 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5670 } else {
5671 let hw1: u16 = 0xF04F;
5672 let hw2: u16 = (rd_bits as u16) << 8;
5673 bytes.extend_from_slice(&hw1.to_le_bytes());
5674 bytes.extend_from_slice(&hw2.to_le_bytes());
5675 }
5676
5677 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5679 bytes.extend_from_slice(&it.to_le_bytes());
5680
5681 if rd_bits < 8 {
5683 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5684 bytes.extend_from_slice(&mov_one.to_le_bytes());
5685 } else {
5686 let hw1: u16 = 0xF04F;
5687 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5688 bytes.extend_from_slice(&hw1.to_le_bytes());
5689 bytes.extend_from_slice(&hw2.to_le_bytes());
5690 }
5691
5692 Ok(bytes)
5693 }
5694
5695 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5697 let mut bytes = Vec::new();
5698 let bits = value.to_bits();
5699 let lo32 = bits as u32;
5700 let hi32 = (bits >> 32) as u32;
5701
5702 let lo16 = lo32 & 0xFFFF;
5704 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5705
5706 let hi16 = (lo32 >> 16) & 0xFFFF;
5708 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5709
5710 let lo16 = hi32 & 0xFFFF;
5712 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5713
5714 let hi16 = (hi32 >> 16) & 0xFFFF;
5716 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5717
5718 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5720 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5721
5722 Ok(bytes)
5723 }
5724
5725 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5727 let mut bytes = Vec::new();
5728
5729 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5731 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5732
5733 let dd_num = vfp_dreg_to_num(dd)?;
5735 let (vd, d) = encode_dreg(dd_num);
5736 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5737 let vcvt = base | (d << 22) | (vd << 12);
5738 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5739
5740 Ok(bytes)
5741 }
5742
5743 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5745 let dd_num = vfp_dreg_to_num(dd)?;
5746 let sm_num = vfp_sreg_to_num(sm)?;
5747 let (vd, d) = encode_dreg(dd_num);
5748 let (vm, m) = encode_sreg(sm_num);
5749
5750 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5751 Ok(vfp_to_thumb_bytes(vcvt))
5752 }
5753
5754 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5756 let mut bytes = Vec::new();
5757 let dm_num = vfp_dreg_to_num(dm)?;
5758 let (vm, m) = encode_dreg(dm_num);
5759
5760 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5762 let vcvt = base | (m << 5) | vm;
5763 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5764
5765 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5767 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5768
5769 Ok(bytes)
5770 }
5771
5772 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5776 let mut bytes = Vec::new();
5777 let dm_num = vfp_dreg_to_num(dm)?;
5778 let dd_num = vfp_dreg_to_num(dd)?;
5779 let (vm, m) = encode_dreg(dm_num);
5780 let (vd, d) = encode_dreg(dd_num);
5781
5782 if mode == 0b11 {
5783 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5785 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5786 } else {
5787 let rt: u32 = 12;
5788
5789 let vmrs = 0xEEF10A10 | (rt << 12);
5791 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5792
5793 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5795 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5796 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5797 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5798
5799 if mode != 0 {
5801 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5802 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5803 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5804 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5805 }
5806
5807 let vmsr = 0xEEE10A10 | (rt << 12);
5809 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5810
5811 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5813 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5814
5815 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5817 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5818 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5819 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5820 }
5821
5822 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5824 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5825
5826 Ok(bytes)
5827 }
5828
5829 fn encode_thumb_f64_minmax(
5831 &self,
5832 dd: &VfpReg,
5833 dn: &VfpReg,
5834 dm: &VfpReg,
5835 is_min: bool,
5836 ) -> Result<Vec<u8>> {
5837 let mut bytes = Vec::new();
5838 let dn_num = vfp_dreg_to_num(dn)?;
5839 let dm_num = vfp_dreg_to_num(dm)?;
5840 let dd_num = vfp_dreg_to_num(dd)?;
5841
5842 let (vd, d) = encode_dreg(dd_num);
5844 let (vn, n) = encode_dreg(dn_num);
5845 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5846 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5847
5848 let (vm, m) = encode_dreg(dm_num);
5850 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5851 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5852
5853 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5855
5856 let cond: u16 = if is_min { 0xC } else { 0x4 };
5858 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5859 bytes.extend_from_slice(&it.to_le_bytes());
5860
5861 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5863 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5864
5865 Ok(bytes)
5866 }
5867
5868 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5870 let mut bytes = Vec::new();
5871
5872 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5874 false,
5875 dm,
5876 &Reg::R0,
5877 &Reg::R12,
5878 )?));
5879
5880 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5882 false,
5883 dn,
5884 &Reg::R1,
5885 &Reg::R2,
5886 )?));
5887
5888 let hw1: u16 = 0xF000 | 12;
5890 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5891 bytes.extend_from_slice(&hw1.to_le_bytes());
5892 bytes.extend_from_slice(&hw2.to_le_bytes());
5893
5894 let hw1: u16 = 0xF020 | 2;
5896 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5897 bytes.extend_from_slice(&hw1.to_le_bytes());
5898 bytes.extend_from_slice(&hw2.to_le_bytes());
5899
5900 let hw1: u16 = 0xEA40 | 2;
5902 let hw2: u16 = (2 << 8) | 12;
5903 bytes.extend_from_slice(&hw1.to_le_bytes());
5904 bytes.extend_from_slice(&hw2.to_le_bytes());
5905
5906 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5908 true,
5909 dd,
5910 &Reg::R1,
5911 &Reg::R2,
5912 )?));
5913
5914 Ok(bytes)
5915 }
5916
5917 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5919 let mut bytes = Vec::new();
5920
5921 let sm_num = vfp_sreg_to_num(sm)?;
5922 let (vd, d) = encode_sreg(sm_num);
5923 let (vm, m) = encode_sreg(sm_num);
5924 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5925 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5926 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5927
5928 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5930 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5931
5932 Ok(bytes)
5933 }
5934
5935 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5939 let rd_bits = reg_to_bits(rd);
5940 let rn_bits = reg_to_bits(rn);
5941
5942 let i_bit = (imm >> 11) & 1;
5946 let imm3 = (imm >> 8) & 0x7;
5947 let imm8 = imm & 0xFF;
5948
5949 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5950 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5951
5952 let mut bytes = hw1.to_le_bytes().to_vec();
5953 bytes.extend_from_slice(&hw2.to_le_bytes());
5954 Ok(bytes)
5955 }
5956
5957 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5959 let rd_bits = reg_to_bits(rd);
5960 let rn_bits = reg_to_bits(rn);
5961
5962 let i_bit = (imm >> 11) & 1;
5963 let imm3 = (imm >> 8) & 0x7;
5964 let imm8 = imm & 0xFF;
5965
5966 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5967 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5968
5969 let mut bytes = hw1.to_le_bytes().to_vec();
5970 bytes.extend_from_slice(&hw2.to_le_bytes());
5971 Ok(bytes)
5972 }
5973
5974 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5976 let rd_bits = reg_to_bits(rd);
5977 let rn_bits = reg_to_bits(rn);
5978
5979 let i_bit = (imm >> 11) & 1;
5980 let imm3 = (imm >> 8) & 0x7;
5981 let imm8 = imm & 0xFF;
5982
5983 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5986 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5987
5988 let mut bytes = hw1.to_le_bytes().to_vec();
5989 bytes.extend_from_slice(&hw2.to_le_bytes());
5990 Ok(bytes)
5991 }
5992
5993 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5995 let rd_bits = reg_to_bits(rd);
5996 let rn_bits = reg_to_bits(rn);
5997
5998 let i_bit = (imm >> 11) & 1;
5999 let imm3 = (imm >> 8) & 0x7;
6000 let imm8 = imm & 0xFF;
6001
6002 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6005 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6006
6007 let mut bytes = hw1.to_le_bytes().to_vec();
6008 bytes.extend_from_slice(&hw2.to_le_bytes());
6009 Ok(bytes)
6010 }
6011
6012 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6021 let rd_bits = reg_to_bits(rd);
6022 reg_bits_checked(rd_bits)?;
6023 let imm16 = imm & 0xFFFF;
6024
6025 let imm4 = (imm16 >> 12) & 0xF;
6028 let i_bit = (imm16 >> 11) & 1;
6029 let imm3 = (imm16 >> 8) & 0x7;
6030 let imm8 = imm16 & 0xFF;
6031
6032 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6033 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6034
6035 let mut bytes = hw1.to_le_bytes().to_vec();
6036 bytes.extend_from_slice(&hw2.to_le_bytes());
6037 encoding_contracts::verify_thumb32(&bytes);
6038 Ok(bytes)
6039 }
6040
6041 fn encode_thumb32_shift(
6049 &self,
6050 rd: &Reg,
6051 rm: &Reg,
6052 shift: u32,
6053 shift_type: u8,
6054 ) -> Result<Vec<u8>> {
6055 let rd_bits = reg_to_bits(rd);
6056 let rm_bits = reg_to_bits(rm);
6057 reg_bits_checked(rd_bits)?;
6058 reg_bits_checked(rm_bits)?;
6059 let imm5 = shift & 0x1F;
6060 let imm2 = imm5 & 0x3;
6061 let imm3 = (imm5 >> 2) & 0x7;
6062
6063 let hw1: u16 = 0xEA4F;
6066 let hw2: u16 =
6067 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6068 as u16;
6069
6070 let mut bytes = hw1.to_le_bytes().to_vec();
6071 bytes.extend_from_slice(&hw2.to_le_bytes());
6072 Ok(bytes)
6073 }
6074
6075 fn encode_thumb32_shift_reg(
6079 &self,
6080 rd: &Reg,
6081 rn: &Reg,
6082 rm: &Reg,
6083 shift_type: u8,
6084 ) -> Result<Vec<u8>> {
6085 let rd_bits = reg_to_bits(rd);
6086 let rn_bits = reg_to_bits(rn);
6087 let rm_bits = reg_to_bits(rm);
6088
6089 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6091 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6093
6094 let mut bytes = hw1.to_le_bytes().to_vec();
6095 bytes.extend_from_slice(&hw2.to_le_bytes());
6096 Ok(bytes)
6097 }
6098
6099 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6101 let rn_bits = reg_to_bits(rn);
6102
6103 let i_bit = (imm >> 11) & 1;
6104 let imm3 = (imm >> 8) & 0x7;
6105 let imm8 = imm & 0xFF;
6106
6107 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6109 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6110
6111 let mut bytes = hw1.to_le_bytes().to_vec();
6112 bytes.extend_from_slice(&hw2.to_le_bytes());
6113 Ok(bytes)
6114 }
6115
6116 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6118 let rd_bits = reg_to_bits(rd);
6119 let base_bits = reg_to_bits(base);
6120
6121 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6123 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6124
6125 let mut bytes = hw1.to_le_bytes().to_vec();
6126 bytes.extend_from_slice(&hw2.to_le_bytes());
6127 Ok(bytes)
6128 }
6129
6130 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6132 let rd_bits = reg_to_bits(rd);
6133 let base_bits = reg_to_bits(base);
6134
6135 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6137 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6138
6139 let mut bytes = hw1.to_le_bytes().to_vec();
6140 bytes.extend_from_slice(&hw2.to_le_bytes());
6141 Ok(bytes)
6142 }
6143
6144 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6146 let rd_bits = reg_to_bits(rd);
6147 let base_bits = reg_to_bits(base);
6148 let rm_bits = reg_to_bits(offset_reg);
6149
6150 let hw1: u16 = (0xF850 | base_bits) as u16;
6154 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6155
6156 let mut bytes = hw1.to_le_bytes().to_vec();
6157 bytes.extend_from_slice(&hw2.to_le_bytes());
6158 Ok(bytes)
6159 }
6160
6161 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6163 let rd_bits = reg_to_bits(rd);
6164 let base_bits = reg_to_bits(base);
6165 let rm_bits = reg_to_bits(offset_reg);
6166
6167 let hw1: u16 = (0xF840 | base_bits) as u16;
6171 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6172
6173 let mut bytes = hw1.to_le_bytes().to_vec();
6174 bytes.extend_from_slice(&hw2.to_le_bytes());
6175 Ok(bytes)
6176 }
6177
6178 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6182 let rd_bits = reg_to_bits(rd);
6183 let base_bits = reg_to_bits(base);
6184 let hw1: u16 = (0xF890 | base_bits) as u16;
6186 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6187 let mut bytes = hw1.to_le_bytes().to_vec();
6188 bytes.extend_from_slice(&hw2.to_le_bytes());
6189 Ok(bytes)
6190 }
6191
6192 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6194 let rd_bits = reg_to_bits(rd);
6195 let base_bits = reg_to_bits(base);
6196 let rm_bits = reg_to_bits(offset_reg);
6197 let hw1: u16 = (0xF810 | base_bits) as u16;
6199 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6200 let mut bytes = hw1.to_le_bytes().to_vec();
6201 bytes.extend_from_slice(&hw2.to_le_bytes());
6202 Ok(bytes)
6203 }
6204
6205 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6207 let rd_bits = reg_to_bits(rd);
6208 let base_bits = reg_to_bits(base);
6209 let hw1: u16 = (0xF990 | base_bits) as u16;
6211 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6212 let mut bytes = hw1.to_le_bytes().to_vec();
6213 bytes.extend_from_slice(&hw2.to_le_bytes());
6214 Ok(bytes)
6215 }
6216
6217 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6219 let rd_bits = reg_to_bits(rd);
6220 let base_bits = reg_to_bits(base);
6221 let rm_bits = reg_to_bits(offset_reg);
6222 let hw1: u16 = (0xF910 | base_bits) as u16;
6224 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6225 let mut bytes = hw1.to_le_bytes().to_vec();
6226 bytes.extend_from_slice(&hw2.to_le_bytes());
6227 Ok(bytes)
6228 }
6229
6230 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6232 let rd_bits = reg_to_bits(rd);
6233 let base_bits = reg_to_bits(base);
6234 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6236 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6237 let mut bytes = hw1.to_le_bytes().to_vec();
6238 bytes.extend_from_slice(&hw2.to_le_bytes());
6239 Ok(bytes)
6240 }
6241
6242 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6244 let rd_bits = reg_to_bits(rd);
6245 let base_bits = reg_to_bits(base);
6246 let rm_bits = reg_to_bits(offset_reg);
6247 let hw1: u16 = (0xF830 | base_bits) as u16;
6249 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6250 let mut bytes = hw1.to_le_bytes().to_vec();
6251 bytes.extend_from_slice(&hw2.to_le_bytes());
6252 Ok(bytes)
6253 }
6254
6255 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6257 let rd_bits = reg_to_bits(rd);
6258 let base_bits = reg_to_bits(base);
6259 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6261 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6262 let mut bytes = hw1.to_le_bytes().to_vec();
6263 bytes.extend_from_slice(&hw2.to_le_bytes());
6264 Ok(bytes)
6265 }
6266
6267 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6269 let rd_bits = reg_to_bits(rd);
6270 let base_bits = reg_to_bits(base);
6271 let rm_bits = reg_to_bits(offset_reg);
6272 let hw1: u16 = (0xF930 | base_bits) as u16;
6274 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6275 let mut bytes = hw1.to_le_bytes().to_vec();
6276 bytes.extend_from_slice(&hw2.to_le_bytes());
6277 Ok(bytes)
6278 }
6279
6280 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6282 let rd_bits = reg_to_bits(rd);
6283 let base_bits = reg_to_bits(base);
6284 let hw1: u16 = (0xF880 | base_bits) as u16;
6286 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6287 let mut bytes = hw1.to_le_bytes().to_vec();
6288 bytes.extend_from_slice(&hw2.to_le_bytes());
6289 Ok(bytes)
6290 }
6291
6292 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6294 let rd_bits = reg_to_bits(rd);
6295 let base_bits = reg_to_bits(base);
6296 let rm_bits = reg_to_bits(offset_reg);
6297 let hw1: u16 = (0xF800 | base_bits) as u16;
6299 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6300 let mut bytes = hw1.to_le_bytes().to_vec();
6301 bytes.extend_from_slice(&hw2.to_le_bytes());
6302 Ok(bytes)
6303 }
6304
6305 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6307 let rd_bits = reg_to_bits(rd);
6308 let base_bits = reg_to_bits(base);
6309 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6311 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6312 let mut bytes = hw1.to_le_bytes().to_vec();
6313 bytes.extend_from_slice(&hw2.to_le_bytes());
6314 Ok(bytes)
6315 }
6316
6317 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6319 let rd_bits = reg_to_bits(rd);
6320 let base_bits = reg_to_bits(base);
6321 let rm_bits = reg_to_bits(offset_reg);
6322 let hw1: u16 = (0xF820 | base_bits) as u16;
6324 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6325 let mut bytes = hw1.to_le_bytes().to_vec();
6326 bytes.extend_from_slice(&hw2.to_le_bytes());
6327 Ok(bytes)
6328 }
6329
6330 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6332 let rd_bits = reg_to_bits(rd);
6333 let rn_bits = reg_to_bits(rn);
6334
6335 if imm <= 0xFFF {
6341 let i_bit = (imm >> 11) & 1;
6342 let imm3 = (imm >> 8) & 0x7;
6343 let imm8 = imm & 0xFF;
6344
6345 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6346 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6347
6348 let mut bytes = hw1.to_le_bytes().to_vec();
6349 bytes.extend_from_slice(&hw2.to_le_bytes());
6350 Ok(bytes)
6351 } else {
6352 Err(synth_core::Error::synthesis(
6355 "ADD immediate too large for single instruction",
6356 ))
6357 }
6358 }
6359
6360 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6370 reg_bits_checked(rd)?;
6371 encoding_contracts::verify_imm16(imm16);
6372 let imm16 = imm16 & 0xFFFF;
6375 let imm4 = (imm16 >> 12) & 0xF;
6376 let i_bit = (imm16 >> 11) & 1;
6377 let imm3 = (imm16 >> 8) & 0x7;
6378 let imm8 = imm16 & 0xFF;
6379
6380 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6381 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6382
6383 let mut bytes = hw1.to_le_bytes().to_vec();
6384 bytes.extend_from_slice(&hw2.to_le_bytes());
6385 encoding_contracts::verify_thumb32(&bytes);
6386 Ok(bytes)
6387 }
6388
6389 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6397 reg_bits_checked(rd)?;
6398 encoding_contracts::verify_imm16(imm16);
6399 let imm16 = imm16 & 0xFFFF;
6402 let imm4 = (imm16 >> 12) & 0xF;
6403 let i_bit = (imm16 >> 11) & 1;
6404 let imm3 = (imm16 >> 8) & 0x7;
6405 let imm8 = imm16 & 0xFF;
6406
6407 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6408 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6409
6410 let mut bytes = hw1.to_le_bytes().to_vec();
6411 bytes.extend_from_slice(&hw2.to_le_bytes());
6412 encoding_contracts::verify_thumb32(&bytes);
6413 Ok(bytes)
6414 }
6415
6416 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6418 let imm5 = shift & 0x1F;
6421 let imm2 = imm5 & 0x3;
6422 let imm3 = (imm5 >> 2) & 0x7;
6423
6424 let hw1: u16 = 0xEA4F;
6425 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6426
6427 let mut bytes = hw1.to_le_bytes().to_vec();
6428 bytes.extend_from_slice(&hw2.to_le_bytes());
6429 Ok(bytes)
6430 }
6431
6432 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6434 let hw1: u16 = (0xEA00 | rn) as u16;
6437 let hw2: u16 = ((rd << 8) | rm) as u16;
6438
6439 let mut bytes = hw1.to_le_bytes().to_vec();
6440 bytes.extend_from_slice(&hw2.to_le_bytes());
6441 Ok(bytes)
6442 }
6443
6444 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6446 let i_bit = (imm >> 11) & 1;
6450 let imm3 = (imm >> 8) & 0x7;
6451 let imm8 = imm & 0xFF;
6452
6453 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6454 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6455
6456 let mut bytes = hw1.to_le_bytes().to_vec();
6457 bytes.extend_from_slice(&hw2.to_le_bytes());
6458 Ok(bytes)
6459 }
6460
6461 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6463 let hw1: u16 = (0xEBA0 | rn) as u16;
6466 let hw2: u16 = ((rd << 8) | rm) as u16;
6467
6468 let mut bytes = hw1.to_le_bytes().to_vec();
6469 bytes.extend_from_slice(&hw2.to_le_bytes());
6470 Ok(bytes)
6471 }
6472
6473 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6475 let hw1: u16 = (0xEB00 | rn) as u16;
6478 let hw2: u16 = ((rd << 8) | rm) as u16;
6479
6480 let mut bytes = hw1.to_le_bytes().to_vec();
6481 bytes.extend_from_slice(&hw2.to_le_bytes());
6482 Ok(bytes)
6483 }
6484
6485 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6489 let hw1: u16 = (0xEB10 | rn) as u16;
6491 let hw2: u16 = ((rd << 8) | rm) as u16;
6492 let mut bytes = hw1.to_le_bytes().to_vec();
6493 bytes.extend_from_slice(&hw2.to_le_bytes());
6494 Ok(bytes)
6495 }
6496
6497 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6500 let hw1: u16 = (0xEBB0 | rn) as u16;
6502 let hw2: u16 = ((rd << 8) | rm) as u16;
6503 let mut bytes = hw1.to_le_bytes().to_vec();
6504 bytes.extend_from_slice(&hw2.to_le_bytes());
6505 Ok(bytes)
6506 }
6507
6508 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6510 let mut code = Vec::new();
6511
6512 for op in ops {
6513 let encoded = self.encode(op)?;
6514 code.extend_from_slice(&encoded);
6515 }
6516
6517 Ok(code)
6518 }
6519}
6520
6521fn reg_to_bits(reg: &Reg) -> u32 {
6523 match reg {
6524 Reg::R0 => 0,
6525 Reg::R1 => 1,
6526 Reg::R2 => 2,
6527 Reg::R3 => 3,
6528 Reg::R4 => 4,
6529 Reg::R5 => 5,
6530 Reg::R6 => 6,
6531 Reg::R7 => 7,
6532 Reg::R8 => 8,
6533 Reg::R9 => 9,
6534 Reg::R10 => 10,
6535 Reg::R11 => 11,
6536 Reg::R12 => 12,
6537 Reg::SP => 13,
6538 Reg::LR => 14,
6539 Reg::PC => 15,
6540 }
6541}
6542
6543fn reg_bits_checked(bits: u32) -> Result<()> {
6551 if bits > 14 {
6552 return Err(synth_core::Error::synthesis(format!(
6553 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6554 )));
6555 }
6556 Ok(())
6557}
6558
6559fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6562 if val == 0 {
6563 return Some((0, 1));
6564 }
6565 for rot in 0..16u32 {
6566 let shift = rot * 2;
6567 let unrotated = val.rotate_left(shift);
6569 if unrotated <= 0xFF {
6570 return Some(((rot << 8) | unrotated, 1));
6572 }
6573 }
6574 None
6575}
6576
6577fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6582 match op2 {
6583 Operand2::Imm(val) => {
6584 let uval = *val as u32;
6585 if let Some(encoded) = try_encode_rotated_imm(uval) {
6587 encoded
6588 } else {
6589 let imm = uval & 0xFF;
6594 (imm, 1)
6595 }
6596 }
6597
6598 Operand2::Reg(reg) => {
6599 let reg_bits = reg_to_bits(reg);
6600 (reg_bits, 0) }
6602
6603 Operand2::RegShift {
6604 rm,
6605 shift: _,
6606 amount,
6607 } => {
6608 let rm_bits = reg_to_bits(rm);
6610 let shift_bits = (*amount & 0x1F) << 7;
6611 (shift_bits | rm_bits, 0)
6612 }
6613 }
6614}
6615
6616fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6618 let base_bits = reg_to_bits(&addr.base);
6619 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6621}
6622
6623fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6625 match reg {
6626 VfpReg::S0 => Ok(0),
6627 VfpReg::S1 => Ok(1),
6628 VfpReg::S2 => Ok(2),
6629 VfpReg::S3 => Ok(3),
6630 VfpReg::S4 => Ok(4),
6631 VfpReg::S5 => Ok(5),
6632 VfpReg::S6 => Ok(6),
6633 VfpReg::S7 => Ok(7),
6634 VfpReg::S8 => Ok(8),
6635 VfpReg::S9 => Ok(9),
6636 VfpReg::S10 => Ok(10),
6637 VfpReg::S11 => Ok(11),
6638 VfpReg::S12 => Ok(12),
6639 VfpReg::S13 => Ok(13),
6640 VfpReg::S14 => Ok(14),
6641 VfpReg::S15 => Ok(15),
6642 VfpReg::S16 => Ok(16),
6643 VfpReg::S17 => Ok(17),
6644 VfpReg::S18 => Ok(18),
6645 VfpReg::S19 => Ok(19),
6646 VfpReg::S20 => Ok(20),
6647 VfpReg::S21 => Ok(21),
6648 VfpReg::S22 => Ok(22),
6649 VfpReg::S23 => Ok(23),
6650 VfpReg::S24 => Ok(24),
6651 VfpReg::S25 => Ok(25),
6652 VfpReg::S26 => Ok(26),
6653 VfpReg::S27 => Ok(27),
6654 VfpReg::S28 => Ok(28),
6655 VfpReg::S29 => Ok(29),
6656 VfpReg::S30 => Ok(30),
6657 VfpReg::S31 => Ok(31),
6658 _ => Err(synth_core::Error::SynthesisError(
6660 "D-register not supported in single-precision VFP encoding".to_string(),
6661 )),
6662 }
6663}
6664
6665fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6667 match reg {
6668 VfpReg::D0 => Ok(0),
6669 VfpReg::D1 => Ok(1),
6670 VfpReg::D2 => Ok(2),
6671 VfpReg::D3 => Ok(3),
6672 VfpReg::D4 => Ok(4),
6673 VfpReg::D5 => Ok(5),
6674 VfpReg::D6 => Ok(6),
6675 VfpReg::D7 => Ok(7),
6676 VfpReg::D8 => Ok(8),
6677 VfpReg::D9 => Ok(9),
6678 VfpReg::D10 => Ok(10),
6679 VfpReg::D11 => Ok(11),
6680 VfpReg::D12 => Ok(12),
6681 VfpReg::D13 => Ok(13),
6682 VfpReg::D14 => Ok(14),
6683 VfpReg::D15 => Ok(15),
6684 _ => Err(synth_core::Error::SynthesisError(
6686 "S-register not supported in double-precision VFP encoding".to_string(),
6687 )),
6688 }
6689}
6690
6691fn encode_sreg(s: u32) -> (u32, u32) {
6695 (s >> 1, s & 1)
6696}
6697
6698fn encode_dreg(d: u32) -> (u32, u32) {
6702 (d & 0xF, (d >> 4) & 1)
6703}
6704
6705fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6711 let sd_num = vfp_sreg_to_num(sd)?;
6712 let sn_num = vfp_sreg_to_num(sn)?;
6713 let sm_num = vfp_sreg_to_num(sm)?;
6714 let (vd, d) = encode_sreg(sd_num);
6715 let (vn, n) = encode_sreg(sn_num);
6716 let (vm, m) = encode_sreg(sm_num);
6717
6718 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6719}
6720
6721fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6724 let sd_num = vfp_sreg_to_num(sd)?;
6725 let sm_num = vfp_sreg_to_num(sm)?;
6726 let (vd, d) = encode_sreg(sd_num);
6727 let (vm, m) = encode_sreg(sm_num);
6728
6729 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6730}
6731
6732fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6736 let sd_num = vfp_sreg_to_num(sd)?;
6737 let (vd, d) = encode_sreg(sd_num);
6738 let rn = reg_to_bits(&addr.base);
6739
6740 let offset = addr.offset;
6741 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6742 let abs_offset = offset.unsigned_abs();
6743 let imm8 = (abs_offset / 4) & 0xFF;
6744
6745 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6746}
6747
6748fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6752 let s_num = vfp_sreg_to_num(sreg)?;
6753 let (vn, n) = encode_sreg(s_num);
6754 let rt = reg_to_bits(core);
6755
6756 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6757 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6758}
6759
6760fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6764 let dd_num = vfp_dreg_to_num(dd)?;
6765 let dn_num = vfp_dreg_to_num(dn)?;
6766 let dm_num = vfp_dreg_to_num(dm)?;
6767 let (vd, d) = encode_dreg(dd_num);
6768 let (vn, n) = encode_dreg(dn_num);
6769 let (vm, m) = encode_dreg(dm_num);
6770
6771 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6772}
6773
6774fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6776 let dd_num = vfp_dreg_to_num(dd)?;
6777 let dm_num = vfp_dreg_to_num(dm)?;
6778 let (vd, d) = encode_dreg(dd_num);
6779 let (vm, m) = encode_dreg(dm_num);
6780
6781 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6782}
6783
6784fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6787 let dd_num = vfp_dreg_to_num(dd)?;
6788 let (vd, d) = encode_dreg(dd_num);
6789 let rn = reg_to_bits(&addr.base);
6790
6791 let offset = addr.offset;
6792 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6793 let abs_offset = offset.unsigned_abs();
6794 let imm8 = (abs_offset / 4) & 0xFF;
6795
6796 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6797}
6798
6799fn encode_vmov_core_dreg(
6803 to_dreg: bool,
6804 dreg: &VfpReg,
6805 core_lo: &Reg,
6806 core_hi: &Reg,
6807) -> Result<u32> {
6808 let d_num = vfp_dreg_to_num(dreg)?;
6809 let (vm, m) = encode_dreg(d_num);
6810 let rt = reg_to_bits(core_lo);
6811 let rt2 = reg_to_bits(core_hi);
6812
6813 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6814 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6815}
6816
6817fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6819 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6820 let hw2 = (instr & 0xFFFF) as u16;
6821 let mut bytes = hw1.to_le_bytes().to_vec();
6822 bytes.extend_from_slice(&hw2.to_le_bytes());
6823 bytes
6824}
6825
6826fn qreg_to_num(reg: &QReg) -> u32 {
6832 match reg {
6833 QReg::Q0 => 0,
6834 QReg::Q1 => 1,
6835 QReg::Q2 => 2,
6836 QReg::Q3 => 3,
6837 QReg::Q4 => 4,
6838 QReg::Q5 => 5,
6839 QReg::Q6 => 6,
6840 QReg::Q7 => 7,
6841 }
6842}
6843
6844fn mve_size_bits(size: &MveSize) -> u32 {
6846 match size {
6847 MveSize::S8 => 0b00,
6848 MveSize::S16 => 0b01,
6849 MveSize::S32 => 0b10,
6850 }
6851}
6852
6853fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6857 let d = qreg_to_num(qd) * 2;
6858 let n = qreg_to_num(qn) * 2;
6859 let m = qreg_to_num(qm) * 2;
6860
6861 let vd = d & 0xF;
6866 let d_bit = (d >> 4) & 1;
6867 let vn = n & 0xF;
6868 let n_bit = (n >> 4) & 1;
6869 let vm = m & 0xF;
6870 let m_bit = (m >> 4) & 1;
6871
6872 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6873}
6874
6875fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6877 encode_mve_3reg(base, qd, qn, qm)
6878}
6879
6880fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6883 let qd_enc = qreg_to_num(qd) * 2;
6884 let rn = reg_to_bits(&addr.base);
6885 let offset = addr.offset;
6886 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6887 let abs_offset = offset.unsigned_abs();
6888 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6892 | (u_bit << 23)
6893 | ((qd_enc >> 4) << 22)
6894 | (rn << 16)
6895 | ((qd_enc & 0xF) << 12)
6896 | (imm7 & 0x7F)
6897}
6898
6899fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6901 let qd_enc = qreg_to_num(qd) * 2;
6902 let rn = reg_to_bits(&addr.base);
6903 let offset = addr.offset;
6904 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6905 let abs_offset = offset.unsigned_abs();
6906 let imm7 = (abs_offset / 4) & 0x7F;
6907
6908 0xED000E80
6909 | (u_bit << 23)
6910 | ((qd_enc >> 4) << 22)
6911 | (rn << 16)
6912 | ((qd_enc & 0xF) << 12)
6913 | (imm7 & 0x7F)
6914}
6915
6916impl ArmEncoder {
6917 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6919 let mut result = Vec::new();
6920 let qd_num = qreg_to_num(qd);
6921
6922 for i in 0..4 {
6924 let word = u32::from_le_bytes([
6925 bytes[i * 4],
6926 bytes[i * 4 + 1],
6927 bytes[i * 4 + 2],
6928 bytes[i * 4 + 3],
6929 ]);
6930 let lo16 = word & 0xFFFF;
6931 let hi16 = (word >> 16) & 0xFFFF;
6932
6933 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6935 if hi16 != 0 {
6937 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6938 }
6939
6940 let s_num = qd_num * 4 + i as u32;
6942 let (vn, n) = encode_sreg(s_num);
6943 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6944 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6945 }
6946
6947 Ok(result)
6948 }
6949
6950 fn encode_thumb_mve_lane_wise_f32_binop(
6952 &self,
6953 qd: &QReg,
6954 qn: &QReg,
6955 qm: &QReg,
6956 vfp_base: u32,
6957 ) -> Result<Vec<u8>> {
6958 let mut result = Vec::new();
6959 let qd_num = qreg_to_num(qd);
6960 let qn_num = qreg_to_num(qn);
6961 let qm_num = qreg_to_num(qm);
6962
6963 for i in 0..4u32 {
6965 let sd = qd_num * 4 + i;
6966 let sn = qn_num * 4 + i;
6967 let sm = qm_num * 4 + i;
6968
6969 let (vd, d) = encode_sreg(sd);
6970 let (vn, n) = encode_sreg(sn);
6971 let (vm, m) = encode_sreg(sm);
6972
6973 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6974 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6975 }
6976
6977 Ok(result)
6978 }
6979
6980 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6982 let mut result = Vec::new();
6983 let qd_num = qreg_to_num(qd);
6984 let qm_num = qreg_to_num(qm);
6985
6986 for i in 0..4u32 {
6988 let sd = qd_num * 4 + i;
6989 let sm = qm_num * 4 + i;
6990
6991 let (vd, d) = encode_sreg(sd);
6992 let (vm, m) = encode_sreg(sm);
6993
6994 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6995 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6996 }
6997
6998 Ok(result)
6999 }
7000}
7001
7002#[cfg(test)]
7003mod tests {
7004 use super::*;
7005
7006 #[test]
7007 fn test_encoder_creation() {
7008 let encoder_arm = ArmEncoder::new_arm32();
7009 assert!(!encoder_arm.thumb_mode);
7010
7011 let encoder_thumb = ArmEncoder::new_thumb2();
7012 assert!(encoder_thumb.thumb_mode);
7013 }
7014
7015 #[test]
7022 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7023 use synth_synthesis::{ArmOp, Condition, Reg};
7024 let enc = ArmEncoder::new_thumb2();
7025 let hi = enc
7027 .encode(&ArmOp::SetCond {
7028 rd: Reg::R12,
7029 cond: Condition::NE,
7030 })
7031 .unwrap();
7032 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7033 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7035 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7036 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7037 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7038 let lo = enc
7040 .encode(&ArmOp::SetCond {
7041 rd: Reg::R0,
7042 cond: Condition::NE,
7043 })
7044 .unwrap();
7045 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7046 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7047 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7048 }
7049
7050 #[test]
7057 fn test_encode_arm32_indexed_load_keeps_index_206() {
7058 use synth_synthesis::{ArmOp, MemAddr, Reg};
7059 let enc = ArmEncoder::new_arm32();
7060 let bytes = enc
7062 .encode(&ArmOp::Ldr {
7063 rd: Reg::R0,
7064 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7065 })
7066 .unwrap();
7067 assert_eq!(
7068 bytes.len(),
7069 8,
7070 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7071 );
7072 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7073 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7074 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7076 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7078 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7080 }
7081
7082 #[test]
7089 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7090 let encoder = ArmEncoder::new_thumb2();
7091
7092 let code = encoder
7094 .encode(&ArmOp::Add {
7095 rd: Reg::R12,
7096 rn: Reg::R12,
7097 op2: Operand2::Reg(Reg::R0),
7098 })
7099 .unwrap();
7100 assert_eq!(
7102 code,
7103 vec![0x0C, 0xEB, 0x00, 0x0C],
7104 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7105 );
7106 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7108
7109 let lo = encoder
7111 .encode(&ArmOp::Add {
7112 rd: Reg::R1,
7113 rn: Reg::R2,
7114 op2: Operand2::Reg(Reg::R3),
7115 })
7116 .unwrap();
7117 assert_eq!(
7118 lo.len(),
7119 2,
7120 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7121 );
7122 }
7123
7124 #[test]
7127 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7128 let encoder = ArmEncoder::new_thumb2();
7129
7130 let adds = encoder
7132 .encode(&ArmOp::Adds {
7133 rd: Reg::R10,
7134 rn: Reg::R10,
7135 op2: Operand2::Reg(Reg::R8),
7136 })
7137 .unwrap();
7138 assert_eq!(
7139 adds,
7140 vec![0x1A, 0xEB, 0x08, 0x0A],
7141 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7142 );
7143
7144 let subs = encoder
7146 .encode(&ArmOp::Subs {
7147 rd: Reg::R10,
7148 rn: Reg::R10,
7149 op2: Operand2::Reg(Reg::R8),
7150 })
7151 .unwrap();
7152 assert_eq!(
7153 subs,
7154 vec![0xBA, 0xEB, 0x08, 0x0A],
7155 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7156 );
7157 }
7158
7159 #[test]
7162 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7163 let encoder = ArmEncoder::new_thumb2();
7164
7165 let cmn = encoder
7167 .encode(&ArmOp::Cmn {
7168 rn: Reg::R10,
7169 op2: Operand2::Reg(Reg::R8),
7170 })
7171 .unwrap();
7172 assert_eq!(
7173 cmn,
7174 vec![0x1A, 0xEB, 0x08, 0x0F],
7175 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7176 );
7177
7178 let lo = encoder
7180 .encode(&ArmOp::Cmn {
7181 rn: Reg::R1,
7182 op2: Operand2::Reg(Reg::R2),
7183 })
7184 .unwrap();
7185 assert_eq!(
7186 lo.len(),
7187 2,
7188 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7189 );
7190 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7191 }
7192
7193 #[test]
7197 fn test_encode_pc_operand_returns_err_not_panic_185() {
7198 let encoder = ArmEncoder::new_thumb2();
7199 for op in [
7200 ArmOp::Sdiv {
7201 rd: Reg::PC,
7202 rn: Reg::R0,
7203 rm: Reg::R1,
7204 },
7205 ArmOp::Udiv {
7206 rd: Reg::R0,
7207 rn: Reg::PC,
7208 rm: Reg::R1,
7209 },
7210 ArmOp::Sdiv {
7211 rd: Reg::R0,
7212 rn: Reg::R1,
7213 rm: Reg::PC,
7214 },
7215 ] {
7216 let r = encoder.encode(&op);
7217 assert!(
7218 r.is_err(),
7219 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7220 );
7221 }
7222 assert!(
7224 encoder
7225 .encode(&ArmOp::Sdiv {
7226 rd: Reg::R0,
7227 rn: Reg::R1,
7228 rm: Reg::R2
7229 })
7230 .is_ok()
7231 );
7232 }
7233
7234 #[test]
7235 fn test_encode_nop_arm32() {
7236 let encoder = ArmEncoder::new_arm32();
7237 let code = encoder.encode(&ArmOp::Nop).unwrap();
7238
7239 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7242
7243 #[test]
7244 fn test_encode_nop_thumb() {
7245 let encoder = ArmEncoder::new_thumb2();
7246 let code = encoder.encode(&ArmOp::Nop).unwrap();
7247
7248 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7251
7252 #[test]
7253 fn test_encode_mov_immediate_arm32() {
7254 let encoder = ArmEncoder::new_arm32();
7255 let op = ArmOp::Mov {
7256 rd: Reg::R0,
7257 op2: Operand2::Imm(42),
7258 };
7259
7260 let code = encoder.encode(&op).unwrap();
7261 assert_eq!(code.len(), 4);
7262
7263 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7265 assert_eq!(instr & 0x0E000000, 0x02000000); }
7267
7268 #[test]
7269 fn test_encode_add_registers_arm32() {
7270 let encoder = ArmEncoder::new_arm32();
7271 let op = ArmOp::Add {
7272 rd: Reg::R0,
7273 rn: Reg::R1,
7274 op2: Operand2::Reg(Reg::R2),
7275 };
7276
7277 let code = encoder.encode(&op).unwrap();
7278 assert_eq!(code.len(), 4);
7279
7280 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7281 assert_eq!(instr & 0x0FE00000, 0x00800000);
7283 }
7284
7285 #[test]
7286 fn test_encode_ldr_arm32() {
7287 let encoder = ArmEncoder::new_arm32();
7288 let op = ArmOp::Ldr {
7289 rd: Reg::R0,
7290 addr: MemAddr::imm(Reg::R1, 4),
7291 };
7292
7293 let code = encoder.encode(&op).unwrap();
7294 assert_eq!(code.len(), 4);
7295
7296 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7297 assert_eq!(instr & 0x00100000, 0x00100000);
7299 }
7300
7301 #[test]
7302 fn test_encode_str_arm32() {
7303 let encoder = ArmEncoder::new_arm32();
7304 let op = ArmOp::Str {
7305 rd: Reg::R0,
7306 addr: MemAddr::imm(Reg::SP, 0),
7307 };
7308
7309 let code = encoder.encode(&op).unwrap();
7310 assert_eq!(code.len(), 4);
7311 }
7312
7313 #[test]
7314 fn test_encode_branch_arm32() {
7315 let encoder = ArmEncoder::new_arm32();
7316 let op = ArmOp::Bl {
7317 label: "main".to_string(),
7318 };
7319
7320 let code = encoder.encode(&op).unwrap();
7321 assert_eq!(code.len(), 4);
7322
7323 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7324 assert_eq!(instr & 0x0F000000, 0x0B000000);
7326 }
7327
7328 #[test]
7338 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7339 let encoder = ArmEncoder::new_thumb2();
7340 let op = ArmOp::Bl {
7341 label: "callee".to_string(),
7342 };
7343
7344 let code = encoder.encode(&op).unwrap();
7345 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7346
7347 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7348 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7349 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7350 assert_eq!(
7351 hw2, 0xFFFE,
7352 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7353 );
7354 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7355 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7356 }
7357
7358 #[test]
7359 fn test_encode_sequence() {
7360 let encoder = ArmEncoder::new_arm32();
7361 let ops = vec![
7362 ArmOp::Mov {
7363 rd: Reg::R0,
7364 op2: Operand2::Imm(42),
7365 },
7366 ArmOp::Mov {
7367 rd: Reg::R1,
7368 op2: Operand2::Imm(10),
7369 },
7370 ArmOp::Add {
7371 rd: Reg::R2,
7372 rn: Reg::R0,
7373 op2: Operand2::Reg(Reg::R1),
7374 },
7375 ];
7376
7377 let code = encoder.encode_sequence(&ops).unwrap();
7378 assert_eq!(code.len(), 12); }
7380
7381 #[test]
7382 fn test_reg_to_bits() {
7383 assert_eq!(reg_to_bits(&Reg::R0), 0);
7384 assert_eq!(reg_to_bits(&Reg::R7), 7);
7385 assert_eq!(reg_to_bits(&Reg::SP), 13);
7386 assert_eq!(reg_to_bits(&Reg::LR), 14);
7387 assert_eq!(reg_to_bits(&Reg::PC), 15);
7388 }
7389
7390 #[test]
7391 fn test_encode_bitwise_operations() {
7392 let encoder = ArmEncoder::new_arm32();
7393
7394 let and_op = ArmOp::And {
7395 rd: Reg::R0,
7396 rn: Reg::R1,
7397 op2: Operand2::Reg(Reg::R2),
7398 };
7399 let and_code = encoder.encode(&and_op).unwrap();
7400 assert_eq!(and_code.len(), 4);
7401
7402 let orr_op = ArmOp::Orr {
7403 rd: Reg::R0,
7404 rn: Reg::R1,
7405 op2: Operand2::Reg(Reg::R2),
7406 };
7407 let orr_code = encoder.encode(&orr_op).unwrap();
7408 assert_eq!(orr_code.len(), 4);
7409
7410 let eor_op = ArmOp::Eor {
7411 rd: Reg::R0,
7412 rn: Reg::R1,
7413 op2: Operand2::Reg(Reg::R2),
7414 };
7415 let eor_code = encoder.encode(&eor_op).unwrap();
7416 assert_eq!(eor_code.len(), 4);
7417 }
7418
7419 #[test]
7422 fn test_encode_sdiv_thumb2() {
7423 let encoder = ArmEncoder::new_thumb2();
7424 let op = ArmOp::Sdiv {
7425 rd: Reg::R0,
7426 rn: Reg::R1,
7427 rm: Reg::R2,
7428 };
7429
7430 let code = encoder.encode(&op).unwrap();
7431 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7438 assert_eq!(code[1], 0xFB);
7439 assert_eq!(code[2], 0xF2);
7440 assert_eq!(code[3], 0xF0);
7441 }
7442
7443 #[test]
7444 fn test_encode_udiv_thumb2() {
7445 let encoder = ArmEncoder::new_thumb2();
7446 let op = ArmOp::Udiv {
7447 rd: Reg::R0,
7448 rn: Reg::R1,
7449 rm: Reg::R2,
7450 };
7451
7452 let code = encoder.encode(&op).unwrap();
7453 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7458 assert_eq!(code[1], 0xFB);
7459 assert_eq!(code[2], 0xF2);
7460 assert_eq!(code[3], 0xF0);
7461 }
7462
7463 #[test]
7464 fn test_encode_mul_thumb2() {
7465 let encoder = ArmEncoder::new_thumb2();
7466 let op = ArmOp::Mul {
7467 rd: Reg::R0,
7468 rn: Reg::R1,
7469 rm: Reg::R2,
7470 };
7471
7472 let code = encoder.encode(&op).unwrap();
7473 assert_eq!(code.len(), 4); }
7475
7476 #[test]
7477 fn test_encode_and_thumb2() {
7478 let encoder = ArmEncoder::new_thumb2();
7479 let op = ArmOp::And {
7480 rd: Reg::R0,
7481 rn: Reg::R1,
7482 op2: Operand2::Reg(Reg::R2),
7483 };
7484
7485 let code = encoder.encode(&op).unwrap();
7486 assert_eq!(code.len(), 4); }
7488
7489 #[test]
7490 fn test_encode_lsl_thumb2_low_regs() {
7491 let encoder = ArmEncoder::new_thumb2();
7492 let op = ArmOp::Lsl {
7493 rd: Reg::R0,
7494 rn: Reg::R1,
7495 shift: 5,
7496 };
7497
7498 let code = encoder.encode(&op).unwrap();
7499 assert_eq!(code.len(), 2); }
7501
7502 #[test]
7503 fn test_encode_clz_thumb2() {
7504 let encoder = ArmEncoder::new_thumb2();
7505 let op = ArmOp::Clz {
7506 rd: Reg::R0,
7507 rm: Reg::R1,
7508 };
7509
7510 let code = encoder.encode(&op).unwrap();
7511 assert_eq!(code.len(), 4); }
7513
7514 #[test]
7515 fn test_encode_bx_thumb2() {
7516 let encoder = ArmEncoder::new_thumb2();
7517 let op = ArmOp::Bx { rm: Reg::LR };
7518
7519 let code = encoder.encode(&op).unwrap();
7520 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7524 }
7525
7526 #[test]
7531 fn test_encode_f32_abs_arm32() {
7532 let encoder = ArmEncoder::new_arm32();
7533 let op = ArmOp::F32Abs {
7534 sd: VfpReg::S0,
7535 sm: VfpReg::S2,
7536 };
7537 let code = encoder.encode(&op).unwrap();
7538 assert_eq!(code.len(), 4); }
7540
7541 #[test]
7542 fn test_encode_f32_neg_arm32() {
7543 let encoder = ArmEncoder::new_arm32();
7544 let op = ArmOp::F32Neg {
7545 sd: VfpReg::S0,
7546 sm: VfpReg::S2,
7547 };
7548 let code = encoder.encode(&op).unwrap();
7549 assert_eq!(code.len(), 4);
7550 }
7551
7552 #[test]
7553 fn test_encode_f32_sqrt_arm32() {
7554 let encoder = ArmEncoder::new_arm32();
7555 let op = ArmOp::F32Sqrt {
7556 sd: VfpReg::S0,
7557 sm: VfpReg::S2,
7558 };
7559 let code = encoder.encode(&op).unwrap();
7560 assert_eq!(code.len(), 4);
7561 }
7562
7563 #[test]
7564 fn test_encode_f32_ceil_arm32() {
7565 let encoder = ArmEncoder::new_arm32();
7566 let op = ArmOp::F32Ceil {
7567 sd: VfpReg::S0,
7568 sm: VfpReg::S2,
7569 };
7570 let code = encoder.encode(&op).unwrap();
7571 assert_eq!(code.len(), 36);
7573 }
7574
7575 #[test]
7576 fn test_encode_f32_floor_thumb2() {
7577 let encoder = ArmEncoder::new_thumb2();
7578 let op = ArmOp::F32Floor {
7579 sd: VfpReg::S0,
7580 sm: VfpReg::S2,
7581 };
7582 let code = encoder.encode(&op).unwrap();
7583 assert_eq!(code.len(), 36);
7585 }
7586
7587 #[test]
7588 fn test_encode_f32_min_arm32() {
7589 let encoder = ArmEncoder::new_arm32();
7590 let op = ArmOp::F32Min {
7591 sd: VfpReg::S0,
7592 sn: VfpReg::S2,
7593 sm: VfpReg::S4,
7594 };
7595 let code = encoder.encode(&op).unwrap();
7596 assert_eq!(code.len(), 16); }
7598
7599 #[test]
7600 fn test_encode_f32_max_thumb2() {
7601 let encoder = ArmEncoder::new_thumb2();
7602 let op = ArmOp::F32Max {
7603 sd: VfpReg::S0,
7604 sn: VfpReg::S2,
7605 sm: VfpReg::S4,
7606 };
7607 let code = encoder.encode(&op).unwrap();
7608 assert_eq!(code.len(), 18);
7610 }
7611
7612 #[test]
7613 fn test_encode_f32_copysign_arm32() {
7614 let encoder = ArmEncoder::new_arm32();
7615 let op = ArmOp::F32Copysign {
7616 sd: VfpReg::S0,
7617 sn: VfpReg::S2,
7618 sm: VfpReg::S4,
7619 };
7620 let code = encoder.encode(&op).unwrap();
7621 assert_eq!(code.len(), 24);
7623 }
7624
7625 #[test]
7630 fn test_encode_f64_add_arm32() {
7631 let encoder = ArmEncoder::new_arm32();
7632 let op = ArmOp::F64Add {
7633 dd: VfpReg::D0,
7634 dn: VfpReg::D1,
7635 dm: VfpReg::D2,
7636 };
7637 let code = encoder.encode(&op).unwrap();
7638 assert_eq!(code.len(), 4);
7639 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7641 assert_eq!((instr >> 8) & 0xF, 0xB); }
7643
7644 #[test]
7645 fn test_encode_f64_sub_thumb2() {
7646 let encoder = ArmEncoder::new_thumb2();
7647 let op = ArmOp::F64Sub {
7648 dd: VfpReg::D0,
7649 dn: VfpReg::D1,
7650 dm: VfpReg::D2,
7651 };
7652 let code = encoder.encode(&op).unwrap();
7653 assert_eq!(code.len(), 4); }
7655
7656 #[test]
7657 fn test_encode_f64_mul_arm32() {
7658 let encoder = ArmEncoder::new_arm32();
7659 let op = ArmOp::F64Mul {
7660 dd: VfpReg::D0,
7661 dn: VfpReg::D1,
7662 dm: VfpReg::D2,
7663 };
7664 let code = encoder.encode(&op).unwrap();
7665 assert_eq!(code.len(), 4);
7666 }
7667
7668 #[test]
7669 fn test_encode_f64_div_arm32() {
7670 let encoder = ArmEncoder::new_arm32();
7671 let op = ArmOp::F64Div {
7672 dd: VfpReg::D0,
7673 dn: VfpReg::D1,
7674 dm: VfpReg::D2,
7675 };
7676 let code = encoder.encode(&op).unwrap();
7677 assert_eq!(code.len(), 4);
7678 }
7679
7680 #[test]
7681 fn test_encode_f64_abs_arm32() {
7682 let encoder = ArmEncoder::new_arm32();
7683 let op = ArmOp::F64Abs {
7684 dd: VfpReg::D0,
7685 dm: VfpReg::D2,
7686 };
7687 let code = encoder.encode(&op).unwrap();
7688 assert_eq!(code.len(), 4);
7689 }
7690
7691 #[test]
7692 fn test_encode_f64_neg_arm32() {
7693 let encoder = ArmEncoder::new_arm32();
7694 let op = ArmOp::F64Neg {
7695 dd: VfpReg::D0,
7696 dm: VfpReg::D2,
7697 };
7698 let code = encoder.encode(&op).unwrap();
7699 assert_eq!(code.len(), 4);
7700 }
7701
7702 #[test]
7703 fn test_encode_f64_sqrt_arm32() {
7704 let encoder = ArmEncoder::new_arm32();
7705 let op = ArmOp::F64Sqrt {
7706 dd: VfpReg::D0,
7707 dm: VfpReg::D2,
7708 };
7709 let code = encoder.encode(&op).unwrap();
7710 assert_eq!(code.len(), 4);
7711 }
7712
7713 #[test]
7714 fn test_encode_f64_load_arm32() {
7715 let encoder = ArmEncoder::new_arm32();
7716 let op = ArmOp::F64Load {
7717 dd: VfpReg::D0,
7718 addr: MemAddr::imm(Reg::R0, 8),
7719 };
7720 let code = encoder.encode(&op).unwrap();
7721 assert_eq!(code.len(), 4);
7722 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7723 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7726
7727 #[test]
7728 fn test_encode_f64_store_thumb2() {
7729 let encoder = ArmEncoder::new_thumb2();
7730 let op = ArmOp::F64Store {
7731 dd: VfpReg::D0,
7732 addr: MemAddr::imm(Reg::SP, 0),
7733 };
7734 let code = encoder.encode(&op).unwrap();
7735 assert_eq!(code.len(), 4);
7736 }
7737
7738 #[test]
7739 fn test_encode_f64_compare_arm32() {
7740 let encoder = ArmEncoder::new_arm32();
7741 let op = ArmOp::F64Eq {
7742 rd: Reg::R0,
7743 dn: VfpReg::D0,
7744 dm: VfpReg::D1,
7745 };
7746 let code = encoder.encode(&op).unwrap();
7747 assert_eq!(code.len(), 16); }
7749
7750 #[test]
7751 fn test_encode_f64_compare_thumb2() {
7752 let encoder = ArmEncoder::new_thumb2();
7753 let op = ArmOp::F64Lt {
7754 rd: Reg::R0,
7755 dn: VfpReg::D0,
7756 dm: VfpReg::D1,
7757 };
7758 let code = encoder.encode(&op).unwrap();
7759 assert_eq!(code.len(), 14);
7761 }
7762
7763 #[test]
7764 fn test_encode_f64_const_arm32() {
7765 let encoder = ArmEncoder::new_arm32();
7766 let op = ArmOp::F64Const {
7767 dd: VfpReg::D0,
7768 value: 3.125,
7769 };
7770 let code = encoder.encode(&op).unwrap();
7771 assert_eq!(code.len(), 20);
7773 }
7774
7775 #[test]
7776 fn test_encode_f64_const_thumb2() {
7777 let encoder = ArmEncoder::new_thumb2();
7778 let op = ArmOp::F64Const {
7779 dd: VfpReg::D0,
7780 value: 2.5,
7781 };
7782 let code = encoder.encode(&op).unwrap();
7783 assert_eq!(code.len(), 20);
7785 }
7786
7787 #[test]
7788 fn test_encode_f64_convert_i32s_arm32() {
7789 let encoder = ArmEncoder::new_arm32();
7790 let op = ArmOp::F64ConvertI32S {
7791 dd: VfpReg::D0,
7792 rm: Reg::R0,
7793 };
7794 let code = encoder.encode(&op).unwrap();
7795 assert_eq!(code.len(), 8);
7797 }
7798
7799 #[test]
7800 fn test_encode_f64_promote_f32_arm32() {
7801 let encoder = ArmEncoder::new_arm32();
7802 let op = ArmOp::F64PromoteF32 {
7803 dd: VfpReg::D0,
7804 sm: VfpReg::S0,
7805 };
7806 let code = encoder.encode(&op).unwrap();
7807 assert_eq!(code.len(), 4); }
7809
7810 #[test]
7811 fn test_encode_f64_promote_f32_thumb2() {
7812 let encoder = ArmEncoder::new_thumb2();
7813 let op = ArmOp::F64PromoteF32 {
7814 dd: VfpReg::D0,
7815 sm: VfpReg::S0,
7816 };
7817 let code = encoder.encode(&op).unwrap();
7818 assert_eq!(code.len(), 4);
7819 }
7820
7821 #[test]
7822 fn test_encode_i32_trunc_f64s_arm32() {
7823 let encoder = ArmEncoder::new_arm32();
7824 let op = ArmOp::I32TruncF64S {
7825 rd: Reg::R0,
7826 dm: VfpReg::D0,
7827 };
7828 let code = encoder.encode(&op).unwrap();
7829 assert_eq!(code.len(), 8);
7831 }
7832
7833 #[test]
7834 fn test_encode_f64_reinterpret_i64_arm32() {
7835 let encoder = ArmEncoder::new_arm32();
7836 let op = ArmOp::F64ReinterpretI64 {
7837 dd: VfpReg::D0,
7838 rmlo: Reg::R0,
7839 rmhi: Reg::R1,
7840 };
7841 let code = encoder.encode(&op).unwrap();
7842 assert_eq!(code.len(), 4); }
7844
7845 #[test]
7846 fn test_encode_i64_reinterpret_f64_thumb2() {
7847 let encoder = ArmEncoder::new_thumb2();
7848 let op = ArmOp::I64ReinterpretF64 {
7849 rdlo: Reg::R0,
7850 rdhi: Reg::R1,
7851 dm: VfpReg::D0,
7852 };
7853 let code = encoder.encode(&op).unwrap();
7854 assert_eq!(code.len(), 4);
7855 }
7856
7857 #[test]
7858 fn test_encode_f64_trunc_thumb2() {
7859 let encoder = ArmEncoder::new_thumb2();
7860 let op = ArmOp::F64Trunc {
7861 dd: VfpReg::D0,
7862 dm: VfpReg::D1,
7863 };
7864 let code = encoder.encode(&op).unwrap();
7865 assert_eq!(code.len(), 8);
7867 }
7868
7869 #[test]
7870 fn test_encode_f64_min_arm32() {
7871 let encoder = ArmEncoder::new_arm32();
7872 let op = ArmOp::F64Min {
7873 dd: VfpReg::D0,
7874 dn: VfpReg::D1,
7875 dm: VfpReg::D2,
7876 };
7877 let code = encoder.encode(&op).unwrap();
7878 assert_eq!(code.len(), 16);
7880 }
7881
7882 #[test]
7883 fn test_f64_cp11_encoding() {
7884 let encoder = ArmEncoder::new_arm32();
7886
7887 let code = encoder
7889 .encode(&ArmOp::F64Add {
7890 dd: VfpReg::D0,
7891 dn: VfpReg::D0,
7892 dm: VfpReg::D0,
7893 })
7894 .unwrap();
7895 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7896 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7897
7898 let code = encoder
7900 .encode(&ArmOp::F32Add {
7901 sd: VfpReg::S0,
7902 sn: VfpReg::S0,
7903 sm: VfpReg::S0,
7904 })
7905 .unwrap();
7906 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7907 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7908 }
7909
7910 #[test]
7911 fn test_dreg_encoding_higher_registers() {
7912 let encoder = ArmEncoder::new_arm32();
7913
7914 let op = ArmOp::F64Add {
7916 dd: VfpReg::D15,
7917 dn: VfpReg::D14,
7918 dm: VfpReg::D13,
7919 };
7920 let code = encoder.encode(&op).unwrap();
7921 assert_eq!(code.len(), 4);
7922
7923 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7925 assert_eq!((instr >> 8) & 0xF, 0xB); }
7927
7928 #[test]
7933 fn test_encode_label_emits_no_bytes() {
7934 let encoder = ArmEncoder::new_thumb2();
7935 let op = ArmOp::Label {
7936 name: ".Lblock_end_0".to_string(),
7937 };
7938 let code = encoder.encode(&op).unwrap();
7939 assert!(code.is_empty(), "Label should emit zero bytes");
7940
7941 let encoder32 = ArmEncoder::new_arm32();
7942 let code32 = encoder32.encode(&op).unwrap();
7943 assert!(
7944 code32.is_empty(),
7945 "Label should emit zero bytes in ARM32 too"
7946 );
7947 }
7948
7949 #[test]
7950 fn test_encode_bcc_eq_thumb2() {
7951 use synth_synthesis::Condition;
7952 let encoder = ArmEncoder::new_thumb2();
7953 let op = ArmOp::Bcc {
7954 cond: Condition::EQ,
7955 label: "target".to_string(),
7956 };
7957 let code = encoder.encode(&op).unwrap();
7958 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7962 }
7963
7964 #[test]
7965 fn test_encode_bcc_ne_thumb2() {
7966 use synth_synthesis::Condition;
7967 let encoder = ArmEncoder::new_thumb2();
7968 let op = ArmOp::Bcc {
7969 cond: Condition::NE,
7970 label: "target".to_string(),
7971 };
7972 let code = encoder.encode(&op).unwrap();
7973 assert_eq!(code.len(), 2);
7974
7975 assert_eq!(code, vec![0x00, 0xD1]);
7977 }
7978
7979 #[test]
7980 fn test_encode_bcc_arm32() {
7981 use synth_synthesis::Condition;
7982 let encoder = ArmEncoder::new_arm32();
7983 let op = ArmOp::Bcc {
7984 cond: Condition::EQ,
7985 label: "target".to_string(),
7986 };
7987 let code = encoder.encode(&op).unwrap();
7988 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7991 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7995
7996 #[test]
7997 fn test_encode_udf_thumb2() {
7998 let encoder = ArmEncoder::new_thumb2();
7999 let op = ArmOp::Udf { imm: 0 };
8000 let code = encoder.encode(&op).unwrap();
8001 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8005 }
8006
8007 #[test]
8008 fn test_encode_nop_thumb2() {
8009 let encoder = ArmEncoder::new_thumb2();
8010 let op = ArmOp::Nop;
8011 let code = encoder.encode(&op).unwrap();
8012 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8016 }
8017
8018 #[test]
8023 fn test_encode_i64_add_thumb2() {
8024 let encoder = ArmEncoder::new_thumb2();
8025 let op = ArmOp::I64Add {
8026 rdlo: Reg::R0,
8027 rdhi: Reg::R1,
8028 rnlo: Reg::R0,
8029 rnhi: Reg::R1,
8030 rmlo: Reg::R2,
8031 rmhi: Reg::R3,
8032 };
8033 let code = encoder.encode(&op).unwrap();
8034 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8036 }
8037
8038 #[test]
8039 fn test_encode_i64_sub_thumb2() {
8040 let encoder = ArmEncoder::new_thumb2();
8041 let op = ArmOp::I64Sub {
8042 rdlo: Reg::R0,
8043 rdhi: Reg::R1,
8044 rnlo: Reg::R0,
8045 rnhi: Reg::R1,
8046 rmlo: Reg::R2,
8047 rmhi: Reg::R3,
8048 };
8049 let code = encoder.encode(&op).unwrap();
8050 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8052 }
8053
8054 #[test]
8055 fn test_encode_i64_and_thumb2() {
8056 let encoder = ArmEncoder::new_thumb2();
8057 let op = ArmOp::I64And {
8058 rdlo: Reg::R0,
8059 rdhi: Reg::R1,
8060 rnlo: Reg::R0,
8061 rnhi: Reg::R1,
8062 rmlo: Reg::R2,
8063 rmhi: Reg::R3,
8064 };
8065 let code = encoder.encode(&op).unwrap();
8066 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8068 }
8069
8070 #[test]
8071 fn test_encode_i64_or_thumb2() {
8072 let encoder = ArmEncoder::new_thumb2();
8073 let op = ArmOp::I64Or {
8074 rdlo: Reg::R0,
8075 rdhi: Reg::R1,
8076 rnlo: Reg::R0,
8077 rnhi: Reg::R1,
8078 rmlo: Reg::R2,
8079 rmhi: Reg::R3,
8080 };
8081 let code = encoder.encode(&op).unwrap();
8082 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8083 }
8084
8085 #[test]
8086 fn test_encode_i64_xor_thumb2() {
8087 let encoder = ArmEncoder::new_thumb2();
8088 let op = ArmOp::I64Xor {
8089 rdlo: Reg::R0,
8090 rdhi: Reg::R1,
8091 rnlo: Reg::R0,
8092 rnhi: Reg::R1,
8093 rmlo: Reg::R2,
8094 rmhi: Reg::R3,
8095 };
8096 let code = encoder.encode(&op).unwrap();
8097 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8098 }
8099
8100 #[test]
8101 fn test_encode_i64_const_small_thumb2() {
8102 let encoder = ArmEncoder::new_thumb2();
8103 let op = ArmOp::I64Const {
8105 rdlo: Reg::R0,
8106 rdhi: Reg::R1,
8107 value: 42,
8108 };
8109 let code = encoder.encode(&op).unwrap();
8110 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8112 }
8113
8114 #[test]
8115 fn test_encode_i64_const_large_thumb2() {
8116 let encoder = ArmEncoder::new_thumb2();
8117 let op = ArmOp::I64Const {
8119 rdlo: Reg::R0,
8120 rdhi: Reg::R1,
8121 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8122 };
8123 let code = encoder.encode(&op).unwrap();
8124 assert_eq!(
8126 code.len(),
8127 16,
8128 "I64Const with large value should be 16 bytes"
8129 );
8130 }
8131
8132 #[test]
8133 fn test_encode_i64_extend_i32_s_thumb2() {
8134 let encoder = ArmEncoder::new_thumb2();
8135 let op = ArmOp::I64ExtendI32S {
8136 rdlo: Reg::R0,
8137 rdhi: Reg::R1,
8138 rn: Reg::R0,
8139 };
8140 let code = encoder.encode(&op).unwrap();
8141 assert_eq!(
8143 code.len(),
8144 4,
8145 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8146 );
8147 }
8148
8149 #[test]
8150 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8151 let encoder = ArmEncoder::new_thumb2();
8152 let op = ArmOp::I64ExtendI32S {
8153 rdlo: Reg::R0,
8154 rdhi: Reg::R1,
8155 rn: Reg::R2,
8156 };
8157 let code = encoder.encode(&op).unwrap();
8158 assert!(
8160 code.len() >= 6,
8161 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8162 );
8163 }
8164
8165 #[test]
8166 fn test_encode_i64_extend_i32_u_thumb2() {
8167 let encoder = ArmEncoder::new_thumb2();
8168 let op = ArmOp::I64ExtendI32U {
8169 rdlo: Reg::R0,
8170 rdhi: Reg::R1,
8171 rn: Reg::R0,
8172 };
8173 let code = encoder.encode(&op).unwrap();
8174 assert_eq!(
8176 code.len(),
8177 2,
8178 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8179 );
8180 }
8181
8182 #[test]
8183 fn test_encode_i32_wrap_i64_nop_thumb2() {
8184 let encoder = ArmEncoder::new_thumb2();
8185 let op = ArmOp::I32WrapI64 {
8187 rd: Reg::R0,
8188 rnlo: Reg::R0,
8189 };
8190 let code = encoder.encode(&op).unwrap();
8191 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8192 assert_eq!(code, vec![0x00, 0xBF]); }
8194
8195 #[test]
8196 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8197 let encoder = ArmEncoder::new_thumb2();
8198 let op = ArmOp::I32WrapI64 {
8199 rd: Reg::R2,
8200 rnlo: Reg::R0,
8201 };
8202 let code = encoder.encode(&op).unwrap();
8203 assert!(
8205 code.len() >= 2,
8206 "I32WrapI64 diff reg should emit at least 2 bytes"
8207 );
8208 }
8209
8210 #[test]
8211 fn test_encode_i64_eqz_thumb2() {
8212 let encoder = ArmEncoder::new_thumb2();
8213 let op = ArmOp::I64Eqz {
8214 rd: Reg::R0,
8215 rnlo: Reg::R0,
8216 rnhi: Reg::R1,
8217 };
8218 let code = encoder.encode(&op).unwrap();
8219 assert!(
8221 code.len() >= 6,
8222 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8223 );
8224 }
8225
8226 #[test]
8227 fn test_encode_i64_eq_thumb2() {
8228 let encoder = ArmEncoder::new_thumb2();
8229 let op = ArmOp::I64Eq {
8230 rd: Reg::R0,
8231 rnlo: Reg::R0,
8232 rnhi: Reg::R1,
8233 rmlo: Reg::R2,
8234 rmhi: Reg::R3,
8235 };
8236 let code = encoder.encode(&op).unwrap();
8237 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8239 }
8240
8241 #[test]
8242 fn test_encode_i64_ldr_thumb2() {
8243 let encoder = ArmEncoder::new_thumb2();
8244 let op = ArmOp::I64Ldr {
8245 rdlo: Reg::R0,
8246 rdhi: Reg::R1,
8247 addr: MemAddr::imm(Reg::SP, 0),
8248 };
8249 let code = encoder.encode(&op).unwrap();
8250 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8252 }
8253
8254 #[test]
8255 fn test_encode_i64_str_thumb2() {
8256 let encoder = ArmEncoder::new_thumb2();
8257 let op = ArmOp::I64Str {
8258 rdlo: Reg::R0,
8259 rdhi: Reg::R1,
8260 addr: MemAddr::imm(Reg::SP, 0),
8261 };
8262 let code = encoder.encode(&op).unwrap();
8263 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8265 }
8266
8267 #[test]
8268 fn test_encode_i64_all_comparisons_thumb2() {
8269 let encoder = ArmEncoder::new_thumb2();
8270
8271 let ops = vec![
8272 ArmOp::I64Ne {
8273 rd: Reg::R0,
8274 rnlo: Reg::R0,
8275 rnhi: Reg::R1,
8276 rmlo: Reg::R2,
8277 rmhi: Reg::R3,
8278 },
8279 ArmOp::I64LtS {
8280 rd: Reg::R0,
8281 rnlo: Reg::R0,
8282 rnhi: Reg::R1,
8283 rmlo: Reg::R2,
8284 rmhi: Reg::R3,
8285 },
8286 ArmOp::I64LtU {
8287 rd: Reg::R0,
8288 rnlo: Reg::R0,
8289 rnhi: Reg::R1,
8290 rmlo: Reg::R2,
8291 rmhi: Reg::R3,
8292 },
8293 ArmOp::I64LeS {
8294 rd: Reg::R0,
8295 rnlo: Reg::R0,
8296 rnhi: Reg::R1,
8297 rmlo: Reg::R2,
8298 rmhi: Reg::R3,
8299 },
8300 ArmOp::I64LeU {
8301 rd: Reg::R0,
8302 rnlo: Reg::R0,
8303 rnhi: Reg::R1,
8304 rmlo: Reg::R2,
8305 rmhi: Reg::R3,
8306 },
8307 ArmOp::I64GtS {
8308 rd: Reg::R0,
8309 rnlo: Reg::R0,
8310 rnhi: Reg::R1,
8311 rmlo: Reg::R2,
8312 rmhi: Reg::R3,
8313 },
8314 ArmOp::I64GtU {
8315 rd: Reg::R0,
8316 rnlo: Reg::R0,
8317 rnhi: Reg::R1,
8318 rmlo: Reg::R2,
8319 rmhi: Reg::R3,
8320 },
8321 ArmOp::I64GeS {
8322 rd: Reg::R0,
8323 rnlo: Reg::R0,
8324 rnhi: Reg::R1,
8325 rmlo: Reg::R2,
8326 rmhi: Reg::R3,
8327 },
8328 ArmOp::I64GeU {
8329 rd: Reg::R0,
8330 rnlo: Reg::R0,
8331 rnhi: Reg::R1,
8332 rmlo: Reg::R2,
8333 rmhi: Reg::R3,
8334 },
8335 ];
8336
8337 for op in &ops {
8338 let code = encoder.encode(op).unwrap();
8339 assert!(
8340 code.len() >= 8,
8341 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8342 op,
8343 code.len()
8344 );
8345 }
8346 }
8347
8348 #[test]
8349 fn test_encode_i64_const_zero_thumb2() {
8350 let encoder = ArmEncoder::new_thumb2();
8351 let op = ArmOp::I64Const {
8352 rdlo: Reg::R0,
8353 rdhi: Reg::R1,
8354 value: 0,
8355 };
8356 let code = encoder.encode(&op).unwrap();
8357 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8359 }
8360
8361 #[test]
8362 fn test_encode_i64_const_negative_one_thumb2() {
8363 let encoder = ArmEncoder::new_thumb2();
8364 let op = ArmOp::I64Const {
8365 rdlo: Reg::R0,
8366 rdhi: Reg::R1,
8367 value: -1, };
8369 let code = encoder.encode(&op).unwrap();
8370 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8372 }
8373
8374 #[test]
8379 fn test_encode_ldrb_arm32() {
8380 let encoder = ArmEncoder::new_arm32();
8381 let op = ArmOp::Ldrb {
8382 rd: Reg::R0,
8383 addr: MemAddr::imm(Reg::R1, 4),
8384 };
8385 let code = encoder.encode(&op).unwrap();
8386 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8387 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8389 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8390 }
8391
8392 #[test]
8393 fn test_encode_strb_arm32() {
8394 let encoder = ArmEncoder::new_arm32();
8395 let op = ArmOp::Strb {
8396 rd: Reg::R0,
8397 addr: MemAddr::imm(Reg::R1, 0),
8398 };
8399 let code = encoder.encode(&op).unwrap();
8400 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8401 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8403 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8404 }
8405
8406 #[test]
8407 fn test_encode_ldrh_arm32() {
8408 let encoder = ArmEncoder::new_arm32();
8409 let op = ArmOp::Ldrh {
8410 rd: Reg::R0,
8411 addr: MemAddr::imm(Reg::R1, 2),
8412 };
8413 let code = encoder.encode(&op).unwrap();
8414 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8415 }
8416
8417 #[test]
8418 fn test_encode_strh_arm32() {
8419 let encoder = ArmEncoder::new_arm32();
8420 let op = ArmOp::Strh {
8421 rd: Reg::R0,
8422 addr: MemAddr::imm(Reg::R1, 0),
8423 };
8424 let code = encoder.encode(&op).unwrap();
8425 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8426 }
8427
8428 #[test]
8429 fn test_encode_ldrsb_arm32() {
8430 let encoder = ArmEncoder::new_arm32();
8431 let op = ArmOp::Ldrsb {
8432 rd: Reg::R0,
8433 addr: MemAddr::imm(Reg::R1, 0),
8434 };
8435 let code = encoder.encode(&op).unwrap();
8436 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8437 }
8438
8439 #[test]
8440 fn test_encode_ldrsh_arm32() {
8441 let encoder = ArmEncoder::new_arm32();
8442 let op = ArmOp::Ldrsh {
8443 rd: Reg::R0,
8444 addr: MemAddr::imm(Reg::R1, 0),
8445 };
8446 let code = encoder.encode(&op).unwrap();
8447 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8448 }
8449
8450 #[test]
8451 fn test_encode_ldrb_thumb2_16bit() {
8452 let encoder = ArmEncoder::new_thumb2();
8453 let op = ArmOp::Ldrb {
8454 rd: Reg::R0,
8455 addr: MemAddr::imm(Reg::R1, 4),
8456 };
8457 let code = encoder.encode(&op).unwrap();
8458 assert_eq!(
8460 code.len(),
8461 2,
8462 "Thumb-2 LDRB with small offset should be 16-bit"
8463 );
8464 }
8465
8466 #[test]
8467 fn test_encode_ldrb_thumb2_32bit() {
8468 let encoder = ArmEncoder::new_thumb2();
8469 let op = ArmOp::Ldrb {
8470 rd: Reg::R0,
8471 addr: MemAddr::imm(Reg::R1, 100), };
8473 let code = encoder.encode(&op).unwrap();
8474 assert_eq!(
8475 code.len(),
8476 4,
8477 "Thumb-2 LDRB with large offset should be 32-bit"
8478 );
8479 }
8480
8481 #[test]
8482 fn test_encode_strb_thumb2_16bit() {
8483 let encoder = ArmEncoder::new_thumb2();
8484 let op = ArmOp::Strb {
8485 rd: Reg::R0,
8486 addr: MemAddr::imm(Reg::R1, 10),
8487 };
8488 let code = encoder.encode(&op).unwrap();
8489 assert_eq!(
8490 code.len(),
8491 2,
8492 "Thumb-2 STRB with small offset should be 16-bit"
8493 );
8494 }
8495
8496 #[test]
8497 fn test_encode_ldrh_thumb2_16bit() {
8498 let encoder = ArmEncoder::new_thumb2();
8499 let op = ArmOp::Ldrh {
8500 rd: Reg::R0,
8501 addr: MemAddr::imm(Reg::R1, 4), };
8503 let code = encoder.encode(&op).unwrap();
8504 assert_eq!(
8505 code.len(),
8506 2,
8507 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8508 );
8509 }
8510
8511 #[test]
8512 fn test_encode_strh_thumb2_16bit() {
8513 let encoder = ArmEncoder::new_thumb2();
8514 let op = ArmOp::Strh {
8515 rd: Reg::R0,
8516 addr: MemAddr::imm(Reg::R1, 4),
8517 };
8518 let code = encoder.encode(&op).unwrap();
8519 assert_eq!(
8520 code.len(),
8521 2,
8522 "Thumb-2 STRH with small aligned offset should be 16-bit"
8523 );
8524 }
8525
8526 #[test]
8527 fn test_encode_ldrsb_thumb2() {
8528 let encoder = ArmEncoder::new_thumb2();
8529 let op = ArmOp::Ldrsb {
8530 rd: Reg::R0,
8531 addr: MemAddr::imm(Reg::R1, 0),
8532 };
8533 let code = encoder.encode(&op).unwrap();
8534 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8536 }
8537
8538 #[test]
8539 fn test_encode_ldrsh_thumb2() {
8540 let encoder = ArmEncoder::new_thumb2();
8541 let op = ArmOp::Ldrsh {
8542 rd: Reg::R0,
8543 addr: MemAddr::imm(Reg::R1, 0),
8544 };
8545 let code = encoder.encode(&op).unwrap();
8546 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8547 }
8548
8549 #[test]
8550 fn test_encode_memory_size_thumb2() {
8551 let encoder = ArmEncoder::new_thumb2();
8552 let op = ArmOp::MemorySize { rd: Reg::R0 };
8553 let code = encoder.encode(&op).unwrap();
8554 assert!(!code.is_empty(), "MemorySize should produce code");
8556 }
8557
8558 #[test]
8559 fn test_encode_memory_grow_thumb2() {
8560 let encoder = ArmEncoder::new_thumb2();
8561 let op = ArmOp::MemoryGrow {
8562 rd: Reg::R0,
8563 rn: Reg::R0,
8564 };
8565 let code = encoder.encode(&op).unwrap();
8566 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8567 }
8568
8569 #[test]
8570 fn test_encode_subword_reg_offset_thumb2() {
8571 let encoder = ArmEncoder::new_thumb2();
8572
8573 let op = ArmOp::Ldrb {
8575 rd: Reg::R0,
8576 addr: MemAddr::reg(Reg::R1, Reg::R2),
8577 };
8578 let code = encoder.encode(&op).unwrap();
8579 assert_eq!(
8580 code.len(),
8581 4,
8582 "Thumb-2 LDRB with reg offset should be 32-bit"
8583 );
8584
8585 let op = ArmOp::Strb {
8587 rd: Reg::R0,
8588 addr: MemAddr::reg(Reg::R1, Reg::R2),
8589 };
8590 let code = encoder.encode(&op).unwrap();
8591 assert_eq!(
8592 code.len(),
8593 4,
8594 "Thumb-2 STRB with reg offset should be 32-bit"
8595 );
8596
8597 let op = ArmOp::Ldrh {
8599 rd: Reg::R0,
8600 addr: MemAddr::reg(Reg::R1, Reg::R2),
8601 };
8602 let code = encoder.encode(&op).unwrap();
8603 assert_eq!(
8604 code.len(),
8605 4,
8606 "Thumb-2 LDRH with reg offset should be 32-bit"
8607 );
8608
8609 let op = ArmOp::Strh {
8611 rd: Reg::R0,
8612 addr: MemAddr::reg(Reg::R1, Reg::R2),
8613 };
8614 let code = encoder.encode(&op).unwrap();
8615 assert_eq!(
8616 code.len(),
8617 4,
8618 "Thumb-2 STRH with reg offset should be 32-bit"
8619 );
8620 }
8621
8622 #[test]
8623 fn test_encode_subword_reg_imm_offset_thumb2() {
8624 let encoder = ArmEncoder::new_thumb2();
8625
8626 let op = ArmOp::Ldrb {
8628 rd: Reg::R0,
8629 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8630 };
8631 let code = encoder.encode(&op).unwrap();
8632 assert_eq!(
8634 code.len(),
8635 8,
8636 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8637 );
8638 }
8639
8640 #[test]
8645 fn test_encode_mve_addi32_thumb2() {
8646 let encoder = ArmEncoder::new_thumb2();
8647 let op = ArmOp::MveAddI {
8648 qd: QReg::Q0,
8649 qn: QReg::Q1,
8650 qm: QReg::Q2,
8651 size: MveSize::S32,
8652 };
8653 let code = encoder.encode(&op).unwrap();
8654 assert_eq!(
8655 code.len(),
8656 4,
8657 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8658 );
8659 }
8660
8661 #[test]
8662 fn test_encode_mve_subi16_thumb2() {
8663 let encoder = ArmEncoder::new_thumb2();
8664 let op = ArmOp::MveSubI {
8665 qd: QReg::Q0,
8666 qn: QReg::Q1,
8667 qm: QReg::Q2,
8668 size: MveSize::S16,
8669 };
8670 let code = encoder.encode(&op).unwrap();
8671 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8672 }
8673
8674 #[test]
8675 fn test_encode_mve_muli8_thumb2() {
8676 let encoder = ArmEncoder::new_thumb2();
8677 let op = ArmOp::MveMulI {
8678 qd: QReg::Q0,
8679 qn: QReg::Q1,
8680 qm: QReg::Q2,
8681 size: MveSize::S8,
8682 };
8683 let code = encoder.encode(&op).unwrap();
8684 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8685 }
8686
8687 #[test]
8688 fn test_encode_mve_bitwise_thumb2() {
8689 let encoder = ArmEncoder::new_thumb2();
8690
8691 let ops = vec![
8692 ArmOp::MveAnd {
8693 qd: QReg::Q0,
8694 qn: QReg::Q1,
8695 qm: QReg::Q2,
8696 },
8697 ArmOp::MveOrr {
8698 qd: QReg::Q0,
8699 qn: QReg::Q1,
8700 qm: QReg::Q2,
8701 },
8702 ArmOp::MveEor {
8703 qd: QReg::Q0,
8704 qn: QReg::Q1,
8705 qm: QReg::Q2,
8706 },
8707 ArmOp::MveBic {
8708 qd: QReg::Q0,
8709 qn: QReg::Q1,
8710 qm: QReg::Q2,
8711 },
8712 ];
8713 for op in ops {
8714 let code = encoder.encode(&op).unwrap();
8715 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8716 }
8717 }
8718
8719 #[test]
8720 fn test_encode_mve_mvn_thumb2() {
8721 let encoder = ArmEncoder::new_thumb2();
8722 let op = ArmOp::MveMvn {
8723 qd: QReg::Q0,
8724 qm: QReg::Q1,
8725 };
8726 let code = encoder.encode(&op).unwrap();
8727 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8728 }
8729
8730 #[test]
8731 fn test_encode_mve_load_store_thumb2() {
8732 let encoder = ArmEncoder::new_thumb2();
8733
8734 let load = ArmOp::MveLoad {
8735 qd: QReg::Q0,
8736 addr: MemAddr::imm(Reg::R0, 16),
8737 };
8738 let code = encoder.encode(&load).unwrap();
8739 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8740
8741 let store = ArmOp::MveStore {
8742 qd: QReg::Q1,
8743 addr: MemAddr::imm(Reg::R1, 0),
8744 };
8745 let code = encoder.encode(&store).unwrap();
8746 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8747 }
8748
8749 #[test]
8750 fn test_encode_mve_const_thumb2() {
8751 let encoder = ArmEncoder::new_thumb2();
8752 let op = ArmOp::MveConst {
8753 qd: QReg::Q0,
8754 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8755 };
8756 let code = encoder.encode(&op).unwrap();
8757 assert!(
8760 code.len() >= 24,
8761 "MVE const should produce multiple instructions"
8762 );
8763 }
8764
8765 #[test]
8766 fn test_encode_mve_dup_thumb2() {
8767 let encoder = ArmEncoder::new_thumb2();
8768 let op = ArmOp::MveDup {
8769 qd: QReg::Q0,
8770 rn: Reg::R0,
8771 size: MveSize::S32,
8772 };
8773 let code = encoder.encode(&op).unwrap();
8774 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8775 }
8776
8777 #[test]
8778 fn test_encode_mve_extract_lane_thumb2() {
8779 let encoder = ArmEncoder::new_thumb2();
8780 let op = ArmOp::MveExtractLane {
8781 rd: Reg::R0,
8782 qn: QReg::Q1,
8783 lane: 2,
8784 size: MveSize::S32,
8785 };
8786 let code = encoder.encode(&op).unwrap();
8787 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8788 }
8789
8790 #[test]
8791 fn test_encode_mve_insert_lane_thumb2() {
8792 let encoder = ArmEncoder::new_thumb2();
8793 let op = ArmOp::MveInsertLane {
8794 qd: QReg::Q0,
8795 rn: Reg::R1,
8796 lane: 3,
8797 size: MveSize::S32,
8798 };
8799 let code = encoder.encode(&op).unwrap();
8800 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8801 }
8802
8803 #[test]
8804 fn test_encode_mve_addf32_thumb2() {
8805 let encoder = ArmEncoder::new_thumb2();
8806 let op = ArmOp::MveAddF32 {
8807 qd: QReg::Q0,
8808 qn: QReg::Q1,
8809 qm: QReg::Q2,
8810 };
8811 let code = encoder.encode(&op).unwrap();
8812 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8813 }
8814
8815 #[test]
8816 fn test_encode_mve_divf32_thumb2() {
8817 let encoder = ArmEncoder::new_thumb2();
8818 let op = ArmOp::MveDivF32 {
8819 qd: QReg::Q0,
8820 qn: QReg::Q1,
8821 qm: QReg::Q2,
8822 };
8823 let code = encoder.encode(&op).unwrap();
8824 assert_eq!(
8826 code.len(),
8827 16,
8828 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8829 );
8830 }
8831
8832 #[test]
8833 fn test_encode_mve_sqrtf32_thumb2() {
8834 let encoder = ArmEncoder::new_thumb2();
8835 let op = ArmOp::MveSqrtF32 {
8836 qd: QReg::Q0,
8837 qm: QReg::Q1,
8838 };
8839 let code = encoder.encode(&op).unwrap();
8840 assert_eq!(
8842 code.len(),
8843 16,
8844 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8845 );
8846 }
8847
8848 #[test]
8849 fn test_encode_mve_negf32_thumb2() {
8850 let encoder = ArmEncoder::new_thumb2();
8851 let op = ArmOp::MveNegF32 {
8852 qd: QReg::Q0,
8853 qm: QReg::Q1,
8854 };
8855 let code = encoder.encode(&op).unwrap();
8856 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8857 }
8858
8859 #[test]
8860 fn test_encode_mve_absf32_thumb2() {
8861 let encoder = ArmEncoder::new_thumb2();
8862 let op = ArmOp::MveAbsF32 {
8863 qd: QReg::Q0,
8864 qm: QReg::Q1,
8865 };
8866 let code = encoder.encode(&op).unwrap();
8867 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8868 }
8869
8870 #[test]
8871 fn test_encode_mve_different_qregs() {
8872 let encoder = ArmEncoder::new_thumb2();
8873
8874 let op1 = ArmOp::MveAddI {
8876 qd: QReg::Q0,
8877 qn: QReg::Q0,
8878 qm: QReg::Q0,
8879 size: MveSize::S32,
8880 };
8881 let op2 = ArmOp::MveAddI {
8882 qd: QReg::Q3,
8883 qn: QReg::Q5,
8884 qm: QReg::Q7,
8885 size: MveSize::S32,
8886 };
8887 let code1 = encoder.encode(&op1).unwrap();
8888 let code2 = encoder.encode(&op2).unwrap();
8889 assert_ne!(
8890 code1, code2,
8891 "Different Q-registers should produce different encodings"
8892 );
8893 }
8894
8895 #[test]
8896 fn test_encode_mve_arm32_nop() {
8897 let encoder = ArmEncoder::new_arm32();
8899 let op = ArmOp::MveAddI {
8900 qd: QReg::Q0,
8901 qn: QReg::Q1,
8902 qm: QReg::Q2,
8903 size: MveSize::S32,
8904 };
8905 let code = encoder.encode(&op).unwrap();
8906 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8907 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8909 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8910 }
8911}