Mercurial > lcfOS
annotate python/cortexm3.py @ 287:1c7c1e619be8
File movage
author | Windel Bouwman |
---|---|
date | Thu, 21 Nov 2013 11:57:27 +0100 |
parents | 02385f62f250 |
children |
rev | line source |
---|---|
261 | 1 import struct |
2 import types | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
3 from target import Register, Instruction, Target, Imm8, Label, Imm3, LabelRef |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
4 from target import Imm32, Imm7 |
234 | 5 from asmnodes import ASymbol, ANumber, AUnop, ABinop |
202 | 6 from ppci import CompilerError |
205 | 7 import ir |
202 | 8 |
287 | 9 """ |
10 ARM target description. | |
11 """ | |
12 | |
218 | 13 # TODO: encode this in DSL (domain specific language) |
275 | 14 # TBD: is this required? |
218 | 15 |
202 | 16 def u16(h): |
17 return struct.pack('<H', h) | |
18 | |
205 | 19 def u32(x): |
20 return struct.pack('<I', x) | |
21 | |
202 | 22 armtarget = Target('arm') |
23 | |
277 | 24 class ArmRegister(Register): |
202 | 25 def __init__(self, num, name): |
26 super().__init__(name) | |
27 self.num = num | |
277 | 28 |
206 | 29 def __repr__(self): |
30 return self.name | |
202 | 31 |
203 | 32 @classmethod |
33 def Create(cls, vop): | |
34 if type(vop) is ASymbol: | |
35 name = vop.name | |
36 regs = {} | |
37 for r in armtarget.registers: | |
38 regs[r.name] = r | |
39 if name in regs: | |
40 r = regs[name] | |
277 | 41 if isinstance(r, cls): |
42 return r | |
234 | 43 |
219 | 44 |
277 | 45 class Reg8Op(ArmRegister): |
46 pass | |
47 | |
203 | 48 |
277 | 49 class Reg16Op(ArmRegister): |
50 pass | |
275 | 51 |
52 | |
53 class RegSpOp: | |
54 @classmethod | |
55 def Create(cls, vop): | |
56 if type(vop) is ASymbol: | |
57 if vop.name.lower() == 'sp': | |
58 return cls() | |
59 | |
206 | 60 def getRegNum(n): |
61 for r in armtarget.registers: | |
62 if r.num == n: | |
63 return r | |
203 | 64 |
206 | 65 def getRegisterRange(n1, n2): |
66 regs = [] | |
67 if n1.num < n2.num: | |
68 for n in range(n1.num, n2.num + 1): | |
69 r = getRegNum(n) | |
70 assert r | |
71 regs.append(r) | |
72 return regs | |
203 | 73 |
224 | 74 def isRegOffset(regname, x, y): |
75 if type(x) is ASymbol and type(y) is ANumber and x.name.upper() == regname: | |
76 return y.number | |
77 elif type(y) is ASymbol and type(x) is ANumber and y.name.upper() == regname: | |
78 return x.number | |
79 | |
80 | |
81 class MemRegXRel: | |
82 def __init__(self, offset): | |
83 assert offset % 4 == 0 | |
212 | 84 self.offset = offset |
85 | |
219 | 86 def __repr__(self): |
224 | 87 return '[{}, #{}]'.format(self.regname, self.offset) |
219 | 88 |
212 | 89 @classmethod |
90 def Create(cls, vop): | |
276 | 91 if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+': |
212 | 92 vop = vop.arg # descent |
224 | 93 offset = isRegOffset(cls.regname, vop.arg1, vop.arg2) |
94 if type(offset) is int: | |
95 if offset % 4 == 0: | |
223 | 96 offset = vop.arg2.number |
97 return cls(offset) | |
224 | 98 elif type(vop) is ASymbol and vop.name.upper() == self.regname: |
223 | 99 return cls(0) |
100 | |
276 | 101 |
224 | 102 class MemSpRel(MemRegXRel): |
103 regname = 'SP' | |
104 | |
105 | |
225 | 106 class MemR8Rel: |
219 | 107 def __init__(self, basereg, offset): |
277 | 108 assert type(basereg) is Reg8Op |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
109 assert type(offset) is int |
219 | 110 self.basereg = basereg |
111 self.offset = offset | |
112 | |
113 def __repr__(self): | |
114 return '[{}, #{}]'.format(self.basereg, self.offset) | |
115 | |
116 @classmethod | |
117 def Create(cls, vop): | |
118 if type(vop) is AUnop and vop.operation == '[]': | |
119 vop = vop.arg # descent | |
120 if type(vop) is ABinop: | |
121 if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: | |
122 offset = vop.arg2.number | |
123 if offset > 120: | |
124 return | |
125 basereg = Reg8Op.Create(vop.arg1) | |
126 if not basereg: | |
127 return | |
128 else: | |
129 return | |
130 elif type(vop) is ASymbol: | |
131 offset = 0 | |
132 basereg = Reg8Op.Create(vop) | |
133 if not basereg: | |
134 return | |
135 else: | |
136 return | |
137 return cls(getRegNum(basereg.num), offset) | |
212 | 138 |
205 | 139 class RegisterSet: |
140 def __init__(self, regs): | |
206 | 141 assert type(regs) is set |
142 self.regs = regs | |
276 | 143 |
206 | 144 def __repr__(self): |
145 return ','.join([str(r) for r in self.regs]) | |
276 | 146 |
206 | 147 @classmethod |
148 def Create(cls, vop): | |
149 assert type(vop) is AUnop and vop.operation == '{}' | |
150 assert type(vop.arg) is list | |
151 regs = set() | |
152 for arg in vop.arg: | |
153 if type(arg) is ASymbol: | |
277 | 154 reg = ArmRegister.Create(arg) |
206 | 155 if not reg: |
156 return | |
157 regs.add(reg) | |
158 elif type(arg) is ABinop and arg.op == '-': | |
277 | 159 reg1 = ArmRegister.Create(arg.arg1) |
160 reg2 = ArmRegister.Create(arg.arg2) | |
206 | 161 if not reg1: |
162 return | |
163 if not reg2: | |
164 return | |
165 for r in getRegisterRange(reg1, reg2): | |
166 regs.add(r) | |
167 else: | |
168 raise Exception('Cannot be') | |
169 return cls(regs) | |
170 | |
171 def registerNumbers(self): | |
172 return [r.num for r in self.regs] | |
205 | 173 |
277 | 174 def makeReg(cls, num, name): |
175 r = cls(num, name) | |
176 armtarget.registers.append(r) | |
177 return r | |
178 | |
202 | 179 # 8 bit registers: |
277 | 180 r0 = makeReg(Reg8Op, 0, 'r0') |
181 r1 = makeReg(Reg8Op, 1, 'r1') | |
182 r2 = makeReg(Reg8Op, 2, 'r2') | |
183 r3 = makeReg(Reg8Op, 3, 'r3') | |
184 r4 = makeReg(Reg8Op, 4, 'r4') | |
185 r5 = makeReg(Reg8Op, 5, 'r5') | |
186 r6 = makeReg(Reg8Op, 6, 'r6') | |
187 r7 = makeReg(Reg8Op, 7, 'r7') | |
206 | 188 # Other registers: |
189 # TODO | |
277 | 190 sp = makeReg(ArmRegister, 13, 'sp') |
191 lr = makeReg(ArmRegister, 14, 'lr') | |
192 pc = makeReg(ArmRegister, 15, 'pc') | |
202 | 193 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
194 # Sanity checks: |
277 | 195 assert isinstance(sp, ArmRegister) |
196 assert isinstance(r3, ArmRegister) | |
197 assert ArmRegister.Create(ASymbol('r3')) is r3 | |
198 assert ArmRegister.Create(ASymbol('sp')) is sp | |
276 | 199 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
200 |
202 | 201 class ArmInstruction(Instruction): |
202 pass | |
203 | |
235 | 204 |
205 @armtarget.instruction | |
205 | 206 class dcd_ins(ArmInstruction): |
207 mnemonic = 'dcd' | |
235 | 208 operands = (Imm32,) |
205 | 209 def __init__(self, expr): |
237 | 210 if isinstance(expr, Imm32): |
211 self.expr = expr.imm | |
212 self.label = None | |
213 elif isinstance(expr, LabelRef): | |
214 self.expr = 0 | |
215 self.label = expr | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
216 elif isinstance(expr, int): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
217 self.expr = expr |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
218 self.label = None |
237 | 219 else: |
220 raise NotImplementedError() | |
221 | |
222 def resolve(self, f): | |
223 if self.label: | |
224 self.expr = f(self.label.name) | |
219 | 225 |
205 | 226 def encode(self): |
227 return u32(self.expr) | |
202 | 228 |
219 | 229 def __repr__(self): |
230 return 'DCD 0x{0:X}'.format(self.expr) | |
231 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
232 |
279 | 233 @armtarget.instruction |
234 class nop_ins(ArmInstruction): | |
235 mnemonic = 'nop' | |
236 operands = tuple() | |
237 | |
238 def encode(self): | |
239 return bytes() | |
240 | |
241 def __repr__(self): | |
242 return 'NOP' | |
219 | 243 |
244 | |
245 # Memory related | |
246 | |
247 class LS_imm5_base(ArmInstruction): | |
248 """ ??? Rt, [Rn, imm5] """ | |
225 | 249 operands = (Reg8Op, MemR8Rel) |
212 | 250 def __init__(self, rt, memop): |
251 assert memop.offset % 4 == 0 | |
252 self.imm5 = memop.offset >> 2 | |
253 self.rn = memop.basereg.num | |
225 | 254 self.rt = rt |
219 | 255 self.memloc = memop |
256 assert self.rn < 8 | |
225 | 257 assert self.rt.num < 8 |
212 | 258 |
259 def encode(self): | |
260 Rn = self.rn | |
225 | 261 Rt = self.rt.num |
212 | 262 imm5 = self.imm5 |
219 | 263 |
264 h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt | |
265 return u16(h) | |
275 | 266 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
267 |
219 | 268 def __repr__(self): |
269 return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) | |
270 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
271 |
219 | 272 @armtarget.instruction |
273 class storeimm5_ins(LS_imm5_base): | |
274 mnemonic = 'STR' | |
275 opcode = 0xC | |
276 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
277 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
278 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
279 mem = MemR8Rel(im.src[0], im.others[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
280 return cls(im.src[1], mem) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
281 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
282 |
219 | 283 @armtarget.instruction |
284 class loadimm5_ins(LS_imm5_base): | |
285 mnemonic = 'LDR' | |
286 opcode = 0xD | |
287 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
288 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
289 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
290 mem = MemR8Rel(im.src[0], im.others[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
291 return cls(im.dst[0], mem) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
292 |
219 | 293 class ls_sp_base_imm8(ArmInstruction): |
224 | 294 operands = (Reg8Op, MemSpRel) |
219 | 295 def __init__(self, rt, memop): |
296 self.rt = rt | |
297 self.offset = memop.offset | |
298 | |
299 def encode(self): | |
300 rt = self.rt.num | |
301 assert rt < 8 | |
302 imm8 = self.offset >> 2 | |
303 assert imm8 < 256 | |
304 h = (self.opcode << 8) | (rt << 8) | imm8 | |
212 | 305 return u16(h) |
306 | |
219 | 307 def __repr__(self): |
308 return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) | |
309 | |
236 | 310 def align(x, m): |
311 while ((x % m) != 0): | |
312 x = x + 1 | |
313 return x | |
314 | |
277 | 315 |
212 | 316 @armtarget.instruction |
219 | 317 class ldr_pcrel(ArmInstruction): |
276 | 318 """ ldr Rt, LABEL, load value from pc relative position """ |
212 | 319 mnemonic = 'ldr' |
277 | 320 operands = (Reg8Op, LabelRef) |
219 | 321 def __init__(self, rt, label): |
235 | 322 assert isinstance(label, LabelRef) |
219 | 323 self.rt = rt |
324 self.label = label | |
325 self.offset = 0 | |
212 | 326 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
327 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
328 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
329 return cls(im.dst[0], im.others[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
330 |
234 | 331 def resolve(self, f): |
235 | 332 la = f(self.label.name) |
236 | 333 sa = align(self.address + 2, 4) |
334 self.offset = (la - sa) | |
235 | 335 if self.offset < 0: |
336 self.offset = 0 | |
234 | 337 |
212 | 338 def encode(self): |
219 | 339 rt = self.rt.num |
340 assert rt < 8 | |
279 | 341 assert self.offset % 4 == 0 |
219 | 342 imm8 = self.offset >> 2 |
343 assert imm8 < 256 | |
235 | 344 assert imm8 >= 0 |
219 | 345 h = (0x9 << 11) | (rt << 8) | imm8 |
212 | 346 return u16(h) |
347 | |
219 | 348 def __repr__(self): |
232 | 349 return 'LDR {}, {}'.format(self.rt, self.label.name) |
219 | 350 |
277 | 351 |
219 | 352 @armtarget.instruction |
353 class ldr_sprel(ls_sp_base_imm8): | |
354 """ ldr Rt, [SP, imm8] """ | |
355 mnemonic = 'LDR' | |
356 opcode = 0x98 | |
357 | |
277 | 358 |
219 | 359 @armtarget.instruction |
360 class str_sprel(ls_sp_base_imm8): | |
361 """ str Rt, [SP, imm8] """ | |
362 mnemonic = 'STR' | |
363 opcode = 0x90 | |
364 | |
277 | 365 |
212 | 366 @armtarget.instruction |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
367 class mov_imm8_ins(ArmInstruction): |
202 | 368 """ mov Rd, imm8, move immediate value into register """ |
369 mnemonic = 'mov' | |
203 | 370 opcode = 4 # 00100 Rd(3) imm8 |
277 | 371 operands = (Reg8Op, Imm8) |
203 | 372 def __init__(self, rd, imm): |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
373 if type(imm) is int: |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
374 imm = Imm8(imm) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
375 assert type(imm) is Imm8 |
203 | 376 self.imm = imm.imm |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
377 assert type(rd) is Reg8Op, str(type(rd)) |
277 | 378 self.rd = rd |
205 | 379 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
380 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
381 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
382 return cls(im.dst[0], im.others[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
383 |
202 | 384 def encode(self): |
277 | 385 rd = self.rd.num |
202 | 386 opcode = self.opcode |
387 imm8 = self.imm | |
388 h = (opcode << 11) | (rd << 8) | imm8 | |
389 return u16(h) | |
277 | 390 |
219 | 391 def __repr__(self): |
277 | 392 return 'MOV {}, {}'.format(self.rd, self.imm) |
203 | 393 |
219 | 394 |
395 | |
396 # Arithmatics: | |
397 | |
275 | 398 |
399 | |
276 | 400 class regregimm3_base(ArmInstruction): |
401 operands = (Reg8Op, Reg8Op, Imm3) | |
203 | 402 def __init__(self, rd, rn, imm3): |
403 self.rd = rd | |
404 self.rn = rn | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
405 assert type(imm3) is Imm3 |
203 | 406 self.imm3 = imm3 |
277 | 407 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
408 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
409 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
410 return cls(im.dst[0], im.src[0], im.others[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
411 |
203 | 412 def encode(self): |
413 rd = self.rd.num | |
414 rn = self.rn.num | |
415 imm3 = self.imm3.imm | |
416 opcode = self.opcode | |
276 | 417 h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd |
203 | 418 return u16(h) |
419 | |
277 | 420 def __repr__(self): |
421 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm) | |
276 | 422 |
423 @armtarget.instruction | |
424 class addregregimm3_ins(regregimm3_base): | |
425 """ add Rd, Rn, imm3 """ | |
426 mnemonic = 'add' | |
427 opcode = 0b0001110 | |
428 | |
429 | |
430 @armtarget.instruction | |
431 class subregregimm3_ins(regregimm3_base): | |
432 """ sub Rd, Rn, imm3 """ | |
433 mnemonic = 'sub' | |
434 opcode = 0b0001111 | |
435 | |
436 | |
219 | 437 class regregreg_base(ArmInstruction): |
438 """ ??? Rd, Rn, Rm """ | |
439 operands = (Reg8Op, Reg8Op, Reg8Op) | |
440 def __init__(self, rd, rn, rm): | |
441 self.rd = rd | |
442 self.rn = rn | |
443 self.rm = rm | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
444 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
445 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
446 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
447 return cls(im.dst[0], im.src[0], im.src[1]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
448 |
219 | 449 def encode(self): |
450 rd = self.rd.num | |
451 rn = self.rn.num | |
452 rm = self.rm.num | |
453 h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd | |
454 return u16(h) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
455 |
219 | 456 def __repr__(self): |
457 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) | |
458 | |
277 | 459 |
219 | 460 @armtarget.instruction |
461 class addregs_ins(regregreg_base): | |
462 mnemonic = 'ADD' | |
463 opcode = 0b0001100 | |
464 | |
277 | 465 |
219 | 466 @armtarget.instruction |
467 class subregs_ins(regregreg_base): | |
468 mnemonic = 'SUB' | |
469 opcode = 0b0001101 | |
470 | |
275 | 471 |
277 | 472 |
275 | 473 @armtarget.instruction |
474 class movregreg_ext_ins(ArmInstruction): | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
475 """ mov rd, rm """ |
277 | 476 operands = (ArmRegister, ArmRegister) |
275 | 477 mnemonic = 'MOV' |
478 def __init__(self, rd, rm): | |
479 self.rd = rd | |
480 self.rm = rm | |
277 | 481 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
482 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
483 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
484 return cls(im.dst[0], im.src[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
485 |
275 | 486 def encode(self): |
487 Rd = self.rd.num & 0x7 | |
488 D = (self.rd.num >> 3) & 0x1 | |
489 Rm = self.rm.num | |
490 opcode = 0b01000110 | |
491 return u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) | |
277 | 492 |
275 | 493 def __repr__(self): |
494 return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) | |
495 | |
496 | |
276 | 497 @armtarget.instruction |
498 class mulregreg_ins(ArmInstruction): | |
499 """ mul Rn, Rdm """ | |
500 operands = (Reg8Op, Reg8Op) | |
279 | 501 mnemonic = 'MUL' |
276 | 502 def __init__(self, rn, rdm): |
503 self.rn = rn | |
504 self.rdm = rdm | |
277 | 505 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
506 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
507 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
508 assert im.src[1] is im.dst[0] |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
509 return cls(im.src[0], im.dst[0]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
510 |
276 | 511 def encode(self): |
512 rn = self.rn.num | |
513 rdm = self.rdm.num | |
514 opcode = 0b0100001101 | |
515 h = (opcode << 6) | (rn << 3) | rdm | |
516 return u16(h) | |
277 | 517 |
276 | 518 def __repr__(self): |
277 | 519 return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) |
520 | |
275 | 521 |
219 | 522 class regreg_base(ArmInstruction): |
523 """ ??? Rdn, Rm """ | |
524 operands = (Reg8Op, Reg8Op) | |
277 | 525 # TODO: integrate with the code gen interface: |
526 src = (0, 1) | |
527 dst = (0,) | |
219 | 528 def __init__(self, rdn, rm): |
529 self.rdn = rdn | |
530 self.rm = rm | |
277 | 531 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
532 @classmethod |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
533 def fromim(cls, im): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
534 return cls(im.src[0], im.src[1]) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
535 |
219 | 536 def encode(self): |
537 rdn = self.rdn.num | |
538 rm = self.rm.num | |
539 h = (self.opcode << 6) | (rm << 3) | rdn | |
540 return u16(h) | |
277 | 541 |
219 | 542 def __repr__(self): |
543 return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) | |
544 | |
277 | 545 |
219 | 546 @armtarget.instruction |
258 | 547 class movregreg_ins(regreg_base): |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
548 """ mov Rd, Rm (reg8 operands) """ |
277 | 549 # TODO: match this: |
550 pattern = ir.Move(ir.Temp, ir.Temp) | |
258 | 551 mnemonic = 'mov' |
552 opcode = 0 | |
553 | |
277 | 554 |
258 | 555 @armtarget.instruction |
219 | 556 class andregs_ins(regreg_base): |
557 mnemonic = 'AND' | |
558 opcode = 0b0100000000 | |
559 | |
277 | 560 |
219 | 561 @armtarget.instruction |
562 class orrregs_ins(regreg_base): | |
563 mnemonic = 'ORR' | |
564 opcode = 0b0100001100 | |
565 | |
277 | 566 |
219 | 567 @armtarget.instruction |
568 class cmp_ins(regreg_base): | |
569 mnemonic = 'CMP' | |
570 opcode = 0b0100001010 | |
571 | |
277 | 572 |
203 | 573 @armtarget.instruction |
232 | 574 class lslregs_ins(regreg_base): |
575 mnemonic = 'LSL' | |
576 opcode = 0b0100000010 | |
577 | |
578 @armtarget.instruction | |
203 | 579 class cmpregimm8_ins(ArmInstruction): |
580 """ cmp Rn, imm8 """ | |
581 mnemonic = 'cmp' | |
582 opcode = 5 # 00101 | |
277 | 583 operands = (Reg8Op, Imm8) |
203 | 584 def __init__(self, rn, imm): |
585 self.rn = rn | |
586 self.imm = imm | |
587 def encode(self): | |
588 rn = self.rn.num | |
589 imm = self.imm.imm | |
590 opcode = self.opcode | |
591 h = (opcode << 11) | (rn << 8) | imm | |
592 return u16(h) | |
202 | 593 |
277 | 594 |
219 | 595 # Jumping: |
218 | 596 |
238 | 597 def wrap_negative(x, bits): |
598 b = struct.unpack('<I', struct.pack('<i', x))[0] | |
599 mask = (1 << bits) - 1 | |
600 return b & mask | |
601 | |
237 | 602 class jumpBase_ins(ArmInstruction): |
603 operands = (LabelRef,) | |
205 | 604 def __init__(self, target_label): |
237 | 605 assert type(target_label) is LabelRef |
205 | 606 self.target = target_label |
237 | 607 self.offset = 0 |
608 | |
609 def resolve(self, f): | |
610 la = f(self.target.name) | |
238 | 611 sa = self.address + 4 |
237 | 612 self.offset = (la - sa) |
613 | |
219 | 614 def __repr__(self): |
237 | 615 return '{} {}'.format(self.mnemonic, self.target.name) |
219 | 616 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
617 |
219 | 618 @armtarget.instruction |
237 | 619 class b_ins(jumpBase_ins): |
620 mnemonic = 'B' | |
621 def encode(self): | |
238 | 622 imm11 = wrap_negative(self.offset >> 1, 11) |
623 h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode | |
237 | 624 return u16(h) |
625 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
626 |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
627 @armtarget.instruction |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
628 class bl_ins(jumpBase_ins): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
629 mnemonic = 'BL' |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
630 def encode(self): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
631 imm32 = wrap_negative(self.offset >> 1, 32) |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
632 imm11 = imm32 & 0x7FF |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
633 imm10 = (imm32 >> 11) & 0x3FF |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
634 j1 = 1 # TODO: what do these mean? |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
635 j2 = 1 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
636 s = (imm32 >> 24) & 0x1 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
637 h1 = (0b11110 << 11) | (s << 10) | imm10 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
638 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
639 return u16(h1) + u16(h2) |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
640 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
641 |
237 | 642 class cond_base_ins(jumpBase_ins): |
643 def encode(self): | |
238 | 644 imm8 = wrap_negative(self.offset >> 1, 8) |
237 | 645 h = (0b1101 << 12) | (self.cond << 8) | imm8 |
646 return u16(h) | |
647 | |
262 | 648 |
237 | 649 @armtarget.instruction |
650 class beq_ins(cond_base_ins): | |
219 | 651 mnemonic = 'beq' |
237 | 652 cond = 0 |
653 | |
262 | 654 |
237 | 655 @armtarget.instruction |
262 | 656 class bne_ins(cond_base_ins): |
237 | 657 mnemonic = 'bne' |
658 cond = 1 | |
205 | 659 |
262 | 660 |
661 @armtarget.instruction | |
662 class blt_ins(cond_base_ins): | |
663 mnemonic = 'blt' | |
664 cond = 0b1011 | |
665 | |
666 | |
667 @armtarget.instruction | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
668 class bgt_ins(cond_base_ins): |
262 | 669 mnemonic = 'bgt' |
670 cond = 0b1100 | |
671 | |
672 | |
205 | 673 @armtarget.instruction |
674 class push_ins(ArmInstruction): | |
206 | 675 operands = (RegisterSet,) |
205 | 676 mnemonic = 'push' |
677 def __init__(self, regs): | |
206 | 678 assert (type(regs),) == self.operands, (type(regs),) |
205 | 679 self.regs = regs |
206 | 680 def __repr__(self): |
681 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
205 | 682 def encode(self): |
206 | 683 reg_list = 0 |
684 M = 0 | |
685 for n in self.regs.registerNumbers(): | |
686 if n < 8: | |
687 reg_list |= (1 << n) | |
688 elif n == 14: | |
689 M = 1 | |
690 else: | |
691 raise NotImplementedError('not implemented for this register') | |
692 h = (0x5a << 9) | (M << 8) | reg_list | |
693 return u16(h) | |
205 | 694 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
695 |
205 | 696 @armtarget.instruction |
697 class pop_ins(ArmInstruction): | |
206 | 698 operands = (RegisterSet,) |
205 | 699 mnemonic = 'pop' |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
700 |
205 | 701 def __init__(self, regs): |
702 self.regs = regs | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
703 |
207 | 704 def __repr__(self): |
705 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
706 |
205 | 707 def encode(self): |
206 | 708 reg_list = 0 |
709 P = 0 | |
710 for n in self.regs.registerNumbers(): | |
711 if n < 8: | |
712 reg_list |= (1 << n) | |
713 elif n == 15: | |
714 P = 1 | |
715 else: | |
716 raise NotImplementedError('not implemented for this register') | |
717 h = (0x5E << 9) | (P << 8) | reg_list | |
718 return u16(h) | |
205 | 719 |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
720 |
205 | 721 @armtarget.instruction |
202 | 722 class yield_ins(ArmInstruction): |
723 operands = () | |
724 mnemonic = 'yield' | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
725 |
202 | 726 def encode(self): |
727 return u16(0xbf10) | |
728 | |
275 | 729 # misc: |
730 | |
731 # add/sub SP: | |
277 | 732 class addspsp_base(ArmInstruction): |
275 | 733 operands = (RegSpOp, RegSpOp, Imm7) |
734 def __init__(self, _sp, _sp2, imm7): | |
735 self.imm7 = imm7.imm | |
736 assert self.imm7 % 4 == 0 | |
737 self.imm7 >>= 2 | |
738 | |
739 def encode(self): | |
277 | 740 return u16((self.opcode << 7) |self.imm7) |
741 | |
742 def __repr__(self): | |
743 return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2) | |
275 | 744 |
745 @armtarget.instruction | |
277 | 746 class addspsp_ins(addspsp_base): |
747 mnemonic = 'add' | |
748 opcode = 0b101100000 | |
749 | |
750 | |
751 @armtarget.instruction | |
752 class subspsp_ins(addspsp_base): | |
275 | 753 mnemonic = 'sub' |
277 | 754 opcode = 0b101100001 |
275 | 755 |
206 | 756 armtarget.check() |
757 |