home *** CD-ROM | disk | FTP | other *** search
- /*
- (C) 1995 AROS - The Amiga Replacement OS
- $Id: copymem.c 1.1 1995/11/14 22:31:07 digulla Exp digulla $
- $Log: copymem.c $
- * Revision 1.1 1995/11/14 22:31:07 digulla
- * Initial revision
- *
- Desc:
- Lang: english
- */
- #include "exec_intern.h"
- #include <aros/machine.h>
-
- /*****************************************************************************
-
- NAME */
- #include <exec/types.h>
- #include <clib/exec_protos.h>
-
- __AROS_LH3I(void, CopyMem,
-
- /* SYNOPSIS */
- __AROS_LA(APTR , source, A0),
- __AROS_LA(APTR , dest, A1),
- __AROS_LA(unsigned long, size, D0),
-
- /* LOCATION */
- struct ExecBase *, SysBase, 104, Exec)
-
- /* FUNCTION
- This is a fast memory to memory copy function. It copies
- arbitrary amounts of memory with arbitrary alignments. The
- routine tries to be smart and uses optimized copies if
- this is possible.
-
- INPUTS
- source - These bytes are copied to dest
- dest - This is the destination for size bytes starting at source
- size - This many bytes will be copied.
-
- RESULT
- None.
-
- NOTES
- The routine can't handle situations where the destination is
- somewhere in source (eg. insert elements in an array).
-
- EXAMPLE
- char ptr1[] = "Some text.";
- char ptr2[32];
-
- CopyMem (ptr1, ptr2, strlen (ptr1));
-
- BUGS
-
- SEE ALSO
- CopyMemQuick()
-
- INTERNALS
-
- HISTORY
- 21-10-95 digulla automatically created from
- include:clib/exec_protos.h
- Written the code.
- 26-10-95 digulla adjusted to new calling scheme
- 17-12-95 digulla Incorporated code by Matthias Fleischner
-
- *****************************************************************************/
- {
- __AROS_FUNC_INIT
- UBYTE *src=(UBYTE *)source,*dst=(UBYTE *)dest;
- ULONG mis,low,high;
-
- /*
- I try to fall back to copying LONGs if possible. To do this I copy
- the misaligned leading bytes of the source first. I use sizeof(LONG)
- instead of LONGALIGN because it is sometimes faster.
- */
- mis = (ULONG)src&(sizeof(LONG)-1);
- if(mis>size)
- mis=size;
- size-=mis;
-
- if(mis)
- do
- *dst++=*src++;
- while(--mis);
-
- /*
- The source has the right alignment now. All I need to do is to
- check if this is true for the destination, too.
- */
- if(!((ULONG)dst&(LONGALIGN-1)))
- {
- /* Yes. I may copy LONGs. */
- LONG *s=(LONG *)src,*d=(LONG *)dst;
- ULONG longs;
-
- /* How many of them? */
- longs=size/sizeof(LONG);
-
- /*
- To minimize the loop overhead I copy more than one (eight) LONG per
- iteration. Therefore I need to split size into size/8 and the rest.
- */
- low =longs&7;
- high=longs/8;
-
- /* Then copy for both parts */
- if(low)
- do
- *d++=*s++;
- while(--low);
-
- if(high)
- do
- {
- *d++=*s++;
- *d++=*s++;
- *d++=*s++;
- *d++=*s++;
- *d++=*s++;
- *d++=*s++;
- *d++=*s++;
- *d++=*s++;
- }while(--high);
-
- /* Get the rest. */
- size&=sizeof(LONG)-1;
- src=(UBYTE *)s;
- dst=(UBYTE *)d;
- }
-
- /* The remaining job can only be done by copying single bytes. */
- low =size&7;
- high=size/8;
-
- /* Copy for both parts */
- if(low)
- do
- *dst++=*src++;
- while(--low);
-
- /*
- Partly unrolled copying loop. The predecrement helps the compiler to
- find the best possible loop. The if is necessary to do this.
- */
- if(high)
- do
- {
- *dst++=*src++;
- *dst++=*src++;
- *dst++=*src++;
- *dst++=*src++;
- *dst++=*src++;
- *dst++=*src++;
- *dst++=*src++;
- *dst++=*src++;
- }while(--high);
- __AROS_FUNC_EXIT
- } /* CopyMem */
-