Subject: port-sgimips/36251: Support for denormalized 32-bit floats broken on sgimips
To: None <port-sgimips-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: Henrik Grubbstrom <grubba@grubba.org>
List: netbsd-bugs
Date: 04/30/2007 21:20:00
>Number:         36251
>Category:       port-sgimips
>Synopsis:       The emulation code for cvt.d.s seems broken for denormalized values.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    port-sgimips-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Apr 30 21:20:00 +0000 2007
>Originator:     Henrik Grubbstrom
>Release:        NetBSD 3.1
>Organization:

>Environment:


System: NetBSD shinon.grubba.org 3.1 NetBSD 3.1 (GENERIC32_IP3x) #0: Tue Oct 31 08:26:30 UTC 2006 builds@b1.netbsd.org:/home/builds/ab/netbsd-3-1-RELEASE/sgimips/200610302053Z-obj/home/builds/ab/netbsd-3-1-RELEASE/src/sys/arch/sgimips/compile/GENERIC32_IP3x sgimips
Architecture: mipseb
Machine: sgimips
>Description:

   The emulation of the opcode cvt.d.s doesn't handle denormalized
   values correctly. Eg the value (float)pow(2.0, -128) is converted
   to the value pow(2.0, -125).

>How-To-Repeat:

Test program:

#include <stdio.h>
#include <math.h>

int main(int argc, char **argv)
{
   float f = (float)pow(2.0, -128.0);
   double d = f;
   float ff = (float)d;
   double dd = ff;
   int i;

   if (f == ff) return 0;
   fprintf(stderr, "f: ");
   for (i=0; i < sizeof(f); i++)
     fprintf(stderr, "%02x ", ((unsigned char *)&f)[i]);
   fprintf(stderr, "\nd: ");
   for (i=0; i < sizeof(d); i++)
     fprintf(stderr, "%02x ", ((unsigned char *)&d)[i]);
   fprintf(stderr, "\nff: ");
   for (i=0; i < sizeof(ff); i++)
     fprintf(stderr, "%02x ", ((unsigned char *)&ff)[i]);
   fprintf(stderr, "\ndd: ");
   for (i=0; i < sizeof(dd); i++)
     fprintf(stderr, "%02x ", ((unsigned char *)&dd)[i]);
   fprintf(stderr, "\n");
   return 1;
}

$ gcc bug.c -o bug -lm
$ ./bug 
f: 00 20 00 00 
d: 38 20 00 00 00 00 00 00 
ff: 01 00 00 00 
dd: 38 20 00 00 00 00 00 00

The expected value for d is:

   37 f0 00 00 00 00 00 00

>Fix:

   I believe the problem lies in sys/arch/mips/fp.S:cvt_d_s or in the renorm_*
   function it uses.

>Unformatted: