xref: /titanic_50/usr/src/lib/libc/i386/gen/memcpy.s (revision 46b592853d0f4f11781b6b0a7533f267c6aee132)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
58cd45542Sraf * Common Development and Distribution License (the "License").
68cd45542Sraf * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
218cd45542Sraf
227c478bd9Sstevel@tonic-gate/*
23*46b59285SSudheer A * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
279a70fc3bSMark J. Nelson	.file	"memcpy.s"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK(memmove,function)
327c478bd9Sstevel@tonic-gate	ANSI_PRAGMA_WEAK(memcpy,function)
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate#include "SYS.h"
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate	ENTRY(memcpy)
377c478bd9Sstevel@tonic-gate	movl	%edi,%edx	/ save register variables
387c478bd9Sstevel@tonic-gate	pushl	%esi
397c478bd9Sstevel@tonic-gate	movl	8(%esp),%edi	/ %edi = dest address
407c478bd9Sstevel@tonic-gate	movl	12(%esp),%esi	/ %esi = source address
417c478bd9Sstevel@tonic-gate	movl	16(%esp),%ecx	/ %ecx = length of string
427c478bd9Sstevel@tonic-gate	movl	%edi,%eax	/ return value from the call
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate	shrl	$2,%ecx		/ %ecx = number of words to move
457c478bd9Sstevel@tonic-gate	rep ; smovl		/ move the words
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate	movl	16(%esp),%ecx	/ %ecx = number of bytes to move
487c478bd9Sstevel@tonic-gate	andl	$0x3,%ecx	/ %ecx = number of bytes left to move
497c478bd9Sstevel@tonic-gate	rep ; smovb		/ move the bytes
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate	popl	%esi		/ restore register variables
527c478bd9Sstevel@tonic-gate	movl	%edx,%edi
537c478bd9Sstevel@tonic-gate	ret
547c478bd9Sstevel@tonic-gate	SET_SIZE(memcpy)
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate	ENTRY(memmove)
587c478bd9Sstevel@tonic-gate	pushl	%edi		/ save off %edi, %esi and move destination
597c478bd9Sstevel@tonic-gate	movl	4+12(%esp),%ecx	/ get number of bytes to move
607c478bd9Sstevel@tonic-gate	pushl	%esi
617c478bd9Sstevel@tonic-gate	testl	%ecx,%ecx	/ if (n == 0)
627c478bd9Sstevel@tonic-gate	je	.CleanupReturn	/    return(s);
637c478bd9Sstevel@tonic-gate	movl	8+ 4(%esp),%edi	/ destination buffer address
647c478bd9Sstevel@tonic-gate	movl	8+ 8(%esp),%esi	/ source buffer address
657c478bd9Sstevel@tonic-gate.Common:
667c478bd9Sstevel@tonic-gate	movl	$3,%eax		/ heavily used constant
677c478bd9Sstevel@tonic-gate	cmpl	%esi,%edi	/ if (source addr > dest addr)
687c478bd9Sstevel@tonic-gate	leal	-1(%esi,%ecx),%edx
69*46b59285SSudheer A	jbe	.CopyRight	/
707c478bd9Sstevel@tonic-gate	cmpl	%edx,%edi
71*46b59285SSudheer A	jbe	.CopyLeft
727c478bd9Sstevel@tonic-gate.CopyRight:
737c478bd9Sstevel@tonic-gate	cmpl	$8,%ecx		/    if (size < 8 bytes)
747c478bd9Sstevel@tonic-gate	jbe	.OneByteCopy	/        goto fast short copy loop
757c478bd9Sstevel@tonic-gate.FourByteCopy:
767c478bd9Sstevel@tonic-gate	movl	%ecx,%edx	/    save count
777c478bd9Sstevel@tonic-gate	movl	%esi,%ecx	/    get source buffer 4 byte aligned
787c478bd9Sstevel@tonic-gate	andl	%eax,%ecx
797c478bd9Sstevel@tonic-gate	jz	.SkipAlignRight
807c478bd9Sstevel@tonic-gate	subl	%ecx,%edx
817c478bd9Sstevel@tonic-gate	rep;	smovb		/    do the byte part of copy
827c478bd9Sstevel@tonic-gate.SkipAlignRight:
837c478bd9Sstevel@tonic-gate	movl	%edx,%ecx
847c478bd9Sstevel@tonic-gate	shrl	$2,%ecx
857c478bd9Sstevel@tonic-gate	rep;	smovl		/    do the long word part
867c478bd9Sstevel@tonic-gate	movl	%edx,%ecx	/    compute bytes left to move
877c478bd9Sstevel@tonic-gate	andl	%eax,%ecx	/    complete copy of remaining bytes
887c478bd9Sstevel@tonic-gate	jz	.CleanupReturn
897c478bd9Sstevel@tonic-gate.OneByteCopy:
907c478bd9Sstevel@tonic-gate	rep;	smovb		/    do the byte part of copy
917c478bd9Sstevel@tonic-gate.CleanupReturn:
927c478bd9Sstevel@tonic-gate	popl	%esi		/  }
937c478bd9Sstevel@tonic-gate	popl	%edi		/  restore registers
947c478bd9Sstevel@tonic-gate	movl	4(%esp),%eax	/  set up return value
957c478bd9Sstevel@tonic-gate.Return:
967c478bd9Sstevel@tonic-gate	ret			/  return(dba);
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate.CopyLeft:
997c478bd9Sstevel@tonic-gate	std				/ reverse direction bit (RtoL)
1007c478bd9Sstevel@tonic-gate	cmpl	$12,%ecx		/ if (size < 12)
1017c478bd9Sstevel@tonic-gate	ja	.BigCopyLeft		/ {
1027c478bd9Sstevel@tonic-gate	movl	%edx,%esi		/     src = src + size - 1
1037c478bd9Sstevel@tonic-gate	leal	-1(%ecx,%edi),%edi	/     dst = dst + size - 1
1047c478bd9Sstevel@tonic-gate	rep;	smovb			/    do the byte copy
1057c478bd9Sstevel@tonic-gate	cld				/    reset direction flag to LtoR
1067c478bd9Sstevel@tonic-gate	popl	%esi			/  }
1077c478bd9Sstevel@tonic-gate	popl	%edi			/  restore registers
1087c478bd9Sstevel@tonic-gate	movl	4(%esp),%eax		/  set up return value
1097c478bd9Sstevel@tonic-gate	ret				/  return(dba);
1107c478bd9Sstevel@tonic-gate.BigCopyLeft:				/ } else {
1117c478bd9Sstevel@tonic-gate	xchgl	%edx,%ecx
1127c478bd9Sstevel@tonic-gate	movl	%ecx,%esi		/ align source w/byte copy
1137c478bd9Sstevel@tonic-gate	leal	-1(%edx,%edi),%edi
1147c478bd9Sstevel@tonic-gate	andl	%eax,%ecx
1157c478bd9Sstevel@tonic-gate	jz	.SkipAlignLeft
1167c478bd9Sstevel@tonic-gate	addl	$1, %ecx		/ we need to insure that future
1177c478bd9Sstevel@tonic-gate	subl	%ecx,%edx		/ copy is done on aligned boundary
1187c478bd9Sstevel@tonic-gate	rep;	smovb
1197c478bd9Sstevel@tonic-gate.SkipAlignLeft:
1207c478bd9Sstevel@tonic-gate	movl	%edx,%ecx
1217c478bd9Sstevel@tonic-gate	subl	%eax,%esi
1227c478bd9Sstevel@tonic-gate	shrl	$2,%ecx			/ do 4 byte copy RtoL
1237c478bd9Sstevel@tonic-gate	subl	%eax,%edi
1247c478bd9Sstevel@tonic-gate	rep;	smovl
1257c478bd9Sstevel@tonic-gate	andl	%eax,%edx		/ do 1 byte copy whats left
1267c478bd9Sstevel@tonic-gate	jz	.CleanupReturnLeft
1277c478bd9Sstevel@tonic-gate	movl	%edx,%ecx
1287c478bd9Sstevel@tonic-gate	addl	%eax,%esi		/ rep; smovl instruction will decrement
1297c478bd9Sstevel@tonic-gate	addl	%eax,%edi		/ %edi, %esi by four after each copy
1307c478bd9Sstevel@tonic-gate					/ adding 3 will restore pointers to byte
1317c478bd9Sstevel@tonic-gate					/ before last double word copied
1327c478bd9Sstevel@tonic-gate					/ which is where they are expected to
1337c478bd9Sstevel@tonic-gate					/ be for the single byte copy code
1347c478bd9Sstevel@tonic-gate	rep;	smovb
1357c478bd9Sstevel@tonic-gate.CleanupReturnLeft:
1367c478bd9Sstevel@tonic-gate	cld				/ reset direction flag to LtoR
1377c478bd9Sstevel@tonic-gate	popl	%esi
1387c478bd9Sstevel@tonic-gate	popl	%edi			/ restore registers
1397c478bd9Sstevel@tonic-gate	movl	4(%esp),%eax		/ set up return value
1407c478bd9Sstevel@tonic-gate	ret				/ return(dba);
1417c478bd9Sstevel@tonic-gate	SET_SIZE(memmove)
142