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 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1399 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1401 Ok(instr.to_le_bytes().to_vec())
1402 } else {
1403 self.encode_thumb32_add_reg_raw(
1405 rd_bits as u32,
1406 rn_bits as u32,
1407 rm_bits as u32,
1408 )
1409 }
1410 } else if let Operand2::Imm(imm) = op2 {
1411 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1412 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1414 Ok(instr.to_le_bytes().to_vec())
1415 } else {
1416 self.encode_thumb32_add(rd, rn, *imm as u32)
1418 }
1419 } else {
1420 self.encode_thumb32_add(rd, rn, 0)
1422 }
1423 }
1424
1425 ArmOp::Sub { rd, rn, op2 } => {
1426 let rd_bits = reg_to_bits(rd) as u16;
1427 let rn_bits = reg_to_bits(rn) as u16;
1428
1429 if let Operand2::Reg(rm) = op2 {
1430 let rm_bits = reg_to_bits(rm) as u16;
1431 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1433 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1435 Ok(instr.to_le_bytes().to_vec())
1436 } else {
1437 self.encode_thumb32_sub_reg_raw(
1439 rd_bits as u32,
1440 rn_bits as u32,
1441 rm_bits as u32,
1442 )
1443 }
1444 } else if let Operand2::Imm(imm) = op2 {
1445 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1446 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1448 Ok(instr.to_le_bytes().to_vec())
1449 } else {
1450 self.encode_thumb32_sub(rd, rn, *imm as u32)
1451 }
1452 } else {
1453 self.encode_thumb32_sub(rd, rn, 0)
1454 }
1455 }
1456
1457 ArmOp::Mov { rd, op2 } => {
1458 let rd_bits = reg_to_bits(rd) as u16;
1459
1460 if let Operand2::Imm(imm) = op2 {
1461 if *imm <= 255 && rd_bits < 8 {
1462 let imm_bits = (*imm as u16) & 0xFF;
1464 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1465 Ok(instr.to_le_bytes().to_vec())
1466 } else {
1467 self.encode_thumb32_movw(rd, *imm as u32)
1469 }
1470 } else if let Operand2::Reg(rm) = op2 {
1471 let rm_bits = reg_to_bits(rm) as u16;
1472 let d_bit = (rd_bits >> 3) & 1;
1475 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1476 Ok(instr.to_le_bytes().to_vec())
1477 } else {
1478 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1480 }
1481 }
1482
1483 ArmOp::Push { regs } => {
1484 let mut reg_list: u16 = 0;
1488 let mut need_32bit = false;
1489 for r in regs {
1490 let bit = reg_to_bits(r);
1491 if bit >= 8 && *r != Reg::LR {
1492 need_32bit = true;
1493 }
1494 reg_list |= 1 << bit;
1495 }
1496 if !need_32bit {
1497 let m_bit = if reg_list & (1 << 14) != 0 {
1499 1u16
1500 } else {
1501 0u16
1502 };
1503 let low_regs = reg_list & 0xFF;
1504 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1505 Ok(instr.to_le_bytes().to_vec())
1506 } else {
1507 let hw1: u16 = 0xE92D;
1509 let hw2: u16 = reg_list;
1510 let mut bytes = hw1.to_le_bytes().to_vec();
1511 bytes.extend_from_slice(&hw2.to_le_bytes());
1512 Ok(bytes)
1513 }
1514 }
1515
1516 ArmOp::Pop { regs } => {
1517 let mut reg_list: u16 = 0;
1521 let mut need_32bit = false;
1522 for r in regs {
1523 let bit = reg_to_bits(r);
1524 if bit >= 8 && *r != Reg::PC {
1525 need_32bit = true;
1526 }
1527 reg_list |= 1 << bit;
1528 }
1529 if !need_32bit {
1530 let p_bit = if reg_list & (1 << 15) != 0 {
1532 1u16
1533 } else {
1534 0u16
1535 };
1536 let low_regs = reg_list & 0xFF;
1537 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1538 Ok(instr.to_le_bytes().to_vec())
1539 } else {
1540 let hw1: u16 = 0xE8BD;
1542 let hw2: u16 = reg_list;
1543 let mut bytes = hw1.to_le_bytes().to_vec();
1544 bytes.extend_from_slice(&hw2.to_le_bytes());
1545 Ok(bytes)
1546 }
1547 }
1548
1549 ArmOp::Nop => {
1550 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1552 }
1553
1554 ArmOp::Udf { imm } => {
1555 let instr: u16 = 0xDE00 | (*imm as u16);
1558 let bytes = instr.to_le_bytes().to_vec();
1559 encoding_contracts::verify_thumb16(&bytes);
1560 Ok(bytes)
1561 }
1562
1563 ArmOp::Adds { rd, rn, op2 } => {
1566 let rd_bits = reg_to_bits(rd) as u16;
1567 let rn_bits = reg_to_bits(rn) as u16;
1568
1569 if let Operand2::Reg(rm) = op2 {
1570 let rm_bits = reg_to_bits(rm) as u16;
1571 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1576 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1578 Ok(instr.to_le_bytes().to_vec())
1579 } else {
1580 self.encode_thumb32_adds_reg_raw(
1581 rd_bits as u32,
1582 rn_bits as u32,
1583 rm_bits as u32,
1584 )
1585 }
1586 } else {
1587 self.encode_thumb32_adds(rd, rn, 0)
1589 }
1590 }
1591
1592 ArmOp::Adc { rd, rn, op2 } => {
1595 let rd_bits = reg_to_bits(rd);
1596 let rn_bits = reg_to_bits(rn);
1597
1598 if let Operand2::Reg(rm) = op2 {
1599 let rm_bits = reg_to_bits(rm);
1600 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1602 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1603
1604 let mut bytes = hw1.to_le_bytes().to_vec();
1605 bytes.extend_from_slice(&hw2.to_le_bytes());
1606 Ok(bytes)
1607 } else {
1608 let hw1: u16 = (0xF140 | rn_bits) as u16;
1610 let hw2: u16 = (rd_bits << 8) as u16;
1611 let mut bytes = hw1.to_le_bytes().to_vec();
1612 bytes.extend_from_slice(&hw2.to_le_bytes());
1613 Ok(bytes)
1614 }
1615 }
1616
1617 ArmOp::Subs { rd, rn, op2 } => {
1619 let rd_bits = reg_to_bits(rd) as u16;
1620 let rn_bits = reg_to_bits(rn) as u16;
1621
1622 if let Operand2::Reg(rm) = op2 {
1623 let rm_bits = reg_to_bits(rm) as u16;
1624 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1628 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1630 Ok(instr.to_le_bytes().to_vec())
1631 } else {
1632 self.encode_thumb32_subs_reg_raw(
1633 rd_bits as u32,
1634 rn_bits as u32,
1635 rm_bits as u32,
1636 )
1637 }
1638 } else {
1639 self.encode_thumb32_subs(rd, rn, 0)
1641 }
1642 }
1643
1644 ArmOp::Sbc { rd, rn, op2 } => {
1647 let rd_bits = reg_to_bits(rd);
1648 let rn_bits = reg_to_bits(rn);
1649
1650 if let Operand2::Reg(rm) = op2 {
1651 let rm_bits = reg_to_bits(rm);
1652 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1654 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1655
1656 let mut bytes = hw1.to_le_bytes().to_vec();
1657 bytes.extend_from_slice(&hw2.to_le_bytes());
1658 Ok(bytes)
1659 } else {
1660 let hw1: u16 = (0xF160 | rn_bits) as u16;
1662 let hw2: u16 = (rd_bits << 8) as u16;
1663 let mut bytes = hw1.to_le_bytes().to_vec();
1664 bytes.extend_from_slice(&hw2.to_le_bytes());
1665 Ok(bytes)
1666 }
1667 }
1668
1669 ArmOp::Sdiv { rd, rn, rm } => {
1673 let rd_bits = reg_to_bits(rd);
1674 let rn_bits = reg_to_bits(rn);
1675 let rm_bits = reg_to_bits(rm);
1676 reg_bits_checked(rd_bits)?;
1677 reg_bits_checked(rn_bits)?;
1678 reg_bits_checked(rm_bits)?;
1679
1680 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1684 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1685
1686 let mut bytes = hw1.to_le_bytes().to_vec();
1688 bytes.extend_from_slice(&hw2.to_le_bytes());
1689 encoding_contracts::verify_thumb32(&bytes);
1690 Ok(bytes)
1691 }
1692
1693 ArmOp::Udiv { rd, rn, rm } => {
1695 let rd_bits = reg_to_bits(rd);
1696 let rn_bits = reg_to_bits(rn);
1697 let rm_bits = reg_to_bits(rm);
1698 reg_bits_checked(rd_bits)?;
1699 reg_bits_checked(rn_bits)?;
1700 reg_bits_checked(rm_bits)?;
1701
1702 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1704 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1705
1706 let mut bytes = hw1.to_le_bytes().to_vec();
1707 bytes.extend_from_slice(&hw2.to_le_bytes());
1708 encoding_contracts::verify_thumb32(&bytes);
1709 Ok(bytes)
1710 }
1711
1712 ArmOp::Mul { rd, rn, rm } => {
1714 let rd_bits = reg_to_bits(rd);
1715 let rn_bits = reg_to_bits(rn);
1716 let rm_bits = reg_to_bits(rm);
1717
1718 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1721 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1722
1723 let mut bytes = hw1.to_le_bytes().to_vec();
1724 bytes.extend_from_slice(&hw2.to_le_bytes());
1725 Ok(bytes)
1726 }
1727
1728 ArmOp::Mls { rd, rn, rm, ra } => {
1730 let rd_bits = reg_to_bits(rd);
1731 let rn_bits = reg_to_bits(rn);
1732 let rm_bits = reg_to_bits(rm);
1733 let ra_bits = reg_to_bits(ra);
1734
1735 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1738 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1739
1740 let mut bytes = hw1.to_le_bytes().to_vec();
1741 bytes.extend_from_slice(&hw2.to_le_bytes());
1742 Ok(bytes)
1743 }
1744
1745 ArmOp::And { rd, rn, op2 } => {
1747 if let Operand2::Reg(rm) = op2 {
1748 let rd_bits = reg_to_bits(rd);
1749 let rn_bits = reg_to_bits(rn);
1750 let rm_bits = reg_to_bits(rm);
1751
1752 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1754 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1755
1756 let mut bytes = hw1.to_le_bytes().to_vec();
1757 bytes.extend_from_slice(&hw2.to_le_bytes());
1758 Ok(bytes)
1759 } else if let Operand2::Imm(imm) = op2 {
1760 let rd_bits = reg_to_bits(rd);
1761 let rn_bits = reg_to_bits(rn);
1762 let imm_val = *imm as u32;
1763
1764 let i_bit = (imm_val >> 11) & 1;
1766 let imm3 = (imm_val >> 8) & 0x7;
1767 let imm8 = imm_val & 0xFF;
1768
1769 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1770 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1771
1772 let mut bytes = hw1.to_le_bytes().to_vec();
1773 bytes.extend_from_slice(&hw2.to_le_bytes());
1774 Ok(bytes)
1775 } else {
1776 let instr: u16 = 0xBF00;
1778 Ok(instr.to_le_bytes().to_vec())
1779 }
1780 }
1781
1782 ArmOp::Orr { rd, rn, op2 } => {
1784 if let Operand2::Reg(rm) = op2 {
1785 let rd_bits = reg_to_bits(rd);
1786 let rn_bits = reg_to_bits(rn);
1787 let rm_bits = reg_to_bits(rm);
1788
1789 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1791 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1792
1793 let mut bytes = hw1.to_le_bytes().to_vec();
1794 bytes.extend_from_slice(&hw2.to_le_bytes());
1795 Ok(bytes)
1796 } else {
1797 let instr: u16 = 0xBF00;
1798 Ok(instr.to_le_bytes().to_vec())
1799 }
1800 }
1801
1802 ArmOp::Eor { rd, rn, op2 } => {
1804 if let Operand2::Reg(rm) = op2 {
1805 let rd_bits = reg_to_bits(rd);
1806 let rn_bits = reg_to_bits(rn);
1807 let rm_bits = reg_to_bits(rm);
1808
1809 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1811 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1812
1813 let mut bytes = hw1.to_le_bytes().to_vec();
1814 bytes.extend_from_slice(&hw2.to_le_bytes());
1815 Ok(bytes)
1816 } else {
1817 let instr: u16 = 0xBF00;
1818 Ok(instr.to_le_bytes().to_vec())
1819 }
1820 }
1821
1822 ArmOp::Lsl { rd, rn, shift } => {
1824 let rd_bits = reg_to_bits(rd) as u16;
1825 let rn_bits = reg_to_bits(rn) as u16;
1826 let shift_bits = (*shift as u16) & 0x1F;
1827
1828 if rd_bits < 8 && rn_bits < 8 {
1829 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1831 Ok(instr.to_le_bytes().to_vec())
1832 } else {
1833 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1836 }
1837
1838 ArmOp::Lsr { rd, rn, shift } => {
1839 let rd_bits = reg_to_bits(rd) as u16;
1840 let rn_bits = reg_to_bits(rn) as u16;
1841 let shift_bits = (*shift as u16) & 0x1F;
1842
1843 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1844 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1846 Ok(instr.to_le_bytes().to_vec())
1847 } else {
1848 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
1850 }
1851
1852 ArmOp::Asr { rd, rn, shift } => {
1853 let rd_bits = reg_to_bits(rd) as u16;
1854 let rn_bits = reg_to_bits(rn) as u16;
1855 let shift_bits = (*shift as u16) & 0x1F;
1856
1857 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1858 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1860 Ok(instr.to_le_bytes().to_vec())
1861 } else {
1862 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
1864 }
1865
1866 ArmOp::Ror { rd, rn, shift } => {
1867 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
1870
1871 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
1875 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
1876 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
1877 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
1878
1879 ArmOp::Rsb { rd, rn, imm } => {
1882 let rd_bits = reg_to_bits(rd);
1883 let rn_bits = reg_to_bits(rn);
1884 let imm_val = *imm;
1885
1886 let i_bit = (imm_val >> 11) & 1;
1887 let imm3 = (imm_val >> 8) & 0x7;
1888 let imm8 = imm_val & 0xFF;
1889
1890 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
1892 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1894
1895 let mut bytes = hw1.to_le_bytes().to_vec();
1896 bytes.extend_from_slice(&hw2.to_le_bytes());
1897 Ok(bytes)
1898 }
1899
1900 ArmOp::Clz { rd, rm } => {
1902 let rd_bits = reg_to_bits(rd);
1903 let rm_bits = reg_to_bits(rm);
1904
1905 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
1908 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
1909
1910 let mut bytes = hw1.to_le_bytes().to_vec();
1911 bytes.extend_from_slice(&hw2.to_le_bytes());
1912 Ok(bytes)
1913 }
1914
1915 ArmOp::Rbit { rd, rm } => {
1917 let rd_bits = reg_to_bits(rd);
1918 let rm_bits = reg_to_bits(rm);
1919
1920 let hw1: u16 = (0xFA90 | rm_bits) as u16;
1923 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
1924
1925 let mut bytes = hw1.to_le_bytes().to_vec();
1926 bytes.extend_from_slice(&hw2.to_le_bytes());
1927 Ok(bytes)
1928 }
1929
1930 ArmOp::Sxtb { rd, rm } => {
1932 let rd_bits = reg_to_bits(rd) as u16;
1933 let rm_bits = reg_to_bits(rm) as u16;
1934
1935 if rd_bits < 8 && rm_bits < 8 {
1936 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
1938 Ok(instr.to_le_bytes().to_vec())
1939 } else {
1940 let rd_bits32 = rd_bits as u32;
1943 let rm_bits32 = rm_bits as u32;
1944 let hw1: u16 = 0xFA4F;
1945 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
1946 let mut bytes = hw1.to_le_bytes().to_vec();
1947 bytes.extend_from_slice(&hw2.to_le_bytes());
1948 Ok(bytes)
1949 }
1950 }
1951
1952 ArmOp::Sxth { rd, rm } => {
1954 let rd_bits = reg_to_bits(rd) as u16;
1955 let rm_bits = reg_to_bits(rm) as u16;
1956
1957 if rd_bits < 8 && rm_bits < 8 {
1958 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
1960 Ok(instr.to_le_bytes().to_vec())
1961 } else {
1962 let rd_bits32 = rd_bits as u32;
1965 let rm_bits32 = rm_bits as u32;
1966 let hw1: u16 = 0xFA0F;
1967 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
1968 let mut bytes = hw1.to_le_bytes().to_vec();
1969 bytes.extend_from_slice(&hw2.to_le_bytes());
1970 Ok(bytes)
1971 }
1972 }
1973
1974 ArmOp::Cmp { rn, op2 } => {
1976 let rn_bits = reg_to_bits(rn) as u16;
1977
1978 if let Operand2::Imm(imm) = op2 {
1979 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
1982 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
1984 Ok(instr.to_le_bytes().to_vec())
1985 } else {
1986 self.encode_thumb32_cmp_imm(rn, *imm as u32)
1987 }
1988 } else if let Operand2::Reg(rm) = op2 {
1989 let rm_bits = reg_to_bits(rm) as u16;
1990 if rn_bits < 8 && rm_bits < 8 {
1991 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
1993 Ok(instr.to_le_bytes().to_vec())
1994 } else {
1995 let n_bit = (rn_bits >> 3) & 1;
1997 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
1998 Ok(instr.to_le_bytes().to_vec())
1999 }
2000 } else {
2001 let instr: u16 = 0xBF00;
2002 Ok(instr.to_le_bytes().to_vec())
2003 }
2004 }
2005
2006 ArmOp::Cmn { rn, op2 } => {
2009 let rn_bits = reg_to_bits(rn) as u16;
2010
2011 if let Operand2::Imm(imm) = op2 {
2012 if *imm >= 0 && *imm <= 255 {
2015 let imm8 = *imm as u16 & 0xFF;
2016 let hw1: u16 = 0xF110 | rn_bits;
2017 let hw2: u16 = 0x0F00 | imm8;
2018 let mut bytes = hw1.to_le_bytes().to_vec();
2019 bytes.extend_from_slice(&hw2.to_le_bytes());
2020 Ok(bytes)
2021 } else {
2022 Ok(vec![0xBF, 0x00])
2024 }
2025 } else if let Operand2::Reg(rm) = op2 {
2026 let rm_bits = reg_to_bits(rm) as u16;
2027 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2029 Ok(instr.to_le_bytes().to_vec())
2030 } else {
2031 Ok(vec![0xBF, 0x00])
2032 }
2033 }
2034
2035 ArmOp::Ldr { rd, addr } => {
2037 let rd_bits = reg_to_bits(rd);
2038 let base_bits = reg_to_bits(&addr.base);
2039
2040 if let Some(offset_reg) = &addr.offset_reg {
2042 let rm_bits = reg_to_bits(offset_reg);
2043
2044 if addr.offset != 0 {
2046 let scratch = Reg::R12;
2049 let mut bytes =
2050 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2051 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2052 return Ok(bytes);
2053 }
2054
2055 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2058 let instr: u16 = 0x5800
2060 | ((rm_bits as u16) << 6)
2061 | ((base_bits as u16) << 3)
2062 | (rd_bits as u16);
2063 return Ok(instr.to_le_bytes().to_vec());
2064 }
2065
2066 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2068 }
2069
2070 let offset = addr.offset as u32;
2072
2073 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2074 let imm5 = (offset >> 2) as u16;
2076 let instr: u16 =
2077 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2078 Ok(instr.to_le_bytes().to_vec())
2079 } else {
2080 self.encode_thumb32_ldr(rd, &addr.base, offset)
2081 }
2082 }
2083
2084 ArmOp::Str { rd, addr } => {
2086 let rd_bits = reg_to_bits(rd);
2087 let base_bits = reg_to_bits(&addr.base);
2088
2089 if let Some(offset_reg) = &addr.offset_reg {
2091 let rm_bits = reg_to_bits(offset_reg);
2092
2093 if addr.offset != 0 {
2095 let scratch = Reg::R12;
2098 let mut bytes =
2099 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2100 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2101 return Ok(bytes);
2102 }
2103
2104 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2107 let instr: u16 = 0x5000
2109 | ((rm_bits as u16) << 6)
2110 | ((base_bits as u16) << 3)
2111 | (rd_bits as u16);
2112 return Ok(instr.to_le_bytes().to_vec());
2113 }
2114
2115 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2117 }
2118
2119 let offset = addr.offset as u32;
2121
2122 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2123 let imm5 = (offset >> 2) as u16;
2125 let instr: u16 =
2126 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2127 Ok(instr.to_le_bytes().to_vec())
2128 } else {
2129 self.encode_thumb32_str(rd, &addr.base, offset)
2130 }
2131 }
2132
2133 ArmOp::Ldrb { rd, addr } => {
2135 let rd_bits = reg_to_bits(rd);
2136 let base_bits = reg_to_bits(&addr.base);
2137
2138 if let Some(offset_reg) = &addr.offset_reg {
2139 if addr.offset != 0 {
2140 let scratch = Reg::R12;
2141 let mut bytes =
2142 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2143 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2144 return Ok(bytes);
2145 }
2146 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2147 }
2148
2149 let offset = addr.offset as u32;
2150 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2151 let instr: u16 = 0x7800
2153 | ((offset as u16) << 6)
2154 | ((base_bits as u16) << 3)
2155 | (rd_bits as u16);
2156 Ok(instr.to_le_bytes().to_vec())
2157 } else {
2158 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2159 }
2160 }
2161
2162 ArmOp::Ldrsb { rd, addr } => {
2164 let rd_bits = reg_to_bits(rd);
2165 let base_bits = reg_to_bits(&addr.base);
2166
2167 if let Some(offset_reg) = &addr.offset_reg {
2168 if addr.offset != 0 {
2169 let scratch = Reg::R12;
2170 let mut bytes =
2171 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2172 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2173 return Ok(bytes);
2174 }
2175 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2176 }
2177
2178 let offset = addr.offset as u32;
2179 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2182 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2184 } else {
2185 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2186 }
2187 }
2188
2189 ArmOp::Ldrh { rd, addr } => {
2191 let rd_bits = reg_to_bits(rd);
2192 let base_bits = reg_to_bits(&addr.base);
2193
2194 if let Some(offset_reg) = &addr.offset_reg {
2195 if addr.offset != 0 {
2196 let scratch = Reg::R12;
2197 let mut bytes =
2198 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2199 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2200 return Ok(bytes);
2201 }
2202 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2203 }
2204
2205 let offset = addr.offset as u32;
2206 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2207 let imm5 = (offset >> 1) as u16;
2209 let instr: u16 =
2210 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2211 Ok(instr.to_le_bytes().to_vec())
2212 } else {
2213 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2214 }
2215 }
2216
2217 ArmOp::Ldrsh { rd, addr } => {
2219 if let Some(offset_reg) = &addr.offset_reg {
2220 if addr.offset != 0 {
2221 let scratch = Reg::R12;
2222 let mut bytes =
2223 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2224 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2225 return Ok(bytes);
2226 }
2227 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2228 }
2229
2230 let offset = addr.offset as u32;
2231 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2232 }
2233
2234 ArmOp::Strb { rd, addr } => {
2236 let rd_bits = reg_to_bits(rd);
2237 let base_bits = reg_to_bits(&addr.base);
2238
2239 if let Some(offset_reg) = &addr.offset_reg {
2240 if addr.offset != 0 {
2241 let scratch = Reg::R12;
2242 let mut bytes =
2243 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2244 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2245 return Ok(bytes);
2246 }
2247 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2248 }
2249
2250 let offset = addr.offset as u32;
2251 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2252 let instr: u16 = 0x7000
2254 | ((offset as u16) << 6)
2255 | ((base_bits as u16) << 3)
2256 | (rd_bits as u16);
2257 Ok(instr.to_le_bytes().to_vec())
2258 } else {
2259 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2260 }
2261 }
2262
2263 ArmOp::Strh { rd, addr } => {
2265 let rd_bits = reg_to_bits(rd);
2266 let base_bits = reg_to_bits(&addr.base);
2267
2268 if let Some(offset_reg) = &addr.offset_reg {
2269 if addr.offset != 0 {
2270 let scratch = Reg::R12;
2271 let mut bytes =
2272 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2273 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2274 return Ok(bytes);
2275 }
2276 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2277 }
2278
2279 let offset = addr.offset as u32;
2280 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2281 let imm5 = (offset >> 1) as u16;
2283 let instr: u16 =
2284 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2285 Ok(instr.to_le_bytes().to_vec())
2286 } else {
2287 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2288 }
2289 }
2290
2291 ArmOp::MemorySize { rd } => {
2293 let rd_bits = reg_to_bits(rd);
2296 let r10_bits = reg_to_bits(&Reg::R10);
2297 if rd_bits < 8 && r10_bits < 8 {
2298 let instr: u16 =
2299 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2300 Ok(instr.to_le_bytes().to_vec())
2301 } else {
2302 let imm5: u32 = 16;
2304 let imm3 = (imm5 >> 2) & 0x7;
2305 let imm2 = imm5 & 0x3;
2306 let hw1: u16 = 0xEA4F;
2307 let hw2: u16 =
2308 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2309 let mut bytes = hw1.to_le_bytes().to_vec();
2310 bytes.extend_from_slice(&hw2.to_le_bytes());
2311 Ok(bytes)
2312 }
2313 }
2314
2315 ArmOp::MemoryGrow { rd, .. } => {
2317 let rd_bits = reg_to_bits(rd);
2321 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2324 bytes.extend_from_slice(&hw2.to_le_bytes());
2325 Ok(bytes)
2326 }
2327
2328 ArmOp::Bx { rm } => {
2330 let rm_bits = reg_to_bits(rm) as u16;
2331 let instr: u16 = 0x4700 | (rm_bits << 3);
2333 Ok(instr.to_le_bytes().to_vec())
2334 }
2335
2336 ArmOp::Blx { rm } => {
2339 let rm_bits = reg_to_bits(rm) as u16;
2340 let instr: u16 = 0x4780 | (rm_bits << 3);
2341 Ok(instr.to_le_bytes().to_vec())
2342 }
2343
2344 ArmOp::CallIndirect {
2348 rd: _,
2349 type_idx: _,
2350 table_index_reg,
2351 } => {
2352 let idx_reg = reg_to_bits(table_index_reg);
2353 let mut bytes = Vec::new();
2354
2355 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2371 bytes.extend_from_slice(&hw1.to_le_bytes());
2372 bytes.extend_from_slice(&hw2.to_le_bytes());
2373
2374 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2380 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2381
2382 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2386
2387 Ok(bytes)
2388 }
2389
2390 ArmOp::Label { .. } => Ok(Vec::new()),
2392
2393 ArmOp::Bcc { cond, label: _ } => {
2395 use synth_synthesis::Condition;
2396 let cond_bits: u16 = match cond {
2397 Condition::EQ => 0x0,
2398 Condition::NE => 0x1,
2399 Condition::HS => 0x2,
2400 Condition::LO => 0x3,
2401 Condition::HI => 0x8,
2402 Condition::LS => 0x9,
2403 Condition::GE => 0xA,
2404 Condition::LT => 0xB,
2405 Condition::GT => 0xC,
2406 Condition::LE => 0xD,
2407 };
2408 let instr: u16 = 0xD000 | (cond_bits << 8);
2410 Ok(instr.to_le_bytes().to_vec())
2411 }
2412
2413 ArmOp::B { label: _ } => {
2415 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2419 }
2420
2421 ArmOp::Bhs { label: _ } => {
2424 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2428 }
2429
2430 ArmOp::Blo { label: _ } => {
2433 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2437 }
2438
2439 ArmOp::BOffset { offset } => {
2442 let halfword_offset = *offset;
2445
2446 if (-1024..=1022).contains(&halfword_offset) {
2449 let imm11 = (halfword_offset as u16) & 0x7FF;
2451 let instr: u16 = 0xE000 | imm11;
2452 Ok(instr.to_le_bytes().to_vec())
2453 } else {
2454 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2470 let uoffset = signed_offset as u32;
2471 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;
2479 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2480
2481 let mut bytes = hw1.to_le_bytes().to_vec();
2482 bytes.extend_from_slice(&hw2.to_le_bytes());
2483 Ok(bytes)
2484 }
2485 }
2486
2487 ArmOp::BCondOffset { cond, offset } => {
2489 use synth_synthesis::Condition;
2490 let cond_bits: u16 = match cond {
2491 Condition::EQ => 0x0,
2492 Condition::NE => 0x1,
2493 Condition::HS => 0x2,
2494 Condition::LO => 0x3,
2495 Condition::HI => 0x8,
2496 Condition::LS => 0x9,
2497 Condition::GE => 0xA,
2498 Condition::LT => 0xB,
2499 Condition::GT => 0xC,
2500 Condition::LE => 0xD,
2501 };
2502
2503 let halfword_offset = *offset;
2506
2507 if (-128..=127).contains(&halfword_offset) {
2510 let imm8 = (halfword_offset as u16) & 0xFF;
2511 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2512 Ok(instr.to_le_bytes().to_vec())
2513 } else {
2514 let offset = halfword_offset >> 1;
2518 let s = if offset < 0 { 1u32 } else { 0u32 };
2519 let imm6 = ((offset >> 11) as u32) & 0x3F;
2520 let imm11 = (offset as u32) & 0x7FF;
2521 let j1 = if s == 1 { 1 } else { 0 };
2522 let j2 = if s == 1 { 1 } else { 0 };
2523
2524 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2525 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2526
2527 let mut bytes = hw1.to_le_bytes().to_vec();
2528 bytes.extend_from_slice(&hw2.to_le_bytes());
2529 Ok(bytes)
2530 }
2531 }
2532
2533 ArmOp::Bl { label: _ } => {
2534 let hw1: u16 = 0xF7FF;
2549 let hw2: u16 = 0xFFFE;
2550 let mut bytes = hw1.to_le_bytes().to_vec();
2551 bytes.extend_from_slice(&hw2.to_le_bytes());
2552 Ok(bytes)
2553 }
2554
2555 ArmOp::Mvn { rd, op2 } => {
2557 if let Operand2::Reg(rm) = op2 {
2558 let rd_bits = reg_to_bits(rd) as u16;
2559 let rm_bits = reg_to_bits(rm) as u16;
2560
2561 if rd_bits < 8 && rm_bits < 8 {
2562 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2564 Ok(instr.to_le_bytes().to_vec())
2565 } else {
2566 let hw1: u16 = 0xEA6F_u16;
2568 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2569 let mut bytes = hw1.to_le_bytes().to_vec();
2570 bytes.extend_from_slice(&hw2.to_le_bytes());
2571 Ok(bytes)
2572 }
2573 } else {
2574 let instr: u16 = 0xBF00;
2575 Ok(instr.to_le_bytes().to_vec())
2576 }
2577 }
2578
2579 ArmOp::Movw { rd, imm16 } => {
2581 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2582 }
2583
2584 ArmOp::Movt { rd, imm16 } => {
2586 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2587 }
2588
2589 ArmOp::SetCond { rd, cond } => {
2595 let rd_bits = reg_to_bits(rd) as u16;
2596
2597 use synth_synthesis::Condition;
2599 let cond_bits: u16 = match cond {
2600 Condition::EQ => 0x0,
2601 Condition::NE => 0x1,
2602 Condition::LT => 0xB,
2603 Condition::LE => 0xD,
2604 Condition::GT => 0xC,
2605 Condition::GE => 0xA,
2606 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2611
2612 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2617 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2618
2619 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2621
2622 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2624
2625 let mut bytes = ite_instr.to_le_bytes().to_vec();
2627 bytes.extend_from_slice(&mov_one.to_le_bytes());
2628 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2629 Ok(bytes)
2630 }
2631
2632 ArmOp::I64SetCond {
2637 rd,
2638 rn_lo,
2639 rn_hi,
2640 rm_lo,
2641 rm_hi,
2642 cond,
2643 } => {
2644 use synth_synthesis::Condition;
2645 let rd_bits = reg_to_bits(rd) as u16;
2646 let mut bytes = Vec::new();
2647
2648 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2650 rm: &synth_synthesis::Reg|
2651 -> Vec<u8> {
2652 let rn_bits = reg_to_bits(rn) as u16;
2653 let rm_bits = reg_to_bits(rm) as u16;
2654 if rn_bits < 8 && rm_bits < 8 {
2655 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2656 instr.to_le_bytes().to_vec()
2657 } else {
2658 let n_bit = (rn_bits >> 3) & 1;
2659 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2660 instr.to_le_bytes().to_vec()
2661 }
2662 };
2663
2664 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2666 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2667 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2668 ite_instr.to_le_bytes().to_vec()
2669 };
2670
2671 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2673 let mut b = encode_ite(cond_bits);
2674 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2675 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2676 b.extend_from_slice(&mov_one.to_le_bytes());
2677 b.extend_from_slice(&mov_zero.to_le_bytes());
2678 b
2679 };
2680
2681 match cond {
2682 Condition::EQ | Condition::NE => {
2683 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2685
2686 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2689
2690 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2692
2693 let cond_bits: u16 = match cond {
2695 Condition::EQ => 0x0,
2696 Condition::NE => 0x1,
2697 _ => unreachable!(),
2698 };
2699 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2700 }
2701
2702 Condition::LT => {
2703 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2705
2706 let rn_hi_bits = reg_to_bits(rn_hi);
2709 let rm_hi_bits = reg_to_bits(rm_hi);
2710 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2711 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2712 bytes.extend_from_slice(&hw1.to_le_bytes());
2713 bytes.extend_from_slice(&hw2.to_le_bytes());
2714
2715 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2718
2719 Condition::GT => {
2720 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2723
2724 let rm_hi_bits = reg_to_bits(rm_hi);
2726 let rn_hi_bits = reg_to_bits(rn_hi);
2727 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2728 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2729 bytes.extend_from_slice(&hw1.to_le_bytes());
2730 bytes.extend_from_slice(&hw2.to_le_bytes());
2731
2732 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2735
2736 Condition::LE => {
2737 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2741
2742 let rm_hi_bits = reg_to_bits(rm_hi);
2744 let rn_hi_bits = reg_to_bits(rn_hi);
2745 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2746 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2747 bytes.extend_from_slice(&hw1.to_le_bytes());
2748 bytes.extend_from_slice(&hw2.to_le_bytes());
2749
2750 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2753
2754 Condition::GE => {
2755 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2758
2759 let rn_hi_bits = reg_to_bits(rn_hi);
2761 let rm_hi_bits = reg_to_bits(rm_hi);
2762 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2763 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2764 bytes.extend_from_slice(&hw1.to_le_bytes());
2765 bytes.extend_from_slice(&hw2.to_le_bytes());
2766
2767 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2770
2771 Condition::LO => {
2773 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2775 let rn_hi_bits = reg_to_bits(rn_hi);
2776 let rm_hi_bits = reg_to_bits(rm_hi);
2777 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2778 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2779 bytes.extend_from_slice(&hw1.to_le_bytes());
2780 bytes.extend_from_slice(&hw2.to_le_bytes());
2781 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2783
2784 Condition::HI => {
2785 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2787 let rm_hi_bits = reg_to_bits(rm_hi);
2788 let rn_hi_bits = reg_to_bits(rn_hi);
2789 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2790 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2791 bytes.extend_from_slice(&hw1.to_le_bytes());
2792 bytes.extend_from_slice(&hw2.to_le_bytes());
2793 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2795
2796 Condition::LS => {
2797 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2799 let rm_hi_bits = reg_to_bits(rm_hi);
2800 let rn_hi_bits = reg_to_bits(rn_hi);
2801 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2802 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2803 bytes.extend_from_slice(&hw1.to_le_bytes());
2804 bytes.extend_from_slice(&hw2.to_le_bytes());
2805 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2807
2808 Condition::HS => {
2809 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2811 let rn_hi_bits = reg_to_bits(rn_hi);
2812 let rm_hi_bits = reg_to_bits(rm_hi);
2813 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2814 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2815 bytes.extend_from_slice(&hw1.to_le_bytes());
2816 bytes.extend_from_slice(&hw2.to_le_bytes());
2817 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2819 }
2820
2821 Ok(bytes)
2822 }
2823
2824 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2827 let rd_bits = reg_to_bits(rd);
2828 let rn_lo_bits = reg_to_bits(rn_lo);
2829 let rn_hi_bits = reg_to_bits(rn_hi);
2830 let mut bytes = Vec::new();
2831
2832 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2834 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2835 bytes.extend_from_slice(&hw1.to_le_bytes());
2836 bytes.extend_from_slice(&hw2.to_le_bytes());
2837
2838 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2840 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2841
2842 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2845 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2846 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2847 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2848 bytes.extend_from_slice(&mov_one.to_le_bytes());
2849 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2850
2851 Ok(bytes)
2852 }
2853
2854 ArmOp::I64Mul {
2858 rd_lo,
2859 rd_hi,
2860 rn_lo,
2861 rn_hi,
2862 rm_lo,
2863 rm_hi,
2864 } => {
2865 let rd_lo_bits = reg_to_bits(rd_lo);
2866 let rd_hi_bits = reg_to_bits(rd_hi);
2867 let rn_lo_bits = reg_to_bits(rn_lo);
2868 let rn_hi_bits = reg_to_bits(rn_hi);
2869 let rm_lo_bits = reg_to_bits(rm_lo);
2870 let rm_hi_bits = reg_to_bits(rm_hi);
2871 let r12: u32 = 12; let mut bytes = Vec::new();
2873
2874 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2877 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2878 bytes.extend_from_slice(&hw1.to_le_bytes());
2879 bytes.extend_from_slice(&hw2.to_le_bytes());
2880
2881 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2884 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
2885 bytes.extend_from_slice(&hw1.to_le_bytes());
2886 bytes.extend_from_slice(&hw2.to_le_bytes());
2887
2888 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
2891 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2892 bytes.extend_from_slice(&hw1.to_le_bytes());
2893 bytes.extend_from_slice(&hw2.to_le_bytes());
2894
2895 let d_bit = (rd_hi_bits >> 3) & 1;
2898 let add_instr: u16 =
2899 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
2900 bytes.extend_from_slice(&add_instr.to_le_bytes());
2901
2902 Ok(bytes)
2903 }
2904
2905 ArmOp::I64Shl {
2908 rd_lo,
2909 rd_hi,
2910 rn_lo,
2911 rn_hi,
2912 rm_lo,
2913 rm_hi,
2914 } => {
2915 let rd_lo_bits = reg_to_bits(rd_lo);
2916 let rd_hi_bits = reg_to_bits(rd_hi);
2917 let rn_lo_bits = reg_to_bits(rn_lo);
2918 let rn_hi_bits = reg_to_bits(rn_hi);
2919 let rm_lo_bits = reg_to_bits(rm_lo);
2920 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2922
2923 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2925 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2926 bytes.extend_from_slice(&hw1.to_le_bytes());
2927 bytes.extend_from_slice(&hw2.to_le_bytes());
2928
2929 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2931 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2932 bytes.extend_from_slice(&hw1.to_le_bytes());
2933 bytes.extend_from_slice(&hw2.to_le_bytes());
2934
2935 let bpl: u16 = 0xD50A;
2937 bytes.extend_from_slice(&bpl.to_le_bytes());
2938
2939 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2942 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2943 bytes.extend_from_slice(&hw1.to_le_bytes());
2944 bytes.extend_from_slice(&hw2.to_le_bytes());
2945
2946 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2948 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2949 bytes.extend_from_slice(&hw1.to_le_bytes());
2950 bytes.extend_from_slice(&hw2.to_le_bytes());
2951
2952 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2954 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2955 bytes.extend_from_slice(&hw1.to_le_bytes());
2956 bytes.extend_from_slice(&hw2.to_le_bytes());
2957
2958 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
2960 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
2961 bytes.extend_from_slice(&hw1.to_le_bytes());
2962 bytes.extend_from_slice(&hw2.to_le_bytes());
2963
2964 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2966 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2967 bytes.extend_from_slice(&hw1.to_le_bytes());
2968 bytes.extend_from_slice(&hw2.to_le_bytes());
2969
2970 let b_done: u16 = 0xE002;
2972 bytes.extend_from_slice(&b_done.to_le_bytes());
2973
2974 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2977 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
2978 bytes.extend_from_slice(&hw1.to_le_bytes());
2979 bytes.extend_from_slice(&hw2.to_le_bytes());
2980
2981 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
2983 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2984
2985 Ok(bytes) }
2987
2988 ArmOp::I64ShrU {
2990 rd_lo,
2991 rd_hi,
2992 rn_lo,
2993 rn_hi,
2994 rm_lo,
2995 rm_hi,
2996 } => {
2997 let rd_lo_bits = reg_to_bits(rd_lo);
2998 let rd_hi_bits = reg_to_bits(rd_hi);
2999 let rn_lo_bits = reg_to_bits(rn_lo);
3000 let rn_hi_bits = reg_to_bits(rn_hi);
3001 let rm_lo_bits = reg_to_bits(rm_lo);
3002 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3004
3005 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3007 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3008 bytes.extend_from_slice(&hw1.to_le_bytes());
3009 bytes.extend_from_slice(&hw2.to_le_bytes());
3010
3011 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3013 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3014 bytes.extend_from_slice(&hw1.to_le_bytes());
3015 bytes.extend_from_slice(&hw2.to_le_bytes());
3016
3017 let bpl: u16 = 0xD50A;
3019 bytes.extend_from_slice(&bpl.to_le_bytes());
3020
3021 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3024 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3025 bytes.extend_from_slice(&hw1.to_le_bytes());
3026 bytes.extend_from_slice(&hw2.to_le_bytes());
3027
3028 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3030 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3031 bytes.extend_from_slice(&hw1.to_le_bytes());
3032 bytes.extend_from_slice(&hw2.to_le_bytes());
3033
3034 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3036 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3037 bytes.extend_from_slice(&hw1.to_le_bytes());
3038 bytes.extend_from_slice(&hw2.to_le_bytes());
3039
3040 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3042 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3043 bytes.extend_from_slice(&hw1.to_le_bytes());
3044 bytes.extend_from_slice(&hw2.to_le_bytes());
3045
3046 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3048 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3049 bytes.extend_from_slice(&hw1.to_le_bytes());
3050 bytes.extend_from_slice(&hw2.to_le_bytes());
3051
3052 let b_done: u16 = 0xE002;
3054 bytes.extend_from_slice(&b_done.to_le_bytes());
3055
3056 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3059 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3060 bytes.extend_from_slice(&hw1.to_le_bytes());
3061 bytes.extend_from_slice(&hw2.to_le_bytes());
3062
3063 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3065 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3066
3067 Ok(bytes) }
3069
3070 ArmOp::I64ShrS {
3072 rd_lo,
3073 rd_hi,
3074 rn_lo,
3075 rn_hi,
3076 rm_lo,
3077 rm_hi,
3078 } => {
3079 let rd_lo_bits = reg_to_bits(rd_lo);
3080 let rd_hi_bits = reg_to_bits(rd_hi);
3081 let rn_lo_bits = reg_to_bits(rn_lo);
3082 let rn_hi_bits = reg_to_bits(rn_hi);
3083 let rm_lo_bits = reg_to_bits(rm_lo);
3084 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3086
3087 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3089 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3090 bytes.extend_from_slice(&hw1.to_le_bytes());
3091 bytes.extend_from_slice(&hw2.to_le_bytes());
3092
3093 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3095 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3096 bytes.extend_from_slice(&hw1.to_le_bytes());
3097 bytes.extend_from_slice(&hw2.to_le_bytes());
3098
3099 let bpl: u16 = 0xD50A;
3101 bytes.extend_from_slice(&bpl.to_le_bytes());
3102
3103 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3106 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3107 bytes.extend_from_slice(&hw1.to_le_bytes());
3108 bytes.extend_from_slice(&hw2.to_le_bytes());
3109
3110 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3112 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3113 bytes.extend_from_slice(&hw1.to_le_bytes());
3114 bytes.extend_from_slice(&hw2.to_le_bytes());
3115
3116 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3118 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3119 bytes.extend_from_slice(&hw1.to_le_bytes());
3120 bytes.extend_from_slice(&hw2.to_le_bytes());
3121
3122 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3124 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3125 bytes.extend_from_slice(&hw1.to_le_bytes());
3126 bytes.extend_from_slice(&hw2.to_le_bytes());
3127
3128 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3130 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3131 bytes.extend_from_slice(&hw1.to_le_bytes());
3132 bytes.extend_from_slice(&hw2.to_le_bytes());
3133
3134 let b_done: u16 = 0xE003;
3136 bytes.extend_from_slice(&b_done.to_le_bytes());
3137
3138 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3141 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3142 bytes.extend_from_slice(&hw1.to_le_bytes());
3143 bytes.extend_from_slice(&hw2.to_le_bytes());
3144
3145 let hw1: u16 = 0xEA4F;
3149 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3150 bytes.extend_from_slice(&hw1.to_le_bytes());
3151 bytes.extend_from_slice(&hw2.to_le_bytes());
3152
3153 Ok(bytes) }
3155
3156 ArmOp::I64Rotl {
3161 rdlo,
3162 rdhi,
3163 rnlo,
3164 rnhi,
3165 shift,
3166 } => {
3167 let rd_lo_bits = reg_to_bits(rdlo);
3168 let rd_hi_bits = reg_to_bits(rdhi);
3169 let rn_lo_bits = reg_to_bits(rnlo);
3170 let rn_hi_bits = reg_to_bits(rnhi);
3171 let shift_bits = reg_to_bits(shift);
3172 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3176
3177 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3179
3180 let hw1: u16 = (0xF000 | shift_bits) as u16;
3182 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3183 bytes.extend_from_slice(&hw1.to_le_bytes());
3184 bytes.extend_from_slice(&hw2.to_le_bytes());
3185
3186 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3188 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3189 bytes.extend_from_slice(&hw1.to_le_bytes());
3190 bytes.extend_from_slice(&hw2.to_le_bytes());
3191
3192 let bpl: u16 = 0xD50E;
3194 bytes.extend_from_slice(&bpl.to_le_bytes());
3195
3196 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3199 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3200 bytes.extend_from_slice(&hw1.to_le_bytes());
3201 bytes.extend_from_slice(&hw2.to_le_bytes());
3202
3203 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3205 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3206 bytes.extend_from_slice(&hw1.to_le_bytes());
3207 bytes.extend_from_slice(&hw2.to_le_bytes());
3208
3209 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3211 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3212 bytes.extend_from_slice(&hw1.to_le_bytes());
3213 bytes.extend_from_slice(&hw2.to_le_bytes());
3214
3215 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3217 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3218 bytes.extend_from_slice(&hw1.to_le_bytes());
3219 bytes.extend_from_slice(&hw2.to_le_bytes());
3220
3221 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3223 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3224 bytes.extend_from_slice(&hw1.to_le_bytes());
3225 bytes.extend_from_slice(&hw2.to_le_bytes());
3226
3227 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3229 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3230 bytes.extend_from_slice(&hw1.to_le_bytes());
3231 bytes.extend_from_slice(&hw2.to_le_bytes());
3232
3233 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3235 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3236 bytes.extend_from_slice(&hw1.to_le_bytes());
3237 bytes.extend_from_slice(&hw2.to_le_bytes());
3238
3239 let b_done: u16 = 0xE00E;
3241 bytes.extend_from_slice(&b_done.to_le_bytes());
3242
3243 let hw1: u16 = (0xF1C0 | r3) as u16;
3247 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3248 bytes.extend_from_slice(&hw1.to_le_bytes());
3249 bytes.extend_from_slice(&hw2.to_le_bytes());
3250
3251 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3253 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3254 bytes.extend_from_slice(&hw1.to_le_bytes());
3255 bytes.extend_from_slice(&hw2.to_le_bytes());
3256
3257 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3259 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3260 bytes.extend_from_slice(&hw1.to_le_bytes());
3261 bytes.extend_from_slice(&hw2.to_le_bytes());
3262
3263 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3265 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3266 bytes.extend_from_slice(&hw1.to_le_bytes());
3267 bytes.extend_from_slice(&hw2.to_le_bytes());
3268
3269 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3271 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3272 bytes.extend_from_slice(&hw1.to_le_bytes());
3273 bytes.extend_from_slice(&hw2.to_le_bytes());
3274
3275 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3277 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3278 bytes.extend_from_slice(&hw1.to_le_bytes());
3279 bytes.extend_from_slice(&hw2.to_le_bytes());
3280
3281 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3283 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3284 bytes.extend_from_slice(&hw1.to_le_bytes());
3285 bytes.extend_from_slice(&hw2.to_le_bytes());
3286
3287 let d_bit = (rd_hi_bits >> 3) & 1;
3289 let mov_instr: u16 =
3290 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3291 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3292
3293 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3295
3296 Ok(bytes) }
3298
3299 ArmOp::I64Rotr {
3304 rdlo,
3305 rdhi,
3306 rnlo,
3307 rnhi,
3308 shift,
3309 } => {
3310 let rd_lo_bits = reg_to_bits(rdlo);
3311 let rd_hi_bits = reg_to_bits(rdhi);
3312 let rn_lo_bits = reg_to_bits(rnlo);
3313 let rn_hi_bits = reg_to_bits(rnhi);
3314 let shift_bits = reg_to_bits(shift);
3315 let r12: u32 = 12;
3316 let r3: u32 = 3;
3317 let r4: u32 = 4;
3318 let mut bytes = Vec::new();
3319
3320 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3322
3323 let hw1: u16 = (0xF000 | shift_bits) as u16;
3325 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3326 bytes.extend_from_slice(&hw1.to_le_bytes());
3327 bytes.extend_from_slice(&hw2.to_le_bytes());
3328
3329 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3331 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3332 bytes.extend_from_slice(&hw1.to_le_bytes());
3333 bytes.extend_from_slice(&hw2.to_le_bytes());
3334
3335 let bpl: u16 = 0xD50E;
3337 bytes.extend_from_slice(&bpl.to_le_bytes());
3338
3339 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3342 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3343 bytes.extend_from_slice(&hw1.to_le_bytes());
3344 bytes.extend_from_slice(&hw2.to_le_bytes());
3345
3346 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3348 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3349 bytes.extend_from_slice(&hw1.to_le_bytes());
3350 bytes.extend_from_slice(&hw2.to_le_bytes());
3351
3352 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3354 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3355 bytes.extend_from_slice(&hw1.to_le_bytes());
3356 bytes.extend_from_slice(&hw2.to_le_bytes());
3357
3358 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3360 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3361 bytes.extend_from_slice(&hw1.to_le_bytes());
3362 bytes.extend_from_slice(&hw2.to_le_bytes());
3363
3364 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3366 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3367 bytes.extend_from_slice(&hw1.to_le_bytes());
3368 bytes.extend_from_slice(&hw2.to_le_bytes());
3369
3370 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3372 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3373 bytes.extend_from_slice(&hw1.to_le_bytes());
3374 bytes.extend_from_slice(&hw2.to_le_bytes());
3375
3376 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3378 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3379 bytes.extend_from_slice(&hw1.to_le_bytes());
3380 bytes.extend_from_slice(&hw2.to_le_bytes());
3381
3382 let b_done: u16 = 0xE00E;
3384 bytes.extend_from_slice(&b_done.to_le_bytes());
3385
3386 let hw1: u16 = (0xF1C0 | r3) as u16;
3389 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3390 bytes.extend_from_slice(&hw1.to_le_bytes());
3391 bytes.extend_from_slice(&hw2.to_le_bytes());
3392
3393 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3395 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3396 bytes.extend_from_slice(&hw1.to_le_bytes());
3397 bytes.extend_from_slice(&hw2.to_le_bytes());
3398
3399 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3401 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3402 bytes.extend_from_slice(&hw1.to_le_bytes());
3403 bytes.extend_from_slice(&hw2.to_le_bytes());
3404
3405 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3407 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3408 bytes.extend_from_slice(&hw1.to_le_bytes());
3409 bytes.extend_from_slice(&hw2.to_le_bytes());
3410
3411 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3413 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3414 bytes.extend_from_slice(&hw1.to_le_bytes());
3415 bytes.extend_from_slice(&hw2.to_le_bytes());
3416
3417 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3419 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3420 bytes.extend_from_slice(&hw1.to_le_bytes());
3421 bytes.extend_from_slice(&hw2.to_le_bytes());
3422
3423 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3425 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3426 bytes.extend_from_slice(&hw1.to_le_bytes());
3427 bytes.extend_from_slice(&hw2.to_le_bytes());
3428
3429 let d_bit = (rd_lo_bits >> 3) & 1;
3431 let mov_instr: u16 =
3432 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3433 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3434
3435 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3437
3438 Ok(bytes) }
3440
3441 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3455 let rd_bits = reg_to_bits(rd);
3456 let rn_lo_bits = reg_to_bits(rnlo);
3457 let rn_hi_bits = reg_to_bits(rnhi);
3458 let mut bytes = Vec::new();
3459
3460 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3462 let hw2: u16 = 0x0F00;
3463 bytes.extend_from_slice(&hw1.to_le_bytes());
3464 bytes.extend_from_slice(&hw2.to_le_bytes());
3465
3466 let beq: u16 = 0xD003;
3469 bytes.extend_from_slice(&beq.to_le_bytes());
3470
3471 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3474 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3475 bytes.extend_from_slice(&hw1.to_le_bytes());
3476 bytes.extend_from_slice(&hw2.to_le_bytes());
3477
3478 let b_done: u16 = 0xE004;
3481 bytes.extend_from_slice(&b_done.to_le_bytes());
3482
3483 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3485
3486 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3490 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3491 bytes.extend_from_slice(&hw1.to_le_bytes());
3492 bytes.extend_from_slice(&hw2.to_le_bytes());
3493
3494 let hw1: u16 = (0xF100 | rd_bits) as u16;
3496 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3497 bytes.extend_from_slice(&hw1.to_le_bytes());
3498 bytes.extend_from_slice(&hw2.to_le_bytes());
3499
3500 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3504 bytes.extend_from_slice(&mov0.to_le_bytes());
3505
3506 Ok(bytes)
3507 }
3508
3509 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3525 let rd_bits = reg_to_bits(rd);
3526 let rn_lo_bits = reg_to_bits(rnlo);
3527 let rn_hi_bits = reg_to_bits(rnhi);
3528 let mut bytes = Vec::new();
3529
3530 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3532 let hw2: u16 = 0x0F00;
3533 bytes.extend_from_slice(&hw1.to_le_bytes());
3534 bytes.extend_from_slice(&hw2.to_le_bytes());
3535
3536 let beq: u16 = 0xD005;
3539 bytes.extend_from_slice(&beq.to_le_bytes());
3540
3541 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3544 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3545 bytes.extend_from_slice(&hw1.to_le_bytes());
3546 bytes.extend_from_slice(&hw2.to_le_bytes());
3547
3548 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3551 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3552 bytes.extend_from_slice(&hw1.to_le_bytes());
3553 bytes.extend_from_slice(&hw2.to_le_bytes());
3554
3555 let b_done: u16 = 0xE006;
3558 bytes.extend_from_slice(&b_done.to_le_bytes());
3559
3560 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3562
3563 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3567 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3568 bytes.extend_from_slice(&hw1.to_le_bytes());
3569 bytes.extend_from_slice(&hw2.to_le_bytes());
3570
3571 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3574 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3575 bytes.extend_from_slice(&hw1.to_le_bytes());
3576 bytes.extend_from_slice(&hw2.to_le_bytes());
3577
3578 let hw1: u16 = (0xF100 | rd_bits) as u16;
3580 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3581 bytes.extend_from_slice(&hw1.to_le_bytes());
3582 bytes.extend_from_slice(&hw2.to_le_bytes());
3583
3584 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3587 bytes.extend_from_slice(&mov0.to_le_bytes());
3588
3589 Ok(bytes)
3590 }
3591
3592 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3596 let rd_bits = reg_to_bits(rd);
3597 let rn_lo_bits = reg_to_bits(rnlo);
3598 let rn_hi_bits = reg_to_bits(rnhi);
3599 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3602
3603 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3605
3606 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3616 bytes.extend_from_slice(&mov.to_le_bytes());
3617
3618 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3621 bytes.extend_from_slice(&mov.to_le_bytes());
3622
3623 let hw1: u16 = 0xEA4F;
3627 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3628 bytes.extend_from_slice(&hw1.to_le_bytes());
3629 bytes.extend_from_slice(&hw2.to_le_bytes());
3630
3631 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3634 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3635 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3637 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3638
3639 let hw1: u16 = (0xEA00 | r12) as u16;
3641 let hw2: u16 = ((r12 << 8) | r3) 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 = (0xEBA0 | 4) as u16;
3647 let hw2: u16 = ((4 << 8) | r12) as u16;
3648 bytes.extend_from_slice(&hw1.to_le_bytes());
3649 bytes.extend_from_slice(&hw2.to_le_bytes());
3650
3651 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3655 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3656 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3658 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3659
3660 let hw1: u16 = (0xEA00 | 4) as u16;
3662 let hw2: u16 = ((r12 << 8) | r3) as u16;
3663 bytes.extend_from_slice(&hw1.to_le_bytes());
3664 bytes.extend_from_slice(&hw2.to_le_bytes());
3665
3666 let hw1: u16 = 0xEA4F;
3668 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3669 bytes.extend_from_slice(&hw1.to_le_bytes());
3670 bytes.extend_from_slice(&hw2.to_le_bytes());
3671
3672 let hw1: u16 = (0xEA00 | 4) as u16;
3674 let hw2: u16 = ((4 << 8) | r3) as u16;
3675 bytes.extend_from_slice(&hw1.to_le_bytes());
3676 bytes.extend_from_slice(&hw2.to_le_bytes());
3677
3678 let hw1: u16 = (0xEB00 | 4) as u16;
3680 let hw2: u16 = ((4 << 8) | r12) as u16;
3681 bytes.extend_from_slice(&hw1.to_le_bytes());
3682 bytes.extend_from_slice(&hw2.to_le_bytes());
3683
3684 let hw1: u16 = 0xEA4F;
3689 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3690 bytes.extend_from_slice(&hw1.to_le_bytes());
3691 bytes.extend_from_slice(&hw2.to_le_bytes());
3692
3693 let hw1: u16 = (0xEB00 | 4) as u16;
3695 let hw2: u16 = ((4 << 8) | r12) as u16;
3696 bytes.extend_from_slice(&hw1.to_le_bytes());
3697 bytes.extend_from_slice(&hw2.to_le_bytes());
3698
3699 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3704 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3705 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3707 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3708
3709 let hw1: u16 = (0xEA00 | 4) as u16;
3711 let hw2: u16 = ((4 << 8) | r3) as u16;
3712 bytes.extend_from_slice(&hw1.to_le_bytes());
3713 bytes.extend_from_slice(&hw2.to_le_bytes());
3714
3715 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3719 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3720 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3722 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3723
3724 let hw1: u16 = (0xFB00 | 4) as u16;
3727 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3728 bytes.extend_from_slice(&hw1.to_le_bytes());
3729 bytes.extend_from_slice(&hw2.to_le_bytes());
3730
3731 let hw1: u16 = 0xEA4F;
3734 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) 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 = 0xEA4F;
3741 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3742 bytes.extend_from_slice(&hw1.to_le_bytes());
3743 bytes.extend_from_slice(&hw2.to_le_bytes());
3744
3745 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3747 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3748 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3749 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3750
3751 let hw1: u16 = (0xEA00 | r12) as u16;
3752 let hw2: u16 = ((r12 << 8) | r3) as u16;
3753 bytes.extend_from_slice(&hw1.to_le_bytes());
3754 bytes.extend_from_slice(&hw2.to_le_bytes());
3755
3756 let hw1: u16 = (0xEBA0 | 5) as u16;
3757 let hw2: u16 = ((5 << 8) | r12) as u16;
3758 bytes.extend_from_slice(&hw1.to_le_bytes());
3759 bytes.extend_from_slice(&hw2.to_le_bytes());
3760
3761 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3763 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3764 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3765 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3766
3767 let hw1: u16 = (0xEA00 | 5) as u16;
3768 let hw2: u16 = ((r12 << 8) | r3) as u16;
3769 bytes.extend_from_slice(&hw1.to_le_bytes());
3770 bytes.extend_from_slice(&hw2.to_le_bytes());
3771
3772 let hw1: u16 = 0xEA4F;
3773 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3774 bytes.extend_from_slice(&hw1.to_le_bytes());
3775 bytes.extend_from_slice(&hw2.to_le_bytes());
3776
3777 let hw1: u16 = (0xEA00 | 5) as u16;
3778 let hw2: u16 = ((5 << 8) | r3) as u16;
3779 bytes.extend_from_slice(&hw1.to_le_bytes());
3780 bytes.extend_from_slice(&hw2.to_le_bytes());
3781
3782 let hw1: u16 = (0xEB00 | 5) as u16;
3783 let hw2: u16 = ((5 << 8) | r12) as u16;
3784 bytes.extend_from_slice(&hw1.to_le_bytes());
3785 bytes.extend_from_slice(&hw2.to_le_bytes());
3786
3787 let hw1: u16 = 0xEA4F;
3790 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3791 bytes.extend_from_slice(&hw1.to_le_bytes());
3792 bytes.extend_from_slice(&hw2.to_le_bytes());
3793
3794 let hw1: u16 = (0xEB00 | 5) as u16;
3795 let hw2: u16 = ((5 << 8) | r12) as u16;
3796 bytes.extend_from_slice(&hw1.to_le_bytes());
3797 bytes.extend_from_slice(&hw2.to_le_bytes());
3798
3799 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3801 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3802 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3803 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3804
3805 let hw1: u16 = (0xEA00 | 5) as u16;
3806 let hw2: u16 = ((5 << 8) | r3) as u16;
3807 bytes.extend_from_slice(&hw1.to_le_bytes());
3808 bytes.extend_from_slice(&hw2.to_le_bytes());
3809
3810 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3812 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3813 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3814 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3815
3816 let hw1: u16 = (0xFB00 | 5) as u16;
3819 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3820 bytes.extend_from_slice(&hw1.to_le_bytes());
3821 bytes.extend_from_slice(&hw2.to_le_bytes());
3822
3823 let hw1: u16 = 0xEA4F;
3826 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3827 bytes.extend_from_slice(&hw1.to_le_bytes());
3828 bytes.extend_from_slice(&hw2.to_le_bytes());
3829
3830 let rd_bits_u16 = rd_bits as u16;
3833 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3834 bytes.extend_from_slice(&instr.to_le_bytes());
3835
3836 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3838
3839 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3841 bytes.extend_from_slice(&mov0.to_le_bytes());
3842
3843 Ok(bytes)
3844 }
3845
3846 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3849 let rdlo_bits = reg_to_bits(rdlo);
3850 let rdhi_bits = reg_to_bits(rdhi);
3851 let rnlo_bits = reg_to_bits(rnlo);
3852 let mut bytes = Vec::new();
3853
3854 let hw1: u16 = 0xFA4F_u16;
3857 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3858 bytes.extend_from_slice(&hw1.to_le_bytes());
3859 bytes.extend_from_slice(&hw2.to_le_bytes());
3860
3861 let hw1: u16 = 0xEA4F;
3866 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3867 bytes.extend_from_slice(&hw1.to_le_bytes());
3868 bytes.extend_from_slice(&hw2.to_le_bytes());
3869
3870 Ok(bytes)
3871 }
3872
3873 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3876 let rdlo_bits = reg_to_bits(rdlo);
3877 let rdhi_bits = reg_to_bits(rdhi);
3878 let rnlo_bits = reg_to_bits(rnlo);
3879 let mut bytes = Vec::new();
3880
3881 let hw1: u16 = 0xFA0F_u16;
3884 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3885 bytes.extend_from_slice(&hw1.to_le_bytes());
3886 bytes.extend_from_slice(&hw2.to_le_bytes());
3887
3888 let hw1: u16 = 0xEA4F;
3890 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3891 bytes.extend_from_slice(&hw1.to_le_bytes());
3892 bytes.extend_from_slice(&hw2.to_le_bytes());
3893
3894 Ok(bytes)
3895 }
3896
3897 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
3900 let rdlo_bits = reg_to_bits(rdlo);
3901 let rdhi_bits = reg_to_bits(rdhi);
3902 let rnlo_bits = reg_to_bits(rnlo);
3903 let mut bytes = Vec::new();
3904
3905 if rdlo_bits != rnlo_bits {
3907 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
3909 let mov: u16 = 0x4600
3910 | (d_bit << 7)
3911 | ((rnlo_bits as u16) << 3)
3912 | ((rdlo_bits & 0x7) as u16);
3913 bytes.extend_from_slice(&mov.to_le_bytes());
3914 }
3915
3916 let hw1: u16 = 0xEA4F;
3918 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
3919 bytes.extend_from_slice(&hw1.to_le_bytes());
3920 bytes.extend_from_slice(&hw2.to_le_bytes());
3921
3922 Ok(bytes)
3923 }
3924
3925 ArmOp::SelectMove { rd, rm, cond } => {
3928 let rd_bits = reg_to_bits(rd) as u16;
3929 let rm_bits = reg_to_bits(rm) as u16;
3930
3931 use synth_synthesis::Condition;
3933 let cond_bits: u16 = match cond {
3934 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, };
3945
3946 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
3949
3950 let d_bit = (rd_bits >> 3) & 1;
3953 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3954
3955 let mut bytes = it_instr.to_le_bytes().to_vec();
3957 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3958 Ok(bytes)
3959 }
3960
3961 ArmOp::Popcnt { rd, rm } => {
3972 let mut bytes = Vec::new();
3973
3974 if rd != rm {
3976 let rd_bits = reg_to_bits(rd) as u16;
3977 let rm_bits = reg_to_bits(rm) as u16;
3978 let d_bit = (rd_bits >> 3) & 1;
3980 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3981 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3982 }
3983
3984 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
3987 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
3988
3989 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
3992
3993 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
3995
3996 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
3998 reg_to_bits(rd),
3999 reg_to_bits(rd),
4000 11,
4001 )?);
4002
4003 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4006 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4007
4008 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4010 11,
4011 reg_to_bits(rd),
4012 12,
4013 )?);
4014
4015 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4017 reg_to_bits(rd),
4018 reg_to_bits(rd),
4019 2,
4020 )?);
4021
4022 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4024 reg_to_bits(rd),
4025 reg_to_bits(rd),
4026 12,
4027 )?);
4028
4029 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4031 reg_to_bits(rd),
4032 reg_to_bits(rd),
4033 11,
4034 )?);
4035
4036 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4039
4040 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4042 reg_to_bits(rd),
4043 reg_to_bits(rd),
4044 11,
4045 )?);
4046
4047 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4049 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4050
4051 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4053 reg_to_bits(rd),
4054 reg_to_bits(rd),
4055 12,
4056 )?);
4057
4058 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4061
4062 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4064 reg_to_bits(rd),
4065 reg_to_bits(rd),
4066 11,
4067 )?);
4068
4069 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4072
4073 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4075 reg_to_bits(rd),
4076 reg_to_bits(rd),
4077 11,
4078 )?);
4079
4080 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4083 reg_to_bits(rd),
4084 reg_to_bits(rd),
4085 0x3F,
4086 )?);
4087
4088 Ok(bytes)
4089 }
4090
4091 ArmOp::I64DivU {
4096 rdlo: _,
4097 rdhi: _,
4098 rnlo: _,
4099 rnhi: _,
4100 rmlo: _,
4101 rmhi: _,
4102 } => {
4103 let mut bytes = Vec::new();
4104
4105 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4109
4110 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());
4121 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4122
4123 let loop_start = bytes.len();
4125
4126 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4137 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());
4146 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4147 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4151 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4152
4153 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4158 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4159 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());
4190 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4191 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4194
4195 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4199 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4200
4201 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4204 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4205 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4206
4207 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4215
4216 Ok(bytes)
4217 }
4218
4219 ArmOp::I64DivS {
4224 rdlo: _,
4225 rdhi: _,
4226 rnlo: _,
4227 rnhi: _,
4228 rmlo: _,
4229 rmhi: _,
4230 } => {
4231 let mut bytes = Vec::new();
4232
4233 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4235 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4236
4237 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4240 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4241
4242 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());
4255
4256 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());
4266
4267 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4270 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4271 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4273 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4274 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4276 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4277
4278 let loop_start = bytes.len();
4279
4280 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4284 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());
4290 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4293
4294 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4298 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());
4311 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4313
4314 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4317
4318 let branch_offset_bytes = bytes.len() - loop_start + 4;
4319 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4320 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4321 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4322
4323 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());
4330 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());
4338
4339 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4341 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4342
4343 Ok(bytes)
4344 }
4345
4346 ArmOp::I64RemU {
4351 rdlo: _,
4352 rdhi: _,
4353 rnlo: _,
4354 rnhi: _,
4355 rmlo: _,
4356 rmhi: _,
4357 } => {
4358 let mut bytes = Vec::new();
4359
4360 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4362 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4363
4364 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4366 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4367 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4369 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4370 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4372 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4373
4374 let loop_start = bytes.len();
4375
4376 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4380 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());
4386 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4389
4390 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4394 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());
4407 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4409
4410 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4413
4414 let branch_offset_bytes = bytes.len() - loop_start + 4;
4415 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4416 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4417 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4418
4419 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4425 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4426
4427 Ok(bytes)
4428 }
4429
4430 ArmOp::I64RemS {
4435 rdlo: _,
4436 rdhi: _,
4437 rnlo: _,
4438 rnhi: _,
4439 rmlo: _,
4440 rmhi: _,
4441 } => {
4442 let mut bytes = Vec::new();
4443
4444 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4446 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4447
4448 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());
4462
4463 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());
4473
4474 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4477 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4478 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4480 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4481 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4483 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4484
4485 let loop_start = bytes.len();
4486
4487 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4491 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());
4497 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4500
4501 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4505 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());
4518 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4520
4521 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4524
4525 let branch_offset_bytes = bytes.len() - loop_start + 4;
4526 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4527 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4528 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4529
4530 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());
4537 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());
4545
4546 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4548 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4549
4550 Ok(bytes)
4551 }
4552
4553 ArmOp::F32Add { sd, sn, sm } => {
4556 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4557 }
4558 ArmOp::F32Sub { sd, sn, sm } => {
4559 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4560 }
4561 ArmOp::F32Mul { sd, sn, sm } => {
4562 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4563 }
4564 ArmOp::F32Div { sd, sn, sm } => {
4565 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4566 }
4567 ArmOp::F32Abs { sd, sm } => {
4568 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4569 }
4570 ArmOp::F32Neg { sd, sm } => {
4571 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4572 }
4573 ArmOp::F32Sqrt { sd, sm } => {
4574 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4575 }
4576
4577 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4580 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4581 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4582 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4583 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4584 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4585 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4586
4587 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4589 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4590 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4591 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4592 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4593 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4594
4595 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4596
4597 ArmOp::F32Load { sd, addr } => {
4598 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4599 }
4600 ArmOp::F32Store { sd, addr } => {
4601 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4602 }
4603
4604 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4605 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4606 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4607 Err(synth_core::Error::synthesis(
4608 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4609 ))
4610 }
4611 ArmOp::F32ReinterpretI32 { sd, rm } => {
4612 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4613 }
4614 ArmOp::I32ReinterpretF32 { rd, sm } => {
4615 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4616 }
4617 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4618 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4619
4620 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4623 0xEE300B00, dd, dn, dm,
4624 )?)),
4625 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4626 0xEE300B40, dd, dn, dm,
4627 )?)),
4628 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4629 0xEE200B00, dd, dn, dm,
4630 )?)),
4631 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4632 0xEE800B00, dd, dn, dm,
4633 )?)),
4634 ArmOp::F64Abs { dd, dm } => {
4635 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4636 }
4637 ArmOp::F64Neg { dd, dm } => {
4638 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4639 }
4640 ArmOp::F64Sqrt { dd, dm } => {
4641 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4642 }
4643
4644 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4647 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4648 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4649 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4650 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4651 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4652 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4653
4654 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4656 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4657 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4658 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4659 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4660 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4661
4662 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4663
4664 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4665 0xED900B00, dd, addr,
4666 )?)),
4667 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4668 0xED800B00, dd, addr,
4669 )?)),
4670
4671 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4672 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4673 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4674 Err(synth_core::Error::synthesis(
4675 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4676 ))
4677 }
4678 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4679 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4680 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4681 )),
4682 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4683 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4684 )),
4685 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4686 Err(synth_core::Error::synthesis(
4687 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4688 ))
4689 }
4690 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4691 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4692
4693 ArmOp::I64Add {
4697 rdlo,
4698 rdhi,
4699 rnlo,
4700 rnhi,
4701 rmlo,
4702 rmhi,
4703 } => {
4704 let mut bytes = Vec::new();
4705 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4707 rd: *rdlo,
4708 rn: *rnlo,
4709 op2: Operand2::Reg(*rmlo),
4710 })?);
4711 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4713 rd: *rdhi,
4714 rn: *rnhi,
4715 op2: Operand2::Reg(*rmhi),
4716 })?);
4717 Ok(bytes)
4718 }
4719
4720 ArmOp::I64Sub {
4722 rdlo,
4723 rdhi,
4724 rnlo,
4725 rnhi,
4726 rmlo,
4727 rmhi,
4728 } => {
4729 let mut bytes = Vec::new();
4730 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4732 rd: *rdlo,
4733 rn: *rnlo,
4734 op2: Operand2::Reg(*rmlo),
4735 })?);
4736 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4738 rd: *rdhi,
4739 rn: *rnhi,
4740 op2: Operand2::Reg(*rmhi),
4741 })?);
4742 Ok(bytes)
4743 }
4744
4745 ArmOp::I64And {
4747 rdlo,
4748 rdhi,
4749 rnlo,
4750 rnhi,
4751 rmlo,
4752 rmhi,
4753 } => {
4754 let mut bytes = Vec::new();
4755 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4756 rd: *rdlo,
4757 rn: *rnlo,
4758 op2: Operand2::Reg(*rmlo),
4759 })?);
4760 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4761 rd: *rdhi,
4762 rn: *rnhi,
4763 op2: Operand2::Reg(*rmhi),
4764 })?);
4765 Ok(bytes)
4766 }
4767
4768 ArmOp::I64Or {
4770 rdlo,
4771 rdhi,
4772 rnlo,
4773 rnhi,
4774 rmlo,
4775 rmhi,
4776 } => {
4777 let mut bytes = Vec::new();
4778 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4779 rd: *rdlo,
4780 rn: *rnlo,
4781 op2: Operand2::Reg(*rmlo),
4782 })?);
4783 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4784 rd: *rdhi,
4785 rn: *rnhi,
4786 op2: Operand2::Reg(*rmhi),
4787 })?);
4788 Ok(bytes)
4789 }
4790
4791 ArmOp::I64Xor {
4793 rdlo,
4794 rdhi,
4795 rnlo,
4796 rnhi,
4797 rmlo,
4798 rmhi,
4799 } => {
4800 let mut bytes = Vec::new();
4801 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4802 rd: *rdlo,
4803 rn: *rnlo,
4804 op2: Operand2::Reg(*rmlo),
4805 })?);
4806 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4807 rd: *rdhi,
4808 rn: *rnhi,
4809 op2: Operand2::Reg(*rmhi),
4810 })?);
4811 Ok(bytes)
4812 }
4813
4814 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4816 rd: *rd,
4817 rn_lo: *rnlo,
4818 rn_hi: *rnhi,
4819 }),
4820
4821 ArmOp::I64Eq {
4823 rd,
4824 rnlo,
4825 rnhi,
4826 rmlo,
4827 rmhi,
4828 } => self.encode_thumb(&ArmOp::I64SetCond {
4829 rd: *rd,
4830 rn_lo: *rnlo,
4831 rn_hi: *rnhi,
4832 rm_lo: *rmlo,
4833 rm_hi: *rmhi,
4834 cond: synth_synthesis::Condition::EQ,
4835 }),
4836
4837 ArmOp::I64Ne {
4838 rd,
4839 rnlo,
4840 rnhi,
4841 rmlo,
4842 rmhi,
4843 } => self.encode_thumb(&ArmOp::I64SetCond {
4844 rd: *rd,
4845 rn_lo: *rnlo,
4846 rn_hi: *rnhi,
4847 rm_lo: *rmlo,
4848 rm_hi: *rmhi,
4849 cond: synth_synthesis::Condition::NE,
4850 }),
4851
4852 ArmOp::I64LtS {
4853 rd,
4854 rnlo,
4855 rnhi,
4856 rmlo,
4857 rmhi,
4858 } => self.encode_thumb(&ArmOp::I64SetCond {
4859 rd: *rd,
4860 rn_lo: *rnlo,
4861 rn_hi: *rnhi,
4862 rm_lo: *rmlo,
4863 rm_hi: *rmhi,
4864 cond: synth_synthesis::Condition::LT,
4865 }),
4866
4867 ArmOp::I64LtU {
4868 rd,
4869 rnlo,
4870 rnhi,
4871 rmlo,
4872 rmhi,
4873 } => self.encode_thumb(&ArmOp::I64SetCond {
4874 rd: *rd,
4875 rn_lo: *rnlo,
4876 rn_hi: *rnhi,
4877 rm_lo: *rmlo,
4878 rm_hi: *rmhi,
4879 cond: synth_synthesis::Condition::LO,
4880 }),
4881
4882 ArmOp::I64LeS {
4883 rd,
4884 rnlo,
4885 rnhi,
4886 rmlo,
4887 rmhi,
4888 } => self.encode_thumb(&ArmOp::I64SetCond {
4889 rd: *rd,
4890 rn_lo: *rnlo,
4891 rn_hi: *rnhi,
4892 rm_lo: *rmlo,
4893 rm_hi: *rmhi,
4894 cond: synth_synthesis::Condition::LE,
4895 }),
4896
4897 ArmOp::I64LeU {
4898 rd,
4899 rnlo,
4900 rnhi,
4901 rmlo,
4902 rmhi,
4903 } => self.encode_thumb(&ArmOp::I64SetCond {
4904 rd: *rd,
4905 rn_lo: *rnlo,
4906 rn_hi: *rnhi,
4907 rm_lo: *rmlo,
4908 rm_hi: *rmhi,
4909 cond: synth_synthesis::Condition::LS,
4910 }),
4911
4912 ArmOp::I64GtS {
4913 rd,
4914 rnlo,
4915 rnhi,
4916 rmlo,
4917 rmhi,
4918 } => self.encode_thumb(&ArmOp::I64SetCond {
4919 rd: *rd,
4920 rn_lo: *rnlo,
4921 rn_hi: *rnhi,
4922 rm_lo: *rmlo,
4923 rm_hi: *rmhi,
4924 cond: synth_synthesis::Condition::GT,
4925 }),
4926
4927 ArmOp::I64GtU {
4928 rd,
4929 rnlo,
4930 rnhi,
4931 rmlo,
4932 rmhi,
4933 } => self.encode_thumb(&ArmOp::I64SetCond {
4934 rd: *rd,
4935 rn_lo: *rnlo,
4936 rn_hi: *rnhi,
4937 rm_lo: *rmlo,
4938 rm_hi: *rmhi,
4939 cond: synth_synthesis::Condition::HI,
4940 }),
4941
4942 ArmOp::I64GeS {
4943 rd,
4944 rnlo,
4945 rnhi,
4946 rmlo,
4947 rmhi,
4948 } => self.encode_thumb(&ArmOp::I64SetCond {
4949 rd: *rd,
4950 rn_lo: *rnlo,
4951 rn_hi: *rnhi,
4952 rm_lo: *rmlo,
4953 rm_hi: *rmhi,
4954 cond: synth_synthesis::Condition::GE,
4955 }),
4956
4957 ArmOp::I64GeU {
4958 rd,
4959 rnlo,
4960 rnhi,
4961 rmlo,
4962 rmhi,
4963 } => self.encode_thumb(&ArmOp::I64SetCond {
4964 rd: *rd,
4965 rn_lo: *rnlo,
4966 rn_hi: *rnhi,
4967 rm_lo: *rmlo,
4968 rm_hi: *rmhi,
4969 cond: synth_synthesis::Condition::HS,
4970 }),
4971
4972 ArmOp::I64Const { rdlo, rdhi, value } => {
4974 let lo32 = *value as u32;
4975 let hi32 = (*value >> 32) as u32;
4976 let mut bytes = Vec::new();
4977 bytes.extend_from_slice(
4979 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
4980 );
4981 if lo32 > 0xFFFF {
4982 bytes.extend_from_slice(
4983 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
4984 );
4985 }
4986 bytes.extend_from_slice(
4988 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
4989 );
4990 if hi32 > 0xFFFF {
4991 bytes.extend_from_slice(
4992 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
4993 );
4994 }
4995 Ok(bytes)
4996 }
4997
4998 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5000 let mut bytes = Vec::new();
5001 let offset = if addr.offset < 0 {
5002 0u32
5003 } else {
5004 addr.offset as u32
5005 };
5006 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5007 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5008 rdhi,
5009 &addr.base,
5010 offset.wrapping_add(4),
5011 )?);
5012 Ok(bytes)
5013 }
5014
5015 ArmOp::I64Str { rdlo, rdhi, addr } => {
5017 let mut bytes = Vec::new();
5018 let offset = if addr.offset < 0 {
5019 0u32
5020 } else {
5021 addr.offset as u32
5022 };
5023 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5024 bytes.extend_from_slice(&self.encode_thumb32_str(
5025 rdhi,
5026 &addr.base,
5027 offset.wrapping_add(4),
5028 )?);
5029 Ok(bytes)
5030 }
5031
5032 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5034 let mut bytes = Vec::new();
5035 if rdlo != rn {
5036 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5038 rd: *rdlo,
5039 op2: Operand2::Reg(*rn),
5040 })?);
5041 }
5042 bytes.extend_from_slice(
5044 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5046 Ok(bytes)
5047 }
5048
5049 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5051 let mut bytes = Vec::new();
5052 if rdlo != rn {
5053 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5055 rd: *rdlo,
5056 op2: Operand2::Reg(*rn),
5057 })?);
5058 }
5059 let rdhi_bits = reg_to_bits(rdhi) as u16;
5061 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5062 bytes.extend_from_slice(&instr.to_le_bytes());
5063 Ok(bytes)
5064 }
5065
5066 ArmOp::I32WrapI64 { rd, rnlo } => {
5068 if rd == rnlo {
5069 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5072 } else {
5073 self.encode_thumb(&ArmOp::Mov {
5075 rd: *rd,
5076 op2: Operand2::Reg(*rnlo),
5077 })
5078 }
5079 }
5080
5081 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5083 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5084 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5085 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5086 0xEF000150, qd, qn, qm,
5087 ))),
5088 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5089 0xEF200150, qd, qn, qm,
5090 ))),
5091 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5092 0xFF000150, qd, qn, qm,
5093 ))),
5094 ArmOp::MveMvn { qd, qm } => {
5095 let qd_enc = qreg_to_num(qd);
5097 let qm_enc = qreg_to_num(qm);
5098 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5099 Ok(vfp_to_thumb_bytes(instr))
5100 }
5101 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5102 0xEF100150, qd, qn, qm,
5103 ))),
5104 ArmOp::MveAddI { qd, qn, qm, size } => {
5105 let sz = mve_size_bits(size);
5106 let base: u32 = 0xEF000840 | (sz << 20);
5107 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5108 }
5109 ArmOp::MveSubI { qd, qn, qm, size } => {
5110 let sz = mve_size_bits(size);
5111 let base: u32 = 0xFF000840 | (sz << 20);
5112 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5113 }
5114 ArmOp::MveMulI { qd, qn, qm, size } => {
5115 let sz = mve_size_bits(size);
5116 let base: u32 = 0xEF000950 | (sz << 20);
5117 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5118 }
5119 ArmOp::MveNegI { qd, qm, size } => {
5120 let sz = mve_size_bits(size);
5121 let qd_enc = qreg_to_num(qd);
5123 let qm_enc = qreg_to_num(qm);
5124 let base: u32 = 0xFFB103C0 | (sz << 18);
5125 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5126 Ok(vfp_to_thumb_bytes(instr))
5127 }
5128 ArmOp::MveDup { qd, rn, size } => {
5129 let sz = mve_size_bits(size);
5130 let qd_enc = qreg_to_num(qd);
5131 let rn_bits = reg_to_bits(rn);
5132 let be = match sz {
5135 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5139 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5140 Ok(vfp_to_thumb_bytes(instr))
5141 }
5142 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5143 let qn_enc = qreg_to_num(qn);
5144 let rd_bits = reg_to_bits(rd);
5145 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5148 let lane_in_d = (*lane as u32) & 1;
5149 let _sz = mve_size_bits(size);
5150 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5152 Ok(vfp_to_thumb_bytes(instr))
5153 }
5154 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5155 let qd_enc = qreg_to_num(qd);
5156 let rn_bits = reg_to_bits(rn);
5157 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5158 let lane_in_d = (*lane as u32) & 1;
5159 let _sz = mve_size_bits(size);
5160 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5162 Ok(vfp_to_thumb_bytes(instr))
5163 }
5164
5165 ArmOp::MveCmpEqI { qd, qn, qm, size }
5167 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5168 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5169 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5170 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5171 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5172 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5173 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5174 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5175 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5176 let sz = mve_size_bits(size);
5179 let base: u32 = 0xEF000840 | (sz << 20);
5180 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5181 }
5182
5183 ArmOp::MveAddF32 { qd, qn, qm } => {
5185 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5187 }
5188 ArmOp::MveSubF32 { qd, qn, qm } => {
5189 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5191 }
5192 ArmOp::MveMulF32 { qd, qn, qm } => {
5193 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5195 }
5196 ArmOp::MveNegF32 { qd, qm } => {
5197 let qd_enc = qreg_to_num(qd);
5198 let qm_enc = qreg_to_num(qm);
5199 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5201 Ok(vfp_to_thumb_bytes(instr))
5202 }
5203 ArmOp::MveAbsF32 { qd, qm } => {
5204 let qd_enc = qreg_to_num(qd);
5205 let qm_enc = qreg_to_num(qm);
5206 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5208 Ok(vfp_to_thumb_bytes(instr))
5209 }
5210 ArmOp::MveCmpEqF32 { qd, qn, qm }
5211 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5212 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5213 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5214 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5215 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5216 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5218 }
5219 ArmOp::MveDupF32 { qd, rn } => {
5220 let qd_enc = qreg_to_num(qd);
5221 let rn_bits = reg_to_bits(rn);
5222 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5224 Ok(vfp_to_thumb_bytes(instr))
5225 }
5226 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5227 let qn_enc = qreg_to_num(qn);
5228 let rd_bits = reg_to_bits(rd);
5229 let s_num = qn_enc * 4 + (*lane as u32);
5231 let (vn, n) = encode_sreg(s_num);
5232 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5233 Ok(vfp_to_thumb_bytes(instr))
5234 }
5235 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5236 let qd_enc = qreg_to_num(qd);
5237 let rn_bits = reg_to_bits(rn);
5238 let s_num = qd_enc * 4 + (*lane as u32);
5240 let (vn, n) = encode_sreg(s_num);
5241 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5242 Ok(vfp_to_thumb_bytes(instr))
5243 }
5244 ArmOp::MveDivF32 { qd, qn, qm } => {
5245 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5247 }
5248 ArmOp::MveSqrtF32 { qd, qm } => {
5249 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5251 }
5252
5253 _ => {
5255 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5257 }
5258 }
5259 }
5260
5261 fn encode_thumb_f32_compare(
5265 &self,
5266 rd: &Reg,
5267 sn: &VfpReg,
5268 sm: &VfpReg,
5269 cond_code: u32,
5270 ) -> Result<Vec<u8>> {
5271 let mut bytes = Vec::new();
5272 let rd_bits = reg_to_bits(rd);
5273
5274 let sn_num = vfp_sreg_to_num(sn)?;
5276 let sm_num = vfp_sreg_to_num(sm)?;
5277 let (vd, d) = encode_sreg(sn_num);
5278 let (vm, m) = encode_sreg(sm_num);
5279 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5280 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5281
5282 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5284
5285 if rd_bits < 8 {
5287 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5288 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5289 } else {
5290 let hw1: u16 = 0xF04F;
5292 let hw2: u16 = (rd_bits as u16) << 8;
5293 bytes.extend_from_slice(&hw1.to_le_bytes());
5294 bytes.extend_from_slice(&hw2.to_le_bytes());
5295 }
5296
5297 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5301 bytes.extend_from_slice(&it.to_le_bytes());
5302
5303 if rd_bits < 8 {
5305 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5306 bytes.extend_from_slice(&mov_one.to_le_bytes());
5307 } else {
5308 let hw1: u16 = 0xF04F;
5310 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5311 bytes.extend_from_slice(&hw1.to_le_bytes());
5312 bytes.extend_from_slice(&hw2.to_le_bytes());
5313 }
5314
5315 Ok(bytes)
5316 }
5317
5318 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5320 let mut bytes = Vec::new();
5321 let bits = value.to_bits();
5322 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5327 let imm4 = (lo16 >> 12) & 0xF;
5328 let i_bit = (lo16 >> 11) & 1;
5329 let imm3 = (lo16 >> 8) & 0x7;
5330 let imm8 = lo16 & 0xFF;
5331 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5332 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5333 bytes.extend_from_slice(&hw1.to_le_bytes());
5334 bytes.extend_from_slice(&hw2.to_le_bytes());
5335
5336 let hi16 = (bits >> 16) & 0xFFFF;
5338 let imm4 = (hi16 >> 12) & 0xF;
5339 let i_bit = (hi16 >> 11) & 1;
5340 let imm3 = (hi16 >> 8) & 0x7;
5341 let imm8 = hi16 & 0xFF;
5342 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5343 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5344 bytes.extend_from_slice(&hw1.to_le_bytes());
5345 bytes.extend_from_slice(&hw2.to_le_bytes());
5346
5347 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5349 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5350
5351 Ok(bytes)
5352 }
5353
5354 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5356 let mut bytes = Vec::new();
5357
5358 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5360 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5361
5362 let sd_num = vfp_sreg_to_num(sd)?;
5364 let (vd, d) = encode_sreg(sd_num);
5365 let (vm, m) = encode_sreg(sd_num);
5366 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5367 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5368 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5369
5370 Ok(bytes)
5371 }
5372
5373 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5381 let mut bytes = Vec::new();
5382 let sm_num = vfp_sreg_to_num(sm)?;
5383 let sd_num = vfp_sreg_to_num(sd)?;
5384 let (vd_s, d_s) = encode_sreg(sd_num);
5385 let (vm_s, m_s) = encode_sreg(sm_num);
5386
5387 if mode == 0b11 {
5388 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5390 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5391 } else {
5392 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5397 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5398
5399 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5405 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5406 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5407
5408 if mode != 0 {
5410 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5412 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5413 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5414 }
5415
5416 let vmsr = 0xEEE10A10 | (rt << 12);
5418 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5419
5420 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5422 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5423
5424 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5426 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5427 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5428 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5429 }
5430
5431 let (vd2, d2) = encode_sreg(sd_num);
5433 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5434 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5435
5436 Ok(bytes)
5437 }
5438
5439 fn encode_thumb_f32_minmax(
5441 &self,
5442 sd: &VfpReg,
5443 sn: &VfpReg,
5444 sm: &VfpReg,
5445 is_min: bool,
5446 ) -> Result<Vec<u8>> {
5447 let mut bytes = Vec::new();
5448 let sn_num = vfp_sreg_to_num(sn)?;
5449 let sm_num = vfp_sreg_to_num(sm)?;
5450 let sd_num = vfp_sreg_to_num(sd)?;
5451
5452 let (vd, d) = encode_sreg(sd_num);
5454 let (vn, n) = encode_sreg(sn_num);
5455 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5456 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5457
5458 let (vm, m) = encode_sreg(sm_num);
5460 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5461 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5462
5463 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5465
5466 let cond: u16 = if is_min { 0xC } else { 0x4 };
5468 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5469 bytes.extend_from_slice(&it.to_le_bytes());
5470
5471 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5473 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5474
5475 Ok(bytes)
5476 }
5477
5478 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5480 let mut bytes = Vec::new();
5481
5482 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5484 false,
5485 sm,
5486 &Reg::R12,
5487 )?));
5488
5489 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5491 false,
5492 sn,
5493 &Reg::R0,
5494 )?));
5495
5496 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5508 bytes.extend_from_slice(&hw2.to_le_bytes());
5509
5510 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5514 bytes.extend_from_slice(&hw2.to_le_bytes());
5515
5516 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5520 bytes.extend_from_slice(&hw2.to_le_bytes());
5521
5522 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5524 true,
5525 sd,
5526 &Reg::R0,
5527 )?));
5528
5529 Ok(bytes)
5530 }
5531
5532 fn encode_thumb_f64_compare(
5534 &self,
5535 rd: &Reg,
5536 dn: &VfpReg,
5537 dm: &VfpReg,
5538 cond_code: u32,
5539 ) -> Result<Vec<u8>> {
5540 let mut bytes = Vec::new();
5541 let rd_bits = reg_to_bits(rd);
5542
5543 let dn_num = vfp_dreg_to_num(dn)?;
5545 let dm_num = vfp_dreg_to_num(dm)?;
5546 let (vd, d) = encode_dreg(dn_num);
5547 let (vm, m) = encode_dreg(dm_num);
5548 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5549 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5550
5551 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5553
5554 if rd_bits < 8 {
5556 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5557 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5558 } else {
5559 let hw1: u16 = 0xF04F;
5560 let hw2: u16 = (rd_bits as u16) << 8;
5561 bytes.extend_from_slice(&hw1.to_le_bytes());
5562 bytes.extend_from_slice(&hw2.to_le_bytes());
5563 }
5564
5565 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5567 bytes.extend_from_slice(&it.to_le_bytes());
5568
5569 if rd_bits < 8 {
5571 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5572 bytes.extend_from_slice(&mov_one.to_le_bytes());
5573 } else {
5574 let hw1: u16 = 0xF04F;
5575 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5576 bytes.extend_from_slice(&hw1.to_le_bytes());
5577 bytes.extend_from_slice(&hw2.to_le_bytes());
5578 }
5579
5580 Ok(bytes)
5581 }
5582
5583 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5585 let mut bytes = Vec::new();
5586 let bits = value.to_bits();
5587 let lo32 = bits as u32;
5588 let hi32 = (bits >> 32) as u32;
5589
5590 let lo16 = lo32 & 0xFFFF;
5592 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5593
5594 let hi16 = (lo32 >> 16) & 0xFFFF;
5596 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5597
5598 let lo16 = hi32 & 0xFFFF;
5600 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5601
5602 let hi16 = (hi32 >> 16) & 0xFFFF;
5604 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5605
5606 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5608 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5609
5610 Ok(bytes)
5611 }
5612
5613 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5615 let mut bytes = Vec::new();
5616
5617 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5619 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5620
5621 let dd_num = vfp_dreg_to_num(dd)?;
5623 let (vd, d) = encode_dreg(dd_num);
5624 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5625 let vcvt = base | (d << 22) | (vd << 12);
5626 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5627
5628 Ok(bytes)
5629 }
5630
5631 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5633 let dd_num = vfp_dreg_to_num(dd)?;
5634 let sm_num = vfp_sreg_to_num(sm)?;
5635 let (vd, d) = encode_dreg(dd_num);
5636 let (vm, m) = encode_sreg(sm_num);
5637
5638 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5639 Ok(vfp_to_thumb_bytes(vcvt))
5640 }
5641
5642 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5644 let mut bytes = Vec::new();
5645 let dm_num = vfp_dreg_to_num(dm)?;
5646 let (vm, m) = encode_dreg(dm_num);
5647
5648 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5650 let vcvt = base | (m << 5) | vm;
5651 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5652
5653 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5655 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5656
5657 Ok(bytes)
5658 }
5659
5660 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5664 let mut bytes = Vec::new();
5665 let dm_num = vfp_dreg_to_num(dm)?;
5666 let dd_num = vfp_dreg_to_num(dd)?;
5667 let (vm, m) = encode_dreg(dm_num);
5668 let (vd, d) = encode_dreg(dd_num);
5669
5670 if mode == 0b11 {
5671 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5673 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5674 } else {
5675 let rt: u32 = 12;
5676
5677 let vmrs = 0xEEF10A10 | (rt << 12);
5679 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5680
5681 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5683 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5684 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5685 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5686
5687 if mode != 0 {
5689 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5690 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5691 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5692 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5693 }
5694
5695 let vmsr = 0xEEE10A10 | (rt << 12);
5697 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5698
5699 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5701 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5702
5703 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5705 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5706 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5707 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5708 }
5709
5710 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5712 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5713
5714 Ok(bytes)
5715 }
5716
5717 fn encode_thumb_f64_minmax(
5719 &self,
5720 dd: &VfpReg,
5721 dn: &VfpReg,
5722 dm: &VfpReg,
5723 is_min: bool,
5724 ) -> Result<Vec<u8>> {
5725 let mut bytes = Vec::new();
5726 let dn_num = vfp_dreg_to_num(dn)?;
5727 let dm_num = vfp_dreg_to_num(dm)?;
5728 let dd_num = vfp_dreg_to_num(dd)?;
5729
5730 let (vd, d) = encode_dreg(dd_num);
5732 let (vn, n) = encode_dreg(dn_num);
5733 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5734 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5735
5736 let (vm, m) = encode_dreg(dm_num);
5738 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5739 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5740
5741 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5743
5744 let cond: u16 = if is_min { 0xC } else { 0x4 };
5746 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5747 bytes.extend_from_slice(&it.to_le_bytes());
5748
5749 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5751 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5752
5753 Ok(bytes)
5754 }
5755
5756 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5758 let mut bytes = Vec::new();
5759
5760 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5762 false,
5763 dm,
5764 &Reg::R0,
5765 &Reg::R12,
5766 )?));
5767
5768 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5770 false,
5771 dn,
5772 &Reg::R1,
5773 &Reg::R2,
5774 )?));
5775
5776 let hw1: u16 = 0xF000 | 12;
5778 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5779 bytes.extend_from_slice(&hw1.to_le_bytes());
5780 bytes.extend_from_slice(&hw2.to_le_bytes());
5781
5782 let hw1: u16 = 0xF020 | 2;
5784 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5785 bytes.extend_from_slice(&hw1.to_le_bytes());
5786 bytes.extend_from_slice(&hw2.to_le_bytes());
5787
5788 let hw1: u16 = 0xEA40 | 2;
5790 let hw2: u16 = (2 << 8) | 12;
5791 bytes.extend_from_slice(&hw1.to_le_bytes());
5792 bytes.extend_from_slice(&hw2.to_le_bytes());
5793
5794 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5796 true,
5797 dd,
5798 &Reg::R1,
5799 &Reg::R2,
5800 )?));
5801
5802 Ok(bytes)
5803 }
5804
5805 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5807 let mut bytes = Vec::new();
5808
5809 let sm_num = vfp_sreg_to_num(sm)?;
5810 let (vd, d) = encode_sreg(sm_num);
5811 let (vm, m) = encode_sreg(sm_num);
5812 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5813 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5814 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5815
5816 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5818 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5819
5820 Ok(bytes)
5821 }
5822
5823 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5827 let rd_bits = reg_to_bits(rd);
5828 let rn_bits = reg_to_bits(rn);
5829
5830 let i_bit = (imm >> 11) & 1;
5834 let imm3 = (imm >> 8) & 0x7;
5835 let imm8 = imm & 0xFF;
5836
5837 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5838 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5839
5840 let mut bytes = hw1.to_le_bytes().to_vec();
5841 bytes.extend_from_slice(&hw2.to_le_bytes());
5842 Ok(bytes)
5843 }
5844
5845 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5847 let rd_bits = reg_to_bits(rd);
5848 let rn_bits = reg_to_bits(rn);
5849
5850 let i_bit = (imm >> 11) & 1;
5851 let imm3 = (imm >> 8) & 0x7;
5852 let imm8 = imm & 0xFF;
5853
5854 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5855 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5856
5857 let mut bytes = hw1.to_le_bytes().to_vec();
5858 bytes.extend_from_slice(&hw2.to_le_bytes());
5859 Ok(bytes)
5860 }
5861
5862 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5864 let rd_bits = reg_to_bits(rd);
5865 let rn_bits = reg_to_bits(rn);
5866
5867 let i_bit = (imm >> 11) & 1;
5868 let imm3 = (imm >> 8) & 0x7;
5869 let imm8 = imm & 0xFF;
5870
5871 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5874 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5875
5876 let mut bytes = hw1.to_le_bytes().to_vec();
5877 bytes.extend_from_slice(&hw2.to_le_bytes());
5878 Ok(bytes)
5879 }
5880
5881 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5883 let rd_bits = reg_to_bits(rd);
5884 let rn_bits = reg_to_bits(rn);
5885
5886 let i_bit = (imm >> 11) & 1;
5887 let imm3 = (imm >> 8) & 0x7;
5888 let imm8 = imm & 0xFF;
5889
5890 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5893 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5894
5895 let mut bytes = hw1.to_le_bytes().to_vec();
5896 bytes.extend_from_slice(&hw2.to_le_bytes());
5897 Ok(bytes)
5898 }
5899
5900 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
5909 let rd_bits = reg_to_bits(rd);
5910 reg_bits_checked(rd_bits)?;
5911 let imm16 = imm & 0xFFFF;
5912
5913 let imm4 = (imm16 >> 12) & 0xF;
5916 let i_bit = (imm16 >> 11) & 1;
5917 let imm3 = (imm16 >> 8) & 0x7;
5918 let imm8 = imm16 & 0xFF;
5919
5920 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5921 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5922
5923 let mut bytes = hw1.to_le_bytes().to_vec();
5924 bytes.extend_from_slice(&hw2.to_le_bytes());
5925 encoding_contracts::verify_thumb32(&bytes);
5926 Ok(bytes)
5927 }
5928
5929 fn encode_thumb32_shift(
5937 &self,
5938 rd: &Reg,
5939 rm: &Reg,
5940 shift: u32,
5941 shift_type: u8,
5942 ) -> Result<Vec<u8>> {
5943 let rd_bits = reg_to_bits(rd);
5944 let rm_bits = reg_to_bits(rm);
5945 reg_bits_checked(rd_bits)?;
5946 reg_bits_checked(rm_bits)?;
5947 let imm5 = shift & 0x1F;
5948 let imm2 = imm5 & 0x3;
5949 let imm3 = (imm5 >> 2) & 0x7;
5950
5951 let hw1: u16 = 0xEA4F;
5954 let hw2: u16 =
5955 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
5956 as u16;
5957
5958 let mut bytes = hw1.to_le_bytes().to_vec();
5959 bytes.extend_from_slice(&hw2.to_le_bytes());
5960 Ok(bytes)
5961 }
5962
5963 fn encode_thumb32_shift_reg(
5967 &self,
5968 rd: &Reg,
5969 rn: &Reg,
5970 rm: &Reg,
5971 shift_type: u8,
5972 ) -> Result<Vec<u8>> {
5973 let rd_bits = reg_to_bits(rd);
5974 let rn_bits = reg_to_bits(rn);
5975 let rm_bits = reg_to_bits(rm);
5976
5977 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
5979 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
5981
5982 let mut bytes = hw1.to_le_bytes().to_vec();
5983 bytes.extend_from_slice(&hw2.to_le_bytes());
5984 Ok(bytes)
5985 }
5986
5987 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5989 let rn_bits = reg_to_bits(rn);
5990
5991 let i_bit = (imm >> 11) & 1;
5992 let imm3 = (imm >> 8) & 0x7;
5993 let imm8 = imm & 0xFF;
5994
5995 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5997 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
5998
5999 let mut bytes = hw1.to_le_bytes().to_vec();
6000 bytes.extend_from_slice(&hw2.to_le_bytes());
6001 Ok(bytes)
6002 }
6003
6004 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6006 let rd_bits = reg_to_bits(rd);
6007 let base_bits = reg_to_bits(base);
6008
6009 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6011 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6012
6013 let mut bytes = hw1.to_le_bytes().to_vec();
6014 bytes.extend_from_slice(&hw2.to_le_bytes());
6015 Ok(bytes)
6016 }
6017
6018 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6020 let rd_bits = reg_to_bits(rd);
6021 let base_bits = reg_to_bits(base);
6022
6023 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6025 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6026
6027 let mut bytes = hw1.to_le_bytes().to_vec();
6028 bytes.extend_from_slice(&hw2.to_le_bytes());
6029 Ok(bytes)
6030 }
6031
6032 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6034 let rd_bits = reg_to_bits(rd);
6035 let base_bits = reg_to_bits(base);
6036 let rm_bits = reg_to_bits(offset_reg);
6037
6038 let hw1: u16 = (0xF850 | base_bits) as u16;
6042 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6043
6044 let mut bytes = hw1.to_le_bytes().to_vec();
6045 bytes.extend_from_slice(&hw2.to_le_bytes());
6046 Ok(bytes)
6047 }
6048
6049 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6051 let rd_bits = reg_to_bits(rd);
6052 let base_bits = reg_to_bits(base);
6053 let rm_bits = reg_to_bits(offset_reg);
6054
6055 let hw1: u16 = (0xF840 | base_bits) as u16;
6059 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6060
6061 let mut bytes = hw1.to_le_bytes().to_vec();
6062 bytes.extend_from_slice(&hw2.to_le_bytes());
6063 Ok(bytes)
6064 }
6065
6066 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6070 let rd_bits = reg_to_bits(rd);
6071 let base_bits = reg_to_bits(base);
6072 let hw1: u16 = (0xF890 | base_bits) as u16;
6074 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6075 let mut bytes = hw1.to_le_bytes().to_vec();
6076 bytes.extend_from_slice(&hw2.to_le_bytes());
6077 Ok(bytes)
6078 }
6079
6080 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6082 let rd_bits = reg_to_bits(rd);
6083 let base_bits = reg_to_bits(base);
6084 let rm_bits = reg_to_bits(offset_reg);
6085 let hw1: u16 = (0xF810 | base_bits) as u16;
6087 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6088 let mut bytes = hw1.to_le_bytes().to_vec();
6089 bytes.extend_from_slice(&hw2.to_le_bytes());
6090 Ok(bytes)
6091 }
6092
6093 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6095 let rd_bits = reg_to_bits(rd);
6096 let base_bits = reg_to_bits(base);
6097 let hw1: u16 = (0xF990 | base_bits) as u16;
6099 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6100 let mut bytes = hw1.to_le_bytes().to_vec();
6101 bytes.extend_from_slice(&hw2.to_le_bytes());
6102 Ok(bytes)
6103 }
6104
6105 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6107 let rd_bits = reg_to_bits(rd);
6108 let base_bits = reg_to_bits(base);
6109 let rm_bits = reg_to_bits(offset_reg);
6110 let hw1: u16 = (0xF910 | base_bits) as u16;
6112 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6113 let mut bytes = hw1.to_le_bytes().to_vec();
6114 bytes.extend_from_slice(&hw2.to_le_bytes());
6115 Ok(bytes)
6116 }
6117
6118 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6120 let rd_bits = reg_to_bits(rd);
6121 let base_bits = reg_to_bits(base);
6122 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6124 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6125 let mut bytes = hw1.to_le_bytes().to_vec();
6126 bytes.extend_from_slice(&hw2.to_le_bytes());
6127 Ok(bytes)
6128 }
6129
6130 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6132 let rd_bits = reg_to_bits(rd);
6133 let base_bits = reg_to_bits(base);
6134 let rm_bits = reg_to_bits(offset_reg);
6135 let hw1: u16 = (0xF830 | base_bits) as u16;
6137 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6138 let mut bytes = hw1.to_le_bytes().to_vec();
6139 bytes.extend_from_slice(&hw2.to_le_bytes());
6140 Ok(bytes)
6141 }
6142
6143 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6145 let rd_bits = reg_to_bits(rd);
6146 let base_bits = reg_to_bits(base);
6147 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6149 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6150 let mut bytes = hw1.to_le_bytes().to_vec();
6151 bytes.extend_from_slice(&hw2.to_le_bytes());
6152 Ok(bytes)
6153 }
6154
6155 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6157 let rd_bits = reg_to_bits(rd);
6158 let base_bits = reg_to_bits(base);
6159 let rm_bits = reg_to_bits(offset_reg);
6160 let hw1: u16 = (0xF930 | base_bits) as u16;
6162 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6163 let mut bytes = hw1.to_le_bytes().to_vec();
6164 bytes.extend_from_slice(&hw2.to_le_bytes());
6165 Ok(bytes)
6166 }
6167
6168 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6170 let rd_bits = reg_to_bits(rd);
6171 let base_bits = reg_to_bits(base);
6172 let hw1: u16 = (0xF880 | base_bits) as u16;
6174 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6175 let mut bytes = hw1.to_le_bytes().to_vec();
6176 bytes.extend_from_slice(&hw2.to_le_bytes());
6177 Ok(bytes)
6178 }
6179
6180 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6182 let rd_bits = reg_to_bits(rd);
6183 let base_bits = reg_to_bits(base);
6184 let rm_bits = reg_to_bits(offset_reg);
6185 let hw1: u16 = (0xF800 | base_bits) as u16;
6187 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6188 let mut bytes = hw1.to_le_bytes().to_vec();
6189 bytes.extend_from_slice(&hw2.to_le_bytes());
6190 Ok(bytes)
6191 }
6192
6193 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6195 let rd_bits = reg_to_bits(rd);
6196 let base_bits = reg_to_bits(base);
6197 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6199 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6200 let mut bytes = hw1.to_le_bytes().to_vec();
6201 bytes.extend_from_slice(&hw2.to_le_bytes());
6202 Ok(bytes)
6203 }
6204
6205 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6207 let rd_bits = reg_to_bits(rd);
6208 let base_bits = reg_to_bits(base);
6209 let rm_bits = reg_to_bits(offset_reg);
6210 let hw1: u16 = (0xF820 | base_bits) as u16;
6212 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6213 let mut bytes = hw1.to_le_bytes().to_vec();
6214 bytes.extend_from_slice(&hw2.to_le_bytes());
6215 Ok(bytes)
6216 }
6217
6218 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6220 let rd_bits = reg_to_bits(rd);
6221 let rn_bits = reg_to_bits(rn);
6222
6223 if imm <= 0xFFF {
6229 let i_bit = (imm >> 11) & 1;
6230 let imm3 = (imm >> 8) & 0x7;
6231 let imm8 = imm & 0xFF;
6232
6233 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6234 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6235
6236 let mut bytes = hw1.to_le_bytes().to_vec();
6237 bytes.extend_from_slice(&hw2.to_le_bytes());
6238 Ok(bytes)
6239 } else {
6240 Err(synth_core::Error::synthesis(
6243 "ADD immediate too large for single instruction",
6244 ))
6245 }
6246 }
6247
6248 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6258 reg_bits_checked(rd)?;
6259 encoding_contracts::verify_imm16(imm16);
6260 let imm16 = imm16 & 0xFFFF;
6263 let imm4 = (imm16 >> 12) & 0xF;
6264 let i_bit = (imm16 >> 11) & 1;
6265 let imm3 = (imm16 >> 8) & 0x7;
6266 let imm8 = imm16 & 0xFF;
6267
6268 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6269 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6270
6271 let mut bytes = hw1.to_le_bytes().to_vec();
6272 bytes.extend_from_slice(&hw2.to_le_bytes());
6273 encoding_contracts::verify_thumb32(&bytes);
6274 Ok(bytes)
6275 }
6276
6277 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6285 reg_bits_checked(rd)?;
6286 encoding_contracts::verify_imm16(imm16);
6287 let imm16 = imm16 & 0xFFFF;
6290 let imm4 = (imm16 >> 12) & 0xF;
6291 let i_bit = (imm16 >> 11) & 1;
6292 let imm3 = (imm16 >> 8) & 0x7;
6293 let imm8 = imm16 & 0xFF;
6294
6295 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6296 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6297
6298 let mut bytes = hw1.to_le_bytes().to_vec();
6299 bytes.extend_from_slice(&hw2.to_le_bytes());
6300 encoding_contracts::verify_thumb32(&bytes);
6301 Ok(bytes)
6302 }
6303
6304 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6306 let imm5 = shift & 0x1F;
6309 let imm2 = imm5 & 0x3;
6310 let imm3 = (imm5 >> 2) & 0x7;
6311
6312 let hw1: u16 = 0xEA4F;
6313 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6314
6315 let mut bytes = hw1.to_le_bytes().to_vec();
6316 bytes.extend_from_slice(&hw2.to_le_bytes());
6317 Ok(bytes)
6318 }
6319
6320 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6322 let hw1: u16 = (0xEA00 | rn) as u16;
6325 let hw2: u16 = ((rd << 8) | rm) as u16;
6326
6327 let mut bytes = hw1.to_le_bytes().to_vec();
6328 bytes.extend_from_slice(&hw2.to_le_bytes());
6329 Ok(bytes)
6330 }
6331
6332 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6334 let i_bit = (imm >> 11) & 1;
6338 let imm3 = (imm >> 8) & 0x7;
6339 let imm8 = imm & 0xFF;
6340
6341 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6342 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6343
6344 let mut bytes = hw1.to_le_bytes().to_vec();
6345 bytes.extend_from_slice(&hw2.to_le_bytes());
6346 Ok(bytes)
6347 }
6348
6349 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6351 let hw1: u16 = (0xEBA0 | rn) as u16;
6354 let hw2: u16 = ((rd << 8) | rm) as u16;
6355
6356 let mut bytes = hw1.to_le_bytes().to_vec();
6357 bytes.extend_from_slice(&hw2.to_le_bytes());
6358 Ok(bytes)
6359 }
6360
6361 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6363 let hw1: u16 = (0xEB00 | rn) as u16;
6366 let hw2: u16 = ((rd << 8) | rm) as u16;
6367
6368 let mut bytes = hw1.to_le_bytes().to_vec();
6369 bytes.extend_from_slice(&hw2.to_le_bytes());
6370 Ok(bytes)
6371 }
6372
6373 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6377 let hw1: u16 = (0xEB10 | rn) as u16;
6379 let hw2: u16 = ((rd << 8) | rm) as u16;
6380 let mut bytes = hw1.to_le_bytes().to_vec();
6381 bytes.extend_from_slice(&hw2.to_le_bytes());
6382 Ok(bytes)
6383 }
6384
6385 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6388 let hw1: u16 = (0xEBB0 | rn) as u16;
6390 let hw2: u16 = ((rd << 8) | rm) as u16;
6391 let mut bytes = hw1.to_le_bytes().to_vec();
6392 bytes.extend_from_slice(&hw2.to_le_bytes());
6393 Ok(bytes)
6394 }
6395
6396 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6398 let mut code = Vec::new();
6399
6400 for op in ops {
6401 let encoded = self.encode(op)?;
6402 code.extend_from_slice(&encoded);
6403 }
6404
6405 Ok(code)
6406 }
6407}
6408
6409fn reg_to_bits(reg: &Reg) -> u32 {
6411 match reg {
6412 Reg::R0 => 0,
6413 Reg::R1 => 1,
6414 Reg::R2 => 2,
6415 Reg::R3 => 3,
6416 Reg::R4 => 4,
6417 Reg::R5 => 5,
6418 Reg::R6 => 6,
6419 Reg::R7 => 7,
6420 Reg::R8 => 8,
6421 Reg::R9 => 9,
6422 Reg::R10 => 10,
6423 Reg::R11 => 11,
6424 Reg::R12 => 12,
6425 Reg::SP => 13,
6426 Reg::LR => 14,
6427 Reg::PC => 15,
6428 }
6429}
6430
6431fn reg_bits_checked(bits: u32) -> Result<()> {
6439 if bits > 14 {
6440 return Err(synth_core::Error::synthesis(format!(
6441 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6442 )));
6443 }
6444 Ok(())
6445}
6446
6447fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6450 if val == 0 {
6451 return Some((0, 1));
6452 }
6453 for rot in 0..16u32 {
6454 let shift = rot * 2;
6455 let unrotated = val.rotate_left(shift);
6457 if unrotated <= 0xFF {
6458 return Some(((rot << 8) | unrotated, 1));
6460 }
6461 }
6462 None
6463}
6464
6465fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6470 match op2 {
6471 Operand2::Imm(val) => {
6472 let uval = *val as u32;
6473 if let Some(encoded) = try_encode_rotated_imm(uval) {
6475 encoded
6476 } else {
6477 let imm = uval & 0xFF;
6482 (imm, 1)
6483 }
6484 }
6485
6486 Operand2::Reg(reg) => {
6487 let reg_bits = reg_to_bits(reg);
6488 (reg_bits, 0) }
6490
6491 Operand2::RegShift {
6492 rm,
6493 shift: _,
6494 amount,
6495 } => {
6496 let rm_bits = reg_to_bits(rm);
6498 let shift_bits = (*amount & 0x1F) << 7;
6499 (shift_bits | rm_bits, 0)
6500 }
6501 }
6502}
6503
6504fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6506 let base_bits = reg_to_bits(&addr.base);
6507 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6509}
6510
6511fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6513 match reg {
6514 VfpReg::S0 => Ok(0),
6515 VfpReg::S1 => Ok(1),
6516 VfpReg::S2 => Ok(2),
6517 VfpReg::S3 => Ok(3),
6518 VfpReg::S4 => Ok(4),
6519 VfpReg::S5 => Ok(5),
6520 VfpReg::S6 => Ok(6),
6521 VfpReg::S7 => Ok(7),
6522 VfpReg::S8 => Ok(8),
6523 VfpReg::S9 => Ok(9),
6524 VfpReg::S10 => Ok(10),
6525 VfpReg::S11 => Ok(11),
6526 VfpReg::S12 => Ok(12),
6527 VfpReg::S13 => Ok(13),
6528 VfpReg::S14 => Ok(14),
6529 VfpReg::S15 => Ok(15),
6530 VfpReg::S16 => Ok(16),
6531 VfpReg::S17 => Ok(17),
6532 VfpReg::S18 => Ok(18),
6533 VfpReg::S19 => Ok(19),
6534 VfpReg::S20 => Ok(20),
6535 VfpReg::S21 => Ok(21),
6536 VfpReg::S22 => Ok(22),
6537 VfpReg::S23 => Ok(23),
6538 VfpReg::S24 => Ok(24),
6539 VfpReg::S25 => Ok(25),
6540 VfpReg::S26 => Ok(26),
6541 VfpReg::S27 => Ok(27),
6542 VfpReg::S28 => Ok(28),
6543 VfpReg::S29 => Ok(29),
6544 VfpReg::S30 => Ok(30),
6545 VfpReg::S31 => Ok(31),
6546 _ => Err(synth_core::Error::SynthesisError(
6548 "D-register not supported in single-precision VFP encoding".to_string(),
6549 )),
6550 }
6551}
6552
6553fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6555 match reg {
6556 VfpReg::D0 => Ok(0),
6557 VfpReg::D1 => Ok(1),
6558 VfpReg::D2 => Ok(2),
6559 VfpReg::D3 => Ok(3),
6560 VfpReg::D4 => Ok(4),
6561 VfpReg::D5 => Ok(5),
6562 VfpReg::D6 => Ok(6),
6563 VfpReg::D7 => Ok(7),
6564 VfpReg::D8 => Ok(8),
6565 VfpReg::D9 => Ok(9),
6566 VfpReg::D10 => Ok(10),
6567 VfpReg::D11 => Ok(11),
6568 VfpReg::D12 => Ok(12),
6569 VfpReg::D13 => Ok(13),
6570 VfpReg::D14 => Ok(14),
6571 VfpReg::D15 => Ok(15),
6572 _ => Err(synth_core::Error::SynthesisError(
6574 "S-register not supported in double-precision VFP encoding".to_string(),
6575 )),
6576 }
6577}
6578
6579fn encode_sreg(s: u32) -> (u32, u32) {
6583 (s >> 1, s & 1)
6584}
6585
6586fn encode_dreg(d: u32) -> (u32, u32) {
6590 (d & 0xF, (d >> 4) & 1)
6591}
6592
6593fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6599 let sd_num = vfp_sreg_to_num(sd)?;
6600 let sn_num = vfp_sreg_to_num(sn)?;
6601 let sm_num = vfp_sreg_to_num(sm)?;
6602 let (vd, d) = encode_sreg(sd_num);
6603 let (vn, n) = encode_sreg(sn_num);
6604 let (vm, m) = encode_sreg(sm_num);
6605
6606 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6607}
6608
6609fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6612 let sd_num = vfp_sreg_to_num(sd)?;
6613 let sm_num = vfp_sreg_to_num(sm)?;
6614 let (vd, d) = encode_sreg(sd_num);
6615 let (vm, m) = encode_sreg(sm_num);
6616
6617 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6618}
6619
6620fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6624 let sd_num = vfp_sreg_to_num(sd)?;
6625 let (vd, d) = encode_sreg(sd_num);
6626 let rn = reg_to_bits(&addr.base);
6627
6628 let offset = addr.offset;
6629 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6630 let abs_offset = offset.unsigned_abs();
6631 let imm8 = (abs_offset / 4) & 0xFF;
6632
6633 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6634}
6635
6636fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6640 let s_num = vfp_sreg_to_num(sreg)?;
6641 let (vn, n) = encode_sreg(s_num);
6642 let rt = reg_to_bits(core);
6643
6644 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6645 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6646}
6647
6648fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6652 let dd_num = vfp_dreg_to_num(dd)?;
6653 let dn_num = vfp_dreg_to_num(dn)?;
6654 let dm_num = vfp_dreg_to_num(dm)?;
6655 let (vd, d) = encode_dreg(dd_num);
6656 let (vn, n) = encode_dreg(dn_num);
6657 let (vm, m) = encode_dreg(dm_num);
6658
6659 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6660}
6661
6662fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6664 let dd_num = vfp_dreg_to_num(dd)?;
6665 let dm_num = vfp_dreg_to_num(dm)?;
6666 let (vd, d) = encode_dreg(dd_num);
6667 let (vm, m) = encode_dreg(dm_num);
6668
6669 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6670}
6671
6672fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6675 let dd_num = vfp_dreg_to_num(dd)?;
6676 let (vd, d) = encode_dreg(dd_num);
6677 let rn = reg_to_bits(&addr.base);
6678
6679 let offset = addr.offset;
6680 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6681 let abs_offset = offset.unsigned_abs();
6682 let imm8 = (abs_offset / 4) & 0xFF;
6683
6684 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6685}
6686
6687fn encode_vmov_core_dreg(
6691 to_dreg: bool,
6692 dreg: &VfpReg,
6693 core_lo: &Reg,
6694 core_hi: &Reg,
6695) -> Result<u32> {
6696 let d_num = vfp_dreg_to_num(dreg)?;
6697 let (vm, m) = encode_dreg(d_num);
6698 let rt = reg_to_bits(core_lo);
6699 let rt2 = reg_to_bits(core_hi);
6700
6701 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6702 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6703}
6704
6705fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6707 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6708 let hw2 = (instr & 0xFFFF) as u16;
6709 let mut bytes = hw1.to_le_bytes().to_vec();
6710 bytes.extend_from_slice(&hw2.to_le_bytes());
6711 bytes
6712}
6713
6714fn qreg_to_num(reg: &QReg) -> u32 {
6720 match reg {
6721 QReg::Q0 => 0,
6722 QReg::Q1 => 1,
6723 QReg::Q2 => 2,
6724 QReg::Q3 => 3,
6725 QReg::Q4 => 4,
6726 QReg::Q5 => 5,
6727 QReg::Q6 => 6,
6728 QReg::Q7 => 7,
6729 }
6730}
6731
6732fn mve_size_bits(size: &MveSize) -> u32 {
6734 match size {
6735 MveSize::S8 => 0b00,
6736 MveSize::S16 => 0b01,
6737 MveSize::S32 => 0b10,
6738 }
6739}
6740
6741fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6745 let d = qreg_to_num(qd) * 2;
6746 let n = qreg_to_num(qn) * 2;
6747 let m = qreg_to_num(qm) * 2;
6748
6749 let vd = d & 0xF;
6754 let d_bit = (d >> 4) & 1;
6755 let vn = n & 0xF;
6756 let n_bit = (n >> 4) & 1;
6757 let vm = m & 0xF;
6758 let m_bit = (m >> 4) & 1;
6759
6760 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6761}
6762
6763fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6765 encode_mve_3reg(base, qd, qn, qm)
6766}
6767
6768fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6771 let qd_enc = qreg_to_num(qd) * 2;
6772 let rn = reg_to_bits(&addr.base);
6773 let offset = addr.offset;
6774 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6775 let abs_offset = offset.unsigned_abs();
6776 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6780 | (u_bit << 23)
6781 | ((qd_enc >> 4) << 22)
6782 | (rn << 16)
6783 | ((qd_enc & 0xF) << 12)
6784 | (imm7 & 0x7F)
6785}
6786
6787fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6789 let qd_enc = qreg_to_num(qd) * 2;
6790 let rn = reg_to_bits(&addr.base);
6791 let offset = addr.offset;
6792 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6793 let abs_offset = offset.unsigned_abs();
6794 let imm7 = (abs_offset / 4) & 0x7F;
6795
6796 0xED000E80
6797 | (u_bit << 23)
6798 | ((qd_enc >> 4) << 22)
6799 | (rn << 16)
6800 | ((qd_enc & 0xF) << 12)
6801 | (imm7 & 0x7F)
6802}
6803
6804impl ArmEncoder {
6805 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6807 let mut result = Vec::new();
6808 let qd_num = qreg_to_num(qd);
6809
6810 for i in 0..4 {
6812 let word = u32::from_le_bytes([
6813 bytes[i * 4],
6814 bytes[i * 4 + 1],
6815 bytes[i * 4 + 2],
6816 bytes[i * 4 + 3],
6817 ]);
6818 let lo16 = word & 0xFFFF;
6819 let hi16 = (word >> 16) & 0xFFFF;
6820
6821 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6823 if hi16 != 0 {
6825 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6826 }
6827
6828 let s_num = qd_num * 4 + i as u32;
6830 let (vn, n) = encode_sreg(s_num);
6831 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6832 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6833 }
6834
6835 Ok(result)
6836 }
6837
6838 fn encode_thumb_mve_lane_wise_f32_binop(
6840 &self,
6841 qd: &QReg,
6842 qn: &QReg,
6843 qm: &QReg,
6844 vfp_base: u32,
6845 ) -> Result<Vec<u8>> {
6846 let mut result = Vec::new();
6847 let qd_num = qreg_to_num(qd);
6848 let qn_num = qreg_to_num(qn);
6849 let qm_num = qreg_to_num(qm);
6850
6851 for i in 0..4u32 {
6853 let sd = qd_num * 4 + i;
6854 let sn = qn_num * 4 + i;
6855 let sm = qm_num * 4 + i;
6856
6857 let (vd, d) = encode_sreg(sd);
6858 let (vn, n) = encode_sreg(sn);
6859 let (vm, m) = encode_sreg(sm);
6860
6861 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6862 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6863 }
6864
6865 Ok(result)
6866 }
6867
6868 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6870 let mut result = Vec::new();
6871 let qd_num = qreg_to_num(qd);
6872 let qm_num = qreg_to_num(qm);
6873
6874 for i in 0..4u32 {
6876 let sd = qd_num * 4 + i;
6877 let sm = qm_num * 4 + i;
6878
6879 let (vd, d) = encode_sreg(sd);
6880 let (vm, m) = encode_sreg(sm);
6881
6882 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6883 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6884 }
6885
6886 Ok(result)
6887 }
6888}
6889
6890#[cfg(test)]
6891mod tests {
6892 use super::*;
6893
6894 #[test]
6895 fn test_encoder_creation() {
6896 let encoder_arm = ArmEncoder::new_arm32();
6897 assert!(!encoder_arm.thumb_mode);
6898
6899 let encoder_thumb = ArmEncoder::new_thumb2();
6900 assert!(encoder_thumb.thumb_mode);
6901 }
6902
6903 #[test]
6910 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
6911 let encoder = ArmEncoder::new_thumb2();
6912
6913 let code = encoder
6915 .encode(&ArmOp::Add {
6916 rd: Reg::R12,
6917 rn: Reg::R12,
6918 op2: Operand2::Reg(Reg::R0),
6919 })
6920 .unwrap();
6921 assert_eq!(
6923 code,
6924 vec![0x0C, 0xEB, 0x00, 0x0C],
6925 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
6926 );
6927 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
6929
6930 let lo = encoder
6932 .encode(&ArmOp::Add {
6933 rd: Reg::R1,
6934 rn: Reg::R2,
6935 op2: Operand2::Reg(Reg::R3),
6936 })
6937 .unwrap();
6938 assert_eq!(
6939 lo.len(),
6940 2,
6941 "low-reg ADD should remain 16-bit, got {lo:02X?}"
6942 );
6943 }
6944
6945 #[test]
6948 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
6949 let encoder = ArmEncoder::new_thumb2();
6950
6951 let adds = encoder
6953 .encode(&ArmOp::Adds {
6954 rd: Reg::R10,
6955 rn: Reg::R10,
6956 op2: Operand2::Reg(Reg::R8),
6957 })
6958 .unwrap();
6959 assert_eq!(
6960 adds,
6961 vec![0x1A, 0xEB, 0x08, 0x0A],
6962 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
6963 );
6964
6965 let subs = encoder
6967 .encode(&ArmOp::Subs {
6968 rd: Reg::R10,
6969 rn: Reg::R10,
6970 op2: Operand2::Reg(Reg::R8),
6971 })
6972 .unwrap();
6973 assert_eq!(
6974 subs,
6975 vec![0xBA, 0xEB, 0x08, 0x0A],
6976 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
6977 );
6978 }
6979
6980 #[test]
6984 fn test_encode_pc_operand_returns_err_not_panic_185() {
6985 let encoder = ArmEncoder::new_thumb2();
6986 for op in [
6987 ArmOp::Sdiv {
6988 rd: Reg::PC,
6989 rn: Reg::R0,
6990 rm: Reg::R1,
6991 },
6992 ArmOp::Udiv {
6993 rd: Reg::R0,
6994 rn: Reg::PC,
6995 rm: Reg::R1,
6996 },
6997 ArmOp::Sdiv {
6998 rd: Reg::R0,
6999 rn: Reg::R1,
7000 rm: Reg::PC,
7001 },
7002 ] {
7003 let r = encoder.encode(&op);
7004 assert!(
7005 r.is_err(),
7006 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7007 );
7008 }
7009 assert!(
7011 encoder
7012 .encode(&ArmOp::Sdiv {
7013 rd: Reg::R0,
7014 rn: Reg::R1,
7015 rm: Reg::R2
7016 })
7017 .is_ok()
7018 );
7019 }
7020
7021 #[test]
7022 fn test_encode_nop_arm32() {
7023 let encoder = ArmEncoder::new_arm32();
7024 let code = encoder.encode(&ArmOp::Nop).unwrap();
7025
7026 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7029
7030 #[test]
7031 fn test_encode_nop_thumb() {
7032 let encoder = ArmEncoder::new_thumb2();
7033 let code = encoder.encode(&ArmOp::Nop).unwrap();
7034
7035 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7038
7039 #[test]
7040 fn test_encode_mov_immediate_arm32() {
7041 let encoder = ArmEncoder::new_arm32();
7042 let op = ArmOp::Mov {
7043 rd: Reg::R0,
7044 op2: Operand2::Imm(42),
7045 };
7046
7047 let code = encoder.encode(&op).unwrap();
7048 assert_eq!(code.len(), 4);
7049
7050 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7052 assert_eq!(instr & 0x0E000000, 0x02000000); }
7054
7055 #[test]
7056 fn test_encode_add_registers_arm32() {
7057 let encoder = ArmEncoder::new_arm32();
7058 let op = ArmOp::Add {
7059 rd: Reg::R0,
7060 rn: Reg::R1,
7061 op2: Operand2::Reg(Reg::R2),
7062 };
7063
7064 let code = encoder.encode(&op).unwrap();
7065 assert_eq!(code.len(), 4);
7066
7067 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7068 assert_eq!(instr & 0x0FE00000, 0x00800000);
7070 }
7071
7072 #[test]
7073 fn test_encode_ldr_arm32() {
7074 let encoder = ArmEncoder::new_arm32();
7075 let op = ArmOp::Ldr {
7076 rd: Reg::R0,
7077 addr: MemAddr::imm(Reg::R1, 4),
7078 };
7079
7080 let code = encoder.encode(&op).unwrap();
7081 assert_eq!(code.len(), 4);
7082
7083 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7084 assert_eq!(instr & 0x00100000, 0x00100000);
7086 }
7087
7088 #[test]
7089 fn test_encode_str_arm32() {
7090 let encoder = ArmEncoder::new_arm32();
7091 let op = ArmOp::Str {
7092 rd: Reg::R0,
7093 addr: MemAddr::imm(Reg::SP, 0),
7094 };
7095
7096 let code = encoder.encode(&op).unwrap();
7097 assert_eq!(code.len(), 4);
7098 }
7099
7100 #[test]
7101 fn test_encode_branch_arm32() {
7102 let encoder = ArmEncoder::new_arm32();
7103 let op = ArmOp::Bl {
7104 label: "main".to_string(),
7105 };
7106
7107 let code = encoder.encode(&op).unwrap();
7108 assert_eq!(code.len(), 4);
7109
7110 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7111 assert_eq!(instr & 0x0F000000, 0x0B000000);
7113 }
7114
7115 #[test]
7125 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7126 let encoder = ArmEncoder::new_thumb2();
7127 let op = ArmOp::Bl {
7128 label: "callee".to_string(),
7129 };
7130
7131 let code = encoder.encode(&op).unwrap();
7132 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7133
7134 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7135 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7136 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7137 assert_eq!(
7138 hw2, 0xFFFE,
7139 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7140 );
7141 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7142 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7143 }
7144
7145 #[test]
7146 fn test_encode_sequence() {
7147 let encoder = ArmEncoder::new_arm32();
7148 let ops = vec![
7149 ArmOp::Mov {
7150 rd: Reg::R0,
7151 op2: Operand2::Imm(42),
7152 },
7153 ArmOp::Mov {
7154 rd: Reg::R1,
7155 op2: Operand2::Imm(10),
7156 },
7157 ArmOp::Add {
7158 rd: Reg::R2,
7159 rn: Reg::R0,
7160 op2: Operand2::Reg(Reg::R1),
7161 },
7162 ];
7163
7164 let code = encoder.encode_sequence(&ops).unwrap();
7165 assert_eq!(code.len(), 12); }
7167
7168 #[test]
7169 fn test_reg_to_bits() {
7170 assert_eq!(reg_to_bits(&Reg::R0), 0);
7171 assert_eq!(reg_to_bits(&Reg::R7), 7);
7172 assert_eq!(reg_to_bits(&Reg::SP), 13);
7173 assert_eq!(reg_to_bits(&Reg::LR), 14);
7174 assert_eq!(reg_to_bits(&Reg::PC), 15);
7175 }
7176
7177 #[test]
7178 fn test_encode_bitwise_operations() {
7179 let encoder = ArmEncoder::new_arm32();
7180
7181 let and_op = ArmOp::And {
7182 rd: Reg::R0,
7183 rn: Reg::R1,
7184 op2: Operand2::Reg(Reg::R2),
7185 };
7186 let and_code = encoder.encode(&and_op).unwrap();
7187 assert_eq!(and_code.len(), 4);
7188
7189 let orr_op = ArmOp::Orr {
7190 rd: Reg::R0,
7191 rn: Reg::R1,
7192 op2: Operand2::Reg(Reg::R2),
7193 };
7194 let orr_code = encoder.encode(&orr_op).unwrap();
7195 assert_eq!(orr_code.len(), 4);
7196
7197 let eor_op = ArmOp::Eor {
7198 rd: Reg::R0,
7199 rn: Reg::R1,
7200 op2: Operand2::Reg(Reg::R2),
7201 };
7202 let eor_code = encoder.encode(&eor_op).unwrap();
7203 assert_eq!(eor_code.len(), 4);
7204 }
7205
7206 #[test]
7209 fn test_encode_sdiv_thumb2() {
7210 let encoder = ArmEncoder::new_thumb2();
7211 let op = ArmOp::Sdiv {
7212 rd: Reg::R0,
7213 rn: Reg::R1,
7214 rm: Reg::R2,
7215 };
7216
7217 let code = encoder.encode(&op).unwrap();
7218 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7225 assert_eq!(code[1], 0xFB);
7226 assert_eq!(code[2], 0xF2);
7227 assert_eq!(code[3], 0xF0);
7228 }
7229
7230 #[test]
7231 fn test_encode_udiv_thumb2() {
7232 let encoder = ArmEncoder::new_thumb2();
7233 let op = ArmOp::Udiv {
7234 rd: Reg::R0,
7235 rn: Reg::R1,
7236 rm: Reg::R2,
7237 };
7238
7239 let code = encoder.encode(&op).unwrap();
7240 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7245 assert_eq!(code[1], 0xFB);
7246 assert_eq!(code[2], 0xF2);
7247 assert_eq!(code[3], 0xF0);
7248 }
7249
7250 #[test]
7251 fn test_encode_mul_thumb2() {
7252 let encoder = ArmEncoder::new_thumb2();
7253 let op = ArmOp::Mul {
7254 rd: Reg::R0,
7255 rn: Reg::R1,
7256 rm: Reg::R2,
7257 };
7258
7259 let code = encoder.encode(&op).unwrap();
7260 assert_eq!(code.len(), 4); }
7262
7263 #[test]
7264 fn test_encode_and_thumb2() {
7265 let encoder = ArmEncoder::new_thumb2();
7266 let op = ArmOp::And {
7267 rd: Reg::R0,
7268 rn: Reg::R1,
7269 op2: Operand2::Reg(Reg::R2),
7270 };
7271
7272 let code = encoder.encode(&op).unwrap();
7273 assert_eq!(code.len(), 4); }
7275
7276 #[test]
7277 fn test_encode_lsl_thumb2_low_regs() {
7278 let encoder = ArmEncoder::new_thumb2();
7279 let op = ArmOp::Lsl {
7280 rd: Reg::R0,
7281 rn: Reg::R1,
7282 shift: 5,
7283 };
7284
7285 let code = encoder.encode(&op).unwrap();
7286 assert_eq!(code.len(), 2); }
7288
7289 #[test]
7290 fn test_encode_clz_thumb2() {
7291 let encoder = ArmEncoder::new_thumb2();
7292 let op = ArmOp::Clz {
7293 rd: Reg::R0,
7294 rm: Reg::R1,
7295 };
7296
7297 let code = encoder.encode(&op).unwrap();
7298 assert_eq!(code.len(), 4); }
7300
7301 #[test]
7302 fn test_encode_bx_thumb2() {
7303 let encoder = ArmEncoder::new_thumb2();
7304 let op = ArmOp::Bx { rm: Reg::LR };
7305
7306 let code = encoder.encode(&op).unwrap();
7307 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7311 }
7312
7313 #[test]
7318 fn test_encode_f32_abs_arm32() {
7319 let encoder = ArmEncoder::new_arm32();
7320 let op = ArmOp::F32Abs {
7321 sd: VfpReg::S0,
7322 sm: VfpReg::S2,
7323 };
7324 let code = encoder.encode(&op).unwrap();
7325 assert_eq!(code.len(), 4); }
7327
7328 #[test]
7329 fn test_encode_f32_neg_arm32() {
7330 let encoder = ArmEncoder::new_arm32();
7331 let op = ArmOp::F32Neg {
7332 sd: VfpReg::S0,
7333 sm: VfpReg::S2,
7334 };
7335 let code = encoder.encode(&op).unwrap();
7336 assert_eq!(code.len(), 4);
7337 }
7338
7339 #[test]
7340 fn test_encode_f32_sqrt_arm32() {
7341 let encoder = ArmEncoder::new_arm32();
7342 let op = ArmOp::F32Sqrt {
7343 sd: VfpReg::S0,
7344 sm: VfpReg::S2,
7345 };
7346 let code = encoder.encode(&op).unwrap();
7347 assert_eq!(code.len(), 4);
7348 }
7349
7350 #[test]
7351 fn test_encode_f32_ceil_arm32() {
7352 let encoder = ArmEncoder::new_arm32();
7353 let op = ArmOp::F32Ceil {
7354 sd: VfpReg::S0,
7355 sm: VfpReg::S2,
7356 };
7357 let code = encoder.encode(&op).unwrap();
7358 assert_eq!(code.len(), 36);
7360 }
7361
7362 #[test]
7363 fn test_encode_f32_floor_thumb2() {
7364 let encoder = ArmEncoder::new_thumb2();
7365 let op = ArmOp::F32Floor {
7366 sd: VfpReg::S0,
7367 sm: VfpReg::S2,
7368 };
7369 let code = encoder.encode(&op).unwrap();
7370 assert_eq!(code.len(), 36);
7372 }
7373
7374 #[test]
7375 fn test_encode_f32_min_arm32() {
7376 let encoder = ArmEncoder::new_arm32();
7377 let op = ArmOp::F32Min {
7378 sd: VfpReg::S0,
7379 sn: VfpReg::S2,
7380 sm: VfpReg::S4,
7381 };
7382 let code = encoder.encode(&op).unwrap();
7383 assert_eq!(code.len(), 16); }
7385
7386 #[test]
7387 fn test_encode_f32_max_thumb2() {
7388 let encoder = ArmEncoder::new_thumb2();
7389 let op = ArmOp::F32Max {
7390 sd: VfpReg::S0,
7391 sn: VfpReg::S2,
7392 sm: VfpReg::S4,
7393 };
7394 let code = encoder.encode(&op).unwrap();
7395 assert_eq!(code.len(), 18);
7397 }
7398
7399 #[test]
7400 fn test_encode_f32_copysign_arm32() {
7401 let encoder = ArmEncoder::new_arm32();
7402 let op = ArmOp::F32Copysign {
7403 sd: VfpReg::S0,
7404 sn: VfpReg::S2,
7405 sm: VfpReg::S4,
7406 };
7407 let code = encoder.encode(&op).unwrap();
7408 assert_eq!(code.len(), 24);
7410 }
7411
7412 #[test]
7417 fn test_encode_f64_add_arm32() {
7418 let encoder = ArmEncoder::new_arm32();
7419 let op = ArmOp::F64Add {
7420 dd: VfpReg::D0,
7421 dn: VfpReg::D1,
7422 dm: VfpReg::D2,
7423 };
7424 let code = encoder.encode(&op).unwrap();
7425 assert_eq!(code.len(), 4);
7426 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7428 assert_eq!((instr >> 8) & 0xF, 0xB); }
7430
7431 #[test]
7432 fn test_encode_f64_sub_thumb2() {
7433 let encoder = ArmEncoder::new_thumb2();
7434 let op = ArmOp::F64Sub {
7435 dd: VfpReg::D0,
7436 dn: VfpReg::D1,
7437 dm: VfpReg::D2,
7438 };
7439 let code = encoder.encode(&op).unwrap();
7440 assert_eq!(code.len(), 4); }
7442
7443 #[test]
7444 fn test_encode_f64_mul_arm32() {
7445 let encoder = ArmEncoder::new_arm32();
7446 let op = ArmOp::F64Mul {
7447 dd: VfpReg::D0,
7448 dn: VfpReg::D1,
7449 dm: VfpReg::D2,
7450 };
7451 let code = encoder.encode(&op).unwrap();
7452 assert_eq!(code.len(), 4);
7453 }
7454
7455 #[test]
7456 fn test_encode_f64_div_arm32() {
7457 let encoder = ArmEncoder::new_arm32();
7458 let op = ArmOp::F64Div {
7459 dd: VfpReg::D0,
7460 dn: VfpReg::D1,
7461 dm: VfpReg::D2,
7462 };
7463 let code = encoder.encode(&op).unwrap();
7464 assert_eq!(code.len(), 4);
7465 }
7466
7467 #[test]
7468 fn test_encode_f64_abs_arm32() {
7469 let encoder = ArmEncoder::new_arm32();
7470 let op = ArmOp::F64Abs {
7471 dd: VfpReg::D0,
7472 dm: VfpReg::D2,
7473 };
7474 let code = encoder.encode(&op).unwrap();
7475 assert_eq!(code.len(), 4);
7476 }
7477
7478 #[test]
7479 fn test_encode_f64_neg_arm32() {
7480 let encoder = ArmEncoder::new_arm32();
7481 let op = ArmOp::F64Neg {
7482 dd: VfpReg::D0,
7483 dm: VfpReg::D2,
7484 };
7485 let code = encoder.encode(&op).unwrap();
7486 assert_eq!(code.len(), 4);
7487 }
7488
7489 #[test]
7490 fn test_encode_f64_sqrt_arm32() {
7491 let encoder = ArmEncoder::new_arm32();
7492 let op = ArmOp::F64Sqrt {
7493 dd: VfpReg::D0,
7494 dm: VfpReg::D2,
7495 };
7496 let code = encoder.encode(&op).unwrap();
7497 assert_eq!(code.len(), 4);
7498 }
7499
7500 #[test]
7501 fn test_encode_f64_load_arm32() {
7502 let encoder = ArmEncoder::new_arm32();
7503 let op = ArmOp::F64Load {
7504 dd: VfpReg::D0,
7505 addr: MemAddr::imm(Reg::R0, 8),
7506 };
7507 let code = encoder.encode(&op).unwrap();
7508 assert_eq!(code.len(), 4);
7509 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7510 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7513
7514 #[test]
7515 fn test_encode_f64_store_thumb2() {
7516 let encoder = ArmEncoder::new_thumb2();
7517 let op = ArmOp::F64Store {
7518 dd: VfpReg::D0,
7519 addr: MemAddr::imm(Reg::SP, 0),
7520 };
7521 let code = encoder.encode(&op).unwrap();
7522 assert_eq!(code.len(), 4);
7523 }
7524
7525 #[test]
7526 fn test_encode_f64_compare_arm32() {
7527 let encoder = ArmEncoder::new_arm32();
7528 let op = ArmOp::F64Eq {
7529 rd: Reg::R0,
7530 dn: VfpReg::D0,
7531 dm: VfpReg::D1,
7532 };
7533 let code = encoder.encode(&op).unwrap();
7534 assert_eq!(code.len(), 16); }
7536
7537 #[test]
7538 fn test_encode_f64_compare_thumb2() {
7539 let encoder = ArmEncoder::new_thumb2();
7540 let op = ArmOp::F64Lt {
7541 rd: Reg::R0,
7542 dn: VfpReg::D0,
7543 dm: VfpReg::D1,
7544 };
7545 let code = encoder.encode(&op).unwrap();
7546 assert_eq!(code.len(), 14);
7548 }
7549
7550 #[test]
7551 fn test_encode_f64_const_arm32() {
7552 let encoder = ArmEncoder::new_arm32();
7553 let op = ArmOp::F64Const {
7554 dd: VfpReg::D0,
7555 value: 3.125,
7556 };
7557 let code = encoder.encode(&op).unwrap();
7558 assert_eq!(code.len(), 20);
7560 }
7561
7562 #[test]
7563 fn test_encode_f64_const_thumb2() {
7564 let encoder = ArmEncoder::new_thumb2();
7565 let op = ArmOp::F64Const {
7566 dd: VfpReg::D0,
7567 value: 2.5,
7568 };
7569 let code = encoder.encode(&op).unwrap();
7570 assert_eq!(code.len(), 20);
7572 }
7573
7574 #[test]
7575 fn test_encode_f64_convert_i32s_arm32() {
7576 let encoder = ArmEncoder::new_arm32();
7577 let op = ArmOp::F64ConvertI32S {
7578 dd: VfpReg::D0,
7579 rm: Reg::R0,
7580 };
7581 let code = encoder.encode(&op).unwrap();
7582 assert_eq!(code.len(), 8);
7584 }
7585
7586 #[test]
7587 fn test_encode_f64_promote_f32_arm32() {
7588 let encoder = ArmEncoder::new_arm32();
7589 let op = ArmOp::F64PromoteF32 {
7590 dd: VfpReg::D0,
7591 sm: VfpReg::S0,
7592 };
7593 let code = encoder.encode(&op).unwrap();
7594 assert_eq!(code.len(), 4); }
7596
7597 #[test]
7598 fn test_encode_f64_promote_f32_thumb2() {
7599 let encoder = ArmEncoder::new_thumb2();
7600 let op = ArmOp::F64PromoteF32 {
7601 dd: VfpReg::D0,
7602 sm: VfpReg::S0,
7603 };
7604 let code = encoder.encode(&op).unwrap();
7605 assert_eq!(code.len(), 4);
7606 }
7607
7608 #[test]
7609 fn test_encode_i32_trunc_f64s_arm32() {
7610 let encoder = ArmEncoder::new_arm32();
7611 let op = ArmOp::I32TruncF64S {
7612 rd: Reg::R0,
7613 dm: VfpReg::D0,
7614 };
7615 let code = encoder.encode(&op).unwrap();
7616 assert_eq!(code.len(), 8);
7618 }
7619
7620 #[test]
7621 fn test_encode_f64_reinterpret_i64_arm32() {
7622 let encoder = ArmEncoder::new_arm32();
7623 let op = ArmOp::F64ReinterpretI64 {
7624 dd: VfpReg::D0,
7625 rmlo: Reg::R0,
7626 rmhi: Reg::R1,
7627 };
7628 let code = encoder.encode(&op).unwrap();
7629 assert_eq!(code.len(), 4); }
7631
7632 #[test]
7633 fn test_encode_i64_reinterpret_f64_thumb2() {
7634 let encoder = ArmEncoder::new_thumb2();
7635 let op = ArmOp::I64ReinterpretF64 {
7636 rdlo: Reg::R0,
7637 rdhi: Reg::R1,
7638 dm: VfpReg::D0,
7639 };
7640 let code = encoder.encode(&op).unwrap();
7641 assert_eq!(code.len(), 4);
7642 }
7643
7644 #[test]
7645 fn test_encode_f64_trunc_thumb2() {
7646 let encoder = ArmEncoder::new_thumb2();
7647 let op = ArmOp::F64Trunc {
7648 dd: VfpReg::D0,
7649 dm: VfpReg::D1,
7650 };
7651 let code = encoder.encode(&op).unwrap();
7652 assert_eq!(code.len(), 8);
7654 }
7655
7656 #[test]
7657 fn test_encode_f64_min_arm32() {
7658 let encoder = ArmEncoder::new_arm32();
7659 let op = ArmOp::F64Min {
7660 dd: VfpReg::D0,
7661 dn: VfpReg::D1,
7662 dm: VfpReg::D2,
7663 };
7664 let code = encoder.encode(&op).unwrap();
7665 assert_eq!(code.len(), 16);
7667 }
7668
7669 #[test]
7670 fn test_f64_cp11_encoding() {
7671 let encoder = ArmEncoder::new_arm32();
7673
7674 let code = encoder
7676 .encode(&ArmOp::F64Add {
7677 dd: VfpReg::D0,
7678 dn: VfpReg::D0,
7679 dm: VfpReg::D0,
7680 })
7681 .unwrap();
7682 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7683 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7684
7685 let code = encoder
7687 .encode(&ArmOp::F32Add {
7688 sd: VfpReg::S0,
7689 sn: VfpReg::S0,
7690 sm: VfpReg::S0,
7691 })
7692 .unwrap();
7693 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7694 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7695 }
7696
7697 #[test]
7698 fn test_dreg_encoding_higher_registers() {
7699 let encoder = ArmEncoder::new_arm32();
7700
7701 let op = ArmOp::F64Add {
7703 dd: VfpReg::D15,
7704 dn: VfpReg::D14,
7705 dm: VfpReg::D13,
7706 };
7707 let code = encoder.encode(&op).unwrap();
7708 assert_eq!(code.len(), 4);
7709
7710 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7712 assert_eq!((instr >> 8) & 0xF, 0xB); }
7714
7715 #[test]
7720 fn test_encode_label_emits_no_bytes() {
7721 let encoder = ArmEncoder::new_thumb2();
7722 let op = ArmOp::Label {
7723 name: ".Lblock_end_0".to_string(),
7724 };
7725 let code = encoder.encode(&op).unwrap();
7726 assert!(code.is_empty(), "Label should emit zero bytes");
7727
7728 let encoder32 = ArmEncoder::new_arm32();
7729 let code32 = encoder32.encode(&op).unwrap();
7730 assert!(
7731 code32.is_empty(),
7732 "Label should emit zero bytes in ARM32 too"
7733 );
7734 }
7735
7736 #[test]
7737 fn test_encode_bcc_eq_thumb2() {
7738 use synth_synthesis::Condition;
7739 let encoder = ArmEncoder::new_thumb2();
7740 let op = ArmOp::Bcc {
7741 cond: Condition::EQ,
7742 label: "target".to_string(),
7743 };
7744 let code = encoder.encode(&op).unwrap();
7745 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7749 }
7750
7751 #[test]
7752 fn test_encode_bcc_ne_thumb2() {
7753 use synth_synthesis::Condition;
7754 let encoder = ArmEncoder::new_thumb2();
7755 let op = ArmOp::Bcc {
7756 cond: Condition::NE,
7757 label: "target".to_string(),
7758 };
7759 let code = encoder.encode(&op).unwrap();
7760 assert_eq!(code.len(), 2);
7761
7762 assert_eq!(code, vec![0x00, 0xD1]);
7764 }
7765
7766 #[test]
7767 fn test_encode_bcc_arm32() {
7768 use synth_synthesis::Condition;
7769 let encoder = ArmEncoder::new_arm32();
7770 let op = ArmOp::Bcc {
7771 cond: Condition::EQ,
7772 label: "target".to_string(),
7773 };
7774 let code = encoder.encode(&op).unwrap();
7775 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7778 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7782
7783 #[test]
7784 fn test_encode_udf_thumb2() {
7785 let encoder = ArmEncoder::new_thumb2();
7786 let op = ArmOp::Udf { imm: 0 };
7787 let code = encoder.encode(&op).unwrap();
7788 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
7792 }
7793
7794 #[test]
7795 fn test_encode_nop_thumb2() {
7796 let encoder = ArmEncoder::new_thumb2();
7797 let op = ArmOp::Nop;
7798 let code = encoder.encode(&op).unwrap();
7799 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
7803 }
7804
7805 #[test]
7810 fn test_encode_i64_add_thumb2() {
7811 let encoder = ArmEncoder::new_thumb2();
7812 let op = ArmOp::I64Add {
7813 rdlo: Reg::R0,
7814 rdhi: Reg::R1,
7815 rnlo: Reg::R0,
7816 rnhi: Reg::R1,
7817 rmlo: Reg::R2,
7818 rmhi: Reg::R3,
7819 };
7820 let code = encoder.encode(&op).unwrap();
7821 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
7823 }
7824
7825 #[test]
7826 fn test_encode_i64_sub_thumb2() {
7827 let encoder = ArmEncoder::new_thumb2();
7828 let op = ArmOp::I64Sub {
7829 rdlo: Reg::R0,
7830 rdhi: Reg::R1,
7831 rnlo: Reg::R0,
7832 rnhi: Reg::R1,
7833 rmlo: Reg::R2,
7834 rmhi: Reg::R3,
7835 };
7836 let code = encoder.encode(&op).unwrap();
7837 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
7839 }
7840
7841 #[test]
7842 fn test_encode_i64_and_thumb2() {
7843 let encoder = ArmEncoder::new_thumb2();
7844 let op = ArmOp::I64And {
7845 rdlo: Reg::R0,
7846 rdhi: Reg::R1,
7847 rnlo: Reg::R0,
7848 rnhi: Reg::R1,
7849 rmlo: Reg::R2,
7850 rmhi: Reg::R3,
7851 };
7852 let code = encoder.encode(&op).unwrap();
7853 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
7855 }
7856
7857 #[test]
7858 fn test_encode_i64_or_thumb2() {
7859 let encoder = ArmEncoder::new_thumb2();
7860 let op = ArmOp::I64Or {
7861 rdlo: Reg::R0,
7862 rdhi: Reg::R1,
7863 rnlo: Reg::R0,
7864 rnhi: Reg::R1,
7865 rmlo: Reg::R2,
7866 rmhi: Reg::R3,
7867 };
7868 let code = encoder.encode(&op).unwrap();
7869 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
7870 }
7871
7872 #[test]
7873 fn test_encode_i64_xor_thumb2() {
7874 let encoder = ArmEncoder::new_thumb2();
7875 let op = ArmOp::I64Xor {
7876 rdlo: Reg::R0,
7877 rdhi: Reg::R1,
7878 rnlo: Reg::R0,
7879 rnhi: Reg::R1,
7880 rmlo: Reg::R2,
7881 rmhi: Reg::R3,
7882 };
7883 let code = encoder.encode(&op).unwrap();
7884 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
7885 }
7886
7887 #[test]
7888 fn test_encode_i64_const_small_thumb2() {
7889 let encoder = ArmEncoder::new_thumb2();
7890 let op = ArmOp::I64Const {
7892 rdlo: Reg::R0,
7893 rdhi: Reg::R1,
7894 value: 42,
7895 };
7896 let code = encoder.encode(&op).unwrap();
7897 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
7899 }
7900
7901 #[test]
7902 fn test_encode_i64_const_large_thumb2() {
7903 let encoder = ArmEncoder::new_thumb2();
7904 let op = ArmOp::I64Const {
7906 rdlo: Reg::R0,
7907 rdhi: Reg::R1,
7908 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
7909 };
7910 let code = encoder.encode(&op).unwrap();
7911 assert_eq!(
7913 code.len(),
7914 16,
7915 "I64Const with large value should be 16 bytes"
7916 );
7917 }
7918
7919 #[test]
7920 fn test_encode_i64_extend_i32_s_thumb2() {
7921 let encoder = ArmEncoder::new_thumb2();
7922 let op = ArmOp::I64ExtendI32S {
7923 rdlo: Reg::R0,
7924 rdhi: Reg::R1,
7925 rn: Reg::R0,
7926 };
7927 let code = encoder.encode(&op).unwrap();
7928 assert_eq!(
7930 code.len(),
7931 4,
7932 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
7933 );
7934 }
7935
7936 #[test]
7937 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
7938 let encoder = ArmEncoder::new_thumb2();
7939 let op = ArmOp::I64ExtendI32S {
7940 rdlo: Reg::R0,
7941 rdhi: Reg::R1,
7942 rn: Reg::R2,
7943 };
7944 let code = encoder.encode(&op).unwrap();
7945 assert!(
7947 code.len() >= 6,
7948 "I64ExtendI32S (diff reg) should be at least 6 bytes"
7949 );
7950 }
7951
7952 #[test]
7953 fn test_encode_i64_extend_i32_u_thumb2() {
7954 let encoder = ArmEncoder::new_thumb2();
7955 let op = ArmOp::I64ExtendI32U {
7956 rdlo: Reg::R0,
7957 rdhi: Reg::R1,
7958 rn: Reg::R0,
7959 };
7960 let code = encoder.encode(&op).unwrap();
7961 assert_eq!(
7963 code.len(),
7964 2,
7965 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
7966 );
7967 }
7968
7969 #[test]
7970 fn test_encode_i32_wrap_i64_nop_thumb2() {
7971 let encoder = ArmEncoder::new_thumb2();
7972 let op = ArmOp::I32WrapI64 {
7974 rd: Reg::R0,
7975 rnlo: Reg::R0,
7976 };
7977 let code = encoder.encode(&op).unwrap();
7978 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
7979 assert_eq!(code, vec![0x00, 0xBF]); }
7981
7982 #[test]
7983 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
7984 let encoder = ArmEncoder::new_thumb2();
7985 let op = ArmOp::I32WrapI64 {
7986 rd: Reg::R2,
7987 rnlo: Reg::R0,
7988 };
7989 let code = encoder.encode(&op).unwrap();
7990 assert!(
7992 code.len() >= 2,
7993 "I32WrapI64 diff reg should emit at least 2 bytes"
7994 );
7995 }
7996
7997 #[test]
7998 fn test_encode_i64_eqz_thumb2() {
7999 let encoder = ArmEncoder::new_thumb2();
8000 let op = ArmOp::I64Eqz {
8001 rd: Reg::R0,
8002 rnlo: Reg::R0,
8003 rnhi: Reg::R1,
8004 };
8005 let code = encoder.encode(&op).unwrap();
8006 assert!(
8008 code.len() >= 6,
8009 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8010 );
8011 }
8012
8013 #[test]
8014 fn test_encode_i64_eq_thumb2() {
8015 let encoder = ArmEncoder::new_thumb2();
8016 let op = ArmOp::I64Eq {
8017 rd: Reg::R0,
8018 rnlo: Reg::R0,
8019 rnhi: Reg::R1,
8020 rmlo: Reg::R2,
8021 rmhi: Reg::R3,
8022 };
8023 let code = encoder.encode(&op).unwrap();
8024 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8026 }
8027
8028 #[test]
8029 fn test_encode_i64_ldr_thumb2() {
8030 let encoder = ArmEncoder::new_thumb2();
8031 let op = ArmOp::I64Ldr {
8032 rdlo: Reg::R0,
8033 rdhi: Reg::R1,
8034 addr: MemAddr::imm(Reg::SP, 0),
8035 };
8036 let code = encoder.encode(&op).unwrap();
8037 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8039 }
8040
8041 #[test]
8042 fn test_encode_i64_str_thumb2() {
8043 let encoder = ArmEncoder::new_thumb2();
8044 let op = ArmOp::I64Str {
8045 rdlo: Reg::R0,
8046 rdhi: Reg::R1,
8047 addr: MemAddr::imm(Reg::SP, 0),
8048 };
8049 let code = encoder.encode(&op).unwrap();
8050 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8052 }
8053
8054 #[test]
8055 fn test_encode_i64_all_comparisons_thumb2() {
8056 let encoder = ArmEncoder::new_thumb2();
8057
8058 let ops = vec![
8059 ArmOp::I64Ne {
8060 rd: Reg::R0,
8061 rnlo: Reg::R0,
8062 rnhi: Reg::R1,
8063 rmlo: Reg::R2,
8064 rmhi: Reg::R3,
8065 },
8066 ArmOp::I64LtS {
8067 rd: Reg::R0,
8068 rnlo: Reg::R0,
8069 rnhi: Reg::R1,
8070 rmlo: Reg::R2,
8071 rmhi: Reg::R3,
8072 },
8073 ArmOp::I64LtU {
8074 rd: Reg::R0,
8075 rnlo: Reg::R0,
8076 rnhi: Reg::R1,
8077 rmlo: Reg::R2,
8078 rmhi: Reg::R3,
8079 },
8080 ArmOp::I64LeS {
8081 rd: Reg::R0,
8082 rnlo: Reg::R0,
8083 rnhi: Reg::R1,
8084 rmlo: Reg::R2,
8085 rmhi: Reg::R3,
8086 },
8087 ArmOp::I64LeU {
8088 rd: Reg::R0,
8089 rnlo: Reg::R0,
8090 rnhi: Reg::R1,
8091 rmlo: Reg::R2,
8092 rmhi: Reg::R3,
8093 },
8094 ArmOp::I64GtS {
8095 rd: Reg::R0,
8096 rnlo: Reg::R0,
8097 rnhi: Reg::R1,
8098 rmlo: Reg::R2,
8099 rmhi: Reg::R3,
8100 },
8101 ArmOp::I64GtU {
8102 rd: Reg::R0,
8103 rnlo: Reg::R0,
8104 rnhi: Reg::R1,
8105 rmlo: Reg::R2,
8106 rmhi: Reg::R3,
8107 },
8108 ArmOp::I64GeS {
8109 rd: Reg::R0,
8110 rnlo: Reg::R0,
8111 rnhi: Reg::R1,
8112 rmlo: Reg::R2,
8113 rmhi: Reg::R3,
8114 },
8115 ArmOp::I64GeU {
8116 rd: Reg::R0,
8117 rnlo: Reg::R0,
8118 rnhi: Reg::R1,
8119 rmlo: Reg::R2,
8120 rmhi: Reg::R3,
8121 },
8122 ];
8123
8124 for op in &ops {
8125 let code = encoder.encode(op).unwrap();
8126 assert!(
8127 code.len() >= 8,
8128 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8129 op,
8130 code.len()
8131 );
8132 }
8133 }
8134
8135 #[test]
8136 fn test_encode_i64_const_zero_thumb2() {
8137 let encoder = ArmEncoder::new_thumb2();
8138 let op = ArmOp::I64Const {
8139 rdlo: Reg::R0,
8140 rdhi: Reg::R1,
8141 value: 0,
8142 };
8143 let code = encoder.encode(&op).unwrap();
8144 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8146 }
8147
8148 #[test]
8149 fn test_encode_i64_const_negative_one_thumb2() {
8150 let encoder = ArmEncoder::new_thumb2();
8151 let op = ArmOp::I64Const {
8152 rdlo: Reg::R0,
8153 rdhi: Reg::R1,
8154 value: -1, };
8156 let code = encoder.encode(&op).unwrap();
8157 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8159 }
8160
8161 #[test]
8166 fn test_encode_ldrb_arm32() {
8167 let encoder = ArmEncoder::new_arm32();
8168 let op = ArmOp::Ldrb {
8169 rd: Reg::R0,
8170 addr: MemAddr::imm(Reg::R1, 4),
8171 };
8172 let code = encoder.encode(&op).unwrap();
8173 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8174 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8176 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8177 }
8178
8179 #[test]
8180 fn test_encode_strb_arm32() {
8181 let encoder = ArmEncoder::new_arm32();
8182 let op = ArmOp::Strb {
8183 rd: Reg::R0,
8184 addr: MemAddr::imm(Reg::R1, 0),
8185 };
8186 let code = encoder.encode(&op).unwrap();
8187 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8188 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8190 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8191 }
8192
8193 #[test]
8194 fn test_encode_ldrh_arm32() {
8195 let encoder = ArmEncoder::new_arm32();
8196 let op = ArmOp::Ldrh {
8197 rd: Reg::R0,
8198 addr: MemAddr::imm(Reg::R1, 2),
8199 };
8200 let code = encoder.encode(&op).unwrap();
8201 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8202 }
8203
8204 #[test]
8205 fn test_encode_strh_arm32() {
8206 let encoder = ArmEncoder::new_arm32();
8207 let op = ArmOp::Strh {
8208 rd: Reg::R0,
8209 addr: MemAddr::imm(Reg::R1, 0),
8210 };
8211 let code = encoder.encode(&op).unwrap();
8212 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8213 }
8214
8215 #[test]
8216 fn test_encode_ldrsb_arm32() {
8217 let encoder = ArmEncoder::new_arm32();
8218 let op = ArmOp::Ldrsb {
8219 rd: Reg::R0,
8220 addr: MemAddr::imm(Reg::R1, 0),
8221 };
8222 let code = encoder.encode(&op).unwrap();
8223 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8224 }
8225
8226 #[test]
8227 fn test_encode_ldrsh_arm32() {
8228 let encoder = ArmEncoder::new_arm32();
8229 let op = ArmOp::Ldrsh {
8230 rd: Reg::R0,
8231 addr: MemAddr::imm(Reg::R1, 0),
8232 };
8233 let code = encoder.encode(&op).unwrap();
8234 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8235 }
8236
8237 #[test]
8238 fn test_encode_ldrb_thumb2_16bit() {
8239 let encoder = ArmEncoder::new_thumb2();
8240 let op = ArmOp::Ldrb {
8241 rd: Reg::R0,
8242 addr: MemAddr::imm(Reg::R1, 4),
8243 };
8244 let code = encoder.encode(&op).unwrap();
8245 assert_eq!(
8247 code.len(),
8248 2,
8249 "Thumb-2 LDRB with small offset should be 16-bit"
8250 );
8251 }
8252
8253 #[test]
8254 fn test_encode_ldrb_thumb2_32bit() {
8255 let encoder = ArmEncoder::new_thumb2();
8256 let op = ArmOp::Ldrb {
8257 rd: Reg::R0,
8258 addr: MemAddr::imm(Reg::R1, 100), };
8260 let code = encoder.encode(&op).unwrap();
8261 assert_eq!(
8262 code.len(),
8263 4,
8264 "Thumb-2 LDRB with large offset should be 32-bit"
8265 );
8266 }
8267
8268 #[test]
8269 fn test_encode_strb_thumb2_16bit() {
8270 let encoder = ArmEncoder::new_thumb2();
8271 let op = ArmOp::Strb {
8272 rd: Reg::R0,
8273 addr: MemAddr::imm(Reg::R1, 10),
8274 };
8275 let code = encoder.encode(&op).unwrap();
8276 assert_eq!(
8277 code.len(),
8278 2,
8279 "Thumb-2 STRB with small offset should be 16-bit"
8280 );
8281 }
8282
8283 #[test]
8284 fn test_encode_ldrh_thumb2_16bit() {
8285 let encoder = ArmEncoder::new_thumb2();
8286 let op = ArmOp::Ldrh {
8287 rd: Reg::R0,
8288 addr: MemAddr::imm(Reg::R1, 4), };
8290 let code = encoder.encode(&op).unwrap();
8291 assert_eq!(
8292 code.len(),
8293 2,
8294 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8295 );
8296 }
8297
8298 #[test]
8299 fn test_encode_strh_thumb2_16bit() {
8300 let encoder = ArmEncoder::new_thumb2();
8301 let op = ArmOp::Strh {
8302 rd: Reg::R0,
8303 addr: MemAddr::imm(Reg::R1, 4),
8304 };
8305 let code = encoder.encode(&op).unwrap();
8306 assert_eq!(
8307 code.len(),
8308 2,
8309 "Thumb-2 STRH with small aligned offset should be 16-bit"
8310 );
8311 }
8312
8313 #[test]
8314 fn test_encode_ldrsb_thumb2() {
8315 let encoder = ArmEncoder::new_thumb2();
8316 let op = ArmOp::Ldrsb {
8317 rd: Reg::R0,
8318 addr: MemAddr::imm(Reg::R1, 0),
8319 };
8320 let code = encoder.encode(&op).unwrap();
8321 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8323 }
8324
8325 #[test]
8326 fn test_encode_ldrsh_thumb2() {
8327 let encoder = ArmEncoder::new_thumb2();
8328 let op = ArmOp::Ldrsh {
8329 rd: Reg::R0,
8330 addr: MemAddr::imm(Reg::R1, 0),
8331 };
8332 let code = encoder.encode(&op).unwrap();
8333 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8334 }
8335
8336 #[test]
8337 fn test_encode_memory_size_thumb2() {
8338 let encoder = ArmEncoder::new_thumb2();
8339 let op = ArmOp::MemorySize { rd: Reg::R0 };
8340 let code = encoder.encode(&op).unwrap();
8341 assert!(!code.is_empty(), "MemorySize should produce code");
8343 }
8344
8345 #[test]
8346 fn test_encode_memory_grow_thumb2() {
8347 let encoder = ArmEncoder::new_thumb2();
8348 let op = ArmOp::MemoryGrow {
8349 rd: Reg::R0,
8350 rn: Reg::R0,
8351 };
8352 let code = encoder.encode(&op).unwrap();
8353 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8354 }
8355
8356 #[test]
8357 fn test_encode_subword_reg_offset_thumb2() {
8358 let encoder = ArmEncoder::new_thumb2();
8359
8360 let op = ArmOp::Ldrb {
8362 rd: Reg::R0,
8363 addr: MemAddr::reg(Reg::R1, Reg::R2),
8364 };
8365 let code = encoder.encode(&op).unwrap();
8366 assert_eq!(
8367 code.len(),
8368 4,
8369 "Thumb-2 LDRB with reg offset should be 32-bit"
8370 );
8371
8372 let op = ArmOp::Strb {
8374 rd: Reg::R0,
8375 addr: MemAddr::reg(Reg::R1, Reg::R2),
8376 };
8377 let code = encoder.encode(&op).unwrap();
8378 assert_eq!(
8379 code.len(),
8380 4,
8381 "Thumb-2 STRB with reg offset should be 32-bit"
8382 );
8383
8384 let op = ArmOp::Ldrh {
8386 rd: Reg::R0,
8387 addr: MemAddr::reg(Reg::R1, Reg::R2),
8388 };
8389 let code = encoder.encode(&op).unwrap();
8390 assert_eq!(
8391 code.len(),
8392 4,
8393 "Thumb-2 LDRH with reg offset should be 32-bit"
8394 );
8395
8396 let op = ArmOp::Strh {
8398 rd: Reg::R0,
8399 addr: MemAddr::reg(Reg::R1, Reg::R2),
8400 };
8401 let code = encoder.encode(&op).unwrap();
8402 assert_eq!(
8403 code.len(),
8404 4,
8405 "Thumb-2 STRH with reg offset should be 32-bit"
8406 );
8407 }
8408
8409 #[test]
8410 fn test_encode_subword_reg_imm_offset_thumb2() {
8411 let encoder = ArmEncoder::new_thumb2();
8412
8413 let op = ArmOp::Ldrb {
8415 rd: Reg::R0,
8416 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8417 };
8418 let code = encoder.encode(&op).unwrap();
8419 assert_eq!(
8421 code.len(),
8422 8,
8423 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8424 );
8425 }
8426
8427 #[test]
8432 fn test_encode_mve_addi32_thumb2() {
8433 let encoder = ArmEncoder::new_thumb2();
8434 let op = ArmOp::MveAddI {
8435 qd: QReg::Q0,
8436 qn: QReg::Q1,
8437 qm: QReg::Q2,
8438 size: MveSize::S32,
8439 };
8440 let code = encoder.encode(&op).unwrap();
8441 assert_eq!(
8442 code.len(),
8443 4,
8444 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8445 );
8446 }
8447
8448 #[test]
8449 fn test_encode_mve_subi16_thumb2() {
8450 let encoder = ArmEncoder::new_thumb2();
8451 let op = ArmOp::MveSubI {
8452 qd: QReg::Q0,
8453 qn: QReg::Q1,
8454 qm: QReg::Q2,
8455 size: MveSize::S16,
8456 };
8457 let code = encoder.encode(&op).unwrap();
8458 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8459 }
8460
8461 #[test]
8462 fn test_encode_mve_muli8_thumb2() {
8463 let encoder = ArmEncoder::new_thumb2();
8464 let op = ArmOp::MveMulI {
8465 qd: QReg::Q0,
8466 qn: QReg::Q1,
8467 qm: QReg::Q2,
8468 size: MveSize::S8,
8469 };
8470 let code = encoder.encode(&op).unwrap();
8471 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8472 }
8473
8474 #[test]
8475 fn test_encode_mve_bitwise_thumb2() {
8476 let encoder = ArmEncoder::new_thumb2();
8477
8478 let ops = vec![
8479 ArmOp::MveAnd {
8480 qd: QReg::Q0,
8481 qn: QReg::Q1,
8482 qm: QReg::Q2,
8483 },
8484 ArmOp::MveOrr {
8485 qd: QReg::Q0,
8486 qn: QReg::Q1,
8487 qm: QReg::Q2,
8488 },
8489 ArmOp::MveEor {
8490 qd: QReg::Q0,
8491 qn: QReg::Q1,
8492 qm: QReg::Q2,
8493 },
8494 ArmOp::MveBic {
8495 qd: QReg::Q0,
8496 qn: QReg::Q1,
8497 qm: QReg::Q2,
8498 },
8499 ];
8500 for op in ops {
8501 let code = encoder.encode(&op).unwrap();
8502 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8503 }
8504 }
8505
8506 #[test]
8507 fn test_encode_mve_mvn_thumb2() {
8508 let encoder = ArmEncoder::new_thumb2();
8509 let op = ArmOp::MveMvn {
8510 qd: QReg::Q0,
8511 qm: QReg::Q1,
8512 };
8513 let code = encoder.encode(&op).unwrap();
8514 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8515 }
8516
8517 #[test]
8518 fn test_encode_mve_load_store_thumb2() {
8519 let encoder = ArmEncoder::new_thumb2();
8520
8521 let load = ArmOp::MveLoad {
8522 qd: QReg::Q0,
8523 addr: MemAddr::imm(Reg::R0, 16),
8524 };
8525 let code = encoder.encode(&load).unwrap();
8526 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8527
8528 let store = ArmOp::MveStore {
8529 qd: QReg::Q1,
8530 addr: MemAddr::imm(Reg::R1, 0),
8531 };
8532 let code = encoder.encode(&store).unwrap();
8533 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8534 }
8535
8536 #[test]
8537 fn test_encode_mve_const_thumb2() {
8538 let encoder = ArmEncoder::new_thumb2();
8539 let op = ArmOp::MveConst {
8540 qd: QReg::Q0,
8541 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8542 };
8543 let code = encoder.encode(&op).unwrap();
8544 assert!(
8547 code.len() >= 24,
8548 "MVE const should produce multiple instructions"
8549 );
8550 }
8551
8552 #[test]
8553 fn test_encode_mve_dup_thumb2() {
8554 let encoder = ArmEncoder::new_thumb2();
8555 let op = ArmOp::MveDup {
8556 qd: QReg::Q0,
8557 rn: Reg::R0,
8558 size: MveSize::S32,
8559 };
8560 let code = encoder.encode(&op).unwrap();
8561 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8562 }
8563
8564 #[test]
8565 fn test_encode_mve_extract_lane_thumb2() {
8566 let encoder = ArmEncoder::new_thumb2();
8567 let op = ArmOp::MveExtractLane {
8568 rd: Reg::R0,
8569 qn: QReg::Q1,
8570 lane: 2,
8571 size: MveSize::S32,
8572 };
8573 let code = encoder.encode(&op).unwrap();
8574 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8575 }
8576
8577 #[test]
8578 fn test_encode_mve_insert_lane_thumb2() {
8579 let encoder = ArmEncoder::new_thumb2();
8580 let op = ArmOp::MveInsertLane {
8581 qd: QReg::Q0,
8582 rn: Reg::R1,
8583 lane: 3,
8584 size: MveSize::S32,
8585 };
8586 let code = encoder.encode(&op).unwrap();
8587 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8588 }
8589
8590 #[test]
8591 fn test_encode_mve_addf32_thumb2() {
8592 let encoder = ArmEncoder::new_thumb2();
8593 let op = ArmOp::MveAddF32 {
8594 qd: QReg::Q0,
8595 qn: QReg::Q1,
8596 qm: QReg::Q2,
8597 };
8598 let code = encoder.encode(&op).unwrap();
8599 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8600 }
8601
8602 #[test]
8603 fn test_encode_mve_divf32_thumb2() {
8604 let encoder = ArmEncoder::new_thumb2();
8605 let op = ArmOp::MveDivF32 {
8606 qd: QReg::Q0,
8607 qn: QReg::Q1,
8608 qm: QReg::Q2,
8609 };
8610 let code = encoder.encode(&op).unwrap();
8611 assert_eq!(
8613 code.len(),
8614 16,
8615 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8616 );
8617 }
8618
8619 #[test]
8620 fn test_encode_mve_sqrtf32_thumb2() {
8621 let encoder = ArmEncoder::new_thumb2();
8622 let op = ArmOp::MveSqrtF32 {
8623 qd: QReg::Q0,
8624 qm: QReg::Q1,
8625 };
8626 let code = encoder.encode(&op).unwrap();
8627 assert_eq!(
8629 code.len(),
8630 16,
8631 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8632 );
8633 }
8634
8635 #[test]
8636 fn test_encode_mve_negf32_thumb2() {
8637 let encoder = ArmEncoder::new_thumb2();
8638 let op = ArmOp::MveNegF32 {
8639 qd: QReg::Q0,
8640 qm: QReg::Q1,
8641 };
8642 let code = encoder.encode(&op).unwrap();
8643 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8644 }
8645
8646 #[test]
8647 fn test_encode_mve_absf32_thumb2() {
8648 let encoder = ArmEncoder::new_thumb2();
8649 let op = ArmOp::MveAbsF32 {
8650 qd: QReg::Q0,
8651 qm: QReg::Q1,
8652 };
8653 let code = encoder.encode(&op).unwrap();
8654 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8655 }
8656
8657 #[test]
8658 fn test_encode_mve_different_qregs() {
8659 let encoder = ArmEncoder::new_thumb2();
8660
8661 let op1 = ArmOp::MveAddI {
8663 qd: QReg::Q0,
8664 qn: QReg::Q0,
8665 qm: QReg::Q0,
8666 size: MveSize::S32,
8667 };
8668 let op2 = ArmOp::MveAddI {
8669 qd: QReg::Q3,
8670 qn: QReg::Q5,
8671 qm: QReg::Q7,
8672 size: MveSize::S32,
8673 };
8674 let code1 = encoder.encode(&op1).unwrap();
8675 let code2 = encoder.encode(&op2).unwrap();
8676 assert_ne!(
8677 code1, code2,
8678 "Different Q-registers should produce different encodings"
8679 );
8680 }
8681
8682 #[test]
8683 fn test_encode_mve_arm32_nop() {
8684 let encoder = ArmEncoder::new_arm32();
8686 let op = ArmOp::MveAddI {
8687 qd: QReg::Q0,
8688 qn: QReg::Q1,
8689 qm: QReg::Q2,
8690 size: MveSize::S32,
8691 };
8692 let code = encoder.encode(&op).unwrap();
8693 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8694 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8696 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8697 }
8698}