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;
2498 let hw2: u16 = 0xD000;
2499 let mut bytes = hw1.to_le_bytes().to_vec();
2500 bytes.extend_from_slice(&hw2.to_le_bytes());
2501 Ok(bytes)
2502 }
2503
2504 ArmOp::Mvn { rd, op2 } => {
2506 if let Operand2::Reg(rm) = op2 {
2507 let rd_bits = reg_to_bits(rd) as u16;
2508 let rm_bits = reg_to_bits(rm) as u16;
2509
2510 if rd_bits < 8 && rm_bits < 8 {
2511 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2513 Ok(instr.to_le_bytes().to_vec())
2514 } else {
2515 let hw1: u16 = 0xEA6F_u16;
2517 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2518 let mut bytes = hw1.to_le_bytes().to_vec();
2519 bytes.extend_from_slice(&hw2.to_le_bytes());
2520 Ok(bytes)
2521 }
2522 } else {
2523 let instr: u16 = 0xBF00;
2524 Ok(instr.to_le_bytes().to_vec())
2525 }
2526 }
2527
2528 ArmOp::Movw { rd, imm16 } => {
2530 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2531 }
2532
2533 ArmOp::Movt { rd, imm16 } => {
2535 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2536 }
2537
2538 ArmOp::SetCond { rd, cond } => {
2544 let rd_bits = reg_to_bits(rd) as u16;
2545
2546 use synth_synthesis::Condition;
2548 let cond_bits: u16 = match cond {
2549 Condition::EQ => 0x0,
2550 Condition::NE => 0x1,
2551 Condition::LT => 0xB,
2552 Condition::LE => 0xD,
2553 Condition::GT => 0xC,
2554 Condition::GE => 0xA,
2555 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2560
2561 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2566 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2567
2568 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2570
2571 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2573
2574 let mut bytes = ite_instr.to_le_bytes().to_vec();
2576 bytes.extend_from_slice(&mov_one.to_le_bytes());
2577 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2578 Ok(bytes)
2579 }
2580
2581 ArmOp::I64SetCond {
2586 rd,
2587 rn_lo,
2588 rn_hi,
2589 rm_lo,
2590 rm_hi,
2591 cond,
2592 } => {
2593 use synth_synthesis::Condition;
2594 let rd_bits = reg_to_bits(rd) as u16;
2595 let mut bytes = Vec::new();
2596
2597 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2599 rm: &synth_synthesis::Reg|
2600 -> Vec<u8> {
2601 let rn_bits = reg_to_bits(rn) as u16;
2602 let rm_bits = reg_to_bits(rm) as u16;
2603 if rn_bits < 8 && rm_bits < 8 {
2604 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2605 instr.to_le_bytes().to_vec()
2606 } else {
2607 let n_bit = (rn_bits >> 3) & 1;
2608 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2609 instr.to_le_bytes().to_vec()
2610 }
2611 };
2612
2613 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2615 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2616 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2617 ite_instr.to_le_bytes().to_vec()
2618 };
2619
2620 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2622 let mut b = encode_ite(cond_bits);
2623 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2624 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2625 b.extend_from_slice(&mov_one.to_le_bytes());
2626 b.extend_from_slice(&mov_zero.to_le_bytes());
2627 b
2628 };
2629
2630 match cond {
2631 Condition::EQ | Condition::NE => {
2632 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2634
2635 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2638
2639 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2641
2642 let cond_bits: u16 = match cond {
2644 Condition::EQ => 0x0,
2645 Condition::NE => 0x1,
2646 _ => unreachable!(),
2647 };
2648 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2649 }
2650
2651 Condition::LT => {
2652 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2654
2655 let rn_hi_bits = reg_to_bits(rn_hi);
2658 let rm_hi_bits = reg_to_bits(rm_hi);
2659 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2660 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2661 bytes.extend_from_slice(&hw1.to_le_bytes());
2662 bytes.extend_from_slice(&hw2.to_le_bytes());
2663
2664 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2667
2668 Condition::GT => {
2669 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2672
2673 let rm_hi_bits = reg_to_bits(rm_hi);
2675 let rn_hi_bits = reg_to_bits(rn_hi);
2676 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2677 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2678 bytes.extend_from_slice(&hw1.to_le_bytes());
2679 bytes.extend_from_slice(&hw2.to_le_bytes());
2680
2681 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2684
2685 Condition::LE => {
2686 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2690
2691 let rm_hi_bits = reg_to_bits(rm_hi);
2693 let rn_hi_bits = reg_to_bits(rn_hi);
2694 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2695 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2696 bytes.extend_from_slice(&hw1.to_le_bytes());
2697 bytes.extend_from_slice(&hw2.to_le_bytes());
2698
2699 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2702
2703 Condition::GE => {
2704 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2707
2708 let rn_hi_bits = reg_to_bits(rn_hi);
2710 let rm_hi_bits = reg_to_bits(rm_hi);
2711 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2712 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2713 bytes.extend_from_slice(&hw1.to_le_bytes());
2714 bytes.extend_from_slice(&hw2.to_le_bytes());
2715
2716 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2719
2720 Condition::LO => {
2722 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2724 let rn_hi_bits = reg_to_bits(rn_hi);
2725 let rm_hi_bits = reg_to_bits(rm_hi);
2726 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2727 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2728 bytes.extend_from_slice(&hw1.to_le_bytes());
2729 bytes.extend_from_slice(&hw2.to_le_bytes());
2730 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2732
2733 Condition::HI => {
2734 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2736 let rm_hi_bits = reg_to_bits(rm_hi);
2737 let rn_hi_bits = reg_to_bits(rn_hi);
2738 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2739 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2740 bytes.extend_from_slice(&hw1.to_le_bytes());
2741 bytes.extend_from_slice(&hw2.to_le_bytes());
2742 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2744
2745 Condition::LS => {
2746 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2748 let rm_hi_bits = reg_to_bits(rm_hi);
2749 let rn_hi_bits = reg_to_bits(rn_hi);
2750 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2751 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2752 bytes.extend_from_slice(&hw1.to_le_bytes());
2753 bytes.extend_from_slice(&hw2.to_le_bytes());
2754 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2756
2757 Condition::HS => {
2758 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2760 let rn_hi_bits = reg_to_bits(rn_hi);
2761 let rm_hi_bits = reg_to_bits(rm_hi);
2762 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2763 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2764 bytes.extend_from_slice(&hw1.to_le_bytes());
2765 bytes.extend_from_slice(&hw2.to_le_bytes());
2766 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2768 }
2769
2770 Ok(bytes)
2771 }
2772
2773 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2776 let rd_bits = reg_to_bits(rd);
2777 let rn_lo_bits = reg_to_bits(rn_lo);
2778 let rn_hi_bits = reg_to_bits(rn_hi);
2779 let mut bytes = Vec::new();
2780
2781 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2783 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2784 bytes.extend_from_slice(&hw1.to_le_bytes());
2785 bytes.extend_from_slice(&hw2.to_le_bytes());
2786
2787 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2789 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2790
2791 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2794 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2795 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2796 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2797 bytes.extend_from_slice(&mov_one.to_le_bytes());
2798 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2799
2800 Ok(bytes)
2801 }
2802
2803 ArmOp::I64Mul {
2807 rd_lo,
2808 rd_hi,
2809 rn_lo,
2810 rn_hi,
2811 rm_lo,
2812 rm_hi,
2813 } => {
2814 let rd_lo_bits = reg_to_bits(rd_lo);
2815 let rd_hi_bits = reg_to_bits(rd_hi);
2816 let rn_lo_bits = reg_to_bits(rn_lo);
2817 let rn_hi_bits = reg_to_bits(rn_hi);
2818 let rm_lo_bits = reg_to_bits(rm_lo);
2819 let rm_hi_bits = reg_to_bits(rm_hi);
2820 let r12: u32 = 12; let mut bytes = Vec::new();
2822
2823 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2826 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2827 bytes.extend_from_slice(&hw1.to_le_bytes());
2828 bytes.extend_from_slice(&hw2.to_le_bytes());
2829
2830 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2833 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_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 = (0xFBA0 | rn_lo_bits) as u16;
2840 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 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 d_bit = (rd_hi_bits >> 3) & 1;
2847 let add_instr: u16 =
2848 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
2849 bytes.extend_from_slice(&add_instr.to_le_bytes());
2850
2851 Ok(bytes)
2852 }
2853
2854 ArmOp::I64Shl {
2857 rd_lo,
2858 rd_hi,
2859 rn_lo,
2860 rn_hi,
2861 rm_lo,
2862 rm_hi,
2863 } => {
2864 let rd_lo_bits = reg_to_bits(rd_lo);
2865 let rd_hi_bits = reg_to_bits(rd_hi);
2866 let rn_lo_bits = reg_to_bits(rn_lo);
2867 let rn_hi_bits = reg_to_bits(rn_hi);
2868 let rm_lo_bits = reg_to_bits(rm_lo);
2869 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2871
2872 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2874 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2875 bytes.extend_from_slice(&hw1.to_le_bytes());
2876 bytes.extend_from_slice(&hw2.to_le_bytes());
2877
2878 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2880 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2881 bytes.extend_from_slice(&hw1.to_le_bytes());
2882 bytes.extend_from_slice(&hw2.to_le_bytes());
2883
2884 let bpl: u16 = 0xD50A;
2886 bytes.extend_from_slice(&bpl.to_le_bytes());
2887
2888 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2891 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2892 bytes.extend_from_slice(&hw1.to_le_bytes());
2893 bytes.extend_from_slice(&hw2.to_le_bytes());
2894
2895 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2897 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2898 bytes.extend_from_slice(&hw1.to_le_bytes());
2899 bytes.extend_from_slice(&hw2.to_le_bytes());
2900
2901 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2903 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2904 bytes.extend_from_slice(&hw1.to_le_bytes());
2905 bytes.extend_from_slice(&hw2.to_le_bytes());
2906
2907 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
2909 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
2910 bytes.extend_from_slice(&hw1.to_le_bytes());
2911 bytes.extend_from_slice(&hw2.to_le_bytes());
2912
2913 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2915 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2916 bytes.extend_from_slice(&hw1.to_le_bytes());
2917 bytes.extend_from_slice(&hw2.to_le_bytes());
2918
2919 let b_done: u16 = 0xE002;
2921 bytes.extend_from_slice(&b_done.to_le_bytes());
2922
2923 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2926 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
2927 bytes.extend_from_slice(&hw1.to_le_bytes());
2928 bytes.extend_from_slice(&hw2.to_le_bytes());
2929
2930 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
2932 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2933
2934 Ok(bytes) }
2936
2937 ArmOp::I64ShrU {
2939 rd_lo,
2940 rd_hi,
2941 rn_lo,
2942 rn_hi,
2943 rm_lo,
2944 rm_hi,
2945 } => {
2946 let rd_lo_bits = reg_to_bits(rd_lo);
2947 let rd_hi_bits = reg_to_bits(rd_hi);
2948 let rn_lo_bits = reg_to_bits(rn_lo);
2949 let rn_hi_bits = reg_to_bits(rn_hi);
2950 let rm_lo_bits = reg_to_bits(rm_lo);
2951 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2953
2954 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2956 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2957 bytes.extend_from_slice(&hw1.to_le_bytes());
2958 bytes.extend_from_slice(&hw2.to_le_bytes());
2959
2960 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2962 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2963 bytes.extend_from_slice(&hw1.to_le_bytes());
2964 bytes.extend_from_slice(&hw2.to_le_bytes());
2965
2966 let bpl: u16 = 0xD50A;
2968 bytes.extend_from_slice(&bpl.to_le_bytes());
2969
2970 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2973 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2974 bytes.extend_from_slice(&hw1.to_le_bytes());
2975 bytes.extend_from_slice(&hw2.to_le_bytes());
2976
2977 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2979 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2980 bytes.extend_from_slice(&hw1.to_le_bytes());
2981 bytes.extend_from_slice(&hw2.to_le_bytes());
2982
2983 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2985 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2986 bytes.extend_from_slice(&hw1.to_le_bytes());
2987 bytes.extend_from_slice(&hw2.to_le_bytes());
2988
2989 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
2991 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
2992 bytes.extend_from_slice(&hw1.to_le_bytes());
2993 bytes.extend_from_slice(&hw2.to_le_bytes());
2994
2995 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
2997 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2998 bytes.extend_from_slice(&hw1.to_le_bytes());
2999 bytes.extend_from_slice(&hw2.to_le_bytes());
3000
3001 let b_done: u16 = 0xE002;
3003 bytes.extend_from_slice(&b_done.to_le_bytes());
3004
3005 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3008 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3009 bytes.extend_from_slice(&hw1.to_le_bytes());
3010 bytes.extend_from_slice(&hw2.to_le_bytes());
3011
3012 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3014 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3015
3016 Ok(bytes) }
3018
3019 ArmOp::I64ShrS {
3021 rd_lo,
3022 rd_hi,
3023 rn_lo,
3024 rn_hi,
3025 rm_lo,
3026 rm_hi,
3027 } => {
3028 let rd_lo_bits = reg_to_bits(rd_lo);
3029 let rd_hi_bits = reg_to_bits(rd_hi);
3030 let rn_lo_bits = reg_to_bits(rn_lo);
3031 let rn_hi_bits = reg_to_bits(rn_hi);
3032 let rm_lo_bits = reg_to_bits(rm_lo);
3033 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3035
3036 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3038 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3039 bytes.extend_from_slice(&hw1.to_le_bytes());
3040 bytes.extend_from_slice(&hw2.to_le_bytes());
3041
3042 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3044 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3045 bytes.extend_from_slice(&hw1.to_le_bytes());
3046 bytes.extend_from_slice(&hw2.to_le_bytes());
3047
3048 let bpl: u16 = 0xD50A;
3050 bytes.extend_from_slice(&bpl.to_le_bytes());
3051
3052 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3055 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3056 bytes.extend_from_slice(&hw1.to_le_bytes());
3057 bytes.extend_from_slice(&hw2.to_le_bytes());
3058
3059 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3061 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3062 bytes.extend_from_slice(&hw1.to_le_bytes());
3063 bytes.extend_from_slice(&hw2.to_le_bytes());
3064
3065 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3067 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3068 bytes.extend_from_slice(&hw1.to_le_bytes());
3069 bytes.extend_from_slice(&hw2.to_le_bytes());
3070
3071 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3073 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3074 bytes.extend_from_slice(&hw1.to_le_bytes());
3075 bytes.extend_from_slice(&hw2.to_le_bytes());
3076
3077 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3079 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3080 bytes.extend_from_slice(&hw1.to_le_bytes());
3081 bytes.extend_from_slice(&hw2.to_le_bytes());
3082
3083 let b_done: u16 = 0xE003;
3085 bytes.extend_from_slice(&b_done.to_le_bytes());
3086
3087 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3090 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3091 bytes.extend_from_slice(&hw1.to_le_bytes());
3092 bytes.extend_from_slice(&hw2.to_le_bytes());
3093
3094 let hw1: u16 = 0xEA4F;
3098 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3099 bytes.extend_from_slice(&hw1.to_le_bytes());
3100 bytes.extend_from_slice(&hw2.to_le_bytes());
3101
3102 Ok(bytes) }
3104
3105 ArmOp::I64Rotl {
3110 rdlo,
3111 rdhi,
3112 rnlo,
3113 rnhi,
3114 shift,
3115 } => {
3116 let rd_lo_bits = reg_to_bits(rdlo);
3117 let rd_hi_bits = reg_to_bits(rdhi);
3118 let rn_lo_bits = reg_to_bits(rnlo);
3119 let rn_hi_bits = reg_to_bits(rnhi);
3120 let shift_bits = reg_to_bits(shift);
3121 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3125
3126 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3128
3129 let hw1: u16 = (0xF000 | shift_bits) as u16;
3131 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3132 bytes.extend_from_slice(&hw1.to_le_bytes());
3133 bytes.extend_from_slice(&hw2.to_le_bytes());
3134
3135 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3137 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3138 bytes.extend_from_slice(&hw1.to_le_bytes());
3139 bytes.extend_from_slice(&hw2.to_le_bytes());
3140
3141 let bpl: u16 = 0xD50E;
3143 bytes.extend_from_slice(&bpl.to_le_bytes());
3144
3145 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3148 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3149 bytes.extend_from_slice(&hw1.to_le_bytes());
3150 bytes.extend_from_slice(&hw2.to_le_bytes());
3151
3152 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3154 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3155 bytes.extend_from_slice(&hw1.to_le_bytes());
3156 bytes.extend_from_slice(&hw2.to_le_bytes());
3157
3158 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3160 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3161 bytes.extend_from_slice(&hw1.to_le_bytes());
3162 bytes.extend_from_slice(&hw2.to_le_bytes());
3163
3164 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3166 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3167 bytes.extend_from_slice(&hw1.to_le_bytes());
3168 bytes.extend_from_slice(&hw2.to_le_bytes());
3169
3170 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3172 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3173 bytes.extend_from_slice(&hw1.to_le_bytes());
3174 bytes.extend_from_slice(&hw2.to_le_bytes());
3175
3176 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3178 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3179 bytes.extend_from_slice(&hw1.to_le_bytes());
3180 bytes.extend_from_slice(&hw2.to_le_bytes());
3181
3182 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3184 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3185 bytes.extend_from_slice(&hw1.to_le_bytes());
3186 bytes.extend_from_slice(&hw2.to_le_bytes());
3187
3188 let b_done: u16 = 0xE00E;
3190 bytes.extend_from_slice(&b_done.to_le_bytes());
3191
3192 let hw1: u16 = (0xF1C0 | r3) as u16;
3196 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3197 bytes.extend_from_slice(&hw1.to_le_bytes());
3198 bytes.extend_from_slice(&hw2.to_le_bytes());
3199
3200 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3202 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3203 bytes.extend_from_slice(&hw1.to_le_bytes());
3204 bytes.extend_from_slice(&hw2.to_le_bytes());
3205
3206 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3208 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3209 bytes.extend_from_slice(&hw1.to_le_bytes());
3210 bytes.extend_from_slice(&hw2.to_le_bytes());
3211
3212 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3214 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3215 bytes.extend_from_slice(&hw1.to_le_bytes());
3216 bytes.extend_from_slice(&hw2.to_le_bytes());
3217
3218 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3220 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3221 bytes.extend_from_slice(&hw1.to_le_bytes());
3222 bytes.extend_from_slice(&hw2.to_le_bytes());
3223
3224 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3226 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3227 bytes.extend_from_slice(&hw1.to_le_bytes());
3228 bytes.extend_from_slice(&hw2.to_le_bytes());
3229
3230 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3232 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3233 bytes.extend_from_slice(&hw1.to_le_bytes());
3234 bytes.extend_from_slice(&hw2.to_le_bytes());
3235
3236 let d_bit = (rd_hi_bits >> 3) & 1;
3238 let mov_instr: u16 =
3239 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3240 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3241
3242 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3244
3245 Ok(bytes) }
3247
3248 ArmOp::I64Rotr {
3253 rdlo,
3254 rdhi,
3255 rnlo,
3256 rnhi,
3257 shift,
3258 } => {
3259 let rd_lo_bits = reg_to_bits(rdlo);
3260 let rd_hi_bits = reg_to_bits(rdhi);
3261 let rn_lo_bits = reg_to_bits(rnlo);
3262 let rn_hi_bits = reg_to_bits(rnhi);
3263 let shift_bits = reg_to_bits(shift);
3264 let r12: u32 = 12;
3265 let r3: u32 = 3;
3266 let r4: u32 = 4;
3267 let mut bytes = Vec::new();
3268
3269 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3271
3272 let hw1: u16 = (0xF000 | shift_bits) as u16;
3274 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3275 bytes.extend_from_slice(&hw1.to_le_bytes());
3276 bytes.extend_from_slice(&hw2.to_le_bytes());
3277
3278 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3280 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3281 bytes.extend_from_slice(&hw1.to_le_bytes());
3282 bytes.extend_from_slice(&hw2.to_le_bytes());
3283
3284 let bpl: u16 = 0xD50E;
3286 bytes.extend_from_slice(&bpl.to_le_bytes());
3287
3288 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3291 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3292 bytes.extend_from_slice(&hw1.to_le_bytes());
3293 bytes.extend_from_slice(&hw2.to_le_bytes());
3294
3295 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3297 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3298 bytes.extend_from_slice(&hw1.to_le_bytes());
3299 bytes.extend_from_slice(&hw2.to_le_bytes());
3300
3301 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3303 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3304 bytes.extend_from_slice(&hw1.to_le_bytes());
3305 bytes.extend_from_slice(&hw2.to_le_bytes());
3306
3307 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3309 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3310 bytes.extend_from_slice(&hw1.to_le_bytes());
3311 bytes.extend_from_slice(&hw2.to_le_bytes());
3312
3313 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3315 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3316 bytes.extend_from_slice(&hw1.to_le_bytes());
3317 bytes.extend_from_slice(&hw2.to_le_bytes());
3318
3319 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3321 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3322 bytes.extend_from_slice(&hw1.to_le_bytes());
3323 bytes.extend_from_slice(&hw2.to_le_bytes());
3324
3325 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3327 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3328 bytes.extend_from_slice(&hw1.to_le_bytes());
3329 bytes.extend_from_slice(&hw2.to_le_bytes());
3330
3331 let b_done: u16 = 0xE00E;
3333 bytes.extend_from_slice(&b_done.to_le_bytes());
3334
3335 let hw1: u16 = (0xF1C0 | r3) as u16;
3338 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3339 bytes.extend_from_slice(&hw1.to_le_bytes());
3340 bytes.extend_from_slice(&hw2.to_le_bytes());
3341
3342 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3344 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3345 bytes.extend_from_slice(&hw1.to_le_bytes());
3346 bytes.extend_from_slice(&hw2.to_le_bytes());
3347
3348 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3350 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3351 bytes.extend_from_slice(&hw1.to_le_bytes());
3352 bytes.extend_from_slice(&hw2.to_le_bytes());
3353
3354 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3356 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3357 bytes.extend_from_slice(&hw1.to_le_bytes());
3358 bytes.extend_from_slice(&hw2.to_le_bytes());
3359
3360 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3362 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3363 bytes.extend_from_slice(&hw1.to_le_bytes());
3364 bytes.extend_from_slice(&hw2.to_le_bytes());
3365
3366 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3368 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3369 bytes.extend_from_slice(&hw1.to_le_bytes());
3370 bytes.extend_from_slice(&hw2.to_le_bytes());
3371
3372 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3374 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3375 bytes.extend_from_slice(&hw1.to_le_bytes());
3376 bytes.extend_from_slice(&hw2.to_le_bytes());
3377
3378 let d_bit = (rd_lo_bits >> 3) & 1;
3380 let mov_instr: u16 =
3381 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3382 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3383
3384 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3386
3387 Ok(bytes) }
3389
3390 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3404 let rd_bits = reg_to_bits(rd);
3405 let rn_lo_bits = reg_to_bits(rnlo);
3406 let rn_hi_bits = reg_to_bits(rnhi);
3407 let mut bytes = Vec::new();
3408
3409 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3411 let hw2: u16 = 0x0F00;
3412 bytes.extend_from_slice(&hw1.to_le_bytes());
3413 bytes.extend_from_slice(&hw2.to_le_bytes());
3414
3415 let beq: u16 = 0xD003;
3418 bytes.extend_from_slice(&beq.to_le_bytes());
3419
3420 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3423 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3424 bytes.extend_from_slice(&hw1.to_le_bytes());
3425 bytes.extend_from_slice(&hw2.to_le_bytes());
3426
3427 let b_done: u16 = 0xE004;
3430 bytes.extend_from_slice(&b_done.to_le_bytes());
3431
3432 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3434
3435 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3439 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3440 bytes.extend_from_slice(&hw1.to_le_bytes());
3441 bytes.extend_from_slice(&hw2.to_le_bytes());
3442
3443 let hw1: u16 = (0xF100 | rd_bits) as u16;
3445 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3446 bytes.extend_from_slice(&hw1.to_le_bytes());
3447 bytes.extend_from_slice(&hw2.to_le_bytes());
3448
3449 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3453 bytes.extend_from_slice(&mov0.to_le_bytes());
3454
3455 Ok(bytes)
3456 }
3457
3458 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3474 let rd_bits = reg_to_bits(rd);
3475 let rn_lo_bits = reg_to_bits(rnlo);
3476 let rn_hi_bits = reg_to_bits(rnhi);
3477 let mut bytes = Vec::new();
3478
3479 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3481 let hw2: u16 = 0x0F00;
3482 bytes.extend_from_slice(&hw1.to_le_bytes());
3483 bytes.extend_from_slice(&hw2.to_le_bytes());
3484
3485 let beq: u16 = 0xD005;
3488 bytes.extend_from_slice(&beq.to_le_bytes());
3489
3490 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3493 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3494 bytes.extend_from_slice(&hw1.to_le_bytes());
3495 bytes.extend_from_slice(&hw2.to_le_bytes());
3496
3497 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3500 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3501 bytes.extend_from_slice(&hw1.to_le_bytes());
3502 bytes.extend_from_slice(&hw2.to_le_bytes());
3503
3504 let b_done: u16 = 0xE006;
3507 bytes.extend_from_slice(&b_done.to_le_bytes());
3508
3509 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3511
3512 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3516 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3517 bytes.extend_from_slice(&hw1.to_le_bytes());
3518 bytes.extend_from_slice(&hw2.to_le_bytes());
3519
3520 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3523 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_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 = (0xF100 | rd_bits) as u16;
3529 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3530 bytes.extend_from_slice(&hw1.to_le_bytes());
3531 bytes.extend_from_slice(&hw2.to_le_bytes());
3532
3533 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3536 bytes.extend_from_slice(&mov0.to_le_bytes());
3537
3538 Ok(bytes)
3539 }
3540
3541 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3545 let rd_bits = reg_to_bits(rd);
3546 let rn_lo_bits = reg_to_bits(rnlo);
3547 let rn_hi_bits = reg_to_bits(rnhi);
3548 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3551
3552 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3554
3555 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3565 bytes.extend_from_slice(&mov.to_le_bytes());
3566
3567 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3570 bytes.extend_from_slice(&mov.to_le_bytes());
3571
3572 let hw1: u16 = 0xEA4F;
3576 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3577 bytes.extend_from_slice(&hw1.to_le_bytes());
3578 bytes.extend_from_slice(&hw2.to_le_bytes());
3579
3580 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3583 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3584 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3586 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3587
3588 let hw1: u16 = (0xEA00 | r12) as u16;
3590 let hw2: u16 = ((r12 << 8) | r3) as u16;
3591 bytes.extend_from_slice(&hw1.to_le_bytes());
3592 bytes.extend_from_slice(&hw2.to_le_bytes());
3593
3594 let hw1: u16 = (0xEBA0 | 4) as u16;
3596 let hw2: u16 = ((4 << 8) | r12) as u16;
3597 bytes.extend_from_slice(&hw1.to_le_bytes());
3598 bytes.extend_from_slice(&hw2.to_le_bytes());
3599
3600 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3604 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3605 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3607 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3608
3609 let hw1: u16 = (0xEA00 | 4) as u16;
3611 let hw2: u16 = ((r12 << 8) | r3) as u16;
3612 bytes.extend_from_slice(&hw1.to_le_bytes());
3613 bytes.extend_from_slice(&hw2.to_le_bytes());
3614
3615 let hw1: u16 = 0xEA4F;
3617 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3618 bytes.extend_from_slice(&hw1.to_le_bytes());
3619 bytes.extend_from_slice(&hw2.to_le_bytes());
3620
3621 let hw1: u16 = (0xEA00 | 4) as u16;
3623 let hw2: u16 = ((4 << 8) | r3) as u16;
3624 bytes.extend_from_slice(&hw1.to_le_bytes());
3625 bytes.extend_from_slice(&hw2.to_le_bytes());
3626
3627 let hw1: u16 = (0xEB00 | 4) as u16;
3629 let hw2: u16 = ((4 << 8) | r12) as u16;
3630 bytes.extend_from_slice(&hw1.to_le_bytes());
3631 bytes.extend_from_slice(&hw2.to_le_bytes());
3632
3633 let hw1: u16 = 0xEA4F;
3638 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3639 bytes.extend_from_slice(&hw1.to_le_bytes());
3640 bytes.extend_from_slice(&hw2.to_le_bytes());
3641
3642 let hw1: u16 = (0xEB00 | 4) as u16;
3644 let hw2: u16 = ((4 << 8) | r12) as u16;
3645 bytes.extend_from_slice(&hw1.to_le_bytes());
3646 bytes.extend_from_slice(&hw2.to_le_bytes());
3647
3648 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3653 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3654 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3656 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3657
3658 let hw1: u16 = (0xEA00 | 4) as u16;
3660 let hw2: u16 = ((4 << 8) | r3) as u16;
3661 bytes.extend_from_slice(&hw1.to_le_bytes());
3662 bytes.extend_from_slice(&hw2.to_le_bytes());
3663
3664 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3668 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3669 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3671 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3672
3673 let hw1: u16 = (0xFB00 | 4) as u16;
3676 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3677 bytes.extend_from_slice(&hw1.to_le_bytes());
3678 bytes.extend_from_slice(&hw2.to_le_bytes());
3679
3680 let hw1: u16 = 0xEA4F;
3683 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) 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 = ((r12 << 8) | 0x50 | 5) as u16;
3691 bytes.extend_from_slice(&hw1.to_le_bytes());
3692 bytes.extend_from_slice(&hw2.to_le_bytes());
3693
3694 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3696 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3697 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3698 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3699
3700 let hw1: u16 = (0xEA00 | r12) as u16;
3701 let hw2: u16 = ((r12 << 8) | r3) as u16;
3702 bytes.extend_from_slice(&hw1.to_le_bytes());
3703 bytes.extend_from_slice(&hw2.to_le_bytes());
3704
3705 let hw1: u16 = (0xEBA0 | 5) as u16;
3706 let hw2: u16 = ((5 << 8) | r12) as u16;
3707 bytes.extend_from_slice(&hw1.to_le_bytes());
3708 bytes.extend_from_slice(&hw2.to_le_bytes());
3709
3710 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3712 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3713 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3714 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3715
3716 let hw1: u16 = (0xEA00 | 5) as u16;
3717 let hw2: u16 = ((r12 << 8) | r3) as u16;
3718 bytes.extend_from_slice(&hw1.to_le_bytes());
3719 bytes.extend_from_slice(&hw2.to_le_bytes());
3720
3721 let hw1: u16 = 0xEA4F;
3722 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3723 bytes.extend_from_slice(&hw1.to_le_bytes());
3724 bytes.extend_from_slice(&hw2.to_le_bytes());
3725
3726 let hw1: u16 = (0xEA00 | 5) as u16;
3727 let hw2: u16 = ((5 << 8) | r3) as u16;
3728 bytes.extend_from_slice(&hw1.to_le_bytes());
3729 bytes.extend_from_slice(&hw2.to_le_bytes());
3730
3731 let hw1: u16 = (0xEB00 | 5) as u16;
3732 let hw2: u16 = ((5 << 8) | r12) as u16;
3733 bytes.extend_from_slice(&hw1.to_le_bytes());
3734 bytes.extend_from_slice(&hw2.to_le_bytes());
3735
3736 let hw1: u16 = 0xEA4F;
3739 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) 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 = (0xEB00 | 5) as u16;
3744 let hw2: u16 = ((5 << 8) | r12) as u16;
3745 bytes.extend_from_slice(&hw1.to_le_bytes());
3746 bytes.extend_from_slice(&hw2.to_le_bytes());
3747
3748 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3750 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3751 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3752 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3753
3754 let hw1: u16 = (0xEA00 | 5) as u16;
3755 let hw2: u16 = ((5 << 8) | r3) as u16;
3756 bytes.extend_from_slice(&hw1.to_le_bytes());
3757 bytes.extend_from_slice(&hw2.to_le_bytes());
3758
3759 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3761 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3762 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3763 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3764
3765 let hw1: u16 = (0xFB00 | 5) as u16;
3768 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3769 bytes.extend_from_slice(&hw1.to_le_bytes());
3770 bytes.extend_from_slice(&hw2.to_le_bytes());
3771
3772 let hw1: u16 = 0xEA4F;
3775 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3776 bytes.extend_from_slice(&hw1.to_le_bytes());
3777 bytes.extend_from_slice(&hw2.to_le_bytes());
3778
3779 let rd_bits_u16 = rd_bits as u16;
3782 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3783 bytes.extend_from_slice(&instr.to_le_bytes());
3784
3785 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3787
3788 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3790 bytes.extend_from_slice(&mov0.to_le_bytes());
3791
3792 Ok(bytes)
3793 }
3794
3795 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3798 let rdlo_bits = reg_to_bits(rdlo);
3799 let rdhi_bits = reg_to_bits(rdhi);
3800 let rnlo_bits = reg_to_bits(rnlo);
3801 let mut bytes = Vec::new();
3802
3803 let hw1: u16 = 0xFA4F_u16;
3806 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3807 bytes.extend_from_slice(&hw1.to_le_bytes());
3808 bytes.extend_from_slice(&hw2.to_le_bytes());
3809
3810 let hw1: u16 = 0xEA4F;
3815 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3816 bytes.extend_from_slice(&hw1.to_le_bytes());
3817 bytes.extend_from_slice(&hw2.to_le_bytes());
3818
3819 Ok(bytes)
3820 }
3821
3822 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3825 let rdlo_bits = reg_to_bits(rdlo);
3826 let rdhi_bits = reg_to_bits(rdhi);
3827 let rnlo_bits = reg_to_bits(rnlo);
3828 let mut bytes = Vec::new();
3829
3830 let hw1: u16 = 0xFA0F_u16;
3833 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3834 bytes.extend_from_slice(&hw1.to_le_bytes());
3835 bytes.extend_from_slice(&hw2.to_le_bytes());
3836
3837 let hw1: u16 = 0xEA4F;
3839 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3840 bytes.extend_from_slice(&hw1.to_le_bytes());
3841 bytes.extend_from_slice(&hw2.to_le_bytes());
3842
3843 Ok(bytes)
3844 }
3845
3846 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
3849 let rdlo_bits = reg_to_bits(rdlo);
3850 let rdhi_bits = reg_to_bits(rdhi);
3851 let rnlo_bits = reg_to_bits(rnlo);
3852 let mut bytes = Vec::new();
3853
3854 if rdlo_bits != rnlo_bits {
3856 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
3858 let mov: u16 = 0x4600
3859 | (d_bit << 7)
3860 | ((rnlo_bits as u16) << 3)
3861 | ((rdlo_bits & 0x7) as u16);
3862 bytes.extend_from_slice(&mov.to_le_bytes());
3863 }
3864
3865 let hw1: u16 = 0xEA4F;
3867 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
3868 bytes.extend_from_slice(&hw1.to_le_bytes());
3869 bytes.extend_from_slice(&hw2.to_le_bytes());
3870
3871 Ok(bytes)
3872 }
3873
3874 ArmOp::SelectMove { rd, rm, cond } => {
3877 let rd_bits = reg_to_bits(rd) as u16;
3878 let rm_bits = reg_to_bits(rm) as u16;
3879
3880 use synth_synthesis::Condition;
3882 let cond_bits: u16 = match cond {
3883 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, };
3894
3895 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
3898
3899 let d_bit = (rd_bits >> 3) & 1;
3902 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3903
3904 let mut bytes = it_instr.to_le_bytes().to_vec();
3906 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3907 Ok(bytes)
3908 }
3909
3910 ArmOp::Popcnt { rd, rm } => {
3921 let mut bytes = Vec::new();
3922
3923 if rd != rm {
3925 let rd_bits = reg_to_bits(rd) as u16;
3926 let rm_bits = reg_to_bits(rm) as u16;
3927 let d_bit = (rd_bits >> 3) & 1;
3929 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3930 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3931 }
3932
3933 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
3936 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
3937
3938 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
3941
3942 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
3944
3945 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
3947 reg_to_bits(rd),
3948 reg_to_bits(rd),
3949 11,
3950 )?);
3951
3952 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
3955 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
3956
3957 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
3959 11,
3960 reg_to_bits(rd),
3961 12,
3962 )?);
3963
3964 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
3966 reg_to_bits(rd),
3967 reg_to_bits(rd),
3968 2,
3969 )?);
3970
3971 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
3973 reg_to_bits(rd),
3974 reg_to_bits(rd),
3975 12,
3976 )?);
3977
3978 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
3980 reg_to_bits(rd),
3981 reg_to_bits(rd),
3982 11,
3983 )?);
3984
3985 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
3988
3989 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
3991 reg_to_bits(rd),
3992 reg_to_bits(rd),
3993 11,
3994 )?);
3995
3996 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
3998 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
3999
4000 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4002 reg_to_bits(rd),
4003 reg_to_bits(rd),
4004 12,
4005 )?);
4006
4007 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4010
4011 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4013 reg_to_bits(rd),
4014 reg_to_bits(rd),
4015 11,
4016 )?);
4017
4018 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4021
4022 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4024 reg_to_bits(rd),
4025 reg_to_bits(rd),
4026 11,
4027 )?);
4028
4029 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4032 reg_to_bits(rd),
4033 reg_to_bits(rd),
4034 0x3F,
4035 )?);
4036
4037 Ok(bytes)
4038 }
4039
4040 ArmOp::I64DivU {
4045 rdlo: _,
4046 rdhi: _,
4047 rnlo: _,
4048 rnhi: _,
4049 rmlo: _,
4050 rmhi: _,
4051 } => {
4052 let mut bytes = Vec::new();
4053
4054 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4058
4059 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());
4070 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4071
4072 let loop_start = bytes.len();
4074
4075 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4086 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());
4095 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4096 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4100 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4101
4102 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4107 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4108 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());
4139 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4140 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4143
4144 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4148 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4149
4150 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4153 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4154 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4155
4156 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4164
4165 Ok(bytes)
4166 }
4167
4168 ArmOp::I64DivS {
4173 rdlo: _,
4174 rdhi: _,
4175 rnlo: _,
4176 rnhi: _,
4177 rmlo: _,
4178 rmhi: _,
4179 } => {
4180 let mut bytes = Vec::new();
4181
4182 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4184 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4185
4186 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4189 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4190
4191 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());
4204
4205 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());
4215
4216 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4219 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4220 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4222 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4223 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4225 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4226
4227 let loop_start = bytes.len();
4228
4229 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4233 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());
4239 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4242
4243 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4247 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());
4260 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4262
4263 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4266
4267 let branch_offset_bytes = bytes.len() - loop_start + 4;
4268 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4269 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4270 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4271
4272 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());
4279 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());
4287
4288 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4290 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4291
4292 Ok(bytes)
4293 }
4294
4295 ArmOp::I64RemU {
4300 rdlo: _,
4301 rdhi: _,
4302 rnlo: _,
4303 rnhi: _,
4304 rmlo: _,
4305 rmhi: _,
4306 } => {
4307 let mut bytes = Vec::new();
4308
4309 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4311 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4312
4313 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4315 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4316 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4318 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4319 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4321 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4322
4323 let loop_start = bytes.len();
4324
4325 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4329 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());
4335 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4338
4339 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4343 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());
4356 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4358
4359 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4362
4363 let branch_offset_bytes = bytes.len() - loop_start + 4;
4364 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4365 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4366 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4367
4368 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4374 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4375
4376 Ok(bytes)
4377 }
4378
4379 ArmOp::I64RemS {
4384 rdlo: _,
4385 rdhi: _,
4386 rnlo: _,
4387 rnhi: _,
4388 rmlo: _,
4389 rmhi: _,
4390 } => {
4391 let mut bytes = Vec::new();
4392
4393 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4395 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4396
4397 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());
4411
4412 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());
4422
4423 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4426 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4427 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4429 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4430 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4432 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4433
4434 let loop_start = bytes.len();
4435
4436 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4440 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());
4446 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4449
4450 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4454 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());
4467 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4469
4470 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4473
4474 let branch_offset_bytes = bytes.len() - loop_start + 4;
4475 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4476 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4477 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4478
4479 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());
4486 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());
4494
4495 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4497 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4498
4499 Ok(bytes)
4500 }
4501
4502 ArmOp::F32Add { sd, sn, sm } => {
4505 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4506 }
4507 ArmOp::F32Sub { sd, sn, sm } => {
4508 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4509 }
4510 ArmOp::F32Mul { sd, sn, sm } => {
4511 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4512 }
4513 ArmOp::F32Div { sd, sn, sm } => {
4514 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4515 }
4516 ArmOp::F32Abs { sd, sm } => {
4517 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4518 }
4519 ArmOp::F32Neg { sd, sm } => {
4520 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4521 }
4522 ArmOp::F32Sqrt { sd, sm } => {
4523 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4524 }
4525
4526 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4529 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4530 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4531 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4532 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4533 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4534 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4535
4536 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4538 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4539 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4540 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4541 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4542 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4543
4544 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4545
4546 ArmOp::F32Load { sd, addr } => {
4547 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4548 }
4549 ArmOp::F32Store { sd, addr } => {
4550 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4551 }
4552
4553 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4554 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4555 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4556 Err(synth_core::Error::synthesis(
4557 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4558 ))
4559 }
4560 ArmOp::F32ReinterpretI32 { sd, rm } => {
4561 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4562 }
4563 ArmOp::I32ReinterpretF32 { rd, sm } => {
4564 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4565 }
4566 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4567 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4568
4569 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4572 0xEE300B00, dd, dn, dm,
4573 )?)),
4574 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4575 0xEE300B40, dd, dn, dm,
4576 )?)),
4577 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4578 0xEE200B00, dd, dn, dm,
4579 )?)),
4580 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4581 0xEE800B00, dd, dn, dm,
4582 )?)),
4583 ArmOp::F64Abs { dd, dm } => {
4584 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4585 }
4586 ArmOp::F64Neg { dd, dm } => {
4587 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4588 }
4589 ArmOp::F64Sqrt { dd, dm } => {
4590 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4591 }
4592
4593 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4596 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4597 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4598 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4599 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4600 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4601 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4602
4603 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4605 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4606 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4607 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4608 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4609 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4610
4611 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4612
4613 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4614 0xED900B00, dd, addr,
4615 )?)),
4616 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4617 0xED800B00, dd, addr,
4618 )?)),
4619
4620 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4621 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4622 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4623 Err(synth_core::Error::synthesis(
4624 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4625 ))
4626 }
4627 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4628 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4629 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4630 )),
4631 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4632 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4633 )),
4634 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4635 Err(synth_core::Error::synthesis(
4636 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4637 ))
4638 }
4639 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4640 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4641
4642 ArmOp::I64Add {
4646 rdlo,
4647 rdhi,
4648 rnlo,
4649 rnhi,
4650 rmlo,
4651 rmhi,
4652 } => {
4653 let mut bytes = Vec::new();
4654 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4656 rd: *rdlo,
4657 rn: *rnlo,
4658 op2: Operand2::Reg(*rmlo),
4659 })?);
4660 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4662 rd: *rdhi,
4663 rn: *rnhi,
4664 op2: Operand2::Reg(*rmhi),
4665 })?);
4666 Ok(bytes)
4667 }
4668
4669 ArmOp::I64Sub {
4671 rdlo,
4672 rdhi,
4673 rnlo,
4674 rnhi,
4675 rmlo,
4676 rmhi,
4677 } => {
4678 let mut bytes = Vec::new();
4679 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4681 rd: *rdlo,
4682 rn: *rnlo,
4683 op2: Operand2::Reg(*rmlo),
4684 })?);
4685 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4687 rd: *rdhi,
4688 rn: *rnhi,
4689 op2: Operand2::Reg(*rmhi),
4690 })?);
4691 Ok(bytes)
4692 }
4693
4694 ArmOp::I64And {
4696 rdlo,
4697 rdhi,
4698 rnlo,
4699 rnhi,
4700 rmlo,
4701 rmhi,
4702 } => {
4703 let mut bytes = Vec::new();
4704 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4705 rd: *rdlo,
4706 rn: *rnlo,
4707 op2: Operand2::Reg(*rmlo),
4708 })?);
4709 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4710 rd: *rdhi,
4711 rn: *rnhi,
4712 op2: Operand2::Reg(*rmhi),
4713 })?);
4714 Ok(bytes)
4715 }
4716
4717 ArmOp::I64Or {
4719 rdlo,
4720 rdhi,
4721 rnlo,
4722 rnhi,
4723 rmlo,
4724 rmhi,
4725 } => {
4726 let mut bytes = Vec::new();
4727 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4728 rd: *rdlo,
4729 rn: *rnlo,
4730 op2: Operand2::Reg(*rmlo),
4731 })?);
4732 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4733 rd: *rdhi,
4734 rn: *rnhi,
4735 op2: Operand2::Reg(*rmhi),
4736 })?);
4737 Ok(bytes)
4738 }
4739
4740 ArmOp::I64Xor {
4742 rdlo,
4743 rdhi,
4744 rnlo,
4745 rnhi,
4746 rmlo,
4747 rmhi,
4748 } => {
4749 let mut bytes = Vec::new();
4750 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4751 rd: *rdlo,
4752 rn: *rnlo,
4753 op2: Operand2::Reg(*rmlo),
4754 })?);
4755 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4756 rd: *rdhi,
4757 rn: *rnhi,
4758 op2: Operand2::Reg(*rmhi),
4759 })?);
4760 Ok(bytes)
4761 }
4762
4763 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4765 rd: *rd,
4766 rn_lo: *rnlo,
4767 rn_hi: *rnhi,
4768 }),
4769
4770 ArmOp::I64Eq {
4772 rd,
4773 rnlo,
4774 rnhi,
4775 rmlo,
4776 rmhi,
4777 } => self.encode_thumb(&ArmOp::I64SetCond {
4778 rd: *rd,
4779 rn_lo: *rnlo,
4780 rn_hi: *rnhi,
4781 rm_lo: *rmlo,
4782 rm_hi: *rmhi,
4783 cond: synth_synthesis::Condition::EQ,
4784 }),
4785
4786 ArmOp::I64Ne {
4787 rd,
4788 rnlo,
4789 rnhi,
4790 rmlo,
4791 rmhi,
4792 } => self.encode_thumb(&ArmOp::I64SetCond {
4793 rd: *rd,
4794 rn_lo: *rnlo,
4795 rn_hi: *rnhi,
4796 rm_lo: *rmlo,
4797 rm_hi: *rmhi,
4798 cond: synth_synthesis::Condition::NE,
4799 }),
4800
4801 ArmOp::I64LtS {
4802 rd,
4803 rnlo,
4804 rnhi,
4805 rmlo,
4806 rmhi,
4807 } => self.encode_thumb(&ArmOp::I64SetCond {
4808 rd: *rd,
4809 rn_lo: *rnlo,
4810 rn_hi: *rnhi,
4811 rm_lo: *rmlo,
4812 rm_hi: *rmhi,
4813 cond: synth_synthesis::Condition::LT,
4814 }),
4815
4816 ArmOp::I64LtU {
4817 rd,
4818 rnlo,
4819 rnhi,
4820 rmlo,
4821 rmhi,
4822 } => self.encode_thumb(&ArmOp::I64SetCond {
4823 rd: *rd,
4824 rn_lo: *rnlo,
4825 rn_hi: *rnhi,
4826 rm_lo: *rmlo,
4827 rm_hi: *rmhi,
4828 cond: synth_synthesis::Condition::LO,
4829 }),
4830
4831 ArmOp::I64LeS {
4832 rd,
4833 rnlo,
4834 rnhi,
4835 rmlo,
4836 rmhi,
4837 } => self.encode_thumb(&ArmOp::I64SetCond {
4838 rd: *rd,
4839 rn_lo: *rnlo,
4840 rn_hi: *rnhi,
4841 rm_lo: *rmlo,
4842 rm_hi: *rmhi,
4843 cond: synth_synthesis::Condition::LE,
4844 }),
4845
4846 ArmOp::I64LeU {
4847 rd,
4848 rnlo,
4849 rnhi,
4850 rmlo,
4851 rmhi,
4852 } => self.encode_thumb(&ArmOp::I64SetCond {
4853 rd: *rd,
4854 rn_lo: *rnlo,
4855 rn_hi: *rnhi,
4856 rm_lo: *rmlo,
4857 rm_hi: *rmhi,
4858 cond: synth_synthesis::Condition::LS,
4859 }),
4860
4861 ArmOp::I64GtS {
4862 rd,
4863 rnlo,
4864 rnhi,
4865 rmlo,
4866 rmhi,
4867 } => self.encode_thumb(&ArmOp::I64SetCond {
4868 rd: *rd,
4869 rn_lo: *rnlo,
4870 rn_hi: *rnhi,
4871 rm_lo: *rmlo,
4872 rm_hi: *rmhi,
4873 cond: synth_synthesis::Condition::GT,
4874 }),
4875
4876 ArmOp::I64GtU {
4877 rd,
4878 rnlo,
4879 rnhi,
4880 rmlo,
4881 rmhi,
4882 } => self.encode_thumb(&ArmOp::I64SetCond {
4883 rd: *rd,
4884 rn_lo: *rnlo,
4885 rn_hi: *rnhi,
4886 rm_lo: *rmlo,
4887 rm_hi: *rmhi,
4888 cond: synth_synthesis::Condition::HI,
4889 }),
4890
4891 ArmOp::I64GeS {
4892 rd,
4893 rnlo,
4894 rnhi,
4895 rmlo,
4896 rmhi,
4897 } => self.encode_thumb(&ArmOp::I64SetCond {
4898 rd: *rd,
4899 rn_lo: *rnlo,
4900 rn_hi: *rnhi,
4901 rm_lo: *rmlo,
4902 rm_hi: *rmhi,
4903 cond: synth_synthesis::Condition::GE,
4904 }),
4905
4906 ArmOp::I64GeU {
4907 rd,
4908 rnlo,
4909 rnhi,
4910 rmlo,
4911 rmhi,
4912 } => self.encode_thumb(&ArmOp::I64SetCond {
4913 rd: *rd,
4914 rn_lo: *rnlo,
4915 rn_hi: *rnhi,
4916 rm_lo: *rmlo,
4917 rm_hi: *rmhi,
4918 cond: synth_synthesis::Condition::HS,
4919 }),
4920
4921 ArmOp::I64Const { rdlo, rdhi, value } => {
4923 let lo32 = *value as u32;
4924 let hi32 = (*value >> 32) as u32;
4925 let mut bytes = Vec::new();
4926 bytes.extend_from_slice(
4928 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
4929 );
4930 if lo32 > 0xFFFF {
4931 bytes.extend_from_slice(
4932 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
4933 );
4934 }
4935 bytes.extend_from_slice(
4937 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
4938 );
4939 if hi32 > 0xFFFF {
4940 bytes.extend_from_slice(
4941 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
4942 );
4943 }
4944 Ok(bytes)
4945 }
4946
4947 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
4949 let mut bytes = Vec::new();
4950 let offset = if addr.offset < 0 {
4951 0u32
4952 } else {
4953 addr.offset as u32
4954 };
4955 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
4956 bytes.extend_from_slice(&self.encode_thumb32_ldr(
4957 rdhi,
4958 &addr.base,
4959 offset.wrapping_add(4),
4960 )?);
4961 Ok(bytes)
4962 }
4963
4964 ArmOp::I64Str { rdlo, rdhi, addr } => {
4966 let mut bytes = Vec::new();
4967 let offset = if addr.offset < 0 {
4968 0u32
4969 } else {
4970 addr.offset as u32
4971 };
4972 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
4973 bytes.extend_from_slice(&self.encode_thumb32_str(
4974 rdhi,
4975 &addr.base,
4976 offset.wrapping_add(4),
4977 )?);
4978 Ok(bytes)
4979 }
4980
4981 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
4983 let mut bytes = Vec::new();
4984 if rdlo != rn {
4985 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
4987 rd: *rdlo,
4988 op2: Operand2::Reg(*rn),
4989 })?);
4990 }
4991 bytes.extend_from_slice(
4993 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
4995 Ok(bytes)
4996 }
4997
4998 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5000 let mut bytes = Vec::new();
5001 if rdlo != rn {
5002 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5004 rd: *rdlo,
5005 op2: Operand2::Reg(*rn),
5006 })?);
5007 }
5008 let rdhi_bits = reg_to_bits(rdhi) as u16;
5010 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5011 bytes.extend_from_slice(&instr.to_le_bytes());
5012 Ok(bytes)
5013 }
5014
5015 ArmOp::I32WrapI64 { rd, rnlo } => {
5017 if rd == rnlo {
5018 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5021 } else {
5022 self.encode_thumb(&ArmOp::Mov {
5024 rd: *rd,
5025 op2: Operand2::Reg(*rnlo),
5026 })
5027 }
5028 }
5029
5030 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5032 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5033 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5034 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5035 0xEF000150, qd, qn, qm,
5036 ))),
5037 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5038 0xEF200150, qd, qn, qm,
5039 ))),
5040 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5041 0xFF000150, qd, qn, qm,
5042 ))),
5043 ArmOp::MveMvn { qd, qm } => {
5044 let qd_enc = qreg_to_num(qd);
5046 let qm_enc = qreg_to_num(qm);
5047 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5048 Ok(vfp_to_thumb_bytes(instr))
5049 }
5050 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5051 0xEF100150, qd, qn, qm,
5052 ))),
5053 ArmOp::MveAddI { qd, qn, qm, size } => {
5054 let sz = mve_size_bits(size);
5055 let base: u32 = 0xEF000840 | (sz << 20);
5056 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5057 }
5058 ArmOp::MveSubI { qd, qn, qm, size } => {
5059 let sz = mve_size_bits(size);
5060 let base: u32 = 0xFF000840 | (sz << 20);
5061 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5062 }
5063 ArmOp::MveMulI { qd, qn, qm, size } => {
5064 let sz = mve_size_bits(size);
5065 let base: u32 = 0xEF000950 | (sz << 20);
5066 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5067 }
5068 ArmOp::MveNegI { qd, qm, size } => {
5069 let sz = mve_size_bits(size);
5070 let qd_enc = qreg_to_num(qd);
5072 let qm_enc = qreg_to_num(qm);
5073 let base: u32 = 0xFFB103C0 | (sz << 18);
5074 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5075 Ok(vfp_to_thumb_bytes(instr))
5076 }
5077 ArmOp::MveDup { qd, rn, size } => {
5078 let sz = mve_size_bits(size);
5079 let qd_enc = qreg_to_num(qd);
5080 let rn_bits = reg_to_bits(rn);
5081 let be = match sz {
5084 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5088 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5089 Ok(vfp_to_thumb_bytes(instr))
5090 }
5091 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5092 let qn_enc = qreg_to_num(qn);
5093 let rd_bits = reg_to_bits(rd);
5094 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5097 let lane_in_d = (*lane as u32) & 1;
5098 let _sz = mve_size_bits(size);
5099 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5101 Ok(vfp_to_thumb_bytes(instr))
5102 }
5103 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5104 let qd_enc = qreg_to_num(qd);
5105 let rn_bits = reg_to_bits(rn);
5106 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5107 let lane_in_d = (*lane as u32) & 1;
5108 let _sz = mve_size_bits(size);
5109 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5111 Ok(vfp_to_thumb_bytes(instr))
5112 }
5113
5114 ArmOp::MveCmpEqI { qd, qn, qm, size }
5116 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5117 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5118 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5119 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5120 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5121 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5122 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5123 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5124 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5125 let sz = mve_size_bits(size);
5128 let base: u32 = 0xEF000840 | (sz << 20);
5129 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5130 }
5131
5132 ArmOp::MveAddF32 { qd, qn, qm } => {
5134 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5136 }
5137 ArmOp::MveSubF32 { qd, qn, qm } => {
5138 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5140 }
5141 ArmOp::MveMulF32 { qd, qn, qm } => {
5142 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5144 }
5145 ArmOp::MveNegF32 { qd, qm } => {
5146 let qd_enc = qreg_to_num(qd);
5147 let qm_enc = qreg_to_num(qm);
5148 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5150 Ok(vfp_to_thumb_bytes(instr))
5151 }
5152 ArmOp::MveAbsF32 { qd, qm } => {
5153 let qd_enc = qreg_to_num(qd);
5154 let qm_enc = qreg_to_num(qm);
5155 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5157 Ok(vfp_to_thumb_bytes(instr))
5158 }
5159 ArmOp::MveCmpEqF32 { qd, qn, qm }
5160 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5161 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5162 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5163 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5164 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5165 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5167 }
5168 ArmOp::MveDupF32 { qd, rn } => {
5169 let qd_enc = qreg_to_num(qd);
5170 let rn_bits = reg_to_bits(rn);
5171 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5173 Ok(vfp_to_thumb_bytes(instr))
5174 }
5175 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5176 let qn_enc = qreg_to_num(qn);
5177 let rd_bits = reg_to_bits(rd);
5178 let s_num = qn_enc * 4 + (*lane as u32);
5180 let (vn, n) = encode_sreg(s_num);
5181 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5182 Ok(vfp_to_thumb_bytes(instr))
5183 }
5184 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5185 let qd_enc = qreg_to_num(qd);
5186 let rn_bits = reg_to_bits(rn);
5187 let s_num = qd_enc * 4 + (*lane as u32);
5189 let (vn, n) = encode_sreg(s_num);
5190 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5191 Ok(vfp_to_thumb_bytes(instr))
5192 }
5193 ArmOp::MveDivF32 { qd, qn, qm } => {
5194 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5196 }
5197 ArmOp::MveSqrtF32 { qd, qm } => {
5198 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5200 }
5201
5202 _ => {
5204 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5206 }
5207 }
5208 }
5209
5210 fn encode_thumb_f32_compare(
5214 &self,
5215 rd: &Reg,
5216 sn: &VfpReg,
5217 sm: &VfpReg,
5218 cond_code: u32,
5219 ) -> Result<Vec<u8>> {
5220 let mut bytes = Vec::new();
5221 let rd_bits = reg_to_bits(rd);
5222
5223 let sn_num = vfp_sreg_to_num(sn)?;
5225 let sm_num = vfp_sreg_to_num(sm)?;
5226 let (vd, d) = encode_sreg(sn_num);
5227 let (vm, m) = encode_sreg(sm_num);
5228 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5229 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5230
5231 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5233
5234 if rd_bits < 8 {
5236 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5237 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5238 } else {
5239 let hw1: u16 = 0xF04F;
5241 let hw2: u16 = (rd_bits as u16) << 8;
5242 bytes.extend_from_slice(&hw1.to_le_bytes());
5243 bytes.extend_from_slice(&hw2.to_le_bytes());
5244 }
5245
5246 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5250 bytes.extend_from_slice(&it.to_le_bytes());
5251
5252 if rd_bits < 8 {
5254 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5255 bytes.extend_from_slice(&mov_one.to_le_bytes());
5256 } else {
5257 let hw1: u16 = 0xF04F;
5259 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5260 bytes.extend_from_slice(&hw1.to_le_bytes());
5261 bytes.extend_from_slice(&hw2.to_le_bytes());
5262 }
5263
5264 Ok(bytes)
5265 }
5266
5267 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5269 let mut bytes = Vec::new();
5270 let bits = value.to_bits();
5271 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5276 let imm4 = (lo16 >> 12) & 0xF;
5277 let i_bit = (lo16 >> 11) & 1;
5278 let imm3 = (lo16 >> 8) & 0x7;
5279 let imm8 = lo16 & 0xFF;
5280 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5281 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5282 bytes.extend_from_slice(&hw1.to_le_bytes());
5283 bytes.extend_from_slice(&hw2.to_le_bytes());
5284
5285 let hi16 = (bits >> 16) & 0xFFFF;
5287 let imm4 = (hi16 >> 12) & 0xF;
5288 let i_bit = (hi16 >> 11) & 1;
5289 let imm3 = (hi16 >> 8) & 0x7;
5290 let imm8 = hi16 & 0xFF;
5291 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5292 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5293 bytes.extend_from_slice(&hw1.to_le_bytes());
5294 bytes.extend_from_slice(&hw2.to_le_bytes());
5295
5296 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5298 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5299
5300 Ok(bytes)
5301 }
5302
5303 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5305 let mut bytes = Vec::new();
5306
5307 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5309 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5310
5311 let sd_num = vfp_sreg_to_num(sd)?;
5313 let (vd, d) = encode_sreg(sd_num);
5314 let (vm, m) = encode_sreg(sd_num);
5315 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5316 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5317 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5318
5319 Ok(bytes)
5320 }
5321
5322 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5330 let mut bytes = Vec::new();
5331 let sm_num = vfp_sreg_to_num(sm)?;
5332 let sd_num = vfp_sreg_to_num(sd)?;
5333 let (vd_s, d_s) = encode_sreg(sd_num);
5334 let (vm_s, m_s) = encode_sreg(sm_num);
5335
5336 if mode == 0b11 {
5337 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5339 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5340 } else {
5341 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5346 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5347
5348 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5354 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5355 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5356
5357 if mode != 0 {
5359 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5361 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5362 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5363 }
5364
5365 let vmsr = 0xEEE10A10 | (rt << 12);
5367 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5368
5369 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5371 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5372
5373 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5375 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5376 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5377 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5378 }
5379
5380 let (vd2, d2) = encode_sreg(sd_num);
5382 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5383 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5384
5385 Ok(bytes)
5386 }
5387
5388 fn encode_thumb_f32_minmax(
5390 &self,
5391 sd: &VfpReg,
5392 sn: &VfpReg,
5393 sm: &VfpReg,
5394 is_min: bool,
5395 ) -> Result<Vec<u8>> {
5396 let mut bytes = Vec::new();
5397 let sn_num = vfp_sreg_to_num(sn)?;
5398 let sm_num = vfp_sreg_to_num(sm)?;
5399 let sd_num = vfp_sreg_to_num(sd)?;
5400
5401 let (vd, d) = encode_sreg(sd_num);
5403 let (vn, n) = encode_sreg(sn_num);
5404 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5405 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5406
5407 let (vm, m) = encode_sreg(sm_num);
5409 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5410 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5411
5412 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5414
5415 let cond: u16 = if is_min { 0xC } else { 0x4 };
5417 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5418 bytes.extend_from_slice(&it.to_le_bytes());
5419
5420 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5422 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5423
5424 Ok(bytes)
5425 }
5426
5427 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5429 let mut bytes = Vec::new();
5430
5431 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5433 false,
5434 sm,
5435 &Reg::R12,
5436 )?));
5437
5438 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5440 false,
5441 sn,
5442 &Reg::R0,
5443 )?));
5444
5445 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5457 bytes.extend_from_slice(&hw2.to_le_bytes());
5458
5459 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5463 bytes.extend_from_slice(&hw2.to_le_bytes());
5464
5465 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5469 bytes.extend_from_slice(&hw2.to_le_bytes());
5470
5471 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5473 true,
5474 sd,
5475 &Reg::R0,
5476 )?));
5477
5478 Ok(bytes)
5479 }
5480
5481 fn encode_thumb_f64_compare(
5483 &self,
5484 rd: &Reg,
5485 dn: &VfpReg,
5486 dm: &VfpReg,
5487 cond_code: u32,
5488 ) -> Result<Vec<u8>> {
5489 let mut bytes = Vec::new();
5490 let rd_bits = reg_to_bits(rd);
5491
5492 let dn_num = vfp_dreg_to_num(dn)?;
5494 let dm_num = vfp_dreg_to_num(dm)?;
5495 let (vd, d) = encode_dreg(dn_num);
5496 let (vm, m) = encode_dreg(dm_num);
5497 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5498 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5499
5500 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5502
5503 if rd_bits < 8 {
5505 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5506 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5507 } else {
5508 let hw1: u16 = 0xF04F;
5509 let hw2: u16 = (rd_bits as u16) << 8;
5510 bytes.extend_from_slice(&hw1.to_le_bytes());
5511 bytes.extend_from_slice(&hw2.to_le_bytes());
5512 }
5513
5514 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5516 bytes.extend_from_slice(&it.to_le_bytes());
5517
5518 if rd_bits < 8 {
5520 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5521 bytes.extend_from_slice(&mov_one.to_le_bytes());
5522 } else {
5523 let hw1: u16 = 0xF04F;
5524 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5525 bytes.extend_from_slice(&hw1.to_le_bytes());
5526 bytes.extend_from_slice(&hw2.to_le_bytes());
5527 }
5528
5529 Ok(bytes)
5530 }
5531
5532 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5534 let mut bytes = Vec::new();
5535 let bits = value.to_bits();
5536 let lo32 = bits as u32;
5537 let hi32 = (bits >> 32) as u32;
5538
5539 let lo16 = lo32 & 0xFFFF;
5541 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5542
5543 let hi16 = (lo32 >> 16) & 0xFFFF;
5545 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5546
5547 let lo16 = hi32 & 0xFFFF;
5549 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5550
5551 let hi16 = (hi32 >> 16) & 0xFFFF;
5553 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5554
5555 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5557 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5558
5559 Ok(bytes)
5560 }
5561
5562 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5564 let mut bytes = Vec::new();
5565
5566 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5568 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5569
5570 let dd_num = vfp_dreg_to_num(dd)?;
5572 let (vd, d) = encode_dreg(dd_num);
5573 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5574 let vcvt = base | (d << 22) | (vd << 12);
5575 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5576
5577 Ok(bytes)
5578 }
5579
5580 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5582 let dd_num = vfp_dreg_to_num(dd)?;
5583 let sm_num = vfp_sreg_to_num(sm)?;
5584 let (vd, d) = encode_dreg(dd_num);
5585 let (vm, m) = encode_sreg(sm_num);
5586
5587 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5588 Ok(vfp_to_thumb_bytes(vcvt))
5589 }
5590
5591 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5593 let mut bytes = Vec::new();
5594 let dm_num = vfp_dreg_to_num(dm)?;
5595 let (vm, m) = encode_dreg(dm_num);
5596
5597 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5599 let vcvt = base | (m << 5) | vm;
5600 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5601
5602 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5604 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5605
5606 Ok(bytes)
5607 }
5608
5609 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5613 let mut bytes = Vec::new();
5614 let dm_num = vfp_dreg_to_num(dm)?;
5615 let dd_num = vfp_dreg_to_num(dd)?;
5616 let (vm, m) = encode_dreg(dm_num);
5617 let (vd, d) = encode_dreg(dd_num);
5618
5619 if mode == 0b11 {
5620 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5622 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5623 } else {
5624 let rt: u32 = 12;
5625
5626 let vmrs = 0xEEF10A10 | (rt << 12);
5628 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5629
5630 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5632 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5633 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5634 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5635
5636 if mode != 0 {
5638 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5639 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5640 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5641 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5642 }
5643
5644 let vmsr = 0xEEE10A10 | (rt << 12);
5646 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5647
5648 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5650 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5651
5652 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5654 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5655 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5656 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5657 }
5658
5659 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5661 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5662
5663 Ok(bytes)
5664 }
5665
5666 fn encode_thumb_f64_minmax(
5668 &self,
5669 dd: &VfpReg,
5670 dn: &VfpReg,
5671 dm: &VfpReg,
5672 is_min: bool,
5673 ) -> Result<Vec<u8>> {
5674 let mut bytes = Vec::new();
5675 let dn_num = vfp_dreg_to_num(dn)?;
5676 let dm_num = vfp_dreg_to_num(dm)?;
5677 let dd_num = vfp_dreg_to_num(dd)?;
5678
5679 let (vd, d) = encode_dreg(dd_num);
5681 let (vn, n) = encode_dreg(dn_num);
5682 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5683 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5684
5685 let (vm, m) = encode_dreg(dm_num);
5687 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5688 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5689
5690 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5692
5693 let cond: u16 = if is_min { 0xC } else { 0x4 };
5695 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5696 bytes.extend_from_slice(&it.to_le_bytes());
5697
5698 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5700 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5701
5702 Ok(bytes)
5703 }
5704
5705 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5707 let mut bytes = Vec::new();
5708
5709 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5711 false,
5712 dm,
5713 &Reg::R0,
5714 &Reg::R12,
5715 )?));
5716
5717 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5719 false,
5720 dn,
5721 &Reg::R1,
5722 &Reg::R2,
5723 )?));
5724
5725 let hw1: u16 = 0xF000 | 12;
5727 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5728 bytes.extend_from_slice(&hw1.to_le_bytes());
5729 bytes.extend_from_slice(&hw2.to_le_bytes());
5730
5731 let hw1: u16 = 0xF020 | 2;
5733 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5734 bytes.extend_from_slice(&hw1.to_le_bytes());
5735 bytes.extend_from_slice(&hw2.to_le_bytes());
5736
5737 let hw1: u16 = 0xEA40 | 2;
5739 let hw2: u16 = (2 << 8) | 12;
5740 bytes.extend_from_slice(&hw1.to_le_bytes());
5741 bytes.extend_from_slice(&hw2.to_le_bytes());
5742
5743 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5745 true,
5746 dd,
5747 &Reg::R1,
5748 &Reg::R2,
5749 )?));
5750
5751 Ok(bytes)
5752 }
5753
5754 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5756 let mut bytes = Vec::new();
5757
5758 let sm_num = vfp_sreg_to_num(sm)?;
5759 let (vd, d) = encode_sreg(sm_num);
5760 let (vm, m) = encode_sreg(sm_num);
5761 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5762 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5763 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5764
5765 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5767 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5768
5769 Ok(bytes)
5770 }
5771
5772 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5776 let rd_bits = reg_to_bits(rd);
5777 let rn_bits = reg_to_bits(rn);
5778
5779 let i_bit = (imm >> 11) & 1;
5783 let imm3 = (imm >> 8) & 0x7;
5784 let imm8 = imm & 0xFF;
5785
5786 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5787 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5788
5789 let mut bytes = hw1.to_le_bytes().to_vec();
5790 bytes.extend_from_slice(&hw2.to_le_bytes());
5791 Ok(bytes)
5792 }
5793
5794 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5796 let rd_bits = reg_to_bits(rd);
5797 let rn_bits = reg_to_bits(rn);
5798
5799 let i_bit = (imm >> 11) & 1;
5800 let imm3 = (imm >> 8) & 0x7;
5801 let imm8 = imm & 0xFF;
5802
5803 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5804 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5805
5806 let mut bytes = hw1.to_le_bytes().to_vec();
5807 bytes.extend_from_slice(&hw2.to_le_bytes());
5808 Ok(bytes)
5809 }
5810
5811 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5813 let rd_bits = reg_to_bits(rd);
5814 let rn_bits = reg_to_bits(rn);
5815
5816 let i_bit = (imm >> 11) & 1;
5817 let imm3 = (imm >> 8) & 0x7;
5818 let imm8 = imm & 0xFF;
5819
5820 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5823 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5824
5825 let mut bytes = hw1.to_le_bytes().to_vec();
5826 bytes.extend_from_slice(&hw2.to_le_bytes());
5827 Ok(bytes)
5828 }
5829
5830 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5832 let rd_bits = reg_to_bits(rd);
5833 let rn_bits = reg_to_bits(rn);
5834
5835 let i_bit = (imm >> 11) & 1;
5836 let imm3 = (imm >> 8) & 0x7;
5837 let imm8 = imm & 0xFF;
5838
5839 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5842 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5843
5844 let mut bytes = hw1.to_le_bytes().to_vec();
5845 bytes.extend_from_slice(&hw2.to_le_bytes());
5846 Ok(bytes)
5847 }
5848
5849 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
5858 let rd_bits = reg_to_bits(rd);
5859 encoding_contracts::verify_reg_bits(rd_bits);
5860 let imm16 = imm & 0xFFFF;
5861
5862 let imm4 = (imm16 >> 12) & 0xF;
5865 let i_bit = (imm16 >> 11) & 1;
5866 let imm3 = (imm16 >> 8) & 0x7;
5867 let imm8 = imm16 & 0xFF;
5868
5869 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5870 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5871
5872 let mut bytes = hw1.to_le_bytes().to_vec();
5873 bytes.extend_from_slice(&hw2.to_le_bytes());
5874 encoding_contracts::verify_thumb32(&bytes);
5875 Ok(bytes)
5876 }
5877
5878 fn encode_thumb32_shift(
5886 &self,
5887 rd: &Reg,
5888 rm: &Reg,
5889 shift: u32,
5890 shift_type: u8,
5891 ) -> Result<Vec<u8>> {
5892 let rd_bits = reg_to_bits(rd);
5893 let rm_bits = reg_to_bits(rm);
5894 encoding_contracts::verify_reg_bits(rd_bits);
5895 encoding_contracts::verify_reg_bits(rm_bits);
5896 let imm5 = shift & 0x1F;
5897 let imm2 = imm5 & 0x3;
5898 let imm3 = (imm5 >> 2) & 0x7;
5899
5900 let hw1: u16 = 0xEA4F;
5903 let hw2: u16 =
5904 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
5905 as u16;
5906
5907 let mut bytes = hw1.to_le_bytes().to_vec();
5908 bytes.extend_from_slice(&hw2.to_le_bytes());
5909 Ok(bytes)
5910 }
5911
5912 fn encode_thumb32_shift_reg(
5916 &self,
5917 rd: &Reg,
5918 rn: &Reg,
5919 rm: &Reg,
5920 shift_type: u8,
5921 ) -> Result<Vec<u8>> {
5922 let rd_bits = reg_to_bits(rd);
5923 let rn_bits = reg_to_bits(rn);
5924 let rm_bits = reg_to_bits(rm);
5925
5926 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
5928 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
5930
5931 let mut bytes = hw1.to_le_bytes().to_vec();
5932 bytes.extend_from_slice(&hw2.to_le_bytes());
5933 Ok(bytes)
5934 }
5935
5936 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5938 let rn_bits = reg_to_bits(rn);
5939
5940 let i_bit = (imm >> 11) & 1;
5941 let imm3 = (imm >> 8) & 0x7;
5942 let imm8 = imm & 0xFF;
5943
5944 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5946 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
5947
5948 let mut bytes = hw1.to_le_bytes().to_vec();
5949 bytes.extend_from_slice(&hw2.to_le_bytes());
5950 Ok(bytes)
5951 }
5952
5953 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
5955 let rd_bits = reg_to_bits(rd);
5956 let base_bits = reg_to_bits(base);
5957
5958 let hw1: u16 = (0xF8D0 | base_bits) as u16;
5960 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
5961
5962 let mut bytes = hw1.to_le_bytes().to_vec();
5963 bytes.extend_from_slice(&hw2.to_le_bytes());
5964 Ok(bytes)
5965 }
5966
5967 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
5969 let rd_bits = reg_to_bits(rd);
5970 let base_bits = reg_to_bits(base);
5971
5972 let hw1: u16 = (0xF8C0 | base_bits) as u16;
5974 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
5975
5976 let mut bytes = hw1.to_le_bytes().to_vec();
5977 bytes.extend_from_slice(&hw2.to_le_bytes());
5978 Ok(bytes)
5979 }
5980
5981 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
5983 let rd_bits = reg_to_bits(rd);
5984 let base_bits = reg_to_bits(base);
5985 let rm_bits = reg_to_bits(offset_reg);
5986
5987 let hw1: u16 = (0xF850 | base_bits) as u16;
5991 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
5992
5993 let mut bytes = hw1.to_le_bytes().to_vec();
5994 bytes.extend_from_slice(&hw2.to_le_bytes());
5995 Ok(bytes)
5996 }
5997
5998 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6000 let rd_bits = reg_to_bits(rd);
6001 let base_bits = reg_to_bits(base);
6002 let rm_bits = reg_to_bits(offset_reg);
6003
6004 let hw1: u16 = (0xF840 | base_bits) as u16;
6008 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6009
6010 let mut bytes = hw1.to_le_bytes().to_vec();
6011 bytes.extend_from_slice(&hw2.to_le_bytes());
6012 Ok(bytes)
6013 }
6014
6015 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6019 let rd_bits = reg_to_bits(rd);
6020 let base_bits = reg_to_bits(base);
6021 let hw1: u16 = (0xF890 | base_bits) as u16;
6023 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6024 let mut bytes = hw1.to_le_bytes().to_vec();
6025 bytes.extend_from_slice(&hw2.to_le_bytes());
6026 Ok(bytes)
6027 }
6028
6029 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6031 let rd_bits = reg_to_bits(rd);
6032 let base_bits = reg_to_bits(base);
6033 let rm_bits = reg_to_bits(offset_reg);
6034 let hw1: u16 = (0xF810 | base_bits) as u16;
6036 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6037 let mut bytes = hw1.to_le_bytes().to_vec();
6038 bytes.extend_from_slice(&hw2.to_le_bytes());
6039 Ok(bytes)
6040 }
6041
6042 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6044 let rd_bits = reg_to_bits(rd);
6045 let base_bits = reg_to_bits(base);
6046 let hw1: u16 = (0xF990 | base_bits) as u16;
6048 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6049 let mut bytes = hw1.to_le_bytes().to_vec();
6050 bytes.extend_from_slice(&hw2.to_le_bytes());
6051 Ok(bytes)
6052 }
6053
6054 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6056 let rd_bits = reg_to_bits(rd);
6057 let base_bits = reg_to_bits(base);
6058 let rm_bits = reg_to_bits(offset_reg);
6059 let hw1: u16 = (0xF910 | base_bits) as u16;
6061 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6062 let mut bytes = hw1.to_le_bytes().to_vec();
6063 bytes.extend_from_slice(&hw2.to_le_bytes());
6064 Ok(bytes)
6065 }
6066
6067 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6069 let rd_bits = reg_to_bits(rd);
6070 let base_bits = reg_to_bits(base);
6071 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6073 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6074 let mut bytes = hw1.to_le_bytes().to_vec();
6075 bytes.extend_from_slice(&hw2.to_le_bytes());
6076 Ok(bytes)
6077 }
6078
6079 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6081 let rd_bits = reg_to_bits(rd);
6082 let base_bits = reg_to_bits(base);
6083 let rm_bits = reg_to_bits(offset_reg);
6084 let hw1: u16 = (0xF830 | base_bits) as u16;
6086 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6087 let mut bytes = hw1.to_le_bytes().to_vec();
6088 bytes.extend_from_slice(&hw2.to_le_bytes());
6089 Ok(bytes)
6090 }
6091
6092 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6094 let rd_bits = reg_to_bits(rd);
6095 let base_bits = reg_to_bits(base);
6096 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6098 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6099 let mut bytes = hw1.to_le_bytes().to_vec();
6100 bytes.extend_from_slice(&hw2.to_le_bytes());
6101 Ok(bytes)
6102 }
6103
6104 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6106 let rd_bits = reg_to_bits(rd);
6107 let base_bits = reg_to_bits(base);
6108 let rm_bits = reg_to_bits(offset_reg);
6109 let hw1: u16 = (0xF930 | base_bits) as u16;
6111 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6112 let mut bytes = hw1.to_le_bytes().to_vec();
6113 bytes.extend_from_slice(&hw2.to_le_bytes());
6114 Ok(bytes)
6115 }
6116
6117 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6119 let rd_bits = reg_to_bits(rd);
6120 let base_bits = reg_to_bits(base);
6121 let hw1: u16 = (0xF880 | base_bits) as u16;
6123 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6124 let mut bytes = hw1.to_le_bytes().to_vec();
6125 bytes.extend_from_slice(&hw2.to_le_bytes());
6126 Ok(bytes)
6127 }
6128
6129 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6131 let rd_bits = reg_to_bits(rd);
6132 let base_bits = reg_to_bits(base);
6133 let rm_bits = reg_to_bits(offset_reg);
6134 let hw1: u16 = (0xF800 | base_bits) as u16;
6136 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6137 let mut bytes = hw1.to_le_bytes().to_vec();
6138 bytes.extend_from_slice(&hw2.to_le_bytes());
6139 Ok(bytes)
6140 }
6141
6142 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6144 let rd_bits = reg_to_bits(rd);
6145 let base_bits = reg_to_bits(base);
6146 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6148 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6149 let mut bytes = hw1.to_le_bytes().to_vec();
6150 bytes.extend_from_slice(&hw2.to_le_bytes());
6151 Ok(bytes)
6152 }
6153
6154 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6156 let rd_bits = reg_to_bits(rd);
6157 let base_bits = reg_to_bits(base);
6158 let rm_bits = reg_to_bits(offset_reg);
6159 let hw1: u16 = (0xF820 | base_bits) as u16;
6161 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6162 let mut bytes = hw1.to_le_bytes().to_vec();
6163 bytes.extend_from_slice(&hw2.to_le_bytes());
6164 Ok(bytes)
6165 }
6166
6167 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6169 let rd_bits = reg_to_bits(rd);
6170 let rn_bits = reg_to_bits(rn);
6171
6172 if imm <= 0xFFF {
6178 let i_bit = (imm >> 11) & 1;
6179 let imm3 = (imm >> 8) & 0x7;
6180 let imm8 = imm & 0xFF;
6181
6182 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6183 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6184
6185 let mut bytes = hw1.to_le_bytes().to_vec();
6186 bytes.extend_from_slice(&hw2.to_le_bytes());
6187 Ok(bytes)
6188 } else {
6189 Err(synth_core::Error::synthesis(
6192 "ADD immediate too large for single instruction",
6193 ))
6194 }
6195 }
6196
6197 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6207 encoding_contracts::verify_reg_bits(rd);
6208 encoding_contracts::verify_imm16(imm16);
6209 let imm16 = imm16 & 0xFFFF;
6212 let imm4 = (imm16 >> 12) & 0xF;
6213 let i_bit = (imm16 >> 11) & 1;
6214 let imm3 = (imm16 >> 8) & 0x7;
6215 let imm8 = imm16 & 0xFF;
6216
6217 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6218 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6219
6220 let mut bytes = hw1.to_le_bytes().to_vec();
6221 bytes.extend_from_slice(&hw2.to_le_bytes());
6222 encoding_contracts::verify_thumb32(&bytes);
6223 Ok(bytes)
6224 }
6225
6226 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6234 encoding_contracts::verify_reg_bits(rd);
6235 encoding_contracts::verify_imm16(imm16);
6236 let imm16 = imm16 & 0xFFFF;
6239 let imm4 = (imm16 >> 12) & 0xF;
6240 let i_bit = (imm16 >> 11) & 1;
6241 let imm3 = (imm16 >> 8) & 0x7;
6242 let imm8 = imm16 & 0xFF;
6243
6244 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6245 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6246
6247 let mut bytes = hw1.to_le_bytes().to_vec();
6248 bytes.extend_from_slice(&hw2.to_le_bytes());
6249 encoding_contracts::verify_thumb32(&bytes);
6250 Ok(bytes)
6251 }
6252
6253 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6255 let imm5 = shift & 0x1F;
6258 let imm2 = imm5 & 0x3;
6259 let imm3 = (imm5 >> 2) & 0x7;
6260
6261 let hw1: u16 = 0xEA4F;
6262 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6263
6264 let mut bytes = hw1.to_le_bytes().to_vec();
6265 bytes.extend_from_slice(&hw2.to_le_bytes());
6266 Ok(bytes)
6267 }
6268
6269 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6271 let hw1: u16 = (0xEA00 | rn) as u16;
6274 let hw2: u16 = ((rd << 8) | rm) as u16;
6275
6276 let mut bytes = hw1.to_le_bytes().to_vec();
6277 bytes.extend_from_slice(&hw2.to_le_bytes());
6278 Ok(bytes)
6279 }
6280
6281 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6283 let i_bit = (imm >> 11) & 1;
6287 let imm3 = (imm >> 8) & 0x7;
6288 let imm8 = imm & 0xFF;
6289
6290 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6291 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6292
6293 let mut bytes = hw1.to_le_bytes().to_vec();
6294 bytes.extend_from_slice(&hw2.to_le_bytes());
6295 Ok(bytes)
6296 }
6297
6298 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6300 let hw1: u16 = (0xEBA0 | rn) as u16;
6303 let hw2: u16 = ((rd << 8) | rm) as u16;
6304
6305 let mut bytes = hw1.to_le_bytes().to_vec();
6306 bytes.extend_from_slice(&hw2.to_le_bytes());
6307 Ok(bytes)
6308 }
6309
6310 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6312 let hw1: u16 = (0xEB00 | rn) as u16;
6315 let hw2: u16 = ((rd << 8) | rm) as u16;
6316
6317 let mut bytes = hw1.to_le_bytes().to_vec();
6318 bytes.extend_from_slice(&hw2.to_le_bytes());
6319 Ok(bytes)
6320 }
6321
6322 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6324 let mut code = Vec::new();
6325
6326 for op in ops {
6327 let encoded = self.encode(op)?;
6328 code.extend_from_slice(&encoded);
6329 }
6330
6331 Ok(code)
6332 }
6333}
6334
6335fn reg_to_bits(reg: &Reg) -> u32 {
6337 match reg {
6338 Reg::R0 => 0,
6339 Reg::R1 => 1,
6340 Reg::R2 => 2,
6341 Reg::R3 => 3,
6342 Reg::R4 => 4,
6343 Reg::R5 => 5,
6344 Reg::R6 => 6,
6345 Reg::R7 => 7,
6346 Reg::R8 => 8,
6347 Reg::R9 => 9,
6348 Reg::R10 => 10,
6349 Reg::R11 => 11,
6350 Reg::R12 => 12,
6351 Reg::SP => 13,
6352 Reg::LR => 14,
6353 Reg::PC => 15,
6354 }
6355}
6356
6357fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6360 if val == 0 {
6361 return Some((0, 1));
6362 }
6363 for rot in 0..16u32 {
6364 let shift = rot * 2;
6365 let unrotated = val.rotate_left(shift);
6367 if unrotated <= 0xFF {
6368 return Some(((rot << 8) | unrotated, 1));
6370 }
6371 }
6372 None
6373}
6374
6375fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6380 match op2 {
6381 Operand2::Imm(val) => {
6382 let uval = *val as u32;
6383 if let Some(encoded) = try_encode_rotated_imm(uval) {
6385 encoded
6386 } else {
6387 let imm = uval & 0xFF;
6392 (imm, 1)
6393 }
6394 }
6395
6396 Operand2::Reg(reg) => {
6397 let reg_bits = reg_to_bits(reg);
6398 (reg_bits, 0) }
6400
6401 Operand2::RegShift {
6402 rm,
6403 shift: _,
6404 amount,
6405 } => {
6406 let rm_bits = reg_to_bits(rm);
6408 let shift_bits = (*amount & 0x1F) << 7;
6409 (shift_bits | rm_bits, 0)
6410 }
6411 }
6412}
6413
6414fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6416 let base_bits = reg_to_bits(&addr.base);
6417 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6419}
6420
6421fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6423 match reg {
6424 VfpReg::S0 => Ok(0),
6425 VfpReg::S1 => Ok(1),
6426 VfpReg::S2 => Ok(2),
6427 VfpReg::S3 => Ok(3),
6428 VfpReg::S4 => Ok(4),
6429 VfpReg::S5 => Ok(5),
6430 VfpReg::S6 => Ok(6),
6431 VfpReg::S7 => Ok(7),
6432 VfpReg::S8 => Ok(8),
6433 VfpReg::S9 => Ok(9),
6434 VfpReg::S10 => Ok(10),
6435 VfpReg::S11 => Ok(11),
6436 VfpReg::S12 => Ok(12),
6437 VfpReg::S13 => Ok(13),
6438 VfpReg::S14 => Ok(14),
6439 VfpReg::S15 => Ok(15),
6440 VfpReg::S16 => Ok(16),
6441 VfpReg::S17 => Ok(17),
6442 VfpReg::S18 => Ok(18),
6443 VfpReg::S19 => Ok(19),
6444 VfpReg::S20 => Ok(20),
6445 VfpReg::S21 => Ok(21),
6446 VfpReg::S22 => Ok(22),
6447 VfpReg::S23 => Ok(23),
6448 VfpReg::S24 => Ok(24),
6449 VfpReg::S25 => Ok(25),
6450 VfpReg::S26 => Ok(26),
6451 VfpReg::S27 => Ok(27),
6452 VfpReg::S28 => Ok(28),
6453 VfpReg::S29 => Ok(29),
6454 VfpReg::S30 => Ok(30),
6455 VfpReg::S31 => Ok(31),
6456 _ => Err(synth_core::Error::SynthesisError(
6458 "D-register not supported in single-precision VFP encoding".to_string(),
6459 )),
6460 }
6461}
6462
6463fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6465 match reg {
6466 VfpReg::D0 => Ok(0),
6467 VfpReg::D1 => Ok(1),
6468 VfpReg::D2 => Ok(2),
6469 VfpReg::D3 => Ok(3),
6470 VfpReg::D4 => Ok(4),
6471 VfpReg::D5 => Ok(5),
6472 VfpReg::D6 => Ok(6),
6473 VfpReg::D7 => Ok(7),
6474 VfpReg::D8 => Ok(8),
6475 VfpReg::D9 => Ok(9),
6476 VfpReg::D10 => Ok(10),
6477 VfpReg::D11 => Ok(11),
6478 VfpReg::D12 => Ok(12),
6479 VfpReg::D13 => Ok(13),
6480 VfpReg::D14 => Ok(14),
6481 VfpReg::D15 => Ok(15),
6482 _ => Err(synth_core::Error::SynthesisError(
6484 "S-register not supported in double-precision VFP encoding".to_string(),
6485 )),
6486 }
6487}
6488
6489fn encode_sreg(s: u32) -> (u32, u32) {
6493 (s >> 1, s & 1)
6494}
6495
6496fn encode_dreg(d: u32) -> (u32, u32) {
6500 (d & 0xF, (d >> 4) & 1)
6501}
6502
6503fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6509 let sd_num = vfp_sreg_to_num(sd)?;
6510 let sn_num = vfp_sreg_to_num(sn)?;
6511 let sm_num = vfp_sreg_to_num(sm)?;
6512 let (vd, d) = encode_sreg(sd_num);
6513 let (vn, n) = encode_sreg(sn_num);
6514 let (vm, m) = encode_sreg(sm_num);
6515
6516 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6517}
6518
6519fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6522 let sd_num = vfp_sreg_to_num(sd)?;
6523 let sm_num = vfp_sreg_to_num(sm)?;
6524 let (vd, d) = encode_sreg(sd_num);
6525 let (vm, m) = encode_sreg(sm_num);
6526
6527 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6528}
6529
6530fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6534 let sd_num = vfp_sreg_to_num(sd)?;
6535 let (vd, d) = encode_sreg(sd_num);
6536 let rn = reg_to_bits(&addr.base);
6537
6538 let offset = addr.offset;
6539 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6540 let abs_offset = offset.unsigned_abs();
6541 let imm8 = (abs_offset / 4) & 0xFF;
6542
6543 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6544}
6545
6546fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6550 let s_num = vfp_sreg_to_num(sreg)?;
6551 let (vn, n) = encode_sreg(s_num);
6552 let rt = reg_to_bits(core);
6553
6554 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6555 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6556}
6557
6558fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6562 let dd_num = vfp_dreg_to_num(dd)?;
6563 let dn_num = vfp_dreg_to_num(dn)?;
6564 let dm_num = vfp_dreg_to_num(dm)?;
6565 let (vd, d) = encode_dreg(dd_num);
6566 let (vn, n) = encode_dreg(dn_num);
6567 let (vm, m) = encode_dreg(dm_num);
6568
6569 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6570}
6571
6572fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6574 let dd_num = vfp_dreg_to_num(dd)?;
6575 let dm_num = vfp_dreg_to_num(dm)?;
6576 let (vd, d) = encode_dreg(dd_num);
6577 let (vm, m) = encode_dreg(dm_num);
6578
6579 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6580}
6581
6582fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6585 let dd_num = vfp_dreg_to_num(dd)?;
6586 let (vd, d) = encode_dreg(dd_num);
6587 let rn = reg_to_bits(&addr.base);
6588
6589 let offset = addr.offset;
6590 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6591 let abs_offset = offset.unsigned_abs();
6592 let imm8 = (abs_offset / 4) & 0xFF;
6593
6594 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6595}
6596
6597fn encode_vmov_core_dreg(
6601 to_dreg: bool,
6602 dreg: &VfpReg,
6603 core_lo: &Reg,
6604 core_hi: &Reg,
6605) -> Result<u32> {
6606 let d_num = vfp_dreg_to_num(dreg)?;
6607 let (vm, m) = encode_dreg(d_num);
6608 let rt = reg_to_bits(core_lo);
6609 let rt2 = reg_to_bits(core_hi);
6610
6611 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6612 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6613}
6614
6615fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6617 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6618 let hw2 = (instr & 0xFFFF) as u16;
6619 let mut bytes = hw1.to_le_bytes().to_vec();
6620 bytes.extend_from_slice(&hw2.to_le_bytes());
6621 bytes
6622}
6623
6624fn qreg_to_num(reg: &QReg) -> u32 {
6630 match reg {
6631 QReg::Q0 => 0,
6632 QReg::Q1 => 1,
6633 QReg::Q2 => 2,
6634 QReg::Q3 => 3,
6635 QReg::Q4 => 4,
6636 QReg::Q5 => 5,
6637 QReg::Q6 => 6,
6638 QReg::Q7 => 7,
6639 }
6640}
6641
6642fn mve_size_bits(size: &MveSize) -> u32 {
6644 match size {
6645 MveSize::S8 => 0b00,
6646 MveSize::S16 => 0b01,
6647 MveSize::S32 => 0b10,
6648 }
6649}
6650
6651fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6655 let d = qreg_to_num(qd) * 2;
6656 let n = qreg_to_num(qn) * 2;
6657 let m = qreg_to_num(qm) * 2;
6658
6659 let vd = d & 0xF;
6664 let d_bit = (d >> 4) & 1;
6665 let vn = n & 0xF;
6666 let n_bit = (n >> 4) & 1;
6667 let vm = m & 0xF;
6668 let m_bit = (m >> 4) & 1;
6669
6670 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6671}
6672
6673fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6675 encode_mve_3reg(base, qd, qn, qm)
6676}
6677
6678fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6681 let qd_enc = qreg_to_num(qd) * 2;
6682 let rn = reg_to_bits(&addr.base);
6683 let offset = addr.offset;
6684 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6685 let abs_offset = offset.unsigned_abs();
6686 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6690 | (u_bit << 23)
6691 | ((qd_enc >> 4) << 22)
6692 | (rn << 16)
6693 | ((qd_enc & 0xF) << 12)
6694 | (imm7 & 0x7F)
6695}
6696
6697fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6699 let qd_enc = qreg_to_num(qd) * 2;
6700 let rn = reg_to_bits(&addr.base);
6701 let offset = addr.offset;
6702 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6703 let abs_offset = offset.unsigned_abs();
6704 let imm7 = (abs_offset / 4) & 0x7F;
6705
6706 0xED000E80
6707 | (u_bit << 23)
6708 | ((qd_enc >> 4) << 22)
6709 | (rn << 16)
6710 | ((qd_enc & 0xF) << 12)
6711 | (imm7 & 0x7F)
6712}
6713
6714impl ArmEncoder {
6715 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6717 let mut result = Vec::new();
6718 let qd_num = qreg_to_num(qd);
6719
6720 for i in 0..4 {
6722 let word = u32::from_le_bytes([
6723 bytes[i * 4],
6724 bytes[i * 4 + 1],
6725 bytes[i * 4 + 2],
6726 bytes[i * 4 + 3],
6727 ]);
6728 let lo16 = word & 0xFFFF;
6729 let hi16 = (word >> 16) & 0xFFFF;
6730
6731 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6733 if hi16 != 0 {
6735 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6736 }
6737
6738 let s_num = qd_num * 4 + i as u32;
6740 let (vn, n) = encode_sreg(s_num);
6741 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6742 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6743 }
6744
6745 Ok(result)
6746 }
6747
6748 fn encode_thumb_mve_lane_wise_f32_binop(
6750 &self,
6751 qd: &QReg,
6752 qn: &QReg,
6753 qm: &QReg,
6754 vfp_base: u32,
6755 ) -> Result<Vec<u8>> {
6756 let mut result = Vec::new();
6757 let qd_num = qreg_to_num(qd);
6758 let qn_num = qreg_to_num(qn);
6759 let qm_num = qreg_to_num(qm);
6760
6761 for i in 0..4u32 {
6763 let sd = qd_num * 4 + i;
6764 let sn = qn_num * 4 + i;
6765 let sm = qm_num * 4 + i;
6766
6767 let (vd, d) = encode_sreg(sd);
6768 let (vn, n) = encode_sreg(sn);
6769 let (vm, m) = encode_sreg(sm);
6770
6771 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6772 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6773 }
6774
6775 Ok(result)
6776 }
6777
6778 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6780 let mut result = Vec::new();
6781 let qd_num = qreg_to_num(qd);
6782 let qm_num = qreg_to_num(qm);
6783
6784 for i in 0..4u32 {
6786 let sd = qd_num * 4 + i;
6787 let sm = qm_num * 4 + i;
6788
6789 let (vd, d) = encode_sreg(sd);
6790 let (vm, m) = encode_sreg(sm);
6791
6792 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6793 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6794 }
6795
6796 Ok(result)
6797 }
6798}
6799
6800#[cfg(test)]
6801mod tests {
6802 use super::*;
6803
6804 #[test]
6805 fn test_encoder_creation() {
6806 let encoder_arm = ArmEncoder::new_arm32();
6807 assert!(!encoder_arm.thumb_mode);
6808
6809 let encoder_thumb = ArmEncoder::new_thumb2();
6810 assert!(encoder_thumb.thumb_mode);
6811 }
6812
6813 #[test]
6814 fn test_encode_nop_arm32() {
6815 let encoder = ArmEncoder::new_arm32();
6816 let code = encoder.encode(&ArmOp::Nop).unwrap();
6817
6818 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
6821
6822 #[test]
6823 fn test_encode_nop_thumb() {
6824 let encoder = ArmEncoder::new_thumb2();
6825 let code = encoder.encode(&ArmOp::Nop).unwrap();
6826
6827 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
6830
6831 #[test]
6832 fn test_encode_mov_immediate_arm32() {
6833 let encoder = ArmEncoder::new_arm32();
6834 let op = ArmOp::Mov {
6835 rd: Reg::R0,
6836 op2: Operand2::Imm(42),
6837 };
6838
6839 let code = encoder.encode(&op).unwrap();
6840 assert_eq!(code.len(), 4);
6841
6842 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6844 assert_eq!(instr & 0x0E000000, 0x02000000); }
6846
6847 #[test]
6848 fn test_encode_add_registers_arm32() {
6849 let encoder = ArmEncoder::new_arm32();
6850 let op = ArmOp::Add {
6851 rd: Reg::R0,
6852 rn: Reg::R1,
6853 op2: Operand2::Reg(Reg::R2),
6854 };
6855
6856 let code = encoder.encode(&op).unwrap();
6857 assert_eq!(code.len(), 4);
6858
6859 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6860 assert_eq!(instr & 0x0FE00000, 0x00800000);
6862 }
6863
6864 #[test]
6865 fn test_encode_ldr_arm32() {
6866 let encoder = ArmEncoder::new_arm32();
6867 let op = ArmOp::Ldr {
6868 rd: Reg::R0,
6869 addr: MemAddr::imm(Reg::R1, 4),
6870 };
6871
6872 let code = encoder.encode(&op).unwrap();
6873 assert_eq!(code.len(), 4);
6874
6875 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6876 assert_eq!(instr & 0x00100000, 0x00100000);
6878 }
6879
6880 #[test]
6881 fn test_encode_str_arm32() {
6882 let encoder = ArmEncoder::new_arm32();
6883 let op = ArmOp::Str {
6884 rd: Reg::R0,
6885 addr: MemAddr::imm(Reg::SP, 0),
6886 };
6887
6888 let code = encoder.encode(&op).unwrap();
6889 assert_eq!(code.len(), 4);
6890 }
6891
6892 #[test]
6893 fn test_encode_branch_arm32() {
6894 let encoder = ArmEncoder::new_arm32();
6895 let op = ArmOp::Bl {
6896 label: "main".to_string(),
6897 };
6898
6899 let code = encoder.encode(&op).unwrap();
6900 assert_eq!(code.len(), 4);
6901
6902 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6903 assert_eq!(instr & 0x0F000000, 0x0B000000);
6905 }
6906
6907 #[test]
6908 fn test_encode_sequence() {
6909 let encoder = ArmEncoder::new_arm32();
6910 let ops = vec![
6911 ArmOp::Mov {
6912 rd: Reg::R0,
6913 op2: Operand2::Imm(42),
6914 },
6915 ArmOp::Mov {
6916 rd: Reg::R1,
6917 op2: Operand2::Imm(10),
6918 },
6919 ArmOp::Add {
6920 rd: Reg::R2,
6921 rn: Reg::R0,
6922 op2: Operand2::Reg(Reg::R1),
6923 },
6924 ];
6925
6926 let code = encoder.encode_sequence(&ops).unwrap();
6927 assert_eq!(code.len(), 12); }
6929
6930 #[test]
6931 fn test_reg_to_bits() {
6932 assert_eq!(reg_to_bits(&Reg::R0), 0);
6933 assert_eq!(reg_to_bits(&Reg::R7), 7);
6934 assert_eq!(reg_to_bits(&Reg::SP), 13);
6935 assert_eq!(reg_to_bits(&Reg::LR), 14);
6936 assert_eq!(reg_to_bits(&Reg::PC), 15);
6937 }
6938
6939 #[test]
6940 fn test_encode_bitwise_operations() {
6941 let encoder = ArmEncoder::new_arm32();
6942
6943 let and_op = ArmOp::And {
6944 rd: Reg::R0,
6945 rn: Reg::R1,
6946 op2: Operand2::Reg(Reg::R2),
6947 };
6948 let and_code = encoder.encode(&and_op).unwrap();
6949 assert_eq!(and_code.len(), 4);
6950
6951 let orr_op = ArmOp::Orr {
6952 rd: Reg::R0,
6953 rn: Reg::R1,
6954 op2: Operand2::Reg(Reg::R2),
6955 };
6956 let orr_code = encoder.encode(&orr_op).unwrap();
6957 assert_eq!(orr_code.len(), 4);
6958
6959 let eor_op = ArmOp::Eor {
6960 rd: Reg::R0,
6961 rn: Reg::R1,
6962 op2: Operand2::Reg(Reg::R2),
6963 };
6964 let eor_code = encoder.encode(&eor_op).unwrap();
6965 assert_eq!(eor_code.len(), 4);
6966 }
6967
6968 #[test]
6971 fn test_encode_sdiv_thumb2() {
6972 let encoder = ArmEncoder::new_thumb2();
6973 let op = ArmOp::Sdiv {
6974 rd: Reg::R0,
6975 rn: Reg::R1,
6976 rm: Reg::R2,
6977 };
6978
6979 let code = encoder.encode(&op).unwrap();
6980 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
6987 assert_eq!(code[1], 0xFB);
6988 assert_eq!(code[2], 0xF2);
6989 assert_eq!(code[3], 0xF0);
6990 }
6991
6992 #[test]
6993 fn test_encode_udiv_thumb2() {
6994 let encoder = ArmEncoder::new_thumb2();
6995 let op = ArmOp::Udiv {
6996 rd: Reg::R0,
6997 rn: Reg::R1,
6998 rm: Reg::R2,
6999 };
7000
7001 let code = encoder.encode(&op).unwrap();
7002 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7007 assert_eq!(code[1], 0xFB);
7008 assert_eq!(code[2], 0xF2);
7009 assert_eq!(code[3], 0xF0);
7010 }
7011
7012 #[test]
7013 fn test_encode_mul_thumb2() {
7014 let encoder = ArmEncoder::new_thumb2();
7015 let op = ArmOp::Mul {
7016 rd: Reg::R0,
7017 rn: Reg::R1,
7018 rm: Reg::R2,
7019 };
7020
7021 let code = encoder.encode(&op).unwrap();
7022 assert_eq!(code.len(), 4); }
7024
7025 #[test]
7026 fn test_encode_and_thumb2() {
7027 let encoder = ArmEncoder::new_thumb2();
7028 let op = ArmOp::And {
7029 rd: Reg::R0,
7030 rn: Reg::R1,
7031 op2: Operand2::Reg(Reg::R2),
7032 };
7033
7034 let code = encoder.encode(&op).unwrap();
7035 assert_eq!(code.len(), 4); }
7037
7038 #[test]
7039 fn test_encode_lsl_thumb2_low_regs() {
7040 let encoder = ArmEncoder::new_thumb2();
7041 let op = ArmOp::Lsl {
7042 rd: Reg::R0,
7043 rn: Reg::R1,
7044 shift: 5,
7045 };
7046
7047 let code = encoder.encode(&op).unwrap();
7048 assert_eq!(code.len(), 2); }
7050
7051 #[test]
7052 fn test_encode_clz_thumb2() {
7053 let encoder = ArmEncoder::new_thumb2();
7054 let op = ArmOp::Clz {
7055 rd: Reg::R0,
7056 rm: Reg::R1,
7057 };
7058
7059 let code = encoder.encode(&op).unwrap();
7060 assert_eq!(code.len(), 4); }
7062
7063 #[test]
7064 fn test_encode_bx_thumb2() {
7065 let encoder = ArmEncoder::new_thumb2();
7066 let op = ArmOp::Bx { rm: Reg::LR };
7067
7068 let code = encoder.encode(&op).unwrap();
7069 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7073 }
7074
7075 #[test]
7080 fn test_encode_f32_abs_arm32() {
7081 let encoder = ArmEncoder::new_arm32();
7082 let op = ArmOp::F32Abs {
7083 sd: VfpReg::S0,
7084 sm: VfpReg::S2,
7085 };
7086 let code = encoder.encode(&op).unwrap();
7087 assert_eq!(code.len(), 4); }
7089
7090 #[test]
7091 fn test_encode_f32_neg_arm32() {
7092 let encoder = ArmEncoder::new_arm32();
7093 let op = ArmOp::F32Neg {
7094 sd: VfpReg::S0,
7095 sm: VfpReg::S2,
7096 };
7097 let code = encoder.encode(&op).unwrap();
7098 assert_eq!(code.len(), 4);
7099 }
7100
7101 #[test]
7102 fn test_encode_f32_sqrt_arm32() {
7103 let encoder = ArmEncoder::new_arm32();
7104 let op = ArmOp::F32Sqrt {
7105 sd: VfpReg::S0,
7106 sm: VfpReg::S2,
7107 };
7108 let code = encoder.encode(&op).unwrap();
7109 assert_eq!(code.len(), 4);
7110 }
7111
7112 #[test]
7113 fn test_encode_f32_ceil_arm32() {
7114 let encoder = ArmEncoder::new_arm32();
7115 let op = ArmOp::F32Ceil {
7116 sd: VfpReg::S0,
7117 sm: VfpReg::S2,
7118 };
7119 let code = encoder.encode(&op).unwrap();
7120 assert_eq!(code.len(), 36);
7122 }
7123
7124 #[test]
7125 fn test_encode_f32_floor_thumb2() {
7126 let encoder = ArmEncoder::new_thumb2();
7127 let op = ArmOp::F32Floor {
7128 sd: VfpReg::S0,
7129 sm: VfpReg::S2,
7130 };
7131 let code = encoder.encode(&op).unwrap();
7132 assert_eq!(code.len(), 36);
7134 }
7135
7136 #[test]
7137 fn test_encode_f32_min_arm32() {
7138 let encoder = ArmEncoder::new_arm32();
7139 let op = ArmOp::F32Min {
7140 sd: VfpReg::S0,
7141 sn: VfpReg::S2,
7142 sm: VfpReg::S4,
7143 };
7144 let code = encoder.encode(&op).unwrap();
7145 assert_eq!(code.len(), 16); }
7147
7148 #[test]
7149 fn test_encode_f32_max_thumb2() {
7150 let encoder = ArmEncoder::new_thumb2();
7151 let op = ArmOp::F32Max {
7152 sd: VfpReg::S0,
7153 sn: VfpReg::S2,
7154 sm: VfpReg::S4,
7155 };
7156 let code = encoder.encode(&op).unwrap();
7157 assert_eq!(code.len(), 18);
7159 }
7160
7161 #[test]
7162 fn test_encode_f32_copysign_arm32() {
7163 let encoder = ArmEncoder::new_arm32();
7164 let op = ArmOp::F32Copysign {
7165 sd: VfpReg::S0,
7166 sn: VfpReg::S2,
7167 sm: VfpReg::S4,
7168 };
7169 let code = encoder.encode(&op).unwrap();
7170 assert_eq!(code.len(), 24);
7172 }
7173
7174 #[test]
7179 fn test_encode_f64_add_arm32() {
7180 let encoder = ArmEncoder::new_arm32();
7181 let op = ArmOp::F64Add {
7182 dd: VfpReg::D0,
7183 dn: VfpReg::D1,
7184 dm: VfpReg::D2,
7185 };
7186 let code = encoder.encode(&op).unwrap();
7187 assert_eq!(code.len(), 4);
7188 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7190 assert_eq!((instr >> 8) & 0xF, 0xB); }
7192
7193 #[test]
7194 fn test_encode_f64_sub_thumb2() {
7195 let encoder = ArmEncoder::new_thumb2();
7196 let op = ArmOp::F64Sub {
7197 dd: VfpReg::D0,
7198 dn: VfpReg::D1,
7199 dm: VfpReg::D2,
7200 };
7201 let code = encoder.encode(&op).unwrap();
7202 assert_eq!(code.len(), 4); }
7204
7205 #[test]
7206 fn test_encode_f64_mul_arm32() {
7207 let encoder = ArmEncoder::new_arm32();
7208 let op = ArmOp::F64Mul {
7209 dd: VfpReg::D0,
7210 dn: VfpReg::D1,
7211 dm: VfpReg::D2,
7212 };
7213 let code = encoder.encode(&op).unwrap();
7214 assert_eq!(code.len(), 4);
7215 }
7216
7217 #[test]
7218 fn test_encode_f64_div_arm32() {
7219 let encoder = ArmEncoder::new_arm32();
7220 let op = ArmOp::F64Div {
7221 dd: VfpReg::D0,
7222 dn: VfpReg::D1,
7223 dm: VfpReg::D2,
7224 };
7225 let code = encoder.encode(&op).unwrap();
7226 assert_eq!(code.len(), 4);
7227 }
7228
7229 #[test]
7230 fn test_encode_f64_abs_arm32() {
7231 let encoder = ArmEncoder::new_arm32();
7232 let op = ArmOp::F64Abs {
7233 dd: VfpReg::D0,
7234 dm: VfpReg::D2,
7235 };
7236 let code = encoder.encode(&op).unwrap();
7237 assert_eq!(code.len(), 4);
7238 }
7239
7240 #[test]
7241 fn test_encode_f64_neg_arm32() {
7242 let encoder = ArmEncoder::new_arm32();
7243 let op = ArmOp::F64Neg {
7244 dd: VfpReg::D0,
7245 dm: VfpReg::D2,
7246 };
7247 let code = encoder.encode(&op).unwrap();
7248 assert_eq!(code.len(), 4);
7249 }
7250
7251 #[test]
7252 fn test_encode_f64_sqrt_arm32() {
7253 let encoder = ArmEncoder::new_arm32();
7254 let op = ArmOp::F64Sqrt {
7255 dd: VfpReg::D0,
7256 dm: VfpReg::D2,
7257 };
7258 let code = encoder.encode(&op).unwrap();
7259 assert_eq!(code.len(), 4);
7260 }
7261
7262 #[test]
7263 fn test_encode_f64_load_arm32() {
7264 let encoder = ArmEncoder::new_arm32();
7265 let op = ArmOp::F64Load {
7266 dd: VfpReg::D0,
7267 addr: MemAddr::imm(Reg::R0, 8),
7268 };
7269 let code = encoder.encode(&op).unwrap();
7270 assert_eq!(code.len(), 4);
7271 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7272 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7275
7276 #[test]
7277 fn test_encode_f64_store_thumb2() {
7278 let encoder = ArmEncoder::new_thumb2();
7279 let op = ArmOp::F64Store {
7280 dd: VfpReg::D0,
7281 addr: MemAddr::imm(Reg::SP, 0),
7282 };
7283 let code = encoder.encode(&op).unwrap();
7284 assert_eq!(code.len(), 4);
7285 }
7286
7287 #[test]
7288 fn test_encode_f64_compare_arm32() {
7289 let encoder = ArmEncoder::new_arm32();
7290 let op = ArmOp::F64Eq {
7291 rd: Reg::R0,
7292 dn: VfpReg::D0,
7293 dm: VfpReg::D1,
7294 };
7295 let code = encoder.encode(&op).unwrap();
7296 assert_eq!(code.len(), 16); }
7298
7299 #[test]
7300 fn test_encode_f64_compare_thumb2() {
7301 let encoder = ArmEncoder::new_thumb2();
7302 let op = ArmOp::F64Lt {
7303 rd: Reg::R0,
7304 dn: VfpReg::D0,
7305 dm: VfpReg::D1,
7306 };
7307 let code = encoder.encode(&op).unwrap();
7308 assert_eq!(code.len(), 14);
7310 }
7311
7312 #[test]
7313 fn test_encode_f64_const_arm32() {
7314 let encoder = ArmEncoder::new_arm32();
7315 let op = ArmOp::F64Const {
7316 dd: VfpReg::D0,
7317 value: 3.125,
7318 };
7319 let code = encoder.encode(&op).unwrap();
7320 assert_eq!(code.len(), 20);
7322 }
7323
7324 #[test]
7325 fn test_encode_f64_const_thumb2() {
7326 let encoder = ArmEncoder::new_thumb2();
7327 let op = ArmOp::F64Const {
7328 dd: VfpReg::D0,
7329 value: 2.5,
7330 };
7331 let code = encoder.encode(&op).unwrap();
7332 assert_eq!(code.len(), 20);
7334 }
7335
7336 #[test]
7337 fn test_encode_f64_convert_i32s_arm32() {
7338 let encoder = ArmEncoder::new_arm32();
7339 let op = ArmOp::F64ConvertI32S {
7340 dd: VfpReg::D0,
7341 rm: Reg::R0,
7342 };
7343 let code = encoder.encode(&op).unwrap();
7344 assert_eq!(code.len(), 8);
7346 }
7347
7348 #[test]
7349 fn test_encode_f64_promote_f32_arm32() {
7350 let encoder = ArmEncoder::new_arm32();
7351 let op = ArmOp::F64PromoteF32 {
7352 dd: VfpReg::D0,
7353 sm: VfpReg::S0,
7354 };
7355 let code = encoder.encode(&op).unwrap();
7356 assert_eq!(code.len(), 4); }
7358
7359 #[test]
7360 fn test_encode_f64_promote_f32_thumb2() {
7361 let encoder = ArmEncoder::new_thumb2();
7362 let op = ArmOp::F64PromoteF32 {
7363 dd: VfpReg::D0,
7364 sm: VfpReg::S0,
7365 };
7366 let code = encoder.encode(&op).unwrap();
7367 assert_eq!(code.len(), 4);
7368 }
7369
7370 #[test]
7371 fn test_encode_i32_trunc_f64s_arm32() {
7372 let encoder = ArmEncoder::new_arm32();
7373 let op = ArmOp::I32TruncF64S {
7374 rd: Reg::R0,
7375 dm: VfpReg::D0,
7376 };
7377 let code = encoder.encode(&op).unwrap();
7378 assert_eq!(code.len(), 8);
7380 }
7381
7382 #[test]
7383 fn test_encode_f64_reinterpret_i64_arm32() {
7384 let encoder = ArmEncoder::new_arm32();
7385 let op = ArmOp::F64ReinterpretI64 {
7386 dd: VfpReg::D0,
7387 rmlo: Reg::R0,
7388 rmhi: Reg::R1,
7389 };
7390 let code = encoder.encode(&op).unwrap();
7391 assert_eq!(code.len(), 4); }
7393
7394 #[test]
7395 fn test_encode_i64_reinterpret_f64_thumb2() {
7396 let encoder = ArmEncoder::new_thumb2();
7397 let op = ArmOp::I64ReinterpretF64 {
7398 rdlo: Reg::R0,
7399 rdhi: Reg::R1,
7400 dm: VfpReg::D0,
7401 };
7402 let code = encoder.encode(&op).unwrap();
7403 assert_eq!(code.len(), 4);
7404 }
7405
7406 #[test]
7407 fn test_encode_f64_trunc_thumb2() {
7408 let encoder = ArmEncoder::new_thumb2();
7409 let op = ArmOp::F64Trunc {
7410 dd: VfpReg::D0,
7411 dm: VfpReg::D1,
7412 };
7413 let code = encoder.encode(&op).unwrap();
7414 assert_eq!(code.len(), 8);
7416 }
7417
7418 #[test]
7419 fn test_encode_f64_min_arm32() {
7420 let encoder = ArmEncoder::new_arm32();
7421 let op = ArmOp::F64Min {
7422 dd: VfpReg::D0,
7423 dn: VfpReg::D1,
7424 dm: VfpReg::D2,
7425 };
7426 let code = encoder.encode(&op).unwrap();
7427 assert_eq!(code.len(), 16);
7429 }
7430
7431 #[test]
7432 fn test_f64_cp11_encoding() {
7433 let encoder = ArmEncoder::new_arm32();
7435
7436 let code = encoder
7438 .encode(&ArmOp::F64Add {
7439 dd: VfpReg::D0,
7440 dn: VfpReg::D0,
7441 dm: VfpReg::D0,
7442 })
7443 .unwrap();
7444 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7445 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7446
7447 let code = encoder
7449 .encode(&ArmOp::F32Add {
7450 sd: VfpReg::S0,
7451 sn: VfpReg::S0,
7452 sm: VfpReg::S0,
7453 })
7454 .unwrap();
7455 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7456 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7457 }
7458
7459 #[test]
7460 fn test_dreg_encoding_higher_registers() {
7461 let encoder = ArmEncoder::new_arm32();
7462
7463 let op = ArmOp::F64Add {
7465 dd: VfpReg::D15,
7466 dn: VfpReg::D14,
7467 dm: VfpReg::D13,
7468 };
7469 let code = encoder.encode(&op).unwrap();
7470 assert_eq!(code.len(), 4);
7471
7472 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7474 assert_eq!((instr >> 8) & 0xF, 0xB); }
7476
7477 #[test]
7482 fn test_encode_label_emits_no_bytes() {
7483 let encoder = ArmEncoder::new_thumb2();
7484 let op = ArmOp::Label {
7485 name: ".Lblock_end_0".to_string(),
7486 };
7487 let code = encoder.encode(&op).unwrap();
7488 assert!(code.is_empty(), "Label should emit zero bytes");
7489
7490 let encoder32 = ArmEncoder::new_arm32();
7491 let code32 = encoder32.encode(&op).unwrap();
7492 assert!(
7493 code32.is_empty(),
7494 "Label should emit zero bytes in ARM32 too"
7495 );
7496 }
7497
7498 #[test]
7499 fn test_encode_bcc_eq_thumb2() {
7500 use synth_synthesis::Condition;
7501 let encoder = ArmEncoder::new_thumb2();
7502 let op = ArmOp::Bcc {
7503 cond: Condition::EQ,
7504 label: "target".to_string(),
7505 };
7506 let code = encoder.encode(&op).unwrap();
7507 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7511 }
7512
7513 #[test]
7514 fn test_encode_bcc_ne_thumb2() {
7515 use synth_synthesis::Condition;
7516 let encoder = ArmEncoder::new_thumb2();
7517 let op = ArmOp::Bcc {
7518 cond: Condition::NE,
7519 label: "target".to_string(),
7520 };
7521 let code = encoder.encode(&op).unwrap();
7522 assert_eq!(code.len(), 2);
7523
7524 assert_eq!(code, vec![0x00, 0xD1]);
7526 }
7527
7528 #[test]
7529 fn test_encode_bcc_arm32() {
7530 use synth_synthesis::Condition;
7531 let encoder = ArmEncoder::new_arm32();
7532 let op = ArmOp::Bcc {
7533 cond: Condition::EQ,
7534 label: "target".to_string(),
7535 };
7536 let code = encoder.encode(&op).unwrap();
7537 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7540 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7544
7545 #[test]
7546 fn test_encode_udf_thumb2() {
7547 let encoder = ArmEncoder::new_thumb2();
7548 let op = ArmOp::Udf { imm: 0 };
7549 let code = encoder.encode(&op).unwrap();
7550 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
7554 }
7555
7556 #[test]
7557 fn test_encode_nop_thumb2() {
7558 let encoder = ArmEncoder::new_thumb2();
7559 let op = ArmOp::Nop;
7560 let code = encoder.encode(&op).unwrap();
7561 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
7565 }
7566
7567 #[test]
7572 fn test_encode_i64_add_thumb2() {
7573 let encoder = ArmEncoder::new_thumb2();
7574 let op = ArmOp::I64Add {
7575 rdlo: Reg::R0,
7576 rdhi: Reg::R1,
7577 rnlo: Reg::R0,
7578 rnhi: Reg::R1,
7579 rmlo: Reg::R2,
7580 rmhi: Reg::R3,
7581 };
7582 let code = encoder.encode(&op).unwrap();
7583 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
7585 }
7586
7587 #[test]
7588 fn test_encode_i64_sub_thumb2() {
7589 let encoder = ArmEncoder::new_thumb2();
7590 let op = ArmOp::I64Sub {
7591 rdlo: Reg::R0,
7592 rdhi: Reg::R1,
7593 rnlo: Reg::R0,
7594 rnhi: Reg::R1,
7595 rmlo: Reg::R2,
7596 rmhi: Reg::R3,
7597 };
7598 let code = encoder.encode(&op).unwrap();
7599 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
7601 }
7602
7603 #[test]
7604 fn test_encode_i64_and_thumb2() {
7605 let encoder = ArmEncoder::new_thumb2();
7606 let op = ArmOp::I64And {
7607 rdlo: Reg::R0,
7608 rdhi: Reg::R1,
7609 rnlo: Reg::R0,
7610 rnhi: Reg::R1,
7611 rmlo: Reg::R2,
7612 rmhi: Reg::R3,
7613 };
7614 let code = encoder.encode(&op).unwrap();
7615 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
7617 }
7618
7619 #[test]
7620 fn test_encode_i64_or_thumb2() {
7621 let encoder = ArmEncoder::new_thumb2();
7622 let op = ArmOp::I64Or {
7623 rdlo: Reg::R0,
7624 rdhi: Reg::R1,
7625 rnlo: Reg::R0,
7626 rnhi: Reg::R1,
7627 rmlo: Reg::R2,
7628 rmhi: Reg::R3,
7629 };
7630 let code = encoder.encode(&op).unwrap();
7631 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
7632 }
7633
7634 #[test]
7635 fn test_encode_i64_xor_thumb2() {
7636 let encoder = ArmEncoder::new_thumb2();
7637 let op = ArmOp::I64Xor {
7638 rdlo: Reg::R0,
7639 rdhi: Reg::R1,
7640 rnlo: Reg::R0,
7641 rnhi: Reg::R1,
7642 rmlo: Reg::R2,
7643 rmhi: Reg::R3,
7644 };
7645 let code = encoder.encode(&op).unwrap();
7646 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
7647 }
7648
7649 #[test]
7650 fn test_encode_i64_const_small_thumb2() {
7651 let encoder = ArmEncoder::new_thumb2();
7652 let op = ArmOp::I64Const {
7654 rdlo: Reg::R0,
7655 rdhi: Reg::R1,
7656 value: 42,
7657 };
7658 let code = encoder.encode(&op).unwrap();
7659 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
7661 }
7662
7663 #[test]
7664 fn test_encode_i64_const_large_thumb2() {
7665 let encoder = ArmEncoder::new_thumb2();
7666 let op = ArmOp::I64Const {
7668 rdlo: Reg::R0,
7669 rdhi: Reg::R1,
7670 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
7671 };
7672 let code = encoder.encode(&op).unwrap();
7673 assert_eq!(
7675 code.len(),
7676 16,
7677 "I64Const with large value should be 16 bytes"
7678 );
7679 }
7680
7681 #[test]
7682 fn test_encode_i64_extend_i32_s_thumb2() {
7683 let encoder = ArmEncoder::new_thumb2();
7684 let op = ArmOp::I64ExtendI32S {
7685 rdlo: Reg::R0,
7686 rdhi: Reg::R1,
7687 rn: Reg::R0,
7688 };
7689 let code = encoder.encode(&op).unwrap();
7690 assert_eq!(
7692 code.len(),
7693 4,
7694 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
7695 );
7696 }
7697
7698 #[test]
7699 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
7700 let encoder = ArmEncoder::new_thumb2();
7701 let op = ArmOp::I64ExtendI32S {
7702 rdlo: Reg::R0,
7703 rdhi: Reg::R1,
7704 rn: Reg::R2,
7705 };
7706 let code = encoder.encode(&op).unwrap();
7707 assert!(
7709 code.len() >= 6,
7710 "I64ExtendI32S (diff reg) should be at least 6 bytes"
7711 );
7712 }
7713
7714 #[test]
7715 fn test_encode_i64_extend_i32_u_thumb2() {
7716 let encoder = ArmEncoder::new_thumb2();
7717 let op = ArmOp::I64ExtendI32U {
7718 rdlo: Reg::R0,
7719 rdhi: Reg::R1,
7720 rn: Reg::R0,
7721 };
7722 let code = encoder.encode(&op).unwrap();
7723 assert_eq!(
7725 code.len(),
7726 2,
7727 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
7728 );
7729 }
7730
7731 #[test]
7732 fn test_encode_i32_wrap_i64_nop_thumb2() {
7733 let encoder = ArmEncoder::new_thumb2();
7734 let op = ArmOp::I32WrapI64 {
7736 rd: Reg::R0,
7737 rnlo: Reg::R0,
7738 };
7739 let code = encoder.encode(&op).unwrap();
7740 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
7741 assert_eq!(code, vec![0x00, 0xBF]); }
7743
7744 #[test]
7745 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
7746 let encoder = ArmEncoder::new_thumb2();
7747 let op = ArmOp::I32WrapI64 {
7748 rd: Reg::R2,
7749 rnlo: Reg::R0,
7750 };
7751 let code = encoder.encode(&op).unwrap();
7752 assert!(
7754 code.len() >= 2,
7755 "I32WrapI64 diff reg should emit at least 2 bytes"
7756 );
7757 }
7758
7759 #[test]
7760 fn test_encode_i64_eqz_thumb2() {
7761 let encoder = ArmEncoder::new_thumb2();
7762 let op = ArmOp::I64Eqz {
7763 rd: Reg::R0,
7764 rnlo: Reg::R0,
7765 rnhi: Reg::R1,
7766 };
7767 let code = encoder.encode(&op).unwrap();
7768 assert!(
7770 code.len() >= 6,
7771 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
7772 );
7773 }
7774
7775 #[test]
7776 fn test_encode_i64_eq_thumb2() {
7777 let encoder = ArmEncoder::new_thumb2();
7778 let op = ArmOp::I64Eq {
7779 rd: Reg::R0,
7780 rnlo: Reg::R0,
7781 rnhi: Reg::R1,
7782 rmlo: Reg::R2,
7783 rmhi: Reg::R3,
7784 };
7785 let code = encoder.encode(&op).unwrap();
7786 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
7788 }
7789
7790 #[test]
7791 fn test_encode_i64_ldr_thumb2() {
7792 let encoder = ArmEncoder::new_thumb2();
7793 let op = ArmOp::I64Ldr {
7794 rdlo: Reg::R0,
7795 rdhi: Reg::R1,
7796 addr: MemAddr::imm(Reg::SP, 0),
7797 };
7798 let code = encoder.encode(&op).unwrap();
7799 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
7801 }
7802
7803 #[test]
7804 fn test_encode_i64_str_thumb2() {
7805 let encoder = ArmEncoder::new_thumb2();
7806 let op = ArmOp::I64Str {
7807 rdlo: Reg::R0,
7808 rdhi: Reg::R1,
7809 addr: MemAddr::imm(Reg::SP, 0),
7810 };
7811 let code = encoder.encode(&op).unwrap();
7812 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
7814 }
7815
7816 #[test]
7817 fn test_encode_i64_all_comparisons_thumb2() {
7818 let encoder = ArmEncoder::new_thumb2();
7819
7820 let ops = vec![
7821 ArmOp::I64Ne {
7822 rd: Reg::R0,
7823 rnlo: Reg::R0,
7824 rnhi: Reg::R1,
7825 rmlo: Reg::R2,
7826 rmhi: Reg::R3,
7827 },
7828 ArmOp::I64LtS {
7829 rd: Reg::R0,
7830 rnlo: Reg::R0,
7831 rnhi: Reg::R1,
7832 rmlo: Reg::R2,
7833 rmhi: Reg::R3,
7834 },
7835 ArmOp::I64LtU {
7836 rd: Reg::R0,
7837 rnlo: Reg::R0,
7838 rnhi: Reg::R1,
7839 rmlo: Reg::R2,
7840 rmhi: Reg::R3,
7841 },
7842 ArmOp::I64LeS {
7843 rd: Reg::R0,
7844 rnlo: Reg::R0,
7845 rnhi: Reg::R1,
7846 rmlo: Reg::R2,
7847 rmhi: Reg::R3,
7848 },
7849 ArmOp::I64LeU {
7850 rd: Reg::R0,
7851 rnlo: Reg::R0,
7852 rnhi: Reg::R1,
7853 rmlo: Reg::R2,
7854 rmhi: Reg::R3,
7855 },
7856 ArmOp::I64GtS {
7857 rd: Reg::R0,
7858 rnlo: Reg::R0,
7859 rnhi: Reg::R1,
7860 rmlo: Reg::R2,
7861 rmhi: Reg::R3,
7862 },
7863 ArmOp::I64GtU {
7864 rd: Reg::R0,
7865 rnlo: Reg::R0,
7866 rnhi: Reg::R1,
7867 rmlo: Reg::R2,
7868 rmhi: Reg::R3,
7869 },
7870 ArmOp::I64GeS {
7871 rd: Reg::R0,
7872 rnlo: Reg::R0,
7873 rnhi: Reg::R1,
7874 rmlo: Reg::R2,
7875 rmhi: Reg::R3,
7876 },
7877 ArmOp::I64GeU {
7878 rd: Reg::R0,
7879 rnlo: Reg::R0,
7880 rnhi: Reg::R1,
7881 rmlo: Reg::R2,
7882 rmhi: Reg::R3,
7883 },
7884 ];
7885
7886 for op in &ops {
7887 let code = encoder.encode(op).unwrap();
7888 assert!(
7889 code.len() >= 8,
7890 "i64 comparison {:?} should emit at least 8 bytes, got {}",
7891 op,
7892 code.len()
7893 );
7894 }
7895 }
7896
7897 #[test]
7898 fn test_encode_i64_const_zero_thumb2() {
7899 let encoder = ArmEncoder::new_thumb2();
7900 let op = ArmOp::I64Const {
7901 rdlo: Reg::R0,
7902 rdhi: Reg::R1,
7903 value: 0,
7904 };
7905 let code = encoder.encode(&op).unwrap();
7906 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
7908 }
7909
7910 #[test]
7911 fn test_encode_i64_const_negative_one_thumb2() {
7912 let encoder = ArmEncoder::new_thumb2();
7913 let op = ArmOp::I64Const {
7914 rdlo: Reg::R0,
7915 rdhi: Reg::R1,
7916 value: -1, };
7918 let code = encoder.encode(&op).unwrap();
7919 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
7921 }
7922
7923 #[test]
7928 fn test_encode_ldrb_arm32() {
7929 let encoder = ArmEncoder::new_arm32();
7930 let op = ArmOp::Ldrb {
7931 rd: Reg::R0,
7932 addr: MemAddr::imm(Reg::R1, 4),
7933 };
7934 let code = encoder.encode(&op).unwrap();
7935 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
7936 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7938 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
7939 }
7940
7941 #[test]
7942 fn test_encode_strb_arm32() {
7943 let encoder = ArmEncoder::new_arm32();
7944 let op = ArmOp::Strb {
7945 rd: Reg::R0,
7946 addr: MemAddr::imm(Reg::R1, 0),
7947 };
7948 let code = encoder.encode(&op).unwrap();
7949 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
7950 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7952 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
7953 }
7954
7955 #[test]
7956 fn test_encode_ldrh_arm32() {
7957 let encoder = ArmEncoder::new_arm32();
7958 let op = ArmOp::Ldrh {
7959 rd: Reg::R0,
7960 addr: MemAddr::imm(Reg::R1, 2),
7961 };
7962 let code = encoder.encode(&op).unwrap();
7963 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
7964 }
7965
7966 #[test]
7967 fn test_encode_strh_arm32() {
7968 let encoder = ArmEncoder::new_arm32();
7969 let op = ArmOp::Strh {
7970 rd: Reg::R0,
7971 addr: MemAddr::imm(Reg::R1, 0),
7972 };
7973 let code = encoder.encode(&op).unwrap();
7974 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
7975 }
7976
7977 #[test]
7978 fn test_encode_ldrsb_arm32() {
7979 let encoder = ArmEncoder::new_arm32();
7980 let op = ArmOp::Ldrsb {
7981 rd: Reg::R0,
7982 addr: MemAddr::imm(Reg::R1, 0),
7983 };
7984 let code = encoder.encode(&op).unwrap();
7985 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
7986 }
7987
7988 #[test]
7989 fn test_encode_ldrsh_arm32() {
7990 let encoder = ArmEncoder::new_arm32();
7991 let op = ArmOp::Ldrsh {
7992 rd: Reg::R0,
7993 addr: MemAddr::imm(Reg::R1, 0),
7994 };
7995 let code = encoder.encode(&op).unwrap();
7996 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
7997 }
7998
7999 #[test]
8000 fn test_encode_ldrb_thumb2_16bit() {
8001 let encoder = ArmEncoder::new_thumb2();
8002 let op = ArmOp::Ldrb {
8003 rd: Reg::R0,
8004 addr: MemAddr::imm(Reg::R1, 4),
8005 };
8006 let code = encoder.encode(&op).unwrap();
8007 assert_eq!(
8009 code.len(),
8010 2,
8011 "Thumb-2 LDRB with small offset should be 16-bit"
8012 );
8013 }
8014
8015 #[test]
8016 fn test_encode_ldrb_thumb2_32bit() {
8017 let encoder = ArmEncoder::new_thumb2();
8018 let op = ArmOp::Ldrb {
8019 rd: Reg::R0,
8020 addr: MemAddr::imm(Reg::R1, 100), };
8022 let code = encoder.encode(&op).unwrap();
8023 assert_eq!(
8024 code.len(),
8025 4,
8026 "Thumb-2 LDRB with large offset should be 32-bit"
8027 );
8028 }
8029
8030 #[test]
8031 fn test_encode_strb_thumb2_16bit() {
8032 let encoder = ArmEncoder::new_thumb2();
8033 let op = ArmOp::Strb {
8034 rd: Reg::R0,
8035 addr: MemAddr::imm(Reg::R1, 10),
8036 };
8037 let code = encoder.encode(&op).unwrap();
8038 assert_eq!(
8039 code.len(),
8040 2,
8041 "Thumb-2 STRB with small offset should be 16-bit"
8042 );
8043 }
8044
8045 #[test]
8046 fn test_encode_ldrh_thumb2_16bit() {
8047 let encoder = ArmEncoder::new_thumb2();
8048 let op = ArmOp::Ldrh {
8049 rd: Reg::R0,
8050 addr: MemAddr::imm(Reg::R1, 4), };
8052 let code = encoder.encode(&op).unwrap();
8053 assert_eq!(
8054 code.len(),
8055 2,
8056 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8057 );
8058 }
8059
8060 #[test]
8061 fn test_encode_strh_thumb2_16bit() {
8062 let encoder = ArmEncoder::new_thumb2();
8063 let op = ArmOp::Strh {
8064 rd: Reg::R0,
8065 addr: MemAddr::imm(Reg::R1, 4),
8066 };
8067 let code = encoder.encode(&op).unwrap();
8068 assert_eq!(
8069 code.len(),
8070 2,
8071 "Thumb-2 STRH with small aligned offset should be 16-bit"
8072 );
8073 }
8074
8075 #[test]
8076 fn test_encode_ldrsb_thumb2() {
8077 let encoder = ArmEncoder::new_thumb2();
8078 let op = ArmOp::Ldrsb {
8079 rd: Reg::R0,
8080 addr: MemAddr::imm(Reg::R1, 0),
8081 };
8082 let code = encoder.encode(&op).unwrap();
8083 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8085 }
8086
8087 #[test]
8088 fn test_encode_ldrsh_thumb2() {
8089 let encoder = ArmEncoder::new_thumb2();
8090 let op = ArmOp::Ldrsh {
8091 rd: Reg::R0,
8092 addr: MemAddr::imm(Reg::R1, 0),
8093 };
8094 let code = encoder.encode(&op).unwrap();
8095 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8096 }
8097
8098 #[test]
8099 fn test_encode_memory_size_thumb2() {
8100 let encoder = ArmEncoder::new_thumb2();
8101 let op = ArmOp::MemorySize { rd: Reg::R0 };
8102 let code = encoder.encode(&op).unwrap();
8103 assert!(!code.is_empty(), "MemorySize should produce code");
8105 }
8106
8107 #[test]
8108 fn test_encode_memory_grow_thumb2() {
8109 let encoder = ArmEncoder::new_thumb2();
8110 let op = ArmOp::MemoryGrow {
8111 rd: Reg::R0,
8112 rn: Reg::R0,
8113 };
8114 let code = encoder.encode(&op).unwrap();
8115 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8116 }
8117
8118 #[test]
8119 fn test_encode_subword_reg_offset_thumb2() {
8120 let encoder = ArmEncoder::new_thumb2();
8121
8122 let op = ArmOp::Ldrb {
8124 rd: Reg::R0,
8125 addr: MemAddr::reg(Reg::R1, Reg::R2),
8126 };
8127 let code = encoder.encode(&op).unwrap();
8128 assert_eq!(
8129 code.len(),
8130 4,
8131 "Thumb-2 LDRB with reg offset should be 32-bit"
8132 );
8133
8134 let op = ArmOp::Strb {
8136 rd: Reg::R0,
8137 addr: MemAddr::reg(Reg::R1, Reg::R2),
8138 };
8139 let code = encoder.encode(&op).unwrap();
8140 assert_eq!(
8141 code.len(),
8142 4,
8143 "Thumb-2 STRB with reg offset should be 32-bit"
8144 );
8145
8146 let op = ArmOp::Ldrh {
8148 rd: Reg::R0,
8149 addr: MemAddr::reg(Reg::R1, Reg::R2),
8150 };
8151 let code = encoder.encode(&op).unwrap();
8152 assert_eq!(
8153 code.len(),
8154 4,
8155 "Thumb-2 LDRH with reg offset should be 32-bit"
8156 );
8157
8158 let op = ArmOp::Strh {
8160 rd: Reg::R0,
8161 addr: MemAddr::reg(Reg::R1, Reg::R2),
8162 };
8163 let code = encoder.encode(&op).unwrap();
8164 assert_eq!(
8165 code.len(),
8166 4,
8167 "Thumb-2 STRH with reg offset should be 32-bit"
8168 );
8169 }
8170
8171 #[test]
8172 fn test_encode_subword_reg_imm_offset_thumb2() {
8173 let encoder = ArmEncoder::new_thumb2();
8174
8175 let op = ArmOp::Ldrb {
8177 rd: Reg::R0,
8178 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8179 };
8180 let code = encoder.encode(&op).unwrap();
8181 assert_eq!(
8183 code.len(),
8184 8,
8185 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8186 );
8187 }
8188
8189 #[test]
8194 fn test_encode_mve_addi32_thumb2() {
8195 let encoder = ArmEncoder::new_thumb2();
8196 let op = ArmOp::MveAddI {
8197 qd: QReg::Q0,
8198 qn: QReg::Q1,
8199 qm: QReg::Q2,
8200 size: MveSize::S32,
8201 };
8202 let code = encoder.encode(&op).unwrap();
8203 assert_eq!(
8204 code.len(),
8205 4,
8206 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8207 );
8208 }
8209
8210 #[test]
8211 fn test_encode_mve_subi16_thumb2() {
8212 let encoder = ArmEncoder::new_thumb2();
8213 let op = ArmOp::MveSubI {
8214 qd: QReg::Q0,
8215 qn: QReg::Q1,
8216 qm: QReg::Q2,
8217 size: MveSize::S16,
8218 };
8219 let code = encoder.encode(&op).unwrap();
8220 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8221 }
8222
8223 #[test]
8224 fn test_encode_mve_muli8_thumb2() {
8225 let encoder = ArmEncoder::new_thumb2();
8226 let op = ArmOp::MveMulI {
8227 qd: QReg::Q0,
8228 qn: QReg::Q1,
8229 qm: QReg::Q2,
8230 size: MveSize::S8,
8231 };
8232 let code = encoder.encode(&op).unwrap();
8233 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8234 }
8235
8236 #[test]
8237 fn test_encode_mve_bitwise_thumb2() {
8238 let encoder = ArmEncoder::new_thumb2();
8239
8240 let ops = vec![
8241 ArmOp::MveAnd {
8242 qd: QReg::Q0,
8243 qn: QReg::Q1,
8244 qm: QReg::Q2,
8245 },
8246 ArmOp::MveOrr {
8247 qd: QReg::Q0,
8248 qn: QReg::Q1,
8249 qm: QReg::Q2,
8250 },
8251 ArmOp::MveEor {
8252 qd: QReg::Q0,
8253 qn: QReg::Q1,
8254 qm: QReg::Q2,
8255 },
8256 ArmOp::MveBic {
8257 qd: QReg::Q0,
8258 qn: QReg::Q1,
8259 qm: QReg::Q2,
8260 },
8261 ];
8262 for op in ops {
8263 let code = encoder.encode(&op).unwrap();
8264 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8265 }
8266 }
8267
8268 #[test]
8269 fn test_encode_mve_mvn_thumb2() {
8270 let encoder = ArmEncoder::new_thumb2();
8271 let op = ArmOp::MveMvn {
8272 qd: QReg::Q0,
8273 qm: QReg::Q1,
8274 };
8275 let code = encoder.encode(&op).unwrap();
8276 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8277 }
8278
8279 #[test]
8280 fn test_encode_mve_load_store_thumb2() {
8281 let encoder = ArmEncoder::new_thumb2();
8282
8283 let load = ArmOp::MveLoad {
8284 qd: QReg::Q0,
8285 addr: MemAddr::imm(Reg::R0, 16),
8286 };
8287 let code = encoder.encode(&load).unwrap();
8288 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8289
8290 let store = ArmOp::MveStore {
8291 qd: QReg::Q1,
8292 addr: MemAddr::imm(Reg::R1, 0),
8293 };
8294 let code = encoder.encode(&store).unwrap();
8295 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8296 }
8297
8298 #[test]
8299 fn test_encode_mve_const_thumb2() {
8300 let encoder = ArmEncoder::new_thumb2();
8301 let op = ArmOp::MveConst {
8302 qd: QReg::Q0,
8303 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8304 };
8305 let code = encoder.encode(&op).unwrap();
8306 assert!(
8309 code.len() >= 24,
8310 "MVE const should produce multiple instructions"
8311 );
8312 }
8313
8314 #[test]
8315 fn test_encode_mve_dup_thumb2() {
8316 let encoder = ArmEncoder::new_thumb2();
8317 let op = ArmOp::MveDup {
8318 qd: QReg::Q0,
8319 rn: Reg::R0,
8320 size: MveSize::S32,
8321 };
8322 let code = encoder.encode(&op).unwrap();
8323 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8324 }
8325
8326 #[test]
8327 fn test_encode_mve_extract_lane_thumb2() {
8328 let encoder = ArmEncoder::new_thumb2();
8329 let op = ArmOp::MveExtractLane {
8330 rd: Reg::R0,
8331 qn: QReg::Q1,
8332 lane: 2,
8333 size: MveSize::S32,
8334 };
8335 let code = encoder.encode(&op).unwrap();
8336 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8337 }
8338
8339 #[test]
8340 fn test_encode_mve_insert_lane_thumb2() {
8341 let encoder = ArmEncoder::new_thumb2();
8342 let op = ArmOp::MveInsertLane {
8343 qd: QReg::Q0,
8344 rn: Reg::R1,
8345 lane: 3,
8346 size: MveSize::S32,
8347 };
8348 let code = encoder.encode(&op).unwrap();
8349 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8350 }
8351
8352 #[test]
8353 fn test_encode_mve_addf32_thumb2() {
8354 let encoder = ArmEncoder::new_thumb2();
8355 let op = ArmOp::MveAddF32 {
8356 qd: QReg::Q0,
8357 qn: QReg::Q1,
8358 qm: QReg::Q2,
8359 };
8360 let code = encoder.encode(&op).unwrap();
8361 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8362 }
8363
8364 #[test]
8365 fn test_encode_mve_divf32_thumb2() {
8366 let encoder = ArmEncoder::new_thumb2();
8367 let op = ArmOp::MveDivF32 {
8368 qd: QReg::Q0,
8369 qn: QReg::Q1,
8370 qm: QReg::Q2,
8371 };
8372 let code = encoder.encode(&op).unwrap();
8373 assert_eq!(
8375 code.len(),
8376 16,
8377 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8378 );
8379 }
8380
8381 #[test]
8382 fn test_encode_mve_sqrtf32_thumb2() {
8383 let encoder = ArmEncoder::new_thumb2();
8384 let op = ArmOp::MveSqrtF32 {
8385 qd: QReg::Q0,
8386 qm: QReg::Q1,
8387 };
8388 let code = encoder.encode(&op).unwrap();
8389 assert_eq!(
8391 code.len(),
8392 16,
8393 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8394 );
8395 }
8396
8397 #[test]
8398 fn test_encode_mve_negf32_thumb2() {
8399 let encoder = ArmEncoder::new_thumb2();
8400 let op = ArmOp::MveNegF32 {
8401 qd: QReg::Q0,
8402 qm: QReg::Q1,
8403 };
8404 let code = encoder.encode(&op).unwrap();
8405 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8406 }
8407
8408 #[test]
8409 fn test_encode_mve_absf32_thumb2() {
8410 let encoder = ArmEncoder::new_thumb2();
8411 let op = ArmOp::MveAbsF32 {
8412 qd: QReg::Q0,
8413 qm: QReg::Q1,
8414 };
8415 let code = encoder.encode(&op).unwrap();
8416 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8417 }
8418
8419 #[test]
8420 fn test_encode_mve_different_qregs() {
8421 let encoder = ArmEncoder::new_thumb2();
8422
8423 let op1 = ArmOp::MveAddI {
8425 qd: QReg::Q0,
8426 qn: QReg::Q0,
8427 qm: QReg::Q0,
8428 size: MveSize::S32,
8429 };
8430 let op2 = ArmOp::MveAddI {
8431 qd: QReg::Q3,
8432 qn: QReg::Q5,
8433 qm: QReg::Q7,
8434 size: MveSize::S32,
8435 };
8436 let code1 = encoder.encode(&op1).unwrap();
8437 let code2 = encoder.encode(&op2).unwrap();
8438 assert_ne!(
8439 code1, code2,
8440 "Different Q-registers should produce different encodings"
8441 );
8442 }
8443
8444 #[test]
8445 fn test_encode_mve_arm32_nop() {
8446 let encoder = ArmEncoder::new_arm32();
8448 let op = ArmOp::MveAddI {
8449 qd: QReg::Q0,
8450 qn: QReg::Q1,
8451 qm: QReg::Q2,
8452 size: MveSize::S32,
8453 };
8454 let code = encoder.encode(&op).unwrap();
8455 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8456 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8458 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8459 }
8460}