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 mut bytes = ite_instr.to_le_bytes().to_vec();
2647 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2648 if rd_bits <= 7 {
2649 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2651 } else {
2652 let hw1: u16 = 0xF04F;
2654 let hw2: u16 = (rd_bits << 8) | imm;
2655 bytes.extend_from_slice(&hw1.to_le_bytes());
2656 bytes.extend_from_slice(&hw2.to_le_bytes());
2657 }
2658 };
2659 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2662 }
2663
2664 ArmOp::I64SetCond {
2669 rd,
2670 rn_lo,
2671 rn_hi,
2672 rm_lo,
2673 rm_hi,
2674 cond,
2675 } => {
2676 use synth_synthesis::Condition;
2677 let rd_bits = reg_to_bits(rd) as u16;
2678 let mut bytes = Vec::new();
2679
2680 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2682 rm: &synth_synthesis::Reg|
2683 -> Vec<u8> {
2684 let rn_bits = reg_to_bits(rn) as u16;
2685 let rm_bits = reg_to_bits(rm) as u16;
2686 if rn_bits < 8 && rm_bits < 8 {
2687 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2688 instr.to_le_bytes().to_vec()
2689 } else {
2690 let n_bit = (rn_bits >> 3) & 1;
2691 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2692 instr.to_le_bytes().to_vec()
2693 }
2694 };
2695
2696 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2698 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2699 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2700 ite_instr.to_le_bytes().to_vec()
2701 };
2702
2703 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2705 let mut b = encode_ite(cond_bits);
2706 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2707 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2708 b.extend_from_slice(&mov_one.to_le_bytes());
2709 b.extend_from_slice(&mov_zero.to_le_bytes());
2710 b
2711 };
2712
2713 match cond {
2714 Condition::EQ | Condition::NE => {
2715 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2717
2718 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2721
2722 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2724
2725 let cond_bits: u16 = match cond {
2727 Condition::EQ => 0x0,
2728 Condition::NE => 0x1,
2729 _ => unreachable!(),
2730 };
2731 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2732 }
2733
2734 Condition::LT => {
2735 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2737
2738 let rn_hi_bits = reg_to_bits(rn_hi);
2741 let rm_hi_bits = reg_to_bits(rm_hi);
2742 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2743 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2744 bytes.extend_from_slice(&hw1.to_le_bytes());
2745 bytes.extend_from_slice(&hw2.to_le_bytes());
2746
2747 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2750
2751 Condition::GT => {
2752 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2755
2756 let rm_hi_bits = reg_to_bits(rm_hi);
2758 let rn_hi_bits = reg_to_bits(rn_hi);
2759 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2760 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2761 bytes.extend_from_slice(&hw1.to_le_bytes());
2762 bytes.extend_from_slice(&hw2.to_le_bytes());
2763
2764 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2767
2768 Condition::LE => {
2769 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2773
2774 let rm_hi_bits = reg_to_bits(rm_hi);
2776 let rn_hi_bits = reg_to_bits(rn_hi);
2777 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2778 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2779 bytes.extend_from_slice(&hw1.to_le_bytes());
2780 bytes.extend_from_slice(&hw2.to_le_bytes());
2781
2782 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2785
2786 Condition::GE => {
2787 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2790
2791 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
2799 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2802
2803 Condition::LO => {
2805 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2807 let rn_hi_bits = reg_to_bits(rn_hi);
2808 let rm_hi_bits = reg_to_bits(rm_hi);
2809 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2810 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2811 bytes.extend_from_slice(&hw1.to_le_bytes());
2812 bytes.extend_from_slice(&hw2.to_le_bytes());
2813 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2815
2816 Condition::HI => {
2817 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2819 let rm_hi_bits = reg_to_bits(rm_hi);
2820 let rn_hi_bits = reg_to_bits(rn_hi);
2821 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2822 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2823 bytes.extend_from_slice(&hw1.to_le_bytes());
2824 bytes.extend_from_slice(&hw2.to_le_bytes());
2825 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2827
2828 Condition::LS => {
2829 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2831 let rm_hi_bits = reg_to_bits(rm_hi);
2832 let rn_hi_bits = reg_to_bits(rn_hi);
2833 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2834 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2835 bytes.extend_from_slice(&hw1.to_le_bytes());
2836 bytes.extend_from_slice(&hw2.to_le_bytes());
2837 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2839
2840 Condition::HS => {
2841 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2843 let rn_hi_bits = reg_to_bits(rn_hi);
2844 let rm_hi_bits = reg_to_bits(rm_hi);
2845 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2846 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2847 bytes.extend_from_slice(&hw1.to_le_bytes());
2848 bytes.extend_from_slice(&hw2.to_le_bytes());
2849 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2851 }
2852
2853 Ok(bytes)
2854 }
2855
2856 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2859 let rd_bits = reg_to_bits(rd);
2860 let rn_lo_bits = reg_to_bits(rn_lo);
2861 let rn_hi_bits = reg_to_bits(rn_hi);
2862 let mut bytes = Vec::new();
2863
2864 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2866 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2867 bytes.extend_from_slice(&hw1.to_le_bytes());
2868 bytes.extend_from_slice(&hw2.to_le_bytes());
2869
2870 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2872 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2873
2874 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2877 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2878 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2879 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2880 bytes.extend_from_slice(&mov_one.to_le_bytes());
2881 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2882
2883 Ok(bytes)
2884 }
2885
2886 ArmOp::I64Mul {
2890 rd_lo,
2891 rd_hi,
2892 rn_lo,
2893 rn_hi,
2894 rm_lo,
2895 rm_hi,
2896 } => {
2897 let rd_lo_bits = reg_to_bits(rd_lo);
2898 let rd_hi_bits = reg_to_bits(rd_hi);
2899 let rn_lo_bits = reg_to_bits(rn_lo);
2900 let rn_hi_bits = reg_to_bits(rn_hi);
2901 let rm_lo_bits = reg_to_bits(rm_lo);
2902 let rm_hi_bits = reg_to_bits(rm_hi);
2903 let r12: u32 = 12; let mut bytes = Vec::new();
2905
2906 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
2909 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
2910 bytes.extend_from_slice(&hw1.to_le_bytes());
2911 bytes.extend_from_slice(&hw2.to_le_bytes());
2912
2913 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
2916 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
2917 bytes.extend_from_slice(&hw1.to_le_bytes());
2918 bytes.extend_from_slice(&hw2.to_le_bytes());
2919
2920 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
2923 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2924 bytes.extend_from_slice(&hw1.to_le_bytes());
2925 bytes.extend_from_slice(&hw2.to_le_bytes());
2926
2927 let d_bit = (rd_hi_bits >> 3) & 1;
2930 let add_instr: u16 =
2931 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
2932 bytes.extend_from_slice(&add_instr.to_le_bytes());
2933
2934 Ok(bytes)
2935 }
2936
2937 ArmOp::I64Shl {
2940 rd_lo,
2941 rd_hi,
2942 rn_lo,
2943 rn_hi,
2944 rm_lo,
2945 rm_hi,
2946 } => {
2947 let rd_lo_bits = reg_to_bits(rd_lo);
2948 let rd_hi_bits = reg_to_bits(rd_hi);
2949 let rn_lo_bits = reg_to_bits(rn_lo);
2950 let rn_hi_bits = reg_to_bits(rn_hi);
2951 let rm_lo_bits = reg_to_bits(rm_lo);
2952 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
2954
2955 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
2957 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
2958 bytes.extend_from_slice(&hw1.to_le_bytes());
2959 bytes.extend_from_slice(&hw2.to_le_bytes());
2960
2961 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
2963 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2964 bytes.extend_from_slice(&hw1.to_le_bytes());
2965 bytes.extend_from_slice(&hw2.to_le_bytes());
2966
2967 let bpl: u16 = 0xD50A;
2969 bytes.extend_from_slice(&bpl.to_le_bytes());
2970
2971 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
2974 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
2975 bytes.extend_from_slice(&hw1.to_le_bytes());
2976 bytes.extend_from_slice(&hw2.to_le_bytes());
2977
2978 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
2980 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
2981 bytes.extend_from_slice(&hw1.to_le_bytes());
2982 bytes.extend_from_slice(&hw2.to_le_bytes());
2983
2984 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
2986 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
2987 bytes.extend_from_slice(&hw1.to_le_bytes());
2988 bytes.extend_from_slice(&hw2.to_le_bytes());
2989
2990 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
2992 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
2993 bytes.extend_from_slice(&hw1.to_le_bytes());
2994 bytes.extend_from_slice(&hw2.to_le_bytes());
2995
2996 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
2998 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
2999 bytes.extend_from_slice(&hw1.to_le_bytes());
3000 bytes.extend_from_slice(&hw2.to_le_bytes());
3001
3002 let b_done: u16 = 0xE002;
3004 bytes.extend_from_slice(&b_done.to_le_bytes());
3005
3006 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3009 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3010 bytes.extend_from_slice(&hw1.to_le_bytes());
3011 bytes.extend_from_slice(&hw2.to_le_bytes());
3012
3013 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3015 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3016
3017 Ok(bytes) }
3019
3020 ArmOp::I64ShrU {
3022 rd_lo,
3023 rd_hi,
3024 rn_lo,
3025 rn_hi,
3026 rm_lo,
3027 rm_hi,
3028 } => {
3029 let rd_lo_bits = reg_to_bits(rd_lo);
3030 let rd_hi_bits = reg_to_bits(rd_hi);
3031 let rn_lo_bits = reg_to_bits(rn_lo);
3032 let rn_hi_bits = reg_to_bits(rn_hi);
3033 let rm_lo_bits = reg_to_bits(rm_lo);
3034 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3036
3037 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3039 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3040 bytes.extend_from_slice(&hw1.to_le_bytes());
3041 bytes.extend_from_slice(&hw2.to_le_bytes());
3042
3043 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3045 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3046 bytes.extend_from_slice(&hw1.to_le_bytes());
3047 bytes.extend_from_slice(&hw2.to_le_bytes());
3048
3049 let bpl: u16 = 0xD50A;
3051 bytes.extend_from_slice(&bpl.to_le_bytes());
3052
3053 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3056 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3057 bytes.extend_from_slice(&hw1.to_le_bytes());
3058 bytes.extend_from_slice(&hw2.to_le_bytes());
3059
3060 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3062 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3063 bytes.extend_from_slice(&hw1.to_le_bytes());
3064 bytes.extend_from_slice(&hw2.to_le_bytes());
3065
3066 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3068 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3069 bytes.extend_from_slice(&hw1.to_le_bytes());
3070 bytes.extend_from_slice(&hw2.to_le_bytes());
3071
3072 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3074 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3075 bytes.extend_from_slice(&hw1.to_le_bytes());
3076 bytes.extend_from_slice(&hw2.to_le_bytes());
3077
3078 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3080 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3081 bytes.extend_from_slice(&hw1.to_le_bytes());
3082 bytes.extend_from_slice(&hw2.to_le_bytes());
3083
3084 let b_done: u16 = 0xE002;
3086 bytes.extend_from_slice(&b_done.to_le_bytes());
3087
3088 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3091 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3092 bytes.extend_from_slice(&hw1.to_le_bytes());
3093 bytes.extend_from_slice(&hw2.to_le_bytes());
3094
3095 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3097 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3098
3099 Ok(bytes) }
3101
3102 ArmOp::I64ShrS {
3104 rd_lo,
3105 rd_hi,
3106 rn_lo,
3107 rn_hi,
3108 rm_lo,
3109 rm_hi,
3110 } => {
3111 let rd_lo_bits = reg_to_bits(rd_lo);
3112 let rd_hi_bits = reg_to_bits(rd_hi);
3113 let rn_lo_bits = reg_to_bits(rn_lo);
3114 let rn_hi_bits = reg_to_bits(rn_hi);
3115 let rm_lo_bits = reg_to_bits(rm_lo);
3116 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3118
3119 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3121 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3122 bytes.extend_from_slice(&hw1.to_le_bytes());
3123 bytes.extend_from_slice(&hw2.to_le_bytes());
3124
3125 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3127 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3128 bytes.extend_from_slice(&hw1.to_le_bytes());
3129 bytes.extend_from_slice(&hw2.to_le_bytes());
3130
3131 let bpl: u16 = 0xD50A;
3133 bytes.extend_from_slice(&bpl.to_le_bytes());
3134
3135 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3138 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3139 bytes.extend_from_slice(&hw1.to_le_bytes());
3140 bytes.extend_from_slice(&hw2.to_le_bytes());
3141
3142 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3144 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3145 bytes.extend_from_slice(&hw1.to_le_bytes());
3146 bytes.extend_from_slice(&hw2.to_le_bytes());
3147
3148 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3150 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3151 bytes.extend_from_slice(&hw1.to_le_bytes());
3152 bytes.extend_from_slice(&hw2.to_le_bytes());
3153
3154 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3156 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3157 bytes.extend_from_slice(&hw1.to_le_bytes());
3158 bytes.extend_from_slice(&hw2.to_le_bytes());
3159
3160 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3162 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3163 bytes.extend_from_slice(&hw1.to_le_bytes());
3164 bytes.extend_from_slice(&hw2.to_le_bytes());
3165
3166 let b_done: u16 = 0xE003;
3168 bytes.extend_from_slice(&b_done.to_le_bytes());
3169
3170 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3173 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3174 bytes.extend_from_slice(&hw1.to_le_bytes());
3175 bytes.extend_from_slice(&hw2.to_le_bytes());
3176
3177 let hw1: u16 = 0xEA4F;
3181 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3182 bytes.extend_from_slice(&hw1.to_le_bytes());
3183 bytes.extend_from_slice(&hw2.to_le_bytes());
3184
3185 Ok(bytes) }
3187
3188 ArmOp::I64Rotl {
3193 rdlo,
3194 rdhi,
3195 rnlo,
3196 rnhi,
3197 shift,
3198 } => {
3199 let rd_lo_bits = reg_to_bits(rdlo);
3200 let rd_hi_bits = reg_to_bits(rdhi);
3201 let rn_lo_bits = reg_to_bits(rnlo);
3202 let rn_hi_bits = reg_to_bits(rnhi);
3203 let shift_bits = reg_to_bits(shift);
3204 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3208
3209 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3211
3212 let hw1: u16 = (0xF000 | shift_bits) as u16;
3214 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3215 bytes.extend_from_slice(&hw1.to_le_bytes());
3216 bytes.extend_from_slice(&hw2.to_le_bytes());
3217
3218 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3220 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3221 bytes.extend_from_slice(&hw1.to_le_bytes());
3222 bytes.extend_from_slice(&hw2.to_le_bytes());
3223
3224 let bpl: u16 = 0xD50E;
3226 bytes.extend_from_slice(&bpl.to_le_bytes());
3227
3228 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3231 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3232 bytes.extend_from_slice(&hw1.to_le_bytes());
3233 bytes.extend_from_slice(&hw2.to_le_bytes());
3234
3235 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3237 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3238 bytes.extend_from_slice(&hw1.to_le_bytes());
3239 bytes.extend_from_slice(&hw2.to_le_bytes());
3240
3241 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3243 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3244 bytes.extend_from_slice(&hw1.to_le_bytes());
3245 bytes.extend_from_slice(&hw2.to_le_bytes());
3246
3247 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3249 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3250 bytes.extend_from_slice(&hw1.to_le_bytes());
3251 bytes.extend_from_slice(&hw2.to_le_bytes());
3252
3253 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3255 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3256 bytes.extend_from_slice(&hw1.to_le_bytes());
3257 bytes.extend_from_slice(&hw2.to_le_bytes());
3258
3259 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3261 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3262 bytes.extend_from_slice(&hw1.to_le_bytes());
3263 bytes.extend_from_slice(&hw2.to_le_bytes());
3264
3265 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3267 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3268 bytes.extend_from_slice(&hw1.to_le_bytes());
3269 bytes.extend_from_slice(&hw2.to_le_bytes());
3270
3271 let b_done: u16 = 0xE00E;
3273 bytes.extend_from_slice(&b_done.to_le_bytes());
3274
3275 let hw1: u16 = (0xF1C0 | r3) as u16;
3279 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3280 bytes.extend_from_slice(&hw1.to_le_bytes());
3281 bytes.extend_from_slice(&hw2.to_le_bytes());
3282
3283 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3285 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3286 bytes.extend_from_slice(&hw1.to_le_bytes());
3287 bytes.extend_from_slice(&hw2.to_le_bytes());
3288
3289 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3291 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3292 bytes.extend_from_slice(&hw1.to_le_bytes());
3293 bytes.extend_from_slice(&hw2.to_le_bytes());
3294
3295 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3297 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3298 bytes.extend_from_slice(&hw1.to_le_bytes());
3299 bytes.extend_from_slice(&hw2.to_le_bytes());
3300
3301 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3303 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3304 bytes.extend_from_slice(&hw1.to_le_bytes());
3305 bytes.extend_from_slice(&hw2.to_le_bytes());
3306
3307 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3309 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3310 bytes.extend_from_slice(&hw1.to_le_bytes());
3311 bytes.extend_from_slice(&hw2.to_le_bytes());
3312
3313 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3315 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3316 bytes.extend_from_slice(&hw1.to_le_bytes());
3317 bytes.extend_from_slice(&hw2.to_le_bytes());
3318
3319 let d_bit = (rd_hi_bits >> 3) & 1;
3321 let mov_instr: u16 =
3322 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3323 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3324
3325 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3327
3328 Ok(bytes) }
3330
3331 ArmOp::I64Rotr {
3336 rdlo,
3337 rdhi,
3338 rnlo,
3339 rnhi,
3340 shift,
3341 } => {
3342 let rd_lo_bits = reg_to_bits(rdlo);
3343 let rd_hi_bits = reg_to_bits(rdhi);
3344 let rn_lo_bits = reg_to_bits(rnlo);
3345 let rn_hi_bits = reg_to_bits(rnhi);
3346 let shift_bits = reg_to_bits(shift);
3347 let r12: u32 = 12;
3348 let r3: u32 = 3;
3349 let r4: u32 = 4;
3350 let mut bytes = Vec::new();
3351
3352 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3354
3355 let hw1: u16 = (0xF000 | shift_bits) as u16;
3357 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3358 bytes.extend_from_slice(&hw1.to_le_bytes());
3359 bytes.extend_from_slice(&hw2.to_le_bytes());
3360
3361 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3363 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3364 bytes.extend_from_slice(&hw1.to_le_bytes());
3365 bytes.extend_from_slice(&hw2.to_le_bytes());
3366
3367 let bpl: u16 = 0xD50E;
3369 bytes.extend_from_slice(&bpl.to_le_bytes());
3370
3371 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3374 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3375 bytes.extend_from_slice(&hw1.to_le_bytes());
3376 bytes.extend_from_slice(&hw2.to_le_bytes());
3377
3378 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3380 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3381 bytes.extend_from_slice(&hw1.to_le_bytes());
3382 bytes.extend_from_slice(&hw2.to_le_bytes());
3383
3384 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3386 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3387 bytes.extend_from_slice(&hw1.to_le_bytes());
3388 bytes.extend_from_slice(&hw2.to_le_bytes());
3389
3390 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3392 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3393 bytes.extend_from_slice(&hw1.to_le_bytes());
3394 bytes.extend_from_slice(&hw2.to_le_bytes());
3395
3396 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3398 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3399 bytes.extend_from_slice(&hw1.to_le_bytes());
3400 bytes.extend_from_slice(&hw2.to_le_bytes());
3401
3402 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3404 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3405 bytes.extend_from_slice(&hw1.to_le_bytes());
3406 bytes.extend_from_slice(&hw2.to_le_bytes());
3407
3408 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3410 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3411 bytes.extend_from_slice(&hw1.to_le_bytes());
3412 bytes.extend_from_slice(&hw2.to_le_bytes());
3413
3414 let b_done: u16 = 0xE00E;
3416 bytes.extend_from_slice(&b_done.to_le_bytes());
3417
3418 let hw1: u16 = (0xF1C0 | r3) as u16;
3421 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3422 bytes.extend_from_slice(&hw1.to_le_bytes());
3423 bytes.extend_from_slice(&hw2.to_le_bytes());
3424
3425 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3427 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3428 bytes.extend_from_slice(&hw1.to_le_bytes());
3429 bytes.extend_from_slice(&hw2.to_le_bytes());
3430
3431 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3433 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3434 bytes.extend_from_slice(&hw1.to_le_bytes());
3435 bytes.extend_from_slice(&hw2.to_le_bytes());
3436
3437 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3439 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3440 bytes.extend_from_slice(&hw1.to_le_bytes());
3441 bytes.extend_from_slice(&hw2.to_le_bytes());
3442
3443 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3445 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3446 bytes.extend_from_slice(&hw1.to_le_bytes());
3447 bytes.extend_from_slice(&hw2.to_le_bytes());
3448
3449 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3451 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3452 bytes.extend_from_slice(&hw1.to_le_bytes());
3453 bytes.extend_from_slice(&hw2.to_le_bytes());
3454
3455 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3457 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3458 bytes.extend_from_slice(&hw1.to_le_bytes());
3459 bytes.extend_from_slice(&hw2.to_le_bytes());
3460
3461 let d_bit = (rd_lo_bits >> 3) & 1;
3463 let mov_instr: u16 =
3464 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3465 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3466
3467 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3469
3470 Ok(bytes) }
3472
3473 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3487 let rd_bits = reg_to_bits(rd);
3488 let rn_lo_bits = reg_to_bits(rnlo);
3489 let rn_hi_bits = reg_to_bits(rnhi);
3490 let mut bytes = Vec::new();
3491
3492 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3494 let hw2: u16 = 0x0F00;
3495 bytes.extend_from_slice(&hw1.to_le_bytes());
3496 bytes.extend_from_slice(&hw2.to_le_bytes());
3497
3498 let beq: u16 = 0xD003;
3501 bytes.extend_from_slice(&beq.to_le_bytes());
3502
3503 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3506 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3507 bytes.extend_from_slice(&hw1.to_le_bytes());
3508 bytes.extend_from_slice(&hw2.to_le_bytes());
3509
3510 let b_done: u16 = 0xE004;
3513 bytes.extend_from_slice(&b_done.to_le_bytes());
3514
3515 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3517
3518 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3522 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3523 bytes.extend_from_slice(&hw1.to_le_bytes());
3524 bytes.extend_from_slice(&hw2.to_le_bytes());
3525
3526 let hw1: u16 = (0xF100 | rd_bits) as u16;
3528 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3529 bytes.extend_from_slice(&hw1.to_le_bytes());
3530 bytes.extend_from_slice(&hw2.to_le_bytes());
3531
3532 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3536 bytes.extend_from_slice(&mov0.to_le_bytes());
3537
3538 Ok(bytes)
3539 }
3540
3541 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3557 let rd_bits = reg_to_bits(rd);
3558 let rn_lo_bits = reg_to_bits(rnlo);
3559 let rn_hi_bits = reg_to_bits(rnhi);
3560 let mut bytes = Vec::new();
3561
3562 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3564 let hw2: u16 = 0x0F00;
3565 bytes.extend_from_slice(&hw1.to_le_bytes());
3566 bytes.extend_from_slice(&hw2.to_le_bytes());
3567
3568 let beq: u16 = 0xD005;
3571 bytes.extend_from_slice(&beq.to_le_bytes());
3572
3573 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3576 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3577 bytes.extend_from_slice(&hw1.to_le_bytes());
3578 bytes.extend_from_slice(&hw2.to_le_bytes());
3579
3580 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3583 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3584 bytes.extend_from_slice(&hw1.to_le_bytes());
3585 bytes.extend_from_slice(&hw2.to_le_bytes());
3586
3587 let b_done: u16 = 0xE006;
3590 bytes.extend_from_slice(&b_done.to_le_bytes());
3591
3592 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3594
3595 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3599 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3600 bytes.extend_from_slice(&hw1.to_le_bytes());
3601 bytes.extend_from_slice(&hw2.to_le_bytes());
3602
3603 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3606 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3607 bytes.extend_from_slice(&hw1.to_le_bytes());
3608 bytes.extend_from_slice(&hw2.to_le_bytes());
3609
3610 let hw1: u16 = (0xF100 | rd_bits) as u16;
3612 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3613 bytes.extend_from_slice(&hw1.to_le_bytes());
3614 bytes.extend_from_slice(&hw2.to_le_bytes());
3615
3616 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3619 bytes.extend_from_slice(&mov0.to_le_bytes());
3620
3621 Ok(bytes)
3622 }
3623
3624 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3628 let rd_bits = reg_to_bits(rd);
3629 let rn_lo_bits = reg_to_bits(rnlo);
3630 let rn_hi_bits = reg_to_bits(rnhi);
3631 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3634
3635 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3637
3638 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3648 bytes.extend_from_slice(&mov.to_le_bytes());
3649
3650 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3653 bytes.extend_from_slice(&mov.to_le_bytes());
3654
3655 let hw1: u16 = 0xEA4F;
3659 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3660 bytes.extend_from_slice(&hw1.to_le_bytes());
3661 bytes.extend_from_slice(&hw2.to_le_bytes());
3662
3663 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3666 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3667 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3669 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3670
3671 let hw1: u16 = (0xEA00 | r12) as u16;
3673 let hw2: u16 = ((r12 << 8) | r3) as u16;
3674 bytes.extend_from_slice(&hw1.to_le_bytes());
3675 bytes.extend_from_slice(&hw2.to_le_bytes());
3676
3677 let hw1: u16 = (0xEBA0 | 4) as u16;
3679 let hw2: u16 = ((4 << 8) | r12) as u16;
3680 bytes.extend_from_slice(&hw1.to_le_bytes());
3681 bytes.extend_from_slice(&hw2.to_le_bytes());
3682
3683 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3687 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3688 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3690 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3691
3692 let hw1: u16 = (0xEA00 | 4) as u16;
3694 let hw2: u16 = ((r12 << 8) | r3) as u16;
3695 bytes.extend_from_slice(&hw1.to_le_bytes());
3696 bytes.extend_from_slice(&hw2.to_le_bytes());
3697
3698 let hw1: u16 = 0xEA4F;
3700 let hw2: u16 = ((4 << 8) | 0x90 | 4) as u16;
3701 bytes.extend_from_slice(&hw1.to_le_bytes());
3702 bytes.extend_from_slice(&hw2.to_le_bytes());
3703
3704 let hw1: u16 = (0xEA00 | 4) as u16;
3706 let hw2: u16 = ((4 << 8) | r3) 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 let hw1: u16 = 0xEA4F;
3721 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3722 bytes.extend_from_slice(&hw1.to_le_bytes());
3723 bytes.extend_from_slice(&hw2.to_le_bytes());
3724
3725 let hw1: u16 = (0xEB00 | 4) as u16;
3727 let hw2: u16 = ((4 << 8) | r12) as u16;
3728 bytes.extend_from_slice(&hw1.to_le_bytes());
3729 bytes.extend_from_slice(&hw2.to_le_bytes());
3730
3731 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3736 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3737 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3739 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3740
3741 let hw1: u16 = (0xEA00 | 4) as u16;
3743 let hw2: u16 = ((4 << 8) | r3) as u16;
3744 bytes.extend_from_slice(&hw1.to_le_bytes());
3745 bytes.extend_from_slice(&hw2.to_le_bytes());
3746
3747 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3751 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3752 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3754 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3755
3756 let hw1: u16 = (0xFB00 | 4) as u16;
3759 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3760 bytes.extend_from_slice(&hw1.to_le_bytes());
3761 bytes.extend_from_slice(&hw2.to_le_bytes());
3762
3763 let hw1: u16 = 0xEA4F;
3766 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3767 bytes.extend_from_slice(&hw1.to_le_bytes());
3768 bytes.extend_from_slice(&hw2.to_le_bytes());
3769
3770 let hw1: u16 = 0xEA4F;
3773 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3774 bytes.extend_from_slice(&hw1.to_le_bytes());
3775 bytes.extend_from_slice(&hw2.to_le_bytes());
3776
3777 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3779 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3780 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3781 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3782
3783 let hw1: u16 = (0xEA00 | r12) as u16;
3784 let hw2: u16 = ((r12 << 8) | r3) as u16;
3785 bytes.extend_from_slice(&hw1.to_le_bytes());
3786 bytes.extend_from_slice(&hw2.to_le_bytes());
3787
3788 let hw1: u16 = (0xEBA0 | 5) as u16;
3789 let hw2: u16 = ((5 << 8) | r12) as u16;
3790 bytes.extend_from_slice(&hw1.to_le_bytes());
3791 bytes.extend_from_slice(&hw2.to_le_bytes());
3792
3793 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3795 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3796 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3797 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3798
3799 let hw1: u16 = (0xEA00 | 5) as u16;
3800 let hw2: u16 = ((r12 << 8) | r3) 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;
3805 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3806 bytes.extend_from_slice(&hw1.to_le_bytes());
3807 bytes.extend_from_slice(&hw2.to_le_bytes());
3808
3809 let hw1: u16 = (0xEA00 | 5) as u16;
3810 let hw2: u16 = ((5 << 8) | r3) as u16;
3811 bytes.extend_from_slice(&hw1.to_le_bytes());
3812 bytes.extend_from_slice(&hw2.to_le_bytes());
3813
3814 let hw1: u16 = (0xEB00 | 5) as u16;
3815 let hw2: u16 = ((5 << 8) | r12) as u16;
3816 bytes.extend_from_slice(&hw1.to_le_bytes());
3817 bytes.extend_from_slice(&hw2.to_le_bytes());
3818
3819 let hw1: u16 = 0xEA4F;
3822 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3823 bytes.extend_from_slice(&hw1.to_le_bytes());
3824 bytes.extend_from_slice(&hw2.to_le_bytes());
3825
3826 let hw1: u16 = (0xEB00 | 5) as u16;
3827 let hw2: u16 = ((5 << 8) | r12) as u16;
3828 bytes.extend_from_slice(&hw1.to_le_bytes());
3829 bytes.extend_from_slice(&hw2.to_le_bytes());
3830
3831 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3833 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3834 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3835 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3836
3837 let hw1: u16 = (0xEA00 | 5) as u16;
3838 let hw2: u16 = ((5 << 8) | r3) as u16;
3839 bytes.extend_from_slice(&hw1.to_le_bytes());
3840 bytes.extend_from_slice(&hw2.to_le_bytes());
3841
3842 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3844 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3845 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3846 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3847
3848 let hw1: u16 = (0xFB00 | 5) as u16;
3851 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3852 bytes.extend_from_slice(&hw1.to_le_bytes());
3853 bytes.extend_from_slice(&hw2.to_le_bytes());
3854
3855 let hw1: u16 = 0xEA4F;
3858 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3859 bytes.extend_from_slice(&hw1.to_le_bytes());
3860 bytes.extend_from_slice(&hw2.to_le_bytes());
3861
3862 let rd_bits_u16 = rd_bits as u16;
3865 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3866 bytes.extend_from_slice(&instr.to_le_bytes());
3867
3868 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3870
3871 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3873 bytes.extend_from_slice(&mov0.to_le_bytes());
3874
3875 Ok(bytes)
3876 }
3877
3878 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3881 let rdlo_bits = reg_to_bits(rdlo);
3882 let rdhi_bits = reg_to_bits(rdhi);
3883 let rnlo_bits = reg_to_bits(rnlo);
3884 let mut bytes = Vec::new();
3885
3886 let hw1: u16 = 0xFA4F_u16;
3889 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3890 bytes.extend_from_slice(&hw1.to_le_bytes());
3891 bytes.extend_from_slice(&hw2.to_le_bytes());
3892
3893 let hw1: u16 = 0xEA4F;
3898 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3899 bytes.extend_from_slice(&hw1.to_le_bytes());
3900 bytes.extend_from_slice(&hw2.to_le_bytes());
3901
3902 Ok(bytes)
3903 }
3904
3905 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
3908 let rdlo_bits = reg_to_bits(rdlo);
3909 let rdhi_bits = reg_to_bits(rdhi);
3910 let rnlo_bits = reg_to_bits(rnlo);
3911 let mut bytes = Vec::new();
3912
3913 let hw1: u16 = 0xFA0F_u16;
3916 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
3917 bytes.extend_from_slice(&hw1.to_le_bytes());
3918 bytes.extend_from_slice(&hw2.to_le_bytes());
3919
3920 let hw1: u16 = 0xEA4F;
3922 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
3923 bytes.extend_from_slice(&hw1.to_le_bytes());
3924 bytes.extend_from_slice(&hw2.to_le_bytes());
3925
3926 Ok(bytes)
3927 }
3928
3929 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
3932 let rdlo_bits = reg_to_bits(rdlo);
3933 let rdhi_bits = reg_to_bits(rdhi);
3934 let rnlo_bits = reg_to_bits(rnlo);
3935 let mut bytes = Vec::new();
3936
3937 if rdlo_bits != rnlo_bits {
3939 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
3941 let mov: u16 = 0x4600
3942 | (d_bit << 7)
3943 | ((rnlo_bits as u16) << 3)
3944 | ((rdlo_bits & 0x7) as u16);
3945 bytes.extend_from_slice(&mov.to_le_bytes());
3946 }
3947
3948 let hw1: u16 = 0xEA4F;
3950 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
3951 bytes.extend_from_slice(&hw1.to_le_bytes());
3952 bytes.extend_from_slice(&hw2.to_le_bytes());
3953
3954 Ok(bytes)
3955 }
3956
3957 ArmOp::SelectMove { rd, rm, cond } => {
3960 let rd_bits = reg_to_bits(rd) as u16;
3961 let rm_bits = reg_to_bits(rm) as u16;
3962
3963 use synth_synthesis::Condition;
3965 let cond_bits: u16 = match cond {
3966 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, };
3977
3978 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
3981
3982 let d_bit = (rd_bits >> 3) & 1;
3985 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
3986
3987 let mut bytes = it_instr.to_le_bytes().to_vec();
3989 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3990 Ok(bytes)
3991 }
3992
3993 ArmOp::Popcnt { rd, rm } => {
4004 let mut bytes = Vec::new();
4005
4006 if rd != rm {
4008 let rd_bits = reg_to_bits(rd) as u16;
4009 let rm_bits = reg_to_bits(rm) as u16;
4010 let d_bit = (rd_bits >> 3) & 1;
4012 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4013 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4014 }
4015
4016 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4019 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4020
4021 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4024
4025 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4027
4028 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4030 reg_to_bits(rd),
4031 reg_to_bits(rd),
4032 11,
4033 )?);
4034
4035 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4038 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4039
4040 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4042 11,
4043 reg_to_bits(rd),
4044 12,
4045 )?);
4046
4047 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4049 reg_to_bits(rd),
4050 reg_to_bits(rd),
4051 2,
4052 )?);
4053
4054 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4056 reg_to_bits(rd),
4057 reg_to_bits(rd),
4058 12,
4059 )?);
4060
4061 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4063 reg_to_bits(rd),
4064 reg_to_bits(rd),
4065 11,
4066 )?);
4067
4068 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4071
4072 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4074 reg_to_bits(rd),
4075 reg_to_bits(rd),
4076 11,
4077 )?);
4078
4079 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4081 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4082
4083 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4085 reg_to_bits(rd),
4086 reg_to_bits(rd),
4087 12,
4088 )?);
4089
4090 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4093
4094 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4096 reg_to_bits(rd),
4097 reg_to_bits(rd),
4098 11,
4099 )?);
4100
4101 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4104
4105 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4107 reg_to_bits(rd),
4108 reg_to_bits(rd),
4109 11,
4110 )?);
4111
4112 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4115 reg_to_bits(rd),
4116 reg_to_bits(rd),
4117 0x3F,
4118 )?);
4119
4120 Ok(bytes)
4121 }
4122
4123 ArmOp::I64DivU {
4128 rdlo: _,
4129 rdhi: _,
4130 rnlo: _,
4131 rnhi: _,
4132 rmlo: _,
4133 rmhi: _,
4134 } => {
4135 let mut bytes = Vec::new();
4136
4137 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4141
4142 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());
4153 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4154
4155 let loop_start = bytes.len();
4157
4158 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4169 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());
4178 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4179 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4183 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4184
4185 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4190 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4191 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());
4222 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4223 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4226
4227 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4231 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4232
4233 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4236 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4237 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4238
4239 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4247
4248 Ok(bytes)
4249 }
4250
4251 ArmOp::I64DivS {
4256 rdlo: _,
4257 rdhi: _,
4258 rnlo: _,
4259 rnhi: _,
4260 rmlo: _,
4261 rmhi: _,
4262 } => {
4263 let mut bytes = Vec::new();
4264
4265 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4267 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4268
4269 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4272 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4273
4274 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());
4287
4288 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());
4298
4299 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4302 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4303 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4305 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4306 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4308 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4309
4310 let loop_start = bytes.len();
4311
4312 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4316 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());
4322 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4325
4326 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4330 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());
4343 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4345
4346 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4349
4350 let branch_offset_bytes = bytes.len() - loop_start + 4;
4351 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4352 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4353 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4354
4355 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());
4362 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());
4370
4371 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4373 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4374
4375 Ok(bytes)
4376 }
4377
4378 ArmOp::I64RemU {
4383 rdlo: _,
4384 rdhi: _,
4385 rnlo: _,
4386 rnhi: _,
4387 rmlo: _,
4388 rmhi: _,
4389 } => {
4390 let mut bytes = Vec::new();
4391
4392 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4394 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4395
4396 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4398 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4399 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4401 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4402 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4404 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4405
4406 let loop_start = bytes.len();
4407
4408 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4412 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());
4418 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4421
4422 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4426 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());
4439 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4441
4442 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4445
4446 let branch_offset_bytes = bytes.len() - loop_start + 4;
4447 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4448 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4449 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4450
4451 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4457 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4458
4459 Ok(bytes)
4460 }
4461
4462 ArmOp::I64RemS {
4467 rdlo: _,
4468 rdhi: _,
4469 rnlo: _,
4470 rnhi: _,
4471 rmlo: _,
4472 rmhi: _,
4473 } => {
4474 let mut bytes = Vec::new();
4475
4476 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4478 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4479
4480 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());
4494
4495 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());
4505
4506 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4509 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4510 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4512 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4513 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4515 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4516
4517 let loop_start = bytes.len();
4518
4519 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4523 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());
4529 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4532
4533 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4537 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());
4550 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4552
4553 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4556
4557 let branch_offset_bytes = bytes.len() - loop_start + 4;
4558 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4559 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4560 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4561
4562 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());
4569 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());
4577
4578 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4580 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4581
4582 Ok(bytes)
4583 }
4584
4585 ArmOp::F32Add { sd, sn, sm } => {
4588 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4589 }
4590 ArmOp::F32Sub { sd, sn, sm } => {
4591 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4592 }
4593 ArmOp::F32Mul { sd, sn, sm } => {
4594 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4595 }
4596 ArmOp::F32Div { sd, sn, sm } => {
4597 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4598 }
4599 ArmOp::F32Abs { sd, sm } => {
4600 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4601 }
4602 ArmOp::F32Neg { sd, sm } => {
4603 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4604 }
4605 ArmOp::F32Sqrt { sd, sm } => {
4606 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4607 }
4608
4609 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4612 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4613 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4614 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4615 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4616 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4617 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4618
4619 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4621 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4622 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4623 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4624 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4625 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4626
4627 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4628
4629 ArmOp::F32Load { sd, addr } => {
4630 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4631 }
4632 ArmOp::F32Store { sd, addr } => {
4633 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4634 }
4635
4636 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4637 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4638 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4639 Err(synth_core::Error::synthesis(
4640 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4641 ))
4642 }
4643 ArmOp::F32ReinterpretI32 { sd, rm } => {
4644 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4645 }
4646 ArmOp::I32ReinterpretF32 { rd, sm } => {
4647 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4648 }
4649 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4650 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4651
4652 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4655 0xEE300B00, dd, dn, dm,
4656 )?)),
4657 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4658 0xEE300B40, dd, dn, dm,
4659 )?)),
4660 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4661 0xEE200B00, dd, dn, dm,
4662 )?)),
4663 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4664 0xEE800B00, dd, dn, dm,
4665 )?)),
4666 ArmOp::F64Abs { dd, dm } => {
4667 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4668 }
4669 ArmOp::F64Neg { dd, dm } => {
4670 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4671 }
4672 ArmOp::F64Sqrt { dd, dm } => {
4673 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4674 }
4675
4676 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4679 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4680 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4681 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4682 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4683 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4684 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4685
4686 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4688 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4689 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4690 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4691 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4692 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4693
4694 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4695
4696 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4697 0xED900B00, dd, addr,
4698 )?)),
4699 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4700 0xED800B00, dd, addr,
4701 )?)),
4702
4703 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4704 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4705 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4706 Err(synth_core::Error::synthesis(
4707 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4708 ))
4709 }
4710 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4711 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4712 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4713 )),
4714 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4715 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4716 )),
4717 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4718 Err(synth_core::Error::synthesis(
4719 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4720 ))
4721 }
4722 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4723 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4724
4725 ArmOp::I64Add {
4729 rdlo,
4730 rdhi,
4731 rnlo,
4732 rnhi,
4733 rmlo,
4734 rmhi,
4735 } => {
4736 let mut bytes = Vec::new();
4737 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4739 rd: *rdlo,
4740 rn: *rnlo,
4741 op2: Operand2::Reg(*rmlo),
4742 })?);
4743 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4745 rd: *rdhi,
4746 rn: *rnhi,
4747 op2: Operand2::Reg(*rmhi),
4748 })?);
4749 Ok(bytes)
4750 }
4751
4752 ArmOp::I64Sub {
4754 rdlo,
4755 rdhi,
4756 rnlo,
4757 rnhi,
4758 rmlo,
4759 rmhi,
4760 } => {
4761 let mut bytes = Vec::new();
4762 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4764 rd: *rdlo,
4765 rn: *rnlo,
4766 op2: Operand2::Reg(*rmlo),
4767 })?);
4768 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4770 rd: *rdhi,
4771 rn: *rnhi,
4772 op2: Operand2::Reg(*rmhi),
4773 })?);
4774 Ok(bytes)
4775 }
4776
4777 ArmOp::I64And {
4779 rdlo,
4780 rdhi,
4781 rnlo,
4782 rnhi,
4783 rmlo,
4784 rmhi,
4785 } => {
4786 let mut bytes = Vec::new();
4787 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4788 rd: *rdlo,
4789 rn: *rnlo,
4790 op2: Operand2::Reg(*rmlo),
4791 })?);
4792 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4793 rd: *rdhi,
4794 rn: *rnhi,
4795 op2: Operand2::Reg(*rmhi),
4796 })?);
4797 Ok(bytes)
4798 }
4799
4800 ArmOp::I64Or {
4802 rdlo,
4803 rdhi,
4804 rnlo,
4805 rnhi,
4806 rmlo,
4807 rmhi,
4808 } => {
4809 let mut bytes = Vec::new();
4810 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4811 rd: *rdlo,
4812 rn: *rnlo,
4813 op2: Operand2::Reg(*rmlo),
4814 })?);
4815 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4816 rd: *rdhi,
4817 rn: *rnhi,
4818 op2: Operand2::Reg(*rmhi),
4819 })?);
4820 Ok(bytes)
4821 }
4822
4823 ArmOp::I64Xor {
4825 rdlo,
4826 rdhi,
4827 rnlo,
4828 rnhi,
4829 rmlo,
4830 rmhi,
4831 } => {
4832 let mut bytes = Vec::new();
4833 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4834 rd: *rdlo,
4835 rn: *rnlo,
4836 op2: Operand2::Reg(*rmlo),
4837 })?);
4838 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4839 rd: *rdhi,
4840 rn: *rnhi,
4841 op2: Operand2::Reg(*rmhi),
4842 })?);
4843 Ok(bytes)
4844 }
4845
4846 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4848 rd: *rd,
4849 rn_lo: *rnlo,
4850 rn_hi: *rnhi,
4851 }),
4852
4853 ArmOp::I64Eq {
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::EQ,
4867 }),
4868
4869 ArmOp::I64Ne {
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::NE,
4882 }),
4883
4884 ArmOp::I64LtS {
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::LT,
4897 }),
4898
4899 ArmOp::I64LtU {
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::LO,
4912 }),
4913
4914 ArmOp::I64LeS {
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::LE,
4927 }),
4928
4929 ArmOp::I64LeU {
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::LS,
4942 }),
4943
4944 ArmOp::I64GtS {
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::GT,
4957 }),
4958
4959 ArmOp::I64GtU {
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::HI,
4972 }),
4973
4974 ArmOp::I64GeS {
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::GE,
4987 }),
4988
4989 ArmOp::I64GeU {
4990 rd,
4991 rnlo,
4992 rnhi,
4993 rmlo,
4994 rmhi,
4995 } => self.encode_thumb(&ArmOp::I64SetCond {
4996 rd: *rd,
4997 rn_lo: *rnlo,
4998 rn_hi: *rnhi,
4999 rm_lo: *rmlo,
5000 rm_hi: *rmhi,
5001 cond: synth_synthesis::Condition::HS,
5002 }),
5003
5004 ArmOp::I64Const { rdlo, rdhi, value } => {
5006 let lo32 = *value as u32;
5007 let hi32 = (*value >> 32) as u32;
5008 let mut bytes = Vec::new();
5009 bytes.extend_from_slice(
5011 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5012 );
5013 if lo32 > 0xFFFF {
5014 bytes.extend_from_slice(
5015 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5016 );
5017 }
5018 bytes.extend_from_slice(
5020 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5021 );
5022 if hi32 > 0xFFFF {
5023 bytes.extend_from_slice(
5024 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5025 );
5026 }
5027 Ok(bytes)
5028 }
5029
5030 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5032 let mut bytes = Vec::new();
5033 let offset = if addr.offset < 0 {
5034 0u32
5035 } else {
5036 addr.offset as u32
5037 };
5038 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5039 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5040 rdhi,
5041 &addr.base,
5042 offset.wrapping_add(4),
5043 )?);
5044 Ok(bytes)
5045 }
5046
5047 ArmOp::I64Str { rdlo, rdhi, addr } => {
5049 let mut bytes = Vec::new();
5050 let offset = if addr.offset < 0 {
5051 0u32
5052 } else {
5053 addr.offset as u32
5054 };
5055 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5056 bytes.extend_from_slice(&self.encode_thumb32_str(
5057 rdhi,
5058 &addr.base,
5059 offset.wrapping_add(4),
5060 )?);
5061 Ok(bytes)
5062 }
5063
5064 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5066 let mut bytes = Vec::new();
5067 if rdlo != rn {
5068 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5070 rd: *rdlo,
5071 op2: Operand2::Reg(*rn),
5072 })?);
5073 }
5074 bytes.extend_from_slice(
5076 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5078 Ok(bytes)
5079 }
5080
5081 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5083 let mut bytes = Vec::new();
5084 if rdlo != rn {
5085 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5087 rd: *rdlo,
5088 op2: Operand2::Reg(*rn),
5089 })?);
5090 }
5091 let rdhi_bits = reg_to_bits(rdhi) as u16;
5093 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5094 bytes.extend_from_slice(&instr.to_le_bytes());
5095 Ok(bytes)
5096 }
5097
5098 ArmOp::I32WrapI64 { rd, rnlo } => {
5100 if rd == rnlo {
5101 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5104 } else {
5105 self.encode_thumb(&ArmOp::Mov {
5107 rd: *rd,
5108 op2: Operand2::Reg(*rnlo),
5109 })
5110 }
5111 }
5112
5113 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5115 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5116 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5117 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5118 0xEF000150, qd, qn, qm,
5119 ))),
5120 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5121 0xEF200150, qd, qn, qm,
5122 ))),
5123 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5124 0xFF000150, qd, qn, qm,
5125 ))),
5126 ArmOp::MveMvn { qd, qm } => {
5127 let qd_enc = qreg_to_num(qd);
5129 let qm_enc = qreg_to_num(qm);
5130 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5131 Ok(vfp_to_thumb_bytes(instr))
5132 }
5133 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5134 0xEF100150, qd, qn, qm,
5135 ))),
5136 ArmOp::MveAddI { qd, qn, qm, size } => {
5137 let sz = mve_size_bits(size);
5138 let base: u32 = 0xEF000840 | (sz << 20);
5139 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5140 }
5141 ArmOp::MveSubI { qd, qn, qm, size } => {
5142 let sz = mve_size_bits(size);
5143 let base: u32 = 0xFF000840 | (sz << 20);
5144 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5145 }
5146 ArmOp::MveMulI { qd, qn, qm, size } => {
5147 let sz = mve_size_bits(size);
5148 let base: u32 = 0xEF000950 | (sz << 20);
5149 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5150 }
5151 ArmOp::MveNegI { qd, qm, size } => {
5152 let sz = mve_size_bits(size);
5153 let qd_enc = qreg_to_num(qd);
5155 let qm_enc = qreg_to_num(qm);
5156 let base: u32 = 0xFFB103C0 | (sz << 18);
5157 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5158 Ok(vfp_to_thumb_bytes(instr))
5159 }
5160 ArmOp::MveDup { qd, rn, size } => {
5161 let sz = mve_size_bits(size);
5162 let qd_enc = qreg_to_num(qd);
5163 let rn_bits = reg_to_bits(rn);
5164 let be = match sz {
5167 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5171 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5172 Ok(vfp_to_thumb_bytes(instr))
5173 }
5174 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5175 let qn_enc = qreg_to_num(qn);
5176 let rd_bits = reg_to_bits(rd);
5177 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5180 let lane_in_d = (*lane as u32) & 1;
5181 let _sz = mve_size_bits(size);
5182 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5184 Ok(vfp_to_thumb_bytes(instr))
5185 }
5186 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5187 let qd_enc = qreg_to_num(qd);
5188 let rn_bits = reg_to_bits(rn);
5189 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5190 let lane_in_d = (*lane as u32) & 1;
5191 let _sz = mve_size_bits(size);
5192 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5194 Ok(vfp_to_thumb_bytes(instr))
5195 }
5196
5197 ArmOp::MveCmpEqI { qd, qn, qm, size }
5199 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5200 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5201 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5202 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5203 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5204 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5205 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5206 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5207 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5208 let sz = mve_size_bits(size);
5211 let base: u32 = 0xEF000840 | (sz << 20);
5212 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5213 }
5214
5215 ArmOp::MveAddF32 { qd, qn, qm } => {
5217 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5219 }
5220 ArmOp::MveSubF32 { qd, qn, qm } => {
5221 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5223 }
5224 ArmOp::MveMulF32 { qd, qn, qm } => {
5225 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5227 }
5228 ArmOp::MveNegF32 { qd, qm } => {
5229 let qd_enc = qreg_to_num(qd);
5230 let qm_enc = qreg_to_num(qm);
5231 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5233 Ok(vfp_to_thumb_bytes(instr))
5234 }
5235 ArmOp::MveAbsF32 { qd, qm } => {
5236 let qd_enc = qreg_to_num(qd);
5237 let qm_enc = qreg_to_num(qm);
5238 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5240 Ok(vfp_to_thumb_bytes(instr))
5241 }
5242 ArmOp::MveCmpEqF32 { qd, qn, qm }
5243 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5244 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5245 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5246 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5247 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5248 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5250 }
5251 ArmOp::MveDupF32 { qd, rn } => {
5252 let qd_enc = qreg_to_num(qd);
5253 let rn_bits = reg_to_bits(rn);
5254 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5256 Ok(vfp_to_thumb_bytes(instr))
5257 }
5258 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5259 let qn_enc = qreg_to_num(qn);
5260 let rd_bits = reg_to_bits(rd);
5261 let s_num = qn_enc * 4 + (*lane as u32);
5263 let (vn, n) = encode_sreg(s_num);
5264 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5265 Ok(vfp_to_thumb_bytes(instr))
5266 }
5267 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5268 let qd_enc = qreg_to_num(qd);
5269 let rn_bits = reg_to_bits(rn);
5270 let s_num = qd_enc * 4 + (*lane as u32);
5272 let (vn, n) = encode_sreg(s_num);
5273 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5274 Ok(vfp_to_thumb_bytes(instr))
5275 }
5276 ArmOp::MveDivF32 { qd, qn, qm } => {
5277 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5279 }
5280 ArmOp::MveSqrtF32 { qd, qm } => {
5281 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5283 }
5284
5285 _ => {
5287 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5289 }
5290 }
5291 }
5292
5293 fn encode_thumb_f32_compare(
5297 &self,
5298 rd: &Reg,
5299 sn: &VfpReg,
5300 sm: &VfpReg,
5301 cond_code: u32,
5302 ) -> Result<Vec<u8>> {
5303 let mut bytes = Vec::new();
5304 let rd_bits = reg_to_bits(rd);
5305
5306 let sn_num = vfp_sreg_to_num(sn)?;
5308 let sm_num = vfp_sreg_to_num(sm)?;
5309 let (vd, d) = encode_sreg(sn_num);
5310 let (vm, m) = encode_sreg(sm_num);
5311 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5312 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5313
5314 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5316
5317 if rd_bits < 8 {
5319 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5320 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5321 } else {
5322 let hw1: u16 = 0xF04F;
5324 let hw2: u16 = (rd_bits as u16) << 8;
5325 bytes.extend_from_slice(&hw1.to_le_bytes());
5326 bytes.extend_from_slice(&hw2.to_le_bytes());
5327 }
5328
5329 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5333 bytes.extend_from_slice(&it.to_le_bytes());
5334
5335 if rd_bits < 8 {
5337 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5338 bytes.extend_from_slice(&mov_one.to_le_bytes());
5339 } else {
5340 let hw1: u16 = 0xF04F;
5342 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5343 bytes.extend_from_slice(&hw1.to_le_bytes());
5344 bytes.extend_from_slice(&hw2.to_le_bytes());
5345 }
5346
5347 Ok(bytes)
5348 }
5349
5350 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5352 let mut bytes = Vec::new();
5353 let bits = value.to_bits();
5354 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5359 let imm4 = (lo16 >> 12) & 0xF;
5360 let i_bit = (lo16 >> 11) & 1;
5361 let imm3 = (lo16 >> 8) & 0x7;
5362 let imm8 = lo16 & 0xFF;
5363 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5364 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5365 bytes.extend_from_slice(&hw1.to_le_bytes());
5366 bytes.extend_from_slice(&hw2.to_le_bytes());
5367
5368 let hi16 = (bits >> 16) & 0xFFFF;
5370 let imm4 = (hi16 >> 12) & 0xF;
5371 let i_bit = (hi16 >> 11) & 1;
5372 let imm3 = (hi16 >> 8) & 0x7;
5373 let imm8 = hi16 & 0xFF;
5374 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5375 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5376 bytes.extend_from_slice(&hw1.to_le_bytes());
5377 bytes.extend_from_slice(&hw2.to_le_bytes());
5378
5379 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5381 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5382
5383 Ok(bytes)
5384 }
5385
5386 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5388 let mut bytes = Vec::new();
5389
5390 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5392 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5393
5394 let sd_num = vfp_sreg_to_num(sd)?;
5396 let (vd, d) = encode_sreg(sd_num);
5397 let (vm, m) = encode_sreg(sd_num);
5398 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5399 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5400 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5401
5402 Ok(bytes)
5403 }
5404
5405 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5413 let mut bytes = Vec::new();
5414 let sm_num = vfp_sreg_to_num(sm)?;
5415 let sd_num = vfp_sreg_to_num(sd)?;
5416 let (vd_s, d_s) = encode_sreg(sd_num);
5417 let (vm_s, m_s) = encode_sreg(sm_num);
5418
5419 if mode == 0b11 {
5420 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5422 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5423 } else {
5424 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5429 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5430
5431 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5437 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5438 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5439
5440 if mode != 0 {
5442 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5444 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5445 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5446 }
5447
5448 let vmsr = 0xEEE10A10 | (rt << 12);
5450 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5451
5452 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5454 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5455
5456 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5458 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5459 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5460 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5461 }
5462
5463 let (vd2, d2) = encode_sreg(sd_num);
5465 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5466 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5467
5468 Ok(bytes)
5469 }
5470
5471 fn encode_thumb_f32_minmax(
5473 &self,
5474 sd: &VfpReg,
5475 sn: &VfpReg,
5476 sm: &VfpReg,
5477 is_min: bool,
5478 ) -> Result<Vec<u8>> {
5479 let mut bytes = Vec::new();
5480 let sn_num = vfp_sreg_to_num(sn)?;
5481 let sm_num = vfp_sreg_to_num(sm)?;
5482 let sd_num = vfp_sreg_to_num(sd)?;
5483
5484 let (vd, d) = encode_sreg(sd_num);
5486 let (vn, n) = encode_sreg(sn_num);
5487 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5488 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5489
5490 let (vm, m) = encode_sreg(sm_num);
5492 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5493 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5494
5495 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5497
5498 let cond: u16 = if is_min { 0xC } else { 0x4 };
5500 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5501 bytes.extend_from_slice(&it.to_le_bytes());
5502
5503 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5505 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5506
5507 Ok(bytes)
5508 }
5509
5510 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5512 let mut bytes = Vec::new();
5513
5514 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5516 false,
5517 sm,
5518 &Reg::R12,
5519 )?));
5520
5521 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5523 false,
5524 sn,
5525 &Reg::R0,
5526 )?));
5527
5528 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5540 bytes.extend_from_slice(&hw2.to_le_bytes());
5541
5542 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5546 bytes.extend_from_slice(&hw2.to_le_bytes());
5547
5548 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5552 bytes.extend_from_slice(&hw2.to_le_bytes());
5553
5554 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5556 true,
5557 sd,
5558 &Reg::R0,
5559 )?));
5560
5561 Ok(bytes)
5562 }
5563
5564 fn encode_thumb_f64_compare(
5566 &self,
5567 rd: &Reg,
5568 dn: &VfpReg,
5569 dm: &VfpReg,
5570 cond_code: u32,
5571 ) -> Result<Vec<u8>> {
5572 let mut bytes = Vec::new();
5573 let rd_bits = reg_to_bits(rd);
5574
5575 let dn_num = vfp_dreg_to_num(dn)?;
5577 let dm_num = vfp_dreg_to_num(dm)?;
5578 let (vd, d) = encode_dreg(dn_num);
5579 let (vm, m) = encode_dreg(dm_num);
5580 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5581 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5582
5583 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5585
5586 if rd_bits < 8 {
5588 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5589 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5590 } else {
5591 let hw1: u16 = 0xF04F;
5592 let hw2: u16 = (rd_bits as u16) << 8;
5593 bytes.extend_from_slice(&hw1.to_le_bytes());
5594 bytes.extend_from_slice(&hw2.to_le_bytes());
5595 }
5596
5597 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5599 bytes.extend_from_slice(&it.to_le_bytes());
5600
5601 if rd_bits < 8 {
5603 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5604 bytes.extend_from_slice(&mov_one.to_le_bytes());
5605 } else {
5606 let hw1: u16 = 0xF04F;
5607 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5608 bytes.extend_from_slice(&hw1.to_le_bytes());
5609 bytes.extend_from_slice(&hw2.to_le_bytes());
5610 }
5611
5612 Ok(bytes)
5613 }
5614
5615 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5617 let mut bytes = Vec::new();
5618 let bits = value.to_bits();
5619 let lo32 = bits as u32;
5620 let hi32 = (bits >> 32) as u32;
5621
5622 let lo16 = lo32 & 0xFFFF;
5624 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5625
5626 let hi16 = (lo32 >> 16) & 0xFFFF;
5628 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5629
5630 let lo16 = hi32 & 0xFFFF;
5632 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5633
5634 let hi16 = (hi32 >> 16) & 0xFFFF;
5636 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5637
5638 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5640 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5641
5642 Ok(bytes)
5643 }
5644
5645 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5647 let mut bytes = Vec::new();
5648
5649 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5651 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5652
5653 let dd_num = vfp_dreg_to_num(dd)?;
5655 let (vd, d) = encode_dreg(dd_num);
5656 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5657 let vcvt = base | (d << 22) | (vd << 12);
5658 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5659
5660 Ok(bytes)
5661 }
5662
5663 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5665 let dd_num = vfp_dreg_to_num(dd)?;
5666 let sm_num = vfp_sreg_to_num(sm)?;
5667 let (vd, d) = encode_dreg(dd_num);
5668 let (vm, m) = encode_sreg(sm_num);
5669
5670 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5671 Ok(vfp_to_thumb_bytes(vcvt))
5672 }
5673
5674 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5676 let mut bytes = Vec::new();
5677 let dm_num = vfp_dreg_to_num(dm)?;
5678 let (vm, m) = encode_dreg(dm_num);
5679
5680 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5682 let vcvt = base | (m << 5) | vm;
5683 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5684
5685 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5687 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5688
5689 Ok(bytes)
5690 }
5691
5692 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5696 let mut bytes = Vec::new();
5697 let dm_num = vfp_dreg_to_num(dm)?;
5698 let dd_num = vfp_dreg_to_num(dd)?;
5699 let (vm, m) = encode_dreg(dm_num);
5700 let (vd, d) = encode_dreg(dd_num);
5701
5702 if mode == 0b11 {
5703 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5705 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5706 } else {
5707 let rt: u32 = 12;
5708
5709 let vmrs = 0xEEF10A10 | (rt << 12);
5711 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5712
5713 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5715 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5716 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5717 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5718
5719 if mode != 0 {
5721 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5722 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5723 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5724 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5725 }
5726
5727 let vmsr = 0xEEE10A10 | (rt << 12);
5729 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5730
5731 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5733 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5734
5735 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5737 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5738 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5739 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5740 }
5741
5742 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5744 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5745
5746 Ok(bytes)
5747 }
5748
5749 fn encode_thumb_f64_minmax(
5751 &self,
5752 dd: &VfpReg,
5753 dn: &VfpReg,
5754 dm: &VfpReg,
5755 is_min: bool,
5756 ) -> Result<Vec<u8>> {
5757 let mut bytes = Vec::new();
5758 let dn_num = vfp_dreg_to_num(dn)?;
5759 let dm_num = vfp_dreg_to_num(dm)?;
5760 let dd_num = vfp_dreg_to_num(dd)?;
5761
5762 let (vd, d) = encode_dreg(dd_num);
5764 let (vn, n) = encode_dreg(dn_num);
5765 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5766 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5767
5768 let (vm, m) = encode_dreg(dm_num);
5770 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5771 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5772
5773 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5775
5776 let cond: u16 = if is_min { 0xC } else { 0x4 };
5778 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5779 bytes.extend_from_slice(&it.to_le_bytes());
5780
5781 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5783 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5784
5785 Ok(bytes)
5786 }
5787
5788 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5790 let mut bytes = Vec::new();
5791
5792 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5794 false,
5795 dm,
5796 &Reg::R0,
5797 &Reg::R12,
5798 )?));
5799
5800 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5802 false,
5803 dn,
5804 &Reg::R1,
5805 &Reg::R2,
5806 )?));
5807
5808 let hw1: u16 = 0xF000 | 12;
5810 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5811 bytes.extend_from_slice(&hw1.to_le_bytes());
5812 bytes.extend_from_slice(&hw2.to_le_bytes());
5813
5814 let hw1: u16 = 0xF020 | 2;
5816 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5817 bytes.extend_from_slice(&hw1.to_le_bytes());
5818 bytes.extend_from_slice(&hw2.to_le_bytes());
5819
5820 let hw1: u16 = 0xEA40 | 2;
5822 let hw2: u16 = (2 << 8) | 12;
5823 bytes.extend_from_slice(&hw1.to_le_bytes());
5824 bytes.extend_from_slice(&hw2.to_le_bytes());
5825
5826 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5828 true,
5829 dd,
5830 &Reg::R1,
5831 &Reg::R2,
5832 )?));
5833
5834 Ok(bytes)
5835 }
5836
5837 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5839 let mut bytes = Vec::new();
5840
5841 let sm_num = vfp_sreg_to_num(sm)?;
5842 let (vd, d) = encode_sreg(sm_num);
5843 let (vm, m) = encode_sreg(sm_num);
5844 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5845 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5846 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5847
5848 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5850 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5851
5852 Ok(bytes)
5853 }
5854
5855 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5859 let rd_bits = reg_to_bits(rd);
5860 let rn_bits = reg_to_bits(rn);
5861
5862 let i_bit = (imm >> 11) & 1;
5866 let imm3 = (imm >> 8) & 0x7;
5867 let imm8 = imm & 0xFF;
5868
5869 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5870 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5871
5872 let mut bytes = hw1.to_le_bytes().to_vec();
5873 bytes.extend_from_slice(&hw2.to_le_bytes());
5874 Ok(bytes)
5875 }
5876
5877 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5879 let rd_bits = reg_to_bits(rd);
5880 let rn_bits = reg_to_bits(rn);
5881
5882 let i_bit = (imm >> 11) & 1;
5883 let imm3 = (imm >> 8) & 0x7;
5884 let imm8 = imm & 0xFF;
5885
5886 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5887 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5888
5889 let mut bytes = hw1.to_le_bytes().to_vec();
5890 bytes.extend_from_slice(&hw2.to_le_bytes());
5891 Ok(bytes)
5892 }
5893
5894 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5896 let rd_bits = reg_to_bits(rd);
5897 let rn_bits = reg_to_bits(rn);
5898
5899 let i_bit = (imm >> 11) & 1;
5900 let imm3 = (imm >> 8) & 0x7;
5901 let imm8 = imm & 0xFF;
5902
5903 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
5906 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5907
5908 let mut bytes = hw1.to_le_bytes().to_vec();
5909 bytes.extend_from_slice(&hw2.to_le_bytes());
5910 Ok(bytes)
5911 }
5912
5913 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5915 let rd_bits = reg_to_bits(rd);
5916 let rn_bits = reg_to_bits(rn);
5917
5918 let i_bit = (imm >> 11) & 1;
5919 let imm3 = (imm >> 8) & 0x7;
5920 let imm8 = imm & 0xFF;
5921
5922 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
5925 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5926
5927 let mut bytes = hw1.to_le_bytes().to_vec();
5928 bytes.extend_from_slice(&hw2.to_le_bytes());
5929 Ok(bytes)
5930 }
5931
5932 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
5941 let rd_bits = reg_to_bits(rd);
5942 reg_bits_checked(rd_bits)?;
5943 let imm16 = imm & 0xFFFF;
5944
5945 let imm4 = (imm16 >> 12) & 0xF;
5948 let i_bit = (imm16 >> 11) & 1;
5949 let imm3 = (imm16 >> 8) & 0x7;
5950 let imm8 = imm16 & 0xFF;
5951
5952 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5953 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5954
5955 let mut bytes = hw1.to_le_bytes().to_vec();
5956 bytes.extend_from_slice(&hw2.to_le_bytes());
5957 encoding_contracts::verify_thumb32(&bytes);
5958 Ok(bytes)
5959 }
5960
5961 fn encode_thumb32_shift(
5969 &self,
5970 rd: &Reg,
5971 rm: &Reg,
5972 shift: u32,
5973 shift_type: u8,
5974 ) -> Result<Vec<u8>> {
5975 let rd_bits = reg_to_bits(rd);
5976 let rm_bits = reg_to_bits(rm);
5977 reg_bits_checked(rd_bits)?;
5978 reg_bits_checked(rm_bits)?;
5979 let imm5 = shift & 0x1F;
5980 let imm2 = imm5 & 0x3;
5981 let imm3 = (imm5 >> 2) & 0x7;
5982
5983 let hw1: u16 = 0xEA4F;
5986 let hw2: u16 =
5987 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
5988 as u16;
5989
5990 let mut bytes = hw1.to_le_bytes().to_vec();
5991 bytes.extend_from_slice(&hw2.to_le_bytes());
5992 Ok(bytes)
5993 }
5994
5995 fn encode_thumb32_shift_reg(
5999 &self,
6000 rd: &Reg,
6001 rn: &Reg,
6002 rm: &Reg,
6003 shift_type: u8,
6004 ) -> Result<Vec<u8>> {
6005 let rd_bits = reg_to_bits(rd);
6006 let rn_bits = reg_to_bits(rn);
6007 let rm_bits = reg_to_bits(rm);
6008
6009 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6011 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6013
6014 let mut bytes = hw1.to_le_bytes().to_vec();
6015 bytes.extend_from_slice(&hw2.to_le_bytes());
6016 Ok(bytes)
6017 }
6018
6019 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6021 let rn_bits = reg_to_bits(rn);
6022
6023 let i_bit = (imm >> 11) & 1;
6024 let imm3 = (imm >> 8) & 0x7;
6025 let imm8 = imm & 0xFF;
6026
6027 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6029 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6030
6031 let mut bytes = hw1.to_le_bytes().to_vec();
6032 bytes.extend_from_slice(&hw2.to_le_bytes());
6033 Ok(bytes)
6034 }
6035
6036 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6038 let rd_bits = reg_to_bits(rd);
6039 let base_bits = reg_to_bits(base);
6040
6041 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6043 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6044
6045 let mut bytes = hw1.to_le_bytes().to_vec();
6046 bytes.extend_from_slice(&hw2.to_le_bytes());
6047 Ok(bytes)
6048 }
6049
6050 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6052 let rd_bits = reg_to_bits(rd);
6053 let base_bits = reg_to_bits(base);
6054
6055 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6057 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6058
6059 let mut bytes = hw1.to_le_bytes().to_vec();
6060 bytes.extend_from_slice(&hw2.to_le_bytes());
6061 Ok(bytes)
6062 }
6063
6064 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6066 let rd_bits = reg_to_bits(rd);
6067 let base_bits = reg_to_bits(base);
6068 let rm_bits = reg_to_bits(offset_reg);
6069
6070 let hw1: u16 = (0xF850 | base_bits) as u16;
6074 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6075
6076 let mut bytes = hw1.to_le_bytes().to_vec();
6077 bytes.extend_from_slice(&hw2.to_le_bytes());
6078 Ok(bytes)
6079 }
6080
6081 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6083 let rd_bits = reg_to_bits(rd);
6084 let base_bits = reg_to_bits(base);
6085 let rm_bits = reg_to_bits(offset_reg);
6086
6087 let hw1: u16 = (0xF840 | base_bits) as u16;
6091 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6092
6093 let mut bytes = hw1.to_le_bytes().to_vec();
6094 bytes.extend_from_slice(&hw2.to_le_bytes());
6095 Ok(bytes)
6096 }
6097
6098 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6102 let rd_bits = reg_to_bits(rd);
6103 let base_bits = reg_to_bits(base);
6104 let hw1: u16 = (0xF890 | base_bits) as u16;
6106 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6107 let mut bytes = hw1.to_le_bytes().to_vec();
6108 bytes.extend_from_slice(&hw2.to_le_bytes());
6109 Ok(bytes)
6110 }
6111
6112 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6114 let rd_bits = reg_to_bits(rd);
6115 let base_bits = reg_to_bits(base);
6116 let rm_bits = reg_to_bits(offset_reg);
6117 let hw1: u16 = (0xF810 | base_bits) as u16;
6119 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6120 let mut bytes = hw1.to_le_bytes().to_vec();
6121 bytes.extend_from_slice(&hw2.to_le_bytes());
6122 Ok(bytes)
6123 }
6124
6125 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6127 let rd_bits = reg_to_bits(rd);
6128 let base_bits = reg_to_bits(base);
6129 let hw1: u16 = (0xF990 | base_bits) as u16;
6131 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6132 let mut bytes = hw1.to_le_bytes().to_vec();
6133 bytes.extend_from_slice(&hw2.to_le_bytes());
6134 Ok(bytes)
6135 }
6136
6137 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6139 let rd_bits = reg_to_bits(rd);
6140 let base_bits = reg_to_bits(base);
6141 let rm_bits = reg_to_bits(offset_reg);
6142 let hw1: u16 = (0xF910 | base_bits) as u16;
6144 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6145 let mut bytes = hw1.to_le_bytes().to_vec();
6146 bytes.extend_from_slice(&hw2.to_le_bytes());
6147 Ok(bytes)
6148 }
6149
6150 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6152 let rd_bits = reg_to_bits(rd);
6153 let base_bits = reg_to_bits(base);
6154 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6156 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6157 let mut bytes = hw1.to_le_bytes().to_vec();
6158 bytes.extend_from_slice(&hw2.to_le_bytes());
6159 Ok(bytes)
6160 }
6161
6162 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6164 let rd_bits = reg_to_bits(rd);
6165 let base_bits = reg_to_bits(base);
6166 let rm_bits = reg_to_bits(offset_reg);
6167 let hw1: u16 = (0xF830 | base_bits) as u16;
6169 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6170 let mut bytes = hw1.to_le_bytes().to_vec();
6171 bytes.extend_from_slice(&hw2.to_le_bytes());
6172 Ok(bytes)
6173 }
6174
6175 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6177 let rd_bits = reg_to_bits(rd);
6178 let base_bits = reg_to_bits(base);
6179 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6181 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6182 let mut bytes = hw1.to_le_bytes().to_vec();
6183 bytes.extend_from_slice(&hw2.to_le_bytes());
6184 Ok(bytes)
6185 }
6186
6187 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6189 let rd_bits = reg_to_bits(rd);
6190 let base_bits = reg_to_bits(base);
6191 let rm_bits = reg_to_bits(offset_reg);
6192 let hw1: u16 = (0xF930 | base_bits) as u16;
6194 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6195 let mut bytes = hw1.to_le_bytes().to_vec();
6196 bytes.extend_from_slice(&hw2.to_le_bytes());
6197 Ok(bytes)
6198 }
6199
6200 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6202 let rd_bits = reg_to_bits(rd);
6203 let base_bits = reg_to_bits(base);
6204 let hw1: u16 = (0xF880 | base_bits) as u16;
6206 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6207 let mut bytes = hw1.to_le_bytes().to_vec();
6208 bytes.extend_from_slice(&hw2.to_le_bytes());
6209 Ok(bytes)
6210 }
6211
6212 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6214 let rd_bits = reg_to_bits(rd);
6215 let base_bits = reg_to_bits(base);
6216 let rm_bits = reg_to_bits(offset_reg);
6217 let hw1: u16 = (0xF800 | base_bits) as u16;
6219 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6220 let mut bytes = hw1.to_le_bytes().to_vec();
6221 bytes.extend_from_slice(&hw2.to_le_bytes());
6222 Ok(bytes)
6223 }
6224
6225 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6227 let rd_bits = reg_to_bits(rd);
6228 let base_bits = reg_to_bits(base);
6229 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6231 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6232 let mut bytes = hw1.to_le_bytes().to_vec();
6233 bytes.extend_from_slice(&hw2.to_le_bytes());
6234 Ok(bytes)
6235 }
6236
6237 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6239 let rd_bits = reg_to_bits(rd);
6240 let base_bits = reg_to_bits(base);
6241 let rm_bits = reg_to_bits(offset_reg);
6242 let hw1: u16 = (0xF820 | base_bits) as u16;
6244 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6245 let mut bytes = hw1.to_le_bytes().to_vec();
6246 bytes.extend_from_slice(&hw2.to_le_bytes());
6247 Ok(bytes)
6248 }
6249
6250 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6252 let rd_bits = reg_to_bits(rd);
6253 let rn_bits = reg_to_bits(rn);
6254
6255 if imm <= 0xFFF {
6261 let i_bit = (imm >> 11) & 1;
6262 let imm3 = (imm >> 8) & 0x7;
6263 let imm8 = imm & 0xFF;
6264
6265 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6266 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6267
6268 let mut bytes = hw1.to_le_bytes().to_vec();
6269 bytes.extend_from_slice(&hw2.to_le_bytes());
6270 Ok(bytes)
6271 } else {
6272 Err(synth_core::Error::synthesis(
6275 "ADD immediate too large for single instruction",
6276 ))
6277 }
6278 }
6279
6280 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6290 reg_bits_checked(rd)?;
6291 encoding_contracts::verify_imm16(imm16);
6292 let imm16 = imm16 & 0xFFFF;
6295 let imm4 = (imm16 >> 12) & 0xF;
6296 let i_bit = (imm16 >> 11) & 1;
6297 let imm3 = (imm16 >> 8) & 0x7;
6298 let imm8 = imm16 & 0xFF;
6299
6300 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6301 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6302
6303 let mut bytes = hw1.to_le_bytes().to_vec();
6304 bytes.extend_from_slice(&hw2.to_le_bytes());
6305 encoding_contracts::verify_thumb32(&bytes);
6306 Ok(bytes)
6307 }
6308
6309 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6317 reg_bits_checked(rd)?;
6318 encoding_contracts::verify_imm16(imm16);
6319 let imm16 = imm16 & 0xFFFF;
6322 let imm4 = (imm16 >> 12) & 0xF;
6323 let i_bit = (imm16 >> 11) & 1;
6324 let imm3 = (imm16 >> 8) & 0x7;
6325 let imm8 = imm16 & 0xFF;
6326
6327 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6328 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6329
6330 let mut bytes = hw1.to_le_bytes().to_vec();
6331 bytes.extend_from_slice(&hw2.to_le_bytes());
6332 encoding_contracts::verify_thumb32(&bytes);
6333 Ok(bytes)
6334 }
6335
6336 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6338 let imm5 = shift & 0x1F;
6341 let imm2 = imm5 & 0x3;
6342 let imm3 = (imm5 >> 2) & 0x7;
6343
6344 let hw1: u16 = 0xEA4F;
6345 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6346
6347 let mut bytes = hw1.to_le_bytes().to_vec();
6348 bytes.extend_from_slice(&hw2.to_le_bytes());
6349 Ok(bytes)
6350 }
6351
6352 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6354 let hw1: u16 = (0xEA00 | rn) as u16;
6357 let hw2: u16 = ((rd << 8) | rm) as u16;
6358
6359 let mut bytes = hw1.to_le_bytes().to_vec();
6360 bytes.extend_from_slice(&hw2.to_le_bytes());
6361 Ok(bytes)
6362 }
6363
6364 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6366 let i_bit = (imm >> 11) & 1;
6370 let imm3 = (imm >> 8) & 0x7;
6371 let imm8 = imm & 0xFF;
6372
6373 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6374 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6375
6376 let mut bytes = hw1.to_le_bytes().to_vec();
6377 bytes.extend_from_slice(&hw2.to_le_bytes());
6378 Ok(bytes)
6379 }
6380
6381 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6383 let hw1: u16 = (0xEBA0 | rn) as u16;
6386 let hw2: u16 = ((rd << 8) | rm) as u16;
6387
6388 let mut bytes = hw1.to_le_bytes().to_vec();
6389 bytes.extend_from_slice(&hw2.to_le_bytes());
6390 Ok(bytes)
6391 }
6392
6393 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6395 let hw1: u16 = (0xEB00 | rn) as u16;
6398 let hw2: u16 = ((rd << 8) | rm) as u16;
6399
6400 let mut bytes = hw1.to_le_bytes().to_vec();
6401 bytes.extend_from_slice(&hw2.to_le_bytes());
6402 Ok(bytes)
6403 }
6404
6405 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6409 let hw1: u16 = (0xEB10 | rn) as u16;
6411 let hw2: u16 = ((rd << 8) | rm) as u16;
6412 let mut bytes = hw1.to_le_bytes().to_vec();
6413 bytes.extend_from_slice(&hw2.to_le_bytes());
6414 Ok(bytes)
6415 }
6416
6417 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6420 let hw1: u16 = (0xEBB0 | rn) as u16;
6422 let hw2: u16 = ((rd << 8) | rm) as u16;
6423 let mut bytes = hw1.to_le_bytes().to_vec();
6424 bytes.extend_from_slice(&hw2.to_le_bytes());
6425 Ok(bytes)
6426 }
6427
6428 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6430 let mut code = Vec::new();
6431
6432 for op in ops {
6433 let encoded = self.encode(op)?;
6434 code.extend_from_slice(&encoded);
6435 }
6436
6437 Ok(code)
6438 }
6439}
6440
6441fn reg_to_bits(reg: &Reg) -> u32 {
6443 match reg {
6444 Reg::R0 => 0,
6445 Reg::R1 => 1,
6446 Reg::R2 => 2,
6447 Reg::R3 => 3,
6448 Reg::R4 => 4,
6449 Reg::R5 => 5,
6450 Reg::R6 => 6,
6451 Reg::R7 => 7,
6452 Reg::R8 => 8,
6453 Reg::R9 => 9,
6454 Reg::R10 => 10,
6455 Reg::R11 => 11,
6456 Reg::R12 => 12,
6457 Reg::SP => 13,
6458 Reg::LR => 14,
6459 Reg::PC => 15,
6460 }
6461}
6462
6463fn reg_bits_checked(bits: u32) -> Result<()> {
6471 if bits > 14 {
6472 return Err(synth_core::Error::synthesis(format!(
6473 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6474 )));
6475 }
6476 Ok(())
6477}
6478
6479fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6482 if val == 0 {
6483 return Some((0, 1));
6484 }
6485 for rot in 0..16u32 {
6486 let shift = rot * 2;
6487 let unrotated = val.rotate_left(shift);
6489 if unrotated <= 0xFF {
6490 return Some(((rot << 8) | unrotated, 1));
6492 }
6493 }
6494 None
6495}
6496
6497fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6502 match op2 {
6503 Operand2::Imm(val) => {
6504 let uval = *val as u32;
6505 if let Some(encoded) = try_encode_rotated_imm(uval) {
6507 encoded
6508 } else {
6509 let imm = uval & 0xFF;
6514 (imm, 1)
6515 }
6516 }
6517
6518 Operand2::Reg(reg) => {
6519 let reg_bits = reg_to_bits(reg);
6520 (reg_bits, 0) }
6522
6523 Operand2::RegShift {
6524 rm,
6525 shift: _,
6526 amount,
6527 } => {
6528 let rm_bits = reg_to_bits(rm);
6530 let shift_bits = (*amount & 0x1F) << 7;
6531 (shift_bits | rm_bits, 0)
6532 }
6533 }
6534}
6535
6536fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6538 let base_bits = reg_to_bits(&addr.base);
6539 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6541}
6542
6543fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6545 match reg {
6546 VfpReg::S0 => Ok(0),
6547 VfpReg::S1 => Ok(1),
6548 VfpReg::S2 => Ok(2),
6549 VfpReg::S3 => Ok(3),
6550 VfpReg::S4 => Ok(4),
6551 VfpReg::S5 => Ok(5),
6552 VfpReg::S6 => Ok(6),
6553 VfpReg::S7 => Ok(7),
6554 VfpReg::S8 => Ok(8),
6555 VfpReg::S9 => Ok(9),
6556 VfpReg::S10 => Ok(10),
6557 VfpReg::S11 => Ok(11),
6558 VfpReg::S12 => Ok(12),
6559 VfpReg::S13 => Ok(13),
6560 VfpReg::S14 => Ok(14),
6561 VfpReg::S15 => Ok(15),
6562 VfpReg::S16 => Ok(16),
6563 VfpReg::S17 => Ok(17),
6564 VfpReg::S18 => Ok(18),
6565 VfpReg::S19 => Ok(19),
6566 VfpReg::S20 => Ok(20),
6567 VfpReg::S21 => Ok(21),
6568 VfpReg::S22 => Ok(22),
6569 VfpReg::S23 => Ok(23),
6570 VfpReg::S24 => Ok(24),
6571 VfpReg::S25 => Ok(25),
6572 VfpReg::S26 => Ok(26),
6573 VfpReg::S27 => Ok(27),
6574 VfpReg::S28 => Ok(28),
6575 VfpReg::S29 => Ok(29),
6576 VfpReg::S30 => Ok(30),
6577 VfpReg::S31 => Ok(31),
6578 _ => Err(synth_core::Error::SynthesisError(
6580 "D-register not supported in single-precision VFP encoding".to_string(),
6581 )),
6582 }
6583}
6584
6585fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6587 match reg {
6588 VfpReg::D0 => Ok(0),
6589 VfpReg::D1 => Ok(1),
6590 VfpReg::D2 => Ok(2),
6591 VfpReg::D3 => Ok(3),
6592 VfpReg::D4 => Ok(4),
6593 VfpReg::D5 => Ok(5),
6594 VfpReg::D6 => Ok(6),
6595 VfpReg::D7 => Ok(7),
6596 VfpReg::D8 => Ok(8),
6597 VfpReg::D9 => Ok(9),
6598 VfpReg::D10 => Ok(10),
6599 VfpReg::D11 => Ok(11),
6600 VfpReg::D12 => Ok(12),
6601 VfpReg::D13 => Ok(13),
6602 VfpReg::D14 => Ok(14),
6603 VfpReg::D15 => Ok(15),
6604 _ => Err(synth_core::Error::SynthesisError(
6606 "S-register not supported in double-precision VFP encoding".to_string(),
6607 )),
6608 }
6609}
6610
6611fn encode_sreg(s: u32) -> (u32, u32) {
6615 (s >> 1, s & 1)
6616}
6617
6618fn encode_dreg(d: u32) -> (u32, u32) {
6622 (d & 0xF, (d >> 4) & 1)
6623}
6624
6625fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6631 let sd_num = vfp_sreg_to_num(sd)?;
6632 let sn_num = vfp_sreg_to_num(sn)?;
6633 let sm_num = vfp_sreg_to_num(sm)?;
6634 let (vd, d) = encode_sreg(sd_num);
6635 let (vn, n) = encode_sreg(sn_num);
6636 let (vm, m) = encode_sreg(sm_num);
6637
6638 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6639}
6640
6641fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6644 let sd_num = vfp_sreg_to_num(sd)?;
6645 let sm_num = vfp_sreg_to_num(sm)?;
6646 let (vd, d) = encode_sreg(sd_num);
6647 let (vm, m) = encode_sreg(sm_num);
6648
6649 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6650}
6651
6652fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6656 let sd_num = vfp_sreg_to_num(sd)?;
6657 let (vd, d) = encode_sreg(sd_num);
6658 let rn = reg_to_bits(&addr.base);
6659
6660 let offset = addr.offset;
6661 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6662 let abs_offset = offset.unsigned_abs();
6663 let imm8 = (abs_offset / 4) & 0xFF;
6664
6665 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6666}
6667
6668fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6672 let s_num = vfp_sreg_to_num(sreg)?;
6673 let (vn, n) = encode_sreg(s_num);
6674 let rt = reg_to_bits(core);
6675
6676 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6677 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6678}
6679
6680fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6684 let dd_num = vfp_dreg_to_num(dd)?;
6685 let dn_num = vfp_dreg_to_num(dn)?;
6686 let dm_num = vfp_dreg_to_num(dm)?;
6687 let (vd, d) = encode_dreg(dd_num);
6688 let (vn, n) = encode_dreg(dn_num);
6689 let (vm, m) = encode_dreg(dm_num);
6690
6691 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6692}
6693
6694fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6696 let dd_num = vfp_dreg_to_num(dd)?;
6697 let dm_num = vfp_dreg_to_num(dm)?;
6698 let (vd, d) = encode_dreg(dd_num);
6699 let (vm, m) = encode_dreg(dm_num);
6700
6701 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6702}
6703
6704fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6707 let dd_num = vfp_dreg_to_num(dd)?;
6708 let (vd, d) = encode_dreg(dd_num);
6709 let rn = reg_to_bits(&addr.base);
6710
6711 let offset = addr.offset;
6712 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6713 let abs_offset = offset.unsigned_abs();
6714 let imm8 = (abs_offset / 4) & 0xFF;
6715
6716 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6717}
6718
6719fn encode_vmov_core_dreg(
6723 to_dreg: bool,
6724 dreg: &VfpReg,
6725 core_lo: &Reg,
6726 core_hi: &Reg,
6727) -> Result<u32> {
6728 let d_num = vfp_dreg_to_num(dreg)?;
6729 let (vm, m) = encode_dreg(d_num);
6730 let rt = reg_to_bits(core_lo);
6731 let rt2 = reg_to_bits(core_hi);
6732
6733 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6734 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6735}
6736
6737fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6739 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6740 let hw2 = (instr & 0xFFFF) as u16;
6741 let mut bytes = hw1.to_le_bytes().to_vec();
6742 bytes.extend_from_slice(&hw2.to_le_bytes());
6743 bytes
6744}
6745
6746fn qreg_to_num(reg: &QReg) -> u32 {
6752 match reg {
6753 QReg::Q0 => 0,
6754 QReg::Q1 => 1,
6755 QReg::Q2 => 2,
6756 QReg::Q3 => 3,
6757 QReg::Q4 => 4,
6758 QReg::Q5 => 5,
6759 QReg::Q6 => 6,
6760 QReg::Q7 => 7,
6761 }
6762}
6763
6764fn mve_size_bits(size: &MveSize) -> u32 {
6766 match size {
6767 MveSize::S8 => 0b00,
6768 MveSize::S16 => 0b01,
6769 MveSize::S32 => 0b10,
6770 }
6771}
6772
6773fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6777 let d = qreg_to_num(qd) * 2;
6778 let n = qreg_to_num(qn) * 2;
6779 let m = qreg_to_num(qm) * 2;
6780
6781 let vd = d & 0xF;
6786 let d_bit = (d >> 4) & 1;
6787 let vn = n & 0xF;
6788 let n_bit = (n >> 4) & 1;
6789 let vm = m & 0xF;
6790 let m_bit = (m >> 4) & 1;
6791
6792 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6793}
6794
6795fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6797 encode_mve_3reg(base, qd, qn, qm)
6798}
6799
6800fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6803 let qd_enc = qreg_to_num(qd) * 2;
6804 let rn = reg_to_bits(&addr.base);
6805 let offset = addr.offset;
6806 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6807 let abs_offset = offset.unsigned_abs();
6808 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6812 | (u_bit << 23)
6813 | ((qd_enc >> 4) << 22)
6814 | (rn << 16)
6815 | ((qd_enc & 0xF) << 12)
6816 | (imm7 & 0x7F)
6817}
6818
6819fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6821 let qd_enc = qreg_to_num(qd) * 2;
6822 let rn = reg_to_bits(&addr.base);
6823 let offset = addr.offset;
6824 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6825 let abs_offset = offset.unsigned_abs();
6826 let imm7 = (abs_offset / 4) & 0x7F;
6827
6828 0xED000E80
6829 | (u_bit << 23)
6830 | ((qd_enc >> 4) << 22)
6831 | (rn << 16)
6832 | ((qd_enc & 0xF) << 12)
6833 | (imm7 & 0x7F)
6834}
6835
6836impl ArmEncoder {
6837 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6839 let mut result = Vec::new();
6840 let qd_num = qreg_to_num(qd);
6841
6842 for i in 0..4 {
6844 let word = u32::from_le_bytes([
6845 bytes[i * 4],
6846 bytes[i * 4 + 1],
6847 bytes[i * 4 + 2],
6848 bytes[i * 4 + 3],
6849 ]);
6850 let lo16 = word & 0xFFFF;
6851 let hi16 = (word >> 16) & 0xFFFF;
6852
6853 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6855 if hi16 != 0 {
6857 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6858 }
6859
6860 let s_num = qd_num * 4 + i as u32;
6862 let (vn, n) = encode_sreg(s_num);
6863 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6864 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6865 }
6866
6867 Ok(result)
6868 }
6869
6870 fn encode_thumb_mve_lane_wise_f32_binop(
6872 &self,
6873 qd: &QReg,
6874 qn: &QReg,
6875 qm: &QReg,
6876 vfp_base: u32,
6877 ) -> Result<Vec<u8>> {
6878 let mut result = Vec::new();
6879 let qd_num = qreg_to_num(qd);
6880 let qn_num = qreg_to_num(qn);
6881 let qm_num = qreg_to_num(qm);
6882
6883 for i in 0..4u32 {
6885 let sd = qd_num * 4 + i;
6886 let sn = qn_num * 4 + i;
6887 let sm = qm_num * 4 + i;
6888
6889 let (vd, d) = encode_sreg(sd);
6890 let (vn, n) = encode_sreg(sn);
6891 let (vm, m) = encode_sreg(sm);
6892
6893 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
6894 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6895 }
6896
6897 Ok(result)
6898 }
6899
6900 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
6902 let mut result = Vec::new();
6903 let qd_num = qreg_to_num(qd);
6904 let qm_num = qreg_to_num(qm);
6905
6906 for i in 0..4u32 {
6908 let sd = qd_num * 4 + i;
6909 let sm = qm_num * 4 + i;
6910
6911 let (vd, d) = encode_sreg(sd);
6912 let (vm, m) = encode_sreg(sm);
6913
6914 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
6915 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
6916 }
6917
6918 Ok(result)
6919 }
6920}
6921
6922#[cfg(test)]
6923mod tests {
6924 use super::*;
6925
6926 #[test]
6927 fn test_encoder_creation() {
6928 let encoder_arm = ArmEncoder::new_arm32();
6929 assert!(!encoder_arm.thumb_mode);
6930
6931 let encoder_thumb = ArmEncoder::new_thumb2();
6932 assert!(encoder_thumb.thumb_mode);
6933 }
6934
6935 #[test]
6942 fn test_encode_setcond_high_reg_uses_mov_w_204() {
6943 use synth_synthesis::{ArmOp, Condition, Reg};
6944 let enc = ArmEncoder::new_thumb2();
6945 let hi = enc
6947 .encode(&ArmOp::SetCond {
6948 rd: Reg::R12,
6949 cond: Condition::NE,
6950 })
6951 .unwrap();
6952 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
6953 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
6955 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
6956 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
6957 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
6958 let lo = enc
6960 .encode(&ArmOp::SetCond {
6961 rd: Reg::R0,
6962 cond: Condition::NE,
6963 })
6964 .unwrap();
6965 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
6966 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
6967 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
6968 }
6969
6970 #[test]
6977 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
6978 let encoder = ArmEncoder::new_thumb2();
6979
6980 let code = encoder
6982 .encode(&ArmOp::Add {
6983 rd: Reg::R12,
6984 rn: Reg::R12,
6985 op2: Operand2::Reg(Reg::R0),
6986 })
6987 .unwrap();
6988 assert_eq!(
6990 code,
6991 vec![0x0C, 0xEB, 0x00, 0x0C],
6992 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
6993 );
6994 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
6996
6997 let lo = encoder
6999 .encode(&ArmOp::Add {
7000 rd: Reg::R1,
7001 rn: Reg::R2,
7002 op2: Operand2::Reg(Reg::R3),
7003 })
7004 .unwrap();
7005 assert_eq!(
7006 lo.len(),
7007 2,
7008 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7009 );
7010 }
7011
7012 #[test]
7015 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7016 let encoder = ArmEncoder::new_thumb2();
7017
7018 let adds = encoder
7020 .encode(&ArmOp::Adds {
7021 rd: Reg::R10,
7022 rn: Reg::R10,
7023 op2: Operand2::Reg(Reg::R8),
7024 })
7025 .unwrap();
7026 assert_eq!(
7027 adds,
7028 vec![0x1A, 0xEB, 0x08, 0x0A],
7029 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7030 );
7031
7032 let subs = encoder
7034 .encode(&ArmOp::Subs {
7035 rd: Reg::R10,
7036 rn: Reg::R10,
7037 op2: Operand2::Reg(Reg::R8),
7038 })
7039 .unwrap();
7040 assert_eq!(
7041 subs,
7042 vec![0xBA, 0xEB, 0x08, 0x0A],
7043 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7044 );
7045 }
7046
7047 #[test]
7050 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7051 let encoder = ArmEncoder::new_thumb2();
7052
7053 let cmn = encoder
7055 .encode(&ArmOp::Cmn {
7056 rn: Reg::R10,
7057 op2: Operand2::Reg(Reg::R8),
7058 })
7059 .unwrap();
7060 assert_eq!(
7061 cmn,
7062 vec![0x1A, 0xEB, 0x08, 0x0F],
7063 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7064 );
7065
7066 let lo = encoder
7068 .encode(&ArmOp::Cmn {
7069 rn: Reg::R1,
7070 op2: Operand2::Reg(Reg::R2),
7071 })
7072 .unwrap();
7073 assert_eq!(
7074 lo.len(),
7075 2,
7076 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7077 );
7078 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7079 }
7080
7081 #[test]
7085 fn test_encode_pc_operand_returns_err_not_panic_185() {
7086 let encoder = ArmEncoder::new_thumb2();
7087 for op in [
7088 ArmOp::Sdiv {
7089 rd: Reg::PC,
7090 rn: Reg::R0,
7091 rm: Reg::R1,
7092 },
7093 ArmOp::Udiv {
7094 rd: Reg::R0,
7095 rn: Reg::PC,
7096 rm: Reg::R1,
7097 },
7098 ArmOp::Sdiv {
7099 rd: Reg::R0,
7100 rn: Reg::R1,
7101 rm: Reg::PC,
7102 },
7103 ] {
7104 let r = encoder.encode(&op);
7105 assert!(
7106 r.is_err(),
7107 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7108 );
7109 }
7110 assert!(
7112 encoder
7113 .encode(&ArmOp::Sdiv {
7114 rd: Reg::R0,
7115 rn: Reg::R1,
7116 rm: Reg::R2
7117 })
7118 .is_ok()
7119 );
7120 }
7121
7122 #[test]
7123 fn test_encode_nop_arm32() {
7124 let encoder = ArmEncoder::new_arm32();
7125 let code = encoder.encode(&ArmOp::Nop).unwrap();
7126
7127 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7130
7131 #[test]
7132 fn test_encode_nop_thumb() {
7133 let encoder = ArmEncoder::new_thumb2();
7134 let code = encoder.encode(&ArmOp::Nop).unwrap();
7135
7136 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7139
7140 #[test]
7141 fn test_encode_mov_immediate_arm32() {
7142 let encoder = ArmEncoder::new_arm32();
7143 let op = ArmOp::Mov {
7144 rd: Reg::R0,
7145 op2: Operand2::Imm(42),
7146 };
7147
7148 let code = encoder.encode(&op).unwrap();
7149 assert_eq!(code.len(), 4);
7150
7151 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7153 assert_eq!(instr & 0x0E000000, 0x02000000); }
7155
7156 #[test]
7157 fn test_encode_add_registers_arm32() {
7158 let encoder = ArmEncoder::new_arm32();
7159 let op = ArmOp::Add {
7160 rd: Reg::R0,
7161 rn: Reg::R1,
7162 op2: Operand2::Reg(Reg::R2),
7163 };
7164
7165 let code = encoder.encode(&op).unwrap();
7166 assert_eq!(code.len(), 4);
7167
7168 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7169 assert_eq!(instr & 0x0FE00000, 0x00800000);
7171 }
7172
7173 #[test]
7174 fn test_encode_ldr_arm32() {
7175 let encoder = ArmEncoder::new_arm32();
7176 let op = ArmOp::Ldr {
7177 rd: Reg::R0,
7178 addr: MemAddr::imm(Reg::R1, 4),
7179 };
7180
7181 let code = encoder.encode(&op).unwrap();
7182 assert_eq!(code.len(), 4);
7183
7184 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7185 assert_eq!(instr & 0x00100000, 0x00100000);
7187 }
7188
7189 #[test]
7190 fn test_encode_str_arm32() {
7191 let encoder = ArmEncoder::new_arm32();
7192 let op = ArmOp::Str {
7193 rd: Reg::R0,
7194 addr: MemAddr::imm(Reg::SP, 0),
7195 };
7196
7197 let code = encoder.encode(&op).unwrap();
7198 assert_eq!(code.len(), 4);
7199 }
7200
7201 #[test]
7202 fn test_encode_branch_arm32() {
7203 let encoder = ArmEncoder::new_arm32();
7204 let op = ArmOp::Bl {
7205 label: "main".to_string(),
7206 };
7207
7208 let code = encoder.encode(&op).unwrap();
7209 assert_eq!(code.len(), 4);
7210
7211 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7212 assert_eq!(instr & 0x0F000000, 0x0B000000);
7214 }
7215
7216 #[test]
7226 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7227 let encoder = ArmEncoder::new_thumb2();
7228 let op = ArmOp::Bl {
7229 label: "callee".to_string(),
7230 };
7231
7232 let code = encoder.encode(&op).unwrap();
7233 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7234
7235 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7236 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7237 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7238 assert_eq!(
7239 hw2, 0xFFFE,
7240 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7241 );
7242 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7243 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7244 }
7245
7246 #[test]
7247 fn test_encode_sequence() {
7248 let encoder = ArmEncoder::new_arm32();
7249 let ops = vec![
7250 ArmOp::Mov {
7251 rd: Reg::R0,
7252 op2: Operand2::Imm(42),
7253 },
7254 ArmOp::Mov {
7255 rd: Reg::R1,
7256 op2: Operand2::Imm(10),
7257 },
7258 ArmOp::Add {
7259 rd: Reg::R2,
7260 rn: Reg::R0,
7261 op2: Operand2::Reg(Reg::R1),
7262 },
7263 ];
7264
7265 let code = encoder.encode_sequence(&ops).unwrap();
7266 assert_eq!(code.len(), 12); }
7268
7269 #[test]
7270 fn test_reg_to_bits() {
7271 assert_eq!(reg_to_bits(&Reg::R0), 0);
7272 assert_eq!(reg_to_bits(&Reg::R7), 7);
7273 assert_eq!(reg_to_bits(&Reg::SP), 13);
7274 assert_eq!(reg_to_bits(&Reg::LR), 14);
7275 assert_eq!(reg_to_bits(&Reg::PC), 15);
7276 }
7277
7278 #[test]
7279 fn test_encode_bitwise_operations() {
7280 let encoder = ArmEncoder::new_arm32();
7281
7282 let and_op = ArmOp::And {
7283 rd: Reg::R0,
7284 rn: Reg::R1,
7285 op2: Operand2::Reg(Reg::R2),
7286 };
7287 let and_code = encoder.encode(&and_op).unwrap();
7288 assert_eq!(and_code.len(), 4);
7289
7290 let orr_op = ArmOp::Orr {
7291 rd: Reg::R0,
7292 rn: Reg::R1,
7293 op2: Operand2::Reg(Reg::R2),
7294 };
7295 let orr_code = encoder.encode(&orr_op).unwrap();
7296 assert_eq!(orr_code.len(), 4);
7297
7298 let eor_op = ArmOp::Eor {
7299 rd: Reg::R0,
7300 rn: Reg::R1,
7301 op2: Operand2::Reg(Reg::R2),
7302 };
7303 let eor_code = encoder.encode(&eor_op).unwrap();
7304 assert_eq!(eor_code.len(), 4);
7305 }
7306
7307 #[test]
7310 fn test_encode_sdiv_thumb2() {
7311 let encoder = ArmEncoder::new_thumb2();
7312 let op = ArmOp::Sdiv {
7313 rd: Reg::R0,
7314 rn: Reg::R1,
7315 rm: Reg::R2,
7316 };
7317
7318 let code = encoder.encode(&op).unwrap();
7319 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7326 assert_eq!(code[1], 0xFB);
7327 assert_eq!(code[2], 0xF2);
7328 assert_eq!(code[3], 0xF0);
7329 }
7330
7331 #[test]
7332 fn test_encode_udiv_thumb2() {
7333 let encoder = ArmEncoder::new_thumb2();
7334 let op = ArmOp::Udiv {
7335 rd: Reg::R0,
7336 rn: Reg::R1,
7337 rm: Reg::R2,
7338 };
7339
7340 let code = encoder.encode(&op).unwrap();
7341 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7346 assert_eq!(code[1], 0xFB);
7347 assert_eq!(code[2], 0xF2);
7348 assert_eq!(code[3], 0xF0);
7349 }
7350
7351 #[test]
7352 fn test_encode_mul_thumb2() {
7353 let encoder = ArmEncoder::new_thumb2();
7354 let op = ArmOp::Mul {
7355 rd: Reg::R0,
7356 rn: Reg::R1,
7357 rm: Reg::R2,
7358 };
7359
7360 let code = encoder.encode(&op).unwrap();
7361 assert_eq!(code.len(), 4); }
7363
7364 #[test]
7365 fn test_encode_and_thumb2() {
7366 let encoder = ArmEncoder::new_thumb2();
7367 let op = ArmOp::And {
7368 rd: Reg::R0,
7369 rn: Reg::R1,
7370 op2: Operand2::Reg(Reg::R2),
7371 };
7372
7373 let code = encoder.encode(&op).unwrap();
7374 assert_eq!(code.len(), 4); }
7376
7377 #[test]
7378 fn test_encode_lsl_thumb2_low_regs() {
7379 let encoder = ArmEncoder::new_thumb2();
7380 let op = ArmOp::Lsl {
7381 rd: Reg::R0,
7382 rn: Reg::R1,
7383 shift: 5,
7384 };
7385
7386 let code = encoder.encode(&op).unwrap();
7387 assert_eq!(code.len(), 2); }
7389
7390 #[test]
7391 fn test_encode_clz_thumb2() {
7392 let encoder = ArmEncoder::new_thumb2();
7393 let op = ArmOp::Clz {
7394 rd: Reg::R0,
7395 rm: Reg::R1,
7396 };
7397
7398 let code = encoder.encode(&op).unwrap();
7399 assert_eq!(code.len(), 4); }
7401
7402 #[test]
7403 fn test_encode_bx_thumb2() {
7404 let encoder = ArmEncoder::new_thumb2();
7405 let op = ArmOp::Bx { rm: Reg::LR };
7406
7407 let code = encoder.encode(&op).unwrap();
7408 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7412 }
7413
7414 #[test]
7419 fn test_encode_f32_abs_arm32() {
7420 let encoder = ArmEncoder::new_arm32();
7421 let op = ArmOp::F32Abs {
7422 sd: VfpReg::S0,
7423 sm: VfpReg::S2,
7424 };
7425 let code = encoder.encode(&op).unwrap();
7426 assert_eq!(code.len(), 4); }
7428
7429 #[test]
7430 fn test_encode_f32_neg_arm32() {
7431 let encoder = ArmEncoder::new_arm32();
7432 let op = ArmOp::F32Neg {
7433 sd: VfpReg::S0,
7434 sm: VfpReg::S2,
7435 };
7436 let code = encoder.encode(&op).unwrap();
7437 assert_eq!(code.len(), 4);
7438 }
7439
7440 #[test]
7441 fn test_encode_f32_sqrt_arm32() {
7442 let encoder = ArmEncoder::new_arm32();
7443 let op = ArmOp::F32Sqrt {
7444 sd: VfpReg::S0,
7445 sm: VfpReg::S2,
7446 };
7447 let code = encoder.encode(&op).unwrap();
7448 assert_eq!(code.len(), 4);
7449 }
7450
7451 #[test]
7452 fn test_encode_f32_ceil_arm32() {
7453 let encoder = ArmEncoder::new_arm32();
7454 let op = ArmOp::F32Ceil {
7455 sd: VfpReg::S0,
7456 sm: VfpReg::S2,
7457 };
7458 let code = encoder.encode(&op).unwrap();
7459 assert_eq!(code.len(), 36);
7461 }
7462
7463 #[test]
7464 fn test_encode_f32_floor_thumb2() {
7465 let encoder = ArmEncoder::new_thumb2();
7466 let op = ArmOp::F32Floor {
7467 sd: VfpReg::S0,
7468 sm: VfpReg::S2,
7469 };
7470 let code = encoder.encode(&op).unwrap();
7471 assert_eq!(code.len(), 36);
7473 }
7474
7475 #[test]
7476 fn test_encode_f32_min_arm32() {
7477 let encoder = ArmEncoder::new_arm32();
7478 let op = ArmOp::F32Min {
7479 sd: VfpReg::S0,
7480 sn: VfpReg::S2,
7481 sm: VfpReg::S4,
7482 };
7483 let code = encoder.encode(&op).unwrap();
7484 assert_eq!(code.len(), 16); }
7486
7487 #[test]
7488 fn test_encode_f32_max_thumb2() {
7489 let encoder = ArmEncoder::new_thumb2();
7490 let op = ArmOp::F32Max {
7491 sd: VfpReg::S0,
7492 sn: VfpReg::S2,
7493 sm: VfpReg::S4,
7494 };
7495 let code = encoder.encode(&op).unwrap();
7496 assert_eq!(code.len(), 18);
7498 }
7499
7500 #[test]
7501 fn test_encode_f32_copysign_arm32() {
7502 let encoder = ArmEncoder::new_arm32();
7503 let op = ArmOp::F32Copysign {
7504 sd: VfpReg::S0,
7505 sn: VfpReg::S2,
7506 sm: VfpReg::S4,
7507 };
7508 let code = encoder.encode(&op).unwrap();
7509 assert_eq!(code.len(), 24);
7511 }
7512
7513 #[test]
7518 fn test_encode_f64_add_arm32() {
7519 let encoder = ArmEncoder::new_arm32();
7520 let op = ArmOp::F64Add {
7521 dd: VfpReg::D0,
7522 dn: VfpReg::D1,
7523 dm: VfpReg::D2,
7524 };
7525 let code = encoder.encode(&op).unwrap();
7526 assert_eq!(code.len(), 4);
7527 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7529 assert_eq!((instr >> 8) & 0xF, 0xB); }
7531
7532 #[test]
7533 fn test_encode_f64_sub_thumb2() {
7534 let encoder = ArmEncoder::new_thumb2();
7535 let op = ArmOp::F64Sub {
7536 dd: VfpReg::D0,
7537 dn: VfpReg::D1,
7538 dm: VfpReg::D2,
7539 };
7540 let code = encoder.encode(&op).unwrap();
7541 assert_eq!(code.len(), 4); }
7543
7544 #[test]
7545 fn test_encode_f64_mul_arm32() {
7546 let encoder = ArmEncoder::new_arm32();
7547 let op = ArmOp::F64Mul {
7548 dd: VfpReg::D0,
7549 dn: VfpReg::D1,
7550 dm: VfpReg::D2,
7551 };
7552 let code = encoder.encode(&op).unwrap();
7553 assert_eq!(code.len(), 4);
7554 }
7555
7556 #[test]
7557 fn test_encode_f64_div_arm32() {
7558 let encoder = ArmEncoder::new_arm32();
7559 let op = ArmOp::F64Div {
7560 dd: VfpReg::D0,
7561 dn: VfpReg::D1,
7562 dm: VfpReg::D2,
7563 };
7564 let code = encoder.encode(&op).unwrap();
7565 assert_eq!(code.len(), 4);
7566 }
7567
7568 #[test]
7569 fn test_encode_f64_abs_arm32() {
7570 let encoder = ArmEncoder::new_arm32();
7571 let op = ArmOp::F64Abs {
7572 dd: VfpReg::D0,
7573 dm: VfpReg::D2,
7574 };
7575 let code = encoder.encode(&op).unwrap();
7576 assert_eq!(code.len(), 4);
7577 }
7578
7579 #[test]
7580 fn test_encode_f64_neg_arm32() {
7581 let encoder = ArmEncoder::new_arm32();
7582 let op = ArmOp::F64Neg {
7583 dd: VfpReg::D0,
7584 dm: VfpReg::D2,
7585 };
7586 let code = encoder.encode(&op).unwrap();
7587 assert_eq!(code.len(), 4);
7588 }
7589
7590 #[test]
7591 fn test_encode_f64_sqrt_arm32() {
7592 let encoder = ArmEncoder::new_arm32();
7593 let op = ArmOp::F64Sqrt {
7594 dd: VfpReg::D0,
7595 dm: VfpReg::D2,
7596 };
7597 let code = encoder.encode(&op).unwrap();
7598 assert_eq!(code.len(), 4);
7599 }
7600
7601 #[test]
7602 fn test_encode_f64_load_arm32() {
7603 let encoder = ArmEncoder::new_arm32();
7604 let op = ArmOp::F64Load {
7605 dd: VfpReg::D0,
7606 addr: MemAddr::imm(Reg::R0, 8),
7607 };
7608 let code = encoder.encode(&op).unwrap();
7609 assert_eq!(code.len(), 4);
7610 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7611 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7614
7615 #[test]
7616 fn test_encode_f64_store_thumb2() {
7617 let encoder = ArmEncoder::new_thumb2();
7618 let op = ArmOp::F64Store {
7619 dd: VfpReg::D0,
7620 addr: MemAddr::imm(Reg::SP, 0),
7621 };
7622 let code = encoder.encode(&op).unwrap();
7623 assert_eq!(code.len(), 4);
7624 }
7625
7626 #[test]
7627 fn test_encode_f64_compare_arm32() {
7628 let encoder = ArmEncoder::new_arm32();
7629 let op = ArmOp::F64Eq {
7630 rd: Reg::R0,
7631 dn: VfpReg::D0,
7632 dm: VfpReg::D1,
7633 };
7634 let code = encoder.encode(&op).unwrap();
7635 assert_eq!(code.len(), 16); }
7637
7638 #[test]
7639 fn test_encode_f64_compare_thumb2() {
7640 let encoder = ArmEncoder::new_thumb2();
7641 let op = ArmOp::F64Lt {
7642 rd: Reg::R0,
7643 dn: VfpReg::D0,
7644 dm: VfpReg::D1,
7645 };
7646 let code = encoder.encode(&op).unwrap();
7647 assert_eq!(code.len(), 14);
7649 }
7650
7651 #[test]
7652 fn test_encode_f64_const_arm32() {
7653 let encoder = ArmEncoder::new_arm32();
7654 let op = ArmOp::F64Const {
7655 dd: VfpReg::D0,
7656 value: 3.125,
7657 };
7658 let code = encoder.encode(&op).unwrap();
7659 assert_eq!(code.len(), 20);
7661 }
7662
7663 #[test]
7664 fn test_encode_f64_const_thumb2() {
7665 let encoder = ArmEncoder::new_thumb2();
7666 let op = ArmOp::F64Const {
7667 dd: VfpReg::D0,
7668 value: 2.5,
7669 };
7670 let code = encoder.encode(&op).unwrap();
7671 assert_eq!(code.len(), 20);
7673 }
7674
7675 #[test]
7676 fn test_encode_f64_convert_i32s_arm32() {
7677 let encoder = ArmEncoder::new_arm32();
7678 let op = ArmOp::F64ConvertI32S {
7679 dd: VfpReg::D0,
7680 rm: Reg::R0,
7681 };
7682 let code = encoder.encode(&op).unwrap();
7683 assert_eq!(code.len(), 8);
7685 }
7686
7687 #[test]
7688 fn test_encode_f64_promote_f32_arm32() {
7689 let encoder = ArmEncoder::new_arm32();
7690 let op = ArmOp::F64PromoteF32 {
7691 dd: VfpReg::D0,
7692 sm: VfpReg::S0,
7693 };
7694 let code = encoder.encode(&op).unwrap();
7695 assert_eq!(code.len(), 4); }
7697
7698 #[test]
7699 fn test_encode_f64_promote_f32_thumb2() {
7700 let encoder = ArmEncoder::new_thumb2();
7701 let op = ArmOp::F64PromoteF32 {
7702 dd: VfpReg::D0,
7703 sm: VfpReg::S0,
7704 };
7705 let code = encoder.encode(&op).unwrap();
7706 assert_eq!(code.len(), 4);
7707 }
7708
7709 #[test]
7710 fn test_encode_i32_trunc_f64s_arm32() {
7711 let encoder = ArmEncoder::new_arm32();
7712 let op = ArmOp::I32TruncF64S {
7713 rd: Reg::R0,
7714 dm: VfpReg::D0,
7715 };
7716 let code = encoder.encode(&op).unwrap();
7717 assert_eq!(code.len(), 8);
7719 }
7720
7721 #[test]
7722 fn test_encode_f64_reinterpret_i64_arm32() {
7723 let encoder = ArmEncoder::new_arm32();
7724 let op = ArmOp::F64ReinterpretI64 {
7725 dd: VfpReg::D0,
7726 rmlo: Reg::R0,
7727 rmhi: Reg::R1,
7728 };
7729 let code = encoder.encode(&op).unwrap();
7730 assert_eq!(code.len(), 4); }
7732
7733 #[test]
7734 fn test_encode_i64_reinterpret_f64_thumb2() {
7735 let encoder = ArmEncoder::new_thumb2();
7736 let op = ArmOp::I64ReinterpretF64 {
7737 rdlo: Reg::R0,
7738 rdhi: Reg::R1,
7739 dm: VfpReg::D0,
7740 };
7741 let code = encoder.encode(&op).unwrap();
7742 assert_eq!(code.len(), 4);
7743 }
7744
7745 #[test]
7746 fn test_encode_f64_trunc_thumb2() {
7747 let encoder = ArmEncoder::new_thumb2();
7748 let op = ArmOp::F64Trunc {
7749 dd: VfpReg::D0,
7750 dm: VfpReg::D1,
7751 };
7752 let code = encoder.encode(&op).unwrap();
7753 assert_eq!(code.len(), 8);
7755 }
7756
7757 #[test]
7758 fn test_encode_f64_min_arm32() {
7759 let encoder = ArmEncoder::new_arm32();
7760 let op = ArmOp::F64Min {
7761 dd: VfpReg::D0,
7762 dn: VfpReg::D1,
7763 dm: VfpReg::D2,
7764 };
7765 let code = encoder.encode(&op).unwrap();
7766 assert_eq!(code.len(), 16);
7768 }
7769
7770 #[test]
7771 fn test_f64_cp11_encoding() {
7772 let encoder = ArmEncoder::new_arm32();
7774
7775 let code = encoder
7777 .encode(&ArmOp::F64Add {
7778 dd: VfpReg::D0,
7779 dn: VfpReg::D0,
7780 dm: VfpReg::D0,
7781 })
7782 .unwrap();
7783 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7784 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7785
7786 let code = encoder
7788 .encode(&ArmOp::F32Add {
7789 sd: VfpReg::S0,
7790 sn: VfpReg::S0,
7791 sm: VfpReg::S0,
7792 })
7793 .unwrap();
7794 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7795 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7796 }
7797
7798 #[test]
7799 fn test_dreg_encoding_higher_registers() {
7800 let encoder = ArmEncoder::new_arm32();
7801
7802 let op = ArmOp::F64Add {
7804 dd: VfpReg::D15,
7805 dn: VfpReg::D14,
7806 dm: VfpReg::D13,
7807 };
7808 let code = encoder.encode(&op).unwrap();
7809 assert_eq!(code.len(), 4);
7810
7811 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7813 assert_eq!((instr >> 8) & 0xF, 0xB); }
7815
7816 #[test]
7821 fn test_encode_label_emits_no_bytes() {
7822 let encoder = ArmEncoder::new_thumb2();
7823 let op = ArmOp::Label {
7824 name: ".Lblock_end_0".to_string(),
7825 };
7826 let code = encoder.encode(&op).unwrap();
7827 assert!(code.is_empty(), "Label should emit zero bytes");
7828
7829 let encoder32 = ArmEncoder::new_arm32();
7830 let code32 = encoder32.encode(&op).unwrap();
7831 assert!(
7832 code32.is_empty(),
7833 "Label should emit zero bytes in ARM32 too"
7834 );
7835 }
7836
7837 #[test]
7838 fn test_encode_bcc_eq_thumb2() {
7839 use synth_synthesis::Condition;
7840 let encoder = ArmEncoder::new_thumb2();
7841 let op = ArmOp::Bcc {
7842 cond: Condition::EQ,
7843 label: "target".to_string(),
7844 };
7845 let code = encoder.encode(&op).unwrap();
7846 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
7850 }
7851
7852 #[test]
7853 fn test_encode_bcc_ne_thumb2() {
7854 use synth_synthesis::Condition;
7855 let encoder = ArmEncoder::new_thumb2();
7856 let op = ArmOp::Bcc {
7857 cond: Condition::NE,
7858 label: "target".to_string(),
7859 };
7860 let code = encoder.encode(&op).unwrap();
7861 assert_eq!(code.len(), 2);
7862
7863 assert_eq!(code, vec![0x00, 0xD1]);
7865 }
7866
7867 #[test]
7868 fn test_encode_bcc_arm32() {
7869 use synth_synthesis::Condition;
7870 let encoder = ArmEncoder::new_arm32();
7871 let op = ArmOp::Bcc {
7872 cond: Condition::EQ,
7873 label: "target".to_string(),
7874 };
7875 let code = encoder.encode(&op).unwrap();
7876 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7879 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
7883
7884 #[test]
7885 fn test_encode_udf_thumb2() {
7886 let encoder = ArmEncoder::new_thumb2();
7887 let op = ArmOp::Udf { imm: 0 };
7888 let code = encoder.encode(&op).unwrap();
7889 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
7893 }
7894
7895 #[test]
7896 fn test_encode_nop_thumb2() {
7897 let encoder = ArmEncoder::new_thumb2();
7898 let op = ArmOp::Nop;
7899 let code = encoder.encode(&op).unwrap();
7900 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
7904 }
7905
7906 #[test]
7911 fn test_encode_i64_add_thumb2() {
7912 let encoder = ArmEncoder::new_thumb2();
7913 let op = ArmOp::I64Add {
7914 rdlo: Reg::R0,
7915 rdhi: Reg::R1,
7916 rnlo: Reg::R0,
7917 rnhi: Reg::R1,
7918 rmlo: Reg::R2,
7919 rmhi: Reg::R3,
7920 };
7921 let code = encoder.encode(&op).unwrap();
7922 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
7924 }
7925
7926 #[test]
7927 fn test_encode_i64_sub_thumb2() {
7928 let encoder = ArmEncoder::new_thumb2();
7929 let op = ArmOp::I64Sub {
7930 rdlo: Reg::R0,
7931 rdhi: Reg::R1,
7932 rnlo: Reg::R0,
7933 rnhi: Reg::R1,
7934 rmlo: Reg::R2,
7935 rmhi: Reg::R3,
7936 };
7937 let code = encoder.encode(&op).unwrap();
7938 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
7940 }
7941
7942 #[test]
7943 fn test_encode_i64_and_thumb2() {
7944 let encoder = ArmEncoder::new_thumb2();
7945 let op = ArmOp::I64And {
7946 rdlo: Reg::R0,
7947 rdhi: Reg::R1,
7948 rnlo: Reg::R0,
7949 rnhi: Reg::R1,
7950 rmlo: Reg::R2,
7951 rmhi: Reg::R3,
7952 };
7953 let code = encoder.encode(&op).unwrap();
7954 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
7956 }
7957
7958 #[test]
7959 fn test_encode_i64_or_thumb2() {
7960 let encoder = ArmEncoder::new_thumb2();
7961 let op = ArmOp::I64Or {
7962 rdlo: Reg::R0,
7963 rdhi: Reg::R1,
7964 rnlo: Reg::R0,
7965 rnhi: Reg::R1,
7966 rmlo: Reg::R2,
7967 rmhi: Reg::R3,
7968 };
7969 let code = encoder.encode(&op).unwrap();
7970 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
7971 }
7972
7973 #[test]
7974 fn test_encode_i64_xor_thumb2() {
7975 let encoder = ArmEncoder::new_thumb2();
7976 let op = ArmOp::I64Xor {
7977 rdlo: Reg::R0,
7978 rdhi: Reg::R1,
7979 rnlo: Reg::R0,
7980 rnhi: Reg::R1,
7981 rmlo: Reg::R2,
7982 rmhi: Reg::R3,
7983 };
7984 let code = encoder.encode(&op).unwrap();
7985 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
7986 }
7987
7988 #[test]
7989 fn test_encode_i64_const_small_thumb2() {
7990 let encoder = ArmEncoder::new_thumb2();
7991 let op = ArmOp::I64Const {
7993 rdlo: Reg::R0,
7994 rdhi: Reg::R1,
7995 value: 42,
7996 };
7997 let code = encoder.encode(&op).unwrap();
7998 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8000 }
8001
8002 #[test]
8003 fn test_encode_i64_const_large_thumb2() {
8004 let encoder = ArmEncoder::new_thumb2();
8005 let op = ArmOp::I64Const {
8007 rdlo: Reg::R0,
8008 rdhi: Reg::R1,
8009 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8010 };
8011 let code = encoder.encode(&op).unwrap();
8012 assert_eq!(
8014 code.len(),
8015 16,
8016 "I64Const with large value should be 16 bytes"
8017 );
8018 }
8019
8020 #[test]
8021 fn test_encode_i64_extend_i32_s_thumb2() {
8022 let encoder = ArmEncoder::new_thumb2();
8023 let op = ArmOp::I64ExtendI32S {
8024 rdlo: Reg::R0,
8025 rdhi: Reg::R1,
8026 rn: Reg::R0,
8027 };
8028 let code = encoder.encode(&op).unwrap();
8029 assert_eq!(
8031 code.len(),
8032 4,
8033 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8034 );
8035 }
8036
8037 #[test]
8038 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8039 let encoder = ArmEncoder::new_thumb2();
8040 let op = ArmOp::I64ExtendI32S {
8041 rdlo: Reg::R0,
8042 rdhi: Reg::R1,
8043 rn: Reg::R2,
8044 };
8045 let code = encoder.encode(&op).unwrap();
8046 assert!(
8048 code.len() >= 6,
8049 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8050 );
8051 }
8052
8053 #[test]
8054 fn test_encode_i64_extend_i32_u_thumb2() {
8055 let encoder = ArmEncoder::new_thumb2();
8056 let op = ArmOp::I64ExtendI32U {
8057 rdlo: Reg::R0,
8058 rdhi: Reg::R1,
8059 rn: Reg::R0,
8060 };
8061 let code = encoder.encode(&op).unwrap();
8062 assert_eq!(
8064 code.len(),
8065 2,
8066 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8067 );
8068 }
8069
8070 #[test]
8071 fn test_encode_i32_wrap_i64_nop_thumb2() {
8072 let encoder = ArmEncoder::new_thumb2();
8073 let op = ArmOp::I32WrapI64 {
8075 rd: Reg::R0,
8076 rnlo: Reg::R0,
8077 };
8078 let code = encoder.encode(&op).unwrap();
8079 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8080 assert_eq!(code, vec![0x00, 0xBF]); }
8082
8083 #[test]
8084 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8085 let encoder = ArmEncoder::new_thumb2();
8086 let op = ArmOp::I32WrapI64 {
8087 rd: Reg::R2,
8088 rnlo: Reg::R0,
8089 };
8090 let code = encoder.encode(&op).unwrap();
8091 assert!(
8093 code.len() >= 2,
8094 "I32WrapI64 diff reg should emit at least 2 bytes"
8095 );
8096 }
8097
8098 #[test]
8099 fn test_encode_i64_eqz_thumb2() {
8100 let encoder = ArmEncoder::new_thumb2();
8101 let op = ArmOp::I64Eqz {
8102 rd: Reg::R0,
8103 rnlo: Reg::R0,
8104 rnhi: Reg::R1,
8105 };
8106 let code = encoder.encode(&op).unwrap();
8107 assert!(
8109 code.len() >= 6,
8110 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8111 );
8112 }
8113
8114 #[test]
8115 fn test_encode_i64_eq_thumb2() {
8116 let encoder = ArmEncoder::new_thumb2();
8117 let op = ArmOp::I64Eq {
8118 rd: Reg::R0,
8119 rnlo: Reg::R0,
8120 rnhi: Reg::R1,
8121 rmlo: Reg::R2,
8122 rmhi: Reg::R3,
8123 };
8124 let code = encoder.encode(&op).unwrap();
8125 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8127 }
8128
8129 #[test]
8130 fn test_encode_i64_ldr_thumb2() {
8131 let encoder = ArmEncoder::new_thumb2();
8132 let op = ArmOp::I64Ldr {
8133 rdlo: Reg::R0,
8134 rdhi: Reg::R1,
8135 addr: MemAddr::imm(Reg::SP, 0),
8136 };
8137 let code = encoder.encode(&op).unwrap();
8138 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8140 }
8141
8142 #[test]
8143 fn test_encode_i64_str_thumb2() {
8144 let encoder = ArmEncoder::new_thumb2();
8145 let op = ArmOp::I64Str {
8146 rdlo: Reg::R0,
8147 rdhi: Reg::R1,
8148 addr: MemAddr::imm(Reg::SP, 0),
8149 };
8150 let code = encoder.encode(&op).unwrap();
8151 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8153 }
8154
8155 #[test]
8156 fn test_encode_i64_all_comparisons_thumb2() {
8157 let encoder = ArmEncoder::new_thumb2();
8158
8159 let ops = vec![
8160 ArmOp::I64Ne {
8161 rd: Reg::R0,
8162 rnlo: Reg::R0,
8163 rnhi: Reg::R1,
8164 rmlo: Reg::R2,
8165 rmhi: Reg::R3,
8166 },
8167 ArmOp::I64LtS {
8168 rd: Reg::R0,
8169 rnlo: Reg::R0,
8170 rnhi: Reg::R1,
8171 rmlo: Reg::R2,
8172 rmhi: Reg::R3,
8173 },
8174 ArmOp::I64LtU {
8175 rd: Reg::R0,
8176 rnlo: Reg::R0,
8177 rnhi: Reg::R1,
8178 rmlo: Reg::R2,
8179 rmhi: Reg::R3,
8180 },
8181 ArmOp::I64LeS {
8182 rd: Reg::R0,
8183 rnlo: Reg::R0,
8184 rnhi: Reg::R1,
8185 rmlo: Reg::R2,
8186 rmhi: Reg::R3,
8187 },
8188 ArmOp::I64LeU {
8189 rd: Reg::R0,
8190 rnlo: Reg::R0,
8191 rnhi: Reg::R1,
8192 rmlo: Reg::R2,
8193 rmhi: Reg::R3,
8194 },
8195 ArmOp::I64GtS {
8196 rd: Reg::R0,
8197 rnlo: Reg::R0,
8198 rnhi: Reg::R1,
8199 rmlo: Reg::R2,
8200 rmhi: Reg::R3,
8201 },
8202 ArmOp::I64GtU {
8203 rd: Reg::R0,
8204 rnlo: Reg::R0,
8205 rnhi: Reg::R1,
8206 rmlo: Reg::R2,
8207 rmhi: Reg::R3,
8208 },
8209 ArmOp::I64GeS {
8210 rd: Reg::R0,
8211 rnlo: Reg::R0,
8212 rnhi: Reg::R1,
8213 rmlo: Reg::R2,
8214 rmhi: Reg::R3,
8215 },
8216 ArmOp::I64GeU {
8217 rd: Reg::R0,
8218 rnlo: Reg::R0,
8219 rnhi: Reg::R1,
8220 rmlo: Reg::R2,
8221 rmhi: Reg::R3,
8222 },
8223 ];
8224
8225 for op in &ops {
8226 let code = encoder.encode(op).unwrap();
8227 assert!(
8228 code.len() >= 8,
8229 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8230 op,
8231 code.len()
8232 );
8233 }
8234 }
8235
8236 #[test]
8237 fn test_encode_i64_const_zero_thumb2() {
8238 let encoder = ArmEncoder::new_thumb2();
8239 let op = ArmOp::I64Const {
8240 rdlo: Reg::R0,
8241 rdhi: Reg::R1,
8242 value: 0,
8243 };
8244 let code = encoder.encode(&op).unwrap();
8245 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8247 }
8248
8249 #[test]
8250 fn test_encode_i64_const_negative_one_thumb2() {
8251 let encoder = ArmEncoder::new_thumb2();
8252 let op = ArmOp::I64Const {
8253 rdlo: Reg::R0,
8254 rdhi: Reg::R1,
8255 value: -1, };
8257 let code = encoder.encode(&op).unwrap();
8258 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8260 }
8261
8262 #[test]
8267 fn test_encode_ldrb_arm32() {
8268 let encoder = ArmEncoder::new_arm32();
8269 let op = ArmOp::Ldrb {
8270 rd: Reg::R0,
8271 addr: MemAddr::imm(Reg::R1, 4),
8272 };
8273 let code = encoder.encode(&op).unwrap();
8274 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8275 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8277 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8278 }
8279
8280 #[test]
8281 fn test_encode_strb_arm32() {
8282 let encoder = ArmEncoder::new_arm32();
8283 let op = ArmOp::Strb {
8284 rd: Reg::R0,
8285 addr: MemAddr::imm(Reg::R1, 0),
8286 };
8287 let code = encoder.encode(&op).unwrap();
8288 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8289 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8291 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8292 }
8293
8294 #[test]
8295 fn test_encode_ldrh_arm32() {
8296 let encoder = ArmEncoder::new_arm32();
8297 let op = ArmOp::Ldrh {
8298 rd: Reg::R0,
8299 addr: MemAddr::imm(Reg::R1, 2),
8300 };
8301 let code = encoder.encode(&op).unwrap();
8302 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8303 }
8304
8305 #[test]
8306 fn test_encode_strh_arm32() {
8307 let encoder = ArmEncoder::new_arm32();
8308 let op = ArmOp::Strh {
8309 rd: Reg::R0,
8310 addr: MemAddr::imm(Reg::R1, 0),
8311 };
8312 let code = encoder.encode(&op).unwrap();
8313 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8314 }
8315
8316 #[test]
8317 fn test_encode_ldrsb_arm32() {
8318 let encoder = ArmEncoder::new_arm32();
8319 let op = ArmOp::Ldrsb {
8320 rd: Reg::R0,
8321 addr: MemAddr::imm(Reg::R1, 0),
8322 };
8323 let code = encoder.encode(&op).unwrap();
8324 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8325 }
8326
8327 #[test]
8328 fn test_encode_ldrsh_arm32() {
8329 let encoder = ArmEncoder::new_arm32();
8330 let op = ArmOp::Ldrsh {
8331 rd: Reg::R0,
8332 addr: MemAddr::imm(Reg::R1, 0),
8333 };
8334 let code = encoder.encode(&op).unwrap();
8335 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8336 }
8337
8338 #[test]
8339 fn test_encode_ldrb_thumb2_16bit() {
8340 let encoder = ArmEncoder::new_thumb2();
8341 let op = ArmOp::Ldrb {
8342 rd: Reg::R0,
8343 addr: MemAddr::imm(Reg::R1, 4),
8344 };
8345 let code = encoder.encode(&op).unwrap();
8346 assert_eq!(
8348 code.len(),
8349 2,
8350 "Thumb-2 LDRB with small offset should be 16-bit"
8351 );
8352 }
8353
8354 #[test]
8355 fn test_encode_ldrb_thumb2_32bit() {
8356 let encoder = ArmEncoder::new_thumb2();
8357 let op = ArmOp::Ldrb {
8358 rd: Reg::R0,
8359 addr: MemAddr::imm(Reg::R1, 100), };
8361 let code = encoder.encode(&op).unwrap();
8362 assert_eq!(
8363 code.len(),
8364 4,
8365 "Thumb-2 LDRB with large offset should be 32-bit"
8366 );
8367 }
8368
8369 #[test]
8370 fn test_encode_strb_thumb2_16bit() {
8371 let encoder = ArmEncoder::new_thumb2();
8372 let op = ArmOp::Strb {
8373 rd: Reg::R0,
8374 addr: MemAddr::imm(Reg::R1, 10),
8375 };
8376 let code = encoder.encode(&op).unwrap();
8377 assert_eq!(
8378 code.len(),
8379 2,
8380 "Thumb-2 STRB with small offset should be 16-bit"
8381 );
8382 }
8383
8384 #[test]
8385 fn test_encode_ldrh_thumb2_16bit() {
8386 let encoder = ArmEncoder::new_thumb2();
8387 let op = ArmOp::Ldrh {
8388 rd: Reg::R0,
8389 addr: MemAddr::imm(Reg::R1, 4), };
8391 let code = encoder.encode(&op).unwrap();
8392 assert_eq!(
8393 code.len(),
8394 2,
8395 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8396 );
8397 }
8398
8399 #[test]
8400 fn test_encode_strh_thumb2_16bit() {
8401 let encoder = ArmEncoder::new_thumb2();
8402 let op = ArmOp::Strh {
8403 rd: Reg::R0,
8404 addr: MemAddr::imm(Reg::R1, 4),
8405 };
8406 let code = encoder.encode(&op).unwrap();
8407 assert_eq!(
8408 code.len(),
8409 2,
8410 "Thumb-2 STRH with small aligned offset should be 16-bit"
8411 );
8412 }
8413
8414 #[test]
8415 fn test_encode_ldrsb_thumb2() {
8416 let encoder = ArmEncoder::new_thumb2();
8417 let op = ArmOp::Ldrsb {
8418 rd: Reg::R0,
8419 addr: MemAddr::imm(Reg::R1, 0),
8420 };
8421 let code = encoder.encode(&op).unwrap();
8422 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8424 }
8425
8426 #[test]
8427 fn test_encode_ldrsh_thumb2() {
8428 let encoder = ArmEncoder::new_thumb2();
8429 let op = ArmOp::Ldrsh {
8430 rd: Reg::R0,
8431 addr: MemAddr::imm(Reg::R1, 0),
8432 };
8433 let code = encoder.encode(&op).unwrap();
8434 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8435 }
8436
8437 #[test]
8438 fn test_encode_memory_size_thumb2() {
8439 let encoder = ArmEncoder::new_thumb2();
8440 let op = ArmOp::MemorySize { rd: Reg::R0 };
8441 let code = encoder.encode(&op).unwrap();
8442 assert!(!code.is_empty(), "MemorySize should produce code");
8444 }
8445
8446 #[test]
8447 fn test_encode_memory_grow_thumb2() {
8448 let encoder = ArmEncoder::new_thumb2();
8449 let op = ArmOp::MemoryGrow {
8450 rd: Reg::R0,
8451 rn: Reg::R0,
8452 };
8453 let code = encoder.encode(&op).unwrap();
8454 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8455 }
8456
8457 #[test]
8458 fn test_encode_subword_reg_offset_thumb2() {
8459 let encoder = ArmEncoder::new_thumb2();
8460
8461 let op = ArmOp::Ldrb {
8463 rd: Reg::R0,
8464 addr: MemAddr::reg(Reg::R1, Reg::R2),
8465 };
8466 let code = encoder.encode(&op).unwrap();
8467 assert_eq!(
8468 code.len(),
8469 4,
8470 "Thumb-2 LDRB with reg offset should be 32-bit"
8471 );
8472
8473 let op = ArmOp::Strb {
8475 rd: Reg::R0,
8476 addr: MemAddr::reg(Reg::R1, Reg::R2),
8477 };
8478 let code = encoder.encode(&op).unwrap();
8479 assert_eq!(
8480 code.len(),
8481 4,
8482 "Thumb-2 STRB with reg offset should be 32-bit"
8483 );
8484
8485 let op = ArmOp::Ldrh {
8487 rd: Reg::R0,
8488 addr: MemAddr::reg(Reg::R1, Reg::R2),
8489 };
8490 let code = encoder.encode(&op).unwrap();
8491 assert_eq!(
8492 code.len(),
8493 4,
8494 "Thumb-2 LDRH with reg offset should be 32-bit"
8495 );
8496
8497 let op = ArmOp::Strh {
8499 rd: Reg::R0,
8500 addr: MemAddr::reg(Reg::R1, Reg::R2),
8501 };
8502 let code = encoder.encode(&op).unwrap();
8503 assert_eq!(
8504 code.len(),
8505 4,
8506 "Thumb-2 STRH with reg offset should be 32-bit"
8507 );
8508 }
8509
8510 #[test]
8511 fn test_encode_subword_reg_imm_offset_thumb2() {
8512 let encoder = ArmEncoder::new_thumb2();
8513
8514 let op = ArmOp::Ldrb {
8516 rd: Reg::R0,
8517 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8518 };
8519 let code = encoder.encode(&op).unwrap();
8520 assert_eq!(
8522 code.len(),
8523 8,
8524 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8525 );
8526 }
8527
8528 #[test]
8533 fn test_encode_mve_addi32_thumb2() {
8534 let encoder = ArmEncoder::new_thumb2();
8535 let op = ArmOp::MveAddI {
8536 qd: QReg::Q0,
8537 qn: QReg::Q1,
8538 qm: QReg::Q2,
8539 size: MveSize::S32,
8540 };
8541 let code = encoder.encode(&op).unwrap();
8542 assert_eq!(
8543 code.len(),
8544 4,
8545 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8546 );
8547 }
8548
8549 #[test]
8550 fn test_encode_mve_subi16_thumb2() {
8551 let encoder = ArmEncoder::new_thumb2();
8552 let op = ArmOp::MveSubI {
8553 qd: QReg::Q0,
8554 qn: QReg::Q1,
8555 qm: QReg::Q2,
8556 size: MveSize::S16,
8557 };
8558 let code = encoder.encode(&op).unwrap();
8559 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8560 }
8561
8562 #[test]
8563 fn test_encode_mve_muli8_thumb2() {
8564 let encoder = ArmEncoder::new_thumb2();
8565 let op = ArmOp::MveMulI {
8566 qd: QReg::Q0,
8567 qn: QReg::Q1,
8568 qm: QReg::Q2,
8569 size: MveSize::S8,
8570 };
8571 let code = encoder.encode(&op).unwrap();
8572 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8573 }
8574
8575 #[test]
8576 fn test_encode_mve_bitwise_thumb2() {
8577 let encoder = ArmEncoder::new_thumb2();
8578
8579 let ops = vec![
8580 ArmOp::MveAnd {
8581 qd: QReg::Q0,
8582 qn: QReg::Q1,
8583 qm: QReg::Q2,
8584 },
8585 ArmOp::MveOrr {
8586 qd: QReg::Q0,
8587 qn: QReg::Q1,
8588 qm: QReg::Q2,
8589 },
8590 ArmOp::MveEor {
8591 qd: QReg::Q0,
8592 qn: QReg::Q1,
8593 qm: QReg::Q2,
8594 },
8595 ArmOp::MveBic {
8596 qd: QReg::Q0,
8597 qn: QReg::Q1,
8598 qm: QReg::Q2,
8599 },
8600 ];
8601 for op in ops {
8602 let code = encoder.encode(&op).unwrap();
8603 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8604 }
8605 }
8606
8607 #[test]
8608 fn test_encode_mve_mvn_thumb2() {
8609 let encoder = ArmEncoder::new_thumb2();
8610 let op = ArmOp::MveMvn {
8611 qd: QReg::Q0,
8612 qm: QReg::Q1,
8613 };
8614 let code = encoder.encode(&op).unwrap();
8615 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8616 }
8617
8618 #[test]
8619 fn test_encode_mve_load_store_thumb2() {
8620 let encoder = ArmEncoder::new_thumb2();
8621
8622 let load = ArmOp::MveLoad {
8623 qd: QReg::Q0,
8624 addr: MemAddr::imm(Reg::R0, 16),
8625 };
8626 let code = encoder.encode(&load).unwrap();
8627 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8628
8629 let store = ArmOp::MveStore {
8630 qd: QReg::Q1,
8631 addr: MemAddr::imm(Reg::R1, 0),
8632 };
8633 let code = encoder.encode(&store).unwrap();
8634 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8635 }
8636
8637 #[test]
8638 fn test_encode_mve_const_thumb2() {
8639 let encoder = ArmEncoder::new_thumb2();
8640 let op = ArmOp::MveConst {
8641 qd: QReg::Q0,
8642 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8643 };
8644 let code = encoder.encode(&op).unwrap();
8645 assert!(
8648 code.len() >= 24,
8649 "MVE const should produce multiple instructions"
8650 );
8651 }
8652
8653 #[test]
8654 fn test_encode_mve_dup_thumb2() {
8655 let encoder = ArmEncoder::new_thumb2();
8656 let op = ArmOp::MveDup {
8657 qd: QReg::Q0,
8658 rn: Reg::R0,
8659 size: MveSize::S32,
8660 };
8661 let code = encoder.encode(&op).unwrap();
8662 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8663 }
8664
8665 #[test]
8666 fn test_encode_mve_extract_lane_thumb2() {
8667 let encoder = ArmEncoder::new_thumb2();
8668 let op = ArmOp::MveExtractLane {
8669 rd: Reg::R0,
8670 qn: QReg::Q1,
8671 lane: 2,
8672 size: MveSize::S32,
8673 };
8674 let code = encoder.encode(&op).unwrap();
8675 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8676 }
8677
8678 #[test]
8679 fn test_encode_mve_insert_lane_thumb2() {
8680 let encoder = ArmEncoder::new_thumb2();
8681 let op = ArmOp::MveInsertLane {
8682 qd: QReg::Q0,
8683 rn: Reg::R1,
8684 lane: 3,
8685 size: MveSize::S32,
8686 };
8687 let code = encoder.encode(&op).unwrap();
8688 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8689 }
8690
8691 #[test]
8692 fn test_encode_mve_addf32_thumb2() {
8693 let encoder = ArmEncoder::new_thumb2();
8694 let op = ArmOp::MveAddF32 {
8695 qd: QReg::Q0,
8696 qn: QReg::Q1,
8697 qm: QReg::Q2,
8698 };
8699 let code = encoder.encode(&op).unwrap();
8700 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8701 }
8702
8703 #[test]
8704 fn test_encode_mve_divf32_thumb2() {
8705 let encoder = ArmEncoder::new_thumb2();
8706 let op = ArmOp::MveDivF32 {
8707 qd: QReg::Q0,
8708 qn: QReg::Q1,
8709 qm: QReg::Q2,
8710 };
8711 let code = encoder.encode(&op).unwrap();
8712 assert_eq!(
8714 code.len(),
8715 16,
8716 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8717 );
8718 }
8719
8720 #[test]
8721 fn test_encode_mve_sqrtf32_thumb2() {
8722 let encoder = ArmEncoder::new_thumb2();
8723 let op = ArmOp::MveSqrtF32 {
8724 qd: QReg::Q0,
8725 qm: QReg::Q1,
8726 };
8727 let code = encoder.encode(&op).unwrap();
8728 assert_eq!(
8730 code.len(),
8731 16,
8732 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8733 );
8734 }
8735
8736 #[test]
8737 fn test_encode_mve_negf32_thumb2() {
8738 let encoder = ArmEncoder::new_thumb2();
8739 let op = ArmOp::MveNegF32 {
8740 qd: QReg::Q0,
8741 qm: QReg::Q1,
8742 };
8743 let code = encoder.encode(&op).unwrap();
8744 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8745 }
8746
8747 #[test]
8748 fn test_encode_mve_absf32_thumb2() {
8749 let encoder = ArmEncoder::new_thumb2();
8750 let op = ArmOp::MveAbsF32 {
8751 qd: QReg::Q0,
8752 qm: QReg::Q1,
8753 };
8754 let code = encoder.encode(&op).unwrap();
8755 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8756 }
8757
8758 #[test]
8759 fn test_encode_mve_different_qregs() {
8760 let encoder = ArmEncoder::new_thumb2();
8761
8762 let op1 = ArmOp::MveAddI {
8764 qd: QReg::Q0,
8765 qn: QReg::Q0,
8766 qm: QReg::Q0,
8767 size: MveSize::S32,
8768 };
8769 let op2 = ArmOp::MveAddI {
8770 qd: QReg::Q3,
8771 qn: QReg::Q5,
8772 qm: QReg::Q7,
8773 size: MveSize::S32,
8774 };
8775 let code1 = encoder.encode(&op1).unwrap();
8776 let code2 = encoder.encode(&op2).unwrap();
8777 assert_ne!(
8778 code1, code2,
8779 "Different Q-registers should produce different encodings"
8780 );
8781 }
8782
8783 #[test]
8784 fn test_encode_mve_arm32_nop() {
8785 let encoder = ArmEncoder::new_arm32();
8787 let op = ArmOp::MveAddI {
8788 qd: QReg::Q0,
8789 qn: QReg::Q1,
8790 qm: QReg::Q2,
8791 size: MveSize::S32,
8792 };
8793 let code = encoder.encode(&op).unwrap();
8794 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8795 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8797 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8798 }
8799}