[pypy-svn] r78248 - in pypy/branch/arm-backend/pypy/jit/backend/arm: . test
david at codespeak.net
david at codespeak.net
Sun Oct 24 14:37:18 CEST 2010
Author: david
Date: Sun Oct 24 14:37:16 2010
New Revision: 78248
Modified:
pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py
pypy/branch/arm-backend/pypy/jit/backend/arm/codebuilder.py
pypy/branch/arm-backend/pypy/jit/backend/arm/instructions.py
pypy/branch/arm-backend/pypy/jit/backend/arm/runner.py
pypy/branch/arm-backend/pypy/jit/backend/arm/test/support.py
pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py
Log:
Refactor guards and finish res op to leave using common code.
Start implementig bridges based on refactored code.
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py Sun Oct 24 14:37:16 2010
@@ -1,11 +1,14 @@
-from pypy.jit.backend.arm.codebuilder import ARMv7Builder
-from pypy.jit.backend.arm import registers as r
from pypy.jit.backend.arm import conditions as c
-from pypy.jit.backend.llsupport.regalloc import compute_vars_longevity
+from pypy.jit.backend.arm import registers as r
+from pypy.jit.backend.arm.arch import WORD, FUNC_ALIGN
+from pypy.jit.backend.arm.codebuilder import ARMv7Builder, ARMv7InMemoryBuilder
from pypy.jit.backend.arm.regalloc import ARMRegisterManager
+from pypy.jit.backend.llsupport.regalloc import compute_vars_longevity
+from pypy.jit.metainterp.history import ConstInt, Box, BasicFailDescr
from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.metainterp.history import ConstInt, Box
-from pypy.rpython.lltypesystem import lltype
+from pypy.rlib import rgc
+from pypy.rpython.annlowlevel import llhelper
+from pypy.rpython.lltypesystem import lltype, rffi, llmemory
# XXX Move to llsupport
from pypy.jit.backend.x86.support import values_array
@@ -17,15 +20,132 @@
self.cpu = cpu
self.input_arg_boxes_int = values_array(lltype.Signed, failargs_limit) # merge with fail_boxes_int later
self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
+ self._debug_asm = True
+
+ self._gen_exit_path()
+ self.align()
+ self.mc._start_addr = self.mc.curraddr()
+
+
+ def setup_failure_recovery(self):
+
+ @rgc.no_collect
+ def failure_recovery_func(mem_loc, stackloc):
+ """mem_loc is a structure in memory describing where the values for
+ the failargs are stored. stacklock is the address of the stack
+ section where the registers were saved."""
+ enc = rffi.cast(rffi.CCHARP, mem_loc)
+ stack = rffi.cast(rffi.CCHARP, stackloc)
+ return self.decode_registers_and_descr(enc, stack)
+
+ self.failure_recovery_func = failure_recovery_func
+
+ @rgc.no_collect
+ def decode_registers_and_descr(self, enc, stack):
+ """Decode locations encoded in memory at enc and write the values to
+ the failboxes.
+ Registers are saved on the stack
+ XXX Rest to follow"""
+ i = -1
+ while(True):
+ i += 1
+ r = enc[i]
+ if r == '\xFF':
+ break
+ reg = ord(enc[i])
+ self.fail_boxes_int.setitem(i, self.decode32(stack, reg*WORD))
+ assert enc[i] == '\xFF'
+ descr = self.decode32(enc, i+1)
+ return descr
+
+ def decode32(self, mem, index):
+ highval = ord(mem[index+3])
+ if highval >= 128:
+ highval -= 256
+ return (ord(mem[index])
+ | ord(mem[index+1]) << 8
+ | ord(mem[index+2]) << 16
+ | highval << 24)
+
+ def encode32(self, 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)
+
+ def _gen_exit_path(self):
+ self.setup_failure_recovery()
+ functype = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+ decode_registers_addr = llhelper(functype, self.failure_recovery_func)
+ self.mc.PUSH(range(12)) # registers r0 .. r11
+ self.mc.MOV_rr(r.r0, r.lr) # move mem block address, to r0 to pass as
+ # parameter to next procedure call
+ self.mc.MOV_rr(r.r1, r.sp) # pass the current stack pointer as second param
+ self.mc.gen_load_int(r.r2, rffi.cast(lltype.Signed, decode_registers_addr))
+ self.mc.gen_load_int(r.lr, self.mc.curraddr()+self.mc.size_of_gen_load_int+WORD)
+ self.mc.MOV_rr(r.pc, r.r2)
+ self.mc.MOV_rr(r.ip, r.r0)
+ self.mc.LDM(r.sp, range(12), w=1) # XXX Replace with POP instr. someday
+
+ self.mc.MOV_rr(r.r0, r.ip)
+
+ self.gen_func_epilog()
+
+ def _gen_path_to_exit_path(self, op, args, regalloc, fcond=c.AL):
+ box = Box()
+ reg = regalloc.try_allocate_reg(box)
+ # XXX free this memory
+ mem = lltype.malloc(rffi.CArray(lltype.Char), len(args)+5, flavor='raw')
+ for i in range(len(args)):
+ curreg = regalloc.try_allocate_reg(args[i])
+ mem[i] = chr(curreg)
+ i = len(args)
+ mem[i] = chr(0xFF)
+ memaddr = rffi.cast(lltype.Signed, mem)
+
+
+ n = self.cpu.get_fail_descr_number(op.getdescr())
+ self.encode32(mem, i+1, n)
+ self.mc.gen_load_int(r.lr, memaddr, cond=fcond)
+ self.mc.gen_load_int(reg, self.mc.baseaddr(), cond=fcond)
+ self.mc.MOV_rr(r.pc, reg, cond=fcond)
+
+ op.getdescr()._arm_guard_reg = reg
+ return memaddr
+
+ def align(self):
+ while(self.mc.curraddr() % FUNC_ALIGN != 0):
+ self.mc.writechar(chr(0))
+
+ def gen_func_epilog(self,cond=c.AL):
+ self.mc.LDM(r.sp, r.callee_restored_registers, cond=cond, w=1)
+
+ def gen_func_prolog(self):
+ self.mc.PUSH(r.callee_saved_registers)
+
+ def gen_bootstrap_code(self, inputargs, regalloc):
+ for i in range(len(inputargs)):
+ reg = regalloc.try_allocate_reg(inputargs[i])
+ addr = self.fail_boxes_int.get_addr_for_num(i)
+ self.mc.gen_load_int(reg, addr)
+ self.mc.LDR_ri(reg, reg)
+
+ def gen_bridge_bootstrap_code(self, inputargs, regalloc):
+ for i in range(len(inputargs)):
+ reg = regalloc.try_allocate_reg(inputargs[i])
+ addr = self.fail_boxes_int.get_addr_for_num(i)
+ self.mc.gen_load_int(reg, addr)
+ self.mc.LDR_ri(reg, reg)
+ # cpu interface
def assemble_loop(self, inputargs, operations, looptoken):
- assert len(inputargs) == 1
longevity = compute_vars_longevity(inputargs, operations)
regalloc = ARMRegisterManager(longevity, assembler=self.mc)
+ loop_start=self.mc.curraddr()
self.gen_func_prolog()
self.gen_bootstrap_code(inputargs, regalloc)
loop_head=self.mc.curraddr()
- looptoken._arm_bootstrap_code = self.mc.baseaddr()
+ looptoken._arm_bootstrap_code = loop_start
looptoken._arm_loop_code = loop_head
looptoken._temp_inputargs = inputargs#XXX remove
fcond=c.AL
@@ -33,12 +153,42 @@
opnum = op.getopnum()
fcond = self.operations[opnum](self, op, regalloc, fcond)
self.gen_func_epilog()
- f = open('loop.asm', 'wb')
- for i in range(self.mc._pos):
- f.write(self.mc._data[i])
- f.close()
+ if self._debug_asm:
+ self._dump_trace('loop.asm')
print 'Done assembling'
+ def assemble_bridge(self, faildescr, inputargs, operations):
+ # XXX need to restore args here
+ longevity = compute_vars_longevity(inputargs, operations)
+ regalloc = ARMRegisterManager(longevity, assembler=self.mc)
+ bridge_head = self.mc.curraddr()
+ self.gen_bridge_bootstrap_code(inputargs, regalloc)
+ fcond = c.AL
+ for op in operations:
+ opnum = op.getopnum()
+ fcond = self.operations[opnum](self, op, regalloc, fcond)
+ self.gen_func_epilog()
+ print 'Done building bridges'
+ self.patch_trace(faildescr, bridge_head)
+ print 'Done patching trace'
+ if self._debug_asm:
+ self._dump_trace('bridge.asm')
+
+
+ def _dump_trace(self, name):
+ self.mc._dump_trace(name)
+
+ def patch_trace(self, faildescr, bridge_addr):
+ # XXX make sure there is enough space at patch target
+ fcond = faildescr._arm_guard_cond
+ b = ARMv7InMemoryBuilder(faildescr._arm_guard_code, faildescr._arm_guard_code+100)
+ reg = faildescr._arm_guard_reg
+ b.gen_load_int(reg, bridge_addr, fcond)
+ b.MOV_rr(r.pc, reg, cond=fcond)
+
+
+ # Resoperations
+
def emit_op_jump(self, op, regalloc, fcond):
tmp = Box()
tmpreg = regalloc.try_allocate_reg(tmp)
@@ -49,13 +199,13 @@
# XXX only if every value is in a register
self.mc.MOV_rr(inpreg, reg)
loop_code = op.getdescr()._arm_loop_code
- self.gen_load_int(tmpreg, loop_code)
+ self.mc.gen_load_int(tmpreg, loop_code)
self.mc.MOV_rr(r.pc, tmpreg)
regalloc.possibly_free_var(tmpreg)
return fcond
def emit_op_finish(self, op, regalloc, fcond):
- self.gen_write_back(op, op.getarglist(), regalloc, fcond)
+ self._gen_path_to_exit_path(op, op.getarglist(), regalloc, fcond)
return fcond
def emit_op_int_le(self, op, regalloc, fcond):
@@ -74,46 +224,14 @@
def emit_op_guard_true(self, op, regalloc, fcond):
assert fcond == c.GT
- self.gen_write_back(op, op.getfailargs(), regalloc, fcond)
- self.gen_func_epilog(cond=fcond)
+ descr = op.getdescr()
+ assert isinstance(descr, BasicFailDescr)
+ memaddr = self._gen_path_to_exit_path(op, op.getfailargs(), regalloc, fcond)
+ descr._failure_recovery_code = memaddr
+ descr._arm_guard_code = self.mc.curraddr()
+ descr._arm_guard_cond = fcond
return c.AL
- def gen_write_back(self, op, args, regalloc, fcond):
- temp = Box()
- temp_reg = regalloc.try_allocate_reg(temp)
- for i in range(len(args)):
- reg = regalloc.try_allocate_reg(args[i])
- addr = self.fail_boxes_int.get_addr_for_num(i)
- self.gen_load_int(temp_reg, addr, cond=fcond)
- self.mc.STR_ri(reg, temp_reg, cond=fcond)
-
- regalloc.possibly_free_var(temp_reg)
- n = self.cpu.get_fail_descr_number(op.getdescr())
- self.mc.MOV_ri(r.r0, n, cond=fcond)
-
- def gen_func_epilog(self,cond=c.AL):
- self.mc.LDM(r.sp, r.callee_restored_registers, cond=cond)
-
- def gen_func_prolog(self):
- self.mc.PUSH(r.callee_saved_registers)
-
- def gen_bootstrap_code(self, inputargs, regalloc):
- for i in range(len(inputargs)):
- reg = regalloc.try_allocate_reg(inputargs[i])
- addr = self.input_arg_boxes_int.get_addr_for_num(i)
- self.gen_load_int(reg, addr)
- self.mc.LDR_ri(reg, reg)
-
- def gen_load_int(self, reg, value, cond=c.AL):
- assert reg != r.ip, 'ip is used to load int'
- self.mc.MOV_ri(reg, (value & 0xFF), cond=cond)
-
- for offset in range(8, 25, 8):
- self.mc.MOV_ri(r.ip, (value >> offset) & 0xFF, cond=cond)
- self.mc.ORR_rr(reg, reg, r.ip, offset, cond=cond)
-
-
-
def make_operation_list():
def notimplemented(self, op, regalloc, fcond):
raise NotImplementedError
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/codebuilder.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/codebuilder.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/codebuilder.py Sun Oct 24 14:37:16 2010
@@ -1,22 +1,29 @@
-import conditions as cond
-import registers as reg
-from pypy.rlib.rmmap import alloc
-from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.jit.backend.arm import conditions as cond
+from pypy.jit.backend.arm import registers as reg
+from pypy.jit.backend.arm.arch import WORD
from pypy.jit.backend.arm.instruction_builder import define_instructions
-class ARMv7Builder(object):
+from pypy.rlib.rmmap import alloc, PTR
+from pypy.rpython.lltypesystem import lltype, rffi
- def __init__(self):
- self._data = alloc(1024)
+class AbstractARMv7Builder(object):
+ def _init(self, data, map_size):
+ self._data = data
+ self._size = map_size
self._pos = 0
+ def _dump_trace(self, name):
+ f = open('output/%s' % name, 'wb')
+ for i in range(self._pos):
+ f.write(self._data[i])
+ f.close()
+
def PUSH(self, regs, cond=cond.AL):
assert reg.sp not in regs
instr = self._encode_reg_list(cond << 28 | 0x92D << 16, regs)
self.write32(instr)
- def LDM(self, rn, regs, cond=cond.AL):
- w = 0
+ def LDM(self, rn, regs, w=0, cond=cond.AL):
instr = cond << 28 | 0x89 << 20 | w << 21 | (rn & 0xFF) << 16
instr = self._encode_reg_list(instr, regs)
self.write32(instr)
@@ -58,4 +65,30 @@
def curraddr(self):
return self.baseaddr() + self._pos
-define_instructions(ARMv7Builder)
+ size_of_gen_load_int = 7 * WORD
+ def gen_load_int(self, r, value, cond=cond.AL):
+ assert r != reg.ip, 'ip is used to load int'
+ self.MOV_ri(r, (value & 0xFF), cond=cond)
+
+ for offset in range(8, 25, 8):
+ t = (value >> offset) & 0xFF
+ #if t == 0:
+ # continue
+ self.MOV_ri(reg.ip, t, cond=cond)
+ self.ORR_rr(r, r, reg.ip, offset, cond=cond)
+
+class ARMv7InMemoryBuilder(AbstractARMv7Builder):
+ def __init__(self, start, end):
+ map_size = end - start
+ data = rffi.cast(PTR, start)
+ self._init(data, map_size)
+
+class ARMv7Builder(AbstractARMv7Builder):
+
+ def __init__(self):
+ map_size = 1024
+ data = alloc(1024)
+ self._pos = 0
+ self._init(data, map_size)
+
+define_instructions(AbstractARMv7Builder)
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/instructions.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/instructions.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/instructions.py Sun Oct 24 14:37:16 2010
@@ -56,3 +56,18 @@
supervisor_and_coproc = {
'MCR': {'op1': 0x20, 'op': 1, 'rn':0, 'coproc':0},
}
+
+block_data = {
+ 'STMDA': {'op': 0x0},
+ 'LDMDA': {'op': 0x1},
+ 'STMIA': {'op': 0x8},
+ 'LDMDB': {'op': 0x11},
+ 'STMIB': {'op': 0x18},
+ 'LDMIB': {'op': 0x19},
+ 'STM': {'op': 0x4},
+ 'LDM': {'op': 0x5},
+}
+branch = {
+ 'B': {'op': 0x20},
+ 'BL': {'op': 0x30},
+}
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/runner.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/runner.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/runner.py Sun Oct 24 14:37:16 2010
@@ -18,6 +18,9 @@
def compile_loop(self, inputargs, operations, looptoken):
self.assembler.assemble_loop(inputargs, operations, looptoken)
+ def compile_bridge(self, faildescr, inputargs, operations):
+ self.assembler.assemble_bridge(faildescr, inputargs, operations)
+
def set_future_value_int(self, index, intvalue):
self.assembler.input_arg_boxes_int.setitem(index, intvalue)
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/test/support.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/test/support.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/test/support.py Sun Oct 24 14:37:16 2010
@@ -10,7 +10,7 @@
def run_asm(asm):
BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed)
- addr = asm.mc.baseaddr()
+ addr = asm.mc._start_addr
assert addr % 8 == 0
func = rffi.cast(lltype.Ptr(BOOTSTRAP_TP), addr)
return func()
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py Sun Oct 24 14:37:16 2010
@@ -1,9 +1,14 @@
-from pypy.jit.backend.arm import registers as r
from pypy.jit.backend.arm import conditions as c
+from pypy.jit.backend.arm import registers as r
+from pypy.jit.backend.arm.arch import WORD
from pypy.jit.backend.arm.assembler import AssemblerARM
+from pypy.jit.backend.arm.codebuilder import ARMv7InMemoryBuilder
from pypy.jit.backend.arm.test.support import skip_unless_arm, run_asm
from pypy.jit.metainterp.resoperation import rop
+from pypy.rpython.annlowlevel import llhelper
+from pypy.rpython.lltypesystem import lltype, rffi, llmemory
+
skip_unless_arm()
class TestRunningAssembler():
@@ -16,19 +21,19 @@
def test_load_small_int_to_reg(self):
self.a.gen_func_prolog()
- self.a.gen_load_int(r.r0, 123)
+ self.a.mc.gen_load_int(r.r0, 123)
self.a.gen_func_epilog()
assert run_asm(self.a) == 123
def test_load_medium_int_to_reg(self):
self.a.gen_func_prolog()
- self.a.gen_load_int(r.r0, 0xBBD7)
+ self.a.mc.gen_load_int(r.r0, 0xBBD7)
self.a.gen_func_epilog()
assert run_asm(self.a) == 48087
def test_load_int_to_reg(self):
self.a.gen_func_prolog()
- self.a.gen_load_int(r.r0, 0xFFFFFF85)
+ self.a.mc.gen_load_int(r.r0, 0xFFFFFF85)
self.a.gen_func_epilog()
assert run_asm(self.a) == -123
@@ -43,14 +48,14 @@
def test_sub(self):
self.a.gen_func_prolog()
- self.a.gen_load_int(r.r1, 123456)
+ self.a.mc.gen_load_int(r.r1, 123456)
self.a.mc.SUB_ri(r.r0, r.r1, 123)
self.a.gen_func_epilog()
assert run_asm(self.a) == 123333
def test_cmp(self):
self.a.gen_func_prolog()
- self.a.gen_load_int(r.r1, 22)
+ self.a.mc.gen_load_int(r.r1, 22)
self.a.mc.CMP(r.r1, 123)
self.a.mc.MOV_ri(r.r0, 1, c.LE)
self.a.mc.MOV_ri(r.r0, 0, c.GT)
@@ -59,7 +64,7 @@
def test_int_le_false(self):
self.a.gen_func_prolog()
- self.a.gen_load_int(r.r1, 2222)
+ self.a.mc.gen_load_int(r.r1, 2222)
self.a.mc.CMP(r.r1, 123)
self.a.mc.MOV_ri(r.r0, 1, c.LE)
self.a.mc.MOV_ri(r.r0, 0, c.GT)
@@ -73,7 +78,7 @@
self.a.mc.CMP(r.r1, 0) # z=0, z=1
self.a.mc.MOV_ri(r.r1, 0, cond=c.NE)
self.a.mc.MOV_ri(r.r1, 7, cond=c.EQ)
- self.a.gen_load_int(r.r4, loop_head, cond=c.NE)
+ self.a.mc.gen_load_int(r.r4, loop_head, cond=c.NE)
self.a.mc.MOV_rr(r.pc, r.r4, cond=c.NE)
self.a.mc.MOV_rr(r.r0, r.r1)
self.a.gen_func_epilog()
@@ -85,10 +90,25 @@
loop_head = self.a.mc.curraddr()
self.a.mc.ADD_ri(r.r1, r.r1, 1)
self.a.mc.CMP(r.r1, 9)
- self.a.gen_load_int(r.r4, loop_head, cond=c.NE)
+ self.a.mc.gen_load_int(r.r4, loop_head, cond=c.NE)
self.a.mc.MOV_rr(r.pc, r.r4, cond=c.NE)
self.a.mc.MOV_rr(r.r0, r.r1)
self.a.gen_func_epilog()
assert run_asm(self.a) == 9
+ def test_call_python_func(self):
+ functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
+ call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
+ self.a.gen_func_prolog()
+ self.a.mc.MOV_ri(r.r0, 123)
+ self.a.mc.gen_load_int(r.r1, call_addr)
+ self.a.mc.gen_load_int(r.lr, self.a.mc.curraddr()+self.a.mc.size_of_gen_load_int+WORD)
+ self.a.mc.MOV_rr(r.pc, r.r1)
+ self.a.gen_func_epilog()
+ assert run_asm(self.a) == 133
+
+def callme(inp):
+ i = inp + 10
+ return i
+
More information about the Pypy-commit
mailing list