tools/llvm: Do not build with symbols
[minix3.git] / lib / libc / arch / powerpc / string / bzero.S
blob9c632b6688f54bab903b567eb29b6eb14610216a
1 /*      $NetBSD: bzero.S,v 1.14 2013/09/12 15:36:15 joerg Exp $ */
3 /*-
4  * Copyright (C) 2001   Martin J. Laubach <mjl@NetBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*----------------------------------------------------------------------*/
31 #include <machine/asm.h>
34 #if defined(LIBC_SCCS) && !defined(lint)
35 __RCSID("$NetBSD: bzero.S,v 1.14 2013/09/12 15:36:15 joerg Exp $")
36 #endif /* LIBC_SCCS && !lint */
38 #include "assym.h"
40 #define USE_STSWX 0     /* don't. slower than trivial copy loop */
42 /*----------------------------------------------------------------------*/
44      void bzero(void *b %r3, size_t len %r4);
45      void * memset(void *b %r3, int c %r4, size_t len %r5);
47 /*----------------------------------------------------------------------*/
49 #define r_dst   %r3
50 #define r_len   %r4
51 #define r_val   %r0
53                 .text
54                 .align 4
55 ENTRY(bzero)
56                 li      r_val, 0                /* Value to stuff in */
57                 b       cb_memset
58 END(bzero)
60 ENTRY(memset)
61                 cmplwi  %cr1, %r5, 0
62                 mr.     %r0, %r4
63                 mr      %r8, %r3
64                 beqlr-  %cr1                    /* Nothing to do */
66                 rlwimi  %r0, %r4, 8, 16, 23     /* word extend fill value */
67                 rlwimi  %r0, %r0, 16, 0, 15
68                 mr      %r4, %r5
69                 bne-    simple_fill             /* =! 0, use trivial fill */
70 cb_memset:
72 /*----------------------------------------------------------------------*/
73 #ifndef _KERNEL
74 #ifdef __PIC__
75                 /* First get cache line size */
76                 mflr    %r9
77                 bcl     20,31,1f
78 1:              mflr    %r10
79                 mtlr    %r9
80                 addis   %r10,%r10,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE-1b@ha
81                 lwz     %r9,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE-1b@l(%r10)
82 #else
83                 lis     %r10,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE@ha
84                 lwz     %r9,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE@l(%r10)
85 #endif
86                 cmplwi  %cr1, %r9, 0            /* Unknown? */
87                 beq-    simple_fill             /* a trivial fill routine */
88 #else /* _KERNEL */
89 #ifdef  MULTIPROCESSOR
90                 mfsprg  %r10, 0                 /* Get cpu_info pointer */
91 #else
92                 lis     %r10, cpu_info_store@ha
93                 addi    %r10, %r10, cpu_info_store@l
94 #endif
95                 lwz     %r9, CPU_CI+CACHE_INFO_DCACHE_LINE_SIZE(%r10)   /* Load D$ line size */
96 #endif /* _KERNEL */
97                 cntlzw  %r10, %r9                       /* Calculate shift.. */
98                 li      %r6, 31
99                 subf    %r10, %r10, %r6
100                 /* Back in memory filling business */
101                 
102                 cmplwi  %cr1, r_len, 0          /* Nothing to do? */
103                 add     %r5, %r9, %r9
104                 cmplw   r_len, %r5              /* <= 2*CL bytes to move? */
105                 beqlr-  %cr1                    /* then do nothing */
107                 blt+    simple_fill             /* a trivial fill routine */
109                 /* Word align the block, fill bytewise until dst even*/
110                 
111                 andi.   %r5, r_dst, 0x03        
112                 li      %r6, 4
113                 beq+    cb_aligned_w            /* already aligned to word? */
115                 subf    %r5, %r5, %r6           /* bytes to fill to align4 */
116 #if USE_STSWX
117                 mtxer   %r5
118                 stswx   %r0, 0, r_dst
119                 add     r_dst, %r5, r_dst
120 #else
121                 mtctr   %r5
123                 subi    r_dst, r_dst, 1
124 1:              stbu    r_val, 1(r_dst)         /* Fill bytewise */
125                 bdnz    1b
127                 addi    r_dst, r_dst, 1
128 #endif
129                 subf    r_len, %r5, r_len
131 cb_aligned_w:   /* Cache block align, fill wordwise until dst aligned */
133                 /* I know I have something to do since we had > 2*CL initially */
134                 /* so no need to check for r_len = 0 */
136                 subi    %r6, %r9, 1             /* CL mask */
137                 and.    %r5, r_dst, %r6
138                 srwi    %r5, %r5, 2
139                 srwi    %r6, %r9, 2
140                 beq     cb_aligned_cb           /* already on CL boundary? */
142                 subf    %r5, %r5, %r6           /* words to fill to alignment */
143                 mtctr   %r5
144                 slwi    %r5, %r5, 2
145                 subf    r_len, %r5, r_len
147                 subi    r_dst, r_dst, 4
148 1:              stwu    r_val, 4(r_dst)         /* Fill wordwise */
149                 bdnz    1b
150                 addi    r_dst, r_dst, 4
152 cb_aligned_cb:  /* no need to check r_len, see above */
153                 
154                 srw.    %r5, r_len, %r10                /* Number of cache blocks */
155                 mtctr   %r5
156                 beq     cblocks_done
158                 slw     %r5, %r5, %r10
159                 subf    r_len, %r5, r_len
161 1:              dcbz    0, r_dst                /* Clear blockwise */
162                 add     r_dst, r_dst, %r9
163                 bdnz    1b
165 cblocks_done:   /* still CL aligned, but less than CL bytes left */
166                 cmplwi  %cr1, r_len, 0
167                 cmplwi  r_len, 8
168                 beq-    %cr1, sf_return
170                 blt-    sf_bytewise             /* <8 remaining? */
171                 b       sf_aligned_w
173 /*----------------------------------------------------------------------*/
174 wbzero:         li      r_val, 0
176                 cmplwi  r_len, 0
177                 beqlr-                          /* Nothing to do */
179 simple_fill:
180 #if USE_STSWX
181                 cmplwi  %cr1, r_len, 12         /* < 12 bytes to move? */
182 #else
183                 cmplwi  %cr1, r_len, 8          /* < 8 bytes to move? */
184 #endif
185                 andi.   %r5, r_dst, 0x03                /* bytes to fill to align4 */
186                 blt     %cr1, sf_bytewise       /* trivial byte mover */
188                 li      %r6, 4
189                 subf    %r5, %r5, %r6
190                 beq+    sf_aligned_w            /* dest is word aligned */
192 #if USE_STSWX
193                 mtxer   %r5
194                 stswx   %r0, 0, r_dst
195                 add     r_dst, %r5, r_dst
196 #else
197                 mtctr   %r5                     /* nope, then fill bytewise */
198                 subi    r_dst, r_dst, 1         /* until it is */
199 1:              stbu    r_val, 1(r_dst)         
200                 bdnz    1b
202                 addi    r_dst, r_dst, 1
203 #endif
204                 subf    r_len, %r5, r_len
206 sf_aligned_w:   /* no need to check r_len since it were >= 8 bytes initially */
207 #if USE_STSWX
208                 mr      %r6, %r0
209                 mr      %r7, %r0
211                 srwi    %r5, r_len, 3
212                 mtctr   %r5
213                 
214                 slwi    %r5, %r5, 3             /* adjust len */
215                 subf.   r_len, %r5, r_len
216                 
217 1:              stswi   %r6, r_dst, 8
218                 addi    r_dst, r_dst, 8
219                 bdnz    1b
220 #else
221                 srwi    %r5, r_len, 2           /* words to fill */
222                 mtctr   %r5
224                 slwi    %r5, %r5, 2
225                 subf.   r_len, %r5, r_len       /* adjust len for fill */
227                 subi    r_dst, r_dst, 4
228 1:              stwu    r_val, 4(r_dst)
229                 bdnz    1b
230                 addi    r_dst, r_dst, 4
231 #endif
233 sf_word_done:   bne-    sf_bytewise
235 sf_return:      mr      %r3, %r8                        /* restore orig ptr */
236                 blr                             /* for memset functionality */
238 sf_bytewise:
239 #if USE_STSWX
240                 mr      %r5, %r0
241                 mr      %r6, %r0
242                 mr      %r7, %r0
243                 
244                 mtxer   r_len
245                 stswx   %r5, 0, r_dst
246 #else
247                 mtctr   r_len
249                 subi    r_dst, r_dst, 1
250 1:              stbu    r_val, 1(r_dst)
251                 bdnz    1b
252 #endif
253                 mr      %r3, %r8                        /* restore orig ptr */
254                 blr                             /* for memset functionality */
255 END(memset)
257 /*----------------------------------------------------------------------*/
258 #ifndef _KERNEL
259                 .data
260                 .p2align 2
261 cache_info:     .long   -1, -1, -1, -1
262 cache_sh:       .long   0
264 #endif
265 /*----------------------------------------------------------------------*/