1*41956Sbostic /*- 2*41956Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*41956Sbostic * All rights reserved. 4*41956Sbostic * 5*41956Sbostic * This code is derived from software contributed to Berkeley by 6*41956Sbostic * Chris Torek. 7*41956Sbostic * 8*41956Sbostic * %sccs.include.redist.c% 9*41956Sbostic */ 10*41956Sbostic 11*41956Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*41956Sbostic static char sccsid[] = "@(#)memmove.c 5.1 (Berkeley) 05/15/90"; 13*41956Sbostic #endif /* LIBC_SCCS and not lint */ 14*41956Sbostic 15*41956Sbostic #include <string.h> 16*41956Sbostic #include <sys/stdc.h> 17*41956Sbostic 18*41956Sbostic /* 19*41956Sbostic * sizeof(word) MUST BE A POWER OF TWO 20*41956Sbostic * SO THAT wmask BELOW IS ALL ONES 21*41956Sbostic */ 22*41956Sbostic typedef int word; /* "word" used for optimal copy speed */ 23*41956Sbostic 24*41956Sbostic #define wsize sizeof(word) 25*41956Sbostic #define wmask (wsize - 1) 26*41956Sbostic 27*41956Sbostic /* 28*41956Sbostic * Copy a block of memory, handling overlap. 29*41956Sbostic */ 30*41956Sbostic void * 31*41956Sbostic memmove(dst0, src0, length) 32*41956Sbostic void *dst0; 33*41956Sbostic const void *src0; 34*41956Sbostic register size_t length; 35*41956Sbostic { 36*41956Sbostic register char *dst = dst0; 37*41956Sbostic register const char *src = src0; 38*41956Sbostic register size_t t; 39*41956Sbostic 40*41956Sbostic if (length == 0 || dst == src) 41*41956Sbostic return (dst0); /* nothing to do */ 42*41956Sbostic 43*41956Sbostic /* 44*41956Sbostic * Macros: loop-t-times; and loop-t-times, t>0 45*41956Sbostic */ 46*41956Sbostic #if mc68000 /* encourage dbra */ 47*41956Sbostic #define TLOOP(s) TLOOP1(s) 48*41956Sbostic #define TLOOP1(s) while (--t != -1) { s; } 49*41956Sbostic #else 50*41956Sbostic #define TLOOP(s) if (t) TLOOP1(s) 51*41956Sbostic #define TLOOP1(s) do { s; } while (--t) 52*41956Sbostic #endif 53*41956Sbostic 54*41956Sbostic if ((unsigned long)dst < (unsigned long)src) { 55*41956Sbostic /* 56*41956Sbostic * Copy forward. 57*41956Sbostic */ 58*41956Sbostic t = (int)src; /* only need low bits */ 59*41956Sbostic if ((t | (int)dst) & wmask) { 60*41956Sbostic /* 61*41956Sbostic * Try to align operands. This cannot be done 62*41956Sbostic * unless the low bits match. 63*41956Sbostic */ 64*41956Sbostic if ((t ^ (int)dst) & wmask || length < wsize) 65*41956Sbostic t = length; 66*41956Sbostic else 67*41956Sbostic t = wsize - (t & wmask); 68*41956Sbostic length -= t; 69*41956Sbostic TLOOP1(*dst++ = *src++); 70*41956Sbostic } 71*41956Sbostic /* 72*41956Sbostic * Copy whole words, then mop up any trailing bytes. 73*41956Sbostic */ 74*41956Sbostic t = length / wsize; 75*41956Sbostic TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); 76*41956Sbostic t = length & wmask; 77*41956Sbostic TLOOP(*dst++ = *src++); 78*41956Sbostic } else { 79*41956Sbostic /* 80*41956Sbostic * Copy backwards. Otherwise essentially the same. 81*41956Sbostic * Alignment works as before, except that it takes 82*41956Sbostic * (t&wmask) bytes to align, not wsize-(t&wmask). 83*41956Sbostic */ 84*41956Sbostic src += length; 85*41956Sbostic dst += length; 86*41956Sbostic t = (int)src; 87*41956Sbostic if ((t | (int)dst) & wmask) { 88*41956Sbostic if ((t ^ (int)dst) & wmask || length <= wsize) 89*41956Sbostic t = length; 90*41956Sbostic else 91*41956Sbostic t &= wmask; 92*41956Sbostic length -= t; 93*41956Sbostic TLOOP1(*--dst = *--src); 94*41956Sbostic } 95*41956Sbostic t = length / wsize; 96*41956Sbostic TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); 97*41956Sbostic t = length & wmask; 98*41956Sbostic TLOOP(*--dst = *--src); 99*41956Sbostic } 100*41956Sbostic return (dst0); 101*41956Sbostic } 102