changeset 232:e621e3ba78d2

Added left shift instruction
author Windel Bouwman
date Sun, 14 Jul 2013 11:50:58 +0200
parents 521567d17388
children d3dccf12ca88
files python/c3/codegenerator.py python/c3/lexer.py python/c3/parser.py python/c3/typecheck.py python/codegenarm.py python/cortexm3.py python/stm32f4/blink.c3 python/testasm.py
diffstat 8 files changed, 80 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/python/c3/codegenerator.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/c3/codegenerator.py	Sun Jul 14 11:50:58 2013 +0200
@@ -4,7 +4,8 @@
 from ppci import CompilerError
 from .typecheck import theType
 
-tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', '&':'and'}
+tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', \
+    '&':'and', '>>':'shl', '<<':'shr'}
 
 class CodeGenerator:
     """ Generates intermediate code from a package """
@@ -141,7 +142,7 @@
         if type(expr) is astnodes.Binop:
              ra = self.genExprCode(expr.a)
              rb = self.genExprCode(expr.b)
-             ops = ['+', '-', '*', '/', '|', '&']
+             ops = ['+', '-', '*', '/', '|', '&', '<<', '>>']
              if expr.op in ops:
                 tmp = self.builder.newTmp(tmpnames[expr.op])
                 op = expr.op
--- a/python/c3/lexer.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/c3/lexer.py	Sun Jul 14 11:50:58 2013 +0200
@@ -29,7 +29,7 @@
        ('COMMENTS', r'//.*'),
        ('LONGCOMMENTBEGIN', r'\/\*'),
        ('LONGCOMMENTEND', r'\*\/'),
-       ('LEESTEKEN', r'==|->|[\.,=:;\-+*\[\]/\(\)]|>=|<=|<>|>|<|{|}|&|\^|\|'),
+       ('LEESTEKEN', r'==|->|<<|>>|[\.,=:;\-+*\[\]/\(\)]|>=|<=|<>|>|<|{|}|&|\^|\|'),
        ('STRING', r"'.*?'")
      ]
      tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tok_spec)
--- a/python/c3/parser.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/c3/parser.py	Sun Jul 14 11:50:58 2013 +0200
@@ -270,6 +270,15 @@
         return ee
 
     def SimpleExpression(self):
+        """ Shift operations before + and - ? """
+        e = self.AddExpression()
+        while self.Peak in ['>>', '<<']:
+            op = self.Consume(self.Peak)
+            e2 = self.AddExpression()
+            e = astnodes.Binop(e, op.typ, e2, op.loc)
+        return e
+
+    def AddExpression(self):
         e = self.Term()
         while self.Peak in ['+', '-']:
             op = self.Consume(self.Peak)
@@ -314,7 +323,7 @@
             t = self.parseTypeSpec()
             self.Consume('>')
             self.Consume('(')
-            ce = self.CastExpression()
+            ce = self.Expression()
             self.Consume(')')
             return astnodes.TypeCast(t, ce, loc)
         else:
--- a/python/c3/typecheck.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/c3/typecheck.py	Sun Jul 14 11:50:58 2013 +0200
@@ -145,7 +145,7 @@
                 sym.typ = intType
         elif type(sym) is Binop:
             sym.lvalue = False
-            if sym.op in ['+', '-', '*', '/']:
+            if sym.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']:
                 expectRval(sym.a)
                 expectRval(sym.b)
                 if equalTypes(sym.a.typ, sym.b.typ):
@@ -168,14 +168,6 @@
                    self.error('Must be {0}'.format(boolType), sym.a.loc)
                 if not equalTypes(sym.b.typ, boolType):
                    self.error('Must be {0}'.format(boolType), sym.b.loc)
-            elif sym.op in ['|', '&']:
-                sym.typ = intType
-                sym.lvalue = False
-                if equalTypes(sym.a.typ, sym.b.typ):
-                    if not equalTypes(sym.a.typ, intType):
-                        self.error('Can only add integers', sym.loc)
-                else:
-                   self.error('Types unequal {} != {}'.format(sym.a.typ, sym.b.typ), sym.loc)
             else:
                 raise Exception('Unknown binop {0}'.format(sym.op))
         elif type(sym) is Variable:
