xref: /titanic_50/usr/src/uts/sun4u/ml/mach_copy.s (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate/*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate/*
23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate#include <sys/param.h>
30*7c478bd9Sstevel@tonic-gate#include <sys/errno.h>
31*7c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
32*7c478bd9Sstevel@tonic-gate#include <sys/vtrace.h>
33*7c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
34*7c478bd9Sstevel@tonic-gate#include <sys/clock.h>
35*7c478bd9Sstevel@tonic-gate#include <sys/asi.h>
36*7c478bd9Sstevel@tonic-gate#include <sys/fsr.h>
37*7c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
38*7c478bd9Sstevel@tonic-gate
39*7c478bd9Sstevel@tonic-gate#if !defined(lint)
40*7c478bd9Sstevel@tonic-gate#include "assym.h"
41*7c478bd9Sstevel@tonic-gate#endif	/* lint */
42*7c478bd9Sstevel@tonic-gate
43*7c478bd9Sstevel@tonic-gate#define	FP_USED 1
44*7c478bd9Sstevel@tonic-gate#define	LOFAULT_SET 2
45*7c478bd9Sstevel@tonic-gate
46*7c478bd9Sstevel@tonic-gate/*
47*7c478bd9Sstevel@tonic-gate * Error barrier:
48*7c478bd9Sstevel@tonic-gate * We use membar sync to establish an error barrier for
49*7c478bd9Sstevel@tonic-gate * deferred errors. Membar syncs are added before any update
50*7c478bd9Sstevel@tonic-gate * to t_lofault to ensure that deferred errors from earlier
51*7c478bd9Sstevel@tonic-gate * accesses will not be reported after the membar. This error
52*7c478bd9Sstevel@tonic-gate * isolation is important when we try to recover from async
53*7c478bd9Sstevel@tonic-gate * errors which tries to distinguish kernel accesses to user
54*7c478bd9Sstevel@tonic-gate * data.
55*7c478bd9Sstevel@tonic-gate */
56*7c478bd9Sstevel@tonic-gate
57*7c478bd9Sstevel@tonic-gate/*
58*7c478bd9Sstevel@tonic-gate * Zero a block of storage.
59*7c478bd9Sstevel@tonic-gate *
60*7c478bd9Sstevel@tonic-gate * uzero is used by the kernel to zero a block in user address space.
61*7c478bd9Sstevel@tonic-gate */
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate#if defined(lint)
64*7c478bd9Sstevel@tonic-gate
65*7c478bd9Sstevel@tonic-gate/* ARGSUSED */
66*7c478bd9Sstevel@tonic-gateint
67*7c478bd9Sstevel@tonic-gatekzero(void *addr, size_t count)
68*7c478bd9Sstevel@tonic-gate{ return(0); }
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate/* ARGSUSED */
71*7c478bd9Sstevel@tonic-gatevoid
72*7c478bd9Sstevel@tonic-gateuzero(void *addr, size_t count)
73*7c478bd9Sstevel@tonic-gate{}
74*7c478bd9Sstevel@tonic-gate
75*7c478bd9Sstevel@tonic-gate#else	/* lint */
76*7c478bd9Sstevel@tonic-gate
77*7c478bd9Sstevel@tonic-gate	ENTRY(uzero)
78*7c478bd9Sstevel@tonic-gate	!
79*7c478bd9Sstevel@tonic-gate	! Set a new lo_fault handler only if we came in with one
80*7c478bd9Sstevel@tonic-gate	! already specified.
81*7c478bd9Sstevel@tonic-gate	!
82*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_USER, %asi
83*7c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
84*7c478bd9Sstevel@tonic-gate	tst	%o5
85*7c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .do_zero
86*7c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
87*7c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
88*7c478bd9Sstevel@tonic-gate	membar	#Sync
89*7c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .do_zero
90*7c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]
91*7c478bd9Sstevel@tonic-gate
92*7c478bd9Sstevel@tonic-gate	ENTRY(kzero)
93*7c478bd9Sstevel@tonic-gate	!
94*7c478bd9Sstevel@tonic-gate	! Always set a lo_fault handler
95*7c478bd9Sstevel@tonic-gate	!
96*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
97*7c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5
98*7c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
99*7c478bd9Sstevel@tonic-gate	or	%o5, LOFAULT_SET, %o5
100*7c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
101*7c478bd9Sstevel@tonic-gate	membar	#Sync
102*7c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .do_zero
103*7c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]
104*7c478bd9Sstevel@tonic-gate
105*7c478bd9Sstevel@tonic-gate/*
106*7c478bd9Sstevel@tonic-gate * We got here because of a fault during kzero or if
107*7c478bd9Sstevel@tonic-gate * uzero or bzero was called with t_lofault non-zero.
108*7c478bd9Sstevel@tonic-gate * Otherwise we've already run screaming from the room.
109*7c478bd9Sstevel@tonic-gate * Errno value is in %g1. Note that we're here iff
110*7c478bd9Sstevel@tonic-gate * we did set t_lofault.
111*7c478bd9Sstevel@tonic-gate */
112*7c478bd9Sstevel@tonic-gate.zeroerr:
113*7c478bd9Sstevel@tonic-gate	!
114*7c478bd9Sstevel@tonic-gate	! Undo asi register setting. Just set it to be the
115*7c478bd9Sstevel@tonic-gate        ! kernel default without checking.
116*7c478bd9Sstevel@tonic-gate	!
117*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
118*7c478bd9Sstevel@tonic-gate	!
119*7c478bd9Sstevel@tonic-gate	! If saved t_lofault has FP_USED set, clear the %fprs register
120*7c478bd9Sstevel@tonic-gate	!
121*7c478bd9Sstevel@tonic-gate	btst	FP_USED, %o5
122*7c478bd9Sstevel@tonic-gate	bz,pt	%ncc, 1f		! skip if not used
123*7c478bd9Sstevel@tonic-gate	nop
124*7c478bd9Sstevel@tonic-gate	membar #Sync
125*7c478bd9Sstevel@tonic-gate	wr	%g0, %g0, %fprs		! clear fprs
126*7c478bd9Sstevel@tonic-gate	andn	%o5, FP_USED, %o5	! turn off flag bit
127*7c478bd9Sstevel@tonic-gate	!
128*7c478bd9Sstevel@tonic-gate	! We did set t_lofault. It may well have been zero coming in.
129*7c478bd9Sstevel@tonic-gate	!
130*7c478bd9Sstevel@tonic-gate1:
131*7c478bd9Sstevel@tonic-gate	tst	%o5
132*7c478bd9Sstevel@tonic-gate	membar #Sync
133*7c478bd9Sstevel@tonic-gate	bne,pn	%ncc, 3f
134*7c478bd9Sstevel@tonic-gate	andncc	%o5, LOFAULT_SET, %o5
135*7c478bd9Sstevel@tonic-gate2:
136*7c478bd9Sstevel@tonic-gate	!
137*7c478bd9Sstevel@tonic-gate	! Old handler was zero. Just return the error.
138*7c478bd9Sstevel@tonic-gate	!
139*7c478bd9Sstevel@tonic-gate	retl				! return
140*7c478bd9Sstevel@tonic-gate	mov	%g1, %o0		! error code from %g1
141*7c478bd9Sstevel@tonic-gate3:
142*7c478bd9Sstevel@tonic-gate	!
143*7c478bd9Sstevel@tonic-gate	! We're here because %o5 was non-zero. It was non-zero
144*7c478bd9Sstevel@tonic-gate	! because either LOFAULT_SET was present, a previous fault
145*7c478bd9Sstevel@tonic-gate	! handler was present or both. In all cases we need to reset
146*7c478bd9Sstevel@tonic-gate	! T_LOFAULT to the value of %o5 after clearing LOFAULT_SET
147*7c478bd9Sstevel@tonic-gate	! before we either simply return the error or we invoke the
148*7c478bd9Sstevel@tonic-gate	! previously specified handler.
149*7c478bd9Sstevel@tonic-gate	!
150*7c478bd9Sstevel@tonic-gate	be	%ncc, 2b
151*7c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]
152*7c478bd9Sstevel@tonic-gate	jmp	%o5			! goto real handler
153*7c478bd9Sstevel@tonic-gate	  nop
154*7c478bd9Sstevel@tonic-gate	SET_SIZE(kzero)
155*7c478bd9Sstevel@tonic-gate	SET_SIZE(uzero)
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate#endif	/* lint */
158*7c478bd9Sstevel@tonic-gate
159*7c478bd9Sstevel@tonic-gate/*
160*7c478bd9Sstevel@tonic-gate * Zero a block of storage.
161*7c478bd9Sstevel@tonic-gate */
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate#if defined(lint)
164*7c478bd9Sstevel@tonic-gate
165*7c478bd9Sstevel@tonic-gate/* ARGSUSED */
166*7c478bd9Sstevel@tonic-gatevoid
167*7c478bd9Sstevel@tonic-gatebzero(void *addr, size_t count)
168*7c478bd9Sstevel@tonic-gate{}
169*7c478bd9Sstevel@tonic-gate
170*7c478bd9Sstevel@tonic-gate#else	/* lint */
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate	ENTRY(bzero)
173*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
174*7c478bd9Sstevel@tonic-gate
175*7c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5	! save old vector
176*7c478bd9Sstevel@tonic-gate	tst	%o5
177*7c478bd9Sstevel@tonic-gate	bz,pt	%ncc, .do_zero
178*7c478bd9Sstevel@tonic-gate	sethi	%hi(.zeroerr), %o2
179*7c478bd9Sstevel@tonic-gate	or	%o2, %lo(.zeroerr), %o2
180*7c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
181*7c478bd9Sstevel@tonic-gate	stn	%o2, [THREAD_REG + T_LOFAULT]	! install new vector
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate.do_zero:
184*7c478bd9Sstevel@tonic-gate	cmp	%o1, 15			! check for small counts
185*7c478bd9Sstevel@tonic-gate	blu,pn	%ncc, .byteclr		! just clear bytes
186*7c478bd9Sstevel@tonic-gate	nop
187*7c478bd9Sstevel@tonic-gate
188*7c478bd9Sstevel@tonic-gate	cmp	%o1, 192		! check for large counts
189*7c478bd9Sstevel@tonic-gate	blu	%ncc, .bzero_small
190*7c478bd9Sstevel@tonic-gate	nop
191*7c478bd9Sstevel@tonic-gate
192*7c478bd9Sstevel@tonic-gate	sethi	%hi(use_hw_bzero), %o2
193*7c478bd9Sstevel@tonic-gate	ld	[%o2 + %lo(use_hw_bzero)], %o2
194*7c478bd9Sstevel@tonic-gate	tst	%o2
195*7c478bd9Sstevel@tonic-gate	bz	%icc, .bzero_small
196*7c478bd9Sstevel@tonic-gate	nop
197*7c478bd9Sstevel@tonic-gate
198*7c478bd9Sstevel@tonic-gate	rd	%fprs, %o2		! check for unused fp
199*7c478bd9Sstevel@tonic-gate	btst	FPRS_FEF, %o2
200*7c478bd9Sstevel@tonic-gate	bnz	%icc, .bzero_small
201*7c478bd9Sstevel@tonic-gate	nop
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LWP], %o2
204*7c478bd9Sstevel@tonic-gate	tst	%o2
205*7c478bd9Sstevel@tonic-gate	bz,pn	%ncc, .bzero_small
206*7c478bd9Sstevel@tonic-gate	nop
207*7c478bd9Sstevel@tonic-gate
208*7c478bd9Sstevel@tonic-gate	! Check for block alignment
209*7c478bd9Sstevel@tonic-gate	btst	(64-1), %o0
210*7c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_block
211*7c478bd9Sstevel@tonic-gate	nop
212*7c478bd9Sstevel@tonic-gate
213*7c478bd9Sstevel@tonic-gate	! Check for double-word alignment
214*7c478bd9Sstevel@tonic-gate	btst	(8-1), %o0
215*7c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_dword
216*7c478bd9Sstevel@tonic-gate	nop
217*7c478bd9Sstevel@tonic-gate
218*7c478bd9Sstevel@tonic-gate	! Check for word alignment
219*7c478bd9Sstevel@tonic-gate	btst	(4-1), %o0
220*7c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_word
221*7c478bd9Sstevel@tonic-gate	nop
222*7c478bd9Sstevel@tonic-gate
223*7c478bd9Sstevel@tonic-gate	! Clear bytes until word aligned
224*7c478bd9Sstevel@tonic-gate.bzl_byte:
225*7c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi
226*7c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0
227*7c478bd9Sstevel@tonic-gate	btst	(4-1), %o0
228*7c478bd9Sstevel@tonic-gate	bnz	%icc, .bzl_byte
229*7c478bd9Sstevel@tonic-gate	sub	%o1, 1, %o1
230*7c478bd9Sstevel@tonic-gate
231*7c478bd9Sstevel@tonic-gate	! Check for dword-aligned
232*7c478bd9Sstevel@tonic-gate	btst	(8-1), %o0
233*7c478bd9Sstevel@tonic-gate	bz	%icc, .bzl_dword
234*7c478bd9Sstevel@tonic-gate	nop
235*7c478bd9Sstevel@tonic-gate
236*7c478bd9Sstevel@tonic-gate	! Clear words until double-word aligned
237*7c478bd9Sstevel@tonic-gate.bzl_word:
238*7c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi
239*7c478bd9Sstevel@tonic-gate	add	%o0, 4, %o0
240*7c478bd9Sstevel@tonic-gate	btst	(8-1), %o0
241*7c478bd9Sstevel@tonic-gate	bnz	%icc, .bzl_word
242*7c478bd9Sstevel@tonic-gate	sub	%o1, 4, %o1
243*7c478bd9Sstevel@tonic-gate
244*7c478bd9Sstevel@tonic-gate.bzl_dword:
245*7c478bd9Sstevel@tonic-gate	! Clear dwords until block aligned
246*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
247*7c478bd9Sstevel@tonic-gate	add	%o0, 8, %o0
248*7c478bd9Sstevel@tonic-gate	btst	(64-1), %o0
249*7c478bd9Sstevel@tonic-gate	bnz	%icc, .bzl_dword
250*7c478bd9Sstevel@tonic-gate	sub	%o1, 8, %o1
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate.bzl_block:
253*7c478bd9Sstevel@tonic-gate	membar	#StoreStore|#StoreLoad|#LoadStore
254*7c478bd9Sstevel@tonic-gate	wr	%g0, FPRS_FEF, %fprs
255*7c478bd9Sstevel@tonic-gate
256*7c478bd9Sstevel@tonic-gate	! Set the lower bit in the saved t_lofault to indicate
257*7c478bd9Sstevel@tonic-gate	! that we need to clear the %fprs register on the way
258*7c478bd9Sstevel@tonic-gate	! out
259*7c478bd9Sstevel@tonic-gate	or	%o5, FP_USED, %o5
260*7c478bd9Sstevel@tonic-gate
261*7c478bd9Sstevel@tonic-gate	! Clear block
262*7c478bd9Sstevel@tonic-gate	fzero	%d0
263*7c478bd9Sstevel@tonic-gate	fzero	%d2
264*7c478bd9Sstevel@tonic-gate	fzero	%d4
265*7c478bd9Sstevel@tonic-gate	fzero	%d6
266*7c478bd9Sstevel@tonic-gate	fzero	%d8
267*7c478bd9Sstevel@tonic-gate	fzero	%d10
268*7c478bd9Sstevel@tonic-gate	fzero	%d12
269*7c478bd9Sstevel@tonic-gate	fzero	%d14
270*7c478bd9Sstevel@tonic-gate	rd	%asi, %o3
271*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_BLK_P, %asi
272*7c478bd9Sstevel@tonic-gate	cmp	%o3, ASI_P
273*7c478bd9Sstevel@tonic-gate	bne,a	%icc, 1f
274*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_BLK_AIUS, %asi
275*7c478bd9Sstevel@tonic-gate1:
276*7c478bd9Sstevel@tonic-gate	mov	256, %o3
277*7c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzl_doblock
278*7c478bd9Sstevel@tonic-gate	nop
279*7c478bd9Sstevel@tonic-gate
280*7c478bd9Sstevel@tonic-gate.bzl_blkstart:
281*7c478bd9Sstevel@tonic-gate      ! stda	%d0, [%o0+192]%asi  ! in dly slot of branch that got us here
282*7c478bd9Sstevel@tonic-gate	stda	%d0, [%o0+128]%asi
283*7c478bd9Sstevel@tonic-gate	stda	%d0, [%o0+64]%asi
284*7c478bd9Sstevel@tonic-gate	stda	%d0, [%o0]%asi
285*7c478bd9Sstevel@tonic-gate.bzl_zinst:
286*7c478bd9Sstevel@tonic-gate	add	%o0, %o3, %o0
287*7c478bd9Sstevel@tonic-gate	sub	%o1, %o3, %o1
288*7c478bd9Sstevel@tonic-gate.bzl_doblock:
289*7c478bd9Sstevel@tonic-gate	cmp	%o1, 256
290*7c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, .bzl_blkstart
291*7c478bd9Sstevel@tonic-gate	stda	%d0, [%o0+192]%asi
292*7c478bd9Sstevel@tonic-gate
293*7c478bd9Sstevel@tonic-gate	cmp	%o1, 64
294*7c478bd9Sstevel@tonic-gate	blu	%ncc, .bzl_finish
295*7c478bd9Sstevel@tonic-gate
296*7c478bd9Sstevel@tonic-gate	andn	%o1, (64-1), %o3
297*7c478bd9Sstevel@tonic-gate	srl	%o3, 4, %o2		! using blocks, 1 instr / 16 words
298*7c478bd9Sstevel@tonic-gate	set	.bzl_zinst, %o4
299*7c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4
300*7c478bd9Sstevel@tonic-gate	jmp	%o4
301*7c478bd9Sstevel@tonic-gate	nop
302*7c478bd9Sstevel@tonic-gate
303*7c478bd9Sstevel@tonic-gate.bzl_finish:
304*7c478bd9Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
305*7c478bd9Sstevel@tonic-gate	wr	%g0, %g0, %fprs
306*7c478bd9Sstevel@tonic-gate	andn	%o5, FP_USED, %o5
307*7c478bd9Sstevel@tonic-gate
308*7c478bd9Sstevel@tonic-gate	rd	%asi, %o4
309*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_P, %asi
310*7c478bd9Sstevel@tonic-gate	cmp	%o4, ASI_BLK_P
311*7c478bd9Sstevel@tonic-gate	bne,a	%icc, 1f
312*7c478bd9Sstevel@tonic-gate	wr	%g0, ASI_USER, %asi
313*7c478bd9Sstevel@tonic-gate1:
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate.bzlf_dword:
316*7c478bd9Sstevel@tonic-gate	! double words
317*7c478bd9Sstevel@tonic-gate	cmp	%o1, 8
318*7c478bd9Sstevel@tonic-gate	blu	%ncc, .bzlf_word
319*7c478bd9Sstevel@tonic-gate	nop
320*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
321*7c478bd9Sstevel@tonic-gate	add	%o0, 8, %o0
322*7c478bd9Sstevel@tonic-gate	sub	%o1, 8, %o1
323*7c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzlf_dword
324*7c478bd9Sstevel@tonic-gate	nop
325*7c478bd9Sstevel@tonic-gate
326*7c478bd9Sstevel@tonic-gate.bzlf_word:
327*7c478bd9Sstevel@tonic-gate	! words
328*7c478bd9Sstevel@tonic-gate	cmp	%o1, 4
329*7c478bd9Sstevel@tonic-gate	blu	%ncc, .bzlf_byte
330*7c478bd9Sstevel@tonic-gate	nop
331*7c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi
332*7c478bd9Sstevel@tonic-gate	add	%o0, 4, %o0
333*7c478bd9Sstevel@tonic-gate	sub	%o1, 4, %o1
334*7c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzlf_word
335*7c478bd9Sstevel@tonic-gate	nop
336*7c478bd9Sstevel@tonic-gate
337*7c478bd9Sstevel@tonic-gate1:
338*7c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0		! increment address
339*7c478bd9Sstevel@tonic-gate.bzlf_byte:
340*7c478bd9Sstevel@tonic-gate	subcc	%o1, 1, %o1		! decrement count
341*7c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 1b
342*7c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi		! zero a byte
343*7c478bd9Sstevel@tonic-gate
344*7c478bd9Sstevel@tonic-gate	!
345*7c478bd9Sstevel@tonic-gate	! If we used the FP registers, that bit was turned
346*7c478bd9Sstevel@tonic-gate	! off after we were finished. We're just concerned with
347*7c478bd9Sstevel@tonic-gate	! whether t_lofault was set when we came in. We end up
348*7c478bd9Sstevel@tonic-gate	! here from either kzero() or bzero(). kzero() *always*
349*7c478bd9Sstevel@tonic-gate	! sets a lofault handler. It ors LOFAULT_SET into %o5
350*7c478bd9Sstevel@tonic-gate	! to indicate it has done this even if the value of %o5
351*7c478bd9Sstevel@tonic-gate	! is otherwise zero. bzero() sets a lofault handler *only*
352*7c478bd9Sstevel@tonic-gate	! if one was previously set. Accordingly we need to examine
353*7c478bd9Sstevel@tonic-gate	! %o5 and if it is non-zero be sure to clear LOFAULT_SET
354*7c478bd9Sstevel@tonic-gate	! before resetting the error handler.
355*7c478bd9Sstevel@tonic-gate	!
356*7c478bd9Sstevel@tonic-gate	tst	%o5
357*7c478bd9Sstevel@tonic-gate	bz,pt	%ncc, 1f
358*7c478bd9Sstevel@tonic-gate	andn	%o5, LOFAULT_SET, %o5
359*7c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
360*7c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
361*7c478bd9Sstevel@tonic-gate1:
362*7c478bd9Sstevel@tonic-gate	retl
363*7c478bd9Sstevel@tonic-gate	clr	%o0			! return (0)
364*7c478bd9Sstevel@tonic-gate
365*7c478bd9Sstevel@tonic-gate.bzero_small:
366*7c478bd9Sstevel@tonic-gate
367*7c478bd9Sstevel@tonic-gate	!
368*7c478bd9Sstevel@tonic-gate	! Check for word alignment.
369*7c478bd9Sstevel@tonic-gate	!
370*7c478bd9Sstevel@tonic-gate	btst	3, %o0
371*7c478bd9Sstevel@tonic-gate	bz	.bzero_probe
372*7c478bd9Sstevel@tonic-gate	mov	0x100, %o3		! constant size of main loop
373*7c478bd9Sstevel@tonic-gate	!
374*7c478bd9Sstevel@tonic-gate	!
375*7c478bd9Sstevel@tonic-gate	! clear bytes until word aligned
376*7c478bd9Sstevel@tonic-gate	!
377*7c478bd9Sstevel@tonic-gate1:	stba	%g0,[%o0]%asi
378*7c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0
379*7c478bd9Sstevel@tonic-gate	btst	3, %o0
380*7c478bd9Sstevel@tonic-gate	bnz	1b
381*7c478bd9Sstevel@tonic-gate	sub	%o1, 1, %o1
382*7c478bd9Sstevel@tonic-gate.bzero_probe:
383*7c478bd9Sstevel@tonic-gate
384*7c478bd9Sstevel@tonic-gate	!
385*7c478bd9Sstevel@tonic-gate	! if needed move a word to become double-word aligned.
386*7c478bd9Sstevel@tonic-gate	!
387*7c478bd9Sstevel@tonic-gate	btst	7, %o0			! is double aligned?
388*7c478bd9Sstevel@tonic-gate	bz	%icc, .bzero_nobuf
389*7c478bd9Sstevel@tonic-gate	nop
390*7c478bd9Sstevel@tonic-gate	sta	%g0, [%o0]%asi		! clr to double boundry
391*7c478bd9Sstevel@tonic-gate	sub	%o1, 4, %o1
392*7c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .bzero_nobuf
393*7c478bd9Sstevel@tonic-gate	add	%o0, 4, %o0
394*7c478bd9Sstevel@tonic-gate
395*7c478bd9Sstevel@tonic-gate	!stxa	%g0, [%o0+0xf8]%asi
396*7c478bd9Sstevel@tonic-gate.bzero_blk:
397*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xf0]%asi
398*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xe8]%asi
399*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xe0]%asi
400*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xd8]%asi
401*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xd0]%asi
402*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xc8]%asi
403*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xc0]%asi
404*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xb8]%asi
405*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xb0]%asi
406*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xa8]%asi
407*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xa0]%asi
408*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x98]%asi
409*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x90]%asi
410*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x88]%asi
411*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x80]%asi
412*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x78]%asi
413*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x70]%asi
414*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x68]%asi
415*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x60]%asi
416*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x58]%asi
417*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x50]%asi
418*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x48]%asi
419*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x40]%asi
420*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x38]%asi
421*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x30]%asi
422*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x28]%asi
423*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x20]%asi
424*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x18]%asi
425*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x10]%asi
426*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0x08]%asi
427*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]%asi
428*7c478bd9Sstevel@tonic-gate.zinst:
429*7c478bd9Sstevel@tonic-gate	add	%o0, %o3, %o0		! increment source address
430*7c478bd9Sstevel@tonic-gate	sub	%o1, %o3, %o1		! decrement count
431*7c478bd9Sstevel@tonic-gate.bzero_nobuf:
432*7c478bd9Sstevel@tonic-gate	cmp	%o1, 0x100		! can we do whole chunk?
433*7c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, .bzero_blk
434*7c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0+0xf8]%asi	! do first double of chunk
435*7c478bd9Sstevel@tonic-gate
436*7c478bd9Sstevel@tonic-gate	cmp	%o1, 7			! can we zero any more double words
437*7c478bd9Sstevel@tonic-gate	bleu	%ncc, .byteclr		! too small go zero bytes
438*7c478bd9Sstevel@tonic-gate
439*7c478bd9Sstevel@tonic-gate	andn	%o1, 7, %o3		! %o3 bytes left, double-word aligned
440*7c478bd9Sstevel@tonic-gate	srl	%o3, 1, %o2		! using doubles, need 1 instr / 2 words
441*7c478bd9Sstevel@tonic-gate	set	.zinst, %o4		! address of clr instructions
442*7c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4		! jmp address relative to instr
443*7c478bd9Sstevel@tonic-gate	jmp	%o4
444*7c478bd9Sstevel@tonic-gate	nop
445*7c478bd9Sstevel@tonic-gate	!
446*7c478bd9Sstevel@tonic-gate	! do leftover bytes
447*7c478bd9Sstevel@tonic-gate	!
448*7c478bd9Sstevel@tonic-gate3:
449*7c478bd9Sstevel@tonic-gate	add	%o0, 1, %o0		! increment address
450*7c478bd9Sstevel@tonic-gate.byteclr:
451*7c478bd9Sstevel@tonic-gate	subcc	%o1, 1, %o1		! decrement count
452*7c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 3b
453*7c478bd9Sstevel@tonic-gate	stba	%g0, [%o0]%asi		! zero a byte
454*7c478bd9Sstevel@tonic-gate
455*7c478bd9Sstevel@tonic-gate.bzero_finished:
456*7c478bd9Sstevel@tonic-gate	!
457*7c478bd9Sstevel@tonic-gate	! We're just concerned with whether t_lofault was set
458*7c478bd9Sstevel@tonic-gate	! when we came in. We end up here from either kzero()
459*7c478bd9Sstevel@tonic-gate	! or bzero(). kzero() *always* sets a lofault handler.
460*7c478bd9Sstevel@tonic-gate	! It ors LOFAULT_SET into %o5 to indicate it has done
461*7c478bd9Sstevel@tonic-gate	! this even if the value of %o5 is otherwise zero.
462*7c478bd9Sstevel@tonic-gate	! bzero() sets a lofault handler *only* if one was
463*7c478bd9Sstevel@tonic-gate	! previously set. Accordingly we need to examine
464*7c478bd9Sstevel@tonic-gate	! %o5 and if it is non-zero be sure to clear LOFAULT_SET
465*7c478bd9Sstevel@tonic-gate	! before resetting the error handler.
466*7c478bd9Sstevel@tonic-gate	!
467*7c478bd9Sstevel@tonic-gate	tst	%o5
468*7c478bd9Sstevel@tonic-gate	bz	%ncc, 1f
469*7c478bd9Sstevel@tonic-gate	andn	%o5, LOFAULT_SET, %o5
470*7c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
471*7c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! restore old t_lofault
472*7c478bd9Sstevel@tonic-gate1:
473*7c478bd9Sstevel@tonic-gate	retl
474*7c478bd9Sstevel@tonic-gate	clr	%o0			! return (0)
475*7c478bd9Sstevel@tonic-gate
476*7c478bd9Sstevel@tonic-gate	SET_SIZE(bzero)
477*7c478bd9Sstevel@tonic-gate#endif	/* lint */
478