# HG changeset patch # User Windel Bouwman # Date 1393169041 -3600 # Node ID c7cc54c0dfdf597413f9c0751a691ecce4fe3d65 # Parent 6ee17c4dd6b8eff2c3c690bf213e46cf9cd45ea7 Test featurebranch diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf .hgignore --- a/.hgignore Fri Feb 21 13:35:07 2014 +0100 +++ b/.hgignore Sun Feb 23 16:24:01 2014 +0100 @@ -4,6 +4,7 @@ *.pyc *.o *.bin +*.elf cos/bootdisk.img cos/lcfosinitrd.img diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/debug.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/debug.sh Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,4 @@ +#!/bin/bash + +qemu-system-arm -M vexpress-a9 -m 128M -kernel test.bin \ + -serial file:output.txt -s -S diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/display.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/display.c Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,75 @@ + + +#define PL110_CR_EN 0x001 +#define PL110_CR_16BPP 0x008 +#define PL110_CR_MONO 0x010 +#define PL110_CR_TFT 0x020 +#define PL110_CR_MONO_8B 0x040 +#define PL110_CR_DUAL_LCD 0x080 +#define PL110_CR_BGR 0x100 +#define PL110_CR_BEBO 0x200 +#define PL110_CR_BEPO 0x400 +#define PL110_CR_PWR 0x800 + + + + +#define PL110_IOBASE 0x10020000 +#define FB_BASE 0x60050000 + + +typedef unsigned int uint32; +typedef unsigned char uint8; +typedef unsigned short uint16; + +typedef struct +{ + uint32 volatile tim0; //0 + uint32 volatile tim1; //4 + uint32 volatile tim2; //8 + uint32 volatile tim3; //c + uint32 volatile upbase; //10 + uint32 volatile lpbase; //14 + uint32 volatile control; //18 +} PL111MMIO; + +void print_uart0(const char *s); + +extern uint16* image_data; +extern int image_width; +extern int image_height; + +void do_display(void) +{ + uint16 volatile *fb; + PL111MMIO *plio; + int x, y; + + plio = (PL111MMIO*)PL110_IOBASE; + + plio->tim0 = 0x3f1f3f9c; + plio->tim1 = 0x080b61df; + plio->upbase = FB_BASE; + + /* 16-bit color */ + plio->control = PL110_CR_EN | (0xC) | PL110_CR_TFT | PL110_CR_PWR; + + fb = (uint16*)FB_BASE; + + for (x = 0; x < (640 * 480) - 10; ++x) + { + fb[x] = 0x1f << (5 + 6) | 0xf << 5; + } + + print_uart0("Cleared disp\n"); + + for (x = 0; x < image_width; x++) + { + for (y = 0; y < image_height; y++) + { + fb[x + 640 * y] = image_data[x + image_width * y]; + } + } + +} + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/layout.ld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/layout.ld Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,14 @@ + +ENTRY(_Reset) + +SECTIONS +{ + . = 0x60010000; + .startup . : { startup.o(.text) } + .text : {*(.text)} + .data : {*(.data)} + .bss : {*(.bss)} + . = . + 0x1000; + stack_top = .; +} + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/main.c Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,23 @@ + + +volatile unsigned int * const UART0_DR = (unsigned int *)0x10009000; + + +void print_uart0(const char *s) +{ + while(*s != '\0') { /* Loop until end of string */ + *UART0_DR = (unsigned int)(*s); /* Transmit char */ + s++; /* Next char */ + } +} + +void do_display(void); + +void start(void) +{ + print_uart0("Hello world\n"); + do_display(); + for (;;); +} + + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/make.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/make.sh Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,15 @@ +#!/bin/bash + + +TARGET=arm-none-eabi +MCPU=arm926ej-s + +python make_image.py +$TARGET-as -mcpu=$MCPU -g startup.s -o startup.o +$TARGET-gcc -c -g -mcpu=$MCPU -marm main.c -nostdlib -o main.o +$TARGET-gcc -c -g -mcpu=$MCPU -marm display.c -nostdlib -o disp.o +$TARGET-gcc -c -g -mcpu=$MCPU -marm image.c -nostdlib -o img.o +$TARGET-ld -g -T layout.ld main.o startup.o disp.o img.o -o test.elf +$TARGET-objcopy -O binary test.elf test.bin + + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/make_image.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/make_image.py Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,26 @@ + +from PyQt5.QtGui import QImage, QGuiApplication, qRed, qBlue, qGreen + +app = QGuiApplication([]) +img = QImage('../../python/ide/icons/hardware.png') +#print(img) + +f = open('image.c', 'w') +print('typedef unsigned short uint16;',file=f) +print('uint16 image_width = {};'.format(img.width()), file=f) +print('uint16 image_height = {};'.format(img.height()), file=f) +print('uint16 image_data[{}] = {{'.format(img.width()*img.height()+1), file=f) +for y in range(img.height()): + for x in range(img.width()): + pix = img.pixel(x, y) + #print(qRed(pix)) + r = qRed(pix) >> 3 + g = qGreen(pix) >> 2 + b = qBlue(pix) >> 3 + u16 = (r << 11) | (g << 6) | b + assert u16 in range(2**16) + print(' {},'.format(hex(u16)),file=f) + +print('0x0};', file=f) +f.close() + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/run.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/run.sh Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,5 @@ +#!/bin/bash + +qemu-system-arm -M vexpress-a9 -m 128M -kernel test.bin \ + -serial file:output.txt + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf experiments/qemu_vexpress_a9/startup.s --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/experiments/qemu_vexpress_a9/startup.s Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,8 @@ + + +.global _Reset; +_Reset: + LDR sp, =stack_top + BL start + B . + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf kernel/kernel.c3 --- a/kernel/kernel.c3 Fri Feb 21 13:35:07 2014 +0100 +++ b/kernel/kernel.c3 Sun Feb 23 16:24:01 2014 +0100 @@ -8,6 +8,10 @@ // Main entry point of the kernel: function void start() { + var int* UART0DR; + UART0DR = cast(0x10009000); // UART0 Data register + *UART0DR = 72; + process.init(); //memory:init(); @@ -15,6 +19,7 @@ //Process proc = new process:Process(); //scheduler:queue(proc); + while(true) {} } diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf kernel/make.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/make.sh Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,3 @@ +#!/bin/bash + +../python/zcc.py recipe recipe.yaml diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf kernel/monitor.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/monitor.sh Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,3 @@ +#!/bin/bash + +socat stdio UNIX-CONNECT:vm.sock diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf kernel/qemutst.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/qemutst.sh Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e + +echo "quit" | socat stdio stdio + +echo "Trying to run test on stellaris qemu machine" + +# -S means halt at start: +qemu-system-arm -M vexpress-a9 -m 128M -kernel kernel.bin \ + -monitor unix:vm.sock,server -serial file:output.txt -S -s + +#sleep 1 + +# Send quit to the monitor application +#echo "quit" | socat stdio UNIX-CONNECT:vm.sock + +#echo "Output from terminal:" +#cat output.txt +#echo "" + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf kernel/recipe.yaml --- a/kernel/recipe.yaml Fri Feb 21 13:35:07 2014 +0100 +++ b/kernel/recipe.yaml Sun Feb 23 16:24:01 2014 +0100 @@ -2,7 +2,7 @@ link: inputs: - assemble: - source: startup_m3.asm + source: startup_a9.asm machine: arm - compile: sources: [memory.c3, kernel.c3, syscall.c3, process.c3, schedule.c3, arch_arm.c3] @@ -10,7 +10,7 @@ machine: arm output: kernel.elf2 layout: - code: 0x0 + code: 0x10000 data: 0x20000000 output: kernel.bin diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf kernel/startup_a9.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/startup_a9.asm Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,6 @@ + +; DCD 0x20000678 ; Setup stack pointer +DCD 0x06daa0e3 ; mov sp, #0x60 << 8 +DCD 0x60010009 ; Reset vector, jump to address 8 +B kernel_start ; Branch to main (this is actually in the interrupt vector) + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf python/ppci/assembler.py --- a/python/ppci/assembler.py Fri Feb 21 13:35:07 2014 +0100 +++ b/python/ppci/assembler.py Sun Feb 23 16:24:01 2014 +0100 @@ -5,6 +5,7 @@ from target import Target, Label from .asmnodes import ALabel, AInstruction, ABinop, AUnop, ASymbol, ANumber + def tokenize(s): """ Tokenizer, generates an iterator that @@ -70,11 +71,12 @@ class Parser: - def __init__(self): + def __init__(self, tokens, instruction_rules): # Construct a parser given a grammar: ident = lambda x: x # Identity helper function g = pyyacc.Grammar(['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS, 'COMMENT', '{', '}', pyyacc.EOF]) + # Global structure of assembly line: g.add_production('asmline', ['asmline2']) g.add_production('asmline', ['asmline2', 'COMMENT']) g.add_production('asmline2', ['label', 'instruction']) @@ -83,17 +85,19 @@ g.add_production('asmline2', []) g.add_production('label', ['ID', ':'], self.p_label) #g.add_production('label', []) - g.add_production('instruction', ['opcode', 'operands'], self.p_ins_1) - g.add_production('instruction', ['opcode'], self.p_ins_2) + + # 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) + #g.add_production('instruction', []) - g.add_production('opcode', ['ID'], lambda x: x.val) - g.add_production('operands', ['operand'], self.p_operands_1) - g.add_production('operands', ['operands', ',', 'operand'], self.p_operands_2) - g.add_production('operand', ['expression'], ident) - g.add_production('operand', ['[', 'expression', ']'], self.p_mem_op) - g.add_production('operand', ['{', 'listitems', '}'], self.p_list_op) - g.add_production('listitems', ['expression'], self.p_listitems_1) - g.add_production('listitems', ['listitems', ',', 'expression'], self.p_listitems_2) g.add_production('expression', ['term'], ident) g.add_production('expression', ['expression', 'addop', 'term'], self.p_binop) g.add_production('addop', ['-'], lambda x: x.val) @@ -147,56 +151,31 @@ self.emit = emitter self.p.parse(lexer) -# Pre construct parser to save time: -asmParser = Parser() class Assembler: def __init__(self, target, stream): self.target = target - assert isinstance(target,Target) + assert isinstance(target, Target) self.stream = stream - self.restart() - self.p = asmParser + self.parser = Parser(None, target.assembler_rules, self.stream.emit) # Top level interface: - def restart(self): - self.stack = [] - - def emit(self, a): - """ Emit a parsed instruction """ - self.stack.append(a) - def parse_line(self, line): - """ Parse line into asm AST """ + """ Parse line into assembly instructions """ tokens = Lexer(line) - self.p.parse(tokens, self.emit) + self.parser.parse(tokens) def assemble(self, asmsrc): """ Assemble this source snippet """ - if type(asmsrc) is not str: + if hasattr(asmsrc, 'read'): asmsrc2 = asmsrc.read() asmsrc.close() asmsrc = asmsrc2 + # TODO: use generic newline?? + # TODO: the bothersome newline ... for line in asmsrc.split('\n'): - self.assemble_line(line) + self.parse_line(line) def assemble_line(self, line): - """ - Assemble a single source line. - Do not take newlines into account - """ + """ Assemble a single assembly line. """ self.parse_line(line) - self.assemble_aast() - - def assemble_aast(self): - """ Assemble a parsed asm line """ - while self.stack: - vi = self.stack.pop(0) - if type(vi) is AInstruction: - mi = self.target.mapInstruction(vi) - elif type(vi) is ALabel: - mi = Label(vi.name) - else: - raise NotImplementedError('{}'.format(vi)) - if self.stream: - self.stream.emit(mi) diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf python/pyyacc.py --- a/python/pyyacc.py Fri Feb 21 13:35:07 2014 +0100 +++ b/python/pyyacc.py Sun Feb 23 16:24:01 2014 +0100 @@ -201,14 +201,15 @@ if symbol not in self.Symbols: raise ParserGenerationException('Symbol {0} undefined'.format(symbol)) - def genParser(self): - """ Generates a parser from the grammar (using a caching algorithm) """ - action_table, goto_table = self.doGenerate() + def generate_parser(self): + """ Generates a parser from the grammar """ + action_table, goto_table = self.generate_tables() p = LRParser(action_table, goto_table, self.start_symbol) p.grammar = self return p - def doGenerate(self): + def generate_tables(self): + """ Generate parsing tables """ if not self.start_symbol: self.start_symbol = self.productions[0].name self.checkSymbols() diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf python/target/arminstructions.py --- a/python/target/arminstructions.py Fri Feb 21 13:35:07 2014 +0100 +++ b/python/target/arminstructions.py Sun Feb 23 16:24:01 2014 +0100 @@ -3,6 +3,11 @@ from .basetarget import Register, Instruction, Target, Label, LabelRef from .basetarget import Imm32, Imm8, Imm7, Imm3 +from .armtokens import ThumbToken, ArmToken +from .armregisters import R0 + +def add_rule(rhs, f): + pass def u16(h): return struct.pack('> 3) & 0x1 Rm = self.rm.num @@ -559,7 +479,7 @@ return cls(im.src[0], im.dst[0]) def encode(self): - at = ArmToken() + at = ThumbToken() rn = self.rn.num at.rd = self.rdm.num opcode = 0b0100001101 @@ -587,7 +507,7 @@ return cls(im.src[0], im.src[1]) def encode(self): - at = ArmToken() + at = ThumbToken() at.rd = self.rdn.num rm = self.rm.num at[3:6] = rm @@ -774,6 +694,8 @@ return u16(h) +add_rule(['pop', 'reg_list'], lambda rhs: Pop(rhs[1])) + @instruction class Pop(ArmInstruction): operands = (RegisterSet,) diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf python/target/armregisters.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/target/armregisters.py Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,41 @@ + +from .basetarget import Register + +class ArmRegister(Register): + def __init__(self, num, name): + super().__init__(name) + self.num = num + + def __repr__(self): + return self.name + + +class Reg8Op(ArmRegister): + pass + + +class Reg16Op(ArmRegister): + pass + + +R0 = Reg8Op(0, 'r0') +R1 = Reg8Op(1, 'r1') +R2 = Reg8Op(2, 'r2') +R3 = Reg8Op(3, 'r3') +R4 = Reg8Op(4, 'r4') +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') + +# Other registers: +# TODO +SP = ArmRegister(13, 'sp') +LR = ArmRegister(14, 'lr') +PC = ArmRegister(15, 'pc') + +registers = [R0, R1, R2, R3, R4, R5, R6, R7, SP, LR, PC] diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf python/target/armtarget.py --- a/python/target/armtarget.py Fri Feb 21 13:35:07 2014 +0100 +++ b/python/target/armtarget.py Sun Feb 23 16:24:01 2014 +0100 @@ -2,8 +2,7 @@ from .basetarget import Register, Instruction, Target, Label, LabelRef from .basetarget import Imm32, Imm8, Imm7, Imm3 from .arminstructions import allins, Reg8Op, ArmRegister -from .arminstructions import Dcd, B -from .arminstructions import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP +from .arminstructions import thumb_assembly_rules from .armframe import ArmFrame from .arminstructionselector import ArmInstructionSelector @@ -15,9 +14,9 @@ # TODO: make a difference between armv7 and armv5? -class ArmTarget(Target): +class ArmThumbTarget(Target): def __init__(self): - super().__init__('arm') + super().__init__('arm_thumb') for i in allins: self.addInstruction(i) # TODO: fix this nicer? @@ -25,3 +24,10 @@ self.check() self.ins_sel = ArmInstructionSelector() self.FrameClass = ArmFrame + self.assembler_rules = thumb_assembly_rules + + +class ArmArmTarget(Target): + def __init__(self): + super().__init__('arm_arm') + diff -r 6ee17c4dd6b8 -r c7cc54c0dfdf python/target/armtoken.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/target/armtoken.py Sun Feb 23 16:24:01 2014 +0100 @@ -0,0 +1,53 @@ + +def val2bit(v, bits): + b = [] + for i in range(bits): + b.append(bool((1<