[pypy-commit] pypy s390x-backend: adding jump instruction and working on correct assembly of guard failure

plan_rich noreply at buildbot.pypy.org
Wed Oct 28 07:02:27 EDT 2015


Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r80472:dd415ed2de42
Date: 2015-10-28 12:01 +0100
http://bitbucket.org/pypy/pypy/changeset/dd415ed2de42/

Log:	adding jump instruction and working on correct assembly of guard
	failure

diff --git a/rpython/jit/backend/llsupport/jump.py b/rpython/jit/backend/llsupport/jump.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/jump.py
@@ -0,0 +1,109 @@
+def remap_frame_layout(assembler, src_locations, dst_locations, tmpreg):
+    pending_dests = len(dst_locations)
+    srccount = {}    # maps dst_locations to how many times the same
+                     # location appears in src_locations
+    for dst in dst_locations:
+        key = dst.as_key()
+        assert key not in srccount, "duplicate value in dst_locations!"
+        srccount[key] = 0
+    for i in range(len(dst_locations)):
+        src = src_locations[i]
+        if src.is_imm():
+            continue
+        key = src.as_key()
+        if key in srccount:
+            if key == dst_locations[i].as_key():
+                # ignore a move "x = x"
+                # setting any "large enough" negative value is ok, but
+                # be careful of overflows, don't use -sys.maxint
+                srccount[key] = -len(dst_locations) - 1
+                pending_dests -= 1
+            else:
+                srccount[key] += 1
+
+    while pending_dests > 0:
+        progress = False
+        for i in range(len(dst_locations)):
+            dst = dst_locations[i]
+            key = dst.as_key()
+            if srccount[key] == 0:
+                srccount[key] = -1       # means "it's done"
+                pending_dests -= 1
+                src = src_locations[i]
+                if not src.is_imm():
+                    key = src.as_key()
+                    if key in srccount:
+                        srccount[key] -= 1
+                _move(assembler, src, dst, tmpreg)
+                progress = True
+        if not progress:
+            # we are left with only pure disjoint cycles
+            sources = {}     # maps dst_locations to src_locations
+            for i in range(len(dst_locations)):
+                src = src_locations[i]
+                dst = dst_locations[i]
+                sources[dst.as_key()] = src
+            #
+            for i in range(len(dst_locations)):
+                dst = dst_locations[i]
+                originalkey = dst.as_key()
+                if srccount[originalkey] >= 0:
+                    assembler.regalloc_push(dst, 0)
+                    while True:
+                        key = dst.as_key()
+                        assert srccount[key] == 1
+                        # ^^^ because we are in a simple cycle
+                        srccount[key] = -1
+                        pending_dests -= 1
+                        src = sources[key]
+                        if src.as_key() == originalkey:
+                            break
+                        _move(assembler, src, dst, tmpreg)
+                        dst = src
+                    assembler.regalloc_pop(dst, 0)
+            assert pending_dests == 0
+
+def _move(assembler, src, dst, tmpreg):
+    if dst.is_stack() and src.is_stack():
+        assembler.regalloc_mov(src, tmpreg)
+        src = tmpreg
+    assembler.regalloc_mov(src, dst)
+
+def remap_frame_layout_mixed(assembler,
+                             src_locations1, dst_locations1, tmpreg1,
+                             src_locations2, dst_locations2, tmpreg2):
+    # find and push the fp stack locations from src_locations2 that
+    # are going to be overwritten by dst_locations1
+    # TODO
+    from rpython.jit.backend.zarch.arch import WORD
+    extrapushes = []
+    dst_keys = {}
+    for loc in dst_locations1:
+        dst_keys[loc.as_key()] = None
+    src_locations2red = []
+    dst_locations2red = []
+    for i in range(len(src_locations2)):
+        loc    = src_locations2[i]
+        dstloc = dst_locations2[i]
+        if loc.is_stack():
+            key = loc.as_key()
+            if (key in dst_keys or (loc.width > WORD and
+                                    (key + 1) in dst_keys)):
+                assembler.regalloc_push(loc, len(extrapushes))
+                extrapushes.append(dstloc)
+                continue
+        src_locations2red.append(loc)
+        dst_locations2red.append(dstloc)
+    src_locations2 = src_locations2red
+    dst_locations2 = dst_locations2red
+    #
+    # remap the integer and pointer registers and stack locations
+    remap_frame_layout(assembler, src_locations1, dst_locations1, tmpreg1)
+    #
+    # remap the fp registers and stack locations
+    remap_frame_layout(assembler, src_locations2, dst_locations2, tmpreg2)
+    #
+    # finally, pop the extra fp stack locations
+    while len(extrapushes) > 0:
+        loc = extrapushes.pop()
+        assembler.regalloc_pop(loc, len(extrapushes))
diff --git a/rpython/jit/backend/zarch/assembler.py b/rpython/jit/backend/zarch/assembler.py
--- a/rpython/jit/backend/zarch/assembler.py
+++ b/rpython/jit/backend/zarch/assembler.py
@@ -16,7 +16,8 @@
 from rpython.jit.metainterp.resoperation import rop
 from rpython.rlib.debug import (debug_print, debug_start, debug_stop,
                                 have_debug_prints)
