changeset 362:c05ab629976a

Added CPUID for arm
author Windel Bouwman
date Sat, 15 Mar 2014 10:56:34 +0100
parents 614a7f6d4d4d
children 396e5cefba13
files kernel/arch/vexpressA9.c3 kernel/qemutst.sh kernel/src/kernel.c3 kernel/startup_a9.asm python/ppci/c3/codegenerator.py python/ppci/c3/parser.py python/ppci/c3/visitor.py python/ppci/target/arm/__init__.py python/ppci/target/arm/instructions.py python/ppci/target/basetarget.py test/testarmasm.py test/testsamples.py util/test_patterns.txt
diffstat 13 files changed, 151 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/kernel/arch/vexpressA9.c3	Fri Mar 14 16:18:54 2014 +0100
+++ b/kernel/arch/vexpressA9.c3	Sat Mar 15 10:56:34 2014 +0100
@@ -1,10 +1,16 @@
 module arch;
 
+
 function void init()
 {
     // putc(65)
 }
 
+function int pfr0();
+function int pfr1();
+function int mmfr0();
+function int mpuir();
+
 function void putc(int c)
 {
     var int *UART0DR;
--- a/kernel/qemutst.sh	Fri Mar 14 16:18:54 2014 +0100
+++ b/kernel/qemutst.sh	Sat Mar 15 10:56:34 2014 +0100
@@ -2,20 +2,7 @@
 
 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_arm.bin \
     -serial stdio -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/src/kernel.c3	Fri Mar 14 16:18:54 2014 +0100
+++ b/kernel/src/kernel.c3	Sat Mar 15 10:56:34 2014 +0100
@@ -10,16 +10,24 @@
 function void start()
 {
     arch.init();
+
     io.println("Welcome to lcfos!");
+
     io.print_int(0x1337);
     io.print_int(0x1338);
     io.print2("Test: ", 0x13);
 
     var int a;
-    for (a = 0; a < 10; a = a + 1)
+    for (a = 0; a < 2; a = a + 1)
     {
-      io.print2("a = ", a);
+      //io.print2("a = ", a);
     }
+
+    io.print2("PFR0 = ", arch.pfr0());
+    io.print2("PFR1 = ", arch.pfr1());
+    io.print2("MMFR0 = ", arch.mmfr0());
+    io.print2("MPUIR = ", arch.mpuir());
+
     // process.init();
     //memory:init();
 
--- a/kernel/startup_a9.asm	Fri Mar 14 16:18:54 2014 +0100
+++ b/kernel/startup_a9.asm	Sat Mar 15 10:56:34 2014 +0100
@@ -3,3 +3,22 @@
 BL kernel_start          ; Branch to main (this is actually in the interrupt vector)
 local_loop:
 B local_loop
+
+
+; 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
--- a/python/ppci/c3/codegenerator.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/python/ppci/c3/codegenerator.py	Sat Mar 15 10:56:34 2014 +0100
@@ -40,12 +40,15 @@
         self.funcMap = {}
         self.m = ir.Module(pkg.name)
         try:
-            for s in pkg.innerScope.Functions:
+            # Only generate function if function contains a body:
+            real_functions = list(filter(lambda f: f.body, pkg.innerScope.Functions))
+            #real_functions = list(filter(None, pkg.innerScope.Functions))
+            for s in real_functions:
                 f = self.newFunction(s.name)
                 self.funcMap[s] = f
             for v in pkg.innerScope.Variables:
                 self.varMap[v] = self.newTemp()
-            for s in pkg.innerScope.Functions:
+            for s in real_functions:
                 self.gen_function(s)
         except SemanticError as e:
             self.error(e.msg, e.loc)
--- a/python/ppci/c3/parser.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/python/ppci/c3/parser.py	Sat Mar 15 10:56:34 2014 +0100
@@ -80,7 +80,7 @@
 
     def parseTopLevel(self):
         if self.Peak == 'function':
-            self.parseFunctionDef()
+            self.parse_function_def()
         elif self.Peak == 'var':
             self.parseVarDef()
             # TODO handle variable initialization
@@ -188,7 +188,7 @@
                 break
         self.Consume(';')
 
-    def parseFunctionDef(self):
+    def parse_function_def(self):
         loc = self.Consume('function').loc
         returntype = self.parse_type_spec()
         fname = self.Consume('ID').val
@@ -211,7 +211,11 @@
             self.Consume(')')
         paramtypes = [p.typ for p in parameters]
         f.typ = FunctionType(paramtypes, returntype)
-        f.body = self.parseCompound()
+        if self.Peak == ';':
+            self.Consume(';')
+            f.body = None
+        else:
+            f.body = self.parseCompound()
         self.currentPart = savePart
 
     def parse_if(self):
--- a/python/ppci/c3/visitor.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/python/ppci/c3/visitor.py	Sat Mar 15 10:56:34 2014 +0100
@@ -24,7 +24,8 @@
             for s in node.declarations:
                 self.do(s)
             self.do(node.typ)
-            self.do(node.body)
+            if node.body:
+                self.do(node.body)
         elif type(node) is Compound:
             for s in node.statements:
                 self.do(s)
--- a/python/ppci/target/arm/__init__.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/python/ppci/target/arm/__init__.py	Sat Mar 15 10:56:34 2014 +0100
@@ -8,6 +8,7 @@
 from .instructions import Lsr1, Lsl1, And1, Sub1
 from .instructions import B, Bl, Ble, Bgt, Beq, Blt, Cmp, Cmp2
 from .instructions import Push, Pop, Str, Ldr, Ldr3, Str1, Ldr1, Adr
+from .instructions import Mcr, Mrc
 from .selector import ArmInstructionSelector
 from .frame import ArmFrame
 
@@ -75,6 +76,8 @@
         self.add_keyword('mov')
         self.add_instruction(['mov', 'reg', ',', 'imm32'],
                 lambda rhs: Mov(rhs[1], rhs[3]))
+        self.add_instruction(['mov', 'reg', ',', 'reg'],
+                lambda rhs: Mov(rhs[1], rhs[3]))
 
         self.add_keyword('cmp')
         self.add_instruction(['cmp', 'reg', ',', 'imm32'],
@@ -169,3 +172,25 @@
 
         self.add_rule('reg_or_range', ['reg', '-', 'reg'],
             lambda rhs: register_range(rhs[0], rhs[2]))
+
+        # Add MCR and MRC (co-processor)
+        for i in range(16):
+            creg = 'c{}'.format(i)
+            self.add_keyword(creg)
+            self.add_rule('coreg', [creg], i)
+
+        for i in range(8, 16):
+            px = 'p{}'.format(i)
+            self.add_keyword(px)
+            # Ran into trouble when using i inside lambda function:
+            # When using inside lambda (as a closure), i is bound to the latest
+            # value (15)
+            self.add_rule('coproc', [px], i)
+
+        self.add_keyword('mcr')
+        self.add_instruction(['mcr', 'coproc', ',', 'imm3', ',', 'reg', ',', 'coreg', ',', 'coreg', ',', 'imm3'],
+            lambda rhs: Mcr(rhs[1], rhs[3], rhs[5], rhs[7], rhs[9], rhs[11]))
+
+        self.add_keyword('mrc')
+        self.add_instruction(['mrc', 'coproc', ',', 'imm3', ',', 'reg', ',', 'coreg', ',', 'coreg', ',', 'imm3'],
+            lambda rhs: Mrc(rhs[1], rhs[3], rhs[5], rhs[7], rhs[9], rhs[11]))
--- a/python/ppci/target/arm/instructions.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/python/ppci/target/arm/instructions.py	Sat Mar 15 10:56:34 2014 +0100
@@ -495,3 +495,36 @@
         self.token[16:23] = 0b0011111
         self.token[24:28] = 0b0101
         return self.token.encode()
+
+
+class McrBase(ArmInstruction):
+    """ Mov arm register to coprocessor register """
+    def __init__(self, coproc, opc1, rt, crn, crm, opc2):
+        super().__init__()
+        self.coproc = coproc
+        self.opc1 = opc1
+        self.rt = rt
+        self.crn = crn
+        self.crm = crm
+        self.opc2 = opc2
+
+    def encode(self):
+        self.token[0:4] = self.crm
+        self.token[4] = 1
+        self.token[5:8] = self.opc2
+        self.token[8:12] = self.coproc
+        self.token[12:16] = self.rt.num
+        self.token[16:20] = self.crn
+        self.token[20] = self.b20
+        self.token[21:24] = self.opc1
+        self.token[24:28] = 0b1110
+        self.token.cond = AL
+        return self.token.encode()
+
+
+class Mcr(McrBase):
+    b20 = 0
+
+
+class Mrc(McrBase):
+    b20 = 1
--- a/python/ppci/target/basetarget.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/python/ppci/target/basetarget.py	Sat Mar 15 10:56:34 2014 +0100
@@ -1,3 +1,4 @@
+import types
 from ppci import CompilerError
 
 """
@@ -124,7 +125,12 @@
         self.add_rule('instruction', rhs, f)
 
     def add_rule(self, lhs, rhs, f):
-        self.assembler_rules.append((lhs, rhs, f))
+        if type(f) is int:
+            f2 = lambda x: f
+        else:
+            f2 = f
+        assert type(f2) is types.FunctionType
+        self.assembler_rules.append((lhs, rhs, f2))
 
     def lower_frame_to_stream(self, frame, outs):
         """ Lower instructions from frame to output stream """
--- a/test/testarmasm.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/test/testarmasm.py	Sat Mar 15 10:56:34 2014 +0100
@@ -25,6 +25,14 @@
         self.feed('mov sp, 0x6000')
         self.check('06daa0e3')
 
+    def testMovReg(self):
+        self.feed('mov r3, sp')
+        self.feed('mov pc, lr')
+        self.feed('mov pc, r2')
+        self.feed('mov sp, r4')
+        self.feed('mov r5, r6')
+        self.check('0d30a0e1 0ef0a0e1 02f0a0e1 04d0a0e1 0650a0e1')
+
     def testAdd2(self):
         self.feed('add r12, r11, 300')
         self.check('4bcf8be2')
@@ -120,6 +128,17 @@
         self.feed('adr r1, cval')
         self.check('04508fe2 00908fe2 04804fe2 08b04fe2 0cc04fe2 10104fe2')
 
+    def testMcr(self):
+        """ Test move coprocessor register from arm register """
+        self.feed('mcr p15, 0, r1, c2, c0, 0')
+        self.feed('mcr p14, 0, r1, c8, c7, 0')
+        self.check('101f02ee 171e08ee')
+
+    def testMrc(self):
+        self.feed('mrc p15, 0, r1, c2, c0, 0')
+        self.feed('mrc p14, 0, r1, c8, c7, 0')
+        self.check('101f12ee 171e18ee')
+
 
 if __name__ == '__main__':
     unittest.main()
--- a/test/testsamples.py	Fri Mar 14 16:18:54 2014 +0100
+++ b/test/testsamples.py	Sat Mar 15 10:56:34 2014 +0100
@@ -23,19 +23,21 @@
          function void start()
          {
             var int i;
-            for (i=0;i<10;i++)
+            for (i=0; i<10; i++)
             {
-              io.print("A");
+              io.print2("A = ", i);
             }
          }
         """
-        self.do(snippet, "AAAAAAAAAA")
+        res = "".join("A = 0x{0:08X}\n".format(a) for a in range(10))
+        self.do(snippet, res)
 
 
 class TestSamplesOnVexpress(unittest.TestCase, Samples):
     def do(self, src, expected_output):
         runner = TaskRunner()
         recipe_loader = RecipeLoader(runner)
+        print(expected_output)
         return
         # TODO: improve recipe loading??
         recipe_loader.load_dict({
@@ -54,3 +56,5 @@
         res = runQemu()
         self.assertEqual(expected_output, res)
 
+if __name__ == '__main__':
+    unittest.main()
--- a/util/test_patterns.txt	Fri Mar 14 16:18:54 2014 +0100
+++ b/util/test_patterns.txt	Sat Mar 15 10:56:34 2014 +0100
@@ -4,6 +4,10 @@
 mov sp, #0x6000
 ===
 mov r3, sp
+mov pc, lr
+mov pc, r2
+mov sp, r4
+mov r5, r6
 ===
 yield
 ===
@@ -46,3 +50,10 @@
 ===
 and r9, r0, r2
 and r4, r8, r6
+===
+mcr p15, 0, r1, c2, c0, 0
+mcr p14, 0, r1, c8, c7, 0
+===
+mrc p15, 0, r1, c2, c0, 0
+mrc p14, 0, r1, c8, c7, 0
+