changeset 219:1fa3e0050b49

Expanded ad hoc code generator
author Windel Bouwman
date Sat, 06 Jul 2013 12:38:09 +0200
parents 494828a7adf1
children 3f6c30a5d234
files python/asm.py python/c3/parser.py python/codegenarm.py python/cortexm3.py python/ir/basicblock.py python/ir/instruction.py python/outstream.py python/stm32f4/blink.c3 python/target.py python/testasm.py python/transform.py python/zcc.py
diffstat 12 files changed, 362 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/python/asm.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/asm.py	Sat Jul 06 12:38:09 2013 +0200
@@ -137,7 +137,9 @@
         self.emit = emitter
         self.p.parse(tokens)
 
+# Pre construct parser to save time:
 asmParser = Parser()
+
 class Assembler:
     def __init__(self, target=None):
         self.target = target
--- a/python/c3/parser.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/c3/parser.py	Sat Jul 06 12:38:09 2013 +0200
@@ -41,14 +41,14 @@
       return False
 
     def NextToken(self):
-      t = self.token
-      if t.typ != 'END':
-         self.token = self.tokens.__next__()
-      return t
+        t = self.token
+        if t.typ != 'END':
+            self.token = self.tokens.__next__()
+        return t
 
     def initLex(self, source):
-      self.tokens = lexer.tokenize(source) # Lexical stage
-      self.token = self.tokens.__next__()
+        self.tokens = lexer.tokenize(source) # Lexical stage
+        self.token = self.tokens.__next__()
     def addDeclaration(self, decl):
         self.currentPart.declarations.append(decl)
     
@@ -88,7 +88,7 @@
     # Type system
     def parseTypeSpec(self):
         # For now, do simple type spec, just parse an ID:
-        return self.parseDesignator()
+        #return self.parseDesignator()
         if self.Peak == 'struct':
             self.Consume('struct')
             self.Consume('{')
--- a/python/codegenarm.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/codegenarm.py	Sat Jul 06 12:38:09 2013 +0200
@@ -4,7 +4,10 @@
 from ppci import CompilerError
 
 class ArmCodeGenerator:
-    """ Simple code generator """
+    """
+        Simple code generator
+        Ad hoc implementation
+    """
     def __init__(self, out):
         self.outs = out
 
@@ -21,8 +24,14 @@
             # TODO: use initial value:
             self.emit(arm.dcd_ins(0))
 
+        self.imms = [] # list with immediates relative to PC.
         self.outs.selectSection('code')
         for f in ircode.Functions:
+            # Add global variable addresses to immediate list:
+            for gvar in ircode.Variables:
+                pass  #self.imms.append((
+
+            self.stack_frame = []
             self.emit(ALabel(f.name))
             # Save some registers:
             self.emit(arm.push_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6,arm.r7,arm.lr})))
@@ -31,27 +40,67 @@
                 for ins in bb.Instructions:
                     self.generateInstruction(ins)
 
+            self.outs.align(4)
+            while self.imms:
+                l, v = self.imms.pop()
+                self.emit(ALabel(l))
+                self.emit(arm.dcd_ins(v))
+            self.outs.align(4)
+
+    def getStack(self, v):
+        off = self.stack_frame.index(v)
+        return off * 4
+    def addStack(self, v):
+        self.stack_frame.append(v)
+        return self.getStack(v)
+    def getGlobal(self, r, g):
+        _global_address = g.name + '__global'
+        self.emit(arm.ldr_pcrel(r, ALabel(_global_address)))
+
     def generateInstruction(self, ins):
         if type(ins) is ir.Branch:
