Package envi :: Module bits
[hide private]
[frames] | no frames]

Source Code for Module envi.bits

  1  """ 
  2  A file full of bit twidling helpers 
  3  """ 
  4   
  5  import struct 
  6   
  7  MAX_WORD = 8 # Dont have any more than 64 bit archs 
  8   
  9  # Masks to use for unsigned anding to size 
 10  u_maxes = [ (2 ** (8*i)) - 1 for i in range(MAX_WORD+1) ] 
 11  u_maxes[0] = 0 # powers of 0 are 1, but we need 0 
 12   
 13  # Masks of just the sign bit for different sizes 
 14  sign_bits = [ (2 ** (8*i)) >> 1 for i in range(MAX_WORD+1) ] 
 15  sign_bits[0] = 0 # powers of 0 are 1, but we need 0 
 16   
 17  # Max *signed* masks (all but top bit ) 
 18  s_maxes = [ u_maxes[i] ^ sign_bits[i] for i in range(len(u_maxes))] 
 19  s_maxes[0] = 0 
 20   
 21  # bit width masks  
 22  b_masks = [ (2**i)-1 for i in range(MAX_WORD*8) ] 
 23  b_masks[0] = 0 
 24   
25 -def unsigned(value, size):
26 """ 27 Make a value unsigned based on it's size. 28 """ 29 # In python "&" will do abs value 30 return value & u_maxes[size]
31
32 -def signed(value, size):
33 """ 34 Make a value signed based on it's size. 35 """ 36 x = unsigned(value, size) 37 if x & sign_bits[size]: 38 x = (x - u_maxes[size]) - 1 39 return x
40
41 -def is_signed(value, size):
42 x = unsigned(value, size) 43 return bool(x & sign_bits[size])
44
45 -def sign_extend(value, cursize, newsize):
46 """ 47 Take a value and extend it's size filling 48 in the space with the value of the high 49 order bit. 50 """ 51 x = unsigned(value, cursize) 52 if cursize != newsize: 53 # Test for signed w/o the call 54 if x & sign_bits[cursize]: 55 delta = newsize - cursize 56 highbits = u_maxes[delta] 57 x |= highbits << (8*cursize) 58 return x
59
60 -def is_parity(val):
61 s = 0 62 while val: 63 s ^= val & 1 64 val = val >> 1 65 return (not s)
66 67 parity_table = [] 68 for i in range(256): 69 parity_table.append(is_parity(i)) 70
71 -def is_parity_byte(bval):
72 """ 73 An "optimized" parity checker that looks up the index. 74 """ 75 return parity_table[bval & 0xff]
76
77 -def lsb(value):
78 return value & 0x1
79
80 -def msb(value, size):
81 if value & sign_bits[size]: 82 return 1 83 return 0
84
85 -def is_signed_overflow(value, size):
86 max = s_maxes[size] 87 if value > max: 88 return True 89 if value < -max: 90 return True 91 return False
92
93 -def is_unsigned_carry(value, size):
94 umax = u_maxes[size] 95 if value > umax: 96 return True 97 elif value < 0: 98 return True 99 return False
100
101 -def is_aux_carry(src, dst):
102 # FIXME this is only how to do it for add... 103 dst = dst & 0xf 104 src = src & 0xf 105 if (dst + src) > 15: 106 return True 107 return False
108 109 le_fmt_chars = (None,"B","<H",None,"<L",None,None,None,"<Q") 110 be_fmt_chars = (None,"B",">H",None,">L",None,None,None,">Q")
111 -def parsebytes(bytes, offset, size, sign=False, bigend=False):
112 """ 113 Mostly for pulling immediates out of strings... 114 """ 115 if size > 8: 116 return slowparsebytes(bytes, offset, size, sign=sign, bigend=bigend) 117 if bigend: 118 f = be_fmt_chars[size] 119 else: 120 f = le_fmt_chars[size] 121 if f == None: 122 return slowparsebytes(bytes, offset, size, sign=sign, bigend=bigend) 123 d = bytes[offset:offset+size] 124 x = struct.unpack(f, d)[0] 125 if sign: 126 x = signed(x, size) 127 return x
128
129 -def slowparsebytes(bytes, offset, size, sign=False, bigend=False):
130 if bigend: 131 begin = offset 132 inc = 1 133 else: 134 begin = offset + (size-1) 135 inc = -1 136 137 ret = 0 138 ioff = 0 139 for x in range(size): 140 ret = ret << 8 141 ret |= ord(bytes[begin+ioff]) 142 ioff += inc 143 if sign: 144 ret = signed(ret, size) 145 return ret
146
147 -def buildbytes(value, size, bigend=False):
148 if bigend: 149 f = be_fmt_chars[size] 150 else: 151 f = le_fmt_chars[size] 152 if f == None: 153 raise Exception("envi.bits.buildbytes needs slowbuildbytes") 154 return struct.pack(f, value)
155
156 -def byteswap(value, size):
157 ret = 0 158 for i in range(size): 159 ret |= (value >> (8*i)) & 0xff 160 ret = ret << 8 161 return ret
162 163 hex_fmt = { 164 1:"0x%.2x", 165 2:"0x%.4x", 166 4:"0x%.8x", 167 8:"0x%.16x", 168 } 169
170 -def intwidth(val):
171 if val < 0: 172 val = abs(val) 173 ret = 0 174 while val: 175 ret += 1 176 val = val >> 8 177 return ret
178
179 -def hex(value, size=None):
180 if size == None: 181 size = intwidth(value) 182 183 fmt = hex_fmt.get(size) 184 if fmt != None: 185 return fmt % value 186 187 x = [] 188 while value: 189 x.append('%.2x' % (value & 0xff)) 190 value = value >> 8 191 x.reverse() 192 return '0x%.s' % ''.join(x) 193 194 195 return hex_fmt.get(size) % value
196
197 -def binrepr(intval, bitwidth=None):
198 ''' 199 Return a string of one's and zero's for the given value. 200 ''' 201 ret = [] 202 while intval: 203 ret.append(str(intval & 0x1)) 204 intval >>= 1 205 ret.reverse() 206 binstr = ''.join(ret) 207 if bitwidth != None: 208 binstr = binstr.rjust(bitwidth, '0') 209 return binstr
210
211 -def binary(binstr):
212 ''' 213 Decode a binary string of 1/0's into a python number 214 ''' 215 x = 0 216 for c in binstr: 217 x = (x << 1) + int(c) 218 return x
219
220 -def binbytes(binstr):
221 ''' 222 Decode a binary string of 1/0's into a python binary 223 string. 224 ''' 225 if len(binstr) % 8 != 0: 226 raise Exception('Byte padded binary strings only for now!') 227 bytes = '' 228 while binstr: 229 bytes += chr( binary(binstr[:8]) ) 230 binstr = binstr[8:] 231 return bytes
232
233 -def parsebits(bytes, offset, bitoff, bitsize):
234 ''' 235 Parse bitsize bits from the bit offset bitoff beginning 236 at offset bytes. 237 238 Example: 239 ''' 240 val = 0 241 cnt = 0 242 while cnt < bitsize: 243 244 addbit = bitoff + cnt 245 addoff = offset + (addbit / 8) 246 247 modoff = addbit % 8 248 249 o = ord(bytes[addoff]) 250 val = (val << 1) + ((o >> (7 - modoff)) & 1) 251 252 cnt += 1 253 254 return val
255 256 #if __name__ == '__main__': 257 #print hex(parsebits('\x0f\x00', 0, 4, 8)) 258 #print hex(parsebits('\x0f\x0f', 0, 4, 12)) 259 #print hex(parsebits('\x0f\x0f\xf0', 1, 4, 4)) 260