xref: /csrg-svn/lib/libc/sparc/string/bzero.s (revision 61174)
154400Storek/*
2*61174Sbostic * Copyright (c) 1992, 1993
3*61174Sbostic *	The Regents of the University of California.  All rights reserved.
454400Storek *
554400Storek * This software was developed by the Computer Systems Engineering group
654400Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
754400Storek * contributed to Berkeley.
854400Storek *
954400Storek * %sccs.include.redist.c%
1054400Storek *
1154400Storek * from: $Header: bzero.s,v 1.1 92/06/25 12:52:46 torek Exp $
1254400Storek */
1354400Storek
1454400Storek#if defined(LIBC_SCCS) && !defined(lint)
15*61174Sbostic	.asciz "@(#)bzero.s	8.1 (Berkeley) 06/04/93"
1654400Storek#endif  /* LIBC_SCCS and not lint */
1754400Storek
1854400Storek#include "DEFS.h"
1954400Storek
2054400Storek/*
2154400Storek * bzero(addr, len)
2254400Storek *
2354400Storek * We should unroll the loop, but at the moment this would
2454400Storek * gain nothing since the `std' instructions are what limits us.
2554400Storek */
2654400StorekENTRY(bzero)
2754400Storek	! %o0 = addr, %o1 = len
2854400Storek
2954400Storek	! Optimize a common case: addr and len are both multiples of 8.
3054400Storek	or	%o0, %o1, %o2
3154400Storek	btst	7, %o2			! ((addr | len) & 7) != 0?
3254400Storek	bnz	1f			! if so, cannot optimize
3354400Storek	 clr	%g1			! in any case, we want g1=0
3454400Storek
3554400Storek	/* `Good' operands, can just store doubles. */
3654400Storek0:
3754400Storek	deccc	8, %o1			! while ((len -= 8) >= 0)
3854400Storek	bge,a	0b
3954400Storek	 std	%g0, [%o0 + %o1]	!	*(quad *)(addr + len) = 0;
4054400Storek	retl
4154400Storek	nop
4254400Storek
4354400Storek	/*
4454400Storek	 * Either the address is unaligned, or the count is not a
4554400Storek	 * multiple of 8, or both.  We will have to align the address
4654400Storek	 * in order to use anything `better' than stb.
4754400Storek	 */
4854400Storek1:
4954400Storek	cmp	%o1, 15			! len >= 15?
5054400Storek	bge,a	Lstd			! yes, use std
5154400Storek	 btst	1, %o0			! (but first check alignment)
5254400Storek
5354400Storek	! not enough to bother: do byte-at-a-time loop.
5454400Storek2:
5554400Storek	deccc	%o1			! while (--len >= 0)
5654400Storek	bge,a	2b
5754400Storek	 stb	%g0, [%o0 + %o1]	!	addr[len] = 0;
5854400Storek	retl
5954400Storek	 nop
6054400Storek
6154400StorekLstd:
6254400Storek	/*
6354400Storek	 * There are at least 15 bytes to zero.
6454400Storek	 * We may have to zero some initial stuff to align
6554400Storek	 * the address.
6654400Storek	 */
6754400Storek	bz,a	1f			! if (addr & 1) {
6854400Storek	 btst	2, %o0
6954400Storek	stb	%g0, [%o0]		!	*addr = 0;
7054400Storek	inc	%o0			!	addr++;
7154400Storek	dec	%o1			!	len--;
7254400Storek	btst	2, %o0			! }
7354400Storek1:
7454400Storek	bz,a	1f			! if (addr & 2) {
7554400Storek	 btst	4, %o0
7654400Storek	sth	%g0, [%o0]		!	*(short *)addr = 0;
7754400Storek	inc	2, %o0			!	addr += 2;
7854400Storek	dec	2, %o1			!	len -= 2;
7954400Storek	btst	4, %o0			! }
8054400Storek1:
8154400Storek	bz	1f			! if (addr & 4) {
8254400Storek	 dec	8, %o1
8354400Storek	st	%g0, [%o0]		!	*(int *)addr = 0;
8454400Storek	inc	4, %o0			!	addr += 4;
8554400Storek	dec	4, %o1			!	len -= 4;
8654400Storek					! }
8754400Storek	/*
8854400Storek	 * Address is double word aligned; len is 8 less than
8954400Storek	 * the number of bytes remaining (i.e., len is 0 if
9054400Storek	 * the remaining count is 8, 1 if it is 9, etc.).
9154400Storek	 */
9254400Storek1:
9354400Storek	std	%g0, [%o0]		! do {
9454400Storek2:					!	*(quad *)addr = 0;
9554400Storek	inc	8, %o0			!	addr += 8;
9654400Storek	deccc	8, %o1			! } while ((len -= 8) >= 0);
9754400Storek	 bge,a	2b
9854400Storek	std	%g0, [%o0]
9954400Storek
10054400Storek	/*
10154400Storek	 * Len is in [-8..-1] where -8 => done, -7 => 1 byte to zero,
10254400Storek	 * -6 => two bytes, etc.  Mop up this remainder, if any.
10354400Storek	 */
10454400Storek	btst	4, %o1
10554400Storek	bz	1f			! if (len & 4) {
10654400Storek	 btst	2, %o1
10754400Storek	st	%g0, [%o0]		!	*(int *)addr = 0;
10854400Storek	inc	4, %o0			!	addr += 4;
10954400Storek1:
11054400Storek	bz	1f			! if (len & 2) {
11154400Storek	 btst	1, %o1
11254400Storek	sth	%g0, [%o0]		!	*(short *)addr = 0;
11354400Storek	inc	2, %o0			!	addr += 2;
11454400Storek1:
11554400Storek	bnz,a	1f			! if (len & 1)
11654400Storek	 stb	%g0, [%o0]		!	*addr = 0;
11754400Storek1:
11854400Storek	retl
11954400Storek	 nop
120