#!/usr/bin/env python import re import sys import math # word = int(sys.argv[1], 16) def field_disp(lm): if lm[0] == lm[1]: return "%d" % lm[0] else: return "%d:%d" % (lm[0], lm[1]) def inv_sort_sizes(sz): return sorted([(v, k) for k, v in sz.iteritems()]) class Desc(object): SIZES = { 'B': 8, 'W': 16, 'D': 32, 'Q': 64, } INV_SIZES = inv_sort_sizes(SIZES) def __init__(self, lines): self.struct = [] self.cur = [] self.curname = None self.curbase = None self.cursz = None self.up = None self.base = 0 # base offset (in bits) for lnum, line in enumerate(lines): lnum += 1 line = line.strip() if not line: continue if line.upper() in self.SIZES: self.new_word(line.upper()) continue parts = re.split(r"\s*:\s*", line) if len(parts) == 1: parts = parts * 2 if len(parts) > 2: raise ValueError("bad line: %s" % line) limits = [int(p) for p in parts] if limits[0] < limits[1]: raise ValueError("wrong order in line %d: %r" % (lnum, line)) if limits[1] < 0: raise ValueError("bad bit num in line %d: %r" % (lnum, line)) if self.cursz is None: for bn, size_qual in self.INV_SIZES: if bn > limits[0]: self.new_word(size_qual, "auto ") break else: raise ValueError("out of range bitfield in line %d: %r" % (lnum, line)) if limits[0] + 1 > self.up: raise ValueError("out of range or not in decreasing order " "at line %d: %r" % (lnum, line)) if limits[0] + 1 < self.up: auto_ins = [self.up - 1, limits[0] + 1] self.ins_bitfield(auto_ins, "auto ") self.ins_bitfield(limits) if limits[1] == 0: self.close_cur() self.close_cur() def ins_bitfield(self, bf, why=""): print "%sinserting bit field %s" % (why, field_disp(bf)) self.up = bf[1] self.cur.append(bf) def new_word(self, size_qual, why=""): bit_num = self.SIZES[size_qual] self.close_cur() self.cursz = self.up = bit_num self.curbase = self.base self.curname = "%s@%d(%d)" % (size_qual, self.base / 8, self.base) self.base += bit_num print "%snew word %s" % (why, self.curname) def close_cur(self): if self.cursz is None: return if not self.cur: self.ins_bitfield([self.cursz - 1, 0], "auto ") elif self.cur[-1][1] > 0: self.ins_bitfield([self.cur[-1][1] - 1, 0], "auto ") print "closing %s" % self.curname self.struct.append((self.curname, self.curbase, self.cur)) self.cur = [] self.curname = None self.cursz = None self.up = None def parse_print(self, val): for name, base, fields in self.struct: wval = val >> base print "%s:" % name for hb, lb in fields: bn = (hb - lb + 1) fval = (wval >> lb) & ((1 << bn) - 1) print " %s\t%sb\t%sh\t%d" % ( field_disp([hb, lb]), to_bin(fval, bn), to_hex(fval, bn), fval) def to_bin(v, bn): pref = "" if v & ((1 << bn) - 1) != v: pref = "OVERFLOW:" bn = int((math.ceil(math.log(v + 1, 2)))) return pref + ''.join([str((v >> i) & 1) for i in xrange(bn - 1, -1, -1)]) def to_hex(v, bn): hn = (bn + 3) / 4 fmt = "%%0%dx" % hn return fmt % v desc = Desc(sys.stdin) print desc.parse_print(int(sys.argv[1], 16))