1*4882a593Smuzhiyun// SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun// Copyright (C) 2005-2017 Andes Technology Corporation 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun#include <linux/linkage.h> 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun/* 7*4882a593Smuzhiyun void *memmove(void *dst, const void *src, int n); 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun dst: $r0 10*4882a593Smuzhiyun src: $r1 11*4882a593Smuzhiyun n : $r2 12*4882a593Smuzhiyun ret: $r0 - pointer to the memory area dst. 13*4882a593Smuzhiyun*/ 14*4882a593Smuzhiyun .text 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunENTRY(memmove) 17*4882a593Smuzhiyun move $r5, $r0 ! Set return value = det 18*4882a593Smuzhiyun beq $r0, $r1, exit_memcpy ! Exit when det = src 19*4882a593Smuzhiyun beqz $r2, exit_memcpy ! Exit when n = 0 20*4882a593Smuzhiyun pushm $t0, $t1 ! Save reg 21*4882a593Smuzhiyun srli $p1, $r2, #2 ! $p1 is how many words to copy 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun ! Avoid data lost when memory overlap 24*4882a593Smuzhiyun ! Copy data reversely when src < dst 25*4882a593Smuzhiyun slt $p0, $r0, $r1 ! check if $r0 < $r1 26*4882a593Smuzhiyun beqz $p0, do_reverse ! branch if dst > src 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun ! No reverse, dst < src 29*4882a593Smuzhiyun andi $r2, $r2, #3 ! How many bytes are less than a word 30*4882a593Smuzhiyun li $t0, #1 ! Determining copy direction in byte_cpy 31*4882a593Smuzhiyun beqz $p1, byte_cpy ! When n is less than a word 32*4882a593Smuzhiyun 33*4882a593Smuzhiyunword_cpy: 34*4882a593Smuzhiyun lmw.bim $p0, [$r1], $p0 ! Read a word from src 35*4882a593Smuzhiyun addi $p1, $p1, #-1 ! How many words left to copy 36*4882a593Smuzhiyun smw.bim $p0, [$r0], $p0 ! Copy the word to det 37*4882a593Smuzhiyun bnez $p1, word_cpy ! If remained words > 0 38*4882a593Smuzhiyun beqz $r2, end_memcpy ! No left bytes to copy 39*4882a593Smuzhiyun b byte_cpy 40*4882a593Smuzhiyun 41*4882a593Smuzhiyundo_reverse: 42*4882a593Smuzhiyun add $r0, $r0, $r2 ! Start with the end of $r0 43*4882a593Smuzhiyun add $r1, $r1, $r2 ! Start with the end of $r1 44*4882a593Smuzhiyun andi $r2, $r2, #3 ! How many bytes are less than a word 45*4882a593Smuzhiyun li $t0, #-1 ! Determining copy direction in byte_cpy 46*4882a593Smuzhiyun beqz $p1, reverse_byte_cpy ! When n is less than a word 47*4882a593Smuzhiyun 48*4882a593Smuzhiyunreverse_word_cpy: 49*4882a593Smuzhiyun lmw.adm $p0, [$r1], $p0 ! Read a word from src 50*4882a593Smuzhiyun addi $p1, $p1, #-1 ! How many words left to copy 51*4882a593Smuzhiyun smw.adm $p0, [$r0], $p0 ! Copy the word to det 52*4882a593Smuzhiyun bnez $p1, reverse_word_cpy ! If remained words > 0 53*4882a593Smuzhiyun beqz $r2, end_memcpy ! No left bytes to copy 54*4882a593Smuzhiyun 55*4882a593Smuzhiyunreverse_byte_cpy: 56*4882a593Smuzhiyun addi $r0, $r0, #-1 57*4882a593Smuzhiyun addi $r1, $r1, #-1 58*4882a593Smuzhiyunbyte_cpy: ! Less than 4 bytes to copy now 59*4882a593Smuzhiyun lb.bi $p0, [$r1], $t0 ! Read a byte from src 60*4882a593Smuzhiyun addi $r2, $r2, #-1 ! How many bytes left to copy 61*4882a593Smuzhiyun sb.bi $p0, [$r0], $t0 ! copy the byte to det 62*4882a593Smuzhiyun bnez $r2, byte_cpy ! If remained bytes > 0 63*4882a593Smuzhiyun 64*4882a593Smuzhiyunend_memcpy: 65*4882a593Smuzhiyun popm $t0, $t1 66*4882a593Smuzhiyunexit_memcpy: 67*4882a593Smuzhiyun move $r0, $r5 68*4882a593Smuzhiyun ret 69*4882a593Smuzhiyun 70*4882a593SmuzhiyunENDPROC(memmove) 71