-from rpython.jit.metainterp.history import (INT, REF, FLOAT)
+from rpython.jit.metainterp.history import (INT, REF, FLOAT,
+        TargetToken)
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.objectmodel import we_are_translated, specialize, compute_unique_id
 from rpython.rlib import rgc
@@ -208,6 +209,21 @@
         self.failure_recovery_code[exc + 2 * withfloats] = rawstart
         self.mc = None
 
+    def generate_quick_failure(self, guardtok):
+        startpos = self.mc.currpos()
+        fail_descr, target = self.store_info_on_descr(startpos, guardtok)
+        assert target != 0
+        self.load_gcmap(self.mc, r.r2, gcmap=guardtok.gcmap)
+        self.mc.write('\x00\x00\x00\x00')
+        #load_imm(r.r0, target)
+        #self.mc.mtctr(r.r0.value)
+        #self.mc.load_imm(r.r0, fail_descr)
+        #self.mc.bctr()
+        # we need to write at least 6 insns here, for patch_jump_for_descr()
+        #while self.mc.currpos() < startpos + 6 * 4:
+        #    self.mc.trap()
+        return startpos
+
     def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False):
         pass # TODO
 
@@ -309,9 +325,9 @@
         ops_offset = self.mc.ops_offset
         if not we_are_translated():
             # used only by looptoken.dump() -- useful in tests
