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