diff python/ppci/target/arm/instructions.py @ 347:742588fb8cd6 devel

Merge into devel branch
author Windel Bouwman
date Fri, 07 Mar 2014 17:10:21 +0100
parents 3bb7dcfe5529
children 2b02bd286fe9
line wrap: on
line diff
--- a/python/ppci/target/arm/instructions.py	Sat Mar 01 16:27:52 2014 +0100
+++ b/python/ppci/target/arm/instructions.py	Fri Mar 07 17:10:21 2014 +0100
@@ -1,10 +1,22 @@
-
 
 from ..basetarget import Instruction
+from ...bitfun import rotate_left
 
 from .token import ArmToken
-from .registers import R0, SP
+from .registers import R0, SP, ArmRegister
+
 
+def encode_imm32(v):
+    """ Bundle 32 bit value into 4 bits rotation and 8 bits value
+     """
+    for i in range(0, 16):
+        v2 = rotate_left(v, i*2)
+        if (v2 & 0xFFFFFF00) == 0:
+            rotation = i
+            val = v2 & 0xFF
+            x = (rotation << 8) | val
+            return x
+    raise Exception("Invalid value {}".format(v))
 
 # Instructions:
 
@@ -13,25 +25,299 @@
         self.token = ArmToken()
 
 
-class Mov(ArmInstruction):
+class Dcd(ArmInstruction):
+    def __init__(self, v):
+        super().__init__()
+        self.v = v
+
+    def encode(self):
+        self.token[0:32] = self.v
+        return self.token.encode()
+
+
+def Mov(*args):
+    if len(args) == 2:
+        if isinstance(args[1], int):
+            return Mov1(*args)
+        elif isinstance(args[1], ArmRegister):
+            return Mov2(*args)
+    raise Exception()
+
+
+class Mov1(ArmInstruction):
     """ Mov Rd, imm16 """
     def __init__(self, reg, imm):
         super().__init__()
+        assert type(imm) is int
         self.reg = reg
         self.imm = imm
 
     def encode(self):
-        self.token[0:12] = self.imm
-        self.token[12:16] = self.reg.num
+        self.token[0:12] = encode_imm32(self.imm)
+        self.token.Rd = self.reg.num
         self.token[16:20] = 0
-        self.token[20] = 0
+        self.token[20] = 0  # Set flags
         self.token[21:28] = 0b0011101
-        self.token.cond = 0xE # Always!
+        self.token.cond = AL
         return self.token.encode()
 
     def relocations(self):
         return []
 
     def __repr__(self):
-        return 'DCD 0x{0:X}'.format(self.expr)
+        return 'Mov {}, {}'.format(self.reg, self.imm)
+
+
+class Mov2(ArmInstruction):
+    def __init__(self, rd, rm):
+        super().__init__()
+        self.rd = rd
+        self.rm = rm
+
+    def encode(self):
+        self.token[0:4] = self.rm.num
+        self.token[4:12] = 0
+        self.token[12:16] = self.rd.num
+        self.token[16:20] = 0
+        self.token.S = 0
+        self.token[21:28] = 0xD
+        self.token.cond = AL
+        return self.token.encode()
+
+
+def Add(*args):
+    if len(args) == 3 and isinstance(args[0], ArmRegister) and \
+            isinstance(args[1], ArmRegister):
+        if isinstance(args[2], ArmRegister):
+            return Add1(args[0], args[1], args[2])
+        elif isinstance(args[2], int):
+            return Add2(args[0], args[1], args[2])
+    raise Exception()
+
+def Sub(*args):
+    if len(args) == 3 and isinstance(args[0], ArmRegister) and \
+            isinstance(args[1], ArmRegister):
+        if isinstance(args[2], ArmRegister):
+            return Sub1(args[0], args[1], args[2])
+        elif isinstance(args[2], int):
+            return Sub2(args[0], args[1], args[2])
+    raise Exception()
+
+def Mul(*args):
+    return Mul1(args[0], args[1], args[2])
+
+
+class Mul(ArmInstruction):
+    def __init__(self, rd, rn, rm):
+        super().__init__()
+        self.rd = rd
+        self.rn = rn
+        self.rm = rm
+
+    def encode(self):
+        self.token[0:4] = self.rn.num
+        self.token[4:8] = 0b1001
+        self.token[8:12] = self.rm.num
+        self.token[16:20] = self.rd.num
+        self.token.S = 0
+        self.token.cond = AL
+        return self.token.encode()
+
+
+class OpRegRegReg(ArmInstruction):
+    """ add rd, rn, rm """
+    def __init__(self, rd, rn, rm, shift=0):
+        super().__init__()
+        self.rd = rd
+        self.rn = rn
+        self.rm = rm
+
+    def encode(self):
+        self.token[0:4] = self.rm.num
+        self.token[4] = 0
+        self.token[5:7] = 0
+        self.token[7:12] = 0 # Shift
+        self.token.Rd = self.rd.num
+        self.token.Rn = self.rn.num
+        self.token.S = 0 # Set flags
+        self.token[21:28] = self.opcode
+        self.token.cond = 0xE # Always!
+        return self.token.encode()
+
+    def __repr__(self):
+        return 'add {}, {}, {}'.format(self.rd, self.rn, self.rm)
+
+
+class Add1(OpRegRegReg):
+    opcode = 0b0000100
+
+
+class Sub1(OpRegRegReg):
+    opcode = 0b0000010
+
+
+class Orr1(OpRegRegReg):
+    opcode = 0b0001100
+
+
+class OpRegRegImm(ArmInstruction):
+    """ add rd, rn, imm12 """
+    def __init__(self, rd, rn, imm):
+        super().__init__()
+        self.rd = rd
+        self.rn = rn
+        self.imm2 = encode_imm32(imm)
+        self.imm = imm
+
+    def encode(self):
+        self.token[0:12] = self.imm2
+        self.token.Rd = self.rd.num
+        self.token.Rn = self.rn.num
+        self.token.S = 0 # Set flags
+        self.token[21:28] = self.opcode
+        self.token.cond = 0xE # Always!
+        return self.token.encode()
+
+    def __repr__(self):
+        return 'add {}, {}, {}'.format(self.rd, self.rn, self.imm)
+
+
+class Add2(OpRegRegImm):
+    opcode = 0b0010100
+
+
+class Sub2(OpRegRegImm):
+    opcode = 0b0010010
+
+
+
+# Branches:
 
