Subject: port-i386/11914: div(3) and ldiv(3) are broken on i386
To: None <gnats-bugs@gnats.netbsd.org>
From: None <lukem@wasabisystems.com>
List: netbsd-bugs
Date: 01/07/2001 19:49:20
>Number:         11914
>Category:       port-i386
>Synopsis:       div(3) and ldiv(3) return incorrect results on i386
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    port-i386-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 07 19:49:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Luke Mewburn
>Release:        1.5 (and -current)
>Organization:
Luke Mewburn  <lukem@wasabisystems.com>  http://www.wasabisystems.com
Luke Mewburn     <lukem@netbsd.org>      http://www.netbsd.org
Wasabi Systems - providing NetBSD sales, support and service.
>Environment:
System: NetBSD argo.akimbo.com.au 1.5_BETA2 NetBSD 1.5_BETA2 (ARGO) #0: Thu Nov 16 19:55:34 EST 2000 lukem@argo.akimbo.com.au:/z/src/netbsd-1-5/src/sys/arch/i386/compile/ARGO i386

>Description:
	ldiv(3) doesn't return the correct results. from observation, i'd
	say it's just returning garbage back on the stack.  a quick test
	shows div(3) is borken too.

	it's just the assembly versions in libc/arch/i386/stdlibc/*div.S
	which seem to be at fault.

	i noticed this whilst debugging why the `adnshost' program in
	the `adns-1.0' asynchronous dns package wasn't working.


>How-To-Repeat:
	try and use ldiv or div. notice they're knackered.
	i've attached a small test program.

======
#include <stdio.h>
#include <stdlib.h>

#ifdef USE_LDIV
#define	FUNC	ldiv
#define	IN_T	long
#define	RET_T	ldiv_t
#define FMT_T	"%ld"
#else
#define	FUNC	div
#define	IN_T	int
#define	RET_T	div_t
#define FMT_T	"%d"
#endif

int
main(int argc, char *argv[])
{
	IN_T	val;
	RET_T	dr;

	val = 1999236;
	dr = FUNC(val, 1000000);
	printf("in " FMT_T ", result: quotient " FMT_T " remainder " FMT_T "\n",
	    val, dr.quot, dr.rem);

	return (0);
}
=====

	the following will product wrong results for div & ldiv:
		% gcc test.c
		% ./a.out
		in 1999236, result: quotient 134514686 remainder 134519216

		% gcc -DUSE_LDIV test.c
		% ./a.out
		in 1999236, result: quotient 134514686 remainder 134519216

	compare against using the C versions:
		% gcc test.c /usr/src/lib/libc/stdlib/div.c
		% ./a.out
		in 1999236, result: quotient 1 remainder 999236

		% gcc -DUSE_LDIV test.c /usr/src/lib/libc/stdlib/ldiv.c
		% ./a.out
		in 1999236, result: quotient 1 remainder 999236


>Fix:
	don't use the assembly versions; div & ldiv aren't that
	commonly used that the effort of fixing and maintaining the
	assembly versions is worth the effort (IMHO).

	if we decide that not supporting the assembly versions is TRT,
	then we could probably remove support from
	libc/arch/*/stdlib/Makefile.inc for building div.o and ldiv.o
	and move it back to libc/stdlib/Makefile.inc, since the i386
	is the only port that provides assembly versions of these
	anyway.

	i'm happy to commit a fix to ditch the assembly stuff in
	favour of the C versions.
>Release-Note:
>Audit-Trail:
>Unformatted: