2.5-18.1
[glibc.git] / powerpc-cpu / sysdeps / powerpc / powerpc32 / power4 / memset.S
blobb07ed3c2d3a851f17c8902494c7e1b6cf16964ec
1 /* Optimized memset implementation for PowerPC64.
2    Copyright (C) 1997,99, 2000,02,03, 2006 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston MA
18    02110-1301 USA.  */
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
24 /* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
25    Returns 's'.
27    The memset is done in three sizes: byte (8 bits), word (32 bits),
28    cache line (1024 bits). There is a special case for setting cache lines
29    to 0, to take advantage of the dcbz instruction.  */
31 EALIGN (BP_SYM (memset), 5, 0)
32         CALL_MCOUNT
34 #define rTMP    r0
35 #define rRTN    r3      /* Initial value of 1st argument.  */
36 #define rMEMP0  r3      /* Original value of 1st arg.  */
37 #define rCHR    r4      /* Char to set in each byte.  */
38 #define rLEN    r5      /* Length of region to set.  */
39 #define rMEMP   r6      /* Address at which we are storing.  */
40 #define rALIGN  r7      /* Number of bytes we are setting now (when aligning). */
41 #define rMEMP2  r8
43 #define rNEG64  r8      /* Constant -64 for clearing with dcbz.  */
44 #define rCLS    r8      /* Cache line size (known to be 128).  */
45 #define rCLM    r9      /* Cache line size mask to check for cache alignment.  */
46 L(_memset):
47 /* Take care of case for size <= 4.  */
48         cmplwi  cr1, rLEN, 4
49         andi.   rALIGN, rMEMP0, 3
50         mr      rMEMP, rMEMP0
51         ble-    cr1, L(small)
53 /* Align to word boundary.  */
54         cmplwi  cr5, rLEN, 31
55         rlwimi  rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
56         beq+    L(aligned)
57         mtcrf   0x01, rMEMP0
58         subfic  rALIGN, rALIGN, 4
59         add     rMEMP, rMEMP, rALIGN
60         sub     rLEN, rLEN, rALIGN
61         bf+     31, L(g0)
62         stb     rCHR, 0(rMEMP0)
63         bt      30, L(aligned)
64 L(g0):
65         sth     rCHR, -2(rMEMP)
67 /* Handle the case of size < 31.  */
68 L(aligned):
69         mtcrf   0x01, rLEN
70         rlwimi  rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
71         ble     cr5, L(medium)
72 /* Align to 32-byte boundary.  */
73         andi.   rALIGN, rMEMP, 0x1C
74         subfic  rALIGN, rALIGN, 0x20
75         beq     L(caligned)
76         mtcrf   0x01, rALIGN
77         add     rMEMP, rMEMP, rALIGN
78         sub     rLEN, rLEN, rALIGN
79         cmplwi  cr1, rALIGN, 0x10
80         mr      rMEMP2, rMEMP
81         bf      28, L(a1)
82         stw     rCHR, -4(rMEMP2)
83         stwu    rCHR, -8(rMEMP2)
84 L(a1):  blt     cr1, L(a2)
85         stw     rCHR, -4(rMEMP2)
86         stw     rCHR, -8(rMEMP2)
87         stw     rCHR, -12(rMEMP2)
88         stwu    rCHR, -16(rMEMP2)
89 L(a2):  bf      29, L(caligned)
90         stw     rCHR, -4(rMEMP2)
92 /* Now aligned to a 32 byte boundary.  */
93 L(caligned):
94         cmplwi  cr1, rCHR, 0
95         clrrwi. rALIGN, rLEN, 5
96         mtcrf   0x01, rLEN
97         beq     cr1, L(zloopstart) /* Special case for clearing memory using dcbz.  */
98 L(nondcbz):
99         srwi    rTMP, rALIGN, 5
100         mtctr   rTMP
101         beq     L(medium)       /* We may not actually get to do a full line.  */
102         clrlwi. rLEN, rLEN, 27
103         add     rMEMP, rMEMP, rALIGN
104         li      rNEG64, -0x40
105         bdz     L(cloopdone)
107         .align 4
108 L(c3):  dcbtst  rNEG64, rMEMP
109         stw     rCHR, -4(rMEMP)
110         stw     rCHR, -8(rMEMP)
111         stw     rCHR, -12(rMEMP)
112         stw     rCHR, -16(rMEMP)
113         stw     rCHR, -20(rMEMP)
114         stw     rCHR, -24(rMEMP)
115         stw     rCHR, -28(rMEMP)
116         stwu    rCHR, -32(rMEMP)
117         bdnz    L(c3)
118 L(cloopdone):
119         stw     rCHR, -4(rMEMP)
120         stw     rCHR, -8(rMEMP)
121         stw     rCHR, -12(rMEMP)
122         stw     rCHR, -16(rMEMP)
123         cmplwi  cr1, rLEN, 16
124         stw     rCHR, -20(rMEMP)
125         stw     rCHR, -24(rMEMP)
126         stw     rCHR, -28(rMEMP)
127         stwu    rCHR, -32(rMEMP)
128         beqlr
129         add     rMEMP, rMEMP, rALIGN
130         b       L(medium_tail2)
132         .align 5
133 /* Clear lines of memory in 128-byte chunks.  */
134 L(zloopstart):
135 /* If the remaining length is less the 32 bytes, don't bother getting
136          the cache line size.  */
137         beq     L(medium)
138         li      rCLS,128  /* cache line size is 128 */
139         dcbt    0,rMEMP
140 L(getCacheAligned):
141         cmplwi  cr1,rLEN,32
142         andi.   rTMP,rMEMP,127
143         blt     cr1,L(handletail32)
144         beq     L(cacheAligned)
145         addi    rMEMP,rMEMP,32
146         addi    rLEN,rLEN,-32
147         stw     rCHR,-32(rMEMP)
148         stw     rCHR,-28(rMEMP)
149         stw     rCHR,-24(rMEMP)
150         stw     rCHR,-20(rMEMP)
151         stw     rCHR,-16(rMEMP)
152         stw     rCHR,-12(rMEMP)
153         stw     rCHR,-8(rMEMP)
154         stw     rCHR,-4(rMEMP)
155         b       L(getCacheAligned)
157 /* Now we are aligned to the cache line and can use dcbz.  */
158         .align 4
159 L(cacheAligned):
160         cmplw   cr1,rLEN,rCLS
161         blt     cr1,L(handletail32)
162         dcbz    0,rMEMP
163         subf    rLEN,rCLS,rLEN
164         add     rMEMP,rMEMP,rCLS
165         b       L(cacheAligned)
167 /* We are here because the cache line size was set and the remainder 
168   (rLEN) is less than the actual cache line size.
169    So set up the preconditions for L(nondcbz) and go there.  */
170 L(handletail32):
171         clrrwi. rALIGN, rLEN, 5
172         b               L(nondcbz)
174         .align 5
175 L(small):
176 /* Memset of 4 bytes or less.  */
177         cmplwi  cr5, rLEN, 1
178         cmplwi  cr1, rLEN, 3
179         bltlr   cr5
180         stb     rCHR, 0(rMEMP)
181         beqlr   cr5
182         stb     rCHR, 1(rMEMP)
183         bltlr   cr1
184         stb     rCHR, 2(rMEMP)
185         beqlr   cr1
186         stb     rCHR, 3(rMEMP)
187         blr
189 /* Memset of 0-31 bytes.  */
190         .align 5
191 L(medium):
192         cmplwi  cr1, rLEN, 16
193 L(medium_tail2):
194         add     rMEMP, rMEMP, rLEN
195 L(medium_tail):
196         bt-     31, L(medium_31t)
197         bt-     30, L(medium_30t)
198 L(medium_30f):
199         bt-     29, L(medium_29t)
200 L(medium_29f):
201         bge-    cr1, L(medium_27t)
202         bflr-   28
203         stw     rCHR, -4(rMEMP)
204         stw     rCHR, -8(rMEMP)
205         blr
207 L(medium_31t):
208         stbu    rCHR, -1(rMEMP)
209         bf-     30, L(medium_30f)
210 L(medium_30t):
211         sthu    rCHR, -2(rMEMP)
212         bf-     29, L(medium_29f)
213 L(medium_29t):
214         stwu    rCHR, -4(rMEMP)
215         blt-    cr1, L(medium_27f)
216 L(medium_27t):
217         stw     rCHR, -4(rMEMP)
218         stw     rCHR, -8(rMEMP)
219         stw     rCHR, -12(rMEMP)
220         stwu    rCHR, -16(rMEMP)
221 L(medium_27f):
222         bflr-   28
223 L(medium_28t):
224         stw     rCHR, -4(rMEMP)
225         stw     rCHR, -8(rMEMP)
226         blr
227 END (BP_SYM (memset))
228 libc_hidden_builtin_def (memset)