changeset 292:534b94b40aa8

Fixup reorganize
author Windel Bouwman
date Wed, 27 Nov 2013 08:06:42 +0100
parents 7b38782ed496
children 6aa721e7b10b
files kernel/kernel.c3 kernel/make.sh kernel/process.c3 kernel/syscall.c3 python/adi.py python/bin2c.py python/codegen.py python/devices.py python/diagramitems.py python/hexfile.py python/ide/ide.py python/ide/st-util.py python/ir.py python/irmach.py python/lsusb.py python/makeinitrd.py python/mem2reg.py python/other/bouncing_cube.py python/other/diagramitems.py python/ppci/__init__.py python/ppci/common.py python/st-flash.py python/st-util.py python/stlink.py python/stm32.py python/target/__init__.py python/target/armframe.py python/target/arminstructions.py python/target/arminstructionselector.py python/target/armtarget.py python/target/armv7.lidl python/target/basetarget.py python/target/msp430.py python/target/openrisc.lidl python/usb.py python/utils/__init__.py python/utils/adi.py python/utils/devices.py python/utils/hexfile.py python/utils/lsusb.py python/utils/st-flash.py python/utils/stlink.py python/utils/stm32.py python/utils/usb.py python/zcc.py test/testarmasm.py test/testasm.py test/testc3.py test/testcg.py test/testhexfile.py test/testir.py test/testmsp430asm.py test/testx86asm.py test/testzcc.py
diffstat 54 files changed, 3774 insertions(+), 3721 deletions(-) [+]
line wrap: on
line diff
--- a/kernel/kernel.c3	Sun Nov 24 11:24:15 2013 +0100
+++ b/kernel/kernel.c3	Wed Nov 27 08:06:42 2013 +0100
@@ -1,19 +1,25 @@
 module kernel;
+
 import memory;
 import process;
+import scheduler;
+import arch;
 
 // Main entry point of the kernel:
 func start()
 {
-  process.Init();
-  memory.Init();
+    process.Init();
+    memory.Init();
+
+
+    Process proc = new process.Process();
+
+    scheduler.queue(proc);
 }
 
 
 func panic()
 {
-  while(true)
-  {
-  }
+    arch.halt();
 }
 
--- a/kernel/make.sh	Sun Nov 24 11:24:15 2013 +0100
+++ b/kernel/make.sh	Wed Nov 27 08:06:42 2013 +0100
@@ -1,4 +1,4 @@
 #!/bin/bash
 
-../python/zcc.py memory.c3
+../python/zcc.py memory.c3 kernel.c3
 
--- a/kernel/process.c3	Sun Nov 24 11:24:15 2013 +0100
+++ b/kernel/process.c3	Wed Nov 27 08:06:42 2013 +0100
@@ -5,8 +5,12 @@
 // process type definition:
 typedef struct {
     int id;
+    int status;
 } process_t;
 
+// Or, use this list structure:
+List<process_t> procs;
+
 // init is the root of all processes:
 var process_t* init = 0;
 var int next_pid = 0;
@@ -34,4 +38,10 @@
     // clean memory
 }
 
+public process_t* byId(int id)
+{
+    // Perform lookup
+    return 0;
+}
 
+
--- a/kernel/syscall.c3	Sun Nov 24 11:24:15 2013 +0100
+++ b/kernel/syscall.c3	Wed Nov 27 08:06:42 2013 +0100
@@ -1,9 +1,60 @@
 module syscall;
 
+/*
+    This module handles all the system calls from user space.
+*/
+
+enum {
+    SendMsg = 1,
+    ReceiveMsg = 2,
+
+} syscall_t;
 
 // System call handlers. System calls are made from user space.
+func void handle_system_call(int callId, int a, int b, int c, int d)
+{
+    // Main entry, check what to do here
+    switch(callId)
+    {
+        case SendMsg:
+            handle_send_msg();
+            proc = process.byId(a);
+            if (not proc)
+            {
+                panic();
+            }
 
-func void handle_system_call()
-{
+            proc.setMessage();
+            scheduler.current.setState(Sleep);
+            break;
+        case ReceiveMsg:
+            break;
+        case Reboot:
+            arch.reboot();
+            break;
+        default:
+            return NO_SUCH_CALL;
+    }
+
+    return OK;
 }
 
+// Handle send message syscall
+func void handle_send_msg()
+{
+    p = process.byId(msg.to_id);
+    scheduler.attempt(p);
+}
+
+func handle_recv_msg()
+{
+    // Block until we have a message
+    currentProc->setState(Sleep);
+    scheduler.executeNext();
+}
+
+func handle_reboot()
+{
+    reboot();
+}
+
--- a/python/adi.py	Sun Nov 24 11:24:15 2013 +0100
+++ /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)
-
-
--- a/python/bin2c.py	Sun Nov 24 11:24:15 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-
-import sys
-print(sys.argv)
-if len(sys.argv) < 2:
-   print('Usage: {0} binfile [headerfile]'.format(sys.argv[0]))
-   sys.exit(-1)
-
-with open(sys.argv[1], 'rb') as f:
-   data = f.read()
-
-s = ', '.join(hex(b) for b in data)
-output = 'unsigned char data[] = {{{0}}};'.format(s)
-if len(sys.argv) < 3:
-   print(output)
-else:
-   with open(sys.argv[2], 'w') as f:
-      f.write(output)
-
--- a/python/codegen.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/codegen.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,30 +1,28 @@
 import ir
-import target
+from target import Target
 from ppci import CompilerError
 import transform
 import canon
+import registerallocator
 
 
-# TODO: this class could be target independent:
 class CodeGenerator:
-    def __init__(self, outs, target):
+    """ Generic code generator """
+    def __init__(self, target):
         # TODO: schedule traces in better order.
         # This is optional!
-        assert isinstance(tg, target.Target)
+        assert isinstance(target, Target), target
         self.target = target
-        self.ins_sel = ArmInstructionSelector()
+        self.ins_sel = target.ins_sel
         self.ra = registerallocator.RegisterAllocator()
-        self.outs = outs
-        self.outs.getSection('code').address = 0x08000000
-        self.outs.getSection('data').address = 0x20000000
 
-    def generateFunc(self, irfunc):
+    def generateFunc(self, irfunc, outs):
         """ Generate code for one function into a frame """
         # Cleanup function:
         transform.removeEmptyBlocks(irfunc)
 
         # Create a frame for this function:
-        frame = ArmFrame(irfunc.name)
+        frame = self.target.FrameClass(irfunc.name)
 
         # Canonicalize the intermediate language:
         canon.make(irfunc, frame)
@@ -34,32 +32,21 @@
         self.ra.allocFrame(frame)
         # TODO: Peep-hole here?
 
-        # Can we materialize here??
-
         # Add label and return and stack adjustment:
         frame.EntryExitGlue3()
 
         # Materialize assembly
         # Materialize the register allocated instructions into a stream of
         # real instructions.
-        frame.lower_to(self.outs)
+        frame.lower_to(outs)
         return frame
 
-    def generate(self, ircode):
+    def generate(self, ircode, outs):
         assert isinstance(ircode, ir.Module)
-        self.outs.selectSection('code')
-        # assembly glue to make it work:
-        # TODO: this must be in source code, not in compiler
-        self.outs.emit(arm.dcd_ins(Imm32(0x20000678)))   # initial SP
-        self.outs.emit(arm.dcd_ins(Imm32(0x08000009)))   # reset vector
-        self.outs.emit(arm.b_ins(LabelRef('main')))
+        outs.selectSection('code')
 
         # Munch program into a bunch of frames. One frame per function.
         # Each frame has a flat list of abstract instructions.
         # Generate code for all functions:
-        self.frames = [self.generateFunc(func) for func in ircode.Functions]
-
-        # TODO: fixup references, do this in another way?
-        self.outs.backpatch()
-        self.outs.backpatch()  # Why two times?
+        self.frames = [self.generateFunc(func, outs) for func in ircode.Functions]
         return self.frames
--- a/python/devices.py	Sun Nov 24 11:24:15 2013 +0100
+++ /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
-
--- a/python/diagramitems.py	Sun Nov 24 11:24:15 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,437 +0,0 @@
-"""
- Contains all blocks that can be used to build models.
-"""
-
-from PyQt4.QtGui import *
-from PyQt4.QtCore import *
-
-def uniqify(name, names):
-   newname, i = name, 1
-   while newname in names: newname, i = name + str(i), i + 1
-   return newname
-
-def enum(**enums):
-   return type('Enum', (), enums)
-
-Position = enum(TOP=0, TOP_RIGHT=1, RIGHT=2, BOTTOM_RIGHT=3, BOTTOM=4, BOTTOM_LEFT=5, LEFT=6, TOP_LEFT=7)
-
-def buildPath(pts):
-   path = QPainterPath(pts[0])
-   for pt in pts[1:]: path.lineTo(pt)
-   return path
-
-def equalSpace(n, l, offset=15):
-   if n == 1:
-      return [l / 2]
-   elif n > 1:
-      return [offset + (l - offset*2)/(n - 1)*i for i in range(n)]
-   return []
-
-class Connection(QGraphicsPathItem):
-   """ A connection between blocks """
-   def __init__(self, fromPort=None, toPort=None):
-      super(Connection, self).__init__()
-      self.pos2 = self.fromPort = self.toPort = None
-      self.setFlags(self.ItemIsSelectable | self.ItemClipsToShape)
-      pen = QPen(Qt.blue, 2, cap=Qt.RoundCap)
-      self.setPen(pen)
-      self.arrowhead = QGraphicsPathItem(self)
-      self.arrowhead.setPath(buildPath([QPointF(0.0, 0.0), QPointF(-6.0, 10.0), QPointF(6.0, 10.0), QPointF(0.0, 0.0)]))
-      self.arrowhead.setPen(pen)
-      self.arrowhead.setBrush(QBrush(pen.color()))
-      self.vias = []
-      self.setFromPort(fromPort)
-      self.setToPort(toPort)
-   def getDict(self):
-      d = {}
-      d['fromBlock'] = self.fromPort.block.name
-      d['fromPort'] = self.fromPort.name
-      d['toBlock'] = self.toPort.block.name
-      d['toPort'] = self.toPort.name
-      return d
-   Dict = property(getDict)
-   def myDelete(self):
-      scene = self.scene()
-      if scene:
-         self.setFromPort(None)
-         self.setToPort(None)
-         scene.removeItem(self)
-   def setFromPort(self, fromPort):
-      if self.fromPort:
-         self.fromPort.posCallbacks.remove(self.setBeginPos)
-         self.fromPort.connection = None
-      self.fromPort = fromPort
-      if self.fromPort:
-         self.fromPort.connection = self
-         self.updateLineStukken()
-         self.fromPort.posCallbacks.append(self.setBeginPos)
-   def setToPort(self, toPort):
-      if self.toPort:
-         self.toPort.posCallbacks.remove(self.setEndPos)
-         self.toPort.connection = None
-      self.toPort = toPort
-      if self.toPort:
-         self.setEndPos(toPort.scenePos())
-         self.toPort.connection = self
-         self.toPort.posCallbacks.append(self.setEndPos)
-   def getPos1(self):
-      if self.fromPort:
-         return self.fromPort.scenePos()
-   def setBeginPos(self, pos1): self.updateLineStukken()
-   def setEndPos(self, endpos):
-      self.pos2 = endpos
-      self.updateLineStukken()
-   def itemChange(self, change, value):
-      if change == self.ItemSelectedHasChanged:
-         for via in self.vias:
-            via.setVisible(value)
-      return super(Connection, self).itemChange(change, value)
-   def shape(self): return self.myshape
-   def updateLineStukken(self):
-      """
-         This algorithm determines the optimal routing of all signals.
-         TODO: implement nice automatic line router
-      """
-      pos1 = self.getPos1()
-      pos2 = self.pos2
-      if pos1 is None or pos2 is None:
-         return
-      scene = self.scene()
-      vias = [pos1 + QPointF(20, 0)] + self.vias + [pos2 + QPointF(-20, 0)]
-      if scene:
-         litem = QGraphicsLineItem()
-         litem.setFlags(self.ItemIsSelectable)
-         scene.addItem(litem)
-         for p1, p2 in zip(vias[:-1], vias[1:]):
-            line = QLineF(p1, p2)
-            litem.setLine(line)
-            citems = scene.collidingItems(litem)
-            citems = [i for i in citems if type(i) is Block]
-         scene.removeItem(litem)
-      pts = [pos1] + vias + [pos2]
-      self.arrowhead.setPos(pos2)
-      self.arrowhead.setRotation(90)
-      p = buildPath(pts)
-      self.setPath(p)
-      """ Create a shape outline using the path stroker """
-      s = super(Connection, self).shape()
-      pps = QPainterPathStroker()
-      pps.setWidth(10)
-      self.myshape = pps.createStroke(s).simplified()
-
-class PortItem(QGraphicsPathItem):
-   """ Represents a port to a subsystem """
-   def __init__(self, name, block):
-      super(PortItem, self).__init__(block)
-      self.textItem = QGraphicsTextItem(self)
-      self.connection = None
-      self.block = block
-      self.setCursor(QCursor(Qt.CrossCursor))
-      self.setPen(QPen(Qt.blue, 2, cap=Qt.RoundCap))
-      self.name = name
-      self.posCallbacks = []
-      self.setFlag(self.ItemSendsScenePositionChanges, True)
-   def getName(self): return self.textItem.toPlainText()
-   def setName(self, name):
-      self.textItem.setPlainText(name)
-      rect = self.textItem.boundingRect()
-      lw, lh = rect.width(), rect.height()
-      lx = 3 if type(self) is InputPort else -3 - lw
-      self.textItem.setPos(lx, -lh / 2)
-   name = property(getName, setName)
-   def getDict(self): 
-      return {'name': self.name}
-   Dict = property(getDict)
-   def itemChange(self, change, value):
-      if change == self.ItemScenePositionHasChanged:
-         for cb in self.posCallbacks: cb(value)
-         return value
-      return super(PortItem, self).itemChange(change, value)
-
-class OutputPort(PortItem):
-   def __init__(self, name, block, d=10.0):
-      super(OutputPort, self).__init__(name, block)
-      self.setPath(buildPath([QPointF(0.0, -d), QPointF(d, 0), QPointF(0.0, d)]))
-   def mousePressEvent(self, event):
-      self.scene().startConnection(self)
-
-class InputPort(PortItem):
-   def __init__(self, name, block, d=10.0):
-      super(InputPort, self).__init__(name, block)
-      self.setPath(buildPath([QPointF(-d, -d), QPointF(0, 0), QPointF(-d, d)]))
-
-class Handle(QGraphicsEllipseItem):
-   """ A handle that can be moved by the mouse """
-   def __init__(self, dx=10.0, parent=None):
-      super(Handle, self).__init__(QRectF(-0.5*dx,-0.5*dx,dx,dx), parent)
-      self.setBrush(QBrush(Qt.white))
-      self.setFlags(self.ItemIsMovable)
-      self.setZValue(1)
-      self.setVisible(False)
-      self.setCursor(QCursor(Qt.SizeFDiagCursor))
-   def mouseMoveEvent(self, event):
-      """ Move function without moving the other selected elements """
-      p = self.mapToParent(event.pos())
-      self.setPos(p)
-
-class ResizeSelectionHandle(Handle):
-   def __init__(self, position, block):
-      super(ResizeSelectionHandle, self).__init__(dx=12, parent=block)
-      self.position = position
-      self.block = block
-      if position in [Position.TOP_LEFT, Position.BOTTOM_RIGHT]:
-         self.setCursor(QCursor(Qt.SizeFDiagCursor))
-      elif position in [Position.TOP_RIGHT, Position.BOTTOM_LEFT]:
-         self.setCursor(QCursor(Qt.SizeBDiagCursor))
-      elif position in [Position.TOP, Position.BOTTOM]:
-         self.setCursor(QCursor(Qt.SizeVerCursor))
-      elif position in [Position.LEFT, Position.RIGHT]:
-         self.setCursor(QCursor(Qt.SizeHorCursor))
-   def mouseMoveEvent(self, event):
-      self.block.sizerMoveEvent(self, event.scenePos())
-
-class Block(QGraphicsRectItem):
-   """ Represents a block in the diagram. """
-   def __init__(self, name='Untitled', parent=None):
-      super(Block, self).__init__(parent)
-      self.selectionHandles = [ResizeSelectionHandle(i, self) for i in range(8)]
-      # Properties of the rectangle:
-      self.setPen(QPen(Qt.blue, 2))
-      self.setBrush(QBrush(Qt.lightGray))
-      self.setFlags(self.ItemIsSelectable | self.ItemIsMovable | self.ItemSendsScenePositionChanges)
-      self.setCursor(QCursor(Qt.PointingHandCursor))
-      self.setAcceptHoverEvents(True)
-      self.label = QGraphicsTextItem(name, self)
-      self.name = name
-      # Create corner for resize:
-      button = QPushButton('+in')
-      button.clicked.connect(self.newInputPort)
-      self.buttonItemAddInput = QGraphicsProxyWidget(self)
-      self.buttonItemAddInput.setWidget(button)
-      self.buttonItemAddInput.setVisible(False)
-      button = QPushButton('+out')
-      button.clicked.connect(self.newOutputPort)
-      self.buttonItemAddOutput = QGraphicsProxyWidget(self)
-      self.buttonItemAddOutput.setWidget(button)
-      self.buttonItemAddOutput.setVisible(False)
-      # Inputs and outputs of the block:
-      self.inputs = []
-      self.outputs = []
-      self.changeSize(2,2)
-   def editParameters(self):
-      pd = ParameterDialog(self, self.window())
-      pd.exec_()
-   def newInputPort(self):
-      names = [i.name for i in self.inputs + self.outputs]
-      self.addInput(InputPort(uniqify('in', names), self))
-   def newOutputPort(self):
-      names = [i.name for i in self.inputs + self.outputs]
-      self.addOutput(OutputPort(uniqify('out', names), self))
-   def setName(self, name): self.label.setPlainText(name)
-   def getName(self): return self.label.toPlainText()
-   name = property(getName, setName)
-   def getDict(self):
-      d = {'x': self.scenePos().x(), 'y': self.scenePos().y()}
-      rect = self.rect()
-      d.update({'width': rect.width(), 'height': rect.height()})
-      d['name'] = self.name
-      d['inputs'] = [inp.Dict for inp in self.inputs]
-      d['outputs'] = [outp.Dict for outp in self.outputs]
-      return d
-   def setDict(self, d):
-      self.name = d['name']
-      self.setPos(d['x'], d['y'])
-      self.changeSize(d['width'], d['height'])
-      for inp in d['inputs']:
-         self.addInput(InputPort(inp['name'], self))
-      for outp in d['outputs']:
-         self.addOutput(OutputPort(outp['name'], self))
-   Dict = property(getDict, setDict)
-   def addInput(self, i):
-      self.inputs.append(i)
-      self.updateSize()
-   def addOutput(self, o):
-      self.outputs.append(o)
-      self.updateSize()
-   def contextMenuEvent(self, event):
-      menu = QMenu()
-      pa = menu.addAction('Parameters')
-      pa.triggered.connect(self.editParameters)
-      menu.exec_(event.screenPos())
-   def itemChange(self, change, value):
-      if change == self.ItemSelectedHasChanged:
-         for child in [self.buttonItemAddInput, self.buttonItemAddOutput]:
-            child.setVisible(value)
-         if value:
-            self.repositionAndShowHandles()
-         else:
-            [h.setVisible(False) for h in self.selectionHandles]
-
-      return super(Block, self).itemChange(change, value)
-   def hoverEnterEvent(self, event):
-      if not self.isSelected():
-         self.repositionAndShowHandles()
-      super(Block, self).hoverEnterEvent(event)
-   def hoverLeaveEvent(self, event):
-      if not self.isSelected():
-         [h.setVisible(False) for h in self.selectionHandles]
-      super(Block, self).hoverLeaveEvent(event)
-   def myDelete(self):
-      for p in self.inputs + self.outputs:
-         if p.connection: p.connection.myDelete()
-      self.scene().removeItem(self)
-   def repositionAndShowHandles(self):
-         r = self.rect()
-         self.selectionHandles[Position.TOP_LEFT].setPos(r.topLeft())
-         self.selectionHandles[Position.TOP].setPos(r.center().x(), r.top())
-         self.selectionHandles[Position.TOP_RIGHT].setPos(r.topRight())
-         self.selectionHandles[Position.RIGHT].setPos(r.right(), r.center().y())
-         self.selectionHandles[Position.BOTTOM_RIGHT].setPos(r.bottomRight())
-         self.selectionHandles[Position.BOTTOM].setPos(r.center().x(), r.bottom())
-         self.selectionHandles[Position.BOTTOM_LEFT].setPos(r.bottomLeft())
-         self.selectionHandles[Position.LEFT].setPos(r.left(), r.center().y())
-         for h in self.selectionHandles:
-            h.setVisible(True)
-   def sizerMoveEvent(self, handle, pos):
-      r = self.rect().translated(self.pos())
-      if handle.position == Position.TOP_LEFT: r.setTopLeft(pos)
-      elif handle.position == Position.TOP: r.setTop(pos.y())
-      elif handle.position == Position.TOP_RIGHT: r.setTopRight(pos)
-      elif handle.position == Position.RIGHT: r.setRight(pos.x())
-      elif handle.position == Position.BOTTOM_RIGHT: r.setBottomRight(pos)
-      elif handle.position == Position.BOTTOM: r.setBottom(pos.y())
-      elif handle.position == Position.BOTTOM_LEFT: r.setBottomLeft(pos)
-      elif handle.position == Position.LEFT: r.setLeft(pos.x())
-      else:
-         print('invalid position')
-      self.setCenterAndSize(r.center(), r.size())
-      self.repositionAndShowHandles()
-   def updateSize(self):
-      rect = self.rect()
-      h, w = rect.height(), rect.width()
-      self.buttonItemAddInput.setPos(0, h + 4)
-      self.buttonItemAddOutput.setPos(w+10, h+4)
-      for inp, y in zip(self.inputs, equalSpace(len(self.inputs), h)):
-         inp.setPos(0.0, y)
-      for outp, y in zip(self.outputs, equalSpace(len(self.outputs), h)):
-         outp.setPos(w, y)
-   def setCenterAndSize(self, center, size):
-      self.changeSize(size.width(), size.height())
-      p = QPointF(size.width(), size.height())
-      self.setPos(center - p / 2)
-   def changeSize(self, w, h):
-      minw = 150
-      minh = 50
-      h = minh if h < minh else h
-      w = minw if w < minw else w
-      self.setRect(0.0, 0.0, w, h)
-      rect = self.label.boundingRect()
-      self.label.setPos((w - rect.width()) / 2, (h - rect.height()) / 2)
-      self.updateSize()
-
-class CodeBlock(Block):
-   def __init__(self, name='Untitled', parent=None):
-      super(CodeBlock, self).__init__(name, parent)
-      self.code = ''
-   def setDict(self, d):
-      super(CodeBlock, self).setDict(d)
-      self.code = d['code']
-   def getDict(self):
-      d = super(CodeBlock, self).getDict()
-      d['code'] = self.code
-      return d
-   def gencode(self):
-      c = ['def {0}():'.format(self.name)]
-      if self.code:
-         c += indent(self.code.split('\n'))
-      else:
-         c += indent(['pass'])
-      return c
-
-class DiagramBlock(Block):
-   def __init__(self, name='Untitled', parent=None):
-      super(DiagramBlock, self).__init__(name, parent)
-      self.subModel = DiagramScene()
-      self.subModel.containingBlock = self
-   def setDict(self, d):
-      self.subModel.Dict = d['submodel']
-   def mouseDoubleClickEvent(self, event):
-      # descent into child diagram
-      #self.editParameters()
-      print('descent')
-      scene = self.scene()
-      if scene:
-         for view in scene.views():
-            view.diagram = self.subModel
-            view.zoomAll()
-
-class DiagramScene(QGraphicsScene):
-   """ A diagram scene consisting of blocks and connections """
-   structureChanged = pyqtSignal()
-   def __init__(self):
-      super(DiagramScene, self).__init__()
-      self.startedConnection = None
-
-   blocks = property(lambda sel: [i for i in sel.items() if isinstance(i, Block)])
-   connections = property(lambda sel: [i for i in sel.items() if type(i) is Connection])
-   def addItem(self, item):
-      super(DiagramScene, self).addItem(item)
-      if isinstance(item, Block):
-         self.structureChanged.emit()
-   def removeItem(self, item):
-      super(DiagramScene, self).removeItem(item)
-      if isinstance(item, Block):
-         self.structureChanged.emit()
-   def setDict(self, d):
-      for block in d['blocks']:
-         b = Block()
-         self.addItem(b)
-         b.Dict = block
-      for con in d['connections']:
-         fromPort = self.findPort(con['fromBlock'], con['fromPort'])
-         toPort = self.findPort(con['toBlock'], con['toPort'])
-         self.addItem(Connection(fromPort, toPort))
-   def getDict(self):
-      return {'blocks': [b.Dict for b in self.blocks], 'connections': [c.Dict for c in self.connections]}
-   Dict = property(getDict, setDict)
-   def gencode(self):
-      c = []
-      for b in self.blocks:
-         c += b.gencode()
-      for b in self.blocks:
-         c.append('{0}()'.format(b.name))
-      return c
-   def findPort(self, blockname, portname):
-      block = self.findBlock(blockname)
-      if block:
-         for port in block.inputs + block.outputs:
-            if port.name == portname: return port
-   def findBlock(self, blockname):
-      for block in self.blocks:
-         if block.name == blockname: return block
-   def uniqify(self, name):
-      blocknames = [item.name for item in self.blocks]
-      return uniqify(name, blocknames)
-   def mouseMoveEvent(self, event):
-      if self.startedConnection:
-         pos = event.scenePos()
-         self.startedConnection.setEndPos(pos)
-      super(DiagramScene, self).mouseMoveEvent(event)
-   def mouseReleaseEvent(self, event):
-      if self.startedConnection:
-         for item in self.items(event.scenePos()):
-            if type(item) is InputPort and item.connection == None:
-               self.startedConnection.setToPort(item)
-               self.startedConnection = None
-               return
-         self.startedConnection.myDelete()
-         self.startedConnection = None
-      super(DiagramScene, self).mouseReleaseEvent(event)
-   def startConnection(self, port):
-      self.startedConnection = Connection(port, None)
-      pos = port.scenePos()
-      self.startedConnection.setEndPos(pos)
-      self.addItem(self.startedConnection)
-   def deleteItems(self):
-      for item in list(self.selectedItems()): item.myDelete()
-
--- a/python/hexfile.py	Sun Nov 24 11:24:15 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +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(len(r.data) for r in self.regions)
-        return 'Hexfile containing {} bytes'.format(size)
-
-    def dump(self):
-        print(self)
-        for r in self.regions:
-            print(r)
-
-    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 EndAddress(self):
-        return self.address + len(self.data)
-
-
--- a/python/ide/ide.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/ide/ide.py	Wed Nov 27 08:06:42 2013 +0100
@@ -10,11 +10,15 @@
 from PyQt4.QtGui import *
 
 # Compiler imports:
