| // Compiler: |
| // |
| // Run-time: |
| // status: 0 |
| |
| #![feature(asm_const)] |
| |
| #[cfg(target_arch="x86_64")] |
| use std::arch::{asm, global_asm}; |
| |
| #[cfg(target_arch="x86_64")] |
| global_asm!( |
| " |
| .global add_asm |
| add_asm: |
| mov rax, rdi |
| add rax, rsi |
| ret" |
| ); |
| |
| extern "C" { |
| fn add_asm(a: i64, b: i64) -> i64; |
| } |
| |
| #[cfg(target_arch="x86_64")] |
| pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { |
| asm!( |
| "rep movsb", |
| inout("rdi") dst => _, |
| inout("rsi") src => _, |
| inout("rcx") len => _, |
| options(preserves_flags, nostack) |
| ); |
| } |
| |
| #[cfg(target_arch="x86_64")] |
| fn asm() { |
| unsafe { |
| asm!("nop"); |
| } |
| |
| let x: u64; |
| unsafe { |
| asm!("mov $5, {}", |
| out(reg) x, |
| options(att_syntax) |
| ); |
| } |
| assert_eq!(x, 5); |
| |
| let x: u64; |
| let input: u64 = 42; |
| unsafe { |
| asm!("mov {input}, {output}", |
| "add $1, {output}", |
| input = in(reg) input, |
| output = out(reg) x, |
| options(att_syntax) |
| ); |
| } |
| assert_eq!(x, 43); |
| |
| let x: u64; |
| unsafe { |
| asm!("mov {}, 6", |
| out(reg) x, |
| ); |
| } |
| assert_eq!(x, 6); |
| |
| let x: u64; |
| let input: u64 = 42; |
| unsafe { |
| asm!("mov {output}, {input}", |
| "add {output}, 1", |
| input = in(reg) input, |
| output = out(reg) x, |
| ); |
| } |
| assert_eq!(x, 43); |
| |
| // check inout(reg_class) x |
| let mut x: u64 = 42; |
| unsafe { |
| asm!("add {0}, {0}", |
| inout(reg) x |
| ); |
| } |
| assert_eq!(x, 84); |
| |
| // check inout("reg") x |
| let mut x: u64 = 42; |
| unsafe { |
| asm!("add r11, r11", |
| inout("r11") x |
| ); |
| } |
| assert_eq!(x, 84); |
| |
| // check a mix of |
| // in("reg") |
| // inout(class) x => y |
| // inout (class) x |
| let x: u64 = 702; |
| let y: u64 = 100; |
| let res: u64; |
| let mut rem: u64 = 0; |
| unsafe { |
| asm!("div r11", |
| in("r11") y, |
| inout("eax") x => res, |
| inout("edx") rem, |
| ); |
| } |
| assert_eq!(res, 7); |
| assert_eq!(rem, 2); |
| |
| // check const |
| let mut x: u64 = 42; |
| unsafe { |
| asm!("add {}, {}", |
| inout(reg) x, |
| const 1 |
| ); |
| } |
| assert_eq!(x, 43); |
| |
| // check const (ATT syntax) |
| let mut x: u64 = 42; |
| unsafe { |
| asm!("add ${}, {}", |
| const 1, |
| inout(reg) x, |
| options(att_syntax) |
| ); |
| } |
| assert_eq!(x, 43); |
| |
| // check sym fn |
| extern "C" fn foo() -> u64 { |
| 42 |
| } |
| let x: u64; |
| unsafe { |
| asm!("call {}", sym foo, lateout("rax") x); |
| } |
| assert_eq!(x, 42); |
| |
| // check sym fn (ATT syntax) |
| let x: u64; |
| unsafe { |
| asm!("call {}", sym foo, lateout("rax") x, options(att_syntax)); |
| } |
| assert_eq!(x, 42); |
| |
| // check sym static |
| static FOO: u64 = 42; |
| let x: u64; |
| unsafe { |
| asm!("mov {1}, qword ptr [rip + {0}]", sym FOO, lateout(reg) x); |
| } |
| assert_eq!(x, 42); |
| |
| // check sym static (ATT syntax) |
| let x: u64; |
| unsafe { |
| asm!("movq {0}(%rip), {1}", sym FOO, lateout(reg) x, options(att_syntax)); |
| } |
| assert_eq!(x, 42); |
| |
| assert_eq!(unsafe { add_asm(40, 2) }, 42); |
| |
| let array1 = [1u8, 2, 3]; |
| let mut array2 = [0u8, 0, 0]; |
| unsafe { |
| mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3); |
| } |
| assert_eq!(array1, array2); |
| } |
| |
| #[cfg(not(target_arch="x86_64"))] |
| fn asm() { |
| } |
| |
| fn main() { |
| asm(); |
| } |