-            self.emit(arm.jmp_ins(ins.target))
-        elif type(ins) is ir.ImmLoad and ins.value < 255:
-            self.emit(arm.mov_ins(arm.r0, arm.Imm8(ins.value)))
-            # determine stack frame..
-            self.emit(arm.mov_ins(arm.r1, arm.Imm8(9)))
-            #self.emit(arm.
-        elif type(ins) is ir.ImmLoad and ins.value < (2**32):
-            print(ins)
+            tgt = ALabel(ins.target.name)
+            self.emit(arm.jmp_ins(tgt))
+        elif type(ins) is ir.ImmLoad:
+            lname = ins.target.name + '_ivalue'
+            self.emit(arm.ldr_pcrel(arm.r0, ALabel(lname)))
+            self.imms.append((lname, ins.value))
+            self.emit(arm.str_sprel(arm.r0, self.addStack(ins.target)))
         elif type(ins) is ir.Store:
-            print(ins)
-        elif type(ins) is ir.Return:
-            self.emit(arm.pop_ins(arm.RegisterSet({arm.r5, arm.r6, arm.pc})))
+            # Load value in r0:
+            self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.value)))
+            # store in memory:
+            self.getGlobal(arm.r1, ins.location)
+            self.emit(arm.storeimm5_ins(arm.r0, arm.MemoryOp(arm.r1, 0)))
         elif type(ins) is ir.Load:
-            print(ins)
+            self.getGlobal(arm.r0, ins.location)
+            self.emit(arm.loadimm5_ins(arm.r0, arm.MemoryOp(arm.r0, 0)))
+            # Store value on stack:
+            self.emit(arm.str_sprel(arm.r0, self.addStack(ins.value)))
         elif type(ins) is ir.BinaryOperator:
-            print(ins)
+            # Load operands:
+            self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.value1)))
+            self.emit(arm.ldr_sprel(arm.r1, self.getStack(ins.value2)))
+            # do operation:
+            if ins.operation == '+':
+                self.emit(arm.addregs_ins(arm.r0, arm.r0, arm.r1))
+            else:
+                print('operation not implemented', ins.operation)
+            # Store value back:
+            self.emit(arm.str_sprel(arm.r0, self.addStack(ins.result)))
+        elif type(ins) is ir.Return:
+            self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc})))
         elif type(ins) is ir.ConditionalBranch:
-            print(ins)
+            self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.a)))
+            self.emit(arm.ldr_sprel(arm.r1, self.getStack(ins.b)))
             self.emit(arm.cmp_ins(arm.r1, arm.r0))
+            tgt_yes = ALabel(ins.lab1.name)
+            if ins.cond == '==':
+                self.emit(arm.beq_ins(tgt_yes))
+            else:
+                print('TODO', ins.cond)
+            tgt_no = ALabel(ins.lab2.name)
+            self.emit(arm.jmp_ins(tgt_no))
         else:
             raise CompilerError('IR "{}" not covered'.format(ins))
 
--- a/python/cortexm3.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/cortexm3.py	Sat Jul 06 12:38:09 2013 +0200
@@ -1,6 +1,6 @@
 import struct, types
 from target import Register, Instruction, Target, Imm8, Label, Imm3
-from asmnodes import ASymbol, ANumber, AUnop, ABinop
+from asmnodes import ASymbol, ANumber, AUnop, ABinop, ALabel
 from ppci import CompilerError
 import ir
 
@@ -36,6 +36,23 @@
             if name in regs:
                 r = regs[name]
                 return cls(r.num)
+                
+class Reg8Op:
+    def __init__(self, num):
+        assert num < 8
+        self.num = num
+
+    @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 r.num < 8:
+                    return cls(r.num)
 
 def getRegNum(n):
     for r in armtarget.registers:
@@ -57,6 +74,9 @@
         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 == '[]':
@@ -77,7 +97,38 @@
             else:
                 return
             return cls(getRegNum(basereg.num), offset)
-        pass
+
+class MemoryOpReg8Imm5:
+    def __init__(self, basereg, offset):
+        assert type(basereg) is ArmReg
+        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):
@@ -129,10 +180,6 @@
 armtarget.registers.append(r6)
 r7 = ArmReg(7, 'r7')
 armtarget.registers.append(r7)
