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