|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
- * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
|
|
|
|
|
|
+ * Copyright (C) 2013, 2014-2015, 2017 Synopsys, Inc. (www.synopsys.com)
|
|
* Copyright (C) 2007 ARC International (UK) LTD
|
|
* Copyright (C) 2007 ARC International (UK) LTD
|
|
*
|
|
*
|
|
* Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
|
|
* Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
|
|
@@ -7,12 +7,18 @@
|
|
|
|
|
|
#include <sysdep.h>
|
|
#include <sysdep.h>
|
|
|
|
|
|
|
|
+#if !defined(__ARC700__) && !defined(__ARCHS__)
|
|
|
|
+#error "Neither ARC700 nor ARCHS is defined!"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ENTRY(memcpy)
|
|
|
|
+
|
|
|
|
+#ifdef __ARC700__
|
|
/* This memcpy implementation does not support objects of 1GB or larger -
|
|
/* This memcpy implementation does not support objects of 1GB or larger -
|
|
the check for alignment does not work then. */
|
|
the check for alignment does not work then. */
|
|
/* We assume that most sources and destinations are aligned, and
|
|
/* We assume that most sources and destinations are aligned, and
|
|
that also lengths are mostly a multiple of four, although to a lesser
|
|
that also lengths are mostly a multiple of four, although to a lesser
|
|
extent. */
|
|
extent. */
|
|
-ENTRY(memcpy)
|
|
|
|
or r3,r0,r1
|
|
or r3,r0,r1
|
|
asl_s r3,r3,30
|
|
asl_s r3,r3,30
|
|
mov_s r5,r0
|
|
mov_s r5,r0
|
|
@@ -67,5 +73,233 @@ ENTRY(memcpy)
|
|
.Lendbloop:
|
|
.Lendbloop:
|
|
j_s.d [blink]
|
|
j_s.d [blink]
|
|
stb r12,[r5,0]
|
|
stb r12,[r5,0]
|
|
|
|
+#endif /* __ARC700__ */
|
|
|
|
+
|
|
|
|
+#ifdef __ARCHS__
|
|
|
|
+#ifdef __LITTLE_ENDIAN__
|
|
|
|
+# define SHIFT_1(RX,RY,IMM) asl RX, RY, IMM ; <<
|
|
|
|
+# define SHIFT_2(RX,RY,IMM) lsr RX, RY, IMM ; >>
|
|
|
|
+# define MERGE_1(RX,RY,IMM) asl RX, RY, IMM
|
|
|
|
+# define MERGE_2(RX,RY,IMM)
|
|
|
|
+# define EXTRACT_1(RX,RY,IMM) and RX, RY, 0xFFFF
|
|
|
|
+# define EXTRACT_2(RX,RY,IMM) lsr RX, RY, IMM
|
|
|
|
+#else
|
|
|
|
+# define SHIFT_1(RX,RY,IMM) lsr RX, RY, IMM ; >>
|
|
|
|
+# define SHIFT_2(RX,RY,IMM) asl RX, RY, IMM ; <<
|
|
|
|
+# define MERGE_1(RX,RY,IMM) asl RX, RY, IMM ; <<
|
|
|
|
+# define MERGE_2(RX,RY,IMM) asl RX, RY, IMM ; <<
|
|
|
|
+# define EXTRACT_1(RX,RY,IMM) lsr RX, RY, IMM
|
|
|
|
+# define EXTRACT_2(RX,RY,IMM) lsr RX, RY, 0x08
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#if defined(__LL64__) || defined(__ARC_LL64__)
|
|
|
|
+# define PREFETCH_READ(RX) prefetch [RX, 56]
|
|
|
|
+# define PREFETCH_WRITE(RX) prefetchw [RX, 64]
|
|
|
|
+# define LOADX(DST,RX) ldd.ab DST, [RX, 8]
|
|
|
|
+# define STOREX(SRC,RX) std.ab SRC, [RX, 8]
|
|
|
|
+# define ZOLSHFT 5
|
|
|
|
+# define ZOLAND 0x1F
|
|
|
|
+#else
|
|
|
|
+# define PREFETCH_READ(RX) prefetch [RX, 28]
|
|
|
|
+# define PREFETCH_WRITE(RX) prefetchw [RX, 32]
|
|
|
|
+# define LOADX(DST,RX) ld.ab DST, [RX, 4]
|
|
|
|
+# define STOREX(SRC,RX) st.ab SRC, [RX, 4]
|
|
|
|
+# define ZOLSHFT 4
|
|
|
|
+# define ZOLAND 0xF
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ prefetch [r1] ; Prefetch the read location
|
|
|
|
+ prefetchw [r0] ; Prefetch the write location
|
|
|
|
+ mov.f 0, r2
|
|
|
|
+;;; if size is zero
|
|
|
|
+ jz.d [blink]
|
|
|
|
+ mov r3, r0 ; don't clobber ret val
|
|
|
|
+
|
|
|
|
+;;; if size <= 8
|
|
|
|
+ cmp r2, 8
|
|
|
|
+ bls.d @.Lsmallchunk
|
|
|
|
+ mov.f lp_count, r2
|
|
|
|
+
|
|
|
|
+ and.f r4, r0, 0x03
|
|
|
|
+ rsub lp_count, r4, 4
|
|
|
|
+ lpnz @.Laligndestination
|
|
|
|
+ ;; LOOP BEGIN
|
|
|
|
+ ldb.ab r5, [r1,1]
|
|
|
|
+ sub r2, r2, 1
|
|
|
|
+ stb.ab r5, [r3,1]
|
|
|
|
+.Laligndestination:
|
|
|
|
+
|
|
|
|
+;;; Check the alignment of the source
|
|
|
|
+ and.f r4, r1, 0x03
|
|
|
|
+ bnz.d @.Lsourceunaligned
|
|
|
|
+
|
|
|
|
+;;; CASE 0: Both source and destination are 32bit aligned
|
|
|
|
+;;; Convert len to Dwords, unfold x4
|
|
|
|
+ lsr.f lp_count, r2, ZOLSHFT
|
|
|
|
+ lpnz @.Lcopy32_64bytes
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ LOADX (r6, r1)
|
|
|
|
+ PREFETCH_READ (r1)
|
|
|
|
+ PREFETCH_WRITE (r3)
|
|
|
|
+ LOADX (r8, r1)
|
|
|
|
+ LOADX (r10, r1)
|
|
|
|
+ LOADX (r4, r1)
|
|
|
|
+ STOREX (r6, r3)
|
|
|
|
+ STOREX (r8, r3)
|
|
|
|
+ STOREX (r10, r3)
|
|
|
|
+ STOREX (r4, r3)
|
|
|
|
+.Lcopy32_64bytes:
|
|
|
|
+
|
|
|
|
+ and.f lp_count, r2, ZOLAND ;Last remaining 31 bytes
|
|
|
|
+.Lsmallchunk:
|
|
|
|
+ lpnz @.Lcopyremainingbytes
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ldb.ab r5, [r1,1]
|
|
|
|
+ stb.ab r5, [r3,1]
|
|
|
|
+.Lcopyremainingbytes:
|
|
|
|
+
|
|
|
|
+ j [blink]
|
|
|
|
+;;; END CASE 0
|
|
|
|
+
|
|
|
|
+.Lsourceunaligned:
|
|
|
|
+ cmp r4, 2
|
|
|
|
+ beq.d @.LunalignedOffby2
|
|
|
|
+ sub r2, r2, 1
|
|
|
|
+
|
|
|
|
+ bhi.d @.LunalignedOffby3
|
|
|
|
+ ldb.ab r5, [r1, 1]
|
|
|
|
+
|
|
|
|
+;;; CASE 1: The source is unaligned, off by 1
|
|
|
|
+ ;; Hence I need to read 1 byte for a 16bit alignment
|
|
|
|
+ ;; and 2bytes to reach 32bit alignment
|
|
|
|
+ ldh.ab r6, [r1, 2]
|
|
|
|
+ sub r2, r2, 2
|
|
|
|
+ ;; Convert to words, unfold x2
|
|
|
|
+ lsr.f lp_count, r2, 3
|
|
|
|
+ MERGE_1 (r6, r6, 8)
|
|
|
|
+ MERGE_2 (r5, r5, 24)
|
|
|
|
+ or r5, r5, r6
|
|
|
|
+
|
|
|
|
+ ;; Both src and dst are aligned
|
|
|
|
+ lpnz @.Lcopy8bytes_1
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ld.ab r6, [r1, 4]
|
|
|
|
+ prefetch [r1, 28] ;Prefetch the next read location
|
|
|
|
+ ld.ab r8, [r1,4]
|
|
|
|
+ prefetchw [r3, 32] ;Prefetch the next write location
|
|
|
|
+
|
|
|
|
+ SHIFT_1 (r7, r6, 24)
|
|
|
|
+ or r7, r7, r5
|
|
|
|
+ SHIFT_2 (r5, r6, 8)
|
|
|
|
+
|
|
|
|
+ SHIFT_1 (r9, r8, 24)
|
|
|
|
+ or r9, r9, r5
|
|
|
|
+ SHIFT_2 (r5, r8, 8)
|
|
|
|
+
|
|
|
|
+ st.ab r7, [r3, 4]
|
|
|
|
+ st.ab r9, [r3, 4]
|
|
|
|
+.Lcopy8bytes_1:
|
|
|
|
+
|
|
|
|
+ ;; Write back the remaining 16bits
|
|
|
|
+ EXTRACT_1 (r6, r5, 16)
|
|
|
|
+ sth.ab r6, [r3, 2]
|
|
|
|
+ ;; Write back the remaining 8bits
|
|
|
|
+ EXTRACT_2 (r5, r5, 16)
|
|
|
|
+ stb.ab r5, [r3, 1]
|
|
|
|
+
|
|
|
|
+ and.f lp_count, r2, 0x07 ;Last 8bytes
|
|
|
|
+ lpnz @.Lcopybytewise_1
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ldb.ab r6, [r1,1]
|
|
|
|
+ stb.ab r6, [r3,1]
|
|
|
|
+.Lcopybytewise_1:
|
|
|
|
+ j [blink]
|
|
|
|
+
|
|
|
|
+.LunalignedOffby2:
|
|
|
|
+;;; CASE 2: The source is unaligned, off by 2
|
|
|
|
+ ldh.ab r5, [r1, 2]
|
|
|
|
+ sub r2, r2, 1
|
|
|
|
+
|
|
|
|
+ ;; Both src and dst are aligned
|
|
|
|
+ ;; Convert to words, unfold x2
|
|
|
|
+ lsr.f lp_count, r2, 3
|
|
|
|
+#ifdef __BIG_ENDIAN__
|
|
|
|
+ asl.nz r5, r5, 16
|
|
|
|
+#endif
|
|
|
|
+ lpnz @.Lcopy8bytes_2
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ld.ab r6, [r1, 4]
|
|
|
|
+ prefetch [r1, 28] ;Prefetch the next read location
|
|
|
|
+ ld.ab r8, [r1,4]
|
|
|
|
+ prefetchw [r3, 32] ;Prefetch the next write location
|
|
|
|
+
|
|
|
|
+ SHIFT_1 (r7, r6, 16)
|
|
|
|
+ or r7, r7, r5
|
|
|
|
+ SHIFT_2 (r5, r6, 16)
|
|
|
|
+
|
|
|
|
+ SHIFT_1 (r9, r8, 16)
|
|
|
|
+ or r9, r9, r5
|
|
|
|
+ SHIFT_2 (r5, r8, 16)
|
|
|
|
+
|
|
|
|
+ st.ab r7, [r3, 4]
|
|
|
|
+ st.ab r9, [r3, 4]
|
|
|
|
+.Lcopy8bytes_2:
|
|
|
|
+
|
|
|
|
+#ifdef __BIG_ENDIAN__
|
|
|
|
+ lsr.nz r5, r5, 16
|
|
|
|
+#endif
|
|
|
|
+ sth.ab r5, [r3, 2]
|
|
|
|
+
|
|
|
|
+ and.f lp_count, r2, 0x07 ;Last 8bytes
|
|
|
|
+ lpnz @.Lcopybytewise_2
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ldb.ab r6, [r1,1]
|
|
|
|
+ stb.ab r6, [r3,1]
|
|
|
|
+.Lcopybytewise_2:
|
|
|
|
+ j [blink]
|
|
|
|
+
|
|
|
|
+.LunalignedOffby3:
|
|
|
|
+;;; CASE 3: The source is unaligned, off by 3
|
|
|
|
+;;; Hence, I need to read 1byte for achieve the 32bit alignment
|
|
|
|
+
|
|
|
|
+ ;; Both src and dst are aligned
|
|
|
|
+ ;; Convert to words, unfold x2
|
|
|
|
+ lsr.f lp_count, r2, 3
|
|
|
|
+#ifdef __BIG_ENDIAN__
|
|
|
|
+ asl.ne r5, r5, 24
|
|
|
|
+#endif
|
|
|
|
+ lpnz @.Lcopy8bytes_3
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ld.ab r6, [r1, 4]
|
|
|
|
+ prefetch [r1, 28] ;Prefetch the next read location
|
|
|
|
+ ld.ab r8, [r1,4]
|
|
|
|
+ prefetchw [r3, 32] ;Prefetch the next write location
|
|
|
|
+
|
|
|
|
+ SHIFT_1 (r7, r6, 8)
|
|
|
|
+ or r7, r7, r5
|
|
|
|
+ SHIFT_2 (r5, r6, 24)
|
|
|
|
+
|
|
|
|
+ SHIFT_1 (r9, r8, 8)
|
|
|
|
+ or r9, r9, r5
|
|
|
|
+ SHIFT_2 (r5, r8, 24)
|
|
|
|
+
|
|
|
|
+ st.ab r7, [r3, 4]
|
|
|
|
+ st.ab r9, [r3, 4]
|
|
|
|
+.Lcopy8bytes_3:
|
|
|
|
+
|
|
|
|
+#ifdef __BIG_ENDIAN__
|
|
|
|
+ lsr.nz r5, r5, 24
|
|
|
|
+#endif
|
|
|
|
+ stb.ab r5, [r3, 1]
|
|
|
|
+
|
|
|
|
+ and.f lp_count, r2, 0x07 ;Last 8bytes
|
|
|
|
+ lpnz @.Lcopybytewise_3
|
|
|
|
+ ;; LOOP START
|
|
|
|
+ ldb.ab r6, [r1,1]
|
|
|
|
+ stb.ab r6, [r3,1]
|
|
|
|
+.Lcopybytewise_3:
|
|
|
|
+ j [blink]
|
|
|
|
+#endif /* __ARCHS__ */
|
|
|
|
+
|
|
END(memcpy)
|
|
END(memcpy)
|
|
libc_hidden_def(memcpy)
|
|
libc_hidden_def(memcpy)
|