* sysdeps/mips/mips64/memcpy.S, sysdeps/mips/mips64/memset.S: New.
[kopensolaris-gnu/glibc.git] / sysdeps / mips / mips64 / memcpy.S
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>
5
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.
10
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.
15
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.  */
20
21 #include <sysdep.h>
22 #include <endian.h>
23 #include <sys/asm.h>
24
25
26 /* void *memcpy(void *s1, const void *s2, size_t n);
27         
28    This could probably be optimized further.  */
29
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
41
42 ENTRY (memcpy)
43         .set    noreorder
44
45         slti    a4, a2, 8               # Less than 8?
46         bne     a4, zero, L(last8)
47         move    v0, a0                  # Setup exit value before too late
48
49         xor     a4, a1, a0              # Find a0/a1 displacement
50         andi    a4, 0x7
51         bne     a4, zero, L(shift)      # Go handle the unaligned case
52         PTR_SUBU a5, zero, a1
53         andi    a5, 0x7                 # a0/a1 are aligned, but are we
54         beq     a5, zero, L(chk8w)      #  starting in the middle of a word?
55         PTR_SUBU a2, a5
56         LDHI    a4, 0(a1)               # Yes we are... take care of that
57         PTR_ADDU a1, a5
58         SDHI    a4, 0(a0)
59         PTR_ADDU a0, a5
60
61 L(chk8w):
62         andi    a4, a2, 0x3f            # 64 or more bytes left?
63         beq     a4, a2, L(chk1w)
64         PTR_SUBU a3, a2, a4             # Yes
65         PTR_ADDU a3, a1                 # a3 = end address of loop
66         move    a2, a4                  # a2 = what will be left after loop
67 L(lop8w):       
68         ld      a4,  0(a1)              # Loop taking 8 words at a time
69         ld      a5,  8(a1)
70         ld      a6, 16(a1)
71         ld      a7, 24(a1)
72         ld      t4, 32(a1)
73         ld      t5, 40(a1)
74         ld      t6, 48(a1)
75         ld      t7, 56(a1)
76         PTR_ADDIU a0, 64
77         PTR_ADDIU a1, 64
78         sd      a4, -64(a0)
79         sd      a5, -56(a0)
80         sd      a6, -48(a0)
81         sd      a7, -40(a0)
82         sd      t4, -32(a0)
83         sd      t5, -24(a0)
84         sd      t6, -16(a0)
85         bne     a1, a3, L(lop8w)
86         sd      t7,  -8(a0)
87
88 L(chk1w):
89         andi    a4, a2, 0x7             # 4 or more bytes left?
90         beq     a4, a2, L(last8)
91         PTR_SUBU a3, a2, a4             # Yes, handle them one word at a time
92         PTR_ADDU a3, a1                 # a3 again end address
93         move    a2, a4
94 L(lop1w):       
95         ld      a4, 0(a1)
96         PTR_ADDIU a0, 8
97         PTR_ADDIU a1, 8
98         bne     a1, a3, L(lop1w)
99         sd      a4, -8(a0)
100
101 L(last8):
102         blez    a2, L(lst8e)            # Handle last 8 bytes, one at a time
103         PTR_ADDU a3, a2, a1
104 L(lst8l):
105         lb      a4, 0(a1)
106         PTR_ADDIU a0, 1
107         PTR_ADDIU a1, 1
108         bne     a1, a3, L(lst8l)
109         sb      a4, -1(a0)
110 L(lst8e):
111         jr      ra                      # Bye, bye
112         nop
113
114 L(shift):
115         PTR_SUBU a3, zero, a0           # Src and Dest unaligned 
116         andi    a3, 0x7                 #  (unoptimized case...)
117         beq     a3, zero, L(shfa5)
118         PTR_SUBU a2, a3                 # a2 = bytes left
119         LDHI    a4, 0(a1)               # Take care of first odd part
120         LDLO    a4, 7(a1)
121         PTR_ADDU a1, a3
122         SDHI    a4, 0(a0)
123         PTR_ADDU a0, a3
124 L(shfa5):
125         andi    a4, a2, 0x7
126         PTR_SUBU a3, a2, a4
127         PTR_ADDU a3, a1
128 L(shfth):
129         LDHI    a5, 0(a1)               # Limp through, word by word
130         LDLO    a5, 7(a1)
131         PTR_ADDIU a0, 8
132         PTR_ADDIU a1, 8
133         bne     a1, a3, L(shfth)
134         sd      a5, -8(a0)
135         b       L(last8)                # Handle anything which may be left
136         move    a2, a4
137
138         .set    reorder
139 END (memcpy)