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