changeset 234:83781bd10fdb

wip
author Windel Bouwman
date Sun, 14 Jul 2013 19:29:21 +0200
parents d3dccf12ca88
children ff40407c0240
files python/asmnodes.py python/codegenarm.py python/cortexm3.py python/outstream.py python/target.py python/testasm.py
diffstat 6 files changed, 71 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/python/asmnodes.py	Sun Jul 14 12:28:23 2013 +0200
+++ b/python/asmnodes.py	Sun Jul 14 19:29:21 2013 +0200
@@ -11,11 +11,6 @@
     def __repr__(self):
         return '{0}:'.format(self.name)
 
-class AComment(ANode):
-    def __init__(self, name):
-        self.txt = name
-    def __repr__(self):
-        return '; {}'.format(self.txt)
 
 class AInstruction(ANode):
     def __init__(self, mnemonic, operands):
--- a/python/codegenarm.py	Sun Jul 14 12:28:23 2013 +0200
+++ b/python/codegenarm.py	Sun Jul 14 19:29:21 2013 +0200
@@ -1,5 +1,5 @@
 import ir
-from asmnodes import ALabel, AComment
+from target import Label, Comment
 import cortexm3 as arm
 from ppci import CompilerError
 
@@ -37,18 +37,18 @@
                 pass  #self.imms.append((
 
             self.stack_frame = []
-            self.emit(ALabel(f.name))
+            self.emit(Label(f.name))
             # Save some registers:
             self.emit(arm.push_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6,arm.r7,arm.lr})))
             for bb in f.BasicBlocks:
-                self.emit(ALabel(bb.name))
+                self.emit(Label(bb.name))
                 for ins in bb.Instructions:
                     self.generateInstruction(ins)
 
             self.outs.align(4)
             while self.imms:
                 l, v = self.imms.pop()
-                self.emit(ALabel(l))
+                self.emit(Label(l))
                 self.emit(arm.dcd_ins(v))
             self.outs.align(4)
 
@@ -65,16 +65,16 @@
     def loadStack(self, reg, val):
         self.emit(arm.ldr_sprel(reg, arm.MemSpRel(self.getStack(val))))
     def comment(self, txt):
-        self.emit(AComment(txt))
+        self.emit(Comment(txt))
 
     def generateInstruction(self, ins):
         self.comment(str(ins))
         if type(ins) is ir.Branch:
-            tgt = ALabel(ins.target.name)
+            tgt = Label(ins.target.name)
             self.emit(arm.jmp_ins(tgt))
         elif type(ins) is ir.ImmLoad:
             lname = ins.target.name + '_ivalue'
