xref: /titanic_51/usr/src/uts/sun4v/cpu/generic_copy.s (revision c2b6e926ea57d0ba055f91471cfc9772c7fbacd0)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5651ee059Siskreen * Common Development and Distribution License (the "License").
6651ee059Siskreen * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22651ee059Siskreen * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
26*c2b6e926Sae112802# ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate#include <sys/param.h>
297c478bd9Sstevel@tonic-gate#include <sys/errno.h>
307c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
317c478bd9Sstevel@tonic-gate#include <sys/vtrace.h>
327c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
337c478bd9Sstevel@tonic-gate#include <sys/clock.h>
347c478bd9Sstevel@tonic-gate#include <sys/asi.h>
357c478bd9Sstevel@tonic-gate#include <sys/fsr.h>
367c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate#if !defined(lint)
397c478bd9Sstevel@tonic-gate#include "assym.h"
407c478bd9Sstevel@tonic-gate#endif	/* lint */
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate/*
447c478bd9Sstevel@tonic-gate * Less then or equal this number of bytes we will always copy byte-for-byte
457c478bd9Sstevel@tonic-gate */
467c478bd9Sstevel@tonic-gate#define	SMALL_LIMIT	7
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate/*
49473b13d4Sae112802 * LOFAULT_SET : Flag set by kzero and kcopy to indicate that t_lofault
50473b13d4Sae112802 * handler was set
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate#define	LOFAULT_SET 2
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate/*
567c478bd9Sstevel@tonic-gate * Copy a block of storage, returning an error code if `from' or
577c478bd9Sstevel@tonic-gate * `to' takes a kernel pagefault which cannot be resolved.
587c478bd9Sstevel@tonic-gate * Returns errno value on pagefault error, 0 if all ok
597c478bd9Sstevel@tonic-gate */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate#if defined(lint)
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate/* ARGSUSED */
667c478bd9Sstevel@tonic-gateint
677c478bd9Sstevel@tonic-gatekcopy(const void *from, void *to, size_t count)
687c478bd9Sstevel@tonic-gate{ return(0); }
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate#else	/* lint */
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate	.seg	".text"
737c478bd9Sstevel@tonic-gate	.align	4
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate	ENTRY(kcopy)
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
78473b13d4Sae112802	set	.copyerr, %l7			! copyerr is lofault value
79473b13d4Sae112802	ldn	[THREAD_REG + T_LOFAULT], %o5	! save existing handler
80473b13d4Sae112802	or	%o5, LOFAULT_SET, %o5
81473b13d4Sae112802	membar	#Sync				! sync error barrier
827c478bd9Sstevel@tonic-gate	b	.do_copy			! common code
83473b13d4Sae112802	stn	%l7, [THREAD_REG + T_LOFAULT]	! set t_lofault
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate/*
867c478bd9Sstevel@tonic-gate * We got here because of a fault during kcopy.
877c478bd9Sstevel@tonic-gate * Errno value is in %g1.
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate.copyerr:
90473b13d4Sae112802	! The kcopy() *always* sets a t_lofault handler and it ORs LOFAULT_SET
91473b13d4Sae112802	! into %o5 to indicate it has set t_lofault handler. Need to clear
92473b13d4Sae112802	! LOFAULT_SET flag before restoring the error handler.
93473b13d4Sae112802	andn	%o5, LOFAULT_SET, %o5
947c478bd9Sstevel@tonic-gate	membar	#Sync			! sync error barrier
957c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
967c478bd9Sstevel@tonic-gate	ret
977c478bd9Sstevel@tonic-gate	restore	%g1, 0, %o0
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate	SET_SIZE(kcopy)
1007c478bd9Sstevel@tonic-gate#endif	/* lint */
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate/*
1047c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to).
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate#if defined(lint)
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate/* ARGSUSED */
1097c478bd9Sstevel@tonic-gatevoid
1107c478bd9Sstevel@tonic-gatebcopy(const void *from, void *to, size_t count)
1117c478bd9Sstevel@tonic-gate{}
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate#else	/* lint */
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate	ENTRY(bcopy)
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
118473b13d4Sae112802	clr	%o5			! flag LOFAULT_SET is not set for bcopy
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate.do_copy:
121651ee059Siskreen        mov     %i1, %g5                ! save dest addr start
122651ee059Siskreen
123651ee059Siskreen        mov     %i2, %l6                ! save size
124651ee059Siskreen
1257c478bd9Sstevel@tonic-gate	cmp	%i2, 12			! for small counts
1267c478bd9Sstevel@tonic-gate	blu	%ncc, .bytecp		! just copy bytes
1277c478bd9Sstevel@tonic-gate	  .empty
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate	!
1307c478bd9Sstevel@tonic-gate	! use aligned transfers where possible
1317c478bd9Sstevel@tonic-gate	!
1327c478bd9Sstevel@tonic-gate	xor	%i0, %i1, %o4		! xor from and to address
1337c478bd9Sstevel@tonic-gate	btst	7, %o4			! if lower three bits zero
1347c478bd9Sstevel@tonic-gate	bz	.aldoubcp		! can align on double boundary
1357c478bd9Sstevel@tonic-gate	.empty	! assembler complaints about label
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate	xor	%i0, %i1, %o4		! xor from and to address
1387c478bd9Sstevel@tonic-gate	btst	3, %o4			! if lower two bits zero
1397c478bd9Sstevel@tonic-gate	bz	.alwordcp		! can align on word boundary
1407c478bd9Sstevel@tonic-gate	btst	3, %i0			! delay slot, from address unaligned?
1417c478bd9Sstevel@tonic-gate	!
1427c478bd9Sstevel@tonic-gate	! use aligned reads and writes where possible
1437c478bd9Sstevel@tonic-gate	! this differs from wordcp in that it copes
1447c478bd9Sstevel@tonic-gate	! with odd alignment between source and destnation
1457c478bd9Sstevel@tonic-gate	! using word reads and writes with the proper shifts
1467c478bd9Sstevel@tonic-gate	! in between to align transfers to and from memory
1477c478bd9Sstevel@tonic-gate	! i0 - src address, i1 - dest address, i2 - count
1487c478bd9Sstevel@tonic-gate	! i3, i4 - tmps for used generating complete word
1497c478bd9Sstevel@tonic-gate	! i5 (word to write)
1507c478bd9Sstevel@tonic-gate	! l0 size in bits of upper part of source word (US)
1517c478bd9Sstevel@tonic-gate	! l1 size in bits of lower part of source word (LS = 32 - US)
1527c478bd9Sstevel@tonic-gate	! l2 size in bits of upper part of destination word (UD)
1537c478bd9Sstevel@tonic-gate	! l3 size in bits of lower part of destination word (LD = 32 - UD)
1547c478bd9Sstevel@tonic-gate	! l4 number of bytes leftover after aligned transfers complete
1557c478bd9Sstevel@tonic-gate	! l5 the number 32
1567c478bd9Sstevel@tonic-gate	!
1577c478bd9Sstevel@tonic-gate	mov	32, %l5			! load an oft-needed constant
1587c478bd9Sstevel@tonic-gate	bz	.align_dst_only
1597c478bd9Sstevel@tonic-gate	btst	3, %i1			! is destnation address aligned?
1607c478bd9Sstevel@tonic-gate	clr	%i4			! clear registers used in either case
1617c478bd9Sstevel@tonic-gate	bz	.align_src_only
1627c478bd9Sstevel@tonic-gate	clr	%l0
1637c478bd9Sstevel@tonic-gate	!
1647c478bd9Sstevel@tonic-gate	! both source and destination addresses are unaligned
1657c478bd9Sstevel@tonic-gate	!
1667c478bd9Sstevel@tonic-gate1:					! align source
1677c478bd9Sstevel@tonic-gate	ldub	[%i0], %i3		! read a byte from source address
1687c478bd9Sstevel@tonic-gate	add	%i0, 1, %i0		! increment source address
1697c478bd9Sstevel@tonic-gate	or	%i4, %i3, %i4		! or in with previous bytes (if any)
1707c478bd9Sstevel@tonic-gate	btst	3, %i0			! is source aligned?
1717c478bd9Sstevel@tonic-gate	add	%l0, 8, %l0		! increment size of upper source (US)
1727c478bd9Sstevel@tonic-gate	bnz,a	1b
1737c478bd9Sstevel@tonic-gate	sll	%i4, 8, %i4		! make room for next byte
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate	sub	%l5, %l0, %l1		! generate shift left count (LS)
1767c478bd9Sstevel@tonic-gate	sll	%i4, %l1, %i4		! prepare to get rest
1777c478bd9Sstevel@tonic-gate	ld	[%i0], %i3		! read a word
1787c478bd9Sstevel@tonic-gate	add	%i0, 4, %i0		! increment source address
1797c478bd9Sstevel@tonic-gate	srl	%i3, %l0, %i5		! upper src bits into lower dst bits
1807c478bd9Sstevel@tonic-gate	or	%i4, %i5, %i5		! merge
1817c478bd9Sstevel@tonic-gate	mov	24, %l3			! align destination
1827c478bd9Sstevel@tonic-gate1:
1837c478bd9Sstevel@tonic-gate	srl	%i5, %l3, %i4		! prepare to write a single byte
1847c478bd9Sstevel@tonic-gate	stb	%i4, [%i1]		! write a byte
1857c478bd9Sstevel@tonic-gate	add	%i1, 1, %i1		! increment destination address
1867c478bd9Sstevel@tonic-gate	sub	%i2, 1, %i2		! decrement count
1877c478bd9Sstevel@tonic-gate	btst	3, %i1			! is destination aligned?
1887c478bd9Sstevel@tonic-gate	bnz,a	1b
1897c478bd9Sstevel@tonic-gate	sub	%l3, 8, %l3		! delay slot, decrement shift count (LD)
1907c478bd9Sstevel@tonic-gate	sub	%l5, %l3, %l2		! generate shift left count (UD)
1917c478bd9Sstevel@tonic-gate	sll	%i5, %l2, %i5		! move leftover into upper bytes
1927c478bd9Sstevel@tonic-gate	cmp	%l2, %l0		! cmp # reqd to fill dst w old src left
1937c478bd9Sstevel@tonic-gate	bgu	%ncc, .more_needed	! need more to fill than we have
1947c478bd9Sstevel@tonic-gate	nop
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate	sll	%i3, %l1, %i3		! clear upper used byte(s)
1977c478bd9Sstevel@tonic-gate	srl	%i3, %l1, %i3
1987c478bd9Sstevel@tonic-gate	! get the odd bytes between alignments
1997c478bd9Sstevel@tonic-gate	sub	%l0, %l2, %l0		! regenerate shift count
2007c478bd9Sstevel@tonic-gate	sub	%l5, %l0, %l1		! generate new shift left count (LS)
2017c478bd9Sstevel@tonic-gate	and	%i2, 3, %l4		! must do remaining bytes if count%4 > 0
2027c478bd9Sstevel@tonic-gate	andn	%i2, 3, %i2		! # of aligned bytes that can be moved
2037c478bd9Sstevel@tonic-gate	srl	%i3, %l0, %i4
2047c478bd9Sstevel@tonic-gate	or	%i5, %i4, %i5
2057c478bd9Sstevel@tonic-gate	st	%i5, [%i1]		! write a word
2067c478bd9Sstevel@tonic-gate	subcc	%i2, 4, %i2		! decrement count
2077c478bd9Sstevel@tonic-gate	bz	%ncc, .unalign_out
2087c478bd9Sstevel@tonic-gate	add	%i1, 4, %i1		! increment destination address
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate	b	2f
2117c478bd9Sstevel@tonic-gate	sll	%i3, %l1, %i5		! get leftover into upper bits
2127c478bd9Sstevel@tonic-gate.more_needed:
2137c478bd9Sstevel@tonic-gate	sll	%i3, %l0, %i3		! save remaining byte(s)
2147c478bd9Sstevel@tonic-gate	srl	%i3, %l0, %i3
2157c478bd9Sstevel@tonic-gate	sub	%l2, %l0, %l1		! regenerate shift count
2167c478bd9Sstevel@tonic-gate	sub	%l5, %l1, %l0		! generate new shift left count
2177c478bd9Sstevel@tonic-gate	sll	%i3, %l1, %i4		! move to fill empty space
2187c478bd9Sstevel@tonic-gate	b	3f
2197c478bd9Sstevel@tonic-gate	or	%i5, %i4, %i5		! merge to complete word
2207c478bd9Sstevel@tonic-gate	!
2217c478bd9Sstevel@tonic-gate	! the source address is aligned and destination is not
2227c478bd9Sstevel@tonic-gate	!
2237c478bd9Sstevel@tonic-gate.align_dst_only:
2247c478bd9Sstevel@tonic-gate	ld	[%i0], %i4		! read a word
2257c478bd9Sstevel@tonic-gate	add	%i0, 4, %i0		! increment source address
2267c478bd9Sstevel@tonic-gate	mov	24, %l0			! initial shift alignment count
2277c478bd9Sstevel@tonic-gate1:
2287c478bd9Sstevel@tonic-gate	srl	%i4, %l0, %i3		! prepare to write a single byte
2297c478bd9Sstevel@tonic-gate	stb	%i3, [%i1]		! write a byte
2307c478bd9Sstevel@tonic-gate	add	%i1, 1, %i1		! increment destination address
2317c478bd9Sstevel@tonic-gate	sub	%i2, 1, %i2		! decrement count
2327c478bd9Sstevel@tonic-gate	btst	3, %i1			! is destination aligned?
2337c478bd9Sstevel@tonic-gate	bnz,a	1b
2347c478bd9Sstevel@tonic-gate	sub	%l0, 8, %l0		! delay slot, decrement shift count
2357c478bd9Sstevel@tonic-gate.xfer:
2367c478bd9Sstevel@tonic-gate	sub	%l5, %l0, %l1		! generate shift left count
2377c478bd9Sstevel@tonic-gate	sll	%i4, %l1, %i5		! get leftover
2387c478bd9Sstevel@tonic-gate3:
2397c478bd9Sstevel@tonic-gate	and	%i2, 3, %l4		! must do remaining bytes if count%4 > 0
2407c478bd9Sstevel@tonic-gate	andn	%i2, 3, %i2		! # of aligned bytes that can be moved
2417c478bd9Sstevel@tonic-gate2:
2427c478bd9Sstevel@tonic-gate	ld	[%i0], %i3		! read a source word
2437c478bd9Sstevel@tonic-gate	add	%i0, 4, %i0		! increment source address
2447c478bd9Sstevel@tonic-gate	srl	%i3, %l0, %i4		! upper src bits into lower dst bits
2457c478bd9Sstevel@tonic-gate	or	%i5, %i4, %i5		! merge with upper dest bits (leftover)
2467c478bd9Sstevel@tonic-gate	st	%i5, [%i1]		! write a destination word
2477c478bd9Sstevel@tonic-gate	subcc	%i2, 4, %i2		! decrement count
2487c478bd9Sstevel@tonic-gate	bz	%ncc, .unalign_out	! check if done
2497c478bd9Sstevel@tonic-gate	add	%i1, 4, %i1		! increment destination address
2507c478bd9Sstevel@tonic-gate	b	2b			! loop
2517c478bd9Sstevel@tonic-gate	sll	%i3, %l1, %i5		! get leftover
2527c478bd9Sstevel@tonic-gate.unalign_out:
2537c478bd9Sstevel@tonic-gate	tst	%l4			! any bytes leftover?
2547c478bd9Sstevel@tonic-gate	bz	%ncc, .cpdone
2557c478bd9Sstevel@tonic-gate	.empty				! allow next instruction in delay slot
2567c478bd9Sstevel@tonic-gate1:
2577c478bd9Sstevel@tonic-gate	sub	%l0, 8, %l0		! decrement shift
2587c478bd9Sstevel@tonic-gate	srl	%i3, %l0, %i4		! upper src byte into lower dst byte
2597c478bd9Sstevel@tonic-gate	stb	%i4, [%i1]		! write a byte
2607c478bd9Sstevel@tonic-gate	subcc	%l4, 1, %l4		! decrement count
2617c478bd9Sstevel@tonic-gate	bz	%ncc, .cpdone		! done?
2627c478bd9Sstevel@tonic-gate	add	%i1, 1, %i1		! increment destination
2637c478bd9Sstevel@tonic-gate	tst	%l0			! any more previously read bytes
2647c478bd9Sstevel@tonic-gate	bnz	%ncc, 1b		! we have leftover bytes
2657c478bd9Sstevel@tonic-gate	mov	%l4, %i2		! delay slot, mv cnt where dbytecp wants
2667c478bd9Sstevel@tonic-gate	b	.dbytecp		! let dbytecp do the rest
2677c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0		! i0 gets the difference of src and dst
2687c478bd9Sstevel@tonic-gate	!
2697c478bd9Sstevel@tonic-gate	! the destination address is aligned and the source is not
2707c478bd9Sstevel@tonic-gate	!
2717c478bd9Sstevel@tonic-gate.align_src_only:
2727c478bd9Sstevel@tonic-gate	ldub	[%i0], %i3		! read a byte from source address
2737c478bd9Sstevel@tonic-gate	add	%i0, 1, %i0		! increment source address
2747c478bd9Sstevel@tonic-gate	or	%i4, %i3, %i4		! or in with previous bytes (if any)
2757c478bd9Sstevel@tonic-gate	btst	3, %i0			! is source aligned?
2767c478bd9Sstevel@tonic-gate	add	%l0, 8, %l0		! increment shift count (US)
2777c478bd9Sstevel@tonic-gate	bnz,a	.align_src_only
2787c478bd9Sstevel@tonic-gate	sll	%i4, 8, %i4		! make room for next byte
2797c478bd9Sstevel@tonic-gate	b,a	.xfer
2807c478bd9Sstevel@tonic-gate	!
2817c478bd9Sstevel@tonic-gate	! if from address unaligned for double-word moves,
2827c478bd9Sstevel@tonic-gate	! move bytes till it is, if count is < 56 it could take
2837c478bd9Sstevel@tonic-gate	! longer to align the thing than to do the transfer
2847c478bd9Sstevel@tonic-gate	! in word size chunks right away
2857c478bd9Sstevel@tonic-gate	!
2867c478bd9Sstevel@tonic-gate.aldoubcp:
2877c478bd9Sstevel@tonic-gate	cmp	%i2, 56			! if count < 56, use wordcp, it takes
2887c478bd9Sstevel@tonic-gate	blu,a	%ncc, .alwordcp		! longer to align doubles than words
2897c478bd9Sstevel@tonic-gate	mov	3, %o0			! mask for word alignment
2907c478bd9Sstevel@tonic-gate	call	.alignit		! copy bytes until aligned
2917c478bd9Sstevel@tonic-gate	mov	7, %o0			! mask for double alignment
2927c478bd9Sstevel@tonic-gate	!
2937c478bd9Sstevel@tonic-gate	! source and destination are now double-word aligned
2947c478bd9Sstevel@tonic-gate	! i3 has aligned count returned by alignit
2957c478bd9Sstevel@tonic-gate	!
2967c478bd9Sstevel@tonic-gate	and	%i2, 7, %i2		! unaligned leftover count
2977c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0		! i0 gets the difference of src and dst
2987c478bd9Sstevel@tonic-gate5:
2997c478bd9Sstevel@tonic-gate	ldx	[%i0+%i1], %o4		! read from address
3007c478bd9Sstevel@tonic-gate	stx	%o4, [%i1]		! write at destination address
3017c478bd9Sstevel@tonic-gate	subcc	%i3, 8, %i3		! dec count
3027c478bd9Sstevel@tonic-gate	bgu	%ncc, 5b
3037c478bd9Sstevel@tonic-gate	add	%i1, 8, %i1		! delay slot, inc to address
3047c478bd9Sstevel@tonic-gate	cmp	%i2, 4			! see if we can copy a word
3057c478bd9Sstevel@tonic-gate	blu	%ncc, .dbytecp		! if 3 or less bytes use bytecp
3067c478bd9Sstevel@tonic-gate	.empty
3077c478bd9Sstevel@tonic-gate	!
3087c478bd9Sstevel@tonic-gate	! for leftover bytes we fall into wordcp, if needed
3097c478bd9Sstevel@tonic-gate	!
3107c478bd9Sstevel@tonic-gate.wordcp:
3117c478bd9Sstevel@tonic-gate	and	%i2, 3, %i2		! unaligned leftover count
3127c478bd9Sstevel@tonic-gate5:
3137c478bd9Sstevel@tonic-gate	ld	[%i0+%i1], %o4		! read from address
3147c478bd9Sstevel@tonic-gate	st	%o4, [%i1]		! write at destination address
3157c478bd9Sstevel@tonic-gate	subcc	%i3, 4, %i3		! dec count
3167c478bd9Sstevel@tonic-gate	bgu	%ncc, 5b
3177c478bd9Sstevel@tonic-gate	add	%i1, 4, %i1		! delay slot, inc to address
3187c478bd9Sstevel@tonic-gate	b,a	.dbytecp
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate	! we come here to align copies on word boundaries
3217c478bd9Sstevel@tonic-gate.alwordcp:
3227c478bd9Sstevel@tonic-gate	call	.alignit		! go word-align it
3237c478bd9Sstevel@tonic-gate	mov	3, %o0			! bits that must be zero to be aligned
3247c478bd9Sstevel@tonic-gate	b	.wordcp
3257c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0		! i0 gets the difference of src and dst
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate	!
3287c478bd9Sstevel@tonic-gate	! byte copy, works with any alignment
3297c478bd9Sstevel@tonic-gate	!
3307c478bd9Sstevel@tonic-gate.bytecp:
3317c478bd9Sstevel@tonic-gate	b	.dbytecp
3327c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0		! i0 gets difference of src and dst
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate	!
3357c478bd9Sstevel@tonic-gate	! differenced byte copy, works with any alignment
3367c478bd9Sstevel@tonic-gate	! assumes dest in %i1 and (source - dest) in %i0
3377c478bd9Sstevel@tonic-gate	!
3387c478bd9Sstevel@tonic-gate1:
3397c478bd9Sstevel@tonic-gate	stb	%o4, [%i1]		! write to address
3407c478bd9Sstevel@tonic-gate	inc	%i1			! inc to address
3417c478bd9Sstevel@tonic-gate.dbytecp:
3427c478bd9Sstevel@tonic-gate	deccc	%i2			! dec count
3437c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 1b		! loop till done
3447c478bd9Sstevel@tonic-gate	ldub	[%i0+%i1], %o4		! read from address
3457c478bd9Sstevel@tonic-gate.cpdone:
3467c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
347473b13d4Sae112802	! Restore t_lofault handler, if came here from kcopy().
348473b13d4Sae112802	tst	%o5
349473b13d4Sae112802	bz	%ncc, 1f
350473b13d4Sae112802	andn	%o5, LOFAULT_SET, %o5
351473b13d4Sae112802	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
352473b13d4Sae1128021:
353651ee059Siskreen        mov     %g5, %o0                ! copy dest address
354651ee059Siskreen        call    sync_icache
355651ee059Siskreen        mov     %l6, %o1                ! saved size
3567c478bd9Sstevel@tonic-gate	ret
3577c478bd9Sstevel@tonic-gate	restore %g0, 0, %o0		! return (0)
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate/*
3607c478bd9Sstevel@tonic-gate * Common code used to align transfers on word and doubleword
3617c478bd9Sstevel@tonic-gate * boudaries.  Aligns source and destination and returns a count
3627c478bd9Sstevel@tonic-gate * of aligned bytes to transfer in %i3
3637c478bd9Sstevel@tonic-gate */
3647c478bd9Sstevel@tonic-gate1:
3657c478bd9Sstevel@tonic-gate	inc	%i0			! inc from
3667c478bd9Sstevel@tonic-gate	stb	%o4, [%i1]		! write a byte
3677c478bd9Sstevel@tonic-gate	inc	%i1			! inc to
3687c478bd9Sstevel@tonic-gate	dec	%i2			! dec count
3697c478bd9Sstevel@tonic-gate.alignit:
3707c478bd9Sstevel@tonic-gate	btst	%o0, %i0		! %o0 is bit mask to check for alignment
3717c478bd9Sstevel@tonic-gate	bnz,a	1b
3727c478bd9Sstevel@tonic-gate	ldub	[%i0], %o4		! read next byte
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate	retl
3757c478bd9Sstevel@tonic-gate	andn	%i2, %o0, %i3		! return size of aligned bytes
3767c478bd9Sstevel@tonic-gate	SET_SIZE(bcopy)
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate#endif	/* lint */
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate/*
3817c478bd9Sstevel@tonic-gate * Block copy with possibly overlapped operands.
3827c478bd9Sstevel@tonic-gate */
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate#if defined(lint)
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3877c478bd9Sstevel@tonic-gatevoid
3887c478bd9Sstevel@tonic-gateovbcopy(const void *from, void *to, size_t count)
3897c478bd9Sstevel@tonic-gate{}
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate#else	/* lint */
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate	ENTRY(ovbcopy)
3947c478bd9Sstevel@tonic-gate	tst	%o2			! check count
3957c478bd9Sstevel@tonic-gate	bgu,a	%ncc, 1f		! nothing to do or bad arguments
3967c478bd9Sstevel@tonic-gate	subcc	%o0, %o1, %o3		! difference of from and to address
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate	retl				! return
3997c478bd9Sstevel@tonic-gate	nop
4007c478bd9Sstevel@tonic-gate1:
4017c478bd9Sstevel@tonic-gate	bneg,a	%ncc, 2f
4027c478bd9Sstevel@tonic-gate	neg	%o3			! if < 0, make it positive
4037c478bd9Sstevel@tonic-gate2:	cmp	%o2, %o3		! cmp size and abs(from - to)
4047c478bd9Sstevel@tonic-gate	bleu	%ncc, bcopy		! if size <= abs(diff): use bcopy,
4057c478bd9Sstevel@tonic-gate	.empty				!   no overlap
4067c478bd9Sstevel@tonic-gate	cmp	%o0, %o1		! compare from and to addresses
4077c478bd9Sstevel@tonic-gate	blu	%ncc, .ov_bkwd		! if from < to, copy backwards
4087c478bd9Sstevel@tonic-gate	nop
4097c478bd9Sstevel@tonic-gate	!
4107c478bd9Sstevel@tonic-gate	! Copy forwards.
4117c478bd9Sstevel@tonic-gate	!
4127c478bd9Sstevel@tonic-gate.ov_fwd:
4137c478bd9Sstevel@tonic-gate	ldub	[%o0], %o3		! read from address
4147c478bd9Sstevel@tonic-gate	inc	%o0			! inc from address
4157c478bd9Sstevel@tonic-gate	stb	%o3, [%o1]		! write to address
4167c478bd9Sstevel@tonic-gate	deccc	%o2			! dec count
4177c478bd9Sstevel@tonic-gate	bgu	%ncc, .ov_fwd		! loop till done
4187c478bd9Sstevel@tonic-gate	inc	%o1			! inc to address
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate	retl				! return
4217c478bd9Sstevel@tonic-gate	nop
4227c478bd9Sstevel@tonic-gate	!
4237c478bd9Sstevel@tonic-gate	! Copy backwards.
4247c478bd9Sstevel@tonic-gate	!
4257c478bd9Sstevel@tonic-gate.ov_bkwd:
4267c478bd9Sstevel@tonic-gate	deccc	%o2			! dec count
4277c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o2], %o3	! get byte at end of src
4287c478bd9Sstevel@tonic-gate	bgu	%ncc, .ov_bkwd		! loop till done
4297c478bd9Sstevel@tonic-gate	stb	%o3, [%o1 + %o2]	! delay slot, store at end of dst
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate	retl				! return
4327c478bd9Sstevel@tonic-gate	nop
4337c478bd9Sstevel@tonic-gate	SET_SIZE(ovbcopy)
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate#endif	/* lint */
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate/*
4387c478bd9Sstevel@tonic-gate * hwblkpagecopy()
4397c478bd9Sstevel@tonic-gate *
4407c478bd9Sstevel@tonic-gate * Copies exactly one page.  This routine assumes the caller (ppcopy)
4417c478bd9Sstevel@tonic-gate * has already disabled kernel preemption and has checked
4427c478bd9Sstevel@tonic-gate * use_hw_bcopy.
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate#ifdef lint
4457c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4467c478bd9Sstevel@tonic-gatevoid
4477c478bd9Sstevel@tonic-gatehwblkpagecopy(const void *src, void *dst)
4487c478bd9Sstevel@tonic-gate{ }
4497c478bd9Sstevel@tonic-gate#else /* lint */
4507c478bd9Sstevel@tonic-gate	ENTRY(hwblkpagecopy)
4517c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate	! %i0 - source address (arg)
4547c478bd9Sstevel@tonic-gate	! %i1 - destination address (arg)
4557c478bd9Sstevel@tonic-gate	! %i2 - length of region (not arg)
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate	set	PAGESIZE, %i2
458651ee059Siskreen	mov     %i1,    %o0     ! store destination address for flushing
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate	/*
4617c478bd9Sstevel@tonic-gate	 * Copying exactly one page and PAGESIZE is in mutliple of 0x80.
4627c478bd9Sstevel@tonic-gate	 */
4637c478bd9Sstevel@tonic-gate1:
4647c478bd9Sstevel@tonic-gate	ldx	[%i0+0x0], %l0
4657c478bd9Sstevel@tonic-gate	ldx	[%i0+0x8], %l1
4667c478bd9Sstevel@tonic-gate	ldx	[%i0+0x10], %l2
4677c478bd9Sstevel@tonic-gate	ldx	[%i0+0x18], %l3
4687c478bd9Sstevel@tonic-gate	ldx	[%i0+0x20], %l4
4697c478bd9Sstevel@tonic-gate	ldx	[%i0+0x28], %l5
4707c478bd9Sstevel@tonic-gate	ldx	[%i0+0x30], %l6
4717c478bd9Sstevel@tonic-gate	ldx	[%i0+0x38], %l7
4727c478bd9Sstevel@tonic-gate	stx	%l0, [%i1+0x0]
4737c478bd9Sstevel@tonic-gate	stx	%l1, [%i1+0x8]
4747c478bd9Sstevel@tonic-gate	stx	%l2, [%i1+0x10]
4757c478bd9Sstevel@tonic-gate	stx	%l3, [%i1+0x18]
4767c478bd9Sstevel@tonic-gate	stx	%l4, [%i1+0x20]
4777c478bd9Sstevel@tonic-gate	stx	%l5, [%i1+0x28]
4787c478bd9Sstevel@tonic-gate	stx	%l6, [%i1+0x30]
4797c478bd9Sstevel@tonic-gate	stx	%l7, [%i1+0x38]
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate	ldx	[%i0+0x40], %l0
4827c478bd9Sstevel@tonic-gate	ldx	[%i0+0x48], %l1
4837c478bd9Sstevel@tonic-gate	ldx	[%i0+0x50], %l2
4847c478bd9Sstevel@tonic-gate	ldx	[%i0+0x58], %l3
4857c478bd9Sstevel@tonic-gate	ldx	[%i0+0x60], %l4
4867c478bd9Sstevel@tonic-gate	ldx	[%i0+0x68], %l5
4877c478bd9Sstevel@tonic-gate	ldx	[%i0+0x70], %l6
4887c478bd9Sstevel@tonic-gate	ldx	[%i0+0x78], %l7
4897c478bd9Sstevel@tonic-gate	stx	%l0, [%i1+0x40]
4907c478bd9Sstevel@tonic-gate	stx	%l1, [%i1+0x48]
4917c478bd9Sstevel@tonic-gate	stx	%l2, [%i1+0x50]
4927c478bd9Sstevel@tonic-gate	stx	%l3, [%i1+0x58]
4937c478bd9Sstevel@tonic-gate	stx	%l4, [%i1+0x60]
4947c478bd9Sstevel@tonic-gate	stx	%l5, [%i1+0x68]
4957c478bd9Sstevel@tonic-gate	stx	%l6, [%i1+0x70]
4967c478bd9Sstevel@tonic-gate	stx	%l7, [%i1+0x78]
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate	add	%i0, 0x80, %i0
4997c478bd9Sstevel@tonic-gate	subcc	%i2, 0x80, %i2
5007c478bd9Sstevel@tonic-gate	bgu,pt	%xcc, 1b
5017c478bd9Sstevel@tonic-gate	add	%i1, 0x80, %i1
5027c478bd9Sstevel@tonic-gate
503651ee059Siskreen	! %o0 contains the dest. address
504651ee059Siskreen	set	PAGESIZE, %o1
505651ee059Siskreen	call	sync_icache
506651ee059Siskreen	nop
507651ee059Siskreen
5087c478bd9Sstevel@tonic-gate	membar #Sync
5097c478bd9Sstevel@tonic-gate	ret
5107c478bd9Sstevel@tonic-gate	restore	%g0, 0, %o0
5117c478bd9Sstevel@tonic-gate	SET_SIZE(hwblkpagecopy)
5127c478bd9Sstevel@tonic-gate#endif	/* lint */
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate/*
5167c478bd9Sstevel@tonic-gate * Transfer data to and from user space -
5177c478bd9Sstevel@tonic-gate * Note that these routines can cause faults
5187c478bd9Sstevel@tonic-gate * It is assumed that the kernel has nothing at
5197c478bd9Sstevel@tonic-gate * less than KERNELBASE in the virtual address space.
5207c478bd9Sstevel@tonic-gate *
5217c478bd9Sstevel@tonic-gate * Note that copyin(9F) and copyout(9F) are part of the
5227c478bd9Sstevel@tonic-gate * DDI/DKI which specifies that they return '-1' on "errors."
5237c478bd9Sstevel@tonic-gate *
5247c478bd9Sstevel@tonic-gate * Sigh.
5257c478bd9Sstevel@tonic-gate *
5267c478bd9Sstevel@tonic-gate * So there's two extremely similar routines - xcopyin() and xcopyout()
5277c478bd9Sstevel@tonic-gate * which return the errno that we've faithfully computed.  This
5287c478bd9Sstevel@tonic-gate * allows other callers (e.g. uiomove(9F)) to work correctly.
5297c478bd9Sstevel@tonic-gate * Given that these are used pretty heavily, we expand the calling
5307c478bd9Sstevel@tonic-gate * sequences inline for all flavours (rather than making wrappers).
5317c478bd9Sstevel@tonic-gate *
5327c478bd9Sstevel@tonic-gate * There are also stub routines for xcopyout_little and xcopyin_little,
5337c478bd9Sstevel@tonic-gate * which currently are intended to handle requests of <= 16 bytes from
5347c478bd9Sstevel@tonic-gate * do_unaligned. Future enhancement to make them handle 8k pages efficiently
5357c478bd9Sstevel@tonic-gate * is left as an exercise...
5367c478bd9Sstevel@tonic-gate */
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate/*
5397c478bd9Sstevel@tonic-gate * Copy user data to kernel space (copyOP/xcopyOP/copyOP_noerr)
5407c478bd9Sstevel@tonic-gate *
5417c478bd9Sstevel@tonic-gate * General theory of operation:
5427c478bd9Sstevel@tonic-gate *
5437c478bd9Sstevel@tonic-gate * None of the copyops routines grab a window.
5447c478bd9Sstevel@tonic-gate *
5457c478bd9Sstevel@tonic-gate * Flow:
5467c478bd9Sstevel@tonic-gate *
5477c478bd9Sstevel@tonic-gate * If count == zero return zero.
5487c478bd9Sstevel@tonic-gate *
5497c478bd9Sstevel@tonic-gate * Store the previous lo_fault handler into %g6.
5507c478bd9Sstevel@tonic-gate * Place our secondary lofault handler into %g5.
5517c478bd9Sstevel@tonic-gate * Place the address of our fault handler into %o3.
5527c478bd9Sstevel@tonic-gate *
5537c478bd9Sstevel@tonic-gate * If count is less than or equal to SMALL_LIMIT (7) we
5547c478bd9Sstevel@tonic-gate * always do a byte for byte copy.
5557c478bd9Sstevel@tonic-gate *
5567c478bd9Sstevel@tonic-gate * If count is > SMALL_LIMIT, we check the alignment of the input
5577c478bd9Sstevel@tonic-gate * and output pointers.  We store -count in %o3, we store the number
5587c478bd9Sstevel@tonic-gate * of chunks (8, 4, 2 or 1 byte) operated on in our basic copy loop
5597c478bd9Sstevel@tonic-gate * in %o2. Following this we branch to the appropriate copy loop and
5607c478bd9Sstevel@tonic-gate * copy that many chunks.  Since we've been adding the chunk size
5617c478bd9Sstevel@tonic-gate * to %o3 each time through as well as decrementing %o2, we can tell
5627c478bd9Sstevel@tonic-gate * if any data is is left to be copied by examining %o3. If that is
5637c478bd9Sstevel@tonic-gate * zero, we're done and can go home. If not, we figure out what the
5647c478bd9Sstevel@tonic-gate * largest chunk size left to be copied is and branch to that copy
5657c478bd9Sstevel@tonic-gate * loop unless there's only one byte left. We load that as we're
5667c478bd9Sstevel@tonic-gate * branching to code that stores it just before we return.
5677c478bd9Sstevel@tonic-gate *
5687c478bd9Sstevel@tonic-gate * Fault handlers are invoked if we reference memory that has no
5697c478bd9Sstevel@tonic-gate * current mapping.  All forms share the same copyio_fault handler.
5707c478bd9Sstevel@tonic-gate * This routine handles fixing up the stack and general housecleaning.
5717c478bd9Sstevel@tonic-gate * Each copy operation has a simple fault handler that is then called
5727c478bd9Sstevel@tonic-gate * to do the work specific to the invidual operation.  The handler
5737c478bd9Sstevel@tonic-gate * for copyOP and xcopyOP are found at the end of individual function.
5747c478bd9Sstevel@tonic-gate * The handlers for xcopyOP_little are found at the end of xcopyin_little.
5757c478bd9Sstevel@tonic-gate * The handlers for copyOP_noerr are found at the end of copyin_noerr.
5767c478bd9Sstevel@tonic-gate */
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate/*
5797c478bd9Sstevel@tonic-gate * Copy kernel data to user space (copyout/xcopyout/xcopyout_little).
5807c478bd9Sstevel@tonic-gate */
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate#if defined(lint)
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate/*ARGSUSED*/
5857c478bd9Sstevel@tonic-gateint
5867c478bd9Sstevel@tonic-gatecopyout(const void *kaddr, void *uaddr, size_t count)
5877c478bd9Sstevel@tonic-gate{ return (0); }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate#else	/* lint */
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate/*
5927c478bd9Sstevel@tonic-gate * We save the arguments in the following registers in case of a fault:
5937c478bd9Sstevel@tonic-gate * 	kaddr - %g2
5947c478bd9Sstevel@tonic-gate * 	uaddr - %g3
5957c478bd9Sstevel@tonic-gate * 	count - %g4
5967c478bd9Sstevel@tonic-gate */
5977c478bd9Sstevel@tonic-gate#define	SAVE_SRC	%g2
5987c478bd9Sstevel@tonic-gate#define	SAVE_DST	%g3
5997c478bd9Sstevel@tonic-gate#define	SAVE_COUNT	%g4
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate#define	REAL_LOFAULT		%g5
6027c478bd9Sstevel@tonic-gate#define	SAVED_LOFAULT		%g6
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate/*
6057c478bd9Sstevel@tonic-gate * Generic copyio fault handler.  This is the first line of defense when a
6067c478bd9Sstevel@tonic-gate * fault occurs in (x)copyin/(x)copyout.  In order for this to function
6077c478bd9Sstevel@tonic-gate * properly, the value of the 'real' lofault handler should be in REAL_LOFAULT.
6087c478bd9Sstevel@tonic-gate * This allows us to share common code for all the flavors of the copy
6097c478bd9Sstevel@tonic-gate * operations, including the _noerr versions.
6107c478bd9Sstevel@tonic-gate *
6117c478bd9Sstevel@tonic-gate * Note that this function will restore the original input parameters before
6127c478bd9Sstevel@tonic-gate * calling REAL_LOFAULT.  So the real handler can vector to the appropriate
6137c478bd9Sstevel@tonic-gate * member of the t_copyop structure, if needed.
6147c478bd9Sstevel@tonic-gate */
6157c478bd9Sstevel@tonic-gate	ENTRY(copyio_fault)
6167c478bd9Sstevel@tonic-gate	membar	#Sync
6177c478bd9Sstevel@tonic-gate	stn	SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate	mov	SAVE_SRC, %o0
6207c478bd9Sstevel@tonic-gate	mov	SAVE_DST, %o1
6217c478bd9Sstevel@tonic-gate	jmp	REAL_LOFAULT
6227c478bd9Sstevel@tonic-gate	  mov	SAVE_COUNT, %o2
6237c478bd9Sstevel@tonic-gate	SET_SIZE(copyio_fault)
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate	ENTRY(copyout)
6267c478bd9Sstevel@tonic-gate	sethi	%hi(.copyout_err), REAL_LOFAULT
6277c478bd9Sstevel@tonic-gate	or	REAL_LOFAULT, %lo(.copyout_err), REAL_LOFAULT
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate.do_copyout:
6307c478bd9Sstevel@tonic-gate	!
6317c478bd9Sstevel@tonic-gate	! Check the length and bail if zero.
6327c478bd9Sstevel@tonic-gate	!
6337c478bd9Sstevel@tonic-gate	tst	%o2
6347c478bd9Sstevel@tonic-gate	bnz,pt	%ncc, 1f
6357c478bd9Sstevel@tonic-gate	  nop
6367c478bd9Sstevel@tonic-gate	retl
6377c478bd9Sstevel@tonic-gate	  clr	%o0
6387c478bd9Sstevel@tonic-gate1:
6397c478bd9Sstevel@tonic-gate	sethi	%hi(copyio_fault), %o3
6407c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], SAVED_LOFAULT
6417c478bd9Sstevel@tonic-gate	or	%o3, %lo(copyio_fault), %o3
6427c478bd9Sstevel@tonic-gate	membar	#Sync
6437c478bd9Sstevel@tonic-gate	stn	%o3, [THREAD_REG + T_LOFAULT]
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate	mov	%o0, SAVE_SRC
6467c478bd9Sstevel@tonic-gate	mov	%o1, SAVE_DST
6477c478bd9Sstevel@tonic-gate	mov	%o2, SAVE_COUNT
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate	!
6507c478bd9Sstevel@tonic-gate	! Check to see if we're more than SMALL_LIMIT (7 bytes).
6517c478bd9Sstevel@tonic-gate	! Run in leaf mode, using the %o regs as our input regs.
6527c478bd9Sstevel@tonic-gate	!
6537c478bd9Sstevel@tonic-gate	subcc	%o2, SMALL_LIMIT, %o3
6547c478bd9Sstevel@tonic-gate	bgu,a,pt %ncc, .dco_ns
6557c478bd9Sstevel@tonic-gate	or	%o0, %o1, %o3
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate.dcobcp:
6587c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3		! negate count
6597c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0		! make %o0 point at the end
6607c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1		! make %o1 point at the end
6617c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dcocl
6627c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o3], %o4	! load first byte
6637c478bd9Sstevel@tonic-gate	!
6647c478bd9Sstevel@tonic-gate	! %o0 and %o2 point at the end and remain pointing at the end
6657c478bd9Sstevel@tonic-gate	! of their buffers. We pull things out by adding %o3 (which is
6667c478bd9Sstevel@tonic-gate	! the negation of the length) to the buffer end which gives us
6677c478bd9Sstevel@tonic-gate	! the curent location in the buffers. By incrementing %o3 we walk
6687c478bd9Sstevel@tonic-gate	! through both buffers without having to bump each buffer's
6697c478bd9Sstevel@tonic-gate	! pointer. A very fast 4 instruction loop.
6707c478bd9Sstevel@tonic-gate	!
6717c478bd9Sstevel@tonic-gate	.align 16
6727c478bd9Sstevel@tonic-gate.dcocl:
6737c478bd9Sstevel@tonic-gate	stba	%o4, [%o1 + %o3]ASI_USER
6747c478bd9Sstevel@tonic-gate	inccc	%o3
6757c478bd9Sstevel@tonic-gate	bl,a,pt	%ncc, .dcocl
6767c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o3], %o4
6777c478bd9Sstevel@tonic-gate	!
6787c478bd9Sstevel@tonic-gate	! We're done. Go home.
6797c478bd9Sstevel@tonic-gate	!
6807c478bd9Sstevel@tonic-gate	membar	#Sync
6817c478bd9Sstevel@tonic-gate	stn	SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]
6827c478bd9Sstevel@tonic-gate	retl
6837c478bd9Sstevel@tonic-gate	clr	%o0
6847c478bd9Sstevel@tonic-gate	!
6857c478bd9Sstevel@tonic-gate	! Try aligned copies from here.
6867c478bd9Sstevel@tonic-gate	!
6877c478bd9Sstevel@tonic-gate.dco_ns:
6887c478bd9Sstevel@tonic-gate	! %o0 = kernel addr (to be copied from)
6897c478bd9Sstevel@tonic-gate	! %o1 = user addr (to be copied to)
6907c478bd9Sstevel@tonic-gate	! %o2 = length
6917c478bd9Sstevel@tonic-gate	! %o3 = %o1 | %o2 (used for alignment checking)
6927c478bd9Sstevel@tonic-gate	! %o4 is alternate lo_fault
6937c478bd9Sstevel@tonic-gate	! %o5 is original lo_fault
6947c478bd9Sstevel@tonic-gate	!
6957c478bd9Sstevel@tonic-gate	! See if we're single byte aligned. If we are, check the
6967c478bd9Sstevel@tonic-gate	! limit for single byte copies. If we're smaller or equal,
6977c478bd9Sstevel@tonic-gate	! bounce to the byte for byte copy loop. Otherwise do it in
6987c478bd9Sstevel@tonic-gate	! HW (if enabled).
6997c478bd9Sstevel@tonic-gate	!
7007c478bd9Sstevel@tonic-gate	btst	1, %o3
7017c478bd9Sstevel@tonic-gate	bz,pt	%icc, .dcoh8
7027c478bd9Sstevel@tonic-gate	btst	7, %o3
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate	ba	.dcobcp
7057c478bd9Sstevel@tonic-gate	nop
7067c478bd9Sstevel@tonic-gate.dcoh8:
7077c478bd9Sstevel@tonic-gate	!
7087c478bd9Sstevel@tonic-gate	! 8 byte aligned?
7097c478bd9Sstevel@tonic-gate	!
7107c478bd9Sstevel@tonic-gate	bnz,a	%ncc, .dcoh4
7117c478bd9Sstevel@tonic-gate	btst	3, %o3
7127c478bd9Sstevel@tonic-gate.dcos8:
7137c478bd9Sstevel@tonic-gate	!
7147c478bd9Sstevel@tonic-gate	! Housekeeping for copy loops. Uses same idea as in the byte for
7157c478bd9Sstevel@tonic-gate	! byte copy loop above.
7167c478bd9Sstevel@tonic-gate	!
7177c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
7187c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
7197c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3
7207c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dodebc
7217c478bd9Sstevel@tonic-gate	srl	%o2, 3, %o2		! Number of 8 byte chunks to copy
7227c478bd9Sstevel@tonic-gate	!
7237c478bd9Sstevel@tonic-gate	! 4 byte aligned?
7247c478bd9Sstevel@tonic-gate	!
7257c478bd9Sstevel@tonic-gate.dcoh4:
7267c478bd9Sstevel@tonic-gate	bnz,pn	%ncc, .dcoh2
7277c478bd9Sstevel@tonic-gate	nop
7287c478bd9Sstevel@tonic-gate.dcos4:
7297c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
7307c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
7317c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3
7327c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dodfbc
7337c478bd9Sstevel@tonic-gate	srl	%o2, 2, %o2		! Number of 4 byte chunks to copy
7347c478bd9Sstevel@tonic-gate	!
7357c478bd9Sstevel@tonic-gate	! We must be 2 byte aligned. Off we go.
7367c478bd9Sstevel@tonic-gate	! The check for small copies was done in the
7377c478bd9Sstevel@tonic-gate	! delay at .dcoh4
7387c478bd9Sstevel@tonic-gate	!
7397c478bd9Sstevel@tonic-gate.dcoh2:
7407c478bd9Sstevel@tonic-gate.dcos2:
7417c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
7427c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
7437c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3
7447c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dodtbc
7457c478bd9Sstevel@tonic-gate	srl	%o2, 1, %o2		! Number of 2 byte chunks to copy
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate.dodebc:
7487c478bd9Sstevel@tonic-gate	ldx	[%o0 + %o3], %o4
7497c478bd9Sstevel@tonic-gate	deccc	%o2
7507c478bd9Sstevel@tonic-gate	stxa	%o4, [%o1 + %o3]ASI_USER
7517c478bd9Sstevel@tonic-gate	bg,pt	%ncc, .dodebc
7527c478bd9Sstevel@tonic-gate	addcc	%o3, 8, %o3
7537c478bd9Sstevel@tonic-gate	!
7547c478bd9Sstevel@tonic-gate	! End of copy loop. Check to see if we're done. Most
7557c478bd9Sstevel@tonic-gate	! eight byte aligned copies end here.
7567c478bd9Sstevel@tonic-gate	!
7577c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .dcofh
7587c478bd9Sstevel@tonic-gate	nop
7597c478bd9Sstevel@tonic-gate	!
7607c478bd9Sstevel@tonic-gate	! Something is left - do it byte for byte.
7617c478bd9Sstevel@tonic-gate	!
7627c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dcocl
7637c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o3], %o4	! load next byte
7647c478bd9Sstevel@tonic-gate	!
7657c478bd9Sstevel@tonic-gate	! Four byte copy loop. %o2 is the number of 4 byte chunks to copy.
7667c478bd9Sstevel@tonic-gate	!
7677c478bd9Sstevel@tonic-gate	.align 32
7687c478bd9Sstevel@tonic-gate.dodfbc:
7697c478bd9Sstevel@tonic-gate	lduw	[%o0 + %o3], %o4
7707c478bd9Sstevel@tonic-gate	deccc	%o2
7717c478bd9Sstevel@tonic-gate	sta	%o4, [%o1 + %o3]ASI_USER
7727c478bd9Sstevel@tonic-gate	bg,pt	%ncc, .dodfbc
7737c478bd9Sstevel@tonic-gate	addcc	%o3, 4, %o3
7747c478bd9Sstevel@tonic-gate	!
7757c478bd9Sstevel@tonic-gate	! End of copy loop. Check to see if we're done. Most
7767c478bd9Sstevel@tonic-gate	! four byte aligned copies end here.
7777c478bd9Sstevel@tonic-gate	!
7787c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .dcofh
7797c478bd9Sstevel@tonic-gate	nop
7807c478bd9Sstevel@tonic-gate	!
7817c478bd9Sstevel@tonic-gate	! Something is left. Do it byte for byte.
7827c478bd9Sstevel@tonic-gate	!
7837c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dcocl
7847c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o3], %o4	! load next byte
7857c478bd9Sstevel@tonic-gate	!
7867c478bd9Sstevel@tonic-gate	! two byte aligned copy loop. %o2 is the number of 2 byte chunks to
7877c478bd9Sstevel@tonic-gate	! copy.
7887c478bd9Sstevel@tonic-gate	!
7897c478bd9Sstevel@tonic-gate	.align 32
7907c478bd9Sstevel@tonic-gate.dodtbc:
7917c478bd9Sstevel@tonic-gate	lduh	[%o0 + %o3], %o4
7927c478bd9Sstevel@tonic-gate	deccc	%o2
7937c478bd9Sstevel@tonic-gate	stha	%o4, [%o1 + %o3]ASI_USER
7947c478bd9Sstevel@tonic-gate	bg,pt	%ncc, .dodtbc
7957c478bd9Sstevel@tonic-gate	addcc	%o3, 2, %o3
7967c478bd9Sstevel@tonic-gate	!
7977c478bd9Sstevel@tonic-gate	! End of copy loop. Anything left?
7987c478bd9Sstevel@tonic-gate	!
7997c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .dcofh
8007c478bd9Sstevel@tonic-gate	nop
8017c478bd9Sstevel@tonic-gate	!
8027c478bd9Sstevel@tonic-gate	! Deal with the last byte
8037c478bd9Sstevel@tonic-gate	!
8047c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o3], %o4
8057c478bd9Sstevel@tonic-gate	stba	%o4, [%o1 + %o3]ASI_USER
8067c478bd9Sstevel@tonic-gate.dcofh:
8077c478bd9Sstevel@tonic-gate	membar	#Sync
8087c478bd9Sstevel@tonic-gate	stn	SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
8097c478bd9Sstevel@tonic-gate	retl
8107c478bd9Sstevel@tonic-gate	clr	%o0
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate.copyout_err:
8137c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_COPYOPS], %o4
8147c478bd9Sstevel@tonic-gate	brz	%o4, 2f
8157c478bd9Sstevel@tonic-gate	nop
8167c478bd9Sstevel@tonic-gate	ldn	[%o4 + CP_COPYOUT], %g2
8177c478bd9Sstevel@tonic-gate	jmp	%g2
8187c478bd9Sstevel@tonic-gate	nop
8197c478bd9Sstevel@tonic-gate2:
8207c478bd9Sstevel@tonic-gate	retl
8217c478bd9Sstevel@tonic-gate	mov	-1, %o0
8227c478bd9Sstevel@tonic-gate	SET_SIZE(copyout)
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate#endif	/* lint */
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate#ifdef	lint
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate/*ARGSUSED*/
8307c478bd9Sstevel@tonic-gateint
8317c478bd9Sstevel@tonic-gatexcopyout(const void *kaddr, void *uaddr, size_t count)
8327c478bd9Sstevel@tonic-gate{ return (0); }
8337c478bd9Sstevel@tonic-gate
8347c478bd9Sstevel@tonic-gate#else	/* lint */
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate	ENTRY(xcopyout)
8377c478bd9Sstevel@tonic-gate	sethi	%hi(.xcopyout_err), REAL_LOFAULT
8387c478bd9Sstevel@tonic-gate	b	.do_copyout
8397c478bd9Sstevel@tonic-gate	  or	REAL_LOFAULT, %lo(.xcopyout_err), REAL_LOFAULT
8407c478bd9Sstevel@tonic-gate.xcopyout_err:
8417c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_COPYOPS], %o4
8427c478bd9Sstevel@tonic-gate	brz	%o4, 2f
8437c478bd9Sstevel@tonic-gate	nop
8447c478bd9Sstevel@tonic-gate	ldn	[%o4 + CP_XCOPYOUT], %g2
8457c478bd9Sstevel@tonic-gate	jmp	%g2
8467c478bd9Sstevel@tonic-gate	nop
8477c478bd9Sstevel@tonic-gate2:
8487c478bd9Sstevel@tonic-gate	retl
8497c478bd9Sstevel@tonic-gate	mov	%g1, %o0
8507c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyout)
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate#endif	/* lint */
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate#ifdef	lint
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate/*ARGSUSED*/
8577c478bd9Sstevel@tonic-gateint
8587c478bd9Sstevel@tonic-gatexcopyout_little(const void *kaddr, void *uaddr, size_t count)
8597c478bd9Sstevel@tonic-gate{ return (0); }
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate#else	/* lint */
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate	ENTRY(xcopyout_little)
8647c478bd9Sstevel@tonic-gate	sethi	%hi(.little_err), %o4
8657c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
8667c478bd9Sstevel@tonic-gate	or	%o4, %lo(.little_err), %o4
8677c478bd9Sstevel@tonic-gate	membar	#Sync			! sync error barrier
8687c478bd9Sstevel@tonic-gate	stn	%o4, [THREAD_REG + T_LOFAULT]
8697c478bd9Sstevel@tonic-gate
8707c478bd9Sstevel@tonic-gate	subcc	%g0, %o2, %o3
8717c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
8727c478bd9Sstevel@tonic-gate	bz,pn	%ncc, 2f		! check for zero bytes
8737c478bd9Sstevel@tonic-gate	sub	%o2, 1, %o4
8747c478bd9Sstevel@tonic-gate	add	%o0, %o4, %o0		! start w/last byte
8757c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
8767c478bd9Sstevel@tonic-gate	ldub	[%o0+%o3], %o4
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate1:	stba	%o4, [%o1+%o3]ASI_AIUSL
8797c478bd9Sstevel@tonic-gate	inccc	%o3
8807c478bd9Sstevel@tonic-gate	sub	%o0, 2, %o0		! get next byte
8817c478bd9Sstevel@tonic-gate	bcc,a,pt %ncc, 1b
8827c478bd9Sstevel@tonic-gate	  ldub	[%o0+%o3], %o4
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate2:	membar	#Sync			! sync error barrier
8857c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
8867c478bd9Sstevel@tonic-gate	retl
8877c478bd9Sstevel@tonic-gate	mov	%g0, %o0		! return (0)
8887c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyout_little)
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate#endif	/* lint */
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate/*
8937c478bd9Sstevel@tonic-gate * Copy user data to kernel space (copyin/xcopyin/xcopyin_little)
8947c478bd9Sstevel@tonic-gate */
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate#if defined(lint)
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate/*ARGSUSED*/
8997c478bd9Sstevel@tonic-gateint
9007c478bd9Sstevel@tonic-gatecopyin(const void *uaddr, void *kaddr, size_t count)
9017c478bd9Sstevel@tonic-gate{ return (0); }
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate#else	/* lint */
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate	ENTRY(copyin)
9067c478bd9Sstevel@tonic-gate	sethi	%hi(.copyin_err), REAL_LOFAULT
9077c478bd9Sstevel@tonic-gate	or	REAL_LOFAULT, %lo(.copyin_err), REAL_LOFAULT
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate.do_copyin:
9107c478bd9Sstevel@tonic-gate	!
9117c478bd9Sstevel@tonic-gate	! Check the length and bail if zero.
9127c478bd9Sstevel@tonic-gate	!
9137c478bd9Sstevel@tonic-gate	tst	%o2
9147c478bd9Sstevel@tonic-gate	bnz,pt	%ncc, 1f
9157c478bd9Sstevel@tonic-gate	  nop
9167c478bd9Sstevel@tonic-gate	retl
9177c478bd9Sstevel@tonic-gate	  clr	%o0
9187c478bd9Sstevel@tonic-gate1:
9197c478bd9Sstevel@tonic-gate	sethi	%hi(copyio_fault), %o3
9207c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], SAVED_LOFAULT
9217c478bd9Sstevel@tonic-gate	or	%o3, %lo(copyio_fault), %o3
9227c478bd9Sstevel@tonic-gate	membar	#Sync
9237c478bd9Sstevel@tonic-gate	stn	%o3, [THREAD_REG + T_LOFAULT]
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate	mov	%o0, SAVE_SRC
9267c478bd9Sstevel@tonic-gate	mov	%o1, SAVE_DST
9277c478bd9Sstevel@tonic-gate	mov	%o2, SAVE_COUNT
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate	!
9307c478bd9Sstevel@tonic-gate	! Check to see if we're more than SMALL_LIMIT.
9317c478bd9Sstevel@tonic-gate	!
9327c478bd9Sstevel@tonic-gate	subcc	%o2, SMALL_LIMIT, %o3
9337c478bd9Sstevel@tonic-gate	bgu,a,pt %ncc, .dci_ns
9347c478bd9Sstevel@tonic-gate	or	%o0, %o1, %o3
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate.dcibcp:
9377c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3		! setup for copy loop
9387c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
9397c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
9407c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dcicl
9417c478bd9Sstevel@tonic-gate	lduba	[%o0 + %o3]ASI_USER, %o4
9427c478bd9Sstevel@tonic-gate	!
9437c478bd9Sstevel@tonic-gate	! %o0 and %o1 point at the end and remain pointing at the end
9447c478bd9Sstevel@tonic-gate	! of their buffers. We pull things out by adding %o3 (which is
9457c478bd9Sstevel@tonic-gate	! the negation of the length) to the buffer end which gives us
9467c478bd9Sstevel@tonic-gate	! the curent location in the buffers. By incrementing %o3 we walk
9477c478bd9Sstevel@tonic-gate	! through both buffers without having to bump each buffer's
9487c478bd9Sstevel@tonic-gate	! pointer. A very fast 4 instruction loop.
9497c478bd9Sstevel@tonic-gate	!
9507c478bd9Sstevel@tonic-gate	.align 16
9517c478bd9Sstevel@tonic-gate.dcicl:
9527c478bd9Sstevel@tonic-gate	stb	%o4, [%o1 + %o3]
9537c478bd9Sstevel@tonic-gate	inccc	%o3
9547c478bd9Sstevel@tonic-gate	bl,a,pt %ncc, .dcicl
9557c478bd9Sstevel@tonic-gate	lduba	[%o0 + %o3]ASI_USER, %o4
9567c478bd9Sstevel@tonic-gate	!
9577c478bd9Sstevel@tonic-gate	! We're done. Go home.
9587c478bd9Sstevel@tonic-gate	!
9597c478bd9Sstevel@tonic-gate	membar	#Sync
9607c478bd9Sstevel@tonic-gate	stn	SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]
9617c478bd9Sstevel@tonic-gate	retl
9627c478bd9Sstevel@tonic-gate	clr	%o0
9637c478bd9Sstevel@tonic-gate	!
9647c478bd9Sstevel@tonic-gate	! Try aligned copies from here.
9657c478bd9Sstevel@tonic-gate	!
9667c478bd9Sstevel@tonic-gate.dci_ns:
9677c478bd9Sstevel@tonic-gate	!
9687c478bd9Sstevel@tonic-gate	! See if we're single byte aligned. If we are, check the
9697c478bd9Sstevel@tonic-gate	! limit for single byte copies. If we're smaller, or equal,
9707c478bd9Sstevel@tonic-gate	! bounce to the byte for byte copy loop. Otherwise do it in
9717c478bd9Sstevel@tonic-gate	! HW (if enabled).
9727c478bd9Sstevel@tonic-gate	!
9737c478bd9Sstevel@tonic-gate	btst	1, %o3
9747c478bd9Sstevel@tonic-gate	bz,a,pt	%icc, .dcih8
9757c478bd9Sstevel@tonic-gate	btst	7, %o3
9767c478bd9Sstevel@tonic-gate	ba	.dcibcp
9777c478bd9Sstevel@tonic-gate	nop
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate.dcih8:
9807c478bd9Sstevel@tonic-gate	!
9817c478bd9Sstevel@tonic-gate	! 8 byte aligned?
9827c478bd9Sstevel@tonic-gate	!
9837c478bd9Sstevel@tonic-gate	bnz,a	%ncc, .dcih4
9847c478bd9Sstevel@tonic-gate	btst	3, %o3
9857c478bd9Sstevel@tonic-gate.dcis8:
9867c478bd9Sstevel@tonic-gate	!
9877c478bd9Sstevel@tonic-gate	! Housekeeping for copy loops. Uses same idea as in the byte for
9887c478bd9Sstevel@tonic-gate	! byte copy loop above.
9897c478bd9Sstevel@tonic-gate	!
9907c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
9917c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
9927c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3
9937c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .didebc
9947c478bd9Sstevel@tonic-gate	srl	%o2, 3, %o2		! Number of 8 byte chunks to copy
9957c478bd9Sstevel@tonic-gate	!
9967c478bd9Sstevel@tonic-gate	! 4 byte aligned?
9977c478bd9Sstevel@tonic-gate	!
9987c478bd9Sstevel@tonic-gate.dcih4:
9997c478bd9Sstevel@tonic-gate	bnz	%ncc, .dcih2
10007c478bd9Sstevel@tonic-gate	nop
10017c478bd9Sstevel@tonic-gate.dcis4:
10027c478bd9Sstevel@tonic-gate	!
10037c478bd9Sstevel@tonic-gate	! Housekeeping for copy loops. Uses same idea as in the byte
10047c478bd9Sstevel@tonic-gate	! for byte copy loop above.
10057c478bd9Sstevel@tonic-gate	!
10067c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
10077c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
10087c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3
10097c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .didfbc
10107c478bd9Sstevel@tonic-gate	srl	%o2, 2, %o2		! Number of 4 byte chunks to copy
10117c478bd9Sstevel@tonic-gate.dcih2:
10127c478bd9Sstevel@tonic-gate.dcis2:
10137c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
10147c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
10157c478bd9Sstevel@tonic-gate	sub	%g0, %o2, %o3
10167c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .didtbc
10177c478bd9Sstevel@tonic-gate	srl	%o2, 1, %o2		! Number of 2 byte chunks to copy
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate.didebc:
10207c478bd9Sstevel@tonic-gate	ldxa	[%o0 + %o3]ASI_USER, %o4
10217c478bd9Sstevel@tonic-gate	deccc	%o2
10227c478bd9Sstevel@tonic-gate	stx	%o4, [%o1 + %o3]
10237c478bd9Sstevel@tonic-gate	bg,pt	%ncc, .didebc
10247c478bd9Sstevel@tonic-gate	addcc	%o3, 8, %o3
10257c478bd9Sstevel@tonic-gate	!
10267c478bd9Sstevel@tonic-gate	! End of copy loop. Most 8 byte aligned copies end here.
10277c478bd9Sstevel@tonic-gate	!
10287c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .dcifh
10297c478bd9Sstevel@tonic-gate	nop
10307c478bd9Sstevel@tonic-gate	!
10317c478bd9Sstevel@tonic-gate	! Something is left. Do it byte for byte.
10327c478bd9Sstevel@tonic-gate	!
10337c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dcicl
10347c478bd9Sstevel@tonic-gate	lduba	[%o0 + %o3]ASI_USER, %o4
10357c478bd9Sstevel@tonic-gate	!
10367c478bd9Sstevel@tonic-gate	! 4 byte copy loop. %o2 is number of 4 byte chunks to copy.
10377c478bd9Sstevel@tonic-gate	!
10387c478bd9Sstevel@tonic-gate	.align 32
10397c478bd9Sstevel@tonic-gate.didfbc:
10407c478bd9Sstevel@tonic-gate	lduwa	[%o0 + %o3]ASI_USER, %o4
10417c478bd9Sstevel@tonic-gate	deccc	%o2
10427c478bd9Sstevel@tonic-gate	st	%o4, [%o1 + %o3]
10437c478bd9Sstevel@tonic-gate	bg,pt	%ncc, .didfbc
10447c478bd9Sstevel@tonic-gate	addcc	%o3, 4, %o3
10457c478bd9Sstevel@tonic-gate	!
10467c478bd9Sstevel@tonic-gate	! End of copy loop. Most 4 byte aligned copies end here.
10477c478bd9Sstevel@tonic-gate	!
10487c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .dcifh
10497c478bd9Sstevel@tonic-gate	nop
10507c478bd9Sstevel@tonic-gate	!
10517c478bd9Sstevel@tonic-gate	! Something is left. Do it byte for byte.
10527c478bd9Sstevel@tonic-gate	!
10537c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .dcicl
10547c478bd9Sstevel@tonic-gate	lduba	[%o0 + %o3]ASI_USER, %o4
10557c478bd9Sstevel@tonic-gate	!
10567c478bd9Sstevel@tonic-gate	! 2 byte aligned copy loop. %o2 is number of 2 byte chunks to
10577c478bd9Sstevel@tonic-gate	! copy.
10587c478bd9Sstevel@tonic-gate	!
10597c478bd9Sstevel@tonic-gate	.align 32
10607c478bd9Sstevel@tonic-gate.didtbc:
10617c478bd9Sstevel@tonic-gate	lduha	[%o0 + %o3]ASI_USER, %o4
10627c478bd9Sstevel@tonic-gate	deccc	%o2
10637c478bd9Sstevel@tonic-gate	sth	%o4, [%o1 + %o3]
10647c478bd9Sstevel@tonic-gate	bg,pt	%ncc, .didtbc
10657c478bd9Sstevel@tonic-gate	addcc	%o3, 2, %o3
10667c478bd9Sstevel@tonic-gate	!
10677c478bd9Sstevel@tonic-gate	! End of copy loop. Most 2 byte aligned copies end here.
10687c478bd9Sstevel@tonic-gate	!
10697c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .dcifh
10707c478bd9Sstevel@tonic-gate	nop
10717c478bd9Sstevel@tonic-gate	!
10727c478bd9Sstevel@tonic-gate	! Deal with the last byte
10737c478bd9Sstevel@tonic-gate	!
10747c478bd9Sstevel@tonic-gate	lduba	[%o0 + %o3]ASI_USER, %o4
10757c478bd9Sstevel@tonic-gate	stb	%o4, [%o1 + %o3]
10767c478bd9Sstevel@tonic-gate.dcifh:
10777c478bd9Sstevel@tonic-gate	membar	#Sync
10787c478bd9Sstevel@tonic-gate	stn     SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]   ! restore old t_lofault
10797c478bd9Sstevel@tonic-gate	retl
10807c478bd9Sstevel@tonic-gate	clr	%o0
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate.copyin_err:
10837c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_COPYOPS], %o4
10847c478bd9Sstevel@tonic-gate	brz	%o4, 2f
10857c478bd9Sstevel@tonic-gate	nop
10867c478bd9Sstevel@tonic-gate	ldn	[%o4 + CP_COPYIN], %g2
10877c478bd9Sstevel@tonic-gate	jmp	%g2
10887c478bd9Sstevel@tonic-gate	nop
10897c478bd9Sstevel@tonic-gate2:
10907c478bd9Sstevel@tonic-gate	retl
10917c478bd9Sstevel@tonic-gate	mov	-1, %o0
10927c478bd9Sstevel@tonic-gate	SET_SIZE(copyin)
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate#endif	/* lint */
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate#ifdef	lint
10977c478bd9Sstevel@tonic-gate
10987c478bd9Sstevel@tonic-gate/*ARGSUSED*/
10997c478bd9Sstevel@tonic-gateint
11007c478bd9Sstevel@tonic-gatexcopyin(const void *uaddr, void *kaddr, size_t count)
11017c478bd9Sstevel@tonic-gate{ return (0); }
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate#else	/* lint */
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate	ENTRY(xcopyin)
11067c478bd9Sstevel@tonic-gate	sethi	%hi(.xcopyin_err), REAL_LOFAULT
11077c478bd9Sstevel@tonic-gate	b	.do_copyin
11087c478bd9Sstevel@tonic-gate	  or	REAL_LOFAULT, %lo(.xcopyin_err), REAL_LOFAULT
11097c478bd9Sstevel@tonic-gate.xcopyin_err:
11107c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_COPYOPS], %o4
11117c478bd9Sstevel@tonic-gate	brz	%o4, 2f
11127c478bd9Sstevel@tonic-gate	nop
11137c478bd9Sstevel@tonic-gate	ldn	[%o4 + CP_XCOPYIN], %g2
11147c478bd9Sstevel@tonic-gate	jmp	%g2
11157c478bd9Sstevel@tonic-gate	nop
11167c478bd9Sstevel@tonic-gate2:
11177c478bd9Sstevel@tonic-gate	retl
11187c478bd9Sstevel@tonic-gate	mov	%g1, %o0
11197c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyin)
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate#endif	/* lint */
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate#ifdef	lint
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate/*ARGSUSED*/
11267c478bd9Sstevel@tonic-gateint
11277c478bd9Sstevel@tonic-gatexcopyin_little(const void *uaddr, void *kaddr, size_t count)
11287c478bd9Sstevel@tonic-gate{ return (0); }
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate#else	/* lint */
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate	ENTRY(xcopyin_little)
11337c478bd9Sstevel@tonic-gate	sethi	%hi(.little_err), %o4
11347c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
11357c478bd9Sstevel@tonic-gate	or	%o4, %lo(.little_err), %o4
11367c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
11377c478bd9Sstevel@tonic-gate	stn	%o4, [THREAD_REG + T_LOFAULT]
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate	subcc	%g0, %o2, %o3
11407c478bd9Sstevel@tonic-gate	add	%o0, %o2, %o0
11417c478bd9Sstevel@tonic-gate	bz,pn	%ncc, 2f		! check for zero bytes
11427c478bd9Sstevel@tonic-gate	sub	%o2, 1, %o4
11437c478bd9Sstevel@tonic-gate	add	%o0, %o4, %o0		! start w/last byte
11447c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
11457c478bd9Sstevel@tonic-gate	lduba	[%o0+%o3]ASI_AIUSL, %o4
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate1:	stb	%o4, [%o1+%o3]
11487c478bd9Sstevel@tonic-gate	inccc	%o3
11497c478bd9Sstevel@tonic-gate	sub	%o0, 2, %o0		! get next byte
11507c478bd9Sstevel@tonic-gate	bcc,a,pt %ncc, 1b
11517c478bd9Sstevel@tonic-gate	  lduba	[%o0+%o3]ASI_AIUSL, %o4
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate2:	membar	#Sync				! sync error barrier
11547c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
11557c478bd9Sstevel@tonic-gate	retl
11567c478bd9Sstevel@tonic-gate	mov	%g0, %o0		! return (0)
11577c478bd9Sstevel@tonic-gate
11587c478bd9Sstevel@tonic-gate.little_err:
11597c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
11607c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
11617c478bd9Sstevel@tonic-gate	retl
11627c478bd9Sstevel@tonic-gate	mov	%g1, %o0
11637c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyin_little)
11647c478bd9Sstevel@tonic-gate
11657c478bd9Sstevel@tonic-gate#endif	/* lint */
11667c478bd9Sstevel@tonic-gate
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate/*
11697c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to).
11707c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault())
11717c478bd9Sstevel@tonic-gate */
11727c478bd9Sstevel@tonic-gate#if defined(lint)
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate/* ARGSUSED */
11757c478bd9Sstevel@tonic-gatevoid
11767c478bd9Sstevel@tonic-gatecopyin_noerr(const void *ufrom, void *kto, size_t count)
11777c478bd9Sstevel@tonic-gate{}
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate#else	/* lint */
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate	ENTRY(copyin_noerr)
11827c478bd9Sstevel@tonic-gate	sethi	%hi(.copyio_noerr), REAL_LOFAULT
11837c478bd9Sstevel@tonic-gate	b	.do_copyin
11847c478bd9Sstevel@tonic-gate	  or	REAL_LOFAULT, %lo(.copyio_noerr), REAL_LOFAULT
11857c478bd9Sstevel@tonic-gate.copyio_noerr:
11867c478bd9Sstevel@tonic-gate	jmp	SAVED_LOFAULT
11877c478bd9Sstevel@tonic-gate	  nop
11887c478bd9Sstevel@tonic-gate	SET_SIZE(copyin_noerr)
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate#endif /* lint */
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate/*
11937c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to).
11947c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault())
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate
11977c478bd9Sstevel@tonic-gate#if defined(lint)
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate/* ARGSUSED */
12007c478bd9Sstevel@tonic-gatevoid
12017c478bd9Sstevel@tonic-gatecopyout_noerr(const void *kfrom, void *uto, size_t count)
12027c478bd9Sstevel@tonic-gate{}
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate#else	/* lint */
12057c478bd9Sstevel@tonic-gate
12067c478bd9Sstevel@tonic-gate	ENTRY(copyout_noerr)
12077c478bd9Sstevel@tonic-gate	sethi	%hi(.copyio_noerr), REAL_LOFAULT
12087c478bd9Sstevel@tonic-gate	b	.do_copyout
12097c478bd9Sstevel@tonic-gate	  or	REAL_LOFAULT, %lo(.copyio_noerr), REAL_LOFAULT
12107c478bd9Sstevel@tonic-gate	SET_SIZE(copyout_noerr)
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate#endif /* lint */
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate#if defined(lint)
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gateint use_hw_bcopy = 1;
12177c478bd9Sstevel@tonic-gateint use_hw_bzero = 1;
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate#else /* !lint */
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate	.align	4
12227c478bd9Sstevel@tonic-gate	DGDEF(use_hw_bcopy)
12237c478bd9Sstevel@tonic-gate	.word	1
12247c478bd9Sstevel@tonic-gate	DGDEF(use_hw_bzero)
12257c478bd9Sstevel@tonic-gate	.word	1
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate	.align	64
12287c478bd9Sstevel@tonic-gate	.section ".text"
12297c478bd9Sstevel@tonic-gate#endif /* !lint */
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate/*
12337c478bd9Sstevel@tonic-gate * hwblkclr - clears block-aligned, block-multiple-sized regions that are
1234*c2b6e926Sae112802 * longer than 256 bytes in length. For the generic module we will simply
1235*c2b6e926Sae112802 * call bzero and return 1 to ensure that the pages in cache should be
1236a4070553Siskreen * flushed to ensure integrity.
12377c478bd9Sstevel@tonic-gate * Caller is responsible for ensuring use_hw_bzero is true and that
12387c478bd9Sstevel@tonic-gate * kpreempt_disable() has been called.
12397c478bd9Sstevel@tonic-gate */
12407c478bd9Sstevel@tonic-gate#ifdef lint
12417c478bd9Sstevel@tonic-gate/*ARGSUSED*/
12427c478bd9Sstevel@tonic-gateint
12437c478bd9Sstevel@tonic-gatehwblkclr(void *addr, size_t len)
12447c478bd9Sstevel@tonic-gate{
12457c478bd9Sstevel@tonic-gate	return(0);
12467c478bd9Sstevel@tonic-gate}
12477c478bd9Sstevel@tonic-gate#else /* lint */
12487c478bd9Sstevel@tonic-gate	! %i0 - start address
12497c478bd9Sstevel@tonic-gate	! %i1 - length of region (multiple of 64)
12507c478bd9Sstevel@tonic-gate
12517c478bd9Sstevel@tonic-gate	ENTRY(hwblkclr)
12527c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
12537c478bd9Sstevel@tonic-gate
1254*c2b6e926Sae112802	! Simply call bzero and notify the caller that bzero was used
12557c478bd9Sstevel@tonic-gate	mov	%i0, %o0
12567c478bd9Sstevel@tonic-gate	call	bzero
12577c478bd9Sstevel@tonic-gate	  mov	%i1, %o1
12587c478bd9Sstevel@tonic-gate	ret
12597c478bd9Sstevel@tonic-gate	restore	%g0, 1, %o0	! return (1) - did not use block operations
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gate	SET_SIZE(hwblkclr)
12627c478bd9Sstevel@tonic-gate#endif	/* lint */
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate#ifdef	lint
12657c478bd9Sstevel@tonic-gate/* Copy 32 bytes of data from src to dst using physical addresses */
12667c478bd9Sstevel@tonic-gate/*ARGSUSED*/
12677c478bd9Sstevel@tonic-gatevoid
12687c478bd9Sstevel@tonic-gatehw_pa_bcopy32(uint64_t src, uint64_t dst)
12697c478bd9Sstevel@tonic-gate{}
12707c478bd9Sstevel@tonic-gate#else	/*!lint */
12717c478bd9Sstevel@tonic-gate
12727c478bd9Sstevel@tonic-gate	/*
12737c478bd9Sstevel@tonic-gate	 * Copy 32 bytes of data from src (%o0) to dst (%o1)
12747c478bd9Sstevel@tonic-gate	 * using physical addresses.
12757c478bd9Sstevel@tonic-gate	 */
12767c478bd9Sstevel@tonic-gate	ENTRY_NP(hw_pa_bcopy32)
12777c478bd9Sstevel@tonic-gate	rdpr    %pstate, %g1
12787c478bd9Sstevel@tonic-gate	andn    %g1, PSTATE_IE, %g2
12797c478bd9Sstevel@tonic-gate	wrpr    %g0, %g2, %pstate
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate	ldxa    [%o0]ASI_MEM, %o2
12827c478bd9Sstevel@tonic-gate	add     %o0, 8, %o0
12837c478bd9Sstevel@tonic-gate	ldxa    [%o0]ASI_MEM, %o3
12847c478bd9Sstevel@tonic-gate	add     %o0, 8, %o0
12857c478bd9Sstevel@tonic-gate	ldxa    [%o0]ASI_MEM, %o4
12867c478bd9Sstevel@tonic-gate	add     %o0, 8, %o0
12877c478bd9Sstevel@tonic-gate	ldxa    [%o0]ASI_MEM, %o5
12887c478bd9Sstevel@tonic-gate	stxa    %o2, [%o1]ASI_MEM
12897c478bd9Sstevel@tonic-gate	add     %o1, 8, %o1
12907c478bd9Sstevel@tonic-gate	stxa    %o3, [%o1]ASI_MEM
12917c478bd9Sstevel@tonic-gate	add     %o1, 8, %o1
12927c478bd9Sstevel@tonic-gate	stxa    %o4, [%o1]ASI_MEM
12937c478bd9Sstevel@tonic-gate	add     %o1, 8, %o1
12947c478bd9Sstevel@tonic-gate	stxa    %o5, [%o1]ASI_MEM
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate	membar	#Sync
12977c478bd9Sstevel@tonic-gate	retl
12987c478bd9Sstevel@tonic-gate	  wrpr    %g0, %g1, %pstate
12997c478bd9Sstevel@tonic-gate	SET_SIZE(hw_pa_bcopy32)
13007c478bd9Sstevel@tonic-gate#endif /* lint */
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate/*
13037c478bd9Sstevel@tonic-gate * Zero a block of storage.
13047c478bd9Sstevel@tonic-gate *
13057c478bd9Sstevel@tonic-gate * uzero is used by the kernel to zero a block in user address space.
13067c478bd9Sstevel@tonic-gate */
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate#if defined(lint)
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate/* ARGSUSED */
13127c478bd9Sstevel@tonic-gateint
13137c478bd9Sstevel@tonic-gatekzero(void *addr, size_t count)
13147c478bd9Sstevel@tonic-gate{ return(0); }
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate/* ARGSUSED */
13177c478bd9Sstevel@tonic-gatevoid
13187c478bd9Sstevel@tonic-gateuzero(void *addr, size_t count)
13197c478bd9Sstevel@tonic-gate{}
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate#else	/* lint */
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate	ENTRY(uzero)
13247c478bd9Sstevel@tonic-gate	!
13257c478bd9Sstevel@tonic-gate	! Set a new lo_fault handler only if we came in with one
13267c478bd9Sstevel@tonic-gate	! already specified.
13277c478bd9Sstevel@tonic-gate	!
13287c478bd9Sstevel@tonic-gate	wr	%g0, ASI_USER, %asi
13297c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
13307c478bd9Sstevel@tonic-gate	tst	%o5
13317c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .do_zero
13327c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
13337c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
13347c478bd9Sstevel@tonic-gate	membar	#Sync
13357c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .do_zero
13367c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate	ENTRY(kzero)
13397c478bd9Sstevel@tonic-gate	!
13407c478bd9Sstevel@tonic-gate	! Always set a lo_fault handler
13417c478bd9Sstevel@tonic-gate	!
13427c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
13437c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
13447c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
13457c478bd9Sstevel@tonic-gate	or	%o5, LOFAULT_SET, %o5
13467c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
13477c478bd9Sstevel@tonic-gate	membar	#Sync
13487c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .do_zero
13497c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]
13507c478bd9Sstevel@tonic-gate
13517c478bd9Sstevel@tonic-gate/*
13527c478bd9Sstevel@tonic-gate * We got here because of a fault during kzero or if
13537c478bd9Sstevel@tonic-gate * uzero or bzero was called with t_lofault non-zero.
13547c478bd9Sstevel@tonic-gate * Otherwise we've already run screaming from the room.
13557c478bd9Sstevel@tonic-gate * Errno value is in %g1. Note that we're here iff
13567c478bd9Sstevel@tonic-gate * we did set t_lofault.
13577c478bd9Sstevel@tonic-gate */
13587c478bd9Sstevel@tonic-gate.zeroerr:
13597c478bd9Sstevel@tonic-gate	!
13607c478bd9Sstevel@tonic-gate	! Undo asi register setting. Just set it to be the
13617c478bd9Sstevel@tonic-gate        ! kernel default without checking.
13627c478bd9Sstevel@tonic-gate	!
13637c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate	!
13667c478bd9Sstevel@tonic-gate	! We did set t_lofault. It may well have been zero coming in.
13677c478bd9Sstevel@tonic-gate	!
13687c478bd9Sstevel@tonic-gate1:
13697c478bd9Sstevel@tonic-gate	tst	%o5
13707c478bd9Sstevel@tonic-gate	membar #Sync
13717c478bd9Sstevel@tonic-gate	bne,pn	%ncc, 3f
13727c478bd9Sstevel@tonic-gate	andncc	%o5, LOFAULT_SET, %o5
13737c478bd9Sstevel@tonic-gate2:
13747c478bd9Sstevel@tonic-gate	!
13757c478bd9Sstevel@tonic-gate	! Old handler was zero. Just return the error.
13767c478bd9Sstevel@tonic-gate	!
13777c478bd9Sstevel@tonic-gate	retl				! return
13787c478bd9Sstevel@tonic-gate	mov	%g1, %o0		! error code from %g1
13797c478bd9Sstevel@tonic-gate3:
13807c478bd9Sstevel@tonic-gate	!
13817c478bd9Sstevel@tonic-gate	! We're here because %o5 was non-zero. It was non-zero
13827c478bd9Sstevel@tonic-gate	! because either LOFAULT_SET was present, a previous fault
13837c478bd9Sstevel@tonic-gate	! handler was present or both. In all cases we need to reset
13847c478bd9Sstevel@tonic-gate	! T_LOFAULT to the value of %o5 after clearing LOFAULT_SET
13857c478bd9Sstevel@tonic-gate	! before we either simply return the error or we invoke the
13867c478bd9Sstevel@tonic-gate	! previously specified handler.
13877c478bd9Sstevel@tonic-gate	!
13887c478bd9Sstevel@tonic-gate	be	%ncc, 2b
13897c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]
13907c478bd9Sstevel@tonic-gate	jmp	%o5			! goto real handler
13917c478bd9Sstevel@tonic-gate	  nop
13927c478bd9Sstevel@tonic-gate	SET_SIZE(kzero)
13937c478bd9Sstevel@tonic-gate	SET_SIZE(uzero)
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate#endif	/* lint */
13967c478bd9Sstevel@tonic-gate
13977c478bd9Sstevel@tonic-gate/*
13987c478bd9Sstevel@tonic-gate * Zero a block of storage.
13997c478bd9Sstevel@tonic-gate */
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate#if defined(lint)
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate/* ARGSUSED */
14047c478bd9Sstevel@tonic-gatevoid
14057c478bd9Sstevel@tonic-gatebzero(void *addr, size_t count)
14067c478bd9Sstevel@tonic-gate{}
14077c478bd9Sstevel@tonic-gate
14087c478bd9Sstevel@tonic-gate#else	/* lint */
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate	ENTRY(bzero)
14117c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5	! save old vector
14147c478bd9Sstevel@tonic-gate	tst	%o5
14157c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .do_zero
14167c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
14177c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
14187c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
14197c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]	! install new vector
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate.do_zero:
14227c478bd9Sstevel@tonic-gate	cmp	%o1, 7
14237c478bd9Sstevel@tonic-gate	blu,pn	%ncc, .byteclr
14247c478bd9Sstevel@tonic-gate	nop
14257c478bd9Sstevel@tonic-gate
14267c478bd9Sstevel@tonic-gate	cmp	%o1, 15
14277c478bd9Sstevel@tonic-gate	blu,pn	%ncc, .wdalign
14287c478bd9Sstevel@tonic-gate	nop
14297c478bd9Sstevel@tonic-gate
14307c478bd9Sstevel@tonic-gate	andcc	%o0, 7, %o3		! is add aligned on a 8 byte bound
14317c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .blkalign		! already double aligned
14327c478bd9Sstevel@tonic-gate	sub	%o3, 8, %o3		! -(bytes till double aligned)
14337c478bd9Sstevel@tonic-gate	add	%o1, %o3, %o1		! update o1 with new count
14347c478bd9Sstevel@tonic-gate
14357c478bd9Sstevel@tonic-gate1:
14367c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi
14377c478bd9Sstevel@tonic-gate	inccc	%o3
14387c478bd9Sstevel@tonic-gate	bl,pt	%ncc, 1b
14397c478bd9Sstevel@tonic-gate	inc	%o0
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate	! Now address is double aligned
14427c478bd9Sstevel@tonic-gate.blkalign:
14437c478bd9Sstevel@tonic-gate	cmp	%o1, 0x80		! check if there are 128 bytes to set
14447c478bd9Sstevel@tonic-gate	blu,pn	%ncc, .bzero_small
14457c478bd9Sstevel@tonic-gate	mov	%o1, %o3
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gate	andcc	%o0, 0x3f, %o3		! is block aligned?
14487c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .bzero_blk
14497c478bd9Sstevel@tonic-gate	sub	%o3, 0x40, %o3		! -(bytes till block aligned)
14507c478bd9Sstevel@tonic-gate	add	%o1, %o3, %o1		! o1 is the remainder
14517c478bd9Sstevel@tonic-gate
14527c478bd9Sstevel@tonic-gate	! Clear -(%o3) bytes till block aligned
14537c478bd9Sstevel@tonic-gate1:
14547c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
14557c478bd9Sstevel@tonic-gate	addcc	%o3, 8, %o3
14567c478bd9Sstevel@tonic-gate	bl,pt	%ncc, 1b
14577c478bd9Sstevel@tonic-gate	add	%o0, 8, %o0
14587c478bd9Sstevel@tonic-gate
14597c478bd9Sstevel@tonic-gate.bzero_blk:
14607c478bd9Sstevel@tonic-gate	and	%o1, 0x3f, %o3		! calc bytes left after blk clear
14617c478bd9Sstevel@tonic-gate	andn	%o1, 0x3f, %o4		! calc size of blocks in bytes
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate	cmp	%o4, 0x100		! 256 bytes or more
14647c478bd9Sstevel@tonic-gate	blu,pn	%ncc, 3f
14657c478bd9Sstevel@tonic-gate	nop
14667c478bd9Sstevel@tonic-gate
14677c478bd9Sstevel@tonic-gate2:
14687c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x0]%asi
14697c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x40]%asi
14707c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x80]%asi
14717c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xc0]%asi
14727c478bd9Sstevel@tonic-gate
14737c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x8]%asi
14747c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x10]%asi
14757c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x18]%asi
14767c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x20]%asi
14777c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x28]%asi
14787c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x30]%asi
14797c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x38]%asi
14807c478bd9Sstevel@tonic-gate
14817c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x48]%asi
14827c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x50]%asi
14837c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x58]%asi
14847c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x60]%asi
14857c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x68]%asi
14867c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x70]%asi
14877c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x78]%asi
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x88]%asi
14907c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x90]%asi
14917c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x98]%asi
14927c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xa0]%asi
14937c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xa8]%asi
14947c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xb0]%asi
14957c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xb8]%asi
14967c478bd9Sstevel@tonic-gate
14977c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xc8]%asi
14987c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xd0]%asi
14997c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xd8]%asi
15007c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xe0]%asi
15017c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xe8]%asi
15027c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xf0]%asi
15037c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xf8]%asi
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate	sub	%o4, 0x100, %o4
15067c478bd9Sstevel@tonic-gate	cmp	%o4, 0x100
15077c478bd9Sstevel@tonic-gate	bgu,pt	%ncc, 2b
15087c478bd9Sstevel@tonic-gate	add	%o0, 0x100, %o0
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate3:
15117c478bd9Sstevel@tonic-gate	! ... check if 64 bytes to set
15127c478bd9Sstevel@tonic-gate	cmp	%o4, 0x40
15137c478bd9Sstevel@tonic-gate	blu	%ncc, .bzero_blk_done
15147c478bd9Sstevel@tonic-gate	nop
15157c478bd9Sstevel@tonic-gate
15167c478bd9Sstevel@tonic-gate4:
15177c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x0]%asi
15187c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x8]%asi
15197c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x10]%asi
15207c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x18]%asi
15217c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x20]%asi
15227c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x28]%asi
15237c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x30]%asi
15247c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x38]%asi
15257c478bd9Sstevel@tonic-gate
15267c478bd9Sstevel@tonic-gate	subcc	%o4, 0x40, %o4
15277c478bd9Sstevel@tonic-gate	bgu,pt	%ncc, 3b
15287c478bd9Sstevel@tonic-gate	add	%o0, 0x40, %o0
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate.bzero_blk_done:
15317c478bd9Sstevel@tonic-gate	membar	#Sync
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate.bzero_small:
15347c478bd9Sstevel@tonic-gate	! Set the remaining doubles
15357c478bd9Sstevel@tonic-gate	subcc	%o3, 8, %o3		! Can we store any doubles?
15367c478bd9Sstevel@tonic-gate	blu,pn	%ncc, .byteclr
15377c478bd9Sstevel@tonic-gate	and	%o1, 7, %o1		! calc bytes left after doubles
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate.dbclr:
15407c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi		! Clear the doubles
15417c478bd9Sstevel@tonic-gate	subcc	%o3, 8, %o3
15427c478bd9Sstevel@tonic-gate	bgeu,pt	%ncc, .dbclr
15437c478bd9Sstevel@tonic-gate	add	%o0, 8, %o0
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate	ba	.byteclr
15467c478bd9Sstevel@tonic-gate	nop
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate.wdalign:
15497c478bd9Sstevel@tonic-gate	andcc	%o0, 3, %o3		! is add aligned on a word boundary
15507c478bd9Sstevel@tonic-gate	bz,pn	%ncc, .wdclr
15517c478bd9Sstevel@tonic-gate	andn	%o1, 3, %o3		! create word sized count in %o3
15527c478bd9Sstevel@tonic-gate
15537c478bd9Sstevel@tonic-gate	dec	%o1			! decrement count
15547c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi		! clear a byte
15557c478bd9Sstevel@tonic-gate	ba	.wdalign
15567c478bd9Sstevel@tonic-gate	inc	%o0			! next byte
15577c478bd9Sstevel@tonic-gate
15587c478bd9Sstevel@tonic-gate.wdclr:
15597c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi		! 4-byte clearing loop
15607c478bd9Sstevel@tonic-gate	subcc	%o3, 4, %o3
15617c478bd9Sstevel@tonic-gate	bnz,pt	%ncc, .wdclr
15627c478bd9Sstevel@tonic-gate	inc	4, %o0
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate	and	%o1, 3, %o1		! leftover count, if any
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate.byteclr:
15677c478bd9Sstevel@tonic-gate	! Set the leftover bytes
15687c478bd9Sstevel@tonic-gate	brz	%o1, .bzero_exit
15697c478bd9Sstevel@tonic-gate	nop
15707c478bd9Sstevel@tonic-gate
15717c478bd9Sstevel@tonic-gate7:
15727c478bd9Sstevel@tonic-gate	deccc	%o1			! byte clearing loop
15737c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi
15747c478bd9Sstevel@tonic-gate	bgu,pt	%ncc, 7b
15757c478bd9Sstevel@tonic-gate	inc	%o0
15767c478bd9Sstevel@tonic-gate
15777c478bd9Sstevel@tonic-gate.bzero_exit:
15787c478bd9Sstevel@tonic-gate	!
15797c478bd9Sstevel@tonic-gate	! We're just concerned with whether t_lofault was set
15807c478bd9Sstevel@tonic-gate	! when we came in. We end up here from either kzero()
15817c478bd9Sstevel@tonic-gate	! or bzero(). kzero() *always* sets a lofault handler.
15827c478bd9Sstevel@tonic-gate	! It ors LOFAULT_SET into %o5 to indicate it has done
15837c478bd9Sstevel@tonic-gate	! this even if the value of %o5 is otherwise zero.
15847c478bd9Sstevel@tonic-gate	! bzero() sets a lofault handler *only* if one was
15857c478bd9Sstevel@tonic-gate	! previously set. Accordingly we need to examine
15867c478bd9Sstevel@tonic-gate	! %o5 and if it is non-zero be sure to clear LOFAULT_SET
15877c478bd9Sstevel@tonic-gate	! before resetting the error handler.
15887c478bd9Sstevel@tonic-gate	!
15897c478bd9Sstevel@tonic-gate	tst	%o5
15907c478bd9Sstevel@tonic-gate	bz	%ncc, 1f
15917c478bd9Sstevel@tonic-gate	andn	%o5, LOFAULT_SET, %o5
15927c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
15937c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
15947c478bd9Sstevel@tonic-gate1:
15957c478bd9Sstevel@tonic-gate	retl
15967c478bd9Sstevel@tonic-gate	clr	%o0			! return (0)
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate	SET_SIZE(bzero)
15997c478bd9Sstevel@tonic-gate#endif	/* lint */
1600