* sysdeps/mips/memcpy.S: Map t0-3 to a4-7 on new abis. * sysdeps/mips/memset.S: Likew...
[platform/upstream/glibc.git] / sysdeps / mips / memset.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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <endian.h>
22
23
24 /* void *memset(void *s, int c, size_t n).
25
26    This routine could be optimized further for MIPS64, but this is left
27    as an exercise for the future. When it is done, the file should be kept
28    as a sisterfile to this one, and placed in the sysdeps/mips/mips64 
29    directory.  */
30
31 #if __BYTE_ORDER == __BIG_ENDIAN
32 # define SWHI   swl             /* high part is left in big-endian      */
33 #else
34 # define SWHI   swr             /* high part is right in little-endian  */
35 #endif
36
37 #ifndef t0
38 # define t0 a4
39 #endif
40 #ifndef t1
41 # define t1 a5
42 #endif
43
44 ENTRY (memset)
45         .set    noreorder
46
47         slti    t1, a2, 8               # Less than 8?
48         bne     t1, zero, L(last8)
49         move    v0, a0                  # Setup exit value before too late
50
51         beq     a1, zero, L(ueven)      # If zero pattern, no need to extend
52         andi    a1, 0xff                # Avoid problems with bogus arguments
53         sll     t0, a1, 8
54         or      a1, t0
55         sll     t0, a1, 16
56         or      a1, t0                  # a1 is now pattern in full word
57
58 L(ueven):       subu    t0, zero, a0            # Unaligned address?
59         andi    t0, 0x3
60         beq     t0, zero, L(chkw)
61         subu    a2, t0
62         SWHI    a1, 0(a0)               # Yes, handle first unaligned part
63         addu    a0, t0                  # Now both a0 and a2 are updated
64
65 L(chkw):        andi    t0, a2, 0x7             # Enough left for one loop iteration?
66         beq     t0, a2, L(chkl)
67         subu    a3, a2, t0
68         addu    a3, a0                  # a3 is last loop address +1
69         move    a2, t0                  # a2 is now # of bytes left after loop
70 L(loopw):       addiu   a0, 8                   # Handle 2 words pr. iteration
71         sw      a1, -8(a0)
72         bne     a0, a3, L(loopw)
73         sw      a1, -4(a0)
74
75 L(chkl):        andi    t0, a2, 0x4             # Check if there is at least a full
76         beq     t0, zero, L(last8)      #  word remaining after the loop
77         subu    a2, t0
78         sw      a1, 0(a0)               # Yes...
79         addiu   a0, 4
80
81 L(last8):       blez    a2, L(exit)             # Handle last 8 bytes (if cnt>0)
82         addu    a3, a2, a0              # a3 is last address +1
83 L(lst8l):       addiu   a0, 1
84         bne     a0, a3, L(lst8l)
85         sb      a1, -1(a0)
86 L(exit):        j       ra                      # Bye, bye
87         nop
88
89         .set    reorder
90 END (memset)