1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "tests/malloc.h"
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is a Marie Celeste instruction.  Some IBM documents think it
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exists, others don't.  The same appears to be true for
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   implementations - ppc970 doesn't think it exists, but POWER5
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   does. */
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndouble do_fre ( double x )
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  double block[2];
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  block[0] = x;
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  __asm__ __volatile__(
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "lfd %%f1, 0(%0)\n\t"
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ".long 0xfc200830\n\t" /* == fre %%f1,%%f1 */
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "stfd %%f1, 8(%0)"
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*out*/
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*in*/ "b" (&block[0])
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*trash*/ "memory", "fr1"
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  );
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return block[1];
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndouble do_fres ( double x )
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  double block[2];
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  block[0] = x;
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  __asm__ __volatile__(
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "lfd %%f1, 0(%0)\n\t"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "fres %%f1,%%f1\n\t"
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "stfd %%f1, 8(%0)"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*out*/
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*in*/ "b" (&block[0])
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*trash*/ "memory", "fr1"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return block[1];
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndouble do_frsqrte ( double x )
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  double block[2];
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  block[0] = x;
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  __asm__ __volatile__(
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "lfd %%f1, 0(%0)\n\t"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "frsqrte %%f1,%%f1\n\t"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "stfd %%f1, 8(%0)"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*out*/
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*in*/ "b" (&block[0])
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*trash*/ "memory", "fr1"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return block[1];
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Another Marie Celeste insn. */
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndouble do_frsqrtes ( double x )
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  double block[2];
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  block[0] = x;
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  __asm__ __volatile__(
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "lfd %%f1, 0(%0)\n\t"
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ".long 0xec200834\n\t" /* == frsqrtes %%f1,%%f1 */
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     "stfd %%f1, 8(%0)"
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*out*/
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*in*/ "b" (&block[0])
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     : /*trash*/ "memory", "fr1"
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return block[1];
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_one ( char* name,
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              double(*f)(double),
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              double* args, int nargs,
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              char* argfmt, char* resfmt )
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int i;
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  double a, r;
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\n");
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (i = 0; i < nargs; i++) {
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = args[i];
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    r = f(a);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("%s ", name);
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf(argfmt, a);
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf(" -> ");
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf(resfmt, r);
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("\n");
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main ( void )
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int nargs = 19;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  double* args = malloc(nargs * sizeof(double));
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[0]  =  0.0;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[1]  =  1.0 / 0.0; // inf
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[2]  = -args[1]; //  -inf
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[3]  = args[2]/args[2]; // nan
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[4]  = -args[3]; // -nan
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[5]  = -5e100;
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[6]  = -5e20;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[7]  = -501.0;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[8]  = -6.0;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[9]  = -1.01;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[10] = -2e-20;
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[11] = -2e-200;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[12] =  2e-200;
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[13] =  2e-20;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[14] =  1.01;
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[15] =  6.0;
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[16] =  501.0;
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[17] =  5e20;
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  args[18] =  5e100;
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_one( "fre",  do_fre,  args, nargs, "%e", "%4.1e");
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_one( "fres", do_fres, args, nargs, "%e", "%4.1e");
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_one( "frsqrte",  do_frsqrte,  args, nargs, "%e", "%4.1e");
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_one( "frsqrtes", do_frsqrtes, args, nargs, "%e", "%4.1e");
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(args);
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0;
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
125