# HG changeset patch # User Windel Bouwman # Date 1398526916 -7200 # Node ID 6df89163e114820d97c36344f9e7e7b93bdc0971 # Parent 67a584582aeea06650bba22f3f2fc440fca84520 Fix section and ldr pseudo instruction diff -r 67a584582aee -r 6df89163e114 doc/utils.rst --- a/doc/utils.rst Fri Apr 18 13:08:45 2014 +0200 +++ b/doc/utils.rst Sat Apr 26 17:41:56 2014 +0200 @@ -29,3 +29,43 @@ .. automodule:: pyburg + +Machine descriptions +-------------------- + +There are some attempts made already to describe machines in a Domain +Specific Language (DSL). Examples of these are: +- Tablegen (llvm) +- cgen (gnu) +- LISA (Aachen) +- nML (Berlin) +- SLED (Specifying representations of machine instructions (norman ramsey and Mary F. Fernandez)) + + +The goal of a machine description file is to describe a file and generate +tools like assemblers, disassemblers, linkers, debuggers and simulators. + +Advantage of using this approach is that porting these tools is a semi automated +process. Rewriting all of these tools from scratch is tedious and errorprone. + +Concepts to use in this language: +- Single stream of instructions +- State stored in memory +- Pipelining +- Instruction semantics + +Each instruction has the following properties: +- Bit representation +- Assembly language representation +- Semantic action + +Optionally a description in terms of compiler code generation can be attached +to this. But perhaps this clutters the description too much and we need to put +it elsewhere. + + +The description language can help to expand these descriptions by expanding +the permutations. + + + diff -r 67a584582aee -r 6df89163e114 kernel/arch/qemu_vexpress/archmem.c3 --- a/kernel/arch/qemu_vexpress/archmem.c3 Fri Apr 18 13:08:45 2014 +0200 +++ b/kernel/arch/qemu_vexpress/archmem.c3 Sat Apr 26 17:41:56 2014 +0200 @@ -1,19 +1,4 @@ module archmem; import io; -function void init() -{ - // putc(65) - io.print2("PFR0 = ", pfr0()); - io.print2("PFR1 = ", pfr1()); - io.print2("MMFR0 = ", mmfr0()); - // This below is not compatible with all qemu versions: - // io.print2("MPUIR = ", arch.mpuir()); -} - -function int pfr0(); -function int pfr1(); -function int mmfr0(); -// function int mpuir(); - diff -r 67a584582aee -r 6df89163e114 kernel/arch/qemu_vexpress/startup_a9.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/arch/qemu_vexpress/startup_a9.asm Sat Apr 26 17:41:56 2014 +0200 @@ -0,0 +1,73 @@ + +section code + +interrupt_vector_table: +ivt_reset: B start ; 0x0 reset +ivt_undef: B undef_handler ; 0x4 undefined instruction +ivt_svc: B undef_handler ; 0x08 Supervisor call +ivt_prefetch: B undef_handler ; 0x0C prefetch abort +ivt_data: B undef_handler ; 0x10 data abort +ivt_hyptrap: B undef_handler ; 0x14 not used +ivt_irq: B undef_handler ; 0x18 IRQ +ivt_fiq: B undef_handler ; 0x18 FIQ + + +start: + +; Setup TTBR1 (translation table base register) + +ldr r0, =kernel_table0 ; pseudo instruction which loads the value of the symbol +; -KERNEL_BASE +mcr p15, 0, r0, c2, c0, 1 ; TTBR1 +mcr p15, 0, r0, c2, c0, 0 ; TTBR0 + +; Prepare the TTBCR (translation table base control register) +mov r0, 0x1 ; TBD: why set this to 1? +mcr p15, 0, r0, c2, c0, 2 + +; Enable the VMSA (Virtual memory system architecture): +mrc p15, 0, r0, c1, c0, 0 +; TODO: +; orr r0, r0, 0x1 +mcr p15, 0, r0, c1, c0, 0 + +; Setup stack: +mov sp, 0x30000 +BL kernel_start ; Branch to main (this is actually in the interrupt vector) +local_loop: +B local_loop + + +; Interrupt handlers: + +undef_handler: +B undef_handler + + +; Assembly language helpers: +; Called to identify the proc: +arch_pfr0: +mrc p15, 0, r0, c0, c1, 0 +mov pc, lr + +arch_pfr1: +mrc p15, 0, r0, c0, c1, 1 +mov pc, lr + +arch_mmfr0: +mrc p15, 0, r0, c0, c1, 4 +mov pc, lr + + +arch_mpuir: +mrc p15, 0, r0, c0, c0, 4 +mov pc, lr + + +; Memory map tables: + +section mem_tables + +kernel_table0: + dcd 0x000402 + diff -r 67a584582aee -r 6df89163e114 kernel/arch/qemu_vexpress/vexpressA9.mmap --- a/kernel/arch/qemu_vexpress/vexpressA9.mmap Fri Apr 18 13:08:45 2014 +0200 +++ b/kernel/arch/qemu_vexpress/vexpressA9.mmap Sat Apr 26 17:41:56 2014 +0200 @@ -1,6 +1,7 @@ { "code": "0x10000", + "mem_tables": "0x11000", "data": "0x20000" } diff -r 67a584582aee -r 6df89163e114 kernel/arch/vexpressA9.c3 --- a/kernel/arch/vexpressA9.c3 Fri Apr 18 13:08:45 2014 +0200 +++ b/kernel/arch/vexpressA9.c3 Sat Apr 26 17:41:56 2014 +0200 @@ -5,6 +5,12 @@ function void init() { // putc(65) + io.print2("PFR0 = ", pfr0()); + io.print2("PFR1 = ", pfr1()); + io.print2("MMFR0 = ", mmfr0()); + + // This below is not compatible with all qemu versions: + // io.print2("MPUIR = ", arch.mpuir()); } function void putc(int c) @@ -16,5 +22,11 @@ function void halt() { + while(true) {} } +function int pfr0(); +function int pfr1(); +function int mmfr0(); +// function int mpuir(); + diff -r 67a584582aee -r 6df89163e114 kernel/build.xml --- a/kernel/build.xml Fri Apr 18 13:08:45 2014 +0200 +++ b/kernel/build.xml Sat Apr 26 17:41:56 2014 +0200 @@ -5,7 +5,7 @@ - + diff -r 67a584582aee -r 6df89163e114 kernel/make.sh --- a/kernel/make.sh Fri Apr 18 13:08:45 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -#!/bin/bash - -# ../python/zcc.py recipe thumb.yaml - -../python/zcc.py --report log.txt recipe arm.yaml diff -r 67a584582aee -r 6df89163e114 kernel/src/kernel.c3 --- a/kernel/src/kernel.c3 Fri Apr 18 13:08:45 2014 +0200 +++ b/kernel/src/kernel.c3 Sat Apr 26 17:41:56 2014 +0200 @@ -6,12 +6,13 @@ import arch; import io; + // Main entry point of the kernel: function void start() { + io.println("Welcome to lcfos!"); arch.init(); - io.println("Welcome to lcfos!"); // process.init(); memory.init(); @@ -19,7 +20,8 @@ //Process proc = new process:Process(); //scheduler:queue(proc); - while(true) {} + io.println("Kernel finished"); + arch.halt(); } // Called in total stress: diff -r 67a584582aee -r 6df89163e114 kernel/src/memory.c3 --- a/kernel/src/memory.c3 Fri Apr 18 13:08:45 2014 +0200 +++ b/kernel/src/memory.c3 Sat Apr 26 17:41:56 2014 +0200 @@ -1,12 +1,14 @@ module memory; import arch; +import io; var int ptr; function void init() { - arch.init(); + ptr = 0; + io.print2("ptr = ", ptr); // TODO } diff -r 67a584582aee -r 6df89163e114 kernel/startup_a9.asm --- a/kernel/startup_a9.asm Fri Apr 18 13:08:45 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ - - -interrupt_vector_table: -ivt_reset: B start ; 0x0 reset -ivt_undef: B undef_handler ; 0x4 undefined instruction -ivt_svc: B undef_handler ; 0x08 Supervisor call -ivt_prefetch: B undef_handler ; 0x0C prefetch abort -ivt_data: B undef_handler ; 0x10 data abort -ivt_hyptrap: B undef_handler ; 0x14 not used -ivt_irq: B undef_handler ; 0x18 IRQ -ivt_fiq: B undef_handler ; 0x18 FIQ - - -start: - -; Setup TTBR1 (translation table base register) - -; mov r0, =kernel_table0-KERNEL_BASE -mcr p15, 0, r0, c2, c0, 1 ; TTBR1 -mcr p15, 0, r0, c2, c0, 0 ; TTBR0 - -; Prepare the TTBCR (translation table base control register) -mov r0, 0x1 ; TBD: why set this to 1? -mcr p15, 0, r0, c2, c0, 2 - -; Enable the VMSA (Virtual memory system architecture): -mrc p15, 0, r0, c1, c0, 0 -; TODO: -; orr r0, r0, 0x1 -mcr p15, 0, r0, c1, c0, 0 - -; Setup stack: -mov sp, 0x30000 -BL kernel_start ; Branch to main (this is actually in the interrupt vector) -local_loop: -B local_loop - - -; Interrupt handlers: - -undef_handler: -B undef_handler - -; Called to identify the proc: -archmem_pfr0: -mrc p15, 0, r0, c0, c1, 0 -mov pc, lr - -archmem_pfr1: -mrc p15, 0, r0, c0, c1, 1 -mov pc, lr - -archmem_mmfr0: -mrc p15, 0, r0, c0, c1, 4 -mov pc, lr - - -archmem_mpuir: -mrc p15, 0, r0, c0, c0, 4 -mov pc, lr diff -r 67a584582aee -r 6df89163e114 python/asm.py --- a/python/asm.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/asm.py Sat Apr 26 17:41:56 2014 +0200 @@ -1,7 +1,8 @@ #!/usr/bin/env python3 import argparse -from ppci.assembler import Assembler +from ppci.target.target_list import targets +from ppci.buildfunctions import assemble if __name__ == '__main__': # When run as main file, try to grab command line arguments: @@ -9,5 +10,4 @@ parser.add_argument('sourcefile', type=argparse.FileType('r'), help='the source file to assemble') args = parser.parse_args() - a = Assembler() - obj = a.assemble(args.sourcefile.read()) + obj = assemble(args.sourcefile, targets['arm']) diff -r 67a584582aee -r 6df89163e114 python/ppci/assembler.py --- a/python/ppci/assembler.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/assembler.py Sat Apr 26 17:41:56 2014 +0200 @@ -89,7 +89,8 @@ if prod == 'instruction': def f_wrap(*args): i = f(args) - self.emit(i) + if i: + self.emit(i) else: def f_wrap(*rhs): return f(rhs) @@ -112,7 +113,6 @@ g.add_production('asmline2', ['label']) g.add_production('asmline2', []) g.add_production('label', ['ID', ':'], self.p_label) - #g.add_production('label', []) # Add instruction rules for the target in question: for prod, rhs, f in instruction_rules: @@ -134,11 +134,14 @@ self.p.parse(lexer) -class Assembler: +class BaseAssembler: + """ Assembler base class, inherited by assemblers specific for a target """ def __init__(self, target): self.target = target assert isinstance(target, Target) - self.parser = Parser(target.asm_keywords, target.assembler_rules, self.emit) + + def make_parser(self): + self.parser = Parser(self.target.asm_keywords, self.target.assembler_rules, self.emit) def emit(self, *args): self.stream.emit(*args) @@ -151,7 +154,9 @@ def assemble(self, asmsrc, stream): """ Assemble this source snippet """ - if hasattr(asmsrc, 'read'): + if type(asmsrc) is str: + pass + elif hasattr(asmsrc, 'read'): asmsrc2 = asmsrc.read() asmsrc.close() asmsrc = asmsrc2 @@ -160,5 +165,6 @@ self.stream = stream for line in asmsrc.split('\n'): self.parse_line(line) - self.stream = None + def flush(self): + pass diff -r 67a584582aee -r 6df89163e114 python/ppci/buildfunctions.py --- a/python/ppci/buildfunctions.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/buildfunctions.py Sat Apr 26 17:41:56 2014 +0200 @@ -13,12 +13,11 @@ from .transform import CleanPass, RemoveAddZero from .linker import Linker from .target.target_list import targets -from .outstream import BinaryOutputStream, MasterOutputStream -from .outstream import LoggerOutputStream -from .assembler import Assembler +from .outstream import BinaryAndLoggingStream from .objectfile import ObjectFile, load_object from . import DiagnosticsManager, CompilerError + def fix_target(tg): """ Try to return an instance of the Target class """ if isinstance(tg, Target): @@ -28,6 +27,7 @@ return targets[tg] raise TaskError('Invalid target {}'.format(tg)) + def fix_file(f): """ Determine if argument is a file like object or make it so! """ if hasattr(f, 'read'): @@ -38,6 +38,7 @@ else: raise TaskError('cannot use {} as input'.format(f)) + def fix_object(o): if isinstance(o, ObjectFile): return o @@ -49,22 +50,23 @@ def assemble(source, target): + """ Invoke the assembler on the given source, returns an object containing + the output. """ logger = logging.getLogger('assemble') target = fix_target(target) source = fix_file(source) output = ObjectFile() - assembler = Assembler(target) + assembler = target.assembler logger.debug('Assembling into code section') - o2 = BinaryOutputStream(output) - o1 = LoggerOutputStream() - ostream = MasterOutputStream([o1, o2]) + ostream = BinaryAndLoggingStream(output) ostream.select_section('code') assembler.assemble(source, ostream) + assembler.flush() return output def c3compile(sources, includes, target): - """ Compile a set of sources """ + """ Compile a set of sources for the given target """ logger = logging.getLogger('c3c') logger.debug('C3 compilation started') target = fix_target(target) @@ -75,9 +77,7 @@ c3b = Builder(diag, target) cg = CodeGenerator(target) - o2 = BinaryOutputStream(output) - o1 = LoggerOutputStream() - o = MasterOutputStream([o1, o2]) + output_stream = BinaryAndLoggingStream(output) for ircode in c3b.build(sources, includes): if not ircode: @@ -100,7 +100,7 @@ d = {'ircode':ircode} logger.debug('Starting code generation for {}'.format(ircode), extra=d) - cg.generate(ircode, o) + cg.generate(ircode, output_stream) if not c3b.ok: diag.printErrors() @@ -109,7 +109,12 @@ def link(objects, layout): + """ Links the iterable of objects into one using the given layout """ objects = list(map(fix_object, objects)) linker = Linker() output_obj = linker.link(objects, layout) return output_obj + + +def objcopy(obj): + return diff -r 67a584582aee -r 6df89163e114 python/ppci/buildtasks.py --- a/python/ppci/buildtasks.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/buildtasks.py Sat Apr 26 17:41:56 2014 +0200 @@ -53,6 +53,8 @@ raise TaskError('Error during assembly:' + str(e)) except CompilerError as e: raise TaskError('Error during assembly:' + str(e)) + except OSError as e: + raise TaskError('Error:' + str(e)) with open(output_filename, 'w') as f: output.save(f) self.logger.debug('Assembling finished') diff -r 67a584582aee -r 6df89163e114 python/ppci/linker.py --- a/python/ppci/linker.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/linker.py Sat Apr 26 17:41:56 2014 +0200 @@ -99,7 +99,7 @@ if offset < 0: offset = -offset U = 0 - assert offset < 4096 + assert offset < 4096, str(sym) + str(section) + str(reloc) section.data[reloc.offset+2] |= (U << 7) section.data[reloc.offset+1] |= (offset >> 8) & 0xF section.data[reloc.offset+0] = offset & 0xFF @@ -130,16 +130,13 @@ section.data[reloc.offset+0] = offset & 0xFF -class Layout: - pass - class Linker: """ Merges the sections of several object files and performs relocation """ def __init__(self): self.logger = logging.getLogger('Linker') - def link(self, objs, layout={}): + def link(self, objs, layout): assert type(objs) is list # Create new object file to store output: self.dst = ObjectFile() @@ -175,6 +172,9 @@ offset = offsets[reloc.section] + reloc.offset self.dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) + # Apply layout rules: + # TODO + # Perform relocations: for reloc in self.dst.relocations: # Lookup symbol: diff -r 67a584582aee -r 6df89163e114 python/ppci/outstream.py --- a/python/ppci/outstream.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/outstream.py Sat Apr 26 17:41:56 2014 +0200 @@ -23,6 +23,7 @@ def __init__(self, obj_file): super().__init__() self.obj_file = obj_file + self.literal_pool = [] def emit(self, item): """ Encode instruction and add symbol and relocation information """ @@ -83,3 +84,11 @@ def select_section(self, sname): for output_stream in self.substreams: output_stream.select_section(sname) + + +def BinaryAndLoggingStream(output): + """ Create a stream object that both logs and writes to an object file """ + o2 = BinaryOutputStream(output) + o1 = LoggerOutputStream() + ostream = MasterOutputStream([o1, o2]) + return ostream diff -r 67a584582aee -r 6df89163e114 python/ppci/target/arm/__init__.py --- a/python/ppci/target/arm/__init__.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/target/arm/__init__.py Sat Apr 26 17:41:56 2014 +0200 @@ -12,6 +12,36 @@ from .instructions import LdrPseudo from .selector import ArmInstructionSelector from .frame import ArmFrame +from ...assembler import BaseAssembler + + +class ArmAssembler(BaseAssembler): + def __init__(self, target): + super().__init__(target) + self.target.add_keyword('section') + self.target.add_instruction(['section', 'ID'], + lambda rhs: self.select_section(rhs[1].val)) + self.make_parser() + self.lit_pool = [] + self.lit_counter = 0 + + def select_section(self, name): + self.flush() + self.stream.select_section(name) + + def flush(self): + while self.lit_pool: + i = self.lit_pool.pop(0) + self.emit(i) + + def add_literal(self, v): + """ For use in the pseudo instruction LDR r0, =SOMESYM """ + # Invent some label for the literal and store it. + self.lit_counter += 1 + label_name = "_lit_{}".format(self.lit_counter) + self.lit_pool.append(Label(label_name)) + self.lit_pool.append(Dcd(v)) + return label_name class ArmTarget(Target): def __init__(self): @@ -19,6 +49,7 @@ self.make_parser() self.ins_sel = ArmInstructionSelector() self.FrameClass = ArmFrame + self.assembler = ArmAssembler(self) self.add_lowering(Ldr3, lambda im: Ldr3(im.dst[0], im.others[0])) self.add_lowering(Str1, lambda im: Str1(im.src[1], im.src[0], im.others[0])) @@ -38,6 +69,7 @@ outs.emit(Label(lname)) outs.emit(Dcd(0)) + def make_parser(self): # Assembly grammar: self.add_keyword('r0') @@ -157,7 +189,7 @@ # This is a pseudo instruction: self.add_instruction(['ldr', 'reg', ',', '=', 'ID'], - lambda rhs: LdrPseudo(rhs[1], rhs[4].val)) + lambda rhs: LdrPseudo(rhs[1], rhs[4].val, self.assembler.add_literal)) self.add_keyword('str') self.add_instruction(['str', 'reg', ',', '[', 'reg', ',', 'imm8', ']'], diff -r 67a584582aee -r 6df89163e114 python/ppci/target/arm/armv7.lidl --- a/python/ppci/target/arm/armv7.lidl Fri Apr 18 13:08:45 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ - -# This file specifies the encoding of the arm instruction set. - -fields { - word16 16 { - opcode 15:12 - top2 15:14 - top6 15:10 - data_opcode 9..6 - opB 11:9 - Rm 8:6 - Rn 5:3 - Rt 2:0 - } -} - -patterns { - add = 0 - sub, mul = 1..2 - [r1, r2, r3, r4, r5] is todo = 1..5 - [STR, STRH, STRB, LDRSB, LDR, LDRH, LDRB, LDRSH] is opcode = 0b0101 & opB = {0 to 7} - - EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL = 0..14 - [AND, EOR, LSL, LSR, ASR, ADC, SBC, ROR, TST, RSB, CMP, CMN, ORR, MUL, BIC, MVN] is 0..15 - - memop is STR | STRH | STRB | LDRSB | LDR | LDR | LDRH | LDRB | LDRSH -} - - -constructors -{ - alu rs1, reg_or_imm, rd - memop Rt, [Rn, Rm] is memop & Rt & Rn & Rm -} - - diff -r 67a584582aee -r 6df89163e114 python/ppci/target/arm/instructions.py --- a/python/ppci/target/arm/instructions.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/target/arm/instructions.py Sat Apr 26 17:41:56 2014 +0200 @@ -406,9 +406,10 @@ raise Exception() -def LdrPseudo(rt, lab): +def LdrPseudo(rt, lab, add_lit): """ Ldr rt, =lab ==> ldr rt, [pc, offset in litpool] ... dcd lab """ - return Ldr(rt, R0) + lit_lbl = add_lit(LabelAddress(lab)) + return Ldr(rt, lit_lbl) def Str(*args): if len(args) == 3 and isinstance(args[1], ArmRegister): diff -r 67a584582aee -r 6df89163e114 python/ppci/target/basetarget.py --- a/python/ppci/target/basetarget.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/target/basetarget.py Sat Apr 26 17:41:56 2014 +0200 @@ -16,6 +16,9 @@ def symbols(self): return [] + def literals(self, add_literal): + pass + class Nop(Instruction): """ Instruction that does nothing and has zero size """ @@ -138,6 +141,7 @@ if isinstance(im.assem, Instruction): outs.emit(im.assem) else: + # TODO assert isinstance(Abs ins = self.lower_functions[im.assem](im) outs.emit(ins) diff -r 67a584582aee -r 6df89163e114 python/ppci/target/msp430/msp430.py --- a/python/ppci/target/msp430/msp430.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/target/msp430/msp430.py Sat Apr 26 17:41:56 2014 +0200 @@ -4,9 +4,17 @@ from ppci import CompilerError from .registers import r10, r11, r12, r13, r14, r15 from .instructions import Reti, Mov, Add +from ...assembler import BaseAssembler + # Create the target class (singleton): +class Msp430Assembler(BaseAssembler): + def __init__(self, target): + super().__init__(target) + self.make_parser() + + class Msp430Target(Target): def __init__(self): super().__init__('msp430') @@ -39,6 +47,7 @@ self.add_keyword('reti') self.add_instruction(['reti'], lambda rhs: Reti()) + self.assembler = Msp430Assembler(self) msp430target = Msp430Target() diff -r 67a584582aee -r 6df89163e114 python/ppci/target/thumb/armtarget.py --- a/python/ppci/target/thumb/armtarget.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/ppci/target/thumb/armtarget.py Sat Apr 26 17:41:56 2014 +0200 @@ -9,6 +9,7 @@ from .arminstructionselector import ArmInstructionSelector from ..arm.registers import R0, R1, R2, R3, R4, R5, R6, R7, SP, LR, PC from ..arm.registers import register_range +from ...assembler import BaseAssembler """ ARM target description. """ @@ -17,9 +18,11 @@ # 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 ThumbAssembler(BaseAssembler): + def __init__(self, target): + super().__init__(target) + self.make_parser() class ThumbTarget(Target): @@ -45,6 +48,8 @@ self.add_lowering(Lsl, lambda im: Lsl(im.src[0], im.src[1])) self.add_lowering(Cmp, lambda im: Cmp(im.src[0], im.src[1])) + self.assembler = ThumbAssembler(self) + def add_rules(self): # Add instructions: diff -r 67a584582aee -r 6df89163e114 python/zcc.py --- a/python/zcc.py Fri Apr 18 13:08:45 2014 +0200 +++ b/python/zcc.py Sat Apr 26 17:41:56 2014 +0200 @@ -1,16 +1,13 @@ #!/usr/bin/env python import sys -import os import argparse import logging from ppci.tasks import TaskRunner -import ppci.buildtasks from ppci.report import RstFormatter -from ppci.objectfile import ObjectFile -from ppci.target.target_list import targets, targetnames from ppci.recipe import RecipeLoader +import ppci.buildtasks # Include not used, but it registers build tasks. import ppci diff -r 67a584582aee -r 6df89163e114 readme.rst --- a/readme.rst Fri Apr 18 13:08:45 2014 +0200 +++ b/readme.rst Sat Apr 26 17:41:56 2014 +0200 @@ -68,3 +68,8 @@ http://www.ohloh.net/p/lcfos +Live demo is at redhat openshift: + +http://lcfos-windel.rhcloud.com/ + + diff -r 67a584582aee -r 6df89163e114 test/runtests.sh --- a/test/runtests.sh Fri Apr 18 13:08:45 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -export PYTHONPATH=$PYTHONPATH:`pwd`/../python:`pwd`/../python/ide - -if [ "$1" == "loop" ] -then - DIR=.. - while :; do - python -m unittest - #python -m unittest -v - echo "Awaiting changes in $DIR" - inotifywait -r -e modify $DIR - done -else - set -e - python -m unittest -fi - - diff -r 67a584582aee -r 6df89163e114 test/testarmasm.py --- a/test/testarmasm.py Fri Apr 18 13:08:45 2014 +0200 +++ b/test/testarmasm.py Sat Apr 26 17:41:56 2014 +0200 @@ -1,13 +1,10 @@ import unittest from ppci.outstream import BinaryOutputStream from ppci.objectfile import ObjectFile -from asm import Assembler from testasm import AsmTestCaseBase from ppci.target.target_list import arm_target -a = Assembler(arm_target) - class ArmAssemblerTestCase(AsmTestCaseBase): """ ARM-mode (not thumb-mode) instruction assembly test case """ def setUp(self): @@ -15,7 +12,7 @@ self.obj = ObjectFile() self.ostream = BinaryOutputStream(self.obj) self.ostream.select_section('.text') - self.a = a + self.assembler = arm_target.assembler def testMovImm(self): self.feed('mov r4, 100') @@ -69,17 +66,17 @@ self.check('3092a0e1 3846a0e1') def testBranches(self): - self.feed('b sjakie') - self.feed('ble sjakie') - self.feed('bgt sjakie') - self.feed('beq sjakie') - self.feed('bl sjakie') - self.feed('sjakie:') - self.feed('b sjakie') - self.feed('ble sjakie') - self.feed('bgt sjakie') - self.feed('beq sjakie') - self.feed('bl sjakie') + self.feed("""b sjakie + ble sjakie + bgt sjakie + beq sjakie + bl sjakie + sjakie: + b sjakie + ble sjakie + bgt sjakie + beq sjakie + bl sjakie""") self.check('030000ea 020000da 010000ca 0000000a ffffffeb feffffea fdffffda fcffffca fbffff0a faffffeb') def testPush(self): @@ -116,12 +113,16 @@ self.feed('adr r1, cval') self.check('04508fe2 00908fe2 04804fe2 08b04fe2 0cc04fe2 10104fe2') - @unittest.skip('Too hard') def testLdrLabelAddress(self): self.feed('ldr r8, =a') self.feed('a:') - self.feed('dcd 6677') - self.check('00801fe5 151a0000 04000000') + self.check('04801fe5 04000000') + + def testLdrLabelAddressAt10000(self): + """ Link code at 0x10000 and check if symbol was correctly patched """ + self.feed('ldr r8, =a') + self.feed('a:') + self.check('04801fe5 04000100', {'.text':0x10000}) def testCmp(self): self.feed('cmp r4, r11') diff -r 67a584582aee -r 6df89163e114 test/testasm.py --- a/test/testasm.py Fri Apr 18 13:08:45 2014 +0200 +++ b/test/testasm.py Sat Apr 26 17:41:56 2014 +0200 @@ -2,11 +2,11 @@ import unittest from ppci import CompilerError -from ppci.assembler import tokenize, Assembler, Lexer +from ppci.assembler import tokenize from ppci.objectfile import ObjectFile -from ppci.linker import Linker from ppci.outstream import BinaryOutputStream from ppci.target.basetarget import Label +from ppci.buildfunctions import link class AssemblerLexingCase(unittest.TestCase): @@ -34,64 +34,6 @@ list(tokenize(asmline, [])) -class AssemblerParsingTestCase(unittest.TestCase): - """ - Tests the assembler parts - """ - def setUp(self): - self.skipTest('refactoring asm parser') - self.parser = asmParser - self.stack = [] - - def emit(self, x): - self.stack.append(x) - - def parse_line(self, line): - self.parser.parse(Lexer(line), self.emit) - - def testParse(self): - asmline = 'lab1: mov rax, rbx' - self.parse_line(asmline) - - def expectTree(self, asmline, stack): - self.parse_line(asmline) - self.assertSequenceEqual(stack, self.stack) - - def testParse2(self): - asmline = 'a: mov rax, [rbx + 2]' - output = [] - output.append(ALabel('a')) - output.append(AInstruction('mov', [ASymbol('rax'), AUnop('[]', ASymbol('rbx') + ANumber(2))])) - self.expectTree(asmline, output) - - def testParse3(self): - # A label must be optional: - asmline = 'mov rax, 1' - output = [AInstruction('mov', [ASymbol('rax'), ANumber(1)])] - self.expectTree(asmline, output) - - def testParse4(self): - # Test 3 operands: - asmline = 'add rax, [4*rbx + 22], rcx' - ops = [] - ops.append(ASymbol('rax')) - ops.append(AUnop('[]', ANumber(4) * ASymbol('rbx') + ANumber(22))) - ops.append(ASymbol('rcx')) - output = [AInstruction('add', ops)] - self.expectTree(asmline, output) - - def testParse5(self): - # An instruction must be optional: - asmline = 'lab1:' - output = [] - output.append(ALabel('lab1')) - self.expectTree(asmline, output) - - def testParse6(self): - # A line can be empty - self.parse_line('') - - class OustreamTestCase(unittest.TestCase): def test1(self): obj = ObjectFile() @@ -104,11 +46,11 @@ class AsmTestCaseBase(unittest.TestCase): """ Base testcase for assembly """ def feed(self, line): - self.a.assemble(line, self.ostream) + self.assembler.assemble(line, self.ostream) - def check(self, hexstr): - l = Linker() - self.obj = l.link([self.obj]) + def check(self, hexstr, layout={}): + self.assembler.flush() + self.obj = link([self.obj], layout) data = bytes(self.obj.get_section('.text').data) self.assertSequenceEqual(bytes.fromhex(hexstr), data) diff -r 67a584582aee -r 6df89163e114 test/testbintools.py --- a/test/testbintools.py Fri Apr 18 13:08:45 2014 +0200 +++ b/test/testbintools.py Sat Apr 26 17:41:56 2014 +0200 @@ -7,6 +7,7 @@ from ppci import CompilerError from ppci.tasks import TaskRunner, TaskError from ppci.buildtasks import EmptyTask +from ppci.buildfunctions import link class TaskTestCase(unittest.TestCase): @@ -53,16 +54,14 @@ 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]) + o3 = link([o1, o2], {}) def testDuplicateSymbol(self): - l = Linker() o1 = ObjectFile() o1.get_section('.text') o1.add_symbol('a', 0, '.text') @@ -70,33 +69,30 @@ o2.get_section('.text') o2.add_symbol('a', 0, '.text') with self.assertRaises(CompilerError): - o3 = l.link([o1, o2]) + o3 = 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]) + o3 = 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]) + o3 = 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)) @@ -106,7 +102,7 @@ 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) + o3 = link([o1, o2], 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) diff -r 67a584582aee -r 6df89163e114 test/testmsp430asm.py --- a/test/testmsp430asm.py Fri Apr 18 13:08:45 2014 +0200 +++ b/test/testmsp430asm.py Sat Apr 26 17:41:56 2014 +0200 @@ -1,13 +1,11 @@ #!/usr/bin/python import unittest -from ppci.assembler import tokenize, Assembler from ppci.objectfile import ObjectFile from ppci.outstream import BinaryOutputStream from ppci.target.target_list import msp430target from testasm import AsmTestCaseBase -a = Assembler(msp430target) class Msp430AssemblerTestCase(AsmTestCaseBase): def setUp(self): @@ -15,7 +13,7 @@ self.obj = ObjectFile() self.ostream = BinaryOutputStream(self.obj) self.ostream.select_section('.text') - self.a = a + self.assembler = msp430target.assembler def testMov(self): self.feed("mov r14, r15") diff -r 67a584582aee -r 6df89163e114 test/testsamples.py --- a/test/testsamples.py Fri Apr 18 13:08:45 2014 +0200 +++ b/test/testsamples.py Sat Apr 26 17:41:56 2014 +0200 @@ -12,6 +12,18 @@ B local_loop """ +modarchcode = """ +module arch; + +function void putc(int c) +{ + var int *UART0DR; + UART0DR = cast(0x10009000); // UART0 DR register + *UART0DR = c; +} + +""" + class Samples: def testPrint(self): snippet = """ @@ -122,7 +134,7 @@ o1 = assemble(io.StringIO(startercode), 'arm') o2 = c3compile([ relpath('..', 'kernel', 'src', 'io.c3'), - relpath('..', 'kernel', 'arch', 'vexpressA9.c3'), + io.StringIO(modarchcode), io.StringIO(src)], [], 'arm') layout = {'code': 0x10000, 'data': 0x20000} o3 = link([o1, o2], layout) diff -r 67a584582aee -r 6df89163e114 test/testthumbasm.py --- a/test/testthumbasm.py Fri Apr 18 13:08:45 2014 +0200 +++ b/test/testthumbasm.py Sat Apr 26 17:41:56 2014 +0200 @@ -1,11 +1,9 @@ import unittest from ppci.outstream import BinaryOutputStream from ppci.objectfile import ObjectFile -from asm import Assembler from testasm import AsmTestCaseBase from ppci.target.target_list import thumb_target -a = Assembler(thumb_target) class ThumbAssemblerTestCase(AsmTestCaseBase): def setUp(self): @@ -13,7 +11,7 @@ self.obj = ObjectFile() self.ostream = BinaryOutputStream(self.obj) self.ostream.select_section('.text') - self.a = a # + self.assembler = thumb_target.assembler def testMovImm8(self): self.feed('mov r4, 100') @@ -148,4 +146,3 @@ self.feed('b henkie') self.check('32b41519 94420198 049332bc a340ab42 f6d0f5d1 f4e7') - diff -r 67a584582aee -r 6df89163e114 util/test_patterns.txt --- a/util/test_patterns.txt Fri Apr 18 13:08:45 2014 +0200 +++ b/util/test_patterns.txt Sat Apr 26 17:41:56 2014 +0200 @@ -59,5 +59,4 @@ === ldr r8, =a a: -.word 6677