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