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