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