|
@@ -1,264 +1,243 @@
|
|
|
-
|
|
|
- Copyright (C) 1994, 1995, 2000 Axis Communications AB.
|
|
|
-
|
|
|
- This file is part of the GNU C Library.
|
|
|
-
|
|
|
- The GNU C Library is free software; you can redistribute it and/or
|
|
|
- modify it under the terms of the GNU Library General Public License as
|
|
|
- published by the Free Software Foundation; either version 2 of the
|
|
|
- License, or (at your option) any later version.
|
|
|
-
|
|
|
- The GNU C Library is distributed in the hope that it will be useful,
|
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
- Library General Public License for more details.
|
|
|
-
|
|
|
- You should have received a copy of the GNU Library General Public
|
|
|
- License along with the GNU C Library; see the file COPYING.LIB. If not,
|
|
|
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
- Boston, MA 02111-1307, USA. */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-#include <features.h>
|
|
|
-
|
|
|
-#ifdef __CONFIG_CRISV32__
|
|
|
+
|
|
|
+ Copyright (C) 1994-2008 Axis Communications.
|
|
|
+ All rights reserved.
|
|
|
+
|
|
|
+ Redistribution and use in source and binary forms, with or without
|
|
|
+ modification, are permitted provided that the following conditions
|
|
|
+ are met:
|
|
|
+
|
|
|
+ 1. Redistributions of source code must retain the above copyright
|
|
|
+ notice, this list of conditions and the following disclaimer.
|
|
|
+
|
|
|
+ 2. Neither the name of Axis Communications nor the names of its
|
|
|
+ contributors may be used to endorse or promote products derived
|
|
|
+ from this software without specific prior written permission.
|
|
|
+
|
|
|
+ THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS
|
|
|
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS
|
|
|
+ COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
|
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
|
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
+ POSSIBILITY OF SUCH DAMAGE. */
|
|
|
+
|
|
|
+
|
|
|
+ result is somewhat depending on gcc generating what we expect rather
|
|
|
+ than what we describe. An assembly file should be used instead. */
|
|
|
+
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+#ifdef __arch_v32
|
|
|
|
|
|
-#define MEMCPY_BLOCK_THRESHOLD (44)
|
|
|
+#define MEMCPY_BY_BLOCK_THRESHOLD (44)
|
|
|
#else
|
|
|
-
|
|
|
-#define MEMCPY_BLOCK_THRESHOLD (44*2)
|
|
|
+
|
|
|
+ modulo 44, so up to the next multiple of 44, we use ordinary code. */
|
|
|
+#define MEMCPY_BY_BLOCK_THRESHOLD (44 * 2)
|
|
|
#endif
|
|
|
|
|
|
-void *memcpy(void *, const void *, unsigned int);
|
|
|
+
|
|
|
+__asm__ (".syntax no_register_prefix");
|
|
|
|
|
|
|
|
|
-void *memcpy(void *pdst,
|
|
|
- const void *psrc,
|
|
|
- unsigned int pn)
|
|
|
+void *
|
|
|
+memcpy(void *pdst, const void *psrc, size_t pn)
|
|
|
{
|
|
|
-
|
|
|
+
|
|
|
Make sure the compiler is able to make something useful of this.
|
|
|
- As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
|
|
|
+ As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
|
|
|
|
|
|
If gcc was allright, it really would need no temporaries, and no
|
|
|
- stack space to save stuff on. */
|
|
|
+ stack space to save stuff on. */
|
|
|
|
|
|
-#ifndef MEMPCPY
|
|
|
register void *return_dst __asm__ ("r10") = pdst;
|
|
|
-#else
|
|
|
-
|
|
|
-# define return_dst dst
|
|
|
-#endif
|
|
|
-
|
|
|
- register char *dst __asm__ ("r13") = pdst;
|
|
|
- register char *src __asm__ ("r11") = (char *) psrc;
|
|
|
+ register unsigned char *dst __asm__ ("r13") = pdst;
|
|
|
+ register unsigned const char *src __asm__ ("r11") = psrc;
|
|
|
register int n __asm__ ("r12") = pn;
|
|
|
|
|
|
-
|
|
|
|
|
|
cycles. I believe it would take as many to check that the
|
|
|
re-alignment was unnecessary. */
|
|
|
if (((unsigned long) dst & 3) != 0
|
|
|
|
|
|
- don't have to check further for overflows. */
|
|
|
+ don't have to check further for overflows. */
|
|
|
&& n >= 3)
|
|
|
{
|
|
|
if ((unsigned long) dst & 1)
|
|
|
- {
|
|
|
- n--;
|
|
|
- *(char*)dst = *(char*)src;
|
|
|
- src++;
|
|
|
- dst++;
|
|
|
- }
|
|
|
+ {
|
|
|
+ n--;
|
|
|
+ *dst = *src;
|
|
|
+ src++;
|
|
|
+ dst++;
|
|
|
+ }
|
|
|
|
|
|
if ((unsigned long) dst & 2)
|
|
|
- {
|
|
|
- n -= 2;
|
|
|
- *(short*)dst = *(short*)src;
|
|
|
- src += 2;
|
|
|
- dst += 2;
|
|
|
- }
|
|
|
+ {
|
|
|
+ n -= 2;
|
|
|
+ *(short *) dst = *(short *) src;
|
|
|
+ src += 2;
|
|
|
+ dst += 2;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- if (n >= MEMCPY_BLOCK_THRESHOLD)
|
|
|
- {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- registers; that will move the saving/restoring of those registers
|
|
|
- to the function prologue/epilogue, and make non-movem sizes
|
|
|
- suboptimal.
|
|
|
-
|
|
|
- This method is not foolproof; it assumes that the "register asm"
|
|
|
- declarations at the beginning of the function really are used
|
|
|
- here (beware: they may be moved to temporary registers).
|
|
|
- This way, we do not have to save/move the registers around into
|
|
|
- temporaries; we can safely use them straight away. */
|
|
|
- __asm__ __volatile__ ("\
|
|
|
- .syntax no_register_prefix \n\
|
|
|
- \n\
|
|
|
- ;; Check that the register asm declaration got right. \n\
|
|
|
- ;; The GCC manual explicitly says TRT will happen. \n\
|
|
|
- .ifnc %0-%1-%2,$r13-$r11-$r12 \n\
|
|
|
- .err \n\
|
|
|
- .endif \n\
|
|
|
- \n\
|
|
|
- ;; Save the registers we'll use in the movem process \n\
|
|
|
- ;; on the stack. \n\
|
|
|
- subq 11*4,sp \n\
|
|
|
- movem r10,[sp] \n\
|
|
|
- \n\
|
|
|
- ;; Now we've got this: \n\
|
|
|
- ;; r11 - src \n\
|
|
|
- ;; r13 - dst \n\
|
|
|
- ;; r12 - n \n\
|
|
|
- \n\
|
|
|
- ;; Update n for the first loop \n\
|
|
|
- subq 44,r12 \n\
|
|
|
-0: \n\
|
|
|
- movem [r11+],r10 \n\
|
|
|
- subq 44,r12 \n\
|
|
|
- bge 0b \n\
|
|
|
- movem r10,[r13+] \n\
|
|
|
- \n\
|
|
|
- addq 44,r12 ;; compensate for last loop underflowing n \n\
|
|
|
- \n\
|
|
|
- ;; Restore registers from stack \n\
|
|
|
- movem [sp+],r10"
|
|
|
-
|
|
|
- : "=r" (dst), "=r" (src), "=r" (n)
|
|
|
- : "0" (dst), "1" (src), "2" (n));
|
|
|
- }
|
|
|
+
|
|
|
+ if (n >= MEMCPY_BY_BLOCK_THRESHOLD)
|
|
|
+ {
|
|
|
+
|
|
|
+ registers; that will move the saving/restoring of those registers
|
|
|
+ to the function prologue/epilogue, and make non-movem sizes
|
|
|
+ suboptimal. */
|
|
|
+ __asm__ __volatile__
|
|
|
+ ("\
|
|
|
+ ;; GCC does promise correct register allocations, but let's \n\
|
|
|
+ ;; make sure it keeps its promises. \n\
|
|
|
+ .ifnc %0-%1-%2,$r13-$r11-$r12 \n\
|
|
|
+ .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\
|
|
|
+ .endif \n\
|
|
|
+ \n\
|
|
|
+ ;; Save the registers we'll use in the movem process \n\
|
|
|
+ ;; on the stack. \n\
|
|
|
+ subq 11*4,sp \n\
|
|
|
+ movem r10,[sp] \n\
|
|
|
+ \n\
|
|
|
+ ;; Now we've got this: \n\
|
|
|
+ ;; r11 - src \n\
|
|
|
+ ;; r13 - dst \n\
|
|
|
+ ;; r12 - n \n\
|
|
|
+ \n\
|
|
|
+ ;; Update n for the first loop. \n\
|
|
|
+ subq 44,r12 \n\
|
|
|
+0: \n\
|
|
|
+"
|
|
|
+#ifdef __arch_common_v10_v32
|
|
|
+
|
|
|
+ assume the branch below has an 8-bit offset. */
|
|
|
+" setf\n"
|
|
|
+#endif
|
|
|
+" movem [r11+],r10 \n\
|
|
|
+ subq 44,r12 \n\
|
|
|
+ bge 0b \n\
|
|
|
+ movem r10,[r13+] \n\
|
|
|
+ \n\
|
|
|
+ ;; Compensate for last loop underflowing n. \n\
|
|
|
+ addq 44,r12 \n\
|
|
|
+ \n\
|
|
|
+ ;; Restore registers from stack. \n\
|
|
|
+ movem [sp+],r10"
|
|
|
+
|
|
|
+
|
|
|
+ : "=r" (dst), "=r" (src), "=r" (n)
|
|
|
+
|
|
|
+
|
|
|
+ : "0" (dst), "1" (src), "2" (n));
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
- in a loop, or we copy as much as possible with 'movem'
|
|
|
- and then the last block (<44 bytes) is copied here.
|
|
|
- This will work since 'movem' will have updated src,dst,n. */
|
|
|
+ while (n >= 16)
|
|
|
+ {
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
|
|
|
- while ( n >= 16 )
|
|
|
- {
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- n -= 16;
|
|
|
- }
|
|
|
+ n -= 16;
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
- * Particularly if you inline code this.
|
|
|
- */
|
|
|
switch (n)
|
|
|
- {
|
|
|
+ {
|
|
|
case 0:
|
|
|
break;
|
|
|
+
|
|
|
case 1:
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 2:
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
+ *(short *) dst = *(short *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 3:
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(short *) dst = *(short *) src; dst += 2; src += 2;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 4:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
+ *(long *) dst = *(long *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 5:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 6:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(short *) dst = *(short *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 7:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(short *) dst = *(short *) src; dst += 2; src += 2;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 8:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 9:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 10:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(short *) dst = *(short *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 11:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(short *) dst = *(short *) src; dst += 2; src += 2;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 12:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 13:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
+
|
|
|
case 14:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(short *) dst = *(short *) src;
|
|
|
break;
|
|
|
+
|
|
|
case 15:
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((long*)dst)++ = *((long*)src)++;
|
|
|
- *((short*)dst)++ = *((short*)src)++;
|
|
|
- *((char*)dst)++ = *((char*)src)++;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(long *) dst = *(long *) src; dst += 4; src += 4;
|
|
|
+ *(short *) dst = *(short *) src; dst += 2; src += 2;
|
|
|
+ *dst = *src;
|
|
|
break;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- return return_dst;
|
|
|
-}
|
|
|
+ return return_dst;
|
|
|
+}
|
|
|
libc_hidden_def(memcpy)
|