xref: /linux/arch/csky/abiv2/memmove.S (revision 3dfc242f11d792535db774613c6fd1df565c2137)
1c5af58b7SGuo Ren/* SPDX-License-Identifier: GPL-2.0 */
2c5af58b7SGuo Ren// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3c5af58b7SGuo Ren
4c5af58b7SGuo Ren#include <linux/linkage.h>
5c5af58b7SGuo Ren#include "sysdep.h"
6c5af58b7SGuo Ren
7c5af58b7SGuo Ren	.weak memmove
8c5af58b7SGuo RenENTRY(__memmove)
9c5af58b7SGuo RenENTRY(memmove)
10c5af58b7SGuo Ren	subu	r3, r0, r1
11c5af58b7SGuo Ren	cmphs	r3, r2
12c5af58b7SGuo Ren	bt	memcpy
13c5af58b7SGuo Ren
14c5af58b7SGuo Ren	mov	r12, r0
15c5af58b7SGuo Ren	addu	r0, r0, r2
16c5af58b7SGuo Ren	addu	r1, r1, r2
17c5af58b7SGuo Ren
18c5af58b7SGuo Ren	/* Test if len less than 4 bytes.  */
19c5af58b7SGuo Ren	cmplti	r2, 4
20c5af58b7SGuo Ren	bt	.L_copy_by_byte
21c5af58b7SGuo Ren
22c5af58b7SGuo Ren	andi	r13, r0, 3
23c5af58b7SGuo Ren	/* Test if dest is not 4 bytes aligned.  */
24c5af58b7SGuo Ren	bnez	r13, .L_dest_not_aligned
25c5af58b7SGuo Ren	/* Hardware can handle unaligned access directly.  */
26c5af58b7SGuo Ren.L_dest_aligned:
27c5af58b7SGuo Ren	/* If dest is aligned, then copy.  */
28c5af58b7SGuo Ren	zext	r18, r2, 31, 4
29c5af58b7SGuo Ren	/* Test if len less than 16 bytes.  */
30c5af58b7SGuo Ren	bez	r18, .L_len_less_16bytes
31c5af58b7SGuo Ren	movi	r19, 0
32c5af58b7SGuo Ren
33c5af58b7SGuo Ren	/* len > 16 bytes */
34c5af58b7SGuo Ren	LABLE_ALIGN
35c5af58b7SGuo Ren.L_len_larger_16bytes:
36c5af58b7SGuo Ren	subi	r1, 16
37c5af58b7SGuo Ren	subi	r0, 16
38*3dfc242fSGuo Ren#if defined(__CK860__)
39c5af58b7SGuo Ren	ldw	r3, (r1, 12)
40c5af58b7SGuo Ren	stw	r3, (r0, 12)
41c5af58b7SGuo Ren	ldw	r3, (r1, 8)
42c5af58b7SGuo Ren	stw	r3, (r0, 8)
43c5af58b7SGuo Ren	ldw	r3, (r1, 4)
44c5af58b7SGuo Ren	stw	r3, (r0, 4)
45c5af58b7SGuo Ren	ldw	r3, (r1, 0)
46c5af58b7SGuo Ren	stw	r3, (r0, 0)
47c5af58b7SGuo Ren#else
48c5af58b7SGuo Ren	ldw	r20, (r1, 0)
49c5af58b7SGuo Ren	ldw	r21, (r1, 4)
50c5af58b7SGuo Ren	ldw	r22, (r1, 8)
51c5af58b7SGuo Ren	ldw	r23, (r1, 12)
52c5af58b7SGuo Ren	stw	r20, (r0, 0)
53c5af58b7SGuo Ren	stw	r21, (r0, 4)
54c5af58b7SGuo Ren	stw	r22, (r0, 8)
55c5af58b7SGuo Ren	stw	r23, (r0, 12)
56c5af58b7SGuo Ren	PRE_BNEZAD (r18)
57c5af58b7SGuo Ren#endif
58c5af58b7SGuo Ren	BNEZAD (r18, .L_len_larger_16bytes)
59c5af58b7SGuo Ren
60c5af58b7SGuo Ren.L_len_less_16bytes:
61c5af58b7SGuo Ren	zext	r18, r2, 3, 2
62c5af58b7SGuo Ren	bez	r18, .L_copy_by_byte
63c5af58b7SGuo Ren.L_len_less_16bytes_loop:
64c5af58b7SGuo Ren	subi	r1, 4
65c5af58b7SGuo Ren	subi	r0, 4
66c5af58b7SGuo Ren	ldw	r3, (r1, 0)
67c5af58b7SGuo Ren	PRE_BNEZAD (r18)
68c5af58b7SGuo Ren	stw	r3, (r0, 0)
69c5af58b7SGuo Ren	BNEZAD (r18, .L_len_less_16bytes_loop)
70c5af58b7SGuo Ren
71c5af58b7SGuo Ren	/* Test if len less than 4 bytes.  */
72c5af58b7SGuo Ren.L_copy_by_byte:
73c5af58b7SGuo Ren	zext	r18, r2, 1, 0
74c5af58b7SGuo Ren	bez	r18, .L_return
75c5af58b7SGuo Ren.L_copy_by_byte_loop:
76c5af58b7SGuo Ren	subi	r1, 1
77c5af58b7SGuo Ren	subi	r0, 1
78c5af58b7SGuo Ren	ldb	r3, (r1, 0)
79c5af58b7SGuo Ren	PRE_BNEZAD (r18)
80c5af58b7SGuo Ren	stb	r3, (r0, 0)
81c5af58b7SGuo Ren	BNEZAD (r18, .L_copy_by_byte_loop)
82c5af58b7SGuo Ren
83c5af58b7SGuo Ren.L_return:
84c5af58b7SGuo Ren	mov	r0, r12
85c5af58b7SGuo Ren	rts
86c5af58b7SGuo Ren
87c5af58b7SGuo Ren	/* If dest is not aligned, just copy some bytes makes the dest
88c5af58b7SGuo Ren	   align.  */
89c5af58b7SGuo Ren.L_dest_not_aligned:
90c5af58b7SGuo Ren	sub	r2, r13
91c5af58b7SGuo Ren.L_dest_not_aligned_loop:
92c5af58b7SGuo Ren	subi	r1, 1
93c5af58b7SGuo Ren	subi	r0, 1
94c5af58b7SGuo Ren	/* Makes the dest align.  */
95c5af58b7SGuo Ren	ldb	r3, (r1, 0)
96c5af58b7SGuo Ren	PRE_BNEZAD (r13)
97c5af58b7SGuo Ren	stb	r3, (r0, 0)
98c5af58b7SGuo Ren	BNEZAD (r13, .L_dest_not_aligned_loop)
99c5af58b7SGuo Ren	cmplti	r2, 4
100c5af58b7SGuo Ren	bt	.L_copy_by_byte
101c5af58b7SGuo Ren	/* Check whether the src is aligned.  */
102c5af58b7SGuo Ren	jbr	.L_dest_aligned
103c5af58b7SGuo RenENDPROC(memmove)
104c5af58b7SGuo RenENDPROC(__memmove)
105