[pypy-svn] r78438 - in pypy/branch/arm-backend/pypy/jit/backend/arm: . test

david at codespeak.net david at codespeak.net
Fri Oct 29 09:36:55 CEST 2010


Author: david
Date: Fri Oct 29 09:36:53 2010
New Revision: 78438

Modified:
   pypy/branch/arm-backend/pypy/jit/backend/arm/arch.py
   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/locations.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.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:
Implement int_mul, int_floordiv and int_mod operations.

- Added support to codebuilder to allocate new memory for instructions
- Implement int_div and int_mod as functions called from assembler, because doesn't provide instructions for them



Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/arch.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/arch.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/arch.py	Fri Oct 29 09:36:53 2010
@@ -1,2 +1,20 @@
+from pypy.rpython.lltypesystem import lltype
+
 FUNC_ALIGN=8
 WORD=4
+
+arm_int_div_sign = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+arm_int_mod_sign = arm_int_div_sign
+
+def arm_int_div(a, b):
+    return int(a/float(b))
+
+def arm_int_mod(a, b):
+    sign = 1
+    if a < 0:
+        a = -1 * a
+        sign = -1
+    if b < 0:
+        b = -1 * b
+    res = a % b
+    return sign * res

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	Fri Oct 29 09:36:53 2010
@@ -3,7 +3,7 @@
 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.arm.regalloc import ARMRegisterManager, ARMFrameManager
 from pypy.jit.backend.llsupport.regalloc import compute_vars_longevity
 from pypy.jit.metainterp.history import ConstInt, BoxInt, Box, BasicFailDescr
 from pypy.jit.metainterp.resoperation import rop
@@ -25,6 +25,7 @@
         self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
         self._debug_asm = True
 
+        self._exit_code_addr = self.mc.curraddr()
         self._gen_exit_path()
         self.align()
         self.mc._start_addr = self.mc.curraddr()
@@ -136,7 +137,7 @@
         n = self.cpu.get_fail_descr_number(op.getdescr())
         self.encode32(mem, j+1, n)
         self.mc.gen_load_int(r.lr.value, memaddr, cond=fcond)
-        self.mc.gen_load_int(reg.value, self.mc.baseaddr(), cond=fcond)
+        self.mc.gen_load_int(reg.value, self._exit_code_addr, cond=fcond)
         self.mc.MOV_rr(r.pc.value, reg.value, cond=fcond)
 
         # This register is used for patching when assembling a bridge
@@ -168,7 +169,7 @@
     # cpu interface
     def assemble_loop(self, inputargs, operations, looptoken):
         longevity = compute_vars_longevity(inputargs, operations)
-        regalloc = ARMRegisterManager(longevity, assembler=self.mc)
+        regalloc = ARMRegisterManager(longevity, assembler=self.mc, frame_manager=ARMFrameManager())
         self.align()
         loop_start=self.mc.curraddr()
         self.gen_func_prolog()
@@ -189,7 +190,7 @@
     def assemble_bridge(self, faildescr, inputargs, operations):
         enc = rffi.cast(rffi.CCHARP, faildescr._failure_recovery_code)
         longevity = compute_vars_longevity(inputargs, operations)
-        regalloc = ARMRegisterManager(longevity, assembler=self.mc)
+        regalloc = ARMRegisterManager(longevity, assembler=self.mc, frame_manager=ARMFrameManager())
 
         regalloc.update_bindings(enc, inputargs)
         bridge_head = self.mc.curraddr()

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	Fri Oct 29 09:36:53 2010
@@ -1,10 +1,13 @@
 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.arch import (WORD, FUNC_ALIGN, arm_int_div,
+                                        arm_int_div_sign, arm_int_mod_sign, arm_int_mod)
 from pypy.jit.backend.arm.instruction_builder import define_instructions
 
 from pypy.rlib.rmmap import alloc, PTR
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.jit.metainterp.history import ConstInt, BoxInt, Box, BasicFailDescr
 
 class AbstractARMv7Builder(object):
     def _init(self, data, map_size):
@@ -40,6 +43,26 @@
     def BKPT(self, cond=cond.AL):
         self.write32(cond << 28 | 0x1200070)
 
