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 
do_64_to_80(UChar * dst,UChar * src)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 
do_80_to_64(UChar * dst,UChar * src)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 
print80(char * s,UChar * v)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 
print64(char * s,UChar * v)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 
rev64(UChar * f64)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 
rev80(UChar * f80)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 
main(void)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