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 = 0xF7FF;
2510 let hw2: u16 = 0xFFFE;
2511 let mut bytes = hw1.to_le_bytes().to_vec();
2512 bytes.extend_from_slice(&hw2.to_le_bytes());
2513 Ok(bytes)
2514 }
2515
2516 ArmOp::Mvn { rd, op2 } => {
2518 if let Operand2::Reg(rm) = op2 {
2519 let rd_bits = reg_to_bits(rd) as u16;
2520 let rm_bits = reg_to_bits(rm) as u16;
2521
2522 if rd_bits < 8 && rm_bits < 8 {
2523 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2525 Ok(instr.to_le_bytes().to_vec())
2526 } else {
2527 let hw1: u16 = 0xEA6F_u16;
2529 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2530 let mut bytes = hw1.to_le_bytes().to_vec();
2531 bytes.extend_from_slice(&hw2.to_le_bytes());
2532 Ok(bytes)
2533 }
2534 } else {
2535 let instr: u16 = 0xBF00;
2536 Ok(instr.to_le_bytes().to_vec())
2537 }
2538 }
2539
2540 ArmOp::Movw { rd, imm16 } => {
2542 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2543 }
2544
2545 ArmOp::Movt { rd, imm16 } => {
2547 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2548 }
2549
2550 ArmOp::SetCond { rd, cond } => {
2556 let rd_bits = reg_to_bits(rd) as u16;
2557
2558 use synth_synthesis::Condition;
2560 let cond_bits: u16 = match cond {
2561 Condition::EQ => 0x0,
2562 Condition::NE => 0x1,
2563 Condition::LT => 0xB,
2564 Condition::LE => 0xD,
2565 Condition::GT => 0xC,
2566 Condition::GE => 0xA,
2567 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2572
2573 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2578 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2579
2580 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2582
2583 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2585
2586 let mut bytes = ite_instr.to_le_bytes().to_vec();
2588 bytes.extend_from_slice(&mov_one.to_le_bytes());
2589 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2590 Ok(bytes)
2591 }
2592
2593 ArmOp::I64SetCond {
2598 rd,
2599 rn_lo,
2600 rn_hi,
2601 rm_lo,
2602 rm_hi,
2603 cond,
2604 } => {
2605 use synth_synthesis::Condition;
2606 let rd_bits = reg_to_bits(rd) as u16;
2607 let mut bytes = Vec::new();
2608
2609 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2611 rm: &synth_synthesis::Reg|
2612 -> Vec<u8> {
2613 let rn_bits = reg_to_bits(rn) as u16;
2614 let rm_bits = reg_to_bits(rm) as u16;
2615 if rn_bits < 8 && rm_bits < 8 {
2616 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2617 instr.to_le_bytes().to_vec()
2618 } else {
2619 let n_bit = (rn_bits >> 3) & 1;
2620 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2621 instr.to_le_bytes().to_vec()
2622 }
2623 };
2624
2625 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2627 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2628 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2629 ite_instr.to_le_bytes().to_vec()
2630 };
2631
2632 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2634 let mut b = encode_ite(cond_bits);
2635 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2636 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2637 b.extend_from_slice(&mov_one.to_le_bytes());
2638 b.extend_from_slice(&mov_zero.to_le_bytes());
2639 b
2640 };
2641
2642 match cond {
2643 Condition::EQ | Condition::NE => {
2644 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2646
2647 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2650
2651 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2653
2654 let cond_bits: u16 = match cond {
2656 Condition::EQ => 0x0,
2657 Condition::NE => 0x1,
2658 _ => unreachable!(),
2659 };
2660 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2661 }
2662
2663 Condition::LT => {
2664 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2666
2667 let rn_hi_bits = reg_to_bits(rn_hi);
2670 let rm_hi_bits = reg_to_bits(rm_hi);
2671 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2672 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2673 bytes.extend_from_slice(&hw1.to_le_bytes());
2674 bytes.extend_from_slice(&hw2.to_le_bytes());
2675
2676 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2679
2680 Condition::GT => {
2681 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2684
2685 let rm_hi_bits = reg_to_bits(rm_hi);
2687 let rn_hi_bits = reg_to_bits(rn_hi);
2688 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2689 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2690 bytes.extend_from_slice(&hw1.to_le_bytes());
2691 bytes.extend_from_slice(&hw2.to_le_bytes());
2692
2693 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2696
2697 Condition::LE => {
2698 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2702
2703 let rm_hi_bits = reg_to_bits(rm_hi);
2705 let rn_hi_bits = reg_to_bits(rn_hi);
2706 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2707 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2708 bytes.extend_from_slice(&hw1.to_le_bytes());
2709 bytes.extend_from_slice(&hw2.to_le_bytes());
2710
2711 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2714
2715 Condition::GE => {
2716 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2719
2720 let rn_hi_bits = reg_to_bits(rn_hi);
2722 let rm_hi_bits = reg_to_bits(rm_hi);
2723 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2724 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2725 bytes.extend_from_slice(&hw1.to_le_bytes());
2726 bytes.extend_from_slice(&hw2.to_le_bytes());
2727
2728 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2731
2732 Condition::LO => {
2734 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2736 let rn_hi_bits = reg_to_bits(rn_hi);
2737 let rm_hi_bits = reg_to_bits(rm_hi);
2738 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2739 let hw2: u16 = ((rd_bits as u32) << 8 | rm_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::HI => {
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(0x3, rd_bits)); }
2756
2757 Condition::LS => {
2758 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2760 let rm_hi_bits = reg_to_bits(rm_hi);
2761 let rn_hi_bits = reg_to_bits(rn_hi);
2762 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2763 let hw2: u16 = ((rd_bits as u32) << 8 | rn_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 Condition::HS => {
2770 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2772 let rn_hi_bits = reg_to_bits(rn_hi);
2773 let rm_hi_bits = reg_to_bits(rm_hi);
2774 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2775 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2776 bytes.extend_from_slice(&hw1.to_le_bytes());
2777 bytes.extend_from_slice(&hw2.to_le_bytes());
2778 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2780 }
2781
2782 Ok(bytes)
2783 }
2784
2785 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2788 let rd_bits = reg_to_bits(rd);
2789 let rn_lo_bits = reg_to_bits(rn_lo);
2790 let rn_hi_bits = reg_to_bits(rn_hi);
2791 let mut bytes = Vec::new();
2792
2793 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2795 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2796 bytes.extend_from_slice(&hw1.to_le_bytes());
2797 bytes.extend_from_slice(&hw2.to_le_bytes());
2798
2799 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2801 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2802
2803 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2806 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2807 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2808 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2809 bytes.extend_from_slice(&mov_one.to_le_bytes());
2810 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2811
2812 Ok(bytes)
2813 }
2814
2815 ArmOp::I64Mul {
2819 rd_lo,
2820 rd_hi,
2821 rn_lo,
2822 rn_hi,
2823 rm_lo,
2824 rm_hi,
2825 } => {
2826 let rd_lo_bits = reg_to_bits(rd_lo);
2827 let rd_hi_bits = reg_to_bits(rd_hi);
2828 let rn_lo_bits = reg_to_bits(rn_lo);
2829 let rn_hi_bits = reg_to_bits(rn_hi);
2830 let rm_lo_bits = reg_to_bits(rm_lo);
2831 let rm_hi_bits = reg_to_bits(rm_hi);
2832 let r12: u32 = 12; let mut bytes = Vec::new();
2834
2835 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2838 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2839 bytes.extend_from_slice(&hw1.to_le_bytes());
2840 bytes.extend_from_slice(&hw2.to_le_bytes());
2841
2842 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2845 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
2846 bytes.extend_from_slice(&hw1.to_le_bytes());
2847 bytes.extend_from_slice(&hw2.to_le_bytes());
2848
2849 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
2852 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2853 bytes.extend_from_slice(&hw1.to_le_bytes());
2854 bytes.extend_from_slice(&hw2.to_le_bytes());
2855
2856 let d_bit = (rd_hi_bits >> 3) & 1;
2859 let add_instr: u16 =
2860 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
2861 bytes.extend_from_slice(&add_instr.to_le_bytes());
2862
2863 Ok(bytes)
2864 }
2865
2866 ArmOp::I64Shl {
2869 rd_lo,
2870 rd_hi,
2871 rn_lo,
2872 rn_hi,
2873 rm_lo,
2874 rm_hi,
2875 } => {
2876 let rd_lo_bits = reg_to_bits(rd_lo);
2877 let rd_hi_bits = reg_to_bits(rd_hi);
2878 let rn_lo_bits = reg_to_bits(rn_lo);
2879 let rn_hi_bits = reg_to_bits(rn_hi);
2880 let rm_lo_bits = reg_to_bits(rm_lo);
2881 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2883
2884 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2886 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2887 bytes.extend_from_slice(&hw1.to_le_bytes());
2888 bytes.extend_from_slice(&hw2.to_le_bytes());
2889
2890 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2892 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2893 bytes.extend_from_slice(&hw1.to_le_bytes());
2894 bytes.extend_from_slice(&hw2.to_le_bytes());
2895
2896 let bpl: u16 = 0xD50A;
2898 bytes.extend_from_slice(&bpl.to_le_bytes());
2899
2900 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2903 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) 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 = (0xFA20 | rn_lo_bits) as u16;
2909 let hw2: u16 = (0xF000 | (rm_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_hi_bits) as u16;
2915 let hw2: u16 = (0xF000 | (rd_hi_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 hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
2921 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
2922 bytes.extend_from_slice(&hw1.to_le_bytes());
2923 bytes.extend_from_slice(&hw2.to_le_bytes());
2924
2925 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2927 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2928 bytes.extend_from_slice(&hw1.to_le_bytes());
2929 bytes.extend_from_slice(&hw2.to_le_bytes());
2930
2931 let b_done: u16 = 0xE002;
2933 bytes.extend_from_slice(&b_done.to_le_bytes());
2934
2935 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2938 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
2939 bytes.extend_from_slice(&hw1.to_le_bytes());
2940 bytes.extend_from_slice(&hw2.to_le_bytes());
2941
2942 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
2944 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2945
2946 Ok(bytes) }
2948
2949 ArmOp::I64ShrU {
2951 rd_lo,
2952 rd_hi,
2953 rn_lo,
2954 rn_hi,
2955 rm_lo,
2956 rm_hi,
2957 } => {
2958 let rd_lo_bits = reg_to_bits(rd_lo);
2959 let rd_hi_bits = reg_to_bits(rd_hi);
2960 let rn_lo_bits = reg_to_bits(rn_lo);
2961 let rn_hi_bits = reg_to_bits(rn_hi);
2962 let rm_lo_bits = reg_to_bits(rm_lo);
2963 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2965
2966 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2968 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2969 bytes.extend_from_slice(&hw1.to_le_bytes());
2970 bytes.extend_from_slice(&hw2.to_le_bytes());
2971
2972 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2974 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2975 bytes.extend_from_slice(&hw1.to_le_bytes());
2976 bytes.extend_from_slice(&hw2.to_le_bytes());
2977
2978 let bpl: u16 = 0xD50A;
2980 bytes.extend_from_slice(&bpl.to_le_bytes());
2981
2982 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2985 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) 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 = (0xFA00 | rn_hi_bits) as u16;
2991 let hw2: u16 = (0xF000 | (rm_hi_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_lo_bits) as u16;
2997 let hw2: u16 = (0xF000 | (rd_lo_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 hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3003 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3004 bytes.extend_from_slice(&hw1.to_le_bytes());
3005 bytes.extend_from_slice(&hw2.to_le_bytes());
3006
3007 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3009 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3010 bytes.extend_from_slice(&hw1.to_le_bytes());
3011 bytes.extend_from_slice(&hw2.to_le_bytes());
3012
3013 let b_done: u16 = 0xE002;
3015 bytes.extend_from_slice(&b_done.to_le_bytes());
3016
3017 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3020 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3021 bytes.extend_from_slice(&hw1.to_le_bytes());
3022 bytes.extend_from_slice(&hw2.to_le_bytes());
3023
3024 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3026 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3027
3028 Ok(bytes) }
3030
3031 ArmOp::I64ShrS {
3033 rd_lo,
3034 rd_hi,
3035 rn_lo,
3036 rn_hi,
3037 rm_lo,
3038 rm_hi,
3039 } => {
3040 let rd_lo_bits = reg_to_bits(rd_lo);
3041 let rd_hi_bits = reg_to_bits(rd_hi);
3042 let rn_lo_bits = reg_to_bits(rn_lo);
3043 let rn_hi_bits = reg_to_bits(rn_hi);
3044 let rm_lo_bits = reg_to_bits(rm_lo);
3045 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3047
3048 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3050 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3051 bytes.extend_from_slice(&hw1.to_le_bytes());
3052 bytes.extend_from_slice(&hw2.to_le_bytes());
3053
3054 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3056 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3057 bytes.extend_from_slice(&hw1.to_le_bytes());
3058 bytes.extend_from_slice(&hw2.to_le_bytes());
3059
3060 let bpl: u16 = 0xD50A;
3062 bytes.extend_from_slice(&bpl.to_le_bytes());
3063
3064 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3067 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) 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 = (0xFA00 | rn_hi_bits) as u16;
3073 let hw2: u16 = (0xF000 | (rm_hi_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 = (0xFA20 | rn_lo_bits) as u16;
3079 let hw2: u16 = (0xF000 | (rd_lo_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 hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3085 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3086 bytes.extend_from_slice(&hw1.to_le_bytes());
3087 bytes.extend_from_slice(&hw2.to_le_bytes());
3088
3089 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3091 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3092 bytes.extend_from_slice(&hw1.to_le_bytes());
3093 bytes.extend_from_slice(&hw2.to_le_bytes());
3094
3095 let b_done: u16 = 0xE003;
3097 bytes.extend_from_slice(&b_done.to_le_bytes());
3098
3099 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3102 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3103 bytes.extend_from_slice(&hw1.to_le_bytes());
3104 bytes.extend_from_slice(&hw2.to_le_bytes());
3105
3106 let hw1: u16 = 0xEA4F;
3110 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3111 bytes.extend_from_slice(&hw1.to_le_bytes());
3112 bytes.extend_from_slice(&hw2.to_le_bytes());
3113
3114 Ok(bytes) }
3116
3117 ArmOp::I64Rotl {
3122 rdlo,
3123 rdhi,
3124 rnlo,
3125 rnhi,
3126 shift,
3127 } => {
3128 let rd_lo_bits = reg_to_bits(rdlo);
3129 let rd_hi_bits = reg_to_bits(rdhi);
3130 let rn_lo_bits = reg_to_bits(rnlo);
3131 let rn_hi_bits = reg_to_bits(rnhi);
3132 let shift_bits = reg_to_bits(shift);
3133 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3137
3138 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3140
3141 let hw1: u16 = (0xF000 | shift_bits) as u16;
3143 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3144 bytes.extend_from_slice(&hw1.to_le_bytes());
3145 bytes.extend_from_slice(&hw2.to_le_bytes());
3146
3147 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3149 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3150 bytes.extend_from_slice(&hw1.to_le_bytes());
3151 bytes.extend_from_slice(&hw2.to_le_bytes());
3152
3153 let bpl: u16 = 0xD50E;
3155 bytes.extend_from_slice(&bpl.to_le_bytes());
3156
3157 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3160 let hw2: u16 = ((r3 << 8) | 0x20) 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 = (0xFA20 | rn_lo_bits) as u16;
3166 let hw2: u16 = (0xF000 | (r4 << 8) | r3) 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 = (0xFA20 | rn_hi_bits) as u16;
3172 let hw2: u16 = (0xF000 | (r12 << 8) | r3) 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_hi_bits) as u16;
3178 let hw2: u16 = (0xF000 | (rd_hi_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_hi_bits) as u16;
3184 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3185 bytes.extend_from_slice(&hw1.to_le_bytes());
3186 bytes.extend_from_slice(&hw2.to_le_bytes());
3187
3188 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3190 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3191 bytes.extend_from_slice(&hw1.to_le_bytes());
3192 bytes.extend_from_slice(&hw2.to_le_bytes());
3193
3194 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3196 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3197 bytes.extend_from_slice(&hw1.to_le_bytes());
3198 bytes.extend_from_slice(&hw2.to_le_bytes());
3199
3200 let b_done: u16 = 0xE00E;
3202 bytes.extend_from_slice(&b_done.to_le_bytes());
3203
3204 let hw1: u16 = (0xF1C0 | r3) as u16;
3208 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3209 bytes.extend_from_slice(&hw1.to_le_bytes());
3210 bytes.extend_from_slice(&hw2.to_le_bytes());
3211
3212 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3214 let hw2: u16 = (0xF000 | (r12 << 8) | r4) 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 = (0xFA20 | rn_lo_bits) as u16;
3220 let hw2: u16 = (0xF000 | (r4 << 8) | r4) 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_lo_bits) as u16;
3226 let hw2: u16 = (0xF000 | (shift_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 | shift_bits) as u16;
3232 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3233 bytes.extend_from_slice(&hw1.to_le_bytes());
3234 bytes.extend_from_slice(&hw2.to_le_bytes());
3235
3236 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3238 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3239 bytes.extend_from_slice(&hw1.to_le_bytes());
3240 bytes.extend_from_slice(&hw2.to_le_bytes());
3241
3242 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3244 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3245 bytes.extend_from_slice(&hw1.to_le_bytes());
3246 bytes.extend_from_slice(&hw2.to_le_bytes());
3247
3248 let d_bit = (rd_hi_bits >> 3) & 1;
3250 let mov_instr: u16 =
3251 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3252 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3253
3254 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3256
3257 Ok(bytes) }
3259
3260 ArmOp::I64Rotr {
3265 rdlo,
3266 rdhi,
3267 rnlo,
3268 rnhi,
3269 shift,
3270 } => {
3271 let rd_lo_bits = reg_to_bits(rdlo);
3272 let rd_hi_bits = reg_to_bits(rdhi);
3273 let rn_lo_bits = reg_to_bits(rnlo);
3274 let rn_hi_bits = reg_to_bits(rnhi);
3275 let shift_bits = reg_to_bits(shift);
3276 let r12: u32 = 12;
3277 let r3: u32 = 3;
3278 let r4: u32 = 4;
3279 let mut bytes = Vec::new();
3280
3281 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3283
3284 let hw1: u16 = (0xF000 | shift_bits) as u16;
3286 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3287 bytes.extend_from_slice(&hw1.to_le_bytes());
3288 bytes.extend_from_slice(&hw2.to_le_bytes());
3289
3290 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3292 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3293 bytes.extend_from_slice(&hw1.to_le_bytes());
3294 bytes.extend_from_slice(&hw2.to_le_bytes());
3295
3296 let bpl: u16 = 0xD50E;
3298 bytes.extend_from_slice(&bpl.to_le_bytes());
3299
3300 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3303 let hw2: u16 = ((r3 << 8) | 0x20) 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 = (0xFA00 | rn_hi_bits) as u16;
3309 let hw2: u16 = (0xF000 | (r4 << 8) | r3) 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 = (0xFA00 | rn_lo_bits) as u16;
3315 let hw2: u16 = (0xF000 | (r12 << 8) | r3) 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_lo_bits) as u16;
3321 let hw2: u16 = (0xF000 | (rd_lo_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_lo_bits) as u16;
3327 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3328 bytes.extend_from_slice(&hw1.to_le_bytes());
3329 bytes.extend_from_slice(&hw2.to_le_bytes());
3330
3331 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3333 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3334 bytes.extend_from_slice(&hw1.to_le_bytes());
3335 bytes.extend_from_slice(&hw2.to_le_bytes());
3336
3337 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3339 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3340 bytes.extend_from_slice(&hw1.to_le_bytes());
3341 bytes.extend_from_slice(&hw2.to_le_bytes());
3342
3343 let b_done: u16 = 0xE00E;
3345 bytes.extend_from_slice(&b_done.to_le_bytes());
3346
3347 let hw1: u16 = (0xF1C0 | r3) as u16;
3350 let hw2: u16 = ((r4 << 8) | 0x20) 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 = (0xFA00 | rn_lo_bits) as u16;
3356 let hw2: u16 = (0xF000 | (r12 << 8) | r4) 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 = (0xFA00 | rn_hi_bits) as u16;
3362 let hw2: u16 = (0xF000 | (r4 << 8) | r4) 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_hi_bits) as u16;
3368 let hw2: u16 = (0xF000 | (shift_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 | shift_bits) as u16;
3374 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3375 bytes.extend_from_slice(&hw1.to_le_bytes());
3376 bytes.extend_from_slice(&hw2.to_le_bytes());
3377
3378 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3380 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3381 bytes.extend_from_slice(&hw1.to_le_bytes());
3382 bytes.extend_from_slice(&hw2.to_le_bytes());
3383
3384 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3386 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3387 bytes.extend_from_slice(&hw1.to_le_bytes());
3388 bytes.extend_from_slice(&hw2.to_le_bytes());
3389
3390 let d_bit = (rd_lo_bits >> 3) & 1;
3392 let mov_instr: u16 =
3393 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3394 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3395
3396 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3398
3399 Ok(bytes) }
3401
3402 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3416 let rd_bits = reg_to_bits(rd);
3417 let rn_lo_bits = reg_to_bits(rnlo);
3418 let rn_hi_bits = reg_to_bits(rnhi);
3419 let mut bytes = Vec::new();
3420
3421 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3423 let hw2: u16 = 0x0F00;
3424 bytes.extend_from_slice(&hw1.to_le_bytes());
3425 bytes.extend_from_slice(&hw2.to_le_bytes());
3426
3427 let beq: u16 = 0xD003;
3430 bytes.extend_from_slice(&beq.to_le_bytes());
3431
3432 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3435 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3436 bytes.extend_from_slice(&hw1.to_le_bytes());
3437 bytes.extend_from_slice(&hw2.to_le_bytes());
3438
3439 let b_done: u16 = 0xE004;
3442 bytes.extend_from_slice(&b_done.to_le_bytes());
3443
3444 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3446
3447 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3451 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3452 bytes.extend_from_slice(&hw1.to_le_bytes());
3453 bytes.extend_from_slice(&hw2.to_le_bytes());
3454
3455 let hw1: u16 = (0xF100 | rd_bits) as u16;
3457 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3458 bytes.extend_from_slice(&hw1.to_le_bytes());
3459 bytes.extend_from_slice(&hw2.to_le_bytes());
3460
3461 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3465 bytes.extend_from_slice(&mov0.to_le_bytes());
3466
3467 Ok(bytes)
3468 }
3469
3470 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3486 let rd_bits = reg_to_bits(rd);
3487 let rn_lo_bits = reg_to_bits(rnlo);
3488 let rn_hi_bits = reg_to_bits(rnhi);
3489 let mut bytes = Vec::new();
3490
3491 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3493 let hw2: u16 = 0x0F00;
3494 bytes.extend_from_slice(&hw1.to_le_bytes());
3495 bytes.extend_from_slice(&hw2.to_le_bytes());
3496
3497 let beq: u16 = 0xD005;
3500 bytes.extend_from_slice(&beq.to_le_bytes());
3501
3502 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3505 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3506 bytes.extend_from_slice(&hw1.to_le_bytes());
3507 bytes.extend_from_slice(&hw2.to_le_bytes());
3508
3509 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3512 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3513 bytes.extend_from_slice(&hw1.to_le_bytes());
3514 bytes.extend_from_slice(&hw2.to_le_bytes());
3515
3516 let b_done: u16 = 0xE006;
3519 bytes.extend_from_slice(&b_done.to_le_bytes());
3520
3521 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3523
3524 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3528 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3529 bytes.extend_from_slice(&hw1.to_le_bytes());
3530 bytes.extend_from_slice(&hw2.to_le_bytes());
3531
3532 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3535 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3536 bytes.extend_from_slice(&hw1.to_le_bytes());
3537 bytes.extend_from_slice(&hw2.to_le_bytes());
3538
3539 let hw1: u16 = (0xF100 | rd_bits) as u16;
3541 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3542 bytes.extend_from_slice(&hw1.to_le_bytes());
3543 bytes.extend_from_slice(&hw2.to_le_bytes());
3544
3545 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3548 bytes.extend_from_slice(&mov0.to_le_bytes());
3549
3550 Ok(bytes)
3551 }
3552
3553 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3557 let rd_bits = reg_to_bits(rd);
3558 let rn_lo_bits = reg_to_bits(rnlo);
3559 let rn_hi_bits = reg_to_bits(rnhi);
3560 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3563
3564 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3566
3567 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3577 bytes.extend_from_slice(&mov.to_le_bytes());
3578
3579 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3582 bytes.extend_from_slice(&mov.to_le_bytes());
3583
3584 let hw1: u16 = 0xEA4F;
3588 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3589 bytes.extend_from_slice(&hw1.to_le_bytes());
3590 bytes.extend_from_slice(&hw2.to_le_bytes());
3591
3592 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3595 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3596 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3598 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3599
3600 let hw1: u16 = (0xEA00 | r12) as u16;
3602 let hw2: u16 = ((r12 << 8) | r3) as u16;
3603 bytes.extend_from_slice(&hw1.to_le_bytes());
3604 bytes.extend_from_slice(&hw2.to_le_bytes());
3605
3606 let hw1: u16 = (0xEBA0 | 4) as u16;
3608 let hw2: u16 = ((4 << 8) | r12) as u16;
3609 bytes.extend_from_slice(&hw1.to_le_bytes());
3610 bytes.extend_from_slice(&hw2.to_le_bytes());
3611
3612 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3616 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3617 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3619 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3620
3621 let hw1: u16 = (0xEA00 | 4) as u16;
3623 let hw2: u16 = ((r12 << 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 = 0xEA4F;
3629 let hw2: u16 = ((4 << 8) | 0x90 | 4) 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 = (0xEA00 | 4) as u16;
3635 let hw2: u16 = ((4 << 8) | r3) as u16;
3636 bytes.extend_from_slice(&hw1.to_le_bytes());
3637 bytes.extend_from_slice(&hw2.to_le_bytes());
3638
3639 let hw1: u16 = (0xEB00 | 4) as u16;
3641 let hw2: u16 = ((4 << 8) | r12) as u16;
3642 bytes.extend_from_slice(&hw1.to_le_bytes());
3643 bytes.extend_from_slice(&hw2.to_le_bytes());
3644
3645 let hw1: u16 = 0xEA4F;
3650 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3651 bytes.extend_from_slice(&hw1.to_le_bytes());
3652 bytes.extend_from_slice(&hw2.to_le_bytes());
3653
3654 let hw1: u16 = (0xEB00 | 4) as u16;
3656 let hw2: u16 = ((4 << 8) | r12) as u16;
3657 bytes.extend_from_slice(&hw1.to_le_bytes());
3658 bytes.extend_from_slice(&hw2.to_le_bytes());
3659
3660 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3665 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3666 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3668 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3669
3670 let hw1: u16 = (0xEA00 | 4) as u16;
3672 let hw2: u16 = ((4 << 8) | r3) as u16;
3673 bytes.extend_from_slice(&hw1.to_le_bytes());
3674 bytes.extend_from_slice(&hw2.to_le_bytes());
3675
3676 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3680 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3681 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3683 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3684
3685 let hw1: u16 = (0xFB00 | 4) as u16;
3688 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3689 bytes.extend_from_slice(&hw1.to_le_bytes());
3690 bytes.extend_from_slice(&hw2.to_le_bytes());
3691
3692 let hw1: u16 = 0xEA4F;
3695 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3696 bytes.extend_from_slice(&hw1.to_le_bytes());
3697 bytes.extend_from_slice(&hw2.to_le_bytes());
3698
3699 let hw1: u16 = 0xEA4F;
3702 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3703 bytes.extend_from_slice(&hw1.to_le_bytes());
3704 bytes.extend_from_slice(&hw2.to_le_bytes());
3705
3706 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3708 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3709 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3710 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3711
3712 let hw1: u16 = (0xEA00 | r12) as u16;
3713 let hw2: u16 = ((r12 << 8) | r3) as u16;
3714 bytes.extend_from_slice(&hw1.to_le_bytes());
3715 bytes.extend_from_slice(&hw2.to_le_bytes());
3716
3717 let hw1: u16 = (0xEBA0 | 5) as u16;
3718 let hw2: u16 = ((5 << 8) | r12) as u16;
3719 bytes.extend_from_slice(&hw1.to_le_bytes());
3720 bytes.extend_from_slice(&hw2.to_le_bytes());
3721
3722 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3724 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3725 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3726 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3727
3728 let hw1: u16 = (0xEA00 | 5) as u16;
3729 let hw2: u16 = ((r12 << 8) | r3) as u16;
3730 bytes.extend_from_slice(&hw1.to_le_bytes());
3731 bytes.extend_from_slice(&hw2.to_le_bytes());
3732
3733 let hw1: u16 = 0xEA4F;
3734 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3735 bytes.extend_from_slice(&hw1.to_le_bytes());
3736 bytes.extend_from_slice(&hw2.to_le_bytes());
3737
3738 let hw1: u16 = (0xEA00 | 5) as u16;
3739 let hw2: u16 = ((5 << 8) | r3) 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 let hw1: u16 = 0xEA4F;
3751 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3752 bytes.extend_from_slice(&hw1.to_le_bytes());
3753 bytes.extend_from_slice(&hw2.to_le_bytes());
3754
3755 let hw1: u16 = (0xEB00 | 5) as u16;
3756 let hw2: u16 = ((5 << 8) | r12) as u16;
3757 bytes.extend_from_slice(&hw1.to_le_bytes());
3758 bytes.extend_from_slice(&hw2.to_le_bytes());
3759
3760 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3762 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3763 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3764 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3765
3766 let hw1: u16 = (0xEA00 | 5) as u16;
3767 let hw2: u16 = ((5 << 8) | r3) as u16;
3768 bytes.extend_from_slice(&hw1.to_le_bytes());
3769 bytes.extend_from_slice(&hw2.to_le_bytes());
3770
3771 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3773 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3774 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3775 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3776
3777 let hw1: u16 = (0xFB00 | 5) as u16;
3780 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3781 bytes.extend_from_slice(&hw1.to_le_bytes());
3782 bytes.extend_from_slice(&hw2.to_le_bytes());
3783
3784 let hw1: u16 = 0xEA4F;
3787 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3788 bytes.extend_from_slice(&hw1.to_le_bytes());
3789 bytes.extend_from_slice(&hw2.to_le_bytes());
3790
3791 let rd_bits_u16 = rd_bits as u16;
3794 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3795 bytes.extend_from_slice(&instr.to_le_bytes());
3796
3797 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3799
3800 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3802 bytes.extend_from_slice(&mov0.to_le_bytes());
3803
3804 Ok(bytes)
3805 }
3806
3807 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3810 let rdlo_bits = reg_to_bits(rdlo);
3811 let rdhi_bits = reg_to_bits(rdhi);
3812 let rnlo_bits = reg_to_bits(rnlo);
3813 let mut bytes = Vec::new();
3814
3815 let hw1: u16 = 0xFA4F_u16;
3818 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3819 bytes.extend_from_slice(&hw1.to_le_bytes());
3820 bytes.extend_from_slice(&hw2.to_le_bytes());
3821
3822 let hw1: u16 = 0xEA4F;
3827 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3828 bytes.extend_from_slice(&hw1.to_le_bytes());
3829 bytes.extend_from_slice(&hw2.to_le_bytes());
3830
3831 Ok(bytes)
3832 }
3833
3834 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3837 let rdlo_bits = reg_to_bits(rdlo);
3838 let rdhi_bits = reg_to_bits(rdhi);
3839 let rnlo_bits = reg_to_bits(rnlo);
3840 let mut bytes = Vec::new();
3841
3842 let hw1: u16 = 0xFA0F_u16;
3845 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3846 bytes.extend_from_slice(&hw1.to_le_bytes());
3847 bytes.extend_from_slice(&hw2.to_le_bytes());
3848
3849 let hw1: u16 = 0xEA4F;
3851 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3852 bytes.extend_from_slice(&hw1.to_le_bytes());
3853 bytes.extend_from_slice(&hw2.to_le_bytes());
3854
3855 Ok(bytes)
3856 }
3857
3858 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
3861 let rdlo_bits = reg_to_bits(rdlo);
3862 let rdhi_bits = reg_to_bits(rdhi);
3863 let rnlo_bits = reg_to_bits(rnlo);
3864 let mut bytes = Vec::new();
3865
3866 if rdlo_bits != rnlo_bits {
3868 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
3870 let mov: u16 = 0x4600
3871 | (d_bit << 7)
3872 | ((rnlo_bits as u16) << 3)
3873 | ((rdlo_bits & 0x7) as u16);
3874 bytes.extend_from_slice(&mov.to_le_bytes());
3875 }
3876
3877 let hw1: u16 = 0xEA4F;
3879 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
3880 bytes.extend_from_slice(&hw1.to_le_bytes());
3881 bytes.extend_from_slice(&hw2.to_le_bytes());
3882
3883 Ok(bytes)
3884 }
3885
3886 ArmOp::SelectMove { rd, rm, cond } => {
3889 let rd_bits = reg_to_bits(rd) as u16;
3890 let rm_bits = reg_to_bits(rm) as u16;
3891
3892 use synth_synthesis::Condition;
3894 let cond_bits: u16 = match cond {
3895 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, };
3906
3907 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
3910
3911 let d_bit = (rd_bits >> 3) & 1;
3914 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3915
3916 let mut bytes = it_instr.to_le_bytes().to_vec();
3918 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3919 Ok(bytes)
3920 }
3921
3922 ArmOp::Popcnt { rd, rm } => {
3933 let mut bytes = Vec::new();
3934
3935 if rd != rm {
3937 let rd_bits = reg_to_bits(rd) as u16;
3938 let rm_bits = reg_to_bits(rm) as u16;
3939 let d_bit = (rd_bits >> 3) & 1;
3941 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3942 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3943 }
3944
3945 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
3948 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
3949
3950 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
3953
3954 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
3956
3957 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
3959 reg_to_bits(rd),
3960 reg_to_bits(rd),
3961 11,
3962 )?);
3963
3964 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
3967 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
3968
3969 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
3971 11,
3972 reg_to_bits(rd),
3973 12,
3974 )?);
3975
3976 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
3978 reg_to_bits(rd),
3979 reg_to_bits(rd),
3980 2,
3981 )?);
3982
3983 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
3985 reg_to_bits(rd),
3986 reg_to_bits(rd),
3987 12,
3988 )?);
3989
3990 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
3992 reg_to_bits(rd),
3993 reg_to_bits(rd),
3994 11,
3995 )?);
3996
3997 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4000
4001 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4003 reg_to_bits(rd),
4004 reg_to_bits(rd),
4005 11,
4006 )?);
4007
4008 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4010 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4011
4012 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4014 reg_to_bits(rd),
4015 reg_to_bits(rd),
4016 12,
4017 )?);
4018
4019 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4022
4023 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4025 reg_to_bits(rd),
4026 reg_to_bits(rd),
4027 11,
4028 )?);
4029
4030 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4033
4034 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4036 reg_to_bits(rd),
4037 reg_to_bits(rd),
4038 11,
4039 )?);
4040
4041 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4044 reg_to_bits(rd),
4045 reg_to_bits(rd),
4046 0x3F,
4047 )?);
4048
4049 Ok(bytes)
4050 }
4051
4052 ArmOp::I64DivU {
4057 rdlo: _,
4058 rdhi: _,
4059 rnlo: _,
4060 rnhi: _,
4061 rmlo: _,
4062 rmhi: _,
4063 } => {
4064 let mut bytes = Vec::new();
4065
4066 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4070
4071 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());
4082 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4083
4084 let loop_start = bytes.len();
4086
4087 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4098 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());
4107 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4108 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4112 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4113
4114 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4119 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4120 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());
4151 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4152 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4155
4156 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4160 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4161
4162 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4165 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4166 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4167
4168 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4176
4177 Ok(bytes)
4178 }
4179
4180 ArmOp::I64DivS {
4185 rdlo: _,
4186 rdhi: _,
4187 rnlo: _,
4188 rnhi: _,
4189 rmlo: _,
4190 rmhi: _,
4191 } => {
4192 let mut bytes = Vec::new();
4193
4194 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4196 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4197
4198 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4201 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4202
4203 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());
4216
4217 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());
4227
4228 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4231 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4232 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4234 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4235 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4237 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4238
4239 let loop_start = bytes.len();
4240
4241 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4245 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());
4251 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4254
4255 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4259 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());
4272 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4274
4275 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4278
4279 let branch_offset_bytes = bytes.len() - loop_start + 4;
4280 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4281 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4282 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4283
4284 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());
4291 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());
4299
4300 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4302 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4303
4304 Ok(bytes)
4305 }
4306
4307 ArmOp::I64RemU {
4312 rdlo: _,
4313 rdhi: _,
4314 rnlo: _,
4315 rnhi: _,
4316 rmlo: _,
4317 rmhi: _,
4318 } => {
4319 let mut bytes = Vec::new();
4320
4321 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4323 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4324
4325 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4327 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4328 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4330 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4331 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4333 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4334
4335 let loop_start = bytes.len();
4336
4337 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4341 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());
4347 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4350
4351 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4355 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());
4368 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4370
4371 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4374
4375 let branch_offset_bytes = bytes.len() - loop_start + 4;
4376 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4377 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4378 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4379
4380 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4386 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4387
4388 Ok(bytes)
4389 }
4390
4391 ArmOp::I64RemS {
4396 rdlo: _,
4397 rdhi: _,
4398 rnlo: _,
4399 rnhi: _,
4400 rmlo: _,
4401 rmhi: _,
4402 } => {
4403 let mut bytes = Vec::new();
4404
4405 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4407 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4408
4409 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());
4423
4424 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());
4434
4435 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4438 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4439 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4441 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4442 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4444 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4445
4446 let loop_start = bytes.len();
4447
4448 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4452 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());
4458 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4461
4462 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4466 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());
4479 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4481
4482 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4485
4486 let branch_offset_bytes = bytes.len() - loop_start + 4;
4487 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4488 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4489 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4490
4491 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());
4498 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());
4506
4507 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4509 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4510
4511 Ok(bytes)
4512 }
4513
4514 ArmOp::F32Add { sd, sn, sm } => {
4517 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4518 }
4519 ArmOp::F32Sub { sd, sn, sm } => {
4520 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4521 }
4522 ArmOp::F32Mul { sd, sn, sm } => {
4523 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4524 }
4525 ArmOp::F32Div { sd, sn, sm } => {
4526 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4527 }
4528 ArmOp::F32Abs { sd, sm } => {
4529 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4530 }
4531 ArmOp::F32Neg { sd, sm } => {
4532 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4533 }
4534 ArmOp::F32Sqrt { sd, sm } => {
4535 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4536 }
4537
4538 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4541 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4542 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4543 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4544 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4545 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4546 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4547
4548 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4550 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4551 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4552 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4553 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4554 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4555
4556 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4557
4558 ArmOp::F32Load { sd, addr } => {
4559 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4560 }
4561 ArmOp::F32Store { sd, addr } => {
4562 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4563 }
4564
4565 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4566 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4567 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4568 Err(synth_core::Error::synthesis(
4569 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4570 ))
4571 }
4572 ArmOp::F32ReinterpretI32 { sd, rm } => {
4573 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4574 }
4575 ArmOp::I32ReinterpretF32 { rd, sm } => {
4576 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4577 }
4578 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4579 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4580
4581 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4584 0xEE300B00, dd, dn, dm,
4585 )?)),
4586 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4587 0xEE300B40, dd, dn, dm,
4588 )?)),
4589 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4590 0xEE200B00, dd, dn, dm,
4591 )?)),
4592 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4593 0xEE800B00, dd, dn, dm,
4594 )?)),
4595 ArmOp::F64Abs { dd, dm } => {
4596 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4597 }
4598 ArmOp::F64Neg { dd, dm } => {
4599 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4600 }
4601 ArmOp::F64Sqrt { dd, dm } => {
4602 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4603 }
4604
4605 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4608 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4609 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4610 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4611 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4612 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4613 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4614
4615 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4617 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4618 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4619 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4620 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4621 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4622
4623 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4624
4625 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4626 0xED900B00, dd, addr,
4627 )?)),
4628 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4629 0xED800B00, dd, addr,
4630 )?)),
4631
4632 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4633 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4634 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4635 Err(synth_core::Error::synthesis(
4636 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4637 ))
4638 }
4639 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4640 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4641 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4642 )),
4643 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4644 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4645 )),
4646 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4647 Err(synth_core::Error::synthesis(
4648 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4649 ))
4650 }
4651 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4652 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4653
4654 ArmOp::I64Add {
4658 rdlo,
4659 rdhi,
4660 rnlo,
4661 rnhi,
4662 rmlo,
4663 rmhi,
4664 } => {
4665 let mut bytes = Vec::new();
4666 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4668 rd: *rdlo,
4669 rn: *rnlo,
4670 op2: Operand2::Reg(*rmlo),
4671 })?);
4672 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4674 rd: *rdhi,
4675 rn: *rnhi,
4676 op2: Operand2::Reg(*rmhi),
4677 })?);
4678 Ok(bytes)
4679 }
4680
4681 ArmOp::I64Sub {
4683 rdlo,
4684 rdhi,
4685 rnlo,
4686 rnhi,
4687 rmlo,
4688 rmhi,
4689 } => {
4690 let mut bytes = Vec::new();
4691 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4693 rd: *rdlo,
4694 rn: *rnlo,
4695 op2: Operand2::Reg(*rmlo),
4696 })?);
4697 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4699 rd: *rdhi,
4700 rn: *rnhi,
4701 op2: Operand2::Reg(*rmhi),
4702 })?);
4703 Ok(bytes)
4704 }
4705
4706 ArmOp::I64And {
4708 rdlo,
4709 rdhi,
4710 rnlo,
4711 rnhi,
4712 rmlo,
4713 rmhi,
4714 } => {
4715 let mut bytes = Vec::new();
4716 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4717 rd: *rdlo,
4718 rn: *rnlo,
4719 op2: Operand2::Reg(*rmlo),
4720 })?);
4721 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4722 rd: *rdhi,
4723 rn: *rnhi,
4724 op2: Operand2::Reg(*rmhi),
4725 })?);
4726 Ok(bytes)
4727 }
4728
4729 ArmOp::I64Or {
4731 rdlo,
4732 rdhi,
4733 rnlo,
4734 rnhi,
4735 rmlo,
4736 rmhi,
4737 } => {
4738 let mut bytes = Vec::new();
4739 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4740 rd: *rdlo,
4741 rn: *rnlo,
4742 op2: Operand2::Reg(*rmlo),
4743 })?);
4744 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4745 rd: *rdhi,
4746 rn: *rnhi,
4747 op2: Operand2::Reg(*rmhi),
4748 })?);
4749 Ok(bytes)
4750 }
4751
4752 ArmOp::I64Xor {
4754 rdlo,
4755 rdhi,
4756 rnlo,
4757 rnhi,
4758 rmlo,
4759 rmhi,
4760 } => {
4761 let mut bytes = Vec::new();
4762 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4763 rd: *rdlo,
4764 rn: *rnlo,
4765 op2: Operand2::Reg(*rmlo),
4766 })?);
4767 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4768 rd: *rdhi,
4769 rn: *rnhi,
4770 op2: Operand2::Reg(*rmhi),
4771 })?);
4772 Ok(bytes)
4773 }
4774
4775 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4777 rd: *rd,
4778 rn_lo: *rnlo,
4779 rn_hi: *rnhi,
4780 }),
4781
4782 ArmOp::I64Eq {
4784 rd,
4785 rnlo,
4786 rnhi,
4787 rmlo,
4788 rmhi,
4789 } => self.encode_thumb(&ArmOp::I64SetCond {
4790 rd: *rd,
4791 rn_lo: *rnlo,
4792 rn_hi: *rnhi,
4793 rm_lo: *rmlo,
4794 rm_hi: *rmhi,
4795 cond: synth_synthesis::Condition::EQ,
4796 }),
4797
4798 ArmOp::I64Ne {
4799 rd,
4800 rnlo,
4801 rnhi,
4802 rmlo,
4803 rmhi,
4804 } => self.encode_thumb(&ArmOp::I64SetCond {
4805 rd: *rd,
4806 rn_lo: *rnlo,
4807 rn_hi: *rnhi,
4808 rm_lo: *rmlo,
4809 rm_hi: *rmhi,
4810 cond: synth_synthesis::Condition::NE,
4811 }),
4812
4813 ArmOp::I64LtS {
4814 rd,
4815 rnlo,
4816 rnhi,
4817 rmlo,
4818 rmhi,
4819 } => self.encode_thumb(&ArmOp::I64SetCond {
4820 rd: *rd,
4821 rn_lo: *rnlo,
4822 rn_hi: *rnhi,
4823 rm_lo: *rmlo,
4824 rm_hi: *rmhi,
4825 cond: synth_synthesis::Condition::LT,
4826 }),
4827
4828 ArmOp::I64LtU {
4829 rd,
4830 rnlo,
4831 rnhi,
4832 rmlo,
4833 rmhi,
4834 } => self.encode_thumb(&ArmOp::I64SetCond {
4835 rd: *rd,
4836 rn_lo: *rnlo,
4837 rn_hi: *rnhi,
4838 rm_lo: *rmlo,
4839 rm_hi: *rmhi,
4840 cond: synth_synthesis::Condition::LO,
4841 }),
4842
4843 ArmOp::I64LeS {
4844 rd,
4845 rnlo,
4846 rnhi,
4847 rmlo,
4848 rmhi,
4849 } => self.encode_thumb(&ArmOp::I64SetCond {
4850 rd: *rd,
4851 rn_lo: *rnlo,
4852 rn_hi: *rnhi,
4853 rm_lo: *rmlo,
4854 rm_hi: *rmhi,
4855 cond: synth_synthesis::Condition::LE,
4856 }),
4857
4858 ArmOp::I64LeU {
4859 rd,
4860 rnlo,
4861 rnhi,
4862 rmlo,
4863 rmhi,
4864 } => self.encode_thumb(&ArmOp::I64SetCond {
4865 rd: *rd,
4866 rn_lo: *rnlo,
4867 rn_hi: *rnhi,
4868 rm_lo: *rmlo,
4869 rm_hi: *rmhi,
4870 cond: synth_synthesis::Condition::LS,
4871 }),
4872
4873 ArmOp::I64GtS {
4874 rd,
4875 rnlo,
4876 rnhi,
4877 rmlo,
4878 rmhi,
4879 } => self.encode_thumb(&ArmOp::I64SetCond {
4880 rd: *rd,
4881 rn_lo: *rnlo,
4882 rn_hi: *rnhi,
4883 rm_lo: *rmlo,
4884 rm_hi: *rmhi,
4885 cond: synth_synthesis::Condition::GT,
4886 }),
4887
4888 ArmOp::I64GtU {
4889 rd,
4890 rnlo,
4891 rnhi,
4892 rmlo,
4893 rmhi,
4894 } => self.encode_thumb(&ArmOp::I64SetCond {
4895 rd: *rd,
4896 rn_lo: *rnlo,
4897 rn_hi: *rnhi,
4898 rm_lo: *rmlo,
4899 rm_hi: *rmhi,
4900 cond: synth_synthesis::Condition::HI,
4901 }),
4902
4903 ArmOp::I64GeS {
4904 rd,
4905 rnlo,
4906 rnhi,
4907 rmlo,
4908 rmhi,
4909 } => self.encode_thumb(&ArmOp::I64SetCond {
4910 rd: *rd,
4911 rn_lo: *rnlo,
4912 rn_hi: *rnhi,
4913 rm_lo: *rmlo,
4914 rm_hi: *rmhi,
4915 cond: synth_synthesis::Condition::GE,
4916 }),
4917
4918 ArmOp::I64GeU {
4919 rd,
4920 rnlo,
4921 rnhi,
4922 rmlo,
4923 rmhi,
4924 } => self.encode_thumb(&ArmOp::I64SetCond {
4925 rd: *rd,
4926 rn_lo: *rnlo,
4927 rn_hi: *rnhi,
4928 rm_lo: *rmlo,
4929 rm_hi: *rmhi,
4930 cond: synth_synthesis::Condition::HS,
4931 }),
4932
4933 ArmOp::I64Const { rdlo, rdhi, value } => {
4935 let lo32 = *value as u32;
4936 let hi32 = (*value >> 32) as u32;
4937 let mut bytes = Vec::new();
4938 bytes.extend_from_slice(
4940 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
4941 );
4942 if lo32 > 0xFFFF {
4943 bytes.extend_from_slice(
4944 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
4945 );
4946 }
4947 bytes.extend_from_slice(
4949 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
4950 );
4951 if hi32 > 0xFFFF {
4952 bytes.extend_from_slice(
4953 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
4954 );
4955 }
4956 Ok(bytes)
4957 }
4958
4959 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
4961 let mut bytes = Vec::new();
4962 let offset = if addr.offset < 0 {
4963 0u32
4964 } else {
4965 addr.offset as u32
4966 };
4967 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
4968 bytes.extend_from_slice(&self.encode_thumb32_ldr(
4969 rdhi,
4970 &addr.base,
4971 offset.wrapping_add(4),
4972 )?);
4973 Ok(bytes)
4974 }
4975
4976 ArmOp::I64Str { rdlo, rdhi, addr } => {
4978 let mut bytes = Vec::new();
4979 let offset = if addr.offset < 0 {
4980 0u32
4981 } else {
4982 addr.offset as u32
4983 };
4984 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
4985 bytes.extend_from_slice(&self.encode_thumb32_str(
4986 rdhi,
4987 &addr.base,
4988 offset.wrapping_add(4),
4989 )?);
4990 Ok(bytes)
4991 }
4992
4993 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
4995 let mut bytes = Vec::new();
4996 if rdlo != rn {
4997 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
4999 rd: *rdlo,
5000 op2: Operand2::Reg(*rn),
5001 })?);
5002 }
5003 bytes.extend_from_slice(
5005 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5007 Ok(bytes)
5008 }
5009
5010 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5012 let mut bytes = Vec::new();
5013 if rdlo != rn {
5014 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5016 rd: *rdlo,
5017 op2: Operand2::Reg(*rn),
5018 })?);
5019 }
5020 let rdhi_bits = reg_to_bits(rdhi) as u16;
5022 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5023 bytes.extend_from_slice(&instr.to_le_bytes());
5024 Ok(bytes)
5025 }
5026
5027 ArmOp::I32WrapI64 { rd, rnlo } => {
5029 if rd == rnlo {
5030 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5033 } else {
5034 self.encode_thumb(&ArmOp::Mov {
5036 rd: *rd,
5037 op2: Operand2::Reg(*rnlo),
5038 })
5039 }
5040 }
5041
5042 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5044 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5045 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5046 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5047 0xEF000150, qd, qn, qm,
5048 ))),
5049 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5050 0xEF200150, qd, qn, qm,
5051 ))),
5052 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5053 0xFF000150, qd, qn, qm,
5054 ))),
5055 ArmOp::MveMvn { qd, qm } => {
5056 let qd_enc = qreg_to_num(qd);
5058 let qm_enc = qreg_to_num(qm);
5059 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5060 Ok(vfp_to_thumb_bytes(instr))
5061 }
5062 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5063 0xEF100150, qd, qn, qm,
5064 ))),
5065 ArmOp::MveAddI { qd, qn, qm, size } => {
5066 let sz = mve_size_bits(size);
5067 let base: u32 = 0xEF000840 | (sz << 20);
5068 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5069 }
5070 ArmOp::MveSubI { qd, qn, qm, size } => {
5071 let sz = mve_size_bits(size);
5072 let base: u32 = 0xFF000840 | (sz << 20);
5073 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5074 }
5075 ArmOp::MveMulI { qd, qn, qm, size } => {
5076 let sz = mve_size_bits(size);
5077 let base: u32 = 0xEF000950 | (sz << 20);
5078 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5079 }
5080 ArmOp::MveNegI { qd, qm, size } => {
5081 let sz = mve_size_bits(size);
5082 let qd_enc = qreg_to_num(qd);
5084 let qm_enc = qreg_to_num(qm);
5085 let base: u32 = 0xFFB103C0 | (sz << 18);
5086 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5087 Ok(vfp_to_thumb_bytes(instr))
5088 }
5089 ArmOp::MveDup { qd, rn, size } => {
5090 let sz = mve_size_bits(size);
5091 let qd_enc = qreg_to_num(qd);
5092 let rn_bits = reg_to_bits(rn);
5093 let be = match sz {
5096 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5100 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5101 Ok(vfp_to_thumb_bytes(instr))
5102 }
5103 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5104 let qn_enc = qreg_to_num(qn);
5105 let rd_bits = reg_to_bits(rd);
5106 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5109 let lane_in_d = (*lane as u32) & 1;
5110 let _sz = mve_size_bits(size);
5111 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5113 Ok(vfp_to_thumb_bytes(instr))
5114 }
5115 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5116 let qd_enc = qreg_to_num(qd);
5117 let rn_bits = reg_to_bits(rn);
5118 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5119 let lane_in_d = (*lane as u32) & 1;
5120 let _sz = mve_size_bits(size);
5121 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5123 Ok(vfp_to_thumb_bytes(instr))
5124 }
5125
5126 ArmOp::MveCmpEqI { qd, qn, qm, size }
5128 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5129 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5130 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5131 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5132 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5133 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5134 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5135 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5136 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5137 let sz = mve_size_bits(size);
5140 let base: u32 = 0xEF000840 | (sz << 20);
5141 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5142 }
5143
5144 ArmOp::MveAddF32 { qd, qn, qm } => {
5146 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5148 }
5149 ArmOp::MveSubF32 { qd, qn, qm } => {
5150 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5152 }
5153 ArmOp::MveMulF32 { qd, qn, qm } => {
5154 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5156 }
5157 ArmOp::MveNegF32 { qd, qm } => {
5158 let qd_enc = qreg_to_num(qd);
5159 let qm_enc = qreg_to_num(qm);
5160 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5162 Ok(vfp_to_thumb_bytes(instr))
5163 }
5164 ArmOp::MveAbsF32 { qd, qm } => {
5165 let qd_enc = qreg_to_num(qd);
5166 let qm_enc = qreg_to_num(qm);
5167 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5169 Ok(vfp_to_thumb_bytes(instr))
5170 }
5171 ArmOp::MveCmpEqF32 { qd, qn, qm }
5172 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5173 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5174 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5175 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5176 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5177 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5179 }
5180 ArmOp::MveDupF32 { qd, rn } => {
5181 let qd_enc = qreg_to_num(qd);
5182 let rn_bits = reg_to_bits(rn);
5183 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5185 Ok(vfp_to_thumb_bytes(instr))
5186 }
5187 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5188 let qn_enc = qreg_to_num(qn);
5189 let rd_bits = reg_to_bits(rd);
5190 let s_num = qn_enc * 4 + (*lane as u32);
5192 let (vn, n) = encode_sreg(s_num);
5193 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5194 Ok(vfp_to_thumb_bytes(instr))
5195 }
5196 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5197 let qd_enc = qreg_to_num(qd);
5198 let rn_bits = reg_to_bits(rn);
5199 let s_num = qd_enc * 4 + (*lane as u32);
5201 let (vn, n) = encode_sreg(s_num);
5202 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5203 Ok(vfp_to_thumb_bytes(instr))
5204 }
5205 ArmOp::MveDivF32 { qd, qn, qm } => {
5206 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5208 }
5209 ArmOp::MveSqrtF32 { qd, qm } => {
5210 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5212 }
5213
5214 _ => {
5216 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5218 }
5219 }
5220 }
5221
5222 fn encode_thumb_f32_compare(
5226 &self,
5227 rd: &Reg,
5228 sn: &VfpReg,
5229 sm: &VfpReg,
5230 cond_code: u32,
5231 ) -> Result<Vec<u8>> {
5232 let mut bytes = Vec::new();
5233 let rd_bits = reg_to_bits(rd);
5234
5235 let sn_num = vfp_sreg_to_num(sn)?;
5237 let sm_num = vfp_sreg_to_num(sm)?;
5238 let (vd, d) = encode_sreg(sn_num);
5239 let (vm, m) = encode_sreg(sm_num);
5240 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5241 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5242
5243 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5245
5246 if rd_bits < 8 {
5248 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5249 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5250 } else {
5251 let hw1: u16 = 0xF04F;
5253 let hw2: u16 = (rd_bits as u16) << 8;
5254 bytes.extend_from_slice(&hw1.to_le_bytes());
5255 bytes.extend_from_slice(&hw2.to_le_bytes());
5256 }
5257
5258 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5262 bytes.extend_from_slice(&it.to_le_bytes());
5263
5264 if rd_bits < 8 {
5266 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5267 bytes.extend_from_slice(&mov_one.to_le_bytes());
5268 } else {
5269 let hw1: u16 = 0xF04F;
5271 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5272 bytes.extend_from_slice(&hw1.to_le_bytes());
5273 bytes.extend_from_slice(&hw2.to_le_bytes());
5274 }
5275
5276 Ok(bytes)
5277 }
5278
5279 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5281 let mut bytes = Vec::new();
5282 let bits = value.to_bits();
5283 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5288 let imm4 = (lo16 >> 12) & 0xF;
5289 let i_bit = (lo16 >> 11) & 1;
5290 let imm3 = (lo16 >> 8) & 0x7;
5291 let imm8 = lo16 & 0xFF;
5292 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5293 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5294 bytes.extend_from_slice(&hw1.to_le_bytes());
5295 bytes.extend_from_slice(&hw2.to_le_bytes());
5296
5297 let hi16 = (bits >> 16) & 0xFFFF;
5299 let imm4 = (hi16 >> 12) & 0xF;
5300 let i_bit = (hi16 >> 11) & 1;
5301 let imm3 = (hi16 >> 8) & 0x7;
5302 let imm8 = hi16 & 0xFF;
5303 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5304 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5305 bytes.extend_from_slice(&hw1.to_le_bytes());
5306 bytes.extend_from_slice(&hw2.to_le_bytes());
5307
5308 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5310 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5311
5312 Ok(bytes)
5313 }
5314
5315 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5317 let mut bytes = Vec::new();
5318
5319 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5321 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5322
5323 let sd_num = vfp_sreg_to_num(sd)?;
5325 let (vd, d) = encode_sreg(sd_num);
5326 let (vm, m) = encode_sreg(sd_num);
5327 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5328 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5329 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5330
5331 Ok(bytes)
5332 }
5333
5334 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5342 let mut bytes = Vec::new();
5343 let sm_num = vfp_sreg_to_num(sm)?;
5344 let sd_num = vfp_sreg_to_num(sd)?;
5345 let (vd_s, d_s) = encode_sreg(sd_num);
5346 let (vm_s, m_s) = encode_sreg(sm_num);
5347
5348 if mode == 0b11 {
5349 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5351 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5352 } else {
5353 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5358 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5359
5360 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5366 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5367 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5368
5369 if mode != 0 {
5371 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5373 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5374 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5375 }
5376
5377 let vmsr = 0xEEE10A10 | (rt << 12);
5379 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5380
5381 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5383 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5384
5385 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5387 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5388 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5389 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5390 }
5391
5392 let (vd2, d2) = encode_sreg(sd_num);
5394 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5395 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5396
5397 Ok(bytes)
5398 }
5399
5400 fn encode_thumb_f32_minmax(
5402 &self,
5403 sd: &VfpReg,
5404 sn: &VfpReg,
5405 sm: &VfpReg,
5406 is_min: bool,
5407 ) -> Result<Vec<u8>> {
5408 let mut bytes = Vec::new();
5409 let sn_num = vfp_sreg_to_num(sn)?;
5410 let sm_num = vfp_sreg_to_num(sm)?;
5411 let sd_num = vfp_sreg_to_num(sd)?;
5412
5413 let (vd, d) = encode_sreg(sd_num);
5415 let (vn, n) = encode_sreg(sn_num);
5416 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5417 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5418
5419 let (vm, m) = encode_sreg(sm_num);
5421 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5422 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5423
5424 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5426
5427 let cond: u16 = if is_min { 0xC } else { 0x4 };
5429 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5430 bytes.extend_from_slice(&it.to_le_bytes());
5431
5432 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5434 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5435
5436 Ok(bytes)
5437 }
5438
5439 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5441 let mut bytes = Vec::new();
5442
5443 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5445 false,
5446 sm,
5447 &Reg::R12,
5448 )?));
5449
5450 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5452 false,
5453 sn,
5454 &Reg::R0,
5455 )?));
5456
5457 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5469 bytes.extend_from_slice(&hw2.to_le_bytes());
5470
5471 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5475 bytes.extend_from_slice(&hw2.to_le_bytes());
5476
5477 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5481 bytes.extend_from_slice(&hw2.to_le_bytes());
5482
5483 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5485 true,
5486 sd,
5487 &Reg::R0,
5488 )?));
5489
5490 Ok(bytes)
5491 }
5492
5493 fn encode_thumb_f64_compare(
5495 &self,
5496 rd: &Reg,
5497 dn: &VfpReg,
5498 dm: &VfpReg,
5499 cond_code: u32,
5500 ) -> Result<Vec<u8>> {
5501 let mut bytes = Vec::new();
5502 let rd_bits = reg_to_bits(rd);
5503
5504 let dn_num = vfp_dreg_to_num(dn)?;
5506 let dm_num = vfp_dreg_to_num(dm)?;
5507 let (vd, d) = encode_dreg(dn_num);
5508 let (vm, m) = encode_dreg(dm_num);
5509 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5510 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5511
5512 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5514
5515 if rd_bits < 8 {
5517 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5518 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5519 } else {
5520 let hw1: u16 = 0xF04F;
5521 let hw2: u16 = (rd_bits as u16) << 8;
5522 bytes.extend_from_slice(&hw1.to_le_bytes());
5523 bytes.extend_from_slice(&hw2.to_le_bytes());
5524 }
5525
5526 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5528 bytes.extend_from_slice(&it.to_le_bytes());
5529
5530 if rd_bits < 8 {
5532 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5533 bytes.extend_from_slice(&mov_one.to_le_bytes());
5534 } else {
5535 let hw1: u16 = 0xF04F;
5536 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5537 bytes.extend_from_slice(&hw1.to_le_bytes());
5538 bytes.extend_from_slice(&hw2.to_le_bytes());
5539 }
5540
5541 Ok(bytes)
5542 }
5543
5544 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5546 let mut bytes = Vec::new();
5547 let bits = value.to_bits();
5548 let lo32 = bits as u32;
5549 let hi32 = (bits >> 32) as u32;
5550
5551 let lo16 = lo32 & 0xFFFF;
5553 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5554
5555 let hi16 = (lo32 >> 16) & 0xFFFF;
5557 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5558
5559 let lo16 = hi32 & 0xFFFF;
5561 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5562
5563 let hi16 = (hi32 >> 16) & 0xFFFF;
5565 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5566
5567 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5569 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5570
5571 Ok(bytes)
5572 }
5573
5574 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5576 let mut bytes = Vec::new();
5577
5578 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5580 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5581
5582 let dd_num = vfp_dreg_to_num(dd)?;
5584 let (vd, d) = encode_dreg(dd_num);
5585 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5586 let vcvt = base | (d << 22) | (vd << 12);
5587 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5588
5589 Ok(bytes)
5590 }
5591
5592 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5594 let dd_num = vfp_dreg_to_num(dd)?;
5595 let sm_num = vfp_sreg_to_num(sm)?;
5596 let (vd, d) = encode_dreg(dd_num);
5597 let (vm, m) = encode_sreg(sm_num);
5598
5599 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5600 Ok(vfp_to_thumb_bytes(vcvt))
5601 }
5602
5603 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5605 let mut bytes = Vec::new();
5606 let dm_num = vfp_dreg_to_num(dm)?;
5607 let (vm, m) = encode_dreg(dm_num);
5608
5609 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5611 let vcvt = base | (m << 5) | vm;
5612 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5613
5614 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5616 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5617
5618 Ok(bytes)
5619 }
5620
5621 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5625 let mut bytes = Vec::new();
5626 let dm_num = vfp_dreg_to_num(dm)?;
5627 let dd_num = vfp_dreg_to_num(dd)?;
5628 let (vm, m) = encode_dreg(dm_num);
5629 let (vd, d) = encode_dreg(dd_num);
5630
5631 if mode == 0b11 {
5632 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5634 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5635 } else {
5636 let rt: u32 = 12;
5637
5638 let vmrs = 0xEEF10A10 | (rt << 12);
5640 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5641
5642 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5644 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5645 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5646 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5647
5648 if mode != 0 {
5650 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5651 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5652 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5653 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5654 }
5655
5656 let vmsr = 0xEEE10A10 | (rt << 12);
5658 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5659
5660 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5662 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5663
5664 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5666 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5667 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5668 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5669 }
5670
5671 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5673 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5674
5675 Ok(bytes)
5676 }
5677
5678 fn encode_thumb_f64_minmax(
5680 &self,
5681 dd: &VfpReg,
5682 dn: &VfpReg,
5683 dm: &VfpReg,
5684 is_min: bool,
5685 ) -> Result<Vec<u8>> {
5686 let mut bytes = Vec::new();
5687 let dn_num = vfp_dreg_to_num(dn)?;
5688 let dm_num = vfp_dreg_to_num(dm)?;
5689 let dd_num = vfp_dreg_to_num(dd)?;
5690
5691 let (vd, d) = encode_dreg(dd_num);
5693 let (vn, n) = encode_dreg(dn_num);
5694 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5695 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5696
5697 let (vm, m) = encode_dreg(dm_num);
5699 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5700 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5701
5702 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5704
5705 let cond: u16 = if is_min { 0xC } else { 0x4 };
5707 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5708 bytes.extend_from_slice(&it.to_le_bytes());
5709
5710 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5712 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5713
5714 Ok(bytes)
5715 }
5716
5717 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5719 let mut bytes = Vec::new();
5720
5721 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5723 false,
5724 dm,
5725 &Reg::R0,
5726 &Reg::R12,
5727 )?));
5728
5729 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5731 false,
5732 dn,
5733 &Reg::R1,
5734 &Reg::R2,
5735 )?));
5736
5737 let hw1: u16 = 0xF000 | 12;
5739 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5740 bytes.extend_from_slice(&hw1.to_le_bytes());
5741 bytes.extend_from_slice(&hw2.to_le_bytes());
5742
5743 let hw1: u16 = 0xF020 | 2;
5745 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5746 bytes.extend_from_slice(&hw1.to_le_bytes());
5747 bytes.extend_from_slice(&hw2.to_le_bytes());
5748
5749 let hw1: u16 = 0xEA40 | 2;
5751 let hw2: u16 = (2 << 8) | 12;
5752 bytes.extend_from_slice(&hw1.to_le_bytes());
5753 bytes.extend_from_slice(&hw2.to_le_bytes());
5754
5755 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5757 true,
5758 dd,
5759 &Reg::R1,
5760 &Reg::R2,
5761 )?));
5762
5763 Ok(bytes)
5764 }
5765
5766 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5768 let mut bytes = Vec::new();
5769
5770 let sm_num = vfp_sreg_to_num(sm)?;
5771 let (vd, d) = encode_sreg(sm_num);
5772 let (vm, m) = encode_sreg(sm_num);
5773 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5774 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5775 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5776
5777 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5779 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5780
5781 Ok(bytes)
5782 }
5783
5784 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5788 let rd_bits = reg_to_bits(rd);
5789 let rn_bits = reg_to_bits(rn);
5790
5791 let i_bit = (imm >> 11) & 1;
5795 let imm3 = (imm >> 8) & 0x7;
5796 let imm8 = imm & 0xFF;
5797
5798 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5799 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5800
5801 let mut bytes = hw1.to_le_bytes().to_vec();
5802 bytes.extend_from_slice(&hw2.to_le_bytes());
5803 Ok(bytes)
5804 }
5805
5806 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5808 let rd_bits = reg_to_bits(rd);
5809 let rn_bits = reg_to_bits(rn);
5810
5811 let i_bit = (imm >> 11) & 1;
5812 let imm3 = (imm >> 8) & 0x7;
5813 let imm8 = imm & 0xFF;
5814
5815 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5816 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5817
5818 let mut bytes = hw1.to_le_bytes().to_vec();
5819 bytes.extend_from_slice(&hw2.to_le_bytes());
5820 Ok(bytes)
5821 }
5822
5823 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5825 let rd_bits = reg_to_bits(rd);
5826 let rn_bits = reg_to_bits(rn);
5827
5828 let i_bit = (imm >> 11) & 1;
5829 let imm3 = (imm >> 8) & 0x7;
5830 let imm8 = imm & 0xFF;
5831
5832 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5835 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5836
5837 let mut bytes = hw1.to_le_bytes().to_vec();
5838 bytes.extend_from_slice(&hw2.to_le_bytes());
5839 Ok(bytes)
5840 }
5841
5842 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5844 let rd_bits = reg_to_bits(rd);
5845 let rn_bits = reg_to_bits(rn);
5846
5847 let i_bit = (imm >> 11) & 1;
5848 let imm3 = (imm >> 8) & 0x7;
5849 let imm8 = imm & 0xFF;
5850
5851 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5854 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5855
5856 let mut bytes = hw1.to_le_bytes().to_vec();
5857 bytes.extend_from_slice(&hw2.to_le_bytes());
5858 Ok(bytes)
5859 }
5860
5861 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
5870 let rd_bits = reg_to_bits(rd);
5871 encoding_contracts::verify_reg_bits(rd_bits);
5872 let imm16 = imm & 0xFFFF;
5873
5874 let imm4 = (imm16 >> 12) & 0xF;
5877 let i_bit = (imm16 >> 11) & 1;
5878 let imm3 = (imm16 >> 8) & 0x7;
5879 let imm8 = imm16 & 0xFF;
5880
5881 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5882 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5883
5884 let mut bytes = hw1.to_le_bytes().to_vec();
5885 bytes.extend_from_slice(&hw2.to_le_bytes());
5886 encoding_contracts::verify_thumb32(&bytes);
5887 Ok(bytes)
5888 }
5889
5890 fn encode_thumb32_shift(
5898 &self,
5899 rd: &Reg,
5900 rm: &Reg,
5901 shift: u32,
5902 shift_type: u8,
5903 ) -> Result<Vec<u8>> {
5904 let rd_bits = reg_to_bits(rd);
5905 let rm_bits = reg_to_bits(rm);
5906 encoding_contracts::verify_reg_bits(rd_bits);
5907 encoding_contracts::verify_reg_bits(rm_bits);
5908 let imm5 = shift & 0x1F;
5909 let imm2 = imm5 & 0x3;
5910 let imm3 = (imm5 >> 2) & 0x7;
5911
5912 let hw1: u16 = 0xEA4F;
5915 let hw2: u16 =
5916 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
5917 as u16;
5918
5919 let mut bytes = hw1.to_le_bytes().to_vec();
5920 bytes.extend_from_slice(&hw2.to_le_bytes());
5921 Ok(bytes)
5922 }
5923
5924 fn encode_thumb32_shift_reg(
5928 &self,
5929 rd: &Reg,
5930 rn: &Reg,
5931 rm: &Reg,
5932 shift_type: u8,
5933 ) -> Result<Vec<u8>> {
5934 let rd_bits = reg_to_bits(rd);
5935 let rn_bits = reg_to_bits(rn);
5936 let rm_bits = reg_to_bits(rm);
5937
5938 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
5940 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
5942
5943 let mut bytes = hw1.to_le_bytes().to_vec();
5944 bytes.extend_from_slice(&hw2.to_le_bytes());
5945 Ok(bytes)
5946 }
5947
5948 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5950 let rn_bits = reg_to_bits(rn);
5951
5952 let i_bit = (imm >> 11) & 1;
5953 let imm3 = (imm >> 8) & 0x7;
5954 let imm8 = imm & 0xFF;
5955
5956 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5958 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
5959
5960 let mut bytes = hw1.to_le_bytes().to_vec();
5961 bytes.extend_from_slice(&hw2.to_le_bytes());
5962 Ok(bytes)
5963 }
5964
5965 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
5967 let rd_bits = reg_to_bits(rd);
5968 let base_bits = reg_to_bits(base);
5969
5970 let hw1: u16 = (0xF8D0 | base_bits) as u16;
5972 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
5973
5974 let mut bytes = hw1.to_le_bytes().to_vec();
5975 bytes.extend_from_slice(&hw2.to_le_bytes());
5976 Ok(bytes)
5977 }
5978
5979 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
5981 let rd_bits = reg_to_bits(rd);
5982 let base_bits = reg_to_bits(base);
5983
5984 let hw1: u16 = (0xF8C0 | base_bits) as u16;
5986 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
5987
5988 let mut bytes = hw1.to_le_bytes().to_vec();
5989 bytes.extend_from_slice(&hw2.to_le_bytes());
5990 Ok(bytes)
5991 }
5992
5993 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
5995 let rd_bits = reg_to_bits(rd);
5996 let base_bits = reg_to_bits(base);
5997 let rm_bits = reg_to_bits(offset_reg);
5998
5999 let hw1: u16 = (0xF850 | base_bits) as u16;
6003 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6004
6005 let mut bytes = hw1.to_le_bytes().to_vec();
6006 bytes.extend_from_slice(&hw2.to_le_bytes());
6007 Ok(bytes)
6008 }
6009
6010 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6012 let rd_bits = reg_to_bits(rd);
6013 let base_bits = reg_to_bits(base);
6014 let rm_bits = reg_to_bits(offset_reg);
6015
6016 let hw1: u16 = (0xF840 | base_bits) as u16;
6020 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6021
6022 let mut bytes = hw1.to_le_bytes().to_vec();
6023 bytes.extend_from_slice(&hw2.to_le_bytes());
6024 Ok(bytes)
6025 }
6026
6027 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6031 let rd_bits = reg_to_bits(rd);
6032 let base_bits = reg_to_bits(base);
6033 let hw1: u16 = (0xF890 | base_bits) as u16;
6035 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6036 let mut bytes = hw1.to_le_bytes().to_vec();
6037 bytes.extend_from_slice(&hw2.to_le_bytes());
6038 Ok(bytes)
6039 }
6040
6041 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6043 let rd_bits = reg_to_bits(rd);
6044 let base_bits = reg_to_bits(base);
6045 let rm_bits = reg_to_bits(offset_reg);
6046 let hw1: u16 = (0xF810 | base_bits) as u16;
6048 let hw2: u16 = ((rd_bits << 12) | rm_bits) 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_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6056 let rd_bits = reg_to_bits(rd);
6057 let base_bits = reg_to_bits(base);
6058 let hw1: u16 = (0xF990 | base_bits) as u16;
6060 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6061 let mut bytes = hw1.to_le_bytes().to_vec();
6062 bytes.extend_from_slice(&hw2.to_le_bytes());
6063 Ok(bytes)
6064 }
6065
6066 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6068 let rd_bits = reg_to_bits(rd);
6069 let base_bits = reg_to_bits(base);
6070 let rm_bits = reg_to_bits(offset_reg);
6071 let hw1: u16 = (0xF910 | base_bits) as u16;
6073 let hw2: u16 = ((rd_bits << 12) | rm_bits) 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_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6081 let rd_bits = reg_to_bits(rd);
6082 let base_bits = reg_to_bits(base);
6083 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6085 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6086 let mut bytes = hw1.to_le_bytes().to_vec();
6087 bytes.extend_from_slice(&hw2.to_le_bytes());
6088 Ok(bytes)
6089 }
6090
6091 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6093 let rd_bits = reg_to_bits(rd);
6094 let base_bits = reg_to_bits(base);
6095 let rm_bits = reg_to_bits(offset_reg);
6096 let hw1: u16 = (0xF830 | base_bits) as u16;
6098 let hw2: u16 = ((rd_bits << 12) | rm_bits) 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_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6106 let rd_bits = reg_to_bits(rd);
6107 let base_bits = reg_to_bits(base);
6108 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6110 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6111 let mut bytes = hw1.to_le_bytes().to_vec();
6112 bytes.extend_from_slice(&hw2.to_le_bytes());
6113 Ok(bytes)
6114 }
6115
6116 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6118 let rd_bits = reg_to_bits(rd);
6119 let base_bits = reg_to_bits(base);
6120 let rm_bits = reg_to_bits(offset_reg);
6121 let hw1: u16 = (0xF930 | base_bits) as u16;
6123 let hw2: u16 = ((rd_bits << 12) | rm_bits) 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_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6131 let rd_bits = reg_to_bits(rd);
6132 let base_bits = reg_to_bits(base);
6133 let hw1: u16 = (0xF880 | base_bits) as u16;
6135 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6136 let mut bytes = hw1.to_le_bytes().to_vec();
6137 bytes.extend_from_slice(&hw2.to_le_bytes());
6138 Ok(bytes)
6139 }
6140
6141 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6143 let rd_bits = reg_to_bits(rd);
6144 let base_bits = reg_to_bits(base);
6145 let rm_bits = reg_to_bits(offset_reg);
6146 let hw1: u16 = (0xF800 | base_bits) as u16;
6148 let hw2: u16 = ((rd_bits << 12) | rm_bits) 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_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6156 let rd_bits = reg_to_bits(rd);
6157 let base_bits = reg_to_bits(base);
6158 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6160 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6161 let mut bytes = hw1.to_le_bytes().to_vec();
6162 bytes.extend_from_slice(&hw2.to_le_bytes());
6163 Ok(bytes)
6164 }
6165
6166 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6168 let rd_bits = reg_to_bits(rd);
6169 let base_bits = reg_to_bits(base);
6170 let rm_bits = reg_to_bits(offset_reg);
6171 let hw1: u16 = (0xF820 | base_bits) as u16;
6173 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6174 let mut bytes = hw1.to_le_bytes().to_vec();
6175 bytes.extend_from_slice(&hw2.to_le_bytes());
6176 Ok(bytes)
6177 }
6178
6179 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6181 let rd_bits = reg_to_bits(rd);
6182 let rn_bits = reg_to_bits(rn);
6183
6184 if imm <= 0xFFF {
6190 let i_bit = (imm >> 11) & 1;
6191 let imm3 = (imm >> 8) & 0x7;
6192 let imm8 = imm & 0xFF;
6193
6194 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6195 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6196
6197 let mut bytes = hw1.to_le_bytes().to_vec();
6198 bytes.extend_from_slice(&hw2.to_le_bytes());
6199 Ok(bytes)
6200 } else {
6201 Err(synth_core::Error::synthesis(
6204 "ADD immediate too large for single instruction",
6205 ))
6206 }
6207 }
6208
6209 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6219 encoding_contracts::verify_reg_bits(rd);
6220 encoding_contracts::verify_imm16(imm16);
6221 let imm16 = imm16 & 0xFFFF;
6224 let imm4 = (imm16 >> 12) & 0xF;
6225 let i_bit = (imm16 >> 11) & 1;
6226 let imm3 = (imm16 >> 8) & 0x7;
6227 let imm8 = imm16 & 0xFF;
6228
6229 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6230 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6231
6232 let mut bytes = hw1.to_le_bytes().to_vec();
6233 bytes.extend_from_slice(&hw2.to_le_bytes());
6234 encoding_contracts::verify_thumb32(&bytes);
6235 Ok(bytes)
6236 }
6237
6238 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6246 encoding_contracts::verify_reg_bits(rd);
6247 encoding_contracts::verify_imm16(imm16);
6248 let imm16 = imm16 & 0xFFFF;
6251 let imm4 = (imm16 >> 12) & 0xF;
6252 let i_bit = (imm16 >> 11) & 1;
6253 let imm3 = (imm16 >> 8) & 0x7;
6254 let imm8 = imm16 & 0xFF;
6255
6256 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6257 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6258
6259 let mut bytes = hw1.to_le_bytes().to_vec();
6260 bytes.extend_from_slice(&hw2.to_le_bytes());
6261 encoding_contracts::verify_thumb32(&bytes);
6262 Ok(bytes)
6263 }
6264
6265 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6267 let imm5 = shift & 0x1F;
6270 let imm2 = imm5 & 0x3;
6271 let imm3 = (imm5 >> 2) & 0x7;
6272
6273 let hw1: u16 = 0xEA4F;
6274 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | 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_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6283 let hw1: u16 = (0xEA00 | rn) as u16;
6286 let hw2: u16 = ((rd << 8) | rm) as u16;
6287
6288 let mut bytes = hw1.to_le_bytes().to_vec();
6289 bytes.extend_from_slice(&hw2.to_le_bytes());
6290 Ok(bytes)
6291 }
6292
6293 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6295 let i_bit = (imm >> 11) & 1;
6299 let imm3 = (imm >> 8) & 0x7;
6300 let imm8 = imm & 0xFF;
6301
6302 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6303 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) 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_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6312 let hw1: u16 = (0xEBA0 | 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 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6324 let hw1: u16 = (0xEB00 | rn) as u16;
6327 let hw2: u16 = ((rd << 8) | rm) as u16;
6328
6329 let mut bytes = hw1.to_le_bytes().to_vec();
6330 bytes.extend_from_slice(&hw2.to_le_bytes());
6331 Ok(bytes)
6332 }
6333
6334 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6336 let mut code = Vec::new();
6337
6338 for op in ops {
6339 let encoded = self.encode(op)?;
6340 code.extend_from_slice(&encoded);
6341 }
6342
6343 Ok(code)
6344 }
6345}
6346
6347fn reg_to_bits(reg: &Reg) -> u32 {
6349 match reg {
6350 Reg::R0 => 0,
6351 Reg::R1 => 1,
6352 Reg::R2 => 2,
6353 Reg::R3 => 3,
6354 Reg::R4 => 4,
6355 Reg::R5 => 5,
6356 Reg::R6 => 6,
6357 Reg::R7 => 7,
6358 Reg::R8 => 8,
6359 Reg::R9 => 9,
6360 Reg::R10 => 10,
6361 Reg::R11 => 11,
6362 Reg::R12 => 12,
6363 Reg::SP => 13,
6364 Reg::LR => 14,
6365 Reg::PC => 15,
6366 }
6367}
6368
6369fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6372 if val == 0 {
6373 return Some((0, 1));
6374 }
6375 for rot in 0..16u32 {
6376 let shift = rot * 2;
6377 let unrotated = val.rotate_left(shift);
6379 if unrotated <= 0xFF {
6380 return Some(((rot << 8) | unrotated, 1));
6382 }
6383 }
6384 None
6385}
6386
6387fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6392 match op2 {
6393 Operand2::Imm(val) => {
6394 let uval = *val as u32;
6395 if let Some(encoded) = try_encode_rotated_imm(uval) {
6397 encoded
6398 } else {
6399 let imm = uval & 0xFF;
6404 (imm, 1)
6405 }
6406 }
6407
6408 Operand2::Reg(reg) => {
6409 let reg_bits = reg_to_bits(reg);
6410 (reg_bits, 0) }
6412
6413 Operand2::RegShift {
6414 rm,
6415 shift: _,
6416 amount,
6417 } => {
6418 let rm_bits = reg_to_bits(rm);
6420 let shift_bits = (*amount & 0x1F) << 7;
6421 (shift_bits | rm_bits, 0)
6422 }
6423 }
6424}
6425
6426fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6428 let base_bits = reg_to_bits(&addr.base);
6429 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6431}
6432
6433fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6435 match reg {
6436 VfpReg::S0 => Ok(0),
6437 VfpReg::S1 => Ok(1),
6438 VfpReg::S2 => Ok(2),
6439 VfpReg::S3 => Ok(3),
6440 VfpReg::S4 => Ok(4),
6441 VfpReg::S5 => Ok(5),
6442 VfpReg::S6 => Ok(6),
6443 VfpReg::S7 => Ok(7),
6444 VfpReg::S8 => Ok(8),
6445 VfpReg::S9 => Ok(9),
6446 VfpReg::S10 => Ok(10),
6447 VfpReg::S11 => Ok(11),
6448 VfpReg::S12 => Ok(12),
6449 VfpReg::S13 => Ok(13),
6450 VfpReg::S14 => Ok(14),
6451 VfpReg::S15 => Ok(15),
6452 VfpReg::S16 => Ok(16),
6453 VfpReg::S17 => Ok(17),
6454 VfpReg::S18 => Ok(18),
6455 VfpReg::S19 => Ok(19),
6456 VfpReg::S20 => Ok(20),
6457 VfpReg::S21 => Ok(21),
6458 VfpReg::S22 => Ok(22),
6459 VfpReg::S23 => Ok(23),
6460 VfpReg::S24 => Ok(24),
6461 VfpReg::S25 => Ok(25),
6462 VfpReg::S26 => Ok(26),
6463 VfpReg::S27 => Ok(27),
6464 VfpReg::S28 => Ok(28),
6465 VfpReg::S29 => Ok(29),
6466 VfpReg::S30 => Ok(30),
6467 VfpReg::S31 => Ok(31),
6468 _ => Err(synth_core::Error::SynthesisError(
6470 "D-register not supported in single-precision VFP encoding".to_string(),
6471 )),
6472 }
6473}
6474
6475fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6477 match reg {
6478 VfpReg::D0 => Ok(0),
6479 VfpReg::D1 => Ok(1),
6480 VfpReg::D2 => Ok(2),
6481 VfpReg::D3 => Ok(3),
6482 VfpReg::D4 => Ok(4),
6483 VfpReg::D5 => Ok(5),
6484 VfpReg::D6 => Ok(6),
6485 VfpReg::D7 => Ok(7),
6486 VfpReg::D8 => Ok(8),
6487 VfpReg::D9 => Ok(9),
6488 VfpReg::D10 => Ok(10),
6489 VfpReg::D11 => Ok(11),
6490 VfpReg::D12 => Ok(12),
6491 VfpReg::D13 => Ok(13),
6492 VfpReg::D14 => Ok(14),
6493 VfpReg::D15 => Ok(15),
6494 _ => Err(synth_core::Error::SynthesisError(
6496 "S-register not supported in double-precision VFP encoding".to_string(),
6497 )),
6498 }
6499}
6500
6501fn encode_sreg(s: u32) -> (u32, u32) {
6505 (s >> 1, s & 1)
6506}
6507
6508fn encode_dreg(d: u32) -> (u32, u32) {
6512 (d & 0xF, (d >> 4) & 1)
6513}
6514
6515fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6521 let sd_num = vfp_sreg_to_num(sd)?;
6522 let sn_num = vfp_sreg_to_num(sn)?;
6523 let sm_num = vfp_sreg_to_num(sm)?;
6524 let (vd, d) = encode_sreg(sd_num);
6525 let (vn, n) = encode_sreg(sn_num);
6526 let (vm, m) = encode_sreg(sm_num);
6527
6528 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6529}
6530
6531fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6534 let sd_num = vfp_sreg_to_num(sd)?;
6535 let sm_num = vfp_sreg_to_num(sm)?;
6536 let (vd, d) = encode_sreg(sd_num);
6537 let (vm, m) = encode_sreg(sm_num);
6538
6539 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6540}
6541
6542fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6546 let sd_num = vfp_sreg_to_num(sd)?;
6547 let (vd, d) = encode_sreg(sd_num);
6548 let rn = reg_to_bits(&addr.base);
6549
6550 let offset = addr.offset;
6551 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6552 let abs_offset = offset.unsigned_abs();
6553 let imm8 = (abs_offset / 4) & 0xFF;
6554
6555 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6556}
6557
6558fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6562 let s_num = vfp_sreg_to_num(sreg)?;
6563 let (vn, n) = encode_sreg(s_num);
6564 let rt = reg_to_bits(core);
6565
6566 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6567 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6568}
6569
6570fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6574 let dd_num = vfp_dreg_to_num(dd)?;
6575 let dn_num = vfp_dreg_to_num(dn)?;
6576 let dm_num = vfp_dreg_to_num(dm)?;
6577 let (vd, d) = encode_dreg(dd_num);
6578 let (vn, n) = encode_dreg(dn_num);
6579 let (vm, m) = encode_dreg(dm_num);
6580
6581 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6582}
6583
6584fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6586 let dd_num = vfp_dreg_to_num(dd)?;
6587 let dm_num = vfp_dreg_to_num(dm)?;
6588 let (vd, d) = encode_dreg(dd_num);
6589 let (vm, m) = encode_dreg(dm_num);
6590
6591 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6592}
6593
6594fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6597 let dd_num = vfp_dreg_to_num(dd)?;
6598 let (vd, d) = encode_dreg(dd_num);
6599 let rn = reg_to_bits(&addr.base);
6600
6601 let offset = addr.offset;
6602 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6603 let abs_offset = offset.unsigned_abs();
6604 let imm8 = (abs_offset / 4) & 0xFF;
6605
6606 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6607}
6608
6609fn encode_vmov_core_dreg(
6613 to_dreg: bool,
6614 dreg: &VfpReg,
6615 core_lo: &Reg,
6616 core_hi: &Reg,
6617) -> Result<u32> {
6618 let d_num = vfp_dreg_to_num(dreg)?;
6619 let (vm, m) = encode_dreg(d_num);
6620 let rt = reg_to_bits(core_lo);
6621 let rt2 = reg_to_bits(core_hi);
6622
6623 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6624 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6625}
6626
6627fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6629 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6630 let hw2 = (instr & 0xFFFF) as u16;
6631 let mut bytes = hw1.to_le_bytes().to_vec();
6632 bytes.extend_from_slice(&hw2.to_le_bytes());
6633 bytes
6634}
6635
6636fn qreg_to_num(reg: &QReg) -> u32 {
6642 match reg {
6643 QReg::Q0 => 0,
6644 QReg::Q1 => 1,
6645 QReg::Q2 => 2,
6646 QReg::Q3 => 3,
6647 QReg::Q4 => 4,
6648 QReg::Q5 => 5,
6649 QReg::Q6 => 6,
6650 QReg::Q7 => 7,
6651 }
6652}
6653
6654fn mve_size_bits(size: &MveSize) -> u32 {
6656 match size {
6657 MveSize::S8 => 0b00,
6658 MveSize::S16 => 0b01,
6659 MveSize::S32 => 0b10,
6660 }
6661}
6662
6663fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6667 let d = qreg_to_num(qd) * 2;
6668 let n = qreg_to_num(qn) * 2;
6669 let m = qreg_to_num(qm) * 2;
6670
6671 let vd = d & 0xF;
6676 let d_bit = (d >> 4) & 1;
6677 let vn = n & 0xF;
6678 let n_bit = (n >> 4) & 1;
6679 let vm = m & 0xF;
6680 let m_bit = (m >> 4) & 1;
6681
6682 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6683}
6684
6685fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6687 encode_mve_3reg(base, qd, qn, qm)
6688}
6689
6690fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6693 let qd_enc = qreg_to_num(qd) * 2;
6694 let rn = reg_to_bits(&addr.base);
6695 let offset = addr.offset;
6696 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6697 let abs_offset = offset.unsigned_abs();
6698 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6702 | (u_bit << 23)
6703 | ((qd_enc >> 4) << 22)
6704 | (rn << 16)
6705 | ((qd_enc & 0xF) << 12)
6706 | (imm7 & 0x7F)
6707}
6708
6709fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6711 let qd_enc = qreg_to_num(qd) * 2;
6712 let rn = reg_to_bits(&addr.base);
6713 let offset = addr.offset;
6714 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6715 let abs_offset = offset.unsigned_abs();
6716 let imm7 = (abs_offset / 4) & 0x7F;
6717
6718 0xED000E80
6719 | (u_bit << 23)
6720 | ((qd_enc >> 4) << 22)
6721 | (rn << 16)
6722 | ((qd_enc & 0xF) << 12)
6723 | (imm7 & 0x7F)
6724}
6725
6726impl ArmEncoder {
6727 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6729 let mut result = Vec::new();
6730 let qd_num = qreg_to_num(qd);
6731
6732 for i in 0..4 {
6734 let word = u32::from_le_bytes([
6735 bytes[i * 4],
6736 bytes[i * 4 + 1],
6737 bytes[i * 4 + 2],
6738 bytes[i * 4 + 3],
6739 ]);
6740 let lo16 = word & 0xFFFF;
6741 let hi16 = (word >> 16) & 0xFFFF;
6742
6743 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6745 if hi16 != 0 {
6747 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6748 }
6749
6750 let s_num = qd_num * 4 + i as u32;
6752 let (vn, n) = encode_sreg(s_num);
6753 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6754 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6755 }
6756
6757 Ok(result)
6758 }
6759
6760 fn encode_thumb_mve_lane_wise_f32_binop(
6762 &self,
6763 qd: &QReg,
6764 qn: &QReg,
6765 qm: &QReg,
6766 vfp_base: u32,
6767 ) -> Result<Vec<u8>> {
6768 let mut result = Vec::new();
6769 let qd_num = qreg_to_num(qd);
6770 let qn_num = qreg_to_num(qn);
6771 let qm_num = qreg_to_num(qm);
6772
6773 for i in 0..4u32 {
6775 let sd = qd_num * 4 + i;
6776 let sn = qn_num * 4 + i;
6777 let sm = qm_num * 4 + i;
6778
6779 let (vd, d) = encode_sreg(sd);
6780 let (vn, n) = encode_sreg(sn);
6781 let (vm, m) = encode_sreg(sm);
6782
6783 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6784 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6785 }
6786
6787 Ok(result)
6788 }
6789
6790 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6792 let mut result = Vec::new();
6793 let qd_num = qreg_to_num(qd);
6794 let qm_num = qreg_to_num(qm);
6795
6796 for i in 0..4u32 {
6798 let sd = qd_num * 4 + i;
6799 let sm = qm_num * 4 + i;
6800
6801 let (vd, d) = encode_sreg(sd);
6802 let (vm, m) = encode_sreg(sm);
6803
6804 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6805 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6806 }
6807
6808 Ok(result)
6809 }
6810}
6811
6812#[cfg(test)]
6813mod tests {
6814 use super::*;
6815
6816 #[test]
6817 fn test_encoder_creation() {
6818 let encoder_arm = ArmEncoder::new_arm32();
6819 assert!(!encoder_arm.thumb_mode);
6820
6821 let encoder_thumb = ArmEncoder::new_thumb2();
6822 assert!(encoder_thumb.thumb_mode);
6823 }
6824
6825 #[test]
6826 fn test_encode_nop_arm32() {
6827 let encoder = ArmEncoder::new_arm32();
6828 let code = encoder.encode(&ArmOp::Nop).unwrap();
6829
6830 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
6833
6834 #[test]
6835 fn test_encode_nop_thumb() {
6836 let encoder = ArmEncoder::new_thumb2();
6837 let code = encoder.encode(&ArmOp::Nop).unwrap();
6838
6839 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
6842
6843 #[test]
6844 fn test_encode_mov_immediate_arm32() {
6845 let encoder = ArmEncoder::new_arm32();
6846 let op = ArmOp::Mov {
6847 rd: Reg::R0,
6848 op2: Operand2::Imm(42),
6849 };
6850
6851 let code = encoder.encode(&op).unwrap();
6852 assert_eq!(code.len(), 4);
6853
6854 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6856 assert_eq!(instr & 0x0E000000, 0x02000000); }
6858
6859 #[test]
6860 fn test_encode_add_registers_arm32() {
6861 let encoder = ArmEncoder::new_arm32();
6862 let op = ArmOp::Add {
6863 rd: Reg::R0,
6864 rn: Reg::R1,
6865 op2: Operand2::Reg(Reg::R2),
6866 };
6867
6868 let code = encoder.encode(&op).unwrap();
6869 assert_eq!(code.len(), 4);
6870
6871 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6872 assert_eq!(instr & 0x0FE00000, 0x00800000);
6874 }
6875
6876 #[test]
6877 fn test_encode_ldr_arm32() {
6878 let encoder = ArmEncoder::new_arm32();
6879 let op = ArmOp::Ldr {
6880 rd: Reg::R0,
6881 addr: MemAddr::imm(Reg::R1, 4),
6882 };
6883
6884 let code = encoder.encode(&op).unwrap();
6885 assert_eq!(code.len(), 4);
6886
6887 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6888 assert_eq!(instr & 0x00100000, 0x00100000);
6890 }
6891
6892 #[test]
6893 fn test_encode_str_arm32() {
6894 let encoder = ArmEncoder::new_arm32();
6895 let op = ArmOp::Str {
6896 rd: Reg::R0,
6897 addr: MemAddr::imm(Reg::SP, 0),
6898 };
6899
6900 let code = encoder.encode(&op).unwrap();
6901 assert_eq!(code.len(), 4);
6902 }
6903
6904 #[test]
6905 fn test_encode_branch_arm32() {
6906 let encoder = ArmEncoder::new_arm32();
6907 let op = ArmOp::Bl {
6908 label: "main".to_string(),
6909 };
6910
6911 let code = encoder.encode(&op).unwrap();
6912 assert_eq!(code.len(), 4);
6913
6914 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
6915 assert_eq!(instr & 0x0F000000, 0x0B000000);
6917 }
6918
6919 #[test]
6929 fn test_encode_thumb_bl_placeholder_addend_167_174() {
6930 let encoder = ArmEncoder::new_thumb2();
6931 let op = ArmOp::Bl {
6932 label: "callee".to_string(),
6933 };
6934
6935 let code = encoder.encode(&op).unwrap();
6936 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
6937
6938 let hw1 = u16::from_le_bytes([code[0], code[1]]);
6939 let hw2 = u16::from_le_bytes([code[2], code[3]]);
6940 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
6941 assert_eq!(
6942 hw2, 0xFFFE,
6943 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
6944 );
6945 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
6946 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
6947 }
6948
6949 #[test]
6950 fn test_encode_sequence() {
6951 let encoder = ArmEncoder::new_arm32();
6952 let ops = vec![
6953 ArmOp::Mov {
6954 rd: Reg::R0,
6955 op2: Operand2::Imm(42),
6956 },
6957 ArmOp::Mov {
6958 rd: Reg::R1,
6959 op2: Operand2::Imm(10),
6960 },
6961 ArmOp::Add {
6962 rd: Reg::R2,
6963 rn: Reg::R0,
6964 op2: Operand2::Reg(Reg::R1),
6965 },
6966 ];
6967
6968 let code = encoder.encode_sequence(&ops).unwrap();
6969 assert_eq!(code.len(), 12); }
6971
6972 #[test]
6973 fn test_reg_to_bits() {
6974 assert_eq!(reg_to_bits(&Reg::R0), 0);
6975 assert_eq!(reg_to_bits(&Reg::R7), 7);
6976 assert_eq!(reg_to_bits(&Reg::SP), 13);
6977 assert_eq!(reg_to_bits(&Reg::LR), 14);
6978 assert_eq!(reg_to_bits(&Reg::PC), 15);
6979 }
6980
6981 #[test]
6982 fn test_encode_bitwise_operations() {
6983 let encoder = ArmEncoder::new_arm32();
6984
6985 let and_op = ArmOp::And {
6986 rd: Reg::R0,
6987 rn: Reg::R1,
6988 op2: Operand2::Reg(Reg::R2),
6989 };
6990 let and_code = encoder.encode(&and_op).unwrap();
6991 assert_eq!(and_code.len(), 4);
6992
6993 let orr_op = ArmOp::Orr {
6994 rd: Reg::R0,
6995 rn: Reg::R1,
6996 op2: Operand2::Reg(Reg::R2),
6997 };
6998 let orr_code = encoder.encode(&orr_op).unwrap();
6999 assert_eq!(orr_code.len(), 4);
7000
7001 let eor_op = ArmOp::Eor {
7002 rd: Reg::R0,
7003 rn: Reg::R1,
7004 op2: Operand2::Reg(Reg::R2),
7005 };
7006 let eor_code = encoder.encode(&eor_op).unwrap();
7007 assert_eq!(eor_code.len(), 4);
7008 }
7009
7010 #[test]
7013 fn test_encode_sdiv_thumb2() {
7014 let encoder = ArmEncoder::new_thumb2();
7015 let op = ArmOp::Sdiv {
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); assert_eq!(code[0], 0x91);
7029 assert_eq!(code[1], 0xFB);
7030 assert_eq!(code[2], 0xF2);
7031 assert_eq!(code[3], 0xF0);
7032 }
7033
7034 #[test]
7035 fn test_encode_udiv_thumb2() {
7036 let encoder = ArmEncoder::new_thumb2();
7037 let op = ArmOp::Udiv {
7038 rd: Reg::R0,
7039 rn: Reg::R1,
7040 rm: Reg::R2,
7041 };
7042
7043 let code = encoder.encode(&op).unwrap();
7044 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7049 assert_eq!(code[1], 0xFB);
7050 assert_eq!(code[2], 0xF2);
7051 assert_eq!(code[3], 0xF0);
7052 }
7053
7054 #[test]
7055 fn test_encode_mul_thumb2() {
7056 let encoder = ArmEncoder::new_thumb2();
7057 let op = ArmOp::Mul {
7058 rd: Reg::R0,
7059 rn: Reg::R1,
7060 rm: Reg::R2,
7061 };
7062
7063 let code = encoder.encode(&op).unwrap();
7064 assert_eq!(code.len(), 4); }
7066
7067 #[test]
7068 fn test_encode_and_thumb2() {
7069 let encoder = ArmEncoder::new_thumb2();
7070 let op = ArmOp::And {
7071 rd: Reg::R0,
7072 rn: Reg::R1,
7073 op2: Operand2::Reg(Reg::R2),
7074 };
7075
7076 let code = encoder.encode(&op).unwrap();
7077 assert_eq!(code.len(), 4); }
7079
7080 #[test]
7081 fn test_encode_lsl_thumb2_low_regs() {
7082 let encoder = ArmEncoder::new_thumb2();
7083 let op = ArmOp::Lsl {
7084 rd: Reg::R0,
7085 rn: Reg::R1,
7086 shift: 5,
7087 };
7088
7089 let code = encoder.encode(&op).unwrap();
7090 assert_eq!(code.len(), 2); }
7092
7093 #[test]
7094 fn test_encode_clz_thumb2() {
7095 let encoder = ArmEncoder::new_thumb2();
7096 let op = ArmOp::Clz {
7097 rd: Reg::R0,
7098 rm: Reg::R1,
7099 };
7100
7101 let code = encoder.encode(&op).unwrap();
7102 assert_eq!(code.len(), 4); }
7104
7105 #[test]
7106 fn test_encode_bx_thumb2() {
7107 let encoder = ArmEncoder::new_thumb2();
7108 let op = ArmOp::Bx { rm: Reg::LR };
7109
7110 let code = encoder.encode(&op).unwrap();
7111 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7115 }
7116
7117 #[test]
7122 fn test_encode_f32_abs_arm32() {
7123 let encoder = ArmEncoder::new_arm32();
7124 let op = ArmOp::F32Abs {
7125 sd: VfpReg::S0,
7126 sm: VfpReg::S2,
7127 };
7128 let code = encoder.encode(&op).unwrap();
7129 assert_eq!(code.len(), 4); }
7131
7132 #[test]
7133 fn test_encode_f32_neg_arm32() {
7134 let encoder = ArmEncoder::new_arm32();
7135 let op = ArmOp::F32Neg {
7136 sd: VfpReg::S0,
7137 sm: VfpReg::S2,
7138 };
7139 let code = encoder.encode(&op).unwrap();
7140 assert_eq!(code.len(), 4);
7141 }
7142
7143 #[test]
7144 fn test_encode_f32_sqrt_arm32() {
7145 let encoder = ArmEncoder::new_arm32();
7146 let op = ArmOp::F32Sqrt {
7147 sd: VfpReg::S0,
7148 sm: VfpReg::S2,
7149 };
7150 let code = encoder.encode(&op).unwrap();
7151 assert_eq!(code.len(), 4);
7152 }
7153
7154 #[test]
7155 fn test_encode_f32_ceil_arm32() {
7156 let encoder = ArmEncoder::new_arm32();
7157 let op = ArmOp::F32Ceil {
7158 sd: VfpReg::S0,
7159 sm: VfpReg::S2,
7160 };
7161 let code = encoder.encode(&op).unwrap();
7162 assert_eq!(code.len(), 36);
7164 }
7165
7166 #[test]
7167 fn test_encode_f32_floor_thumb2() {
7168 let encoder = ArmEncoder::new_thumb2();
7169 let op = ArmOp::F32Floor {
7170 sd: VfpReg::S0,
7171 sm: VfpReg::S2,
7172 };
7173 let code = encoder.encode(&op).unwrap();
7174 assert_eq!(code.len(), 36);
7176 }
7177
7178 #[test]
7179 fn test_encode_f32_min_arm32() {
7180 let encoder = ArmEncoder::new_arm32();
7181 let op = ArmOp::F32Min {
7182 sd: VfpReg::S0,
7183 sn: VfpReg::S2,
7184 sm: VfpReg::S4,
7185 };
7186 let code = encoder.encode(&op).unwrap();
7187 assert_eq!(code.len(), 16); }
7189
7190 #[test]
7191 fn test_encode_f32_max_thumb2() {
7192 let encoder = ArmEncoder::new_thumb2();
7193 let op = ArmOp::F32Max {
7194 sd: VfpReg::S0,
7195 sn: VfpReg::S2,
7196 sm: VfpReg::S4,
7197 };
7198 let code = encoder.encode(&op).unwrap();
7199 assert_eq!(code.len(), 18);
7201 }
7202
7203 #[test]
7204 fn test_encode_f32_copysign_arm32() {
7205 let encoder = ArmEncoder::new_arm32();
7206 let op = ArmOp::F32Copysign {
7207 sd: VfpReg::S0,
7208 sn: VfpReg::S2,
7209 sm: VfpReg::S4,
7210 };
7211 let code = encoder.encode(&op).unwrap();
7212 assert_eq!(code.len(), 24);
7214 }
7215
7216 #[test]
7221 fn test_encode_f64_add_arm32() {
7222 let encoder = ArmEncoder::new_arm32();
7223 let op = ArmOp::F64Add {
7224 dd: VfpReg::D0,
7225 dn: VfpReg::D1,
7226 dm: VfpReg::D2,
7227 };
7228 let code = encoder.encode(&op).unwrap();
7229 assert_eq!(code.len(), 4);
7230 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7232 assert_eq!((instr >> 8) & 0xF, 0xB); }
7234
7235 #[test]
7236 fn test_encode_f64_sub_thumb2() {
7237 let encoder = ArmEncoder::new_thumb2();
7238 let op = ArmOp::F64Sub {
7239 dd: VfpReg::D0,
7240 dn: VfpReg::D1,
7241 dm: VfpReg::D2,
7242 };
7243 let code = encoder.encode(&op).unwrap();
7244 assert_eq!(code.len(), 4); }
7246
7247 #[test]
7248 fn test_encode_f64_mul_arm32() {
7249 let encoder = ArmEncoder::new_arm32();
7250 let op = ArmOp::F64Mul {
7251 dd: VfpReg::D0,
7252 dn: VfpReg::D1,
7253 dm: VfpReg::D2,
7254 };
7255 let code = encoder.encode(&op).unwrap();
7256 assert_eq!(code.len(), 4);
7257 }
7258
7259 #[test]
7260 fn test_encode_f64_div_arm32() {
7261 let encoder = ArmEncoder::new_arm32();
7262 let op = ArmOp::F64Div {
7263 dd: VfpReg::D0,
7264 dn: VfpReg::D1,
7265 dm: VfpReg::D2,
7266 };
7267 let code = encoder.encode(&op).unwrap();
7268 assert_eq!(code.len(), 4);
7269 }
7270
7271 #[test]
7272 fn test_encode_f64_abs_arm32() {
7273 let encoder = ArmEncoder::new_arm32();
7274 let op = ArmOp::F64Abs {
7275 dd: VfpReg::D0,
7276 dm: VfpReg::D2,
7277 };
7278 let code = encoder.encode(&op).unwrap();
7279 assert_eq!(code.len(), 4);
7280 }
7281
7282 #[test]
7283 fn test_encode_f64_neg_arm32() {
7284 let encoder = ArmEncoder::new_arm32();
7285 let op = ArmOp::F64Neg {
7286 dd: VfpReg::D0,
7287 dm: VfpReg::D2,
7288 };
7289 let code = encoder.encode(&op).unwrap();
7290 assert_eq!(code.len(), 4);
7291 }
7292
7293 #[test]
7294 fn test_encode_f64_sqrt_arm32() {
7295 let encoder = ArmEncoder::new_arm32();
7296 let op = ArmOp::F64Sqrt {
7297 dd: VfpReg::D0,
7298 dm: VfpReg::D2,
7299 };
7300 let code = encoder.encode(&op).unwrap();
7301 assert_eq!(code.len(), 4);
7302 }
7303
7304 #[test]
7305 fn test_encode_f64_load_arm32() {
7306 let encoder = ArmEncoder::new_arm32();
7307 let op = ArmOp::F64Load {
7308 dd: VfpReg::D0,
7309 addr: MemAddr::imm(Reg::R0, 8),
7310 };
7311 let code = encoder.encode(&op).unwrap();
7312 assert_eq!(code.len(), 4);
7313 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7314 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7317
7318 #[test]
7319 fn test_encode_f64_store_thumb2() {
7320 let encoder = ArmEncoder::new_thumb2();
7321 let op = ArmOp::F64Store {
7322 dd: VfpReg::D0,
7323 addr: MemAddr::imm(Reg::SP, 0),
7324 };
7325 let code = encoder.encode(&op).unwrap();
7326 assert_eq!(code.len(), 4);
7327 }
7328
7329 #[test]
7330 fn test_encode_f64_compare_arm32() {
7331 let encoder = ArmEncoder::new_arm32();
7332 let op = ArmOp::F64Eq {
7333 rd: Reg::R0,
7334 dn: VfpReg::D0,
7335 dm: VfpReg::D1,
7336 };
7337 let code = encoder.encode(&op).unwrap();
7338 assert_eq!(code.len(), 16); }
7340
7341 #[test]
7342 fn test_encode_f64_compare_thumb2() {
7343 let encoder = ArmEncoder::new_thumb2();
7344 let op = ArmOp::F64Lt {
7345 rd: Reg::R0,
7346 dn: VfpReg::D0,
7347 dm: VfpReg::D1,
7348 };
7349 let code = encoder.encode(&op).unwrap();
7350 assert_eq!(code.len(), 14);
7352 }
7353
7354 #[test]
7355 fn test_encode_f64_const_arm32() {
7356 let encoder = ArmEncoder::new_arm32();
7357 let op = ArmOp::F64Const {
7358 dd: VfpReg::D0,
7359 value: 3.125,
7360 };
7361 let code = encoder.encode(&op).unwrap();
7362 assert_eq!(code.len(), 20);
7364 }
7365
7366 #[test]
7367 fn test_encode_f64_const_thumb2() {
7368 let encoder = ArmEncoder::new_thumb2();
7369 let op = ArmOp::F64Const {
7370 dd: VfpReg::D0,
7371 value: 2.5,
7372 };
7373 let code = encoder.encode(&op).unwrap();
7374 assert_eq!(code.len(), 20);
7376 }
7377
7378 #[test]
7379 fn test_encode_f64_convert_i32s_arm32() {
7380 let encoder = ArmEncoder::new_arm32();
7381 let op = ArmOp::F64ConvertI32S {
7382 dd: VfpReg::D0,
7383 rm: Reg::R0,
7384 };
7385 let code = encoder.encode(&op).unwrap();
7386 assert_eq!(code.len(), 8);
7388 }
7389
7390 #[test]
7391 fn test_encode_f64_promote_f32_arm32() {
7392 let encoder = ArmEncoder::new_arm32();
7393 let op = ArmOp::F64PromoteF32 {
7394 dd: VfpReg::D0,
7395 sm: VfpReg::S0,
7396 };
7397 let code = encoder.encode(&op).unwrap();
7398 assert_eq!(code.len(), 4); }
7400
7401 #[test]
7402 fn test_encode_f64_promote_f32_thumb2() {
7403 let encoder = ArmEncoder::new_thumb2();
7404 let op = ArmOp::F64PromoteF32 {
7405 dd: VfpReg::D0,
7406 sm: VfpReg::S0,
7407 };
7408 let code = encoder.encode(&op).unwrap();
7409 assert_eq!(code.len(), 4);
7410 }
7411
7412 #[test]
7413 fn test_encode_i32_trunc_f64s_arm32() {
7414 let encoder = ArmEncoder::new_arm32();
7415 let op = ArmOp::I32TruncF64S {
7416 rd: Reg::R0,
7417 dm: VfpReg::D0,
7418 };
7419 let code = encoder.encode(&op).unwrap();
7420 assert_eq!(code.len(), 8);
7422 }
7423
7424 #[test]
7425 fn test_encode_f64_reinterpret_i64_arm32() {
7426 let encoder = ArmEncoder::new_arm32();
7427 let op = ArmOp::F64ReinterpretI64 {
7428 dd: VfpReg::D0,
7429 rmlo: Reg::R0,
7430 rmhi: Reg::R1,
7431 };
7432 let code = encoder.encode(&op).unwrap();
7433 assert_eq!(code.len(), 4); }
7435
7436 #[test]
7437 fn test_encode_i64_reinterpret_f64_thumb2() {
7438 let encoder = ArmEncoder::new_thumb2();
7439 let op = ArmOp::I64ReinterpretF64 {
7440 rdlo: Reg::R0,
7441 rdhi: Reg::R1,
7442 dm: VfpReg::D0,
7443 };
7444 let code = encoder.encode(&op).unwrap();
7445 assert_eq!(code.len(), 4);
7446 }
7447
7448 #[test]
7449 fn test_encode_f64_trunc_thumb2() {
7450 let encoder = ArmEncoder::new_thumb2();
7451 let op = ArmOp::F64Trunc {
7452 dd: VfpReg::D0,
7453 dm: VfpReg::D1,
7454 };
7455 let code = encoder.encode(&op).unwrap();
7456 assert_eq!(code.len(), 8);
7458 }
7459
7460 #[test]
7461 fn test_encode_f64_min_arm32() {
7462 let encoder = ArmEncoder::new_arm32();
7463 let op = ArmOp::F64Min {
7464 dd: VfpReg::D0,
7465 dn: VfpReg::D1,
7466 dm: VfpReg::D2,
7467 };
7468 let code = encoder.encode(&op).unwrap();
7469 assert_eq!(code.len(), 16);
7471 }
7472
7473 #[test]
7474 fn test_f64_cp11_encoding() {
7475 let encoder = ArmEncoder::new_arm32();
7477
7478 let code = encoder
7480 .encode(&ArmOp::F64Add {
7481 dd: VfpReg::D0,
7482 dn: VfpReg::D0,
7483 dm: VfpReg::D0,
7484 })
7485 .unwrap();
7486 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7487 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7488
7489 let code = encoder
7491 .encode(&ArmOp::F32Add {
7492 sd: VfpReg::S0,
7493 sn: VfpReg::S0,
7494 sm: VfpReg::S0,
7495 })
7496 .unwrap();
7497 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7498 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7499 }
7500
7501 #[test]
7502 fn test_dreg_encoding_higher_registers() {
7503 let encoder = ArmEncoder::new_arm32();
7504
7505 let op = ArmOp::F64Add {
7507 dd: VfpReg::D15,
7508 dn: VfpReg::D14,
7509 dm: VfpReg::D13,
7510 };
7511 let code = encoder.encode(&op).unwrap();
7512 assert_eq!(code.len(), 4);
7513
7514 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7516 assert_eq!((instr >> 8) & 0xF, 0xB); }
7518
7519 #[test]
7524 fn test_encode_label_emits_no_bytes() {
7525 let encoder = ArmEncoder::new_thumb2();
7526 let op = ArmOp::Label {
7527 name: ".Lblock_end_0".to_string(),
7528 };
7529 let code = encoder.encode(&op).unwrap();
7530 assert!(code.is_empty(), "Label should emit zero bytes");
7531
7532 let encoder32 = ArmEncoder::new_arm32();
7533 let code32 = encoder32.encode(&op).unwrap();
7534 assert!(
7535 code32.is_empty(),
7536 "Label should emit zero bytes in ARM32 too"
7537 );
7538 }
7539
7540 #[test]
7541 fn test_encode_bcc_eq_thumb2() {
7542 use synth_synthesis::Condition;
7543 let encoder = ArmEncoder::new_thumb2();
7544 let op = ArmOp::Bcc {
7545 cond: Condition::EQ,
7546 label: "target".to_string(),
7547 };
7548 let code = encoder.encode(&op).unwrap();
7549 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7553 }
7554
7555 #[test]
7556 fn test_encode_bcc_ne_thumb2() {
7557 use synth_synthesis::Condition;
7558 let encoder = ArmEncoder::new_thumb2();
7559 let op = ArmOp::Bcc {
7560 cond: Condition::NE,
7561 label: "target".to_string(),
7562 };
7563 let code = encoder.encode(&op).unwrap();
7564 assert_eq!(code.len(), 2);
7565
7566 assert_eq!(code, vec![0x00, 0xD1]);
7568 }
7569
7570 #[test]
7571 fn test_encode_bcc_arm32() {
7572 use synth_synthesis::Condition;
7573 let encoder = ArmEncoder::new_arm32();
7574 let op = ArmOp::Bcc {
7575 cond: Condition::EQ,
7576 label: "target".to_string(),
7577 };
7578 let code = encoder.encode(&op).unwrap();
7579 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7582 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7586
7587 #[test]
7588 fn test_encode_udf_thumb2() {
7589 let encoder = ArmEncoder::new_thumb2();
7590 let op = ArmOp::Udf { imm: 0 };
7591 let code = encoder.encode(&op).unwrap();
7592 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
7596 }
7597
7598 #[test]
7599 fn test_encode_nop_thumb2() {
7600 let encoder = ArmEncoder::new_thumb2();
7601 let op = ArmOp::Nop;
7602 let code = encoder.encode(&op).unwrap();
7603 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
7607 }
7608
7609 #[test]
7614 fn test_encode_i64_add_thumb2() {
7615 let encoder = ArmEncoder::new_thumb2();
7616 let op = ArmOp::I64Add {
7617 rdlo: Reg::R0,
7618 rdhi: Reg::R1,
7619 rnlo: Reg::R0,
7620 rnhi: Reg::R1,
7621 rmlo: Reg::R2,
7622 rmhi: Reg::R3,
7623 };
7624 let code = encoder.encode(&op).unwrap();
7625 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
7627 }
7628
7629 #[test]
7630 fn test_encode_i64_sub_thumb2() {
7631 let encoder = ArmEncoder::new_thumb2();
7632 let op = ArmOp::I64Sub {
7633 rdlo: Reg::R0,
7634 rdhi: Reg::R1,
7635 rnlo: Reg::R0,
7636 rnhi: Reg::R1,
7637 rmlo: Reg::R2,
7638 rmhi: Reg::R3,
7639 };
7640 let code = encoder.encode(&op).unwrap();
7641 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
7643 }
7644
7645 #[test]
7646 fn test_encode_i64_and_thumb2() {
7647 let encoder = ArmEncoder::new_thumb2();
7648 let op = ArmOp::I64And {
7649 rdlo: Reg::R0,
7650 rdhi: Reg::R1,
7651 rnlo: Reg::R0,
7652 rnhi: Reg::R1,
7653 rmlo: Reg::R2,
7654 rmhi: Reg::R3,
7655 };
7656 let code = encoder.encode(&op).unwrap();
7657 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
7659 }
7660
7661 #[test]
7662 fn test_encode_i64_or_thumb2() {
7663 let encoder = ArmEncoder::new_thumb2();
7664 let op = ArmOp::I64Or {
7665 rdlo: Reg::R0,
7666 rdhi: Reg::R1,
7667 rnlo: Reg::R0,
7668 rnhi: Reg::R1,
7669 rmlo: Reg::R2,
7670 rmhi: Reg::R3,
7671 };
7672 let code = encoder.encode(&op).unwrap();
7673 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
7674 }
7675
7676 #[test]
7677 fn test_encode_i64_xor_thumb2() {
7678 let encoder = ArmEncoder::new_thumb2();
7679 let op = ArmOp::I64Xor {
7680 rdlo: Reg::R0,
7681 rdhi: Reg::R1,
7682 rnlo: Reg::R0,
7683 rnhi: Reg::R1,
7684 rmlo: Reg::R2,
7685 rmhi: Reg::R3,
7686 };
7687 let code = encoder.encode(&op).unwrap();
7688 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
7689 }
7690
7691 #[test]
7692 fn test_encode_i64_const_small_thumb2() {
7693 let encoder = ArmEncoder::new_thumb2();
7694 let op = ArmOp::I64Const {
7696 rdlo: Reg::R0,
7697 rdhi: Reg::R1,
7698 value: 42,
7699 };
7700 let code = encoder.encode(&op).unwrap();
7701 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
7703 }
7704
7705 #[test]
7706 fn test_encode_i64_const_large_thumb2() {
7707 let encoder = ArmEncoder::new_thumb2();
7708 let op = ArmOp::I64Const {
7710 rdlo: Reg::R0,
7711 rdhi: Reg::R1,
7712 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
7713 };
7714 let code = encoder.encode(&op).unwrap();
7715 assert_eq!(
7717 code.len(),
7718 16,
7719 "I64Const with large value should be 16 bytes"
7720 );
7721 }
7722
7723 #[test]
7724 fn test_encode_i64_extend_i32_s_thumb2() {
7725 let encoder = ArmEncoder::new_thumb2();
7726 let op = ArmOp::I64ExtendI32S {
7727 rdlo: Reg::R0,
7728 rdhi: Reg::R1,
7729 rn: Reg::R0,
7730 };
7731 let code = encoder.encode(&op).unwrap();
7732 assert_eq!(
7734 code.len(),
7735 4,
7736 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
7737 );
7738 }
7739
7740 #[test]
7741 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
7742 let encoder = ArmEncoder::new_thumb2();
7743 let op = ArmOp::I64ExtendI32S {
7744 rdlo: Reg::R0,
7745 rdhi: Reg::R1,
7746 rn: Reg::R2,
7747 };
7748 let code = encoder.encode(&op).unwrap();
7749 assert!(
7751 code.len() >= 6,
7752 "I64ExtendI32S (diff reg) should be at least 6 bytes"
7753 );
7754 }
7755
7756 #[test]
7757 fn test_encode_i64_extend_i32_u_thumb2() {
7758 let encoder = ArmEncoder::new_thumb2();
7759 let op = ArmOp::I64ExtendI32U {
7760 rdlo: Reg::R0,
7761 rdhi: Reg::R1,
7762 rn: Reg::R0,
7763 };
7764 let code = encoder.encode(&op).unwrap();
7765 assert_eq!(
7767 code.len(),
7768 2,
7769 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
7770 );
7771 }
7772
7773 #[test]
7774 fn test_encode_i32_wrap_i64_nop_thumb2() {
7775 let encoder = ArmEncoder::new_thumb2();
7776 let op = ArmOp::I32WrapI64 {
7778 rd: Reg::R0,
7779 rnlo: Reg::R0,
7780 };
7781 let code = encoder.encode(&op).unwrap();
7782 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
7783 assert_eq!(code, vec![0x00, 0xBF]); }
7785
7786 #[test]
7787 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
7788 let encoder = ArmEncoder::new_thumb2();
7789 let op = ArmOp::I32WrapI64 {
7790 rd: Reg::R2,
7791 rnlo: Reg::R0,
7792 };
7793 let code = encoder.encode(&op).unwrap();
7794 assert!(
7796 code.len() >= 2,
7797 "I32WrapI64 diff reg should emit at least 2 bytes"
7798 );
7799 }
7800
7801 #[test]
7802 fn test_encode_i64_eqz_thumb2() {
7803 let encoder = ArmEncoder::new_thumb2();
7804 let op = ArmOp::I64Eqz {
7805 rd: Reg::R0,
7806 rnlo: Reg::R0,
7807 rnhi: Reg::R1,
7808 };
7809 let code = encoder.encode(&op).unwrap();
7810 assert!(
7812 code.len() >= 6,
7813 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
7814 );
7815 }
7816
7817 #[test]
7818 fn test_encode_i64_eq_thumb2() {
7819 let encoder = ArmEncoder::new_thumb2();
7820 let op = ArmOp::I64Eq {
7821 rd: Reg::R0,
7822 rnlo: Reg::R0,
7823 rnhi: Reg::R1,
7824 rmlo: Reg::R2,
7825 rmhi: Reg::R3,
7826 };
7827 let code = encoder.encode(&op).unwrap();
7828 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
7830 }
7831
7832 #[test]
7833 fn test_encode_i64_ldr_thumb2() {
7834 let encoder = ArmEncoder::new_thumb2();
7835 let op = ArmOp::I64Ldr {
7836 rdlo: Reg::R0,
7837 rdhi: Reg::R1,
7838 addr: MemAddr::imm(Reg::SP, 0),
7839 };
7840 let code = encoder.encode(&op).unwrap();
7841 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
7843 }
7844
7845 #[test]
7846 fn test_encode_i64_str_thumb2() {
7847 let encoder = ArmEncoder::new_thumb2();
7848 let op = ArmOp::I64Str {
7849 rdlo: Reg::R0,
7850 rdhi: Reg::R1,
7851 addr: MemAddr::imm(Reg::SP, 0),
7852 };
7853 let code = encoder.encode(&op).unwrap();
7854 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
7856 }
7857
7858 #[test]
7859 fn test_encode_i64_all_comparisons_thumb2() {
7860 let encoder = ArmEncoder::new_thumb2();
7861
7862 let ops = vec![
7863 ArmOp::I64Ne {
7864 rd: Reg::R0,
7865 rnlo: Reg::R0,
7866 rnhi: Reg::R1,
7867 rmlo: Reg::R2,
7868 rmhi: Reg::R3,
7869 },
7870 ArmOp::I64LtS {
7871 rd: Reg::R0,
7872 rnlo: Reg::R0,
7873 rnhi: Reg::R1,
7874 rmlo: Reg::R2,
7875 rmhi: Reg::R3,
7876 },
7877 ArmOp::I64LtU {
7878 rd: Reg::R0,
7879 rnlo: Reg::R0,
7880 rnhi: Reg::R1,
7881 rmlo: Reg::R2,
7882 rmhi: Reg::R3,
7883 },
7884 ArmOp::I64LeS {
7885 rd: Reg::R0,
7886 rnlo: Reg::R0,
7887 rnhi: Reg::R1,
7888 rmlo: Reg::R2,
7889 rmhi: Reg::R3,
7890 },
7891 ArmOp::I64LeU {
7892 rd: Reg::R0,
7893 rnlo: Reg::R0,
7894 rnhi: Reg::R1,
7895 rmlo: Reg::R2,
7896 rmhi: Reg::R3,
7897 },
7898 ArmOp::I64GtS {
7899 rd: Reg::R0,
7900 rnlo: Reg::R0,
7901 rnhi: Reg::R1,
7902 rmlo: Reg::R2,
7903 rmhi: Reg::R3,
7904 },
7905 ArmOp::I64GtU {
7906 rd: Reg::R0,
7907 rnlo: Reg::R0,
7908 rnhi: Reg::R1,
7909 rmlo: Reg::R2,
7910 rmhi: Reg::R3,
7911 },
7912 ArmOp::I64GeS {
7913 rd: Reg::R0,
7914 rnlo: Reg::R0,
7915 rnhi: Reg::R1,
7916 rmlo: Reg::R2,
7917 rmhi: Reg::R3,
7918 },
7919 ArmOp::I64GeU {
7920 rd: Reg::R0,
7921 rnlo: Reg::R0,
7922 rnhi: Reg::R1,
7923 rmlo: Reg::R2,
7924 rmhi: Reg::R3,
7925 },
7926 ];
7927
7928 for op in &ops {
7929 let code = encoder.encode(op).unwrap();
7930 assert!(
7931 code.len() >= 8,
7932 "i64 comparison {:?} should emit at least 8 bytes, got {}",
7933 op,
7934 code.len()
7935 );
7936 }
7937 }
7938
7939 #[test]
7940 fn test_encode_i64_const_zero_thumb2() {
7941 let encoder = ArmEncoder::new_thumb2();
7942 let op = ArmOp::I64Const {
7943 rdlo: Reg::R0,
7944 rdhi: Reg::R1,
7945 value: 0,
7946 };
7947 let code = encoder.encode(&op).unwrap();
7948 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
7950 }
7951
7952 #[test]
7953 fn test_encode_i64_const_negative_one_thumb2() {
7954 let encoder = ArmEncoder::new_thumb2();
7955 let op = ArmOp::I64Const {
7956 rdlo: Reg::R0,
7957 rdhi: Reg::R1,
7958 value: -1, };
7960 let code = encoder.encode(&op).unwrap();
7961 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
7963 }
7964
7965 #[test]
7970 fn test_encode_ldrb_arm32() {
7971 let encoder = ArmEncoder::new_arm32();
7972 let op = ArmOp::Ldrb {
7973 rd: Reg::R0,
7974 addr: MemAddr::imm(Reg::R1, 4),
7975 };
7976 let code = encoder.encode(&op).unwrap();
7977 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
7978 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7980 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
7981 }
7982
7983 #[test]
7984 fn test_encode_strb_arm32() {
7985 let encoder = ArmEncoder::new_arm32();
7986 let op = ArmOp::Strb {
7987 rd: Reg::R0,
7988 addr: MemAddr::imm(Reg::R1, 0),
7989 };
7990 let code = encoder.encode(&op).unwrap();
7991 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
7992 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7994 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
7995 }
7996
7997 #[test]
7998 fn test_encode_ldrh_arm32() {
7999 let encoder = ArmEncoder::new_arm32();
8000 let op = ArmOp::Ldrh {
8001 rd: Reg::R0,
8002 addr: MemAddr::imm(Reg::R1, 2),
8003 };
8004 let code = encoder.encode(&op).unwrap();
8005 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8006 }
8007
8008 #[test]
8009 fn test_encode_strh_arm32() {
8010 let encoder = ArmEncoder::new_arm32();
8011 let op = ArmOp::Strh {
8012 rd: Reg::R0,
8013 addr: MemAddr::imm(Reg::R1, 0),
8014 };
8015 let code = encoder.encode(&op).unwrap();
8016 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8017 }
8018
8019 #[test]
8020 fn test_encode_ldrsb_arm32() {
8021 let encoder = ArmEncoder::new_arm32();
8022 let op = ArmOp::Ldrsb {
8023 rd: Reg::R0,
8024 addr: MemAddr::imm(Reg::R1, 0),
8025 };
8026 let code = encoder.encode(&op).unwrap();
8027 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8028 }
8029
8030 #[test]
8031 fn test_encode_ldrsh_arm32() {
8032 let encoder = ArmEncoder::new_arm32();
8033 let op = ArmOp::Ldrsh {
8034 rd: Reg::R0,
8035 addr: MemAddr::imm(Reg::R1, 0),
8036 };
8037 let code = encoder.encode(&op).unwrap();
8038 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8039 }
8040
8041 #[test]
8042 fn test_encode_ldrb_thumb2_16bit() {
8043 let encoder = ArmEncoder::new_thumb2();
8044 let op = ArmOp::Ldrb {
8045 rd: Reg::R0,
8046 addr: MemAddr::imm(Reg::R1, 4),
8047 };
8048 let code = encoder.encode(&op).unwrap();
8049 assert_eq!(
8051 code.len(),
8052 2,
8053 "Thumb-2 LDRB with small offset should be 16-bit"
8054 );
8055 }
8056
8057 #[test]
8058 fn test_encode_ldrb_thumb2_32bit() {
8059 let encoder = ArmEncoder::new_thumb2();
8060 let op = ArmOp::Ldrb {
8061 rd: Reg::R0,
8062 addr: MemAddr::imm(Reg::R1, 100), };
8064 let code = encoder.encode(&op).unwrap();
8065 assert_eq!(
8066 code.len(),
8067 4,
8068 "Thumb-2 LDRB with large offset should be 32-bit"
8069 );
8070 }
8071
8072 #[test]
8073 fn test_encode_strb_thumb2_16bit() {
8074 let encoder = ArmEncoder::new_thumb2();
8075 let op = ArmOp::Strb {
8076 rd: Reg::R0,
8077 addr: MemAddr::imm(Reg::R1, 10),
8078 };
8079 let code = encoder.encode(&op).unwrap();
8080 assert_eq!(
8081 code.len(),
8082 2,
8083 "Thumb-2 STRB with small offset should be 16-bit"
8084 );
8085 }
8086
8087 #[test]
8088 fn test_encode_ldrh_thumb2_16bit() {
8089 let encoder = ArmEncoder::new_thumb2();
8090 let op = ArmOp::Ldrh {
8091 rd: Reg::R0,
8092 addr: MemAddr::imm(Reg::R1, 4), };
8094 let code = encoder.encode(&op).unwrap();
8095 assert_eq!(
8096 code.len(),
8097 2,
8098 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8099 );
8100 }
8101
8102 #[test]
8103 fn test_encode_strh_thumb2_16bit() {
8104 let encoder = ArmEncoder::new_thumb2();
8105 let op = ArmOp::Strh {
8106 rd: Reg::R0,
8107 addr: MemAddr::imm(Reg::R1, 4),
8108 };
8109 let code = encoder.encode(&op).unwrap();
8110 assert_eq!(
8111 code.len(),
8112 2,
8113 "Thumb-2 STRH with small aligned offset should be 16-bit"
8114 );
8115 }
8116
8117 #[test]
8118 fn test_encode_ldrsb_thumb2() {
8119 let encoder = ArmEncoder::new_thumb2();
8120 let op = ArmOp::Ldrsb {
8121 rd: Reg::R0,
8122 addr: MemAddr::imm(Reg::R1, 0),
8123 };
8124 let code = encoder.encode(&op).unwrap();
8125 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8127 }
8128
8129 #[test]
8130 fn test_encode_ldrsh_thumb2() {
8131 let encoder = ArmEncoder::new_thumb2();
8132 let op = ArmOp::Ldrsh {
8133 rd: Reg::R0,
8134 addr: MemAddr::imm(Reg::R1, 0),
8135 };
8136 let code = encoder.encode(&op).unwrap();
8137 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8138 }
8139
8140 #[test]
8141 fn test_encode_memory_size_thumb2() {
8142 let encoder = ArmEncoder::new_thumb2();
8143 let op = ArmOp::MemorySize { rd: Reg::R0 };
8144 let code = encoder.encode(&op).unwrap();
8145 assert!(!code.is_empty(), "MemorySize should produce code");
8147 }
8148
8149 #[test]
8150 fn test_encode_memory_grow_thumb2() {
8151 let encoder = ArmEncoder::new_thumb2();
8152 let op = ArmOp::MemoryGrow {
8153 rd: Reg::R0,
8154 rn: Reg::R0,
8155 };
8156 let code = encoder.encode(&op).unwrap();
8157 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8158 }
8159
8160 #[test]
8161 fn test_encode_subword_reg_offset_thumb2() {
8162 let encoder = ArmEncoder::new_thumb2();
8163
8164 let op = ArmOp::Ldrb {
8166 rd: Reg::R0,
8167 addr: MemAddr::reg(Reg::R1, Reg::R2),
8168 };
8169 let code = encoder.encode(&op).unwrap();
8170 assert_eq!(
8171 code.len(),
8172 4,
8173 "Thumb-2 LDRB with reg offset should be 32-bit"
8174 );
8175
8176 let op = ArmOp::Strb {
8178 rd: Reg::R0,
8179 addr: MemAddr::reg(Reg::R1, Reg::R2),
8180 };
8181 let code = encoder.encode(&op).unwrap();
8182 assert_eq!(
8183 code.len(),
8184 4,
8185 "Thumb-2 STRB with reg offset should be 32-bit"
8186 );
8187
8188 let op = ArmOp::Ldrh {
8190 rd: Reg::R0,
8191 addr: MemAddr::reg(Reg::R1, Reg::R2),
8192 };
8193 let code = encoder.encode(&op).unwrap();
8194 assert_eq!(
8195 code.len(),
8196 4,
8197 "Thumb-2 LDRH with reg offset should be 32-bit"
8198 );
8199
8200 let op = ArmOp::Strh {
8202 rd: Reg::R0,
8203 addr: MemAddr::reg(Reg::R1, Reg::R2),
8204 };
8205 let code = encoder.encode(&op).unwrap();
8206 assert_eq!(
8207 code.len(),
8208 4,
8209 "Thumb-2 STRH with reg offset should be 32-bit"
8210 );
8211 }
8212
8213 #[test]
8214 fn test_encode_subword_reg_imm_offset_thumb2() {
8215 let encoder = ArmEncoder::new_thumb2();
8216
8217 let op = ArmOp::Ldrb {
8219 rd: Reg::R0,
8220 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8221 };
8222 let code = encoder.encode(&op).unwrap();
8223 assert_eq!(
8225 code.len(),
8226 8,
8227 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8228 );
8229 }
8230
8231 #[test]
8236 fn test_encode_mve_addi32_thumb2() {
8237 let encoder = ArmEncoder::new_thumb2();
8238 let op = ArmOp::MveAddI {
8239 qd: QReg::Q0,
8240 qn: QReg::Q1,
8241 qm: QReg::Q2,
8242 size: MveSize::S32,
8243 };
8244 let code = encoder.encode(&op).unwrap();
8245 assert_eq!(
8246 code.len(),
8247 4,
8248 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8249 );
8250 }
8251
8252 #[test]
8253 fn test_encode_mve_subi16_thumb2() {
8254 let encoder = ArmEncoder::new_thumb2();
8255 let op = ArmOp::MveSubI {
8256 qd: QReg::Q0,
8257 qn: QReg::Q1,
8258 qm: QReg::Q2,
8259 size: MveSize::S16,
8260 };
8261 let code = encoder.encode(&op).unwrap();
8262 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8263 }
8264
8265 #[test]
8266 fn test_encode_mve_muli8_thumb2() {
8267 let encoder = ArmEncoder::new_thumb2();
8268 let op = ArmOp::MveMulI {
8269 qd: QReg::Q0,
8270 qn: QReg::Q1,
8271 qm: QReg::Q2,
8272 size: MveSize::S8,
8273 };
8274 let code = encoder.encode(&op).unwrap();
8275 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8276 }
8277
8278 #[test]
8279 fn test_encode_mve_bitwise_thumb2() {
8280 let encoder = ArmEncoder::new_thumb2();
8281
8282 let ops = vec![
8283 ArmOp::MveAnd {
8284 qd: QReg::Q0,
8285 qn: QReg::Q1,
8286 qm: QReg::Q2,
8287 },
8288 ArmOp::MveOrr {
8289 qd: QReg::Q0,
8290 qn: QReg::Q1,
8291 qm: QReg::Q2,
8292 },
8293 ArmOp::MveEor {
8294 qd: QReg::Q0,
8295 qn: QReg::Q1,
8296 qm: QReg::Q2,
8297 },
8298 ArmOp::MveBic {
8299 qd: QReg::Q0,
8300 qn: QReg::Q1,
8301 qm: QReg::Q2,
8302 },
8303 ];
8304 for op in ops {
8305 let code = encoder.encode(&op).unwrap();
8306 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8307 }
8308 }
8309
8310 #[test]
8311 fn test_encode_mve_mvn_thumb2() {
8312 let encoder = ArmEncoder::new_thumb2();
8313 let op = ArmOp::MveMvn {
8314 qd: QReg::Q0,
8315 qm: QReg::Q1,
8316 };
8317 let code = encoder.encode(&op).unwrap();
8318 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8319 }
8320
8321 #[test]
8322 fn test_encode_mve_load_store_thumb2() {
8323 let encoder = ArmEncoder::new_thumb2();
8324
8325 let load = ArmOp::MveLoad {
8326 qd: QReg::Q0,
8327 addr: MemAddr::imm(Reg::R0, 16),
8328 };
8329 let code = encoder.encode(&load).unwrap();
8330 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8331
8332 let store = ArmOp::MveStore {
8333 qd: QReg::Q1,
8334 addr: MemAddr::imm(Reg::R1, 0),
8335 };
8336 let code = encoder.encode(&store).unwrap();
8337 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8338 }
8339
8340 #[test]
8341 fn test_encode_mve_const_thumb2() {
8342 let encoder = ArmEncoder::new_thumb2();
8343 let op = ArmOp::MveConst {
8344 qd: QReg::Q0,
8345 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8346 };
8347 let code = encoder.encode(&op).unwrap();
8348 assert!(
8351 code.len() >= 24,
8352 "MVE const should produce multiple instructions"
8353 );
8354 }
8355
8356 #[test]
8357 fn test_encode_mve_dup_thumb2() {
8358 let encoder = ArmEncoder::new_thumb2();
8359 let op = ArmOp::MveDup {
8360 qd: QReg::Q0,
8361 rn: Reg::R0,
8362 size: MveSize::S32,
8363 };
8364 let code = encoder.encode(&op).unwrap();
8365 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8366 }
8367
8368 #[test]
8369 fn test_encode_mve_extract_lane_thumb2() {
8370 let encoder = ArmEncoder::new_thumb2();
8371 let op = ArmOp::MveExtractLane {
8372 rd: Reg::R0,
8373 qn: QReg::Q1,
8374 lane: 2,
8375 size: MveSize::S32,
8376 };
8377 let code = encoder.encode(&op).unwrap();
8378 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8379 }
8380
8381 #[test]
8382 fn test_encode_mve_insert_lane_thumb2() {
8383 let encoder = ArmEncoder::new_thumb2();
8384 let op = ArmOp::MveInsertLane {
8385 qd: QReg::Q0,
8386 rn: Reg::R1,
8387 lane: 3,
8388 size: MveSize::S32,
8389 };
8390 let code = encoder.encode(&op).unwrap();
8391 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8392 }
8393
8394 #[test]
8395 fn test_encode_mve_addf32_thumb2() {
8396 let encoder = ArmEncoder::new_thumb2();
8397 let op = ArmOp::MveAddF32 {
8398 qd: QReg::Q0,
8399 qn: QReg::Q1,
8400 qm: QReg::Q2,
8401 };
8402 let code = encoder.encode(&op).unwrap();
8403 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8404 }
8405
8406 #[test]
8407 fn test_encode_mve_divf32_thumb2() {
8408 let encoder = ArmEncoder::new_thumb2();
8409 let op = ArmOp::MveDivF32 {
8410 qd: QReg::Q0,
8411 qn: QReg::Q1,
8412 qm: QReg::Q2,
8413 };
8414 let code = encoder.encode(&op).unwrap();
8415 assert_eq!(
8417 code.len(),
8418 16,
8419 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8420 );
8421 }
8422
8423 #[test]
8424 fn test_encode_mve_sqrtf32_thumb2() {
8425 let encoder = ArmEncoder::new_thumb2();
8426 let op = ArmOp::MveSqrtF32 {
8427 qd: QReg::Q0,
8428 qm: QReg::Q1,
8429 };
8430 let code = encoder.encode(&op).unwrap();
8431 assert_eq!(
8433 code.len(),
8434 16,
8435 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8436 );
8437 }
8438
8439 #[test]
8440 fn test_encode_mve_negf32_thumb2() {
8441 let encoder = ArmEncoder::new_thumb2();
8442 let op = ArmOp::MveNegF32 {
8443 qd: QReg::Q0,
8444 qm: QReg::Q1,
8445 };
8446 let code = encoder.encode(&op).unwrap();
8447 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8448 }
8449
8450 #[test]
8451 fn test_encode_mve_absf32_thumb2() {
8452 let encoder = ArmEncoder::new_thumb2();
8453 let op = ArmOp::MveAbsF32 {
8454 qd: QReg::Q0,
8455 qm: QReg::Q1,
8456 };
8457 let code = encoder.encode(&op).unwrap();
8458 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8459 }
8460
8461 #[test]
8462 fn test_encode_mve_different_qregs() {
8463 let encoder = ArmEncoder::new_thumb2();
8464
8465 let op1 = ArmOp::MveAddI {
8467 qd: QReg::Q0,
8468 qn: QReg::Q0,
8469 qm: QReg::Q0,
8470 size: MveSize::S32,
8471 };
8472 let op2 = ArmOp::MveAddI {
8473 qd: QReg::Q3,
8474 qn: QReg::Q5,
8475 qm: QReg::Q7,
8476 size: MveSize::S32,
8477 };
8478 let code1 = encoder.encode(&op1).unwrap();
8479 let code2 = encoder.encode(&op2).unwrap();
8480 assert_ne!(
8481 code1, code2,
8482 "Different Q-registers should produce different encodings"
8483 );
8484 }
8485
8486 #[test]
8487 fn test_encode_mve_arm32_nop() {
8488 let encoder = ArmEncoder::new_arm32();
8490 let op = ArmOp::MveAddI {
8491 qd: QReg::Q0,
8492 qn: QReg::Q1,
8493 qm: QReg::Q2,
8494 size: MveSize::S32,
8495 };
8496 let code = encoder.encode(&op).unwrap();
8497 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8498 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8500 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8501 }
8502}