Mercurial > lcfOS
comparison python/ppci/target/thumb/instructions.py @ 342:86b02c98a717 devel
Moved target directory
author | Windel Bouwman |
---|---|
date | Sat, 01 Mar 2014 15:40:31 +0100 |
parents | python/target/arminstructions.py@4d204f6f7d4e |
children | 3bb7dcfe5529 |
comparison
equal
deleted
inserted
replaced
341:4d204f6f7d4e | 342:86b02c98a717 |
---|---|
1 from ..basetarget import Register, Instruction, Target, Label | |
2 from ..basetarget import Imm32, Imm8, Imm7, Imm3 | |
3 from ..token import u16, u32 | |
4 from .armtoken import ThumbToken | |
5 from ..arm.registers import R0, ArmRegister, SP | |
6 | |
7 | |
8 # Instructions: | |
9 | |
10 class ThumbInstruction(Instruction): | |
11 pass | |
12 | |
13 | |
14 class Dcd(ThumbInstruction): | |
15 def __init__(self, expr): | |
16 if isinstance(expr, Imm32): | |
17 self.expr = expr.imm | |
18 self.label = None | |
19 elif isinstance(expr, int): | |
20 self.expr = expr | |
21 self.label = None | |
22 else: | |
23 raise NotImplementedError() | |
24 | |
25 def encode(self): | |
26 return u32(self.expr) | |
27 | |
28 def relocations(self): | |
29 return [] | |
30 | |
31 def __repr__(self): | |
32 return 'DCD 0x{0:X}'.format(self.expr) | |
33 | |
34 | |
35 class nop_ins(ThumbInstruction): | |
36 def encode(self): | |
37 return bytes() | |
38 | |
39 def __repr__(self): | |
40 return 'NOP' | |
41 | |
42 | |
43 # Memory related | |
44 | |
45 class LS_imm5_base(ThumbInstruction): | |
46 """ ??? Rt, [Rn, imm5] """ | |
47 def __init__(self, rt, rn, imm5): | |
48 assert imm5 % 4 == 0 | |
49 self.imm5 = imm5 >> 2 | |
50 self.rn = rn | |
51 self.rt = rt | |
52 assert self.rn.num < 8 | |
53 assert self.rt.num < 8 | |
54 self.token = ThumbToken() | |
55 | |
56 def encode(self): | |
57 Rn = self.rn.num | |
58 Rt = self.rt.num | |
59 imm5 = self.imm5 | |
60 self.token[0:3] = Rt | |
61 self.token[3:6] = Rn | |
62 self.token[6:11] = imm5 | |
63 self.token[11:16] = self.opcode | |
64 return self.token.encode() | |
65 | |
66 def __repr__(self): | |
67 mnemonic = "???" | |
68 return '{} {}, [{}, {}]'.format(mnemonic, self.rt, self.rn, self.imm5) | |
69 | |
70 | |
71 class Str2(LS_imm5_base): | |
72 opcode = 0xC | |
73 | |
74 @classmethod | |
75 def fromim(cls, im): | |
76 return cls(im.src[1], im.src[0], im.others[0]) | |
77 | |
78 | |
79 class Ldr2(LS_imm5_base): | |
80 opcode = 0xD | |
81 | |
82 @classmethod | |
83 def fromim(cls, im): | |
84 return cls(im.dst[0], im.src[0], im.others[0]) | |
85 | |
86 class ls_sp_base_imm8(ThumbInstruction): | |
87 def __init__(self, rt, offset): | |
88 self.rt = rt | |
89 self.offset = offset | |
90 | |
91 def encode(self): | |
92 rt = self.rt.num | |
93 assert rt < 8 | |
94 imm8 = self.offset >> 2 | |
95 assert imm8 < 256 | |
96 h = (self.opcode << 8) | (rt << 8) | imm8 | |
97 return u16(h) | |
98 | |
99 def __repr__(self): | |
100 mnemonic = self.__class__.__name__ | |
101 return '{} {}, [sp,#{}]'.format(mnemonic, self.rt, self.offset) | |
102 | |
103 def align(x, m): | |
104 while ((x % m) != 0): | |
105 x = x + 1 | |
106 return x | |
107 | |
108 def Ldr(*args): | |
109 if len(args) == 2 and isinstance(args[0], ArmRegister) \ | |
110 and isinstance(args[1], str): | |
111 return Ldr3(*args) | |
112 else: | |
113 raise Exception() | |
114 | |
115 | |
116 class Ldr3(ThumbInstruction): | |
117 """ ldr Rt, LABEL, load value from pc relative position """ | |
118 mnemonic = 'ldr' | |
119 def __init__(self, rt, label): | |
120 self.rt = rt | |
121 self.label = label | |
122 | |
123 @classmethod | |
124 def fromim(cls, im): | |
125 return cls(im.dst[0], im.others[0]) | |
126 | |
127 def relocations(self): | |
128 return [(self.label, 'lit_add_8')] | |
129 | |
130 def encode(self): | |
131 rt = self.rt.num | |
132 assert rt < 8 | |
133 imm8 = 0 | |
134 h = (0x9 << 11) | (rt << 8) | imm8 | |
135 return u16(h) | |
136 | |
137 def __repr__(self): | |
138 return 'LDR {}, {}'.format(self.rt, self.label) | |
139 | |
140 | |
141 class Ldr1(ls_sp_base_imm8): | |
142 """ ldr Rt, [SP, imm8] """ | |
143 opcode = 0x98 | |
144 | |
145 | |
146 class Str1(ls_sp_base_imm8): | |
147 """ str Rt, [SP, imm8] """ | |
148 opcode = 0x90 | |
149 | |
150 | |
151 class Mov3(ThumbInstruction): | |
152 """ mov Rd, imm8, move immediate value into register """ | |
153 opcode = 4 # 00100 Rd(3) imm8 | |
154 def __init__(self, rd, imm): | |
155 assert imm < 256 | |
156 self.imm = imm | |
157 self.rd = rd | |
158 self.token = ThumbToken() | |
159 | |
160 @classmethod | |
161 def fromim(cls, im): | |
162 return cls(im.dst[0], im.others[0]) | |
163 | |
164 def encode(self): | |
165 rd = self.rd.num | |
166 self.token[8:11] = rd | |
167 self.token[0:8] = self.imm | |
168 self.token[11:16] = self.opcode | |
169 return self.token.encode() | |
170 | |
171 def __repr__(self): | |
172 return 'MOV {}, {}'.format(self.rd, self.imm) | |
173 | |
174 | |
175 | |
176 # Arithmatics: | |
177 | |
178 | |
179 | |
180 class regregimm3_base(ThumbInstruction): | |
181 def __init__(self, rd, rn, imm3): | |
182 self.rd = rd | |
183 self.rn = rn | |
184 assert imm3 < 8 | |
185 self.imm3 = imm3 | |
186 self.token = ThumbToken() | |
187 | |
188 @classmethod | |
189 def fromim(cls, im): | |
190 return cls(im.dst[0], im.src[0], im.others[0]) | |
191 | |
192 def encode(self): | |
193 rd = self.rd.num | |
194 self.token[0:3] = rd | |
195 self.token[3:6] = self.rn.num | |
196 self.token[6:9] = self.imm3 | |
197 self.token[9:16] = self.opcode | |
198 return self.token.encode() | |
199 | |
200 def __repr__(self): | |
201 mnemonic = self.__class__.__name__ | |
202 return '{} {}, {}, {}'.format(mnemonic, self.rd, self.rn, self.imm3) | |
203 | |
204 | |
205 | |
206 class Add2(regregimm3_base): | |
207 """ add Rd, Rn, imm3 """ | |
208 opcode = 0b0001110 | |
209 | |
210 | |
211 class Sub2(regregimm3_base): | |
212 """ sub Rd, Rn, imm3 """ | |
213 opcode = 0b0001111 | |
214 | |
215 | |
216 def Sub(*args): | |
217 if len(args) == 3 and args[0] is SP and args[1] is SP and \ | |
218 isinstance(args[2], int) and args[2] < 256: | |
219 return SubSp(args[2]) | |
220 elif len(args) == 3 and isinstance(args[0], ArmRegister) and \ | |
221 isinstance(args[1], ArmRegister) and isinstance(args[2], int) and \ | |
222 args[2] < 8: | |
223 return Sub2(args[0], args[1], args[2]) | |
224 else: | |
225 raise Exception() | |
226 | |
227 | |
228 def Add(*args): | |
229 if len(args) == 3 and args[0] is SP and args[1] is SP and \ | |
230 isinstance(args[2], int) and args[2] < 256: | |
231 return AddSp(args[2]) | |
232 elif len(args) == 3 and isinstance(args[0], ArmRegister) and \ | |
233 isinstance(args[1], ArmRegister) and isinstance(args[2], int) and \ | |
234 args[2] < 8: | |
235 return Add2(args[0], args[1], args[2]) | |
236 else: | |
237 raise Exception() | |
238 | |
239 | |
240 class regregreg_base(ThumbInstruction): | |
241 """ ??? Rd, Rn, Rm """ | |
242 def __init__(self, rd, rn, rm): | |
243 self.rd = rd | |
244 self.rn = rn | |
245 self.rm = rm | |
246 | |
247 @classmethod | |
248 def fromim(cls, im): | |
249 return cls(im.dst[0], im.src[0], im.src[1]) | |
250 | |
251 def encode(self): | |
252 at = ThumbToken() | |
253 at.rd = self.rd.num | |
254 rn = self.rn.num | |
255 rm = self.rm.num | |
256 at[3:6] = rn | |
257 at[6:9] = rm | |
258 at[9:16] = self.opcode | |
259 return at.encode() | |
260 | |
261 def __repr__(self): | |
262 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) | |
263 | |
264 | |
265 class Add3(regregreg_base): | |
266 mnemonic = 'ADD' | |
267 opcode = 0b0001100 | |
268 | |
269 | |
270 class Sub3(regregreg_base): | |
271 mnemonic = 'SUB' | |
272 opcode = 0b0001101 | |
273 | |
274 | |
275 class Mov2(ThumbInstruction): | |
276 """ mov rd, rm """ | |
277 mnemonic = 'MOV' | |
278 def __init__(self, rd, rm): | |
279 self.rd = rd | |
280 self.rm = rm | |
281 | |
282 @classmethod | |
283 def fromim(cls, im): | |
284 return cls(im.dst[0], im.src[0]) | |
285 | |
286 def encode(self): | |
287 at = ThumbToken() | |
288 at.rd = self.rd.num & 0x7 | |
289 D = (self.rd.num >> 3) & 0x1 | |
290 Rm = self.rm.num | |
291 opcode = 0b01000110 | |
292 at[8:16] = opcode | |
293 at[3:7] = Rm | |
294 at[7] = D | |
295 return at.encode() | |
296 | |
297 def __repr__(self): | |
298 return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) | |
299 | |
300 | |
301 class Mul(ThumbInstruction): | |
302 """ mul Rn, Rdm """ | |
303 mnemonic = 'MUL' | |
304 def __init__(self, rn, rdm): | |
305 self.rn = rn | |
306 self.rdm = rdm | |
307 | |
308 @classmethod | |
309 def fromim(cls, im): | |
310 assert im.src[1] is im.dst[0] | |
311 return cls(im.src[0], im.dst[0]) | |
312 | |
313 def encode(self): | |
314 at = ThumbToken() | |
315 rn = self.rn.num | |
316 at.rd = self.rdm.num | |
317 opcode = 0b0100001101 | |
318 #h = (opcode << 6) | (rn << 3) | rdm | |
319 at[6:16] = opcode | |
320 at[3:6] = rn | |
321 return at.encode() | |
322 | |
323 def __repr__(self): | |
324 return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) | |
325 | |
326 | |
327 class regreg_base(ThumbInstruction): | |
328 """ ??? Rdn, Rm """ | |
329 def __init__(self, rdn, rm): | |
330 self.rdn = rdn | |
331 self.rm = rm | |
332 | |
333 @classmethod | |
334 def fromim(cls, im): | |
335 return cls(im.src[0], im.src[1]) | |
336 | |
337 def encode(self): | |
338 at = ThumbToken() | |
339 at.rd = self.rdn.num | |
340 rm = self.rm.num | |
341 at[3:6] = rm | |
342 at[6:16] = self.opcode | |
343 return at.encode() | |
344 | |
345 def __repr__(self): | |
346 mnemonic = self.__class__.__name__ | |
347 return '{} {}, {}'.format(mnemonic, self.rdn, self.rm) | |
348 | |
349 | |
350 class movregreg_ins(regreg_base): | |
351 """ mov Rd, Rm (reg8 operands) """ | |
352 opcode = 0 | |
353 | |
354 | |
355 class And(regreg_base): | |
356 opcode = 0b0100000000 | |
357 | |
358 | |
359 class Orr(regreg_base): | |
360 opcode = 0b0100001100 | |
361 | |
362 | |
363 class Cmp(regreg_base): | |
364 opcode = 0b0100001010 | |
365 | |
366 | |
367 class Lsl(regreg_base): | |
368 opcode = 0b0100000010 | |
369 | |
370 | |
371 class Cmp2(ThumbInstruction): | |
372 """ cmp Rn, imm8 """ | |
373 opcode = 5 # 00101 | |
374 def __init__(self, rn, imm): | |
375 self.rn = rn | |
376 self.imm = imm | |
377 | |
378 def encode(self): | |
379 at = ThumbToken() | |
380 at[0:8] = self.imm | |
381 at[8:11] = self.rn.num | |
382 at[11:16] = self.opcode | |
383 return at.encode() | |
384 | |
385 | |
386 # Jumping: | |
387 | |
388 class jumpBase_ins(ThumbInstruction): | |
389 def __init__(self, target_label): | |
390 assert type(target_label) is str | |
391 self.target = target_label | |
392 self.offset = 0 | |
393 | |
394 def __repr__(self): | |
395 mnemonic = self.__class__.__name__ | |
396 return '{} {}'.format(mnemonic, self.target) | |
397 | |
398 | |
399 class B(jumpBase_ins): | |
400 def encode(self): | |
401 h = (0b11100 << 11) | 0 | |
402 # | 1 # 1 to enable thumb mode | |
403 return u16(h) | |
404 | |
405 def relocations(self): | |
406 return [(self.target, 'wrap_new11')] | |
407 | |
408 class Bl(jumpBase_ins): | |
409 def encode(self): | |
410 imm11 = 0 | |
411 imm10 = 0 | |
412 j1 = 1 # TODO: what do these mean? | |
413 j2 = 1 | |
414 s = 0 | |
415 h1 = (0b11110 << 11) | (s << 10) | imm10 | |
416 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 | |
417 return u16(h1) + u16(h2) | |
418 | |
419 def relocations(self): | |
420 return [(self.target, 'bl_imm11_imm10')] | |
421 | |
422 | |
423 class cond_base_ins(jumpBase_ins): | |
424 def encode(self): | |
425 imm8 = 0 | |
426 h = (0b1101 << 12) | (self.cond << 8) | imm8 | |
427 return u16(h) | |
428 | |
429 def relocations(self): | |
430 return [(self.target, 'rel8')] | |
431 | |
432 | |
433 class cond_base_ins_long(jumpBase_ins): | |
434 """ Encoding T3 """ | |
435 def encode(self): | |
436 j1 = 1 # TODO: what do these mean? | |
437 j2 = 1 | |
438 h1 = (0b11110 << 11) | (self.cond << 6) | |
439 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | |
440 return u16(h1) + u16(h2) | |
441 | |
442 def relocations(self): | |
443 return [(self.target, 'b_imm11_imm6')] | |
444 | |
445 | |
446 class Beq(cond_base_ins): | |
447 cond = 0 | |
448 | |
449 | |
450 class Bne(cond_base_ins): | |
451 cond = 1 | |
452 | |
453 | |
454 class Blt(cond_base_ins): | |
455 cond = 0b1011 | |
456 | |
457 | |
458 class Bgt(cond_base_ins): | |
459 cond = 0b1100 | |
460 | |
461 | |
462 class Push(ThumbInstruction): | |
463 def __init__(self, regs): | |
464 assert type(regs) is set | |
465 self.regs = regs | |
466 | |
467 def __repr__(self): | |
468 return 'Push {{{}}}'.format(self.regs) | |
469 | |
470 def encode(self): | |
471 at = ThumbToken() | |
472 for n in register_numbers(self.regs): | |
473 if n < 8: | |
474 at[n] = 1 | |
475 elif n == 14: | |
476 at[8] = 1 | |
477 else: | |
478 raise NotImplementedError('not implemented for {}'.format(n)) | |
479 at[9:16] = 0x5a | |
480 return at.encode() | |
481 | |
482 | |
483 | |
484 def register_numbers(regs): | |
485 for r in regs: | |
486 yield r.num | |
487 | |
488 class Pop(ThumbInstruction): | |
489 def __init__(self, regs): | |
490 assert type(regs) is set | |
491 self.regs = regs | |
492 self.token = ThumbToken() | |
493 | |
494 def __repr__(self): | |
495 return 'Pop {{{}}}'.format(self.regs) | |
496 | |
497 def encode(self): | |
498 for n in register_numbers(self.regs): | |
499 if n < 8: | |
500 self.token[n] = 1 | |
501 elif n == 15: | |
502 self.token[8] = 1 | |
503 else: | |
504 raise NotImplementedError('not implemented for this register') | |
505 self.token[9:16] = 0x5E | |
506 return self.token.encode() | |
507 | |
508 | |
509 | |
510 class Yield(ThumbInstruction): | |
511 def encode(self): | |
512 return u16(0xbf10) | |
513 | |
514 # misc: | |
515 | |
516 # add/sub SP: | |
517 class addspsp_base(ThumbInstruction): | |
518 def __init__(self, imm7): | |
519 self.imm7 = imm7 | |
520 assert self.imm7 % 4 == 0 | |
521 self.imm7 >>= 2 | |
522 | |
523 def encode(self): | |
524 return u16((self.opcode << 7) | self.imm7) | |
525 | |
526 def __repr__(self): | |
527 mnemonic = self.__class__.__name__ | |
528 return '{} sp, sp, {}'.format(mnemonic, self.imm7 << 2) | |
529 | |
530 | |
531 class AddSp(addspsp_base): | |
532 opcode = 0b101100000 | |
533 | |
534 | |
535 class SubSp(addspsp_base): | |
536 opcode = 0b101100001 |