Mercurial > lcfOS
diff python/target/arminstructionselector.py @ 292:534b94b40aa8
Fixup reorganize
author | Windel Bouwman |
---|---|
date | Wed, 27 Nov 2013 08:06:42 +0100 |
parents | |
children | 158068af716c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/target/arminstructionselector.py Wed Nov 27 08:06:42 2013 +0100 @@ -0,0 +1,144 @@ +import ir +from irmach import AbstractInstruction as makeIns +from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop +from .instructionselector import InstructionSelector +from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3, B, Bl, Bgt, Blt, Beq +from .arminstructions import Mov2, Mov3 +from .arminstructions import Add, Sub, Cmp +from .basetarget import Imm8, Imm7, Imm3 + + +class ArmInstructionSelector(InstructionSelector): + """ Instruction selector for the arm architecture """ + def munchExpr(self, e): + if isinstance(e, ir.Alloc): + return 0 + 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(arm.addregregimm3_ins, 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(arm.subregregimm3_ins, 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=[b, d]) + 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=[b, d]) # 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(arm.mulregreg_ins, 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.name)), 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} + 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])