From b18c9b97aeb4a7af1c5bca0bc99f02ad19e716f4 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 10 Oct 2008 18:43:46 +0000 Subject: [PATCH] * Implemented x86 assembly version of memset(). * memset() is now available through the commpage. * CPU modules can provide a model-optimized memset(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27952 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/arch_cpu.h | 2 + src/system/boot/Jamfile | 1 - src/system/boot/arch/m68k/Jamfile | 1 + src/system/boot/arch/ppc/Jamfile | 1 + src/system/kernel/arch/x86/arch_cpu.cpp | 18 ++++- src/system/kernel/arch/x86/asm_offsets.cpp | 2 + src/system/kernel/lib/Jamfile | 1 - src/system/kernel/lib/arch/m68k/Jamfile | 1 + src/system/kernel/lib/arch/ppc/Jamfile | 1 + src/system/kernel/lib/arch/x86/arch_string.S | 81 ++++++++++++++++++- src/system/libroot/posix/string/Jamfile | 1 - .../posix/string/{ => arch/generic}/memset.c | 0 .../libroot/posix/string/arch/m68k/Jamfile | 3 + .../libroot/posix/string/arch/ppc/Jamfile | 1 + .../posix/string/arch/x86/arch_string.S | 18 ++--- src/system/runtime_loader/Jamfile | 1 - src/system/runtime_loader/arch/m68k/Jamfile | 1 + src/system/runtime_loader/arch/ppc/Jamfile | 1 + 18 files changed, 119 insertions(+), 16 deletions(-) rename src/system/libroot/posix/string/{ => arch/generic}/memset.c (100%) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 36257a1138..ff81df09c0 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -100,6 +100,8 @@ typedef struct x86_optimized_functions { void (*memcpy)(void* dest, const void* source, size_t count); void* memcpy_end; + void (*memset)(void* dest, int value, size_t count); + void* memset_end; } x86_optimized_functions; typedef struct x86_cpu_module_info { diff --git a/src/system/boot/Jamfile b/src/system/boot/Jamfile index 3eac06be88..a50ce59cc1 100644 --- a/src/system/boot/Jamfile +++ b/src/system/boot/Jamfile @@ -5,7 +5,6 @@ local librootFunctions = ctype.o qsort.o kernel_vsprintf.o - memset.o memcmp.o memmove.o strdup.o diff --git a/src/system/boot/arch/m68k/Jamfile b/src/system/boot/arch/m68k/Jamfile index d2d4cc7cdb..e7913c3f1c 100644 --- a/src/system/boot/arch/m68k/Jamfile +++ b/src/system/boot/arch/m68k/Jamfile @@ -10,6 +10,7 @@ local librootArchObjects = local kernelLibArchObjects = byteorder.o + memset.o ; KernelMergeObject boot_arch_$(TARGET_ARCH).o : diff --git a/src/system/boot/arch/ppc/Jamfile b/src/system/boot/arch/ppc/Jamfile index 394995e00b..0a064782d1 100644 --- a/src/system/boot/arch/ppc/Jamfile +++ b/src/system/boot/arch/ppc/Jamfile @@ -5,6 +5,7 @@ DEFINES += _BOOT_MODE ; local kernelLibArchObjects = byteorder.o memcpy.o + memset.o ; KernelMergeObject boot_arch_$(TARGET_ARCH).o : diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index ca2f1dc336..0f251748f9 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -87,10 +87,14 @@ static x86_cpu_module_info *sCpuModule; extern "C" void memcpy_generic(void* dest, const void* source, size_t count); extern int memcpy_generic_end; +extern "C" void memset_generic(void* dest, int value, size_t count); +extern int memset_generic_end; x86_optimized_functions gOptimizedFunctions = { memcpy_generic, - &memcpy_generic_end + &memcpy_generic_end, + memset_generic, + &memset_generic_end }; @@ -605,6 +609,11 @@ arch_cpu_init_post_modules(kernel_args *args) gOptimizedFunctions.memcpy = functions.memcpy; gOptimizedFunctions.memcpy_end = functions.memcpy_end; } + + if (functions.memset != NULL) { + gOptimizedFunctions.memset = functions.memset; + gOptimizedFunctions.memset_end = functions.memset_end; + } } // put the optimized functions into the commpage @@ -612,12 +621,19 @@ arch_cpu_init_post_modules(kernel_args *args) - (addr_t)gOptimizedFunctions.memcpy; fill_commpage_entry(COMMPAGE_ENTRY_X86_MEMCPY, (const void*)gOptimizedFunctions.memcpy, memcpyLen); + size_t memsetLen = (addr_t)gOptimizedFunctions.memset_end + - (addr_t)gOptimizedFunctions.memset; + fill_commpage_entry(COMMPAGE_ENTRY_X86_MEMSET, + (const void*)gOptimizedFunctions.memset, memsetLen); // add the functions to the commpage image image_id image = get_commpage_image(); elf_add_memory_image_symbol(image, "commpage_memcpy", ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_MEMCPY], memcpyLen, B_SYMBOL_TYPE_TEXT); + elf_add_memory_image_symbol(image, "commpage_memset", + ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_MEMSET], memsetLen, + B_SYMBOL_TYPE_TEXT); return B_OK; } diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index 77ea318efd..2f82ee6134 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -57,4 +57,6 @@ dummy() // struct x86_optimized_functions DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, memcpy); + DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, + memset); } diff --git a/src/system/kernel/lib/Jamfile b/src/system/kernel/lib/Jamfile index eaa70e1b6a..c4cf4c1efc 100644 --- a/src/system/kernel/lib/Jamfile +++ b/src/system/kernel/lib/Jamfile @@ -86,7 +86,6 @@ KernelMergeObject kernel_lib_posix.o : memchr.c memcmp.c memmove.c - memset.c strcasecmp.c strcasestr.c strcat.c diff --git a/src/system/kernel/lib/arch/m68k/Jamfile b/src/system/kernel/lib/arch/m68k/Jamfile index 638b487410..452b6b97a5 100644 --- a/src/system/kernel/lib/arch/m68k/Jamfile +++ b/src/system/kernel/lib/arch/m68k/Jamfile @@ -27,6 +27,7 @@ KernelMergeObject kernel_lib_posix_arch_$(TARGET_ARCH).o : kernel_setjmp_save_sigs.c arch_string.S + memset.c : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/kernel/lib/arch/ppc/Jamfile b/src/system/kernel/lib/arch/ppc/Jamfile index 047099d474..b7509ba3a3 100644 --- a/src/system/kernel/lib/arch/ppc/Jamfile +++ b/src/system/kernel/lib/arch/ppc/Jamfile @@ -26,6 +26,7 @@ KernelMergeObject kernel_lib_posix_arch_$(TARGET_ARCH).o : kernel_setjmp_save_sigs.c memcpy.c + memset.c : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/kernel/lib/arch/x86/arch_string.S b/src/system/kernel/lib/arch/x86/arch_string.S index 7c7c56a29e..1723e2239c 100644 --- a/src/system/kernel/lib/arch/x86/arch_string.S +++ b/src/system/kernel/lib/arch/x86/arch_string.S @@ -1,6 +1,9 @@ /* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. */ #if !_BOOT_MODE @@ -13,6 +16,7 @@ // We don't need the indirection in the boot loader. #if _BOOT_MODE # define memcpy_generic memcpy +# define memset_generic memset #endif @@ -26,6 +30,7 @@ FUNCTION(memcpy_generic): movl 20(%esp),%ecx /* count */ /* move by words */ + // TODO: The addresses might not be aligned! cld shrl $2,%ecx rep @@ -40,13 +45,85 @@ FUNCTION(memcpy_generic): popl %edi popl %esi ret +FUNCTION_END(memcpy_generic) SYMBOL(memcpy_generic_end): +/* void *memset(void *dest, int value, size_t length); */ +.align 4 +FUNCTION(memset_generic): + push %ebp + mov %esp, %ebp + + // %eax, %ecx, and %edx are scratch registers -- we only have to save %edi + push %edi + + // get the parameters + mov 16(%ebp), %ecx + mov 12(%ebp), %eax + mov 8(%ebp), %edi + + // When touching less than 12 bytes, we just do it bytewise. We might be + // able to process one or two lwords lwordwise, but the additional overhead + // isn't worth it. + cmp $12, %ecx + jl 2f + + // buffer address lword-aligned? + mov %edi, %edx + and $0x3, %edx + jz 1f + + // the buffer is unaligned -- copy the first bytes bytewise + mov $4, %ecx + sub %edx, %ecx + rep stosb + + mov 16(%ebp), %ecx + sub $4, %ecx + add %edx, %ecx + +1: // lwordwise + // prepare %eax -- the low byte must be copied to the other bytes + mov %al, %ah + mov %ax, %dx + shl $16, %eax + mov %dx, %ax + + // get the unaligned remainder into %edx + mov %ecx, %edx + and $0x3, %edx + + // write words + shr $2, %ecx + rep stosl + + mov %edx, %ecx + +2: // bytewise (remaining bytes) + rep stosb + + pop %edi + + // return value is the value passed in + mov 12(%ebp), %eax + + mov %ebp, %esp + pop %ebp + ret +FUNCTION_END(memset_generic) +SYMBOL(memset_generic_end): + + #if !_BOOT_MODE .align 4 FUNCTION(memcpy): jmp *(gOptimizedFunctions + X86_OPTIMIZED_FUNCTIONS_memcpy) +FUNCTION_END(memcpy) + +FUNCTION(memset): + jmp *(gOptimizedFunctions + X86_OPTIMIZED_FUNCTIONS_memset) +FUNCTION_END(memset) #endif // !_BOOT_MODE diff --git a/src/system/libroot/posix/string/Jamfile b/src/system/libroot/posix/string/Jamfile index 23ceedaa2f..0cdc07efc3 100644 --- a/src/system/libroot/posix/string/Jamfile +++ b/src/system/libroot/posix/string/Jamfile @@ -9,7 +9,6 @@ MergeObject posix_string.o : memchr.c memcmp.c memmove.c - memset.c stpcpy.c strcasecmp.c strcasestr.c diff --git a/src/system/libroot/posix/string/memset.c b/src/system/libroot/posix/string/arch/generic/memset.c similarity index 100% rename from src/system/libroot/posix/string/memset.c rename to src/system/libroot/posix/string/arch/generic/memset.c diff --git a/src/system/libroot/posix/string/arch/m68k/Jamfile b/src/system/libroot/posix/string/arch/m68k/Jamfile index 4badb72e70..6642b95fc7 100644 --- a/src/system/libroot/posix/string/arch/m68k/Jamfile +++ b/src/system/libroot/posix/string/arch/m68k/Jamfile @@ -2,6 +2,9 @@ SubDir HAIKU_TOP src system libroot posix string arch m68k ; UsePrivateSystemHeaders ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + MergeObject posix_string_arch_$(TARGET_ARCH).o : arch_string.S + memset.c ; diff --git a/src/system/libroot/posix/string/arch/ppc/Jamfile b/src/system/libroot/posix/string/arch/ppc/Jamfile index ffa9d82101..920c691c46 100644 --- a/src/system/libroot/posix/string/arch/ppc/Jamfile +++ b/src/system/libroot/posix/string/arch/ppc/Jamfile @@ -6,4 +6,5 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; MergeObject posix_string_arch_$(TARGET_ARCH).o : memcpy.c + memset.c ; diff --git a/src/system/libroot/posix/string/arch/x86/arch_string.S b/src/system/libroot/posix/string/arch/x86/arch_string.S index 5fd8e46c28..4ab85e7da0 100644 --- a/src/system/libroot/posix/string/arch/x86/arch_string.S +++ b/src/system/libroot/posix/string/arch/x86/arch_string.S @@ -1,18 +1,18 @@ /* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ - -#if !_KERNEL_MODE - // TODO: This should not even be compiled for the kernel. Fix the TODO in - // src/system/kernel/lib/Jamfile! + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#include #include -#define FUNCTION(x) .global x; .type x,@function; x .align 4 + FUNCTION(memcpy): jmp *(USER_COMMPAGE_ADDR + COMMPAGE_ENTRY_X86_MEMCPY * 4) +FUNCTION_END(memcpy) -#endif // !_KERNEL_MODE +FUNCTION(memset): + jmp *(USER_COMMPAGE_ADDR + COMMPAGE_ENTRY_X86_MEMSET * 4) +FUNCTION_END(memset) diff --git a/src/system/runtime_loader/Jamfile b/src/system/runtime_loader/Jamfile index fc0b655219..c2f6c15bb1 100644 --- a/src/system/runtime_loader/Jamfile +++ b/src/system/runtime_loader/Jamfile @@ -36,7 +36,6 @@ StaticLibrary libruntime_loader.a : memchr.o memcmp.o memmove.o - memset.o strcasecmp.o strcat.o strchr.o diff --git a/src/system/runtime_loader/arch/m68k/Jamfile b/src/system/runtime_loader/arch/m68k/Jamfile index e7cafc8107..1c38982f24 100644 --- a/src/system/runtime_loader/arch/m68k/Jamfile +++ b/src/system/runtime_loader/arch/m68k/Jamfile @@ -12,4 +12,5 @@ StaticLibrary libruntime_loader_$(TARGET_ARCH).a : thread.o arch_string.o + memset.o ; diff --git a/src/system/runtime_loader/arch/ppc/Jamfile b/src/system/runtime_loader/arch/ppc/Jamfile index 312ec91be6..f278b85197 100644 --- a/src/system/runtime_loader/arch/ppc/Jamfile +++ b/src/system/runtime_loader/arch/ppc/Jamfile @@ -12,4 +12,5 @@ StaticLibrary libruntime_loader_$(TARGET_ARCH).a : thread.o memcpy.o + memset.o ;