Author: David Schneider <david.schnei...@picle.org>
Branch: arm-backend-2
Changeset: r47704:9f76d024fa8d
Date: 2011-09-29 11:20 +0200
http://bitbucket.org/pypy/pypy/changeset/9f76d024fa8d/

Log:    refactor regalloc_mov, create separate methods for different casese
        and add tests checking the generated instructions and also add tests
        that check that the not supported cases raise an error

diff --git a/pypy/jit/backend/arm/assembler.py 
b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -861,69 +861,109 @@
             self.mc.gen_load_int(r.ip.value, value.getint())
             self.mc.VLDR(loc.value, r.ip.value)
 
+    def _mov_imm_to_loc(self, prev_loc, loc, cond=c.AL):
+        if not loc.is_reg() and not loc.is_stack():
+            raise AssertionError("invalid target for move from imm value")
+        if loc.is_reg():
+            new_loc = loc
+        elif loc.is_stack():
+            # we use LR here, because the consequent move to the stack uses the
+            # IP register
+            self.mc.PUSH([r.lr.value], cond=cond)
+            new_loc = r.lr
+        self.mc.gen_load_int(new_loc.value, prev_loc.value, cond=cond)
+        if loc.is_stack():
+            self.regalloc_mov(new_loc, loc)
+            self.mc.POP([r.lr.value], cond=cond)
+
+    def _mov_reg_to_loc(self, prev_loc, loc, cond=c.AL):
+        if loc.is_imm():
+            raise AssertionError("mov reg to imm doesn't make sense")
+        if loc.is_reg():
+            self.mc.MOV_rr(loc.value, prev_loc.value, cond=cond)
+        elif loc.is_stack():
+            # spill a core register
+            offset = ConstInt(loc.position*WORD)
+            if not _check_imm_arg(offset, size=0xFFF):
+                self.mc.PUSH([r.ip.value], cond=cond)
+                self.mc.gen_load_int(r.ip.value, -offset.value, cond=cond)
+                self.mc.STR_rr(prev_loc.value, r.fp.value, r.ip.value, 
cond=cond)
+                self.mc.POP([r.ip.value], cond=cond)
+            else:
+                self.mc.STR_ri(prev_loc.value, r.fp.value, 
imm=-1*offset.value, cond=cond)
+        else:
+            assert 0, 'unsupported case'
+
+    def _mov_stack_to_loc(self, prev_loc, loc, cond=c.AL):
+        pushed = False
+        if loc.is_reg():
+            assert prev_loc.type == INT, 'trying to load from an incompatible 
location into a core register'
+            # unspill a core register
+            offset = ConstInt(prev_loc.position*WORD)
+            if not _check_imm_arg(offset, size=0xFFF):
+                self.mc.PUSH([r.ip.value], cond=cond)
+                pushed = True
+                self.mc.gen_load_int(r.ip.value, -offset.value, cond=cond)
+                self.mc.LDR_rr(loc.value, r.fp.value, r.ip.value, cond=cond)
+            else:
+                self.mc.LDR_ri(loc.value, r.fp.value, imm=-offset.value, 
cond=cond)
+            if pushed:
+                self.mc.POP([r.ip.value], cond=cond)
+        elif loc.is_vfp_reg():
+            assert prev_loc.type == FLOAT, 'trying to load from an 
incompatible location into a float register'
+            # load spilled value into vfp reg
+            offset = ConstInt(prev_loc.position*WORD)
+            self.mc.PUSH([r.ip.value], cond=cond)
+            pushed = True
+            if not _check_imm_arg(offset):
+                self.mc.gen_load_int(r.ip.value, offset.value, cond=cond)
+                self.mc.SUB_rr(r.ip.value, r.fp.value, r.ip.value, cond=cond)
+            else:
+                self.mc.SUB_ri(r.ip.value, r.fp.value, offset.value, cond=cond)
+            self.mc.VLDR(loc.value, r.ip.value, cond=cond)
+            if pushed:
+                self.mc.POP([r.ip.value], cond=cond)
+        else:
+            assert 0, 'unsupported case'
+
+    def _mov_imm_float_to_loc(self, prev_loc, loc, cond=c.AL):
+        if not loc.is_vfp_reg():
+            assert 0, 'unsupported case'
+        self.mc.PUSH([r.ip.value], cond=cond)
+        self.mc.gen_load_int(r.ip.value, prev_loc.getint(), cond=cond)
+        self.mc.VLDR(loc.value, r.ip.value, cond=cond)
+        self.mc.POP([r.ip.value], cond=cond)
+
+    def _mov_vfp_reg_to_loc(self, prev_loc, loc, cond=c.AL):
+        if loc.is_vfp_reg():
+            self.mc.VMOV_cc(loc.value, prev_loc.value, cond=cond)
+        elif loc.is_stack():
+            assert loc.type == FLOAT, 'trying to store to an incompatible 
location from a float register'
+            # spill vfp register
+            self.mc.PUSH([r.ip.value], cond=cond)
+            offset = ConstInt(loc.position*WORD)
+            if not _check_imm_arg(offset):
+                self.mc.gen_load_int(r.ip.value, offset.value, cond=cond)
+                self.mc.SUB_rr(r.ip.value, r.fp.value, r.ip.value, cond=cond)
+            else:
+                self.mc.SUB_ri(r.ip.value, r.fp.value, offset.value, cond=cond)
+            self.mc.VSTR(prev_loc.value, r.ip.value, cond=cond)
+            self.mc.POP([r.ip.value], cond=cond)
+        else:
+            assert 0, 'unsupported case'
+
     def regalloc_mov(self, prev_loc, loc, cond=c.AL):
