xref: /titanic_52/usr/src/uts/sparc/v9/ml/float.s (revision 7bafd14382b5b097b3e3940091dfccb91247dfd5)
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
5*7bafd143Sjb145095 * Common Development and Distribution License (the "License").
6*7bafd143Sjb145095 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*7bafd143Sjb145095 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate#ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
297c478bd9Sstevel@tonic-gate#include <sys/trap.h>
307c478bd9Sstevel@tonic-gate#include <sys/machpcb.h>
31*7bafd143Sjb145095#include <sys/machtrap.h>
32*7bafd143Sjb145095#include <sys/machsig.h>
33*7bafd143Sjb145095#include <sys/machthread.h>
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate#if !defined(lint) && !defined(__lint)
367c478bd9Sstevel@tonic-gate#include "assym.h"
377c478bd9Sstevel@tonic-gate#endif	/* lint */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate/*
407c478bd9Sstevel@tonic-gate * Floating point trap handling.
417c478bd9Sstevel@tonic-gate *
427c478bd9Sstevel@tonic-gate *	The FPU is always in a V9 current configuration.
437c478bd9Sstevel@tonic-gate *
447c478bd9Sstevel@tonic-gate *	When a user process is first started via exec,
457c478bd9Sstevel@tonic-gate *	floating point operations will be disabled by default.
467c478bd9Sstevel@tonic-gate *	Upon execution of the first floating point instruction,
477c478bd9Sstevel@tonic-gate *	a fp_disabled trap will be generated; then a word in
487c478bd9Sstevel@tonic-gate *	the uarea is written signifying use of the floating point
497c478bd9Sstevel@tonic-gate *	registers so that subsequent context switches will save
507c478bd9Sstevel@tonic-gate *	and restore the floating point them. The trapped instruction
517c478bd9Sstevel@tonic-gate *	will be restarted and processing will continue as normal.
527c478bd9Sstevel@tonic-gate *
537c478bd9Sstevel@tonic-gate *	When a operation occurs that the hardware cannot properly
547c478bd9Sstevel@tonic-gate *	handle, an unfinshed fp_op exception will be generated.
557c478bd9Sstevel@tonic-gate *	Software routines in the kernel will be	executed to
567c478bd9Sstevel@tonic-gate *	simulate proper handling of such conditions.
577c478bd9Sstevel@tonic-gate *
587c478bd9Sstevel@tonic-gate *	Exception handling will emulate all instructions
597c478bd9Sstevel@tonic-gate *	in the floating point address queue. Note that there
607c478bd9Sstevel@tonic-gate *	is no %fq in sun4u, because it has precise FP traps.
617c478bd9Sstevel@tonic-gate *
627c478bd9Sstevel@tonic-gate *	Floating point queues are now machine dependent, and std %fq
637c478bd9Sstevel@tonic-gate *	is an illegal V9 instruction. The fp_exception code has been
647c478bd9Sstevel@tonic-gate *	moved to sun4u/ml/machfloat.s.
657c478bd9Sstevel@tonic-gate *
667c478bd9Sstevel@tonic-gate *	NOTE: This code DOES NOT SUPPORT KERNEL (DEVICE DRIVER)
677c478bd9Sstevel@tonic-gate *		USE OF THE FPU
687c478bd9Sstevel@tonic-gate *
697c478bd9Sstevel@tonic-gate *	Instructions for running without the hardware fpu:
707c478bd9Sstevel@tonic-gate *	1. Setting fpu_exists to 0 now only works on a DEBUG kernel.
717c478bd9Sstevel@tonic-gate *	2. adb -w unix and set fpu_exists, use_hw_bcopy, use_hw_copyio, and
727c478bd9Sstevel@tonic-gate *		use_hw_bzero to 0 and rename libc_psr.so.1 in
737c478bd9Sstevel@tonic-gate *		/usr/platform/sun4u/lib so that it will not get used by
747c478bd9Sstevel@tonic-gate *		the libc bcopy routines. Then reboot the system and you
757c478bd9Sstevel@tonic-gate *		should see the bootup message "FPU not in use".
767c478bd9Sstevel@tonic-gate *	3. To run kaos, you must comment out the code which sets the
777c478bd9Sstevel@tonic-gate *		version number of the fsr to 7, in fldst: stfsr/stxfsr
787c478bd9Sstevel@tonic-gate *		(unless you are running against a comparison system that
797c478bd9Sstevel@tonic-gate *		has the same fsr version number).
807c478bd9Sstevel@tonic-gate *	4. The stqf{a}/ldqf{a} instructions cause kaos errors, for reasons
817c478bd9Sstevel@tonic-gate *		that appear to be a kaos bug, so don't use them!
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate#ifdef FP_DISABLED
877c478bd9Sstevel@tonic-gateint fpu_exists = 0;
887c478bd9Sstevel@tonic-gate#else
897c478bd9Sstevel@tonic-gateint fpu_exists = 1;
907c478bd9Sstevel@tonic-gate#endif
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate#else	/* lint */
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate	.section ".data"
957c478bd9Sstevel@tonic-gate	.align	8
967c478bd9Sstevel@tonic-gatefsrholder:
977c478bd9Sstevel@tonic-gate	.word	0			! dummy place to write fsr
987c478bd9Sstevel@tonic-gate	.word	0
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate	DGDEF(fpu_exists)		! always exists for V9
1017c478bd9Sstevel@tonic-gate#ifdef FP_DISABLED
1027c478bd9Sstevel@tonic-gate	.word	0
1037c478bd9Sstevel@tonic-gate#else
1047c478bd9Sstevel@tonic-gate	.word	1			! sundiag (gack) uses this variable
1057c478bd9Sstevel@tonic-gate#endif
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate	DGDEF(fpu_version)
1087c478bd9Sstevel@tonic-gate	.word	-1
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate#endif	/* lint */
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate/*
1137c478bd9Sstevel@tonic-gate * FPU probe - read the %fsr and get fpu_version.
1147c478bd9Sstevel@tonic-gate * Called from autoconf. If a %fq is created for
1157c478bd9Sstevel@tonic-gate * future cpu versions, a fq_exists variable
1167c478bd9Sstevel@tonic-gate * could be created by this function.
1177c478bd9Sstevel@tonic-gate */
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate/*ARGSUSED*/
1227c478bd9Sstevel@tonic-gatevoid
1237c478bd9Sstevel@tonic-gatefpu_probe(void)
1247c478bd9Sstevel@tonic-gate{}
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate#else	/* lint */
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate	ENTRY_NP(fpu_probe)
1297c478bd9Sstevel@tonic-gate	wr	%g0, FPRS_FEF, %fprs	! enable fpu in fprs
1307c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g2		! read pstate, save value in %g2
1317c478bd9Sstevel@tonic-gate	or	%g2, PSTATE_PEF, %g1	! new pstate with fpu enabled
1327c478bd9Sstevel@tonic-gate	wrpr	%g1, %g0, %pstate	! write pstate
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate	sethi	%hi(fsrholder), %g2
1357c478bd9Sstevel@tonic-gate	stx	%fsr, [%g2 + %lo(fsrholder)]
1367c478bd9Sstevel@tonic-gate	ldx	[%g2 + %lo(fsrholder)], %g2	! snarf the FSR
1377c478bd9Sstevel@tonic-gate	set	FSR_VER, %g1
1387c478bd9Sstevel@tonic-gate	and	%g2, %g1, %g2			! get version
1397c478bd9Sstevel@tonic-gate	srl	%g2, FSR_VER_SHIFT, %g2		! and shift it down
1407c478bd9Sstevel@tonic-gate	sethi	%hi(fpu_version), %g3		! save the FPU version
1417c478bd9Sstevel@tonic-gate	st	%g2, [%g3 + %lo(fpu_version)]
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate	ba	fp_kstat_init		! initialize the fpu_kstat
1447c478bd9Sstevel@tonic-gate	wr	%g0, %g0, %fprs		! disable fpu and clear fprs
1457c478bd9Sstevel@tonic-gate	SET_SIZE(fpu_probe)
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate#endif	/* lint */
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate/*
1507c478bd9Sstevel@tonic-gate * fp_clearregs(fp)
1517c478bd9Sstevel@tonic-gate *	struct v9_fpu *fp;
1527c478bd9Sstevel@tonic-gate *
1537c478bd9Sstevel@tonic-gate * Initialization for the hardware fpu.
1547c478bd9Sstevel@tonic-gate * Clear the fsr and initialize registers to NaN (-1)
1557c478bd9Sstevel@tonic-gate * The caller (fp_disabled) is supposed to update the fprs
1567c478bd9Sstevel@tonic-gate * so when the return to userland is made, the fpu is enabled.
1577c478bd9Sstevel@tonic-gate */
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate/*ARGSUSED*/
1627c478bd9Sstevel@tonic-gatevoid
1637c478bd9Sstevel@tonic-gatefp_clearregs(kfpu_t *fp)
1647c478bd9Sstevel@tonic-gate{}
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate#else	/* lint */
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate	ENTRY_NP(fp_clearregs)
1697c478bd9Sstevel@tonic-gate	ldx	[%o0 + FPU_FSR], %fsr		! load fsr
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate	mov	-1, %g2				! -1 is NaN
1727c478bd9Sstevel@tonic-gate	stx	%g2, [%o0]			! initialize %f0
1737c478bd9Sstevel@tonic-gate	ldd	[%o0], %d0
1747c478bd9Sstevel@tonic-gate	ldd	[%o0], %d2
1757c478bd9Sstevel@tonic-gate	ldd	[%o0], %d4
1767c478bd9Sstevel@tonic-gate	ldd	[%o0], %d6
1777c478bd9Sstevel@tonic-gate	ldd	[%o0], %d8
1787c478bd9Sstevel@tonic-gate	ldd	[%o0], %d10
1797c478bd9Sstevel@tonic-gate	ldd	[%o0], %d12
1807c478bd9Sstevel@tonic-gate	ldd	[%o0], %d14
1817c478bd9Sstevel@tonic-gate	ldd	[%o0], %d16
1827c478bd9Sstevel@tonic-gate	ldd	[%o0], %d18
1837c478bd9Sstevel@tonic-gate	ldd	[%o0], %d20
1847c478bd9Sstevel@tonic-gate	ldd	[%o0], %d22
1857c478bd9Sstevel@tonic-gate	ldd	[%o0], %d24
1867c478bd9Sstevel@tonic-gate	ldd	[%o0], %d26
1877c478bd9Sstevel@tonic-gate	ldd	[%o0], %d28
1887c478bd9Sstevel@tonic-gate	ldd	[%o0], %d30
1897c478bd9Sstevel@tonic-gate	ldd	[%o0], %d32
1907c478bd9Sstevel@tonic-gate	ldd	[%o0], %d34
1917c478bd9Sstevel@tonic-gate	ldd	[%o0], %d36
1927c478bd9Sstevel@tonic-gate	ldd	[%o0], %d38
1937c478bd9Sstevel@tonic-gate	ldd	[%o0], %d40
1947c478bd9Sstevel@tonic-gate	ldd	[%o0], %d42
1957c478bd9Sstevel@tonic-gate	ldd	[%o0], %d44
1967c478bd9Sstevel@tonic-gate	ldd	[%o0], %d46
1977c478bd9Sstevel@tonic-gate	ldd	[%o0], %d48
1987c478bd9Sstevel@tonic-gate	ldd	[%o0], %d50
1997c478bd9Sstevel@tonic-gate	ldd	[%o0], %d52
2007c478bd9Sstevel@tonic-gate	ldd	[%o0], %d54
2017c478bd9Sstevel@tonic-gate	ldd	[%o0], %d56
2027c478bd9Sstevel@tonic-gate	ldd	[%o0], %d58
2037c478bd9Sstevel@tonic-gate	ldd	[%o0], %d60
2047c478bd9Sstevel@tonic-gate	retl
2057c478bd9Sstevel@tonic-gate	ldd	[%o0], %d62
2067c478bd9Sstevel@tonic-gate	SET_SIZE(fp_clearregs)
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate#endif	/* lint */
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate/*
2117c478bd9Sstevel@tonic-gate * void _fp_read_pfreg(pf, n)
2127c478bd9Sstevel@tonic-gate *	uint32_t	*pf;	Old freg value.
2137c478bd9Sstevel@tonic-gate *	unsigned	n;	Want to read register n
2147c478bd9Sstevel@tonic-gate *
2157c478bd9Sstevel@tonic-gate * {
2167c478bd9Sstevel@tonic-gate *	*pf = %f[n];
2177c478bd9Sstevel@tonic-gate * }
2187c478bd9Sstevel@tonic-gate *
2197c478bd9Sstevel@tonic-gate * void
2207c478bd9Sstevel@tonic-gate * _fp_write_pfreg(pf, n)
2217c478bd9Sstevel@tonic-gate *	uint32_t	*pf;	New freg value.
2227c478bd9Sstevel@tonic-gate *	unsigned	n;	Want to write register n.
2237c478bd9Sstevel@tonic-gate *
2247c478bd9Sstevel@tonic-gate * {
2257c478bd9Sstevel@tonic-gate *	%f[n] = *pf;
2267c478bd9Sstevel@tonic-gate * }
2277c478bd9Sstevel@tonic-gate */
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2327c478bd9Sstevel@tonic-gatevoid
2337c478bd9Sstevel@tonic-gate_fp_read_pfreg(uint32_t *pf, u_int n)
2347c478bd9Sstevel@tonic-gate{}
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2377c478bd9Sstevel@tonic-gatevoid
2387c478bd9Sstevel@tonic-gate_fp_write_pfreg(uint32_t *pf, u_int n)
2397c478bd9Sstevel@tonic-gate{}
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate#else	/* lint */
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_read_pfreg)
2447c478bd9Sstevel@tonic-gate	sll	%o1, 3, %o1		! Table entries are 8 bytes each.
2457c478bd9Sstevel@tonic-gate	set	.stable, %g1		! g1 gets base of table.
2467c478bd9Sstevel@tonic-gate	jmp	%g1 + %o1		! Jump into table
2477c478bd9Sstevel@tonic-gate	nop				! Can't follow CTI by CTI.
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_write_pfreg)
2507c478bd9Sstevel@tonic-gate	sll	%o1, 3, %o1		! Table entries are 8 bytes each.
2517c478bd9Sstevel@tonic-gate	set	.ltable, %g1		! g1 gets base of table.
2527c478bd9Sstevel@tonic-gate	jmp	%g1 + %o1		! Jump into table
2537c478bd9Sstevel@tonic-gate	nop				! Can't follow CTI by CTI.
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate#define STOREFP(n) jmp %o7+8 ; st %f/**/n, [%o0]
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate.stable:
2587c478bd9Sstevel@tonic-gate	STOREFP(0)
2597c478bd9Sstevel@tonic-gate	STOREFP(1)
2607c478bd9Sstevel@tonic-gate	STOREFP(2)
2617c478bd9Sstevel@tonic-gate	STOREFP(3)
2627c478bd9Sstevel@tonic-gate	STOREFP(4)
2637c478bd9Sstevel@tonic-gate	STOREFP(5)
2647c478bd9Sstevel@tonic-gate	STOREFP(6)
2657c478bd9Sstevel@tonic-gate	STOREFP(7)
2667c478bd9Sstevel@tonic-gate	STOREFP(8)
2677c478bd9Sstevel@tonic-gate	STOREFP(9)
2687c478bd9Sstevel@tonic-gate	STOREFP(10)
2697c478bd9Sstevel@tonic-gate	STOREFP(11)
2707c478bd9Sstevel@tonic-gate	STOREFP(12)
2717c478bd9Sstevel@tonic-gate	STOREFP(13)
2727c478bd9Sstevel@tonic-gate	STOREFP(14)
2737c478bd9Sstevel@tonic-gate	STOREFP(15)
2747c478bd9Sstevel@tonic-gate	STOREFP(16)
2757c478bd9Sstevel@tonic-gate	STOREFP(17)
2767c478bd9Sstevel@tonic-gate	STOREFP(18)
2777c478bd9Sstevel@tonic-gate	STOREFP(19)
2787c478bd9Sstevel@tonic-gate	STOREFP(20)
2797c478bd9Sstevel@tonic-gate	STOREFP(21)
2807c478bd9Sstevel@tonic-gate	STOREFP(22)
2817c478bd9Sstevel@tonic-gate	STOREFP(23)
2827c478bd9Sstevel@tonic-gate	STOREFP(24)
2837c478bd9Sstevel@tonic-gate	STOREFP(25)
2847c478bd9Sstevel@tonic-gate	STOREFP(26)
2857c478bd9Sstevel@tonic-gate	STOREFP(27)
2867c478bd9Sstevel@tonic-gate	STOREFP(28)
2877c478bd9Sstevel@tonic-gate	STOREFP(29)
2887c478bd9Sstevel@tonic-gate	STOREFP(30)
2897c478bd9Sstevel@tonic-gate	STOREFP(31)
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate#define LOADFP(n) jmp %o7+8 ; ld [%o0],%f/**/n
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate.ltable:
2947c478bd9Sstevel@tonic-gate	LOADFP(0)
2957c478bd9Sstevel@tonic-gate	LOADFP(1)
2967c478bd9Sstevel@tonic-gate	LOADFP(2)
2977c478bd9Sstevel@tonic-gate	LOADFP(3)
2987c478bd9Sstevel@tonic-gate	LOADFP(4)
2997c478bd9Sstevel@tonic-gate	LOADFP(5)
3007c478bd9Sstevel@tonic-gate	LOADFP(6)
3017c478bd9Sstevel@tonic-gate	LOADFP(7)
3027c478bd9Sstevel@tonic-gate	LOADFP(8)
3037c478bd9Sstevel@tonic-gate	LOADFP(9)
3047c478bd9Sstevel@tonic-gate	LOADFP(10)
3057c478bd9Sstevel@tonic-gate	LOADFP(11)
3067c478bd9Sstevel@tonic-gate	LOADFP(12)
3077c478bd9Sstevel@tonic-gate	LOADFP(13)
3087c478bd9Sstevel@tonic-gate	LOADFP(14)
3097c478bd9Sstevel@tonic-gate	LOADFP(15)
3107c478bd9Sstevel@tonic-gate	LOADFP(16)
3117c478bd9Sstevel@tonic-gate	LOADFP(17)
3127c478bd9Sstevel@tonic-gate	LOADFP(18)
3137c478bd9Sstevel@tonic-gate	LOADFP(19)
3147c478bd9Sstevel@tonic-gate	LOADFP(20)
3157c478bd9Sstevel@tonic-gate	LOADFP(21)
3167c478bd9Sstevel@tonic-gate	LOADFP(22)
3177c478bd9Sstevel@tonic-gate	LOADFP(23)
3187c478bd9Sstevel@tonic-gate	LOADFP(24)
3197c478bd9Sstevel@tonic-gate	LOADFP(25)
3207c478bd9Sstevel@tonic-gate	LOADFP(26)
3217c478bd9Sstevel@tonic-gate	LOADFP(27)
3227c478bd9Sstevel@tonic-gate	LOADFP(28)
3237c478bd9Sstevel@tonic-gate	LOADFP(29)
3247c478bd9Sstevel@tonic-gate	LOADFP(30)
3257c478bd9Sstevel@tonic-gate	LOADFP(31)
3267c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_read_pfreg)
3277c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_write_pfreg)
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate#endif	/* lint */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate/*
3327c478bd9Sstevel@tonic-gate * void _fp_read_pdreg(
3337c478bd9Sstevel@tonic-gate *	uint64_t	*pd,	Old dreg value.
3347c478bd9Sstevel@tonic-gate *	u_int	n)		Want to read register n
3357c478bd9Sstevel@tonic-gate *
3367c478bd9Sstevel@tonic-gate * {
3377c478bd9Sstevel@tonic-gate *	*pd = %d[n];
3387c478bd9Sstevel@tonic-gate * }
3397c478bd9Sstevel@tonic-gate *
3407c478bd9Sstevel@tonic-gate * void
3417c478bd9Sstevel@tonic-gate * _fp_write_pdreg(
3427c478bd9Sstevel@tonic-gate *	uint64_t	*pd,	New dreg value.
3437c478bd9Sstevel@tonic-gate *	u_int	n)		Want to write register n.
3447c478bd9Sstevel@tonic-gate *
3457c478bd9Sstevel@tonic-gate * {
3467c478bd9Sstevel@tonic-gate *	%d[n] = *pd;
3477c478bd9Sstevel@tonic-gate * }
3487c478bd9Sstevel@tonic-gate */
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3537c478bd9Sstevel@tonic-gatevoid
3547c478bd9Sstevel@tonic-gate_fp_read_pdreg(uint64_t *pd, u_int n)
3557c478bd9Sstevel@tonic-gate{}
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3587c478bd9Sstevel@tonic-gatevoid
3597c478bd9Sstevel@tonic-gate_fp_write_pdreg(uint64_t *pd, u_int n)
3607c478bd9Sstevel@tonic-gate{}
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate#else	/* lint */
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_read_pdreg)
3657c478bd9Sstevel@tonic-gate	sll	%o1, 3, %o1		! Table entries are 8 bytes each.
3667c478bd9Sstevel@tonic-gate	set	.dstable, %g1		! g1 gets base of table.
3677c478bd9Sstevel@tonic-gate	jmp	%g1 + %o1		! Jump into table
3687c478bd9Sstevel@tonic-gate	nop				! Can't follow CTI by CTI.
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_write_pdreg)
3717c478bd9Sstevel@tonic-gate	sll	%o1, 3, %o1		! Table entries are 8 bytes each.
3727c478bd9Sstevel@tonic-gate	set	.dltable, %g1		! g1 gets base of table.
3737c478bd9Sstevel@tonic-gate	jmp	%g1 + %o1		! Jump into table
3747c478bd9Sstevel@tonic-gate	nop				! Can't follow CTI by CTI.
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate#define STOREDP(n) jmp %o7+8 ; std %d/**/n, [%o0]
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate.dstable:
3797c478bd9Sstevel@tonic-gate	STOREDP(0)
3807c478bd9Sstevel@tonic-gate	STOREDP(2)
3817c478bd9Sstevel@tonic-gate	STOREDP(4)
3827c478bd9Sstevel@tonic-gate	STOREDP(6)
3837c478bd9Sstevel@tonic-gate	STOREDP(8)
3847c478bd9Sstevel@tonic-gate	STOREDP(10)
3857c478bd9Sstevel@tonic-gate	STOREDP(12)
3867c478bd9Sstevel@tonic-gate	STOREDP(14)
3877c478bd9Sstevel@tonic-gate	STOREDP(16)
3887c478bd9Sstevel@tonic-gate	STOREDP(18)
3897c478bd9Sstevel@tonic-gate	STOREDP(20)
3907c478bd9Sstevel@tonic-gate	STOREDP(22)
3917c478bd9Sstevel@tonic-gate	STOREDP(24)
3927c478bd9Sstevel@tonic-gate	STOREDP(26)
3937c478bd9Sstevel@tonic-gate	STOREDP(28)
3947c478bd9Sstevel@tonic-gate	STOREDP(30)
3957c478bd9Sstevel@tonic-gate	STOREDP(32)
3967c478bd9Sstevel@tonic-gate	STOREDP(34)
3977c478bd9Sstevel@tonic-gate	STOREDP(36)
3987c478bd9Sstevel@tonic-gate	STOREDP(38)
3997c478bd9Sstevel@tonic-gate	STOREDP(40)
4007c478bd9Sstevel@tonic-gate	STOREDP(42)
4017c478bd9Sstevel@tonic-gate	STOREDP(44)
4027c478bd9Sstevel@tonic-gate	STOREDP(46)
4037c478bd9Sstevel@tonic-gate	STOREDP(48)
4047c478bd9Sstevel@tonic-gate	STOREDP(50)
4057c478bd9Sstevel@tonic-gate	STOREDP(52)
4067c478bd9Sstevel@tonic-gate	STOREDP(54)
4077c478bd9Sstevel@tonic-gate	STOREDP(56)
4087c478bd9Sstevel@tonic-gate	STOREDP(58)
4097c478bd9Sstevel@tonic-gate	STOREDP(60)
4107c478bd9Sstevel@tonic-gate	STOREDP(62)
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate#define LOADDP(n) jmp %o7+8 ; ldd [%o0],%d/**/n
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate.dltable:
4157c478bd9Sstevel@tonic-gate	LOADDP(0)
4167c478bd9Sstevel@tonic-gate	LOADDP(2)
4177c478bd9Sstevel@tonic-gate	LOADDP(4)
4187c478bd9Sstevel@tonic-gate	LOADDP(6)
4197c478bd9Sstevel@tonic-gate	LOADDP(8)
4207c478bd9Sstevel@tonic-gate	LOADDP(10)
4217c478bd9Sstevel@tonic-gate	LOADDP(12)
4227c478bd9Sstevel@tonic-gate	LOADDP(14)
4237c478bd9Sstevel@tonic-gate	LOADDP(16)
4247c478bd9Sstevel@tonic-gate	LOADDP(18)
4257c478bd9Sstevel@tonic-gate	LOADDP(20)
4267c478bd9Sstevel@tonic-gate	LOADDP(22)
4277c478bd9Sstevel@tonic-gate	LOADDP(24)
4287c478bd9Sstevel@tonic-gate	LOADDP(26)
4297c478bd9Sstevel@tonic-gate	LOADDP(28)
4307c478bd9Sstevel@tonic-gate	LOADDP(30)
4317c478bd9Sstevel@tonic-gate	LOADDP(32)
4327c478bd9Sstevel@tonic-gate	LOADDP(34)
4337c478bd9Sstevel@tonic-gate	LOADDP(36)
4347c478bd9Sstevel@tonic-gate	LOADDP(38)
4357c478bd9Sstevel@tonic-gate	LOADDP(40)
4367c478bd9Sstevel@tonic-gate	LOADDP(42)
4377c478bd9Sstevel@tonic-gate	LOADDP(44)
4387c478bd9Sstevel@tonic-gate	LOADDP(46)
4397c478bd9Sstevel@tonic-gate	LOADDP(48)
4407c478bd9Sstevel@tonic-gate	LOADDP(50)
4417c478bd9Sstevel@tonic-gate	LOADDP(52)
4427c478bd9Sstevel@tonic-gate	LOADDP(54)
4437c478bd9Sstevel@tonic-gate	LOADDP(56)
4447c478bd9Sstevel@tonic-gate	LOADDP(58)
4457c478bd9Sstevel@tonic-gate	LOADDP(60)
4467c478bd9Sstevel@tonic-gate	LOADDP(62)
4477c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_read_pdreg)
4487c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_write_pdreg)
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate#endif	/* lint */
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4557c478bd9Sstevel@tonic-gatevoid
4567c478bd9Sstevel@tonic-gate_fp_write_pfsr(uint64_t *fsr)
4577c478bd9Sstevel@tonic-gate{}
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate#else	/* lint */
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_write_pfsr)
4627c478bd9Sstevel@tonic-gate	retl
4637c478bd9Sstevel@tonic-gate	ldx	[%o0], %fsr
4647c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_write_pfsr)
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate#endif	/* lint */
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4717c478bd9Sstevel@tonic-gatevoid
4727c478bd9Sstevel@tonic-gate_fp_read_pfsr(uint64_t *fsr)
4737c478bd9Sstevel@tonic-gate{}
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate#else	/* lint */
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_read_pfsr)
4787c478bd9Sstevel@tonic-gate	retl
4797c478bd9Sstevel@tonic-gate	stx	%fsr, [%o0]
4807c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_read_pfsr)
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate#endif	/* lint */
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4877c478bd9Sstevel@tonic-gatevoid
4887c478bd9Sstevel@tonic-gate_fp_write_fprs(u_int fprs_val)
4897c478bd9Sstevel@tonic-gate{}
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate#else	/* lint */
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_write_fprs)
4947c478bd9Sstevel@tonic-gate	retl
4957c478bd9Sstevel@tonic-gate	wr	%o0, %g0, %fprs			! write fprs
4967c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_write_fprs)
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate#endif	/* lint */
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gateunsigned
5037c478bd9Sstevel@tonic-gate_fp_read_fprs(void)
5047c478bd9Sstevel@tonic-gate{return 0;}
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate#else	/* lint */
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_read_fprs)
5097c478bd9Sstevel@tonic-gate	retl
5107c478bd9Sstevel@tonic-gate	rd	%fprs, %o0			! save fprs
5117c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_read_fprs)
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate#endif	/* lint */
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate#if defined(lint) || defined(__lint)
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gateunsigned
5187c478bd9Sstevel@tonic-gate_fp_subcc_ccr(void)
5197c478bd9Sstevel@tonic-gate{return 0;}
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate#else	/* lint */
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate	ENTRY_NP(_fp_subcc_ccr)
5247c478bd9Sstevel@tonic-gate	subcc	%o0, %o1, %g0
5257c478bd9Sstevel@tonic-gate	retl
5267c478bd9Sstevel@tonic-gate	rd	%ccr, %o0			! save ccr
5277c478bd9Sstevel@tonic-gate	SET_SIZE(_fp_subcc_ccr)
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate#endif	/* lint */
530*7bafd143Sjb145095
531*7bafd143Sjb145095/*
532*7bafd143Sjb145095 * Floating Point Exceptions handled according to type:
533*7bafd143Sjb145095 *	2) unfinished_fpop
534*7bafd143Sjb145095 *		re-execute the faulty instruction(s) using
535*7bafd143Sjb145095 *		software emulation (must do every instruction in FQ)
536*7bafd143Sjb145095 *	3) unimplemented_fpop
537*7bafd143Sjb145095 *		an unimplemented instruction, if it is legal,
538*7bafd143Sjb145095 *		will cause emulation of the instruction (and all
539*7bafd143Sjb145095 *		other instuctions in the FQ)
540*7bafd143Sjb145095 *	4) sequence_error
541*7bafd143Sjb145095 *		panic, this should not happen, and if it does it
542*7bafd143Sjb145095 *		it is the result of a kernel bug
543*7bafd143Sjb145095 *
544*7bafd143Sjb145095 * This code assumes the trap preamble has set up the window environment
545*7bafd143Sjb145095 * for execution of kernel code.
546*7bafd143Sjb145095 * Note: this code could be changed to be part of the cpu-specific
547*7bafd143Sjb145095 * (ie, Spitfire-specific) module code before final release.
548*7bafd143Sjb145095 */
549*7bafd143Sjb145095
550*7bafd143Sjb145095#if defined(lint)
551*7bafd143Sjb145095
552*7bafd143Sjb145095/* ARGSUSED */
553*7bafd143Sjb145095void
554*7bafd143Sjb145095_fp_exception(struct regs *rp, uint64_t fsr)
555*7bafd143Sjb145095{}
556*7bafd143Sjb145095
557*7bafd143Sjb145095#else	/* lint */
558*7bafd143Sjb145095
559*7bafd143Sjb145095	ENTRY_NP(_fp_exception)
560*7bafd143Sjb145095	mov	%o7, %l0		! saved return address
561*7bafd143Sjb145095	mov	%o0, %l1		! saved *rp
562*7bafd143Sjb145095	set     FSR_FTT, %o4		! put FSR_FTT in %o4
563*7bafd143Sjb145095	xor	%o4, 0xffffffffffffffff, %o3 ! xor FSR_FTT to get
564*7bafd143Sjb145095	and     %o1, %o3, %o2		! an fsr with a zero'd ftt
565*7bafd143Sjb145095	ldn	[THREAD_REG + T_LWP], %o3 ! get lwp
566*7bafd143Sjb145095	ldn	[%o3 + LWP_FPU], %l3	! get lwp_fpu
567*7bafd143Sjb145095	stx	%o2, [%l3 + FPU_FSR]	! save floating point status
568*7bafd143Sjb145095	and	%o1, %o4, %g2		! get the ftt trap type
569*7bafd143Sjb145095#ifdef  DEBUG
570*7bafd143Sjb145095	brnz,a,pt %g2, fttok
571*7bafd143Sjb145095	  nop
572*7bafd143Sjb145095	set	.badfpfttmsg, %o0	! panic message
573*7bafd143Sjb145095	call	panic			! %o1 has the fsr w/ftt value
574*7bafd143Sjb145095	nop
575*7bafd143Sjb145095fttok:
576*7bafd143Sjb145095#endif  /* DEBUG */
577*7bafd143Sjb145095	srl	%g2, FSR_FTT_SHIFT, %o4	! check ftt
578*7bafd143Sjb145095	cmp	%o4, FTT_SEQ		! sanity check for bogus exceptions
579*7bafd143Sjb145095	!
580*7bafd143Sjb145095	! traps are already enabled to allow other
581*7bafd143Sjb145095	! interrupts while emulating floating point instructions
582*7bafd143Sjb145095	!
583*7bafd143Sjb145095	blt,a,pt %xcc, fpeok
584*7bafd143Sjb145095	nop
585*7bafd143Sjb145095	!
586*7bafd143Sjb145095	! Sequence error or unknown ftt exception.
587*7bafd143Sjb145095	!
588*7bafd143Sjb145095seq_error:
589*7bafd143Sjb145095	set	.badfpexcpmsg, %o0	! panic if bad ftt
590*7bafd143Sjb145095	call	panic
591*7bafd143Sjb145095	sra	%o4, 0, %o1		! mov ftt to o1 for panic message
592*7bafd143Sjb145095
593*7bafd143Sjb145095fpeok:
594*7bafd143Sjb145095	call	fp_kstat_update		! fp_kstat_update(ftt)
595*7bafd143Sjb145095	mov	%o4, %o0		! ftt
596*7bafd143Sjb145095	!
597*7bafd143Sjb145095	! Get the floating point instruction, and run the floating
598*7bafd143Sjb145095	! point simulator. There is no floating point queue, so we fake one.
599*7bafd143Sjb145095	!
600*7bafd143Sjb145095	call	fp_precise		! fp_precise(&regs)
601*7bafd143Sjb145095	mov	%l1, %o0		! saved *rp
602*7bafd143Sjb145095
603*7bafd143Sjb145095fp_ret:
604*7bafd143Sjb145095	rd	%fprs, %g1		! read fprs, save value in %g1
605*7bafd143Sjb145095	st	%g1, [%l3 + FPU_FPRS]	! save fprs
606*7bafd143Sjb145095	jmp	%l0 + 8			! jump to saved return address
607*7bafd143Sjb145095	stx	%fsr, [%l3 + FPU_FSR]	! save fsr
608*7bafd143Sjb145095	SET_SIZE(_fp_exception)
609*7bafd143Sjb145095
610*7bafd143Sjb145095.badfpexcpmsg:
611*7bafd143Sjb145095	.asciz	"unexpected floating point exception %x"
612*7bafd143Sjb145095
613*7bafd143Sjb145095#ifdef	DEBUG
614*7bafd143Sjb145095.badfpfttmsg:
615*7bafd143Sjb145095	.asciz	"No floating point ftt, fsr %llx"
616*7bafd143Sjb145095#endif	/* DEBUG */
617*7bafd143Sjb145095
618*7bafd143Sjb145095#endif	/* lint */
619*7bafd143Sjb145095
620*7bafd143Sjb145095/*
621*7bafd143Sjb145095 * Floating Point Exceptions.
622*7bafd143Sjb145095 * handled according to type:
623*7bafd143Sjb145095 *	1) IEEE_exception
624*7bafd143Sjb145095 *		re-execute the faulty instruction(s) using
625*7bafd143Sjb145095 *		software emulation (must do every instruction in FQ)
626*7bafd143Sjb145095 *
627*7bafd143Sjb145095 * This code assumes the trap preamble has set up the window environment
628*7bafd143Sjb145095 * for execution of kernel code.
629*7bafd143Sjb145095 */
630*7bafd143Sjb145095
631*7bafd143Sjb145095#if defined(lint)
632*7bafd143Sjb145095
633*7bafd143Sjb145095/* ARGSUSED */
634*7bafd143Sjb145095void
635*7bafd143Sjb145095_fp_ieee_exception(struct regs *rp, uint64_t fsr)
636*7bafd143Sjb145095{}
637*7bafd143Sjb145095
638*7bafd143Sjb145095#else	/* lint */
639*7bafd143Sjb145095
640*7bafd143Sjb145095	ENTRY_NP(_fp_ieee_exception)
641*7bafd143Sjb145095	mov	%o7, %l0		! saved return address
642*7bafd143Sjb145095	mov	%o0, %l1		! saved *rp
643*7bafd143Sjb145095	mov	%o1, %l2		! saved fsr
644*7bafd143Sjb145095	set	FSR_FTT, %o4		! put FSR_FTT in %o4
645*7bafd143Sjb145095	xor	%o4, 0xffffffffffffffff, %o3 ! ! xor FSR_FTT to get
646*7bafd143Sjb145095	and	%o1, %o3, %o2		! an fsr with a zero'd ftt
647*7bafd143Sjb145095	ldn	[THREAD_REG + T_LWP], %o3 ! get lwp
648*7bafd143Sjb145095	ldn	[%o3 + LWP_FPU], %l3	! get lwp_fpu
649*7bafd143Sjb145095	stx	%o2, [%l3 + FPU_FSR]	! save floating point status
650*7bafd143Sjb145095	stub	%g0, [%l3 + FPU_QCNT]	! clear fpu_qcnt
651*7bafd143Sjb145095	and	%o1, %o4, %g2		! mask out trap type
652*7bafd143Sjb145095#ifdef  DEBUG
653*7bafd143Sjb145095	brnz,a,pt %g2, fttgd
654*7bafd143Sjb145095	  nop
655*7bafd143Sjb145095	set	.badfpfttmsg, %o0	! panic message
656*7bafd143Sjb145095	call	panic			! %o1 has the fsr w/ftt value
657*7bafd143Sjb145095	nop
658*7bafd143Sjb145095fttgd:
659*7bafd143Sjb145095#endif	/* DEBUG */
660*7bafd143Sjb145095	srl	%g2, FSR_FTT_SHIFT, %o4	! check ftt
661*7bafd143Sjb145095	cmp	%o4, FTT_SEQ		! sanity check for bogus exceptions
662*7bafd143Sjb145095	!
663*7bafd143Sjb145095	! traps are already enabled to allow other
664*7bafd143Sjb145095	! interrupts while emulating floating point instructions
665*7bafd143Sjb145095	!
666*7bafd143Sjb145095	blt,a,pt %xcc, fpegd
667*7bafd143Sjb145095	nop
668*7bafd143Sjb145095	!
669*7bafd143Sjb145095	! Sequence error or unknown ftt exception.
670*7bafd143Sjb145095	!
671*7bafd143Sjb145095seq_err:
672*7bafd143Sjb145095	set	.badfpexcpmsg, %o0	! panic if bad ftt
673*7bafd143Sjb145095	call	panic
674*7bafd143Sjb145095	sra	%o4, 0, %o1		! mov ftt to o1 for panic message
675*7bafd143Sjb145095
676*7bafd143Sjb145095fpegd:
677*7bafd143Sjb145095	call	fp_kstat_update		! fp_kstat_update(ftt)
678*7bafd143Sjb145095	mov	%o4, %o0		! ftt
679*7bafd143Sjb145095	!
680*7bafd143Sjb145095	! Call fpu_trap directly, don't bother to run the fp simulator.
681*7bafd143Sjb145095	! The *rp is already in %o0. Clear fpu_qcnt.
682*7bafd143Sjb145095	!
683*7bafd143Sjb145095	set	(T_FP_EXCEPTION_IEEE), %o2	! trap type
684*7bafd143Sjb145095
685*7bafd143Sjb145095	set	FSR_CEXC, %o3
686*7bafd143Sjb145095	and	%l2, %o3, %g2		! mask out cexc
687*7bafd143Sjb145095
688*7bafd143Sjb145095	andcc	%g2, FSR_CEXC_NX, %g0	! check for inexact
689*7bafd143Sjb145095	bnz,a,pt %xcc, fpok
690*7bafd143Sjb145095	or	%g0, FPE_FLTRES, %o3	! fp inexact code
691*7bafd143Sjb145095
692*7bafd143Sjb145095	andcc	%g2, FSR_CEXC_DZ, %g0	! check for divide-by-zero
693*7bafd143Sjb145095	bnz,a,pt %xcc, fpok
694*7bafd143Sjb145095	or	%g0, FPE_FLTDIV, %o3	! fp divide by zero code
695*7bafd143Sjb145095
696*7bafd143Sjb145095	andcc	%g2, FSR_CEXC_UF, %g0	! check for underflow
697*7bafd143Sjb145095	bnz,a,pt %xcc, fpok
698*7bafd143Sjb145095	or	%g0, FPE_FLTUND, %o3	! fp underflow code
699*7bafd143Sjb145095
700*7bafd143Sjb145095	andcc	%g2, FSR_CEXC_OF, %g0	! check for overflow
701*7bafd143Sjb145095	bnz,a,pt %xcc, fpok
702*7bafd143Sjb145095	or	%g0, FPE_FLTOVF, %o3	! fp overflow code
703*7bafd143Sjb145095
704*7bafd143Sjb145095	andcc	%g2, FSR_CEXC_NV, %g0	! check for invalid
705*7bafd143Sjb145095	bnz,a,pn %xcc, fpok
706*7bafd143Sjb145095	or	%g0, FPE_FLTINV, %o3	! fp invalid code
707*7bafd143Sjb145095
708*7bafd143Sjb145095cexec_err:
709*7bafd143Sjb145095	set	.badfpcexcmsg, %o0	! panic message
710*7bafd143Sjb145095	call	panic			! panic if no cexc bit set
711*7bafd143Sjb145095	mov	%g1, %o1
712*7bafd143Sjb145095fpok:
713*7bafd143Sjb145095	mov	%l1, %o0		! saved *rp
714*7bafd143Sjb145095	call	fpu_trap		! fpu_trap(&regs, addr, type, code)
715*7bafd143Sjb145095	ldn	[%o0 + PC_OFF], %o1 	! address of trapping instruction
716*7bafd143Sjb145095
717*7bafd143Sjb145095	rd	%fprs, %g1		! read fprs, save value in %g1
718*7bafd143Sjb145095	st	%g1, [%l3 + FPU_FPRS]	! save fprs
719*7bafd143Sjb145095	jmp	%l0 + 8			! jump to saved return address
720*7bafd143Sjb145095	stx	%fsr, [%l3 + FPU_FSR]	! save fsr
721*7bafd143Sjb145095	SET_SIZE(_fp_ieee_exception)
722*7bafd143Sjb145095
723*7bafd143Sjb145095.badfpcexcmsg:
724*7bafd143Sjb145095	.asciz	"No floating point exception, fsr %llx"
725*7bafd143Sjb145095
726*7bafd143Sjb145095#endif	/* lint */
727