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