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 PR port-powerpc/51368: powerpc FPU emul...



details:   https://anonhg.NetBSD.org/src/rev/55bcb9f0474f
branches:  trunk
changeset: 820074:55bcb9f0474f
user:      rin <rin%NetBSD.org@localhost>
date:      Wed Dec 28 10:52:30 2016 +0000

description:
PR port-powerpc/51368: powerpc FPU emulation fails for single precision
floating point arithmetic

For single precision instruction, calculate first in double precision,
and then round it. With this fix, single precision arithmetic gets sane
on ibm4xx and booke.

Taken from FreeBSD commit r258250:
  https://svnweb.freebsd.org/base?view=revision&revision=258250

Ok matt and simonb.

diffstat:

 sys/arch/powerpc/fpu/fpu_emu.c |  19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diffs (47 lines):

diff -r 284644ff6a0a -r 55bcb9f0474f sys/arch/powerpc/fpu/fpu_emu.c
--- a/sys/arch/powerpc/fpu/fpu_emu.c    Wed Dec 28 10:30:04 2016 +0000
+++ b/sys/arch/powerpc/fpu/fpu_emu.c    Wed Dec 28 10:52:30 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu_emu.c,v 1.18 2016/12/15 11:32:03 rin Exp $ */
+/*     $NetBSD: fpu_emu.c,v 1.19 2016/12/28 10:52:30 rin Exp $ */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.18 2016/12/15 11:32:03 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.19 2016/12/28 10:52:30 rin Exp $");
 
 #include "opt_ddb.h"
 
@@ -626,9 +626,11 @@
                        rb = instr.i_a.i_frb;
                        rc = instr.i_a.i_frc;
 
-                       type = FTYPE_SNG;
-                       if (instr.i_any.i_opcd & 0x4)
-                               type = FTYPE_DBL;
+                       /*
+                        * All arithmetic operations work on registers, which
+                        * are stored as doubles.
+                        */
+                       type = FTYPE_DBL;
                        switch ((unsigned int)instr.i_a.i_xo) {
                        case    OPC59_FDIVS:
                                FPU_EMU_EVCNT_INCR(fdiv);
@@ -745,6 +747,13 @@
                                return (NOTFPU);
                                break;
                        }
+
+                       /* If the instruction was single precision, round */
+                       if (!(instr.i_any.i_opcd & 0x4)) {
+                               fpu_implode(fe, fp, FTYPE_SNG, 
+                                       (u_int *)&fs->fpreg[rt]);
+                               fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
+                       }
                }
        } else {
                return (NOTFPU);



Home | Main Index | Thread Index | Old Index