forked from Minki/linux
f230e80b42
The original 68000 processors cannot copy 16bit or larger quantities from odd addresses. All newer members of the 68k family (including ColdFire) can do this. In the current memcpy implementation after trying to align the destination address to a 16bit boundary if we end up with an odd source address we go off and try to copy multi-byte quantities from it. This will trap on the 68000. The only solution if we end with an odd source address is to byte wise copy the whole memcpy region. We only need to do this if we are supporting original 68000 processors. Signed-off-by: Greg Ungerer <gerg@uclinux.org>
89 lines
1.7 KiB
C
89 lines
1.7 KiB
C
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file COPYING in the main directory of this archive
|
|
* for more details.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/string.h>
|
|
|
|
void *memcpy(void *to, const void *from, size_t n)
|
|
{
|
|
void *xto = to;
|
|
size_t temp, temp1;
|
|
|
|
if (!n)
|
|
return xto;
|
|
if ((long)to & 1) {
|
|
char *cto = to;
|
|
const char *cfrom = from;
|
|
*cto++ = *cfrom++;
|
|
to = cto;
|
|
from = cfrom;
|
|
n--;
|
|
}
|
|
#if defined(CONFIG_M68000)
|
|
if ((long)from & 1) {
|
|
char *cto = to;
|
|
const char *cfrom = from;
|
|
for (; n; n--)
|
|
*cto++ = *cfrom++;
|
|
return xto;
|
|
}
|
|
#endif
|
|
if (n > 2 && (long)to & 2) {
|
|
short *sto = to;
|
|
const short *sfrom = from;
|
|
*sto++ = *sfrom++;
|
|
to = sto;
|
|
from = sfrom;
|
|
n -= 2;
|
|
}
|
|
temp = n >> 2;
|
|
if (temp) {
|
|
long *lto = to;
|
|
const long *lfrom = from;
|
|
#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
|
|
for (; temp; temp--)
|
|
*lto++ = *lfrom++;
|
|
#else
|
|
asm volatile (
|
|
" movel %2,%3\n"
|
|
" andw #7,%3\n"
|
|
" lsrl #3,%2\n"
|
|
" negw %3\n"
|
|
" jmp %%pc@(1f,%3:w:2)\n"
|
|
"4: movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
" movel %0@+,%1@+\n"
|
|
"1: dbra %2,4b\n"
|
|
" clrw %2\n"
|
|
" subql #1,%2\n"
|
|
" jpl 4b"
|
|
: "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1)
|
|
: "0" (lfrom), "1" (lto), "2" (temp));
|
|
#endif
|
|
to = lto;
|
|
from = lfrom;
|
|
}
|
|
if (n & 2) {
|
|
short *sto = to;
|
|
const short *sfrom = from;
|
|
*sto++ = *sfrom++;
|
|
to = sto;
|
|
from = sfrom;
|
|
}
|
|
if (n & 1) {
|
|
char *cto = to;
|
|
const char *cfrom = from;
|
|
*cto = *cfrom;
|
|
}
|
|
return xto;
|
|
}
|
|
EXPORT_SYMBOL(memcpy);
|