diff python/ppci/target/thumb/instructions.py @ 342:86b02c98a717 devel

Moved target directory
author Windel Bouwman
date Sat, 01 Mar 2014 15:40:31 +0100
parents python/target/arminstructions.py@4d204f6f7d4e
children 3bb7dcfe5529
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/target/thumb/instructions.py	Sat Mar 01 15:40:31 2014 +0100
@@ -0,0 +1,536 @@
+from ..basetarget import Register, Instruction, Target, Label
+from ..basetarget import Imm32, Imm8, Imm7, Imm3
+from ..token import u16, u32
+from .armtoken import ThumbToken
+from ..arm.registers import R0, ArmRegister, SP
+
+
+# Instructions:
+
+class ThumbInstruction(Instruction):
+    pass
+
+
+class Dcd(ThumbInstruction):
+    def __init__(self, expr):
+        if isinstance(expr, Imm32):
+            self.expr = expr.imm
+            self.label = None
+        elif isinstance(expr, int):
+            self.expr = expr
+            self.label = None
+        else:
+            raise NotImplementedError()
+
+    def encode(self):
+        return u32(self.expr)
+
+    def relocations(self):
+        return []
+
+    def __repr__(self):
+        return 'DCD 0x{0:X}'.format(self.expr)
+
+
+class nop_ins(ThumbInstruction):
+    def encode(self):
+        return bytes()
+
+    def __repr__(self):
+        return 'NOP'
+
+
+# Memory related
+
+class LS_imm5_base(ThumbInstruction):
+    """ ??? Rt, [Rn, imm5] """
+    def __init__(self, rt, rn, imm5):
+        assert imm5 % 4 == 0
+        self.imm5 = imm5 >> 2
+        self.rn = rn
+        self.rt = rt
+        assert self.rn.num < 8
+        assert self.rt.num < 8
+        self.token = ThumbToken()
+
+    def encode(self):
+        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()
+
+    def __repr__(self):
+        mnemonic = "???"
+        return '{} {}, [{}, {}]'.format(mnemonic, self.rt, self.rn, self.imm5)
+
+
+class Str2(LS_imm5_base):
+    opcode = 0xC
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.src[1], im.src[0], im.others[0])
+
+
+class Ldr2(LS_imm5_base):
+    opcode = 0xD
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0], im.others[0])
+
+class ls_sp_base_imm8(ThumbInstruction):
+    def __init__(self, rt, offset):
+        self.rt = rt
+        self.offset = offset
+
+    def encode(self):
+        rt = self.rt.num
+        assert rt < 8
+        imm8 = self.offset >> 2
+        assert imm8 < 256
+        h = (self.opcode << 8) | (rt << 8) | imm8
+        return u16(h)
+
+    def __repr__(self):
+        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()
+
+
+class Ldr3(ThumbInstruction):
+    """ ldr Rt, LABEL, load value from pc relative position """
+    mnemonic = 'ldr'
+    def __init__(self, rt, label):
+        self.rt = rt
+        self.label = label
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.others[0])
+
+    def relocations(self):
+        return [(self.label, 'lit_add_8')]
+
+    def encode(self):
+        rt = self.rt.num
+        assert rt < 8
+        imm8 = 0
+        h = (0x9 << 11) | (rt << 8) | imm8
+        return u16(h)
+
+    def __repr__(self):
+        return 'LDR {}, {}'.format(self.rt, self.label)
+
+
+class Ldr1(ls_sp_base_imm8):
+    """ ldr Rt, [SP, imm8] """
+    opcode = 0x98
+
+
+class Str1(ls_sp_base_imm8):
+    """ str Rt, [SP, imm8] """
+    opcode = 0x90
+
+
+class Mov3(ThumbInstruction):
+    """ mov Rd, imm8, move immediate value into register """
+    opcode = 4 # 00100 Rd(3) imm8
+    def __init__(self, rd, imm):
+        assert imm < 256
+        self.imm = imm
+        self.rd = rd
+        self.token = ThumbToken()
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.others[0])
+
+    def encode(self):
+        rd = self.rd.num
+        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)
+
+
+
+# Arithmatics:
+
+
+
+class regregimm3_base(ThumbInstruction):
+    def __init__(self, rd, rn, imm3):
+        self.rd = rd
+        self.rn = rn
+        assert imm3 < 8
+        self.imm3 = imm3
+        self.token = ThumbToken()
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0], im.others[0])
+
+    def encode(self):
+        rd = self.rd.num
+        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):
+        mnemonic = self.__class__.__name__
+        return '{} {}, {}, {}'.format(mnemonic, self.rd, self.rn, self.imm3)
+
+
+
+class Add2(regregimm3_base):
+    """ add Rd, Rn, imm3 """
+    opcode = 0b0001110
+
+
+class Sub2(regregimm3_base):
+    """ sub Rd, Rn, imm3 """
+    opcode = 0b0001111
+
+
+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()
+
+
+def Add(*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 AddSp(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 Add2(args[0], args[1], args[2])
+    else:
+        raise Exception()
+
+
+class regregreg_base(ThumbInstruction):
+    """ ??? Rd, Rn, Rm """
+    def __init__(self, rd, rn, rm):
+        self.rd = rd
+        self.rn = rn
+        self.rm = rm
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0], im.src[1])
+
+    def encode(self):
+        at = ThumbToken()
+        at.rd = self.rd.num
+        rn = self.rn.num
+        rm = self.rm.num
+        at[3:6] = rn
+        at[6:9] = rm
+        at[9:16] = self.opcode
+        return at.encode()
+
+    def __repr__(self):
+        return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm)
+
+
+class Add3(regregreg_base):
+    mnemonic = 'ADD'
+    opcode = 0b0001100
+
+
+class Sub3(regregreg_base):
+    mnemonic = 'SUB'
+    opcode = 0b0001101
+
+
+class Mov2(ThumbInstruction):
+    """ mov rd, rm """
+    mnemonic = 'MOV'
+    def __init__(self, rd, rm):
+        self.rd = rd
+        self.rm = rm
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0])
+
+    def encode(self):
+        at = ThumbToken()
+        at.rd = self.rd.num & 0x7
+        D = (self.rd.num >> 3) & 0x1
+        Rm = self.rm.num
+        opcode = 0b01000110
+        at[8:16] = opcode
+        at[3:7] = Rm
+        at[7] = D
+        return at.encode()
+
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm)
+
+
+class Mul(ThumbInstruction):
+    """ mul Rn, Rdm """
+    mnemonic = 'MUL'
+    def __init__(self, rn, rdm):
+        self.rn = rn
+        self.rdm = rdm
+
+    @classmethod
+    def fromim(cls, im):
+        assert im.src[1] is im.dst[0]
+        return cls(im.src[0], im.dst[0])
+
+    def encode(self):
+        at = ThumbToken()
+        rn = self.rn.num
+        at.rd = self.rdm.num
+        opcode = 0b0100001101
+        #h = (opcode << 6) | (rn << 3) | rdm
+        at[6:16] = opcode
+        at[3:6] = rn
+        return at.encode()
+
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm)
+
+
+class regreg_base(ThumbInstruction):
+    """ ??? Rdn, Rm """
+    def __init__(self, rdn, rm):
+        self.rdn = rdn
+        self.rm = rm
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.src[0], im.src[1])
+
+    def encode(self):
+        at = ThumbToken()
+        at.rd = self.rdn.num
+        rm = self.rm.num
+        at[3:6] = rm
+        at[6:16] = self.opcode
+        return at.encode()
+
+    def __repr__(self):
+        mnemonic = self.__class__.__name__
+        return '{} {}, {}'.format(mnemonic, self.rdn, self.rm)
+
+
+class movregreg_ins(regreg_base):
+    """ mov Rd, Rm (reg8 operands) """
+    opcode = 0
+
+
+class And(regreg_base):
+    opcode = 0b0100000000
+
+
+class Orr(regreg_base):
+    opcode = 0b0100001100
+
+
+class Cmp(regreg_base):
+    opcode = 0b0100001010
+
+
+class Lsl(regreg_base):
+    opcode = 0b0100000010
+
+
+class Cmp2(ThumbInstruction):
+    """ cmp Rn, imm8 """
+    opcode = 5 # 00101
+    def __init__(self, rn, imm):
+        self.rn = rn
+        self.imm = imm
+
+    def encode(self):
+        at = ThumbToken()
+        at[0:8] = self.imm
+        at[8:11] = self.rn.num
+        at[11:16] = self.opcode
+        return at.encode()
+
+
+# Jumping:
+
+class jumpBase_ins(ThumbInstruction):
+    def __init__(self, target_label):
+        assert type(target_label) is str
+        self.target = target_label
+        self.offset = 0
+
+    def __repr__(self):
+        mnemonic = self.__class__.__name__
+        return '{} {}'.format(mnemonic, self.target)
+
+
+class B(jumpBase_ins):
+    def encode(self):
+        h = (0b11100 << 11) | 0
+        # | 1 # 1 to enable thumb mode
+        return u16(h)
+
+    def relocations(self):
+        return [(self.target, 'wrap_new11')]
+
+class Bl(jumpBase_ins):
+    def encode(self):
+        imm11 = 0
+        imm10 = 0
+        j1 = 1 # TODO: what do these mean?
+        j2 = 1
+        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, 'bl_imm11_imm10')]
+
+
+class cond_base_ins(jumpBase_ins):
+    def encode(self):
+        imm8 = 0
+        h = (0b1101 << 12) | (self.cond << 8) | imm8
+        return u16(h)
+
+    def relocations(self):
+        return [(self.target, 'rel8')]
+
+
+class cond_base_ins_long(jumpBase_ins):
+    """ Encoding T3 """
+    def encode(self):
+        j1 = 1 # TODO: what do these mean?
+        j2 = 1
+        h1 = (0b11110 << 11) | (self.cond << 6)
+        h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11)
+        return u16(h1) + u16(h2)
+
+    def relocations(self):
+        return [(self.target, 'b_imm11_imm6')]
+
+
+class Beq(cond_base_ins):
+    cond = 0
+
+
+class Bne(cond_base_ins):
+    cond = 1
+
+
+class Blt(cond_base_ins):
+    cond = 0b1011
+
+
+class Bgt(cond_base_ins):
+    cond = 0b1100
+
+
+class Push(ThumbInstruction):
+    def __init__(self, regs):
+        assert type(regs) is set
+        self.regs = regs
+
+    def __repr__(self):
+        return 'Push {{{}}}'.format(self.regs)
+
+    def encode(self):
+        at = ThumbToken()
+        for n in register_numbers(self.regs):
+            if n < 8:
+                at[n] = 1
+            elif n == 14:
+                at[8] = 1
+            else:
+                raise NotImplementedError('not implemented for {}'.format(n))
+        at[9:16] = 0x5a
+        return at.encode()
+
+
+
+def register_numbers(regs):
+    for r in regs:
+        yield r.num
+
+class Pop(ThumbInstruction):
+    def __init__(self, regs):
+        assert type(regs) is set
+        self.regs = regs
+        self.token = ThumbToken()
+
+    def __repr__(self):
+        return 'Pop {{{}}}'.format(self.regs)
+
+    def encode(self):
+        for n in register_numbers(self.regs):
+            if n < 8:
+                self.token[n] = 1
+            elif n == 15:
+                self.token[8] = 1
+            else:
+                raise NotImplementedError('not implemented for this register')
+        self.token[9:16] = 0x5E
+        return self.token.encode()
+
+
+
+class Yield(ThumbInstruction):
+    def encode(self):
+        return u16(0xbf10)
+
+# misc:
+
+# add/sub SP:
+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)
+
+    def __repr__(self):
+        mnemonic = self.__class__.__name__
+        return '{} sp, sp, {}'.format(mnemonic, self.imm7 << 2)
+
+
+class AddSp(addspsp_base):
+    opcode = 0b101100000
+
+
+class SubSp(addspsp_base):
+    opcode = 0b101100001