Mercurial > lcfOS
comparison python/cortexm3.py @ 219:1fa3e0050b49
Expanded ad hoc code generator
author | Windel Bouwman |
---|---|
date | Sat, 06 Jul 2013 12:38:09 +0200 |
parents | 494828a7adf1 |
children | 85c8105318e7 |
comparison
equal
deleted
inserted
replaced
218:494828a7adf1 | 219:1fa3e0050b49 |
---|---|
1 import struct, types | 1 import struct, types |
2 from target import Register, Instruction, Target, Imm8, Label, Imm3 | 2 from target import Register, Instruction, Target, Imm8, Label, Imm3 |
3 from asmnodes import ASymbol, ANumber, AUnop, ABinop | 3 from asmnodes import ASymbol, ANumber, AUnop, ABinop, ALabel |
4 from ppci import CompilerError | 4 from ppci import CompilerError |
5 import ir | 5 import ir |
6 | 6 |
7 # TODO: encode this in DSL (domain specific language) | 7 # TODO: encode this in DSL (domain specific language) |
8 | 8 |
34 for r in armtarget.registers: | 34 for r in armtarget.registers: |
35 regs[r.name] = r | 35 regs[r.name] = r |
36 if name in regs: | 36 if name in regs: |
37 r = regs[name] | 37 r = regs[name] |
38 return cls(r.num) | 38 return cls(r.num) |
39 | |
40 class Reg8Op: | |
41 def __init__(self, num): | |
42 assert num < 8 | |
43 self.num = num | |
44 | |
45 @classmethod | |
46 def Create(cls, vop): | |
47 if type(vop) is ASymbol: | |
48 name = vop.name | |
49 regs = {} | |
50 for r in armtarget.registers: | |
51 regs[r.name] = r | |
52 if name in regs: | |
53 r = regs[name] | |
54 if r.num < 8: | |
55 return cls(r.num) | |
39 | 56 |
40 def getRegNum(n): | 57 def getRegNum(n): |
41 for r in armtarget.registers: | 58 for r in armtarget.registers: |
42 if r.num == n: | 59 if r.num == n: |
43 return r | 60 return r |
54 class MemoryOp: | 71 class MemoryOp: |
55 def __init__(self, basereg, offset): | 72 def __init__(self, basereg, offset): |
56 assert type(basereg) is ArmReg | 73 assert type(basereg) is ArmReg |
57 self.basereg = basereg | 74 self.basereg = basereg |
58 self.offset = offset | 75 self.offset = offset |
76 | |
77 def __repr__(self): | |
78 return '[{}, #{}]'.format(self.basereg, self.offset) | |
59 | 79 |
60 @classmethod | 80 @classmethod |
61 def Create(cls, vop): | 81 def Create(cls, vop): |
62 if type(vop) is AUnop and vop.operation == '[]': | 82 if type(vop) is AUnop and vop.operation == '[]': |
63 vop = vop.arg # descent | 83 vop = vop.arg # descent |
75 if not basereg: | 95 if not basereg: |
76 return | 96 return |
77 else: | 97 else: |
78 return | 98 return |
79 return cls(getRegNum(basereg.num), offset) | 99 return cls(getRegNum(basereg.num), offset) |
80 pass | 100 |
101 class MemoryOpReg8Imm5: | |
102 def __init__(self, basereg, offset): | |
103 assert type(basereg) is ArmReg | |
104 self.basereg = basereg | |
105 self.offset = offset | |
106 | |
107 def __repr__(self): | |
108 return '[{}, #{}]'.format(self.basereg, self.offset) | |
109 | |
110 @classmethod | |
111 def Create(cls, vop): | |
112 if type(vop) is AUnop and vop.operation == '[]': | |
113 vop = vop.arg # descent | |
114 if type(vop) is ABinop: | |
115 if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: | |
116 offset = vop.arg2.number | |
117 if offset > 120: | |
118 return | |
119 basereg = Reg8Op.Create(vop.arg1) | |
120 if not basereg: | |
121 return | |
122 else: | |
123 return | |
124 elif type(vop) is ASymbol: | |
125 offset = 0 | |
126 basereg = Reg8Op.Create(vop) | |
127 if not basereg: | |
128 return | |
129 else: | |
130 return | |
131 return cls(getRegNum(basereg.num), offset) | |
81 | 132 |
82 class RegisterSet: | 133 class RegisterSet: |
83 def __init__(self, regs): | 134 def __init__(self, regs): |
84 assert type(regs) is set | 135 assert type(regs) is set |
85 self.regs = regs | 136 self.regs = regs |
127 armtarget.registers.append(r5) | 178 armtarget.registers.append(r5) |
128 r6 = ArmReg(6, 'r6') | 179 r6 = ArmReg(6, 'r6') |
129 armtarget.registers.append(r6) | 180 armtarget.registers.append(r6) |
130 r7 = ArmReg(7, 'r7') | 181 r7 = ArmReg(7, 'r7') |
131 armtarget.registers.append(r7) | 182 armtarget.registers.append(r7) |
132 r10 = ArmReg(10, 'r10') | |
133 armtarget.registers.append(r10) | |
134 r11 = ArmReg(11, 'r11') | |
135 armtarget.registers.append(r11) | |
136 # Other registers: | 183 # Other registers: |
137 # TODO | 184 # TODO |
138 sp = ArmReg(13, 'sp') | 185 sp = ArmReg(13, 'sp') |
139 armtarget.registers.append(sp) | 186 armtarget.registers.append(sp) |
140 lr = ArmReg(14, 'lr') | 187 lr = ArmReg(14, 'lr') |
143 armtarget.registers.append(pc) | 190 armtarget.registers.append(pc) |
144 | 191 |
145 class ArmInstruction(Instruction): | 192 class ArmInstruction(Instruction): |
146 pass | 193 pass |
147 | 194 |
148 class ldr_ins(ArmInstruction): | |
149 mnemonic = 'ldr' | |
150 opcode = 1337 | |
151 irpattern = 'todo' | |
152 | |
153 class dcd_ins(ArmInstruction): | 195 class dcd_ins(ArmInstruction): |
154 mnemonic = 'dcd' | 196 mnemonic = 'dcd' |
155 def __init__(self, expr): | 197 def __init__(self, expr): |
156 self.expr = expr | 198 self.expr = expr |
199 | |
157 def encode(self): | 200 def encode(self): |
158 return u32(self.expr) | 201 return u32(self.expr) |
159 | 202 |
160 @armtarget.instruction | 203 def __repr__(self): |
161 class storeimm5_ins(ArmInstruction): | 204 return 'DCD 0x{0:X}'.format(self.expr) |
162 """ str Rt, [Rn, imm5], store value into memory """ | 205 |
163 mnemonic = 'str' | 206 |
164 operands = (RegOp, MemoryOp) | 207 |
208 # Memory related | |
209 | |
210 class LS_imm5_base(ArmInstruction): | |
211 """ ??? Rt, [Rn, imm5] """ | |
212 operands = (Reg8Op, MemoryOpReg8Imm5) | |
165 def __init__(self, rt, memop): | 213 def __init__(self, rt, memop): |
166 assert memop.offset % 4 == 0 | 214 assert memop.offset % 4 == 0 |
167 self.imm5 = memop.offset >> 2 | 215 self.imm5 = memop.offset >> 2 |
168 self.rn = memop.basereg.num | 216 self.rn = memop.basereg.num |
169 self.rt = rt.num | 217 self.rt = rt.num |
218 self.memloc = memop | |
219 assert self.rn < 8 | |
220 assert self.rt < 8 | |
170 | 221 |
171 def encode(self): | 222 def encode(self): |
172 Rn = self.rn | 223 Rn = self.rn |
173 Rt = self.rt | 224 Rt = self.rt |
174 imm5 = self.imm5 | 225 imm5 = self.imm5 |
175 h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt | 226 |
176 return u16(h) | 227 h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt |
177 | 228 return u16(h) |
178 @armtarget.instruction | 229 def __repr__(self): |
179 class loadimm5_ins(ArmInstruction): | 230 return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) |
180 """ str Rt, [Rn, imm5], store value into memory """ | 231 |
232 @armtarget.instruction | |
233 class storeimm5_ins(LS_imm5_base): | |
234 mnemonic = 'STR' | |
235 opcode = 0xC | |
236 | |
237 @armtarget.instruction | |
238 class loadimm5_ins(LS_imm5_base): | |
239 mnemonic = 'LDR' | |
240 opcode = 0xD | |
241 | |
242 class ls_sp_base_imm8(ArmInstruction): | |
243 operands = (Reg8Op, MemoryOp) | |
244 def __init__(self, rt, memop): | |
245 self.rt = rt | |
246 assert memop.basereg.num == 13 | |
247 self.offset = memop.offset | |
248 | |
249 def encode(self): | |
250 rt = self.rt.num | |
251 assert rt < 8 | |
252 imm8 = self.offset >> 2 | |
253 assert imm8 < 256 | |
254 h = (self.opcode << 8) | (rt << 8) | imm8 | |
255 return u16(h) | |
256 | |
257 def __repr__(self): | |
258 return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) | |
259 | |
260 @armtarget.instruction | |
261 class ldr_pcrel(ArmInstruction): | |
262 """ ldr Rt, [PC, imm8], store value into memory """ | |
181 mnemonic = 'ldr' | 263 mnemonic = 'ldr' |
182 operands = (RegOp, MemoryOp) | 264 operands = (RegOp, MemoryOp) |
183 def __init__(self, rt, memop): | 265 def __init__(self, rt, label): |
184 assert memop.offset % 4 == 0 | 266 self.rt = rt |
185 self.imm5 = memop.offset >> 2 | 267 self.label = label |
186 self.rn = memop.basereg.num | 268 self.offset = 0 |
187 self.rt = rt.num | 269 |
188 | 270 def encode(self): |
189 def encode(self): | 271 rt = self.rt.num |
190 Rn = self.rn | 272 assert rt < 8 |
191 Rt = self.rt | 273 imm8 = self.offset >> 2 |
192 imm5 = self.imm5 | 274 assert imm8 < 256 |
193 h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt | 275 h = (0x9 << 11) | (rt << 8) | imm8 |
194 return u16(h) | 276 return u16(h) |
277 | |
278 def __repr__(self): | |
279 return 'LDR {}, [pc,#{}]'.format(self.rt, self.offset) | |
280 | |
281 @armtarget.instruction | |
282 class ldr_sprel(ls_sp_base_imm8): | |
283 """ ldr Rt, [SP, imm8] """ | |
284 mnemonic = 'LDR' | |
285 opcode = 0x98 | |
286 | |
287 @armtarget.instruction | |
288 class str_sprel(ls_sp_base_imm8): | |
289 """ str Rt, [SP, imm8] """ | |
290 mnemonic = 'STR' | |
291 opcode = 0x90 | |
195 | 292 |
196 @armtarget.instruction | 293 @armtarget.instruction |
197 class mov_ins(ArmInstruction): | 294 class mov_ins(ArmInstruction): |
198 """ mov Rd, imm8, move immediate value into register """ | 295 """ mov Rd, imm8, move immediate value into register """ |
199 mnemonic = 'mov' | 296 mnemonic = 'mov' |
202 irpattern = ir.ImmLoad | 299 irpattern = ir.ImmLoad |
203 def __init__(self, rd, imm): | 300 def __init__(self, rd, imm): |
204 self.imm = imm.imm | 301 self.imm = imm.imm |
205 self.r = rd.num | 302 self.r = rd.num |
206 | 303 |
207 @classmethod | |
208 def FromIr(cls, ir_ins): | |
209 pass | |
210 | |
211 def encode(self): | 304 def encode(self): |
212 rd = self.r | 305 rd = self.r |
213 opcode = self.opcode | 306 opcode = self.opcode |
214 imm8 = self.imm | 307 imm8 = self.imm |
215 h = (opcode << 11) | (rd << 8) | imm8 | 308 h = (opcode << 11) | (rd << 8) | imm8 |
216 return u16(h) | 309 return u16(h) |
310 def __repr__(self): | |
311 return 'MOV {0}, xx?'.format(self.r) | |
217 | 312 |
218 @armtarget.instruction | 313 @armtarget.instruction |
219 class movregreg_ins(ArmInstruction): | 314 class movregreg_ins(ArmInstruction): |
220 """ mov Rd, Rm """ | 315 """ mov Rd, Rm """ |
221 mnemonic = 'mov' | 316 mnemonic = 'mov' |
222 opcode = 8 # 01000 Rd(3) imm8 | |
223 operands = (RegOp, RegOp) | 317 operands = (RegOp, RegOp) |
224 def __init__(self, rd, rm): | 318 def __init__(self, rd, rm): |
225 self.rd = rd | 319 self.rd = rd |
226 self.rm = rm | 320 self.rm = rm |
227 def encode(self): | 321 def encode(self): |
230 assert D < 2 | 324 assert D < 2 |
231 rd = rd & 0x7 | 325 rd = rd & 0x7 |
232 rm = self.rm.num | 326 rm = self.rm.num |
233 assert rm < 16 | 327 assert rm < 16 |
234 opcode = self.opcode | 328 opcode = self.opcode |
235 h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd | 329 h = (1 << 14) | (3 << 9) | (D << 7) | (rm << 3) | rd |
236 return u16(h) | 330 return u16(h) |
331 | |
332 | |
333 | |
334 # Arithmatics: | |
237 | 335 |
238 @armtarget.instruction | 336 @armtarget.instruction |
239 class addregregimm3_ins(ArmInstruction): | 337 class addregregimm3_ins(ArmInstruction): |
240 """ add Rd, Rn, imm3 """ | 338 """ add Rd, Rn, imm3 """ |
241 mnemonic = 'add' | 339 mnemonic = 'add' |
252 imm3 = self.imm3.imm | 350 imm3 = self.imm3.imm |
253 opcode = self.opcode | 351 opcode = self.opcode |
254 h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd | 352 h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd |
255 return u16(h) | 353 return u16(h) |
256 | 354 |
355 class regregreg_base(ArmInstruction): | |
356 """ ??? Rd, Rn, Rm """ | |
357 operands = (Reg8Op, Reg8Op, Reg8Op) | |
358 def __init__(self, rd, rn, rm): | |
359 self.rd = rd | |
360 self.rn = rn | |
361 self.rm = rm | |
362 def encode(self): | |
363 rd = self.rd.num | |
364 rn = self.rn.num | |
365 rm = self.rm.num | |
366 h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd | |
367 return u16(h) | |
368 def __repr__(self): | |
369 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) | |
370 | |
371 @armtarget.instruction | |
372 class addregs_ins(regregreg_base): | |
373 mnemonic = 'ADD' | |
374 opcode = 0b0001100 | |
375 | |
376 @armtarget.instruction | |
377 class subregs_ins(regregreg_base): | |
378 mnemonic = 'SUB' | |
379 opcode = 0b0001101 | |
380 | |
381 class regreg_base(ArmInstruction): | |
382 """ ??? Rdn, Rm """ | |
383 operands = (Reg8Op, Reg8Op) | |
384 def __init__(self, rdn, rm): | |
385 self.rdn = rdn | |
386 self.rm = rm | |
387 def encode(self): | |
388 rdn = self.rdn.num | |
389 rm = self.rm.num | |
390 h = (self.opcode << 6) | (rm << 3) | rdn | |
391 return u16(h) | |
392 def __repr__(self): | |
393 return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) | |
394 | |
395 @armtarget.instruction | |
396 class andregs_ins(regreg_base): | |
397 mnemonic = 'AND' | |
398 opcode = 0b0100000000 | |
399 | |
400 @armtarget.instruction | |
401 class orrregs_ins(regreg_base): | |
402 mnemonic = 'ORR' | |
403 opcode = 0b0100001100 | |
404 | |
405 @armtarget.instruction | |
406 class cmp_ins(regreg_base): | |
407 mnemonic = 'CMP' | |
408 opcode = 0b0100001010 | |
409 | |
257 @armtarget.instruction | 410 @armtarget.instruction |
258 class cmpregimm8_ins(ArmInstruction): | 411 class cmpregimm8_ins(ArmInstruction): |
259 """ cmp Rn, imm8 """ | 412 """ cmp Rn, imm8 """ |
260 mnemonic = 'cmp' | 413 mnemonic = 'cmp' |
261 opcode = 5 # 00101 | 414 opcode = 5 # 00101 |
268 imm = self.imm.imm | 421 imm = self.imm.imm |
269 opcode = self.opcode | 422 opcode = self.opcode |
270 h = (opcode << 11) | (rn << 8) | imm | 423 h = (opcode << 11) | (rn << 8) | imm |
271 return u16(h) | 424 return u16(h) |
272 | 425 |
273 @armtarget.instruction | 426 # Jumping: |
274 class cmp_ins(ArmInstruction): | |
275 """ cmp Rn, Rm """ | |
276 mnemonic = 'cmp' | |
277 operands = (RegOp, RegOp) | |
278 def __init__(self, rn, rm): | |
279 self.rn = rn | |
280 self.rm = rm | |
281 def encode(self): | |
282 rn = self.rn.num | |
283 rm = self.rm.num | |
284 assert rn < 8 | |
285 assert rm < 8 | |
286 opcode = 0x42 | |
287 h = (opcode << 8) | (1 << 7) | (rm << 3) | (rn & 0x7) | |
288 return u16(h) | |
289 | 427 |
290 @armtarget.instruction | 428 @armtarget.instruction |
291 class jmp_ins(ArmInstruction): | 429 class jmp_ins(ArmInstruction): |
292 operands = (Label,) | 430 operands = (ALabel,) |
293 mnemonic = 'jmp' | 431 mnemonic = 'jmp' |
294 def __init__(self, target_label): | 432 def __init__(self, target_label): |
433 assert type(target_label) is ALabel | |
295 self.target = target_label | 434 self.target = target_label |
296 def fixUp(self): | 435 def fixUp(self): |
297 pass | 436 pass |
298 def encode(self): | 437 def encode(self): |
299 h = 1337 # TODO | 438 h = 0 # TODO |
300 return u16(h) | 439 return u16(h) |
440 def __repr__(self): | |
441 return 'B {0}'.format(self.target.name) | |
442 | |
443 @armtarget.instruction | |
444 class beq_ins(ArmInstruction): | |
445 operands = (ALabel,) | |
446 mnemonic = 'beq' | |
447 def __init__(self, target_label): | |
448 assert type(target_label) is ALabel | |
449 self.target = target_label | |
450 def fixUp(self): | |
451 pass | |
452 def encode(self): | |
453 h = 0 # TODO | |
454 return u16(h) | |
455 def __repr__(self): | |
456 return 'BEQ {0}'.format(self.target.name) | |
301 | 457 |
302 @armtarget.instruction | 458 @armtarget.instruction |
303 class push_ins(ArmInstruction): | 459 class push_ins(ArmInstruction): |
304 operands = (RegisterSet,) | 460 operands = (RegisterSet,) |
305 mnemonic = 'push' | 461 mnemonic = 'push' |
339 P = 1 | 495 P = 1 |
340 else: | 496 else: |
341 raise NotImplementedError('not implemented for this register') | 497 raise NotImplementedError('not implemented for this register') |
342 h = (0x5E << 9) | (P << 8) | reg_list | 498 h = (0x5E << 9) | (P << 8) | reg_list |
343 return u16(h) | 499 return u16(h) |
344 return u16(0) | |
345 | 500 |
346 @armtarget.instruction | 501 @armtarget.instruction |
347 class yield_ins(ArmInstruction): | 502 class yield_ins(ArmInstruction): |
348 operands = () | 503 operands = () |
349 mnemonic = 'yield' | 504 mnemonic = 'yield' |