-        # really XXX add tests
+        """Moves a value from a previous location to some other location"""
         if prev_loc.is_imm():
-            if loc.is_reg():
-                new_loc = loc
-            else:
-                assert loc is not r.ip
-                new_loc = r.ip
-            if _check_imm_arg(ConstInt(prev_loc.getint())):
-                self.mc.MOV_ri(new_loc.value, prev_loc.getint(), cond=cond)
-            else:
-                self.mc.gen_load_int(new_loc.value, prev_loc.getint(), 
cond=cond)
-            prev_loc = new_loc
-            if not loc.is_stack():
-                return
-        if prev_loc.is_imm_float():
-            assert loc.is_vfp_reg()
-            temp = r.lr
-            self.mc.gen_load_int(temp.value, prev_loc.getint())
-            self.mc.VLDR(loc.value, temp.value)
-            return
-        if loc.is_stack() or prev_loc.is_stack():
-            temp = r.lr
-            if loc.is_stack() and prev_loc.is_reg():
-                # spill a core register
-                offset = ConstInt(loc.position*WORD)
-                if not _check_imm_arg(offset, size=0xFFF):
-                    self.mc.gen_load_int(temp.value, -offset.value)
-                    self.mc.STR_rr(prev_loc.value, r.fp.value, temp.value, 
cond=cond)
-                else:
-                    self.mc.STR_ri(prev_loc.value, r.fp.value, 
imm=-1*offset.value, cond=cond)
-            elif loc.is_reg() and prev_loc.is_stack():
-                # unspill a core register
-                offset = ConstInt(prev_loc.position*WORD)
-                if not _check_imm_arg(offset, size=0xFFF):
-                    self.mc.gen_load_int(temp.value, -offset.value)
-                    self.mc.LDR_rr(loc.value, r.fp.value, temp.value, 
cond=cond)
-                else:
-                    self.mc.LDR_ri(loc.value, r.fp.value, imm=-offset.value, 
cond=cond)
-            elif loc.is_stack() and prev_loc.is_vfp_reg():
-                # spill vfp register
-                offset = ConstInt(loc.position*WORD)
-                if not _check_imm_arg(offset):
-                    self.mc.gen_load_int(temp.value, offset.value)
-                    self.mc.SUB_rr(temp.value, r.fp.value, temp.value)
-                else:
-                    self.mc.SUB_ri(temp.value, r.fp.value, offset.value)
-                self.mc.VSTR(prev_loc.value, temp.value, cond=cond)
-            elif loc.is_vfp_reg() and prev_loc.is_stack():
-                # load spilled value into vfp reg
-                offset = ConstInt(prev_loc.position*WORD)
-                if not _check_imm_arg(offset):
-                    self.mc.gen_load_int(temp.value, offset.value)
-                    self.mc.SUB_rr(temp.value, r.fp.value, temp.value)
-                else:
-                    self.mc.SUB_ri(temp.value, r.fp.value, offset.value)
-                self.mc.VLDR(loc.value, temp.value, cond=cond)
-            else:
-                assert 0, 'unsupported case'
-        elif loc.is_reg() and prev_loc.is_reg():
-            self.mc.MOV_rr(loc.value, prev_loc.value, cond=cond)
-        elif loc.is_vfp_reg() and prev_loc.is_vfp_reg():
-            self.mc.VMOV_cc(loc.value, prev_loc.value, cond=cond)
+            return self._mov_imm_to_loc(prev_loc, loc, cond)
+        elif prev_loc.is_reg():
+            self._mov_reg_to_loc(prev_loc, loc, cond)
+        elif prev_loc.is_stack():
+            self._mov_stack_to_loc(prev_loc, loc, cond)
+        elif prev_loc.is_imm_float():
+            self._mov_imm_float_to_loc(prev_loc, loc, cond)
+        elif prev_loc.is_vfp_reg():
+            self._mov_vfp_reg_to_loc(prev_loc, loc, cond)
         else:
             assert 0, 'unsupported case'
     mov_loc_loc = regalloc_mov
