From nobody@FreeBSD.org  Thu Sep 23 07:26:34 2004
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 8E58516A4CF
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 23 Sep 2004 07:26:34 +0000 (GMT)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 6A0A943D1F
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 23 Sep 2004 07:26:34 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.11/8.12.11) with ESMTP id i8N7QXAE099743
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 23 Sep 2004 07:26:33 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.11/8.12.11/Submit) id i8N7QXTM099742;
	Thu, 23 Sep 2004 07:26:33 GMT
	(envelope-from nobody)
Message-Id: <200409230726.i8N7QXTM099742@www.freebsd.org>
Date: Thu, 23 Sep 2004 07:26:33 GMT
From: Patrick Pelissier <ppelissi@caramail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: LONG_MIN / 1 sends a "Floating exception"
X-Send-Pr-Version: www-2.3

>Number:         72024
>Category:       alpha
>Synopsis:       LONG_MIN / 1 sends a "Floating exception"
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-alpha
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Sep 23 07:30:27 GMT 2004
>Closed-Date:    Wed Dec 08 22:56:46 GMT 2004
>Last-Modified:  Wed Dec 08 22:56:46 GMT 2004
>Originator:     Patrick Pelissier
>Release:        5.2.1
>Organization:
>Environment:
spe149.testdrive.hp.com> uname -a
FreeBSD spe149.testdrive.hp.com 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #0: Tue Feb 24 07:42:14 GMT 2004     root@mithlond.btc.adaptec.com:/usr/obj/usr/src/sys/GENERIC  alpha

>Description:
The following program:

#include <limits.h>
int f(long a, long b);
int main()
{
  return f(LONG_MIN, 1);
}
int f(long a, long b)
{
  return a / b;
}

produces a "Floating exception (core dumped)" on alpha-unknown-freebsd5.2.1
(spe149.testdrive.hp.com) with:
gcc version 3.4.2 and gcc version 3.3.3 [FreeBSD] 20031106.

The test program was compiled without any flags:
spe149.testdrive.hp.com> /tmp/make/bin/gcc test3.c
spe149.testdrive.hp.com> ./a.out
Floating exception (core dumped)
spe149.testdrive.hp.com> /tmp/make/bin/gcc -v
Reading specs from /tmp/make/lib/gcc/alpha-unknown-freebsd5.2.1/3.4.2/specs
Configured with: ./configure --prefix=/tmp/gcc : (reconfigured) ./configure
--prefix=/tmp/gcc : (reconfigured) ./configure --prefix=/tmp/make
--enable-languages=c
Thread model: posix
gcc version 3.4.2

The problem seems to be in the internal function "__divq" which produces the exception.

(See also
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17613 )
 
>How-To-Repeat:
      
>Fix:
      
>Release-Note:
>Audit-Trail:

From: Peter Edwards <peadar@freebsd.org>
To: freebsd-gnats-submit@FreeBSD.org, ppelissi@caramail.com
Cc:  
Subject: Re: alpha/72024: LONG_MIN / 1 sends a "Floating exception"
Date: Sun, 10 Oct 2004 00:03:13 +0100

 This is a multi-part message in MIME format.
 --------------020907060008000208010003
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Ooh a good excuse to look at Alpha assembler. (/me googles for the alpha 
 instruction set.)
 
 (Can someone on the -alpha list tell me if this reasoning is correct, 
 and if I should commit the patch?)
 
 Alpha appears not to have an integer division instruction, so this is 
 implemented by divq(), the source of which is generated from 
 "src/lib/libc/alpha/gen/divrem4"
 
 (For reading the macros when preprocessing as divq, S is true, OP is 
 "div", and WORDSIZE is 64)
 
 If I'm reading it correctly, the start of this function decides what 
 sign the result should have, then gets the absolute value of each 
 operand, (search for "subq zero, A, A" and "subq zero, B, B".) Note, for 
 "LONG_MIN", or 0x8000000000000000, 2's compliment subtraction for zero 
 gives back the 0x8000000000000000
 
 The body of the work is done with logical shifts, so everything still 
 works when treating the dividend as an unsigned long.
 
 At the end of the function, the code takes the calculated result, and 
 decides if it needs to negate it:
 
 >         /* Check to see if we should negate it. */
 >         subqv   zero, RESULT, T_0
 >         cmovlbs NEG, T_0, RESULT
 
 
 The "v" here means "trap overflows", which is why we blow up. LONG_MIN 
 is the only value that _can_ blow up here, and you can only reach this 
 case if you start with LONG_MIN / 1, if my reasoning isn't flawed.
 So, I think it's perfectly safe to remove the "v" from the subq 
 instruction. i.e., I think the attached patch is correct.
 
 --------------020907060008000208010003
 Content-Type: text/plain;
  name="divrem.txt"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="divrem.txt"
 
 Index: lib/libc/alpha/gen/divrem.m4
 ===================================================================
 RCS file: /usr/cvs/FreeBSD-CVS/src/lib/libc/alpha/gen/divrem.m4,v
 retrieving revision 1.3
 diff -u -r1.3 divrem.m4
 --- lib/libc/alpha/gen/divrem.m4	10 May 2000 19:04:57 -0000	1.3
 +++ lib/libc/alpha/gen/divrem.m4	9 Oct 2004 22:54:36 -0000
 @@ -172,7 +172,7 @@
  ifelse(S, `true',
  `
  	/* Check to see if we should negate it. */
 -	subqv	zero, RESULT, T_0
 +	subq	zero, RESULT, T_0
  	cmovlbs	NEG, T_0, RESULT
  ')
  
 
 --------------020907060008000208010003--

From: Peter Edwards <peadar@freebsd.org>
To: freebsd-gnats-submit@FreeBSD.org, ppelissi@caramail.com
Cc:  
Subject: Re: alpha/72024: LONG_MIN / 1 sends a "Floating exception"
Date: Sun, 10 Oct 2004 03:12:19 +0100

 Er,
 After realising that this source came from NetBSD, I checked their CVS 
 repo, and found it already fixed there with an equivalent patch.
 
 There's also an equivalent in the kernel: 
 /usr/src/sys/alpha/alpha/divrem.m4. The kernel case might be a security 
 issue if you could find a syscall that would do arbitrary (assuming not 
 by zero!) division of 64-bit values.
State-Changed-From-To: open->closed 
State-Changed-By: peadar 
State-Changed-When: Wed Dec 8 22:55:59 GMT 2004 
State-Changed-Why:  
Fix committed to 6-current and 5-stable 

http://www.freebsd.org/cgi/query-pr.cgi?pr=72024 
>Unformatted:
