OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libc / string / 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, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <features.h>
20 #include <sysdep.h>
21 #include <endian.h>
22
23 /* void *memset(void *s, int c, size_t n).  */
24
25 #ifdef __mips64
26
27 #include <sys/asm.h>
28
29 #if __BYTE_ORDER == __BIG_ENDIAN
30 # define SDHI   sdl             /* high part is left in big-endian      */
31 #else
32 # define SDHI   sdr             /* high part is right in little-endian  */
33 #endif
34
35 ENTRY (memset)
36         .set    noreorder
37
38         slti    ta1, a2, 16             # Less than 16?
39         bne     ta1, zero, L(last16)
40         move    v0, a0                  # Setup exit value before too late
41
42         beq     a1, zero, L(ueven)      # If zero pattern, no need to extend
43         andi    a1, 0xff                # Avoid problems with bogus arguments
44         dsll    ta0, a1, 8
45         or      a1, ta0
46         dsll    ta0, a1, 16
47         or      a1, ta0                 # a1 is now pattern in full word
48         dsll    ta0, a1, 32
49         or      a1, ta0                 # a1 is now pattern in double word
50
51 L(ueven):
52         PTR_SUBU ta0, zero, a0          # Unaligned address?
53         andi    ta0, 0x7
54         beq     ta0, zero, L(chkw)
55         PTR_SUBU a2, ta0
56         SDHI    a1, 0(a0)               # Yes, handle first unaligned part
57         PTR_ADDU a0, ta0                # Now both a0 and a2 are updated
58
59 L(chkw):
60         andi    ta0, a2, 0xf            # Enough left for one loop iteration?
61         beq     ta0, a2, L(chkl)
62         PTR_SUBU a3, a2, ta0
63         PTR_ADDU a3, a0                 # a3 is last loop address +1
64         move    a2, ta0                 # a2 is now # of bytes left after loop
65 L(loopw):
66         PTR_ADDIU a0, 16                # Handle 2 dwords pr. iteration
67         sd      a1, -16(a0)
68         bne     a0, a3, L(loopw)
69         sd      a1,  -8(a0)
70
71 L(chkl):
72         andi    ta0, a2, 0x8            # Check if there is at least a double
73         beq     ta0, zero, L(last16)    #  word remaining after the loop
74         PTR_SUBU a2, ta0
75         sd      a1, 0(a0)               # Yes...
76         PTR_ADDIU a0, 8
77
78 L(last16):
79         blez    a2, L(exit)             # Handle last 16 bytes (if cnt>0)
80         PTR_ADDU a3, a2, a0             # a3 is last address +1
81 L(lst16l):
82         PTR_ADDIU a0, 1
83         bne     a0, a3, L(lst16l)
84         sb      a1, -1(a0)
85 L(exit):
86         j       ra                      # Bye, bye
87         nop
88
89         .set    reorder
90 END (memset)
91
92 #else /* !__mips64 */
93
94 #if __BYTE_ORDER == __BIG_ENDIAN
95 # define SWHI   swl             /* high part is left in big-endian      */
96 #else
97 # define SWHI   swr             /* high part is right in little-endian  */
98 #endif
99
100 ENTRY (memset)
101         .set    noreorder
102
103         slti    t1, a2, 8               # Less than 8?
104         bne     t1, zero, L(last8)
105         move    v0, a0                  # Setup exit value before too late
106
107         beq     a1, zero, L(ueven)      # If zero pattern, no need to extend
108         andi    a1, 0xff                # Avoid problems with bogus arguments
109         sll     t0, a1, 8
110         or      a1, t0
111         sll     t0, a1, 16
112         or      a1, t0                  # a1 is now pattern in full word
113
114 L(ueven):       
115         subu    t0, zero, a0            # Unaligned address?
116         andi    t0, 0x3
117         beq     t0, zero, L(chkw)
118         subu    a2, t0
119         SWHI    a1, 0(a0)               # Yes, handle first unaligned part
120         addu    a0, t0                  # Now both a0 and a2 are updated
121
122 L(chkw):        
123         andi    t0, a2, 0x7             # Enough left for one loop iteration?
124         beq     t0, a2, L(chkl)
125         subu    a3, a2, t0
126         addu    a3, a0                  # a3 is last loop address +1
127         move    a2, t0                  # a2 is now # of bytes left after loop
128 L(loopw):       
129         addiu   a0, 8                   # Handle 2 words pr. iteration
130         sw      a1, -8(a0)
131         bne     a0, a3, L(loopw)
132         sw      a1, -4(a0)
133
134 L(chkl):        
135         andi    t0, a2, 0x4             # Check if there is at least a full
136         beq     t0, zero, L(last8)      #  word remaining after the loop
137         subu    a2, t0
138         sw      a1, 0(a0)               # Yes...
139         addiu   a0, 4
140
141 L(last8):       
142         blez    a2, L(exit)             # Handle last 8 bytes (if cnt>0)
143         addu    a3, a2, a0              # a3 is last address +1
144 L(lst8l):       
145         addiu   a0, 1
146         bne     a0, a3, L(lst8l)
147         sb      a1, -1(a0)
148 L(exit):        
149         j       ra                      # Bye, bye
150         nop
151
152         .set    reorder
153 END (memset)
154
155 #endif /* !__mips64 */
156
157 libc_hidden_def(memset)