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.
This commit is contained in:
rin 2016-12-28 10:52:30 +00:00
parent 0b5b7fff16
commit 011775c944
1 changed files with 14 additions and 5 deletions

View File

@ -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 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
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 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
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);