Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/* SPDX-License-Identifier: GPL-2.0 */
  2
  3#include <linux/export.h>
  4#include <linux/linkage.h>
  5
  6SYM_FUNC_START(memmove)
  7/*
  8 * void *memmove(void *dest_in, const void *src_in, size_t n)
  9 * -mregparm=3 passes these in registers:
 10 * dest_in: %eax
 11 * src_in: %edx
 12 * n: %ecx
 13 * See also: arch/x86/entry/calling.h for description of the calling convention.
 14 *
 15 * n can remain in %ecx, but for `rep movsl`, we'll need dest in %edi and src
 16 * in %esi.
 17 */
 18.set dest_in, %eax
 19.set dest, %edi
 20.set src_in, %edx
 21.set src, %esi
 22.set n, %ecx
 23.set tmp0, %edx
 24.set tmp0w, %dx
 25.set tmp1, %ebx
 26.set tmp1w, %bx
 27.set tmp2, %eax
 28.set tmp3b, %cl
 29
 30/*
 31 * Save all callee-saved registers, because this function is going to clobber
 32 * all of them:
 33 */
 34	pushl	%ebp
 35	movl	%esp, %ebp	// set standard frame pointer
 36
 37	pushl	%ebx
 38	pushl	%edi
 39	pushl	%esi
 40	pushl	%eax		// save 'dest_in' parameter [eax] as the return value
 41
 42	movl src_in, src
 43	movl dest_in, dest
 44
 45	/* Handle more 16 bytes in loop */
 46	cmpl	$0x10, n
 47	jb	.Lmove_16B
 48
 49	/* Decide forward/backward copy mode */
 50	cmpl	dest, src
 51	jb	.Lbackwards_header
 52
 53	/*
 54	 * movs instruction have many startup latency
 55	 * so we handle small size by general register.
 56	 */
 57	cmpl	$680, n
 58	jb	.Ltoo_small_forwards
 59	/* movs instruction is only good for aligned case. */
 60	movl	src, tmp0
 61	xorl	dest, tmp0
 62	andl	$0xff, tmp0
 63	jz	.Lforward_movs
 64.Ltoo_small_forwards:
 65	subl	$0x10, n
 66
 67	/* We gobble 16 bytes forward in each loop. */
 68.Lmove_16B_forwards_loop:
 69	subl	$0x10, n
 70	movl	0*4(src), tmp0
 71	movl	1*4(src), tmp1
 72	movl	tmp0, 0*4(dest)
 73	movl	tmp1, 1*4(dest)
 74	movl	2*4(src), tmp0
 75	movl	3*4(src), tmp1
 76	movl	tmp0, 2*4(dest)
 77	movl	tmp1, 3*4(dest)
 78	leal	0x10(src), src
 79	leal	0x10(dest), dest
 80	jae	.Lmove_16B_forwards_loop
 81	addl	$0x10, n
 82	jmp	.Lmove_16B
 83
 84	/* Handle data forward by movs. */
 85.p2align 4
 86.Lforward_movs:
 87	movl	-4(src, n), tmp0
 88	leal	-4(dest, n), tmp1
 89	shrl	$2, n
 90	rep	movsl
 91	movl	tmp0, (tmp1)
 92	jmp	.Ldone
 93
 94	/* Handle data backward by movs. */
 95.p2align 4
 96.Lbackwards_movs:
 97	movl	(src), tmp0
 98	movl	dest, tmp1
 99	leal	-4(src, n), src
100	leal	-4(dest, n), dest
101	shrl	$2, n
102	std
103	rep	movsl
104	movl	tmp0,(tmp1)
105	cld
106	jmp	.Ldone
107
108	/* Start to prepare for backward copy. */
109.p2align 4
110.Lbackwards_header:
111	cmpl	$680, n
112	jb	.Ltoo_small_backwards
113	movl	src, tmp0
114	xorl	dest, tmp0
115	andl	$0xff, tmp0
116	jz	.Lbackwards_movs
117
118	/* Calculate copy position to tail. */
119.Ltoo_small_backwards:
120	addl	n, src
121	addl	n, dest
122	subl	$0x10, n
123
124	/* We gobble 16 bytes backward in each loop. */
125.Lmove_16B_backwards_loop:
126	subl	$0x10, n
127
128	movl	-1*4(src), tmp0
129	movl	-2*4(src), tmp1
130	movl	tmp0, -1*4(dest)
131	movl	tmp1, -2*4(dest)
132	movl	-3*4(src), tmp0
133	movl	-4*4(src), tmp1
134	movl	tmp0, -3*4(dest)
135	movl	tmp1, -4*4(dest)
136	leal	-0x10(src), src
137	leal	-0x10(dest), dest
138	jae	.Lmove_16B_backwards_loop
139	/* Calculate copy position to head. */
140	addl	$0x10, n
141	subl	n, src
142	subl	n, dest
143
144	/* Move data from 8 bytes to 15 bytes. */
145.p2align 4
146.Lmove_16B:
147	cmpl	$8, n
148	jb	.Lmove_8B
149	movl	0*4(src), tmp0
150	movl	1*4(src), tmp1
151	movl	-2*4(src, n), tmp2
152	movl	-1*4(src, n), src
153
154	movl	tmp0, 0*4(dest)
155	movl	tmp1, 1*4(dest)
156	movl	tmp2, -2*4(dest, n)
157	movl	src, -1*4(dest, n)
158	jmp	.Ldone
159
160	/* Move data from 4 bytes to 7 bytes. */
161.p2align 4
162.Lmove_8B:
163	cmpl	$4, n
164	jb	.Lmove_4B
165	movl	0*4(src), tmp0
166	movl	-1*4(src, n), tmp1
167	movl	tmp0, 0*4(dest)
168	movl	tmp1, -1*4(dest, n)
169	jmp	.Ldone
170
171	/* Move data from 2 bytes to 3 bytes. */
172.p2align 4
173.Lmove_4B:
174	cmpl	$2, n
175	jb	.Lmove_1B
176	movw	0*2(src), tmp0w
177	movw	-1*2(src, n), tmp1w
178	movw	tmp0w, 0*2(dest)
179	movw	tmp1w, -1*2(dest, n)
180	jmp	.Ldone
181
182	/* Move data for 1 byte. */
183.p2align 4
184.Lmove_1B:
185	cmpl	$1, n
186	jb	.Ldone
187	movb	(src), tmp3b
188	movb	tmp3b, (dest)
189.p2align 4
190.Ldone:
191	popl	dest_in	// restore 'dest_in' [eax] as the return value
192	/* Restore all callee-saved registers: */
193	popl	%esi
194	popl	%edi
195	popl	%ebx
196	popl	%ebp
197
198	RET
199SYM_FUNC_END(memmove)
200EXPORT_SYMBOL(memmove)