riscv: assembler versions of memcpy, memmove, memset
[platform/kernel/u-boot.git] / arch / riscv / lib / memcpy.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2013 Regents of the University of California
4  */
5
6 #include <linux/linkage.h>
7 #include <asm/asm.h>
8
9 /* void *memcpy(void *, const void *, size_t) */
10 ENTRY(__memcpy)
11 WEAK(memcpy)
12         move t6, a0  /* Preserve return value */
13
14         /* Defer to byte-oriented copy for small sizes */
15         sltiu a3, a2, 128
16         bnez a3, 4f
17         /* Use word-oriented copy only if low-order bits match */
18         andi a3, t6, SZREG-1
19         andi a4, a1, SZREG-1
20         bne a3, a4, 4f
21
22         beqz a3, 2f  /* Skip if already aligned */
23         /*
24          * Round to nearest double word-aligned address
25          * greater than or equal to start address
26          */
27         andi a3, a1, ~(SZREG-1)
28         addi a3, a3, SZREG
29         /* Handle initial misalignment */
30         sub a4, a3, a1
31 1:
32         lb a5, 0(a1)
33         addi a1, a1, 1
34         sb a5, 0(t6)
35         addi t6, t6, 1
36         bltu a1, a3, 1b
37         sub a2, a2, a4  /* Update count */
38
39 2:
40         andi a4, a2, ~((16*SZREG)-1)
41         beqz a4, 4f
42         add a3, a1, a4
43 3:
44         REG_L a4,       0(a1)
45         REG_L a5,   SZREG(a1)
46         REG_L a6, 2*SZREG(a1)
47         REG_L a7, 3*SZREG(a1)
48         REG_L t0, 4*SZREG(a1)
49         REG_L t1, 5*SZREG(a1)
50         REG_L t2, 6*SZREG(a1)
51         REG_L t3, 7*SZREG(a1)
52         REG_L t4, 8*SZREG(a1)
53         REG_L t5, 9*SZREG(a1)
54         REG_S a4,       0(t6)
55         REG_S a5,   SZREG(t6)
56         REG_S a6, 2*SZREG(t6)
57         REG_S a7, 3*SZREG(t6)
58         REG_S t0, 4*SZREG(t6)
59         REG_S t1, 5*SZREG(t6)
60         REG_S t2, 6*SZREG(t6)
61         REG_S t3, 7*SZREG(t6)
62         REG_S t4, 8*SZREG(t6)
63         REG_S t5, 9*SZREG(t6)
64         REG_L a4, 10*SZREG(a1)
65         REG_L a5, 11*SZREG(a1)
66         REG_L a6, 12*SZREG(a1)
67         REG_L a7, 13*SZREG(a1)
68         REG_L t0, 14*SZREG(a1)
69         REG_L t1, 15*SZREG(a1)
70         addi a1, a1, 16*SZREG
71         REG_S a4, 10*SZREG(t6)
72         REG_S a5, 11*SZREG(t6)
73         REG_S a6, 12*SZREG(t6)
74         REG_S a7, 13*SZREG(t6)
75         REG_S t0, 14*SZREG(t6)
76         REG_S t1, 15*SZREG(t6)
77         addi t6, t6, 16*SZREG
78         bltu a1, a3, 3b
79         andi a2, a2, (16*SZREG)-1  /* Update count */
80
81 4:
82         /* Handle trailing misalignment */
83         beqz a2, 6f
84         add a3, a1, a2
85
86         /* Use word-oriented copy if co-aligned to word boundary */
87         or a5, a1, t6
88         or a5, a5, a3
89         andi a5, a5, 3
90         bnez a5, 5f
91 7:
92         lw a4, 0(a1)
93         addi a1, a1, 4
94         sw a4, 0(t6)
95         addi t6, t6, 4
96         bltu a1, a3, 7b
97
98         ret
99
100 5:
101         lb a4, 0(a1)
102         addi a1, a1, 1
103         sb a4, 0(t6)
104         addi t6, t6, 1
105         bltu a1, a3, 5b
106 6:
107         ret
108 END(__memcpy)