-r10 = ArmReg(10, 'r10')
-armtarget.registers.append(r10)
-r11 = ArmReg(11, 'r11')
-armtarget.registers.append(r11)
 # Other registers:
 # TODO
 sp = ArmReg(13, 'sp')
@@ -145,54 +192,104 @@
 class ArmInstruction(Instruction):
     pass
 
-class ldr_ins(ArmInstruction):
-    mnemonic = 'ldr'
-    opcode = 1337
-    irpattern = 'todo'
-
 class dcd_ins(ArmInstruction):
     mnemonic = 'dcd'
     def __init__(self, expr):
         self.expr = expr
+
     def encode(self):
         return u32(self.expr)
 
-@armtarget.instruction
-class storeimm5_ins(ArmInstruction):
-    """ str Rt, [Rn, imm5], store value into memory """
-    mnemonic = 'str'
-    operands = (RegOp, MemoryOp)
+    def __repr__(self):
+        return 'DCD 0x{0:X}'.format(self.expr)
+
+
+
+# Memory related
+
+class LS_imm5_base(ArmInstruction):
+    """ ??? Rt, [Rn, imm5] """
+    operands = (Reg8Op, MemoryOpReg8Imm5)
     def __init__(self, rt, memop):
         assert memop.offset % 4 == 0
         self.imm5 = memop.offset >> 2
         self.rn = memop.basereg.num
         self.rt = rt.num
+        self.memloc = memop
+        assert self.rn < 8
+        assert self.rt < 8
 
     def encode(self):
         Rn = self.rn
         Rt = self.rt
         imm5 = self.imm5
-        h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt
+
+        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
+
+@armtarget.instruction
+class loadimm5_ins(LS_imm5_base):
+    mnemonic = 'LDR'
+    opcode = 0xD
+
+class ls_sp_base_imm8(ArmInstruction):
+    operands = (Reg8Op, MemoryOp)
+    def __init__(self, rt, memop):
+        self.rt = rt
+        assert memop.basereg.num == 13
+        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)
+
 @armtarget.instruction
-class loadimm5_ins(ArmInstruction):
-    """ str Rt, [Rn, imm5], store value into memory """
+class ldr_pcrel(ArmInstruction):
+    """ ldr Rt, [PC, imm8], store value into memory """
     mnemonic = 'ldr'
     operands = (RegOp, MemoryOp)
-    def __init__(self, rt, memop):
-        assert memop.offset % 4 == 0
-        self.imm5 = memop.offset >> 2
-        self.rn = memop.basereg.num
-        self.rt = rt.num
+    def __init__(self, rt, label):
+        self.rt = rt
+        self.label = label
+        self.offset = 0
 
     def encode(self):
-        Rn = self.rn
-        Rt = self.rt
-        imm5 = self.imm5
-        h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        rt = self.rt.num
+        assert rt < 8
+        imm8 = self.offset >> 2
+        assert imm8 < 256
+        h = (0x9 << 11) | (rt << 8) | imm8
         return u16(h)
 
+    def __repr__(self):
+        return 'LDR {}, [pc,#{}]'.format(self.rt, self.offset)
+
+@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
+
 @armtarget.instruction
 class mov_ins(ArmInstruction):
     """ mov Rd, imm8, move immediate value into register """
@@ -204,22 +301,19 @@
         self.imm = imm.imm
         self.r = rd.num
 
-    @classmethod
-    def FromIr(cls, ir_ins):
-        pass
-
     def encode(self):
         rd = self.r
         opcode = self.opcode
         imm8 = self.imm
         h = (opcode << 11) | (rd << 8) | imm8
         return u16(h)
+    def __repr__(self):
+        return 'MOV {0}, xx?'.format(self.r)
         
 @armtarget.instruction
 class movregreg_ins(ArmInstruction):
     """ mov Rd, Rm """
     mnemonic = 'mov'
