changeset 218:494828a7adf1

added some sort of cache to assembler
author Windel Bouwman
date Fri, 05 Jul 2013 15:30:22 +0200
parents 8b2e5f3cd579
children 1fa3e0050b49
files python/arm_cm3.py python/asm.py python/codegenarm.py python/cortexm3.py python/pyyacc.py python/testasm.py python/testcg.py python/tests/code1.ks python/tests/main.c python/tests/main.s.bc python/tests/ppcitest.py python/tests/testcode.c python/tests/testproject/main.mod python/tests/testproject/test.lcp python/tests/testproject/test.mod python/zcc.py
diffstat 16 files changed, 414 insertions(+), 451 deletions(-) [+]
line wrap: on
line diff
--- a/python/arm_cm3.py	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-import struct, types
-from target import Register, Instruction, Target, Imm8, Label, Imm3
-from asmnodes import ASymbol, ANumber, AUnop, ABinop
-from ppci import CompilerError
-import ir
-
-def u16(h):
-    return struct.pack('<H', h)
-
-def u32(x):
-    return struct.pack('<I', x)
-
-armtarget = Target('arm')
-
-class ArmReg(Register):
-    def __init__(self, num, name):
-        super().__init__(name)
-        self.num = num
-    def __repr__(self):
-        return self.name
-
-class RegOp:
-    def __init__(self, num):
-        assert num < 16
-        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]
-                return cls(r.num)
-
-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
-
-class MemoryOp:
-    def __init__(self, basereg, offset):
-        assert type(basereg) is ArmReg
-        self.basereg = basereg
-        self.offset = 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
-                    basereg = RegOp.Create(vop.arg1)
-                    if not basereg:
-                        return
-                else:
-                    return
-            elif type(vop) is ASymbol:
-                offset = 0
-                basereg = RegOp.Create(vop)
-                if not basereg:
-                    return
-            else:
-                return
-            return cls(getRegNum(basereg.num), offset)
-        pass
-
-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 = RegOp.Create(arg)
-                if not reg:
-                    return
-                regs.add(reg)
-            elif type(arg) is ABinop and arg.op == '-':
-                reg1 = RegOp.Create(arg.arg1)
-                reg2 = RegOp.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]
-
-# 8 bit registers:
-r0 = ArmReg(0, 'r0')
-armtarget.registers.append(r0)
-r1 = ArmReg(1, 'r1')
-armtarget.registers.append(r1)
-r2 = ArmReg(2, 'r2')
-armtarget.registers.append(r2)
-r3 = ArmReg(3, 'r3')
-armtarget.registers.append(r3)
-r4 = ArmReg(4, 'r4')
-armtarget.registers.append(r4)
-r5 = ArmReg(5, 'r5')
-armtarget.registers.append(r5)
-r6 = ArmReg(6, 'r6')
-armtarget.registers.append(r6)
-r7 = ArmReg(7, 'r7')
-armtarget.registers.append(r7)
-# Other registers:
-# TODO
-sp = ArmReg(13, 'sp')
-armtarget.registers.append(sp)
-lr = ArmReg(14, 'lr')
-armtarget.registers.append(lr)
-pc = ArmReg(15, 'pc')
-armtarget.registers.append(pc)
-
-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 __init__(self, rt, memop):
-        assert memop.offset % 4 == 0
-        self.imm5 = memop.offset >> 2
-        self.rn = memop.basereg.num
-        self.rt = rt.num
-
-    def encode(self):
-        Rn = self.rn
-        Rt = self.rt
-        imm5 = self.imm5
-        h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt
-        return u16(h)
-
-@armtarget.instruction
-class loadimm5_ins(ArmInstruction):
-    """ str Rt, [Rn, imm5], 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 encode(self):
-        Rn = self.rn
-        Rt = self.rt
-        imm5 = self.imm5
-        h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt
-        return u16(h)
-
-@armtarget.instruction
-class mov_ins(ArmInstruction):
-    """ mov Rd, imm8, move immediate value into register """
-    mnemonic = 'mov'
-    opcode = 4 # 00100 Rd(3) imm8
-    operands = (RegOp, Imm8)
-    irpattern = ir.ImmLoad
-    def __init__(self, rd, imm):
-        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)
-        
-@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
-        self.rm = rm
-    def encode(self):
-        rd = self.rd.num
-        D = (rd & 0x8) >> 3
-        assert D < 2
-        rd = rd & 0x7
-        rm = self.rm.num
-        assert rm < 16
-        opcode = self.opcode
-        h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
-        return u16(h)
-
-@armtarget.instruction
-class addregregimm3_ins(ArmInstruction):
-    """ add Rd, Rn, imm3 """
-    mnemonic = 'add'
-    opcode = 3 # 00011
-    operands = (RegOp, RegOp, Imm3)
-    irpattern = 3
-    def __init__(self, rd, rn, imm3):
-        self.rd = rd
-        self.rn = rn
-        self.imm3 = imm3
-    def encode(self):
-        rd = self.rd.num
-        rn = self.rn.num
-        imm3 = self.imm3.imm
-        opcode = self.opcode
-        h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
-        return u16(h)
-
-@armtarget.instruction
-class cmpregimm8_ins(ArmInstruction):
-    """ cmp Rn, imm8 """
-    mnemonic = 'cmp'
-    opcode = 5 # 00101
-    operands = (RegOp, 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)
-
-@armtarget.instruction
-class jmp_ins(ArmInstruction):
-    operands = (Label,)
-    mnemonic = 'jmp'
-    def __init__(self, target_label):
-        self.target = target_label
-    def fixUp(self):
-        pass
-    def encode(self):
-        h = 1337 # TODO
-        return u16(h)
-
-@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)
-        return u16(0)
-
-@armtarget.instruction
-class yield_ins(ArmInstruction):
-    operands = ()
-    mnemonic = 'yield'
-    def encode(self):
-        return u16(0xbf10)
-
-armtarget.check()
-
--- a/python/asm.py	Fri Jul 05 14:13:59 2013 +0200
+++ b/python/asm.py	Fri Jul 05 15:30:22 2013 +0200
@@ -66,11 +66,8 @@
    def Peak(self):
       return self.curTok
 
-
-class Assembler:
-    def __init__(self, target=None):
-        self.target = target
-        self.restart()
+class Parser:
+    def __init__(self):
         # Construct a parser given a grammar:
         ident = lambda x: x   # Identity helper function
         g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS, 'COMMENT', '{', '}'])
@@ -136,6 +133,17 @@
     def p_binop(self, exp1, op, exp2):
         return ABinop(op, exp1, exp2)
 
+    def parse(self, tokens, emitter):
+        self.emit = emitter
+        self.p.parse(tokens)
+
+asmParser = Parser()
+class Assembler:
+    def __init__(self, target=None):
+        self.target = target
+        self.restart()
+        self.p = asmParser
+
     # Top level interface:
     def restart(self):
         self.output = []
@@ -151,7 +159,7 @@
     def parse_line(self, line):
         """ Parse line into asm AST """
         tokens = tokenize(line)
-        self.p.parse(tokens)
+        self.p.parse(tokens, self.emit)
 
     def assemble(self, asmsrc):
         """ Assemble this source snippet """
--- a/python/codegenarm.py	Fri Jul 05 14:13:59 2013 +0200
+++ b/python/codegenarm.py	Fri Jul 05 15:30:22 2013 +0200
@@ -1,6 +1,6 @@
 import ir
 from asmnodes import ALabel
-import arm_cm3 as arm
+import cortexm3 as arm
 from ppci import CompilerError
 
 class ArmCodeGenerator:
@@ -24,7 +24,8 @@
         self.outs.selectSection('code')
         for f in ircode.Functions:
             self.emit(ALabel(f.name))
-            self.emit(arm.push_ins(arm.RegisterSet({arm.r2, arm.r3,arm.lr})))
+            # Save some registers:
+            self.emit(arm.push_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6,arm.r7,arm.lr})))
             for bb in f.BasicBlocks:
                 self.emit(ALabel(bb.name))
                 for ins in bb.Instructions:
@@ -43,15 +44,15 @@
         elif type(ins) is ir.Store:
             print(ins)
         elif type(ins) is ir.Return:
-            self.emit(arm.pop_ins(arm.RegisterSet({arm.r2, arm.r3, arm.pc})))
+            self.emit(arm.pop_ins(arm.RegisterSet({arm.r5, arm.r6, arm.pc})))
         elif type(ins) is ir.Load:
             print(ins)
         elif type(ins) is ir.BinaryOperator:
             print(ins)
         elif type(ins) is ir.ConditionalBranch:
             print(ins)
+            self.emit(arm.cmp_ins(arm.r1, arm.r0))
         else:
-            print(ins)
             raise CompilerError('IR "{}" not covered'.format(ins))
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/cortexm3.py	Fri Jul 05 15:30:22 2013 +0200
@@ -0,0 +1,354 @@
+import struct, types
+from target import Register, Instruction, Target, Imm8, Label, Imm3
+from asmnodes import ASymbol, ANumber, AUnop, ABinop
+from ppci import CompilerError
+import ir
+
+# TODO: encode this in DSL (domain specific language)
+
+def u16(h):
+    return struct.pack('<H', h)
+
+def u32(x):
+    return struct.pack('<I', x)
+
+armtarget = Target('arm')
+
+class ArmReg(Register):
+    def __init__(self, num, name):
+        super().__init__(name)
+        self.num = num
+    def __repr__(self):
+        return self.name
+
+class RegOp:
+    def __init__(self, num):
+        assert num < 16
+        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]
+                return cls(r.num)
+
+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
+
+class MemoryOp:
+    def __init__(self, basereg, offset):
+        assert type(basereg) is ArmReg
+        self.basereg = basereg
+        self.offset = 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
+                    basereg = RegOp.Create(vop.arg1)
+                    if not basereg:
+                        return
+                else:
+                    return
+            elif type(vop) is ASymbol:
+                offset = 0
+                basereg = RegOp.Create(vop)
+                if not basereg:
+                    return
+            else:
+                return
+            return cls(getRegNum(basereg.num), offset)
+        pass
+
+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 = RegOp.Create(arg)
+                if not reg:
+                    return
+                regs.add(reg)
+            elif type(arg) is ABinop and arg.op == '-':
+                reg1 = RegOp.Create(arg.arg1)
+                reg2 = RegOp.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]
+
+# 8 bit registers:
+r0 = ArmReg(0, 'r0')
+armtarget.registers.append(r0)
+r1 = ArmReg(1, 'r1')
+armtarget.registers.append(r1)
+r2 = ArmReg(2, 'r2')
+armtarget.registers.append(r2)
+r3 = ArmReg(3, 'r3')
+armtarget.registers.append(r3)
+r4 = ArmReg(4, 'r4')
+armtarget.registers.append(r4)
+r5 = ArmReg(5, 'r5')
+armtarget.registers.append(r5)
+r6 = ArmReg(6, 'r6')
+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')
+armtarget.registers.append(sp)
+lr = ArmReg(14, 'lr')
+armtarget.registers.append(lr)
+pc = ArmReg(15, 'pc')
+armtarget.registers.append(pc)
+
+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 __init__(self, rt, memop):
+        assert memop.offset % 4 == 0
+        self.imm5 = memop.offset >> 2
+        self.rn = memop.basereg.num
+        self.rt = rt.num
+
+    def encode(self):
+        Rn = self.rn
+        Rt = self.rt
+        imm5 = self.imm5
+        h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        return u16(h)
+
+@armtarget.instruction
+class loadimm5_ins(ArmInstruction):
+    """ str Rt, [Rn, imm5], 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 encode(self):
+        Rn = self.rn
+        Rt = self.rt
+        imm5 = self.imm5
+        h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        return u16(h)
+
+@armtarget.instruction
+class mov_ins(ArmInstruction):
+    """ mov Rd, imm8, move immediate value into register """
+    mnemonic = 'mov'
+    opcode = 4 # 00100 Rd(3) imm8
+    operands = (RegOp, Imm8)
+    irpattern = ir.ImmLoad
+    def __init__(self, rd, imm):
+        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)
+        
+@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
+        self.rm = rm
+    def encode(self):
+        rd = self.rd.num
+        D = (rd & 0x8) >> 3
+        assert D < 2
+        rd = rd & 0x7
+        rm = self.rm.num
+        assert rm < 16
+        opcode = self.opcode
+        h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
+        return u16(h)
+
+@armtarget.instruction
+class addregregimm3_ins(ArmInstruction):
+    """ add Rd, Rn, imm3 """
+    mnemonic = 'add'
+    opcode = 3 # 00011
+    operands = (RegOp, RegOp, Imm3)
+    irpattern = 3
+    def __init__(self, rd, rn, imm3):
+        self.rd = rd
+        self.rn = rn
+        self.imm3 = imm3
+    def encode(self):
+        rd = self.rd.num
+        rn = self.rn.num
+        imm3 = self.imm3.imm
+        opcode = self.opcode
+        h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
+        return u16(h)
+
+@armtarget.instruction
+class cmpregimm8_ins(ArmInstruction):
+    """ cmp Rn, imm8 """
+    mnemonic = 'cmp'
+    opcode = 5 # 00101
+    operands = (RegOp, 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)
+
+@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)
+
+@armtarget.instruction
+class jmp_ins(ArmInstruction):
+    operands = (Label,)
+    mnemonic = 'jmp'
+    def __init__(self, target_label):
+        self.target = target_label
+    def fixUp(self):
+        pass
+    def encode(self):
+        h = 1337 # TODO
+        return u16(h)
+
+@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)
+        return u16(0)
+
+@armtarget.instruction
+class yield_ins(ArmInstruction):
+    operands = ()
+    mnemonic = 'yield'
+    def encode(self):
+        return u16(0xbf10)
+
+armtarget.check()
+
--- a/python/pyyacc.py	Fri Jul 05 14:13:59 2013 +0200
+++ b/python/pyyacc.py	Fri Jul 05 15:30:22 2013 +0200
@@ -2,6 +2,8 @@
   Parser generator script
 """
 
+import shelve
+import hashlib
 from ppci import Token
 
 EPS = 'EPS'
@@ -160,9 +162,30 @@
                 if symbol not in self.Symbols + [EPS]:
                     raise ParserGenerationException('Symbol {0} undefined'.format(symbol))
 
-
+    def getSignature(self):
+        m = hashlib.md5()
+        m.update((str(self.productions) + str(self.start_symbol)).encode('ascii'))
+        signature = m.hexdigest()
+        
     def genParser(self):
-        """ Generates a parser from the grammar """
+        """ Generates a parser from the grammar (using a caching algorithm) """
+        signature = self.getSignature() 
+        cache = shelve.open('__grammar_cache__.shelve')
+        # TODO: fix caching.
+        if ('signature1' in cache) and cache['signature'] == signature:
+            goto_table = cache['goto_table']
+            action_table = cache['action_table']
+        else:
+            action_table, goto_table = self.doGenerate()
+            cache['goto_table'] = goto_table
+            cache['action_table'] = action_table
+            cache['signature'] = signature
+        cache.close()
+        p = LRParser(action_table, goto_table, self.start_symbol)
+        p.grammar = self
+        return p
+
+    def doGenerate(self):
         self.checkSymbols()
         action_table = {}
         goto_table = {}
@@ -181,6 +204,8 @@
         
         def setAction(state, t, action):
             key = (state, t)
+            assert type(state) is int
+            assert type(t) is str
             if key in action_table:
                 action2 = action_table[key]
                 if action != action2:
@@ -209,16 +234,15 @@
                 if item.IsReduce:
                     if item.production.name == self.start_symbol and item.look_ahead == EOF:
                         # Rule 3: accept:
-                        setAction(states.index(state), item.look_ahead, (ACCEPT, item.production))
+                        setAction(states.index(state), item.look_ahead, (ACCEPT, self.productions.index(item.production)))
                     else:
                         # Rule 2, reduce item:
-                        setAction(states.index(state), item.look_ahead, (REDUCE, item.production))
+                        setAction(states.index(state), item.look_ahead, (REDUCE, self.productions.index(item.production)))
             for nt in self.nonterminals:
                 key = (states.index(state), nt)
                 if key in transitions:
                     goto_table[key] = transitions[key]
-
-        return LRParser(action_table, goto_table, self.start_symbol)
+        return action_table, goto_table
 
 
 class Production:
@@ -324,6 +348,7 @@
             action, param = self.action_table[key]
             if action == REDUCE:
                 f_args = []
+                param = self.grammar.productions[param]
                 for s in param.symbols:
                     stack.pop()
                     stack.pop()
@@ -348,6 +373,7 @@
             elif action == ACCEPT:
                 # Pop last rule data off the stack:
                 f_args = []
+                param = self.grammar.productions[param]
                 for s in param.symbols:
                     stack.pop()
                     stack.pop()
--- a/python/testasm.py	Fri Jul 05 14:13:59 2013 +0200
+++ b/python/testasm.py	Fri Jul 05 15:30:22 2013 +0200
@@ -5,7 +5,7 @@
 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber
 from asm import tokenize, Assembler
 import msp430
-import arm_cm3
+import cortexm3 as arm
 
 class AssemblerLexingCase(unittest.TestCase):
     """ Tests the assemblers lexer """
@@ -150,14 +150,14 @@
 
 class AssemblerARMTestCase(unittest.TestCase):
     def setUp(self):
-        self.t = arm_cm3.armtarget
+        self.t = arm.armtarget
         self.a = Assembler(target=self.t)
 
     def feed(self, line):
         self.a.assemble(line)
 
     def check(self, hexstr):
-        self.assertEqual(bytes.fromhex(hexstr), self.a.binout)
+        self.assertSequenceEqual(bytes.fromhex(hexstr), self.a.binout)
         
     def testMapOperand(self):
         pass
@@ -186,6 +186,10 @@
         self.feed('ldr r4, [r0 + 0]')
         self.check('0468')
 
+    def testCmpRegReg(self):
+        self.feed('cmp r0, r1')
+        self.check('8842')
+
     def testSequence1(self):
         self.feed('mov r5, 3')
         self.feed('add r4, r5, 0')
--- a/python/testcg.py	Fri Jul 05 14:13:59 2013 +0200
+++ b/python/testcg.py	Fri Jul 05 15:30:22 2013 +0200
@@ -1,10 +1,10 @@
 import unittest
 import ppci, codegen, ir
-import arm_cm3
+import cortexm3 as arm
 
 class testCodeGeneration(unittest.TestCase):
     def setUp(self):
-        self.cg = codegen.CodeGenerator(arm_cm3.armtarget)
+        self.cg = codegen.CodeGenerator(arm.armtarget)
 
     def testFunction(self):
         m = ir.Module('tst')
--- a/python/tests/code1.ks	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-module s;
-var a, b, c:integer;
-
-procedure test(x:integer);
-begin
-   a := x * x + 1337;
-   b := a * x
-end test;
-
-begin
-  a := 4 + 6;
-  b := a + 2*a - 3;
-  c := a + b
-end s.
-
--- a/python/tests/main.c	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-
-#include <stdio.h>
-
-int main()
-{
-   printf("Hello world\n");
-   return 0;
-}
-
Binary file python/tests/main.s.bc has changed
--- a/python/tests/ppcitest.py	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-
-from core import BitReader
-
-with open('main.s.bc', 'rb') as f:
-   br = BitReader(f)
-   br.parseModule()
-   print(br)
-
--- a/python/tests/testcode.c	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-
-int Calculate(int a, int b, int c)
-{
-   int d, e;
-   d = a + b;
-   e = d * c - a;
-   return a + b + c + d + e;
-}
-
--- a/python/tests/testproject/main.mod	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-module main;
-var 
- a,b,c : integer;
-
-procedure test(x:integer);
- var y,z:integer;
-begin
-  y := x * 3 + 2;
-  z := x + y + a;
-end test;
-
-procedure add(a:integer; b:integer):integer;
- var 
-  tmp : integer;
- begin
-  tmp := a + b;
-  return tmp
- end add;
-
-begin
-  a := 12;
-  b := a * 12 + 33;
-  c := a div b + a * b * 99;
-end main.
-
--- a/python/tests/testproject/test.lcp	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<?xml version="1.0" ?>
-<Project name="Test project">
-	<Files>
-		<File Filename="main.mod"/>
-		<File Filename="test.mod"/>
-	</Files>
-</Project>
--- a/python/tests/testproject/test.mod	Fri Jul 05 14:13:59 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-module test;
-var 
- a,b,c : integer;
-
-procedure test(x:integer);
- var y,z:integer;
-begin
-  y := x * 3 + 2;
-  z := x + y + a;
-end test;
-
-procedure add(a:integer; b:integer):integer;
- var 
-  tmp : integer;
- begin
-  tmp := a + b;
-  return tmp
- end add;
-
-begin
-  a := 12;
-  b := a * 12 + 33;
-  c := a div b + a * b * 99;
-end test.
-
--- a/python/zcc.py	Fri Jul 05 14:13:59 2013 +0200
+++ b/python/zcc.py	Fri Jul 05 15:30:22 2013 +0200
@@ -2,7 +2,6 @@
 
 import sys, argparse
 import c3, ppci, codegen
-import arm_cm3
 import codegenarm
 import outstream