Mercurial > lcfOS
diff python/ppci/target/arm/selector.py @ 346:3bb7dcfe5529
expanded arm target
author | Windel Bouwman |
---|---|
date | Fri, 07 Mar 2014 17:05:32 +0100 |
parents | |
children | 899ae3aea803 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/ppci/target/arm/selector.py Fri Mar 07 17:05:32 2014 +0100 @@ -0,0 +1,90 @@ +from ... import ir, same_dir +from ppci.irmach import AbstractInstruction as makeIns +from ppci.ir2tree import makeTree +from .instructions import Str1, Mov2 +from .instructions import B, Bl, Blt, Bgt, Beq +import pyburg +from ..basetarget import Nop +from ..instructionselector import InstructionSelector + +# 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(Str1, 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(Str1, 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)