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