changeset 340:c7cc54c0dfdf devel

Test featurebranch
author Windel Bouwman
date Sun, 23 Feb 2014 16:24:01 +0100
parents 6ee17c4dd6b8
children 4d204f6f7d4e
files .hgignore experiments/qemu_vexpress_a9/debug.sh 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/kernel.c3 kernel/make.sh kernel/monitor.sh kernel/qemutst.sh kernel/recipe.yaml kernel/startup_a9.asm python/ppci/assembler.py python/pyyacc.py python/target/arminstructions.py python/target/armregisters.py python/target/armtarget.py python/target/armtoken.py python/yacc.py test/testarmasm.py test/testemulation.py util/serve_arm_as.py
diffstat 25 files changed, 385 insertions(+), 159 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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
--- /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];
+        }
+    }
+
+}
+
--- /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 = .;
+}
+
--- /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 (;;);
+}
+
+
--- /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
+
+
--- /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()
+
--- /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
+
--- /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 .
+
--- 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<int*>(0x10009000); // UART0 Data register
+   *UART0DR = 72;
+
     process.init();
     //memory:init();
 
@@ -15,6 +19,7 @@
     //Process proc = new process:Process();
 
     //scheduler:queue(proc);
+    while(true) {}
 }
 
 
--- /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
--- /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
--- /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 ""
+
--- 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
 
--- /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)
+
--- 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)
--- 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()
--- 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('<H', h)
@@ -11,100 +16,12 @@
     return struct.pack('<I', x)
 
 
-def val2bit(v, bits):
-    b = []
-    for i in range(bits):
-        b.append(bool((1<<i) & v))
-    #b.reverse()
-    return b
-
-
-def bit_range(b, e):
-    getter = lambda s: s[b:e]
-    def setter(s, v):
-        s[b:e] = v
-    return property(getter, setter)
-
-class ArmToken:
-    def __init__(self):
-        self.bit_value = 0
-
-    def set_bit(self, i, value):
-        value = bool(value)
-        assert i in range(0, 16)
-        mask = 1 << i
-        if value:
-            self.bit_value |= mask
-        else:
-            self.bit_value &= (~mask)
-
-    def __getitem__(self, key):
-        return False
-
-    def __setitem__(self, key, value):
-        if type(key) is int:
-            self.set_bit(key, value)
-        elif type(key) is slice:
-            assert key.step is None
-            bits = key.stop - key.start
-            value_bits = val2bit(value, bits)
-            for i in range(key.start, key.stop):
-                self.set_bit(i, value_bits[i - key.start])
-        else:
-            raise KeyError()
-
-    rd = bit_range(0, 3)
-
-    def encode(self):
-        return u16(self.bit_value)
+thumb_assembly_rules = []
+arm_assembly_rules = []
 
 
 # Operands:
 
-class ArmRegister(Register):
-    def __init__(self, num, name):
-        super().__init__(name)
-        self.num = num
-
-    def __repr__(self):
-        return self.name
-
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ASymbol:
-            name = vop.name
-            regs = {}
-            for r in registers:
-                regs[r.name] = r
-            if name in regs:
-                r = regs[name]
-                if isinstance(r, cls):
-                    return r
-
-
-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')
-# 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]
 
 
 class RegSpOp:
@@ -136,7 +53,7 @@
         return y.number
     elif type(y) is ASymbol and type(x) is ANumber and y.name.upper() == regname:
         return x.number
-    
+
 
 class MemRegXRel:
     def __init__(self, offset):
@@ -247,8 +164,8 @@
     allins.append(i)
     return i
 
+add_rule(['dcd', 'imm32'], lambda rhs: Dcd(rhs[1]))
 
-@instruction
 class Dcd(ArmInstruction):
     mnemonic = 'dcd'
     operands = (Imm32,)
@@ -462,6 +379,9 @@
     def __repr__(self):
         return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm)
 
+
+add_rule(['add', 'r8', ',', 'r8', ',', 'imm3'], lambda rhs: Add2(rhs[1], rhs[3], rhs[5]))
+
 @instruction
 class Add2(regregimm3_base):
     """ add Rd, Rn, imm3 """
@@ -489,7 +409,7 @@
         return cls(im.dst[0], im.src[0], im.src[1])
 
     def encode(self):
-        at = ArmToken()
+        at = ThumbToken()
         at.rd = self.rd.num
         rn = self.rn.num
         rm = self.rm.num
@@ -530,7 +450,7 @@
         return cls(im.dst[0], im.src[0])
 
     def encode(self):
-        at = ArmToken()
+        at = ThumbToken()
         at.rd = self.rd.num & 0x7
         D = (self.rd.num >> 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,)
