changeset 191:6b2bec5653f1

Added assembler testset
author Windel Bouwman
date Sun, 26 May 2013 15:28:07 +0200
parents 65dda7e7e8bd
children 6cd6260789a1
files python/c3/lexer.py python/dag.py python/libasm.py python/ppci/__init__.py python/ppci/common.py python/ppci/errors.py python/pyyacc.py python/runtests.py python/testasm.py python/testc3.py python/testpyy.py python/testx86asm.py python/x86.py
diffstat 13 files changed, 301 insertions(+), 174 deletions(-) [+]
line wrap: on
line diff
--- a/python/c3/lexer.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/c3/lexer.py	Sun May 26 15:28:07 2013 +0200
@@ -1,14 +1,11 @@
 import collections, re
 
-from ppci import CompilerError, SourceLocation
+from ppci import CompilerError, SourceLocation, Token
 
 """
  Lexical analyzer part. Splits the input character stream into tokens.
 """
 
-# Token is used in the lexical analyzer:
-Token = collections.namedtuple('Token', 'typ val loc')
-
 keywords = ['and', 'or', 'not','true', 'false', \
    'else', 'if', 'while', 'return', \
    'function', 'var', 'type', 'const', \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/dag.py	Sun May 26 15:28:07 2013 +0200
@@ -0,0 +1,57 @@
+
+# Instruction selection with DAG (Directed Acyclic Graph)
+class DagLeaf:
+   def __init__(self, v):
+      self.v = v
+
+class DagNode:
+   def __init__(self, name):
+      self.name = name
+      self.children = []
+   def __repr__(self):
+      return str(self.name)
+
+class Dag:
+   def __init__(self, bb):
+      self.mapping = {}
+      self.buildFromBB(bb)
+   def buildFromBB(self, bb):
+      for ins in bb.Instructions:
+         if type(ins) is ir.BinaryOperator:
+            if not ins.value1 in self.mapping:
+               self.mapping[ins.value1] = DagNode(ins.value1)
+            if not ins.value2 in self.mapping:
+               self.mapping[ins.value2] = DagNode(ins.value2)
+            # look for op with left and right operand the same:
+            N = None
+            lnode = self.mapping[ins.value1]
+            rnode = self.mapping[ins.value2]
+            for node in self.mapping.values():
+               if node.name == ins.operation:
+                  if node.children[0] == lnode and node.children[1] == rnode:
+                     N = node
+                     break
+            if not N:
+               # Create a node.
+               N = DagNode(ins.operation)
+               N.children.append(lnode)
+               N.children.append(rnode)
+            self.mapping[ins.result] = N
+         else:
+            pass
+   def dumpgv(self, outf):
+      outf.write('subgraph {0} {{\n'.format(id(self)))
+      for node in self.mapping.values():
+         outf.write('{0} [label="{1}"];\n'.format(id(node), node.name))
+         for c in node.children:
+            outf.write('{0} -> {1};\n'.format(id(node), id(c)))
+      outf.write('label="dag"}\n')
+
+def insSelect(mod):
+   """ Create DAG from ir-code """
+   for bb in mod.BasicBlocks:
+      print(bb)
+      dag = Dag(bb)
+      print(dag.mapping)
+      bb.dag = dag
+
--- a/python/libasm.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/libasm.py	Sun May 26 15:28:07 2013 +0200
@@ -1,4 +1,6 @@
-import collections, re
+import re
+import pyyacc
+from ppci import Token, CompilerError, SourceLocation
 
 # Different instruction sets:
 class InstructionSet:
@@ -8,19 +10,6 @@
    pass
 
 # Generic assembler:
-
-class SourceLocation:
-   def __init__(self, x):
-      self.pos = x
-
-class SourceRange:
-   def __init__(self, p1, p2):
-      self.p1 = p1
-      self.p2 = p2
-
-# Token is used in the lexical analyzer:
-Token = collections.namedtuple('Token', 'typ val row col')
-
 keywords = ['global', 'db']
 
 def tokenize(s):
@@ -35,13 +24,11 @@
        ('HEXNUMBER', r'0x[\da-fA-F]+'),
        ('NUMBER', r'\d+'),
        ('ID', r'[A-Za-z][A-Za-z\d_]*'),
-       ('NEWLINE', r'\n'),
        ('SKIP', r'[ \t]'),
-       ('LEESTEKEN', r':=|[\.,=:;\-+*\[\]/\(\)]|>=|<=|<>|>|<'),
+       ('LEESTEKEN', r':=|[\.,=:\-+*\[\]/\(\)]|>=|<=|<>|>|<'),
        ('STRING', r"'.*?'")
      ]
      tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tok_spec)
