diff python/ppci/target/arm/instructions.py @ 345:b4882ff0ed06

Added more arm isa tests
author Windel Bouwman
date Sun, 02 Mar 2014 17:12:08 +0100
parents 86b02c98a717
children 3bb7dcfe5529
line wrap: on
line diff
--- a/python/ppci/target/arm/instructions.py	Sat Mar 01 16:32:27 2014 +0100
+++ b/python/ppci/target/arm/instructions.py	Sun Mar 02 17:12:08 2014 +0100
@@ -3,8 +3,41 @@
 from ..basetarget import Instruction
 
 from .token import ArmToken
-from .registers import R0, SP
+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
+     """
+    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:
 
@@ -22,7 +55,7 @@
 
     def encode(self):
         self.token[0:12] = self.imm
-        self.token[12:16] = self.reg.num
+        self.token.Rd = self.reg.num
         self.token[16:20] = 0
         self.token[20] = 0
         self.token[21:28] = 0b0011101
@@ -33,5 +66,129 @@
         return []
 
     def __repr__(self):
-        return 'DCD 0x{0:X}'.format(self.expr)
+        return 'Mov {}, {}'.format(self.reg, self.imm)
+
+
+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()
+
+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')]
+
+
+class BranchBase(BranchBaseRoot):
+    opcode = 0b1010
+
+class BranchLinkBase(BranchBaseRoot):
+    opcode = 0b1011
+
+class Bl(BranchLinkBase):
+    cond = 0xE
+
+class B(BranchBase):
+    cond = 0xE
+
+class Beq(BranchBase):
+    cond = 0x0
+
+class Bgt(BranchBase):
+    cond = 0xC
+
+class Ble(BranchBase):
+    cond = 0xD
+
+