1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef USED_AS_INCLUDE
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "../pub/libvex_basictypes.h"
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdio.h>
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <malloc.h>
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdlib.h>
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <string.h>
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <assert.h>
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Test program for developing code for conversions between
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   x87 64-bit and 80-bit floats.
14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   80-bit format exists only for x86/x86-64, and so the routines
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   hardwire it as little-endian.  The 64-bit format (IEEE double)
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   could exist on any platform, little or big-endian and so we
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   have to take that into account.  IOW, these routines have to
19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   work correctly when compiled on both big- and little-endian
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   targets, but the 80-bit images only ever have to exist in
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   little-endian format.
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void show_f80 ( UChar* );
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void show_f64 ( UChar* );
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline
27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt read_bit_array ( UChar* arr, UInt n )
28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar c = arr[n >> 3];
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   c >>= (n&7);
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return c & 1;
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid write_bit_array ( UChar* arr, UInt n, UInt b )
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar c = arr[n >> 3];
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   c &= ~(1 << (n&7));
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   c |= ((b&1) << (n&7));
40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   arr[n >> 3] = c;
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void convert_f80le_to_f64le_HW ( /*IN*/UChar* f80, /*OUT*/UChar* f64 )
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  asm volatile ("ffree %%st(7); fldt (%0); fstpl (%1)"
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                :
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                : "r" (&f80[0]), "r" (&f64[0])
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                : "memory" );
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void convert_f64le_to_f80le_HW ( /*IN*/UChar* f64, /*OUT*/UChar* f80 )
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  asm volatile ("ffree %%st(7); fldl (%0); fstpt (%1)"
55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                :
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                : "r" (&f64[0]), "r" (&f80[0])
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                : "memory" );
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* ndef USED_AS_INCLUDE */
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* 80 and 64-bit floating point formats:
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   80-bit:
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  0       0-------0      zero
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  0       0X------X      denormals
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  1-7FFE  1X------X      normals (all normals have leading 1)
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  7FFF    10------0      infinity
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  7FFF    10X-----X      snan
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  7FFF    11X-----X      qnan
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   S is the sign bit.  For runs X----X, at least one of the Xs must be
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   nonzero.  Exponent is 15 bits, fractional part is 63 bits, and
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   there is an explicitly represented leading 1, and a sign bit,
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   giving 80 in total.
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   64-bit avoids the confusion of an explicitly represented leading 1
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   and so is simpler:
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  0      0------0   zero
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  0      X------X   denormals
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  1-7FE  any        normals
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  7FF    0------0   infinity
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  7FF    0X-----X   snan
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    S  7FF    1X-----X   qnan
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Exponent is 11 bits, fractional part is 52 bits, and there is a
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sign bit, giving 64 in total.
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Convert a IEEE754 double (64-bit) into an x87 extended double
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (80-bit), mimicing the hardware fairly closely.  Both numbers are
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stored little-endian.  Limitations, all of which could be fixed,
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   given some level of hassle:
98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   * Identity of NaNs is not preserved.
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   See comments in the code for more details.
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void convert_f64le_to_f80le ( /*IN*/UChar* f64, /*OUT*/UChar* f80 )
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool  mantissaIsZero;
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int   bexp, i, j, shift;
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar sign;
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sign = toUChar( (f64[7] >> 7) & 1 );
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bexp &= 0x7FF;
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mantissaIsZero = False;
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp == 0 || bexp == 0x7FF) {
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* We'll need to know whether or not the mantissa (bits 51:0) is
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         all zeroes in order to handle these cases.  So figure it
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         out. */
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mantissaIsZero
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         = toBool(
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              (f64[6] & 0x0F) == 0
121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              && f64[5] == 0 && f64[4] == 0 && f64[3] == 0
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              && f64[2] == 0 && f64[1] == 0 && f64[0] == 0
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           );
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If the exponent is zero, either we have a zero or a denormal.
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Produce a zero.  This is a hack in that it forces denormals to
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      zero.  Could do better. */
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp == 0) {
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f80[9] = toUChar( sign << 7 );
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f80[8] = f80[7] = f80[6] = f80[5] = f80[4]
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             = f80[3] = f80[2] = f80[1] = f80[0] = 0;
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (mantissaIsZero)
135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* It really is zero, so that's all we can do. */
136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* There is at least one 1-bit in the mantissa.  So it's a
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         potentially denormalised double -- but we can produce a
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         normalised long double.  Count the leading zeroes in the
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mantissa so as to decide how much to bump the exponent down
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         by.  Note, this is SLOW. */
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      shift = 0;
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 51; i >= 0; i--) {
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        if (read_bit_array(f64, i))
146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           break;
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        shift++;
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* and copy into place as many bits as we can get our hands on. */
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      j = 63;
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 51 - shift; i >= 0; i--) {
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         write_bit_array( f80, j,
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     	 read_bit_array( f64, i ) );
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         j--;
156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Set the exponent appropriately, and we're done. */
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      bexp -= shift;
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      bexp += (16383 - 1023);
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f80[9] = toUChar( (sign << 7) | ((bexp >> 8) & 0xFF) );
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f80[8] = toUChar( bexp & 0xFF );
163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If the exponent is 7FF, this is either an Infinity, a SNaN or
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      QNaN, as determined by examining bits 51:0, thus:
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          0  ... 0    Inf
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          0X ... X    SNaN
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          1X ... X    QNaN
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      where at least one of the Xs is not zero.
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp == 0x7FF) {
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (mantissaIsZero) {
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Produce an appropriately signed infinity:
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S 1--1 (15)  1  0--0 (63)
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[9] = toUChar( (sign << 7) | 0x7F );
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[8] = 0xFF;
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[7] = 0x80;
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[6] = f80[5] = f80[4] = f80[3]
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                = f80[2] = f80[1] = f80[0] = 0;
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* So it's either a QNaN or SNaN.  Distinguish by considering
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         bit 51.  Note, this destroys all the trailing bits
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (identity?) of the NaN.  IEEE754 doesn't require preserving
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         these (it only requires that there be one QNaN value and one
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         SNaN value), but x87 does seem to have some ability to
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         preserve them.  Anyway, here, the NaN's identity is
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         destroyed.  Could be improved. */
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f64[6] & 8) {
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* QNaN.  Make a QNaN:
194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S 1--1 (15)  1  1--1 (63)
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[9] = toUChar( (sign << 7) | 0x7F );
197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[8] = 0xFF;
198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[7] = 0xFF;
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[6] = f80[5] = f80[4] = f80[3]
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                = f80[2] = f80[1] = f80[0] = 0xFF;
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* SNaN.  Make a SNaN:
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S 1--1 (15)  0  1--1 (63)
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[9] = toUChar( (sign << 7) | 0x7F );
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[8] = 0xFF;
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[7] = 0x7F;
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f80[6] = f80[5] = f80[4] = f80[3]
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                = f80[2] = f80[1] = f80[0] = 0xFF;
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* It's not a zero, denormal, infinity or nan.  So it must be a
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      normalised number.  Rebias the exponent and build the new
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      number.  */
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bexp += (16383 - 1023);
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[9] = toUChar( (sign << 7) | ((bexp >> 8) & 0xFF) );
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[8] = toUChar( bexp & 0xFF );
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[7] = toUChar( (1 << 7) | ((f64[6] << 3) & 0x78)
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              | ((f64[5] >> 5) & 7) );
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[6] = toUChar( ((f64[5] << 3) & 0xF8) | ((f64[4] >> 5) & 7) );
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[5] = toUChar( ((f64[4] << 3) & 0xF8) | ((f64[3] >> 5) & 7) );
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[4] = toUChar( ((f64[3] << 3) & 0xF8) | ((f64[2] >> 5) & 7) );
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[3] = toUChar( ((f64[2] << 3) & 0xF8) | ((f64[1] >> 5) & 7) );
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[2] = toUChar( ((f64[1] << 3) & 0xF8) | ((f64[0] >> 5) & 7) );
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[1] = toUChar( ((f64[0] << 3) & 0xF8) );
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f80[0] = toUChar( 0 );
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Convert a x87 extended double (80-bit) into an IEEE 754 double
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (64-bit), mimicking the hardware fairly closely.  Both numbers are
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stored little-endian.  Limitations, both of which could be fixed,
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   given some level of hassle:
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   * Rounding following truncation could be a bit better.
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   * Identity of NaNs is not preserved.
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   See comments in the code for more details.
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 )
245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool  isInf;
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int   bexp, i, j;
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar sign;
249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sign = toUChar((f80[9] >> 7) & 1);
251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bexp = (((UInt)f80[9]) << 8) | (UInt)f80[8];
252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bexp &= 0x7FFF;
253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If the exponent is zero, either we have a zero or a denormal.
255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      But an extended precision denormal becomes a double precision
256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      zero, so in either case, just produce the appropriately signed
257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      zero. */
258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp == 0) {
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[7] = toUChar(sign << 7);
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If the exponent is 7FFF, this is either an Infinity, a SNaN or
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      QNaN, as determined by examining bits 62:0, thus:
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          0  ... 0    Inf
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          0X ... X    SNaN
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          1X ... X    QNaN
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      where at least one of the Xs is not zero.
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp == 0x7FFF) {
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      isInf = toBool(
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 (f80[7] & 0x7F) == 0
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 && f80[6] == 0 && f80[5] == 0 && f80[4] == 0
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 && f80[3] == 0 && f80[2] == 0 && f80[1] == 0
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 && f80[0] == 0
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              );
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (isInf) {
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (0 == (f80[7] & 0x80))
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto wierd_NaN;
281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Produce an appropriately signed infinity:
282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S 1--1 (11)  0--0 (52)
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[7] = toUChar((sign << 7) | 0x7F);
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[6] = 0xF0;
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* So it's either a QNaN or SNaN.  Distinguish by considering
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         bit 62.  Note, this destroys all the trailing bits
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (identity?) of the NaN.  IEEE754 doesn't require preserving
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         these (it only requires that there be one QNaN value and one
293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         SNaN value), but x87 does seem to have some ability to
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         preserve them.  Anyway, here, the NaN's identity is
295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         destroyed.  Could be improved. */
296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f80[8] & 0x40) {
297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* QNaN.  Make a QNaN:
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S 1--1 (11)  1  1--1 (51)
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[7] = toUChar((sign << 7) | 0x7F);
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[6] = 0xFF;
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* SNaN.  Make a SNaN:
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            S 1--1 (11)  0  1--1 (51)
306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[7] = toUChar((sign << 7) | 0x7F);
308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[6] = 0xF7;
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0xFF;
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If it's not a Zero, NaN or Inf, and the integer part (bit 62) is
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      zero, the x87 FPU appears to consider the number denormalised
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      and converts it to a QNaN. */
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0 == (f80[7] & 0x80)) {
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      wierd_NaN:
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Strange hardware QNaN:
320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         S 1--1 (11)  1  0--0 (51)
321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      */
322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* On a PIII, these QNaNs always appear with sign==1.  I have
323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         no idea why. */
324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[7] = (1 /*sign*/ << 7) | 0x7F;
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[6] = 0xF8;
326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* It's not a zero, denormal, infinity or nan.  So it must be a
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      normalised number.  Rebias the exponent and consider. */
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bexp -= (16383 - 1023);
333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp >= 0x7FF) {
334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* It's too big for a double.  Construct an infinity. */
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[7] = toUChar((sign << 7) | 0x7F);
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[6] = 0xF0;
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bexp <= 0) {
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* It's too small for a normalised double.  First construct a
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         zero and then see if it can be improved into a denormal.  */
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[7] = toUChar(sign << 7);
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      f64[6] = f64[5] = f64[4] = f64[3] = f64[2] = f64[1] = f64[0] = 0;
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (bexp < -52)
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Too small even for a denormal. */
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Ok, let's make a denormal.  Note, this is SLOW. */
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Copy bits 63, 62, 61, etc of the src mantissa into the dst,
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         indexes 52+bexp, 51+bexp, etc, until k+bexp < 0. */
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* bexp is in range -52 .. 0 inclusive */
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 63; i >= 0; i--) {
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         j = i - 12 + bexp;
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (j < 0) break;
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* We shouldn't really call vassert from generated code. */
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assert(j >= 0 && j < 52);
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         write_bit_array ( f64,
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           j,
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           read_bit_array ( f80, i ) );
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* and now we might have to round ... */
365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (read_bit_array(f80, 10+1 - bexp) == 1)
366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto do_rounding;
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Ok, it's a normalised number which is representable as a double.
372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Copy the exponent and mantissa into place. */
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 52; i++)
375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      write_bit_array ( f64,
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        i,
377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        read_bit_array ( f80, i+11 ) );
378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[0] = toUChar( (f80[1] >> 3) | (f80[2] << 5) );
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[1] = toUChar( (f80[2] >> 3) | (f80[3] << 5) );
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[2] = toUChar( (f80[3] >> 3) | (f80[4] << 5) );
382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[3] = toUChar( (f80[4] >> 3) | (f80[5] << 5) );
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[4] = toUChar( (f80[5] >> 3) | (f80[6] << 5) );
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[5] = toUChar( (f80[6] >> 3) | (f80[7] << 5) );
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[6] = toUChar( ((bexp << 4) & 0xF0) | ((f80[7] >> 3) & 0x0F) );
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   f64[7] = toUChar( (sign << 7) | ((bexp >> 4) & 0x7F) );
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Now consider any rounding that needs to happen as a result of
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      truncating the mantissa. */
392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (f80[1] & 4) /* read_bit_array(f80, 10) == 1) */ {
393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* If the bottom bits of f80 are "100 0000 0000", then the
395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         infinitely precise value is deemed to be mid-way between the
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         two closest representable values.  Since we're doing
397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         round-to-nearest (the default mode), in that case it is the
398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         bit immediately above which indicates whether we should round
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         upwards or not -- if 0, we don't.  All that is encapsulated
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         in the following simple test. */
401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if ((f80[1] & 0xF) == 4/*0100b*/ && f80[0] == 0)
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      do_rounding:
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Round upwards.  This is a kludge.  Once in every 2^24
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         roundings (statistically) the bottom three bytes are all 0xFF
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         and so we don't round at all.  Could be improved. */
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f64[0] != 0xFF) {
409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[0]++;
410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f64[0] == 0xFF && f64[1] != 0xFF) {
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[0] = 0;
414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[1]++;
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f64[0] == 0xFF && f64[1] == 0xFF && f64[2] != 0xFF) {
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[0] = 0;
419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[1] = 0;
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         f64[2]++;
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* else we don't round, but we should. */
423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef USED_AS_INCLUDE
428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void show_f80 ( UChar* f80 )
432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Int i;
434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  printf("%d ", read_bit_array(f80, 79));
435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  for (i = 78; i >= 64; i--)
437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%d", read_bit_array(f80, i));
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  printf(" %d ", read_bit_array(f80, 63));
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  for (i = 62; i >= 0; i--)
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%d", read_bit_array(f80, i));
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void show_f64le ( UChar* f64 )
446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Int i;
448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  printf("%d     ", read_bit_array(f64, 63));
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  for (i = 62; i >= 52; i--)
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%d", read_bit_array(f64, i));
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  printf("   ");
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  for (i = 51; i >= 0; i--)
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%d", read_bit_array(f64, i));
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Convert f80 to a 64-bit IEEE double using both the hardware and the
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   soft version, and compare the results.  If they differ, print
463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   details and return 1.  If they are identical, return 0.
464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint do_80_to_64_test ( Int test_no, UChar* f80, UChar* f64h, UChar* f64s)
466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Char buf64s[100], buf64h[100];
468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool same;
469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int k;
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   convert_f80le_to_f64le_HW(f80, f64h);
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   convert_f80le_to_f64le(f80, f64s);
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   same = True;
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (k = 0; k < 8; k++) {
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f64s[k] != f64h[k]) {
475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         same = False; break;
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* bitwise identical */
479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (same)
480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sprintf(buf64s, "%.16e", *(double*)f64s);
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sprintf(buf64h, "%.16e", *(double*)f64h);
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Not bitwise identical, but pretty darn close */
486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0 == strcmp(buf64s, buf64h))
487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("\n");
490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("f80:  "); show_f80(f80); printf("\n");
491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("f64h: "); show_f64le(f64h); printf("\n");
492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("f64s: "); show_f64le(f64s); printf("\n");
493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("[test %d]  %.16Le -> (hw %s, sw %s)\n",
495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           test_no, *(long double*)f80,
496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           buf64h, buf64s );
497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    return 1;
499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Convert an IEEE 64-bit double to a x87 extended double (80 bit)
503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   using both the hardware and the soft version, and compare the
504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   results.  If they differ, print details and return 1.  If they are
505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   identical, return 0.
506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint do_64_to_80_test ( Int test_no, UChar* f64, UChar* f80h, UChar* f80s)
508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Char buf80s[100], buf80h[100];
510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool same;
511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int k;
512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   convert_f64le_to_f80le_HW(f64, f80h);
513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   convert_f64le_to_f80le(f64, f80s);
514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   same = True;
515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (k = 0; k < 10; k++) {
516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (f80s[k] != f80h[k]) {
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         same = False; break;
518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* bitwise identical */
521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (same)
522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sprintf(buf80s, "%.20Le", *(long double*)f80s);
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sprintf(buf80h, "%.20Le", *(long double*)f80h);
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Not bitwise identical, but pretty darn close */
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0 == strcmp(buf80s, buf80h))
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return 0;
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("\n");
532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("f64:  "); show_f64le(f64); printf("\n");
533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("f80h: "); show_f80(f80h); printf("\n");
534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("f80s: "); show_f80(f80s); printf("\n");
535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("[test %d]  %.16e -> (hw %s, sw %s)\n",
537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           test_no, *(double*)f64,
538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           buf80h, buf80s );
539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    return 1;
541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid do_80_to_64_tests ( void )
546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt b9,b8,b7,i, j;
548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int fails=0, tests=0;
549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar* f64h = malloc(8);
550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar* f64s = malloc(8);
551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar* f80  = malloc(10);
552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int STEP = 1;
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   srandom(4343);
555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Ten million random bit patterns */
557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 10000000; i++) {
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     tests++;
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     for (j = 0; j < 10; j++)
560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       f80[j] = (random() >> 7) & 255;
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     fails += do_80_to_64_test(tests, f80, f64h, f64s);
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* 2^24 numbers in which the first 24 bits are tested exhaustively
566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      -- this covers the sign, exponent and leading part of the
567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mantissa. */
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (b9 = 0; b9 < 256; b9 += STEP) {
569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (b8 = 0; b8 < 256; b8 += STEP) {
570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         for (b7 = 0; b7 < 256; b7 += STEP) {
571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           tests++;
572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            for (i = 0; i < 10; i++)
573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               f80[i] = 0;
574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            for (i = 0; i < 8; i++)
575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               f64h[i] = f64s[i] = 0;
576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            f80[9] = b9;
577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            f80[8] = b8;
578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            f80[7] = b7;
579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    fails += do_80_to_64_test(tests, f80, f64h, f64s);
581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }}}
582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf("\n80 -> 64:  %d tests, %d fails\n\n", tests, fails);
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid do_64_to_80_tests ( void )
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt b7,b6,b5,i, j;
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int fails=0, tests=0;
591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar* f80h = malloc(10);
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar* f80s = malloc(10);
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar* f64  = malloc(8);
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int STEP = 1;
595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   srandom(2323);
597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Ten million random bit patterns */
599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 10000000; i++) {
600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     tests++;
601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     for (j = 0; j < 8; j++)
602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       f64[j] = (random() >> 13) & 255;
603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     fails += do_64_to_80_test(tests, f64, f80h, f80s);
605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* 2^24 numbers in which the first 24 bits are tested exhaustively
608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      -- this covers the sign, exponent and leading part of the
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mantissa. */
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (b7 = 0; b7 < 256; b7 += STEP) {
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (b6 = 0; b6 < 256; b6 += STEP) {
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         for (b5 = 0; b5 < 256; b5 += STEP) {
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           tests++;
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            for (i = 0; i < 8; i++)
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               f64[i] = 0;
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            for (i = 0; i < 10; i++)
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               f80h[i] = f80s[i] = 0;
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            f64[7] = b7;
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            f64[6] = b6;
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            f64[5] = b5;
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    fails += do_64_to_80_test(tests, f64, f80h, f80s);
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }}}
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf("\n64 -> 80:  %d tests, %d fails\n\n", tests, fails);
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint main ( void )
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   do_80_to_64_tests();
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   do_64_to_80_tests();
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* ndef USED_AS_INCLUDE */
637