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 | SYM_FUNC_START(__memcpy) |
11 | move t6, a0 /* Preserve return value */ |
12 | |
13 | /* Defer to byte-oriented copy for small sizes */ |
14 | sltiu a3, a2, 128 |
15 | bnez a3, 4f |
16 | /* Use word-oriented copy only if low-order bits match */ |
17 | andi a3, t6, SZREG-1 |
18 | andi a4, a1, SZREG-1 |
19 | bne a3, a4, 4f |
20 | |
21 | beqz a3, 2f /* Skip if already aligned */ |
22 | /* |
23 | * Round to nearest double word-aligned address |
24 | * greater than or equal to start address |
25 | */ |
26 | andi a3, a1, ~(SZREG-1) |
27 | addi a3, a3, SZREG |
28 | /* Handle initial misalignment */ |
29 | sub a4, a3, a1 |
30 | 1: |
31 | lb a5, 0(a1) |
32 | addi a1, a1, 1 |
33 | sb a5, 0(t6) |
34 | addi t6, t6, 1 |
35 | bltu a1, a3, 1b |
36 | sub a2, a2, a4 /* Update count */ |
37 | |
38 | 2: |
39 | andi a4, a2, ~((16*SZREG)-1) |
40 | beqz a4, 4f |
41 | add a3, a1, a4 |
42 | 3: |
43 | REG_L a4, 0(a1) |
44 | REG_L a5, SZREG(a1) |
45 | REG_L a6, 2*SZREG(a1) |
46 | REG_L a7, 3*SZREG(a1) |
47 | REG_L t0, 4*SZREG(a1) |
48 | REG_L t1, 5*SZREG(a1) |
49 | REG_L t2, 6*SZREG(a1) |
50 | REG_L t3, 7*SZREG(a1) |
51 | REG_L t4, 8*SZREG(a1) |
52 | REG_L t5, 9*SZREG(a1) |
53 | REG_S a4, 0(t6) |
54 | REG_S a5, SZREG(t6) |
55 | REG_S a6, 2*SZREG(t6) |
56 | REG_S a7, 3*SZREG(t6) |
57 | REG_S t0, 4*SZREG(t6) |
58 | REG_S t1, 5*SZREG(t6) |
59 | REG_S t2, 6*SZREG(t6) |
60 | REG_S t3, 7*SZREG(t6) |
61 | REG_S t4, 8*SZREG(t6) |
62 | REG_S t5, 9*SZREG(t6) |
63 | REG_L a4, 10*SZREG(a1) |
64 | REG_L a5, 11*SZREG(a1) |
65 | REG_L a6, 12*SZREG(a1) |
66 | REG_L a7, 13*SZREG(a1) |
67 | REG_L t0, 14*SZREG(a1) |
68 | REG_L t1, 15*SZREG(a1) |
69 | addi a1, a1, 16*SZREG |
70 | REG_S a4, 10*SZREG(t6) |
71 | REG_S a5, 11*SZREG(t6) |
72 | REG_S a6, 12*SZREG(t6) |
73 | REG_S a7, 13*SZREG(t6) |
74 | REG_S t0, 14*SZREG(t6) |
75 | REG_S t1, 15*SZREG(t6) |
76 | addi t6, t6, 16*SZREG |
77 | bltu a1, a3, 3b |
78 | andi a2, a2, (16*SZREG)-1 /* Update count */ |
79 | |
80 | 4: |
81 | /* Handle trailing misalignment */ |
82 | beqz a2, 6f |
83 | add a3, a1, a2 |
84 | |
85 | /* Use word-oriented copy if co-aligned to word boundary */ |
86 | or a5, a1, t6 |
87 | or a5, a5, a3 |
88 | andi a5, a5, 3 |
89 | bnez a5, 5f |
90 | 7: |
91 | lw a4, 0(a1) |
92 | addi a1, a1, 4 |
93 | sw a4, 0(t6) |
94 | addi t6, t6, 4 |
95 | bltu a1, a3, 7b |
96 | |
97 | ret |
98 | |
99 | 5: |
100 | lb a4, 0(a1) |
101 | addi a1, a1, 1 |
102 | sb a4, 0(t6) |
103 | addi t6, t6, 1 |
104 | bltu a1, a3, 5b |
105 | 6: |
106 | ret |
107 | SYM_FUNC_END(__memcpy) |
108 | SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy) |
109 | SYM_FUNC_ALIAS(__pi_memcpy, __memcpy) |
110 | SYM_FUNC_ALIAS(__pi___memcpy, __memcpy) |
111 |