diff python/target/arminstructions.py @ 336:d1ecc493384e

Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
author Windel Bouwman
date Wed, 19 Feb 2014 22:32:15 +0100
parents 582a1aaa3983
children c7cc54c0dfdf
line wrap: on
line diff
--- a/python/target/arminstructions.py	Mon Feb 17 20:41:30 2014 +0100
+++ b/python/target/arminstructions.py	Wed Feb 19 22:32:15 2014 +0100
@@ -10,6 +10,55 @@
 def u32(x):
     return struct.pack('<I', x)
 
+
+def val2bit(v, bits):
+    b = []
+    for i in range(bits):
+        b.append(bool((1<<i) & v))
+    #b.reverse()
+    return b
+
+
+def bit_range(b, e):
+    getter = lambda s: s[b:e]
+    def setter(s, v):
+        s[b:e] = v
+    return property(getter, setter)
+
+class ArmToken:
+    def __init__(self):
+        self.bit_value = 0
+
+    def set_bit(self, i, value):
+        value = bool(value)
+        assert i in range(0, 16)
+        mask = 1 << i
+        if value:
+            self.bit_value |= mask
+        else:
+            self.bit_value &= (~mask)
+
+    def __getitem__(self, key):
+        return False
+
+    def __setitem__(self, key, value):
+        if type(key) is int:
+            self.set_bit(key, value)
+        elif type(key) is slice:
+            assert key.step is None
+            bits = key.stop - key.start
+            value_bits = val2bit(value, bits)
+            for i in range(key.start, key.stop):
+                self.set_bit(i, value_bits[i - key.start])
+        else:
+            raise KeyError()
+
+    rd = bit_range(0, 3)
+
+    def encode(self):
+        return u16(self.bit_value)
+
+
 # Operands:
 
 class ArmRegister(Register):
@@ -440,11 +489,16 @@
         return cls(im.dst[0], im.src[0], im.src[1])
 
     def encode(self):
-        rd = self.rd.num
+        at = ArmToken()
+        at.rd = self.rd.num
         rn = self.rn.num
         rm = self.rm.num
-        h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd
-        return u16(h)
+        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)
@@ -476,11 +530,15 @@
         return cls(im.dst[0], im.src[0])
 
     def encode(self):
-        Rd = self.rd.num & 0x7
+        at = ArmToken()
+        at.rd = self.rd.num & 0x7
         D = (self.rd.num >> 3) & 0x1
         Rm = self.rm.num
         opcode = 0b01000110
-        return u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd)
+        at[8:16] = opcode
+        at[3:7] = Rm
+        at[7] = D
+        return at.encode() # u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd)
 
     def __repr__(self):
         return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm)
@@ -501,11 +559,14 @@
         return cls(im.src[0], im.dst[0])
 
     def encode(self):
+        at = ArmToken()
         rn = self.rn.num
-        rdm = self.rdm.num
+        at.rd = self.rdm.num
         opcode = 0b0100001101
-        h = (opcode << 6) | (rn << 3) | rdm
-        return u16(h)
+        #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)
@@ -526,10 +587,12 @@
         return cls(im.src[0], im.src[1])
 
     def encode(self):
-        rdn = self.rdn.num
+        at = ArmToken()
+        at.rd = self.rdn.num
         rm = self.rm.num
-        h = (self.opcode << 6) | (rm << 3) | rdn
-        return u16(h)
+        at[3:6] = rm
+        at[6:16] = self.opcode
+        return at.encode()
 
     def __repr__(self):
         return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm)
@@ -636,7 +699,7 @@
         return [(self.target.name, 'bl_imm11_imm10')]
 
 
-class cond_base_ins_short(jumpBase_ins):
+class cond_base_ins(jumpBase_ins):
     def encode(self):
         imm8 = wrap_negative(self.offset >> 1, 8)
         h = (0b1101 << 12) | (self.cond << 8) | imm8
@@ -646,7 +709,7 @@
         return [(self.target.name, 'rel8')]
 
 
-class cond_base_ins(jumpBase_ins):
+class cond_base_ins_long(jumpBase_ins):
     """ Encoding T3 """
     def encode(self):
         j1 = 1 # TODO: what do these mean?