xref: /titanic_52/usr/src/uts/sun4u/sys/fpras_impl.h (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 2004 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 #ifndef	_SYS_FPRAS_IMPL_H
28*7c478bd9Sstevel@tonic-gate #define	_SYS_FPRAS_IMPL_H
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #include <sys/fpras.h>
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #if !defined(_ASM)
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #else
37*7c478bd9Sstevel@tonic-gate #include <sys/intreg.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
39*7c478bd9Sstevel@tonic-gate #endif	/* _ASM */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
42*7c478bd9Sstevel@tonic-gate extern "C" {
43*7c478bd9Sstevel@tonic-gate #endif
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate  * sun4u/cheetah fpRAS implementation.  Arrays etc will be allocated in sun4u
47*7c478bd9Sstevel@tonic-gate  * post_startup() if fpras_implemented is set.  This file may belong at
48*7c478bd9Sstevel@tonic-gate  * the cpu level (eg, cheetahregs.h) but most of it should be common
49*7c478bd9Sstevel@tonic-gate  * when fpRAS support is added for additional cpu types so we introduce
50*7c478bd9Sstevel@tonic-gate  * it at the sun4u level (and set fpras_implemented in cpu_setup).
51*7c478bd9Sstevel@tonic-gate  *
52*7c478bd9Sstevel@tonic-gate  * If fpRAS is implemented on a sun4u/cpu combination that does not use
53*7c478bd9Sstevel@tonic-gate  * an ASR for %stick then the FPRAS_INTERVAL macro will need some
54*7c478bd9Sstevel@tonic-gate  * modification.
55*7c478bd9Sstevel@tonic-gate  */
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /*
58*7c478bd9Sstevel@tonic-gate  * Upper bound for check frequency per cpu and per operation.  For example, if
59*7c478bd9Sstevel@tonic-gate  * this is 100 then for cpuid N performing a bcopy if that cpu has not
60*7c478bd9Sstevel@tonic-gate  * performed a checked bcopy in the the last 1/100th of a second then
61*7c478bd9Sstevel@tonic-gate  * we'll check the current operation.  A value of 0 will check every operation.
62*7c478bd9Sstevel@tonic-gate  * Modifying fpras_frequency from its default is not recommended.
63*7c478bd9Sstevel@tonic-gate  * fpras_interval is computed from fpras_frequency.
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate #if !defined(_ASM)
66*7c478bd9Sstevel@tonic-gate extern int fpras_frequency;
67*7c478bd9Sstevel@tonic-gate extern int64_t fpras_interval;
68*7c478bd9Sstevel@tonic-gate #endif	/* _ASM */
69*7c478bd9Sstevel@tonic-gate #define	FPRAS_DEFAULT_FREQUENCY	100
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate #if !defined(_ASM)
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate /*
74*7c478bd9Sstevel@tonic-gate  * Structure of a check function.  The preamble prepares registers for the
75*7c478bd9Sstevel@tonic-gate  * upcoming calculation that is performed in blk0 and blk1.  One of those
76*7c478bd9Sstevel@tonic-gate  * blocks will be rewritten as part of an FPRAS_REWRITE operation.  Finally
77*7c478bd9Sstevel@tonic-gate  * the result checked in chkresult should be as predetermined, and we should
78*7c478bd9Sstevel@tonic-gate  * return zero on success and nonzero on failure.  If an illegal instruction
79*7c478bd9Sstevel@tonic-gate  * is encountered in the execution of the check function then we trampoline
80*7c478bd9Sstevel@tonic-gate  * to the final three instructions to return a different value.
81*7c478bd9Sstevel@tonic-gate  *
82*7c478bd9Sstevel@tonic-gate  * Note that the size of this structure is a power of 2 as is the
83*7c478bd9Sstevel@tonic-gate  * size of a struct fpras_chkfngrp.  The asm macros below rely on this
84*7c478bd9Sstevel@tonic-gate  * in performing bit shifts instead of mulx.
85*7c478bd9Sstevel@tonic-gate  */
86*7c478bd9Sstevel@tonic-gate struct fpras_chkfn {
87*7c478bd9Sstevel@tonic-gate 	uint32_t	fpras_preamble[16];
88*7c478bd9Sstevel@tonic-gate 	uint32_t	fpras_blk0[16];
89*7c478bd9Sstevel@tonic-gate 	uint32_t	fpras_blk1[16];
90*7c478bd9Sstevel@tonic-gate 	uint32_t	fpras_chkresult[13];
91*7c478bd9Sstevel@tonic-gate 	uint32_t	fpras_trampoline[3];
92*7c478bd9Sstevel@tonic-gate };
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate  * Check function constructed to match a struct fpras_chkfn
96*7c478bd9Sstevel@tonic-gate  */
97*7c478bd9Sstevel@tonic-gate extern int fpras_chkfn_type1(void);
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate /*
100*7c478bd9Sstevel@tonic-gate  * A group of check functions, one for each operation type.  These will
101*7c478bd9Sstevel@tonic-gate  * be the check functions for copy operations on a particular processor.
102*7c478bd9Sstevel@tonic-gate  */
103*7c478bd9Sstevel@tonic-gate struct fpras_chkfngrp {
104*7c478bd9Sstevel@tonic-gate 	struct fpras_chkfn fpras_fn[FPRAS_NCOPYOPS];
105*7c478bd9Sstevel@tonic-gate };
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate /*
108*7c478bd9Sstevel@tonic-gate  * Where we store check functions for execution.  Indexed by cpuid and
109*7c478bd9Sstevel@tonic-gate  * function within that for cacheline friendliness.  Startup code
110*7c478bd9Sstevel@tonic-gate  * copies the check function into this array.  The fpRAS mechanism will
111*7c478bd9Sstevel@tonic-gate  * rewrite one of fpras_blk0 or fpras_blk1 before calling the check function
112*7c478bd9Sstevel@tonic-gate  * for a cpuid & copy function combination.
113*7c478bd9Sstevel@tonic-gate  */
114*7c478bd9Sstevel@tonic-gate extern struct fpras_chkfngrp *fpras_chkfngrps;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate #endif	/* !_ASM */
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate #if defined(_ASM)
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /*
123*7c478bd9Sstevel@tonic-gate  * The INTERVAL macro decides whether we will check this copy operation,
124*7c478bd9Sstevel@tonic-gate  * based on performing no more than 1 check per cpu & operation in a specified
125*7c478bd9Sstevel@tonic-gate  * time interval.  If it decides to abort this check (ie, we have checked
126*7c478bd9Sstevel@tonic-gate  * recently) then it returns doex NULL, otherwise doex is the address of the
127*7c478bd9Sstevel@tonic-gate  * check function to execute later.  Migration must have been prevented before
128*7c478bd9Sstevel@tonic-gate  * calling this macro.  Args:
129*7c478bd9Sstevel@tonic-gate  *
130*7c478bd9Sstevel@tonic-gate  *	operation (immediate): one of FPRAS_BCOPY etc
131*7c478bd9Sstevel@tonic-gate  *	blk (immediate): which block to copy
132*7c478bd9Sstevel@tonic-gate  *	doex (register): register in which to return check function address
133*7c478bd9Sstevel@tonic-gate  *	tmp1 (register): used for scratch, not preserved
134*7c478bd9Sstevel@tonic-gate  *	tmp2 (register): used for scratch, not preserved
135*7c478bd9Sstevel@tonic-gate  *	tmp3 (register): used for scratch, not preserved
136*7c478bd9Sstevel@tonic-gate  *	tmp4 (register): used for scratch, not preserved
137*7c478bd9Sstevel@tonic-gate  *	label: free local numeric label
138*7c478bd9Sstevel@tonic-gate  */
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate #define	FPRAS_INTERVAL(operation, blk, doex, tmp1, tmp2, tmp3, tmp4, label) \
141*7c478bd9Sstevel@tonic-gate 	sethi	%hi(fpras_interval), tmp1				;\
142*7c478bd9Sstevel@tonic-gate 	ldx	[tmp1 + %lo(fpras_interval)], tmp1			;\
143*7c478bd9Sstevel@tonic-gate 	brlz,pn	tmp1, label/**/f	/* not initialized? */		;\
144*7c478bd9Sstevel@tonic-gate 	  clr	doex							;\
145*7c478bd9Sstevel@tonic-gate 	sethi	%hi(fpras_disableids), tmp2				;\
146*7c478bd9Sstevel@tonic-gate 	ld	[tmp2 + %lo(fpras_disableids)], tmp2			;\
147*7c478bd9Sstevel@tonic-gate 	mov	0x1, tmp3						;\
148*7c478bd9Sstevel@tonic-gate 	sll	tmp3, operation, tmp3					;\
149*7c478bd9Sstevel@tonic-gate 	btst	tmp3, tmp2						;\
150*7c478bd9Sstevel@tonic-gate 	bnz,a,pn %icc, label/**/f	/* disabled for this op? */	;\
151*7c478bd9Sstevel@tonic-gate 	  nop								;\
152*7c478bd9Sstevel@tonic-gate 	set	fpras_chkfn_type1, tmp2					;\
153*7c478bd9Sstevel@tonic-gate 	prefetch [tmp2 + (FPRAS_BLK0 + blk * 64)], #one_read		;\
154*7c478bd9Sstevel@tonic-gate 	ldn	[THREAD_REG + T_CPU], tmp2				;\
155*7c478bd9Sstevel@tonic-gate 	ldn	[tmp2 + CPU_PRIVATE], tmp2				;\
156*7c478bd9Sstevel@tonic-gate 	brz,pn	tmp2, label/**/f	/* early in startup? */		;\
157*7c478bd9Sstevel@tonic-gate 	  mov	operation, tmp3						;\
158*7c478bd9Sstevel@tonic-gate 	sll	tmp3, 3, tmp3						;\
159*7c478bd9Sstevel@tonic-gate 	set	CHPR_FPRAS_TIMESTAMP, tmp4				;\
160*7c478bd9Sstevel@tonic-gate 	add	tmp2, tmp4, tmp2					;\
161*7c478bd9Sstevel@tonic-gate 	add	tmp2, tmp3, tmp2	/* keep ptr for update */	;\
162*7c478bd9Sstevel@tonic-gate 	ldx	[tmp2], tmp3		/* last timestamp */		;\
163*7c478bd9Sstevel@tonic-gate 	rd	STICK, doex		/* doex is a scratch here */	;\
164*7c478bd9Sstevel@tonic-gate 	sub	doex, tmp3, tmp4	/* delta since last check */	;\
165*7c478bd9Sstevel@tonic-gate 	cmp	tmp4, tmp1		/* compare delta to interval */	;\
166*7c478bd9Sstevel@tonic-gate 	blu,a,pn %xcc, label/**/f					;\
167*7c478bd9Sstevel@tonic-gate 	  clr	doex							;\
168*7c478bd9Sstevel@tonic-gate 	stx	doex, [tmp2]		/* updated timestamp */		;\
169*7c478bd9Sstevel@tonic-gate 	ldn	[THREAD_REG + T_CPU], tmp1				;\
170*7c478bd9Sstevel@tonic-gate 	ld	[tmp1 + CPU_ID], tmp1					;\
171*7c478bd9Sstevel@tonic-gate 	sethi	%hi(fpras_chkfngrps), doex				;\
172*7c478bd9Sstevel@tonic-gate 	ldn	[doex + %lo(fpras_chkfngrps)], doex			;\
173*7c478bd9Sstevel@tonic-gate 	sll	tmp1, FPRAS_CHKFNGRP_SIZE_SHIFT, tmp1			;\
174*7c478bd9Sstevel@tonic-gate 	add	doex, tmp1, doex					;\
175*7c478bd9Sstevel@tonic-gate 	mov	operation, tmp1						;\
176*7c478bd9Sstevel@tonic-gate 	sll	tmp1, FPRAS_CHKFN_SIZE_SHIFT, tmp1			;\
177*7c478bd9Sstevel@tonic-gate 	add	doex, tmp1, doex	/* address of check function */	;\
178*7c478bd9Sstevel@tonic-gate label:
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate /*
181*7c478bd9Sstevel@tonic-gate  * The REWRITE macro copies an instruction block from fpras_chkfn_type1
182*7c478bd9Sstevel@tonic-gate  * into a per-cpu fpras check function.
183*7c478bd9Sstevel@tonic-gate  * If doex is NULL it must not attempt any copy, and must leave doex NULL.
184*7c478bd9Sstevel@tonic-gate  * CPU migration of this thread must be prevented before we call this macro.
185*7c478bd9Sstevel@tonic-gate  * We must have checked for fp in use (and saved state, including the
186*7c478bd9Sstevel@tonic-gate  * quadrant of registers indicated by the fpq argument and fp enabled before
187*7c478bd9Sstevel@tonic-gate  * using this macro.  Args:
188*7c478bd9Sstevel@tonic-gate  *
189*7c478bd9Sstevel@tonic-gate  *	blk (immediate): as above
190*7c478bd9Sstevel@tonic-gate  *	doex (register): register in which to return check function addr
191*7c478bd9Sstevel@tonic-gate  *	[fpq (fp register): frf quadrant to be used (%f0/%f16/%f32/%f48)]
192*7c478bd9Sstevel@tonic-gate  *		This is used on type 1 rewrite only - on others the
193*7c478bd9Sstevel@tonic-gate  *		quadrant is implicit/hardcoded in the macro name.
194*7c478bd9Sstevel@tonic-gate  *	tmp1 (register): used for scratch, not preserved
195*7c478bd9Sstevel@tonic-gate  *	label1: free local numeric label
196*7c478bd9Sstevel@tonic-gate  *	[label2: free local numeric label]
197*7c478bd9Sstevel@tonic-gate  *		This is used in type 2 only.
198*7c478bd9Sstevel@tonic-gate  *
199*7c478bd9Sstevel@tonic-gate  * Note that the REWRITE macros do not perform a flush instruction -
200*7c478bd9Sstevel@tonic-gate  * flush is not necessary on Cheetah derivative processors in which
201*7c478bd9Sstevel@tonic-gate  * i$ snoops for invalidations.
202*7c478bd9Sstevel@tonic-gate  */
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate  * Rewrite type 1 will work with any instruction pattern - it just block
206*7c478bd9Sstevel@tonic-gate  * loads and block stores the given block.  A membar after block store
207*7c478bd9Sstevel@tonic-gate  * forces the block store to complete before upcoming reuse of the
208*7c478bd9Sstevel@tonic-gate  * fpregs in the block;  the block load is blocking on sun4u/cheetah
209*7c478bd9Sstevel@tonic-gate  * so no need for a membar after it.
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate #define	FPRAS_REWRITE_TYPE1(blk, doex, fpq, tmp1, label)	\
213*7c478bd9Sstevel@tonic-gate 	brz,pn  doex, label/**/f				;\
214*7c478bd9Sstevel@tonic-gate 	  sethi	%hi(fpras_chkfn_type1), tmp1			;\
215*7c478bd9Sstevel@tonic-gate 	add	tmp1, %lo(fpras_chkfn_type1), tmp1		;\
216*7c478bd9Sstevel@tonic-gate 	add	tmp1, FPRAS_BLK0 + blk * 64, tmp1		;\
217*7c478bd9Sstevel@tonic-gate 	ldda	[tmp1]ASI_BLK_P, fpq				;\
218*7c478bd9Sstevel@tonic-gate 	add	doex, FPRAS_BLK0 + blk * 64, tmp1		;\
219*7c478bd9Sstevel@tonic-gate 	stda	fpq, [tmp1]ASI_BLK_P				;\
220*7c478bd9Sstevel@tonic-gate 	membar	#Sync						;\
221*7c478bd9Sstevel@tonic-gate label:
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate /*
224*7c478bd9Sstevel@tonic-gate  * Rewrite type 2 will only work with instruction blocks that satisfy
225*7c478bd9Sstevel@tonic-gate  * this particular repeat pattern.  Note that the frf quadrant to
226*7c478bd9Sstevel@tonic-gate  * use is implicit in the macro name and had better match what the
227*7c478bd9Sstevel@tonic-gate  * copy function is preserving.
228*7c478bd9Sstevel@tonic-gate *
229*7c478bd9Sstevel@tonic-gate  * The odd looking repetition in the initial loop is designed to open
230*7c478bd9Sstevel@tonic-gate  * up boths paths from prefetch cache to the frf - unrolling the loop
231*7c478bd9Sstevel@tonic-gate  * would defeat this.  In addition we perform idempotent faligndata
232*7c478bd9Sstevel@tonic-gate  * manipulations using %tick as a randomly aligned address (this only
233*7c478bd9Sstevel@tonic-gate  * works for address that aren't doubleword aligned).
234*7c478bd9Sstevel@tonic-gate  */
235*7c478bd9Sstevel@tonic-gate #define	FPRAS_REWRITE_TYPE2Q1(blk, doex, tmp1, tmp2, label1, label2)	\
236*7c478bd9Sstevel@tonic-gate 	brz,pn	doex, label1/**/f					;\
237*7c478bd9Sstevel@tonic-gate 	  mov	0x2, tmp1						;\
238*7c478bd9Sstevel@tonic-gate 	set	fpras_chkfn_type1, tmp2					;\
239*7c478bd9Sstevel@tonic-gate label2:									;\
240*7c478bd9Sstevel@tonic-gate 	deccc		tmp1						;\
241*7c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64)], %f4		;\
242*7c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64) + 8], %f2	;\
243*7c478bd9Sstevel@tonic-gate 	bnz,a,pt	%icc, label2/**/b				;\
244*7c478bd9Sstevel@tonic-gate 	  fsrc1		%f4, %f0					;\
245*7c478bd9Sstevel@tonic-gate 	rdpr		%tick, tmp1					;\
246*7c478bd9Sstevel@tonic-gate 	fsrc1		%f4, %f8					;\
247*7c478bd9Sstevel@tonic-gate 	fsrc1		%f2, %f10					;\
248*7c478bd9Sstevel@tonic-gate 	btst		0x7, tmp1					;\
249*7c478bd9Sstevel@tonic-gate 	alignaddr	tmp1, %g0, %g0	/* changes %gsr */		;\
250*7c478bd9Sstevel@tonic-gate 	bz,pn		%icc, label2/**/f				;\
251*7c478bd9Sstevel@tonic-gate 	  faligndata	%f2, %f4, %f6					;\
252*7c478bd9Sstevel@tonic-gate 	faligndata	%f0, %f2, %f12					;\
253*7c478bd9Sstevel@tonic-gate 	alignaddrl	tmp1, %g0, %g0					;\
254*7c478bd9Sstevel@tonic-gate 	faligndata	%f12, %f6, %f6					;\
255*7c478bd9Sstevel@tonic-gate label2:									;\
256*7c478bd9Sstevel@tonic-gate 	add		doex, FPRAS_BLK0 + blk * 64, tmp1		;\
257*7c478bd9Sstevel@tonic-gate 	fsrc2		%f8, %f12					;\
258*7c478bd9Sstevel@tonic-gate 	fsrc1		%f6, %f14					;\
259*7c478bd9Sstevel@tonic-gate 	stda		%f0, [tmp1]ASI_BLK_P				;\
260*7c478bd9Sstevel@tonic-gate 	membar		#Sync						;\
261*7c478bd9Sstevel@tonic-gate label1:
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate #define	FPRAS_REWRITE_TYPE2Q2(blk, doex, tmp1, tmp2, label1, label2)	\
264*7c478bd9Sstevel@tonic-gate 	brz,pn	doex, label1/**/f					;\
265*7c478bd9Sstevel@tonic-gate 	  mov	0x2, tmp1						;\
266*7c478bd9Sstevel@tonic-gate 	set	fpras_chkfn_type1, tmp2					;\
267*7c478bd9Sstevel@tonic-gate label2:									;\
268*7c478bd9Sstevel@tonic-gate 	deccc		tmp1						;\
269*7c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64)], %f20	;\
270*7c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64) + 8], %f18	;\
271*7c478bd9Sstevel@tonic-gate 	bnz,a,pt	%icc, label2/**/b				;\
272*7c478bd9Sstevel@tonic-gate 	  fsrc1		%f20, %f16					;\
273*7c478bd9Sstevel@tonic-gate 	rdpr		%tick, tmp1					;\
274*7c478bd9Sstevel@tonic-gate 	fsrc1		%f20, %f24					;\
275*7c478bd9Sstevel@tonic-gate 	fsrc1		%f18, %f26					;\
276*7c478bd9Sstevel@tonic-gate 	btst		0x7, tmp1					;\
277*7c478bd9Sstevel@tonic-gate 	alignaddr	tmp1, %g0, %g0	/* changes %gsr */		;\
278*7c478bd9Sstevel@tonic-gate 	bz,pn		%icc, label2/**/f				;\
279*7c478bd9Sstevel@tonic-gate 	  faligndata	%f18, %f20, %f22				;\
280*7c478bd9Sstevel@tonic-gate 	faligndata	%f16, %f18, %f28				;\
281*7c478bd9Sstevel@tonic-gate 	alignaddrl	tmp1, %g0, %g0					;\
282*7c478bd9Sstevel@tonic-gate 	faligndata	%f28, %f22, %f22				;\
283*7c478bd9Sstevel@tonic-gate label2:									;\
284*7c478bd9Sstevel@tonic-gate 	add		doex, FPRAS_BLK0 + blk * 64, tmp1		;\
285*7c478bd9Sstevel@tonic-gate 	fsrc2		%f24, %f28					;\
286*7c478bd9Sstevel@tonic-gate 	fsrc1		%f22, %f30					;\
287*7c478bd9Sstevel@tonic-gate 	stda		%f16, [tmp1]ASI_BLK_P				;\
288*7c478bd9Sstevel@tonic-gate 	membar		#Sync						;\
289*7c478bd9Sstevel@tonic-gate label1:
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate /*
292*7c478bd9Sstevel@tonic-gate  * The CHECK macro takes the 'doex' address of the check function to
293*7c478bd9Sstevel@tonic-gate  * execute and jumps to it (if not NULL). If the check function returns
294*7c478bd9Sstevel@tonic-gate  * nonzero then the check has failed and the CHECK macro must initiate
295*7c478bd9Sstevel@tonic-gate  * an appropriate failure action.  Illegal instruction trap handlers
296*7c478bd9Sstevel@tonic-gate  * will also recognise traps in this PC range as fp failures.  Thread
297*7c478bd9Sstevel@tonic-gate  * migration must only be reallowed after completion of this check.  The
298*7c478bd9Sstevel@tonic-gate  * CHECK macro should be treated as a CALL/JMPL - output registers are
299*7c478bd9Sstevel@tonic-gate  * forfeit after using it.  If the call to fpras_failure returns
300*7c478bd9Sstevel@tonic-gate  * (it may decide to panic) then invoke lofault handler (which must exist)
301*7c478bd9Sstevel@tonic-gate  * to return an error (be sure to use this macro before restoring original
302*7c478bd9Sstevel@tonic-gate  * lofault setup in copy functions).  Note that the lofault handler is the
303*7c478bd9Sstevel@tonic-gate  * copyops aware proxy handler which will perform other tidy up operations
304*7c478bd9Sstevel@tonic-gate  * (unbind, fp state restore) that would normally have been done in the tail
305*7c478bd9Sstevel@tonic-gate  * of the copy function.
306*7c478bd9Sstevel@tonic-gate  *
307*7c478bd9Sstevel@tonic-gate  *	operation (immedidate): as above
308*7c478bd9Sstevel@tonic-gate  *	doex (register): doex value returned from the REWRITE
309*7c478bd9Sstevel@tonic-gate  *	label: free local numeric label
310*7c478bd9Sstevel@tonic-gate  */
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate #define	FPRAS_CHECK(operation, doex, label)				\
313*7c478bd9Sstevel@tonic-gate 	brz,pn	doex, label/**/f					;\
314*7c478bd9Sstevel@tonic-gate 	  nop								;\
315*7c478bd9Sstevel@tonic-gate 	jmpl	doex, %o7						;\
316*7c478bd9Sstevel@tonic-gate 	  nop								;\
317*7c478bd9Sstevel@tonic-gate 	cmp	%o0, FPRAS_OK						;\
318*7c478bd9Sstevel@tonic-gate 	be	%icc, label/**/f					;\
319*7c478bd9Sstevel@tonic-gate 	  nop								;\
320*7c478bd9Sstevel@tonic-gate 	mov	%o0, %o1	/* how detected */			;\
321*7c478bd9Sstevel@tonic-gate 	call	fpras_failure	/* take failure action */		;\
322*7c478bd9Sstevel@tonic-gate 	  mov	operation, %o0						;\
323*7c478bd9Sstevel@tonic-gate 	ldn	[THREAD_REG + T_LOFAULT], doex				;\
324*7c478bd9Sstevel@tonic-gate 	jmp	doex							;\
325*7c478bd9Sstevel@tonic-gate 	  mov	EFAULT, %g1						;\
326*7c478bd9Sstevel@tonic-gate label:
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate /* END CSTYLED */
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate #endif	/* _ASM */
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
333*7c478bd9Sstevel@tonic-gate }
334*7c478bd9Sstevel@tonic-gate #endif
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate #endif	/* _SYS_FPRAS_IMPL_H */
337