-     print(tok_re)
      gettok = re.compile(tok_re).match
      line = 1
      pos = line_start = 0
@@ -69,13 +56,15 @@
            val = float(val)
          elif typ == 'STRING':
            val = val[1:-1]
-         yield Token(typ, val, line, mo.start()-line_start)
+         col = mo.start() - line_start
+         loc = SourceLocation(line, col, 0)   # TODO retrieve length?
+         yield Token(typ, val, loc)
        pos = mo.end()
        mo = gettok(s, pos)
      if pos != len(s):
        col = pos - line_start
-       raise CompilerException('Unexpected character {0}'.format(s[pos]), line, col)
-     yield Token('END', '', line, 0)
+       loc = SourceLocation(line, col, 0)
+       raise CompilerError('Unexpected character {0}'.format(s[pos]), loc)
 
 class Lexer:
    def __init__(self, src):
@@ -89,28 +78,40 @@
    def Peak(self):
       return self.curTok
 
-class Parser:
-   def __init__(self, lxr):
-      self.lxr = lxr
-   def parse(self):
-      t = self.lxr.eat()
+class Assembler:
+    def __init__(self):
+        # Construct a parser given a grammar:
+        g = pyyacc.Grammar(['ID', ',', '[', ']', ':'])
 
-      while True:
-         ins = self.parseLine()
-         print(ins)
-         t = self.lxr.eat()
-   def parseLine(self):
-      self.parseLabel()
-      if self.lxr.Peak == ';':
-         self.eatComments()
-   def parseLabel(self):
-      i = self.lxr.eat()
+        g.add_production('asmline', ['label', 'instruction', 'operands'])
+        g.add_production('label', ['ID', ':'])
+        g.add_production('label', ['EPS'])
+        g.add_production('instruction', ['ID'])
+        g.add_production('operands', ['operand'])
+        g.add_production('operands', ['operands', ',', 'operand'])
+        g.add_production('operand', ['expression'])
+        g.add_production('expression', ['ID'])
+        # TODO: expand grammar
+        g.start_symbol = 'asmline'
 
-class Assembler:
-   def assemble(self, asmsrc):
-      print('assembling', asmsrc)
+        self.p = g.genParser()
+
+    def assemble(self, asmsrc):
       lxr = Lexer(asmsrc)
       prsr = Parser(lxr)
       instructions = prsr.parse()
       return instructions
 
+    def assembleLine(self, line):
+        """ 
+            Assemble a single source line. 
+            Do not take newlines into account 
+        """
+        tokens = tokenize(line)
+        self.p.parse(tokens)
+
+    def assembleAst(self, at):
+        """ Assemble a parsed asm line """
+        pass
+
+
--- a/python/ppci/__init__.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/ppci/__init__.py	Sun May 26 15:28:07 2013 +0200
@@ -9,7 +9,7 @@
    print("Needs to be run in python version 3.x")
    sys.exit(1)
 
-from .common import SourceLocation, SourceRange
+from .common import SourceLocation, SourceRange, Token
 from .errors import CompilerError, DiagnosticsManager
 from .errors import printError
 
--- a/python/ppci/common.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/ppci/common.py	Sun May 26 15:28:07 2013 +0200
@@ -1,7 +1,8 @@
-
 from collections import namedtuple
 
-#SourceLocation = namedtuple('SourceLocation', ['row', 'col'])
+# Token is used in the lexical analyzer:
+Token = namedtuple('Token', 'typ val loc')
+
 class SourceLocation:
    def __init__(self, row, col, ln):
       self.row = row
