1 /* memmove implementation for SH4
3 * Copyright (C) 2009 STMicroelectronics Ltd.
5 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
7 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
10 #ifndef __SH_FPU_ANY__
11 #include "../../generic/memmove.c"
16 #define FPSCR_SR (1 << 20)
17 #define STORE_FPSCR(x) __asm__ __volatile__("sts fpscr, %0" : "=r"(x))
18 #define LOAD_FPSCR(x) __asm__ __volatile__("lds %0, fpscr" : : "r"(x))
20 static void fpu_optimised_copy_fwd(void *dest, const void *src, size_t len)
22 char *d = (char *)dest;
23 char *s = (char *)src;
30 /* Align the dest to 4 byte boundary. */
31 while ((unsigned)d & 0x7) {
39 /* check if s is well aligned to use FPU */
40 if (!((unsigned)s1 & 0x7)) {
42 /* Align the dest to cache-line boundary */
43 while ((unsigned)d1 & 0x1c) {
48 /* Use paired single precision load or store mode for
49 * 64-bit tranfering.*/
54 __asm__ __volatile__ ("fmov @%0+,dr0":"+r" (s1));
55 __asm__ __volatile__ ("fmov @%0+,dr2":"+r" (s1));
56 __asm__ __volatile__ ("fmov @%0+,dr4":"+r" (s1));
57 __asm__ __volatile__ ("fmov @%0+,dr6":"+r" (s1));
59 __volatile__ ("fmov dr0,@%0"::"r"
63 __volatile__ ("fmov dr2,@%0"::"r"
67 __volatile__ ("fmov dr4,@%0"::"r"
71 __volatile__ ("fmov dr6,@%0"::"r"
80 /*TODO: other subcases could be covered here?!?*/
82 /* Go to per-byte copy */
90 void *memmove(void *dest, const void *src, size_t len)
92 unsigned long int d = (long int)dest;
93 unsigned long int s = (long int)src;
94 unsigned long int res;
101 * 1) dest and src are not overlap ==> memcpy (BWD/FDW)
102 * 2) dest and src are 100% overlap ==> memcpy (BWD/FDW)
103 * 3) left-to-right overlap ==> Copy from the beginning to the end
104 * 4) right-to-left overlap ==> Copy from the end to the beginning
107 if (res == 0) /* 100% overlap */
108 memcpy(dest, src, len); /* No overlap */
110 memcpy(dest, src, len);
112 if (d > s) /* right-to-left overlap */
113 memcpy(dest, src, len); /* memcpy is BWD */
114 else /* cannot use SH4 memcpy for this case */
115 fpu_optimised_copy_fwd(dest, src, len);
120 libc_hidden_def(memmove)
121 #endif /*__SH_FPU_ANY__ */