1/* MN10300 Optimised simple memory to memory copy, with support for overlapping
2 * regions
3 *
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <asm/cache.h>
13
14        .section .text
15        .balign	L1_CACHE_BYTES
16
17###############################################################################
18#
19# void *memmove(void *dst, const void *src, size_t n)
20#
21###############################################################################
22	.globl	memmove
23        .type	memmove,@function
24memmove:
25	# fall back to memcpy if dst < src to work bottom up
26	cmp	d1,d0
27	bcs	memmove_memcpy
28
29	# work top down
30	movm	[d2,d3],(sp)
31	mov	d0,(12,sp)
32	mov	d1,(16,sp)
33	mov	(20,sp),d2			# count
34	add	d0,d2,a0			# dst end
35	add	d1,d2,a1			# src end
36	mov	d0,e3				# the return value
37
38	cmp	+0,d2
39	beq	memmove_done			# return if zero-length copy
40
41	# see if the three parameters are all four-byte aligned
42	or	d0,d1,d3
43	or	d2,d3
44	and	+3,d3
45	bne	memmove_1			# jump if not
46
47	# we want to transfer as much as we can in chunks of 32 bytes
48	add	-4,a1
49	cmp	+31,d2
50	bls	memmove_4_remainder		# 4-byte aligned remainder
51
52	add	-32,d2
53	mov	+32,d3
54
55memmove_4_loop:
56	mov	(a1),d0
57	sub_sub	+4,a1,+4,a0
58	mov	d0,(a0)
59	mov	(a1),d1
60	sub_sub	+4,a1,+4,a0
61	mov	d1,(a0)
62
63	mov	(a1),d0
64	sub_sub	+4,a1,+4,a0
65	mov	d0,(a0)
66	mov	(a1),d1
67	sub_sub	+4,a1,+4,a0
68	mov	d1,(a0)
69
70	mov	(a1),d0
71	sub_sub	+4,a1,+4,a0
72	mov	d0,(a0)
73	mov	(a1),d1
74	sub_sub	+4,a1,+4,a0
75	mov	d1,(a0)
76
77	mov	(a1),d0
78	sub_sub	+4,a1,+4,a0
79	mov	d0,(a0)
80	mov	(a1),d1
81	sub_sub	+4,a1,+4,a0
82	mov	d1,(a0)
83
84	sub	d3,d2
85	bcc	memmove_4_loop
86
87	add	d3,d2
88	beq	memmove_4_no_remainder
89
90memmove_4_remainder:
91	# cut 4-7 words down to 0-3
92	cmp	+16,d2
93	bcs	memmove_4_three_or_fewer_words
94	mov	(a1),d0
95	sub_sub	+4,a1,+4,a0
96	mov	d0,(a0)
97	mov	(a1),d1
98	sub_sub	+4,a1,+4,a0
99	mov	d1,(a0)
100	mov	(a1),e0
101	sub_sub	+4,a1,+4,a0
102	mov	e0,(a0)
103	mov	(a1),e1
104	sub_sub	+4,a1,+4,a0
105	mov	e1,(a0)
106	add	-16,d2
107	beq	memmove_4_no_remainder
108
109	# copy the remaining 1, 2 or 3 words
110memmove_4_three_or_fewer_words:
111	cmp	+8,d2
112	bcs	memmove_4_one_word
113	beq	memmove_4_two_words
114	mov	(a1),d0
115	sub_sub	+4,a1,+4,a0
116	mov	d0,(a0)
117memmove_4_two_words:
118	mov	(a1),d0
119	sub_sub	+4,a1,+4,a0
120	mov	d0,(a0)
121memmove_4_one_word:
122	mov	(a1),d0
123	sub_sub	+4,a1,+4,a0
124	mov	d0,(a0)
125
126memmove_4_no_remainder:
127	# check we copied the correct amount
128	# TODO: REMOVE CHECK
129	sub	e3,a0,d2
130	beq	memmove_done
131	break
132	break
133	break
134
135memmove_done:
136	mov	e3,a0
137	ret	[d2,d3],8
138
139	# handle misaligned copying
140memmove_1:
141	add	-1,a1
142	add	-1,d2
143	mov	+1,d3
144	setlb					# setlb requires the next insns
145						# to occupy exactly 4 bytes
146
147	sub	d3,d2
148	movbu	(a1),d0
149	sub_sub	d3,a1,d3,a0
150	movbu	d0,(a0)
151	lcc
152
153	mov	e3,a0
154	ret	[d2,d3],8
155
156memmove_memcpy:
157	jmp	memcpy
158
159memmove_end:
160	.size	memmove, memmove_end-memmove
161