Mercurial > lcfOS
changeset 386:2a970e7270e2
Added repeat assembler macro
author | Windel Bouwman |
---|---|
date | Thu, 01 May 2014 17:40:59 +0200 |
parents | d056b552d3f4 |
children | 34ac19044b8a |
files | experiments/qemu_vexpress_a9/display.c experiments/qemu_vexpress_a9/layout.ld experiments/qemu_vexpress_a9/main.c experiments/qemu_vexpress_a9/make.sh experiments/qemu_vexpress_a9/make_image.py experiments/qemu_vexpress_a9/run.sh experiments/qemu_vexpress_a9/startup.s kernel/arch/qemu_vexpress/startup_a9.asm kernel/arch/qemu_vexpress/vexpressA9.mmap python/ppci/assembler.py python/ppci/buildfunctions.py python/ppci/layout.py python/ppci/linker.py python/ppci/target/arm/__init__.py python/ppci/target/basetarget.py test/testarmasm.py |
diffstat | 16 files changed, 170 insertions(+), 144 deletions(-) [+] |
line wrap: on
line diff
--- a/experiments/qemu_vexpress_a9/display.c Thu May 01 14:03:12 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ - - -#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]; - } - } - -} -
--- a/experiments/qemu_vexpress_a9/layout.ld Thu May 01 14:03:12 2014 +0200 +++ b/experiments/qemu_vexpress_a9/layout.ld Thu May 01 17:40:59 2014 +0200 @@ -3,10 +3,14 @@ SECTIONS { - . = 0x60010000; - .startup . : { startup.o(.text) } + . = 0x0010000; + .startup . : { startup.o(.init) } .text : {*(.text)} - .data : {*(.data)} + . = ALIGN(0x4000); + .data : { + *(.padata) + *(.data) + } .bss : {*(.bss)} . = . + 0x1000; stack_top = .;
--- a/experiments/qemu_vexpress_a9/main.c Thu May 01 14:03:12 2014 +0200 +++ b/experiments/qemu_vexpress_a9/main.c Thu May 01 17:40:59 2014 +0200 @@ -11,12 +11,10 @@ } } -void do_display(void); void start(void) { print_uart0("Hello world\n"); - do_display(); for (;;); }
--- a/experiments/qemu_vexpress_a9/make.sh Thu May 01 14:03:12 2014 +0200 +++ b/experiments/qemu_vexpress_a9/make.sh Thu May 01 17:40:59 2014 +0200 @@ -4,12 +4,10 @@ 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-ld -g -T layout.ld main.o startup.o -o test.elf $TARGET-objcopy -O binary test.elf test.bin +$TARGET-nm test.elf
--- a/experiments/qemu_vexpress_a9/make_image.py Thu May 01 14:03:12 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ - -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() -
--- a/experiments/qemu_vexpress_a9/run.sh Thu May 01 14:03:12 2014 +0200 +++ b/experiments/qemu_vexpress_a9/run.sh Thu May 01 17:40:59 2014 +0200 @@ -1,5 +1,5 @@ #!/bin/bash qemu-system-arm -M vexpress-a9 -m 128M -kernel test.bin \ - -serial stdio + -serial stdio # -nographic
--- a/experiments/qemu_vexpress_a9/startup.s Thu May 01 14:03:12 2014 +0200 +++ b/experiments/qemu_vexpress_a9/startup.s Thu May 01 17:40:59 2014 +0200 @@ -1,8 +1,53 @@ +.section .init .global _Reset; _Reset: LDR sp, =stack_top + + ldr r2, =0x10009000 + + mov r1, #'1' + str r1, [r2] + + ldr r0, =kernel_table0 + mcr p15, 0, r0, c2, c0, 1 + mcr p15, 0, r0, c2, c0, 0 + + mov r1, #'2' + str r1, [r2] + + mov r1, #'3' + str r1, [r2] + +mov r0, #3 +mcr p15, 0, r0, c3, c0, 0 + + mov r1, #'4' + str r1, [r2] + +mrc p15, 0, r0, c1, c0, 0 +orr r0, r0, #1 +mcr p15, 0, r0, c1, c0, 0 + + mov r1, #'5' + str r1, [r2] + + BL start B . + + +.section .padata + +kernel_table0: + .long 0x0402 + .rept 0xFFF + .long 0x0 + .endr + + .rept 0xFFF + .long 0x0 + .endr +
--- a/kernel/arch/qemu_vexpress/startup_a9.asm Thu May 01 14:03:12 2014 +0200 +++ b/kernel/arch/qemu_vexpress/startup_a9.asm Thu May 01 17:40:59 2014 +0200 @@ -25,10 +25,17 @@ mov r0, 0x1 ; TBD: why set this to 1? mcr p15, 0, r0, c2, c0, 2 + +; Set domain 0 to manager: +mov r0, 3 +mcr p15, 0, r0, c3, c0, 0 + + ; Enable the VMSA (Virtual memory system architecture): mrc p15, 0, r0, c1, c0, 0 ; TODO: -; orr r0, r0, 0x1 +; mov r1, 0x1 +; orr r0, r0, r1 ; TODO: implement orr r0, r0, 1 mcr p15, 0, r0, c1, c0, 0 ; Setup stack: @@ -48,6 +55,7 @@ ; Called to identify the proc: arch_pfr0: mrc p15, 0, r0, c0, c1, 0 +ldr r0, =kernel_table0 mov pc, lr arch_pfr1: @@ -69,5 +77,8 @@ section mem_tables kernel_table0: - dcd 0x000402 + dcd 0x000402 ; Identity map first 1 MB + repeat 0xFFE + dcd 0 + endrepeat
--- a/kernel/arch/qemu_vexpress/vexpressA9.mmap Thu May 01 14:03:12 2014 +0200 +++ b/kernel/arch/qemu_vexpress/vexpressA9.mmap Thu May 01 17:40:59 2014 +0200 @@ -2,6 +2,8 @@ MEMORY image LOCATION=0x10000 SIZE=0x10000 { SECTION(reset) SECTION(code) + ALIGN(0x4000) + SECTION(mem_tables) } MEMORY ram LOCATION=0x20000 SIZE=0x10000 {
--- a/python/ppci/assembler.py Thu May 01 14:03:12 2014 +0200 +++ b/python/ppci/assembler.py Thu May 01 17:40:59 2014 +0200 @@ -103,6 +103,9 @@ self.parser = Parser(self.target.asm_keywords, self.target.assembler_rules, self.emit) self.lexer = AsmLexer(self.target.asm_keywords) + def prepare(self): + pass + def emit(self, *args): self.stream.emit(*args)
--- a/python/ppci/buildfunctions.py Thu May 01 14:03:12 2014 +0200 +++ b/python/ppci/buildfunctions.py Thu May 01 17:40:59 2014 +0200 @@ -75,6 +75,7 @@ logger.debug('Assembling into code section') ostream = BinaryAndLoggingStream(output) ostream.select_section('code') + assembler.prepare() assembler.assemble(source, ostream) assembler.flush() return output
--- a/python/ppci/layout.py Thu May 01 14:03:12 2014 +0200 +++ b/python/ppci/layout.py Thu May 01 17:40:59 2014 +0200 @@ -56,6 +56,14 @@ return 'Align({})'.format(self.alignment) +class SymbolDefinition(Input): + def __init__(self, symbol_name): + self.symbol_name = symbol_name + + def __repr__(self): + return 'Symbol define: {}'.format(self.symbol_name) + + class LayoutLexer(BaseLexer): def __init__(self): tok_spec = [ @@ -67,7 +75,7 @@ ('STRING', r"'.*?'", lambda typ, val: (typ, val[1:-1])), ] super().__init__(tok_spec) - self.kws = ['MEMORY', 'ALIGN', 'LOCATION','SECTION','SIZE'] + self.kws = ['MEMORY', 'ALIGN', 'LOCATION','SECTION','SIZE', 'DEFINESYMBOL'] def handle_id(self, typ, val): if val in self.kws: @@ -90,6 +98,7 @@ g.add_one_or_more('input', 'input_list') g.add_production('input', ['ALIGN', '(', 'NUMBER', ')'], self.handle_align) g.add_production('input', ['SECTION', '(', 'ID', ')'], self.handle_section) + g.add_production('input', ['DEFINESYMBOL', '(', 'ID', ')'], self.handle_defsym) g.start_symbol = 'layout' self.p = g.generate_parser() @@ -112,6 +121,9 @@ def handle_section(self, section_tag, lbrace, section_name, rbrace): return Section(section_name.val) + def handle_defsym(self, section_tag, lbrace, name, rbrace): + return SymbolDefinition(name.val) + class LayoutLoader: def __init__(self):
--- a/python/ppci/linker.py Thu May 01 14:03:12 2014 +0200 +++ b/python/ppci/linker.py Thu May 01 17:40:59 2014 +0200 @@ -1,7 +1,7 @@ import logging from .objectfile import ObjectFile from . import CompilerError -from .layout import Layout, Section +from .layout import Layout, Section, SymbolDefinition, Align class Linker: @@ -11,31 +11,7 @@ self.logger = logging.getLogger('Linker') self.target = target - def layout_sections(self, dst, layout): - """ Use the given layout to place sections into memories """ - # Create sections with address: - dst.images = {} - for mem in layout.memories: - cur_addr = mem.location - output_memory = bytearray() - for memory_input in mem.inputs: - if type(memory_input) is Section: - section = dst.get_section(memory_input.section_name) - section.address = cur_addr - cur_addr += section.Size - output_memory += section.data - # TODO: align sections - else: - print(memory_input) - dst.images[mem.name] = bytes(output_memory) - - def link(self, objs, layout): - assert type(objs) is list - assert type(layout) is Layout - # Create new object file to store output: - dst = ObjectFile() - - # First copy all sections into output sections: + def merge_sections(self, objs, dst): for iobj in objs: offsets = {} # Merge sections: @@ -62,10 +38,32 @@ offset = offsets[reloc.section] + reloc.offset dst.add_relocation(reloc.sym, offset, reloc.typ, reloc.section) - # Apply layout rules: - self.layout_sections(dst, layout) + def layout_sections(self, dst, layout): + """ Use the given layout to place sections into memories """ + # Create sections with address: + dst.images = {} + for mem in layout.memories: + cur_addr = mem.location + output_memory = bytearray() + for memory_input in mem.inputs: + if type(memory_input) is Section: + section = dst.get_section(memory_input.section_name) + section.address = cur_addr + cur_addr += section.Size + output_memory += section.data + # TODO: align sections + elif type(memory_input) is SymbolDefinition: + dst.add_symbol(memory_input.symbol_name, cur_addr, "code") + elif type(memory_input) is Align: + while (cur_addr % memory_input.alignment) != 0: + cur_addr += 1 + output_memory += bytes([0]) + else: + print(memory_input) + dst.images[mem.name] = bytes(output_memory) - # Perform relocations: + def do_relocations(self, dst): + """ Perform the correct relocation as listed """ for reloc in dst.relocations: # Lookup symbol: if reloc.sym not in dst.symbols: @@ -83,6 +81,22 @@ else: raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ)) + def link(self, objs, layout): + """ Link together the given object files using the layout """ + assert type(objs) is list + assert type(layout) is Layout + # Create new object file to store output: + dst = ObjectFile() + + # First merge all sections into output sections: + self.merge_sections(objs, dst) + + # Apply layout rules: + self.layout_sections(dst, layout) + + # Perform relocations: + self.do_relocations(dst) + # Create memories for the second time # TODO: make this nicer? self.layout_sections(dst, layout)
--- a/python/ppci/target/arm/__init__.py Thu May 01 14:03:12 2014 +0200 +++ b/python/ppci/target/arm/__init__.py Thu May 01 17:40:59 2014 +0200 @@ -21,15 +21,46 @@ self.target.add_keyword('section') self.target.add_instruction(['section', 'ID'], lambda rhs: self.select_section(rhs[1].val)) + self.target.add_keyword('repeat') + self.target.add_keyword('endrepeat') + self.target.add_instruction(['repeat', 'imm32'], self.begin_repeat) + self.target.add_instruction(['endrepeat'], self.end_repeat) + self.make_parser() self.lit_pool = [] self.lit_counter = 0 + self.inMacro = False + + def prepare(self): + self.inMacro = False + + def begin_repeat(self, rhs): + if self.inMacro: + raise Exception() + self.inMacro = True + self.rep_count = rhs[1] + self.recording = [] + + def end_repeat(self, rhs): + if not self.inMacro: + raise Exception() + self.inMacro = False + for rec in self.recording * self.rep_count: + self.emit(*rec) + + def emit(self, *args): + if self.inMacro: + self.recording.append(args) + else: + super().emit(*args) def select_section(self, name): self.flush() self.stream.select_section(name) def flush(self): + if self.inMacro: + raise Exception() while self.lit_pool: i = self.lit_pool.pop(0) self.emit(i) @@ -43,6 +74,7 @@ self.lit_pool.append(Dcd(v)) return label_name + class ArmTarget(Target): def __init__(self): super().__init__('arm')
--- a/python/ppci/target/basetarget.py Thu May 01 14:03:12 2014 +0200 +++ b/python/ppci/target/basetarget.py Thu May 01 17:40:59 2014 +0200 @@ -135,7 +135,7 @@ f2 = lambda x: f else: f2 = f - assert type(f2) is types.FunctionType + assert type(f2) in [types.FunctionType, types.MethodType] self.assembler_rules.append((lhs, rhs, f2)) def lower_frame_to_stream(self, frame, outs):
--- a/test/testarmasm.py Thu May 01 14:03:12 2014 +0200 +++ b/test/testarmasm.py Thu May 01 17:40:59 2014 +0200 @@ -15,6 +15,7 @@ self.ostream = BinaryOutputStream(self.obj) self.ostream.select_section('code') self.assembler = arm_target.assembler + self.assembler.prepare() def testMovImm(self): self.feed('mov r4, 100') @@ -155,6 +156,12 @@ self.feed('mrc p14, 0, r1, c8, c7, 0') self.check('101f12ee 171e18ee') + def testRepeat(self): + self.feed('repeat 0x5') + self.feed('dcd 0x11') + self.feed('endrepeat') + self.check('11000000 11000000 11000000 11000000 11000000') + if __name__ == '__main__': unittest.main()