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'