--- a/python/ppci/errors.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/ppci/errors.py	Sun May 26 15:28:07 2013 +0200
@@ -4,11 +4,11 @@
 """
 
 class CompilerError(Exception):
-  def __init__(self, msg, loc):
-    self.msg = msg
-    self.loc = loc
-  def __repr__(self):
-     return 'Compilererror {0} at row {1}'.format(self.msg, self.loc.row)
+    def __init__(self, msg, loc):
+        self.msg = msg
+        self.loc = loc
+    def __repr__(self):
+        return 'Compilererror {0} at row {1}'.format(self.msg, self.loc.row)
 
 def printError(source, e):
      def printLine(row, txt):
--- a/python/pyyacc.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/pyyacc.py	Sun May 26 15:28:07 2013 +0200
@@ -2,6 +2,8 @@
   Parser generator script
 """
 
+from ppci import Token
+
 EPS = 'EPS'
 EOF = 'EOF'
 SHIFT = 1
@@ -272,15 +274,17 @@
         self.goto_table = goto_table
 
     def parse(self, toks):
+        """ Parse an iterable with tokens """
+        assert hasattr(toks, '__iter__'), '{0} not iter type'.format(type(toks))
         stack = [0]
-        look_ahead = toks.pop(0)
+        look_ahead = toks.__next__()
+        assert type(look_ahead) is Token
         while True:
             state = stack[-1]   # top of stack
-            key = (state, look_ahead)
+            key = (state, look_ahead.typ)
             if not key in self.action_table:
-                print(key)
-                raise Exception('Error parsing')
-            action, param = self.action_table[(state, look_ahead)]
+                raise Exception('Error parsing at character {0}'.format(look_ahead))
+            action, param = self.action_table[key]
             if action == REDUCE:
                 for s in param.symbols:
                     stack.pop()
@@ -289,9 +293,13 @@
                 stack.append(param.name)
                 stack.append(self.goto_table[(state, param.name)])
             elif action == SHIFT:
-                stack.append(look_ahead)
+                stack.append(look_ahead.typ)
                 stack.append(param)
-                look_ahead = toks.pop(0)
+                try:
+                    look_ahead = toks.__next__()
+                except StopIteration:
+                    look_ahead = Token(EOF, EOF, 0)
+                assert type(look_ahead) is Token
             elif action == ACCEPT:
                 break
 
--- a/python/runtests.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/runtests.py	Sun May 26 15:28:07 2013 +0200
@@ -144,117 +144,6 @@
       ast = Parser(tokens).parseExpression()
       code = CodeGenerator().genexprcode(ast)
 
