[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