[pypy-svn] pypy default: Copy the logic of CPython to fix the precision around

arigo commits-noreply at bitbucket.org
Sun Feb 13 13:46:34 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41872:1ea103d126e9
Date: 2011-02-13 13:03 +0100
http://bitbucket.org/pypy/pypy/changeset/1ea103d126e9/

Log:	Copy the logic of CPython to fix the precision around calls to
	dtoa.c, on x87 fpus.

diff --git a/pypy/translator/c/src/asm.h b/pypy/translator/c/src/asm.h
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/src/asm.h
@@ -0,0 +1,13 @@
+
+/* optional assembler bits */
+#if defined(__GNUC__) && defined(__i386__)
+#  include "src/asm_gcc_x86.h"
+#endif
+
+#if defined(__GNUC__) && defined(__amd64__)
+#  include "src/asm_gcc_x86_64.h"
+#endif
+
+#if defined(__GNUC__) && defined(__ppc__)
+#  include "src/asm_ppc.h"
+#endif

diff --git a/pypy/jit/backend/x86/support.py b/pypy/jit/backend/x86/support.py
--- a/pypy/jit/backend/x86/support.py
+++ b/pypy/jit/backend/x86/support.py
@@ -39,7 +39,8 @@
     ensure_sse2_floats = lambda : None
 else:
     _sse2_eci = ExternalCompilationInfo(
-        compile_extra = ['-msse2', '-mfpmath=sse'],
+        compile_extra = ['-msse2', '-mfpmath=sse',
+                         '-DPYPY_CPU_HAS_STANDARD_PRECISION'],
         separate_module_sources = ['void PYPY_NO_OP(void) {}'],
         )
     ensure_sse2_floats = rffi.llexternal('PYPY_NO_OP', [], lltype.Void,

diff --git a/pypy/translator/c/src/g_include.h b/pypy/translator/c/src/g_include.h
--- a/pypy/translator/c/src/g_include.h
+++ b/pypy/translator/c/src/g_include.h
@@ -37,19 +37,7 @@
 #include "src/llgroup.h"
 
 #include "src/instrument.h"
-
-/* optional assembler bits */
-#if defined(__GNUC__) && defined(__i386__)
-#  include "src/asm_gcc_x86.h"
-#endif
-
-#if defined(__GNUC__) && defined(__amd64__)
-#  include "src/asm_gcc_x86_64.h"
-#endif
-
-#if defined(__GNUC__) && defined(__ppc__)
-#  include "src/asm_ppc.h"
-#endif
+#include "src/asm.h"
 
 
 /*** modules ***/

diff --git a/pypy/translator/c/src/asm_gcc_x86.h b/pypy/translator/c/src/asm_gcc_x86.h
--- a/pypy/translator/c/src/asm_gcc_x86.h
+++ b/pypy/translator/c/src/asm_gcc_x86.h
@@ -71,6 +71,37 @@
 // I don't know how important it is, comment talks about time warps
 
 
+#ifndef PYPY_CPU_HAS_STANDARD_PRECISION
+/* On x86-32, we have to use the following hacks to set and restore
+ * the CPU's precision to 53 bits around calls to dtoa.c.  The macro
+ * PYPY_CPU_HAS_STANDARD_PRECISION is defined if we are compiling
+ * with -mss2 -mfpmath=sse anyway, in which case the precision is
+ * already ok.
+ */
+#define _PyPy_SET_53BIT_PRECISION_HEADER                          \
+    unsigned short old_387controlword, new_387controlword
+#define _PyPy_SET_53BIT_PRECISION_START                                 \
+    do {                                                                \
+        old_387controlword = _PyPy_get_387controlword();                \
+        new_387controlword = (old_387controlword & ~0x0f00) | 0x0200;   \
+        if (new_387controlword != old_387controlword)                   \
+            _PyPy_set_387controlword(new_387controlword);               \
+    } while (0)
+#define _PyPy_SET_53BIT_PRECISION_END                           \
+    if (new_387controlword != old_387controlword)               \
+        _PyPy_set_387controlword(old_387controlword)
+
+static unsigned short _PyPy_get_387controlword(void) {
+    unsigned short cw;
+    __asm__ __volatile__ ("fnstcw %0" : "=m" (cw));
+    return cw;
+}
+static void _PyPy_set_387controlword(unsigned short cw) {
+    __asm__ __volatile__ ("fldcw %0" : : "m" (cw));
+}
+#endif  /* !PYPY_CPU_HAS_STANDARD_PRECISION */
+
+
 /* implementations */
 
 #ifndef PYPY_NOT_MAIN_FILE

diff --git a/pypy/translator/c/src/dtoa.c b/pypy/translator/c/src/dtoa.c
--- a/pypy/translator/c/src/dtoa.c
+++ b/pypy/translator/c/src/dtoa.c
@@ -130,11 +130,9 @@
 #include <string.h>
 #define PYPY_NOT_MAIN_FILE
 #include "src/allocator.h"
+#include "src/asm.h"
 #define PyMem_Malloc PyObject_Malloc
 #define PyMem_Free PyObject_Free
-#define _Py_dg_strtod _PyPy_dg_strtod
-#define _Py_dg_dtoa _PyPy_dg_dtoa
-#define _Py_dg_freedtoa _PyPy_dg_freedtoa
 /* End PYPY hacks */
 
 
@@ -1508,7 +1506,7 @@
     return 0;
 }
 
