Commits

David Schneider committed cc499f0 Merge

merge armhf-singlefloat

  • Participants
  • Parent commits f265ce8, 83952b7

Comments (0)

Files changed (7)

File pypy/doc/whatsnew-head.rst

 .. branch: windows-packaging
 Package tk/tcl runtime with win32
 
+.. branch: armhf-singlefloat
+JIT support for singlefloats on ARM using the hardfloat ABI

File rpython/jit/backend/arm/callbuilder.py

 
 class HardFloatCallBuilder(ARMCallbuilder):
 
+    next_arg_vfp = 0
+    next_arg_svfp = 0
+
+    def get_next_vfp(self, tp):
+        assert tp in 'fS'
+        if self.next_arg_vfp == -1:
+            return None
+        if tp == 'S':
+            i = self.next_arg_svfp
+            next_vfp = (i >> 1) + 1
+            if not (i + 1) & 1: # i is even
+                self.next_arg_vfp = max(self.next_arg_vfp, next_vfp)
+                self.next_arg_svfp = self.next_arg_vfp << 1
+            else:
+                self.next_arg_svfp += 1
+                self.next_arg_vfp = next_vfp
+            lst = r.svfp_argument_regs
+        else: # 64bit double
+            i = self.next_arg_vfp
+            self.next_arg_vfp += 1
+            if self.next_arg_svfp >> 1 == i:
+                self.next_arg_svfp = self.next_arg_vfp << 1
+            lst = r.vfp_argument_regs
+        try:
+            return lst[i]
+        except IndexError:
+            self.next_arg_vfp = self.next_arg_svfp = -1
+            return None
+
     def prepare_arguments(self):
         non_float_locs = []
         non_float_regs = []
         float_locs = []
         float_regs = []
         stack_args = []
+        singlefloats = None
 
         arglocs = self.arglocs
         argtypes = self.argtypes
 
         count = 0                      # stack alignment counter
         on_stack = 0
-        for arg in arglocs:
-            if arg.type != FLOAT:
+        for i in range(len(arglocs)):
+            argtype = INT
+            if i < len(argtypes) and argtypes[i] == 'S':
+                argtype = argtypes[i]
+            arg = arglocs[i]
+            if arg.is_float():
+                argtype = FLOAT
+                reg = self.get_next_vfp(argtype)
+                if reg:
+                    assert len(float_regs) < len(r.vfp_argument_regs)
+                    float_locs.append(arg)
+                    assert reg not in float_regs
+                    float_regs.append(reg)
+                else:  # float argument that needs to go on the stack
+                    if count % 2 != 0:
+                        stack_args.append(None)
+                        count = 0
+                        on_stack += 1
+                    stack_args.append(arg)
+                    on_stack += 2
+            elif argtype == 'S':
+                # Singlefloat argument
+                if singlefloats is None:
+                    singlefloats = []
+                tgt = self.get_next_vfp(argtype)
+                if tgt:
+                    singlefloats.append((arg, tgt))
+                else:  # Singlefloat argument that needs to go on the stack
+                       # treated the same as a regular core register argument
+                    count += 1
+                    on_stack += 1
+                    stack_args.append(arg)
+            else:
                 if len(non_float_regs) < len(r.argument_regs):
                     reg = r.argument_regs[len(non_float_regs)]
                     non_float_locs.append(arg)
                     count += 1
                     on_stack += 1
                     stack_args.append(arg)
-            else:
-                if len(float_regs) < len(r.vfp_argument_regs):
-                    reg = r.vfp_argument_regs[len(float_regs)]
-                    float_locs.append(arg)
-                    float_regs.append(reg)
-                else:  # float argument that needs to go on the stack
-                    if count % 2 != 0:
-                        stack_args.append(None)
-                        count = 0
-                        on_stack += 1
-                    stack_args.append(arg)
-                    on_stack += 2
         # align the stack
         if count % 2 != 0:
             stack_args.append(None)
             non_float_locs.append(self.fnloc)
             non_float_regs.append(r.r4)
             self.fnloc = r.r4
