Mercurial > lcfOS
diff python/codegenarm.py @ 280:02385f62f250
Rework from str interface to Instruction interface
author | Windel Bouwman |
---|---|
date | Sat, 02 Nov 2013 10:03:26 +0100 |
parents | 2ccd57b1d78c |
children |
line wrap: on
line diff
--- a/python/codegenarm.py Sat Oct 12 09:56:23 2013 +0200 +++ b/python/codegenarm.py Sat Nov 02 10:03:26 2013 +0100 @@ -1,13 +1,15 @@ import logging import ir -from target import Label, Comment, Alignment, LabelRef, Imm32, DebugInfo +from target import Label, Comment, Alignment, LabelRef, Imm32, DebugInfo, Nop +from target import Imm3 import cortexm3 as arm from ppci import CompilerError import registerallocator from instructionselector import InstructionSelector import irmach -from irmach import makeIns +from irmach import AbstractInstruction as makeIns import canon +import transform import asm class ArmFrame(irmach.Frame): @@ -17,7 +19,7 @@ def __init__(self, name): # We use r7 as frame pointer. super().__init__(name) - self.regs = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6'] + self.regs = [arm.r0, arm.r1, arm.r2, arm.r3, arm.r4, arm.r5, arm.r6] self.rv = ir.Temp('special_RV') self.p1 = ir.Temp('special_P1') self.p2 = ir.Temp('special_P2') @@ -26,12 +28,12 @@ self.fp = ir.Temp('special_FP') # Pre-colored registers: self.tempMap = {} - self.tempMap[self.rv] = 'r0' - self.tempMap[self.p1] = 'r1' - self.tempMap[self.p2] = 'r2' - self.tempMap[self.p3] = 'r3' - self.tempMap[self.p4] = 'r4' - self.tempMap[self.fp] = 'r7' + self.tempMap[self.rv] = arm.r0 + self.tempMap[self.p1] = arm.r1 + self.tempMap[self.p2] = arm.r2 + self.tempMap[self.p3] = arm.r3 + self.tempMap[self.p4] = arm.r4 + self.tempMap[self.fp] = arm.r7 self.locVars = {} self.parMap = {} # Literal pool: @@ -68,20 +70,20 @@ Add code for the prologue and the epilogue. Add a label, the return instruction and the stack pointer adjustment for the frame. """ - self.instructions.insert(0, makeIns('{}:'.format(self.name))) - self.instructions.insert(1, makeIns('push {lr, r7}')) + self.instructions.insert(0, makeIns(arm.Label(self.name))) + self.instructions.insert(1, makeIns(arm.push_ins(arm.RegisterSet({arm.lr, arm.r7})))) # Reserve stack space for locals: - self.instructions.insert(2, makeIns('sub sp, sp, {}'.format(self.stacksize))) + self.instructions.insert(2, makeIns(arm.subspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize)))) # Setup frame pointer: - self.instructions.insert(3, makeIns('mov r7, sp')) + self.instructions.insert(3, makeIns(arm.movregreg_ext_ins(arm.r7, arm.sp))) # Stack grows downwards - self.instructions.append(makeIns('add sp, sp, {}'.format(self.stacksize))) - self.instructions.append(makeIns('pop {pc,r7}')) + self.instructions.append(makeIns(arm.addspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize)))) + self.instructions.append(makeIns(arm.pop_ins(arm.RegisterSet({arm.pc, arm.r7})))) # Add constant literals: - self.instructions.append(makeIns('align 4')) # Align at 4 bytes + self.instructions.append(makeIns(Alignment(4))) # Align at 4 bytes for ln, v in self.constants: - self.instructions.append(makeIns('{}:'.format(ln))) - self.instructions.append(makeIns('dcd {}'.format(v))) + self.instructions.append(makeIns(arm.Label(ln))) + self.instructions.append(makeIns(arm.dcd_ins(v))) class ArmInstructionSelector(InstructionSelector): @@ -94,39 +96,41 @@ isinstance(e.b, ir.Const) and e.b.value < 8: a = self.munchExpr(e.a) d = self.newTmp() - self.emit('add %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) + 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 %d0, %s0, %s1', dst=[d], src=[a, b]) + self.emit(arm.addregs_ins, 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() - self.emit('sub %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) + 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 %d0, %s0, %s1', dst=[d], src=[a, b]) + self.emit(arm.subregs_ins, 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 %s1, %s0', dst=[], src=[b, d]) + self.emit(arm.orrregs_ins, 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 %s1, %s0', dst=[], src=[b, d]) # TODO: is d a source variable? + self.emit(arm.lslregs_ins, 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) @@ -134,29 +138,29 @@ d = self.newTmp() self.move(d, a) # this mul instruction has operands swapped: - self.emit('mul %s0, %d0', dst=[d], src=[b, d]) + 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('mov %d0, {}'.format(e.value), dst=[d]) + self.emit(arm.mov_imm8_ins, others=[arm.Imm8(e.value)], dst=[d]) return d elif isinstance(e, ir.Const) and e.value < (2**31): d = self.newTmp() - ln = self.frame.addConstant(e.value) - self.emit('ldr %d0, {}'.format(ln), dst=[d]) + ln = LabelRef(self.frame.addConstant(e.value)) + self.emit(arm.ldr_pcrel, 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('ldr %d0, [%s0 + {}]'.format(c), src=[base], dst=[d]) + self.emit(arm.loadimm5_ins, 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('ldr %d0, [%s0]', src=[base], dst=[d]) + self.emit(arm.loadimm5_ins, others=[0], src=[base], dst=[d]) return d elif isinstance(e, ir.Temp): return e @@ -169,7 +173,7 @@ self.munchStm(m) if isinstance(loc, ir.Temp): reguses.append(loc) - self.emit('bl {}'.format(e.f.name), src=reguses, dst=[self.frame.rv]) + self.emit(arm.bl_ins(LabelRef(e.f.name)), src=reguses, dst=[self.frame.rv]) d = self.newTmp() self.move(d, self.frame.rv) return d @@ -185,35 +189,39 @@ a = self.munchExpr(s.dst.e.a) val = self.munchExpr(s.src) c = s.dst.e.b.value - self.emit('str %s1, [%s0 + {}]'.format(c), src=[a, val]) + self.emit(arm.storeimm5_ins, 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('str %s1, [%s0]', src=[memloc, val]) + self.emit(arm.storeimm5_ins, 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.emit('mov %d0, %s0', dst=[dreg], src=[val]) + 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]) + self.emit(Nop(), src=[x]) elif isinstance(s, ir.Jump): tgt = self.targets[s.target] - self.emit('b {}'.format(s.target.name), jumps=[tgt]) + self.emit(arm.b_ins(LabelRef(s.target.name)), 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]) + self.emit(arm.cmp_ins, src=[a, b]) ntgt = self.targets[s.lab_no] ytgt = self.targets[s.lab_yes] - jmp_ins = makeIns('b {}'.format(s.lab_no.name), jumps=[ntgt]) - # Explicitely add fallthrough: - self.emit('beq {}'.format(s.lab_yes.name), jumps=[ytgt, jmp_ins]) + jmp_ins = makeIns(arm.b_ins(LabelRef(s.lab_no.name)), jumps=[ntgt]) + opnames = {'<': arm.blt_ins, '>':arm.bgt_ins, '==':arm.beq_ins} + 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(arm.movregreg_ext_ins, src=[src], dst=[dst]) + # TODO: this class could be target independent: class ArmCodeGenerator: @@ -227,47 +235,45 @@ self.outs.getSection('data').address = 0x20000000 def generateFunc(self, irfunc): + """ Generate code for one function into a frame """ + # Cleanup function: + transform.removeEmptyBlocks(irfunc) + # Create a frame for this function: frame = ArmFrame(irfunc.name) # Canonicalize the intermediate language: canon.make(irfunc, frame) - print('after canonicalize:') - irfunc.dump() self.ins_sel.munchFunction(irfunc, frame) - print('Selected instructions:') - for i in frame.instructions: - print(i) # Do register allocation: self.ra.allocFrame(frame) # TODO: Peep-hole here? + # Can we materialize here?? + # Add label and return and stack adjustment: frame.EntryExitGlue3() + + # Materialize assembly + # Materialize the register allocated instructions into a stream of + # real instructions. + frame.lower_to(self.outs) return frame def generate(self, ircode): + self.outs.selectSection('code') + # assembly glue to make it work: + # TODO: this must be in source code, not in compiler + self.outs.emit(arm.dcd_ins(Imm32(0x20000678))) # initial SP + self.outs.emit(arm.dcd_ins(Imm32(0x08000009))) # reset vector + self.outs.emit(arm.b_ins(LabelRef('main'))) + # Munch program into a bunch of frames. One frame per function. # Each frame has a flat list of abstract instructions. # Generate code for all functions: self.frames = [self.generateFunc(func) for func in ircode.Functions] - # Materialize assembly - # Reparse the register allocated instructions into a stream of - # real instructions. - # TODO: this is ugly via string representations. This could be - # another interface? - assembler = asm.Assembler(target=arm.armtarget, stream=self.outs) - self.outs.selectSection('code') - # assembly glue to make it work: - self.outs.emit(arm.dcd_ins(Imm32(0x20000678))) # initial SP - self.outs.emit(arm.dcd_ins(Imm32(0x08000009))) # reset vector - self.outs.emit(arm.b_ins(LabelRef('main'))) - for frame in self.frames: - for i in frame.instructions: - assembler.assemble_line(str(i)) - # TODO: fixup references, do this in another way? self.outs.backpatch() self.outs.backpatch()