1/* SPDX-License-Identifier: GPL-2.0 */
2
3#include <linux/linkage.h>
4#include <asm/asm.h>
5
6ENTRY(__memmove)
7WEAK(memmove)
8        move    t0, a0
9        move    t1, a1
10
11        beq     a0, a1, exit_memcpy
12        beqz    a2, exit_memcpy
13        srli    t2, a2, 0x2
14
15        slt     t3, a0, a1
16        beqz    t3, do_reverse
17
18        andi    a2, a2, 0x3
19        li      t4, 1
20        beqz    t2, byte_copy
21
22word_copy:
23        lw      t3, 0(a1)
24        addi    t2, t2, -1
25        addi    a1, a1, 4
26        sw      t3, 0(a0)
27        addi    a0, a0, 4
28        bnez    t2, word_copy
29        beqz    a2, exit_memcpy
30        j       byte_copy
31
32do_reverse:
33        add     a0, a0, a2
34        add     a1, a1, a2
35        andi    a2, a2, 0x3
36        li      t4, -1
37        beqz    t2, reverse_byte_copy
38
39reverse_word_copy:
40        addi    a1, a1, -4
41        addi    t2, t2, -1
42        lw      t3, 0(a1)
43        addi    a0, a0, -4
44        sw      t3, 0(a0)
45        bnez    t2, reverse_word_copy
46        beqz    a2, exit_memcpy
47
48reverse_byte_copy:
49        addi    a0, a0, -1
50        addi    a1, a1, -1
51
52byte_copy:
53        lb      t3, 0(a1)
54        addi    a2, a2, -1
55        sb      t3, 0(a0)
56        add     a1, a1, t4
57        add     a0, a0, t4
58        bnez    a2, byte_copy
59
60exit_memcpy:
61        move a0, t0
62        move a1, t1
63        ret
64END(__memmove)
65