--- a/python/codegenarm.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/codegenarm.py	Sun Jul 14 11:50:58 2013 +0200
@@ -26,6 +26,11 @@
 
         self.imms = [] # list with immediates relative to PC.
         self.outs.selectSection('code')
+
+        # Manually inserted startup code:
+        self.emit(arm.dcd_ins(0x20000678)) # initial stack ptr
+        self.emit(arm.dcd_ins(0x08000401)) # reset vector
+
         for f in ircode.Functions:
             # Add global variable addresses to immediate list:
             for gvar in ircode.Variables:
@@ -63,45 +68,48 @@
         self.emit(AComment(txt))
 
     def generateInstruction(self, ins):
+        self.comment(str(ins))
         if type(ins) is ir.Branch:
             tgt = ALabel(ins.target.name)
             self.emit(arm.jmp_ins(tgt))
         elif type(ins) is ir.ImmLoad:
-            self.comment(str(ins))
             lname = ins.target.name + '_ivalue'
             self.emit(arm.ldr_pcrel(arm.r0, ALabel(lname)))
             self.imms.append((lname, ins.value))
             self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.target))))
         elif type(ins) is ir.Store:
-            self.comment(str(ins))
             # Load value in r0:
             self.loadStack(arm.r0, ins.value)
             # store in memory:
-            self.getGlobal(arm.r1, ins.location)
+            # TODO: split globals and locals??
+            #self.getGlobal(arm.r1, ins.location)
+            self.loadStack(arm.r1, ins.location)
             self.emit(arm.storeimm5_ins(arm.r0, arm.MemR8Rel(arm.r1, 0)))
         elif type(ins) is ir.Load:
-            self.comment(str(ins))
-            self.getGlobal(arm.r0, ins.location)
+            # TODO: differ global and local??
+            #self.getGlobal(arm.r0, ins.location)
+            self.loadStack(arm.r0, ins.location)
             self.emit(arm.loadimm5_ins(arm.r0, arm.MemR8Rel(arm.r0, 0)))
             # Store value on stack:
             self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.value))))
         elif type(ins) is ir.BinaryOperator:
-            self.comment(str(ins))
             # Load operands:
             self.loadStack(arm.r0, ins.value1)
             self.loadStack(arm.r1, ins.value2)
             # do operation:
             if ins.operation == '+':
                 self.emit(arm.addregs_ins(arm.r0, arm.r0, arm.r1))
+            elif ins.operation == '<<':
+                self.emit(arm.lslregs_ins(arm.r0, arm.r1))
+            elif ins.operation == '|':
+                self.emit(arm.orrregs_ins(arm.r0, arm.r1))
             else:
                 print('operation not implemented', ins.operation)
             # Store value back:
             self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.result))))
         elif type(ins) is ir.Return:
-            self.comment(str(ins))
             self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc})))
         elif type(ins) is ir.ConditionalBranch:
-            self.comment(str(ins))
             self.loadStack(arm.r0, ins.a)
             self.loadStack(arm.r1, ins.b)
             self.emit(arm.cmp_ins(arm.r1, arm.r0))
@@ -113,6 +121,7 @@
             tgt_no = ALabel(ins.lab2.name)
             self.emit(arm.jmp_ins(tgt_no))
         elif type(ins) is ir.Alloc:
+            # Local variables are added to stack
             self.addStack(ins.value)
         else:
             raise CompilerError('IR "{}" not covered'.format(ins))
--- a/python/cortexm3.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/cortexm3.py	Sun Jul 14 11:50:58 2013 +0200
@@ -278,7 +278,7 @@
         return u16(h)
 
     def __repr__(self):
