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