#[cfg(target_arch = "x86_64")]
use dynasm::dynasm;
#[cfg(target_arch = "x86_64")]
use dynasmrt::x64::Assembler;
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
pub fn emit_abi_prologue(asm: &mut Assembler) {
dynasm!(asm
; .arch x64
; push rdi
; push rsi
; mov rdi, rcx ; mov rsi, rdx );
}
#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
pub fn emit_abi_prologue(asm: &mut Assembler) {
let _ = asm;
}
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
pub fn emit_abi_epilogue(asm: &mut Assembler) {
dynasm!(asm
; .arch x64
; pop rsi
; pop rdi
);
}
#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
pub fn emit_abi_epilogue(asm: &mut Assembler) {
let _ = asm;
}
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
pub fn emit_abi_prologue_with_r13(asm: &mut Assembler) {
dynasm!(asm
; .arch x64
; push rdi
; push rsi
; push r13
; mov rdi, rcx
; mov rsi, rdx
);
}
#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
pub fn emit_abi_prologue_with_r13(asm: &mut Assembler) {
dynasm!(asm
; .arch x64
; push r13
);
}
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
pub fn emit_abi_epilogue_with_r13(asm: &mut Assembler) {
dynasm!(asm
; .arch x64
; pop r13
; pop rsi
; pop rdi
);
}
#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
pub fn emit_abi_epilogue_with_r13(asm: &mut Assembler) {
dynasm!(asm
; .arch x64
; pop r13
);
}
#[cfg(target_arch = "aarch64")]
use dynasm::dynasm;
#[cfg(target_arch = "aarch64")]
use dynasmrt::aarch64::Assembler as Aarch64Assembler;
#[cfg(target_arch = "aarch64")]
pub fn emit_abi_prologue_aarch64(asm: &mut Aarch64Assembler) {
dynasm!(asm
; .arch aarch64
; stp x19, x20, [sp, #-16]!
; mov x19, x0 ; mov x20, x1 );
}
#[cfg(target_arch = "aarch64")]
pub fn emit_abi_epilogue_aarch64(asm: &mut Aarch64Assembler) {
dynasm!(asm
; .arch aarch64
; ldp x19, x20, [sp], #16
);
}
#[cfg(target_arch = "aarch64")]
pub fn emit_abi_prologue_full_aarch64(asm: &mut Aarch64Assembler) {
dynasm!(asm
; .arch aarch64
; stp x29, x30, [sp, #-16]!
; mov x29, sp
; stp x19, x20, [sp, #-16]!
; stp x21, x22, [sp, #-16]!
; stp x23, x24, [sp, #-16]!
; mov x19, x0 ; mov x20, x1 );
}
#[cfg(target_arch = "aarch64")]
pub fn emit_abi_epilogue_full_aarch64(asm: &mut Aarch64Assembler) {
dynasm!(asm
; .arch aarch64
; ldp x23, x24, [sp], #16
; ldp x21, x22, [sp], #16
; ldp x19, x20, [sp], #16
; ldp x29, x30, [sp], #16
);
}
#[inline]
pub const fn is_windows() -> bool {
cfg!(target_os = "windows")
}
#[inline]
pub const fn is_aarch64() -> bool {
cfg!(target_arch = "aarch64")
}
#[inline]
pub const fn calling_convention_name() -> &'static str {
if cfg!(target_arch = "aarch64") {
"AAPCS64"
} else if cfg!(target_os = "windows") {
"Microsoft x64"
} else {
"System V AMD64"
}
}
#[inline]
pub const fn arch_name() -> &'static str {
if cfg!(target_arch = "aarch64") {
"aarch64"
} else if cfg!(target_arch = "x86_64") {
"x86_64"
} else {
"unknown"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calling_convention_name() {
let name = calling_convention_name();
#[cfg(target_arch = "aarch64")]
assert_eq!(name, "AAPCS64");
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
assert_eq!(name, "Microsoft x64");
#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
assert_eq!(name, "System V AMD64");
}
#[test]
fn test_arch_name() {
let arch = arch_name();
#[cfg(target_arch = "aarch64")]
assert_eq!(arch, "aarch64");
#[cfg(target_arch = "x86_64")]
assert_eq!(arch, "x86_64");
}
}