+        # remap values stored in vfp registers
+        remap_frame_layout(self.asm, float_locs, float_regs, r.vfp_ip)
+        if singlefloats:
+            for src, dest in singlefloats:
+                if src.is_float():
+                    assert 0, 'unsupported case'
+                if src.is_stack():
+                    # use special VLDR for 32bit
+                    self.asm.regalloc_mov(src, r.ip)
+                    src = r.ip
+                if src.is_imm():
+                    self.mc.gen_load_int(r.ip.value, src.value)
+                    src = r.ip
+                if src.is_core_reg():
+                    self.mc.VMOV_cs(dest.value, src.value)
         # remap values stored in core registers
         remap_frame_layout(self.asm, non_float_locs, non_float_regs, r.ip)
-        # remap values stored in vfp registers
-        remap_frame_layout(self.asm, float_locs, float_regs, r.vfp_ip)
 
     def load_result(self):
         resloc = self.resloc
+        if self.restype == 'S':
+            self.mc.VMOV_sc(resloc.value, r.s0.value)
         # ensure the result is wellformed and stored in the correct location
         if resloc is not None and resloc.is_core_reg():
             self._ensure_result_bit_extension(resloc,

File rpython/jit/backend/arm/codebuilder.py

                 | (dm & 0xF))
         self.write32(instr)
 
