~ubuntu-branches/ubuntu/hoary/kvirc/hoary

« back to all changes in this revision

Viewing changes to src/kvicore/kvi_memmove.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Robin Verduijn
  • Date: 2004-12-14 15:32:19 UTC
  • mfrom: (0.2.1 upstream) (1.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20041214153219-fdink3gyp2s20b6g
Tags: 2:2.1.3.1-2
* Change Recommends on xmms to a Suggests.
* Rebuild against KDE 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
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
4
 
//
5
 
//   This file is part of the KVirc irc client distribution
6
 
//   Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
7
 
//
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.
12
 
//
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.
17
 
//
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.
21
 
//
22
 
 
23
 
#include "kvi_debug.h"
24
 
 
25
 
#define _KVI_MEMMOVE_CPP_
26
 
#include "kvi_memmove.h"
27
 
 
28
 
#include "kvi_settings.h"
29
 
 
30
 
#ifdef COMPILE_i386_ASM_CODE
31
 
 
32
 
void *kvi_memmove(void * dst_ptr,const void *src_ptr,int len)
33
 
{
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
40
 
        // Load arguments
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
47
 
        // dst_ptr > src_ptr
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
70
 
        // dst_ptr <= src_ptr
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!)
91
 
}
92
 
 
93
 
#else
94
 
 
95
 
void *kvi_memmove(void *dst_ptr,const void *src_ptr,int len)
96
 
{
97
 
        __range_valid(dst_ptr);
98
 
        __range_valid(src_ptr);
99
 
        __range_valid(len >= 0);
100
 
        register char *dst;
101
 
        register char *src;
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++;
110
 
    }
111
 
    return dst_ptr;
112
 
}
113
 
 
114
 
void kvi_fastmove(void *dst_ptr,const void *src_ptr,int len)
115
 
{
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++;
122
 
}
123
 
 
124
 
#endif