1 2 /* Test conversions between 64- and 80- bit quiet NaNs. Uses 3 "canonical forms" for qNaNs. It also tests sNaNs but it's not 4 clear what the canonical form of them should be, so the results are 5 pretty much irrelevant. Failure to do this right is the cause 6 of https://bugzilla.mozilla.org/show_bug.cgi?id=738117 7 */ 8 9 #include <assert.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 typedef unsigned char UChar; 15 16 17 void do_64_to_80 ( UChar* dst, UChar* src ) 18 { 19 __asm__ __volatile__( 20 "fldl (%0); fstpt (%1)" 21 : : "r"(src), "r"(dst) : "memory" 22 ); 23 } 24 25 void do_80_to_64 ( UChar* dst, UChar* src ) 26 { 27 __asm__ __volatile__( 28 "fldt (%0); fstpl (%1)" 29 : : "r"(src), "r"(dst) : "memory" 30 ); 31 } 32 33 void print80 ( char* s, UChar* v ) 34 { 35 int i; 36 printf("%s", s); 37 for (i = 9; i >= 0; i--) 38 printf("%02x", (unsigned int)v[i]); 39 printf("\n"); 40 } 41 42 void print64 ( char* s, UChar* v ) 43 { 44 int i; 45 printf("%s", s); 46 for (i = 7; i >= 0; i--) { 47 printf("%02x", (unsigned int)v[i]); 48 } 49 printf("\n"); 50 } 51 52 #if 0 53 void gen_qnan_64 ( UChar* dst ) 54 { 55 56 } 57 #endif 58 59 #define SWAPC(_xx,_yy) { UChar tmp = _xx; _xx = _yy; _yy = tmp; } 60 61 static void rev64 ( UChar* f64 ) 62 { 63 SWAPC( f64[0], f64[7] ); 64 SWAPC( f64[1], f64[6] ); 65 SWAPC( f64[2], f64[5] ); 66 SWAPC( f64[3], f64[4] ); 67 } 68 69 static void rev80 ( UChar* f80 ) 70 { 71 SWAPC( f80[0], f80[9] ); 72 SWAPC( f80[1], f80[8] ); 73 SWAPC( f80[2], f80[7] ); 74 SWAPC( f80[3], f80[6] ); 75 SWAPC( f80[4], f80[5] ); 76 } 77 78 #undef SWAPC 79 80 int main ( void ) 81 { 82 UChar ref_qnan64[8] 83 = { 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 84 85 UChar ref_snan64[8] 86 = { 0x7f, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 87 88 UChar ref_qnan80[10] 89 = { 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 90 91 UChar ref_snan80[10] 92 = { 0x7f, 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 93 94 rev64( ref_qnan64 ); 95 rev64( ref_snan64 ); 96 rev80( ref_qnan80 ); 97 rev80( ref_snan80 ); 98 99 UChar* res = malloc(10); 100 #define ZAP memset(res, 0x55, 10) 101 102 103 int pass; 104 for (pass = 1; pass <= 2; pass++) { 105 106 ZAP; do_64_to_80( res, ref_qnan64 ); 107 print64( "src = qnan64: ", ref_qnan64 ); 108 print80( "dst = qnan80: ", res ); 109 printf("\n"); 110 111 ZAP; do_64_to_80( res, ref_snan64 ); 112 print64( "src = snan64: ", ref_snan64 ); 113 print80( "dst = snan80: ", res ); 114 printf("\n"); 115 116 ZAP; do_80_to_64( res, ref_qnan80 ); 117 print80( "src = qnan80: ", ref_qnan80 ); 118 print64( "dst = qnan64: ", res ); 119 printf("\n"); 120 121 ZAP; do_80_to_64( res, ref_snan80 ); 122 print80( "src = snan80: ", ref_snan80 ); 123 print64( "dst = snan64: ", res ); 124 printf("\n"); 125 126 /* now make all the reference inputs negative and do it again */ 127 128 ref_qnan64[7] ^= 0x80; 129 ref_snan64[7] ^= 0x80; 130 131 ref_qnan80[9] ^= 0x80; 132 ref_snan80[9] ^= 0x80; 133 134 } 135 136 #undef ZAP 137 138 free(res); 139 return 0; 140 } 141