Mercurial > lcfOS
view python/target/arminstructionselector.py @ 322:44f336460c2a
Half of use of burg spec for arm
author | Windel Bouwman |
---|---|
date | Mon, 27 Jan 2014 19:58:07 +0100 |
parents | e84047f29c78 |
children | e9fe6988497c |
line wrap: on
line source
import os from ppci import ir from ppci.irmach import AbstractInstruction as makeIns from ppci.ir2tree import makeTree import pyburg from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop from .instructionselector import InstructionSelector from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3 from .arminstructions import B, Bl, Bgt, Blt, Beq, Bne from .arminstructions import Mov2, Mov3 from .arminstructions import Add, Sub, Cmp, Sub2, Add2, Mul from .basetarget import Imm8, Imm7, Imm3 # Import BURG spec for arm: spec_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'arm.brg') arm_matcher = pyburg.load_as_module(spec_file) class ArmMatcher(arm_matcher.Matcher): def __init__(self): super().__init__() def newTmp(self): pass def emit(self, *args, **kwargs): pass class ArmInstructionSelector(InstructionSelector): """ Instruction selector for the arm architecture """ def __init__(self): super().__init__() self.matcher = ArmMatcher() def munchExpr(self, e): #t = makeTree(e) #print(t) #return self.matcher.gen(t) # TODO: below is obsolete: if isinstance(e, ir.Binop) and e.operation == '+' and \ isinstance(e.b, ir.Const) and e.b.value < 8: a = self.munchExpr(e.a) d = self.newTmp() c = Imm3(e.b.value) self.emit(Add2, others=[c], dst=[d], src=[a]) return d elif isinstance(e, ir.Binop) and e.operation == '+': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() self.emit(Add, dst=[d], src=[a, b]) return d elif isinstance(e, ir.Binop) and e.operation == '-' and \ isinstance(e.b, ir.Const) and e.b.value < 8: a = self.munchExpr(e.a) d = self.newTmp() c = Imm3(e.b.value) self.emit(Sub2, others=[c], dst=[d], src=[a]) return d elif isinstance(e, ir.Binop) and e.operation == '-': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() self.emit(Sub, dst=[d], src=[a, b]) return d elif isinstance(e, ir.Binop) and e.operation == '|': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() self.move(d, a) self.emit(Orr, dst=[], src=[d, b]) return d elif isinstance(e, ir.Binop) and e.operation == '<<': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() self.move(d, a) self.emit(Lsl, dst=[], src=[d, b]) # TODO: is d a source variable? return d elif isinstance(e, ir.Binop) and e.operation == '*': a = self.munchExpr(e.a) b = self.munchExpr(e.b) d = self.newTmp() self.move(d, a) # this mul instruction has operands swapped: self.emit(Mul, dst=[d], src=[b, d]) return d elif isinstance(e, ir.Const) and e.value < 256: d = self.newTmp() self.emit(Mov3, others=[Imm8(e.value)], dst=[d]) return d elif isinstance(e, ir.Const) and e.value < (2**31): d = self.newTmp() ln = LabelRef(self.frame.addConstant(e.value)) self.emit(Ldr3, others=[ln], dst=[d]) return d elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \ e.e.operation == '+' and isinstance(e.e.b, ir.Const): base = self.munchExpr(e.e.a) d = self.newTmp() c = e.e.b.value self.emit(Ldr2, others=[c], src=[base], dst=[d]) return d elif isinstance(e, ir.Mem): # Load from memory base = self.munchExpr(e.e) d = self.newTmp() self.emit(Ldr2, others=[0], src=[base], dst=[d]) return d elif isinstance(e, ir.Temp): return e elif isinstance(e, ir.Call): # 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(LabelRef(e.f)), src=reguses, dst=[self.frame.rv]) d = self.newTmp() self.move(d, self.frame.rv) return d else: raise NotImplementedError('Expr --> {}'.format(e)) 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(LabelRef(s.target.name)), 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(LabelRef(s.lab_no.name)), jumps=[ntgt]) opnames = {'<': Blt, '>':Bgt, '==':Beq, '!=':Bne} op = opnames[s.cond](LabelRef(s.lab_yes.name)) 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)