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