-            self.emit(arm.ldr_pcrel(arm.r0, ALabel(lname)))
+            self.emit(arm.ldr_pcrel(arm.r0, Label(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:
--- a/python/cortexm3.py	Sun Jul 14 12:28:23 2013 +0200
+++ b/python/cortexm3.py	Sun Jul 14 19:29:21 2013 +0200
@@ -1,6 +1,6 @@
 import struct, types
 from target import Register, Instruction, Target, Imm8, Label, Imm3
-from asmnodes import ASymbol, ANumber, AUnop, ABinop, ALabel
+from asmnodes import ASymbol, ANumber, AUnop, ABinop
 from ppci import CompilerError
 import ir
 
@@ -36,7 +36,7 @@
             if name in regs:
                 r = regs[name]
                 return cls(r.num)
-                
+
 class Reg8Op:
     def __init__(self, num):
         assert num < 8
@@ -269,6 +269,10 @@
         self.label = label
         self.offset = 0
 
+    def resolve(self, f):
+        la = f(self.label)
+        self.offset = (la - self.address) + 4
+
     def encode(self):
         rt = self.rt.num
         assert rt < 8
--- a/python/outstream.py	Sun Jul 14 12:28:23 2013 +0200
+++ b/python/outstream.py	Sun Jul 14 19:29:21 2013 +0200
@@ -1,13 +1,11 @@
 import binascii
-from asmnodes import ALabel, AComment
+from target import Instruction, Label
+
 """
  The output stream is a stream of instructions that can be output
  to a file or binary or hexfile.
 """
 
-class Alignment:
-    def __init__(self, a):
-        self.align = a
 
 class OutputStream:
     def __init__(self):
@@ -15,16 +13,26 @@
         self.currentSection = None
 
     def emit(self, item):
+        assert isinstance(item, Instruction)
         self.sections[self.currentSection].append(item)
 
     def align(self, alignment):
         self.emit(Alignment(alignment))
-        
+
     def selectSection(self, s):
         self.currentSection = s
         if not s in self.sections:
             self.sections[s] = []
 
+    def getLabelAddress(self, l):
+        assert isinstance(l, Label)
+        for s in self.sections.values():
+            for i in s:
+                if type(i) is Label:
+                    if i.name == l.name:
+                        return i.address
+        return 0
+
     def backpatch(self):
         """ Fixup references to other parts in the assembler """
         for s in self.sections:
@@ -37,12 +45,7 @@
                 address = 0x0
             for i in self.sections[s]:
                 i.address = address
-                if type(i) in [ALabel, AComment]:
-                    continue
-                if type(i) is Alignment:
-                    while (address % i.align) != 0:
-                        address += 1
-                    continue
+                i.resolve(self.getLabelAddress)
                 bts = i.encode()
                 address += len(bts)
 
@@ -54,17 +57,12 @@
     def dumpSection(self, s):
         print('.section '+s)
         for i in self.sections[s]:
-            if type(i) in [ALabel, AComment]:
-                print(i)
-            elif type(i) is Alignment:
-                pass
-            else:
-                addr = i.address
-                insword = i.encode()
-                assert type(insword) is bytes
-                insword = binascii.hexlify(bytes(reversed(insword))).decode('ascii')
-                asm = str(i)
-                print('    0x{0:08x} 0x{1} {2}'.format(addr, insword, asm))
+            addr = i.address
+            insword = i.encode()
+            assert type(insword) is bytes
+            insword = binascii.hexlify(bytes(reversed(insword))).decode('ascii')
+            asm = str(i)
+            print('    0x{0:08x} 0x{1} {2}'.format(addr, insword, asm))
 
 class TextOutputStream(OutputStream):
     pass
--- a/python/target.py	Sun Jul 14 12:28:23 2013 +0200
+++ b/python/target.py	Sun Jul 14 19:29:21 2013 +0200
@@ -21,7 +21,7 @@
     def Create(cls, vop):
         if type(vop) is ANumber and vop.number < 256:
             return cls(vop.number)
-        
+
 class Imm3:
     def __init__(self, imm):
         assert imm < 8
@@ -33,9 +33,21 @@
         if type(vop) is ANumber and vop.number < 8:
             return cls(vop.number)
 
-class Label:
+class Instruction:
+    def encode(self):
+        raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self)))
+    def resolve(self, f):
+        pass
+
+
+class PseudoInstruction(Instruction):
+    pass
+
+
+class Label(PseudoInstruction):
     def __init__(self, name):
         self.name = name
+        self.address = 0
 
     @classmethod
     def Create(cls, vop):
@@ -43,13 +55,28 @@
             name = vop.name
             return cls(name)
 
+class Comment(PseudoInstruction):
+    def __init__(self, txt):
+        self.txt = txt
+    def __repr__(self):
+        return '; {}'.format(self.txt)
+
+class Alignment(PseudoInstruction):
+    def __init__(self, a):
+        self.align = a
+    def encode(self):
+        pad = []
+        address = self.address
+        while (address % i.align) != 0:
+            address += 1
+            pad.append(0)
+        return bytes(pad)
+
+
 class Register(Operand):
     def __init__(self, name):
         self.name = name
 
-class Instruction:
-    def encode(self):
-        raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self)))
 
 class Target:
     def __init__(self, name, desc=''):
--- a/python/testasm.py	Sun Jul 14 12:28:23 2013 +0200
+++ b/python/testasm.py	Sun Jul 14 19:29:21 2013 +0200
@@ -194,6 +194,12 @@
         self.feed('str r0, [sp + 4]')
         self.check('0190')
 
+    def testLdrPcRel(self):
+        self.feed('ldr r1, henkie')
+        self.feed('dcd 1')
+        self.feed('henkie: dcd 2')
+        self.check('04490100000002000000')
+
     def testCmpRegReg(self):
         self.feed('cmp r0, r1')
         self.check('8842')