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