-    opcode = 8 # 01000 Rd(3) imm8
     operands = (RegOp, RegOp)
     def __init__(self, rd, rm):
         self.rd = rd
@@ -232,9 +326,13 @@
         rm = self.rm.num
         assert rm < 16
         opcode = self.opcode
-        h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
+        h = (1 << 14) | (3 << 9) | (D << 7) | (rm << 3) | rd
         return u16(h)
 
+
+
+# Arithmatics:
+
 @armtarget.instruction
 class addregregimm3_ins(ArmInstruction):
     """ add Rd, Rn, imm3 """
@@ -254,6 +352,61 @@
         h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
         return u16(h)
 
+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
+    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
+
+class regreg_base(ArmInstruction):
+    """ ??? Rdn, Rm """
+    operands = (Reg8Op, Reg8Op)
+    def __init__(self, rdn, rm):
+        self.rdn = rdn
+        self.rm = rm
+    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 andregs_ins(regreg_base):
+    mnemonic = 'AND'
+    opcode = 0b0100000000
+
+@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 cmpregimm8_ins(ArmInstruction):
     """ cmp Rn, imm8 """
@@ -270,34 +423,37 @@
         h = (opcode << 11) | (rn << 8) | imm
         return u16(h)
 
-@armtarget.instruction
-class cmp_ins(ArmInstruction):
-    """ cmp Rn, Rm """
-    mnemonic = 'cmp'
-    operands = (RegOp, RegOp)
-    def __init__(self, rn, rm):
-        self.rn = rn
-        self.rm = rm
-    def encode(self):
-        rn = self.rn.num
-        rm = self.rm.num
-        assert rn < 8
-        assert rm < 8
-        opcode = 0x42
-        h = (opcode << 8) | (1 << 7) | (rm << 3) | (rn & 0x7)
-        return u16(h)
+# Jumping:
 
 @armtarget.instruction
 class jmp_ins(ArmInstruction):
-    operands = (Label,)
+    operands = (ALabel,)
     mnemonic = 'jmp'
     def __init__(self, target_label):
+        assert type(target_label) is ALabel
         self.target = target_label
     def fixUp(self):
         pass
     def encode(self):
-        h = 1337 # TODO
+        h = 0 # TODO
         return u16(h)
+    def __repr__(self):
+        return 'B {0}'.format(self.target.name)
+
+@armtarget.instruction
+class beq_ins(ArmInstruction):
+    operands = (ALabel,)
+    mnemonic = 'beq'
+    def __init__(self, target_label):
+        assert type(target_label) is ALabel
+        self.target = target_label
+    def fixUp(self):
+        pass
+    def encode(self):
+        h = 0 # TODO
+        return u16(h)
+    def __repr__(self):
+        return 'BEQ {0}'.format(self.target.name)
 
 @armtarget.instruction
 class push_ins(ArmInstruction):
@@ -341,7 +497,6 @@
                 raise NotImplementedError('not implemented for this register')
         h = (0x5E << 9) | (P << 8) | reg_list
         return u16(h)
-        return u16(0)
 
 @armtarget.instruction
 class yield_ins(ArmInstruction):
--- a/python/ir/basicblock.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/ir/basicblock.py	Sat Jul 06 12:38:09 2013 +0200
@@ -1,60 +1,61 @@
 
 class BasicBlock:
-   """ Uninterrupted sequence of instructions. """
-   def __init__(self, name):
+    """ Uninterrupted sequence of instructions. """
+    def __init__(self, name):
       self.name = name
       self.instructions = []
-   def __repr__(self):
+    def __repr__(self):
       return 'BasicBlock {0}'.format(self.name)
-   def addInstruction(self, i):
+    def addInstruction(self, i):
       i.parent = self
       self.instructions.append(i)
-   addIns = addInstruction
+    addIns = addInstruction
 
-   def replaceInstruction(self, i1, i2):
+    def replaceInstruction(self, i1, i2):
       idx = self.instructions.index(i1)
       i1.parent = None
       i1.delete()
       i2.parent = self
       self.instructions[idx] = i2
 
