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.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
493 0xEA000000 | offset_bits
494 }
495
496 ArmOp::BCondOffset { cond, offset } => {
498 use synth_synthesis::Condition;
499 let cond_bits: u32 = match cond {
500 Condition::EQ => 0x0,
501 Condition::NE => 0x1,
502 Condition::HS => 0x2,
503 Condition::LO => 0x3,
504 Condition::HI => 0x8,
505 Condition::LS => 0x9,
506 Condition::GE => 0xA,
507 Condition::LT => 0xB,
508 Condition::GT => 0xC,
509 Condition::LE => 0xD,
510 };
511 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
515 (cond_bits << 28) | 0x0A000000 | offset_bits
516 }
517
518 ArmOp::Bl { label: _ } => {
519 0xEB000000
521 }
522
523 ArmOp::Bx { rm } => {
524 let rm_bits = reg_to_bits(rm);
525
526 0xE12FFF10 | rm_bits
528 }
529
530 ArmOp::Blx { rm } => {
531 let rm_bits = reg_to_bits(rm);
532
533 0xE12FFF30 | rm_bits
535 }
536
537 ArmOp::Push { regs } => {
538 let mut reg_list: u32 = 0;
540 for r in regs {
541 reg_list |= 1 << reg_to_bits(r);
542 }
543 0xE92D0000 | reg_list
544 }
545
546 ArmOp::Pop { regs } => {
547 let mut reg_list: u32 = 0;
549 for r in regs {
550 reg_list |= 1 << reg_to_bits(r);
551 }
552 0xE8BD0000 | reg_list
553 }
554
555 ArmOp::Nop => {
556 0xE1A00000
558 }
559
560 ArmOp::Udf { imm } => {
561 let imm8 = *imm as u32;
564 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
565 }
566
567 ArmOp::Popcnt { .. } => {
570 0xE1A00000 }
574
575 ArmOp::SetCond { .. } => {
576 0xE1A00000 }
580
581 ArmOp::SelectMove { .. } => {
582 0xE1A00000 }
586
587 ArmOp::Select { .. } => {
588 0xE1A00000 }
592
593 ArmOp::LocalGet { .. } => {
594 0xE1A00000 }
598
599 ArmOp::LocalSet { .. } => {
600 0xE1A00000 }
604
605 ArmOp::LocalTee { .. } => {
606 0xE1A00000 }
610
611 ArmOp::GlobalGet { .. } => {
612 0xE1A00000 }
616
617 ArmOp::GlobalSet { .. } => {
618 0xE1A00000 }
622
623 ArmOp::BrTable { .. } => {
624 0xE1A00000 }
628
629 ArmOp::Call { .. } => {
630 0xE1A00000 }
634
635 ArmOp::CallIndirect { .. } => {
636 0xE1A00000 }
640
641 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)?,
678 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
679 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
680 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
681 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
682 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
683 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
684
685 ArmOp::F32Ceil { sd, sm } => {
688 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
690 ArmOp::F32Floor { sd, sm } => {
691 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
693 ArmOp::F32Trunc { sd, sm } => {
694 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
696 ArmOp::F32Nearest { sd, sm } => {
697 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
699 ArmOp::F32Min { sd, sn, sm } => {
700 return self.encode_arm_f32_minmax(sd, sn, sm, true);
701 }
702 ArmOp::F32Max { sd, sn, sm } => {
703 return self.encode_arm_f32_minmax(sd, sn, sm, false);
704 }
705 ArmOp::F32Copysign { sd, sn, sm } => {
706 return self.encode_arm_f32_copysign(sd, sn, sm);
707 }
708
709 ArmOp::F32Eq { rd, sn, sm } => {
711 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
713 ArmOp::F32Ne { rd, sn, sm } => {
714 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
716 ArmOp::F32Lt { rd, sn, sm } => {
717 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
719 ArmOp::F32Le { rd, sn, sm } => {
720 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
722 ArmOp::F32Gt { rd, sn, sm } => {
723 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
725 ArmOp::F32Ge { rd, sn, sm } => {
726 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
728
729 ArmOp::F32Const { sd, value } => {
731 return self.encode_arm_f32_const(sd, *value);
732 }
733
734 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
735 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
736
737 ArmOp::F32ConvertI32S { sd, rm } => {
739 return self.encode_arm_f32_convert_i32(sd, rm, true);
740 }
741 ArmOp::F32ConvertI32U { sd, rm } => {
742 return self.encode_arm_f32_convert_i32(sd, rm, false);
743 }
744 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
745 return Err(synth_core::Error::synthesis(
746 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
747 ));
748 }
749 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
750 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
751 ArmOp::I32TruncF32S { rd, sm } => {
752 return self.encode_arm_i32_trunc_f32(rd, sm, true);
753 }
754 ArmOp::I32TruncF32U { rd, sm } => {
755 return self.encode_arm_i32_trunc_f32(rd, sm, false);
756 }
757
758 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
761 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
762 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
763 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
764 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
765 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
766 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
767
768 ArmOp::F64Ceil { dd, dm } => {
771 return self.encode_arm_f64_rounding(dd, dm, 0b01);
772 }
773 ArmOp::F64Floor { dd, dm } => {
774 return self.encode_arm_f64_rounding(dd, dm, 0b10);
775 }
776 ArmOp::F64Trunc { dd, dm } => {
777 return self.encode_arm_f64_rounding(dd, dm, 0b11);
778 }
779 ArmOp::F64Nearest { dd, dm } => {
780 return self.encode_arm_f64_rounding(dd, dm, 0b00);
781 }
782 ArmOp::F64Min { dd, dn, dm } => {
783 return self.encode_arm_f64_minmax(dd, dn, dm, true);
784 }
785 ArmOp::F64Max { dd, dn, dm } => {
786 return self.encode_arm_f64_minmax(dd, dn, dm, false);
787 }
788 ArmOp::F64Copysign { dd, dn, dm } => {
789 return self.encode_arm_f64_copysign(dd, dn, dm);
790 }
791
792 ArmOp::F64Eq { rd, dn, dm } => {
794 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
795 }
796 ArmOp::F64Ne { rd, dn, dm } => {
797 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
798 }
799 ArmOp::F64Lt { rd, dn, dm } => {
800 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
801 }
802 ArmOp::F64Le { rd, dn, dm } => {
803 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
804 }
805 ArmOp::F64Gt { rd, dn, dm } => {
806 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
807 }
808 ArmOp::F64Ge { rd, dn, dm } => {
809 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
810 }
811
812 ArmOp::F64Const { dd, value } => {
813 return self.encode_arm_f64_const(dd, *value);
814 }
815
816 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
817 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
818
819 ArmOp::F64ConvertI32S { dd, rm } => {
820 return self.encode_arm_f64_convert_i32(dd, rm, true);
821 }
822 ArmOp::F64ConvertI32U { dd, rm } => {
823 return self.encode_arm_f64_convert_i32(dd, rm, false);
824 }
825 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
826 return Err(synth_core::Error::synthesis(
827 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
828 ));
829 }
830 ArmOp::F64PromoteF32 { dd, sm } => {
831 return self.encode_arm_f64_promote_f32(dd, sm);
832 }
833 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
834 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
835 }
836 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
837 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
838 }
839 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
840 return Err(synth_core::Error::synthesis(
841 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
842 ));
843 }
844 ArmOp::I32TruncF64S { rd, dm } => {
845 return self.encode_arm_i32_trunc_f64(rd, dm, true);
846 }
847 ArmOp::I32TruncF64U { rd, dm } => {
848 return self.encode_arm_i32_trunc_f64(rd, dm, false);
849 }
850 ArmOp::I64SetCond { .. }
852 | ArmOp::I64SetCondZ { .. }
853 | ArmOp::I64Mul { .. }
854 | ArmOp::I64Shl { .. }
855 | ArmOp::I64ShrS { .. }
856 | ArmOp::I64ShrU { .. }
857 | ArmOp::I64Rotl { .. }
858 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
862 | ArmOp::MveStore { .. }
863 | ArmOp::MveConst { .. }
864 | ArmOp::MveAnd { .. }
865 | ArmOp::MveOrr { .. }
866 | ArmOp::MveEor { .. }
867 | ArmOp::MveMvn { .. }
868 | ArmOp::MveBic { .. }
869 | ArmOp::MveAddI { .. }
870 | ArmOp::MveSubI { .. }
871 | ArmOp::MveMulI { .. }
872 | ArmOp::MveNegI { .. }
873 | ArmOp::MveCmpEqI { .. }
874 | ArmOp::MveCmpNeI { .. }
875 | ArmOp::MveCmpLtS { .. }
876 | ArmOp::MveCmpLtU { .. }
877 | ArmOp::MveCmpGtS { .. }
878 | ArmOp::MveCmpGtU { .. }
879 | ArmOp::MveCmpLeS { .. }
880 | ArmOp::MveCmpLeU { .. }
881 | ArmOp::MveCmpGeS { .. }
882 | ArmOp::MveCmpGeU { .. }
883 | ArmOp::MveDup { .. }
884 | ArmOp::MveExtractLane { .. }
885 | ArmOp::MveInsertLane { .. }
886 | ArmOp::MveAddF32 { .. }
887 | ArmOp::MveSubF32 { .. }
888 | ArmOp::MveMulF32 { .. }
889 | ArmOp::MveNegF32 { .. }
890 | ArmOp::MveAbsF32 { .. }
891 | ArmOp::MveCmpEqF32 { .. }
892 | ArmOp::MveCmpNeF32 { .. }
893 | ArmOp::MveCmpLtF32 { .. }
894 | ArmOp::MveCmpLeF32 { .. }
895 | ArmOp::MveCmpGtF32 { .. }
896 | ArmOp::MveCmpGeF32 { .. }
897 | ArmOp::MveDupF32 { .. }
898 | ArmOp::MveExtractLaneF32 { .. }
899 | ArmOp::MveReplaceLaneF32 { .. }
900 | ArmOp::MveDivF32 { .. }
901 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
903
904 Ok(instr.to_le_bytes().to_vec())
906 }
907
908 fn encode_arm_f32_compare(
912 &self,
913 rd: &Reg,
914 sn: &VfpReg,
915 sm: &VfpReg,
916 cond_code: u32,
917 ) -> Result<Vec<u8>> {
918 let mut bytes = Vec::new();
919
920 let sn_num = vfp_sreg_to_num(sn)?;
922 let sm_num = vfp_sreg_to_num(sm)?;
923 let (vd, d) = encode_sreg(sn_num);
924 let (vm, m) = encode_sreg(sm_num);
925 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
926 bytes.extend_from_slice(&vcmp.to_le_bytes());
927
928 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
930
931 let rd_bits = reg_to_bits(rd);
933 let mov_zero = 0xE3A00000 | (rd_bits << 12);
934 bytes.extend_from_slice(&mov_zero.to_le_bytes());
935
936 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
938 bytes.extend_from_slice(&mov_one.to_le_bytes());
939
940 Ok(bytes)
941 }
942
943 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
945 let mut bytes = Vec::new();
946 let bits = value.to_bits();
947
948 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
953 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
954 bytes.extend_from_slice(&movw.to_le_bytes());
955
956 let hi16 = (bits >> 16) & 0xFFFF;
958 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
959 bytes.extend_from_slice(&movt.to_le_bytes());
960
961 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
963 bytes.extend_from_slice(&vmov.to_le_bytes());
964
965 Ok(bytes)
966 }
967
968 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
970 let mut bytes = Vec::new();
971
972 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
974 bytes.extend_from_slice(&vmov.to_le_bytes());
975
976 let sd_num = vfp_sreg_to_num(sd)?;
979 let (vd, d) = encode_sreg(sd_num);
980 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
982 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
983 bytes.extend_from_slice(&vcvt.to_le_bytes());
984
985 Ok(bytes)
986 }
987
988 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1000 let mut bytes = Vec::new();
1001 let sm_num = vfp_sreg_to_num(sm)?;
1002 let sd_num = vfp_sreg_to_num(sd)?;
1003 let (vd_s, d_s) = encode_sreg(sd_num);
1004 let (vm_s, m_s) = encode_sreg(sm_num);
1005
1006 if mode == 0b11 {
1007 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1010 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1011 } else {
1012 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1017 bytes.extend_from_slice(&vmrs.to_le_bytes());
1018
1019 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1022 bytes.extend_from_slice(&bic.to_le_bytes());
1023
1024 if mode != 0 {
1026 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1028 bytes.extend_from_slice(&orr.to_le_bytes());
1029 }
1030
1031 let vmsr = 0xEEE10A10 | (rt << 12);
1033 bytes.extend_from_slice(&vmsr.to_le_bytes());
1034
1035 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1037 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1038
1039 bytes.extend_from_slice(&vmrs.to_le_bytes());
1041 bytes.extend_from_slice(&bic.to_le_bytes());
1042 bytes.extend_from_slice(&vmsr.to_le_bytes());
1043 }
1044
1045 let (vd2, d2) = encode_sreg(sd_num);
1047 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1048 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1049
1050 Ok(bytes)
1051 }
1052
1053 fn encode_arm_f32_minmax(
1055 &self,
1056 sd: &VfpReg,
1057 sn: &VfpReg,
1058 sm: &VfpReg,
1059 is_min: bool,
1060 ) -> Result<Vec<u8>> {
1061 let mut bytes = Vec::new();
1062 let sn_num = vfp_sreg_to_num(sn)?;
1063 let sm_num = vfp_sreg_to_num(sm)?;
1064 let sd_num = vfp_sreg_to_num(sd)?;
1065
1066 let (vd, d) = encode_sreg(sd_num);
1068 let (vn, n) = encode_sreg(sn_num);
1069 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1070 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1071
1072 let (vm, m) = encode_sreg(sm_num);
1074 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1075 bytes.extend_from_slice(&vcmp.to_le_bytes());
1076
1077 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1079
1080 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1083
1084 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1086 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1087
1088 Ok(bytes)
1089 }
1090
1091 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1093 let mut bytes = Vec::new();
1094
1095 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1097 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1098
1099 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1101 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1102
1103 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1107 bytes.extend_from_slice(&and_sign.to_le_bytes());
1108
1109 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1112 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1113
1114 let orr = 0xE1800000u32 | 12;
1117 bytes.extend_from_slice(&orr.to_le_bytes());
1118
1119 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1121 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1122
1123 Ok(bytes)
1124 }
1125
1126 fn encode_arm_f64_compare(
1128 &self,
1129 rd: &Reg,
1130 dn: &VfpReg,
1131 dm: &VfpReg,
1132 cond_code: u32,
1133 ) -> Result<Vec<u8>> {
1134 let mut bytes = Vec::new();
1135
1136 let dn_num = vfp_dreg_to_num(dn)?;
1138 let dm_num = vfp_dreg_to_num(dm)?;
1139 let (vd, d) = encode_dreg(dn_num);
1140 let (vm, m) = encode_dreg(dm_num);
1141 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1142 bytes.extend_from_slice(&vcmp.to_le_bytes());
1143
1144 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1146
1147 let rd_bits = reg_to_bits(rd);
1149 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1150 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1151
1152 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1154 bytes.extend_from_slice(&mov_one.to_le_bytes());
1155
1156 Ok(bytes)
1157 }
1158
1159 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1161 let mut bytes = Vec::new();
1162 let bits = value.to_bits();
1163 let lo32 = bits as u32;
1164 let hi32 = (bits >> 32) as u32;
1165
1166 let lo16 = lo32 & 0xFFFF;
1168 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1169 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1170 let hi16 = (lo32 >> 16) & 0xFFFF;
1171 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1172 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1173
1174 let lo16 = hi32 & 0xFFFF;
1176 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1177 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1178 let hi16 = (hi32 >> 16) & 0xFFFF;
1179 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1180 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1181
1182 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1184 bytes.extend_from_slice(&vmov.to_le_bytes());
1185
1186 Ok(bytes)
1187 }
1188
1189 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1191 let mut bytes = Vec::new();
1192
1193 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1195 bytes.extend_from_slice(&vmov.to_le_bytes());
1196
1197 let dd_num = vfp_dreg_to_num(dd)?;
1200 let (vd, d) = encode_dreg(dd_num);
1201 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1202 let vcvt = base | (d << 22) | (vd << 12);
1204 bytes.extend_from_slice(&vcvt.to_le_bytes());
1205
1206 Ok(bytes)
1207 }
1208
1209 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1211 let dd_num = vfp_dreg_to_num(dd)?;
1212 let sm_num = vfp_sreg_to_num(sm)?;
1213 let (vd, d) = encode_dreg(dd_num);
1214 let (vm, m) = encode_sreg(sm_num);
1215
1216 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1218 Ok(vcvt.to_le_bytes().to_vec())
1219 }
1220
1221 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1223 let mut bytes = Vec::new();
1224 let dm_num = vfp_dreg_to_num(dm)?;
1225 let (vm, m) = encode_dreg(dm_num);
1226
1227 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1230 let vcvt = base | (m << 5) | vm;
1231 bytes.extend_from_slice(&vcvt.to_le_bytes());
1232
1233 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1235 bytes.extend_from_slice(&vmov.to_le_bytes());
1236
1237 Ok(bytes)
1238 }
1239
1240 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1248 let mut bytes = Vec::new();
1249 let dm_num = vfp_dreg_to_num(dm)?;
1250 let dd_num = vfp_dreg_to_num(dd)?;
1251 let (vm, m) = encode_dreg(dm_num);
1252 let (vd, d) = encode_dreg(dd_num);
1253
1254 if mode == 0b11 {
1255 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1257 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1258 } else {
1259 let rt: u32 = 12;
1261
1262 let vmrs = 0xEEF10A10 | (rt << 12);
1264 bytes.extend_from_slice(&vmrs.to_le_bytes());
1265
1266 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1268 bytes.extend_from_slice(&bic.to_le_bytes());
1269
1270 if mode != 0 {
1272 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1273 bytes.extend_from_slice(&orr.to_le_bytes());
1274 }
1275
1276 let vmsr = 0xEEE10A10 | (rt << 12);
1278 bytes.extend_from_slice(&vmsr.to_le_bytes());
1279
1280 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1282 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1283
1284 bytes.extend_from_slice(&vmrs.to_le_bytes());
1286 bytes.extend_from_slice(&bic.to_le_bytes());
1287 bytes.extend_from_slice(&vmsr.to_le_bytes());
1288 }
1289
1290 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1292 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1293
1294 Ok(bytes)
1295 }
1296
1297 fn encode_arm_f64_minmax(
1299 &self,
1300 dd: &VfpReg,
1301 dn: &VfpReg,
1302 dm: &VfpReg,
1303 is_min: bool,
1304 ) -> Result<Vec<u8>> {
1305 let mut bytes = Vec::new();
1306 let dn_num = vfp_dreg_to_num(dn)?;
1307 let dm_num = vfp_dreg_to_num(dm)?;
1308 let dd_num = vfp_dreg_to_num(dd)?;
1309
1310 let (vd, d) = encode_dreg(dd_num);
1312 let (vn, n) = encode_dreg(dn_num);
1313 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1314 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1315
1316 let (vm, m) = encode_dreg(dm_num);
1318 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1319 bytes.extend_from_slice(&vcmp.to_le_bytes());
1320
1321 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1323
1324 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1325 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1326 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1327
1328 Ok(bytes)
1329 }
1330
1331 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1333 let mut bytes = Vec::new();
1334
1335 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1337 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1338
1339 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1342 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1343
1344 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1346 bytes.extend_from_slice(&and_sign.to_le_bytes());
1347
1348 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1350 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1351
1352 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1354 bytes.extend_from_slice(&orr.to_le_bytes());
1355
1356 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1358 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1359
1360 Ok(bytes)
1361 }
1362
1363 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1365 let mut bytes = Vec::new();
1366
1367 let sm_num = vfp_sreg_to_num(sm)?;
1370 let (vd, d) = encode_sreg(sm_num);
1371 let (vm, m) = encode_sreg(sm_num);
1372 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1373 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1374 bytes.extend_from_slice(&vcvt.to_le_bytes());
1375
1376 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1378 bytes.extend_from_slice(&vmov.to_le_bytes());
1379
1380 Ok(bytes)
1381 }
1382
1383 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1385 match op {
1388 ArmOp::Add { rd, rn, op2 } => {
1390 let rd_bits = reg_to_bits(rd) as u16;
1391 let rn_bits = reg_to_bits(rn) as u16;
1392
1393 if let Operand2::Reg(rm) = op2 {
1394 let rm_bits = reg_to_bits(rm) as u16;
1395 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1403 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1405 Ok(instr.to_le_bytes().to_vec())
1406 } else {
1407 self.encode_thumb32_add_reg_raw(
1409 rd_bits as u32,
1410 rn_bits as u32,
1411 rm_bits as u32,
1412 )
1413 }
1414 } else if let Operand2::Imm(imm) = op2 {
1415 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1416 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1418 Ok(instr.to_le_bytes().to_vec())
1419 } else {
1420 self.encode_thumb32_add(rd, rn, *imm as u32)
1422 }
1423 } else {
1424 self.encode_thumb32_add(rd, rn, 0)
1426 }
1427 }
1428
1429 ArmOp::Sub { rd, rn, op2 } => {
1430 let rd_bits = reg_to_bits(rd) as u16;
1431 let rn_bits = reg_to_bits(rn) as u16;
1432
1433 if let Operand2::Reg(rm) = op2 {
1434 let rm_bits = reg_to_bits(rm) as u16;
1435 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1437 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1439 Ok(instr.to_le_bytes().to_vec())
1440 } else {
1441 self.encode_thumb32_sub_reg_raw(
1443 rd_bits as u32,
1444 rn_bits as u32,
1445 rm_bits as u32,
1446 )
1447 }
1448 } else if let Operand2::Imm(imm) = op2 {
1449 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1450 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1452 Ok(instr.to_le_bytes().to_vec())
1453 } else {
1454 self.encode_thumb32_sub(rd, rn, *imm as u32)
1455 }
1456 } else {
1457 self.encode_thumb32_sub(rd, rn, 0)
1458 }
1459 }
1460
1461 ArmOp::Mov { rd, op2 } => {
1462 let rd_bits = reg_to_bits(rd) as u16;
1463
1464 if let Operand2::Imm(imm) = op2 {
1465 if *imm <= 255 && rd_bits < 8 {
1466 let imm_bits = (*imm as u16) & 0xFF;
1468 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1469 Ok(instr.to_le_bytes().to_vec())
1470 } else {
1471 self.encode_thumb32_movw(rd, *imm as u32)
1473 }
1474 } else if let Operand2::Reg(rm) = op2 {
1475 let rm_bits = reg_to_bits(rm) as u16;
1476 let d_bit = (rd_bits >> 3) & 1;
1479 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1480 Ok(instr.to_le_bytes().to_vec())
1481 } else {
1482 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1484 }
1485 }
1486
1487 ArmOp::Push { regs } => {
1488 let mut reg_list: u16 = 0;
1492 let mut need_32bit = false;
1493 for r in regs {
1494 let bit = reg_to_bits(r);
1495 if bit >= 8 && *r != Reg::LR {
1496 need_32bit = true;
1497 }
1498 reg_list |= 1 << bit;
1499 }
1500 if !need_32bit {
1501 let m_bit = if reg_list & (1 << 14) != 0 {
1503 1u16
1504 } else {
1505 0u16
1506 };
1507 let low_regs = reg_list & 0xFF;
1508 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1509 Ok(instr.to_le_bytes().to_vec())
1510 } else {
1511 let hw1: u16 = 0xE92D;
1513 let hw2: u16 = reg_list;
1514 let mut bytes = hw1.to_le_bytes().to_vec();
1515 bytes.extend_from_slice(&hw2.to_le_bytes());
1516 Ok(bytes)
1517 }
1518 }
1519
1520 ArmOp::Pop { regs } => {
1521 let mut reg_list: u16 = 0;
1525 let mut need_32bit = false;
1526 for r in regs {
1527 let bit = reg_to_bits(r);
1528 if bit >= 8 && *r != Reg::PC {
1529 need_32bit = true;
1530 }
1531 reg_list |= 1 << bit;
1532 }
1533 if !need_32bit {
1534 let p_bit = if reg_list & (1 << 15) != 0 {
1536 1u16
1537 } else {
1538 0u16
1539 };
1540 let low_regs = reg_list & 0xFF;
1541 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1542 Ok(instr.to_le_bytes().to_vec())
1543 } else {
1544 let hw1: u16 = 0xE8BD;
1546 let hw2: u16 = reg_list;
1547 let mut bytes = hw1.to_le_bytes().to_vec();
1548 bytes.extend_from_slice(&hw2.to_le_bytes());
1549 Ok(bytes)
1550 }
1551 }
1552
1553 ArmOp::Nop => {
1554 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1556 }
1557
1558 ArmOp::Udf { imm } => {
1559 let instr: u16 = 0xDE00 | (*imm as u16);
1562 let bytes = instr.to_le_bytes().to_vec();
1563 encoding_contracts::verify_thumb16(&bytes);
1564 Ok(bytes)
1565 }
1566
1567 ArmOp::Adds { rd, rn, op2 } => {
1570 let rd_bits = reg_to_bits(rd) as u16;
1571 let rn_bits = reg_to_bits(rn) as u16;
1572
1573 if let Operand2::Reg(rm) = op2 {
1574 let rm_bits = reg_to_bits(rm) as u16;
1575 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1580 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1582 Ok(instr.to_le_bytes().to_vec())
1583 } else {
1584 self.encode_thumb32_adds_reg_raw(
1585 rd_bits as u32,
1586 rn_bits as u32,
1587 rm_bits as u32,
1588 )
1589 }
1590 } else {
1591 self.encode_thumb32_adds(rd, rn, 0)
1593 }
1594 }
1595
1596 ArmOp::Adc { rd, rn, op2 } => {
1599 let rd_bits = reg_to_bits(rd);
1600 let rn_bits = reg_to_bits(rn);
1601
1602 if let Operand2::Reg(rm) = op2 {
1603 let rm_bits = reg_to_bits(rm);
1604 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1606 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1607
1608 let mut bytes = hw1.to_le_bytes().to_vec();
1609 bytes.extend_from_slice(&hw2.to_le_bytes());
1610 Ok(bytes)
1611 } else {
1612 let hw1: u16 = (0xF140 | rn_bits) as u16;
1614 let hw2: u16 = (rd_bits << 8) as u16;
1615 let mut bytes = hw1.to_le_bytes().to_vec();
1616 bytes.extend_from_slice(&hw2.to_le_bytes());
1617 Ok(bytes)
1618 }
1619 }
1620
1621 ArmOp::Subs { rd, rn, op2 } => {
1623 let rd_bits = reg_to_bits(rd) as u16;
1624 let rn_bits = reg_to_bits(rn) as u16;
1625
1626 if let Operand2::Reg(rm) = op2 {
1627 let rm_bits = reg_to_bits(rm) as u16;
1628 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1632 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1634 Ok(instr.to_le_bytes().to_vec())
1635 } else {
1636 self.encode_thumb32_subs_reg_raw(
1637 rd_bits as u32,
1638 rn_bits as u32,
1639 rm_bits as u32,
1640 )
1641 }
1642 } else {
1643 self.encode_thumb32_subs(rd, rn, 0)
1645 }
1646 }
1647
1648 ArmOp::Sbc { rd, rn, op2 } => {
1651 let rd_bits = reg_to_bits(rd);
1652 let rn_bits = reg_to_bits(rn);
1653
1654 if let Operand2::Reg(rm) = op2 {
1655 let rm_bits = reg_to_bits(rm);
1656 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1658 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1659
1660 let mut bytes = hw1.to_le_bytes().to_vec();
1661 bytes.extend_from_slice(&hw2.to_le_bytes());
1662 Ok(bytes)
1663 } else {
1664 let hw1: u16 = (0xF160 | rn_bits) as u16;
1666 let hw2: u16 = (rd_bits << 8) as u16;
1667 let mut bytes = hw1.to_le_bytes().to_vec();
1668 bytes.extend_from_slice(&hw2.to_le_bytes());
1669 Ok(bytes)
1670 }
1671 }
1672
1673 ArmOp::Sdiv { rd, rn, rm } => {
1677 let rd_bits = reg_to_bits(rd);
1678 let rn_bits = reg_to_bits(rn);
1679 let rm_bits = reg_to_bits(rm);
1680 reg_bits_checked(rd_bits)?;
1681 reg_bits_checked(rn_bits)?;
1682 reg_bits_checked(rm_bits)?;
1683
1684 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1688 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1689
1690 let mut bytes = hw1.to_le_bytes().to_vec();
1692 bytes.extend_from_slice(&hw2.to_le_bytes());
1693 encoding_contracts::verify_thumb32(&bytes);
1694 Ok(bytes)
1695 }
1696
1697 ArmOp::Udiv { rd, rn, rm } => {
1699 let rd_bits = reg_to_bits(rd);
1700 let rn_bits = reg_to_bits(rn);
1701 let rm_bits = reg_to_bits(rm);
1702 reg_bits_checked(rd_bits)?;
1703 reg_bits_checked(rn_bits)?;
1704 reg_bits_checked(rm_bits)?;
1705
1706 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1708 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1709
1710 let mut bytes = hw1.to_le_bytes().to_vec();
1711 bytes.extend_from_slice(&hw2.to_le_bytes());
1712 encoding_contracts::verify_thumb32(&bytes);
1713 Ok(bytes)
1714 }
1715
1716 ArmOp::Mul { rd, rn, rm } => {
1718 let rd_bits = reg_to_bits(rd);
1719 let rn_bits = reg_to_bits(rn);
1720 let rm_bits = reg_to_bits(rm);
1721
1722 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1725 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1726
1727 let mut bytes = hw1.to_le_bytes().to_vec();
1728 bytes.extend_from_slice(&hw2.to_le_bytes());
1729 Ok(bytes)
1730 }
1731
1732 ArmOp::Mls { rd, rn, rm, ra } => {
1734 let rd_bits = reg_to_bits(rd);
1735 let rn_bits = reg_to_bits(rn);
1736 let rm_bits = reg_to_bits(rm);
1737 let ra_bits = reg_to_bits(ra);
1738
1739 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1742 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1743
1744 let mut bytes = hw1.to_le_bytes().to_vec();
1745 bytes.extend_from_slice(&hw2.to_le_bytes());
1746 Ok(bytes)
1747 }
1748
1749 ArmOp::And { rd, rn, op2 } => {
1751 if let Operand2::Reg(rm) = op2 {
1752 let rd_bits = reg_to_bits(rd);
1753 let rn_bits = reg_to_bits(rn);
1754 let rm_bits = reg_to_bits(rm);
1755
1756 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1758 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1759
1760 let mut bytes = hw1.to_le_bytes().to_vec();
1761 bytes.extend_from_slice(&hw2.to_le_bytes());
1762 Ok(bytes)
1763 } else if let Operand2::Imm(imm) = op2 {
1764 let rd_bits = reg_to_bits(rd);
1765 let rn_bits = reg_to_bits(rn);
1766 let imm_val = *imm as u32;
1767
1768 let i_bit = (imm_val >> 11) & 1;
1770 let imm3 = (imm_val >> 8) & 0x7;
1771 let imm8 = imm_val & 0xFF;
1772
1773 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1774 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1775
1776 let mut bytes = hw1.to_le_bytes().to_vec();
1777 bytes.extend_from_slice(&hw2.to_le_bytes());
1778 Ok(bytes)
1779 } else {
1780 let instr: u16 = 0xBF00;
1782 Ok(instr.to_le_bytes().to_vec())
1783 }
1784 }
1785
1786 ArmOp::Orr { rd, rn, op2 } => {
1788 if let Operand2::Reg(rm) = op2 {
1789 let rd_bits = reg_to_bits(rd);
1790 let rn_bits = reg_to_bits(rn);
1791 let rm_bits = reg_to_bits(rm);
1792
1793 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1795 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1796
1797 let mut bytes = hw1.to_le_bytes().to_vec();
1798 bytes.extend_from_slice(&hw2.to_le_bytes());
1799 Ok(bytes)
1800 } else {
1801 let instr: u16 = 0xBF00;
1802 Ok(instr.to_le_bytes().to_vec())
1803 }
1804 }
1805
1806 ArmOp::Eor { rd, rn, op2 } => {
1808 if let Operand2::Reg(rm) = op2 {
1809 let rd_bits = reg_to_bits(rd);
1810 let rn_bits = reg_to_bits(rn);
1811 let rm_bits = reg_to_bits(rm);
1812
1813 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1815 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1816
1817 let mut bytes = hw1.to_le_bytes().to_vec();
1818 bytes.extend_from_slice(&hw2.to_le_bytes());
1819 Ok(bytes)
1820 } else {
1821 let instr: u16 = 0xBF00;
1822 Ok(instr.to_le_bytes().to_vec())
1823 }
1824 }
1825
1826 ArmOp::Lsl { rd, rn, shift } => {
1828 let rd_bits = reg_to_bits(rd) as u16;
1829 let rn_bits = reg_to_bits(rn) as u16;
1830 let shift_bits = (*shift as u16) & 0x1F;
1831
1832 if rd_bits < 8 && rn_bits < 8 {
1833 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1835 Ok(instr.to_le_bytes().to_vec())
1836 } else {
1837 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1840 }
1841
1842 ArmOp::Lsr { rd, rn, shift } => {
1843 let rd_bits = reg_to_bits(rd) as u16;
1844 let rn_bits = reg_to_bits(rn) as u16;
1845 let shift_bits = (*shift as u16) & 0x1F;
1846
1847 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1848 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1850 Ok(instr.to_le_bytes().to_vec())
1851 } else {
1852 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
1854 }
1855
1856 ArmOp::Asr { rd, rn, shift } => {
1857 let rd_bits = reg_to_bits(rd) as u16;
1858 let rn_bits = reg_to_bits(rn) as u16;
1859 let shift_bits = (*shift as u16) & 0x1F;
1860
1861 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1862 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1864 Ok(instr.to_le_bytes().to_vec())
1865 } else {
1866 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
1868 }
1869
1870 ArmOp::Ror { rd, rn, shift } => {
1871 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
1874
1875 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
1879 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
1880 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
1881 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
1882
1883 ArmOp::Rsb { rd, rn, imm } => {
1886 let rd_bits = reg_to_bits(rd);
1887 let rn_bits = reg_to_bits(rn);
1888 let imm_val = *imm;
1889
1890 let i_bit = (imm_val >> 11) & 1;
1891 let imm3 = (imm_val >> 8) & 0x7;
1892 let imm8 = imm_val & 0xFF;
1893
1894 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
1896 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1898
1899 let mut bytes = hw1.to_le_bytes().to_vec();
1900 bytes.extend_from_slice(&hw2.to_le_bytes());
1901 Ok(bytes)
1902 }
1903
1904 ArmOp::Clz { rd, rm } => {
1906 let rd_bits = reg_to_bits(rd);
1907 let rm_bits = reg_to_bits(rm);
1908
1909 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
1912 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
1913
1914 let mut bytes = hw1.to_le_bytes().to_vec();
1915 bytes.extend_from_slice(&hw2.to_le_bytes());
1916 Ok(bytes)
1917 }
1918
1919 ArmOp::Rbit { rd, rm } => {
1921 let rd_bits = reg_to_bits(rd);
1922 let rm_bits = reg_to_bits(rm);
1923
1924 let hw1: u16 = (0xFA90 | rm_bits) as u16;
1927 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
1928
1929 let mut bytes = hw1.to_le_bytes().to_vec();
1930 bytes.extend_from_slice(&hw2.to_le_bytes());
1931 Ok(bytes)
1932 }
1933
1934 ArmOp::Sxtb { rd, rm } => {
1936 let rd_bits = reg_to_bits(rd) as u16;
1937 let rm_bits = reg_to_bits(rm) as u16;
1938
1939 if rd_bits < 8 && rm_bits < 8 {
1940 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
1942 Ok(instr.to_le_bytes().to_vec())
1943 } else {
1944 let rd_bits32 = rd_bits as u32;
1947 let rm_bits32 = rm_bits as u32;
1948 let hw1: u16 = 0xFA4F;
1949 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
1950 let mut bytes = hw1.to_le_bytes().to_vec();
1951 bytes.extend_from_slice(&hw2.to_le_bytes());
1952 Ok(bytes)
1953 }
1954 }
1955
1956 ArmOp::Sxth { rd, rm } => {
1958 let rd_bits = reg_to_bits(rd) as u16;
1959 let rm_bits = reg_to_bits(rm) as u16;
1960
1961 if rd_bits < 8 && rm_bits < 8 {
1962 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
1964 Ok(instr.to_le_bytes().to_vec())
1965 } else {
1966 let rd_bits32 = rd_bits as u32;
1969 let rm_bits32 = rm_bits as u32;
1970 let hw1: u16 = 0xFA0F;
1971 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
1972 let mut bytes = hw1.to_le_bytes().to_vec();
1973 bytes.extend_from_slice(&hw2.to_le_bytes());
1974 Ok(bytes)
1975 }
1976 }
1977
1978 ArmOp::Cmp { rn, op2 } => {
1980 let rn_bits = reg_to_bits(rn) as u16;
1981
1982 if let Operand2::Imm(imm) = op2 {
1983 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
1986 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
1988 Ok(instr.to_le_bytes().to_vec())
1989 } else {
1990 self.encode_thumb32_cmp_imm(rn, *imm as u32)
1991 }
1992 } else if let Operand2::Reg(rm) = op2 {
1993 let rm_bits = reg_to_bits(rm) as u16;
1994 if rn_bits < 8 && rm_bits < 8 {
1995 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
1997 Ok(instr.to_le_bytes().to_vec())
1998 } else {
1999 let n_bit = (rn_bits >> 3) & 1;
2001 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2002 Ok(instr.to_le_bytes().to_vec())
2003 }
2004 } else {
2005 let instr: u16 = 0xBF00;
2006 Ok(instr.to_le_bytes().to_vec())
2007 }
2008 }
2009
2010 ArmOp::Cmn { rn, op2 } => {
2013 let rn_bits = reg_to_bits(rn) as u16;
2014
2015 if let Operand2::Imm(imm) = op2 {
2016 if *imm >= 0 && *imm <= 255 {
2019 let imm8 = *imm as u16 & 0xFF;
2020 let hw1: u16 = 0xF110 | rn_bits;
2021 let hw2: u16 = 0x0F00 | imm8;
2022 let mut bytes = hw1.to_le_bytes().to_vec();
2023 bytes.extend_from_slice(&hw2.to_le_bytes());
2024 Ok(bytes)
2025 } else {
2026 Ok(vec![0xBF, 0x00])
2028 }
2029 } else if let Operand2::Reg(rm) = op2 {
2030 let rm_bits = reg_to_bits(rm) as u16;
2031 if rn_bits < 8 && rm_bits < 8 {
2037 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2039 Ok(instr.to_le_bytes().to_vec())
2040 } else {
2041 let hw1: u16 = 0xEB10 | rn_bits;
2042 let hw2: u16 = 0x0F00 | rm_bits;
2043 let mut bytes = hw1.to_le_bytes().to_vec();
2044 bytes.extend_from_slice(&hw2.to_le_bytes());
2045 Ok(bytes)
2046 }
2047 } else {
2048 Ok(vec![0xBF, 0x00])
2049 }
2050 }
2051
2052 ArmOp::Ldr { rd, addr } => {
2054 let rd_bits = reg_to_bits(rd);
2055 let base_bits = reg_to_bits(&addr.base);
2056
2057 if let Some(offset_reg) = &addr.offset_reg {
2059 let rm_bits = reg_to_bits(offset_reg);
2060
2061 if addr.offset != 0 {
2063 let scratch = Reg::R12;
2066 let mut bytes =
2067 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2068 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2069 return Ok(bytes);
2070 }
2071
2072 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2075 let instr: u16 = 0x5800
2077 | ((rm_bits as u16) << 6)
2078 | ((base_bits as u16) << 3)
2079 | (rd_bits as u16);
2080 return Ok(instr.to_le_bytes().to_vec());
2081 }
2082
2083 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2085 }
2086
2087 let offset = addr.offset as u32;
2089
2090 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2091 let imm5 = (offset >> 2) as u16;
2093 let instr: u16 =
2094 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2095 Ok(instr.to_le_bytes().to_vec())
2096 } else {
2097 self.encode_thumb32_ldr(rd, &addr.base, offset)
2098 }
2099 }
2100
2101 ArmOp::Str { rd, addr } => {
2103 let rd_bits = reg_to_bits(rd);
2104 let base_bits = reg_to_bits(&addr.base);
2105
2106 if let Some(offset_reg) = &addr.offset_reg {
2108 let rm_bits = reg_to_bits(offset_reg);
2109
2110 if addr.offset != 0 {
2112 let scratch = Reg::R12;
2115 let mut bytes =
2116 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2117 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2118 return Ok(bytes);
2119 }
2120
2121 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2124 let instr: u16 = 0x5000
2126 | ((rm_bits as u16) << 6)
2127 | ((base_bits as u16) << 3)
2128 | (rd_bits as u16);
2129 return Ok(instr.to_le_bytes().to_vec());
2130 }
2131
2132 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2134 }
2135
2136 let offset = addr.offset as u32;
2138
2139 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2140 let imm5 = (offset >> 2) as u16;
2142 let instr: u16 =
2143 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2144 Ok(instr.to_le_bytes().to_vec())
2145 } else {
2146 self.encode_thumb32_str(rd, &addr.base, offset)
2147 }
2148 }
2149
2150 ArmOp::Ldrb { rd, addr } => {
2152 let rd_bits = reg_to_bits(rd);
2153 let base_bits = reg_to_bits(&addr.base);
2154
2155 if let Some(offset_reg) = &addr.offset_reg {
2156 if addr.offset != 0 {
2157 let scratch = Reg::R12;
2158 let mut bytes =
2159 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2160 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2161 return Ok(bytes);
2162 }
2163 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2164 }
2165
2166 let offset = addr.offset as u32;
2167 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2168 let instr: u16 = 0x7800
2170 | ((offset as u16) << 6)
2171 | ((base_bits as u16) << 3)
2172 | (rd_bits as u16);
2173 Ok(instr.to_le_bytes().to_vec())
2174 } else {
2175 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2176 }
2177 }
2178
2179 ArmOp::Ldrsb { rd, addr } => {
2181 let rd_bits = reg_to_bits(rd);
2182 let base_bits = reg_to_bits(&addr.base);
2183
2184 if let Some(offset_reg) = &addr.offset_reg {
2185 if addr.offset != 0 {
2186 let scratch = Reg::R12;
2187 let mut bytes =
2188 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2189 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2190 return Ok(bytes);
2191 }
2192 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2193 }
2194
2195 let offset = addr.offset as u32;
2196 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2199 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2201 } else {
2202 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2203 }
2204 }
2205
2206 ArmOp::Ldrh { rd, addr } => {
2208 let rd_bits = reg_to_bits(rd);
2209 let base_bits = reg_to_bits(&addr.base);
2210
2211 if let Some(offset_reg) = &addr.offset_reg {
2212 if addr.offset != 0 {
2213 let scratch = Reg::R12;
2214 let mut bytes =
2215 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2216 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2217 return Ok(bytes);
2218 }
2219 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2220 }
2221
2222 let offset = addr.offset as u32;
2223 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2224 let imm5 = (offset >> 1) as u16;
2226 let instr: u16 =
2227 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2228 Ok(instr.to_le_bytes().to_vec())
2229 } else {
2230 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2231 }
2232 }
2233
2234 ArmOp::Ldrsh { rd, addr } => {
2236 if let Some(offset_reg) = &addr.offset_reg {
2237 if addr.offset != 0 {
2238 let scratch = Reg::R12;
2239 let mut bytes =
2240 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2241 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2242 return Ok(bytes);
2243 }
2244 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2245 }
2246
2247 let offset = addr.offset as u32;
2248 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2249 }
2250
2251 ArmOp::Strb { rd, addr } => {
2253 let rd_bits = reg_to_bits(rd);
2254 let base_bits = reg_to_bits(&addr.base);
2255
2256 if let Some(offset_reg) = &addr.offset_reg {
2257 if addr.offset != 0 {
2258 let scratch = Reg::R12;
2259 let mut bytes =
2260 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2261 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2262 return Ok(bytes);
2263 }
2264 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2265 }
2266
2267 let offset = addr.offset as u32;
2268 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2269 let instr: u16 = 0x7000
2271 | ((offset as u16) << 6)
2272 | ((base_bits as u16) << 3)
2273 | (rd_bits as u16);
2274 Ok(instr.to_le_bytes().to_vec())
2275 } else {
2276 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2277 }
2278 }
2279
2280 ArmOp::Strh { rd, addr } => {
2282 let rd_bits = reg_to_bits(rd);
2283 let base_bits = reg_to_bits(&addr.base);
2284
2285 if let Some(offset_reg) = &addr.offset_reg {
2286 if addr.offset != 0 {
2287 let scratch = Reg::R12;
2288 let mut bytes =
2289 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2290 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2291 return Ok(bytes);
2292 }
2293 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2294 }
2295
2296 let offset = addr.offset as u32;
2297 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2298 let imm5 = (offset >> 1) as u16;
2300 let instr: u16 =
2301 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2302 Ok(instr.to_le_bytes().to_vec())
2303 } else {
2304 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2305 }
2306 }
2307
2308 ArmOp::MemorySize { rd } => {
2310 let rd_bits = reg_to_bits(rd);
2313 let r10_bits = reg_to_bits(&Reg::R10);
2314 if rd_bits < 8 && r10_bits < 8 {
2315 let instr: u16 =
2316 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2317 Ok(instr.to_le_bytes().to_vec())
2318 } else {
2319 let imm5: u32 = 16;
2321 let imm3 = (imm5 >> 2) & 0x7;
2322 let imm2 = imm5 & 0x3;
2323 let hw1: u16 = 0xEA4F;
2324 let hw2: u16 =
2325 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2326 let mut bytes = hw1.to_le_bytes().to_vec();
2327 bytes.extend_from_slice(&hw2.to_le_bytes());
2328 Ok(bytes)
2329 }
2330 }
2331
2332 ArmOp::MemoryGrow { rd, .. } => {
2334 let rd_bits = reg_to_bits(rd);
2338 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2341 bytes.extend_from_slice(&hw2.to_le_bytes());
2342 Ok(bytes)
2343 }
2344
2345 ArmOp::Bx { rm } => {
2347 let rm_bits = reg_to_bits(rm) as u16;
2348 let instr: u16 = 0x4700 | (rm_bits << 3);
2350 Ok(instr.to_le_bytes().to_vec())
2351 }
2352
2353 ArmOp::Blx { rm } => {
2356 let rm_bits = reg_to_bits(rm) as u16;
2357 let instr: u16 = 0x4780 | (rm_bits << 3);
2358 Ok(instr.to_le_bytes().to_vec())
2359 }
2360
2361 ArmOp::CallIndirect {
2365 rd: _,
2366 type_idx: _,
2367 table_index_reg,
2368 } => {
2369 let idx_reg = reg_to_bits(table_index_reg);
2370 let mut bytes = Vec::new();
2371
2372 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2388 bytes.extend_from_slice(&hw1.to_le_bytes());
2389 bytes.extend_from_slice(&hw2.to_le_bytes());
2390
2391 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2397 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2398
2399 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2403
2404 Ok(bytes)
2405 }
2406
2407 ArmOp::Label { .. } => Ok(Vec::new()),
2409
2410 ArmOp::Bcc { cond, label: _ } => {
2412 use synth_synthesis::Condition;
2413 let cond_bits: u16 = match cond {
2414 Condition::EQ => 0x0,
2415 Condition::NE => 0x1,
2416 Condition::HS => 0x2,
2417 Condition::LO => 0x3,
2418 Condition::HI => 0x8,
2419 Condition::LS => 0x9,
2420 Condition::GE => 0xA,
2421 Condition::LT => 0xB,
2422 Condition::GT => 0xC,
2423 Condition::LE => 0xD,
2424 };
2425 let instr: u16 = 0xD000 | (cond_bits << 8);
2427 Ok(instr.to_le_bytes().to_vec())
2428 }
2429
2430 ArmOp::B { label: _ } => {
2432 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2436 }
2437
2438 ArmOp::Bhs { label: _ } => {
2441 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2445 }
2446
2447 ArmOp::Blo { label: _ } => {
2450 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2454 }
2455
2456 ArmOp::BOffset { offset } => {
2459 let halfword_offset = *offset;
2462
2463 if (-1024..=1022).contains(&halfword_offset) {
2466 let imm11 = (halfword_offset as u16) & 0x7FF;
2468 let instr: u16 = 0xE000 | imm11;
2469 Ok(instr.to_le_bytes().to_vec())
2470 } else {
2471 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2487 let uoffset = signed_offset as u32;
2488 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;
2496 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2497
2498 let mut bytes = hw1.to_le_bytes().to_vec();
2499 bytes.extend_from_slice(&hw2.to_le_bytes());
2500 Ok(bytes)
2501 }
2502 }
2503
2504 ArmOp::BCondOffset { cond, offset } => {
2506 use synth_synthesis::Condition;
2507 let cond_bits: u16 = match cond {
2508 Condition::EQ => 0x0,
2509 Condition::NE => 0x1,
2510 Condition::HS => 0x2,
2511 Condition::LO => 0x3,
2512 Condition::HI => 0x8,
2513 Condition::LS => 0x9,
2514 Condition::GE => 0xA,
2515 Condition::LT => 0xB,
2516 Condition::GT => 0xC,
2517 Condition::LE => 0xD,
2518 };
2519
2520 let halfword_offset = *offset;
2523
2524 if (-128..=127).contains(&halfword_offset) {
2527 let imm8 = (halfword_offset as u16) & 0xFF;
2528 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2529 Ok(instr.to_le_bytes().to_vec())
2530 } else {
2531 let offset = halfword_offset >> 1;
2535 let s = if offset < 0 { 1u32 } else { 0u32 };
2536 let imm6 = ((offset >> 11) as u32) & 0x3F;
2537 let imm11 = (offset as u32) & 0x7FF;
2538 let j1 = if s == 1 { 1 } else { 0 };
2539 let j2 = if s == 1 { 1 } else { 0 };
2540
2541 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2542 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2543
2544 let mut bytes = hw1.to_le_bytes().to_vec();
2545 bytes.extend_from_slice(&hw2.to_le_bytes());
2546 Ok(bytes)
2547 }
2548 }
2549
2550 ArmOp::Bl { label: _ } => {
2551 let hw1: u16 = 0xF7FF;
2566 let hw2: u16 = 0xFFFE;
2567 let mut bytes = hw1.to_le_bytes().to_vec();
2568 bytes.extend_from_slice(&hw2.to_le_bytes());
2569 Ok(bytes)
2570 }
2571
2572 ArmOp::Mvn { rd, op2 } => {
2574 if let Operand2::Reg(rm) = op2 {
2575 let rd_bits = reg_to_bits(rd) as u16;
2576 let rm_bits = reg_to_bits(rm) as u16;
2577
2578 if rd_bits < 8 && rm_bits < 8 {
2579 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2581 Ok(instr.to_le_bytes().to_vec())
2582 } else {
2583 let hw1: u16 = 0xEA6F_u16;
2585 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2586 let mut bytes = hw1.to_le_bytes().to_vec();
2587 bytes.extend_from_slice(&hw2.to_le_bytes());
2588 Ok(bytes)
2589 }
2590 } else {
2591 let instr: u16 = 0xBF00;
2592 Ok(instr.to_le_bytes().to_vec())
2593 }
2594 }
2595
2596 ArmOp::Movw { rd, imm16 } => {
2598 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2599 }
2600
2601 ArmOp::Movt { rd, imm16 } => {
2603 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2604 }
2605
2606 ArmOp::SetCond { rd, cond } => {
2612 let rd_bits = reg_to_bits(rd) as u16;
2613
2614 use synth_synthesis::Condition;
2616 let cond_bits: u16 = match cond {
2617 Condition::EQ => 0x0,
2618 Condition::NE => 0x1,
2619 Condition::LT => 0xB,
2620 Condition::LE => 0xD,
2621 Condition::GT => 0xC,
2622 Condition::GE => 0xA,
2623 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2628
2629 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2634 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2635
2636 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2638
2639 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2641
2642 let mut bytes = ite_instr.to_le_bytes().to_vec();
2644 bytes.extend_from_slice(&mov_one.to_le_bytes());
2645 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2646 Ok(bytes)
2647 }
2648
2649 ArmOp::I64SetCond {
2654 rd,
2655 rn_lo,
2656 rn_hi,
2657 rm_lo,
2658 rm_hi,
2659 cond,
2660 } => {
2661 use synth_synthesis::Condition;
2662 let rd_bits = reg_to_bits(rd) as u16;
2663 let mut bytes = Vec::new();
2664
2665 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2667 rm: &synth_synthesis::Reg|
2668 -> Vec<u8> {
2669 let rn_bits = reg_to_bits(rn) as u16;
2670 let rm_bits = reg_to_bits(rm) as u16;
2671 if rn_bits < 8 && rm_bits < 8 {
2672 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2673 instr.to_le_bytes().to_vec()
2674 } else {
2675 let n_bit = (rn_bits >> 3) & 1;
2676 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2677 instr.to_le_bytes().to_vec()
2678 }
2679 };
2680
2681 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2683 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2684 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2685 ite_instr.to_le_bytes().to_vec()
2686 };
2687
2688 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2690 let mut b = encode_ite(cond_bits);
2691 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2692 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2693 b.extend_from_slice(&mov_one.to_le_bytes());
2694 b.extend_from_slice(&mov_zero.to_le_bytes());
2695 b
2696 };
2697
2698 match cond {
2699 Condition::EQ | Condition::NE => {
2700 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2702
2703 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2706
2707 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2709
2710 let cond_bits: u16 = match cond {
2712 Condition::EQ => 0x0,
2713 Condition::NE => 0x1,
2714 _ => unreachable!(),
2715 };
2716 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2717 }
2718
2719 Condition::LT => {
2720 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2722
2723 let rn_hi_bits = reg_to_bits(rn_hi);
2726 let rm_hi_bits = reg_to_bits(rm_hi);
2727 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2728 let hw2: u16 = ((rd_bits as u32) << 8 | rm_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::GT => {
2737 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2740
2741 let rm_hi_bits = reg_to_bits(rm_hi);
2743 let rn_hi_bits = reg_to_bits(rn_hi);
2744 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2745 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2746 bytes.extend_from_slice(&hw1.to_le_bytes());
2747 bytes.extend_from_slice(&hw2.to_le_bytes());
2748
2749 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2752
2753 Condition::LE => {
2754 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2758
2759 let rm_hi_bits = reg_to_bits(rm_hi);
2761 let rn_hi_bits = reg_to_bits(rn_hi);
2762 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2763 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2764 bytes.extend_from_slice(&hw1.to_le_bytes());
2765 bytes.extend_from_slice(&hw2.to_le_bytes());
2766
2767 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2770
2771 Condition::GE => {
2772 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2775
2776 let rn_hi_bits = reg_to_bits(rn_hi);
2778 let rm_hi_bits = reg_to_bits(rm_hi);
2779 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2780 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2781 bytes.extend_from_slice(&hw1.to_le_bytes());
2782 bytes.extend_from_slice(&hw2.to_le_bytes());
2783
2784 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2787
2788 Condition::LO => {
2790 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2792 let rn_hi_bits = reg_to_bits(rn_hi);
2793 let rm_hi_bits = reg_to_bits(rm_hi);
2794 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2795 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2796 bytes.extend_from_slice(&hw1.to_le_bytes());
2797 bytes.extend_from_slice(&hw2.to_le_bytes());
2798 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2800
2801 Condition::HI => {
2802 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2804 let rm_hi_bits = reg_to_bits(rm_hi);
2805 let rn_hi_bits = reg_to_bits(rn_hi);
2806 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2807 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2808 bytes.extend_from_slice(&hw1.to_le_bytes());
2809 bytes.extend_from_slice(&hw2.to_le_bytes());
2810 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2812
2813 Condition::LS => {
2814 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2816 let rm_hi_bits = reg_to_bits(rm_hi);
2817 let rn_hi_bits = reg_to_bits(rn_hi);
2818 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2819 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2820 bytes.extend_from_slice(&hw1.to_le_bytes());
2821 bytes.extend_from_slice(&hw2.to_le_bytes());
2822 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2824
2825 Condition::HS => {
2826 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2828 let rn_hi_bits = reg_to_bits(rn_hi);
2829 let rm_hi_bits = reg_to_bits(rm_hi);
2830 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2831 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2832 bytes.extend_from_slice(&hw1.to_le_bytes());
2833 bytes.extend_from_slice(&hw2.to_le_bytes());
2834 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2836 }
2837
2838 Ok(bytes)
2839 }
2840
2841 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2844 let rd_bits = reg_to_bits(rd);
2845 let rn_lo_bits = reg_to_bits(rn_lo);
2846 let rn_hi_bits = reg_to_bits(rn_hi);
2847 let mut bytes = Vec::new();
2848
2849 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2851 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2852 bytes.extend_from_slice(&hw1.to_le_bytes());
2853 bytes.extend_from_slice(&hw2.to_le_bytes());
2854
2855 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2857 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2858
2859 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2862 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2863 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2864 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2865 bytes.extend_from_slice(&mov_one.to_le_bytes());
2866 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2867
2868 Ok(bytes)
2869 }
2870
2871 ArmOp::I64Mul {
2875 rd_lo,
2876 rd_hi,
2877 rn_lo,
2878 rn_hi,
2879 rm_lo,
2880 rm_hi,
2881 } => {
2882 let rd_lo_bits = reg_to_bits(rd_lo);
2883 let rd_hi_bits = reg_to_bits(rd_hi);
2884 let rn_lo_bits = reg_to_bits(rn_lo);
2885 let rn_hi_bits = reg_to_bits(rn_hi);
2886 let rm_lo_bits = reg_to_bits(rm_lo);
2887 let rm_hi_bits = reg_to_bits(rm_hi);
2888 let r12: u32 = 12; let mut bytes = Vec::new();
2890
2891 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2894 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2895 bytes.extend_from_slice(&hw1.to_le_bytes());
2896 bytes.extend_from_slice(&hw2.to_le_bytes());
2897
2898 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2901 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
2902 bytes.extend_from_slice(&hw1.to_le_bytes());
2903 bytes.extend_from_slice(&hw2.to_le_bytes());
2904
2905 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
2908 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2909 bytes.extend_from_slice(&hw1.to_le_bytes());
2910 bytes.extend_from_slice(&hw2.to_le_bytes());
2911
2912 let d_bit = (rd_hi_bits >> 3) & 1;
2915 let add_instr: u16 =
2916 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
2917 bytes.extend_from_slice(&add_instr.to_le_bytes());
2918
2919 Ok(bytes)
2920 }
2921
2922 ArmOp::I64Shl {
2925 rd_lo,
2926 rd_hi,
2927 rn_lo,
2928 rn_hi,
2929 rm_lo,
2930 rm_hi,
2931 } => {
2932 let rd_lo_bits = reg_to_bits(rd_lo);
2933 let rd_hi_bits = reg_to_bits(rd_hi);
2934 let rn_lo_bits = reg_to_bits(rn_lo);
2935 let rn_hi_bits = reg_to_bits(rn_hi);
2936 let rm_lo_bits = reg_to_bits(rm_lo);
2937 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2939
2940 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2942 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) 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 = (0xF1B0 | rm_lo_bits) as u16;
2948 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2949 bytes.extend_from_slice(&hw1.to_le_bytes());
2950 bytes.extend_from_slice(&hw2.to_le_bytes());
2951
2952 let bpl: u16 = 0xD50A;
2954 bytes.extend_from_slice(&bpl.to_le_bytes());
2955
2956 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2959 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2960 bytes.extend_from_slice(&hw1.to_le_bytes());
2961 bytes.extend_from_slice(&hw2.to_le_bytes());
2962
2963 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2965 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2966 bytes.extend_from_slice(&hw1.to_le_bytes());
2967 bytes.extend_from_slice(&hw2.to_le_bytes());
2968
2969 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2971 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2972 bytes.extend_from_slice(&hw1.to_le_bytes());
2973 bytes.extend_from_slice(&hw2.to_le_bytes());
2974
2975 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
2977 let hw2: u16 = ((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 hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2983 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2984 bytes.extend_from_slice(&hw1.to_le_bytes());
2985 bytes.extend_from_slice(&hw2.to_le_bytes());
2986
2987 let b_done: u16 = 0xE002;
2989 bytes.extend_from_slice(&b_done.to_le_bytes());
2990
2991 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2994 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
2995 bytes.extend_from_slice(&hw1.to_le_bytes());
2996 bytes.extend_from_slice(&hw2.to_le_bytes());
2997
2998 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3000 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3001
3002 Ok(bytes) }
3004
3005 ArmOp::I64ShrU {
3007 rd_lo,
3008 rd_hi,
3009 rn_lo,
3010 rn_hi,
3011 rm_lo,
3012 rm_hi,
3013 } => {
3014 let rd_lo_bits = reg_to_bits(rd_lo);
3015 let rd_hi_bits = reg_to_bits(rd_hi);
3016 let rn_lo_bits = reg_to_bits(rn_lo);
3017 let rn_hi_bits = reg_to_bits(rn_hi);
3018 let rm_lo_bits = reg_to_bits(rm_lo);
3019 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3021
3022 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3024 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) 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 = (0xF1B0 | rm_lo_bits) as u16;
3030 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3031 bytes.extend_from_slice(&hw1.to_le_bytes());
3032 bytes.extend_from_slice(&hw2.to_le_bytes());
3033
3034 let bpl: u16 = 0xD50A;
3036 bytes.extend_from_slice(&bpl.to_le_bytes());
3037
3038 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3041 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3042 bytes.extend_from_slice(&hw1.to_le_bytes());
3043 bytes.extend_from_slice(&hw2.to_le_bytes());
3044
3045 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3047 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3048 bytes.extend_from_slice(&hw1.to_le_bytes());
3049 bytes.extend_from_slice(&hw2.to_le_bytes());
3050
3051 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3053 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3054 bytes.extend_from_slice(&hw1.to_le_bytes());
3055 bytes.extend_from_slice(&hw2.to_le_bytes());
3056
3057 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3059 let hw2: u16 = ((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 hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3065 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3066 bytes.extend_from_slice(&hw1.to_le_bytes());
3067 bytes.extend_from_slice(&hw2.to_le_bytes());
3068
3069 let b_done: u16 = 0xE002;
3071 bytes.extend_from_slice(&b_done.to_le_bytes());
3072
3073 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3076 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3077 bytes.extend_from_slice(&hw1.to_le_bytes());
3078 bytes.extend_from_slice(&hw2.to_le_bytes());
3079
3080 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3082 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3083
3084 Ok(bytes) }
3086
3087 ArmOp::I64ShrS {
3089 rd_lo,
3090 rd_hi,
3091 rn_lo,
3092 rn_hi,
3093 rm_lo,
3094 rm_hi,
3095 } => {
3096 let rd_lo_bits = reg_to_bits(rd_lo);
3097 let rd_hi_bits = reg_to_bits(rd_hi);
3098 let rn_lo_bits = reg_to_bits(rn_lo);
3099 let rn_hi_bits = reg_to_bits(rn_hi);
3100 let rm_lo_bits = reg_to_bits(rm_lo);
3101 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3103
3104 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3106 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) 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 = (0xF1B0 | rm_lo_bits) as u16;
3112 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3113 bytes.extend_from_slice(&hw1.to_le_bytes());
3114 bytes.extend_from_slice(&hw2.to_le_bytes());
3115
3116 let bpl: u16 = 0xD50A;
3118 bytes.extend_from_slice(&bpl.to_le_bytes());
3119
3120 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3123 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3124 bytes.extend_from_slice(&hw1.to_le_bytes());
3125 bytes.extend_from_slice(&hw2.to_le_bytes());
3126
3127 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3129 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3130 bytes.extend_from_slice(&hw1.to_le_bytes());
3131 bytes.extend_from_slice(&hw2.to_le_bytes());
3132
3133 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3135 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3136 bytes.extend_from_slice(&hw1.to_le_bytes());
3137 bytes.extend_from_slice(&hw2.to_le_bytes());
3138
3139 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3141 let hw2: u16 = ((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 = (0xFA40 | rn_hi_bits) as u16;
3147 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3148 bytes.extend_from_slice(&hw1.to_le_bytes());
3149 bytes.extend_from_slice(&hw2.to_le_bytes());
3150
3151 let b_done: u16 = 0xE003;
3153 bytes.extend_from_slice(&b_done.to_le_bytes());
3154
3155 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3158 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3159 bytes.extend_from_slice(&hw1.to_le_bytes());
3160 bytes.extend_from_slice(&hw2.to_le_bytes());
3161
3162 let hw1: u16 = 0xEA4F;
3166 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3167 bytes.extend_from_slice(&hw1.to_le_bytes());
3168 bytes.extend_from_slice(&hw2.to_le_bytes());
3169
3170 Ok(bytes) }
3172
3173 ArmOp::I64Rotl {
3178 rdlo,
3179 rdhi,
3180 rnlo,
3181 rnhi,
3182 shift,
3183 } => {
3184 let rd_lo_bits = reg_to_bits(rdlo);
3185 let rd_hi_bits = reg_to_bits(rdhi);
3186 let rn_lo_bits = reg_to_bits(rnlo);
3187 let rn_hi_bits = reg_to_bits(rnhi);
3188 let shift_bits = reg_to_bits(shift);
3189 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3193
3194 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3196
3197 let hw1: u16 = (0xF000 | shift_bits) as u16;
3199 let hw2: u16 = ((shift_bits << 8) | 0x3F) 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 = (0xF1B0 | shift_bits) as u16;
3205 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3206 bytes.extend_from_slice(&hw1.to_le_bytes());
3207 bytes.extend_from_slice(&hw2.to_le_bytes());
3208
3209 let bpl: u16 = 0xD50E;
3211 bytes.extend_from_slice(&bpl.to_le_bytes());
3212
3213 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3216 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3217 bytes.extend_from_slice(&hw1.to_le_bytes());
3218 bytes.extend_from_slice(&hw2.to_le_bytes());
3219
3220 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3222 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3223 bytes.extend_from_slice(&hw1.to_le_bytes());
3224 bytes.extend_from_slice(&hw2.to_le_bytes());
3225
3226 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3228 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3229 bytes.extend_from_slice(&hw1.to_le_bytes());
3230 bytes.extend_from_slice(&hw2.to_le_bytes());
3231
3232 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3234 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3235 bytes.extend_from_slice(&hw1.to_le_bytes());
3236 bytes.extend_from_slice(&hw2.to_le_bytes());
3237
3238 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3240 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3241 bytes.extend_from_slice(&hw1.to_le_bytes());
3242 bytes.extend_from_slice(&hw2.to_le_bytes());
3243
3244 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3246 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3247 bytes.extend_from_slice(&hw1.to_le_bytes());
3248 bytes.extend_from_slice(&hw2.to_le_bytes());
3249
3250 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3252 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3253 bytes.extend_from_slice(&hw1.to_le_bytes());
3254 bytes.extend_from_slice(&hw2.to_le_bytes());
3255
3256 let b_done: u16 = 0xE00E;
3258 bytes.extend_from_slice(&b_done.to_le_bytes());
3259
3260 let hw1: u16 = (0xF1C0 | r3) as u16;
3264 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3265 bytes.extend_from_slice(&hw1.to_le_bytes());
3266 bytes.extend_from_slice(&hw2.to_le_bytes());
3267
3268 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3270 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3271 bytes.extend_from_slice(&hw1.to_le_bytes());
3272 bytes.extend_from_slice(&hw2.to_le_bytes());
3273
3274 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3276 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3277 bytes.extend_from_slice(&hw1.to_le_bytes());
3278 bytes.extend_from_slice(&hw2.to_le_bytes());
3279
3280 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3282 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3283 bytes.extend_from_slice(&hw1.to_le_bytes());
3284 bytes.extend_from_slice(&hw2.to_le_bytes());
3285
3286 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3288 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3289 bytes.extend_from_slice(&hw1.to_le_bytes());
3290 bytes.extend_from_slice(&hw2.to_le_bytes());
3291
3292 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3294 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3295 bytes.extend_from_slice(&hw1.to_le_bytes());
3296 bytes.extend_from_slice(&hw2.to_le_bytes());
3297
3298 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3300 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3301 bytes.extend_from_slice(&hw1.to_le_bytes());
3302 bytes.extend_from_slice(&hw2.to_le_bytes());
3303
3304 let d_bit = (rd_hi_bits >> 3) & 1;
3306 let mov_instr: u16 =
3307 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3308 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3309
3310 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3312
3313 Ok(bytes) }
3315
3316 ArmOp::I64Rotr {
3321 rdlo,
3322 rdhi,
3323 rnlo,
3324 rnhi,
3325 shift,
3326 } => {
3327 let rd_lo_bits = reg_to_bits(rdlo);
3328 let rd_hi_bits = reg_to_bits(rdhi);
3329 let rn_lo_bits = reg_to_bits(rnlo);
3330 let rn_hi_bits = reg_to_bits(rnhi);
3331 let shift_bits = reg_to_bits(shift);
3332 let r12: u32 = 12;
3333 let r3: u32 = 3;
3334 let r4: u32 = 4;
3335 let mut bytes = Vec::new();
3336
3337 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3339
3340 let hw1: u16 = (0xF000 | shift_bits) as u16;
3342 let hw2: u16 = ((shift_bits << 8) | 0x3F) 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 = (0xF1B0 | shift_bits) as u16;
3348 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3349 bytes.extend_from_slice(&hw1.to_le_bytes());
3350 bytes.extend_from_slice(&hw2.to_le_bytes());
3351
3352 let bpl: u16 = 0xD50E;
3354 bytes.extend_from_slice(&bpl.to_le_bytes());
3355
3356 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3359 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3360 bytes.extend_from_slice(&hw1.to_le_bytes());
3361 bytes.extend_from_slice(&hw2.to_le_bytes());
3362
3363 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3365 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3366 bytes.extend_from_slice(&hw1.to_le_bytes());
3367 bytes.extend_from_slice(&hw2.to_le_bytes());
3368
3369 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3371 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3372 bytes.extend_from_slice(&hw1.to_le_bytes());
3373 bytes.extend_from_slice(&hw2.to_le_bytes());
3374
3375 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3377 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3378 bytes.extend_from_slice(&hw1.to_le_bytes());
3379 bytes.extend_from_slice(&hw2.to_le_bytes());
3380
3381 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3383 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3384 bytes.extend_from_slice(&hw1.to_le_bytes());
3385 bytes.extend_from_slice(&hw2.to_le_bytes());
3386
3387 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3389 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3390 bytes.extend_from_slice(&hw1.to_le_bytes());
3391 bytes.extend_from_slice(&hw2.to_le_bytes());
3392
3393 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3395 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3396 bytes.extend_from_slice(&hw1.to_le_bytes());
3397 bytes.extend_from_slice(&hw2.to_le_bytes());
3398
3399 let b_done: u16 = 0xE00E;
3401 bytes.extend_from_slice(&b_done.to_le_bytes());
3402
3403 let hw1: u16 = (0xF1C0 | r3) as u16;
3406 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3407 bytes.extend_from_slice(&hw1.to_le_bytes());
3408 bytes.extend_from_slice(&hw2.to_le_bytes());
3409
3410 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3412 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3413 bytes.extend_from_slice(&hw1.to_le_bytes());
3414 bytes.extend_from_slice(&hw2.to_le_bytes());
3415
3416 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3418 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3419 bytes.extend_from_slice(&hw1.to_le_bytes());
3420 bytes.extend_from_slice(&hw2.to_le_bytes());
3421
3422 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3424 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3425 bytes.extend_from_slice(&hw1.to_le_bytes());
3426 bytes.extend_from_slice(&hw2.to_le_bytes());
3427
3428 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3430 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3431 bytes.extend_from_slice(&hw1.to_le_bytes());
3432 bytes.extend_from_slice(&hw2.to_le_bytes());
3433
3434 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3436 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3437 bytes.extend_from_slice(&hw1.to_le_bytes());
3438 bytes.extend_from_slice(&hw2.to_le_bytes());
3439
3440 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3442 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3443 bytes.extend_from_slice(&hw1.to_le_bytes());
3444 bytes.extend_from_slice(&hw2.to_le_bytes());
3445
3446 let d_bit = (rd_lo_bits >> 3) & 1;
3448 let mov_instr: u16 =
3449 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3450 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3451
3452 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3454
3455 Ok(bytes) }
3457
3458 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3472 let rd_bits = reg_to_bits(rd);
3473 let rn_lo_bits = reg_to_bits(rnlo);
3474 let rn_hi_bits = reg_to_bits(rnhi);
3475 let mut bytes = Vec::new();
3476
3477 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3479 let hw2: u16 = 0x0F00;
3480 bytes.extend_from_slice(&hw1.to_le_bytes());
3481 bytes.extend_from_slice(&hw2.to_le_bytes());
3482
3483 let beq: u16 = 0xD003;
3486 bytes.extend_from_slice(&beq.to_le_bytes());
3487
3488 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3491 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3492 bytes.extend_from_slice(&hw1.to_le_bytes());
3493 bytes.extend_from_slice(&hw2.to_le_bytes());
3494
3495 let b_done: u16 = 0xE004;
3498 bytes.extend_from_slice(&b_done.to_le_bytes());
3499
3500 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3502
3503 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3507 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3508 bytes.extend_from_slice(&hw1.to_le_bytes());
3509 bytes.extend_from_slice(&hw2.to_le_bytes());
3510
3511 let hw1: u16 = (0xF100 | rd_bits) as u16;
3513 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3514 bytes.extend_from_slice(&hw1.to_le_bytes());
3515 bytes.extend_from_slice(&hw2.to_le_bytes());
3516
3517 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3521 bytes.extend_from_slice(&mov0.to_le_bytes());
3522
3523 Ok(bytes)
3524 }
3525
3526 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3542 let rd_bits = reg_to_bits(rd);
3543 let rn_lo_bits = reg_to_bits(rnlo);
3544 let rn_hi_bits = reg_to_bits(rnhi);
3545 let mut bytes = Vec::new();
3546
3547 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3549 let hw2: u16 = 0x0F00;
3550 bytes.extend_from_slice(&hw1.to_le_bytes());
3551 bytes.extend_from_slice(&hw2.to_le_bytes());
3552
3553 let beq: u16 = 0xD005;
3556 bytes.extend_from_slice(&beq.to_le_bytes());
3557
3558 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3561 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3562 bytes.extend_from_slice(&hw1.to_le_bytes());
3563 bytes.extend_from_slice(&hw2.to_le_bytes());
3564
3565 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3568 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3569 bytes.extend_from_slice(&hw1.to_le_bytes());
3570 bytes.extend_from_slice(&hw2.to_le_bytes());
3571
3572 let b_done: u16 = 0xE006;
3575 bytes.extend_from_slice(&b_done.to_le_bytes());
3576
3577 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3579
3580 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3584 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3585 bytes.extend_from_slice(&hw1.to_le_bytes());
3586 bytes.extend_from_slice(&hw2.to_le_bytes());
3587
3588 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3591 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3592 bytes.extend_from_slice(&hw1.to_le_bytes());
3593 bytes.extend_from_slice(&hw2.to_le_bytes());
3594
3595 let hw1: u16 = (0xF100 | rd_bits) as u16;
3597 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3598 bytes.extend_from_slice(&hw1.to_le_bytes());
3599 bytes.extend_from_slice(&hw2.to_le_bytes());
3600
3601 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3604 bytes.extend_from_slice(&mov0.to_le_bytes());
3605
3606 Ok(bytes)
3607 }
3608
3609 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3613 let rd_bits = reg_to_bits(rd);
3614 let rn_lo_bits = reg_to_bits(rnlo);
3615 let rn_hi_bits = reg_to_bits(rnhi);
3616 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3619
3620 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3622
3623 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3633 bytes.extend_from_slice(&mov.to_le_bytes());
3634
3635 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3638 bytes.extend_from_slice(&mov.to_le_bytes());
3639
3640 let hw1: u16 = 0xEA4F;
3644 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3645 bytes.extend_from_slice(&hw1.to_le_bytes());
3646 bytes.extend_from_slice(&hw2.to_le_bytes());
3647
3648 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3651 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3652 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3654 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3655
3656 let hw1: u16 = (0xEA00 | r12) as u16;
3658 let hw2: u16 = ((r12 << 8) | r3) as u16;
3659 bytes.extend_from_slice(&hw1.to_le_bytes());
3660 bytes.extend_from_slice(&hw2.to_le_bytes());
3661
3662 let hw1: u16 = (0xEBA0 | 4) as u16;
3664 let hw2: u16 = ((4 << 8) | r12) as u16;
3665 bytes.extend_from_slice(&hw1.to_le_bytes());
3666 bytes.extend_from_slice(&hw2.to_le_bytes());
3667
3668 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3672 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3673 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3675 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3676
3677 let hw1: u16 = (0xEA00 | 4) as u16;
3679 let hw2: u16 = ((r12 << 8) | r3) as u16;
3680 bytes.extend_from_slice(&hw1.to_le_bytes());
3681 bytes.extend_from_slice(&hw2.to_le_bytes());
3682
3683 let hw1: u16 = 0xEA4F;
3685 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3686 bytes.extend_from_slice(&hw1.to_le_bytes());
3687 bytes.extend_from_slice(&hw2.to_le_bytes());
3688
3689 let hw1: u16 = (0xEA00 | 4) as u16;
3691 let hw2: u16 = ((4 << 8) | r3) as u16;
3692 bytes.extend_from_slice(&hw1.to_le_bytes());
3693 bytes.extend_from_slice(&hw2.to_le_bytes());
3694
3695 let hw1: u16 = (0xEB00 | 4) as u16;
3697 let hw2: u16 = ((4 << 8) | r12) as u16;
3698 bytes.extend_from_slice(&hw1.to_le_bytes());
3699 bytes.extend_from_slice(&hw2.to_le_bytes());
3700
3701 let hw1: u16 = 0xEA4F;
3706 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3707 bytes.extend_from_slice(&hw1.to_le_bytes());
3708 bytes.extend_from_slice(&hw2.to_le_bytes());
3709
3710 let hw1: u16 = (0xEB00 | 4) as u16;
3712 let hw2: u16 = ((4 << 8) | r12) as u16;
3713 bytes.extend_from_slice(&hw1.to_le_bytes());
3714 bytes.extend_from_slice(&hw2.to_le_bytes());
3715
3716 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3721 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3722 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3724 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3725
3726 let hw1: u16 = (0xEA00 | 4) as u16;
3728 let hw2: u16 = ((4 << 8) | r3) as u16;
3729 bytes.extend_from_slice(&hw1.to_le_bytes());
3730 bytes.extend_from_slice(&hw2.to_le_bytes());
3731
3732 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3736 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3737 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3739 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3740
3741 let hw1: u16 = (0xFB00 | 4) as u16;
3744 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3745 bytes.extend_from_slice(&hw1.to_le_bytes());
3746 bytes.extend_from_slice(&hw2.to_le_bytes());
3747
3748 let hw1: u16 = 0xEA4F;
3751 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3752 bytes.extend_from_slice(&hw1.to_le_bytes());
3753 bytes.extend_from_slice(&hw2.to_le_bytes());
3754
3755 let hw1: u16 = 0xEA4F;
3758 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3759 bytes.extend_from_slice(&hw1.to_le_bytes());
3760 bytes.extend_from_slice(&hw2.to_le_bytes());
3761
3762 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3764 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3765 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3766 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3767
3768 let hw1: u16 = (0xEA00 | r12) as u16;
3769 let hw2: u16 = ((r12 << 8) | r3) as u16;
3770 bytes.extend_from_slice(&hw1.to_le_bytes());
3771 bytes.extend_from_slice(&hw2.to_le_bytes());
3772
3773 let hw1: u16 = (0xEBA0 | 5) as u16;
3774 let hw2: u16 = ((5 << 8) | r12) as u16;
3775 bytes.extend_from_slice(&hw1.to_le_bytes());
3776 bytes.extend_from_slice(&hw2.to_le_bytes());
3777
3778 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3780 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3781 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3782 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3783
3784 let hw1: u16 = (0xEA00 | 5) as u16;
3785 let hw2: u16 = ((r12 << 8) | r3) as u16;
3786 bytes.extend_from_slice(&hw1.to_le_bytes());
3787 bytes.extend_from_slice(&hw2.to_le_bytes());
3788
3789 let hw1: u16 = 0xEA4F;
3790 let hw2: u16 = ((5 << 8) | 0x90 | 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 = (0xEA00 | 5) as u16;
3795 let hw2: u16 = ((5 << 8) | r3) as u16;
3796 bytes.extend_from_slice(&hw1.to_le_bytes());
3797 bytes.extend_from_slice(&hw2.to_le_bytes());
3798
3799 let hw1: u16 = (0xEB00 | 5) as u16;
3800 let hw2: u16 = ((5 << 8) | r12) as u16;
3801 bytes.extend_from_slice(&hw1.to_le_bytes());
3802 bytes.extend_from_slice(&hw2.to_le_bytes());
3803
3804 let hw1: u16 = 0xEA4F;
3807 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3808 bytes.extend_from_slice(&hw1.to_le_bytes());
3809 bytes.extend_from_slice(&hw2.to_le_bytes());
3810
3811 let hw1: u16 = (0xEB00 | 5) as u16;
3812 let hw2: u16 = ((5 << 8) | r12) as u16;
3813 bytes.extend_from_slice(&hw1.to_le_bytes());
3814 bytes.extend_from_slice(&hw2.to_le_bytes());
3815
3816 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3818 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3819 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3820 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3821
3822 let hw1: u16 = (0xEA00 | 5) as u16;
3823 let hw2: u16 = ((5 << 8) | r3) as u16;
3824 bytes.extend_from_slice(&hw1.to_le_bytes());
3825 bytes.extend_from_slice(&hw2.to_le_bytes());
3826
3827 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3829 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3830 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3831 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3832
3833 let hw1: u16 = (0xFB00 | 5) as u16;
3836 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3837 bytes.extend_from_slice(&hw1.to_le_bytes());
3838 bytes.extend_from_slice(&hw2.to_le_bytes());
3839
3840 let hw1: u16 = 0xEA4F;
3843 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3844 bytes.extend_from_slice(&hw1.to_le_bytes());
3845 bytes.extend_from_slice(&hw2.to_le_bytes());
3846
3847 let rd_bits_u16 = rd_bits as u16;
3850 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3851 bytes.extend_from_slice(&instr.to_le_bytes());
3852
3853 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3855
3856 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3858 bytes.extend_from_slice(&mov0.to_le_bytes());
3859
3860 Ok(bytes)
3861 }
3862
3863 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3866 let rdlo_bits = reg_to_bits(rdlo);
3867 let rdhi_bits = reg_to_bits(rdhi);
3868 let rnlo_bits = reg_to_bits(rnlo);
3869 let mut bytes = Vec::new();
3870
3871 let hw1: u16 = 0xFA4F_u16;
3874 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3875 bytes.extend_from_slice(&hw1.to_le_bytes());
3876 bytes.extend_from_slice(&hw2.to_le_bytes());
3877
3878 let hw1: u16 = 0xEA4F;
3883 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3884 bytes.extend_from_slice(&hw1.to_le_bytes());
3885 bytes.extend_from_slice(&hw2.to_le_bytes());
3886
3887 Ok(bytes)
3888 }
3889
3890 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3893 let rdlo_bits = reg_to_bits(rdlo);
3894 let rdhi_bits = reg_to_bits(rdhi);
3895 let rnlo_bits = reg_to_bits(rnlo);
3896 let mut bytes = Vec::new();
3897
3898 let hw1: u16 = 0xFA0F_u16;
3901 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3902 bytes.extend_from_slice(&hw1.to_le_bytes());
3903 bytes.extend_from_slice(&hw2.to_le_bytes());
3904
3905 let hw1: u16 = 0xEA4F;
3907 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3908 bytes.extend_from_slice(&hw1.to_le_bytes());
3909 bytes.extend_from_slice(&hw2.to_le_bytes());
3910
3911 Ok(bytes)
3912 }
3913
3914 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
3917 let rdlo_bits = reg_to_bits(rdlo);
3918 let rdhi_bits = reg_to_bits(rdhi);
3919 let rnlo_bits = reg_to_bits(rnlo);
3920 let mut bytes = Vec::new();
3921
3922 if rdlo_bits != rnlo_bits {
3924 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
3926 let mov: u16 = 0x4600
3927 | (d_bit << 7)
3928 | ((rnlo_bits as u16) << 3)
3929 | ((rdlo_bits & 0x7) as u16);
3930 bytes.extend_from_slice(&mov.to_le_bytes());
3931 }
3932
3933 let hw1: u16 = 0xEA4F;
3935 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
3936 bytes.extend_from_slice(&hw1.to_le_bytes());
3937 bytes.extend_from_slice(&hw2.to_le_bytes());
3938
3939 Ok(bytes)
3940 }
3941
3942 ArmOp::SelectMove { rd, rm, cond } => {
3945 let rd_bits = reg_to_bits(rd) as u16;
3946 let rm_bits = reg_to_bits(rm) as u16;
3947
3948 use synth_synthesis::Condition;
3950 let cond_bits: u16 = match cond {
3951 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, };
3962
3963 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
3966
3967 let d_bit = (rd_bits >> 3) & 1;
3970 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3971
3972 let mut bytes = it_instr.to_le_bytes().to_vec();
3974 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3975 Ok(bytes)
3976 }
3977
3978 ArmOp::Popcnt { rd, rm } => {
3989 let mut bytes = Vec::new();
3990
3991 if rd != rm {
3993 let rd_bits = reg_to_bits(rd) as u16;
3994 let rm_bits = reg_to_bits(rm) as u16;
3995 let d_bit = (rd_bits >> 3) & 1;
3997 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3998 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3999 }
4000
4001 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4004 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4005
4006 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4009
4010 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4012
4013 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4015 reg_to_bits(rd),
4016 reg_to_bits(rd),
4017 11,
4018 )?);
4019
4020 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4023 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4024
4025 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4027 11,
4028 reg_to_bits(rd),
4029 12,
4030 )?);
4031
4032 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4034 reg_to_bits(rd),
4035 reg_to_bits(rd),
4036 2,
4037 )?);
4038
4039 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4041 reg_to_bits(rd),
4042 reg_to_bits(rd),
4043 12,
4044 )?);
4045
4046 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4048 reg_to_bits(rd),
4049 reg_to_bits(rd),
4050 11,
4051 )?);
4052
4053 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4056
4057 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4059 reg_to_bits(rd),
4060 reg_to_bits(rd),
4061 11,
4062 )?);
4063
4064 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4066 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4067
4068 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4070 reg_to_bits(rd),
4071 reg_to_bits(rd),
4072 12,
4073 )?);
4074
4075 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4078
4079 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4081 reg_to_bits(rd),
4082 reg_to_bits(rd),
4083 11,
4084 )?);
4085
4086 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4089
4090 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4092 reg_to_bits(rd),
4093 reg_to_bits(rd),
4094 11,
4095 )?);
4096
4097 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4100 reg_to_bits(rd),
4101 reg_to_bits(rd),
4102 0x3F,
4103 )?);
4104
4105 Ok(bytes)
4106 }
4107
4108 ArmOp::I64DivU {
4113 rdlo: _,
4114 rdhi: _,
4115 rnlo: _,
4116 rnhi: _,
4117 rmlo: _,
4118 rmhi: _,
4119 } => {
4120 let mut bytes = Vec::new();
4121
4122 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4126
4127 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());
4138 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4139
4140 let loop_start = bytes.len();
4142
4143 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4154 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());
4163 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4164 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4168 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4169
4170 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4175 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4176 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());
4207 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4208 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4211
4212 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4216 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4217
4218 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4221 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4222 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4223
4224 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4232
4233 Ok(bytes)
4234 }
4235
4236 ArmOp::I64DivS {
4241 rdlo: _,
4242 rdhi: _,
4243 rnlo: _,
4244 rnhi: _,
4245 rmlo: _,
4246 rmhi: _,
4247 } => {
4248 let mut bytes = Vec::new();
4249
4250 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4252 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4253
4254 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4257 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4258
4259 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());
4272
4273 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());
4283
4284 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4287 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4288 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4290 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4291 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4293 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4294
4295 let loop_start = bytes.len();
4296
4297 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4301 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());
4307 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4310
4311 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4315 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());
4328 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4330
4331 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4334
4335 let branch_offset_bytes = bytes.len() - loop_start + 4;
4336 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4337 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4338 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4339
4340 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());
4347 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());
4355
4356 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4358 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4359
4360 Ok(bytes)
4361 }
4362
4363 ArmOp::I64RemU {
4368 rdlo: _,
4369 rdhi: _,
4370 rnlo: _,
4371 rnhi: _,
4372 rmlo: _,
4373 rmhi: _,
4374 } => {
4375 let mut bytes = Vec::new();
4376
4377 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4379 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4380
4381 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4383 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4384 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4386 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4387 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4389 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4390
4391 let loop_start = bytes.len();
4392
4393 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4397 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());
4403 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4406
4407 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4411 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());
4424 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4426
4427 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4430
4431 let branch_offset_bytes = bytes.len() - loop_start + 4;
4432 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4433 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4434 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4435
4436 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4442 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4443
4444 Ok(bytes)
4445 }
4446
4447 ArmOp::I64RemS {
4452 rdlo: _,
4453 rdhi: _,
4454 rnlo: _,
4455 rnhi: _,
4456 rmlo: _,
4457 rmhi: _,
4458 } => {
4459 let mut bytes = Vec::new();
4460
4461 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4463 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4464
4465 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());
4479
4480 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());
4490
4491 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4494 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4495 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4497 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4498 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4500 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4501
4502 let loop_start = bytes.len();
4503
4504 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4508 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());
4514 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4517
4518 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4522 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());
4535 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4537
4538 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4541
4542 let branch_offset_bytes = bytes.len() - loop_start + 4;
4543 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4544 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4545 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4546
4547 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());
4554 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());
4562
4563 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4565 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4566
4567 Ok(bytes)
4568 }
4569
4570 ArmOp::F32Add { sd, sn, sm } => {
4573 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4574 }
4575 ArmOp::F32Sub { sd, sn, sm } => {
4576 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4577 }
4578 ArmOp::F32Mul { sd, sn, sm } => {
4579 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4580 }
4581 ArmOp::F32Div { sd, sn, sm } => {
4582 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4583 }
4584 ArmOp::F32Abs { sd, sm } => {
4585 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4586 }
4587 ArmOp::F32Neg { sd, sm } => {
4588 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4589 }
4590 ArmOp::F32Sqrt { sd, sm } => {
4591 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4592 }
4593
4594 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4597 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4598 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4599 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4600 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4601 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4602 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4603
4604 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4606 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4607 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4608 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4609 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4610 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4611
4612 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4613
4614 ArmOp::F32Load { sd, addr } => {
4615 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4616 }
4617 ArmOp::F32Store { sd, addr } => {
4618 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4619 }
4620
4621 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4622 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4623 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4624 Err(synth_core::Error::synthesis(
4625 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4626 ))
4627 }
4628 ArmOp::F32ReinterpretI32 { sd, rm } => {
4629 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4630 }
4631 ArmOp::I32ReinterpretF32 { rd, sm } => {
4632 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4633 }
4634 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4635 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4636
4637 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4640 0xEE300B00, dd, dn, dm,
4641 )?)),
4642 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4643 0xEE300B40, dd, dn, dm,
4644 )?)),
4645 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4646 0xEE200B00, dd, dn, dm,
4647 )?)),
4648 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4649 0xEE800B00, dd, dn, dm,
4650 )?)),
4651 ArmOp::F64Abs { dd, dm } => {
4652 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4653 }
4654 ArmOp::F64Neg { dd, dm } => {
4655 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4656 }
4657 ArmOp::F64Sqrt { dd, dm } => {
4658 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4659 }
4660
4661 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4664 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4665 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4666 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4667 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4668 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4669 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4670
4671 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4673 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4674 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4675 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4676 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4677 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4678
4679 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4680
4681 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4682 0xED900B00, dd, addr,
4683 )?)),
4684 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4685 0xED800B00, dd, addr,
4686 )?)),
4687
4688 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4689 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4690 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4691 Err(synth_core::Error::synthesis(
4692 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4693 ))
4694 }
4695 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4696 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4697 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4698 )),
4699 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4700 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4701 )),
4702 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4703 Err(synth_core::Error::synthesis(
4704 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4705 ))
4706 }
4707 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4708 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4709
4710 ArmOp::I64Add {
4714 rdlo,
4715 rdhi,
4716 rnlo,
4717 rnhi,
4718 rmlo,
4719 rmhi,
4720 } => {
4721 let mut bytes = Vec::new();
4722 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4724 rd: *rdlo,
4725 rn: *rnlo,
4726 op2: Operand2::Reg(*rmlo),
4727 })?);
4728 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4730 rd: *rdhi,
4731 rn: *rnhi,
4732 op2: Operand2::Reg(*rmhi),
4733 })?);
4734 Ok(bytes)
4735 }
4736
4737 ArmOp::I64Sub {
4739 rdlo,
4740 rdhi,
4741 rnlo,
4742 rnhi,
4743 rmlo,
4744 rmhi,
4745 } => {
4746 let mut bytes = Vec::new();
4747 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4749 rd: *rdlo,
4750 rn: *rnlo,
4751 op2: Operand2::Reg(*rmlo),
4752 })?);
4753 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4755 rd: *rdhi,
4756 rn: *rnhi,
4757 op2: Operand2::Reg(*rmhi),
4758 })?);
4759 Ok(bytes)
4760 }
4761
4762 ArmOp::I64And {
4764 rdlo,
4765 rdhi,
4766 rnlo,
4767 rnhi,
4768 rmlo,
4769 rmhi,
4770 } => {
4771 let mut bytes = Vec::new();
4772 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4773 rd: *rdlo,
4774 rn: *rnlo,
4775 op2: Operand2::Reg(*rmlo),
4776 })?);
4777 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4778 rd: *rdhi,
4779 rn: *rnhi,
4780 op2: Operand2::Reg(*rmhi),
4781 })?);
4782 Ok(bytes)
4783 }
4784
4785 ArmOp::I64Or {
4787 rdlo,
4788 rdhi,
4789 rnlo,
4790 rnhi,
4791 rmlo,
4792 rmhi,
4793 } => {
4794 let mut bytes = Vec::new();
4795 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4796 rd: *rdlo,
4797 rn: *rnlo,
4798 op2: Operand2::Reg(*rmlo),
4799 })?);
4800 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4801 rd: *rdhi,
4802 rn: *rnhi,
4803 op2: Operand2::Reg(*rmhi),
4804 })?);
4805 Ok(bytes)
4806 }
4807
4808 ArmOp::I64Xor {
4810 rdlo,
4811 rdhi,
4812 rnlo,
4813 rnhi,
4814 rmlo,
4815 rmhi,
4816 } => {
4817 let mut bytes = Vec::new();
4818 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4819 rd: *rdlo,
4820 rn: *rnlo,
4821 op2: Operand2::Reg(*rmlo),
4822 })?);
4823 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4824 rd: *rdhi,
4825 rn: *rnhi,
4826 op2: Operand2::Reg(*rmhi),
4827 })?);
4828 Ok(bytes)
4829 }
4830
4831 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4833 rd: *rd,
4834 rn_lo: *rnlo,
4835 rn_hi: *rnhi,
4836 }),
4837
4838 ArmOp::I64Eq {
4840 rd,
4841 rnlo,
4842 rnhi,
4843 rmlo,
4844 rmhi,
4845 } => self.encode_thumb(&ArmOp::I64SetCond {
4846 rd: *rd,
4847 rn_lo: *rnlo,
4848 rn_hi: *rnhi,
4849 rm_lo: *rmlo,
4850 rm_hi: *rmhi,
4851 cond: synth_synthesis::Condition::EQ,
4852 }),
4853
4854 ArmOp::I64Ne {
4855 rd,
4856 rnlo,
4857 rnhi,
4858 rmlo,
4859 rmhi,
4860 } => self.encode_thumb(&ArmOp::I64SetCond {
4861 rd: *rd,
4862 rn_lo: *rnlo,
4863 rn_hi: *rnhi,
4864 rm_lo: *rmlo,
4865 rm_hi: *rmhi,
4866 cond: synth_synthesis::Condition::NE,
4867 }),
4868
4869 ArmOp::I64LtS {
4870 rd,
4871 rnlo,
4872 rnhi,
4873 rmlo,
4874 rmhi,
4875 } => self.encode_thumb(&ArmOp::I64SetCond {
4876 rd: *rd,
4877 rn_lo: *rnlo,
4878 rn_hi: *rnhi,
4879 rm_lo: *rmlo,
4880 rm_hi: *rmhi,
4881 cond: synth_synthesis::Condition::LT,
4882 }),
4883
4884 ArmOp::I64LtU {
4885 rd,
4886 rnlo,
4887 rnhi,
4888 rmlo,
4889 rmhi,
4890 } => self.encode_thumb(&ArmOp::I64SetCond {
4891 rd: *rd,
4892 rn_lo: *rnlo,
4893 rn_hi: *rnhi,
4894 rm_lo: *rmlo,
4895 rm_hi: *rmhi,
4896 cond: synth_synthesis::Condition::LO,
4897 }),
4898
4899 ArmOp::I64LeS {
4900 rd,
4901 rnlo,
4902 rnhi,
4903 rmlo,
4904 rmhi,
4905 } => self.encode_thumb(&ArmOp::I64SetCond {
4906 rd: *rd,
4907 rn_lo: *rnlo,
4908 rn_hi: *rnhi,
4909 rm_lo: *rmlo,
4910 rm_hi: *rmhi,
4911 cond: synth_synthesis::Condition::LE,
4912 }),
4913
4914 ArmOp::I64LeU {
4915 rd,
4916 rnlo,
4917 rnhi,
4918 rmlo,
4919 rmhi,
4920 } => self.encode_thumb(&ArmOp::I64SetCond {
4921 rd: *rd,
4922 rn_lo: *rnlo,
4923 rn_hi: *rnhi,
4924 rm_lo: *rmlo,
4925 rm_hi: *rmhi,
4926 cond: synth_synthesis::Condition::LS,
4927 }),
4928
4929 ArmOp::I64GtS {
4930 rd,
4931 rnlo,
4932 rnhi,
4933 rmlo,
4934 rmhi,
4935 } => self.encode_thumb(&ArmOp::I64SetCond {
4936 rd: *rd,
4937 rn_lo: *rnlo,
4938 rn_hi: *rnhi,
4939 rm_lo: *rmlo,
4940 rm_hi: *rmhi,
4941 cond: synth_synthesis::Condition::GT,
4942 }),
4943
4944 ArmOp::I64GtU {
4945 rd,
4946 rnlo,
4947 rnhi,
4948 rmlo,
4949 rmhi,
4950 } => self.encode_thumb(&ArmOp::I64SetCond {
4951 rd: *rd,
4952 rn_lo: *rnlo,
4953 rn_hi: *rnhi,
4954 rm_lo: *rmlo,
4955 rm_hi: *rmhi,
4956 cond: synth_synthesis::Condition::HI,
4957 }),
4958
4959 ArmOp::I64GeS {
4960 rd,
4961 rnlo,
4962 rnhi,
4963 rmlo,
4964 rmhi,
4965 } => self.encode_thumb(&ArmOp::I64SetCond {
4966 rd: *rd,
4967 rn_lo: *rnlo,
4968 rn_hi: *rnhi,
4969 rm_lo: *rmlo,
4970 rm_hi: *rmhi,
4971 cond: synth_synthesis::Condition::GE,
4972 }),
4973
4974 ArmOp::I64GeU {
4975 rd,
4976 rnlo,
4977 rnhi,
4978 rmlo,
4979 rmhi,
4980 } => self.encode_thumb(&ArmOp::I64SetCond {
4981 rd: *rd,
4982 rn_lo: *rnlo,
4983 rn_hi: *rnhi,
4984 rm_lo: *rmlo,
4985 rm_hi: *rmhi,
4986 cond: synth_synthesis::Condition::HS,
4987 }),
4988
4989 ArmOp::I64Const { rdlo, rdhi, value } => {
4991 let lo32 = *value as u32;
4992 let hi32 = (*value >> 32) as u32;
4993 let mut bytes = Vec::new();
4994 bytes.extend_from_slice(
4996 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
4997 );
4998 if lo32 > 0xFFFF {
4999 bytes.extend_from_slice(
5000 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5001 );
5002 }
5003 bytes.extend_from_slice(
5005 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5006 );
5007 if hi32 > 0xFFFF {
5008 bytes.extend_from_slice(
5009 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5010 );
5011 }
5012 Ok(bytes)
5013 }
5014
5015 ArmOp::I64Ldr { 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_ldr(rdlo, &addr.base, offset)?);
5024 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5025 rdhi,
5026 &addr.base,
5027 offset.wrapping_add(4),
5028 )?);
5029 Ok(bytes)
5030 }
5031
5032 ArmOp::I64Str { rdlo, rdhi, addr } => {
5034 let mut bytes = Vec::new();
5035 let offset = if addr.offset < 0 {
5036 0u32
5037 } else {
5038 addr.offset as u32
5039 };
5040 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5041 bytes.extend_from_slice(&self.encode_thumb32_str(
5042 rdhi,
5043 &addr.base,
5044 offset.wrapping_add(4),
5045 )?);
5046 Ok(bytes)
5047 }
5048
5049 ArmOp::I64ExtendI32S { 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 bytes.extend_from_slice(
5061 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5063 Ok(bytes)
5064 }
5065
5066 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5068 let mut bytes = Vec::new();
5069 if rdlo != rn {
5070 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5072 rd: *rdlo,
5073 op2: Operand2::Reg(*rn),
5074 })?);
5075 }
5076 let rdhi_bits = reg_to_bits(rdhi) as u16;
5078 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5079 bytes.extend_from_slice(&instr.to_le_bytes());
5080 Ok(bytes)
5081 }
5082
5083 ArmOp::I32WrapI64 { rd, rnlo } => {
5085 if rd == rnlo {
5086 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5089 } else {
5090 self.encode_thumb(&ArmOp::Mov {
5092 rd: *rd,
5093 op2: Operand2::Reg(*rnlo),
5094 })
5095 }
5096 }
5097
5098 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5100 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5101 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5102 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5103 0xEF000150, qd, qn, qm,
5104 ))),
5105 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5106 0xEF200150, qd, qn, qm,
5107 ))),
5108 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5109 0xFF000150, qd, qn, qm,
5110 ))),
5111 ArmOp::MveMvn { qd, qm } => {
5112 let qd_enc = qreg_to_num(qd);
5114 let qm_enc = qreg_to_num(qm);
5115 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5116 Ok(vfp_to_thumb_bytes(instr))
5117 }
5118 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5119 0xEF100150, qd, qn, qm,
5120 ))),
5121 ArmOp::MveAddI { qd, qn, qm, size } => {
5122 let sz = mve_size_bits(size);
5123 let base: u32 = 0xEF000840 | (sz << 20);
5124 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5125 }
5126 ArmOp::MveSubI { qd, qn, qm, size } => {
5127 let sz = mve_size_bits(size);
5128 let base: u32 = 0xFF000840 | (sz << 20);
5129 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5130 }
5131 ArmOp::MveMulI { qd, qn, qm, size } => {
5132 let sz = mve_size_bits(size);
5133 let base: u32 = 0xEF000950 | (sz << 20);
5134 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5135 }
5136 ArmOp::MveNegI { qd, qm, size } => {
5137 let sz = mve_size_bits(size);
5138 let qd_enc = qreg_to_num(qd);
5140 let qm_enc = qreg_to_num(qm);
5141 let base: u32 = 0xFFB103C0 | (sz << 18);
5142 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5143 Ok(vfp_to_thumb_bytes(instr))
5144 }
5145 ArmOp::MveDup { qd, rn, size } => {
5146 let sz = mve_size_bits(size);
5147 let qd_enc = qreg_to_num(qd);
5148 let rn_bits = reg_to_bits(rn);
5149 let be = match sz {
5152 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5156 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5157 Ok(vfp_to_thumb_bytes(instr))
5158 }
5159 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5160 let qn_enc = qreg_to_num(qn);
5161 let rd_bits = reg_to_bits(rd);
5162 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5165 let lane_in_d = (*lane as u32) & 1;
5166 let _sz = mve_size_bits(size);
5167 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5169 Ok(vfp_to_thumb_bytes(instr))
5170 }
5171 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5172 let qd_enc = qreg_to_num(qd);
5173 let rn_bits = reg_to_bits(rn);
5174 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5175 let lane_in_d = (*lane as u32) & 1;
5176 let _sz = mve_size_bits(size);
5177 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5179 Ok(vfp_to_thumb_bytes(instr))
5180 }
5181
5182 ArmOp::MveCmpEqI { qd, qn, qm, size }
5184 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5185 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5186 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5187 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5188 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5189 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5190 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5191 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5192 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5193 let sz = mve_size_bits(size);
5196 let base: u32 = 0xEF000840 | (sz << 20);
5197 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5198 }
5199
5200 ArmOp::MveAddF32 { qd, qn, qm } => {
5202 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5204 }
5205 ArmOp::MveSubF32 { qd, qn, qm } => {
5206 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5208 }
5209 ArmOp::MveMulF32 { qd, qn, qm } => {
5210 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5212 }
5213 ArmOp::MveNegF32 { qd, qm } => {
5214 let qd_enc = qreg_to_num(qd);
5215 let qm_enc = qreg_to_num(qm);
5216 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5218 Ok(vfp_to_thumb_bytes(instr))
5219 }
5220 ArmOp::MveAbsF32 { qd, qm } => {
5221 let qd_enc = qreg_to_num(qd);
5222 let qm_enc = qreg_to_num(qm);
5223 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5225 Ok(vfp_to_thumb_bytes(instr))
5226 }
5227 ArmOp::MveCmpEqF32 { qd, qn, qm }
5228 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5229 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5230 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5231 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5232 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5233 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5235 }
5236 ArmOp::MveDupF32 { qd, rn } => {
5237 let qd_enc = qreg_to_num(qd);
5238 let rn_bits = reg_to_bits(rn);
5239 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5241 Ok(vfp_to_thumb_bytes(instr))
5242 }
5243 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5244 let qn_enc = qreg_to_num(qn);
5245 let rd_bits = reg_to_bits(rd);
5246 let s_num = qn_enc * 4 + (*lane as u32);
5248 let (vn, n) = encode_sreg(s_num);
5249 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5250 Ok(vfp_to_thumb_bytes(instr))
5251 }
5252 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5253 let qd_enc = qreg_to_num(qd);
5254 let rn_bits = reg_to_bits(rn);
5255 let s_num = qd_enc * 4 + (*lane as u32);
5257 let (vn, n) = encode_sreg(s_num);
5258 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5259 Ok(vfp_to_thumb_bytes(instr))
5260 }
5261 ArmOp::MveDivF32 { qd, qn, qm } => {
5262 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5264 }
5265 ArmOp::MveSqrtF32 { qd, qm } => {
5266 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5268 }
5269
5270 _ => {
5272 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5274 }
5275 }
5276 }
5277
5278 fn encode_thumb_f32_compare(
5282 &self,
5283 rd: &Reg,
5284 sn: &VfpReg,
5285 sm: &VfpReg,
5286 cond_code: u32,
5287 ) -> Result<Vec<u8>> {
5288 let mut bytes = Vec::new();
5289 let rd_bits = reg_to_bits(rd);
5290
5291 let sn_num = vfp_sreg_to_num(sn)?;
5293 let sm_num = vfp_sreg_to_num(sm)?;
5294 let (vd, d) = encode_sreg(sn_num);
5295 let (vm, m) = encode_sreg(sm_num);
5296 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5297 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5298
5299 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5301
5302 if rd_bits < 8 {
5304 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5305 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5306 } else {
5307 let hw1: u16 = 0xF04F;
5309 let hw2: u16 = (rd_bits as u16) << 8;
5310 bytes.extend_from_slice(&hw1.to_le_bytes());
5311 bytes.extend_from_slice(&hw2.to_le_bytes());
5312 }
5313
5314 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5318 bytes.extend_from_slice(&it.to_le_bytes());
5319
5320 if rd_bits < 8 {
5322 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5323 bytes.extend_from_slice(&mov_one.to_le_bytes());
5324 } else {
5325 let hw1: u16 = 0xF04F;
5327 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5328 bytes.extend_from_slice(&hw1.to_le_bytes());
5329 bytes.extend_from_slice(&hw2.to_le_bytes());
5330 }
5331
5332 Ok(bytes)
5333 }
5334
5335 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5337 let mut bytes = Vec::new();
5338 let bits = value.to_bits();
5339 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5344 let imm4 = (lo16 >> 12) & 0xF;
5345 let i_bit = (lo16 >> 11) & 1;
5346 let imm3 = (lo16 >> 8) & 0x7;
5347 let imm8 = lo16 & 0xFF;
5348 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5349 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5350 bytes.extend_from_slice(&hw1.to_le_bytes());
5351 bytes.extend_from_slice(&hw2.to_le_bytes());
5352
5353 let hi16 = (bits >> 16) & 0xFFFF;
5355 let imm4 = (hi16 >> 12) & 0xF;
5356 let i_bit = (hi16 >> 11) & 1;
5357 let imm3 = (hi16 >> 8) & 0x7;
5358 let imm8 = hi16 & 0xFF;
5359 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5360 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5361 bytes.extend_from_slice(&hw1.to_le_bytes());
5362 bytes.extend_from_slice(&hw2.to_le_bytes());
5363
5364 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5366 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5367
5368 Ok(bytes)
5369 }
5370
5371 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5373 let mut bytes = Vec::new();
5374
5375 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5377 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5378
5379 let sd_num = vfp_sreg_to_num(sd)?;
5381 let (vd, d) = encode_sreg(sd_num);
5382 let (vm, m) = encode_sreg(sd_num);
5383 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5384 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5385 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5386
5387 Ok(bytes)
5388 }
5389
5390 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5398 let mut bytes = Vec::new();
5399 let sm_num = vfp_sreg_to_num(sm)?;
5400 let sd_num = vfp_sreg_to_num(sd)?;
5401 let (vd_s, d_s) = encode_sreg(sd_num);
5402 let (vm_s, m_s) = encode_sreg(sm_num);
5403
5404 if mode == 0b11 {
5405 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5407 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5408 } else {
5409 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5414 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5415
5416 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5422 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5423 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5424
5425 if mode != 0 {
5427 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5429 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5430 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5431 }
5432
5433 let vmsr = 0xEEE10A10 | (rt << 12);
5435 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5436
5437 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5439 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5440
5441 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5443 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5444 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5445 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5446 }
5447
5448 let (vd2, d2) = encode_sreg(sd_num);
5450 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5451 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5452
5453 Ok(bytes)
5454 }
5455
5456 fn encode_thumb_f32_minmax(
5458 &self,
5459 sd: &VfpReg,
5460 sn: &VfpReg,
5461 sm: &VfpReg,
5462 is_min: bool,
5463 ) -> Result<Vec<u8>> {
5464 let mut bytes = Vec::new();
5465 let sn_num = vfp_sreg_to_num(sn)?;
5466 let sm_num = vfp_sreg_to_num(sm)?;
5467 let sd_num = vfp_sreg_to_num(sd)?;
5468
5469 let (vd, d) = encode_sreg(sd_num);
5471 let (vn, n) = encode_sreg(sn_num);
5472 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5473 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5474
5475 let (vm, m) = encode_sreg(sm_num);
5477 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5478 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5479
5480 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5482
5483 let cond: u16 = if is_min { 0xC } else { 0x4 };
5485 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5486 bytes.extend_from_slice(&it.to_le_bytes());
5487
5488 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5490 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5491
5492 Ok(bytes)
5493 }
5494
5495 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5497 let mut bytes = Vec::new();
5498
5499 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5501 false,
5502 sm,
5503 &Reg::R12,
5504 )?));
5505
5506 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5508 false,
5509 sn,
5510 &Reg::R0,
5511 )?));
5512
5513 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5525 bytes.extend_from_slice(&hw2.to_le_bytes());
5526
5527 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5531 bytes.extend_from_slice(&hw2.to_le_bytes());
5532
5533 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5537 bytes.extend_from_slice(&hw2.to_le_bytes());
5538
5539 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5541 true,
5542 sd,
5543 &Reg::R0,
5544 )?));
5545
5546 Ok(bytes)
5547 }
5548
5549 fn encode_thumb_f64_compare(
5551 &self,
5552 rd: &Reg,
5553 dn: &VfpReg,
5554 dm: &VfpReg,
5555 cond_code: u32,
5556 ) -> Result<Vec<u8>> {
5557 let mut bytes = Vec::new();
5558 let rd_bits = reg_to_bits(rd);
5559
5560 let dn_num = vfp_dreg_to_num(dn)?;
5562 let dm_num = vfp_dreg_to_num(dm)?;
5563 let (vd, d) = encode_dreg(dn_num);
5564 let (vm, m) = encode_dreg(dm_num);
5565 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5566 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5567
5568 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5570
5571 if rd_bits < 8 {
5573 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5574 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5575 } else {
5576 let hw1: u16 = 0xF04F;
5577 let hw2: u16 = (rd_bits as u16) << 8;
5578 bytes.extend_from_slice(&hw1.to_le_bytes());
5579 bytes.extend_from_slice(&hw2.to_le_bytes());
5580 }
5581
5582 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5584 bytes.extend_from_slice(&it.to_le_bytes());
5585
5586 if rd_bits < 8 {
5588 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5589 bytes.extend_from_slice(&mov_one.to_le_bytes());
5590 } else {
5591 let hw1: u16 = 0xF04F;
5592 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5593 bytes.extend_from_slice(&hw1.to_le_bytes());
5594 bytes.extend_from_slice(&hw2.to_le_bytes());
5595 }
5596
5597 Ok(bytes)
5598 }
5599
5600 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5602 let mut bytes = Vec::new();
5603 let bits = value.to_bits();
5604 let lo32 = bits as u32;
5605 let hi32 = (bits >> 32) as u32;
5606
5607 let lo16 = lo32 & 0xFFFF;
5609 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5610
5611 let hi16 = (lo32 >> 16) & 0xFFFF;
5613 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5614
5615 let lo16 = hi32 & 0xFFFF;
5617 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5618
5619 let hi16 = (hi32 >> 16) & 0xFFFF;
5621 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5622
5623 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5625 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5626
5627 Ok(bytes)
5628 }
5629
5630 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5632 let mut bytes = Vec::new();
5633
5634 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5636 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5637
5638 let dd_num = vfp_dreg_to_num(dd)?;
5640 let (vd, d) = encode_dreg(dd_num);
5641 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5642 let vcvt = base | (d << 22) | (vd << 12);
5643 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5644
5645 Ok(bytes)
5646 }
5647
5648 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5650 let dd_num = vfp_dreg_to_num(dd)?;
5651 let sm_num = vfp_sreg_to_num(sm)?;
5652 let (vd, d) = encode_dreg(dd_num);
5653 let (vm, m) = encode_sreg(sm_num);
5654
5655 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5656 Ok(vfp_to_thumb_bytes(vcvt))
5657 }
5658
5659 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5661 let mut bytes = Vec::new();
5662 let dm_num = vfp_dreg_to_num(dm)?;
5663 let (vm, m) = encode_dreg(dm_num);
5664
5665 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5667 let vcvt = base | (m << 5) | vm;
5668 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5669
5670 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5672 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5673
5674 Ok(bytes)
5675 }
5676
5677 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5681 let mut bytes = Vec::new();
5682 let dm_num = vfp_dreg_to_num(dm)?;
5683 let dd_num = vfp_dreg_to_num(dd)?;
5684 let (vm, m) = encode_dreg(dm_num);
5685 let (vd, d) = encode_dreg(dd_num);
5686
5687 if mode == 0b11 {
5688 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5690 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5691 } else {
5692 let rt: u32 = 12;
5693
5694 let vmrs = 0xEEF10A10 | (rt << 12);
5696 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5697
5698 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5700 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5701 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5702 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5703
5704 if mode != 0 {
5706 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5707 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5708 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5709 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5710 }
5711
5712 let vmsr = 0xEEE10A10 | (rt << 12);
5714 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5715
5716 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5718 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5719
5720 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5722 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5723 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5724 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5725 }
5726
5727 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5729 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5730
5731 Ok(bytes)
5732 }
5733
5734 fn encode_thumb_f64_minmax(
5736 &self,
5737 dd: &VfpReg,
5738 dn: &VfpReg,
5739 dm: &VfpReg,
5740 is_min: bool,
5741 ) -> Result<Vec<u8>> {
5742 let mut bytes = Vec::new();
5743 let dn_num = vfp_dreg_to_num(dn)?;
5744 let dm_num = vfp_dreg_to_num(dm)?;
5745 let dd_num = vfp_dreg_to_num(dd)?;
5746
5747 let (vd, d) = encode_dreg(dd_num);
5749 let (vn, n) = encode_dreg(dn_num);
5750 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5751 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5752
5753 let (vm, m) = encode_dreg(dm_num);
5755 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5756 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5757
5758 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5760
5761 let cond: u16 = if is_min { 0xC } else { 0x4 };
5763 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5764 bytes.extend_from_slice(&it.to_le_bytes());
5765
5766 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5768 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5769
5770 Ok(bytes)
5771 }
5772
5773 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5775 let mut bytes = Vec::new();
5776
5777 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5779 false,
5780 dm,
5781 &Reg::R0,
5782 &Reg::R12,
5783 )?));
5784
5785 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5787 false,
5788 dn,
5789 &Reg::R1,
5790 &Reg::R2,
5791 )?));
5792
5793 let hw1: u16 = 0xF000 | 12;
5795 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5796 bytes.extend_from_slice(&hw1.to_le_bytes());
5797 bytes.extend_from_slice(&hw2.to_le_bytes());
5798
5799 let hw1: u16 = 0xF020 | 2;
5801 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5802 bytes.extend_from_slice(&hw1.to_le_bytes());
5803 bytes.extend_from_slice(&hw2.to_le_bytes());
5804
5805 let hw1: u16 = 0xEA40 | 2;
5807 let hw2: u16 = (2 << 8) | 12;
5808 bytes.extend_from_slice(&hw1.to_le_bytes());
5809 bytes.extend_from_slice(&hw2.to_le_bytes());
5810
5811 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5813 true,
5814 dd,
5815 &Reg::R1,
5816 &Reg::R2,
5817 )?));
5818
5819 Ok(bytes)
5820 }
5821
5822 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5824 let mut bytes = Vec::new();
5825
5826 let sm_num = vfp_sreg_to_num(sm)?;
5827 let (vd, d) = encode_sreg(sm_num);
5828 let (vm, m) = encode_sreg(sm_num);
5829 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5830 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5831 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5832
5833 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5835 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5836
5837 Ok(bytes)
5838 }
5839
5840 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5844 let rd_bits = reg_to_bits(rd);
5845 let rn_bits = reg_to_bits(rn);
5846
5847 let i_bit = (imm >> 11) & 1;
5851 let imm3 = (imm >> 8) & 0x7;
5852 let imm8 = imm & 0xFF;
5853
5854 let hw1: u16 = (0xF100 | (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_sub(&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 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5872 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5873
5874 let mut bytes = hw1.to_le_bytes().to_vec();
5875 bytes.extend_from_slice(&hw2.to_le_bytes());
5876 Ok(bytes)
5877 }
5878
5879 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5881 let rd_bits = reg_to_bits(rd);
5882 let rn_bits = reg_to_bits(rn);
5883
5884 let i_bit = (imm >> 11) & 1;
5885 let imm3 = (imm >> 8) & 0x7;
5886 let imm8 = imm & 0xFF;
5887
5888 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5891 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5892
5893 let mut bytes = hw1.to_le_bytes().to_vec();
5894 bytes.extend_from_slice(&hw2.to_le_bytes());
5895 Ok(bytes)
5896 }
5897
5898 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5900 let rd_bits = reg_to_bits(rd);
5901 let rn_bits = reg_to_bits(rn);
5902
5903 let i_bit = (imm >> 11) & 1;
5904 let imm3 = (imm >> 8) & 0x7;
5905 let imm8 = imm & 0xFF;
5906
5907 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5910 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5911
5912 let mut bytes = hw1.to_le_bytes().to_vec();
5913 bytes.extend_from_slice(&hw2.to_le_bytes());
5914 Ok(bytes)
5915 }
5916
5917 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
5926 let rd_bits = reg_to_bits(rd);
5927 reg_bits_checked(rd_bits)?;
5928 let imm16 = imm & 0xFFFF;
5929
5930 let imm4 = (imm16 >> 12) & 0xF;
5933 let i_bit = (imm16 >> 11) & 1;
5934 let imm3 = (imm16 >> 8) & 0x7;
5935 let imm8 = imm16 & 0xFF;
5936
5937 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5938 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5939
5940 let mut bytes = hw1.to_le_bytes().to_vec();
5941 bytes.extend_from_slice(&hw2.to_le_bytes());
5942 encoding_contracts::verify_thumb32(&bytes);
5943 Ok(bytes)
5944 }
5945
5946 fn encode_thumb32_shift(
5954 &self,
5955 rd: &Reg,
5956 rm: &Reg,
5957 shift: u32,
5958 shift_type: u8,
5959 ) -> Result<Vec<u8>> {
5960 let rd_bits = reg_to_bits(rd);
5961 let rm_bits = reg_to_bits(rm);
5962 reg_bits_checked(rd_bits)?;
5963 reg_bits_checked(rm_bits)?;
5964 let imm5 = shift & 0x1F;
5965 let imm2 = imm5 & 0x3;
5966 let imm3 = (imm5 >> 2) & 0x7;
5967
5968 let hw1: u16 = 0xEA4F;
5971 let hw2: u16 =
5972 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
5973 as u16;
5974
5975 let mut bytes = hw1.to_le_bytes().to_vec();
5976 bytes.extend_from_slice(&hw2.to_le_bytes());
5977 Ok(bytes)
5978 }
5979
5980 fn encode_thumb32_shift_reg(
5984 &self,
5985 rd: &Reg,
5986 rn: &Reg,
5987 rm: &Reg,
5988 shift_type: u8,
5989 ) -> Result<Vec<u8>> {
5990 let rd_bits = reg_to_bits(rd);
5991 let rn_bits = reg_to_bits(rn);
5992 let rm_bits = reg_to_bits(rm);
5993
5994 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
5996 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) 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_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6006 let rn_bits = reg_to_bits(rn);
6007
6008 let i_bit = (imm >> 11) & 1;
6009 let imm3 = (imm >> 8) & 0x7;
6010 let imm8 = imm & 0xFF;
6011
6012 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6014 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6015
6016 let mut bytes = hw1.to_le_bytes().to_vec();
6017 bytes.extend_from_slice(&hw2.to_le_bytes());
6018 Ok(bytes)
6019 }
6020
6021 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6023 let rd_bits = reg_to_bits(rd);
6024 let base_bits = reg_to_bits(base);
6025
6026 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6028 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6029
6030 let mut bytes = hw1.to_le_bytes().to_vec();
6031 bytes.extend_from_slice(&hw2.to_le_bytes());
6032 Ok(bytes)
6033 }
6034
6035 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6037 let rd_bits = reg_to_bits(rd);
6038 let base_bits = reg_to_bits(base);
6039
6040 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6042 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) 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_ldr_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 = (0xF850 | 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_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6068 let rd_bits = reg_to_bits(rd);
6069 let base_bits = reg_to_bits(base);
6070 let rm_bits = reg_to_bits(offset_reg);
6071
6072 let hw1: u16 = (0xF840 | base_bits) as u16;
6076 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6077
6078 let mut bytes = hw1.to_le_bytes().to_vec();
6079 bytes.extend_from_slice(&hw2.to_le_bytes());
6080 Ok(bytes)
6081 }
6082
6083 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6087 let rd_bits = reg_to_bits(rd);
6088 let base_bits = reg_to_bits(base);
6089 let hw1: u16 = (0xF890 | base_bits) as u16;
6091 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6092 let mut bytes = hw1.to_le_bytes().to_vec();
6093 bytes.extend_from_slice(&hw2.to_le_bytes());
6094 Ok(bytes)
6095 }
6096
6097 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6099 let rd_bits = reg_to_bits(rd);
6100 let base_bits = reg_to_bits(base);
6101 let rm_bits = reg_to_bits(offset_reg);
6102 let hw1: u16 = (0xF810 | base_bits) as u16;
6104 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6105 let mut bytes = hw1.to_le_bytes().to_vec();
6106 bytes.extend_from_slice(&hw2.to_le_bytes());
6107 Ok(bytes)
6108 }
6109
6110 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6112 let rd_bits = reg_to_bits(rd);
6113 let base_bits = reg_to_bits(base);
6114 let hw1: u16 = (0xF990 | base_bits) as u16;
6116 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6117 let mut bytes = hw1.to_le_bytes().to_vec();
6118 bytes.extend_from_slice(&hw2.to_le_bytes());
6119 Ok(bytes)
6120 }
6121
6122 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6124 let rd_bits = reg_to_bits(rd);
6125 let base_bits = reg_to_bits(base);
6126 let rm_bits = reg_to_bits(offset_reg);
6127 let hw1: u16 = (0xF910 | base_bits) as u16;
6129 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6130 let mut bytes = hw1.to_le_bytes().to_vec();
6131 bytes.extend_from_slice(&hw2.to_le_bytes());
6132 Ok(bytes)
6133 }
6134
6135 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6137 let rd_bits = reg_to_bits(rd);
6138 let base_bits = reg_to_bits(base);
6139 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6141 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6142 let mut bytes = hw1.to_le_bytes().to_vec();
6143 bytes.extend_from_slice(&hw2.to_le_bytes());
6144 Ok(bytes)
6145 }
6146
6147 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6149 let rd_bits = reg_to_bits(rd);
6150 let base_bits = reg_to_bits(base);
6151 let rm_bits = reg_to_bits(offset_reg);
6152 let hw1: u16 = (0xF830 | base_bits) as u16;
6154 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6155 let mut bytes = hw1.to_le_bytes().to_vec();
6156 bytes.extend_from_slice(&hw2.to_le_bytes());
6157 Ok(bytes)
6158 }
6159
6160 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6162 let rd_bits = reg_to_bits(rd);
6163 let base_bits = reg_to_bits(base);
6164 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6166 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6167 let mut bytes = hw1.to_le_bytes().to_vec();
6168 bytes.extend_from_slice(&hw2.to_le_bytes());
6169 Ok(bytes)
6170 }
6171
6172 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6174 let rd_bits = reg_to_bits(rd);
6175 let base_bits = reg_to_bits(base);
6176 let rm_bits = reg_to_bits(offset_reg);
6177 let hw1: u16 = (0xF930 | base_bits) as u16;
6179 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6180 let mut bytes = hw1.to_le_bytes().to_vec();
6181 bytes.extend_from_slice(&hw2.to_le_bytes());
6182 Ok(bytes)
6183 }
6184
6185 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6187 let rd_bits = reg_to_bits(rd);
6188 let base_bits = reg_to_bits(base);
6189 let hw1: u16 = (0xF880 | base_bits) as u16;
6191 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6192 let mut bytes = hw1.to_le_bytes().to_vec();
6193 bytes.extend_from_slice(&hw2.to_le_bytes());
6194 Ok(bytes)
6195 }
6196
6197 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6199 let rd_bits = reg_to_bits(rd);
6200 let base_bits = reg_to_bits(base);
6201 let rm_bits = reg_to_bits(offset_reg);
6202 let hw1: u16 = (0xF800 | base_bits) as u16;
6204 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6205 let mut bytes = hw1.to_le_bytes().to_vec();
6206 bytes.extend_from_slice(&hw2.to_le_bytes());
6207 Ok(bytes)
6208 }
6209
6210 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6212 let rd_bits = reg_to_bits(rd);
6213 let base_bits = reg_to_bits(base);
6214 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6216 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6217 let mut bytes = hw1.to_le_bytes().to_vec();
6218 bytes.extend_from_slice(&hw2.to_le_bytes());
6219 Ok(bytes)
6220 }
6221
6222 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6224 let rd_bits = reg_to_bits(rd);
6225 let base_bits = reg_to_bits(base);
6226 let rm_bits = reg_to_bits(offset_reg);
6227 let hw1: u16 = (0xF820 | base_bits) as u16;
6229 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6230 let mut bytes = hw1.to_le_bytes().to_vec();
6231 bytes.extend_from_slice(&hw2.to_le_bytes());
6232 Ok(bytes)
6233 }
6234
6235 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6237 let rd_bits = reg_to_bits(rd);
6238 let rn_bits = reg_to_bits(rn);
6239
6240 if imm <= 0xFFF {
6246 let i_bit = (imm >> 11) & 1;
6247 let imm3 = (imm >> 8) & 0x7;
6248 let imm8 = imm & 0xFF;
6249
6250 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6251 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6252
6253 let mut bytes = hw1.to_le_bytes().to_vec();
6254 bytes.extend_from_slice(&hw2.to_le_bytes());
6255 Ok(bytes)
6256 } else {
6257 Err(synth_core::Error::synthesis(
6260 "ADD immediate too large for single instruction",
6261 ))
6262 }
6263 }
6264
6265 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6275 reg_bits_checked(rd)?;
6276 encoding_contracts::verify_imm16(imm16);
6277 let imm16 = imm16 & 0xFFFF;
6280 let imm4 = (imm16 >> 12) & 0xF;
6281 let i_bit = (imm16 >> 11) & 1;
6282 let imm3 = (imm16 >> 8) & 0x7;
6283 let imm8 = imm16 & 0xFF;
6284
6285 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6286 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6287
6288 let mut bytes = hw1.to_le_bytes().to_vec();
6289 bytes.extend_from_slice(&hw2.to_le_bytes());
6290 encoding_contracts::verify_thumb32(&bytes);
6291 Ok(bytes)
6292 }
6293
6294 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6302 reg_bits_checked(rd)?;
6303 encoding_contracts::verify_imm16(imm16);
6304 let imm16 = imm16 & 0xFFFF;
6307 let imm4 = (imm16 >> 12) & 0xF;
6308 let i_bit = (imm16 >> 11) & 1;
6309 let imm3 = (imm16 >> 8) & 0x7;
6310 let imm8 = imm16 & 0xFF;
6311
6312 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6313 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6314
6315 let mut bytes = hw1.to_le_bytes().to_vec();
6316 bytes.extend_from_slice(&hw2.to_le_bytes());
6317 encoding_contracts::verify_thumb32(&bytes);
6318 Ok(bytes)
6319 }
6320
6321 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6323 let imm5 = shift & 0x1F;
6326 let imm2 = imm5 & 0x3;
6327 let imm3 = (imm5 >> 2) & 0x7;
6328
6329 let hw1: u16 = 0xEA4F;
6330 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6331
6332 let mut bytes = hw1.to_le_bytes().to_vec();
6333 bytes.extend_from_slice(&hw2.to_le_bytes());
6334 Ok(bytes)
6335 }
6336
6337 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6339 let hw1: u16 = (0xEA00 | rn) as u16;
6342 let hw2: u16 = ((rd << 8) | rm) 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_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6351 let i_bit = (imm >> 11) & 1;
6355 let imm3 = (imm >> 8) & 0x7;
6356 let imm8 = imm & 0xFF;
6357
6358 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6359 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6360
6361 let mut bytes = hw1.to_le_bytes().to_vec();
6362 bytes.extend_from_slice(&hw2.to_le_bytes());
6363 Ok(bytes)
6364 }
6365
6366 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6368 let hw1: u16 = (0xEBA0 | rn) as u16;
6371 let hw2: u16 = ((rd << 8) | rm) as u16;
6372
6373 let mut bytes = hw1.to_le_bytes().to_vec();
6374 bytes.extend_from_slice(&hw2.to_le_bytes());
6375 Ok(bytes)
6376 }
6377
6378 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6380 let hw1: u16 = (0xEB00 | rn) as u16;
6383 let hw2: u16 = ((rd << 8) | rm) as u16;
6384
6385 let mut bytes = hw1.to_le_bytes().to_vec();
6386 bytes.extend_from_slice(&hw2.to_le_bytes());
6387 Ok(bytes)
6388 }
6389
6390 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6394 let hw1: u16 = (0xEB10 | rn) as u16;
6396 let hw2: u16 = ((rd << 8) | rm) as u16;
6397 let mut bytes = hw1.to_le_bytes().to_vec();
6398 bytes.extend_from_slice(&hw2.to_le_bytes());
6399 Ok(bytes)
6400 }
6401
6402 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6405 let hw1: u16 = (0xEBB0 | rn) as u16;
6407 let hw2: u16 = ((rd << 8) | rm) as u16;
6408 let mut bytes = hw1.to_le_bytes().to_vec();
6409 bytes.extend_from_slice(&hw2.to_le_bytes());
6410 Ok(bytes)
6411 }
6412
6413 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6415 let mut code = Vec::new();
6416
6417 for op in ops {
6418 let encoded = self.encode(op)?;
6419 code.extend_from_slice(&encoded);
6420 }
6421
6422 Ok(code)
6423 }
6424}
6425
6426fn reg_to_bits(reg: &Reg) -> u32 {
6428 match reg {
6429 Reg::R0 => 0,
6430 Reg::R1 => 1,
6431 Reg::R2 => 2,
6432 Reg::R3 => 3,
6433 Reg::R4 => 4,
6434 Reg::R5 => 5,
6435 Reg::R6 => 6,
6436 Reg::R7 => 7,
6437 Reg::R8 => 8,
6438 Reg::R9 => 9,
6439 Reg::R10 => 10,
6440 Reg::R11 => 11,
6441 Reg::R12 => 12,
6442 Reg::SP => 13,
6443 Reg::LR => 14,
6444 Reg::PC => 15,
6445 }
6446}
6447
6448fn reg_bits_checked(bits: u32) -> Result<()> {
6456 if bits > 14 {
6457 return Err(synth_core::Error::synthesis(format!(
6458 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6459 )));
6460 }
6461 Ok(())
6462}
6463
6464fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6467 if val == 0 {
6468 return Some((0, 1));
6469 }
6470 for rot in 0..16u32 {
6471 let shift = rot * 2;
6472 let unrotated = val.rotate_left(shift);
6474 if unrotated <= 0xFF {
6475 return Some(((rot << 8) | unrotated, 1));
6477 }
6478 }
6479 None
6480}
6481
6482fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6487 match op2 {
6488 Operand2::Imm(val) => {
6489 let uval = *val as u32;
6490 if let Some(encoded) = try_encode_rotated_imm(uval) {
6492 encoded
6493 } else {
6494 let imm = uval & 0xFF;
6499 (imm, 1)
6500 }
6501 }
6502
6503 Operand2::Reg(reg) => {
6504 let reg_bits = reg_to_bits(reg);
6505 (reg_bits, 0) }
6507
6508 Operand2::RegShift {
6509 rm,
6510 shift: _,
6511 amount,
6512 } => {
6513 let rm_bits = reg_to_bits(rm);
6515 let shift_bits = (*amount & 0x1F) << 7;
6516 (shift_bits | rm_bits, 0)
6517 }
6518 }
6519}
6520
6521fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6523 let base_bits = reg_to_bits(&addr.base);
6524 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6526}
6527
6528fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6530 match reg {
6531 VfpReg::S0 => Ok(0),
6532 VfpReg::S1 => Ok(1),
6533 VfpReg::S2 => Ok(2),
6534 VfpReg::S3 => Ok(3),
6535 VfpReg::S4 => Ok(4),
6536 VfpReg::S5 => Ok(5),
6537 VfpReg::S6 => Ok(6),
6538 VfpReg::S7 => Ok(7),
6539 VfpReg::S8 => Ok(8),
6540 VfpReg::S9 => Ok(9),
6541 VfpReg::S10 => Ok(10),
6542 VfpReg::S11 => Ok(11),
6543 VfpReg::S12 => Ok(12),
6544 VfpReg::S13 => Ok(13),
6545 VfpReg::S14 => Ok(14),
6546 VfpReg::S15 => Ok(15),
6547 VfpReg::S16 => Ok(16),
6548 VfpReg::S17 => Ok(17),
6549 VfpReg::S18 => Ok(18),
6550 VfpReg::S19 => Ok(19),
6551 VfpReg::S20 => Ok(20),
6552 VfpReg::S21 => Ok(21),
6553 VfpReg::S22 => Ok(22),
6554 VfpReg::S23 => Ok(23),
6555 VfpReg::S24 => Ok(24),
6556 VfpReg::S25 => Ok(25),
6557 VfpReg::S26 => Ok(26),
6558 VfpReg::S27 => Ok(27),
6559 VfpReg::S28 => Ok(28),
6560 VfpReg::S29 => Ok(29),
6561 VfpReg::S30 => Ok(30),
6562 VfpReg::S31 => Ok(31),
6563 _ => Err(synth_core::Error::SynthesisError(
6565 "D-register not supported in single-precision VFP encoding".to_string(),
6566 )),
6567 }
6568}
6569
6570fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6572 match reg {
6573 VfpReg::D0 => Ok(0),
6574 VfpReg::D1 => Ok(1),
6575 VfpReg::D2 => Ok(2),
6576 VfpReg::D3 => Ok(3),
6577 VfpReg::D4 => Ok(4),
6578 VfpReg::D5 => Ok(5),
6579 VfpReg::D6 => Ok(6),
6580 VfpReg::D7 => Ok(7),
6581 VfpReg::D8 => Ok(8),
6582 VfpReg::D9 => Ok(9),
6583 VfpReg::D10 => Ok(10),
6584 VfpReg::D11 => Ok(11),
6585 VfpReg::D12 => Ok(12),
6586 VfpReg::D13 => Ok(13),
6587 VfpReg::D14 => Ok(14),
6588 VfpReg::D15 => Ok(15),
6589 _ => Err(synth_core::Error::SynthesisError(
6591 "S-register not supported in double-precision VFP encoding".to_string(),
6592 )),
6593 }
6594}
6595
6596fn encode_sreg(s: u32) -> (u32, u32) {
6600 (s >> 1, s & 1)
6601}
6602
6603fn encode_dreg(d: u32) -> (u32, u32) {
6607 (d & 0xF, (d >> 4) & 1)
6608}
6609
6610fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6616 let sd_num = vfp_sreg_to_num(sd)?;
6617 let sn_num = vfp_sreg_to_num(sn)?;
6618 let sm_num = vfp_sreg_to_num(sm)?;
6619 let (vd, d) = encode_sreg(sd_num);
6620 let (vn, n) = encode_sreg(sn_num);
6621 let (vm, m) = encode_sreg(sm_num);
6622
6623 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6624}
6625
6626fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6629 let sd_num = vfp_sreg_to_num(sd)?;
6630 let sm_num = vfp_sreg_to_num(sm)?;
6631 let (vd, d) = encode_sreg(sd_num);
6632 let (vm, m) = encode_sreg(sm_num);
6633
6634 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6635}
6636
6637fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6641 let sd_num = vfp_sreg_to_num(sd)?;
6642 let (vd, d) = encode_sreg(sd_num);
6643 let rn = reg_to_bits(&addr.base);
6644
6645 let offset = addr.offset;
6646 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6647 let abs_offset = offset.unsigned_abs();
6648 let imm8 = (abs_offset / 4) & 0xFF;
6649
6650 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6651}
6652
6653fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6657 let s_num = vfp_sreg_to_num(sreg)?;
6658 let (vn, n) = encode_sreg(s_num);
6659 let rt = reg_to_bits(core);
6660
6661 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6662 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6663}
6664
6665fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6669 let dd_num = vfp_dreg_to_num(dd)?;
6670 let dn_num = vfp_dreg_to_num(dn)?;
6671 let dm_num = vfp_dreg_to_num(dm)?;
6672 let (vd, d) = encode_dreg(dd_num);
6673 let (vn, n) = encode_dreg(dn_num);
6674 let (vm, m) = encode_dreg(dm_num);
6675
6676 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6677}
6678
6679fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6681 let dd_num = vfp_dreg_to_num(dd)?;
6682 let dm_num = vfp_dreg_to_num(dm)?;
6683 let (vd, d) = encode_dreg(dd_num);
6684 let (vm, m) = encode_dreg(dm_num);
6685
6686 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6687}
6688
6689fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6692 let dd_num = vfp_dreg_to_num(dd)?;
6693 let (vd, d) = encode_dreg(dd_num);
6694 let rn = reg_to_bits(&addr.base);
6695
6696 let offset = addr.offset;
6697 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6698 let abs_offset = offset.unsigned_abs();
6699 let imm8 = (abs_offset / 4) & 0xFF;
6700
6701 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6702}
6703
6704fn encode_vmov_core_dreg(
6708 to_dreg: bool,
6709 dreg: &VfpReg,
6710 core_lo: &Reg,
6711 core_hi: &Reg,
6712) -> Result<u32> {
6713 let d_num = vfp_dreg_to_num(dreg)?;
6714 let (vm, m) = encode_dreg(d_num);
6715 let rt = reg_to_bits(core_lo);
6716 let rt2 = reg_to_bits(core_hi);
6717
6718 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6719 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6720}
6721
6722fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6724 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6725 let hw2 = (instr & 0xFFFF) as u16;
6726 let mut bytes = hw1.to_le_bytes().to_vec();
6727 bytes.extend_from_slice(&hw2.to_le_bytes());
6728 bytes
6729}
6730
6731fn qreg_to_num(reg: &QReg) -> u32 {
6737 match reg {
6738 QReg::Q0 => 0,
6739 QReg::Q1 => 1,
6740 QReg::Q2 => 2,
6741 QReg::Q3 => 3,
6742 QReg::Q4 => 4,
6743 QReg::Q5 => 5,
6744 QReg::Q6 => 6,
6745 QReg::Q7 => 7,
6746 }
6747}
6748
6749fn mve_size_bits(size: &MveSize) -> u32 {
6751 match size {
6752 MveSize::S8 => 0b00,
6753 MveSize::S16 => 0b01,
6754 MveSize::S32 => 0b10,
6755 }
6756}
6757
6758fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6762 let d = qreg_to_num(qd) * 2;
6763 let n = qreg_to_num(qn) * 2;
6764 let m = qreg_to_num(qm) * 2;
6765
6766 let vd = d & 0xF;
6771 let d_bit = (d >> 4) & 1;
6772 let vn = n & 0xF;
6773 let n_bit = (n >> 4) & 1;
6774 let vm = m & 0xF;
6775 let m_bit = (m >> 4) & 1;
6776
6777 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6778}
6779
6780fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6782 encode_mve_3reg(base, qd, qn, qm)
6783}
6784
6785fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6788 let qd_enc = qreg_to_num(qd) * 2;
6789 let rn = reg_to_bits(&addr.base);
6790 let offset = addr.offset;
6791 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6792 let abs_offset = offset.unsigned_abs();
6793 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6797 | (u_bit << 23)
6798 | ((qd_enc >> 4) << 22)
6799 | (rn << 16)
6800 | ((qd_enc & 0xF) << 12)
6801 | (imm7 & 0x7F)
6802}
6803
6804fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6806 let qd_enc = qreg_to_num(qd) * 2;
6807 let rn = reg_to_bits(&addr.base);
6808 let offset = addr.offset;
6809 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6810 let abs_offset = offset.unsigned_abs();
6811 let imm7 = (abs_offset / 4) & 0x7F;
6812
6813 0xED000E80
6814 | (u_bit << 23)
6815 | ((qd_enc >> 4) << 22)
6816 | (rn << 16)
6817 | ((qd_enc & 0xF) << 12)
6818 | (imm7 & 0x7F)
6819}
6820
6821impl ArmEncoder {
6822 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6824 let mut result = Vec::new();
6825 let qd_num = qreg_to_num(qd);
6826
6827 for i in 0..4 {
6829 let word = u32::from_le_bytes([
6830 bytes[i * 4],
6831 bytes[i * 4 + 1],
6832 bytes[i * 4 + 2],
6833 bytes[i * 4 + 3],
6834 ]);
6835 let lo16 = word & 0xFFFF;
6836 let hi16 = (word >> 16) & 0xFFFF;
6837
6838 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6840 if hi16 != 0 {
6842 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6843 }
6844
6845 let s_num = qd_num * 4 + i as u32;
6847 let (vn, n) = encode_sreg(s_num);
6848 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6849 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6850 }
6851
6852 Ok(result)
6853 }
6854
6855 fn encode_thumb_mve_lane_wise_f32_binop(
6857 &self,
6858 qd: &QReg,
6859 qn: &QReg,
6860 qm: &QReg,
6861 vfp_base: u32,
6862 ) -> Result<Vec<u8>> {
6863 let mut result = Vec::new();
6864 let qd_num = qreg_to_num(qd);
6865 let qn_num = qreg_to_num(qn);
6866 let qm_num = qreg_to_num(qm);
6867
6868 for i in 0..4u32 {
6870 let sd = qd_num * 4 + i;
6871 let sn = qn_num * 4 + i;
6872 let sm = qm_num * 4 + i;
6873
6874 let (vd, d) = encode_sreg(sd);
6875 let (vn, n) = encode_sreg(sn);
6876 let (vm, m) = encode_sreg(sm);
6877
6878 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6879 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6880 }
6881
6882 Ok(result)
6883 }
6884
6885 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6887 let mut result = Vec::new();
6888 let qd_num = qreg_to_num(qd);
6889 let qm_num = qreg_to_num(qm);
6890
6891 for i in 0..4u32 {
6893 let sd = qd_num * 4 + i;
6894 let sm = qm_num * 4 + i;
6895
6896 let (vd, d) = encode_sreg(sd);
6897 let (vm, m) = encode_sreg(sm);
6898
6899 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6900 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6901 }
6902
6903 Ok(result)
6904 }
6905}
6906
6907#[cfg(test)]
6908mod tests {
6909 use super::*;
6910
6911 #[test]
6912 fn test_encoder_creation() {
6913 let encoder_arm = ArmEncoder::new_arm32();
6914 assert!(!encoder_arm.thumb_mode);
6915
6916 let encoder_thumb = ArmEncoder::new_thumb2();
6917 assert!(encoder_thumb.thumb_mode);
6918 }
6919
6920 #[test]
6927 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
6928 let encoder = ArmEncoder::new_thumb2();
6929
6930 let code = encoder
6932 .encode(&ArmOp::Add {
6933 rd: Reg::R12,
6934 rn: Reg::R12,
6935 op2: Operand2::Reg(Reg::R0),
6936 })
6937 .unwrap();
6938 assert_eq!(
6940 code,
6941 vec![0x0C, 0xEB, 0x00, 0x0C],
6942 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
6943 );
6944 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
6946
6947 let lo = encoder
6949 .encode(&ArmOp::Add {
6950 rd: Reg::R1,
6951 rn: Reg::R2,
6952 op2: Operand2::Reg(Reg::R3),
6953 })
6954 .unwrap();
6955 assert_eq!(
6956 lo.len(),
6957 2,
6958 "low-reg ADD should remain 16-bit, got {lo:02X?}"
6959 );
6960 }
6961
6962 #[test]
6965 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
6966 let encoder = ArmEncoder::new_thumb2();
6967
6968 let adds = encoder
6970 .encode(&ArmOp::Adds {
6971 rd: Reg::R10,
6972 rn: Reg::R10,
6973 op2: Operand2::Reg(Reg::R8),
6974 })
6975 .unwrap();
6976 assert_eq!(
6977 adds,
6978 vec![0x1A, 0xEB, 0x08, 0x0A],
6979 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
6980 );
6981
6982 let subs = encoder
6984 .encode(&ArmOp::Subs {
6985 rd: Reg::R10,
6986 rn: Reg::R10,
6987 op2: Operand2::Reg(Reg::R8),
6988 })
6989 .unwrap();
6990 assert_eq!(
6991 subs,
6992 vec![0xBA, 0xEB, 0x08, 0x0A],
6993 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
6994 );
6995 }
6996
6997 #[test]
7000 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7001 let encoder = ArmEncoder::new_thumb2();
7002
7003 let cmn = encoder
7005 .encode(&ArmOp::Cmn {
7006 rn: Reg::R10,
7007 op2: Operand2::Reg(Reg::R8),
7008 })
7009 .unwrap();
7010 assert_eq!(
7011 cmn,
7012 vec![0x1A, 0xEB, 0x08, 0x0F],
7013 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7014 );
7015
7016 let lo = encoder
7018 .encode(&ArmOp::Cmn {
7019 rn: Reg::R1,
7020 op2: Operand2::Reg(Reg::R2),
7021 })
7022 .unwrap();
7023 assert_eq!(
7024 lo.len(),
7025 2,
7026 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7027 );
7028 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7029 }
7030
7031 #[test]
7035 fn test_encode_pc_operand_returns_err_not_panic_185() {
7036 let encoder = ArmEncoder::new_thumb2();
7037 for op in [
7038 ArmOp::Sdiv {
7039 rd: Reg::PC,
7040 rn: Reg::R0,
7041 rm: Reg::R1,
7042 },
7043 ArmOp::Udiv {
7044 rd: Reg::R0,
7045 rn: Reg::PC,
7046 rm: Reg::R1,
7047 },
7048 ArmOp::Sdiv {
7049 rd: Reg::R0,
7050 rn: Reg::R1,
7051 rm: Reg::PC,
7052 },
7053 ] {
7054 let r = encoder.encode(&op);
7055 assert!(
7056 r.is_err(),
7057 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7058 );
7059 }
7060 assert!(
7062 encoder
7063 .encode(&ArmOp::Sdiv {
7064 rd: Reg::R0,
7065 rn: Reg::R1,
7066 rm: Reg::R2
7067 })
7068 .is_ok()
7069 );
7070 }
7071
7072 #[test]
7073 fn test_encode_nop_arm32() {
7074 let encoder = ArmEncoder::new_arm32();
7075 let code = encoder.encode(&ArmOp::Nop).unwrap();
7076
7077 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7080
7081 #[test]
7082 fn test_encode_nop_thumb() {
7083 let encoder = ArmEncoder::new_thumb2();
7084 let code = encoder.encode(&ArmOp::Nop).unwrap();
7085
7086 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7089
7090 #[test]
7091 fn test_encode_mov_immediate_arm32() {
7092 let encoder = ArmEncoder::new_arm32();
7093 let op = ArmOp::Mov {
7094 rd: Reg::R0,
7095 op2: Operand2::Imm(42),
7096 };
7097
7098 let code = encoder.encode(&op).unwrap();
7099 assert_eq!(code.len(), 4);
7100
7101 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7103 assert_eq!(instr & 0x0E000000, 0x02000000); }
7105
7106 #[test]
7107 fn test_encode_add_registers_arm32() {
7108 let encoder = ArmEncoder::new_arm32();
7109 let op = ArmOp::Add {
7110 rd: Reg::R0,
7111 rn: Reg::R1,
7112 op2: Operand2::Reg(Reg::R2),
7113 };
7114
7115 let code = encoder.encode(&op).unwrap();
7116 assert_eq!(code.len(), 4);
7117
7118 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7119 assert_eq!(instr & 0x0FE00000, 0x00800000);
7121 }
7122
7123 #[test]
7124 fn test_encode_ldr_arm32() {
7125 let encoder = ArmEncoder::new_arm32();
7126 let op = ArmOp::Ldr {
7127 rd: Reg::R0,
7128 addr: MemAddr::imm(Reg::R1, 4),
7129 };
7130
7131 let code = encoder.encode(&op).unwrap();
7132 assert_eq!(code.len(), 4);
7133
7134 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7135 assert_eq!(instr & 0x00100000, 0x00100000);
7137 }
7138
7139 #[test]
7140 fn test_encode_str_arm32() {
7141 let encoder = ArmEncoder::new_arm32();
7142 let op = ArmOp::Str {
7143 rd: Reg::R0,
7144 addr: MemAddr::imm(Reg::SP, 0),
7145 };
7146
7147 let code = encoder.encode(&op).unwrap();
7148 assert_eq!(code.len(), 4);
7149 }
7150
7151 #[test]
7152 fn test_encode_branch_arm32() {
7153 let encoder = ArmEncoder::new_arm32();
7154 let op = ArmOp::Bl {
7155 label: "main".to_string(),
7156 };
7157
7158 let code = encoder.encode(&op).unwrap();
7159 assert_eq!(code.len(), 4);
7160
7161 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7162 assert_eq!(instr & 0x0F000000, 0x0B000000);
7164 }
7165
7166 #[test]
7176 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7177 let encoder = ArmEncoder::new_thumb2();
7178 let op = ArmOp::Bl {
7179 label: "callee".to_string(),
7180 };
7181
7182 let code = encoder.encode(&op).unwrap();
7183 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7184
7185 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7186 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7187 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7188 assert_eq!(
7189 hw2, 0xFFFE,
7190 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7191 );
7192 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7193 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7194 }
7195
7196 #[test]
7197 fn test_encode_sequence() {
7198 let encoder = ArmEncoder::new_arm32();
7199 let ops = vec![
7200 ArmOp::Mov {
7201 rd: Reg::R0,
7202 op2: Operand2::Imm(42),
7203 },
7204 ArmOp::Mov {
7205 rd: Reg::R1,
7206 op2: Operand2::Imm(10),
7207 },
7208 ArmOp::Add {
7209 rd: Reg::R2,
7210 rn: Reg::R0,
7211 op2: Operand2::Reg(Reg::R1),
7212 },
7213 ];
7214
7215 let code = encoder.encode_sequence(&ops).unwrap();
7216 assert_eq!(code.len(), 12); }
7218
7219 #[test]
7220 fn test_reg_to_bits() {
7221 assert_eq!(reg_to_bits(&Reg::R0), 0);
7222 assert_eq!(reg_to_bits(&Reg::R7), 7);
7223 assert_eq!(reg_to_bits(&Reg::SP), 13);
7224 assert_eq!(reg_to_bits(&Reg::LR), 14);
7225 assert_eq!(reg_to_bits(&Reg::PC), 15);
7226 }
7227
7228 #[test]
7229 fn test_encode_bitwise_operations() {
7230 let encoder = ArmEncoder::new_arm32();
7231
7232 let and_op = ArmOp::And {
7233 rd: Reg::R0,
7234 rn: Reg::R1,
7235 op2: Operand2::Reg(Reg::R2),
7236 };
7237 let and_code = encoder.encode(&and_op).unwrap();
7238 assert_eq!(and_code.len(), 4);
7239
7240 let orr_op = ArmOp::Orr {
7241 rd: Reg::R0,
7242 rn: Reg::R1,
7243 op2: Operand2::Reg(Reg::R2),
7244 };
7245 let orr_code = encoder.encode(&orr_op).unwrap();
7246 assert_eq!(orr_code.len(), 4);
7247
7248 let eor_op = ArmOp::Eor {
7249 rd: Reg::R0,
7250 rn: Reg::R1,
7251 op2: Operand2::Reg(Reg::R2),
7252 };
7253 let eor_code = encoder.encode(&eor_op).unwrap();
7254 assert_eq!(eor_code.len(), 4);
7255 }
7256
7257 #[test]
7260 fn test_encode_sdiv_thumb2() {
7261 let encoder = ArmEncoder::new_thumb2();
7262 let op = ArmOp::Sdiv {
7263 rd: Reg::R0,
7264 rn: Reg::R1,
7265 rm: Reg::R2,
7266 };
7267
7268 let code = encoder.encode(&op).unwrap();
7269 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7276 assert_eq!(code[1], 0xFB);
7277 assert_eq!(code[2], 0xF2);
7278 assert_eq!(code[3], 0xF0);
7279 }
7280
7281 #[test]
7282 fn test_encode_udiv_thumb2() {
7283 let encoder = ArmEncoder::new_thumb2();
7284 let op = ArmOp::Udiv {
7285 rd: Reg::R0,
7286 rn: Reg::R1,
7287 rm: Reg::R2,
7288 };
7289
7290 let code = encoder.encode(&op).unwrap();
7291 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7296 assert_eq!(code[1], 0xFB);
7297 assert_eq!(code[2], 0xF2);
7298 assert_eq!(code[3], 0xF0);
7299 }
7300
7301 #[test]
7302 fn test_encode_mul_thumb2() {
7303 let encoder = ArmEncoder::new_thumb2();
7304 let op = ArmOp::Mul {
7305 rd: Reg::R0,
7306 rn: Reg::R1,
7307 rm: Reg::R2,
7308 };
7309
7310 let code = encoder.encode(&op).unwrap();
7311 assert_eq!(code.len(), 4); }
7313
7314 #[test]
7315 fn test_encode_and_thumb2() {
7316 let encoder = ArmEncoder::new_thumb2();
7317 let op = ArmOp::And {
7318 rd: Reg::R0,
7319 rn: Reg::R1,
7320 op2: Operand2::Reg(Reg::R2),
7321 };
7322
7323 let code = encoder.encode(&op).unwrap();
7324 assert_eq!(code.len(), 4); }
7326
7327 #[test]
7328 fn test_encode_lsl_thumb2_low_regs() {
7329 let encoder = ArmEncoder::new_thumb2();
7330 let op = ArmOp::Lsl {
7331 rd: Reg::R0,
7332 rn: Reg::R1,
7333 shift: 5,
7334 };
7335
7336 let code = encoder.encode(&op).unwrap();
7337 assert_eq!(code.len(), 2); }
7339
7340 #[test]
7341 fn test_encode_clz_thumb2() {
7342 let encoder = ArmEncoder::new_thumb2();
7343 let op = ArmOp::Clz {
7344 rd: Reg::R0,
7345 rm: Reg::R1,
7346 };
7347
7348 let code = encoder.encode(&op).unwrap();
7349 assert_eq!(code.len(), 4); }
7351
7352 #[test]
7353 fn test_encode_bx_thumb2() {
7354 let encoder = ArmEncoder::new_thumb2();
7355 let op = ArmOp::Bx { rm: Reg::LR };
7356
7357 let code = encoder.encode(&op).unwrap();
7358 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7362 }
7363
7364 #[test]
7369 fn test_encode_f32_abs_arm32() {
7370 let encoder = ArmEncoder::new_arm32();
7371 let op = ArmOp::F32Abs {
7372 sd: VfpReg::S0,
7373 sm: VfpReg::S2,
7374 };
7375 let code = encoder.encode(&op).unwrap();
7376 assert_eq!(code.len(), 4); }
7378
7379 #[test]
7380 fn test_encode_f32_neg_arm32() {
7381 let encoder = ArmEncoder::new_arm32();
7382 let op = ArmOp::F32Neg {
7383 sd: VfpReg::S0,
7384 sm: VfpReg::S2,
7385 };
7386 let code = encoder.encode(&op).unwrap();
7387 assert_eq!(code.len(), 4);
7388 }
7389
7390 #[test]
7391 fn test_encode_f32_sqrt_arm32() {
7392 let encoder = ArmEncoder::new_arm32();
7393 let op = ArmOp::F32Sqrt {
7394 sd: VfpReg::S0,
7395 sm: VfpReg::S2,
7396 };
7397 let code = encoder.encode(&op).unwrap();
7398 assert_eq!(code.len(), 4);
7399 }
7400
7401 #[test]
7402 fn test_encode_f32_ceil_arm32() {
7403 let encoder = ArmEncoder::new_arm32();
7404 let op = ArmOp::F32Ceil {
7405 sd: VfpReg::S0,
7406 sm: VfpReg::S2,
7407 };
7408 let code = encoder.encode(&op).unwrap();
7409 assert_eq!(code.len(), 36);
7411 }
7412
7413 #[test]
7414 fn test_encode_f32_floor_thumb2() {
7415 let encoder = ArmEncoder::new_thumb2();
7416 let op = ArmOp::F32Floor {
7417 sd: VfpReg::S0,
7418 sm: VfpReg::S2,
7419 };
7420 let code = encoder.encode(&op).unwrap();
7421 assert_eq!(code.len(), 36);
7423 }
7424
7425 #[test]
7426 fn test_encode_f32_min_arm32() {
7427 let encoder = ArmEncoder::new_arm32();
7428 let op = ArmOp::F32Min {
7429 sd: VfpReg::S0,
7430 sn: VfpReg::S2,
7431 sm: VfpReg::S4,
7432 };
7433 let code = encoder.encode(&op).unwrap();
7434 assert_eq!(code.len(), 16); }
7436
7437 #[test]
7438 fn test_encode_f32_max_thumb2() {
7439 let encoder = ArmEncoder::new_thumb2();
7440 let op = ArmOp::F32Max {
7441 sd: VfpReg::S0,
7442 sn: VfpReg::S2,
7443 sm: VfpReg::S4,
7444 };
7445 let code = encoder.encode(&op).unwrap();
7446 assert_eq!(code.len(), 18);
7448 }
7449
7450 #[test]
7451 fn test_encode_f32_copysign_arm32() {
7452 let encoder = ArmEncoder::new_arm32();
7453 let op = ArmOp::F32Copysign {
7454 sd: VfpReg::S0,
7455 sn: VfpReg::S2,
7456 sm: VfpReg::S4,
7457 };
7458 let code = encoder.encode(&op).unwrap();
7459 assert_eq!(code.len(), 24);
7461 }
7462
7463 #[test]
7468 fn test_encode_f64_add_arm32() {
7469 let encoder = ArmEncoder::new_arm32();
7470 let op = ArmOp::F64Add {
7471 dd: VfpReg::D0,
7472 dn: VfpReg::D1,
7473 dm: VfpReg::D2,
7474 };
7475 let code = encoder.encode(&op).unwrap();
7476 assert_eq!(code.len(), 4);
7477 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7479 assert_eq!((instr >> 8) & 0xF, 0xB); }
7481
7482 #[test]
7483 fn test_encode_f64_sub_thumb2() {
7484 let encoder = ArmEncoder::new_thumb2();
7485 let op = ArmOp::F64Sub {
7486 dd: VfpReg::D0,
7487 dn: VfpReg::D1,
7488 dm: VfpReg::D2,
7489 };
7490 let code = encoder.encode(&op).unwrap();
7491 assert_eq!(code.len(), 4); }
7493
7494 #[test]
7495 fn test_encode_f64_mul_arm32() {
7496 let encoder = ArmEncoder::new_arm32();
7497 let op = ArmOp::F64Mul {
7498 dd: VfpReg::D0,
7499 dn: VfpReg::D1,
7500 dm: VfpReg::D2,
7501 };
7502 let code = encoder.encode(&op).unwrap();
7503 assert_eq!(code.len(), 4);
7504 }
7505
7506 #[test]
7507 fn test_encode_f64_div_arm32() {
7508 let encoder = ArmEncoder::new_arm32();
7509 let op = ArmOp::F64Div {
7510 dd: VfpReg::D0,
7511 dn: VfpReg::D1,
7512 dm: VfpReg::D2,
7513 };
7514 let code = encoder.encode(&op).unwrap();
7515 assert_eq!(code.len(), 4);
7516 }
7517
7518 #[test]
7519 fn test_encode_f64_abs_arm32() {
7520 let encoder = ArmEncoder::new_arm32();
7521 let op = ArmOp::F64Abs {
7522 dd: VfpReg::D0,
7523 dm: VfpReg::D2,
7524 };
7525 let code = encoder.encode(&op).unwrap();
7526 assert_eq!(code.len(), 4);
7527 }
7528
7529 #[test]
7530 fn test_encode_f64_neg_arm32() {
7531 let encoder = ArmEncoder::new_arm32();
7532 let op = ArmOp::F64Neg {
7533 dd: VfpReg::D0,
7534 dm: VfpReg::D2,
7535 };
7536 let code = encoder.encode(&op).unwrap();
7537 assert_eq!(code.len(), 4);
7538 }
7539
7540 #[test]
7541 fn test_encode_f64_sqrt_arm32() {
7542 let encoder = ArmEncoder::new_arm32();
7543 let op = ArmOp::F64Sqrt {
7544 dd: VfpReg::D0,
7545 dm: VfpReg::D2,
7546 };
7547 let code = encoder.encode(&op).unwrap();
7548 assert_eq!(code.len(), 4);
7549 }
7550
7551 #[test]
7552 fn test_encode_f64_load_arm32() {
7553 let encoder = ArmEncoder::new_arm32();
7554 let op = ArmOp::F64Load {
7555 dd: VfpReg::D0,
7556 addr: MemAddr::imm(Reg::R0, 8),
7557 };
7558 let code = encoder.encode(&op).unwrap();
7559 assert_eq!(code.len(), 4);
7560 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7561 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7564
7565 #[test]
7566 fn test_encode_f64_store_thumb2() {
7567 let encoder = ArmEncoder::new_thumb2();
7568 let op = ArmOp::F64Store {
7569 dd: VfpReg::D0,
7570 addr: MemAddr::imm(Reg::SP, 0),
7571 };
7572 let code = encoder.encode(&op).unwrap();
7573 assert_eq!(code.len(), 4);
7574 }
7575
7576 #[test]
7577 fn test_encode_f64_compare_arm32() {
7578 let encoder = ArmEncoder::new_arm32();
7579 let op = ArmOp::F64Eq {
7580 rd: Reg::R0,
7581 dn: VfpReg::D0,
7582 dm: VfpReg::D1,
7583 };
7584 let code = encoder.encode(&op).unwrap();
7585 assert_eq!(code.len(), 16); }
7587
7588 #[test]
7589 fn test_encode_f64_compare_thumb2() {
7590 let encoder = ArmEncoder::new_thumb2();
7591 let op = ArmOp::F64Lt {
7592 rd: Reg::R0,
7593 dn: VfpReg::D0,
7594 dm: VfpReg::D1,
7595 };
7596 let code = encoder.encode(&op).unwrap();
7597 assert_eq!(code.len(), 14);
7599 }
7600
7601 #[test]
7602 fn test_encode_f64_const_arm32() {
7603 let encoder = ArmEncoder::new_arm32();
7604 let op = ArmOp::F64Const {
7605 dd: VfpReg::D0,
7606 value: 3.125,
7607 };
7608 let code = encoder.encode(&op).unwrap();
7609 assert_eq!(code.len(), 20);
7611 }
7612
7613 #[test]
7614 fn test_encode_f64_const_thumb2() {
7615 let encoder = ArmEncoder::new_thumb2();
7616 let op = ArmOp::F64Const {
7617 dd: VfpReg::D0,
7618 value: 2.5,
7619 };
7620 let code = encoder.encode(&op).unwrap();
7621 assert_eq!(code.len(), 20);
7623 }
7624
7625 #[test]
7626 fn test_encode_f64_convert_i32s_arm32() {
7627 let encoder = ArmEncoder::new_arm32();
7628 let op = ArmOp::F64ConvertI32S {
7629 dd: VfpReg::D0,
7630 rm: Reg::R0,
7631 };
7632 let code = encoder.encode(&op).unwrap();
7633 assert_eq!(code.len(), 8);
7635 }
7636
7637 #[test]
7638 fn test_encode_f64_promote_f32_arm32() {
7639 let encoder = ArmEncoder::new_arm32();
7640 let op = ArmOp::F64PromoteF32 {
7641 dd: VfpReg::D0,
7642 sm: VfpReg::S0,
7643 };
7644 let code = encoder.encode(&op).unwrap();
7645 assert_eq!(code.len(), 4); }
7647
7648 #[test]
7649 fn test_encode_f64_promote_f32_thumb2() {
7650 let encoder = ArmEncoder::new_thumb2();
7651 let op = ArmOp::F64PromoteF32 {
7652 dd: VfpReg::D0,
7653 sm: VfpReg::S0,
7654 };
7655 let code = encoder.encode(&op).unwrap();
7656 assert_eq!(code.len(), 4);
7657 }
7658
7659 #[test]
7660 fn test_encode_i32_trunc_f64s_arm32() {
7661 let encoder = ArmEncoder::new_arm32();
7662 let op = ArmOp::I32TruncF64S {
7663 rd: Reg::R0,
7664 dm: VfpReg::D0,
7665 };
7666 let code = encoder.encode(&op).unwrap();
7667 assert_eq!(code.len(), 8);
7669 }
7670
7671 #[test]
7672 fn test_encode_f64_reinterpret_i64_arm32() {
7673 let encoder = ArmEncoder::new_arm32();
7674 let op = ArmOp::F64ReinterpretI64 {
7675 dd: VfpReg::D0,
7676 rmlo: Reg::R0,
7677 rmhi: Reg::R1,
7678 };
7679 let code = encoder.encode(&op).unwrap();
7680 assert_eq!(code.len(), 4); }
7682
7683 #[test]
7684 fn test_encode_i64_reinterpret_f64_thumb2() {
7685 let encoder = ArmEncoder::new_thumb2();
7686 let op = ArmOp::I64ReinterpretF64 {
7687 rdlo: Reg::R0,
7688 rdhi: Reg::R1,
7689 dm: VfpReg::D0,
7690 };
7691 let code = encoder.encode(&op).unwrap();
7692 assert_eq!(code.len(), 4);
7693 }
7694
7695 #[test]
7696 fn test_encode_f64_trunc_thumb2() {
7697 let encoder = ArmEncoder::new_thumb2();
7698 let op = ArmOp::F64Trunc {
7699 dd: VfpReg::D0,
7700 dm: VfpReg::D1,
7701 };
7702 let code = encoder.encode(&op).unwrap();
7703 assert_eq!(code.len(), 8);
7705 }
7706
7707 #[test]
7708 fn test_encode_f64_min_arm32() {
7709 let encoder = ArmEncoder::new_arm32();
7710 let op = ArmOp::F64Min {
7711 dd: VfpReg::D0,
7712 dn: VfpReg::D1,
7713 dm: VfpReg::D2,
7714 };
7715 let code = encoder.encode(&op).unwrap();
7716 assert_eq!(code.len(), 16);
7718 }
7719
7720 #[test]
7721 fn test_f64_cp11_encoding() {
7722 let encoder = ArmEncoder::new_arm32();
7724
7725 let code = encoder
7727 .encode(&ArmOp::F64Add {
7728 dd: VfpReg::D0,
7729 dn: VfpReg::D0,
7730 dm: VfpReg::D0,
7731 })
7732 .unwrap();
7733 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7734 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7735
7736 let code = encoder
7738 .encode(&ArmOp::F32Add {
7739 sd: VfpReg::S0,
7740 sn: VfpReg::S0,
7741 sm: VfpReg::S0,
7742 })
7743 .unwrap();
7744 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7745 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7746 }
7747
7748 #[test]
7749 fn test_dreg_encoding_higher_registers() {
7750 let encoder = ArmEncoder::new_arm32();
7751
7752 let op = ArmOp::F64Add {
7754 dd: VfpReg::D15,
7755 dn: VfpReg::D14,
7756 dm: VfpReg::D13,
7757 };
7758 let code = encoder.encode(&op).unwrap();
7759 assert_eq!(code.len(), 4);
7760
7761 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7763 assert_eq!((instr >> 8) & 0xF, 0xB); }
7765
7766 #[test]
7771 fn test_encode_label_emits_no_bytes() {
7772 let encoder = ArmEncoder::new_thumb2();
7773 let op = ArmOp::Label {
7774 name: ".Lblock_end_0".to_string(),
7775 };
7776 let code = encoder.encode(&op).unwrap();
7777 assert!(code.is_empty(), "Label should emit zero bytes");
7778
7779 let encoder32 = ArmEncoder::new_arm32();
7780 let code32 = encoder32.encode(&op).unwrap();
7781 assert!(
7782 code32.is_empty(),
7783 "Label should emit zero bytes in ARM32 too"
7784 );
7785 }
7786
7787 #[test]
7788 fn test_encode_bcc_eq_thumb2() {
7789 use synth_synthesis::Condition;
7790 let encoder = ArmEncoder::new_thumb2();
7791 let op = ArmOp::Bcc {
7792 cond: Condition::EQ,
7793 label: "target".to_string(),
7794 };
7795 let code = encoder.encode(&op).unwrap();
7796 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7800 }
7801
7802 #[test]
7803 fn test_encode_bcc_ne_thumb2() {
7804 use synth_synthesis::Condition;
7805 let encoder = ArmEncoder::new_thumb2();
7806 let op = ArmOp::Bcc {
7807 cond: Condition::NE,
7808 label: "target".to_string(),
7809 };
7810 let code = encoder.encode(&op).unwrap();
7811 assert_eq!(code.len(), 2);
7812
7813 assert_eq!(code, vec![0x00, 0xD1]);
7815 }
7816
7817 #[test]
7818 fn test_encode_bcc_arm32() {
7819 use synth_synthesis::Condition;
7820 let encoder = ArmEncoder::new_arm32();
7821 let op = ArmOp::Bcc {
7822 cond: Condition::EQ,
7823 label: "target".to_string(),
7824 };
7825 let code = encoder.encode(&op).unwrap();
7826 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7829 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7833
7834 #[test]
7835 fn test_encode_udf_thumb2() {
7836 let encoder = ArmEncoder::new_thumb2();
7837 let op = ArmOp::Udf { imm: 0 };
7838 let code = encoder.encode(&op).unwrap();
7839 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
7843 }
7844
7845 #[test]
7846 fn test_encode_nop_thumb2() {
7847 let encoder = ArmEncoder::new_thumb2();
7848 let op = ArmOp::Nop;
7849 let code = encoder.encode(&op).unwrap();
7850 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
7854 }
7855
7856 #[test]
7861 fn test_encode_i64_add_thumb2() {
7862 let encoder = ArmEncoder::new_thumb2();
7863 let op = ArmOp::I64Add {
7864 rdlo: Reg::R0,
7865 rdhi: Reg::R1,
7866 rnlo: Reg::R0,
7867 rnhi: Reg::R1,
7868 rmlo: Reg::R2,
7869 rmhi: Reg::R3,
7870 };
7871 let code = encoder.encode(&op).unwrap();
7872 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
7874 }
7875
7876 #[test]
7877 fn test_encode_i64_sub_thumb2() {
7878 let encoder = ArmEncoder::new_thumb2();
7879 let op = ArmOp::I64Sub {
7880 rdlo: Reg::R0,
7881 rdhi: Reg::R1,
7882 rnlo: Reg::R0,
7883 rnhi: Reg::R1,
7884 rmlo: Reg::R2,
7885 rmhi: Reg::R3,
7886 };
7887 let code = encoder.encode(&op).unwrap();
7888 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
7890 }
7891
7892 #[test]
7893 fn test_encode_i64_and_thumb2() {
7894 let encoder = ArmEncoder::new_thumb2();
7895 let op = ArmOp::I64And {
7896 rdlo: Reg::R0,
7897 rdhi: Reg::R1,
7898 rnlo: Reg::R0,
7899 rnhi: Reg::R1,
7900 rmlo: Reg::R2,
7901 rmhi: Reg::R3,
7902 };
7903 let code = encoder.encode(&op).unwrap();
7904 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
7906 }
7907
7908 #[test]
7909 fn test_encode_i64_or_thumb2() {
7910 let encoder = ArmEncoder::new_thumb2();
7911 let op = ArmOp::I64Or {
7912 rdlo: Reg::R0,
7913 rdhi: Reg::R1,
7914 rnlo: Reg::R0,
7915 rnhi: Reg::R1,
7916 rmlo: Reg::R2,
7917 rmhi: Reg::R3,
7918 };
7919 let code = encoder.encode(&op).unwrap();
7920 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
7921 }
7922
7923 #[test]
7924 fn test_encode_i64_xor_thumb2() {
7925 let encoder = ArmEncoder::new_thumb2();
7926 let op = ArmOp::I64Xor {
7927 rdlo: Reg::R0,
7928 rdhi: Reg::R1,
7929 rnlo: Reg::R0,
7930 rnhi: Reg::R1,
7931 rmlo: Reg::R2,
7932 rmhi: Reg::R3,
7933 };
7934 let code = encoder.encode(&op).unwrap();
7935 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
7936 }
7937
7938 #[test]
7939 fn test_encode_i64_const_small_thumb2() {
7940 let encoder = ArmEncoder::new_thumb2();
7941 let op = ArmOp::I64Const {
7943 rdlo: Reg::R0,
7944 rdhi: Reg::R1,
7945 value: 42,
7946 };
7947 let code = encoder.encode(&op).unwrap();
7948 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
7950 }
7951
7952 #[test]
7953 fn test_encode_i64_const_large_thumb2() {
7954 let encoder = ArmEncoder::new_thumb2();
7955 let op = ArmOp::I64Const {
7957 rdlo: Reg::R0,
7958 rdhi: Reg::R1,
7959 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
7960 };
7961 let code = encoder.encode(&op).unwrap();
7962 assert_eq!(
7964 code.len(),
7965 16,
7966 "I64Const with large value should be 16 bytes"
7967 );
7968 }
7969
7970 #[test]
7971 fn test_encode_i64_extend_i32_s_thumb2() {
7972 let encoder = ArmEncoder::new_thumb2();
7973 let op = ArmOp::I64ExtendI32S {
7974 rdlo: Reg::R0,
7975 rdhi: Reg::R1,
7976 rn: Reg::R0,
7977 };
7978 let code = encoder.encode(&op).unwrap();
7979 assert_eq!(
7981 code.len(),
7982 4,
7983 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
7984 );
7985 }
7986
7987 #[test]
7988 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
7989 let encoder = ArmEncoder::new_thumb2();
7990 let op = ArmOp::I64ExtendI32S {
7991 rdlo: Reg::R0,
7992 rdhi: Reg::R1,
7993 rn: Reg::R2,
7994 };
7995 let code = encoder.encode(&op).unwrap();
7996 assert!(
7998 code.len() >= 6,
7999 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8000 );
8001 }
8002
8003 #[test]
8004 fn test_encode_i64_extend_i32_u_thumb2() {
8005 let encoder = ArmEncoder::new_thumb2();
8006 let op = ArmOp::I64ExtendI32U {
8007 rdlo: Reg::R0,
8008 rdhi: Reg::R1,
8009 rn: Reg::R0,
8010 };
8011 let code = encoder.encode(&op).unwrap();
8012 assert_eq!(
8014 code.len(),
8015 2,
8016 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8017 );
8018 }
8019
8020 #[test]
8021 fn test_encode_i32_wrap_i64_nop_thumb2() {
8022 let encoder = ArmEncoder::new_thumb2();
8023 let op = ArmOp::I32WrapI64 {
8025 rd: Reg::R0,
8026 rnlo: Reg::R0,
8027 };
8028 let code = encoder.encode(&op).unwrap();
8029 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8030 assert_eq!(code, vec![0x00, 0xBF]); }
8032
8033 #[test]
8034 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8035 let encoder = ArmEncoder::new_thumb2();
8036 let op = ArmOp::I32WrapI64 {
8037 rd: Reg::R2,
8038 rnlo: Reg::R0,
8039 };
8040 let code = encoder.encode(&op).unwrap();
8041 assert!(
8043 code.len() >= 2,
8044 "I32WrapI64 diff reg should emit at least 2 bytes"
8045 );
8046 }
8047
8048 #[test]
8049 fn test_encode_i64_eqz_thumb2() {
8050 let encoder = ArmEncoder::new_thumb2();
8051 let op = ArmOp::I64Eqz {
8052 rd: Reg::R0,
8053 rnlo: Reg::R0,
8054 rnhi: Reg::R1,
8055 };
8056 let code = encoder.encode(&op).unwrap();
8057 assert!(
8059 code.len() >= 6,
8060 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8061 );
8062 }
8063
8064 #[test]
8065 fn test_encode_i64_eq_thumb2() {
8066 let encoder = ArmEncoder::new_thumb2();
8067 let op = ArmOp::I64Eq {
8068 rd: Reg::R0,
8069 rnlo: Reg::R0,
8070 rnhi: Reg::R1,
8071 rmlo: Reg::R2,
8072 rmhi: Reg::R3,
8073 };
8074 let code = encoder.encode(&op).unwrap();
8075 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8077 }
8078
8079 #[test]
8080 fn test_encode_i64_ldr_thumb2() {
8081 let encoder = ArmEncoder::new_thumb2();
8082 let op = ArmOp::I64Ldr {
8083 rdlo: Reg::R0,
8084 rdhi: Reg::R1,
8085 addr: MemAddr::imm(Reg::SP, 0),
8086 };
8087 let code = encoder.encode(&op).unwrap();
8088 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8090 }
8091
8092 #[test]
8093 fn test_encode_i64_str_thumb2() {
8094 let encoder = ArmEncoder::new_thumb2();
8095 let op = ArmOp::I64Str {
8096 rdlo: Reg::R0,
8097 rdhi: Reg::R1,
8098 addr: MemAddr::imm(Reg::SP, 0),
8099 };
8100 let code = encoder.encode(&op).unwrap();
8101 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8103 }
8104
8105 #[test]
8106 fn test_encode_i64_all_comparisons_thumb2() {
8107 let encoder = ArmEncoder::new_thumb2();
8108
8109 let ops = vec![
8110 ArmOp::I64Ne {
8111 rd: Reg::R0,
8112 rnlo: Reg::R0,
8113 rnhi: Reg::R1,
8114 rmlo: Reg::R2,
8115 rmhi: Reg::R3,
8116 },
8117 ArmOp::I64LtS {
8118 rd: Reg::R0,
8119 rnlo: Reg::R0,
8120 rnhi: Reg::R1,
8121 rmlo: Reg::R2,
8122 rmhi: Reg::R3,
8123 },
8124 ArmOp::I64LtU {
8125 rd: Reg::R0,
8126 rnlo: Reg::R0,
8127 rnhi: Reg::R1,
8128 rmlo: Reg::R2,
8129 rmhi: Reg::R3,
8130 },
8131 ArmOp::I64LeS {
8132 rd: Reg::R0,
8133 rnlo: Reg::R0,
8134 rnhi: Reg::R1,
8135 rmlo: Reg::R2,
8136 rmhi: Reg::R3,
8137 },
8138 ArmOp::I64LeU {
8139 rd: Reg::R0,
8140 rnlo: Reg::R0,
8141 rnhi: Reg::R1,
8142 rmlo: Reg::R2,
8143 rmhi: Reg::R3,
8144 },
8145 ArmOp::I64GtS {
8146 rd: Reg::R0,
8147 rnlo: Reg::R0,
8148 rnhi: Reg::R1,
8149 rmlo: Reg::R2,
8150 rmhi: Reg::R3,
8151 },
8152 ArmOp::I64GtU {
8153 rd: Reg::R0,
8154 rnlo: Reg::R0,
8155 rnhi: Reg::R1,
8156 rmlo: Reg::R2,
8157 rmhi: Reg::R3,
8158 },
8159 ArmOp::I64GeS {
8160 rd: Reg::R0,
8161 rnlo: Reg::R0,
8162 rnhi: Reg::R1,
8163 rmlo: Reg::R2,
8164 rmhi: Reg::R3,
8165 },
8166 ArmOp::I64GeU {
8167 rd: Reg::R0,
8168 rnlo: Reg::R0,
8169 rnhi: Reg::R1,
8170 rmlo: Reg::R2,
8171 rmhi: Reg::R3,
8172 },
8173 ];
8174
8175 for op in &ops {
8176 let code = encoder.encode(op).unwrap();
8177 assert!(
8178 code.len() >= 8,
8179 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8180 op,
8181 code.len()
8182 );
8183 }
8184 }
8185
8186 #[test]
8187 fn test_encode_i64_const_zero_thumb2() {
8188 let encoder = ArmEncoder::new_thumb2();
8189 let op = ArmOp::I64Const {
8190 rdlo: Reg::R0,
8191 rdhi: Reg::R1,
8192 value: 0,
8193 };
8194 let code = encoder.encode(&op).unwrap();
8195 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8197 }
8198
8199 #[test]
8200 fn test_encode_i64_const_negative_one_thumb2() {
8201 let encoder = ArmEncoder::new_thumb2();
8202 let op = ArmOp::I64Const {
8203 rdlo: Reg::R0,
8204 rdhi: Reg::R1,
8205 value: -1, };
8207 let code = encoder.encode(&op).unwrap();
8208 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8210 }
8211
8212 #[test]
8217 fn test_encode_ldrb_arm32() {
8218 let encoder = ArmEncoder::new_arm32();
8219 let op = ArmOp::Ldrb {
8220 rd: Reg::R0,
8221 addr: MemAddr::imm(Reg::R1, 4),
8222 };
8223 let code = encoder.encode(&op).unwrap();
8224 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8225 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8227 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8228 }
8229
8230 #[test]
8231 fn test_encode_strb_arm32() {
8232 let encoder = ArmEncoder::new_arm32();
8233 let op = ArmOp::Strb {
8234 rd: Reg::R0,
8235 addr: MemAddr::imm(Reg::R1, 0),
8236 };
8237 let code = encoder.encode(&op).unwrap();
8238 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8239 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8241 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8242 }
8243
8244 #[test]
8245 fn test_encode_ldrh_arm32() {
8246 let encoder = ArmEncoder::new_arm32();
8247 let op = ArmOp::Ldrh {
8248 rd: Reg::R0,
8249 addr: MemAddr::imm(Reg::R1, 2),
8250 };
8251 let code = encoder.encode(&op).unwrap();
8252 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8253 }
8254
8255 #[test]
8256 fn test_encode_strh_arm32() {
8257 let encoder = ArmEncoder::new_arm32();
8258 let op = ArmOp::Strh {
8259 rd: Reg::R0,
8260 addr: MemAddr::imm(Reg::R1, 0),
8261 };
8262 let code = encoder.encode(&op).unwrap();
8263 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8264 }
8265
8266 #[test]
8267 fn test_encode_ldrsb_arm32() {
8268 let encoder = ArmEncoder::new_arm32();
8269 let op = ArmOp::Ldrsb {
8270 rd: Reg::R0,
8271 addr: MemAddr::imm(Reg::R1, 0),
8272 };
8273 let code = encoder.encode(&op).unwrap();
8274 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8275 }
8276
8277 #[test]
8278 fn test_encode_ldrsh_arm32() {
8279 let encoder = ArmEncoder::new_arm32();
8280 let op = ArmOp::Ldrsh {
8281 rd: Reg::R0,
8282 addr: MemAddr::imm(Reg::R1, 0),
8283 };
8284 let code = encoder.encode(&op).unwrap();
8285 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8286 }
8287
8288 #[test]
8289 fn test_encode_ldrb_thumb2_16bit() {
8290 let encoder = ArmEncoder::new_thumb2();
8291 let op = ArmOp::Ldrb {
8292 rd: Reg::R0,
8293 addr: MemAddr::imm(Reg::R1, 4),
8294 };
8295 let code = encoder.encode(&op).unwrap();
8296 assert_eq!(
8298 code.len(),
8299 2,
8300 "Thumb-2 LDRB with small offset should be 16-bit"
8301 );
8302 }
8303
8304 #[test]
8305 fn test_encode_ldrb_thumb2_32bit() {
8306 let encoder = ArmEncoder::new_thumb2();
8307 let op = ArmOp::Ldrb {
8308 rd: Reg::R0,
8309 addr: MemAddr::imm(Reg::R1, 100), };
8311 let code = encoder.encode(&op).unwrap();
8312 assert_eq!(
8313 code.len(),
8314 4,
8315 "Thumb-2 LDRB with large offset should be 32-bit"
8316 );
8317 }
8318
8319 #[test]
8320 fn test_encode_strb_thumb2_16bit() {
8321 let encoder = ArmEncoder::new_thumb2();
8322 let op = ArmOp::Strb {
8323 rd: Reg::R0,
8324 addr: MemAddr::imm(Reg::R1, 10),
8325 };
8326 let code = encoder.encode(&op).unwrap();
8327 assert_eq!(
8328 code.len(),
8329 2,
8330 "Thumb-2 STRB with small offset should be 16-bit"
8331 );
8332 }
8333
8334 #[test]
8335 fn test_encode_ldrh_thumb2_16bit() {
8336 let encoder = ArmEncoder::new_thumb2();
8337 let op = ArmOp::Ldrh {
8338 rd: Reg::R0,
8339 addr: MemAddr::imm(Reg::R1, 4), };
8341 let code = encoder.encode(&op).unwrap();
8342 assert_eq!(
8343 code.len(),
8344 2,
8345 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8346 );
8347 }
8348
8349 #[test]
8350 fn test_encode_strh_thumb2_16bit() {
8351 let encoder = ArmEncoder::new_thumb2();
8352 let op = ArmOp::Strh {
8353 rd: Reg::R0,
8354 addr: MemAddr::imm(Reg::R1, 4),
8355 };
8356 let code = encoder.encode(&op).unwrap();
8357 assert_eq!(
8358 code.len(),
8359 2,
8360 "Thumb-2 STRH with small aligned offset should be 16-bit"
8361 );
8362 }
8363
8364 #[test]
8365 fn test_encode_ldrsb_thumb2() {
8366 let encoder = ArmEncoder::new_thumb2();
8367 let op = ArmOp::Ldrsb {
8368 rd: Reg::R0,
8369 addr: MemAddr::imm(Reg::R1, 0),
8370 };
8371 let code = encoder.encode(&op).unwrap();
8372 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8374 }
8375
8376 #[test]
8377 fn test_encode_ldrsh_thumb2() {
8378 let encoder = ArmEncoder::new_thumb2();
8379 let op = ArmOp::Ldrsh {
8380 rd: Reg::R0,
8381 addr: MemAddr::imm(Reg::R1, 0),
8382 };
8383 let code = encoder.encode(&op).unwrap();
8384 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8385 }
8386
8387 #[test]
8388 fn test_encode_memory_size_thumb2() {
8389 let encoder = ArmEncoder::new_thumb2();
8390 let op = ArmOp::MemorySize { rd: Reg::R0 };
8391 let code = encoder.encode(&op).unwrap();
8392 assert!(!code.is_empty(), "MemorySize should produce code");
8394 }
8395
8396 #[test]
8397 fn test_encode_memory_grow_thumb2() {
8398 let encoder = ArmEncoder::new_thumb2();
8399 let op = ArmOp::MemoryGrow {
8400 rd: Reg::R0,
8401 rn: Reg::R0,
8402 };
8403 let code = encoder.encode(&op).unwrap();
8404 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8405 }
8406
8407 #[test]
8408 fn test_encode_subword_reg_offset_thumb2() {
8409 let encoder = ArmEncoder::new_thumb2();
8410
8411 let op = ArmOp::Ldrb {
8413 rd: Reg::R0,
8414 addr: MemAddr::reg(Reg::R1, Reg::R2),
8415 };
8416 let code = encoder.encode(&op).unwrap();
8417 assert_eq!(
8418 code.len(),
8419 4,
8420 "Thumb-2 LDRB with reg offset should be 32-bit"
8421 );
8422
8423 let op = ArmOp::Strb {
8425 rd: Reg::R0,
8426 addr: MemAddr::reg(Reg::R1, Reg::R2),
8427 };
8428 let code = encoder.encode(&op).unwrap();
8429 assert_eq!(
8430 code.len(),
8431 4,
8432 "Thumb-2 STRB with reg offset should be 32-bit"
8433 );
8434
8435 let op = ArmOp::Ldrh {
8437 rd: Reg::R0,
8438 addr: MemAddr::reg(Reg::R1, Reg::R2),
8439 };
8440 let code = encoder.encode(&op).unwrap();
8441 assert_eq!(
8442 code.len(),
8443 4,
8444 "Thumb-2 LDRH with reg offset should be 32-bit"
8445 );
8446
8447 let op = ArmOp::Strh {
8449 rd: Reg::R0,
8450 addr: MemAddr::reg(Reg::R1, Reg::R2),
8451 };
8452 let code = encoder.encode(&op).unwrap();
8453 assert_eq!(
8454 code.len(),
8455 4,
8456 "Thumb-2 STRH with reg offset should be 32-bit"
8457 );
8458 }
8459
8460 #[test]
8461 fn test_encode_subword_reg_imm_offset_thumb2() {
8462 let encoder = ArmEncoder::new_thumb2();
8463
8464 let op = ArmOp::Ldrb {
8466 rd: Reg::R0,
8467 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8468 };
8469 let code = encoder.encode(&op).unwrap();
8470 assert_eq!(
8472 code.len(),
8473 8,
8474 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8475 );
8476 }
8477
8478 #[test]
8483 fn test_encode_mve_addi32_thumb2() {
8484 let encoder = ArmEncoder::new_thumb2();
8485 let op = ArmOp::MveAddI {
8486 qd: QReg::Q0,
8487 qn: QReg::Q1,
8488 qm: QReg::Q2,
8489 size: MveSize::S32,
8490 };
8491 let code = encoder.encode(&op).unwrap();
8492 assert_eq!(
8493 code.len(),
8494 4,
8495 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8496 );
8497 }
8498
8499 #[test]
8500 fn test_encode_mve_subi16_thumb2() {
8501 let encoder = ArmEncoder::new_thumb2();
8502 let op = ArmOp::MveSubI {
8503 qd: QReg::Q0,
8504 qn: QReg::Q1,
8505 qm: QReg::Q2,
8506 size: MveSize::S16,
8507 };
8508 let code = encoder.encode(&op).unwrap();
8509 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8510 }
8511
8512 #[test]
8513 fn test_encode_mve_muli8_thumb2() {
8514 let encoder = ArmEncoder::new_thumb2();
8515 let op = ArmOp::MveMulI {
8516 qd: QReg::Q0,
8517 qn: QReg::Q1,
8518 qm: QReg::Q2,
8519 size: MveSize::S8,
8520 };
8521 let code = encoder.encode(&op).unwrap();
8522 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8523 }
8524
8525 #[test]
8526 fn test_encode_mve_bitwise_thumb2() {
8527 let encoder = ArmEncoder::new_thumb2();
8528
8529 let ops = vec![
8530 ArmOp::MveAnd {
8531 qd: QReg::Q0,
8532 qn: QReg::Q1,
8533 qm: QReg::Q2,
8534 },
8535 ArmOp::MveOrr {
8536 qd: QReg::Q0,
8537 qn: QReg::Q1,
8538 qm: QReg::Q2,
8539 },
8540 ArmOp::MveEor {
8541 qd: QReg::Q0,
8542 qn: QReg::Q1,
8543 qm: QReg::Q2,
8544 },
8545 ArmOp::MveBic {
8546 qd: QReg::Q0,
8547 qn: QReg::Q1,
8548 qm: QReg::Q2,
8549 },
8550 ];
8551 for op in ops {
8552 let code = encoder.encode(&op).unwrap();
8553 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8554 }
8555 }
8556
8557 #[test]
8558 fn test_encode_mve_mvn_thumb2() {
8559 let encoder = ArmEncoder::new_thumb2();
8560 let op = ArmOp::MveMvn {
8561 qd: QReg::Q0,
8562 qm: QReg::Q1,
8563 };
8564 let code = encoder.encode(&op).unwrap();
8565 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8566 }
8567
8568 #[test]
8569 fn test_encode_mve_load_store_thumb2() {
8570 let encoder = ArmEncoder::new_thumb2();
8571
8572 let load = ArmOp::MveLoad {
8573 qd: QReg::Q0,
8574 addr: MemAddr::imm(Reg::R0, 16),
8575 };
8576 let code = encoder.encode(&load).unwrap();
8577 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8578
8579 let store = ArmOp::MveStore {
8580 qd: QReg::Q1,
8581 addr: MemAddr::imm(Reg::R1, 0),
8582 };
8583 let code = encoder.encode(&store).unwrap();
8584 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8585 }
8586
8587 #[test]
8588 fn test_encode_mve_const_thumb2() {
8589 let encoder = ArmEncoder::new_thumb2();
8590 let op = ArmOp::MveConst {
8591 qd: QReg::Q0,
8592 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8593 };
8594 let code = encoder.encode(&op).unwrap();
8595 assert!(
8598 code.len() >= 24,
8599 "MVE const should produce multiple instructions"
8600 );
8601 }
8602
8603 #[test]
8604 fn test_encode_mve_dup_thumb2() {
8605 let encoder = ArmEncoder::new_thumb2();
8606 let op = ArmOp::MveDup {
8607 qd: QReg::Q0,
8608 rn: Reg::R0,
8609 size: MveSize::S32,
8610 };
8611 let code = encoder.encode(&op).unwrap();
8612 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8613 }
8614
8615 #[test]
8616 fn test_encode_mve_extract_lane_thumb2() {
8617 let encoder = ArmEncoder::new_thumb2();
8618 let op = ArmOp::MveExtractLane {
8619 rd: Reg::R0,
8620 qn: QReg::Q1,
8621 lane: 2,
8622 size: MveSize::S32,
8623 };
8624 let code = encoder.encode(&op).unwrap();
8625 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8626 }
8627
8628 #[test]
8629 fn test_encode_mve_insert_lane_thumb2() {
8630 let encoder = ArmEncoder::new_thumb2();
8631 let op = ArmOp::MveInsertLane {
8632 qd: QReg::Q0,
8633 rn: Reg::R1,
8634 lane: 3,
8635 size: MveSize::S32,
8636 };
8637 let code = encoder.encode(&op).unwrap();
8638 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8639 }
8640
8641 #[test]
8642 fn test_encode_mve_addf32_thumb2() {
8643 let encoder = ArmEncoder::new_thumb2();
8644 let op = ArmOp::MveAddF32 {
8645 qd: QReg::Q0,
8646 qn: QReg::Q1,
8647 qm: QReg::Q2,
8648 };
8649 let code = encoder.encode(&op).unwrap();
8650 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8651 }
8652
8653 #[test]
8654 fn test_encode_mve_divf32_thumb2() {
8655 let encoder = ArmEncoder::new_thumb2();
8656 let op = ArmOp::MveDivF32 {
8657 qd: QReg::Q0,
8658 qn: QReg::Q1,
8659 qm: QReg::Q2,
8660 };
8661 let code = encoder.encode(&op).unwrap();
8662 assert_eq!(
8664 code.len(),
8665 16,
8666 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8667 );
8668 }
8669
8670 #[test]
8671 fn test_encode_mve_sqrtf32_thumb2() {
8672 let encoder = ArmEncoder::new_thumb2();
8673 let op = ArmOp::MveSqrtF32 {
8674 qd: QReg::Q0,
8675 qm: QReg::Q1,
8676 };
8677 let code = encoder.encode(&op).unwrap();
8678 assert_eq!(
8680 code.len(),
8681 16,
8682 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8683 );
8684 }
8685
8686 #[test]
8687 fn test_encode_mve_negf32_thumb2() {
8688 let encoder = ArmEncoder::new_thumb2();
8689 let op = ArmOp::MveNegF32 {
8690 qd: QReg::Q0,
8691 qm: QReg::Q1,
8692 };
8693 let code = encoder.encode(&op).unwrap();
8694 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8695 }
8696
8697 #[test]
8698 fn test_encode_mve_absf32_thumb2() {
8699 let encoder = ArmEncoder::new_thumb2();
8700 let op = ArmOp::MveAbsF32 {
8701 qd: QReg::Q0,
8702 qm: QReg::Q1,
8703 };
8704 let code = encoder.encode(&op).unwrap();
8705 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8706 }
8707
8708 #[test]
8709 fn test_encode_mve_different_qregs() {
8710 let encoder = ArmEncoder::new_thumb2();
8711
8712 let op1 = ArmOp::MveAddI {
8714 qd: QReg::Q0,
8715 qn: QReg::Q0,
8716 qm: QReg::Q0,
8717 size: MveSize::S32,
8718 };
8719 let op2 = ArmOp::MveAddI {
8720 qd: QReg::Q3,
8721 qn: QReg::Q5,
8722 qm: QReg::Q7,
8723 size: MveSize::S32,
8724 };
8725 let code1 = encoder.encode(&op1).unwrap();
8726 let code2 = encoder.encode(&op2).unwrap();
8727 assert_ne!(
8728 code1, code2,
8729 "Different Q-registers should produce different encodings"
8730 );
8731 }
8732
8733 #[test]
8734 fn test_encode_mve_arm32_nop() {
8735 let encoder = ArmEncoder::new_arm32();
8737 let op = ArmOp::MveAddI {
8738 qd: QReg::Q0,
8739 qn: QReg::Q1,
8740 qm: QReg::Q2,
8741 size: MveSize::S32,
8742 };
8743 let code = encoder.encode(&op).unwrap();
8744 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8745 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8747 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8748 }
8749}