+class BranchBaseRoot(ArmInstruction):
+    def __init__(self, target):
+        super().__init__()
+        self.target = target
+
+    def encode(self):
+        self.token.cond = self.cond
+        self.token[24:28] = self.opcode
+        return self.token.encode()
+
+    def relocations(self):
+        return [(self.target, 'b_imm24')]
+
+
+EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL = range(15)
+
+class BranchBase(BranchBaseRoot):
+    opcode = 0b1010
+
+class BranchLinkBase(BranchBaseRoot):
+    opcode = 0b1011
+
+class Bl(BranchLinkBase):
+    cond = AL
+
+class B(BranchBase):
+    cond = AL
+
+class Beq(BranchBase):
+    cond = EQ
+
+class Bgt(BranchBase):
+    cond = GT
+
+class Ble(BranchBase):
+    cond = LE
+
+class Blt(BranchBase):
+    cond = LT
+
+
+# Memory:
+
+def reg_list_to_mask(reg_list):
+    mask = 0
+    for reg in reg_list:
+        mask |= (1 << reg.num)
+    return mask
+
+
+class Push(ArmInstruction):
+    def __init__(self, register_set):
+        super().__init__()
+        self.reg_list = register_set
+
+    def encode(self):
+        self.token.cond = AL
+        self.token[16:28] = 0b100100101101
+        reg_list = 0
+        self.token[0:16] = reg_list_to_mask(self.reg_list)
+        return self.token.encode()
+
+class Pop(ArmInstruction):
+    def __init__(self, register_set):
+        super().__init__()
+        self.reg_list = register_set
+
+    def encode(self):
+        self.token.cond = AL
+        self.token[16:28] = 0b100010111101
+        self.token[0:16] = reg_list_to_mask(self.reg_list)
+        return self.token.encode()
+
+
+def Ldr(*args):
+    if len(args) == 3 and isinstance(args[1], ArmRegister):
+        return Ldr1(*args)
+    elif len(args) == 2 and isinstance(args[1], ArmRegister):
+        return Ldr1(args[0], args[1], 0)
+    raise Exception()
+
+def Str(*args):
+    if len(args) == 3 and isinstance(args[1], ArmRegister):
+        return Str1(*args)
+    elif len(args) == 2 and isinstance(args[1], ArmRegister):
+        return Str1(args[0], args[1], 0)
+    raise Exception()
+
+
+class LdrStrBase(ArmInstruction):
+    def __init__(self, rt, rn, offset):
+        super().__init__()
+        self.rt = rt
+        self.rn = rn
+        self.offset = offset
+
+    def encode(self):
+        self.token.cond = AL
+        self.token.Rn = self.rn.num
+        self.token[25:28] = self.opcode
+        self.token[20] = self.bit20
+        self.token[12:16] = self.rt.num
+        self.token[24] = 1  # Index
+        if self.offset >= 0:
+            self.token[23] = 1  # U == 1 'add'
+            self.token[0:12] = self.offset
+        else:
+            self.token[23] = 0
+            self.token[0:12] = -self.offset
+        return self.token.encode()
+
+
+class Str1(LdrStrBase):
+    opcode = 0b010
+    bit20 = 0
+
+
+class Ldr1(LdrStrBase):
+    opcode = 0b010
+    bit20 = 1
+
+
+class Ldr3(ArmInstruction):
+    """ Load PC relative constant value """
+    def __init__(self, rt, label):
+        self.rt = rt
+        self.label = label
+