-   def removeInstruction(self, i):
+    def removeInstruction(self, i):
       i.parent = None
       self.instructions.remove(i)
 
-   def getInstructions(self):
+    def getInstructions(self):
         return self.instructions
 
-   def setInstructions(self, ins):
+    def setInstructions(self, ins):
       for i in self.instructions:
          i.parent = None
       self.instructions = ins
       for i in self.instructions:
          i.parent = self
-   Instructions = property(getInstructions, setInstructions)
+    Instructions = property(getInstructions, setInstructions)
 
-   def getLastIns(self):
+    def getLastIns(self):
       return self.instructions[-1]
-   LastInstruction = property(getLastIns)
-   @property
-   def Empty(self):
+    LastInstruction = property(getLastIns)
+    @property
+    def Empty(self):
       return len(self.instructions) == 0
-   @property
-   def FirstInstruction(self):
+    @property
+    def FirstInstruction(self):
       return self.instructions[0]
-   FirstIns = FirstInstruction
-   def getSuccessors(self):
+    FirstIns = FirstInstruction
+
+    def getSuccessors(self):
       if not self.Empty:
          i = self.LastInstruction
-         print(i)
          return i.Targets
       return []
-   Successors = property(getSuccessors)
-   def getPredecessors(self):
+    Successors = property(getSuccessors)
+
+    def getPredecessors(self):
       preds = []
       for bb in self.parent.BasicBlocks:
          if self in bb.Successors:
             preds.append(bb)
       return preds
-   Predecessors = property(getPredecessors)
+    Predecessors = property(getPredecessors)
 
--- a/python/ir/instruction.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/ir/instruction.py	Sat Jul 06 12:38:09 2013 +0200
@@ -156,17 +156,17 @@
 
 # Branching:
 class Branch(Terminator):
-   def __init__(self, target):
+    def __init__(self, target):
       super().__init__()
       assert type(target) is BasicBlock
       self.target = target
-   def __repr__(self):
-      return 'BRANCH {0}'.format(self.target)
-   def getTargets(self):
-      return [self.target]
-   def changeTarget(self, tfrom, tto):
-      if tfrom is self.target:
-         self.target = tto
+    def __repr__(self):
+        return 'BRANCH {0}'.format(self.target)
+    def getTargets(self):
+        return [self.target]
+    def changeTarget(self, tfrom, tto):
+        assert tfrom is self.target
+        self.target = tto
 
 class ConditionalBranch(Terminator):
    def __init__(self, a, cond, b, lab1, lab2):
@@ -187,9 +187,10 @@
    def getTargets(self):
       return [self.lab1, self.lab2]
    def changeTarget(self, tfrom, tto):
+      assert tfrom is self.lab1 or tfrom is self.lab2
       if tfrom is self.lab1:
          self.lab1 = tto
-      if tfrom is self.lab2:
+      elif tfrom is self.lab2:
          self.lab2 = tto
 
 class PhiNode(Instruction):
