#include <stdio.h> #include "tests/malloc.h" /* This is a Marie Celeste instruction. Some IBM documents think it exists, others don't. The same appears to be true for implementations - ppc970 doesn't think it exists, but POWER5 does. */ double do_fre ( double x ) { double block[2]; block[0] = x; __asm__ __volatile__( "lfd %%f1, 0(%0)\n\t" ".long 0xfc200830\n\t" /* == fre %%f1,%%f1 */ "stfd %%f1, 8(%0)" : /*out*/ : /*in*/ "b" (&block[0]) : /*trash*/ "memory", "fr1" ); return block[1]; } double do_fres ( double x ) { double block[2]; block[0] = x; __asm__ __volatile__( "lfd %%f1, 0(%0)\n\t" "fres %%f1,%%f1\n\t" "stfd %%f1, 8(%0)" : /*out*/ : /*in*/ "b" (&block[0]) : /*trash*/ "memory", "fr1" ); return block[1]; } double do_frsqrte ( double x ) { double block[2]; block[0] = x; __asm__ __volatile__( "lfd %%f1, 0(%0)\n\t" "frsqrte %%f1,%%f1\n\t" "stfd %%f1, 8(%0)" : /*out*/ : /*in*/ "b" (&block[0]) : /*trash*/ "memory", "fr1" ); return block[1]; } /* Another Marie Celeste insn. */ double do_frsqrtes ( double x ) { double block[2]; block[0] = x; __asm__ __volatile__( "lfd %%f1, 0(%0)\n\t" ".long 0xec200834\n\t" /* == frsqrtes %%f1,%%f1 */ "stfd %%f1, 8(%0)" : /*out*/ : /*in*/ "b" (&block[0]) : /*trash*/ "memory", "fr1" ); return block[1]; } //////////////////////////////////////////////////////////// void do_one ( char* name, double(*f)(double), double* args, int nargs, char* argfmt, char* resfmt ) { int i; double a, r; printf("\n"); for (i = 0; i < nargs; i++) { a = args[i]; r = f(a); printf("%s ", name); printf(argfmt, a); printf(" -> "); printf(resfmt, r); printf("\n"); } } int main ( void ) { int nargs = 19; double* args = malloc(nargs * sizeof(double)); args[0] = 0.0; args[1] = 1.0 / 0.0; // inf args[2] = -args[1]; // -inf args[3] = args[2]/args[2]; // nan args[4] = -args[3]; // -nan args[5] = -5e100; args[6] = -5e20; args[7] = -501.0; args[8] = -6.0; args[9] = -1.01; args[10] = -2e-20; args[11] = -2e-200; args[12] = 2e-200; args[13] = 2e-20; args[14] = 1.01; args[15] = 6.0; args[16] = 501.0; args[17] = 5e20; args[18] = 5e100; do_one( "fre", do_fre, args, nargs, "%e", "%4.1e"); do_one( "fres", do_fres, args, nargs, "%e", "%4.1e"); do_one( "frsqrte", do_frsqrte, args, nargs, "%e", "%4.1e"); do_one( "frsqrtes", do_frsqrtes, args, nargs, "%e", "%4.1e"); free(args); return 0; }