+p = os.path.join(os.path.dirname(__file__), '..')
+# print(p)
+sys.path.insert(0, p)
+sys.path.insert(0, os.path.join(p, 'utils'))
 import ppci
 from astviewer import AstViewer
 from codeedit import CodeEdit
 from logview import LogView as BuildOutput
-from disasm import Disassembly
+#from disasm import Disassembly
 stutil = __import__('st-util')
 import c3
 import zcc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ide/st-util.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,385 @@
+#!/usr/bin/python
+
+import sys
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+import stlink, devices, stm32, usb
+from devices import Interface, Device
+from hexedit import HexEdit
+
+
+class InformationDialog(QDialog):
+   def __init__(self, parent):
+      super().__init__(parent)
+      self.setWindowTitle('Info')
+      fl = QFormLayout(self)
+      if parent.stl:
+         fl.addRow('ST link version:', QLabel(parent.stl.Version))
+         fl.addRow('Chip id:', QLabel('0x{0:X}'.format(parent.stl.ChipId)))
+         fl.addRow('Current mode:', QLabel(parent.stl.CurrentModeString))
+         fl.addRow('Status:', QLabel(parent.stl.StatusString))
+
+
+class RegisterModel(QAbstractTableModel):
+    def __init__(self):
+      super().__init__()
+      self.regCount = 15
+      self.device = None
+
+    def rowCount(self, parent):
+      if parent.isValid():
+         return 0
+      if self.device:
+         return 21 # TODO make variable
+      else:
+         return 0
+
+    def setDevice(self, dev):
+      self.device = dev
+      self.modelReset.emit()
+
+    def columnCount(self, parent):
+      if parent.isValid():
+         return 0
+      return 2
+
+    def data(self, index, role):
+      if index.isValid():
+         row, col = index.row(), index.column()
+         if role == Qt.DisplayRole:
+            if col == 0:
+                if row == 15:
+                    return 'PC'
+                elif row == 14:
+                    return 'LR'
+                elif row == 13:
+                    return 'SP'
+                else:
+                    return 'R{0}'.format(row)
+            elif col == 1:
+               v = self.device.iface.read_reg(row)
+               return '0x{0:X}'.format(v)
+
+    def setData(self, index, value, role):
+      if index.isValid():
+         row = index.row()
+         col = index.column()
+         if role == Qt.EditRole and col == 1:
+            value = int(value, 16)
+            self.device.iface.write_reg(row, value)
+            return True
+      return False
+
+    def flags(self, index):
+      if index.isValid():
+         row = index.row()
+         col = index.column()
+         if col == 1:
+            return super().flags(index) | Qt.ItemIsEditable
+      return super().flags(index)
+
+    def refresh(self):
+      if self.device:
+         fromIndex = self.index(0, 1)
+         toIndex = self.index(21, 1)
+         self.dataChanged.emit(fromIndex, toIndex)
+
+
+class RegisterView(QTableView):
+    def __init__(self):
+      super().__init__()
+      self.mdl = RegisterModel()
+      self.setModel(self.mdl)
+
+    def refresh(self):
+      if self.mdl.device:
+         self.setEnabled(not self.mdl.device.Running)
+      self.mdl.refresh()
+
+
+class MemoryView(QWidget):
+    BlockSize = 0x100
+    def __init__(self):
+      super().__init__()
+      l = QVBoxLayout(self)
+      l2 = QHBoxLayout()
+      l2.addWidget(QLabel('Address'))
+      self.addressLine = QLineEdit()
+      self.addressLine.setInputMask('Hhhhhhhh')
+      l2.addWidget(self.addressLine)
+      upButton = QPushButton('up')
+      l2.addWidget(upButton)
+      upButton.clicked.connect(self.doUp)
+      downButton = QPushButton('down')
+      downButton.clicked.connect(self.doDown)
+      l2.addWidget(downButton)
+      l.addLayout(l2)
+      self.device = None
+      self.hexEdit = HexEdit()
+      self.Address = 0x8000000
+      l.addWidget(self.hexEdit)
+      self.addressLine.returnPressed.connect(self.refresh)
+
+    def refresh(self):
+        address = self.Address
+        if self.device:
+            data = self.device.iface.read_mem32(address, self.BlockSize)
+        else:
+            data = bytearray(self.BlockSize)
+        self.hexEdit.bv.Data = data
+        self.hexEdit.bv.Offset = address
+
+    def getAddress(self):
+          txt = self.addressLine.text()
+          return int(txt, 16)
+
+    def doUp(self):
+        self.Address -= self.BlockSize
+
+    def doDown(self):
+        self.Address += self.BlockSize
+
+    def setAddress(self, address):
+        self.addressLine.setText('{0:08X}'.format(address))
+        self.refresh()
+    Address = property(getAddress, setAddress)
+    def setDevice(self, dev):
+      self.device = dev
+      self.Address = 0x8000000
+
+
+class DebugToolbar(QToolBar):
+   statusChange = pyqtSignal()
+   codePosition = pyqtSignal(int)
+   def __init__(self):
+      super().__init__()
+      self.device = None
+      # generate actions:
+      def genAction(name, callback):
+         a = QAction(name, self)
+         a.triggered.connect(callback)
+         self.addAction(a)
+         return a
+      self.stepAction = genAction('Step', self.doStep)
+      self.runAction = genAction('Run', self.doRun)
+      self.stopAction = genAction('Stop', self.doHalt)
+      self.resetAction = genAction('Reset', self.doReset)
+      self.enableTraceAction = genAction('Enable trace', self.doEnableTrace)
+      self.updateEnables()
+   def updateEnables(self):
+      if self.device:
+         self.resetAction.setEnabled(True)
+         self.enableTraceAction.setEnabled(True)
+         self.runAction.setEnabled(not self.device.Running)
+         self.stepAction.setEnabled(not self.device.Running)
+         self.stopAction.setEnabled(self.device.Running)
+         self.statusChange.emit()
+         if not self.device.Running:
+            PC = 15
+            v = self.device.iface.read_reg(PC)
+            self.codePosition.emit(v)
+      else:
+         self.resetAction.setEnabled(False)
+         self.enableTraceAction.setEnabled(False)
+         self.runAction.setEnabled(False)
+         self.stepAction.setEnabled(False)
+         self.stopAction.setEnabled(False)
+   def doStep(self):
+      self.device.iface.step()
+      self.updateEnables()
+   def doReset(self):
+      self.device.iface.reset()
+      self.updateEnables()
+   def doRun(self):
+      self.device.iface.run()
+      self.updateEnables()
+   def doHalt(self):
+      self.device.iface.halt()
+      self.updateEnables()
+   def doEnableTrace(self):
+      self.device.iface.traceEnable()
+      self.updateEnables()
+   def setDevice(self, dev):
+      self.device = dev
+      self.updateEnables()
+
+
+class FlashTool(QWidget):
+   def __init__(self):
+      super().__init__()
+      # TODO!
+
+
+class DeviceTreeModel(QAbstractItemModel):
+   def __init__(self):
+      super().__init__()
+      self.chipPixmap = QPixmap('icons/chip.png').scaled(32, 32)
+      self.hardwarePixmap = QPixmap('icons/hardware.png').scaled(32, 32)
+      self.refresh()
+   def refresh(self):
+      """ Check all usb interfaces for interfaces """
+      self.interfaces = devices.createInterfaces()
+      self.devices = []
+      self.modelReset.emit()
+   def addDevice(self, device):
+      if device.iface in [lambda d: d.iface for d in self.devices]:
+         print('device already open')
+         return
+      self.devices.append(device)
+      self.modelReset.emit()
+   def index(self, row, column, parent):
+      if parent.isValid():
+         ip = parent.internalPointer()
+         if isinstance(ip, Interface):
+            devs = [d for d in self.devices if d.iface is ip]
+            return self.createIndex(row, column, devs[row])
+      else:
+         iface = self.interfaces[row]
+         return self.createIndex(row, column, iface)
+      return idx
+   def parent(self, index):
+      if index.isValid():
+         ip = index.internalPointer()
+         if isinstance(ip, Interface):
+            return QModelIndex()
+         elif isinstance(ip, Device):
+            iface = ip.iface
+            row = self.interfaces.index(iface)
+            return self.createIndex(row, 0, iface)
+         return QModelIndex()
+   def rowCount(self, parent):
+      if parent.isValid():
+         # non-root level:
+         ip = parent.internalPointer()
+         if isinstance(ip, Interface):
+            devs = [d for d in self.devices if d.iface is ip]
+            return len(devs)
+      else:
+         # root level:
+         return len(self.interfaces)
+      return 0
+   def columnCount(self, parent):
+      return 1
+   def data(self, index, role):
+      if index.isValid():
+         ip = index.internalPointer()
+         if role == Qt.DisplayRole:
+            return str(ip)
+         elif role == Qt.DecorationRole:
+            if isinstance(ip, Interface):
+               return self.hardwarePixmap
+            if isinstance(ip, Device):
+               return self.chipPixmap
+
+class DeviceExplorer(QTreeView):
+   """ Lists all interfaces plugged in and allows selection """
+   deviceSelected = pyqtSignal(Device)
+   def __init__(self):
+      super().__init__()
+      self.mdl = DeviceTreeModel()
+      self.setModel(self.mdl)
+      self.activated.connect(self.openItem)
+      self.header().close()
+      self.customContextMenuRequested.connect(self.openMenu)
+      self.setContextMenuPolicy(Qt.CustomContextMenu)
+   def openItem(self, idx):
+      if idx.isValid():
+         ip = idx.internalPointer()
+         if isinstance(ip, Interface):
+            if not ip.IsOpen:
+               try:
+                  ip.open()
+               except usb.UsbError as e:
+                  QMessageBox.critical(self, "Error", 'Error opening interface: "{0}"'.format(e))
+               else:
+                  # Try to get a device:
+                  self.mdl.addDevice(ip.createDevice())
+         if isinstance(ip, Device):
+            self.deviceSelected.emit(ip)
+   def openMenu(self, pt):
+      idx = self.indexAt(pt)
+      menu = QMenu()
+      menu.addAction('Refresh', self.mdl.refresh)
+      if idx.isValid():
+         ip = idx.internalPointer()
+         if isinstance(ip, Interface):
+            if ip.IsOpen:
+               def closeInterface():
+                  self.mdl.closeInterface(ip)
+               menu.addAction('Close', closeInterface)
+            else:
+               def openInterface():
+                  ip.open()
+                  # Try to get a device:
+                  self.mdl.addDevice(ip.createDevice())
+               menu.addAction('Open', openInterface)
+         elif isinstance(ip, Device):
+            def selectDevice():
+               self.deviceSelected.emit(ip)
+            menu.addAction('Select', selectDevice)
+      menu.exec(self.mapToGlobal(pt))
+
+
+class StUtil(QMainWindow):
+   connected = pyqtSignal(bool)
+   def __init__(self):
+      super().__init__()
+      self.stl = None
+      def buildAction(name, callback, shortcut=None):
+         a = QAction(name, self)
+         a.triggered.connect(callback)
+         if shortcut:
+            a.setShortcut(shortcut)
+         return a
+      mb = self.menuBar()
+      fileMenu = mb.addMenu("File")
+      self.connectAction = buildAction('Connect', self.connect)
+      fileMenu.addAction(self.connectAction)
+      self.disconnectAction = buildAction('Disconnect', self.disconnect)
+      fileMenu.addAction(self.disconnectAction)
+
+      self.miscMenu = mb.addMenu("Misc")
+      infoAction = buildAction('Info', self.info)
+      self.miscMenu.addAction(infoAction)
+
+      sb = self.statusBar()
+
+      devexplr = DeviceExplorer()
+      self.setCentralWidget(devexplr)
+      devexplr.deviceSelected.connect(self.handleDeviceSelected)
+
+      self.connected.connect(self.handleConnectedChange)
+      self.connected.emit(False)
+   def handleDeviceSelected(self, dev):
+      self.dev = dev
+      self.handleConnectedChange(True)
+   def handleConnectedChange(self, state):
+      self.miscMenu.setEnabled(state)
+      self.connectAction.setEnabled(not state)
+      self.disconnectAction.setEnabled(state)
+      msg = 'Connected!' if state else 'Disconnected!'
+      self.statusBar().showMessage(msg)
+   def info(self):
+      infoDialog = InformationDialog(self)
+      infoDialog.exec()
+   def connect(self):
+      try:
+         self.stl = stlink.STLink()
+         self.stl.open()
+      except (stlink.STLinkException, usb.UsbError) as e:
+         QMessageBox.warning(self, "Error", str(e))
+         self.stl = None
+      if self.stl:
+         self.connected.emit(True)
+   def disconnect(self):
+      if self.stl:
+         self.stl.close()
+         self.connected.emit(False)
+      self.stl = None
+
+if __name__ == '__main__':
+   app = QApplication(sys.argv)
+   stu = StUtil()
+   stu.show()
+   app.exec()
+
--- a/python/ir.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/ir.py	Wed Nov 27 08:06:42 2013 +0100
@@ -278,12 +278,15 @@
     """ Convenience call """
     return Binop(a, '+', b)
 
+
 def Sub(a, b):
     return Binop(a, '-', b)
 
+
 def Mul(a, b):
     return Binop(a, '*', b)
 
+
 def Div(a, b):
     return Binop(a, '/', b)
 
--- a/python/irmach.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/irmach.py	Wed Nov 27 08:06:42 2013 +0100
@@ -67,5 +67,3 @@
             p = '%l{}'.format(i)
             x = x.replace(p, str(j))
         return x
-        
-
--- a/python/lsusb.py	Sun Nov 24 11:24:15 2013 +0100
+++ /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)
-
--- a/python/makeinitrd.py	Sun Nov 24 11:24:15 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#!/usr/bin/python
-
-# Script for generation of an initial ramdisk that contains 
-# the first programs to run.
-
-import struct
-import sys
-
-if len(sys.argv) < 3:
-   print('Usage: {0} output file1 [file2] ...'.format(sys.argv[0]))
-   sys.exit(1)
-
-outputfilename = sys.argv[1]
-inputFileNames = sys.argv[2:]
-
-with open(outputfilename, 'wb') as outputFile:
-   # Amount of files:
-   outputFile.write(struct.pack('<I', 0x1337babe))
-   outputFile.write(struct.pack('<I', len(inputFileNames)))
-   for inputFileName in inputFileNames:
-      # Magic:
-      outputFile.write(struct.pack('<I', 0xcafebabe))
-
-      # Filename:
-      fn = inputFileName.encode('ascii')
-      outputFile.write(struct.pack('<I', len(fn)))
-      outputFile.write(fn)
-
-      # Data:
-      with open(inputFileName, 'rb') as inputFile:
-         data = inputFile.read()
-      outputFile.write(struct.pack('<I', len(data)))
-      outputFile.write(data)
-
--- a/python/mem2reg.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/mem2reg.py	Wed Nov 27 08:06:42 2013 +0100
@@ -7,6 +7,7 @@
     assert type(allocinst) is Alloc
     return all(type(use) in [Load, Store] for use in allocinst.value.used_by)
 
+
 class Mem2RegPromotor(FunctionPass):
     def promoteSingleBlock(self, ai):
         v = ai.value
--- a/python/other/bouncing_cube.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/other/bouncing_cube.py	Wed Nov 27 08:06:42 2013 +0100
@@ -11,7 +11,6 @@
 import numpy as np
 import time
 import scipy.integrate
-#import pyopencl
 
 """
   Test script that lets a dice bounce.
@@ -21,139 +20,142 @@
     http://www.20sim.com
 
 """
+
+# OpenGL drawing madness:
 def drawCube(w):
-      glBegin(GL_QUADS)			# Start Drawing The Cube
-      glColor3f(0.0,1.0,0.0)			# Set The Color To Blue
-      glVertex3f( w, w,-w)		# Top Right Of The Quad (Top)
-      glVertex3f(-w, w,-w)		# Top Left Of The Quad (Top)
-      glVertex3f(-w, w, w)		# Bottom Left Of The Quad (Top)
-      glVertex3f( w, w, w)		# Bottom Right Of The Quad (Top)
+    glBegin(GL_QUADS)			# Start Drawing The Cube
+    glColor3f(0.0,1.0,0.0)			# Set The Color To Blue
+    glVertex3f( w, w,-w)		# Top Right Of The Quad (Top)
+    glVertex3f(-w, w,-w)		# Top Left Of The Quad (Top)
+    glVertex3f(-w, w, w)		# Bottom Left Of The Quad (Top)
+    glVertex3f( w, w, w)		# Bottom Right Of The Quad (Top)
 
-      glColor3f(1.0,0.5,0.0)			# Set The Color To Orange
-      glVertex3f( w,-w, w)		# Top Right Of The Quad (Bottom)
-      glVertex3f(-w,-w, w)		# Top Left Of The Quad (Bottom)
-      glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Bottom)
-      glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Bottom)
+    glColor3f(1.0,0.5,0.0)			# Set The Color To Orange
+    glVertex3f( w,-w, w)		# Top Right Of The Quad (Bottom)
+    glVertex3f(-w,-w, w)		# Top Left Of The Quad (Bottom)
+    glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Bottom)
+    glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Bottom)
 
-      glColor3f(1.0,0.0,0.0)			# Set The Color To Red
-      glVertex3f( w, w, w)		# Top Right Of The Quad (Front)
-      glVertex3f(-w, w, w)		# Top Left Of The Quad (Front)
-      glVertex3f(-w,-w, w)		# Bottom Left Of The Quad (Front)
-      glVertex3f( w,-w, w)		# Bottom Right Of The Quad (Front)
+    glColor3f(1.0,0.0,0.0)			# Set The Color To Red
+    glVertex3f( w, w, w)		# Top Right Of The Quad (Front)
+    glVertex3f(-w, w, w)		# Top Left Of The Quad (Front)
+    glVertex3f(-w,-w, w)		# Bottom Left Of The Quad (Front)
+    glVertex3f( w,-w, w)		# Bottom Right Of The Quad (Front)
 
-      glColor3f(1.0,1.0,0.0)			# Set The Color To Yellow
-      glVertex3f( w,-w,-w)		# Bottom Left Of The Quad (Back)
-      glVertex3f(-w,-w,-w)		# Bottom Right Of The Quad (Back)
-      glVertex3f(-w, w,-w)		# Top Right Of The Quad (Back)
-      glVertex3f( w, w,-w)		# Top Left Of The Quad (Back)
+    glColor3f(1.0,1.0,0.0)			# Set The Color To Yellow
+    glVertex3f( w,-w,-w)		# Bottom Left Of The Quad (Back)
+    glVertex3f(-w,-w,-w)		# Bottom Right Of The Quad (Back)
+    glVertex3f(-w, w,-w)		# Top Right Of The Quad (Back)
+    glVertex3f( w, w,-w)		# Top Left Of The Quad (Back)
 
-      glColor3f(0.0,0.0,1.0)			# Set The Color To Blue
-      glVertex3f(-w, w, w)		# Top Right Of The Quad (Left)
-      glVertex3f(-w, w,-w)		# Top Left Of The Quad (Left)
-      glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Left)
-      glVertex3f(-w,-w, w)		# Bottom Right Of The Quad (Left)
+    glColor3f(0.0,0.0,1.0)			# Set The Color To Blue
+    glVertex3f(-w, w, w)		# Top Right Of The Quad (Left)
+    glVertex3f(-w, w,-w)		# Top Left Of The Quad (Left)
+    glVertex3f(-w,-w,-w)		# Bottom Left Of The Quad (Left)
+    glVertex3f(-w,-w, w)		# Bottom Right Of The Quad (Left)
 
-      glColor3f(1.0,0.0,1.0)			# Set The Color To Violet
-      glVertex3f( w, w,-w)		# Top Right Of The Quad (Right)
-      glVertex3f( w, w, w)		# Top Left Of The Quad (Right)
-      glVertex3f( w,-w, w)		# Bottom Left Of The Quad (Right)
-      glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Right)
-      glEnd()				# Done Drawing The Quad
+    glColor3f(1.0,0.0,1.0)			# Set The Color To Violet
+    glVertex3f( w, w,-w)		# Top Right Of The Quad (Right)
+    glVertex3f( w, w, w)		# Top Left Of The Quad (Right)
+    glVertex3f( w,-w, w)		# Bottom Left Of The Quad (Right)
+    glVertex3f( w,-w,-w)		# Bottom Right Of The Quad (Right)
+    glEnd()				# Done Drawing The Quad
 
 def drawFloor(w, h):
-      glBegin(GL_QUADS)			# Start Drawing The Cube
-
-      glColor3f(1.0,0.5,0.0) # Set The Color To Orange
-      glVertex3f( w,-w,h)# Top Right Of The Quad (Bottom)
-      glVertex3f(-w,-w,h)# Top Left Of The Quad (Bottom)
-      glVertex3f(-w,w,h)# Bottom Left Of The Quad (Bottom)
-      glVertex3f( w,w,h)# Bottom Right Of The Quad (Bottom)
-      glEnd()				# Done Drawing The Quad
+    glBegin(GL_QUADS)			# Start Drawing The Cube
+    glColor3f(1.0,0.5,0.0) # Set The Color To Orange
+    glVertex3f( w,-w,h)# Top Right Of The Quad (Bottom)
+    glVertex3f(-w,-w,h)# Top Left Of The Quad (Bottom)
+    glVertex3f(-w,w,h)# Bottom Left Of The Quad (Bottom)
+    glVertex3f( w,w,h)# Bottom Right Of The Quad (Bottom)
+    glEnd()				# Done Drawing The Quad
 
 def drawAxis():
-  glLineWidth(0.5)
-  glBegin(GL_LINES)
-  glColor3f(1.0, 0.0, 0.0)
-  glVertex3f(0,0,0)
-  glVertex3f(1,0,0)
-  glColor3f(0.0, 1.0, 0.0)
-  glVertex3f(0,0,0)
-  glVertex3f(0,1,0)
-  glColor3f(0.0, 0.0, 1.0)
-  glVertex3f(0,0,0)
-  glVertex3f(0,0,1)
-  glEnd()
+    glLineWidth(0.5)
+    glBegin(GL_LINES)
+    glColor3f(1.0, 0.0, 0.0)
+    glVertex3f(0,0,0)
+    glVertex3f(1,0,0)
+    glColor3f(0.0, 1.0, 0.0)
+    glVertex3f(0,0,0)
+    glVertex3f(0,1,0)
+    glColor3f(0.0, 0.0, 1.0)
+    glVertex3f(0,0,0)
+    glVertex3f(0,0,1)
+    glEnd()
 
 
+# Math helper functions:
+
 def cross(A, B):
-   a = A.A1
-   b = B.A1
-   return mat(np.cross(a, b)).T
+    a = A.A1
+    b = B.A1
+    return mat(np.cross(a, b)).T
 
 def skew(X):
-  Y = mat(zeros( (3, 3) ))
-  a,b,c = X.A1
-  Y[0,1] = -c
-  Y[0,2] = b
-  Y[1,0] = c
-  Y[1,2] = -a
-  Y[2,0] = -b
-  Y[2,1] = a
-  return Y
+    Y = mat(zeros( (3, 3) ))
+    a, b, c = X.A1
+    Y[0,1] = -c
+    Y[0,2] = b
+    Y[1,0] = c
+    Y[1,2] = -a
+    Y[2,0] = -b
+    Y[2,1] = a
+    return Y
 
 def adjoint(T):
-  W = T[0:3, 0]
-  V = T[3:6, 0]
-  a = mat(zeros( (6,6) ) )
-  a[0:3, 0:3] = skew(W)
-  a[3:6, 0:3] = skew(V)
-  a[3:6, 3:6] = skew(W)
-  return a
+    W = T[0:3, 0]
+    V = T[3:6, 0]
+    a = mat(zeros( (6, 6) ) )
+    a[0:3, 0:3] = skew(W)
+    a[3:6, 0:3] = skew(V)
+    a[3:6, 3:6] = skew(W)
+    return a
 
 def Adjoint(H):
-  R = H[0:3, 0:3]
-  P = H[0:3, 3]
-  a = mat(zeros( (6,6) ) )
-  a[0:3, 0:3] = R
-  a[3:6, 3:6] = R
-  a[3:6, 0:3] = skew(P) * R
-  return a
+    R = H[0:3, 0:3]
+    P = H[0:3, 3]
+    a = mat(zeros( (6, 6) ) )
+    a[0:3, 0:3] = R
+    a[3:6, 3:6] = R
+    a[3:6, 0:3] = skew(P) * R
+    return a
 
 def quatToR(q):
-  x, y, z, w = q.A1
-  r = mat(eye(3))
-  r[0,0] = 1 - (2*y**2+2*z**2)
-  r[0,1] = 2*x*y+2*z*w
-  r[0,2] = 2*x*z - 2*y*w
-  r[1,0] = 2*x*y-2*z*w
-  r[1,1] = 1 - (2*x**2 + 2*z**2)
-  r[1,2] = 2*y*z + 2*x*w
-  r[2,0] = 2*x*z+2*y*w
-  r[2,1] = 2*y*z - 2*x*w
-  r[2,2] = 1 - (2*x**2+2*y**2)
-  return r
+    x, y, z, w = q.A1
+    r = mat(eye(3))
+    r[0,0] = 1 - (2*y**2+2*z**2)
+    r[0,1] = 2*x*y+2*z*w
+    r[0,2] = 2*x*z - 2*y*w
+    r[1,0] = 2*x*y-2*z*w
+    r[1,1] = 1 - (2*x**2 + 2*z**2)
+    r[1,2] = 2*y*z + 2*x*w
+    r[2,0] = 2*x*z+2*y*w
+    r[2,1] = 2*y*z - 2*x*w
+    r[2,2] = 1 - (2*x**2+2*y**2)
+    return r
 
 def rotateAbout(axis, angle):
-   ax, ay, az = (axis/norm(axis)).A1
-   qx = ax*sin(angle/2.0)
-   qy = ay*sin(angle/2.0)
-   qz = az*sin(angle/2.0)
-   qw = cos(angle/2.0)
-   q = mat(array([qx,qy,qz,qw])).T
-   return q
+    ax, ay, az = (axis/norm(axis)).A1
+    qx = ax*sin(angle/2.0)
+    qy = ay*sin(angle/2.0)
+    qz = az*sin(angle/2.0)
+    qw = cos(angle/2.0)
+    q = mat(array([qx,qy,qz,qw])).T
+    return q
 
 def normalizeQuaternion(quat):
-  x,y,z,w = quat.A1
-  magnitude = sqrt(x*x + y*y + z*z + w*w)
-  x = x / magnitude
-  y = y / magnitude
-  z = z / magnitude
-  w = w / magnitude
-  quat[0, 0] = x
-  quat[1, 0] = y
-  quat[2, 0] = z
-  quat[3, 0] = w
-  return quat
+    x,y,z,w = quat.A1
+    magnitude = sqrt(x*x + y*y + z*z + w*w)
+    x = x / magnitude
+    y = y / magnitude
+    z = z / magnitude
+    w = w / magnitude
+    quat[0, 0] = x
+    quat[1, 0] = y
+    quat[2, 0] = z
+    quat[3, 0] = w
+    return quat
 
 def VTo4x4(V):
     v1, v2, v3 = V.A1
@@ -163,211 +165,256 @@
       [-v2, v1, 0.0, -v3], \
       [v1, v2, v3, 0.0] ]))
 
-def homogeneous(R,p):
+def homogeneous(R, p):
+    """ Create a H matrix from rotation and position """
     H = mat(eye(4))
     H[0:3, 0:3] = R
     H[0:3, 3] = p
     return H
 
-def rateOfChange(states, thetime, parameters):
-    quat = states[0:4,  0] # Orientation (4)
-    pos  = states[4:7,  0] # Position (3)
-    P    = states[7:13, 0] # Momentum (6)
-    massI, gravity = parameters
-    # Rigid body parts:
-    # Forward Kinematic chain:
-    H = homogeneous(quatToR(quat), pos) # Forward kinematics
 
-    AdjX2 = mat(eye(6)) # The connectionpoint in the real world
-    adjAdjX2_1 = adjoint(AdjX2[0:6,0])
-    adjAdjX2_2 = adjoint(AdjX2[0:6,1])
-    adjAdjX2_3 = adjoint(AdjX2[0:6,2])
-    adjAdjX2_4 = adjoint(AdjX2[0:6,3])
-    adjAdjX2_5 = adjoint(AdjX2[0:6,4])
-    adjAdjX2_6 = adjoint(AdjX2[0:6,5])
-    AdjInv2 = Adjoint(H.I)
-    M2 = AdjInv2.T * (massI * AdjInv2) # Transfor mass to base frame
-    MassMatrix = M2
-
-    wrenchGrav2 = mat( zeros((1,6)) )
-    wrenchGrav2[0, 0:3] = -cross(gravity, pos).T
-    wrenchGrav2[0, 3:6] = gravity.T
-
-    Bk = mat( zeros( (6,6) ))
-    Bk[0:3, 0:3] = skew(P[0:3, 0])
-    Bk[3:6, 0:3] = skew(P[3:6, 0])
-    Bk[0:3, 3:6] = skew(P[3:6, 0])
-
-    # TODO: do this a cholesky:
-    v = np.linalg.solve(MassMatrix, P) # Matrix inverse like thingy !
-
-    T2_00 = v # Calculate the relative twist!
-    TM2 = T2_00.T * M2
-    twistExternal = T2_00 # Twist van het blokje
-    TMSum2 = TM2
-
-    PDotBodies = mat( zeros( (6,1)) )
-    PDotBodies[0,0] = TMSum2 * (adjAdjX2_1 * T2_00)
-    PDotBodies[1,0] = TMSum2 * (adjAdjX2_2 * T2_00)
-    PDotBodies[2,0] = TMSum2 * (adjAdjX2_3 * T2_00)
-    PDotBodies[3,0] = TMSum2 * (adjAdjX2_4 * T2_00)
-    PDotBodies[4,0] = TMSum2 * (adjAdjX2_5 * T2_00)
-    PDotBodies[5,0] = TMSum2 * (adjAdjX2_6 * T2_00)
-    
-    PDot = -PDotBodies - Bk * v
-    PDot += wrenchGrav2.T
-    
-    ##### Contact wrench part:
-    HB_W = H # Is H-matrix van het blokje
-    WrenchB = mat(zeros( (1,6) ))
-    for px in [-0.5, 0.5]:
-      for py in [-0.5, 0.5]:
-        for pz in [-0.5, 0.5]:
-          HB1_B = homogeneous(mat(eye(3)), mat([px,py,pz]).T)
-          HB1_W = HB_W * HB1_B
-          HW1_W = homogeneous(mat(eye(3)), HB1_W[0:3,3])
-          HW_W1 = HW1_W.I
-          HB_W1 = HW_W1 * HB_W
-    
-          AdjHB_W1 = Adjoint(HB_W1)
-          TB_W1_W1 = AdjHB_W1 * twistExternal
-          z = HB1_W[2, 3]
-          vx, vy, vz = TB_W1_W1[3:6, 0].A1
-          if z < 0:
-            # Contact forces:
-            Fx = -50.0*vx
-            Fy = -50.0*vy
-            Fz = -z*50000.0 
-          else:
-            Fx = 0.0
-            Fy = 0.0
-            Fz = 0.0
-          # TODO: reflect impulse
-          WrenchW1 = mat([0,0,0,0,0,Fz])
-          # Transform it back:
-          WrenchB += (AdjHB_W1.T * WrenchW1.T).T
-    ##### End of contact wrench
-
-    PDot += (WrenchB * AdjInv2).T
-
-    # Position and orientation rates:
-    QOmega = VTo4x4(v[0:3, 0])
-    quatDot = 0.5 * QOmega * quat
-    vel = v[3:6, 0]
-    posDot = skew(v[0:3]) * pos + vel
-    # The rate vector:
-    rates = mat(zeros( (13,1) ))
-    rates[0:4, 0] = quatDot
-    rates[4:7, 0] = posDot
-    rates[7:13, 0] = PDot
-    return rates
-
-def fWrapper(y, t, parameters):
-   y = mat(y).T
-   dy = rateOfChange(y, t, parameters)
-   return dy.T.A1
-  
-def SCIPY(endtime, dt, state, parameters):
-    times = np.arange(0.0, endtime, dt)
-    y0 = state.T.A1
-    res = scipy.integrate.odeint(fWrapper, y0, times, args=(parameters,))
-    states = []
-    res = res.T
-    r,c =  res.shape
-    for ci in range(0,c):
-      states.append(mat(res[:,ci]).T)
-    return states
-  
-def RK4(endtime, dt, state, parameters):
-    t = 0.0
-    states = []
-    while t < endtime:
-      newstate = mat (zeros( state.shape )) # Create a new object
-
-      #### Runge Kutta integration:
-      k1 = rateOfChange(state,             t, parameters)
-      k2 = rateOfChange(state + 0.5*dt*k1, t, parameters)
-      k3 = rateOfChange(state + 0.5*dt*k1, t, parameters)
-      k4 = rateOfChange(state + dt*k3,     t, parameters)
-      newstate = state + (dt/6.0)*(k1+2*k2+2*k3+k4)
-
-      # Normalize quat:
-      newstate[0:4, 0] = normalizeQuaternion(newstate[0:4, 0])
-      states.append(newstate)
-
-      state = newstate
-
-      t += dt
-      print(state[6,0], t, ' ', (t/endtime)*100.0, '%')
-    return states
+class Simulation:
+    def simulate(self, endtime, dt):
+        """ Evaluate the state of the system over a given time """
+        state = self.initial()
+        times = np.arange(0.0, endtime, dt)
+        y0 = state.T.A1
+        def fWrapper(y, t):
+           y = mat(y).T
+           dy = self.rateOfChange(y, t)
+           return dy.T.A1
+        res = scipy.integrate.odeint(fWrapper, y0, times)
+        states = []
+        res = res.T
+        r,c =  res.shape
+        for ci in range(0,c):
+            states.append(mat(res[:,ci]).T)
+        self.result = states
+        return states
   
 
-def simulate(endtime, dt):
-    PInitial = mat( zeros((6,1)) )
-    posInitial = mat(array([-1.2, -1.3, 2.8])).T
-    quatInitial = rotateAbout(mat(array([0.2, 1.0, 0.4])).T, 0.5)
-    # Parameters:
-    gravity = mat( array([0,0,-9.81]) ).T
-    massI = mat(eye(6)) * 1.01 # Mass matrix
-    parameters = (massI, gravity)
+class BouncingCube(Simulation):
+    """ Simulation of a bouncing cube """
+    def __init__(self):
+        # Parameters:
+        self.gravity = mat( array([0,0,-9.81]) ).T
+        self.massI = mat(eye(6)) * 1.01 # Mass matrix
+
+    def initial(self):
+        """ Return initial pose """
+        PInitial = mat( zeros((6, 1)) )
+        posInitial = mat(array([-1.2, -1.3, 2.8])).T
+        quatInitial = rotateAbout(mat(array([0.2, 1.0, 0.4])).T, 0.5)
+
+        # The state vector!
+        state = mat(zeros( (13,1) ))
+        state[0:4, 0] = quatInitial
+        state[4:7, 0] = posInitial
+        state[7:13, 0] = PInitial
+        return state
+
+    def rateOfChange(self, states, thetime):
+        """ Calculates rate of change given the current states. """
+        quat = states[0:4,  0] # Orientation (4)
+        pos  = states[4:7,  0] # Position (3)
+        P    = states[7:13, 0] # Momentum (6)
+        massI, gravity = self.massI, self.gravity
+        # Rigid body parts:
+        # Forward Kinematic chain:
+        H = homogeneous(quatToR(quat), pos) # Forward kinematics
+
+        AdjX2 = mat(eye(6)) # The connectionpoint in the real world
+        adjAdjX2_1 = adjoint(AdjX2[0:6,0])
+        adjAdjX2_2 = adjoint(AdjX2[0:6,1])
+        adjAdjX2_3 = adjoint(AdjX2[0:6,2])
+        adjAdjX2_4 = adjoint(AdjX2[0:6,3])
+        adjAdjX2_5 = adjoint(AdjX2[0:6,4])
+        adjAdjX2_6 = adjoint(AdjX2[0:6,5])
+        AdjInv2 = Adjoint(H.I)
+        M2 = AdjInv2.T * (massI * AdjInv2) # Transfor mass to base frame
+        MassMatrix = M2
+
+        wrenchGrav2 = mat( zeros((1,6)) )
+        wrenchGrav2[0, 0:3] = -cross(gravity, pos).T
+        wrenchGrav2[0, 3:6] = gravity.T
+
+        Bk = mat( zeros( (6,6) ))
+        Bk[0:3, 0:3] = skew(P[0:3, 0])
+        Bk[3:6, 0:3] = skew(P[3:6, 0])
+        Bk[0:3, 3:6] = skew(P[3:6, 0])
+
+        # TODO: do this a cholesky:
+        v = np.linalg.solve(MassMatrix, P) # Matrix inverse like thingy !
+
+        T2_00 = v # Calculate the relative twist!
+        TM2 = T2_00.T * M2
+        twistExternal = T2_00 # Twist van het blokje
+        TMSum2 = TM2
 
-    # The state vector!
-    state = mat(zeros( (13,1) ))
-    state[0:4, 0] = quatInitial
-    state[4:7, 0] = posInitial
-    state[7:13, 0] = PInitial
+        PDotBodies = mat( zeros( (6,1)) )
+        PDotBodies[0,0] = TMSum2 * (adjAdjX2_1 * T2_00)
+        PDotBodies[1,0] = TMSum2 * (adjAdjX2_2 * T2_00)
+        PDotBodies[2,0] = TMSum2 * (adjAdjX2_3 * T2_00)
+        PDotBodies[3,0] = TMSum2 * (adjAdjX2_4 * T2_00)
+        PDotBodies[4,0] = TMSum2 * (adjAdjX2_5 * T2_00)
+        PDotBodies[5,0] = TMSum2 * (adjAdjX2_6 * T2_00)
+        
+        PDot = -PDotBodies - Bk * v
+        PDot += wrenchGrav2.T
+        
+        ##### Contact wrench part:
+        HB_W = H # Is H-matrix van het blokje
+        WrenchB = mat(zeros( (1,6) ))
+        for px in [-0.5, 0.5]:
+          for py in [-0.5, 0.5]:
+            for pz in [-0.5, 0.5]:
+              HB1_B = homogeneous(mat(eye(3)), mat([px,py,pz]).T)
+              HB1_W = HB_W * HB1_B
+              HW1_W = homogeneous(mat(eye(3)), HB1_W[0:3,3])
+              HW_W1 = HW1_W.I
+              HB_W1 = HW_W1 * HB_W
+        
+              AdjHB_W1 = Adjoint(HB_W1)
+              TB_W1_W1 = AdjHB_W1 * twistExternal
+              z = HB1_W[2, 3]
+              vx, vy, vz = TB_W1_W1[3:6, 0].A1
+              if True:
+                # Contact forces:
+                Fx = 0 #np.exp(-5.0*vx)
+                Fy = 0 # np.exp(-5.0*vy)
+                Fz = np.exp(-z*10.0)
+              else:
+                Fx = 0.0
+                Fy = 0.0
+                Fz = 0.0
+              # TODO: reflect impulse
+              WrenchW1 = mat([0,0,0,0,0,Fz])
+              # Transform it back:
+              WrenchB += (AdjHB_W1.T * WrenchW1.T).T
+        ##### End of contact wrench
+
+        PDot += (WrenchB * AdjInv2).T
+
+        # Position and orientation rates:
+        QOmega = VTo4x4(v[0:3, 0])
+        quatDot = 0.5 * QOmega * quat
+        vel = v[3:6, 0]
+        posDot = skew(v[0:3]) * pos + vel
+        # The rate vector:
+        rates = mat(zeros( (13,1) ))
+        rates[0:4, 0] = quatDot
+        rates[4:7, 0] = posDot
+        rates[7:13, 0] = PDot
+        return rates
 
-    return SCIPY(endtime, dt, state, parameters)
+    def draw(self, state):
+        Dicequat = state[0:4, 0]
+        Dicepos = state[4:7, 0]
+
+        x, y, z = Dicepos.A1
+        R = quatToR(Dicequat)
+
+        glTranslatef(x, y, z)
+        # Trick to rotate the openGL matrix:
+        r = R.A1
+        rotR = (r[0], r[3], r[6], 0.0,
+              r[1], r[4], r[7], 0.0,
+              r[2], r[5], r[8], 0.0,
+              0.0,  0.0,  0.0,  1.0)
+        glMultMatrixd(rotR)
+      
+        drawCube(0.6)
+
+
+class RollingPendulum(Simulation):
+    """ A 2D pendulum with a rolling contact. """
+    def __init__(self):
+        self.R = 0.01
+        self.L = 1
+        self.M = 1
+        self.g = 9.81
+
+    def initial(self):
+        i = mat(zeros((2,1)))
+        i[0, 0] = 
+        return i
+
+    def rateOfChange(self, states, thetime):
+        phi, omega = states[0:2, 0]
+        rates = mat(zeros((2,1)))
+        return rates
+
+    def draw(self, state):
+        pass
+        #drawCube(0.6)
+
+
+class WobbelingWheel(Simulation):
+    """ A wheel pushed sideways over a surface """
+    def __init__(self):
+        self.r1 = 0.5
+        self.r2 = 0.05
+
+    def initial(self):
+        i = mat(zeros((5,1)))
+        return i
+
+    def rateOfChange(self, states, thetime):
+        x, y = states[0:2, 0] 
+        rates = mat(zeros((5,1)))
+        return rates
+
+    def draw(self, state):
+        pass
+        #drawCube(0.6)
+
 
 class W(QGLWidget):
-  time = 0.0
-  index = 0
-  def __init__(self, states, dt, parent=None):
-    super(W, self).__init__(parent)
-    self.firstRun = True
-    self.savePNGS = False
-    self.dt = dt
-    self.resize(500,500)
-    self.states = states
-    self.UP()
-    t = QTimer(self)
-    t.timeout.connect(self.UP)
-    t.start(self.dt*1000.0)
+    time = 0.0
+    index = 0
+    def __init__(self, sim):
+        super().__init__()
+        self.firstRun = True
+        self.savePNGS = False
+        self.index = 0
+        self.sim = sim
+        self.resize(500,500)
+        self.UP()
+        t = QTimer(self)
+        t.timeout.connect(self.UP)
+        t.start(40)
 
-  def UP(self):
-    self.time += self.dt
-    if self.states:
-      state = self.states[self.index]
-      self.Dicequat = state[0:4, 0]
-      self.Dicepos = state[4:7, 0]
-      self.index += 1
-      if self.index == len(self.states):
-        self.index = 0
-        self.firstRun = False
-    # Paint:
-    self.update()
-    if self.firstRun:
-       # Create png images for the movie:
-       if self.savePNGS:
-          pm = self.renderPixmap()
-          pm.save('image'+str(self.index)+'.png')
+    def UP(self):
+        if self.sim.result:
+            if self.index + 1 < len(self.sim.result):
+                self.index += 1
+            else:
+                self.index = 0
+        # Paint:
+        self.update()
+        
+        if self.firstRun:
+           # Create png images for the movie:
+           if self.savePNGS:
+              pm = self.renderPixmap()
+              pm.save('image'+str(self.index)+'.png')
 
-  def initializeGL(self):
+    def initializeGL(self):
       glClearColor(0.0, 0.5, 0.0, 1.0)
       glEnable(GL_DEPTH_TEST)
       glDepthFunc(GL_LESS)
       glShadeModel(GL_SMOOTH)
-  def resizeGL(self,w,h):
+
+    def resizeGL(self,w,h):
       glViewport(0, 0, w, h)
       glMatrixMode(GL_PROJECTION)
       glLoadIdentity()
       gluPerspective(45.0, float(w)/float(h), 0.1, 100.0)
       glMatrixMode(GL_MODELVIEW)
-  def paintGL(self):
+
+    def paintGL(self):
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Clear buffers
       glLoadIdentity() # Reset The View
-
-      glLoadIdentity()
       glTranslatef(0.0,-2.0,-10.0) # Move Left And Into The Screen
       glRotatef(-90.0, 1.0, 0.0, 0.0)
       drawFloor(2.0, 0.0)
@@ -375,32 +422,22 @@
       self.renderText(1.0, 0.0, 0.0, 'X')
       self.renderText(0.0, 1.0, 0.0, 'Y')
       self.renderText(0.0, 0.0, 1.0, 'Z')
-
       self.renderText(0.0,0.0,1.2,str(self.time))
+      if self.sim.result:
+          self.sim.draw(self.sim.result[self.index])
 
-      x,y,z = self.Dicepos.A1
-      R = quatToR(self.Dicequat)
 
-      glTranslatef(x, y, z)
-      # Trick to rotate the openGL matrix:
-      r = R.A1
-      rotR = (r[0], r[3], r[6], 0.0,
-              r[1], r[4], r[7], 0.0,
-              r[2], r[5], r[8], 0.0,
-              0.0,  0.0,  0.0,  1.0)
-      glMultMatrixd(rotR)
-      
-      drawCube(0.6)
-
-et = 20.0
+et = 1.5
 dt = 0.04
+# sim = BouncingCube()
+sim = WobbelingWheel()
 print('starting integration... endtime =', et, ' stepsize =', dt)
 t0 = time.time()
-states = simulate(et, dt)
+states = sim.simulate(et, dt)
 t1 = time.time()
-print('That was heavy, it took me ', t1-t0, ' seconds!')
+print('That was heavy, it took me ', t1 -t0, ' seconds!')
 app = QApplication(sys.argv)
-w = W(states, dt)
+w = W(sim)
 w.show()
 sys.exit(app.exec_())
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/other/diagramitems.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,437 @@
+"""
+ Contains all blocks that can be used to build models.
+"""
+
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+
+def uniqify(name, names):
+   newname, i = name, 1
+   while newname in names: newname, i = name + str(i), i + 1
+   return newname
+
+def enum(**enums):
+   return type('Enum', (), enums)
+
+Position = enum(TOP=0, TOP_RIGHT=1, RIGHT=2, BOTTOM_RIGHT=3, BOTTOM=4, BOTTOM_LEFT=5, LEFT=6, TOP_LEFT=7)
+
+def buildPath(pts):
+   path = QPainterPath(pts[0])
+   for pt in pts[1:]: path.lineTo(pt)
+   return path
+
+def equalSpace(n, l, offset=15):
+   if n == 1:
+      return [l / 2]
+   elif n > 1:
+      return [offset + (l - offset*2)/(n - 1)*i for i in range(n)]
+   return []
+
+class Connection(QGraphicsPathItem):
+   """ A connection between blocks """
+   def __init__(self, fromPort=None, toPort=None):
+      super(Connection, self).__init__()
+      self.pos2 = self.fromPort = self.toPort = None
+      self.setFlags(self.ItemIsSelectable | self.ItemClipsToShape)
+      pen = QPen(Qt.blue, 2, cap=Qt.RoundCap)
+      self.setPen(pen)
+      self.arrowhead = QGraphicsPathItem(self)
+      self.arrowhead.setPath(buildPath([QPointF(0.0, 0.0), QPointF(-6.0, 10.0), QPointF(6.0, 10.0), QPointF(0.0, 0.0)]))
+      self.arrowhead.setPen(pen)
+      self.arrowhead.setBrush(QBrush(pen.color()))
+      self.vias = []
+      self.setFromPort(fromPort)
+      self.setToPort(toPort)
+   def getDict(self):
+      d = {}
+      d['fromBlock'] = self.fromPort.block.name
+      d['fromPort'] = self.fromPort.name
+      d['toBlock'] = self.toPort.block.name
+      d['toPort'] = self.toPort.name
+      return d
+   Dict = property(getDict)
+   def myDelete(self):
+      scene = self.scene()
+      if scene:
+         self.setFromPort(None)
+         self.setToPort(None)
+         scene.removeItem(self)
+   def setFromPort(self, fromPort):
+      if self.fromPort:
+         self.fromPort.posCallbacks.remove(self.setBeginPos)
+         self.fromPort.connection = None
+      self.fromPort = fromPort
+      if self.fromPort:
+         self.fromPort.connection = self
+         self.updateLineStukken()
+         self.fromPort.posCallbacks.append(self.setBeginPos)
+   def setToPort(self, toPort):
+      if self.toPort:
+         self.toPort.posCallbacks.remove(self.setEndPos)
+         self.toPort.connection = None
+      self.toPort = toPort
+      if self.toPort:
+         self.setEndPos(toPort.scenePos())
+         self.toPort.connection = self
+         self.toPort.posCallbacks.append(self.setEndPos)
+   def getPos1(self):
+      if self.fromPort:
+         return self.fromPort.scenePos()
+   def setBeginPos(self, pos1): self.updateLineStukken()
+   def setEndPos(self, endpos):
+      self.pos2 = endpos
+      self.updateLineStukken()
+   def itemChange(self, change, value):
+      if change == self.ItemSelectedHasChanged:
+         for via in self.vias:
+            via.setVisible(value)
+      return super(Connection, self).itemChange(change, value)
+   def shape(self): return self.myshape
+   def updateLineStukken(self):
+      """
+         This algorithm determines the optimal routing of all signals.
+         TODO: implement nice automatic line router
+      """
+      pos1 = self.getPos1()
+      pos2 = self.pos2
+      if pos1 is None or pos2 is None:
+         return
+      scene = self.scene()
+      vias = [pos1 + QPointF(20, 0)] + self.vias + [pos2 + QPointF(-20, 0)]
+      if scene:
+         litem = QGraphicsLineItem()
+         litem.setFlags(self.ItemIsSelectable)
+         scene.addItem(litem)
+         for p1, p2 in zip(vias[:-1], vias[1:]):
+            line = QLineF(p1, p2)
+            litem.setLine(line)
+            citems = scene.collidingItems(litem)
+            citems = [i for i in citems if type(i) is Block]
+         scene.removeItem(litem)
+      pts = [pos1] + vias + [pos2]
+      self.arrowhead.setPos(pos2)
+      self.arrowhead.setRotation(90)
+      p = buildPath(pts)
+      self.setPath(p)
+      """ Create a shape outline using the path stroker """
+      s = super(Connection, self).shape()
+      pps = QPainterPathStroker()
+      pps.setWidth(10)
+      self.myshape = pps.createStroke(s).simplified()
+
+class PortItem(QGraphicsPathItem):
+   """ Represents a port to a subsystem """
+   def __init__(self, name, block):
+      super(PortItem, self).__init__(block)
+      self.textItem = QGraphicsTextItem(self)
+      self.connection = None
+      self.block = block
+      self.setCursor(QCursor(Qt.CrossCursor))
+      self.setPen(QPen(Qt.blue, 2, cap=Qt.RoundCap))
+      self.name = name
+      self.posCallbacks = []
+      self.setFlag(self.ItemSendsScenePositionChanges, True)
+   def getName(self): return self.textItem.toPlainText()
+   def setName(self, name):
+      self.textItem.setPlainText(name)
+      rect = self.textItem.boundingRect()
+      lw, lh = rect.width(), rect.height()
+      lx = 3 if type(self) is InputPort else -3 - lw
+      self.textItem.setPos(lx, -lh / 2)
+   name = property(getName, setName)
+   def getDict(self): 
+      return {'name': self.name}
+   Dict = property(getDict)
+   def itemChange(self, change, value):
+      if change == self.ItemScenePositionHasChanged:
+         for cb in self.posCallbacks: cb(value)
+         return value
+      return super(PortItem, self).itemChange(change, value)
+
+class OutputPort(PortItem):
+   def __init__(self, name, block, d=10.0):
+      super(OutputPort, self).__init__(name, block)
+      self.setPath(buildPath([QPointF(0.0, -d), QPointF(d, 0), QPointF(0.0, d)]))
+   def mousePressEvent(self, event):
+      self.scene().startConnection(self)
+
+class InputPort(PortItem):
+   def __init__(self, name, block, d=10.0):
+      super(InputPort, self).__init__(name, block)
+      self.setPath(buildPath([QPointF(-d, -d), QPointF(0, 0), QPointF(-d, d)]))
+
+class Handle(QGraphicsEllipseItem):
+   """ A handle that can be moved by the mouse """
+   def __init__(self, dx=10.0, parent=None):
+      super(Handle, self).__init__(QRectF(-0.5*dx,-0.5*dx,dx,dx), parent)
+      self.setBrush(QBrush(Qt.white))
+      self.setFlags(self.ItemIsMovable)
+      self.setZValue(1)
+      self.setVisible(False)
+      self.setCursor(QCursor(Qt.SizeFDiagCursor))
+   def mouseMoveEvent(self, event):
+      """ Move function without moving the other selected elements """
+      p = self.mapToParent(event.pos())
+      self.setPos(p)
+
+class ResizeSelectionHandle(Handle):
+   def __init__(self, position, block):
+      super(ResizeSelectionHandle, self).__init__(dx=12, parent=block)
+      self.position = position
+      self.block = block
+      if position in [Position.TOP_LEFT, Position.BOTTOM_RIGHT]:
+         self.setCursor(QCursor(Qt.SizeFDiagCursor))
+      elif position in [Position.TOP_RIGHT, Position.BOTTOM_LEFT]:
+         self.setCursor(QCursor(Qt.SizeBDiagCursor))
+      elif position in [Position.TOP, Position.BOTTOM]:
+         self.setCursor(QCursor(Qt.SizeVerCursor))
+      elif position in [Position.LEFT, Position.RIGHT]:
+         self.setCursor(QCursor(Qt.SizeHorCursor))
+   def mouseMoveEvent(self, event):
+      self.block.sizerMoveEvent(self, event.scenePos())
+
+class Block(QGraphicsRectItem):
+   """ Represents a block in the diagram. """
+   def __init__(self, name='Untitled', parent=None):
+      super(Block, self).__init__(parent)
+      self.selectionHandles = [ResizeSelectionHandle(i, self) for i in range(8)]
+      # Properties of the rectangle:
+      self.setPen(QPen(Qt.blue, 2))
+      self.setBrush(QBrush(Qt.lightGray))
+      self.setFlags(self.ItemIsSelectable | self.ItemIsMovable | self.ItemSendsScenePositionChanges)
+      self.setCursor(QCursor(Qt.PointingHandCursor))
+      self.setAcceptHoverEvents(True)
+      self.label = QGraphicsTextItem(name, self)
+      self.name = name
+      # Create corner for resize:
+      button = QPushButton('+in')
+      button.clicked.connect(self.newInputPort)
+      self.buttonItemAddInput = QGraphicsProxyWidget(self)
+      self.buttonItemAddInput.setWidget(button)
+      self.buttonItemAddInput.setVisible(False)
+      button = QPushButton('+out')
+      button.clicked.connect(self.newOutputPort)
+      self.buttonItemAddOutput = QGraphicsProxyWidget(self)
+      self.buttonItemAddOutput.setWidget(button)
+      self.buttonItemAddOutput.setVisible(False)
+      # Inputs and outputs of the block:
+      self.inputs = []
+      self.outputs = []
+      self.changeSize(2,2)
+   def editParameters(self):
+      pd = ParameterDialog(self, self.window())
+      pd.exec_()
+   def newInputPort(self):
+      names = [i.name for i in self.inputs + self.outputs]
+      self.addInput(InputPort(uniqify('in', names), self))
+   def newOutputPort(self):
+      names = [i.name for i in self.inputs + self.outputs]
+      self.addOutput(OutputPort(uniqify('out', names), self))
+   def setName(self, name): self.label.setPlainText(name)
+   def getName(self): return self.label.toPlainText()
+   name = property(getName, setName)
+   def getDict(self):
+      d = {'x': self.scenePos().x(), 'y': self.scenePos().y()}
+      rect = self.rect()
+      d.update({'width': rect.width(), 'height': rect.height()})
+      d['name'] = self.name
+      d['inputs'] = [inp.Dict for inp in self.inputs]
+      d['outputs'] = [outp.Dict for outp in self.outputs]
+      return d
+   def setDict(self, d):
+      self.name = d['name']
+      self.setPos(d['x'], d['y'])
+      self.changeSize(d['width'], d['height'])
+      for inp in d['inputs']:
+         self.addInput(InputPort(inp['name'], self))
+      for outp in d['outputs']:
+         self.addOutput(OutputPort(outp['name'], self))
+   Dict = property(getDict, setDict)
+   def addInput(self, i):
+      self.inputs.append(i)
+      self.updateSize()
+   def addOutput(self, o):
+      self.outputs.append(o)
+      self.updateSize()
+   def contextMenuEvent(self, event):
+      menu = QMenu()
+      pa = menu.addAction('Parameters')
+      pa.triggered.connect(self.editParameters)
+      menu.exec_(event.screenPos())
+   def itemChange(self, change, value):
+      if change == self.ItemSelectedHasChanged:
+         for child in [self.buttonItemAddInput, self.buttonItemAddOutput]:
+            child.setVisible(value)
+         if value:
+            self.repositionAndShowHandles()
+         else:
+            [h.setVisible(False) for h in self.selectionHandles]
+
+      return super(Block, self).itemChange(change, value)
+   def hoverEnterEvent(self, event):
+      if not self.isSelected():
+         self.repositionAndShowHandles()
+      super(Block, self).hoverEnterEvent(event)
+   def hoverLeaveEvent(self, event):
+      if not self.isSelected():
+         [h.setVisible(False) for h in self.selectionHandles]
+      super(Block, self).hoverLeaveEvent(event)
+   def myDelete(self):
+      for p in self.inputs + self.outputs:
+         if p.connection: p.connection.myDelete()
+      self.scene().removeItem(self)
+   def repositionAndShowHandles(self):
+         r = self.rect()
+         self.selectionHandles[Position.TOP_LEFT].setPos(r.topLeft())
+         self.selectionHandles[Position.TOP].setPos(r.center().x(), r.top())
+         self.selectionHandles[Position.TOP_RIGHT].setPos(r.topRight())
+         self.selectionHandles[Position.RIGHT].setPos(r.right(), r.center().y())
+         self.selectionHandles[Position.BOTTOM_RIGHT].setPos(r.bottomRight())
+         self.selectionHandles[Position.BOTTOM].setPos(r.center().x(), r.bottom())
+         self.selectionHandles[Position.BOTTOM_LEFT].setPos(r.bottomLeft())
+         self.selectionHandles[Position.LEFT].setPos(r.left(), r.center().y())
+         for h in self.selectionHandles:
+            h.setVisible(True)
+   def sizerMoveEvent(self, handle, pos):
+      r = self.rect().translated(self.pos())
+      if handle.position == Position.TOP_LEFT: r.setTopLeft(pos)
+      elif handle.position == Position.TOP: r.setTop(pos.y())
+      elif handle.position == Position.TOP_RIGHT: r.setTopRight(pos)
+      elif handle.position == Position.RIGHT: r.setRight(pos.x())
+      elif handle.position == Position.BOTTOM_RIGHT: r.setBottomRight(pos)
+      elif handle.position == Position.BOTTOM: r.setBottom(pos.y())
+      elif handle.position == Position.BOTTOM_LEFT: r.setBottomLeft(pos)
+      elif handle.position == Position.LEFT: r.setLeft(pos.x())
+      else:
+         print('invalid position')
+      self.setCenterAndSize(r.center(), r.size())
+      self.repositionAndShowHandles()
+   def updateSize(self):
+      rect = self.rect()
+      h, w = rect.height(), rect.width()
+      self.buttonItemAddInput.setPos(0, h + 4)
+      self.buttonItemAddOutput.setPos(w+10, h+4)
+      for inp, y in zip(self.inputs, equalSpace(len(self.inputs), h)):
+         inp.setPos(0.0, y)
+      for outp, y in zip(self.outputs, equalSpace(len(self.outputs), h)):
+         outp.setPos(w, y)
+   def setCenterAndSize(self, center, size):
+      self.changeSize(size.width(), size.height())
+      p = QPointF(size.width(), size.height())
+      self.setPos(center - p / 2)
+   def changeSize(self, w, h):
+      minw = 150
+      minh = 50
+      h = minh if h < minh else h
+      w = minw if w < minw else w
+      self.setRect(0.0, 0.0, w, h)
+      rect = self.label.boundingRect()
+      self.label.setPos((w - rect.width()) / 2, (h - rect.height()) / 2)
+      self.updateSize()
+
+class CodeBlock(Block):
+   def __init__(self, name='Untitled', parent=None):
+      super(CodeBlock, self).__init__(name, parent)
+      self.code = ''
+   def setDict(self, d):
+      super(CodeBlock, self).setDict(d)
+      self.code = d['code']
+   def getDict(self):
+      d = super(CodeBlock, self).getDict()
+      d['code'] = self.code
+      return d
+   def gencode(self):
+      c = ['def {0}():'.format(self.name)]
+      if self.code:
+         c += indent(self.code.split('\n'))
+      else:
+         c += indent(['pass'])
+      return c
+
+class DiagramBlock(Block):
+   def __init__(self, name='Untitled', parent=None):
+      super(DiagramBlock, self).__init__(name, parent)
+      self.subModel = DiagramScene()
+      self.subModel.containingBlock = self
+   def setDict(self, d):
+      self.subModel.Dict = d['submodel']
+   def mouseDoubleClickEvent(self, event):
+      # descent into child diagram
+      #self.editParameters()
+      print('descent')
+      scene = self.scene()
+      if scene:
+         for view in scene.views():
+            view.diagram = self.subModel
+            view.zoomAll()
+
+class DiagramScene(QGraphicsScene):
+   """ A diagram scene consisting of blocks and connections """
+   structureChanged = pyqtSignal()
+   def __init__(self):
+      super(DiagramScene, self).__init__()
+      self.startedConnection = None
+
+   blocks = property(lambda sel: [i for i in sel.items() if isinstance(i, Block)])
+   connections = property(lambda sel: [i for i in sel.items() if type(i) is Connection])
+   def addItem(self, item):
+      super(DiagramScene, self).addItem(item)
+      if isinstance(item, Block):
+         self.structureChanged.emit()
+   def removeItem(self, item):
+      super(DiagramScene, self).removeItem(item)
+      if isinstance(item, Block):
+         self.structureChanged.emit()
+   def setDict(self, d):
+      for block in d['blocks']:
+         b = Block()
+         self.addItem(b)
+         b.Dict = block
+      for con in d['connections']:
+         fromPort = self.findPort(con['fromBlock'], con['fromPort'])
+         toPort = self.findPort(con['toBlock'], con['toPort'])
+         self.addItem(Connection(fromPort, toPort))
+   def getDict(self):
+      return {'blocks': [b.Dict for b in self.blocks], 'connections': [c.Dict for c in self.connections]}
+   Dict = property(getDict, setDict)
+   def gencode(self):
+      c = []
+      for b in self.blocks:
+         c += b.gencode()
+      for b in self.blocks:
+         c.append('{0}()'.format(b.name))
+      return c
+   def findPort(self, blockname, portname):
+      block = self.findBlock(blockname)
+      if block:
+         for port in block.inputs + block.outputs:
+            if port.name == portname: return port
+   def findBlock(self, blockname):
+      for block in self.blocks:
+         if block.name == blockname: return block
+   def uniqify(self, name):
+      blocknames = [item.name for item in self.blocks]
+      return uniqify(name, blocknames)
+   def mouseMoveEvent(self, event):
+      if self.startedConnection:
+         pos = event.scenePos()
+         self.startedConnection.setEndPos(pos)
+      super(DiagramScene, self).mouseMoveEvent(event)
+   def mouseReleaseEvent(self, event):
+      if self.startedConnection:
+         for item in self.items(event.scenePos()):
+            if type(item) is InputPort and item.connection == None:
+               self.startedConnection.setToPort(item)
+               self.startedConnection = None
+               return
+         self.startedConnection.myDelete()
+         self.startedConnection = None
+      super(DiagramScene, self).mouseReleaseEvent(event)
+   def startConnection(self, port):
+      self.startedConnection = Connection(port, None)
+      pos = port.scenePos()
+      self.startedConnection.setEndPos(pos)
+      self.addItem(self.startedConnection)
+   def deleteItems(self):
+      for item in list(self.selectedItems()): item.myDelete()
+
--- a/python/ppci/__init__.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/ppci/__init__.py	Wed Nov 27 08:06:42 2013 +0100
@@ -12,4 +12,3 @@
 from .common import SourceLocation, SourceRange, Token
 from .errors import CompilerError, DiagnosticsManager
 from .errors import printError
-
--- a/python/ppci/common.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/ppci/common.py	Wed Nov 27 08:06:42 2013 +0100
@@ -10,6 +10,7 @@
             loc = SourceLocation('', 0, 0, 0)
         assert type(loc) is SourceLocation
         self.loc = loc
+
     def __repr__(self):
         return 'Token({0}, {1})'.format(self.typ, self.val)
 
@@ -26,4 +27,3 @@
 
 
 SourceRange = namedtuple('SourceRange', ['p1', 'p2'])