--- a/python/outstream.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/outstream.py	Sat Jul 06 12:38:09 2013 +0200
@@ -5,12 +5,20 @@
  to a file or binary or hexfile.
 """
 
+class Alignment:
+    def __init__(self, a):
+        self.align = a
+
 class OutputStream:
     def __init__(self):
         self.sections = {}
         self.currentSection = None
     def emit(self, item):
         self.sections[self.currentSection].append(item)
+
+    def align(self, alignment):
+        self.emit(Alignment(alignment))
+        
     def selectSection(self, s):
         self.currentSection = s
         if not s in self.sections:
@@ -30,6 +38,10 @@
                 i.address = address
                 if type(i) is ALabel:
                     continue
+                if type(i) is Alignment:
+                    while (address % i.align) != 0:
+                        address += 1
+                    continue
                 bts = i.encode()
                 address += len(bts)
 
@@ -43,6 +55,8 @@
         for i in self.sections[s]:
             if type(i) is ALabel:
                 print(i)
+            elif type(i) is Alignment:
+                pass
             else:
                 addr = i.address
                 insword = i.encode()
--- a/python/stm32f4/blink.c3	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/stm32f4/blink.c3	Sat Jul 06 12:38:09 2013 +0200
@@ -17,7 +17,7 @@
     if (true)
 	{
 		divider = divider + 1;
-		if (divider > 100000)
+		if (divider == 100000)
 		{
 			divider = 0;
 			//GPIOD->ODR ^= (1 << 13);
@@ -28,6 +28,9 @@
 function void main()
 {
     divider = 0;
+
+    var int* RCC_AHB1ENR;
+    RCC_AHB1ENR = 0x40003022;
     /*
 	RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
 	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
--- a/python/target.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/target.py	Sat Jul 06 12:38:09 2013 +0200
@@ -93,7 +93,7 @@
 
         # look for a suitable instruction
         for ic in self.instructions:
-            if ic.mnemonic == vi.mnemonic and len(ic.operands) == len(vi.operands):
+            if ic.mnemonic.upper() == vi.mnemonic.upper() and len(ic.operands) == len(vi.operands):
                 # Try to map operands to the correct operand types:
                 rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)]
 
--- a/python/testasm.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/testasm.py	Sat Jul 06 12:38:09 2013 +0200
@@ -186,6 +186,16 @@
         self.feed('ldr r4, [r0 + 0]')
         self.check('0468')
 
+    @unittest.skip
+    def testLdrSpRel(self):
+        self.feed('ldr r0, [sp + 4]')
+        self.check('0198')
+
+    @unittest.skip
+    def testStrSpRel(self):
+        self.feed('str r0, [sp + 4]')
+        self.check('0190')
+
     def testCmpRegReg(self):
         self.feed('cmp r0, r1')
         self.check('8842')
--- a/python/transform.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/transform.py	Sat Jul 06 12:38:09 2013 +0200
@@ -78,19 +78,28 @@
    return True
 
 class CleanPass(FunctionPass):
-   def onFunction(self, f):
+    def onFunction(self, f):
       bbs = list(f.BasicBlocks)
       for bb in bbs:
          # TODO: determine check for 'empty'
+
+         # If a block only contains a branch, it can be removed:
          if len(bb.Instructions) == 1:
             # This block is empty.
             # find predecessors of this block and replace this block reference with the jumped reference.
             ins = bb.LastInstruction
             if type(ins) is Branch:
-               print(ins, bb.Predecessors)
-               for pred in bb.Predecessors:
-                  pred.LastInstruction.changeTarget(bb, ins.target)
-            f.removeBasicBlock(bb)
+                print('Removing block {}'.format(bb))
+                #print(ins, bb.Predecessors)
+                preds = bb.Predecessors
+                if bb in preds:
+                    # Do not remove if preceeded by itself
+                    pass
+                else:
+                    for pred in bb.Predecessors:
+                          print('predecessor: {}'.format(pred))
+                          pred.LastInstruction.changeTarget(bb, ins.target)
+                    f.removeBasicBlock(bb)
 
 class Mem2RegPromotor(FunctionPass):
    def onFunction(self, f):
--- a/python/zcc.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/zcc.py	Sat Jul 06 12:38:09 2013 +0200
@@ -3,6 +3,7 @@
 import sys, argparse
 import c3, ppci, codegen
 import codegenarm
+from transform import CleanPass
 import outstream
 
 # Parse arguments:
@@ -24,9 +25,12 @@
         diag.printErrors(src)
         sys.exit(1)
 
+    # Optimization passes:
+    cp = CleanPass()
+    cp.run(ircode)
+
     if args.dumpir:
         ircode.dump()
-
     # Code generation:
 
     #cg = codegen.CodeGenerator(arm_cm3.armtarget)