-            looptoken._ppc_rawstart = rawstart
-            looptoken._ppc_fullsize = full_size
-            looptoken._ppc_ops_offset = ops_offset
+            looptoken._zarch_rawstart = rawstart
+            looptoken._zarch_fullsize = full_size
+            looptoken._zarch_ops_offset = ops_offset
         looptoken._ll_function_addr = rawstart
         if logger:
             logger.log_loop(inputargs, operations, 0, "rewritten",
@@ -328,7 +344,7 @@
         frame_depth = regalloc.get_final_frame_depth()
         jump_target_descr = regalloc.jump_target_descr
         if jump_target_descr is not None:
-            tgt_depth = jump_target_descr._ppc_clt.frame_info.jfi_frame_depth
+            tgt_depth = jump_target_descr._zarch_clt.frame_info.jfi_frame_depth
             target_frame_depth = tgt_depth - JITFRAME_FIXED_SIZE
             frame_depth = max(frame_depth, target_frame_depth)
         return frame_depth
@@ -375,7 +391,7 @@
             # move to memory
             elif loc.is_stack():
                 offset = loc.value
-                self.mc.store(prev_loc, r.SPP, offset)
+                self.mc.STG(prev_loc, l.addr(offset, r.SPP))
                 return
             assert 0, "not supported location"
         elif prev_loc.is_imm_float():
@@ -522,6 +538,24 @@
     def emit_label(self, op, arglocs, regalloc):
         pass
 
+    def emit_jump(self, op, arglocs, regalloc):
+        # The backend's logic assumes that the target code is in a piece of
+        # assembler that was also called with the same number of arguments,
+        # so that the locations [ebp+8..] of the input arguments are valid
+        # stack locations both before and after the jump.
+        #
+        descr = op.getdescr()
+        assert isinstance(descr, TargetToken)
+        my_nbargs = self.current_clt._debug_nbargs
+        target_nbargs = descr._zarch_clt._debug_nbargs
+        assert my_nbargs == target_nbargs
+
+        if descr in self.target_tokens_currently_compiling:
+            self.mc.b_offset(descr._ll_loop_code)
+        else:
+            self.mc.b_abs(descr._ll_loop_code)
+
+
     def emit_finish(self, op, arglocs, regalloc):
         base_ofs = self.cpu.get_baseofs_of_frame_field()
         if len(arglocs) > 1:
@@ -552,7 +586,7 @@
             gcmap = self._finish_gcmap
         else:
             gcmap = lltype.nullptr(jitframe.GCMAP)
-        # TODO self.load_gcmap(self.mc, r.r2, gcmap)
+        self.load_gcmap(self.mc, r.r2, gcmap)
 
         assert fail_descr_loc.getint() <= 2**12-1
         self.mc.LGHI(r.r5, fail_descr_loc)
@@ -566,8 +600,8 @@
     def load_gcmap(self, mc, reg, gcmap):
         # load the current gcmap into register 'reg'
         ptr = rffi.cast(lltype.Signed, gcmap)
-        #mc.LGHI(mc.pool
-        #mc.load_imm(reg, ptr)
+        assert 0 <= ptr <= 2**15-1
+        mc.LGHI(reg, loc.imm(ptr))
 
 def notimplemented_op(asm, op, arglocs, regalloc):
     print "[ZARCH/asm] %s not implemented" % op.getopname()
diff --git a/rpython/jit/backend/zarch/codebuilder.py b/rpython/jit/backend/zarch/codebuilder.py
--- a/rpython/jit/backend/zarch/codebuilder.py
+++ b/rpython/jit/backend/zarch/codebuilder.py
@@ -95,6 +95,10 @@
     def currpos(self):
         return self.get_relative_pos()
 
+    def b_offset(self, reladdr):
+        offset = reladdr - self.get_relative_pos()
+        self.BRC(l.imm(0xf), l.imm(offset))
+
     def cmp_op(self, a, b, pool=False, signed=True, fp=False):
         if fp == True:
             xxx
diff --git a/rpython/jit/backend/zarch/opassembler.py b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -69,7 +69,9 @@
         token.pos_jump_offset = self.mc.currpos()
         assert token.guard_not_invalidated() == is_guard_not_invalidated
         if not is_guard_not_invalidated:
-            self.mc.trap()     # has to be patched later on
+            pass
+            # TODO
+            #self.mc.trap()     # has to be patched later on
         self.pending_guard_tokens.append(token)
 
     def build_guard_token(self, op, frame_depth, arglocs, fcond):
diff --git a/rpython/jit/backend/zarch/regalloc.py b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -1,6 +1,7 @@
 from rpython.jit.backend.llsupport.regalloc import (RegisterManager, FrameManager,
                                                     TempVar, compute_vars_longevity,
                                                     BaseRegalloc)
+from rpython.jit.backend.llsupport.jump import remap_frame_layout_mixed
 from rpython.jit.backend.zarch.arch import WORD
 from rpython.jit.codewriter import longlong
 from rpython.jit.backend.zarch.locations import imm, get_fp_offset
@@ -561,6 +562,39 @@
         if jump_op is not None and jump_op.getdescr() is descr:
             self._compute_hint_frame_locations_from_descr(descr)
 
+    def prepare_jump(self, op):
+        descr = op.getdescr()
+        assert isinstance(descr, TargetToken)
+        self.jump_target_descr = descr
+        arglocs = self.assembler.target_arglocs(descr)
+
+        # get temporary locs
+        tmploc = r.SCRATCH
+        fptmploc = r.f0
+
+        # Part about non-floats
+        src_locations1 = []
+        dst_locations1 = []
+        src_locations2 = []
+        dst_locations2 = []
+
+        # Build the four lists
+        for i in range(op.numargs()):
+            box = op.getarg(i)
+            src_loc = self.loc(box)
+            dst_loc = arglocs[i]
+            if box.type != FLOAT:
+                src_locations1.append(src_loc)
+                dst_locations1.append(dst_loc)
+            else:
+                src_locations2.append(src_loc)
+                dst_locations2.append(dst_loc)
+
+        remap_frame_layout_mixed(self.assembler,
+                                 src_locations1, dst_locations1, tmploc,
+                                 src_locations2, dst_locations2, fptmploc)
+        return []
+
     def prepare_finish(self, op):
         descr = op.getdescr()
         fail_descr = cast_instance_to_gcref(descr)
diff --git a/rpython/jit/backend/zarch/registers.py b/rpython/jit/backend/zarch/registers.py
--- a/rpython/jit/backend/zarch/registers.py
+++ b/rpython/jit/backend/zarch/registers.py
@@ -13,6 +13,7 @@
 RETURN = r14
 POOL = r13
 SPP = r11
+SCRATCH = r0
 
 [f0,f1,f2,f3,f4,f5,f6,f7,f8,
  f9,f10,f11,f12,f13,f14,f15] = fpregisters
diff --git a/rpython/jit/backend/zarch/runner.py b/rpython/jit/backend/zarch/runner.py
--- a/rpython/jit/backend/zarch/runner.py
+++ b/rpython/jit/backend/zarch/runner.py
@@ -1,7 +1,8 @@
 from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
+from rpython.jit.backend.zarch import registers as r
 from rpython.jit.backend.zarch.assembler import AssemblerZARCH
+from rpython.rlib import rgc
 from rpython.rtyper.lltypesystem import lltype, llmemory
-from rpython.rlib import rgc
 
 class AbstractZARCHCPU(AbstractLLCPU):
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
@@ -18,6 +19,15 @@
 class CPU_S390_64(AbstractZARCHCPU):
     supports_floats = True
 
+    IS_64_BIT = True
+
+    frame_reg = r.SP
+    all_reg_indexes = [-1] * 32
+    for _i, _r in enumerate(r.MANAGED_REGS):
+        all_reg_indexes[_r.value] = _i
+    gen_regs = r.MANAGED_REGS
+    float_regs = r.MANAGED_FP_REGS
+
     def setup(self):
         self.assembler = AssemblerZARCH(self)
 


More information about the pypy-commit mailing list