comparison 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
comparison
equal deleted inserted replaced
289:bd2593de3ff8 290:7b38782ed496
1 import ir
2 from ppci import CompilerError
3 from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
4 from .basetarget import Imm32, Imm3
5 import .armtarget as arm
6 from .instructionselector import InstructionSelector
7 import irmach
8 from irmach import AbstractInstruction as makeIns
9 import asm
10
11
12 class ArmFrame(irmach.Frame):
13 """
14 Arm specific frame for functions.
15 """
16 def __init__(self, name):
17 # We use r7 as frame pointer.
18 super().__init__(name)
19 self.regs = [arm.r0, arm.r1, arm.r2, arm.r3, arm.r4, arm.r5, arm.r6]
20 self.rv = ir.Temp('special_RV')
21 self.p1 = ir.Temp('special_P1')
22 self.p2 = ir.Temp('special_P2')
23 self.p3 = ir.Temp('special_P3')
24 self.p4 = ir.Temp('special_P4')
25 self.fp = ir.Temp('special_FP')
26 # Pre-colored registers:
27 self.tempMap = {}
28 self.tempMap[self.rv] = arm.r0
29 self.tempMap[self.p1] = arm.r1
30 self.tempMap[self.p2] = arm.r2
31 self.tempMap[self.p3] = arm.r3
32 self.tempMap[self.p4] = arm.r4
33 self.tempMap[self.fp] = arm.r7
34 self.locVars = {}
35 self.parMap = {}
36 # Literal pool:
37 self.constants = []
38
39 def argLoc(self, pos):
40 """
41 Gets the function parameter location in IR-code format.
42 """
43 if pos == 0:
44 return self.p1
45 elif pos == 1:
46 return self.p2
47 elif pos == 2:
48 return self.p3
49 elif pos == 3:
50 return self.p4
51 else:
52 raise NotImplementedError('No more than 4 parameters implemented')
53
54 def allocVar(self, lvar):
55 if lvar not in self.locVars:
56 self.locVars[lvar] = self.stacksize
57 self.stacksize = self.stacksize + 4
58 return self.locVars[lvar]
59
60 def addConstant(self, value):
61 lab_name = '{}_literal_{}'.format(self.name, len(self.constants))
62 self.constants.append((lab_name, value))
63 return lab_name
64
65 def EntryExitGlue3(self):
66 """
67 Add code for the prologue and the epilogue. Add a label, the
68 return instruction and the stack pointer adjustment for the frame.
69 """
70 self.instructions.insert(0, makeIns(arm.Label(self.name)))
71 self.instructions.insert(1, makeIns(arm.push_ins(arm.RegisterSet({arm.lr, arm.r7}))))
72 # Reserve stack space for locals:
73 self.instructions.insert(2, makeIns(arm.subspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize))))
74 # Setup frame pointer:
75 self.instructions.insert(3, makeIns(arm.movregreg_ext_ins(arm.r7, arm.sp)))
76 # Stack grows downwards
77 self.instructions.append(makeIns(arm.addspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize))))
78 self.instructions.append(makeIns(arm.pop_ins(arm.RegisterSet({arm.pc, arm.r7}))))
79 # Add constant literals:
80 self.instructions.append(makeIns(Alignment(4))) # Align at 4 bytes
81 for ln, v in self.constants:
82 self.instructions.append(makeIns(arm.Label(ln)))
83 self.instructions.append(makeIns(arm.dcd_ins(v)))
84
85
86 class ArmInstructionSelector(InstructionSelector):
87 """ Instruction selector for the arm architecture """
88 def munchExpr(self, e):
89 if isinstance(e, ir.Alloc):
90 return 0
91 elif isinstance(e, ir.Binop) and e.operation == '+' and \
92 isinstance(e.b, ir.Const) and e.b.value < 8:
93 a = self.munchExpr(e.a)
94 d = self.newTmp()
95 c = Imm3(e.b.value)
96 self.emit(arm.addregregimm3_ins, others=[c], dst=[d], src=[a])
97 return d
98 elif isinstance(e, ir.Binop) and e.operation == '+':
99 a = self.munchExpr(e.a)
100 b = self.munchExpr(e.b)
101 d = self.newTmp()
102 self.emit(arm.addregs_ins, dst=[d], src=[a, b])
103 return d
104 elif isinstance(e, ir.Binop) and e.operation == '-' and \
105 isinstance(e.b, ir.Const) and e.b.value < 8:
106 a = self.munchExpr(e.a)
107 d = self.newTmp()
108 c = Imm3(e.b.value)
109 self.emit(arm.subregregimm3_ins, others=[c], dst=[d], src=[a])
110 return d
111 elif isinstance(e, ir.Binop) and e.operation == '-':
112 a = self.munchExpr(e.a)
113 b = self.munchExpr(e.b)
114 d = self.newTmp()
115 self.emit(arm.subregs_ins, dst=[d], src=[a, b])
116 return d
117 elif isinstance(e, ir.Binop) and e.operation == '|':
118 a = self.munchExpr(e.a)
119 b = self.munchExpr(e.b)
120 d = self.newTmp()
121 self.move(d, a)
122 self.emit(arm.orrregs_ins, dst=[], src=[b, d])
123 return d
124 elif isinstance(e, ir.Binop) and e.operation == '<<':
125 a = self.munchExpr(e.a)
126 b = self.munchExpr(e.b)
127 d = self.newTmp()
128 self.move(d, a)
129 self.emit(arm.lslregs_ins, dst=[], src=[b, d]) # TODO: is d a source variable?
130 return d
131 elif isinstance(e, ir.Binop) and e.operation == '*':
132 a = self.munchExpr(e.a)
133 b = self.munchExpr(e.b)
134 d = self.newTmp()
135 self.move(d, a)
136 # this mul instruction has operands swapped:
137 self.emit(arm.mulregreg_ins, dst=[d], src=[b, d])
138 return d
139 elif isinstance(e, ir.Const) and e.value < 256:
140 d = self.newTmp()
141 self.emit(arm.mov_imm8_ins, others=[arm.Imm8(e.value)], dst=[d])
142 return d
143 elif isinstance(e, ir.Const) and e.value < (2**31):
144 d = self.newTmp()
145 ln = LabelRef(self.frame.addConstant(e.value))
146 self.emit(arm.ldr_pcrel, others=[ln], dst=[d])
147 return d
148 elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \
149 e.e.operation == '+' and isinstance(e.e.b, ir.Const):
150 base = self.munchExpr(e.e.a)
151 d = self.newTmp()
152 c = e.e.b.value
153 self.emit(arm.loadimm5_ins, others=[c], src=[base], dst=[d])
154 return d
155 elif isinstance(e, ir.Mem):
156 # Load from memory
157 base = self.munchExpr(e.e)
158 d = self.newTmp()
159 self.emit(arm.loadimm5_ins, others=[0], src=[base], dst=[d])
160 return d
161 elif isinstance(e, ir.Temp):
162 return e
163 elif isinstance(e, ir.Call):
164 # Move arguments into proper locations:
165 reguses = []
166 for i, a in enumerate(e.arguments):
167 loc = self.frame.argLoc(i)
168 m = ir.Move(loc, a)
169 self.munchStm(m)
170 if isinstance(loc, ir.Temp):
171 reguses.append(loc)
172 self.emit(arm.bl_ins(LabelRef(e.f.name)), src=reguses, dst=[self.frame.rv])
173 d = self.newTmp()
174 self.move(d, self.frame.rv)
175 return d
176 else:
177 raise NotImplementedError('Expr --> {}'.format(e))
178
179 def munchStm(self, s):
180 if isinstance(s, ir.Terminator):
181 pass
182 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \
183 isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \
184 isinstance(s.dst.e.b, ir.Const):
185 a = self.munchExpr(s.dst.e.a)
186 val = self.munchExpr(s.src)
187 c = s.dst.e.b.value
188 self.emit(arm.storeimm5_ins, others=[c], src=[a, val])
189 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
190 memloc = self.munchExpr(s.dst.e)
191 val = self.munchExpr(s.src)
192 self.emit(arm.storeimm5_ins, others=[0], src=[memloc, val])
193 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
194 val = self.munchExpr(s.src)
195 dreg = s.dst
196 self.move(dreg, val)
197 elif isinstance(s, ir.Exp):
198 # Generate expression code and discard the result.
199 x = self.munchExpr(s.e)
200 self.emit(Nop(), src=[x])
201 elif isinstance(s, ir.Jump):
202 tgt = self.targets[s.target]
203 self.emit(arm.b_ins(LabelRef(s.target.name)), jumps=[tgt])
204 elif isinstance(s, ir.CJump):
205 a = self.munchExpr(s.a)
206 b = self.munchExpr(s.b)
207 self.emit(arm.cmp_ins, src=[a, b])
208 ntgt = self.targets[s.lab_no]
209 ytgt = self.targets[s.lab_yes]
210 jmp_ins = makeIns(arm.b_ins(LabelRef(s.lab_no.name)), jumps=[ntgt])
211 opnames = {'<': arm.blt_ins, '>':arm.bgt_ins, '==':arm.beq_ins}
212 op = opnames[s.cond](LabelRef(s.lab_yes.name))
213 self.emit(op, jumps=[ytgt, jmp_ins]) # Explicitely add fallthrough
214 self.emit2(jmp_ins)
215 else:
216 raise NotImplementedError('Stmt --> {}'.format(s))
217
218 def move(self, dst, src):
219 self.emit(arm.movregreg_ext_ins, src=[src], dst=[dst])