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