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