-double
+static double
 _Py_dg_strtod(const char *s00, char **se)
 {
     int bb2, bb5, bbe, bd2, bd5, bs2, c, dsign, e, e1, error;
@@ -2286,7 +2284,7 @@
  * when MULTIPLE_THREADS is not defined.
  */
 
-void
+static void
 _Py_dg_freedtoa(char *s)
 {
     Bigint *b = (Bigint *)((int *)s - 1);
@@ -2332,7 +2330,7 @@
    leakage, a successful call to _Py_dg_dtoa should always be matched by a
    call to _Py_dg_freedtoa. */
 
-char *
+static char *
 _Py_dg_dtoa(double dd, int mode, int ndigits,
             int *decpt, int *sign, char **rve)
 {
@@ -2933,6 +2931,47 @@
         _Py_dg_freedtoa(s0);
     return NULL;
 }
+
+
+/* Begin PYPY hacks */
+#ifndef _PyPy_SET_53BIT_PRECISION_HEADER
+# define _PyPy_SET_53BIT_PRECISION_HEADER  /* nothing */
+#endif
+#ifndef _PyPy_SET_53BIT_PRECISION_START
+# define _PyPy_SET_53BIT_PRECISION_START   /* nothing */
+#endif
+#ifndef _PyPy_SET_53BIT_PRECISION_END
+# define _PyPy_SET_53BIT_PRECISION_END     /* nothing */
+#endif
+double _PyPy_dg_strtod(const char *s00, char **se)
+{
+    double result;
+    _PyPy_SET_53BIT_PRECISION_HEADER;
+
+    _PyPy_SET_53BIT_PRECISION_START;
+    result = _Py_dg_strtod(s00, se);
+    _PyPy_SET_53BIT_PRECISION_END;
+    return result;
+}
+
+char * _PyPy_dg_dtoa(double dd, int mode, int ndigits,
+                   int *decpt, int *sign, char **rve)
+{
+    char* result;
+    _PyPy_SET_53BIT_PRECISION_HEADER;
+
+    _PyPy_SET_53BIT_PRECISION_START;
+    result = _Py_dg_dtoa(dd, mode, ndigits, decpt, sign, rve);
+    _PyPy_SET_53BIT_PRECISION_END;
+    return result;
+}
+
+void _PyPy_dg_freedtoa(char *s)
+{
+    _Py_dg_freedtoa(s);
+}
+/* End PYPY hacks */
+
 #ifdef __cplusplus
 }
 #endif


More information about the Pypy-commit mailing list