summaryrefslogtreecommitdiffstats
path: root/newlib/libc/machine/i386/memmove.S
blob: 102658205a92f533db0d42a7aeb801d8b3aab46b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 * ====================================================
 * Copyright (C) 1998, 2002 by Red Hat Inc. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

	#include "i386mach.h"
	
	.global SYM (memmove)
       SOTYPE_FUNCTION(memmove)

SYM (memmove):

#ifdef __iamcu__
	pushl esi
	pushl edi
	movl eax,edi
	movl edx,esi
	cmp esi,edi
	ja .Lcopy_backward
	je .Lbwd_write_0bytes

	rep movsb

	popl edi
	popl esi
	ret

.Lcopy_backward:
	lea -1(edi,ecx),edi
	lea -1(esi,ecx),esi
	std
	rep movsb
	cld

.Lbwd_write_0bytes:
	popl edi
	popl esi
#else
	pushl ebp
	movl esp,ebp
	pushl esi
	pushl edi
	pushl ebx
	movl 8(ebp),edi
	movl 16(ebp),ecx
	movl 12(ebp),esi

/*  check for destructive overlap (src < dst && dst < src + length) */

	cld
	cmpl edi,esi
	jae  .L2
	leal -1(ecx,esi),ebx
	cmpl ebx,edi
	ja   .L2

/* IF:	 destructive overlap, must copy backwards */

	addl ecx,esi
	addl ecx,edi
	std

#ifndef __OPTIMIZE_SIZE__
	
	cmpl $8,ecx
	jbe .L13
.L18:

/* move trailing bytes in reverse until destination address is long word aligned */
		
	movl edi,edx
	movl ecx,ebx
	andl $3,edx
	jz .L21
	
	movl edx,ecx
	decl esi
	decl edi
	subl ecx,ebx
	rep
	movsb
	
	mov ebx,ecx
	incl esi
	incl edi

.L21:
	
/* move bytes in reverse, a long word at a time */
		
	shrl $2,ecx
	subl $4,esi
	subl $4,edi
	rep
	movsl
	
	addl $4,esi
	addl $4,edi
	movl ebx,ecx
	andl $3,ecx
	
#endif /* !__OPTIMIZE_SIZE__ */

/* handle any remaining bytes not on a long word boundary */			
	
.L13: 
	decl esi
	decl edi

.L15:
	rep
	movsb
	jmp .L5
	.p2align 4,,7

/* ELSE:   no destructive overlap so we copy forwards */
		
.L2:

#ifndef __OPTIMIZE_SIZE__
		
	cmpl $8,ecx
	jbe .L3

/* move any preceding bytes until destination address is long word aligned */
		
	movl edi,edx	
	movl ecx,ebx
	andl $3,edx
	jz .L11
	movl $4,ecx
	subl edx,ecx
	andl $3,ecx
	subl ecx,ebx
	rep
	movsb
	
	mov ebx,ecx

/* move bytes a long word at a time */
		
.L11:
	shrl $2,ecx
	.p2align 2
	rep
	movsl
	
	movl ebx,ecx
	andl $3,ecx
	
#endif /* !__OPTIMIZE_SIZE__ */

/* handle any remaining bytes */
		
.L3:		
	rep
	movsb
.L5:		
	movl 8(ebp),eax
	cld

	leal -12(ebp),esp
	popl ebx
	popl edi
	popl esi
	leave
#endif
	ret