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