Home | History | Annotate | Download | only in amd64
      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