# 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