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