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