-   def testAssembler(self):
-      """ Check all kind of assembler cases """
-      assert(assembler.shortjump(5) == [0xeb, 0x5])
-      assert(assembler.shortjump(-2) == [0xeb, 0xfc])
-      assert(assembler.shortjump(10,'GE') == [0x7d, 0xa])
-      assert(assembler.nearjump(5) == [0xe9, 0x5,0x0,0x0,0x0])
-      assert(assembler.nearjump(-2) == [0xe9, 0xf9, 0xff,0xff,0xff])
-      assert(assembler.nearjump(10,'LE') == [0x0f, 0x8e, 0xa,0x0,0x0,0x0])
-
-   def testCall(self):
-      assert(assembler.call('r10') == [0x41, 0xff, 0xd2])
-      assert(assembler.call('rcx') == [0xff, 0xd1])
-   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):
-      assert(assembler.increg64('r11') == [0x49, 0xff, 0xc3])
-      assert(assembler.increg64('rcx') == [0x48, 0xff, 0xc1])
-
-   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):
-      # 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):
-      assert(assembler.mov('rax', ['r8','r15',0x11]) == [0x4b,0x8b,0x44,0x38,0x11])
-      assert(assembler.mov('r13', ['rbp','rcx',0x23]) == [0x4c,0x8b,0x6c,0xd,0x23])
-
-      assert(assembler.mov('r9', ['rbp',-0x33]) == [0x4c,0x8b,0x4d,0xcd])
-      #assert(assembler.movreg64('rbx', ['rax']) == [0x48, 0x8b,0x18])
-
-      assert(assembler.mov('rax', [0xb000]) == [0x48,0x8b,0x4,0x25,0x0,0xb0,0x0,0x0])
-      assert(assembler.mov('r11', [0xa0]) == [0x4c,0x8b,0x1c,0x25,0xa0,0x0,0x0,0x0])
-
-      assert(assembler.mov('r11', ['RIP', 0xf]) == [0x4c,0x8b,0x1d,0x0f,0x0,0x0,0x0])
-
-   def testAsmMemStores(self):
-      assert(assembler.mov(['rbp', 0x13],'rbx') == [0x48,0x89,0x5d,0x13])
-      assert(assembler.mov(['r12', 0x12],'r9') == [0x4d,0x89,0x4c,0x24,0x12])
-      assert(assembler.mov(['rcx', 0x11],'r14') == [0x4c,0x89,0x71,0x11])
-
-
-      assert(assembler.mov([0xab], 'rbx') == [0x48,0x89,0x1c,0x25,0xab,0x0,0x0,0x0])
-      assert(assembler.mov([0xcd], 'r13') == [0x4c,0x89,0x2c,0x25,0xcd,0x0,0x0,0x0])
-
-      assert(assembler.mov(['RIP', 0xf], 'r9') == [0x4c,0x89,0x0d,0x0f,0x0,0x0,0x0])
-
-   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):
-      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):
-      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):
-      assert(assembler.addreg64('rbx', 'r13') == [0x4c, 0x01, 0xeb])
-      assert(assembler.addreg64('rax', 'rbx') == [0x48, 0x01, 0xd8])
-      assert(assembler.addreg64('r12', 'r13') == [0x4d, 0x01, 0xec])
-
-      assert(assembler.addreg64('rbx', 0x13) == [0x48, 0x83, 0xc3, 0x13])
-      assert(assembler.addreg64('r11', 0x1234567) == [0x49, 0x81, 0xc3, 0x67, 0x45,0x23,0x1])
-      assert(assembler.addreg64('rsp', 0x33) == [0x48, 0x83, 0xc4, 0x33])
-
-   def testAssemblerSUB(self):
-      assert(assembler.subreg64('rdx', 'r14') == [0x4c, 0x29, 0xf2])
-      assert(assembler.subreg64('r15', 'rbx') == [0x49, 0x29, 0xdf])
-      assert(assembler.subreg64('r8', 'r9') == [0x4d, 0x29, 0xc8])
-
-      assert(assembler.subreg64('rsp', 0x123456) == [0x48, 0x81, 0xec, 0x56,0x34,0x12,0x0])
-      assert(assembler.subreg64('rsp', 0x12) == [0x48, 0x83, 0xec, 0x12])
-
-   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):
-      assert(assembler.imulreg64_rax('rdi') == [0x48, 0xf7, 0xef])
-      assert(assembler.imulreg64_rax('r10') == [0x49, 0xf7, 0xea])
-      assert(assembler.imulreg64_rax('rdx') == [0x48, 0xf7, 0xea])
-
-      assert(assembler.imulreg64('r11', 'rdi') == [0x4c, 0xf, 0xaf, 0xdf])
-      assert(assembler.imulreg64('r12', 'rbx') == [0x4c, 0xf, 0xaf, 0xe3])
-      # nasm generates this machine code: 0x4d, 0x6b, 0xff, 0xee
-      # This also works: 4D0FAFFE (another variant?? )
-      assert(assembler.imulreg64('r15', 'r14') == [0x4d, 0x0f, 0xaf, 0xfe])
    def testProject(self):
       p = Project('test.xml', isnew=True)
       p.name = "Test project"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/testasm.py	Sun May 26 15:28:07 2013 +0200
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+import unittest
+import libasm
+import ppci
+
+class AssemblerTestCase(unittest.TestCase):
+    """ 
+        Tests the assembler parts
+    """
+    def setUp(self):
+        pass
+
+    def testLex0(self):
+        """ Check if the lexer is OK """
+        asmline, toks = 'mov rax, rbx ', ['ID', 'ID', ',', 'ID']
+        self.assertSequenceEqual([tok.typ for tok in libasm.tokenize(asmline)], toks)
+
+    def testLex1(self):
+        asmline, toks = 'lab1: mov rax, rbx ', ['ID', ':', 'ID', 'ID', ',', 'ID']
+        self.assertSequenceEqual([tok.typ for tok in libasm.tokenize(asmline)], toks)
+
+    def testLex2(self):
+        asmline = '0z4: mov rax, rbx $ '
+        with self.assertRaises(ppci.CompilerError):
+            list(libasm.tokenize(asmline))
+
+    def testParse(self):
+        asmline = 'lab1: mov rax, rbx'
+        a = libasm.Assembler()
+        a.assembleLine(asmline)
+
+if __name__ == '__main__':
+    unittest.main()
+
--- a/python/testc3.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/testc3.py	Sun May 26 15:28:07 2013 +0200
@@ -201,8 +201,10 @@
          return b;
       }
       """
-      ir = self.builder.build(snippet)
-      self.assertTrue(ir)
+      ircode = self.builder.build(snippet)
+      if not ircode:
+        self.diag.printErrors(snippet)
+      self.assertTrue(ircode)
    def test2(self):
       # testsrc2 is valid code:
       self.diag.clear()
--- a/python/testpyy.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/testpyy.py	Sun May 26 15:28:07 2013 +0200
@@ -1,6 +1,10 @@
 import unittest, pprint
 from pyyacc import Grammar, Item, EOF 
+from ppci import Token
 
+def genTokens(lst):
+    for t in lst:
+        yield Token(t, t, 0)
 
 class testLR(unittest.TestCase):
     def setUp(self):
@@ -18,7 +22,7 @@
         g.add_production('factor', ['identifier'])
         g.start_symbol = 'input'
         # 2. define input:
-        tokens = ['identifier', '+', 'identifier', '+', 'identifier', 'EOF']
+        tokens = genTokens(['identifier', '+', 'identifier', '+', 'identifier'])
         # 3. build parser:
         p = g.genParser()
         # 4. feed input:
@@ -108,14 +112,14 @@
         self.assertIn(Item(p4, 0, '('), s0)
 
     def testParser(self):
-        tokens = ['(', '(', ')', ')', '(', ')', EOF]
+        tokens = ['(', '(', ')', ')', '(', ')']
         # 3. build parser:
         p = self.g.genParser()
         self.assertEqual(len(p.goto_table), 5)
         self.assertEqual(len(p.action_table), 19)
 
         # 4. feed input:
-        p.parse(tokens)
+        p.parse(genTokens(tokens))
 
 if __name__ == '__main__':
     unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/testx86asm.py	Sun May 26 15:28:07 2013 +0200
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+
+import unittest
+
+
+class AssemblerTestCase(unittest.TestCase):
+   """ 
+    test methods start with 'test*' 
+     Checks several assembly constructs agains their bytecodes
+   """
+   def setUp(self):
+        self.skipTest('not implemented yet')
+        self.assembler = Assembler('x86-64')
+
+   def tstAssembler(self):
+      """ Check all kind of assembler cases """
+      assert(assembler.shortjump(5) == [0xeb, 0x5])
+      assert(assembler.shortjump(-2) == [0xeb, 0xfc])
+      assert(assembler.shortjump(10,'GE') == [0x7d, 0xa])
+      assert(assembler.nearjump(5) == [0xe9, 0x5,0x0,0x0,0x0])
+      assert(assembler.nearjump(-2) == [0xe9, 0xf9, 0xff,0xff,0xff])
+      assert(assembler.nearjump(10,'LE') == [0x0f, 0x8e, 0xa,0x0,0x0,0x0])
+
+   def testCall(self):
+      assert(assembler.call('r10') == [0x41, 0xff, 0xd2])
+      assert(assembler.call('rcx') == [0xff, 0xd1])
+   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):
+      assert(assembler.increg64('r11') == [0x49, 0xff, 0xc3])
+      assert(assembler.increg64('rcx') == [0x48, 0xff, 0xc1])
+
+   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):
+      # 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):
+      assert(assembler.mov('rax', ['r8','r15',0x11]) == [0x4b,0x8b,0x44,0x38,0x11])
+      assert(assembler.mov('r13', ['rbp','rcx',0x23]) == [0x4c,0x8b,0x6c,0xd,0x23])
+
+      assert(assembler.mov('r9', ['rbp',-0x33]) == [0x4c,0x8b,0x4d,0xcd])
+      #assert(assembler.movreg64('rbx', ['rax']) == [0x48, 0x8b,0x18])
+
+      assert(assembler.mov('rax', [0xb000]) == [0x48,0x8b,0x4,0x25,0x0,0xb0,0x0,0x0])
+      assert(assembler.mov('r11', [0xa0]) == [0x4c,0x8b,0x1c,0x25,0xa0,0x0,0x0,0x0])
+
+      assert(assembler.mov('r11', ['RIP', 0xf]) == [0x4c,0x8b,0x1d,0x0f,0x0,0x0,0x0])
+
+   def testAsmMemStores(self):
+      assert(assembler.mov(['rbp', 0x13],'rbx') == [0x48,0x89,0x5d,0x13])
+      assert(assembler.mov(['r12', 0x12],'r9') == [0x4d,0x89,0x4c,0x24,0x12])
+      assert(assembler.mov(['rcx', 0x11],'r14') == [0x4c,0x89,0x71,0x11])
+
+
+      assert(assembler.mov([0xab], 'rbx') == [0x48,0x89,0x1c,0x25,0xab,0x0,0x0,0x0])
+      assert(assembler.mov([0xcd], 'r13') == [0x4c,0x89,0x2c,0x25,0xcd,0x0,0x0,0x0])
+
+      assert(assembler.mov(['RIP', 0xf], 'r9') == [0x4c,0x89,0x0d,0x0f,0x0,0x0,0x0])
+
+   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):
+      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):
+      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):
+      assert(assembler.addreg64('rbx', 'r13') == [0x4c, 0x01, 0xeb])
+      assert(assembler.addreg64('rax', 'rbx') == [0x48, 0x01, 0xd8])
+      assert(assembler.addreg64('r12', 'r13') == [0x4d, 0x01, 0xec])
+
+      assert(assembler.addreg64('rbx', 0x13) == [0x48, 0x83, 0xc3, 0x13])
+      assert(assembler.addreg64('r11', 0x1234567) == [0x49, 0x81, 0xc3, 0x67, 0x45,0x23,0x1])
+      assert(assembler.addreg64('rsp', 0x33) == [0x48, 0x83, 0xc4, 0x33])
+
+   def testAssemblerSUB(self):
+      assert(assembler.subreg64('rdx', 'r14') == [0x4c, 0x29, 0xf2])
+      assert(assembler.subreg64('r15', 'rbx') == [0x49, 0x29, 0xdf])
+      assert(assembler.subreg64('r8', 'r9') == [0x4d, 0x29, 0xc8])
+
+      assert(assembler.subreg64('rsp', 0x123456) == [0x48, 0x81, 0xec, 0x56,0x34,0x12,0x0])
+      assert(assembler.subreg64('rsp', 0x12) == [0x48, 0x83, 0xec, 0x12])
+
+   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):
+      assert(assembler.imulreg64_rax('rdi') == [0x48, 0xf7, 0xef])
+      assert(assembler.imulreg64_rax('r10') == [0x49, 0xf7, 0xea])
+      assert(assembler.imulreg64_rax('rdx') == [0x48, 0xf7, 0xea])
+
+      assert(assembler.imulreg64('r11', 'rdi') == [0x4c, 0xf, 0xaf, 0xdf])
+      assert(assembler.imulreg64('r12', 'rbx') == [0x4c, 0xf, 0xaf, 0xe3])
+      # nasm generates this machine code: 0x4d, 0x6b, 0xff, 0xee
+      # This also works: 4D0FAFFE (another variant?? )
+      assert(assembler.imulreg64('r15', 'r14') == [0x4d, 0x0f, 0xaf, 0xfe])
+
+
+if __name__ == '__main__':
+    unittest.main()
+
--- a/python/x86.py	Sat May 25 15:15:42 2013 +0200
+++ b/python/x86.py	Sun May 26 15:28:07 2013 +0200
@@ -2,7 +2,10 @@
 import ir
 
 class X86CodeGenSimple:
-   """ Inefficient code generation, assume stack machine """
+   """ 
+    Inefficient code generation, assume stack machine 
+    backend
+   """
    def __init__(self, diag):
       self.diag = diag