Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-rpi.git] / arch / riscv / lib / memcpy.S
1 /*
2  * Copyright (C) 2013 Regents of the University of California
3  *
4  *   This program is free software; you can redistribute it and/or
5  *   modify it under the terms of the GNU General Public License
6  *   as published by the Free Software Foundation, version 2.
7  *
8  *   This program is distributed in the hope that it will be useful,
9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *   GNU General Public License for more details.
12  */
13
14 #include <linux/linkage.h>
15 #include <asm/asm.h>
16
17 /* void *memcpy(void *, const void *, size_t) */
18 ENTRY(memcpy)
19         move t6, a0  /* Preserve return value */
20
21         /* Defer to byte-oriented copy for small sizes */
22         sltiu a3, a2, 128
23         bnez a3, 4f
24         /* Use word-oriented copy only if low-order bits match */
25         andi a3, t6, SZREG-1
26         andi a4, a1, SZREG-1
27         bne a3, a4, 4f
28
29         beqz a3, 2f  /* Skip if already aligned */
30         /*
31          * Round to nearest double word-aligned address
32          * greater than or equal to start address
33          */
34         andi a3, a1, ~(SZREG-1)
35         addi a3, a3, SZREG
36         /* Handle initial misalignment */
37         sub a4, a3, a1
38 1:
39         lb a5, 0(a1)
40         addi a1, a1, 1
41         sb a5, 0(t6)
42         addi t6, t6, 1
43         bltu a1, a3, 1b
44         sub a2, a2, a4  /* Update count */
45
46 2:
47         andi a4, a2, ~((16*SZREG)-1)
48         beqz a4, 4f
49         add a3, a1, a4
50 3:
51         REG_L a4,       0(a1)
52         REG_L a5,   SZREG(a1)
53         REG_L a6, 2*SZREG(a1)
54         REG_L a7, 3*SZREG(a1)
55         REG_L t0, 4*SZREG(a1)
56         REG_L t1, 5*SZREG(a1)
57         REG_L t2, 6*SZREG(a1)
58         REG_L t3, 7*SZREG(a1)
59         REG_L t4, 8*SZREG(a1)
60         REG_L t5, 9*SZREG(a1)
61         REG_S a4,       0(t6)
62         REG_S a5,   SZREG(t6)
63         REG_S a6, 2*SZREG(t6)
64         REG_S a7, 3*SZREG(t6)
65         REG_S t0, 4*SZREG(t6)
66         REG_S t1, 5*SZREG(t6)
67         REG_S t2, 6*SZREG(t6)
68         REG_S t3, 7*SZREG(t6)
69         REG_S t4, 8*SZREG(t6)
70         REG_S t5, 9*SZREG(t6)
71         REG_L a4, 10*SZREG(a1)
72         REG_L a5, 11*SZREG(a1)
73         REG_L a6, 12*SZREG(a1)
74         REG_L a7, 13*SZREG(a1)
75         REG_L t0, 14*SZREG(a1)
76         REG_L t1, 15*SZREG(a1)
77         addi a1, a1, 16*SZREG
78         REG_S a4, 10*SZREG(t6)
79         REG_S a5, 11*SZREG(t6)
80         REG_S a6, 12*SZREG(t6)
81         REG_S a7, 13*SZREG(t6)
82         REG_S t0, 14*SZREG(t6)
83         REG_S t1, 15*SZREG(t6)
84         addi t6, t6, 16*SZREG
85         bltu a1, a3, 3b
86         andi a2, a2, (16*SZREG)-1  /* Update count */
87
88 4:
89         /* Handle trailing misalignment */
90         beqz a2, 6f
91         add a3, a1, a2
92
93         /* Use word-oriented copy if co-aligned to word boundary */
94         or a5, a1, t6
95         or a5, a5, a3
96         andi a5, a5, 3
97         bnez a5, 5f
98 7:
99         lw a4, 0(a1)
100         addi a1, a1, 4
101         sw a4, 0(t6)
102         addi t6, t6, 4
103         bltu a1, a3, 7b
104
105         ret
106
107 5:
108         lb a4, 0(a1)
109         addi a1, a1, 1
110         sb a4, 0(t6)
111         addi t6, t6, 1
112         bltu a1, a3, 5b
113 6:
114         ret
115 END(memcpy)