1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
6 #include <linux/linkage.h>
8 #ifdef __LITTLE_ENDIAN__
9 # define SHIFT_1(RX,RY,IMM) asl RX, RY, IMM ; <<
10 # define SHIFT_2(RX,RY,IMM) lsr RX, RY, IMM ; >>
11 # define MERGE_1(RX,RY,IMM) asl RX, RY, IMM
12 # define MERGE_2(RX,RY,IMM)
13 # define EXTRACT_1(RX,RY,IMM) and RX, RY, 0xFFFF
14 # define EXTRACT_2(RX,RY,IMM) lsr RX, RY, IMM
16 # define SHIFT_1(RX,RY,IMM) lsr RX, RY, IMM ; >>
17 # define SHIFT_2(RX,RY,IMM) asl RX, RY, IMM ; <<
18 # define MERGE_1(RX,RY,IMM) asl RX, RY, IMM ; <<
19 # define MERGE_2(RX,RY,IMM) asl RX, RY, IMM ; <<
20 # define EXTRACT_1(RX,RY,IMM) lsr RX, RY, IMM
21 # define EXTRACT_2(RX,RY,IMM) lsr RX, RY, 0x08
24 #ifdef CONFIG_ARC_HAS_LL64
25 # define LOADX(DST,RX) ldd.ab DST, [RX, 8]
26 # define STOREX(SRC,RX) std.ab SRC, [RX, 8]
30 # define LOADX(DST,RX) ld.ab DST, [RX, 4]
31 # define STOREX(SRC,RX) st.ab SRC, [RX, 4]
40 mov r3, r0 ; don;t clobber ret val
49 lpnz @.Laligndestination
56 ;;; Check the alignment of the source
58 bnz.d @.Lsourceunaligned
60 ;;; CASE 0: Both source and destination are 32bit aligned
61 ;;; Convert len to Dwords, unfold x4
62 lsr.f lp_count, r2, ZOLSHFT
63 lpnz @.Lcopy32_64bytes
75 and.f lp_count, r2, ZOLAND ;Last remaining 31 bytes
77 lpnz @.Lcopyremainingbytes
88 beq.d @.LunalignedOffby2
91 bhi.d @.LunalignedOffby3
94 ;;; CASE 1: The source is unaligned, off by 1
95 ;; Hence I need to read 1 byte for a 16bit alignment
96 ;; and 2bytes to reach 32bit alignment
99 ;; Convert to words, unfold x2
100 lsr.f lp_count, r2, 3
105 ;; Both src and dst are aligned
123 ;; Write back the remaining 16bits
124 EXTRACT_1 (r6, r5, 16)
126 ;; Write back the remaining 8bits
127 EXTRACT_2 (r5, r5, 16)
130 and.f lp_count, r2, 0x07 ;Last 8bytes
131 lpnz @.Lcopybytewise_1
139 ;;; CASE 2: The source is unaligned, off by 2
143 ;; Both src and dst are aligned
144 ;; Convert to words, unfold x2
145 lsr.f lp_count, r2, 3
146 #ifdef __BIG_ENDIAN__
166 #ifdef __BIG_ENDIAN__
171 and.f lp_count, r2, 0x07 ;Last 8bytes
172 lpnz @.Lcopybytewise_2
180 ;;; CASE 3: The source is unaligned, off by 3
181 ;;; Hence, I need to read 1byte for achieve the 32bit alignment
183 ;; Both src and dst are aligned
184 ;; Convert to words, unfold x2
185 lsr.f lp_count, r2, 3
186 #ifdef __BIG_ENDIAN__
206 #ifdef __BIG_ENDIAN__
211 and.f lp_count, r2, 0x07 ;Last 8bytes
212 lpnz @.Lcopybytewise_3