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