| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 | /* * src/fpu.cc * * This work was supported by the Director, Office of Science, Division * of Mathematical, Information, and Computational Sciences of the * U.S. Department of Energy under contract number DE-AC03-76SF00098. * * Copyright (c) 2000-2001 * * Contains functions to set and restore the round-to-double flag in the * control word of a x86 FPU. */#include "config.h"#include <qd/fpu.h>#ifdef X86#ifdef  _WIN32#include <float.h>#else#ifdef HAVE_FPU_CONTROL_H#include <fpu_control.h>#endif#ifndef _FPU_GETCW#define _FPU_GETCW(x) asm volatile ("fnstcw %0":"=m" (x));#endif#ifndef _FPU_SETCW#define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x));#endif#ifndef _FPU_EXTENDED#define _FPU_EXTENDED 0x0300#endif#ifndef _FPU_DOUBLE#define _FPU_DOUBLE 0x0200#endif#endif#endif /* X86 */extern "C" {void fpu_fix_start(unsigned int *old_cw) {#ifdef X86#ifdef _WIN32#ifdef __BORLANDC__  /* Win 32 Borland C */  unsigned short cw = _control87(0, 0);  _control87(0x0200, 0x0300);  if (old_cw) {    *old_cw = cw;  }#else  /* Win 32 MSVC */  unsigned int cw = _control87(0, 0);  _control87(0x00010000, 0x00030000);  if (old_cw) {    *old_cw = cw;  }#endif#else  /* Linux */  volatile unsigned short cw, new_cw;  _FPU_GETCW(cw);  new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;  _FPU_SETCW(new_cw);    if (old_cw) {    *old_cw = cw;  }#endif#endif}void fpu_fix_end(unsigned int *old_cw) {#ifdef X86#ifdef _WIN32#ifdef __BORLANDC__  /* Win 32 Borland C */  if (old_cw) {    unsigned short cw = (unsigned short) *old_cw;    _control87(cw, 0xFFFF);  }#else  /* Win 32 MSVC */  if (old_cw) {    _control87(*old_cw, 0xFFFFFFFF);  }#endif#else  /* Linux */  if (old_cw) {    int cw;    cw = *old_cw;    _FPU_SETCW(cw);  }#endif#endif}#ifdef HAVE_FORTRAN#define f_fpu_fix_start FC_FUNC_(f_fpu_fix_start, F_FPU_FIX_START)#define f_fpu_fix_end   FC_FUNC_(f_fpu_fix_end,   F_FPU_FIX_END)void f_fpu_fix_start(unsigned int *old_cw) {  fpu_fix_start(old_cw);}void f_fpu_fix_end(unsigned int *old_cw) {  fpu_fix_end(old_cw);}#endif} 
 |