1
2#include <stdio.h>
3#include <math.h>
4
5typedef unsigned long long int ULong;
6
7typedef
8   struct { double d; int i; } Res;
9
10static 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)
28     : /*in*/  "m" (f64), "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
35static void show ( char* s, Res* res )
36{
37  printf("%s -> 0x%04x %f\n", s, (int)res->i, (double)res->d);
38}
39
40int 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