1*84d9c625SLionel Sambuc/* $NetBSD: bzero.S,v 1.14 2013/09/12 15:36:15 joerg Exp $ */ 22fe8fb19SBen Gras 32fe8fb19SBen Gras/*- 42fe8fb19SBen Gras * Copyright (C) 2001 Martin J. Laubach <mjl@NetBSD.org> 52fe8fb19SBen Gras * All rights reserved. 62fe8fb19SBen Gras * 72fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without 82fe8fb19SBen Gras * modification, are permitted provided that the following conditions 92fe8fb19SBen Gras * are met: 102fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright 112fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer. 122fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright 132fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the 142fe8fb19SBen Gras * documentation and/or other materials provided with the distribution. 152fe8fb19SBen Gras * 3. The name of the author may not be used to endorse or promote products 162fe8fb19SBen Gras * derived from this software without specific prior written permission. 172fe8fb19SBen Gras * 182fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 192fe8fb19SBen Gras * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 202fe8fb19SBen Gras * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 212fe8fb19SBen Gras * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 222fe8fb19SBen Gras * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 232fe8fb19SBen Gras * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242fe8fb19SBen Gras * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252fe8fb19SBen Gras * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262fe8fb19SBen Gras * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272fe8fb19SBen Gras * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282fe8fb19SBen Gras */ 292fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 302fe8fb19SBen Gras 312fe8fb19SBen Gras#include <machine/asm.h> 322fe8fb19SBen Gras 332fe8fb19SBen Gras 342fe8fb19SBen Gras#if defined(LIBC_SCCS) && !defined(lint) 35*84d9c625SLionel Sambuc__RCSID("$NetBSD: bzero.S,v 1.14 2013/09/12 15:36:15 joerg Exp $") 362fe8fb19SBen Gras#endif /* LIBC_SCCS && !lint */ 372fe8fb19SBen Gras 38*84d9c625SLionel Sambuc#include "assym.h" 392fe8fb19SBen Gras 402fe8fb19SBen Gras#define USE_STSWX 0 /* don't. slower than trivial copy loop */ 412fe8fb19SBen Gras 422fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 432fe8fb19SBen Gras/* 442fe8fb19SBen Gras void bzero(void *b %r3, size_t len %r4); 452fe8fb19SBen Gras void * memset(void *b %r3, int c %r4, size_t len %r5); 462fe8fb19SBen Gras*/ 472fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 482fe8fb19SBen Gras 492fe8fb19SBen Gras#define r_dst %r3 502fe8fb19SBen Gras#define r_len %r4 512fe8fb19SBen Gras#define r_val %r0 522fe8fb19SBen Gras 532fe8fb19SBen Gras .text 542fe8fb19SBen Gras .align 4 552fe8fb19SBen GrasENTRY(bzero) 562fe8fb19SBen Gras li r_val, 0 /* Value to stuff in */ 572fe8fb19SBen Gras b cb_memset 582fe8fb19SBen GrasEND(bzero) 592fe8fb19SBen Gras 602fe8fb19SBen GrasENTRY(memset) 61e415d488SLionel Sambuc cmplwi %cr1, %r5, 0 622fe8fb19SBen Gras mr. %r0, %r4 632fe8fb19SBen Gras mr %r8, %r3 64e415d488SLionel Sambuc beqlr- %cr1 /* Nothing to do */ 652fe8fb19SBen Gras 662fe8fb19SBen Gras rlwimi %r0, %r4, 8, 16, 23 /* word extend fill value */ 672fe8fb19SBen Gras rlwimi %r0, %r0, 16, 0, 15 682fe8fb19SBen Gras mr %r4, %r5 692fe8fb19SBen Gras bne- simple_fill /* =! 0, use trivial fill */ 702fe8fb19SBen Grascb_memset: 712fe8fb19SBen Gras 722fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 732fe8fb19SBen Gras#ifndef _KERNEL 74*84d9c625SLionel Sambuc#ifdef __PIC__ 75*84d9c625SLionel Sambuc /* First get cache line size */ 762fe8fb19SBen Gras mflr %r9 77*84d9c625SLionel Sambuc bcl 20,31,1f 78*84d9c625SLionel Sambuc1: mflr %r10 792fe8fb19SBen Gras mtlr %r9 80*84d9c625SLionel Sambuc addis %r10,%r10,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE-1b@ha 81*84d9c625SLionel Sambuc lwz %r9,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE-1b@l(%r10) 822fe8fb19SBen Gras#else 83*84d9c625SLionel Sambuc lis %r10,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE@ha 84*84d9c625SLionel Sambuc lwz %r9,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE@l(%r10) 852fe8fb19SBen Gras#endif 86*84d9c625SLionel Sambuc cmplwi %cr1, %r9, 0 /* Unknown? */ 87*84d9c625SLionel Sambuc beq- simple_fill /* a trivial fill routine */ 882fe8fb19SBen Gras#else /* _KERNEL */ 892fe8fb19SBen Gras#ifdef MULTIPROCESSOR 902fe8fb19SBen Gras mfsprg %r10, 0 /* Get cpu_info pointer */ 912fe8fb19SBen Gras#else 922fe8fb19SBen Gras lis %r10, cpu_info_store@ha 932fe8fb19SBen Gras addi %r10, %r10, cpu_info_store@l 942fe8fb19SBen Gras#endif 95*84d9c625SLionel Sambuc lwz %r9, CPU_CI+CACHE_INFO_DCACHE_LINE_SIZE(%r10) /* Load D$ line size */ 96*84d9c625SLionel Sambuc#endif /* _KERNEL */ 972fe8fb19SBen Gras cntlzw %r10, %r9 /* Calculate shift.. */ 982fe8fb19SBen Gras li %r6, 31 992fe8fb19SBen Gras subf %r10, %r10, %r6 1002fe8fb19SBen Gras /* Back in memory filling business */ 1012fe8fb19SBen Gras 102e415d488SLionel Sambuc cmplwi %cr1, r_len, 0 /* Nothing to do? */ 1032fe8fb19SBen Gras add %r5, %r9, %r9 1042fe8fb19SBen Gras cmplw r_len, %r5 /* <= 2*CL bytes to move? */ 105e415d488SLionel Sambuc beqlr- %cr1 /* then do nothing */ 1062fe8fb19SBen Gras 1072fe8fb19SBen Gras blt+ simple_fill /* a trivial fill routine */ 1082fe8fb19SBen Gras 1092fe8fb19SBen Gras /* Word align the block, fill bytewise until dst even*/ 1102fe8fb19SBen Gras 1112fe8fb19SBen Gras andi. %r5, r_dst, 0x03 1122fe8fb19SBen Gras li %r6, 4 1132fe8fb19SBen Gras beq+ cb_aligned_w /* already aligned to word? */ 1142fe8fb19SBen Gras 1152fe8fb19SBen Gras subf %r5, %r5, %r6 /* bytes to fill to align4 */ 1162fe8fb19SBen Gras#if USE_STSWX 1172fe8fb19SBen Gras mtxer %r5 1182fe8fb19SBen Gras stswx %r0, 0, r_dst 1192fe8fb19SBen Gras add r_dst, %r5, r_dst 1202fe8fb19SBen Gras#else 1212fe8fb19SBen Gras mtctr %r5 1222fe8fb19SBen Gras 1232fe8fb19SBen Gras subi r_dst, r_dst, 1 1242fe8fb19SBen Gras1: stbu r_val, 1(r_dst) /* Fill bytewise */ 1252fe8fb19SBen Gras bdnz 1b 1262fe8fb19SBen Gras 1272fe8fb19SBen Gras addi r_dst, r_dst, 1 1282fe8fb19SBen Gras#endif 1292fe8fb19SBen Gras subf r_len, %r5, r_len 1302fe8fb19SBen Gras 1312fe8fb19SBen Grascb_aligned_w: /* Cache block align, fill wordwise until dst aligned */ 1322fe8fb19SBen Gras 1332fe8fb19SBen Gras /* I know I have something to do since we had > 2*CL initially */ 1342fe8fb19SBen Gras /* so no need to check for r_len = 0 */ 1352fe8fb19SBen Gras 1362fe8fb19SBen Gras subi %r6, %r9, 1 /* CL mask */ 1372fe8fb19SBen Gras and. %r5, r_dst, %r6 1382fe8fb19SBen Gras srwi %r5, %r5, 2 1392fe8fb19SBen Gras srwi %r6, %r9, 2 1402fe8fb19SBen Gras beq cb_aligned_cb /* already on CL boundary? */ 1412fe8fb19SBen Gras 1422fe8fb19SBen Gras subf %r5, %r5, %r6 /* words to fill to alignment */ 1432fe8fb19SBen Gras mtctr %r5 1442fe8fb19SBen Gras slwi %r5, %r5, 2 1452fe8fb19SBen Gras subf r_len, %r5, r_len 1462fe8fb19SBen Gras 1472fe8fb19SBen Gras subi r_dst, r_dst, 4 1482fe8fb19SBen Gras1: stwu r_val, 4(r_dst) /* Fill wordwise */ 1492fe8fb19SBen Gras bdnz 1b 1502fe8fb19SBen Gras addi r_dst, r_dst, 4 1512fe8fb19SBen Gras 1522fe8fb19SBen Grascb_aligned_cb: /* no need to check r_len, see above */ 1532fe8fb19SBen Gras 1542fe8fb19SBen Gras srw. %r5, r_len, %r10 /* Number of cache blocks */ 1552fe8fb19SBen Gras mtctr %r5 1562fe8fb19SBen Gras beq cblocks_done 1572fe8fb19SBen Gras 1582fe8fb19SBen Gras slw %r5, %r5, %r10 1592fe8fb19SBen Gras subf r_len, %r5, r_len 1602fe8fb19SBen Gras 1612fe8fb19SBen Gras1: dcbz 0, r_dst /* Clear blockwise */ 1622fe8fb19SBen Gras add r_dst, r_dst, %r9 1632fe8fb19SBen Gras bdnz 1b 1642fe8fb19SBen Gras 1652fe8fb19SBen Grascblocks_done: /* still CL aligned, but less than CL bytes left */ 166e415d488SLionel Sambuc cmplwi %cr1, r_len, 0 1672fe8fb19SBen Gras cmplwi r_len, 8 168e415d488SLionel Sambuc beq- %cr1, sf_return 1692fe8fb19SBen Gras 1702fe8fb19SBen Gras blt- sf_bytewise /* <8 remaining? */ 1712fe8fb19SBen Gras b sf_aligned_w 1722fe8fb19SBen Gras 1732fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 1742fe8fb19SBen Graswbzero: li r_val, 0 1752fe8fb19SBen Gras 1762fe8fb19SBen Gras cmplwi r_len, 0 1772fe8fb19SBen Gras beqlr- /* Nothing to do */ 1782fe8fb19SBen Gras 1792fe8fb19SBen Grassimple_fill: 1802fe8fb19SBen Gras#if USE_STSWX 181e415d488SLionel Sambuc cmplwi %cr1, r_len, 12 /* < 12 bytes to move? */ 1822fe8fb19SBen Gras#else 183e415d488SLionel Sambuc cmplwi %cr1, r_len, 8 /* < 8 bytes to move? */ 1842fe8fb19SBen Gras#endif 1852fe8fb19SBen Gras andi. %r5, r_dst, 0x03 /* bytes to fill to align4 */ 186e415d488SLionel Sambuc blt %cr1, sf_bytewise /* trivial byte mover */ 1872fe8fb19SBen Gras 1882fe8fb19SBen Gras li %r6, 4 1892fe8fb19SBen Gras subf %r5, %r5, %r6 1902fe8fb19SBen Gras beq+ sf_aligned_w /* dest is word aligned */ 1912fe8fb19SBen Gras 1922fe8fb19SBen Gras#if USE_STSWX 1932fe8fb19SBen Gras mtxer %r5 1942fe8fb19SBen Gras stswx %r0, 0, r_dst 1952fe8fb19SBen Gras add r_dst, %r5, r_dst 1962fe8fb19SBen Gras#else 1972fe8fb19SBen Gras mtctr %r5 /* nope, then fill bytewise */ 1982fe8fb19SBen Gras subi r_dst, r_dst, 1 /* until it is */ 1992fe8fb19SBen Gras1: stbu r_val, 1(r_dst) 2002fe8fb19SBen Gras bdnz 1b 2012fe8fb19SBen Gras 2022fe8fb19SBen Gras addi r_dst, r_dst, 1 2032fe8fb19SBen Gras#endif 2042fe8fb19SBen Gras subf r_len, %r5, r_len 2052fe8fb19SBen Gras 2062fe8fb19SBen Grassf_aligned_w: /* no need to check r_len since it were >= 8 bytes initially */ 2072fe8fb19SBen Gras#if USE_STSWX 2082fe8fb19SBen Gras mr %r6, %r0 2092fe8fb19SBen Gras mr %r7, %r0 2102fe8fb19SBen Gras 2112fe8fb19SBen Gras srwi %r5, r_len, 3 2122fe8fb19SBen Gras mtctr %r5 2132fe8fb19SBen Gras 2142fe8fb19SBen Gras slwi %r5, %r5, 3 /* adjust len */ 2152fe8fb19SBen Gras subf. r_len, %r5, r_len 2162fe8fb19SBen Gras 2172fe8fb19SBen Gras1: stswi %r6, r_dst, 8 2182fe8fb19SBen Gras addi r_dst, r_dst, 8 2192fe8fb19SBen Gras bdnz 1b 2202fe8fb19SBen Gras#else 2212fe8fb19SBen Gras srwi %r5, r_len, 2 /* words to fill */ 2222fe8fb19SBen Gras mtctr %r5 2232fe8fb19SBen Gras 2242fe8fb19SBen Gras slwi %r5, %r5, 2 2252fe8fb19SBen Gras subf. r_len, %r5, r_len /* adjust len for fill */ 2262fe8fb19SBen Gras 2272fe8fb19SBen Gras subi r_dst, r_dst, 4 2282fe8fb19SBen Gras1: stwu r_val, 4(r_dst) 2292fe8fb19SBen Gras bdnz 1b 2302fe8fb19SBen Gras addi r_dst, r_dst, 4 2312fe8fb19SBen Gras#endif 2322fe8fb19SBen Gras 2332fe8fb19SBen Grassf_word_done: bne- sf_bytewise 2342fe8fb19SBen Gras 2352fe8fb19SBen Grassf_return: mr %r3, %r8 /* restore orig ptr */ 2362fe8fb19SBen Gras blr /* for memset functionality */ 2372fe8fb19SBen Gras 2382fe8fb19SBen Grassf_bytewise: 2392fe8fb19SBen Gras#if USE_STSWX 2402fe8fb19SBen Gras mr %r5, %r0 2412fe8fb19SBen Gras mr %r6, %r0 2422fe8fb19SBen Gras mr %r7, %r0 2432fe8fb19SBen Gras 2442fe8fb19SBen Gras mtxer r_len 2452fe8fb19SBen Gras stswx %r5, 0, r_dst 2462fe8fb19SBen Gras#else 2472fe8fb19SBen Gras mtctr r_len 2482fe8fb19SBen Gras 2492fe8fb19SBen Gras subi r_dst, r_dst, 1 2502fe8fb19SBen Gras1: stbu r_val, 1(r_dst) 2512fe8fb19SBen Gras bdnz 1b 2522fe8fb19SBen Gras#endif 2532fe8fb19SBen Gras mr %r3, %r8 /* restore orig ptr */ 2542fe8fb19SBen Gras blr /* for memset functionality */ 2552fe8fb19SBen GrasEND(memset) 2562fe8fb19SBen Gras 2572fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 2582fe8fb19SBen Gras#ifndef _KERNEL 2592fe8fb19SBen Gras .data 260*84d9c625SLionel Sambuc .p2align 2 2612fe8fb19SBen Grascache_info: .long -1, -1, -1, -1 2622fe8fb19SBen Grascache_sh: .long 0 2632fe8fb19SBen Gras 2642fe8fb19SBen Gras#endif 2652fe8fb19SBen Gras/*----------------------------------------------------------------------*/ 266