Mercurial > lcfOS
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