From 528ffa985ae85daff33821721f27ca2cfaa253c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jedelsk=C3=BD?= <hjajet@gmail.com> Date: Thu, 5 Oct 2017 14:19:25 +0200 Subject: [PATCH] Deduplicate memcpy, memmove, memset and memcmp functions --- src/externs.rs | 203 +++++++++---------------------------------------- src/lib.rs | 1 + 2 files changed, 36 insertions(+), 168 deletions(-) diff --git a/src/externs.rs b/src/externs.rs index 42fb3e63..03bc34cd 100644 --- a/src/externs.rs +++ b/src/externs.rs @@ -1,45 +1,25 @@ +use core::mem; + +const WORD_SIZE: usize = mem::size_of::<usize>(); + /// Memcpy /// /// Copy N bytes of memory from one location to another. /// /// 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). -#[cfg(target_pointer_width = "64")] #[no_mangle] pub unsafe extern fn memcpy(dest: *mut u8, src: *const 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 -#[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 n_usize: usize = n/WORD_SIZE; // Number of word sized groups let mut i: usize = 0; - // Copy 4 bytes at a time - while i < n_32 { - *((dest as usize + i) as *mut u32) = - *((src as usize + i) as *const u32); - i += 4; + // Copy `WORD_SIZE` bytes at a time + while i < n_usize { + *((dest as usize + i) as *mut usize) = + *((src as usize + i) as *const usize); + i += WORD_SIZE; } // Copy 1 byte at a time @@ -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 /// 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] pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { if src < dest as *const u8 { - let n_32: usize = n/4; // Number of 32-bit groups - let mut i: usize = n_32*4; + let n_usize: usize = n/WORD_SIZE; // Number of word sized groups + let mut i: usize = n_usize*WORD_SIZE; - // Copy 4 bytes at a time + // Copy `WORD_SIZE` bytes at a time while i != 0 { - i -= 4; - *((dest as usize + i) as *mut u32) = - *((src as usize + i) as *const u32); + i -= WORD_SIZE; + *((dest as usize + i) as *mut usize) = + *((src as usize + i) as *const usize); } let mut i: usize = n; // Copy 1 byte at a time - while i != n_32*4 { + while i != n_usize*WORD_SIZE { i -= 1; *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); } } else { - let n_32: usize = n/4; // Number of 32-bit groups + let n_usize: usize = n/WORD_SIZE; // Number of 64-bit groups let mut i: usize = 0; - // Copy 4 bytes at a time - while i < n_32 { - *((dest as usize + i) as *mut u32) = - *((src as usize + i) as *const u32); - i += 4; + // Copy `WORD_SIZE` bytes at a time + while i < n_usize { + *((dest as usize + i) as *mut usize) = + *((src as usize + i) as *const usize); + i += WORD_SIZE; } // Copy 1 byte at a time @@ -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 /// 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] pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { - let c = c as u32; - let c = (c << 24) | (c << 16) | (c << 8) | c; - let n_32: usize = n/4; + let c: usize = mem::transmute([c as u8; WORD_SIZE]); + let n_usize: usize = n/WORD_SIZE; let mut i: usize = 0; - // Set 4 bytes at a time - while i < n_32 { - *((dest as usize + i) as *mut u32) = c; - i += 4; + // Set `WORD_SIZE` bytes at a time + while i < n_usize { + *((dest as usize + i) as *mut usize) = c; + i += WORD_SIZE; } let c = c as 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 /// 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] 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; - while i < n_32 { - let a = *((s1 as usize + i) as *const u32); - let b = *((s2 as usize + i) as *const u32); + while i < n_usize { + let a = *((s1 as usize + i) as *const usize); + let b = *((s2 as usize + i) as *const usize); if a != b { - let n: usize = i + 4; + let n: usize = i + WORD_SIZE; // Find the one byte that is not equal while i < n { 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 { i += 1; } } - i += 4; + i += WORD_SIZE; } while i < n { diff --git a/src/lib.rs b/src/lib.rs index 92c2dbbc..56ec8f16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ #![feature(never_type)] #![feature(thread_local)] #![feature(unique)] +#![feature(const_size_of)] #![no_std] extern crate alloc_kernel as allocator; -- GitLab