summaryrefslogtreecommitdiffstats
path: root/newlib/libc/machine/xscale/strcpy.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2000-11-30 01:57:27 +0000
committerNick Clifton <nickc@redhat.com>2000-11-30 01:57:27 +0000
commit0ffc3b94a0cc452f63eb977633e844dae8539f3a (patch)
treedf045c028255a9399e7a5c489a946561619cac3b /newlib/libc/machine/xscale/strcpy.c
parent09872ef885e9307dc41eb41fdc08bdb1f8ffef7a (diff)
downloadcygnal-0ffc3b94a0cc452f63eb977633e844dae8539f3a.tar.gz
cygnal-0ffc3b94a0cc452f63eb977633e844dae8539f3a.tar.bz2
cygnal-0ffc3b94a0cc452f63eb977633e844dae8539f3a.zip
Add support for Intel's XScale processor
Diffstat (limited to 'newlib/libc/machine/xscale/strcpy.c')
-rw-r--r--newlib/libc/machine/xscale/strcpy.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/newlib/libc/machine/xscale/strcpy.c b/newlib/libc/machine/xscale/strcpy.c
new file mode 100644
index 000000000..707902671
--- /dev/null
+++ b/newlib/libc/machine/xscale/strcpy.c
@@ -0,0 +1,62 @@
+#if defined __thumb__
+
+#include "../../string/strcpy.c"
+
+#else
+
+#include <string.h>
+#include "xscale.h"
+
+char *
+strcpy (char *dest, const char *src)
+{
+ char *dest0 = dest;
+
+ asm (PRELOADSTR ("%0") : : "r" (src));
+
+#ifndef __OPTIMIZE_SIZE__
+ if (((long)src & 3) == ((long)dest & 3))
+ {
+ /* Skip unaligned part. */
+ while ((long)src & 3)
+ {
+ if (! (*dest++ = *src++))
+ return dest0;
+ }
+
+ /* Load two constants:
+ R4 = 0xfefefeff [ == ~(0x80808080 << 1) ]
+ R5 = 0x80808080 */
+
+ asm ("mov r5, #0x80
+ ldr r1, [%1, #0]
+ add r5, r5, #0x8000
+ add r5, r5, r5, lsl #16
+ mvn r4, r5, lsl #1
+
+ add r3, r1, r5
+ bic r3, r3, r1
+ ands r2, r3, r4
+ bne 1f
+0:
+ ldr r3, [%1, #0]
+ ldr r1, [%1, #4]!
+" PRELOADSTR("%1") "
+ str r3, [%0], #4
+ add r2, r1, r4
+ bic r2, r2, r1
+ ands r3, r2, r5
+ beq 0b
+1:"
+ : "=&r" (dest), "=&r" (src)
+ : "0" (dest), "1" (src)
+ : "r1", "r2", "r3", "r4", "r5", "memory", "cc");
+ }
+#endif
+
+ while (*dest++ = *src++)
+ asm (PRELOADSTR ("%0") : : "r" (src));
+ return dest0;
+}
+
+#endif