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. */ 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 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 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. */ 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 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 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