Fix issues with x86 memcpy
authorMathias Krause <minipli@googlemail.com>
Sat, 31 Mar 2012 15:23:53 +0000 (17:23 +0200)
committerPeter Stuge <peter@stuge.se>
Sat, 31 Mar 2012 18:26:20 +0000 (20:26 +0200)
The x86 memcpy() implementation did not mention its implicit output
registers ESI, EDI and ECX which might make this code miscompile when
the compiler uses the value of EDI for the return value *after* the 'rep
movsb' has completed. That would break the API of memcpy as this would
return 'dst+len' instead of 'dst'.

Fix this possible bug by removing the wrong comment and listing all
output registers as such (using dummy stack variables that get optimized
away).

Also the leading 'cld' is superflous as the ABI mandates the direction
flag to be cleared all the time when we're in C (see
<http://gcc.gnu.org/gcc-4.3/changes.html>) and we have no ASM call sites
that might require it to be cleared explicitly (SMM might come to mind,
but it clears the DF itself before passing control to the C part of the
SMI handler).

Last but not least fix the prototype to match the one from <string.h>.

Change-Id: I106422d41180c4ed876078cabb26b45e49f3fa93
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Reviewed-on: http://review.coreboot.org/836
Tested-by: build bot (Jenkins)
Reviewed-by: Peter Stuge <peter@stuge.se>
src/arch/x86/lib/memcpy.c

index de210928a38c85e6edc476cd25a7e52e483dc202..f8607cfc50542acb785e9f2d526607548ba905cf 100644 (file)
@@ -1,13 +1,15 @@
 #include <string.h>
 
-void *memcpy(void *__restrict __dest,
-            __const void *__restrict __src, size_t __n)
+void *memcpy(void *dest, const void *src, size_t n)
 {
-       asm("cld\n"
-           "rep\n"
-           "movsb"
-           :   /* no input (?) */
-           :"S"(__src), "D"(__dest), "c"(__n)
-       );
-       return __dest;
+       unsigned long d0, d1, d2;
+
+       asm volatile(
+               "rep movsb"
+               : "=S"(d0), "=D"(d1), "=c"(d2)
+               : "0"(src), "1"(dest), "2"(n)
+               : "memory"
+               );
+
+       return dest;
 }