+    def DIV(self, cond=cond.AL):
+        """Generates a call to a helper function used for division, takes its
+        arguments in r0 and r1, result is placed in r0"""
+        self.PUSH(range(2, 12), cond=cond)
+        div_addr = rffi.cast(lltype.Signed, llhelper(arm_int_div_sign, arm_int_div))
+        self.gen_load_int(reg.r2.value, div_addr, cond=cond)
+        self.gen_load_int(reg.lr.value, self.curraddr()+self.size_of_gen_load_int+WORD, cond=cond)
+        self.MOV_rr(reg.pc.value, reg.r2.value, cond=cond)
+        self.LDM(reg.sp.value, range(2, 12), w=1, cond=cond) # XXX Replace with POP instr. someday
+
+    def MOD(self, cond=cond.AL):
+        """Generate a call to a helper function used for modulo, takes its
+        arguments in r0 and r1, result is placed in r0"""
+        self.PUSH(range(2, 12), cond=cond)
+        mod_addr = rffi.cast(lltype.Signed, llhelper(arm_int_mod_sign, arm_int_mod))
+        self.gen_load_int(reg.r2.value, mod_addr, cond=cond)
+        self.gen_load_int(reg.lr.value, self.curraddr()+self.size_of_gen_load_int+WORD, cond=cond)
+        self.MOV_rr(reg.pc.value, reg.r2.value, cond=cond)
+        self.LDM(reg.sp.value, range(2, 12), w=1, cond=cond) # XXX Replace with POP instr. someday
+
     def _encode_reg_list(self, instr, regs):
         for reg in regs:
             instr |= 0x1 << reg
@@ -73,16 +96,22 @@
         """r is the register number, value is the value to be loaded to the
         register"""
         assert r != reg.ip.value, 'ip is used to load int'
-        self.MOV_ri(r, (value & 0xFF), cond=cond)
         ip = reg.ip.value
 
+        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(ip, t, cond=cond)
             self.ORR_rr(r, r, ip, offset, cond=cond)
 
+    # regalloc support
+    def regalloc_mov(self, prev_loc, loc):
+        if isinstance(prev_loc, ConstInt):
+            # XXX check size of imm for current instr
+            self.gen_load_int(loc.value, prev_loc.getint())
+        else:
+            self.MOV_rr(loc.value, prev_loc.value)
+
 class ARMv7InMemoryBuilder(AbstractARMv7Builder):
     def __init__(self, start, end):
         map_size = end - start
@@ -96,5 +125,28 @@
         data = alloc(map_size)
         self._pos = 0
         self._init(data, map_size)
+        self.checks = True
+        self.n_data=0
+
+    _space_for_jump = 10 * WORD
+    def writechar(self, char):
+        if self.checks and not self._pos < self._size - self._space_for_jump:
+            self.checks = False
+            self._add_more_mem()
+            self.checks = True
+        assert self._pos < self._size
+        AbstractARMv7Builder.writechar(self, char)
+
+    def _add_more_mem(self):
+        new_mem = alloc(self._size)
+        new_mem_addr = rffi.cast(lltype.Signed, new_mem)
+        self.PUSH([reg.r0.value])
+        self.gen_load_int(reg.r0.value, new_mem_addr)
+        self.MOV_rr(reg.pc.value, reg.r0.value)
+        self._dump_trace('data%d.asm' % self.n_data)
+        self.n_data+=1
+        self._data = new_mem
+        self._pos = 0
+        self.LDM(reg.sp.value, [reg.r0.value], w=1) # XXX Replace with POP instr. someday
 
 define_instructions(AbstractARMv7Builder)

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py	Fri Oct 29 09:36:53 2010
@@ -5,3 +5,6 @@
 
     def __init__(self, value):
         self.value = value
+
+    def __repr__(self):
+        return 'r%d' % self.value

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	Fri Oct 29 09:36:53 2010
@@ -1,7 +1,8 @@
 from pypy.jit.backend.arm import conditions as c
 from pypy.jit.backend.arm import locations
 from pypy.jit.backend.arm import registers as r
-from pypy.jit.backend.arm.arch import WORD, FUNC_ALIGN
+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.codebuilder import ARMv7Builder, ARMv7InMemoryBuilder
 from pypy.jit.backend.arm.regalloc import ARMRegisterManager
 from pypy.jit.backend.llsupport.regalloc import compute_vars_longevity
@@ -68,7 +69,44 @@
         return fcond
 
     def emit_op_int_mul(self, op, regalloc, fcond):
