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