Move all files into ports/ subdirectory in preparation for merge with glibc
[glibc.git] / ports / sysdeps / mips / mips64 / memcpy.S
blob49ef34d0c6162b24aefb7c1e3b700f5e6ab17da6
1 /* Copyright (C) 2002-2012 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Hartvig Ekner <hartvige@mips.com>, 2002.
4    Ported to mips3 n32/n64 by Alexandre Oliva <aoliva@redhat.com>
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library.  If not, see
18    <http://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
21 #include <sys/asm.h>
24 /* void *memcpy(void *s1, const void *s2, size_t n);
25         
26    This could probably be optimized further.  */
28 #if __MIPSEB
29 #  define LDHI  ldl             /* high part is left in big-endian      */
30 #  define SDHI  sdl             /* high part is left in big-endian      */
31 #  define LDLO  ldr             /* low part is right in big-endian      */
32 #  define SDLO  sdr             /* low part is right in big-endian      */
33 #else
34 #  define LDHI  ldr             /* high part is right in little-endian  */
35 #  define SDHI  sdr             /* high part is right in little-endian  */
36 #  define LDLO  ldl             /* low part is left in little-endian    */
37 #  define SDLO  sdl             /* low part is left in little-endian    */
38 #endif
40 ENTRY (memcpy)
41         .set    noreorder
43         slti    t0, a2, 16              # Less than 16?
44         bne     t0, zero, L(last16)
45         move    v0, a0                  # Setup exit value before too late
47         xor     t0, a1, a0              # Find a0/a1 displacement
48         andi    t0, 0x7
49         bne     t0, zero, L(shift)      # Go handle the unaligned case
50         PTR_SUBU t1, zero, a1
51         andi    t1, 0x7                 # a0/a1 are aligned, but are we
52         beq     t1, zero, L(chk8w)      #  starting in the middle of a word?
53         PTR_SUBU a2, t1
54         LDHI    t0, 0(a1)               # Yes we are... take care of that
55         PTR_ADDU a1, t1
56         SDHI    t0, 0(a0)
57         PTR_ADDU a0, t1
59 L(chk8w):
60         andi    t0, a2, 0x3f            # 64 or more bytes left?
61         beq     t0, a2, L(chk1w)
62         PTR_SUBU a3, a2, t0             # Yes
63         PTR_ADDU a3, a1                 # a3 = end address of loop
64         move    a2, t0                  # a2 = what will be left after loop
65 L(lop8w):       
66         ld      t0,  0(a1)              # Loop taking 8 words at a time
67         ld      t1,  8(a1)
68         ld      t2, 16(a1)
69         ld      t3, 24(a1)
70         ld      ta0, 32(a1)
71         ld      ta1, 40(a1)
72         ld      ta2, 48(a1)
73         ld      ta3, 56(a1)
74         PTR_ADDIU a0, 64
75         PTR_ADDIU a1, 64
76         sd      t0, -64(a0)
77         sd      t1, -56(a0)
78         sd      t2, -48(a0)
79         sd      t3, -40(a0)
80         sd      ta0, -32(a0)
81         sd      ta1, -24(a0)
82         sd      ta2, -16(a0)
83         bne     a1, a3, L(lop8w)
84         sd      ta3,  -8(a0)
86 L(chk1w):
87         andi    t0, a2, 0x7             # 8 or more bytes left?
88         beq     t0, a2, L(last16)
89         PTR_SUBU a3, a2, t0             # Yes, handle them one dword at a time
90         PTR_ADDU a3, a1                 # a3 again end address
91         move    a2, t0
92 L(lop1w):
93         ld      t0, 0(a1)
94         PTR_ADDIU a0, 8
95         PTR_ADDIU a1, 8
96         bne     a1, a3, L(lop1w)
97         sd      t0, -8(a0)
99 L(last16):
100         blez    a2, L(lst16e)           # Handle last 16 bytes, one at a time
101         PTR_ADDU a3, a2, a1
102 L(lst16l):
103         lb      t0, 0(a1)
104         PTR_ADDIU a0, 1
105         PTR_ADDIU a1, 1
106         bne     a1, a3, L(lst16l)
107         sb      t0, -1(a0)
108 L(lst16e):
109         jr      ra                      # Bye, bye
110         nop
112 L(shift):
113         PTR_SUBU a3, zero, a0           # Src and Dest unaligned 
114         andi    a3, 0x7                 #  (unoptimized case...)
115         beq     a3, zero, L(shft1)
116         PTR_SUBU a2, a3                 # a2 = bytes left
117         LDHI    t0, 0(a1)               # Take care of first odd part
118         LDLO    t0, 7(a1)
119         PTR_ADDU a1, a3
120         SDHI    t0, 0(a0)
121         PTR_ADDU a0, a3
122 L(shft1):
123         andi    t0, a2, 0x7
124         PTR_SUBU a3, a2, t0
125         PTR_ADDU a3, a1
126 L(shfth):
127         LDHI    t1, 0(a1)               # Limp through, dword by dword
128         LDLO    t1, 7(a1)
129         PTR_ADDIU a0, 8
130         PTR_ADDIU a1, 8
131         bne     a1, a3, L(shfth)
132         sd      t1, -8(a0)
133         b       L(last16)               # Handle anything which may be left
134         move    a2, t0
136         .set    reorder
137 END (memcpy)
138 libc_hidden_builtin_def (memcpy)