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