1. Split fp.h into fp.h and fsr.h so that the latter can be included

in asm files.
2. Temporarily cause subnormal operands in floating point operations
   to be treated as zeros so that comlpetion of the operation does not
   need to be emulated.
3. Catch fp_exception_other and correctly skip over the unfinished
   instruction, but basically ignore them.  Emulating the instruction
   is not yet supported.
4. Zero td_retval[1] as well in syscall().

Submitted by:	tmm (2, 3)
This commit is contained in:
Jake Burkholder 2001-11-18 04:00:22 +00:00
parent bf8f99b4b7
commit 86f466074c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=86530
5 changed files with 155 additions and 45 deletions

View File

@ -27,43 +27,6 @@
#ifndef _MACHINE_FP_H_
#define _MACHINE_FP_H_
#define FPRS_DL (1 << 0)
#define FPRS_DU (1 << 1)
#define FPRS_FEF (1 << 2)
#define FSR_CEXC_NX (1 << 0)
#define FSR_CEXC_DZ (1 << 1)
#define FSR_CEXC_UF (1 << 2)
#define FSR_CEXC_OF (1 << 3)
#define FSR_CEXC_NV (1 << 4)
#define FSR_AEXC_NX (1 << 5)
#define FSR_AEXC_DZ (1 << 6)
#define FSR_AEXC_UF (1 << 7)
#define FSR_AEXC_OF (1 << 8)
#define FSR_AEXC_NV (1 << 9)
#define FSR_QNE (1 << 13)
#define FSR_NS (1 << 22)
#define FSR_TEM_NX (1 << 23)
#define FSR_TEM_DZ (1 << 24)
#define FSR_TEM_UF (1 << 25)
#define FSR_TEM_OF (1 << 26)
#define FSR_TEM_NV (1 << 27)
#define FSR_FCC0_SHIFT 10
#define FSR_FCC0(x) (((x) >> FSR_FCC0_SHIFT) & 3)
#define FSR_FTT_SHIFT 14
#define FSR_FTT(x) (((x) >> FSR_FTT_SHIFT) & 7)
#define FSR_VER_SHIFT 17
#define FSR_VER(x) (((x) >> FSR_VER_SHIFT) & 7)
#define FSR_RD_SHIFT 30
#define FSR_RD(x) (((x) >> FSR_RD_SHIFT) & 3)
#define FSR_FCC1_SHIFT 32
#define FSR_FCC1(x) (((x) >> FSR_FCC1_SHIFT) & 3)
#define FSR_FCC2_SHIFT 34
#define FSR_FCC2(x) (((x) >> FSR_FCC2_SHIFT) & 3)
#define FSR_FCC3_SHIFT 36
#define FSR_FCC3(x) (((x) >> FSR_FCC3_SHIFT) & 3)
/* A block of 8 double-precision (16 single-precision) FP registers. */
struct fpblock {
u_long fpq_l[8];
@ -75,8 +38,14 @@ struct fpstate {
u_long fp_fprs;
};
#ifdef _KERNEL
struct pcb;
struct thread;
void fp_init_thread(struct pcb *);
int fp_enable_thread(struct thread *);
int fp_enable_thread(struct thread *, struct trapframe *);
int fp_exception_other(struct thread *, struct trapframe *);
/*
* Note: The pointers passed to the next two functions must be aligned on
* 64 byte boundaries.
@ -84,4 +53,5 @@ int fp_enable_thread(struct thread *);
void savefpctx(struct fpstate *);
void restorefpctx(struct fpstate *);
#endif /* _KERNEL */
#endif /* !_MACHINE_FP_H_ */

105
sys/sparc64/include/fsr.h Normal file
View File

@ -0,0 +1,105 @@
/*-
* Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_FSR_H_
#define _MACHINE_FSR_H_
#define FPRS_DL (1 << 0)
#define FPRS_DU (1 << 1)
#define FPRS_FEF (1 << 2)
#define FSR_EXC_BITS 5
#define FSR_EXC_MASK ((1 << FSR_EXC_BITS) - 1)
#define FSR_CEXC_SHIFT 0
#define FSR_CEXC_MASK (FSR_EXC_MASK << FSR_CEXC_SHIFT)
#define FSR_CEXC(b) ((b) << FSR_CEXC_SHIFT)
#define FSR_AEXC_SHIFT 5
#define FSR_AEXC_MASK (FSR_EXC_MASK << FSR_AEXC_SHIFT)
#define FSR_AEXC(b) ((b) << FSR_AEXC_SHIFT)
#define FSR_QNE (1 << 13)
#define FSR_NS (1 << 22)
#define FSR_TEM_SHIFT 23
#define FSR_TEM_MASK (FSR_EXC_MASK << FSR_TEM_SHIFT)
#define FSR_TEM(b) ((b) << FSR_TEM_SHIFT)
#define FSR_FCC0_SHIFT 10
#define FSR_FCC0_BITS 2
#define FSR_FCC0_MASK (((1 << FSR_FCC0_BITS) - 1) << FSR_FCC0_SHIFT)
#define FSR_FCC0(x) ((x) << FSR_FCC0_SHIFT)
#define FSR_GET_FCC0(x) (((x) >> FSR_FCC0_SHIFT) & 3)
#define FSR_FTT_SHIFT 14
#define FSR_FTT_BITS 3
#define FSR_FTT_MASK (((1 << FSR_FTT_BITS) - 1) << FSR_FTT_SHIFT)
#define FSR_FTT(x) ((x) << FSR_FTT_SHIFT)
#define FSR_GET_FTT(x) (((x) & FSR_FTT_MASK) >> FSR_FTT_SHIFT)
#define FSR_VER_SHIFT 17
#define FSR_GET_VER(x) (((x) >> FSR_VER_SHIFT) & 7)
#define FSR_RD_SHIFT 30
#define FSR_RD_BITS 2
#define FSR_RD_MASK (((1 << FSR_RD_BITS) - 1) << FSR_RD_SHIFT)
#define FSR_RD(x) ((x) << FSR_RD_SHIFT)
#define FSR_GET_RD(x) (((x) >> FSR_RD_SHIFT) & 3)
#define FSR_FCC1_SHIFT 32
#define FSR_FCC1_BITS 2
#define FSR_FCC1_MASK (((1 << FSR_FCC1_BITS) - 1) << FSR_FCC1_SHIFT)
#define FSR_FCC1(x) ((x) << FSR_FCC1_SHIFT)
#define FSR_GET_FCC1(x) (((x) >> FSR_FCC1_SHIFT) & 3)
#define FSR_FCC2_SHIFT 34
#define FSR_FCC2_BITS 2
#define FSR_FCC2_MASK (((1 << FSR_FCC2_BITS) - 1) << FSR_FCC2_SHIFT)
#define FSR_FCC2(x) ((x) << FSR_FCC2_SHIFT)
#define FSR_GET_FCC2(x) (((x) >> FSR_FCC2_SHIFT) & 3)
#define FSR_FCC3_SHIFT 36
#define FSR_FCC3_BITS 2
#define FSR_FCC3_MASK (((1 << FSR_FCC3_BITS) - 1) << FSR_FCC3_SHIFT)
#define FSR_FCC3(x) ((x) << FSR_FCC3_SHIFT)
#define FSR_GET_FCC3(x) (((x) >> FSR_FCC3_SHIFT) & 3)
/* CEXC/AEXC/TEM exception values */
#define FSR_NX (1 << 0)
#define FSR_DZ (1 << 1)
#define FSR_UF (1 << 2)
#define FSR_OF (1 << 3)
#define FSR_NV (1 << 4)
/* FTT values. */
#define FSR_FTT_NONE 0
#define FSR_FTT_IEEE 1
#define FSR_FTT_UNFIN 2
#define FSR_FTT_UNIMP 3
#define FSR_FTT_SEQERR 4
#define FSR_FTT_HWERR 5
#define FSR_FTT_INVREG 6
/* RD values */
#define FSR_RD_N 0 /* nearest */
#define FSR_RD_Z 1 /* zero */
#define FSR_RD_PINF 2 /* +infinity */
#define FSR_RD_NINF 3 /* -infinity */
/* condition codes */
#define FSR_CC_EQ 0 /* a = b */
#define FSR_CC_LT 1 /* a < b */
#define FSR_CC_GT 2 /* a > b */
#define FSR_CC_UO 3 /* unordered */
#endif /* !_MACHINE_FSR_H_ */

View File

@ -160,6 +160,7 @@
#include <machine/cache.h>
#include <machine/cpufunc.h>
#include <machine/fp.h>
#include <machine/fsr.h>
#include <machine/pcb.h>
#include <machine/pmap.h>
#include <machine/tte.h>

View File

@ -26,12 +26,15 @@
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/ktr.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <machine/fp.h>
#include <machine/frame.h>
#include <machine/fsr.h>
#include <machine/pcb.h>
#include <machine/tstate.h>
@ -40,17 +43,31 @@ fp_init_thread(struct pcb *pcb)
{
bzero(&pcb->pcb_fpstate.fp_fb, sizeof(pcb->pcb_fpstate.fp_fb));
#if 0
pcb->pcb_fpstate.fp_fsr = 0;
#else
/*
* This causes subnormal operands to be treated as zeroes, which
* prevents unfinished_FPop traps in this cases, which would require
* emultation that is not yet implemented.
* This does of course reduce the accuracy, so it should be removed
* as soon as possible.
*/
pcb->pcb_fpstate.fp_fsr = FSR_NS;
#endif
wr(fprs, 0, 0);
}
int
fp_enable_thread(struct thread *td)
fp_enable_thread(struct thread *td, struct trapframe *tf)
{
struct pcb *pcb;
pcb = td->td_pcb;
if ((td->td_frame->tf_tstate & TSTATE_PEF) != 0 &&
CTR5(KTR_TRAP, "fp_enable_thread: tpc=%#lx, tnpc=%#lx, tstate=%#lx, "
"fprs=%#lx, fsr=%#lx", tf->tf_tpc, tf->tf_tnpc, tf->tf_tstate,
pcb->pcb_fpstate.fp_fprs, pcb->pcb_fpstate.fp_fsr);
if ((tf->tf_tstate & TSTATE_PEF) != 0 &&
(pcb->pcb_fpstate.fp_fprs & FPRS_FEF) == 0) {
/*
* Enable FEF for now. The SCD mandates that this should be
@ -61,12 +78,24 @@ fp_enable_thread(struct thread *td)
return (1);
}
if ((td->td_frame->tf_tstate & TSTATE_PEF) != 0)
if ((tf->tf_tstate & TSTATE_PEF) != 0)
return (0);
mtx_lock_spin(&sched_lock);
td->td_frame->tf_tstate |= TSTATE_PEF;
tf->tf_tstate |= TSTATE_PEF;
/* Actually load the FP state into the registers. */
restorefpctx(&pcb->pcb_fpstate);
mtx_unlock_spin(&sched_lock);
return (1);
}
int
fp_exception_other(struct thread *td, struct trapframe *tf)
{
u_long fsr;
__asm __volatile("stx %%fsr, %0" : "=m" (fsr));
CTR4(KTR_TRAP, "fp_exception_other: tpc=%#lx, tnpc=%#lx, ftt=%lx "
"fsr=%lx", tf->tf_tpc, tf->tf_tnpc, FSR_FTT(fsr), fsr);
/* XXX: emulate unimplemented and unfinished instructions. */
return (SIGFPE);
}

View File

@ -194,13 +194,18 @@ trap(struct trapframe *tf)
sig = SIGFPE;
goto trapsig;
case T_FP_DISABLED:
if (fp_enable_thread(td))
if (fp_enable_thread(td, tf))
goto user;
/* Fallthrough. */
case T_FP_IEEE:
case T_FP_OTHER:
sig = SIGFPE;
goto trapsig;
case T_FP_OTHER:
if ((sig = fp_exception_other(td, tf)) == 0) {
TF_DONE(tf);
goto user;
}
goto trapsig;
case T_DATA_ERROR:
case T_DATA_EXCPTN:
case T_INSN_ERROR:
@ -590,7 +595,7 @@ syscall(struct trapframe *tf)
}
#endif
td->td_retval[0] = 0;
td->td_retval[1] = tf->tf_out[1];
td->td_retval[1] = 0;
STOPEVENT(p, S_SCE, narg); /* MP aware */