Mercurial > lcfOS
annotate 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 |
rev | line source |
---|---|
211 | 1 import ir |
2 from ppci import CompilerError | |
290 | 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 | |
272 | 7 import irmach |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
8 from irmach import AbstractInstruction as makeIns |
275 | 9 import asm |
274 | 10 |
290 | 11 |
274 | 12 class ArmFrame(irmach.Frame): |
13 """ | |
14 Arm specific frame for functions. | |
15 """ | |
275 | 16 def __init__(self, name): |
17 # We use r7 as frame pointer. | |
18 super().__init__(name) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
19 self.regs = [arm.r0, arm.r1, arm.r2, arm.r3, arm.r4, arm.r5, arm.r6] |
275 | 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 = {} | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
28 self.tempMap[self.rv] = arm.r0 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
29 self.tempMap[self.p1] = arm.r1 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
30 self.tempMap[self.p2] = arm.r2 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
31 self.tempMap[self.p3] = arm.r3 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
32 self.tempMap[self.p4] = arm.r4 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
33 self.tempMap[self.fp] = arm.r7 |
275 | 34 self.locVars = {} |
35 self.parMap = {} | |
276 | 36 # Literal pool: |
37 self.constants = [] | |
275 | 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 | |
276 | 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 | |
275 | 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 """ | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
70 self.instructions.insert(0, makeIns(arm.Label(self.name))) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
71 self.instructions.insert(1, makeIns(arm.push_ins(arm.RegisterSet({arm.lr, arm.r7})))) |
279 | 72 # Reserve stack space for locals: |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
73 self.instructions.insert(2, makeIns(arm.subspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize)))) |
279 | 74 # Setup frame pointer: |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
75 self.instructions.insert(3, makeIns(arm.movregreg_ext_ins(arm.r7, arm.sp))) |
279 | 76 # Stack grows downwards |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
77 self.instructions.append(makeIns(arm.addspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize)))) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
78 self.instructions.append(makeIns(arm.pop_ins(arm.RegisterSet({arm.pc, arm.r7})))) |
276 | 79 # Add constant literals: |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
80 self.instructions.append(makeIns(Alignment(4))) # Align at 4 bytes |
276 | 81 for ln, v in self.constants: |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
82 self.instructions.append(makeIns(arm.Label(ln))) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
83 self.instructions.append(makeIns(arm.dcd_ins(v))) |
274 | 84 |
85 | |
268 | 86 class ArmInstructionSelector(InstructionSelector): |
269 | 87 """ Instruction selector for the arm architecture """ |
268 | 88 def munchExpr(self, e): |
89 if isinstance(e, ir.Alloc): | |
90 return 0 | |
279 | 91 elif isinstance(e, ir.Binop) and e.operation == '+' and \ |
92 isinstance(e.b, ir.Const) and e.b.value < 8: | |
275 | 93 a = self.munchExpr(e.a) |
94 d = self.newTmp() | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
95 c = Imm3(e.b.value) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
96 self.emit(arm.addregregimm3_ins, others=[c], dst=[d], src=[a]) |
275 | 97 return d |
268 | 98 elif isinstance(e, ir.Binop) and e.operation == '+': |
275 | 99 a = self.munchExpr(e.a) |
100 b = self.munchExpr(e.b) | |
268 | 101 d = self.newTmp() |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
102 self.emit(arm.addregs_ins, dst=[d], src=[a, b]) |
268 | 103 return d |
279 | 104 elif isinstance(e, ir.Binop) and e.operation == '-' and \ |
105 isinstance(e.b, ir.Const) and e.b.value < 8: | |
275 | 106 a = self.munchExpr(e.a) |
107 d = self.newTmp() | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
108 c = Imm3(e.b.value) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
109 self.emit(arm.subregregimm3_ins, others=[c], dst=[d], src=[a]) |
275 | 110 return d |
269 | 111 elif isinstance(e, ir.Binop) and e.operation == '-': |
275 | 112 a = self.munchExpr(e.a) |
113 b = self.munchExpr(e.b) | |
269 | 114 d = self.newTmp() |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
115 self.emit(arm.subregs_ins, dst=[d], src=[a, b]) |
269 | 116 return d |
268 | 117 elif isinstance(e, ir.Binop) and e.operation == '|': |
275 | 118 a = self.munchExpr(e.a) |
119 b = self.munchExpr(e.b) | |
268 | 120 d = self.newTmp() |
279 | 121 self.move(d, a) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
122 self.emit(arm.orrregs_ins, dst=[], src=[b, d]) |
268 | 123 return d |
124 elif isinstance(e, ir.Binop) and e.operation == '<<': | |
275 | 125 a = self.munchExpr(e.a) |
126 b = self.munchExpr(e.b) | |
268 | 127 d = self.newTmp() |
279 | 128 self.move(d, a) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
129 self.emit(arm.lslregs_ins, dst=[], src=[b, d]) # TODO: is d a source variable? |
268 | 130 return d |
131 elif isinstance(e, ir.Binop) and e.operation == '*': | |
275 | 132 a = self.munchExpr(e.a) |
133 b = self.munchExpr(e.b) | |
268 | 134 d = self.newTmp() |
279 | 135 self.move(d, a) |
136 # this mul instruction has operands swapped: | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
137 self.emit(arm.mulregreg_ins, dst=[d], src=[b, d]) |
268 | 138 return d |
275 | 139 elif isinstance(e, ir.Const) and e.value < 256: |
268 | 140 d = self.newTmp() |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
141 self.emit(arm.mov_imm8_ins, others=[arm.Imm8(e.value)], dst=[d]) |
275 | 142 return d |
276 | 143 elif isinstance(e, ir.Const) and e.value < (2**31): |
144 d = self.newTmp() | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
145 ln = LabelRef(self.frame.addConstant(e.value)) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
146 self.emit(arm.ldr_pcrel, others=[ln], dst=[d]) |
276 | 147 return d |
275 | 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() | |
279 | 152 c = e.e.b.value |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
153 self.emit(arm.loadimm5_ins, others=[c], src=[base], dst=[d]) |
268 | 154 return d |
155 elif isinstance(e, ir.Mem): | |
156 # Load from memory | |
275 | 157 base = self.munchExpr(e.e) |
268 | 158 d = self.newTmp() |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
159 self.emit(arm.loadimm5_ins, others=[0], src=[base], dst=[d]) |
268 | 160 return d |
161 elif isinstance(e, ir.Temp): | |
275 | 162 return e |
272 | 163 elif isinstance(e, ir.Call): |
275 | 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) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
172 self.emit(arm.bl_ins(LabelRef(e.f.name)), src=reguses, dst=[self.frame.rv]) |
275 | 173 d = self.newTmp() |
174 self.move(d, self.frame.rv) | |
175 return d | |
268 | 176 else: |
272 | 177 raise NotImplementedError('Expr --> {}'.format(e)) |
268 | 178 |
179 def munchStm(self, s): | |
275 | 180 if isinstance(s, ir.Terminator): |
181 pass | |
279 | 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) | |
275 | 186 val = self.munchExpr(s.src) |
279 | 187 c = s.dst.e.b.value |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
188 self.emit(arm.storeimm5_ins, others=[c], src=[a, val]) |
275 | 189 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem): |
268 | 190 memloc = self.munchExpr(s.dst.e) |
191 val = self.munchExpr(s.src) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
192 self.emit(arm.storeimm5_ins, others=[0], src=[memloc, val]) |
268 | 193 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp): |
194 val = self.munchExpr(s.src) | |
275 | 195 dreg = s.dst |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
196 self.move(dreg, val) |
275 | 197 elif isinstance(s, ir.Exp): |
198 # Generate expression code and discard the result. | |
199 x = self.munchExpr(s.e) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
200 self.emit(Nop(), src=[x]) |
268 | 201 elif isinstance(s, ir.Jump): |
269 | 202 tgt = self.targets[s.target] |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
203 self.emit(arm.b_ins(LabelRef(s.target.name)), jumps=[tgt]) |
268 | 204 elif isinstance(s, ir.CJump): |
269 | 205 a = self.munchExpr(s.a) |
206 b = self.munchExpr(s.b) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
207 self.emit(arm.cmp_ins, src=[a, b]) |
269 | 208 ntgt = self.targets[s.lab_no] |
209 ytgt = self.targets[s.lab_yes] | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
210 jmp_ins = makeIns(arm.b_ins(LabelRef(s.lab_no.name)), jumps=[ntgt]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
211 opnames = {'<': arm.blt_ins, '>':arm.bgt_ins, '==':arm.beq_ins} |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
212 op = opnames[s.cond](LabelRef(s.lab_yes.name)) |
290 | 213 self.emit(op, jumps=[ytgt, jmp_ins]) # Explicitely add fallthrough |
269 | 214 self.emit2(jmp_ins) |
268 | 215 else: |
274 | 216 raise NotImplementedError('Stmt --> {}'.format(s)) |
268 | 217 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
218 def move(self, dst, src): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
219 self.emit(arm.movregreg_ext_ins, src=[src], dst=[dst]) |