# HG changeset patch # User windel # Date 1356903115 -3600 # Node ID ed230e947dc6319b9dd821a9b16632545b707002 # Parent 28a35161ef23b4e9421f18b8bb6b1ffbee8c0495 Added hexviewer diff -r 28a35161ef23 -r ed230e947dc6 python/hexfile.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/hexfile.py Sun Dec 30 22:31:55 2012 +0100 @@ -0,0 +1,97 @@ +import os + +class HexFileException(Exception): + pass + +def parseHexLine(line): + """ Parses a hexfile line into three parts """ + line = line[1:] # Remove ':' + nums = bytes.fromhex(line) + bytecount = nums[0] + if len(nums) != bytecount + 5: + raise HexFileException('byte count field incorrect') + crc = sum(nums) + if (crc & 0xFF) != 0: + raise HexFileException('crc incorrect') + address = nums[1] * 256 + nums[2] + typ = nums[3] + data = nums[4:-1] + return (address, typ, data) + +class HexFile: + """ Represents an intel hexfile """ + def __init__(self, filename=None): + self.regions = [] + self.startAddress = 0 + self.filename = None + if filename: + self.load(filename) + + def load(self, filename): + with open(filename, 'r') as f: + endOfFile = False + offset = 0 + startAddress = 0 + curAddress = 0 + curData = bytearray() + for line in f: + line = line.strip() # Strip spaces and newlines + if not line: continue # Skip empty lines + if line[0] != ':': continue # Skip lines that do not start with a ':' + if endOfFile: raise HexFileException('hexfile line after end of file record') + address, typ, data = parseHexLine(line) + if typ == 0x0: # Data record + address += offset # Fix address with offset + # Append data + if address == curAddress: + curData += data + curAddress += len(data) + else: + if curData: + self.regions.append(HexFileRegion(startAddress, bytes(curData))) + startAddress = address + curAddress = address + len(data) + curData = bytearray(data) + elif typ == 0x4: # Extended linear address record + offset = ((data[0] << 8) + data[1]) << 16 + elif typ == 0x1: # End of file record + if len(data) != 0: + raise HexFileException('end of file record must contain no data') + endOfFile = True + elif typ == 0x5: # Start address record (where IP goes after loading) + self.startAddress = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3] + else: + raise HexFileException('record type {0} not implemented'.format(typ)) + print(hex(address), typ, data) + # After all lines: + if curData: + self.regions.append(HexFileRegion(startAddress, bytes(curData))) + # Store the filename: + self.filename = filename + def __repr__(self): + i = [] + i.append(super().__repr__()) + i.append('Start address {0}'.format(hex(self.startAddress))) + i.append('Filename: {0}'.format(self.filename)) + for r in self.regions: + i.append(str(r)) + return os.linesep.join(i) + def save(self, filename): + with open(filename, 'w') as f: + for line in f: + pass + +class HexFileRegion: + def __init__(self, address, data = bytes()): + self.address = address + self.data = data + def __repr__(self): + return 'Region at 0x{0:X} of {1} bytes'.format(self.address, len(self.data)) + +if __name__ == '__main__': + h = HexFile() + print(h) + """ Test hexfile implementation with some hexfile """ + h1 = HexFile('audio.hex') + print(h1) + diff -r 28a35161ef23 -r ed230e947dc6 python/hexviewer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/hexviewer.py Sun Dec 30 22:31:55 2012 +0100 @@ -0,0 +1,78 @@ +#!/usr/bin/python + +from PyQt4.QtCore import * +from PyQt4.QtGui import * +import sys +import hexfile + +class BinViewer(QWidget): + """ + The binviewer consists of a hex view, a ascii view + and perhaps others.. + """ + def __init__(self): + super().__init__() + self.setFont(QFont('Courier')) + self.fontHeight = self.fontMetrics().height() + self.fontWidth = self.fontMetrics().width('x') + self.hexfile = hexfile.HexFile() + def paintEvent(self, event): + painter = QPainter(self) + br = QBrush(Qt.lightGray) + painter.setBrush(br) + h = self.height() + addressWidth = self.fontWidth * 8 + painter.drawRect(2, 2, addressWidth, h) + br2 = QBrush(Qt.yellow) + painter.setBrush(br2) + w = self.width() + byteWidth = self.fontWidth * 16 * 3 + painter.drawRect(addressWidth + 4, 2, byteWidth, h) + asciiWidth = self.fontWidth * 16 + br2 = QBrush(Qt.gray) + painter.setBrush(br2) + painter.drawRect(addressWidth + byteWidth + 4, 2, asciiWidth, h) + for r in range(1, 10): + addr = '{0:08X}'.format(r << 16) + painter.drawText(2, 2 + self.fontHeight * r, addr) + bts = bytes(range(16)) + x = addressWidth + 4 + for b in bts: + b = '{0:02X}'.format(b) + painter.drawText(x, 2 + self.fontHeight * r, b) + x += 3 * self.fontWidth + x = addressWidth + byteWidth + 4 + for b in bts: + b = '{0}'.format(chr(b)) + painter.drawText(x, 2 + self.fontHeight * r, b) + x += 1 * self.fontWidth + def setHexFile(self, hf): + self.hexFile = hf + self.update() + +class BinViewMain(QMainWindow): + def __init__(self): + super().__init__() + self.bv = BinViewer() + self.setCentralWidget(self.bv) + self.bv.setHexFile(hexfile.HexFile('audio.hex')) + mb = self.menuBar() + fileMenu = mb.addMenu("File") + + def addMenuEntry(name, menu, callback, shortcut=None): + a = QAction(name, self) + menu.addAction(a) + a.triggered.connect(callback) + if shortcut: a.setShortcut(shortcut) + addMenuEntry("Open", fileMenu, self.openFile, QKeySequence(QKeySequence.Open)) + def openFile(self): + filename = QFileDialog.getOpenFileName(self, "Open hex file...", "*.hex", "Intel hexfiles (*.hex)") + if filename: + h = hexfile.HexFile(filename) + +if __name__ == '__main__': + app = QApplication(sys.argv) + bv = BinViewMain() + bv.show() + app.exec_() + diff -r 28a35161ef23 -r ed230e947dc6 python/ppci/compilers/kscompiler.py --- a/python/ppci/compilers/kscompiler.py Wed Dec 26 10:53:33 2012 +0100 +++ b/python/ppci/compilers/kscompiler.py Sun Dec 30 22:31:55 2012 +0100 @@ -5,17 +5,16 @@ #from .codegenerator import CodeGenerator #from .nodes import ExportedSymbol from ..core.errors import CompilerException -from ..core import version +from ..core.bitreader import BitcodeWriter +from ..core import version, Context #from .. import version class KsCompiler: def __repr__(self): return 'LCFOS compiler {0}'.format(version) - def generateSignature(self, src): - return hashlib.md5(bytes(src,encoding='ascii')).hexdigest() - def compilesource(self, src): + context = Context() """ Front end that handles the stages: """ self.errorlist = [] # Pass 1: parsing and type checking @@ -28,22 +27,10 @@ if len(p.errorlist) > 0: self.errorlist = p.errorlist return + ir = KsIrGenerator().generateIr(context, ast) # pass 2: Optimization # TODO: implement optimization # Pass 3: code generation - ir = KsIrGenerator().generateIr(ast) - # Attach a signature: - ast.signature = self.generateSignature(src) - # Generate exported symbols: return ast - def compileProject(self, project): - mods = [] - for fname in project.files: - print('Compiling {0}...'.format(fname)) - source = project.loadProjectFile(fname) - mod = self.compilesource(source) - mods.append(mod) - return mods - diff -r 28a35161ef23 -r ed230e947dc6 python/ppci/core/__init__.py --- a/python/ppci/core/__init__.py Wed Dec 26 10:53:33 2012 +0100 +++ b/python/ppci/core/__init__.py Sun Dec 30 22:31:55 2012 +0100 @@ -1,10 +1,11 @@ from .instruction import * -from .function import * -from .value import * -from .bitreader import BitReader +from .function import Function +from .value import Value +from .bitreader import BitReader, BitcodeWriter from .errors import CompilerException from .module import Module - +from .llvmtype import FunctionType +from .context import Context version='0.0.1' diff -r 28a35161ef23 -r ed230e947dc6 python/ppci/core/bitreader.py --- a/python/ppci/core/bitreader.py Wed Dec 26 10:53:33 2012 +0100 +++ b/python/ppci/core/bitreader.py Sun Dec 30 22:31:55 2012 +0100 @@ -26,3 +26,49 @@ return int(b[0]) return 2 +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('