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