1pub use crate::{
2 arm64_decl::{ARM64Register, ArgumentRegisterAllocator, GPR, NEON},
3 location::{Multiplier, Reg},
4 machine::{Label, Offset},
5};
6use crate::{
7 codegen_error, common_decl::Size, location::Location as AbstractLocation,
8 machine_arm64::ARM64_RETURN_VALUE_REGISTERS, output_reporter::ChunkedOutputReporter,
9};
10pub use dynasmrt::aarch64::{encode_logical_immediate_32bit, encode_logical_immediate_64bit};
11use dynasmrt::{
12 AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, VecAssembler,
13 aarch64::Aarch64Relocation,
14};
15use wasmer_compiler::types::{
16 function::FunctionBody,
17 section::{CustomSection, CustomSectionProtection, SectionBody},
18};
19use wasmer_types::{
20 CompilationProgressCallback, CompileError, FunctionIndex, FunctionType, Type, VMOffsets,
21 target::CallingConvention, vmctx_offset,
22};
23
24type Assembler = VecAssembler<Aarch64Relocation>;
25
26macro_rules! dynasm {
31 ($a:expr ; $($tt:tt)*) => {
32 dynasm::dynasm!(
33 $a
34 ; .arch aarch64
35 ; $($tt)*
36 )
37 };
38}
39
40pub type Location = AbstractLocation<GPR, NEON>;
41
42#[derive(Copy, Clone, Debug, Eq, PartialEq)]
43#[allow(dead_code)]
44#[repr(u8)]
45pub enum Condition {
46 Eq = 0,
49 Ne = 1,
51 Cs = 2,
53 Cc = 3,
55 Mi = 4,
57 Pl = 5,
59 Vs = 6,
61 Vc = 7,
63 Hi = 8,
65 Ls = 9,
67 Ge = 10,
69 Lt = 11,
71 Gt = 12,
73 Le = 13,
75 Al = 14,
77}
78
79#[derive(Copy, Clone, Debug, Eq, PartialEq)]
80#[allow(dead_code, clippy::upper_case_acronyms)]
81pub enum NeonOrMemory {
82 NEON(NEON),
83 Memory(GPR, i32),
84}
85
86#[derive(Copy, Clone, Debug)]
87#[allow(dead_code, clippy::upper_case_acronyms)]
88pub enum GPROrMemory {
89 GPR(GPR),
90 Memory(GPR, i32),
91}
92
93#[allow(unused)]
94pub trait EmitterARM64 {
95 fn get_label(&mut self) -> Label;
96 fn get_offset(&self) -> Offset;
97 fn get_jmp_instr_size(&self) -> u8;
98
99 fn finalize_function(&mut self);
100
101 fn emit_str(&mut self, sz: Size, reg: Location, addr: Location) -> Result<(), CompileError>;
102 fn emit_ldr(&mut self, sz: Size, reg: Location, addr: Location) -> Result<(), CompileError>;
103 fn emit_stur(
104 &mut self,
105 sz: Size,
106 reg: Location,
107 addr: GPR,
108 offset: i32,
109 ) -> Result<(), CompileError>;
110 fn emit_ldur(
111 &mut self,
112 sz: Size,
113 reg: Location,
114 addr: GPR,
115 offset: i32,
116 ) -> Result<(), CompileError>;
117 fn emit_strdb(
118 &mut self,
119 sz: Size,
120 reg: Location,
121 addr: GPR,
122 offset: u32,
123 ) -> Result<(), CompileError>;
124 fn emit_stria(
125 &mut self,
126 sz: Size,
127 reg: Location,
128 addr: GPR,
129 offset: u32,
130 ) -> Result<(), CompileError>;
131 fn emit_ldria(
132 &mut self,
133 sz: Size,
134 reg: Location,
135 addr: GPR,
136 offset: u32,
137 ) -> Result<(), CompileError>;
138 fn emit_stpdb(
139 &mut self,
140 sz: Size,
141 reg1: Location,
142 reg2: Location,
143 addr: GPR,
144 offset: u32,
145 ) -> Result<(), CompileError>;
146 fn emit_ldpia(
147 &mut self,
148 sz: Size,
149 reg1: Location,
150 reg2: Location,
151 addr: GPR,
152 offset: u32,
153 ) -> Result<(), CompileError>;
154
155 fn emit_ldrb(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
156 fn emit_ldrh(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
157 fn emit_ldrsb(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
158 fn emit_ldrsh(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
159 fn emit_ldrsw(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
160 fn emit_strb(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
161 fn emit_strh(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
162
163 fn emit_ldaxr(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
164 fn emit_ldaxrb(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
165 fn emit_ldaxrh(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError>;
166 fn emit_stlxr(
167 &mut self,
168 sz: Size,
169 status: Location,
170 reg: Location,
171 dst: Location,
172 ) -> Result<(), CompileError>;
173 fn emit_stlxrb(
174 &mut self,
175 sz: Size,
176 status: Location,
177 reg: Location,
178 dst: Location,
179 ) -> Result<(), CompileError>;
180 fn emit_stlxrh(
181 &mut self,
182 sz: Size,
183 status: Location,
184 reg: Location,
185 dst: Location,
186 ) -> Result<(), CompileError>;
187
188 fn emit_mov(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
189
190 fn emit_movn(&mut self, sz: Size, reg: Location, val: u32) -> Result<(), CompileError>;
191 fn emit_movz(&mut self, reg: Location, val: u32) -> Result<(), CompileError>;
192 fn emit_movk(&mut self, reg: Location, val: u32, shift: u32) -> Result<(), CompileError>;
193
194 fn emit_mov_imm(&mut self, dst: Location, val: u64) -> Result<(), CompileError>;
195
196 fn emit_add(
197 &mut self,
198 sz: Size,
199 src1: Location,
200 src2: Location,
201 dst: Location,
202 ) -> Result<(), CompileError>;
203 fn emit_sub(
204 &mut self,
205 sz: Size,
206 src1: Location,
207 src2: Location,
208 dst: Location,
209 ) -> Result<(), CompileError>;
210 fn emit_mul(
211 &mut self,
212 sz: Size,
213 src1: Location,
214 src2: Location,
215 dst: Location,
216 ) -> Result<(), CompileError>;
217 fn emit_adds(
218 &mut self,
219 sz: Size,
220 src1: Location,
221 src2: Location,
222 dst: Location,
223 ) -> Result<(), CompileError>;
224 fn emit_subs(
225 &mut self,
226 sz: Size,
227 src1: Location,
228 src2: Location,
229 dst: Location,
230 ) -> Result<(), CompileError>;
231
232 fn emit_add_lsl(
233 &mut self,
234 sz: Size,
235 src1: Location,
236 src2: Location,
237 lsl: u32,
238 dst: Location,
239 ) -> Result<(), CompileError>;
240
241 fn emit_cmp(&mut self, sz: Size, left: Location, right: Location) -> Result<(), CompileError>;
242 fn emit_tst(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
243
244 fn emit_lsl(
245 &mut self,
246 sz: Size,
247 src1: Location,
248 src2: Location,
249 dst: Location,
250 ) -> Result<(), CompileError>;
251 fn emit_lsr(
252 &mut self,
253 sz: Size,
254 src1: Location,
255 src2: Location,
256 dst: Location,
257 ) -> Result<(), CompileError>;
258 fn emit_asr(
259 &mut self,
260 sz: Size,
261 src1: Location,
262 src2: Location,
263 dst: Location,
264 ) -> Result<(), CompileError>;
265 fn emit_ror(
266 &mut self,
267 sz: Size,
268 src1: Location,
269 src2: Location,
270 dst: Location,
271 ) -> Result<(), CompileError>;
272
273 fn emit_or(
274 &mut self,
275 sz: Size,
276 src1: Location,
277 src2: Location,
278 dst: Location,
279 ) -> Result<(), CompileError>;
280 fn emit_and(
281 &mut self,
282 sz: Size,
283 src1: Location,
284 src2: Location,
285 dst: Location,
286 ) -> Result<(), CompileError>;
287 fn emit_eor(
288 &mut self,
289 sz: Size,
290 src1: Location,
291 src2: Location,
292 dst: Location,
293 ) -> Result<(), CompileError>;
294
295 fn emit_bfc(
296 &mut self,
297 se: Size,
298 lsb: u32,
299 width: u32,
300 dst: Location,
301 ) -> Result<(), CompileError>;
302 fn emit_bfi(
303 &mut self,
304 se: Size,
305 src: Location,
306 lsb: u32,
307 width: u32,
308 dst: Location,
309 ) -> Result<(), CompileError>;
310
311 fn emit_udiv(
312 &mut self,
313 sz: Size,
314 src1: Location,
315 src2: Location,
316 dst: Location,
317 ) -> Result<(), CompileError>;
318 fn emit_sdiv(
319 &mut self,
320 sz: Size,
321 src1: Location,
322 src2: Location,
323 dst: Location,
324 ) -> Result<(), CompileError>;
325 fn emit_msub(
327 &mut self,
328 sz: Size,
329 a: Location,
330 b: Location,
331 c: Location,
332 dst: Location,
333 ) -> Result<(), CompileError>;
334
335 fn emit_sxtb(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
336 fn emit_sxth(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
337 fn emit_sxtw(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
338 fn emit_uxtb(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
339 fn emit_uxth(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
340
341 fn emit_cset(&mut self, sz: Size, dst: Location, cond: Condition) -> Result<(), CompileError>;
342 fn emit_csetm(&mut self, sz: Size, dst: Location, cond: Condition) -> Result<(), CompileError>;
343 fn emit_cinc(
344 &mut self,
345 sz: Size,
346 src: Location,
347 dst: Location,
348 cond: Condition,
349 ) -> Result<(), CompileError>;
350 fn emit_clz(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
351 fn emit_rbit(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
352
353 fn emit_label(&mut self, label: Label) -> Result<(), CompileError>;
354 fn emit_load_label(&mut self, reg: GPR, label: Label) -> Result<(), CompileError>;
355 fn emit_b_label(&mut self, label: Label) -> Result<(), CompileError>;
356 fn emit_cbz_label(&mut self, sz: Size, reg: Location, label: Label)
357 -> Result<(), CompileError>;
358 fn emit_cbnz_label(
359 &mut self,
360 sz: Size,
361 reg: Location,
362 label: Label,
363 ) -> Result<(), CompileError>;
364 fn emit_cbz_label_far(
365 &mut self,
366 sz: Size,
367 reg: Location,
368 label: Label,
369 ) -> Result<(), CompileError>;
370 fn emit_tbz_label(
371 &mut self,
372 sz: Size,
373 reg: Location,
374 n: u32,
375 label: Label,
376 ) -> Result<(), CompileError>;
377 fn emit_tbnz_label(
378 &mut self,
379 sz: Size,
380 reg: Location,
381 n: u32,
382 label: Label,
383 ) -> Result<(), CompileError>;
384 fn emit_bcond_label(&mut self, condition: Condition, label: Label) -> Result<(), CompileError>;
385 fn emit_bcond_label_far(
386 &mut self,
387 condition: Condition,
388 label: Label,
389 ) -> Result<(), CompileError>;
390 fn emit_b_register(&mut self, reg: GPR) -> Result<(), CompileError>;
391 fn emit_call_label(&mut self, label: Label) -> Result<(), CompileError>;
392 fn emit_call_register(&mut self, reg: GPR) -> Result<(), CompileError>;
393 fn emit_ret(&mut self) -> Result<(), CompileError>;
394
395 fn emit_udf(&mut self, payload: u16) -> Result<(), CompileError>;
396 fn emit_dmb(&mut self) -> Result<(), CompileError>;
397 fn emit_brk(&mut self) -> Result<(), CompileError>;
398
399 fn emit_fcmp(&mut self, sz: Size, src1: Location, src2: Location) -> Result<(), CompileError>;
400 fn emit_fneg(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
401 fn emit_fsqrt(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
402
403 fn emit_fadd(
404 &mut self,
405 sz: Size,
406 src1: Location,
407 src2: Location,
408 dst: Location,
409 ) -> Result<(), CompileError>;
410 fn emit_fsub(
411 &mut self,
412 sz: Size,
413 src1: Location,
414 src2: Location,
415 dst: Location,
416 ) -> Result<(), CompileError>;
417 fn emit_fmul(
418 &mut self,
419 sz: Size,
420 src1: Location,
421 src2: Location,
422 dst: Location,
423 ) -> Result<(), CompileError>;
424 fn emit_fdiv(
425 &mut self,
426 sz: Size,
427 src1: Location,
428 src2: Location,
429 dst: Location,
430 ) -> Result<(), CompileError>;
431
432 fn emit_fmin(
433 &mut self,
434 sz: Size,
435 src1: Location,
436 src2: Location,
437 dst: Location,
438 ) -> Result<(), CompileError>;
439 fn emit_fmax(
440 &mut self,
441 sz: Size,
442 src1: Location,
443 src2: Location,
444 dst: Location,
445 ) -> Result<(), CompileError>;
446
447 fn emit_frintz(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
448 fn emit_frintn(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
449 fn emit_frintm(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
450 fn emit_frintp(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
451
452 fn emit_scvtf(
453 &mut self,
454 sz_in: Size,
455 src: Location,
456 sz_out: Size,
457 dst: Location,
458 ) -> Result<(), CompileError>;
459 fn emit_ucvtf(
460 &mut self,
461 sz_in: Size,
462 src: Location,
463 sz_out: Size,
464 dst: Location,
465 ) -> Result<(), CompileError>;
466 fn emit_fcvt(&mut self, sz_in: Size, src: Location, dst: Location) -> Result<(), CompileError>;
467 fn emit_fcvtzs(
468 &mut self,
469 sz_in: Size,
470 src: Location,
471 sz_out: Size,
472 dst: Location,
473 ) -> Result<(), CompileError>;
474 fn emit_fcvtzu(
475 &mut self,
476 sz_in: Size,
477 src: Location,
478 sz_out: Size,
479 dst: Location,
480 ) -> Result<(), CompileError>;
481
482 fn emit_fmov(
483 &mut self,
484 src_size: Size,
485 src: Location,
486 dst_size: Size,
487 dst: Location,
488 ) -> Result<(), CompileError>;
489 fn emit_cnt(&mut self, src: NEON, dst: NEON) -> Result<(), CompileError>;
490 fn emit_addv(&mut self, src: NEON, dst: NEON) -> Result<(), CompileError>;
491 fn emit_read_fpcr(&mut self, reg: GPR) -> Result<(), CompileError>;
492 fn emit_write_fpcr(&mut self, reg: GPR) -> Result<(), CompileError>;
493 fn emit_read_fpsr(&mut self, reg: GPR) -> Result<(), CompileError>;
494 fn emit_write_fpsr(&mut self, reg: GPR) -> Result<(), CompileError>;
495
496 fn arch_emit_indirect_call_with_trampoline(
497 &mut self,
498 _loc: Location,
499 ) -> Result<(), CompileError> {
500 codegen_error!("singlepass arch_emit_indirect_call_with_trampoline unimplemented")
501 }
502}
503
504impl EmitterARM64 for Assembler {
505 fn get_label(&mut self) -> DynamicLabel {
506 self.new_dynamic_label()
507 }
508
509 fn get_offset(&self) -> AssemblyOffset {
510 self.offset()
511 }
512
513 fn get_jmp_instr_size(&self) -> u8 {
514 4 }
516
517 fn finalize_function(&mut self) {}
518
519 fn emit_str(&mut self, sz: Size, reg: Location, addr: Location) -> Result<(), CompileError> {
520 match (sz, reg, addr) {
521 (Size::S64, Location::GPR(reg), Location::Memory(addr, disp)) => {
522 let disp = disp as u32;
523 assert!(disp.is_multiple_of(8) && (disp < 0x8000));
524 dynasm!(self ; str X(reg), [X(addr), disp]);
525 }
526 (Size::S32, Location::GPR(reg), Location::Memory(addr, disp)) => {
527 let disp = disp as u32;
528 assert!(disp.is_multiple_of(4) && (disp < 0x4000));
529 dynasm!(self ; str W(reg), [X(addr), disp]);
530 }
531 (Size::S16, Location::GPR(reg), Location::Memory(addr, disp)) => {
532 let disp = disp as u32;
533 assert!(disp.is_multiple_of(2) && (disp < 0x2000));
534 dynasm!(self ; strh W(reg), [X(addr), disp]);
535 }
536 (Size::S8, Location::GPR(reg), Location::Memory(addr, disp)) => {
537 let disp = disp as u32;
538 assert!(disp < 0x1000);
539 dynasm!(self ; strb W(reg), [X(addr), disp]);
540 }
541 (Size::S64, Location::SIMD(reg), Location::Memory(addr, disp)) => {
542 let disp = disp as u32;
543 assert!(disp.is_multiple_of(8) && (disp < 0x8000));
544 dynasm!(self ; str D(reg), [X(addr), disp]);
545 }
546 (Size::S32, Location::SIMD(reg), Location::Memory(addr, disp)) => {
547 let disp = disp as u32;
548 assert!(disp.is_multiple_of(4) && (disp < 0x4000));
549 dynasm!(self ; str S(reg), [X(addr), disp]);
550 }
551 (Size::S64, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
552 assert!(offs == 0);
553 let mult = mult as u32;
554 match mult {
555 0 => dynasm!(self ; str X(reg), [X(addr)]),
556 1 => dynasm!(self ; str X(reg), [X(addr), X(r2)]),
557 _ => dynasm!(self ; str X(reg), [X(addr), X(r2), LSL mult]),
558 };
559 }
560 (Size::S32, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
561 assert!(offs == 0);
562 let mult = mult as u32;
563 match mult {
564 0 => dynasm!(self ; str W(reg), [X(addr)]),
565 1 => dynasm!(self ; str W(reg), [X(addr), X(r2)]),
566 _ => dynasm!(self ; str W(reg), [X(addr), X(r2), LSL mult]),
567 };
568 }
569 _ => codegen_error!("singlepass can't emit STR {:?}, {:?}, {:?}", sz, reg, addr),
570 }
571 Ok(())
572 }
573 fn emit_ldr(&mut self, sz: Size, reg: Location, addr: Location) -> Result<(), CompileError> {
574 match (sz, reg, addr) {
575 (Size::S64, Location::GPR(reg), Location::Memory(addr, disp)) => {
576 assert!((disp & 0x7) == 0 && (disp < 0x8000));
577 let disp = disp as u32;
578 dynasm!(self ; ldr X(reg), [X(addr), disp]);
579 }
580 (Size::S32, Location::GPR(reg), Location::Memory(addr, disp)) => {
581 assert!((disp & 0x3) == 0 && (disp < 0x4000));
582 let disp = disp as u32;
583 dynasm!(self ; ldr W(reg), [X(addr), disp]);
584 }
585 (Size::S16, Location::GPR(reg), Location::Memory(addr, disp)) => {
586 assert!((disp & 0x1 == 0) && (disp < 0x2000));
587 let disp = disp as u32;
588 dynasm!(self ; ldrh W(reg), [X(addr), disp]);
589 }
590 (Size::S8, Location::GPR(reg), Location::Memory(addr, disp)) => {
591 assert!(disp < 0x1000);
592 let disp = disp as u32;
593 dynasm!(self ; ldrb W(reg), [X(addr), disp]);
594 }
595 (Size::S64, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
596 assert!(offs == 0);
597 let mult = mult as u32;
598 match mult {
599 0 => dynasm!(self ; ldr X(reg), [X(addr)]),
600 1 => dynasm!(self ; ldr X(reg), [X(addr), X(r2)]),
601 _ => dynasm!(self ; ldr X(reg), [X(addr), X(r2), LSL mult]),
602 };
603 }
604 (Size::S32, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
605 assert!(offs == 0);
606 let mult = mult as u32;
607 match mult {
608 0 => dynasm!(self ; ldr W(reg), [X(addr)]),
609 1 => dynasm!(self ; ldr W(reg), [X(addr), X(r2)]),
610 _ => dynasm!(self ; ldr W(reg), [X(addr), X(r2), LSL mult]),
611 };
612 }
613 (Size::S64, Location::SIMD(reg), Location::Memory(addr, disp)) => {
614 let disp = disp as u32;
615 assert!((disp & 0x7) == 0 && (disp < 0x8000));
616 dynasm!(self ; ldr D(reg), [X(addr), disp]);
617 }
618 (Size::S32, Location::SIMD(reg), Location::Memory(addr, disp)) => {
619 let disp = disp as u32;
620 assert!((disp & 0x3) == 0 && (disp < 0x4000));
621 dynasm!(self ; ldr S(reg), [X(addr), disp]);
622 }
623 (Size::S64, Location::SIMD(reg), Location::Memory2(addr, r2, mult, offs)) => {
624 assert!(offs == 0);
625 let mult = mult as u32;
626 match mult {
627 0 => dynasm!(self ; ldr D(reg), [X(addr)]),
628 1 => dynasm!(self ; ldr D(reg), [X(addr), X(r2)]),
629 _ => dynasm!(self ; ldr D(reg), [X(addr), X(r2), LSL mult]),
630 };
631 }
632 (Size::S32, Location::SIMD(reg), Location::Memory2(addr, r2, mult, offs)) => {
633 assert!(offs == 0);
634 let mult = mult as u32;
635 match mult {
636 0 => dynasm!(self ; ldr S(reg), [X(addr)]),
637 1 => dynasm!(self ; ldr S(reg), [X(addr), X(r2)]),
638 _ => dynasm!(self ; ldr S(reg), [X(addr), X(r2), LSL mult]),
639 };
640 }
641 _ => codegen_error!("singlepass can't emit LDR {:?}, {:?}, {:?}", sz, reg, addr),
642 }
643 Ok(())
644 }
645 fn emit_stur(
646 &mut self,
647 sz: Size,
648 reg: Location,
649 addr: GPR,
650 offset: i32,
651 ) -> Result<(), CompileError> {
652 assert!((-255..=255).contains(&offset));
653 match (sz, reg) {
654 (Size::S64, Location::GPR(reg)) => {
655 dynasm!(self ; stur X(reg), [X(addr), offset]);
656 }
657 (Size::S32, Location::GPR(reg)) => {
658 dynasm!(self ; stur W(reg), [X(addr), offset]);
659 }
660 (Size::S64, Location::SIMD(reg)) => {
661 dynasm!(self ; stur D(reg), [X(addr), offset]);
662 }
663 (Size::S32, Location::SIMD(reg)) => {
664 dynasm!(self ; stur S(reg), [X(addr), offset]);
665 }
666 _ => codegen_error!(
667 "singlepass can't emit STUR {:?}, {:?}, {:?}, {:?}",
668 sz,
669 reg,
670 addr,
671 offset
672 ),
673 }
674 Ok(())
675 }
676 fn emit_ldur(
677 &mut self,
678 sz: Size,
679 reg: Location,
680 addr: GPR,
681 offset: i32,
682 ) -> Result<(), CompileError> {
683 assert!((-255..=255).contains(&offset));
684 match (sz, reg) {
685 (Size::S64, Location::GPR(reg)) => {
686 dynasm!(self ; ldur X(reg), [X(addr), offset]);
687 }
688 (Size::S32, Location::GPR(reg)) => {
689 dynasm!(self ; ldur W(reg), [X(addr), offset]);
690 }
691 (Size::S64, Location::SIMD(reg)) => {
692 dynasm!(self ; ldur D(reg), [X(addr), offset]);
693 }
694 (Size::S32, Location::SIMD(reg)) => {
695 dynasm!(self ; ldur S(reg), [X(addr), offset]);
696 }
697 _ => codegen_error!(
698 "singlepass can't emit LDUR {:?}, {:?}, {:?}, {:?}",
699 sz,
700 reg,
701 addr,
702 offset
703 ),
704 }
705 Ok(())
706 }
707
708 fn emit_strdb(
709 &mut self,
710 sz: Size,
711 reg: Location,
712 addr: GPR,
713 offset: u32,
714 ) -> Result<(), CompileError> {
715 assert!(offset <= 255);
716 match (sz, reg) {
717 (Size::S64, Location::GPR(reg)) => {
718 dynasm!(self ; str X(reg), [X(addr), -(offset as i32)]!);
719 }
720 (Size::S64, Location::SIMD(reg)) => {
721 dynasm!(self ; str D(reg), [X(addr), -(offset as i32)]!);
722 }
723 _ => codegen_error!("singlepass can't emit STRDB"),
724 }
725 Ok(())
726 }
727 fn emit_stria(
728 &mut self,
729 sz: Size,
730 reg: Location,
731 addr: GPR,
732 offset: u32,
733 ) -> Result<(), CompileError> {
734 assert!(offset <= 255);
735 match (sz, reg) {
736 (Size::S64, Location::GPR(reg)) => {
737 dynasm!(self ; str X(reg), [X(addr)], offset as i32);
738 }
739 (Size::S64, Location::SIMD(reg)) => {
740 dynasm!(self ; str D(reg), [X(addr)], offset as i32);
741 }
742 _ => codegen_error!("singlepass can't emit STRIA"),
743 }
744 Ok(())
745 }
746 fn emit_ldria(
747 &mut self,
748 sz: Size,
749 reg: Location,
750 addr: GPR,
751 offset: u32,
752 ) -> Result<(), CompileError> {
753 assert!(offset <= 255);
754 match (sz, reg) {
755 (Size::S64, Location::GPR(reg)) => {
756 dynasm!(self ; ldr X(reg), [X(addr)], offset as _);
757 }
758 (Size::S64, Location::SIMD(reg)) => {
759 dynasm!(self ; ldr D(reg), [X(addr)], offset as _);
760 }
761 _ => codegen_error!("singlepass can't emit LDRIA"),
762 }
763 Ok(())
764 }
765
766 fn emit_stpdb(
767 &mut self,
768 sz: Size,
769 reg1: Location,
770 reg2: Location,
771 addr: GPR,
772 offset: u32,
773 ) -> Result<(), CompileError> {
774 assert!(offset <= 255);
775 match (sz, reg1, reg2) {
776 (Size::S64, Location::GPR(reg1), Location::GPR(reg2)) => {
777 dynasm!(self ; stp X(reg1), X(reg2), [X(addr), -(offset as i32)]!);
778 }
779 _ => codegen_error!("singlepass can't emit STPDB"),
780 }
781 Ok(())
782 }
783 fn emit_ldpia(
784 &mut self,
785 sz: Size,
786 reg1: Location,
787 reg2: Location,
788 addr: GPR,
789 offset: u32,
790 ) -> Result<(), CompileError> {
791 assert!(offset <= 255);
792 match (sz, reg1, reg2) {
793 (Size::S64, Location::GPR(reg1), Location::GPR(reg2)) => {
794 dynasm!(self ; ldp X(reg1), X(reg2), [X(addr)], offset as _);
795 }
796 _ => codegen_error!("singlepass can't emit LDPIA"),
797 }
798 Ok(())
799 }
800
801 fn emit_ldrb(&mut self, _sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
802 match (reg, dst) {
803 (Location::GPR(reg), Location::Memory(addr, offset)) => {
804 let offset = offset as u32;
805 assert!(offset < 0x1000);
806 dynasm!(self ; ldrb W(reg), [X(addr), offset]);
807 }
808 (Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
809 assert!(offs == 0);
810 let mult = mult as u32;
811 match mult {
812 0 => dynasm!(self ; ldrb W(reg), [X(addr)]),
813 1 => dynasm!(self ; ldrb W(reg), [X(addr), X(r2)]),
814 _ => dynasm!(self ; ldrb W(reg), [X(addr), X(r2), LSL mult]),
815 };
816 }
817 _ => codegen_error!("singlepass can't emit LDRB {:?}, {:?}", reg, dst),
818 }
819 Ok(())
820 }
821 fn emit_ldrh(&mut self, _sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
822 match (reg, dst) {
823 (Location::GPR(reg), Location::Memory(addr, offset)) => {
824 let offset = offset as u32;
825 assert!((offset & 1 == 0) && (offset < 0x2000));
826 dynasm!(self ; ldrh W(reg), [X(addr), offset]);
827 }
828 (Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
829 assert!(offs == 0);
830 let mult = mult as u32;
831 match mult {
832 0 => dynasm!(self ; ldrh W(reg), [X(addr)]),
833 1 => dynasm!(self ; ldrh W(reg), [X(addr), X(r2)]),
834 _ => dynasm!(self ; ldrh W(reg), [X(addr), X(r2), LSL mult]),
835 };
836 }
837 _ => codegen_error!("singlepass can't emit LDRH {:?}, {:?}", reg, dst),
838 }
839 Ok(())
840 }
841 fn emit_ldrsb(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
842 match (sz, reg, dst) {
843 (Size::S64, Location::GPR(reg), Location::Memory(addr, offset)) => {
844 let offset = offset as u32;
845 assert!(offset < 0x1000);
846 dynasm!(self ; ldrsb X(reg), [X(addr), offset]);
847 }
848 (Size::S32, Location::GPR(reg), Location::Memory(addr, offset)) => {
849 let offset = offset as u32;
850 assert!(offset < 0x1000);
851 dynasm!(self ; ldrsb W(reg), [X(addr), offset]);
852 }
853 (Size::S64, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
854 assert!(offs == 0);
855 let mult = mult as u32;
856 match mult {
857 0 => dynasm!(self ; ldrsb X(reg), [X(addr)]),
858 1 => dynasm!(self ; ldrsb X(reg), [X(addr), X(r2)]),
859 _ => dynasm!(self ; ldrsb X(reg), [X(addr), X(r2), LSL mult]),
860 };
861 }
862 (Size::S32, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
863 assert!(offs == 0);
864 let mult = mult as u32;
865 match mult {
866 0 => dynasm!(self ; ldrsb W(reg), [X(addr)]),
867 1 => dynasm!(self ; ldrsb W(reg), [X(addr), X(r2)]),
868 _ => dynasm!(self ; ldrsb W(reg), [X(addr), X(r2), LSL mult]),
869 };
870 }
871 _ => codegen_error!("singlepass can't emit LDRSB {:?}, {:?}, {:?}", sz, reg, dst),
872 }
873 Ok(())
874 }
875 fn emit_ldrsh(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
876 match (sz, reg, dst) {
877 (Size::S64, Location::GPR(reg), Location::Memory(addr, offset)) => {
878 let offset = offset as u32;
879 assert!((offset & 1 == 0) && (offset < 0x2000));
880 dynasm!(self ; ldrsh X(reg), [X(addr), offset]);
881 }
882 (Size::S32, Location::GPR(reg), Location::Memory(addr, offset)) => {
883 let offset = offset as u32;
884 assert!((offset & 1 == 0) && (offset < 0x2000));
885 dynasm!(self ; ldrsh W(reg), [X(addr), offset]);
886 }
887 (Size::S64, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
888 assert!(offs == 0);
889 let mult = mult as u32;
890 match mult {
891 0 => dynasm!(self ; ldrsh X(reg), [X(addr)]),
892 1 => dynasm!(self ; ldrsh X(reg), [X(addr), X(r2)]),
893 _ => dynasm!(self ; ldrsh X(reg), [X(addr), X(r2), LSL mult]),
894 };
895 }
896 (Size::S32, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
897 assert!(offs == 0);
898 let mult = mult as u32;
899 match mult {
900 0 => dynasm!(self ; ldrsh W(reg), [X(addr)]),
901 1 => dynasm!(self ; ldrsh W(reg), [X(addr), X(r2)]),
902 _ => dynasm!(self ; ldrsh W(reg), [X(addr), X(r2), LSL mult]),
903 };
904 }
905 _ => codegen_error!("singlepass can't emit LDRSH {:?}, {:?}, {:?}", sz, reg, dst),
906 }
907 Ok(())
908 }
909 fn emit_ldrsw(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
910 match (sz, reg, dst) {
911 (Size::S64, Location::GPR(reg), Location::Memory(addr, offset)) => {
912 let offset = offset as u32;
913 assert!((offset & 3 == 0) && (offset < 0x4000));
914 dynasm!(self ; ldrsw X(reg), [X(addr), offset]);
915 }
916 (Size::S64, Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
917 assert!(offs == 0);
918 let mult = mult as u32;
919 match mult {
920 0 => dynasm!(self ; ldrsw X(reg), [X(addr)]),
921 1 => dynasm!(self ; ldrsw X(reg), [X(addr), X(r2)]),
922 _ => dynasm!(self ; ldrsw X(reg), [X(addr), X(r2), LSL mult]),
923 };
924 }
925 _ => codegen_error!("singlepass can't emit LDRSW {:?}, {:?}, {:?}", sz, reg, dst),
926 }
927 Ok(())
928 }
929 fn emit_strb(&mut self, _sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
930 match (reg, dst) {
931 (Location::GPR(reg), Location::Memory(addr, offset)) => {
932 let offset = offset as u32;
933 assert!(offset < 0x1000);
934 dynasm!(self ; strb W(reg), [X(addr), offset]);
935 }
936 (Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
937 assert!(offs == 0);
938 let mult = mult as u32;
939 match mult {
940 0 => dynasm!(self ; strb W(reg), [X(addr)]),
941 1 => dynasm!(self ; strb W(reg), [X(addr), X(r2)]),
942 _ => dynasm!(self ; strb W(reg), [X(addr), X(r2), LSL mult]),
943 };
944 }
945 _ => codegen_error!("singlepass can't emit STRB {:?}, {:?}", reg, dst),
946 }
947 Ok(())
948 }
949 fn emit_strh(&mut self, _sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
950 match (reg, dst) {
951 (Location::GPR(reg), Location::Memory(addr, offset)) => {
952 let offset = offset as u32;
953 assert!((offset & 1 == 0) && (offset < 0x2000));
954 dynasm!(self ; strh W(reg), [X(addr), offset]);
955 }
956 (Location::GPR(reg), Location::Memory2(addr, r2, mult, offs)) => {
957 assert!(offs == 0);
958 let mult = mult as u32;
959 match mult {
960 0 => dynasm!(self ; strh W(reg), [X(addr)]),
961 1 => dynasm!(self ; strh W(reg), [X(addr), X(r2)]),
962 _ => dynasm!(self ; strh W(reg), [X(addr), X(r2), LSL mult]),
963 };
964 }
965 _ => codegen_error!("singlepass can't emit STRH {:?}, {:?}", reg, dst),
966 }
967 Ok(())
968 }
969
970 fn emit_ldaxr(&mut self, sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
971 match (sz, reg, dst) {
972 (Size::S32, Location::GPR(reg), Location::GPR(dst)) => {
973 dynasm!(self ; ldaxr W(reg), [X(dst)]);
974 }
975 (Size::S64, Location::GPR(reg), Location::GPR(dst)) => {
976 dynasm!(self ; ldaxr X(reg), [X(dst)]);
977 }
978 _ => codegen_error!("singlepass can't emit LDAXR {:?}, {:?}", reg, dst),
979 }
980 Ok(())
981 }
982 fn emit_ldaxrb(&mut self, _sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
983 match (reg, dst) {
984 (Location::GPR(reg), Location::GPR(dst)) => {
985 dynasm!(self ; ldaxrb W(reg), [X(dst)]);
986 }
987 _ => codegen_error!("singlepass can't emit LDAXRB {:?}, {:?}", reg, dst),
988 }
989 Ok(())
990 }
991 fn emit_ldaxrh(&mut self, _sz: Size, reg: Location, dst: Location) -> Result<(), CompileError> {
992 match (reg, dst) {
993 (Location::GPR(reg), Location::GPR(dst)) => {
994 dynasm!(self ; ldaxrh W(reg), [X(dst)]);
995 }
996 _ => codegen_error!("singlepass can't emit LDAXRH {:?}, {:?}", reg, dst),
997 }
998 Ok(())
999 }
1000 fn emit_stlxr(
1001 &mut self,
1002 sz: Size,
1003 status: Location,
1004 reg: Location,
1005 dst: Location,
1006 ) -> Result<(), CompileError> {
1007 match (sz, status, reg, dst) {
1008 (Size::S32, Location::GPR(status), Location::GPR(reg), Location::GPR(dst)) => {
1009 dynasm!(self ; stlxr W(status), W(reg), [X(dst)]);
1010 }
1011 (Size::S64, Location::GPR(status), Location::GPR(reg), Location::GPR(dst)) => {
1012 dynasm!(self ; stlxr W(status), X(reg), [X(dst)]);
1013 }
1014 _ => codegen_error!("singlepass can't emit STLXR {:?}, {:?}", reg, dst),
1015 }
1016 Ok(())
1017 }
1018 fn emit_stlxrb(
1019 &mut self,
1020 _sz: Size,
1021 status: Location,
1022 reg: Location,
1023 dst: Location,
1024 ) -> Result<(), CompileError> {
1025 match (status, reg, dst) {
1026 (Location::GPR(status), Location::GPR(reg), Location::GPR(dst)) => {
1027 dynasm!(self ; stlxrb W(status), W(reg), [X(dst)]);
1028 }
1029 _ => codegen_error!("singlepass can't emit STLXRB {:?}, {:?}", reg, dst),
1030 }
1031 Ok(())
1032 }
1033 fn emit_stlxrh(
1034 &mut self,
1035 _sz: Size,
1036 status: Location,
1037 reg: Location,
1038 dst: Location,
1039 ) -> Result<(), CompileError> {
1040 match (status, reg, dst) {
1041 (Location::GPR(status), Location::GPR(reg), Location::GPR(dst)) => {
1042 dynasm!(self ; stlxrh W(status), W(reg), [X(dst)]);
1043 }
1044 _ => codegen_error!("singlepass can't emit STLXRH {:?}, {:?}", reg, dst),
1045 }
1046 Ok(())
1047 }
1048
1049 fn emit_mov(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1050 match (sz, src, dst) {
1051 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1052 dynasm!(self ; mov X(dst), X(src));
1053 }
1054 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1055 dynasm!(self ; mov W(dst), W(src));
1056 }
1057 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
1058 dynasm!(self ; mov V(dst).D[0], V(src).D[0]);
1059 }
1060 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
1061 dynasm!(self ; mov V(dst).S[0], V(src).S[0]);
1062 }
1063 (Size::S64, Location::GPR(src), Location::SIMD(dst)) => {
1064 dynasm!(self ; mov V(dst).D[0], X(src));
1065 }
1066 (Size::S32, Location::GPR(src), Location::SIMD(dst)) => {
1067 dynasm!(self ; mov V(dst).S[0], W(src));
1068 }
1069 (Size::S64, Location::SIMD(src), Location::GPR(dst)) => {
1070 dynasm!(self ; mov X(dst), V(src).D[0]);
1071 }
1072 (Size::S32, Location::SIMD(src), Location::GPR(dst)) => {
1073 dynasm!(self ; mov W(dst), V(src).S[0]);
1074 }
1075 (Size::S32, Location::Imm32(val), Location::GPR(dst)) => {
1076 if val < 0x1000 || encode_logical_immediate_32bit(val as _).is_some() {
1077 dynasm!(self ; mov W(dst), val);
1078 } else {
1079 dynasm!(self
1080 ; movz W(dst), val
1081 ; movk W(dst), val, lsl #16);
1082 }
1083 }
1084 (Size::S64, Location::Imm32(val), Location::GPR(dst)) => {
1085 if val < 0x1000 {
1086 dynasm!(self ; mov W(dst), val);
1087 } else if encode_logical_immediate_64bit(val as _).is_some() {
1088 dynasm!(self ; mov X(dst), val as _);
1089 } else {
1090 dynasm!(self
1091 ; movz X(dst), val
1092 ; movk X(dst), val, lsl #16);
1093 }
1094 }
1095 (Size::S64, Location::Imm64(val), Location::GPR(dst)) => {
1096 if val < 0x1000 || encode_logical_immediate_64bit(val as _).is_some() {
1097 dynasm!(self ; mov X(dst), val as _);
1098 } else {
1099 dynasm!(self
1100 ; movz X(dst), val as _
1101 ; movk X(dst), val as _, lsl #16
1102 ; movk X(dst), val as _, lsl #32
1103 ; movk X(dst), val as _, lsl #48);
1104 }
1105 }
1106 _ => codegen_error!("singlepass can't emit MOV {:?}, {:?}, {:?}", sz, src, dst),
1107 }
1108 Ok(())
1109 }
1110
1111 fn emit_movn(&mut self, sz: Size, reg: Location, val: u32) -> Result<(), CompileError> {
1112 match (sz, reg) {
1113 (Size::S32, Location::GPR(reg)) => {
1114 dynasm!(self ; movn W(reg), val);
1115 }
1116 (Size::S64, Location::GPR(reg)) => {
1117 dynasm!(self ; movn X(reg), val);
1118 }
1119 _ => codegen_error!("singlepass can't emit MOVN"),
1120 }
1121 Ok(())
1122 }
1123 fn emit_movz(&mut self, reg: Location, val: u32) -> Result<(), CompileError> {
1124 match reg {
1125 Location::GPR(reg) => {
1126 dynasm!(self ; movz W(reg), val);
1127 }
1128 _ => codegen_error!("singlepass can't emit MOVZ"),
1129 }
1130 Ok(())
1131 }
1132 fn emit_movk(&mut self, reg: Location, val: u32, shift: u32) -> Result<(), CompileError> {
1133 match reg {
1134 Location::GPR(reg) => {
1135 dynasm!(self ; movk X(reg), val, LSL shift);
1136 }
1137 _ => codegen_error!("singlepass can't emit MOVK"),
1138 }
1139 Ok(())
1140 }
1141
1142 fn emit_mov_imm(&mut self, dst: Location, val: u64) -> Result<(), CompileError> {
1143 match dst {
1144 Location::GPR(dst) => {
1145 let offset = val.trailing_zeros() & 48;
1146 let masked = 0xffff & (val >> offset);
1147 if (masked << offset) == val {
1148 dynasm!(self ; movz X(dst), masked as u32, LSL offset);
1149 } else if val >> 16 == 0xffff_ffff_ffff {
1150 let val: u16 = !((val & 0xffff) as u16);
1151 dynasm!(self ; movn X(dst), val as u32);
1152 } else if val >> 16 == 0xffff {
1153 let val: u16 = !((val & 0xffff) as u16);
1154 dynasm!(self ; movn W(dst), val as u32);
1155 } else {
1156 dynasm!(self ; movz W(dst), (val&0xffff) as u32);
1157 let val = val >> 16;
1158 if val != 0 {
1159 dynasm!(self ; movk X(dst), (val&0xffff) as u32, LSL 16);
1160 let val = val >> 16;
1161 if val != 0 {
1162 dynasm!(self ; movk X(dst), (val&0xffff) as u32, LSL 32);
1163 let val = val >> 16;
1164 if val != 0 {
1165 dynasm!(self ; movk X(dst), (val&0xffff) as u32, LSL 48);
1166 }
1167 }
1168 }
1169 }
1170 }
1171 _ => codegen_error!("singlepass can't emit MOVW {:?}", dst),
1172 }
1173 Ok(())
1174 }
1175
1176 fn emit_add(
1177 &mut self,
1178 sz: Size,
1179 src1: Location,
1180 src2: Location,
1181 dst: Location,
1182 ) -> Result<(), CompileError> {
1183 match (sz, src1, src2, dst) {
1184 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1185 dynasm!(self ; add XSP(dst), XSP(src1), X(src2), UXTX);
1186 }
1187 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1188 dynasm!(self ; add WSP(dst), WSP(src1), W(src2), UXTX);
1189 }
1190 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst))
1191 | (Size::S64, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => {
1192 dynasm!(self ; add XSP(dst), XSP(src1), imm as _);
1193 }
1194 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst))
1195 | (Size::S64, Location::Imm32(imm), Location::GPR(src1), Location::GPR(dst)) => {
1196 if imm >= 0x1000 {
1197 unreachable!();
1198 }
1199 dynasm!(self ; add XSP(dst), XSP(src1), imm);
1200 }
1201 (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst))
1202 | (Size::S64, Location::Imm64(imm), Location::GPR(src1), Location::GPR(dst)) => {
1203 if imm >= 0x1000 {
1204 unreachable!();
1205 }
1206 let imm = imm as u32;
1207 dynasm!(self ; add XSP(dst), XSP(src1), imm);
1208 }
1209 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst))
1210 | (Size::S32, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => {
1211 dynasm!(self ; add WSP(dst), WSP(src1), imm as u32);
1212 }
1213 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst))
1214 | (Size::S32, Location::Imm32(imm), Location::GPR(src1), Location::GPR(dst)) => {
1215 if imm >= 0x1000 {
1216 unreachable!();
1217 }
1218 dynasm!(self ; add WSP(dst), WSP(src1), imm);
1219 }
1220 _ => codegen_error!(
1221 "singlepass can't emit ADD {:?} {:?} {:?} {:?}",
1222 sz,
1223 src1,
1224 src2,
1225 dst
1226 ),
1227 }
1228 Ok(())
1229 }
1230 fn emit_sub(
1231 &mut self,
1232 sz: Size,
1233 src1: Location,
1234 src2: Location,
1235 dst: Location,
1236 ) -> Result<(), CompileError> {
1237 match (sz, src1, src2, dst) {
1238 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1239 dynasm!(self; sub XSP(dst), XSP(src1), X(src2), UXTX 0);
1240 }
1241 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1242 dynasm!(self ; sub WSP(dst), WSP(src1), W(src2), UXTX 0);
1243 }
1244 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1245 dynasm!(self ; sub XSP(dst), XSP(src1), imm as u32);
1246 }
1247 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1248 dynasm!(self ; sub WSP(dst), WSP(src1), imm as u32);
1249 }
1250 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1251 if imm >= 0x1000 {
1252 unreachable!();
1253 }
1254 dynasm!(self ; sub WSP(dst), WSP(src1), imm);
1255 }
1256 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1257 if imm >= 0x1000 {
1258 unreachable!();
1259 }
1260 dynasm!(self ; sub XSP(dst), XSP(src1), imm);
1261 }
1262 (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst)) => {
1263 if imm >= 0x1000 {
1264 unreachable!();
1265 }
1266 dynasm!(self ; sub XSP(dst), XSP(src1), imm as u32);
1267 }
1268 _ => codegen_error!(
1269 "singlepass can't emit SUB {:?} {:?} {:?} {:?}",
1270 sz,
1271 src1,
1272 src2,
1273 dst
1274 ),
1275 }
1276 Ok(())
1277 }
1278 fn emit_mul(
1279 &mut self,
1280 sz: Size,
1281 src1: Location,
1282 src2: Location,
1283 dst: Location,
1284 ) -> Result<(), CompileError> {
1285 match (sz, src1, src2, dst) {
1286 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1287 dynasm!(self ; mul X(dst), X(src1), X(src2));
1288 }
1289 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1290 dynasm!(self ; mul W(dst), W(src1), W(src2));
1291 }
1292 _ => codegen_error!(
1293 "singlepass can't emit MUL {:?} {:?} {:?} {:?}",
1294 sz,
1295 src1,
1296 src2,
1297 dst
1298 ),
1299 }
1300 Ok(())
1301 }
1302 fn emit_adds(
1303 &mut self,
1304 sz: Size,
1305 src1: Location,
1306 src2: Location,
1307 dst: Location,
1308 ) -> Result<(), CompileError> {
1309 match (sz, src1, src2, dst) {
1310 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1311 dynasm!(self ; adds X(dst), X(src1), X(src2));
1312 }
1313 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1314 dynasm!(self ; adds W(dst), W(src1), W(src2));
1315 }
1316 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst))
1317 | (Size::S64, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => {
1318 dynasm!(self ; adds X(dst), XSP(src1), imm as u32);
1319 }
1320 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst))
1321 | (Size::S64, Location::Imm32(imm), Location::GPR(src1), Location::GPR(dst)) => {
1322 if imm >= 0x1000 {
1323 codegen_error!("singlepass ADD.S with imm too large {}", imm);
1324 }
1325 dynasm!(self ; adds X(dst), XSP(src1), imm);
1326 }
1327 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst))
1328 | (Size::S32, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => {
1329 dynasm!(self ; adds W(dst), WSP(src1), imm as u32);
1330 }
1331 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst))
1332 | (Size::S32, Location::Imm32(imm), Location::GPR(src1), Location::GPR(dst)) => {
1333 if imm >= 0x1000 {
1334 codegen_error!("singlepass ADD.S with imm too large {}", imm);
1335 }
1336 dynasm!(self ; adds W(dst), WSP(src1), imm);
1337 }
1338 _ => codegen_error!(
1339 "singlepass can't emit ADD.S {:?} {:?} {:?} {:?}",
1340 sz,
1341 src1,
1342 src2,
1343 dst
1344 ),
1345 }
1346 Ok(())
1347 }
1348 fn emit_subs(
1349 &mut self,
1350 sz: Size,
1351 src1: Location,
1352 src2: Location,
1353 dst: Location,
1354 ) -> Result<(), CompileError> {
1355 match (sz, src1, src2, dst) {
1356 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1357 dynasm!(self ; subs X(dst), X(src1), X(src2));
1358 }
1359 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1360 dynasm!(self ; subs W(dst), W(src1), W(src2));
1361 }
1362 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1363 dynasm!(self ; subs X(dst), XSP(src1), imm as u32);
1364 }
1365 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1366 dynasm!(self ; subs W(dst), WSP(src1), imm as u32);
1367 }
1368 _ => codegen_error!(
1369 "singlepass can't emit SUB.S {:?} {:?} {:?} {:?}",
1370 sz,
1371 src1,
1372 src2,
1373 dst
1374 ),
1375 }
1376 Ok(())
1377 }
1378 fn emit_add_lsl(
1379 &mut self,
1380 sz: Size,
1381 src1: Location,
1382 src2: Location,
1383 lsl: u32,
1384 dst: Location,
1385 ) -> Result<(), CompileError> {
1386 match (sz, src1, src2, dst) {
1387 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1388 dynasm!(self ; add X(dst), X(src1), X(src2), LSL lsl);
1389 }
1390 _ => codegen_error!(
1391 "singlepass can't emit LSL {:?} {:?} {:?} {:?} LSL {:?}",
1392 sz,
1393 src1,
1394 src2,
1395 dst,
1396 lsl
1397 ),
1398 }
1399 Ok(())
1400 }
1401
1402 fn emit_cmp(&mut self, sz: Size, left: Location, right: Location) -> Result<(), CompileError> {
1408 match (sz, left, right) {
1409 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1410 dynasm!(self ; cmp X(dst), X(src));
1411 }
1412 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1413 dynasm!(self ; cmp W(dst), W(src));
1414 }
1415 (Size::S64, Location::Imm8(imm), Location::GPR(dst)) => {
1416 dynasm!(self ; cmp XSP(dst), imm as u32);
1417 }
1418 (Size::S64, Location::Imm32(imm), Location::GPR(dst)) => {
1419 if imm >= 0x1000 {
1420 codegen_error!("singlepass CMP with imm too large {}", imm);
1421 }
1422 dynasm!(self ; cmp XSP(dst), imm as u32);
1423 }
1424 (Size::S64, Location::Imm64(imm), Location::GPR(dst)) => {
1425 if imm >= 0x1000 {
1426 codegen_error!("singlepass CMP with imm too large {}", imm);
1427 }
1428 dynasm!(self ; cmp XSP(dst), imm as u32);
1429 }
1430 (Size::S32, Location::Imm8(imm), Location::GPR(dst)) => {
1431 dynasm!(self ; cmp WSP(dst), imm as u32);
1432 }
1433 (Size::S32, Location::Imm32(imm), Location::GPR(dst)) => {
1434 if imm >= 0x1000 {
1435 codegen_error!("singlepass CMP with imm too large {}", imm);
1436 }
1437 dynasm!(self ; cmp WSP(dst), imm as u32);
1438 }
1439 _ => codegen_error!("singlepass can't emit CMP {:?} {:?} {:?}", sz, left, right),
1440 }
1441 Ok(())
1442 }
1443
1444 fn emit_tst(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1445 match (sz, src, dst) {
1446 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1447 dynasm!(self ; tst X(dst), X(src));
1448 }
1449 (Size::S64, Location::Imm32(imm), Location::GPR(dst)) => {
1450 if encode_logical_immediate_64bit(imm as u64).is_none() {
1451 codegen_error!("singlepass TST with incompatible imm {}", imm);
1452 }
1453 dynasm!(self ; tst X(dst), imm as u64);
1454 }
1455 (Size::S64, Location::Imm64(imm), Location::GPR(dst)) => {
1456 if encode_logical_immediate_64bit(imm as u64).is_none() {
1457 codegen_error!("singlepass TST with incompatible imm {}", imm);
1458 }
1459 dynasm!(self ; tst X(dst), imm as u64);
1460 }
1461 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1462 dynasm!(self ; tst W(dst), W(src));
1463 }
1464 (Size::S32, Location::Imm32(imm), Location::GPR(dst)) => {
1465 if encode_logical_immediate_64bit(imm as u64).is_none() {
1466 codegen_error!("singlepass TST with incompatible imm {}", imm);
1467 }
1468 dynasm!(self ; tst W(dst), imm);
1469 }
1470 _ => codegen_error!("singlepass can't emit TST"),
1471 }
1472 Ok(())
1473 }
1474
1475 fn emit_lsl(
1476 &mut self,
1477 sz: Size,
1478 src1: Location,
1479 src2: Location,
1480 dst: Location,
1481 ) -> Result<(), CompileError> {
1482 match (sz, src1, src2, dst) {
1483 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1484 dynasm!(self ; lsl X(dst), X(src1), X(src2));
1485 }
1486 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1487 if imm > 63 {
1488 codegen_error!("singlepass LSL with incompatible imm {}", imm);
1489 }
1490 let imm = imm as u32;
1491
1492 dynasm!(self ; lsl X(dst), X(src1), imm);
1493 }
1494 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1495 dynasm!(self ; lsl W(dst), W(src1), W(src2));
1496 }
1497 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1498 if imm > 63 {
1499 codegen_error!("singlepass LSL with incompatible imm {}", imm);
1500 }
1501 dynasm!(self ; lsl X(dst), X(src1), imm as u32);
1502 }
1503 (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst)) => {
1504 if imm > 63 {
1505 codegen_error!("singlepass LSL with incompatible imm {}", imm);
1506 }
1507 dynasm!(self ; lsl X(dst), X(src1), imm as u32);
1508 }
1509 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1510 if imm > 31 {
1511 codegen_error!("singlepass LSL with incompatible imm {}", imm);
1512 }
1513 dynasm!(self ; lsl W(dst), W(src1), imm as u32);
1514 }
1515 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1516 if imm > 31 {
1517 codegen_error!("singlepass LSL with incompatible imm {}", imm);
1518 }
1519 dynasm!(self ; lsl W(dst), W(src1), imm as u32);
1520 }
1521 _ => codegen_error!(
1522 "singlepass can't emit LSL {:?} {:?} {:?} {:?}",
1523 sz,
1524 src1,
1525 src2,
1526 dst
1527 ),
1528 }
1529 Ok(())
1530 }
1531 fn emit_asr(
1532 &mut self,
1533 sz: Size,
1534 src1: Location,
1535 src2: Location,
1536 dst: Location,
1537 ) -> Result<(), CompileError> {
1538 match (sz, src1, src2, dst) {
1539 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1540 dynasm!(self ; asr X(dst), X(src1), X(src2));
1541 }
1542 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1543 let imm = imm as u32;
1544
1545 if imm == 0 || imm > 63 {
1546 codegen_error!("singlepass ASR with incompatible imm {}", imm);
1547 }
1548 dynasm!(self ; asr X(dst), X(src1), imm);
1549 }
1550 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1551 dynasm!(self ; asr W(dst), W(src1), W(src2));
1552 }
1553 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1554 if imm == 0 || imm > 63 {
1555 codegen_error!("singlepass ASR with incompatible imm {}", imm);
1556 }
1557 dynasm!(self ; asr X(dst), X(src1), imm as u32);
1558 }
1559 (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst)) => {
1560 if imm == 0 || imm > 63 {
1561 codegen_error!("singlepass ASR with incompatible imm {}", imm);
1562 }
1563 dynasm!(self ; asr X(dst), X(src1), imm as u32);
1564 }
1565 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1566 if imm == 0 || imm > 31 {
1567 codegen_error!("singlepass ASR with incompatible imm {}", imm);
1568 }
1569 dynasm!(self ; asr W(dst), W(src1), imm as u32);
1570 }
1571 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1572 if imm == 0 || imm > 31 {
1573 codegen_error!("singlepass ASR with incompatible imm {}", imm);
1574 }
1575 dynasm!(self ; asr W(dst), W(src1), imm as u32);
1576 }
1577 _ => codegen_error!(
1578 "singlepass can't emit ASR {:?} {:?} {:?} {:?}",
1579 sz,
1580 src1,
1581 src2,
1582 dst
1583 ),
1584 }
1585 Ok(())
1586 }
1587 fn emit_lsr(
1588 &mut self,
1589 sz: Size,
1590 src1: Location,
1591 src2: Location,
1592 dst: Location,
1593 ) -> Result<(), CompileError> {
1594 match (sz, src1, src2, dst) {
1595 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1596 dynasm!(self ; lsr X(dst), X(src1), X(src2));
1597 }
1598 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1599 let imm = imm as u32;
1600
1601 if imm == 0 || imm > 63 {
1602 codegen_error!("singlepass LSR with incompatible imm {}", imm);
1603 }
1604 dynasm!(self ; lsr X(dst), X(src1), imm);
1605 }
1606 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1607 dynasm!(self ; lsr W(dst), W(src1), W(src2));
1608 }
1609 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1610 if imm == 0 || imm > 63 {
1611 codegen_error!("singlepass LSR with incompatible imm {}", imm);
1612 }
1613 dynasm!(self ; lsr X(dst), X(src1), imm as u32);
1614 }
1615 (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst)) => {
1616 if imm == 0 || imm > 63 {
1617 codegen_error!("singlepass LSR with incompatible imm {}", imm);
1618 }
1619 dynasm!(self ; lsr X(dst), X(src1), imm as u32);
1620 }
1621 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1622 if imm == 0 || imm > 31 {
1623 codegen_error!("singlepass LSR with incompatible imm {}", imm);
1624 }
1625 dynasm!(self ; lsr W(dst), W(src1), imm as u32);
1626 }
1627 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1628 if imm == 0 || imm > 31 {
1629 codegen_error!("singlepass LSR with incompatible imm {}", imm);
1630 }
1631 dynasm!(self ; lsr W(dst), W(src1), imm as u32);
1632 }
1633 _ => codegen_error!(
1634 "singlepass can't emit LSR {:?} {:?} {:?} {:?}",
1635 sz,
1636 src1,
1637 src2,
1638 dst
1639 ),
1640 }
1641 Ok(())
1642 }
1643 fn emit_ror(
1644 &mut self,
1645 sz: Size,
1646 src1: Location,
1647 src2: Location,
1648 dst: Location,
1649 ) -> Result<(), CompileError> {
1650 match (sz, src1, src2, dst) {
1651 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1652 dynasm!(self ; ror X(dst), X(src1), X(src2));
1653 }
1654 (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1655 let imm = imm as u32;
1656
1657 if imm == 0 || imm > 63 {
1658 codegen_error!("singlepass ROR with incompatible imm {}", imm);
1659 }
1660 dynasm!(self ; ror X(dst), X(src1), imm);
1661 }
1662 (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst)) => {
1663 let imm = imm as u32;
1664
1665 if imm == 0 || imm > 63 {
1666 codegen_error!("singlepass ROR with incompatible imm {}", imm);
1667 }
1668 dynasm!(self ; ror X(dst), X(src1), imm);
1669 }
1670 (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst)) => {
1671 if imm == 0 || imm > 31 {
1672 codegen_error!("singlepass ROR with incompatible imm {}", imm);
1673 }
1674 dynasm!(self ; ror W(dst), W(src1), imm as u32);
1675 }
1676 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1677 dynasm!(self ; ror W(dst), W(src1), W(src2));
1678 }
1679 (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1680 if imm == 0 || imm > 63 {
1681 codegen_error!("singlepass ROR with incompatible imm {}", imm);
1682 }
1683 dynasm!(self ; ror X(dst), X(src1), imm as u32);
1684 }
1685 (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
1686 if imm == 0 || imm > 31 {
1687 codegen_error!("singlepass ROR with incompatible imm {}", imm);
1688 }
1689 dynasm!(self ; ror W(dst), W(src1), imm as u32);
1690 }
1691 _ => codegen_error!(
1692 "singlepass can't emit ROR {:?} {:?} {:?} {:?}",
1693 sz,
1694 src1,
1695 src2,
1696 dst
1697 ),
1698 }
1699 Ok(())
1700 }
1701
1702 fn emit_or(
1703 &mut self,
1704 sz: Size,
1705 src1: Location,
1706 src2: Location,
1707 dst: Location,
1708 ) -> Result<(), CompileError> {
1709 match (sz, src1, src2, dst) {
1710 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1711 dynasm!(self ; orr X(dst), X(src1), X(src2));
1712 }
1713 (Size::S64, Location::GPR(src1), Location::Imm64(src2), Location::GPR(dst)) => {
1714 let src2 = src2 as u64;
1715
1716 if encode_logical_immediate_64bit(src2 as u64).is_none() {
1717 codegen_error!("singlepass OR with incompatible imm {}", src2);
1718 }
1719 dynasm!(self ; orr XSP(dst), X(src1), src2);
1720 }
1721 (Size::S32, Location::GPR(src1), Location::Imm32(src2), Location::GPR(dst)) => {
1722 let src2 = src2 as u32;
1723
1724 if encode_logical_immediate_32bit(src2).is_none() {
1725 codegen_error!("singlepass OR with incompatible imm {}", src2);
1726 }
1727 dynasm!(self ; orr WSP(dst), W(src1), src2);
1728 }
1729 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1730 dynasm!(self ; orr W(dst), W(src1), W(src2));
1731 }
1732 _ => codegen_error!(
1733 "singlepass can't emit OR {:?} {:?} {:?} {:?}",
1734 sz,
1735 src1,
1736 src2,
1737 dst
1738 ),
1739 }
1740 Ok(())
1741 }
1742 fn emit_and(
1743 &mut self,
1744 sz: Size,
1745 src1: Location,
1746 src2: Location,
1747 dst: Location,
1748 ) -> Result<(), CompileError> {
1749 match (sz, src1, src2, dst) {
1750 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1751 dynasm!(self ; and X(dst), X(src1), X(src2));
1752 }
1753 (Size::S64, Location::GPR(src1), Location::Imm64(src2), Location::GPR(dst)) => {
1754 let src2 = src2 as u64;
1755
1756 if encode_logical_immediate_64bit(src2 as u64).is_none() {
1757 codegen_error!("singlepass AND with incompatible imm {}", src2);
1758 }
1759 dynasm!(self ; and XSP(dst), X(src1), src2);
1760 }
1761 (Size::S32, Location::GPR(src1), Location::Imm32(src2), Location::GPR(dst)) => {
1762 let src2 = src2 as u32;
1763
1764 if encode_logical_immediate_32bit(src2).is_none() {
1765 codegen_error!("singlepass AND with incompatible imm {}", src2);
1766 }
1767 dynasm!(self ; and WSP(dst), W(src1), src2);
1768 }
1769 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1770 dynasm!(self ; and W(dst), W(src1), W(src2));
1771 }
1772 _ => codegen_error!(
1773 "singlepass can't emit AND {:?} {:?} {:?} {:?}",
1774 sz,
1775 src1,
1776 src2,
1777 dst
1778 ),
1779 }
1780 Ok(())
1781 }
1782 fn emit_eor(
1783 &mut self,
1784 sz: Size,
1785 src1: Location,
1786 src2: Location,
1787 dst: Location,
1788 ) -> Result<(), CompileError> {
1789 match (sz, src1, src2, dst) {
1790 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1791 dynasm!(self ; eor X(dst), X(src1), X(src2));
1792 }
1793 (Size::S64, Location::GPR(src1), Location::Imm64(src2), Location::GPR(dst)) => {
1794 let src2 = src2 as u64;
1795
1796 if encode_logical_immediate_64bit(src2 as u64).is_none() {
1797 codegen_error!("singlepass EOR with incompatible imm {}", src2);
1798 }
1799 dynasm!(self ; eor XSP(dst), X(src1), src2);
1800 }
1801 (Size::S32, Location::GPR(src1), Location::Imm32(src2), Location::GPR(dst)) => {
1802 let src2 = src2 as u32;
1803
1804 if encode_logical_immediate_32bit(src2).is_none() {
1805 codegen_error!("singlepass EOR with incompatible imm {}", src2);
1806 }
1807 dynasm!(self ; eor WSP(dst), W(src1), src2);
1808 }
1809 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1810 dynasm!(self ; eor W(dst), W(src1), W(src2));
1811 }
1812 _ => codegen_error!(
1813 "singlepass can't emit EOR {:?} {:?} {:?} {:?}",
1814 sz,
1815 src1,
1816 src2,
1817 dst
1818 ),
1819 }
1820 Ok(())
1821 }
1822
1823 fn emit_bfc(
1824 &mut self,
1825 sz: Size,
1826 lsb: u32,
1827 width: u32,
1828 dst: Location,
1829 ) -> Result<(), CompileError> {
1830 match (sz, dst) {
1831 (Size::S32, Location::GPR(dst)) => {
1832 dynasm!(self ; bfc W(dst), lsb, width);
1833 }
1834 (Size::S64, Location::GPR(dst)) => {
1835 dynasm!(self ; bfc X(dst), lsb, width);
1836 }
1837 _ => codegen_error!("singlepass can't emit BFC"),
1838 }
1839 Ok(())
1840 }
1841 fn emit_bfi(
1842 &mut self,
1843 sz: Size,
1844 src: Location,
1845 lsb: u32,
1846 width: u32,
1847 dst: Location,
1848 ) -> Result<(), CompileError> {
1849 match (sz, src, dst) {
1850 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1851 dynasm!(self ; bfi W(dst), W(src), lsb, width);
1852 }
1853 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1854 dynasm!(self ; bfi X(dst), X(src), lsb, width);
1855 }
1856 _ => codegen_error!("singlepass can't emit BFI"),
1857 }
1858 Ok(())
1859 }
1860
1861 fn emit_udiv(
1862 &mut self,
1863 sz: Size,
1864 src1: Location,
1865 src2: Location,
1866 dst: Location,
1867 ) -> Result<(), CompileError> {
1868 match (sz, src1, src2, dst) {
1869 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1870 dynasm!(self ; udiv W(dst), W(src1), W(src2));
1871 }
1872 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1873 dynasm!(self ; udiv X(dst), X(src1), X(src2));
1874 }
1875 _ => codegen_error!(
1876 "singlepass can't emit UDIV {:?} {:?} {:?} {:?}",
1877 sz,
1878 src1,
1879 src2,
1880 dst
1881 ),
1882 }
1883 Ok(())
1884 }
1885 fn emit_sdiv(
1886 &mut self,
1887 sz: Size,
1888 src1: Location,
1889 src2: Location,
1890 dst: Location,
1891 ) -> Result<(), CompileError> {
1892 match (sz, src1, src2, dst) {
1893 (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1894 dynasm!(self ; sdiv W(dst), W(src1), W(src2));
1895 }
1896 (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {
1897 dynasm!(self ; sdiv X(dst), X(src1), X(src2));
1898 }
1899 _ => codegen_error!(
1900 "singlepass can't emit SDIV {:?} {:?} {:?} {:?}",
1901 sz,
1902 src1,
1903 src2,
1904 dst
1905 ),
1906 }
1907 Ok(())
1908 }
1909
1910 fn emit_msub(
1912 &mut self,
1913 sz: Size,
1914 a: Location,
1915 b: Location,
1916 c: Location,
1917 dst: Location,
1918 ) -> Result<(), CompileError> {
1919 match (sz, a, b, c, dst) {
1920 (
1921 Size::S32,
1922 Location::GPR(a),
1923 Location::GPR(b),
1924 Location::GPR(c),
1925 Location::GPR(dst),
1926 ) => {
1927 dynasm!(self ; msub W(dst), W(a), W(b), W(c));
1928 }
1929 (
1930 Size::S64,
1931 Location::GPR(a),
1932 Location::GPR(b),
1933 Location::GPR(c),
1934 Location::GPR(dst),
1935 ) => {
1936 dynasm!(self ; msub X(dst), X(a), X(b), X(c));
1937 }
1938 _ => codegen_error!(
1939 "singlepass can't emit msub {:?} {:?} {:?} {:?} {:?}",
1940 sz,
1941 a,
1942 b,
1943 c,
1944 dst
1945 ),
1946 }
1947 Ok(())
1948 }
1949
1950 fn emit_sxtb(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1951 match (sz, src, dst) {
1952 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1953 dynasm!(self ; sxtb W(dst), W(src));
1954 }
1955 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1956 dynasm!(self ; sxtb X(dst), W(src));
1957 }
1958 _ => codegen_error!("singlepass can't emit SXTB {:?} {:?} {:?}", sz, src, dst),
1959 }
1960 Ok(())
1961 }
1962 fn emit_sxth(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1963 match (sz, src, dst) {
1964 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1965 dynasm!(self ; sxth W(dst), W(src));
1966 }
1967 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1968 dynasm!(self ; sxth X(dst), W(src));
1969 }
1970 _ => codegen_error!("singlepass can't emit SXTH {:?} {:?} {:?}", sz, src, dst),
1971 }
1972 Ok(())
1973 }
1974 fn emit_sxtw(&mut self, _sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1975 match (src, dst) {
1976 (Location::GPR(src), Location::GPR(dst)) => {
1977 dynasm!(self ; sxtw X(dst), W(src));
1978 }
1979 _ => codegen_error!("singlepass can't emit SXTW {:?} {:?}", src, dst),
1980 }
1981 Ok(())
1982 }
1983 fn emit_uxtb(&mut self, _sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1984 match (src, dst) {
1985 (Location::GPR(src), Location::GPR(dst)) => {
1986 dynasm!(self ; uxtb W(dst), W(src));
1987 }
1988 _ => codegen_error!("singlepass can't emit UXTB {:?} {:?}", src, dst),
1989 }
1990 Ok(())
1991 }
1992 fn emit_uxth(&mut self, _sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1993 match (src, dst) {
1994 (Location::GPR(src), Location::GPR(dst)) => {
1995 dynasm!(self ; uxth W(dst), W(src));
1996 }
1997 _ => codegen_error!("singlepass can't emit UXTH {:?} {:?}", src, dst),
1998 }
1999 Ok(())
2000 }
2001
2002 fn emit_cset(&mut self, sz: Size, dst: Location, cond: Condition) -> Result<(), CompileError> {
2003 match (sz, dst) {
2004 (Size::S32, Location::GPR(reg)) => match cond {
2005 Condition::Eq => dynasm!(self ; cset W(reg), eq),
2006 Condition::Ne => dynasm!(self ; cset W(reg), ne),
2007 Condition::Cs => dynasm!(self ; cset W(reg), cs),
2008 Condition::Cc => dynasm!(self ; cset W(reg), cc),
2009 Condition::Mi => dynasm!(self ; cset W(reg), mi),
2010 Condition::Pl => dynasm!(self ; cset W(reg), pl),
2011 Condition::Vs => dynasm!(self ; cset W(reg), vs),
2012 Condition::Vc => dynasm!(self ; cset W(reg), vc),
2013 Condition::Hi => dynasm!(self ; cset W(reg), hi),
2014 Condition::Ls => dynasm!(self ; cset W(reg), ls),
2015 Condition::Ge => dynasm!(self ; cset W(reg), ge),
2016 Condition::Lt => dynasm!(self ; cset W(reg), lt),
2017 Condition::Gt => dynasm!(self ; cset W(reg), gt),
2018 Condition::Le => dynasm!(self ; cset W(reg), le),
2019 Condition::Al => dynasm!(self ; cset W(reg), al),
2020 },
2021 (Size::S64, Location::GPR(reg)) => match cond {
2022 Condition::Eq => dynasm!(self ; cset X(reg), eq),
2023 Condition::Ne => dynasm!(self ; cset X(reg), ne),
2024 Condition::Cs => dynasm!(self ; cset X(reg), cs),
2025 Condition::Cc => dynasm!(self ; cset X(reg), cc),
2026 Condition::Mi => dynasm!(self ; cset X(reg), mi),
2027 Condition::Pl => dynasm!(self ; cset X(reg), pl),
2028 Condition::Vs => dynasm!(self ; cset X(reg), vs),
2029 Condition::Vc => dynasm!(self ; cset X(reg), vc),
2030 Condition::Hi => dynasm!(self ; cset X(reg), hi),
2031 Condition::Ls => dynasm!(self ; cset X(reg), ls),
2032 Condition::Ge => dynasm!(self ; cset X(reg), ge),
2033 Condition::Lt => dynasm!(self ; cset X(reg), lt),
2034 Condition::Gt => dynasm!(self ; cset X(reg), gt),
2035 Condition::Le => dynasm!(self ; cset X(reg), le),
2036 Condition::Al => dynasm!(self ; cset X(reg), al),
2037 },
2038 _ => codegen_error!("singlepass can't emit CSET {:?} {:?} {:?}", sz, dst, cond),
2039 }
2040 Ok(())
2041 }
2042 fn emit_csetm(&mut self, sz: Size, dst: Location, cond: Condition) -> Result<(), CompileError> {
2043 match (sz, dst) {
2044 (Size::S32, Location::GPR(reg)) => match cond {
2045 Condition::Eq => dynasm!(self ; csetm W(reg), eq),
2046 Condition::Ne => dynasm!(self ; csetm W(reg), ne),
2047 Condition::Cs => dynasm!(self ; csetm W(reg), cs),
2048 Condition::Cc => dynasm!(self ; csetm W(reg), cc),
2049 Condition::Mi => dynasm!(self ; csetm W(reg), mi),
2050 Condition::Pl => dynasm!(self ; csetm W(reg), pl),
2051 Condition::Vs => dynasm!(self ; csetm W(reg), vs),
2052 Condition::Vc => dynasm!(self ; csetm W(reg), vc),
2053 Condition::Hi => dynasm!(self ; csetm W(reg), hi),
2054 Condition::Ls => dynasm!(self ; csetm W(reg), ls),
2055 Condition::Ge => dynasm!(self ; csetm W(reg), ge),
2056 Condition::Lt => dynasm!(self ; csetm W(reg), lt),
2057 Condition::Gt => dynasm!(self ; csetm W(reg), gt),
2058 Condition::Le => dynasm!(self ; csetm W(reg), le),
2059 Condition::Al => dynasm!(self ; csetm W(reg), al),
2060 },
2061 (Size::S64, Location::GPR(reg)) => match cond {
2062 Condition::Eq => dynasm!(self ; csetm X(reg), eq),
2063 Condition::Ne => dynasm!(self ; csetm X(reg), ne),
2064 Condition::Cs => dynasm!(self ; csetm X(reg), cs),
2065 Condition::Cc => dynasm!(self ; csetm X(reg), cc),
2066 Condition::Mi => dynasm!(self ; csetm X(reg), mi),
2067 Condition::Pl => dynasm!(self ; csetm X(reg), pl),
2068 Condition::Vs => dynasm!(self ; csetm X(reg), vs),
2069 Condition::Vc => dynasm!(self ; csetm X(reg), vc),
2070 Condition::Hi => dynasm!(self ; csetm X(reg), hi),
2071 Condition::Ls => dynasm!(self ; csetm X(reg), ls),
2072 Condition::Ge => dynasm!(self ; csetm X(reg), ge),
2073 Condition::Lt => dynasm!(self ; csetm X(reg), lt),
2074 Condition::Gt => dynasm!(self ; csetm X(reg), gt),
2075 Condition::Le => dynasm!(self ; csetm X(reg), le),
2076 Condition::Al => dynasm!(self ; csetm X(reg), al),
2077 },
2078 _ => codegen_error!("singlepass can't emit CSETM {:?} {:?} {:?}", sz, dst, cond),
2079 }
2080 Ok(())
2081 }
2082 fn emit_cinc(
2083 &mut self,
2084 sz: Size,
2085 src: Location,
2086 dst: Location,
2087 cond: Condition,
2088 ) -> Result<(), CompileError> {
2089 match (sz, src, dst) {
2090 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
2091 match cond {
2092 Condition::Eq => dynasm!(self ; cinc W(dst), W(src), eq),
2093 Condition::Ne => dynasm!(self ; cinc W(dst), W(src), ne),
2094 Condition::Cs => dynasm!(self ; cinc W(dst), W(src), cs),
2095 Condition::Cc => dynasm!(self ; cinc W(dst), W(src), cc),
2096 Condition::Mi => dynasm!(self ; cinc W(dst), W(src), mi),
2097 Condition::Pl => dynasm!(self ; cinc W(dst), W(src), pl),
2098 Condition::Vs => dynasm!(self ; cinc W(dst), W(src), vs),
2099 Condition::Vc => dynasm!(self ; cinc W(dst), W(src), vc),
2100 Condition::Hi => dynasm!(self ; cinc W(dst), W(src), hi),
2101 Condition::Ls => dynasm!(self ; cinc W(dst), W(src), ls),
2102 Condition::Ge => dynasm!(self ; cinc W(dst), W(src), ge),
2103 Condition::Lt => dynasm!(self ; cinc W(dst), W(src), lt),
2104 Condition::Gt => dynasm!(self ; cinc W(dst), W(src), gt),
2105 Condition::Le => dynasm!(self ; cinc W(dst), W(src), le),
2106 Condition::Al => dynasm!(self ; cinc W(dst), W(src), al),
2107 };
2108 }
2109 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
2110 match cond {
2111 Condition::Eq => dynasm!(self ; cinc X(src), X(dst), eq),
2112 Condition::Ne => dynasm!(self ; cinc X(src), X(dst), ne),
2113 Condition::Cs => dynasm!(self ; cinc X(src), X(dst), cs),
2114 Condition::Cc => dynasm!(self ; cinc X(src), X(dst), cc),
2115 Condition::Mi => dynasm!(self ; cinc X(src), X(dst), mi),
2116 Condition::Pl => dynasm!(self ; cinc X(src), X(dst), pl),
2117 Condition::Vs => dynasm!(self ; cinc X(src), X(dst), vs),
2118 Condition::Vc => dynasm!(self ; cinc X(src), X(dst), vc),
2119 Condition::Hi => dynasm!(self ; cinc X(src), X(dst), hi),
2120 Condition::Ls => dynasm!(self ; cinc X(src), X(dst), ls),
2121 Condition::Ge => dynasm!(self ; cinc X(src), X(dst), ge),
2122 Condition::Lt => dynasm!(self ; cinc X(src), X(dst), lt),
2123 Condition::Gt => dynasm!(self ; cinc X(src), X(dst), gt),
2124 Condition::Le => dynasm!(self ; cinc X(src), X(dst), le),
2125 Condition::Al => dynasm!(self ; cinc X(src), X(dst), al),
2126 };
2127 }
2128 _ => codegen_error!("singlepass can't emit CINC"),
2129 }
2130 Ok(())
2131 }
2132
2133 fn emit_clz(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2134 match (sz, src, dst) {
2135 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
2136 dynasm!(self ; clz X(dst), X(src));
2137 }
2138 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
2139 dynasm!(self ; clz W(dst), W(src));
2140 }
2141 _ => codegen_error!("singlepass can't emit CLS {:?} {:?} {:?}", sz, src, dst),
2142 }
2143 Ok(())
2144 }
2145 fn emit_rbit(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2146 match (sz, src, dst) {
2147 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
2148 dynasm!(self ; rbit X(dst), X(src));
2149 }
2150 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
2151 dynasm!(self ; rbit W(dst), W(src));
2152 }
2153 _ => codegen_error!("singlepass can't emit CLS {:?} {:?} {:?}", sz, src, dst),
2154 }
2155 Ok(())
2156 }
2157
2158 fn emit_label(&mut self, label: Label) -> Result<(), CompileError> {
2159 dynasm!(self ; => label);
2160 Ok(())
2161 }
2162 fn emit_load_label(&mut self, reg: GPR, label: Label) -> Result<(), CompileError> {
2163 dynasm!(self ; adr X(reg), =>label);
2164 Ok(())
2165 }
2166
2167 fn emit_b_label(&mut self, label: Label) -> Result<(), CompileError> {
2168 dynasm!(self ; b =>label);
2169 Ok(())
2170 }
2171 fn emit_cbz_label(
2172 &mut self,
2173 sz: Size,
2174 reg: Location,
2175 label: Label,
2176 ) -> Result<(), CompileError> {
2177 match (sz, reg) {
2178 (Size::S32, Location::GPR(reg)) => {
2179 dynasm!(self ; cbz W(reg), =>label);
2180 }
2181 (Size::S64, Location::GPR(reg)) => {
2182 dynasm!(self ; cbz X(reg), =>label);
2183 }
2184 _ => codegen_error!("singlepass can't emit CBZ {:?} {:?} {:?}", sz, reg, label),
2185 }
2186 Ok(())
2187 }
2188 fn emit_cbnz_label(
2189 &mut self,
2190 sz: Size,
2191 reg: Location,
2192 label: Label,
2193 ) -> Result<(), CompileError> {
2194 match (sz, reg) {
2195 (Size::S32, Location::GPR(reg)) => {
2196 dynasm!(self ; cbnz W(reg), =>label);
2197 }
2198 (Size::S64, Location::GPR(reg)) => {
2199 dynasm!(self ; cbnz X(reg), =>label);
2200 }
2201 _ => codegen_error!("singlepass can't emit CBNZ {:?} {:?} {:?}", sz, reg, label),
2202 }
2203 Ok(())
2204 }
2205 fn emit_cbz_label_far(
2206 &mut self,
2207 sz: Size,
2208 reg: Location,
2209 label: Label,
2210 ) -> Result<(), CompileError> {
2211 let near_label: Label = self.get_label();
2212 let continue_label: Label = self.get_label();
2213
2214 match (sz, reg) {
2215 (Size::S32, Location::GPR(reg)) => {
2216 dynasm!(self ; cbz W(reg), => near_label);
2217 dynasm!(self ; b => continue_label);
2218 }
2219 (Size::S64, Location::GPR(reg)) => {
2220 dynasm!(self ; cbz X(reg), => near_label);
2221 dynasm!(self ; b => continue_label);
2222 }
2223 _ => codegen_error!("singlepass can't emit CBZ {:?} {:?} {:?}", sz, reg, label),
2224 }
2225 self.emit_label(near_label)?;
2226 dynasm!(self ; b => label );
2227
2228 self.emit_label(continue_label)?;
2229
2230 Ok(())
2231 }
2232 fn emit_tbz_label(
2233 &mut self,
2234 sz: Size,
2235 reg: Location,
2236 n: u32,
2237 label: Label,
2238 ) -> Result<(), CompileError> {
2239 match (sz, reg) {
2240 (Size::S32, Location::GPR(reg)) => {
2241 dynasm!(self ; tbz W(reg), n, =>label);
2242 }
2243 (Size::S64, Location::GPR(reg)) => {
2244 dynasm!(self ; tbz X(reg), n, =>label);
2245 }
2246 _ => codegen_error!(
2247 "singlepass can't emit TBZ {:?} {:?} {:?} {:?}",
2248 sz,
2249 reg,
2250 n,
2251 label
2252 ),
2253 }
2254 Ok(())
2255 }
2256 fn emit_tbnz_label(
2257 &mut self,
2258 sz: Size,
2259 reg: Location,
2260 n: u32,
2261 label: Label,
2262 ) -> Result<(), CompileError> {
2263 match (sz, reg) {
2264 (Size::S32, Location::GPR(reg)) => {
2265 dynasm!(self ; tbnz W(reg), n, =>label);
2266 }
2267 (Size::S64, Location::GPR(reg)) => {
2268 dynasm!(self ; tbnz X(reg), n, =>label);
2269 }
2270 _ => codegen_error!(
2271 "singlepass can't emit TBNZ {:?} {:?} {:?} {:?}",
2272 sz,
2273 reg,
2274 n,
2275 label
2276 ),
2277 }
2278 Ok(())
2279 }
2280 fn emit_bcond_label(&mut self, condition: Condition, label: Label) -> Result<(), CompileError> {
2281 match condition {
2282 Condition::Eq => dynasm!(self ; b.eq => label),
2283 Condition::Ne => dynasm!(self ; b.ne => label),
2284 Condition::Cs => dynasm!(self ; b.cs => label),
2285 Condition::Cc => dynasm!(self ; b.cc => label),
2286 Condition::Mi => dynasm!(self ; b.mi => label),
2287 Condition::Pl => dynasm!(self ; b.pl => label),
2288 Condition::Vs => dynasm!(self ; b.vs => label),
2289 Condition::Vc => dynasm!(self ; b.vc => label),
2290 Condition::Hi => dynasm!(self ; b.hi => label),
2291 Condition::Ls => dynasm!(self ; b.ls => label),
2292 Condition::Ge => dynasm!(self ; b.ge => label),
2293 Condition::Lt => dynasm!(self ; b.lt => label),
2294 Condition::Gt => dynasm!(self ; b.gt => label),
2295 Condition::Le => dynasm!(self ; b.le => label),
2296 Condition::Al => dynasm!(self ; b => label),
2297 }
2298 Ok(())
2299 }
2300 fn emit_bcond_label_far(
2301 &mut self,
2302 condition: Condition,
2303 label: Label,
2304 ) -> Result<(), CompileError> {
2305 let cont: Label = self.get_label();
2306 match condition {
2307 Condition::Eq => dynasm!(self ; b.ne => cont),
2309 Condition::Ne => dynasm!(self ; b.eq => cont),
2310 Condition::Cs => dynasm!(self ; b.cc => cont),
2311 Condition::Cc => dynasm!(self ; b.cs => cont),
2312 Condition::Mi => dynasm!(self ; b.pl => cont),
2313 Condition::Pl => dynasm!(self ; b.mi => cont),
2314 Condition::Vs => dynasm!(self ; b.vc => cont),
2315 Condition::Vc => dynasm!(self ; b.vs => cont),
2316 Condition::Hi => dynasm!(self ; b.ls => cont),
2317 Condition::Ls => dynasm!(self ; b.hi => cont),
2318 Condition::Ge => dynasm!(self ; b.lt => cont),
2319 Condition::Lt => dynasm!(self ; b.ge => cont),
2320 Condition::Gt => dynasm!(self ; b.le => cont),
2321 Condition::Le => dynasm!(self ; b.gt => cont),
2322 Condition::Al => { }
2323 }
2324 dynasm!(self ; b => label);
2325 self.emit_label(cont)?;
2326 Ok(())
2327 }
2328 fn emit_b_register(&mut self, reg: GPR) -> Result<(), CompileError> {
2329 dynasm!(self ; br X(reg));
2330 Ok(())
2331 }
2332 fn emit_call_label(&mut self, label: Label) -> Result<(), CompileError> {
2333 dynasm!(self ; bl =>label);
2334 Ok(())
2335 }
2336 fn emit_call_register(&mut self, reg: GPR) -> Result<(), CompileError> {
2337 dynasm!(self ; blr X(reg));
2338 Ok(())
2339 }
2340 fn emit_ret(&mut self) -> Result<(), CompileError> {
2341 dynasm!(self ; ret);
2342 Ok(())
2343 }
2344
2345 fn emit_udf(&mut self, payload: u16) -> Result<(), CompileError> {
2346 dynasm!(self ; udf payload as u32);
2347 Ok(())
2348 }
2349 fn emit_dmb(&mut self) -> Result<(), CompileError> {
2350 dynasm!(self ; dmb ish);
2351 Ok(())
2352 }
2353 fn emit_brk(&mut self) -> Result<(), CompileError> {
2354 dynasm!(self ; brk 0);
2355 Ok(())
2356 }
2357
2358 fn emit_fcmp(&mut self, sz: Size, src1: Location, src2: Location) -> Result<(), CompileError> {
2359 match (sz, src1, src2) {
2360 (Size::S32, Location::SIMD(src1), Location::SIMD(src2)) => {
2361 dynasm!(self ; fcmp S(src1), S(src2));
2362 }
2363 (Size::S64, Location::SIMD(src1), Location::SIMD(src2)) => {
2364 dynasm!(self ; fcmp D(src1), D(src2));
2365 }
2366 _ => codegen_error!("singlepass can't emit FCMP {:?} {:?} {:?}", sz, src1, src2),
2367 }
2368 Ok(())
2369 }
2370
2371 fn emit_fneg(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2372 match (sz, src, dst) {
2373 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2374 dynasm!(self ; fneg S(dst), S(src));
2375 }
2376 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2377 dynasm!(self ; fneg D(dst), D(src));
2378 }
2379 _ => codegen_error!("singlepass can't emit FNEG {:?} {:?} {:?}", sz, src, dst),
2380 }
2381 Ok(())
2382 }
2383 fn emit_fsqrt(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2384 match (sz, src, dst) {
2385 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2386 dynasm!(self ; fsqrt S(dst), S(src));
2387 }
2388 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2389 dynasm!(self ; fsqrt D(dst), D(src));
2390 }
2391 _ => codegen_error!("singlepass can't emit FSQRT {:?} {:?} {:?}", sz, src, dst),
2392 }
2393 Ok(())
2394 }
2395
2396 fn emit_fadd(
2397 &mut self,
2398 sz: Size,
2399 src1: Location,
2400 src2: Location,
2401 dst: Location,
2402 ) -> Result<(), CompileError> {
2403 match (sz, src1, src2, dst) {
2404 (Size::S32, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2405 dynasm!(self ; fadd S(dst), S(src1), S(src2));
2406 }
2407 (Size::S64, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2408 dynasm!(self ; fadd D(dst), D(src1), D(src2));
2409 }
2410 _ => codegen_error!(
2411 "singlepass can't emit FADD {:?} {:?} {:?} {:?}",
2412 sz,
2413 src1,
2414 src2,
2415 dst
2416 ),
2417 }
2418 Ok(())
2419 }
2420 fn emit_fsub(
2421 &mut self,
2422 sz: Size,
2423 src1: Location,
2424 src2: Location,
2425 dst: Location,
2426 ) -> Result<(), CompileError> {
2427 match (sz, src1, src2, dst) {
2428 (Size::S32, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2429 dynasm!(self ; fsub S(dst), S(src1), S(src2));
2430 }
2431 (Size::S64, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2432 dynasm!(self ; fsub D(dst), D(src1), D(src2));
2433 }
2434 _ => codegen_error!(
2435 "singlepass can't emit FSUB {:?} {:?} {:?} {:?}",
2436 sz,
2437 src1,
2438 src2,
2439 dst
2440 ),
2441 }
2442 Ok(())
2443 }
2444 fn emit_fmul(
2445 &mut self,
2446 sz: Size,
2447 src1: Location,
2448 src2: Location,
2449 dst: Location,
2450 ) -> Result<(), CompileError> {
2451 match (sz, src1, src2, dst) {
2452 (Size::S32, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2453 dynasm!(self ; fmul S(dst), S(src1), S(src2));
2454 }
2455 (Size::S64, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2456 dynasm!(self ; fmul D(dst), D(src1), D(src2));
2457 }
2458 _ => codegen_error!(
2459 "singlepass can't emit FMUL {:?} {:?} {:?} {:?}",
2460 sz,
2461 src1,
2462 src2,
2463 dst
2464 ),
2465 }
2466 Ok(())
2467 }
2468 fn emit_fdiv(
2469 &mut self,
2470 sz: Size,
2471 src1: Location,
2472 src2: Location,
2473 dst: Location,
2474 ) -> Result<(), CompileError> {
2475 match (sz, src1, src2, dst) {
2476 (Size::S32, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2477 dynasm!(self ; fdiv S(dst), S(src1), S(src2));
2478 }
2479 (Size::S64, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2480 dynasm!(self ; fdiv D(dst), D(src1), D(src2));
2481 }
2482 _ => codegen_error!(
2483 "singlepass can't emit FDIV {:?} {:?} {:?} {:?}",
2484 sz,
2485 src1,
2486 src2,
2487 dst
2488 ),
2489 }
2490 Ok(())
2491 }
2492
2493 fn emit_fmin(
2494 &mut self,
2495 sz: Size,
2496 src1: Location,
2497 src2: Location,
2498 dst: Location,
2499 ) -> Result<(), CompileError> {
2500 match (sz, src1, src2, dst) {
2501 (Size::S32, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2502 dynasm!(self ; fmin S(dst), S(src1), S(src2));
2503 }
2504 (Size::S64, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2505 dynasm!(self ; fmin D(dst), D(src1), D(src2));
2506 }
2507 _ => codegen_error!(
2508 "singlepass can't emit FMIN {:?} {:?} {:?} {:?}",
2509 sz,
2510 src1,
2511 src2,
2512 dst
2513 ),
2514 }
2515 Ok(())
2516 }
2517 fn emit_fmax(
2518 &mut self,
2519 sz: Size,
2520 src1: Location,
2521 src2: Location,
2522 dst: Location,
2523 ) -> Result<(), CompileError> {
2524 match (sz, src1, src2, dst) {
2525 (Size::S32, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2526 dynasm!(self ; fmax S(dst), S(src1), S(src2));
2527 }
2528 (Size::S64, Location::SIMD(src1), Location::SIMD(src2), Location::SIMD(dst)) => {
2529 dynasm!(self ; fmax D(dst), D(src1), D(src2));
2530 }
2531 _ => codegen_error!(
2532 "singlepass can't emit FMAX {:?} {:?} {:?} {:?}",
2533 sz,
2534 src1,
2535 src2,
2536 dst
2537 ),
2538 }
2539 Ok(())
2540 }
2541
2542 fn emit_frintz(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2543 match (sz, src, dst) {
2544 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2545 dynasm!(self ; frintz S(dst), S(src));
2546 }
2547 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2548 dynasm!(self ; frintz D(dst), D(src));
2549 }
2550 _ => codegen_error!("singlepass can't emit FRINTZ {:?} {:?} {:?}", sz, src, dst),
2551 }
2552 Ok(())
2553 }
2554 fn emit_frintn(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2555 match (sz, src, dst) {
2556 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2557 dynasm!(self ; frintn S(dst), S(src));
2558 }
2559 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2560 dynasm!(self ; frintn D(dst), D(src));
2561 }
2562 _ => codegen_error!("singlepass can't emit FRINTN {:?} {:?} {:?}", sz, src, dst),
2563 }
2564 Ok(())
2565 }
2566 fn emit_frintm(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2567 match (sz, src, dst) {
2568 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2569 dynasm!(self ; frintm S(dst), S(src));
2570 }
2571 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2572 dynasm!(self ; frintm D(dst), D(src));
2573 }
2574 _ => codegen_error!("singlepass can't emit FRINTM {:?} {:?} {:?}", sz, src, dst),
2575 }
2576 Ok(())
2577 }
2578 fn emit_frintp(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2579 match (sz, src, dst) {
2580 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2581 dynasm!(self ; frintp S(dst), S(src));
2582 }
2583 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2584 dynasm!(self ; frintp D(dst), D(src));
2585 }
2586 _ => codegen_error!("singlepass can't emit FRINTP {:?} {:?} {:?}", sz, src, dst),
2587 }
2588 Ok(())
2589 }
2590
2591 fn emit_scvtf(
2592 &mut self,
2593 sz_in: Size,
2594 src: Location,
2595 sz_out: Size,
2596 dst: Location,
2597 ) -> Result<(), CompileError> {
2598 match (sz_in, src, sz_out, dst) {
2599 (Size::S32, Location::GPR(src), Size::S32, Location::SIMD(dst)) => {
2600 dynasm!(self ; scvtf S(dst), W(src));
2601 }
2602 (Size::S64, Location::GPR(src), Size::S32, Location::SIMD(dst)) => {
2603 dynasm!(self ; scvtf S(dst), X(src));
2604 }
2605 (Size::S32, Location::GPR(src), Size::S64, Location::SIMD(dst)) => {
2606 dynasm!(self ; scvtf D(dst), W(src));
2607 }
2608 (Size::S64, Location::GPR(src), Size::S64, Location::SIMD(dst)) => {
2609 dynasm!(self ; scvtf D(dst), X(src));
2610 }
2611 _ => codegen_error!(
2612 "singlepass can't emit SCVTF {:?} {:?} {:?} {:?}",
2613 sz_in,
2614 src,
2615 sz_out,
2616 dst
2617 ),
2618 }
2619 Ok(())
2620 }
2621 fn emit_ucvtf(
2622 &mut self,
2623 sz_in: Size,
2624 src: Location,
2625 sz_out: Size,
2626 dst: Location,
2627 ) -> Result<(), CompileError> {
2628 match (sz_in, src, sz_out, dst) {
2629 (Size::S32, Location::GPR(src), Size::S32, Location::SIMD(dst)) => {
2630 dynasm!(self ; ucvtf S(dst), W(src));
2631 }
2632 (Size::S64, Location::GPR(src), Size::S32, Location::SIMD(dst)) => {
2633 dynasm!(self ; ucvtf S(dst), X(src));
2634 }
2635 (Size::S32, Location::GPR(src), Size::S64, Location::SIMD(dst)) => {
2636 dynasm!(self ; ucvtf D(dst), W(src));
2637 }
2638 (Size::S64, Location::GPR(src), Size::S64, Location::SIMD(dst)) => {
2639 dynasm!(self ; ucvtf D(dst), X(src));
2640 }
2641 _ => codegen_error!(
2642 "singlepass can't emit UCVTF {:?} {:?} {:?} {:?}",
2643 sz_in,
2644 src,
2645 sz_out,
2646 dst
2647 ),
2648 }
2649 Ok(())
2650 }
2651 fn emit_fcvt(&mut self, sz_in: Size, src: Location, dst: Location) -> Result<(), CompileError> {
2652 match (sz_in, src, dst) {
2653 (Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
2654 dynasm!(self ; fcvt D(dst), S(src));
2655 }
2656 (Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
2657 dynasm!(self ; fcvt S(dst), D(src));
2658 }
2659 _ => codegen_error!(
2660 "singlepass can't emit UCVTF {:?} {:?} {:?}",
2661 sz_in,
2662 src,
2663 dst
2664 ),
2665 }
2666 Ok(())
2667 }
2668 fn emit_fcvtzs(
2669 &mut self,
2670 sz_in: Size,
2671 src: Location,
2672 sz_out: Size,
2673 dst: Location,
2674 ) -> Result<(), CompileError> {
2675 match (sz_in, src, sz_out, dst) {
2676 (Size::S32, Location::SIMD(src), Size::S32, Location::GPR(dst)) => {
2677 dynasm!(self ; fcvtzs W(dst), S(src));
2678 }
2679 (Size::S64, Location::SIMD(src), Size::S32, Location::GPR(dst)) => {
2680 dynasm!(self ; fcvtzs W(dst), D(src));
2681 }
2682 (Size::S32, Location::SIMD(src), Size::S64, Location::GPR(dst)) => {
2683 dynasm!(self ; fcvtzs X(dst), S(src));
2684 }
2685 (Size::S64, Location::SIMD(src), Size::S64, Location::GPR(dst)) => {
2686 dynasm!(self ; fcvtzs X(dst), D(src));
2687 }
2688 _ => codegen_error!(
2689 "singlepass can't emit FCVTZS {:?} {:?} {:?} {:?}",
2690 sz_in,
2691 src,
2692 sz_out,
2693 dst
2694 ),
2695 }
2696 Ok(())
2697 }
2698 fn emit_fcvtzu(
2699 &mut self,
2700 sz_in: Size,
2701 src: Location,
2702 sz_out: Size,
2703 dst: Location,
2704 ) -> Result<(), CompileError> {
2705 match (sz_in, src, sz_out, dst) {
2706 (Size::S32, Location::SIMD(src), Size::S32, Location::GPR(dst)) => {
2707 dynasm!(self ; fcvtzu W(dst), S(src));
2708 }
2709 (Size::S64, Location::SIMD(src), Size::S32, Location::GPR(dst)) => {
2710 dynasm!(self ; fcvtzu W(dst), D(src));
2711 }
2712 (Size::S32, Location::SIMD(src), Size::S64, Location::GPR(dst)) => {
2713 dynasm!(self ; fcvtzu X(dst), S(src));
2714 }
2715 (Size::S64, Location::SIMD(src), Size::S64, Location::GPR(dst)) => {
2716 dynasm!(self ; fcvtzu X(dst), D(src));
2717 }
2718 _ => codegen_error!(
2719 "singlepass can't emit FCVTZU {:?} {:?} {:?} {:?}",
2720 sz_in,
2721 src,
2722 sz_out,
2723 dst
2724 ),
2725 }
2726 Ok(())
2727 }
2728
2729 fn emit_read_fpcr(&mut self, reg: GPR) -> Result<(), CompileError> {
2731 dynasm!(self ; mrs X(reg), 0b1_011_0100_0100_000);
2732 Ok(())
2733 }
2734 fn emit_write_fpcr(&mut self, reg: GPR) -> Result<(), CompileError> {
2735 dynasm!(self ; msr 0b1_011_0100_0100_000, X(reg));
2736 Ok(())
2737 }
2738 fn emit_read_fpsr(&mut self, reg: GPR) -> Result<(), CompileError> {
2740 dynasm!(self ; mrs X(reg), 0b1_011_0100_0100_001);
2741 Ok(())
2742 }
2743 fn emit_write_fpsr(&mut self, reg: GPR) -> Result<(), CompileError> {
2744 dynasm!(self ; msr 0b1_011_0100_0100_001, X(reg));
2745 Ok(())
2746 }
2747
2748 fn emit_cnt(&mut self, src: NEON, dst: NEON) -> Result<(), CompileError> {
2749 dynasm!(self ; cnt V(dst).B8, V(src).B8);
2750 Ok(())
2751 }
2752
2753 fn emit_addv(&mut self, src: NEON, dst: NEON) -> Result<(), CompileError> {
2754 dynasm!(self ; addv B(dst), V(src).B8);
2755 Ok(())
2756 }
2757
2758 #[allow(clippy::unit_arg)]
2759 fn emit_fmov(
2760 &mut self,
2761 src_size: Size,
2762 src: Location,
2763 dst_size: Size,
2764 dst: Location,
2765 ) -> Result<(), CompileError> {
2766 let mut err = false;
2767 match (src, dst) {
2768 (AbstractLocation::GPR(src), AbstractLocation::SIMD(dst)) => {
2769 match (src_size, dst_size) {
2770 (Size::S32, Size::S32) => dynasm!(self ; fmov S(dst), W(src)),
2771 (Size::S64, Size::S64) => dynasm!(self ; fmov D(dst), X(src)),
2772 _ => {
2773 err = true;
2774 }
2775 }
2776 }
2777 (AbstractLocation::SIMD(src), AbstractLocation::GPR(dst)) => {
2778 match (src_size, dst_size) {
2779 (Size::S32, Size::S32) => dynasm!(self ; fmov W(dst), S(src)),
2780 (Size::S64, Size::S64) => dynasm!(self ; fmov X(dst), D(src)),
2781 _ => {
2782 err = true;
2783 }
2784 }
2785 }
2786 _ => {
2790 err = true;
2791 }
2792 };
2793
2794 if err {
2795 codegen_error!(
2796 "singlepass can't generate fmov instruction for src_size: {:?}, src: {:?}, dst_size: {:?}, dst: {:?}",
2797 src_size,
2798 src,
2799 dst_size,
2800 dst,
2801 )
2802 }
2803 Ok(())
2804 }
2805}
2806
2807pub fn gen_std_trampoline_arm64(
2808 sig: &FunctionType,
2809 calling_convention: CallingConvention,
2810 progress_callback: Option<&CompilationProgressCallback>,
2811) -> Result<FunctionBody, CompileError> {
2812 let mut a = Assembler::new(0);
2813 let mut output_reporter = ChunkedOutputReporter::new(progress_callback);
2814
2815 let fptr = GPR::X27;
2816 let args = GPR::X28;
2817
2818 dynasm!(a
2819 ; sub sp, sp, 32
2820 ; stp x29, x30, [sp]
2821 ; stp X(fptr), X(args), [sp, 16]
2822 ; mov x29, sp
2823 ; mov X(fptr), x1
2824 ; mov X(args), x2
2825 );
2826
2827 let stack_args = sig.params().len().saturating_sub(7); let stack_return_slots = sig
2829 .results()
2830 .len()
2831 .saturating_sub(ARM64_RETURN_VALUE_REGISTERS.len());
2832 let mut stack_offset = (stack_args + stack_return_slots) as u32 * 8;
2833 if stack_offset > 0 {
2834 if !stack_offset.is_multiple_of(16) {
2835 stack_offset += 8;
2836 assert!(stack_offset.is_multiple_of(16));
2837 }
2838 if stack_offset < 0x1000 {
2839 dynasm!(a ; sub sp, sp, stack_offset);
2840 } else {
2841 a.emit_mov_imm(Location::GPR(GPR::X26), stack_offset as u64)?;
2842 dynasm!(a ; sub sp, sp, x26);
2843 }
2844 }
2845
2846 let mut caller_stack_offset = stack_return_slots as u32 * 8;
2849 for (i, param) in sig.params().iter().enumerate() {
2850 let sz = match *param {
2851 Type::I32 | Type::F32 => Size::S32,
2852 Type::I64 | Type::F64 => Size::S64,
2853 Type::ExternRef => Size::S64,
2854 Type::FuncRef => Size::S64,
2855 _ => codegen_error!(
2856 "singlepass unsupported param type for trampoline {:?}",
2857 *param
2858 ),
2859 };
2860 match i {
2861 0..=6 => {
2862 a.emit_ldr(
2863 sz,
2864 Location::GPR(GPR::from_index(i + 1).unwrap()),
2865 Location::Memory(args, (i * 16) as i32),
2866 )?;
2867 }
2868 _ => {
2869 #[allow(clippy::single_match)]
2870 match calling_convention {
2871 CallingConvention::AppleAarch64 => {
2872 caller_stack_offset = caller_stack_offset.next_multiple_of(sz.bytes());
2874 }
2875 _ => (),
2876 };
2877 a.emit_ldr(
2879 sz,
2880 Location::GPR(GPR::X16),
2881 Location::Memory(args, (i * 16) as i32),
2882 )?;
2883 a.emit_str(
2884 sz,
2885 Location::GPR(GPR::X16),
2886 Location::Memory(GPR::XzrSp, caller_stack_offset as _),
2887 )?;
2888 match calling_convention {
2889 CallingConvention::AppleAarch64 => {
2890 caller_stack_offset += sz.bytes();
2891 }
2892 _ => {
2893 caller_stack_offset += 8;
2894 }
2895 }
2896 }
2897 }
2898 output_reporter.check(a.offset().0)?;
2899 }
2900
2901 dynasm!(a ; blr X(fptr));
2902
2903 let mut n_stack_return_slots: usize = 0;
2905 for i in 0..sig.results().len() {
2906 let src = if let Some(®) = ARM64_RETURN_VALUE_REGISTERS.get(i) {
2907 reg
2908 } else {
2909 let loc = GPR::X16;
2910 a.emit_ldr(
2911 Size::S64,
2912 Location::GPR(GPR::X16),
2913 Location::Memory(GPR::XzrSp, (n_stack_return_slots as u32 * 8) as _),
2914 )?;
2915 n_stack_return_slots += 1;
2916 loc
2917 };
2918 a.emit_str(
2919 Size::S64,
2920 Location::GPR(src),
2921 Location::Memory(args, (i * 16) as _),
2922 )?;
2923 output_reporter.check(a.offset().0)?;
2924 }
2925
2926 dynasm!(a
2928 ; ldp X(fptr), X(args), [x29, 16]
2929 ; ldp x29, x30, [x29]
2930 );
2931 let restored_stack_offset = 32 + stack_offset;
2932 if restored_stack_offset < 0x1000 {
2933 dynasm!(a; add sp, sp, restored_stack_offset);
2934 } else {
2935 a.emit_mov_imm(Location::GPR(GPR::X26), restored_stack_offset as u64)?;
2936 dynasm!(a; add sp, sp, x26);
2937 }
2938 dynasm!(a; ret);
2939
2940 let mut body = a.finalize().unwrap();
2941 body.shrink_to_fit();
2942 output_reporter.finish(body.len())?;
2943 Ok(FunctionBody {
2944 body,
2945 unwind_info: None,
2946 })
2947}
2948pub fn gen_std_dynamic_import_trampoline_arm64(
2950 vmoffsets: &VMOffsets,
2951 sig: &FunctionType,
2952 calling_convention: CallingConvention,
2953 progress_callback: Option<&CompilationProgressCallback>,
2954) -> Result<FunctionBody, CompileError> {
2955 let mut a = Assembler::new(0);
2956 let mut output_reporter = ChunkedOutputReporter::new(progress_callback);
2957 let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len());
2959 a.emit_stpdb(
2961 Size::S64,
2962 Location::GPR(GPR::X30),
2963 Location::GPR(GPR::X26),
2964 GPR::XzrSp,
2965 16,
2966 )?;
2967
2968 if stack_offset != 0 {
2969 if stack_offset < 0x1000 {
2970 a.emit_sub(
2971 Size::S64,
2972 Location::GPR(GPR::XzrSp),
2973 Location::Imm32(stack_offset as _),
2974 Location::GPR(GPR::XzrSp),
2975 )?;
2976 } else {
2977 a.emit_mov_imm(Location::GPR(GPR::X26), stack_offset as u64)?;
2978 a.emit_sub(
2979 Size::S64,
2980 Location::GPR(GPR::XzrSp),
2981 Location::GPR(GPR::X26),
2982 Location::GPR(GPR::XzrSp),
2983 )?;
2984 }
2985 }
2986
2987 if !sig.params().is_empty() {
2989 let mut argalloc = ArgumentRegisterAllocator::default();
2990 argalloc.next(Type::I64, calling_convention).unwrap(); let mut stack_param_count: usize = 0;
2993
2994 for (i, ty) in sig.params().iter().enumerate() {
2995 let source_loc = match argalloc.next(*ty, calling_convention)? {
2996 Some(ARM64Register::GPR(gpr)) => Location::GPR(gpr),
2997 Some(ARM64Register::NEON(neon)) => Location::SIMD(neon),
2998 None => {
2999 let sz = match calling_convention {
3000 CallingConvention::AppleAarch64 => match *ty {
3001 Type::I32 | Type::F32 => Size::S32,
3002 _ => {
3003 stack_param_count = stack_param_count.next_multiple_of(8);
3004 Size::S64
3005 }
3006 },
3007 _ => Size::S64,
3008 };
3009 a.emit_ldr(
3010 sz,
3011 Location::GPR(GPR::X26),
3012 Location::Memory(GPR::XzrSp, (stack_offset + 16 + stack_param_count) as _),
3013 )?;
3014 stack_param_count += match sz {
3015 Size::S32 => 4,
3016 Size::S64 => 8,
3017 _ => codegen_error!(
3018 "singlepass unreachable in gen_std_dynamic_import_trampoline_arm64"
3019 ),
3020 };
3021 Location::GPR(GPR::X26)
3022 }
3023 };
3024 a.emit_str(
3025 Size::S64,
3026 source_loc,
3027 Location::Memory(GPR::XzrSp, (i * 16) as _),
3028 )?;
3029
3030 a.emit_str(
3032 Size::S64,
3033 Location::GPR(GPR::XzrSp), Location::Memory(GPR::XzrSp, (i * 16 + 8) as _), )?;
3036 output_reporter.check(a.offset().0)?;
3037 }
3038 }
3039
3040 #[allow(clippy::match_single_binding)]
3041 match calling_convention {
3042 _ => {
3043 let offset = vmoffsets.vmdynamicfunction_import_context_address();
3045 a.emit_ldur(Size::S64, Location::GPR(GPR::X26), GPR::X0, offset as i32)?;
3046 a.emit_add(
3048 Size::S64,
3049 Location::GPR(GPR::XzrSp),
3050 Location::Imm8(0),
3051 Location::GPR(GPR::X1),
3052 )?;
3053 }
3054 };
3055
3056 a.emit_call_register(GPR::X26)?;
3058
3059 if !sig.results().is_empty() {
3061 assert_eq!(sig.results().len(), 1);
3062 a.emit_ldr(
3063 Size::S64,
3064 Location::GPR(GPR::X0),
3065 Location::Memory(GPR::XzrSp, 0),
3066 )?;
3067 }
3068
3069 if stack_offset != 0 {
3071 if stack_offset < 0x1000 {
3072 a.emit_add(
3073 Size::S64,
3074 Location::GPR(GPR::XzrSp),
3075 Location::Imm32(stack_offset as _),
3076 Location::GPR(GPR::XzrSp),
3077 )?;
3078 } else {
3079 a.emit_mov_imm(Location::GPR(GPR::X26), stack_offset as u64)?;
3080 a.emit_add(
3081 Size::S64,
3082 Location::GPR(GPR::XzrSp),
3083 Location::GPR(GPR::X26),
3084 Location::GPR(GPR::XzrSp),
3085 )?;
3086 }
3087 }
3088 a.emit_ldpia(
3089 Size::S64,
3090 Location::GPR(GPR::X30),
3091 Location::GPR(GPR::X26),
3092 GPR::XzrSp,
3093 16,
3094 )?;
3095
3096 a.emit_ret()?;
3098
3099 let mut body = a.finalize().unwrap();
3100 body.shrink_to_fit();
3101 output_reporter.finish(body.len())?;
3102 Ok(FunctionBody {
3103 body,
3104 unwind_info: None,
3105 })
3106}
3107pub fn gen_import_call_trampoline_arm64(
3109 vmoffsets: &VMOffsets,
3110 index: FunctionIndex,
3111 sig: &FunctionType,
3112 calling_convention: CallingConvention,
3113 progress_callback: Option<&CompilationProgressCallback>,
3114) -> Result<CustomSection, CompileError> {
3115 let mut a = Assembler::new(0);
3116 let mut output_reporter = ChunkedOutputReporter::new(progress_callback);
3117
3118 if sig
3123 .params()
3124 .iter()
3125 .any(|&x| x == Type::F32 || x == Type::F64)
3126 {
3127 #[allow(clippy::match_single_binding)]
3128 match calling_convention {
3129 _ => {
3130 let mut stack_offset: u32 = if sig.params().len() > 7 {
3132 7 * 8
3133 } else {
3134 (sig.params().len() as u32) * 8
3135 };
3136 stack_offset = stack_offset.next_multiple_of(16);
3137 if stack_offset != 0 {
3138 if stack_offset < 0x1000 {
3139 a.emit_sub(
3140 Size::S64,
3141 Location::GPR(GPR::XzrSp),
3142 Location::Imm32(stack_offset as u32),
3143 Location::GPR(GPR::XzrSp),
3144 )?;
3145 } else {
3146 a.emit_mov_imm(Location::GPR(GPR::X16), stack_offset as u64)?;
3147 a.emit_sub(
3148 Size::S64,
3149 Location::GPR(GPR::XzrSp),
3150 Location::GPR(GPR::X16),
3151 Location::GPR(GPR::XzrSp),
3152 )?;
3153 }
3154 }
3155
3156 static PARAM_REGS: &[GPR] = &[
3158 GPR::X1,
3159 GPR::X2,
3160 GPR::X3,
3161 GPR::X4,
3162 GPR::X5,
3163 GPR::X6,
3164 GPR::X7,
3165 ];
3166 let mut param_locations = vec![];
3167 for (i, param_reg) in PARAM_REGS.iter().enumerate().take(sig.params().len()) {
3168 let loc = match i {
3169 0..=6 => {
3170 let loc = Location::Memory(GPR::XzrSp, (i * 8) as i32);
3171 a.emit_str(Size::S64, Location::GPR(*param_reg), loc)?;
3172 loc
3173 }
3174 _ => {
3175 Location::Memory(GPR::XzrSp, (stack_offset + (i as u32 - 7) * 8) as i32)
3176 }
3177 };
3178 param_locations.push(loc);
3179 output_reporter.check(a.offset().0)?;
3180 }
3181
3182 let mut caller_stack_offset: u32 = 0;
3184 let mut argalloc = ArgumentRegisterAllocator::default();
3185 argalloc.next(Type::I64, calling_convention).unwrap(); for (i, ty) in sig.params().iter().enumerate() {
3187 let prev_loc = param_locations[i];
3188 let targ = match argalloc.next(*ty, calling_convention)? {
3189 Some(ARM64Register::GPR(gpr)) => Location::GPR(gpr),
3190 Some(ARM64Register::NEON(neon)) => Location::SIMD(neon),
3191 None => {
3192 a.emit_ldr(Size::S64, Location::GPR(GPR::X16), prev_loc)?;
3194 a.emit_str(
3195 Size::S64,
3196 Location::GPR(GPR::X16),
3197 Location::Memory(
3198 GPR::XzrSp,
3199 (stack_offset + caller_stack_offset) as i32,
3200 ),
3201 )?;
3202 caller_stack_offset += 8;
3203 output_reporter.check(a.offset().0)?;
3204 continue;
3205 }
3206 };
3207 a.emit_ldr(Size::S64, targ, prev_loc)?;
3208 output_reporter.check(a.offset().0)?;
3209 }
3210
3211 if stack_offset > 0 {
3213 if stack_offset < 0x1000 {
3214 a.emit_add(
3215 Size::S64,
3216 Location::GPR(GPR::XzrSp),
3217 Location::Imm32(stack_offset as u32),
3218 Location::GPR(GPR::XzrSp),
3219 )?;
3220 } else {
3221 a.emit_mov_imm(Location::GPR(GPR::X16), stack_offset as u64)?;
3222 a.emit_add(
3223 Size::S64,
3224 Location::GPR(GPR::XzrSp),
3225 Location::GPR(GPR::X16),
3226 Location::GPR(GPR::XzrSp),
3227 )?;
3228 }
3229 }
3230 }
3231 }
3232 }
3233
3234 let offset = vmoffsets.vmctx_vmfunction_import(index);
3238 let offset =
3241 if (offset > 0) && ((offset < 0xF8) || (offset < 0x7FF8 && offset.is_multiple_of(8))) {
3242 offset
3243 } else {
3244 a.emit_mov_imm(Location::GPR(GPR::X16), (offset as i64) as u64)?;
3245 a.emit_add(
3246 Size::S64,
3247 Location::GPR(GPR::X0),
3248 Location::GPR(GPR::X16),
3249 Location::GPR(GPR::X0),
3250 )?;
3251 0
3252 };
3253 let ptr_arg_offset = vmctx_offset(offset)?;
3254 let vmctx_arg_offset = vmctx_offset(offset.saturating_add(8))?;
3255
3256 #[allow(clippy::match_single_binding)]
3257 match calling_convention {
3258 _ => {
3259 if (ptr_arg_offset as u32).is_multiple_of(8) {
3260 a.emit_ldr(
3261 Size::S64,
3262 Location::GPR(GPR::X16),
3263 Location::Memory(GPR::X0, ptr_arg_offset), )?;
3265 a.emit_ldr(
3266 Size::S64,
3267 Location::GPR(GPR::X0),
3268 Location::Memory(GPR::X0, vmctx_arg_offset), )?;
3270 } else {
3271 a.emit_ldur(
3272 Size::S64,
3273 Location::GPR(GPR::X16),
3274 GPR::X0,
3275 ptr_arg_offset, )?;
3277 a.emit_ldur(
3278 Size::S64,
3279 Location::GPR(GPR::X0),
3280 GPR::X0,
3281 vmctx_arg_offset, )?;
3283 }
3284 }
3285 }
3286 a.emit_b_register(GPR::X16)?;
3287
3288 let mut contents = a.finalize().unwrap();
3289 contents.shrink_to_fit();
3290 output_reporter.finish(contents.len())?;
3291 let section_body = SectionBody::new_with_vec(contents);
3292
3293 Ok(CustomSection {
3294 protection: CustomSectionProtection::ReadExecute,
3295 alignment: None,
3296 bytes: section_body,
3297 relocations: vec![],
3298 })
3299}