[pypy-svn] pypy default: Import float2longlong() from the jitypes2 branch, and use it in

arigo commits-noreply at bitbucket.org
Fri Jan 14 15:06:17 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r40671:2e48ec813eda
Date: 2011-01-14 14:16 +0100
http://bitbucket.org/pypy/pypy/changeset/2e48ec813eda/

Log:	Import float2longlong() from the jitypes2 branch, and use it in the
	new FloatImmedLoc.

diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -25,7 +25,7 @@
                                          X86_64_XMM_SCRATCH_REG,
                                          RegLoc, StackLoc, ConstFloatLoc,
                                          ImmedLoc, AddressLoc, imm,
-                                         imm0, imm1)
+                                         imm0, imm1, FloatImmedLoc)
 
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.backend.x86 import rx86, regloc, codebuf
@@ -1170,8 +1170,13 @@
             self.mc.MOV16(dest_addr, value_loc)
         elif size == 4:
             self.mc.MOV32(dest_addr, value_loc)
-        elif IS_X86_64 and size == 8:
-            self.mc.MOV(dest_addr, value_loc)
+        elif size == 8:
+            if IS_X86_64:
+                self.mc.MOV(dest_addr, value_loc)
+            else:
+                assert isinstance(value_loc, FloatImmedLoc)
+                self.mc.MOV(dest_addr, value_loc.low_part_loc())
+                self.mc.MOV(dest_addr.add_offset(4), value_loc.high_part_loc())
         else:
             not_implemented("save_into_mem size = %d" % size)
 

diff --git a/pypy/rlib/longlong2float.py b/pypy/rlib/longlong2float.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/longlong2float.py
@@ -0,0 +1,47 @@
+"""
+This module exposes the functions longlong2float() and float2longlong(),
+which cast the bit pattern of a long long into a float and back.
+"""
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+# -------- implement longlong2float and float2longlong --------
+DOUBLE_ARRAY_PTR = lltype.Ptr(lltype.Array(rffi.DOUBLE))
+LONGLONG_ARRAY_PTR = lltype.Ptr(lltype.Array(rffi.LONGLONG))
+
+# these definitions are used only in tests, when not translated
+def longlong2float_emulator(llval):
+    d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw')
+    ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
+    ll_array[0] = llval
+    floatval = d_array[0]
+    lltype.free(d_array, flavor='raw')
+    return floatval
+
+def float2longlong_emulator(floatval):
+    d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw')
+    ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
+    d_array[0] = floatval
+    llval = ll_array[0]
+    lltype.free(d_array, flavor='raw')
+    return llval
+
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+eci = ExternalCompilationInfo(post_include_bits=["""
+static double pypy__longlong2float(long long x) {
+    return *((double*)&x);
+}
+static long long pypy__float2longlong(double x) {
+    return *((long long*)&x);
+}
+"""])
+
+longlong2float = rffi.llexternal(
+    "pypy__longlong2float", [rffi.LONGLONG], rffi.DOUBLE,
+    _callable=longlong2float_emulator, compilation_info=eci,
+    _nowrapper=True, pure_function=True)
+
+float2longlong = rffi.llexternal(
+    "pypy__float2longlong", [rffi.DOUBLE], rffi.LONGLONG,
+    _callable=float2longlong_emulator, compilation_info=eci,
+    _nowrapper=True, pure_function=True)

diff --git a/pypy/jit/backend/x86/regloc.py b/pypy/jit/backend/x86/regloc.py
--- a/pypy/jit/backend/x86/regloc.py
+++ b/pypy/jit/backend/x86/regloc.py
@@ -3,7 +3,7 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.jit.backend.x86.arch import WORD, IS_X86_32, IS_X86_64
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.objectmodel import specialize
+from pypy.rlib.objectmodel import specialize, instantiate
 from pypy.rlib.rarithmetic import intmask
 from pypy.jit.metainterp.history import FLOAT
 
@@ -175,6 +175,19 @@
                 return edx
         return eax
 
+    def add_offset(self, ofs):
+        result = instantiate(AddressLoc)
+        result._location_code = self._location_code
+        if self._location_code == 'm':
+            result.loc_m = (self.loc_m[0], self.loc_m[1] + ofs)
+        elif self._location_code == 'a':
+            result.loc_a = self.loc_a[:3] + (self.loc_a[3] + ofs,)
+        elif self._location_code == 'j':
+            result.value = self.value + ofs
+        else:
+            raise AssertionError(self._location_code)
+        return result
+
 class ConstFloatLoc(AssemblerLocation):
     # XXX: We have to use this class instead of just AddressLoc because
     # we want a width of 8  (... I think.  Check this!)
@@ -190,6 +203,40 @@
     def location_code(self):
         return 'j'
 
+class FloatImmedLoc(AssemblerLocation):
+    # This stands for an immediate float.  It cannot be directly used in
+    # any assembler instruction.  Instead, it is meant to be decomposed
+    # in two 32-bit halves.  On 64-bit, only use low_part(), which is
+    # actually everything.
+    _immutable_ = True
+    width = 8
+
+    def __init__(self, floatvalue):
+        from pypy.rlib.longlong2float import float2longlong
+        self.aslonglong = float2longlong(floatvalue)
+
+    def low_part(self):
+        return intmask(self.aslonglong)
+
+    def high_part(self):
+        assert IS_X86_32
+        return intmask(self.aslonglong >> 32)
+
+    def low_part_loc(self):
+        return ImmedLoc(self.low_part())
+
+    def high_part_loc(self):
+        return ImmedLoc(self.high_part())
+
+    def __repr__(self):
+        from pypy.rlib.longlong2float import longlong2float
+        floatvalue = longlong2float(self.aslonglong)
+        return '<FloatImmedLoc(%s)>' % (floatvalue,)
+
+    def location_code(self):
+        raise NotImplementedError
+
+
 REGLOCS = [RegLoc(i, is_xmm=False) for i in range(16)]
 XMMREGLOCS = [RegLoc(i, is_xmm=True) for i in range(16)]
 eax, ecx, edx, ebx, esp, ebp, esi, edi, r8, r9, r10, r11, r12, r13, r14, r15 = REGLOCS

diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -4,7 +4,7 @@
 
 import os
 from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr,
-                                         ResOperation, BoxPtr, BoxFloat,
+                                         ResOperation, BoxPtr, ConstFloat,
                                          LoopToken, INT, REF, FLOAT)
 from pypy.jit.backend.x86.regloc import *
 from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr
@@ -212,8 +212,8 @@
     def make_sure_var_in_reg(self, var, forbidden_vars=[],
                              selected_reg=None, need_lower_byte=False):
         if var.type == FLOAT:
-            assert isinstance(var, BoxFloat), (
-                "ConstFloats must be handled differently")
+            if isinstance(var, ConstFloat):
+                return FloatImmedLoc(var.getfloat())
             return self.xrm.make_sure_var_in_reg(var, forbidden_vars,
                                                  selected_reg, need_lower_byte)
         else:


More information about the Pypy-commit mailing list