home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
dbmalloc-1.14-src.tgz
/
tar.out
/
contrib
/
dbmalloc
/
datamc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
6KB
|
348 lines
/*
* (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
*
* This software may be distributed freely as long as the following conditions
* are met:
* * the distribution, or any derivative thereof, may not be
* included as part of a commercial product
* * full source code is provided including this copyright
* * there is no charge for the software itself (there may be
* a minimal charge for the copying or distribution effort)
* * this copyright notice is not modified or removed from any
* source file
*/
/*
* datamc.c - this module contains functions designed to efficiently
* copy memory areas in a portable fasion
*
* The configure script will usually override this module with a copy
* of the system suplied memcpy() utility if it can figure out how to
* convert the module name to DataMS.
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: datamc.c,v 1.7 1992/08/22 16:27:13 cpcahil Exp $";
#endif
#include <stdio.h>
#include "mallocin.h"
typedef int word;
#define wordmask (sizeof(word)-1)
#ifndef DONT_USE_ASM
#ifdef i386
#define ASM_MEMCPY 1
/*
* DataMemcpy() - asm version of memcpy for use on 386 architecture systems.
* This is much faster than performing the operation directly.
* Note that the operation is performed by the use of word
* moves followed by byte moves and it doesn't matter that
* the word moves are not on a word aligned offset.
*
* This function differs from the system memcpy in that it correcly handles
* overlapping memory regions. This is a requirement here because this is
* the same function that is called from memmove, memcpy, and bcopy.
*/
/*
* DataMemcpy(tgt,src,len)
*/
asm(" .text");
asm(" .align 4");
#ifdef USE_UNDERSCORE
asm(" .globl _DataMC");
asm("_DataMC:");
#else
asm(" .globl DataMC");
asm("DataMC:");
#endif
asm(" pushl %edi");
asm(" pushl %esi");
asm(" pushl %ebx");
/*
* get tgt -> edi
* src -> esi
* len -> ecx
*/
asm(" movl 16(%esp),%edi");
asm(" movl 20(%esp),%esi");
asm(" movl 24(%esp),%ecx");
/*
* compare target to src
*/
asm(" cmpl %edi,%esi");
/*
* if( tgt == src ) nothing to do, so return
*/
asm(" je .memdone");
/*
* if( (tgt > src)
*/
asm(" jg .movenorm");
/*
* && tgt < (src + len)
*/
asm(" movl %esi,%eax");
asm(" addl %ecx,%eax");
asm(" cmpl %edi,%eax");
asm(" jl .movenorm");
/*
* {
*/
/*
* move the pointers to the end of the data area to be
* moved and set the direction flag so that
*/
/*
* && ( len >= 4 ) )
*/
asm(" cmpl $4,%ecx");
asm(" jl .moveshort");
/*
* {
*/
asm(" addl %ecx,%edi");
asm(" subl $4,%edi");
asm(" addl %ecx,%esi");
asm(" subl $4,%esi");
asm(" xor %ebx,%ebx");
asm(" jmp .moveback");
/*
* }
* else
* {
*/
asm(" addl %ecx,%edi");
asm(" addl %ecx,%esi");
asm(".moveshort:");
asm(" movl $1,%ebx");
/*
* }
*/
asm(".moveback:");
asm(" std");
asm(" jmp .movedata");
/*
* }
* else
* {
*/
asm(".movenorm:");
asm(" mov $1,%ebx");
/*
* }
*/
/*
* now go move the data
*/
asm(".movedata:");
asm(" movl %edi,%eax");
asm(" movl %ecx,%edx");
asm(" shrl $02,%ecx");
#ifdef USE_REPE
asm(" repe");
#else
asm(" repz");
#endif
asm(" movsl ");
/*
* if we were performing a negative move, adjust the pointer
* so that it points to the previous byte (right now it points
* to the previous word
*/
asm(" cmpl $0,%ebx");
asm(" jnz .movedata2");
/*
* {
*/
asm(" addl $3,%edi");
asm(" addl $3,%esi");
/*
* }
*/
asm(".movedata2:");
asm(" movl %edx,%ecx");
asm(" andl $03,%ecx");
#ifdef USE_REPE
asm(" repe");
#else
asm(" repz");
#endif
asm(" movsb ");
asm(" cld");
/*
* return
*/
asm(".memdone:");
asm(" popl %ebx");
asm(" popl %esi");
asm(" popl %edi");
asm(" ret");
#endif /* i386 */
#endif /* DONT_USE_ASM */
#ifndef ASM_MEMCPY
void
DataMC(ptr1,ptr2,len)
MEMDATA * ptr1;
CONST MEMDATA * ptr2;
MEMSIZE len;
{
register MEMSIZE i;
register char * myptr1;
register CONST char * myptr2;
if( len <= 0 )
{
return;
}
myptr1 = ptr1;
myptr2 = ptr2;
/*
* while the normal memcpy does not guarrantee that it will
* handle overlapping memory correctly, we will try...
*/
if( (myptr1 > myptr2) && (myptr1 < (myptr2+len)) )
{
myptr1 += len;
myptr2 += len;
if( (((long)myptr1)&wordmask) == (((long)myptr2)&wordmask))
{
/*
* if the pointer is not on an even word boundary
*/
if( (i = (((long)myptr1) & wordmask)) != 0 )
{
/*
* process an extra byte at the word boundary
* itself
*/
while( (i-- > 0) && (len > 0) )
{
*(--myptr1) = *(--myptr2);
len--;
}
}
/*
* convert remaining number of bytes to number of words
*/
i = len >> (sizeof(word)/2);
/*
* and copy them
*/
while( i-- > 0 )
{
myptr1 -= sizeof(word);
myptr2 -= sizeof(word);
*(word *)myptr1 = *(CONST word *)myptr2;
}
/*
* and now handle any trailing bytes
*/
if( (i = (len & wordmask)) != 0 )
{
while( i-- > 0 )
{
*(--myptr1) = *(--myptr2);
}
}
}
/*
* else we have to do it on a byte by byte basis
*/
else
{
while( len-- > 0 )
{
*(--myptr1) = *(--myptr2);
}
}
}
else
{
/*
* if we can make this move on even boundaries
*/
if( (((long)myptr1)&wordmask) == (((long)myptr2)&wordmask) )
{
/*
* if the pointer is not on an even word boundary
*/
if( (i = (((long)myptr1) & wordmask)) != 0 )
{
while( (i++ < sizeof(word)) && (len > 0) )
{
*(myptr1++) = *(myptr2++);
len--;
}
}
/*
* convert remaining number of bytes to number of words
*/
i = len >> (sizeof(word)/2);
/*
* and copy them
*/
while( i-- > 0 )
{
*(word *)myptr1 = *(CONST word *)myptr2;
myptr1 += sizeof(word);
myptr2 += sizeof(word);
}
/*
* and now handle any trailing bytes
*/
if( (i = (len & wordmask)) != 0 )
{
while( i-- > 0 )
{
*(myptr1++) = *(myptr2++);
}
}
}
/*
* else we have to handle it a byte at a time
*/
else
{
while( len-- > 0 )
{
*(myptr1++) = *(myptr2++);
}
}
}
return;
} /* DataMC(... */
#endif /* ASM_MEMCPY */