2
// File : kvi_memmove.cpp (/usr/build/NEW_kvirc/kvirc/src/kvicore/kvi_memmove.cpp)
3
// Creation date : Fri Mar 19 1999 03:14:50 by Szymon Stefanek
5
// This file is part of the KVirc irc client distribution
6
// Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
8
// This program is FREE software. You can redistribute it and/or
9
// modify it under the terms of the GNU General Public License
10
// as published by the Free Software Foundation; either version 2
11
// of the License, or (at your opinion) any later version.
13
// This program is distributed in the HOPE that it will be USEFUL,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
// See the GNU General Public License for more details.
18
// You should have received a copy of the GNU General Public License
19
// along with this program. If not, write to the Free Software Foundation,
20
// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
#include "kvi_debug.h"
25
#define _KVI_MEMMOVE_CPP_
26
#include "kvi_memmove.h"
28
#include "kvi_settings.h"
30
#ifdef COMPILE_i386_ASM_CODE
32
void *kvi_memmove(void * dst_ptr,const void *src_ptr,int len)
34
__range_valid(dst_ptr);
35
__range_valid(src_ptr);
36
__range_valid(len >= 0);
37
// Save pointer registers
38
asm(" pushl %esi"); // save %esi
39
asm(" pushl %edi"); // save %edi
41
asm(" movl 16(%ebp),%ecx"); // %ecx = len
42
asm(" movl 12(%ebp),%esi"); // %esi = src
43
asm(" movl 8(%ebp),%edi"); // %edi = dst
44
// Compare src and dest
45
asm(" cmpl %esi,%edi"); // %edi - %esi
46
asm(" jbe move_from_bottom_to_top"); // if(%edi < %esi) jump to move_from_bottom_to_top
48
asm(" addl %ecx,%esi"); // %esi += %ecx (src_ptr += len);
49
asm(" addl %ecx,%edi"); // %edi += %ecx (dst_ptr += len);
50
asm(" decl %esi"); // %esi--; (src_ptr--);
51
asm(" decl %edi"); // %edi--; (dst_ptr--);
52
asm(" std"); // set direction flag (decrement esi and edi in movsb)
53
// Optimization : check for non-odd len (1,3,5,7...)
54
asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
55
asm(" jnc move_two_bytes_top_to_bottom_directly"); // if !carry (CF == 0) skip this move
56
// Move the first byte (non-odd)
57
asm(" movsb %ds:(%esi),%es:(%edi)"); // *dst-- = *src-- if DF else *dst++ = *src++
58
asm("move_two_bytes_top_to_bottom_directly:");
59
asm(" decl %esi"); // %esi--; (src_ptr--);
60
asm(" decl %edi"); // %edi--; (dst_ptr--);
61
asm("move_two_bytes_top_to_bottom:");
62
asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
63
asm(" jnc move_the_rest_top_to_bottom_directly"); // if !carry (CF == 0) skip this move
64
// Move the next two bytes
65
asm(" movsw %ds:(%esi),%es:(%edi)"); // *((word *)dst)-- = *((word)src)-- if DF else *((word *)dst)++ = *((word)src)++
66
asm("move_the_rest_top_to_bottom_directly:");
67
asm(" subl $2,%esi"); // %esi-=2; (src-=2);
68
asm(" subl $2,%edi"); // %edi-=2; (dst-=2);
69
asm(" jmp move_the_rest"); // call last repnz movsl
71
asm("move_from_bottom_to_top:");
72
asm(" cld"); // clear direction flag (increment esi and edi in movsb)
73
// Optimization : check for non-odd len (1,3,5,7...)
74
asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
75
asm(" jnc move_two_bytes"); // if !carry (CF == 0) skip this move
76
// Move the first byte (non-odd)
77
asm(" movsb %ds:(%esi),%es:(%edi)"); // *dst-- = *src-- if DF else *dst++ = *src++
78
// Optimization : pass 2 , check for %2 and %3
79
asm("move_two_bytes:");
80
asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
81
asm(" jnc move_the_rest"); // if !carry (CF == 0) skip this move
82
// Move the next two bytes
83
asm(" movsw %ds:(%esi),%es:(%edi)"); // *((word *)dst)-- = *((word)src)-- if DF else *((word *)dst)++ = *((word)src)++
84
// Main move remaining part
85
asm("move_the_rest:");
86
asm(" repnz; movsl %ds:(%esi),%es:(%edi)"); // loop moving 4 bytes at once (increment or decrement as above)
87
// Restore pointer registers
88
asm(" popl %edi"); // restore %edi
89
asm(" popl %esi"); // restore %esi
90
return dst_ptr; //asm(" movl 8(%ebp),%eax"); <-- gcc will put that (AFTER THE OPTIMISATION PASS!)
95
void *kvi_memmove(void *dst_ptr,const void *src_ptr,int len)
97
__range_valid(dst_ptr);
98
__range_valid(src_ptr);
99
__range_valid(len >= 0);
102
if(dst_ptr > src_ptr){
103
dst = (char *)dst_ptr + len - 1;
104
src = (char *)src_ptr + len - 1;
105
while(len--)*dst-- = *src--;
106
} else { //it is valid even if dst_ptr == src_ptr
107
dst = (char *)dst_ptr;
108
src = (char *)src_ptr;
109
while(len--)*dst++ = *src++;
114
void kvi_fastmove(void *dst_ptr,const void *src_ptr,int len)
116
__range_valid(dst_ptr);
117
__range_valid(src_ptr);
118
__range_valid(len >= 0);
119
register const char *src = (const char *)src_ptr;
120
register char *dst = (char *)dst_ptr;
121
while(len--)*dst++ = *src++;