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