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 14typedef unsigned char UChar; 15 16 17void 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 25void 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 33void 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 42void 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 53void gen_qnan_64 ( UChar* dst ) 54{ 55 56} 57#endif 58 59#define SWAPC(_xx,_yy) { UChar tmp = _xx; _xx = _yy; _yy = tmp; } 60 61static 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 69static 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 80int 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