OBE C Compiler - Integer Division Error

Written: DW - Apr 9, 1997

The National Semiconductor C Version 4.42 compiler for our NS32016 microprocessor 
aboard the LEB does not always produce code to divide negative integers correctly.

This line of C code produces incorrect results:

*p = ( (*p>0) ? (*p+d) : (*p-d))/scale;

If (*p+d) is positive all is well but if (*p-d) is negative it always treats 
the signed int as an unsigned int!  Examining the assembler code showed the mistake.  

Example:   *p = 0, scale = 10, d = 4 
            Then *p = -4/10 should be zero in integer arithmetic.  

Instead the compiler produces code that does the following :

-4 = 0xfffffffc
10 = 0xa

0xfffffffc / 0xa = 0x19999999 = 429496729 (decimal)

Thus the National Semiconductor answer is -4/10 =  429496729 

There is no hope of getting a compiler fix.

---------- begin Include ----------------

National Semiconductor
Customer Response Group
(800) 272-9959

Hello,

In response to your request:

This device was obsoleted a number of years ago. We have no information 
available to us on this device and will not be able to help you resolve your 
issues.

Please feel free to call our Customer Response Group at (800) 272-9959  
if you have additional questions or requests.                           
                                                                        
Regards,                                                                
                                                                        
support@nsc.com    

---------- end Include ----------------
Here is the program div.c  :

#include 
 
main()
{ int a = -4, b = 10;
printf("0x%x/0x%x = %d\n",a,b,a/b);
}


Here is the output of div (compiled with gcc) on my Sun:

wang@ares 15 : div
0xfffffffc/0xa = 0

Here is the workaround:

int divide()
{ int a = -4, b = 10;
  int temp,temp1,temp2;
  if(a < 0) temp = -a
  else temp = a;
  if(b < 0) temp1 = -b
  else temp1 = b;
  temp2 = temp/temp1;
  if((temp < 0 && temp1 < 0) || (temp >= 0 && temp1 >= 0)) return temp2;
  else return -temp2;
}