Mercurial > lcfOS
comparison python/target/armtarget.py @ 292:534b94b40aa8
Fixup reorganize
author | Windel Bouwman |
---|---|
date | Wed, 27 Nov 2013 08:06:42 +0100 |
parents | 7b38782ed496 |
children | 44f336460c2a |
comparison
equal
deleted
inserted
replaced
290:7b38782ed496 | 292:534b94b40aa8 |
---|---|
1 import struct | 1 import struct |
2 import types | |
3 import ir | |
4 from asmnodes import ASymbol, ANumber, AUnop, ABinop | |
5 from ppci import CompilerError | |
6 from .basetarget import Register, Instruction, Target, Label, LabelRef | 2 from .basetarget import Register, Instruction, Target, Label, LabelRef |
7 from .basetarget import Imm32, Imm8, Imm7, Imm3 | 3 from .basetarget import Imm32, Imm8, Imm7, Imm3 |
8 from .armframe import ArmFrame, ArmInstructionSelector | 4 from .arminstructions import allins, Reg8Op, ArmRegister |
5 from .arminstructions import Dcd, B | |
6 from .arminstructions import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP | |
9 | 7 |
10 | 8 |
11 """ ARM target description. """ | 9 """ ARM target description. """ |
12 | 10 |
13 # TODO: encode this in DSL (domain specific language) | 11 # TODO: encode this in DSL (domain specific language) |
14 # TBD: is this required? | 12 # TBD: is this required? |
15 | 13 # TODO: make a difference between armv7 and armv5? |
16 def u16(h): | |
17 return struct.pack('<H', h) | |
18 | |
19 def u32(x): | |
20 return struct.pack('<I', x) | |
21 | |
22 armtarget = Target('arm') | |
23 armtarget.InstructionSelector = ArmInstructionSelector | |
24 armtarget.Frame = ArmFrame | |
25 | |
26 class ArmRegister(Register): | |
27 def __init__(self, num, name): | |
28 super().__init__(name) | |
29 self.num = num | |
30 | |
31 def __repr__(self): | |
32 return self.name | |
33 | |
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] | |
43 if isinstance(r, cls): | |
44 return r | |
45 | 14 |
46 | 15 |
47 class Reg8Op(ArmRegister): | 16 class ArmTarget(Target): |
48 pass | 17 def __init__(self): |
18 super().__init__('arm') | |
19 for i in allins: | |
20 self.addInstruction(i) | |
21 # TODO: fix this nicer? | |
22 #setattr(self, i.__name__, i) | |
23 self.check() | |
49 | 24 |
50 | 25 def startCode(self, outs): |
51 class Reg16Op(ArmRegister): | 26 """ Emit some startup code in the output stream """ |
52 pass | 27 outs.selectSection('code') |
53 | 28 # assembly glue to make it work: |
54 | 29 # TODO: this must be in source code, not in compiler |
55 class RegSpOp: | 30 outs.emit(Dcd(Imm32(0x20000678))) # initial SP |
56 @classmethod | 31 outs.emit(Dcd(Imm32(0x08000009))) # reset vector |
57 def Create(cls, vop): | 32 outs.emit(B(LabelRef('main'))) |
58 if type(vop) is ASymbol: | |
59 if vop.name.lower() == 'sp': | |
60 return cls() | |
61 | |
62 def getRegNum(n): | |
63 for r in armtarget.registers: | |
64 if r.num == n: | |
65 return r | |
66 | |
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 | |
75 | |
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 | |
86 self.offset = offset | |
87 | |
88 def __repr__(self): | |
89 return '[{}, #{}]'.format(self.regname, self.offset) | |
90 | |
91 @classmethod | |
92 def Create(cls, vop): | |
93 if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+': | |
94 vop = vop.arg # descent | |
95 offset = isRegOffset(cls.regname, vop.arg1, vop.arg2) | |
96 if type(offset) is int: | |
97 if offset % 4 == 0: | |
98 offset = vop.arg2.number | |
99 return cls(offset) | |
100 elif type(vop) is ASymbol and vop.name.upper() == self.regname: | |
101 return cls(0) | |
102 | |
103 | |
104 class MemSpRel(MemRegXRel): | |
105 regname = 'SP' | |
106 | |
107 | |
108 class MemR8Rel: | |
109 def __init__(self, basereg, offset): | |
110 assert type(basereg) is Reg8Op | |
111 assert type(offset) is int | |
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) | |
140 | |
141 class RegisterSet: | |
142 def __init__(self, regs): | |
143 assert type(regs) is set | |
144 self.regs = regs | |
145 | |
146 def __repr__(self): | |
147 return ','.join([str(r) for r in self.regs]) | |
148 | |
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: | |
156 reg = ArmRegister.Create(arg) | |
157 if not reg: | |
158 return | |
159 regs.add(reg) | |
160 elif type(arg) is ABinop and arg.op == '-': | |
161 reg1 = ArmRegister.Create(arg.arg1) | |
162 reg2 = ArmRegister.Create(arg.arg2) | |
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] | |
175 | |
176 def makeReg(cls, num, name): | |
177 r = cls(num, name) | |
178 armtarget.registers.append(r) | |
179 return r | |
180 | |
181 # 8 bit registers: | |
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') | |
190 # Other registers: | |
191 # TODO | |
192 sp = makeReg(ArmRegister, 13, 'sp') | |
193 lr = makeReg(ArmRegister, 14, 'lr') | |
194 pc = makeReg(ArmRegister, 15, 'pc') | |
195 | |
196 # Sanity checks: | |
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 | |
201 | |
202 | |
203 class ArmInstruction(Instruction): | |
204 pass | |
205 | |
206 | |
207 @armtarget.instruction | |
208 class dcd_ins(ArmInstruction): | |
209 mnemonic = 'dcd' | |
210 operands = (Imm32,) | |
211 def __init__(self, expr): | |
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 | |
218 elif isinstance(expr, int): | |
219 self.expr = expr | |
220 self.label = None | |
221 else: | |
222 raise NotImplementedError() | |
223 | |
224 def resolve(self, f): | |
225 if self.label: | |
226 self.expr = f(self.label.name) | |
227 | |
228 def encode(self): | |
229 return u32(self.expr) | |
230 | |
231 def __repr__(self): | |
232 return 'DCD 0x{0:X}'.format(self.expr) | |
233 | |
234 | |
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' | |
245 | |
246 | |
247 # Memory related | |
248 | |
249 class LS_imm5_base(ArmInstruction): | |
250 """ ??? Rt, [Rn, imm5] """ | |
251 operands = (Reg8Op, MemR8Rel) | |
252 def __init__(self, rt, memop): | |
253 assert memop.offset % 4 == 0 | |
254 self.imm5 = memop.offset >> 2 | |
255 self.rn = memop.basereg.num | |
256 self.rt = rt | |
257 self.memloc = memop | |
258 assert self.rn < 8 | |
259 assert self.rt.num < 8 | |
260 | |
261 def encode(self): | |
262 Rn = self.rn | |
263 Rt = self.rt.num | |
264 imm5 = self.imm5 | |
265 | |
266 h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt | |
267 return u16(h) | |
268 | |
269 | |
270 def __repr__(self): | |
271 return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) | |
272 | |
273 | |
274 @armtarget.instruction | |
275 class storeimm5_ins(LS_imm5_base): | |
276 mnemonic = 'STR' | |
277 opcode = 0xC | |
278 | |
279 @classmethod | |
280 def fromim(cls, im): | |
281 mem = MemR8Rel(im.src[0], im.others[0]) | |
282 return cls(im.src[1], mem) | |
283 | |
284 | |
285 @armtarget.instruction | |
286 class loadimm5_ins(LS_imm5_base): | |
287 mnemonic = 'LDR' | |
288 opcode = 0xD | |
289 | |
290 @classmethod | |
291 def fromim(cls, im): | |
292 mem = MemR8Rel(im.src[0], im.others[0]) | |
293 return cls(im.dst[0], mem) | |
294 | |
295 class ls_sp_base_imm8(ArmInstruction): | |
296 operands = (Reg8Op, MemSpRel) | |
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 | |
307 return u16(h) | |
308 | |
309 def __repr__(self): | |
310 return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) | |
311 | |
312 def align(x, m): | |
313 while ((x % m) != 0): | |
314 x = x + 1 | |
315 return x | |
316 | |
317 | |
318 @armtarget.instruction | |
319 class ldr_pcrel(ArmInstruction): | |
320 """ ldr Rt, LABEL, load value from pc relative position """ | |
321 mnemonic = 'ldr' | |
322 operands = (Reg8Op, LabelRef) | |
323 def __init__(self, rt, label): | |
324 assert isinstance(label, LabelRef) | |
325 self.rt = rt | |
326 self.label = label | |
327 self.offset = 0 | |
328 | |
329 @classmethod | |
330 def fromim(cls, im): | |
331 return cls(im.dst[0], im.others[0]) | |
332 | |
333 def resolve(self, f): | |
334 la = f(self.label.name) | |
335 sa = align(self.address + 2, 4) | |
336 self.offset = (la - sa) | |
337 if self.offset < 0: | |
338 self.offset = 0 | |
339 | |
340 def encode(self): | |
341 rt = self.rt.num | |
342 assert rt < 8 | |
343 assert self.offset % 4 == 0 | |
344 imm8 = self.offset >> 2 | |
345 assert imm8 < 256 | |
346 assert imm8 >= 0 | |
347 h = (0x9 << 11) | (rt << 8) | imm8 | |
348 return u16(h) | |
349 | |
350 def __repr__(self): | |
351 return 'LDR {}, {}'.format(self.rt, self.label.name) | |
352 | |
353 | |
354 @armtarget.instruction | |
355 class ldr_sprel(ls_sp_base_imm8): | |
356 """ ldr Rt, [SP, imm8] """ | |
357 mnemonic = 'LDR' | |
358 opcode = 0x98 | |
359 | |
360 | |
361 @armtarget.instruction | |
362 class str_sprel(ls_sp_base_imm8): | |
363 """ str Rt, [SP, imm8] """ | |
364 mnemonic = 'STR' | |
365 opcode = 0x90 | |
366 | |
367 | |
368 @armtarget.instruction | |
369 class mov_imm8_ins(ArmInstruction): | |
370 """ mov Rd, imm8, move immediate value into register """ | |
371 mnemonic = 'mov' | |
372 opcode = 4 # 00100 Rd(3) imm8 | |
373 operands = (Reg8Op, Imm8) | |
374 def __init__(self, rd, imm): | |
375 if type(imm) is int: | |
376 imm = Imm8(imm) | |
377 assert type(imm) is Imm8 | |
378 self.imm = imm.imm | |
379 assert type(rd) is Reg8Op, str(type(rd)) | |
380 self.rd = rd | |
381 | |
382 @classmethod | |
383 def fromim(cls, im): | |
384 return cls(im.dst[0], im.others[0]) | |
385 | |
386 def encode(self): | |
387 rd = self.rd.num | |
388 opcode = self.opcode | |
389 imm8 = self.imm | |
390 h = (opcode << 11) | (rd << 8) | imm8 | |
391 return u16(h) | |
392 | |
393 def __repr__(self): | |
394 return 'MOV {}, {}'.format(self.rd, self.imm) | |
395 | |
396 | |
397 | |
398 # Arithmatics: | |
399 | |
400 | |
401 | |
402 class regregimm3_base(ArmInstruction): | |
403 operands = (Reg8Op, Reg8Op, Imm3) | |
404 def __init__(self, rd, rn, imm3): | |
405 self.rd = rd | |
406 self.rn = rn | |
407 assert type(imm3) is Imm3 | |
408 self.imm3 = imm3 | |
409 | |
410 @classmethod | |
411 def fromim(cls, im): | |
412 return cls(im.dst[0], im.src[0], im.others[0]) | |
413 | |
414 def encode(self): | |
415 rd = self.rd.num | |
416 rn = self.rn.num | |
417 imm3 = self.imm3.imm | |
418 opcode = self.opcode | |
419 h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd | |
420 return u16(h) | |
421 | |
422 def __repr__(self): | |
423 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm) | |
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 | |
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 | |
446 | |
447 @classmethod | |
448 def fromim(cls, im): | |
449 return cls(im.dst[0], im.src[0], im.src[1]) | |
450 | |
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) | |
457 | |
458 def __repr__(self): | |
459 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) | |
460 | |
461 | |
462 @armtarget.instruction | |
463 class addregs_ins(regregreg_base): | |
464 mnemonic = 'ADD' | |
465 opcode = 0b0001100 | |
466 | |
467 | |
468 @armtarget.instruction | |
469 class subregs_ins(regregreg_base): | |
470 mnemonic = 'SUB' | |
471 opcode = 0b0001101 | |
472 | |
473 | |
474 | |
475 @armtarget.instruction | |
476 class movregreg_ext_ins(ArmInstruction): | |
477 """ mov rd, rm """ | |
478 operands = (ArmRegister, ArmRegister) | |
479 mnemonic = 'MOV' | |
480 def __init__(self, rd, rm): | |
481 self.rd = rd | |
482 self.rm = rm | |
483 | |
484 @classmethod | |
485 def fromim(cls, im): | |
486 return cls(im.dst[0], im.src[0]) | |
487 | |
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) | |
494 | |
495 def __repr__(self): | |
496 return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) | |
497 | |
498 | |
499 @armtarget.instruction | |
500 class mulregreg_ins(ArmInstruction): | |
501 """ mul Rn, Rdm """ | |
502 operands = (Reg8Op, Reg8Op) | |
503 mnemonic = 'MUL' | |
504 def __init__(self, rn, rdm): | |
505 self.rn = rn | |
506 self.rdm = rdm | |
507 | |
508 @classmethod | |
509 def fromim(cls, im): | |
510 assert im.src[1] is im.dst[0] | |
511 return cls(im.src[0], im.dst[0]) | |
512 | |
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) | |
519 | |
520 def __repr__(self): | |
521 return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) | |
522 | |
523 | |
524 class regreg_base(ArmInstruction): | |
525 """ ??? Rdn, Rm """ | |
526 operands = (Reg8Op, Reg8Op) | |
527 # TODO: integrate with the code gen interface: | |
528 src = (0, 1) | |
529 dst = (0,) | |
530 def __init__(self, rdn, rm): | |
531 self.rdn = rdn | |
532 self.rm = rm | |
533 | |
534 @classmethod | |
535 def fromim(cls, im): | |
536 return cls(im.src[0], im.src[1]) | |
537 | |
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) | |
543 | |
544 def __repr__(self): | |
545 return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) | |
546 | |
547 | |
548 @armtarget.instruction | |
549 class movregreg_ins(regreg_base): | |
550 """ mov Rd, Rm (reg8 operands) """ | |
551 # TODO: match this: | |
552 pattern = ir.Move(ir.Temp, ir.Temp) | |
553 mnemonic = 'mov' | |
554 opcode = 0 | |
555 | |
556 | |
557 @armtarget.instruction | |
558 class andregs_ins(regreg_base): | |
559 mnemonic = 'AND' | |
560 opcode = 0b0100000000 | |
561 | |
562 | |
563 @armtarget.instruction | |
564 class orrregs_ins(regreg_base): | |
565 mnemonic = 'ORR' | |
566 opcode = 0b0100001100 | |
567 | |
568 | |
569 @armtarget.instruction | |
570 class cmp_ins(regreg_base): | |
571 mnemonic = 'CMP' | |
572 opcode = 0b0100001010 | |
573 | |
574 | |
575 @armtarget.instruction | |
576 class lslregs_ins(regreg_base): | |
577 mnemonic = 'LSL' | |
578 opcode = 0b0100000010 | |
579 | |
580 @armtarget.instruction | |
581 class cmpregimm8_ins(ArmInstruction): | |
582 """ cmp Rn, imm8 """ | |
583 mnemonic = 'cmp' | |
584 opcode = 5 # 00101 | |
585 operands = (Reg8Op, Imm8) | |
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) | |
595 | |
596 | |
597 # Jumping: | |
598 | |
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 | |
604 class jumpBase_ins(ArmInstruction): | |
605 operands = (LabelRef,) | |
606 def __init__(self, target_label): | |
607 assert type(target_label) is LabelRef | |
608 self.target = target_label | |
609 self.offset = 0 | |
610 | |
611 def resolve(self, f): | |
612 la = f(self.target.name) | |
613 sa = self.address + 4 | |
614 self.offset = (la - sa) | |
615 | |
616 def __repr__(self): | |
617 return '{} {}'.format(self.mnemonic, self.target.name) | |
618 | |
619 | |
620 @armtarget.instruction | |
621 class b_ins(jumpBase_ins): | |
622 mnemonic = 'B' | |
623 def encode(self): | |
624 imm11 = wrap_negative(self.offset >> 1, 11) | |
625 h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode | |
626 return u16(h) | |
627 | |
628 | |
629 @armtarget.instruction | |
630 class bl_ins(jumpBase_ins): | |
631 mnemonic = 'BL' | |
632 def encode(self): | |
633 imm32 = wrap_negative(self.offset >> 1, 32) | |
634 imm11 = imm32 & 0x7FF | |
635 imm10 = (imm32 >> 11) & 0x3FF | |
636 j1 = 1 # TODO: what do these mean? | |
637 j2 = 1 | |
638 s = (imm32 >> 24) & 0x1 | |
639 h1 = (0b11110 << 11) | (s << 10) | imm10 | |
640 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 | |
641 return u16(h1) + u16(h2) | |
642 | |
643 | |
644 class cond_base_ins(jumpBase_ins): | |
645 def encode(self): | |
646 imm8 = wrap_negative(self.offset >> 1, 8) | |
647 h = (0b1101 << 12) | (self.cond << 8) | imm8 | |
648 return u16(h) | |
649 | |
650 | |
651 @armtarget.instruction | |
652 class beq_ins(cond_base_ins): | |
653 mnemonic = 'beq' | |
654 cond = 0 | |
655 | |
656 | |
657 @armtarget.instruction | |
658 class bne_ins(cond_base_ins): | |
659 mnemonic = 'bne' | |
660 cond = 1 | |
661 | |
662 | |
663 @armtarget.instruction | |
664 class blt_ins(cond_base_ins): | |
665 mnemonic = 'blt' | |
666 cond = 0b1011 | |
667 | |
668 | |
669 @armtarget.instruction | |
670 class bgt_ins(cond_base_ins): | |
671 mnemonic = 'bgt' | |
672 cond = 0b1100 | |
673 | |
674 | |
675 @armtarget.instruction | |
676 class push_ins(ArmInstruction): | |
677 operands = (RegisterSet,) | |
678 mnemonic = 'push' | |
679 def __init__(self, regs): | |
680 assert (type(regs),) == self.operands, (type(regs),) | |
681 self.regs = regs | |
682 def __repr__(self): | |
683 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
684 def encode(self): | |
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) | |
696 | |
697 | |
698 @armtarget.instruction | |
699 class pop_ins(ArmInstruction): | |
700 operands = (RegisterSet,) | |
701 mnemonic = 'pop' | |
702 | |
703 def __init__(self, regs): | |
704 self.regs = regs | |
705 | |
706 def __repr__(self): | |
707 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
708 | |
709 def encode(self): | |
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) | |
721 | |
722 | |
723 @armtarget.instruction | |
724 class yield_ins(ArmInstruction): | |
725 operands = () | |
726 mnemonic = 'yield' | |
727 | |
728 def encode(self): | |
729 return u16(0xbf10) | |
730 | |
731 # misc: | |
732 | |
733 # add/sub SP: | |
734 class addspsp_base(ArmInstruction): | |
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): | |
742 return u16((self.opcode << 7) |self.imm7) | |
743 | |
744 def __repr__(self): | |
745 return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2) | |
746 | |
747 @armtarget.instruction | |
748 class addspsp_ins(addspsp_base): | |
749 mnemonic = 'add' | |
750 opcode = 0b101100000 | |
751 | |
752 | |
753 @armtarget.instruction | |
754 class subspsp_ins(addspsp_base): | |
755 mnemonic = 'sub' | |
756 opcode = 0b101100001 | |
757 | |
758 armtarget.check() | |
759 |