xref: /minix3/lib/libc/arch/powerpc/string/bzero.S (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
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