// Checks if the correct registers are being used to pass arguments // when the sysv64 ABI is specified. // ignore-android // ignore-arm // ignore-aarch64 #![feature(asm)] #[cfg(target_arch = "x86_64")] pub extern "sysv64" fn all_the_registers(rdi: i64, rsi: i64, rdx: i64, rcx: i64, r8 : i64, r9 : i64, xmm0: f32, xmm1: f32, xmm2: f32, xmm3: f32, xmm4: f32, xmm5: f32, xmm6: f32, xmm7: f32) -> i64 { assert_eq!(rdi, 1); assert_eq!(rsi, 2); assert_eq!(rdx, 3); assert_eq!(rcx, 4); assert_eq!(r8, 5); assert_eq!(r9, 6); assert_eq!(xmm0, 1.0f32); assert_eq!(xmm1, 2.0f32); assert_eq!(xmm2, 4.0f32); assert_eq!(xmm3, 8.0f32); assert_eq!(xmm4, 16.0f32); assert_eq!(xmm5, 32.0f32); assert_eq!(xmm6, 64.0f32); assert_eq!(xmm7, 128.0f32); 42 } // this struct contains 8 i64's, while only 6 can be passed in registers. #[cfg(target_arch = "x86_64")] #[derive(PartialEq, Eq, Debug)] pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64); #[cfg(target_arch = "x86_64")] #[inline(never)] pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct { foo.0 *= 1; foo.1 *= 2; foo.2 *= 3; foo.3 *= 4; foo.4 *= 5; foo.5 *= 6; foo.6 *= 7; foo.7 *= 8; foo } #[cfg(target_arch = "x86_64")] pub fn main() { let result: i64; unsafe { asm!("mov rdi, 1; mov rsi, 2; mov rdx, 3; mov rcx, 4; mov r8, 5; mov r9, 6; mov eax, 0x3F800000; movd xmm0, eax; mov eax, 0x40000000; movd xmm1, eax; mov eax, 0x40800000; movd xmm2, eax; mov eax, 0x41000000; movd xmm3, eax; mov eax, 0x41800000; movd xmm4, eax; mov eax, 0x42000000; movd xmm5, eax; mov eax, 0x42800000; movd xmm6, eax; mov eax, 0x43000000; movd xmm7, eax; call r10 " : "={rax}"(result) : "{r10}"(all_the_registers as usize) : "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11", "cc", "memory" : "intel", "alignstack" ) } assert_eq!(result, 42); assert_eq!( large_struct_by_val(LargeStruct(1, 2, 3, 4, 5, 6, 7, 8)), LargeStruct(1, 4, 9, 16, 25, 36, 49, 64) ); } #[cfg(not(target_arch = "x86_64"))] pub fn main() {}