diff python/ppci/target/arm/instructions.py @ 346:3bb7dcfe5529

expanded arm target
author Windel Bouwman
date Fri, 07 Mar 2014 17:05:32 +0100
parents b4882ff0ed06
children 2b02bd286fe9
line wrap: on
line diff
--- a/python/ppci/target/arm/instructions.py	Sun Mar 02 17:12:08 2014 +0100
+++ b/python/ppci/target/arm/instructions.py	Fri Mar 07 17:05:32 2014 +0100
@@ -1,31 +1,10 @@
-
 
 from ..basetarget import Instruction
+from ...bitfun import rotate_left
 
 from .token import ArmToken
 from .registers import R0, SP, ArmRegister
 
-# Helpers:
-
-def rotate_right(v, n):
-    """ bit-wise Rotate right n times """
-    mask = (2**n) - 1
-    mask_bits = v & mask
-    return (v >> n) | (mask_bits << (32 - n))
-
-def rotate_left(v, n):
-    assert n >= 0
-    assert n < 32
-    return rotate_right(v, 32 - n)
-
-masks = [rotate_right(0xFF, i * 2) for i in range(16)]
-#0x000000FF,
-#0xC000007F,
-#0xF000000F,
-#0xFC000003,
-#0xFF000000, # 4
-
-assert masks[4] == 0xFF000000, hex(masks[4])
 
 def encode_imm32(v):
     """ Bundle 32 bit value into 4 bits rotation and 8 bits value
@@ -46,20 +25,40 @@
         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[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):
@@ -69,6 +68,23 @@
         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):
@@ -87,6 +103,27 @@
             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):
@@ -170,6 +207,8 @@
         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
 
@@ -177,18 +216,108 @@
     opcode = 0b1011
 
 class Bl(BranchLinkBase):
-    cond = 0xE
+    cond = AL
 
 class B(BranchBase):
-    cond = 0xE
+    cond = AL
 
 class Beq(BranchBase):
-    cond = 0x0
+    cond = EQ
 
 class Bgt(BranchBase):
-    cond = 0xC
+    cond = GT
 
 class Ble(BranchBase):
-    cond = 0xD
+    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
+