# HG changeset patch # User Windel Bouwman # Date 1373031022 -7200 # Node ID 494828a7adf1fd9411324feda18965f5b5f31cf6 # Parent 8b2e5f3cd579afa8988e845faf0613f9cbac0aa5 added some sort of cache to assembler diff -r 8b2e5f3cd579 -r 494828a7adf1 python/arm_cm3.py --- 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('> 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() - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/asm.py --- 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 """ diff -r 8b2e5f3cd579 -r 494828a7adf1 python/codegenarm.py --- 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)) diff -r 8b2e5f3cd579 -r 494828a7adf1 python/cortexm3.py --- /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('> 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() + diff -r 8b2e5f3cd579 -r 494828a7adf1 python/pyyacc.py --- 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() diff -r 8b2e5f3cd579 -r 494828a7adf1 python/testasm.py --- 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') diff -r 8b2e5f3cd579 -r 494828a7adf1 python/testcg.py --- 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') diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/code1.ks --- 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. - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/main.c --- 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 - -int main() -{ - printf("Hello world\n"); - return 0; -} - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/main.s.bc Binary file python/tests/main.s.bc has changed diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/ppcitest.py --- 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) - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/testcode.c --- 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; -} - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/testproject/main.mod --- 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. - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/testproject/test.lcp --- 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 @@ - - - - - - - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/tests/testproject/test.mod --- 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. - diff -r 8b2e5f3cd579 -r 494828a7adf1 python/zcc.py --- 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