Mercurial > lcfOS
view python/ppci/core/bitreader.py @ 139:2ec4d4332b7a
Improve hexedit
author | Windel Bouwman |
---|---|
date | Sat, 26 Jan 2013 19:44:36 +0100 |
parents | 6a303f835c6d |
children |
line wrap: on
line source
from .errors import CompilerException from .module import Module import struct def enum(**enums): return type('Enum', (), enums) BitCodes = enum(END_BLOCK=0, ENTER_SUBBLOCK=1) class BitstreamReader: def __init__(self, f): self.f = f # Initialize the bitreader: self.bitsInCurrent = 32 self.curWord = self.getWord() self.curCodeSize = 2 def getWord(self): bts = self.f.read(4) return struct.unpack('<I', bts)[0] def Read(self, numbits): if numbits > 32: raise CompilerException("Cannot read more than 32 bits") if self.bitsInCurrent >= numbits: # numbits inside the current word: R = self.curWord & ((1 << numbits) - 1) self.curWord = self.curWord >> numbits self.bitsInCurrent -= numbits return R R = self.curWord self.curWord = self.getWord() bitsLeft = numbits - self.bitsInCurrent # Add remaining bits: R |= (self.curWord & (0xFFFFFFFF >> (32 - bitsLeft))) << self.bitsInCurrent # Update curword and bits in current: self.curWord = self.curWord >> bitsLeft self.bitsInCurrent = 32 - bitsLeft return R def ReadVBR(self, numbits): """ Read variable bits, checking for the last bit is zero. """ piece = self.Read(numbits) if (piece & (1 << (numbits - 1))) == 0: return piece result = 0 nextbit = 0 while True: mask = (1 << (numbits - 1)) - 1 result |= ( piece & mask ) << nextbit if (piece & (1 << (numbits - 1))) == 0: return result nextbit += numbits - 1 piece = self.Read(numbits) def ReadCode(self): """ Read the code depending on the current code size """ return self.Read(self.curCodeSize) def ReadSubBlockId(self): return self.ReadVBR(8) def EnterSubBlock(self, blockId): pass BLOCKINFO_BLOCKID = 0 FIRST_APPLICATION_BLOCKID = 8 MODULE_BLOCKID = FIRST_APPLICATION_BLOCKID class BitcodeReader: def __init__(self, f): self.stream = BitstreamReader(f) def parseModule(self): for bitsig in [ord('B'), ord('C')]: if self.stream.Read(8) != bitsig: raise CompilerException('Invalid bitcode signature') for bitsig in [0x0, 0xC, 0xE, 0xD]: if self.stream.Read(4) != bitsig: raise CompilerException('Invalid bitcode signature') while True: code = self.stream.ReadCode() if code != BitCodes.ENTER_SUBBLOCK: raise CompilerException('Invalid record at toplevel') blockId = self.stream.ReadSubBlockId() if blockId == MODULE_BLOCKID: print('module block') pass else: print('Block id:', blockId) raise return Module() class BitstreamWriter: def __init__(self, f): self.f = f self.u32 = 0 self.curpos = 0 def Emit1(self, val): self.Emit(val, 1) def Emit(self, val, numbits): """ Emits value using numbits bits """ if numbits == 1: if val != 0: self.u32 |= (0x1 << self.curpos) self.curpos += 1 if self.curpos == 32: self.writeWord() elif numbits > 1: for i in range(numbits): if val & (1 << i) != 0: self.Emit1(1) else: self.Emit1(0) def writeWord(self): bts = struct.pack('<I', self.u32) self.f.write(bts) self.u32 = 0 self.curpos = 0 def flush(self): if self.curpos != 0: self.writeWord() class BitcodeWriter: def __init__(self): pass def WriteModule(self, module): pass def WriteModuleToFile(self, module, f): s = BitstreamWriter(f) s.Emit(ord('B'), 8) s.Emit(ord('C'), 8) s.Emit(0x0, 4) s.Emit(0xC, 4) s.Emit(0xE, 4) s.Emit(0xD, 4) self.WriteModule(module) s.flush()