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