Mercurial > lcfOS
view python/codegenarm.py @ 269:5f8c04a8d26b
Towards better modularity
author | Windel Bouwman |
---|---|
date | Sun, 18 Aug 2013 17:43:18 +0200 |
parents | 5ec7580976d9 |
children | cdc76d183bcc |
line wrap: on
line source
import logging import ir from target import Label, Comment, Alignment, LabelRef, Imm32, DebugInfo import cortexm3 as arm from ppci import CompilerError import graph import flowgraph import registerallocator from instructionselector import InstructionSelector 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 == '+': a = self.munchExpr(e.value1) b = self.munchExpr(e.value2) d = self.newTmp() self.emit('add %d0, %s0, %s1', dst=[d], src=[a, b]) return d elif isinstance(e, ir.Binop) and e.operation == '-': a = self.munchExpr(e.value1) b = self.munchExpr(e.value2) d = self.newTmp() self.emit('sub %d0, %s0, %s1', dst=[d], src=[a, b]) return d elif isinstance(e, ir.Binop) and e.operation == '|': a = self.munchExpr(e.value1) b = self.munchExpr(e.value2) d = self.newTmp() self.emit('or %d0, %s0, %s1', dst=[d], src=[a, b]) return d elif isinstance(e, ir.Binop) and e.operation == '<<': a = self.munchExpr(e.value1) b = self.munchExpr(e.value2) d = self.newTmp() self.emit('lsl %d0, %s0, %s1', dst=[d], src=[a, b]) return d elif isinstance(e, ir.Binop) and e.operation == '*': a = self.munchExpr(e.value1) b = self.munchExpr(e.value2) d = self.newTmp() self.emit('mul %d0, %s0, %s1', dst=[d], src=[a, b]) return d elif isinstance(e, ir.Const): d = self.newTmp() if e.value < 256: self.emit('ldr %d0, {}'.format(e.value), dst=[d]) else: self.emit('ldrpcrel TODO', dst=[d]) return d elif isinstance(e, ir.Mem): # Load from memory loc = self.munchExpr(e.e) d = self.newTmp() self.emit('ldr %d0, [%s0]', src=[loc], dst=[d]) return d elif isinstance(e, ir.Temp): return self.getTempReg(e) else: raise NotImplementedError('--> {}'.format(e)) def munchStm(self, s): if isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem): memloc = self.munchExpr(s.dst.e) val = self.munchExpr(s.src) self.emit('str [%s0], %s1') elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp): val = self.munchExpr(s.src) dreg = self.getTempReg(s.dst) self.emit('mov %d0, %s0', dst=[dreg], src=[val]) elif isinstance(s, ir.Return): #etgt = self.targets[ self.emit('jmp exit', jumps=[]) elif isinstance(s, ir.Jump): tgt = self.targets[s.target] self.emit('jmp {}'.format(s), jumps=[tgt]) elif isinstance(s, ir.CJump): a = self.munchExpr(s.a) b = self.munchExpr(s.b) self.emit('cmp %s0, %s1', src=[a, b]) ntgt = self.targets[s.lab_no] ytgt = self.targets[s.lab_yes] jmp_ins = self.makeIns('jmp {}'.format(s.lab_no), jumps=[ntgt]) # Explicitely add fallthrough: self.emit('jeq {}'.format(s.lab_yes), jumps=[ytgt, jmp_ins]) self.emit2(jmp_ins) else: raise NotImplementedError('--> {}'.format(s)) class ArmCodeGenerator: def __init__(self, outs): # TODO: schedule traces in better order. # This is optional! self.ins_sel = ArmInstructionSelector() self.outs = outs self.outs.getSection('code').address = 0x08000000 self.outs.getSection('data').address = 0x20000000 def generate(self, ircode, cfg_file=None, ig_file=None): x = self.ins_sel.munchProgram(ircode) cfg = flowgraph.FlowGraph(x) if cfg_file: cfg.to_dot(cfg_file) ig = registerallocator.InterferenceGraph(cfg) if ig_file: ig.to_dot(ig_file) regs = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7'] ra = registerallocator.RegisterAllocator() ra.registerAllocate(ig, regs)