www.delorie.com/djgpp/bugs/show.cgi   search  
Bug 000301

When Created: 08/23/1999 18:00:21
Against DJGPP version: 2.02
By whom: bhoyt@voyager.co.nz
Abstract: sqrt hangs in emu387 on a 486SX
A simple test program shows the bug on a 486SX:

/* Test for emu387 sqrt bug */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main(int argc, char **argv) {
    double n, sqrn;
    if (argc == 0) {
        printf("No argument\n");
        return 1;
    }
    n = atoi(argv[1]);
    sqrn = sqrt(n);
    printf("Square root of %G = %G\n", n, sqrn);
    return 0;
}

This program works fine on my machine with an FPU as follows:

c:\> sqrt 2 
Square root of 2 = 1.41421

But on my old laptop, which is where I want to use it, the program hangs
and I have to break out with Ctrl-Break.

I searched the archives but found no solution.

Bruce

Solution added: 08/29/1999 10:00:57
By whom: eliz@is.elta.co.il
This is a known bug in all versions of the emulator, up to and
including v2.02: any operation that uses FP addition or subtraction
instructions might fail for some specific arguments.

I tried to run the test program with emu387 from the alpha release
of DJGPP v2.03, where the bug is fixed, and the program runs without
any problems.  So it seems that this will be fixed in v2.03.

If you have the library sources (djlsr202.zip), then you can apply
the following patch and rebuild:

*** src/libemu/src/emu387.c~1   Tue Jun  8 13:36:22 1999                        
--- src/libemu/src/emu387.cc    Wed Jun  9 19:06:00 1999                        
*************** static int compare(reg& a, reg& b)                              
*** 220,227 ****                                                                
      b.exp--;                                                                  
    }                                                                           
    int diff = a.exp - b.exp;                                                   
!   if (diff == 0) diff = a.sigh - b.sigh;                                      
!   if (diff == 0) diff = a.sigl - b.sigl;                                      
    if (a.sign == SIGN_NEG)                                                     
      diff = -diff;                                                             
    if (diff > 0) return COMP_A_GT_B;                                           
--- 220,227 ----                                                                
      b.exp--;                                                                  
    }                                                                           
    int diff = a.exp - b.exp;                                                   
!   if (diff == 0) diff = a.sigh > b.sigh ? 1 : (a.sigh < b.sigh ? -1 : 0);     
!   if (diff == 0) diff = a.sigl > b.sigl ? 1 : (a.sigl < b.sigl ? -1 : 0);     
    if (a.sign == SIGN_NEG)                                                     
      diff = -diff;                                                             
    if (diff > 0) return COMP_A_GT_B;                                           
*************** static void r_uadd(reg& a, reg& b, reg&                         
*** 457,464 ****                                                                
  {                                                                             
    reg t;                                                                      
    int dif = a.exp - b.exp;                                                    
!   if (!dif) dif = a.sigh - b.sigh;                                            
!   if (!dif) dif = a.sigl - b.sigl;                                            
    if (dif > 0)                                                                
    {                                                                           
      s = a;                                                                    
--- 457,464 ----                                                                
  {                                                                             
    reg t;                                                                      
    int dif = a.exp - b.exp;                                                    
!   if (!dif) dif = a.sigh > b.sigh ? 1 : (a.sigh < b.sigh ? -1 : 0);           
!   if (!dif) dif = a.sigl > b.sigl ? 1 : (a.sigl < b.sigl ? -1 : 0);           
    if (dif > 0)                                                                
    {                                                                           
      s = a;                                                                    
*************** static void r_sub(reg& a, reg& b, reg& d                        
*** 583,591 ****                                                                
    int mdif;                                                                   
    mdif = a.exp - b.exp;                                                       
    if (!mdif)                                                                  
!     mdif = a.sigh - b.sigh;                                                   
    if (!mdif)                                                                  
!     mdif = a.sigl - b.sigl;                                                   
                                                                                
    switch (a.sign*2 + b.sign)                                                  
    {                                                                           
--- 583,591 ----                                                                
    int mdif;                                                                   
    mdif = a.exp - b.exp;                                                       
    if (!mdif)                                                                  
!     mdif = a.sigh > b.sigh ? 1 : (a.sigh < b.sigh ? -1 : 0);                  
    if (!mdif)                                                                  
!     mdif = a.sigl > b.sigl ? 1 : (a.sigl < b.sigl ? -1 : 0);                  
                                                                                
    switch (a.sign*2 + b.sign)                                                  
    {

Fixed in version on 08/29/1999 10:00:40
By whom: eliz@is.elta.co.il



  webmaster     delorie software   privacy  
  Copyright © 2010   by DJ Delorie     Updated Jul 2010