// assembly-output: emit-asm // compile-flags: --target avr-unknown-gnu-atmega328 // needs-llvm-components: avr #![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] #[rustc_builtin_macro] macro_rules! asm { () => {}; } #[rustc_builtin_macro] macro_rules! concat { () => {}; } #[lang = "sized"] trait Sized {} #[lang = "copy"] trait Copy {} type ptr = *const u64; impl Copy for i8 {} impl Copy for i16 {} impl Copy for i32 {} impl Copy for i64 {} impl Copy for ptr {} macro_rules! check { ($func:ident $ty:ident $class:ident) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!("mov {}, {}", lateout($class) y, in($class) x); y } }; } macro_rules! checkw { ($func:ident $ty:ident $class:ident) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!("movw {}, {}", lateout($class) y, in($class) x); y } }; } macro_rules! check_reg { ($func:ident $ty:ident $reg:tt) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!(concat!("mov ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); y } }; } macro_rules! check_regw { ($func:ident $ty:ident $reg:tt $reg_lit:tt) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!(concat!("movw ", $reg_lit, ", ", $reg_lit), lateout($reg) y, in($reg) x); y } }; } extern "C" { fn extern_func(); static extern_static: i8; } // CHECK-LABEL: sym_fn // CHECK: ;APP // CHECK: call extern_func // CHECK: ;NO_APP #[no_mangle] pub unsafe fn sym_fn() { asm!("call {}", sym extern_func); } // CHECK-LABEL: sym_static // CHECK: ;APP // CHECK: lds r{{[0-9]+}}, extern_static // CHECK: ;NO_APP #[no_mangle] pub unsafe fn sym_static() -> i8 { let y; asm!("lds {}, {}", lateout(reg) y, sym extern_static); y } // CHECK-LABEL: ld_z: // CHECK: ;APP // CHECK: ld r{{[0-9]+}}, Z // CHECK: ;NO_APP #[no_mangle] pub unsafe fn ld_z(x: i16) -> i8 { let y; asm!("ld {}, Z", out(reg) y, in("Z") x); y } // CHECK-LABEL: ldd_z: // CHECK: ;APP // CHECK: ldd r{{[0-9]+}}, Z+4 // CHECK: ;NO_APP #[no_mangle] pub unsafe fn ldd_z(x: i16) -> i8 { let y; asm!("ldd {}, Z+4", out(reg) y, in("Z") x); y } // CHECK-LABEL: ld_predecrement: // CHECK: ;APP // CHECK: ld r{{[0-9]+}}, -Z // CHECK: ;NO_APP #[no_mangle] pub unsafe fn ld_predecrement(x: i16) -> i8 { let y; asm!("ld {}, -Z", out(reg) y, in("Z") x); y } // CHECK-LABEL: ld_postincrement: // CHECK: ;APP // CHECK: ld r{{[0-9]+}}, Z+ // CHECK: ;NO_APP #[no_mangle] pub unsafe fn ld_postincrement(x: i16) -> i8 { let y; asm!("ld {}, Z+", out(reg) y, in("Z") x); y } // CHECK-LABEL: muls_clobber: // CHECK: ;APP // CHECK: muls r{{[0-9]+}}, r{{[0-9]+}} // CHECK: movw r{{[0-9]+}}, r0 // CHECK: ;NO_APP #[no_mangle] pub unsafe fn muls_clobber(x: i8, y: i8) -> i16 { let z; asm!( "muls {}, {}", "movw {}, r1:r0", out(reg_iw) z, in(reg) x, in(reg) y, ); z } // CHECK-LABEL: reg_i8: // CHECK: ;APP // CHECK: mov r{{[0-9]+}}, r{{[0-9]+}} // CHECK: ;NO_APP check!(reg_i8 i8 reg); // CHECK-LABEL: reg_upper_i8: // CHECK: ;APP // CHECK: mov r{{[1-3][0-9]}}, r{{[1-3][0-9]}} // CHECK: ;NO_APP check!(reg_upper_i8 i8 reg_upper); // CHECK-LABEL: reg_pair_i16: // CHECK: ;APP // CHECK: movw r{{[0-9]+}}, r{{[0-9]+}} // CHECK: ;NO_APP checkw!(reg_pair_i16 i16 reg_pair); // CHECK-LABEL: reg_iw_i16: // CHECK: ;APP // CHECK: movw r{{[0-9]+}}, r{{[0-9]+}} // CHECK: ;NO_APP checkw!(reg_iw_i16 i16 reg_iw); // CHECK-LABEL: reg_ptr_i16: // CHECK: ;APP // CHECK: movw r{{[0-9]+}}, r{{[0-9]+}} // CHECK: ;NO_APP checkw!(reg_ptr_i16 i16 reg_ptr); // CHECK-LABEL: r2_i8: // CHECK: ;APP // CHECK: mov r2, r2 // CHECK: ;NO_APP check_reg!(r2_i8 i8 "r2"); // CHECK-LABEL: xl_i8: // CHECK: ;APP // CHECK: mov r26, r26 // CHECK: ;NO_APP check_reg!(xl_i8 i8 "XL"); // CHECK-LABEL: xh_i8: // CHECK: ;APP // CHECK: mov r27, r27 // CHECK: ;NO_APP check_reg!(xh_i8 i8 "XH"); // CHECK-LABEL: x_i16: // CHECK: ;APP // CHECK: movw r26, r26 // CHECK: ;NO_APP check_regw!(x_i16 i16 "X" "X"); // CHECK-LABEL: r25r24_i16: // CHECK: ;APP // CHECK: movw r24, r24 // CHECK: ;NO_APP check_regw!(r25r24_i16 i16 "r25r24" "r24");