-        return 'LDR {}, [pc,#{}]'.format(self.rt, self.offset)
+        return 'LDR {}, {}'.format(self.rt, self.label.name)
 
 @armtarget.instruction
 class ldr_sprel(ls_sp_base_imm8):
@@ -311,7 +311,8 @@
         return u16(h)
     def __repr__(self):
         return 'MOV {0}, xx?'.format(self.r)
-        
+
+
 @armtarget.instruction
 class movregreg_ins(ArmInstruction):
     """ mov Rd, Rm """
@@ -410,6 +411,11 @@
     opcode = 0b0100001010
 
 @armtarget.instruction
+class lslregs_ins(regreg_base):
+    mnemonic = 'LSL'
+    opcode = 0b0100000010
+
+@armtarget.instruction
 class cmpregimm8_ins(ArmInstruction):
     """ cmp Rn, imm8 """
     mnemonic = 'cmp'
--- a/python/stm32f4/blink.c3	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/stm32f4/blink.c3	Sun Jul 14 11:50:58 2013 +0200
@@ -1,4 +1,9 @@
-// This file blinks a LED on the STM32F4 discovery board.
+/* This file blinks a LED on the STM32F4 discovery board.
+
+the board has 4 leds on PD12, PD13, PD14 and PD15
+
+*/
+
 package blink;
 
 type struct {
@@ -11,36 +16,42 @@
 }* GPIO_Type;
 
 type struct {
-} RCC_Type;
+    int CR;
+    int PLLCFGR;
+    int CFGR;
+    int CIR;
+    int AHB1RSTR;
+    int AHB2RSTR;
+    int AHB3RSTR;
+    int reserved0;
+    int APB1RSTR;
+    int APB2RSTR;
+    int reserved1a, reserved1b;
+    int AHB1ENR;
+    int AHB2ENR;
+    int AHB3ENR;
+    int reserved2;
+    int APB1ENR, APB2ENR;
+}* RCC_Type;
 
 
 // Functions:
 function void main()
 {
-    var int APB1PERIPH_BASE;
-    APB1PERIPH_BASE = 0x40000000
-    //var int 
+    // Memory mapped control registers:
     var GPIO_Type GPIOD;
-    GPIOD = cast<GPIO_Type>(0x400000);
+    GPIOD = cast<GPIO_Type>(0x40020C00);
+    var RCC_Type RCC;
+    RCC = cast<RCC_Type>(0x40023800);
 
-    var int* RCC_AHB1ENR;
-    RCC_AHB1ENR = cast<int*>(0x40003022);
-    *RCC_AHB1ENR = *RCC_AHB1ENR | 8943;
-    /*
-	RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
-	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
-	
-	GPIOD->MODER = (1<<26);
-	
-	NVIC->ISER[0] |= 1<< (TIM2_IRQn);
-	
-	TIM2->PSC = 0xE000;
-	TIM2->DIER |= TIM_DIER_UIE;
-	TIM2->ARR = 0xE000;
-	TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_CEN;
-	TIM2->EGR = 1;
-	
-    */
+    // Enable the clock to port D:
+    RCC->AHB1ENR = RCC->AHB1ENR | 0x8;
+
+
+    // PD13 == output (01)
+    GPIOD->MODER = (1 << 26);
+    GPIOD->ODR = (1 << 13);
+
     while(true) {}
 }
 
--- a/python/testasm.py	Sat Jul 13 20:20:44 2013 +0200
+++ b/python/testasm.py	Sun Jul 14 11:50:58 2013 +0200
@@ -158,7 +158,7 @@
 
     def check(self, hexstr):
         self.assertSequenceEqual(bytes.fromhex(hexstr), self.a.binout)
-        
+
     def testMapOperand(self):
         pass
 
@@ -198,6 +198,10 @@
         self.feed('cmp r0, r1')
         self.check('8842')
 
+    def testLeftShit(self):
+        self.feed('lsl r3, r5')
+        self.check('ab40')
+
     def testSequence1(self):
         self.feed('mov r5, 3')
         self.feed('add r4, r5, 0')