[feat]: Adding the plumbing necessary for the singlepass to choose between different simd instruction sets. Partial work on supporting SSE4.2

This commit is contained in:
R2D2
2022-01-30 10:55:26 +01:00
parent 67be3eaa51
commit b32b5cfa53
6 changed files with 928 additions and 315 deletions

View File

@ -12,9 +12,9 @@ readme = "README.md"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmer-compiler = { path = "../compiler", version = "=2.1.1", features = ["translator"], default-features = false } wasmer-compiler = { path = "../compiler", version = "2.1.1", features = ["translator"], default-features = false }
wasmer-vm = { path = "../vm", version = "=2.1.1" } wasmer-vm = { path = "../vm", version = "2.1.1" }
wasmer-types = { path = "../types", version = "=2.1.1", default-features = false, features = ["std"] } wasmer-types = { path = "../types", version = "2.1.1", default-features = false, features = ["std"] }
rayon = { version = "1.5", optional = true } rayon = { version = "1.5", optional = true }
hashbrown = { version = "0.11", optional = true } hashbrown = { version = "0.11", optional = true }
more-asserts = "0.2" more-asserts = "0.2"
@ -32,6 +32,8 @@ target-lexicon = { version = "0.12.2", default-features = false }
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[features] [features]
default = ["std", "rayon"] default = ["std", "rayon", "avx"]
std = ["wasmer-compiler/std", "wasmer-types/std"] std = ["wasmer-compiler/std", "wasmer-types/std"]
core = ["hashbrown", "wasmer-types/core"] core = ["hashbrown", "wasmer-types/core"]
sse = []
avx = []

View File