diff --git a/pypy/jit/backend/arm/test/test_regalloc_mov.py 
b/pypy/jit/backend/arm/test/test_regalloc_mov.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/arm/test/test_regalloc_mov.py
@@ -0,0 +1,240 @@
+from pypy.rlib.objectmodel import instantiate
+from pypy.jit.backend.arm.assembler import AssemblerARM
+from pypy.jit.backend.arm.locations import imm, ImmLocation, ConstFloatLoc,\
+                                        RegisterLocation, StackLocation, \
+                                        VFPRegisterLocation
+from pypy.jit.backend.arm.registers import lr, ip, fp
+from pypy.jit.backend.arm.conditions import AL
+from pypy.jit.metainterp.history import INT, FLOAT, REF
+import py
+class MockInstr(object):
+    def __init__(self, name, *args, **kwargs):
+        self.name = name
+        self.args = args
+        self.kwargs = kwargs
+
+    def __call__(self, *args, **kwargs):
+        self.args = args
+        self.kwargs = kwargs
+
+    def __repr__(self):
+        return "%s %r %r" % (self.name, self.args, self.kwargs)
+
+    __str__ = __repr__
+
+    def __eq__(self, other):
+        return (self.__class__ == other.__class__
+                and self.name == other.name
+                and self.args == other.args
+                and self.kwargs == other.kwargs)
+mi = MockInstr
+# helper method for tests
+def r(i):
+    return RegisterLocation(i)
+
+def vfp(i):
+    return VFPRegisterLocation(i)
+
+stack = StackLocation
+def stack_float(i):
+    return stack(i, num_words=2, type=FLOAT)
+
+def imm_float(value):
+    addr = int(value) # whatever
+    return ConstFloatLoc(addr)
+
+class MockBuilder(object):
+    def __init__(self):
+        self.instrs = []
+
+    def __getattr__(self, name):
+        i = MockInstr(name)
+        self.instrs.append(i)
+        return i
+
+class TestRegallocMov(object):
+    def setup_method(self, method):
+        self.builder = MockBuilder()
+        self.asm = instantiate(AssemblerARM)
+        self.asm.mc = self.builder
+
+    def mov(self, a, b, expected=None):
+        self.asm.regalloc_mov(a, b)
+        result =self.builder.instrs
+        assert result == expected
+
+    def test_mov_imm_to_reg(self):
+        val = imm(123)
+        reg = r(7)
+        expected = [mi('gen_load_int', 7, 123, cond=AL)]
+        self.mov(val, reg, expected)
+
+    def test_mov_large_imm_to_reg(self):
+        val = imm(65536)
+        reg = r(7)
+        expected = [mi('gen_load_int', 7, 65536, cond=AL)]
+        self.mov(val, reg, expected)
+
+    def test_mov_imm_to_stacklock(self):
+        val = imm(100)
+        s = stack(7)
+        expected = [
+                mi('PUSH', [lr.value], cond=AL),
+                mi('gen_load_int', lr.value, 100, cond=AL), 
+                mi('STR_ri', lr.value, fp.value, imm=-28, cond=AL),
+                mi('POP', [lr.value], cond=AL)]
+        self.mov(val, s, expected)
+
+    def test_mov_big_imm_to_stacklock(self):
+        val = imm(65536)
+        s = stack(7)
+        expected = [
+                mi('PUSH', [lr.value], cond=AL),
+                mi('gen_load_int', lr.value, 65536, cond=AL), 
+                mi('STR_ri', lr.value, fp.value, imm=-28, cond=AL),
+                mi('POP', [lr.value], cond=AL)]
+
+        self.mov(val, s, expected)
+    def test_mov_imm_to_big_stacklock(self):
+        val = imm(100)
+        s = stack(8191)
+        expected = [mi('PUSH', [lr.value], cond=AL),
+                    mi('gen_load_int', lr.value, 100, cond=AL),
+                    mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, -32764, cond=AL),
+                    mi('STR_rr', lr.value, fp.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL),
+                    mi('POP', [lr.value], cond=AL)]
+        self.mov(val, s, expected)
+
+    def test_mov_big_imm_to_big_stacklock(self):
+        val = imm(65536)
+        s = stack(8191)
+        expected = [mi('PUSH', [lr.value], cond=AL),
+                    mi('gen_load_int', lr.value, 65536, cond=AL),
+                    mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, -32764, cond=AL),
+                    mi('STR_rr', lr.value, fp.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL),
+                    mi('POP', [lr.value], cond=AL)]
+        self.mov(val, s, expected)
+
+    def test_mov_reg_to_reg(self):
+        r1 = r(1)
+        r9 = r(9)
+        expected = [mi('MOV_rr', r9.value, r1.value, cond=AL)]
+        self.mov(r1, r9, expected)
+
+    def test_mov_reg_to_stack(self):
+        s = stack(10)
+        r6 = r(6)
+        expected = [mi('STR_ri', r6.value, fp.value, imm=-40, cond=AL)]
+        self.mov(r6, s, expected)
+
+    def test_mov_reg_to_big_stackloc(self):
+        s = stack(8191)
+        r6 = r(6)
+        expected = [mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, -32764, cond=AL),
+                    mi('STR_rr', r6.value, fp.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(r6, s, expected)
+
+    def test_mov_stack_to_reg(self):
+        s = stack(10)
+        r6 = r(6)
+        expected = [mi('LDR_ri', r6.value, fp.value, imm=-40, cond=AL)]
+        self.mov(s, r6, expected)
+
+    def test_mov_big_stackloc_to_reg(self):
+        s = stack(8191)
+        r6 = r(6)
+        expected = [
+                    mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, -32764, cond=AL),
+                    mi('LDR_rr', r6.value, fp.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(s, r6, expected)
+
+    def test_mov_float_imm_to_vfp_reg(self):
+        f = imm_float(3.5)
+        reg = vfp(5)
+        expected = [
+                    mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, f.value, cond=AL),
+                    mi('VLDR', 5, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(f, reg, expected)
+
+    def test_mov_vfp_reg_to_vfp_reg(self):
+        reg1 = vfp(5)
+        reg2 = vfp(14)
+        expected = [mi('VMOV_cc', reg2.value, reg1.value, cond=AL)]
+        self.mov(reg1, reg2, expected)
+
+    def test_mov_vfp_reg_to_stack(self):
+        reg = vfp(7)
+        s = stack_float(3)
+        expected = [mi('PUSH', [ip.value], cond=AL),
+                    mi('SUB_ri', ip.value, fp.value, 12, cond=AL),
+                    mi('VSTR', reg.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(reg, s, expected)
+
+    def test_mov_vfp_reg_to_large_stackloc(self):
+        reg = vfp(7)
+        s = stack_float(800)
+        expected = [mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, 3200, cond=AL),
+                    mi('SUB_rr', ip.value, fp.value, ip.value, cond=AL),
+                    mi('VSTR', reg.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(reg, s, expected)
+
+    def test_mov_stack_to_vfp_reg(self):
+        reg = vfp(7)
+        s = stack_float(3)
+        expected = [mi('PUSH', [ip.value], cond=AL),
+                    mi('SUB_ri', ip.value, fp.value, 12, cond=AL),
+                    mi('VLDR', reg.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(s, reg, expected)
+
+    def test_mov_big_stackloc_to_vfp_reg(self):
+        reg = vfp(7)
+        s = stack_float(800)
+        expected = [mi('PUSH', [ip.value], cond=AL),
+                    mi('gen_load_int', ip.value, 3200, cond=AL),
+                    mi('SUB_rr', ip.value, fp.value, ip.value, cond=AL),
+                    mi('VSTR', reg.value, ip.value, cond=AL),
+                    mi('POP', [ip.value], cond=AL)]
+        self.mov(reg, s, expected)
+
+    def test_unsopported_cases(self):
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm(1), imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm(1), vfp(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm_float(1), 
r(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm_float(1), 
stack(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm_float(1), 
stack_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm_float(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(imm_float(1), 
imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(r(1), imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(r(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(vfp(1), imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(vfp(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack(1), 
stack(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack(1), 
imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack(1), 
vfp(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack_float(1), 
r(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack_float(1), 
imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack_float(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(stack_float(1), 
stack_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(vfp(1), imm(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(vfp(1), 
imm_float(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(vfp(1), r(2))')
+        py.test.raises(AssertionError, 'self.asm.regalloc_mov(vfp(1), 
stack(2))')
+
+class TestMovFromToVFPLoc(object):
+    pass
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to