view python/ppci/target/thumb/arminstructionselector.py @ 345:b4882ff0ed06

Added more arm isa tests
author Windel Bouwman
date Sun, 02 Mar 2014 17:12:08 +0100
parents 86b02c98a717
children
line wrap: on
line source

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)