Skip to content

Commit cb939ea

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

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

src/lib.rs

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

src/mem/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ type c_int = i16;
66
type c_int = i32;
77

88
// memcpy and friends have optimized implementations on some architectures
9-
#[path = "fallback.rs"]
9+
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
10+
#[cfg_attr(not(target_arch = "x86_64"), path = "fallback.rs")]
1011
mod memcpy;
1112
pub use self::memcpy::*;
1213

src/mem/x86_64.rs

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use super::c_int;
2+
3+
#[inline(always)]
4+
unsafe fn copy_forward(dest: *mut u8, src: *const u8, count: usize) {
5+
asm!(
6+
"rep movsb [rdi], [rsi]",
7+
inout("rdi") dest => _,
8+
inout("rsi") src => _,
9+
inout("rcx") count => _,
10+
options(nostack, preserves_flags)
11+
);
12+
}
13+
14+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
15+
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 {
16+
copy_forward(dest, src, count);
17+
dest
18+
}
19+
20+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
21+
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 {
22+
if src < dest as *const u8 {
23+
// copy backwards
24+
asm!(
25+
"std
26+
rep movsb [rdi], [rsi]
27+
cld",
28+
inout("rdi") dest.add(count).sub(1) => _,
29+
inout("rsi") src.add(count).sub(1) => _,
30+
inout("rcx") count => _,
31+
options(nostack, preserves_flags)
32+
);
33+
} else {
34+
copy_forward(dest, src, count);
35+
}
36+
dest
37+
}
38+
39+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
40+
pub unsafe extern "C" fn memset(dest: *mut u8, c: c_int, count: usize) -> *mut u8 {
41+
asm!(
42+
"rep stosb [rdi], al",
43+
inout("rdi") dest => _,
44+
in("al") c as u8,
45+
inout("rcx") count => _,
46+
options(nostack, preserves_flags)
47+
);
48+
dest
49+
}
50+
51+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
52+
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, count: usize) -> i32 {
53+
let res: i32;
54+
asm!(
55+
"repe cmpsb [rsi], [rdi]
56+
setb {0:l}
57+
cmova {0:e}, {1:e}",
58+
inout(reg_abcd) 0 => res,
59+
in(reg) -1i32,
60+
inout("rsi") s2 => _,
61+
inout("rdi") s1 => _,
62+
inout("rcx") count => _,
63+
options(nostack, pure, readonly)
64+
);
65+
res
66+
}
67+
68+
#[cfg_attr(all(feature = "mem", not(feature = "mangled-names")), no_mangle)]
69+
pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, count: usize) -> i32 {
70+
let res: i32;
71+
asm!(
72+
"repe cmpsb [rsi], [rdi]
73+
setne {0:l}",
74+
inout(reg_abcd) 0 => res,
75+
inout("rsi") s2 => _,
76+
inout("rdi") s1 => _,
77+
inout("rcx") count => _,
78+
options(nostack, pure, readonly)
79+
);
80+
res
81+
}

0 commit comments

Comments
 (0)