Linux 4.18.10
[linux/fpc-iii.git] / arch / arc / lib / memcpy-archs.S
blobd61044dd8b58e0e6620984468b2c5acc1fb2870b
1 /*
2  * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
9 #include <linux/linkage.h>
11 #ifdef __LITTLE_ENDIAN__
12 # define SHIFT_1(RX,RY,IMM)     asl     RX, RY, IMM     ; <<
13 # define SHIFT_2(RX,RY,IMM)     lsr     RX, RY, IMM     ; >>
14 # define MERGE_1(RX,RY,IMM)     asl     RX, RY, IMM
15 # define MERGE_2(RX,RY,IMM)
16 # define EXTRACT_1(RX,RY,IMM)   and     RX, RY, 0xFFFF
17 # define EXTRACT_2(RX,RY,IMM)   lsr     RX, RY, IMM
18 #else
19 # define SHIFT_1(RX,RY,IMM)     lsr     RX, RY, IMM     ; >>
20 # define SHIFT_2(RX,RY,IMM)     asl     RX, RY, IMM     ; <<
21 # define MERGE_1(RX,RY,IMM)     asl     RX, RY, IMM     ; <<
22 # define MERGE_2(RX,RY,IMM)     asl     RX, RY, IMM     ; <<
23 # define EXTRACT_1(RX,RY,IMM)   lsr     RX, RY, IMM
24 # define EXTRACT_2(RX,RY,IMM)   lsr     RX, RY, 0x08
25 #endif
27 #ifdef CONFIG_ARC_HAS_LL64
28 # define PREFETCH_READ(RX)      prefetch    [RX, 56]
29 # define PREFETCH_WRITE(RX)     prefetchw   [RX, 64]
30 # define LOADX(DST,RX)          ldd.ab  DST, [RX, 8]
31 # define STOREX(SRC,RX)         std.ab  SRC, [RX, 8]
32 # define ZOLSHFT                5
33 # define ZOLAND                 0x1F
34 #else
35 # define PREFETCH_READ(RX)      prefetch    [RX, 28]
36 # define PREFETCH_WRITE(RX)     prefetchw   [RX, 32]
37 # define LOADX(DST,RX)          ld.ab   DST, [RX, 4]
38 # define STOREX(SRC,RX)         st.ab   SRC, [RX, 4]
39 # define ZOLSHFT                4
40 # define ZOLAND                 0xF
41 #endif
43 ENTRY_CFI(memcpy)
44         prefetch [r1]           ; Prefetch the read location
45         prefetchw [r0]          ; Prefetch the write location
46         mov.f   0, r2
47 ;;; if size is zero
48         jz.d    [blink]
49         mov     r3, r0          ; don;t clobber ret val
51 ;;; if size <= 8
52         cmp     r2, 8
53         bls.d   @.Lsmallchunk
54         mov.f   lp_count, r2
56         and.f   r4, r0, 0x03
57         rsub    lp_count, r4, 4
58         lpnz    @.Laligndestination
59         ;; LOOP BEGIN
60         ldb.ab  r5, [r1,1]
61         sub     r2, r2, 1
62         stb.ab  r5, [r3,1]
63 .Laligndestination:
65 ;;; Check the alignment of the source
66         and.f   r4, r1, 0x03
67         bnz.d   @.Lsourceunaligned
69 ;;; CASE 0: Both source and destination are 32bit aligned
70 ;;; Convert len to Dwords, unfold x4
71         lsr.f   lp_count, r2, ZOLSHFT
72         lpnz    @.Lcopy32_64bytes
73         ;; LOOP START
74         LOADX (r6, r1)
75         PREFETCH_READ (r1)
76         PREFETCH_WRITE (r3)
77         LOADX (r8, r1)
78         LOADX (r10, r1)
79         LOADX (r4, r1)
80         STOREX (r6, r3)
81         STOREX (r8, r3)
82         STOREX (r10, r3)
83         STOREX (r4, r3)
84 .Lcopy32_64bytes:
86         and.f   lp_count, r2, ZOLAND ;Last remaining 31 bytes
87 .Lsmallchunk:
88         lpnz    @.Lcopyremainingbytes
89         ;; LOOP START
90         ldb.ab  r5, [r1,1]
91         stb.ab  r5, [r3,1]
92 .Lcopyremainingbytes:
94         j       [blink]
95 ;;; END CASE 0
97 .Lsourceunaligned:
98         cmp     r4, 2
99         beq.d   @.LunalignedOffby2
100         sub     r2, r2, 1
102         bhi.d   @.LunalignedOffby3
103         ldb.ab  r5, [r1, 1]
105 ;;; CASE 1: The source is unaligned, off by 1
106         ;; Hence I need to read 1 byte for a 16bit alignment
107         ;; and 2bytes to reach 32bit alignment
108         ldh.ab  r6, [r1, 2]
109         sub     r2, r2, 2
110         ;; Convert to words, unfold x2
111         lsr.f   lp_count, r2, 3
112         MERGE_1 (r6, r6, 8)
113         MERGE_2 (r5, r5, 24)
114         or      r5, r5, r6
116         ;; Both src and dst are aligned
117         lpnz    @.Lcopy8bytes_1
118         ;; LOOP START
119         ld.ab   r6, [r1, 4]
120         prefetch [r1, 28]       ;Prefetch the next read location
121         ld.ab   r8, [r1,4]
122         prefetchw [r3, 32]      ;Prefetch the next write location
124         SHIFT_1 (r7, r6, 24)
125         or      r7, r7, r5
126         SHIFT_2 (r5, r6, 8)
128         SHIFT_1 (r9, r8, 24)
129         or      r9, r9, r5
130         SHIFT_2 (r5, r8, 8)
132         st.ab   r7, [r3, 4]
133         st.ab   r9, [r3, 4]
134 .Lcopy8bytes_1:
136         ;; Write back the remaining 16bits
137         EXTRACT_1 (r6, r5, 16)
138         sth.ab  r6, [r3, 2]
139         ;; Write back the remaining 8bits
140         EXTRACT_2 (r5, r5, 16)
141         stb.ab  r5, [r3, 1]
143         and.f   lp_count, r2, 0x07 ;Last 8bytes
144         lpnz    @.Lcopybytewise_1
145         ;; LOOP START
146         ldb.ab  r6, [r1,1]
147         stb.ab  r6, [r3,1]
148 .Lcopybytewise_1:
149         j       [blink]
151 .LunalignedOffby2:
152 ;;; CASE 2: The source is unaligned, off by 2
153         ldh.ab  r5, [r1, 2]
154         sub     r2, r2, 1
156         ;; Both src and dst are aligned
157         ;; Convert to words, unfold x2
158         lsr.f   lp_count, r2, 3
159 #ifdef __BIG_ENDIAN__
160         asl.nz  r5, r5, 16
161 #endif
162         lpnz    @.Lcopy8bytes_2
163         ;; LOOP START
164         ld.ab   r6, [r1, 4]
165         prefetch [r1, 28]       ;Prefetch the next read location
166         ld.ab   r8, [r1,4]
167         prefetchw [r3, 32]      ;Prefetch the next write location
169         SHIFT_1 (r7, r6, 16)
170         or      r7, r7, r5
171         SHIFT_2 (r5, r6, 16)
173         SHIFT_1 (r9, r8, 16)
174         or      r9, r9, r5
175         SHIFT_2 (r5, r8, 16)
177         st.ab   r7, [r3, 4]
178         st.ab   r9, [r3, 4]
179 .Lcopy8bytes_2:
181 #ifdef __BIG_ENDIAN__
182         lsr.nz  r5, r5, 16
183 #endif
184         sth.ab  r5, [r3, 2]
186         and.f   lp_count, r2, 0x07 ;Last 8bytes
187         lpnz    @.Lcopybytewise_2
188         ;; LOOP START
189         ldb.ab  r6, [r1,1]
190         stb.ab  r6, [r3,1]
191 .Lcopybytewise_2:
192         j       [blink]
194 .LunalignedOffby3:
195 ;;; CASE 3: The source is unaligned, off by 3
196 ;;; Hence, I need to read 1byte for achieve the 32bit alignment
198         ;; Both src and dst are aligned
199         ;; Convert to words, unfold x2
200         lsr.f   lp_count, r2, 3
201 #ifdef __BIG_ENDIAN__
202         asl.ne  r5, r5, 24
203 #endif
204         lpnz    @.Lcopy8bytes_3
205         ;; LOOP START
206         ld.ab   r6, [r1, 4]
207         prefetch [r1, 28]       ;Prefetch the next read location
208         ld.ab   r8, [r1,4]
209         prefetchw [r3, 32]      ;Prefetch the next write location
211         SHIFT_1 (r7, r6, 8)
212         or      r7, r7, r5
213         SHIFT_2 (r5, r6, 24)
215         SHIFT_1 (r9, r8, 8)
216         or      r9, r9, r5
217         SHIFT_2 (r5, r8, 24)
219         st.ab   r7, [r3, 4]
220         st.ab   r9, [r3, 4]
221 .Lcopy8bytes_3:
223 #ifdef __BIG_ENDIAN__
224         lsr.nz  r5, r5, 24
225 #endif
226         stb.ab  r5, [r3, 1]
228         and.f   lp_count, r2, 0x07 ;Last 8bytes
229         lpnz    @.Lcopybytewise_3
230         ;; LOOP START
231         ldb.ab  r6, [r1,1]
232         stb.ab  r6, [r3,1]
233 .Lcopybytewise_3:
234         j       [blink]
236 END_CFI(memcpy)