1use crate::{
2 codegen_error, common_decl::Size, location::Location as AbstractLocation,
3 machine_x64::AssemblerX64,
4};
5pub use crate::{
6 location::Multiplier,
7 machine::{Label, Offset},
8 x64_decl::{GPR, XMM},
9};
10use dynasmrt::{AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi};
11use wasmer_types::{CompileError, target::CpuFeature};
12
13macro_rules! dynasm {
18 ($a:expr ; $($tt:tt)*) => {
19 dynasm::dynasm!(
20 $a.inner
21 ; .arch x64
22 ; $($tt)*
23 )
24 };
25}
26
27pub type Location = AbstractLocation<GPR, XMM>;
28
29#[derive(Copy, Clone, Debug, Eq, PartialEq)]
30pub enum Condition {
31 None,
32 Above,
33 AboveEqual,
34 Below,
35 BelowEqual,
36 Greater,
37 GreaterEqual,
38 Less,
39 LessEqual,
40 Equal,
41 NotEqual,
42 Signed,
43 Carry,
44}
45
46#[derive(Copy, Clone, Debug, Eq, PartialEq)]
47#[allow(dead_code, clippy::upper_case_acronyms)]
48pub enum XMMOrMemory {
49 XMM(XMM),
50 Memory(GPR, i32),
51}
52
53#[derive(Copy, Clone, Debug)]
54#[allow(dead_code, clippy::upper_case_acronyms)]
55pub enum GPROrMemory {
56 GPR(GPR),
57 Memory(GPR, i32),
58}
59
60pub enum Precision {
61 Single,
62 Double,
63}
64
65#[allow(unused)]
66pub trait EmitterX64 {
67 fn get_simd_arch(&self) -> Option<&CpuFeature>;
68 fn get_label(&mut self) -> Label;
69 fn get_offset(&self) -> Offset;
70 fn get_jmp_instr_size(&self) -> u8;
71
72 fn finalize_function(&mut self) -> Result<(), CompileError> {
73 Ok(())
74 }
75
76 fn emit_u64(&mut self, x: u64) -> Result<(), CompileError>;
77 fn emit_bytes(&mut self, bytes: &[u8]) -> Result<(), CompileError>;
78
79 fn emit_label(&mut self, label: Label) -> Result<(), CompileError>;
80
81 fn emit_nop(&mut self) -> Result<(), CompileError>;
82
83 fn emit_nop_n(&mut self, n: usize) -> Result<(), CompileError>;
86
87 fn emit_mov(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
88 fn emit_lea(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
89 fn emit_lea_label(&mut self, label: Label, dst: Location) -> Result<(), CompileError>;
90 fn emit_cdq(&mut self) -> Result<(), CompileError>;
91 fn emit_cqo(&mut self) -> Result<(), CompileError>;
92 fn emit_xor(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
93 fn emit_jmp(&mut self, condition: Condition, label: Label) -> Result<(), CompileError>;
94 fn emit_jmp_location(&mut self, loc: Location) -> Result<(), CompileError>;
95 fn emit_set(&mut self, condition: Condition, dst: GPR) -> Result<(), CompileError>;
96 fn emit_push(&mut self, sz: Size, src: Location) -> Result<(), CompileError>;
97 fn emit_pop(&mut self, sz: Size, dst: Location) -> Result<(), CompileError>;
98 fn emit_cmp(&mut self, sz: Size, left: Location, right: Location) -> Result<(), CompileError>;
99 fn emit_add(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
100 fn emit_sub(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
101 fn emit_neg(&mut self, sz: Size, value: Location) -> Result<(), CompileError>;
102 fn emit_imul(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
103 fn emit_imul_imm32_gpr64(&mut self, src: u32, dst: GPR) -> Result<(), CompileError>;
104 fn emit_div(&mut self, sz: Size, divisor: Location) -> Result<(), CompileError>;
105 fn emit_idiv(&mut self, sz: Size, divisor: Location) -> Result<(), CompileError>;
106 fn emit_shl(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
107 fn emit_shr(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
108 fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
109 fn emit_rol(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
110 fn emit_ror(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
111 fn emit_and(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
112 fn emit_test(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
113 fn emit_or(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
114 fn emit_bsr(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
115 fn emit_bsf(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
116 fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
117 fn emit_movzx(
118 &mut self,
119 sz_src: Size,
120 src: Location,
121 sz_dst: Size,
122 dst: Location,
123 ) -> Result<(), CompileError>;
124 fn emit_movsx(
125 &mut self,
126 sz_src: Size,
127 src: Location,
128 sz_dst: Size,
129 dst: Location,
130 ) -> Result<(), CompileError>;
131 fn emit_xchg(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError>;
132 fn emit_lock_xadd(
133 &mut self,
134 sz: Size,
135 src: Location,
136 dst: Location,
137 ) -> Result<(), CompileError>;
138 fn emit_lock_cmpxchg(
139 &mut self,
140 sz: Size,
141 src: Location,
142 dst: Location,
143 ) -> Result<(), CompileError>;
144 fn emit_rep_stosq(&mut self) -> Result<(), CompileError>;
145
146 fn emit_btc_gpr_imm8_32(&mut self, src: u8, dst: GPR) -> Result<(), CompileError>;
147 fn emit_btc_gpr_imm8_64(&mut self, src: u8, dst: GPR) -> Result<(), CompileError>;
148
149 fn emit_cmovae_gpr_32(&mut self, src: GPR, dst: GPR) -> Result<(), CompileError>;
150 fn emit_cmovae_gpr_64(&mut self, src: GPR, dst: GPR) -> Result<(), CompileError>;
151
152 fn emit_vmovaps(&mut self, src: XMMOrMemory, dst: XMMOrMemory) -> Result<(), CompileError>;
153 fn emit_vmovapd(&mut self, src: XMMOrMemory, dst: XMMOrMemory) -> Result<(), CompileError>;
154 fn emit_vxorps(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
155 fn emit_vxorpd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
156
157 fn emit_vaddss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
158 fn emit_vaddsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
159 fn emit_vsubss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
160 fn emit_vsubsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
161 fn emit_vmulss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
162 fn emit_vmulsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
163 fn emit_vdivss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
164 fn emit_vdivsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
165 fn emit_vmaxss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
166 fn emit_vmaxsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
167 fn emit_vminss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
168 fn emit_vminsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
169
170 fn emit_vcmpeqss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
171 -> Result<(), CompileError>;
172 fn emit_vcmpeqsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
173 -> Result<(), CompileError>;
174
175 fn emit_vcmpneqss(
176 &mut self,
177 src1: XMM,
178 src2: XMMOrMemory,
179 dst: XMM,
180 ) -> Result<(), CompileError>;
181 fn emit_vcmpneqsd(
182 &mut self,
183 src1: XMM,
184 src2: XMMOrMemory,
185 dst: XMM,
186 ) -> Result<(), CompileError>;
187
188 fn emit_vcmpltss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
189 -> Result<(), CompileError>;
190 fn emit_vcmpltsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
191 -> Result<(), CompileError>;
192
193 fn emit_vcmpless(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
194 -> Result<(), CompileError>;
195 fn emit_vcmplesd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
196 -> Result<(), CompileError>;
197
198 fn emit_vcmpgtss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
199 -> Result<(), CompileError>;
200 fn emit_vcmpgtsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
201 -> Result<(), CompileError>;
202
203 fn emit_vcmpgess(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
204 -> Result<(), CompileError>;
205 fn emit_vcmpgesd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM)
206 -> Result<(), CompileError>;
207
208 fn emit_vcmpunordss(
209 &mut self,
210 src1: XMM,
211 src2: XMMOrMemory,
212 dst: XMM,
213 ) -> Result<(), CompileError>;
214 fn emit_vcmpunordsd(
215 &mut self,
216 src1: XMM,
217 src2: XMMOrMemory,
218 dst: XMM,
219 ) -> Result<(), CompileError>;
220
221 fn emit_vcmpordss(
222 &mut self,
223 src1: XMM,
224 src2: XMMOrMemory,
225 dst: XMM,
226 ) -> Result<(), CompileError>;
227 fn emit_vcmpordsd(
228 &mut self,
229 src1: XMM,
230 src2: XMMOrMemory,
231 dst: XMM,
232 ) -> Result<(), CompileError>;
233
234 fn emit_vsqrtss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
235 fn emit_vsqrtsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
236
237 fn emit_vroundss_nearest(
238 &mut self,
239 src1: XMM,
240 src2: XMMOrMemory,
241 dst: XMM,
242 ) -> Result<(), CompileError>;
243 fn emit_vroundss_floor(
244 &mut self,
245 src1: XMM,
246 src2: XMMOrMemory,
247 dst: XMM,
248 ) -> Result<(), CompileError>;
249 fn emit_vroundss_ceil(
250 &mut self,
251 src1: XMM,
252 src2: XMMOrMemory,
253 dst: XMM,
254 ) -> Result<(), CompileError>;
255 fn emit_vroundss_trunc(
256 &mut self,
257 src1: XMM,
258 src2: XMMOrMemory,
259 dst: XMM,
260 ) -> Result<(), CompileError>;
261 fn emit_vroundsd_nearest(
262 &mut self,
263 src1: XMM,
264 src2: XMMOrMemory,
265 dst: XMM,
266 ) -> Result<(), CompileError>;
267 fn emit_vroundsd_floor(
268 &mut self,
269 src1: XMM,
270 src2: XMMOrMemory,
271 dst: XMM,
272 ) -> Result<(), CompileError>;
273 fn emit_vroundsd_ceil(
274 &mut self,
275 src1: XMM,
276 src2: XMMOrMemory,
277 dst: XMM,
278 ) -> Result<(), CompileError>;
279 fn emit_vroundsd_trunc(
280 &mut self,
281 src1: XMM,
282 src2: XMMOrMemory,
283 dst: XMM,
284 ) -> Result<(), CompileError>;
285
286 fn emit_vcvtss2sd(
287 &mut self,
288 src1: XMM,
289 src2: XMMOrMemory,
290 dst: XMM,
291 ) -> Result<(), CompileError>;
292 fn emit_vcvtsd2ss(
293 &mut self,
294 src1: XMM,
295 src2: XMMOrMemory,
296 dst: XMM,
297 ) -> Result<(), CompileError>;
298
299 fn emit_ucomiss(&mut self, src: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
300 fn emit_ucomisd(&mut self, src: XMMOrMemory, dst: XMM) -> Result<(), CompileError>;
301
302 fn emit_cvttss2si_32(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError>;
303 fn emit_cvttss2si_64(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError>;
304 fn emit_cvttsd2si_32(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError>;
305 fn emit_cvttsd2si_64(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError>;
306
307 fn emit_vcvtsi2ss_32(
308 &mut self,
309 src1: XMM,
310 src2: GPROrMemory,
311 dst: XMM,
312 ) -> Result<(), CompileError>;
313 fn emit_vcvtsi2ss_64(
314 &mut self,
315 src1: XMM,
316 src2: GPROrMemory,
317 dst: XMM,
318 ) -> Result<(), CompileError>;
319 fn emit_vcvtsi2sd_32(
320 &mut self,
321 src1: XMM,
322 src2: GPROrMemory,
323 dst: XMM,
324 ) -> Result<(), CompileError>;
325 fn emit_vcvtsi2sd_64(
326 &mut self,
327 src1: XMM,
328 src2: GPROrMemory,
329 dst: XMM,
330 ) -> Result<(), CompileError>;
331
332 fn emit_vblendvps(
333 &mut self,
334 src1: XMM,
335 src2: XMMOrMemory,
336 mask: XMM,
337 dst: XMM,
338 ) -> Result<(), CompileError>;
339 fn emit_vblendvpd(
340 &mut self,
341 src1: XMM,
342 src2: XMMOrMemory,
343 mask: XMM,
344 dst: XMM,
345 ) -> Result<(), CompileError>;
346
347 fn emit_test_gpr_64(&mut self, reg: GPR) -> Result<(), CompileError>;
348
349 fn emit_ud2(&mut self) -> Result<(), CompileError>;
350 fn emit_ud1_payload(&mut self, payload: u8) -> Result<(), CompileError>;
351 fn emit_ret(&mut self) -> Result<(), CompileError>;
352 fn emit_call_label(&mut self, label: Label) -> Result<(), CompileError>;
353 fn emit_call_location(&mut self, loc: Location) -> Result<(), CompileError>;
354
355 fn emit_call_register(&mut self, reg: GPR) -> Result<(), CompileError>;
356
357 fn emit_bkpt(&mut self) -> Result<(), CompileError>;
358
359 fn emit_host_redirection(&mut self, target: GPR) -> Result<(), CompileError>;
360
361 fn arch_has_itruncf(&self) -> bool {
362 false
363 }
364 fn arch_emit_i32_trunc_sf32(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
365 codegen_error!("singplepass arch_emit_i32_trunc_sf32 unimplemented")
366 }
367 fn arch_emit_i32_trunc_sf64(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
368 codegen_error!("singplepass arch_emit_i32_trunc_sf64 unimplemented")
369 }
370 fn arch_emit_i32_trunc_uf32(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
371 codegen_error!("singplepass arch_emit_i32_trunc_uf32 unimplemented")
372 }
373 fn arch_emit_i32_trunc_uf64(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
374 codegen_error!("singplepass arch_emit_i32_trunc_uf64 unimplemented")
375 }
376 fn arch_emit_i64_trunc_sf32(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
377 codegen_error!("singplepass arch_emit_i64_trunc_sf32 unimplemented")
378 }
379 fn arch_emit_i64_trunc_sf64(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
380 codegen_error!("singplepass arch_emit_i64_trunc_sf64 unimplemented")
381 }
382 fn arch_emit_i64_trunc_uf32(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
383 codegen_error!("singplepass arch_emit_i64_trunc_uf32 unimplemented")
384 }
385 fn arch_emit_i64_trunc_uf64(&mut self, _src: XMM, _dst: GPR) -> Result<(), CompileError> {
386 codegen_error!("singplepass arch_emit_i64_trunc_uf64 unimplemented")
387 }
388
389 fn arch_has_fconverti(&self) -> bool {
390 false
391 }
392 fn arch_emit_f32_convert_si32(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
393 codegen_error!("singlepass arch_emit_f32_convert_si32 unimplemented")
394 }
395 fn arch_emit_f32_convert_si64(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
396 codegen_error!("singlepass arch_emit_f32_convert_si64 unimplemented")
397 }
398 fn arch_emit_f32_convert_ui32(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
399 codegen_error!("singlepass arch_emit_f32_convert_ui32 unimplemented")
400 }
401 fn arch_emit_f32_convert_ui64(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
402 codegen_error!("singlepass arch_emit_f32_convert_ui64 unimplemented")
403 }
404 fn arch_emit_f64_convert_si32(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
405 codegen_error!("singlepass arch_emit_f64_convert_si32 unimplemented")
406 }
407 fn arch_emit_f64_convert_si64(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
408 codegen_error!("singlepass arch_emit_f64_convert_si64 unimplemented")
409 }
410 fn arch_emit_f64_convert_ui32(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
411 codegen_error!("singlepass arch_emit_f64_convert_ui32 unimplemented")
412 }
413 fn arch_emit_f64_convert_ui64(&mut self, _src: GPR, _dst: XMM) -> Result<(), CompileError> {
414 codegen_error!("singlepass arch_emit_f64_convert_ui64 unimplemented")
415 }
416
417 fn arch_has_fneg(&self) -> bool {
418 false
419 }
420 fn arch_emit_f32_neg(&mut self, _src: XMM, _dst: XMM) -> Result<(), CompileError> {
421 codegen_error!("singlepass arch_emit_f32_neg unimplemented")
422 }
423 fn arch_emit_f64_neg(&mut self, _src: XMM, _dst: XMM) -> Result<(), CompileError> {
424 codegen_error!("singlepass arch_emit_f64_neg unimplemented")
425 }
426
427 fn arch_has_xzcnt(&self) -> bool {
428 false
429 }
430 fn arch_emit_lzcnt(
431 &mut self,
432 _sz: Size,
433 _src: Location,
434 _dst: Location,
435 ) -> Result<(), CompileError> {
436 codegen_error!("singlepass arch_emit_lzcnt unimplemented")
437 }
438 fn arch_emit_tzcnt(
439 &mut self,
440 _sz: Size,
441 _src: Location,
442 _dst: Location,
443 ) -> Result<(), CompileError> {
444 codegen_error!("singlepass arch_emit_tzcnt unimplemented")
445 }
446
447 fn arch_emit_indirect_call_with_trampoline(
448 &mut self,
449 _loc: Location,
450 ) -> Result<(), CompileError> {
451 codegen_error!("singlepass arch_emit_indirect_call_with_trampoline unimplemented")
452 }
453
454 fn arch_emit_entry_trampoline(&mut self) -> Result<(), CompileError> {
456 Ok(())
457 }
458
459 fn arch_mov64_imm_offset(&self) -> Result<usize, CompileError> {
462 codegen_error!("singlepass arch_mov64_imm_offset unimplemented")
463 }
464}
465
466macro_rules! unop_gpr {
467 ($ins:ident, $assembler:tt, $sz:expr, $loc:expr, $otherwise:block) => {
468 match ($sz, $loc) {
469 (Size::S32, Location::GPR(loc)) => {
470 dynasm!($assembler ; $ins Rd(loc));
471 },
472 (Size::S64, Location::GPR(loc)) => {
473 dynasm!($assembler ; $ins Rq(loc));
474 },
475 _ => $otherwise
476 }
477 };
478}
479
480macro_rules! unop_mem {
481 ($ins:ident, $assembler:tt, $sz:expr, $loc:expr, $otherwise:block) => {
482 match ($sz, $loc) {
483 (Size::S32, Location::Memory(loc, disp)) => {
484 dynasm!($assembler ; $ins DWORD [Rq(loc) + disp] );
485 },
486 (Size::S64, Location::Memory(loc, disp)) => {
487 dynasm!($assembler ; $ins QWORD [Rq(loc) + disp] );
488 },
489 _ => $otherwise
490 }
491 };
492}
493
494macro_rules! unop_gpr_or_mem {
495 ($ins:ident, $assembler:tt, $sz:expr, $loc:expr, $otherwise:block) => {
496 unop_gpr!($ins, $assembler, $sz, $loc, {
497 unop_mem!($ins, $assembler, $sz, $loc, $otherwise)
498 })
499 };
500}
501
502macro_rules! binop_imm32_gpr {
503 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
504 match ($sz, $src, $dst) {
505 (Size::S32, Location::Imm32(src), Location::GPR(dst)) => {
506 dynasm!($assembler ; $ins Rd(dst), src as i32); },
508 (Size::S64, Location::Imm32(src), Location::GPR(dst)) => {
509 dynasm!($assembler ; $ins Rq(dst), src as i32); },
511 _ => $otherwise
512 }
513 };
514}
515
516macro_rules! binop_imm32_mem {
517 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
518 match ($sz, $src, $dst) {
519 (Size::S32, Location::Imm32(src), Location::Memory(dst, disp)) => {
520 dynasm!($assembler ; $ins DWORD [Rq(dst) + disp], src as i32);
521 },
522 (Size::S64, Location::Imm32(src), Location::Memory(dst, disp)) => {
523 dynasm!($assembler ; $ins QWORD [Rq(dst) + disp], src as i32);
524 },
525 _ => $otherwise
526 }
527 };
528}
529
530macro_rules! binop_imm64_gpr {
531 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
532 match ($sz, $src, $dst) {
533 (Size::S64, Location::Imm64(src), Location::GPR(dst)) => {
534 dynasm!($assembler ; $ins Rq(dst), QWORD src as i64); },
536 _ => $otherwise
537 }
538 };
539}
540
541macro_rules! binop_gpr_gpr {
542 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
543 match ($sz, $src, $dst) {
544 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
545 dynasm!($assembler ; $ins Rd(dst), Rd(src)); },
547 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
548 dynasm!($assembler ; $ins Rq(dst), Rq(src)); },
550 _ => $otherwise
551 }
552 };
553}
554
555macro_rules! binop_gpr_mem {
556 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
557 match ($sz, $src, $dst) {
558 (Size::S32, Location::GPR(src), Location::Memory(dst, disp)) => {
559 dynasm!($assembler ; $ins [Rq(dst) + disp], Rd(src)); },
561 (Size::S64, Location::GPR(src), Location::Memory(dst, disp)) => {
562 dynasm!($assembler ; $ins [Rq(dst) + disp], Rq(src)); },
564 _ => $otherwise
565 }
566 };
567}
568
569macro_rules! binop_mem_gpr {
570 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
571 match ($sz, $src, $dst) {
572 (Size::S32, Location::Memory(src, disp), Location::GPR(dst)) => {
573 dynasm!($assembler ; $ins Rd(dst), [Rq(src) + disp]); },
575 (Size::S64, Location::Memory(src, disp), Location::GPR(dst)) => {
576 dynasm!($assembler ; $ins Rq(dst), [Rq(src) + disp]); },
578 _ => $otherwise
579 }
580 };
581}
582
583macro_rules! binop_all_nofp {
584 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
585 binop_imm32_gpr!($ins, $assembler, $sz, $src, $dst, {
586 binop_imm32_mem!($ins, $assembler, $sz, $src, $dst, {
587 binop_gpr_gpr!($ins, $assembler, $sz, $src, $dst, {
588 binop_gpr_mem!($ins, $assembler, $sz, $src, $dst, {
589 binop_mem_gpr!($ins, $assembler, $sz, $src, $dst, $otherwise)
590 })
591 })
592 })
593 })
594 };
595}
596
597macro_rules! binop_shift {
598 ($ins:ident, $assembler:tt, $sz:expr, $src:expr, $dst:expr, $otherwise:block) => {
599 match ($sz, $src, $dst) {
600 (Size::S32, Location::GPR(GPR::RCX), Location::GPR(dst)) => {
601 dynasm!($assembler ; $ins Rd(dst), cl);
602 },
603 (Size::S32, Location::GPR(GPR::RCX), Location::Memory(dst, disp)) => {
604 dynasm!($assembler ; $ins DWORD [Rq(dst) + disp], cl);
605 },
606 (Size::S32, Location::Imm8(imm), Location::GPR(dst)) => {
607 dynasm!($assembler ; $ins Rd(dst), imm as i8);
608 },
609 (Size::S32, Location::Imm8(imm), Location::Memory(dst, disp)) => {
610 dynasm!($assembler ; $ins DWORD [Rq(dst) + disp], imm as i8);
611 },
612 (Size::S64, Location::GPR(GPR::RCX), Location::GPR(dst)) => {
613 dynasm!($assembler ; $ins Rq(dst), cl);
614 },
615 (Size::S64, Location::GPR(GPR::RCX), Location::Memory(dst, disp)) => {
616 dynasm!($assembler ; $ins QWORD [Rq(dst) + disp], cl);
617 },
618 (Size::S64, Location::Imm8(imm), Location::GPR(dst)) => {
619 dynasm!($assembler ; $ins Rq(dst), imm as i8);
620 },
621 (Size::S64, Location::Imm8(imm), Location::Memory(dst, disp)) => {
622 dynasm!($assembler ; $ins QWORD [Rq(dst) + disp], imm as i8);
623 },
624 _ => $otherwise
625 }
626 }
627}
628
629macro_rules! jmp_op {
630 ($ins:ident, $assembler:tt, $label:ident) => {
631 dynasm!($assembler ; $ins =>$label)
632 }
633}
634
635fn move_src_to_dst(emitter: &mut AssemblerX64, precision: Precision, src: XMM, dst: XMM) {
642 if src == dst {
643 return;
644 }
645 match precision {
646 Precision::Single => dynasm!(emitter ; movss Rx(dst), Rx(src)),
647 Precision::Double => dynasm!(emitter ; movsd Rx(dst), Rx(src)),
648 }
649}
650
651macro_rules! avx_fn {
652 ($ins:ident, $emitter:ident, $src1:ident, $src2:ident, $dst:ident) => {
653 match $src2 {
654 XMMOrMemory::XMM(x) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), Rx(x)),
655 XMMOrMemory::Memory(base, disp) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), [Rq(base) + disp]),
656 }
657 }
658}
659
660macro_rules! sse_fn {
661 ($ins:ident, $emitter:ident, $precision:expr, $src1:ident, $src2:ident, $dst:ident) => {
662 match $src2 {
663 XMMOrMemory::XMM(x) => {
664 if x == $dst {
665 dynasm!($emitter ; $ins Rx($dst), Rx($src1))
666 } else {
667 move_src_to_dst($emitter, $precision, $src1, $dst);
668 dynasm!($emitter ; $ins Rx($dst), Rx(x))
669 }
670 }
671 XMMOrMemory::Memory(base, disp) => {
672 move_src_to_dst($emitter, $precision, $src1, $dst);
673 dynasm!($emitter ; $ins Rx($dst), [Rq(base) + disp])
674 }
675 }
676 };
677 ($ins:ident, $mode:expr, $emitter:ident, $precision:expr, $src1:ident, $src2:ident, $dst:ident) => {
678 match $src2 {
679 XMMOrMemory::XMM(x) => {
680 move_src_to_dst($emitter, $precision, $src1, $dst);
681 dynasm!($emitter ; $ins Rx($dst), Rx(x), $mode)
682 }
683 XMMOrMemory::Memory(base, disp) => {
684 move_src_to_dst($emitter, $precision, $src1, $dst);
685 dynasm!($emitter ; $ins Rx($dst), [Rq(base) + disp], $mode)
686 }
687 }
688 };
689}
690
691macro_rules! avx_i2f_64_fn {
692 ($ins:ident, $emitter:ident, $src1:ident, $src2:ident, $dst:ident) => {
693 match $src2 {
694 GPROrMemory::GPR(x) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), Rq(x)),
695 GPROrMemory::Memory(base, disp) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), QWORD [Rq(base) + disp]),
696 }
697 }
698}
699
700macro_rules! sse_i2f_64_fn {
701 ($ins:ident, $emitter:ident, $precision:expr, $src1:ident, $src2:ident, $dst:ident) => {
702 match $src2 {
703 GPROrMemory::GPR(x) => {
704 move_src_to_dst($emitter, $precision, $src1, $dst);
705 dynasm!($emitter ; $ins Rx($dst), Rq(x))
706 },
707 GPROrMemory::Memory(base, disp) => {
708 move_src_to_dst($emitter, $precision, $src1, $dst);
709 dynasm!($emitter ; $ins Rx($dst), QWORD [Rq(base) + disp])
710 }
711 }
712 }
713}
714
715macro_rules! avx_i2f_32_fn {
716 ($ins:ident, $emitter:ident, $src1:ident, $src2:ident, $dst:ident) => {
717 match $src2 {
718 GPROrMemory::GPR(x) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), Rd(x)),
719 GPROrMemory::Memory(base, disp) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), DWORD [Rq(base) + disp]),
720 }
721 }
722}
723
724macro_rules! sse_i2f_32_fn {
725 ($ins:ident, $emitter:ident, $precision:expr, $src1:ident, $src2:ident, $dst:ident) => {
726 match $src2 {
727 GPROrMemory::GPR(x) => {
728 move_src_to_dst($emitter, $precision, $src1, $dst);
729 dynasm!($emitter; $ins Rx($src1), Rd(x))
730 },
731 GPROrMemory::Memory(base, disp) => {
732 move_src_to_dst($emitter, $precision, $src1, $dst);
733 dynasm!($emitter; $ins Rx($dst), DWORD [Rq(base) + disp])
734 }
735 }
736 }
737}
738
739macro_rules! avx_round_fn {
740 ($ins:ident, $mode:expr, $emitter:ident, $src1:ident, $src2:ident, $dst:ident) => {
741 match $src2 {
742 XMMOrMemory::XMM(x) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), Rx(x), $mode),
743 XMMOrMemory::Memory(base, disp) => dynasm!($emitter ; $ins Rx($dst), Rx($src1), [Rq(base) + disp], $mode),
744 }
745 }
746}
747
748macro_rules! sse_round_fn {
749 ($ins:ident, $mode:expr, $emitter:ident, $precision:expr, $src1:ident, $src2:ident, $dst:ident) => {
750 match $src2 {
751 XMMOrMemory::XMM(x) => {
752 if x != $dst {
753 move_src_to_dst($emitter, $precision, $src1, $dst);
754 }
755 dynasm!($emitter ; $ins Rx(x), Rx($dst), $mode)
756 }
757 XMMOrMemory::Memory(base, disp) => {
758 dynasm!($emitter ; $ins Rx($dst), [Rq(base) + disp], $mode)
759 },
760 }
761 }
762}
763
764impl EmitterX64 for AssemblerX64 {
765 fn get_simd_arch(&self) -> Option<&CpuFeature> {
766 Some(&self.simd_arch)
767 }
768
769 fn get_label(&mut self) -> DynamicLabel {
770 self.new_dynamic_label()
771 }
772
773 fn get_offset(&self) -> AssemblyOffset {
774 self.offset()
775 }
776
777 fn get_jmp_instr_size(&self) -> u8 {
778 5
779 }
780
781 fn finalize_function(&mut self) -> Result<(), CompileError> {
782 Ok(())
783 }
784
785 fn arch_has_xzcnt(&self) -> bool {
786 match &self.target {
787 Some(target) => {
788 target.cpu_features().contains(CpuFeature::LZCNT)
789 && target.cpu_features().contains(CpuFeature::BMI1)
790 }
791 None => false,
792 }
793 }
794
795 fn arch_emit_lzcnt(
796 &mut self,
797 sz: Size,
798 src: Location,
799 dst: Location,
800 ) -> Result<(), CompileError> {
801 binop_gpr_gpr!(lzcnt, self, sz, src, dst, {
802 binop_mem_gpr!(lzcnt, self, sz, src, dst, {
803 codegen_error!("singlepass cannot emit lzcnt")
804 })
805 });
806 Ok(())
807 }
808
809 fn arch_emit_tzcnt(
810 &mut self,
811 sz: Size,
812 src: Location,
813 dst: Location,
814 ) -> Result<(), CompileError> {
815 binop_gpr_gpr!(tzcnt, self, sz, src, dst, {
816 binop_mem_gpr!(tzcnt, self, sz, src, dst, {
817 codegen_error!("singlepass cannot emit tzcnt")
818 })
819 });
820 Ok(())
821 }
822
823 fn emit_u64(&mut self, x: u64) -> Result<(), CompileError> {
824 self.push_u64(x);
825 Ok(())
826 }
827
828 fn emit_bytes(&mut self, bytes: &[u8]) -> Result<(), CompileError> {
829 for &b in bytes {
830 self.push(b);
831 }
832 Ok(())
833 }
834
835 fn emit_label(&mut self, label: Label) -> Result<(), CompileError> {
836 dynasm!(self ; => label);
837 Ok(())
838 }
839
840 fn emit_nop(&mut self) -> Result<(), CompileError> {
841 dynasm!(self ; nop);
842 Ok(())
843 }
844
845 fn emit_nop_n(&mut self, mut n: usize) -> Result<(), CompileError> {
846 while n >= 9 {
858 n -= 9;
859 self.emit_bytes(&[0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00])?;
860 }
862 let seq: &[u8] = match n {
863 0 => &[],
864 1 => &[0x90],
865 2 => &[0x66, 0x90],
866 3 => &[0x0f, 0x1f, 0x00],
867 4 => &[0x0f, 0x1f, 0x40, 0x00],
868 5 => &[0x0f, 0x1f, 0x44, 0x00, 0x00],
869 6 => &[0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00],
870 7 => &[0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00],
871 8 => &[0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
872 _ => codegen_error!("singlepass emit_nop_n unreachable"),
873 };
874 self.emit_bytes(seq)
875 }
876
877 fn emit_mov(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
878 if let (Location::Imm32(0), Location::GPR(x)) = (src, dst) {
880 dynasm!(self ; xor Rd(x), Rd(x));
881 return Ok(());
882 }
883
884 binop_all_nofp!(mov, self, sz, src, dst, {
885 binop_imm64_gpr!(mov, self, sz, src, dst, {
886 match (sz, src, dst) {
887 (Size::S8, Location::GPR(src), Location::Memory(dst, disp)) => {
888 dynasm!(self ; mov [Rq(dst) + disp], Rb(src));
889 }
890 (Size::S8, Location::Memory(src, disp), Location::GPR(dst)) => {
891 dynasm!(self ; mov Rb(dst), [Rq(src) + disp]);
892 }
893 (Size::S8, Location::Imm32(src), Location::GPR(dst)) => {
894 dynasm!(self ; mov Rb(dst), src as i8);
895 }
896 (Size::S8, Location::Imm64(src), Location::GPR(dst)) => {
897 dynasm!(self ; mov Rb(dst), src as i8);
898 }
899 (Size::S8, Location::Imm32(src), Location::Memory(dst, disp)) => {
900 dynasm!(self ; mov BYTE [Rq(dst) + disp], src as i8);
901 }
902 (Size::S8, Location::Imm64(src), Location::Memory(dst, disp)) => {
903 dynasm!(self ; mov BYTE [Rq(dst) + disp], src as i8);
904 }
905 (Size::S16, Location::GPR(src), Location::Memory(dst, disp)) => {
906 dynasm!(self ; mov [Rq(dst) + disp], Rw(src));
907 }
908 (Size::S16, Location::Memory(src, disp), Location::GPR(dst)) => {
909 dynasm!(self ; mov Rw(dst), [Rq(src) + disp]);
910 }
911 (Size::S16, Location::Imm32(src), Location::GPR(dst)) => {
912 dynasm!(self ; mov Rw(dst), src as i16);
913 }
914 (Size::S16, Location::Imm64(src), Location::GPR(dst)) => {
915 dynasm!(self ; mov Rw(dst), src as i16);
916 }
917 (Size::S16, Location::Imm32(src), Location::Memory(dst, disp)) => {
918 dynasm!(self ; mov WORD [Rq(dst) + disp], src as i16);
919 }
920 (Size::S16, Location::Imm64(src), Location::Memory(dst, disp)) => {
921 dynasm!(self ; mov WORD [Rq(dst) + disp], src as i16);
922 }
923 (Size::S32, Location::Imm64(src), Location::GPR(dst)) => {
924 dynasm!(self ; mov Rd(dst), src as i32);
925 }
926 (Size::S32, Location::Imm64(src), Location::Memory(dst, disp)) => {
927 dynasm!(self ; mov DWORD [Rq(dst) + disp], src as i32);
928 }
929 (Size::S32, Location::GPR(src), Location::SIMD(dst)) => {
930 dynasm!(self ; movd Rx(dst), Rd(src));
931 }
932 (Size::S32, Location::SIMD(src), Location::GPR(dst)) => {
933 dynasm!(self ; movd Rd(dst), Rx(src));
934 }
935 (Size::S32, Location::Memory(src, disp), Location::SIMD(dst)) => {
936 dynasm!(self ; movd Rx(dst), [Rq(src) + disp]);
937 }
938 (Size::S32, Location::SIMD(src), Location::Memory(dst, disp)) => {
939 dynasm!(self ; movd [Rq(dst) + disp], Rx(src));
940 }
941 (Size::S64, Location::Imm64(src), Location::GPR(dst)) => {
942 dynasm!(self ; mov Rd(dst), src as i32);
943 }
944 (Size::S64, Location::Imm32(src), Location::GPR(dst)) => {
945 dynasm!(self ; mov Rd(dst), src as i32);
946 }
947 (Size::S64, Location::Imm8(src), Location::GPR(dst)) => {
948 dynasm!(self ; mov Rd(dst), src as i32);
949 }
950
951 (Size::S64, Location::GPR(src), Location::SIMD(dst)) => {
952 dynasm!(self ; movq Rx(dst), Rq(src));
953 }
954 (Size::S64, Location::SIMD(src), Location::GPR(dst)) => {
955 dynasm!(self ; movq Rq(dst), Rx(src));
956 }
957 (Size::S64, Location::Memory(src, disp), Location::SIMD(dst)) => {
958 dynasm!(self ; movq Rx(dst), [Rq(src) + disp]);
959 }
960 (Size::S64, Location::SIMD(src), Location::Memory(dst, disp)) => {
961 dynasm!(self ; movq [Rq(dst) + disp], Rx(src));
962 }
963 (_, Location::SIMD(src), Location::SIMD(dst)) => {
964 dynasm!(self ; movq Rx(dst), Rx(src));
965 }
966
967 _ => codegen_error!("singlepass can't emit MOV {:?} {:?} {:?}", sz, src, dst),
968 }
969 })
970 });
971 Ok(())
972 }
973 fn emit_lea(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
974 match (sz, src, dst) {
975 (Size::S32, Location::Memory(src, disp), Location::GPR(dst)) => {
976 dynasm!(self ; lea Rd(dst), [Rq(src) + disp]);
977 }
978 (Size::S64, Location::Memory(src, disp), Location::GPR(dst)) => {
979 dynasm!(self ; lea Rq(dst), [Rq(src) + disp]);
980 }
981 (Size::S32, Location::Memory2(src1, src2, mult, disp), Location::GPR(dst)) => {
982 match mult {
983 Multiplier::Zero => dynasm!(self ; lea Rd(dst), [Rq(src1) + disp]),
984 Multiplier::One => {
985 dynasm!(self ; lea Rd(dst), [Rq(src1) + Rq(src2) + disp])
986 }
987 Multiplier::Two => {
988 dynasm!(self ; lea Rd(dst), [Rq(src1) + Rq(src2) * 2 + disp])
989 }
990 Multiplier::Four => {
991 dynasm!(self ; lea Rd(dst), [Rq(src1) + Rq(src2) * 4 + disp])
992 }
993 Multiplier::Height => {
994 dynasm!(self ; lea Rd(dst), [Rq(src1) + Rq(src2) * 8 + disp])
995 }
996 };
997 }
998 (Size::S64, Location::Memory2(src1, src2, mult, disp), Location::GPR(dst)) => {
999 match mult {
1000 Multiplier::Zero => dynasm!(self ; lea Rq(dst), [Rq(src1) + disp]),
1001 Multiplier::One => {
1002 dynasm!(self ; lea Rq(dst), [Rq(src1) + Rq(src2) + disp])
1003 }
1004 Multiplier::Two => {
1005 dynasm!(self ; lea Rq(dst), [Rq(src1) + Rq(src2) * 2 + disp])
1006 }
1007 Multiplier::Four => {
1008 dynasm!(self ; lea Rq(dst), [Rq(src1) + Rq(src2) * 4 + disp])
1009 }
1010 Multiplier::Height => {
1011 dynasm!(self ; lea Rq(dst), [Rq(src1) + Rq(src2) * 8 + disp])
1012 }
1013 };
1014 }
1015 _ => codegen_error!("singlepass can't emit LEA {:?} {:?} {:?}", sz, src, dst),
1016 }
1017 Ok(())
1018 }
1019 fn emit_lea_label(&mut self, label: Label, dst: Location) -> Result<(), CompileError> {
1020 match dst {
1021 Location::GPR(x) => {
1022 dynasm!(self ; lea Rq(x), [=>label]);
1023 }
1024 _ => codegen_error!("singlepass can't emit LEA label={:?} {:?}", label, dst),
1025 }
1026 Ok(())
1027 }
1028 fn emit_cdq(&mut self) -> Result<(), CompileError> {
1029 dynasm!(self ; cdq);
1030 Ok(())
1031 }
1032 fn emit_cqo(&mut self) -> Result<(), CompileError> {
1033 dynasm!(self ; cqo);
1034 Ok(())
1035 }
1036 fn emit_xor(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1037 binop_all_nofp!(xor, self, sz, src, dst, {
1038 codegen_error!("singlepass can't emit XOR {:?} {:?} {:?}", sz, src, dst)
1039 });
1040 Ok(())
1041 }
1042 fn emit_jmp(&mut self, condition: Condition, label: Label) -> Result<(), CompileError> {
1043 match condition {
1044 Condition::None => jmp_op!(jmp, self, label),
1045 Condition::Above => jmp_op!(ja, self, label),
1046 Condition::AboveEqual => jmp_op!(jae, self, label),
1047 Condition::Below => jmp_op!(jb, self, label),
1048 Condition::BelowEqual => jmp_op!(jbe, self, label),
1049 Condition::Greater => jmp_op!(jg, self, label),
1050 Condition::GreaterEqual => jmp_op!(jge, self, label),
1051 Condition::Less => jmp_op!(jl, self, label),
1052 Condition::LessEqual => jmp_op!(jle, self, label),
1053 Condition::Equal => jmp_op!(je, self, label),
1054 Condition::NotEqual => jmp_op!(jne, self, label),
1055 Condition::Signed => jmp_op!(js, self, label),
1056 Condition::Carry => jmp_op!(jc, self, label),
1057 }
1058 Ok(())
1059 }
1060 fn emit_jmp_location(&mut self, loc: Location) -> Result<(), CompileError> {
1061 match loc {
1062 Location::GPR(x) => dynasm!(self ; jmp Rq(x)),
1063 Location::Memory(base, disp) => dynasm!(self ; jmp QWORD [Rq(base) + disp]),
1064 _ => codegen_error!("singlepass can't emit JMP {:?}", loc),
1065 }
1066 Ok(())
1067 }
1068 fn emit_set(&mut self, condition: Condition, dst: GPR) -> Result<(), CompileError> {
1069 match condition {
1070 Condition::Above => dynasm!(self ; seta Rb(dst)),
1071 Condition::AboveEqual => dynasm!(self ; setae Rb(dst)),
1072 Condition::Below => dynasm!(self ; setb Rb(dst)),
1073 Condition::BelowEqual => dynasm!(self ; setbe Rb(dst)),
1074 Condition::Greater => dynasm!(self ; setg Rb(dst)),
1075 Condition::GreaterEqual => dynasm!(self ; setge Rb(dst)),
1076 Condition::Less => dynasm!(self ; setl Rb(dst)),
1077 Condition::LessEqual => dynasm!(self ; setle Rb(dst)),
1078 Condition::Equal => dynasm!(self ; sete Rb(dst)),
1079 Condition::NotEqual => dynasm!(self ; setne Rb(dst)),
1080 Condition::Signed => dynasm!(self ; sets Rb(dst)),
1081 Condition::Carry => dynasm!(self ; setc Rb(dst)),
1082 _ => codegen_error!("singlepass can't emit SET {:?} {:?}", condition, dst),
1083 }
1084 Ok(())
1085 }
1086 fn emit_push(&mut self, sz: Size, src: Location) -> Result<(), CompileError> {
1087 match (sz, src) {
1088 (Size::S64, Location::Imm32(src)) => dynasm!(self ; push src as i32),
1089 (Size::S64, Location::GPR(src)) => dynasm!(self ; push Rq(src)),
1090 (Size::S64, Location::Memory(src, disp)) => {
1091 dynasm!(self ; push QWORD [Rq(src) + disp])
1092 }
1093 _ => codegen_error!("singlepass can't emit PUSH {:?} {:?}", sz, src),
1094 }
1095 Ok(())
1096 }
1097 fn emit_pop(&mut self, sz: Size, dst: Location) -> Result<(), CompileError> {
1098 match (sz, dst) {
1099 (Size::S64, Location::GPR(dst)) => dynasm!(self ; pop Rq(dst)),
1100 (Size::S64, Location::Memory(dst, disp)) => {
1101 dynasm!(self ; pop QWORD [Rq(dst) + disp])
1102 }
1103 _ => codegen_error!("singlepass can't emit POP {:?} {:?}", sz, dst),
1104 }
1105 Ok(())
1106 }
1107
1108 fn emit_cmp(&mut self, sz: Size, left: Location, right: Location) -> Result<(), CompileError> {
1109 binop_all_nofp!(cmp, self, sz, left, right, {
1110 codegen_error!("singlepass can't emit CMP {:?} {:?} {:?}", sz, left, right);
1111 });
1112 Ok(())
1113 }
1114
1115 fn emit_add(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1116 if let Location::Imm32(0) = src {
1118 return Ok(());
1119 }
1120 binop_all_nofp!(add, self, sz, src, dst, {
1121 codegen_error!("singlepass can't emit ADD {:?} {:?} {:?}", sz, src, dst)
1122 });
1123 Ok(())
1124 }
1125 fn emit_sub(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1126 if let Location::Imm32(0) = src {
1128 return Ok(());
1129 }
1130 binop_all_nofp!(sub, self, sz, src, dst, {
1131 codegen_error!("singlepass can't emit SUB {:?} {:?} {:?}", sz, src, dst)
1132 });
1133 Ok(())
1134 }
1135 fn emit_neg(&mut self, sz: Size, value: Location) -> Result<(), CompileError> {
1136 match (sz, value) {
1137 (Size::S8, Location::GPR(value)) => dynasm!(self ; neg Rb(value)),
1138 (Size::S8, Location::Memory(value, disp)) => {
1139 dynasm!(self ; neg [Rq(value) + disp])
1140 }
1141 (Size::S16, Location::GPR(value)) => dynasm!(self ; neg Rw(value)),
1142 (Size::S16, Location::Memory(value, disp)) => {
1143 dynasm!(self ; neg [Rq(value) + disp])
1144 }
1145 (Size::S32, Location::GPR(value)) => dynasm!(self ; neg Rd(value)),
1146 (Size::S32, Location::Memory(value, disp)) => {
1147 dynasm!(self ; neg [Rq(value) + disp])
1148 }
1149 (Size::S64, Location::GPR(value)) => dynasm!(self ; neg Rq(value)),
1150 (Size::S64, Location::Memory(value, disp)) => {
1151 dynasm!(self ; neg [Rq(value) + disp])
1152 }
1153 _ => codegen_error!("singlepass can't emit NEG {:?} {:?}", sz, value),
1154 }
1155 Ok(())
1156 }
1157 fn emit_imul(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1158 binop_gpr_gpr!(imul, self, sz, src, dst, {
1159 binop_mem_gpr!(imul, self, sz, src, dst, {
1160 codegen_error!("singlepass can't emit IMUL {:?} {:?} {:?}", sz, src, dst)
1161 })
1162 });
1163 Ok(())
1164 }
1165 fn emit_imul_imm32_gpr64(&mut self, src: u32, dst: GPR) -> Result<(), CompileError> {
1166 dynasm!(self ; imul Rq(dst), Rq(dst), src as i32);
1167 Ok(())
1168 }
1169 fn emit_div(&mut self, sz: Size, divisor: Location) -> Result<(), CompileError> {
1170 unop_gpr_or_mem!(div, self, sz, divisor, {
1171 codegen_error!("singlepass can't emit DIV {:?} {:?}", sz, divisor)
1172 });
1173 Ok(())
1174 }
1175 fn emit_idiv(&mut self, sz: Size, divisor: Location) -> Result<(), CompileError> {
1176 unop_gpr_or_mem!(idiv, self, sz, divisor, {
1177 codegen_error!("singlepass can't emit IDIV {:?} {:?}", sz, divisor)
1178 });
1179 Ok(())
1180 }
1181 fn emit_shl(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1182 binop_shift!(shl, self, sz, src, dst, {
1183 codegen_error!("singlepass can't emit SHL {:?} {:?} {:?}", sz, src, dst)
1184 });
1185 Ok(())
1186 }
1187 fn emit_shr(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1188 binop_shift!(shr, self, sz, src, dst, {
1189 codegen_error!("singlepass can't emit SHR {:?} {:?} {:?}", sz, src, dst)
1190 });
1191 Ok(())
1192 }
1193 fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1194 binop_shift!(sar, self, sz, src, dst, {
1195 codegen_error!("singlepass can't emit SAR {:?} {:?} {:?}", sz, src, dst)
1196 });
1197 Ok(())
1198 }
1199 fn emit_rol(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1200 binop_shift!(rol, self, sz, src, dst, {
1201 codegen_error!("singlepass can't emit ROL {:?} {:?} {:?}", sz, src, dst)
1202 });
1203 Ok(())
1204 }
1205 fn emit_ror(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1206 binop_shift!(ror, self, sz, src, dst, {
1207 codegen_error!("singlepass can't emit ROR {:?} {:?} {:?}", sz, src, dst)
1208 });
1209 Ok(())
1210 }
1211 fn emit_and(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1212 binop_all_nofp!(and, self, sz, src, dst, {
1213 codegen_error!("singlepass can't emit AND {:?} {:?} {:?}", sz, src, dst)
1214 });
1215 Ok(())
1216 }
1217 fn emit_test(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1218 binop_all_nofp!(test, self, sz, src, dst, {
1219 codegen_error!("singlepass can't emit TEST {:?} {:?} {:?}", sz, src, dst)
1220 });
1221 Ok(())
1222 }
1223 fn emit_or(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1224 binop_all_nofp!(or, self, sz, src, dst, {
1225 codegen_error!("singlepass can't emit OR {:?} {:?} {:?}", sz, src, dst)
1226 });
1227 Ok(())
1228 }
1229 fn emit_bsr(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1230 binop_gpr_gpr!(bsr, self, sz, src, dst, {
1231 binop_mem_gpr!(bsr, self, sz, src, dst, {
1232 codegen_error!("singlepass can't emit BSR {:?} {:?} {:?}", sz, src, dst)
1233 })
1234 });
1235 Ok(())
1236 }
1237 fn emit_bsf(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1238 binop_gpr_gpr!(bsf, self, sz, src, dst, {
1239 binop_mem_gpr!(bsf, self, sz, src, dst, {
1240 codegen_error!("singlepass can't emit BSF {:?} {:?} {:?}", sz, src, dst)
1241 })
1242 });
1243 Ok(())
1244 }
1245 fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1246 binop_gpr_gpr!(popcnt, self, sz, src, dst, {
1247 binop_mem_gpr!(popcnt, self, sz, src, dst, {
1248 codegen_error!("singlepass can't emit POPCNT {:?} {:?} {:?}", sz, src, dst)
1249 })
1250 });
1251 Ok(())
1252 }
1253 fn emit_movzx(
1254 &mut self,
1255 sz_src: Size,
1256 src: Location,
1257 sz_dst: Size,
1258 dst: Location,
1259 ) -> Result<(), CompileError> {
1260 match (sz_src, src, sz_dst, dst) {
1261 (Size::S8, Location::GPR(src), Size::S32, Location::GPR(dst)) => {
1262 dynasm!(self ; movzx Rd(dst), Rb(src));
1263 }
1264 (Size::S16, Location::GPR(src), Size::S32, Location::GPR(dst)) => {
1265 dynasm!(self ; movzx Rd(dst), Rw(src));
1266 }
1267 (Size::S8, Location::Memory(src, disp), Size::S32, Location::GPR(dst)) => {
1268 dynasm!(self ; movzx Rd(dst), BYTE [Rq(src) + disp]);
1269 }
1270 (Size::S16, Location::Memory(src, disp), Size::S32, Location::GPR(dst)) => {
1271 dynasm!(self ; movzx Rd(dst), WORD [Rq(src) + disp]);
1272 }
1273 (Size::S16, Location::Imm32(imm), Size::S32, Location::GPR(dst)) => {
1274 dynasm!(self ; mov Rd(dst), imm as i32);
1275 }
1276 (Size::S8, Location::GPR(src), Size::S64, Location::GPR(dst)) => {
1277 dynasm!(self ; movzx Rq(dst), Rb(src));
1278 }
1279 (Size::S16, Location::GPR(src), Size::S64, Location::GPR(dst)) => {
1280 dynasm!(self ; movzx Rq(dst), Rw(src));
1281 }
1282 (Size::S8, Location::Memory(src, disp), Size::S64, Location::GPR(dst)) => {
1283 dynasm!(self ; movzx Rq(dst), BYTE [Rq(src) + disp]);
1284 }
1285 (Size::S16, Location::Memory(src, disp), Size::S64, Location::GPR(dst)) => {
1286 dynasm!(self ; movzx Rq(dst), WORD [Rq(src) + disp]);
1287 }
1288 (Size::S32, Location::GPR(src), Size::S64, Location::GPR(dst)) => {
1289 dynasm!(self ; mov Rd(dst), Rd(src));
1290 }
1291 (Size::S32, Location::Memory(src, disp), Size::S64, Location::GPR(dst)) => {
1292 dynasm!(self ; mov Rd(dst), DWORD [Rq(src) + disp]);
1293 }
1294 (Size::S8, Location::Imm32(imm), Size::S32, Location::GPR(dst)) => {
1295 dynasm!(self ; mov Rq(dst), imm as i32);
1296 }
1297 (Size::S16, Location::Imm32(imm), Size::S64, Location::GPR(dst)) => {
1298 dynasm!(self ; mov Rq(dst), imm as i32);
1299 }
1300 (Size::S32, Location::Imm32(imm), Size::S64, Location::GPR(dst)) => {
1301 dynasm!(self ; mov Rq(dst), imm as i32);
1302 }
1303 (Size::S8, Location::Imm64(imm), Size::S64, Location::GPR(dst)) => {
1304 dynasm!(self ; mov Rq(dst), imm as i32);
1305 }
1306 (Size::S16, Location::Imm64(imm), Size::S64, Location::GPR(dst)) => {
1307 dynasm!(self ; mov Rq(dst), imm as i32);
1308 }
1309 (Size::S32, Location::Imm64(imm), Size::S64, Location::GPR(dst)) => {
1310 dynasm!(self ; mov Rq(dst), imm as i32);
1311 }
1312 _ => {
1313 codegen_error!(
1314 "singlepass can't emit MOVZX {:?} {:?} {:?} {:?}",
1315 sz_src,
1316 src,
1317 sz_dst,
1318 dst
1319 )
1320 }
1321 }
1322 Ok(())
1323 }
1324 fn emit_movsx(
1325 &mut self,
1326 sz_src: Size,
1327 src: Location,
1328 sz_dst: Size,
1329 dst: Location,
1330 ) -> Result<(), CompileError> {
1331 match (sz_src, src, sz_dst, dst) {
1332 (Size::S8, Location::GPR(src), Size::S32, Location::GPR(dst)) => {
1333 dynasm!(self ; movsx Rd(dst), Rb(src));
1334 }
1335 (Size::S16, Location::GPR(src), Size::S32, Location::GPR(dst)) => {
1336 dynasm!(self ; movsx Rd(dst), Rw(src));
1337 }
1338 (Size::S8, Location::Memory(src, disp), Size::S32, Location::GPR(dst)) => {
1339 dynasm!(self ; movsx Rd(dst), BYTE [Rq(src) + disp]);
1340 }
1341 (Size::S16, Location::Memory(src, disp), Size::S32, Location::GPR(dst)) => {
1342 dynasm!(self ; movsx Rd(dst), WORD [Rq(src) + disp]);
1343 }
1344 (Size::S8, Location::GPR(src), Size::S64, Location::GPR(dst)) => {
1345 dynasm!(self ; movsx Rq(dst), Rb(src));
1346 }
1347 (Size::S16, Location::GPR(src), Size::S64, Location::GPR(dst)) => {
1348 dynasm!(self ; movsx Rq(dst), Rw(src));
1349 }
1350 (Size::S32, Location::GPR(src), Size::S64, Location::GPR(dst)) => {
1351 dynasm!(self ; movsx Rq(dst), Rd(src));
1352 }
1353 (Size::S8, Location::Memory(src, disp), Size::S64, Location::GPR(dst)) => {
1354 dynasm!(self ; movsx Rq(dst), BYTE [Rq(src) + disp]);
1355 }
1356 (Size::S16, Location::Memory(src, disp), Size::S64, Location::GPR(dst)) => {
1357 dynasm!(self ; movsx Rq(dst), WORD [Rq(src) + disp]);
1358 }
1359 (Size::S32, Location::Memory(src, disp), Size::S64, Location::GPR(dst)) => {
1360 dynasm!(self ; movsx Rq(dst), DWORD [Rq(src) + disp]);
1361 }
1362 _ => {
1363 codegen_error!(
1364 "singlepass can't emit MOVSX {:?} {:?} {:?} {:?}",
1365 sz_src,
1366 src,
1367 sz_dst,
1368 dst
1369 )
1370 }
1371 }
1372 Ok(())
1373 }
1374
1375 fn emit_xchg(&mut self, sz: Size, src: Location, dst: Location) -> Result<(), CompileError> {
1376 match (sz, src, dst) {
1377 (Size::S8, Location::GPR(src), Location::GPR(dst)) => {
1378 dynasm!(self ; xchg Rb(dst), Rb(src));
1379 }
1380 (Size::S16, Location::GPR(src), Location::GPR(dst)) => {
1381 dynasm!(self ; xchg Rw(dst), Rw(src));
1382 }
1383 (Size::S32, Location::GPR(src), Location::GPR(dst)) => {
1384 dynasm!(self ; xchg Rd(dst), Rd(src));
1385 }
1386 (Size::S64, Location::GPR(src), Location::GPR(dst)) => {
1387 dynasm!(self ; xchg Rq(dst), Rq(src));
1388 }
1389 (Size::S8, Location::Memory(src, disp), Location::GPR(dst)) => {
1390 dynasm!(self ; xchg Rb(dst), [Rq(src) + disp]);
1391 }
1392 (Size::S8, Location::GPR(src), Location::Memory(dst, disp)) => {
1393 dynasm!(self ; xchg [Rq(dst) + disp], Rb(src));
1394 }
1395 (Size::S16, Location::Memory(src, disp), Location::GPR(dst)) => {
1396 dynasm!(self ; xchg Rw(dst), [Rq(src) + disp]);
1397 }
1398 (Size::S16, Location::GPR(src), Location::Memory(dst, disp)) => {
1399 dynasm!(self ; xchg [Rq(dst) + disp], Rw(src));
1400 }
1401 (Size::S32, Location::Memory(src, disp), Location::GPR(dst)) => {
1402 dynasm!(self ; xchg Rd(dst), [Rq(src) + disp]);
1403 }
1404 (Size::S32, Location::GPR(src), Location::Memory(dst, disp)) => {
1405 dynasm!(self ; xchg [Rq(dst) + disp], Rd(src));
1406 }
1407 (Size::S64, Location::Memory(src, disp), Location::GPR(dst)) => {
1408 dynasm!(self ; xchg Rq(dst), [Rq(src) + disp]);
1409 }
1410 (Size::S64, Location::GPR(src), Location::Memory(dst, disp)) => {
1411 dynasm!(self ; xchg [Rq(dst) + disp], Rq(src));
1412 }
1413 _ => codegen_error!("singlepass can't emit XCHG {:?} {:?} {:?}", sz, src, dst),
1414 }
1415 Ok(())
1416 }
1417
1418 fn emit_lock_xadd(
1419 &mut self,
1420 sz: Size,
1421 src: Location,
1422 dst: Location,
1423 ) -> Result<(), CompileError> {
1424 match (sz, src, dst) {
1425 (Size::S8, Location::GPR(src), Location::Memory(dst, disp)) => {
1426 dynasm!(self ; lock xadd [Rq(dst) + disp], Rb(src));
1427 }
1428 (Size::S16, Location::GPR(src), Location::Memory(dst, disp)) => {
1429 dynasm!(self ; lock xadd [Rq(dst) + disp], Rw(src));
1430 }
1431 (Size::S32, Location::GPR(src), Location::Memory(dst, disp)) => {
1432 dynasm!(self ; lock xadd [Rq(dst) + disp], Rd(src));
1433 }
1434 (Size::S64, Location::GPR(src), Location::Memory(dst, disp)) => {
1435 dynasm!(self ; lock xadd [Rq(dst) + disp], Rq(src));
1436 }
1437 _ => codegen_error!(
1438 "singlepass can't emit LOCK XADD {:?} {:?} {:?}",
1439 sz,
1440 src,
1441 dst
1442 ),
1443 }
1444 Ok(())
1445 }
1446
1447 fn emit_lock_cmpxchg(
1448 &mut self,
1449 sz: Size,
1450 src: Location,
1451 dst: Location,
1452 ) -> Result<(), CompileError> {
1453 match (sz, src, dst) {
1454 (Size::S8, Location::GPR(src), Location::Memory(dst, disp)) => {
1455 dynasm!(self ; lock cmpxchg [Rq(dst) + disp], Rb(src));
1456 }
1457 (Size::S16, Location::GPR(src), Location::Memory(dst, disp)) => {
1458 dynasm!(self ; lock cmpxchg [Rq(dst) + disp], Rw(src));
1459 }
1460 (Size::S32, Location::GPR(src), Location::Memory(dst, disp)) => {
1461 dynasm!(self ; lock cmpxchg [Rq(dst) + disp], Rd(src));
1462 }
1463 (Size::S64, Location::GPR(src), Location::Memory(dst, disp)) => {
1464 dynasm!(self ; lock cmpxchg [Rq(dst) + disp], Rq(src));
1465 }
1466 _ => codegen_error!(
1467 "singlepass can't emit LOCK CMPXCHG {:?} {:?} {:?}",
1468 sz,
1469 src,
1470 dst
1471 ),
1472 }
1473 Ok(())
1474 }
1475
1476 fn emit_rep_stosq(&mut self) -> Result<(), CompileError> {
1477 dynasm!(self ; rep stosq);
1478 Ok(())
1479 }
1480 fn emit_btc_gpr_imm8_32(&mut self, src: u8, dst: GPR) -> Result<(), CompileError> {
1481 dynasm!(self ; btc Rd(dst), BYTE src as i8);
1482 Ok(())
1483 }
1484
1485 fn emit_btc_gpr_imm8_64(&mut self, src: u8, dst: GPR) -> Result<(), CompileError> {
1486 dynasm!(self ; btc Rq(dst), BYTE src as i8);
1487 Ok(())
1488 }
1489
1490 fn emit_cmovae_gpr_32(&mut self, src: GPR, dst: GPR) -> Result<(), CompileError> {
1491 dynasm!(self ; cmovae Rd(dst), Rd(src));
1492 Ok(())
1493 }
1494
1495 fn emit_cmovae_gpr_64(&mut self, src: GPR, dst: GPR) -> Result<(), CompileError> {
1496 dynasm!(self ; cmovae Rq(dst), Rq(src));
1497 Ok(())
1498 }
1499
1500 fn emit_vmovaps(&mut self, src: XMMOrMemory, dst: XMMOrMemory) -> Result<(), CompileError> {
1501 match (src, dst) {
1502 (XMMOrMemory::XMM(src), XMMOrMemory::XMM(dst)) => {
1503 dynasm!(self ; movaps Rx(dst), Rx(src))
1504 }
1505 (XMMOrMemory::Memory(base, disp), XMMOrMemory::XMM(dst)) => {
1506 dynasm!(self ; movaps Rx(dst), [Rq(base) + disp])
1507 }
1508 (XMMOrMemory::XMM(src), XMMOrMemory::Memory(base, disp)) => {
1509 dynasm!(self ; movaps [Rq(base) + disp], Rx(src))
1510 }
1511 _ => codegen_error!("singlepass can't emit VMOVAPS {:?} {:?}", src, dst),
1512 };
1513 Ok(())
1514 }
1515
1516 fn emit_vmovapd(&mut self, src: XMMOrMemory, dst: XMMOrMemory) -> Result<(), CompileError> {
1517 match (src, dst) {
1518 (XMMOrMemory::XMM(src), XMMOrMemory::XMM(dst)) => {
1519 dynasm!(self ; movapd Rx(dst), Rx(src))
1520 }
1521 (XMMOrMemory::Memory(base, disp), XMMOrMemory::XMM(dst)) => {
1522 dynasm!(self ; movapd Rx(dst), [Rq(base) + disp])
1523 }
1524 (XMMOrMemory::XMM(src), XMMOrMemory::Memory(base, disp)) => {
1525 dynasm!(self ; movapd [Rq(base) + disp], Rx(src))
1526 }
1527 _ => codegen_error!("singlepass can't emit VMOVAPD {:?} {:?}", src, dst),
1528 };
1529 Ok(())
1530 }
1531 fn emit_vxorps(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1532 match self.get_simd_arch() {
1533 Some(CpuFeature::AVX) => avx_fn!(vxorps, self, src1, src2, dst),
1534 Some(CpuFeature::SSE42) => sse_fn!(xorps, self, Precision::Single, src1, src2, dst),
1535 _ => {}
1536 }
1537 Ok(())
1538 }
1539 fn emit_vxorpd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1540 match self.get_simd_arch() {
1541 Some(CpuFeature::AVX) => avx_fn!(vxorpd, self, src1, src2, dst),
1542 Some(CpuFeature::SSE42) => sse_fn!(xorpd, self, Precision::Double, src1, src2, dst),
1543 _ => {}
1544 }
1545 Ok(())
1546 }
1547 fn emit_vaddss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1548 match self.get_simd_arch() {
1549 Some(CpuFeature::AVX) => avx_fn!(vaddss, self, src1, src2, dst),
1550 Some(CpuFeature::SSE42) => sse_fn!(addss, self, Precision::Single, src1, src2, dst),
1551 _ => {}
1552 }
1553 Ok(())
1554 }
1555 fn emit_vaddsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1556 match self.get_simd_arch() {
1557 Some(CpuFeature::AVX) => avx_fn!(vaddsd, self, src1, src2, dst),
1558 Some(CpuFeature::SSE42) => sse_fn!(addsd, self, Precision::Double, src1, src2, dst),
1559 _ => {}
1560 }
1561 Ok(())
1562 }
1563 fn emit_vsubss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1564 match self.get_simd_arch() {
1565 Some(CpuFeature::AVX) => avx_fn!(vsubss, self, src1, src2, dst),
1566 Some(CpuFeature::SSE42) => sse_fn!(subss, self, Precision::Single, src1, src2, dst),
1567 _ => {}
1568 }
1569 Ok(())
1570 }
1571 fn emit_vsubsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1572 match self.get_simd_arch() {
1573 Some(CpuFeature::AVX) => avx_fn!(vsubsd, self, src1, src2, dst),
1574 Some(CpuFeature::SSE42) => sse_fn!(subsd, self, Precision::Double, src1, src2, dst),
1575 _ => {}
1576 }
1577 Ok(())
1578 }
1579 fn emit_vmulss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1580 match self.get_simd_arch() {
1581 Some(CpuFeature::AVX) => avx_fn!(vmulss, self, src1, src2, dst),
1582 Some(CpuFeature::SSE42) => sse_fn!(mulss, self, Precision::Single, src1, src2, dst),
1583 _ => {}
1584 }
1585 Ok(())
1586 }
1587 fn emit_vmulsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1588 match self.get_simd_arch() {
1589 Some(CpuFeature::AVX) => avx_fn!(vmulsd, self, src1, src2, dst),
1590 Some(CpuFeature::SSE42) => sse_fn!(mulsd, self, Precision::Double, src1, src2, dst),
1591 _ => {}
1592 }
1593 Ok(())
1594 }
1595 fn emit_vdivss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1596 match self.get_simd_arch() {
1597 Some(CpuFeature::AVX) => avx_fn!(vdivss, self, src1, src2, dst),
1598 Some(CpuFeature::SSE42) => sse_fn!(divss, self, Precision::Single, src1, src2, dst),
1599 _ => {}
1600 }
1601 Ok(())
1602 }
1603 fn emit_vdivsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1604 match self.get_simd_arch() {
1605 Some(CpuFeature::AVX) => avx_fn!(vdivsd, self, src1, src2, dst),
1606 Some(CpuFeature::SSE42) => sse_fn!(divsd, self, Precision::Double, src1, src2, dst),
1607 _ => {}
1608 }
1609 Ok(())
1610 }
1611 fn emit_vmaxss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1612 match self.get_simd_arch() {
1613 Some(CpuFeature::AVX) => avx_fn!(vmaxss, self, src1, src2, dst),
1614 Some(CpuFeature::SSE42) => sse_fn!(maxss, self, Precision::Single, src1, src2, dst),
1615 _ => {}
1616 }
1617 Ok(())
1618 }
1619 fn emit_vmaxsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1620 match self.get_simd_arch() {
1621 Some(CpuFeature::AVX) => avx_fn!(vmaxsd, self, src1, src2, dst),
1622 Some(CpuFeature::SSE42) => sse_fn!(maxsd, self, Precision::Double, src1, src2, dst),
1623 _ => {}
1624 }
1625 Ok(())
1626 }
1627 fn emit_vminss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1628 match self.get_simd_arch() {
1629 Some(CpuFeature::AVX) => avx_fn!(vminss, self, src1, src2, dst),
1630 Some(CpuFeature::SSE42) => sse_fn!(minss, self, Precision::Single, src1, src2, dst),
1631 _ => {}
1632 }
1633 Ok(())
1634 }
1635 fn emit_vminsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1636 match self.get_simd_arch() {
1637 Some(CpuFeature::AVX) => avx_fn!(vminsd, self, src1, src2, dst),
1638 Some(CpuFeature::SSE42) => sse_fn!(minsd, self, Precision::Double, src1, src2, dst),
1639 _ => {}
1640 }
1641 Ok(())
1642 }
1643 fn emit_vcmpeqss(
1644 &mut self,
1645 src1: XMM,
1646 src2: XMMOrMemory,
1647 dst: XMM,
1648 ) -> Result<(), CompileError> {
1649 match self.get_simd_arch() {
1650 Some(CpuFeature::AVX) => avx_fn!(vcmpeqss, self, src1, src2, dst),
1651 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 0, self, Precision::Single, src1, src2, dst),
1652 _ => {}
1653 }
1654 Ok(())
1655 }
1656 fn emit_vcmpeqsd(
1657 &mut self,
1658 src1: XMM,
1659 src2: XMMOrMemory,
1660 dst: XMM,
1661 ) -> Result<(), CompileError> {
1662 match self.get_simd_arch() {
1663 Some(CpuFeature::AVX) => avx_fn!(vcmpeqsd, self, src1, src2, dst),
1664 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 0, self, Precision::Double, src1, src2, dst),
1665 _ => {}
1666 }
1667 Ok(())
1668 }
1669 fn emit_vcmpneqss(
1670 &mut self,
1671 src1: XMM,
1672 src2: XMMOrMemory,
1673 dst: XMM,
1674 ) -> Result<(), CompileError> {
1675 match self.get_simd_arch() {
1676 Some(CpuFeature::AVX) => avx_fn!(vcmpneqss, self, src1, src2, dst),
1677 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 4, self, Precision::Single, src1, src2, dst),
1678 _ => {}
1679 }
1680 Ok(())
1681 }
1682 fn emit_vcmpneqsd(
1683 &mut self,
1684 src1: XMM,
1685 src2: XMMOrMemory,
1686 dst: XMM,
1687 ) -> Result<(), CompileError> {
1688 match self.get_simd_arch() {
1689 Some(CpuFeature::AVX) => avx_fn!(vcmpneqsd, self, src1, src2, dst),
1690 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 4, self, Precision::Double, src1, src2, dst),
1691 _ => {}
1692 }
1693 Ok(())
1694 }
1695 fn emit_vcmpltss(
1696 &mut self,
1697 src1: XMM,
1698 src2: XMMOrMemory,
1699 dst: XMM,
1700 ) -> Result<(), CompileError> {
1701 match self.get_simd_arch() {
1702 Some(CpuFeature::AVX) => avx_fn!(vcmpltss, self, src1, src2, dst),
1703 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 1, self, Precision::Single, src1, src2, dst),
1704 _ => {}
1705 }
1706 Ok(())
1707 }
1708 fn emit_vcmpltsd(
1709 &mut self,
1710 src1: XMM,
1711 src2: XMMOrMemory,
1712 dst: XMM,
1713 ) -> Result<(), CompileError> {
1714 match self.get_simd_arch() {
1715 Some(CpuFeature::AVX) => avx_fn!(vcmpltsd, self, src1, src2, dst),
1716 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 1, self, Precision::Double, src1, src2, dst),
1717 _ => {}
1718 }
1719 Ok(())
1720 }
1721 fn emit_vcmpless(
1722 &mut self,
1723 src1: XMM,
1724 src2: XMMOrMemory,
1725 dst: XMM,
1726 ) -> Result<(), CompileError> {
1727 match self.get_simd_arch() {
1728 Some(CpuFeature::AVX) => avx_fn!(vcmpless, self, src1, src2, dst),
1729 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 2, self, Precision::Single, src1, src2, dst),
1730 _ => {}
1731 }
1732 Ok(())
1733 }
1734 fn emit_vcmplesd(
1735 &mut self,
1736 src1: XMM,
1737 src2: XMMOrMemory,
1738 dst: XMM,
1739 ) -> Result<(), CompileError> {
1740 match self.get_simd_arch() {
1741 Some(CpuFeature::AVX) => avx_fn!(vcmplesd, self, src1, src2, dst),
1742 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 2, self, Precision::Double, src1, src2, dst),
1743 _ => {}
1744 }
1745 Ok(())
1746 }
1747 fn emit_vcmpgtss(
1748 &mut self,
1749 src1: XMM,
1750 src2: XMMOrMemory,
1751 dst: XMM,
1752 ) -> Result<(), CompileError> {
1753 match self.get_simd_arch() {
1754 Some(CpuFeature::AVX) => avx_fn!(vcmpgtss, self, src1, src2, dst),
1755 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 6, self, Precision::Single, src1, src2, dst),
1756 _ => {}
1757 }
1758 Ok(())
1759 }
1760 fn emit_vcmpgtsd(
1761 &mut self,
1762 src1: XMM,
1763 src2: XMMOrMemory,
1764 dst: XMM,
1765 ) -> Result<(), CompileError> {
1766 match self.get_simd_arch() {
1767 Some(CpuFeature::AVX) => avx_fn!(vcmpgtsd, self, src1, src2, dst),
1768 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 6, self, Precision::Double, src1, src2, dst),
1769 _ => {}
1770 }
1771 Ok(())
1772 }
1773 fn emit_vcmpgess(
1774 &mut self,
1775 src1: XMM,
1776 src2: XMMOrMemory,
1777 dst: XMM,
1778 ) -> Result<(), CompileError> {
1779 match self.get_simd_arch() {
1780 Some(CpuFeature::AVX) => avx_fn!(vcmpgess, self, src1, src2, dst),
1781 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 5, self, Precision::Single, src1, src2, dst),
1782 _ => {}
1783 }
1784 Ok(())
1785 }
1786 fn emit_vcmpgesd(
1787 &mut self,
1788 src1: XMM,
1789 src2: XMMOrMemory,
1790 dst: XMM,
1791 ) -> Result<(), CompileError> {
1792 match self.get_simd_arch() {
1793 Some(CpuFeature::AVX) => avx_fn!(vcmpgesd, self, src1, src2, dst),
1794 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 5, self, Precision::Double, src1, src2, dst),
1795 _ => {}
1796 }
1797 Ok(())
1798 }
1799 fn emit_vcmpunordss(
1800 &mut self,
1801 src1: XMM,
1802 src2: XMMOrMemory,
1803 dst: XMM,
1804 ) -> Result<(), CompileError> {
1805 match self.get_simd_arch() {
1806 Some(CpuFeature::AVX) => avx_fn!(vcmpunordss, self, src1, src2, dst),
1807 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 3, self, Precision::Single, src1, src2, dst),
1808 _ => {}
1809 }
1810 Ok(())
1811 }
1812 fn emit_vcmpunordsd(
1813 &mut self,
1814 src1: XMM,
1815 src2: XMMOrMemory,
1816 dst: XMM,
1817 ) -> Result<(), CompileError> {
1818 match self.get_simd_arch() {
1819 Some(CpuFeature::AVX) => avx_fn!(vcmpunordsd, self, src1, src2, dst),
1820 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 3, self, Precision::Double, src1, src2, dst),
1821 _ => {}
1822 }
1823 Ok(())
1824 }
1825 fn emit_vcmpordss(
1826 &mut self,
1827 src1: XMM,
1828 src2: XMMOrMemory,
1829 dst: XMM,
1830 ) -> Result<(), CompileError> {
1831 match self.get_simd_arch() {
1832 Some(CpuFeature::AVX) => avx_fn!(vcmpordss, self, src1, src2, dst),
1833 Some(CpuFeature::SSE42) => sse_fn!(cmpss, 7, self, Precision::Single, src1, src2, dst),
1834 _ => {}
1835 }
1836 Ok(())
1837 }
1838 fn emit_vcmpordsd(
1839 &mut self,
1840 src1: XMM,
1841 src2: XMMOrMemory,
1842 dst: XMM,
1843 ) -> Result<(), CompileError> {
1844 match self.get_simd_arch() {
1845 Some(CpuFeature::AVX) => avx_fn!(vcmpordsd, self, src1, src2, dst),
1846 Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 7, self, Precision::Double, src1, src2, dst),
1847 _ => {}
1848 }
1849 Ok(())
1850 }
1851 fn emit_vsqrtss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1852 match self.get_simd_arch() {
1853 Some(CpuFeature::AVX) => avx_fn!(vsqrtss, self, src1, src2, dst),
1854 Some(CpuFeature::SSE42) => sse_fn!(sqrtss, self, Precision::Single, src1, src2, dst),
1855 _ => {}
1856 }
1857 Ok(())
1858 }
1859 fn emit_vsqrtsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
1860 match self.get_simd_arch() {
1861 Some(CpuFeature::AVX) => avx_fn!(vsqrtsd, self, src1, src2, dst),
1862 Some(CpuFeature::SSE42) => sse_fn!(sqrtsd, self, Precision::Double, src1, src2, dst),
1863 _ => {}
1864 }
1865 Ok(())
1866 }
1867 fn emit_vcvtss2sd(
1868 &mut self,
1869 src1: XMM,
1870 src2: XMMOrMemory,
1871 dst: XMM,
1872 ) -> Result<(), CompileError> {
1873 match self.get_simd_arch() {
1874 Some(CpuFeature::AVX) => avx_fn!(vcvtss2sd, self, src1, src2, dst),
1875 Some(CpuFeature::SSE42) => sse_fn!(cvtss2sd, self, Precision::Single, src1, src2, dst),
1876 _ => {}
1877 }
1878 Ok(())
1879 }
1880 fn emit_vcvtsd2ss(
1881 &mut self,
1882 src1: XMM,
1883 src2: XMMOrMemory,
1884 dst: XMM,
1885 ) -> Result<(), CompileError> {
1886 match self.get_simd_arch() {
1887 Some(CpuFeature::AVX) => avx_fn!(vcvtsd2ss, self, src1, src2, dst),
1888 Some(CpuFeature::SSE42) => sse_fn!(cvtsd2ss, self, Precision::Double, src1, src2, dst),
1889 _ => {}
1890 }
1891 Ok(())
1892 }
1893 fn emit_vroundss_nearest(
1894 &mut self,
1895 src1: XMM,
1896 src2: XMMOrMemory,
1897 dst: XMM,
1898 ) -> Result<(), CompileError> {
1899 match self.get_simd_arch() {
1900 Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 0, self, src1, src2, dst),
1901 Some(CpuFeature::SSE42) => {
1902 sse_round_fn!(roundss, 0, self, Precision::Single, src1, src2, dst)
1903 }
1904 _ => {}
1905 }
1906 Ok(())
1907 }
1908 fn emit_vroundsd_nearest(
1909 &mut self,
1910 src1: XMM,
1911 src2: XMMOrMemory,
1912 dst: XMM,
1913 ) -> Result<(), CompileError> {
1914 match self.get_simd_arch() {
1915 Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 0, self, src1, src2, dst),
1916 Some(CpuFeature::SSE42) => {
1917 sse_round_fn!(roundsd, 0, self, Precision::Double, src1, src2, dst)
1918 }
1919 _ => {}
1920 }
1921 Ok(())
1922 }
1923 fn emit_vroundss_floor(
1924 &mut self,
1925 src1: XMM,
1926 src2: XMMOrMemory,
1927 dst: XMM,
1928 ) -> Result<(), CompileError> {
1929 match self.get_simd_arch() {
1930 Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 1, self, src1, src2, dst),
1931 Some(CpuFeature::SSE42) => {
1932 sse_round_fn!(roundss, 1, self, Precision::Single, src1, src2, dst)
1933 }
1934 _ => {}
1935 }
1936 Ok(())
1937 }
1938 fn emit_vroundsd_floor(
1939 &mut self,
1940 src1: XMM,
1941 src2: XMMOrMemory,
1942 dst: XMM,
1943 ) -> Result<(), CompileError> {
1944 match self.get_simd_arch() {
1945 Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 1, self, src1, src2, dst),
1946 Some(CpuFeature::SSE42) => {
1947 sse_round_fn!(roundsd, 1, self, Precision::Double, src1, src2, dst)
1948 }
1949 _ => {}
1950 }
1951 Ok(())
1952 }
1953 fn emit_vroundss_ceil(
1954 &mut self,
1955 src1: XMM,
1956 src2: XMMOrMemory,
1957 dst: XMM,
1958 ) -> Result<(), CompileError> {
1959 match self.get_simd_arch() {
1960 Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 2, self, src1, src2, dst),
1961 Some(CpuFeature::SSE42) => {
1962 sse_round_fn!(roundss, 2, self, Precision::Single, src1, src2, dst)
1963 }
1964 _ => {}
1965 }
1966 Ok(())
1967 }
1968 fn emit_vroundsd_ceil(
1969 &mut self,
1970 src1: XMM,
1971 src2: XMMOrMemory,
1972 dst: XMM,
1973 ) -> Result<(), CompileError> {
1974 match self.get_simd_arch() {
1975 Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 2, self, src1, src2, dst),
1976 Some(CpuFeature::SSE42) => {
1977 sse_round_fn!(roundsd, 2, self, Precision::Double, src1, src2, dst)
1978 }
1979 _ => {}
1980 }
1981 Ok(())
1982 }
1983 fn emit_vroundss_trunc(
1984 &mut self,
1985 src1: XMM,
1986 src2: XMMOrMemory,
1987 dst: XMM,
1988 ) -> Result<(), CompileError> {
1989 match self.get_simd_arch() {
1990 Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 3, self, src1, src2, dst),
1991 Some(CpuFeature::SSE42) => {
1992 sse_round_fn!(roundss, 3, self, Precision::Single, src1, src2, dst)
1993 }
1994 _ => {}
1995 }
1996 Ok(())
1997 }
1998 fn emit_vroundsd_trunc(
1999 &mut self,
2000 src1: XMM,
2001 src2: XMMOrMemory,
2002 dst: XMM,
2003 ) -> Result<(), CompileError> {
2004 match self.get_simd_arch() {
2005 Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 3, self, src1, src2, dst),
2006 Some(CpuFeature::SSE42) => {
2007 sse_round_fn!(roundsd, 3, self, Precision::Double, src1, src2, dst)
2008 }
2009 _ => {}
2010 }
2011 Ok(())
2012 }
2013 fn emit_vcvtsi2ss_32(
2014 &mut self,
2015 src1: XMM,
2016 src2: GPROrMemory,
2017 dst: XMM,
2018 ) -> Result<(), CompileError> {
2019 match self.get_simd_arch() {
2020 Some(CpuFeature::AVX) => avx_i2f_32_fn!(vcvtsi2ss, self, src1, src2, dst),
2021 Some(CpuFeature::SSE42) => {
2022 sse_i2f_32_fn!(cvtsi2ss, self, Precision::Single, src1, src2, dst)
2023 }
2024 _ => {}
2025 }
2026 Ok(())
2027 }
2028 fn emit_vcvtsi2sd_32(
2029 &mut self,
2030 src1: XMM,
2031 src2: GPROrMemory,
2032 dst: XMM,
2033 ) -> Result<(), CompileError> {
2034 match self.get_simd_arch() {
2035 Some(CpuFeature::AVX) => avx_i2f_32_fn!(vcvtsi2sd, self, src1, src2, dst),
2036 Some(CpuFeature::SSE42) => {
2037 sse_i2f_32_fn!(cvtsi2sd, self, Precision::Double, src1, src2, dst)
2038 }
2039 _ => {}
2040 }
2041 Ok(())
2042 }
2043 fn emit_vcvtsi2ss_64(
2044 &mut self,
2045 src1: XMM,
2046 src2: GPROrMemory,
2047 dst: XMM,
2048 ) -> Result<(), CompileError> {
2049 match self.get_simd_arch() {
2050 Some(CpuFeature::AVX) => avx_i2f_64_fn!(vcvtsi2ss, self, src1, src2, dst),
2051 Some(CpuFeature::SSE42) => {
2052 sse_i2f_64_fn!(cvtsi2ss, self, Precision::Single, src1, src2, dst)
2053 }
2054 _ => {}
2055 }
2056 Ok(())
2057 }
2058 fn emit_vcvtsi2sd_64(
2059 &mut self,
2060 src1: XMM,
2061 src2: GPROrMemory,
2062 dst: XMM,
2063 ) -> Result<(), CompileError> {
2064 match self.get_simd_arch() {
2065 Some(CpuFeature::AVX) => avx_i2f_64_fn!(vcvtsi2sd, self, src1, src2, dst),
2066 Some(CpuFeature::SSE42) => {
2067 sse_i2f_64_fn!(cvtsi2sd, self, Precision::Double, src1, src2, dst)
2068 }
2069 _ => {}
2070 }
2071 Ok(())
2072 }
2073
2074 fn emit_vblendvps(
2075 &mut self,
2076 src1: XMM,
2077 src2: XMMOrMemory,
2078 mask: XMM,
2079 dst: XMM,
2080 ) -> Result<(), CompileError> {
2081 match self.get_simd_arch() {
2083 Some(CpuFeature::AVX) => match src2 {
2084 XMMOrMemory::XMM(src2) => {
2085 dynasm!( self; vblendvps Rx(dst), Rx(mask), Rx(src2), Rx(src1))
2087 }
2088 XMMOrMemory::Memory(base, disp) => {
2089 dynasm!( self; vblendvps Rx(dst), Rx(mask), [Rq(base) + disp], Rx(src1))
2090 }
2091 },
2092 Some(CpuFeature::SSE42) => match src2 {
2093 XMMOrMemory::XMM(src2) => {
2094 move_src_to_dst(self, Precision::Single, src1, dst);
2095 dynasm!( self; blendvps Rx(dst), Rx(src2))
2096 }
2097 XMMOrMemory::Memory(base, disp) => {
2098 move_src_to_dst(self, Precision::Single, src1, dst);
2099 dynasm!( self; blendvps Rx(dst), [Rq(base) + disp])
2100 }
2101 },
2102 _ => {}
2103 }
2104 Ok(())
2105 }
2106
2107 fn emit_vblendvpd(
2108 &mut self,
2109 src1: XMM,
2110 src2: XMMOrMemory,
2111 mask: XMM,
2112 dst: XMM,
2113 ) -> Result<(), CompileError> {
2114 match self.get_simd_arch() {
2116 Some(CpuFeature::AVX) => match src2 {
2117 XMMOrMemory::XMM(src2) => {
2118 dynasm!( self; vblendvpd Rx(dst), Rx(mask), Rx(src2), Rx(src1))
2120 }
2121 XMMOrMemory::Memory(base, disp) => {
2122 dynasm!( self; vblendvpd Rx(dst), Rx(mask), [Rq(base) + disp], Rx(src1))
2123 }
2124 },
2125 Some(CpuFeature::SSE42) => match src2 {
2126 XMMOrMemory::XMM(src2) => {
2127 move_src_to_dst(self, Precision::Double, src1, dst);
2128 dynasm!( self; blendvpd Rx(dst), Rx(src2))
2129 }
2130 XMMOrMemory::Memory(base, disp) => {
2131 move_src_to_dst(self, Precision::Double, src1, dst);
2132 dynasm!( self; blendvpd Rx(dst), [Rq(base) + disp])
2133 }
2134 },
2135 _ => {}
2136 }
2137 Ok(())
2138 }
2139
2140 fn emit_ucomiss(&mut self, src: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
2141 match src {
2142 XMMOrMemory::XMM(x) => dynasm!(self ; ucomiss Rx(dst), Rx(x)),
2143 XMMOrMemory::Memory(base, disp) => {
2144 dynasm!(self ; ucomiss Rx(dst), [Rq(base) + disp])
2145 }
2146 }
2147 Ok(())
2148 }
2149
2150 fn emit_ucomisd(&mut self, src: XMMOrMemory, dst: XMM) -> Result<(), CompileError> {
2151 match src {
2152 XMMOrMemory::XMM(x) => dynasm!(self ; ucomisd Rx(dst), Rx(x)),
2153 XMMOrMemory::Memory(base, disp) => {
2154 dynasm!(self ; ucomisd Rx(dst), [Rq(base) + disp])
2155 }
2156 }
2157 Ok(())
2158 }
2159
2160 fn emit_cvttss2si_32(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError> {
2161 match src {
2162 XMMOrMemory::XMM(x) => dynasm!(self ; cvttss2si Rd(dst), Rx(x)),
2163 XMMOrMemory::Memory(base, disp) => {
2164 dynasm!(self ; cvttss2si Rd(dst), [Rq(base) + disp])
2165 }
2166 }
2167 Ok(())
2168 }
2169
2170 fn emit_cvttss2si_64(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError> {
2171 match src {
2172 XMMOrMemory::XMM(x) => dynasm!(self ; cvttss2si Rq(dst), Rx(x)),
2173 XMMOrMemory::Memory(base, disp) => {
2174 dynasm!(self ; cvttss2si Rq(dst), [Rq(base) + disp])
2175 }
2176 }
2177 Ok(())
2178 }
2179
2180 fn emit_cvttsd2si_32(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError> {
2181 match src {
2182 XMMOrMemory::XMM(x) => dynasm!(self ; cvttsd2si Rd(dst), Rx(x)),
2183 XMMOrMemory::Memory(base, disp) => {
2184 dynasm!(self ; cvttsd2si Rd(dst), [Rq(base) + disp])
2185 }
2186 }
2187 Ok(())
2188 }
2189
2190 fn emit_cvttsd2si_64(&mut self, src: XMMOrMemory, dst: GPR) -> Result<(), CompileError> {
2191 match src {
2192 XMMOrMemory::XMM(x) => dynasm!(self ; cvttsd2si Rq(dst), Rx(x)),
2193 XMMOrMemory::Memory(base, disp) => {
2194 dynasm!(self ; cvttsd2si Rq(dst), [Rq(base) + disp])
2195 }
2196 }
2197 Ok(())
2198 }
2199
2200 fn emit_test_gpr_64(&mut self, reg: GPR) -> Result<(), CompileError> {
2201 dynasm!(self ; test Rq(reg), Rq(reg));
2202 Ok(())
2203 }
2204
2205 fn emit_ud2(&mut self) -> Result<(), CompileError> {
2206 dynasm!(self ; ud2);
2207 Ok(())
2208 }
2209 #[allow(clippy::useless_conversion)]
2210 fn emit_ud1_payload(&mut self, payload: u8) -> Result<(), CompileError> {
2211 assert!(payload & 0xf0 == 0);
2212 let reg1 = (payload >> 3) & 1;
2213 let reg2 = payload & 7;
2214
2215 dynasm!(self ; ud1 Rd(reg1), Rd(reg2));
2216 Ok(())
2217 }
2218 fn emit_ret(&mut self) -> Result<(), CompileError> {
2219 dynasm!(self ; ret);
2220 Ok(())
2221 }
2222
2223 fn emit_call_label(&mut self, label: Label) -> Result<(), CompileError> {
2224 dynasm!(self ; call =>label);
2225 Ok(())
2226 }
2227 fn emit_call_location(&mut self, loc: Location) -> Result<(), CompileError> {
2228 match loc {
2229 Location::GPR(x) => dynasm!(self ; call Rq(x)),
2230 Location::Memory(base, disp) => dynasm!(self ; call QWORD [Rq(base) + disp]),
2231 _ => codegen_error!("singlepass can't emit CALL {:?}", loc),
2232 }
2233 Ok(())
2234 }
2235
2236 fn emit_call_register(&mut self, reg: GPR) -> Result<(), CompileError> {
2237 dynasm!(self ; call Rq(reg));
2238 Ok(())
2239 }
2240
2241 fn emit_bkpt(&mut self) -> Result<(), CompileError> {
2242 dynasm!(self ; int3);
2243 Ok(())
2244 }
2245
2246 fn emit_host_redirection(&mut self, target: GPR) -> Result<(), CompileError> {
2247 self.emit_jmp_location(Location::GPR(target))
2248 }
2249
2250 fn arch_mov64_imm_offset(&self) -> Result<usize, CompileError> {
2251 Ok(2)
2252 }
2253}