Skip to content
Snippets Groups Projects
externs.rs 7.66 KiB
Newer Older
/// 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*8) as *mut u64) =
            *((src as usize + i*8) as *const u64);
        i += 1;
    }

    let mut i: usize = 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/8; // Number of 32-bit groups
    let mut i: usize = 0;

    // Copy 4 bytes at a time
    while i < n_32 {
        *((dest as usize + i*4) as *mut u32) =
            *((src as usize + i*4) as *const u32);
        i += 1;
    }

    let mut i: usize = i*4;
    while i < n {
        *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8);
        i += 1;
    }

    dest
}

/// Memmove
///
/// Copy N bytes of memory from src to dest. The memory areas may overlap.
///
/// 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;

        // Copy 8 bytes at a time
            *((dest as usize + i*8) as *mut u64) =
                *((src as usize + i*8) 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);
        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*8) as *mut u64) =
                *((src as usize + i*8) as *const u64);
            i += 1;
        }

        let mut i: usize = i*8;

        // Copy 1 byte at a time
            *((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;

        // Copy 4 bytes at a time
        while i != 0 {
            i -= 1;
            *((dest as usize + i*4) as *mut u32) =
                *((src as usize + i*4) as *const u32);
        }

        let mut i: usize = n;

        // Copy 1 byte at a time
        while i != n_32*4 {
            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 mut i: usize = 0;

        // Copy 4 bytes at a time
        while i < n_32 {
            *((dest as usize + i*4) as *mut u32) =
                *((src as usize + i*4) as *const u32);
            i += 1;
        }

        let mut i: usize = i*4;

        // 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
}

/// Memset
///
/// Fill a block of memory with a specified value.
///
/// 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*8) as *mut u64) = c;
        i += 1;
    }

    let c = c as u8;
    let mut i: usize = i*8;

    // 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 mut i: usize = 0;

    // Set 4 bytes at a time
    while i < n_32 {
        *((dest as usize + i*4) as *mut u32) = c;
        i += 1;
    }

    let c = c as u8;
    let mut i: usize = i*4;

    // Set 1 byte at a time
        *((dest as usize + i) as *mut u8) = c;
        i += 1;
    }

    dest
}

/// Memcmp
///
/// Compare two blocks of memory.
///
/// 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*8) as *const u64);
        let b = *((s2 as usize + i*8) as *const u64);
        if a != b {
            let mut i: usize = i*8;
            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 += 1;
    }

    let mut i: usize = 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 mut i: usize = 0;

    while i < n_32 {
        let a = *((s1 as usize + i*4) as *const u32);
        let b = *((s2 as usize + i*4) as *const u32);
        if a != b {
            let mut i: usize = i*4;
            let n: usize = i + 4;
            // 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 += 1;
    }

    let mut i: usize = i*4;

    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;