Skip to content

Commit

Permalink
mem: Add REP MOVSB/STOSB implementations
Browse files Browse the repository at this point in the history
The assembly generated seems correct:
    https://rust.godbolt.org/z/GGnec8

Signed-off-by: Joe Richey <[email protected]>
  • Loading branch information
josephlr committed Oct 15, 2020
1 parent ee54782 commit 8d25b6a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
#![cfg_attr(feature = "asm", feature(asm))]
#![feature(abi_unadjusted)]
#![feature(asm)]
#![feature(llvm_asm)]
#![feature(global_asm)]
#![feature(cfg_target_has_atomic)]
Expand Down
1 change: 1 addition & 0 deletions src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::mem;
use core::ops::{BitOr, Shl};

// memcpy/memmove/memset have optimized implementations on some architectures
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
mod memcpy;
pub use self::memcpy::*;

Expand Down
46 changes: 46 additions & 0 deletions src/mem/x86_64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use super::c_int;

#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 {
asm!(
"rep movsb [rdi], [rsi]",
inout("rcx") count => _,
inout("rdi") dest => _,
inout("rsi") src => _,
options(nostack, preserves_flags)
);
dest
}

#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 {
let delta = dest as usize - src as usize;
if delta >= count {
// We can copy forwards because either dest is far enough ahead of src,
// or src is ahead of dest (and delta overflowed).
return self::memcpy(dest, src, count);
}
// copy backwards
asm!(
"std",
"rep movsb [rdi], [rsi]",
"cld",
inout("rcx") count => _,
inout("rdi") dest.add(count).sub(1) => _,
inout("rsi") src.add(count).sub(1) => _,
options(nostack, preserves_flags)
);
dest
}

#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
pub unsafe extern "C" fn memset(dest: *mut u8, c: c_int, count: usize) -> *mut u8 {
asm!(
"rep stosb [rdi], al",
inout("rcx") count => _,
inout("rdi") dest => _,
in("al") c as u8,
options(nostack, preserves_flags)
);
dest
}

0 comments on commit 8d25b6a

Please sign in to comment.