Author: David Schneider <[email protected]>
Branch:
Changeset: r68236:cc499f0c7d91
Date: 2013-11-19 09:30 +0100
http://bitbucket.org/pypy/pypy/changeset/cc499f0c7d91/
Log: merge armhf-singlefloat
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -13,3 +13,5 @@
.. branch: windows-packaging
Package tk/tcl runtime with win32
+.. branch: armhf-singlefloat
+JIT support for singlefloats on ARM using the hardfloat ABI
diff --git a/rpython/jit/backend/arm/callbuilder.py
b/rpython/jit/backend/arm/callbuilder.py
--- a/rpython/jit/backend/arm/callbuilder.py
+++ b/rpython/jit/backend/arm/callbuilder.py
@@ -227,20 +227,81 @@
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)
@@ -249,18 +310,6 @@
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)
@@ -275,13 +324,28 @@
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,
diff --git a/rpython/jit/backend/arm/codebuilder.py
b/rpython/jit/backend/arm/codebuilder.py
--- a/rpython/jit/backend/arm/codebuilder.py
+++ b/rpython/jit/backend/arm/codebuilder.py
@@ -178,6 +178,30 @@
| (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
@@ -198,8 +222,16 @@
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
@@ -216,8 +248,8 @@
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
diff --git a/rpython/jit/backend/arm/locations.py
b/rpython/jit/backend/arm/locations.py
--- a/rpython/jit/backend/arm/locations.py
+++ b/rpython/jit/backend/arm/locations.py
@@ -55,12 +55,8 @@
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
@@ -74,6 +70,14 @@
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
diff --git a/rpython/jit/backend/arm/opassembler.py
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -1102,17 +1102,16 @@
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')
@@ -1147,15 +1146,14 @@
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
diff --git a/rpython/jit/backend/arm/registers.py
b/rpython/jit/backend/arm/registers.py
--- a/rpython/jit/backend/arm/registers.py
+++ b/rpython/jit/backend/arm/registers.py
@@ -1,8 +1,10 @@
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
@@ -10,6 +12,10 @@
[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
@@ -17,6 +23,7 @@
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]
@@ -27,6 +34,7 @@
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
diff --git a/rpython/jit/backend/arm/runner.py
b/rpython/jit/backend/arm/runner.py
--- a/rpython/jit/backend/arm/runner.py
+++ b/rpython/jit/backend/arm/runner.py
@@ -22,7 +22,7 @@
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))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit