Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* ibmfloat.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* IBM Floating Point Format                                                 */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. /*****************************************************************************
  12.  * Includes
  13.  *****************************************************************************/
  14.  
  15. #include "stdinc.h"
  16. #include <math.h>
  17.  
  18. #include "ieeefloat.h"
  19. #include "errmsg.h"
  20. #include "asmerr.h"
  21. #include "ibmfloat.h"
  22.  
  23. /*!------------------------------------------------------------------------
  24.  * \fn     Double2IBMFloat(Word *pDest, double Src, Boolean ToDouble)
  25.  * \brief  convert floating point number to IBM single precision format
  26.  * \param  pDest where to write result (2 words)
  27.  * \param  Src floating point number to store
  28.  * \param  ToDouble convert to double precision (64 instead of 32 bits)?
  29.  * \return True if conversion was successful
  30.  * ------------------------------------------------------------------------ */
  31.  
  32. #define DBG_FLOAT 0
  33.  
  34. Boolean Double2IBMFloat(Word *pDest, double Src, Boolean ToDouble)
  35. {
  36.   Word Sign;
  37.   Integer Exponent;
  38.   LongWord Mantissa, Fraction;
  39.  
  40. #if DBG_FLOAT
  41.   fprintf(stderr, "(0) %lf\n", Src);
  42. #endif
  43.  
  44.   /* (1) Dissect IEEE number */
  45.  
  46.   ieee8_dissect(&Sign, &Exponent, &Mantissa, &Fraction, Src);
  47.  
  48.   /* (2) Convert IEEE 2^n exponent to multiple of four since IBM float exponent is to the base of 16: */
  49.  
  50.   while ((Mantissa & 0x10000000ul) || (Exponent & 3))
  51.   {
  52.     if (Mantissa & 1)
  53.       Fraction |= 0x1000000ul;
  54.     Mantissa >>= 1;
  55.     Fraction >>= 1;
  56.     Exponent++;
  57.   }
  58. #if DBG_FLOAT
  59.   fprintf(stderr, "(expo4) %2d * 0x%08x * 2^%d Fraction 0x%08x\n", Sign ? -1 : 1, Mantissa, Exponent, Fraction);
  60. #endif
  61.  
  62.   /* (3) make base-16 exponent explicit */
  63.  
  64.   Exponent /= 4;
  65. #if DBG_FLOAT
  66.   fprintf(stderr, "(exp16) %2d * 0x%08x * 16^%d Fraction 0x%08x\n", Sign ? -1 : 1, Mantissa, Exponent, Fraction);
  67. #endif
  68.  
  69.   /* (2a) Round-to-the-nearest for single precision: */
  70.  
  71.   if (!ToDouble)
  72.   {
  73.     Boolean RoundUp;
  74.  
  75.     /* Bits 27..4 of mantissa will make it into dest, so the decision bit is bit 3: */
  76.  
  77.     if (Mantissa & 0x8) /* fraction is >= 0.5 */
  78.     {
  79.       if ((Mantissa & 7) || Fraction) /* fraction is > 0.5 -> round up */
  80.         RoundUp = True;
  81.       else /* fraction is 0.5 -> round towards even, i.e. round up if mantissa is odd */
  82.         RoundUp = !!(Mantissa & 0x10);
  83.     }
  84.     else /* fraction is < 0.5 -> round down */
  85.       RoundUp = False;
  86. #if DBG_FLOAT
  87.     fprintf(stderr, "RoundUp %u\n", RoundUp);
  88. #endif
  89.     if (RoundUp)
  90.     {
  91.       Mantissa += 16 - (Mantissa & 15);
  92.       Fraction = 0;
  93.       if (Mantissa & 0x10000000ul)
  94.       {
  95.         Mantissa >>= 4;
  96.         Exponent++;
  97.       }
  98.     }
  99. #if DBG_FLOAT
  100.     fprintf(stderr, "(round) %2d * 0x%08x * 16^%d Fraction 0x%08x\n", Sign ? -1 : 1, Mantissa, Exponent, Fraction);
  101. #endif
  102.   }
  103.  
  104.   /* (3a) Overrange? */
  105.  
  106.   if (Exponent > 63)
  107.   {
  108.     WrError(ErrNum_OverRange);
  109.     return False;
  110.   }
  111.   else
  112.   {
  113.     /* (3b) number that is too small may degenerate to 0: */
  114.  
  115.     while ((Exponent < -64) && Mantissa)
  116.     {
  117.       Exponent++; Mantissa >>= 4;
  118.     }
  119.     if (Exponent < -64)
  120.       Exponent = -64;
  121.  
  122.     /* (3c) add bias to exponent */
  123.  
  124.     Exponent += 64;
  125.  
  126.     /* (3d) store result */
  127.  
  128.     pDest[0] = (Sign << 15) | ((Exponent << 8) & 0x7f00) | ((Mantissa >> 20) & 0xff);
  129.     pDest[1] = (Mantissa >> 4) & 0xffff;
  130.  
  131.     /* IBM format has four mantissa bits more than IEEE double, so the 4 LSBs
  132.        remain zero: */
  133.  
  134.     if (ToDouble)
  135.     {
  136.       pDest[2] = ((Mantissa & 15) << 12) | ((Fraction >> 12) & 0x0fff);
  137.       pDest[3] = (Fraction & 0x0fff) << 4;
  138.     }
  139.     return True;
  140.   }
  141. }
  142.