162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/linkage.h> 562306a36Sopenharmony_ci#include "sysdep.h" 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciENTRY(__memcpy) 862306a36Sopenharmony_ciENTRY(memcpy) 962306a36Sopenharmony_ci /* Test if len less than 4 bytes. */ 1062306a36Sopenharmony_ci mov r12, r0 1162306a36Sopenharmony_ci cmplti r2, 4 1262306a36Sopenharmony_ci bt .L_copy_by_byte 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci andi r13, r0, 3 1562306a36Sopenharmony_ci movi r19, 4 1662306a36Sopenharmony_ci /* Test if dest is not 4 bytes aligned. */ 1762306a36Sopenharmony_ci bnez r13, .L_dest_not_aligned 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* Hardware can handle unaligned access directly. */ 2062306a36Sopenharmony_ci.L_dest_aligned: 2162306a36Sopenharmony_ci /* If dest is aligned, then copy. */ 2262306a36Sopenharmony_ci zext r18, r2, 31, 4 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci /* Test if len less than 16 bytes. */ 2562306a36Sopenharmony_ci bez r18, .L_len_less_16bytes 2662306a36Sopenharmony_ci movi r19, 0 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci LABLE_ALIGN 2962306a36Sopenharmony_ci.L_len_larger_16bytes: 3062306a36Sopenharmony_ci#if defined(__CK860__) 3162306a36Sopenharmony_ci ldw r3, (r1, 0) 3262306a36Sopenharmony_ci stw r3, (r0, 0) 3362306a36Sopenharmony_ci ldw r3, (r1, 4) 3462306a36Sopenharmony_ci stw r3, (r0, 4) 3562306a36Sopenharmony_ci ldw r3, (r1, 8) 3662306a36Sopenharmony_ci stw r3, (r0, 8) 3762306a36Sopenharmony_ci ldw r3, (r1, 12) 3862306a36Sopenharmony_ci addi r1, 16 3962306a36Sopenharmony_ci stw r3, (r0, 12) 4062306a36Sopenharmony_ci addi r0, 16 4162306a36Sopenharmony_ci#else 4262306a36Sopenharmony_ci ldw r20, (r1, 0) 4362306a36Sopenharmony_ci ldw r21, (r1, 4) 4462306a36Sopenharmony_ci ldw r22, (r1, 8) 4562306a36Sopenharmony_ci ldw r23, (r1, 12) 4662306a36Sopenharmony_ci stw r20, (r0, 0) 4762306a36Sopenharmony_ci stw r21, (r0, 4) 4862306a36Sopenharmony_ci stw r22, (r0, 8) 4962306a36Sopenharmony_ci stw r23, (r0, 12) 5062306a36Sopenharmony_ci PRE_BNEZAD (r18) 5162306a36Sopenharmony_ci addi r1, 16 5262306a36Sopenharmony_ci addi r0, 16 5362306a36Sopenharmony_ci#endif 5462306a36Sopenharmony_ci BNEZAD (r18, .L_len_larger_16bytes) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci.L_len_less_16bytes: 5762306a36Sopenharmony_ci zext r18, r2, 3, 2 5862306a36Sopenharmony_ci bez r18, .L_copy_by_byte 5962306a36Sopenharmony_ci.L_len_less_16bytes_loop: 6062306a36Sopenharmony_ci ldw r3, (r1, 0) 6162306a36Sopenharmony_ci PRE_BNEZAD (r18) 6262306a36Sopenharmony_ci addi r1, 4 6362306a36Sopenharmony_ci stw r3, (r0, 0) 6462306a36Sopenharmony_ci addi r0, 4 6562306a36Sopenharmony_ci BNEZAD (r18, .L_len_less_16bytes_loop) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* Test if len less than 4 bytes. */ 6862306a36Sopenharmony_ci.L_copy_by_byte: 6962306a36Sopenharmony_ci zext r18, r2, 1, 0 7062306a36Sopenharmony_ci bez r18, .L_return 7162306a36Sopenharmony_ci.L_copy_by_byte_loop: 7262306a36Sopenharmony_ci ldb r3, (r1, 0) 7362306a36Sopenharmony_ci PRE_BNEZAD (r18) 7462306a36Sopenharmony_ci addi r1, 1 7562306a36Sopenharmony_ci stb r3, (r0, 0) 7662306a36Sopenharmony_ci addi r0, 1 7762306a36Sopenharmony_ci BNEZAD (r18, .L_copy_by_byte_loop) 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci.L_return: 8062306a36Sopenharmony_ci mov r0, r12 8162306a36Sopenharmony_ci rts 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* 8462306a36Sopenharmony_ci * If dest is not aligned, just copying some bytes makes the 8562306a36Sopenharmony_ci * dest align. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci.L_dest_not_aligned: 8862306a36Sopenharmony_ci sub r13, r19, r13 8962306a36Sopenharmony_ci sub r2, r13 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* Makes the dest align. */ 9262306a36Sopenharmony_ci.L_dest_not_aligned_loop: 9362306a36Sopenharmony_ci ldb r3, (r1, 0) 9462306a36Sopenharmony_ci PRE_BNEZAD (r13) 9562306a36Sopenharmony_ci addi r1, 1 9662306a36Sopenharmony_ci stb r3, (r0, 0) 9762306a36Sopenharmony_ci addi r0, 1 9862306a36Sopenharmony_ci BNEZAD (r13, .L_dest_not_aligned_loop) 9962306a36Sopenharmony_ci cmplti r2, 4 10062306a36Sopenharmony_ci bt .L_copy_by_byte 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* Check whether the src is aligned. */ 10362306a36Sopenharmony_ci jbr .L_dest_aligned 10462306a36Sopenharmony_ciENDPROC(__memcpy) 105