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