Skip to content
Snippets Groups Projects
Commit b023a715 authored by Jeremy Soller's avatar Jeremy Soller Committed by GitHub
Browse files

Merge pull request #56 from jaje/externs

 Deduplicate memcpy, memmove, memset and memcmp functions
parents c417f0cf 05dc9140
No related branches found
No related tags found
No related merge requests found
use core::mem;
const WORD_SIZE: usize = mem::size_of::<usize>();
/// Memcpy /// Memcpy
/// ///
/// Copy N bytes of memory from one location to another. /// Copy N bytes of memory from one location to another.
/// ///
/// This faster implementation works by copying bytes not one-by-one, but in /// This faster implementation works by copying bytes not one-by-one, but in
/// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures).
#[cfg(target_pointer_width = "64")]
#[no_mangle] #[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 { n: usize) -> *mut u8 {
let n_64: usize = n/8; // Number of 64-bit groups
let mut i: usize = 0;
// Copy 8 bytes at a time
while i < n_64 {
*((dest as usize + i) as *mut u64) =
*((src as usize + i) as *const u64);
i += 8;
}
// Copy 1 byte at a time
while i < n {
*((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8);
i += 1;
}
dest
}
// 32-bit version of the function above let n_usize: usize = n/WORD_SIZE; // Number of word sized groups
#[cfg(target_pointer_width = "32")]
#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 {
let n_32: usize = n/4; // Number of 32-bit groups
let mut i: usize = 0; let mut i: usize = 0;
// Copy 4 bytes at a time // Copy `WORD_SIZE` bytes at a time
while i < n_32 { while i < n_usize {
*((dest as usize + i) as *mut u32) = *((dest as usize + i) as *mut usize) =
*((src as usize + i) as *const u32); *((src as usize + i) as *const usize);
i += 4; i += WORD_SIZE;
} }
// Copy 1 byte at a time // Copy 1 byte at a time
...@@ -57,84 +37,37 @@ pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, ...@@ -57,84 +37,37 @@ pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
/// ///
/// This faster implementation works by copying bytes not one-by-one, but in /// This faster implementation works by copying bytes not one-by-one, but in
/// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures).
#[cfg(target_pointer_width = "64")]
#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 {
if src < dest as *const u8 {
let n_64: usize = n/8; // Number of 64-bit groups
let mut i: usize = n_64*8;
// Copy 8 bytes at a time
while i != 0 {
i -= 8;
*((dest as usize + i) as *mut u64) =
*((src as usize + i) as *const u64);
}
let mut i: usize = n;
// Copy 1 byte at a time
while i != n_64*8 {
i -= 1;
*((dest as usize + i) as *mut u8) =
*((src as usize + i) as *const u8);
}
} else {
let n_64: usize = n/8; // Number of 64-bit groups
let mut i: usize = 0;
// Copy 8 bytes at a time
while i < n_64 {
*((dest as usize + i) as *mut u64) =
*((src as usize + i) as *const u64);
i += 8;
}
// Copy 1 byte at a time
while i < n {
*((dest as usize + i) as *mut u8) =
*((src as usize + i) as *const u8);
i += 1;
}
}
dest
}
// 32-bit version of the function above
#[cfg(target_pointer_width = "32")]
#[no_mangle] #[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 { n: usize) -> *mut u8 {
if src < dest as *const u8 { if src < dest as *const u8 {
let n_32: usize = n/4; // Number of 32-bit groups let n_usize: usize = n/WORD_SIZE; // Number of word sized groups
let mut i: usize = n_32*4; let mut i: usize = n_usize*WORD_SIZE;
// Copy 4 bytes at a time // Copy `WORD_SIZE` bytes at a time
while i != 0 { while i != 0 {
i -= 4; i -= WORD_SIZE;
*((dest as usize + i) as *mut u32) = *((dest as usize + i) as *mut usize) =
*((src as usize + i) as *const u32); *((src as usize + i) as *const usize);
} }
let mut i: usize = n; let mut i: usize = n;
// Copy 1 byte at a time // Copy 1 byte at a time
while i != n_32*4 { while i != n_usize*WORD_SIZE {
i -= 1; i -= 1;
*((dest as usize + i) as *mut u8) = *((dest as usize + i) as *mut u8) =
*((src as usize + i) as *const u8); *((src as usize + i) as *const u8);
} }
} else { } else {
let n_32: usize = n/4; // Number of 32-bit groups let n_usize: usize = n/WORD_SIZE; // Number of word sized groups
let mut i: usize = 0; let mut i: usize = 0;
// Copy 4 bytes at a time // Copy `WORD_SIZE` bytes at a time
while i < n_32 { while i < n_usize {
*((dest as usize + i) as *mut u32) = *((dest as usize + i) as *mut usize) =
*((src as usize + i) as *const u32); *((src as usize + i) as *const usize);
i += 4; i += WORD_SIZE;
} }
// Copy 1 byte at a time // Copy 1 byte at a time
...@@ -154,45 +87,16 @@ pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, ...@@ -154,45 +87,16 @@ pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
/// ///
/// This faster implementation works by setting bytes not one-by-one, but in /// This faster implementation works by setting bytes not one-by-one, but in
/// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures).
#[cfg(target_pointer_width = "64")]
#[no_mangle]
pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 {
let c = c as u64;
let c = (c << 56) | (c << 48) | (c << 40) | (c << 32)
| (c << 24) | (c << 16) | (c << 8) | c;
let n_64: usize = n/8;
let mut i: usize = 0;
// Set 8 bytes at a time
while i < n_64 {
*((dest as usize + i) as *mut u64) = c;
i += 8;
}
let c = c as u8;
// Set 1 byte at a time
while i < n {
*((dest as usize + i) as *mut u8) = c;
i += 1;
}
dest
}
// 32-bit version of the function above
#[cfg(target_pointer_width = "32")]
#[no_mangle] #[no_mangle]
pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 {
let c = c as u32; let c: usize = mem::transmute([c as u8; WORD_SIZE]);
let c = (c << 24) | (c << 16) | (c << 8) | c; let n_usize: usize = n/WORD_SIZE;
let n_32: usize = n/4;
let mut i: usize = 0; let mut i: usize = 0;
// Set 4 bytes at a time // Set `WORD_SIZE` bytes at a time
while i < n_32 { while i < n_usize {
*((dest as usize + i) as *mut u32) = c; *((dest as usize + i) as *mut usize) = c;
i += 4; i += WORD_SIZE;
} }
let c = c as u8; let c = c as u8;
...@@ -212,53 +116,16 @@ pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { ...@@ -212,53 +116,16 @@ pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 {
/// ///
/// This faster implementation works by comparing bytes not one-by-one, but in /// This faster implementation works by comparing bytes not one-by-one, but in
/// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures). /// groups of 8 bytes (or 4 bytes in the case of 32-bit architectures).
#[cfg(target_pointer_width = "64")]
#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
let n_64: usize = n/8;
let mut i: usize = 0;
while i < n_64 {
let a = *((s1 as usize + i) as *const u64);
let b = *((s2 as usize + i) as *const u64);
if a != b {
let n: usize = i + 8;
// Find the one byte that is not equal
while i < n {
let a = *((s1 as usize + i) as *const u8);
let b = *((s2 as usize + i) as *const u8);
if a != b {
return a as i32 - b as i32;
}
i += 1;
}
}
i += 8;
}
while i < n {
let a = *((s1 as usize + i) as *const u8);
let b = *((s2 as usize + i) as *const u8);
if a != b {
return a as i32 - b as i32;
}
i += 1;
}
0
}
#[cfg(target_pointer_width = "32")]
#[no_mangle] #[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
let n_32: usize = n/4; let n_usize: usize = n/WORD_SIZE;
let mut i: usize = 0; let mut i: usize = 0;
while i < n_32 { while i < n_usize {
let a = *((s1 as usize + i) as *const u32); let a = *((s1 as usize + i) as *const usize);
let b = *((s2 as usize + i) as *const u32); let b = *((s2 as usize + i) as *const usize);
if a != b { if a != b {
let n: usize = i + 4; let n: usize = i + WORD_SIZE;
// Find the one byte that is not equal // Find the one byte that is not equal
while i < n { while i < n {
let a = *((s1 as usize + i) as *const u8); let a = *((s1 as usize + i) as *const u8);
...@@ -269,7 +136,7 @@ pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { ...@@ -269,7 +136,7 @@ pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
i += 1; i += 1;
} }
} }
i += 4; i += WORD_SIZE;
} }
while i < n { while i < n {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#![feature(never_type)] #![feature(never_type)]
#![feature(thread_local)] #![feature(thread_local)]
#![feature(unique)] #![feature(unique)]
#![feature(const_size_of)]
#![no_std] #![no_std]
extern crate alloc_kernel as allocator; extern crate alloc_kernel as allocator;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment