Module Name:    src
Committed By:   dsl
Date:           Sun Nov 22 17:25:47 UTC 2009

Modified Files:
        src/common/lib/libc/arch/x86_64/string: bcopy.S

Log Message:
Align to the destination buffer.
This probably costs 1 clock (on modern cpus) in the normal case.
But gives a big benefit when the destination is misaligned.
In particular when the source has the same misalignment - although
that may not be a gain on Nehalem!
Fixes PR/35535


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/common/lib/libc/arch/x86_64/string/bcopy.S

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/common/lib/libc/arch/x86_64/string/bcopy.S
diff -u src/common/lib/libc/arch/x86_64/string/bcopy.S:1.3 src/common/lib/libc/arch/x86_64/string/bcopy.S:1.4
--- src/common/lib/libc/arch/x86_64/string/bcopy.S:1.3	Sat Nov 21 19:52:54 2009
+++ src/common/lib/libc/arch/x86_64/string/bcopy.S	Sun Nov 22 17:25:47 2009
@@ -32,14 +32,14 @@
 #include <machine/asm.h>
 
 #if defined(LIBC_SCCS)
-	RCSID("$NetBSD: bcopy.S,v 1.3 2009/11/21 19:52:54 dsl Exp $")
+	RCSID("$NetBSD: bcopy.S,v 1.4 2009/11/22 17:25:47 dsl Exp $")
 #endif
 
 	/*
 	 * (ov)bcopy (src,dst,cnt)
 	 *  [email protected]     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
 	 *
-	 * Hacked about by [email protected]
+	 * Hacked about by [email protected]
 	 */
 
 #ifdef MEMCOPY
@@ -55,7 +55,9 @@
 	movq	%rdx,%rcx
 #if defined(MEMCOPY) || defined(MEMMOVE)
 	movq	%rdi,%rax	/* must return destination address */
+	mov	%rdi,%r11	/* for misaligned check */
 #else
+	mov	%rsi,%r11	/* for misaligned check */
 	xchgq	%rdi,%rsi	/* bcopy() has arg order reversed */
 #endif
 
@@ -68,7 +70,7 @@
 	jz	8f		/* j if less than 8 bytes */
 
 	lea	-8(%rdi,%rdx),%r9	/* target address of last 8 */
-	mov	-8(%rsi,%rdx),%r10	/* get last bytes */
+	mov	-8(%rsi,%rdx),%r10	/* get last word */
 #if !defined(NO_OVERLAP)
 	cmpq	%rdx,%r8	/* overlapping? */
 	jb	10f
@@ -80,16 +82,41 @@
  * if %ecx is more than 76.
  * AMD might do something similar some day.
  */
+	and	$7,%r11		/* destination misaligned ? */
+	jnz	2f
 	rep
 	movsq
-	mov	%r10,(%r9)	/* write last bytes */
+	mov	%r10,(%r9)	/* write last word */
+	ret
+
+/*
+ * Destination misaligned
+ * AMD say it is better to align the destination (not the source).
+ * This will also re-align copies if the source and dest are both
+ * misaligned by the same amount)
+ * (I think Nehalem will use its accelerated copy if the source
+ * and destination have the same alignment.)
+ */
+2:
+	lea	-9(%r11,%rdx),%rcx	/* post re-alignment count */
+	neg	%r11			/* now -1 .. -7 */
+	mov	(%rsi),%rdx		/* get first word */
+	mov	%rdi,%r8		/* target for first word */
+	lea	8(%rsi,%r11),%rsi
+	lea	8(%rdi,%r11),%rdi
+	shr	$3,%rcx
+	rep
+	movsq
+	mov	%rdx,(%r8)		/* write first word */
+	mov	%r10,(%r9)		/* write last word */
 	ret
 
 #if !defined(NO_OVERLAP)
 /* Must copy backwards.
  * Reverse copy is probably easy to code faster than 'rep movds'
- * since that requires (IIRC) an extra clock per iteration.
+ * since that requires (IIRC) an extra clock every 3 iterations (AMD).
  * However I don't suppose anything cares that much!
+ * The big cost is the std/cld pair - reputedly 50+ cycles on Netburst P4.
  * The copy is aligned with the buffer start (more likely to
  * be a multiple of 8 than the end).
  */
@@ -106,7 +133,7 @@
 
 /* Less than 8 bytes to copy, copy by bytes */
 /* Intel Nehalem optimise 'rep movsb' for <= 7 bytes (9-15 clocks).
- * For long transfers it is 50+ !
+ * For longer transfers it is 50+ !
  */
 8:	mov	%rdx,%rcx
 

Reply via email to