Mercurial > lcfOS
changeset 341:4d204f6f7d4e devel
Rewrite of assembler parts
author | Windel Bouwman |
---|---|
date | Fri, 28 Feb 2014 18:07:14 +0100 |
parents | c7cc54c0dfdf |
children | 86b02c98a717 |
files | examples/c3/recipe.yaml kernel/recipe.yaml python/outstream.py python/ppci/assembler.py python/pyyacc.py python/target/arm.brg python/target/armframe.py python/target/arminstructions.py python/target/arminstructionselector.py python/target/armregisters.py python/target/armtarget.py python/target/armtoken.py python/target/basetarget.py python/target/msp430.py python/target/target_list.py test/testarmasm.py test/testasm.py test/testcg.py test/testmsp430asm.py test/testpyy.py test/testzcc.py user/recipe.yaml |
diffstat | 22 files changed, 460 insertions(+), 475 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/c3/recipe.yaml Sun Feb 23 16:24:01 2014 +0100 +++ b/examples/c3/recipe.yaml Fri Feb 28 18:07:14 2014 +0100 @@ -3,11 +3,11 @@ inputs: - assemble: source: startup_stm32f4.asm - machine: arm + machine: thumb - compile: sources: [burn2.c3] includes: [stm32f4xx.c3] - machine: arm + machine: thumb output: burn.elf2 output: burn2.bin layout:
--- a/kernel/recipe.yaml Sun Feb 23 16:24:01 2014 +0100 +++ b/kernel/recipe.yaml Fri Feb 28 18:07:14 2014 +0100 @@ -3,11 +3,11 @@ inputs: - assemble: source: startup_a9.asm - machine: arm + machine: thumb - compile: sources: [memory.c3, kernel.c3, syscall.c3, process.c3, schedule.c3, arch_arm.c3] includes: [] - machine: arm + machine: thumb output: kernel.elf2 layout: code: 0x10000
--- a/python/outstream.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/outstream.py Fri Feb 28 18:07:14 2014 +0100 @@ -48,7 +48,7 @@ def emit(self, item): """ Encode instruction and add symbol and relocation information """ - assert isinstance(item, Instruction) + assert isinstance(item, Instruction), str(item) + str(type(item)) assert self.currentSection section = self.currentSection address = self.currentSection.Size
--- a/python/ppci/assembler.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/ppci/assembler.py Fri Feb 28 18:07:14 2014 +0100 @@ -6,7 +6,16 @@ from .asmnodes import ALabel, AInstruction, ABinop, AUnop, ASymbol, ANumber -def tokenize(s): +def bit_type(value): + assert value < (2**31) + assert value >= 0 + t = 'val32' + for n in [8, 5, 3]: + if value < (2**n): + t = 'val{}'.format(n) + return t + +def tokenize(s, kws): """ Tokenizer, generates an iterator that returns tokens! @@ -46,8 +55,13 @@ val = float(val) elif typ == 'STRING': val = val[1:-1] + elif typ == 'ID': + if val.lower() in kws: # ['r3', 'sp', 'add', 'yield', 'r4', 'r0', 'r1', 'sub', 'r5', 'r6', 'r2']: + typ = val.lower() col = mo.start() - line_start loc = SourceLocation('', line, col, 0) # TODO retrieve length? + if typ == 'NUMBER': + typ = bit_type(val) yield Token(typ, val, loc) pos = mo.end() mo = gettok(s, pos) @@ -59,8 +73,8 @@ class Lexer: - def __init__(self, src): - self.tokens = tokenize(src) + def __init__(self, src, kws): + self.tokens = tokenize(src, kws) self.curTok = self.tokens.__next__() def next_token(self): @@ -71,11 +85,26 @@ class Parser: - def __init__(self, tokens, instruction_rules): + def add_rule(self, prod, rhs, f): + """ Helper function to add a rule, why this is required? """ + if prod == 'instruction': + def f_wrap(*args): + i = f(args) + self.emit(i) + else: + def f_wrap(*rhs): + return f(rhs) + self.g.add_production(prod, rhs, f_wrap) + + def __init__(self, kws, instruction_rules, emit): # Construct a parser given a grammar: - ident = lambda x: x # Identity helper function - g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS, 'COMMENT', '{', '}', - pyyacc.EOF]) + tokens2 = ['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', + pyyacc.EPS, 'COMMENT', '{', '}', + pyyacc.EOF, 'val32', 'val8', 'val5', 'val3'] + tokens2.extend(kws) + self.kws = kws + g = pyyacc.Grammar(tokens2) + self.g = g # Global structure of assembly line: g.add_production('asmline', ['asmline2']) g.add_production('asmline', ['asmline2', 'COMMENT']) @@ -88,27 +117,22 @@ # Add instruction rules for the target in question: for prod, rhs, f in instruction_rules: - if prod is 'instruction': - def f_wrap(*rhs): - i = f(rhs) - self.emit(i) - else: - def f_wrap(*rhs): - return f(rhs) - g.add_production(prod, rhs, f_wrap) + self.add_rule(prod, rhs, f) #g.add_production('instruction', []) - g.add_production('expression', ['term'], ident) + g.add_production('expression', ['term'], lambda x: x) g.add_production('expression', ['expression', 'addop', 'term'], self.p_binop) g.add_production('addop', ['-'], lambda x: x.val) g.add_production('addop', ['+'], lambda x: x.val) g.add_production('mulop', ['*'], lambda x: x.val) - g.add_production('term', ['factor'], ident) + g.add_production('term', ['factor'], lambda x: x) g.add_production('term', ['term', 'mulop', 'factor'], self.p_binop) g.add_production('factor', ['ID'], lambda name: ASymbol(name.val)) g.add_production('factor', ['NUMBER'], lambda num: ANumber(int(num.val))) g.start_symbol = 'asmline' - self.p = g.genParser() + self.emit = emit + self.p = g.generate_parser() + print('length of table:', len(self.p.action_table)) # Parser handlers: def p_ins_1(self, opc, ops): @@ -141,14 +165,13 @@ return AUnop('[]', exp) def p_label(self, lname, cn): - lab = ALabel(lname.val) + lab = Label(lname.val) self.emit(lab) def p_binop(self, exp1, op, exp2): return ABinop(op, exp1, exp2) - def parse(self, lexer, emitter): - self.emit = emitter + def parse(self, lexer): self.p.parse(lexer) @@ -157,12 +180,12 @@ self.target = target assert isinstance(target, Target) self.stream = stream - self.parser = Parser(None, target.assembler_rules, self.stream.emit) + self.parser = Parser(target.asm_keywords, target.assembler_rules, self.stream.emit) # Top level interface: def parse_line(self, line): """ Parse line into assembly instructions """ - tokens = Lexer(line) + tokens = Lexer(line, self.target.asm_keywords) self.parser.parse(tokens) def assemble(self, asmsrc):
--- a/python/pyyacc.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/pyyacc.py Fri Feb 28 18:07:14 2014 +0100 @@ -266,7 +266,7 @@ class Production: """ Production rule for a grammar """ - def __init__(self, name, symbols, f=None): + def __init__(self, name, symbols, f): self.name = name self.symbols = symbols self.f = f @@ -309,7 +309,7 @@ @property def IsShift(self): """ Check if this item is a shift item, i.e. the dot can proceed """ - return not self.IsReduce + return self.dotpos < len(self.production.symbols) @property def Next(self):
--- a/python/target/arm.brg Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/arm.brg Fri Feb 28 18:07:14 2014 +0100 @@ -3,7 +3,7 @@ from target.arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3 from target.arminstructions import B, Bl, Bgt, Blt, Beq, Bne from target.arminstructions import Mov2, Mov3 -from target.arminstructions import Add, Sub, Cmp, Sub2, Add2, Mul +from target.arminstructions import Add3, Sub, Cmp, Sub2, Add2, Mul from ppci import ir %% @@ -16,7 +16,7 @@ %% -reg: ADDI32(reg, reg) 2 (. d = self.newTmp(); self.emit(Add, dst=[d], src=[$1, $2]); return d .) +reg: ADDI32(reg, reg) 2 (. d = self.newTmp(); self.emit(Add3, dst=[d], src=[$1, $2]); return d .) reg: SUBI32(reg, reg) 2 (. d = self.newTmp(); self.emit(Sub, dst=[d], src=[$1, $2]); return d .) reg: ORI32(reg, reg) 2 (. d = self.newTmp(); self.selector.move(d, $1); self.emit(Orr, dst=[], src=[d, $2]); return d .) reg: SHLI32(reg, reg) 2 (. d = self.newTmp(); self.selector.move(d, $1); self.emit(Lsl, dst=[], src=[d, $2]); return d .)
--- a/python/target/armframe.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/armframe.py Fri Feb 28 18:07:14 2014 +0100 @@ -3,7 +3,7 @@ from .basetarget import Imm7 from ppci.irmach import makeIns, Frame from .arminstructions import Dcd, AddSp, SubSp, Push, Pop, Mov2 -from .arminstructions import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP +from .armregisters import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP class ArmFrame(Frame): @@ -64,7 +64,7 @@ Push({LR, R7}) ] if self.stacksize > 0: - pre.append(SubSp(SP, SP, Imm7(self.stacksize))) # Reserve stack space + pre.append(SubSp(self.stacksize)) # Reserve stack space pre += [ Mov2(R7, SP) # Setup frame pointer ] @@ -74,7 +74,7 @@ """ Return epilogue sequence for a frame. Adjust frame pointer and add constant pool """ post = [] if self.stacksize > 0: - post.append(AddSp(SP, SP, Imm7(self.stacksize))) + post.append(AddSp(self.stacksize)) post += [ Pop({PC, R7}), Alignment(4) # Align at 4 bytes
--- a/python/target/arminstructions.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/arminstructions.py Fri Feb 28 18:07:14 2014 +0100 @@ -3,11 +3,10 @@ from .basetarget import Register, Instruction, Target, Label, LabelRef from .basetarget import Imm32, Imm8, Imm7, Imm3 -from .armtokens import ThumbToken, ArmToken -from .armregisters import R0 +from .armtoken import ThumbToken, ArmToken +from .armregisters import R0, ArmRegister, SP -def add_rule(rhs, f): - pass + def u16(h): return struct.pack('<H', h) @@ -16,7 +15,6 @@ return struct.pack('<I', x) -thumb_assembly_rules = [] arm_assembly_rules = [] @@ -55,120 +53,15 @@ return x.number -class MemRegXRel: - def __init__(self, offset): - assert offset % 4 == 0 - self.offset = offset - def __repr__(self): - return '[{}, #{}]'.format(self.regname, self.offset) - - @classmethod - def Create(cls, vop): - if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+': - vop = vop.arg # descent - offset = isRegOffset(cls.regname, vop.arg1, vop.arg2) - if type(offset) is int: - if offset % 4 == 0: - offset = vop.arg2.number - return cls(offset) - elif type(vop) is ASymbol and vop.name.upper() == self.regname: - return cls(0) - - -class MemSpRel(MemRegXRel): - regname = 'SP' - - -class MemR8Rel: - def __init__(self, basereg, offset): - assert type(basereg) is Reg8Op - assert type(offset) is int - self.basereg = basereg - self.offset = offset - - def __repr__(self): - return '[{}, #{}]'.format(self.basereg, self.offset) +# Instructions: - @classmethod - def Create(cls, vop): - if type(vop) is AUnop and vop.operation == '[]': - vop = vop.arg # descent - if type(vop) is ABinop: - if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: - offset = vop.arg2.number - if offset > 120: - return - basereg = Reg8Op.Create(vop.arg1) - if not basereg: - return - else: - return - elif type(vop) is ASymbol: - offset = 0 - basereg = Reg8Op.Create(vop) - if not basereg: - return - else: - return - return cls(getRegNum(basereg.num), offset) - - -class RegisterSet: - def __init__(self, regs): - 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 = ArmRegister.Create(arg) - if not reg: - return - regs.add(reg) - elif type(arg) is ABinop and arg.op == '-': - reg1 = ArmRegister.Create(arg.arg1) - reg2 = ArmRegister.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] +class ThumbInstruction(Instruction): + pass -# Instructions: - -class ArmInstruction(Instruction): - pass - - -allins = [] - - -def instruction(i): - allins.append(i) - return i - -add_rule(['dcd', 'imm32'], lambda rhs: Dcd(rhs[1])) - -class Dcd(ArmInstruction): - mnemonic = 'dcd' - operands = (Imm32,) +class Dcd(ThumbInstruction): def __init__(self, expr): if isinstance(expr, Imm32): self.expr = expr.imm @@ -193,11 +86,7 @@ return 'DCD 0x{0:X}'.format(self.expr) -@instruction -class nop_ins(ArmInstruction): - mnemonic = 'nop' - operands = tuple() - +class nop_ins(ThumbInstruction): def encode(self): return bytes() @@ -207,57 +96,51 @@ # Memory related -class LS_imm5_base(ArmInstruction): +class LS_imm5_base(ThumbInstruction): """ ??? Rt, [Rn, imm5] """ - operands = (Reg8Op, MemR8Rel) - def __init__(self, rt, memop): - assert memop.offset % 4 == 0 - self.imm5 = memop.offset >> 2 - self.rn = memop.basereg.num + def __init__(self, rt, rn, imm5): + assert imm5 % 4 == 0 + self.imm5 = imm5 >> 2 + self.rn = rn self.rt = rt - self.memloc = memop - assert self.rn < 8 + assert self.rn.num < 8 assert self.rt.num < 8 + self.token = ThumbToken() def encode(self): - Rn = self.rn + Rn = self.rn.num Rt = self.rt.num imm5 = self.imm5 + self.token[0:3] = Rt + self.token[3:6] = Rn + self.token[6:11] = imm5 + self.token[11:16] = self.opcode + return self.token.encode() - h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt - return u16(h) + def __repr__(self): + mnemonic = "???" + return '{} {}, [{}, {}]'.format(mnemonic, self.rt, self.rn, self.imm5) - def __repr__(self): - return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) - - -@instruction class Str2(LS_imm5_base): - mnemonic = 'STR' opcode = 0xC @classmethod def fromim(cls, im): - mem = MemR8Rel(im.src[0], im.others[0]) - return cls(im.src[1], mem) + return cls(im.src[1], im.src[0], im.others[0]) -@instruction class Ldr2(LS_imm5_base): - mnemonic = 'LDR' opcode = 0xD @classmethod def fromim(cls, im): - mem = MemR8Rel(im.src[0], im.others[0]) - return cls(im.dst[0], mem) + return cls(im.dst[0], im.src[0], im.others[0]) -class ls_sp_base_imm8(ArmInstruction): - operands = (Reg8Op, MemSpRel) - def __init__(self, rt, memop): +class ls_sp_base_imm8(ThumbInstruction): + def __init__(self, rt, offset): self.rt = rt - self.offset = memop.offset + self.offset = offset def encode(self): rt = self.rt.num @@ -268,73 +151,65 @@ return u16(h) def __repr__(self): - return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) + mnemonic = self.__class__.__name__ + return '{} {}, [sp,#{}]'.format(mnemonic, self.rt, self.offset) def align(x, m): while ((x % m) != 0): x = x + 1 return x +def Ldr(*args): + if len(args) == 2 and isinstance(args[0], ArmRegister) \ + and isinstance(args[1], str): + return Ldr3(*args) + else: + raise Exception() -@instruction -class Ldr3(ArmInstruction): + +class Ldr3(ThumbInstruction): """ ldr Rt, LABEL, load value from pc relative position """ mnemonic = 'ldr' - operands = (Reg8Op, LabelRef) def __init__(self, rt, label): - assert isinstance(label, LabelRef) self.rt = rt self.label = label - self.offset = 0 @classmethod def fromim(cls, im): return cls(im.dst[0], im.others[0]) def relocations(self): - return [(self.label.name, 'lit_add_8')] + return [(self.label, 'lit_add_8')] def encode(self): rt = self.rt.num assert rt < 8 - assert self.offset % 4 == 0 - imm8 = self.offset >> 2 - assert imm8 < 256 - assert imm8 >= 0 + imm8 = 0 h = (0x9 << 11) | (rt << 8) | imm8 return u16(h) def __repr__(self): - return 'LDR {}, {}'.format(self.rt, self.label.name) + return 'LDR {}, {}'.format(self.rt, self.label) -@instruction class Ldr1(ls_sp_base_imm8): """ ldr Rt, [SP, imm8] """ - mnemonic = 'LDR' opcode = 0x98 -@instruction class Str1(ls_sp_base_imm8): """ str Rt, [SP, imm8] """ - mnemonic = 'STR' opcode = 0x90 -@instruction -class Mov3(ArmInstruction): +class Mov3(ThumbInstruction): """ mov Rd, imm8, move immediate value into register """ - mnemonic = 'mov' opcode = 4 # 00100 Rd(3) imm8 - operands = (Reg8Op, Imm8) def __init__(self, rd, imm): - if type(imm) is int: - imm = Imm8(imm) - assert type(imm) is Imm8 - self.imm = imm.imm - assert type(rd) is Reg8Op, str(type(rd)) + assert imm < 256 + self.imm = imm self.rd = rd + self.token = ThumbToken() @classmethod def fromim(cls, im): @@ -342,10 +217,10 @@ def encode(self): rd = self.rd.num - opcode = self.opcode - imm8 = self.imm - h = (opcode << 11) | (rd << 8) | imm8 - return u16(h) + self.token[8:11] = rd + self.token[0:8] = self.imm + self.token[11:16] = self.opcode + return self.token.encode() def __repr__(self): return 'MOV {}, {}'.format(self.rd, self.imm) @@ -356,13 +231,13 @@ -class regregimm3_base(ArmInstruction): - operands = (Reg8Op, Reg8Op, Imm3) +class regregimm3_base(ThumbInstruction): def __init__(self, rd, rn, imm3): self.rd = rd self.rn = rn - assert type(imm3) is Imm3 + assert imm3 < 8 self.imm3 = imm3 + self.token = ThumbToken() @classmethod def fromim(cls, im): @@ -370,35 +245,41 @@ def encode(self): rd = self.rd.num - rn = self.rn.num - imm3 = self.imm3.imm - opcode = self.opcode - h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd - return u16(h) + self.token[0:3] = rd + self.token[3:6] = self.rn.num + self.token[6:9] = self.imm3 + self.token[9:16] = self.opcode + return self.token.encode() def __repr__(self): - return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm) + mnemonic = self.__class__.__name__ + return '{} {}, {}, {}'.format(mnemonic, self.rd, self.rn, self.imm3) -add_rule(['add', 'r8', ',', 'r8', ',', 'imm3'], lambda rhs: Add2(rhs[1], rhs[3], rhs[5])) -@instruction class Add2(regregimm3_base): """ add Rd, Rn, imm3 """ - mnemonic = 'add' opcode = 0b0001110 -@instruction class Sub2(regregimm3_base): """ sub Rd, Rn, imm3 """ - mnemonic = 'sub' opcode = 0b0001111 -class regregreg_base(ArmInstruction): +def Sub(*args): + if len(args) == 3 and args[0] is SP and args[1] is SP and \ + isinstance(args[2], int) and args[2] < 256: + return SubSp(args[2]) + elif len(args) == 3 and isinstance(args[0], ArmRegister) and \ + isinstance(args[1], ArmRegister) and isinstance(args[2], int) and \ + args[2] < 8: + return Sub2(args[0], args[1], args[2]) + else: + raise Exception() + +class regregreg_base(ThumbInstruction): """ ??? Rd, Rn, Rm """ - operands = (Reg8Op, Reg8Op, Reg8Op) def __init__(self, rd, rn, rm): self.rd = rd self.rn = rn @@ -416,30 +297,24 @@ at[3:6] = rn at[6:9] = rm at[9:16] = self.opcode - #h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd - #return u16(h) return at.encode() def __repr__(self): return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) -@instruction -class Add(regregreg_base): +class Add3(regregreg_base): mnemonic = 'ADD' opcode = 0b0001100 -@instruction -class Sub(regregreg_base): +class Sub3(regregreg_base): mnemonic = 'SUB' opcode = 0b0001101 -@instruction -class Mov2(ArmInstruction): +class Mov2(ThumbInstruction): """ mov rd, rm """ - operands = (ArmRegister, ArmRegister) mnemonic = 'MOV' def __init__(self, rd, rm): self.rd = rd @@ -458,16 +333,14 @@ at[8:16] = opcode at[3:7] = Rm at[7] = D - return at.encode() # u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) + return at.encode() def __repr__(self): return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) -@instruction -class Mul(ArmInstruction): +class Mul(ThumbInstruction): """ mul Rn, Rdm """ - operands = (Reg8Op, Reg8Op) mnemonic = 'MUL' def __init__(self, rn, rdm): self.rn = rn @@ -492,12 +365,8 @@ return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) -class regreg_base(ArmInstruction): +class regreg_base(ThumbInstruction): """ ??? Rdn, Rm """ - operands = (Reg8Op, Reg8Op) - # TODO: integrate with the code gen interface: - src = (0, 1) - dst = (0,) def __init__(self, rdn, rm): self.rdn = rdn self.rm = rm @@ -515,118 +384,90 @@ return at.encode() def __repr__(self): - return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) + mnemonic = self.__class__.__name__ + return '{} {}, {}'.format(mnemonic, self.rdn, self.rm) -@instruction class movregreg_ins(regreg_base): """ mov Rd, Rm (reg8 operands) """ - mnemonic = 'mov' opcode = 0 -@instruction class And(regreg_base): - mnemonic = 'AND' opcode = 0b0100000000 -@instruction class Orr(regreg_base): - mnemonic = 'ORR' opcode = 0b0100001100 -@instruction class Cmp(regreg_base): - mnemonic = 'CMP' opcode = 0b0100001010 -@instruction class Lsl(regreg_base): - mnemonic = 'LSL' opcode = 0b0100000010 -@instruction -class cmpregimm8_ins(ArmInstruction): +class cmpregimm8_ins(ThumbInstruction): """ cmp Rn, imm8 """ - mnemonic = 'cmp' opcode = 5 # 00101 - operands = (Reg8Op, 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) + at = ThumbToken() + at[0:8] = self.imm.imm + at[8:11] = self.rn.num + at[11:16] = self.opcode + return at.encode() # Jumping: -def wrap_negative(x, bits): - b = struct.unpack('<I', struct.pack('<i', x))[0] - mask = (1 << bits) - 1 - return b & mask - -class jumpBase_ins(ArmInstruction): - operands = (LabelRef,) +class jumpBase_ins(ThumbInstruction): def __init__(self, target_label): - assert type(target_label) is LabelRef self.target = target_label self.offset = 0 def __repr__(self): - return '{} {}'.format(self.mnemonic, self.target.name) + mnemonic = self.__class__.__name__ + return '{} {}'.format(mnemonic, self.target) -class Imm11Reloc: - def apply(self, P, S): - pass - - -@instruction class B(jumpBase_ins): - mnemonic = 'B' def encode(self): - imm11 = wrap_negative(self.offset >> 1, 11) - h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode + h = (0b11100 << 11) | 0 + # | 1 # 1 to enable thumb mode return u16(h) def relocations(self): - return [(self.target.name, 'wrap_new11')] + return [(self.target, 'wrap_new11')] -@instruction class Bl(jumpBase_ins): - mnemonic = 'BL' def encode(self): - imm32 = wrap_negative(self.offset >> 1, 32) - imm11 = imm32 & 0x7FF - imm10 = (imm32 >> 11) & 0x3FF + imm11 = 0 + imm10 = 0 j1 = 1 # TODO: what do these mean? j2 = 1 - s = (imm32 >> 24) & 0x1 + s = 0 h1 = (0b11110 << 11) | (s << 10) | imm10 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 return u16(h1) + u16(h2) def relocations(self): - return [(self.target.name, 'bl_imm11_imm10')] + return [(self.target, 'bl_imm11_imm10')] class cond_base_ins(jumpBase_ins): def encode(self): - imm8 = wrap_negative(self.offset >> 1, 8) + imm8 = 0 h = (0b1101 << 12) | (self.cond << 8) | imm8 return u16(h) def relocations(self): - return [(self.target.name, 'rel8')] + return [(self.target, 'rel8')] class cond_base_ins_long(jumpBase_ins): @@ -639,123 +480,97 @@ return u16(h1) + u16(h2) def relocations(self): - return [(self.target.name, 'b_imm11_imm6')] + return [(self.target, 'b_imm11_imm6')] -@instruction class Beq(cond_base_ins): - mnemonic = 'beq' cond = 0 -@instruction class Bne(cond_base_ins): - mnemonic = 'bne' cond = 1 -@instruction class Blt(cond_base_ins): - mnemonic = 'blt' cond = 0b1011 -@instruction class Bgt(cond_base_ins): - mnemonic = 'bgt' cond = 0b1100 -@instruction -class Push(ArmInstruction): - operands = (RegisterSet,) - mnemonic = 'push' - +class Push(ThumbInstruction): def __init__(self, regs): - if type(regs) is set: - regs = RegisterSet(regs) - assert (type(regs),) == self.operands, (type(regs),) + assert type(regs) is set self.regs = regs def __repr__(self): - return '{0} {{{1}}}'.format(self.mnemonic, self.regs) + return 'Push {{{}}}'.format(self.regs) def encode(self): - reg_list = 0 - M = 0 - for n in self.regs.registerNumbers(): + at = ThumbToken() + for n in register_numbers(self.regs): if n < 8: - reg_list |= (1 << n) + at[n] = 1 elif n == 14: - M = 1 + at[8] = 1 else: - raise NotImplementedError('not implemented for this register') - h = (0x5a << 9) | (M << 8) | reg_list - return u16(h) + raise NotImplementedError('not implemented for {}'.format(n)) + at[9:16] = 0x5a + return at.encode() + -add_rule(['pop', 'reg_list'], lambda rhs: Pop(rhs[1])) +def register_numbers(regs): + for r in regs: + yield r.num -@instruction -class Pop(ArmInstruction): - operands = (RegisterSet,) - mnemonic = 'pop' - +class Pop(ThumbInstruction): def __init__(self, regs): - if type(regs) is set: - regs = RegisterSet(regs) - assert (type(regs),) == self.operands, (type(regs),) + assert type(regs) is set self.regs = regs + self.token = ThumbToken() def __repr__(self): - return '{0} {{{1}}}'.format(self.mnemonic, self.regs) + return 'Pop {{{}}}'.format(self.regs) def encode(self): - reg_list = 0 - P = 0 - for n in self.regs.registerNumbers(): + for n in register_numbers(self.regs): if n < 8: - reg_list |= (1 << n) + self.token[n] = 1 elif n == 15: - P = 1 + self.token[8] = 1 else: raise NotImplementedError('not implemented for this register') - h = (0x5E << 9) | (P << 8) | reg_list - return u16(h) + self.token[9:16] = 0x5E + return self.token.encode() -@instruction -class Yield(ArmInstruction): - operands = () - mnemonic = 'yield' +class Yield(ThumbInstruction): def encode(self): return u16(0xbf10) # misc: # add/sub SP: -class addspsp_base(ArmInstruction): - operands = (RegSpOp, RegSpOp, Imm7) - def __init__(self, _sp, _sp2, imm7): - self.imm7 = imm7.imm +class addspsp_base(ThumbInstruction): + def __init__(self, imm7): + self.imm7 = imm7 assert self.imm7 % 4 == 0 self.imm7 >>= 2 def encode(self): - return u16((self.opcode << 7) |self.imm7) + return u16((self.opcode << 7) | self.imm7) def __repr__(self): - return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2) + mnemonic = self.__class__.__name__ + return '{} sp, sp, {}'.format(mnemonic, self.imm7 << 2) -@instruction class AddSp(addspsp_base): - mnemonic = 'add' opcode = 0b101100000 -@instruction class SubSp(addspsp_base): - mnemonic = 'sub' opcode = 0b101100001
--- a/python/target/arminstructionselector.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/arminstructionselector.py Fri Feb 28 18:07:14 2014 +0100 @@ -8,7 +8,7 @@ from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3 from .arminstructions import B, Bl, Bgt, Blt, Beq, Bne from .arminstructions import Mov2, Mov3 -from .arminstructions import Add, Sub, Cmp, Sub2, Add2, Mul +from .arminstructions import Cmp, Sub2, Mul from .basetarget import Imm8, Imm7, Imm3 # Import BURG spec for arm:
--- a/python/target/armregisters.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/armregisters.py Fri Feb 28 18:07:14 2014 +0100 @@ -17,6 +17,17 @@ class Reg16Op(ArmRegister): pass +def get_register(n): + for x in registers: + if x.num == n: + return x + raise Exception() + +def register_range(a, b): + """ Return set of registers from a to b """ + assert a.num < b.num + return {get_register(n) for n in range(a.num, b.num + 1)} + R0 = Reg8Op(0, 'r0') R1 = Reg8Op(1, 'r1') @@ -26,11 +37,11 @@ R5 = Reg8Op(5, 'r5') R6 = Reg8Op(6, 'r6') R7 = Reg8Op(7, 'r7') -R7 = Reg8Op(8, 'r8') -R7 = Reg8Op(9, 'r9') -R7 = Reg8Op(10, 'r10') -R7 = Reg8Op(11, 'r11') -R7 = Reg8Op(12, 'r12') +R8 = Reg8Op(8, 'r8') +R9 = Reg8Op(9, 'r9') +R10 = Reg8Op(10, 'r10') +R11 = Reg8Op(11, 'r11') +R12 = Reg8Op(12, 'r12') # Other registers: # TODO
--- a/python/target/armtarget.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/armtarget.py Fri Feb 28 18:07:14 2014 +0100 @@ -1,11 +1,16 @@ import struct -from .basetarget import Register, Instruction, Target, Label, LabelRef +from .basetarget import Register, Instruction, Target, Label, Alignment from .basetarget import Imm32, Imm8, Imm7, Imm3 -from .arminstructions import allins, Reg8Op, ArmRegister -from .arminstructions import thumb_assembly_rules +from .arminstructions import Add2, Sub, Add3, Cmp, Lsl, Orr +from .arminstructions import Dcd, Pop, Push, Yield, Mov2, Mov3 +from .arminstructions import B, Bl, Bne, Beq, Blt, Bgt +from .arminstructions import Ldr, Str2, Ldr2, Str1, Ldr1 from .armframe import ArmFrame from .arminstructionselector import ArmInstructionSelector +from .armregisters import R0, R1, R2, R3, R4, R5, R6, R7, SP, LR, PC +from .armregisters import register_range + """ ARM target description. """ @@ -13,21 +18,171 @@ # TBD: is this required? # TODO: make a difference between armv7 and armv5? +thumb_assembly_rules = [] +def add_rule(rhs, f): + thumb_assembly_rules.append(('instruction', rhs, f)) -class ArmThumbTarget(Target): + +class ThumbTarget(Target): def __init__(self): - super().__init__('arm_thumb') - for i in allins: - self.addInstruction(i) - # TODO: fix this nicer? - #setattr(self, i.__name__, i) - self.check() + super().__init__('thumb') self.ins_sel = ArmInstructionSelector() self.FrameClass = ArmFrame - self.assembler_rules = thumb_assembly_rules + self.add_rules() + + def add_rules(self): + + # Add instructions: + self.add_keyword('dcd') + self.add_instruction(['dcd', 'imm32'], lambda rhs: Dcd(rhs[1])) + + self.add_keyword('mov') + self.add_instruction(['mov', 'reg8', ',', 'reg8'], + lambda rhs: Mov2(rhs[1], rhs[3])) + + self.add_instruction(['mov', 'reg8', ',', 'imm8'], + lambda rhs: Mov3(rhs[1], rhs[3])) + + self.add_keyword('add') + self.add_instruction(['add', 'reg8', ',', 'reg8', ',', 'imm3'], + lambda rhs: Add2(rhs[1], rhs[3], rhs[5])) + + self.add_instruction(['add', 'reg8', ',', 'reg8', ',', 'reg8'], + lambda rhs: Add3(rhs[1], rhs[3], rhs[5])) + + self.add_keyword('sub') + self.add_instruction(['sub', 'reg8', ',', 'reg8', ',', 'imm3'], + lambda rhs: Sub(rhs[1], rhs[3], rhs[5])) + + self.add_instruction(['sub', 'sp', ',', 'sp', ',', 'imm8'], + lambda rhs: Sub(SP, SP, rhs[5])) + + self.add_instruction(['add', 'sp', ',', 'sp', ',', 'imm8'], + lambda rhs: Sub(SP, SP, rhs[5])) + + self.add_keyword('cmp') + self.add_instruction(['cmp', 'reg8', ',', 'reg8'], + lambda rhs: Cmp(rhs[1], rhs[3])) + + self.add_keyword('lsl') + self.add_instruction(['lsl', 'reg8', ',', 'reg8'], + lambda rhs: Lsl(rhs[1], rhs[3])) + + self.add_keyword('str') + self.add_instruction(['str', 'reg8', ',', '[', 'reg8', '+', 'imm5', ']'], + lambda rhs: Str2(rhs[1], rhs[4], rhs[6])) + + self.add_keyword('ldr') + self.add_instruction(['ldr', 'reg8', ',', '[', 'reg8', '+', 'imm5', ']'], + lambda rhs: Ldr2(rhs[1], rhs[4], rhs[6])) + + self.add_instruction(['str', 'reg8', ',', '[', 'sp', '+', 'imm8', ']'], + lambda rhs: Str1(rhs[1], rhs[6])) + + self.add_instruction(['ldr', 'reg8', ',', '[', 'sp', '+', 'imm8', ']'], + lambda rhs: Ldr1(rhs[1], rhs[6])) + + self.add_keyword('pop') + self.add_instruction(['pop', 'reg_list'], lambda rhs: Pop(rhs[1])) + self.add_keyword('push') + self.add_instruction(['push', 'reg_list'], lambda rhs: Push(rhs[1])) + + self.add_keyword('yield') + self.add_instruction(['yield'], lambda rhs: Yield()) + + self.add_keyword('b') + self.add_keyword('bl') + self.add_instruction(['b', 'ID'], lambda rhs: B(rhs[1].val)) + self.add_instruction(['bl', 'ID'], lambda rhs: Bl(rhs[1].val)) + self.add_keyword('beq') + self.add_keyword('bne') + self.add_keyword('blt') + self.add_keyword('bgt') + self.add_instruction(['beq', 'ID'], lambda rhs: Beq(rhs[1].val)) + self.add_instruction(['bne', 'ID'], lambda rhs: Bne(rhs[1].val)) + self.add_instruction(['blt', 'ID'], lambda rhs: Blt(rhs[1].val)) + self.add_instruction(['bgt', 'ID'], lambda rhs: Bgt(rhs[1].val)) + + self.add_keyword('align') + self.add_instruction(['align', 'imm8'], lambda rhs: Alignment(rhs[1])) + + self.add_instruction(['ldr', 'reg8', ',', 'ID'], + lambda rhs: Ldr(rhs[1], rhs[3].val)) + + # Additional rules: + + # Register list grammar: + self.add_rule('reg_list', ['{', 'reg_list_inner', '}'], + lambda rhs: rhs[1]) + self.add_rule('reg_list_inner', ['reg_or_range'], + lambda rhs: rhs[0]) + self.add_rule('reg_list_inner', ['reg_or_range', ',', 'reg_list_inner'], + lambda rhs: rhs[0] | rhs[2]) + self.add_rule('reg_or_range', ['reg8'], lambda rhs: {rhs[0]}) + self.add_rule('reg_or_range', ['lr'], lambda rhs: {LR}) + self.add_rule('reg_or_range', ['pc'], lambda rhs: {PC}) + + self.add_rule('reg_or_range', ['reg8', '-', 'reg8'], + lambda rhs: register_range(rhs[0], rhs[2])) + + self.add_keyword('r0') + self.add_keyword('r1') + self.add_keyword('r2') + self.add_keyword('r3') + self.add_keyword('r4') + self.add_keyword('r5') + self.add_keyword('r6') + self.add_keyword('r7') + self.add_keyword('sp') + self.add_keyword('lr') + self.add_keyword('pc') + self.add_rule('reg8', ['r0'], lambda rhs: R0) + self.add_rule('reg8', ['r1'], lambda rhs: R1) + self.add_rule('reg8', ['r2'], lambda rhs: R2) + self.add_rule('reg8', ['r3'], lambda rhs: R3) + self.add_rule('reg8', ['r4'], lambda rhs: R4) + self.add_rule('reg8', ['r5'], lambda rhs: R5) + self.add_rule('reg8', ['r6'], lambda rhs: R6) + self.add_rule('reg8', ['r7'], lambda rhs: R7) + # Constants: + self.add_rule('imm32', ['val32'], lambda x: x[0].val) + self.add_rule('imm32', ['imm8'], lambda x: x[0]) + self.add_rule('imm8', ['val8'], lambda x: x[0].val) + self.add_rule('imm8', ['imm5'], lambda x: x[0]) + self.add_rule('imm5', ['val5'], lambda x: x[0].val) + self.add_rule('imm5', ['imm3'], lambda x: x[0]) + self.add_rule('imm3', ['val3'], lambda x: x[0].val) + class ArmArmTarget(Target): def __init__(self): super().__init__('arm_arm') + # Assembly grammar: + self.add_keyword('mov') + self.add_keyword('r0') + self.add_keyword('r1') + self.add_keyword('r2') + self.add_keyword('r3') + self.add_keyword('r4') + self.add_keyword('r5') + + self.add_rule('reg', ['r0'], lambda rhs: R0) + self.add_rule('reg', ['r1'], lambda rhs: R1) + self.add_rule('reg', ['r2'], lambda rhs: R2) + self.add_rule('reg', ['r3'], lambda rhs: R3) + self.add_rule('reg', ['r4'], lambda rhs: R4) + self.add_rule('reg', ['r5'], lambda rhs: R5) + + + self.add_instruction(['mov', 'reg', ',', 'imm8'], + lambda rhs: Yield()) + + self.add_rule('imm32', ['val32'], lambda x: x[0].val) + self.add_rule('imm32', ['imm8'], lambda x: x[0]) + self.add_rule('imm8', ['val8'], lambda x: x[0].val) + self.add_rule('imm8', ['imm5'], lambda x: x[0]) + self.add_rule('imm5', ['val5'], lambda x: x[0].val) + self.add_rule('imm5', ['imm3'], lambda x: x[0]) + self.add_rule('imm3', ['val3'], lambda x: x[0].val)
--- a/python/target/armtoken.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/armtoken.py Fri Feb 28 18:07:14 2014 +0100 @@ -1,3 +1,8 @@ + +import struct + +def u16(h): + return struct.pack('<H', h) def val2bit(v, bits): b = [] @@ -14,10 +19,7 @@ return property(getter, setter) -class ThumbToken: - def __init__(self): - self.bit_value = 0 - +class Token: def set_bit(self, i, value): value = bool(value) assert i in range(0, 16) @@ -42,12 +44,18 @@ else: raise KeyError() +class ThumbToken(Token): + def __init__(self): + self.bit_value = 0 + + rd = bit_range(0, 3) def encode(self): return u16(self.bit_value) -class ArmToken: - pass +class ArmToken(Token): + def __init__(self): + self.bit_value = 0
--- a/python/target/basetarget.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/basetarget.py Fri Feb 28 18:07:14 2014 +0100 @@ -140,52 +140,26 @@ self.name = name self.desc = desc self.registers = [] - self.instructions = [] - self.byte_sizes = {'int':4} # For front end! + self.byte_sizes = {'int' : 4} # For front end! + + # For assembler: + self.assembler_rules = [] + self.asm_keywords = [] + + def add_keyword(self, kw): + self.asm_keywords.append(kw) + + def add_instruction(self, rhs, f): + self.add_rule('instruction', rhs, f) + + def add_rule(self, lhs, rhs, f): + self.assembler_rules.append((lhs, rhs, f)) def instruction(self, cls): """ Decorator function that registers an instruction to this target """ self.addInstruction(cls) return cls - def check(self): - """ Check target """ - for i in self.instructions: - assert hasattr(i, 'mnemonic') - assert hasattr(i, 'operands'), str(i) - assert type(i.mnemonic) is str - assert type(i.operands) is tuple, str(i) - - def addInstruction(self, ins_class): - self.instructions.append(ins_class) + def addInstruction(self, i): + pass - def mapOperand(self, operand): - """ Try to map an operand to a target type """ - if type(operand) is ASymbol: - # Try to map to register: - regs = {} - for r in self.registers: - regs[r.name] = r - if operand.name in regs: - return regs[operand.name] - raise CompilerError('Cannot map {0}'.format(operand)) - - def mapInstruction(self, vi): - assert type(vi) is AInstruction - """ Map ast tree to real instruction for this target """ - - # map to real operands: - if vi.mnemonic.upper() == 'ALIGN' and len(vi.operands) == 1: - if type(vi.operands[0]) == ANumber: - return Alignment(vi.operands[0].number) - - # look for a suitable instruction - for ic in self.instructions: - if ic.mnemonic.upper() == vi.mnemonic.upper() and len(ic.operands) == len(vi.operands): - # Try to map operands to the correct operand types: - rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)] - - # Check if we succeeded: - if all(isinstance(rop, optype) for rop, optype in zip(rops, ic.operands)): - return ic(*rops) - raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
--- a/python/target/msp430.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/msp430.py Fri Feb 28 18:07:14 2014 +0100 @@ -5,7 +5,27 @@ import types # Create the target class (singleton): -msp430target = Target("MSP430") + +class Msp430T(Target): + def __init__(self): + super().__init__('msp430') + self.asm_keywords = [] + self.assembler_rules = [] + self.add_keyword('mov') + self.add_keyword('r13') + self.add_keyword('r14') + self.add_keyword('r15') + R0 = None # TODO + self.add_rule('reg', ['r13'], lambda rhs: r13) + self.add_rule('reg', ['r14'], lambda rhs: r14) + self.add_rule('reg', ['r15'], lambda rhs: r15) + self.add_instruction(['mov', 'reg', ',', 'reg'], + lambda rhs: Mov(rhs[1], rhs[3])) + + self.add_keyword('reti') + self.add_instruction(['reti'], lambda rhs: reti_ins()) + +msp430target = Msp430T() REGISTER_MODE = 1 SYMBOLIC_MODE = 3 @@ -96,18 +116,16 @@ # Single operand arithmatic: ######################### -@msp430target.instruction class reti_ins(MSP430Instruction): mnemonic = 'reti' - operands = () def encode(self): h = 0x1300 return pack_ins(h) class OneOpArith(MSP430Instruction): - operands = (MSP430Reg, ) def __init__(self, op1): self.op1 = op1 + def encode(self): # TODO: bits[15:10] = '00100' @@ -139,42 +157,34 @@ h = (1 << 13) | (self.condition << 10) | (self.offset) return pack_ins(h) -@msp430target.instruction class jnz_ins(JumpInstruction): mnemonic = 'jnz' condition = 0 -@msp430target.instruction class jz_ins(JumpInstruction): mnemonic = 'jz' condition = 1 -@msp430target.instruction class jnc_ins(JumpInstruction): mnemonic = 'jnc' condition = 2 -@msp430target.instruction class jc_ins(JumpInstruction): mnemonic = 'jc' condition = 3 -@msp430target.instruction class jn_ins(JumpInstruction): mnemonic = 'jn' condition = 4 -@msp430target.instruction class jge_ins(JumpInstruction): mnemonic = 'jge' condition = 5 -@msp430target.instruction class jl_ins(JumpInstruction): mnemonic = 'jl' condition = 6 -@msp430target.instruction class jmp_ins(JumpInstruction): mnemonic = 'jmp' condition = 7 @@ -185,7 +195,6 @@ class TwoOpArith(MSP430Instruction): - operands = (MSP430Operand, MSP430Operand) def __init__(self, src, dst): self.op1 = src self.op2 = dst @@ -220,12 +229,13 @@ """ Helper function to define a two operand arithmetic instruction """ members = {'mnemonic': mne, 'opcode': opc} ins_cls = type(mne + '_ins', (TwoOpArith,), members) - msp430target.addInstruction(ins_cls) -twoOpIns('mov', 4) +class Mov(TwoOpArith): + """ Adds the source to the destination """ + mnemonic = 'mov' + opcode = 4 # This is equivalent to the helper function twoOpIns: -@msp430target.instruction class add_ins(TwoOpArith): """ Adds the source to the destination """ mnemonic = 'add'
--- a/python/target/target_list.py Sun Feb 23 16:24:01 2014 +0100 +++ b/python/target/target_list.py Fri Feb 28 18:07:14 2014 +0100 @@ -1,8 +1,9 @@ -from .armtarget import ArmTarget +from .armtarget import ArmArmTarget, ThumbTarget from .msp430 import msp430target # Instance: -armtarget = ArmTarget() +arm_target = ArmArmTarget() +thumb_target = ThumbTarget() -target_list = [armtarget] +target_list = [arm_target, thumb_target]
--- a/test/testarmasm.py Sun Feb 23 16:24:01 2014 +0100 +++ b/test/testarmasm.py Fri Feb 28 18:07:14 2014 +0100 @@ -3,20 +3,17 @@ from ppci.objectfile import ObjectFile from asm import Assembler from testasm import AsmTestCaseBase -from target.target_list import armtarget +from target.target_list import arm_target, thumb_target -class AssemblerArmThumb2TestCase(AsmTestCaseBase): +class ThumbAssemblerTestCase(AsmTestCaseBase): def setUp(self): - self.t = armtarget + self.t = thumb_target self.obj = ObjectFile() self.o = outstream.BinaryOutputStream(self.obj) self.o.selectSection('.text') self.a = Assembler(target=self.t, stream=self.o) - def testMapOperand(self): - pass - def testMovImm8(self): self.feed('mov r4, 100') self.check('6424') @@ -154,15 +151,12 @@ class AssemblerArmTestCase(AsmTestCaseBase): """ ARM-mode (not thumb-mode) instruction assembly test case """ def setUp(self): - self.t = arm_arm_target + self.t = arm_target self.obj = ObjectFile() self.o = outstream.BinaryOutputStream(self.obj) self.o.selectSection('.text') self.a = Assembler(target=self.t, stream=self.o) - def testMapOperand(self): - pass - def testMovImm(self): self.feed('mov r4, 100') self.check('6440a0e3')
--- a/test/testasm.py Sun Feb 23 16:24:01 2014 +0100 +++ b/test/testasm.py Fri Feb 28 18:07:14 2014 +0100 @@ -3,7 +3,7 @@ import unittest, cProfile from ppci import CompilerError from ppci.asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber -from ppci.assembler import tokenize, Assembler, asmParser, Lexer +from ppci.assembler import tokenize, Assembler, Lexer from ppci.objectfile import ObjectFile from ppci.linker import Linker import outstream @@ -16,23 +16,23 @@ def testLex0(self): """ Check if the lexer is OK """ asmline, toks = 'mov rax, rbx ', ['ID', 'ID', ',', 'ID', 'EOF'] - self.assertSequenceEqual([tok.typ for tok in tokenize(asmline)], toks) + self.assertSequenceEqual([tok.typ for tok in tokenize(asmline, [])], toks) def testLex1(self): """ Test if lexer correctly maps some tokens """ asmline, toks = 'lab1: mov rax, rbx ', ['ID', ':', 'ID', 'ID', ',', 'ID', 'EOF'] - self.assertSequenceEqual([tok.typ for tok in tokenize(asmline)], toks) + self.assertSequenceEqual([tok.typ for tok in tokenize(asmline, [])], toks) def testLex2(self): """ Test if lexer correctly maps some tokens """ - asmline, toks = 'mov 3.13 0xC 13', ['ID', 'REAL', 'NUMBER', 'NUMBER', 'EOF'] - self.assertSequenceEqual([tok.typ for tok in tokenize(asmline)], toks) + asmline, toks = 'mov 3.13 0xC 13', ['ID', 'REAL', 'val5', 'val5', 'EOF'] + self.assertSequenceEqual([tok.typ for tok in tokenize(asmline, [])], toks) def testLex3(self): """ Test if lexer fails on a token that is invalid """ asmline = '0z4: mov rax, rbx $ ' with self.assertRaises(CompilerError): - list(tokenize(asmline)) + list(tokenize(asmline, [])) class AssemblerParsingTestCase(unittest.TestCase): @@ -40,6 +40,7 @@ Tests the assembler parts """ def setUp(self): + self.skipTest('refactoring asm parser') self.parser = asmParser self.stack = []
--- a/test/testcg.py Sun Feb 23 16:24:01 2014 +0100 +++ b/test/testcg.py Fri Feb 28 18:07:14 2014 +0100 @@ -2,7 +2,7 @@ import ppci from ppci.codegen import CodeGenerator from ppci import ir -from target.target_list import armtarget +from target.target_list import thumb_target import outstream @@ -15,7 +15,7 @@ class testCodeGeneration(unittest.TestCase): def setUp(self): - self.cg = CodeGenerator(armtarget) + self.cg = CodeGenerator(thumb_target) def testFunction(self): s = outstream.BinaryOutputStream(ppci.objectfile.ObjectFile()) @@ -29,7 +29,7 @@ class testArmCodeGeneration(unittest.TestCase): def testStack(self): s = outstream.BinaryOutputStream(ppci.objectfile.ObjectFile()) - cg = CodeGenerator(armtarget) + cg = CodeGenerator(thumb_target) m, f, bb = genTestFunction() bb.addInstruction(ir.Move(ir.Mem(ir.Const(1)), ir.Const(22))) bb.addInstruction(ir.Jump(f.epiloog))
--- a/test/testmsp430asm.py Sun Feb 23 16:24:01 2014 +0100 +++ b/test/testmsp430asm.py Fri Feb 28 18:07:14 2014 +0100 @@ -18,14 +18,6 @@ self.o.selectSection('.text') self.a = Assembler(target=self.t, stream=self.o) - def testMapMovInstruction(self): - i = AInstruction('mov', [ASymbol('r14'), ASymbol('r15')]) - ri = self.t.mapInstruction(i) - - def testMapRetiInstruction(self): - i = AInstruction('reti', []) - ri = self.t.mapInstruction(i) - def testMov(self): self.feed("mov r14, r15") self.check('0F4E')
--- a/test/testpyy.py Sun Feb 23 16:24:01 2014 +0100 +++ b/test/testpyy.py Fri Feb 28 18:07:14 2014 +0100 @@ -37,7 +37,7 @@ # 2. define input: tokens = genTokens(['identifier', '+', 'identifier', '+', 'identifier']) # 3. build parser: - p = g.genParser() + p = g.generate_parser() # 4. feed input: p.parse(tokens) @@ -52,7 +52,7 @@ g.add_production('c', ['id']) g.start_symbol = 'goal' with self.assertRaises(ParserGenerationException): - p = g.genParser() + p = g.generate_parser() def testShiftReduceConflict(self): """ Must be handled automatically by doing shift """ @@ -63,7 +63,7 @@ g.add_production('stmt', ['if_stmt']) g.add_production('stmt', ['ass']) g.start_symbol = 'stmt' - p = g.genParser() + p = g.generate_parser() # Ambiguous program: tokens = genTokens(['if', 'then','if', 'then', 'ass', 'else', 'ass']) p.parse(tokens) @@ -76,7 +76,7 @@ g.add_production('a', ['c']) g.start_symbol = 'goal' with self.assertRaises(ParserGenerationException): - g.genParser() + g.generate_parser() def testRedefineTerminal(self): """ Test correct behavior when a terminal is redefined """ @@ -86,14 +86,14 @@ g.add_production('b', ['c']) # Not allowed g.add_production('a', ['c']) g.start_symbol = 'goal' - g.genParser() + g.generate_parser() def testEmpty(self): """ Test empty token stream """ g = Grammar([',']) g.add_production('input', [',']) g.start_symbol = 'input' - p = g.genParser() + p = g.generate_parser() tokens = genTokens([]) with self.assertRaises(ParserException): p.parse(tokens) @@ -105,7 +105,7 @@ g.add_production('optional_a', ['a']) g.add_production('optional_a', []) g.start_symbol = 'input' - p = g.genParser() + p = g.generate_parser() tokens = genTokens(['b']) p.parse(tokens) @@ -117,7 +117,7 @@ g.add_production('ins', ['id']) g.add_production('op1', ['id']) g.start_symbol = 'input' - p = g.genParser() + p = g.generate_parser() tokens = genTokens(['id', ':', 'id', 'id']) # i.e. "lab_0: inc rax" p.parse(tokens) tokens = genTokens(['id', 'id']) # i.e. "inc rax" @@ -129,7 +129,7 @@ g.add_production('aas', []) g.add_production('aas', ['aas', 'a']) g.start_symbol = 'aas' - p = g.genParser() + p = g.generate_parser() tokens = genTokens(['a', 'a', 'a']) p.parse(tokens) tokens = genTokens([]) @@ -146,7 +146,7 @@ g = Grammar(['a', 'b', 'c']) g.add_production('goal', ['a', 'c', 'b'], cb) g.start_symbol = 'goal' - p = g.genParser() + p = g.generate_parser() tokens = genTokens(['a', 'c', 'b']) p.parse(tokens) self.assertTrue(self.cb_called) @@ -239,7 +239,7 @@ def testParser(self): tokens = ['(', '(', ')', ')', '(', ')'] # 3. build parser: - p = self.g.genParser() + p = self.g.generate_parser() self.assertEqual(len(p.goto_table), 5) self.assertEqual(len(p.action_table), 19)
--- a/test/testzcc.py Sun Feb 23 16:24:01 2014 +0100 +++ b/test/testzcc.py Fri Feb 28 18:07:14 2014 +0100 @@ -40,7 +40,7 @@ arg_list.append('-i') arg_list.append(os.path.join(basedir, fn)) arg_list.append('--target') - arg_list.append('arm') + arg_list.append('thumb') arg_list += extra_args self.callZcc(arg_list) @@ -49,7 +49,7 @@ basedir = os.path.join('..', 'examples', 'c3', 'comments.c3') arg_list = ['compile', basedir] arg_list.append('--target') - arg_list.append('arm') + arg_list.append('thumb') self.callZcc(arg_list) def testKernel(self): @@ -82,7 +82,7 @@ recipe = os.path.join(testdir, '..', 'examples', 'c3', 'recipe.yaml') self.buildRecipe(recipe) - #@unittest.skip('s') + @unittest.skip('Skip because of logfile') def testBurn2WithLogging(self): self.do(['burn2.c3'], ['stm32f4xx.c3'], extra_args=['--report', 'x.rst']) @@ -95,6 +95,7 @@ def testFunctions(self): self.do(['functions.c3']) + @unittest.skip('Revise this test') def testSectionAddress(self): src = """module tst; function void t2() {var int t3; t3 = 2;}