--- /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]
--- 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')
+
--- /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<<i) & v))
+    #b.reverse()
+    return b
+
+
+def bit_range(b, e):
+    getter = lambda s: s[b:e]
+    def setter(s, v):
+        s[b:e] = v
+    return property(getter, setter)
+
+
+class ThumbToken:
+    def __init__(self):
+        self.bit_value = 0
+
+    def set_bit(self, i, value):
+        value = bool(value)
+        assert i in range(0, 16)
+        mask = 1 << i
+        if value:
+            self.bit_value |= mask
+        else:
+            self.bit_value &= (~mask)
+
+    def __getitem__(self, key):
+        return False
+
+    def __setitem__(self, key, value):
+        if type(key) is int:
+            self.set_bit(key, value)
+        elif type(key) is slice:
+            assert key.step is None
+            bits = key.stop - key.start
+            value_bits = val2bit(value, bits)
+            for i in range(key.start, key.stop):
+                self.set_bit(i, value_bits[i - key.start])
+        else:
+            raise KeyError()
+
+    rd = bit_range(0, 3)
+
+    def encode(self):
+        return u16(self.bit_value)
+
+
+class ArmToken:
+    pass
+
--- a/python/yacc.py	Fri Feb 21 13:35:07 2014 +0100
+++ b/python/yacc.py	Sun Feb 23 16:24:01 2014 +0100
@@ -209,7 +209,7 @@
         self.grammar = grammar
         self.headers = headers
         self.logger.info('Generating parser for grammar {}'.format(grammar))
-        self.action_table, self.goto_table = grammar.doGenerate()
+        self.action_table, self.goto_table = grammar.generate_tables()
         self.generate_python_script()
 
     def print(self, *args):
--- a/test/testarmasm.py	Fri Feb 21 13:35:07 2014 +0100
+++ b/test/testarmasm.py	Sun Feb 23 16:24:01 2014 +0100
@@ -6,7 +6,7 @@
 from target.target_list import armtarget
 
 
-class AssemblerARMTestCase(AsmTestCaseBase):
+class AssemblerArmThumb2TestCase(AsmTestCaseBase):
     def setUp(self):
         self.t = armtarget
         self.obj = ObjectFile()
@@ -149,3 +149,20 @@
         self.feed('bne henkie')
         self.feed('b henkie')
         self.check('32b41519 94420198 049332bc a340ab42 f6d0f5d1 f4e7')
+
+
+class AssemblerArmTestCase(AsmTestCaseBase):
+    """ ARM-mode (not thumb-mode) instruction assembly test case """
+    def setUp(self):
+        self.t = arm_arm_target
+        self.obj = ObjectFile()
+        self.o = outstream.BinaryOutputStream(self.obj)
+        self.o.selectSection('.text')
+        self.a = Assembler(target=self.t, stream=self.o)
+
+    def testMapOperand(self):
+        pass
+
+    def testMovImm(self):
+        self.feed('mov r4, 100')
+        self.check('6440a0e3')
--- a/test/testemulation.py	Fri Feb 21 13:35:07 2014 +0100
+++ b/test/testemulation.py	Sun Feb 23 16:24:01 2014 +0100
@@ -21,7 +21,7 @@
     def tearDown(self):
         os.chdir(testdir)
 
-    def runQemu(self, kernel, timespan=2):
+    def runQemu(self, kernel):
         args = ['qemu-system-arm', '-M', 'lm3s811evb', '-m', '16M', 
             '-nographic', '-kernel', kernel, '-monitor',
             'unix:qemucontrol.sock,server',
@@ -35,7 +35,7 @@
         qemu_control = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
         qemu_control.connect('qemucontrol.sock')
 
-        time.sleep(2.5)
+        time.sleep(0.5)
 
         # Now connect to the serial output:
         qemu_serial = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
@@ -47,9 +47,7 @@
 
         # Send quit command:
         qemu_control.send("quit\n".encode('ascii'))
-
-        p.wait(timeout=timespan)
-
+        p.wait(timeout=3)
         qemu_control.close()
         qemu_serial.close()
 
--- a/util/serve_arm_as.py	Fri Feb 21 13:35:07 2014 +0100
+++ b/util/serve_arm_as.py	Sun Feb 23 16:24:01 2014 +0100
@@ -10,7 +10,7 @@
 
 def mangle(inp, outstream):
     print('assembling...', file=outstream)
-    p_as = subprocess.Popen(['arm-elf-as', '-mthumb'], stdin=subprocess.PIPE)
+    p_as = subprocess.Popen(['arm-elf-as'], stdin=subprocess.PIPE)
     p_as.communicate(input=inp.encode('ascii'))
 
     p_objdump = subprocess.Popen(['arm-elf-objdump', '-d'], stdout=subprocess.PIPE)