[pypy-commit] pypy arm64: start working on cond_call, we need float support for that
fijal
pypy.commits at gmail.com
Tue Jun 18 07:01:00 EDT 2019
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: arm64
Changeset: r96818:98896de049b1
Date: 2019-06-18 10:56 +0000
http://bitbucket.org/pypy/pypy/changeset/98896de049b1/
Log: start working on cond_call, we need float support for that
diff --git a/rpython/jit/backend/aarch64/assembler.py b/rpython/jit/backend/aarch64/assembler.py
--- a/rpython/jit/backend/aarch64/assembler.py
+++ b/rpython/jit/backend/aarch64/assembler.py
@@ -530,7 +530,26 @@
self.propagate_exception_path = rawstart
def _build_cond_call_slowpath(self, supports_floats, callee_only):
- pass
+ """ This builds a general call slowpath, for whatever call happens to
+ come.
+ """
+ mc = InstrBuilder()
+ #
+ self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats, callee_only)
+ ## args are in their respective positions
+ mc.SUB_ri(r.sp.value, r.sp.value, 2 * WORD)
+ mc.STR_ri(r.ip0.value, r.sp.value, WORD)
+ mc.STR_ri(r.lr.value, r.sp.value, 0)
+ mc.BL(r.ip1.value)
+ mc.MOV_rr(r.ip1.value, r.x0.value) # return comes back in ip1
+ self._reload_frame_if_necessary(mc)
+ self._pop_all_regs_from_jitframe(mc, [], supports_floats,
+ callee_only)
+ # return
+ mc.LDR_ri(r.ip0.value, r.sp.value, 0)
+ mc.ADD_ri(r.sp.value, r.sp.value, 2 * WORD)
+ mc.RET_r(r.ip0.value)
+ return mc.materialize(self.cpu, [])
def _build_stack_check_slowpath(self):
self.stack_check_slowpath = 0 #XXX
diff --git a/rpython/jit/backend/aarch64/opassembler.py b/rpython/jit/backend/aarch64/opassembler.py
--- a/rpython/jit/backend/aarch64/opassembler.py
+++ b/rpython/jit/backend/aarch64/opassembler.py
@@ -1,5 +1,6 @@
from rpython.rlib.objectmodel import we_are_translated
+from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt,
INT, FLOAT, REF)
from rpython.jit.backend.aarch64 import registers as r
@@ -502,6 +503,49 @@
self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs,
array=True)
+ def emit_op_cond_call(self, op, arglocs):
+ self.mc.gen_load_int(r.ip1.value, rffi.cast(lltype.Signed,
+ op.getarg(1).getint()))
+
+ #if len(arglocs) == 2:
+ # res_loc = arglocs[1] # cond_call_value
+ #else:
+ # res_loc = None # cond_call
+ # see x86.regalloc for why we skip res_loc in the gcmap
+ res_loc = None
+ gcmap = self._regalloc.get_gcmap([res_loc])
+
+ jmp_adr = self.mc.currpos()
+ self.mc.BRK() # patched later: the conditional jump
+ #
+ self.push_gcmap(self.mc, gcmap)
+ #
+ callee_only = False
+ floats = False
+ if self._regalloc is not None:
+ for reg in self._regalloc.rm.reg_bindings.values():
+ if reg not in self._regalloc.rm.save_around_call_regs:
+ break
+ else:
+ callee_only = True
+ if self._regalloc.vfprm.reg_bindings:
+ floats = True
+ cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only]
+ assert cond_call_adr
+ self.mc.BL(cond_call_adr)
+ # if this is a COND_CALL_VALUE, we need to move the result in place
+ # from its current location (which is, unusually, in r4: see
+ # cond_call_slowpath)
+ if res_loc is not None:
+ self.mc.MOV_rr(res_loc.value, r.ip1.value)
+ #
+ self.pop_gcmap(self.mc)
+ pmc = OverwritingBuilder(self.mc, jmp_adr, WORD)
+ pmc.B_ofs_cond(self.mc.currpos(), c.EQ)
+ # might be overridden again to skip over the following
+ # guard_no_exception too
+ self.previous_cond_call_jcond = jmp_adr, c.EQ
+
def _write_barrier_fastpath(self, mc, descr, arglocs, array=False, is_frame=False):
# Write code equivalent to write_barrier() in the GC: it checks
# a flag in the object at arglocs[0], and if set, it calls a
diff --git a/rpython/jit/backend/aarch64/regalloc.py b/rpython/jit/backend/aarch64/regalloc.py
--- a/rpython/jit/backend/aarch64/regalloc.py
+++ b/rpython/jit/backend/aarch64/regalloc.py
@@ -630,6 +630,42 @@
self._compute_hint_frame_locations_from_descr(descr)
return []
+ def prepare_op_cond_call(self, op):
+ assert 2 <= op.numargs() <= 4 + 2
+ v = op.getarg(1)
+ assert isinstance(v, Const)
+ args_so_far = []
+ for i in range(2, op.numargs()):
+ reg = r.argument_regs[i - 2]
+ arg = op.getarg(i)
+ self.make_sure_var_in_reg(arg, args_so_far, selected_reg=reg)
+ args_so_far.append(arg)
+
+ if op.type == 'v':
+ # a plain COND_CALL. Calls the function when args[0] is
+ # true. Often used just after a comparison operation.
+ return []
+ else:
+ XXX
+ # COND_CALL_VALUE_I/R. Calls the function when args[0]
+ # is equal to 0 or NULL. Returns the result from the
+ # function call if done, or args[0] if it was not 0/NULL.
+ # Implemented by forcing the result to live in the same
+ # register as args[0], and overwriting it if we really do
+ # the call.
+
+ # Load the register for the result. Possibly reuse 'args[0]'.
+ # But the old value of args[0], if it survives, is first
+ # spilled away. We can't overwrite any of op.args[2:] here.
+ args = op.getarglist()
+ resloc = self.rm.force_result_in_reg(op, args[0],
+ forbidden_vars=args[2:])
+ # Test the register for the result.
+ self.assembler.mc.CMP_ri(resloc.value, 0)
+ self.assembler.guard_success_cc = c.EQ
+ return [tmpreg, resloc]
+
+
def prepare_op_finish(self, op):
# the frame is in fp, but we have to point where in the frame is
# the potential argument to FINISH
More information about the pypy-commit
mailing list