-        import pdb; pdb.set_trace()
+        res = regalloc.try_allocate_reg(op.result)
+        reg1 = self._put_in_reg(op.getarg(0), regalloc)
+        reg2 = self._put_in_reg(op.getarg(1), regalloc)
+        self.mc.MUL(res.value, reg1.value, reg2.value)
+        regalloc.possibly_free_var(reg1)
+        regalloc.possibly_free_var(reg2)
+        return fcond
+
+    def emit_op_int_floordiv(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)
+        self.mc.DIV(fcond)
+        self.mc.MOV_rr(res.value, r.r0.value, cond=fcond)
+        regalloc.possibly_free_vars_for_op(op)
+        return fcond
+
+    def emit_op_int_mod(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)
+        self.mc.MOD(fcond)
+        self.mc.MOV_rr(res.value, r.r0.value, cond=fcond)
+        regalloc.possibly_free_vars_for_op(op)
+        return fcond
+
+    def _put_in_reg(self, box, regalloc):
+        if isinstance(box, ConstInt):
+            t = Box()
+            reg = regalloc.try_allocate_reg(t)
+            self.mc.gen_load_int(reg.value, box.getint())
+        else:
+            reg = regalloc.try_allocate_reg(box)
+        return reg
 
 class GuardOpAssembler(object):
     _mixin_ = True

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py	Fri Oct 29 09:36:53 2010
@@ -19,6 +19,9 @@
             self.try_allocate_reg(inputargs[i], r.all_regs[ord(enc[j])])
             j += 1
 
+    def convert_to_imm(self, c):
+        return c
+
 class ARMFrameManager(FrameManager):
     @staticmethod
     def frame_pos(loc, type):

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	Fri Oct 29 09:36:53 2010
@@ -13,6 +13,7 @@
     addr = asm.mc._start_addr
     assert addr % 8 == 0
     func = rffi.cast(lltype.Ptr(BOOTSTRAP_TP), addr)
+    asm.mc._dump_trace('test.asm')
     return func()
 
 def skip_unless_arm():

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	Fri Oct 29 09:36:53 2010
@@ -1,3 +1,4 @@
+from pypy.jit.backend.arm.arch import arm_int_div, arm_int_div_sign
 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
@@ -37,6 +38,18 @@
         self.a.gen_func_epilog()
         assert run_asm(self.a) == -123
 
+    def test_load_neg_int_to_reg(self):
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.r0.value, -110)
+        self.a.gen_func_epilog()
+        assert run_asm(self.a) == -110
+
+    def test_load_neg_int_to_reg2(self):
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.r0.value, -3)
+        self.a.gen_func_epilog()
+        assert run_asm(self.a) == -3
+
 
     def test_or(self):
         self.a.gen_func_prolog()
@@ -108,6 +121,47 @@
         self.a.gen_func_epilog()
         assert run_asm(self.a) == 133
 
+    def test_division(self):
+        self.a.gen_func_prolog()
+        self.a.mc.MOV_ri(r.r0.value, 123)
+        self.a.mc.MOV_ri(r.r1.value, 2)
+
+        # call to div
+        self.a.mc.PUSH(range(2, 12))
+        div_addr = rffi.cast(lltype.Signed, llhelper(arm_int_div_sign, arm_int_div))
+        self.a.mc.gen_load_int(r.r10.value, div_addr)
+        self.a.mc.gen_load_int(r.lr.value, self.a.mc.curraddr()+self.a.mc.size_of_gen_load_int+WORD)
+        self.a.mc.MOV_rr(r.pc.value, r.r10.value)
+        self.a.mc.LDM(r.sp.value, range(2, 12), w=1) # XXX Replace with POP instr. someday
+        self.a.gen_func_epilog()
+        assert run_asm(self.a) == 61
+
+    def test_DIV(self):
+        self.a.gen_func_prolog()
+        self.a.mc.MOV_ri(r.r0.value, 123)
+        self.a.mc.MOV_ri(r.r1.value, 2)
+        self.a.mc.DIV()
+        self.a.gen_func_epilog()
+        assert run_asm(self.a) == 61
+
+    def test_DIV2(self):
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.r0.value, -110)
+        self.a.mc.gen_load_int(r.r1.value, 3)
+        self.a.mc.DIV()
+        self.a.gen_func_epilog()
+        assert run_asm(self.a) == -36
+
+    def test_DIV3(self):
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.r8.value, 110)
+        self.a.mc.gen_load_int(r.r9.value, -3)
+        self.a.mc.MOV_rr(r.r0.value, r.r8.value)
+        self.a.mc.MOV_rr(r.r1.value, r.r9.value)
+        self.a.mc.DIV()
+        self.a.gen_func_epilog()
+        assert run_asm(self.a) == -36
+
 def callme(inp):
     i = inp + 10
     return i



More information about the Pypy-commit mailing list