Subject: lib/1005: error in unsigned long long multiplication (libc/quad/muldi3.c)
To: None <gnats-admin@sun-lamp.cs.berkeley.edu>
From: None <jarle@idt.unit.no>
List: netbsd-bugs
Date: 04/29/1995 14:50:05
>Number:         1005
>Category:       lib
>Synopsis:       error in unsigned long long multiplication (libc/quad/muldi3.c)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Apr 29 14:50:03 1995
>Originator:     Jarle Greipsland
>Organization:
Department of Tautological Pleonasms and Superfluous Redundancies Department
>Release:        1.0A 25th April 1995
>Environment:
	
System: NetBSD darling.idt.unit.no 1.0A NetBSD 1.0A (DARLING) #17: Wed Apr 26 13:08:40 MET DST 1995 jarle@darling.idt.unit.no:/usr/src/sys/arch/i386/compile/DARLING i386


>Description:
	Multiplying two unsigned long long variables sometimes yields a
wrong result!  It seems that values in the range 0xffffffff-0x80000000
expose the error.  This bug does not exist in 1.0 but has been introduced
at some point after the release of 1.0.  It seems that some macros in
quad.h (HHALF, LHALF and LHUP) have been changed in this timeframe, and that
these changes cause gcc to emit sarl instructions instead of shrl.  I have
only tested this on an i486 machine, so endianness might also play a role.

>How-To-Repeat:
Small program.  Compile and run.

Correct result is (NetBSD-1.0):
(quad) x=ffffffff, y=2, z=1fffffffe
(little) x=0:ffffffff, y=0:2, z=1:fffffffe

Wrong result is (NetBSD-current):
(quad) x=ffffffff, y=2, z=fffffffffffffffe
(little) x=0:ffffffff, y=0:2, z=ffffffff:fffffffe

#include <sys/types.h>
#include <stdio.h>

union myquad {
	u_int64_t q;
	u_int32_t i[2];
};

main()
{
	union myquad x, y, z;

	x.q = 0x80000000;
	y.q = 0x2;
	z.q = x.q * y.q;	/* Should be 0x100000000 */
	printf("(quad) x=%qx, y=%qx, z=%qx\n", x.q, y.q, z.q);
#if (BYTE_ORDER==LITTLE_ENDIAN)
	printf("(little) x=%lx:%lx, y=%lx:%lx, z=%lx:%lx\n", 
	       x.i[1], x.i[0], y.i[1], y.i[0], z.i[1], z.i[0]);
#else
	printf("(big) x=%lx:%lx, y=%lx:%lx, z=%lx:%lx\n", 
	       x.i[0], x.i[1], y.i[0], y.i[1], z.i[0], z.i[1]);
#endif

}

	
>Fix:
Probably change some macros, but since the macros seem heavily used
throughout the quad stuff I think someone more familiar with it should look
into it :-)
	
>Audit-Trail:
>Unformatted: