Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc/fpu Set FPSCR[FPRF] for calculated result, ...
details: https://anonhg.NetBSD.org/src/rev/d006cdcce40e
branches: trunk
changeset: 369788:d006cdcce40e
user: rin <rin%NetBSD.org@localhost>
date: Thu Sep 01 06:08:16 2022 +0000
description:
Set FPSCR[FPRF] for calculated result, for all instructions
that are documented to update this field.
Exceptions are fcti{w,d}{,z}; FPSCR[FPRF] becomes undefined,
according to Power ISA. We do not overwrite this field for
these insns at the moment.
diffstat:
sys/arch/powerpc/fpu/fpu_emu.c | 13 +++---
sys/arch/powerpc/fpu/fpu_emu.h | 15 ++++---
sys/arch/powerpc/fpu/fpu_implode.c | 74 +++++++++++++++++++++++++++++++------
3 files changed, 76 insertions(+), 26 deletions(-)
diffs (300 lines):
diff -r 93b8b40f51d1 -r d006cdcce40e sys/arch/powerpc/fpu/fpu_emu.c
--- a/sys/arch/powerpc/fpu/fpu_emu.c Thu Sep 01 05:58:19 2022 +0000
+++ b/sys/arch/powerpc/fpu/fpu_emu.c Thu Sep 01 06:08:16 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emu.c,v 1.43 2022/08/30 11:09:34 rin Exp $ */
+/* $NetBSD: fpu_emu.c,v 1.44 2022/09/01 06:08:16 rin Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.43 2022/08/30 11:09:34 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.44 2022/09/01 06:08:16 rin Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -496,7 +496,7 @@
fpu_implode(fe, fp, FTYPE_SNG,
(u_int *)&fs->fpreg[rt]);
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
- type = FTYPE_DBL;
+ type = FTYPE_DBL | FTYPE_FPRF;
break;
case OPC63_FCTIW:
case OPC63_FCTIWZ:
@@ -624,7 +624,7 @@
DPRINTF(FPE_INSN, ("fpu_execute: FCFID\n"));
type = FTYPE_LNG;
fpu_explode(fe, fp = &fe->fe_f1, type, rb);
- type = FTYPE_DBL;
+ type = FTYPE_DBL | FTYPE_FPRF;
break;
default:
return (NOTFPU);
@@ -765,10 +765,11 @@
/* If the instruction was single precision, round */
if (!(instr.i_any.i_opcd & 0x4)) {
- fpu_implode(fe, fp, FTYPE_SNG,
+ fpu_implode(fe, fp, FTYPE_SNG | FTYPE_FPRF,
(u_int *)&fs->fpreg[rt]);
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
- }
+ } else
+ type |= FTYPE_FPRF;
}
} else {
return (NOTFPU);
diff -r 93b8b40f51d1 -r d006cdcce40e sys/arch/powerpc/fpu/fpu_emu.h
--- a/sys/arch/powerpc/fpu/fpu_emu.h Thu Sep 01 05:58:19 2022 +0000
+++ b/sys/arch/powerpc/fpu/fpu_emu.h Thu Sep 01 06:08:16 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emu.h,v 1.6 2022/08/30 11:09:34 rin Exp $ */
+/* $NetBSD: fpu_emu.h,v 1.7 2022/09/01 06:08:16 rin Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -136,12 +136,13 @@
/*
* FPU data types.
*/
-#define FTYPE_INT 0x0 /* data = 32-bit signed integer */
-#define FTYPE_LNG 0x1 /* data = 64-bit signed long integer */
-#define FTYPE_SNG 0x2 /* data = 32-bit float */
-#define FTYPE_DBL 0x4 /* data = 64-bit double */
-#define FTYPE_RD_RZ 0x8
-#define FTYPE_RD_MASK (FTYPE_RD_RZ)
+#define FTYPE_INT 0x00 /* data = 32-bit signed integer */
+#define FTYPE_LNG 0x01 /* data = 64-bit signed long integer */
+#define FTYPE_SNG 0x02 /* data = 32-bit float */
+#define FTYPE_DBL 0x04 /* data = 64-bit double */
+#define FTYPE_RD_RZ 0x08
+#define FTYPE_FPRF 0x10
+#define FTYPE_FLAG_MASK (FTYPE_RD_RZ | FTYPE_FPRF)
/*
* Emulator state.
diff -r 93b8b40f51d1 -r d006cdcce40e sys/arch/powerpc/fpu/fpu_implode.c
--- a/sys/arch/powerpc/fpu/fpu_implode.c Thu Sep 01 05:58:19 2022 +0000
+++ b/sys/arch/powerpc/fpu/fpu_implode.c Thu Sep 01 06:08:16 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_implode.c,v 1.13 2022/09/01 05:58:19 rin Exp $ */
+/* $NetBSD: fpu_implode.c,v 1.14 2022/09/01 06:08:16 rin Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_implode.c,v 1.13 2022/09/01 05:58:19 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_implode.c,v 1.14 2022/09/01 06:08:16 rin Exp $");
#include <sys/types.h>
#include <sys/systm.h>
@@ -66,8 +66,8 @@
static u_int fpu_ftoi(struct fpemu *, struct fpn *, int);
static uint64_t fpu_ftox(struct fpemu *, struct fpn *, int);
-static u_int fpu_ftos(struct fpemu *, struct fpn *);
-static u_int fpu_ftod(struct fpemu *, struct fpn *, u_int *);
+static u_int fpu_ftos(struct fpemu *, struct fpn *, bool);
+static u_int fpu_ftod(struct fpemu *, struct fpn *, u_int *, bool);
/*
* Round a number (algorithm from Motorola MC68882 manual, modified for
@@ -333,12 +333,14 @@
return (0x7fffffffffffffffLL + sign);
}
+#define FPRF_SIGN(sign) ((sign) ? FPSCR_FL : FPSCR_FG)
+
/*
* fpn -> single (32 bit single returned as return value).
* We assume <= 29 bits in a single-precision fraction (1.f part).
*/
static u_int
-fpu_ftos(struct fpemu *fe, struct fpn *fp)
+fpu_ftos(struct fpemu *fe, struct fpn *fp, bool fprf)
{
u_int sign = fp->fp_sign << 31;
int exp;
@@ -348,6 +350,8 @@
/* Take care of non-numbers first. */
if (ISNAN(fp)) {
+ if (fprf)
+ fe->fe_cx |= FPSCR_C | FPSCR_FU;
/*
* Preserve upper bits of NaN, per SPARC V8 appendix N.
* Note that fp->fp_mant[0] has the quiet bit set,
@@ -357,10 +361,19 @@
exp = SNG_EXP_INFNAN;
goto done;
}
- if (ISINF(fp))
+ if (ISINF(fp)) {
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign) | FPSCR_FU;
return (sign | SNG_EXP(SNG_EXP_INFNAN));
- if (ISZERO(fp))
+ }
+ if (ISZERO(fp)) {
+ if (fprf) {
+ fe->fe_cx |= FPSCR_FE;
+ if (sign)
+ fe->fe_cx |= FPSCR_C;
+ }
return (sign);
+ }
/*
* Normals (including subnormals). Drop all the fraction bits
@@ -386,8 +399,13 @@
if ((exp = fp->fp_exp + SNG_EXP_BIAS) <= 0) { /* subnormal */
/* -NG for g,r; -SNG_FRACBITS-exp for fraction */
(void) fpu_shr(fp, FP_NMANT - FP_NG - SNG_FRACBITS - exp);
- if (round(fe, fp) && fp->fp_mant[3] == SNG_EXP(1))
+ if (round(fe, fp) && fp->fp_mant[3] == SNG_EXP(1)) {
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign);
return (sign | SNG_EXP(1) | 0);
+ }
+ if (fprf)
+ fe->fe_cx |= FPSCR_C | FPRF_SIGN(sign);
if ((fe->fe_cx & FPSCR_FI) ||
(fe->fe_fpscr & FPSCR_UX))
fe->fe_cx |= FPSCR_UX;
@@ -403,10 +421,17 @@
exp++;
if (exp >= SNG_EXP_INFNAN) {
/* overflow to inf or to max single */
- if (toinf(fe, sign))
+ if (toinf(fe, sign)) {
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign) | FPSCR_FU;
return (sign | SNG_EXP(SNG_EXP_INFNAN));
+ }
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign);
return (sign | SNG_EXP(SNG_EXP_INFNAN - 1) | SNG_MASK);
}
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign);
done:
/* phew, made it */
return (sign | SNG_EXP(exp) | (fp->fp_mant[3] & SNG_MASK));
@@ -419,7 +444,7 @@
* This code mimics fpu_ftos; see it for comments.
*/
static u_int
-fpu_ftod(struct fpemu *fe, struct fpn *fp, u_int *res)
+fpu_ftod(struct fpemu *fe, struct fpn *fp, u_int *res, bool fprf)
{
u_int sign = fp->fp_sign << 31;
int exp;
@@ -428,15 +453,24 @@
#define DBL_MASK (DBL_EXP(1) - 1)
if (ISNAN(fp)) {
+ if (fprf)
+ fe->fe_cx |= FPSCR_C | FPSCR_FU;
(void) fpu_shr(fp, FP_NMANT - 1 - DBL_FRACBITS);
exp = DBL_EXP_INFNAN;
goto done;
}
if (ISINF(fp)) {
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign) | FPSCR_FU;
sign |= DBL_EXP(DBL_EXP_INFNAN);
goto zero;
}
if (ISZERO(fp)) {
+ if (fprf) {
+ fe->fe_cx |= FPSCR_FE;
+ if (sign)
+ fe->fe_cx |= FPSCR_C;
+ }
zero: res[1] = 0;
return (sign);
}
@@ -444,9 +478,13 @@
if ((exp = fp->fp_exp + DBL_EXP_BIAS) <= 0) {
(void) fpu_shr(fp, FP_NMANT - FP_NG - DBL_FRACBITS - exp);
if (round(fe, fp) && fp->fp_mant[2] == DBL_EXP(1)) {
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign);
res[1] = 0;
return (sign | DBL_EXP(1) | 0);
}
+ if (fprf)
+ fe->fe_cx |= FPSCR_C | FPRF_SIGN(sign);
if ((fe->fe_cx & FPSCR_FI) ||
(fe->fe_fpscr & FPSCR_UX))
fe->fe_cx |= FPSCR_UX;
@@ -459,12 +497,18 @@
if (exp >= DBL_EXP_INFNAN) {
fe->fe_cx |= FPSCR_OX;
if (toinf(fe, sign)) {
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign) | FPSCR_FU;
res[1] = 0;
return (sign | DBL_EXP(DBL_EXP_INFNAN) | 0);
}
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign);
res[1] = ~0;
return (sign | DBL_EXP(DBL_EXP_INFNAN) | DBL_MASK);
}
+ if (fprf)
+ fe->fe_cx |= FPRF_SIGN(sign);
done:
res[1] = fp->fp_mant[3];
return (sign | DBL_EXP(exp) | (fp->fp_mant[2] & DBL_MASK));
@@ -477,22 +521,26 @@
fpu_implode(struct fpemu *fe, struct fpn *fp, int type, u_int *space)
{
int rn;
+ bool fprf;
if (type & FTYPE_RD_RZ)
rn = FSR_RD_RZ;
else
rn = fe->fe_fpscr & FPSCR_RN;
- type &= ~FTYPE_RD_MASK;
+ fprf = type & FTYPE_FPRF;
+ type &= ~FTYPE_FLAG_MASK;
switch (type) {
case FTYPE_LNG:
+ /* FPRF is undefined. */
*(uint64_t *)space = fpu_ftox(fe, fp, rn);
DPRINTF(FPE_REG, ("fpu_implode: long %x %x\n",
space[0], space[1]));
break;
case FTYPE_INT:
+ /* FPRF is undefined. */
space[0] = 0;
space[1] = fpu_ftoi(fe, fp, rn);
DPRINTF(FPE_REG, ("fpu_implode: int %x\n",
@@ -500,13 +548,13 @@
break;
case FTYPE_SNG:
- space[0] = fpu_ftos(fe, fp);
+ space[0] = fpu_ftos(fe, fp, fprf);
DPRINTF(FPE_REG, ("fpu_implode: single %x\n",
space[0]));
break;
case FTYPE_DBL:
- space[0] = fpu_ftod(fe, fp, space);
+ space[0] = fpu_ftod(fe, fp, space, fprf);
DPRINTF(FPE_REG, ("fpu_implode: double %x %x\n",
space[0], space[1]));
break; break;
Home |
Main Index |
Thread Index |
Old Index