]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memcpy.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / string / mips / 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
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <features.h>
20 #include <sysdep.h>
21 #include <endian.h>
22
23 /* void *memcpy(void *s1, const void *s2, size_t n);  */
24
25 #ifdef __mips64
26
27 #include <sys/asm.h>
28
29 #if __BYTE_ORDER == __BIG_ENDIAN
30 #  define LDHI  ldl             /* high part is left in big-endian      */
31 #  define SDHI  sdl             /* high part is left in big-endian      */
32 #  define LDLO  ldr             /* low part is right in big-endian      */
33 #  define SDLO  sdr             /* low part is right in big-endian      */
34 #else
35 #  define LDHI  ldr             /* high part is right in little-endian  */
36 #  define SDHI  sdr             /* high part is right in little-endian  */
37 #  define LDLO  ldl             /* low part is left in little-endian    */
38 #  define SDLO  sdl             /* low part is left in little-endian    */
39 #endif
40
41 ENTRY (memcpy)
42         .set    noreorder
43
44         slti    t0, a2, 16              # Less than 16?
45         bne     t0, zero, L(last16)
46         move    v0, a0                  # Setup exit value before too late
47
48         xor     t0, a1, a0              # Find a0/a1 displacement
49         andi    t0, 0x7
50         bne     t0, zero, L(shift)      # Go handle the unaligned case
51         PTR_SUBU t1, zero, a1
52         andi    t1, 0x7                 # a0/a1 are aligned, but are we
53         beq     t1, zero, L(chk8w)      #  starting in the middle of a word?
54         PTR_SUBU a2, t1
55         LDHI    t0, 0(a1)               # Yes we are... take care of that
56         PTR_ADDU a1, t1
57         SDHI    t0, 0(a0)
58         PTR_ADDU a0, t1
59
60 L(chk8w):
61         andi    t0, a2, 0x3f            # 64 or more bytes left?
62         beq     t0, a2, L(chk1w)
63         PTR_SUBU a3, a2, t0             # Yes
64         PTR_ADDU a3, a1                 # a3 = end address of loop
65         move    a2, t0                  # a2 = what will be left after loop
66 L(lop8w):       
67         ld      t0,  0(a1)              # Loop taking 8 words at a time
68         ld      t1,  8(a1)
69         ld      t2, 16(a1)
70         ld      t3, 24(a1)
71         ld      ta0, 32(a1)
72         ld      ta1, 40(a1)
73         ld      ta2, 48(a1)
74         ld      ta3, 56(a1)
75         PTR_ADDIU a0, 64
76         PTR_ADDIU a1, 64
77         sd      t0, -64(a0)
78         sd      t1, -56(a0)
79         sd      t2, -48(a0)
80         sd      t3, -40(a0)
81         sd      ta0, -32(a0)
82         sd      ta1, -24(a0)
83         sd      ta2, -16(a0)
84         bne     a1, a3, L(lop8w)
85         sd      ta3,  -8(a0)
86
87 L(chk1w):
88         andi    t0, a2, 0x7             # 8 or more bytes left?
89         beq     t0, a2, L(last16)
90         PTR_SUBU a3, a2, t0             # Yes, handle them one dword at a time
91         PTR_ADDU a3, a1                 # a3 again end address
92         move    a2, t0
93 L(lop1w):
94         ld      t0, 0(a1)
95         PTR_ADDIU a0, 8
96         PTR_ADDIU a1, 8
97         bne     a1, a3, L(lop1w)
98         sd      t0, -8(a0)
99
100 L(last16):
101         blez    a2, L(lst16e)           # Handle last 16 bytes, one at a time
102         PTR_ADDU a3, a2, a1
103 L(lst16l):
104         lb      t0, 0(a1)
105         PTR_ADDIU a0, 1
106         PTR_ADDIU a1, 1
107         bne     a1, a3, L(lst16l)
108         sb      t0, -1(a0)
109 L(lst16e):
110         jr      ra                      # Bye, bye
111         nop
112
113 L(shift):
114         PTR_SUBU a3, zero, a0           # Src and Dest unaligned 
115         andi    a3, 0x7                 #  (unoptimized case...)
116         beq     a3, zero, L(shft1)
117         PTR_SUBU a2, a3                 # a2 = bytes left
118         LDHI    t0, 0(a1)               # Take care of first odd part
119         LDLO    t0, 7(a1)
120         PTR_ADDU a1, a3
121         SDHI    t0, 0(a0)
122         PTR_ADDU a0, a3
123 L(shft1):
124         andi    t0, a2, 0x7
125         PTR_SUBU a3, a2, t0
126         PTR_ADDU a3, a1
127 L(shfth):
128         LDHI    t1, 0(a1)               # Limp through, dword by dword
129         LDLO    t1, 7(a1)
130         PTR_ADDIU a0, 8
131         PTR_ADDIU a1, 8
132         bne     a1, a3, L(shfth)
133         sd      t1, -8(a0)
134         b       L(last16)               # Handle anything which may be left
135         move    a2, t0
136
137         .set    reorder
138 END (memcpy)
139
140 #else /* !__mips64 */
141
142 #if __BYTE_ORDER == __BIG_ENDIAN
143 #  define LWHI  lwl             /* high part is left in big-endian      */
144 #  define SWHI  swl             /* high part is left in big-endian      */
145 #  define LWLO  lwr             /* low part is right in big-endian      */
146 #  define SWLO  swr             /* low part is right in big-endian      */
147 #else
148 #  define LWHI  lwr             /* high part is right in little-endian  */
149 #  define SWHI  swr             /* high part is right in little-endian  */
150 #  define LWLO  lwl             /* low part is left in little-endian    */
151 #  define SWLO  swl             /* low part is left in little-endian    */
152 #endif
153
154 ENTRY (memcpy)
155         .set    noreorder
156
157         slti    t0, a2, 8               # Less than 8?
158         bne     t0, zero, L(last8)
159         move    v0, a0                  # Setup exit value before too late
160
161         xor     t0, a1, a0              # Find a0/a1 displacement
162         andi    t0, 0x3
163         bne     t0, zero, L(shift)      # Go handle the unaligned case
164         subu    t1, zero, a1
165         andi    t1, 0x3                 # a0/a1 are aligned, but are we
166         beq     t1, zero, L(chk8w)      #  starting in the middle of a word?
167         subu    a2, t1
168         LWHI    t0, 0(a1)               # Yes we are... take care of that
169         addu    a1, t1
170         SWHI    t0, 0(a0)
171         addu    a0, t1
172
173 L(chk8w):       
174         andi    t0, a2, 0x1f            # 32 or more bytes left?
175         beq     t0, a2, L(chk1w)
176         subu    a3, a2, t0              # Yes
177         addu    a3, a1                  # a3 = end address of loop
178         move    a2, t0                  # a2 = what will be left after loop
179 L(lop8w):       
180         lw      t0,  0(a1)              # Loop taking 8 words at a time
181         lw      t1,  4(a1)
182         lw      t2,  8(a1)
183         lw      t3, 12(a1)
184         lw      t4, 16(a1)
185         lw      t5, 20(a1)
186         lw      t6, 24(a1)
187         lw      t7, 28(a1)
188         addiu   a0, 32
189         addiu   a1, 32
190         sw      t0, -32(a0)
191         sw      t1, -28(a0)
192         sw      t2, -24(a0)
193         sw      t3, -20(a0)
194         sw      t4, -16(a0)
195         sw      t5, -12(a0)
196         sw      t6,  -8(a0)
197         bne     a1, a3, L(lop8w)
198         sw      t7,  -4(a0)
199
200 L(chk1w):       
201         andi    t0, a2, 0x3             # 4 or more bytes left?
202         beq     t0, a2, L(last8)
203         subu    a3, a2, t0              # Yes, handle them one word at a time
204         addu    a3, a1                  # a3 again end address
205         move    a2, t0
206 L(lop1w):       
207         lw      t0, 0(a1)
208         addiu   a0, 4
209         addiu   a1, 4
210         bne     a1, a3, L(lop1w)
211         sw      t0, -4(a0)
212
213 L(last8):       
214         blez    a2, L(lst8e)            # Handle last 8 bytes, one at a time
215         addu    a3, a2, a1
216 L(lst8l):       
217         lb      t0, 0(a1)
218         addiu   a0, 1
219         addiu   a1, 1
220         bne     a1, a3, L(lst8l)
221         sb      t0, -1(a0)
222 L(lst8e):       
223         jr      ra                      # Bye, bye
224         nop
225
226 L(shift):       
227         subu    a3, zero, a0            # Src and Dest unaligned 
228         andi    a3, 0x3                 #  (unoptimized case...)
229         beq     a3, zero, L(shft1)
230         subu    a2, a3                  # a2 = bytes left
231         LWHI    t0, 0(a1)               # Take care of first odd part
232         LWLO    t0, 3(a1)
233         addu    a1, a3
234         SWHI    t0, 0(a0)
235         addu    a0, a3
236 L(shft1):       
237         andi    t0, a2, 0x3
238         subu    a3, a2, t0
239         addu    a3, a1
240 L(shfth):       
241         LWHI    t1, 0(a1)               # Limp through, word by word
242         LWLO    t1, 3(a1)
243         addiu   a0, 4
244         addiu   a1, 4
245         bne     a1, a3, L(shfth)
246         sw      t1, -4(a0)
247         b       L(last8)                # Handle anything which may be left
248         move    a2, t0
249
250         .set    reorder
251 END (memcpy)
252
253 #endif /* !__mips64 */
254
255 libc_hidden_def(memcpy)