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_reg_offset_mem(&self, op: &ArmOp) -> Result<Option<Vec<u8>>> {
61 use synth_synthesis::Reg;
62 let addr = match op {
63 ArmOp::Ldr { addr, .. }
64 | ArmOp::Str { addr, .. }
65 | ArmOp::Ldrb { addr, .. }
66 | ArmOp::Strb { addr, .. }
67 | ArmOp::Ldrh { addr, .. }
68 | ArmOp::Strh { addr, .. }
69 | ArmOp::Ldrsb { addr, .. }
70 | ArmOp::Ldrsh { addr, .. } => addr,
71 _ => return Ok(None),
72 };
73 let Some(rm) = addr.offset_reg else {
74 return Ok(None);
75 };
76 let ip = Reg::R12;
77 let add: u32 = 0xE0800000
79 | (reg_to_bits(&addr.base) << 16)
80 | (reg_to_bits(&ip) << 12)
81 | reg_to_bits(&rm);
82 let mut bytes = add.to_le_bytes().to_vec();
83 let imm_addr = MemAddr::imm(ip, addr.offset);
86 let imm_op = match op {
87 ArmOp::Ldr { rd, .. } => ArmOp::Ldr {
88 rd: *rd,
89 addr: imm_addr,
90 },
91 ArmOp::Str { rd, .. } => ArmOp::Str {
92 rd: *rd,
93 addr: imm_addr,
94 },
95 ArmOp::Ldrb { rd, .. } => ArmOp::Ldrb {
96 rd: *rd,
97 addr: imm_addr,
98 },
99 ArmOp::Strb { rd, .. } => ArmOp::Strb {
100 rd: *rd,
101 addr: imm_addr,
102 },
103 ArmOp::Ldrh { rd, .. } => ArmOp::Ldrh {
104 rd: *rd,
105 addr: imm_addr,
106 },
107 ArmOp::Strh { rd, .. } => ArmOp::Strh {
108 rd: *rd,
109 addr: imm_addr,
110 },
111 ArmOp::Ldrsb { rd, .. } => ArmOp::Ldrsb {
112 rd: *rd,
113 addr: imm_addr,
114 },
115 ArmOp::Ldrsh { rd, .. } => ArmOp::Ldrsh {
116 rd: *rd,
117 addr: imm_addr,
118 },
119 _ => unreachable!(),
120 };
121 bytes.extend(self.encode_arm(&imm_op)?);
122 Ok(Some(bytes))
123 }
124
125 fn encode_arm(&self, op: &ArmOp) -> Result<Vec<u8>> {
126 if let Some(bytes) = self.encode_arm_reg_offset_mem(op)? {
133 return Ok(bytes);
134 }
135 let instr: u32 = match op {
136 ArmOp::Add { rd, rn, op2 } => {
138 let rd_bits = reg_to_bits(rd);
139 let rn_bits = reg_to_bits(rn);
140 let (op2_bits, i_flag) = encode_operand2(op2);
141
142 0xE0800000 | (i_flag << 25)
145 | (rn_bits << 16)
146 | (rd_bits << 12)
147 | op2_bits
148 }
149
150 ArmOp::Sub { rd, rn, op2 } => {
151 let rd_bits = reg_to_bits(rd);
152 let rn_bits = reg_to_bits(rn);
153 let (op2_bits, i_flag) = encode_operand2(op2);
154
155 0xE0400000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
157 }
158
159 ArmOp::Adds { rd, rn, op2 } => {
161 let rd_bits = reg_to_bits(rd);
162 let rn_bits = reg_to_bits(rn);
163 let (op2_bits, i_flag) = encode_operand2(op2);
164
165 0xE0900000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
167 }
168
169 ArmOp::Adc { rd, rn, op2 } => {
170 let rd_bits = reg_to_bits(rd);
171 let rn_bits = reg_to_bits(rn);
172 let (op2_bits, i_flag) = encode_operand2(op2);
173
174 0xE0A00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
176 }
177
178 ArmOp::Subs { rd, rn, op2 } => {
179 let rd_bits = reg_to_bits(rd);
180 let rn_bits = reg_to_bits(rn);
181 let (op2_bits, i_flag) = encode_operand2(op2);
182
183 0xE0500000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
185 }
186
187 ArmOp::Sbc { rd, rn, op2 } => {
188 let rd_bits = reg_to_bits(rd);
189 let rn_bits = reg_to_bits(rn);
190 let (op2_bits, i_flag) = encode_operand2(op2);
191
192 0xE0C00000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
194 }
195
196 ArmOp::Mul { rd, rn, rm } => {
197 let rd_bits = reg_to_bits(rd);
198 let rn_bits = reg_to_bits(rn);
199 let rm_bits = reg_to_bits(rm);
200
201 0xE0000090 | (rd_bits << 16) | (rn_bits << 8) | rm_bits
203 }
204
205 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
206 let rdlo_bits = reg_to_bits(rdlo);
207 let rdhi_bits = reg_to_bits(rdhi);
208 let rn_bits = reg_to_bits(rn);
209 let rm_bits = reg_to_bits(rm);
210
211 0xE0800090 | (rdhi_bits << 16) | (rdlo_bits << 12) | (rm_bits << 8) | rn_bits
213 }
214
215 ArmOp::Sdiv { rd, rn, rm } => {
216 let rd_bits = reg_to_bits(rd);
217 let rn_bits = reg_to_bits(rn);
218 let rm_bits = reg_to_bits(rm);
219
220 0xE710F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
223 }
224
225 ArmOp::Udiv { rd, rn, rm } => {
226 let rd_bits = reg_to_bits(rd);
227 let rn_bits = reg_to_bits(rn);
228 let rm_bits = reg_to_bits(rm);
229
230 0xE730F010 | (rd_bits << 16) | (rm_bits << 8) | rn_bits
233 }
234
235 ArmOp::Mls { rd, rn, rm, ra } => {
236 let rd_bits = reg_to_bits(rd);
237 let rn_bits = reg_to_bits(rn);
238 let rm_bits = reg_to_bits(rm);
239 let ra_bits = reg_to_bits(ra);
240
241 0xE0600090 | (rd_bits << 16) | (ra_bits << 12) | (rm_bits << 8) | rn_bits
244 }
245
246 ArmOp::And { rd, rn, op2 } => {
247 let rd_bits = reg_to_bits(rd);
248 let rn_bits = reg_to_bits(rn);
249 let (op2_bits, i_flag) = encode_operand2(op2);
250
251 0xE0000000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
253 }
254
255 ArmOp::Orr { rd, rn, op2 } => {
256 let rd_bits = reg_to_bits(rd);
257 let rn_bits = reg_to_bits(rn);
258 let (op2_bits, i_flag) = encode_operand2(op2);
259
260 0xE1800000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
262 }
263
264 ArmOp::Eor { rd, rn, op2 } => {
265 let rd_bits = reg_to_bits(rd);
266 let rn_bits = reg_to_bits(rn);
267 let (op2_bits, i_flag) = encode_operand2(op2);
268
269 0xE0200000 | (i_flag << 25) | (rn_bits << 16) | (rd_bits << 12) | op2_bits
271 }
272
273 ArmOp::Lsl { rd, rn, shift } => {
275 let rd_bits = reg_to_bits(rd);
276 let rn_bits = reg_to_bits(rn);
277 let shift_bits = *shift & 0x1F;
278
279 0xE1A00000 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
281 }
282
283 ArmOp::Lsr { rd, rn, shift } => {
284 let rd_bits = reg_to_bits(rd);
285 let rn_bits = reg_to_bits(rn);
286 let shift_bits = *shift & 0x1F;
287
288 0xE1A00020 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
290 }
291
292 ArmOp::Asr { rd, rn, shift } => {
293 let rd_bits = reg_to_bits(rd);
294 let rn_bits = reg_to_bits(rn);
295 let shift_bits = *shift & 0x1F;
296
297 0xE1A00040 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
299 }
300
301 ArmOp::Ror { rd, rn, shift } => {
302 let rd_bits = reg_to_bits(rd);
303 let rn_bits = reg_to_bits(rn);
304 let shift_bits = *shift & 0x1F;
305
306 0xE1A00060 | (rd_bits << 12) | (shift_bits << 7) | rn_bits
308 }
309
310 ArmOp::LslReg { rd, rn, rm } => {
313 let rd_bits = reg_to_bits(rd);
314 let rn_bits = reg_to_bits(rn);
315 let rm_bits = reg_to_bits(rm);
316 0xE1A00010 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
317 }
318 ArmOp::LsrReg { rd, rn, rm } => {
319 let rd_bits = reg_to_bits(rd);
320 let rn_bits = reg_to_bits(rn);
321 let rm_bits = reg_to_bits(rm);
322 0xE1A00030 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
323 }
324 ArmOp::AsrReg { rd, rn, rm } => {
325 let rd_bits = reg_to_bits(rd);
326 let rn_bits = reg_to_bits(rn);
327 let rm_bits = reg_to_bits(rm);
328 0xE1A00050 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
329 }
330 ArmOp::RorReg { rd, rn, rm } => {
331 let rd_bits = reg_to_bits(rd);
332 let rn_bits = reg_to_bits(rn);
333 let rm_bits = reg_to_bits(rm);
334 0xE1A00070 | (rd_bits << 12) | (rm_bits << 8) | rn_bits
335 }
336
337 ArmOp::Rsb { rd, rn, imm } => {
339 let rd_bits = reg_to_bits(rd);
340 let rn_bits = reg_to_bits(rn);
341 0xE2600000 | (rn_bits << 16) | (rd_bits << 12) | (*imm & 0xFF)
344 }
345
346 ArmOp::Clz { rd, rm } => {
348 let rd_bits = reg_to_bits(rd);
349 let rm_bits = reg_to_bits(rm);
350
351 0xE16F0F10 | (rd_bits << 12) | rm_bits
354 }
355
356 ArmOp::Rbit { rd, rm } => {
357 let rd_bits = reg_to_bits(rd);
358 let rm_bits = reg_to_bits(rm);
359
360 0xE6FF0F30 | (rd_bits << 12) | rm_bits
363 }
364
365 ArmOp::Sxtb { rd, rm } => {
366 let rd_bits = reg_to_bits(rd);
367 let rm_bits = reg_to_bits(rm);
368
369 0xE6AF0070 | (rd_bits << 12) | rm_bits
372 }
373
374 ArmOp::Sxth { rd, rm } => {
375 let rd_bits = reg_to_bits(rd);
376 let rm_bits = reg_to_bits(rm);
377
378 0xE6BF0070 | (rd_bits << 12) | rm_bits
381 }
382
383 ArmOp::Mov { rd, op2 } => {
385 let rd_bits = reg_to_bits(rd);
386 let (op2_bits, i_flag) = encode_operand2(op2);
387
388 0xE1A00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
390 }
391
392 ArmOp::Mvn { rd, op2 } => {
393 let rd_bits = reg_to_bits(rd);
394 let (op2_bits, i_flag) = encode_operand2(op2);
395
396 0xE1E00000 | (i_flag << 25) | (rd_bits << 12) | op2_bits
398 }
399
400 ArmOp::Movw { rd, imm16 } => {
403 let rd_bits = reg_to_bits(rd);
404 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
405 let imm12 = (*imm16 as u32) & 0xFFF;
406 0xE3000000 | (imm4 << 16) | (rd_bits << 12) | imm12
407 }
408
409 ArmOp::Movt { rd, imm16 } => {
412 let rd_bits = reg_to_bits(rd);
413 let imm4 = ((*imm16 as u32) >> 12) & 0xF;
414 let imm12 = (*imm16 as u32) & 0xFFF;
415 0xE3400000 | (imm4 << 16) | (rd_bits << 12) | imm12
416 }
417
418 ArmOp::Cmp { rn, op2 } => {
420 let rn_bits = reg_to_bits(rn);
421 let (op2_bits, i_flag) = encode_operand2(op2);
422
423 0xE1500000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
425 }
426
427 ArmOp::Cmn { rn, op2 } => {
429 let rn_bits = reg_to_bits(rn);
430 let (op2_bits, i_flag) = encode_operand2(op2);
431
432 0xE1700000 | (i_flag << 25) | (rn_bits << 16) | op2_bits
434 }
435
436 ArmOp::Ldr { rd, addr } => {
438 let rd_bits = reg_to_bits(rd);
439 let (base_bits, offset_bits) = encode_mem_addr(addr);
440
441 0xE5900000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
444 }
445
446 ArmOp::Str { rd, addr } => {
447 let rd_bits = reg_to_bits(rd);
448 let (base_bits, offset_bits) = encode_mem_addr(addr);
449
450 0xE5800000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
452 }
453
454 ArmOp::Ldrb { rd, addr } => {
456 let rd_bits = reg_to_bits(rd);
457 let (base_bits, offset_bits) = encode_mem_addr(addr);
458 0xE5D00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
460 }
461
462 ArmOp::Ldrsb { rd, addr } => {
463 let rd_bits = reg_to_bits(rd);
464 let (base_bits, offset_bits) = encode_mem_addr(addr);
465 let offset_val = offset_bits & 0xFF;
468 let imm4h = (offset_val >> 4) & 0xF;
469 let imm4l = offset_val & 0xF;
470 0xE1D000D0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
471 }
472
473 ArmOp::Ldrh { rd, addr } => {
474 let rd_bits = reg_to_bits(rd);
475 let (base_bits, offset_bits) = encode_mem_addr(addr);
476 let offset_val = offset_bits & 0xFF;
478 let imm4h = (offset_val >> 4) & 0xF;
479 let imm4l = offset_val & 0xF;
480 0xE1D000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
481 }
482
483 ArmOp::Ldrsh { rd, addr } => {
484 let rd_bits = reg_to_bits(rd);
485 let (base_bits, offset_bits) = encode_mem_addr(addr);
486 let offset_val = offset_bits & 0xFF;
488 let imm4h = (offset_val >> 4) & 0xF;
489 let imm4l = offset_val & 0xF;
490 0xE1D000F0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
491 }
492
493 ArmOp::Strb { rd, addr } => {
495 let rd_bits = reg_to_bits(rd);
496 let (base_bits, offset_bits) = encode_mem_addr(addr);
497 0xE5C00000 | (base_bits << 16) | (rd_bits << 12) | offset_bits
499 }
500
501 ArmOp::Strh { rd, addr } => {
502 let rd_bits = reg_to_bits(rd);
503 let (base_bits, offset_bits) = encode_mem_addr(addr);
504 let offset_val = offset_bits & 0xFF;
506 let imm4h = (offset_val >> 4) & 0xF;
507 let imm4l = offset_val & 0xF;
508 0xE1C000B0 | (base_bits << 16) | (rd_bits << 12) | (imm4h << 8) | imm4l
509 }
510
511 ArmOp::MemorySize { rd } => {
513 let rd_bits = reg_to_bits(rd);
514 0xE1A00820 | (rd_bits << 12) | 0x0A }
519
520 ArmOp::MemoryGrow { rd, .. } => {
521 let rd_bits = reg_to_bits(rd);
522 0xE3E00000 | (rd_bits << 12) }
525
526 ArmOp::Label { .. } => {
528 return Ok(Vec::new());
529 }
530
531 ArmOp::B { label: _ } => {
533 0xEA000000
536 }
537
538 ArmOp::Bcc { cond, label: _ } => {
540 use synth_synthesis::Condition;
541 let cond_bits: u32 = match cond {
542 Condition::EQ => 0x0,
543 Condition::NE => 0x1,
544 Condition::HS => 0x2,
545 Condition::LO => 0x3,
546 Condition::HI => 0x8,
547 Condition::LS => 0x9,
548 Condition::GE => 0xA,
549 Condition::LT => 0xB,
550 Condition::GT => 0xC,
551 Condition::LE => 0xD,
552 };
553 (cond_bits << 28) | 0x0A000000
555 }
556
557 ArmOp::Bhs { label: _ } => {
559 0x2A000000 }
562
563 ArmOp::Blo { label: _ } => {
565 0x3A000000 }
568
569 ArmOp::BOffset { offset } => {
573 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
583 0xEA000000 | offset_bits
584 }
585
586 ArmOp::BCondOffset { cond, offset } => {
588 use synth_synthesis::Condition;
589 let cond_bits: u32 = match cond {
590 Condition::EQ => 0x0,
591 Condition::NE => 0x1,
592 Condition::HS => 0x2,
593 Condition::LO => 0x3,
594 Condition::HI => 0x8,
595 Condition::LS => 0x9,
596 Condition::GE => 0xA,
597 Condition::LT => 0xB,
598 Condition::GT => 0xC,
599 Condition::LE => 0xD,
600 };
601 let adjusted_offset = offset.wrapping_sub(2); let offset_bits = (adjusted_offset as u32) & 0x00FFFFFF;
605 (cond_bits << 28) | 0x0A000000 | offset_bits
606 }
607
608 ArmOp::Bl { label: _ } => {
609 0xEB000000
611 }
612
613 ArmOp::Bx { rm } => {
614 let rm_bits = reg_to_bits(rm);
615
616 0xE12FFF10 | rm_bits
618 }
619
620 ArmOp::Blx { rm } => {
621 let rm_bits = reg_to_bits(rm);
622
623 0xE12FFF30 | rm_bits
625 }
626
627 ArmOp::Push { regs } => {
628 let mut reg_list: u32 = 0;
630 for r in regs {
631 reg_list |= 1 << reg_to_bits(r);
632 }
633 0xE92D0000 | reg_list
634 }
635
636 ArmOp::Pop { regs } => {
637 let mut reg_list: u32 = 0;
639 for r in regs {
640 reg_list |= 1 << reg_to_bits(r);
641 }
642 0xE8BD0000 | reg_list
643 }
644
645 ArmOp::Nop => {
646 0xE1A00000
648 }
649
650 ArmOp::Udf { imm } => {
651 let imm8 = *imm as u32;
654 0xE7F000F0 | ((imm8 & 0xF0) << 4) | (imm8 & 0x0F)
655 }
656
657 ArmOp::Popcnt { .. } => {
660 0xE1A00000 }
664
665 ArmOp::SetCond { .. } => {
666 0xE1A00000 }
670
671 ArmOp::SelectMove { .. } => {
672 0xE1A00000 }
676
677 ArmOp::Select { .. } => {
678 0xE1A00000 }
682
683 ArmOp::LocalGet { .. } => {
684 0xE1A00000 }
688
689 ArmOp::LocalSet { .. } => {
690 0xE1A00000 }
694
695 ArmOp::LocalTee { .. } => {
696 0xE1A00000 }
700
701 ArmOp::GlobalGet { .. } => {
702 0xE1A00000 }
706
707 ArmOp::GlobalSet { .. } => {
708 0xE1A00000 }
712
713 ArmOp::BrTable { .. } => {
714 0xE1A00000 }
718
719 ArmOp::Call { .. } => {
720 0xE1A00000 }
724
725 ArmOp::CallIndirect { .. } => {
726 0xE1A00000 }
730
731 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)?,
768 ArmOp::F32Sub { sd, sn, sm } => encode_vfp_3reg(0xEE300A40, sd, sn, sm)?,
769 ArmOp::F32Mul { sd, sn, sm } => encode_vfp_3reg(0xEE200A00, sd, sn, sm)?,
770 ArmOp::F32Div { sd, sn, sm } => encode_vfp_3reg(0xEE800A00, sd, sn, sm)?,
771 ArmOp::F32Abs { sd, sm } => encode_vfp_2reg(0xEEB00AC0, sd, sm)?,
772 ArmOp::F32Neg { sd, sm } => encode_vfp_2reg(0xEEB10A40, sd, sm)?,
773 ArmOp::F32Sqrt { sd, sm } => encode_vfp_2reg(0xEEB10AC0, sd, sm)?,
774
775 ArmOp::F32Ceil { sd, sm } => {
778 return self.encode_arm_f32_rounding(sd, sm, 0b01); }
780 ArmOp::F32Floor { sd, sm } => {
781 return self.encode_arm_f32_rounding(sd, sm, 0b10); }
783 ArmOp::F32Trunc { sd, sm } => {
784 return self.encode_arm_f32_rounding(sd, sm, 0b11); }
786 ArmOp::F32Nearest { sd, sm } => {
787 return self.encode_arm_f32_rounding(sd, sm, 0b00); }
789 ArmOp::F32Min { sd, sn, sm } => {
790 return self.encode_arm_f32_minmax(sd, sn, sm, true);
791 }
792 ArmOp::F32Max { sd, sn, sm } => {
793 return self.encode_arm_f32_minmax(sd, sn, sm, false);
794 }
795 ArmOp::F32Copysign { sd, sn, sm } => {
796 return self.encode_arm_f32_copysign(sd, sn, sm);
797 }
798
799 ArmOp::F32Eq { rd, sn, sm } => {
801 return self.encode_arm_f32_compare(rd, sn, sm, 0x0); }
803 ArmOp::F32Ne { rd, sn, sm } => {
804 return self.encode_arm_f32_compare(rd, sn, sm, 0x1); }
806 ArmOp::F32Lt { rd, sn, sm } => {
807 return self.encode_arm_f32_compare(rd, sn, sm, 0x4); }
809 ArmOp::F32Le { rd, sn, sm } => {
810 return self.encode_arm_f32_compare(rd, sn, sm, 0x9); }
812 ArmOp::F32Gt { rd, sn, sm } => {
813 return self.encode_arm_f32_compare(rd, sn, sm, 0xC); }
815 ArmOp::F32Ge { rd, sn, sm } => {
816 return self.encode_arm_f32_compare(rd, sn, sm, 0xA); }
818
819 ArmOp::F32Const { sd, value } => {
821 return self.encode_arm_f32_const(sd, *value);
822 }
823
824 ArmOp::F32Load { sd, addr } => encode_vfp_ldst(0xED900A00, sd, addr)?,
825 ArmOp::F32Store { sd, addr } => encode_vfp_ldst(0xED800A00, sd, addr)?,
826
827 ArmOp::F32ConvertI32S { sd, rm } => {
829 return self.encode_arm_f32_convert_i32(sd, rm, true);
830 }
831 ArmOp::F32ConvertI32U { sd, rm } => {
832 return self.encode_arm_f32_convert_i32(sd, rm, false);
833 }
834 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
835 return Err(synth_core::Error::synthesis(
836 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
837 ));
838 }
839 ArmOp::F32ReinterpretI32 { sd, rm } => encode_vmov_core_sreg(true, sd, rm)?,
840 ArmOp::I32ReinterpretF32 { rd, sm } => encode_vmov_core_sreg(false, sm, rd)?,
841 ArmOp::I32TruncF32S { rd, sm } => {
842 return self.encode_arm_i32_trunc_f32(rd, sm, true);
843 }
844 ArmOp::I32TruncF32U { rd, sm } => {
845 return self.encode_arm_i32_trunc_f32(rd, sm, false);
846 }
847
848 ArmOp::F64Add { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B00, dd, dn, dm)?,
851 ArmOp::F64Sub { dd, dn, dm } => encode_vfp_3reg_f64(0xEE300B40, dd, dn, dm)?,
852 ArmOp::F64Mul { dd, dn, dm } => encode_vfp_3reg_f64(0xEE200B00, dd, dn, dm)?,
853 ArmOp::F64Div { dd, dn, dm } => encode_vfp_3reg_f64(0xEE800B00, dd, dn, dm)?,
854 ArmOp::F64Abs { dd, dm } => encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?,
855 ArmOp::F64Neg { dd, dm } => encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?,
856 ArmOp::F64Sqrt { dd, dm } => encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?,
857
858 ArmOp::F64Ceil { dd, dm } => {
861 return self.encode_arm_f64_rounding(dd, dm, 0b01);
862 }
863 ArmOp::F64Floor { dd, dm } => {
864 return self.encode_arm_f64_rounding(dd, dm, 0b10);
865 }
866 ArmOp::F64Trunc { dd, dm } => {
867 return self.encode_arm_f64_rounding(dd, dm, 0b11);
868 }
869 ArmOp::F64Nearest { dd, dm } => {
870 return self.encode_arm_f64_rounding(dd, dm, 0b00);
871 }
872 ArmOp::F64Min { dd, dn, dm } => {
873 return self.encode_arm_f64_minmax(dd, dn, dm, true);
874 }
875 ArmOp::F64Max { dd, dn, dm } => {
876 return self.encode_arm_f64_minmax(dd, dn, dm, false);
877 }
878 ArmOp::F64Copysign { dd, dn, dm } => {
879 return self.encode_arm_f64_copysign(dd, dn, dm);
880 }
881
882 ArmOp::F64Eq { rd, dn, dm } => {
884 return self.encode_arm_f64_compare(rd, dn, dm, 0x0);
885 }
886 ArmOp::F64Ne { rd, dn, dm } => {
887 return self.encode_arm_f64_compare(rd, dn, dm, 0x1);
888 }
889 ArmOp::F64Lt { rd, dn, dm } => {
890 return self.encode_arm_f64_compare(rd, dn, dm, 0x4);
891 }
892 ArmOp::F64Le { rd, dn, dm } => {
893 return self.encode_arm_f64_compare(rd, dn, dm, 0x9);
894 }
895 ArmOp::F64Gt { rd, dn, dm } => {
896 return self.encode_arm_f64_compare(rd, dn, dm, 0xC);
897 }
898 ArmOp::F64Ge { rd, dn, dm } => {
899 return self.encode_arm_f64_compare(rd, dn, dm, 0xA);
900 }
901
902 ArmOp::F64Const { dd, value } => {
903 return self.encode_arm_f64_const(dd, *value);
904 }
905
906 ArmOp::F64Load { dd, addr } => encode_vfp_ldst_f64(0xED900B00, dd, addr)?,
907 ArmOp::F64Store { dd, addr } => encode_vfp_ldst_f64(0xED800B00, dd, addr)?,
908
909 ArmOp::F64ConvertI32S { dd, rm } => {
910 return self.encode_arm_f64_convert_i32(dd, rm, true);
911 }
912 ArmOp::F64ConvertI32U { dd, rm } => {
913 return self.encode_arm_f64_convert_i32(dd, rm, false);
914 }
915 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
916 return Err(synth_core::Error::synthesis(
917 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
918 ));
919 }
920 ArmOp::F64PromoteF32 { dd, sm } => {
921 return self.encode_arm_f64_promote_f32(dd, sm);
922 }
923 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => {
924 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?
925 }
926 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => {
927 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?
928 }
929 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
930 return Err(synth_core::Error::synthesis(
931 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
932 ));
933 }
934 ArmOp::I32TruncF64S { rd, dm } => {
935 return self.encode_arm_i32_trunc_f64(rd, dm, true);
936 }
937 ArmOp::I32TruncF64U { rd, dm } => {
938 return self.encode_arm_i32_trunc_f64(rd, dm, false);
939 }
940 ArmOp::I64SetCond { .. }
942 | ArmOp::I64SetCondZ { .. }
943 | ArmOp::I64Mul { .. }
944 | ArmOp::I64Shl { .. }
945 | ArmOp::I64ShrS { .. }
946 | ArmOp::I64ShrU { .. }
947 | ArmOp::I64Rotl { .. }
948 | ArmOp::I64Rotr { .. } => 0xE1A00000, ArmOp::MveLoad { .. }
952 | ArmOp::MveStore { .. }
953 | ArmOp::MveConst { .. }
954 | ArmOp::MveAnd { .. }
955 | ArmOp::MveOrr { .. }
956 | ArmOp::MveEor { .. }
957 | ArmOp::MveMvn { .. }
958 | ArmOp::MveBic { .. }
959 | ArmOp::MveAddI { .. }
960 | ArmOp::MveSubI { .. }
961 | ArmOp::MveMulI { .. }
962 | ArmOp::MveNegI { .. }
963 | ArmOp::MveCmpEqI { .. }
964 | ArmOp::MveCmpNeI { .. }
965 | ArmOp::MveCmpLtS { .. }
966 | ArmOp::MveCmpLtU { .. }
967 | ArmOp::MveCmpGtS { .. }
968 | ArmOp::MveCmpGtU { .. }
969 | ArmOp::MveCmpLeS { .. }
970 | ArmOp::MveCmpLeU { .. }
971 | ArmOp::MveCmpGeS { .. }
972 | ArmOp::MveCmpGeU { .. }
973 | ArmOp::MveDup { .. }
974 | ArmOp::MveExtractLane { .. }
975 | ArmOp::MveInsertLane { .. }
976 | ArmOp::MveAddF32 { .. }
977 | ArmOp::MveSubF32 { .. }
978 | ArmOp::MveMulF32 { .. }
979 | ArmOp::MveNegF32 { .. }
980 | ArmOp::MveAbsF32 { .. }
981 | ArmOp::MveCmpEqF32 { .. }
982 | ArmOp::MveCmpNeF32 { .. }
983 | ArmOp::MveCmpLtF32 { .. }
984 | ArmOp::MveCmpLeF32 { .. }
985 | ArmOp::MveCmpGtF32 { .. }
986 | ArmOp::MveCmpGeF32 { .. }
987 | ArmOp::MveDupF32 { .. }
988 | ArmOp::MveExtractLaneF32 { .. }
989 | ArmOp::MveReplaceLaneF32 { .. }
990 | ArmOp::MveDivF32 { .. }
991 | ArmOp::MveSqrtF32 { .. } => 0xE1A00000, };
993
994 Ok(instr.to_le_bytes().to_vec())
996 }
997
998 fn encode_arm_f32_compare(
1002 &self,
1003 rd: &Reg,
1004 sn: &VfpReg,
1005 sm: &VfpReg,
1006 cond_code: u32,
1007 ) -> Result<Vec<u8>> {
1008 let mut bytes = Vec::new();
1009
1010 let sn_num = vfp_sreg_to_num(sn)?;
1012 let sm_num = vfp_sreg_to_num(sm)?;
1013 let (vd, d) = encode_sreg(sn_num);
1014 let (vm, m) = encode_sreg(sm_num);
1015 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1016 bytes.extend_from_slice(&vcmp.to_le_bytes());
1017
1018 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1020
1021 let rd_bits = reg_to_bits(rd);
1023 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1024 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1025
1026 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1028 bytes.extend_from_slice(&mov_one.to_le_bytes());
1029
1030 Ok(bytes)
1031 }
1032
1033 fn encode_arm_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
1035 let mut bytes = Vec::new();
1036 let bits = value.to_bits();
1037
1038 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
1043 let movw = 0xE3000000 | (rt << 12) | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1044 bytes.extend_from_slice(&movw.to_le_bytes());
1045
1046 let hi16 = (bits >> 16) & 0xFFFF;
1048 let movt = 0xE3400000 | (rt << 12) | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1049 bytes.extend_from_slice(&movt.to_le_bytes());
1050
1051 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
1053 bytes.extend_from_slice(&vmov.to_le_bytes());
1054
1055 Ok(bytes)
1056 }
1057
1058 fn encode_arm_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1060 let mut bytes = Vec::new();
1061
1062 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
1064 bytes.extend_from_slice(&vmov.to_le_bytes());
1065
1066 let sd_num = vfp_sreg_to_num(sd)?;
1069 let (vd, d) = encode_sreg(sd_num);
1070 let (vm, m) = encode_sreg(sd_num); let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
1072 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1073 bytes.extend_from_slice(&vcvt.to_le_bytes());
1074
1075 Ok(bytes)
1076 }
1077
1078 fn encode_arm_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1090 let mut bytes = Vec::new();
1091 let sm_num = vfp_sreg_to_num(sm)?;
1092 let sd_num = vfp_sreg_to_num(sd)?;
1093 let (vd_s, d_s) = encode_sreg(sd_num);
1094 let (vm_s, m_s) = encode_sreg(sm_num);
1095
1096 if mode == 0b11 {
1097 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1100 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1101 } else {
1102 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
1107 bytes.extend_from_slice(&vmrs.to_le_bytes());
1108
1109 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1112 bytes.extend_from_slice(&bic.to_le_bytes());
1113
1114 if mode != 0 {
1116 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1118 bytes.extend_from_slice(&orr.to_le_bytes());
1119 }
1120
1121 let vmsr = 0xEEE10A10 | (rt << 12);
1123 bytes.extend_from_slice(&vmsr.to_le_bytes());
1124
1125 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
1127 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1128
1129 bytes.extend_from_slice(&vmrs.to_le_bytes());
1131 bytes.extend_from_slice(&bic.to_le_bytes());
1132 bytes.extend_from_slice(&vmsr.to_le_bytes());
1133 }
1134
1135 let (vd2, d2) = encode_sreg(sd_num);
1137 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
1138 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1139
1140 Ok(bytes)
1141 }
1142
1143 fn encode_arm_f32_minmax(
1145 &self,
1146 sd: &VfpReg,
1147 sn: &VfpReg,
1148 sm: &VfpReg,
1149 is_min: bool,
1150 ) -> Result<Vec<u8>> {
1151 let mut bytes = Vec::new();
1152 let sn_num = vfp_sreg_to_num(sn)?;
1153 let sm_num = vfp_sreg_to_num(sm)?;
1154 let sd_num = vfp_sreg_to_num(sd)?;
1155
1156 let (vd, d) = encode_sreg(sd_num);
1158 let (vn, n) = encode_sreg(sn_num);
1159 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1160 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1161
1162 let (vm, m) = encode_sreg(sm_num);
1164 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1165 bytes.extend_from_slice(&vcmp.to_le_bytes());
1166
1167 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1169
1170 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1173
1174 let vmov_cond = (cond << 28) | 0x0EB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1176 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1177
1178 Ok(bytes)
1179 }
1180
1181 fn encode_arm_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1183 let mut bytes = Vec::new();
1184
1185 let vmov_sm = encode_vmov_core_sreg(false, sm, &Reg::R12)?;
1187 bytes.extend_from_slice(&vmov_sm.to_le_bytes());
1188
1189 let vmov_sn = encode_vmov_core_sreg(false, sn, &Reg::R0)?;
1191 bytes.extend_from_slice(&vmov_sn.to_le_bytes());
1192
1193 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1197 bytes.extend_from_slice(&and_sign.to_le_bytes());
1198
1199 let bic_sign = 0xE3C00000u32 | (1 << 8) | 0x02;
1202 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1203
1204 let orr = 0xE1800000u32 | 12;
1207 bytes.extend_from_slice(&orr.to_le_bytes());
1208
1209 let vmov_result = encode_vmov_core_sreg(true, sd, &Reg::R0)?;
1211 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1212
1213 Ok(bytes)
1214 }
1215
1216 fn encode_arm_f64_compare(
1218 &self,
1219 rd: &Reg,
1220 dn: &VfpReg,
1221 dm: &VfpReg,
1222 cond_code: u32,
1223 ) -> Result<Vec<u8>> {
1224 let mut bytes = Vec::new();
1225
1226 let dn_num = vfp_dreg_to_num(dn)?;
1228 let dm_num = vfp_dreg_to_num(dm)?;
1229 let (vd, d) = encode_dreg(dn_num);
1230 let (vm, m) = encode_dreg(dm_num);
1231 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1232 bytes.extend_from_slice(&vcmp.to_le_bytes());
1233
1234 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1236
1237 let rd_bits = reg_to_bits(rd);
1239 let mov_zero = 0xE3A00000 | (rd_bits << 12);
1240 bytes.extend_from_slice(&mov_zero.to_le_bytes());
1241
1242 let mov_one = (cond_code << 28) | 0x03A00001 | (rd_bits << 12);
1244 bytes.extend_from_slice(&mov_one.to_le_bytes());
1245
1246 Ok(bytes)
1247 }
1248
1249 fn encode_arm_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
1251 let mut bytes = Vec::new();
1252 let bits = value.to_bits();
1253 let lo32 = bits as u32;
1254 let hi32 = (bits >> 32) as u32;
1255
1256 let lo16 = lo32 & 0xFFFF;
1258 let movw_r0 = 0xE3000000 | ((lo16 >> 12) << 16) | (lo16 & 0xFFF);
1259 bytes.extend_from_slice(&movw_r0.to_le_bytes());
1260 let hi16 = (lo32 >> 16) & 0xFFFF;
1261 let movt_r0 = 0xE3400000 | ((hi16 >> 12) << 16) | (hi16 & 0xFFF);
1262 bytes.extend_from_slice(&movt_r0.to_le_bytes());
1263
1264 let lo16 = hi32 & 0xFFFF;
1266 let movw_r12 = 0xE3000000 | ((lo16 >> 12) << 16) | (12 << 12) | (lo16 & 0xFFF);
1267 bytes.extend_from_slice(&movw_r12.to_le_bytes());
1268 let hi16 = (hi32 >> 16) & 0xFFFF;
1269 let movt_r12 = 0xE3400000 | ((hi16 >> 12) << 16) | (12 << 12) | (hi16 & 0xFFF);
1270 bytes.extend_from_slice(&movt_r12.to_le_bytes());
1271
1272 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
1274 bytes.extend_from_slice(&vmov.to_le_bytes());
1275
1276 Ok(bytes)
1277 }
1278
1279 fn encode_arm_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
1281 let mut bytes = Vec::new();
1282
1283 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
1285 bytes.extend_from_slice(&vmov.to_le_bytes());
1286
1287 let dd_num = vfp_dreg_to_num(dd)?;
1290 let (vd, d) = encode_dreg(dd_num);
1291 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
1292 let vcvt = base | (d << 22) | (vd << 12);
1294 bytes.extend_from_slice(&vcvt.to_le_bytes());
1295
1296 Ok(bytes)
1297 }
1298
1299 fn encode_arm_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
1301 let dd_num = vfp_dreg_to_num(dd)?;
1302 let sm_num = vfp_sreg_to_num(sm)?;
1303 let (vd, d) = encode_dreg(dd_num);
1304 let (vm, m) = encode_sreg(sm_num);
1305
1306 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
1308 Ok(vcvt.to_le_bytes().to_vec())
1309 }
1310
1311 fn encode_arm_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1313 let mut bytes = Vec::new();
1314 let dm_num = vfp_dreg_to_num(dm)?;
1315 let (vm, m) = encode_dreg(dm_num);
1316
1317 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
1320 let vcvt = base | (m << 5) | vm;
1321 bytes.extend_from_slice(&vcvt.to_le_bytes());
1322
1323 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
1325 bytes.extend_from_slice(&vmov.to_le_bytes());
1326
1327 Ok(bytes)
1328 }
1329
1330 fn encode_arm_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
1338 let mut bytes = Vec::new();
1339 let dm_num = vfp_dreg_to_num(dm)?;
1340 let dd_num = vfp_dreg_to_num(dd)?;
1341 let (vm, m) = encode_dreg(dm_num);
1342 let (vd, d) = encode_dreg(dd_num);
1343
1344 if mode == 0b11 {
1345 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
1347 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1348 } else {
1349 let rt: u32 = 12;
1351
1352 let vmrs = 0xEEF10A10 | (rt << 12);
1354 bytes.extend_from_slice(&vmrs.to_le_bytes());
1355
1356 let bic = 0xE3CC0000 | (rt << 12) | (0x05 << 8) | 0x03;
1358 bytes.extend_from_slice(&bic.to_le_bytes());
1359
1360 if mode != 0 {
1362 let orr = 0xE38C0000 | (rt << 12) | (0x05 << 8) | (mode as u32);
1363 bytes.extend_from_slice(&orr.to_le_bytes());
1364 }
1365
1366 let vmsr = 0xEEE10A10 | (rt << 12);
1368 bytes.extend_from_slice(&vmsr.to_le_bytes());
1369
1370 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
1372 bytes.extend_from_slice(&vcvt_to_int.to_le_bytes());
1373
1374 bytes.extend_from_slice(&vmrs.to_le_bytes());
1376 bytes.extend_from_slice(&bic.to_le_bytes());
1377 bytes.extend_from_slice(&vmsr.to_le_bytes());
1378 }
1379
1380 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
1382 bytes.extend_from_slice(&vcvt_to_float.to_le_bytes());
1383
1384 Ok(bytes)
1385 }
1386
1387 fn encode_arm_f64_minmax(
1389 &self,
1390 dd: &VfpReg,
1391 dn: &VfpReg,
1392 dm: &VfpReg,
1393 is_min: bool,
1394 ) -> Result<Vec<u8>> {
1395 let mut bytes = Vec::new();
1396 let dn_num = vfp_dreg_to_num(dn)?;
1397 let dm_num = vfp_dreg_to_num(dm)?;
1398 let dd_num = vfp_dreg_to_num(dd)?;
1399
1400 let (vd, d) = encode_dreg(dd_num);
1402 let (vn, n) = encode_dreg(dn_num);
1403 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
1404 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1405
1406 let (vm, m) = encode_dreg(dm_num);
1408 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
1409 bytes.extend_from_slice(&vcmp.to_le_bytes());
1410
1411 bytes.extend_from_slice(&0xEEF1FA10u32.to_le_bytes());
1413
1414 let cond = if is_min { 0xCu32 } else { 0x4u32 };
1415 let vmov_cond = (cond << 28) | 0x0EB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
1416 bytes.extend_from_slice(&vmov_cond.to_le_bytes());
1417
1418 Ok(bytes)
1419 }
1420
1421 fn encode_arm_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
1423 let mut bytes = Vec::new();
1424
1425 let vmov_dm = encode_vmov_core_dreg(false, dm, &Reg::R0, &Reg::R12)?;
1427 bytes.extend_from_slice(&vmov_dm.to_le_bytes());
1428
1429 let vmov_dn = encode_vmov_core_dreg(false, dn, &Reg::R1, &Reg::R2)?;
1432 bytes.extend_from_slice(&vmov_dn.to_le_bytes());
1433
1434 let and_sign = 0xE2000000u32 | (12 << 16) | (12 << 12) | (1 << 8) | 0x02;
1436 bytes.extend_from_slice(&and_sign.to_le_bytes());
1437
1438 let bic_sign = 0xE3C00000u32 | (2 << 16) | (2 << 12) | (1 << 8) | 0x02;
1440 bytes.extend_from_slice(&bic_sign.to_le_bytes());
1441
1442 let orr = 0xE1800000u32 | (2 << 16) | (2 << 12) | 12;
1444 bytes.extend_from_slice(&orr.to_le_bytes());
1445
1446 let vmov_result = encode_vmov_core_dreg(true, dd, &Reg::R1, &Reg::R2)?;
1448 bytes.extend_from_slice(&vmov_result.to_le_bytes());
1449
1450 Ok(bytes)
1451 }
1452
1453 fn encode_arm_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
1455 let mut bytes = Vec::new();
1456
1457 let sm_num = vfp_sreg_to_num(sm)?;
1460 let (vd, d) = encode_sreg(sm_num);
1461 let (vm, m) = encode_sreg(sm_num);
1462 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
1463 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
1464 bytes.extend_from_slice(&vcvt.to_le_bytes());
1465
1466 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
1468 bytes.extend_from_slice(&vmov.to_le_bytes());
1469
1470 Ok(bytes)
1471 }
1472
1473 fn encode_thumb(&self, op: &ArmOp) -> Result<Vec<u8>> {
1475 match op {
1478 ArmOp::Add { rd, rn, op2 } => {
1480 let rd_bits = reg_to_bits(rd) as u16;
1481 let rn_bits = reg_to_bits(rn) as u16;
1482
1483 if let Operand2::Reg(rm) = op2 {
1484 let rm_bits = reg_to_bits(rm) as u16;
1485 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1493 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1495 Ok(instr.to_le_bytes().to_vec())
1496 } else {
1497 self.encode_thumb32_add_reg_raw(
1499 rd_bits as u32,
1500 rn_bits as u32,
1501 rm_bits as u32,
1502 )
1503 }
1504 } else if let Operand2::Imm(imm) = op2 {
1505 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1506 let instr: u16 = 0x1C00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1508 Ok(instr.to_le_bytes().to_vec())
1509 } else {
1510 self.encode_thumb32_add(rd, rn, *imm as u32)
1512 }
1513 } else {
1514 self.encode_thumb32_add(rd, rn, 0)
1516 }
1517 }
1518
1519 ArmOp::Sub { rd, rn, op2 } => {
1520 let rd_bits = reg_to_bits(rd) as u16;
1521 let rn_bits = reg_to_bits(rn) as u16;
1522
1523 if let Operand2::Reg(rm) = op2 {
1524 let rm_bits = reg_to_bits(rm) as u16;
1525 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1527 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1529 Ok(instr.to_le_bytes().to_vec())
1530 } else {
1531 self.encode_thumb32_sub_reg_raw(
1533 rd_bits as u32,
1534 rn_bits as u32,
1535 rm_bits as u32,
1536 )
1537 }
1538 } else if let Operand2::Imm(imm) = op2 {
1539 if *imm <= 7 && rd_bits < 8 && rn_bits < 8 {
1540 let instr: u16 = 0x1E00 | ((*imm as u16) << 6) | (rn_bits << 3) | rd_bits;
1542 Ok(instr.to_le_bytes().to_vec())
1543 } else {
1544 self.encode_thumb32_sub(rd, rn, *imm as u32)
1545 }
1546 } else {
1547 self.encode_thumb32_sub(rd, rn, 0)
1548 }
1549 }
1550
1551 ArmOp::Mov { rd, op2 } => {
1552 let rd_bits = reg_to_bits(rd) as u16;
1553
1554 if let Operand2::Imm(imm) = op2 {
1555 if *imm <= 255 && rd_bits < 8 {
1556 let imm_bits = (*imm as u16) & 0xFF;
1558 let instr: u16 = 0x2000 | (rd_bits << 8) | imm_bits;
1559 Ok(instr.to_le_bytes().to_vec())
1560 } else {
1561 self.encode_thumb32_movw(rd, *imm as u32)
1563 }
1564 } else if let Operand2::Reg(rm) = op2 {
1565 let rm_bits = reg_to_bits(rm) as u16;
1566 let d_bit = (rd_bits >> 3) & 1;
1569 let instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
1570 Ok(instr.to_le_bytes().to_vec())
1571 } else {
1572 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1574 }
1575 }
1576
1577 ArmOp::Push { regs } => {
1578 let mut reg_list: u16 = 0;
1582 let mut need_32bit = false;
1583 for r in regs {
1584 let bit = reg_to_bits(r);
1585 if bit >= 8 && *r != Reg::LR {
1586 need_32bit = true;
1587 }
1588 reg_list |= 1 << bit;
1589 }
1590 if !need_32bit {
1591 let m_bit = if reg_list & (1 << 14) != 0 {
1593 1u16
1594 } else {
1595 0u16
1596 };
1597 let low_regs = reg_list & 0xFF;
1598 let instr: u16 = 0xB400 | (m_bit << 8) | low_regs;
1599 Ok(instr.to_le_bytes().to_vec())
1600 } else {
1601 let hw1: u16 = 0xE92D;
1603 let hw2: u16 = reg_list;
1604 let mut bytes = hw1.to_le_bytes().to_vec();
1605 bytes.extend_from_slice(&hw2.to_le_bytes());
1606 Ok(bytes)
1607 }
1608 }
1609
1610 ArmOp::Pop { regs } => {
1611 let mut reg_list: u16 = 0;
1615 let mut need_32bit = false;
1616 for r in regs {
1617 let bit = reg_to_bits(r);
1618 if bit >= 8 && *r != Reg::PC {
1619 need_32bit = true;
1620 }
1621 reg_list |= 1 << bit;
1622 }
1623 if !need_32bit {
1624 let p_bit = if reg_list & (1 << 15) != 0 {
1626 1u16
1627 } else {
1628 0u16
1629 };
1630 let low_regs = reg_list & 0xFF;
1631 let instr: u16 = 0xBC00 | (p_bit << 8) | low_regs;
1632 Ok(instr.to_le_bytes().to_vec())
1633 } else {
1634 let hw1: u16 = 0xE8BD;
1636 let hw2: u16 = reg_list;
1637 let mut bytes = hw1.to_le_bytes().to_vec();
1638 bytes.extend_from_slice(&hw2.to_le_bytes());
1639 Ok(bytes)
1640 }
1641 }
1642
1643 ArmOp::Nop => {
1644 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
1646 }
1647
1648 ArmOp::Udf { imm } => {
1649 let instr: u16 = 0xDE00 | (*imm as u16);
1652 let bytes = instr.to_le_bytes().to_vec();
1653 encoding_contracts::verify_thumb16(&bytes);
1654 Ok(bytes)
1655 }
1656
1657 ArmOp::Adds { rd, rn, op2 } => {
1660 let rd_bits = reg_to_bits(rd) as u16;
1661 let rn_bits = reg_to_bits(rn) as u16;
1662
1663 if let Operand2::Reg(rm) = op2 {
1664 let rm_bits = reg_to_bits(rm) as u16;
1665 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1670 let instr: u16 = 0x1800 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1672 Ok(instr.to_le_bytes().to_vec())
1673 } else {
1674 self.encode_thumb32_adds_reg_raw(
1675 rd_bits as u32,
1676 rn_bits as u32,
1677 rm_bits as u32,
1678 )
1679 }
1680 } else {
1681 self.encode_thumb32_adds(rd, rn, 0)
1683 }
1684 }
1685
1686 ArmOp::Adc { rd, rn, op2 } => {
1689 let rd_bits = reg_to_bits(rd);
1690 let rn_bits = reg_to_bits(rn);
1691
1692 if let Operand2::Reg(rm) = op2 {
1693 let rm_bits = reg_to_bits(rm);
1694 let hw1: u16 = (0xEB40 | rn_bits) as u16;
1696 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1697
1698 let mut bytes = hw1.to_le_bytes().to_vec();
1699 bytes.extend_from_slice(&hw2.to_le_bytes());
1700 Ok(bytes)
1701 } else {
1702 let hw1: u16 = (0xF140 | rn_bits) as u16;
1704 let hw2: u16 = (rd_bits << 8) as u16;
1705 let mut bytes = hw1.to_le_bytes().to_vec();
1706 bytes.extend_from_slice(&hw2.to_le_bytes());
1707 Ok(bytes)
1708 }
1709 }
1710
1711 ArmOp::Subs { rd, rn, op2 } => {
1713 let rd_bits = reg_to_bits(rd) as u16;
1714 let rn_bits = reg_to_bits(rn) as u16;
1715
1716 if let Operand2::Reg(rm) = op2 {
1717 let rm_bits = reg_to_bits(rm) as u16;
1718 if rd_bits < 8 && rn_bits < 8 && rm_bits < 8 {
1722 let instr: u16 = 0x1A00 | (rm_bits << 6) | (rn_bits << 3) | rd_bits;
1724 Ok(instr.to_le_bytes().to_vec())
1725 } else {
1726 self.encode_thumb32_subs_reg_raw(
1727 rd_bits as u32,
1728 rn_bits as u32,
1729 rm_bits as u32,
1730 )
1731 }
1732 } else {
1733 self.encode_thumb32_subs(rd, rn, 0)
1735 }
1736 }
1737
1738 ArmOp::Sbc { rd, rn, op2 } => {
1741 let rd_bits = reg_to_bits(rd);
1742 let rn_bits = reg_to_bits(rn);
1743
1744 if let Operand2::Reg(rm) = op2 {
1745 let rm_bits = reg_to_bits(rm);
1746 let hw1: u16 = (0xEB60 | rn_bits) as u16;
1748 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1749
1750 let mut bytes = hw1.to_le_bytes().to_vec();
1751 bytes.extend_from_slice(&hw2.to_le_bytes());
1752 Ok(bytes)
1753 } else {
1754 let hw1: u16 = (0xF160 | rn_bits) as u16;
1756 let hw2: u16 = (rd_bits << 8) as u16;
1757 let mut bytes = hw1.to_le_bytes().to_vec();
1758 bytes.extend_from_slice(&hw2.to_le_bytes());
1759 Ok(bytes)
1760 }
1761 }
1762
1763 ArmOp::Sdiv { rd, rn, rm } => {
1767 let rd_bits = reg_to_bits(rd);
1768 let rn_bits = reg_to_bits(rn);
1769 let rm_bits = reg_to_bits(rm);
1770 reg_bits_checked(rd_bits)?;
1771 reg_bits_checked(rn_bits)?;
1772 reg_bits_checked(rm_bits)?;
1773
1774 let hw1: u16 = (0xFB90 | rn_bits) as u16;
1778 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1779
1780 let mut bytes = hw1.to_le_bytes().to_vec();
1782 bytes.extend_from_slice(&hw2.to_le_bytes());
1783 encoding_contracts::verify_thumb32(&bytes);
1784 Ok(bytes)
1785 }
1786
1787 ArmOp::Udiv { rd, rn, rm } => {
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 reg_bits_checked(rd_bits)?;
1793 reg_bits_checked(rn_bits)?;
1794 reg_bits_checked(rm_bits)?;
1795
1796 let hw1: u16 = (0xFBB0 | rn_bits) as u16;
1798 let hw2: u16 = (0xF0F0 | (rd_bits << 8) | rm_bits) as u16;
1799
1800 let mut bytes = hw1.to_le_bytes().to_vec();
1801 bytes.extend_from_slice(&hw2.to_le_bytes());
1802 encoding_contracts::verify_thumb32(&bytes);
1803 Ok(bytes)
1804 }
1805
1806 ArmOp::Umull { rdlo, rdhi, rn, rm } => {
1807 let rdlo_bits = reg_to_bits(rdlo);
1808 let rdhi_bits = reg_to_bits(rdhi);
1809 let rn_bits = reg_to_bits(rn);
1810 let rm_bits = reg_to_bits(rm);
1811 reg_bits_checked(rdlo_bits)?;
1812 reg_bits_checked(rdhi_bits)?;
1813 reg_bits_checked(rn_bits)?;
1814 reg_bits_checked(rm_bits)?;
1815
1816 let hw1: u16 = (0xFBA0 | rn_bits) as u16;
1818 let hw2: u16 = ((rdlo_bits << 12) | (rdhi_bits << 8) | rm_bits) as u16;
1819
1820 let mut bytes = hw1.to_le_bytes().to_vec();
1821 bytes.extend_from_slice(&hw2.to_le_bytes());
1822 encoding_contracts::verify_thumb32(&bytes);
1823 Ok(bytes)
1824 }
1825
1826 ArmOp::Mul { rd, rn, rm } => {
1828 let rd_bits = reg_to_bits(rd);
1829 let rn_bits = reg_to_bits(rn);
1830 let rm_bits = reg_to_bits(rm);
1831
1832 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1835 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
1836
1837 let mut bytes = hw1.to_le_bytes().to_vec();
1838 bytes.extend_from_slice(&hw2.to_le_bytes());
1839 Ok(bytes)
1840 }
1841
1842 ArmOp::Mls { rd, rn, rm, ra } => {
1844 let rd_bits = reg_to_bits(rd);
1845 let rn_bits = reg_to_bits(rn);
1846 let rm_bits = reg_to_bits(rm);
1847 let ra_bits = reg_to_bits(ra);
1848
1849 let hw1: u16 = (0xFB00 | rn_bits) as u16;
1852 let hw2: u16 = ((ra_bits << 12) | (rd_bits << 8) | 0x10 | rm_bits) as u16;
1853
1854 let mut bytes = hw1.to_le_bytes().to_vec();
1855 bytes.extend_from_slice(&hw2.to_le_bytes());
1856 Ok(bytes)
1857 }
1858
1859 ArmOp::And { rd, rn, op2 } => {
1861 if let Operand2::Reg(rm) = op2 {
1862 let rd_bits = reg_to_bits(rd);
1863 let rn_bits = reg_to_bits(rn);
1864 let rm_bits = reg_to_bits(rm);
1865
1866 let hw1: u16 = (0xEA00 | rn_bits) as u16;
1868 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1869
1870 let mut bytes = hw1.to_le_bytes().to_vec();
1871 bytes.extend_from_slice(&hw2.to_le_bytes());
1872 Ok(bytes)
1873 } else if let Operand2::Imm(imm) = op2 {
1874 let rd_bits = reg_to_bits(rd);
1875 let rn_bits = reg_to_bits(rn);
1876 let imm_val = *imm as u32;
1877
1878 let i_bit = (imm_val >> 11) & 1;
1880 let imm3 = (imm_val >> 8) & 0x7;
1881 let imm8 = imm_val & 0xFF;
1882
1883 let hw1: u16 = (0xF000 | (i_bit << 10) | rn_bits) as u16;
1884 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
1885
1886 let mut bytes = hw1.to_le_bytes().to_vec();
1887 bytes.extend_from_slice(&hw2.to_le_bytes());
1888 Ok(bytes)
1889 } else {
1890 let instr: u16 = 0xBF00;
1892 Ok(instr.to_le_bytes().to_vec())
1893 }
1894 }
1895
1896 ArmOp::Orr { rd, rn, op2 } => {
1898 if let Operand2::Reg(rm) = op2 {
1899 let rd_bits = reg_to_bits(rd);
1900 let rn_bits = reg_to_bits(rn);
1901 let rm_bits = reg_to_bits(rm);
1902
1903 let hw1: u16 = (0xEA40 | rn_bits) as u16;
1905 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1906
1907 let mut bytes = hw1.to_le_bytes().to_vec();
1908 bytes.extend_from_slice(&hw2.to_le_bytes());
1909 Ok(bytes)
1910 } else {
1911 let instr: u16 = 0xBF00;
1912 Ok(instr.to_le_bytes().to_vec())
1913 }
1914 }
1915
1916 ArmOp::Eor { rd, rn, op2 } => {
1918 if let Operand2::Reg(rm) = op2 {
1919 let rd_bits = reg_to_bits(rd);
1920 let rn_bits = reg_to_bits(rn);
1921 let rm_bits = reg_to_bits(rm);
1922
1923 let hw1: u16 = (0xEA80 | rn_bits) as u16;
1925 let hw2: u16 = ((rd_bits << 8) | rm_bits) as u16;
1926
1927 let mut bytes = hw1.to_le_bytes().to_vec();
1928 bytes.extend_from_slice(&hw2.to_le_bytes());
1929 Ok(bytes)
1930 } else {
1931 let instr: u16 = 0xBF00;
1932 Ok(instr.to_le_bytes().to_vec())
1933 }
1934 }
1935
1936 ArmOp::Lsl { rd, rn, shift } => {
1938 let rd_bits = reg_to_bits(rd) as u16;
1939 let rn_bits = reg_to_bits(rn) as u16;
1940 let shift_bits = (*shift as u16) & 0x1F;
1941
1942 if rd_bits < 8 && rn_bits < 8 {
1943 let instr: u16 = (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1945 Ok(instr.to_le_bytes().to_vec())
1946 } else {
1947 self.encode_thumb32_shift(rd, rn, *shift, 0b00) }
1950 }
1951
1952 ArmOp::Lsr { rd, rn, shift } => {
1953 let rd_bits = reg_to_bits(rd) as u16;
1954 let rn_bits = reg_to_bits(rn) as u16;
1955 let shift_bits = (*shift as u16) & 0x1F;
1956
1957 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1958 let instr: u16 = 0x0800 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1960 Ok(instr.to_le_bytes().to_vec())
1961 } else {
1962 self.encode_thumb32_shift(rd, rn, *shift, 0b01) }
1964 }
1965
1966 ArmOp::Asr { rd, rn, shift } => {
1967 let rd_bits = reg_to_bits(rd) as u16;
1968 let rn_bits = reg_to_bits(rn) as u16;
1969 let shift_bits = (*shift as u16) & 0x1F;
1970
1971 if rd_bits < 8 && rn_bits < 8 && shift_bits > 0 {
1972 let instr: u16 = 0x1000 | (shift_bits << 6) | (rn_bits << 3) | rd_bits;
1974 Ok(instr.to_le_bytes().to_vec())
1975 } else {
1976 self.encode_thumb32_shift(rd, rn, *shift, 0b10) }
1978 }
1979
1980 ArmOp::Ror { rd, rn, shift } => {
1981 self.encode_thumb32_shift(rd, rn, *shift, 0b11) }
1984
1985 ArmOp::LslReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b00),
1989 ArmOp::LsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b01),
1990 ArmOp::AsrReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b10),
1991 ArmOp::RorReg { rd, rn, rm } => self.encode_thumb32_shift_reg(rd, rn, rm, 0b11),
1992
1993 ArmOp::Rsb { rd, rn, imm } => {
1996 let rd_bits = reg_to_bits(rd);
1997 let rn_bits = reg_to_bits(rn);
1998 let imm_val = *imm;
1999
2000 let i_bit = (imm_val >> 11) & 1;
2001 let imm3 = (imm_val >> 8) & 0x7;
2002 let imm8 = imm_val & 0xFF;
2003
2004 let hw1: u16 = (0xF1C0 | (i_bit << 10) | rn_bits) as u16;
2006 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
2008
2009 let mut bytes = hw1.to_le_bytes().to_vec();
2010 bytes.extend_from_slice(&hw2.to_le_bytes());
2011 Ok(bytes)
2012 }
2013
2014 ArmOp::Clz { rd, rm } => {
2016 let rd_bits = reg_to_bits(rd);
2017 let rm_bits = reg_to_bits(rm);
2018
2019 let hw1: u16 = (0xFAB0 | rm_bits) as u16;
2022 let hw2: u16 = (0xF080 | (rd_bits << 8) | rm_bits) as u16;
2023
2024 let mut bytes = hw1.to_le_bytes().to_vec();
2025 bytes.extend_from_slice(&hw2.to_le_bytes());
2026 Ok(bytes)
2027 }
2028
2029 ArmOp::Rbit { rd, rm } => {
2031 let rd_bits = reg_to_bits(rd);
2032 let rm_bits = reg_to_bits(rm);
2033
2034 let hw1: u16 = (0xFA90 | rm_bits) as u16;
2037 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rm_bits) as u16;
2038
2039 let mut bytes = hw1.to_le_bytes().to_vec();
2040 bytes.extend_from_slice(&hw2.to_le_bytes());
2041 Ok(bytes)
2042 }
2043
2044 ArmOp::Sxtb { rd, rm } => {
2046 let rd_bits = reg_to_bits(rd) as u16;
2047 let rm_bits = reg_to_bits(rm) as u16;
2048
2049 if rd_bits < 8 && rm_bits < 8 {
2050 let instr: u16 = 0xB240 | (rm_bits << 3) | rd_bits;
2052 Ok(instr.to_le_bytes().to_vec())
2053 } else {
2054 let rd_bits32 = rd_bits as u32;
2057 let rm_bits32 = rm_bits as u32;
2058 let hw1: u16 = 0xFA4F;
2059 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2060 let mut bytes = hw1.to_le_bytes().to_vec();
2061 bytes.extend_from_slice(&hw2.to_le_bytes());
2062 Ok(bytes)
2063 }
2064 }
2065
2066 ArmOp::Sxth { rd, rm } => {
2068 let rd_bits = reg_to_bits(rd) as u16;
2069 let rm_bits = reg_to_bits(rm) as u16;
2070
2071 if rd_bits < 8 && rm_bits < 8 {
2072 let instr: u16 = 0xB200 | (rm_bits << 3) | rd_bits;
2074 Ok(instr.to_le_bytes().to_vec())
2075 } else {
2076 let rd_bits32 = rd_bits as u32;
2079 let rm_bits32 = rm_bits as u32;
2080 let hw1: u16 = 0xFA0F;
2081 let hw2: u16 = (0xF080 | (rd_bits32 << 8) | rm_bits32) as u16;
2082 let mut bytes = hw1.to_le_bytes().to_vec();
2083 bytes.extend_from_slice(&hw2.to_le_bytes());
2084 Ok(bytes)
2085 }
2086 }
2087
2088 ArmOp::Cmp { rn, op2 } => {
2090 let rn_bits = reg_to_bits(rn) as u16;
2091
2092 if let Operand2::Imm(imm) = op2 {
2093 if *imm >= 0 && *imm <= 255 && rn_bits < 8 {
2096 let instr: u16 = 0x2800 | (rn_bits << 8) | (*imm as u16 & 0xFF);
2098 Ok(instr.to_le_bytes().to_vec())
2099 } else {
2100 self.encode_thumb32_cmp_imm(rn, *imm as u32)
2101 }
2102 } else if let Operand2::Reg(rm) = op2 {
2103 let rm_bits = reg_to_bits(rm) as u16;
2104 if rn_bits < 8 && rm_bits < 8 {
2105 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2107 Ok(instr.to_le_bytes().to_vec())
2108 } else {
2109 let n_bit = (rn_bits >> 3) & 1;
2111 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2112 Ok(instr.to_le_bytes().to_vec())
2113 }
2114 } else {
2115 let instr: u16 = 0xBF00;
2116 Ok(instr.to_le_bytes().to_vec())
2117 }
2118 }
2119
2120 ArmOp::Cmn { rn, op2 } => {
2123 let rn_bits = reg_to_bits(rn) as u16;
2124
2125 if let Operand2::Imm(imm) = op2 {
2126 if *imm >= 0 && *imm <= 255 {
2129 let imm8 = *imm as u16 & 0xFF;
2130 let hw1: u16 = 0xF110 | rn_bits;
2131 let hw2: u16 = 0x0F00 | imm8;
2132 let mut bytes = hw1.to_le_bytes().to_vec();
2133 bytes.extend_from_slice(&hw2.to_le_bytes());
2134 Ok(bytes)
2135 } else {
2136 Ok(vec![0xBF, 0x00])
2138 }
2139 } else if let Operand2::Reg(rm) = op2 {
2140 let rm_bits = reg_to_bits(rm) as u16;
2141 if rn_bits < 8 && rm_bits < 8 {
2147 let instr: u16 = 0x42C0 | (rm_bits << 3) | rn_bits;
2149 Ok(instr.to_le_bytes().to_vec())
2150 } else {
2151 let hw1: u16 = 0xEB10 | rn_bits;
2152 let hw2: u16 = 0x0F00 | rm_bits;
2153 let mut bytes = hw1.to_le_bytes().to_vec();
2154 bytes.extend_from_slice(&hw2.to_le_bytes());
2155 Ok(bytes)
2156 }
2157 } else {
2158 Ok(vec![0xBF, 0x00])
2159 }
2160 }
2161
2162 ArmOp::Ldr { rd, addr } => {
2164 let rd_bits = reg_to_bits(rd);
2165 let base_bits = reg_to_bits(&addr.base);
2166
2167 if let Some(offset_reg) = &addr.offset_reg {
2169 let rm_bits = reg_to_bits(offset_reg);
2170
2171 if addr.offset != 0 {
2173 let scratch = Reg::R12;
2176 let mut bytes =
2177 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2178 bytes.extend(self.encode_thumb32_ldr_reg(rd, &addr.base, &scratch)?);
2179 return Ok(bytes);
2180 }
2181
2182 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2185 let instr: u16 = 0x5800
2187 | ((rm_bits as u16) << 6)
2188 | ((base_bits as u16) << 3)
2189 | (rd_bits as u16);
2190 return Ok(instr.to_le_bytes().to_vec());
2191 }
2192
2193 return self.encode_thumb32_ldr_reg(rd, &addr.base, offset_reg);
2195 }
2196
2197 let offset = addr.offset as u32;
2199
2200 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2201 let imm5 = (offset >> 2) as u16;
2203 let instr: u16 =
2204 0x6800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2205 Ok(instr.to_le_bytes().to_vec())
2206 } else {
2207 self.encode_thumb32_ldr(rd, &addr.base, offset)
2208 }
2209 }
2210
2211 ArmOp::Str { rd, addr } => {
2213 let rd_bits = reg_to_bits(rd);
2214 let base_bits = reg_to_bits(&addr.base);
2215
2216 if let Some(offset_reg) = &addr.offset_reg {
2218 let rm_bits = reg_to_bits(offset_reg);
2219
2220 if addr.offset != 0 {
2222 let scratch = Reg::R12;
2225 let mut bytes =
2226 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2227 bytes.extend(self.encode_thumb32_str_reg(rd, &addr.base, &scratch)?);
2228 return Ok(bytes);
2229 }
2230
2231 if rd_bits < 8 && base_bits < 8 && rm_bits < 8 {
2234 let instr: u16 = 0x5000
2236 | ((rm_bits as u16) << 6)
2237 | ((base_bits as u16) << 3)
2238 | (rd_bits as u16);
2239 return Ok(instr.to_le_bytes().to_vec());
2240 }
2241
2242 return self.encode_thumb32_str_reg(rd, &addr.base, offset_reg);
2244 }
2245
2246 let offset = addr.offset as u32;
2248
2249 if rd_bits < 8 && base_bits < 8 && (offset & 0x3) == 0 && offset <= 124 {
2250 let imm5 = (offset >> 2) as u16;
2252 let instr: u16 =
2253 0x6000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2254 Ok(instr.to_le_bytes().to_vec())
2255 } else {
2256 self.encode_thumb32_str(rd, &addr.base, offset)
2257 }
2258 }
2259
2260 ArmOp::Ldrb { rd, addr } => {
2262 let rd_bits = reg_to_bits(rd);
2263 let base_bits = reg_to_bits(&addr.base);
2264
2265 if let Some(offset_reg) = &addr.offset_reg {
2266 if addr.offset != 0 {
2267 let scratch = Reg::R12;
2268 let mut bytes =
2269 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2270 bytes.extend(self.encode_thumb32_ldrb_reg(rd, &addr.base, &scratch)?);
2271 return Ok(bytes);
2272 }
2273 return self.encode_thumb32_ldrb_reg(rd, &addr.base, offset_reg);
2274 }
2275
2276 let offset = addr.offset as u32;
2277 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2278 let instr: u16 = 0x7800
2280 | ((offset as u16) << 6)
2281 | ((base_bits as u16) << 3)
2282 | (rd_bits as u16);
2283 Ok(instr.to_le_bytes().to_vec())
2284 } else {
2285 self.encode_thumb32_ldrb_imm(rd, &addr.base, offset)
2286 }
2287 }
2288
2289 ArmOp::Ldrsb { rd, addr } => {
2291 let rd_bits = reg_to_bits(rd);
2292 let base_bits = reg_to_bits(&addr.base);
2293
2294 if let Some(offset_reg) = &addr.offset_reg {
2295 if addr.offset != 0 {
2296 let scratch = Reg::R12;
2297 let mut bytes =
2298 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2299 bytes.extend(self.encode_thumb32_ldrsb_reg(rd, &addr.base, &scratch)?);
2300 return Ok(bytes);
2301 }
2302 return self.encode_thumb32_ldrsb_reg(rd, &addr.base, offset_reg);
2303 }
2304
2305 let offset = addr.offset as u32;
2306 if rd_bits < 8 && base_bits < 8 && offset == 0 {
2309 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2311 } else {
2312 self.encode_thumb32_ldrsb_imm(rd, &addr.base, offset)
2313 }
2314 }
2315
2316 ArmOp::Ldrh { rd, addr } => {
2318 let rd_bits = reg_to_bits(rd);
2319 let base_bits = reg_to_bits(&addr.base);
2320
2321 if let Some(offset_reg) = &addr.offset_reg {
2322 if addr.offset != 0 {
2323 let scratch = Reg::R12;
2324 let mut bytes =
2325 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2326 bytes.extend(self.encode_thumb32_ldrh_reg(rd, &addr.base, &scratch)?);
2327 return Ok(bytes);
2328 }
2329 return self.encode_thumb32_ldrh_reg(rd, &addr.base, offset_reg);
2330 }
2331
2332 let offset = addr.offset as u32;
2333 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2334 let imm5 = (offset >> 1) as u16;
2336 let instr: u16 =
2337 0x8800 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2338 Ok(instr.to_le_bytes().to_vec())
2339 } else {
2340 self.encode_thumb32_ldrh_imm(rd, &addr.base, offset)
2341 }
2342 }
2343
2344 ArmOp::Ldrsh { rd, addr } => {
2346 if let Some(offset_reg) = &addr.offset_reg {
2347 if addr.offset != 0 {
2348 let scratch = Reg::R12;
2349 let mut bytes =
2350 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2351 bytes.extend(self.encode_thumb32_ldrsh_reg(rd, &addr.base, &scratch)?);
2352 return Ok(bytes);
2353 }
2354 return self.encode_thumb32_ldrsh_reg(rd, &addr.base, offset_reg);
2355 }
2356
2357 let offset = addr.offset as u32;
2358 self.encode_thumb32_ldrsh_imm(rd, &addr.base, offset)
2359 }
2360
2361 ArmOp::Strb { rd, addr } => {
2363 let rd_bits = reg_to_bits(rd);
2364 let base_bits = reg_to_bits(&addr.base);
2365
2366 if let Some(offset_reg) = &addr.offset_reg {
2367 if addr.offset != 0 {
2368 let scratch = Reg::R12;
2369 let mut bytes =
2370 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2371 bytes.extend(self.encode_thumb32_strb_reg(rd, &addr.base, &scratch)?);
2372 return Ok(bytes);
2373 }
2374 return self.encode_thumb32_strb_reg(rd, &addr.base, offset_reg);
2375 }
2376
2377 let offset = addr.offset as u32;
2378 if rd_bits < 8 && base_bits < 8 && offset <= 31 {
2379 let instr: u16 = 0x7000
2381 | ((offset as u16) << 6)
2382 | ((base_bits as u16) << 3)
2383 | (rd_bits as u16);
2384 Ok(instr.to_le_bytes().to_vec())
2385 } else {
2386 self.encode_thumb32_strb_imm(rd, &addr.base, offset)
2387 }
2388 }
2389
2390 ArmOp::Strh { rd, addr } => {
2392 let rd_bits = reg_to_bits(rd);
2393 let base_bits = reg_to_bits(&addr.base);
2394
2395 if let Some(offset_reg) = &addr.offset_reg {
2396 if addr.offset != 0 {
2397 let scratch = Reg::R12;
2398 let mut bytes =
2399 self.encode_thumb32_add_imm(&scratch, offset_reg, addr.offset as u32)?;
2400 bytes.extend(self.encode_thumb32_strh_reg(rd, &addr.base, &scratch)?);
2401 return Ok(bytes);
2402 }
2403 return self.encode_thumb32_strh_reg(rd, &addr.base, offset_reg);
2404 }
2405
2406 let offset = addr.offset as u32;
2407 if rd_bits < 8 && base_bits < 8 && (offset & 0x1) == 0 && offset <= 62 {
2408 let imm5 = (offset >> 1) as u16;
2410 let instr: u16 =
2411 0x8000 | (imm5 << 6) | ((base_bits as u16) << 3) | (rd_bits as u16);
2412 Ok(instr.to_le_bytes().to_vec())
2413 } else {
2414 self.encode_thumb32_strh_imm(rd, &addr.base, offset)
2415 }
2416 }
2417
2418 ArmOp::MemorySize { rd } => {
2420 let rd_bits = reg_to_bits(rd);
2423 let r10_bits = reg_to_bits(&Reg::R10);
2424 if rd_bits < 8 && r10_bits < 8 {
2425 let instr: u16 =
2426 0x0800 | (16u16 << 6) | ((r10_bits as u16) << 3) | (rd_bits as u16);
2427 Ok(instr.to_le_bytes().to_vec())
2428 } else {
2429 let imm5: u32 = 16;
2431 let imm3 = (imm5 >> 2) & 0x7;
2432 let imm2 = imm5 & 0x3;
2433 let hw1: u16 = 0xEA4F;
2434 let hw2: u16 =
2435 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | 0x10 | r10_bits) as u16;
2436 let mut bytes = hw1.to_le_bytes().to_vec();
2437 bytes.extend_from_slice(&hw2.to_le_bytes());
2438 Ok(bytes)
2439 }
2440 }
2441
2442 ArmOp::MemoryGrow { rd, .. } => {
2444 let rd_bits = reg_to_bits(rd);
2448 let hw1: u16 = 0xF06F; let hw2: u16 = (rd_bits << 8) as u16; let mut bytes = hw1.to_le_bytes().to_vec();
2451 bytes.extend_from_slice(&hw2.to_le_bytes());
2452 Ok(bytes)
2453 }
2454
2455 ArmOp::Bx { rm } => {
2457 let rm_bits = reg_to_bits(rm) as u16;
2458 let instr: u16 = 0x4700 | (rm_bits << 3);
2460 Ok(instr.to_le_bytes().to_vec())
2461 }
2462
2463 ArmOp::Blx { rm } => {
2466 let rm_bits = reg_to_bits(rm) as u16;
2467 let instr: u16 = 0x4780 | (rm_bits << 3);
2468 Ok(instr.to_le_bytes().to_vec())
2469 }
2470
2471 ArmOp::CallIndirect {
2475 rd: _,
2476 type_idx: _,
2477 table_index_reg,
2478 } => {
2479 let idx_reg = reg_to_bits(table_index_reg);
2480 let mut bytes = Vec::new();
2481
2482 let hw1: u16 = 0xEA4F_u16; let hw2: u16 = ((0x0C00 | (0b10 << 4)) | idx_reg) as u16;
2498 bytes.extend_from_slice(&hw1.to_le_bytes());
2499 bytes.extend_from_slice(&hw2.to_le_bytes());
2500
2501 let ldr_hw1: u16 = 0xF85B; let ldr_hw2: u16 = 0xC00C; bytes.extend_from_slice(&ldr_hw1.to_le_bytes());
2507 bytes.extend_from_slice(&ldr_hw2.to_le_bytes());
2508
2509 let blx: u16 = 0x47E0; bytes.extend_from_slice(&blx.to_le_bytes());
2513
2514 Ok(bytes)
2515 }
2516
2517 ArmOp::Label { .. } => Ok(Vec::new()),
2519
2520 ArmOp::Bcc { cond, label: _ } => {
2522 use synth_synthesis::Condition;
2523 let cond_bits: u16 = match cond {
2524 Condition::EQ => 0x0,
2525 Condition::NE => 0x1,
2526 Condition::HS => 0x2,
2527 Condition::LO => 0x3,
2528 Condition::HI => 0x8,
2529 Condition::LS => 0x9,
2530 Condition::GE => 0xA,
2531 Condition::LT => 0xB,
2532 Condition::GT => 0xC,
2533 Condition::LE => 0xD,
2534 };
2535 let instr: u16 = 0xD000 | (cond_bits << 8);
2537 Ok(instr.to_le_bytes().to_vec())
2538 }
2539
2540 ArmOp::B { label: _ } => {
2542 let instr: u16 = 0xE000; Ok(instr.to_le_bytes().to_vec())
2546 }
2547
2548 ArmOp::Bhs { label: _ } => {
2551 let instr: u16 = 0xD200; Ok(instr.to_le_bytes().to_vec())
2555 }
2556
2557 ArmOp::Blo { label: _ } => {
2560 let instr: u16 = 0xD300; Ok(instr.to_le_bytes().to_vec())
2564 }
2565
2566 ArmOp::BOffset { offset } => {
2569 let halfword_offset = *offset;
2572
2573 if (-1024..=1022).contains(&halfword_offset) {
2576 let imm11 = (halfword_offset as u16) & 0x7FF;
2578 let instr: u16 = 0xE000 | imm11;
2579 Ok(instr.to_le_bytes().to_vec())
2580 } else {
2581 let signed_offset = halfword_offset << 1; let s = if signed_offset < 0 { 1u32 } else { 0u32 };
2597 let uoffset = signed_offset as u32;
2598 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;
2606 let hw2: u16 = (0x9000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2607
2608 let mut bytes = hw1.to_le_bytes().to_vec();
2609 bytes.extend_from_slice(&hw2.to_le_bytes());
2610 Ok(bytes)
2611 }
2612 }
2613
2614 ArmOp::BCondOffset { cond, offset } => {
2616 use synth_synthesis::Condition;
2617 let cond_bits: u16 = match cond {
2618 Condition::EQ => 0x0,
2619 Condition::NE => 0x1,
2620 Condition::HS => 0x2,
2621 Condition::LO => 0x3,
2622 Condition::HI => 0x8,
2623 Condition::LS => 0x9,
2624 Condition::GE => 0xA,
2625 Condition::LT => 0xB,
2626 Condition::GT => 0xC,
2627 Condition::LE => 0xD,
2628 };
2629
2630 let halfword_offset = *offset;
2633
2634 if (-128..=127).contains(&halfword_offset) {
2637 let imm8 = (halfword_offset as u16) & 0xFF;
2638 let instr: u16 = 0xD000 | (cond_bits << 8) | imm8;
2639 Ok(instr.to_le_bytes().to_vec())
2640 } else {
2641 let offset = halfword_offset >> 1;
2645 let s = if offset < 0 { 1u32 } else { 0u32 };
2646 let imm6 = ((offset >> 11) as u32) & 0x3F;
2647 let imm11 = (offset as u32) & 0x7FF;
2648 let j1 = if s == 1 { 1 } else { 0 };
2649 let j2 = if s == 1 { 1 } else { 0 };
2650
2651 let hw1: u16 = (0xF000 | (s << 10) | ((cond_bits as u32) << 6) | imm6) as u16;
2652 let hw2: u16 = (0x8000 | (j1 << 13) | (j2 << 11) | imm11) as u16;
2653
2654 let mut bytes = hw1.to_le_bytes().to_vec();
2655 bytes.extend_from_slice(&hw2.to_le_bytes());
2656 Ok(bytes)
2657 }
2658 }
2659
2660 ArmOp::Bl { label: _ } => {
2661 let hw1: u16 = 0xF7FF;
2676 let hw2: u16 = 0xFFFE;
2677 let mut bytes = hw1.to_le_bytes().to_vec();
2678 bytes.extend_from_slice(&hw2.to_le_bytes());
2679 Ok(bytes)
2680 }
2681
2682 ArmOp::Mvn { rd, op2 } => {
2684 if let Operand2::Reg(rm) = op2 {
2685 let rd_bits = reg_to_bits(rd) as u16;
2686 let rm_bits = reg_to_bits(rm) as u16;
2687
2688 if rd_bits < 8 && rm_bits < 8 {
2689 let instr: u16 = 0x43C0 | (rm_bits << 3) | rd_bits;
2691 Ok(instr.to_le_bytes().to_vec())
2692 } else {
2693 let hw1: u16 = 0xEA6F_u16;
2695 let hw2: u16 = ((reg_to_bits(rd) << 8) | reg_to_bits(rm)) as u16;
2696 let mut bytes = hw1.to_le_bytes().to_vec();
2697 bytes.extend_from_slice(&hw2.to_le_bytes());
2698 Ok(bytes)
2699 }
2700 } else {
2701 let instr: u16 = 0xBF00;
2702 Ok(instr.to_le_bytes().to_vec())
2703 }
2704 }
2705
2706 ArmOp::Movw { rd, imm16 } => {
2708 self.encode_thumb32_movw_raw(reg_to_bits(rd), *imm16 as u32)
2709 }
2710
2711 ArmOp::Movt { rd, imm16 } => {
2713 self.encode_thumb32_movt_raw(reg_to_bits(rd), *imm16 as u32)
2714 }
2715
2716 ArmOp::SetCond { rd, cond } => {
2722 let rd_bits = reg_to_bits(rd) as u16;
2723
2724 use synth_synthesis::Condition;
2726 let cond_bits: u16 = match cond {
2727 Condition::EQ => 0x0,
2728 Condition::NE => 0x1,
2729 Condition::LT => 0xB,
2730 Condition::LE => 0xD,
2731 Condition::GT => 0xC,
2732 Condition::GE => 0xA,
2733 Condition::LO => 0x3, Condition::LS => 0x9, Condition::HI => 0x8, Condition::HS => 0x2, };
2738
2739 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2744 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2745
2746 let mut bytes = ite_instr.to_le_bytes().to_vec();
2757 let push_mov = |bytes: &mut Vec<u8>, imm: u16| {
2758 if rd_bits <= 7 {
2759 let m: u16 = 0x2000 | (rd_bits << 8) | imm; bytes.extend_from_slice(&m.to_le_bytes());
2761 } else {
2762 let hw1: u16 = 0xF04F;
2764 let hw2: u16 = (rd_bits << 8) | imm;
2765 bytes.extend_from_slice(&hw1.to_le_bytes());
2766 bytes.extend_from_slice(&hw2.to_le_bytes());
2767 }
2768 };
2769 push_mov(&mut bytes, 1); push_mov(&mut bytes, 0); Ok(bytes)
2772 }
2773
2774 ArmOp::I64SetCond {
2779 rd,
2780 rn_lo,
2781 rn_hi,
2782 rm_lo,
2783 rm_hi,
2784 cond,
2785 } => {
2786 use synth_synthesis::Condition;
2787 let rd_bits = reg_to_bits(rd) as u16;
2788 let mut bytes = Vec::new();
2789
2790 let encode_cmp_reg = |rn: &synth_synthesis::Reg,
2792 rm: &synth_synthesis::Reg|
2793 -> Vec<u8> {
2794 let rn_bits = reg_to_bits(rn) as u16;
2795 let rm_bits = reg_to_bits(rm) as u16;
2796 if rn_bits < 8 && rm_bits < 8 {
2797 let instr: u16 = 0x4280 | (rm_bits << 3) | rn_bits;
2798 instr.to_le_bytes().to_vec()
2799 } else {
2800 let n_bit = (rn_bits >> 3) & 1;
2801 let instr: u16 = 0x4500 | (n_bit << 7) | (rm_bits << 3) | (rn_bits & 0x7);
2802 instr.to_le_bytes().to_vec()
2803 }
2804 };
2805
2806 let encode_ite = |cond_bits: u16| -> Vec<u8> {
2808 let mask = if (cond_bits & 1) == 0 { 0xC } else { 0x4 };
2809 let ite_instr: u16 = 0xBF00 | (cond_bits << 4) | mask;
2810 ite_instr.to_le_bytes().to_vec()
2811 };
2812
2813 let encode_setcond = |cond_bits: u16, rd_bits: u16| -> Vec<u8> {
2815 let mut b = encode_ite(cond_bits);
2816 let mov_one: u16 = 0x2001 | (rd_bits << 8);
2817 let mov_zero: u16 = 0x2000 | (rd_bits << 8);
2818 b.extend_from_slice(&mov_one.to_le_bytes());
2819 b.extend_from_slice(&mov_zero.to_le_bytes());
2820 b
2821 };
2822
2823 match cond {
2824 Condition::EQ | Condition::NE => {
2825 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2827
2828 let it_eq: u16 = 0xBF08; bytes.extend_from_slice(&it_eq.to_le_bytes());
2831
2832 bytes.extend_from_slice(&encode_cmp_reg(rn_hi, rm_hi));
2834
2835 let cond_bits: u16 = match cond {
2837 Condition::EQ => 0x0,
2838 Condition::NE => 0x1,
2839 _ => unreachable!(),
2840 };
2841 bytes.extend_from_slice(&encode_setcond(cond_bits, rd_bits));
2842 }
2843
2844 Condition::LT => {
2845 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2847
2848 let rn_hi_bits = reg_to_bits(rn_hi);
2851 let rm_hi_bits = reg_to_bits(rm_hi);
2852 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2853 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2854 bytes.extend_from_slice(&hw1.to_le_bytes());
2855 bytes.extend_from_slice(&hw2.to_le_bytes());
2856
2857 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2860
2861 Condition::GT => {
2862 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2865
2866 let rm_hi_bits = reg_to_bits(rm_hi);
2868 let rn_hi_bits = reg_to_bits(rn_hi);
2869 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2870 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2871 bytes.extend_from_slice(&hw1.to_le_bytes());
2872 bytes.extend_from_slice(&hw2.to_le_bytes());
2873
2874 bytes.extend_from_slice(&encode_setcond(0xB, rd_bits)); }
2877
2878 Condition::LE => {
2879 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2883
2884 let rm_hi_bits = reg_to_bits(rm_hi);
2886 let rn_hi_bits = reg_to_bits(rn_hi);
2887 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2888 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2889 bytes.extend_from_slice(&hw1.to_le_bytes());
2890 bytes.extend_from_slice(&hw2.to_le_bytes());
2891
2892 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2895
2896 Condition::GE => {
2897 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2900
2901 let rn_hi_bits = reg_to_bits(rn_hi);
2903 let rm_hi_bits = reg_to_bits(rm_hi);
2904 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2905 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2906 bytes.extend_from_slice(&hw1.to_le_bytes());
2907 bytes.extend_from_slice(&hw2.to_le_bytes());
2908
2909 bytes.extend_from_slice(&encode_setcond(0xA, rd_bits)); }
2912
2913 Condition::LO => {
2915 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2917 let rn_hi_bits = reg_to_bits(rn_hi);
2918 let rm_hi_bits = reg_to_bits(rm_hi);
2919 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2920 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2921 bytes.extend_from_slice(&hw1.to_le_bytes());
2922 bytes.extend_from_slice(&hw2.to_le_bytes());
2923 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2925
2926 Condition::HI => {
2927 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2929 let rm_hi_bits = reg_to_bits(rm_hi);
2930 let rn_hi_bits = reg_to_bits(rn_hi);
2931 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2932 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2933 bytes.extend_from_slice(&hw1.to_le_bytes());
2934 bytes.extend_from_slice(&hw2.to_le_bytes());
2935 bytes.extend_from_slice(&encode_setcond(0x3, rd_bits)); }
2937
2938 Condition::LS => {
2939 bytes.extend_from_slice(&encode_cmp_reg(rm_lo, rn_lo));
2941 let rm_hi_bits = reg_to_bits(rm_hi);
2942 let rn_hi_bits = reg_to_bits(rn_hi);
2943 let hw1: u16 = (0xEB70 | rm_hi_bits) as u16;
2944 let hw2: u16 = ((rd_bits as u32) << 8 | rn_hi_bits) as u16;
2945 bytes.extend_from_slice(&hw1.to_le_bytes());
2946 bytes.extend_from_slice(&hw2.to_le_bytes());
2947 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2949
2950 Condition::HS => {
2951 bytes.extend_from_slice(&encode_cmp_reg(rn_lo, rm_lo));
2953 let rn_hi_bits = reg_to_bits(rn_hi);
2954 let rm_hi_bits = reg_to_bits(rm_hi);
2955 let hw1: u16 = (0xEB70 | rn_hi_bits) as u16;
2956 let hw2: u16 = ((rd_bits as u32) << 8 | rm_hi_bits) as u16;
2957 bytes.extend_from_slice(&hw1.to_le_bytes());
2958 bytes.extend_from_slice(&hw2.to_le_bytes());
2959 bytes.extend_from_slice(&encode_setcond(0x2, rd_bits)); }
2961 }
2962
2963 Ok(bytes)
2964 }
2965
2966 ArmOp::I64SetCondZ { rd, rn_lo, rn_hi } => {
2969 let rd_bits = reg_to_bits(rd);
2970 let rn_lo_bits = reg_to_bits(rn_lo);
2971 let rn_hi_bits = reg_to_bits(rn_hi);
2972 let mut bytes = Vec::new();
2973
2974 let hw1: u16 = (0xEA40 | rn_lo_bits) as u16;
2976 let hw2: u16 = ((rd_bits << 8) | rn_hi_bits) as u16;
2977 bytes.extend_from_slice(&hw1.to_le_bytes());
2978 bytes.extend_from_slice(&hw2.to_le_bytes());
2979
2980 let cmp_instr: u16 = 0x2800 | ((rd_bits as u16) << 8);
2982 bytes.extend_from_slice(&cmp_instr.to_le_bytes());
2983
2984 let mask = 0xC_u16; let ite_instr: u16 = 0xBF00 | mask;
2987 bytes.extend_from_slice(&ite_instr.to_le_bytes());
2988 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
2989 let mov_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
2990 bytes.extend_from_slice(&mov_one.to_le_bytes());
2991 bytes.extend_from_slice(&mov_zero.to_le_bytes());
2992
2993 Ok(bytes)
2994 }
2995
2996 ArmOp::I64Mul {
3000 rd_lo,
3001 rd_hi,
3002 rn_lo,
3003 rn_hi,
3004 rm_lo,
3005 rm_hi,
3006 } => {
3007 let rd_lo_bits = reg_to_bits(rd_lo);
3008 let rd_hi_bits = reg_to_bits(rd_hi);
3009 let rn_lo_bits = reg_to_bits(rn_lo);
3010 let rn_hi_bits = reg_to_bits(rn_hi);
3011 let rm_lo_bits = reg_to_bits(rm_lo);
3012 let rm_hi_bits = reg_to_bits(rm_hi);
3013 let r12: u32 = 12; let mut bytes = Vec::new();
3015
3016 let hw1: u16 = (0xFB00 | rn_lo_bits) as u16;
3019 let hw2: u16 = (0xF000 | (r12 << 8) | rm_hi_bits) as u16;
3020 bytes.extend_from_slice(&hw1.to_le_bytes());
3021 bytes.extend_from_slice(&hw2.to_le_bytes());
3022
3023 let hw1: u16 = (0xFB00 | rn_hi_bits) as u16;
3026 let hw2: u16 = ((r12 << 12) | (r12 << 8) | rm_lo_bits) as u16;
3027 bytes.extend_from_slice(&hw1.to_le_bytes());
3028 bytes.extend_from_slice(&hw2.to_le_bytes());
3029
3030 let hw1: u16 = (0xFBA0 | rn_lo_bits) as u16;
3033 let hw2: u16 = ((rd_lo_bits << 12) | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3034 bytes.extend_from_slice(&hw1.to_le_bytes());
3035 bytes.extend_from_slice(&hw2.to_le_bytes());
3036
3037 let d_bit = (rd_hi_bits >> 3) & 1;
3040 let add_instr: u16 =
3041 (0x4400 | (d_bit << 7) | (r12 << 3) | (rd_hi_bits & 0x7)) as u16;
3042 bytes.extend_from_slice(&add_instr.to_le_bytes());
3043
3044 Ok(bytes)
3045 }
3046
3047 ArmOp::I64Shl {
3050 rd_lo,
3051 rd_hi,
3052 rn_lo,
3053 rn_hi,
3054 rm_lo,
3055 rm_hi,
3056 } => {
3057 let rd_lo_bits = reg_to_bits(rd_lo);
3058 let rd_hi_bits = reg_to_bits(rd_hi);
3059 let rn_lo_bits = reg_to_bits(rn_lo);
3060 let rn_hi_bits = reg_to_bits(rn_hi);
3061 let rm_lo_bits = reg_to_bits(rm_lo);
3062 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3064
3065 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3067 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3068 bytes.extend_from_slice(&hw1.to_le_bytes());
3069 bytes.extend_from_slice(&hw2.to_le_bytes());
3070
3071 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3073 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3074 bytes.extend_from_slice(&hw1.to_le_bytes());
3075 bytes.extend_from_slice(&hw2.to_le_bytes());
3076
3077 let bpl: u16 = 0xD50A;
3079 bytes.extend_from_slice(&bpl.to_le_bytes());
3080
3081 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3084 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3085 bytes.extend_from_slice(&hw1.to_le_bytes());
3086 bytes.extend_from_slice(&hw2.to_le_bytes());
3087
3088 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3090 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3091 bytes.extend_from_slice(&hw1.to_le_bytes());
3092 bytes.extend_from_slice(&hw2.to_le_bytes());
3093
3094 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3096 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3097 bytes.extend_from_slice(&hw1.to_le_bytes());
3098 bytes.extend_from_slice(&hw2.to_le_bytes());
3099
3100 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3102 let hw2: u16 = ((rd_hi_bits << 8) | rm_hi_bits) as u16;
3103 bytes.extend_from_slice(&hw1.to_le_bytes());
3104 bytes.extend_from_slice(&hw2.to_le_bytes());
3105
3106 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3108 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3109 bytes.extend_from_slice(&hw1.to_le_bytes());
3110 bytes.extend_from_slice(&hw2.to_le_bytes());
3111
3112 let b_done: u16 = 0xE002;
3114 bytes.extend_from_slice(&b_done.to_le_bytes());
3115
3116 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3119 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_hi_bits) as u16;
3120 bytes.extend_from_slice(&hw1.to_le_bytes());
3121 bytes.extend_from_slice(&hw2.to_le_bytes());
3122
3123 let mov_zero: u16 = 0x2000 | ((rd_lo_bits as u16) << 8);
3125 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3126
3127 Ok(bytes) }
3129
3130 ArmOp::I64ShrU {
3132 rd_lo,
3133 rd_hi,
3134 rn_lo,
3135 rn_hi,
3136 rm_lo,
3137 rm_hi,
3138 } => {
3139 let rd_lo_bits = reg_to_bits(rd_lo);
3140 let rd_hi_bits = reg_to_bits(rd_hi);
3141 let rn_lo_bits = reg_to_bits(rn_lo);
3142 let rn_hi_bits = reg_to_bits(rn_hi);
3143 let rm_lo_bits = reg_to_bits(rm_lo);
3144 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3146
3147 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3149 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) as u16;
3150 bytes.extend_from_slice(&hw1.to_le_bytes());
3151 bytes.extend_from_slice(&hw2.to_le_bytes());
3152
3153 let hw1: u16 = (0xF1B0 | rm_lo_bits) as u16;
3155 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3156 bytes.extend_from_slice(&hw1.to_le_bytes());
3157 bytes.extend_from_slice(&hw2.to_le_bytes());
3158
3159 let bpl: u16 = 0xD50A;
3161 bytes.extend_from_slice(&bpl.to_le_bytes());
3162
3163 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3166 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3167 bytes.extend_from_slice(&hw1.to_le_bytes());
3168 bytes.extend_from_slice(&hw2.to_le_bytes());
3169
3170 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3172 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3173 bytes.extend_from_slice(&hw1.to_le_bytes());
3174 bytes.extend_from_slice(&hw2.to_le_bytes());
3175
3176 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3178 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3179 bytes.extend_from_slice(&hw1.to_le_bytes());
3180 bytes.extend_from_slice(&hw2.to_le_bytes());
3181
3182 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3184 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3185 bytes.extend_from_slice(&hw1.to_le_bytes());
3186 bytes.extend_from_slice(&hw2.to_le_bytes());
3187
3188 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3190 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3191 bytes.extend_from_slice(&hw1.to_le_bytes());
3192 bytes.extend_from_slice(&hw2.to_le_bytes());
3193
3194 let b_done: u16 = 0xE002;
3196 bytes.extend_from_slice(&b_done.to_le_bytes());
3197
3198 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3201 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3202 bytes.extend_from_slice(&hw1.to_le_bytes());
3203 bytes.extend_from_slice(&hw2.to_le_bytes());
3204
3205 let mov_zero: u16 = 0x2000 | ((rd_hi_bits as u16) << 8);
3207 bytes.extend_from_slice(&mov_zero.to_le_bytes());
3208
3209 Ok(bytes) }
3211
3212 ArmOp::I64ShrS {
3214 rd_lo,
3215 rd_hi,
3216 rn_lo,
3217 rn_hi,
3218 rm_lo,
3219 rm_hi,
3220 } => {
3221 let rd_lo_bits = reg_to_bits(rd_lo);
3222 let rd_hi_bits = reg_to_bits(rd_hi);
3223 let rn_lo_bits = reg_to_bits(rn_lo);
3224 let rn_hi_bits = reg_to_bits(rn_hi);
3225 let rm_lo_bits = reg_to_bits(rm_lo);
3226 let rm_hi_bits = reg_to_bits(rm_hi); let mut bytes = Vec::new();
3228
3229 let hw1: u16 = (0xF000 | rm_lo_bits) as u16;
3231 let hw2: u16 = ((rm_lo_bits << 8) | 0x3F) 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 = (0xF1B0 | rm_lo_bits) as u16;
3237 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3238 bytes.extend_from_slice(&hw1.to_le_bytes());
3239 bytes.extend_from_slice(&hw2.to_le_bytes());
3240
3241 let bpl: u16 = 0xD50A;
3243 bytes.extend_from_slice(&bpl.to_le_bytes());
3244
3245 let hw1: u16 = (0xF1C0 | rm_lo_bits) as u16;
3248 let hw2: u16 = ((rm_hi_bits << 8) | 0x20) as u16;
3249 bytes.extend_from_slice(&hw1.to_le_bytes());
3250 bytes.extend_from_slice(&hw2.to_le_bytes());
3251
3252 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3254 let hw2: u16 = (0xF000 | (rm_hi_bits << 8) | rm_hi_bits) as u16;
3255 bytes.extend_from_slice(&hw1.to_le_bytes());
3256 bytes.extend_from_slice(&hw2.to_le_bytes());
3257
3258 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3260 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_lo_bits) as u16;
3261 bytes.extend_from_slice(&hw1.to_le_bytes());
3262 bytes.extend_from_slice(&hw2.to_le_bytes());
3263
3264 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3266 let hw2: u16 = ((rd_lo_bits << 8) | rm_hi_bits) as u16;
3267 bytes.extend_from_slice(&hw1.to_le_bytes());
3268 bytes.extend_from_slice(&hw2.to_le_bytes());
3269
3270 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3272 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | rm_lo_bits) as u16;
3273 bytes.extend_from_slice(&hw1.to_le_bytes());
3274 bytes.extend_from_slice(&hw2.to_le_bytes());
3275
3276 let b_done: u16 = 0xE003;
3278 bytes.extend_from_slice(&b_done.to_le_bytes());
3279
3280 let hw1: u16 = (0xFA40 | rn_hi_bits) as u16;
3283 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | rm_hi_bits) as u16;
3284 bytes.extend_from_slice(&hw1.to_le_bytes());
3285 bytes.extend_from_slice(&hw2.to_le_bytes());
3286
3287 let hw1: u16 = 0xEA4F;
3291 let hw2: u16 = (0x7000 | (rd_hi_bits << 8) | 0x00E0 | rn_hi_bits) as u16;
3292 bytes.extend_from_slice(&hw1.to_le_bytes());
3293 bytes.extend_from_slice(&hw2.to_le_bytes());
3294
3295 Ok(bytes) }
3297
3298 ArmOp::I64Rotl {
3303 rdlo,
3304 rdhi,
3305 rnlo,
3306 rnhi,
3307 shift,
3308 } => {
3309 let rd_lo_bits = reg_to_bits(rdlo);
3310 let rd_hi_bits = reg_to_bits(rdhi);
3311 let rn_lo_bits = reg_to_bits(rnlo);
3312 let rn_hi_bits = reg_to_bits(rnhi);
3313 let shift_bits = reg_to_bits(shift);
3314 let r12: u32 = 12; let r3: u32 = 3; let r4: u32 = 4; let mut bytes = Vec::new();
3318
3319 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3321
3322 let hw1: u16 = (0xF000 | shift_bits) as u16;
3324 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3325 bytes.extend_from_slice(&hw1.to_le_bytes());
3326 bytes.extend_from_slice(&hw2.to_le_bytes());
3327
3328 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3330 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3331 bytes.extend_from_slice(&hw1.to_le_bytes());
3332 bytes.extend_from_slice(&hw2.to_le_bytes());
3333
3334 let bpl: u16 = 0xD50E;
3336 bytes.extend_from_slice(&bpl.to_le_bytes());
3337
3338 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3341 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3342 bytes.extend_from_slice(&hw1.to_le_bytes());
3343 bytes.extend_from_slice(&hw2.to_le_bytes());
3344
3345 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3347 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3348 bytes.extend_from_slice(&hw1.to_le_bytes());
3349 bytes.extend_from_slice(&hw2.to_le_bytes());
3350
3351 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3353 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3354 bytes.extend_from_slice(&hw1.to_le_bytes());
3355 bytes.extend_from_slice(&hw2.to_le_bytes());
3356
3357 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3359 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3360 bytes.extend_from_slice(&hw1.to_le_bytes());
3361 bytes.extend_from_slice(&hw2.to_le_bytes());
3362
3363 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3365 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3366 bytes.extend_from_slice(&hw1.to_le_bytes());
3367 bytes.extend_from_slice(&hw2.to_le_bytes());
3368
3369 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3371 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3372 bytes.extend_from_slice(&hw1.to_le_bytes());
3373 bytes.extend_from_slice(&hw2.to_le_bytes());
3374
3375 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3377 let hw2: u16 = ((rd_lo_bits << 8) | r12) as u16;
3378 bytes.extend_from_slice(&hw1.to_le_bytes());
3379 bytes.extend_from_slice(&hw2.to_le_bytes());
3380
3381 let b_done: u16 = 0xE00E;
3383 bytes.extend_from_slice(&b_done.to_le_bytes());
3384
3385 let hw1: u16 = (0xF1C0 | r3) as u16;
3389 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3390 bytes.extend_from_slice(&hw1.to_le_bytes());
3391 bytes.extend_from_slice(&hw2.to_le_bytes());
3392
3393 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3395 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3396 bytes.extend_from_slice(&hw1.to_le_bytes());
3397 bytes.extend_from_slice(&hw2.to_le_bytes());
3398
3399 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3401 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3402 bytes.extend_from_slice(&hw1.to_le_bytes());
3403 bytes.extend_from_slice(&hw2.to_le_bytes());
3404
3405 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3407 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3408 bytes.extend_from_slice(&hw1.to_le_bytes());
3409 bytes.extend_from_slice(&hw2.to_le_bytes());
3410
3411 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3413 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3414 bytes.extend_from_slice(&hw1.to_le_bytes());
3415 bytes.extend_from_slice(&hw2.to_le_bytes());
3416
3417 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3419 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | r3) as u16;
3420 bytes.extend_from_slice(&hw1.to_le_bytes());
3421 bytes.extend_from_slice(&hw2.to_le_bytes());
3422
3423 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3425 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3426 bytes.extend_from_slice(&hw1.to_le_bytes());
3427 bytes.extend_from_slice(&hw2.to_le_bytes());
3428
3429 let d_bit = (rd_hi_bits >> 3) & 1;
3431 let mov_instr: u16 =
3432 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_hi_bits & 0x7)) as u16;
3433 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3434
3435 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3437
3438 Ok(bytes) }
3440
3441 ArmOp::I64Rotr {
3446 rdlo,
3447 rdhi,
3448 rnlo,
3449 rnhi,
3450 shift,
3451 } => {
3452 let rd_lo_bits = reg_to_bits(rdlo);
3453 let rd_hi_bits = reg_to_bits(rdhi);
3454 let rn_lo_bits = reg_to_bits(rnlo);
3455 let rn_hi_bits = reg_to_bits(rnhi);
3456 let shift_bits = reg_to_bits(shift);
3457 let r12: u32 = 12;
3458 let r3: u32 = 3;
3459 let r4: u32 = 4;
3460 let mut bytes = Vec::new();
3461
3462 bytes.extend_from_slice(&0xB410u16.to_le_bytes());
3464
3465 let hw1: u16 = (0xF000 | shift_bits) as u16;
3467 let hw2: u16 = ((shift_bits << 8) | 0x3F) as u16;
3468 bytes.extend_from_slice(&hw1.to_le_bytes());
3469 bytes.extend_from_slice(&hw2.to_le_bytes());
3470
3471 let hw1: u16 = (0xF1B0 | shift_bits) as u16;
3473 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3474 bytes.extend_from_slice(&hw1.to_le_bytes());
3475 bytes.extend_from_slice(&hw2.to_le_bytes());
3476
3477 let bpl: u16 = 0xD50E;
3479 bytes.extend_from_slice(&bpl.to_le_bytes());
3480
3481 let hw1: u16 = (0xF1C0 | shift_bits) as u16;
3484 let hw2: u16 = ((r3 << 8) | 0x20) as u16;
3485 bytes.extend_from_slice(&hw1.to_le_bytes());
3486 bytes.extend_from_slice(&hw2.to_le_bytes());
3487
3488 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3490 let hw2: u16 = (0xF000 | (r4 << 8) | r3) as u16;
3491 bytes.extend_from_slice(&hw1.to_le_bytes());
3492 bytes.extend_from_slice(&hw2.to_le_bytes());
3493
3494 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3496 let hw2: u16 = (0xF000 | (r12 << 8) | r3) as u16;
3497 bytes.extend_from_slice(&hw1.to_le_bytes());
3498 bytes.extend_from_slice(&hw2.to_le_bytes());
3499
3500 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3502 let hw2: u16 = (0xF000 | (rd_lo_bits << 8) | shift_bits) as u16;
3503 bytes.extend_from_slice(&hw1.to_le_bytes());
3504 bytes.extend_from_slice(&hw2.to_le_bytes());
3505
3506 let hw1: u16 = (0xEA40 | rd_lo_bits) as u16;
3508 let hw2: u16 = ((rd_lo_bits << 8) | r4) as u16;
3509 bytes.extend_from_slice(&hw1.to_le_bytes());
3510 bytes.extend_from_slice(&hw2.to_le_bytes());
3511
3512 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3514 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | shift_bits) as u16;
3515 bytes.extend_from_slice(&hw1.to_le_bytes());
3516 bytes.extend_from_slice(&hw2.to_le_bytes());
3517
3518 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3520 let hw2: u16 = ((rd_hi_bits << 8) | r12) as u16;
3521 bytes.extend_from_slice(&hw1.to_le_bytes());
3522 bytes.extend_from_slice(&hw2.to_le_bytes());
3523
3524 let b_done: u16 = 0xE00E;
3526 bytes.extend_from_slice(&b_done.to_le_bytes());
3527
3528 let hw1: u16 = (0xF1C0 | r3) as u16;
3531 let hw2: u16 = ((r4 << 8) | 0x20) as u16;
3532 bytes.extend_from_slice(&hw1.to_le_bytes());
3533 bytes.extend_from_slice(&hw2.to_le_bytes());
3534
3535 let hw1: u16 = (0xFA00 | rn_lo_bits) as u16;
3537 let hw2: u16 = (0xF000 | (r12 << 8) | r4) as u16;
3538 bytes.extend_from_slice(&hw1.to_le_bytes());
3539 bytes.extend_from_slice(&hw2.to_le_bytes());
3540
3541 let hw1: u16 = (0xFA00 | rn_hi_bits) as u16;
3543 let hw2: u16 = (0xF000 | (r4 << 8) | r4) as u16;
3544 bytes.extend_from_slice(&hw1.to_le_bytes());
3545 bytes.extend_from_slice(&hw2.to_le_bytes());
3546
3547 let hw1: u16 = (0xFA20 | rn_hi_bits) as u16;
3549 let hw2: u16 = (0xF000 | (shift_bits << 8) | r3) as u16;
3550 bytes.extend_from_slice(&hw1.to_le_bytes());
3551 bytes.extend_from_slice(&hw2.to_le_bytes());
3552
3553 let hw1: u16 = (0xEA40 | shift_bits) as u16;
3555 let hw2: u16 = ((shift_bits << 8) | r12) as u16;
3556 bytes.extend_from_slice(&hw1.to_le_bytes());
3557 bytes.extend_from_slice(&hw2.to_le_bytes());
3558
3559 let hw1: u16 = (0xFA20 | rn_lo_bits) as u16;
3561 let hw2: u16 = (0xF000 | (rd_hi_bits << 8) | r3) as u16;
3562 bytes.extend_from_slice(&hw1.to_le_bytes());
3563 bytes.extend_from_slice(&hw2.to_le_bytes());
3564
3565 let hw1: u16 = (0xEA40 | rd_hi_bits) as u16;
3567 let hw2: u16 = ((rd_hi_bits << 8) | r4) as u16;
3568 bytes.extend_from_slice(&hw1.to_le_bytes());
3569 bytes.extend_from_slice(&hw2.to_le_bytes());
3570
3571 let d_bit = (rd_lo_bits >> 3) & 1;
3573 let mov_instr: u16 =
3574 (0x4600 | (d_bit << 7) | (shift_bits << 3) | (rd_lo_bits & 0x7)) as u16;
3575 bytes.extend_from_slice(&mov_instr.to_le_bytes());
3576
3577 bytes.extend_from_slice(&0xBC10u16.to_le_bytes());
3579
3580 Ok(bytes) }
3582
3583 ArmOp::I64Clz { rd, rnlo, rnhi } => {
3597 let rd_bits = reg_to_bits(rd);
3598 let rn_lo_bits = reg_to_bits(rnlo);
3599 let rn_hi_bits = reg_to_bits(rnhi);
3600 let mut bytes = Vec::new();
3601
3602 let hw1: u16 = (0xF1B0 | rn_hi_bits) as u16;
3604 let hw2: u16 = 0x0F00;
3605 bytes.extend_from_slice(&hw1.to_le_bytes());
3606 bytes.extend_from_slice(&hw2.to_le_bytes());
3607
3608 let beq: u16 = 0xD003;
3611 bytes.extend_from_slice(&beq.to_le_bytes());
3612
3613 let hw1: u16 = (0xFAB0 | rn_hi_bits) as u16;
3616 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_hi_bits) as u16;
3617 bytes.extend_from_slice(&hw1.to_le_bytes());
3618 bytes.extend_from_slice(&hw2.to_le_bytes());
3619
3620 let b_done: u16 = 0xE004;
3623 bytes.extend_from_slice(&b_done.to_le_bytes());
3624
3625 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3627
3628 let hw1: u16 = (0xFAB0 | rn_lo_bits) as u16;
3632 let hw2: u16 = (0xF080 | (rd_bits << 8) | rn_lo_bits) as u16;
3633 bytes.extend_from_slice(&hw1.to_le_bytes());
3634 bytes.extend_from_slice(&hw2.to_le_bytes());
3635
3636 let hw1: u16 = (0xF100 | rd_bits) as u16;
3638 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3639 bytes.extend_from_slice(&hw1.to_le_bytes());
3640 bytes.extend_from_slice(&hw2.to_le_bytes());
3641
3642 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3646 bytes.extend_from_slice(&mov0.to_le_bytes());
3647
3648 Ok(bytes)
3649 }
3650
3651 ArmOp::I64Ctz { rd, rnlo, rnhi } => {
3667 let rd_bits = reg_to_bits(rd);
3668 let rn_lo_bits = reg_to_bits(rnlo);
3669 let rn_hi_bits = reg_to_bits(rnhi);
3670 let mut bytes = Vec::new();
3671
3672 let hw1: u16 = (0xF1B0 | rn_lo_bits) as u16;
3674 let hw2: u16 = 0x0F00;
3675 bytes.extend_from_slice(&hw1.to_le_bytes());
3676 bytes.extend_from_slice(&hw2.to_le_bytes());
3677
3678 let beq: u16 = 0xD005;
3681 bytes.extend_from_slice(&beq.to_le_bytes());
3682
3683 let hw1: u16 = (0xFA90 | rn_lo_bits) as u16;
3686 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_lo_bits) as u16;
3687 bytes.extend_from_slice(&hw1.to_le_bytes());
3688 bytes.extend_from_slice(&hw2.to_le_bytes());
3689
3690 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3693 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3694 bytes.extend_from_slice(&hw1.to_le_bytes());
3695 bytes.extend_from_slice(&hw2.to_le_bytes());
3696
3697 let b_done: u16 = 0xE006;
3700 bytes.extend_from_slice(&b_done.to_le_bytes());
3701
3702 bytes.extend_from_slice(&0xBF00u16.to_le_bytes());
3704
3705 let hw1: u16 = (0xFA90 | rn_hi_bits) as u16;
3709 let hw2: u16 = (0xF0A0 | (rd_bits << 8) | rn_hi_bits) as u16;
3710 bytes.extend_from_slice(&hw1.to_le_bytes());
3711 bytes.extend_from_slice(&hw2.to_le_bytes());
3712
3713 let hw1: u16 = (0xFAB0 | rd_bits) as u16;
3716 let hw2: u16 = (0xF080 | (rd_bits << 8) | rd_bits) as u16;
3717 bytes.extend_from_slice(&hw1.to_le_bytes());
3718 bytes.extend_from_slice(&hw2.to_le_bytes());
3719
3720 let hw1: u16 = (0xF100 | rd_bits) as u16;
3722 let hw2: u16 = ((rd_bits << 8) | 0x20) as u16;
3723 bytes.extend_from_slice(&hw1.to_le_bytes());
3724 bytes.extend_from_slice(&hw2.to_le_bytes());
3725
3726 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3729 bytes.extend_from_slice(&mov0.to_le_bytes());
3730
3731 Ok(bytes)
3732 }
3733
3734 ArmOp::I64Popcnt { rd, rnlo, rnhi } => {
3738 let rd_bits = reg_to_bits(rd);
3739 let rn_lo_bits = reg_to_bits(rnlo);
3740 let rn_hi_bits = reg_to_bits(rnhi);
3741 let r12: u32 = 12; let r3: u32 = 3; let mut bytes = Vec::new();
3744
3745 bytes.extend_from_slice(&0xB438u16.to_le_bytes());
3747
3748 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_lo_bits << 3) | (4 & 0x7)) as u16;
3758 bytes.extend_from_slice(&mov.to_le_bytes());
3759
3760 let d_bit: u32 = 0; let mov: u16 = (0x4600 | (d_bit << 7) | (rn_hi_bits << 3) | (5 & 0x7)) as u16;
3763 bytes.extend_from_slice(&mov.to_le_bytes());
3764
3765 let hw1: u16 = 0xEA4F;
3769 let hw2: u16 = ((r12 << 8) | 0x50 | 4) as u16;
3770 bytes.extend_from_slice(&hw1.to_le_bytes());
3771 bytes.extend_from_slice(&hw2.to_le_bytes());
3772
3773 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3776 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3777 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3779 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3780
3781 let hw1: u16 = (0xEA00 | r12) as u16;
3783 let hw2: u16 = ((r12 << 8) | r3) as u16;
3784 bytes.extend_from_slice(&hw1.to_le_bytes());
3785 bytes.extend_from_slice(&hw2.to_le_bytes());
3786
3787 let hw1: u16 = (0xEBA0 | 4) as u16;
3789 let hw2: u16 = ((4 << 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());
3797 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3798 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3800 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3801
3802 let hw1: u16 = (0xEA00 | 4) as u16;
3804 let hw2: u16 = ((r12 << 8) | r3) as u16;
3805 bytes.extend_from_slice(&hw1.to_le_bytes());
3806 bytes.extend_from_slice(&hw2.to_le_bytes());
3807
3808 let hw1: u16 = 0xEA4F;
3810 let hw2: u16 = ((4 << 8) | 0x90 | 4) 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 = (0xEA00 | 4) as u16;
3816 let hw2: u16 = ((4 << 8) | r3) as u16;
3817 bytes.extend_from_slice(&hw1.to_le_bytes());
3818 bytes.extend_from_slice(&hw2.to_le_bytes());
3819
3820 let hw1: u16 = (0xEB00 | 4) as u16;
3822 let hw2: u16 = ((4 << 8) | r12) 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 = 0xEA4F;
3831 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 4) as u16;
3832 bytes.extend_from_slice(&hw1.to_le_bytes());
3833 bytes.extend_from_slice(&hw2.to_le_bytes());
3834
3835 let hw1: u16 = (0xEB00 | 4) as u16;
3837 let hw2: u16 = ((4 << 8) | r12) as u16;
3838 bytes.extend_from_slice(&hw1.to_le_bytes());
3839 bytes.extend_from_slice(&hw2.to_le_bytes());
3840
3841 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3846 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3847 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3849 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3850
3851 let hw1: u16 = (0xEA00 | 4) as u16;
3853 let hw2: u16 = ((4 << 8) | r3) as u16;
3854 bytes.extend_from_slice(&hw1.to_le_bytes());
3855 bytes.extend_from_slice(&hw2.to_le_bytes());
3856
3857 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3861 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3862 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3864 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3865
3866 let hw1: u16 = (0xFB00 | 4) as u16;
3869 let hw2: u16 = (0xF000 | (4 << 8) | r3) as u16;
3870 bytes.extend_from_slice(&hw1.to_le_bytes());
3871 bytes.extend_from_slice(&hw2.to_le_bytes());
3872
3873 let hw1: u16 = 0xEA4F;
3876 let hw2: u16 = (0x6000 | (4 << 8) | 0x10 | 4) as u16;
3877 bytes.extend_from_slice(&hw1.to_le_bytes());
3878 bytes.extend_from_slice(&hw2.to_le_bytes());
3879
3880 let hw1: u16 = 0xEA4F;
3883 let hw2: u16 = ((r12 << 8) | 0x50 | 5) as u16;
3884 bytes.extend_from_slice(&hw1.to_le_bytes());
3885 bytes.extend_from_slice(&hw2.to_le_bytes());
3886
3887 bytes.extend_from_slice(&0xF245u16.to_le_bytes());
3889 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3890 bytes.extend_from_slice(&0xF2C5u16.to_le_bytes());
3891 bytes.extend_from_slice(&0x5355u16.to_le_bytes());
3892
3893 let hw1: u16 = (0xEA00 | r12) as u16;
3894 let hw2: u16 = ((r12 << 8) | r3) as u16;
3895 bytes.extend_from_slice(&hw1.to_le_bytes());
3896 bytes.extend_from_slice(&hw2.to_le_bytes());
3897
3898 let hw1: u16 = (0xEBA0 | 5) as u16;
3899 let hw2: u16 = ((5 << 8) | r12) as u16;
3900 bytes.extend_from_slice(&hw1.to_le_bytes());
3901 bytes.extend_from_slice(&hw2.to_le_bytes());
3902
3903 bytes.extend_from_slice(&0xF243u16.to_le_bytes());
3905 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3906 bytes.extend_from_slice(&0xF2C3u16.to_le_bytes());
3907 bytes.extend_from_slice(&0x3333u16.to_le_bytes());
3908
3909 let hw1: u16 = (0xEA00 | 5) as u16;
3910 let hw2: u16 = ((r12 << 8) | r3) as u16;
3911 bytes.extend_from_slice(&hw1.to_le_bytes());
3912 bytes.extend_from_slice(&hw2.to_le_bytes());
3913
3914 let hw1: u16 = 0xEA4F;
3915 let hw2: u16 = ((5 << 8) | 0x90 | 5) as u16;
3916 bytes.extend_from_slice(&hw1.to_le_bytes());
3917 bytes.extend_from_slice(&hw2.to_le_bytes());
3918
3919 let hw1: u16 = (0xEA00 | 5) as u16;
3920 let hw2: u16 = ((5 << 8) | r3) as u16;
3921 bytes.extend_from_slice(&hw1.to_le_bytes());
3922 bytes.extend_from_slice(&hw2.to_le_bytes());
3923
3924 let hw1: u16 = (0xEB00 | 5) as u16;
3925 let hw2: u16 = ((5 << 8) | r12) as u16;
3926 bytes.extend_from_slice(&hw1.to_le_bytes());
3927 bytes.extend_from_slice(&hw2.to_le_bytes());
3928
3929 let hw1: u16 = 0xEA4F;
3932 let hw2: u16 = (0x1000 | (r12 << 8) | 0x10 | 5) as u16;
3933 bytes.extend_from_slice(&hw1.to_le_bytes());
3934 bytes.extend_from_slice(&hw2.to_le_bytes());
3935
3936 let hw1: u16 = (0xEB00 | 5) as u16;
3937 let hw2: u16 = ((5 << 8) | r12) as u16;
3938 bytes.extend_from_slice(&hw1.to_le_bytes());
3939 bytes.extend_from_slice(&hw2.to_le_bytes());
3940
3941 bytes.extend_from_slice(&0xF640u16.to_le_bytes());
3943 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3944 bytes.extend_from_slice(&0xF6C0u16.to_le_bytes());
3945 bytes.extend_from_slice(&0x730Fu16.to_le_bytes());
3946
3947 let hw1: u16 = (0xEA00 | 5) as u16;
3948 let hw2: u16 = ((5 << 8) | r3) as u16;
3949 bytes.extend_from_slice(&hw1.to_le_bytes());
3950 bytes.extend_from_slice(&hw2.to_le_bytes());
3951
3952 bytes.extend_from_slice(&0xF240u16.to_le_bytes());
3954 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3955 bytes.extend_from_slice(&0xF2C0u16.to_le_bytes());
3956 bytes.extend_from_slice(&0x1301u16.to_le_bytes());
3957
3958 let hw1: u16 = (0xFB00 | 5) as u16;
3961 let hw2: u16 = (0xF000 | (5 << 8) | r3) as u16;
3962 bytes.extend_from_slice(&hw1.to_le_bytes());
3963 bytes.extend_from_slice(&hw2.to_le_bytes());
3964
3965 let hw1: u16 = 0xEA4F;
3968 let hw2: u16 = (0x6000 | (5 << 8) | 0x10 | 5) as u16;
3969 bytes.extend_from_slice(&hw1.to_le_bytes());
3970 bytes.extend_from_slice(&hw2.to_le_bytes());
3971
3972 let rd_bits_u16 = rd_bits as u16;
3975 let instr: u16 = 0x1800 | (5 << 6) | (4 << 3) | rd_bits_u16;
3976 bytes.extend_from_slice(&instr.to_le_bytes());
3977
3978 bytes.extend_from_slice(&0xBC38u16.to_le_bytes());
3980
3981 let mov0: u16 = (0x2000 | (rn_hi_bits << 8)) as u16;
3983 bytes.extend_from_slice(&mov0.to_le_bytes());
3984
3985 Ok(bytes)
3986 }
3987
3988 ArmOp::I64Extend8S { rdlo, rdhi, rnlo } => {
3991 let rdlo_bits = reg_to_bits(rdlo);
3992 let rdhi_bits = reg_to_bits(rdhi);
3993 let rnlo_bits = reg_to_bits(rnlo);
3994 let mut bytes = Vec::new();
3995
3996 let hw1: u16 = 0xFA4F_u16;
3999 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4000 bytes.extend_from_slice(&hw1.to_le_bytes());
4001 bytes.extend_from_slice(&hw2.to_le_bytes());
4002
4003 let hw1: u16 = 0xEA4F;
4008 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4009 bytes.extend_from_slice(&hw1.to_le_bytes());
4010 bytes.extend_from_slice(&hw2.to_le_bytes());
4011
4012 Ok(bytes)
4013 }
4014
4015 ArmOp::I64Extend16S { rdlo, rdhi, rnlo } => {
4018 let rdlo_bits = reg_to_bits(rdlo);
4019 let rdhi_bits = reg_to_bits(rdhi);
4020 let rnlo_bits = reg_to_bits(rnlo);
4021 let mut bytes = Vec::new();
4022
4023 let hw1: u16 = 0xFA0F_u16;
4026 let hw2: u16 = (0xF080 | (rdlo_bits << 8) | rnlo_bits) as u16;
4027 bytes.extend_from_slice(&hw1.to_le_bytes());
4028 bytes.extend_from_slice(&hw2.to_le_bytes());
4029
4030 let hw1: u16 = 0xEA4F;
4032 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rdlo_bits) as u16;
4033 bytes.extend_from_slice(&hw1.to_le_bytes());
4034 bytes.extend_from_slice(&hw2.to_le_bytes());
4035
4036 Ok(bytes)
4037 }
4038
4039 ArmOp::I64Extend32S { rdlo, rdhi, rnlo } => {
4042 let rdlo_bits = reg_to_bits(rdlo);
4043 let rdhi_bits = reg_to_bits(rdhi);
4044 let rnlo_bits = reg_to_bits(rnlo);
4045 let mut bytes = Vec::new();
4046
4047 if rdlo_bits != rnlo_bits {
4049 let d_bit = ((rdlo_bits >> 3) & 1) as u16;
4051 let mov: u16 = 0x4600
4052 | (d_bit << 7)
4053 | ((rnlo_bits as u16) << 3)
4054 | ((rdlo_bits & 0x7) as u16);
4055 bytes.extend_from_slice(&mov.to_le_bytes());
4056 }
4057
4058 let hw1: u16 = 0xEA4F;
4060 let hw2: u16 = (0x70E0 | (rdhi_bits << 8) | rnlo_bits) as u16;
4061 bytes.extend_from_slice(&hw1.to_le_bytes());
4062 bytes.extend_from_slice(&hw2.to_le_bytes());
4063
4064 Ok(bytes)
4065 }
4066
4067 ArmOp::SelectMove { rd, rm, cond } => {
4070 let rd_bits = reg_to_bits(rd) as u16;
4071 let rm_bits = reg_to_bits(rm) as u16;
4072
4073 use synth_synthesis::Condition;
4075 let cond_bits: u16 = match cond {
4076 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, };
4087
4088 let it_instr: u16 = 0xBF00 | (cond_bits << 4) | 0x8;
4091
4092 let d_bit = (rd_bits >> 3) & 1;
4095 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4096
4097 let mut bytes = it_instr.to_le_bytes().to_vec();
4099 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4100 Ok(bytes)
4101 }
4102
4103 ArmOp::Popcnt { rd, rm } => {
4114 let mut bytes = Vec::new();
4115
4116 if rd != rm {
4118 let rd_bits = reg_to_bits(rd) as u16;
4119 let rm_bits = reg_to_bits(rm) as u16;
4120 let d_bit = (rd_bits >> 3) & 1;
4122 let mov_instr: u16 = 0x4600 | (d_bit << 7) | (rm_bits << 3) | (rd_bits & 0x7);
4123 bytes.extend_from_slice(&mov_instr.to_le_bytes());
4124 }
4125
4126 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x5555)?);
4129 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x5555)?);
4130
4131 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 1)?);
4134
4135 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(11, 11, 12)?);
4137
4138 bytes.extend_from_slice(&self.encode_thumb32_sub_reg_raw(
4140 reg_to_bits(rd),
4141 reg_to_bits(rd),
4142 11,
4143 )?);
4144
4145 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x3333)?);
4148 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x3333)?);
4149
4150 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4152 11,
4153 reg_to_bits(rd),
4154 12,
4155 )?);
4156
4157 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(
4159 reg_to_bits(rd),
4160 reg_to_bits(rd),
4161 2,
4162 )?);
4163
4164 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4166 reg_to_bits(rd),
4167 reg_to_bits(rd),
4168 12,
4169 )?);
4170
4171 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4173 reg_to_bits(rd),
4174 reg_to_bits(rd),
4175 11,
4176 )?);
4177
4178 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 4)?);
4181
4182 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4184 reg_to_bits(rd),
4185 reg_to_bits(rd),
4186 11,
4187 )?);
4188
4189 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, 0x0F0F)?);
4191 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, 0x0F0F)?);
4192
4193 bytes.extend_from_slice(&self.encode_thumb32_and_reg_raw(
4195 reg_to_bits(rd),
4196 reg_to_bits(rd),
4197 12,
4198 )?);
4199
4200 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 8)?);
4203
4204 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4206 reg_to_bits(rd),
4207 reg_to_bits(rd),
4208 11,
4209 )?);
4210
4211 bytes.extend_from_slice(&self.encode_thumb32_lsr_raw(11, reg_to_bits(rd), 16)?);
4214
4215 bytes.extend_from_slice(&self.encode_thumb32_add_reg_raw(
4217 reg_to_bits(rd),
4218 reg_to_bits(rd),
4219 11,
4220 )?);
4221
4222 bytes.extend_from_slice(&self.encode_thumb32_and_imm_raw(
4225 reg_to_bits(rd),
4226 reg_to_bits(rd),
4227 0x3F,
4228 )?);
4229
4230 Ok(bytes)
4231 }
4232
4233 ArmOp::I64DivU {
4238 rdlo: _,
4239 rdhi: _,
4240 rnlo: _,
4241 rnhi: _,
4242 rmlo: _,
4243 rmhi: _,
4244 } => {
4245 let mut bytes = Vec::new();
4246
4247 bytes.extend_from_slice(&0xB4F0u16.to_le_bytes());
4251
4252 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());
4263 bytes.extend_from_slice(&0x0C40u16.to_le_bytes());
4264
4265 let loop_start = bytes.len();
4267
4268 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes());
4279 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());
4288 bytes.extend_from_slice(&0x77D6u16.to_le_bytes());
4289 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes());
4293 bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4294
4295 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes());
4300 bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4301 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());
4332 bytes.extend_from_slice(&0x0703u16.to_le_bytes());
4333 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4336
4337 bytes.extend_from_slice(&0xF1BCu16.to_le_bytes());
4341 bytes.extend_from_slice(&0x0C01u16.to_le_bytes());
4342
4343 let branch_offset_bytes = bytes.len() - loop_start + 4; let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4346 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4347 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4348
4349 bytes.extend_from_slice(&0x4620u16.to_le_bytes()); bytes.extend_from_slice(&0x4629u16.to_le_bytes()); bytes.extend_from_slice(&0xBCF0u16.to_le_bytes());
4357
4358 Ok(bytes)
4359 }
4360
4361 ArmOp::I64DivS {
4366 rdlo: _,
4367 rdhi: _,
4368 rnlo: _,
4369 rnhi: _,
4370 rmlo: _,
4371 rmhi: _,
4372 } => {
4373 let mut bytes = Vec::new();
4374
4375 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4377 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4378
4379 bytes.extend_from_slice(&0xEA81u16.to_le_bytes());
4382 bytes.extend_from_slice(&0x0903u16.to_le_bytes());
4383
4384 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());
4397
4398 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());
4408
4409 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4412 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4413 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4415 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4416 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4418 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4419
4420 let loop_start = bytes.len();
4421
4422 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4426 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());
4432 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4435
4436 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4440 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());
4453 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4455
4456 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4459
4460 let branch_offset_bytes = bytes.len() - loop_start + 4;
4461 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4462 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4463 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4464
4465 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());
4472 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());
4480
4481 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4483 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4484
4485 Ok(bytes)
4486 }
4487
4488 ArmOp::I64RemU {
4493 rdlo: _,
4494 rdhi: _,
4495 rnlo: _,
4496 rnhi: _,
4497 rmlo: _,
4498 rmhi: _,
4499 } => {
4500 let mut bytes = Vec::new();
4501
4502 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4504 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4505
4506 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4508 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4509 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4511 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4512 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4514 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4515
4516 let loop_start = bytes.len();
4517
4518 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4522 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());
4528 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4531
4532 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4536 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());
4549 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4551
4552 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4555
4556 let branch_offset_bytes = bytes.len() - loop_start + 4;
4557 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4558 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4559 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4560
4561 bytes.extend_from_slice(&0x4630u16.to_le_bytes()); bytes.extend_from_slice(&0x4639u16.to_le_bytes()); bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4567 bytes.extend_from_slice(&0x01F0u16.to_le_bytes());
4568
4569 Ok(bytes)
4570 }
4571
4572 ArmOp::I64RemS {
4577 rdlo: _,
4578 rdhi: _,
4579 rnlo: _,
4580 rnhi: _,
4581 rmlo: _,
4582 rmhi: _,
4583 } => {
4584 let mut bytes = Vec::new();
4585
4586 bytes.extend_from_slice(&0xE92Du16.to_le_bytes());
4588 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4589
4590 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());
4604
4605 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());
4615
4616 bytes.extend_from_slice(&0x2400u16.to_le_bytes());
4619 bytes.extend_from_slice(&0x2500u16.to_le_bytes());
4620 bytes.extend_from_slice(&0x2600u16.to_le_bytes());
4622 bytes.extend_from_slice(&0x2700u16.to_le_bytes());
4623 bytes.extend_from_slice(&0xF04Fu16.to_le_bytes());
4625 bytes.extend_from_slice(&0x0840u16.to_le_bytes());
4626
4627 let loop_start = bytes.len();
4628
4629 bytes.extend_from_slice(&0x006Du16.to_le_bytes()); bytes.extend_from_slice(&0xEA45u16.to_le_bytes()); bytes.extend_from_slice(&0x75D4u16.to_le_bytes());
4633 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());
4639 bytes.extend_from_slice(&0x0076u16.to_le_bytes()); bytes.extend_from_slice(&0xEA46u16.to_le_bytes()); bytes.extend_from_slice(&0x76D1u16.to_le_bytes());
4642
4643 bytes.extend_from_slice(&0x0049u16.to_le_bytes()); bytes.extend_from_slice(&0xEA41u16.to_le_bytes()); bytes.extend_from_slice(&0x71D0u16.to_le_bytes());
4647 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());
4660 bytes.extend_from_slice(&0xF044u16.to_le_bytes()); bytes.extend_from_slice(&0x0401u16.to_le_bytes());
4662
4663 bytes.extend_from_slice(&0xF1B8u16.to_le_bytes()); bytes.extend_from_slice(&0x0801u16.to_le_bytes());
4666
4667 let branch_offset_bytes = bytes.len() - loop_start + 4;
4668 let offset_halfwords = -((branch_offset_bytes / 2) as i16);
4669 let bne_encoding = 0xD100u16 | ((offset_halfwords as u16) & 0xFF);
4670 bytes.extend_from_slice(&bne_encoding.to_le_bytes());
4671
4672 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());
4679 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());
4687
4688 bytes.extend_from_slice(&0xE8BDu16.to_le_bytes());
4690 bytes.extend_from_slice(&0x0FF0u16.to_le_bytes());
4691
4692 Ok(bytes)
4693 }
4694
4695 ArmOp::F32Add { sd, sn, sm } => {
4698 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A00, sd, sn, sm)?))
4699 }
4700 ArmOp::F32Sub { sd, sn, sm } => {
4701 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE300A40, sd, sn, sm)?))
4702 }
4703 ArmOp::F32Mul { sd, sn, sm } => {
4704 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE200A00, sd, sn, sm)?))
4705 }
4706 ArmOp::F32Div { sd, sn, sm } => {
4707 Ok(vfp_to_thumb_bytes(encode_vfp_3reg(0xEE800A00, sd, sn, sm)?))
4708 }
4709 ArmOp::F32Abs { sd, sm } => {
4710 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB00AC0, sd, sm)?))
4711 }
4712 ArmOp::F32Neg { sd, sm } => {
4713 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10A40, sd, sm)?))
4714 }
4715 ArmOp::F32Sqrt { sd, sm } => {
4716 Ok(vfp_to_thumb_bytes(encode_vfp_2reg(0xEEB10AC0, sd, sm)?))
4717 }
4718
4719 ArmOp::F32Ceil { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b01),
4722 ArmOp::F32Floor { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b10),
4723 ArmOp::F32Trunc { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b11),
4724 ArmOp::F32Nearest { sd, sm } => self.encode_thumb_f32_rounding(sd, sm, 0b00),
4725 ArmOp::F32Min { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, true),
4726 ArmOp::F32Max { sd, sn, sm } => self.encode_thumb_f32_minmax(sd, sn, sm, false),
4727 ArmOp::F32Copysign { sd, sn, sm } => self.encode_thumb_f32_copysign(sd, sn, sm),
4728
4729 ArmOp::F32Eq { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x0),
4731 ArmOp::F32Ne { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x1),
4732 ArmOp::F32Lt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x4),
4733 ArmOp::F32Le { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0x9),
4734 ArmOp::F32Gt { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xC),
4735 ArmOp::F32Ge { rd, sn, sm } => self.encode_thumb_f32_compare(rd, sn, sm, 0xA),
4736
4737 ArmOp::F32Const { sd, value } => self.encode_thumb_f32_const(sd, *value),
4738
4739 ArmOp::F32Load { sd, addr } => {
4740 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED900A00, sd, addr)?))
4741 }
4742 ArmOp::F32Store { sd, addr } => {
4743 Ok(vfp_to_thumb_bytes(encode_vfp_ldst(0xED800A00, sd, addr)?))
4744 }
4745
4746 ArmOp::F32ConvertI32S { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, true),
4747 ArmOp::F32ConvertI32U { sd, rm } => self.encode_thumb_f32_convert_i32(sd, rm, false),
4748 ArmOp::F32ConvertI64S { .. } | ArmOp::F32ConvertI64U { .. } => {
4749 Err(synth_core::Error::synthesis(
4750 "F32 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4751 ))
4752 }
4753 ArmOp::F32ReinterpretI32 { sd, rm } => {
4754 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(true, sd, rm)?))
4755 }
4756 ArmOp::I32ReinterpretF32 { rd, sm } => {
4757 Ok(vfp_to_thumb_bytes(encode_vmov_core_sreg(false, sm, rd)?))
4758 }
4759 ArmOp::I32TruncF32S { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, true),
4760 ArmOp::I32TruncF32U { rd, sm } => self.encode_thumb_i32_trunc_f32(rd, sm, false),
4761
4762 ArmOp::F64Add { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4765 0xEE300B00, dd, dn, dm,
4766 )?)),
4767 ArmOp::F64Sub { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4768 0xEE300B40, dd, dn, dm,
4769 )?)),
4770 ArmOp::F64Mul { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4771 0xEE200B00, dd, dn, dm,
4772 )?)),
4773 ArmOp::F64Div { dd, dn, dm } => Ok(vfp_to_thumb_bytes(encode_vfp_3reg_f64(
4774 0xEE800B00, dd, dn, dm,
4775 )?)),
4776 ArmOp::F64Abs { dd, dm } => {
4777 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB00BC0, dd, dm)?))
4778 }
4779 ArmOp::F64Neg { dd, dm } => {
4780 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10B40, dd, dm)?))
4781 }
4782 ArmOp::F64Sqrt { dd, dm } => {
4783 Ok(vfp_to_thumb_bytes(encode_vfp_2reg_f64(0xEEB10BC0, dd, dm)?))
4784 }
4785
4786 ArmOp::F64Ceil { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b01),
4789 ArmOp::F64Floor { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b10),
4790 ArmOp::F64Trunc { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b11),
4791 ArmOp::F64Nearest { dd, dm } => self.encode_thumb_f64_rounding(dd, dm, 0b00),
4792 ArmOp::F64Min { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, true),
4793 ArmOp::F64Max { dd, dn, dm } => self.encode_thumb_f64_minmax(dd, dn, dm, false),
4794 ArmOp::F64Copysign { dd, dn, dm } => self.encode_thumb_f64_copysign(dd, dn, dm),
4795
4796 ArmOp::F64Eq { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x0),
4798 ArmOp::F64Ne { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x1),
4799 ArmOp::F64Lt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x4),
4800 ArmOp::F64Le { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0x9),
4801 ArmOp::F64Gt { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xC),
4802 ArmOp::F64Ge { rd, dn, dm } => self.encode_thumb_f64_compare(rd, dn, dm, 0xA),
4803
4804 ArmOp::F64Const { dd, value } => self.encode_thumb_f64_const(dd, *value),
4805
4806 ArmOp::F64Load { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4807 0xED900B00, dd, addr,
4808 )?)),
4809 ArmOp::F64Store { dd, addr } => Ok(vfp_to_thumb_bytes(encode_vfp_ldst_f64(
4810 0xED800B00, dd, addr,
4811 )?)),
4812
4813 ArmOp::F64ConvertI32S { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, true),
4814 ArmOp::F64ConvertI32U { dd, rm } => self.encode_thumb_f64_convert_i32(dd, rm, false),
4815 ArmOp::F64ConvertI64S { .. } | ArmOp::F64ConvertI64U { .. } => {
4816 Err(synth_core::Error::synthesis(
4817 "F64 i64 conversion not supported (requires register pairs on 32-bit ARM)",
4818 ))
4819 }
4820 ArmOp::F64PromoteF32 { dd, sm } => self.encode_thumb_f64_promote_f32(dd, sm),
4821 ArmOp::F64ReinterpretI64 { dd, rmlo, rmhi } => Ok(vfp_to_thumb_bytes(
4822 encode_vmov_core_dreg(true, dd, rmlo, rmhi)?,
4823 )),
4824 ArmOp::I64ReinterpretF64 { rdlo, rdhi, dm } => Ok(vfp_to_thumb_bytes(
4825 encode_vmov_core_dreg(false, dm, rdlo, rdhi)?,
4826 )),
4827 ArmOp::I64TruncF64S { .. } | ArmOp::I64TruncF64U { .. } => {
4828 Err(synth_core::Error::synthesis(
4829 "i64 truncation from F64 not supported (requires i64 register pairs on 32-bit ARM)",
4830 ))
4831 }
4832 ArmOp::I32TruncF64S { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, true),
4833 ArmOp::I32TruncF64U { rd, dm } => self.encode_thumb_i32_trunc_f64(rd, dm, false),
4834
4835 ArmOp::I64Add {
4839 rdlo,
4840 rdhi,
4841 rnlo,
4842 rnhi,
4843 rmlo,
4844 rmhi,
4845 } => {
4846 let mut bytes = Vec::new();
4847 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adds {
4849 rd: *rdlo,
4850 rn: *rnlo,
4851 op2: Operand2::Reg(*rmlo),
4852 })?);
4853 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Adc {
4855 rd: *rdhi,
4856 rn: *rnhi,
4857 op2: Operand2::Reg(*rmhi),
4858 })?);
4859 Ok(bytes)
4860 }
4861
4862 ArmOp::I64Sub {
4864 rdlo,
4865 rdhi,
4866 rnlo,
4867 rnhi,
4868 rmlo,
4869 rmhi,
4870 } => {
4871 let mut bytes = Vec::new();
4872 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Subs {
4874 rd: *rdlo,
4875 rn: *rnlo,
4876 op2: Operand2::Reg(*rmlo),
4877 })?);
4878 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Sbc {
4880 rd: *rdhi,
4881 rn: *rnhi,
4882 op2: Operand2::Reg(*rmhi),
4883 })?);
4884 Ok(bytes)
4885 }
4886
4887 ArmOp::I64And {
4889 rdlo,
4890 rdhi,
4891 rnlo,
4892 rnhi,
4893 rmlo,
4894 rmhi,
4895 } => {
4896 let mut bytes = Vec::new();
4897 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4898 rd: *rdlo,
4899 rn: *rnlo,
4900 op2: Operand2::Reg(*rmlo),
4901 })?);
4902 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::And {
4903 rd: *rdhi,
4904 rn: *rnhi,
4905 op2: Operand2::Reg(*rmhi),
4906 })?);
4907 Ok(bytes)
4908 }
4909
4910 ArmOp::I64Or {
4912 rdlo,
4913 rdhi,
4914 rnlo,
4915 rnhi,
4916 rmlo,
4917 rmhi,
4918 } => {
4919 let mut bytes = Vec::new();
4920 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4921 rd: *rdlo,
4922 rn: *rnlo,
4923 op2: Operand2::Reg(*rmlo),
4924 })?);
4925 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Orr {
4926 rd: *rdhi,
4927 rn: *rnhi,
4928 op2: Operand2::Reg(*rmhi),
4929 })?);
4930 Ok(bytes)
4931 }
4932
4933 ArmOp::I64Xor {
4935 rdlo,
4936 rdhi,
4937 rnlo,
4938 rnhi,
4939 rmlo,
4940 rmhi,
4941 } => {
4942 let mut bytes = Vec::new();
4943 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4944 rd: *rdlo,
4945 rn: *rnlo,
4946 op2: Operand2::Reg(*rmlo),
4947 })?);
4948 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Eor {
4949 rd: *rdhi,
4950 rn: *rnhi,
4951 op2: Operand2::Reg(*rmhi),
4952 })?);
4953 Ok(bytes)
4954 }
4955
4956 ArmOp::I64Eqz { rd, rnlo, rnhi } => self.encode_thumb(&ArmOp::I64SetCondZ {
4958 rd: *rd,
4959 rn_lo: *rnlo,
4960 rn_hi: *rnhi,
4961 }),
4962
4963 ArmOp::I64Eq {
4965 rd,
4966 rnlo,
4967 rnhi,
4968 rmlo,
4969 rmhi,
4970 } => self.encode_thumb(&ArmOp::I64SetCond {
4971 rd: *rd,
4972 rn_lo: *rnlo,
4973 rn_hi: *rnhi,
4974 rm_lo: *rmlo,
4975 rm_hi: *rmhi,
4976 cond: synth_synthesis::Condition::EQ,
4977 }),
4978
4979 ArmOp::I64Ne {
4980 rd,
4981 rnlo,
4982 rnhi,
4983 rmlo,
4984 rmhi,
4985 } => self.encode_thumb(&ArmOp::I64SetCond {
4986 rd: *rd,
4987 rn_lo: *rnlo,
4988 rn_hi: *rnhi,
4989 rm_lo: *rmlo,
4990 rm_hi: *rmhi,
4991 cond: synth_synthesis::Condition::NE,
4992 }),
4993
4994 ArmOp::I64LtS {
4995 rd,
4996 rnlo,
4997 rnhi,
4998 rmlo,
4999 rmhi,
5000 } => self.encode_thumb(&ArmOp::I64SetCond {
5001 rd: *rd,
5002 rn_lo: *rnlo,
5003 rn_hi: *rnhi,
5004 rm_lo: *rmlo,
5005 rm_hi: *rmhi,
5006 cond: synth_synthesis::Condition::LT,
5007 }),
5008
5009 ArmOp::I64LtU {
5010 rd,
5011 rnlo,
5012 rnhi,
5013 rmlo,
5014 rmhi,
5015 } => self.encode_thumb(&ArmOp::I64SetCond {
5016 rd: *rd,
5017 rn_lo: *rnlo,
5018 rn_hi: *rnhi,
5019 rm_lo: *rmlo,
5020 rm_hi: *rmhi,
5021 cond: synth_synthesis::Condition::LO,
5022 }),
5023
5024 ArmOp::I64LeS {
5025 rd,
5026 rnlo,
5027 rnhi,
5028 rmlo,
5029 rmhi,
5030 } => self.encode_thumb(&ArmOp::I64SetCond {
5031 rd: *rd,
5032 rn_lo: *rnlo,
5033 rn_hi: *rnhi,
5034 rm_lo: *rmlo,
5035 rm_hi: *rmhi,
5036 cond: synth_synthesis::Condition::LE,
5037 }),
5038
5039 ArmOp::I64LeU {
5040 rd,
5041 rnlo,
5042 rnhi,
5043 rmlo,
5044 rmhi,
5045 } => self.encode_thumb(&ArmOp::I64SetCond {
5046 rd: *rd,
5047 rn_lo: *rnlo,
5048 rn_hi: *rnhi,
5049 rm_lo: *rmlo,
5050 rm_hi: *rmhi,
5051 cond: synth_synthesis::Condition::LS,
5052 }),
5053
5054 ArmOp::I64GtS {
5055 rd,
5056 rnlo,
5057 rnhi,
5058 rmlo,
5059 rmhi,
5060 } => self.encode_thumb(&ArmOp::I64SetCond {
5061 rd: *rd,
5062 rn_lo: *rnlo,
5063 rn_hi: *rnhi,
5064 rm_lo: *rmlo,
5065 rm_hi: *rmhi,
5066 cond: synth_synthesis::Condition::GT,
5067 }),
5068
5069 ArmOp::I64GtU {
5070 rd,
5071 rnlo,
5072 rnhi,
5073 rmlo,
5074 rmhi,
5075 } => self.encode_thumb(&ArmOp::I64SetCond {
5076 rd: *rd,
5077 rn_lo: *rnlo,
5078 rn_hi: *rnhi,
5079 rm_lo: *rmlo,
5080 rm_hi: *rmhi,
5081 cond: synth_synthesis::Condition::HI,
5082 }),
5083
5084 ArmOp::I64GeS {
5085 rd,
5086 rnlo,
5087 rnhi,
5088 rmlo,
5089 rmhi,
5090 } => self.encode_thumb(&ArmOp::I64SetCond {
5091 rd: *rd,
5092 rn_lo: *rnlo,
5093 rn_hi: *rnhi,
5094 rm_lo: *rmlo,
5095 rm_hi: *rmhi,
5096 cond: synth_synthesis::Condition::GE,
5097 }),
5098
5099 ArmOp::I64GeU {
5100 rd,
5101 rnlo,
5102 rnhi,
5103 rmlo,
5104 rmhi,
5105 } => self.encode_thumb(&ArmOp::I64SetCond {
5106 rd: *rd,
5107 rn_lo: *rnlo,
5108 rn_hi: *rnhi,
5109 rm_lo: *rmlo,
5110 rm_hi: *rmhi,
5111 cond: synth_synthesis::Condition::HS,
5112 }),
5113
5114 ArmOp::I64Const { rdlo, rdhi, value } => {
5116 let lo32 = *value as u32;
5117 let hi32 = (*value >> 32) as u32;
5118 let mut bytes = Vec::new();
5119 bytes.extend_from_slice(
5121 &self.encode_thumb32_movw_raw(reg_to_bits(rdlo), lo32 & 0xFFFF)?,
5122 );
5123 if lo32 > 0xFFFF {
5124 bytes.extend_from_slice(
5125 &self.encode_thumb32_movt_raw(reg_to_bits(rdlo), lo32 >> 16)?,
5126 );
5127 }
5128 bytes.extend_from_slice(
5130 &self.encode_thumb32_movw_raw(reg_to_bits(rdhi), hi32 & 0xFFFF)?,
5131 );
5132 if hi32 > 0xFFFF {
5133 bytes.extend_from_slice(
5134 &self.encode_thumb32_movt_raw(reg_to_bits(rdhi), hi32 >> 16)?,
5135 );
5136 }
5137 Ok(bytes)
5138 }
5139
5140 ArmOp::I64Ldr { rdlo, rdhi, addr } => {
5142 let mut bytes = Vec::new();
5143 let offset = if addr.offset < 0 {
5144 0u32
5145 } else {
5146 addr.offset as u32
5147 };
5148 bytes.extend_from_slice(&self.encode_thumb32_ldr(rdlo, &addr.base, offset)?);
5149 bytes.extend_from_slice(&self.encode_thumb32_ldr(
5150 rdhi,
5151 &addr.base,
5152 offset.wrapping_add(4),
5153 )?);
5154 Ok(bytes)
5155 }
5156
5157 ArmOp::I64Str { rdlo, rdhi, addr } => {
5159 let mut bytes = Vec::new();
5160 let offset = if addr.offset < 0 {
5161 0u32
5162 } else {
5163 addr.offset as u32
5164 };
5165 bytes.extend_from_slice(&self.encode_thumb32_str(rdlo, &addr.base, offset)?);
5166 bytes.extend_from_slice(&self.encode_thumb32_str(
5167 rdhi,
5168 &addr.base,
5169 offset.wrapping_add(4),
5170 )?);
5171 Ok(bytes)
5172 }
5173
5174 ArmOp::I64ExtendI32S { rdlo, rdhi, rn } => {
5176 let mut bytes = Vec::new();
5177 if rdlo != rn {
5178 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5180 rd: *rdlo,
5181 op2: Operand2::Reg(*rn),
5182 })?);
5183 }
5184 bytes.extend_from_slice(
5186 &self.encode_thumb32_shift(rdhi, rdlo, 31, 0b10)?, );
5188 Ok(bytes)
5189 }
5190
5191 ArmOp::I64ExtendI32U { rdlo, rdhi, rn } => {
5193 let mut bytes = Vec::new();
5194 if rdlo != rn {
5195 bytes.extend_from_slice(&self.encode_thumb(&ArmOp::Mov {
5197 rd: *rdlo,
5198 op2: Operand2::Reg(*rn),
5199 })?);
5200 }
5201 let rdhi_bits = reg_to_bits(rdhi) as u16;
5203 let instr: u16 = 0x2000 | (rdhi_bits << 8);
5204 bytes.extend_from_slice(&instr.to_le_bytes());
5205 Ok(bytes)
5206 }
5207
5208 ArmOp::I32WrapI64 { rd, rnlo } => {
5210 if rd == rnlo {
5211 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5214 } else {
5215 self.encode_thumb(&ArmOp::Mov {
5217 rd: *rd,
5218 op2: Operand2::Reg(*rnlo),
5219 })
5220 }
5221 }
5222
5223 ArmOp::MveLoad { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vldrw(qd, addr))),
5225 ArmOp::MveStore { qd, addr } => Ok(vfp_to_thumb_bytes(encode_mve_vstrw(qd, addr))),
5226 ArmOp::MveConst { qd, bytes } => self.encode_thumb_mve_const(qd, bytes),
5227 ArmOp::MveAnd { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5228 0xEF000150, qd, qn, qm,
5229 ))),
5230 ArmOp::MveOrr { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5231 0xEF200150, qd, qn, qm,
5232 ))),
5233 ArmOp::MveEor { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5234 0xFF000150, qd, qn, qm,
5235 ))),
5236 ArmOp::MveMvn { qd, qm } => {
5237 let qd_enc = qreg_to_num(qd);
5239 let qm_enc = qreg_to_num(qm);
5240 let instr: u32 = 0xFFB005C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5241 Ok(vfp_to_thumb_bytes(instr))
5242 }
5243 ArmOp::MveBic { qd, qn, qm } => Ok(vfp_to_thumb_bytes(encode_mve_3reg_bitwise(
5244 0xEF100150, qd, qn, qm,
5245 ))),
5246 ArmOp::MveAddI { qd, qn, qm, size } => {
5247 let sz = mve_size_bits(size);
5248 let base: u32 = 0xEF000840 | (sz << 20);
5249 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5250 }
5251 ArmOp::MveSubI { qd, qn, qm, size } => {
5252 let sz = mve_size_bits(size);
5253 let base: u32 = 0xFF000840 | (sz << 20);
5254 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5255 }
5256 ArmOp::MveMulI { qd, qn, qm, size } => {
5257 let sz = mve_size_bits(size);
5258 let base: u32 = 0xEF000950 | (sz << 20);
5259 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5260 }
5261 ArmOp::MveNegI { qd, qm, size } => {
5262 let sz = mve_size_bits(size);
5263 let qd_enc = qreg_to_num(qd);
5265 let qm_enc = qreg_to_num(qm);
5266 let base: u32 = 0xFFB103C0 | (sz << 18);
5267 let instr = base | ((qd_enc * 2) << 12) | (qm_enc * 2);
5268 Ok(vfp_to_thumb_bytes(instr))
5269 }
5270 ArmOp::MveDup { qd, rn, size } => {
5271 let sz = mve_size_bits(size);
5272 let qd_enc = qreg_to_num(qd);
5273 let rn_bits = reg_to_bits(rn);
5274 let be = match sz {
5277 0 => 0b00u32, 1 => 0b01, _ => 0b00, };
5281 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12) | (be << 5);
5282 Ok(vfp_to_thumb_bytes(instr))
5283 }
5284 ArmOp::MveExtractLane { rd, qn, lane, size } => {
5285 let qn_enc = qreg_to_num(qn);
5286 let rd_bits = reg_to_bits(rd);
5287 let d_reg = qn_enc * 2 + ((*lane as u32) >> 1);
5290 let lane_in_d = (*lane as u32) & 1;
5291 let _sz = mve_size_bits(size);
5292 let instr: u32 = 0xEE100B10 | (d_reg << 16) | (rd_bits << 12) | (lane_in_d << 21);
5294 Ok(vfp_to_thumb_bytes(instr))
5295 }
5296 ArmOp::MveInsertLane { qd, rn, lane, size } => {
5297 let qd_enc = qreg_to_num(qd);
5298 let rn_bits = reg_to_bits(rn);
5299 let d_reg = qd_enc * 2 + ((*lane as u32) >> 1);
5300 let lane_in_d = (*lane as u32) & 1;
5301 let _sz = mve_size_bits(size);
5302 let instr: u32 = 0xEE000B10 | (d_reg << 16) | (rn_bits << 12) | (lane_in_d << 21);
5304 Ok(vfp_to_thumb_bytes(instr))
5305 }
5306
5307 ArmOp::MveCmpEqI { qd, qn, qm, size }
5309 | ArmOp::MveCmpNeI { qd, qn, qm, size }
5310 | ArmOp::MveCmpLtS { qd, qn, qm, size }
5311 | ArmOp::MveCmpLtU { qd, qn, qm, size }
5312 | ArmOp::MveCmpGtS { qd, qn, qm, size }
5313 | ArmOp::MveCmpGtU { qd, qn, qm, size }
5314 | ArmOp::MveCmpLeS { qd, qn, qm, size }
5315 | ArmOp::MveCmpLeU { qd, qn, qm, size }
5316 | ArmOp::MveCmpGeS { qd, qn, qm, size }
5317 | ArmOp::MveCmpGeU { qd, qn, qm, size } => {
5318 let sz = mve_size_bits(size);
5321 let base: u32 = 0xEF000840 | (sz << 20);
5322 Ok(vfp_to_thumb_bytes(encode_mve_3reg(base, qd, qn, qm)))
5323 }
5324
5325 ArmOp::MveAddF32 { qd, qn, qm } => {
5327 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5329 }
5330 ArmOp::MveSubF32 { qd, qn, qm } => {
5331 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF200D40, qd, qn, qm)))
5333 }
5334 ArmOp::MveMulF32 { qd, qn, qm } => {
5335 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xFF000D50, qd, qn, qm)))
5337 }
5338 ArmOp::MveNegF32 { qd, qm } => {
5339 let qd_enc = qreg_to_num(qd);
5340 let qm_enc = qreg_to_num(qm);
5341 let instr: u32 = 0xFFB907C0 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5343 Ok(vfp_to_thumb_bytes(instr))
5344 }
5345 ArmOp::MveAbsF32 { qd, qm } => {
5346 let qd_enc = qreg_to_num(qd);
5347 let qm_enc = qreg_to_num(qm);
5348 let instr: u32 = 0xFFB90740 | ((qd_enc * 2) << 12) | (qm_enc * 2);
5350 Ok(vfp_to_thumb_bytes(instr))
5351 }
5352 ArmOp::MveCmpEqF32 { qd, qn, qm }
5353 | ArmOp::MveCmpNeF32 { qd, qn, qm }
5354 | ArmOp::MveCmpLtF32 { qd, qn, qm }
5355 | ArmOp::MveCmpLeF32 { qd, qn, qm }
5356 | ArmOp::MveCmpGtF32 { qd, qn, qm }
5357 | ArmOp::MveCmpGeF32 { qd, qn, qm } => {
5358 Ok(vfp_to_thumb_bytes(encode_mve_3reg(0xEF000D40, qd, qn, qm)))
5360 }
5361 ArmOp::MveDupF32 { qd, rn } => {
5362 let qd_enc = qreg_to_num(qd);
5363 let rn_bits = reg_to_bits(rn);
5364 let instr: u32 = 0xEEA00B10 | ((qd_enc * 2) << 16) | (rn_bits << 12);
5366 Ok(vfp_to_thumb_bytes(instr))
5367 }
5368 ArmOp::MveExtractLaneF32 { rd, qn, lane } => {
5369 let qn_enc = qreg_to_num(qn);
5370 let rd_bits = reg_to_bits(rd);
5371 let s_num = qn_enc * 4 + (*lane as u32);
5373 let (vn, n) = encode_sreg(s_num);
5374 let instr: u32 = 0xEE100A10 | (vn << 16) | (rd_bits << 12) | (n << 7);
5375 Ok(vfp_to_thumb_bytes(instr))
5376 }
5377 ArmOp::MveReplaceLaneF32 { qd, rn, lane } => {
5378 let qd_enc = qreg_to_num(qd);
5379 let rn_bits = reg_to_bits(rn);
5380 let s_num = qd_enc * 4 + (*lane as u32);
5382 let (vn, n) = encode_sreg(s_num);
5383 let instr: u32 = 0xEE000A10 | (vn << 16) | (rn_bits << 12) | (n << 7);
5384 Ok(vfp_to_thumb_bytes(instr))
5385 }
5386 ArmOp::MveDivF32 { qd, qn, qm } => {
5387 self.encode_thumb_mve_lane_wise_f32_binop(qd, qn, qm, 0xEE800A00)
5389 }
5390 ArmOp::MveSqrtF32 { qd, qm } => {
5391 self.encode_thumb_mve_lane_wise_f32_sqrt(qd, qm)
5393 }
5394
5395 _ => {
5397 let instr: u16 = 0xBF00; Ok(instr.to_le_bytes().to_vec())
5399 }
5400 }
5401 }
5402
5403 fn encode_thumb_f32_compare(
5407 &self,
5408 rd: &Reg,
5409 sn: &VfpReg,
5410 sm: &VfpReg,
5411 cond_code: u32,
5412 ) -> Result<Vec<u8>> {
5413 let mut bytes = Vec::new();
5414 let rd_bits = reg_to_bits(rd);
5415
5416 let sn_num = vfp_sreg_to_num(sn)?;
5418 let sm_num = vfp_sreg_to_num(sm)?;
5419 let (vd, d) = encode_sreg(sn_num);
5420 let (vm, m) = encode_sreg(sm_num);
5421 let vcmp = 0xEEB40A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5422 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5423
5424 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5426
5427 if rd_bits < 8 {
5429 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5430 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5431 } else {
5432 let hw1: u16 = 0xF04F;
5434 let hw2: u16 = (rd_bits as u16) << 8;
5435 bytes.extend_from_slice(&hw1.to_le_bytes());
5436 bytes.extend_from_slice(&hw2.to_le_bytes());
5437 }
5438
5439 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5443 bytes.extend_from_slice(&it.to_le_bytes());
5444
5445 if rd_bits < 8 {
5447 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5448 bytes.extend_from_slice(&mov_one.to_le_bytes());
5449 } else {
5450 let hw1: u16 = 0xF04F;
5452 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5453 bytes.extend_from_slice(&hw1.to_le_bytes());
5454 bytes.extend_from_slice(&hw2.to_le_bytes());
5455 }
5456
5457 Ok(bytes)
5458 }
5459
5460 fn encode_thumb_f32_const(&self, sd: &VfpReg, value: f32) -> Result<Vec<u8>> {
5462 let mut bytes = Vec::new();
5463 let bits = value.to_bits();
5464 let rt: u32 = 12; let lo16 = bits & 0xFFFF;
5469 let imm4 = (lo16 >> 12) & 0xF;
5470 let i_bit = (lo16 >> 11) & 1;
5471 let imm3 = (lo16 >> 8) & 0x7;
5472 let imm8 = lo16 & 0xFF;
5473 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
5474 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5475 bytes.extend_from_slice(&hw1.to_le_bytes());
5476 bytes.extend_from_slice(&hw2.to_le_bytes());
5477
5478 let hi16 = (bits >> 16) & 0xFFFF;
5480 let imm4 = (hi16 >> 12) & 0xF;
5481 let i_bit = (hi16 >> 11) & 1;
5482 let imm3 = (hi16 >> 8) & 0x7;
5483 let imm8 = hi16 & 0xFF;
5484 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
5485 let hw2: u16 = ((imm3 << 12) | (rt << 8) | imm8) as u16;
5486 bytes.extend_from_slice(&hw1.to_le_bytes());
5487 bytes.extend_from_slice(&hw2.to_le_bytes());
5488
5489 let vmov = encode_vmov_core_sreg(true, sd, &Reg::R12)?;
5491 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5492
5493 Ok(bytes)
5494 }
5495
5496 fn encode_thumb_f32_convert_i32(&self, sd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5498 let mut bytes = Vec::new();
5499
5500 let vmov = encode_vmov_core_sreg(true, sd, rm)?;
5502 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5503
5504 let sd_num = vfp_sreg_to_num(sd)?;
5506 let (vd, d) = encode_sreg(sd_num);
5507 let (vm, m) = encode_sreg(sd_num);
5508 let base = if signed { 0xEEB80A40 } else { 0xEEB80AC0 };
5509 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5510 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5511
5512 Ok(bytes)
5513 }
5514
5515 fn encode_thumb_f32_rounding(&self, sd: &VfpReg, sm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5523 let mut bytes = Vec::new();
5524 let sm_num = vfp_sreg_to_num(sm)?;
5525 let sd_num = vfp_sreg_to_num(sd)?;
5526 let (vd_s, d_s) = encode_sreg(sd_num);
5527 let (vm_s, m_s) = encode_sreg(sm_num);
5528
5529 if mode == 0b11 {
5530 let vcvt_to_int = 0xEEBD0AC0 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5532 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5533 } else {
5534 let rt: u32 = 12; let vmrs = 0xEEF10A10 | (rt << 12);
5539 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5540
5541 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF); let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5547 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5548 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5549
5550 if mode != 0 {
5552 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF); let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5554 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5555 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5556 }
5557
5558 let vmsr = 0xEEE10A10 | (rt << 12);
5560 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5561
5562 let vcvt_to_int = 0xEEBD0A40 | (d_s << 22) | (vd_s << 12) | (m_s << 5) | vm_s;
5564 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5565
5566 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5568 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5569 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5570 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5571 }
5572
5573 let (vd2, d2) = encode_sreg(sd_num);
5575 let vcvt_to_float = 0xEEB80A40 | (d2 << 22) | (vd2 << 12) | (d_s << 5) | vd_s;
5576 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5577
5578 Ok(bytes)
5579 }
5580
5581 fn encode_thumb_f32_minmax(
5583 &self,
5584 sd: &VfpReg,
5585 sn: &VfpReg,
5586 sm: &VfpReg,
5587 is_min: bool,
5588 ) -> Result<Vec<u8>> {
5589 let mut bytes = Vec::new();
5590 let sn_num = vfp_sreg_to_num(sn)?;
5591 let sm_num = vfp_sreg_to_num(sm)?;
5592 let sd_num = vfp_sreg_to_num(sd)?;
5593
5594 let (vd, d) = encode_sreg(sd_num);
5596 let (vn, n) = encode_sreg(sn_num);
5597 let vmov_sn = 0xEEB00A40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5598 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sn));
5599
5600 let (vm, m) = encode_sreg(sm_num);
5602 let vcmp = 0xEEB40A40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5603 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5604
5605 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5607
5608 let cond: u16 = if is_min { 0xC } else { 0x4 };
5610 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5611 bytes.extend_from_slice(&it.to_le_bytes());
5612
5613 let vmov_sm = 0xEEB00A40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5615 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_sm));
5616
5617 Ok(bytes)
5618 }
5619
5620 fn encode_thumb_f32_copysign(&self, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5622 let mut bytes = Vec::new();
5623
5624 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5626 false,
5627 sm,
5628 &Reg::R12,
5629 )?));
5630
5631 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5633 false,
5634 sn,
5635 &Reg::R0,
5636 )?));
5637
5638 let hw1: u16 = 0xF000 | 12; let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5650 bytes.extend_from_slice(&hw2.to_le_bytes());
5651
5652 let hw1: u16 = 0xF020; let hw2: u16 = (0x1 << 12) | 0x02; bytes.extend_from_slice(&hw1.to_le_bytes());
5656 bytes.extend_from_slice(&hw2.to_le_bytes());
5657
5658 let hw1: u16 = 0xEA40; let hw2: u16 = 12; bytes.extend_from_slice(&hw1.to_le_bytes());
5662 bytes.extend_from_slice(&hw2.to_le_bytes());
5663
5664 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_sreg(
5666 true,
5667 sd,
5668 &Reg::R0,
5669 )?));
5670
5671 Ok(bytes)
5672 }
5673
5674 fn encode_thumb_f64_compare(
5676 &self,
5677 rd: &Reg,
5678 dn: &VfpReg,
5679 dm: &VfpReg,
5680 cond_code: u32,
5681 ) -> Result<Vec<u8>> {
5682 let mut bytes = Vec::new();
5683 let rd_bits = reg_to_bits(rd);
5684
5685 let dn_num = vfp_dreg_to_num(dn)?;
5687 let dm_num = vfp_dreg_to_num(dm)?;
5688 let (vd, d) = encode_dreg(dn_num);
5689 let (vm, m) = encode_dreg(dm_num);
5690 let vcmp = 0xEEB40B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5691 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5692
5693 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5695
5696 if rd_bits < 8 {
5698 let movs_zero: u16 = 0x2000 | ((rd_bits as u16) << 8);
5699 bytes.extend_from_slice(&movs_zero.to_le_bytes());
5700 } else {
5701 let hw1: u16 = 0xF04F;
5702 let hw2: u16 = (rd_bits as u16) << 8;
5703 bytes.extend_from_slice(&hw1.to_le_bytes());
5704 bytes.extend_from_slice(&hw2.to_le_bytes());
5705 }
5706
5707 let it: u16 = 0xBF00 | ((cond_code as u16) << 4) | 0x8;
5709 bytes.extend_from_slice(&it.to_le_bytes());
5710
5711 if rd_bits < 8 {
5713 let mov_one: u16 = 0x2001 | ((rd_bits as u16) << 8);
5714 bytes.extend_from_slice(&mov_one.to_le_bytes());
5715 } else {
5716 let hw1: u16 = 0xF04F;
5717 let hw2: u16 = ((rd_bits as u16) << 8) | 0x01;
5718 bytes.extend_from_slice(&hw1.to_le_bytes());
5719 bytes.extend_from_slice(&hw2.to_le_bytes());
5720 }
5721
5722 Ok(bytes)
5723 }
5724
5725 fn encode_thumb_f64_const(&self, dd: &VfpReg, value: f64) -> Result<Vec<u8>> {
5727 let mut bytes = Vec::new();
5728 let bits = value.to_bits();
5729 let lo32 = bits as u32;
5730 let hi32 = (bits >> 32) as u32;
5731
5732 let lo16 = lo32 & 0xFFFF;
5734 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(0, lo16)?);
5735
5736 let hi16 = (lo32 >> 16) & 0xFFFF;
5738 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(0, hi16)?);
5739
5740 let lo16 = hi32 & 0xFFFF;
5742 bytes.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
5743
5744 let hi16 = (hi32 >> 16) & 0xFFFF;
5746 bytes.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
5747
5748 let vmov = encode_vmov_core_dreg(true, dd, &Reg::R0, &Reg::R12)?;
5750 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5751
5752 Ok(bytes)
5753 }
5754
5755 fn encode_thumb_f64_convert_i32(&self, dd: &VfpReg, rm: &Reg, signed: bool) -> Result<Vec<u8>> {
5757 let mut bytes = Vec::new();
5758
5759 let vmov = encode_vmov_core_sreg(true, &VfpReg::S0, rm)?;
5761 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5762
5763 let dd_num = vfp_dreg_to_num(dd)?;
5765 let (vd, d) = encode_dreg(dd_num);
5766 let base = if signed { 0xEEB80B40 } else { 0xEEB80BC0 };
5767 let vcvt = base | (d << 22) | (vd << 12);
5768 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5769
5770 Ok(bytes)
5771 }
5772
5773 fn encode_thumb_f64_promote_f32(&self, dd: &VfpReg, sm: &VfpReg) -> Result<Vec<u8>> {
5775 let dd_num = vfp_dreg_to_num(dd)?;
5776 let sm_num = vfp_sreg_to_num(sm)?;
5777 let (vd, d) = encode_dreg(dd_num);
5778 let (vm, m) = encode_sreg(sm_num);
5779
5780 let vcvt = 0xEEB70AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
5781 Ok(vfp_to_thumb_bytes(vcvt))
5782 }
5783
5784 fn encode_thumb_i32_trunc_f64(&self, rd: &Reg, dm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5786 let mut bytes = Vec::new();
5787 let dm_num = vfp_dreg_to_num(dm)?;
5788 let (vm, m) = encode_dreg(dm_num);
5789
5790 let base = if signed { 0xEEBD0BC0 } else { 0xEEBC0BC0 };
5792 let vcvt = base | (m << 5) | vm;
5793 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5794
5795 let vmov = encode_vmov_core_sreg(false, &VfpReg::S0, rd)?;
5797 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5798
5799 Ok(bytes)
5800 }
5801
5802 fn encode_thumb_f64_rounding(&self, dd: &VfpReg, dm: &VfpReg, mode: u8) -> Result<Vec<u8>> {
5806 let mut bytes = Vec::new();
5807 let dm_num = vfp_dreg_to_num(dm)?;
5808 let dd_num = vfp_dreg_to_num(dd)?;
5809 let (vm, m) = encode_dreg(dm_num);
5810 let (vd, d) = encode_dreg(dd_num);
5811
5812 if mode == 0b11 {
5813 let vcvt_to_int = 0xEEBD0BC0 | (m << 5) | vm;
5815 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5816 } else {
5817 let rt: u32 = 12;
5818
5819 let vmrs = 0xEEF10A10 | (rt << 12);
5821 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5822
5823 let bic_hw1: u16 = 0xF020 | ((rt as u16) & 0xF);
5825 let bic_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | 0x03;
5826 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5827 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5828
5829 if mode != 0 {
5831 let orr_hw1: u16 = 0xF040 | ((rt as u16) & 0xF);
5832 let orr_hw2: u16 = (0x05 << 12) | ((rt as u16) << 8) | (mode as u16);
5833 bytes.extend_from_slice(&orr_hw1.to_le_bytes());
5834 bytes.extend_from_slice(&orr_hw2.to_le_bytes());
5835 }
5836
5837 let vmsr = 0xEEE10A10 | (rt << 12);
5839 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5840
5841 let vcvt_to_int = 0xEEBD0B40 | (m << 5) | vm;
5843 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_int));
5844
5845 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmrs));
5847 bytes.extend_from_slice(&bic_hw1.to_le_bytes());
5848 bytes.extend_from_slice(&bic_hw2.to_le_bytes());
5849 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmsr));
5850 }
5851
5852 let vcvt_to_float = 0xEEB80B40 | (d << 22) | (vd << 12);
5854 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt_to_float));
5855
5856 Ok(bytes)
5857 }
5858
5859 fn encode_thumb_f64_minmax(
5861 &self,
5862 dd: &VfpReg,
5863 dn: &VfpReg,
5864 dm: &VfpReg,
5865 is_min: bool,
5866 ) -> Result<Vec<u8>> {
5867 let mut bytes = Vec::new();
5868 let dn_num = vfp_dreg_to_num(dn)?;
5869 let dm_num = vfp_dreg_to_num(dm)?;
5870 let dd_num = vfp_dreg_to_num(dd)?;
5871
5872 let (vd, d) = encode_dreg(dd_num);
5874 let (vn, n) = encode_dreg(dn_num);
5875 let vmov_dn = 0xEEB00B40 | (d << 22) | (vd << 12) | (n << 5) | vn;
5876 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dn));
5877
5878 let (vm, m) = encode_dreg(dm_num);
5880 let vcmp = 0xEEB40B40 | (n << 22) | (vn << 12) | (m << 5) | vm;
5881 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcmp));
5882
5883 bytes.extend_from_slice(&vfp_to_thumb_bytes(0xEEF1FA10));
5885
5886 let cond: u16 = if is_min { 0xC } else { 0x4 };
5888 let it: u16 = 0xBF00 | (cond << 4) | 0x8;
5889 bytes.extend_from_slice(&it.to_le_bytes());
5890
5891 let vmov_dm = 0xEEB00B40 | (d << 22) | (vd << 12) | (m << 5) | vm;
5893 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov_dm));
5894
5895 Ok(bytes)
5896 }
5897
5898 fn encode_thumb_f64_copysign(&self, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<Vec<u8>> {
5900 let mut bytes = Vec::new();
5901
5902 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5904 false,
5905 dm,
5906 &Reg::R0,
5907 &Reg::R12,
5908 )?));
5909
5910 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5912 false,
5913 dn,
5914 &Reg::R1,
5915 &Reg::R2,
5916 )?));
5917
5918 let hw1: u16 = 0xF000 | 12;
5920 let hw2: u16 = (0x1 << 12) | (12 << 8) | 0x02;
5921 bytes.extend_from_slice(&hw1.to_le_bytes());
5922 bytes.extend_from_slice(&hw2.to_le_bytes());
5923
5924 let hw1: u16 = 0xF020 | 2;
5926 let hw2: u16 = (0x1 << 12) | (2 << 8) | 0x02;
5927 bytes.extend_from_slice(&hw1.to_le_bytes());
5928 bytes.extend_from_slice(&hw2.to_le_bytes());
5929
5930 let hw1: u16 = 0xEA40 | 2;
5932 let hw2: u16 = (2 << 8) | 12;
5933 bytes.extend_from_slice(&hw1.to_le_bytes());
5934 bytes.extend_from_slice(&hw2.to_le_bytes());
5935
5936 bytes.extend_from_slice(&vfp_to_thumb_bytes(encode_vmov_core_dreg(
5938 true,
5939 dd,
5940 &Reg::R1,
5941 &Reg::R2,
5942 )?));
5943
5944 Ok(bytes)
5945 }
5946
5947 fn encode_thumb_i32_trunc_f32(&self, rd: &Reg, sm: &VfpReg, signed: bool) -> Result<Vec<u8>> {
5949 let mut bytes = Vec::new();
5950
5951 let sm_num = vfp_sreg_to_num(sm)?;
5952 let (vd, d) = encode_sreg(sm_num);
5953 let (vm, m) = encode_sreg(sm_num);
5954 let base = if signed { 0xEEBD0AC0 } else { 0xEEBC0AC0 };
5955 let vcvt = base | (d << 22) | (vd << 12) | (m << 5) | vm;
5956 bytes.extend_from_slice(&vfp_to_thumb_bytes(vcvt));
5957
5958 let vmov = encode_vmov_core_sreg(false, sm, rd)?;
5960 bytes.extend_from_slice(&vfp_to_thumb_bytes(vmov));
5961
5962 Ok(bytes)
5963 }
5964
5965 fn encode_thumb32_add(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5969 let rd_bits = reg_to_bits(rd);
5970 let rn_bits = reg_to_bits(rn);
5971
5972 let i_bit = (imm >> 11) & 1;
5976 let imm3 = (imm >> 8) & 0x7;
5977 let imm8 = imm & 0xFF;
5978
5979 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
5980 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5981
5982 let mut bytes = hw1.to_le_bytes().to_vec();
5983 bytes.extend_from_slice(&hw2.to_le_bytes());
5984 Ok(bytes)
5985 }
5986
5987 fn encode_thumb32_sub(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
5989 let rd_bits = reg_to_bits(rd);
5990 let rn_bits = reg_to_bits(rn);
5991
5992 let i_bit = (imm >> 11) & 1;
5993 let imm3 = (imm >> 8) & 0x7;
5994 let imm8 = imm & 0xFF;
5995
5996 let hw1: u16 = (0xF1A0 | (i_bit << 10) | rn_bits) as u16;
5997 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
5998
5999 let mut bytes = hw1.to_le_bytes().to_vec();
6000 bytes.extend_from_slice(&hw2.to_le_bytes());
6001 Ok(bytes)
6002 }
6003
6004 fn encode_thumb32_adds(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6006 let rd_bits = reg_to_bits(rd);
6007 let rn_bits = reg_to_bits(rn);
6008
6009 let i_bit = (imm >> 11) & 1;
6010 let imm3 = (imm >> 8) & 0x7;
6011 let imm8 = imm & 0xFF;
6012
6013 let hw1: u16 = (0xF110 | (i_bit << 10) | rn_bits) as u16;
6016 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6017
6018 let mut bytes = hw1.to_le_bytes().to_vec();
6019 bytes.extend_from_slice(&hw2.to_le_bytes());
6020 Ok(bytes)
6021 }
6022
6023 fn encode_thumb32_subs(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6025 let rd_bits = reg_to_bits(rd);
6026 let rn_bits = reg_to_bits(rn);
6027
6028 let i_bit = (imm >> 11) & 1;
6029 let imm3 = (imm >> 8) & 0x7;
6030 let imm8 = imm & 0xFF;
6031
6032 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6035 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6036
6037 let mut bytes = hw1.to_le_bytes().to_vec();
6038 bytes.extend_from_slice(&hw2.to_le_bytes());
6039 Ok(bytes)
6040 }
6041
6042 fn encode_thumb32_movw(&self, rd: &Reg, imm: u32) -> Result<Vec<u8>> {
6051 let rd_bits = reg_to_bits(rd);
6052 reg_bits_checked(rd_bits)?;
6053 let imm16 = imm & 0xFFFF;
6054
6055 let imm4 = (imm16 >> 12) & 0xF;
6058 let i_bit = (imm16 >> 11) & 1;
6059 let imm3 = (imm16 >> 8) & 0x7;
6060 let imm8 = imm16 & 0xFF;
6061
6062 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6063 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6064
6065 let mut bytes = hw1.to_le_bytes().to_vec();
6066 bytes.extend_from_slice(&hw2.to_le_bytes());
6067 encoding_contracts::verify_thumb32(&bytes);
6068 Ok(bytes)
6069 }
6070
6071 fn encode_thumb32_shift(
6079 &self,
6080 rd: &Reg,
6081 rm: &Reg,
6082 shift: u32,
6083 shift_type: u8,
6084 ) -> Result<Vec<u8>> {
6085 let rd_bits = reg_to_bits(rd);
6086 let rm_bits = reg_to_bits(rm);
6087 reg_bits_checked(rd_bits)?;
6088 reg_bits_checked(rm_bits)?;
6089 let imm5 = shift & 0x1F;
6090 let imm2 = imm5 & 0x3;
6091 let imm3 = (imm5 >> 2) & 0x7;
6092
6093 let hw1: u16 = 0xEA4F;
6096 let hw2: u16 =
6097 ((imm3 << 12) | (rd_bits << 8) | (imm2 << 6) | ((shift_type as u32) << 4) | rm_bits)
6098 as u16;
6099
6100 let mut bytes = hw1.to_le_bytes().to_vec();
6101 bytes.extend_from_slice(&hw2.to_le_bytes());
6102 Ok(bytes)
6103 }
6104
6105 fn encode_thumb32_shift_reg(
6109 &self,
6110 rd: &Reg,
6111 rn: &Reg,
6112 rm: &Reg,
6113 shift_type: u8,
6114 ) -> Result<Vec<u8>> {
6115 let rd_bits = reg_to_bits(rd);
6116 let rn_bits = reg_to_bits(rn);
6117 let rm_bits = reg_to_bits(rm);
6118
6119 let hw1: u16 = (0xFA00 | ((shift_type as u32) << 5) | rn_bits) as u16;
6121 let hw2: u16 = (0xF000 | (rd_bits << 8) | rm_bits) as u16;
6123
6124 let mut bytes = hw1.to_le_bytes().to_vec();
6125 bytes.extend_from_slice(&hw2.to_le_bytes());
6126 Ok(bytes)
6127 }
6128
6129 fn encode_thumb32_cmp_imm(&self, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6131 let rn_bits = reg_to_bits(rn);
6132
6133 let i_bit = (imm >> 11) & 1;
6134 let imm3 = (imm >> 8) & 0x7;
6135 let imm8 = imm & 0xFF;
6136
6137 let hw1: u16 = (0xF1B0 | (i_bit << 10) | rn_bits) as u16;
6139 let hw2: u16 = ((imm3 << 12) | 0x0F00 | imm8) as u16;
6140
6141 let mut bytes = hw1.to_le_bytes().to_vec();
6142 bytes.extend_from_slice(&hw2.to_le_bytes());
6143 Ok(bytes)
6144 }
6145
6146 fn encode_thumb32_ldr(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6148 let rd_bits = reg_to_bits(rd);
6149 let base_bits = reg_to_bits(base);
6150
6151 let hw1: u16 = (0xF8D0 | base_bits) as u16;
6153 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6154
6155 let mut bytes = hw1.to_le_bytes().to_vec();
6156 bytes.extend_from_slice(&hw2.to_le_bytes());
6157 Ok(bytes)
6158 }
6159
6160 fn encode_thumb32_str(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6162 let rd_bits = reg_to_bits(rd);
6163 let base_bits = reg_to_bits(base);
6164
6165 let hw1: u16 = (0xF8C0 | base_bits) as u16;
6167 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6168
6169 let mut bytes = hw1.to_le_bytes().to_vec();
6170 bytes.extend_from_slice(&hw2.to_le_bytes());
6171 Ok(bytes)
6172 }
6173
6174 fn encode_thumb32_ldr_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6176 let rd_bits = reg_to_bits(rd);
6177 let base_bits = reg_to_bits(base);
6178 let rm_bits = reg_to_bits(offset_reg);
6179
6180 let hw1: u16 = (0xF850 | base_bits) as u16;
6184 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6185
6186 let mut bytes = hw1.to_le_bytes().to_vec();
6187 bytes.extend_from_slice(&hw2.to_le_bytes());
6188 Ok(bytes)
6189 }
6190
6191 fn encode_thumb32_str_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6193 let rd_bits = reg_to_bits(rd);
6194 let base_bits = reg_to_bits(base);
6195 let rm_bits = reg_to_bits(offset_reg);
6196
6197 let hw1: u16 = (0xF840 | base_bits) as u16;
6201 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6202
6203 let mut bytes = hw1.to_le_bytes().to_vec();
6204 bytes.extend_from_slice(&hw2.to_le_bytes());
6205 Ok(bytes)
6206 }
6207
6208 fn encode_thumb32_ldrb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6212 let rd_bits = reg_to_bits(rd);
6213 let base_bits = reg_to_bits(base);
6214 let hw1: u16 = (0xF890 | base_bits) as u16;
6216 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6217 let mut bytes = hw1.to_le_bytes().to_vec();
6218 bytes.extend_from_slice(&hw2.to_le_bytes());
6219 Ok(bytes)
6220 }
6221
6222 fn encode_thumb32_ldrb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6224 let rd_bits = reg_to_bits(rd);
6225 let base_bits = reg_to_bits(base);
6226 let rm_bits = reg_to_bits(offset_reg);
6227 let hw1: u16 = (0xF810 | base_bits) as u16;
6229 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6230 let mut bytes = hw1.to_le_bytes().to_vec();
6231 bytes.extend_from_slice(&hw2.to_le_bytes());
6232 Ok(bytes)
6233 }
6234
6235 fn encode_thumb32_ldrsb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6237 let rd_bits = reg_to_bits(rd);
6238 let base_bits = reg_to_bits(base);
6239 let hw1: u16 = (0xF990 | base_bits) as u16;
6241 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6242 let mut bytes = hw1.to_le_bytes().to_vec();
6243 bytes.extend_from_slice(&hw2.to_le_bytes());
6244 Ok(bytes)
6245 }
6246
6247 fn encode_thumb32_ldrsb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6249 let rd_bits = reg_to_bits(rd);
6250 let base_bits = reg_to_bits(base);
6251 let rm_bits = reg_to_bits(offset_reg);
6252 let hw1: u16 = (0xF910 | base_bits) as u16;
6254 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6255 let mut bytes = hw1.to_le_bytes().to_vec();
6256 bytes.extend_from_slice(&hw2.to_le_bytes());
6257 Ok(bytes)
6258 }
6259
6260 fn encode_thumb32_ldrh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6262 let rd_bits = reg_to_bits(rd);
6263 let base_bits = reg_to_bits(base);
6264 let hw1: u16 = (0xF8B0 | base_bits) as u16;
6266 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6267 let mut bytes = hw1.to_le_bytes().to_vec();
6268 bytes.extend_from_slice(&hw2.to_le_bytes());
6269 Ok(bytes)
6270 }
6271
6272 fn encode_thumb32_ldrh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6274 let rd_bits = reg_to_bits(rd);
6275 let base_bits = reg_to_bits(base);
6276 let rm_bits = reg_to_bits(offset_reg);
6277 let hw1: u16 = (0xF830 | base_bits) as u16;
6279 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6280 let mut bytes = hw1.to_le_bytes().to_vec();
6281 bytes.extend_from_slice(&hw2.to_le_bytes());
6282 Ok(bytes)
6283 }
6284
6285 fn encode_thumb32_ldrsh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6287 let rd_bits = reg_to_bits(rd);
6288 let base_bits = reg_to_bits(base);
6289 let hw1: u16 = (0xF9B0 | base_bits) as u16;
6291 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6292 let mut bytes = hw1.to_le_bytes().to_vec();
6293 bytes.extend_from_slice(&hw2.to_le_bytes());
6294 Ok(bytes)
6295 }
6296
6297 fn encode_thumb32_ldrsh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6299 let rd_bits = reg_to_bits(rd);
6300 let base_bits = reg_to_bits(base);
6301 let rm_bits = reg_to_bits(offset_reg);
6302 let hw1: u16 = (0xF930 | base_bits) as u16;
6304 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6305 let mut bytes = hw1.to_le_bytes().to_vec();
6306 bytes.extend_from_slice(&hw2.to_le_bytes());
6307 Ok(bytes)
6308 }
6309
6310 fn encode_thumb32_strb_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6312 let rd_bits = reg_to_bits(rd);
6313 let base_bits = reg_to_bits(base);
6314 let hw1: u16 = (0xF880 | base_bits) as u16;
6316 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6317 let mut bytes = hw1.to_le_bytes().to_vec();
6318 bytes.extend_from_slice(&hw2.to_le_bytes());
6319 Ok(bytes)
6320 }
6321
6322 fn encode_thumb32_strb_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6324 let rd_bits = reg_to_bits(rd);
6325 let base_bits = reg_to_bits(base);
6326 let rm_bits = reg_to_bits(offset_reg);
6327 let hw1: u16 = (0xF800 | base_bits) as u16;
6329 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6330 let mut bytes = hw1.to_le_bytes().to_vec();
6331 bytes.extend_from_slice(&hw2.to_le_bytes());
6332 Ok(bytes)
6333 }
6334
6335 fn encode_thumb32_strh_imm(&self, rd: &Reg, base: &Reg, offset: u32) -> Result<Vec<u8>> {
6337 let rd_bits = reg_to_bits(rd);
6338 let base_bits = reg_to_bits(base);
6339 let hw1: u16 = (0xF8A0 | base_bits) as u16;
6341 let hw2: u16 = ((rd_bits << 12) | (offset & 0xFFF)) as u16;
6342 let mut bytes = hw1.to_le_bytes().to_vec();
6343 bytes.extend_from_slice(&hw2.to_le_bytes());
6344 Ok(bytes)
6345 }
6346
6347 fn encode_thumb32_strh_reg(&self, rd: &Reg, base: &Reg, offset_reg: &Reg) -> Result<Vec<u8>> {
6349 let rd_bits = reg_to_bits(rd);
6350 let base_bits = reg_to_bits(base);
6351 let rm_bits = reg_to_bits(offset_reg);
6352 let hw1: u16 = (0xF820 | base_bits) as u16;
6354 let hw2: u16 = ((rd_bits << 12) | rm_bits) as u16;
6355 let mut bytes = hw1.to_le_bytes().to_vec();
6356 bytes.extend_from_slice(&hw2.to_le_bytes());
6357 Ok(bytes)
6358 }
6359
6360 fn encode_thumb32_add_imm(&self, rd: &Reg, rn: &Reg, imm: u32) -> Result<Vec<u8>> {
6362 let rd_bits = reg_to_bits(rd);
6363 let rn_bits = reg_to_bits(rn);
6364
6365 if imm <= 0xFFF {
6371 let i_bit = (imm >> 11) & 1;
6372 let imm3 = (imm >> 8) & 0x7;
6373 let imm8 = imm & 0xFF;
6374
6375 let hw1: u16 = (0xF100 | (i_bit << 10) | rn_bits) as u16;
6376 let hw2: u16 = ((imm3 << 12) | (rd_bits << 8) | imm8) as u16;
6377
6378 let mut bytes = hw1.to_le_bytes().to_vec();
6379 bytes.extend_from_slice(&hw2.to_le_bytes());
6380 Ok(bytes)
6381 } else {
6382 Err(synth_core::Error::synthesis(
6385 "ADD immediate too large for single instruction",
6386 ))
6387 }
6388 }
6389
6390 fn encode_thumb32_movw_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6400 reg_bits_checked(rd)?;
6401 encoding_contracts::verify_imm16(imm16);
6402 let imm16 = imm16 & 0xFFFF;
6405 let imm4 = (imm16 >> 12) & 0xF;
6406 let i_bit = (imm16 >> 11) & 1;
6407 let imm3 = (imm16 >> 8) & 0x7;
6408 let imm8 = imm16 & 0xFF;
6409
6410 let hw1: u16 = (0xF240 | (i_bit << 10) | imm4) as u16;
6411 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6412
6413 let mut bytes = hw1.to_le_bytes().to_vec();
6414 bytes.extend_from_slice(&hw2.to_le_bytes());
6415 encoding_contracts::verify_thumb32(&bytes);
6416 Ok(bytes)
6417 }
6418
6419 fn encode_thumb32_movt_raw(&self, rd: u32, imm16: u32) -> Result<Vec<u8>> {
6427 reg_bits_checked(rd)?;
6428 encoding_contracts::verify_imm16(imm16);
6429 let imm16 = imm16 & 0xFFFF;
6432 let imm4 = (imm16 >> 12) & 0xF;
6433 let i_bit = (imm16 >> 11) & 1;
6434 let imm3 = (imm16 >> 8) & 0x7;
6435 let imm8 = imm16 & 0xFF;
6436
6437 let hw1: u16 = (0xF2C0 | (i_bit << 10) | imm4) as u16;
6438 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6439
6440 let mut bytes = hw1.to_le_bytes().to_vec();
6441 bytes.extend_from_slice(&hw2.to_le_bytes());
6442 encoding_contracts::verify_thumb32(&bytes);
6443 Ok(bytes)
6444 }
6445
6446 fn encode_thumb32_lsr_raw(&self, rd: u32, rm: u32, shift: u32) -> Result<Vec<u8>> {
6448 let imm5 = shift & 0x1F;
6451 let imm2 = imm5 & 0x3;
6452 let imm3 = (imm5 >> 2) & 0x7;
6453
6454 let hw1: u16 = 0xEA4F;
6455 let hw2: u16 = ((imm3 << 12) | (rd << 8) | (imm2 << 6) | (0b01 << 4) | rm) as u16;
6456
6457 let mut bytes = hw1.to_le_bytes().to_vec();
6458 bytes.extend_from_slice(&hw2.to_le_bytes());
6459 Ok(bytes)
6460 }
6461
6462 fn encode_thumb32_and_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6464 let hw1: u16 = (0xEA00 | rn) as u16;
6467 let hw2: u16 = ((rd << 8) | rm) as u16;
6468
6469 let mut bytes = hw1.to_le_bytes().to_vec();
6470 bytes.extend_from_slice(&hw2.to_le_bytes());
6471 Ok(bytes)
6472 }
6473
6474 fn encode_thumb32_and_imm_raw(&self, rd: u32, rn: u32, imm: u32) -> Result<Vec<u8>> {
6476 let i_bit = (imm >> 11) & 1;
6480 let imm3 = (imm >> 8) & 0x7;
6481 let imm8 = imm & 0xFF;
6482
6483 let hw1: u16 = (0xF000 | (i_bit << 10) | rn) as u16;
6484 let hw2: u16 = ((imm3 << 12) | (rd << 8) | imm8) as u16;
6485
6486 let mut bytes = hw1.to_le_bytes().to_vec();
6487 bytes.extend_from_slice(&hw2.to_le_bytes());
6488 Ok(bytes)
6489 }
6490
6491 fn encode_thumb32_sub_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6493 let hw1: u16 = (0xEBA0 | rn) as u16;
6496 let hw2: u16 = ((rd << 8) | rm) as u16;
6497
6498 let mut bytes = hw1.to_le_bytes().to_vec();
6499 bytes.extend_from_slice(&hw2.to_le_bytes());
6500 Ok(bytes)
6501 }
6502
6503 fn encode_thumb32_add_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6505 let hw1: u16 = (0xEB00 | rn) as u16;
6508 let hw2: u16 = ((rd << 8) | rm) as u16;
6509
6510 let mut bytes = hw1.to_le_bytes().to_vec();
6511 bytes.extend_from_slice(&hw2.to_le_bytes());
6512 Ok(bytes)
6513 }
6514
6515 fn encode_thumb32_adds_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6519 let hw1: u16 = (0xEB10 | rn) as u16;
6521 let hw2: u16 = ((rd << 8) | rm) as u16;
6522 let mut bytes = hw1.to_le_bytes().to_vec();
6523 bytes.extend_from_slice(&hw2.to_le_bytes());
6524 Ok(bytes)
6525 }
6526
6527 fn encode_thumb32_subs_reg_raw(&self, rd: u32, rn: u32, rm: u32) -> Result<Vec<u8>> {
6530 let hw1: u16 = (0xEBB0 | rn) as u16;
6532 let hw2: u16 = ((rd << 8) | rm) as u16;
6533 let mut bytes = hw1.to_le_bytes().to_vec();
6534 bytes.extend_from_slice(&hw2.to_le_bytes());
6535 Ok(bytes)
6536 }
6537
6538 pub fn encode_sequence(&self, ops: &[ArmOp]) -> Result<Vec<u8>> {
6540 let mut code = Vec::new();
6541
6542 for op in ops {
6543 let encoded = self.encode(op)?;
6544 code.extend_from_slice(&encoded);
6545 }
6546
6547 Ok(code)
6548 }
6549}
6550
6551fn reg_to_bits(reg: &Reg) -> u32 {
6553 match reg {
6554 Reg::R0 => 0,
6555 Reg::R1 => 1,
6556 Reg::R2 => 2,
6557 Reg::R3 => 3,
6558 Reg::R4 => 4,
6559 Reg::R5 => 5,
6560 Reg::R6 => 6,
6561 Reg::R7 => 7,
6562 Reg::R8 => 8,
6563 Reg::R9 => 9,
6564 Reg::R10 => 10,
6565 Reg::R11 => 11,
6566 Reg::R12 => 12,
6567 Reg::SP => 13,
6568 Reg::LR => 14,
6569 Reg::PC => 15,
6570 }
6571}
6572
6573fn reg_bits_checked(bits: u32) -> Result<()> {
6581 if bits > 14 {
6582 return Err(synth_core::Error::synthesis(format!(
6583 "register bits {bits} (PC/R15) is not a valid operand for this Thumb-2 encoding"
6584 )));
6585 }
6586 Ok(())
6587}
6588
6589fn try_encode_rotated_imm(val: u32) -> Option<(u32, u32)> {
6592 if val == 0 {
6593 return Some((0, 1));
6594 }
6595 for rot in 0..16u32 {
6596 let shift = rot * 2;
6597 let unrotated = val.rotate_left(shift);
6599 if unrotated <= 0xFF {
6600 return Some(((rot << 8) | unrotated, 1));
6602 }
6603 }
6604 None
6605}
6606
6607fn encode_operand2(op2: &Operand2) -> (u32, u32) {
6612 match op2 {
6613 Operand2::Imm(val) => {
6614 let uval = *val as u32;
6615 if let Some(encoded) = try_encode_rotated_imm(uval) {
6617 encoded
6618 } else {
6619 let imm = uval & 0xFF;
6624 (imm, 1)
6625 }
6626 }
6627
6628 Operand2::Reg(reg) => {
6629 let reg_bits = reg_to_bits(reg);
6630 (reg_bits, 0) }
6632
6633 Operand2::RegShift {
6634 rm,
6635 shift: _,
6636 amount,
6637 } => {
6638 let rm_bits = reg_to_bits(rm);
6640 let shift_bits = (*amount & 0x1F) << 7;
6641 (shift_bits | rm_bits, 0)
6642 }
6643 }
6644}
6645
6646fn encode_mem_addr(addr: &MemAddr) -> (u32, u32) {
6648 let base_bits = reg_to_bits(&addr.base);
6649 let offset_bits = (addr.offset as u32) & 0xFFF; (base_bits, offset_bits)
6651}
6652
6653fn vfp_sreg_to_num(reg: &VfpReg) -> Result<u32> {
6655 match reg {
6656 VfpReg::S0 => Ok(0),
6657 VfpReg::S1 => Ok(1),
6658 VfpReg::S2 => Ok(2),
6659 VfpReg::S3 => Ok(3),
6660 VfpReg::S4 => Ok(4),
6661 VfpReg::S5 => Ok(5),
6662 VfpReg::S6 => Ok(6),
6663 VfpReg::S7 => Ok(7),
6664 VfpReg::S8 => Ok(8),
6665 VfpReg::S9 => Ok(9),
6666 VfpReg::S10 => Ok(10),
6667 VfpReg::S11 => Ok(11),
6668 VfpReg::S12 => Ok(12),
6669 VfpReg::S13 => Ok(13),
6670 VfpReg::S14 => Ok(14),
6671 VfpReg::S15 => Ok(15),
6672 VfpReg::S16 => Ok(16),
6673 VfpReg::S17 => Ok(17),
6674 VfpReg::S18 => Ok(18),
6675 VfpReg::S19 => Ok(19),
6676 VfpReg::S20 => Ok(20),
6677 VfpReg::S21 => Ok(21),
6678 VfpReg::S22 => Ok(22),
6679 VfpReg::S23 => Ok(23),
6680 VfpReg::S24 => Ok(24),
6681 VfpReg::S25 => Ok(25),
6682 VfpReg::S26 => Ok(26),
6683 VfpReg::S27 => Ok(27),
6684 VfpReg::S28 => Ok(28),
6685 VfpReg::S29 => Ok(29),
6686 VfpReg::S30 => Ok(30),
6687 VfpReg::S31 => Ok(31),
6688 _ => Err(synth_core::Error::SynthesisError(
6690 "D-register not supported in single-precision VFP encoding".to_string(),
6691 )),
6692 }
6693}
6694
6695fn vfp_dreg_to_num(reg: &VfpReg) -> Result<u32> {
6697 match reg {
6698 VfpReg::D0 => Ok(0),
6699 VfpReg::D1 => Ok(1),
6700 VfpReg::D2 => Ok(2),
6701 VfpReg::D3 => Ok(3),
6702 VfpReg::D4 => Ok(4),
6703 VfpReg::D5 => Ok(5),
6704 VfpReg::D6 => Ok(6),
6705 VfpReg::D7 => Ok(7),
6706 VfpReg::D8 => Ok(8),
6707 VfpReg::D9 => Ok(9),
6708 VfpReg::D10 => Ok(10),
6709 VfpReg::D11 => Ok(11),
6710 VfpReg::D12 => Ok(12),
6711 VfpReg::D13 => Ok(13),
6712 VfpReg::D14 => Ok(14),
6713 VfpReg::D15 => Ok(15),
6714 _ => Err(synth_core::Error::SynthesisError(
6716 "S-register not supported in double-precision VFP encoding".to_string(),
6717 )),
6718 }
6719}
6720
6721fn encode_sreg(s: u32) -> (u32, u32) {
6725 (s >> 1, s & 1)
6726}
6727
6728fn encode_dreg(d: u32) -> (u32, u32) {
6732 (d & 0xF, (d >> 4) & 1)
6733}
6734
6735fn encode_vfp_3reg(base: u32, sd: &VfpReg, sn: &VfpReg, sm: &VfpReg) -> Result<u32> {
6741 let sd_num = vfp_sreg_to_num(sd)?;
6742 let sn_num = vfp_sreg_to_num(sn)?;
6743 let sm_num = vfp_sreg_to_num(sm)?;
6744 let (vd, d) = encode_sreg(sd_num);
6745 let (vn, n) = encode_sreg(sn_num);
6746 let (vm, m) = encode_sreg(sm_num);
6747
6748 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6749}
6750
6751fn encode_vfp_2reg(base: u32, sd: &VfpReg, sm: &VfpReg) -> Result<u32> {
6754 let sd_num = vfp_sreg_to_num(sd)?;
6755 let sm_num = vfp_sreg_to_num(sm)?;
6756 let (vd, d) = encode_sreg(sd_num);
6757 let (vm, m) = encode_sreg(sm_num);
6758
6759 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6760}
6761
6762fn encode_vfp_ldst(base: u32, sd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6766 let sd_num = vfp_sreg_to_num(sd)?;
6767 let (vd, d) = encode_sreg(sd_num);
6768 let rn = reg_to_bits(&addr.base);
6769
6770 let offset = addr.offset;
6771 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6772 let abs_offset = offset.unsigned_abs();
6773 let imm8 = (abs_offset / 4) & 0xFF;
6774
6775 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6776}
6777
6778fn encode_vmov_core_sreg(to_sreg: bool, sreg: &VfpReg, core: &Reg) -> Result<u32> {
6782 let s_num = vfp_sreg_to_num(sreg)?;
6783 let (vn, n) = encode_sreg(s_num);
6784 let rt = reg_to_bits(core);
6785
6786 let base = if to_sreg { 0xEE000A10 } else { 0xEE100A10 };
6787 Ok(base | (vn << 16) | (rt << 12) | (n << 7))
6788}
6789
6790fn encode_vfp_3reg_f64(base: u32, dd: &VfpReg, dn: &VfpReg, dm: &VfpReg) -> Result<u32> {
6794 let dd_num = vfp_dreg_to_num(dd)?;
6795 let dn_num = vfp_dreg_to_num(dn)?;
6796 let dm_num = vfp_dreg_to_num(dm)?;
6797 let (vd, d) = encode_dreg(dd_num);
6798 let (vn, n) = encode_dreg(dn_num);
6799 let (vm, m) = encode_dreg(dm_num);
6800
6801 Ok(base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm)
6802}
6803
6804fn encode_vfp_2reg_f64(base: u32, dd: &VfpReg, dm: &VfpReg) -> Result<u32> {
6806 let dd_num = vfp_dreg_to_num(dd)?;
6807 let dm_num = vfp_dreg_to_num(dm)?;
6808 let (vd, d) = encode_dreg(dd_num);
6809 let (vm, m) = encode_dreg(dm_num);
6810
6811 Ok(base | (d << 22) | (vd << 12) | (m << 5) | vm)
6812}
6813
6814fn encode_vfp_ldst_f64(base: u32, dd: &VfpReg, addr: &MemAddr) -> Result<u32> {
6817 let dd_num = vfp_dreg_to_num(dd)?;
6818 let (vd, d) = encode_dreg(dd_num);
6819 let rn = reg_to_bits(&addr.base);
6820
6821 let offset = addr.offset;
6822 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6823 let abs_offset = offset.unsigned_abs();
6824 let imm8 = (abs_offset / 4) & 0xFF;
6825
6826 Ok(base | (u_bit << 23) | (d << 22) | (rn << 16) | (vd << 12) | imm8)
6827}
6828
6829fn encode_vmov_core_dreg(
6833 to_dreg: bool,
6834 dreg: &VfpReg,
6835 core_lo: &Reg,
6836 core_hi: &Reg,
6837) -> Result<u32> {
6838 let d_num = vfp_dreg_to_num(dreg)?;
6839 let (vm, m) = encode_dreg(d_num);
6840 let rt = reg_to_bits(core_lo);
6841 let rt2 = reg_to_bits(core_hi);
6842
6843 let base = if to_dreg { 0xEC400B10 } else { 0xEC500B10 };
6844 Ok(base | (rt2 << 16) | (rt << 12) | (m << 5) | vm)
6845}
6846
6847fn vfp_to_thumb_bytes(instr: u32) -> Vec<u8> {
6849 let hw1 = ((instr >> 16) & 0xFFFF) as u16;
6850 let hw2 = (instr & 0xFFFF) as u16;
6851 let mut bytes = hw1.to_le_bytes().to_vec();
6852 bytes.extend_from_slice(&hw2.to_le_bytes());
6853 bytes
6854}
6855
6856fn qreg_to_num(reg: &QReg) -> u32 {
6862 match reg {
6863 QReg::Q0 => 0,
6864 QReg::Q1 => 1,
6865 QReg::Q2 => 2,
6866 QReg::Q3 => 3,
6867 QReg::Q4 => 4,
6868 QReg::Q5 => 5,
6869 QReg::Q6 => 6,
6870 QReg::Q7 => 7,
6871 }
6872}
6873
6874fn mve_size_bits(size: &MveSize) -> u32 {
6876 match size {
6877 MveSize::S8 => 0b00,
6878 MveSize::S16 => 0b01,
6879 MveSize::S32 => 0b10,
6880 }
6881}
6882
6883fn encode_mve_3reg(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6887 let d = qreg_to_num(qd) * 2;
6888 let n = qreg_to_num(qn) * 2;
6889 let m = qreg_to_num(qm) * 2;
6890
6891 let vd = d & 0xF;
6896 let d_bit = (d >> 4) & 1;
6897 let vn = n & 0xF;
6898 let n_bit = (n >> 4) & 1;
6899 let vm = m & 0xF;
6900 let m_bit = (m >> 4) & 1;
6901
6902 base | (d_bit << 22) | (vn << 16) | (vd << 12) | (n_bit << 7) | (m_bit << 5) | vm
6903}
6904
6905fn encode_mve_3reg_bitwise(base: u32, qd: &QReg, qn: &QReg, qm: &QReg) -> u32 {
6907 encode_mve_3reg(base, qd, qn, qm)
6908}
6909
6910fn encode_mve_vldrw(qd: &QReg, addr: &MemAddr) -> u32 {
6913 let qd_enc = qreg_to_num(qd) * 2;
6914 let rn = reg_to_bits(&addr.base);
6915 let offset = addr.offset;
6916 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6917 let abs_offset = offset.unsigned_abs();
6918 let imm7 = (abs_offset / 4) & 0x7F; 0xED100E80
6922 | (u_bit << 23)
6923 | ((qd_enc >> 4) << 22)
6924 | (rn << 16)
6925 | ((qd_enc & 0xF) << 12)
6926 | (imm7 & 0x7F)
6927}
6928
6929fn encode_mve_vstrw(qd: &QReg, addr: &MemAddr) -> u32 {
6931 let qd_enc = qreg_to_num(qd) * 2;
6932 let rn = reg_to_bits(&addr.base);
6933 let offset = addr.offset;
6934 let u_bit = if offset >= 0 { 1u32 } else { 0u32 };
6935 let abs_offset = offset.unsigned_abs();
6936 let imm7 = (abs_offset / 4) & 0x7F;
6937
6938 0xED000E80
6939 | (u_bit << 23)
6940 | ((qd_enc >> 4) << 22)
6941 | (rn << 16)
6942 | ((qd_enc & 0xF) << 12)
6943 | (imm7 & 0x7F)
6944}
6945
6946impl ArmEncoder {
6947 fn encode_thumb_mve_const(&self, qd: &QReg, bytes: &[u8; 16]) -> Result<Vec<u8>> {
6949 let mut result = Vec::new();
6950 let qd_num = qreg_to_num(qd);
6951
6952 for i in 0..4 {
6954 let word = u32::from_le_bytes([
6955 bytes[i * 4],
6956 bytes[i * 4 + 1],
6957 bytes[i * 4 + 2],
6958 bytes[i * 4 + 3],
6959 ]);
6960 let lo16 = word & 0xFFFF;
6961 let hi16 = (word >> 16) & 0xFFFF;
6962
6963 result.extend_from_slice(&self.encode_thumb32_movw_raw(12, lo16)?);
6965 if hi16 != 0 {
6967 result.extend_from_slice(&self.encode_thumb32_movt_raw(12, hi16)?);
6968 }
6969
6970 let s_num = qd_num * 4 + i as u32;
6972 let (vn, n) = encode_sreg(s_num);
6973 let vmov: u32 = 0xEE000A10 | (vn << 16) | (12 << 12) | (n << 7);
6974 result.extend_from_slice(&vfp_to_thumb_bytes(vmov));
6975 }
6976
6977 Ok(result)
6978 }
6979
6980 fn encode_thumb_mve_lane_wise_f32_binop(
6982 &self,
6983 qd: &QReg,
6984 qn: &QReg,
6985 qm: &QReg,
6986 vfp_base: u32,
6987 ) -> Result<Vec<u8>> {
6988 let mut result = Vec::new();
6989 let qd_num = qreg_to_num(qd);
6990 let qn_num = qreg_to_num(qn);
6991 let qm_num = qreg_to_num(qm);
6992
6993 for i in 0..4u32 {
6995 let sd = qd_num * 4 + i;
6996 let sn = qn_num * 4 + i;
6997 let sm = qm_num * 4 + i;
6998
6999 let (vd, d) = encode_sreg(sd);
7000 let (vn, n) = encode_sreg(sn);
7001 let (vm, m) = encode_sreg(sm);
7002
7003 let instr = vfp_base | (d << 22) | (vn << 16) | (vd << 12) | (n << 7) | (m << 5) | vm;
7004 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7005 }
7006
7007 Ok(result)
7008 }
7009
7010 fn encode_thumb_mve_lane_wise_f32_sqrt(&self, qd: &QReg, qm: &QReg) -> Result<Vec<u8>> {
7012 let mut result = Vec::new();
7013 let qd_num = qreg_to_num(qd);
7014 let qm_num = qreg_to_num(qm);
7015
7016 for i in 0..4u32 {
7018 let sd = qd_num * 4 + i;
7019 let sm = qm_num * 4 + i;
7020
7021 let (vd, d) = encode_sreg(sd);
7022 let (vm, m) = encode_sreg(sm);
7023
7024 let instr: u32 = 0xEEB10AC0 | (d << 22) | (vd << 12) | (m << 5) | vm;
7025 result.extend_from_slice(&vfp_to_thumb_bytes(instr));
7026 }
7027
7028 Ok(result)
7029 }
7030}
7031
7032#[cfg(test)]
7033mod tests {
7034 use super::*;
7035
7036 #[test]
7037 fn test_encoder_creation() {
7038 let encoder_arm = ArmEncoder::new_arm32();
7039 assert!(!encoder_arm.thumb_mode);
7040
7041 let encoder_thumb = ArmEncoder::new_thumb2();
7042 assert!(encoder_thumb.thumb_mode);
7043 }
7044
7045 #[test]
7052 fn test_encode_setcond_high_reg_uses_mov_w_204() {
7053 use synth_synthesis::{ArmOp, Condition, Reg};
7054 let enc = ArmEncoder::new_thumb2();
7055 let hi = enc
7057 .encode(&ArmOp::SetCond {
7058 rd: Reg::R12,
7059 cond: Condition::NE,
7060 })
7061 .unwrap();
7062 assert_eq!(hi.len(), 10, "ITE(2) + MOV.W(4) + MOV.W(4): {hi:02x?}");
7063 assert_eq!(&hi[2..4], &[0x4F, 0xF0], "then = MOV.W: {hi:02x?}");
7065 assert_eq!(&hi[6..8], &[0x4F, 0xF0], "else = MOV.W: {hi:02x?}");
7066 assert_eq!(hi[4] & 0x0F, 0x01, "then imm = #1");
7067 assert_eq!(hi[8] & 0x0F, 0x00, "else imm = #0");
7068 let lo = enc
7070 .encode(&ArmOp::SetCond {
7071 rd: Reg::R0,
7072 cond: Condition::NE,
7073 })
7074 .unwrap();
7075 assert_eq!(lo.len(), 6, "ITE(2) + MOVS(2) + MOVS(2): {lo:02x?}");
7076 assert_eq!(lo[2..4], [0x01, 0x20], "then = MOVS R0,#1");
7077 assert_eq!(lo[4..6], [0x00, 0x20], "else = MOVS R0,#0");
7078 }
7079
7080 #[test]
7084 fn test_encode_umull_209b() {
7085 use synth_synthesis::{ArmOp, Reg};
7086 let op = ArmOp::Umull {
7087 rdlo: Reg::R4,
7088 rdhi: Reg::R5,
7089 rn: Reg::R0,
7090 rm: Reg::R3,
7091 };
7092 let t = ArmEncoder::new_thumb2().encode(&op).unwrap();
7094 assert_eq!(
7095 t,
7096 vec![0xA0, 0xFB, 0x03, 0x45],
7097 "umull r4,r5,r0,r3 (T2): {t:02x?}"
7098 );
7099 let a = ArmEncoder::new_arm32().encode(&op).unwrap();
7101 assert_eq!(
7102 a,
7103 0xE085_4390u32.to_le_bytes().to_vec(),
7104 "umull (A32): {a:02x?}"
7105 );
7106 }
7107
7108 #[test]
7115 fn test_encode_arm32_indexed_load_keeps_index_206() {
7116 use synth_synthesis::{ArmOp, MemAddr, Reg};
7117 let enc = ArmEncoder::new_arm32();
7118 let bytes = enc
7120 .encode(&ArmOp::Ldr {
7121 rd: Reg::R0,
7122 addr: MemAddr::reg_imm(Reg::R11, Reg::R1, 8),
7123 })
7124 .unwrap();
7125 assert_eq!(
7126 bytes.len(),
7127 8,
7128 "expected ADD ip + LDR (2 words): {bytes:02x?}"
7129 );
7130 let add = u32::from_le_bytes(bytes[0..4].try_into().unwrap());
7131 let ldr = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
7132 assert_eq!(add, 0xE08B_C001, "ADD ip,r11,r1: {add:#010x}");
7134 assert_eq!(ldr, 0xE59C_0008, "LDR r0,[ip,#8]: {ldr:#010x}");
7136 assert_ne!(ldr, 0xE59B_0008, "index must not be dropped");
7138 }
7139
7140 #[test]
7147 fn test_encode_thumb_add_high_reg_uses_add_w_178_180() {
7148 let encoder = ArmEncoder::new_thumb2();
7149
7150 let code = encoder
7152 .encode(&ArmOp::Add {
7153 rd: Reg::R12,
7154 rn: Reg::R12,
7155 op2: Operand2::Reg(Reg::R0),
7156 })
7157 .unwrap();
7158 assert_eq!(
7160 code,
7161 vec![0x0C, 0xEB, 0x00, 0x0C],
7162 "high-reg Thumb ADD must be 32-bit ADD.W (EB0C 0C00), not corrupt 16-bit; got {code:02X?}"
7163 );
7164 assert_ne!(code, vec![0x6C, 0x18], "regressed to corrupt 16-bit ADDS");
7166
7167 let lo = encoder
7169 .encode(&ArmOp::Add {
7170 rd: Reg::R1,
7171 rn: Reg::R2,
7172 op2: Operand2::Reg(Reg::R3),
7173 })
7174 .unwrap();
7175 assert_eq!(
7176 lo.len(),
7177 2,
7178 "low-reg ADD should remain 16-bit, got {lo:02X?}"
7179 );
7180 }
7181
7182 #[test]
7185 fn test_encode_thumb_adds_subs_high_reg_use_32bit_178_180() {
7186 let encoder = ArmEncoder::new_thumb2();
7187
7188 let adds = encoder
7190 .encode(&ArmOp::Adds {
7191 rd: Reg::R10,
7192 rn: Reg::R10,
7193 op2: Operand2::Reg(Reg::R8),
7194 })
7195 .unwrap();
7196 assert_eq!(
7197 adds,
7198 vec![0x1A, 0xEB, 0x08, 0x0A],
7199 "high-reg ADDS must be 32-bit ADDS.W (EB1A 0A08); got {adds:02X?}"
7200 );
7201
7202 let subs = encoder
7204 .encode(&ArmOp::Subs {
7205 rd: Reg::R10,
7206 rn: Reg::R10,
7207 op2: Operand2::Reg(Reg::R8),
7208 })
7209 .unwrap();
7210 assert_eq!(
7211 subs,
7212 vec![0xBA, 0xEB, 0x08, 0x0A],
7213 "high-reg SUBS must be 32-bit SUBS.W (EBBA 0A08); got {subs:02X?}"
7214 );
7215 }
7216
7217 #[test]
7220 fn test_encode_thumb_cmn_high_reg_uses_cmn_w_184() {
7221 let encoder = ArmEncoder::new_thumb2();
7222
7223 let cmn = encoder
7225 .encode(&ArmOp::Cmn {
7226 rn: Reg::R10,
7227 op2: Operand2::Reg(Reg::R8),
7228 })
7229 .unwrap();
7230 assert_eq!(
7231 cmn,
7232 vec![0x1A, 0xEB, 0x08, 0x0F],
7233 "high-reg CMN must be 32-bit CMN.W (EB1A 0F08); got {cmn:02X?}"
7234 );
7235
7236 let lo = encoder
7238 .encode(&ArmOp::Cmn {
7239 rn: Reg::R1,
7240 op2: Operand2::Reg(Reg::R2),
7241 })
7242 .unwrap();
7243 assert_eq!(
7244 lo.len(),
7245 2,
7246 "low-reg CMN should remain 16-bit, got {lo:02X?}"
7247 );
7248 assert_eq!(lo, vec![0xD1, 0x42], "low-reg CMN bytes wrong: {lo:02X?}");
7249 }
7250
7251 #[test]
7255 fn test_encode_pc_operand_returns_err_not_panic_185() {
7256 let encoder = ArmEncoder::new_thumb2();
7257 for op in [
7258 ArmOp::Sdiv {
7259 rd: Reg::PC,
7260 rn: Reg::R0,
7261 rm: Reg::R1,
7262 },
7263 ArmOp::Udiv {
7264 rd: Reg::R0,
7265 rn: Reg::PC,
7266 rm: Reg::R1,
7267 },
7268 ArmOp::Sdiv {
7269 rd: Reg::R0,
7270 rn: Reg::R1,
7271 rm: Reg::PC,
7272 },
7273 ] {
7274 let r = encoder.encode(&op);
7275 assert!(
7276 r.is_err(),
7277 "encode({op:?}) must return Err for a PC operand, got {r:?}"
7278 );
7279 }
7280 assert!(
7282 encoder
7283 .encode(&ArmOp::Sdiv {
7284 rd: Reg::R0,
7285 rn: Reg::R1,
7286 rm: Reg::R2
7287 })
7288 .is_ok()
7289 );
7290 }
7291
7292 #[test]
7293 fn test_encode_nop_arm32() {
7294 let encoder = ArmEncoder::new_arm32();
7295 let code = encoder.encode(&ArmOp::Nop).unwrap();
7296
7297 assert_eq!(code.len(), 4); assert_eq!(code, vec![0x00, 0x00, 0xA0, 0xE1]); }
7300
7301 #[test]
7302 fn test_encode_nop_thumb() {
7303 let encoder = ArmEncoder::new_thumb2();
7304 let code = encoder.encode(&ArmOp::Nop).unwrap();
7305
7306 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]); }
7309
7310 #[test]
7311 fn test_encode_mov_immediate_arm32() {
7312 let encoder = ArmEncoder::new_arm32();
7313 let op = ArmOp::Mov {
7314 rd: Reg::R0,
7315 op2: Operand2::Imm(42),
7316 };
7317
7318 let code = encoder.encode(&op).unwrap();
7319 assert_eq!(code.len(), 4);
7320
7321 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7323 assert_eq!(instr & 0x0E000000, 0x02000000); }
7325
7326 #[test]
7327 fn test_encode_add_registers_arm32() {
7328 let encoder = ArmEncoder::new_arm32();
7329 let op = ArmOp::Add {
7330 rd: Reg::R0,
7331 rn: Reg::R1,
7332 op2: Operand2::Reg(Reg::R2),
7333 };
7334
7335 let code = encoder.encode(&op).unwrap();
7336 assert_eq!(code.len(), 4);
7337
7338 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7339 assert_eq!(instr & 0x0FE00000, 0x00800000);
7341 }
7342
7343 #[test]
7344 fn test_encode_ldr_arm32() {
7345 let encoder = ArmEncoder::new_arm32();
7346 let op = ArmOp::Ldr {
7347 rd: Reg::R0,
7348 addr: MemAddr::imm(Reg::R1, 4),
7349 };
7350
7351 let code = encoder.encode(&op).unwrap();
7352 assert_eq!(code.len(), 4);
7353
7354 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7355 assert_eq!(instr & 0x00100000, 0x00100000);
7357 }
7358
7359 #[test]
7360 fn test_encode_str_arm32() {
7361 let encoder = ArmEncoder::new_arm32();
7362 let op = ArmOp::Str {
7363 rd: Reg::R0,
7364 addr: MemAddr::imm(Reg::SP, 0),
7365 };
7366
7367 let code = encoder.encode(&op).unwrap();
7368 assert_eq!(code.len(), 4);
7369 }
7370
7371 #[test]
7372 fn test_encode_branch_arm32() {
7373 let encoder = ArmEncoder::new_arm32();
7374 let op = ArmOp::Bl {
7375 label: "main".to_string(),
7376 };
7377
7378 let code = encoder.encode(&op).unwrap();
7379 assert_eq!(code.len(), 4);
7380
7381 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7382 assert_eq!(instr & 0x0F000000, 0x0B000000);
7384 }
7385
7386 #[test]
7396 fn test_encode_thumb_bl_placeholder_addend_167_174() {
7397 let encoder = ArmEncoder::new_thumb2();
7398 let op = ArmOp::Bl {
7399 label: "callee".to_string(),
7400 };
7401
7402 let code = encoder.encode(&op).unwrap();
7403 assert_eq!(code.len(), 4, "Thumb-2 BL is 32-bit");
7404
7405 let hw1 = u16::from_le_bytes([code[0], code[1]]);
7406 let hw2 = u16::from_le_bytes([code[2], code[3]]);
7407 assert_eq!(hw1, 0xF7FF, "BL first halfword (matches gas `bl <extern>`)");
7408 assert_eq!(
7409 hw2, 0xFFFE,
7410 "BL second halfword must be 0xFFFE (-4 addend → nets to S), not 0xF800 (→ S+4, #174) or 0xD000 (#167)"
7411 );
7412 assert_ne!(hw2, 0xF800, "0xF800 (addend 0) lands at S+4 (#174)");
7413 assert_ne!(hw2, 0xD000, "0xD000 bakes in a ~+0x600000 addend (#167)");
7414 }
7415
7416 #[test]
7417 fn test_encode_sequence() {
7418 let encoder = ArmEncoder::new_arm32();
7419 let ops = vec![
7420 ArmOp::Mov {
7421 rd: Reg::R0,
7422 op2: Operand2::Imm(42),
7423 },
7424 ArmOp::Mov {
7425 rd: Reg::R1,
7426 op2: Operand2::Imm(10),
7427 },
7428 ArmOp::Add {
7429 rd: Reg::R2,
7430 rn: Reg::R0,
7431 op2: Operand2::Reg(Reg::R1),
7432 },
7433 ];
7434
7435 let code = encoder.encode_sequence(&ops).unwrap();
7436 assert_eq!(code.len(), 12); }
7438
7439 #[test]
7440 fn test_reg_to_bits() {
7441 assert_eq!(reg_to_bits(&Reg::R0), 0);
7442 assert_eq!(reg_to_bits(&Reg::R7), 7);
7443 assert_eq!(reg_to_bits(&Reg::SP), 13);
7444 assert_eq!(reg_to_bits(&Reg::LR), 14);
7445 assert_eq!(reg_to_bits(&Reg::PC), 15);
7446 }
7447
7448 #[test]
7449 fn test_encode_bitwise_operations() {
7450 let encoder = ArmEncoder::new_arm32();
7451
7452 let and_op = ArmOp::And {
7453 rd: Reg::R0,
7454 rn: Reg::R1,
7455 op2: Operand2::Reg(Reg::R2),
7456 };
7457 let and_code = encoder.encode(&and_op).unwrap();
7458 assert_eq!(and_code.len(), 4);
7459
7460 let orr_op = ArmOp::Orr {
7461 rd: Reg::R0,
7462 rn: Reg::R1,
7463 op2: Operand2::Reg(Reg::R2),
7464 };
7465 let orr_code = encoder.encode(&orr_op).unwrap();
7466 assert_eq!(orr_code.len(), 4);
7467
7468 let eor_op = ArmOp::Eor {
7469 rd: Reg::R0,
7470 rn: Reg::R1,
7471 op2: Operand2::Reg(Reg::R2),
7472 };
7473 let eor_code = encoder.encode(&eor_op).unwrap();
7474 assert_eq!(eor_code.len(), 4);
7475 }
7476
7477 #[test]
7480 fn test_encode_sdiv_thumb2() {
7481 let encoder = ArmEncoder::new_thumb2();
7482 let op = ArmOp::Sdiv {
7483 rd: Reg::R0,
7484 rn: Reg::R1,
7485 rm: Reg::R2,
7486 };
7487
7488 let code = encoder.encode(&op).unwrap();
7489 assert_eq!(code.len(), 4); assert_eq!(code[0], 0x91);
7496 assert_eq!(code[1], 0xFB);
7497 assert_eq!(code[2], 0xF2);
7498 assert_eq!(code[3], 0xF0);
7499 }
7500
7501 #[test]
7502 fn test_encode_udiv_thumb2() {
7503 let encoder = ArmEncoder::new_thumb2();
7504 let op = ArmOp::Udiv {
7505 rd: Reg::R0,
7506 rn: Reg::R1,
7507 rm: Reg::R2,
7508 };
7509
7510 let code = encoder.encode(&op).unwrap();
7511 assert_eq!(code.len(), 4); assert_eq!(code[0], 0xB1);
7516 assert_eq!(code[1], 0xFB);
7517 assert_eq!(code[2], 0xF2);
7518 assert_eq!(code[3], 0xF0);
7519 }
7520
7521 #[test]
7522 fn test_encode_mul_thumb2() {
7523 let encoder = ArmEncoder::new_thumb2();
7524 let op = ArmOp::Mul {
7525 rd: Reg::R0,
7526 rn: Reg::R1,
7527 rm: Reg::R2,
7528 };
7529
7530 let code = encoder.encode(&op).unwrap();
7531 assert_eq!(code.len(), 4); }
7533
7534 #[test]
7535 fn test_encode_and_thumb2() {
7536 let encoder = ArmEncoder::new_thumb2();
7537 let op = ArmOp::And {
7538 rd: Reg::R0,
7539 rn: Reg::R1,
7540 op2: Operand2::Reg(Reg::R2),
7541 };
7542
7543 let code = encoder.encode(&op).unwrap();
7544 assert_eq!(code.len(), 4); }
7546
7547 #[test]
7548 fn test_encode_lsl_thumb2_low_regs() {
7549 let encoder = ArmEncoder::new_thumb2();
7550 let op = ArmOp::Lsl {
7551 rd: Reg::R0,
7552 rn: Reg::R1,
7553 shift: 5,
7554 };
7555
7556 let code = encoder.encode(&op).unwrap();
7557 assert_eq!(code.len(), 2); }
7559
7560 #[test]
7561 fn test_encode_clz_thumb2() {
7562 let encoder = ArmEncoder::new_thumb2();
7563 let op = ArmOp::Clz {
7564 rd: Reg::R0,
7565 rm: Reg::R1,
7566 };
7567
7568 let code = encoder.encode(&op).unwrap();
7569 assert_eq!(code.len(), 4); }
7571
7572 #[test]
7573 fn test_encode_bx_thumb2() {
7574 let encoder = ArmEncoder::new_thumb2();
7575 let op = ArmOp::Bx { rm: Reg::LR };
7576
7577 let code = encoder.encode(&op).unwrap();
7578 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x70, 0x47]);
7582 }
7583
7584 #[test]
7589 fn test_encode_f32_abs_arm32() {
7590 let encoder = ArmEncoder::new_arm32();
7591 let op = ArmOp::F32Abs {
7592 sd: VfpReg::S0,
7593 sm: VfpReg::S2,
7594 };
7595 let code = encoder.encode(&op).unwrap();
7596 assert_eq!(code.len(), 4); }
7598
7599 #[test]
7600 fn test_encode_f32_neg_arm32() {
7601 let encoder = ArmEncoder::new_arm32();
7602 let op = ArmOp::F32Neg {
7603 sd: VfpReg::S0,
7604 sm: VfpReg::S2,
7605 };
7606 let code = encoder.encode(&op).unwrap();
7607 assert_eq!(code.len(), 4);
7608 }
7609
7610 #[test]
7611 fn test_encode_f32_sqrt_arm32() {
7612 let encoder = ArmEncoder::new_arm32();
7613 let op = ArmOp::F32Sqrt {
7614 sd: VfpReg::S0,
7615 sm: VfpReg::S2,
7616 };
7617 let code = encoder.encode(&op).unwrap();
7618 assert_eq!(code.len(), 4);
7619 }
7620
7621 #[test]
7622 fn test_encode_f32_ceil_arm32() {
7623 let encoder = ArmEncoder::new_arm32();
7624 let op = ArmOp::F32Ceil {
7625 sd: VfpReg::S0,
7626 sm: VfpReg::S2,
7627 };
7628 let code = encoder.encode(&op).unwrap();
7629 assert_eq!(code.len(), 36);
7631 }
7632
7633 #[test]
7634 fn test_encode_f32_floor_thumb2() {
7635 let encoder = ArmEncoder::new_thumb2();
7636 let op = ArmOp::F32Floor {
7637 sd: VfpReg::S0,
7638 sm: VfpReg::S2,
7639 };
7640 let code = encoder.encode(&op).unwrap();
7641 assert_eq!(code.len(), 36);
7643 }
7644
7645 #[test]
7646 fn test_encode_f32_min_arm32() {
7647 let encoder = ArmEncoder::new_arm32();
7648 let op = ArmOp::F32Min {
7649 sd: VfpReg::S0,
7650 sn: VfpReg::S2,
7651 sm: VfpReg::S4,
7652 };
7653 let code = encoder.encode(&op).unwrap();
7654 assert_eq!(code.len(), 16); }
7656
7657 #[test]
7658 fn test_encode_f32_max_thumb2() {
7659 let encoder = ArmEncoder::new_thumb2();
7660 let op = ArmOp::F32Max {
7661 sd: VfpReg::S0,
7662 sn: VfpReg::S2,
7663 sm: VfpReg::S4,
7664 };
7665 let code = encoder.encode(&op).unwrap();
7666 assert_eq!(code.len(), 18);
7668 }
7669
7670 #[test]
7671 fn test_encode_f32_copysign_arm32() {
7672 let encoder = ArmEncoder::new_arm32();
7673 let op = ArmOp::F32Copysign {
7674 sd: VfpReg::S0,
7675 sn: VfpReg::S2,
7676 sm: VfpReg::S4,
7677 };
7678 let code = encoder.encode(&op).unwrap();
7679 assert_eq!(code.len(), 24);
7681 }
7682
7683 #[test]
7688 fn test_encode_f64_add_arm32() {
7689 let encoder = ArmEncoder::new_arm32();
7690 let op = ArmOp::F64Add {
7691 dd: VfpReg::D0,
7692 dn: VfpReg::D1,
7693 dm: VfpReg::D2,
7694 };
7695 let code = encoder.encode(&op).unwrap();
7696 assert_eq!(code.len(), 4);
7697 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7699 assert_eq!((instr >> 8) & 0xF, 0xB); }
7701
7702 #[test]
7703 fn test_encode_f64_sub_thumb2() {
7704 let encoder = ArmEncoder::new_thumb2();
7705 let op = ArmOp::F64Sub {
7706 dd: VfpReg::D0,
7707 dn: VfpReg::D1,
7708 dm: VfpReg::D2,
7709 };
7710 let code = encoder.encode(&op).unwrap();
7711 assert_eq!(code.len(), 4); }
7713
7714 #[test]
7715 fn test_encode_f64_mul_arm32() {
7716 let encoder = ArmEncoder::new_arm32();
7717 let op = ArmOp::F64Mul {
7718 dd: VfpReg::D0,
7719 dn: VfpReg::D1,
7720 dm: VfpReg::D2,
7721 };
7722 let code = encoder.encode(&op).unwrap();
7723 assert_eq!(code.len(), 4);
7724 }
7725
7726 #[test]
7727 fn test_encode_f64_div_arm32() {
7728 let encoder = ArmEncoder::new_arm32();
7729 let op = ArmOp::F64Div {
7730 dd: VfpReg::D0,
7731 dn: VfpReg::D1,
7732 dm: VfpReg::D2,
7733 };
7734 let code = encoder.encode(&op).unwrap();
7735 assert_eq!(code.len(), 4);
7736 }
7737
7738 #[test]
7739 fn test_encode_f64_abs_arm32() {
7740 let encoder = ArmEncoder::new_arm32();
7741 let op = ArmOp::F64Abs {
7742 dd: VfpReg::D0,
7743 dm: VfpReg::D2,
7744 };
7745 let code = encoder.encode(&op).unwrap();
7746 assert_eq!(code.len(), 4);
7747 }
7748
7749 #[test]
7750 fn test_encode_f64_neg_arm32() {
7751 let encoder = ArmEncoder::new_arm32();
7752 let op = ArmOp::F64Neg {
7753 dd: VfpReg::D0,
7754 dm: VfpReg::D2,
7755 };
7756 let code = encoder.encode(&op).unwrap();
7757 assert_eq!(code.len(), 4);
7758 }
7759
7760 #[test]
7761 fn test_encode_f64_sqrt_arm32() {
7762 let encoder = ArmEncoder::new_arm32();
7763 let op = ArmOp::F64Sqrt {
7764 dd: VfpReg::D0,
7765 dm: VfpReg::D2,
7766 };
7767 let code = encoder.encode(&op).unwrap();
7768 assert_eq!(code.len(), 4);
7769 }
7770
7771 #[test]
7772 fn test_encode_f64_load_arm32() {
7773 let encoder = ArmEncoder::new_arm32();
7774 let op = ArmOp::F64Load {
7775 dd: VfpReg::D0,
7776 addr: MemAddr::imm(Reg::R0, 8),
7777 };
7778 let code = encoder.encode(&op).unwrap();
7779 assert_eq!(code.len(), 4);
7780 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7781 assert_eq!((instr >> 8) & 0xF, 0xB); assert_eq!(instr & 0xFF, 2); }
7784
7785 #[test]
7786 fn test_encode_f64_store_thumb2() {
7787 let encoder = ArmEncoder::new_thumb2();
7788 let op = ArmOp::F64Store {
7789 dd: VfpReg::D0,
7790 addr: MemAddr::imm(Reg::SP, 0),
7791 };
7792 let code = encoder.encode(&op).unwrap();
7793 assert_eq!(code.len(), 4);
7794 }
7795
7796 #[test]
7797 fn test_encode_f64_compare_arm32() {
7798 let encoder = ArmEncoder::new_arm32();
7799 let op = ArmOp::F64Eq {
7800 rd: Reg::R0,
7801 dn: VfpReg::D0,
7802 dm: VfpReg::D1,
7803 };
7804 let code = encoder.encode(&op).unwrap();
7805 assert_eq!(code.len(), 16); }
7807
7808 #[test]
7809 fn test_encode_f64_compare_thumb2() {
7810 let encoder = ArmEncoder::new_thumb2();
7811 let op = ArmOp::F64Lt {
7812 rd: Reg::R0,
7813 dn: VfpReg::D0,
7814 dm: VfpReg::D1,
7815 };
7816 let code = encoder.encode(&op).unwrap();
7817 assert_eq!(code.len(), 14);
7819 }
7820
7821 #[test]
7822 fn test_encode_f64_const_arm32() {
7823 let encoder = ArmEncoder::new_arm32();
7824 let op = ArmOp::F64Const {
7825 dd: VfpReg::D0,
7826 value: 3.125,
7827 };
7828 let code = encoder.encode(&op).unwrap();
7829 assert_eq!(code.len(), 20);
7831 }
7832
7833 #[test]
7834 fn test_encode_f64_const_thumb2() {
7835 let encoder = ArmEncoder::new_thumb2();
7836 let op = ArmOp::F64Const {
7837 dd: VfpReg::D0,
7838 value: 2.5,
7839 };
7840 let code = encoder.encode(&op).unwrap();
7841 assert_eq!(code.len(), 20);
7843 }
7844
7845 #[test]
7846 fn test_encode_f64_convert_i32s_arm32() {
7847 let encoder = ArmEncoder::new_arm32();
7848 let op = ArmOp::F64ConvertI32S {
7849 dd: VfpReg::D0,
7850 rm: Reg::R0,
7851 };
7852 let code = encoder.encode(&op).unwrap();
7853 assert_eq!(code.len(), 8);
7855 }
7856
7857 #[test]
7858 fn test_encode_f64_promote_f32_arm32() {
7859 let encoder = ArmEncoder::new_arm32();
7860 let op = ArmOp::F64PromoteF32 {
7861 dd: VfpReg::D0,
7862 sm: VfpReg::S0,
7863 };
7864 let code = encoder.encode(&op).unwrap();
7865 assert_eq!(code.len(), 4); }
7867
7868 #[test]
7869 fn test_encode_f64_promote_f32_thumb2() {
7870 let encoder = ArmEncoder::new_thumb2();
7871 let op = ArmOp::F64PromoteF32 {
7872 dd: VfpReg::D0,
7873 sm: VfpReg::S0,
7874 };
7875 let code = encoder.encode(&op).unwrap();
7876 assert_eq!(code.len(), 4);
7877 }
7878
7879 #[test]
7880 fn test_encode_i32_trunc_f64s_arm32() {
7881 let encoder = ArmEncoder::new_arm32();
7882 let op = ArmOp::I32TruncF64S {
7883 rd: Reg::R0,
7884 dm: VfpReg::D0,
7885 };
7886 let code = encoder.encode(&op).unwrap();
7887 assert_eq!(code.len(), 8);
7889 }
7890
7891 #[test]
7892 fn test_encode_f64_reinterpret_i64_arm32() {
7893 let encoder = ArmEncoder::new_arm32();
7894 let op = ArmOp::F64ReinterpretI64 {
7895 dd: VfpReg::D0,
7896 rmlo: Reg::R0,
7897 rmhi: Reg::R1,
7898 };
7899 let code = encoder.encode(&op).unwrap();
7900 assert_eq!(code.len(), 4); }
7902
7903 #[test]
7904 fn test_encode_i64_reinterpret_f64_thumb2() {
7905 let encoder = ArmEncoder::new_thumb2();
7906 let op = ArmOp::I64ReinterpretF64 {
7907 rdlo: Reg::R0,
7908 rdhi: Reg::R1,
7909 dm: VfpReg::D0,
7910 };
7911 let code = encoder.encode(&op).unwrap();
7912 assert_eq!(code.len(), 4);
7913 }
7914
7915 #[test]
7916 fn test_encode_f64_trunc_thumb2() {
7917 let encoder = ArmEncoder::new_thumb2();
7918 let op = ArmOp::F64Trunc {
7919 dd: VfpReg::D0,
7920 dm: VfpReg::D1,
7921 };
7922 let code = encoder.encode(&op).unwrap();
7923 assert_eq!(code.len(), 8);
7925 }
7926
7927 #[test]
7928 fn test_encode_f64_min_arm32() {
7929 let encoder = ArmEncoder::new_arm32();
7930 let op = ArmOp::F64Min {
7931 dd: VfpReg::D0,
7932 dn: VfpReg::D1,
7933 dm: VfpReg::D2,
7934 };
7935 let code = encoder.encode(&op).unwrap();
7936 assert_eq!(code.len(), 16);
7938 }
7939
7940 #[test]
7941 fn test_f64_cp11_encoding() {
7942 let encoder = ArmEncoder::new_arm32();
7944
7945 let code = encoder
7947 .encode(&ArmOp::F64Add {
7948 dd: VfpReg::D0,
7949 dn: VfpReg::D0,
7950 dm: VfpReg::D0,
7951 })
7952 .unwrap();
7953 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7954 assert_eq!((instr >> 8) & 0xF, 0xB, "F64 should use cp11");
7955
7956 let code = encoder
7958 .encode(&ArmOp::F32Add {
7959 sd: VfpReg::S0,
7960 sn: VfpReg::S0,
7961 sm: VfpReg::S0,
7962 })
7963 .unwrap();
7964 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7965 assert_eq!((instr >> 8) & 0xF, 0xA, "F32 should use cp10");
7966 }
7967
7968 #[test]
7969 fn test_dreg_encoding_higher_registers() {
7970 let encoder = ArmEncoder::new_arm32();
7971
7972 let op = ArmOp::F64Add {
7974 dd: VfpReg::D15,
7975 dn: VfpReg::D14,
7976 dm: VfpReg::D13,
7977 };
7978 let code = encoder.encode(&op).unwrap();
7979 assert_eq!(code.len(), 4);
7980
7981 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
7983 assert_eq!((instr >> 8) & 0xF, 0xB); }
7985
7986 #[test]
7991 fn test_encode_label_emits_no_bytes() {
7992 let encoder = ArmEncoder::new_thumb2();
7993 let op = ArmOp::Label {
7994 name: ".Lblock_end_0".to_string(),
7995 };
7996 let code = encoder.encode(&op).unwrap();
7997 assert!(code.is_empty(), "Label should emit zero bytes");
7998
7999 let encoder32 = ArmEncoder::new_arm32();
8000 let code32 = encoder32.encode(&op).unwrap();
8001 assert!(
8002 code32.is_empty(),
8003 "Label should emit zero bytes in ARM32 too"
8004 );
8005 }
8006
8007 #[test]
8008 fn test_encode_bcc_eq_thumb2() {
8009 use synth_synthesis::Condition;
8010 let encoder = ArmEncoder::new_thumb2();
8011 let op = ArmOp::Bcc {
8012 cond: Condition::EQ,
8013 label: "target".to_string(),
8014 };
8015 let code = encoder.encode(&op).unwrap();
8016 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xD0]);
8020 }
8021
8022 #[test]
8023 fn test_encode_bcc_ne_thumb2() {
8024 use synth_synthesis::Condition;
8025 let encoder = ArmEncoder::new_thumb2();
8026 let op = ArmOp::Bcc {
8027 cond: Condition::NE,
8028 label: "target".to_string(),
8029 };
8030 let code = encoder.encode(&op).unwrap();
8031 assert_eq!(code.len(), 2);
8032
8033 assert_eq!(code, vec![0x00, 0xD1]);
8035 }
8036
8037 #[test]
8038 fn test_encode_bcc_arm32() {
8039 use synth_synthesis::Condition;
8040 let encoder = ArmEncoder::new_arm32();
8041 let op = ArmOp::Bcc {
8042 cond: Condition::EQ,
8043 label: "target".to_string(),
8044 };
8045 let code = encoder.encode(&op).unwrap();
8046 assert_eq!(code.len(), 4); let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8049 assert_eq!(instr & 0xF0000000, 0x00000000); assert_eq!(instr & 0x0F000000, 0x0A000000); }
8053
8054 #[test]
8055 fn test_encode_udf_thumb2() {
8056 let encoder = ArmEncoder::new_thumb2();
8057 let op = ArmOp::Udf { imm: 0 };
8058 let code = encoder.encode(&op).unwrap();
8059 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xDE]);
8063 }
8064
8065 #[test]
8066 fn test_encode_nop_thumb2() {
8067 let encoder = ArmEncoder::new_thumb2();
8068 let op = ArmOp::Nop;
8069 let code = encoder.encode(&op).unwrap();
8070 assert_eq!(code.len(), 2); assert_eq!(code, vec![0x00, 0xBF]);
8074 }
8075
8076 #[test]
8081 fn test_encode_i64_add_thumb2() {
8082 let encoder = ArmEncoder::new_thumb2();
8083 let op = ArmOp::I64Add {
8084 rdlo: Reg::R0,
8085 rdhi: Reg::R1,
8086 rnlo: Reg::R0,
8087 rnhi: Reg::R1,
8088 rmlo: Reg::R2,
8089 rmhi: Reg::R3,
8090 };
8091 let code = encoder.encode(&op).unwrap();
8092 assert_eq!(code.len(), 6, "I64Add should be 6 bytes (ADDS + ADC.W)");
8094 }
8095
8096 #[test]
8097 fn test_encode_i64_sub_thumb2() {
8098 let encoder = ArmEncoder::new_thumb2();
8099 let op = ArmOp::I64Sub {
8100 rdlo: Reg::R0,
8101 rdhi: Reg::R1,
8102 rnlo: Reg::R0,
8103 rnhi: Reg::R1,
8104 rmlo: Reg::R2,
8105 rmhi: Reg::R3,
8106 };
8107 let code = encoder.encode(&op).unwrap();
8108 assert_eq!(code.len(), 6, "I64Sub should be 6 bytes (SUBS + SBC.W)");
8110 }
8111
8112 #[test]
8113 fn test_encode_i64_and_thumb2() {
8114 let encoder = ArmEncoder::new_thumb2();
8115 let op = ArmOp::I64And {
8116 rdlo: Reg::R0,
8117 rdhi: Reg::R1,
8118 rnlo: Reg::R0,
8119 rnhi: Reg::R1,
8120 rmlo: Reg::R2,
8121 rmhi: Reg::R3,
8122 };
8123 let code = encoder.encode(&op).unwrap();
8124 assert!(code.len() >= 4, "I64And should emit at least 4 bytes");
8126 }
8127
8128 #[test]
8129 fn test_encode_i64_or_thumb2() {
8130 let encoder = ArmEncoder::new_thumb2();
8131 let op = ArmOp::I64Or {
8132 rdlo: Reg::R0,
8133 rdhi: Reg::R1,
8134 rnlo: Reg::R0,
8135 rnhi: Reg::R1,
8136 rmlo: Reg::R2,
8137 rmhi: Reg::R3,
8138 };
8139 let code = encoder.encode(&op).unwrap();
8140 assert!(code.len() >= 4, "I64Or should emit at least 4 bytes");
8141 }
8142
8143 #[test]
8144 fn test_encode_i64_xor_thumb2() {
8145 let encoder = ArmEncoder::new_thumb2();
8146 let op = ArmOp::I64Xor {
8147 rdlo: Reg::R0,
8148 rdhi: Reg::R1,
8149 rnlo: Reg::R0,
8150 rnhi: Reg::R1,
8151 rmlo: Reg::R2,
8152 rmhi: Reg::R3,
8153 };
8154 let code = encoder.encode(&op).unwrap();
8155 assert!(code.len() >= 4, "I64Xor should emit at least 4 bytes");
8156 }
8157
8158 #[test]
8159 fn test_encode_i64_const_small_thumb2() {
8160 let encoder = ArmEncoder::new_thumb2();
8161 let op = ArmOp::I64Const {
8163 rdlo: Reg::R0,
8164 rdhi: Reg::R1,
8165 value: 42,
8166 };
8167 let code = encoder.encode(&op).unwrap();
8168 assert!(code.len() >= 8, "I64Const should emit at least 8 bytes");
8170 }
8171
8172 #[test]
8173 fn test_encode_i64_const_large_thumb2() {
8174 let encoder = ArmEncoder::new_thumb2();
8175 let op = ArmOp::I64Const {
8177 rdlo: Reg::R0,
8178 rdhi: Reg::R1,
8179 value: 0x1234_5678_9ABC_DEF0_u64 as i64,
8180 };
8181 let code = encoder.encode(&op).unwrap();
8182 assert_eq!(
8184 code.len(),
8185 16,
8186 "I64Const with large value should be 16 bytes"
8187 );
8188 }
8189
8190 #[test]
8191 fn test_encode_i64_extend_i32_s_thumb2() {
8192 let encoder = ArmEncoder::new_thumb2();
8193 let op = ArmOp::I64ExtendI32S {
8194 rdlo: Reg::R0,
8195 rdhi: Reg::R1,
8196 rn: Reg::R0,
8197 };
8198 let code = encoder.encode(&op).unwrap();
8199 assert_eq!(
8201 code.len(),
8202 4,
8203 "I64ExtendI32S (same reg) should be 4 bytes (ASR only)"
8204 );
8205 }
8206
8207 #[test]
8208 fn test_encode_i64_extend_i32_s_diff_reg_thumb2() {
8209 let encoder = ArmEncoder::new_thumb2();
8210 let op = ArmOp::I64ExtendI32S {
8211 rdlo: Reg::R0,
8212 rdhi: Reg::R1,
8213 rn: Reg::R2,
8214 };
8215 let code = encoder.encode(&op).unwrap();
8216 assert!(
8218 code.len() >= 6,
8219 "I64ExtendI32S (diff reg) should be at least 6 bytes"
8220 );
8221 }
8222
8223 #[test]
8224 fn test_encode_i64_extend_i32_u_thumb2() {
8225 let encoder = ArmEncoder::new_thumb2();
8226 let op = ArmOp::I64ExtendI32U {
8227 rdlo: Reg::R0,
8228 rdhi: Reg::R1,
8229 rn: Reg::R0,
8230 };
8231 let code = encoder.encode(&op).unwrap();
8232 assert_eq!(
8234 code.len(),
8235 2,
8236 "I64ExtendI32U (same reg) should be 2 bytes (MOV #0 only)"
8237 );
8238 }
8239
8240 #[test]
8241 fn test_encode_i32_wrap_i64_nop_thumb2() {
8242 let encoder = ArmEncoder::new_thumb2();
8243 let op = ArmOp::I32WrapI64 {
8245 rd: Reg::R0,
8246 rnlo: Reg::R0,
8247 };
8248 let code = encoder.encode(&op).unwrap();
8249 assert_eq!(code.len(), 2, "I32WrapI64 same reg should be NOP (2 bytes)");
8250 assert_eq!(code, vec![0x00, 0xBF]); }
8252
8253 #[test]
8254 fn test_encode_i32_wrap_i64_diff_reg_thumb2() {
8255 let encoder = ArmEncoder::new_thumb2();
8256 let op = ArmOp::I32WrapI64 {
8257 rd: Reg::R2,
8258 rnlo: Reg::R0,
8259 };
8260 let code = encoder.encode(&op).unwrap();
8261 assert!(
8263 code.len() >= 2,
8264 "I32WrapI64 diff reg should emit at least 2 bytes"
8265 );
8266 }
8267
8268 #[test]
8269 fn test_encode_i64_eqz_thumb2() {
8270 let encoder = ArmEncoder::new_thumb2();
8271 let op = ArmOp::I64Eqz {
8272 rd: Reg::R0,
8273 rnlo: Reg::R0,
8274 rnhi: Reg::R1,
8275 };
8276 let code = encoder.encode(&op).unwrap();
8277 assert!(
8279 code.len() >= 6,
8280 "I64Eqz should emit at least 6 bytes for ORR+ITE+MOV+MOV"
8281 );
8282 }
8283
8284 #[test]
8285 fn test_encode_i64_eq_thumb2() {
8286 let encoder = ArmEncoder::new_thumb2();
8287 let op = ArmOp::I64Eq {
8288 rd: Reg::R0,
8289 rnlo: Reg::R0,
8290 rnhi: Reg::R1,
8291 rmlo: Reg::R2,
8292 rmhi: Reg::R3,
8293 };
8294 let code = encoder.encode(&op).unwrap();
8295 assert!(code.len() >= 10, "I64Eq should emit at least 10 bytes");
8297 }
8298
8299 #[test]
8300 fn test_encode_i64_ldr_thumb2() {
8301 let encoder = ArmEncoder::new_thumb2();
8302 let op = ArmOp::I64Ldr {
8303 rdlo: Reg::R0,
8304 rdhi: Reg::R1,
8305 addr: MemAddr::imm(Reg::SP, 0),
8306 };
8307 let code = encoder.encode(&op).unwrap();
8308 assert!(code.len() >= 4, "I64Ldr should emit at least 4 bytes");
8310 }
8311
8312 #[test]
8313 fn test_encode_i64_str_thumb2() {
8314 let encoder = ArmEncoder::new_thumb2();
8315 let op = ArmOp::I64Str {
8316 rdlo: Reg::R0,
8317 rdhi: Reg::R1,
8318 addr: MemAddr::imm(Reg::SP, 0),
8319 };
8320 let code = encoder.encode(&op).unwrap();
8321 assert!(code.len() >= 4, "I64Str should emit at least 4 bytes");
8323 }
8324
8325 #[test]
8326 fn test_encode_i64_all_comparisons_thumb2() {
8327 let encoder = ArmEncoder::new_thumb2();
8328
8329 let ops = vec![
8330 ArmOp::I64Ne {
8331 rd: Reg::R0,
8332 rnlo: Reg::R0,
8333 rnhi: Reg::R1,
8334 rmlo: Reg::R2,
8335 rmhi: Reg::R3,
8336 },
8337 ArmOp::I64LtS {
8338 rd: Reg::R0,
8339 rnlo: Reg::R0,
8340 rnhi: Reg::R1,
8341 rmlo: Reg::R2,
8342 rmhi: Reg::R3,
8343 },
8344 ArmOp::I64LtU {
8345 rd: Reg::R0,
8346 rnlo: Reg::R0,
8347 rnhi: Reg::R1,
8348 rmlo: Reg::R2,
8349 rmhi: Reg::R3,
8350 },
8351 ArmOp::I64LeS {
8352 rd: Reg::R0,
8353 rnlo: Reg::R0,
8354 rnhi: Reg::R1,
8355 rmlo: Reg::R2,
8356 rmhi: Reg::R3,
8357 },
8358 ArmOp::I64LeU {
8359 rd: Reg::R0,
8360 rnlo: Reg::R0,
8361 rnhi: Reg::R1,
8362 rmlo: Reg::R2,
8363 rmhi: Reg::R3,
8364 },
8365 ArmOp::I64GtS {
8366 rd: Reg::R0,
8367 rnlo: Reg::R0,
8368 rnhi: Reg::R1,
8369 rmlo: Reg::R2,
8370 rmhi: Reg::R3,
8371 },
8372 ArmOp::I64GtU {
8373 rd: Reg::R0,
8374 rnlo: Reg::R0,
8375 rnhi: Reg::R1,
8376 rmlo: Reg::R2,
8377 rmhi: Reg::R3,
8378 },
8379 ArmOp::I64GeS {
8380 rd: Reg::R0,
8381 rnlo: Reg::R0,
8382 rnhi: Reg::R1,
8383 rmlo: Reg::R2,
8384 rmhi: Reg::R3,
8385 },
8386 ArmOp::I64GeU {
8387 rd: Reg::R0,
8388 rnlo: Reg::R0,
8389 rnhi: Reg::R1,
8390 rmlo: Reg::R2,
8391 rmhi: Reg::R3,
8392 },
8393 ];
8394
8395 for op in &ops {
8396 let code = encoder.encode(op).unwrap();
8397 assert!(
8398 code.len() >= 8,
8399 "i64 comparison {:?} should emit at least 8 bytes, got {}",
8400 op,
8401 code.len()
8402 );
8403 }
8404 }
8405
8406 #[test]
8407 fn test_encode_i64_const_zero_thumb2() {
8408 let encoder = ArmEncoder::new_thumb2();
8409 let op = ArmOp::I64Const {
8410 rdlo: Reg::R0,
8411 rdhi: Reg::R1,
8412 value: 0,
8413 };
8414 let code = encoder.encode(&op).unwrap();
8415 assert_eq!(code.len(), 8, "I64Const(0) should be 8 bytes");
8417 }
8418
8419 #[test]
8420 fn test_encode_i64_const_negative_one_thumb2() {
8421 let encoder = ArmEncoder::new_thumb2();
8422 let op = ArmOp::I64Const {
8423 rdlo: Reg::R0,
8424 rdhi: Reg::R1,
8425 value: -1, };
8427 let code = encoder.encode(&op).unwrap();
8428 assert_eq!(code.len(), 16, "I64Const(-1) should be 16 bytes");
8430 }
8431
8432 #[test]
8437 fn test_encode_ldrb_arm32() {
8438 let encoder = ArmEncoder::new_arm32();
8439 let op = ArmOp::Ldrb {
8440 rd: Reg::R0,
8441 addr: MemAddr::imm(Reg::R1, 4),
8442 };
8443 let code = encoder.encode(&op).unwrap();
8444 assert_eq!(code.len(), 4, "ARM32 LDRB should be 4 bytes");
8445 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8447 assert_eq!(encoded, 0xE5D10004, "Should encode LDRB R0, [R1, #4]");
8448 }
8449
8450 #[test]
8451 fn test_encode_strb_arm32() {
8452 let encoder = ArmEncoder::new_arm32();
8453 let op = ArmOp::Strb {
8454 rd: Reg::R0,
8455 addr: MemAddr::imm(Reg::R1, 0),
8456 };
8457 let code = encoder.encode(&op).unwrap();
8458 assert_eq!(code.len(), 4, "ARM32 STRB should be 4 bytes");
8459 let encoded = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8461 assert_eq!(encoded, 0xE5C10000, "Should encode STRB R0, [R1, #0]");
8462 }
8463
8464 #[test]
8465 fn test_encode_ldrh_arm32() {
8466 let encoder = ArmEncoder::new_arm32();
8467 let op = ArmOp::Ldrh {
8468 rd: Reg::R0,
8469 addr: MemAddr::imm(Reg::R1, 2),
8470 };
8471 let code = encoder.encode(&op).unwrap();
8472 assert_eq!(code.len(), 4, "ARM32 LDRH should be 4 bytes");
8473 }
8474
8475 #[test]
8476 fn test_encode_strh_arm32() {
8477 let encoder = ArmEncoder::new_arm32();
8478 let op = ArmOp::Strh {
8479 rd: Reg::R0,
8480 addr: MemAddr::imm(Reg::R1, 0),
8481 };
8482 let code = encoder.encode(&op).unwrap();
8483 assert_eq!(code.len(), 4, "ARM32 STRH should be 4 bytes");
8484 }
8485
8486 #[test]
8487 fn test_encode_ldrsb_arm32() {
8488 let encoder = ArmEncoder::new_arm32();
8489 let op = ArmOp::Ldrsb {
8490 rd: Reg::R0,
8491 addr: MemAddr::imm(Reg::R1, 0),
8492 };
8493 let code = encoder.encode(&op).unwrap();
8494 assert_eq!(code.len(), 4, "ARM32 LDRSB should be 4 bytes");
8495 }
8496
8497 #[test]
8498 fn test_encode_ldrsh_arm32() {
8499 let encoder = ArmEncoder::new_arm32();
8500 let op = ArmOp::Ldrsh {
8501 rd: Reg::R0,
8502 addr: MemAddr::imm(Reg::R1, 0),
8503 };
8504 let code = encoder.encode(&op).unwrap();
8505 assert_eq!(code.len(), 4, "ARM32 LDRSH should be 4 bytes");
8506 }
8507
8508 #[test]
8509 fn test_encode_ldrb_thumb2_16bit() {
8510 let encoder = ArmEncoder::new_thumb2();
8511 let op = ArmOp::Ldrb {
8512 rd: Reg::R0,
8513 addr: MemAddr::imm(Reg::R1, 4),
8514 };
8515 let code = encoder.encode(&op).unwrap();
8516 assert_eq!(
8518 code.len(),
8519 2,
8520 "Thumb-2 LDRB with small offset should be 16-bit"
8521 );
8522 }
8523
8524 #[test]
8525 fn test_encode_ldrb_thumb2_32bit() {
8526 let encoder = ArmEncoder::new_thumb2();
8527 let op = ArmOp::Ldrb {
8528 rd: Reg::R0,
8529 addr: MemAddr::imm(Reg::R1, 100), };
8531 let code = encoder.encode(&op).unwrap();
8532 assert_eq!(
8533 code.len(),
8534 4,
8535 "Thumb-2 LDRB with large offset should be 32-bit"
8536 );
8537 }
8538
8539 #[test]
8540 fn test_encode_strb_thumb2_16bit() {
8541 let encoder = ArmEncoder::new_thumb2();
8542 let op = ArmOp::Strb {
8543 rd: Reg::R0,
8544 addr: MemAddr::imm(Reg::R1, 10),
8545 };
8546 let code = encoder.encode(&op).unwrap();
8547 assert_eq!(
8548 code.len(),
8549 2,
8550 "Thumb-2 STRB with small offset should be 16-bit"
8551 );
8552 }
8553
8554 #[test]
8555 fn test_encode_ldrh_thumb2_16bit() {
8556 let encoder = ArmEncoder::new_thumb2();
8557 let op = ArmOp::Ldrh {
8558 rd: Reg::R0,
8559 addr: MemAddr::imm(Reg::R1, 4), };
8561 let code = encoder.encode(&op).unwrap();
8562 assert_eq!(
8563 code.len(),
8564 2,
8565 "Thumb-2 LDRH with small aligned offset should be 16-bit"
8566 );
8567 }
8568
8569 #[test]
8570 fn test_encode_strh_thumb2_16bit() {
8571 let encoder = ArmEncoder::new_thumb2();
8572 let op = ArmOp::Strh {
8573 rd: Reg::R0,
8574 addr: MemAddr::imm(Reg::R1, 4),
8575 };
8576 let code = encoder.encode(&op).unwrap();
8577 assert_eq!(
8578 code.len(),
8579 2,
8580 "Thumb-2 STRH with small aligned offset should be 16-bit"
8581 );
8582 }
8583
8584 #[test]
8585 fn test_encode_ldrsb_thumb2() {
8586 let encoder = ArmEncoder::new_thumb2();
8587 let op = ArmOp::Ldrsb {
8588 rd: Reg::R0,
8589 addr: MemAddr::imm(Reg::R1, 0),
8590 };
8591 let code = encoder.encode(&op).unwrap();
8592 assert_eq!(code.len(), 4, "Thumb-2 LDRSB should be 32-bit");
8594 }
8595
8596 #[test]
8597 fn test_encode_ldrsh_thumb2() {
8598 let encoder = ArmEncoder::new_thumb2();
8599 let op = ArmOp::Ldrsh {
8600 rd: Reg::R0,
8601 addr: MemAddr::imm(Reg::R1, 0),
8602 };
8603 let code = encoder.encode(&op).unwrap();
8604 assert_eq!(code.len(), 4, "Thumb-2 LDRSH should be 32-bit");
8605 }
8606
8607 #[test]
8608 fn test_encode_memory_size_thumb2() {
8609 let encoder = ArmEncoder::new_thumb2();
8610 let op = ArmOp::MemorySize { rd: Reg::R0 };
8611 let code = encoder.encode(&op).unwrap();
8612 assert!(!code.is_empty(), "MemorySize should produce code");
8614 }
8615
8616 #[test]
8617 fn test_encode_memory_grow_thumb2() {
8618 let encoder = ArmEncoder::new_thumb2();
8619 let op = ArmOp::MemoryGrow {
8620 rd: Reg::R0,
8621 rn: Reg::R0,
8622 };
8623 let code = encoder.encode(&op).unwrap();
8624 assert_eq!(code.len(), 4, "MemoryGrow (MVN) should be 32-bit Thumb-2");
8625 }
8626
8627 #[test]
8628 fn test_encode_subword_reg_offset_thumb2() {
8629 let encoder = ArmEncoder::new_thumb2();
8630
8631 let op = ArmOp::Ldrb {
8633 rd: Reg::R0,
8634 addr: MemAddr::reg(Reg::R1, Reg::R2),
8635 };
8636 let code = encoder.encode(&op).unwrap();
8637 assert_eq!(
8638 code.len(),
8639 4,
8640 "Thumb-2 LDRB with reg offset should be 32-bit"
8641 );
8642
8643 let op = ArmOp::Strb {
8645 rd: Reg::R0,
8646 addr: MemAddr::reg(Reg::R1, Reg::R2),
8647 };
8648 let code = encoder.encode(&op).unwrap();
8649 assert_eq!(
8650 code.len(),
8651 4,
8652 "Thumb-2 STRB with reg offset should be 32-bit"
8653 );
8654
8655 let op = ArmOp::Ldrh {
8657 rd: Reg::R0,
8658 addr: MemAddr::reg(Reg::R1, Reg::R2),
8659 };
8660 let code = encoder.encode(&op).unwrap();
8661 assert_eq!(
8662 code.len(),
8663 4,
8664 "Thumb-2 LDRH with reg offset should be 32-bit"
8665 );
8666
8667 let op = ArmOp::Strh {
8669 rd: Reg::R0,
8670 addr: MemAddr::reg(Reg::R1, Reg::R2),
8671 };
8672 let code = encoder.encode(&op).unwrap();
8673 assert_eq!(
8674 code.len(),
8675 4,
8676 "Thumb-2 STRH with reg offset should be 32-bit"
8677 );
8678 }
8679
8680 #[test]
8681 fn test_encode_subword_reg_imm_offset_thumb2() {
8682 let encoder = ArmEncoder::new_thumb2();
8683
8684 let op = ArmOp::Ldrb {
8686 rd: Reg::R0,
8687 addr: MemAddr::reg_imm(Reg::R1, Reg::R2, 4),
8688 };
8689 let code = encoder.encode(&op).unwrap();
8690 assert_eq!(
8692 code.len(),
8693 8,
8694 "Thumb-2 LDRB with reg+imm offset should be 8 bytes"
8695 );
8696 }
8697
8698 #[test]
8703 fn test_encode_mve_addi32_thumb2() {
8704 let encoder = ArmEncoder::new_thumb2();
8705 let op = ArmOp::MveAddI {
8706 qd: QReg::Q0,
8707 qn: QReg::Q1,
8708 qm: QReg::Q2,
8709 size: MveSize::S32,
8710 };
8711 let code = encoder.encode(&op).unwrap();
8712 assert_eq!(
8713 code.len(),
8714 4,
8715 "MVE VADD.I32 should be 4 bytes (Thumb-2 32-bit)"
8716 );
8717 }
8718
8719 #[test]
8720 fn test_encode_mve_subi16_thumb2() {
8721 let encoder = ArmEncoder::new_thumb2();
8722 let op = ArmOp::MveSubI {
8723 qd: QReg::Q0,
8724 qn: QReg::Q1,
8725 qm: QReg::Q2,
8726 size: MveSize::S16,
8727 };
8728 let code = encoder.encode(&op).unwrap();
8729 assert_eq!(code.len(), 4, "MVE VSUB.I16 should be 4 bytes");
8730 }
8731
8732 #[test]
8733 fn test_encode_mve_muli8_thumb2() {
8734 let encoder = ArmEncoder::new_thumb2();
8735 let op = ArmOp::MveMulI {
8736 qd: QReg::Q0,
8737 qn: QReg::Q1,
8738 qm: QReg::Q2,
8739 size: MveSize::S8,
8740 };
8741 let code = encoder.encode(&op).unwrap();
8742 assert_eq!(code.len(), 4, "MVE VMUL.I8 should be 4 bytes");
8743 }
8744
8745 #[test]
8746 fn test_encode_mve_bitwise_thumb2() {
8747 let encoder = ArmEncoder::new_thumb2();
8748
8749 let ops = vec![
8750 ArmOp::MveAnd {
8751 qd: QReg::Q0,
8752 qn: QReg::Q1,
8753 qm: QReg::Q2,
8754 },
8755 ArmOp::MveOrr {
8756 qd: QReg::Q0,
8757 qn: QReg::Q1,
8758 qm: QReg::Q2,
8759 },
8760 ArmOp::MveEor {
8761 qd: QReg::Q0,
8762 qn: QReg::Q1,
8763 qm: QReg::Q2,
8764 },
8765 ArmOp::MveBic {
8766 qd: QReg::Q0,
8767 qn: QReg::Q1,
8768 qm: QReg::Q2,
8769 },
8770 ];
8771 for op in ops {
8772 let code = encoder.encode(&op).unwrap();
8773 assert_eq!(code.len(), 4, "MVE bitwise op should be 4 bytes");
8774 }
8775 }
8776
8777 #[test]
8778 fn test_encode_mve_mvn_thumb2() {
8779 let encoder = ArmEncoder::new_thumb2();
8780 let op = ArmOp::MveMvn {
8781 qd: QReg::Q0,
8782 qm: QReg::Q1,
8783 };
8784 let code = encoder.encode(&op).unwrap();
8785 assert_eq!(code.len(), 4, "MVE VMVN should be 4 bytes");
8786 }
8787
8788 #[test]
8789 fn test_encode_mve_load_store_thumb2() {
8790 let encoder = ArmEncoder::new_thumb2();
8791
8792 let load = ArmOp::MveLoad {
8793 qd: QReg::Q0,
8794 addr: MemAddr::imm(Reg::R0, 16),
8795 };
8796 let code = encoder.encode(&load).unwrap();
8797 assert_eq!(code.len(), 4, "MVE VLDRW.32 should be 4 bytes");
8798
8799 let store = ArmOp::MveStore {
8800 qd: QReg::Q1,
8801 addr: MemAddr::imm(Reg::R1, 0),
8802 };
8803 let code = encoder.encode(&store).unwrap();
8804 assert_eq!(code.len(), 4, "MVE VSTRW.32 should be 4 bytes");
8805 }
8806
8807 #[test]
8808 fn test_encode_mve_const_thumb2() {
8809 let encoder = ArmEncoder::new_thumb2();
8810 let op = ArmOp::MveConst {
8811 qd: QReg::Q0,
8812 bytes: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
8813 };
8814 let code = encoder.encode(&op).unwrap();
8815 assert!(
8818 code.len() >= 24,
8819 "MVE const should produce multiple instructions"
8820 );
8821 }
8822
8823 #[test]
8824 fn test_encode_mve_dup_thumb2() {
8825 let encoder = ArmEncoder::new_thumb2();
8826 let op = ArmOp::MveDup {
8827 qd: QReg::Q0,
8828 rn: Reg::R0,
8829 size: MveSize::S32,
8830 };
8831 let code = encoder.encode(&op).unwrap();
8832 assert_eq!(code.len(), 4, "MVE VDUP.32 should be 4 bytes");
8833 }
8834
8835 #[test]
8836 fn test_encode_mve_extract_lane_thumb2() {
8837 let encoder = ArmEncoder::new_thumb2();
8838 let op = ArmOp::MveExtractLane {
8839 rd: Reg::R0,
8840 qn: QReg::Q1,
8841 lane: 2,
8842 size: MveSize::S32,
8843 };
8844 let code = encoder.encode(&op).unwrap();
8845 assert_eq!(code.len(), 4, "MVE extract lane should be 4 bytes");
8846 }
8847
8848 #[test]
8849 fn test_encode_mve_insert_lane_thumb2() {
8850 let encoder = ArmEncoder::new_thumb2();
8851 let op = ArmOp::MveInsertLane {
8852 qd: QReg::Q0,
8853 rn: Reg::R1,
8854 lane: 3,
8855 size: MveSize::S32,
8856 };
8857 let code = encoder.encode(&op).unwrap();
8858 assert_eq!(code.len(), 4, "MVE insert lane should be 4 bytes");
8859 }
8860
8861 #[test]
8862 fn test_encode_mve_addf32_thumb2() {
8863 let encoder = ArmEncoder::new_thumb2();
8864 let op = ArmOp::MveAddF32 {
8865 qd: QReg::Q0,
8866 qn: QReg::Q1,
8867 qm: QReg::Q2,
8868 };
8869 let code = encoder.encode(&op).unwrap();
8870 assert_eq!(code.len(), 4, "MVE VADD.F32 should be 4 bytes");
8871 }
8872
8873 #[test]
8874 fn test_encode_mve_divf32_thumb2() {
8875 let encoder = ArmEncoder::new_thumb2();
8876 let op = ArmOp::MveDivF32 {
8877 qd: QReg::Q0,
8878 qn: QReg::Q1,
8879 qm: QReg::Q2,
8880 };
8881 let code = encoder.encode(&op).unwrap();
8882 assert_eq!(
8884 code.len(),
8885 16,
8886 "MVE VDIV.F32 (lane-wise) should be 16 bytes"
8887 );
8888 }
8889
8890 #[test]
8891 fn test_encode_mve_sqrtf32_thumb2() {
8892 let encoder = ArmEncoder::new_thumb2();
8893 let op = ArmOp::MveSqrtF32 {
8894 qd: QReg::Q0,
8895 qm: QReg::Q1,
8896 };
8897 let code = encoder.encode(&op).unwrap();
8898 assert_eq!(
8900 code.len(),
8901 16,
8902 "MVE VSQRT.F32 (lane-wise) should be 16 bytes"
8903 );
8904 }
8905
8906 #[test]
8907 fn test_encode_mve_negf32_thumb2() {
8908 let encoder = ArmEncoder::new_thumb2();
8909 let op = ArmOp::MveNegF32 {
8910 qd: QReg::Q0,
8911 qm: QReg::Q1,
8912 };
8913 let code = encoder.encode(&op).unwrap();
8914 assert_eq!(code.len(), 4, "MVE VNEG.F32 should be 4 bytes");
8915 }
8916
8917 #[test]
8918 fn test_encode_mve_absf32_thumb2() {
8919 let encoder = ArmEncoder::new_thumb2();
8920 let op = ArmOp::MveAbsF32 {
8921 qd: QReg::Q0,
8922 qm: QReg::Q1,
8923 };
8924 let code = encoder.encode(&op).unwrap();
8925 assert_eq!(code.len(), 4, "MVE VABS.F32 should be 4 bytes");
8926 }
8927
8928 #[test]
8929 fn test_encode_mve_different_qregs() {
8930 let encoder = ArmEncoder::new_thumb2();
8931
8932 let op1 = ArmOp::MveAddI {
8934 qd: QReg::Q0,
8935 qn: QReg::Q0,
8936 qm: QReg::Q0,
8937 size: MveSize::S32,
8938 };
8939 let op2 = ArmOp::MveAddI {
8940 qd: QReg::Q3,
8941 qn: QReg::Q5,
8942 qm: QReg::Q7,
8943 size: MveSize::S32,
8944 };
8945 let code1 = encoder.encode(&op1).unwrap();
8946 let code2 = encoder.encode(&op2).unwrap();
8947 assert_ne!(
8948 code1, code2,
8949 "Different Q-registers should produce different encodings"
8950 );
8951 }
8952
8953 #[test]
8954 fn test_encode_mve_arm32_nop() {
8955 let encoder = ArmEncoder::new_arm32();
8957 let op = ArmOp::MveAddI {
8958 qd: QReg::Q0,
8959 qn: QReg::Q1,
8960 qm: QReg::Q2,
8961 size: MveSize::S32,
8962 };
8963 let code = encoder.encode(&op).unwrap();
8964 assert_eq!(code.len(), 4, "ARM32 MVE should be 4 bytes (NOP)");
8965 let instr = u32::from_le_bytes([code[0], code[1], code[2], code[3]]);
8967 assert_eq!(instr, 0xE1A00000, "ARM32 MVE should encode as NOP");
8968 }
8969}