+    def VMOV_sc(self, dest, src):
+        """move a single precision vfp register[src] to a core reg[dest]"""
+        self._VMOV_32bit(src, dest, to_arm_register=1)
+
+    def VMOV_cs(self, dest, src):
+        """move a core register[src] to a single precision vfp
+        register[dest]"""
+        self._VMOV_32bit(dest, src, to_arm_register=0)
+
+    def _VMOV_32bit(self, float_reg, core_reg, to_arm_register, cond=cond.AL):
+        """This instruction transfers the contents of a single-precision VFP
+           register to an ARM core register, or the contents of an ARM core
+           register to a single-precision VFP register.
+        """
+        instr = (cond << 28
+                | 0xE << 24
+                | to_arm_register << 20
+                | ((float_reg >> 1) & 0xF) << 16
+                | core_reg << 12
+                | 0xA << 8
+                | (float_reg & 0x1) << 7
+                | 1 << 4)
+        self.write32(instr)
+
     def VMOV_cc(self, dd, dm, cond=cond.AL):
         sz = 1  # for 64-bit mode
         instr = (cond << 28
         self._VCVT(target, source, cond, 0, 1)
 
     def _VCVT(self, target, source, cond, opc2, sz):
-        D = 0
-        M = 0
+        # A8.6.295
+        to_integer = (opc2 >> 2) & 1
+        if to_integer:
+            D = target & 1
+            target >>= 1
+            M = (source >> 4) & 1
+        else:
+            M = source & 1
+            source >>= 1
+            D = (target >> 4) & 1
         op = 1
         instr = (cond << 28
                 | 0xEB8 << 16
 
     def _VCVT_single_double(self, target, source, cond, sz):
         # double_to_single = (sz == '1');
-        D = 0
-        M = 0
+        D = target & 1 if sz else (target >> 4) & 1
+        M = (source >> 4) & 1 if sz else source & 1
         instr = (cond << 28
                 | 0xEB7 << 16
                 | 0xAC << 4

File rpython/jit/backend/arm/locations.py

     type = FLOAT
     width = 2 * WORD
 
-    def get_single_precision_regs(self):
-        return [VFPRegisterLocation(i) for i in
-                        [self.value * 2, self.value * 2 + 1]]
-
     def __repr__(self):
-        return 'vfp%d' % self.value
+        return 'vfp(d%d)' % self.value
 
     def is_core_reg(self):
         return False
     def is_float(self):
         return True
 
+class SVFPRegisterLocation(VFPRegisterLocation):
+    """Single Precission VFP Register"""
+    _immutable_ = True
+    width = WORD
+    type = 'S'
+
+    def __repr__(self):
+        return 'vfp(s%d)' % self.value
 
 class ImmLocation(AssemblerLocation):
     _immutable_ = True

File rpython/jit/backend/arm/opassembler.py

         arg, res = arglocs
         assert arg.is_vfp_reg()
         assert res.is_core_reg()
-        self.mc.VCVT_float_to_int(r.vfp_ip.value, arg.value)
-        self.mc.VMOV_rc(res.value, r.ip.value, r.vfp_ip.value)
+        self.mc.VCVT_float_to_int(r.svfp_ip.value, arg.value)
+        self.mc.VMOV_sc(res.value, r.svfp_ip.value)
         return fcond
 
     def emit_op_cast_int_to_float(self, op, arglocs, regalloc, fcond):
         arg, res = arglocs
         assert res.is_vfp_reg()
         assert arg.is_core_reg()
-        self.mc.MOV_ri(r.ip.value, 0)
-        self.mc.VMOV_cr(res.value, arg.value, r.ip.value)
-        self.mc.VCVT_int_to_float(res.value, res.value)
+        self.mc.VMOV_cs(r.svfp_ip.value, arg.value)
+        self.mc.VCVT_int_to_float(res.value, r.svfp_ip.value)
         return fcond
 
     emit_op_llong_add = gen_emit_float_op('llong_add', 'VADD_i64')
         arg, res = arglocs
         assert arg.is_vfp_reg()
         assert res.is_core_reg()
-        self.mc.VCVT_f64_f32(r.vfp_ip.value, arg.value)
-        self.mc.VMOV_rc(res.value, r.ip.value, r.vfp_ip.value)
+        self.mc.VCVT_f64_f32(r.svfp_ip.value, arg.value)
+        self.mc.VMOV_sc(res.value, r.svfp_ip.value)
         return fcond
 
     def emit_op_cast_singlefloat_to_float(self, op, arglocs, regalloc, fcond):
         arg, res = arglocs
         assert res.is_vfp_reg()
         assert arg.is_core_reg()
-        self.mc.MOV_ri(r.ip.value, 0)
-        self.mc.VMOV_cr(res.value, arg.value, r.ip.value)
-        self.mc.VCVT_f32_f64(res.value, res.value)
+        self.mc.VMOV_cs(r.svfp_ip.value, arg.value)
+        self.mc.VCVT_f32_f64(res.value, r.svfp_ip.value)
         return fcond

File rpython/jit/backend/arm/registers.py

 from rpython.jit.backend.arm.locations import VFPRegisterLocation
+from rpython.jit.backend.arm.locations import SVFPRegisterLocation
 from rpython.jit.backend.arm.locations import RegisterLocation
 
 registers = [RegisterLocation(i) for i in range(16)]
 vfpregisters = [VFPRegisterLocation(i) for i in range(16)]
+svfpregisters = [SVFPRegisterLocation(i) for i in range(32)]
 [r0, r1, r2, r3, r4, r5, r6, r7,
     r8, r9, r10, r11, r12, r13, r14, r15] = registers
 
 [d0, d1, d2, d3, d4, d5, d6, d7,
     d8, d9, d10, d11, d12, d13, d14, d15] = vfpregisters
 
+# single precission VFP registers, 32-bit
+for i in range(32):
+    globals()['s%d' % i] = svfpregisters[i]
+
 # aliases for registers
 fp = r11
 ip = r12
 lr = r14
 pc = r15
 vfp_ip = d15
+svfp_ip = s31
 
 all_regs = [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10]
 all_vfp_regs = vfpregisters[:-1]
 callee_restored_registers = callee_resp + [pc]
 
 vfp_argument_regs = caller_vfp_resp = [d0, d1, d2, d3, d4, d5, d6, d7]
+svfp_argument_regs = [globals()['s%i' % i] for i in range(16)]
 callee_vfp_resp = [d8, d9, d10, d11, d12, d13, d14, d15]
 
 callee_saved_vfp_registers = callee_vfp_resp

File rpython/jit/backend/arm/runner.py

     supports_floats = True
     supports_longlong = False # XXX requires an implementation of
                               # read_timestamp that works in user mode
-    supports_singlefloats = not detect_hardfloat()
+    supports_singlefloats = True
 
     from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE
     all_reg_indexes = range(len(all_regs))