/*
    (C) 1995 AROS - The Amiga Replacement OS
    $Id: copymemquick.c 1.1 1995/11/14 22:31:07 digulla Exp digulla $
    $Log: copymemquick.c $
 * Revision 1.1  1995/11/14  22:31:07  digulla
 * Initial revision
 *
    Desc:
    Lang: english
*/
#include "exec_intern.h"

/*****************************************************************************

    NAME */
	#include <clib/exec_protos.h>

	__AROS_LH3I(void, CopyMemQuick,

/*  SYNOPSIS */
	__AROS_LA(APTR         , source, A0),
	__AROS_LA(APTR         , dest, A1),
	__AROS_LA(unsigned long, size, D0),

/*  LOCATION */
	struct ExecBase *, SysBase, 105, Exec)

/*  FUNCTION
	This routine copies areas of memory very fast. To achieve this
	speed, the user of the function has to take care that the
	arguments match certain requirements. Both pointers (source
	and dest) must be longword aligned ("unsigned long") and the
	size must be divisible by "sizeof (unsigned long)". No checks
	are performed by the function to check these requirements but
	on some hardwares, the system will crash if the requirements
	are not met.

    INPUTS
	source - Pointer to the source area. Must be longword aligned.
	dest - Pointer to the destination area. Must be longword aligned.
	size - The number of bytes to copy. This number must by
		divisible by "sizeof (unsigned long)".

    RESULT
	None.

    NOTES
	The routine can't handle situations where the destination is
	somewhere in source (eg. insert elements in an array).

    EXAMPLE
	long ptr1[] = { 'Hell', 'o Wo', 'rld\0' };
	long ptr2[3];

	CopyMemQuick (ptr1, ptr2, sizeof (ptr1));

    BUGS

    SEE ALSO
	CopyMem()

    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
    ULONG low,high;
    ULONG * dptr, * sptr;

    /* Calculate number of ULONGs to copy */
    size/=sizeof(ULONG);
    sptr = (ULONG *)source;
    dptr = (ULONG *)dest;

    /*
	To minimize the loop overhead I copy more than one (eight) ULONG per
	iteration. Therefore I need to split size into size/8 and the rest.
    */
    low =size&7;
    high=size>>3;

    /* Then copy for both parts */
    if(low)
	do
	    *dptr++=*sptr++;
	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
	{
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	    *dptr++=*sptr++;
	}while(--high);
    __AROS_FUNC_EXIT
} /* CopyMemQuick */
