Author: Richard Plangger <[email protected]>
Branch: s390x-backend
Changeset: r80466:85a292e8a0ad
Date: 2015-10-27 11:20 +0100
http://bitbucket.org/pypy/pypy/changeset/85a292e8a0ad/
Log: adapted some arch details, added failure recovery, finish resop
(partly)
diff --git a/rpython/jit/backend/zarch/arch.py
b/rpython/jit/backend/zarch/arch.py
--- a/rpython/jit/backend/zarch/arch.py
+++ b/rpython/jit/backend/zarch/arch.py
@@ -1,4 +1,20 @@
+WORD = 8
-WORD = 4
+#
+# OFFSET
+# +------------------------------+ 0
+# | gpr save are (int+float) |
+# +------------------------------+ 8
+# | local vars |
+# +------------------------------+ 0
+# | |
+# +------------------------------+
+# | |
+# +------------------------------+ <- SP 0 (r15)
+#
-JITFRAME_FIXED_SIZE = 48
+GPR_STACK_SAVE_IN_BYTES = 120
+STD_FRAME_SIZE_IN_BYTES = 140
+THREADLOCAL_ADDR_OFFSET = 8
+
+assert STD_FRAME_SIZE_IN_BYTES % 2 == 0
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
@@ -6,12 +6,16 @@
from rpython.jit.backend.zarch import registers as r
from rpython.jit.backend.zarch import locations as loc
from rpython.jit.backend.zarch.codebuilder import InstrBuilder
-from rpython.jit.backend.zarch.arch import (WORD, JITFRAME_FIXED_SIZE)
+from rpython.jit.backend.zarch.registers import JITFRAME_FIXED_SIZE
+from rpython.jit.backend.zarch.arch import (WORD,
+ STD_FRAME_SIZE_IN_BYTES, GPR_STACK_SAVE_IN_BYTES,
+ THREADLOCAL_ADDR_OFFSET)
from rpython.jit.backend.zarch.opassembler import IntOpAssembler
from rpython.jit.backend.zarch.regalloc import Regalloc
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.rlib.rarithmetic import r_uint
from rpython.rlib.objectmodel import we_are_translated, specialize,
compute_unique_id
from rpython.rlib import rgc
@@ -30,6 +34,7 @@
self.stack_check_slowpath = 0
self.loop_run_counters = []
self.gcrootmap_retaddr_forced = 0
+ self.failure_recovery_code = [0, 0, 0, 0]
def setup(self, looptoken):
BaseAssembler.setup(self, looptoken)
@@ -62,12 +67,14 @@
return clt.asmmemmgr_blocks
def gen_func_prolog(self):
+ """ NOT_RPYTHON """
STACK_FRAME_SIZE = 40
- self.mc.STMG(r.r11, r.r15, loc.addr(-STACK_FRAME_SIZE, r.sp))
+ self.mc.STMG(r.r11, r.r15, loc.addr(-STACK_FRAME_SIZE, r.SP))
self.mc.AHI(r.sp, loc.imm(-STACK_FRAME_SIZE))
def gen_func_epilog(self):
- self.mc.LMG(r.r11, r.r15, loc.addr(0, r.SPP))
+ """ NOT_RPYTHON """
+ self.mc.LMG(r.r11, r.r15, loc.addr(0, r.SP))
self.jmpto(r.r14)
def jmpto(self, register):
@@ -76,7 +83,42 @@
self.mc.BCR_rr(0xf, register.value)
def _build_failure_recovery(self, exc, withfloats=False):
- pass # TODO
+ mc = InstrBuilder()
+ self.mc = mc
+ # fill in the jf_descr and jf_gcmap fields of the frame according
+ # to which failure we are resuming from. These are set before
+ # this function is called (see generate_quick_failure()).
+ ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+ ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+ mc.STG(r.r2, loc.addr(ofs, r.SPP))
+ mc.STG(r.r3, loc.addr(ofs2, r.SPP))
+
+ self._push_core_regs_to_jitframe(mc)
+ if withfloats:
+ self._push_fp_regs_to_jitframe(mc)
+
+ if exc:
+ pass # TODO
+ #xxx
+ ## We might have an exception pending.
+ #mc.load_imm(r.r2, self.cpu.pos_exc_value())
+ ## Copy it into 'jf_guard_exc'
+ #offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+ #mc.load(r.r0.value, r.r2.value, 0)
+ #mc.store(r.r0.value, r.SPP.value, offset)
+ ## Zero out the exception fields
+ #diff = self.cpu.pos_exception() - self.cpu.pos_exc_value()
+ #assert _check_imm_arg(diff)
+ #mc.li(r.r0.value, 0)
+ #mc.store(r.r0.value, r.r2.value, 0)
+ #mc.store(r.r0.value, r.r2.value, diff)
+
+ # now we return from the complete frame, which starts from
+ # _call_header_with_stack_check(). The _call_footer below does it.
+ self._call_footer()
+ rawstart = mc.materialize(self.cpu, [])
+ self.failure_recovery_code[exc + 2 * withfloats] = rawstart
+ self.mc = None
def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False):
pass # TODO
@@ -106,7 +148,23 @@
pass # TODO
def _call_header_with_stack_check(self):
- pass # TODO
+ self._call_header()
+ if self.stack_check_slowpath == 0:
+ pass # not translated
+ else:
+ endaddr, lengthaddr, _ = self.cpu.insert_stack_check()
+ diff = lengthaddr - endaddr
+ assert _check_imm_arg(diff)
+
+ mc = self.mc
+ mc.load_imm(r.SCRATCH, self.stack_check_slowpath)
+ mc.load_imm(r.SCRATCH2, endaddr) # li r2, endaddr
+ mc.mtctr(r.SCRATCH.value)
+ mc.load(r.SCRATCH.value, r.SCRATCH2.value, 0) # ld r0, [end]
+ mc.load(r.SCRATCH2.value, r.SCRATCH2.value, diff)# ld r2, [length]
+ mc.subf(r.SCRATCH.value, r.SP.value, r.SCRATCH.value) # sub r0, SP
+ mc.cmp_op(0, r.SCRATCH.value, r.SCRATCH2.value, signed=False)
+ mc.bgtctrl()
@rgc.no_release_gil
def assemble_loop(self, jd_id, unique_id, logger, loopname, inputargs,
@@ -322,7 +380,48 @@
clt.invalidate_positions.append((rawstart + relpos,
relative_target))
+ def _call_header(self):
+ # Reserve space for a function descriptor, 3 words
+ #self.mc.write64(0)
+ #self.mc.write64(0)
+ #self.mc.write64(0)
+ # Build a new stackframe of size STD_FRAME_SIZE_IN_BYTES
+ self.mc.STMG(r.r6, r.r15, loc.addr(-GPR_STACK_SAVE_IN_BYTES, r.SP))
+ self.mc.AGHI(r.SP, loc.imm(-STD_FRAME_SIZE_IN_BYTES))
+
+ # save r4, the second argument, to THREADLOCAL_ADDR_OFFSET
+ self.mc.STG(r.r3, loc.addr(THREADLOCAL_ADDR_OFFSET, r.SP))
+
+ # move the first argument to SPP: the jitframe object
+ self.mc.LGR(r.SPP, r.r2)
+
+ gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+ if gcrootmap and gcrootmap.is_shadow_stack:
+ self._call_header_shadowstack(gcrootmap)
+
+ def _call_footer(self):
+ # the return value is the jitframe
+ self.mc.LGR(r.r2, r.SPP)
+
+ gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+ if gcrootmap and gcrootmap.is_shadow_stack:
+ self._call_footer_shadowstack(gcrootmap)
+
+ # restore registers r6-r15
+ upoffset = STD_FRAME_SIZE_IN_BYTES-GPR_STACK_SAVE_IN_BYTES
+ self.mc.LMG(r.r6, r.r15, loc.addr(upoffset, r.SP))
+ self.jmpto(r.r14)
+
+ def _push_core_regs_to_jitframe(self, mc, includes=r.MANAGED_REGS):
+ base_ofs = self.cpu.get_baseofs_of_frame_field()
+ assert len(includes) == 16
+ mc.STMG(r.r0, r.r15, loc.addr(base_ofs, r.SPP))
+
+ def _push_fp_regs_to_jitframe(self, mc, includes=r.MANAGED_FP_REGS):
+ base_ofs = self.cpu.get_baseofs_of_frame_field()
+ assert len(includes) == 16
+ mc.LMG(r.r0, r.r15, loc.addr(base_ofs, r.SPP))
# ________________________________________
# ASSEMBLER EMISSION
@@ -331,7 +430,52 @@
pass # TODO
def emit_finish(self, op, arglocs, regalloc):
- pass # TODO
+ base_ofs = self.cpu.get_baseofs_of_frame_field()
+ if len(arglocs) > 1:
+ [return_val, fail_descr_loc] = arglocs
+ if op.getarg(0).type == FLOAT:
+ raise NotImplementedError
+ #self.mc.stfd(return_val, loc.addr(base_ofs, r.SPP))
+ else:
+ self.mc.STG(return_val, loc.addr(base_ofs, r.SPP))
+ else:
+ [fail_descr_loc] = arglocs
+
+ ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+ ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+
+ # gcmap logic here:
+ arglist = op.getarglist()
+ if arglist and arglist[0].type == REF:
+ if self._finish_gcmap:
+ # we're returning with a guard_not_forced_2, and
+ # additionally we need to say that the result contains
+ # a reference too:
+ self._finish_gcmap[0] |= r_uint(1)
+ gcmap = self._finish_gcmap
+ else:
+ gcmap = self.gcmap_for_finish
+ elif self._finish_gcmap:
+ # we're returning with a guard_not_forced_2
+ gcmap = self._finish_gcmap
+ else:
+ gcmap = lltype.nullptr(jitframe.GCMAP)
+ # TODO self.load_gcmap(self.mc, r.r2, gcmap)
+
+ assert fail_descr_loc.getint() <= 2**12-1
+ self.mc.LGHI(r.r5, fail_descr_loc)
+ self.mc.STG(r.r5, loc.addr(ofs, r.SPP))
+ self.mc.XGR(r.r2, r.r2)
+ self.mc.STG(r.r2, loc.addr(ofs2, r.SPP))
+
+ # exit function
+ self._call_footer()
+
+ 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)
def notimplemented_op(asm, op, arglocs, regalloc):
print "[ZARCH/asm] %s not implemented" % op.getopname()
diff --git a/rpython/jit/backend/zarch/instructions.py
b/rpython/jit/backend/zarch/instructions.py
--- a/rpython/jit/backend/zarch/instructions.py
+++ b/rpython/jit/backend/zarch/instructions.py
@@ -73,15 +73,23 @@
# load memory
'LMD': ('sse', ['\xEF']),
'LMG': ('rsy', ['\xEB','\x04']),
+ 'LHI': ('ri', ['\xA7','\x08']),
'LGHI': ('ri', ['\xA7','\x09']),
'LR': ('rr', ['\x18']),
'LGR': ('rre', ['\xB9','\x04']),
'LG': ('rxy', ['\xE3','\x04']),
+ # store memory
+ 'STMG': ('rsy', ['\xEB','\x24']),
+ 'ST': ('rx', ['\x50']),
+ 'STG': ('rxy', ['\xE3','\x24']),
+ 'STY': ('rxy', ['\xE3','\x50']),
+
# store float
'STE': ('rx', ['\x70']),
'STD': ('rx', ['\x60']),
+
# load binary float
# E -> short (32bit),
# D -> long (64bit),
@@ -166,7 +174,6 @@
'MVCK': ('ssd', ['\xD9']),
'PKA': ('ssf', ['\xE9']),
- 'STMG': ('rsy', ['\xEB','\x24']),
'SVC': ('i', ['\x0A']),
}
diff --git a/rpython/jit/backend/zarch/locations.py
b/rpython/jit/backend/zarch/locations.py
--- a/rpython/jit/backend/zarch/locations.py
+++ b/rpython/jit/backend/zarch/locations.py
@@ -1,5 +1,5 @@
from rpython.jit.metainterp.history import INT, FLOAT
-from rpython.jit.backend.zarch.arch import WORD, JITFRAME_FIXED_SIZE
+from rpython.jit.backend.zarch.arch import WORD
class AssemblerLocation(object):
_immutable_ = True
@@ -190,6 +190,7 @@
return ImmLocation(i)
def get_fp_offset(base_ofs, position):
+ from rpython.jit.backend.zarch.registers import JITFRAME_FIXED_SIZE
return base_ofs + WORD * (position + JITFRAME_FIXED_SIZE)
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
@@ -465,7 +465,17 @@
prepare_int_add = regallochelp._prepare_binary_arith
def prepare_finish(self, op):
- return []
+ descr = op.getdescr()
+ fail_descr = cast_instance_to_gcref(descr)
+ # we know it does not move, but well
+ rgc._make_sure_does_not_move(fail_descr)
+ fail_descr = rffi.cast(lltype.Signed, fail_descr)
+ if op.numargs() > 0:
+ loc = self.ensure_reg(op.getarg(0))
+ locs = [loc, imm(fail_descr)]
+ else:
+ locs = [imm(fail_descr)]
+ return locs
def notimplemented(self, op):
msg = '[S390X/regalloc] %s not implemented\n' % op.getopname()
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
@@ -1,5 +1,3 @@
-
-
from rpython.jit.backend.zarch.locations import FloatRegisterLocation
from rpython.jit.backend.zarch.locations import RegisterLocation
@@ -9,13 +7,28 @@
[r0,r1,r2,r3,r4,r5,r6,r7,r8,
r9,r10,r11,r12,r13,r14,r15] = registers
-MANAGED_REGS = [r0,r1,r2,r3,r4]
-VOLATILES = [r0,r1,r2,r3,r4]
-SPP = r15
+MANAGED_REGS = registers
+VOLATILES = [r6,r7,r8,r9,r10,r11,r12,r13,r14,r15]
+SP = r15
RETURN = r14
+POOL = r13
+SPP = r11
[f0,f1,f2,f3,f4,f5,f6,f7,f8,
f9,f10,f11,f12,f13,f14,f15] = fpregisters
MANAGED_FP_REGS = fpregisters
VOLATILES_FLOAT = []
+
+# The JITFRAME_FIXED_SIZE is measured in words, and should be the
+# number of registers that need to be saved into the jitframe when
+# failing a guard, for example.
+ALL_REG_INDEXES = {}
+for _r in MANAGED_REGS:
+ ALL_REG_INDEXES[_r] = len(ALL_REG_INDEXES)
+for _r in MANAGED_FP_REGS:
+ ALL_REG_INDEXES[_r] = len(ALL_REG_INDEXES) + 1
+ # we leave a never-used hole for f0 ^^^ in the jitframe
+ # to simplify store_info_on_descr(), which assumes that the
+ # register number N is at offset N after the non-fp regs
+JITFRAME_FIXED_SIZE = len(ALL_REG_INDEXES) + 1
diff --git a/rpython/jit/backend/zarch/test/test_runner.py
b/rpython/jit/backend/zarch/test/test_runner.py
--- a/rpython/jit/backend/zarch/test/test_runner.py
+++ b/rpython/jit/backend/zarch/test/test_runner.py
@@ -15,7 +15,7 @@
class FakeStats(object):
pass
-class TestPPC(LLtypeBackendTest):
+class TestZARCH(LLtypeBackendTest):
# for the individual tests see
# ====> ../../test/runner_test.py
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit