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()