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