1/* $NetBSD: bzero.S,v 1.14 2013/09/12 15:36:15 joerg Exp $ */ 2 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/*----------------------------------------------------------------------*/ 30 31#include <machine/asm.h> 32 33 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 */ 37 38#include "assym.h" 39 40#define USE_STSWX 0 /* don't. slower than trivial copy loop */ 41 42/*----------------------------------------------------------------------*/ 43/* 44 void bzero(void *b %r3, size_t len %r4); 45 void * memset(void *b %r3, int c %r4, size_t len %r5); 46*/ 47/*----------------------------------------------------------------------*/ 48 49#define r_dst %r3 50#define r_len %r4 51#define r_val %r0 52 53 .text 54 .align 4 55ENTRY(bzero) 56 li r_val, 0 /* Value to stuff in */ 57 b cb_memset 58END(bzero) 59 60ENTRY(memset) 61 cmplwi %cr1, %r5, 0 62 mr. %r0, %r4 63 mr %r8, %r3 64 beqlr- %cr1 /* Nothing to do */ 65 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 */ 70cb_memset: 71 72/*----------------------------------------------------------------------*/ 73#ifndef _KERNEL 74#ifdef __PIC__ 75 /* First get cache line size */ 76 mflr %r9 77 bcl 20,31,1f 781: 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 */ 106 107 blt+ simple_fill /* a trivial fill routine */ 108 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? */ 114 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 122 123 subi r_dst, r_dst, 1 1241: stbu r_val, 1(r_dst) /* Fill bytewise */ 125 bdnz 1b 126 127 addi r_dst, r_dst, 1 128#endif 129 subf r_len, %r5, r_len 130 131cb_aligned_w: /* Cache block align, fill wordwise until dst aligned */ 132 133 /* I know I have something to do since we had > 2*CL initially */ 134 /* so no need to check for r_len = 0 */ 135 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? */ 141 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 146 147 subi r_dst, r_dst, 4 1481: stwu r_val, 4(r_dst) /* Fill wordwise */ 149 bdnz 1b 150 addi r_dst, r_dst, 4 151 152cb_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 157 158 slw %r5, %r5, %r10 159 subf r_len, %r5, r_len 160 1611: dcbz 0, r_dst /* Clear blockwise */ 162 add r_dst, r_dst, %r9 163 bdnz 1b 164 165cblocks_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 169 170 blt- sf_bytewise /* <8 remaining? */ 171 b sf_aligned_w 172 173/*----------------------------------------------------------------------*/ 174wbzero: li r_val, 0 175 176 cmplwi r_len, 0 177 beqlr- /* Nothing to do */ 178 179simple_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 */ 187 188 li %r6, 4 189 subf %r5, %r5, %r6 190 beq+ sf_aligned_w /* dest is word aligned */ 191 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 */ 1991: stbu r_val, 1(r_dst) 200 bdnz 1b 201 202 addi r_dst, r_dst, 1 203#endif 204 subf r_len, %r5, r_len 205 206sf_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 210 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 2171: 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 223 224 slwi %r5, %r5, 2 225 subf. r_len, %r5, r_len /* adjust len for fill */ 226 227 subi r_dst, r_dst, 4 2281: stwu r_val, 4(r_dst) 229 bdnz 1b 230 addi r_dst, r_dst, 4 231#endif 232 233sf_word_done: bne- sf_bytewise 234 235sf_return: mr %r3, %r8 /* restore orig ptr */ 236 blr /* for memset functionality */ 237 238sf_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 248 249 subi r_dst, r_dst, 1 2501: stbu r_val, 1(r_dst) 251 bdnz 1b 252#endif 253 mr %r3, %r8 /* restore orig ptr */ 254 blr /* for memset functionality */ 255END(memset) 256 257/*----------------------------------------------------------------------*/ 258#ifndef _KERNEL 259 .data 260 .p2align 2 261cache_info: .long -1, -1, -1, -1 262cache_sh: .long 0 263 264#endif 265/*----------------------------------------------------------------------*/ 266