Mercurial > lcfOS
changeset 336:d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
author | Windel Bouwman |
---|---|
date | Wed, 19 Feb 2014 22:32:15 +0100 |
parents | 582a1aaa3983 |
children | b00219172a42 |
files | examples/c3/recipe.yaml examples/c3/startup_stm32f4.asm kernel/recipe.yaml python/ppci/__init__.py python/ppci/assembler.py python/ppci/buildtasks.py python/ppci/c3/astnodes.py python/ppci/c3/codegenerator.py python/ppci/c3/parser.py python/ppci/codegen/codegen.py python/ppci/ir.py python/ppci/linker.py python/ppci/objectfile.py python/ppci/transform.py python/target/arm.brg python/target/arminstructions.py python/target/arminstructionselector.py python/target/instructionselector.py python/zcc.py test/testbintools.py test/testzcc.py user/recipe.yaml |
diffstat | 22 files changed, 338 insertions(+), 111 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/c3/recipe.yaml Mon Feb 17 20:41:30 2014 +0100 +++ b/examples/c3/recipe.yaml Wed Feb 19 22:32:15 2014 +0100 @@ -9,6 +9,8 @@ includes: [stm32f4xx.c3] machine: arm output: burn.elf2 - code: 0x08000000 - data: 0x20000000 + output: burn2.bin + layout: + code: 0x08000000 + data: 0x20000000
--- a/examples/c3/startup_stm32f4.asm Mon Feb 17 20:41:30 2014 +0100 +++ b/examples/c3/startup_stm32f4.asm Wed Feb 19 22:32:15 2014 +0100 @@ -2,5 +2,5 @@ DCD 0x20000678 ; Setup stack pointer DCD 0x08000009 ; Reset vector, jump to address 8 -B main ; Branch to main (this is actually in the interrupt vector) +B burn2_main ; Branch to main (this is actually in the interrupt vector)
--- a/kernel/recipe.yaml Mon Feb 17 20:41:30 2014 +0100 +++ b/kernel/recipe.yaml Wed Feb 19 22:32:15 2014 +0100 @@ -2,13 +2,15 @@ link: inputs: - assemble: - source: ../examples/c3/startup_stm32f4.asm + source: startup_m3.asm machine: arm - compile: sources: [memory.c3, kernel.c3, syscall.c3, process.c3, schedule.c3, arch_arm.c3] includes: [] machine: arm output: kernel.elf2 - code: 0x8000 - data: 0x9000 + layout: + code: 0x0 + data: 0x20000000 + output: kernel.bin
--- a/python/ppci/__init__.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/__init__.py Wed Feb 19 22:32:15 2014 +0100 @@ -1,6 +1,7 @@ # File to make this directory a package. import sys +import os version = '0.0.1' @@ -14,3 +15,5 @@ logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s' +def same_dir(full_path, filename): + return os.path.join(os.path.dirname(os.path.abspath(full_path)), filename)
--- a/python/ppci/assembler.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/assembler.py Wed Feb 19 22:32:15 2014 +0100 @@ -151,7 +151,7 @@ asmParser = Parser() class Assembler: - def __init__(self, target=None, stream=None): + def __init__(self, target, stream): self.target = target self.stream = stream self.restart()
--- a/python/ppci/buildtasks.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/buildtasks.py Wed Feb 19 22:32:15 2014 +0100 @@ -31,10 +31,12 @@ def __init__(self, source, target, output_object): super().__init__('Assemble') self.source = source - self.assembler = Assembler(target=target) self.output = output_object + self.ostream = outstream.BinaryOutputStream(self.output) + self.assembler = Assembler(target, self.ostream) def run(self): + self.ostream.selectSection('code') self.assembler.assemble(self.source) @@ -82,16 +84,22 @@ class Link(BuildTask): """ Link together a collection of object files """ - def __init__(self, objects, output_file): + def __init__(self, objects, layout, output_file): super().__init__('Link') self.objects = objects self.linker = Linker() self.duration = 0.1337 + self.layout = layout + self.output_file = output_file def run(self): - self.linker.link(self.objects) + output_obj = self.linker.link(self.objects, self.layout) + code = output_obj.get_section('code').data + with open(self.output_file, 'wb') as f: + f.write(code) -class ObjCopy(Task): - pass +class ObjCopy(BuildTask): + def __init__(self, objects, output_file): + super().__init__('ObjCopy')
--- a/python/ppci/c3/astnodes.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/c3/astnodes.py Wed Feb 19 22:32:15 2014 +0100 @@ -37,6 +37,11 @@ self.declarations = [] self.imports = [] + def add_declaration(self, decl): + self.declarations.append(decl) + if isinstance(decl, Function): + decl.package = self + def __repr__(self): return 'MODULE {}'.format(self.name) @@ -174,6 +179,9 @@ self.loc = loc self.declarations = [] + def add_declaration(self, decl): + self.declarations.append(decl) + def __repr__(self): return 'Func {}'.format(self.name)
--- a/python/ppci/c3/codegenerator.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/c3/codegenerator.py Wed Feb 19 22:32:15 2014 +0100 @@ -312,7 +312,7 @@ if type(tg) is not ast.Function: raise SemanticError('cannot call {}'.format(tg)) ftyp = tg.typ - fname = tg.name + fname = tg.package.name + '_' + tg.name ptypes = ftyp.parametertypes if len(expr.args) != len(ptypes): raise SemanticError('{} requires {} arguments, {} given'
--- a/python/ppci/c3/parser.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/c3/parser.py Wed Feb 19 22:32:15 2014 +0100 @@ -60,7 +60,7 @@ return t def addDeclaration(self, decl): - self.currentPart.declarations.append(decl) + self.currentPart.add_declaration(decl) def parseImport(self): self.Consume('import')
--- a/python/ppci/codegen/codegen.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/codegen/codegen.py Wed Feb 19 22:32:15 2014 +0100 @@ -1,4 +1,4 @@ -from ..ir import Module +from .. import ir from ..irutils import Verifier from target import Target from ppci import CompilerError @@ -23,7 +23,7 @@ """ Generate code for one function into a frame """ self.logger.debug('Generating code for {}'.format(irfunc.name)) # Create a frame for this function: - frame = self.target.FrameClass(irfunc.name) + frame = self.target.FrameClass(ir.label_name(irfunc)) # Canonicalize the intermediate language: canonicalize(irfunc, frame) @@ -48,7 +48,7 @@ def generate(self, ircode, outs): """ Generate code into output stream """ - assert isinstance(ircode, Module) + assert isinstance(ircode, ir.Module) outs.selectSection('code') # Munch program into a bunch of frames. One frame per function.
--- a/python/ppci/ir.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/ir.py Wed Feb 19 22:32:15 2014 +0100 @@ -3,6 +3,19 @@ """ +def label_name(dut): + """ Function that returns the assembly code label name """ + if isinstance(dut, Block): + f = dut.function + return label_name(f) + '_' + dut.name + elif isinstance(dut, Function): + return label_name(dut.module) + '_' + dut.name + elif isinstance(dut, Module): + return dut.name + else: + raise NotImplementedError(str(dut)) + + class Module: """ Container unit for variables and functions. """ def __init__(self, name): @@ -16,8 +29,9 @@ def add_function(self, f): """ Add a function to this module """ self.functions.append(f) + f.module = self - def addVariable(self, v): + def add_variable(self, v): self.variables.append(v) def getVariables(self): @@ -43,9 +57,9 @@ """ Represents a function. """ def __init__(self, name, module=None): self.name = name - self.entry = Block('{}_entry'.format(name)) + self.entry = Block('entry') self.entry.function = self - self.epiloog = Block('{}_epilog'.format(name)) + self.epiloog = Block('epilog') self.epiloog.function = self self.epiloog.addInstruction(Terminator()) self.return_value = Temp('{}_retval'.format(name)) @@ -195,6 +209,7 @@ class Call(Expression): """ Call a function with some arguments """ def __init__(self, f, arguments): + assert type(f) is str self.f = f self.arguments = arguments
--- a/python/ppci/linker.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/linker.py Wed Feb 19 22:32:15 2014 +0100 @@ -22,19 +22,71 @@ @reloc('lit_add_8') -class LitAdd8: - def apply(self): - pass +def apply_lit8(reloc, sym, section, reloc_value): + assert sym.value % 4 == 0 + offset = (sym.value - (align(reloc_value + 2, 4))) + assert offset in range(0, 1024, 4), str(offset)+str( self.dst.sections) + rel8 = offset >> 2 + section.data[reloc.offset] = rel8 + + +@reloc('wrap_new11') +def apply_wrap_new11(reloc, sym, section, reloc_value): + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-2048, 2046, 2) + imm11 = wrap_negative(offset >> 1, 11) + section.data[reloc.offset] = (imm11 & 0xff) + section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7 + + +@reloc('rel8') +def apply_rel8(reloc, sym, section, reloc_value): + assert sym.value % 2 == 0 + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-256, 254, 2), str(offset) + str(reloc) + imm8 = wrap_negative(offset >> 1, 8) + section.data[reloc.offset] = imm8 + + +@reloc('bl_imm11_imm10') +def apply_bl_imm11(reloc, sym, section, reloc_value): + assert sym.value % 2 == 0 + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-16777216, 16777214, 2), str(offset) + imm32 = wrap_negative(offset >> 1, 32) + imm11 = imm32 & 0x7FF + imm10 = (imm32 >> 11) & 0x3FF + s = (imm32 >> 24) & 0x1 + section.data[reloc.offset + 2] = imm11 & 0xFF + section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 + section.data[reloc.offset] = imm10 & 0xff + section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2) + +@reloc('b_imm11_imm6') +def apply_b_imm11_imm6(reloc, sym, section, reloc_value): + assert sym.value % 2 == 0 + offset = sym.value - (align(reloc_value, 2) + 4) + assert offset in range(-1048576, 1048574, 2), str(offset) + imm32 = wrap_negative(offset >> 1, 32) + imm11 = imm32 & 0x7FF + imm6 = (imm32 >> 11) & 0x3F + s = (imm32 >> 24) & 0x1 + section.data[reloc.offset + 2] = imm11 & 0xFF + section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 + section.data[reloc.offset] |= imm6 + section.data[reloc.offset + 1] |= (s << 2) class Linker: - def set_symbol(self, sym): - self.dst.add_symbol(sym.name, sym.value, sym.section) - - def link(self, objs): + """ Merges the sections of several object files and + performs relocation """ + def link(self, objs, layout={}): # Create new object file to store output: self.dst = ObjectFile() - self.dst.get_section('code').address = 0x08000000 + + # Create sections with address: + for section_name, address in layout.items(): + self.dst.get_section(section_name).address = address # First copy all sections into output sections: for iobj in objs: @@ -42,19 +94,26 @@ # Merge sections: for in_s in iobj.sections.values(): out_s = self.dst.get_section(in_s.name) - offsets[in_s.name] = out_s.address + out_s.Size + # TODO: align section in other way: + while out_s.Size % 4 != 0: + out_s.add_data(bytes([0])) + + # Add new section: + offsets[in_s.name] = out_s.Size out_s.add_data(in_s.data) - # TODO: align section + # Merge symbols: for sym in iobj.symbols.values(): - self.set_symbol(sym) + out_s = self.dst.get_section(sym.section) + value = offsets[sym.section] + out_s.address + sym.value + self.dst.add_symbol(sym.name, value, sym.section) # Merge relocations: for reloc in iobj.relocations: - self.dst.add_relocation(reloc.sym, reloc.offset, reloc.typ, reloc.section) + offset = offsets[reloc.section] + reloc.offset + self.dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) - # Check that there are no more unresolved symbols: # Perform relocations: for reloc in self.dst.relocations: # Lookup symbol: @@ -64,48 +123,12 @@ # patch up: section = self.dst.get_section(reloc.section) - if reloc.typ == 'lit_add_8': - assert sym.value % 4 == 0 - offset = (sym.value - (align(reloc.offset + 2, 4))) - assert offset in range(0, 1024, 4) - rel8 = offset >> 2 - section.data[reloc.offset] = rel8 - elif reloc.typ == 'wrap_new11': - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-2048, 2046, 2) - imm11 = wrap_negative(offset >> 1, 11) - section.data[reloc.offset] = (imm11 & 0xff) - section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7 - elif reloc.typ == 'rel8': - assert sym.value % 2 == 0 - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-256, 254, 2), str(offset) + str(reloc) - imm8 = wrap_negative(offset >> 1, 8) - section.data[reloc.offset] = imm8 - elif reloc.typ == 'bl_imm11_imm10': - assert sym.value % 2 == 0 - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-16777216, 16777214, 2), str(offset) - imm32 = wrap_negative(offset >> 1, 32) - imm11 = imm32 & 0x7FF - imm10 = (imm32 >> 11) & 0x3FF - s = (imm32 >> 24) & 0x1 - section.data[reloc.offset + 2] = imm11 & 0xFF - section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 - section.data[reloc.offset] = imm10 & 0xff - section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2) - elif reloc.typ == 'b_imm11_imm6': - assert sym.value % 2 == 0 - offset = sym.value - (align(reloc.offset, 2) + 4) - assert offset in range(-1048576, 1048574, 2), str(offset) - imm32 = wrap_negative(offset >> 1, 32) - imm11 = imm32 & 0x7FF - imm6 = (imm32 >> 11) & 0x3F - s = (imm32 >> 24) & 0x1 - section.data[reloc.offset + 2] = imm11 & 0xFF - section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 - section.data[reloc.offset] |= imm6 - section.data[reloc.offset + 1] |= (s << 2) + # Determine location in memory of reloc patchup position: + reloc_value = section.address + reloc.offset + + if reloc.typ in reloc_map: + f = reloc_map[reloc.typ] + f(reloc, sym, section, reloc_value) else: raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ))
--- a/python/ppci/objectfile.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/objectfile.py Wed Feb 19 22:32:15 2014 +0100 @@ -4,6 +4,8 @@ is code, symbol table and relocation information. """ +from . import CompilerError + class Symbol: def __init__(self, name, value, section): self.name = name @@ -43,17 +45,26 @@ class ObjectFile: + """ Container for sections with compiled code or data. + Also contains symbols and relocation entries """ def __init__(self): self.symbols = {} self.sections = {} self.relocations = [] + def find_symbol(self, name): + return self.symbols[name] + def add_symbol(self, name, value, section): + if name in self.symbols: + raise CompilerError('{} already defined'.format(name)) + assert section in self.sections sym = Symbol(name, value, section) self.symbols[name] = sym return sym def add_relocation(self, sym_name, offset, typ, section): + assert section in self.sections reloc = Relocation(sym_name, offset, typ, section) self.relocations.append(reloc) return reloc
--- a/python/ppci/transform.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/ppci/transform.py Wed Feb 19 22:32:15 2014 +0100 @@ -157,7 +157,7 @@ def glue_blocks(self, block1, block2, f): """ Glue two blocks together into the first block """ - self.logger.debug('Glueing {} and {}'.format(block1, block2)) + self.logger.debug('Merging {} and {}'.format(block1.name, block2.name)) # Remove the last jump: block1.removeInstruction(block1.LastInstruction)
--- a/python/target/arm.brg Mon Feb 17 20:41:30 2014 +0100 +++ b/python/target/arm.brg Wed Feb 19 22:32:15 2014 +0100 @@ -4,6 +4,7 @@ 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 ppci import ir %%
--- a/python/target/arminstructions.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/target/arminstructions.py Wed Feb 19 22:32:15 2014 +0100 @@ -10,6 +10,55 @@ def u32(x): return struct.pack('<I', x) + +def val2bit(v, bits): + b = [] + for i in range(bits): + b.append(bool((1<<i) & v)) + #b.reverse() + return b + + +def bit_range(b, e): + getter = lambda s: s[b:e] + def setter(s, v): + s[b:e] = v + return property(getter, setter) + +class ArmToken: + def __init__(self): + self.bit_value = 0 + + def set_bit(self, i, value): + value = bool(value) + assert i in range(0, 16) + mask = 1 << i + if value: + self.bit_value |= mask + else: + self.bit_value &= (~mask) + + def __getitem__(self, key): + return False + + def __setitem__(self, key, value): + if type(key) is int: + self.set_bit(key, value) + elif type(key) is slice: + assert key.step is None + bits = key.stop - key.start + value_bits = val2bit(value, bits) + for i in range(key.start, key.stop): + self.set_bit(i, value_bits[i - key.start]) + else: + raise KeyError() + + rd = bit_range(0, 3) + + def encode(self): + return u16(self.bit_value) + + # Operands: class ArmRegister(Register): @@ -440,11 +489,16 @@ return cls(im.dst[0], im.src[0], im.src[1]) def encode(self): - rd = self.rd.num + at = ArmToken() + at.rd = self.rd.num rn = self.rn.num rm = self.rm.num - h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd - return u16(h) + 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) @@ -476,11 +530,15 @@ return cls(im.dst[0], im.src[0]) def encode(self): - Rd = self.rd.num & 0x7 + at = ArmToken() + at.rd = self.rd.num & 0x7 D = (self.rd.num >> 3) & 0x1 Rm = self.rm.num opcode = 0b01000110 - return u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) + at[8:16] = opcode + at[3:7] = Rm + at[7] = D + return at.encode() # u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) def __repr__(self): return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) @@ -501,11 +559,14 @@ return cls(im.src[0], im.dst[0]) def encode(self): + at = ArmToken() rn = self.rn.num - rdm = self.rdm.num + at.rd = self.rdm.num opcode = 0b0100001101 - h = (opcode << 6) | (rn << 3) | rdm - return u16(h) + #h = (opcode << 6) | (rn << 3) | rdm + at[6:16] = opcode + at[3:6] = rn + return at.encode() def __repr__(self): return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) @@ -526,10 +587,12 @@ return cls(im.src[0], im.src[1]) def encode(self): - rdn = self.rdn.num + at = ArmToken() + at.rd = self.rdn.num rm = self.rm.num - h = (self.opcode << 6) | (rm << 3) | rdn - return u16(h) + at[3:6] = rm + at[6:16] = self.opcode + return at.encode() def __repr__(self): return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) @@ -636,7 +699,7 @@ return [(self.target.name, 'bl_imm11_imm10')] -class cond_base_ins_short(jumpBase_ins): +class cond_base_ins(jumpBase_ins): def encode(self): imm8 = wrap_negative(self.offset >> 1, 8) h = (0b1101 << 12) | (self.cond << 8) | imm8 @@ -646,7 +709,7 @@ return [(self.target.name, 'rel8')] -class cond_base_ins(jumpBase_ins): +class cond_base_ins_long(jumpBase_ins): """ Encoding T3 """ def encode(self): j1 = 1 # TODO: what do these mean?
--- a/python/target/arminstructionselector.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/target/arminstructionselector.py Wed Feb 19 22:32:15 2014 +0100 @@ -1,5 +1,5 @@ import os -from ppci import ir +from ppci import ir, same_dir from ppci.irmach import AbstractInstruction as makeIns from ppci.ir2tree import makeTree import pyburg @@ -12,7 +12,7 @@ from .basetarget import Imm8, Imm7, Imm3 # Import BURG spec for arm: -spec_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'arm.brg') +spec_file = same_dir(__file__, 'arm.brg') arm_matcher = pyburg.load_as_module(spec_file) @@ -75,16 +75,16 @@ self.emit(Nop(), src=[x]) elif isinstance(s, ir.Jump): tgt = self.targets[s.target] - self.emit(B(LabelRef(s.target.name)), jumps=[tgt]) + self.emit(B(LabelRef(ir.label_name(s.target))), jumps=[tgt]) elif isinstance(s, ir.CJump): a = self.munchExpr(s.a) b = self.munchExpr(s.b) self.emit(Cmp, src=[a, b]) ntgt = self.targets[s.lab_no] ytgt = self.targets[s.lab_yes] - jmp_ins = makeIns(B(LabelRef(s.lab_no.name)), jumps=[ntgt]) + jmp_ins = makeIns(B(LabelRef(ir.label_name(s.lab_no))), jumps=[ntgt]) opnames = {'<': Blt, '>':Bgt, '==':Beq, '!=':Bne} - op = opnames[s.cond](LabelRef(s.lab_yes.name)) + op = opnames[s.cond](LabelRef(ir.label_name(s.lab_yes))) self.emit(op, jumps=[ytgt, jmp_ins]) # Explicitely add fallthrough self.emit2(jmp_ins) else:
--- a/python/target/instructionselector.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/target/instructionselector.py Wed Feb 19 22:32:15 2014 +0100 @@ -21,6 +21,7 @@ def newTmp(self): return self.temps.__next__() + def munchFunction(self, f, frame): # Entry point for instruction selection assert isinstance(f, ir.Function) @@ -29,7 +30,7 @@ self.frame = frame # First define labels: for bb in f.Blocks: - itgt = makeIns(target.Label(bb.name)) + itgt = makeIns(target.Label(ir.label_name(bb))) self.targets[bb] = itgt # Generate code for all blocks: for bb in f.Blocks:
--- a/python/zcc.py Mon Feb 17 20:41:30 2014 +0100 +++ b/python/zcc.py Wed Feb 19 22:32:15 2014 +0100 @@ -97,7 +97,9 @@ for i in inputs: task = self.load_dict(i) objs.append(task.output) - self.runner.add_task(Link(objs, None)) + layout = value['layout'] + output = self.relpath(value['output']) + self.runner.add_task(Link(objs, layout, output)) def handle_apps(self, value): for a in value:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testbintools.py Wed Feb 19 22:32:15 2014 +0100 @@ -0,0 +1,86 @@ +import unittest +import sys +from target.arminstructions import ArmToken +from ppci.linker import Linker +from ppci.objectfile import ObjectFile +from ppci import CompilerError + + +class TokenTestCase(unittest.TestCase): + def testSetBits(self): + at = ArmToken() + at[2:4] = 0b11 + self.assertEqual(0xc, at.bit_value) + + def testSetBits(self): + at = ArmToken() + at[4:8] = 0b1100 + self.assertEqual(0xc0, at.bit_value) + + +class LinkerTestCase(unittest.TestCase): + def testUndefinedReference(self): + l = Linker() + o1 = ObjectFile() + o1.get_section('.text') + o1.add_relocation('undefined_sym', 0, 'rel8', '.text') + o2 = ObjectFile() + with self.assertRaises(CompilerError): + o3 = l.link([o1, o2]) + + def testDuplicateSymbol(self): + l = Linker() + o1 = ObjectFile() + o1.get_section('.text') + o1.add_symbol('a', 0, '.text') + o2 = ObjectFile() + o2.get_section('.text') + o2.add_symbol('a', 0, '.text') + with self.assertRaises(CompilerError): + o3 = l.link([o1, o2]) + + def testRel8Relocation(self): + l = Linker() + o1 = ObjectFile() + o1.get_section('.text').add_data(bytes([0]*100)) + o1.add_relocation('a', 0, 'rel8', '.text') + o2 = ObjectFile() + o2.get_section('.text').add_data(bytes([0]*100)) + o2.add_symbol('a', 24, '.text') + o3 = l.link([o1, o2]) + + def testSymbolValues(self): + l = Linker() + o1 = ObjectFile() + o1.get_section('.text').add_data(bytes([0]*108)) + o1.add_symbol('b', 24, '.text') + o2 = ObjectFile() + o2.get_section('.text').add_data(bytes([0]*100)) + o2.add_symbol('a', 2, '.text') + o3 = l.link([o1, o2]) + self.assertEqual(110, o3.find_symbol('a').value) + self.assertEqual(24, o3.find_symbol('b').value) + self.assertEqual(208, o3.get_section('.text').Size) + + def testMemoryLayout(self): + l = Linker() + memory_layout = {'.text': 0x08000000, '.data':0x20000000} + o1 = ObjectFile() + o1.get_section('.text').add_data(bytes([0]*108)) + o1.add_symbol('b', 24, '.text') + o2 = ObjectFile() + o2.get_section('.text').add_data(bytes([0]*100)) + o2.get_section('.data').add_data(bytes([0]*100)) + o2.add_symbol('a', 2, '.data') + o2.add_symbol('c', 2, '.text') + o3 = l.link([o1, o2], layout=memory_layout) + self.assertEqual(0x20000000+2, o3.find_symbol('a').value) + self.assertEqual(0x08000000+24, o3.find_symbol('b').value) + self.assertEqual(0x08000000+110, o3.find_symbol('c').value) + self.assertEqual(208, o3.get_section('.text').Size) + self.assertEqual(100, o3.get_section('.data').Size) + + +if __name__ == '__main__': + unittest.main() + sys.exit()
--- a/test/testzcc.py Mon Feb 17 20:41:30 2014 +0100 +++ b/test/testzcc.py Wed Feb 19 22:32:15 2014 +0100 @@ -34,6 +34,7 @@ def callZcc(self, arg_list): parser = zcc.make_parser() + arg_list = ['--log', 'warn'] + arg_list args = parser.parse_args(arg_list) self.assertEqual(0, zcc.main(args)) @@ -53,6 +54,18 @@ recipe = os.path.join(testdir, '..', 'kernel', 'recipe.yaml') self.buildRecipe(recipe) + def testKernelBuildsEqualTwice(self): + """ Build kernel two times and check the output is equal """ + recipe = os.path.join(testdir, '..', 'kernel', 'recipe.yaml') + bin_filename = os.path.join(testdir, '..', 'kernel', 'kernel.bin') + self.buildRecipe(recipe) + with open(bin_filename, 'rb') as f: + a = f.read() + self.buildRecipe(recipe) + with open(bin_filename, 'rb') as f: + b = f.read() + self.assertSequenceEqual(a, b) + def testUser(self): """ Build userspace using zcc: """ recipe = os.path.join(testdir, '..', 'user', 'recipe.yaml')
--- a/user/recipe.yaml Mon Feb 17 20:41:30 2014 +0100 +++ b/user/recipe.yaml Wed Feb 19 22:32:15 2014 +0100 @@ -7,19 +7,8 @@ includes: [] machine: arm output: kernel.elf2 + layout: + code: 0x0 + data: 0x20000000 + output: 'hello.bin' - - link: - inputs: - - compile: - sources: [lib.c3, ipc.c3, screen.c3] - includes: [] - machine: arm - output: kernel.elf2 - - - link: - inputs: - - compile: - sources: [lib.c3, ipc.c3, console.c3] - includes: [] - machine: arm - output: kernel.elf2