xref: /illumos-gate/usr/src/uts/sun4u/ml/mach_copy.S (revision 55fea89d)
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
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate/*
237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate#include <sys/param.h>
287c478bd9Sstevel@tonic-gate#include <sys/errno.h>
297c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
307c478bd9Sstevel@tonic-gate#include <sys/vtrace.h>
317c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
327c478bd9Sstevel@tonic-gate#include <sys/clock.h>
337c478bd9Sstevel@tonic-gate#include <sys/asi.h>
347c478bd9Sstevel@tonic-gate#include <sys/fsr.h>
357c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate#include "assym.h"
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate#define	FP_USED 1
407c478bd9Sstevel@tonic-gate#define	LOFAULT_SET 2
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate/*
437c478bd9Sstevel@tonic-gate * Error barrier:
447c478bd9Sstevel@tonic-gate * We use membar sync to establish an error barrier for
457c478bd9Sstevel@tonic-gate * deferred errors. Membar syncs are added before any update
467c478bd9Sstevel@tonic-gate * to t_lofault to ensure that deferred errors from earlier
477c478bd9Sstevel@tonic-gate * accesses will not be reported after the membar. This error
487c478bd9Sstevel@tonic-gate * isolation is important when we try to recover from async
497c478bd9Sstevel@tonic-gate * errors which tries to distinguish kernel accesses to user
507c478bd9Sstevel@tonic-gate * data.
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate/*
547c478bd9Sstevel@tonic-gate * Zero a block of storage.
557c478bd9Sstevel@tonic-gate *
567c478bd9Sstevel@tonic-gate * uzero is used by the kernel to zero a block in user address space.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate	ENTRY(uzero)
607c478bd9Sstevel@tonic-gate	!
617c478bd9Sstevel@tonic-gate	! Set a new lo_fault handler only if we came in with one
627c478bd9Sstevel@tonic-gate	! already specified.
637c478bd9Sstevel@tonic-gate	!
647c478bd9Sstevel@tonic-gate	wr	%g0, ASI_USER, %asi
657c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
667c478bd9Sstevel@tonic-gate	tst	%o5
677c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .do_zero
687c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
697c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
707c478bd9Sstevel@tonic-gate	membar	#Sync
717c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .do_zero
727c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate	ENTRY(kzero)
757c478bd9Sstevel@tonic-gate	!
767c478bd9Sstevel@tonic-gate	! Always set a lo_fault handler
777c478bd9Sstevel@tonic-gate	!
787c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
797c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
807c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
817c478bd9Sstevel@tonic-gate	or	%o5, LOFAULT_SET, %o5
827c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
837c478bd9Sstevel@tonic-gate	membar	#Sync
847c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .do_zero
857c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate/*
887c478bd9Sstevel@tonic-gate * We got here because of a fault during kzero or if
897c478bd9Sstevel@tonic-gate * uzero or bzero was called with t_lofault non-zero.
907c478bd9Sstevel@tonic-gate * Otherwise we've already run screaming from the room.
917c478bd9Sstevel@tonic-gate * Errno value is in %g1. Note that we're here iff
927c478bd9Sstevel@tonic-gate * we did set t_lofault.
937c478bd9Sstevel@tonic-gate */
947c478bd9Sstevel@tonic-gate.zeroerr:
957c478bd9Sstevel@tonic-gate	!
967c478bd9Sstevel@tonic-gate	! Undo asi register setting. Just set it to be the
977c478bd9Sstevel@tonic-gate        ! kernel default without checking.
987c478bd9Sstevel@tonic-gate	!
997c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
1007c478bd9Sstevel@tonic-gate	!
1017c478bd9Sstevel@tonic-gate	! If saved t_lofault has FP_USED set, clear the %fprs register
1027c478bd9Sstevel@tonic-gate	!
1037c478bd9Sstevel@tonic-gate	btst	FP_USED, %o5
1047c478bd9Sstevel@tonic-gate	bz,pt	%ncc, 1f		! skip if not used
1057c478bd9Sstevel@tonic-gate	nop
1067c478bd9Sstevel@tonic-gate	membar #Sync
1077c478bd9Sstevel@tonic-gate	wr	%g0, %g0, %fprs		! clear fprs
1087c478bd9Sstevel@tonic-gate	andn	%o5, FP_USED, %o5	! turn off flag bit
1097c478bd9Sstevel@tonic-gate	!
1107c478bd9Sstevel@tonic-gate	! We did set t_lofault. It may well have been zero coming in.
1117c478bd9Sstevel@tonic-gate	!
1127c478bd9Sstevel@tonic-gate1:
1137c478bd9Sstevel@tonic-gate	tst	%o5
1147c478bd9Sstevel@tonic-gate	membar #Sync
115*55fea89dSDan Cross	bne,pn	%ncc, 3f
1167c478bd9Sstevel@tonic-gate	andncc	%o5, LOFAULT_SET, %o5
1177c478bd9Sstevel@tonic-gate2:
1187c478bd9Sstevel@tonic-gate	!
1197c478bd9Sstevel@tonic-gate	! Old handler was zero. Just return the error.
1207c478bd9Sstevel@tonic-gate	!
1217c478bd9Sstevel@tonic-gate	retl				! return
1227c478bd9Sstevel@tonic-gate	mov	%g1, %o0		! error code from %g1
1237c478bd9Sstevel@tonic-gate3:
1247c478bd9Sstevel@tonic-gate	!
1257c478bd9Sstevel@tonic-gate	! We're here because %o5 was non-zero. It was non-zero
1267c478bd9Sstevel@tonic-gate	! because either LOFAULT_SET was present, a previous fault
1277c478bd9Sstevel@tonic-gate	! handler was present or both. In all cases we need to reset
1287c478bd9Sstevel@tonic-gate	! T_LOFAULT to the value of %o5 after clearing LOFAULT_SET
1297c478bd9Sstevel@tonic-gate	! before we either simply return the error or we invoke the
1307c478bd9Sstevel@tonic-gate	! previously specified handler.
1317c478bd9Sstevel@tonic-gate	!
1327c478bd9Sstevel@tonic-gate	be	%ncc, 2b
1337c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]
1347c478bd9Sstevel@tonic-gate	jmp	%o5			! goto real handler
1357c478bd9Sstevel@tonic-gate	  nop
1367c478bd9Sstevel@tonic-gate	SET_SIZE(kzero)
1377c478bd9Sstevel@tonic-gate	SET_SIZE(uzero)
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate/*
1407c478bd9Sstevel@tonic-gate * Zero a block of storage.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate	ENTRY(bzero)
1447c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5	! save old vector
1477c478bd9Sstevel@tonic-gate	tst	%o5
1487c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .do_zero
1497c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
1507c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
1517c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
1527c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]	! install new vector
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate.do_zero:
1557c478bd9Sstevel@tonic-gate	cmp	%o1, 15			! check for small counts
1567c478bd9Sstevel@tonic-gate	blu,pn	%ncc, .byteclr		! just clear bytes
1577c478bd9Sstevel@tonic-gate	nop
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate	cmp	%o1, 192		! check for large counts
1607c478bd9Sstevel@tonic-gate	blu	%ncc, .bzero_small
1617c478bd9Sstevel@tonic-gate	nop
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate	sethi	%hi(use_hw_bzero), %o2
1647c478bd9Sstevel@tonic-gate	ld	[%o2 + %lo(use_hw_bzero)], %o2
1657c478bd9Sstevel@tonic-gate	tst	%o2
1667c478bd9Sstevel@tonic-gate	bz	%icc, .bzero_small
1677c478bd9Sstevel@tonic-gate	nop
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate	rd	%fprs, %o2		! check for unused fp
1707c478bd9Sstevel@tonic-gate	btst	FPRS_FEF, %o2
1717c478bd9Sstevel@tonic-gate	bnz	%icc, .bzero_small
1727c478bd9Sstevel@tonic-gate	nop
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LWP], %o2
1757c478bd9Sstevel@tonic-gate	tst	%o2
1767c478bd9Sstevel@tonic-gate	bz,pn	%ncc, .bzero_small
1777c478bd9Sstevel@tonic-gate	nop
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate	! Check for block alignment
1807c478bd9Sstevel@tonic-gate	btst	(64-1), %o0
1817c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_block
1827c478bd9Sstevel@tonic-gate	nop
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate	! Check for double-word alignment
1857c478bd9Sstevel@tonic-gate	btst	(8-1), %o0
1867c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_dword
1877c478bd9Sstevel@tonic-gate	nop
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate	! Check for word alignment
1907c478bd9Sstevel@tonic-gate	btst	(4-1), %o0
1917c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_word
1927c478bd9Sstevel@tonic-gate	nop
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate	! Clear bytes until word aligned
1957c478bd9Sstevel@tonic-gate.bzl_byte:
1967c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi
1977c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0
1987c478bd9Sstevel@tonic-gate	btst	(4-1), %o0
1997c478bd9Sstevel@tonic-gate	bnz	%icc, .bzl_byte
2007c478bd9Sstevel@tonic-gate	sub	%o1, 1, %o1
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate	! Check for dword-aligned
2037c478bd9Sstevel@tonic-gate	btst	(8-1), %o0
2047c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_dword
2057c478bd9Sstevel@tonic-gate	nop
206*55fea89dSDan Cross
2077c478bd9Sstevel@tonic-gate	! Clear words until double-word aligned
2087c478bd9Sstevel@tonic-gate.bzl_word:
2097c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi
2107c478bd9Sstevel@tonic-gate	add	%o0, 4, %o0
2117c478bd9Sstevel@tonic-gate	btst	(8-1), %o0
2127c478bd9Sstevel@tonic-gate	bnz	%icc, .bzl_word
2137c478bd9Sstevel@tonic-gate	sub	%o1, 4, %o1
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate.bzl_dword:
2167c478bd9Sstevel@tonic-gate	! Clear dwords until block aligned
2177c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
2187c478bd9Sstevel@tonic-gate	add	%o0, 8, %o0
2197c478bd9Sstevel@tonic-gate	btst	(64-1), %o0
2207c478bd9Sstevel@tonic-gate	bnz	%icc, .bzl_dword
2217c478bd9Sstevel@tonic-gate	sub	%o1, 8, %o1
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate.bzl_block:
2247c478bd9Sstevel@tonic-gate	membar	#StoreStore|#StoreLoad|#LoadStore
2257c478bd9Sstevel@tonic-gate	wr	%g0, FPRS_FEF, %fprs
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate	! Set the lower bit in the saved t_lofault to indicate
2287c478bd9Sstevel@tonic-gate	! that we need to clear the %fprs register on the way
2297c478bd9Sstevel@tonic-gate	! out
2307c478bd9Sstevel@tonic-gate	or	%o5, FP_USED, %o5
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate	! Clear block
2337c478bd9Sstevel@tonic-gate	fzero	%d0
2347c478bd9Sstevel@tonic-gate	fzero	%d2
2357c478bd9Sstevel@tonic-gate	fzero	%d4
2367c478bd9Sstevel@tonic-gate	fzero	%d6
2377c478bd9Sstevel@tonic-gate	fzero	%d8
2387c478bd9Sstevel@tonic-gate	fzero	%d10
2397c478bd9Sstevel@tonic-gate	fzero	%d12
2407c478bd9Sstevel@tonic-gate	fzero	%d14
2417c478bd9Sstevel@tonic-gate	rd	%asi, %o3
2427c478bd9Sstevel@tonic-gate	wr	%g0, ASI_BLK_P, %asi
2437c478bd9Sstevel@tonic-gate	cmp	%o3, ASI_P
2447c478bd9Sstevel@tonic-gate	bne,a	%icc, 1f
2457c478bd9Sstevel@tonic-gate	wr	%g0, ASI_BLK_AIUS, %asi
246*55fea89dSDan Cross1:
2477c478bd9Sstevel@tonic-gate	mov	256, %o3
2487c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzl_doblock
2497c478bd9Sstevel@tonic-gate	nop
2507c478bd9Sstevel@tonic-gate
251*55fea89dSDan Cross.bzl_blkstart:
2527c478bd9Sstevel@tonic-gate      ! stda	%d0, [%o0+192]%asi  ! in dly slot of branch that got us here
2537c478bd9Sstevel@tonic-gate	stda	%d0, [%o0+128]%asi
2547c478bd9Sstevel@tonic-gate	stda	%d0, [%o0+64]%asi
2557c478bd9Sstevel@tonic-gate	stda	%d0, [%o0]%asi
2567c478bd9Sstevel@tonic-gate.bzl_zinst:
2577c478bd9Sstevel@tonic-gate	add	%o0, %o3, %o0
2587c478bd9Sstevel@tonic-gate	sub	%o1, %o3, %o1
2597c478bd9Sstevel@tonic-gate.bzl_doblock:
2607c478bd9Sstevel@tonic-gate	cmp	%o1, 256
2617c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, .bzl_blkstart
2627c478bd9Sstevel@tonic-gate	stda	%d0, [%o0+192]%asi
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate	cmp	%o1, 64
2657c478bd9Sstevel@tonic-gate	blu	%ncc, .bzl_finish
266*55fea89dSDan Cross
2677c478bd9Sstevel@tonic-gate	andn	%o1, (64-1), %o3
2687c478bd9Sstevel@tonic-gate	srl	%o3, 4, %o2		! using blocks, 1 instr / 16 words
2697c478bd9Sstevel@tonic-gate	set	.bzl_zinst, %o4
2707c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4
2717c478bd9Sstevel@tonic-gate	jmp	%o4
2727c478bd9Sstevel@tonic-gate	nop
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate.bzl_finish:
2757c478bd9Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
2767c478bd9Sstevel@tonic-gate	wr	%g0, %g0, %fprs
2777c478bd9Sstevel@tonic-gate	andn	%o5, FP_USED, %o5
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate	rd	%asi, %o4
2807c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
2817c478bd9Sstevel@tonic-gate	cmp	%o4, ASI_BLK_P
2827c478bd9Sstevel@tonic-gate	bne,a	%icc, 1f
2837c478bd9Sstevel@tonic-gate	wr	%g0, ASI_USER, %asi
2847c478bd9Sstevel@tonic-gate1:
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate.bzlf_dword:
2877c478bd9Sstevel@tonic-gate	! double words
2887c478bd9Sstevel@tonic-gate	cmp	%o1, 8
2897c478bd9Sstevel@tonic-gate	blu	%ncc, .bzlf_word
2907c478bd9Sstevel@tonic-gate	nop
2917c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
2927c478bd9Sstevel@tonic-gate	add	%o0, 8, %o0
2937c478bd9Sstevel@tonic-gate	sub	%o1, 8, %o1
2947c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzlf_dword
2957c478bd9Sstevel@tonic-gate	nop
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate.bzlf_word:
2987c478bd9Sstevel@tonic-gate	! words
2997c478bd9Sstevel@tonic-gate	cmp	%o1, 4
3007c478bd9Sstevel@tonic-gate	blu	%ncc, .bzlf_byte
3017c478bd9Sstevel@tonic-gate	nop
3027c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi
3037c478bd9Sstevel@tonic-gate	add	%o0, 4, %o0
3047c478bd9Sstevel@tonic-gate	sub	%o1, 4, %o1
3057c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzlf_word
3067c478bd9Sstevel@tonic-gate	nop
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate1:
3097c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0		! increment address
3107c478bd9Sstevel@tonic-gate.bzlf_byte:
3117c478bd9Sstevel@tonic-gate	subcc	%o1, 1, %o1		! decrement count
3127c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 1b
3137c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi		! zero a byte
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate	!
3167c478bd9Sstevel@tonic-gate	! If we used the FP registers, that bit was turned
3177c478bd9Sstevel@tonic-gate	! off after we were finished. We're just concerned with
3187c478bd9Sstevel@tonic-gate	! whether t_lofault was set when we came in. We end up
3197c478bd9Sstevel@tonic-gate	! here from either kzero() or bzero(). kzero() *always*
320*55fea89dSDan Cross	! sets a lofault handler. It ors LOFAULT_SET into %o5
3217c478bd9Sstevel@tonic-gate	! to indicate it has done this even if the value of %o5
3227c478bd9Sstevel@tonic-gate	! is otherwise zero. bzero() sets a lofault handler *only*
3237c478bd9Sstevel@tonic-gate	! if one was previously set. Accordingly we need to examine
3247c478bd9Sstevel@tonic-gate	! %o5 and if it is non-zero be sure to clear LOFAULT_SET
3257c478bd9Sstevel@tonic-gate	! before resetting the error handler.
3267c478bd9Sstevel@tonic-gate	!
3277c478bd9Sstevel@tonic-gate	tst	%o5
328*55fea89dSDan Cross	bz,pt	%ncc, 1f
3297c478bd9Sstevel@tonic-gate	andn	%o5, LOFAULT_SET, %o5
3307c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
3317c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
3327c478bd9Sstevel@tonic-gate1:
3337c478bd9Sstevel@tonic-gate	retl
3347c478bd9Sstevel@tonic-gate	clr	%o0			! return (0)
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate.bzero_small:
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate	!
3397c478bd9Sstevel@tonic-gate	! Check for word alignment.
3407c478bd9Sstevel@tonic-gate	!
3417c478bd9Sstevel@tonic-gate	btst	3, %o0
3427c478bd9Sstevel@tonic-gate	bz	.bzero_probe
3437c478bd9Sstevel@tonic-gate	mov	0x100, %o3		! constant size of main loop
3447c478bd9Sstevel@tonic-gate	!
3457c478bd9Sstevel@tonic-gate	!
3467c478bd9Sstevel@tonic-gate	! clear bytes until word aligned
3477c478bd9Sstevel@tonic-gate	!
3487c478bd9Sstevel@tonic-gate1:	stba	%g0,[%o0]%asi
3497c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0
3507c478bd9Sstevel@tonic-gate	btst	3, %o0
3517c478bd9Sstevel@tonic-gate	bnz	1b
3527c478bd9Sstevel@tonic-gate	sub	%o1, 1, %o1
3537c478bd9Sstevel@tonic-gate.bzero_probe:
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate	!
3567c478bd9Sstevel@tonic-gate	! if needed move a word to become double-word aligned.
3577c478bd9Sstevel@tonic-gate	!
3587c478bd9Sstevel@tonic-gate	btst	7, %o0			! is double aligned?
3597c478bd9Sstevel@tonic-gate	bz	%icc, .bzero_nobuf
3607c478bd9Sstevel@tonic-gate	nop
3617c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi		! clr to double boundry
3627c478bd9Sstevel@tonic-gate	sub	%o1, 4, %o1
3637c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzero_nobuf
3647c478bd9Sstevel@tonic-gate	add	%o0, 4, %o0
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate	!stxa	%g0, [%o0+0xf8]%asi
3677c478bd9Sstevel@tonic-gate.bzero_blk:
3687c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xf0]%asi
3697c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xe8]%asi
3707c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xe0]%asi
3717c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xd8]%asi
3727c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xd0]%asi
3737c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xc8]%asi
3747c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xc0]%asi
3757c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xb8]%asi
3767c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xb0]%asi
3777c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xa8]%asi
3787c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xa0]%asi
3797c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x98]%asi
3807c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x90]%asi
3817c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x88]%asi
3827c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x80]%asi
3837c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x78]%asi
3847c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x70]%asi
3857c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x68]%asi
3867c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x60]%asi
3877c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x58]%asi
3887c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x50]%asi
3897c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x48]%asi
3907c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x40]%asi
3917c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x38]%asi
3927c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x30]%asi
3937c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x28]%asi
3947c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x20]%asi
3957c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x18]%asi
3967c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x10]%asi
3977c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x08]%asi
3987c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
3997c478bd9Sstevel@tonic-gate.zinst:
4007c478bd9Sstevel@tonic-gate	add	%o0, %o3, %o0		! increment source address
4017c478bd9Sstevel@tonic-gate	sub	%o1, %o3, %o1		! decrement count
4027c478bd9Sstevel@tonic-gate.bzero_nobuf:
4037c478bd9Sstevel@tonic-gate	cmp	%o1, 0x100		! can we do whole chunk?
4047c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, .bzero_blk
4057c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xf8]%asi	! do first double of chunk
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate	cmp	%o1, 7			! can we zero any more double words
4087c478bd9Sstevel@tonic-gate	bleu	%ncc, .byteclr		! too small go zero bytes
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate	andn	%o1, 7, %o3		! %o3 bytes left, double-word aligned
4117c478bd9Sstevel@tonic-gate	srl	%o3, 1, %o2		! using doubles, need 1 instr / 2 words
4127c478bd9Sstevel@tonic-gate	set	.zinst, %o4		! address of clr instructions
4137c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4		! jmp address relative to instr
4147c478bd9Sstevel@tonic-gate	jmp	%o4
4157c478bd9Sstevel@tonic-gate	nop
4167c478bd9Sstevel@tonic-gate	!
4177c478bd9Sstevel@tonic-gate	! do leftover bytes
4187c478bd9Sstevel@tonic-gate	!
4197c478bd9Sstevel@tonic-gate3:
4207c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0		! increment address
4217c478bd9Sstevel@tonic-gate.byteclr:
4227c478bd9Sstevel@tonic-gate	subcc	%o1, 1, %o1		! decrement count
4237c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 3b
4247c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi		! zero a byte
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate.bzero_finished:
4277c478bd9Sstevel@tonic-gate	!
4287c478bd9Sstevel@tonic-gate	! We're just concerned with whether t_lofault was set
4297c478bd9Sstevel@tonic-gate	! when we came in. We end up here from either kzero()
4307c478bd9Sstevel@tonic-gate	! or bzero(). kzero() *always* sets a lofault handler.
4317c478bd9Sstevel@tonic-gate	! It ors LOFAULT_SET into %o5 to indicate it has done
4327c478bd9Sstevel@tonic-gate	! this even if the value of %o5 is otherwise zero.
4337c478bd9Sstevel@tonic-gate	! bzero() sets a lofault handler *only* if one was
4347c478bd9Sstevel@tonic-gate	! previously set. Accordingly we need to examine
4357c478bd9Sstevel@tonic-gate	! %o5 and if it is non-zero be sure to clear LOFAULT_SET
4367c478bd9Sstevel@tonic-gate	! before resetting the error handler.
4377c478bd9Sstevel@tonic-gate	!
4387c478bd9Sstevel@tonic-gate	tst	%o5
4397c478bd9Sstevel@tonic-gate	bz	%ncc, 1f
4407c478bd9Sstevel@tonic-gate	andn	%o5, LOFAULT_SET, %o5
4417c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
4427c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
4437c478bd9Sstevel@tonic-gate1:
4447c478bd9Sstevel@tonic-gate	retl
4457c478bd9Sstevel@tonic-gate	clr	%o0			! return (0)
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate	SET_SIZE(bzero)
448