2004-10-18 Maciej W. Rozycki <macro@mips.com>
[glibc-ports.git] / sysdeps / mips / mips64 / memcpy.S
blobeab9463f864710477f2cf588501af6b6cf81c358
1 /* Copyright (C) 2002, 2003 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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
21 #include <sysdep.h>
22 #include <endian.h>
23 #include <sys/asm.h>
26 /* void *memcpy(void *s1, const void *s2, size_t n);
27         
28    This could probably be optimized further.  */
30 #if __BYTE_ORDER == __BIG_ENDIAN
31 #  define LDHI  ldl             /* high part is left in big-endian      */
32 #  define SDHI  sdl             /* high part is left in big-endian      */
33 #  define LDLO  ldr             /* low part is right in big-endian      */
34 #  define SDLO  sdr             /* low part is right in big-endian      */
35 #else
36 #  define LDHI  ldr             /* high part is right in little-endian  */
37 #  define SDHI  sdr             /* high part is right in little-endian  */
38 #  define LDLO  ldl             /* low part is left in little-endian    */
39 #  define SDLO  sdl             /* low part is left in little-endian    */
40 #endif
42 ENTRY (memcpy)
43         .set    noreorder
45         slti    t0, a2, 16              # Less than 16?
46         bne     t0, zero, L(last16)
47         move    v0, a0                  # Setup exit value before too late
49         xor     t0, a1, a0              # Find a0/a1 displacement
50         andi    t0, 0x7
51         bne     t0, zero, L(shift)      # Go handle the unaligned case
52         PTR_SUBU t1, zero, a1
53         andi    t1, 0x7                 # a0/a1 are aligned, but are we
54         beq     t1, zero, L(chk8w)      #  starting in the middle of a word?
55         PTR_SUBU a2, t1
56         LDHI    t0, 0(a1)               # Yes we are... take care of that
57         PTR_ADDU a1, t1
58         SDHI    t0, 0(a0)
59         PTR_ADDU a0, t1
61 L(chk8w):
62         andi    t0, a2, 0x3f            # 64 or more bytes left?
63         beq     t0, a2, L(chk1w)
64         PTR_SUBU a3, a2, t0             # Yes
65         PTR_ADDU a3, a1                 # a3 = end address of loop
66         move    a2, t0                  # a2 = what will be left after loop
67 L(lop8w):       
68         ld      t0,  0(a1)              # Loop taking 8 words at a time
69         ld      t1,  8(a1)
70         ld      t2, 16(a1)
71         ld      t3, 24(a1)
72         ld      ta0, 32(a1)
73         ld      ta1, 40(a1)
74         ld      ta2, 48(a1)
75         ld      ta3, 56(a1)
76         PTR_ADDIU a0, 64
77         PTR_ADDIU a1, 64
78         sd      t0, -64(a0)
79         sd      t1, -56(a0)
80         sd      t2, -48(a0)
81         sd      t3, -40(a0)
82         sd      ta0, -32(a0)
83         sd      ta1, -24(a0)
84         sd      ta2, -16(a0)
85         bne     a1, a3, L(lop8w)
86         sd      ta3,  -8(a0)
88 L(chk1w):
89         andi    t0, a2, 0x7             # 8 or more bytes left?
90         beq     t0, a2, L(last16)
91         PTR_SUBU a3, a2, t0             # Yes, handle them one dword at a time
92         PTR_ADDU a3, a1                 # a3 again end address
93         move    a2, t0
94 L(lop1w):
95         ld      t0, 0(a1)
96         PTR_ADDIU a0, 8
97         PTR_ADDIU a1, 8
98         bne     a1, a3, L(lop1w)
99         sd      t0, -8(a0)
101 L(last16):
102         blez    a2, L(lst16e)           # Handle last 16 bytes, one at a time
103         PTR_ADDU a3, a2, a1
104 L(lst16l):
105         lb      t0, 0(a1)
106         PTR_ADDIU a0, 1
107         PTR_ADDIU a1, 1
108         bne     a1, a3, L(lst16l)
109         sb      t0, -1(a0)
110 L(lst16e):
111         jr      ra                      # Bye, bye
112         nop
114 L(shift):
115         PTR_SUBU a3, zero, a0           # Src and Dest unaligned 
116         andi    a3, 0x7                 #  (unoptimized case...)
117         beq     a3, zero, L(shft1)
118         PTR_SUBU a2, a3                 # a2 = bytes left
119         LDHI    t0, 0(a1)               # Take care of first odd part
120         LDLO    t0, 7(a1)
121         PTR_ADDU a1, a3
122         SDHI    t0, 0(a0)
123         PTR_ADDU a0, a3
124 L(shft1):
125         andi    t0, a2, 0x7
126         PTR_SUBU a3, a2, t0
127         PTR_ADDU a3, a1
128 L(shfth):
129         LDHI    t1, 0(a1)               # Limp through, dword by dword
130         LDLO    t1, 7(a1)
131         PTR_ADDIU a0, 8
132         PTR_ADDIU a1, 8
133         bne     a1, a3, L(shfth)
134         sd      t1, -8(a0)
135         b       L(last16)               # Handle anything which may be left
136         move    a2, t0
138         .set    reorder
139 END (memcpy)
140 libc_hidden_builtin_def (memcpy)