# HG changeset patch # User Windel Bouwman # Date 1424296602 -3600 # Node ID 994c00d55fd5803249e5064fe7dd7b28f260f45e # Parent 0374c65cb437ddfe40cfdb44a902e64a8dfe8988 Remove files that are now in ppci diff -r 0374c65cb437 -r 994c00d55fd5 doc/compiler.rst --- a/doc/compiler.rst Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ - - -.. toctree:: - - ir - -Compiler -======== - -This chapter describes the design of the compiler. -The compiler consists a frontend, mid-end and back-end. The frontend deals with -source file parsing and semantics checking. The mid-end performs optimizations. -This is optional. The back-end generates machine code. The front-end produces -intermediate code. This is a simple representation of the source. The back-end -can accept this kind of representation. - -.. graphviz:: - - digraph x { - rankdir="LR" - 1 [label="c3 source file"] - 10 [label="c3 front end" ] - 11 [label="language X front end" ] - 20 [label="mid end" ] - 30 [label="back end for X86" ] - 31 [label="back end for ARM" ] - 40 [label="object file"] - 1 -> 10 - 10 -> 20 [label="IR-code"] - 11 -> 20 [label="IR-code"] - 20 -> 30 [label="IR-code"] - 20 -> 31 [label="IR-code"] - 30 -> 40 - } - - -IR-code -------- - -The intermediate representation (IR) of a program de-couples the front end -from the backend of the compiler. - -See :doc:`ir` for details about all the available instructions. - - -C3 Front-end ------------- - -For the front-end a recursive descent parser is created for the c3 language. -This is a subset of the C language with some additional features. - -.. graphviz:: - - digraph c3 { - rankdir="LR" - 1 [label="source text"] - 10 [label="lexer" ] - 20 [label="parser" ] - 40 [label="code generation"] - 99 [label="IR-code object"] - 1 -> 10 - 10 -> 20 - 20 -> 40 - 40 -> 99 - } - -.. autoclass:: ppci.c3.Lexer - -.. autoclass:: ppci.c3.Parser - -.. autoclass:: ppci.c3.CodeGenerator - -.. autoclass:: ppci.c3.Builder - -Back-end --------- - -The back-end is more complicated. There are several steps to be taken here. - -1. Canonicalization -2. Tree creation -3. Instruction selection -4. register allocation -5. Instruction emission -6. TODO: Peep hole optimization? - -.. automodule:: ppci.codegen - :members: - -Canonicalize -~~~~~~~~~~~~ - -During this phase, the IR-code is made simpler. Function calls are pulled pulled -to top level and the frame pointer is introduced. - -Tree building -~~~~~~~~~~~~~ - -From IR-code a tree is generated which can be used to select instructions. - -Instruction selection -~~~~~~~~~~~~~~~~~~~~~ - -The instruction selection phase takes care of scheduling and instruction -selection. The output of this phase is a one frame per function with a flat -list of abstract machine instructions. - -// .. autoclass:: ppci.irmach.Frame - -// .. autoclass:: ppci.irmach.AbstractInstruction - -To select instruction, a tree rewrite system is used. This is also called -bottom up rewrite generator (BURG). See pyburg. - - -Register allocation -~~~~~~~~~~~~~~~~~~~ - -The selected instructions are used to select correct registers. - - -code emission -~~~~~~~~~~~~~ - -Code is emitted using the outputstream class. The assembler and compiler use -this class to emit instructions to. The stream can output to object file -or to a logger. - -.. autoclass:: ppci.outstream.OutputStream - diff -r 0374c65cb437 -r 994c00d55fd5 doc/ir.rst --- a/doc/ir.rst Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ - - -IR-code -======= - -Front ends generate this IR-code. Backends transform it into machine code. - -The IR-code is implemented in the ir package. - -.. autoclass:: ppci.ir.Module - -.. autoclass:: ppci.ir.Function - -.. autoclass:: ppci.ir.Block - -A block contains a sequence of statements. - -.. autoclass:: ppci.ir.Statement - -.. autoclass:: ppci.ir.Move - -Jump instructions: - -.. autoclass:: ppci.ir.Jump - -.. autoclass:: ppci.ir.CJump - -Statements can contain again expressions. - -.. autoclass:: ppci.ir.Expression - -.. autoclass:: ppci.ir.Const - -.. autoclass:: ppci.ir.Binop - -.. autoclass:: ppci.ir.Call - -.. autoclass:: ppci.ir.Eseq - diff -r 0374c65cb437 -r 994c00d55fd5 doc/utils.rst --- a/doc/utils.rst Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ - -Utilities -========= - -Hexfile manipulation --------------------- - - -.. autoclass:: utils.HexFile - - ->>> from utils import HexFile ->>> h = HexFile() ->>> h.dump() -Hexfile containing 0 bytes ->>> h.addRegion(0, bytes([1,2,3])) ->>> h -Hexfile containing 3 bytes - - -Yacc ----- - -.. automodule:: yacc - - -Burg ----- - -.. automodule:: pyburg - - -Machine descriptions --------------------- - -There are some attempts made already to describe machines in a Domain -Specific Language (DSL). Examples of these are: -- Tablegen (llvm) -- cgen (gnu) -- LISA (Aachen) -- nML (Berlin) -- SLED (Specifying representations of machine instructions (norman ramsey and Mary F. Fernandez)) - - -The goal of a machine description file is to describe a file and generate -tools like assemblers, disassemblers, linkers, debuggers and simulators. - -Advantage of using this approach is that porting these tools is a semi automated -process. Rewriting all of these tools from scratch is tedious and errorprone. - -Concepts to use in this language: -- Single stream of instructions -- State stored in memory -- Pipelining -- Instruction semantics - -Each instruction has the following properties: -- Bit representation -- Assembly language representation -- Semantic action - -Optionally a description in terms of compiler code generation can be attached -to this. But perhaps this clutters the description too much and we need to put -it elsewhere. - - -The description language can help to expand these descriptions by expanding -the permutations. - - - diff -r 0374c65cb437 -r 994c00d55fd5 python/asm.py --- a/python/asm.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -from ppci.target.target_list import targets -from ppci.buildfunctions import assemble - -if __name__ == '__main__': - # When run as main file, try to grab command line arguments: - parser = argparse.ArgumentParser(description="Assembler") - parser.add_argument('sourcefile', type=argparse.FileType('r'), - help='the source file to assemble') - args = parser.parse_args() - obj = assemble(args.sourcefile, targets['arm']) diff -r 0374c65cb437 -r 994c00d55fd5 python/c3c.py --- a/python/c3c.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -#!/usr/bin/env python - -import sys -import argparse -import logging - -from ppci.buildfunctions import c3toir -import ppci.buildtasks # Include not used, but it registers build tasks. -import ppci -from zcc import logLevel - - -def make_parser(): - parser = argparse.ArgumentParser(description='c3 Compiler') - - parser.add_argument('--log', help='Log level (INFO,DEBUG,[WARN])', - type=logLevel, default='INFO') - - parser.add_argument('--target', help='target machine', default="arm") - parser.add_argument('-o', '--output', help='target machine', - type=argparse.FileType('w'), default=sys.stdout) - parser.add_argument('-i', '--include', action='append', - help='include file', default=[]) - parser.add_argument('sources', metavar='source', - help='source file', nargs='+') - return parser - - -def main(args): - # Configure some logging: - logging.getLogger().setLevel(logging.DEBUG) - ch = logging.StreamHandler() - ch.setFormatter(logging.Formatter(ppci.logformat)) - ch.setLevel(args.log) - logging.getLogger().addHandler(ch) - - res = c3toir(args.sources, args.include, args.target) - writer = ppci.irutils.Writer() - for ir_module in res: - writer.write(ir_module, args.output) - - logging.getLogger().removeHandler(ch) - return res - - -if __name__ == '__main__': - parser = make_parser() - arguments = parser.parse_args() - sys.exit(main(arguments)) diff -r 0374c65cb437 -r 994c00d55fd5 python/hexutil.py --- a/python/hexutil.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -#!/usr/bin/python - -import sys -import argparse -from utils import HexFile - -def hex2int(s): - if s.startswith('0x'): - s = s[2:] - return int(s, 16) - raise ValueError('Hexadecimal value must begin with 0x') - -parser = argparse.ArgumentParser( - description='hexfile manipulation tool by Windel Bouwman') -subparsers = parser.add_subparsers(title='commands', - description='possible commands', dest='command') - -p = subparsers.add_parser('info', help='dump info about hexfile') -p.add_argument('hexfile', type=argparse.FileType('r')) - -p = subparsers.add_parser('new', help='create a hexfile') -p.add_argument('hexfile', type=argparse.FileType('w')) -p.add_argument('address', type=hex2int, help="hex address of the data") -p.add_argument('datafile', type=argparse.FileType('rb'), help='binary file to add') - -p = subparsers.add_parser('merge', help='merge two hexfiles into a third') -p.add_argument('hexfile1', type=argparse.FileType('r'), help="hexfile 1") -p.add_argument('hexfile2', type=argparse.FileType('r'), help="hexfile 2") -p.add_argument('rhexfile', type=argparse.FileType('w'), help="resulting hexfile") - - -def main(args): - if args.command == 'info': - hexfile = HexFile() - hexfile.load(args.hexfile) - print(hexfile) - for region in hexfile.regions: - print(region) - elif args.command == 'new': - hf = HexFile() - data = args.datafile.read() - hf.addRegion(args.address, data) - hf.save(args.hexfile) - elif args.command == 'merge': - hf = HexFile() - hf.load(args.hexfile1) - hf2 = HexFile() - hf2.load(args.hexfile2) - hf.merge(hf2) - hf.save(args.rhexfile) - else: - raise NotImplementedError() - -if __name__ == '__main__': - args = parser.parse_args() - if not args.command: - parser.print_usage() - sys.exit(1) - main(args) diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/__init__.py --- a/python/utils/__init__.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - -from .hexfile import HexFile, HexFileException - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/adi.py --- a/python/utils/adi.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ - -# Implementation of the ADI (ARM Debug Interface) v5 interface. - -COMPONENT_CLASSES = {0x1: 'ROM table'} - -class Adi: - def __init__(self, iface): - self.iface = iface - def r32(self, address): - return self.iface.read_debug32(address) - def w32(self, address, value): - self.iface.write_debug32(address, value) - def getId(self, offset): - print('reading id from {0:X}'.format(offset)) - pid4 = self.r32(offset + 0xFD0) - #print('pid4', pid4) - pid5 = self.r32(offset + 0xFD4) - pid6 = self.r32(offset + 0xFD8) - pid7 = self.r32(offset + 0xFDC) - pid0 = self.r32(offset + 0xFE0) - pid1 = self.r32(offset + 0xFE4) - pid2 = self.r32(offset + 0xFE8) - pid3 = self.r32(offset + 0xFEC) - cid0 = self.r32(offset + 0xFF0) - cid1 = self.r32(offset + 0xFF4) - cid2 = self.r32(offset + 0xFF8) - cid3 = self.r32(offset + 0xFFC) - pids = [pid0, pid1, pid2, pid3, pid4, pid5, pid6, pid7] - cids = [cid0, cid1, cid2, cid3] - print('cids:', [hex(x) for x in cids], 'pids', [hex(x) for x in pids]) - valid = cid0 == 0xD and (cid1 & 0xF) == 0x0 and cid2 == 0x5 and cid3 == 0xB1 - if valid: - component_class = cid1 >> 4 - else: - print('invalid class') - component_class = 0 - # TODO: use pids - return component_class, pids - - def parseRomTable(self, offset): - assert (offset & 0xFFF) == 0 - component_class, pid = self.getId(offset) - assert component_class == 1 - print('Component class:', COMPONENT_CLASSES[component_class]) - print('memory also on this bus:', self.r32(offset + 0xFCC)) - idx = 0 - entry = self.r32(offset + idx * 4) - while entry != 0: - #print('Entry: {0:X}'.format(entry)) - entryOffset = entry & 0xFFFFF000 - cls, pids = self.getId((offset + entryOffset) & 0xFFFFFFFF) - print('class:', cls) - if cls == 9: - print('Debug block found!') - - idx += 1 - entry = self.r32(offset + idx * 4) - - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/devices.py --- a/python/utils/devices.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -import sys -import usb - -# Global device list to which devices are registered. -devices = {} - -def registerDevice(chipId): - """ Decorator to register a device """ - def wrapper(dev): - devices[chipId] = dev - return dev - return wrapper - -# Global interface dictionary. -interfaces = {} - -def registerInterface(vid_pid): - def wrapper(iface): - interfaces[vid_pid] = iface - return iface - return wrapper - -def createInterfaces(): - """ Create a list of detected interfaces """ - ctx = usb.UsbContext() - - # Retrieve all usb devices: - devs = ctx.DeviceList - keys = interfaces.keys() - - # Filter function to filter only registered interfaces: - def filt(usbiface): - return (usbiface.VendorId, usbiface.ProductId) in keys - def buildInterface(usbiface): - key = (usbiface.VendorId, usbiface.ProductId) - iface = interfaces[key] - return iface(usbiface) - return [buildInterface(uif) for uif in filter(filt, devs)] - -class Device: - """ - Base class for a device possibly connected via an interface. - """ - def __init__(self, iface): - # Store the interface through which this device is connected: - assert isinstance(iface, Interface) - self.iface = iface - -class Interface: - """ - Generic interface class. Connected via Usb to a JTAG interface. - Possibly is connected with a certain chip. - """ - def createDevice(self): - """ Try to get the device connected to this interface """ - if self.ChipId in devices: - return devices[self.ChipId](self) - raise STLinkException('No device found!') - -class STLinkException(Exception): - """ Exception used for interfaces and devices """ - pass - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/hexfile.py --- a/python/utils/hexfile.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -import os -import struct -import binascii - -DATA = 0 -EOF = 1 -EXTLINADR = 4 - -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 = struct.unpack('>H', nums[1:3])[0] - typ = nums[3] - data = nums[4:-1] - return (address, typ, data) - -def makeHexLine(address, typ, data=bytes()): - bytecount = len(data) - nums = bytearray() - nums.append(bytecount) - nums.extend(struct.pack('>H', address)) - nums.append(typ) - nums.extend(data) - crc = sum(nums) - crc = ((~crc) + 1) & 0xFF - nums.append(crc) - line = ':' + binascii.hexlify(nums).decode('ascii') - return line - -def chunks(data, csize=16): - idx = 0 - while idx < len(data): - s = min(len(data) - idx, csize) - yield data[idx:idx+s] - idx += s - -def hexfields(f): - 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 ':' - yield parseHexLine(line) - - -class HexFile: - """ Represents an intel hexfile """ - def __init__(self): - self.regions = [] - self.startAddress = 0 - - def load(self, f): - endOfFile = False - ext = 0 - for address, typ, data in hexfields(f): - if endOfFile: - raise HexFileException('hexfile line after end of file record') - if typ == 0x0: # Data record - self.addRegion(address + ext, data) - elif typ == EXTLINADR: # Extended linear address record - ext = (struct.unpack('>H', data[0:2])[0]) << 16 - elif typ == EOF: # End of file record - if len(data) != 0: - raise HexFileException('end of file not empty') - endOfFile = True - elif typ == 0x5: # Start address record (where IP goes after loading) - self.startAddress = struct.unpack('>I', data[0:4])[0] - else: - raise HexFileException('record type {0} not implemented'.format(typ)) - - def __repr__(self): - size = sum(r.Size for r in self.regions) - return 'Hexfile containing {} bytes'.format(size) - - def dump(self, outf): - print(self,file=outf) - for r in self.regions: - print(r, file=outf) - - def __eq__(self, other): - regions = self.regions - oregions = other.regions - if len(regions) != len(oregions): - return False - return all(rs == ro for rs, ro in zip(regions, oregions)) - - def addRegion(self, address, data): - r = HexFileRegion(address, data) - self.regions.append(r) - self.check() - - def check(self): - self.regions.sort(key=lambda r: r.address) - change = True - while change and len(self.regions) > 1: - change = False - for r1, r2 in zip(self.regions[:-1], self.regions[1:]): - if r1.EndAddress == r2.address: - r1.addData(r2.data) - self.regions.remove(r2) - change = True - elif r1.EndAddress > r2.address: - raise HexFileException('Overlapping regions') - - def merge(self, other): - for r in other.regions: - self.addRegion(r.address, r.data) - - def save(self, f): - def emit(address, typ, data=bytes()): - print(makeHexLine(address, typ, data), file=f) - for r in self.regions: - ext = r.address & 0xFFFF0000 - emit(0, EXTLINADR, struct.pack('>H', ext >> 16)) - address = r.address - ext - for chunk in chunks(r.data): - if address >= 0x10000: - ext += 0x10000 - emit(0, EXTLINADR, struct.pack('>H', ext >> 16)) - address -= 0x10000 - emit(address, DATA, chunk) - address += len(chunk) - emit(0, EOF) - - -class HexFileRegion: - def __init__(self, address, data = bytes()): - self.address = address - self.data = data - - def __repr__(self): - return 'Region at 0x{:08X} of {} bytes'.format(self.address, len(self.data)) - - def __eq__(self, other): - return (self.address, self.data) == (other.address, other.data) - - def addData(self, d): - self.data = self.data + d - - @property - def Size(self): - return len(self.data) - - @property - def EndAddress(self): - return self.address + len(self.data) diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/iso9660.py --- a/python/utils/iso9660.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -#!/usr/bin/env python - -import argparse - -__doc__ = """ - ISO 9660 filesystem utility. -""" - - -class VolumeDescriptor: - @classmethod - def FromData(cls, d): - ty = d[0] - Id = d[1:6] - assert Id == 'CD001'.encode('ascii') - ver = d[6] - assert ver == 1 - cls = vol_desc_types[ty] - return cls(d) - - -vol_desc_types = {} -def vol_type(t): - def reg_func(cls): - vol_desc_types[t] = cls - return cls - return reg_func - - -@vol_type(0) -class BootRecordVolumeDescriptor(VolumeDescriptor): - def __init__(self, d): - boot_sys_id = d[7:39] - boot_id = d[39:71] - print(boot_sys_id) - print(boot_id) - - -@vol_type(1) -class PrimaryVolumeDescriptor(VolumeDescriptor): - def __init__(self, d): - sys_id = d[8:40] - vol_id = d[40:72] - print(sys_id) - print(vol_id) - - -@vol_type(255) -class VolumeDescriptorTerminator(VolumeDescriptor): - def __init__(self, d): - pass - - -class ISOfs: - def __init__(self): - self.vol_descriptors = [] - - def read(self, f): - # System area: - self.system_area = f.read(16 * 2048) - while True: - d = f.read(2048) - desc = VolumeDescriptor.FromData(d) - self.vol_descriptors.append(desc) - if type(desc) is VolumeDescriptorTerminator: - break - - def dump(self): - for vd in self.vol_descriptors: - print(vd) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('filename') - args = parser.parse_args() - fs = ISOfs() - with open(args.filename, 'rb') as f: - fs.read(f) - fs.dump() - - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/lsusb.py --- a/python/utils/lsusb.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -#!/usr/bin/python - -from usb import UsbContext - -# try to read usb.ids: -vids = {} -pids = {} -try: - with open('usb.ids', 'r', errors='ignore') as f: - vid = 0 - for l in f: - if l.startswith('#') or not l.strip(): - continue - if l.startswith('\t\t'): - print('iface:', l) - elif l.startswith('\t'): - print('product', l) - pid = int(l[1:5], 16) - print('product', hex(pid), l) - else: - print('vendor', l) - vid = int(l[0:4], 16) - print('vendor', hex(vid), l) - -except IOError as e: - print("Error loading usb id's: {0}".format(e)) - -context = UsbContext() -for d in context.DeviceList: - print(d) - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/st-flash.py --- a/python/utils/st-flash.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -#!/usr/bin/python - -import argparse, sys -import stlink, stm32 -import hexfile - -def hex2int(s): - if s.startswith('0x'): - s = s[2:] - return int(s, 16) - raise ValueError('Hexadecimal value must begin with 0x') - -parser = argparse.ArgumentParser( - description='ST-link flash utility by Windel Bouwman') -subparsers = parser.add_subparsers(title='commands', - description='possible commands', dest='command') - -readparser = subparsers.add_parser('read', help='read flash contents') -readparser.add_argument('filename', type=argparse.FileType('wb', 0)) -readparser.add_argument('address', type=hex2int) -readparser.add_argument('size', type=hex2int) - -writeparser = subparsers.add_parser('write', help='write flash contents') -writeparser.add_argument('filename', type=argparse.FileType('rb')) -writeparser.add_argument('address', type=hex2int) - -hexwriteparser = subparsers.add_parser('hexwrite', help='write hexfile to flash') -hexwriteparser.add_argument('hexfile', type=argparse.FileType('r')) - -verifyparser = subparsers.add_parser('verify', help='verify flash contents') -verifyparser.add_argument('filename', type=argparse.FileType('rb')) -verifyparser.add_argument('address', type=hex2int) - -eraseparser = subparsers.add_parser('erase', help='erase flash contents') - -args = parser.parse_args() -if not args.command: - parser.print_usage() - sys.exit(1) - -# In any command case, open a device: -stl = stlink.STLink2() -stl.open() - -# Enter the right mode: -if stl.CurrentMode == stlink.DFU_MODE: - stl.exitDfuMode() - -if stl.CurrentMode != stlink.DEBUG_MODE: - stl.enterSwdMode() - -if stl.ChipId != 0x10016413: - print('Only working on stm32f4discovery board for now.') - sys.exit(2) - -# Retrieve the connected device, if any: -dev = stl.createDevice() - -if args.command == 'read': - dev_content = dev.readFlash(args.address, args.size) - args.filename.write(dev_content) -elif args.command == 'write': - content = args.filename.read() - dev.writeFlash(args.address, content) -elif args.command == 'hexwrite': - hf = hexfile.HexFile() - hf.load(args.hexfile) - for region in hf.regions: - print('flashing {}'.format(region)) - dev.writeFlash(region.address, region.data) -elif args.command == 'verify': - content = args.filename.read() - dev.verifyFlash(args.address, content) -elif args.command == 'erase': - dev.eraseFlash() -else: - print('unknown command', args.command) - -stl.reset() -stl.run() -stl.exitDebugMode() - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/stlink.py --- a/python/utils/stlink.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,367 +0,0 @@ -import struct, time -from usb import UsbContext, UsbDevice -from devices import Interface, STLinkException, registerInterface -import adi - -""" - More or less copied from: - https://github.com/texane/stlink - Tracing from: - https://github.com/obe1line/stlink-trace - -""" -ST_VID, STLINK2_PID = 0x0483, 0x3748 - -def checkDevice(device): - return device.VendorId == ST_VID and device.ProductId == STLINK2_PID - -DFU_MODE, MASS_MODE, DEBUG_MODE = 0, 1, 2 - -CORE_RUNNING = 0x80 -CORE_HALTED = 0x81 - -# Commands: -GET_VERSION = 0xf1 -DEBUG_COMMAND = 0xf2 -DFU_COMMAND = 0xf3 -GET_CURRENT_MODE = 0xf5 - -# dfu commands: -DFU_EXIT = 0x7 - -# debug commands: -DEBUG_ENTER = 0x20 -DEBUG_EXIT = 0x21 -DEBUG_ENTER_SWD = 0xa3 -DEBUG_GETSTATUS = 0x01 -DEBUG_FORCEDEBUG = 0x02 -DEBUG_RESETSYS = 0x03 -DEBUG_READALLREGS = 0x04 -DEBUG_READREG = 0x5 -DEBUG_WRITEREG = 0x6 -DEBUG_READMEM_32BIT = 0x7 -DEBUG_WRITEMEM_32BIT = 0x8 -DEBUG_RUNCORE = 0x9 -DEBUG_STEPCORE = 0xa - -JTAG_WRITEDEBUG_32BIT = 0x35 -JTAG_READDEBUG_32BIT = 0x36 -TRACE_GET_BYTE_COUNT = 0x42 - -# cortex M3 -CM3_REG_CPUID = 0xE000ED00 - -@registerInterface((ST_VID, STLINK2_PID)) -class STLink2(Interface): - """ STlink2 interface implementation. """ - def __init__(self, stlink2=None): - self.devHandle = None - if not stlink2: - context = UsbContext() - stlink2s = list(filter(checkDevice, context.DeviceList)) - if not stlink2s: - raise STLinkException('Could not find an ST link 2 interface') - if len(stlink2s) > 1: - print('More then one stlink2 found, picking first one') - stlink2 = stlink2s[0] - assert isinstance(stlink2, UsbDevice) # Nifty type checking - assert checkDevice(stlink2) - self.stlink2 = stlink2 - def __del__(self): - if self.IsOpen: - if self.CurrentMode == DEBUG_MODE: - self.exitDebugMode() - self.close() - def __str__(self): - if self.IsOpen: - return 'STlink2 device version {0}'.format(self.Version) - else: - return 'STlink2 device' - def open(self): - if self.IsOpen: - return - self.devHandle = self.stlink2.open() - if self.devHandle.Configuration != 1: - self.devHandle.Configuration = 1 - self.devHandle.claimInterface(0) - - # First initialization: - if self.CurrentMode == DFU_MODE: - self.exitDfuMode() - if self.CurrentMode != DEBUG_MODE: - self.enterSwdMode() - #self.reset() - def close(self): - if self.IsOpen: - self.devHandle.close() - self.devHandle = None - @property - def IsOpen(self): - return self.devHandle != None - # modes: - def getCurrentMode(self): - cmd = bytearray(16) - cmd[0] = GET_CURRENT_MODE - reply = self.send_recv(cmd, 2) # Expect 2 bytes back - return reply[0] - CurrentMode = property(getCurrentMode) - @property - def CurrentModeString(self): - modes = {DFU_MODE: 'dfu', MASS_MODE: 'massmode', DEBUG_MODE:'debug'} - return modes[self.CurrentMode] - def exitDfuMode(self): - cmd = bytearray(16) - cmd[0:2] = DFU_COMMAND, DFU_EXIT - self.send_recv(cmd) - def enterSwdMode(self): - cmd = bytearray(16) - cmd[0:3] = DEBUG_COMMAND, DEBUG_ENTER, DEBUG_ENTER_SWD - self.send_recv(cmd) - def exitDebugMode(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, DEBUG_EXIT - self.send_recv(cmd) - - def getVersion(self): - cmd = bytearray(16) - cmd[0] = GET_VERSION - data = self.send_recv(cmd, 6) # Expect 6 bytes back - # Parse 6 bytes into various versions: - b0, b1, b2, b3, b4, b5 = data - stlink_v = b0 >> 4 - jtag_v = ((b0 & 0xf) << 2) | (b1 >> 6) - swim_v = b1 & 0x3f - vid = (b3 << 8) | b2 - pid = (b5 << 8) | b4 - return 'stlink={0} jtag={1} swim={2} vid:pid={3:04X}:{4:04X}'.format(\ - stlink_v, jtag_v, swim_v, vid, pid) - Version = property(getVersion) - - @property - def ChipId(self): - return self.read_debug32(0xE0042000) - @property - def CpuId(self): - u32 = self.read_debug32(CM3_REG_CPUID) - implementer_id = (u32 >> 24) & 0x7f - variant = (u32 >> 20) & 0xf - part = (u32 >> 4) & 0xfff - revision = u32 & 0xf - return implementer_id, variant, part, revision - def getStatus(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, DEBUG_GETSTATUS - reply = self.send_recv(cmd, 2) - return reply[0] - Status = property(getStatus) - @property - def StatusString(self): - s = self.Status - statii = {CORE_RUNNING: 'CORE RUNNING', CORE_HALTED: 'CORE HALTED'} - if s in statii: - return statii[s] - return 'Unknown status' - - def reset(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, DEBUG_RESETSYS - self.send_recv(cmd, 2) - - # debug commands: - def step(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, DEBUG_STEPCORE - self.send_recv(cmd, 2) - def run(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, DEBUG_RUNCORE - self.send_recv(cmd, 2) - def halt(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, DEBUG_FORCEDEBUG - self.send_recv(cmd, 2) - - # Tracing: - def traceEnable(self): - self.write_debug32(0xE000EDF0, 0xA05F0003) - - # Enable TRCENA: - DEMCR = 0xE000EDFC - v = self.read_debug32(DEMCR) - v |= (1 << 24) - self.write_debug32(DEMCR, v) - - # ?? Enable write?? - self.write_debug32(0xE0002000, 0x2) # - - # DBGMCU_CR: - self.write_debug32(0xE0042004, 0x27) # Enable trace in async mode - - # TPIU config: - self.write_debug32(0xE0040004, 0x00000001) # current port size register --> 1 == port size = 1 - self.write_debug32(0xE0040010, 0x23) # random clock divider?? - self.write_debug32(0xE00400F0, 0x2) # selected pin protocol (2 == NRZ) - self.write_debug32(0xE0040304, 0x100) # continuous formatting - - # ITM config: - self.write_debug32(0xE0000FB0, 0xC5ACCE55) # Unlock write access to ITM - self.write_debug32(0xE0000F80, 0x00010005) # ITM Enable, sync enable, ATB=1 - self.write_debug32(0xE0000E00, 0xFFFFFFFF) # Enable all trace ports in ITM - self.write_debug32(0xE0000E40, 0x0000000F) # Set privilege mask for all 32 ports. - def writePort0(self, v32): - self.write_debug32(0xE0000000, v32) - def getTraceByteCount(self): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, 0x42 - reply = self.send_recv(cmd, 2) - return struct.unpack(' 0: - td = self.recv_ep3(bsize) - print(td) - else: - print('no trace data') - - # Helper 1 functions: - def write_debug32(self, address, value): - cmd = bytearray(16) - cmd[0:2] = DEBUG_COMMAND, JTAG_WRITEDEBUG_32BIT - cmd[2:10] = struct.pack(' 0: - return self.devHandle.bulkRead(1, rxsize) # read from endpoint 1 - def recv_ep3(self, rxsize): - return self.devHandle.bulkRead(3, rxsize) - -if __name__ == '__main__': - # Test program - sl = STLink2() - sl.open() - sl.reset() - print('version:', sl.Version) - print('mode before doing anything:', sl.CurrentModeString) - if sl.CurrentMode == DFU_MODE: - sl.exitDfuMode() - sl.enterSwdMode() - print('mode after entering swd mode:', sl.CurrentModeString) - - i = sl.ChipId - print('chip id: 0x{0:X}'.format(i)) - print('cpu: {0}'.format(sl.CpuId)) - - print('status: {0}'.format(sl.StatusString)) - - # test registers: - sl.write_reg(0, 0xdeadbeef) - sl.write_reg(1, 0xcafebabe) - sl.write_reg(2, 0xc0ffee) - sl.write_reg(3, 0x1337) - sl.write_reg(5, 0x1332) - sl.write_reg(6, 0x12345) - assert sl.read_reg(3) == 0x1337 - assert sl.read_reg(5) == 0x1332 - assert sl.read_reg(6) == 0x12345 - regs = sl.read_all_regs() - for i in range(len(regs)): - print('R{0}=0x{1:X}'.format(i, regs[i])) - - print('tracing') - sl.traceEnable() - sl.run() - sl.writePort0(0x1337) # For test - time.sleep(0.1) - td = sl.readTraceData() - print('trace data:', td) - - # Test CoreSight registers: - idr4 = sl.read_debug32(0xE0041fd0) - print('idr4 =', idr4) - - print('== ADI ==') - a = adi.Adi(sl) - a.parseRomTable(0xE00FF000) # why is rom table at 0xE00FF000? - print('== ADI ==') - - # Detect ROM table: - id4 = sl.read_debug32(0xE00FFFD0) - id5 = sl.read_debug32(0xE00FFFD4) - id6 = sl.read_debug32(0xE00FFFD8) - id7 = sl.read_debug32(0xE00FFFDC) - id0 = sl.read_debug32(0xE00FFFE0) - id1 = sl.read_debug32(0xE00FFFE4) - id2 = sl.read_debug32(0xE00FFFE8) - id3 = sl.read_debug32(0xE00FFFEC) - pIDs = [id0, id1, id2, id3, id4, id5, id6, id7] - print(pIDs) - - print('reading from 0xE00FF000') - scs = sl.read_debug32(0xE00FF000) - print('scs {0:08X}'.format(scs)) - dwt = sl.read_debug32(0xE00FF004) - print('dwt {0:08X}'.format(dwt)) - fpb = sl.read_debug32(0xE00FF008) - print('fpb {0:08X}'.format(fpb)) - itm = sl.read_debug32(0xE00FF00C) - print('itm {0:08X}'.format(itm)) - tpiu = sl.read_debug32(0xE00FF010) - print('tpiu {0:08X}'.format(tpiu)) - etm = sl.read_debug32(0xE00FF014) - print('etm {0:08X}'.format(etm)) - assert sl.read_debug32(0xE00FF018) == 0x0 # end marker - - devid = sl.read_debug32(0xE0040FC8) - print('TPIU_DEVID: {0:X}'.format(devid)) - devtype = sl.read_debug32(0xE0040FCC) - print('TPIU_TYPEID: {0:X}'.format(devtype)) - - sl.exitDebugMode() - print('mode at end:', sl.CurrentModeString) - - sl.close() - print('Test succes!') - diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/stm32.py --- a/python/utils/stm32.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,264 +0,0 @@ -import time -import logging -from devices import Device, registerDevice, STLinkException, Interface -import stlink - -# F4 specifics: -STM32_FLASH_BASE = 0x08000000 -STM32_SRAM_BASE = 0x20000000 - -# flash registers: -FLASH_F4_REGS_ADDR = 0x40023c00 -FLASH_F4_KEYR = FLASH_F4_REGS_ADDR + 0x04 -FLASH_F4_SR = FLASH_F4_REGS_ADDR + 0x0c -FLASH_F4_CR = FLASH_F4_REGS_ADDR + 0x10 - -FLASH_F4_CR_START = 16 -FLASH_F4_CR_LOCK = 31 -FLASH_CR_PG = 0 -FLASH_F4_CR_SER = 1 -FLASH_CR_MER = 2 -FLASH_F4_CR_SNB = 3 -FLASH_F4_CR_SNB_MASK = 0x38 -FLASH_F4_SR_BSY = 16 - -class Stm32F4(Device): - """ - Implementation of the specifics of the STM32F4xx device series. - """ - def __init__(self, iface): - super().__init__(iface) - self.logger = logging.getLogger('stm32') - - def __str__(self): - return 'STM32F4 device size=0x{1:X} id=0x{0:X}'.format(\ - self.UID, self.FlashSize) - - def calculate_F4_sector(self, address): - sectorstarts = [] - a = STM32_FLASH_BASE - for sectorsize in self.sectorsizes: - sectorstarts.append(a) - a += sectorsize - # linear search: - sec = 0 - while sec < len(self.sectorsizes) and address >= sectorstarts[sec]: - sec += 1 - sec -= 1 # one back. - return sec, self.sectorsizes[sec] - - def calcSectors(self, address, size): - off = 0 - sectors = [] - while off < size: - sectornum, sectorsize = self.calculate_F4_sector(address + off) - sectors.append((sectornum, sectorsize)) - off += sectorsize - return sectors - - # Device registers: - @property - def UID(self): - uid_base = 0x1FFF7A10 - uid1 = self.iface.read_debug32(uid_base) - uid2 = self.iface.read_debug32(uid_base + 0x4) - uid3 = self.iface.read_debug32(uid_base + 0x8) - return (uid3 << 64) | (uid2 << 32) | uid1 - - @property - def FlashSize(self): - f_id = self.iface.read_debug32(0x1FFF7A22) - f_id = f_id >> 16 - return f_id * 1024 - - @property - def Running(self): - return self.iface.Status == stlink.CORE_RUNNING - - # flashing commands: - def writeFlash(self, address, content): - flashsize = self.FlashSize - pagesize = min(self.sectorsizes) - - # Check address range: - if address < STM32_FLASH_BASE: - raise STLinkException('Flashing below flash start') - if address + len(content) > STM32_FLASH_BASE + flashsize: - raise STLinkException('Flashing above flash size') - if address & 1 == 1: - raise STLinkException('Unaligned flash') - if len(content) & 1 == 1: - self.logger.warning('unaligned length, padding with zero') - content += bytes([0]) - if address & (pagesize - 1) != 0: - raise STLinkException('Address not aligned with pagesize') - # erase required space - sectors = self.calcSectors(address, len(content)) - self.logger.info('erasing {0} sectors'.format(len(sectors))) - for sector, secsize in sectors: - self.logger.info('erasing sector {0} of {1} bytes'.format(sector, secsize)) - self.eraseFlashSector(sector) - # program pages: - self.unlockFlashIf() - self.writeFlashCrPsiz(2) # writes are 32 bits aligned - self.setFlashCrPg() - self.logger.info('writing {0} bytes'.format(len(content))) - offset = 0 - t1 = time.time() - while offset < len(content): - size = len(content) - offset - if size > 0x8000: - size = 0x8000 - chunk = content[offset:offset + size] - while len(chunk) % 4 != 0: - chunk = chunk + bytes([0]) - # Use simple mem32 writes: - self.iface.write_mem32(address + offset, chunk) - offset += size - self.logger.info('{}%'.format(offset*100/len(content))) - self.logger.info('Done!') - self.lockFlash() - # verfify program: - self.verifyFlash(address, content) - - def eraseFlashSector(self, sector): - self.waitFlashBusy() - self.unlockFlashIf() - self.writeFlashCrSnb(sector) - self.setFlashCrStart() - self.waitFlashBusy() - self.lockFlash() - - def eraseFlash(self): - self.waitFlashBusy() - self.unlockFlashIf() - self.setFlashCrMer() - self.setFlashCrStart() - self.waitFlashBusy() - self.clearFlashCrMer() - self.lockFlash() - - def verifyFlash(self, address, content): - device_content = self.readFlash(address, len(content)) - ok = content == device_content - if ok: - self.logger.info('Verify: OK') - else: - self.logger.warning('Verify: Mismatch') - - def readFlash(self, address, size): - self.logger.info('Reading {1} bytes from 0x{0:X}'.format(address, size)) - offset = 0 - tmp_size = 0x1800 - image = bytes() - while offset < size: - # Correct for last page: - if offset + tmp_size > size: - tmp_size = size - offset - - # align size to 4 bytes: - aligned_size = tmp_size - while aligned_size % 4 != 0: - aligned_size += 1 - - mem = self.iface.read_mem32(address + offset, aligned_size) - image += mem[:tmp_size] - - # indicate progress: - self.logger.info('{}%'.format(100*len(image) / size)) - - # increase for next piece: - offset += tmp_size - assert size == len(image) - self.logger.info('Done!') - return image - - def waitFlashBusy(self): - """ block until flash operation completes. """ - while self.isFlashBusy(): - time.sleep(0.01) - - def isFlashLocked(self): - mask = 1 << FLASH_F4_CR_LOCK - return self.Cr & mask == mask - - def unlockFlashIf(self): - FLASH_KEY1, FLASH_KEY2 = 0x45670123, 0xcdef89ab - if self.isFlashLocked(): - self.iface.write_debug32(FLASH_F4_KEYR, FLASH_KEY1) - self.iface.write_debug32(FLASH_F4_KEYR, FLASH_KEY2) - if self.isFlashLocked(): - raise STLinkException('Failed to unlock') - - def lockFlash(self): - self.Cr = self.Cr | (1 << FLASH_F4_CR_LOCK) - - def readFlashSr(self): - return self.iface.read_debug32(FLASH_F4_SR) - - def readFlashCr(self): - return self.iface.read_debug32(FLASH_F4_CR) - - def writeFlashCr(self, x): - self.iface.write_debug32(FLASH_F4_CR, x) - - Cr = property(readFlashCr, writeFlashCr) - - def writeFlashCrSnb(self, sector): - x = self.Cr - x &= ~FLASH_F4_CR_SNB_MASK - x |= sector << FLASH_F4_CR_SNB - x |= 1 << FLASH_F4_CR_SER - self.Cr = x - - def setFlashCrMer(self): - self.Cr = self.Cr | (1 << FLASH_CR_MER) - - def setFlashCrPg(self): - self.Cr = self.Cr | (1 << FLASH_CR_PG) - - def writeFlashCrPsiz(self, n): - x = self.Cr - x &= (0x3 << 8) - x |= n << 8 - self.Cr = x - - def clearFlashCrMer(self): - x = self.Cr - x &= ~(1 << FLASH_CR_MER) - self.Cr = x - - def setFlashCrStart(self): - self.Cr = self.Cr | (1 << FLASH_F4_CR_START) - - def isFlashBusy(self): - mask = 1 << FLASH_F4_SR_BSY - sr = self.readFlashSr() - # Check for error bits: - errorbits = {} - errorbits[7] = 'Programming sequence error' - errorbits[6] = 'Programming parallelism error' - errorbits[5] = 'Programming alignment error' - errorbits[4] = 'Write protection error' - errorbits[1] = 'Operation error' - #errorbits[0] = 'End of operation' - for bit, msg in errorbits.items(): - if sr & (1 << bit) == (1 << bit): - raise STLinkException(msg) - return sr & mask == mask - - -@registerDevice(0x10016413) -class Stm32F40x(Stm32F4): - """ STM32F40x and STM32F41x device series """ - def __init__(self, iface): - super().__init__(iface) - # Assert the proper size for this device: - assert self.FlashSize == 0x100000 - """ - from 0x8000000 to 0x80FFFFF - 4 sectors of 0x4000 (16 kB) - 1 sector of 0x10000 (64 kB) - 7 of 0x20000 (128 kB) - """ - self.sectorsizes = [0x4000] * 4 + [0x10000] + [0x20000] * 7 diff -r 0374c65cb437 -r 994c00d55fd5 python/utils/usb.py --- a/python/utils/usb.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -from ctypes import Structure, POINTER, CDLL, CFUNCTYPE -from ctypes import c_uint16, c_uint8, c_int, c_uint, c_ssize_t, c_void_p -from ctypes import byref, create_string_buffer - -# libusb wrapper: -libusb = CDLL('libusb-1.0.so') - -# helper: -def buildfunc(name, argtypes, restype=c_int): - f = getattr(libusb, name) - f.argtypes = argtypes - f.restype = restype - globals()[name] = f - return f -def enum(**enums): - reverse = dict((value, key) for key, value in enums.items()) - enums['reverse_mapping'] = reverse - return type('enum', (), enums) - -# enums -libusb_class_code = enum(PER_INTERFACE=0, AUDIO=1, COMM=2, HID=3, \ - PHYSICAL=5, PRINTER=7, PTP=6, MASS_STORAGE=8, HUB=9, \ - DATA=10, SMART_CARD=0xb, CONTENT_SECURITY=0xd, VIDEO=0xe, \ - PERSONAL_HEALTHCARE=0xf, DIAGNOSTIC_DEVICE=0xdc, WIRELESS=0xe,\ - APPLICATION=0xfe, VENDOR_SPEC=0xff) -libusb_speed = enum(UNKNOWN=0, LOW=1, FULL=2, HIGH=3, SUPER=4) -libusb_error = enum(SUCCES=0, ERROR_IO=-1, ERROR_INVALID_PARAM=-2, \ - ERROR_ACCESS=-3, ERROR_NO_DEVICE=-4, ERROR_NOT_FOUND=-5, \ - ERROR_BUSY=-6, ERROR_TIMEOUT=-7, ERROR_OVERFLOW=-8, \ - ERROR_PIPE=-9, ERROR_INTERRUPTED=-10, ERROR_NO_MEM=-11, \ - ERROR_NOT_SUPPORTED=-12, ERROR_OTHER=-99) -libusb_transfer_status = enum(\ - COMPLETED=0, ERROR=1, TIMED_OUT=2, \ - CANCELLED=3, STALL=4, NO_DEVICE=5, OVERFLOW=6) - -# types -c_int_p = POINTER(c_int) -class libusb_context(Structure): - pass -libusb_context_p = POINTER(libusb_context) -libusb_context_p_p = POINTER(libusb_context_p) - -class libusb_device(Structure): - pass -libusb_device_p = POINTER(libusb_device) -libusb_device_p_p = POINTER(libusb_device_p) -libusb_device_p_p_p = POINTER(libusb_device_p_p) - -class libusb_device_handle(Structure): - pass -libusb_device_handle_p = POINTER(libusb_device_handle) -libusb_device_handle_p_p = POINTER(libusb_device_handle_p) - -class libusb_device_descriptor(Structure): - _fields_ = [ - ('bLength', c_uint8), - ('bDescriptorType', c_uint8), - ('bcdUSB', c_uint16), - ('bDeviceClass', c_uint8), - ('bDeviceSubClass', c_uint8), - ('bDeviceProtocol', c_uint8), - ('bMaxPacketSize0', c_uint8), - ('idVendor', c_uint16), - ('idProduct', c_uint16), - ('bcdDevice', c_uint16), - ('iManufacturer', c_uint8), - ('iProduct', c_uint8), - ('iSerialNumber', c_uint8), - ('iNumConfigurations', c_uint8) - ] -libusb_device_descriptor_p = POINTER(libusb_device_descriptor) - -""" -class libusb_transfer(Structure): - pass -libusb_transfer_p = POINTER(libusb_transfer) -libusb_transfer_cb_fn = CFUNCTYPE(None, libusb_transfer_p) -libusb_transfer._fields_ = [ - ('dev_handle', libusb_device_handle_p), - ('flags', c_uint8), - ('endpoint', c_uchar), - ('type', c_uchar), - ('timeout', c_uint), - ('status', c_int), # enum libusb_transfer_status - ('length', c_int), - ('actual_length', c_int), - ('callback', libusb_transfer_cb_fn), - ('userdata', c_void_p), - ('buffer', c_void_p), - ('num_iso_packets', c_int), - ('iso_packet_desc', libusb_iso_packet_descriptor) - ] -""" -# functions -buildfunc('libusb_init', [libusb_context_p_p], c_int) - -buildfunc('libusb_get_device_list', \ - [libusb_context_p, libusb_device_p_p_p], c_ssize_t) -buildfunc('libusb_free_device_list', [libusb_device_p_p, c_int], None) -buildfunc('libusb_get_bus_number', [libusb_device_p], c_uint8) -buildfunc('libusb_get_device_address', [libusb_device_p], c_uint8) -buildfunc('libusb_get_device_speed', [libusb_device_p]) -buildfunc('libusb_unref_device', [libusb_device_p], None) -buildfunc('libusb_open', [libusb_device_p, libusb_device_handle_p_p]) -buildfunc('libusb_close', [libusb_device_handle_p], None) -buildfunc('libusb_get_configuration',[libusb_device_handle_p,POINTER(c_int)]) -buildfunc('libusb_set_configuration', [libusb_device_handle_p, c_int]) -buildfunc('libusb_claim_interface', [libusb_device_handle_p, c_int]) - -buildfunc('libusb_get_device_descriptor',\ - [libusb_device_p, libusb_device_descriptor_p]) - -# synchronous functions: -buildfunc('libusb_bulk_transfer', [libusb_device_handle_p, c_uint8, \ - c_void_p, c_int, c_int_p, c_uint]) - -# pythonic API: - -class UsbError(Exception): - def __init__(self, msg, errorcode): - if errorcode in libusb_error.reverse_mapping: - errorcode = libusb_error.reverse_mapping[errorcode] - msg = msg + 'Error code: {0}'.format(errorcode) - super().__init__(msg) - -class UsbContext(object): - """ A usb context in case of multiple use """ - def __init__(self): - self.context_p = libusb_context_p() - r = libusb_init(byref(self.context_p)) - if r != 0: - raise UsbError('libusb_init error!', r) - def getDeviceList(self): - devlist = libusb_device_p_p() - count = libusb_get_device_list(self.context_p, byref(devlist)) - if count < 0: - raise UsbError('Error getting device list', count) - l = [UsbDevice(self, device_p.contents) for device_p in devlist[0:count]] - libusb_free_device_list(devlist, 0) - return l - DeviceList = property(getDeviceList) - -class UsbDevice: - """ A detected usb device """ - def __init__(self, context, device_p): - self.context = context - self.dev_p = device_p - def __del__(self): - libusb_unref_device(self.dev_p) - def getBusNumber(self): - return libusb_get_bus_number(self.dev_p) - BusNumber = property(getBusNumber) - def getDeviceAddress(self): - return libusb_get_device_address(self.dev_p) - DeviceAddress = property(getDeviceAddress) - def getSpeed(self): - s = libusb_get_device_speed(self.dev_p) - if s in libusb_speed.reverse_mapping: - s = libusb_speed.reverse_mapping[s] - return s - Speed = property(getSpeed) - def getDescriptor(self): - descriptor = libusb_device_descriptor() - r = libusb_get_device_descriptor(self.dev_p, byref(descriptor)) - if r != 0: - raise UsbError('Error getting descriptor', r) - return descriptor - Descriptor = property(getDescriptor) - VendorId = property(lambda self: self.Descriptor.idVendor) - ProductId = property(lambda self: self.Descriptor.idProduct) - NumConfigurations = property(lambda self: self.Descriptor.bNumConfigurations) - def open(self): - """ Opens this device and returns a handle """ - handle_p = libusb_device_handle_p() - r = libusb_open(self.dev_p, byref(handle_p)) - if r != 0: - raise UsbError('error opening device', r) - return UsbDeviceHandle(self, handle_p) - def __repr__(self): - r2 = 'Usb device: bus {0} address {1} {2:04X}:{3:04X} speed {4}' \ - .format( \ - self.BusNumber, self.DeviceAddress, self.VendorId, \ - self.ProductId, self.Speed) - return r2 - -USB_ENDPOINT_DIR_MASK = 0x80 -USB_ENDPOINT_IN = 0x80 -USB_ENDPOINT_OUT = 0x0 - -class UsbDeviceHandle: - """ Handle to a detected usb device """ - def __init__(self, device, handle_p): - self.device = device - self.handle_p = handle_p - def __del__(self): - self.close() - def close(self): - if self.handle_p: - libusb_close(self.handle_p) - self.handle_p = None - def getConfiguration(self): - config = c_int() - r = libusb_get_configuration(self.handle_p, byref(config)) - if r != 0: raise UsbError('Error getting configuration', r) - return config.value - def setConfiguration(self, config): - r = libusb_set_configuration(self.handle_p, config) - if r != 0: raise UsbError('Error setting configuration', r) - Configuration = property(getConfiguration, setConfiguration) - def claimInterface(self, interface_number): - r = libusb_claim_interface(self.handle_p, interface_number) - if r != 0: raise UsbError('Error claiming interface', r) - def bulkWrite(self, endpoint, data, timeout=0): - """ Synchronous bulk write """ - assert type(data) is bytes - # assure the endpoint indicates the correct: - endpoint = (endpoint & (~USB_ENDPOINT_DIR_MASK)) | USB_ENDPOINT_OUT - buf = create_string_buffer(data) - transferred = c_int() - r = libusb_bulk_transfer(self.handle_p, endpoint, buf, len(data), \ - byref(transferred), timeout) - if r != 0: - raise UsbError('Bulk write failed', r) - if transferred.value != len(data): - raise UsbError('Not all {0} transferred {1}'.format(len(data), \ - transferred.value)) - def bulkRead(self, endpoint, numbytes, timeout=0): - """ Synchronous bulk read """ - # assure the endpoint indicates the correct: - endpoint = (endpoint & (~USB_ENDPOINT_DIR_MASK)) | USB_ENDPOINT_IN - buf = create_string_buffer(numbytes) - transferred = c_int() - r = libusb_bulk_transfer(self.handle_p, endpoint, buf, numbytes, \ - byref(transferred), timeout) - if r != 0: - raise UsbError('Bulk read failed', r) - if transferred.value != numbytes: - raise UsbError('Not all {0} transferred {1}'.format(numbytes, \ - transferred.value)) - data = buf.raw[0:numbytes] - return data - -class UsbTransfer: - def __init__(self): - libusb_alloc_transfer(0) diff -r 0374c65cb437 -r 994c00d55fd5 test/m3_bare/build.xml --- a/test/m3_bare/build.xml Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ - - - - - - - - - - diff -r 0374c65cb437 -r 994c00d55fd5 test/m3_bare/startup_m3.asm --- a/test/m3_bare/startup_m3.asm Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - - -DCD 0x20000678 ; Setup stack pointer -DCD 0x00000009 ; Reset vector, jump to address 8 -B hello_main ; Branch to main (this is actually in the interrupt vector) - diff -r 0374c65cb437 -r 994c00d55fd5 test/test_burm.py --- a/test/test_burm.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -import unittest -import io -import argparse - -from tree import Tree -import pyburg - - -class testBURG(unittest.TestCase): - def testSample4(self): - """ Test sample4 burg system """ - # Generate matcher from spec: - buf = io.StringIO() - args = argparse.Namespace(source=open('sample4.brg'), output=buf) - pyburg.main(args) - - # Execute generated script into global scope: - exec(buf.getvalue(), globals()) - - # Sample tree: - t = Tree('ASGNI', - Tree('ADDRLP'), - Tree('ADDI', - Tree('CVCI', Tree('INDIRC', Tree('ADDRLP'))), - Tree('CNSTI') - ) - ) - - # Subclass generated matcher: - class MyMatcher(Matcher): - def __init__(self): - super().__init__() - self.trace = [] - - def tr(self, r): - self.trace.append(r) - - # Match tree: - mm = MyMatcher() - mm.gen(t) - self.assertSequenceEqual([8,8,4,11,9,3,1], mm.trace) - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 test/testbintools.py --- a/test/testbintools.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -import unittest -import sys -import io -from ppci.target.arm.token import ArmToken -from ppci.linker import Linker -from ppci.objectfile import ObjectFile, serialize, deserialize, load_object -from ppci import CompilerError -from ppci.tasks import TaskRunner, TaskError -from ppci.buildtasks import EmptyTask -from ppci.buildfunctions import link -from ppci import layout - - -class TaskTestCase(unittest.TestCase): - @unittest.skip('api change') - def testCircular(self): - t1 = EmptyTask('t1') - t2 = EmptyTask('t2') - t1.add_dependency(t2) - with self.assertRaises(TaskError): - t2.add_dependency(t1) - - @unittest.skip('api change') - def testCircularDeeper(self): - t1 = EmptyTask('t1') - t2 = EmptyTask('t2') - t3 = EmptyTask('t3') - t1.add_dependency(t2) - t2.add_dependency(t3) - with self.assertRaises(TaskError): - t3.add_dependency(t1) - - @unittest.skip('api change') - def testSort(self): - t1 = EmptyTask('t1') - t2 = EmptyTask('t2') - runner = TaskRunner() - t1.add_dependency(t2) - runner.add_task(t1) - runner.add_task(t2) - runner.run_tasks() - - -class TokenTestCase(unittest.TestCase): - def testSetBits(self): - at = ArmToken() - at[2:4] = 0b11 - self.assertEqual(0xc, at.bit_value) - - def testSetBits(self): - at = ArmToken() - at[4:8] = 0b1100 - self.assertEqual(0xc0, at.bit_value) - - -class LinkerTestCase(unittest.TestCase): - def testUndefinedReference(self): - o1 = ObjectFile() - o1.get_section('.text') - o1.add_relocation('undefined_sym', 0, 'rel8', '.text') - o2 = ObjectFile() - with self.assertRaises(CompilerError): - o3 = link([o1, o2], layout.Layout(), 'arm') - - def testDuplicateSymbol(self): - o1 = ObjectFile() - o1.get_section('.text') - o1.add_symbol('a', 0, '.text') - o2 = ObjectFile() - o2.get_section('.text') - o2.add_symbol('a', 0, '.text') - with self.assertRaises(CompilerError): - o3 = link([o1, o2], layout.Layout(), 'arm') - - def testRel8Relocation(self): - o1 = ObjectFile() - o1.get_section('.text').add_data(bytes([0]*100)) - o1.add_relocation('a', 0, 'rel8', '.text') - o2 = ObjectFile() - o2.get_section('.text').add_data(bytes([0]*100)) - o2.add_symbol('a', 24, '.text') - o3 = link([o1, o2], layout.Layout(), 'arm') - - def testSymbolValues(self): - o1 = ObjectFile() - o1.get_section('.text').add_data(bytes([0]*108)) - o1.add_symbol('b', 24, '.text') - o2 = ObjectFile() - o2.get_section('.text').add_data(bytes([0]*100)) - o2.add_symbol('a', 2, '.text') - o3 = link([o1, o2], layout.Layout(), 'arm') - self.assertEqual(110, o3.find_symbol('a').value) - self.assertEqual(24, o3.find_symbol('b').value) - self.assertEqual(208, o3.get_section('.text').Size) - - def testMemoryLayout(self): - spec = """ - MEMORY flash LOCATION=0x08000000 SIZE=0x3000 { - SECTION(code) - } - MEMORY flash LOCATION=0x20000000 SIZE=0x3000 { - SECTION(data) - } - """ - memory_layout = layout.load_layout(io.StringIO(spec)) - o1 = ObjectFile() - o1.get_section('code').add_data(bytes([0]*108)) - o1.add_symbol('b', 24, 'code') - o2 = ObjectFile() - o2.get_section('code').add_data(bytes([0]*100)) - o2.get_section('data').add_data(bytes([0]*100)) - o2.add_symbol('a', 2, 'data') - o2.add_symbol('c', 2, 'code') - o3 = link([o1, o2], memory_layout, 'arm') - self.assertEqual(0x20000000+2, o3.get_symbol_value('a')) - self.assertEqual(0x08000000+24, o3.get_symbol_value('b')) - self.assertEqual(0x08000000+110, o3.get_symbol_value('c')) - self.assertEqual(208, o3.get_section('code').Size) - self.assertEqual(100, o3.get_section('data').Size) - - -class ObjectFileTestCase(unittest.TestCase): - def makeTwins(self): - o1 = ObjectFile() - o2 = ObjectFile() - o2.get_section('code').add_data(bytes(range(55))) - o1.get_section('code').add_data(bytes(range(55))) - o1.add_relocation('A', 0x2, 'imm12_dumm', 'code') - o2.add_relocation('A', 0x2, 'imm12_dumm', 'code') - o1.add_symbol('A2', 0x90, 'code') - o2.add_symbol('A2', 0x90, 'code') - o1.add_symbol('A3', 0x90, 'code') - o2.add_symbol('A3', 0x90, 'code') - return o1, o2 - - def testEquality(self): - o1, o2 = self.makeTwins() - self.assertEqual(o1, o2) - - def testSaveAndLoad(self): - o1, o2 = self.makeTwins() - f1 = io.StringIO() - o1.save(f1) - f2 = io.StringIO(f1.getvalue()) - o3 = load_object(f2) - self.assertEqual(o3, o1) - - def testSerialization(self): - o1, o2 = self.makeTwins() - o3 = deserialize(serialize(o1)) - self.assertEqual(o3, o1) - - -class LayoutFileTestCase(unittest.TestCase): - def testLayout1(self): - spec = """ - MEMORY flash LOCATION=0x1000 SIZE=0x3000 { - SECTION(code) - ALIGN(4) - } - """ - layout1 = layout.load_layout(io.StringIO(spec)) - layout2 = layout.Layout() - m = layout.Memory('flash') - m.location = 0x1000 - m.size = 0x3000 - m.add_input(layout.Section('code')) - m.add_input(layout.Align(4)) - layout2.add_memory(m) - self.assertEqual(layout2, layout1) - - -if __name__ == '__main__': - unittest.main() - sys.exit() diff -r 0374c65cb437 -r 994c00d55fd5 test/testbitfun.py --- a/test/testbitfun.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ - - -import unittest -import sys -from ppci.bitfun import rotate_left, rotate_right - - -class BitRotationTestCase(unittest.TestCase): - def testRightRotation(self): - self.assertEqual(0xFF000000, rotate_right(0xFF, 8)) - self.assertEqual(0x0FF00000, rotate_right(0xFF, 12)) - - def testLeftRotation(self): - self.assertEqual(0x0000FF00, rotate_left(0xFF, 8)) - self.assertEqual(0x001FE000, rotate_left(0xFF, 13)) - - -if __name__ == '__main__': - unittest.main() - sys.exit() diff -r 0374c65cb437 -r 994c00d55fd5 test/testgraph.py --- a/test/testgraph.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -#!/usr/bin/python - -import unittest -from ppci.codegen.graph import Graph, Node, DiGraph, DiNode -from ppci.codegen.interferencegraph import InterferenceGraph -from ppci.codegen.flowgraph import FlowGraph -from ppci import ir -from ppci.irmach import AbstractInstruction as AI -from ppci.target import Nop - - -class GraphTestCase(unittest.TestCase): - def testEdge(self): - g = Graph() - n1 = Node(g) - g.add_node(n1) - n2 = Node(g) - g.add_node(n2) - g.addEdge(n1, n2) - self.assertTrue(g.hasEdge(n2, n1)) - self.assertTrue(g.hasEdge(n1, n2)) - g.delNode(n1) - g.delNode(n2) - - def testDegree(self): - g = Graph() - n1 = Node(g) - g.add_node(n1) - n2 = Node(g) - g.add_node(n2) - n3 = Node(g) - g.add_node(n3) - g.addEdge(n1, n2) - g.addEdge(n1, n3) - self.assertEqual(2, n1.Degree) - self.assertEqual(1, n2.Degree) - g.delNode(n2) - self.assertEqual(1, n1.Degree) - - -class DigraphTestCase(unittest.TestCase): - def testSuccessor(self): - g = DiGraph() - a = DiNode(g) - b = DiNode(g) - c = DiNode(g) - g.add_node(a) - g.add_node(b) - g.add_node(c) - g.addEdge(a, b) - g.addEdge(b, c) - self.assertEqual({b}, a.Succ) - self.assertEqual({b}, c.Pred) - g.delNode(c) - self.assertEqual(set(), b.Succ) - - -class InterferenceGraphTestCase(unittest.TestCase): - def testNormalUse(self): - t1 = ir.Temp('t1') - t2 = ir.Temp('t2') - t3 = ir.Temp('t3') - t4 = ir.Temp('t4') - t5 = ir.Temp('t5') - t6 = ir.Temp('t6') - instrs = [] - instrs.append(AI(Nop, dst=[t1])) - instrs.append(AI(Nop, dst=[t2])) - instrs.append(AI(Nop, dst=[t3])) - cfg = FlowGraph(instrs) - ig = InterferenceGraph(cfg) - - def testCombine(self): - t1 = ir.Temp('t1') - t2 = ir.Temp('t2') - t3 = ir.Temp('t3') - t4 = ir.Temp('t4') - instrs = [] - instrs.append(AI(Nop, dst=[t1])) - instrs.append(AI(Nop, dst=[t2])) - instrs.append(AI(Nop, dst=[t3])) - instrs.append(AI(Nop, dst=[t4], src=[t3])) - instrs.append(AI(Nop, src=[t4])) - instrs.append(AI(Nop, src=[t1])) - instrs.append(AI(Nop, src=[t2])) - cfg = FlowGraph(instrs) - ig = InterferenceGraph(cfg) - ig.Combine(ig.getNode(t4), ig.getNode(t3)) - self.assertIs(ig.getNode(t4), ig.getNode(t3)) - - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 test/testhexfile.py --- a/test/testhexfile.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -import unittest -import io -from utils import HexFile, HexFileException - - -class testHexFile(unittest.TestCase): - def saveload(self, hf): - f = io.StringIO() - hf.save(f) - hf2 = HexFile() - hf2.load(io.StringIO(f.getvalue())) - self.assertEqual(hf, hf2) - - def testSave1(self): - hf = HexFile() - hf.addRegion(0x8000, bytes.fromhex('aabbcc')) - self.saveload(hf) - - def testSave2(self): - hf = HexFile() - hf.addRegion(0x8000, bytes.fromhex('aabbcc')) - hf.addRegion(0x118000, bytes.fromhex('aabbcc')) - self.saveload(hf) - - def testSave3(self): - hf = HexFile() - hf.addRegion(0x8000, bytes.fromhex('aabbcc')) - hf.addRegion(0xFFFE, bytes.fromhex('aabbcc')) - self.saveload(hf) - - def testSave4(self): - hf = HexFile() - hf.addRegion(0xF000, bytes.fromhex('ab')*0x10000) - self.saveload(hf) - - def testSave5(self): - hf = HexFile() - hf.addRegion(0xF003, bytes.fromhex('ab')*0x10000) - self.saveload(hf) - - def testTwoRegions(self): - hf = HexFile() - hf2 = HexFile() - hf.addRegion(0x100, bytes.fromhex('abcd')) - hf.addRegion(0x200, bytes.fromhex('beef')) - hf2.addRegion(0x200, bytes.fromhex('beef')) - hf2.addRegion(0x100, bytes.fromhex('abcd')) - self.assertEqual(hf, hf2) - - def testMerge(self): - hf = HexFile() - hf.addRegion(0x10, bytes.fromhex('abcdab')) - hf.addRegion(0x13, bytes.fromhex('abcdab')) - self.assertEqual(1, len(hf.regions)) - - def testOverlapped(self): - hf = HexFile() - hf.addRegion(0x10, bytes.fromhex('abcdab')) - with self.assertRaisesRegex(HexFileException, 'verlap'): - hf.addRegion(0x12, bytes.fromhex('abcdab')) - - def testEqual(self): - hf1 = HexFile() - hf2 = HexFile() - hf1.addRegion(10, bytes.fromhex('aabbcc')) - hf2.addRegion(10, bytes.fromhex('aabbcc')) - self.assertEqual(hf1, hf2) - - def testNotEqual(self): - hf1 = HexFile() - hf2 = HexFile() - hf1.addRegion(10, bytes.fromhex('aabbcc')) - hf2.addRegion(10, bytes.fromhex('aabbdc')) - self.assertNotEqual(hf1, hf2) - - def testNotEqual2(self): - hf1 = HexFile() - hf2 = HexFile() - hf1.addRegion(10, bytes.fromhex('aabbcc')) - hf2.addRegion(10, bytes.fromhex('aabbcc')) - hf2.addRegion(22, bytes.fromhex('aabbcc')) - self.assertNotEqual(hf1, hf2) - - def testLoad(self): - hf = HexFile() - dummyhex = """:01400000aa15""" - f = io.StringIO(dummyhex) - hf.load(f) - self.assertEqual(1, len(hf.regions)) - self.assertEqual(0x4000, hf.regions[0].address) - self.assertSequenceEqual(bytes.fromhex('aa'), hf.regions[0].data) - - def testIncorrectCrc(self): - hf = HexFile() - txt = ":01400000aabb" - f = io.StringIO(txt) - with self.assertRaisesRegex(HexFileException, 'crc'): - hf.load(f) - - def testIncorrectLength(self): - hf = HexFile() - txt = ":0140002200aabb" - f = io.StringIO(txt) - with self.assertRaisesRegex(HexFileException, 'count'): - hf.load(f) - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 test/testir.py --- a/test/testir.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -import unittest -import sys -import io -import ppci -from ppci import ir -from ppci import irutils -from ppci.transform import ConstantFolder - - -class IrCodeTestCase(unittest.TestCase): - def testAdd(self): - v = ir.Add(ir.Const(1), ir.Const(2), "add", ir.i32) - - -class IrBuilderTestCase(unittest.TestCase): - def setUp(self): - self.b = irutils.Builder() - self.m = ir.Module('test') - self.b.setModule(self.m) - - def testBuilder(self): - f = self.b.new_function('add') - self.b.setFunction(f) - bb = self.b.newBlock() - self.b.emit(ir.Jump(bb)) - self.b.setBlock(bb) - self.b.emit(ir.Exp(ir.Const(0))) - self.b.emit(ir.Jump(f.epiloog)) - # Run interpreter: - # r = self.m.getFunction('add').call(1, 2) - #self.assertEqual(3, r) - - -class PatternMatchTestCase(unittest.TestCase): - @unittest.skip('Not yet implemented') - def testSimpleTree(self): - t = ir.Term('x') - pat = ir.Binop(ir.Const(2), '+', t) - res, mp = ir.match_tree(ir.Binop(ir.Const(2), '+', 3), pat) - self.assertTrue(res) - self.assertIn(t, mp) - self.assertEqual(3, mp[t]) - - @unittest.skip('Not yet implemented') - def testSimpleTree2(self): - t = ir.Term('x') - t2 = ir.Term('y') - pat = ir.Binop(ir.Const(2), '+', ir.Binop(t, '-', t2)) - res, mp = ir.match_tree(ir.Binop(ir.Const(2), '+', ir.Binop(2,'-',3)), pat) - self.assertTrue(res) - self.assertIn(t, mp) - self.assertEqual(2, mp[t]) - self.assertIn(t2, mp) - self.assertEqual(3, mp[t2]) - res, mp = ir.match_tree(ir.Const(2), pat) - self.assertFalse(res) - - -class ConstantFolderTestCase(unittest.TestCase): - def setUp(self): - self.b = irutils.Builder() - self.cf = ConstantFolder() - self.m = ir.Module('test') - self.b.setModule(self.m) - - def testBuilder(self): - f = self.b.new_function('test') - self.b.setFunction(f) - bb = self.b.newBlock() - self.b.emit(ir.Jump(bb)) - self.b.setBlock(bb) - v1 = ir.Const(5) - # self.b.emit(v1) - v2 = ir.Const(7) - v3 = ir.Add(v1, v2, "add", ir.i32) - # self.b.emit(v3) - self.b.emit(ir.Jump(f.epiloog)) - self.cf.run(self.m) - - def testAdd0(self): - f = self.b.new_function('test') - self.b.setFunction(f) - self.b.setBlock(self.b.newBlock()) - v1 = ir.Const(12) - v3 = ir.Add(v1, ir.Const(0), "add", ir.i32) - - -class TestWriter(unittest.TestCase): - def testWrite(self): - writer = irutils.Writer() - module = ir.Module('mod1') - function = ir.Function('func1', module) - f = io.StringIO() - writer.write(module, f) - #print(f.getvalue()) - f2 = io.StringIO(f.getvalue()) - reader = irutils.Reader() - module2 = reader.read(f2) - f = io.StringIO() - writer.write(module2, f) - #print(f.getvalue()) - - -class TestReader(unittest.TestCase): - def testAddExample(self): - reader = irutils.Reader() - with open('../examples/pi/add.pi') as f: - m = reader.read(f) - self.assertTrue(m) - #print(m) - - -if __name__ == '__main__': - unittest.main() - sys.exit() diff -r 0374c65cb437 -r 994c00d55fd5 test/testmsp430asm.py --- a/test/testmsp430asm.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#!/usr/bin/python - -import unittest -from ppci.objectfile import ObjectFile -from ppci.outstream import BinaryOutputStream -from ppci.target.target_list import msp430target -from testasm import AsmTestCaseBase - - -class Msp430AssemblerTestCase(AsmTestCaseBase): - def setUp(self): - self.target = msp430target - self.obj = ObjectFile() - self.ostream = BinaryOutputStream(self.obj) - self.ostream.select_section('code') - self.assembler = msp430target.assembler - - def testMov(self): - self.feed("mov r14, r15") - self.check('0F4E') - - def testMov1337(self): - self.feed("mov 0x1337, r12") - self.check('3C403713') - - def testAdd(self): - self.feed("add r15, r13") - self.check('0D5F') - - def testReti(self): - self.feed("reti") - self.check('0013') - - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 test/testpyy.py --- a/test/testpyy.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -import unittest -from pyyacc import Grammar, Item, ParserGenerationException, ParserException -from pyyacc import EPS, EOF, calculate_first_sets -from ppci import Token, SourceLocation - - -class genTokens: - def __init__(self, lst): - def tokGen(): - loc = SourceLocation('', 0, 0, 0) - for t in lst: - yield Token(t, t, loc) - while True: - yield Token(EOF, EOF, loc) - self.tokens = tokGen() - self.token = self.tokens.__next__() - - def next_token(self): - t = self.token - if t.typ != EOF: - self.token = self.tokens.__next__() - return t - - -class testLR(unittest.TestCase): - """ Test basic LR(1) parser generator constructs """ - def testSimpleGrammar(self): - # 1. define a simple grammar: - g = Grammar(['identifier', '(', ')', '+', '*']) - g.add_production('input', ['expression']) - g.add_production('expression', ['term']) - g.add_production('expression', ['expression', '+', 'term']) - g.add_production('term', ['factor']) - g.add_production('term', ['term', '*', 'factor']) - g.add_production('factor', ['(', 'expression', ')']) - g.add_production('factor', ['identifier']) - g.start_symbol = 'input' - # 2. define input: - tokens = genTokens(['identifier', '+', 'identifier', '+', 'identifier']) - # 3. build parser: - p = g.generate_parser() - # 4. feed input: - p.parse(tokens) - - def testReduceReduceConflict(self): - """ Check if a reduce-reduce conflict is detected """ - # Define a grammar with an obvious reduce-reduce conflict: - g = Grammar(['id']) - g.add_production('goal', ['a']) - g.add_production('a', ['b']) - g.add_production('a', ['c']) - g.add_production('b', ['id']) - g.add_production('c', ['id']) - g.start_symbol = 'goal' - with self.assertRaises(ParserGenerationException): - p = g.generate_parser() - - def testShiftReduceConflict(self): - """ Must be handled automatically by doing shift """ - g = Grammar([EOF, 'if', 'then', 'else', 'ass']) - # Ambiguous grammar: - g.add_production('if_stmt', ['if', 'then', 'stmt']) - g.add_production('if_stmt', ['if', 'then', 'stmt', 'else', 'stmt']) - g.add_production('stmt', ['if_stmt']) - g.add_production('stmt', ['ass']) - g.start_symbol = 'stmt' - p = g.generate_parser() - # Ambiguous program: - tokens = genTokens(['if', 'then','if', 'then', 'ass', 'else', 'ass']) - p.parse(tokens) - - def testUndefinedTerminal(self): - """ Test correct behavior when a terminal is undefined """ - g = Grammar(['b']) - g.add_production('goal', ['a']) - g.add_production('a', ['b']) - g.add_production('a', ['c']) - g.start_symbol = 'goal' - with self.assertRaises(ParserGenerationException): - g.generate_parser() - - def testRedefineTerminal(self): - """ Test correct behavior when a terminal is redefined """ - g = Grammar([EOF, 'b', 'c']) - g.add_production('goal', ['a']) - with self.assertRaises(ParserGenerationException): - g.add_production('b', ['c']) # Not allowed - g.add_production('a', ['c']) - g.start_symbol = 'goal' - g.generate_parser() - - def testEmpty(self): - """ Test empty token stream """ - g = Grammar([',']) - g.add_production('input', [',']) - g.start_symbol = 'input' - p = g.generate_parser() - tokens = genTokens([]) - with self.assertRaises(ParserException): - p.parse(tokens) - - def testEps(self): - """ Test epsilon terminal """ - g = Grammar(['a', 'b']) - g.add_production('input', ['optional_a', 'b']) - g.add_production('optional_a', ['a']) - g.add_production('optional_a', []) - g.start_symbol = 'input' - p = g.generate_parser() - tokens = genTokens(['b']) - p.parse(tokens) - - def testEps2(self): - g = Grammar(['id', ':']) - g.add_production('input', ['opt_lab', 'ins', 'op1']) - g.add_production('input', ['ins', 'op1']) - g.add_production('opt_lab', ['id', ':']) - g.add_production('ins', ['id']) - g.add_production('op1', ['id']) - g.start_symbol = 'input' - p = g.generate_parser() - tokens = genTokens(['id', ':', 'id', 'id']) # i.e. "lab_0: inc rax" - p.parse(tokens) - tokens = genTokens(['id', 'id']) # i.e. "inc rax" - p.parse(tokens) - - def testEpsSequence(self): - """ Test epsilon terminal for use in sequences """ - g = Grammar(['a']) - g.add_production('aas', []) - g.add_production('aas', ['aas', 'a']) - g.start_symbol = 'aas' - p = g.generate_parser() - tokens = genTokens(['a', 'a', 'a']) - p.parse(tokens) - tokens = genTokens([]) - p.parse(tokens) - - def test_cb(self): - """ Test callback of one rule and order or parameters """ - self.cb_called = False - def cb(a, c, b): - self.cb_called = True - self.assertEqual(a.val, 'a') - self.assertEqual(b.val, 'b') - self.assertEqual(c.val, 'c') - g = Grammar(['a', 'b', 'c']) - g.add_production('goal', ['a', 'c', 'b'], cb) - g.start_symbol = 'goal' - p = g.generate_parser() - tokens = genTokens(['a', 'c', 'b']) - p.parse(tokens) - self.assertTrue(self.cb_called) - - -class testExpressionGrammar(unittest.TestCase): - def setUp(self): - g = Grammar(['EOF', 'identifier', '(', ')', '+', '*', 'num']) - g.add_production('input', ['expression']) - g.add_production('expression', ['term']) - g.add_production('expression', ['expression', '+', 'term']) - g.add_production('term', ['factor']) - g.add_production('term', ['term', '*', 'factor']) - g.add_production('factor', ['(', 'expression', ')']) - g.add_production('factor', ['identifier']) - g.add_production('factor', ['num']) - g.start_symbol = 'input' - self.g = g - - def testFirstSimpleGrammar(self): - # 1. define a simple grammar: - first = calculate_first_sets(self.g) - self.assertEqual(first['input'], {'identifier', '(', 'num'}) - self.assertEqual(first['term'], {'identifier', '(', 'num'}) - - def testCanonical(self): - s0 = self.g.initialItemSet() - s, gt = self.g.genCanonicalSet(s0) - # Must result in 12 sets: - self.assertEqual(len(s), 24) - - -class testParserGenerator(unittest.TestCase): - """ Tests several parts of the parser generator """ - def setUp(self): - g = Grammar(['(', ')']) - g.add_production('goal', ['list']) - g.add_production('list', ['list', 'pair']) - g.add_production('list', ['pair']) - g.add_production('pair', ['(', 'pair', ')']) - g.add_production('pair', ['(', ')']) - g.start_symbol = 'goal' - self.g = g - - def testFirstSet(self): - for a in ['(', ')', EOF, 'EPS']: - self.assertEqual(self.g.first[a], {a}) - for nt in ['list', 'pair', 'goal']: - self.assertEqual(self.g.first[nt], {'('}) - - def testInitItemSet(self): - p0, p1, p2, p3, p4 = self.g.productions - s0 = self.g.initialItemSet() - self.assertEqual(len(s0), 9) # 9 with the goal rule included! - self.assertIn(Item(p0, 0, EOF), s0) - self.assertIn(Item(p1, 0, EOF), s0) - self.assertIn(Item(p1, 0, '('), s0) - self.assertIn(Item(p2, 0, EOF), s0) - self.assertIn(Item(p2, 0, '('), s0) - self.assertIn(Item(p3, 0, EOF), s0) - self.assertIn(Item(p3, 0, '('), s0) - self.assertIn(Item(p4, 0, EOF), s0) - self.assertIn(Item(p4, 0, '('), s0) - - def testCanonical(self): - s0 = self.g.initialItemSet() - s, gt = self.g.genCanonicalSet(s0) - # Must result in 12 sets: - self.assertEqual(len(s), 12) - - def testClosure(self): - p0, p1, p2, p3, p4 = self.g.productions - s0 = set() - s0.add(Item(p0, 0, EOF)) - self.assertEqual(len(s0), 1) # 1 rule - self.assertIn(Item(p0, 0, EOF), s0) - - # Invoke closure on set: - s0 = self.g.closure(s0) - self.assertIn(Item(p0, 0, EOF), s0) - self.assertIn(Item(p1, 0, EOF), s0) - self.assertIn(Item(p1, 0, '('), s0) - self.assertIn(Item(p2, 0, EOF), s0) - self.assertIn(Item(p2, 0, '('), s0) - self.assertIn(Item(p3, 0, EOF), s0) - self.assertIn(Item(p3, 0, '('), s0) - self.assertIn(Item(p4, 0, EOF), s0) - self.assertIn(Item(p4, 0, '('), s0) - - def testParser(self): - tokens = ['(', '(', ')', ')', '(', ')'] - # 3. build parser: - p = self.g.generate_parser() - self.assertEqual(len(p.goto_table), 5) - self.assertEqual(len(p.action_table), 19) - - # 4. feed input: - p.parse(genTokens(tokens)) - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 test/testregalloc.py --- a/test/testregalloc.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -import unittest -import os -import sys -from ppci.irmach import AbstractInstruction as makeIns, Frame -from ppci.codegen.registerallocator import RegisterAllocator -from ppci import ir -from ppci.target import Nop - - -class RegAllocTestCase(unittest.TestCase): - def setUp(self): - self.ra = RegisterAllocator() - - def testRegAlloc(self): - f = Frame('tst') - f.regs = [1,2,3,4,5,6] # for test use numbers! - f.tempMap = {} - t1 = ir.Temp('t1') - t2 = ir.Temp('t2') - t3 = ir.Temp('t3') - t4 = ir.Temp('t4') - t5 = ir.Temp('t5') - f.instructions.append(makeIns(Nop, dst=[t1])) - f.instructions.append(makeIns(Nop, dst=[t2])) - f.instructions.append(makeIns(Nop, dst=[t3])) - f.instructions.append(makeIns(Nop, dst=[t4], src=[t1, t2])) - f.instructions.append(makeIns(Nop, dst=[t5], src=[t4, t3])) - f.instructions.append(makeIns(Nop, src=[t5])) - self.ra.allocFrame(f) - self.conflict(t1, t2) - self.conflict(t2, t3) - - def conflict(self, ta, tb): - self.assertNotEqual(self.ra.Node(ta).color, self.ra.Node(tb).color) - - def testRegCoalesc(self): - f = Frame('tst') - f.regs = [1,2,3,4,5,6] # for test use numbers! - f.tempMap = {} - t1 = ir.Temp('t1') - t2 = ir.Temp('t2') - t3 = ir.Temp('t3') - t4 = ir.Temp('t4') - t5 = ir.Temp('t5') - t6 = ir.Temp('t6') - f.instructions.append(makeIns(Nop, dst=[t1])) - f.instructions.append(makeIns(Nop, dst=[t2])) - f.instructions.append(makeIns(Nop, dst=[t3])) - f.instructions.append(makeIns(Nop, dst=[t4], src=[t2, t1])) - f.instructions.append(makeIns(Nop, dst=[t5], src=[t3])) - f.instructions.append(makeIns(Nop, dst=[t5], src=[t4, t5])) - f.instructions.append(makeIns(Nop, dst=[t6], src=[t5])) - f.instructions.append(makeIns(Nop, src=[t6])) - self.ra.allocFrame(f) - self.conflict(t1, t2) - self.conflict(t2, t3) - self.conflict(t1, t3) - -if __name__ == '__main__': - unittest.main() - diff -r 0374c65cb437 -r 994c00d55fd5 test/testsamples.py --- a/test/testsamples.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,254 +0,0 @@ -import unittest -import os -import io -from testemulation import runQemu, has_qemu -from testzcc import relpath -from ppci.buildfunctions import assemble, c3compile, link - -mod_io_src = """ -module io; -import arch; - -function void println(string txt) -{ - print(txt); - arch.putc(10); // Newline! -} - -function void print(string txt) -{ - var int i; - i = 0; - - while (i < txt->len) - { - arch.putc(cast(txt->txt[i])); - i = i + 1; - } -} - -// Print integer in hexadecimal notation: -function void print_int(int i) -{ - print("0x"); - - // int txt[20]; - var int b; - var int c; - - for (b=28; b >= 0; b = b - 4) - { - c = (i >> b) & 0xF; - if (c < 10) - { - arch.putc( 48 + c ); - } - else - { - arch.putc( 65 - 10 + c ); - } - } - - arch.putc(10); // Newline! -} - -function void print2(string label, int value) -{ - print(label); - print_int(value); -} -""" - - -class Samples: - def testPrint(self): - snippet = """ - module sample; - import io; - function void start() - { - io.print("Hello world"); - } - """ - self.do(snippet, "Hello world") - - def testForLoopPrint(self): - snippet = """ - module sample; - import io; - function void start() - { - var int i; - for (i=0; i<10; i = i + 1) - { - io.print2("A = ", i); - } - } - """ - res = "".join("A = 0x{0:08X}\n".format(a) for a in range(10)) - self.do(snippet, res) - - def testIfStatement(self): - snippet = """ - module sample; - import io; - function void start() - { - var int i; - i = 13; - if (i*7 < 100) - { - io.print("Wow"); - } - else - { - io.print("Outch"); - } - } - """ - res = "Wow" - self.do(snippet, res) - - def testParameterPassing4(self): - snippet = """ - module sample; - import io; - function void dump(int a, int b, int c, int d) - { - io.print2("a=", a); - io.print2("b=", b); - io.print2("c=", c); - io.print2("d=", d); - } - function void start() - { - dump(4,55,66,0x1337); - } - """ - res = "a=0x{0:08X}\n".format(4) - res += "b=0x{0:08X}\n".format(55) - res += "c=0x{0:08X}\n".format(66) - res += "d=0x{0:08X}\n".format(0x1337) - self.do(snippet, res) - - def testGlobalVariable(self): - snippet = """ - module sample; - import io; - var int G; - function void do1() - { - G = G + 1; - io.print2("G=", G); - } - function void do5() - { - G = G + 5; - io.print2("G=", G); - } - function void start() - { - G = 0; - do1(); - do1(); - do5(); - do1(); - do5(); - } - """ - res = "".join("G=0x{0:08X}\n".format(a) for a in [1, 2, 7, 8, 13]) - self.do(snippet, res) - - -class TestSamplesOnVexpress(unittest.TestCase, Samples): - def setUp(self): - if not has_qemu(): - self.skipTest('Not running qemu tests') - - def do(self, src, expected_output): - startercode = """ - section reset - mov sp, 0x30000 ; setup stack pointer - BL sample_start ; Branch to sample start - local_loop: - B local_loop - """ - - modarchcode = """ - module arch; - - function void putc(int c) - { - var int *UART0DR; - UART0DR = cast(0x10009000); // UART0 DR register - *UART0DR = c; - } - - """ - - arch_mmap = """ - MEMORY image LOCATION=0x10000 SIZE=0x10000 { - SECTION(reset) - SECTION(code) - } - - MEMORY ram LOCATION=0x20000 SIZE=0x10000 { - SECTION(data) - } - """ - # Construct binary file from snippet: - o1 = assemble(io.StringIO(startercode), 'arm') - o2 = c3compile([ - relpath('..', 'kernel', 'src', 'io.c3'), - io.StringIO(modarchcode), - io.StringIO(src)], [], 'arm') - o3 = link([o2, o1], io.StringIO(arch_mmap), 'arm') - - img_data = o3.get_image('image') - sample_filename = 'testsample.bin' - with open(sample_filename, 'wb') as f: - f.write(img_data) - - # Check bin file exists: - self.assertTrue(os.path.isfile(sample_filename)) - - # Run bin file in emulator: - res = runQemu(sample_filename, machine='vexpress-a9') - os.remove(sample_filename) - self.assertEqual(expected_output, res) - - -class TestSamplesOnX86(unittest.TestCase, Samples): - def setUp(self): - if not has_qemu(): - self.skipTest('Not running qemu tests') - self.skipTest('No x86 target yet') - - def do(self, src, expected_output): - # Construct binary file from snippet: - o1 = assemble(io.StringIO(startercode), 'x86') - o2 = c3compile([ - relpath('..', 'kernel', 'src', 'io.c3'), - io.StringIO(modarchcode), - io.StringIO(src)], [], 'x86') - o3 = link([o2, o1], io.StringIO(arch_mmap), 'x86') - - img_data = o3.get_image('image') - sample_filename = 'testsample.bin' - with open(sample_filename, 'wb') as f: - f.write(img_data) - - # Check bin file exists: - self.assertTrue(os.path.isfile(sample_filename)) - - # Run bin file in emulator: - res = runQemu(sample_filename, machine='vexpress-a9') - os.remove(sample_filename) - self.assertEqual(expected_output, res) - -# TODO: test samples on thumb target.. - - -if __name__ == '__main__': - unittest.main() - diff -r 0374c65cb437 -r 994c00d55fd5 test/testthumbasm.py --- a/test/testthumbasm.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -import unittest -from ppci.outstream import BinaryOutputStream -from ppci.objectfile import ObjectFile -from testasm import AsmTestCaseBase -from ppci.target.target_list import thumb_target - - -class ThumbAssemblerTestCase(AsmTestCaseBase): - def setUp(self): - self.target = thumb_target - self.obj = ObjectFile() - self.ostream = BinaryOutputStream(self.obj) - self.ostream.select_section('code') - self.assembler = thumb_target.assembler - - def testMovImm8(self): - self.feed('mov r4, 100') - self.check('6424') - - @unittest.skip - def testMovExt(self): - self.feed('mov r3, sp') - self.check('') - - def testYield(self): - self.feed('yield') - self.check('10bf') - - def testPush(self): - self.feed('push {r2,r3,lr}') - self.check('0cb5') - - def testPop(self): - self.feed('pop {r4-r6, pc}') - self.check('70bd') - - def testStr5(self): - self.feed('str r4, [r1 + 0]') - self.check('0c60') - - def testLdr5(self): - self.feed('ldr r4, [r0 + 0]') - self.check('0468') - - def testLdrSpRel(self): - self.feed('ldr r0, [sp + 4]') - self.check('0198') - - def testStrSpRel(self): - self.feed('str r0, [sp + 4]') - self.check('0190') - - def testLdrPcRel(self): - self.feed('ldr r7, henkie') - self.feed('ldr r6, henkie') - self.feed('ldr r1, henkie') - self.feed('align 4') - self.feed('dcd 1') - self.feed('henkie: dcd 2') - self.check('024F024E 01490000 01000000 02000000') - - def testBranch(self): - self.feed('start: b henkie') - self.feed('beq henkie') - self.feed('bne henkie') - self.feed('henkie: b start') - self.feed('eof: b eof') - self.check('01e000d0 ffd1fbe7 fee7') - - def testConditions(self): - self.feed('blt x') - self.feed('bgt x') - self.feed('x:') - self.check('00dbffdc') - - def testBoff(self): - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('henkie:') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.check('05e004e0 03e002e0 01e000e0 ffe7fee7 fde7fce7 fbe7') - - def testBl(self): - self.feed('bl henkie') - self.feed('bl henkie') - self.feed('henkie:') - self.feed('bl henkie') - self.feed('bl henkie') - self.check('00f0 02f8 00f0 00f8 fff7 feff fff7 fcff') - - def testCmpRegReg(self): - self.feed('cmp r0, r1') - self.check('8842') - - def testAddimm3(self): - self.feed('add r3, r5, 2') - self.feed('add r4, r1, 6') - self.check('ab1c8c1d') - - def testSubImm3(self): - self.feed('sub r3, r5, 2') - self.feed('sub r4, r1, 6') - self.check('ab1e8c1f') - - def testLeftShift(self): - self.feed('lsl r3, r5') - self.check('ab40') - - def testAddSp(self): - self.feed('add sp,sp,8') - self.feed('add sp,sp,16') - self.check('02b004b0') - - def testSubSp(self): - self.feed('sub sp,sp,32') - self.feed('sub sp,sp,4') - self.check('88b081b0') - - def testSequence1(self): - self.feed('mov r5, 3') - self.feed('add r4, r5, 0') - self.feed('loop: add r6, r4, 7') - self.feed('cmp r6, 5') - self.check('0325 2c1c e61d 052e') - - def testSequence2(self): - self.feed('henkie:') - self.feed('push {r1,r4,r5}') - self.feed('add r5, r2, r4') - self.feed('cmp r4, r2') - self.feed('ldr r0, [sp + 4]') - self.feed('str r3, [sp + 16]') - self.feed('pop {r1, r4, r5}') - self.feed('lsl r3, r4') - self.feed('cmp r3, r5') - self.feed('beq henkie') - self.feed('bne henkie') - self.feed('b henkie') - self.check('32b41519 94420198 049332bc a340ab42 f6d0f5d1 f4e7') - diff -r 0374c65cb437 -r 994c00d55fd5 test/testx86asm.py --- a/test/testx86asm.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -#!/usr/bin/python - -import unittest -from ppci.target.target_list import x86target -from testasm import AsmTestCaseBase -from ppci.outstream import BinaryOutputStream -from ppci.objectfile import ObjectFile - - -class AssemblerTestCase(AsmTestCaseBase): - """ - test methods start with 'test*' - Checks several assembly constructs agains their bytecodes - """ - def setUp(self): - self.target = x86target - self.obj = ObjectFile() - self.ostream = BinaryOutputStream(self.obj) - self.ostream.select_section('code') - self.assembler = self.target.assembler - self.assembler.prepare() - - def testX86(self): - self.feed('mov rax, rbx') - self.feed('xor rcx, rbx') - self.feed('inc rcx') - self.check('48 89 d8 48 31 d9 48 ff c1') - - @unittest.skip('not implemented') - def testJumpingAround(self): - """ Check all kind of assembler cases """ - assert(assembler.shortjump(5) == [0xeb, 0x5]) - assert(assembler.shortjump(-2) == [0xeb, 0xfc]) - assert(assembler.shortjump(10,'GE') == [0x7d, 0xa]) - assert(assembler.nearjump(5) == [0xe9, 0x5,0x0,0x0,0x0]) - assert(assembler.nearjump(-2) == [0xe9, 0xf9, 0xff,0xff,0xff]) - assert(assembler.nearjump(10,'LE') == [0x0f, 0x8e, 0xa,0x0,0x0,0x0]) - - @unittest.skip('not implemented') - def testCall(self): - self.feed('call r10') - self.check('') - self.feed('call rcx') - # assert(assembler.call('r10') == [0x41, 0xff, 0xd2]) - # assert(assembler.call('rcx') == [0xff, 0xd1]) - - def testXOR(self): - self.feed('xor rax, rax') - self.feed('xor r9, r8') - self.feed('xor rbx, r11') - self.check('48 31 c0 4d 31 c1 4c 31 db') - - def testINC(self): - self.feed('inc r11') - self.feed('inc rcx') - self.check('49 ff c3 48 ff c1') - - def testPush(self): - self.feed('push rbp') - self.feed('push rbx') - self.feed('push r12') - self.check('55 53 41 54') - - def testPop(self): - self.feed('pop rbx') - self.feed('pop rbp') - self.feed('pop r12') - self.check('5b 5d 41 5c') - - @unittest.skip('not implemented') - def testAsmLoads(self): - self.feed('mov rbx, r14') - self.feed('mov r12, r8') - self.feed('mov rdi, rsp') - self.check('4c 89 f3 4d 89 c4 48 89 e7') - - @unittest.skip('not implemented') - def testAsmMemLoads(self): - assert(assembler.mov('rax', ['r8','r15',0x11]) == [0x4b,0x8b,0x44,0x38,0x11]) - assert(assembler.mov('r13', ['rbp','rcx',0x23]) == [0x4c,0x8b,0x6c,0xd,0x23]) - - assert(assembler.mov('r9', ['rbp',-0x33]) == [0x4c,0x8b,0x4d,0xcd]) - #assert(assembler.movreg64('rbx', ['rax']) == [0x48, 0x8b,0x18]) - - assert(assembler.mov('rax', [0xb000]) == [0x48,0x8b,0x4,0x25,0x0,0xb0,0x0,0x0]) - assert(assembler.mov('r11', [0xa0]) == [0x4c,0x8b,0x1c,0x25,0xa0,0x0,0x0,0x0]) - - assert(assembler.mov('r11', ['RIP', 0xf]) == [0x4c,0x8b,0x1d,0x0f,0x0,0x0,0x0]) - - @unittest.skip - def testAsmMemStores(self): - assert(assembler.mov(['rbp', 0x13],'rbx') == [0x48,0x89,0x5d,0x13]) - assert(assembler.mov(['r12', 0x12],'r9') == [0x4d,0x89,0x4c,0x24,0x12]) - assert(assembler.mov(['rcx', 0x11],'r14') == [0x4c,0x89,0x71,0x11]) - - - assert(assembler.mov([0xab], 'rbx') == [0x48,0x89,0x1c,0x25,0xab,0x0,0x0,0x0]) - assert(assembler.mov([0xcd], 'r13') == [0x4c,0x89,0x2c,0x25,0xcd,0x0,0x0,0x0]) - - assert(assembler.mov(['RIP', 0xf], 'r9') == [0x4c,0x89,0x0d,0x0f,0x0,0x0,0x0]) - - @unittest.skip - def testAsmMOV8(self): - assert(assembler.mov(['rbp', -8], 'al') == [0x88, 0x45, 0xf8]) - assert(assembler.mov(['r11', 9], 'cl') == [0x41, 0x88, 0x4b, 0x09]) - - assert(assembler.mov(['rbx'], 'al') == [0x88, 0x03]) - assert(assembler.mov(['r11'], 'dl') == [0x41, 0x88, 0x13]) - - @unittest.skip - def testAsmLea(self): - assert(assembler.leareg64('r11', ['RIP', 0xf]) == [0x4c,0x8d,0x1d,0x0f,0x0,0x0,0x0]) - assert(assembler.leareg64('rsi', ['RIP', 0x7]) == [0x48,0x8d,0x35,0x07,0x0,0x0,0x0]) - - assert(assembler.leareg64('rcx', ['rbp', -8]) == [0x48,0x8d,0x4d,0xf8]) - - @unittest.skip - def testAssemblerCMP(self): - assert(assembler.cmpreg64('rdi', 'r13') == [0x4c, 0x39, 0xef]) - assert(assembler.cmpreg64('rbx', 'r14') == [0x4c, 0x39, 0xf3]) - assert(assembler.cmpreg64('r12', 'r9') == [0x4d, 0x39, 0xcc]) - - assert(assembler.cmpreg64('rdi', 1) == [0x48, 0x83, 0xff, 0x01]) - assert(assembler.cmpreg64('r11', 2) == [0x49, 0x83, 0xfb, 0x02]) - - @unittest.skip - def testAssemblerADD(self): - assert(assembler.addreg64('rbx', 'r13') == [0x4c, 0x01, 0xeb]) - assert(assembler.addreg64('rax', 'rbx') == [0x48, 0x01, 0xd8]) - assert(assembler.addreg64('r12', 'r13') == [0x4d, 0x01, 0xec]) - - assert(assembler.addreg64('rbx', 0x13) == [0x48, 0x83, 0xc3, 0x13]) - assert(assembler.addreg64('r11', 0x1234567) == [0x49, 0x81, 0xc3, 0x67, 0x45,0x23,0x1]) - assert(assembler.addreg64('rsp', 0x33) == [0x48, 0x83, 0xc4, 0x33]) - - @unittest.skip - def testAssemblerSUB(self): - assert(assembler.subreg64('rdx', 'r14') == [0x4c, 0x29, 0xf2]) - assert(assembler.subreg64('r15', 'rbx') == [0x49, 0x29, 0xdf]) - assert(assembler.subreg64('r8', 'r9') == [0x4d, 0x29, 0xc8]) - - assert(assembler.subreg64('rsp', 0x123456) == [0x48, 0x81, 0xec, 0x56,0x34,0x12,0x0]) - assert(assembler.subreg64('rsp', 0x12) == [0x48, 0x83, 0xec, 0x12]) - - @unittest.skip - def testAssemblerIDIV(self): - assert(assembler.idivreg64('r11') == [0x49, 0xf7, 0xfb]) - assert(assembler.idivreg64('rcx') == [0x48, 0xf7, 0xf9]) - assert(assembler.idivreg64('rsp') == [0x48, 0xf7, 0xfc]) - - @unittest.skip - def testAssemblerIMUL(self): - assert(assembler.imulreg64_rax('rdi') == [0x48, 0xf7, 0xef]) - assert(assembler.imulreg64_rax('r10') == [0x49, 0xf7, 0xea]) - assert(assembler.imulreg64_rax('rdx') == [0x48, 0xf7, 0xea]) - - assert(assembler.imulreg64('r11', 'rdi') == [0x4c, 0xf, 0xaf, 0xdf]) - assert(assembler.imulreg64('r12', 'rbx') == [0x4c, 0xf, 0xaf, 0xe3]) - # nasm generates this machine code: 0x4d, 0x6b, 0xff, 0xee - # This also works: 4D0FAFFE (another variant?? ) - assert(assembler.imulreg64('r15', 'r14') == [0x4d, 0x0f, 0xaf, 0xfe]) - - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 test/testzcc.py --- a/test/testzcc.py Mon Jul 14 22:23:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -import unittest -import os -import sys - -import zcc -from ppci.objectfile import ObjectFile -import ppci -import io -from ppci.target import target_list - -# Store testdir for safe switch back to directory: -testdir = os.path.dirname(os.path.abspath(__file__)) - -def relpath(*args): - return os.path.join(testdir, *args) - - -class ZccBaseTestCase(unittest.TestCase): - def callZcc(self, arg_list): - parser = zcc.make_parser() - arg_list = ['--log', 'warn'] + arg_list - args = parser.parse_args(arg_list) - self.assertEqual(0, zcc.main(args)) - - def buildRecipe(self, recipe, targetlist=[]): - arg_list = ['--buildfile', recipe] + targetlist - self.callZcc(arg_list) - - -class ZccTestCase(ZccBaseTestCase): - """ Tests the compiler driver """ - def setUp(self): - os.chdir(testdir) - - def tearDown(self): - os.chdir(testdir) - - def do(self, filenames, imps=[], extra_args=[]): - return - basedir = relpath('..', 'examples', 'c3') - arg_list = ['compile'] - arg_list += [os.path.join(basedir, fn) for fn in filenames] - for fn in imps: - arg_list.append('-i') - arg_list.append(os.path.join(basedir, fn)) - arg_list.append('--target') - arg_list.append('thumb') - arg_list += extra_args - self.callZcc(arg_list) - - @unittest.skip('Api change') - def testDumpIr(self): - basedir = relpath('..', 'examples', 'c3', 'comments.c3') - arg_list = ['compile', basedir] - arg_list.append('--target') - arg_list.append('thumb') - self.callZcc(arg_list) - - @unittest.skip('Too hard') - def testThumbKernel(self): - """ Build kernel using zcc: """ - recipe = relpath('..', 'kernel', 'thumb.yaml') - self.buildRecipe(recipe) - - def testArmKernel(self): - """ Build kernel using zcc: """ - recipe = relpath('..', 'kernel', 'build.xml') - self.buildRecipe(recipe) - - def testKernelBuildsEqualTwice(self): - """ Build kernel two times and check the output is equal """ - recipe = relpath('..', 'kernel', 'build.xml') - bin_filename = relpath('..', 'kernel', 'kernel_arm.bin') - self.buildRecipe(recipe) - with open(bin_filename, 'rb') as f: - a = f.read() - self.buildRecipe(recipe) - with open(bin_filename, 'rb') as f: - b = f.read() - self.assertSequenceEqual(a, b) - - def testUser(self): - """ Build userspace using zcc: """ - recipe = relpath('..', 'user', 'build.xml') - self.buildRecipe(recipe) - - def testBurn2(self): - recipe = relpath('..', 'examples', 'c3', 'build.xml') - self.buildRecipe(recipe) - - def test_hello_A9_c3_recipe(self): - recipe = relpath('..', 'examples', 'qemu_a9_hello', 'build.xml') - self.buildRecipe(recipe) - - @unittest.skip('Skip because of logfile') - def testBurn2WithLogging(self): - self.do(['burn2.c3'], ['stm32f4xx.c3'], extra_args=['--report', 'x.rst']) - - def testCommentsExample(self): - self.do(['comments.c3']) - - def testCast(self): - self.do(['cast.c3']) - - def testFunctions(self): - self.do(['functions.c3']) - - -if __name__ == '__main__': - unittest.main() diff -r 0374c65cb437 -r 994c00d55fd5 util/test_patterns.txt --- a/util/test_patterns.txt Mon Jul 14 22:23:55 2014 +0200 +++ b/util/test_patterns.txt Wed Feb 18 22:56:42 2015 +0100 @@ -60,3 +60,8 @@ ldr r8, =a a: +=== +ldrb r5, [r3, #87] +=== +strb r2, [r8, #11] +