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