@ -5784,7 +5784,7 @@ impl<'a, M: Machine> FuncGen<'a, M> {
.mark_address_with_trap_code(TrapCode::BadSignature); .mark_address_with_trap_code(TrapCode::BadSignature);
self.machine.emit_illegal_op(); self.machine.emit_illegal_op();
// Notify the assembler backend to generate necessary code at end of function. // Notify the inner backend to generate necessary code at end of function.
self.machine.finalize_function(); self.machine.finalize_function();
let body_len = self.machine.assembler_get_offset().0; let body_len = self.machine.assembler_get_offset().0;

View File

@ -68,11 +68,15 @@ impl Compiler for SinglepassCompiler {
target.triple().architecture.to_string(), target.triple().architecture.to_string(),
)); ));
} }
if !target.cpu_features().contains(CpuFeature::AVX) { let simd_arch = if target.cpu_features().contains(CpuFeature::AVX) {
CpuFeature::AVX
} else if target.cpu_features().contains(CpuFeature::SSE42) {
CpuFeature::SSE42
} else {
return Err(CompileError::UnsupportedTarget( return Err(CompileError::UnsupportedTarget(
"x86_64 without AVX".to_string(), "x86_64 without AVX or SSE 4.2".to_string(),
)); ));
} };
if compile_info.features.multi_value { if compile_info.features.multi_value {
return Err(CompileError::UnsupportedFeature("multivalue".to_string())); return Err(CompileError::UnsupportedFeature("multivalue".to_string()));
} }
@ -127,7 +131,7 @@ impl Compiler for SinglepassCompiler {
} }
let machine = match target.triple().architecture { let machine = match target.triple().architecture {
Architecture::X86_64 => MachineX86_64::new(), Architecture::X86_64 => MachineX86_64::new(Some(simd_arch)),
_ => unimplemented!(), _ => unimplemented!(),
}; };
let mut generator = FuncGen::new( let mut generator = FuncGen::new(

View File

@ -2,13 +2,13 @@ use crate::common_decl::Size;
use crate::location::Location as AbstractLocation; use crate::location::Location as AbstractLocation;
pub use crate::location::Multiplier; pub use crate::location::Multiplier;
pub use crate::machine::{Label, Offset}; pub use crate::machine::{Label, Offset};
use crate::machine_x64::AssemblerX64;
pub use crate::x64_decl::{GPR, XMM}; pub use crate::x64_decl::{GPR, XMM};
use dynasm::dynasm; use dynasm::dynasm;
use dynasmrt::{ use dynasmrt::{
x64::X64Relocation, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, VecAssembler, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi,
}; };
use wasmer_compiler::CpuFeature;
type Assembler = VecAssembler<X64Relocation>;
/// Force `dynasm!` to use the correct arch (x64) when cross-compiling. /// Force `dynasm!` to use the correct arch (x64) when cross-compiling.
/// `dynasm!` proc-macro tries to auto-detect it by default by looking at the /// `dynasm!` proc-macro tries to auto-detect it by default by looking at the
@ -17,7 +17,7 @@ type Assembler = VecAssembler<X64Relocation>;
macro_rules! dynasm { macro_rules! dynasm {
($a:expr ; $($tt:tt)*) => { ($a:expr ; $($tt:tt)*) => {
dynasm::dynasm!( dynasm::dynasm!(
$a $a.inner
; .arch x64 ; .arch x64
; $($tt)* ; $($tt)*
) )
@ -58,6 +58,7 @@ pub enum GPROrMemory {
} }
pub trait EmitterX64 { pub trait EmitterX64 {
fn get_simd_arch(&self) -> Option<&CpuFeature>;
fn get_label(&mut self) -> Label; fn get_label(&mut self) -> Label;
fn get_offset(&self) -> Offset; fn get_offset(&self) -> Offset;
fn get_jmp_instr_size(&self) -> u8; fn get_jmp_instr_size(&self) -> u8;
@ -71,7 +72,7 @@ pub trait EmitterX64 {
fn emit_nop(&mut self); fn emit_nop(&mut self);
/// A high-level assembler method. Emits an instruction sequence of length `n` that is functionally /// A high-level inner method. Emits an instruction sequence of length `n` that is functionally
/// equivalent to a `nop` instruction, without guarantee about the underlying implementation. /// equivalent to a `nop` instruction, without guarantee about the underlying implementation.
fn emit_nop_n(&mut self, n: usize); fn emit_nop_n(&mut self, n: usize);
@ -123,6 +124,7 @@ pub trait EmitterX64 {
fn emit_vxorps(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM); fn emit_vxorps(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM);
fn emit_vxorpd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM); fn emit_vxorpd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM);
fn emit_vaddss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM); fn emit_vaddss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM);
fn emit_vaddsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM); fn emit_vaddsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM);
fn emit_vsubss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM); fn emit_vsubss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM);
@ -472,153 +474,439 @@ macro_rules! jmp_op {
} }
macro_rules! avx_fn { macro_rules! avx_fn {
($ins:ident, $name:ident) => { ($ins:ident) => {
fn $name(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) { |emitter: &mut AssemblerX64, src1: XMM, src2: XMMOrMemory, dst: XMM| {
// Dynasm bug: AVX instructions are not encoded correctly. // Dynasm bug: AVX instructions are not encoded correctly.
match src2 { match src2 {
XMMOrMemory::XMM(x) => match src1 { XMMOrMemory::XMM(x) => match src1 {
XMM::XMM0 => dynasm!(self ; $ins Rx((dst as u8)), xmm0, Rx((x as u8))), XMM::XMM0 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm0, Rx((x as u8))),
XMM::XMM1 => dynasm!(self ; $ins Rx((dst as u8)), xmm1, Rx((x as u8))), XMM::XMM1 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm1, Rx((x as u8))),
XMM::XMM2 => dynasm!(self ; $ins Rx((dst as u8)), xmm2, Rx((x as u8))), XMM::XMM2 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm2, Rx((x as u8))),
XMM::XMM3 => dynasm!(self ; $ins Rx((dst as u8)), xmm3, Rx((x as u8))), XMM::XMM3 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm3, Rx((x as u8))),
XMM::XMM4 => dynasm!(self ; $ins Rx((dst as u8)), xmm4, Rx((x as u8))), XMM::XMM4 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm4, Rx((x as u8))),
XMM::XMM5 => dynasm!(self ; $ins Rx((dst as u8)), xmm5, Rx((x as u8))), XMM::XMM5 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm5, Rx((x as u8))),
XMM::XMM6 => dynasm!(self ; $ins Rx((dst as u8)), xmm6, Rx((x as u8))), XMM::XMM6 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm6, Rx((x as u8))),
XMM::XMM7 => dynasm!(self ; $ins Rx((dst as u8)), xmm7, Rx((x as u8))), XMM::XMM7 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm7, Rx((x as u8))),
XMM::XMM8 => dynasm!(self ; $ins Rx((dst as u8)), xmm8, Rx((x as u8))), XMM::XMM8 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm8, Rx((x as u8))),
XMM::XMM9 => dynasm!(self ; $ins Rx((dst as u8)), xmm9, Rx((x as u8))), XMM::XMM9 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm9, Rx((x as u8))),
XMM::XMM10 => dynasm!(self ; $ins Rx((dst as u8)), xmm10, Rx((x as u8))), XMM::XMM10 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm10, Rx((x as u8))),
XMM::XMM11 => dynasm!(self ; $ins Rx((dst as u8)), xmm11, Rx((x as u8))), XMM::XMM11 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm11, Rx((x as u8))),
XMM::XMM12 => dynasm!(self ; $ins Rx((dst as u8)), xmm12, Rx((x as u8))), XMM::XMM12 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm12, Rx((x as u8))),
XMM::XMM13 => dynasm!(self ; $ins Rx((dst as u8)), xmm13, Rx((x as u8))), XMM::XMM13 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm13, Rx((x as u8))),
XMM::XMM14 => dynasm!(self ; $ins Rx((dst as u8)), xmm14, Rx((x as u8))), XMM::XMM14 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm14, Rx((x as u8))),
XMM::XMM15 => dynasm!(self ; $ins Rx((dst as u8)), xmm15, Rx((x as u8))), XMM::XMM15 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm15, Rx((x as u8))),
}, },
XMMOrMemory::Memory(base, disp) => match src1 { XMMOrMemory::Memory(base, disp) => match src1 {
XMM::XMM0 => dynasm!(self ; $ins Rx((dst as u8)), xmm0, [Rq((base as u8)) + disp]), XMM::XMM0 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm0, [Rq((base as u8)) + disp]),
XMM::XMM1 => dynasm!(self ; $ins Rx((dst as u8)), xmm1, [Rq((base as u8)) + disp]), XMM::XMM1 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm1, [Rq((base as u8)) + disp]),
XMM::XMM2 => dynasm!(self ; $ins Rx((dst as u8)), xmm2, [Rq((base as u8)) + disp]), XMM::XMM2 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm2, [Rq((base as u8)) + disp]),
XMM::XMM3 => dynasm!(self ; $ins Rx((dst as u8)), xmm3, [Rq((base as u8)) + disp]), XMM::XMM3 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm3, [Rq((base as u8)) + disp]),
XMM::XMM4 => dynasm!(self ; $ins Rx((dst as u8)), xmm4, [Rq((base as u8)) + disp]), XMM::XMM4 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm4, [Rq((base as u8)) + disp]),
XMM::XMM5 => dynasm!(self ; $ins Rx((dst as u8)), xmm5, [Rq((base as u8)) + disp]), XMM::XMM5 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm5, [Rq((base as u8)) + disp]),
XMM::XMM6 => dynasm!(self ; $ins Rx((dst as u8)), xmm6, [Rq((base as u8)) + disp]), XMM::XMM6 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm6, [Rq((base as u8)) + disp]),
XMM::XMM7 => dynasm!(self ; $ins Rx((dst as u8)), xmm7, [Rq((base as u8)) + disp]), XMM::XMM7 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm7, [Rq((base as u8)) + disp]),
XMM::XMM8 => dynasm!(self ; $ins Rx((dst as u8)), xmm8, [Rq((base as u8)) + disp]), XMM::XMM8 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm8, [Rq((base as u8)) + disp]),
XMM::XMM9 => dynasm!(self ; $ins Rx((dst as u8)), xmm9, [Rq((base as u8)) + disp]), XMM::XMM9 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm9, [Rq((base as u8)) + disp]),
XMM::XMM10 => dynasm!(self ; $ins Rx((dst as u8)), xmm10, [Rq((base as u8)) + disp]), XMM::XMM10 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm10, [Rq((base as u8)) + disp]),
XMM::XMM11 => dynasm!(self ; $ins Rx((dst as u8)), xmm11, [Rq((base as u8)) + disp]), XMM::XMM11 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm11, [Rq((base as u8)) + disp]),
XMM::XMM12 => dynasm!(self ; $ins Rx((dst as u8)), xmm12, [Rq((base as u8)) + disp]), XMM::XMM12 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm12, [Rq((base as u8)) + disp]),
XMM::XMM13 => dynasm!(self ; $ins Rx((dst as u8)), xmm13, [Rq((base as u8)) + disp]), XMM::XMM13 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm13, [Rq((base as u8)) + disp]),
XMM::XMM14 => dynasm!(self ; $ins Rx((dst as u8)), xmm14, [Rq((base as u8)) + disp]), XMM::XMM14 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm14, [Rq((base as u8)) + disp]),
XMM::XMM15 => dynasm!(self ; $ins Rx((dst as u8)), xmm15, [Rq((base as u8)) + disp]), XMM::XMM15 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm15, [Rq((base as u8)) + disp]),
}, },
} }
} }
} }
} }
macro_rules! sse_fn {
($ins:ident) => {
|emitter: &mut AssemblerX64, src1: XMM, src2: XMMOrMemory, dst: XMM| {
match src2 {
XMMOrMemory::XMM(x) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), Rx((x as u8))),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), Rx((x as u8))),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), Rx((x as u8)))
}
}
XMMOrMemory::Memory(base, disp) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), [Rq((base as u8)) + disp]),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), [Rq((base as u8)) + disp])
}
}
}
}
};
($ins:ident, $mode:expr) => {
|emitter: &mut AssemblerX64, src1: XMM, src2: XMMOrMemory, dst: XMM| {
match src2 {
XMMOrMemory::XMM(x) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), Rx((x as u8)), $mode)
}
}
XMMOrMemory::Memory(base, disp) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), [Rq((base as u8)) + disp], $mode)
}
}
}
}
};
}
macro_rules! avx_i2f_64_fn { macro_rules! avx_i2f_64_fn {
($ins:ident, $name:ident) => { ($ins:ident) => {
fn $name(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM) { |emitter: &mut AssemblerX64, src1: XMM, src2: GPROrMemory, dst: XMM| {
match src2 { match src2 {
GPROrMemory::GPR(x) => match src1 { GPROrMemory::GPR(x) => match src1 {
XMM::XMM0 => dynasm!(self ; $ins Rx((dst as u8)), xmm0, Rq((x as u8))), XMM::XMM0 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm0, Rq((x as u8))),
XMM::XMM1 => dynasm!(self ; $ins Rx((dst as u8)), xmm1, Rq((x as u8))), XMM::XMM1 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm1, Rq((x as u8))),
XMM::XMM2 => dynasm!(self ; $ins Rx((dst as u8)), xmm2, Rq((x as u8))), XMM::XMM2 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm2, Rq((x as u8))),
XMM::XMM3 => dynasm!(self ; $ins Rx((dst as u8)), xmm3, Rq((x as u8))), XMM::XMM3 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm3, Rq((x as u8))),
XMM::XMM4 => dynasm!(self ; $ins Rx((dst as u8)), xmm4, Rq((x as u8))), XMM::XMM4 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm4, Rq((x as u8))),
XMM::XMM5 => dynasm!(self ; $ins Rx((dst as u8)), xmm5, Rq((x as u8))), XMM::XMM5 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm5, Rq((x as u8))),
XMM::XMM6 => dynasm!(self ; $ins Rx((dst as u8)), xmm6, Rq((x as u8))), XMM::XMM6 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm6, Rq((x as u8))),
XMM::XMM7 => dynasm!(self ; $ins Rx((dst as u8)), xmm7, Rq((x as u8))), XMM::XMM7 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm7, Rq((x as u8))),
XMM::XMM8 => dynasm!(self ; $ins Rx((dst as u8)), xmm8, Rq((x as u8))), XMM::XMM8 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm8, Rq((x as u8))),
XMM::XMM9 => dynasm!(self ; $ins Rx((dst as u8)), xmm9, Rq((x as u8))), XMM::XMM9 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm9, Rq((x as u8))),
XMM::XMM10 => dynasm!(self ; $ins Rx((dst as u8)), xmm10, Rq((x as u8))), XMM::XMM10 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm10, Rq((x as u8))),
XMM::XMM11 => dynasm!(self ; $ins Rx((dst as u8)), xmm11, Rq((x as u8))), XMM::XMM11 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm11, Rq((x as u8))),
XMM::XMM12 => dynasm!(self ; $ins Rx((dst as u8)), xmm12, Rq((x as u8))), XMM::XMM12 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm12, Rq((x as u8))),
XMM::XMM13 => dynasm!(self ; $ins Rx((dst as u8)), xmm13, Rq((x as u8))), XMM::XMM13 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm13, Rq((x as u8))),
XMM::XMM14 => dynasm!(self ; $ins Rx((dst as u8)), xmm14, Rq((x as u8))), XMM::XMM14 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm14, Rq((x as u8))),
XMM::XMM15 => dynasm!(self ; $ins Rx((dst as u8)), xmm15, Rq((x as u8))), XMM::XMM15 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm15, Rq((x as u8))),
}, },
GPROrMemory::Memory(base, disp) => match src1 { GPROrMemory::Memory(base, disp) => match src1 {
XMM::XMM0 => dynasm!(self ; $ins Rx((dst as u8)), xmm0, QWORD [Rq((base as u8)) + disp]), XMM::XMM0 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm0, QWORD [Rq((base as u8)) + disp]),
XMM::XMM1 => dynasm!(self ; $ins Rx((dst as u8)), xmm1, QWORD [Rq((base as u8)) + disp]), XMM::XMM1 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm1, QWORD [Rq((base as u8)) + disp]),
XMM::XMM2 => dynasm!(self ; $ins Rx((dst as u8)), xmm2, QWORD [Rq((base as u8)) + disp]), XMM::XMM2 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm2, QWORD [Rq((base as u8)) + disp]),
XMM::XMM3 => dynasm!(self ; $ins Rx((dst as u8)), xmm3, QWORD [Rq((base as u8)) + disp]), XMM::XMM3 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm3, QWORD [Rq((base as u8)) + disp]),
XMM::XMM4 => dynasm!(self ; $ins Rx((dst as u8)), xmm4, QWORD [Rq((base as u8)) + disp]), XMM::XMM4 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm4, QWORD [Rq((base as u8)) + disp]),
XMM::XMM5 => dynasm!(self ; $ins Rx((dst as u8)), xmm5, QWORD [Rq((base as u8)) + disp]), XMM::XMM5 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm5, QWORD [Rq((base as u8)) + disp]),
XMM::XMM6 => dynasm!(self ; $ins Rx((dst as u8)), xmm6, QWORD [Rq((base as u8)) + disp]), XMM::XMM6 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm6, QWORD [Rq((base as u8)) + disp]),
XMM::XMM7 => dynasm!(self ; $ins Rx((dst as u8)), xmm7, QWORD [Rq((base as u8)) + disp]), XMM::XMM7 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm7, QWORD [Rq((base as u8)) + disp]),
XMM::XMM8 => dynasm!(self ; $ins Rx((dst as u8)), xmm8, QWORD [Rq((base as u8)) + disp]), XMM::XMM8 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm8, QWORD [Rq((base as u8)) + disp]),
XMM::XMM9 => dynasm!(self ; $ins Rx((dst as u8)), xmm9, QWORD [Rq((base as u8)) + disp]), XMM::XMM9 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm9, QWORD [Rq((base as u8)) + disp]),
XMM::XMM10 => dynasm!(self ; $ins Rx((dst as u8)), xmm10, QWORD [Rq((base as u8)) + disp]), XMM::XMM10 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm10, QWORD [Rq((base as u8)) + disp]),
XMM::XMM11 => dynasm!(self ; $ins Rx((dst as u8)), xmm11, QWORD [Rq((base as u8)) + disp]), XMM::XMM11 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm11, QWORD [Rq((base as u8)) + disp]),
XMM::XMM12 => dynasm!(self ; $ins Rx((dst as u8)), xmm12, QWORD [Rq((base as u8)) + disp]), XMM::XMM12 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm12, QWORD [Rq((base as u8)) + disp]),
XMM::XMM13 => dynasm!(self ; $ins Rx((dst as u8)), xmm13, QWORD [Rq((base as u8)) + disp]), XMM::XMM13 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm13, QWORD [Rq((base as u8)) + disp]),
XMM::XMM14 => dynasm!(self ; $ins Rx((dst as u8)), xmm14, QWORD [Rq((base as u8)) + disp]), XMM::XMM14 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm14, QWORD [Rq((base as u8)) + disp]),
XMM::XMM15 => dynasm!(self ; $ins Rx((dst as u8)), xmm15, QWORD [Rq((base as u8)) + disp]), XMM::XMM15 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm15, QWORD [Rq((base as u8)) + disp]),
}, },
} }
} }
} }
} }
macro_rules! sse_i2f_64_fn {
($ins:ident) => {
|emitter: &mut AssemblerX64, src1: XMM, src2: GPROrMemory, dst: XMM| {
match src2 {
GPROrMemory::GPR(x) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), Rq((x as u8))),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), Rq((x as u8))),
}
} else {
dynasm!(emitter ; $ins Rx((dst as u8)), Rq((x as u8)))
}
},
GPROrMemory::Memory(base, disp) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), QWORD [Rq((base as u8)) + disp]),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), QWORD [Rq((base as u8)) + disp])
}
}
}
}
}
}
macro_rules! avx_i2f_32_fn { macro_rules! avx_i2f_32_fn {
($ins:ident, $name:ident) => { ($ins:ident) => {
fn $name(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM) { |emitter: &mut AssemblerX64, src1: XMM, src2: GPROrMemory, dst: XMM| {
match src2 { match src2 {
GPROrMemory::GPR(x) => match src1 { GPROrMemory::GPR(x) => match src1 {
XMM::XMM0 => dynasm!(self ; $ins Rx((dst as u8)), xmm0, Rd((x as u8))), XMM::XMM0 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm0, Rd((x as u8))),
XMM::XMM1 => dynasm!(self ; $ins Rx((dst as u8)), xmm1, Rd((x as u8))), XMM::XMM1 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm1, Rd((x as u8))),
XMM::XMM2 => dynasm!(self ; $ins Rx((dst as u8)), xmm2, Rd((x as u8))), XMM::XMM2 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm2, Rd((x as u8))),
XMM::XMM3 => dynasm!(self ; $ins Rx((dst as u8)), xmm3, Rd((x as u8))), XMM::XMM3 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm3, Rd((x as u8))),
XMM::XMM4 => dynasm!(self ; $ins Rx((dst as u8)), xmm4, Rd((x as u8))), XMM::XMM4 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm4, Rd((x as u8))),
XMM::XMM5 => dynasm!(self ; $ins Rx((dst as u8)), xmm5, Rd((x as u8))), XMM::XMM5 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm5, Rd((x as u8))),
XMM::XMM6 => dynasm!(self ; $ins Rx((dst as u8)), xmm6, Rd((x as u8))), XMM::XMM6 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm6, Rd((x as u8))),
XMM::XMM7 => dynasm!(self ; $ins Rx((dst as u8)), xmm7, Rd((x as u8))), XMM::XMM7 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm7, Rd((x as u8))),
XMM::XMM8 => dynasm!(self ; $ins Rx((dst as u8)), xmm8, Rd((x as u8))), XMM::XMM8 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm8, Rd((x as u8))),
XMM::XMM9 => dynasm!(self ; $ins Rx((dst as u8)), xmm9, Rd((x as u8))), XMM::XMM9 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm9, Rd((x as u8))),
XMM::XMM10 => dynasm!(self ; $ins Rx((dst as u8)), xmm10, Rd((x as u8))), XMM::XMM10 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm10, Rd((x as u8))),
XMM::XMM11 => dynasm!(self ; $ins Rx((dst as u8)), xmm11, Rd((x as u8))), XMM::XMM11 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm11, Rd((x as u8))),
XMM::XMM12 => dynasm!(self ; $ins Rx((dst as u8)), xmm12, Rd((x as u8))), XMM::XMM12 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm12, Rd((x as u8))),
XMM::XMM13 => dynasm!(self ; $ins Rx((dst as u8)), xmm13, Rd((x as u8))), XMM::XMM13 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm13, Rd((x as u8))),
XMM::XMM14 => dynasm!(self ; $ins Rx((dst as u8)), xmm14, Rd((x as u8))), XMM::XMM14 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm14, Rd((x as u8))),
XMM::XMM15 => dynasm!(self ; $ins Rx((dst as u8)), xmm15, Rd((x as u8))), XMM::XMM15 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm15, Rd((x as u8))),
}, },
GPROrMemory::Memory(base, disp) => match src1 { GPROrMemory::Memory(base, disp) => match src1 {
XMM::XMM0 => dynasm!(self ; $ins Rx((dst as u8)), xmm0, DWORD [Rq((base as u8)) + disp]), XMM::XMM0 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm0, DWORD [Rq((base as u8)) + disp]),
XMM::XMM1 => dynasm!(self ; $ins Rx((dst as u8)), xmm1, DWORD [Rq((base as u8)) + disp]), XMM::XMM1 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm1, DWORD [Rq((base as u8)) + disp]),
XMM::XMM2 => dynasm!(self ; $ins Rx((dst as u8)), xmm2, DWORD [Rq((base as u8)) + disp]), XMM::XMM2 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm2, DWORD [Rq((base as u8)) + disp]),
XMM::XMM3 => dynasm!(self ; $ins Rx((dst as u8)), xmm3, DWORD [Rq((base as u8)) + disp]), XMM::XMM3 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm3, DWORD [Rq((base as u8)) + disp]),
XMM::XMM4 => dynasm!(self ; $ins Rx((dst as u8)), xmm4, DWORD [Rq((base as u8)) + disp]), XMM::XMM4 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm4, DWORD [Rq((base as u8)) + disp]),
XMM::XMM5 => dynasm!(self ; $ins Rx((dst as u8)), xmm5, DWORD [Rq((base as u8)) + disp]), XMM::XMM5 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm5, DWORD [Rq((base as u8)) + disp]),
XMM::XMM6 => dynasm!(self ; $ins Rx((dst as u8)), xmm6, DWORD [Rq((base as u8)) + disp]), XMM::XMM6 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm6, DWORD [Rq((base as u8)) + disp]),
XMM::XMM7 => dynasm!(self ; $ins Rx((dst as u8)), xmm7, DWORD [Rq((base as u8)) + disp]), XMM::XMM7 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm7, DWORD [Rq((base as u8)) + disp]),
XMM::XMM8 => dynasm!(self ; $ins Rx((dst as u8)), xmm8, DWORD [Rq((base as u8)) + disp]), XMM::XMM8 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm8, DWORD [Rq((base as u8)) + disp]),
XMM::XMM9 => dynasm!(self ; $ins Rx((dst as u8)), xmm9, DWORD [Rq((base as u8)) + disp]), XMM::XMM9 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm9, DWORD [Rq((base as u8)) + disp]),
XMM::XMM10 => dynasm!(self ; $ins Rx((dst as u8)), xmm10, DWORD [Rq((base as u8)) + disp]), XMM::XMM10 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm10, DWORD [Rq((base as u8)) + disp]),
XMM::XMM11 => dynasm!(self ; $ins Rx((dst as u8)), xmm11, DWORD [Rq((base as u8)) + disp]), XMM::XMM11 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm11, DWORD [Rq((base as u8)) + disp]),
XMM::XMM12 => dynasm!(self ; $ins Rx((dst as u8)), xmm12, DWORD [Rq((base as u8)) + disp]), XMM::XMM12 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm12, DWORD [Rq((base as u8)) + disp]),
XMM::XMM13 => dynasm!(self ; $ins Rx((dst as u8)), xmm13, DWORD [Rq((base as u8)) + disp]), XMM::XMM13 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm13, DWORD [Rq((base as u8)) + disp]),
XMM::XMM14 => dynasm!(self ; $ins Rx((dst as u8)), xmm14, DWORD [Rq((base as u8)) + disp]), XMM::XMM14 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm14, DWORD [Rq((base as u8)) + disp]),
XMM::XMM15 => dynasm!(self ; $ins Rx((dst as u8)), xmm15, DWORD [Rq((base as u8)) + disp]), XMM::XMM15 => dynasm!(emitter ; $ins Rx((dst as u8)), xmm15, DWORD [Rq((base as u8)) + disp]),
}, },
} }
} }
} }
} }
macro_rules! sse_i2f_32_fn {
($ins:ident) => {
|emitter: &mut AssemblerX64, src1: XMM, src2: GPROrMemory, dst: XMM| {
match src2 {
GPROrMemory::GPR(x) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), Rd((x as u8))),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), Rd((x as u8))),
}
} else {
dynasm!(emitter; $ins Rx((src1 as u8)), Rd((x as u8)))
}
},
GPROrMemory::Memory(base, disp) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), DWORD [Rq((base as u8)) + disp]),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), DWORD [Rq((base as u8)) + disp])
}
}
}
}
}
}
macro_rules! avx_round_fn { macro_rules! avx_round_fn {
($ins:ident, $name:ident, $mode:expr) => { ($ins:ident, $mode:expr) => {
fn $name(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) { |emitter: &mut AssemblerX64, src1: XMM, src2: XMMOrMemory, dst: XMM| {
match src2 { match src2 {
XMMOrMemory::XMM(x) => dynasm!(self ; $ins Rx((dst as u8)), Rx((src1 as u8)), Rx((x as u8)), $mode), XMMOrMemory::XMM(x) => dynasm!(emitter ; $ins Rx((dst as u8)), Rx((src1 as u8)), Rx((x as u8)), $mode),
XMMOrMemory::Memory(base, disp) => dynasm!(self ; $ins Rx((dst as u8)), Rx((src1 as u8)), [Rq((base as u8)) + disp], $mode), XMMOrMemory::Memory(base, disp) => dynasm!(emitter ; $ins Rx((dst as u8)), Rx((src1 as u8)), [Rq((base as u8)) + disp], $mode),
} }
} }
} }
} }
impl EmitterX64 for Assembler { macro_rules! sse_round_fn {
($ins:ident, $mode:expr) => {
|emitter: &mut AssemblerX64, src1: XMM, src2: XMMOrMemory, dst: XMM| {
match src2 {
XMMOrMemory::XMM(x) =>{
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), Rx((x as u8)), $mode),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), Rx((x as u8)), $mode)
}
}
XMMOrMemory::Memory(base, disp) => {
if src1 != dst {
match src1 {
XMM::XMM0 => dynasm!(emitter ; movss Rx((dst as u8)), xmm0; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM1 => dynasm!(emitter ; movss Rx((dst as u8)), xmm1; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM2 => dynasm!(emitter ; movss Rx((dst as u8)), xmm2; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM3 => dynasm!(emitter ; movss Rx((dst as u8)), xmm3; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM4 => dynasm!(emitter ; movss Rx((dst as u8)), xmm4; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM5 => dynasm!(emitter ; movss Rx((dst as u8)), xmm5; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM6 => dynasm!(emitter ; movss Rx((dst as u8)), xmm6; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM7 => dynasm!(emitter ; movss Rx((dst as u8)), xmm7; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM8 => dynasm!(emitter ; movss Rx((dst as u8)), xmm8; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM9 => dynasm!(emitter ; movss Rx((dst as u8)), xmm9; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM10 => dynasm!(emitter ; movss Rx((dst as u8)), xmm10; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM11 => dynasm!(emitter ; movss Rx((dst as u8)), xmm11; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM12 => dynasm!(emitter ; movss Rx((dst as u8)), xmm12; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM13 => dynasm!(emitter ; movss Rx((dst as u8)), xmm13; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM14 => dynasm!(emitter ; movss Rx((dst as u8)), xmm14; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
XMM::XMM15 => dynasm!(emitter ; movss Rx((dst as u8)), xmm15; $ins Rx((dst as u8)), [Rq((base as u8)) + disp], $mode),
}
} else {
dynasm!(emitter ; $ins Rx((src1 as u8)), [Rq((base as u8)) + disp], $mode)
}
}
}
}
}
}
impl EmitterX64 for AssemblerX64 {
fn get_simd_arch(&self) -> Option<&CpuFeature> {
self.simd_arch.as_ref()
}
fn get_label(&mut self) -> DynamicLabel { fn get_label(&mut self) -> DynamicLabel {
self.new_dynamic_label() self.new_dynamic_label()
} }
@ -1254,71 +1542,328 @@ impl EmitterX64 for Assembler {
_ => panic!("singlepass can't emit VMOVAPD {:?} {:?}", src, dst), _ => panic!("singlepass can't emit VMOVAPD {:?} {:?}", src, dst),
}; };
} }
fn emit_vxorps(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_fn!(vxorps, emit_vxorps); match self.get_simd_arch() {
avx_fn!(vxorpd, emit_vxorpd); Some(CpuFeature::AVX) => avx_fn!(vxorps)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(xorps)(self, src1, src2, dst),
avx_fn!(vaddss, emit_vaddss); _ => {}
avx_fn!(vaddsd, emit_vaddsd); }
}
avx_fn!(vsubss, emit_vsubss); fn emit_vxorpd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_fn!(vsubsd, emit_vsubsd); match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vxorpd)(self, src1, src2, dst),
avx_fn!(vmulss, emit_vmulss); Some(CpuFeature::SSE42) => sse_fn!(xorpd)(self, src1, src2, dst),
avx_fn!(vmulsd, emit_vmulsd); _ => {}
}
avx_fn!(vdivss, emit_vdivss); }
avx_fn!(vdivsd, emit_vdivsd); fn emit_vaddss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
avx_fn!(vmaxss, emit_vmaxss); Some(CpuFeature::AVX) => avx_fn!(vaddss)(self, src1, src2, dst),
avx_fn!(vmaxsd, emit_vmaxsd); Some(CpuFeature::SSE42) => sse_fn!(addss)(self, src1, src2, dst),
_ => {}
avx_fn!(vminss, emit_vminss); }
avx_fn!(vminsd, emit_vminsd); }
fn emit_vaddsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_fn!(vcmpeqss, emit_vcmpeqss); match self.get_simd_arch() {
avx_fn!(vcmpeqsd, emit_vcmpeqsd); Some(CpuFeature::AVX) => avx_fn!(vaddsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(addsd)(self, src1, src2, dst),
avx_fn!(vcmpneqss, emit_vcmpneqss); _ => {}
avx_fn!(vcmpneqsd, emit_vcmpneqsd); }
}
avx_fn!(vcmpltss, emit_vcmpltss); fn emit_vsubss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_fn!(vcmpltsd, emit_vcmpltsd); match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vsubss)(self, src1, src2, dst),
avx_fn!(vcmpless, emit_vcmpless); Some(CpuFeature::SSE42) => sse_fn!(subss)(self, src1, src2, dst),
avx_fn!(vcmplesd, emit_vcmplesd); _ => {}
}
avx_fn!(vcmpgtss, emit_vcmpgtss); }
avx_fn!(vcmpgtsd, emit_vcmpgtsd); fn emit_vsubsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
avx_fn!(vcmpgess, emit_vcmpgess); Some(CpuFeature::AVX) => avx_fn!(vsubsd)(self, src1, src2, dst),
avx_fn!(vcmpgesd, emit_vcmpgesd); Some(CpuFeature::SSE42) => sse_fn!(subsd)(self, src1, src2, dst),
_ => {}
avx_fn!(vcmpunordss, emit_vcmpunordss); }
avx_fn!(vcmpunordsd, emit_vcmpunordsd); }
fn emit_vmulss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_fn!(vcmpordss, emit_vcmpordss); match self.get_simd_arch() {
avx_fn!(vcmpordsd, emit_vcmpordsd); Some(CpuFeature::AVX) => avx_fn!(vmulss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(mulss)(self, src1, src2, dst),
avx_fn!(vsqrtss, emit_vsqrtss); _ => {}
avx_fn!(vsqrtsd, emit_vsqrtsd); }
}
avx_fn!(vcvtss2sd, emit_vcvtss2sd); fn emit_vmulsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_fn!(vcvtsd2ss, emit_vcvtsd2ss); match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vmulsd)(self, src1, src2, dst),
avx_round_fn!(vroundss, emit_vroundss_nearest, 0); Some(CpuFeature::SSE42) => sse_fn!(mulsd)(self, src1, src2, dst),
avx_round_fn!(vroundss, emit_vroundss_floor, 1); _ => {}
avx_round_fn!(vroundss, emit_vroundss_ceil, 2); }
avx_round_fn!(vroundss, emit_vroundss_trunc, 3); }
avx_round_fn!(vroundsd, emit_vroundsd_nearest, 0); fn emit_vdivss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_round_fn!(vroundsd, emit_vroundsd_floor, 1); match self.get_simd_arch() {
avx_round_fn!(vroundsd, emit_vroundsd_ceil, 2); Some(CpuFeature::AVX) => avx_fn!(vdivss)(self, src1, src2, dst),
avx_round_fn!(vroundsd, emit_vroundsd_trunc, 3); Some(CpuFeature::SSE42) => sse_fn!(divss)(self, src1, src2, dst),
_ => {}
avx_i2f_32_fn!(vcvtsi2ss, emit_vcvtsi2ss_32); }
avx_i2f_32_fn!(vcvtsi2sd, emit_vcvtsi2sd_32); }
avx_i2f_64_fn!(vcvtsi2ss, emit_vcvtsi2ss_64); fn emit_vdivsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
avx_i2f_64_fn!(vcvtsi2sd, emit_vcvtsi2sd_64); match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vdivsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(divsd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vmaxss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vmaxss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(maxss)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vmaxsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vmaxsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(maxsd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vminss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vminss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(minss)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vminsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vminsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(minsd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpeqss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpeqss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 0)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpeqsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpeqsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 0)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpneqss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpneqss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 4)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpneqsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpneqsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 4)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpltss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpltss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 1)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpltsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpltsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 1)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpless(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpless)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 2)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmplesd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmplesd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 2)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpgtss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpgtss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 6)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpgtsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpgtsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 6)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpgess(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpgess)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 5)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpgesd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpgesd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 5)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpunordss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpunordss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 3)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpunordsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpunordsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 3)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpordss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpordss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpss, 7)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcmpordsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcmpordsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cmpsd, 7)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vsqrtss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vsqrtss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(sqrtss)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vsqrtsd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vsqrtsd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(sqrtsd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcvtss2sd(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcvtss2sd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cvtss2sd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcvtsd2ss(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_fn!(vcvtsd2ss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_fn!(cvtsd2ss)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundss_nearest(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 0)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundss, 0)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundsd_nearest(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 0)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundsd, 0)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundss_floor(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 1)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundss, 1)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundsd_floor(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 1)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundsd, 1)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundss_ceil(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 2)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundss, 2)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundsd_ceil(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 2)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundsd, 2)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundss_trunc(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundss, 3)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundss, 3)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vroundsd_trunc(&mut self, src1: XMM, src2: XMMOrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_round_fn!(vroundsd, 3)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_round_fn!(roundsd, 3)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcvtsi2ss_32(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_i2f_32_fn!(vcvtsi2ss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_i2f_32_fn!(cvtsi2ss)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcvtsi2sd_32(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_i2f_32_fn!(vcvtsi2sd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_i2f_32_fn!(cvtsi2sd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcvtsi2ss_64(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_i2f_64_fn!(vcvtsi2ss)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_i2f_64_fn!(cvtsi2ss)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vcvtsi2sd_64(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM) {
match self.get_simd_arch() {
Some(CpuFeature::AVX) => avx_i2f_64_fn!(vcvtsi2sd)(self, src1, src2, dst),
Some(CpuFeature::SSE42) => sse_i2f_64_fn!(cvtsi2sd)(self, src1, src2, dst),
_ => {}
}
}
fn emit_vblendvps(&mut self, src1: XMM, src2: XMMOrMemory, mask: XMM, dst: XMM) { fn emit_vblendvps(&mut self, src1: XMM, src2: XMMOrMemory, mask: XMM, dst: XMM) {
match src2 { match src2 {

View File

@ -6,10 +6,7 @@ use std::collections::BTreeMap;
use std::fmt::Debug; use std::fmt::Debug;
pub use wasmer_compiler::wasmparser::MemoryImmediate; pub use wasmer_compiler::wasmparser::MemoryImmediate;
use wasmer_compiler::wasmparser::Type as WpType; use wasmer_compiler::wasmparser::Type as WpType;
use wasmer_compiler::{ use wasmer_compiler::{Architecture, CallingConvention, CustomSection, FunctionBody, InstructionAddressMap, Relocation, RelocationTarget, Target, TrapInformation, CpuFeature};
Architecture, CallingConvention, CustomSection, FunctionBody, InstructionAddressMap,
Relocation, RelocationTarget, Target, TrapInformation,
};
use wasmer_types::{FunctionIndex, FunctionType}; use wasmer_types::{FunctionIndex, FunctionType};
use wasmer_vm::{TrapCode, VMOffsets}; use wasmer_vm::{TrapCode, VMOffsets};
@ -53,7 +50,7 @@ pub struct MachineStackOffset(pub usize);
pub trait Machine { pub trait Machine {
type GPR: Copy + Eq + Debug + Reg; type GPR: Copy + Eq + Debug + Reg;
type SIMD: Copy + Eq + Debug + Reg; type SIMD: Copy + Eq + Debug + Reg;
/// Get current assembler offset /// Get current inner offset
fn assembler_get_offset(&self) -> Offset; fn assembler_get_offset(&self) -> Offset;
/// Convert from a GPR register to index register /// Convert from a GPR register to index register
fn index_from_gpr(&self, x: Self::GPR) -> RegisterIndex; fn index_from_gpr(&self, x: Self::GPR) -> RegisterIndex;
@ -124,17 +121,17 @@ pub trait Machine {
/// Like Location::Memory(GPR::RBP, -(self.stack_offset.0 as i32)) for x86_64 /// Like Location::Memory(GPR::RBP, -(self.stack_offset.0 as i32)) for x86_64
fn local_on_stack(&mut self, stack_offset: i32) -> Location<Self::GPR, Self::SIMD>; fn local_on_stack(&mut self, stack_offset: i32) -> Location<Self::GPR, Self::SIMD>;
/// Adjust stack for locals /// Adjust stack for locals
/// Like assembler.emit_sub(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP)) /// Like inner.emit_sub(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP))
fn adjust_stack(&mut self, delta_stack_offset: u32); fn adjust_stack(&mut self, delta_stack_offset: u32);
/// restore stack /// restore stack
/// Like assembler.emit_add(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP)) /// Like inner.emit_add(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP))
fn restore_stack(&mut self, delta_stack_offset: u32); fn restore_stack(&mut self, delta_stack_offset: u32);
/// push callee saved register to the stack /// push callee saved register to the stack
fn push_callee_saved(&mut self); fn push_callee_saved(&mut self);
/// pop callee saved register from the stack /// pop callee saved register from the stack
fn pop_callee_saved(&mut self); fn pop_callee_saved(&mut self);
/// Pop stack of locals /// Pop stack of locals
/// Like assembler.emit_add(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP)) /// Like inner.emit_add(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP))
fn pop_stack_locals(&mut self, delta_stack_offset: u32); fn pop_stack_locals(&mut self, delta_stack_offset: u32);
/// Zero a location taht is 32bits /// Zero a location taht is 32bits
fn zero_location(&mut self, size: Size, location: Location<Self::GPR, Self::SIMD>); fn zero_location(&mut self, size: Size, location: Location<Self::GPR, Self::SIMD>);
@ -201,7 +198,7 @@ pub trait Machine {
/// Create a new `MachineState` with default values. /// Create a new `MachineState` with default values.
fn new_machine_state(&self) -> MachineState; fn new_machine_state(&self) -> MachineState;
/// Finalize the assembler /// Finalize the inner
fn assembler_finalize(self) -> Vec<u8>; fn assembler_finalize(self) -> Vec<u8>;
/// get_offset of Assembler /// get_offset of Assembler
@ -2167,7 +2164,15 @@ pub fn gen_std_trampoline(
calling_convention: CallingConvention, calling_convention: CallingConvention,
) -> FunctionBody { ) -> FunctionBody {
let machine = match target.triple().architecture { let machine = match target.triple().architecture {
Architecture::X86_64 => MachineX86_64::new(), Architecture::X86_64 => {
if target.cpu_features().contains(CpuFeature::AVX) {
MachineX86_64::new(Some(CpuFeature::AVX))
} else if target.cpu_features().contains(CpuFeature::SSE42) {
MachineX86_64::new(Some(CpuFeature::SSE42))
} else {
unimplemented!()
}
},
_ => unimplemented!(), _ => unimplemented!(),
}; };
machine.gen_std_trampoline(sig, calling_convention) machine.gen_std_trampoline(sig, calling_convention)
@ -2180,7 +2185,15 @@ pub fn gen_std_dynamic_import_trampoline(
calling_convention: CallingConvention, calling_convention: CallingConvention,
) -> FunctionBody { ) -> FunctionBody {
let machine = match target.triple().architecture { let machine = match target.triple().architecture {
Architecture::X86_64 => MachineX86_64::new(), Architecture::X86_64 => {
if target.cpu_features().contains(CpuFeature::AVX) {
MachineX86_64::new(Some(CpuFeature::AVX))
} else if target.cpu_features().contains(CpuFeature::SSE42) {
MachineX86_64::new(Some(CpuFeature::SSE42))
} else {
unimplemented!()
}
},
_ => unimplemented!(), _ => unimplemented!(),
}; };
machine.gen_std_dynamic_import_trampoline(vmoffsets, sig, calling_convention) machine.gen_std_dynamic_import_trampoline(vmoffsets, sig, calling_convention)
@ -2194,7 +2207,15 @@ pub fn gen_import_call_trampoline(
calling_convention: CallingConvention, calling_convention: CallingConvention,
) -> CustomSection { ) -> CustomSection {
let machine = match target.triple().architecture { let machine = match target.triple().architecture {
Architecture::X86_64 => MachineX86_64::new(), Architecture::X86_64 => {
if target.cpu_features().contains(CpuFeature::AVX) {
MachineX86_64::new(Some(CpuFeature::AVX))
} else if target.cpu_features().contains(CpuFeature::SSE42) {
MachineX86_64::new(Some(CpuFeature::SSE42))
} else {
unimplemented!()
}
}
_ => unimplemented!(), _ => unimplemented!(),
}; };
machine.gen_import_call_trampoline(vmoffsets, index, sig, calling_convention) machine.gen_import_call_trampoline(vmoffsets, index, sig, calling_convention)

View File

@ -5,21 +5,59 @@ use crate::machine::Machine;
use crate::machine::{MemoryImmediate, TrapTable}; use crate::machine::{MemoryImmediate, TrapTable};
use crate::x64_decl::new_machine_state; use crate::x64_decl::new_machine_state;
use crate::x64_decl::{ArgumentRegisterAllocator, X64Register, GPR, XMM}; use crate::x64_decl::{ArgumentRegisterAllocator, X64Register, GPR, XMM};
use dynasmrt::{x64::X64Relocation, VecAssembler}; use dynasmrt::{x64::X64Relocation, VecAssembler, DynasmError};
use std::collections::HashSet; use std::collections::HashSet;
use std::ops::{Deref, DerefMut};
use wasmer_compiler::wasmparser::Type as WpType; use wasmer_compiler::wasmparser::Type as WpType;
use wasmer_compiler::{ use wasmer_compiler::{
CallingConvention, CustomSection, CustomSectionProtection, FunctionBody, InstructionAddressMap, CallingConvention, CustomSection, CustomSectionProtection,
Relocation, RelocationKind, RelocationTarget, SectionBody, SourceLoc, TrapInformation, FunctionBody, InstructionAddressMap, Relocation, RelocationKind,
RelocationTarget, SectionBody, SourceLoc, TrapInformation, CpuFeature
}; };
use wasmer_types::{FunctionIndex, FunctionType, Type}; use wasmer_types::{FunctionIndex, FunctionType, Type};
use wasmer_vm::{TrapCode, VMOffsets}; use wasmer_vm::{TrapCode, VMOffsets};
type Assembler = VecAssembler<X64Relocation>; type Assembler = VecAssembler<X64Relocation>;
pub struct AssemblerX64 {
/// the actual inner
pub inner: Assembler,
/// the simd instructions set on the target.
/// Currently only supports SSE 4.2 and AVX
pub simd_arch: Option<CpuFeature>,
}
impl AssemblerX64 {
fn new(baseaddr: usize, simd_arch: Option<CpuFeature>) -> Self {
Self {
inner: Assembler::new(baseaddr),
simd_arch,
}
}
fn finalize(self) -> Result<Vec<u8>, DynasmError> {
self.inner.finalize()
}
}
impl Deref for AssemblerX64 {
type Target = Assembler;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for AssemblerX64 {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
type Location = AbstractLocation<GPR, XMM>; type Location = AbstractLocation<GPR, XMM>;
pub struct MachineX86_64 { pub struct MachineX86_64 {
assembler: Assembler, assembler: AssemblerX64,
used_gprs: HashSet<GPR>, used_gprs: HashSet<GPR>,
used_simd: HashSet<XMM>, used_simd: HashSet<XMM>,
trap_table: TrapTable, trap_table: TrapTable,
@ -32,9 +70,9 @@ pub struct MachineX86_64 {
} }
impl MachineX86_64 { impl MachineX86_64 {
pub fn new() -> Self { pub fn new(simd_arch: Option<CpuFeature>) -> Self {
MachineX86_64 { MachineX86_64 {
assembler: Assembler::new(0), assembler: AssemblerX64::new(0, simd_arch),
used_gprs: HashSet::new(), used_gprs: HashSet::new(),
used_simd: HashSet::new(), used_simd: HashSet::new(),
trap_table: TrapTable::default(), trap_table: TrapTable::default(),
@ -44,7 +82,7 @@ impl MachineX86_64 {
} }
pub fn emit_relaxed_binop( pub fn emit_relaxed_binop(
&mut self, &mut self,
op: fn(&mut Assembler, Size, Location, Location), op: fn(&mut AssemblerX64, Size, Location, Location),
sz: Size, sz: Size,
src: Location, src: Location,
dst: Location, dst: Location,
@ -57,11 +95,11 @@ impl MachineX86_64 {
} }
let mode = match (src, dst) { let mode = match (src, dst) {
(Location::GPR(_), Location::GPR(_)) (Location::GPR(_), Location::GPR(_))
if (op as *const u8 == Assembler::emit_imul as *const u8) => if (op as *const u8 == AssemblerX64::emit_imul as *const u8) =>
{ {
RelaxMode::Direct RelaxMode::Direct
} }
_ if (op as *const u8 == Assembler::emit_imul as *const u8) => RelaxMode::BothToGPR, _ if (op as *const u8 == AssemblerX64::emit_imul as *const u8) => RelaxMode::BothToGPR,
(Location::Memory(_, _), Location::Memory(_, _)) => RelaxMode::SrcToGPR, (Location::Memory(_, _), Location::Memory(_, _)) => RelaxMode::SrcToGPR,
(Location::Imm64(_), Location::Imm64(_)) | (Location::Imm64(_), Location::Imm32(_)) => { (Location::Imm64(_), Location::Imm64(_)) | (Location::Imm64(_), Location::Imm32(_)) => {
@ -70,7 +108,7 @@ impl MachineX86_64 {
(_, Location::Imm32(_)) | (_, Location::Imm64(_)) => RelaxMode::DstToGPR, (_, Location::Imm32(_)) | (_, Location::Imm64(_)) => RelaxMode::DstToGPR,
(Location::Imm64(_), Location::Memory(_, _)) => RelaxMode::SrcToGPR, (Location::Imm64(_), Location::Memory(_, _)) => RelaxMode::SrcToGPR,
(Location::Imm64(_), Location::GPR(_)) (Location::Imm64(_), Location::GPR(_))
if (op as *const u8 != Assembler::emit_mov as *const u8) => if (op as *const u8 != AssemblerX64::emit_mov as *const u8) =>
{ {
RelaxMode::SrcToGPR RelaxMode::SrcToGPR
} }
@ -118,7 +156,7 @@ impl MachineX86_64 {
} }
pub fn emit_relaxed_zx_sx( pub fn emit_relaxed_zx_sx(
&mut self, &mut self,
op: fn(&mut Assembler, Size, Location, Size, Location), op: fn(&mut AssemblerX64, Size, Location, Size, Location),
sz_src: Size, sz_src: Size,
src: Location, src: Location,
sz_dst: Size, sz_dst: Size,
@ -188,7 +226,7 @@ impl MachineX86_64 {
/// I32 binary operation with both operands popped from the virtual stack. /// I32 binary operation with both operands popped from the virtual stack.
fn emit_binop_i32( fn emit_binop_i32(
&mut self, &mut self,
f: fn(&mut Assembler, Size, Location, Location), f: fn(&mut AssemblerX64, Size, Location, Location),
loc_a: Location, loc_a: Location,
loc_b: Location, loc_b: Location,
ret: Location, ret: Location,
@ -206,7 +244,7 @@ impl MachineX86_64 {
/// I64 binary operation with both operands popped from the virtual stack. /// I64 binary operation with both operands popped from the virtual stack.
fn emit_binop_i64( fn emit_binop_i64(
&mut self, &mut self,
f: fn(&mut Assembler, Size, Location, Location), f: fn(&mut AssemblerX64, Size, Location, Location),
loc_a: Location, loc_a: Location,
loc_b: Location, loc_b: Location,
ret: Location, ret: Location,
@ -253,7 +291,7 @@ impl MachineX86_64 {
/// I64 shift with both operands popped from the virtual stack. /// I64 shift with both operands popped from the virtual stack.
fn emit_shift_i64( fn emit_shift_i64(
&mut self, &mut self,
f: fn(&mut Assembler, Size, Location, Location), f: fn(&mut AssemblerX64, Size, Location, Location),
loc_a: Location, loc_a: Location,
loc_b: Location, loc_b: Location,
ret: Location, ret: Location,
@ -270,7 +308,7 @@ impl MachineX86_64 {
/// Moves `loc` to a valid location for `div`/`idiv`. /// Moves `loc` to a valid location for `div`/`idiv`.
fn emit_relaxed_xdiv( fn emit_relaxed_xdiv(
&mut self, &mut self,
op: fn(&mut Assembler, Size, Location), op: fn(&mut AssemblerX64, Size, Location),
sz: Size, sz: Size,
loc: Location, loc: Location,
integer_division_by_zero: Label, integer_division_by_zero: Label,
@ -327,7 +365,7 @@ impl MachineX86_64 {
/// I32 shift with both operands popped from the virtual stack. /// I32 shift with both operands popped from the virtual stack.
fn emit_shift_i32( fn emit_shift_i32(
&mut self, &mut self,
f: fn(&mut Assembler, Size, Location, Location), f: fn(&mut AssemblerX64, Size, Location, Location),
loc_a: Location, loc_a: Location,
loc_b: Location, loc_b: Location,
ret: Location, ret: Location,
@ -360,7 +398,7 @@ impl MachineX86_64 {
let (base_loc, bound_loc) = if imported_memories { let (base_loc, bound_loc) = if imported_memories {
// Imported memories require one level of indirection. // Imported memories require one level of indirection.
self.emit_relaxed_binop( self.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S64, Size::S64,
Location::Memory(self.get_vmctx_reg(), offset), Location::Memory(self.get_vmctx_reg(), offset),
Location::GPR(tmp_addr), Location::GPR(tmp_addr),
@ -807,7 +845,7 @@ impl MachineX86_64 {
/// Moves `src1` and `src2` to valid locations and possibly adds a layer of indirection for `dst` for AVX instructions. /// Moves `src1` and `src2` to valid locations and possibly adds a layer of indirection for `dst` for AVX instructions.
fn emit_relaxed_avx( fn emit_relaxed_avx(
&mut self, &mut self,
op: fn(&mut Assembler, XMM, XMMOrMemory, XMM), op: fn(&mut AssemblerX64, XMM, XMMOrMemory, XMM),
src1: Location, src1: Location,
src2: Location, src2: Location,
dst: Location, dst: Location,
@ -1553,7 +1591,7 @@ impl MachineX86_64 {
} }
fn emit_relaxed_atomic_xchg(&mut self, sz: Size, src: Location, dst: Location) { fn emit_relaxed_atomic_xchg(&mut self, sz: Size, src: Location, dst: Location) {
self.emit_relaxed_binop(Assembler::emit_xchg, sz, src, dst); self.emit_relaxed_binop(AssemblerX64::emit_xchg, sz, src, dst);
} }
} }
@ -2019,7 +2057,7 @@ impl Machine for MachineX86_64 {
new_machine_state() new_machine_state()
} }
// assembler finalize // inner finalize
fn assembler_finalize(self) -> Vec<u8> { fn assembler_finalize(self) -> Vec<u8> {
self.assembler.finalize().unwrap() self.assembler.finalize().unwrap()
} }
@ -2273,10 +2311,10 @@ impl Machine for MachineX86_64 {
// relaxed binop based... // relaxed binop based...
fn emit_relaxed_mov(&mut self, sz: Size, src: Location, dst: Location) { fn emit_relaxed_mov(&mut self, sz: Size, src: Location, dst: Location) {
self.emit_relaxed_binop(Assembler::emit_mov, sz, src, dst); self.emit_relaxed_binop(AssemblerX64::emit_mov, sz, src, dst);
} }
fn emit_relaxed_cmp(&mut self, sz: Size, src: Location, dst: Location) { fn emit_relaxed_cmp(&mut self, sz: Size, src: Location, dst: Location) {
self.emit_relaxed_binop(Assembler::emit_cmp, sz, src, dst); self.emit_relaxed_binop(AssemblerX64::emit_cmp, sz, src, dst);
} }
fn emit_relaxed_zero_extension( fn emit_relaxed_zero_extension(
&mut self, &mut self,
@ -2286,9 +2324,9 @@ impl Machine for MachineX86_64 {
dst: Location, dst: Location,
) { ) {
if (sz_src == Size::S32 || sz_src == Size::S64) && sz_dst == Size::S64 { if (sz_src == Size::S32 || sz_src == Size::S64) && sz_dst == Size::S64 {
self.emit_relaxed_binop(Assembler::emit_mov, sz_src, src, dst); self.emit_relaxed_binop(AssemblerX64::emit_mov, sz_src, src, dst);
} else { } else {
self.emit_relaxed_zx_sx(Assembler::emit_movzx, sz_src, src, sz_dst, dst); self.emit_relaxed_zx_sx(AssemblerX64::emit_movzx, sz_src, src, sz_dst, dst);
} }
} }
fn emit_relaxed_sign_extension( fn emit_relaxed_sign_extension(
@ -2298,17 +2336,17 @@ impl Machine for MachineX86_64 {
sz_dst: Size, sz_dst: Size,
dst: Location, dst: Location,
) { ) {
self.emit_relaxed_zx_sx(Assembler::emit_movsx, sz_src, src, sz_dst, dst); self.emit_relaxed_zx_sx(AssemblerX64::emit_movsx, sz_src, src, sz_dst, dst);
} }
fn emit_binop_add32(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_add32(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i32(Assembler::emit_add, loc_a, loc_b, ret); self.emit_binop_i32(AssemblerX64::emit_add, loc_a, loc_b, ret);
} }
fn emit_binop_sub32(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_sub32(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i32(Assembler::emit_sub, loc_a, loc_b, ret); self.emit_binop_i32(AssemblerX64::emit_sub, loc_a, loc_b, ret);
} }
fn emit_binop_mul32(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_mul32(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i32(Assembler::emit_imul, loc_a, loc_b, ret); self.emit_binop_i32(AssemblerX64::emit_imul, loc_a, loc_b, ret);
} }
fn emit_binop_udiv32( fn emit_binop_udiv32(
&mut self, &mut self,
@ -2323,7 +2361,7 @@ impl Machine for MachineX86_64 {
self.assembler self.assembler
.emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX)); .emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_div, AssemblerX64::emit_div,
Size::S32, Size::S32,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -2344,7 +2382,7 @@ impl Machine for MachineX86_64 {
.emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX)); .emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX));
self.assembler.emit_cdq(); self.assembler.emit_cdq();
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_idiv, AssemblerX64::emit_idiv,
Size::S32, Size::S32,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -2366,7 +2404,7 @@ impl Machine for MachineX86_64 {
self.assembler self.assembler
.emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX)); .emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_div, AssemblerX64::emit_div,
Size::S32, Size::S32,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -2398,7 +2436,7 @@ impl Machine for MachineX86_64 {
.emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX)); .emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX));
self.assembler.emit_cdq(); self.assembler.emit_cdq();
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_idiv, AssemblerX64::emit_idiv,
Size::S32, Size::S32,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -2410,13 +2448,13 @@ impl Machine for MachineX86_64 {
offset offset
} }
fn emit_binop_and32(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_and32(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i32(Assembler::emit_and, loc_a, loc_b, ret); self.emit_binop_i32(AssemblerX64::emit_and, loc_a, loc_b, ret);
} }
fn emit_binop_or32(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_or32(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i32(Assembler::emit_or, loc_a, loc_b, ret); self.emit_binop_i32(AssemblerX64::emit_or, loc_a, loc_b, ret);
} }
fn emit_binop_xor32(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_xor32(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i32(Assembler::emit_xor, loc_a, loc_b, ret); self.emit_binop_i32(AssemblerX64::emit_xor, loc_a, loc_b, ret);
} }
fn i32_cmp_ge_s(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i32_cmp_ge_s(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_cmpop_i32_dynamic_b(Condition::GreaterEqual, loc_a, loc_b, ret); self.emit_cmpop_i32_dynamic_b(Condition::GreaterEqual, loc_a, loc_b, ret);
@ -2582,19 +2620,19 @@ impl Machine for MachineX86_64 {
} }
} }
fn i32_shl(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i32_shl(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i32(Assembler::emit_shl, loc_a, loc_b, ret); self.emit_shift_i32(AssemblerX64::emit_shl, loc_a, loc_b, ret);
} }
fn i32_shr(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i32_shr(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i32(Assembler::emit_shr, loc_a, loc_b, ret); self.emit_shift_i32(AssemblerX64::emit_shr, loc_a, loc_b, ret);
} }
fn i32_sar(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i32_sar(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i32(Assembler::emit_sar, loc_a, loc_b, ret); self.emit_shift_i32(AssemblerX64::emit_sar, loc_a, loc_b, ret);
} }
fn i32_rol(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i32_rol(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i32(Assembler::emit_rol, loc_a, loc_b, ret); self.emit_shift_i32(AssemblerX64::emit_rol, loc_a, loc_b, ret);
} }
fn i32_ror(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i32_ror(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i32(Assembler::emit_ror, loc_a, loc_b, ret); self.emit_shift_i32(AssemblerX64::emit_ror, loc_a, loc_b, ret);
} }
fn i32_load( fn i32_load(
&mut self, &mut self,
@ -2617,7 +2655,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S32, Size::S32,
Location::Memory(addr, 0), Location::Memory(addr, 0),
ret, ret,
@ -2646,7 +2684,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movzx, AssemblerX64::emit_movzx,
Size::S8, Size::S8,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S32, Size::S32,
@ -2676,7 +2714,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movsx, AssemblerX64::emit_movsx,
Size::S8, Size::S8,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S32, Size::S32,
@ -2706,7 +2744,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movzx, AssemblerX64::emit_movzx,
Size::S16, Size::S16,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S32, Size::S32,
@ -2736,7 +2774,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movsx, AssemblerX64::emit_movsx,
Size::S16, Size::S16,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S32, Size::S32,
@ -2848,7 +2886,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S32, Size::S32,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -2877,7 +2915,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S8, Size::S8,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -2906,7 +2944,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S16, Size::S16,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -3739,13 +3777,13 @@ impl Machine for MachineX86_64 {
} }
fn emit_binop_add64(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_add64(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i64(Assembler::emit_add, loc_a, loc_b, ret); self.emit_binop_i64(AssemblerX64::emit_add, loc_a, loc_b, ret);
} }
fn emit_binop_sub64(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_sub64(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i64(Assembler::emit_sub, loc_a, loc_b, ret); self.emit_binop_i64(AssemblerX64::emit_sub, loc_a, loc_b, ret);
} }
fn emit_binop_mul64(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_mul64(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i64(Assembler::emit_imul, loc_a, loc_b, ret); self.emit_binop_i64(AssemblerX64::emit_imul, loc_a, loc_b, ret);
} }
fn emit_binop_udiv64( fn emit_binop_udiv64(
&mut self, &mut self,
@ -3760,7 +3798,7 @@ impl Machine for MachineX86_64 {
self.assembler self.assembler
.emit_xor(Size::S64, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX)); .emit_xor(Size::S64, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_div, AssemblerX64::emit_div,
Size::S64, Size::S64,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -3781,7 +3819,7 @@ impl Machine for MachineX86_64 {
.emit_mov(Size::S64, loc_a, Location::GPR(GPR::RAX)); .emit_mov(Size::S64, loc_a, Location::GPR(GPR::RAX));
self.assembler.emit_cqo(); self.assembler.emit_cqo();
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_idiv, AssemblerX64::emit_idiv,
Size::S64, Size::S64,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -3803,7 +3841,7 @@ impl Machine for MachineX86_64 {
self.assembler self.assembler
.emit_xor(Size::S64, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX)); .emit_xor(Size::S64, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_div, AssemblerX64::emit_div,
Size::S64, Size::S64,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -3835,7 +3873,7 @@ impl Machine for MachineX86_64 {
.emit_mov(Size::S64, loc_a, Location::GPR(GPR::RAX)); .emit_mov(Size::S64, loc_a, Location::GPR(GPR::RAX));
self.assembler.emit_cqo(); self.assembler.emit_cqo();
let offset = self.emit_relaxed_xdiv( let offset = self.emit_relaxed_xdiv(
Assembler::emit_idiv, AssemblerX64::emit_idiv,
Size::S64, Size::S64,
loc_b, loc_b,
integer_division_by_zero, integer_division_by_zero,
@ -3847,13 +3885,13 @@ impl Machine for MachineX86_64 {
offset offset
} }
fn emit_binop_and64(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_and64(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i64(Assembler::emit_and, loc_a, loc_b, ret); self.emit_binop_i64(AssemblerX64::emit_and, loc_a, loc_b, ret);
} }
fn emit_binop_or64(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_or64(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i64(Assembler::emit_or, loc_a, loc_b, ret); self.emit_binop_i64(AssemblerX64::emit_or, loc_a, loc_b, ret);
} }
fn emit_binop_xor64(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn emit_binop_xor64(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_binop_i64(Assembler::emit_xor, loc_a, loc_b, ret); self.emit_binop_i64(AssemblerX64::emit_xor, loc_a, loc_b, ret);
} }
fn i64_cmp_ge_s(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i64_cmp_ge_s(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_cmpop_i64_dynamic_b(Condition::GreaterEqual, loc_a, loc_b, ret); self.emit_cmpop_i64_dynamic_b(Condition::GreaterEqual, loc_a, loc_b, ret);
@ -4019,19 +4057,19 @@ impl Machine for MachineX86_64 {
} }
} }
fn i64_shl(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i64_shl(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i64(Assembler::emit_shl, loc_a, loc_b, ret); self.emit_shift_i64(AssemblerX64::emit_shl, loc_a, loc_b, ret);
} }
fn i64_shr(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i64_shr(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i64(Assembler::emit_shr, loc_a, loc_b, ret); self.emit_shift_i64(AssemblerX64::emit_shr, loc_a, loc_b, ret);
} }
fn i64_sar(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i64_sar(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i64(Assembler::emit_sar, loc_a, loc_b, ret); self.emit_shift_i64(AssemblerX64::emit_sar, loc_a, loc_b, ret);
} }
fn i64_rol(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i64_rol(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i64(Assembler::emit_rol, loc_a, loc_b, ret); self.emit_shift_i64(AssemblerX64::emit_rol, loc_a, loc_b, ret);
} }
fn i64_ror(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn i64_ror(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_shift_i64(Assembler::emit_ror, loc_a, loc_b, ret); self.emit_shift_i64(AssemblerX64::emit_ror, loc_a, loc_b, ret);
} }
fn i64_load( fn i64_load(
&mut self, &mut self,
@ -4054,7 +4092,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S64, Size::S64,
Location::Memory(addr, 0), Location::Memory(addr, 0),
ret, ret,
@ -4083,7 +4121,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movzx, AssemblerX64::emit_movzx,
Size::S8, Size::S8,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S64, Size::S64,
@ -4113,7 +4151,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movsx, AssemblerX64::emit_movsx,
Size::S8, Size::S8,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S64, Size::S64,
@ -4143,7 +4181,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movzx, AssemblerX64::emit_movzx,
Size::S16, Size::S16,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S64, Size::S64,
@ -4173,7 +4211,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movsx, AssemblerX64::emit_movsx,
Size::S16, Size::S16,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S64, Size::S64,
@ -4216,7 +4254,7 @@ impl Machine for MachineX86_64 {
} }
} }
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S32, Size::S32,
Location::Memory(addr, 0), Location::Memory(addr, 0),
ret, ret,
@ -4245,7 +4283,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_zx_sx( this.emit_relaxed_zx_sx(
Assembler::emit_movsx, AssemblerX64::emit_movsx,
Size::S32, Size::S32,
Location::Memory(addr, 0), Location::Memory(addr, 0),
Size::S64, Size::S64,
@ -4399,7 +4437,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S64, Size::S64,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -4428,7 +4466,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S8, Size::S8,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -4457,7 +4495,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S16, Size::S16,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -4486,7 +4524,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S32, Size::S32,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -5576,7 +5614,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S32, Size::S32,
Location::Memory(addr, 0), Location::Memory(addr, 0),
ret, ret,
@ -5608,7 +5646,7 @@ impl Machine for MachineX86_64 {
|this, addr| { |this, addr| {
if !canonicalize { if !canonicalize {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S32, Size::S32,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -5640,7 +5678,7 @@ impl Machine for MachineX86_64 {
heap_access_oob, heap_access_oob,
|this, addr| { |this, addr| {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S64, Size::S64,
Location::Memory(addr, 0), Location::Memory(addr, 0),
ret, ret,
@ -5672,7 +5710,7 @@ impl Machine for MachineX86_64 {
|this, addr| { |this, addr| {
if !canonicalize { if !canonicalize {
this.emit_relaxed_binop( this.emit_relaxed_binop(
Assembler::emit_mov, AssemblerX64::emit_mov,
Size::S64, Size::S64,
target_value, target_value,
Location::Memory(addr, 0), Location::Memory(addr, 0),
@ -5894,10 +5932,10 @@ impl Machine for MachineX86_64 {
} }
} }
fn convert_f64_f32(&mut self, loc: Location, ret: Location) { fn convert_f64_f32(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcvtss2sd, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcvtss2sd, loc, loc, ret);
} }
fn convert_f32_f64(&mut self, loc: Location, ret: Location) { fn convert_f32_f64(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcvtsd2ss, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcvtsd2ss, loc, loc, ret);
} }
fn f64_neg(&mut self, loc: Location, ret: Location) { fn f64_neg(&mut self, loc: Location, ret: Location) {
if self.assembler.arch_has_fneg() { if self.assembler.arch_has_fneg() {
@ -5956,47 +5994,47 @@ impl Machine for MachineX86_64 {
self.release_gpr(c); self.release_gpr(c);
} }
fn f64_sqrt(&mut self, loc: Location, ret: Location) { fn f64_sqrt(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vsqrtsd, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vsqrtsd, loc, loc, ret);
} }
fn f64_trunc(&mut self, loc: Location, ret: Location) { fn f64_trunc(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundsd_trunc, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundsd_trunc, loc, loc, ret);
} }
fn f64_ceil(&mut self, loc: Location, ret: Location) { fn f64_ceil(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundsd_ceil, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundsd_ceil, loc, loc, ret);
} }
fn f64_floor(&mut self, loc: Location, ret: Location) { fn f64_floor(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundsd_floor, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundsd_floor, loc, loc, ret);
} }
fn f64_nearest(&mut self, loc: Location, ret: Location) { fn f64_nearest(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundsd_nearest, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundsd_nearest, loc, loc, ret);
} }
fn f64_cmp_ge(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_cmp_ge(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpgesd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpgesd, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f64_cmp_gt(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_cmp_gt(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpgtsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpgtsd, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f64_cmp_le(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_cmp_le(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmplesd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmplesd, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f64_cmp_lt(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_cmp_lt(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpltsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpltsd, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f64_cmp_ne(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_cmp_ne(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpneqsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpneqsd, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f64_cmp_eq(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_cmp_eq(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpeqsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpeqsd, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f64_min(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_min(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
if !self.arch_supports_canonicalize_nan() { if !self.arch_supports_canonicalize_nan() {
self.emit_relaxed_avx(Assembler::emit_vminsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vminsd, loc_a, loc_b, ret);
} else { } else {
let tmp1 = self.acquire_temp_simd().unwrap(); let tmp1 = self.acquire_temp_simd().unwrap();
let tmp2 = self.acquire_temp_simd().unwrap(); let tmp2 = self.acquire_temp_simd().unwrap();
@ -6105,7 +6143,7 @@ impl Machine for MachineX86_64 {
} }
fn f64_max(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_max(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
if !self.arch_supports_canonicalize_nan() { if !self.arch_supports_canonicalize_nan() {
self.emit_relaxed_avx(Assembler::emit_vmaxsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vmaxsd, loc_a, loc_b, ret);
} else { } else {
let tmp1 = self.acquire_temp_simd().unwrap(); let tmp1 = self.acquire_temp_simd().unwrap();
let tmp2 = self.acquire_temp_simd().unwrap(); let tmp2 = self.acquire_temp_simd().unwrap();
@ -6208,16 +6246,16 @@ impl Machine for MachineX86_64 {
} }
} }
fn f64_add(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_add(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vaddsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vaddsd, loc_a, loc_b, ret);
} }
fn f64_sub(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_sub(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vsubsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vsubsd, loc_a, loc_b, ret);
} }
fn f64_mul(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_mul(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vmulsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vmulsd, loc_a, loc_b, ret);
} }
fn f64_div(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f64_div(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vdivsd, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vdivsd, loc_a, loc_b, ret);
} }
fn f32_neg(&mut self, loc: Location, ret: Location) { fn f32_neg(&mut self, loc: Location, ret: Location) {
if self.assembler.arch_has_fneg() { if self.assembler.arch_has_fneg() {
@ -6260,47 +6298,47 @@ impl Machine for MachineX86_64 {
.emit_or(Size::S32, Location::GPR(tmp2), Location::GPR(tmp1)); .emit_or(Size::S32, Location::GPR(tmp2), Location::GPR(tmp1));
} }
fn f32_sqrt(&mut self, loc: Location, ret: Location) { fn f32_sqrt(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vsqrtss, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vsqrtss, loc, loc, ret);
} }
fn f32_trunc(&mut self, loc: Location, ret: Location) { fn f32_trunc(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundss_trunc, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundss_trunc, loc, loc, ret);
} }
fn f32_ceil(&mut self, loc: Location, ret: Location) { fn f32_ceil(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundss_ceil, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundss_ceil, loc, loc, ret);
} }
fn f32_floor(&mut self, loc: Location, ret: Location) { fn f32_floor(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundss_floor, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundss_floor, loc, loc, ret);
} }
fn f32_nearest(&mut self, loc: Location, ret: Location) { fn f32_nearest(&mut self, loc: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vroundss_nearest, loc, loc, ret); self.emit_relaxed_avx(AssemblerX64::emit_vroundss_nearest, loc, loc, ret);
} }
fn f32_cmp_ge(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_cmp_ge(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpgess, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpgess, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f32_cmp_gt(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_cmp_gt(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpgtss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpgtss, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f32_cmp_le(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_cmp_le(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpless, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpless, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f32_cmp_lt(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_cmp_lt(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpltss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpltss, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f32_cmp_ne(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_cmp_ne(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpneqss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpneqss, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f32_cmp_eq(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_cmp_eq(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vcmpeqss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vcmpeqss, loc_a, loc_b, ret);
self.assembler.emit_and(Size::S32, Location::Imm32(1), ret); self.assembler.emit_and(Size::S32, Location::Imm32(1), ret);
} }
fn f32_min(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_min(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
if !self.arch_supports_canonicalize_nan() { if !self.arch_supports_canonicalize_nan() {
self.emit_relaxed_avx(Assembler::emit_vminss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vminss, loc_a, loc_b, ret);
} else { } else {
let tmp1 = self.acquire_temp_simd().unwrap(); let tmp1 = self.acquire_temp_simd().unwrap();
let tmp2 = self.acquire_temp_simd().unwrap(); let tmp2 = self.acquire_temp_simd().unwrap();
@ -6409,7 +6447,7 @@ impl Machine for MachineX86_64 {
} }
fn f32_max(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_max(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
if !self.arch_supports_canonicalize_nan() { if !self.arch_supports_canonicalize_nan() {
self.emit_relaxed_avx(Assembler::emit_vmaxss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vmaxss, loc_a, loc_b, ret);
} else { } else {
let tmp1 = self.acquire_temp_simd().unwrap(); let tmp1 = self.acquire_temp_simd().unwrap();
let tmp2 = self.acquire_temp_simd().unwrap(); let tmp2 = self.acquire_temp_simd().unwrap();
@ -6512,16 +6550,16 @@ impl Machine for MachineX86_64 {
} }
} }
fn f32_add(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_add(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vaddss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vaddss, loc_a, loc_b, ret);
} }
fn f32_sub(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_sub(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vsubss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vsubss, loc_a, loc_b, ret);
} }
fn f32_mul(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_mul(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vmulss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vmulss, loc_a, loc_b, ret);
} }
fn f32_div(&mut self, loc_a: Location, loc_b: Location, ret: Location) { fn f32_div(&mut self, loc_a: Location, loc_b: Location, ret: Location) {
self.emit_relaxed_avx(Assembler::emit_vdivss, loc_a, loc_b, ret); self.emit_relaxed_avx(AssemblerX64::emit_vdivss, loc_a, loc_b, ret);
} }
fn gen_std_trampoline( fn gen_std_trampoline(
@ -6529,7 +6567,8 @@ impl Machine for MachineX86_64 {
sig: &FunctionType, sig: &FunctionType,
calling_convention: CallingConvention, calling_convention: CallingConvention,
) -> FunctionBody { ) -> FunctionBody {
let mut a = Assembler::new(0); // the cpu feature here is irrelevant
let mut a = AssemblerX64::new(0, None);
// Calculate stack offset. // Calculate stack offset.
let mut stack_offset: u32 = 0; let mut stack_offset: u32 = 0;
@ -6639,7 +6678,8 @@ impl Machine for MachineX86_64 {
sig: &FunctionType, sig: &FunctionType,
calling_convention: CallingConvention, calling_convention: CallingConvention,
) -> FunctionBody { ) -> FunctionBody {
let mut a = Assembler::new(0); // the cpu feature here is irrelevant
let mut a = AssemblerX64::new(0, None);
// Allocate argument array. // Allocate argument array.
let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len()) + 8; // 16 bytes each + 8 bytes sysv call padding let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len()) + 8; // 16 bytes each + 8 bytes sysv call padding
@ -6761,7 +6801,8 @@ impl Machine for MachineX86_64 {
sig: &FunctionType, sig: &FunctionType,
calling_convention: CallingConvention, calling_convention: CallingConvention,
) -> CustomSection { ) -> CustomSection {
let mut a = Assembler::new(0); // the cpu feature here is irrelevant
let mut a = AssemblerX64::new(0, None);
// TODO: ARM entry trampoline is not emitted. // TODO: ARM entry trampoline is not emitted.