1/* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7*/ 8 9#if !_BOOT_MODE 10# include "asm_offsets.h" 11#endif 12 13#include <asm_defs.h> 14 15 16// We don't need the indirection in the boot loader. 17#if _BOOT_MODE 18# define memcpy_generic memcpy 19# define memset_generic memset 20#endif 21 22 23.align 4 24FUNCTION(memcpy_generic): 25 pushl %esi 26 pushl %edi 27 movl 12(%esp),%edi /* dest */ 28 movl %edi,%eax /* save dest ptr as return address */ 29 movl 16(%esp),%esi /* source */ 30 movl 20(%esp),%ecx /* count */ 31 32 /* move by words */ 33 // TODO: The addresses might not be aligned! 34 cld 35 shrl $2,%ecx 36 rep 37 movsl 38 39 /* move any remaining data by bytes */ 40 movl 20(%esp),%ecx 41 andl $3,%ecx 42 rep 43 movsb 44 45 popl %edi 46 popl %esi 47 ret 48FUNCTION_END(memcpy_generic) 49SYMBOL(memcpy_generic_end): 50 51 52/* void *memset(void *dest, int value, size_t length); */ 53.align 4 54FUNCTION(memset_generic): 55 push %ebp 56 mov %esp, %ebp 57 58 // %eax, %ecx, and %edx are scratch registers -- we only have to save %edi 59 push %edi 60 61 // get the parameters 62 mov 16(%ebp), %ecx 63 mov 12(%ebp), %eax 64 mov 8(%ebp), %edi 65 66 // When touching less than 12 bytes, we just do it bytewise. We might be 67 // able to process one or two lwords lwordwise, but the additional overhead 68 // isn't worth it. 69 cmp $12, %ecx 70 jl 2f 71 72 // buffer address lword-aligned? 73 mov %edi, %edx 74 and $0x3, %edx 75 jz 1f 76 77 // the buffer is unaligned -- copy the first bytes bytewise 78 mov $4, %ecx 79 sub %edx, %ecx 80 rep stosb 81 82 mov 16(%ebp), %ecx 83 sub $4, %ecx 84 add %edx, %ecx 85 861: // lwordwise 87 // prepare %eax -- the low byte must be copied to the other bytes 88 mov %al, %ah 89 mov %eax, %edx 90 shl $16, %eax 91 mov %dx, %ax 92 93 // get the unaligned remainder into %edx 94 mov %ecx, %edx 95 and $0x3, %edx 96 97 // write words 98 shr $2, %ecx 99 rep stosl 100 101 mov %edx, %ecx 102 1032: // bytewise (remaining bytes) 104 rep stosb 105 106 pop %edi 107 108 // return value is the value passed in 109 mov 8(%ebp), %eax 110 111 mov %ebp, %esp 112 pop %ebp 113 ret 114FUNCTION_END(memset_generic) 115SYMBOL(memset_generic_end): 116 117 118#if !_BOOT_MODE 119 120.align 4 121FUNCTION(memcpy): 122 jmp *(gOptimizedFunctions + X86_OPTIMIZED_FUNCTIONS_memcpy) 123FUNCTION_END(memcpy) 124 125FUNCTION(memset): 126 jmp *(gOptimizedFunctions + X86_OPTIMIZED_FUNCTIONS_memset) 127FUNCTION_END(memset) 128 129#endif // !_BOOT_MODE 130