Mercurial > lcfOS
annotate python/cortexm3.py @ 277:046017431c6a
Started register allocator
author | Windel Bouwman |
---|---|
date | Thu, 26 Sep 2013 21:14:25 +0200 |
parents | 56d37ed4b4d2 |
children | 2ccd57b1d78c |
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 | |
221 | |
222 | |
223 # Memory related | |
224 | |
225 class LS_imm5_base(ArmInstruction): | |
226 """ ??? Rt, [Rn, imm5] """ | |
225 | 227 operands = (Reg8Op, MemR8Rel) |
212 | 228 def __init__(self, rt, memop): |
229 assert memop.offset % 4 == 0 | |
230 self.imm5 = memop.offset >> 2 | |
231 self.rn = memop.basereg.num | |
225 | 232 self.rt = rt |
219 | 233 self.memloc = memop |
234 assert self.rn < 8 | |
225 | 235 assert self.rt.num < 8 |
212 | 236 |
237 def encode(self): | |
238 Rn = self.rn | |
225 | 239 Rt = self.rt.num |
212 | 240 imm5 = self.imm5 |
219 | 241 |
242 h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt | |
243 return u16(h) | |
275 | 244 |
219 | 245 def __repr__(self): |
246 return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) | |
247 | |
248 @armtarget.instruction | |
249 class storeimm5_ins(LS_imm5_base): | |
250 mnemonic = 'STR' | |
251 opcode = 0xC | |
252 | |
253 @armtarget.instruction | |
254 class loadimm5_ins(LS_imm5_base): | |
255 mnemonic = 'LDR' | |
256 opcode = 0xD | |
257 | |
258 class ls_sp_base_imm8(ArmInstruction): | |
224 | 259 operands = (Reg8Op, MemSpRel) |
219 | 260 def __init__(self, rt, memop): |
261 self.rt = rt | |
262 self.offset = memop.offset | |
263 | |
264 def encode(self): | |
265 rt = self.rt.num | |
266 assert rt < 8 | |
267 imm8 = self.offset >> 2 | |
268 assert imm8 < 256 | |
269 h = (self.opcode << 8) | (rt << 8) | imm8 | |
212 | 270 return u16(h) |
271 | |
219 | 272 def __repr__(self): |
273 return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) | |
274 | |
236 | 275 def align(x, m): |
276 while ((x % m) != 0): | |
277 x = x + 1 | |
278 return x | |
279 | |
277 | 280 |
212 | 281 @armtarget.instruction |
219 | 282 class ldr_pcrel(ArmInstruction): |
276 | 283 """ ldr Rt, LABEL, load value from pc relative position """ |
212 | 284 mnemonic = 'ldr' |
277 | 285 operands = (Reg8Op, LabelRef) |
219 | 286 def __init__(self, rt, label): |
235 | 287 assert isinstance(label, LabelRef) |
219 | 288 self.rt = rt |
289 self.label = label | |
290 self.offset = 0 | |
212 | 291 |
234 | 292 def resolve(self, f): |
235 | 293 la = f(self.label.name) |
236 | 294 sa = align(self.address + 2, 4) |
295 self.offset = (la - sa) | |
235 | 296 if self.offset < 0: |
297 self.offset = 0 | |
234 | 298 |
212 | 299 def encode(self): |
219 | 300 rt = self.rt.num |
301 assert rt < 8 | |
302 imm8 = self.offset >> 2 | |
303 assert imm8 < 256 | |
235 | 304 assert imm8 >= 0 |
219 | 305 h = (0x9 << 11) | (rt << 8) | imm8 |
212 | 306 return u16(h) |
307 | |
219 | 308 def __repr__(self): |
232 | 309 return 'LDR {}, {}'.format(self.rt, self.label.name) |
219 | 310 |
277 | 311 |
219 | 312 @armtarget.instruction |
313 class ldr_sprel(ls_sp_base_imm8): | |
314 """ ldr Rt, [SP, imm8] """ | |
315 mnemonic = 'LDR' | |
316 opcode = 0x98 | |
317 | |
277 | 318 |
219 | 319 @armtarget.instruction |
320 class str_sprel(ls_sp_base_imm8): | |
321 """ str Rt, [SP, imm8] """ | |
322 mnemonic = 'STR' | |
323 opcode = 0x90 | |
324 | |
277 | 325 |
212 | 326 @armtarget.instruction |
202 | 327 class mov_ins(ArmInstruction): |
328 """ mov Rd, imm8, move immediate value into register """ | |
329 mnemonic = 'mov' | |
203 | 330 opcode = 4 # 00100 Rd(3) imm8 |
277 | 331 operands = (Reg8Op, Imm8) |
203 | 332 def __init__(self, rd, imm): |
333 self.imm = imm.imm | |
277 | 334 self.rd = rd |
205 | 335 |
202 | 336 def encode(self): |
277 | 337 rd = self.rd.num |
202 | 338 opcode = self.opcode |
339 imm8 = self.imm | |
340 h = (opcode << 11) | (rd << 8) | imm8 | |
341 return u16(h) | |
277 | 342 |
219 | 343 def __repr__(self): |
277 | 344 return 'MOV {}, {}'.format(self.rd, self.imm) |
203 | 345 |
219 | 346 |
347 | |
348 # Arithmatics: | |
349 | |
275 | 350 |
351 | |
276 | 352 class regregimm3_base(ArmInstruction): |
353 operands = (Reg8Op, Reg8Op, Imm3) | |
203 | 354 def __init__(self, rd, rn, imm3): |
355 self.rd = rd | |
356 self.rn = rn | |
357 self.imm3 = imm3 | |
277 | 358 |
203 | 359 def encode(self): |
360 rd = self.rd.num | |
361 rn = self.rn.num | |
362 imm3 = self.imm3.imm | |
363 opcode = self.opcode | |
276 | 364 h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd |
203 | 365 return u16(h) |
366 | |
277 | 367 def __repr__(self): |
368 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm) | |
276 | 369 |
370 @armtarget.instruction | |
371 class addregregimm3_ins(regregimm3_base): | |
372 """ add Rd, Rn, imm3 """ | |
373 mnemonic = 'add' | |
374 opcode = 0b0001110 | |
375 | |
376 | |
377 @armtarget.instruction | |
378 class subregregimm3_ins(regregimm3_base): | |
379 """ sub Rd, Rn, imm3 """ | |
380 mnemonic = 'sub' | |
381 opcode = 0b0001111 | |
382 | |
383 | |
219 | 384 class regregreg_base(ArmInstruction): |
385 """ ??? Rd, Rn, Rm """ | |
386 operands = (Reg8Op, Reg8Op, Reg8Op) | |
387 def __init__(self, rd, rn, rm): | |
388 self.rd = rd | |
389 self.rn = rn | |
390 self.rm = rm | |
391 def encode(self): | |
392 rd = self.rd.num | |
393 rn = self.rn.num | |
394 rm = self.rm.num | |
395 h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd | |
396 return u16(h) | |
397 def __repr__(self): | |
398 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) | |
399 | |
277 | 400 |
219 | 401 @armtarget.instruction |
402 class addregs_ins(regregreg_base): | |
403 mnemonic = 'ADD' | |
404 opcode = 0b0001100 | |
405 | |
277 | 406 |
219 | 407 @armtarget.instruction |
408 class subregs_ins(regregreg_base): | |
409 mnemonic = 'SUB' | |
410 opcode = 0b0001101 | |
411 | |
275 | 412 |
277 | 413 |
275 | 414 @armtarget.instruction |
415 class movregreg_ext_ins(ArmInstruction): | |
277 | 416 operands = (ArmRegister, ArmRegister) |
275 | 417 mnemonic = 'MOV' |
418 def __init__(self, rd, rm): | |
419 self.rd = rd | |
420 self.rm = rm | |
277 | 421 |
275 | 422 def encode(self): |
423 Rd = self.rd.num & 0x7 | |
424 D = (self.rd.num >> 3) & 0x1 | |
425 Rm = self.rm.num | |
426 opcode = 0b01000110 | |
427 return u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) | |
277 | 428 |
275 | 429 def __repr__(self): |
430 return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) | |
431 | |
432 | |
276 | 433 @armtarget.instruction |
434 class mulregreg_ins(ArmInstruction): | |
435 """ mul Rn, Rdm """ | |
436 operands = (Reg8Op, Reg8Op) | |
437 mnemonic = 'mul' | |
438 def __init__(self, rn, rdm): | |
439 self.rn = rn | |
440 self.rdm = rdm | |
277 | 441 |
276 | 442 def encode(self): |
443 rn = self.rn.num | |
444 rdm = self.rdm.num | |
445 opcode = 0b0100001101 | |
446 h = (opcode << 6) | (rn << 3) | rdm | |
447 return u16(h) | |
277 | 448 |
276 | 449 def __repr__(self): |
277 | 450 return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) |
451 | |
275 | 452 |
219 | 453 class regreg_base(ArmInstruction): |
454 """ ??? Rdn, Rm """ | |
455 operands = (Reg8Op, Reg8Op) | |
277 | 456 # TODO: integrate with the code gen interface: |
457 src = (0, 1) | |
458 dst = (0,) | |
219 | 459 def __init__(self, rdn, rm): |
460 self.rdn = rdn | |
461 self.rm = rm | |
277 | 462 |
219 | 463 def encode(self): |
464 rdn = self.rdn.num | |
465 rm = self.rm.num | |
466 h = (self.opcode << 6) | (rm << 3) | rdn | |
467 return u16(h) | |
277 | 468 |
219 | 469 def __repr__(self): |
470 return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) | |
471 | |
277 | 472 |
219 | 473 @armtarget.instruction |
258 | 474 class movregreg_ins(regreg_base): |
277 | 475 # TODO: match this: |
476 pattern = ir.Move(ir.Temp, ir.Temp) | |
258 | 477 """ mov Rd, Rm """ |
478 mnemonic = 'mov' | |
479 opcode = 0 | |
480 | |
277 | 481 |
258 | 482 @armtarget.instruction |
219 | 483 class andregs_ins(regreg_base): |
484 mnemonic = 'AND' | |
485 opcode = 0b0100000000 | |
486 | |
277 | 487 |
219 | 488 @armtarget.instruction |
489 class orrregs_ins(regreg_base): | |
490 mnemonic = 'ORR' | |
491 opcode = 0b0100001100 | |
492 | |
277 | 493 |
219 | 494 @armtarget.instruction |
495 class cmp_ins(regreg_base): | |
496 mnemonic = 'CMP' | |
497 opcode = 0b0100001010 | |
498 | |
277 | 499 |
203 | 500 @armtarget.instruction |
232 | 501 class lslregs_ins(regreg_base): |
502 mnemonic = 'LSL' | |
503 opcode = 0b0100000010 | |
504 | |
505 @armtarget.instruction | |
203 | 506 class cmpregimm8_ins(ArmInstruction): |
507 """ cmp Rn, imm8 """ | |
508 mnemonic = 'cmp' | |
509 opcode = 5 # 00101 | |
277 | 510 operands = (Reg8Op, Imm8) |
203 | 511 def __init__(self, rn, imm): |
512 self.rn = rn | |
513 self.imm = imm | |
514 def encode(self): | |
515 rn = self.rn.num | |
516 imm = self.imm.imm | |
517 opcode = self.opcode | |
518 h = (opcode << 11) | (rn << 8) | imm | |
519 return u16(h) | |
202 | 520 |
277 | 521 |
219 | 522 # Jumping: |
218 | 523 |
238 | 524 def wrap_negative(x, bits): |
525 b = struct.unpack('<I', struct.pack('<i', x))[0] | |
526 mask = (1 << bits) - 1 | |
527 return b & mask | |
528 | |
237 | 529 class jumpBase_ins(ArmInstruction): |
530 operands = (LabelRef,) | |
205 | 531 def __init__(self, target_label): |
237 | 532 assert type(target_label) is LabelRef |
205 | 533 self.target = target_label |
237 | 534 self.offset = 0 |
535 | |
536 def resolve(self, f): | |
537 la = f(self.target.name) | |
238 | 538 sa = self.address + 4 |
237 | 539 self.offset = (la - sa) |
238 | 540 #if self.offset < 0: |
541 # # TODO: handle negative jump | |
542 # self.offset = 0 | |
237 | 543 |
219 | 544 def __repr__(self): |
237 | 545 return '{} {}'.format(self.mnemonic, self.target.name) |
219 | 546 |
547 @armtarget.instruction | |
237 | 548 class b_ins(jumpBase_ins): |
549 mnemonic = 'B' | |
550 def encode(self): | |
238 | 551 imm11 = wrap_negative(self.offset >> 1, 11) |
552 h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode | |
237 | 553 return u16(h) |
554 | |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
555 @armtarget.instruction |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
556 class bl_ins(jumpBase_ins): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
557 mnemonic = 'BL' |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
558 def encode(self): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
559 imm32 = wrap_negative(self.offset >> 1, 32) |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
560 imm11 = imm32 & 0x7FF |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
561 imm10 = (imm32 >> 11) & 0x3FF |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
562 j1 = 1 # TODO: what do these mean? |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
563 j2 = 1 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
564 s = (imm32 >> 24) & 0x1 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
565 h1 = (0b11110 << 11) | (s << 10) | imm10 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
566 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
567 return u16(h1) + u16(h2) |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
568 |
237 | 569 class cond_base_ins(jumpBase_ins): |
570 def encode(self): | |
238 | 571 imm8 = wrap_negative(self.offset >> 1, 8) |
237 | 572 h = (0b1101 << 12) | (self.cond << 8) | imm8 |
573 return u16(h) | |
574 | |
262 | 575 |
237 | 576 @armtarget.instruction |
577 class beq_ins(cond_base_ins): | |
219 | 578 mnemonic = 'beq' |
237 | 579 cond = 0 |
580 | |
262 | 581 |
237 | 582 @armtarget.instruction |
262 | 583 class bne_ins(cond_base_ins): |
237 | 584 mnemonic = 'bne' |
585 cond = 1 | |
205 | 586 |
262 | 587 |
588 @armtarget.instruction | |
589 class blt_ins(cond_base_ins): | |
590 mnemonic = 'blt' | |
591 cond = 0b1011 | |
592 | |
593 | |
594 @armtarget.instruction | |
595 class blt_ins(cond_base_ins): | |
596 mnemonic = 'bgt' | |
597 cond = 0b1100 | |
598 | |
599 | |
205 | 600 @armtarget.instruction |
601 class push_ins(ArmInstruction): | |
206 | 602 operands = (RegisterSet,) |
205 | 603 mnemonic = 'push' |
604 def __init__(self, regs): | |
206 | 605 assert (type(regs),) == self.operands, (type(regs),) |
205 | 606 self.regs = regs |
206 | 607 def __repr__(self): |
608 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
205 | 609 def encode(self): |
206 | 610 reg_list = 0 |
611 M = 0 | |
612 for n in self.regs.registerNumbers(): | |
613 if n < 8: | |
614 reg_list |= (1 << n) | |
615 elif n == 14: | |
616 M = 1 | |
617 else: | |
618 raise NotImplementedError('not implemented for this register') | |
619 h = (0x5a << 9) | (M << 8) | reg_list | |
620 return u16(h) | |
205 | 621 |
622 @armtarget.instruction | |
623 class pop_ins(ArmInstruction): | |
206 | 624 operands = (RegisterSet,) |
205 | 625 mnemonic = 'pop' |
626 def __init__(self, regs): | |
627 self.regs = regs | |
207 | 628 def __repr__(self): |
629 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
205 | 630 def encode(self): |
206 | 631 reg_list = 0 |
632 P = 0 | |
633 for n in self.regs.registerNumbers(): | |
634 if n < 8: | |
635 reg_list |= (1 << n) | |
636 elif n == 15: | |
637 P = 1 | |
638 else: | |
639 raise NotImplementedError('not implemented for this register') | |
640 h = (0x5E << 9) | (P << 8) | reg_list | |
641 return u16(h) | |
205 | 642 |
643 @armtarget.instruction | |
202 | 644 class yield_ins(ArmInstruction): |
645 operands = () | |
646 mnemonic = 'yield' | |
647 def encode(self): | |
648 return u16(0xbf10) | |
649 | |
275 | 650 # misc: |
651 | |
652 # add/sub SP: | |
277 | 653 class addspsp_base(ArmInstruction): |
275 | 654 operands = (RegSpOp, RegSpOp, Imm7) |
655 def __init__(self, _sp, _sp2, imm7): | |
656 self.imm7 = imm7.imm | |
657 assert self.imm7 % 4 == 0 | |
658 self.imm7 >>= 2 | |
659 | |
660 def encode(self): | |
277 | 661 return u16((self.opcode << 7) |self.imm7) |
662 | |
663 def __repr__(self): | |
664 return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2) | |
275 | 665 |
666 @armtarget.instruction | |
277 | 667 class addspsp_ins(addspsp_base): |
668 mnemonic = 'add' | |
669 opcode = 0b101100000 | |
670 | |
671 | |
672 @armtarget.instruction | |
673 class subspsp_ins(addspsp_base): | |
275 | 674 mnemonic = 'sub' |
277 | 675 opcode = 0b101100001 |
275 | 676 |
206 | 677 armtarget.check() |
678 |