[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