powerpc FPU emulation fails for single precision arithmetic (Was: kernel panic on ibm4xx-based powerpc box with DDB)
Rin Okuyama <[email protected]> Wed, 28 Dec 2016 18:54:32 +0900
| Newsgroups | gmane.os.netbsd.ports.powerpc,gmane.os.netbsd.devel.kernel |
|---|---|
| Message-ID | <[email protected]> |
On 2016/12/28 18:27, Matt Thomas wrote: > >> On Dec 27, 2016, at 11:59 PM, Rin Okuyama <[email protected]> wrote: >> >> Thank you for your kind explanation. I'm starting to understand. >> I will read again the reference manual from this point of view. >> So, could I commit the patch? > > Go commit it. > Thanks, I committed it! By the way, I'd also like to fix port-powerpc/51368: http://gnats.netbsd.org/51368 FPU emulation for ppc gives wrong results for single precision arithmetic. As described in the PR, I found the fix from FreeBSD: ==== https://svnweb.freebsd.org/base?view=revision&revision=258250 Make single precision floating point arithmetic actually work -- I think it never did -- and fix an obvious missing line. Floating point emulation on Book-E still needs some work but this gets it basically functional on soft-FPU systems (hard FPU for Book-E is not yet implemented). MFC after: 1 week ==== With this fix, single precision calculations get sane on ibm4xx and booke as far as I checked. Thanks, Rin ==== --- src/sys/arch/powerpc/fpu/fpu_emu.c.orig 2016-07-27 10:04:00.737524067 +0900 +++ src/sys/arch/powerpc/fpu/fpu_emu.c 2016-07-27 10:03:44.803486129 +0900 @@ -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); --- src/sys/arch/powerpc/fpu/fpu_explode.c.orig 2016-07-27 10:00:01.060507066 +0900 +++ src/sys/arch/powerpc/fpu/fpu_explode.c 2016-07-27 10:00:12.431852649 +0900 @@ -235,6 +235,7 @@ s = fpu_dtof(fp, s, space[1]); break; + default: panic("fpu_explode"); panic("fpu_explode: invalid type %d", type); }