[pypy-commit] pypy arm-longlong: in-progress
arigo
noreply at buildbot.pypy.org
Sun Aug 31 18:44:36 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: arm-longlong
Changeset: r73238:7befb5f6d6db
Date: 2014-08-31 19:39 +0300
http://bitbucket.org/pypy/pypy/changeset/7befb5f6d6db/
Log: in-progress
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
@@ -316,10 +316,12 @@
float_regs = []
stack_args = []
singlefloats = None
+ longlong_mask = 0
arglocs = self.arglocs
argtypes = self.argtypes
+ r_register_count = 0
count = 0 # stack alignment counter
on_stack = 0
for i in range(len(arglocs)):
@@ -327,23 +329,51 @@
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
+ if i < len(argtypes) and argtypes[i] == 'L':
+ # A longlong argument. It uses two regular argument
+ # positions, but aligned to an even number. This is
+ # a bit strange, but it is the case even for registers:
+ # it can be in r0-r1 or in r2-r3 but not in r1-r2.
+ assert arg.is_float()
+ if r_register_count == 0:
+ # will temporarily load the register into d8
+ float_locs.append(arg)
+ float_regs.append(r.d8)
+ longlong_mask |= 1
+ r_register_count = 2
+ continue
+ elif r_register_count <= 2:
+ # will temporarily load the register into d9
+ float_locs.append(arg)
+ float_regs.append(r.d9)
+ longlong_mask |= 2
+ r_register_count = 4
+ continue
+ else:
+ # A 64-bit float argument. Goes into the next free v#
+ # register, or if none, to the stack aligned to an
+ # even number of words.
+ 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)
+ continue
+ # float or longlong 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
+ # Singlefloat (32-bit) argument. Goes into the next free
+ # v# register, or if none, to the stack in a single word.
if singlefloats is None:
singlefloats = []
tgt = self.get_next_vfp(argtype)
@@ -355,19 +385,24 @@
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)]
+ # Regular one-word argument. Goes into the next register
+ # free from the list r0, r1, r2, r3, or to the stack.
+ if r_register_count < len(r.argument_regs):
+ reg = r.argument_regs[r_register_count]
+ r_register_count += 1
non_float_locs.append(arg)
non_float_regs.append(reg)
else: # non-float argument that needs to go on the stack
count += 1
on_stack += 1
stack_args.append(arg)
+
# align the stack
if count % 2 != 0:
stack_args.append(None)
on_stack += 1
self._push_stack_args(stack_args, on_stack*WORD)
+
# Check that the address of the function we want to call is not
# currently stored in one of the registers used to pass the arguments
# or on the stack, which we can not access later
@@ -377,6 +412,7 @@
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:
@@ -392,8 +428,14 @@
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)
+ if longlong_mask & 1:
+ self.mc.FMRRD(r.r0.value, r.r1.value, r.d8.value)
+ if longlong_mask & 2:
+ self.mc.FMRRD(r.r2.value, r.r3.value, r.d9.value)
+
def load_result(self):
resloc = self.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
@@ -339,6 +339,20 @@
MOD = binary_helper_call('int_mod')
UDIV = binary_helper_call('uint_div')
+ def FMDRR(self, dm, rd, rn, c=cond.AL):
+ self.write32(c << 28
+ | 0x0c400b10
+ | (dm & 0xF)
+ | (rd & 0xF) << 12
+ | (rn & 0xF) << 16)
+
+ def FMRRD(self, rd, rn, dm, c=cond.AL):
+ self.write32(c << 28
+ | 0x0c500b10
+ | (dm & 0xF)
+ | (rd & 0xF) << 12
+ | (rn & 0xF) << 16)
+
def _encode_reg_list(self, instr, regs):
for reg in regs:
instr |= 0x1 << reg
diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py b/rpython/jit/backend/arm/test/test_instr_codebuilder.py
--- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py
+++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py
@@ -199,6 +199,14 @@
self.cb.DMB()
self.assert_equal('DMB')
+ def test_fmdrr(self):
+ self.cb.FMDRR(r.d11.value, r.r9.value, r.r14.value)
+ self.assert_equal('FMDRR d11, r9, r14')
+
+ def test_fmrrd(self):
+ self.cb.FMRRD(r.r9.value, r.r14.value, r.d11.value)
+ self.assert_equal('FMRRD r9, r14, d11')
+
def test_size_of_gen_load_int():
for v, n in [(5, 4), (6, 4), (7, 2)]:
More information about the pypy-commit
mailing list