xref: /illumos-gate/usr/src/uts/sun4u/sys/fpras_impl.h (revision 5d9d9091)
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 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #ifndef	_SYS_FPRAS_IMPL_H
287c478bd9Sstevel@tonic-gate #define	_SYS_FPRAS_IMPL_H
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/fpras.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #if !defined(_ASM)
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #else
357c478bd9Sstevel@tonic-gate #include <sys/intreg.h>
367c478bd9Sstevel@tonic-gate #include <sys/errno.h>
377c478bd9Sstevel@tonic-gate #endif	/* _ASM */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
407c478bd9Sstevel@tonic-gate extern "C" {
417c478bd9Sstevel@tonic-gate #endif
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate  * sun4u/cheetah fpRAS implementation.  Arrays etc will be allocated in sun4u
457c478bd9Sstevel@tonic-gate  * post_startup() if fpras_implemented is set.  This file may belong at
467c478bd9Sstevel@tonic-gate  * the cpu level (eg, cheetahregs.h) but most of it should be common
477c478bd9Sstevel@tonic-gate  * when fpRAS support is added for additional cpu types so we introduce
487c478bd9Sstevel@tonic-gate  * it at the sun4u level (and set fpras_implemented in cpu_setup).
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * If fpRAS is implemented on a sun4u/cpu combination that does not use
517c478bd9Sstevel@tonic-gate  * an ASR for %stick then the FPRAS_INTERVAL macro will need some
527c478bd9Sstevel@tonic-gate  * modification.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * Upper bound for check frequency per cpu and per operation.  For example, if
577c478bd9Sstevel@tonic-gate  * this is 100 then for cpuid N performing a bcopy if that cpu has not
587c478bd9Sstevel@tonic-gate  * performed a checked bcopy in the the last 1/100th of a second then
597c478bd9Sstevel@tonic-gate  * we'll check the current operation.  A value of 0 will check every operation.
607c478bd9Sstevel@tonic-gate  * Modifying fpras_frequency from its default is not recommended.
617c478bd9Sstevel@tonic-gate  * fpras_interval is computed from fpras_frequency.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate #if !defined(_ASM)
647c478bd9Sstevel@tonic-gate extern int fpras_frequency;
657c478bd9Sstevel@tonic-gate extern int64_t fpras_interval;
667c478bd9Sstevel@tonic-gate #endif	/* _ASM */
677c478bd9Sstevel@tonic-gate #define	FPRAS_DEFAULT_FREQUENCY	100
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #if !defined(_ASM)
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * Structure of a check function.  The preamble prepares registers for the
737c478bd9Sstevel@tonic-gate  * upcoming calculation that is performed in blk0 and blk1.  One of those
747c478bd9Sstevel@tonic-gate  * blocks will be rewritten as part of an FPRAS_REWRITE operation.  Finally
757c478bd9Sstevel@tonic-gate  * the result checked in chkresult should be as predetermined, and we should
767c478bd9Sstevel@tonic-gate  * return zero on success and nonzero on failure.  If an illegal instruction
777c478bd9Sstevel@tonic-gate  * is encountered in the execution of the check function then we trampoline
787c478bd9Sstevel@tonic-gate  * to the final three instructions to return a different value.
797c478bd9Sstevel@tonic-gate  *
807c478bd9Sstevel@tonic-gate  * Note that the size of this structure is a power of 2 as is the
817c478bd9Sstevel@tonic-gate  * size of a struct fpras_chkfngrp.  The asm macros below rely on this
827c478bd9Sstevel@tonic-gate  * in performing bit shifts instead of mulx.
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate struct fpras_chkfn {
857c478bd9Sstevel@tonic-gate 	uint32_t	fpras_preamble[16];
867c478bd9Sstevel@tonic-gate 	uint32_t	fpras_blk0[16];
877c478bd9Sstevel@tonic-gate 	uint32_t	fpras_blk1[16];
887c478bd9Sstevel@tonic-gate 	uint32_t	fpras_chkresult[13];
897c478bd9Sstevel@tonic-gate 	uint32_t	fpras_trampoline[3];
907c478bd9Sstevel@tonic-gate };
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * Check function constructed to match a struct fpras_chkfn
947c478bd9Sstevel@tonic-gate  */
957c478bd9Sstevel@tonic-gate extern int fpras_chkfn_type1(void);
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * A group of check functions, one for each operation type.  These will
997c478bd9Sstevel@tonic-gate  * be the check functions for copy operations on a particular processor.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate struct fpras_chkfngrp {
1027c478bd9Sstevel@tonic-gate 	struct fpras_chkfn fpras_fn[FPRAS_NCOPYOPS];
1037c478bd9Sstevel@tonic-gate };
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * Where we store check functions for execution.  Indexed by cpuid and
1077c478bd9Sstevel@tonic-gate  * function within that for cacheline friendliness.  Startup code
1087c478bd9Sstevel@tonic-gate  * copies the check function into this array.  The fpRAS mechanism will
1097c478bd9Sstevel@tonic-gate  * rewrite one of fpras_blk0 or fpras_blk1 before calling the check function
1107c478bd9Sstevel@tonic-gate  * for a cpuid & copy function combination.
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate extern struct fpras_chkfngrp *fpras_chkfngrps;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate #endif	/* !_ASM */
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate #if defined(_ASM)
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate  * The INTERVAL macro decides whether we will check this copy operation,
1227c478bd9Sstevel@tonic-gate  * based on performing no more than 1 check per cpu & operation in a specified
1237c478bd9Sstevel@tonic-gate  * time interval.  If it decides to abort this check (ie, we have checked
1247c478bd9Sstevel@tonic-gate  * recently) then it returns doex NULL, otherwise doex is the address of the
1257c478bd9Sstevel@tonic-gate  * check function to execute later.  Migration must have been prevented before
1267c478bd9Sstevel@tonic-gate  * calling this macro.  Args:
1277c478bd9Sstevel@tonic-gate  *
1287c478bd9Sstevel@tonic-gate  *	operation (immediate): one of FPRAS_BCOPY etc
1297c478bd9Sstevel@tonic-gate  *	blk (immediate): which block to copy
1307c478bd9Sstevel@tonic-gate  *	doex (register): register in which to return check function address
1317c478bd9Sstevel@tonic-gate  *	tmp1 (register): used for scratch, not preserved
1327c478bd9Sstevel@tonic-gate  *	tmp2 (register): used for scratch, not preserved
1337c478bd9Sstevel@tonic-gate  *	tmp3 (register): used for scratch, not preserved
1347c478bd9Sstevel@tonic-gate  *	tmp4 (register): used for scratch, not preserved
1357c478bd9Sstevel@tonic-gate  *	label: free local numeric label
1367c478bd9Sstevel@tonic-gate  */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate #define	FPRAS_INTERVAL(operation, blk, doex, tmp1, tmp2, tmp3, tmp4, label) \
1397c478bd9Sstevel@tonic-gate 	sethi	%hi(fpras_interval), tmp1				;\
1407c478bd9Sstevel@tonic-gate 	ldx	[tmp1 + %lo(fpras_interval)], tmp1			;\
141*5d9d9091SRichard Lowe 	brlz,pn	tmp1, label##f	/* not initialized? */		;\
1427c478bd9Sstevel@tonic-gate 	  clr	doex							;\
1437c478bd9Sstevel@tonic-gate 	sethi	%hi(fpras_disableids), tmp2				;\
1447c478bd9Sstevel@tonic-gate 	ld	[tmp2 + %lo(fpras_disableids)], tmp2			;\
1457c478bd9Sstevel@tonic-gate 	mov	0x1, tmp3						;\
1467c478bd9Sstevel@tonic-gate 	sll	tmp3, operation, tmp3					;\
1477c478bd9Sstevel@tonic-gate 	btst	tmp3, tmp2						;\
148*5d9d9091SRichard Lowe 	bnz,a,pn %icc, label##f	/* disabled for this op? */	;\
1497c478bd9Sstevel@tonic-gate 	  nop								;\
1507c478bd9Sstevel@tonic-gate 	set	fpras_chkfn_type1, tmp2					;\
1517c478bd9Sstevel@tonic-gate 	prefetch [tmp2 + (FPRAS_BLK0 + blk * 64)], #one_read		;\
1527c478bd9Sstevel@tonic-gate 	ldn	[THREAD_REG + T_CPU], tmp2				;\
1537c478bd9Sstevel@tonic-gate 	ldn	[tmp2 + CPU_PRIVATE], tmp2				;\
154*5d9d9091SRichard Lowe 	brz,pn	tmp2, label##f	/* early in startup? */		;\
1557c478bd9Sstevel@tonic-gate 	  mov	operation, tmp3						;\
1567c478bd9Sstevel@tonic-gate 	sll	tmp3, 3, tmp3						;\
1577c478bd9Sstevel@tonic-gate 	set	CHPR_FPRAS_TIMESTAMP, tmp4				;\
1587c478bd9Sstevel@tonic-gate 	add	tmp2, tmp4, tmp2					;\
1597c478bd9Sstevel@tonic-gate 	add	tmp2, tmp3, tmp2	/* keep ptr for update */	;\
1607c478bd9Sstevel@tonic-gate 	ldx	[tmp2], tmp3		/* last timestamp */		;\
1617c478bd9Sstevel@tonic-gate 	rd	STICK, doex		/* doex is a scratch here */	;\
1627c478bd9Sstevel@tonic-gate 	sub	doex, tmp3, tmp4	/* delta since last check */	;\
1637c478bd9Sstevel@tonic-gate 	cmp	tmp4, tmp1		/* compare delta to interval */	;\
164*5d9d9091SRichard Lowe 	blu,a,pn %xcc, label##f					;\
1657c478bd9Sstevel@tonic-gate 	  clr	doex							;\
1667c478bd9Sstevel@tonic-gate 	stx	doex, [tmp2]		/* updated timestamp */		;\
1677c478bd9Sstevel@tonic-gate 	ldn	[THREAD_REG + T_CPU], tmp1				;\
1687c478bd9Sstevel@tonic-gate 	ld	[tmp1 + CPU_ID], tmp1					;\
1697c478bd9Sstevel@tonic-gate 	sethi	%hi(fpras_chkfngrps), doex				;\
1707c478bd9Sstevel@tonic-gate 	ldn	[doex + %lo(fpras_chkfngrps)], doex			;\
1717c478bd9Sstevel@tonic-gate 	sll	tmp1, FPRAS_CHKFNGRP_SIZE_SHIFT, tmp1			;\
1727c478bd9Sstevel@tonic-gate 	add	doex, tmp1, doex					;\
1737c478bd9Sstevel@tonic-gate 	mov	operation, tmp1						;\
1747c478bd9Sstevel@tonic-gate 	sll	tmp1, FPRAS_CHKFN_SIZE_SHIFT, tmp1			;\
1757c478bd9Sstevel@tonic-gate 	add	doex, tmp1, doex	/* address of check function */	;\
1767c478bd9Sstevel@tonic-gate label:
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate /*
1797c478bd9Sstevel@tonic-gate  * The REWRITE macro copies an instruction block from fpras_chkfn_type1
1807c478bd9Sstevel@tonic-gate  * into a per-cpu fpras check function.
1817c478bd9Sstevel@tonic-gate  * If doex is NULL it must not attempt any copy, and must leave doex NULL.
1827c478bd9Sstevel@tonic-gate  * CPU migration of this thread must be prevented before we call this macro.
1837c478bd9Sstevel@tonic-gate  * We must have checked for fp in use (and saved state, including the
1847c478bd9Sstevel@tonic-gate  * quadrant of registers indicated by the fpq argument and fp enabled before
1857c478bd9Sstevel@tonic-gate  * using this macro.  Args:
1867c478bd9Sstevel@tonic-gate  *
1877c478bd9Sstevel@tonic-gate  *	blk (immediate): as above
1887c478bd9Sstevel@tonic-gate  *	doex (register): register in which to return check function addr
1897c478bd9Sstevel@tonic-gate  *	[fpq (fp register): frf quadrant to be used (%f0/%f16/%f32/%f48)]
1907c478bd9Sstevel@tonic-gate  *		This is used on type 1 rewrite only - on others the
1917c478bd9Sstevel@tonic-gate  *		quadrant is implicit/hardcoded in the macro name.
1927c478bd9Sstevel@tonic-gate  *	tmp1 (register): used for scratch, not preserved
1937c478bd9Sstevel@tonic-gate  *	label1: free local numeric label
1947c478bd9Sstevel@tonic-gate  *	[label2: free local numeric label]
1957c478bd9Sstevel@tonic-gate  *		This is used in type 2 only.
1967c478bd9Sstevel@tonic-gate  *
1977c478bd9Sstevel@tonic-gate  * Note that the REWRITE macros do not perform a flush instruction -
1987c478bd9Sstevel@tonic-gate  * flush is not necessary on Cheetah derivative processors in which
1997c478bd9Sstevel@tonic-gate  * i$ snoops for invalidations.
2007c478bd9Sstevel@tonic-gate  */
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate  * Rewrite type 1 will work with any instruction pattern - it just block
2047c478bd9Sstevel@tonic-gate  * loads and block stores the given block.  A membar after block store
2057c478bd9Sstevel@tonic-gate  * forces the block store to complete before upcoming reuse of the
2067c478bd9Sstevel@tonic-gate  * fpregs in the block;  the block load is blocking on sun4u/cheetah
2077c478bd9Sstevel@tonic-gate  * so no need for a membar after it.
2087c478bd9Sstevel@tonic-gate  */
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate #define	FPRAS_REWRITE_TYPE1(blk, doex, fpq, tmp1, label)	\
211*5d9d9091SRichard Lowe 	brz,pn  doex, label##f				;\
2127c478bd9Sstevel@tonic-gate 	  sethi	%hi(fpras_chkfn_type1), tmp1			;\
2137c478bd9Sstevel@tonic-gate 	add	tmp1, %lo(fpras_chkfn_type1), tmp1		;\
2147c478bd9Sstevel@tonic-gate 	add	tmp1, FPRAS_BLK0 + blk * 64, tmp1		;\
2157c478bd9Sstevel@tonic-gate 	ldda	[tmp1]ASI_BLK_P, fpq				;\
2167c478bd9Sstevel@tonic-gate 	add	doex, FPRAS_BLK0 + blk * 64, tmp1		;\
2177c478bd9Sstevel@tonic-gate 	stda	fpq, [tmp1]ASI_BLK_P				;\
2187c478bd9Sstevel@tonic-gate 	membar	#Sync						;\
2197c478bd9Sstevel@tonic-gate label:
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate /*
2227c478bd9Sstevel@tonic-gate  * Rewrite type 2 will only work with instruction blocks that satisfy
2237c478bd9Sstevel@tonic-gate  * this particular repeat pattern.  Note that the frf quadrant to
2247c478bd9Sstevel@tonic-gate  * use is implicit in the macro name and had better match what the
2257c478bd9Sstevel@tonic-gate  * copy function is preserving.
2267c478bd9Sstevel@tonic-gate *
2277c478bd9Sstevel@tonic-gate  * The odd looking repetition in the initial loop is designed to open
2287c478bd9Sstevel@tonic-gate  * up boths paths from prefetch cache to the frf - unrolling the loop
2297c478bd9Sstevel@tonic-gate  * would defeat this.  In addition we perform idempotent faligndata
2307c478bd9Sstevel@tonic-gate  * manipulations using %tick as a randomly aligned address (this only
2317c478bd9Sstevel@tonic-gate  * works for address that aren't doubleword aligned).
2327c478bd9Sstevel@tonic-gate  */
2337c478bd9Sstevel@tonic-gate #define	FPRAS_REWRITE_TYPE2Q1(blk, doex, tmp1, tmp2, label1, label2)	\
234*5d9d9091SRichard Lowe 	brz,pn	doex, label1##f					;\
2357c478bd9Sstevel@tonic-gate 	  mov	0x2, tmp1						;\
2367c478bd9Sstevel@tonic-gate 	set	fpras_chkfn_type1, tmp2					;\
2377c478bd9Sstevel@tonic-gate label2:									;\
2387c478bd9Sstevel@tonic-gate 	deccc		tmp1						;\
2397c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64)], %f4		;\
2407c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64) + 8], %f2	;\
241*5d9d9091SRichard Lowe 	bnz,a,pt	%icc, label2##b				;\
2427c478bd9Sstevel@tonic-gate 	  fsrc1		%f4, %f0					;\
2437c478bd9Sstevel@tonic-gate 	rdpr		%tick, tmp1					;\
2447c478bd9Sstevel@tonic-gate 	fsrc1		%f4, %f8					;\
2457c478bd9Sstevel@tonic-gate 	fsrc1		%f2, %f10					;\
2467c478bd9Sstevel@tonic-gate 	btst		0x7, tmp1					;\
2477c478bd9Sstevel@tonic-gate 	alignaddr	tmp1, %g0, %g0	/* changes %gsr */		;\
248*5d9d9091SRichard Lowe 	bz,pn		%icc, label2##f				;\
2497c478bd9Sstevel@tonic-gate 	  faligndata	%f2, %f4, %f6					;\
2507c478bd9Sstevel@tonic-gate 	faligndata	%f0, %f2, %f12					;\
2517c478bd9Sstevel@tonic-gate 	alignaddrl	tmp1, %g0, %g0					;\
2527c478bd9Sstevel@tonic-gate 	faligndata	%f12, %f6, %f6					;\
2537c478bd9Sstevel@tonic-gate label2:									;\
2547c478bd9Sstevel@tonic-gate 	add		doex, FPRAS_BLK0 + blk * 64, tmp1		;\
2557c478bd9Sstevel@tonic-gate 	fsrc2		%f8, %f12					;\
2567c478bd9Sstevel@tonic-gate 	fsrc1		%f6, %f14					;\
2577c478bd9Sstevel@tonic-gate 	stda		%f0, [tmp1]ASI_BLK_P				;\
2587c478bd9Sstevel@tonic-gate 	membar		#Sync						;\
2597c478bd9Sstevel@tonic-gate label1:
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate #define	FPRAS_REWRITE_TYPE2Q2(blk, doex, tmp1, tmp2, label1, label2)	\
262*5d9d9091SRichard Lowe 	brz,pn	doex, label1##f					;\
2637c478bd9Sstevel@tonic-gate 	  mov	0x2, tmp1						;\
2647c478bd9Sstevel@tonic-gate 	set	fpras_chkfn_type1, tmp2					;\
2657c478bd9Sstevel@tonic-gate label2:									;\
2667c478bd9Sstevel@tonic-gate 	deccc		tmp1						;\
2677c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64)], %f20	;\
2687c478bd9Sstevel@tonic-gate 	ldd		[tmp2 + (FPRAS_BLK0 + blk * 64) + 8], %f18	;\
269*5d9d9091SRichard Lowe 	bnz,a,pt	%icc, label2##b				;\
2707c478bd9Sstevel@tonic-gate 	  fsrc1		%f20, %f16					;\
2717c478bd9Sstevel@tonic-gate 	rdpr		%tick, tmp1					;\
2727c478bd9Sstevel@tonic-gate 	fsrc1		%f20, %f24					;\
2737c478bd9Sstevel@tonic-gate 	fsrc1		%f18, %f26					;\
2747c478bd9Sstevel@tonic-gate 	btst		0x7, tmp1					;\
2757c478bd9Sstevel@tonic-gate 	alignaddr	tmp1, %g0, %g0	/* changes %gsr */		;\
276*5d9d9091SRichard Lowe 	bz,pn		%icc, label2##f				;\
2777c478bd9Sstevel@tonic-gate 	  faligndata	%f18, %f20, %f22				;\
2787c478bd9Sstevel@tonic-gate 	faligndata	%f16, %f18, %f28				;\
2797c478bd9Sstevel@tonic-gate 	alignaddrl	tmp1, %g0, %g0					;\
2807c478bd9Sstevel@tonic-gate 	faligndata	%f28, %f22, %f22				;\
2817c478bd9Sstevel@tonic-gate label2:									;\
2827c478bd9Sstevel@tonic-gate 	add		doex, FPRAS_BLK0 + blk * 64, tmp1		;\
2837c478bd9Sstevel@tonic-gate 	fsrc2		%f24, %f28					;\
2847c478bd9Sstevel@tonic-gate 	fsrc1		%f22, %f30					;\
2857c478bd9Sstevel@tonic-gate 	stda		%f16, [tmp1]ASI_BLK_P				;\
2867c478bd9Sstevel@tonic-gate 	membar		#Sync						;\
2877c478bd9Sstevel@tonic-gate label1:
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate /*
2907c478bd9Sstevel@tonic-gate  * The CHECK macro takes the 'doex' address of the check function to
2917c478bd9Sstevel@tonic-gate  * execute and jumps to it (if not NULL). If the check function returns
2927c478bd9Sstevel@tonic-gate  * nonzero then the check has failed and the CHECK macro must initiate
2937c478bd9Sstevel@tonic-gate  * an appropriate failure action.  Illegal instruction trap handlers
2947c478bd9Sstevel@tonic-gate  * will also recognise traps in this PC range as fp failures.  Thread
2957c478bd9Sstevel@tonic-gate  * migration must only be reallowed after completion of this check.  The
2967c478bd9Sstevel@tonic-gate  * CHECK macro should be treated as a CALL/JMPL - output registers are
2977c478bd9Sstevel@tonic-gate  * forfeit after using it.  If the call to fpras_failure returns
2987c478bd9Sstevel@tonic-gate  * (it may decide to panic) then invoke lofault handler (which must exist)
2997c478bd9Sstevel@tonic-gate  * to return an error (be sure to use this macro before restoring original
3007c478bd9Sstevel@tonic-gate  * lofault setup in copy functions).  Note that the lofault handler is the
3017c478bd9Sstevel@tonic-gate  * copyops aware proxy handler which will perform other tidy up operations
3027c478bd9Sstevel@tonic-gate  * (unbind, fp state restore) that would normally have been done in the tail
3037c478bd9Sstevel@tonic-gate  * of the copy function.
3047c478bd9Sstevel@tonic-gate  *
3057c478bd9Sstevel@tonic-gate  *	operation (immedidate): as above
3067c478bd9Sstevel@tonic-gate  *	doex (register): doex value returned from the REWRITE
3077c478bd9Sstevel@tonic-gate  *	label: free local numeric label
3087c478bd9Sstevel@tonic-gate  */
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate #define	FPRAS_CHECK(operation, doex, label)				\
311*5d9d9091SRichard Lowe 	brz,pn	doex, label##f					;\
3127c478bd9Sstevel@tonic-gate 	  nop								;\
3137c478bd9Sstevel@tonic-gate 	jmpl	doex, %o7						;\
3147c478bd9Sstevel@tonic-gate 	  nop								;\
3157c478bd9Sstevel@tonic-gate 	cmp	%o0, FPRAS_OK						;\
316*5d9d9091SRichard Lowe 	be	%icc, label##f					;\
3177c478bd9Sstevel@tonic-gate 	  nop								;\
3187c478bd9Sstevel@tonic-gate 	mov	%o0, %o1	/* how detected */			;\
3197c478bd9Sstevel@tonic-gate 	call	fpras_failure	/* take failure action */		;\
3207c478bd9Sstevel@tonic-gate 	  mov	operation, %o0						;\
3217c478bd9Sstevel@tonic-gate 	ldn	[THREAD_REG + T_LOFAULT], doex				;\
3227c478bd9Sstevel@tonic-gate 	jmp	doex							;\
3237c478bd9Sstevel@tonic-gate 	  mov	EFAULT, %g1						;\
3247c478bd9Sstevel@tonic-gate label:
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate /* END CSTYLED */
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate #endif	/* _ASM */
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate #endif
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate #endif	/* _SYS_FPRAS_IMPL_H */
335