[pypy-svn] r78592 - in pypy/branch/arm-backend/pypy/jit/backend/arm: . helper
david at codespeak.net
david at codespeak.net
Sun Oct 31 13:01:36 CET 2010
Author: david
Date: Sun Oct 31 13:01:34 2010
New Revision: 78592
Added:
pypy/branch/arm-backend/pypy/jit/backend/arm/helper/
pypy/branch/arm-backend/pypy/jit/backend/arm/helper/__init__.py
pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py
Modified:
pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py
pypy/branch/arm-backend/pypy/jit/backend/arm/instructions.py
pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py
Log:
Implement unary int operations and perform some refactoring on opassembler
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 31 13:01:34 2010
@@ -12,12 +12,14 @@
from pypy.rpython.lltypesystem import lltype, rffi, llmemory
from pypy.jit.backend.arm.opassembler import (GuardOpAssembler,
IntOpAsslember,
- OpAssembler)
+ OpAssembler,
+ UnaryIntOpAssembler)
# XXX Move to llsupport
from pypy.jit.backend.x86.support import values_array
-class AssemblerARM(GuardOpAssembler, IntOpAsslember, OpAssembler):
+class AssemblerARM(GuardOpAssembler, IntOpAsslember,
+ OpAssembler, UnaryIntOpAssembler):
def __init__(self, cpu, failargs_limit=1000):
self.mc = ARMv7Builder()
@@ -182,7 +184,6 @@
opnum = op.getopnum()
fcond = self.operations[opnum](self, op, regalloc, fcond)
self.gen_func_epilog()
- print inputargs, operations
if self._debug_asm:
self._dump_trace('loop.asm')
print 'Done assembling'
@@ -210,6 +211,10 @@
def _dump_trace(self, name):
self.mc._dump_trace(name)
+ def _check_imm_arg(self, arg, size=0xFF):
+ #XXX check ranges for different operations
+ return isinstance(arg, ConstInt) and arg.getint() <= size and arg.getint() > 0
+
def patch_trace(self, faildescr, bridge_addr):
# XXX make sure there is enough space at patch target
fcond = faildescr._arm_guard_cond
Added: pypy/branch/arm-backend/pypy/jit/backend/arm/helper/__init__.py
==============================================================================
Added: pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py
==============================================================================
--- (empty file)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py Sun Oct 31 13:01:34 2010
@@ -0,0 +1,82 @@
+from pypy.jit.backend.arm import conditions as c
+from pypy.jit.backend.arm import registers as r
+from pypy.jit.metainterp.history import ConstInt, BoxInt, Box
+
+def gen_emit_op_unary_cmp(true_cond, false_cond):
+ def f(self, op, regalloc, fcond):
+ arg = op.getarg(0)
+ reg = self._put_in_reg(arg, regalloc)
+ res = regalloc.try_allocate_reg(op.result)
+ self.mc.CMP_ri(reg.value, 0)
+ self.mc.MOV_ri(res.value, 1, true_cond)
+ self.mc.MOV_ri(res.value, 0, false_cond)
+ regalloc.possibly_free_var(reg)
+ regalloc.possibly_free_var(res)
+ return fcond
+ return f
+
+def gen_emit_op_ri(opname, imm_size=0xFF, commutative=True):
+ def f(self, op, regalloc, fcond):
+ ri_op = getattr(self.mc, '%s_ri' % opname)
+ rr_op = getattr(self.mc, '%s_rr' % opname)
+
+ arg0 = op.getarg(0)
+ arg1 = op.getarg(1)
+ res = regalloc.try_allocate_reg(op.result)
+ if (commutative
+ and self._check_imm_arg(arg0, imm_size)
+ and not isinstance(arg1, ConstInt)):
+ reg = regalloc.try_allocate_reg(arg1)
+ ri_op(res.value, reg.value, imm=arg0.getint(), cond=fcond)
+ elif self._check_imm_arg(arg1, imm_size) and not isinstance(arg0, ConstInt):
+ reg = regalloc.try_allocate_reg(arg0)
+ ri_op(res.value, reg.value, imm=arg1.getint(), cond=fcond)
+ else:
+ reg = self._put_in_reg(arg0, regalloc)
+ reg2 = self._put_in_reg(arg1, regalloc)
+ rr_op(res.value, reg.value, reg2.value)
+ regalloc.possibly_free_var(reg2)
+
+ regalloc.possibly_free_var(res)
+ regalloc.possibly_free_var(reg)
+ return fcond
+ return f
+
+def gen_emit_op_by_helper_call(opname):
+ def f(self, op, regalloc, fcond):
+ arg1 = regalloc.make_sure_var_in_reg(op.getarg(0), selected_reg=r.r0)
+ arg2 = regalloc.make_sure_var_in_reg(op.getarg(1), selected_reg=r.r1)
+ assert arg1 == r.r0
+ assert arg2 == r.r1
+ res = regalloc.try_allocate_reg(op.result)
+ getattr(self.mc, opname)(fcond)
+ self.mc.MOV_rr(res.value, r.r0.value, cond=fcond)
+ regalloc.possibly_free_vars_for_op(op)
+ return fcond
+ return f
+
+def gen_emit_cmp_op(condition, inverse=False):
+ def f(self, op, regalloc, fcond):
+ assert fcond == c.AL
+ if not inverse:
+ arg0 = op.getarg(0)
+ arg1 = op.getarg(1)
+ else:
+ arg0 = op.getarg(1)
+ arg1 = op.getarg(0)
+ res = regalloc.try_allocate_reg(op.result)
+ # XXX consider swapping argumentes if arg0 is const
+ if self._check_imm_arg(arg1) and not isinstance(arg0, ConstInt):
+ reg = regalloc.try_allocate_reg(arg0)
+ self.mc.CMP_ri(reg.value, imm=arg1.getint(), cond=fcond)
+ else:
+ reg = self._put_in_reg(arg0, regalloc)
+ reg2 = self._put_in_reg(arg1, regalloc)
+ self.mc.CMP_rr(reg.value, reg2.value)
+ regalloc.possibly_free_var(reg2)
+
+ inv = c.get_opposite_of(condition)
+ self.mc.MOV_ri(res.value, 1, cond=condition)
+ self.mc.MOV_ri(res.value, 0, cond=inv)
+ return condition
+ return f
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 31 13:01:34 2010
@@ -32,7 +32,8 @@
#'RRX_ri': {'op1':0x1A, 'op2':0, 'op3':0x3, 'op2cond':'0', 'result':False, 'base':True},
'ROR_ri': {'op1':0x1A, 'op2':0x0, 'op3':0x3, 'op2cond':'!0', 'result':True, 'base':False},
#BIC
- #MVN
+ 'MVN_rr': {'op1':0x1E, 'op2':0x0, 'op3':0x0, 'result':True, 'base':False},
+
}
data_proc_reg_shift_reg = {
Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py (original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py Sun Oct 31 13:01:34 2010
@@ -3,6 +3,10 @@
from pypy.jit.backend.arm import registers as r
from pypy.jit.backend.arm.arch import (WORD, FUNC_ALIGN, arm_int_div,
arm_int_div_sign, arm_int_mod_sign, arm_int_mod)
+
+from pypy.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call,
+ gen_emit_op_unary_cmp,
+ gen_emit_op_ri, gen_emit_cmp_op)
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
@@ -12,95 +16,31 @@
from pypy.rpython.annlowlevel import llhelper
from pypy.rpython.lltypesystem import lltype, rffi, llmemory
-def gen_emit_op_ri(opname, imm_size=0xFF, commutative=True):
- def f(self, op, regalloc, fcond):
- ri_op = getattr(self.mc, '%s_ri' % opname)
- rr_op = getattr(self.mc, '%s_rr' % opname)
-
- arg0 = op.getarg(0)
- arg1 = op.getarg(1)
- res = regalloc.try_allocate_reg(op.result)
- if (commutative
- and self._check_imm_arg(arg0, imm_size)
- and not isinstance(arg1, ConstInt)):
- reg = regalloc.try_allocate_reg(arg1)
- ri_op(res.value, reg.value, imm=arg0.getint(), cond=fcond)
- elif self._check_imm_arg(arg1, imm_size) and not isinstance(arg0, ConstInt):
- reg = regalloc.try_allocate_reg(arg0)
- ri_op(res.value, reg.value, imm=arg1.getint(), cond=fcond)
- else:
- reg = self._put_in_reg(arg0, regalloc)
- reg2 = self._put_in_reg(arg1, regalloc)
- rr_op(res.value, reg.value, reg2.value)
- regalloc.possibly_free_var(reg2)
-
- regalloc.possibly_free_var(res)
- regalloc.possibly_free_var(reg)
- return fcond
- return f
-
-def gen_emit_op_by_helper_call(opname):
- def f(self, op, regalloc, fcond):
- arg1 = regalloc.make_sure_var_in_reg(op.getarg(0), selected_reg=r.r0)
- arg2 = regalloc.make_sure_var_in_reg(op.getarg(1), selected_reg=r.r1)
- assert arg1 == r.r0
- assert arg2 == r.r1
- res = regalloc.try_allocate_reg(op.result)
- getattr(self.mc, opname)(fcond)
- self.mc.MOV_rr(res.value, r.r0.value, cond=fcond)
- regalloc.possibly_free_vars_for_op(op)
- return fcond
- return f
-
-def gen_emit_cmp_op(condition, inverse=False):
- def f(self, op, regalloc, fcond):
- assert fcond == c.AL
- if not inverse:
- arg0 = op.getarg(0)
- arg1 = op.getarg(1)
- else:
- arg0 = op.getarg(1)
- arg1 = op.getarg(0)
- res = regalloc.try_allocate_reg(op.result)
- # XXX consider swapping argumentes if arg0 is const
- if self._check_imm_arg(arg1) and not isinstance(arg0, ConstInt):
- reg = regalloc.try_allocate_reg(arg0)
- self.mc.CMP_ri(reg.value, imm=arg1.getint(), cond=fcond)
- else:
- reg = self._put_in_reg(arg0, regalloc)
- reg2 = self._put_in_reg(arg1, regalloc)
- self.mc.CMP_rr(reg.value, reg2.value)
- regalloc.possibly_free_var(reg2)
-
- inv = c.get_opposite_of(condition)
- self.mc.MOV_ri(res.value, 1, cond=condition)
- self.mc.MOV_ri(res.value, 0, cond=inv)
- return condition
- return f
-
class IntOpAsslember(object):
_mixin_ = True
- # XXX support constants larger than imm
-
def emit_op_int_add(self, op, regalloc, fcond):
# assuming only one argument is constant
res = regalloc.try_allocate_reg(op.result)
- if isinstance(op.getarg(0), ConstInt) or isinstance(op.getarg(1), ConstInt):
- if isinstance(op.getarg(1), ConstInt):
- reg = regalloc.try_allocate_reg(op.getarg(0))
- arg1 = op.getarg(1)
- elif isinstance(op.getarg(0), ConstInt):
- reg = regalloc.try_allocate_reg(op.getarg(1))
- arg1 = op.getarg(0)
+ a0 = op.getarg(0)
+ a1 = op.getarg(1)
+ imm_a0 = isinstance(a0, ConstInt) and (a0.getint() <= 0xFF or -1 * a0.getint() <= 0xFF)
+ imm_a1 = isinstance(a1, ConstInt) and (a1.getint() <= 0xFF or -1 * a1.getint() <= 0xFF)
+ if imm_a0 or imm_a1:
+ if imm_a1:
+ reg = regalloc.try_allocate_reg(a0)
+ arg1 = a1
+ elif imm_a0:
+ reg = regalloc.try_allocate_reg(a1)
+ arg1 = a0
value = arg1.getint()
if value < 0:
self.mc.SUB_ri(res.value, reg.value, -1 * value)
else:
self.mc.ADD_ri(res.value, reg.value, value)
else:
- r1 = regalloc.try_allocate_reg(op.getarg(0))
- r2 = regalloc.try_allocate_reg(op.getarg(1))
+ r1 = regalloc.try_allocate_reg(a0)
+ r2 = regalloc.try_allocate_reg(a1)
self.mc.ADD_rr(res.value, r1.value, r2.value)
regalloc.possibly_free_vars_for_op(op)
@@ -109,17 +49,21 @@
def emit_op_int_sub(self, op, regalloc, fcond):
# assuming only one argument is constant
res = regalloc.try_allocate_reg(op.result)
- if isinstance(op.getarg(0), ConstInt) or isinstance(op.getarg(1), ConstInt):
- if isinstance(op.getarg(1), ConstInt):
- reg = regalloc.try_allocate_reg(op.getarg(0))
- value = op.getarg(1).getint()
+ a0 = op.getarg(0)
+ a1 = op.getarg(1)
+ imm_a0 = isinstance(a0, ConstInt) and (a0.getint() <= 0xFF or -1 * a0.getint() <= 0xFF)
+ imm_a1 = isinstance(a1, ConstInt) and (a1.getint() <= 0xFF or -1 * a1.getint() <= 0xFF)
+ if imm_a0 or imm_a1:
+ if imm_a1:
+ reg = self._put_in_reg(a0, regalloc)
+ value = a1.getint()
if value < 0:
self.mc.ADD_ri(res.value, reg.value, -1 * value)
else:
self.mc.SUB_ri(res.value, reg.value, value)
- elif isinstance(op.getarg(0), ConstInt):
- reg = regalloc.try_allocate_reg(op.getarg(1))
- value = op.getarg(0).getint()
+ elif imm_a0:
+ reg = self._put_in_reg(a1, regalloc)
+ value = a0.getint()
if value < 0:
self.mc.ADD_ri(res.value, reg.value, -1 * value)
self.mc.MVN_rr(res.value, res.value)
@@ -127,8 +71,8 @@
# reverse substract ftw
self.mc.RSB_ri(res.value, reg.value, value)
else:
- r1 = regalloc.try_allocate_reg(op.getarg(0))
- r2 = regalloc.try_allocate_reg(op.getarg(1))
+ r1 = regalloc.try_allocate_reg(a0)
+ r2 = regalloc.try_allocate_reg(a1)
self.mc.SUB_rr(res.value, r1.value, r2.value)
regalloc.possibly_free_vars_for_op(op)
@@ -177,10 +121,32 @@
emit_op_uint_ge = gen_emit_cmp_op(c.LS, inverse=True)
- def _check_imm_arg(self, arg, size=0xFF):
- #XXX check ranges for different operations
- return isinstance(arg, ConstInt) and arg.getint() <= size and arg.getint() > 0
+class UnaryIntOpAssembler(object):
+ emit_op_int_is_true = gen_emit_op_unary_cmp(c.NE, c.EQ)
+ emit_op_int_is_zero = gen_emit_op_unary_cmp(c.EQ, c.NE)
+
+ def emit_op_int_invert(self, op, regalloc, fcond):
+ arg = op.getarg(0)
+ reg = self._put_in_reg(arg, regalloc)
+ res = regalloc.try_allocate_reg(op.result)
+
+ self.mc.MVN_rr(res.value, reg.value)
+ regalloc.possibly_free_var(reg)
+ regalloc.possibly_free_var(res)
+ return fcond
+
+ #XXX check for a better way of doing this
+ def emit_op_int_neg(self, op, regalloc, fcond):
+ arg = op.getarg(0)
+ reg = self._put_in_reg(arg, regalloc)
+ reg2 = self._put_in_reg(ConstInt(-1), regalloc)
+ res = regalloc.try_allocate_reg(op.result)
+ self.mc.MUL(res.value, reg.value, reg2.value)
+ regalloc.possibly_free_var(reg)
+ regalloc.possibly_free_var(reg2)
+ regalloc.possibly_free_var(res)
+ return fcond
class GuardOpAssembler(object):
_mixin_ = True
More information about the Pypy-commit
mailing list