xref: /csrg-svn/lib/libc/sparc/string/bzero.s (revision 54400)
1*54400Storek/*
2*54400Storek * Copyright (c) 1992 The Regents of the University of California.
3*54400Storek * All rights reserved.
4*54400Storek *
5*54400Storek * This software was developed by the Computer Systems Engineering group
6*54400Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*54400Storek * contributed to Berkeley.
8*54400Storek *
9*54400Storek * %sccs.include.redist.c%
10*54400Storek *
11*54400Storek * from: $Header: bzero.s,v 1.1 92/06/25 12:52:46 torek Exp $
12*54400Storek */
13*54400Storek
14*54400Storek#if defined(LIBC_SCCS) && !defined(lint)
15*54400Storek	.asciz "@(#)bzero.s	5.1 (Berkeley) 06/25/92"
16*54400Storek#endif  /* LIBC_SCCS and not lint */
17*54400Storek
18*54400Storek#include "DEFS.h"
19*54400Storek
20*54400Storek/*
21*54400Storek * bzero(addr, len)
22*54400Storek *
23*54400Storek * We should unroll the loop, but at the moment this would
24*54400Storek * gain nothing since the `std' instructions are what limits us.
25*54400Storek */
26*54400StorekENTRY(bzero)
27*54400Storek	! %o0 = addr, %o1 = len
28*54400Storek
29*54400Storek	! Optimize a common case: addr and len are both multiples of 8.
30*54400Storek	or	%o0, %o1, %o2
31*54400Storek	btst	7, %o2			! ((addr | len) & 7) != 0?
32*54400Storek	bnz	1f			! if so, cannot optimize
33*54400Storek	 clr	%g1			! in any case, we want g1=0
34*54400Storek
35*54400Storek	/* `Good' operands, can just store doubles. */
36*54400Storek0:
37*54400Storek	deccc	8, %o1			! while ((len -= 8) >= 0)
38*54400Storek	bge,a	0b
39*54400Storek	 std	%g0, [%o0 + %o1]	!	*(quad *)(addr + len) = 0;
40*54400Storek	retl
41*54400Storek	nop
42*54400Storek
43*54400Storek	/*
44*54400Storek	 * Either the address is unaligned, or the count is not a
45*54400Storek	 * multiple of 8, or both.  We will have to align the address
46*54400Storek	 * in order to use anything `better' than stb.
47*54400Storek	 */
48*54400Storek1:
49*54400Storek	cmp	%o1, 15			! len >= 15?
50*54400Storek	bge,a	Lstd			! yes, use std
51*54400Storek	 btst	1, %o0			! (but first check alignment)
52*54400Storek
53*54400Storek	! not enough to bother: do byte-at-a-time loop.
54*54400Storek2:
55*54400Storek	deccc	%o1			! while (--len >= 0)
56*54400Storek	bge,a	2b
57*54400Storek	 stb	%g0, [%o0 + %o1]	!	addr[len] = 0;
58*54400Storek	retl
59*54400Storek	 nop
60*54400Storek
61*54400StorekLstd:
62*54400Storek	/*
63*54400Storek	 * There are at least 15 bytes to zero.
64*54400Storek	 * We may have to zero some initial stuff to align
65*54400Storek	 * the address.
66*54400Storek	 */
67*54400Storek	bz,a	1f			! if (addr & 1) {
68*54400Storek	 btst	2, %o0
69*54400Storek	stb	%g0, [%o0]		!	*addr = 0;
70*54400Storek	inc	%o0			!	addr++;
71*54400Storek	dec	%o1			!	len--;
72*54400Storek	btst	2, %o0			! }
73*54400Storek1:
74*54400Storek	bz,a	1f			! if (addr & 2) {
75*54400Storek	 btst	4, %o0
76*54400Storek	sth	%g0, [%o0]		!	*(short *)addr = 0;
77*54400Storek	inc	2, %o0			!	addr += 2;
78*54400Storek	dec	2, %o1			!	len -= 2;
79*54400Storek	btst	4, %o0			! }
80*54400Storek1:
81*54400Storek	bz	1f			! if (addr & 4) {
82*54400Storek	 dec	8, %o1
83*54400Storek	st	%g0, [%o0]		!	*(int *)addr = 0;
84*54400Storek	inc	4, %o0			!	addr += 4;
85*54400Storek	dec	4, %o1			!	len -= 4;
86*54400Storek					! }
87*54400Storek	/*
88*54400Storek	 * Address is double word aligned; len is 8 less than
89*54400Storek	 * the number of bytes remaining (i.e., len is 0 if
90*54400Storek	 * the remaining count is 8, 1 if it is 9, etc.).
91*54400Storek	 */
92*54400Storek1:
93*54400Storek	std	%g0, [%o0]		! do {
94*54400Storek2:					!	*(quad *)addr = 0;
95*54400Storek	inc	8, %o0			!	addr += 8;
96*54400Storek	deccc	8, %o1			! } while ((len -= 8) >= 0);
97*54400Storek	 bge,a	2b
98*54400Storek	std	%g0, [%o0]
99*54400Storek
100*54400Storek	/*
101*54400Storek	 * Len is in [-8..-1] where -8 => done, -7 => 1 byte to zero,
102*54400Storek	 * -6 => two bytes, etc.  Mop up this remainder, if any.
103*54400Storek	 */
104*54400Storek	btst	4, %o1
105*54400Storek	bz	1f			! if (len & 4) {
106*54400Storek	 btst	2, %o1
107*54400Storek	st	%g0, [%o0]		!	*(int *)addr = 0;
108*54400Storek	inc	4, %o0			!	addr += 4;
109*54400Storek1:
110*54400Storek	bz	1f			! if (len & 2) {
111*54400Storek	 btst	1, %o1
112*54400Storek	sth	%g0, [%o0]		!	*(short *)addr = 0;
113*54400Storek	inc	2, %o0			!	addr += 2;
114*54400Storek1:
115*54400Storek	bnz,a	1f			! if (len & 1)
116*54400Storek	 stb	%g0, [%o0]		!	*addr = 0;
117*54400Storek1:
118*54400Storek	retl
119*54400Storek	 nop
120