Mercurial > lcfOS
diff python/target/arminstructions.py @ 341:4d204f6f7d4e devel
Rewrite of assembler parts
author | Windel Bouwman |
---|---|
date | Fri, 28 Feb 2014 18:07:14 +0100 |
parents | c7cc54c0dfdf |
children |
line wrap: on
line diff
--- a/python/target/arminstructions.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/arminstructions.py Fri Feb 28 18:07:14 2014 +0100 @@ -3,11 +3,10 @@ from .basetarget import Register, Instruction, Target, Label, LabelRef from .basetarget import Imm32, Imm8, Imm7, Imm3 -from .armtokens import ThumbToken, ArmToken -from .armregisters import R0 +from .armtoken import ThumbToken, ArmToken +from .armregisters import R0, ArmRegister, SP -def add_rule(rhs, f): - pass + def u16(h): return struct.pack('<H', h) @@ -16,7 +15,6 @@ return struct.pack('<I', x) -thumb_assembly_rules = [] arm_assembly_rules = [] @@ -55,120 +53,15 @@ return x.number -class MemRegXRel: - def __init__(self, offset): - assert offset % 4 == 0 - self.offset = offset - def __repr__(self): - return '[{}, #{}]'.format(self.regname, self.offset) - - @classmethod - def Create(cls, vop): - if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+': - vop = vop.arg # descent - offset = isRegOffset(cls.regname, vop.arg1, vop.arg2) - if type(offset) is int: - if offset % 4 == 0: - offset = vop.arg2.number - return cls(offset) - elif type(vop) is ASymbol and vop.name.upper() == self.regname: - return cls(0) - - -class MemSpRel(MemRegXRel): - regname = 'SP' - - -class MemR8Rel: - def __init__(self, basereg, offset): - assert type(basereg) is Reg8Op - assert type(offset) is int - self.basereg = basereg - self.offset = offset - - def __repr__(self): - return '[{}, #{}]'.format(self.basereg, self.offset) +# Instructions: - @classmethod - def Create(cls, vop): - if type(vop) is AUnop and vop.operation == '[]': - vop = vop.arg # descent - if type(vop) is ABinop: - if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: - offset = vop.arg2.number - if offset > 120: - return - basereg = Reg8Op.Create(vop.arg1) - if not basereg: - return - else: - return - elif type(vop) is ASymbol: - offset = 0 - basereg = Reg8Op.Create(vop) - if not basereg: - return - else: - return - return cls(getRegNum(basereg.num), offset) - - -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 = ArmRegister.Create(arg) - if not reg: - return - regs.add(reg) - elif type(arg) is ABinop and arg.op == '-': - reg1 = ArmRegister.Create(arg.arg1) - reg2 = ArmRegister.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] +class ThumbInstruction(Instruction): + pass -# Instructions: - -class ArmInstruction(Instruction): - pass - - -allins = [] - - -def instruction(i): - allins.append(i) - return i - -add_rule(['dcd', 'imm32'], lambda rhs: Dcd(rhs[1])) - -class Dcd(ArmInstruction): - mnemonic = 'dcd' - operands = (Imm32,) +class Dcd(ThumbInstruction): def __init__(self, expr): if isinstance(expr, Imm32): self.expr = expr.imm @@ -193,11 +86,7 @@ return 'DCD 0x{0:X}'.format(self.expr) -@instruction -class nop_ins(ArmInstruction): - mnemonic = 'nop' - operands = tuple() - +class nop_ins(ThumbInstruction): def encode(self): return bytes() @@ -207,57 +96,51 @@ # Memory related -class LS_imm5_base(ArmInstruction): +class LS_imm5_base(ThumbInstruction): """ ??? Rt, [Rn, imm5] """ - operands = (Reg8Op, MemR8Rel) - def __init__(self, rt, memop): - assert memop.offset % 4 == 0 - self.imm5 = memop.offset >> 2 - self.rn = memop.basereg.num + def __init__(self, rt, rn, imm5): + assert imm5 % 4 == 0 + self.imm5 = imm5 >> 2 + self.rn = rn self.rt = rt - self.memloc = memop - assert self.rn < 8 + assert self.rn.num < 8 assert self.rt.num < 8 + self.token = ThumbToken() def encode(self): - Rn = self.rn + Rn = self.rn.num Rt = self.rt.num imm5 = self.imm5 + self.token[0:3] = Rt + self.token[3:6] = Rn + self.token[6:11] = imm5 + self.token[11:16] = self.opcode + return self.token.encode() - h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt - return u16(h) + def __repr__(self): + mnemonic = "???" + return '{} {}, [{}, {}]'.format(mnemonic, self.rt, self.rn, self.imm5) - def __repr__(self): - return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) - - -@instruction class Str2(LS_imm5_base): - mnemonic = 'STR' opcode = 0xC @classmethod def fromim(cls, im): - mem = MemR8Rel(im.src[0], im.others[0]) - return cls(im.src[1], mem) + return cls(im.src[1], im.src[0], im.others[0]) -@instruction class Ldr2(LS_imm5_base): - mnemonic = 'LDR' opcode = 0xD @classmethod def fromim(cls, im): - mem = MemR8Rel(im.src[0], im.others[0]) - return cls(im.dst[0], mem) + return cls(im.dst[0], im.src[0], im.others[0]) -class ls_sp_base_imm8(ArmInstruction): - operands = (Reg8Op, MemSpRel) - def __init__(self, rt, memop): +class ls_sp_base_imm8(ThumbInstruction): + def __init__(self, rt, offset): self.rt = rt - self.offset = memop.offset + self.offset = offset def encode(self): rt = self.rt.num @@ -268,73 +151,65 @@ return u16(h) def __repr__(self): - return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) + mnemonic = self.__class__.__name__ + return '{} {}, [sp,#{}]'.format(mnemonic, self.rt, self.offset) def align(x, m): while ((x % m) != 0): x = x + 1 return x +def Ldr(*args): + if len(args) == 2 and isinstance(args[0], ArmRegister) \ + and isinstance(args[1], str): + return Ldr3(*args) + else: + raise Exception() -@instruction -class Ldr3(ArmInstruction): + +class Ldr3(ThumbInstruction): """ ldr Rt, LABEL, load value from pc relative position """ mnemonic = 'ldr' - operands = (Reg8Op, LabelRef) def __init__(self, rt, label): - assert isinstance(label, LabelRef) self.rt = rt self.label = label - self.offset = 0 @classmethod def fromim(cls, im): return cls(im.dst[0], im.others[0]) def relocations(self): - return [(self.label.name, 'lit_add_8')] + return [(self.label, 'lit_add_8')] def encode(self): rt = self.rt.num assert rt < 8 - assert self.offset % 4 == 0 - imm8 = self.offset >> 2 - assert imm8 < 256 - assert imm8 >= 0 + imm8 = 0 h = (0x9 << 11) | (rt << 8) | imm8 return u16(h) def __repr__(self): - return 'LDR {}, {}'.format(self.rt, self.label.name) + return 'LDR {}, {}'.format(self.rt, self.label) -@instruction class Ldr1(ls_sp_base_imm8): """ ldr Rt, [SP, imm8] """ - mnemonic = 'LDR' opcode = 0x98 -@instruction class Str1(ls_sp_base_imm8): """ str Rt, [SP, imm8] """ - mnemonic = 'STR' opcode = 0x90 -@instruction -class Mov3(ArmInstruction): +class Mov3(ThumbInstruction): """ mov Rd, imm8, move immediate value into register """ - mnemonic = 'mov' opcode = 4 # 00100 Rd(3) imm8 - operands = (Reg8Op, Imm8) def __init__(self, rd, imm): - if type(imm) is int: - imm = Imm8(imm) - assert type(imm) is Imm8 - self.imm = imm.imm - assert type(rd) is Reg8Op, str(type(rd)) + assert imm < 256 + self.imm = imm self.rd = rd + self.token = ThumbToken() @classmethod def fromim(cls, im): @@ -342,10 +217,10 @@ def encode(self): rd = self.rd.num - opcode = self.opcode - imm8 = self.imm - h = (opcode << 11) | (rd << 8) | imm8 - return u16(h) + self.token[8:11] = rd + self.token[0:8] = self.imm + self.token[11:16] = self.opcode + return self.token.encode() def __repr__(self): return 'MOV {}, {}'.format(self.rd, self.imm) @@ -356,13 +231,13 @@ -class regregimm3_base(ArmInstruction): - operands = (Reg8Op, Reg8Op, Imm3) +class regregimm3_base(ThumbInstruction): def __init__(self, rd, rn, imm3): self.rd = rd self.rn = rn - assert type(imm3) is Imm3 + assert imm3 < 8 self.imm3 = imm3 + self.token = ThumbToken() @classmethod def fromim(cls, im): @@ -370,35 +245,41 @@ def encode(self): rd = self.rd.num - rn = self.rn.num - imm3 = self.imm3.imm - opcode = self.opcode - h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd - return u16(h) + self.token[0:3] = rd + self.token[3:6] = self.rn.num + self.token[6:9] = self.imm3 + self.token[9:16] = self.opcode + return self.token.encode() def __repr__(self): - return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm) + mnemonic = self.__class__.__name__ + return '{} {}, {}, {}'.format(mnemonic, self.rd, self.rn, self.imm3) -add_rule(['add', 'r8', ',', 'r8', ',', 'imm3'], lambda rhs: Add2(rhs[1], rhs[3], rhs[5])) -@instruction class Add2(regregimm3_base): """ add Rd, Rn, imm3 """ - mnemonic = 'add' opcode = 0b0001110 -@instruction class Sub2(regregimm3_base): """ sub Rd, Rn, imm3 """ - mnemonic = 'sub' opcode = 0b0001111 -class regregreg_base(ArmInstruction): +def Sub(*args): + if len(args) == 3 and args[0] is SP and args[1] is SP and \ + isinstance(args[2], int) and args[2] < 256: + return SubSp(args[2]) + elif len(args) == 3 and isinstance(args[0], ArmRegister) and \ + isinstance(args[1], ArmRegister) and isinstance(args[2], int) and \ + args[2] < 8: + return Sub2(args[0], args[1], args[2]) + else: + raise Exception() + +class regregreg_base(ThumbInstruction): """ ??? Rd, Rn, Rm """ - operands = (Reg8Op, Reg8Op, Reg8Op) def __init__(self, rd, rn, rm): self.rd = rd self.rn = rn @@ -416,30 +297,24 @@ at[3:6] = rn at[6:9] = rm at[9:16] = self.opcode - #h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd - #return u16(h) return at.encode() def __repr__(self): return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) -@instruction -class Add(regregreg_base): +class Add3(regregreg_base): mnemonic = 'ADD' opcode = 0b0001100 -@instruction -class Sub(regregreg_base): +class Sub3(regregreg_base): mnemonic = 'SUB' opcode = 0b0001101 -@instruction -class Mov2(ArmInstruction): +class Mov2(ThumbInstruction): """ mov rd, rm """ - operands = (ArmRegister, ArmRegister) mnemonic = 'MOV' def __init__(self, rd, rm): self.rd = rd @@ -458,16 +333,14 @@ at[8:16] = opcode at[3:7] = Rm at[7] = D - return at.encode() # u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) + return at.encode() def __repr__(self): return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) -@instruction -class Mul(ArmInstruction): +class Mul(ThumbInstruction): """ mul Rn, Rdm """ - operands = (Reg8Op, Reg8Op) mnemonic = 'MUL' def __init__(self, rn, rdm): self.rn = rn @@ -492,12 +365,8 @@ return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) -class regreg_base(ArmInstruction): +class regreg_base(ThumbInstruction): """ ??? Rdn, Rm """ - operands = (Reg8Op, Reg8Op) - # TODO: integrate with the code gen interface: - src = (0, 1) - dst = (0,) def __init__(self, rdn, rm): self.rdn = rdn self.rm = rm @@ -515,118 +384,90 @@ return at.encode() def __repr__(self): - return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) + mnemonic = self.__class__.__name__ + return '{} {}, {}'.format(mnemonic, self.rdn, self.rm) -@instruction class movregreg_ins(regreg_base): """ mov Rd, Rm (reg8 operands) """ - mnemonic = 'mov' opcode = 0 -@instruction class And(regreg_base): - mnemonic = 'AND' opcode = 0b0100000000 -@instruction class Orr(regreg_base): - mnemonic = 'ORR' opcode = 0b0100001100 -@instruction class Cmp(regreg_base): - mnemonic = 'CMP' opcode = 0b0100001010 -@instruction class Lsl(regreg_base): - mnemonic = 'LSL' opcode = 0b0100000010 -@instruction -class cmpregimm8_ins(ArmInstruction): +class cmpregimm8_ins(ThumbInstruction): """ cmp Rn, imm8 """ - mnemonic = 'cmp' opcode = 5 # 00101 - operands = (Reg8Op, 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) + at = ThumbToken() + at[0:8] = self.imm.imm + at[8:11] = self.rn.num + at[11:16] = self.opcode + return at.encode() # Jumping: -def wrap_negative(x, bits): - b = struct.unpack('<I', struct.pack('<i', x))[0] - mask = (1 << bits) - 1 - return b & mask - -class jumpBase_ins(ArmInstruction): - operands = (LabelRef,) +class jumpBase_ins(ThumbInstruction): def __init__(self, target_label): - assert type(target_label) is LabelRef self.target = target_label self.offset = 0 def __repr__(self): - return '{} {}'.format(self.mnemonic, self.target.name) + mnemonic = self.__class__.__name__ + return '{} {}'.format(mnemonic, self.target) -class Imm11Reloc: - def apply(self, P, S): - pass - - -@instruction class B(jumpBase_ins): - mnemonic = 'B' def encode(self): - imm11 = wrap_negative(self.offset >> 1, 11) - h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode + h = (0b11100 << 11) | 0 + # | 1 # 1 to enable thumb mode return u16(h) def relocations(self): - return [(self.target.name, 'wrap_new11')] + return [(self.target, 'wrap_new11')] -@instruction class Bl(jumpBase_ins): - mnemonic = 'BL' def encode(self): - imm32 = wrap_negative(self.offset >> 1, 32) - imm11 = imm32 & 0x7FF - imm10 = (imm32 >> 11) & 0x3FF + imm11 = 0 + imm10 = 0 j1 = 1 # TODO: what do these mean? j2 = 1 - s = (imm32 >> 24) & 0x1 + s = 0 h1 = (0b11110 << 11) | (s << 10) | imm10 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 return u16(h1) + u16(h2) def relocations(self): - return [(self.target.name, 'bl_imm11_imm10')] + return [(self.target, 'bl_imm11_imm10')] class cond_base_ins(jumpBase_ins): def encode(self): - imm8 = wrap_negative(self.offset >> 1, 8) + imm8 = 0 h = (0b1101 << 12) | (self.cond << 8) | imm8 return u16(h) def relocations(self): - return [(self.target.name, 'rel8')] + return [(self.target, 'rel8')] class cond_base_ins_long(jumpBase_ins): @@ -639,123 +480,97 @@ return u16(h1) + u16(h2) def relocations(self): - return [(self.target.name, 'b_imm11_imm6')] + return [(self.target, 'b_imm11_imm6')] -@instruction class Beq(cond_base_ins): - mnemonic = 'beq' cond = 0 -@instruction class Bne(cond_base_ins): - mnemonic = 'bne' cond = 1 -@instruction class Blt(cond_base_ins): - mnemonic = 'blt' cond = 0b1011 -@instruction class Bgt(cond_base_ins): - mnemonic = 'bgt' cond = 0b1100 -@instruction -class Push(ArmInstruction): - operands = (RegisterSet,) - mnemonic = 'push' - +class Push(ThumbInstruction): def __init__(self, regs): - if type(regs) is set: - regs = RegisterSet(regs) - assert (type(regs),) == self.operands, (type(regs),) + assert type(regs) is set self.regs = regs def __repr__(self): - return '{0} {{{1}}}'.format(self.mnemonic, self.regs) + return 'Push {{{}}}'.format(self.regs) def encode(self): - reg_list = 0 - M = 0 - for n in self.regs.registerNumbers(): + at = ThumbToken() + for n in register_numbers(self.regs): if n < 8: - reg_list |= (1 << n) + at[n] = 1 elif n == 14: - M = 1 + at[8] = 1 else: - raise NotImplementedError('not implemented for this register') - h = (0x5a << 9) | (M << 8) | reg_list - return u16(h) + raise NotImplementedError('not implemented for {}'.format(n)) + at[9:16] = 0x5a + return at.encode() + -add_rule(['pop', 'reg_list'], lambda rhs: Pop(rhs[1])) +def register_numbers(regs): + for r in regs: + yield r.num -@instruction -class Pop(ArmInstruction): - operands = (RegisterSet,) - mnemonic = 'pop' - +class Pop(ThumbInstruction): def __init__(self, regs): - if type(regs) is set: - regs = RegisterSet(regs) - assert (type(regs),) == self.operands, (type(regs),) + assert type(regs) is set self.regs = regs + self.token = ThumbToken() def __repr__(self): - return '{0} {{{1}}}'.format(self.mnemonic, self.regs) + return 'Pop {{{}}}'.format(self.regs) def encode(self): - reg_list = 0 - P = 0 - for n in self.regs.registerNumbers(): + for n in register_numbers(self.regs): if n < 8: - reg_list |= (1 << n) + self.token[n] = 1 elif n == 15: - P = 1 + self.token[8] = 1 else: raise NotImplementedError('not implemented for this register') - h = (0x5E << 9) | (P << 8) | reg_list - return u16(h) + self.token[9:16] = 0x5E + return self.token.encode() -@instruction -class Yield(ArmInstruction): - operands = () - mnemonic = 'yield' +class Yield(ThumbInstruction): def encode(self): return u16(0xbf10) # misc: # add/sub SP: -class addspsp_base(ArmInstruction): - operands = (RegSpOp, RegSpOp, Imm7) - def __init__(self, _sp, _sp2, imm7): - self.imm7 = imm7.imm +class addspsp_base(ThumbInstruction): + def __init__(self, imm7): + self.imm7 = imm7 assert self.imm7 % 4 == 0 self.imm7 >>= 2 def encode(self): - return u16((self.opcode << 7) |self.imm7) + return u16((self.opcode << 7) | self.imm7) def __repr__(self): - return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2) + mnemonic = self.__class__.__name__ + return '{} sp, sp, {}'.format(mnemonic, self.imm7 << 2) -@instruction class AddSp(addspsp_base): - mnemonic = 'add' opcode = 0b101100000 -@instruction class SubSp(addspsp_base): - mnemonic = 'sub' opcode = 0b101100001