riscv: Add and use alignment-ignorant memcpy
[glibc.git] / sysdeps / riscv / memcpy_noalignment.S
blob621f8d028f0c81ab39099830c317ec118f9082d5
1 /* memcpy for RISC-V, ignoring buffer alignment
2    Copyright (C) 2024 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <https://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <sys/asm.h>
22 /* void *memcpy(void *, const void *, size_t) */
23 ENTRY (__memcpy_noalignment)
24         move t6, a0  /* Preserve return value */
26         /* Bail if 0 */
27         beqz a2, 7f
29         /* Jump to byte copy if size < SZREG */
30         li a4, SZREG
31         bltu a2, a4, 5f
33         /* Round down to the nearest "page" size */
34         andi a4, a2, ~((16*SZREG)-1)
35         beqz a4, 2f
36         add a3, a1, a4
38         /* Copy the first word to get dest word aligned */
39         andi a5, t6, SZREG-1
40         beqz a5, 1f
41         REG_L a6, (a1)
42         REG_S a6, (t6)
44         /* Align dst up to a word, move src and size as well. */
45         addi t6, t6, SZREG-1
46         andi t6, t6, ~(SZREG-1)
47         sub a5, t6, a0
48         add a1, a1, a5
49         sub a2, a2, a5
51         /* Recompute page count */
52         andi a4, a2, ~((16*SZREG)-1)
53         beqz a4, 2f
56         /* Copy "pages" (chunks of 16 registers) */
57         REG_L a4,       0(a1)
58         REG_L a5,   SZREG(a1)
59         REG_L a6, 2*SZREG(a1)
60         REG_L a7, 3*SZREG(a1)
61         REG_L t0, 4*SZREG(a1)
62         REG_L t1, 5*SZREG(a1)
63         REG_L t2, 6*SZREG(a1)
64         REG_L t3, 7*SZREG(a1)
65         REG_L t4, 8*SZREG(a1)
66         REG_L t5, 9*SZREG(a1)
67         REG_S a4,       0(t6)
68         REG_S a5,   SZREG(t6)
69         REG_S a6, 2*SZREG(t6)
70         REG_S a7, 3*SZREG(t6)
71         REG_S t0, 4*SZREG(t6)
72         REG_S t1, 5*SZREG(t6)
73         REG_S t2, 6*SZREG(t6)
74         REG_S t3, 7*SZREG(t6)
75         REG_S t4, 8*SZREG(t6)
76         REG_S t5, 9*SZREG(t6)
77         REG_L a4, 10*SZREG(a1)
78         REG_L a5, 11*SZREG(a1)
79         REG_L a6, 12*SZREG(a1)
80         REG_L a7, 13*SZREG(a1)
81         REG_L t0, 14*SZREG(a1)
82         REG_L t1, 15*SZREG(a1)
83         addi a1, a1, 16*SZREG
84         REG_S a4, 10*SZREG(t6)
85         REG_S a5, 11*SZREG(t6)
86         REG_S a6, 12*SZREG(t6)
87         REG_S a7, 13*SZREG(t6)
88         REG_S t0, 14*SZREG(t6)
89         REG_S t1, 15*SZREG(t6)
90         addi t6, t6, 16*SZREG
91         bltu a1, a3, 1b
92         andi a2, a2, (16*SZREG)-1  /* Update count */
95         /* Remainder is smaller than a page, compute native word count */
96         beqz a2, 7f
97         andi a5, a2, ~(SZREG-1)
98         andi a2, a2, (SZREG-1)
99         add a3, a1, a5
100         /* Jump directly to last word if no words. */
101         beqz a5, 4f
104         /* Use single native register copy */
105         REG_L a4, 0(a1)
106         addi a1, a1, SZREG
107         REG_S a4, 0(t6)
108         addi t6, t6, SZREG
109         bltu a1, a3, 3b
111         /* Jump directly out if no more bytes */
112         beqz a2, 7f
115         /* Copy the last word unaligned */
116         add a3, a1, a2
117         add a4, t6, a2
118         REG_L a5, -SZREG(a3)
119         REG_S a5, -SZREG(a4)
120         ret
123         /* Copy bytes when the total copy is <SZREG */
124         add a3, a1, a2
127         lb a4, 0(a1)
128         addi a1, a1, 1
129         sb a4, 0(t6)
130         addi t6, t6, 1
131         bltu a1, a3, 6b
134         ret
136 END (__memcpy_noalignment)