Mercurial > lcfOS
view python/arm_cm3.py @ 206:6c6bf8890d8a
Added push and pop encodings
author | Windel Bouwman |
---|---|
date | Fri, 28 Jun 2013 16:49:38 +0200 |
parents | d77cb5962cc5 |
children | 8b2f20aae086 |
line wrap: on
line source
import struct, types from target import Register, Instruction, Target, Imm8, Label, Imm3 from asmnodes import ASymbol, ANumber, AUnop, ABinop from ppci import CompilerError import ir def u16(h): return struct.pack('<H', h) def u32(x): return struct.pack('<I', x) armtarget = Target('arm') class ArmReg(Register): def __init__(self, num, name): super().__init__(name) self.num = num def __repr__(self): return self.name class RegOp: def __init__(self, num): assert num < 16 self.num = num @classmethod def Create(cls, vop): if type(vop) is ASymbol: name = vop.name regs = {} for r in armtarget.registers: regs[r.name] = r if name in regs: r = regs[name] return cls(r.num) def getRegNum(n): for r in armtarget.registers: if r.num == n: return r def getRegisterRange(n1, n2): regs = [] if n1.num < n2.num: for n in range(n1.num, n2.num + 1): r = getRegNum(n) assert r regs.append(r) return regs class RegisterSet: def __init__(self, regs): assert type(regs) is set self.regs = regs def __repr__(self): return ','.join([str(r) for r in self.regs]) @classmethod def Create(cls, vop): assert type(vop) is AUnop and vop.operation == '{}' assert type(vop.arg) is list regs = set() for arg in vop.arg: if type(arg) is ASymbol: reg = RegOp.Create(arg) if not reg: return regs.add(reg) elif type(arg) is ABinop and arg.op == '-': reg1 = RegOp.Create(arg.arg1) reg2 = RegOp.Create(arg.arg2) if not reg1: return if not reg2: return for r in getRegisterRange(reg1, reg2): regs.add(r) else: raise Exception('Cannot be') return cls(regs) def registerNumbers(self): return [r.num for r in self.regs] # 8 bit registers: r0 = ArmReg(0, 'r0') armtarget.registers.append(r0) r1 = ArmReg(1, 'r1') armtarget.registers.append(r1) r2 = ArmReg(2, 'r2') armtarget.registers.append(r2) r3 = ArmReg(3, 'r3') armtarget.registers.append(r3) r4 = ArmReg(4, 'r4') armtarget.registers.append(r4) r5 = ArmReg(5, 'r5') armtarget.registers.append(r5) r6 = ArmReg(6, 'r6') armtarget.registers.append(r6) r7 = ArmReg(7, 'r7') armtarget.registers.append(r7) # Other registers: # TODO sp = ArmReg(13, 'sp') armtarget.registers.append(sp) lr = ArmReg(14, 'lr') armtarget.registers.append(lr) pc = ArmReg(15, 'pc') armtarget.registers.append(pc) class ArmInstruction(Instruction): pass class ldr_ins(ArmInstruction): mnemonic = 'ldr' opcode = 1337 irpattern = 'todo' class dcd_ins(ArmInstruction): mnemonic = 'dcd' def __init__(self, expr): self.expr = expr def encode(self): return u32(self.expr) @armtarget.instruction class mov_ins(ArmInstruction): """ mov Rd, imm8, move immediate value into register """ mnemonic = 'mov' opcode = 4 # 00100 Rd(3) imm8 operands = (RegOp, Imm8) irpattern = ir.ImmLoad def __init__(self, rd, imm): self.imm = imm.imm self.r = rd.num @classmethod def FromIr(cls, ir_ins): pass def encode(self): rd = self.r opcode = self.opcode imm8 = self.imm h = (opcode << 11) | (rd << 8) | imm8 return u16(h) @armtarget.instruction class movregreg_ins(ArmInstruction): """ mov Rd, Rm """ mnemonic = 'mov' opcode = 8 # 01000 Rd(3) imm8 operands = (RegOp, RegOp) def __init__(self, rd, rm): self.rd = rd self.rm = rm def encode(self): rd = self.rd.num D = (rd & 0x8) >> 3 assert D < 2 rd = rd & 0x7 rm = self.rm.num assert rm < 16 opcode = self.opcode h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd return u16(h) @armtarget.instruction class addregregimm3_ins(ArmInstruction): """ add Rd, Rn, imm3 """ mnemonic = 'add' opcode = 3 # 00011 operands = (RegOp, RegOp, Imm3) irpattern = 3 def __init__(self, rd, rn, imm3): self.rd = rd self.rn = rn self.imm3 = imm3 def encode(self): rd = self.rd.num rn = self.rn.num imm3 = self.imm3.imm opcode = self.opcode h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd return u16(h) @armtarget.instruction class cmpregimm8_ins(ArmInstruction): """ cmp Rn, imm8 """ mnemonic = 'cmp' opcode = 5 # 00101 operands = (RegOp, Imm8) def __init__(self, rn, imm): self.rn = rn self.imm = imm def encode(self): rn = self.rn.num imm = self.imm.imm opcode = self.opcode h = (opcode << 11) | (rn << 8) | imm return u16(h) @armtarget.instruction class jmp_ins(ArmInstruction): operands = (Label,) mnemonic = 'jmp' def __init__(self, target_label): self.target = target_label def fixUp(self): pass def encode(self): h = 1337 # TODO return u16(h) @armtarget.instruction class push_ins(ArmInstruction): operands = (RegisterSet,) mnemonic = 'push' def __init__(self, regs): print(self.operands) assert (type(regs),) == self.operands, (type(regs),) self.regs = regs def __repr__(self): return '{0} {{{1}}}'.format(self.mnemonic, self.regs) def encode(self): reg_list = 0 M = 0 for n in self.regs.registerNumbers(): if n < 8: reg_list |= (1 << n) elif n == 14: M = 1 else: raise NotImplementedError('not implemented for this register') h = (0x5a << 9) | (M << 8) | reg_list return u16(h) @armtarget.instruction class pop_ins(ArmInstruction): operands = (RegisterSet,) mnemonic = 'pop' def __init__(self, regs): self.regs = regs def encode(self): reg_list = 0 P = 0 for n in self.regs.registerNumbers(): if n < 8: reg_list |= (1 << n) elif n == 15: P = 1 else: raise NotImplementedError('not implemented for this register') h = (0x5E << 9) | (P << 8) | reg_list return u16(h) return u16(0) @armtarget.instruction class yield_ins(ArmInstruction): operands = () mnemonic = 'yield' def encode(self): return u16(0xbf10) armtarget.check()