18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/linkage.h>
58c2ecf20Sopenharmony_ci#include "sysdep.h"
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci	.weak memmove
88c2ecf20Sopenharmony_ciENTRY(__memmove)
98c2ecf20Sopenharmony_ciENTRY(memmove)
108c2ecf20Sopenharmony_ci	subu	r3, r0, r1
118c2ecf20Sopenharmony_ci	cmphs	r3, r2
128c2ecf20Sopenharmony_ci	bt	memcpy
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci	mov	r12, r0
158c2ecf20Sopenharmony_ci	addu	r0, r0, r2
168c2ecf20Sopenharmony_ci	addu	r1, r1, r2
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	/* Test if len less than 4 bytes.  */
198c2ecf20Sopenharmony_ci	cmplti	r2, 4
208c2ecf20Sopenharmony_ci	bt	.L_copy_by_byte
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	andi	r13, r0, 3
238c2ecf20Sopenharmony_ci	/* Test if dest is not 4 bytes aligned.  */
248c2ecf20Sopenharmony_ci	bnez	r13, .L_dest_not_aligned
258c2ecf20Sopenharmony_ci	/* Hardware can handle unaligned access directly.  */
268c2ecf20Sopenharmony_ci.L_dest_aligned:
278c2ecf20Sopenharmony_ci	/* If dest is aligned, then copy.  */
288c2ecf20Sopenharmony_ci	zext	r18, r2, 31, 4
298c2ecf20Sopenharmony_ci	/* Test if len less than 16 bytes.  */
308c2ecf20Sopenharmony_ci	bez	r18, .L_len_less_16bytes
318c2ecf20Sopenharmony_ci	movi	r19, 0
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	/* len > 16 bytes */
348c2ecf20Sopenharmony_ci	LABLE_ALIGN
358c2ecf20Sopenharmony_ci.L_len_larger_16bytes:
368c2ecf20Sopenharmony_ci	subi	r1, 16
378c2ecf20Sopenharmony_ci	subi	r0, 16
388c2ecf20Sopenharmony_ci#if defined(__CK860__)
398c2ecf20Sopenharmony_ci	ldw	r3, (r1, 12)
408c2ecf20Sopenharmony_ci	stw	r3, (r0, 12)
418c2ecf20Sopenharmony_ci	ldw	r3, (r1, 8)
428c2ecf20Sopenharmony_ci	stw	r3, (r0, 8)
438c2ecf20Sopenharmony_ci	ldw	r3, (r1, 4)
448c2ecf20Sopenharmony_ci	stw	r3, (r0, 4)
458c2ecf20Sopenharmony_ci	ldw	r3, (r1, 0)
468c2ecf20Sopenharmony_ci	stw	r3, (r0, 0)
478c2ecf20Sopenharmony_ci#else
488c2ecf20Sopenharmony_ci	ldw	r20, (r1, 0)
498c2ecf20Sopenharmony_ci	ldw	r21, (r1, 4)
508c2ecf20Sopenharmony_ci	ldw	r22, (r1, 8)
518c2ecf20Sopenharmony_ci	ldw	r23, (r1, 12)
528c2ecf20Sopenharmony_ci	stw	r20, (r0, 0)
538c2ecf20Sopenharmony_ci	stw	r21, (r0, 4)
548c2ecf20Sopenharmony_ci	stw	r22, (r0, 8)
558c2ecf20Sopenharmony_ci	stw	r23, (r0, 12)
568c2ecf20Sopenharmony_ci	PRE_BNEZAD (r18)
578c2ecf20Sopenharmony_ci#endif
588c2ecf20Sopenharmony_ci	BNEZAD (r18, .L_len_larger_16bytes)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci.L_len_less_16bytes:
618c2ecf20Sopenharmony_ci	zext	r18, r2, 3, 2
628c2ecf20Sopenharmony_ci	bez	r18, .L_copy_by_byte
638c2ecf20Sopenharmony_ci.L_len_less_16bytes_loop:
648c2ecf20Sopenharmony_ci	subi	r1, 4
658c2ecf20Sopenharmony_ci	subi	r0, 4
668c2ecf20Sopenharmony_ci	ldw	r3, (r1, 0)
678c2ecf20Sopenharmony_ci	PRE_BNEZAD (r18)
688c2ecf20Sopenharmony_ci	stw	r3, (r0, 0)
698c2ecf20Sopenharmony_ci	BNEZAD (r18, .L_len_less_16bytes_loop)
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	/* Test if len less than 4 bytes.  */
728c2ecf20Sopenharmony_ci.L_copy_by_byte:
738c2ecf20Sopenharmony_ci	zext	r18, r2, 1, 0
748c2ecf20Sopenharmony_ci	bez	r18, .L_return
758c2ecf20Sopenharmony_ci.L_copy_by_byte_loop:
768c2ecf20Sopenharmony_ci	subi	r1, 1
778c2ecf20Sopenharmony_ci	subi	r0, 1
788c2ecf20Sopenharmony_ci	ldb	r3, (r1, 0)
798c2ecf20Sopenharmony_ci	PRE_BNEZAD (r18)
808c2ecf20Sopenharmony_ci	stb	r3, (r0, 0)
818c2ecf20Sopenharmony_ci	BNEZAD (r18, .L_copy_by_byte_loop)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci.L_return:
848c2ecf20Sopenharmony_ci	mov	r0, r12
858c2ecf20Sopenharmony_ci	rts
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* If dest is not aligned, just copy some bytes makes the dest
888c2ecf20Sopenharmony_ci	   align.  */
898c2ecf20Sopenharmony_ci.L_dest_not_aligned:
908c2ecf20Sopenharmony_ci	sub	r2, r13
918c2ecf20Sopenharmony_ci.L_dest_not_aligned_loop:
928c2ecf20Sopenharmony_ci	subi	r1, 1
938c2ecf20Sopenharmony_ci	subi	r0, 1
948c2ecf20Sopenharmony_ci	/* Makes the dest align.  */
958c2ecf20Sopenharmony_ci	ldb	r3, (r1, 0)
968c2ecf20Sopenharmony_ci	PRE_BNEZAD (r13)
978c2ecf20Sopenharmony_ci	stb	r3, (r0, 0)
988c2ecf20Sopenharmony_ci	BNEZAD (r13, .L_dest_not_aligned_loop)
998c2ecf20Sopenharmony_ci	cmplti	r2, 4
1008c2ecf20Sopenharmony_ci	bt	.L_copy_by_byte
1018c2ecf20Sopenharmony_ci	/* Check whether the src is aligned.  */
1028c2ecf20Sopenharmony_ci	jbr	.L_dest_aligned
1038c2ecf20Sopenharmony_ciENDPROC(memmove)
1048c2ecf20Sopenharmony_ciENDPROC(__memmove)
105