Skip to content

Commit 8d25b6a

Browse files
committed
mem: Add REP MOVSB/STOSB implementations
The assembly generated seems correct: https://rust.godbolt.org/z/GGnec8 Signed-off-by: Joe Richey <[email protected]>
1 parent ee54782 commit 8d25b6a

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
22
#![cfg_attr(feature = "asm", feature(asm))]
33
#![feature(abi_unadjusted)]
4+
#![feature(asm)]
45
#![feature(llvm_asm)]
56
#![feature(global_asm)]
67
#![feature(cfg_target_has_atomic)]

src/mem/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use core::mem;
1010
use core::ops::{BitOr, Shl};
1111

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

src/mem/x86_64.rs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use super::c_int;
2+
3+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
4+
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 {
5+
asm!(
6+
"rep movsb [rdi], [rsi]",
7+
inout("rcx") count => _,
8+
inout("rdi") dest => _,
9+
inout("rsi") src => _,
10+
options(nostack, preserves_flags)
11+
);
12+
dest
13+
}
14+
15+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
16+
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 {
17+
let delta = dest as usize - src as usize;
18+
if delta >= count {
19+
// We can copy forwards because either dest is far enough ahead of src,
20+
// or src is ahead of dest (and delta overflowed).
21+
return self::memcpy(dest, src, count);
22+
}
23+
// copy backwards
24+
asm!(
25+
"std",
26+
"rep movsb [rdi], [rsi]",
27+
"cld",
28+
inout("rcx") count => _,
29+
inout("rdi") dest.add(count).sub(1) => _,
30+
inout("rsi") src.add(count).sub(1) => _,
31+
options(nostack, preserves_flags)
32+
);
33+
dest
34+
}
35+
36+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
37+
pub unsafe extern "C" fn memset(dest: *mut u8, c: c_int, count: usize) -> *mut u8 {
38+
asm!(
39+
"rep stosb [rdi], al",
40+
inout("rcx") count => _,
41+
inout("rdi") dest => _,
42+
in("al") c as u8,
43+
options(nostack, preserves_flags)
44+
);
45+
dest
46+
}

0 commit comments

Comments
 (0)