diff python/ppci/target/thumb/arminstructionselector.py @ 342:86b02c98a717 devel

Moved target directory
author Windel Bouwman
date Sat, 01 Mar 2014 15:40:31 +0100
parents python/target/arminstructionselector.py@4d204f6f7d4e
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/target/thumb/arminstructionselector.py	Sat Mar 01 15:40:31 2014 +0100
@@ -0,0 +1,92 @@
+from ... import ir, same_dir
+from ppci.irmach import AbstractInstruction as makeIns
+from ppci.ir2tree import makeTree
+import pyburg
+from ..basetarget import Nop
+from ..instructionselector import InstructionSelector
+from .instructions import Orr, Lsl, Str2, Ldr2, Ldr3
+from .instructions import B, Bl, Bgt, Blt, Beq, Bne
+from .instructions import Mov2, Mov3
+from .instructions import Cmp, Sub2, Mul
+
+# Import BURG spec for arm:
+spec_file = same_dir(__file__, 'arm.brg')
+arm_matcher = pyburg.load_as_module(spec_file)
+
+
+class ArmMatcher(arm_matcher.Matcher):
+    """ Matcher that derives from a burg spec generated matcher """
+    def __init__(self, selector):
+        super().__init__()
+        self.newTmp = selector.newTmp
+        self.emit = selector.emit
+        self.selector = selector
+
+
+class ArmInstructionSelector(InstructionSelector):
+    """ Instruction selector for the arm architecture """
+    def __init__(self):
+        super().__init__()
+        self.matcher = ArmMatcher(self)
+
+    def munchExpr(self, e):
+        # Use BURG system here:
+        t = makeTree(e)
+        return self.matcher.gen(t)
+
+    def munchCall(self, e):
+        """ Generate code for call sequence """
+        # Move arguments into proper locations:
+        reguses = []
+        for i, a in enumerate(e.arguments):
+            loc = self.frame.argLoc(i)
+            m = ir.Move(loc, a)
+            self.munchStm(m)
+            if isinstance(loc, ir.Temp):
+                reguses.append(loc)
+        self.emit(Bl(e.f), src=reguses, dst=[self.frame.rv])
+        d = self.newTmp()
+        self.move(d, self.frame.rv)
+        return d
+
+    def munchStm(self, s):
+        if isinstance(s, ir.Terminator):
+            pass
+        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \
+            isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \
+            isinstance(s.dst.e.b, ir.Const):
+            a = self.munchExpr(s.dst.e.a)
+            val = self.munchExpr(s.src)
+            c = s.dst.e.b.value
+            self.emit(Str2, others=[c], src=[a, val])
+        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
+            memloc = self.munchExpr(s.dst.e)
+            val = self.munchExpr(s.src)
+            self.emit(Str2, others=[0], src=[memloc, val])
+        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
+            val = self.munchExpr(s.src)
+            dreg = s.dst
+            self.move(dreg, val)
+        elif isinstance(s, ir.Exp):
+            # Generate expression code and discard the result.
+            x = self.munchExpr(s.e)
+            self.emit(Nop(), src=[x])
+        elif isinstance(s, ir.Jump):
+            tgt = self.targets[s.target]
+            self.emit(B(ir.label_name(s.target)), jumps=[tgt])
+        elif isinstance(s, ir.CJump):
+            a = self.munchExpr(s.a)
+            b = self.munchExpr(s.b)
+            self.emit(Cmp, src=[a, b])
+            ntgt = self.targets[s.lab_no]
+            ytgt = self.targets[s.lab_yes]
+            jmp_ins = makeIns(B(ir.label_name(s.lab_no)), jumps=[ntgt])
+            opnames = {'<': Blt, '>':Bgt, '==':Beq, '!=':Bne}
+            op = opnames[s.cond](ir.label_name(s.lab_yes))
+            self.emit(op, jumps=[ytgt, jmp_ins])  # Explicitely add fallthrough
+            self.emit2(jmp_ins)
+        else:
+            raise NotImplementedError('Stmt --> {}'.format(s))
+
+    def move(self, dst, src):
+        self.emit(Mov2, src=[src], dst=[dst], ismove=True)