diff python/target/armframe.py @ 290:7b38782ed496

File moves
author Windel Bouwman
date Sun, 24 Nov 2013 11:24:15 +0100
parents python/codegenarm.py@02385f62f250
children 534b94b40aa8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/target/armframe.py	Sun Nov 24 11:24:15 2013 +0100
@@ -0,0 +1,219 @@
+import ir
+from ppci import CompilerError
+from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
+from .basetarget import Imm32, Imm3
+import .armtarget as arm
+from .instructionselector import InstructionSelector
+import irmach
+from irmach import AbstractInstruction as makeIns
+import asm
+
+
+class ArmFrame(irmach.Frame):
+    """
+      Arm specific frame for functions.
+    """
+    def __init__(self, name):
+        # We use r7 as frame pointer.
+        super().__init__(name)
+        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')
+        self.p3 = ir.Temp('special_P3')
+        self.p4 = ir.Temp('special_P4')
+        self.fp = ir.Temp('special_FP')
+        # Pre-colored registers:
+        self.tempMap = {}
+        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:
+        self.constants = []
+
+    def argLoc(self, pos):
+        """
+            Gets the function parameter location in IR-code format.
+        """
+        if pos == 0:
+            return self.p1
+        elif pos == 1:
+            return self.p2
+        elif pos == 2:
+            return self.p3
+        elif pos == 3:
+            return self.p4
+        else:
+            raise NotImplementedError('No more than 4 parameters implemented')
+
+    def allocVar(self, lvar):
+        if lvar not in self.locVars:
+            self.locVars[lvar] = self.stacksize
+            self.stacksize = self.stacksize + 4
+        return self.locVars[lvar]
+
+    def addConstant(self, value):
+        lab_name = '{}_literal_{}'.format(self.name, len(self.constants))
+        self.constants.append((lab_name, value))
+        return lab_name
+
+    def EntryExitGlue3(self):
+        """
+            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(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(arm.subspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize))))
+        # Setup frame pointer:
+        self.instructions.insert(3, makeIns(arm.movregreg_ext_ins(arm.r7, arm.sp)))
+        # Stack grows downwards
+        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(Alignment(4))) # Align at 4 bytes
+        for ln, v in self.constants:
+            self.instructions.append(makeIns(arm.Label(ln)))
+            self.instructions.append(makeIns(arm.dcd_ins(v)))
+
+
+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(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()
+            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(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(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(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)
+            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(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 = 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(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(arm.loadimm5_ins, 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(arm.bl_ins(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(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(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.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(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(arm.cmp_ins, src=[a, b])
+            ntgt = self.targets[s.lab_no]
+            ytgt = self.targets[s.lab_yes]
+            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])