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(&self, op: &ArmOp) -> Result<Vec<u8>> {
55 let instr: u32 = match op {
56 ArmOp::Add { rd, rn, op2 } => {
58 let rd_bits = reg_to_bits(rd);
59 let rn_bits = reg_to_bits(rn);
60 let (op2_bits, i_flag) = encode_operand2(op2);
61
62 0xE0800000 | (i_flag << 25)
65 | (rn_bits << 16)
66 | (rd_bits << 12)
67 | op2_bits
68 }
69
70 ArmOp::Sub { rd, rn, op2 } => {
71 let rd_bits = reg_to_bits(rd);
72 let rn_bits = reg_to_bits(rn);
73 let (op2_bits, i_flag) = encode_operand2(op2);
74
75 0xE0400000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
77 }
78
79 ArmOp::Adds { rd, rn, op2 } => {
81 let rd_bits = reg_to_bits(rd);
82 let rn_bits = reg_to_bits(rn);
83 let (op2_bits, i_flag) = encode_operand2(op2);
84
85 0xE0900000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
87 }
88
89 ArmOp::Adc { rd, rn, op2 } => {
90 let rd_bits = reg_to_bits(rd);
91 let rn_bits = reg_to_bits(rn);
92 let (op2_bits, i_flag) = encode_operand2(op2);
93
94 0xE0A00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
96 }
97
98 ArmOp::Subs { rd, rn, op2 } => {
99 let rd_bits = reg_to_bits(rd);
100 let rn_bits = reg_to_bits(rn);
101 let (op2_bits, i_flag) = encode_operand2(op2);
102
103 0xE0500000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
105 }
106
107 ArmOp::Sbc { rd, rn, op2 } => {
108 let rd_bits = reg_to_bits(rd);
109 let rn_bits = reg_to_bits(rn);
110 let (op2_bits, i_flag) = encode_operand2(op2);
111
112 0xE0C00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
114 }
115
116 ArmOp::Mul { rd, rn, rm } => {
117 let rd_bits = reg_to_bits(rd);
118 let rn_bits = reg_to_bits(rn);
119 let rm_bits = reg_to_bits(rm);
120
121 0xE0000090 | (rd_bits << 16) | (rn_bits << 8) | rm_bits
123 }
124
125 ArmOp::Sdiv { rd, rn, rm } => {
126 let rd_bits = reg_to_bits(rd);
127 let rn_bits = reg_to_bits(rn);
128 let rm_bits = reg_to_bits(rm);
129
130 0xE710F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
133 }
134
135 ArmOp::Udiv { rd, rn, rm } => {
136 let rd_bits = reg_to_bits(rd);
137 let rn_bits = reg_to_bits(rn);
138 let rm_bits = reg_to_bits(rm);
139
140 0xE730F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
143 }
144
145 ArmOp::Mls { rd, rn, rm, ra } => {
146 let rd_bits = reg_to_bits(rd);
147 let rn_bits = reg_to_bits(rn);
148 let rm_bits = reg_to_bits(rm);
149 let ra_bits = reg_to_bits(ra);
150
151 0xE0600090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
154 }
155
156 ArmOp::And { rd, rn, op2 } => {
157 let rd_bits = reg_to_bits(rd);
158 let rn_bits = reg_to_bits(rn);
159 let (op2_bits, i_flag) = encode_operand2(op2);
160
161 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
163 }
164
165 ArmOp::Orr { rd, rn, op2 } => {
166 let rd_bits = reg_to_bits(rd);
167 let rn_bits = reg_to_bits(rn);
168 let (op2_bits, i_flag) = encode_operand2(op2);
169
170 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
172 }
173
174 ArmOp::Eor { rd, rn, op2 } => {
175 let rd_bits = reg_to_bits(rd);
176 let rn_bits = reg_to_bits(rn);
177 let (op2_bits, i_flag) = encode_operand2(op2);
178
179 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
181 }
182
183 ArmOp::Lsl { rd, rn, shift } => {
185 let rd_bits = reg_to_bits(rd);
186 let rn_bits = reg_to_bits(rn);
187 let shift_bits = *shift & 0x1F;
188
189 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
191 }
192
193 ArmOp::Lsr { rd, rn, shift } => {
194 let rd_bits = reg_to_bits(rd);
195 let rn_bits = reg_to_bits(rn);
196 let shift_bits = *shift & 0x1F;
197
198 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
200 }
201
202 ArmOp::Asr { rd, rn, shift } => {
203 let rd_bits = reg_to_bits(rd);
204 let rn_bits = reg_to_bits(rn);
205 let shift_bits = *shift & 0x1F;
206
207 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
209 }
210
211 ArmOp::Ror { rd, rn, shift } => {
212 let rd_bits = reg_to_bits(rd);
213 let rn_bits = reg_to_bits(rn);
214 let shift_bits = *shift & 0x1F;
215
216 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
218 }
219
220 ArmOp::LslReg { rd, rn, rm } => {
223 let rd_bits = reg_to_bits(rd);
224 let rn_bits = reg_to_bits(rn);
225 let rm_bits = reg_to_bits(rm);
226 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
227 }
228 ArmOp::LsrReg { rd, rn, rm } => {
229 let rd_bits = reg_to_bits(rd);
230 let rn_bits = reg_to_bits(rn);
231 let rm_bits = reg_to_bits(rm);
232 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
233 }
234 ArmOp::AsrReg { rd, rn, rm } => {
235 let rd_bits = reg_to_bits(rd);
236 let rn_bits = reg_to_bits(rn);
237 let rm_bits = reg_to_bits(rm);
238 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
239 }
240 ArmOp::RorReg { rd, rn, rm } => {
241 let rd_bits = reg_to_bits(rd);
242 let rn_bits = reg_to_bits(rn);
243 let rm_bits = reg_to_bits(rm);
244 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
245 }
246
247 ArmOp::Rsb { rd, rn, imm } => {
249 let rd_bits = reg_to_bits(rd);
250 let rn_bits = reg_to_bits(rn);
251 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
254 }
255
256 ArmOp::Clz { rd, rm } => {
258 let rd_bits = reg_to_bits(rd);
259 let rm_bits = reg_to_bits(rm);
260
261 0xE16F0F10 | (rd_bits << 12) | rm_bits
264 }
265
266 ArmOp::Rbit { rd, rm } => {
267 let rd_bits = reg_to_bits(rd);
268 let rm_bits = reg_to_bits(rm);
269
270 0xE6FF0F30 | (rd_bits << 12) | rm_bits
273 }
274
275 ArmOp::Sxtb { rd, rm } => {
276 let rd_bits = reg_to_bits(rd);
277 let rm_bits = reg_to_bits(rm);
278
279 0xE6AF0070 | (rd_bits << 12) | rm_bits
282 }
283
284 ArmOp::Sxth { rd, rm } => {
285 let rd_bits = reg_to_bits(rd);
286 let rm_bits = reg_to_bits(rm);
287
288 0xE6BF0070 | (rd_bits << 12) | rm_bits
291 }
292
293 ArmOp::Mov { rd, op2 } => {
295 let rd_bits = reg_to_bits(rd);
296 let (op2_bits, i_flag) = encode_operand2(op2);
297
298 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
300 }
301
302 ArmOp::Mvn { rd, op2 } => {
303 let rd_bits = reg_to_bits(rd);
304 let (op2_bits, i_flag) = encode_operand2(op2);
305
306 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
308 }
309
310 ArmOp::Movw { rd, imm16 } => {
313 let rd_bits = reg_to_bits(rd);
314 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
315 let imm12 = (*imm16 as u32) & 0xFFF;
316 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
317 }
318
319 ArmOp::Movt { rd, imm16 } => {
322 let rd_bits = reg_to_bits(rd);
323 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
324 let imm12 = (*imm16 as u32) & 0xFFF;
325 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
326 }
327
328 ArmOp::Cmp { rn, op2 } => {
330 let rn_bits = reg_to_bits(rn);
331 let (op2_bits, i_flag) = encode_operand2(op2);
332
333 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
335 }
336
337 ArmOp::Cmn { rn, op2 } => {
339 let rn_bits = reg_to_bits(rn);
340 let (op2_bits, i_flag) = encode_operand2(op2);
341
342 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
344 }
345
346 ArmOp::Ldr { rd, addr } => {
348 let rd_bits = reg_to_bits(rd);
349 let (base_bits, offset_bits) = encode_mem_addr(addr);
350
351 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
354 }
355
356 ArmOp::Str { rd, addr } => {
357 let rd_bits = reg_to_bits(rd);
358 let (base_bits, offset_bits) = encode_mem_addr(addr);
359
360 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
362 }
363
364 ArmOp::Ldrb { rd, addr } => {
366 let rd_bits = reg_to_bits(rd);
367 let (base_bits, offset_bits) = encode_mem_addr(addr);
368 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
370 }
371
372 ArmOp::Ldrsb { rd, addr } => {
373 let rd_bits = reg_to_bits(rd);
374 let (base_bits, offset_bits) = encode_mem_addr(addr);
375 let offset_val = offset_bits & 0xFF;
378 let imm4h = (offset_val >> 4) & 0xF;
379 let imm4l = offset_val & 0xF;
380 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
381 }
382
383 ArmOp::Ldrh { rd, addr } => {
384 let rd_bits = reg_to_bits(rd);
385 let (base_bits, offset_bits) = encode_mem_addr(addr);
386 let offset_val = offset_bits & 0xFF;
388 let imm4h = (offset_val >> 4) & 0xF;
389 let imm4l = offset_val & 0xF;
390 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
391 }
392
393 ArmOp::Ldrsh { rd, addr } => {
394 let rd_bits = reg_to_bits(rd);
395 let (base_bits, offset_bits) = encode_mem_addr(addr);
396 let offset_val = offset_bits & 0xFF;
398 let imm4h = (offset_val >> 4) & 0xF;
399 let imm4l = offset_val & 0xF;
400 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
401 }
402
403 ArmOp::Strb { rd, addr } => {
405 let rd_bits = reg_to_bits(rd);
406 let (base_bits, offset_bits) = encode_mem_addr(addr);
407 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
409 }
410
411 ArmOp::Strh { rd, addr } => {
412 let rd_bits = reg_to_bits(rd);
413 let (base_bits, offset_bits) = encode_mem_addr(addr);
414 let offset_val = offset_bits & 0xFF;
416 let imm4h = (offset_val >> 4) & 0xF;
417 let imm4l = offset_val & 0xF;
418 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
419 }
420
421 ArmOp::MemorySize { rd } => {
423 let rd_bits = reg_to_bits(rd);
424 0xE1A00820 | (rd_bits << 12) | 0x0A }
429
430 ArmOp::MemoryGrow { rd, .. } => {
431 let rd_bits = reg_to_bits(rd);
432 0xE3E00000 | (rd_bits << 12) }
435
436 ArmOp::Label { .. } => {
438 return Ok(Vec::new());
439 }
440
441 ArmOp::B { label: _ } => {
443 0xEA000000
446 }
447
448 ArmOp::Bcc { cond, label: _ } => {
450 use synth_synthesis::Condition;
451 let cond_bits: u32 = match cond {
452 Condition::EQ => 0x0,
453 Condition::NE => 0x1,
454 Condition::HS => 0x2,
455 Condition::LO => 0x3,
456 Condition::HI => 0x8,
457 Condition::LS => 0x9,
458 Condition::GE => 0xA,
459 Condition::LT => 0xB,
460 Condition::GT => 0xC,
461 Condition::LE => 0xD,
462 };
463 (cond_bits << 28) | 0x0A000000
465 }
466
467 ArmOp::Bhs { label: _ } => {
469 0x2A000000 }
472
473 ArmOp::Blo { label: _ } => {
475 0x3A000000 }
478
479 ArmOp::BOffset { offset } => {
483 let adjusted_offset = *offset - 2; let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
490 0xEA000000 | offset_bits
491 }
492
493 ArmOp::BCondOffset { cond, offset } => {
495 use synth_synthesis::Condition;
496 let cond_bits: u32 = match cond {
497 Condition::EQ => 0x0,
498 Condition::NE => 0x1,
499 Condition::HS => 0x2,
500 Condition::LO => 0x3,
501 Condition::HI => 0x8,
502 Condition::LS => 0x9,
503 Condition::GE => 0xA,
504 Condition::LT => 0xB,
505 Condition::GT => 0xC,
506 Condition::LE => 0xD,
507 };
508 let adjusted_offset = *offset - 2; let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
511 (cond_bits << 28) | 0x0A000000 | offset_bits
512 }
513
514 ArmOp::Bl { label: _ } => {
515 0xEB000000
517 }
518
519 ArmOp::Bx { rm } => {
520 let rm_bits = reg_to_bits(rm);
521
522 0xE12FFF10 | rm_bits
524 }
525
526 ArmOp::Blx { rm } => {
527 let rm_bits = reg_to_bits(rm);
528
529 0xE12FFF30 | rm_bits
531 }
532
533 ArmOp::Push { regs } => {
534 let mut reg_list: u32 = 0;
536 for r in regs {
537 reg_list |= 1 << reg_to_bits(r);
538 }
539 0xE92D0000 | reg_list
540 }
541
542 ArmOp::Pop { regs } => {
543 let mut reg_list: u32 = 0;
545 for r in regs {
546 reg_list |= 1 << reg_to_bits(r);
547 }
548 0xE8BD0000 | reg_list
549 }
550
551 ArmOp::Nop => {
552 0xE1A00000
554 }
555
556 ArmOp::Udf { imm } => {
557 let imm8 = *imm as u32;
560 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
561 }
562
563 ArmOp::Popcnt { .. } => {
566 0xE1A00000 }
570
571 ArmOp::SetCond { .. } => {
572 0xE1A00000 }
576
577 ArmOp::SelectMove { .. } => {
578 0xE1A00000 }
582
583 ArmOp::Select { .. } => {
584 0xE1A00000 }
588
589 ArmOp::LocalGet { .. } => {
590 0xE1A00000 }
594
595 ArmOp::LocalSet { .. } => {
596 0xE1A00000 }
600
601 ArmOp::LocalTee { .. } => {
602 0xE1A00000 }
606
607 ArmOp::GlobalGet { .. } => {
608 0xE1A00000 }
612
613 ArmOp::GlobalSet { .. } => {
614 0xE1A00000 }
618
619 ArmOp::BrTable { .. } => {
620 0xE1A00000 }
624
625 ArmOp::Call { .. } => {
626 0xE1A00000 }
630
631 ArmOp::CallIndirect { .. } => {
632 0xE1A00000 }
636
637 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)?,
674 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
675 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
676 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
677 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
678 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
679 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
680
681 ArmOp::F32Ceil { sd, sm } => {
684 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
686 ArmOp::F32Floor { sd, sm } => {
687 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
689 ArmOp::F32Trunc { sd, sm } => {
690 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
692 ArmOp::F32Nearest { sd, sm } => {
693 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
695 ArmOp::F32Min { sd, sn, sm } => {
696 return self.encode_arm_f32_minmax(sd, sn, sm, true);
697 }
698 ArmOp::F32Max { sd, sn, sm } => {
699 return self.encode_arm_f32_minmax(sd, sn, sm, false);
700 }
701 ArmOp::F32Copysign { sd, sn, sm } => {
702 return self.encode_arm_f32_copysign(sd, sn, sm);
703 }
704
705 ArmOp::F32Eq { rd, sn, sm } => {
707 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
709 ArmOp::F32Ne { rd, sn, sm } => {
710 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
712 ArmOp::F32Lt { rd, sn, sm } => {
713 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
715 ArmOp::F32Le { rd, sn, sm } => {
716 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
718 ArmOp::F32Gt { rd, sn, sm } => {
719 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
721 ArmOp::F32Ge { rd, sn, sm } => {
722 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
724
725 ArmOp::F32Const { sd, value } => {
727 return self.encode_arm_f32_const(sd, *value);
728 }
729
730 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
731 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
732
733 ArmOp::F32ConvertI32S { sd, rm } => {
735 return self.encode_arm_f32_convert_i32(sd, rm, true);
736 }
737 ArmOp::F32ConvertI32U { sd, rm } => {
738 return self.encode_arm_f32_convert_i32(sd, rm, false);
739 }
740 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
741 return Err(synth_core::Error::synthesis(
742 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
743 ));
744 }
745 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
746 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
747 ArmOp::I32TruncF32S { rd, sm } => {
748 return self.encode_arm_i32_trunc_f32(rd, sm, true);
749 }
750 ArmOp::I32TruncF32U { rd, sm } => {
751 return self.encode_arm_i32_trunc_f32(rd, sm, false);
752 }
753
754 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
757 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
758 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
759 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
760 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
761 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
762 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
763
764 ArmOp::F64Ceil { dd, dm } => {
767 return self.encode_arm_f64_rounding(dd, dm, 0b01);
768 }
769 ArmOp::F64Floor { dd, dm } => {
770 return self.encode_arm_f64_rounding(dd, dm, 0b10);
771 }
772 ArmOp::F64Trunc { dd, dm } => {
773 return self.encode_arm_f64_rounding(dd, dm, 0b11);
774 }
775 ArmOp::F64Nearest { dd, dm } => {
776 return self.encode_arm_f64_rounding(dd, dm, 0b00);
777 }
778 ArmOp::F64Min { dd, dn, dm } => {
779 return self.encode_arm_f64_minmax(dd, dn, dm, true);
780 }
781 ArmOp::F64Max { dd, dn, dm } => {
782 return self.encode_arm_f64_minmax(dd, dn, dm, false);
783 }
784 ArmOp::F64Copysign { dd, dn, dm } => {
785 return self.encode_arm_f64_copysign(dd, dn, dm);
786 }
787
788 ArmOp::F64Eq { rd, dn, dm } => {
790 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
791 }
792 ArmOp::F64Ne { rd, dn, dm } => {
793 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
794 }
795 ArmOp::F64Lt { rd, dn, dm } => {
796 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
797 }
798 ArmOp::F64Le { rd, dn, dm } => {
799 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
800 }
801 ArmOp::F64Gt { rd, dn, dm } => {
802 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
803 }
804 ArmOp::F64Ge { rd, dn, dm } => {
805 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
806 }
807
808 ArmOp::F64Const { dd, value } => {
809 return self.encode_arm_f64_const(dd, *value);
810 }
811
812 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
813 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
814
815 ArmOp::F64ConvertI32S { dd, rm } => {
816 return self.encode_arm_f64_convert_i32(dd, rm, true);
817 }
818 ArmOp::F64ConvertI32U { dd, rm } => {
819 return self.encode_arm_f64_convert_i32(dd, rm, false);
820 }
821 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
822 return Err(synth_core::Error::synthesis(
823 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
824 ));
825 }
826 ArmOp::F64PromoteF32 { dd, sm } => {
827 return self.encode_arm_f64_promote_f32(dd, sm);
828 }
829 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
830 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
831 }
832 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
833 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
834 }
835 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
836 return Err(synth_core::Error::synthesis(
837 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
838 ));
839 }
840 ArmOp::I32TruncF64S { rd, dm } => {
841 return self.encode_arm_i32_trunc_f64(rd, dm, true);
842 }
843 ArmOp::I32TruncF64U { rd, dm } => {
844 return self.encode_arm_i32_trunc_f64(rd, dm, false);
845 }
846 ArmOp::I64SetCond { .. }
848 | ArmOp::I64SetCondZ { .. }
849 | ArmOp::I64Mul { .. }
850 | ArmOp::I64Shl { .. }
851 | ArmOp::I64ShrS { .. }
852 | ArmOp::I64ShrU { .. }
853 | ArmOp::I64Rotl { .. }
854 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
858 | ArmOp::MveStore { .. }
859 | ArmOp::MveConst { .. }
860 | ArmOp::MveAnd { .. }
861 | ArmOp::MveOrr { .. }
862 | ArmOp::MveEor { .. }
863 | ArmOp::MveMvn { .. }
864 | ArmOp::MveBic { .. }
865 | ArmOp::MveAddI { .. }
866 | ArmOp::MveSubI { .. }
867 | ArmOp::MveMulI { .. }
868 | ArmOp::MveNegI { .. }
869 | ArmOp::MveCmpEqI { .. }
870 | ArmOp::MveCmpNeI { .. }
871 | ArmOp::MveCmpLtS { .. }
872 | ArmOp::MveCmpLtU { .. }
873 | ArmOp::MveCmpGtS { .. }
874 | ArmOp::MveCmpGtU { .. }
875 | ArmOp::MveCmpLeS { .. }
876 | ArmOp::MveCmpLeU { .. }
877 | ArmOp::MveCmpGeS { .. }
878 | ArmOp::MveCmpGeU { .. }
879 | ArmOp::MveDup { .. }
880 | ArmOp::MveExtractLane { .. }
881 | ArmOp::MveInsertLane { .. }
882 | ArmOp::MveAddF32 { .. }
883 | ArmOp::MveSubF32 { .. }
884 | ArmOp::MveMulF32 { .. }
885 | ArmOp::MveNegF32 { .. }
886 | ArmOp::MveAbsF32 { .. }
887 | ArmOp::MveCmpEqF32 { .. }
888 | ArmOp::MveCmpNeF32 { .. }
889 | ArmOp::MveCmpLtF32 { .. }
890 | ArmOp::MveCmpLeF32 { .. }
891 | ArmOp::MveCmpGtF32 { .. }
892 | ArmOp::MveCmpGeF32 { .. }
893 | ArmOp::MveDupF32 { .. }
894 | ArmOp::MveExtractLaneF32 { .. }
895 | ArmOp::MveReplaceLaneF32 { .. }
896 | ArmOp::MveDivF32 { .. }
897 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
899
900 Ok(instr.to_le_bytes().to_vec())
902 }
903
904 fn encode_arm_f32_compare(
908 &self,
909 rd: &Reg,
910 sn: &VfpReg,
911 sm: &VfpReg,
912 cond_code: u32,
913 ) -> Result<Vec<u8>> {
914 let mut bytes = Vec::new();
915
916 let sn_num = vfp_sreg_to_num(sn)?;
918 let sm_num = vfp_sreg_to_num(sm)?;
919 let (vd, d) = encode_sreg(sn_num);
920 let (vm, m) = encode_sreg(sm_num);
921 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
922 bytes.extend_from_slice(&vcmp.to_le_bytes());
923
924 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
926
927 let rd_bits = reg_to_bits(rd);
929 let mov_zero = 0xE3A00000 | (rd_bits << 12);
930 bytes.extend_from_slice(&mov_zero.to_le_bytes());
931
932 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
934 bytes.extend_from_slice(&mov_one.to_le_bytes());
935
936 Ok(bytes)
937 }
938
939 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
941 let mut bytes = Vec::new();
942 let bits = value.to_bits();
943
944 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
949 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
950 bytes.extend_from_slice(&movw.to_le_bytes());
951
952 let hi16 = (bits >> 16) & 0xFFFF;
954 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
955 bytes.extend_from_slice(&movt.to_le_bytes());
956
957 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
959 bytes.extend_from_slice(&vmov.to_le_bytes());
960
961 Ok(bytes)
962 }
963
964 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
966 let mut bytes = Vec::new();
967
968 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
970 bytes.extend_from_slice(&vmov.to_le_bytes());
971
972 let sd_num = vfp_sreg_to_num(sd)?;
975 let (vd, d) = encode_sreg(sd_num);
976 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
978 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
979 bytes.extend_from_slice(&vcvt.to_le_bytes());
980
981 Ok(bytes)
982 }
983
984 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
996 let mut bytes = Vec::new();
997 let sm_num = vfp_sreg_to_num(sm)?;
998 let sd_num = vfp_sreg_to_num(sd)?;
999 let (vd_s, d_s) = encode_sreg(sd_num);
1000 let (vm_s, m_s) = encode_sreg(sm_num);
1001
1002 if mode == 0b11 {
1003 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1006 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1007 } else {
1008 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1013 bytes.extend_from_slice(&vmrs.to_le_bytes());
1014
1015 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1018 bytes.extend_from_slice(&bic.to_le_bytes());
1019
1020 if mode != 0 {
1022 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1024 bytes.extend_from_slice(&orr.to_le_bytes());
1025 }
1026
1027 let vmsr = 0xEEE10A10 | (rt << 12);
1029 bytes.extend_from_slice(&vmsr.to_le_bytes());
1030
1031 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1033 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1034
1035 bytes.extend_from_slice(&vmrs.to_le_bytes());
1037 bytes.extend_from_slice(&bic.to_le_bytes());
1038 bytes.extend_from_slice(&vmsr.to_le_bytes());
1039 }
1040
1041 let (vd2, d2) = encode_sreg(sd_num);
1043 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1044 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1045
1046 Ok(bytes)
1047 }
1048
1049 fn encode_arm_f32_minmax(
1051 &self,
1052 sd: &VfpReg,
1053 sn: &VfpReg,
1054 sm: &VfpReg,
1055 is_min: bool,
1056 ) -> Result<Vec<u8>> {
1057 let mut bytes = Vec::new();
1058 let sn_num = vfp_sreg_to_num(sn)?;
1059 let sm_num = vfp_sreg_to_num(sm)?;
1060 let sd_num = vfp_sreg_to_num(sd)?;
1061
1062 let (vd, d) = encode_sreg(sd_num);
1064 let (vn, n) = encode_sreg(sn_num);
1065 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1066 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1067
1068 let (vm, m) = encode_sreg(sm_num);
1070 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1071 bytes.extend_from_slice(&vcmp.to_le_bytes());
1072
1073 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1075
1076 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1079
1080 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1082 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1083
1084 Ok(bytes)
1085 }
1086
1087 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1089 let mut bytes = Vec::new();
1090
1091 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1093 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1094
1095 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1097 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1098
1099 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1103 bytes.extend_from_slice(&and_sign.to_le_bytes());
1104
1105 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1108 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1109
1110 let orr = 0xE1800000u32 | 12;
1113 bytes.extend_from_slice(&orr.to_le_bytes());
1114
1115 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1117 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1118
1119 Ok(bytes)
1120 }
1121
1122 fn encode_arm_f64_compare(
1124 &self,
1125 rd: &Reg,
1126 dn: &VfpReg,
1127 dm: &VfpReg,
1128 cond_code: u32,
1129 ) -> Result<Vec<u8>> {
1130 let mut bytes = Vec::new();
1131
1132 let dn_num = vfp_dreg_to_num(dn)?;
1134 let dm_num = vfp_dreg_to_num(dm)?;
1135 let (vd, d) = encode_dreg(dn_num);
1136 let (vm, m) = encode_dreg(dm_num);
1137 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1138 bytes.extend_from_slice(&vcmp.to_le_bytes());
1139
1140 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1142
1143 let rd_bits = reg_to_bits(rd);
1145 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1146 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1147
1148 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1150 bytes.extend_from_slice(&mov_one.to_le_bytes());
1151
1152 Ok(bytes)
1153 }
1154
1155 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1157 let mut bytes = Vec::new();
1158 let bits = value.to_bits();
1159 let lo32 = bits as u32;
1160 let hi32 = (bits >> 32) as u32;
1161
1162 let lo16 = lo32 & 0xFFFF;
1164 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1165 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1166 let hi16 = (lo32 >> 16) & 0xFFFF;
1167 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1168 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1169
1170 let lo16 = hi32 & 0xFFFF;
1172 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1173 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1174 let hi16 = (hi32 >> 16) & 0xFFFF;
1175 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1176 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1177
1178 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1180 bytes.extend_from_slice(&vmov.to_le_bytes());
1181
1182 Ok(bytes)
1183 }
1184
1185 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1187 let mut bytes = Vec::new();
1188
1189 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1191 bytes.extend_from_slice(&vmov.to_le_bytes());
1192
1193 let dd_num = vfp_dreg_to_num(dd)?;
1196 let (vd, d) = encode_dreg(dd_num);
1197 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1198 let vcvt = base | (d << 22) | (vd << 12);
1200 bytes.extend_from_slice(&vcvt.to_le_bytes());
1201
1202 Ok(bytes)
1203 }
1204
1205 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1207 let dd_num = vfp_dreg_to_num(dd)?;
1208 let sm_num = vfp_sreg_to_num(sm)?;
1209 let (vd, d) = encode_dreg(dd_num);
1210 let (vm, m) = encode_sreg(sm_num);
1211
1212 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1214 Ok(vcvt.to_le_bytes().to_vec())
1215 }
1216
1217 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1219 let mut bytes = Vec::new();
1220 let dm_num = vfp_dreg_to_num(dm)?;
1221 let (vm, m) = encode_dreg(dm_num);
1222
1223 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1226 let vcvt = base | (m << 5) | vm;
1227 bytes.extend_from_slice(&vcvt.to_le_bytes());
1228
1229 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1231 bytes.extend_from_slice(&vmov.to_le_bytes());
1232
1233 Ok(bytes)
1234 }
1235
1236 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1244 let mut bytes = Vec::new();
1245 let dm_num = vfp_dreg_to_num(dm)?;
1246 let dd_num = vfp_dreg_to_num(dd)?;
1247 let (vm, m) = encode_dreg(dm_num);
1248 let (vd, d) = encode_dreg(dd_num);
1249
1250 if mode == 0b11 {
1251 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1253 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1254 } else {
1255 let rt: u32 = 12;
1257
1258 let vmrs = 0xEEF10A10 | (rt << 12);
1260 bytes.extend_from_slice(&vmrs.to_le_bytes());
1261
1262 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1264 bytes.extend_from_slice(&bic.to_le_bytes());
1265
1266 if mode != 0 {
1268 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1269 bytes.extend_from_slice(&orr.to_le_bytes());
1270 }
1271
1272 let vmsr = 0xEEE10A10 | (rt << 12);
1274 bytes.extend_from_slice(&vmsr.to_le_bytes());
1275
1276 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1278 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1279
1280 bytes.extend_from_slice(&vmrs.to_le_bytes());
1282 bytes.extend_from_slice(&bic.to_le_bytes());
1283 bytes.extend_from_slice(&vmsr.to_le_bytes());
1284 }
1285
1286 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1288 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1289
1290 Ok(bytes)
1291 }
1292
1293 fn encode_arm_f64_minmax(
1295 &self,
1296 dd: &VfpReg,
1297 dn: &VfpReg,
1298 dm: &VfpReg,
1299 is_min: bool,
1300 ) -> Result<Vec<u8>> {
1301 let mut bytes = Vec::new();
1302 let dn_num = vfp_dreg_to_num(dn)?;
1303 let dm_num = vfp_dreg_to_num(dm)?;
1304 let dd_num = vfp_dreg_to_num(dd)?;
1305
1306 let (vd, d) = encode_dreg(dd_num);
1308 let (vn, n) = encode_dreg(dn_num);
1309 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1310 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1311
1312 let (vm, m) = encode_dreg(dm_num);
1314 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1315 bytes.extend_from_slice(&vcmp.to_le_bytes());
1316
1317 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1319
1320 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1321 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1322 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1323
1324 Ok(bytes)
1325 }
1326
1327 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1329 let mut bytes = Vec::new();
1330
1331 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1333 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1334
1335 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1338 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1339
1340 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1342 bytes.extend_from_slice(&and_sign.to_le_bytes());
1343
1344 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1346 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1347
1348 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1350 bytes.extend_from_slice(&orr.to_le_bytes());
1351
1352 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1354 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1355
1356 Ok(bytes)
1357 }
1358
1359 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1361 let mut bytes = Vec::new();
1362
1363 let sm_num = vfp_sreg_to_num(sm)?;
1366 let (vd, d) = encode_sreg(sm_num);
1367 let (vm, m) = encode_sreg(sm_num);
1368 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1369 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1370 bytes.extend_from_slice(&vcvt.to_le_bytes());
1371
1372 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1374 bytes.extend_from_slice(&vmov.to_le_bytes());
1375
1376 Ok(bytes)
1377 }
1378
1379 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1381 match op {
1384 ArmOp::Add { rd, rn, op2 } => {
1386 let rd_bits = reg_to_bits(rd) as u16;
1387 let rn_bits = reg_to_bits(rn) as u16;
1388
1389 if let Operand2::Reg(rm) = op2 {
1390 let rm_bits = reg_to_bits(rm) as u16;
1391 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1393 Ok(instr.to_le_bytes().to_vec())
1394 } else if let Operand2::Imm(imm) = op2 {
1395 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1396 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1398 Ok(instr.to_le_bytes().to_vec())
1399 } else {
1400 self.encode_thumb32_add(rd, rn, *imm as u32)
1402 }
1403 } else {
1404 self.encode_thumb32_add(rd, rn, 0)
1406 }
1407 }
1408
1409 ArmOp::Sub { rd, rn, op2 } => {
1410 let rd_bits = reg_to_bits(rd) as u16;
1411 let rn_bits = reg_to_bits(rn) as u16;
1412
1413 if let Operand2::Reg(rm) = op2 {
1414 let rm_bits = reg_to_bits(rm) as u16;
1415 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1417 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1419 Ok(instr.to_le_bytes().to_vec())
1420 } else {
1421 self.encode_thumb32_sub_reg_raw(
1423 rd_bits as u32,
1424 rn_bits as u32,
1425 rm_bits as u32,
1426 )
1427 }
1428 } else if let Operand2::Imm(imm) = op2 {
1429 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1430 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1432 Ok(instr.to_le_bytes().to_vec())
1433 } else {
1434 self.encode_thumb32_sub(rd, rn, *imm as u32)
1435 }
1436 } else {
1437 self.encode_thumb32_sub(rd, rn, 0)
1438 }
1439 }
1440
1441 ArmOp::Mov { rd, op2 } => {
1442 let rd_bits = reg_to_bits(rd) as u16;
1443
1444 if let Operand2::Imm(imm) = op2 {
1445 if *imm <= 255 && rd_bits < 8 {
1446 let imm_bits = (*imm as u16) & 0xFF;
1448 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1449 Ok(instr.to_le_bytes().to_vec())
1450 } else {
1451 self.encode_thumb32_movw(rd, *imm as u32)
1453 }
1454 } else if let Operand2::Reg(rm) = op2 {
1455 let rm_bits = reg_to_bits(rm) as u16;
1456 let d_bit = (rd_bits >> 3) & 1;
1459 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1460 Ok(instr.to_le_bytes().to_vec())
1461 } else {
1462 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1464 }
1465 }
1466
1467 ArmOp::Push { regs } => {
1468 let mut reg_list: u16 = 0;
1472 let mut need_32bit = false;
1473 for r in regs {
1474 let bit = reg_to_bits(r);
1475 if bit >= 8 && *r != Reg::LR {
1476 need_32bit = true;
1477 }
1478 reg_list |= 1 << bit;
1479 }
1480 if !need_32bit {
1481 let m_bit = if reg_list & (1 << 14) != 0 {
1483 1u16
1484 } else {
1485 0u16
1486 };
1487 let low_regs = reg_list & 0xFF;
1488 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1489 Ok(instr.to_le_bytes().to_vec())
1490 } else {
1491 let hw1: u16 = 0xE92D;
1493 let hw2: u16 = reg_list;
1494 let mut bytes = hw1.to_le_bytes().to_vec();
1495 bytes.extend_from_slice(&hw2.to_le_bytes());
1496 Ok(bytes)
1497 }
1498 }
1499
1500 ArmOp::Pop { regs } => {
1501 let mut reg_list: u16 = 0;
1505 let mut need_32bit = false;
1506 for r in regs {
1507 let bit = reg_to_bits(r);
1508 if bit >= 8 && *r != Reg::PC {
1509 need_32bit = true;
1510 }
1511 reg_list |= 1 << bit;
1512 }
1513 if !need_32bit {
1514 let p_bit = if reg_list & (1 << 15) != 0 {
1516 1u16
1517 } else {
1518 0u16
1519 };
1520 let low_regs = reg_list & 0xFF;
1521 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1522 Ok(instr.to_le_bytes().to_vec())
1523 } else {
1524 let hw1: u16 = 0xE8BD;
1526 let hw2: u16 = reg_list;
1527 let mut bytes = hw1.to_le_bytes().to_vec();
1528 bytes.extend_from_slice(&hw2.to_le_bytes());
1529 Ok(bytes)
1530 }
1531 }
1532
1533 ArmOp::Nop => {
1534 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1536 }
1537
1538 ArmOp::Udf { imm } => {
1539 let instr: u16 = 0xDE00 | (*imm as u16);
1542 let bytes = instr.to_le_bytes().to_vec();
1543 encoding_contracts::verify_thumb16(&bytes);
1544 Ok(bytes)
1545 }
1546
1547 ArmOp::Adds { rd, rn, op2 } => {
1550 let rd_bits = reg_to_bits(rd) as u16;
1551 let rn_bits = reg_to_bits(rn) as u16;
1552
1553 if let Operand2::Reg(rm) = op2 {
1554 let rm_bits = reg_to_bits(rm) as u16;
1555 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1557 Ok(instr.to_le_bytes().to_vec())
1558 } else {
1559 self.encode_thumb32_adds(rd, rn, 0)
1561 }
1562 }
1563
1564 ArmOp::Adc { rd, rn, op2 } => {
1567 let rd_bits = reg_to_bits(rd);
1568 let rn_bits = reg_to_bits(rn);
1569
1570 if let Operand2::Reg(rm) = op2 {
1571 let rm_bits = reg_to_bits(rm);
1572 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1574 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1575
1576 let mut bytes = hw1.to_le_bytes().to_vec();
1577 bytes.extend_from_slice(&hw2.to_le_bytes());
1578 Ok(bytes)
1579 } else {
1580 let hw1: u16 = (0xF140 | rn_bits) as u16;
1582 let hw2: u16 = (rd_bits << 8) as u16;
1583 let mut bytes = hw1.to_le_bytes().to_vec();
1584 bytes.extend_from_slice(&hw2.to_le_bytes());
1585 Ok(bytes)
1586 }
1587 }
1588
1589 ArmOp::Subs { rd, rn, op2 } => {
1591 let rd_bits = reg_to_bits(rd) as u16;
1592 let rn_bits = reg_to_bits(rn) as u16;
1593
1594 if let Operand2::Reg(rm) = op2 {
1595 let rm_bits = reg_to_bits(rm) as u16;
1596 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1598 Ok(instr.to_le_bytes().to_vec())
1599 } else {
1600 self.encode_thumb32_subs(rd, rn, 0)
1602 }
1603 }
1604
1605 ArmOp::Sbc { rd, rn, op2 } => {
1608 let rd_bits = reg_to_bits(rd);
1609 let rn_bits = reg_to_bits(rn);
1610
1611 if let Operand2::Reg(rm) = op2 {
1612 let rm_bits = reg_to_bits(rm);
1613 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1615 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1616
1617 let mut bytes = hw1.to_le_bytes().to_vec();
1618 bytes.extend_from_slice(&hw2.to_le_bytes());
1619 Ok(bytes)
1620 } else {
1621 let hw1: u16 = (0xF160 | rn_bits) as u16;
1623 let hw2: u16 = (rd_bits << 8) as u16;
1624 let mut bytes = hw1.to_le_bytes().to_vec();
1625 bytes.extend_from_slice(&hw2.to_le_bytes());
1626 Ok(bytes)
1627 }
1628 }
1629
1630 ArmOp::Sdiv { rd, rn, rm } => {
1634 let rd_bits = reg_to_bits(rd);
1635 let rn_bits = reg_to_bits(rn);
1636 let rm_bits = reg_to_bits(rm);
1637 encoding_contracts::verify_reg_bits(rd_bits);
1638 encoding_contracts::verify_reg_bits(rn_bits);
1639 encoding_contracts::verify_reg_bits(rm_bits);
1640
1641 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1645 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1646
1647 let mut bytes = hw1.to_le_bytes().to_vec();
1649 bytes.extend_from_slice(&hw2.to_le_bytes());
1650 encoding_contracts::verify_thumb32(&bytes);
1651 Ok(bytes)
1652 }
1653
1654 ArmOp::Udiv { rd, rn, rm } => {
1656 let rd_bits = reg_to_bits(rd);
1657 let rn_bits = reg_to_bits(rn);
1658 let rm_bits = reg_to_bits(rm);
1659 encoding_contracts::verify_reg_bits(rd_bits);
1660 encoding_contracts::verify_reg_bits(rn_bits);
1661 encoding_contracts::verify_reg_bits(rm_bits);
1662
1663 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1665 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1666
1667 let mut bytes = hw1.to_le_bytes().to_vec();
1668 bytes.extend_from_slice(&hw2.to_le_bytes());
1669 encoding_contracts::verify_thumb32(&bytes);
1670 Ok(bytes)
1671 }
1672
1673 ArmOp::Mul { rd, rn, rm } => {
1675 let rd_bits = reg_to_bits(rd);
1676 let rn_bits = reg_to_bits(rn);
1677 let rm_bits = reg_to_bits(rm);
1678
1679 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1682 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1683
1684 let mut bytes = hw1.to_le_bytes().to_vec();
1685 bytes.extend_from_slice(&hw2.to_le_bytes());
1686 Ok(bytes)
1687 }
1688
1689 ArmOp::Mls { rd, rn, rm, ra } => {
1691 let rd_bits = reg_to_bits(rd);
1692 let rn_bits = reg_to_bits(rn);
1693 let rm_bits = reg_to_bits(rm);
1694 let ra_bits = reg_to_bits(ra);
1695
1696 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1699 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1700
1701 let mut bytes = hw1.to_le_bytes().to_vec();
1702 bytes.extend_from_slice(&hw2.to_le_bytes());
1703 Ok(bytes)
1704 }
1705
1706 ArmOp::And { rd, rn, op2 } => {
1708 if let Operand2::Reg(rm) = op2 {
1709 let rd_bits = reg_to_bits(rd);
1710 let rn_bits = reg_to_bits(rn);
1711 let rm_bits = reg_to_bits(rm);
1712
1713 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1715 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1716
1717 let mut bytes = hw1.to_le_bytes().to_vec();
1718 bytes.extend_from_slice(&hw2.to_le_bytes());
1719 Ok(bytes)
1720 } else if let Operand2::Imm(imm) = op2 {
1721 let rd_bits = reg_to_bits(rd);
1722 let rn_bits = reg_to_bits(rn);
1723 let imm_val = *imm as u32;
1724
1725 let i_bit = (imm_val >> 11) & 1;
1727 let imm3 = (imm_val >> 8) & 0x7;
1728 let imm8 = imm_val & 0xFF;
1729
1730 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1731 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1732
1733 let mut bytes = hw1.to_le_bytes().to_vec();
1734 bytes.extend_from_slice(&hw2.to_le_bytes());
1735 Ok(bytes)
1736 } else {
1737 let instr: u16 = 0xBF00;
1739 Ok(instr.to_le_bytes().to_vec())
1740 }
1741 }
1742
1743 ArmOp::Orr { rd, rn, op2 } => {
1745 if let Operand2::Reg(rm) = op2 {
1746 let rd_bits = reg_to_bits(rd);
1747 let rn_bits = reg_to_bits(rn);
1748 let rm_bits = reg_to_bits(rm);
1749
1750 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1752 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1753
1754 let mut bytes = hw1.to_le_bytes().to_vec();
1755 bytes.extend_from_slice(&hw2.to_le_bytes());
1756 Ok(bytes)
1757 } else {
1758 let instr: u16 = 0xBF00;
1759 Ok(instr.to_le_bytes().to_vec())
1760 }
1761 }
1762
1763 ArmOp::Eor { rd, rn, op2 } => {
1765 if let Operand2::Reg(rm) = op2 {
1766 let rd_bits = reg_to_bits(rd);
1767 let rn_bits = reg_to_bits(rn);
1768 let rm_bits = reg_to_bits(rm);
1769
1770 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1772 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1773
1774 let mut bytes = hw1.to_le_bytes().to_vec();
1775 bytes.extend_from_slice(&hw2.to_le_bytes());
1776 Ok(bytes)
1777 } else {
1778 let instr: u16 = 0xBF00;
1779 Ok(instr.to_le_bytes().to_vec())
1780 }
1781 }
1782
1783 ArmOp::Lsl { rd, rn, shift } => {
1785 let rd_bits = reg_to_bits(rd) as u16;
1786 let rn_bits = reg_to_bits(rn) as u16;
1787 let shift_bits = (*shift as u16) & 0x1F;
1788
1789 if rd_bits < 8 && rn_bits < 8 {
1790 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1792 Ok(instr.to_le_bytes().to_vec())
1793 } else {
1794 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1797 }
1798
1799 ArmOp::Lsr { rd, rn, shift } => {
1800 let rd_bits = reg_to_bits(rd) as u16;
1801 let rn_bits = reg_to_bits(rn) as u16;
1802 let shift_bits = (*shift as u16) & 0x1F;
1803
1804 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1805 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1807 Ok(instr.to_le_bytes().to_vec())
1808 } else {
1809 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
1811 }
1812
1813 ArmOp::Asr { rd, rn, shift } => {
1814 let rd_bits = reg_to_bits(rd) as u16;
1815 let rn_bits = reg_to_bits(rn) as u16;
1816 let shift_bits = (*shift as u16) & 0x1F;
1817
1818 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1819 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1821 Ok(instr.to_le_bytes().to_vec())
1822 } else {
1823 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
1825 }
1826
1827 ArmOp::Ror { rd, rn, shift } => {
1828 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
1831
1832 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
1836 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
1837 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
1838 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
1839
1840 ArmOp::Rsb { rd, rn, imm } => {
1843 let rd_bits = reg_to_bits(rd);
1844 let rn_bits = reg_to_bits(rn);
1845 let imm_val = *imm;
1846
1847 let i_bit = (imm_val >> 11) & 1;
1848 let imm3 = (imm_val >> 8) & 0x7;
1849 let imm8 = imm_val & 0xFF;
1850
1851 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
1853 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 }
1860
1861 ArmOp::Clz { rd, rm } => {
1863 let rd_bits = reg_to_bits(rd);
1864 let rm_bits = reg_to_bits(rm);
1865
1866 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
1869 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
1870
1871 let mut bytes = hw1.to_le_bytes().to_vec();
1872 bytes.extend_from_slice(&hw2.to_le_bytes());
1873 Ok(bytes)
1874 }
1875
1876 ArmOp::Rbit { rd, rm } => {
1878 let rd_bits = reg_to_bits(rd);
1879 let rm_bits = reg_to_bits(rm);
1880
1881 let hw1: u16 = (0xFA90 | rm_bits) as u16;
1884 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
1885
1886 let mut bytes = hw1.to_le_bytes().to_vec();
1887 bytes.extend_from_slice(&hw2.to_le_bytes());
1888 Ok(bytes)
1889 }
1890
1891 ArmOp::Sxtb { rd, rm } => {
1893 let rd_bits = reg_to_bits(rd) as u16;
1894 let rm_bits = reg_to_bits(rm) as u16;
1895
1896 if rd_bits < 8 && rm_bits < 8 {
1897 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
1899 Ok(instr.to_le_bytes().to_vec())
1900 } else {
1901 let rd_bits32 = rd_bits as u32;
1904 let rm_bits32 = rm_bits as u32;
1905 let hw1: u16 = 0xFA4F;
1906 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
1907 let mut bytes = hw1.to_le_bytes().to_vec();
1908 bytes.extend_from_slice(&hw2.to_le_bytes());
1909 Ok(bytes)
1910 }
1911 }
1912
1913 ArmOp::Sxth { rd, rm } => {
1915 let rd_bits = reg_to_bits(rd) as u16;
1916 let rm_bits = reg_to_bits(rm) as u16;
1917
1918 if rd_bits < 8 && rm_bits < 8 {
1919 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
1921 Ok(instr.to_le_bytes().to_vec())
1922 } else {
1923 let rd_bits32 = rd_bits as u32;
1926 let rm_bits32 = rm_bits as u32;
1927 let hw1: u16 = 0xFA0F;
1928 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
1929 let mut bytes = hw1.to_le_bytes().to_vec();
1930 bytes.extend_from_slice(&hw2.to_le_bytes());
1931 Ok(bytes)
1932 }
1933 }
1934
1935 ArmOp::Cmp { rn, op2 } => {
1937 let rn_bits = reg_to_bits(rn) as u16;
1938
1939 if let Operand2::Imm(imm) = op2 {
1940 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
1943 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
1945 Ok(instr.to_le_bytes().to_vec())
1946 } else {
1947 self.encode_thumb32_cmp_imm(rn, *imm as u32)
1948 }
1949 } else if let Operand2::Reg(rm) = op2 {
1950 let rm_bits = reg_to_bits(rm) as u16;
1951 if rn_bits < 8 && rm_bits < 8 {
1952 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
1954 Ok(instr.to_le_bytes().to_vec())
1955 } else {
1956 let n_bit = (rn_bits >> 3) & 1;
1958 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
1959 Ok(instr.to_le_bytes().to_vec())
1960 }
1961 } else {
1962 let instr: u16 = 0xBF00;
1963 Ok(instr.to_le_bytes().to_vec())
1964 }
1965 }
1966
1967 ArmOp::Cmn { rn, op2 } => {
1970 let rn_bits = reg_to_bits(rn) as u16;
1971
1972 if let Operand2::Imm(imm) = op2 {
1973 if *imm >= 0 && *imm <= 255 {
1976 let imm8 = *imm as u16 & 0xFF;
1977 let hw1: u16 = 0xF110 | rn_bits;
1978 let hw2: u16 = 0x0F00 | imm8;
1979 let mut bytes = hw1.to_le_bytes().to_vec();
1980 bytes.extend_from_slice(&hw2.to_le_bytes());
1981 Ok(bytes)
1982 } else {
1983 Ok(vec![0xBF, 0x00])
1985 }
1986 } else if let Operand2::Reg(rm) = op2 {
1987 let rm_bits = reg_to_bits(rm) as u16;
1988 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
1990 Ok(instr.to_le_bytes().to_vec())
1991 } else {
1992 Ok(vec![0xBF, 0x00])
1993 }
1994 }
1995
1996 ArmOp::Ldr { rd, addr } => {
1998 let rd_bits = reg_to_bits(rd);
1999 let base_bits = reg_to_bits(&addr.base);
2000
2001 if let Some(offset_reg) = &addr.offset_reg {
2003 let rm_bits = reg_to_bits(offset_reg);
2004
2005 if addr.offset != 0 {
2007 let scratch = Reg::R12;
2010 let mut bytes =
2011 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2012 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2013 return Ok(bytes);
2014 }
2015
2016 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2019 let instr: u16 = 0x5800
2021 | ((rm_bits as u16) << 6)
2022 | ((base_bits as u16) << 3)
2023 | (rd_bits as u16);
2024 return Ok(instr.to_le_bytes().to_vec());
2025 }
2026
2027 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2029 }
2030
2031 let offset = addr.offset as u32;
2033
2034 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2035 let imm5 = (offset >> 2) as u16;
2037 let instr: u16 =
2038 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2039 Ok(instr.to_le_bytes().to_vec())
2040 } else {
2041 self.encode_thumb32_ldr(rd, &addr.base, offset)
2042 }
2043 }
2044
2045 ArmOp::Str { rd, addr } => {
2047 let rd_bits = reg_to_bits(rd);
2048 let base_bits = reg_to_bits(&addr.base);
2049
2050 if let Some(offset_reg) = &addr.offset_reg {
2052 let rm_bits = reg_to_bits(offset_reg);
2053
2054 if addr.offset != 0 {
2056 let scratch = Reg::R12;
2059 let mut bytes =
2060 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2061 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2062 return Ok(bytes);
2063 }
2064
2065 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2068 let instr: u16 = 0x5000
2070 | ((rm_bits as u16) << 6)
2071 | ((base_bits as u16) << 3)
2072 | (rd_bits as u16);
2073 return Ok(instr.to_le_bytes().to_vec());
2074 }
2075
2076 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2078 }
2079
2080 let offset = addr.offset as u32;
2082
2083 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2084 let imm5 = (offset >> 2) as u16;
2086 let instr: u16 =
2087 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2088 Ok(instr.to_le_bytes().to_vec())
2089 } else {
2090 self.encode_thumb32_str(rd, &addr.base, offset)
2091 }
2092 }
2093
2094 ArmOp::Ldrb { rd, addr } => {
2096 let rd_bits = reg_to_bits(rd);
2097 let base_bits = reg_to_bits(&addr.base);
2098
2099 if let Some(offset_reg) = &addr.offset_reg {
2100 if addr.offset != 0 {
2101 let scratch = Reg::R12;
2102 let mut bytes =
2103 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2104 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2105 return Ok(bytes);
2106 }
2107 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2108 }
2109
2110 let offset = addr.offset as u32;
2111 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2112 let instr: u16 = 0x7800
2114 | ((offset as u16) << 6)
2115 | ((base_bits as u16) << 3)
2116 | (rd_bits as u16);
2117 Ok(instr.to_le_bytes().to_vec())
2118 } else {
2119 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2120 }
2121 }
2122
2123 ArmOp::Ldrsb { rd, addr } => {
2125 let rd_bits = reg_to_bits(rd);
2126 let base_bits = reg_to_bits(&addr.base);
2127
2128 if let Some(offset_reg) = &addr.offset_reg {
2129 if addr.offset != 0 {
2130 let scratch = Reg::R12;
2131 let mut bytes =
2132 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2133 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2134 return Ok(bytes);
2135 }
2136 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2137 }
2138
2139 let offset = addr.offset as u32;
2140 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2143 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2145 } else {
2146 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2147 }
2148 }
2149
2150 ArmOp::Ldrh { rd, addr } => {
2152 let rd_bits = reg_to_bits(rd);
2153 let base_bits = reg_to_bits(&addr.base);
2154
2155 if let Some(offset_reg) = &addr.offset_reg {
2156 if addr.offset != 0 {
2157 let scratch = Reg::R12;
2158 let mut bytes =
2159 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2160 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2161 return Ok(bytes);
2162 }
2163 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2164 }
2165
2166 let offset = addr.offset as u32;
2167 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2168 let imm5 = (offset >> 1) as u16;
2170 let instr: u16 =
2171 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2172 Ok(instr.to_le_bytes().to_vec())
2173 } else {
2174 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2175 }
2176 }
2177
2178 ArmOp::Ldrsh { rd, addr } => {
2180 if let Some(offset_reg) = &addr.offset_reg {
2181 if addr.offset != 0 {
2182 let scratch = Reg::R12;
2183 let mut bytes =
2184 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2185 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2186 return Ok(bytes);
2187 }
2188 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2189 }
2190
2191 let offset = addr.offset as u32;
2192 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2193 }
2194
2195 ArmOp::Strb { rd, addr } => {
2197 let rd_bits = reg_to_bits(rd);
2198 let base_bits = reg_to_bits(&addr.base);
2199
2200 if let Some(offset_reg) = &addr.offset_reg {
2201 if addr.offset != 0 {
2202 let scratch = Reg::R12;
2203 let mut bytes =
2204 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2205 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2206 return Ok(bytes);
2207 }
2208 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2209 }
2210
2211 let offset = addr.offset as u32;
2212 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2213 let instr: u16 = 0x7000
2215 | ((offset as u16) << 6)
2216 | ((base_bits as u16) << 3)
2217 | (rd_bits as u16);
2218 Ok(instr.to_le_bytes().to_vec())
2219 } else {
2220 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2221 }
2222 }
2223
2224 ArmOp::Strh { rd, addr } => {
2226 let rd_bits = reg_to_bits(rd);
2227 let base_bits = reg_to_bits(&addr.base);
2228
2229 if let Some(offset_reg) = &addr.offset_reg {
2230 if addr.offset != 0 {
2231 let scratch = Reg::R12;
2232 let mut bytes =
2233 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2234 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2235 return Ok(bytes);
2236 }
2237 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2238 }
2239
2240 let offset = addr.offset as u32;
2241 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2242 let imm5 = (offset >> 1) as u16;
2244 let instr: u16 =
2245 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2246 Ok(instr.to_le_bytes().to_vec())
2247 } else {
2248 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2249 }
2250 }
2251
2252 ArmOp::MemorySize { rd } => {
2254 let rd_bits = reg_to_bits(rd);
2257 let r10_bits = reg_to_bits(&Reg::R10);
2258 if rd_bits < 8 && r10_bits < 8 {
2259 let instr: u16 =
2260 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2261 Ok(instr.to_le_bytes().to_vec())
2262 } else {
2263 let imm5: u32 = 16;
2265 let imm3 = (imm5 >> 2) & 0x7;
2266 let imm2 = imm5 & 0x3;
2267 let hw1: u16 = 0xEA4F;
2268 let hw2: u16 =
2269 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2270 let mut bytes = hw1.to_le_bytes().to_vec();
2271 bytes.extend_from_slice(&hw2.to_le_bytes());
2272 Ok(bytes)
2273 }
2274 }
2275
2276 ArmOp::MemoryGrow { rd, .. } => {
2278 let rd_bits = reg_to_bits(rd);
2282 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2285 bytes.extend_from_slice(&hw2.to_le_bytes());
2286 Ok(bytes)
2287 }
2288
2289 ArmOp::Bx { rm } => {
2291 let rm_bits = reg_to_bits(rm) as u16;
2292 let instr: u16 = 0x4700 | (rm_bits << 3);
2294 Ok(instr.to_le_bytes().to_vec())
2295 }
2296
2297 ArmOp::Blx { rm } => {
2300 let rm_bits = reg_to_bits(rm) as u16;
2301 let instr: u16 = 0x4780 | (rm_bits << 3);
2302 Ok(instr.to_le_bytes().to_vec())
2303 }
2304
2305 ArmOp::CallIndirect {
2309 rd: _,
2310 type_idx: _,
2311 table_index_reg,
2312 } => {
2313 let idx_reg = reg_to_bits(table_index_reg);
2314 let mut bytes = Vec::new();
2315
2316 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2332 bytes.extend_from_slice(&hw1.to_le_bytes());
2333 bytes.extend_from_slice(&hw2.to_le_bytes());
2334
2335 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2341 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2342
2343 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2347
2348 Ok(bytes)
2349 }
2350
2351 ArmOp::Label { .. } => Ok(Vec::new()),
2353
2354 ArmOp::Bcc { cond, label: _ } => {
2356 use synth_synthesis::Condition;
2357 let cond_bits: u16 = match cond {
2358 Condition::EQ => 0x0,
2359 Condition::NE => 0x1,
2360 Condition::HS => 0x2,
2361 Condition::LO => 0x3,
2362 Condition::HI => 0x8,
2363 Condition::LS => 0x9,
2364 Condition::GE => 0xA,
2365 Condition::LT => 0xB,
2366 Condition::GT => 0xC,
2367 Condition::LE => 0xD,
2368 };
2369 let instr: u16 = 0xD000 | (cond_bits << 8);
2371 Ok(instr.to_le_bytes().to_vec())
2372 }
2373
2374 ArmOp::B { label: _ } => {
2376 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2380 }
2381
2382 ArmOp::Bhs { label: _ } => {
2385 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2389 }
2390
2391 ArmOp::Blo { label: _ } => {
2394 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2398 }
2399
2400 ArmOp::BOffset { offset } => {
2403 let halfword_offset = *offset;
2406
2407 if (-1024..=1022).contains(&halfword_offset) {
2410 let imm11 = (halfword_offset as u16) & 0x7FF;
2412 let instr: u16 = 0xE000 | imm11;
2413 Ok(instr.to_le_bytes().to_vec())
2414 } else {
2415 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2431 let uoffset = signed_offset as u32;
2432 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;
2440 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2441
2442 let mut bytes = hw1.to_le_bytes().to_vec();
2443 bytes.extend_from_slice(&hw2.to_le_bytes());
2444 Ok(bytes)
2445 }
2446 }
2447
2448 ArmOp::BCondOffset { cond, offset } => {
2450 use synth_synthesis::Condition;
2451 let cond_bits: u16 = match cond {
2452 Condition::EQ => 0x0,
2453 Condition::NE => 0x1,
2454 Condition::HS => 0x2,
2455 Condition::LO => 0x3,
2456 Condition::HI => 0x8,
2457 Condition::LS => 0x9,
2458 Condition::GE => 0xA,
2459 Condition::LT => 0xB,
2460 Condition::GT => 0xC,
2461 Condition::LE => 0xD,
2462 };
2463
2464 let halfword_offset = *offset;
2467
2468 if (-128..=127).contains(&halfword_offset) {
2471 let imm8 = (halfword_offset as u16) & 0xFF;
2472 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2473 Ok(instr.to_le_bytes().to_vec())
2474 } else {
2475 let offset = halfword_offset >> 1;
2479 let s = if offset < 0 { 1u32 } else { 0u32 };
2480 let imm6 = ((offset >> 11) as u32) & 0x3F;
2481 let imm11 = (offset as u32) & 0x7FF;
2482 let j1 = if s == 1 { 1 } else { 0 };
2483 let j2 = if s == 1 { 1 } else { 0 };
2484
2485 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2486 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2487
2488 let mut bytes = hw1.to_le_bytes().to_vec();
2489 bytes.extend_from_slice(&hw2.to_le_bytes());
2490 Ok(bytes)
2491 }
2492 }
2493
2494 ArmOp::Bl { label: _ } => {
2495 let hw1: u16 = 0xF000;
2505 let hw2: u16 = 0xF800;
2506 let mut bytes = hw1.to_le_bytes().to_vec();
2507 bytes.extend_from_slice(&hw2.to_le_bytes());
2508 Ok(bytes)
2509 }
2510
2511 ArmOp::Mvn { rd, op2 } => {
2513 if let Operand2::Reg(rm) = op2 {
2514 let rd_bits = reg_to_bits(rd) as u16;
2515 let rm_bits = reg_to_bits(rm) as u16;
2516
2517 if rd_bits < 8 && rm_bits < 8 {
2518 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2520 Ok(instr.to_le_bytes().to_vec())
2521 } else {
2522 let hw1: u16 = 0xEA6F_u16;
2524 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2525 let mut bytes = hw1.to_le_bytes().to_vec();
2526 bytes.extend_from_slice(&hw2.to_le_bytes());
2527 Ok(bytes)
2528 }
2529 } else {
2530 let instr: u16 = 0xBF00;
2531 Ok(instr.to_le_bytes().to_vec())
2532 }
2533 }
2534
2535 ArmOp::Movw { rd, imm16 } => {
2537 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2538 }
2539
2540 ArmOp::Movt { rd, imm16 } => {
2542 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2543 }
2544
2545 ArmOp::SetCond { rd, cond } => {
2551 let rd_bits = reg_to_bits(rd) as u16;
2552
2553 use synth_synthesis::Condition;
2555 let cond_bits: u16 = match cond {
2556 Condition::EQ => 0x0,
2557 Condition::NE => 0x1,
2558 Condition::LT => 0xB,
2559 Condition::LE => 0xD,
2560 Condition::GT => 0xC,
2561 Condition::GE => 0xA,
2562 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2567
2568 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2573 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2574
2575 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2577
2578 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2580
2581 let mut bytes = ite_instr.to_le_bytes().to_vec();
2583 bytes.extend_from_slice(&mov_one.to_le_bytes());
2584 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2585 Ok(bytes)
2586 }
2587
2588 ArmOp::I64SetCond {
2593 rd,
2594 rn_lo,
2595 rn_hi,
2596 rm_lo,
2597 rm_hi,
2598 cond,
2599 } => {
2600 use synth_synthesis::Condition;
2601 let rd_bits = reg_to_bits(rd) as u16;
2602 let mut bytes = Vec::new();
2603
2604 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2606 rm: &synth_synthesis::Reg|
2607 -> Vec<u8> {
2608 let rn_bits = reg_to_bits(rn) as u16;
2609 let rm_bits = reg_to_bits(rm) as u16;
2610 if rn_bits < 8 && rm_bits < 8 {
2611 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2612 instr.to_le_bytes().to_vec()
2613 } else {
2614 let n_bit = (rn_bits >> 3) & 1;
2615 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2616 instr.to_le_bytes().to_vec()
2617 }
2618 };
2619
2620 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2622 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2623 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2624 ite_instr.to_le_bytes().to_vec()
2625 };
2626
2627 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2629 let mut b = encode_ite(cond_bits);
2630 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2631 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2632 b.extend_from_slice(&mov_one.to_le_bytes());
2633 b.extend_from_slice(&mov_zero.to_le_bytes());
2634 b
2635 };
2636
2637 match cond {
2638 Condition::EQ | Condition::NE => {
2639 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2641
2642 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2645
2646 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2648
2649 let cond_bits: u16 = match cond {
2651 Condition::EQ => 0x0,
2652 Condition::NE => 0x1,
2653 _ => unreachable!(),
2654 };
2655 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2656 }
2657
2658 Condition::LT => {
2659 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2661
2662 let rn_hi_bits = reg_to_bits(rn_hi);
2665 let rm_hi_bits = reg_to_bits(rm_hi);
2666 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2667 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2668 bytes.extend_from_slice(&hw1.to_le_bytes());
2669 bytes.extend_from_slice(&hw2.to_le_bytes());
2670
2671 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2674
2675 Condition::GT => {
2676 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2679
2680 let rm_hi_bits = reg_to_bits(rm_hi);
2682 let rn_hi_bits = reg_to_bits(rn_hi);
2683 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2684 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2685 bytes.extend_from_slice(&hw1.to_le_bytes());
2686 bytes.extend_from_slice(&hw2.to_le_bytes());
2687
2688 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2691
2692 Condition::LE => {
2693 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2697
2698 let rm_hi_bits = reg_to_bits(rm_hi);
2700 let rn_hi_bits = reg_to_bits(rn_hi);
2701 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2702 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2703 bytes.extend_from_slice(&hw1.to_le_bytes());
2704 bytes.extend_from_slice(&hw2.to_le_bytes());
2705
2706 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2709
2710 Condition::GE => {
2711 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2714
2715 let rn_hi_bits = reg_to_bits(rn_hi);
2717 let rm_hi_bits = reg_to_bits(rm_hi);
2718 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2719 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2720 bytes.extend_from_slice(&hw1.to_le_bytes());
2721 bytes.extend_from_slice(&hw2.to_le_bytes());
2722
2723 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2726
2727 Condition::LO => {
2729 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2731 let rn_hi_bits = reg_to_bits(rn_hi);
2732 let rm_hi_bits = reg_to_bits(rm_hi);
2733 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2734 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2735 bytes.extend_from_slice(&hw1.to_le_bytes());
2736 bytes.extend_from_slice(&hw2.to_le_bytes());
2737 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2739
2740 Condition::HI => {
2741 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2743 let rm_hi_bits = reg_to_bits(rm_hi);
2744 let rn_hi_bits = reg_to_bits(rn_hi);
2745 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2746 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2747 bytes.extend_from_slice(&hw1.to_le_bytes());
2748 bytes.extend_from_slice(&hw2.to_le_bytes());
2749 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2751
2752 Condition::LS => {
2753 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2755 let rm_hi_bits = reg_to_bits(rm_hi);
2756 let rn_hi_bits = reg_to_bits(rn_hi);
2757 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2758 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2759 bytes.extend_from_slice(&hw1.to_le_bytes());
2760 bytes.extend_from_slice(&hw2.to_le_bytes());
2761 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2763
2764 Condition::HS => {
2765 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2767 let rn_hi_bits = reg_to_bits(rn_hi);
2768 let rm_hi_bits = reg_to_bits(rm_hi);
2769 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2770 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2771 bytes.extend_from_slice(&hw1.to_le_bytes());
2772 bytes.extend_from_slice(&hw2.to_le_bytes());
2773 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2775 }
2776
2777 Ok(bytes)
2778 }
2779
2780 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2783 let rd_bits = reg_to_bits(rd);
2784 let rn_lo_bits = reg_to_bits(rn_lo);
2785 let rn_hi_bits = reg_to_bits(rn_hi);
2786 let mut bytes = Vec::new();
2787
2788 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2790 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2791 bytes.extend_from_slice(&hw1.to_le_bytes());
2792 bytes.extend_from_slice(&hw2.to_le_bytes());
2793
2794 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2796 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2797
2798 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2801 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2802 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2803 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2804 bytes.extend_from_slice(&mov_one.to_le_bytes());
2805 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2806
2807 Ok(bytes)
2808 }
2809
2810 ArmOp::I64Mul {
2814 rd_lo,
2815 rd_hi,
2816 rn_lo,
2817 rn_hi,
2818 rm_lo,
2819 rm_hi,
2820 } => {
2821 let rd_lo_bits = reg_to_bits(rd_lo);
2822 let rd_hi_bits = reg_to_bits(rd_hi);
2823 let rn_lo_bits = reg_to_bits(rn_lo);
2824 let rn_hi_bits = reg_to_bits(rn_hi);
2825 let rm_lo_bits = reg_to_bits(rm_lo);
2826 let rm_hi_bits = reg_to_bits(rm_hi);
2827 let r12: u32 = 12; let mut bytes = Vec::new();
2829
2830 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2833 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2834 bytes.extend_from_slice(&hw1.to_le_bytes());
2835 bytes.extend_from_slice(&hw2.to_le_bytes());
2836
2837 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2840 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
2841 bytes.extend_from_slice(&hw1.to_le_bytes());
2842 bytes.extend_from_slice(&hw2.to_le_bytes());
2843
2844 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
2847 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2848 bytes.extend_from_slice(&hw1.to_le_bytes());
2849 bytes.extend_from_slice(&hw2.to_le_bytes());
2850
2851 let d_bit = (rd_hi_bits >> 3) & 1;
2854 let add_instr: u16 =
2855 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
2856 bytes.extend_from_slice(&add_instr.to_le_bytes());
2857
2858 Ok(bytes)
2859 }
2860
2861 ArmOp::I64Shl {
2864 rd_lo,
2865 rd_hi,
2866 rn_lo,
2867 rn_hi,
2868 rm_lo,
2869 rm_hi,
2870 } => {
2871 let rd_lo_bits = reg_to_bits(rd_lo);
2872 let rd_hi_bits = reg_to_bits(rd_hi);
2873 let rn_lo_bits = reg_to_bits(rn_lo);
2874 let rn_hi_bits = reg_to_bits(rn_hi);
2875 let rm_lo_bits = reg_to_bits(rm_lo);
2876 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2878
2879 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2881 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2882 bytes.extend_from_slice(&hw1.to_le_bytes());
2883 bytes.extend_from_slice(&hw2.to_le_bytes());
2884
2885 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2887 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2888 bytes.extend_from_slice(&hw1.to_le_bytes());
2889 bytes.extend_from_slice(&hw2.to_le_bytes());
2890
2891 let bpl: u16 = 0xD50A;
2893 bytes.extend_from_slice(&bpl.to_le_bytes());
2894
2895 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2898 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2899 bytes.extend_from_slice(&hw1.to_le_bytes());
2900 bytes.extend_from_slice(&hw2.to_le_bytes());
2901
2902 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2904 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2905 bytes.extend_from_slice(&hw1.to_le_bytes());
2906 bytes.extend_from_slice(&hw2.to_le_bytes());
2907
2908 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2910 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2911 bytes.extend_from_slice(&hw1.to_le_bytes());
2912 bytes.extend_from_slice(&hw2.to_le_bytes());
2913
2914 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
2916 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
2917 bytes.extend_from_slice(&hw1.to_le_bytes());
2918 bytes.extend_from_slice(&hw2.to_le_bytes());
2919
2920 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2922 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2923 bytes.extend_from_slice(&hw1.to_le_bytes());
2924 bytes.extend_from_slice(&hw2.to_le_bytes());
2925
2926 let b_done: u16 = 0xE002;
2928 bytes.extend_from_slice(&b_done.to_le_bytes());
2929
2930 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2933 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
2934 bytes.extend_from_slice(&hw1.to_le_bytes());
2935 bytes.extend_from_slice(&hw2.to_le_bytes());
2936
2937 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
2939 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2940
2941 Ok(bytes) }
2943
2944 ArmOp::I64ShrU {
2946 rd_lo,
2947 rd_hi,
2948 rn_lo,
2949 rn_hi,
2950 rm_lo,
2951 rm_hi,
2952 } => {
2953 let rd_lo_bits = reg_to_bits(rd_lo);
2954 let rd_hi_bits = reg_to_bits(rd_hi);
2955 let rn_lo_bits = reg_to_bits(rn_lo);
2956 let rn_hi_bits = reg_to_bits(rn_hi);
2957 let rm_lo_bits = reg_to_bits(rm_lo);
2958 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2960
2961 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2963 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2964 bytes.extend_from_slice(&hw1.to_le_bytes());
2965 bytes.extend_from_slice(&hw2.to_le_bytes());
2966
2967 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2969 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2970 bytes.extend_from_slice(&hw1.to_le_bytes());
2971 bytes.extend_from_slice(&hw2.to_le_bytes());
2972
2973 let bpl: u16 = 0xD50A;
2975 bytes.extend_from_slice(&bpl.to_le_bytes());
2976
2977 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2980 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2981 bytes.extend_from_slice(&hw1.to_le_bytes());
2982 bytes.extend_from_slice(&hw2.to_le_bytes());
2983
2984 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2986 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2987 bytes.extend_from_slice(&hw1.to_le_bytes());
2988 bytes.extend_from_slice(&hw2.to_le_bytes());
2989
2990 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2992 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2993 bytes.extend_from_slice(&hw1.to_le_bytes());
2994 bytes.extend_from_slice(&hw2.to_le_bytes());
2995
2996 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
2998 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
2999 bytes.extend_from_slice(&hw1.to_le_bytes());
3000 bytes.extend_from_slice(&hw2.to_le_bytes());
3001
3002 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3004 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3005 bytes.extend_from_slice(&hw1.to_le_bytes());
3006 bytes.extend_from_slice(&hw2.to_le_bytes());
3007
3008 let b_done: u16 = 0xE002;
3010 bytes.extend_from_slice(&b_done.to_le_bytes());
3011
3012 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3015 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3016 bytes.extend_from_slice(&hw1.to_le_bytes());
3017 bytes.extend_from_slice(&hw2.to_le_bytes());
3018
3019 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3021 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3022
3023 Ok(bytes) }
3025
3026 ArmOp::I64ShrS {
3028 rd_lo,
3029 rd_hi,
3030 rn_lo,
3031 rn_hi,
3032 rm_lo,
3033 rm_hi,
3034 } => {
3035 let rd_lo_bits = reg_to_bits(rd_lo);
3036 let rd_hi_bits = reg_to_bits(rd_hi);
3037 let rn_lo_bits = reg_to_bits(rn_lo);
3038 let rn_hi_bits = reg_to_bits(rn_hi);
3039 let rm_lo_bits = reg_to_bits(rm_lo);
3040 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3042
3043 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3045 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3046 bytes.extend_from_slice(&hw1.to_le_bytes());
3047 bytes.extend_from_slice(&hw2.to_le_bytes());
3048
3049 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3051 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3052 bytes.extend_from_slice(&hw1.to_le_bytes());
3053 bytes.extend_from_slice(&hw2.to_le_bytes());
3054
3055 let bpl: u16 = 0xD50A;
3057 bytes.extend_from_slice(&bpl.to_le_bytes());
3058
3059 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3062 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3063 bytes.extend_from_slice(&hw1.to_le_bytes());
3064 bytes.extend_from_slice(&hw2.to_le_bytes());
3065
3066 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3068 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3069 bytes.extend_from_slice(&hw1.to_le_bytes());
3070 bytes.extend_from_slice(&hw2.to_le_bytes());
3071
3072 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3074 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3075 bytes.extend_from_slice(&hw1.to_le_bytes());
3076 bytes.extend_from_slice(&hw2.to_le_bytes());
3077
3078 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3080 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3081 bytes.extend_from_slice(&hw1.to_le_bytes());
3082 bytes.extend_from_slice(&hw2.to_le_bytes());
3083
3084 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3086 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3087 bytes.extend_from_slice(&hw1.to_le_bytes());
3088 bytes.extend_from_slice(&hw2.to_le_bytes());
3089
3090 let b_done: u16 = 0xE003;
3092 bytes.extend_from_slice(&b_done.to_le_bytes());
3093
3094 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3097 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3098 bytes.extend_from_slice(&hw1.to_le_bytes());
3099 bytes.extend_from_slice(&hw2.to_le_bytes());
3100
3101 let hw1: u16 = 0xEA4F;
3105 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3106 bytes.extend_from_slice(&hw1.to_le_bytes());
3107 bytes.extend_from_slice(&hw2.to_le_bytes());
3108
3109 Ok(bytes) }
3111
3112 ArmOp::I64Rotl {
3117 rdlo,
3118 rdhi,
3119 rnlo,
3120 rnhi,
3121 shift,
3122 } => {
3123 let rd_lo_bits = reg_to_bits(rdlo);
3124 let rd_hi_bits = reg_to_bits(rdhi);
3125 let rn_lo_bits = reg_to_bits(rnlo);
3126 let rn_hi_bits = reg_to_bits(rnhi);
3127 let shift_bits = reg_to_bits(shift);
3128 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3132
3133 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3135
3136 let hw1: u16 = (0xF000 | shift_bits) as u16;
3138 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3139 bytes.extend_from_slice(&hw1.to_le_bytes());
3140 bytes.extend_from_slice(&hw2.to_le_bytes());
3141
3142 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3144 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3145 bytes.extend_from_slice(&hw1.to_le_bytes());
3146 bytes.extend_from_slice(&hw2.to_le_bytes());
3147
3148 let bpl: u16 = 0xD50E;
3150 bytes.extend_from_slice(&bpl.to_le_bytes());
3151
3152 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3155 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3156 bytes.extend_from_slice(&hw1.to_le_bytes());
3157 bytes.extend_from_slice(&hw2.to_le_bytes());
3158
3159 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3161 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3162 bytes.extend_from_slice(&hw1.to_le_bytes());
3163 bytes.extend_from_slice(&hw2.to_le_bytes());
3164
3165 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3167 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3168 bytes.extend_from_slice(&hw1.to_le_bytes());
3169 bytes.extend_from_slice(&hw2.to_le_bytes());
3170
3171 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3173 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3174 bytes.extend_from_slice(&hw1.to_le_bytes());
3175 bytes.extend_from_slice(&hw2.to_le_bytes());
3176
3177 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3179 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3180 bytes.extend_from_slice(&hw1.to_le_bytes());
3181 bytes.extend_from_slice(&hw2.to_le_bytes());
3182
3183 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3185 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3186 bytes.extend_from_slice(&hw1.to_le_bytes());
3187 bytes.extend_from_slice(&hw2.to_le_bytes());
3188
3189 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3191 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3192 bytes.extend_from_slice(&hw1.to_le_bytes());
3193 bytes.extend_from_slice(&hw2.to_le_bytes());
3194
3195 let b_done: u16 = 0xE00E;
3197 bytes.extend_from_slice(&b_done.to_le_bytes());
3198
3199 let hw1: u16 = (0xF1C0 | r3) as u16;
3203 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3204 bytes.extend_from_slice(&hw1.to_le_bytes());
3205 bytes.extend_from_slice(&hw2.to_le_bytes());
3206
3207 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3209 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3210 bytes.extend_from_slice(&hw1.to_le_bytes());
3211 bytes.extend_from_slice(&hw2.to_le_bytes());
3212
3213 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3215 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3216 bytes.extend_from_slice(&hw1.to_le_bytes());
3217 bytes.extend_from_slice(&hw2.to_le_bytes());
3218
3219 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3221 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3222 bytes.extend_from_slice(&hw1.to_le_bytes());
3223 bytes.extend_from_slice(&hw2.to_le_bytes());
3224
3225 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3227 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3228 bytes.extend_from_slice(&hw1.to_le_bytes());
3229 bytes.extend_from_slice(&hw2.to_le_bytes());
3230
3231 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3233 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3234 bytes.extend_from_slice(&hw1.to_le_bytes());
3235 bytes.extend_from_slice(&hw2.to_le_bytes());
3236
3237 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3239 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3240 bytes.extend_from_slice(&hw1.to_le_bytes());
3241 bytes.extend_from_slice(&hw2.to_le_bytes());
3242
3243 let d_bit = (rd_hi_bits >> 3) & 1;
3245 let mov_instr: u16 =
3246 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3247 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3248
3249 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3251
3252 Ok(bytes) }
3254
3255 ArmOp::I64Rotr {
3260 rdlo,
3261 rdhi,
3262 rnlo,
3263 rnhi,
3264 shift,
3265 } => {
3266 let rd_lo_bits = reg_to_bits(rdlo);
3267 let rd_hi_bits = reg_to_bits(rdhi);
3268 let rn_lo_bits = reg_to_bits(rnlo);
3269 let rn_hi_bits = reg_to_bits(rnhi);
3270 let shift_bits = reg_to_bits(shift);
3271 let r12: u32 = 12;
3272 let r3: u32 = 3;
3273 let r4: u32 = 4;
3274 let mut bytes = Vec::new();
3275
3276 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3278
3279 let hw1: u16 = (0xF000 | shift_bits) as u16;
3281 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3282 bytes.extend_from_slice(&hw1.to_le_bytes());
3283 bytes.extend_from_slice(&hw2.to_le_bytes());
3284
3285 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3287 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3288 bytes.extend_from_slice(&hw1.to_le_bytes());
3289 bytes.extend_from_slice(&hw2.to_le_bytes());
3290
3291 let bpl: u16 = 0xD50E;
3293 bytes.extend_from_slice(&bpl.to_le_bytes());
3294
3295 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3298 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3299 bytes.extend_from_slice(&hw1.to_le_bytes());
3300 bytes.extend_from_slice(&hw2.to_le_bytes());
3301
3302 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3304 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3305 bytes.extend_from_slice(&hw1.to_le_bytes());
3306 bytes.extend_from_slice(&hw2.to_le_bytes());
3307
3308 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3310 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3311 bytes.extend_from_slice(&hw1.to_le_bytes());
3312 bytes.extend_from_slice(&hw2.to_le_bytes());
3313
3314 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3316 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3317 bytes.extend_from_slice(&hw1.to_le_bytes());
3318 bytes.extend_from_slice(&hw2.to_le_bytes());
3319
3320 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3322 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3323 bytes.extend_from_slice(&hw1.to_le_bytes());
3324 bytes.extend_from_slice(&hw2.to_le_bytes());
3325
3326 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3328 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3329 bytes.extend_from_slice(&hw1.to_le_bytes());
3330 bytes.extend_from_slice(&hw2.to_le_bytes());
3331
3332 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3334 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3335 bytes.extend_from_slice(&hw1.to_le_bytes());
3336 bytes.extend_from_slice(&hw2.to_le_bytes());
3337
3338 let b_done: u16 = 0xE00E;
3340 bytes.extend_from_slice(&b_done.to_le_bytes());
3341
3342 let hw1: u16 = (0xF1C0 | r3) as u16;
3345 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3346 bytes.extend_from_slice(&hw1.to_le_bytes());
3347 bytes.extend_from_slice(&hw2.to_le_bytes());
3348
3349 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3351 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3352 bytes.extend_from_slice(&hw1.to_le_bytes());
3353 bytes.extend_from_slice(&hw2.to_le_bytes());
3354
3355 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3357 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3358 bytes.extend_from_slice(&hw1.to_le_bytes());
3359 bytes.extend_from_slice(&hw2.to_le_bytes());
3360
3361 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3363 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3364 bytes.extend_from_slice(&hw1.to_le_bytes());
3365 bytes.extend_from_slice(&hw2.to_le_bytes());
3366
3367 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3369 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3370 bytes.extend_from_slice(&hw1.to_le_bytes());
3371 bytes.extend_from_slice(&hw2.to_le_bytes());
3372
3373 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3375 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3376 bytes.extend_from_slice(&hw1.to_le_bytes());
3377 bytes.extend_from_slice(&hw2.to_le_bytes());
3378
3379 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3381 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3382 bytes.extend_from_slice(&hw1.to_le_bytes());
3383 bytes.extend_from_slice(&hw2.to_le_bytes());
3384
3385 let d_bit = (rd_lo_bits >> 3) & 1;
3387 let mov_instr: u16 =
3388 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3389 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3390
3391 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3393
3394 Ok(bytes) }
3396
3397 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3411 let rd_bits = reg_to_bits(rd);
3412 let rn_lo_bits = reg_to_bits(rnlo);
3413 let rn_hi_bits = reg_to_bits(rnhi);
3414 let mut bytes = Vec::new();
3415
3416 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3418 let hw2: u16 = 0x0F00;
3419 bytes.extend_from_slice(&hw1.to_le_bytes());
3420 bytes.extend_from_slice(&hw2.to_le_bytes());
3421
3422 let beq: u16 = 0xD003;
3425 bytes.extend_from_slice(&beq.to_le_bytes());
3426
3427 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3430 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3431 bytes.extend_from_slice(&hw1.to_le_bytes());
3432 bytes.extend_from_slice(&hw2.to_le_bytes());
3433
3434 let b_done: u16 = 0xE004;
3437 bytes.extend_from_slice(&b_done.to_le_bytes());
3438
3439 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3441
3442 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3446 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3447 bytes.extend_from_slice(&hw1.to_le_bytes());
3448 bytes.extend_from_slice(&hw2.to_le_bytes());
3449
3450 let hw1: u16 = (0xF100 | rd_bits) as u16;
3452 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3453 bytes.extend_from_slice(&hw1.to_le_bytes());
3454 bytes.extend_from_slice(&hw2.to_le_bytes());
3455
3456 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3460 bytes.extend_from_slice(&mov0.to_le_bytes());
3461
3462 Ok(bytes)
3463 }
3464
3465 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3481 let rd_bits = reg_to_bits(rd);
3482 let rn_lo_bits = reg_to_bits(rnlo);
3483 let rn_hi_bits = reg_to_bits(rnhi);
3484 let mut bytes = Vec::new();
3485
3486 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3488 let hw2: u16 = 0x0F00;
3489 bytes.extend_from_slice(&hw1.to_le_bytes());
3490 bytes.extend_from_slice(&hw2.to_le_bytes());
3491
3492 let beq: u16 = 0xD005;
3495 bytes.extend_from_slice(&beq.to_le_bytes());
3496
3497 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3500 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3501 bytes.extend_from_slice(&hw1.to_le_bytes());
3502 bytes.extend_from_slice(&hw2.to_le_bytes());
3503
3504 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3507 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3508 bytes.extend_from_slice(&hw1.to_le_bytes());
3509 bytes.extend_from_slice(&hw2.to_le_bytes());
3510
3511 let b_done: u16 = 0xE006;
3514 bytes.extend_from_slice(&b_done.to_le_bytes());
3515
3516 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3518
3519 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3523 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3524 bytes.extend_from_slice(&hw1.to_le_bytes());
3525 bytes.extend_from_slice(&hw2.to_le_bytes());
3526
3527 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3530 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3531 bytes.extend_from_slice(&hw1.to_le_bytes());
3532 bytes.extend_from_slice(&hw2.to_le_bytes());
3533
3534 let hw1: u16 = (0xF100 | rd_bits) as u16;
3536 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3537 bytes.extend_from_slice(&hw1.to_le_bytes());
3538 bytes.extend_from_slice(&hw2.to_le_bytes());
3539
3540 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3543 bytes.extend_from_slice(&mov0.to_le_bytes());
3544
3545 Ok(bytes)
3546 }
3547
3548 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3552 let rd_bits = reg_to_bits(rd);
3553 let rn_lo_bits = reg_to_bits(rnlo);
3554 let rn_hi_bits = reg_to_bits(rnhi);
3555 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3558
3559 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3561
3562 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3572 bytes.extend_from_slice(&mov.to_le_bytes());
3573
3574 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3577 bytes.extend_from_slice(&mov.to_le_bytes());
3578
3579 let hw1: u16 = 0xEA4F;
3583 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3584 bytes.extend_from_slice(&hw1.to_le_bytes());
3585 bytes.extend_from_slice(&hw2.to_le_bytes());
3586
3587 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3590 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3591 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3593 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3594
3595 let hw1: u16 = (0xEA00 | r12) as u16;
3597 let hw2: u16 = ((r12 << 8) | r3) as u16;
3598 bytes.extend_from_slice(&hw1.to_le_bytes());
3599 bytes.extend_from_slice(&hw2.to_le_bytes());
3600
3601 let hw1: u16 = (0xEBA0 | 4) as u16;
3603 let hw2: u16 = ((4 << 8) | r12) as u16;
3604 bytes.extend_from_slice(&hw1.to_le_bytes());
3605 bytes.extend_from_slice(&hw2.to_le_bytes());
3606
3607 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3611 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3612 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3614 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3615
3616 let hw1: u16 = (0xEA00 | 4) as u16;
3618 let hw2: u16 = ((r12 << 8) | r3) as u16;
3619 bytes.extend_from_slice(&hw1.to_le_bytes());
3620 bytes.extend_from_slice(&hw2.to_le_bytes());
3621
3622 let hw1: u16 = 0xEA4F;
3624 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3625 bytes.extend_from_slice(&hw1.to_le_bytes());
3626 bytes.extend_from_slice(&hw2.to_le_bytes());
3627
3628 let hw1: u16 = (0xEA00 | 4) as u16;
3630 let hw2: u16 = ((4 << 8) | r3) as u16;
3631 bytes.extend_from_slice(&hw1.to_le_bytes());
3632 bytes.extend_from_slice(&hw2.to_le_bytes());
3633
3634 let hw1: u16 = (0xEB00 | 4) as u16;
3636 let hw2: u16 = ((4 << 8) | r12) as u16;
3637 bytes.extend_from_slice(&hw1.to_le_bytes());
3638 bytes.extend_from_slice(&hw2.to_le_bytes());
3639
3640 let hw1: u16 = 0xEA4F;
3645 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3646 bytes.extend_from_slice(&hw1.to_le_bytes());
3647 bytes.extend_from_slice(&hw2.to_le_bytes());
3648
3649 let hw1: u16 = (0xEB00 | 4) as u16;
3651 let hw2: u16 = ((4 << 8) | r12) as u16;
3652 bytes.extend_from_slice(&hw1.to_le_bytes());
3653 bytes.extend_from_slice(&hw2.to_le_bytes());
3654
3655 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3660 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3661 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3663 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3664
3665 let hw1: u16 = (0xEA00 | 4) as u16;
3667 let hw2: u16 = ((4 << 8) | r3) as u16;
3668 bytes.extend_from_slice(&hw1.to_le_bytes());
3669 bytes.extend_from_slice(&hw2.to_le_bytes());
3670
3671 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3675 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3676 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3678 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3679
3680 let hw1: u16 = (0xFB00 | 4) as u16;
3683 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3684 bytes.extend_from_slice(&hw1.to_le_bytes());
3685 bytes.extend_from_slice(&hw2.to_le_bytes());
3686
3687 let hw1: u16 = 0xEA4F;
3690 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3691 bytes.extend_from_slice(&hw1.to_le_bytes());
3692 bytes.extend_from_slice(&hw2.to_le_bytes());
3693
3694 let hw1: u16 = 0xEA4F;
3697 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3698 bytes.extend_from_slice(&hw1.to_le_bytes());
3699 bytes.extend_from_slice(&hw2.to_le_bytes());
3700
3701 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3703 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3704 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3705 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3706
3707 let hw1: u16 = (0xEA00 | r12) as u16;
3708 let hw2: u16 = ((r12 << 8) | r3) as u16;
3709 bytes.extend_from_slice(&hw1.to_le_bytes());
3710 bytes.extend_from_slice(&hw2.to_le_bytes());
3711
3712 let hw1: u16 = (0xEBA0 | 5) as u16;
3713 let hw2: u16 = ((5 << 8) | r12) as u16;
3714 bytes.extend_from_slice(&hw1.to_le_bytes());
3715 bytes.extend_from_slice(&hw2.to_le_bytes());
3716
3717 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3719 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3720 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3721 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3722
3723 let hw1: u16 = (0xEA00 | 5) as u16;
3724 let hw2: u16 = ((r12 << 8) | r3) as u16;
3725 bytes.extend_from_slice(&hw1.to_le_bytes());
3726 bytes.extend_from_slice(&hw2.to_le_bytes());
3727
3728 let hw1: u16 = 0xEA4F;
3729 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3730 bytes.extend_from_slice(&hw1.to_le_bytes());
3731 bytes.extend_from_slice(&hw2.to_le_bytes());
3732
3733 let hw1: u16 = (0xEA00 | 5) as u16;
3734 let hw2: u16 = ((5 << 8) | r3) as u16;
3735 bytes.extend_from_slice(&hw1.to_le_bytes());
3736 bytes.extend_from_slice(&hw2.to_le_bytes());
3737
3738 let hw1: u16 = (0xEB00 | 5) as u16;
3739 let hw2: u16 = ((5 << 8) | r12) as u16;
3740 bytes.extend_from_slice(&hw1.to_le_bytes());
3741 bytes.extend_from_slice(&hw2.to_le_bytes());
3742
3743 let hw1: u16 = 0xEA4F;
3746 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3747 bytes.extend_from_slice(&hw1.to_le_bytes());
3748 bytes.extend_from_slice(&hw2.to_le_bytes());
3749
3750 let hw1: u16 = (0xEB00 | 5) as u16;
3751 let hw2: u16 = ((5 << 8) | r12) as u16;
3752 bytes.extend_from_slice(&hw1.to_le_bytes());
3753 bytes.extend_from_slice(&hw2.to_le_bytes());
3754
3755 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3757 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3758 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3759 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3760
3761 let hw1: u16 = (0xEA00 | 5) as u16;
3762 let hw2: u16 = ((5 << 8) | r3) as u16;
3763 bytes.extend_from_slice(&hw1.to_le_bytes());
3764 bytes.extend_from_slice(&hw2.to_le_bytes());
3765
3766 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3768 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3769 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3770 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3771
3772 let hw1: u16 = (0xFB00 | 5) as u16;
3775 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3776 bytes.extend_from_slice(&hw1.to_le_bytes());
3777 bytes.extend_from_slice(&hw2.to_le_bytes());
3778
3779 let hw1: u16 = 0xEA4F;
3782 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3783 bytes.extend_from_slice(&hw1.to_le_bytes());
3784 bytes.extend_from_slice(&hw2.to_le_bytes());
3785
3786 let rd_bits_u16 = rd_bits as u16;
3789 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3790 bytes.extend_from_slice(&instr.to_le_bytes());
3791
3792 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3794
3795 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3797 bytes.extend_from_slice(&mov0.to_le_bytes());
3798
3799 Ok(bytes)
3800 }
3801
3802 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3805 let rdlo_bits = reg_to_bits(rdlo);
3806 let rdhi_bits = reg_to_bits(rdhi);
3807 let rnlo_bits = reg_to_bits(rnlo);
3808 let mut bytes = Vec::new();
3809
3810 let hw1: u16 = 0xFA4F_u16;
3813 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3814 bytes.extend_from_slice(&hw1.to_le_bytes());
3815 bytes.extend_from_slice(&hw2.to_le_bytes());
3816
3817 let hw1: u16 = 0xEA4F;
3822 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3823 bytes.extend_from_slice(&hw1.to_le_bytes());
3824 bytes.extend_from_slice(&hw2.to_le_bytes());
3825
3826 Ok(bytes)
3827 }
3828
3829 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3832 let rdlo_bits = reg_to_bits(rdlo);
3833 let rdhi_bits = reg_to_bits(rdhi);
3834 let rnlo_bits = reg_to_bits(rnlo);
3835 let mut bytes = Vec::new();
3836
3837 let hw1: u16 = 0xFA0F_u16;
3840 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3841 bytes.extend_from_slice(&hw1.to_le_bytes());
3842 bytes.extend_from_slice(&hw2.to_le_bytes());
3843
3844 let hw1: u16 = 0xEA4F;
3846 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3847 bytes.extend_from_slice(&hw1.to_le_bytes());
3848 bytes.extend_from_slice(&hw2.to_le_bytes());
3849
3850 Ok(bytes)
3851 }
3852
3853 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
3856 let rdlo_bits = reg_to_bits(rdlo);
3857 let rdhi_bits = reg_to_bits(rdhi);
3858 let rnlo_bits = reg_to_bits(rnlo);
3859 let mut bytes = Vec::new();
3860
3861 if rdlo_bits != rnlo_bits {
3863 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
3865 let mov: u16 = 0x4600
3866 | (d_bit << 7)
3867 | ((rnlo_bits as u16) << 3)
3868 | ((rdlo_bits & 0x7) as u16);
3869 bytes.extend_from_slice(&mov.to_le_bytes());
3870 }
3871
3872 let hw1: u16 = 0xEA4F;
3874 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
3875 bytes.extend_from_slice(&hw1.to_le_bytes());
3876 bytes.extend_from_slice(&hw2.to_le_bytes());
3877
3878 Ok(bytes)
3879 }
3880
3881 ArmOp::SelectMove { rd, rm, cond } => {
3884 let rd_bits = reg_to_bits(rd) as u16;
3885 let rm_bits = reg_to_bits(rm) as u16;
3886
3887 use synth_synthesis::Condition;
3889 let cond_bits: u16 = match cond {
3890 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, };
3901
3902 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
3905
3906 let d_bit = (rd_bits >> 3) & 1;
3909 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3910
3911 let mut bytes = it_instr.to_le_bytes().to_vec();
3913 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3914 Ok(bytes)
3915 }
3916
3917 ArmOp::Popcnt { rd, rm } => {
3928 let mut bytes = Vec::new();
3929
3930 if rd != rm {
3932 let rd_bits = reg_to_bits(rd) as u16;
3933 let rm_bits = reg_to_bits(rm) as u16;
3934 let d_bit = (rd_bits >> 3) & 1;
3936 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3937 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3938 }
3939
3940 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
3943 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
3944
3945 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
3948
3949 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
3951
3952 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
3954 reg_to_bits(rd),
3955 reg_to_bits(rd),
3956 11,
3957 )?);
3958
3959 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
3962 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
3963
3964 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
3966 11,
3967 reg_to_bits(rd),
3968 12,
3969 )?);
3970
3971 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
3973 reg_to_bits(rd),
3974 reg_to_bits(rd),
3975 2,
3976 )?);
3977
3978 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
3980 reg_to_bits(rd),
3981 reg_to_bits(rd),
3982 12,
3983 )?);
3984
3985 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
3987 reg_to_bits(rd),
3988 reg_to_bits(rd),
3989 11,
3990 )?);
3991
3992 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
3995
3996 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
3998 reg_to_bits(rd),
3999 reg_to_bits(rd),
4000 11,
4001 )?);
4002
4003 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4005 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4006
4007 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4009 reg_to_bits(rd),
4010 reg_to_bits(rd),
4011 12,
4012 )?);
4013
4014 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4017
4018 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4020 reg_to_bits(rd),
4021 reg_to_bits(rd),
4022 11,
4023 )?);
4024
4025 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4028
4029 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4031 reg_to_bits(rd),
4032 reg_to_bits(rd),
4033 11,
4034 )?);
4035
4036 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4039 reg_to_bits(rd),
4040 reg_to_bits(rd),
4041 0x3F,
4042 )?);
4043
4044 Ok(bytes)
4045 }
4046
4047 ArmOp::I64DivU {
4052 rdlo: _,
4053 rdhi: _,
4054 rnlo: _,
4055 rnhi: _,
4056 rmlo: _,
4057 rmhi: _,
4058 } => {
4059 let mut bytes = Vec::new();
4060
4061 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4065
4066 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());
4077 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4078
4079 let loop_start = bytes.len();
4081
4082 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4093 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());
4102 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4103 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4107 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4108
4109 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4114 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4115 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());
4146 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4147 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4150
4151 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4155 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4156
4157 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4160 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4161 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4162
4163 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4171
4172 Ok(bytes)
4173 }
4174
4175 ArmOp::I64DivS {
4180 rdlo: _,
4181 rdhi: _,
4182 rnlo: _,
4183 rnhi: _,
4184 rmlo: _,
4185 rmhi: _,
4186 } => {
4187 let mut bytes = Vec::new();
4188
4189 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4191 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4192
4193 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4196 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4197
4198 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());
4211
4212 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());
4222
4223 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4226 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4227 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4229 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4230 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4232 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4233
4234 let loop_start = bytes.len();
4235
4236 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4240 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());
4246 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4249
4250 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4254 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());
4267 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4269
4270 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4273
4274 let branch_offset_bytes = bytes.len() - loop_start + 4;
4275 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4276 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4277 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4278
4279 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());
4286 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());
4294
4295 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4297 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4298
4299 Ok(bytes)
4300 }
4301
4302 ArmOp::I64RemU {
4307 rdlo: _,
4308 rdhi: _,
4309 rnlo: _,
4310 rnhi: _,
4311 rmlo: _,
4312 rmhi: _,
4313 } => {
4314 let mut bytes = Vec::new();
4315
4316 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4318 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4319
4320 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4322 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4323 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4325 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4326 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4328 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4329
4330 let loop_start = bytes.len();
4331
4332 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4336 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());
4342 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4345
4346 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4350 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());
4363 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4365
4366 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4369
4370 let branch_offset_bytes = bytes.len() - loop_start + 4;
4371 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4372 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4373 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4374
4375 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4381 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4382
4383 Ok(bytes)
4384 }
4385
4386 ArmOp::I64RemS {
4391 rdlo: _,
4392 rdhi: _,
4393 rnlo: _,
4394 rnhi: _,
4395 rmlo: _,
4396 rmhi: _,
4397 } => {
4398 let mut bytes = Vec::new();
4399
4400 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4402 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4403
4404 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());
4418
4419 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());
4429
4430 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4433 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4434 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4436 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4437 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4439 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4440
4441 let loop_start = bytes.len();
4442
4443 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4447 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());
4453 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4456
4457 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4461 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());
4474 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4476
4477 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4480
4481 let branch_offset_bytes = bytes.len() - loop_start + 4;
4482 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4483 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4484 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4485
4486 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());
4493 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());
4501
4502 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4504 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4505
4506 Ok(bytes)
4507 }
4508
4509 ArmOp::F32Add { sd, sn, sm } => {
4512 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4513 }
4514 ArmOp::F32Sub { sd, sn, sm } => {
4515 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4516 }
4517 ArmOp::F32Mul { sd, sn, sm } => {
4518 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4519 }
4520 ArmOp::F32Div { sd, sn, sm } => {
4521 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4522 }
4523 ArmOp::F32Abs { sd, sm } => {
4524 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4525 }
4526 ArmOp::F32Neg { sd, sm } => {
4527 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4528 }
4529 ArmOp::F32Sqrt { sd, sm } => {
4530 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4531 }
4532
4533 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4536 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4537 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4538 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4539 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4540 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4541 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4542
4543 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4545 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4546 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4547 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4548 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4549 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4550
4551 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4552
4553 ArmOp::F32Load { sd, addr } => {
4554 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4555 }
4556 ArmOp::F32Store { sd, addr } => {
4557 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4558 }
4559
4560 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4561 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4562 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4563 Err(synth_core::Error::synthesis(
4564 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4565 ))
4566 }
4567 ArmOp::F32ReinterpretI32 { sd, rm } => {
4568 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4569 }
4570 ArmOp::I32ReinterpretF32 { rd, sm } => {
4571 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4572 }
4573 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4574 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4575
4576 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4579 0xEE300B00, dd, dn, dm,
4580 )?)),
4581 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4582 0xEE300B40, dd, dn, dm,
4583 )?)),
4584 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4585 0xEE200B00, dd, dn, dm,
4586 )?)),
4587 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4588 0xEE800B00, dd, dn, dm,
4589 )?)),
4590 ArmOp::F64Abs { dd, dm } => {
4591 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4592 }
4593 ArmOp::F64Neg { dd, dm } => {
4594 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4595 }
4596 ArmOp::F64Sqrt { dd, dm } => {
4597 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4598 }
4599
4600 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4603 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4604 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4605 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4606 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4607 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4608 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4609
4610 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4612 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4613 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4614 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4615 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4616 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4617
4618 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4619
4620 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4621 0xED900B00, dd, addr,
4622 )?)),
4623 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4624 0xED800B00, dd, addr,
4625 )?)),
4626
4627 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4628 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4629 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4630 Err(synth_core::Error::synthesis(
4631 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4632 ))
4633 }
4634 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4635 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4636 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4637 )),
4638 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4639 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4640 )),
4641 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4642 Err(synth_core::Error::synthesis(
4643 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4644 ))
4645 }
4646 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4647 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4648
4649 ArmOp::I64Add {
4653 rdlo,
4654 rdhi,
4655 rnlo,
4656 rnhi,
4657 rmlo,
4658 rmhi,
4659 } => {
4660 let mut bytes = Vec::new();
4661 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4663 rd: *rdlo,
4664 rn: *rnlo,
4665 op2: Operand2::Reg(*rmlo),
4666 })?);
4667 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4669 rd: *rdhi,
4670 rn: *rnhi,
4671 op2: Operand2::Reg(*rmhi),
4672 })?);
4673 Ok(bytes)
4674 }
4675
4676 ArmOp::I64Sub {
4678 rdlo,
4679 rdhi,
4680 rnlo,
4681 rnhi,
4682 rmlo,
4683 rmhi,
4684 } => {
4685 let mut bytes = Vec::new();
4686 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4688 rd: *rdlo,
4689 rn: *rnlo,
4690 op2: Operand2::Reg(*rmlo),
4691 })?);
4692 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4694 rd: *rdhi,
4695 rn: *rnhi,
4696 op2: Operand2::Reg(*rmhi),
4697 })?);
4698 Ok(bytes)
4699 }
4700
4701 ArmOp::I64And {
4703 rdlo,
4704 rdhi,
4705 rnlo,
4706 rnhi,
4707 rmlo,
4708 rmhi,
4709 } => {
4710 let mut bytes = Vec::new();
4711 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4712 rd: *rdlo,
4713 rn: *rnlo,
4714 op2: Operand2::Reg(*rmlo),
4715 })?);
4716 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4717 rd: *rdhi,
4718 rn: *rnhi,
4719 op2: Operand2::Reg(*rmhi),
4720 })?);
4721 Ok(bytes)
4722 }
4723
4724 ArmOp::I64Or {
4726 rdlo,
4727 rdhi,
4728 rnlo,
4729 rnhi,
4730 rmlo,
4731 rmhi,
4732 } => {
4733 let mut bytes = Vec::new();
4734 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4735 rd: *rdlo,
4736 rn: *rnlo,
4737 op2: Operand2::Reg(*rmlo),
4738 })?);
4739 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4740 rd: *rdhi,
4741 rn: *rnhi,
4742 op2: Operand2::Reg(*rmhi),
4743 })?);
4744 Ok(bytes)
4745 }
4746
4747 ArmOp::I64Xor {
4749 rdlo,
4750 rdhi,
4751 rnlo,
4752 rnhi,
4753 rmlo,
4754 rmhi,
4755 } => {
4756 let mut bytes = Vec::new();
4757 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4758 rd: *rdlo,
4759 rn: *rnlo,
4760 op2: Operand2::Reg(*rmlo),
4761 })?);
4762 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4763 rd: *rdhi,
4764 rn: *rnhi,
4765 op2: Operand2::Reg(*rmhi),
4766 })?);
4767 Ok(bytes)
4768 }
4769
4770 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4772 rd: *rd,
4773 rn_lo: *rnlo,
4774 rn_hi: *rnhi,
4775 }),
4776
4777 ArmOp::I64Eq {
4779 rd,
4780 rnlo,
4781 rnhi,
4782 rmlo,
4783 rmhi,
4784 } => self.encode_thumb(&ArmOp::I64SetCond {
4785 rd: *rd,
4786 rn_lo: *rnlo,
4787 rn_hi: *rnhi,
4788 rm_lo: *rmlo,
4789 rm_hi: *rmhi,
4790 cond: synth_synthesis::Condition::EQ,
4791 }),
4792
4793 ArmOp::I64Ne {
4794 rd,
4795 rnlo,
4796 rnhi,
4797 rmlo,
4798 rmhi,
4799 } => self.encode_thumb(&ArmOp::I64SetCond {
4800 rd: *rd,
4801 rn_lo: *rnlo,
4802 rn_hi: *rnhi,
4803 rm_lo: *rmlo,
4804 rm_hi: *rmhi,
4805 cond: synth_synthesis::Condition::NE,
4806 }),
4807
4808 ArmOp::I64LtS {
4809 rd,
4810 rnlo,
4811 rnhi,
4812 rmlo,
4813 rmhi,
4814 } => self.encode_thumb(&ArmOp::I64SetCond {
4815 rd: *rd,
4816 rn_lo: *rnlo,
4817 rn_hi: *rnhi,
4818 rm_lo: *rmlo,
4819 rm_hi: *rmhi,
4820 cond: synth_synthesis::Condition::LT,
4821 }),
4822
4823 ArmOp::I64LtU {
4824 rd,
4825 rnlo,
4826 rnhi,
4827 rmlo,
4828 rmhi,
4829 } => self.encode_thumb(&ArmOp::I64SetCond {
4830 rd: *rd,
4831 rn_lo: *rnlo,
4832 rn_hi: *rnhi,
4833 rm_lo: *rmlo,
4834 rm_hi: *rmhi,
4835 cond: synth_synthesis::Condition::LO,
4836 }),
4837
4838 ArmOp::I64LeS {
4839 rd,
4840 rnlo,
4841 rnhi,
4842 rmlo,
4843 rmhi,
4844 } => self.encode_thumb(&ArmOp::I64SetCond {
4845 rd: *rd,
4846 rn_lo: *rnlo,
4847 rn_hi: *rnhi,
4848 rm_lo: *rmlo,
4849 rm_hi: *rmhi,
4850 cond: synth_synthesis::Condition::LE,
4851 }),
4852
4853 ArmOp::I64LeU {
4854 rd,
4855 rnlo,
4856 rnhi,
4857 rmlo,
4858 rmhi,
4859 } => self.encode_thumb(&ArmOp::I64SetCond {
4860 rd: *rd,
4861 rn_lo: *rnlo,
4862 rn_hi: *rnhi,
4863 rm_lo: *rmlo,
4864 rm_hi: *rmhi,
4865 cond: synth_synthesis::Condition::LS,
4866 }),
4867
4868 ArmOp::I64GtS {
4869 rd,
4870 rnlo,
4871 rnhi,
4872 rmlo,
4873 rmhi,
4874 } => self.encode_thumb(&ArmOp::I64SetCond {
4875 rd: *rd,
4876 rn_lo: *rnlo,
4877 rn_hi: *rnhi,
4878 rm_lo: *rmlo,
4879 rm_hi: *rmhi,
4880 cond: synth_synthesis::Condition::GT,
4881 }),
4882
4883 ArmOp::I64GtU {
4884 rd,
4885 rnlo,
4886 rnhi,
4887 rmlo,
4888 rmhi,
4889 } => self.encode_thumb(&ArmOp::I64SetCond {
4890 rd: *rd,
4891 rn_lo: *rnlo,
4892 rn_hi: *rnhi,
4893 rm_lo: *rmlo,
4894 rm_hi: *rmhi,
4895 cond: synth_synthesis::Condition::HI,
4896 }),
4897
4898 ArmOp::I64GeS {
4899 rd,
4900 rnlo,
4901 rnhi,
4902 rmlo,
4903 rmhi,
4904 } => self.encode_thumb(&ArmOp::I64SetCond {
4905 rd: *rd,
4906 rn_lo: *rnlo,
4907 rn_hi: *rnhi,
4908 rm_lo: *rmlo,
4909 rm_hi: *rmhi,
4910 cond: synth_synthesis::Condition::GE,
4911 }),
4912
4913 ArmOp::I64GeU {
4914 rd,
4915 rnlo,
4916 rnhi,
4917 rmlo,
4918 rmhi,
4919 } => self.encode_thumb(&ArmOp::I64SetCond {
4920 rd: *rd,
4921 rn_lo: *rnlo,
4922 rn_hi: *rnhi,
4923 rm_lo: *rmlo,
4924 rm_hi: *rmhi,
4925 cond: synth_synthesis::Condition::HS,
4926 }),
4927
4928 ArmOp::I64Const { rdlo, rdhi, value } => {
4930 let lo32 = *value as u32;
4931 let hi32 = (*value >> 32) as u32;
4932 let mut bytes = Vec::new();
4933 bytes.extend_from_slice(
4935 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
4936 );
4937 if lo32 > 0xFFFF {
4938 bytes.extend_from_slice(
4939 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
4940 );
4941 }
4942 bytes.extend_from_slice(
4944 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
4945 );
4946 if hi32 > 0xFFFF {
4947 bytes.extend_from_slice(
4948 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
4949 );
4950 }
4951 Ok(bytes)
4952 }
4953
4954 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
4956 let mut bytes = Vec::new();
4957 let offset = if addr.offset < 0 {
4958 0u32
4959 } else {
4960 addr.offset as u32
4961 };
4962 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
4963 bytes.extend_from_slice(&self.encode_thumb32_ldr(
4964 rdhi,
4965 &addr.base,
4966 offset.wrapping_add(4),
4967 )?);
4968 Ok(bytes)
4969 }
4970
4971 ArmOp::I64Str { rdlo, rdhi, addr } => {
4973 let mut bytes = Vec::new();
4974 let offset = if addr.offset < 0 {
4975 0u32
4976 } else {
4977 addr.offset as u32
4978 };
4979 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
4980 bytes.extend_from_slice(&self.encode_thumb32_str(
4981 rdhi,
4982 &addr.base,
4983 offset.wrapping_add(4),
4984 )?);
4985 Ok(bytes)
4986 }
4987
4988 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
4990 let mut bytes = Vec::new();
4991 if rdlo != rn {
4992 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
4994 rd: *rdlo,
4995 op2: Operand2::Reg(*rn),
4996 })?);
4997 }
4998 bytes.extend_from_slice(
5000 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5002 Ok(bytes)
5003 }
5004
5005 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5007 let mut bytes = Vec::new();
5008 if rdlo != rn {
5009 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5011 rd: *rdlo,
5012 op2: Operand2::Reg(*rn),
5013 })?);
5014 }
5015 let rdhi_bits = reg_to_bits(rdhi) as u16;
5017 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5018 bytes.extend_from_slice(&instr.to_le_bytes());
5019 Ok(bytes)
5020 }
5021
5022 ArmOp::I32WrapI64 { rd, rnlo } => {
5024 if rd == rnlo {
5025 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5028 } else {
5029 self.encode_thumb(&ArmOp::Mov {
5031 rd: *rd,
5032 op2: Operand2::Reg(*rnlo),
5033 })
5034 }
5035 }
5036
5037 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5039 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5040 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5041 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5042 0xEF000150, qd, qn, qm,
5043 ))),
5044 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5045 0xEF200150, qd, qn, qm,
5046 ))),
5047 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5048 0xFF000150, qd, qn, qm,
5049 ))),
5050 ArmOp::MveMvn { qd, qm } => {
5051 let qd_enc = qreg_to_num(qd);
5053 let qm_enc = qreg_to_num(qm);
5054 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5055 Ok(vfp_to_thumb_bytes(instr))
5056 }
5057 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5058 0xEF100150, qd, qn, qm,
5059 ))),
5060 ArmOp::MveAddI { qd, qn, qm, size } => {
5061 let sz = mve_size_bits(size);
5062 let base: u32 = 0xEF000840 | (sz << 20);
5063 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5064 }
5065 ArmOp::MveSubI { qd, qn, qm, size } => {
5066 let sz = mve_size_bits(size);
5067 let base: u32 = 0xFF000840 | (sz << 20);
5068 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5069 }
5070 ArmOp::MveMulI { qd, qn, qm, size } => {
5071 let sz = mve_size_bits(size);
5072 let base: u32 = 0xEF000950 | (sz << 20);
5073 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5074 }
5075 ArmOp::MveNegI { qd, qm, size } => {
5076 let sz = mve_size_bits(size);
5077 let qd_enc = qreg_to_num(qd);
5079 let qm_enc = qreg_to_num(qm);
5080 let base: u32 = 0xFFB103C0 | (sz << 18);
5081 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5082 Ok(vfp_to_thumb_bytes(instr))
5083 }
5084 ArmOp::MveDup { qd, rn, size } => {
5085 let sz = mve_size_bits(size);
5086 let qd_enc = qreg_to_num(qd);
5087 let rn_bits = reg_to_bits(rn);
5088 let be = match sz {
5091 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5095 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5096 Ok(vfp_to_thumb_bytes(instr))
5097 }
5098 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5099 let qn_enc = qreg_to_num(qn);
5100 let rd_bits = reg_to_bits(rd);
5101 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5104 let lane_in_d = (*lane as u32) & 1;
5105 let _sz = mve_size_bits(size);
5106 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5108 Ok(vfp_to_thumb_bytes(instr))
5109 }
5110 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5111 let qd_enc = qreg_to_num(qd);
5112 let rn_bits = reg_to_bits(rn);
5113 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5114 let lane_in_d = (*lane as u32) & 1;
5115 let _sz = mve_size_bits(size);
5116 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5118 Ok(vfp_to_thumb_bytes(instr))
5119 }
5120
5121 ArmOp::MveCmpEqI { qd, qn, qm, size }
5123 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5124 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5125 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5126 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5127 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5128 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5129 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5130 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5131 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5132 let sz = mve_size_bits(size);
5135 let base: u32 = 0xEF000840 | (sz << 20);
5136 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5137 }
5138
5139 ArmOp::MveAddF32 { qd, qn, qm } => {
5141 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5143 }
5144 ArmOp::MveSubF32 { qd, qn, qm } => {
5145 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5147 }
5148 ArmOp::MveMulF32 { qd, qn, qm } => {
5149 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5151 }
5152 ArmOp::MveNegF32 { qd, qm } => {
5153 let qd_enc = qreg_to_num(qd);
5154 let qm_enc = qreg_to_num(qm);
5155 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5157 Ok(vfp_to_thumb_bytes(instr))
5158 }
5159 ArmOp::MveAbsF32 { qd, qm } => {
5160 let qd_enc = qreg_to_num(qd);
5161 let qm_enc = qreg_to_num(qm);
5162 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5164 Ok(vfp_to_thumb_bytes(instr))
5165 }
5166 ArmOp::MveCmpEqF32 { qd, qn, qm }
5167 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5168 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5169 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5170 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5171 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5172 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5174 }
5175 ArmOp::MveDupF32 { qd, rn } => {
5176 let qd_enc = qreg_to_num(qd);
5177 let rn_bits = reg_to_bits(rn);
5178 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5180 Ok(vfp_to_thumb_bytes(instr))
5181 }
5182 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5183 let qn_enc = qreg_to_num(qn);
5184 let rd_bits = reg_to_bits(rd);
5185 let s_num = qn_enc * 4 + (*lane as u32);
5187 let (vn, n) = encode_sreg(s_num);
5188 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5189 Ok(vfp_to_thumb_bytes(instr))
5190 }
5191 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5192 let qd_enc = qreg_to_num(qd);
5193 let rn_bits = reg_to_bits(rn);
5194 let s_num = qd_enc * 4 + (*lane as u32);
5196 let (vn, n) = encode_sreg(s_num);
5197 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5198 Ok(vfp_to_thumb_bytes(instr))
5199 }
5200 ArmOp::MveDivF32 { qd, qn, qm } => {
5201 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5203 }
5204 ArmOp::MveSqrtF32 { qd, qm } => {
5205 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5207 }
5208
5209 _ => {
5211 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5213 }
5214 }
5215 }
5216
5217 fn encode_thumb_f32_compare(
5221 &self,
5222 rd: &Reg,
5223 sn: &VfpReg,
5224 sm: &VfpReg,
5225 cond_code: u32,
5226 ) -> Result<Vec<u8>> {
5227 let mut bytes = Vec::new();
5228 let rd_bits = reg_to_bits(rd);
5229
5230 let sn_num = vfp_sreg_to_num(sn)?;
5232 let sm_num = vfp_sreg_to_num(sm)?;
5233 let (vd, d) = encode_sreg(sn_num);
5234 let (vm, m) = encode_sreg(sm_num);
5235 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5236 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5237
5238 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5240
5241 if rd_bits < 8 {
5243 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5244 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5245 } else {
5246 let hw1: u16 = 0xF04F;
5248 let hw2: u16 = (rd_bits as u16) << 8;
5249 bytes.extend_from_slice(&hw1.to_le_bytes());
5250 bytes.extend_from_slice(&hw2.to_le_bytes());
5251 }
5252
5253 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5257 bytes.extend_from_slice(&it.to_le_bytes());
5258
5259 if rd_bits < 8 {
5261 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5262 bytes.extend_from_slice(&mov_one.to_le_bytes());
5263 } else {
5264 let hw1: u16 = 0xF04F;
5266 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5267 bytes.extend_from_slice(&hw1.to_le_bytes());
5268 bytes.extend_from_slice(&hw2.to_le_bytes());
5269 }
5270
5271 Ok(bytes)
5272 }
5273
5274 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5276 let mut bytes = Vec::new();
5277 let bits = value.to_bits();
5278 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5283 let imm4 = (lo16 >> 12) & 0xF;
5284 let i_bit = (lo16 >> 11) & 1;
5285 let imm3 = (lo16 >> 8) & 0x7;
5286 let imm8 = lo16 & 0xFF;
5287 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5288 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5289 bytes.extend_from_slice(&hw1.to_le_bytes());
5290 bytes.extend_from_slice(&hw2.to_le_bytes());
5291
5292 let hi16 = (bits >> 16) & 0xFFFF;
5294 let imm4 = (hi16 >> 12) & 0xF;
5295 let i_bit = (hi16 >> 11) & 1;
5296 let imm3 = (hi16 >> 8) & 0x7;
5297 let imm8 = hi16 & 0xFF;
5298 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5299 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5300 bytes.extend_from_slice(&hw1.to_le_bytes());
5301 bytes.extend_from_slice(&hw2.to_le_bytes());
5302
5303 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5305 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5306
5307 Ok(bytes)
5308 }
5309
5310 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5312 let mut bytes = Vec::new();
5313
5314 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5316 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5317
5318 let sd_num = vfp_sreg_to_num(sd)?;
5320 let (vd, d) = encode_sreg(sd_num);
5321 let (vm, m) = encode_sreg(sd_num);
5322 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5323 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5324 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5325
5326 Ok(bytes)
5327 }
5328
5329 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5337 let mut bytes = Vec::new();
5338 let sm_num = vfp_sreg_to_num(sm)?;
5339 let sd_num = vfp_sreg_to_num(sd)?;
5340 let (vd_s, d_s) = encode_sreg(sd_num);
5341 let (vm_s, m_s) = encode_sreg(sm_num);
5342
5343 if mode == 0b11 {
5344 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5346 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5347 } else {
5348 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5353 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5354
5355 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5361 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5362 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5363
5364 if mode != 0 {
5366 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5368 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5369 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5370 }
5371
5372 let vmsr = 0xEEE10A10 | (rt << 12);
5374 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5375
5376 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5378 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5379
5380 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5382 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5383 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5384 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5385 }
5386
5387 let (vd2, d2) = encode_sreg(sd_num);
5389 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5390 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5391
5392 Ok(bytes)
5393 }
5394
5395 fn encode_thumb_f32_minmax(
5397 &self,
5398 sd: &VfpReg,
5399 sn: &VfpReg,
5400 sm: &VfpReg,
5401 is_min: bool,
5402 ) -> Result<Vec<u8>> {
5403 let mut bytes = Vec::new();
5404 let sn_num = vfp_sreg_to_num(sn)?;
5405 let sm_num = vfp_sreg_to_num(sm)?;
5406 let sd_num = vfp_sreg_to_num(sd)?;
5407
5408 let (vd, d) = encode_sreg(sd_num);
5410 let (vn, n) = encode_sreg(sn_num);
5411 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5412 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5413
5414 let (vm, m) = encode_sreg(sm_num);
5416 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5417 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5418
5419 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5421
5422 let cond: u16 = if is_min { 0xC } else { 0x4 };
5424 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5425 bytes.extend_from_slice(&it.to_le_bytes());
5426
5427 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5429 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5430
5431 Ok(bytes)
5432 }
5433
5434 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5436 let mut bytes = Vec::new();
5437
5438 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5440 false,
5441 sm,
5442 &Reg::R12,
5443 )?));
5444
5445 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5447 false,
5448 sn,
5449 &Reg::R0,
5450 )?));
5451
5452 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5464 bytes.extend_from_slice(&hw2.to_le_bytes());
5465
5466 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5470 bytes.extend_from_slice(&hw2.to_le_bytes());
5471
5472 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5476 bytes.extend_from_slice(&hw2.to_le_bytes());
5477
5478 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5480 true,
5481 sd,
5482 &Reg::R0,
5483 )?));
5484
5485 Ok(bytes)
5486 }
5487
5488 fn encode_thumb_f64_compare(
5490 &self,
5491 rd: &Reg,
5492 dn: &VfpReg,
5493 dm: &VfpReg,
5494 cond_code: u32,
5495 ) -> Result<Vec<u8>> {
5496 let mut bytes = Vec::new();
5497 let rd_bits = reg_to_bits(rd);
5498
5499 let dn_num = vfp_dreg_to_num(dn)?;
5501 let dm_num = vfp_dreg_to_num(dm)?;
5502 let (vd, d) = encode_dreg(dn_num);
5503 let (vm, m) = encode_dreg(dm_num);
5504 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5505 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5506
5507 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5509
5510 if rd_bits < 8 {
5512 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5513 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5514 } else {
5515 let hw1: u16 = 0xF04F;
5516 let hw2: u16 = (rd_bits as u16) << 8;
5517 bytes.extend_from_slice(&hw1.to_le_bytes());
5518 bytes.extend_from_slice(&hw2.to_le_bytes());
5519 }
5520
5521 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5523 bytes.extend_from_slice(&it.to_le_bytes());
5524
5525 if rd_bits < 8 {
5527 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5528 bytes.extend_from_slice(&mov_one.to_le_bytes());
5529 } else {
5530 let hw1: u16 = 0xF04F;
5531 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5532 bytes.extend_from_slice(&hw1.to_le_bytes());
5533 bytes.extend_from_slice(&hw2.to_le_bytes());
5534 }
5535
5536 Ok(bytes)
5537 }
5538
5539 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5541 let mut bytes = Vec::new();
5542 let bits = value.to_bits();
5543 let lo32 = bits as u32;
5544 let hi32 = (bits >> 32) as u32;
5545
5546 let lo16 = lo32 & 0xFFFF;
5548 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5549
5550 let hi16 = (lo32 >> 16) & 0xFFFF;
5552 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5553
5554 let lo16 = hi32 & 0xFFFF;
5556 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5557
5558 let hi16 = (hi32 >> 16) & 0xFFFF;
5560 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5561
5562 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5564 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5565
5566 Ok(bytes)
5567 }
5568
5569 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5571 let mut bytes = Vec::new();
5572
5573 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5575 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5576
5577 let dd_num = vfp_dreg_to_num(dd)?;
5579 let (vd, d) = encode_dreg(dd_num);
5580 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5581 let vcvt = base | (d << 22) | (vd << 12);
5582 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5583
5584 Ok(bytes)
5585 }
5586
5587 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5589 let dd_num = vfp_dreg_to_num(dd)?;
5590 let sm_num = vfp_sreg_to_num(sm)?;
5591 let (vd, d) = encode_dreg(dd_num);
5592 let (vm, m) = encode_sreg(sm_num);
5593
5594 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5595 Ok(vfp_to_thumb_bytes(vcvt))
5596 }
5597
5598 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5600 let mut bytes = Vec::new();
5601 let dm_num = vfp_dreg_to_num(dm)?;
5602 let (vm, m) = encode_dreg(dm_num);
5603
5604 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5606 let vcvt = base | (m << 5) | vm;
5607 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5608
5609 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5611 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5612
5613 Ok(bytes)
5614 }
5615
5616 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5620 let mut bytes = Vec::new();
5621 let dm_num = vfp_dreg_to_num(dm)?;
5622 let dd_num = vfp_dreg_to_num(dd)?;
5623 let (vm, m) = encode_dreg(dm_num);
5624 let (vd, d) = encode_dreg(dd_num);
5625
5626 if mode == 0b11 {
5627 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5629 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5630 } else {
5631 let rt: u32 = 12;
5632
5633 let vmrs = 0xEEF10A10 | (rt << 12);
5635 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5636
5637 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5639 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5640 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5641 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5642
5643 if mode != 0 {
5645 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5646 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5647 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5648 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5649 }
5650
5651 let vmsr = 0xEEE10A10 | (rt << 12);
5653 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5654
5655 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5657 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5658
5659 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5661 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5662 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5663 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5664 }
5665
5666 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5668 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5669
5670 Ok(bytes)
5671 }
5672
5673 fn encode_thumb_f64_minmax(
5675 &self,
5676 dd: &VfpReg,
5677 dn: &VfpReg,
5678 dm: &VfpReg,
5679 is_min: bool,
5680 ) -> Result<Vec<u8>> {
5681 let mut bytes = Vec::new();
5682 let dn_num = vfp_dreg_to_num(dn)?;
5683 let dm_num = vfp_dreg_to_num(dm)?;
5684 let dd_num = vfp_dreg_to_num(dd)?;
5685
5686 let (vd, d) = encode_dreg(dd_num);
5688 let (vn, n) = encode_dreg(dn_num);
5689 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5690 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5691
5692 let (vm, m) = encode_dreg(dm_num);
5694 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5695 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5696
5697 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5699
5700 let cond: u16 = if is_min { 0xC } else { 0x4 };
5702 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5703 bytes.extend_from_slice(&it.to_le_bytes());
5704
5705 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5707 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5708
5709 Ok(bytes)
5710 }
5711
5712 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5714 let mut bytes = Vec::new();
5715
5716 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5718 false,
5719 dm,
5720 &Reg::R0,
5721 &Reg::R12,
5722 )?));
5723
5724 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5726 false,
5727 dn,
5728 &Reg::R1,
5729 &Reg::R2,
5730 )?));
5731
5732 let hw1: u16 = 0xF000 | 12;
5734 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5735 bytes.extend_from_slice(&hw1.to_le_bytes());
5736 bytes.extend_from_slice(&hw2.to_le_bytes());
5737
5738 let hw1: u16 = 0xF020 | 2;
5740 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5741 bytes.extend_from_slice(&hw1.to_le_bytes());
5742 bytes.extend_from_slice(&hw2.to_le_bytes());
5743
5744 let hw1: u16 = 0xEA40 | 2;
5746 let hw2: u16 = (2 << 8) | 12;
5747 bytes.extend_from_slice(&hw1.to_le_bytes());
5748 bytes.extend_from_slice(&hw2.to_le_bytes());
5749
5750 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5752 true,
5753 dd,
5754 &Reg::R1,
5755 &Reg::R2,
5756 )?));
5757
5758 Ok(bytes)
5759 }
5760
5761 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5763 let mut bytes = Vec::new();
5764
5765 let sm_num = vfp_sreg_to_num(sm)?;
5766 let (vd, d) = encode_sreg(sm_num);
5767 let (vm, m) = encode_sreg(sm_num);
5768 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5769 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5770 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5771
5772 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5774 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5775
5776 Ok(bytes)
5777 }
5778
5779 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5783 let rd_bits = reg_to_bits(rd);
5784 let rn_bits = reg_to_bits(rn);
5785
5786 let i_bit = (imm >> 11) & 1;
5790 let imm3 = (imm >> 8) & 0x7;
5791 let imm8 = imm & 0xFF;
5792
5793 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5794 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5795
5796 let mut bytes = hw1.to_le_bytes().to_vec();
5797 bytes.extend_from_slice(&hw2.to_le_bytes());
5798 Ok(bytes)
5799 }
5800
5801 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5803 let rd_bits = reg_to_bits(rd);
5804 let rn_bits = reg_to_bits(rn);
5805
5806 let i_bit = (imm >> 11) & 1;
5807 let imm3 = (imm >> 8) & 0x7;
5808 let imm8 = imm & 0xFF;
5809
5810 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5811 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5812
5813 let mut bytes = hw1.to_le_bytes().to_vec();
5814 bytes.extend_from_slice(&hw2.to_le_bytes());
5815 Ok(bytes)
5816 }
5817
5818 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5820 let rd_bits = reg_to_bits(rd);
5821 let rn_bits = reg_to_bits(rn);
5822
5823 let i_bit = (imm >> 11) & 1;
5824 let imm3 = (imm >> 8) & 0x7;
5825 let imm8 = imm & 0xFF;
5826
5827 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5830 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5831
5832 let mut bytes = hw1.to_le_bytes().to_vec();
5833 bytes.extend_from_slice(&hw2.to_le_bytes());
5834 Ok(bytes)
5835 }
5836
5837 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5839 let rd_bits = reg_to_bits(rd);
5840 let rn_bits = reg_to_bits(rn);
5841
5842 let i_bit = (imm >> 11) & 1;
5843 let imm3 = (imm >> 8) & 0x7;
5844 let imm8 = imm & 0xFF;
5845
5846 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5849 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5850
5851 let mut bytes = hw1.to_le_bytes().to_vec();
5852 bytes.extend_from_slice(&hw2.to_le_bytes());
5853 Ok(bytes)
5854 }
5855
5856 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
5865 let rd_bits = reg_to_bits(rd);
5866 encoding_contracts::verify_reg_bits(rd_bits);
5867 let imm16 = imm & 0xFFFF;
5868
5869 let imm4 = (imm16 >> 12) & 0xF;
5872 let i_bit = (imm16 >> 11) & 1;
5873 let imm3 = (imm16 >> 8) & 0x7;
5874 let imm8 = imm16 & 0xFF;
5875
5876 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5877 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5878
5879 let mut bytes = hw1.to_le_bytes().to_vec();
5880 bytes.extend_from_slice(&hw2.to_le_bytes());
5881 encoding_contracts::verify_thumb32(&bytes);
5882 Ok(bytes)
5883 }
5884
5885 fn encode_thumb32_shift(
5893 &self,
5894 rd: &Reg,
5895 rm: &Reg,
5896 shift: u32,
5897 shift_type: u8,
5898 ) -> Result<Vec<u8>> {
5899 let rd_bits = reg_to_bits(rd);
5900 let rm_bits = reg_to_bits(rm);
5901 encoding_contracts::verify_reg_bits(rd_bits);
5902 encoding_contracts::verify_reg_bits(rm_bits);
5903 let imm5 = shift & 0x1F;
5904 let imm2 = imm5 & 0x3;
5905 let imm3 = (imm5 >> 2) & 0x7;
5906
5907 let hw1: u16 = 0xEA4F;
5910 let hw2: u16 =
5911 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
5912 as u16;
5913
5914 let mut bytes = hw1.to_le_bytes().to_vec();
5915 bytes.extend_from_slice(&hw2.to_le_bytes());
5916 Ok(bytes)
5917 }
5918
5919 fn encode_thumb32_shift_reg(
5923 &self,
5924 rd: &Reg,
5925 rn: &Reg,
5926 rm: &Reg,
5927 shift_type: u8,
5928 ) -> Result<Vec<u8>> {
5929 let rd_bits = reg_to_bits(rd);
5930 let rn_bits = reg_to_bits(rn);
5931 let rm_bits = reg_to_bits(rm);
5932
5933 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
5935 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
5937
5938 let mut bytes = hw1.to_le_bytes().to_vec();
5939 bytes.extend_from_slice(&hw2.to_le_bytes());
5940 Ok(bytes)
5941 }
5942
5943 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5945 let rn_bits = reg_to_bits(rn);
5946
5947 let i_bit = (imm >> 11) & 1;
5948 let imm3 = (imm >> 8) & 0x7;
5949 let imm8 = imm & 0xFF;
5950
5951 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5953 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
5954
5955 let mut bytes = hw1.to_le_bytes().to_vec();
5956 bytes.extend_from_slice(&hw2.to_le_bytes());
5957 Ok(bytes)
5958 }
5959
5960 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
5962 let rd_bits = reg_to_bits(rd);
5963 let base_bits = reg_to_bits(base);
5964
5965 let hw1: u16 = (0xF8D0 | base_bits) as u16;
5967 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) 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_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
5976 let rd_bits = reg_to_bits(rd);
5977 let base_bits = reg_to_bits(base);
5978
5979 let hw1: u16 = (0xF8C0 | base_bits) as u16;
5981 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
5982
5983 let mut bytes = hw1.to_le_bytes().to_vec();
5984 bytes.extend_from_slice(&hw2.to_le_bytes());
5985 Ok(bytes)
5986 }
5987
5988 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
5990 let rd_bits = reg_to_bits(rd);
5991 let base_bits = reg_to_bits(base);
5992 let rm_bits = reg_to_bits(offset_reg);
5993
5994 let hw1: u16 = (0xF850 | base_bits) as u16;
5998 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
5999
6000 let mut bytes = hw1.to_le_bytes().to_vec();
6001 bytes.extend_from_slice(&hw2.to_le_bytes());
6002 Ok(bytes)
6003 }
6004
6005 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6007 let rd_bits = reg_to_bits(rd);
6008 let base_bits = reg_to_bits(base);
6009 let rm_bits = reg_to_bits(offset_reg);
6010
6011 let hw1: u16 = (0xF840 | base_bits) as u16;
6015 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6016
6017 let mut bytes = hw1.to_le_bytes().to_vec();
6018 bytes.extend_from_slice(&hw2.to_le_bytes());
6019 Ok(bytes)
6020 }
6021
6022 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6026 let rd_bits = reg_to_bits(rd);
6027 let base_bits = reg_to_bits(base);
6028 let hw1: u16 = (0xF890 | base_bits) as u16;
6030 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6031 let mut bytes = hw1.to_le_bytes().to_vec();
6032 bytes.extend_from_slice(&hw2.to_le_bytes());
6033 Ok(bytes)
6034 }
6035
6036 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6038 let rd_bits = reg_to_bits(rd);
6039 let base_bits = reg_to_bits(base);
6040 let rm_bits = reg_to_bits(offset_reg);
6041 let hw1: u16 = (0xF810 | base_bits) as u16;
6043 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6044 let mut bytes = hw1.to_le_bytes().to_vec();
6045 bytes.extend_from_slice(&hw2.to_le_bytes());
6046 Ok(bytes)
6047 }
6048
6049 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6051 let rd_bits = reg_to_bits(rd);
6052 let base_bits = reg_to_bits(base);
6053 let hw1: u16 = (0xF990 | base_bits) as u16;
6055 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6056 let mut bytes = hw1.to_le_bytes().to_vec();
6057 bytes.extend_from_slice(&hw2.to_le_bytes());
6058 Ok(bytes)
6059 }
6060
6061 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6063 let rd_bits = reg_to_bits(rd);
6064 let base_bits = reg_to_bits(base);
6065 let rm_bits = reg_to_bits(offset_reg);
6066 let hw1: u16 = (0xF910 | base_bits) as u16;
6068 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6069 let mut bytes = hw1.to_le_bytes().to_vec();
6070 bytes.extend_from_slice(&hw2.to_le_bytes());
6071 Ok(bytes)
6072 }
6073
6074 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6076 let rd_bits = reg_to_bits(rd);
6077 let base_bits = reg_to_bits(base);
6078 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6080 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6081 let mut bytes = hw1.to_le_bytes().to_vec();
6082 bytes.extend_from_slice(&hw2.to_le_bytes());
6083 Ok(bytes)
6084 }
6085
6086 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6088 let rd_bits = reg_to_bits(rd);
6089 let base_bits = reg_to_bits(base);
6090 let rm_bits = reg_to_bits(offset_reg);
6091 let hw1: u16 = (0xF830 | base_bits) as u16;
6093 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
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_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6101 let rd_bits = reg_to_bits(rd);
6102 let base_bits = reg_to_bits(base);
6103 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6105 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6106 let mut bytes = hw1.to_le_bytes().to_vec();
6107 bytes.extend_from_slice(&hw2.to_le_bytes());
6108 Ok(bytes)
6109 }
6110
6111 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6113 let rd_bits = reg_to_bits(rd);
6114 let base_bits = reg_to_bits(base);
6115 let rm_bits = reg_to_bits(offset_reg);
6116 let hw1: u16 = (0xF930 | base_bits) as u16;
6118 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6119 let mut bytes = hw1.to_le_bytes().to_vec();
6120 bytes.extend_from_slice(&hw2.to_le_bytes());
6121 Ok(bytes)
6122 }
6123
6124 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6126 let rd_bits = reg_to_bits(rd);
6127 let base_bits = reg_to_bits(base);
6128 let hw1: u16 = (0xF880 | base_bits) as u16;
6130 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6131 let mut bytes = hw1.to_le_bytes().to_vec();
6132 bytes.extend_from_slice(&hw2.to_le_bytes());
6133 Ok(bytes)
6134 }
6135
6136 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6138 let rd_bits = reg_to_bits(rd);
6139 let base_bits = reg_to_bits(base);
6140 let rm_bits = reg_to_bits(offset_reg);
6141 let hw1: u16 = (0xF800 | base_bits) as u16;
6143 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6144 let mut bytes = hw1.to_le_bytes().to_vec();
6145 bytes.extend_from_slice(&hw2.to_le_bytes());
6146 Ok(bytes)
6147 }
6148
6149 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6151 let rd_bits = reg_to_bits(rd);
6152 let base_bits = reg_to_bits(base);
6153 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6155 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
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_strh_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 let hw1: u16 = (0xF820 | base_bits) as u16;
6168 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6169 let mut bytes = hw1.to_le_bytes().to_vec();
6170 bytes.extend_from_slice(&hw2.to_le_bytes());
6171 Ok(bytes)
6172 }
6173
6174 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6176 let rd_bits = reg_to_bits(rd);
6177 let rn_bits = reg_to_bits(rn);
6178
6179 if imm <= 0xFFF {
6185 let i_bit = (imm >> 11) & 1;
6186 let imm3 = (imm >> 8) & 0x7;
6187 let imm8 = imm & 0xFF;
6188
6189 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6190 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6191
6192 let mut bytes = hw1.to_le_bytes().to_vec();
6193 bytes.extend_from_slice(&hw2.to_le_bytes());
6194 Ok(bytes)
6195 } else {
6196 Err(synth_core::Error::synthesis(
6199 "ADD immediate too large for single instruction",
6200 ))
6201 }
6202 }
6203
6204 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6214 encoding_contracts::verify_reg_bits(rd);
6215 encoding_contracts::verify_imm16(imm16);
6216 let imm16 = imm16 & 0xFFFF;
6219 let imm4 = (imm16 >> 12) & 0xF;
6220 let i_bit = (imm16 >> 11) & 1;
6221 let imm3 = (imm16 >> 8) & 0x7;
6222 let imm8 = imm16 & 0xFF;
6223
6224 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6225 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6226
6227 let mut bytes = hw1.to_le_bytes().to_vec();
6228 bytes.extend_from_slice(&hw2.to_le_bytes());
6229 encoding_contracts::verify_thumb32(&bytes);
6230 Ok(bytes)
6231 }
6232
6233 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6241 encoding_contracts::verify_reg_bits(rd);
6242 encoding_contracts::verify_imm16(imm16);
6243 let imm16 = imm16 & 0xFFFF;
6246 let imm4 = (imm16 >> 12) & 0xF;
6247 let i_bit = (imm16 >> 11) & 1;
6248 let imm3 = (imm16 >> 8) & 0x7;
6249 let imm8 = imm16 & 0xFF;
6250
6251 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6252 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6253
6254 let mut bytes = hw1.to_le_bytes().to_vec();
6255 bytes.extend_from_slice(&hw2.to_le_bytes());
6256 encoding_contracts::verify_thumb32(&bytes);
6257 Ok(bytes)
6258 }
6259
6260 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6262 let imm5 = shift & 0x1F;
6265 let imm2 = imm5 & 0x3;
6266 let imm3 = (imm5 >> 2) & 0x7;
6267
6268 let hw1: u16 = 0xEA4F;
6269 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6270
6271 let mut bytes = hw1.to_le_bytes().to_vec();
6272 bytes.extend_from_slice(&hw2.to_le_bytes());
6273 Ok(bytes)
6274 }
6275
6276 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6278 let hw1: u16 = (0xEA00 | rn) as u16;
6281 let hw2: u16 = ((rd << 8) | rm) as u16;
6282
6283 let mut bytes = hw1.to_le_bytes().to_vec();
6284 bytes.extend_from_slice(&hw2.to_le_bytes());
6285 Ok(bytes)
6286 }
6287
6288 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6290 let i_bit = (imm >> 11) & 1;
6294 let imm3 = (imm >> 8) & 0x7;
6295 let imm8 = imm & 0xFF;
6296
6297 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6298 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6299
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_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6307 let hw1: u16 = (0xEBA0 | rn) as u16;
6310 let hw2: u16 = ((rd << 8) | rm) as u16;
6311
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_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6319 let hw1: u16 = (0xEB00 | rn) as u16;
6322 let hw2: u16 = ((rd << 8) | rm) as u16;
6323
6324 let mut bytes = hw1.to_le_bytes().to_vec();
6325 bytes.extend_from_slice(&hw2.to_le_bytes());
6326 Ok(bytes)
6327 }
6328
6329 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6331 let mut code = Vec::new();
6332
6333 for op in ops {
6334 let encoded = self.encode(op)?;
6335 code.extend_from_slice(&encoded);
6336 }
6337
6338 Ok(code)
6339 }
6340}
6341
6342fn reg_to_bits(reg: &Reg) -> u32 {
6344 match reg {
6345 Reg::R0 => 0,
6346 Reg::R1 => 1,
6347 Reg::R2 => 2,
6348 Reg::R3 => 3,
6349 Reg::R4 => 4,
6350 Reg::R5 => 5,
6351 Reg::R6 => 6,
6352 Reg::R7 => 7,
6353 Reg::R8 => 8,
6354 Reg::R9 => 9,
6355 Reg::R10 => 10,
6356 Reg::R11 => 11,
6357 Reg::R12 => 12,
6358 Reg::SP => 13,
6359 Reg::LR => 14,
6360 Reg::PC => 15,
6361 }
6362}
6363
6364fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6367 if val == 0 {
6368 return Some((0, 1));
6369 }
6370 for rot in 0..16u32 {
6371 let shift = rot * 2;
6372 let unrotated = val.rotate_left(shift);
6374 if unrotated <= 0xFF {
6375 return Some(((rot << 8) | unrotated, 1));
6377 }
6378 }
6379 None
6380}
6381
6382fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6387 match op2 {
6388 Operand2::Imm(val) => {
6389 let uval = *val as u32;
6390 if let Some(encoded) = try_encode_rotated_imm(uval) {
6392 encoded
6393 } else {
6394 let imm = uval & 0xFF;
6399 (imm, 1)
6400 }
6401 }
6402
6403 Operand2::Reg(reg) => {
6404 let reg_bits = reg_to_bits(reg);
6405 (reg_bits, 0) }
6407
6408 Operand2::RegShift {
6409 rm,
6410 shift: _,
6411 amount,
6412 } => {
6413 let rm_bits = reg_to_bits(rm);
6415 let shift_bits = (*amount & 0x1F) << 7;
6416 (shift_bits | rm_bits, 0)
6417 }
6418 }
6419}
6420
6421fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6423 let base_bits = reg_to_bits(&addr.base);
6424 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6426}
6427
6428fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6430 match reg {
6431 VfpReg::S0 => Ok(0),
6432 VfpReg::S1 => Ok(1),
6433 VfpReg::S2 => Ok(2),
6434 VfpReg::S3 => Ok(3),
6435 VfpReg::S4 => Ok(4),
6436 VfpReg::S5 => Ok(5),
6437 VfpReg::S6 => Ok(6),
6438 VfpReg::S7 => Ok(7),
6439 VfpReg::S8 => Ok(8),
6440 VfpReg::S9 => Ok(9),
6441 VfpReg::S10 => Ok(10),
6442 VfpReg::S11 => Ok(11),
6443 VfpReg::S12 => Ok(12),
6444 VfpReg::S13 => Ok(13),
6445 VfpReg::S14 => Ok(14),
6446 VfpReg::S15 => Ok(15),
6447 VfpReg::S16 => Ok(16),
6448 VfpReg::S17 => Ok(17),
6449 VfpReg::S18 => Ok(18),
6450 VfpReg::S19 => Ok(19),
6451 VfpReg::S20 => Ok(20),
6452 VfpReg::S21 => Ok(21),
6453 VfpReg::S22 => Ok(22),
6454 VfpReg::S23 => Ok(23),
6455 VfpReg::S24 => Ok(24),
6456 VfpReg::S25 => Ok(25),
6457 VfpReg::S26 => Ok(26),
6458 VfpReg::S27 => Ok(27),
6459 VfpReg::S28 => Ok(28),
6460 VfpReg::S29 => Ok(29),
6461 VfpReg::S30 => Ok(30),
6462 VfpReg::S31 => Ok(31),
6463 _ => Err(synth_core::Error::SynthesisError(
6465 "D-register not supported in single-precision VFP encoding".to_string(),
6466 )),
6467 }
6468}
6469
6470fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6472 match reg {
6473 VfpReg::D0 => Ok(0),
6474 VfpReg::D1 => Ok(1),
6475 VfpReg::D2 => Ok(2),
6476 VfpReg::D3 => Ok(3),
6477 VfpReg::D4 => Ok(4),
6478 VfpReg::D5 => Ok(5),
6479 VfpReg::D6 => Ok(6),
6480 VfpReg::D7 => Ok(7),
6481 VfpReg::D8 => Ok(8),
6482 VfpReg::D9 => Ok(9),
6483 VfpReg::D10 => Ok(10),
6484 VfpReg::D11 => Ok(11),
6485 VfpReg::D12 => Ok(12),
6486 VfpReg::D13 => Ok(13),
6487 VfpReg::D14 => Ok(14),
6488 VfpReg::D15 => Ok(15),
6489 _ => Err(synth_core::Error::SynthesisError(
6491 "S-register not supported in double-precision VFP encoding".to_string(),
6492 )),
6493 }
6494}
6495
6496fn encode_sreg(s: u32) -> (u32, u32) {
6500 (s >> 1, s & 1)
6501}
6502
6503fn encode_dreg(d: u32) -> (u32, u32) {
6507 (d & 0xF, (d >> 4) & 1)
6508}
6509
6510fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6516 let sd_num = vfp_sreg_to_num(sd)?;
6517 let sn_num = vfp_sreg_to_num(sn)?;
6518 let sm_num = vfp_sreg_to_num(sm)?;
6519 let (vd, d) = encode_sreg(sd_num);
6520 let (vn, n) = encode_sreg(sn_num);
6521 let (vm, m) = encode_sreg(sm_num);
6522
6523 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6524}
6525
6526fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6529 let sd_num = vfp_sreg_to_num(sd)?;
6530 let sm_num = vfp_sreg_to_num(sm)?;
6531 let (vd, d) = encode_sreg(sd_num);
6532 let (vm, m) = encode_sreg(sm_num);
6533
6534 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6535}
6536
6537fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6541 let sd_num = vfp_sreg_to_num(sd)?;
6542 let (vd, d) = encode_sreg(sd_num);
6543 let rn = reg_to_bits(&addr.base);
6544
6545 let offset = addr.offset;
6546 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6547 let abs_offset = offset.unsigned_abs();
6548 let imm8 = (abs_offset / 4) & 0xFF;
6549
6550 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6551}
6552
6553fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6557 let s_num = vfp_sreg_to_num(sreg)?;
6558 let (vn, n) = encode_sreg(s_num);
6559 let rt = reg_to_bits(core);
6560
6561 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6562 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6563}
6564
6565fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6569 let dd_num = vfp_dreg_to_num(dd)?;
6570 let dn_num = vfp_dreg_to_num(dn)?;
6571 let dm_num = vfp_dreg_to_num(dm)?;
6572 let (vd, d) = encode_dreg(dd_num);
6573 let (vn, n) = encode_dreg(dn_num);
6574 let (vm, m) = encode_dreg(dm_num);
6575
6576 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6577}
6578
6579fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6581 let dd_num = vfp_dreg_to_num(dd)?;
6582 let dm_num = vfp_dreg_to_num(dm)?;
6583 let (vd, d) = encode_dreg(dd_num);
6584 let (vm, m) = encode_dreg(dm_num);
6585
6586 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6587}
6588
6589fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6592 let dd_num = vfp_dreg_to_num(dd)?;
6593 let (vd, d) = encode_dreg(dd_num);
6594 let rn = reg_to_bits(&addr.base);
6595
6596 let offset = addr.offset;
6597 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6598 let abs_offset = offset.unsigned_abs();
6599 let imm8 = (abs_offset / 4) & 0xFF;
6600
6601 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6602}
6603
6604fn encode_vmov_core_dreg(
6608 to_dreg: bool,
6609 dreg: &VfpReg,
6610 core_lo: &Reg,
6611 core_hi: &Reg,
6612) -> Result<u32> {
6613 let d_num = vfp_dreg_to_num(dreg)?;
6614 let (vm, m) = encode_dreg(d_num);
6615 let rt = reg_to_bits(core_lo);
6616 let rt2 = reg_to_bits(core_hi);
6617
6618 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6619 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6620}
6621
6622fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6624 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6625 let hw2 = (instr & 0xFFFF) as u16;
6626 let mut bytes = hw1.to_le_bytes().to_vec();
6627 bytes.extend_from_slice(&hw2.to_le_bytes());
6628 bytes
6629}
6630
6631fn qreg_to_num(reg: &QReg) -> u32 {
6637 match reg {
6638 QReg::Q0 => 0,
6639 QReg::Q1 => 1,
6640 QReg::Q2 => 2,
6641 QReg::Q3 => 3,
6642 QReg::Q4 => 4,
6643 QReg::Q5 => 5,
6644 QReg::Q6 => 6,
6645 QReg::Q7 => 7,
6646 }
6647}
6648
6649fn mve_size_bits(size: &MveSize) -> u32 {
6651 match size {
6652 MveSize::S8 => 0b00,
6653 MveSize::S16 => 0b01,
6654 MveSize::S32 => 0b10,
6655 }
6656}
6657
6658fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6662 let d = qreg_to_num(qd) * 2;
6663 let n = qreg_to_num(qn) * 2;
6664 let m = qreg_to_num(qm) * 2;
6665
6666 let vd = d & 0xF;
6671 let d_bit = (d >> 4) & 1;
6672 let vn = n & 0xF;
6673 let n_bit = (n >> 4) & 1;
6674 let vm = m & 0xF;
6675 let m_bit = (m >> 4) & 1;
6676
6677 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6678}
6679
6680fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6682 encode_mve_3reg(base, qd, qn, qm)
6683}
6684
6685fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6688 let qd_enc = qreg_to_num(qd) * 2;
6689 let rn = reg_to_bits(&addr.base);
6690 let offset = addr.offset;
6691 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6692 let abs_offset = offset.unsigned_abs();
6693 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6697 | (u_bit << 23)
6698 | ((qd_enc >> 4) << 22)
6699 | (rn << 16)
6700 | ((qd_enc & 0xF) << 12)
6701 | (imm7 & 0x7F)
6702}
6703
6704fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6706 let qd_enc = qreg_to_num(qd) * 2;
6707 let rn = reg_to_bits(&addr.base);
6708 let offset = addr.offset;
6709 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6710 let abs_offset = offset.unsigned_abs();
6711 let imm7 = (abs_offset / 4) & 0x7F;
6712
6713 0xED000E80
6714 | (u_bit << 23)
6715 | ((qd_enc >> 4) << 22)
6716 | (rn << 16)
6717 | ((qd_enc & 0xF) << 12)
6718 | (imm7 & 0x7F)
6719}
6720
6721impl ArmEncoder {
6722 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6724 let mut result = Vec::new();
6725 let qd_num = qreg_to_num(qd);
6726
6727 for i in 0..4 {
6729 let word = u32::from_le_bytes([
6730 bytes[i * 4],
6731 bytes[i * 4 + 1],
6732 bytes[i * 4 + 2],
6733 bytes[i * 4 + 3],
6734 ]);
6735 let lo16 = word & 0xFFFF;
6736 let hi16 = (word >> 16) & 0xFFFF;
6737
6738 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6740 if hi16 != 0 {
6742 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6743 }
6744
6745 let s_num = qd_num * 4 + i as u32;
6747 let (vn, n) = encode_sreg(s_num);
6748 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6749 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6750 }
6751
6752 Ok(result)
6753 }
6754
6755 fn encode_thumb_mve_lane_wise_f32_binop(
6757 &self,
6758 qd: &QReg,
6759 qn: &QReg,
6760 qm: &QReg,
6761 vfp_base: u32,
6762 ) -> Result<Vec<u8>> {
6763 let mut result = Vec::new();
6764 let qd_num = qreg_to_num(qd);
6765 let qn_num = qreg_to_num(qn);
6766 let qm_num = qreg_to_num(qm);
6767
6768 for i in 0..4u32 {
6770 let sd = qd_num * 4 + i;
6771 let sn = qn_num * 4 + i;
6772 let sm = qm_num * 4 + i;
6773
6774 let (vd, d) = encode_sreg(sd);
6775 let (vn, n) = encode_sreg(sn);
6776 let (vm, m) = encode_sreg(sm);
6777
6778 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6779 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6780 }
6781
6782 Ok(result)
6783 }
6784
6785 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6787 let mut result = Vec::new();
6788 let qd_num = qreg_to_num(qd);
6789 let qm_num = qreg_to_num(qm);
6790
6791 for i in 0..4u32 {
6793 let sd = qd_num * 4 + i;
6794 let sm = qm_num * 4 + i;
6795
6796 let (vd, d) = encode_sreg(sd);
6797 let (vm, m) = encode_sreg(sm);
6798
6799 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6800 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6801 }
6802
6803 Ok(result)
6804 }
6805}
6806
6807#[cfg(test)]
6808mod tests {
6809 use super::*;
6810
6811 #[test]
6812 fn test_encoder_creation() {
6813 let encoder_arm = ArmEncoder::new_arm32();
6814 assert!(!encoder_arm.thumb_mode);
6815
6816 let encoder_thumb = ArmEncoder::new_thumb2();
6817 assert!(encoder_thumb.thumb_mode);
6818 }
6819
6820 #[test]
6821 fn test_encode_nop_arm32() {
6822 let encoder = ArmEncoder::new_arm32();
6823 let code = encoder.encode(&ArmOp::Nop).unwrap();
6824
6825 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
6828
6829 #[test]
6830 fn test_encode_nop_thumb() {
6831 let encoder = ArmEncoder::new_thumb2();
6832 let code = encoder.encode(&ArmOp::Nop).unwrap();
6833
6834 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
6837
6838 #[test]
6839 fn test_encode_mov_immediate_arm32() {
6840 let encoder = ArmEncoder::new_arm32();
6841 let op = ArmOp::Mov {
6842 rd: Reg::R0,
6843 op2: Operand2::Imm(42),
6844 };
6845
6846 let code = encoder.encode(&op).unwrap();
6847 assert_eq!(code.len(), 4);
6848
6849 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6851 assert_eq!(instr & 0x0E000000, 0x02000000); }
6853
6854 #[test]
6855 fn test_encode_add_registers_arm32() {
6856 let encoder = ArmEncoder::new_arm32();
6857 let op = ArmOp::Add {
6858 rd: Reg::R0,
6859 rn: Reg::R1,
6860 op2: Operand2::Reg(Reg::R2),
6861 };
6862
6863 let code = encoder.encode(&op).unwrap();
6864 assert_eq!(code.len(), 4);
6865
6866 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6867 assert_eq!(instr & 0x0FE00000, 0x00800000);
6869 }
6870
6871 #[test]
6872 fn test_encode_ldr_arm32() {
6873 let encoder = ArmEncoder::new_arm32();
6874 let op = ArmOp::Ldr {
6875 rd: Reg::R0,
6876 addr: MemAddr::imm(Reg::R1, 4),
6877 };
6878
6879 let code = encoder.encode(&op).unwrap();
6880 assert_eq!(code.len(), 4);
6881
6882 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6883 assert_eq!(instr & 0x00100000, 0x00100000);
6885 }
6886
6887 #[test]
6888 fn test_encode_str_arm32() {
6889 let encoder = ArmEncoder::new_arm32();
6890 let op = ArmOp::Str {
6891 rd: Reg::R0,
6892 addr: MemAddr::imm(Reg::SP, 0),
6893 };
6894
6895 let code = encoder.encode(&op).unwrap();
6896 assert_eq!(code.len(), 4);
6897 }
6898
6899 #[test]
6900 fn test_encode_branch_arm32() {
6901 let encoder = ArmEncoder::new_arm32();
6902 let op = ArmOp::Bl {
6903 label: "main".to_string(),
6904 };
6905
6906 let code = encoder.encode(&op).unwrap();
6907 assert_eq!(code.len(), 4);
6908
6909 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6910 assert_eq!(instr & 0x0F000000, 0x0B000000);
6912 }
6913
6914 #[test]
6915 fn test_encode_sequence() {
6916 let encoder = ArmEncoder::new_arm32();
6917 let ops = vec![
6918 ArmOp::Mov {
6919 rd: Reg::R0,
6920 op2: Operand2::Imm(42),
6921 },
6922 ArmOp::Mov {
6923 rd: Reg::R1,
6924 op2: Operand2::Imm(10),
6925 },
6926 ArmOp::Add {
6927 rd: Reg::R2,
6928 rn: Reg::R0,
6929 op2: Operand2::Reg(Reg::R1),
6930 },
6931 ];
6932
6933 let code = encoder.encode_sequence(&ops).unwrap();
6934 assert_eq!(code.len(), 12); }
6936
6937 #[test]
6938 fn test_reg_to_bits() {
6939 assert_eq!(reg_to_bits(&Reg::R0), 0);
6940 assert_eq!(reg_to_bits(&Reg::R7), 7);
6941 assert_eq!(reg_to_bits(&Reg::SP), 13);
6942 assert_eq!(reg_to_bits(&Reg::LR), 14);
6943 assert_eq!(reg_to_bits(&Reg::PC), 15);
6944 }
6945
6946 #[test]
6947 fn test_encode_bitwise_operations() {
6948 let encoder = ArmEncoder::new_arm32();
6949
6950 let and_op = ArmOp::And {
6951 rd: Reg::R0,
6952 rn: Reg::R1,
6953 op2: Operand2::Reg(Reg::R2),
6954 };
6955 let and_code = encoder.encode(&and_op).unwrap();
6956 assert_eq!(and_code.len(), 4);
6957
6958 let orr_op = ArmOp::Orr {
6959 rd: Reg::R0,
6960 rn: Reg::R1,
6961 op2: Operand2::Reg(Reg::R2),
6962 };
6963 let orr_code = encoder.encode(&orr_op).unwrap();
6964 assert_eq!(orr_code.len(), 4);
6965
6966 let eor_op = ArmOp::Eor {
6967 rd: Reg::R0,
6968 rn: Reg::R1,
6969 op2: Operand2::Reg(Reg::R2),
6970 };
6971 let eor_code = encoder.encode(&eor_op).unwrap();
6972 assert_eq!(eor_code.len(), 4);
6973 }
6974
6975 #[test]
6978 fn test_encode_sdiv_thumb2() {
6979 let encoder = ArmEncoder::new_thumb2();
6980 let op = ArmOp::Sdiv {
6981 rd: Reg::R0,
6982 rn: Reg::R1,
6983 rm: Reg::R2,
6984 };
6985
6986 let code = encoder.encode(&op).unwrap();
6987 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
6994 assert_eq!(code[1], 0xFB);
6995 assert_eq!(code[2], 0xF2);
6996 assert_eq!(code[3], 0xF0);
6997 }
6998
6999 #[test]
7000 fn test_encode_udiv_thumb2() {
7001 let encoder = ArmEncoder::new_thumb2();
7002 let op = ArmOp::Udiv {
7003 rd: Reg::R0,
7004 rn: Reg::R1,
7005 rm: Reg::R2,
7006 };
7007
7008 let code = encoder.encode(&op).unwrap();
7009 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7014 assert_eq!(code[1], 0xFB);
7015 assert_eq!(code[2], 0xF2);
7016 assert_eq!(code[3], 0xF0);
7017 }
7018
7019 #[test]
7020 fn test_encode_mul_thumb2() {
7021 let encoder = ArmEncoder::new_thumb2();
7022 let op = ArmOp::Mul {
7023 rd: Reg::R0,
7024 rn: Reg::R1,
7025 rm: Reg::R2,
7026 };
7027
7028 let code = encoder.encode(&op).unwrap();
7029 assert_eq!(code.len(), 4); }
7031
7032 #[test]
7033 fn test_encode_and_thumb2() {
7034 let encoder = ArmEncoder::new_thumb2();
7035 let op = ArmOp::And {
7036 rd: Reg::R0,
7037 rn: Reg::R1,
7038 op2: Operand2::Reg(Reg::R2),
7039 };
7040
7041 let code = encoder.encode(&op).unwrap();
7042 assert_eq!(code.len(), 4); }
7044
7045 #[test]
7046 fn test_encode_lsl_thumb2_low_regs() {
7047 let encoder = ArmEncoder::new_thumb2();
7048 let op = ArmOp::Lsl {
7049 rd: Reg::R0,
7050 rn: Reg::R1,
7051 shift: 5,
7052 };
7053
7054 let code = encoder.encode(&op).unwrap();
7055 assert_eq!(code.len(), 2); }
7057
7058 #[test]
7059 fn test_encode_clz_thumb2() {
7060 let encoder = ArmEncoder::new_thumb2();
7061 let op = ArmOp::Clz {
7062 rd: Reg::R0,
7063 rm: Reg::R1,
7064 };
7065
7066 let code = encoder.encode(&op).unwrap();
7067 assert_eq!(code.len(), 4); }
7069
7070 #[test]
7071 fn test_encode_bx_thumb2() {
7072 let encoder = ArmEncoder::new_thumb2();
7073 let op = ArmOp::Bx { rm: Reg::LR };
7074
7075 let code = encoder.encode(&op).unwrap();
7076 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7080 }
7081
7082 #[test]
7087 fn test_encode_f32_abs_arm32() {
7088 let encoder = ArmEncoder::new_arm32();
7089 let op = ArmOp::F32Abs {
7090 sd: VfpReg::S0,
7091 sm: VfpReg::S2,
7092 };
7093 let code = encoder.encode(&op).unwrap();
7094 assert_eq!(code.len(), 4); }
7096
7097 #[test]
7098 fn test_encode_f32_neg_arm32() {
7099 let encoder = ArmEncoder::new_arm32();
7100 let op = ArmOp::F32Neg {
7101 sd: VfpReg::S0,
7102 sm: VfpReg::S2,
7103 };
7104 let code = encoder.encode(&op).unwrap();
7105 assert_eq!(code.len(), 4);
7106 }
7107
7108 #[test]
7109 fn test_encode_f32_sqrt_arm32() {
7110 let encoder = ArmEncoder::new_arm32();
7111 let op = ArmOp::F32Sqrt {
7112 sd: VfpReg::S0,
7113 sm: VfpReg::S2,
7114 };
7115 let code = encoder.encode(&op).unwrap();
7116 assert_eq!(code.len(), 4);
7117 }
7118
7119 #[test]
7120 fn test_encode_f32_ceil_arm32() {
7121 let encoder = ArmEncoder::new_arm32();
7122 let op = ArmOp::F32Ceil {
7123 sd: VfpReg::S0,
7124 sm: VfpReg::S2,
7125 };
7126 let code = encoder.encode(&op).unwrap();
7127 assert_eq!(code.len(), 36);
7129 }
7130
7131 #[test]
7132 fn test_encode_f32_floor_thumb2() {
7133 let encoder = ArmEncoder::new_thumb2();
7134 let op = ArmOp::F32Floor {
7135 sd: VfpReg::S0,
7136 sm: VfpReg::S2,
7137 };
7138 let code = encoder.encode(&op).unwrap();
7139 assert_eq!(code.len(), 36);
7141 }
7142
7143 #[test]
7144 fn test_encode_f32_min_arm32() {
7145 let encoder = ArmEncoder::new_arm32();
7146 let op = ArmOp::F32Min {
7147 sd: VfpReg::S0,
7148 sn: VfpReg::S2,
7149 sm: VfpReg::S4,
7150 };
7151 let code = encoder.encode(&op).unwrap();
7152 assert_eq!(code.len(), 16); }
7154
7155 #[test]
7156 fn test_encode_f32_max_thumb2() {
7157 let encoder = ArmEncoder::new_thumb2();
7158 let op = ArmOp::F32Max {
7159 sd: VfpReg::S0,
7160 sn: VfpReg::S2,
7161 sm: VfpReg::S4,
7162 };
7163 let code = encoder.encode(&op).unwrap();
7164 assert_eq!(code.len(), 18);
7166 }
7167
7168 #[test]
7169 fn test_encode_f32_copysign_arm32() {
7170 let encoder = ArmEncoder::new_arm32();
7171 let op = ArmOp::F32Copysign {
7172 sd: VfpReg::S0,
7173 sn: VfpReg::S2,
7174 sm: VfpReg::S4,
7175 };
7176 let code = encoder.encode(&op).unwrap();
7177 assert_eq!(code.len(), 24);
7179 }
7180
7181 #[test]
7186 fn test_encode_f64_add_arm32() {
7187 let encoder = ArmEncoder::new_arm32();
7188 let op = ArmOp::F64Add {
7189 dd: VfpReg::D0,
7190 dn: VfpReg::D1,
7191 dm: VfpReg::D2,
7192 };
7193 let code = encoder.encode(&op).unwrap();
7194 assert_eq!(code.len(), 4);
7195 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7197 assert_eq!((instr >> 8) & 0xF, 0xB); }
7199
7200 #[test]
7201 fn test_encode_f64_sub_thumb2() {
7202 let encoder = ArmEncoder::new_thumb2();
7203 let op = ArmOp::F64Sub {
7204 dd: VfpReg::D0,
7205 dn: VfpReg::D1,
7206 dm: VfpReg::D2,
7207 };
7208 let code = encoder.encode(&op).unwrap();
7209 assert_eq!(code.len(), 4); }
7211
7212 #[test]
7213 fn test_encode_f64_mul_arm32() {
7214 let encoder = ArmEncoder::new_arm32();
7215 let op = ArmOp::F64Mul {
7216 dd: VfpReg::D0,
7217 dn: VfpReg::D1,
7218 dm: VfpReg::D2,
7219 };
7220 let code = encoder.encode(&op).unwrap();
7221 assert_eq!(code.len(), 4);
7222 }
7223
7224 #[test]
7225 fn test_encode_f64_div_arm32() {
7226 let encoder = ArmEncoder::new_arm32();
7227 let op = ArmOp::F64Div {
7228 dd: VfpReg::D0,
7229 dn: VfpReg::D1,
7230 dm: VfpReg::D2,
7231 };
7232 let code = encoder.encode(&op).unwrap();
7233 assert_eq!(code.len(), 4);
7234 }
7235
7236 #[test]
7237 fn test_encode_f64_abs_arm32() {
7238 let encoder = ArmEncoder::new_arm32();
7239 let op = ArmOp::F64Abs {
7240 dd: VfpReg::D0,
7241 dm: VfpReg::D2,
7242 };
7243 let code = encoder.encode(&op).unwrap();
7244 assert_eq!(code.len(), 4);
7245 }
7246
7247 #[test]
7248 fn test_encode_f64_neg_arm32() {
7249 let encoder = ArmEncoder::new_arm32();
7250 let op = ArmOp::F64Neg {
7251 dd: VfpReg::D0,
7252 dm: VfpReg::D2,
7253 };
7254 let code = encoder.encode(&op).unwrap();
7255 assert_eq!(code.len(), 4);
7256 }
7257
7258 #[test]
7259 fn test_encode_f64_sqrt_arm32() {
7260 let encoder = ArmEncoder::new_arm32();
7261 let op = ArmOp::F64Sqrt {
7262 dd: VfpReg::D0,
7263 dm: VfpReg::D2,
7264 };
7265 let code = encoder.encode(&op).unwrap();
7266 assert_eq!(code.len(), 4);
7267 }
7268
7269 #[test]
7270 fn test_encode_f64_load_arm32() {
7271 let encoder = ArmEncoder::new_arm32();
7272 let op = ArmOp::F64Load {
7273 dd: VfpReg::D0,
7274 addr: MemAddr::imm(Reg::R0, 8),
7275 };
7276 let code = encoder.encode(&op).unwrap();
7277 assert_eq!(code.len(), 4);
7278 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7279 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7282
7283 #[test]
7284 fn test_encode_f64_store_thumb2() {
7285 let encoder = ArmEncoder::new_thumb2();
7286 let op = ArmOp::F64Store {
7287 dd: VfpReg::D0,
7288 addr: MemAddr::imm(Reg::SP, 0),
7289 };
7290 let code = encoder.encode(&op).unwrap();
7291 assert_eq!(code.len(), 4);
7292 }
7293
7294 #[test]
7295 fn test_encode_f64_compare_arm32() {
7296 let encoder = ArmEncoder::new_arm32();
7297 let op = ArmOp::F64Eq {
7298 rd: Reg::R0,
7299 dn: VfpReg::D0,
7300 dm: VfpReg::D1,
7301 };
7302 let code = encoder.encode(&op).unwrap();
7303 assert_eq!(code.len(), 16); }
7305
7306 #[test]
7307 fn test_encode_f64_compare_thumb2() {
7308 let encoder = ArmEncoder::new_thumb2();
7309 let op = ArmOp::F64Lt {
7310 rd: Reg::R0,
7311 dn: VfpReg::D0,
7312 dm: VfpReg::D1,
7313 };
7314 let code = encoder.encode(&op).unwrap();
7315 assert_eq!(code.len(), 14);
7317 }
7318
7319 #[test]
7320 fn test_encode_f64_const_arm32() {
7321 let encoder = ArmEncoder::new_arm32();
7322 let op = ArmOp::F64Const {
7323 dd: VfpReg::D0,
7324 value: 3.125,
7325 };
7326 let code = encoder.encode(&op).unwrap();
7327 assert_eq!(code.len(), 20);
7329 }
7330
7331 #[test]
7332 fn test_encode_f64_const_thumb2() {
7333 let encoder = ArmEncoder::new_thumb2();
7334 let op = ArmOp::F64Const {
7335 dd: VfpReg::D0,
7336 value: 2.5,
7337 };
7338 let code = encoder.encode(&op).unwrap();
7339 assert_eq!(code.len(), 20);
7341 }
7342
7343 #[test]
7344 fn test_encode_f64_convert_i32s_arm32() {
7345 let encoder = ArmEncoder::new_arm32();
7346 let op = ArmOp::F64ConvertI32S {
7347 dd: VfpReg::D0,
7348 rm: Reg::R0,
7349 };
7350 let code = encoder.encode(&op).unwrap();
7351 assert_eq!(code.len(), 8);
7353 }
7354
7355 #[test]
7356 fn test_encode_f64_promote_f32_arm32() {
7357 let encoder = ArmEncoder::new_arm32();
7358 let op = ArmOp::F64PromoteF32 {
7359 dd: VfpReg::D0,
7360 sm: VfpReg::S0,
7361 };
7362 let code = encoder.encode(&op).unwrap();
7363 assert_eq!(code.len(), 4); }
7365
7366 #[test]
7367 fn test_encode_f64_promote_f32_thumb2() {
7368 let encoder = ArmEncoder::new_thumb2();
7369 let op = ArmOp::F64PromoteF32 {
7370 dd: VfpReg::D0,
7371 sm: VfpReg::S0,
7372 };
7373 let code = encoder.encode(&op).unwrap();
7374 assert_eq!(code.len(), 4);
7375 }
7376
7377 #[test]
7378 fn test_encode_i32_trunc_f64s_arm32() {
7379 let encoder = ArmEncoder::new_arm32();
7380 let op = ArmOp::I32TruncF64S {
7381 rd: Reg::R0,
7382 dm: VfpReg::D0,
7383 };
7384 let code = encoder.encode(&op).unwrap();
7385 assert_eq!(code.len(), 8);
7387 }
7388
7389 #[test]
7390 fn test_encode_f64_reinterpret_i64_arm32() {
7391 let encoder = ArmEncoder::new_arm32();
7392 let op = ArmOp::F64ReinterpretI64 {
7393 dd: VfpReg::D0,
7394 rmlo: Reg::R0,
7395 rmhi: Reg::R1,
7396 };
7397 let code = encoder.encode(&op).unwrap();
7398 assert_eq!(code.len(), 4); }
7400
7401 #[test]
7402 fn test_encode_i64_reinterpret_f64_thumb2() {
7403 let encoder = ArmEncoder::new_thumb2();
7404 let op = ArmOp::I64ReinterpretF64 {
7405 rdlo: Reg::R0,
7406 rdhi: Reg::R1,
7407 dm: VfpReg::D0,
7408 };
7409 let code = encoder.encode(&op).unwrap();
7410 assert_eq!(code.len(), 4);
7411 }
7412
7413 #[test]
7414 fn test_encode_f64_trunc_thumb2() {
7415 let encoder = ArmEncoder::new_thumb2();
7416 let op = ArmOp::F64Trunc {
7417 dd: VfpReg::D0,
7418 dm: VfpReg::D1,
7419 };
7420 let code = encoder.encode(&op).unwrap();
7421 assert_eq!(code.len(), 8);
7423 }
7424
7425 #[test]
7426 fn test_encode_f64_min_arm32() {
7427 let encoder = ArmEncoder::new_arm32();
7428 let op = ArmOp::F64Min {
7429 dd: VfpReg::D0,
7430 dn: VfpReg::D1,
7431 dm: VfpReg::D2,
7432 };
7433 let code = encoder.encode(&op).unwrap();
7434 assert_eq!(code.len(), 16);
7436 }
7437
7438 #[test]
7439 fn test_f64_cp11_encoding() {
7440 let encoder = ArmEncoder::new_arm32();
7442
7443 let code = encoder
7445 .encode(&ArmOp::F64Add {
7446 dd: VfpReg::D0,
7447 dn: VfpReg::D0,
7448 dm: VfpReg::D0,
7449 })
7450 .unwrap();
7451 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7452 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7453
7454 let code = encoder
7456 .encode(&ArmOp::F32Add {
7457 sd: VfpReg::S0,
7458 sn: VfpReg::S0,
7459 sm: VfpReg::S0,
7460 })
7461 .unwrap();
7462 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7463 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7464 }
7465
7466 #[test]
7467 fn test_dreg_encoding_higher_registers() {
7468 let encoder = ArmEncoder::new_arm32();
7469
7470 let op = ArmOp::F64Add {
7472 dd: VfpReg::D15,
7473 dn: VfpReg::D14,
7474 dm: VfpReg::D13,
7475 };
7476 let code = encoder.encode(&op).unwrap();
7477 assert_eq!(code.len(), 4);
7478
7479 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7481 assert_eq!((instr >> 8) & 0xF, 0xB); }
7483
7484 #[test]
7489 fn test_encode_label_emits_no_bytes() {
7490 let encoder = ArmEncoder::new_thumb2();
7491 let op = ArmOp::Label {
7492 name: ".Lblock_end_0".to_string(),
7493 };
7494 let code = encoder.encode(&op).unwrap();
7495 assert!(code.is_empty(), "Label should emit zero bytes");
7496
7497 let encoder32 = ArmEncoder::new_arm32();
7498 let code32 = encoder32.encode(&op).unwrap();
7499 assert!(
7500 code32.is_empty(),
7501 "Label should emit zero bytes in ARM32 too"
7502 );
7503 }
7504
7505 #[test]
7506 fn test_encode_bcc_eq_thumb2() {
7507 use synth_synthesis::Condition;
7508 let encoder = ArmEncoder::new_thumb2();
7509 let op = ArmOp::Bcc {
7510 cond: Condition::EQ,
7511 label: "target".to_string(),
7512 };
7513 let code = encoder.encode(&op).unwrap();
7514 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7518 }
7519
7520 #[test]
7521 fn test_encode_bcc_ne_thumb2() {
7522 use synth_synthesis::Condition;
7523 let encoder = ArmEncoder::new_thumb2();
7524 let op = ArmOp::Bcc {
7525 cond: Condition::NE,
7526 label: "target".to_string(),
7527 };
7528 let code = encoder.encode(&op).unwrap();
7529 assert_eq!(code.len(), 2);
7530
7531 assert_eq!(code, vec![0x00, 0xD1]);
7533 }
7534
7535 #[test]
7536 fn test_encode_bcc_arm32() {
7537 use synth_synthesis::Condition;
7538 let encoder = ArmEncoder::new_arm32();
7539 let op = ArmOp::Bcc {
7540 cond: Condition::EQ,
7541 label: "target".to_string(),
7542 };
7543 let code = encoder.encode(&op).unwrap();
7544 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7547 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7551
7552 #[test]
7553 fn test_encode_udf_thumb2() {
7554 let encoder = ArmEncoder::new_thumb2();
7555 let op = ArmOp::Udf { imm: 0 };
7556 let code = encoder.encode(&op).unwrap();
7557 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
7561 }
7562
7563 #[test]
7564 fn test_encode_nop_thumb2() {
7565 let encoder = ArmEncoder::new_thumb2();
7566 let op = ArmOp::Nop;
7567 let code = encoder.encode(&op).unwrap();
7568 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
7572 }
7573
7574 #[test]
7579 fn test_encode_i64_add_thumb2() {
7580 let encoder = ArmEncoder::new_thumb2();
7581 let op = ArmOp::I64Add {
7582 rdlo: Reg::R0,
7583 rdhi: Reg::R1,
7584 rnlo: Reg::R0,
7585 rnhi: Reg::R1,
7586 rmlo: Reg::R2,
7587 rmhi: Reg::R3,
7588 };
7589 let code = encoder.encode(&op).unwrap();
7590 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
7592 }
7593
7594 #[test]
7595 fn test_encode_i64_sub_thumb2() {
7596 let encoder = ArmEncoder::new_thumb2();
7597 let op = ArmOp::I64Sub {
7598 rdlo: Reg::R0,
7599 rdhi: Reg::R1,
7600 rnlo: Reg::R0,
7601 rnhi: Reg::R1,
7602 rmlo: Reg::R2,
7603 rmhi: Reg::R3,
7604 };
7605 let code = encoder.encode(&op).unwrap();
7606 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
7608 }
7609
7610 #[test]
7611 fn test_encode_i64_and_thumb2() {
7612 let encoder = ArmEncoder::new_thumb2();
7613 let op = ArmOp::I64And {
7614 rdlo: Reg::R0,
7615 rdhi: Reg::R1,
7616 rnlo: Reg::R0,
7617 rnhi: Reg::R1,
7618 rmlo: Reg::R2,
7619 rmhi: Reg::R3,
7620 };
7621 let code = encoder.encode(&op).unwrap();
7622 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
7624 }
7625
7626 #[test]
7627 fn test_encode_i64_or_thumb2() {
7628 let encoder = ArmEncoder::new_thumb2();
7629 let op = ArmOp::I64Or {
7630 rdlo: Reg::R0,
7631 rdhi: Reg::R1,
7632 rnlo: Reg::R0,
7633 rnhi: Reg::R1,
7634 rmlo: Reg::R2,
7635 rmhi: Reg::R3,
7636 };
7637 let code = encoder.encode(&op).unwrap();
7638 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
7639 }
7640
7641 #[test]
7642 fn test_encode_i64_xor_thumb2() {
7643 let encoder = ArmEncoder::new_thumb2();
7644 let op = ArmOp::I64Xor {
7645 rdlo: Reg::R0,
7646 rdhi: Reg::R1,
7647 rnlo: Reg::R0,
7648 rnhi: Reg::R1,
7649 rmlo: Reg::R2,
7650 rmhi: Reg::R3,
7651 };
7652 let code = encoder.encode(&op).unwrap();
7653 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
7654 }
7655
7656 #[test]
7657 fn test_encode_i64_const_small_thumb2() {
7658 let encoder = ArmEncoder::new_thumb2();
7659 let op = ArmOp::I64Const {
7661 rdlo: Reg::R0,
7662 rdhi: Reg::R1,
7663 value: 42,
7664 };
7665 let code = encoder.encode(&op).unwrap();
7666 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
7668 }
7669
7670 #[test]
7671 fn test_encode_i64_const_large_thumb2() {
7672 let encoder = ArmEncoder::new_thumb2();
7673 let op = ArmOp::I64Const {
7675 rdlo: Reg::R0,
7676 rdhi: Reg::R1,
7677 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
7678 };
7679 let code = encoder.encode(&op).unwrap();
7680 assert_eq!(
7682 code.len(),
7683 16,
7684 "I64Const with large value should be 16 bytes"
7685 );
7686 }
7687
7688 #[test]
7689 fn test_encode_i64_extend_i32_s_thumb2() {
7690 let encoder = ArmEncoder::new_thumb2();
7691 let op = ArmOp::I64ExtendI32S {
7692 rdlo: Reg::R0,
7693 rdhi: Reg::R1,
7694 rn: Reg::R0,
7695 };
7696 let code = encoder.encode(&op).unwrap();
7697 assert_eq!(
7699 code.len(),
7700 4,
7701 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
7702 );
7703 }
7704
7705 #[test]
7706 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
7707 let encoder = ArmEncoder::new_thumb2();
7708 let op = ArmOp::I64ExtendI32S {
7709 rdlo: Reg::R0,
7710 rdhi: Reg::R1,
7711 rn: Reg::R2,
7712 };
7713 let code = encoder.encode(&op).unwrap();
7714 assert!(
7716 code.len() >= 6,
7717 "I64ExtendI32S (diff reg) should be at least 6 bytes"
7718 );
7719 }
7720
7721 #[test]
7722 fn test_encode_i64_extend_i32_u_thumb2() {
7723 let encoder = ArmEncoder::new_thumb2();
7724 let op = ArmOp::I64ExtendI32U {
7725 rdlo: Reg::R0,
7726 rdhi: Reg::R1,
7727 rn: Reg::R0,
7728 };
7729 let code = encoder.encode(&op).unwrap();
7730 assert_eq!(
7732 code.len(),
7733 2,
7734 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
7735 );
7736 }
7737
7738 #[test]
7739 fn test_encode_i32_wrap_i64_nop_thumb2() {
7740 let encoder = ArmEncoder::new_thumb2();
7741 let op = ArmOp::I32WrapI64 {
7743 rd: Reg::R0,
7744 rnlo: Reg::R0,
7745 };
7746 let code = encoder.encode(&op).unwrap();
7747 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
7748 assert_eq!(code, vec![0x00, 0xBF]); }
7750
7751 #[test]
7752 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
7753 let encoder = ArmEncoder::new_thumb2();
7754 let op = ArmOp::I32WrapI64 {
7755 rd: Reg::R2,
7756 rnlo: Reg::R0,
7757 };
7758 let code = encoder.encode(&op).unwrap();
7759 assert!(
7761 code.len() >= 2,
7762 "I32WrapI64 diff reg should emit at least 2 bytes"
7763 );
7764 }
7765
7766 #[test]
7767 fn test_encode_i64_eqz_thumb2() {
7768 let encoder = ArmEncoder::new_thumb2();
7769 let op = ArmOp::I64Eqz {
7770 rd: Reg::R0,
7771 rnlo: Reg::R0,
7772 rnhi: Reg::R1,
7773 };
7774 let code = encoder.encode(&op).unwrap();
7775 assert!(
7777 code.len() >= 6,
7778 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
7779 );
7780 }
7781
7782 #[test]
7783 fn test_encode_i64_eq_thumb2() {
7784 let encoder = ArmEncoder::new_thumb2();
7785 let op = ArmOp::I64Eq {
7786 rd: Reg::R0,
7787 rnlo: Reg::R0,
7788 rnhi: Reg::R1,
7789 rmlo: Reg::R2,
7790 rmhi: Reg::R3,
7791 };
7792 let code = encoder.encode(&op).unwrap();
7793 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
7795 }
7796
7797 #[test]
7798 fn test_encode_i64_ldr_thumb2() {
7799 let encoder = ArmEncoder::new_thumb2();
7800 let op = ArmOp::I64Ldr {
7801 rdlo: Reg::R0,
7802 rdhi: Reg::R1,
7803 addr: MemAddr::imm(Reg::SP, 0),
7804 };
7805 let code = encoder.encode(&op).unwrap();
7806 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
7808 }
7809
7810 #[test]
7811 fn test_encode_i64_str_thumb2() {
7812 let encoder = ArmEncoder::new_thumb2();
7813 let op = ArmOp::I64Str {
7814 rdlo: Reg::R0,
7815 rdhi: Reg::R1,
7816 addr: MemAddr::imm(Reg::SP, 0),
7817 };
7818 let code = encoder.encode(&op).unwrap();
7819 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
7821 }
7822
7823 #[test]
7824 fn test_encode_i64_all_comparisons_thumb2() {
7825 let encoder = ArmEncoder::new_thumb2();
7826
7827 let ops = vec![
7828 ArmOp::I64Ne {
7829 rd: Reg::R0,
7830 rnlo: Reg::R0,
7831 rnhi: Reg::R1,
7832 rmlo: Reg::R2,
7833 rmhi: Reg::R3,
7834 },
7835 ArmOp::I64LtS {
7836 rd: Reg::R0,
7837 rnlo: Reg::R0,
7838 rnhi: Reg::R1,
7839 rmlo: Reg::R2,
7840 rmhi: Reg::R3,
7841 },
7842 ArmOp::I64LtU {
7843 rd: Reg::R0,
7844 rnlo: Reg::R0,
7845 rnhi: Reg::R1,
7846 rmlo: Reg::R2,
7847 rmhi: Reg::R3,
7848 },
7849 ArmOp::I64LeS {
7850 rd: Reg::R0,
7851 rnlo: Reg::R0,
7852 rnhi: Reg::R1,
7853 rmlo: Reg::R2,
7854 rmhi: Reg::R3,
7855 },
7856 ArmOp::I64LeU {
7857 rd: Reg::R0,
7858 rnlo: Reg::R0,
7859 rnhi: Reg::R1,
7860 rmlo: Reg::R2,
7861 rmhi: Reg::R3,
7862 },
7863 ArmOp::I64GtS {
7864 rd: Reg::R0,
7865 rnlo: Reg::R0,
7866 rnhi: Reg::R1,
7867 rmlo: Reg::R2,
7868 rmhi: Reg::R3,
7869 },
7870 ArmOp::I64GtU {
7871 rd: Reg::R0,
7872 rnlo: Reg::R0,
7873 rnhi: Reg::R1,
7874 rmlo: Reg::R2,
7875 rmhi: Reg::R3,
7876 },
7877 ArmOp::I64GeS {
7878 rd: Reg::R0,
7879 rnlo: Reg::R0,
7880 rnhi: Reg::R1,
7881 rmlo: Reg::R2,
7882 rmhi: Reg::R3,
7883 },
7884 ArmOp::I64GeU {
7885 rd: Reg::R0,
7886 rnlo: Reg::R0,
7887 rnhi: Reg::R1,
7888 rmlo: Reg::R2,
7889 rmhi: Reg::R3,
7890 },
7891 ];
7892
7893 for op in &ops {
7894 let code = encoder.encode(op).unwrap();
7895 assert!(
7896 code.len() >= 8,
7897 "i64 comparison {:?} should emit at least 8 bytes, got {}",
7898 op,
7899 code.len()
7900 );
7901 }
7902 }
7903
7904 #[test]
7905 fn test_encode_i64_const_zero_thumb2() {
7906 let encoder = ArmEncoder::new_thumb2();
7907 let op = ArmOp::I64Const {
7908 rdlo: Reg::R0,
7909 rdhi: Reg::R1,
7910 value: 0,
7911 };
7912 let code = encoder.encode(&op).unwrap();
7913 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
7915 }
7916
7917 #[test]
7918 fn test_encode_i64_const_negative_one_thumb2() {
7919 let encoder = ArmEncoder::new_thumb2();
7920 let op = ArmOp::I64Const {
7921 rdlo: Reg::R0,
7922 rdhi: Reg::R1,
7923 value: -1, };
7925 let code = encoder.encode(&op).unwrap();
7926 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
7928 }
7929
7930 #[test]
7935 fn test_encode_ldrb_arm32() {
7936 let encoder = ArmEncoder::new_arm32();
7937 let op = ArmOp::Ldrb {
7938 rd: Reg::R0,
7939 addr: MemAddr::imm(Reg::R1, 4),
7940 };
7941 let code = encoder.encode(&op).unwrap();
7942 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
7943 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7945 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
7946 }
7947
7948 #[test]
7949 fn test_encode_strb_arm32() {
7950 let encoder = ArmEncoder::new_arm32();
7951 let op = ArmOp::Strb {
7952 rd: Reg::R0,
7953 addr: MemAddr::imm(Reg::R1, 0),
7954 };
7955 let code = encoder.encode(&op).unwrap();
7956 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
7957 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7959 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
7960 }
7961
7962 #[test]
7963 fn test_encode_ldrh_arm32() {
7964 let encoder = ArmEncoder::new_arm32();
7965 let op = ArmOp::Ldrh {
7966 rd: Reg::R0,
7967 addr: MemAddr::imm(Reg::R1, 2),
7968 };
7969 let code = encoder.encode(&op).unwrap();
7970 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
7971 }
7972
7973 #[test]
7974 fn test_encode_strh_arm32() {
7975 let encoder = ArmEncoder::new_arm32();
7976 let op = ArmOp::Strh {
7977 rd: Reg::R0,
7978 addr: MemAddr::imm(Reg::R1, 0),
7979 };
7980 let code = encoder.encode(&op).unwrap();
7981 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
7982 }
7983
7984 #[test]
7985 fn test_encode_ldrsb_arm32() {
7986 let encoder = ArmEncoder::new_arm32();
7987 let op = ArmOp::Ldrsb {
7988 rd: Reg::R0,
7989 addr: MemAddr::imm(Reg::R1, 0),
7990 };
7991 let code = encoder.encode(&op).unwrap();
7992 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
7993 }
7994
7995 #[test]
7996 fn test_encode_ldrsh_arm32() {
7997 let encoder = ArmEncoder::new_arm32();
7998 let op = ArmOp::Ldrsh {
7999 rd: Reg::R0,
8000 addr: MemAddr::imm(Reg::R1, 0),
8001 };
8002 let code = encoder.encode(&op).unwrap();
8003 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8004 }
8005
8006 #[test]
8007 fn test_encode_ldrb_thumb2_16bit() {
8008 let encoder = ArmEncoder::new_thumb2();
8009 let op = ArmOp::Ldrb {
8010 rd: Reg::R0,
8011 addr: MemAddr::imm(Reg::R1, 4),
8012 };
8013 let code = encoder.encode(&op).unwrap();
8014 assert_eq!(
8016 code.len(),
8017 2,
8018 "Thumb-2 LDRB with small offset should be 16-bit"
8019 );
8020 }
8021
8022 #[test]
8023 fn test_encode_ldrb_thumb2_32bit() {
8024 let encoder = ArmEncoder::new_thumb2();
8025 let op = ArmOp::Ldrb {
8026 rd: Reg::R0,
8027 addr: MemAddr::imm(Reg::R1, 100), };
8029 let code = encoder.encode(&op).unwrap();
8030 assert_eq!(
8031 code.len(),
8032 4,
8033 "Thumb-2 LDRB with large offset should be 32-bit"
8034 );
8035 }
8036
8037 #[test]
8038 fn test_encode_strb_thumb2_16bit() {
8039 let encoder = ArmEncoder::new_thumb2();
8040 let op = ArmOp::Strb {
8041 rd: Reg::R0,
8042 addr: MemAddr::imm(Reg::R1, 10),
8043 };
8044 let code = encoder.encode(&op).unwrap();
8045 assert_eq!(
8046 code.len(),
8047 2,
8048 "Thumb-2 STRB with small offset should be 16-bit"
8049 );
8050 }
8051
8052 #[test]
8053 fn test_encode_ldrh_thumb2_16bit() {
8054 let encoder = ArmEncoder::new_thumb2();
8055 let op = ArmOp::Ldrh {
8056 rd: Reg::R0,
8057 addr: MemAddr::imm(Reg::R1, 4), };
8059 let code = encoder.encode(&op).unwrap();
8060 assert_eq!(
8061 code.len(),
8062 2,
8063 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8064 );
8065 }
8066
8067 #[test]
8068 fn test_encode_strh_thumb2_16bit() {
8069 let encoder = ArmEncoder::new_thumb2();
8070 let op = ArmOp::Strh {
8071 rd: Reg::R0,
8072 addr: MemAddr::imm(Reg::R1, 4),
8073 };
8074 let code = encoder.encode(&op).unwrap();
8075 assert_eq!(
8076 code.len(),
8077 2,
8078 "Thumb-2 STRH with small aligned offset should be 16-bit"
8079 );
8080 }
8081
8082 #[test]
8083 fn test_encode_ldrsb_thumb2() {
8084 let encoder = ArmEncoder::new_thumb2();
8085 let op = ArmOp::Ldrsb {
8086 rd: Reg::R0,
8087 addr: MemAddr::imm(Reg::R1, 0),
8088 };
8089 let code = encoder.encode(&op).unwrap();
8090 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8092 }
8093
8094 #[test]
8095 fn test_encode_ldrsh_thumb2() {
8096 let encoder = ArmEncoder::new_thumb2();
8097 let op = ArmOp::Ldrsh {
8098 rd: Reg::R0,
8099 addr: MemAddr::imm(Reg::R1, 0),
8100 };
8101 let code = encoder.encode(&op).unwrap();
8102 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8103 }
8104
8105 #[test]
8106 fn test_encode_memory_size_thumb2() {
8107 let encoder = ArmEncoder::new_thumb2();
8108 let op = ArmOp::MemorySize { rd: Reg::R0 };
8109 let code = encoder.encode(&op).unwrap();
8110 assert!(!code.is_empty(), "MemorySize should produce code");
8112 }
8113
8114 #[test]
8115 fn test_encode_memory_grow_thumb2() {
8116 let encoder = ArmEncoder::new_thumb2();
8117 let op = ArmOp::MemoryGrow {
8118 rd: Reg::R0,
8119 rn: Reg::R0,
8120 };
8121 let code = encoder.encode(&op).unwrap();
8122 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8123 }
8124
8125 #[test]
8126 fn test_encode_subword_reg_offset_thumb2() {
8127 let encoder = ArmEncoder::new_thumb2();
8128
8129 let op = ArmOp::Ldrb {
8131 rd: Reg::R0,
8132 addr: MemAddr::reg(Reg::R1, Reg::R2),
8133 };
8134 let code = encoder.encode(&op).unwrap();
8135 assert_eq!(
8136 code.len(),
8137 4,
8138 "Thumb-2 LDRB with reg offset should be 32-bit"
8139 );
8140
8141 let op = ArmOp::Strb {
8143 rd: Reg::R0,
8144 addr: MemAddr::reg(Reg::R1, Reg::R2),
8145 };
8146 let code = encoder.encode(&op).unwrap();
8147 assert_eq!(
8148 code.len(),
8149 4,
8150 "Thumb-2 STRB with reg offset should be 32-bit"
8151 );
8152
8153 let op = ArmOp::Ldrh {
8155 rd: Reg::R0,
8156 addr: MemAddr::reg(Reg::R1, Reg::R2),
8157 };
8158 let code = encoder.encode(&op).unwrap();
8159 assert_eq!(
8160 code.len(),
8161 4,
8162 "Thumb-2 LDRH with reg offset should be 32-bit"
8163 );
8164
8165 let op = ArmOp::Strh {
8167 rd: Reg::R0,
8168 addr: MemAddr::reg(Reg::R1, Reg::R2),
8169 };
8170 let code = encoder.encode(&op).unwrap();
8171 assert_eq!(
8172 code.len(),
8173 4,
8174 "Thumb-2 STRH with reg offset should be 32-bit"
8175 );
8176 }
8177
8178 #[test]
8179 fn test_encode_subword_reg_imm_offset_thumb2() {
8180 let encoder = ArmEncoder::new_thumb2();
8181
8182 let op = ArmOp::Ldrb {
8184 rd: Reg::R0,
8185 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8186 };
8187 let code = encoder.encode(&op).unwrap();
8188 assert_eq!(
8190 code.len(),
8191 8,
8192 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8193 );
8194 }
8195
8196 #[test]
8201 fn test_encode_mve_addi32_thumb2() {
8202 let encoder = ArmEncoder::new_thumb2();
8203 let op = ArmOp::MveAddI {
8204 qd: QReg::Q0,
8205 qn: QReg::Q1,
8206 qm: QReg::Q2,
8207 size: MveSize::S32,
8208 };
8209 let code = encoder.encode(&op).unwrap();
8210 assert_eq!(
8211 code.len(),
8212 4,
8213 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8214 );
8215 }
8216
8217 #[test]
8218 fn test_encode_mve_subi16_thumb2() {
8219 let encoder = ArmEncoder::new_thumb2();
8220 let op = ArmOp::MveSubI {
8221 qd: QReg::Q0,
8222 qn: QReg::Q1,
8223 qm: QReg::Q2,
8224 size: MveSize::S16,
8225 };
8226 let code = encoder.encode(&op).unwrap();
8227 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8228 }
8229
8230 #[test]
8231 fn test_encode_mve_muli8_thumb2() {
8232 let encoder = ArmEncoder::new_thumb2();
8233 let op = ArmOp::MveMulI {
8234 qd: QReg::Q0,
8235 qn: QReg::Q1,
8236 qm: QReg::Q2,
8237 size: MveSize::S8,
8238 };
8239 let code = encoder.encode(&op).unwrap();
8240 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8241 }
8242
8243 #[test]
8244 fn test_encode_mve_bitwise_thumb2() {
8245 let encoder = ArmEncoder::new_thumb2();
8246
8247 let ops = vec![
8248 ArmOp::MveAnd {
8249 qd: QReg::Q0,
8250 qn: QReg::Q1,
8251 qm: QReg::Q2,
8252 },
8253 ArmOp::MveOrr {
8254 qd: QReg::Q0,
8255 qn: QReg::Q1,
8256 qm: QReg::Q2,
8257 },
8258 ArmOp::MveEor {
8259 qd: QReg::Q0,
8260 qn: QReg::Q1,
8261 qm: QReg::Q2,
8262 },
8263 ArmOp::MveBic {
8264 qd: QReg::Q0,
8265 qn: QReg::Q1,
8266 qm: QReg::Q2,
8267 },
8268 ];
8269 for op in ops {
8270 let code = encoder.encode(&op).unwrap();
8271 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8272 }
8273 }
8274
8275 #[test]
8276 fn test_encode_mve_mvn_thumb2() {
8277 let encoder = ArmEncoder::new_thumb2();
8278 let op = ArmOp::MveMvn {
8279 qd: QReg::Q0,
8280 qm: QReg::Q1,
8281 };
8282 let code = encoder.encode(&op).unwrap();
8283 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8284 }
8285
8286 #[test]
8287 fn test_encode_mve_load_store_thumb2() {
8288 let encoder = ArmEncoder::new_thumb2();
8289
8290 let load = ArmOp::MveLoad {
8291 qd: QReg::Q0,
8292 addr: MemAddr::imm(Reg::R0, 16),
8293 };
8294 let code = encoder.encode(&load).unwrap();
8295 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8296
8297 let store = ArmOp::MveStore {
8298 qd: QReg::Q1,
8299 addr: MemAddr::imm(Reg::R1, 0),
8300 };
8301 let code = encoder.encode(&store).unwrap();
8302 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8303 }
8304
8305 #[test]
8306 fn test_encode_mve_const_thumb2() {
8307 let encoder = ArmEncoder::new_thumb2();
8308 let op = ArmOp::MveConst {
8309 qd: QReg::Q0,
8310 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8311 };
8312 let code = encoder.encode(&op).unwrap();
8313 assert!(
8316 code.len() >= 24,
8317 "MVE const should produce multiple instructions"
8318 );
8319 }
8320
8321 #[test]
8322 fn test_encode_mve_dup_thumb2() {
8323 let encoder = ArmEncoder::new_thumb2();
8324 let op = ArmOp::MveDup {
8325 qd: QReg::Q0,
8326 rn: Reg::R0,
8327 size: MveSize::S32,
8328 };
8329 let code = encoder.encode(&op).unwrap();
8330 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8331 }
8332
8333 #[test]
8334 fn test_encode_mve_extract_lane_thumb2() {
8335 let encoder = ArmEncoder::new_thumb2();
8336 let op = ArmOp::MveExtractLane {
8337 rd: Reg::R0,
8338 qn: QReg::Q1,
8339 lane: 2,
8340 size: MveSize::S32,
8341 };
8342 let code = encoder.encode(&op).unwrap();
8343 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8344 }
8345
8346 #[test]
8347 fn test_encode_mve_insert_lane_thumb2() {
8348 let encoder = ArmEncoder::new_thumb2();
8349 let op = ArmOp::MveInsertLane {
8350 qd: QReg::Q0,
8351 rn: Reg::R1,
8352 lane: 3,
8353 size: MveSize::S32,
8354 };
8355 let code = encoder.encode(&op).unwrap();
8356 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8357 }
8358
8359 #[test]
8360 fn test_encode_mve_addf32_thumb2() {
8361 let encoder = ArmEncoder::new_thumb2();
8362 let op = ArmOp::MveAddF32 {
8363 qd: QReg::Q0,
8364 qn: QReg::Q1,
8365 qm: QReg::Q2,
8366 };
8367 let code = encoder.encode(&op).unwrap();
8368 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8369 }
8370
8371 #[test]
8372 fn test_encode_mve_divf32_thumb2() {
8373 let encoder = ArmEncoder::new_thumb2();
8374 let op = ArmOp::MveDivF32 {
8375 qd: QReg::Q0,
8376 qn: QReg::Q1,
8377 qm: QReg::Q2,
8378 };
8379 let code = encoder.encode(&op).unwrap();
8380 assert_eq!(
8382 code.len(),
8383 16,
8384 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8385 );
8386 }
8387
8388 #[test]
8389 fn test_encode_mve_sqrtf32_thumb2() {
8390 let encoder = ArmEncoder::new_thumb2();
8391 let op = ArmOp::MveSqrtF32 {
8392 qd: QReg::Q0,
8393 qm: QReg::Q1,
8394 };
8395 let code = encoder.encode(&op).unwrap();
8396 assert_eq!(
8398 code.len(),
8399 16,
8400 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8401 );
8402 }
8403
8404 #[test]
8405 fn test_encode_mve_negf32_thumb2() {
8406 let encoder = ArmEncoder::new_thumb2();
8407 let op = ArmOp::MveNegF32 {
8408 qd: QReg::Q0,
8409 qm: QReg::Q1,
8410 };
8411 let code = encoder.encode(&op).unwrap();
8412 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8413 }
8414
8415 #[test]
8416 fn test_encode_mve_absf32_thumb2() {
8417 let encoder = ArmEncoder::new_thumb2();
8418 let op = ArmOp::MveAbsF32 {
8419 qd: QReg::Q0,
8420 qm: QReg::Q1,
8421 };
8422 let code = encoder.encode(&op).unwrap();
8423 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8424 }
8425
8426 #[test]
8427 fn test_encode_mve_different_qregs() {
8428 let encoder = ArmEncoder::new_thumb2();
8429
8430 let op1 = ArmOp::MveAddI {
8432 qd: QReg::Q0,
8433 qn: QReg::Q0,
8434 qm: QReg::Q0,
8435 size: MveSize::S32,
8436 };
8437 let op2 = ArmOp::MveAddI {
8438 qd: QReg::Q3,
8439 qn: QReg::Q5,
8440 qm: QReg::Q7,
8441 size: MveSize::S32,
8442 };
8443 let code1 = encoder.encode(&op1).unwrap();
8444 let code2 = encoder.encode(&op2).unwrap();
8445 assert_ne!(
8446 code1, code2,
8447 "Different Q-registers should produce different encodings"
8448 );
8449 }
8450
8451 #[test]
8452 fn test_encode_mve_arm32_nop() {
8453 let encoder = ArmEncoder::new_arm32();
8455 let op = ArmOp::MveAddI {
8456 qd: QReg::Q0,
8457 qn: QReg::Q1,
8458 qm: QReg::Q2,
8459 size: MveSize::S32,
8460 };
8461 let code = encoder.encode(&op).unwrap();
8462 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8463 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8465 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8466 }
8467}