-
--- a/python/st-flash.py	Sun Nov 24 11:24:15 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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)
-    r = hf.regions[0]
-    dev.writeFlash(r.address, r.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()
-
--- a/python/st-util.py	Sun Nov 24 11:24:15 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-#!/usr/bin/python
-
-import sys
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-import stlink, devices, stm32, usb
-from devices import Interface, Device
-from hexedit import HexEdit
-
-class InformationDialog(QDialog):
-   def __init__(self, parent):
-      super().__init__(parent)
-      self.setWindowTitle('Info')
-      fl = QFormLayout(self)
-      if parent.stl:
-         fl.addRow('ST link version:', QLabel(parent.stl.Version))
-         fl.addRow('Chip id:', QLabel('0x{0:X}'.format(parent.stl.ChipId)))
-         fl.addRow('Current mode:', QLabel(parent.stl.CurrentModeString))
-         fl.addRow('Status:', QLabel(parent.stl.StatusString))
-
-class RegisterModel(QAbstractTableModel):
-    def __init__(self):
-      super().__init__()
-      self.regCount = 15
-      self.device = None
-
-    def rowCount(self, parent):
-      if parent.isValid():
-         return 0
-      if self.device:
-         return 21 # TODO make variable
-      else:
-         return 0
-
-    def setDevice(self, dev):
-      self.device = dev
-      self.modelReset.emit()
-
-    def columnCount(self, parent):
-      if parent.isValid():
-         return 0
-      return 2
-
-    def data(self, index, role):
-      if index.isValid():
-         row, col = index.row(), index.column()
-         if role == Qt.DisplayRole:
-            if col == 0:
-                if row == 15:
-                    return 'PC'
-                elif row == 14:
-                    return 'LR'
-                elif row == 13:
-                    return 'SP'
-                else:
-                    return 'R{0}'.format(row)
-            elif col == 1:
-               v = self.device.iface.read_reg(row)
-               return '0x{0:X}'.format(v)
-
-    def setData(self, index, value, role):
-      if index.isValid():
-         row = index.row()
-         col = index.column()
-         if role == Qt.EditRole and col == 1:
-            value = int(value, 16)
-            self.device.iface.write_reg(row, value)
-            return True
-      return False
-
-    def flags(self, index):
-      if index.isValid():
-         row = index.row()
-         col = index.column()
-         if col == 1:
-            return super().flags(index) | Qt.ItemIsEditable
-      return super().flags(index)
-
-    def refresh(self):
-      if self.device:
-         fromIndex = self.index(0, 1)
-         toIndex = self.index(21, 1)
-         self.dataChanged.emit(fromIndex, toIndex)
-
-
-class RegisterView(QTableView):
-    def __init__(self):
-      super().__init__()
-      self.mdl = RegisterModel()
-      self.setModel(self.mdl)
-
-    def refresh(self):
-      if self.mdl.device:
-         self.setEnabled(not self.mdl.device.Running)
-      self.mdl.refresh()
-
-
-class MemoryView(QWidget):
-    BlockSize = 0x100
-    def __init__(self):
-      super().__init__()
-      l = QVBoxLayout(self)
-      l2 = QHBoxLayout()
-      l2.addWidget(QLabel('Address'))
-      self.addressLine = QLineEdit()
-      self.addressLine.setInputMask('Hhhhhhhh')
-      l2.addWidget(self.addressLine)
-      upButton = QPushButton('up')
-      l2.addWidget(upButton)
-      upButton.clicked.connect(self.doUp)
-      downButton = QPushButton('down')
-      downButton.clicked.connect(self.doDown)
-      l2.addWidget(downButton)
-      l.addLayout(l2)
-      self.device = None
-      self.hexEdit = HexEdit()
-      self.Address = 0x8000000
-      l.addWidget(self.hexEdit)
-      self.addressLine.returnPressed.connect(self.refresh)
-
-    def refresh(self):
-        address = self.Address
-        if self.device:
-            data = self.device.iface.read_mem32(address, self.BlockSize)
-        else:
-            data = bytearray(self.BlockSize)
-        self.hexEdit.bv.Data = data
-        self.hexEdit.bv.Offset = address
-
-    def getAddress(self):
-          txt = self.addressLine.text()
-          return int(txt, 16)
-
-    def doUp(self):
-        self.Address -= self.BlockSize
-
-    def doDown(self):
-        self.Address += self.BlockSize
-
-    def setAddress(self, address):
-        self.addressLine.setText('{0:08X}'.format(address))
-        self.refresh()
-    Address = property(getAddress, setAddress)
-    def setDevice(self, dev):
-      self.device = dev
-      self.Address = 0x8000000
-
-
-class DebugToolbar(QToolBar):
-   statusChange = pyqtSignal()
-   codePosition = pyqtSignal(int)
-   def __init__(self):
-      super().__init__()
-      self.device = None
-      # generate actions:
-      def genAction(name, callback):
-         a = QAction(name, self)
-         a.triggered.connect(callback)
-         self.addAction(a)
-         return a
-      self.stepAction = genAction('Step', self.doStep)
-      self.runAction = genAction('Run', self.doRun)
-      self.stopAction = genAction('Stop', self.doHalt)
-      self.resetAction = genAction('Reset', self.doReset)
-      self.enableTraceAction = genAction('Enable trace', self.doEnableTrace)
-      self.updateEnables()
-   def updateEnables(self):
-      if self.device:
-         self.resetAction.setEnabled(True)
-         self.enableTraceAction.setEnabled(True)
-         self.runAction.setEnabled(not self.device.Running)
-         self.stepAction.setEnabled(not self.device.Running)
-         self.stopAction.setEnabled(self.device.Running)
-         self.statusChange.emit()
-         if not self.device.Running:
-            PC = 15
-            v = self.device.iface.read_reg(PC)
-            self.codePosition.emit(v)
-      else:
-         self.resetAction.setEnabled(False)
-         self.enableTraceAction.setEnabled(False)
-         self.runAction.setEnabled(False)
-         self.stepAction.setEnabled(False)
-         self.stopAction.setEnabled(False)
-   def doStep(self):
-      self.device.iface.step()
-      self.updateEnables()
-   def doReset(self):
-      self.device.iface.reset()
-      self.updateEnables()
-   def doRun(self):
-      self.device.iface.run()
-      self.updateEnables()
-   def doHalt(self):
-      self.device.iface.halt()
-      self.updateEnables()
-   def doEnableTrace(self):
-      self.device.iface.traceEnable()
-      self.updateEnables()
-   def setDevice(self, dev):
-      self.device = dev
-      self.updateEnables()
-
-
-class FlashTool(QWidget):
-   def __init__(self):
-      super().__init__()
-      # TODO!
-
-
-class DeviceTreeModel(QAbstractItemModel):
-   def __init__(self):
-      super().__init__()
-      self.chipPixmap = QPixmap('icons/chip.png').scaled(32, 32)
-      self.hardwarePixmap = QPixmap('icons/hardware.png').scaled(32, 32)
-      self.refresh()
-   def refresh(self):
-      """ Check all usb interfaces for interfaces """
-      self.interfaces = devices.createInterfaces()
-      self.devices = []
-      self.modelReset.emit()
-   def addDevice(self, device):
-      if device.iface in [lambda d: d.iface for d in self.devices]:
-         print('device already open')
-         return
-      self.devices.append(device)
-      self.modelReset.emit()
-   def index(self, row, column, parent):
-      if parent.isValid():
-         ip = parent.internalPointer()
-         if isinstance(ip, Interface):
-            devs = [d for d in self.devices if d.iface is ip]
-            return self.createIndex(row, column, devs[row])
-      else:
-         iface = self.interfaces[row]
-         return self.createIndex(row, column, iface)
-      return idx
-   def parent(self, index):
-      if index.isValid():
-         ip = index.internalPointer()
-         if isinstance(ip, Interface):
-            return QModelIndex()
-         elif isinstance(ip, Device):
-            iface = ip.iface
-            row = self.interfaces.index(iface)
-            return self.createIndex(row, 0, iface)
-         return QModelIndex()
-   def rowCount(self, parent):
-      if parent.isValid():
-         # non-root level:
-         ip = parent.internalPointer()
-         if isinstance(ip, Interface):
-            devs = [d for d in self.devices if d.iface is ip]
-            return len(devs)
-      else:
-         # root level:
-         return len(self.interfaces)
-      return 0
-   def columnCount(self, parent):
-      return 1
-   def data(self, index, role):
-      if index.isValid():
-         ip = index.internalPointer()
-         if role == Qt.DisplayRole:
-            return str(ip)
-         elif role == Qt.DecorationRole:
-            if isinstance(ip, Interface):
-               return self.hardwarePixmap
-            if isinstance(ip, Device):
-               return self.chipPixmap
-
-class DeviceExplorer(QTreeView):
-   """ Lists all interfaces plugged in and allows selection """
-   deviceSelected = pyqtSignal(Device)
-   def __init__(self):
-      super().__init__()
-      self.mdl = DeviceTreeModel()
-      self.setModel(self.mdl)
-      self.activated.connect(self.openItem)
-      self.header().close()
-      self.customContextMenuRequested.connect(self.openMenu)
-      self.setContextMenuPolicy(Qt.CustomContextMenu)
-   def openItem(self, idx):
-      if idx.isValid():
-         ip = idx.internalPointer()
-         if isinstance(ip, Interface):
-            if not ip.IsOpen:
-               try:
-                  ip.open()
-               except usb.UsbError as e:
-                  QMessageBox.critical(self, "Error", 'Error opening interface: "{0}"'.format(e))
-               else:
-                  # Try to get a device:
-                  self.mdl.addDevice(ip.createDevice())
-         if isinstance(ip, Device):
-            self.deviceSelected.emit(ip)
-   def openMenu(self, pt):
-      idx = self.indexAt(pt)
-      menu = QMenu()
-      menu.addAction('Refresh', self.mdl.refresh)
-      if idx.isValid():
-         ip = idx.internalPointer()
-         if isinstance(ip, Interface):
-            if ip.IsOpen:
-               def closeInterface():
-                  self.mdl.closeInterface(ip)
-               menu.addAction('Close', closeInterface)
-            else:
-               def openInterface():
-                  ip.open()
-                  # Try to get a device:
-                  self.mdl.addDevice(ip.createDevice())
-               menu.addAction('Open', openInterface)
-         elif isinstance(ip, Device):
-            def selectDevice():
-               self.deviceSelected.emit(ip)
-            menu.addAction('Select', selectDevice)
-      menu.exec(self.mapToGlobal(pt))
-
-class StUtil(QMainWindow):
-   connected = pyqtSignal(bool)
-   def __init__(self):
-      super().__init__()
-      self.stl = None
-      def buildAction(name, callback, shortcut=None):
-         a = QAction(name, self)
-         a.triggered.connect(callback)
-         if shortcut:
-            a.setShortcut(shortcut)
-         return a
-      mb = self.menuBar()
-      fileMenu = mb.addMenu("File")
-      self.connectAction = buildAction('Connect', self.connect)
-      fileMenu.addAction(self.connectAction)
-      self.disconnectAction = buildAction('Disconnect', self.disconnect)
-      fileMenu.addAction(self.disconnectAction)
-
-      self.miscMenu = mb.addMenu("Misc")
-      infoAction = buildAction('Info', self.info)
-      self.miscMenu.addAction(infoAction)
-
-      sb = self.statusBar()
-
-      devexplr = DeviceExplorer()
-      self.setCentralWidget(devexplr)
-      devexplr.deviceSelected.connect(self.handleDeviceSelected)
-
-      self.connected.connect(self.handleConnectedChange)
-      self.connected.emit(False)
-   def handleDeviceSelected(self, dev):
-      self.dev = dev
-      self.handleConnectedChange(True)
-   def handleConnectedChange(self, state):
-      self.miscMenu.setEnabled(state)
-      self.connectAction.setEnabled(not state)
-      self.disconnectAction.setEnabled(state)
-      msg = 'Connected!' if state else 'Disconnected!'
-      self.statusBar().showMessage(msg)
-   def info(self):
-      infoDialog = InformationDialog(self)
-      infoDialog.exec()
-   def connect(self):
-      try:
-         self.stl = stlink.STLink()
-         self.stl.open()
-      except (stlink.STLinkException, usb.UsbError) as e:
-         QMessageBox.warning(self, "Error", str(e))
-         self.stl = None
-      if self.stl:
-         self.connected.emit(True)
-   def disconnect(self):
-      if self.stl:
-         self.stl.close()
-         self.connected.emit(False)
-      self.stl = None
-
-if __name__ == '__main__':
-   app = QApplication(sys.argv)
-   stu = StUtil()
-   stu.show()
-   app.exec()
-
--- a/python/stlink.py	Sun Nov 24 11:24:15 2013 +0100
+++ /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('<H', reply[0:2])[0]
-   def readTraceData(self):
-      bsize = self.getTraceByteCount()
-      if bsize > 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('<II', address, value)
-      r = self.send_recv(cmd, 2)
-   def read_debug32(self, address):
-      cmd = bytearray(16)
-      cmd[0:2] = DEBUG_COMMAND, JTAG_READDEBUG_32BIT
-      cmd[2:6] = struct.pack('<I', address) # pack into u32 little endian
-      reply = self.send_recv(cmd, 8)
-      return struct.unpack('<I', reply[4:8])[0]
-   def write_reg(self, reg, value):
-      cmd = bytearray(16)
-      cmd[0:3] = DEBUG_COMMAND, DEBUG_WRITEREG, reg
-      cmd[3:7] = struct.pack('<I', value)
-      r = self.send_recv(cmd, 2)
-   def read_reg(self, reg):
-      cmd = bytearray(16)
-      cmd[0:3] = DEBUG_COMMAND, DEBUG_READREG, reg
-      reply = self.send_recv(cmd, 4)
-      return struct.unpack('<I', reply)[0]
-   def read_all_regs(self):
-      cmd = bytearray(16)
-      cmd[0:2] = DEBUG_COMMAND, DEBUG_READALLREGS
-      reply = self.send_recv(cmd, 84)
-      fmt = '<' + 'I' * 21 # unpack 21 register values
-      return list(struct.unpack(fmt, reply))
-   def write_mem32(self, address, content):
-      assert len(content) % 4 == 0
-      cmd = bytearray(16)
-      cmd[0:2] = DEBUG_COMMAND, DEBUG_WRITEMEM_32BIT
-      cmd[2:8] = struct.pack('<IH', address, len(content))
-      self.send_recv(cmd)
-      self.send_recv(content)
-   def read_mem32(self, address, length):
-      assert length % 4 == 0
-      cmd = bytearray(16)
-      cmd[0:2] = DEBUG_COMMAND, DEBUG_READMEM_32BIT
-      cmd[2:8] = struct.pack('<IH', address, length)
-      reply = self.send_recv(cmd, length) # expect memory back!
-      return reply
-
-   # Helper 2 functions:
-   def send_recv(self, tx, rxsize=0):
-      """ Helper function that transmits and receives data in bulk mode. """
-      # TODO: we could use here the non-blocking libusb api.
-      tx = bytes(tx)
-      #assert len(tx) == 16
-      self.devHandle.bulkWrite(2, tx) # write to endpoint 2
-      if rxsize > 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!')
-
--- a/python/stm32.py	Sun Nov 24 11:24:15 2013 +0100
+++ /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
--- a/python/target/__init__.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/target/__init__.py	Wed Nov 27 08:06:42 2013 +0100
@@ -2,7 +2,18 @@
 
 from .basetarget import Nop, Instruction, Label, Target, Comment, Alignment
 from .basetarget import Imm32, DebugInfo
-#from .armtarget import armtarget
+
+from .armtarget import ArmTarget
+from .armframe import ArmFrame
+from .arminstructionselector import ArmInstructionSelector
+
+from .msp430 import msp430target
+
+# Instance:
+armtarget = ArmTarget()
+armtarget.ins_sel = ArmInstructionSelector()
+armtarget.FrameClass = ArmFrame
+
 #from .msp430target import msp430target
 
-#target_list = [armtarget, msp430target]
+target_list = [armtarget]
--- a/python/target/armframe.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/target/armframe.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,22 +1,17 @@
 import ir
-from ppci import CompilerError
 from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
-from .basetarget import Imm32, Imm3
-import .armtarget as arm
-from .instructionselector import InstructionSelector
-import irmach
-from irmach import AbstractInstruction as makeIns
-import asm
+from .basetarget import Imm7
+from irmach import AbstractInstruction as makeIns, Frame
+from .arminstructions import Dcd, AddSp, SubSp, Push, Pop, Mov2
+from .arminstructions import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP
 
 
-class ArmFrame(irmach.Frame):
-    """
-      Arm specific frame for functions.
-    """
+class ArmFrame(Frame):
+    """ Arm specific frame for functions. """
     def __init__(self, name):
         # We use r7 as frame pointer.
         super().__init__(name)
-        self.regs = [arm.r0, arm.r1, arm.r2, arm.r3, arm.r4, arm.r5, arm.r6]
+        self.regs = [R0, R1, R2, R3, R4, R5, R6]
         self.rv = ir.Temp('special_RV')
         self.p1 = ir.Temp('special_P1')
         self.p2 = ir.Temp('special_P2')
@@ -25,12 +20,12 @@
         self.fp = ir.Temp('special_FP')
         # Pre-colored registers:
         self.tempMap = {}
-        self.tempMap[self.rv] = arm.r0
-        self.tempMap[self.p1] = arm.r1
-        self.tempMap[self.p2] = arm.r2
-        self.tempMap[self.p3] = arm.r3
-        self.tempMap[self.p4] = arm.r4
-        self.tempMap[self.fp] = arm.r7
+        self.tempMap[self.rv] = R0
+        self.tempMap[self.p1] = R1
+        self.tempMap[self.p2] = R2
+        self.tempMap[self.p3] = R3
+        self.tempMap[self.p4] = R4
+        self.tempMap[self.fp] = R7
         self.locVars = {}
         self.parMap = {}
         # Literal pool:
@@ -67,153 +62,17 @@
             Add code for the prologue and the epilogue. Add a label, the
             return instruction and the stack pointer adjustment for the frame.
         """
-        self.instructions.insert(0, makeIns(arm.Label(self.name)))
-        self.instructions.insert(1, makeIns(arm.push_ins(arm.RegisterSet({arm.lr, arm.r7}))))
+        self.instructions.insert(0, makeIns(Label(self.name)))
+        self.instructions.insert(1, makeIns(Push({LR, R7})))
         # Reserve stack space for locals:
-        self.instructions.insert(2, makeIns(arm.subspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize))))
+        self.instructions.insert(2, makeIns(SubSp(SP, SP, Imm7(self.stacksize))))
         # Setup frame pointer:
-        self.instructions.insert(3, makeIns(arm.movregreg_ext_ins(arm.r7, arm.sp)))
+        self.instructions.insert(3, makeIns(Mov2(R7, SP)))
         # Stack grows downwards
-        self.instructions.append(makeIns(arm.addspsp_ins(arm.sp, arm.sp, arm.Imm7(self.stacksize))))
-        self.instructions.append(makeIns(arm.pop_ins(arm.RegisterSet({arm.pc, arm.r7}))))
+        self.instructions.append(makeIns(AddSp(SP, SP, Imm7(self.stacksize))))
+        self.instructions.append(makeIns(Pop({PC, R7})))
         # Add constant literals:
         self.instructions.append(makeIns(Alignment(4))) # Align at 4 bytes
         for ln, v in self.constants:
-            self.instructions.append(makeIns(arm.Label(ln)))
-            self.instructions.append(makeIns(arm.dcd_ins(v)))
-
-
-class ArmInstructionSelector(InstructionSelector):
-    """ Instruction selector for the arm architecture """
-    def munchExpr(self, e):
-        if isinstance(e, ir.Alloc):
-            return 0
-        elif isinstance(e, ir.Binop) and e.operation == '+' and \
-            isinstance(e.b, ir.Const) and e.b.value < 8:
-            a = self.munchExpr(e.a)
-            d = self.newTmp()
-            c = Imm3(e.b.value)
-            self.emit(arm.addregregimm3_ins, others=[c], dst=[d], src=[a])
-            return d
-        elif isinstance(e, ir.Binop) and e.operation == '+':
-            a = self.munchExpr(e.a)
-            b = self.munchExpr(e.b)
-            d = self.newTmp()
-            self.emit(arm.addregs_ins, dst=[d], src=[a, b])
-            return d
-        elif isinstance(e, ir.Binop) and e.operation == '-' and \
-            isinstance(e.b, ir.Const) and e.b.value < 8:
-            a = self.munchExpr(e.a)
-            d = self.newTmp()
-            c = Imm3(e.b.value)
-            self.emit(arm.subregregimm3_ins, others=[c], dst=[d], src=[a])
-            return d
-        elif isinstance(e, ir.Binop) and e.operation == '-':
-            a = self.munchExpr(e.a)
-            b = self.munchExpr(e.b)
-            d = self.newTmp()
-            self.emit(arm.subregs_ins, dst=[d], src=[a, b])
-            return d
-        elif isinstance(e, ir.Binop) and e.operation == '|':
-            a = self.munchExpr(e.a)
-            b = self.munchExpr(e.b)
-            d = self.newTmp()
-            self.move(d, a)
-            self.emit(arm.orrregs_ins, dst=[], src=[b, d])
-            return d
-        elif isinstance(e, ir.Binop) and e.operation == '<<':
-            a = self.munchExpr(e.a)
-            b = self.munchExpr(e.b)
-            d = self.newTmp()
-            self.move(d, a)
-            self.emit(arm.lslregs_ins, dst=[], src=[b, d]) # TODO: is d a source variable?
-            return d
-        elif isinstance(e, ir.Binop) and e.operation == '*':
-            a = self.munchExpr(e.a)
-            b = self.munchExpr(e.b)
-            d = self.newTmp()
-            self.move(d, a)
-            # this mul instruction has operands swapped:
-            self.emit(arm.mulregreg_ins, dst=[d], src=[b, d])
-            return d
-        elif isinstance(e, ir.Const) and e.value < 256:
-            d = self.newTmp()
-            self.emit(arm.mov_imm8_ins, others=[arm.Imm8(e.value)], dst=[d])
-            return d
-        elif isinstance(e, ir.Const) and e.value < (2**31):
-            d = self.newTmp()
-            ln = LabelRef(self.frame.addConstant(e.value))
-            self.emit(arm.ldr_pcrel, others=[ln], dst=[d])
-            return d
-        elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \
-                e.e.operation == '+' and isinstance(e.e.b, ir.Const):
-            base = self.munchExpr(e.e.a)
-            d = self.newTmp()
-            c = e.e.b.value
-            self.emit(arm.loadimm5_ins, others=[c], src=[base], dst=[d])
-            return d
-        elif isinstance(e, ir.Mem):
-            # Load from memory
-            base = self.munchExpr(e.e)
-            d = self.newTmp()
-            self.emit(arm.loadimm5_ins, others=[0], src=[base], dst=[d])
-            return d
-        elif isinstance(e, ir.Temp):
-            return e
-        elif isinstance(e, ir.Call):
-            # Move arguments into proper locations:
-            reguses = []
-            for i, a in enumerate(e.arguments):
-                loc = self.frame.argLoc(i)
-                m = ir.Move(loc, a)
-                self.munchStm(m)
-                if isinstance(loc, ir.Temp):
-                    reguses.append(loc)
-            self.emit(arm.bl_ins(LabelRef(e.f.name)), src=reguses, dst=[self.frame.rv])
-            d = self.newTmp()
-            self.move(d, self.frame.rv)
-            return d
-        else:
-            raise NotImplementedError('Expr --> {}'.format(e))
-
-    def munchStm(self, s):
-        if isinstance(s, ir.Terminator):
-            pass
-        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \
-            isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \
-            isinstance(s.dst.e.b, ir.Const):
-            a = self.munchExpr(s.dst.e.a)
-            val = self.munchExpr(s.src)
-            c = s.dst.e.b.value
-            self.emit(arm.storeimm5_ins, others=[c], src=[a, val])
-        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
-            memloc = self.munchExpr(s.dst.e)
-            val = self.munchExpr(s.src)
-            self.emit(arm.storeimm5_ins, others=[0], src=[memloc, val])
-        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
-            val = self.munchExpr(s.src)
-            dreg = s.dst
-            self.move(dreg, val)
-        elif isinstance(s, ir.Exp):
-            # Generate expression code and discard the result.
-            x = self.munchExpr(s.e)
-            self.emit(Nop(), src=[x])
-        elif isinstance(s, ir.Jump):
-            tgt = self.targets[s.target]
-            self.emit(arm.b_ins(LabelRef(s.target.name)), jumps=[tgt])
-        elif isinstance(s, ir.CJump):
-            a = self.munchExpr(s.a)
-            b = self.munchExpr(s.b)
-            self.emit(arm.cmp_ins, src=[a, b])
-            ntgt = self.targets[s.lab_no]
-            ytgt = self.targets[s.lab_yes]
-            jmp_ins = makeIns(arm.b_ins(LabelRef(s.lab_no.name)), jumps=[ntgt])
-            opnames = {'<': arm.blt_ins, '>':arm.bgt_ins, '==':arm.beq_ins}
-            op = opnames[s.cond](LabelRef(s.lab_yes.name))
-            self.emit(op, jumps=[ytgt, jmp_ins])  # Explicitely add fallthrough
-            self.emit2(jmp_ins)
-        else:
-            raise NotImplementedError('Stmt --> {}'.format(s))
-
-    def move(self, dst, src):
-        self.emit(arm.movregreg_ext_ins, src=[src], dst=[dst])
+            self.instructions.append(makeIns(Label(ln)))
+            self.instructions.append(makeIns(Dcd(v)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/target/arminstructions.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,758 @@
+import struct
+from asmnodes import ASymbol, AInstruction, ANumber, AUnop, ABinop
+from .basetarget import Register, Instruction, Target, Label, LabelRef
+from .basetarget import Imm32, Imm8, Imm7, Imm3
+
+
+def u16(h):
+    return struct.pack('<H', h)
+
+def u32(x):
+    return struct.pack('<I', x)
+
+# Operands:
+
+class ArmRegister(Register):
+    def __init__(self, num, name):
+        super().__init__(name)
+        self.num = num
+
+    def __repr__(self):
+        return self.name
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ASymbol:
+            name = vop.name
+            regs = {}
+            for r in registers:
+                regs[r.name] = r
+            if name in regs:
+                r = regs[name]
+                if isinstance(r, cls):
+                    return r
+
+
+class Reg8Op(ArmRegister):
+    pass
+
+
+class Reg16Op(ArmRegister):
+    pass
+
+
+R0 = Reg8Op(0, 'r0')
+R1 = Reg8Op(1, 'r1')
+R2 = Reg8Op(2, 'r2')
+R3 = Reg8Op(3, 'r3')
+R4 = Reg8Op(4, 'r4')
+R5 = Reg8Op(5, 'r5')
+R6 = Reg8Op(6, 'r6')
+R7 = Reg8Op(7, 'r7')
+# Other registers:
+# TODO
+SP = ArmRegister(13, 'sp')
+LR = ArmRegister(14, 'lr')
+PC = ArmRegister(15, 'pc')
+
+registers = [R0, R1, R2, R3, R4, R5, R6, R7, SP, LR, PC]
+
+
+class RegSpOp:
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ASymbol:
+            if vop.name.lower() == 'sp':
+                return cls()
+
+
+def getRegNum(n):
+    for r in registers:
+        if r.num == n:
+            return r
+
+
+def getRegisterRange(n1, n2):
+    regs = []
+    if n1.num < n2.num:
+        for n in range(n1.num, n2.num + 1):
+            r = getRegNum(n)
+            assert r
+            regs.append(r)
+    return regs
+
+
+def isRegOffset(regname, x, y):
+    if type(x) is ASymbol and type(y) is ANumber and x.name.upper() == regname:
+        return y.number
+    elif type(y) is ASymbol and type(x) is ANumber and y.name.upper() == regname:
+        return x.number
+    
+
+class MemRegXRel:
+    def __init__(self, offset):
+        assert offset % 4 == 0
+        self.offset = offset
+
+    def __repr__(self):
+        return '[{}, #{}]'.format(self.regname, self.offset)
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+':
+            vop = vop.arg # descent
+            offset = isRegOffset(cls.regname, vop.arg1, vop.arg2)
+            if type(offset) is int:
+                if offset % 4 == 0:
+                    offset = vop.arg2.number
+                    return cls(offset)
+            elif type(vop) is ASymbol and vop.name.upper() == self.regname:
+                return cls(0)
+
+
+class MemSpRel(MemRegXRel):
+    regname = 'SP'
+
+
+class MemR8Rel:
+    def __init__(self, basereg, offset):
+        assert type(basereg) is Reg8Op
+        assert type(offset) is int
+        self.basereg = basereg
+        self.offset = offset
+
+    def __repr__(self):
+        return '[{}, #{}]'.format(self.basereg, self.offset)
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is AUnop and vop.operation == '[]':
+            vop = vop.arg # descent
+            if type(vop) is ABinop:
+                if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber:
+                    offset = vop.arg2.number
+                    if offset > 120:
+                        return
+                    basereg = Reg8Op.Create(vop.arg1)
+                    if not basereg:
+                        return
+                else:
+                    return
+            elif type(vop) is ASymbol:
+                offset = 0
+                basereg = Reg8Op.Create(vop)
+                if not basereg:
+                    return
+            else:
+                return
+            return cls(getRegNum(basereg.num), offset)
+
+
+class RegisterSet:
+    def __init__(self, regs):
+        assert type(regs) is set
+        self.regs = regs
+
+    def __repr__(self):
+        return ','.join([str(r) for r in self.regs])
+
+    @classmethod
+    def Create(cls, vop):
+        assert type(vop) is AUnop and vop.operation == '{}'
+        assert type(vop.arg) is list
+        regs = set()
+        for arg in vop.arg:
+            if type(arg) is ASymbol:
+                reg = ArmRegister.Create(arg)
+                if not reg:
+                    return
+                regs.add(reg)
+            elif type(arg) is ABinop and arg.op == '-':
+                reg1 = ArmRegister.Create(arg.arg1)
+                reg2 = ArmRegister.Create(arg.arg2)
+                if not reg1:
+                    return
+                if not reg2:
+                    return
+                for r in getRegisterRange(reg1, reg2):
+                    regs.add(r)
+            else:
+                raise Exception('Cannot be')
+        return cls(regs)
+
+    def registerNumbers(self):
+        return [r.num for r in self.regs]
+
+
+
+# Instructions:
+
+class ArmInstruction(Instruction):
+    pass
+
+
+allins = []
+
+
+def instruction(i):
+    allins.append(i)
+    return i
+
+
+@instruction
+class Dcd(ArmInstruction):
+    mnemonic = 'dcd'
+    operands = (Imm32,)
+    def __init__(self, expr):
+        if isinstance(expr, Imm32):
+            self.expr = expr.imm
+            self.label = None
+        elif isinstance(expr, LabelRef):
+            self.expr = 0
+            self.label = expr
+        elif isinstance(expr, int):
+            self.expr = expr
+            self.label = None
+        else:
+            raise NotImplementedError()
+
+    def resolve(self, f):
+        if self.label:
+            self.expr = f(self.label.name)
+
+    def encode(self):
+        return u32(self.expr)
+
+    def __repr__(self):
+        return 'DCD 0x{0:X}'.format(self.expr)
+
+
+@instruction
+class nop_ins(ArmInstruction):
+    mnemonic = 'nop'
+    operands = tuple()
+
+    def encode(self):
+        return bytes()
+
+    def __repr__(self):
+        return 'NOP'
+
+
+# Memory related
+
+class LS_imm5_base(ArmInstruction):
+    """ ??? Rt, [Rn, imm5] """
+    operands = (Reg8Op, MemR8Rel)
+    def __init__(self, rt, memop):
+        assert memop.offset % 4 == 0
+        self.imm5 = memop.offset >> 2
+        self.rn = memop.basereg.num
+        self.rt = rt
+        self.memloc = memop
+        assert self.rn < 8
+        assert self.rt.num < 8
+
+    def encode(self):
+        Rn = self.rn
+        Rt = self.rt.num
+        imm5 = self.imm5
+
+        h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        return u16(h)
+
+
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc)
+
+
+@instruction
+class Str2(LS_imm5_base):
+    mnemonic = 'STR'
+    opcode = 0xC
+
+    @classmethod
+    def fromim(cls, im):
+        mem = MemR8Rel(im.src[0], im.others[0])
+        return cls(im.src[1], mem)
+
+
+@instruction
+class Ldr2(LS_imm5_base):
+    mnemonic = 'LDR'
+    opcode = 0xD
+
+    @classmethod
+    def fromim(cls, im):
+        mem = MemR8Rel(im.src[0], im.others[0])
+        return cls(im.dst[0], mem)
+
+class ls_sp_base_imm8(ArmInstruction):
+    operands = (Reg8Op, MemSpRel)
+    def __init__(self, rt, memop):
+        self.rt = rt
+        self.offset = memop.offset
+
+    def encode(self):
+        rt = self.rt.num
+        assert rt < 8
+        imm8 = self.offset >> 2
+        assert imm8 < 256
+        h = (self.opcode << 8) | (rt << 8) | imm8
+        return u16(h)
+
+    def __repr__(self):
+        return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset)
+
+def align(x, m):
+    while ((x % m) != 0):
+        x = x + 1
+    return x
+
+
+@instruction
+class Ldr3(ArmInstruction):
+    """ ldr Rt, LABEL, load value from pc relative position """
+    mnemonic = 'ldr'
+    operands = (Reg8Op, LabelRef)
+    def __init__(self, rt, label):
+        assert isinstance(label, LabelRef)
+        self.rt = rt
+        self.label = label
+        self.offset = 0
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.others[0])
+
+    def resolve(self, f):
+        la = f(self.label.name)
+        sa = align(self.address + 2, 4)
+        self.offset = (la - sa)
+        if self.offset < 0:
+            self.offset = 0
+
+    def encode(self):
+        rt = self.rt.num
+        assert rt < 8
+        assert self.offset % 4 == 0
+        imm8 = self.offset >> 2
+        assert imm8 < 256
+        assert imm8 >= 0
+        h = (0x9 << 11) | (rt << 8) | imm8
+        return u16(h)
+
+    def __repr__(self):
+        return 'LDR {}, {}'.format(self.rt, self.label.name)
+
+
+@instruction
+class Ldr1(ls_sp_base_imm8):
+    """ ldr Rt, [SP, imm8] """
+    mnemonic = 'LDR'
+    opcode = 0x98
+
+
+@instruction
+class Str1(ls_sp_base_imm8):
+    """ str Rt, [SP, imm8] """
+    mnemonic = 'STR'
+    opcode = 0x90
+
+
+@instruction
+class Mov3(ArmInstruction):
+    """ mov Rd, imm8, move immediate value into register """
+    mnemonic = 'mov'
+    opcode = 4 # 00100 Rd(3) imm8
+    operands = (Reg8Op, Imm8)
+    def __init__(self, rd, imm):
+        if type(imm) is int:
+            imm = Imm8(imm)
+        assert type(imm) is Imm8
+        self.imm = imm.imm
+        assert type(rd) is Reg8Op, str(type(rd))
+        self.rd = rd
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.others[0])
+
+    def encode(self):
+        rd = self.rd.num
+        opcode = self.opcode
+        imm8 = self.imm
+        h = (opcode << 11) | (rd << 8) | imm8
+        return u16(h)
+
+    def __repr__(self):
+        return 'MOV {}, {}'.format(self.rd, self.imm)
+
+
+
+# Arithmatics:
+
+
+
+class regregimm3_base(ArmInstruction):
+    operands = (Reg8Op, Reg8Op, Imm3)
+    def __init__(self, rd, rn, imm3):
+        self.rd = rd
+        self.rn = rn
+        assert type(imm3) is Imm3
+        self.imm3 = imm3
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0], im.others[0])
+
+    def encode(self):
+        rd = self.rd.num
+        rn = self.rn.num
+        imm3 = self.imm3.imm
+        opcode = self.opcode
+        h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd
+        return u16(h)
+
+    def __repr__(self):
+        return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm)
+
+@instruction
+class addregregimm3_ins(regregimm3_base):
+    """ add Rd, Rn, imm3 """
+    mnemonic = 'add'
+    opcode = 0b0001110
+
+
+@instruction
+class subregregimm3_ins(regregimm3_base):
+    """ sub Rd, Rn, imm3 """
+    mnemonic = 'sub'
+    opcode = 0b0001111
+
+
+class regregreg_base(ArmInstruction):
+    """ ??? Rd, Rn, Rm """
+    operands = (Reg8Op, Reg8Op, Reg8Op)
+    def __init__(self, rd, rn, rm):
+        self.rd = rd
+        self.rn = rn
+        self.rm = rm
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0], im.src[1])
+
+    def encode(self):
+        rd = self.rd.num
+        rn = self.rn.num
+        rm = self.rm.num
+        h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd
+        return u16(h)
+
+    def __repr__(self):
+        return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm)
+
+
+@instruction
+class Add(regregreg_base):
+    mnemonic = 'ADD'
+    opcode = 0b0001100
+
+
+@instruction
+class Sub(regregreg_base):
+    mnemonic = 'SUB'
+    opcode = 0b0001101
+
+
+@instruction
+class Mov2(ArmInstruction):
+    """ mov rd, rm """
+    operands = (ArmRegister, ArmRegister)
+    mnemonic = 'MOV'
+    def __init__(self, rd, rm):
+        self.rd = rd
+        self.rm = rm
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.dst[0], im.src[0])
+
+    def encode(self):
+        Rd = self.rd.num & 0x7
+        D = (self.rd.num >> 3) & 0x1
+        Rm = self.rm.num
+        opcode = 0b01000110
+        return u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd)
+
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm)
+        
+
+@instruction
+class mulregreg_ins(ArmInstruction):
+    """ mul Rn, Rdm """
+    operands = (Reg8Op, Reg8Op)
+    mnemonic = 'MUL'
+    def __init__(self, rn, rdm):
+        self.rn = rn
+        self.rdm = rdm
+
+    @classmethod
+    def fromim(cls, im):
+        assert im.src[1] is im.dst[0]
+        return cls(im.src[0], im.dst[0])
+
+    def encode(self):
+        rn = self.rn.num
+        rdm = self.rdm.num
+        opcode = 0b0100001101
+        h = (opcode << 6) | (rn << 3) | rdm
+        return u16(h)
+
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm)
+
+
+class regreg_base(ArmInstruction):
+    """ ??? Rdn, Rm """
+    operands = (Reg8Op, Reg8Op)
+    # TODO: integrate with the code gen interface:
+    src = (0, 1)
+    dst = (0,)
+    def __init__(self, rdn, rm):
+        self.rdn = rdn
+        self.rm = rm
+
+    @classmethod
+    def fromim(cls, im):
+        return cls(im.src[0], im.src[1])
+
+    def encode(self):
+        rdn = self.rdn.num
+        rm = self.rm.num
+        h = (self.opcode << 6) | (rm << 3) | rdn
+        return u16(h)
+
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm)
+
+
+@instruction
+class movregreg_ins(regreg_base):
+    """ mov Rd, Rm (reg8 operands) """
+    mnemonic = 'mov'
+    opcode = 0
+
+
+@instruction
+class And(regreg_base):
+    mnemonic = 'AND'
+    opcode = 0b0100000000
+
+
+@instruction
+class Orr(regreg_base):
+    mnemonic = 'ORR'
+    opcode = 0b0100001100
+
+
+@instruction
+class Cmp(regreg_base):
+    mnemonic = 'CMP'
+    opcode = 0b0100001010
+
+
+@instruction
+class Lsl(regreg_base):
+    mnemonic = 'LSL'
+    opcode = 0b0100000010
+
+
+@instruction
+class cmpregimm8_ins(ArmInstruction):
+    """ cmp Rn, imm8 """
+    mnemonic = 'cmp'
+    opcode = 5 # 00101
+    operands = (Reg8Op, Imm8)
+    def __init__(self, rn, imm):
+        self.rn = rn
+        self.imm = imm
+
+    def encode(self):
+        rn = self.rn.num
+        imm = self.imm.imm
+        opcode = self.opcode
+        h = (opcode << 11) | (rn << 8) | imm
+        return u16(h)
+
+
+# Jumping:
+
+def wrap_negative(x, bits):
+    b = struct.unpack('<I', struct.pack('<i', x))[0]
+    mask = (1 << bits) - 1
+    return b & mask
+
+class jumpBase_ins(ArmInstruction):
+    operands = (LabelRef,)
+    def __init__(self, target_label):
+        assert type(target_label) is LabelRef
+        self.target = target_label
+        self.offset = 0
+
+    def resolve(self, f):
+        la = f(self.target.name)
+        sa = self.address + 4
+        self.offset = (la - sa)
+
+    def __repr__(self):
+        return '{} {}'.format(self.mnemonic, self.target.name)
+
+
+@instruction
+class B(jumpBase_ins):
+    mnemonic = 'B'
+    def encode(self):
+        imm11 = wrap_negative(self.offset >> 1, 11)
+        h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode
+        return u16(h)
+
+
+@instruction
+class Bl(jumpBase_ins):
+    mnemonic = 'BL'
+    def encode(self):
+        imm32 = wrap_negative(self.offset >> 1, 32)
+        imm11 = imm32 & 0x7FF
+        imm10 = (imm32 >> 11) & 0x3FF
+        j1 = 1 # TODO: what do these mean?
+        j2 = 1
+        s = (imm32 >> 24) & 0x1
+        h1 = (0b11110 << 11) | (s << 10) | imm10 
+        h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11
+        return u16(h1) + u16(h2)
+
+
+class cond_base_ins(jumpBase_ins):
+    def encode(self):
+        imm8 = wrap_negative(self.offset >> 1, 8)
+        h = (0b1101 << 12) | (self.cond << 8) | imm8
+        return u16(h)
+
+
+@instruction
+class Beq(cond_base_ins):
+    mnemonic = 'beq'
+    cond = 0
+
+
+@instruction
+class Bne(cond_base_ins):
+    mnemonic = 'bne'
+    cond = 1
+
+
+@instruction
+class Blt(cond_base_ins):
+    mnemonic = 'blt'
+    cond = 0b1011
+
+
+@instruction
+class Bgt(cond_base_ins):
+    mnemonic = 'bgt'
+    cond = 0b1100
+
+
+@instruction
+class Push(ArmInstruction):
+    operands = (RegisterSet,)
+    mnemonic = 'push'
+
+    def __init__(self, regs):
+        if type(regs) is set:
+            regs = RegisterSet(regs)
+        assert (type(regs),) == self.operands, (type(regs),)
+        self.regs = regs
+
+    def __repr__(self):
+        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
+
+    def encode(self):
+        reg_list = 0
+        M = 0
+        for n in self.regs.registerNumbers():
+            if n < 8:
+                reg_list |= (1 << n)
+            elif n == 14:
+                M = 1
+            else:
+                raise NotImplementedError('not implemented for this register')
+        h = (0x5a << 9) | (M << 8) | reg_list
+        return u16(h)
+
+
+@instruction
+class Pop(ArmInstruction):
+    operands = (RegisterSet,)
+    mnemonic = 'pop'
+
+    def __init__(self, regs):
+        if type(regs) is set:
+            regs = RegisterSet(regs)
+        assert (type(regs),) == self.operands, (type(regs),)
+        self.regs = regs
+
+    def __repr__(self):
+        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
+
+    def encode(self):
+        reg_list = 0
+        P = 0
+        for n in self.regs.registerNumbers():
+            if n < 8:
+                reg_list |= (1 << n)
+            elif n == 15:
+                P = 1
+            else:
+                raise NotImplementedError('not implemented for this register')
+        h = (0x5E << 9) | (P << 8) | reg_list
+        return u16(h)
+
+
+@instruction
+class Yield(ArmInstruction):
+    operands = ()
+    mnemonic = 'yield'
+
+    def encode(self):
+        return u16(0xbf10)
+
+# misc:
+
+# add/sub SP:
+class addspsp_base(ArmInstruction):
+    operands = (RegSpOp, RegSpOp, Imm7)
+    def __init__(self, _sp, _sp2, imm7):
+        self.imm7 = imm7.imm
+        assert self.imm7 % 4 == 0
+        self.imm7 >>= 2
+
+    def encode(self):
+        return u16((self.opcode << 7) |self.imm7)
+
+    def __repr__(self):
+        return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2)
+
+@instruction
+class AddSp(addspsp_base):
+    mnemonic = 'add'
+    opcode = 0b101100000
+
+
+@instruction
+class SubSp(addspsp_base):
+    mnemonic = 'sub'
+    opcode = 0b101100001
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/target/arminstructionselector.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,144 @@
+import ir
+from irmach import AbstractInstruction as makeIns
+from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
+from .instructionselector import InstructionSelector
+from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3, B, Bl, Bgt, Blt, Beq
+from .arminstructions import Mov2, Mov3
+from .arminstructions import Add, Sub, Cmp
+from .basetarget import Imm8, Imm7, Imm3
+
+
+class ArmInstructionSelector(InstructionSelector):
+    """ Instruction selector for the arm architecture """
+    def munchExpr(self, e):
+        if isinstance(e, ir.Alloc):
+            return 0
+        elif isinstance(e, ir.Binop) and e.operation == '+' and \
+            isinstance(e.b, ir.Const) and e.b.value < 8:
+            a = self.munchExpr(e.a)
+            d = self.newTmp()
+            c = Imm3(e.b.value)
+            self.emit(arm.addregregimm3_ins, others=[c], dst=[d], src=[a])
+            return d
+        elif isinstance(e, ir.Binop) and e.operation == '+':
+            a = self.munchExpr(e.a)
+            b = self.munchExpr(e.b)
+            d = self.newTmp()
+            self.emit(Add, dst=[d], src=[a, b])
+            return d
+        elif isinstance(e, ir.Binop) and e.operation == '-' and \
+            isinstance(e.b, ir.Const) and e.b.value < 8:
+            a = self.munchExpr(e.a)
+            d = self.newTmp()
+            c = Imm3(e.b.value)
+            self.emit(arm.subregregimm3_ins, others=[c], dst=[d], src=[a])
+            return d
+        elif isinstance(e, ir.Binop) and e.operation == '-':
+            a = self.munchExpr(e.a)
+            b = self.munchExpr(e.b)
+            d = self.newTmp()
+            self.emit(Sub, dst=[d], src=[a, b])
+            return d
+        elif isinstance(e, ir.Binop) and e.operation == '|':
+            a = self.munchExpr(e.a)
+            b = self.munchExpr(e.b)
+            d = self.newTmp()
+            self.move(d, a)
+            self.emit(Orr, dst=[], src=[b, d])
+            return d
+        elif isinstance(e, ir.Binop) and e.operation == '<<':
+            a = self.munchExpr(e.a)
+            b = self.munchExpr(e.b)
+            d = self.newTmp()
+            self.move(d, a)
+            self.emit(Lsl, dst=[], src=[b, d]) # TODO: is d a source variable?
+            return d
+        elif isinstance(e, ir.Binop) and e.operation == '*':
+            a = self.munchExpr(e.a)
+            b = self.munchExpr(e.b)
+            d = self.newTmp()
+            self.move(d, a)
+            # this mul instruction has operands swapped:
+            self.emit(arm.mulregreg_ins, dst=[d], src=[b, d])
+            return d
+        elif isinstance(e, ir.Const) and e.value < 256:
+            d = self.newTmp()
+            self.emit(Mov3, others=[Imm8(e.value)], dst=[d])
+            return d
+        elif isinstance(e, ir.Const) and e.value < (2**31):
+            d = self.newTmp()
+            ln = LabelRef(self.frame.addConstant(e.value))
+            self.emit(Ldr3, others=[ln], dst=[d])
+            return d
+        elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \
+                e.e.operation == '+' and isinstance(e.e.b, ir.Const):
+            base = self.munchExpr(e.e.a)
+            d = self.newTmp()
+            c = e.e.b.value
+            self.emit(Ldr2, others=[c], src=[base], dst=[d])
+            return d
+        elif isinstance(e, ir.Mem):
+            # Load from memory
+            base = self.munchExpr(e.e)
+            d = self.newTmp()
+            self.emit(Ldr2, others=[0], src=[base], dst=[d])
+            return d
+        elif isinstance(e, ir.Temp):
+            return e
+        elif isinstance(e, ir.Call):
+            # Move arguments into proper locations:
+            reguses = []
+            for i, a in enumerate(e.arguments):
+                loc = self.frame.argLoc(i)
+                m = ir.Move(loc, a)
+                self.munchStm(m)
+                if isinstance(loc, ir.Temp):
+                    reguses.append(loc)
+            self.emit(Bl(LabelRef(e.f.name)), src=reguses, dst=[self.frame.rv])
+            d = self.newTmp()
+            self.move(d, self.frame.rv)
+            return d
+        else:
+            raise NotImplementedError('Expr --> {}'.format(e))
+
+    def munchStm(self, s):
+        if isinstance(s, ir.Terminator):
+            pass
+        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \
+            isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \
+            isinstance(s.dst.e.b, ir.Const):
+            a = self.munchExpr(s.dst.e.a)
+            val = self.munchExpr(s.src)
+            c = s.dst.e.b.value
+            self.emit(Str2, others=[c], src=[a, val])
+        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
+            memloc = self.munchExpr(s.dst.e)
+            val = self.munchExpr(s.src)
+            self.emit(Str2, others=[0], src=[memloc, val])
+        elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
+            val = self.munchExpr(s.src)
+            dreg = s.dst
+            self.move(dreg, val)
+        elif isinstance(s, ir.Exp):
+            # Generate expression code and discard the result.
+            x = self.munchExpr(s.e)
+            self.emit(Nop(), src=[x])
+        elif isinstance(s, ir.Jump):
+            tgt = self.targets[s.target]
+            self.emit(B(LabelRef(s.target.name)), jumps=[tgt])
+        elif isinstance(s, ir.CJump):
+            a = self.munchExpr(s.a)
+            b = self.munchExpr(s.b)
+            self.emit(Cmp, src=[a, b])
+            ntgt = self.targets[s.lab_no]
+            ytgt = self.targets[s.lab_yes]
+            jmp_ins = makeIns(B(LabelRef(s.lab_no.name)), jumps=[ntgt])
+            opnames = {'<': Blt, '>':Bgt, '==':Beq}
+            op = opnames[s.cond](LabelRef(s.lab_yes.name))
+            self.emit(op, jumps=[ytgt, jmp_ins])  # Explicitely add fallthrough
+            self.emit2(jmp_ins)
+        else:
+            raise NotImplementedError('Stmt --> {}'.format(s))
+
+    def move(self, dst, src):
+        self.emit(Mov2, src=[src], dst=[dst])
--- a/python/target/armtarget.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/target/armtarget.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,759 +1,32 @@
 import struct
-import types
-import ir
-from asmnodes import ASymbol, ANumber, AUnop, ABinop
-from ppci import CompilerError
 from .basetarget import Register, Instruction, Target, Label, LabelRef
 from .basetarget import Imm32, Imm8, Imm7, Imm3
-from .armframe import ArmFrame, ArmInstructionSelector
+from .arminstructions import allins, Reg8Op, ArmRegister
+from .arminstructions import Dcd, B
+from .arminstructions import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP
 
 
 """ ARM target description. """
 
 # TODO: encode this in DSL (domain specific language)
 # TBD: is this required?
-
-def u16(h):
-    return struct.pack('<H', h)
-
-def u32(x):
-    return struct.pack('<I', x)
-
-armtarget = Target('arm')
-armtarget.InstructionSelector = ArmInstructionSelector
-armtarget.Frame = ArmFrame
-
-class ArmRegister(Register):
-    def __init__(self, num, name):
-        super().__init__(name)
-        self.num = num
-
-    def __repr__(self):
-        return self.name
-
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ASymbol:
-            name = vop.name
-            regs = {}
-            for r in armtarget.registers:
-                regs[r.name] = r
-            if name in regs:
-                r = regs[name]
-                if isinstance(r, cls):
-                    return r
-
-
-class Reg8Op(ArmRegister):
-    pass
-
-
-class Reg16Op(ArmRegister):
-    pass
-
-
-class RegSpOp:
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ASymbol:
-            if vop.name.lower() == 'sp':
-                return cls()
-
-def getRegNum(n):
-    for r in armtarget.registers:
-        if r.num == n:
-            return r
-
-def getRegisterRange(n1, n2):
-    regs = []
-    if n1.num < n2.num:
-        for n in range(n1.num, n2.num + 1):
-            r = getRegNum(n)
-            assert r
-            regs.append(r)
-    return regs
-
-def isRegOffset(regname, x, y):
-    if type(x) is ASymbol and type(y) is ANumber and x.name.upper() == regname:
-        return y.number
-    elif type(y) is ASymbol and type(x) is ANumber and y.name.upper() == regname:
-        return x.number
-    
-
-class MemRegXRel:
-    def __init__(self, offset):
-        assert offset % 4 == 0
-        self.offset = offset
-
-    def __repr__(self):
-        return '[{}, #{}]'.format(self.regname, self.offset)
-
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+':
-            vop = vop.arg # descent
-            offset = isRegOffset(cls.regname, vop.arg1, vop.arg2)
-            if type(offset) is int:
-                if offset % 4 == 0:
-                    offset = vop.arg2.number
-                    return cls(offset)
-            elif type(vop) is ASymbol and vop.name.upper() == self.regname:
-                return cls(0)
-
-
-class MemSpRel(MemRegXRel):
-    regname = 'SP'
-
-
-class MemR8Rel:
-    def __init__(self, basereg, offset):
-        assert type(basereg) is Reg8Op
-        assert type(offset) is int
-        self.basereg = basereg
-        self.offset = offset
-
-    def __repr__(self):
-        return '[{}, #{}]'.format(self.basereg, self.offset)
-
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is AUnop and vop.operation == '[]':
-            vop = vop.arg # descent
-            if type(vop) is ABinop:
-                if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber:
-                    offset = vop.arg2.number
-                    if offset > 120:
-                        return
-                    basereg = Reg8Op.Create(vop.arg1)
-                    if not basereg:
-                        return
-                else:
-                    return
-            elif type(vop) is ASymbol:
-                offset = 0
-                basereg = Reg8Op.Create(vop)
-                if not basereg:
-                    return
-            else:
-                return
-            return cls(getRegNum(basereg.num), offset)
-
-class RegisterSet:
-    def __init__(self, regs):
-        assert type(regs) is set
-        self.regs = regs
-
-    def __repr__(self):
-        return ','.join([str(r) for r in self.regs])
-
-    @classmethod
-    def Create(cls, vop):
-        assert type(vop) is AUnop and vop.operation == '{}'
-        assert type(vop.arg) is list
-        regs = set()
-        for arg in vop.arg:
-            if type(arg) is ASymbol:
-                reg = ArmRegister.Create(arg)
-                if not reg:
-                    return
-                regs.add(reg)
-            elif type(arg) is ABinop and arg.op == '-':
-                reg1 = ArmRegister.Create(arg.arg1)
-                reg2 = ArmRegister.Create(arg.arg2)
-                if not reg1:
-                    return
-                if not reg2:
-                    return
-                for r in getRegisterRange(reg1, reg2):
-                    regs.add(r)
-            else:
-                raise Exception('Cannot be')
-        return cls(regs)
-
-    def registerNumbers(self):
-        return [r.num for r in self.regs]
-
-def makeReg(cls, num, name):
-    r = cls(num, name)
-    armtarget.registers.append(r)
-    return r
-
-# 8 bit registers:
-r0 = makeReg(Reg8Op, 0, 'r0')
-r1 = makeReg(Reg8Op, 1, 'r1')
-r2 = makeReg(Reg8Op, 2, 'r2')
-r3 = makeReg(Reg8Op, 3, 'r3')
-r4 = makeReg(Reg8Op, 4, 'r4')
-r5 = makeReg(Reg8Op, 5, 'r5')
-r6 = makeReg(Reg8Op, 6, 'r6')
-r7 = makeReg(Reg8Op, 7, 'r7')
-# Other registers:
-# TODO
-sp = makeReg(ArmRegister, 13, 'sp')
-lr = makeReg(ArmRegister, 14, 'lr')
-pc = makeReg(ArmRegister, 15, 'pc')
-
-# Sanity checks:
-assert isinstance(sp, ArmRegister)
-assert isinstance(r3, ArmRegister)
-assert ArmRegister.Create(ASymbol('r3')) is r3
-assert ArmRegister.Create(ASymbol('sp')) is sp
-
-
-class ArmInstruction(Instruction):
-    pass
-
-
-@armtarget.instruction
-class dcd_ins(ArmInstruction):
-    mnemonic = 'dcd'
-    operands = (Imm32,)
-    def __init__(self, expr):
-        if isinstance(expr, Imm32):
-            self.expr = expr.imm
-            self.label = None
-        elif isinstance(expr, LabelRef):
-            self.expr = 0
-            self.label = expr
-        elif isinstance(expr, int):
-            self.expr = expr
-            self.label = None
-        else:
-            raise NotImplementedError()
-
-    def resolve(self, f):
-        if self.label:
-            self.expr = f(self.label.name)
-
-    def encode(self):
-        return u32(self.expr)
-
-    def __repr__(self):
-        return 'DCD 0x{0:X}'.format(self.expr)
-
-
-@armtarget.instruction
-class nop_ins(ArmInstruction):
-    mnemonic = 'nop'
-    operands = tuple()
-
-    def encode(self):
-        return bytes()
-
-    def __repr__(self):
-        return 'NOP'
-
-
-# Memory related
-
-class LS_imm5_base(ArmInstruction):
-    """ ??? Rt, [Rn, imm5] """
-    operands = (Reg8Op, MemR8Rel)
-    def __init__(self, rt, memop):
-        assert memop.offset % 4 == 0
-        self.imm5 = memop.offset >> 2
-        self.rn = memop.basereg.num
-        self.rt = rt
-        self.memloc = memop
-        assert self.rn < 8
-        assert self.rt.num < 8
-
-    def encode(self):
-        Rn = self.rn
-        Rt = self.rt.num
-        imm5 = self.imm5
-
-        h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt
-        return u16(h)
-
-
-    def __repr__(self):
-        return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc)
-
-
-@armtarget.instruction
-class storeimm5_ins(LS_imm5_base):
-    mnemonic = 'STR'
-    opcode = 0xC
-
-    @classmethod
-    def fromim(cls, im):
-        mem = MemR8Rel(im.src[0], im.others[0])
-        return cls(im.src[1], mem)
-
-
-@armtarget.instruction
-class loadimm5_ins(LS_imm5_base):
-    mnemonic = 'LDR'
-    opcode = 0xD
-
-    @classmethod
-    def fromim(cls, im):
-        mem = MemR8Rel(im.src[0], im.others[0])
-        return cls(im.dst[0], mem)
-
-class ls_sp_base_imm8(ArmInstruction):
-    operands = (Reg8Op, MemSpRel)
-    def __init__(self, rt, memop):
-        self.rt = rt
-        self.offset = memop.offset
-
-    def encode(self):
-        rt = self.rt.num
-        assert rt < 8
-        imm8 = self.offset >> 2
-        assert imm8 < 256
-        h = (self.opcode << 8) | (rt << 8) | imm8
-        return u16(h)
-
-    def __repr__(self):
-        return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset)
-
-def align(x, m):
-    while ((x % m) != 0):
-        x = x + 1
-    return x
-
-
-@armtarget.instruction
-class ldr_pcrel(ArmInstruction):
-    """ ldr Rt, LABEL, load value from pc relative position """
-    mnemonic = 'ldr'
-    operands = (Reg8Op, LabelRef)
-    def __init__(self, rt, label):
-        assert isinstance(label, LabelRef)
-        self.rt = rt
-        self.label = label
-        self.offset = 0
-
-    @classmethod
-    def fromim(cls, im):
-        return cls(im.dst[0], im.others[0])
-
-    def resolve(self, f):
-        la = f(self.label.name)
-        sa = align(self.address + 2, 4)
-        self.offset = (la - sa)
-        if self.offset < 0:
-            self.offset = 0
-
-    def encode(self):
-        rt = self.rt.num
-        assert rt < 8
-        assert self.offset % 4 == 0
-        imm8 = self.offset >> 2
-        assert imm8 < 256
-        assert imm8 >= 0
-        h = (0x9 << 11) | (rt << 8) | imm8
-        return u16(h)
-
-    def __repr__(self):
-        return 'LDR {}, {}'.format(self.rt, self.label.name)
-
-
-@armtarget.instruction
-class ldr_sprel(ls_sp_base_imm8):
-    """ ldr Rt, [SP, imm8] """
-    mnemonic = 'LDR'
-    opcode = 0x98
-
-
-@armtarget.instruction
-class str_sprel(ls_sp_base_imm8):
-    """ str Rt, [SP, imm8] """
-    mnemonic = 'STR'
-    opcode = 0x90
+# TODO: make a difference between armv7 and armv5?
 
 
-@armtarget.instruction
-class mov_imm8_ins(ArmInstruction):
-    """ mov Rd, imm8, move immediate value into register """
-    mnemonic = 'mov'
-    opcode = 4 # 00100 Rd(3) imm8
-    operands = (Reg8Op, Imm8)
-    def __init__(self, rd, imm):
-        if type(imm) is int:
-            imm = Imm8(imm)
-        assert type(imm) is Imm8
-        self.imm = imm.imm
-        assert type(rd) is Reg8Op, str(type(rd))
-        self.rd = rd
-
-    @classmethod
-    def fromim(cls, im):
-        return cls(im.dst[0], im.others[0])
-
-    def encode(self):
-        rd = self.rd.num
-        opcode = self.opcode
-        imm8 = self.imm
-        h = (opcode << 11) | (rd << 8) | imm8
-        return u16(h)
-
-    def __repr__(self):
-        return 'MOV {}, {}'.format(self.rd, self.imm)
-
-
-
-# Arithmatics:
-
-
-
-class regregimm3_base(ArmInstruction):
-    operands = (Reg8Op, Reg8Op, Imm3)
-    def __init__(self, rd, rn, imm3):
-        self.rd = rd
-        self.rn = rn
-        assert type(imm3) is Imm3
-        self.imm3 = imm3
-
-    @classmethod
-    def fromim(cls, im):
-        return cls(im.dst[0], im.src[0], im.others[0])
-
-    def encode(self):
-        rd = self.rd.num
-        rn = self.rn.num
-        imm3 = self.imm3.imm
-        opcode = self.opcode
-        h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd
-        return u16(h)
-
-    def __repr__(self):
-        return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm)
-
-@armtarget.instruction
-class addregregimm3_ins(regregimm3_base):
-    """ add Rd, Rn, imm3 """
-    mnemonic = 'add'
-    opcode = 0b0001110
-
-
-@armtarget.instruction
-class subregregimm3_ins(regregimm3_base):
-    """ sub Rd, Rn, imm3 """
-    mnemonic = 'sub'
-    opcode = 0b0001111
-
-
-class regregreg_base(ArmInstruction):
-    """ ??? Rd, Rn, Rm """
-    operands = (Reg8Op, Reg8Op, Reg8Op)
-    def __init__(self, rd, rn, rm):
-        self.rd = rd
-        self.rn = rn
-        self.rm = rm
-
-    @classmethod
-    def fromim(cls, im):
-        return cls(im.dst[0], im.src[0], im.src[1])
-
-    def encode(self):
-        rd = self.rd.num
-        rn = self.rn.num
-        rm = self.rm.num
-        h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd
-        return u16(h)
-
-    def __repr__(self):
-        return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm)
-
-
-@armtarget.instruction
-class addregs_ins(regregreg_base):
-    mnemonic = 'ADD'
-    opcode = 0b0001100
-
-
-@armtarget.instruction
-class subregs_ins(regregreg_base):
-    mnemonic = 'SUB'
-    opcode = 0b0001101
-
-
-
-@armtarget.instruction
-class movregreg_ext_ins(ArmInstruction):
-    """ mov rd, rm """
-    operands = (ArmRegister, ArmRegister)
-    mnemonic = 'MOV'
-    def __init__(self, rd, rm):
-        self.rd = rd
-        self.rm = rm
-
-    @classmethod
-    def fromim(cls, im):
-        return cls(im.dst[0], im.src[0])
-
-    def encode(self):
-        Rd = self.rd.num & 0x7
-        D = (self.rd.num >> 3) & 0x1
-        Rm = self.rm.num
-        opcode = 0b01000110
-        return u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd)
-
-    def __repr__(self):
-        return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm)
-        
-
-@armtarget.instruction
-class mulregreg_ins(ArmInstruction):
-    """ mul Rn, Rdm """
-    operands = (Reg8Op, Reg8Op)
-    mnemonic = 'MUL'
-    def __init__(self, rn, rdm):
-        self.rn = rn
-        self.rdm = rdm
-
-    @classmethod
-    def fromim(cls, im):
-        assert im.src[1] is im.dst[0]
-        return cls(im.src[0], im.dst[0])
-
-    def encode(self):
-        rn = self.rn.num
-        rdm = self.rdm.num
-        opcode = 0b0100001101
-        h = (opcode << 6) | (rn << 3) | rdm
-        return u16(h)
-
-    def __repr__(self):
-        return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm)
-
-
-class regreg_base(ArmInstruction):
-    """ ??? Rdn, Rm """
-    operands = (Reg8Op, Reg8Op)
-    # TODO: integrate with the code gen interface:
-    src = (0, 1)
-    dst = (0,)
-    def __init__(self, rdn, rm):
-        self.rdn = rdn
-        self.rm = rm
-
-    @classmethod
-    def fromim(cls, im):
-        return cls(im.src[0], im.src[1])
-
-    def encode(self):
-        rdn = self.rdn.num
-        rm = self.rm.num
-        h = (self.opcode << 6) | (rm << 3) | rdn
-        return u16(h)
-
-    def __repr__(self):
-        return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm)
-
-
-@armtarget.instruction
-class movregreg_ins(regreg_base):
-    """ mov Rd, Rm (reg8 operands) """
-    # TODO: match this:
-    pattern = ir.Move(ir.Temp, ir.Temp)
-    mnemonic = 'mov'
-    opcode = 0
-
-
-@armtarget.instruction
-class andregs_ins(regreg_base):
-    mnemonic = 'AND'
-    opcode = 0b0100000000
-
+class ArmTarget(Target):
+    def __init__(self):
+        super().__init__('arm')
+        for i in allins:
+            self.addInstruction(i)
+            # TODO: fix this nicer?
+            #setattr(self, i.__name__, i)
+        self.check()
 
-@armtarget.instruction
-class orrregs_ins(regreg_base):
-    mnemonic = 'ORR'
-    opcode = 0b0100001100
-
-
-@armtarget.instruction
-class cmp_ins(regreg_base):
-    mnemonic = 'CMP'
-    opcode = 0b0100001010
-
-
-@armtarget.instruction
-class lslregs_ins(regreg_base):
-    mnemonic = 'LSL'
-    opcode = 0b0100000010
-
-@armtarget.instruction
-class cmpregimm8_ins(ArmInstruction):
-    """ cmp Rn, imm8 """
-    mnemonic = 'cmp'
-    opcode = 5 # 00101
-    operands = (Reg8Op, Imm8)
-    def __init__(self, rn, imm):
-        self.rn = rn
-        self.imm = imm
-    def encode(self):
-        rn = self.rn.num
-        imm = self.imm.imm
-        opcode = self.opcode
-        h = (opcode << 11) | (rn << 8) | imm
-        return u16(h)
-
-
-# Jumping:
-
-def wrap_negative(x, bits):
-    b = struct.unpack('<I', struct.pack('<i', x))[0]
-    mask = (1 << bits) - 1
-    return b & mask
-
-class jumpBase_ins(ArmInstruction):
-    operands = (LabelRef,)
-    def __init__(self, target_label):
-        assert type(target_label) is LabelRef
-        self.target = target_label
-        self.offset = 0
-
-    def resolve(self, f):
-        la = f(self.target.name)
-        sa = self.address + 4
-        self.offset = (la - sa)
-
-    def __repr__(self):
-        return '{} {}'.format(self.mnemonic, self.target.name)
-
-
-@armtarget.instruction
-class b_ins(jumpBase_ins):
-    mnemonic = 'B'
-    def encode(self):
-        imm11 = wrap_negative(self.offset >> 1, 11)
-        h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode
-        return u16(h)
-
-
-@armtarget.instruction
-class bl_ins(jumpBase_ins):
-    mnemonic = 'BL'
-    def encode(self):
-        imm32 = wrap_negative(self.offset >> 1, 32)
-        imm11 = imm32 & 0x7FF
-        imm10 = (imm32 >> 11) & 0x3FF
-        j1 = 1 # TODO: what do these mean?
-        j2 = 1
-        s = (imm32 >> 24) & 0x1
-        h1 = (0b11110 << 11) | (s << 10) | imm10 
-        h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11
-        return u16(h1) + u16(h2)
-
-
-class cond_base_ins(jumpBase_ins):
-    def encode(self):
-        imm8 = wrap_negative(self.offset >> 1, 8)
-        h = (0b1101 << 12) | (self.cond << 8) | imm8
-        return u16(h)
-
-
-@armtarget.instruction
-class beq_ins(cond_base_ins):
-    mnemonic = 'beq'
-    cond = 0
-
-
-@armtarget.instruction
-class bne_ins(cond_base_ins):
-    mnemonic = 'bne'
-    cond = 1
-
-
-@armtarget.instruction
-class blt_ins(cond_base_ins):
-    mnemonic = 'blt'
-    cond = 0b1011
-
-
-@armtarget.instruction
-class bgt_ins(cond_base_ins):
-    mnemonic = 'bgt'
-    cond = 0b1100
-
-
-@armtarget.instruction
-class push_ins(ArmInstruction):
-    operands = (RegisterSet,)
-    mnemonic = 'push'
-    def __init__(self, regs):
-        assert (type(regs),) == self.operands, (type(regs),)
-        self.regs = regs
-    def __repr__(self):
-        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
-    def encode(self):
-        reg_list = 0
-        M = 0
-        for n in self.regs.registerNumbers():
-            if n < 8:
-                reg_list |= (1 << n)
-            elif n == 14:
-                M = 1
-            else:
-                raise NotImplementedError('not implemented for this register')
-        h = (0x5a << 9) | (M << 8) | reg_list
-        return u16(h)
-
-
-@armtarget.instruction
-class pop_ins(ArmInstruction):
-    operands = (RegisterSet,)
-    mnemonic = 'pop'
-
-    def __init__(self, regs):
-        self.regs = regs
-
-    def __repr__(self):
-        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
-
-    def encode(self):
-        reg_list = 0
-        P = 0
-        for n in self.regs.registerNumbers():
-            if n < 8:
-                reg_list |= (1 << n)
-            elif n == 15:
-                P = 1
-            else:
-                raise NotImplementedError('not implemented for this register')
-        h = (0x5E << 9) | (P << 8) | reg_list
-        return u16(h)
-
-
-@armtarget.instruction
-class yield_ins(ArmInstruction):
-    operands = ()
-    mnemonic = 'yield'
-
-    def encode(self):
-        return u16(0xbf10)
-
-# misc:
-
-# add/sub SP:
-class addspsp_base(ArmInstruction):
-    operands = (RegSpOp, RegSpOp, Imm7)
-    def __init__(self, _sp, _sp2, imm7):
-        self.imm7 = imm7.imm
-        assert self.imm7 % 4 == 0
-        self.imm7 >>= 2
-
-    def encode(self):
-        return u16((self.opcode << 7) |self.imm7)
-
-    def __repr__(self):
-        return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2)
-
-@armtarget.instruction
-class addspsp_ins(addspsp_base):
-    mnemonic = 'add'
-    opcode = 0b101100000
-    
-
-@armtarget.instruction
-class subspsp_ins(addspsp_base):
-    mnemonic = 'sub'
-    opcode = 0b101100001
-
-armtarget.check()
-
+    def startCode(self, outs):
+        """ Emit some startup code in the output stream """
+        outs.selectSection('code')
+        # assembly glue to make it work:
+        # TODO: this must be in source code, not in compiler
+        outs.emit(Dcd(Imm32(0x20000678)))   # initial SP
+        outs.emit(Dcd(Imm32(0x08000009)))   # reset vector
+        outs.emit(B(LabelRef('main')))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/target/armv7.lidl	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,16 @@
+
+
+instruction yield {
+  encoding: 0xbf10
+}
+
+base rrr_base {
+  encoding: ''
+}
+
+instruction add : rrr_base {
+  semantics: {
+    Rd = Rm + Rn;
+  }
+}
+
--- a/python/target/basetarget.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/target/basetarget.py	Wed Nov 27 08:06:42 2013 +0100
@@ -12,47 +12,36 @@
 
 # standard immediates:
 
-class Imm8:
+class ImmBase:
     def __init__(self, imm):
-        assert imm < 256
+        assert type(imm) is int
+        assert imm < self.Max()
         self.imm = imm
 
     @classmethod
-    def Create(cls, vop):
-        if type(vop) is ANumber and vop.number < 256:
-            return cls(vop.number)
-
-class Imm7:
-    def __init__(self, imm):
-        assert imm < 128
-        self.imm = imm
+    def Max(cls):
+        return 2**cls.bits
 
     @classmethod
     def Create(cls, vop):
-        if type(vop) is ANumber and vop.number < 128:
+        if type(vop) is ANumber and vop.number < cls.Max():
             return cls(vop.number)
 
-class Imm3:
-    def __init__(self, imm):
-        assert imm < 8
-        assert type(imm) is int
-        self.imm = imm
+
+class Imm3(ImmBase):
+    bits = 3
 
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ANumber and vop.number < 8:
-            return cls(vop.number)
+
+class Imm7(ImmBase):
+    bits = 7
 
-class Imm32:
-    def __init__(self, imm):
-        assert imm < 2**32
-        assert type(imm) is int
-        self.imm = imm
+
+class Imm8(ImmBase):
+    bits = 8
 
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ANumber and vop.number < 2**32:
-            return cls(vop.number)
+
+class Imm32(ImmBase):
+    bits = 32
 
 
 class LabelRef:
@@ -65,9 +54,12 @@
         if type(vop) is ASymbol:
             return cls(vop.name)
 
+
 class Instruction:
+    """ Base instruction class """
     def encode(self):
         raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self)))
+
     def resolve(self, f):
         pass
 
@@ -77,7 +69,6 @@
     def encode(self):
         return bytes()
 
-    
 
 class PseudoInstruction(Instruction):
     pass
@@ -127,6 +118,7 @@
             pad.append(0)
         return bytes(pad)
 
+
 class DebugInfo(PseudoInstruction):
     def __init__(self, i):
         self.info = i
@@ -137,6 +129,7 @@
     def encode(self):
         return bytes()
 
+
 class Register(Operand):
     def __init__(self, name):
         self.name = name
@@ -195,4 +188,3 @@
                 if all(isinstance(rop, optype) for rop, optype in zip(rops, ic.operands)):
                     return ic(*rops)
         raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
-
--- a/python/target/msp430.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/target/msp430.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,4 +1,4 @@
-from target import Register, Instruction, Target
+from .basetarget import Register, Instruction, Target
 from asmnodes import ASymbol, ANumber
 from ppci import CompilerError
 import struct
@@ -245,4 +245,3 @@
 twoOpIns('bis', 13)
 twoOpIns('xor', 14)
 twoOpIns('and', 15)
-
--- a/python/target/openrisc.lidl	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/target/openrisc.lidl	Wed Nov 27 08:06:42 2013 +0100
@@ -1,5 +1,5 @@
 
-// Openrisc description in lidl (lcfos isa description language)
+// Openrisc description in LIDL (lcfos isa description language)
 
 // Register storage:
 storage r {
--- a/python/usb.py	Sun Nov 24 11:24:15 2013 +0100
+++ /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)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/__init__.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,4 @@
+
+
+from .hexfile import HexFile, HexFileException
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/adi.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,59 @@
+
+# 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)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/devices.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,63 @@
+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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/hexfile.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,154 @@
+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(len(r.data) for r in self.regions)
+        return 'Hexfile containing {} bytes'.format(size)
+
+    def dump(self):
+        print(self)
+        for r in self.regions:
+            print(r)
+
+    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 EndAddress(self):
+        return self.address + len(self.data)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/lsusb.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,31 @@
+#!/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)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/st-flash.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,81 @@
+#!/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)
+    r = hf.regions[0]
+    dev.writeFlash(r.address, r.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()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/stlink.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,367 @@
+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('<H', reply[0:2])[0]
+   def readTraceData(self):
+      bsize = self.getTraceByteCount()
+      if bsize > 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('<II', address, value)
+      r = self.send_recv(cmd, 2)
+   def read_debug32(self, address):
+      cmd = bytearray(16)
+      cmd[0:2] = DEBUG_COMMAND, JTAG_READDEBUG_32BIT
+      cmd[2:6] = struct.pack('<I', address) # pack into u32 little endian
+      reply = self.send_recv(cmd, 8)
+      return struct.unpack('<I', reply[4:8])[0]
+   def write_reg(self, reg, value):
+      cmd = bytearray(16)
+      cmd[0:3] = DEBUG_COMMAND, DEBUG_WRITEREG, reg
+      cmd[3:7] = struct.pack('<I', value)
+      r = self.send_recv(cmd, 2)
+   def read_reg(self, reg):
+      cmd = bytearray(16)
+      cmd[0:3] = DEBUG_COMMAND, DEBUG_READREG, reg
+      reply = self.send_recv(cmd, 4)
+      return struct.unpack('<I', reply)[0]
+   def read_all_regs(self):
+      cmd = bytearray(16)
+      cmd[0:2] = DEBUG_COMMAND, DEBUG_READALLREGS
+      reply = self.send_recv(cmd, 84)
+      fmt = '<' + 'I' * 21 # unpack 21 register values
+      return list(struct.unpack(fmt, reply))
+   def write_mem32(self, address, content):
+      assert len(content) % 4 == 0
+      cmd = bytearray(16)
+      cmd[0:2] = DEBUG_COMMAND, DEBUG_WRITEMEM_32BIT
+      cmd[2:8] = struct.pack('<IH', address, len(content))
+      self.send_recv(cmd)
+      self.send_recv(content)
+   def read_mem32(self, address, length):
+      assert length % 4 == 0
+      cmd = bytearray(16)
+      cmd[0:2] = DEBUG_COMMAND, DEBUG_READMEM_32BIT
+      cmd[2:8] = struct.pack('<IH', address, length)
+      reply = self.send_recv(cmd, length) # expect memory back!
+      return reply
+
+   # Helper 2 functions:
+   def send_recv(self, tx, rxsize=0):
+      """ Helper function that transmits and receives data in bulk mode. """
+      # TODO: we could use here the non-blocking libusb api.
+      tx = bytes(tx)
+      #assert len(tx) == 16
+      self.devHandle.bulkWrite(2, tx) # write to endpoint 2
+      if rxsize > 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!')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/stm32.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,264 @@
+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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/utils/usb.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,245 @@
+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)
--- a/python/zcc.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/python/zcc.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 import sys
 import argparse
@@ -8,7 +8,7 @@
 import ppci
 import codegen
 import outstream
-import hexfile
+from utils import HexFile
 import target
 
 
@@ -23,7 +23,8 @@
 
 
 target_list = [target.armtarget]
-targetnames = {t.name: t for t in target_list}
+targets = {t.name: t for t in target_list}
+targetnames = list(targets.keys())
 
 # Parse arguments:
 parser = argparse.ArgumentParser(description='lcfos Compiler')
@@ -37,14 +38,14 @@
 parser.add_argument('--dumpasm', action='store_true', help="Dump ASM-code")
 parser.add_argument('--optimize', action='store_true', help="Optimize")
 parser.add_argument('--target', help="Backend selection",
-    choices=targetnames.keys())
+    choices=targetnames, required=True)
 parser.add_argument('-o', '--output', help='Output file', metavar='filename')
 parser.add_argument('--hexfile', help='Output hexfile',
     type=argparse.FileType('w'))
 parser.add_argument('--log', help='Log level (INFO,DEBUG)', type=logLevel)
 
 
-def zcc(srcs, imps, outs, diag, dumpir=False):
+def zcc(srcs, imps, tg, outs, diag, dumpir=False):
     """
         Compile sources into output stream.
         Sources is an iterable of open files.
@@ -52,9 +53,14 @@
     logging.info('Zcc started')
     # Front end:
     c3b = c3.Builder(diag)
-    tg = target.armtarget.armtarget
-    # TODO select target here!
-    cg = codegen.CodeGenerator(outs, tg)
+    cg = codegen.CodeGenerator(tg)
+
+    # TODO: remove this arm specifics:
+    outs.getSection('code').address = 0x08000000
+    outs.getSection('data').address = 0x20000000
+
+    # Emit some custom start code:
+    tg.startCode(outs)
     for ircode in c3b.build(srcs, imps):
         if not ircode:
             return
@@ -65,7 +71,10 @@
             ircode.dump()
 
         # Code generation:
-        cg.generate(ircode)
+        cg.generate(ircode, outs)
+    # TODO: fixup references, do this in another way?
+    outs.backpatch()
+    outs.backpatch()  # Why two times?
     return c3b.ok
 
 
@@ -73,11 +82,11 @@
     logging.basicConfig(format=logformat, level=args.log)
     src = args.source
     imps = args.imp
+    tg = targets[args.target]
     diag = ppci.DiagnosticsManager()
     outs = outstream.TextOutputStream()
 
-    # Invoke compiler:
-    res = zcc(src, imps, outs, diag, dumpir=args.dumpir)
+    res = zcc(src, imps, tg, outs, diag, dumpir=args.dumpir)
     if not res:
         diag.printErrors(src)
         return 1
@@ -93,7 +102,7 @@
 
     if args.hexfile:
         logging.info('Creating hexfile')
-        hf = hexfile.HexFile()
+        hf = HexFile()
         hf.addRegion(0x08000000, code_bytes)
         hf.save(args.hexfile)
     return 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testarmasm.py	Wed Nov 27 08:06:42 2013 +0100
@@ -0,0 +1,149 @@
+import unittest
+import outstream
+from asm import Assembler
+from testasm import AsmTestCaseBase
+from target import armtarget
+
+
+class AssemblerARMTestCase(AsmTestCaseBase):
+    def setUp(self):
+        self.t = armtarget
+        self.o = outstream.BinOutputStream()
+        self.o.selectSection('.text')
+        self.a = Assembler(target=self.t, stream=self.o)
+
+    def testMapOperand(self):
+        pass
+
+    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')
--- a/test/testasm.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testasm.py	Wed Nov 27 08:06:42 2013 +0100
@@ -4,7 +4,6 @@
 from ppci import CompilerError
 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber
 from asm import tokenize, Assembler
-import target.armtarget as arm
 import outstream
 from target import Label
 
@@ -83,25 +82,13 @@
         # A line can be empty
         self.a.parse_line('')
     
+
 class AssemblerOtherTestCase(unittest.TestCase):
     def testWithoutTarget(self):
         a = Assembler()
         with self.assertRaises(CompilerError):
             a.assemble_line('')
 
-    @unittest.skip 
-    def testX86(self):
-        testsrc = """ ; tst
-        begin:
-        mov rax, rbx ; 0x48, 0x89, 0xd8
-        xor rcx, rbx ; 0x48, 0x31, 0xd9
-        inc rcx ; 0x48 0xff 0xc1
-        """
-        a = Assembler()
-        a.assemble(testsrc)
-        # Compare with nasm output:
-        nasmbytes = [0x48, 0x89, 0xd8, 0x48, 0x31, 0xd9, 0x48, 0xff, 0xc1]
-
 
 class OustreamTestCase(unittest.TestCase):
     def test1(self):
@@ -112,6 +99,7 @@
 
 
 class AsmTestCaseBase(unittest.TestCase):
+    """ Base testcase for assembly """
     def feed(self, line):
         self.a.assemble(line)
 
@@ -119,199 +107,5 @@
         self.assertSequenceEqual(bytes.fromhex(hexstr), self.o.Data)
 
 
-class AssemblerMSP430TestCase(AsmTestCaseBase):
-    def setUp(self):
-        self.t = msp430.msp430target
-        self.o = outstream.BinOutputStream()
-        self.o.selectSection('.text')
-        self.a = Assembler(target=self.t, stream=self.o)
-
-    def testMapMovInstruction(self):
-        i = AInstruction('mov', [ASymbol('r14'), ASymbol('r15')])
-        ri = self.t.mapInstruction(i)
-
-    def testMapRetiInstruction(self):
-        i = AInstruction('reti', [])
-        ri = self.t.mapInstruction(i)
-
-    @unittest.skip
-    def testMapOperand(self):
-        o = ASymbol('r14')
-        mo = self.t.mapOperand(o)
-        self.assertEqual(mo, msp430.r14)
-
-    @unittest.skip
-    def testMapOperandIndirection(self):
-        o = AUnop('[]', ASymbol('r14'))
-        mo = self.t.mapOperand(o)
-
-    def testMov(self):
-        line1 = "mov r14, r15"
-        self.feed(line1)
-        self.check('0F4E')
-
-    def testMov1337(self):
-        line1 = "mov 0x1337, r12"
-        self.feed(line1)
-        self.check('3C403713')
-
-    def testAdd(self):
-        line1 = "add r15, r13"
-        self.feed(line1)
-        self.check('0D5F')
-
-    def testReti(self):
-        line1 = "reti"
-        self.feed(line1)
-        self.check('0013')
-
-    def testMSPinstructionCount(self):
-        """ Check that there are 27 instructions """
-        self.assertEqual(27, len(self.t.instructions))
-
-
-class AssemblerARMTestCase(AsmTestCaseBase):
-    def setUp(self):
-        self.t = arm.armtarget
-        self.o = outstream.BinOutputStream()
-        self.o.selectSection('.text')
-        self.a = Assembler(target=self.t, stream=self.o)
-
-    def testMapOperand(self):
-        pass
-
-    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')
-
 if __name__ == '__main__':
     unittest.main()
--- a/test/testc3.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testc3.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,7 +1,6 @@
 import c3
 import time
 import ppci
-import x86
 import ir
 import unittest
 import glob
--- a/test/testcg.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testcg.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,7 +1,8 @@
 import unittest
-import ppci, codegen, ir
-import cortexm3 as arm
-import codegenarm
+import ppci
+from codegen import CodeGenerator
+import ir
+from target import armtarget
 import outstream
 
 
@@ -14,26 +15,27 @@
 
 class testCodeGeneration(unittest.TestCase):
     def setUp(self):
-        self.cg = codegen.CodeGenerator(arm.armtarget)
+        self.cg = CodeGenerator(armtarget)
 
     def testFunction(self):
+        s = outstream.OutputStream()
         m, f, bb = genTestFunction()
-        bb.addInstruction(ir.Const(123))
+        bb.addInstruction(ir.Exp(ir.Const(123)))
         bb.addInstruction(ir.Jump(f.epiloog))
         m.check()
-        obj = self.cg.generate(m)
+        obj = self.cg.generate(m, s)
         self.assertTrue(obj)
 
 
 class testArmCodeGeneration(unittest.TestCase):
     def testStack(self):
         s = outstream.OutputStream()
-        cg = codegenarm.ArmCodeGenerator(s)
+        cg = CodeGenerator(armtarget)
         m, f, bb = genTestFunction()
         bb.addInstruction(ir.Move(ir.Mem(ir.Const(1)), ir.Const(22)))
         bb.addInstruction(ir.Jump(f.epiloog))
         m.check()
-        cg.generate(m)
+        cg.generate(m, s)
         #s.dump()
 
 
--- a/test/testhexfile.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testhexfile.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,6 +1,6 @@
 import unittest
 import io
-from hexfile import HexFile, HexFileException
+from utils import HexFile, HexFileException
 
 
 class testHexFile(unittest.TestCase):
@@ -38,6 +38,15 @@
         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'))
@@ -74,9 +83,7 @@
 
     def testLoad(self):
         hf = HexFile()
-        dummyhex = """
-        :01400000aa15
-        """
+        dummyhex = """:01400000aa15"""
         f = io.StringIO(dummyhex)
         hf.load(f)
         self.assertEqual(1, len(hf.regions))
@@ -99,4 +106,3 @@
 
 if __name__ == '__main__':
     unittest.main()
-
--- a/test/testir.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testir.py	Wed Nov 27 08:06:42 2013 +0100
@@ -2,7 +2,8 @@
 import sys
 import c3
 import ppci
-import ir, x86, transform
+import ir
+import transform
 import optimize
 
 
@@ -129,34 +130,5 @@
 """
 
 if __name__ == '__main__':
-    #unittest.main()
-    #sys.exit()
-    diag = ppci.DiagnosticsManager()
-    builder = c3.Builder(diag)
-    cgenx86 = x86.X86CodeGenSimple(diag)
-    ir = builder.build(testsrc)
-    diag.printErrors(testsrc)
-    ir.check()
-    ir.dump()
-    optimize.optimize(ir)
-    print('dump IR')
-    print('dump IR')
-    print('dump IR')
-    print('dump IR')
-    ir.dump()
-
-    # Dump a graphiz file:
-    with open('graaf.gv', 'w') as f:
-      ir.dumpgv(f)
-    os.system('dot -Tsvg -ograaf.svg graaf.gv')
-
+    unittest.main()
     sys.exit()
-    asm = cgenx86.genBin(ir)
-    #for a in asm:
-    #   print(a)
-    with open('out.asm', 'w') as f:
-      f.write('BITS 64\n')
-      for a in asm:
-         f.write(str(a) + '\n')
-         print(a)
-
--- a/test/testmsp430asm.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testmsp430asm.py	Wed Nov 27 08:06:42 2013 +0100
@@ -3,15 +3,14 @@
 import unittest
 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber
 from asm import tokenize, Assembler
-import msp430
 import outstream
-from target import Label
+from target import Label, msp430target
 from testasm import AsmTestCaseBase
 
 
 class AssemblerMSP430TestCase(AsmTestCaseBase):
     def setUp(self):
-        self.t = msp430.msp430target
+        self.t = msp430target
         self.o = outstream.BinOutputStream()
         self.o.selectSection('.text')
         self.a = Assembler(target=self.t, stream=self.o)
--- a/test/testx86asm.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testx86asm.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,18 +1,27 @@
 #!/usr/bin/python
 
 import unittest
+from testasm import AsmTestCaseBase
 
 
-class AssemblerTestCase(unittest.TestCase):
-   """ 
+class AssemblerTestCase(AsmTestCaseBase):
+    """ 
     test methods start with 'test*' 
      Checks several assembly constructs agains their bytecodes
-   """
-   def setUp(self):
+    """
+    def setUp(self):
         self.skipTest('not implemented yet')
         self.assembler = Assembler('x86-64')
+        a = Assembler()
 
-   def tstAssembler(self):
+    @unittest.skip 
+    def testX86(self):
+        self.feed('mov rax, rbx')  # ; 0x48, 0x89, 0xd8
+        self.feed('xor rcx, rbx')  # ; 0x48, 0x31, 0xd9
+        self.feed('inc rcx')  # ; 0x48 0xff 0xc1
+        self.check('48 89 d8 48 31 d9 48 ff c1')
+        
+    def tstAssembler(self):
       """ Check all kind of assembler cases """
       assert(assembler.shortjump(5) == [0xeb, 0x5])
       assert(assembler.shortjump(-2) == [0xeb, 0xfc])
@@ -21,35 +30,43 @@
       assert(assembler.nearjump(-2) == [0xe9, 0xf9, 0xff,0xff,0xff])
       assert(assembler.nearjump(10,'LE') == [0x0f, 0x8e, 0xa,0x0,0x0,0x0])
 
-   def testCall(self):
-      assert(assembler.call('r10') == [0x41, 0xff, 0xd2])
-      assert(assembler.call('rcx') == [0xff, 0xd1])
+    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):
+    def testXOR(self):
       assert(assembler.xorreg64('rax', 'rax') == [0x48, 0x31, 0xc0])
       assert(assembler.xorreg64('r9', 'r8') == [0x4d, 0x31, 0xc1])
       assert(assembler.xorreg64('rbx', 'r11') == [0x4c, 0x31, 0xdb])
 
-   def testINC(self):
+    def testINC(self):
       assert(assembler.increg64('r11') == [0x49, 0xff, 0xc3])
       assert(assembler.increg64('rcx') == [0x48, 0xff, 0xc1])
 
-   def testPush(self):
+    def testPush(self):
       assert(assembler.push('rbp') == [0x55])
       assert(assembler.push('rbx') == [0x53])
       assert(assembler.push('r12') == [0x41, 0x54])
-   def testPop(self):
-      assert(assembler.pop('rbx') == [0x5b])
-      assert(assembler.pop('rbp') == [0x5d])
-      assert(assembler.pop('r12') == [0x41, 0x5c])
 
-   def testAsmLoads(self):
+    def testPop(self):
+        self.feed('pop rbx')
+        self.feed('pop rbp')
+        self.feed('pop r12')
+        assert(assembler.pop('rbx') == [0x5b])
+        assert(assembler.pop('rbp') == [0x5d])
+        assert(assembler.pop('r12') == [0x41, 0x5c])
+
+    def testAsmLoads(self):
       # TODO constant add testcases
       assert(assembler.mov('rbx', 'r14') == [0x4c, 0x89, 0xf3])
       assert(assembler.mov('r12', 'r8')  == [0x4d, 0x89, 0xc4])
       assert(assembler.mov('rdi', 'rsp') == [0x48, 0x89, 0xe7])
 
-   def testAsmMemLoads(self):
+    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])
 
@@ -61,7 +78,7 @@
 
       assert(assembler.mov('r11', ['RIP', 0xf]) == [0x4c,0x8b,0x1d,0x0f,0x0,0x0,0x0])
 
-   def testAsmMemStores(self):
+    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])
@@ -72,27 +89,28 @@
 
       assert(assembler.mov(['RIP', 0xf], 'r9') == [0x4c,0x89,0x0d,0x0f,0x0,0x0,0x0])
 
-   def testAsmMOV8(self):
+    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])
 
-   def testAsmLea(self):
+    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])
 
-   def testAssemblerCMP(self):
+    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])
-   def testAssemblerADD(self):
+
+    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])
@@ -101,7 +119,7 @@
       assert(assembler.addreg64('r11', 0x1234567) == [0x49, 0x81, 0xc3, 0x67, 0x45,0x23,0x1])
       assert(assembler.addreg64('rsp', 0x33) == [0x48, 0x83, 0xc4, 0x33])
 
-   def testAssemblerSUB(self):
+    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])
@@ -109,12 +127,12 @@
       assert(assembler.subreg64('rsp', 0x123456) == [0x48, 0x81, 0xec, 0x56,0x34,0x12,0x0])
       assert(assembler.subreg64('rsp', 0x12) == [0x48, 0x83, 0xec, 0x12])
 
-   def testAssemblerIDIV(self):
+    def testAssemblerIDIV(self):
       assert(assembler.idivreg64('r11') == [0x49, 0xf7, 0xfb])
       assert(assembler.idivreg64('rcx') == [0x48, 0xf7, 0xf9])
       assert(assembler.idivreg64('rsp') == [0x48, 0xf7, 0xfc])
 
-   def testAssemblerIMUL(self):
+    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])
--- a/test/testzcc.py	Sun Nov 24 11:24:15 2013 +0100
+++ b/test/testzcc.py	Wed Nov 27 08:06:42 2013 +0100
@@ -1,10 +1,10 @@
 import unittest
-import glob
 import zcc
 import outstream
 import ppci
 import io
 import os
+import target
 
 
 class ZccTestCase(unittest.TestCase):
@@ -16,6 +16,8 @@
         for fn in imps:
             arg_list.append('-i')
             arg_list.append(os.path.join(basedir, fn))
+        arg_list.append('--target')
+        arg_list.append('arm')
         args = zcc.parser.parse_args(arg_list)
         self.assertEqual(0, zcc.main(args))
 
@@ -39,7 +41,8 @@
         f = io.StringIO(src)
         diag = ppci.DiagnosticsManager()
         outs = outstream.TextOutputStream()
-        self.assertTrue(zcc.zcc([f], [], outs, diag))
+        tg = target.armtarget
+        self.assertTrue(zcc.zcc([f], [], tg, outs, diag))
         code = outs.getSection('code')
         self.assertEqual(0x08000000, code.address)
         data = outs.getSection('data')