Home | History | Annotate | Download | only in amd64
      1 
      2 #include <stdio.h>
      3 #include <math.h>
      4 
      5 typedef unsigned long long int ULong;
      6 
      7 typedef
      8    struct { double d; int i; } Res;
      9 
     10 static void do_fprem ( Res* res, double x, double y )
     11 {
     12   ULong c3210;
     13   double f64;
     14   double xx = x;
     15   double yy = y;
     16   __asm__ __volatile__(
     17      "finit\n\t"
     18      "fldl    %2\n\t"
     19      "fldl    %3\n\t"
     20      "fprem\n\t"
     21      "fstpl   %1\n\t"
     22      "movq    %%rax,%%r15\n\t"
     23      "xorq    %%rax,%%rax\n\t"
     24      "fnstsw  %%ax\n\t"
     25      "movq    %%rax,%0\n\t"
     26      "movq    %%r15,%%rax"
     27      : /*out*/ "=r" (c3210), "=m" (f64)
     28      : /*in*/  "m" (xx), "m" (yy)
     29      : /*trash*/ "r15", "rax", "%st", "%st(1)", "cc"
     30    );
     31   res->d = f64;
     32   res->i = (int)(c3210 & 0x4700); /* mask for C3,2,1,0 */
     33 }
     34 
     35 static void show ( char* s, Res* res )
     36 {
     37   printf("%s -> 0x%04x %f\n", s, (int)res->i, (double)res->d);
     38 }
     39 
     40 int main ( void )
     41 {
     42   Res r;
     43   int i;
     44   double theta;
     45 
     46   do_fprem(&r, 10.1, 200.2); show("xx1", &r);
     47   do_fprem(&r, 20.3, 1.44);  show("xx2", &r);
     48 
     49   for (i = 0; i < 20; i++) {
     50     theta = (2.0 * 3.14159) / 10.0 * (double)i;
     51     do_fprem(&r, 12.3*sin(theta), cos(theta)); show("xx", &r);
     52   }
     53 
     54   return 0;
     55 }
     56