diff python/cortexm3.py @ 218:494828a7adf1

added some sort of cache to assembler
author Windel Bouwman
date Fri, 05 Jul 2013 15:30:22 +0200
parents python/arm_cm3.py@57c032c5e753
children 1fa3e0050b49
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/cortexm3.py	Fri Jul 05 15:30:22 2013 +0200
@@ -0,0 +1,354 @@
+import struct, types
+from target import Register, Instruction, Target, Imm8, Label, Imm3
+from asmnodes import ASymbol, ANumber, AUnop, ABinop
+from ppci import CompilerError
+import ir
+
+# TODO: encode this in DSL (domain specific language)
+
+def u16(h):
+    return struct.pack('<H', h)
+
+def u32(x):
+    return struct.pack('<I', x)
+
+armtarget = Target('arm')
+
+class ArmReg(Register):
+    def __init__(self, num, name):
+        super().__init__(name)
+        self.num = num
+    def __repr__(self):
+        return self.name
+
+class RegOp:
+    def __init__(self, num):
+        assert num < 16
+        self.num = num
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ASymbol:
+            name = vop.name
+            regs = {}
+            for r in armtarget.registers:
+                regs[r.name] = r
+            if name in regs:
+                r = regs[name]
+                return cls(r.num)
+
+def getRegNum(n):
+    for r in armtarget.registers:
+        if r.num == n:
+            return r
+
+def getRegisterRange(n1, n2):
+    regs = []
+    if n1.num < n2.num:
+        for n in range(n1.num, n2.num + 1):
+            r = getRegNum(n)
+            assert r
+            regs.append(r)
+    return regs
+
+class MemoryOp:
+    def __init__(self, basereg, offset):
+        assert type(basereg) is ArmReg
+        self.basereg = basereg
+        self.offset = offset
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is AUnop and vop.operation == '[]':
+            vop = vop.arg # descent
+            if type(vop) is ABinop:
+                if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber:
+                    offset = vop.arg2.number
+                    basereg = RegOp.Create(vop.arg1)
+                    if not basereg:
+                        return
+                else:
+                    return
+            elif type(vop) is ASymbol:
+                offset = 0
+                basereg = RegOp.Create(vop)
+                if not basereg:
+                    return
+            else:
+                return
+            return cls(getRegNum(basereg.num), offset)
+        pass
+
+class RegisterSet:
+    def __init__(self, regs):
+        assert type(regs) is set
+        self.regs = regs
+    def __repr__(self):
+        return ','.join([str(r) for r in self.regs])
+    @classmethod
+    def Create(cls, vop):
+        assert type(vop) is AUnop and vop.operation == '{}'
+        assert type(vop.arg) is list
+        regs = set()
+        for arg in vop.arg:
+            if type(arg) is ASymbol:
+                reg = RegOp.Create(arg)
+                if not reg:
+                    return
+                regs.add(reg)
+            elif type(arg) is ABinop and arg.op == '-':
+                reg1 = RegOp.Create(arg.arg1)
+                reg2 = RegOp.Create(arg.arg2)
+                if not reg1:
+                    return
+                if not reg2:
+                    return
+                for r in getRegisterRange(reg1, reg2):
+                    regs.add(r)
+            else:
+                raise Exception('Cannot be')
+        return cls(regs)
+
+    def registerNumbers(self):
+        return [r.num for r in self.regs]
+
+# 8 bit registers:
+r0 = ArmReg(0, 'r0')
+armtarget.registers.append(r0)
+r1 = ArmReg(1, 'r1')
+armtarget.registers.append(r1)
+r2 = ArmReg(2, 'r2')
+armtarget.registers.append(r2)
+r3 = ArmReg(3, 'r3')
+armtarget.registers.append(r3)
+r4 = ArmReg(4, 'r4')
+armtarget.registers.append(r4)
+r5 = ArmReg(5, 'r5')
+armtarget.registers.append(r5)
+r6 = ArmReg(6, 'r6')
+armtarget.registers.append(r6)
+r7 = ArmReg(7, 'r7')
+armtarget.registers.append(r7)
+r10 = ArmReg(10, 'r10')
+armtarget.registers.append(r10)
+r11 = ArmReg(11, 'r11')
+armtarget.registers.append(r11)
+# Other registers:
+# TODO
+sp = ArmReg(13, 'sp')
+armtarget.registers.append(sp)
+lr = ArmReg(14, 'lr')
+armtarget.registers.append(lr)
+pc = ArmReg(15, 'pc')
+armtarget.registers.append(pc)
+
+class ArmInstruction(Instruction):
+    pass
+
+class ldr_ins(ArmInstruction):
+    mnemonic = 'ldr'
+    opcode = 1337
+    irpattern = 'todo'
+
+class dcd_ins(ArmInstruction):
+    mnemonic = 'dcd'
+    def __init__(self, expr):
+        self.expr = expr
+    def encode(self):
+        return u32(self.expr)
+
+@armtarget.instruction
+class storeimm5_ins(ArmInstruction):
+    """ str Rt, [Rn, imm5], store value into memory """
+    mnemonic = 'str'
+    operands = (RegOp, MemoryOp)
+    def __init__(self, rt, memop):
+        assert memop.offset % 4 == 0
+        self.imm5 = memop.offset >> 2
+        self.rn = memop.basereg.num
+        self.rt = rt.num
+
+    def encode(self):
+        Rn = self.rn
+        Rt = self.rt
+        imm5 = self.imm5
+        h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        return u16(h)
+
+@armtarget.instruction
+class loadimm5_ins(ArmInstruction):
+    """ str Rt, [Rn, imm5], store value into memory """
+    mnemonic = 'ldr'
+    operands = (RegOp, MemoryOp)
+    def __init__(self, rt, memop):
+        assert memop.offset % 4 == 0
+        self.imm5 = memop.offset >> 2
+        self.rn = memop.basereg.num
+        self.rt = rt.num
+
+    def encode(self):
+        Rn = self.rn
+        Rt = self.rt
+        imm5 = self.imm5
+        h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        return u16(h)
+
+@armtarget.instruction
+class mov_ins(ArmInstruction):
+    """ mov Rd, imm8, move immediate value into register """
+    mnemonic = 'mov'
+    opcode = 4 # 00100 Rd(3) imm8
+    operands = (RegOp, Imm8)
+    irpattern = ir.ImmLoad
+    def __init__(self, rd, imm):
+        self.imm = imm.imm
+        self.r = rd.num
+
+    @classmethod
+    def FromIr(cls, ir_ins):
+        pass
+
+    def encode(self):
+        rd = self.r
+        opcode = self.opcode
+        imm8 = self.imm
+        h = (opcode << 11) | (rd << 8) | imm8
+        return u16(h)
+        
+@armtarget.instruction
+class movregreg_ins(ArmInstruction):
+    """ mov Rd, Rm """
+    mnemonic = 'mov'
+    opcode = 8 # 01000 Rd(3) imm8
+    operands = (RegOp, RegOp)
+    def __init__(self, rd, rm):
+        self.rd = rd
+        self.rm = rm
+    def encode(self):
+        rd = self.rd.num
+        D = (rd & 0x8) >> 3
+        assert D < 2
+        rd = rd & 0x7
+        rm = self.rm.num
+        assert rm < 16
+        opcode = self.opcode
+        h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
+        return u16(h)
+
+@armtarget.instruction
+class addregregimm3_ins(ArmInstruction):
+    """ add Rd, Rn, imm3 """
+    mnemonic = 'add'
+    opcode = 3 # 00011
+    operands = (RegOp, RegOp, Imm3)
+    irpattern = 3
+    def __init__(self, rd, rn, imm3):
+        self.rd = rd
+        self.rn = rn
+        self.imm3 = imm3
+    def encode(self):
+        rd = self.rd.num
+        rn = self.rn.num
+        imm3 = self.imm3.imm
+        opcode = self.opcode
+        h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
+        return u16(h)
+
+@armtarget.instruction
+class cmpregimm8_ins(ArmInstruction):
+    """ cmp Rn, imm8 """
+    mnemonic = 'cmp'
+    opcode = 5 # 00101
+    operands = (RegOp, Imm8)
+    def __init__(self, rn, imm):
+        self.rn = rn
+        self.imm = imm
+    def encode(self):
+        rn = self.rn.num
+        imm = self.imm.imm
+        opcode = self.opcode
+        h = (opcode << 11) | (rn << 8) | imm
+        return u16(h)
+
+@armtarget.instruction
+class cmp_ins(ArmInstruction):
+    """ cmp Rn, Rm """
+    mnemonic = 'cmp'
+    operands = (RegOp, RegOp)
+    def __init__(self, rn, rm):
+        self.rn = rn
+        self.rm = rm
+    def encode(self):
+        rn = self.rn.num
+        rm = self.rm.num
+        assert rn < 8
+        assert rm < 8
+        opcode = 0x42
+        h = (opcode << 8) | (1 << 7) | (rm << 3) | (rn & 0x7)
+        return u16(h)
+
+@armtarget.instruction
+class jmp_ins(ArmInstruction):
+    operands = (Label,)
+    mnemonic = 'jmp'
+    def __init__(self, target_label):
+        self.target = target_label
+    def fixUp(self):
+        pass
+    def encode(self):
+        h = 1337 # TODO
+        return u16(h)
+
+@armtarget.instruction
+class push_ins(ArmInstruction):
+    operands = (RegisterSet,)
+    mnemonic = 'push'
+    def __init__(self, regs):
+        assert (type(regs),) == self.operands, (type(regs),)
+        self.regs = regs
+    def __repr__(self):
+        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
+    def encode(self):
+        reg_list = 0
+        M = 0
+        for n in self.regs.registerNumbers():
+            if n < 8:
+                reg_list |= (1 << n)
+            elif n == 14:
+                M = 1
+            else:
+                raise NotImplementedError('not implemented for this register')
+        h = (0x5a << 9) | (M << 8) | reg_list
+        return u16(h)
+
+@armtarget.instruction
+class pop_ins(ArmInstruction):
+    operands = (RegisterSet,)
+    mnemonic = 'pop'
+    def __init__(self, regs):
+        self.regs = regs
+    def __repr__(self):
+        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
+    def encode(self):
+        reg_list = 0
+        P = 0
+        for n in self.regs.registerNumbers():
+            if n < 8:
+                reg_list |= (1 << n)
+            elif n == 15:
+                P = 1
+            else:
+                raise NotImplementedError('not implemented for this register')
+        h = (0x5E << 9) | (P << 8) | reg_list
+        return u16(h)
+        return u16(0)
+
+@armtarget.instruction
+class yield_ins(ArmInstruction):
+    operands = ()
+    mnemonic = 'yield'
+    def encode(self):
+        return u16(0xbf10)
+
+armtarget.check()
+