Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Aug 2003 23:24:46 +0200 (CEST)
From:      Mark Kettenis <kettenis@gnu.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   sparc64/55773: Conversion from long to long double is broken
Message-ID:  <200308192124.h7JLOknL002339@elgar.kettenis.dyndns.org>
Resent-Message-ID: <200308200941.h7K9fqFE090746@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         55773
>Category:       sparc64
>Synopsis:       Conversion from long to long double is broken
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-sparc64
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 20 02:41:50 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Mark Kettenis
>Release:        FreeBSD 5.1-CURRENT sparc64
>Organization:
>Environment:
System: FreeBSD panther.freebsd.org 5.1-CURRENT FreeBSD 5.1-CURRENT #166: Fri Aug 15 11:44:38 PDT 2003     root@panther.freebsd.org:/s/src/sys/sparc64/compile/PANTHER  sparc64

	
>Description:

Conversion of `long' and `unsigned long' to `long double' are broken
on FreeBSD/sparc64.  GCC generates the right code AFAICT, but the
implementation of _Qp_xtoq() and _Qp_uxtoq() in
/src/lib/libc/sparc64/fpu/fpu_qp.c seem to be broken.  Every value
that has bit 32 set will be negative when converted to a `long
double'.

	
>How-To-Repeat:

The following test program exhibits the behaviour:

#include <stdio.h>

unsigned long mant_long = 0x80000000;

int
main (void)
{
  long double mant = mant_long;
  printf ("%lu\n", mant_long);
  printf ("%Lf\n", mant);
  return 0;
}

which should print

2147483648
2147483648.000000

but will print

2147483648
-2147483648.000000

	
>Fix:

Looking at the code in /usr/src/lib/libc/sparc64/fpu/fpu_qp.c (I'm
looking at revision 1.3), it seems that the _QP_TTOQ() macro only
handles 32-bit signed integers since on line 63 of that file we have:

	fe.fe_f1.fp_sign = a[0] >> 31;

I think that this line should be

	fe.fe_f1.fp_sign = a[0] >> 63;

for `long' (_Qp_xtoq) and that the line should be completely absent
for `unsigned' (_Qp_uitoq) and `unsigned long' (_Qp_uxtoq).  Some
not-too-thorough testing seems to indicate that's right.
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308192124.h7JLOknL002339>