162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/string.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_civoid *memcpy(void *to, const void *from, size_t n) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci void *xto = to; 1362306a36Sopenharmony_ci size_t temp; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci if (!n) 1662306a36Sopenharmony_ci return xto; 1762306a36Sopenharmony_ci if ((long)to & 1) { 1862306a36Sopenharmony_ci char *cto = to; 1962306a36Sopenharmony_ci const char *cfrom = from; 2062306a36Sopenharmony_ci *cto++ = *cfrom++; 2162306a36Sopenharmony_ci to = cto; 2262306a36Sopenharmony_ci from = cfrom; 2362306a36Sopenharmony_ci n--; 2462306a36Sopenharmony_ci } 2562306a36Sopenharmony_ci#if defined(CONFIG_M68000) 2662306a36Sopenharmony_ci if ((long)from & 1) { 2762306a36Sopenharmony_ci char *cto = to; 2862306a36Sopenharmony_ci const char *cfrom = from; 2962306a36Sopenharmony_ci for (; n; n--) 3062306a36Sopenharmony_ci *cto++ = *cfrom++; 3162306a36Sopenharmony_ci return xto; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci#endif 3462306a36Sopenharmony_ci if (n > 2 && (long)to & 2) { 3562306a36Sopenharmony_ci short *sto = to; 3662306a36Sopenharmony_ci const short *sfrom = from; 3762306a36Sopenharmony_ci *sto++ = *sfrom++; 3862306a36Sopenharmony_ci to = sto; 3962306a36Sopenharmony_ci from = sfrom; 4062306a36Sopenharmony_ci n -= 2; 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci temp = n >> 2; 4362306a36Sopenharmony_ci if (temp) { 4462306a36Sopenharmony_ci long *lto = to; 4562306a36Sopenharmony_ci const long *lfrom = from; 4662306a36Sopenharmony_ci#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) 4762306a36Sopenharmony_ci for (; temp; temp--) 4862306a36Sopenharmony_ci *lto++ = *lfrom++; 4962306a36Sopenharmony_ci#else 5062306a36Sopenharmony_ci size_t temp1; 5162306a36Sopenharmony_ci asm volatile ( 5262306a36Sopenharmony_ci " movel %2,%3\n" 5362306a36Sopenharmony_ci " andw #7,%3\n" 5462306a36Sopenharmony_ci " lsrl #3,%2\n" 5562306a36Sopenharmony_ci " negw %3\n" 5662306a36Sopenharmony_ci " jmp %%pc@(1f,%3:w:2)\n" 5762306a36Sopenharmony_ci "4: movel %0@+,%1@+\n" 5862306a36Sopenharmony_ci " movel %0@+,%1@+\n" 5962306a36Sopenharmony_ci " movel %0@+,%1@+\n" 6062306a36Sopenharmony_ci " movel %0@+,%1@+\n" 6162306a36Sopenharmony_ci " movel %0@+,%1@+\n" 6262306a36Sopenharmony_ci " movel %0@+,%1@+\n" 6362306a36Sopenharmony_ci " movel %0@+,%1@+\n" 6462306a36Sopenharmony_ci " movel %0@+,%1@+\n" 6562306a36Sopenharmony_ci "1: dbra %2,4b\n" 6662306a36Sopenharmony_ci " clrw %2\n" 6762306a36Sopenharmony_ci " subql #1,%2\n" 6862306a36Sopenharmony_ci " jpl 4b" 6962306a36Sopenharmony_ci : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1) 7062306a36Sopenharmony_ci : "0" (lfrom), "1" (lto), "2" (temp)); 7162306a36Sopenharmony_ci#endif 7262306a36Sopenharmony_ci to = lto; 7362306a36Sopenharmony_ci from = lfrom; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci if (n & 2) { 7662306a36Sopenharmony_ci short *sto = to; 7762306a36Sopenharmony_ci const short *sfrom = from; 7862306a36Sopenharmony_ci *sto++ = *sfrom++; 7962306a36Sopenharmony_ci to = sto; 8062306a36Sopenharmony_ci from = sfrom; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci if (n & 1) { 8362306a36Sopenharmony_ci char *cto = to; 8462306a36Sopenharmony_ci const char *cfrom = from; 8562306a36Sopenharmony_ci *cto = *cfrom; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci return xto; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ciEXPORT_SYMBOL(memcpy); 90