diff options
Diffstat (limited to 'newlib/libc/machine/riscv/strcpy.c')
-rw-r--r-- | newlib/libc/machine/riscv/strcpy.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/newlib/libc/machine/riscv/strcpy.c b/newlib/libc/machine/riscv/strcpy.c new file mode 100644 index 000000000..905a9b8df --- /dev/null +++ b/newlib/libc/machine/riscv/strcpy.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2017 SiFive Inc. All rights reserved. + + This copyrighted material is made available to anyone wishing to use, + modify, copy, or redistribute it subject to the terms and conditions + of the BSD License. This program is distributed in the hope that + it will be useful, but WITHOUT ANY WARRANTY expressed or implied, + including the implied warranties of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. A copy of this license is available at + http://www.opensource.org/licenses. +*/ + +#include <string.h> +#include <stdint.h> + +char *strcpy(char *dst, const char *src) +{ + char *dst0 = dst; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + int misaligned = ((uintptr_t)dst | (uintptr_t)src) & (sizeof (long) - 1); + if (__builtin_expect(!misaligned, 1)) + { + long *ldst = (long *)dst; + const long *lsrc = (const long *)src; + + while (!__libc_detect_null(*lsrc)) + *ldst++ = *lsrc++; + + dst = (char *)ldst; + src = (const char *)lsrc; + + char c0 = src[0]; + char c1 = src[1]; + char c2 = src[2]; + if (!(*dst++ = c0)) return dst0; + if (!(*dst++ = c1)) return dst0; + char c3 = src[3]; + if (!(*dst++ = c2)) return dst0; + if (sizeof (long) == 4) goto out; + char c4 = src[4]; + if (!(*dst++ = c3)) return dst0; + char c5 = src[5]; + if (!(*dst++ = c4)) return dst0; + char c6 = src[6]; + if (!(*dst++ = c5)) return dst0; + if (!(*dst++ = c6)) return dst0; + +out: + *dst++ = 0; + return dst0; + } +#endif /* not PREFER_SIZE_OVER_SPEED */ + + char ch; + do + { + ch = *src; + src++; + dst++; + *(dst - 1) = ch; + } while (ch); + + return dst0; +} |