Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1126 savelij 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
}