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