xref: /titanic_51/usr/src/lib/libc/i386/gen/memcpy.s (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27	.ident	"%Z%%M%	%I%	%E% SMI"
28
29	.file	"%M%"
30
31#include <sys/asm_linkage.h>
32
33	ANSI_PRAGMA_WEAK(memmove,function)
34	ANSI_PRAGMA_WEAK(memcpy,function)
35
36#include "SYS.h"
37
38	ANSI_PRAGMA_WEAK2(_private_memcpy,memcpy,function)
39
40	ENTRY(memcpy)
41	movl	%edi,%edx	/ save register variables
42	pushl	%esi
43	movl	8(%esp),%edi	/ %edi = dest address
44	movl	12(%esp),%esi	/ %esi = source address
45	movl	16(%esp),%ecx	/ %ecx = length of string
46	movl	%edi,%eax	/ return value from the call
47
48	shrl	$2,%ecx		/ %ecx = number of words to move
49	rep ; smovl		/ move the words
50
51	movl	16(%esp),%ecx	/ %ecx = number of bytes to move
52	andl	$0x3,%ecx	/ %ecx = number of bytes left to move
53	rep ; smovb		/ move the bytes
54
55	popl	%esi		/ restore register variables
56	movl	%edx,%edi
57	ret
58	SET_SIZE(memcpy)
59
60
61	ENTRY(memmove)
62	pushl	%edi		/ save off %edi, %esi and move destination
63	movl	4+12(%esp),%ecx	/ get number of bytes to move
64	pushl	%esi
65	testl	%ecx,%ecx	/ if (n == 0)
66	je	.CleanupReturn	/    return(s);
67	movl	8+ 4(%esp),%edi	/ destination buffer address
68	movl	8+ 8(%esp),%esi	/ source buffer address
69.Common:
70	movl	$3,%eax		/ heavily used constant
71	cmpl	%esi,%edi	/ if (source addr > dest addr)
72	leal	-1(%esi,%ecx),%edx
73	jle	.CopyRight	/
74	cmpl	%edx,%edi
75	jle	.CopyLeft
76.CopyRight:
77	cmpl	$8,%ecx		/    if (size < 8 bytes)
78	jbe	.OneByteCopy	/        goto fast short copy loop
79.FourByteCopy:
80	movl	%ecx,%edx	/    save count
81	movl	%esi,%ecx	/    get source buffer 4 byte aligned
82	andl	%eax,%ecx
83	jz	.SkipAlignRight
84	subl	%ecx,%edx
85	rep;	smovb		/    do the byte part of copy
86.SkipAlignRight:
87	movl	%edx,%ecx
88	shrl	$2,%ecx
89	rep;	smovl		/    do the long word part
90	movl	%edx,%ecx	/    compute bytes left to move
91	andl	%eax,%ecx	/    complete copy of remaining bytes
92	jz	.CleanupReturn
93.OneByteCopy:
94	rep;	smovb		/    do the byte part of copy
95.CleanupReturn:
96	popl	%esi		/  }
97	popl	%edi		/  restore registers
98	movl	4(%esp),%eax	/  set up return value
99.Return:
100	ret			/  return(dba);
101
102.CopyLeft:
103	std				/ reverse direction bit (RtoL)
104	cmpl	$12,%ecx		/ if (size < 12)
105	ja	.BigCopyLeft		/ {
106	movl	%edx,%esi		/     src = src + size - 1
107	leal	-1(%ecx,%edi),%edi	/     dst = dst + size - 1
108	rep;	smovb			/    do the byte copy
109	cld				/    reset direction flag to LtoR
110	popl	%esi			/  }
111	popl	%edi			/  restore registers
112	movl	4(%esp),%eax		/  set up return value
113	ret				/  return(dba);
114.BigCopyLeft:				/ } else {
115	xchgl	%edx,%ecx
116	movl	%ecx,%esi		/ align source w/byte copy
117	leal	-1(%edx,%edi),%edi
118	andl	%eax,%ecx
119	jz	.SkipAlignLeft
120	addl	$1, %ecx		/ we need to insure that future
121	subl	%ecx,%edx		/ copy is done on aligned boundary
122	rep;	smovb
123.SkipAlignLeft:
124	movl	%edx,%ecx
125	subl	%eax,%esi
126	shrl	$2,%ecx			/ do 4 byte copy RtoL
127	subl	%eax,%edi
128	rep;	smovl
129	andl	%eax,%edx		/ do 1 byte copy whats left
130	jz	.CleanupReturnLeft
131	movl	%edx,%ecx
132	addl	%eax,%esi		/ rep; smovl instruction will decrement
133	addl	%eax,%edi		/ %edi, %esi by four after each copy
134					/ adding 3 will restore pointers to byte
135					/ before last double word copied
136					/ which is where they are expected to
137					/ be for the single byte copy code
138	rep;	smovb
139.CleanupReturnLeft:
140	cld				/ reset direction flag to LtoR
141	popl	%esi
142	popl	%edi			/ restore registers
143	movl	4(%esp),%eax		/ set up return value
144	ret				/ return(dba);
145	SET_SIZE(memmove)
146