[pypy-commit] pypy ppc-jit-backend: (bivab, shager): Implemented the encoding/decoding of states (registers, memory, descrs, immediates).
hager
noreply at buildbot.pypy.org
Fri Oct 14 16:25:23 CEST 2011
Author: hager <sven.hager at uni-duesseldorf.de>
Branch: ppc-jit-backend
Changeset: r48056:e95d2d9863da
Date: 2011-10-14 16:24 +0200
http://bitbucket.org/pypy/pypy/changeset/e95d2d9863da/
Log: (bivab, shager): Implemented the encoding/decoding of states
(registers, memory, descrs, immediates). First tests pass, added a
test regarding decode32 and encode32.
diff --git a/pypy/jit/backend/arm/test/test_helper.py b/pypy/jit/backend/arm/test/test_helper.py
--- a/pypy/jit/backend/arm/test/test_helper.py
+++ b/pypy/jit/backend/arm/test/test_helper.py
@@ -33,6 +33,8 @@
assert decode32(mem, 0) == 1234567
mem = list('\x00\x00\x0F\x00')
assert decode32(mem, 0) == 983040
+ mem = list("\x03\x00\x00\x00")
+ assert decode32(mem, 0) == 3
def test_decode64():
mem = list('\x87\xd6\x12\x00\x00\x00\x0F\x00')
diff --git a/pypy/jit/backend/ppc/ppcgen/helper/assembler.py b/pypy/jit/backend/ppc/ppcgen/helper/assembler.py
--- a/pypy/jit/backend/ppc/ppcgen/helper/assembler.py
+++ b/pypy/jit/backend/ppc/ppcgen/helper/assembler.py
@@ -31,16 +31,16 @@
return f
def encode32(mem, i, n):
- mem[i] = chr(n & 0xFF)
- mem[i+1] = chr((n >> 8) & 0xFF)
- mem[i+2] = chr((n >> 16) & 0xFF)
- mem[i+3] = chr((n >> 24) & 0xFF)
+ mem[i+3] = chr(n & 0xFF)
+ mem[i+2] = chr((n >> 8) & 0xFF)
+ mem[i+1] = chr((n >> 16) & 0xFF)
+ mem[i] = chr((n >> 24) & 0xFF)
def decode32(mem, index):
- return intmask(ord(mem[index])
- | ord(mem[index+1]) << 8
- | ord(mem[index+2]) << 16
- | ord(mem[index+3]) << 24)
+ return intmask(ord(mem[index+3])
+ | ord(mem[index+2]) << 8
+ | ord(mem[index+1]) << 16
+ | ord(mem[index]) << 24)
class saved_registers(object):
def __init__(self, assembler, regs_to_save, regalloc=None):
diff --git a/pypy/jit/backend/ppc/ppcgen/ppc_assembler.py b/pypy/jit/backend/ppc/ppcgen/ppc_assembler.py
--- a/pypy/jit/backend/ppc/ppcgen/ppc_assembler.py
+++ b/pypy/jit/backend/ppc/ppcgen/ppc_assembler.py
@@ -11,7 +11,7 @@
from pypy.jit.backend.ppc.ppcgen.arch import (IS_PPC_32, WORD, NONVOLATILES,
GPR_SAVE_AREA)
from pypy.jit.backend.ppc.ppcgen.helper.assembler import (gen_emit_cmp_op,
- encode32)
+ encode32, decode32)
import pypy.jit.backend.ppc.ppcgen.register as r
import pypy.jit.backend.ppc.ppcgen.condition as c
from pypy.jit.metainterp.history import (Const, ConstPtr, LoopToken,
@@ -28,6 +28,8 @@
from pypy.jit.metainterp.history import (BoxInt, ConstInt, ConstPtr,
ConstFloat, Box, INT, REF, FLOAT)
from pypy.jit.backend.x86.support import values_array
+from pypy.rlib import rgc
+from pypy.rpython.annlowlevel import llhelper
memcpy_fn = rffi.llexternal('memcpy', [llmemory.Address, llmemory.Address,
rffi.SIZE_T], lltype.Void,
@@ -173,59 +175,133 @@
offset = target_pos - curpos
self.mc.b(offset)
- #def _make_epilogue(self):
- # for op_index, fail_index, guard, reglist in self.patch_list:
- # curpos = self.mc.get_rel_pos()
- # offset = curpos - (4 * op_index)
- # assert (1 << 15) > offset
- # self.mc.beq(offset)
- # self.mc.patch_op(op_index)
+ def setup_failure_recovery(self):
- # # store return parameters in memory
- # used_mem_indices = []
- # for index, reg in enumerate(reglist):
- # # if reg is None, then there is a hole in the failargs
- # if reg is not None:
- # addr = self.fail_boxes_int.get_addr_for_num(index)
- # self.store_reg(reg, addr)
- # used_mem_indices.append(index)
+ @rgc.no_collect
+ def failure_recovery_func(mem_loc, frame_pointer, stack_pointer):
+ """mem_loc is a structure in memory describing where the values for
+ the failargs are stored.
+ frame loc is the address of the frame pointer for the frame to be
+ decoded frame """
+ return self.decode_registers_and_descr(mem_loc, frame_pointer, stack_pointer)
- # patch_op = self.mc.get_number_of_ops()
- # patch_pos = self.mc.get_rel_pos()
- # descr = self.cpu.saved_descr[fail_index]
- # descr.patch_op = patch_op
- # descr.patch_pos = patch_pos
- # descr.used_mem_indices = used_mem_indices
+ self.failure_recovery_func = failure_recovery_func
- # self.mc.li(r.r3.value, fail_index)
+ recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed,
+ lltype.Signed, lltype.Signed], lltype.Signed))
- # #self._restore_nonvolatiles()
+ @rgc.no_collect
+ def decode_registers_and_descr(self, mem_loc, stack_loc, spp_loc):
+ '''
+ mem_loc : pointer to encoded state
+ stack_loc : pointer to top of the stack
+ spp_loc : pointer to begin of the spilling area
+ '''
+ enc = rffi.cast(rffi.CCHARP, mem_loc)
+ managed_size = WORD * len(r.MANAGED_REGS)
+ spilling_depth = spp_loc - stack_loc + managed_size
+ spilling_area = rffi.cast(rffi.CCHARP, stack_loc + managed_size)
+ assert spilling_depth >= 0
- # #self.mc.lwz(0, 1, self.framesize + 4)
- # #if IS_PPC_32:
- # # self.mc.lwz(0, 1, self.framesize + WORD) # 36
- # #else:
- # # self.mc.ld(0, 1, self.framesize + WORD) # 36
- # #self.mc.mtlr(0)
- # #self.mc.addi(1, 1, self.framesize)
- # #self.mc.li(r.r3.value, fail_index)
- # #self.mc.blr()
+ regs = rffi.cast(rffi.CCHARP, stack_loc)
+ i = -1
+ fail_index = -1
+ while(True):
+ i += 1
+ fail_index += 1
+ res = enc[i]
+ if res == self.END_OF_LOCS:
+ break
+ if res == self.EMPTY_LOC:
+ continue
+
+ group = res
+ i += 1
+ res = enc[i]
+ if res == self.IMM_LOC:
+ # imm value
+ if group == self.INT_TYPE or group == self.REF_TYPE:
+ value = decode32(enc, i+1)
+ i += 4
+ else:
+ assert group == self.FLOAT_TYPE
+ adr = decode32(enc, i+1)
+ value = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), adr)[0]
+ self.fail_boxes_float.setitem(fail_index, value)
+ i += 4
+ continue
+ elif res == self.STACK_LOC:
+ stack_loc = decode32(enc, i+1)
+ i += 4
+ if group == self.FLOAT_TYPE:
+ value = decode64(stack, frame_depth - stack_loc*WORD)
+ self.fail_boxes_float.setitem(fail_index, value)
+ continue
+ else:
+ value = decode32(spilling_area, spilling_area - stack_loc * WORD)
+ else: # REG_LOC
+ reg = ord(enc[i])
+ if group == self.FLOAT_TYPE:
+ value = decode64(vfp_regs, reg*2*WORD)
+ self.fail_boxes_float.setitem(fail_index, value)
+ continue
+ else:
+ value = decode32(regs, reg*WORD - 2 * WORD)
+
+ if group == self.INT_TYPE:
+ self.fail_boxes_int.setitem(fail_index, value)
+ elif group == self.REF_TYPE:
+ tgt = self.fail_boxes_ptr.get_addr_for_num(fail_index)
+ rffi.cast(rffi.LONGP, tgt)[0] = value
+ else:
+ assert 0, 'unknown type'
+
+
+ assert enc[i] == self.END_OF_LOCS
+ descr = decode32(enc, i+1)
+ self.fail_boxes_count = fail_index
+ self.fail_force_index = spp_loc
+ return descr
def _gen_leave_jitted_hook_code(self, save_exc=False):
mc = PPCBuilder()
- ### XXX add a check if cpu supports floats
- #with saved_registers(mc, r.caller_resp + [r.ip], r.caller_vfp_resp):
- # addr = self.cpu.get_on_leave_jitted_int(save_exception=save_exc)
- # mc.BL(addr)
- #assert self._exit_code_addr != 0
- #mc.B(self._exit_code_addr)
+
+ # PLAN:
+ # =====
+ # save caller save registers AND(!) r0
+ # (r0 contains address of state encoding)
+
mc.b_abs(self.exit_code_adr)
mc.prepare_insts_blocks()
return mc.materialize(self.cpu.asmmemmgr, [],
self.cpu.gc_ll_descr.gcrootmap)
+ # XXX 64 bit adjustment needed
def _gen_exit_path(self):
- mc = PPCBuilder()
+ mc = PPCBuilder()
+ #
+ self._save_managed_regs(mc)
+ # adjust SP (r1)
+ size = WORD * len(r.MANAGED_REGS)
+ mc.addi(r.SP.value, r.SP.value, -size)
+ #
+ decode_func_addr = llhelper(self.recovery_func_sign,
+ self.failure_recovery_func)
+ addr = rffi.cast(lltype.Signed, decode_func_addr)
+ #
+ # load parameters into parameter registers
+ mc.lwz(r.r3.value, r.SPP.value, 0)
+ #mc.mr(r.r3.value, r.r0.value) # address of state encoding
+ mc.mr(r.r4.value, r.SP.value) # load stack pointer
+ mc.mr(r.r5.value, r.SPP.value) # load spilling pointer
+ #
+ # load address of decoding function into r0
+ mc.load_imm(r.r0, addr)
+ # ... and branch there
+ mc.mtctr(r.r0.value)
+ mc.bctrl()
+ #
+ mc.addi(r.SP.value, r.SP.value, size)
# save SPP in r5
# (assume that r5 has been written to failboxes)
mc.mr(r.r5.value, r.SPP.value)
@@ -242,6 +318,17 @@
return mc.materialize(self.cpu.asmmemmgr, [],
self.cpu.gc_ll_descr.gcrootmap)
+ # Save all registers which are managed by the register
+ # allocator on top of the stack before decoding.
+ # XXX adjust for 64 bit
+ def _save_managed_regs(self, mc):
+ for i in range(len(r.MANAGED_REGS) - 1, -1, -1):
+ reg = r.MANAGED_REGS[i]
+ if IS_PPC_32:
+ mc.stw(reg.value, r.SP.value, -(len(r.MANAGED_REGS) - i) * WORD)
+ else:
+ assert 0, "not implemented yet"
+
def gen_bootstrap_code(self, nonfloatlocs, inputargs):
for i in range(len(nonfloatlocs)):
loc = nonfloatlocs[i]
@@ -273,6 +360,7 @@
def setup_once(self):
self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
+ self.setup_failure_recovery()
self.exit_code_adr = self._gen_exit_path()
#self._leave_jitted_hook_save_exc = self._gen_leave_jitted_hook_code(True)
self._leave_jitted_hook = self._gen_leave_jitted_hook_code(False)
@@ -352,6 +440,7 @@
mem[j] = self.EMPTY_LOC
j += 1
i += 1
+ # XXX 64 bit adjustment needed
mem[j] = chr(0xFF)
@@ -427,8 +516,6 @@
path = self._leave_jitted_hook_save_exc
else:
path = self._leave_jitted_hook
- self.mc.trap()
- #self.mc.ba(path)
self.branch_abs(path)
return memaddr
diff --git a/pypy/jit/backend/ppc/ppcgen/regalloc.py b/pypy/jit/backend/ppc/ppcgen/regalloc.py
--- a/pypy/jit/backend/ppc/ppcgen/regalloc.py
+++ b/pypy/jit/backend/ppc/ppcgen/regalloc.py
@@ -26,7 +26,7 @@
return "<TempPtr at %s>" % (id(self),)
class PPCRegisterManager(RegisterManager):
- all_regs = r.ALL_REGS[:-1]
+ all_regs = r.MANAGED_REGS
box_types = None # or a list of acceptable types
no_lower_byte_regs = all_regs
save_around_call_regs = r.VOLATILES
diff --git a/pypy/jit/backend/ppc/ppcgen/register.py b/pypy/jit/backend/ppc/ppcgen/register.py
--- a/pypy/jit/backend/ppc/ppcgen/register.py
+++ b/pypy/jit/backend/ppc/ppcgen/register.py
@@ -13,3 +13,8 @@
SPP = r31
SP = r1
RES = r3
+
+MANAGED_REGS = [r2, r3, r4, r5, r6, r7, r8, r9, r10,
+ r11, r12, r13, r14, r15, r16, r17, r18,
+ r19, r20, r21, r22, r23, r24, r25, r26,
+ r27, r28, r29, r30]
diff --git a/pypy/jit/backend/ppc/ppcgen/test/test_helper.py b/pypy/jit/backend/ppc/ppcgen/test/test_helper.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/ppc/ppcgen/test/test_helper.py
@@ -0,0 +1,25 @@
+from pypy.jit.backend.ppc.ppcgen.helper.assembler import (encode32, decode32)
+ #encode64, decode64)
+
+def test_encode32():
+ mem = [None]*4
+ encode32(mem, 0, 1234567)
+ assert ''.join(mem) == '\x00\x12\xd6\x87'
+ mem = [None]*4
+ encode32(mem, 0, 983040)
+ assert ''.join(mem) == '\x00\x0F\x00\x00'
+
+def test_decode32():
+ mem = list('\x00\x12\xd6\x87')
+ assert decode32(mem, 0) == 1234567
+ mem = list('\x00\x0F\x00\x00')
+ assert decode32(mem, 0) == 983040
+ mem = list("\x00\x00\x00\x03")
+ assert decode32(mem, 0) == 3
+
+def test_encode32_and_decode32():
+ mem = [None] * 4
+ for val in [1, 45654, -456456, 123, 99999]:
+ encode32(mem, 0, val)
+ assert decode32(mem, 0) == val
+
diff --git a/pypy/jit/backend/ppc/runner.py b/pypy/jit/backend/ppc/runner.py
--- a/pypy/jit/backend/ppc/runner.py
+++ b/pypy/jit/backend/ppc/runner.py
@@ -102,7 +102,7 @@
addr = looptoken.ppc_code
func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr)
fail_index = self._execute_call(func)
- return self.saved_descr[fail_index]
+ return self.get_fail_descr_from_number(fail_index)
def _execute_call(self, func):
prev_interpreter = None
diff --git a/pypy/jit/backend/ppc/test/test_runner.py b/pypy/jit/backend/ppc/test/test_runner.py
--- a/pypy/jit/backend/ppc/test/test_runner.py
+++ b/pypy/jit/backend/ppc/test/test_runner.py
@@ -5,7 +5,7 @@
pass
class TestPPC(LLtypeBackendTest):
-
- def setup_method(self, method):
- self.cpu = PPC_64_CPU(rtyper=None, stats=FakeStats())
- self.cpu.setup_once()
+
+ def setup_class(cls):
+ cls.cpu = PPC_64_CPU(rtyper=None, stats=FakeStats())
+ cls.cpu.setup_once()
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -155,7 +155,7 @@
i1 = BoxInt()
i2 = BoxInt()
looptoken = LoopToken()
- operations = [
+ operations = [
ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr(2)),
More information about the pypy-commit
mailing list