diff python/cortexm3.py @ 219:1fa3e0050b49

Expanded ad hoc code generator
author Windel Bouwman
date Sat, 06 Jul 2013 12:38:09 +0200
parents 494828a7adf1
children 85c8105318e7
line wrap: on
line diff
--- a/python/cortexm3.py	Fri Jul 05 15:30:22 2013 +0200
+++ b/python/cortexm3.py	Sat Jul 06 12:38:09 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
+from asmnodes import ASymbol, ANumber, AUnop, ABinop, ALabel
 from ppci import CompilerError
 import ir
 
@@ -36,6 +36,23 @@
             if name in regs:
                 r = regs[name]
                 return cls(r.num)
+                
+class Reg8Op:
+    def __init__(self, num):
+        assert num < 8
+        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]
+                if r.num < 8:
+                    return cls(r.num)
 
 def getRegNum(n):
     for r in armtarget.registers:
@@ -57,6 +74,9 @@
         self.basereg = basereg
         self.offset = offset
 
+    def __repr__(self):
+        return '[{}, #{}]'.format(self.basereg, self.offset)
+
     @classmethod
     def Create(cls, vop):
         if type(vop) is AUnop and vop.operation == '[]':
@@ -77,7 +97,38 @@
             else:
                 return
             return cls(getRegNum(basereg.num), offset)
-        pass
+
+class MemoryOpReg8Imm5:
+    def __init__(self, basereg, offset):
+        assert type(basereg) is ArmReg
+        self.basereg = basereg
+        self.offset = offset
+
+    def __repr__(self):
+        return '[{}, #{}]'.format(self.basereg, self.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
+                    if offset > 120:
+                        return
+                    basereg = Reg8Op.Create(vop.arg1)
+                    if not basereg:
+                        return
+                else:
+                    return
+            elif type(vop) is ASymbol:
+                offset = 0
+                basereg = Reg8Op.Create(vop)
+                if not basereg:
+                    return
+            else:
+                return
+            return cls(getRegNum(basereg.num), offset)
 
 class RegisterSet:
     def __init__(self, regs):
@@ -129,10 +180,6 @@
 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')
@@ -145,54 +192,104 @@
 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 __repr__(self):
+        return 'DCD 0x{0:X}'.format(self.expr)
+
+
+
+# Memory related
+
+class LS_imm5_base(ArmInstruction):
+    """ ??? Rt, [Rn, imm5] """
+    operands = (Reg8Op, MemoryOpReg8Imm5)
     def __init__(self, rt, memop):
         assert memop.offset % 4 == 0
         self.imm5 = memop.offset >> 2
         self.rn = memop.basereg.num
         self.rt = rt.num
+        self.memloc = memop
+        assert self.rn < 8
+        assert self.rt < 8
 
     def encode(self):
         Rn = self.rn
         Rt = self.rt
         imm5 = self.imm5
-        h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt
+
+        h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        return u16(h)
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc)
+
+@armtarget.instruction
+class storeimm5_ins(LS_imm5_base):
+    mnemonic = 'STR'
+    opcode = 0xC
+
+@armtarget.instruction
+class loadimm5_ins(LS_imm5_base):
+    mnemonic = 'LDR'
+    opcode = 0xD
+
+class ls_sp_base_imm8(ArmInstruction):
+    operands = (Reg8Op, MemoryOp)
+    def __init__(self, rt, memop):
+        self.rt = rt
+        assert memop.basereg.num == 13
+        self.offset = memop.offset
+
+    def encode(self):
+        rt = self.rt.num
+        assert rt < 8
+        imm8 = self.offset >> 2
+        assert imm8 < 256
+        h = (self.opcode << 8) | (rt << 8) | imm8
         return u16(h)
 
+    def __repr__(self):
+        return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset)
+
 @armtarget.instruction
-class loadimm5_ins(ArmInstruction):
-    """ str Rt, [Rn, imm5], store value into memory """
+class ldr_pcrel(ArmInstruction):
+    """ ldr Rt, [PC, imm8], 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 __init__(self, rt, label):
+        self.rt = rt
+        self.label = label
+        self.offset = 0
 
     def encode(self):
-        Rn = self.rn
-        Rt = self.rt
-        imm5 = self.imm5
-        h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt
+        rt = self.rt.num
+        assert rt < 8
+        imm8 = self.offset >> 2
+        assert imm8 < 256
+        h = (0x9 << 11) | (rt << 8) | imm8
         return u16(h)
 
+    def __repr__(self):
+        return 'LDR {}, [pc,#{}]'.format(self.rt, self.offset)
+
+@armtarget.instruction
+class ldr_sprel(ls_sp_base_imm8):
+    """ ldr Rt, [SP, imm8] """
+    mnemonic = 'LDR'
+    opcode = 0x98
+
+@armtarget.instruction
+class str_sprel(ls_sp_base_imm8):
+    """ str Rt, [SP, imm8] """
+    mnemonic = 'STR'
+    opcode = 0x90
+
 @armtarget.instruction
 class mov_ins(ArmInstruction):
     """ mov Rd, imm8, move immediate value into register """
@@ -204,22 +301,19 @@
         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)
+    def __repr__(self):
+        return 'MOV {0}, xx?'.format(self.r)
         
 @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
@@ -232,9 +326,13 @@
         rm = self.rm.num
         assert rm < 16
         opcode = self.opcode
-        h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
+        h = (1 << 14) | (3 << 9) | (D << 7) | (rm << 3) | rd
         return u16(h)
 
+
+
+# Arithmatics:
+
 @armtarget.instruction
 class addregregimm3_ins(ArmInstruction):
     """ add Rd, Rn, imm3 """
@@ -254,6 +352,61 @@
         h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
         return u16(h)
 
+class regregreg_base(ArmInstruction):
+    """ ??? Rd, Rn, Rm """
+    operands = (Reg8Op, Reg8Op, Reg8Op)
+    def __init__(self, rd, rn, rm):
+        self.rd = rd
+        self.rn = rn
+        self.rm = rm
+    def encode(self):
+        rd = self.rd.num
+        rn = self.rn.num
+        rm = self.rm.num
+        h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd
+        return u16(h)
+    def __repr__(self):
+        return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm)
+
+@armtarget.instruction
+class addregs_ins(regregreg_base):
+    mnemonic = 'ADD'
+    opcode = 0b0001100
+
+@armtarget.instruction
+class subregs_ins(regregreg_base):
+    mnemonic = 'SUB'
+    opcode = 0b0001101
+
+class regreg_base(ArmInstruction):
+    """ ??? Rdn, Rm """
+    operands = (Reg8Op, Reg8Op)
+    def __init__(self, rdn, rm):
+        self.rdn = rdn
+        self.rm = rm
+    def encode(self):
+        rdn = self.rdn.num
+        rm = self.rm.num
+        h = (self.opcode << 6) | (rm << 3) | rdn
+        return u16(h)
+    def __repr__(self):
+        return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm)
+
+@armtarget.instruction
+class andregs_ins(regreg_base):
+    mnemonic = 'AND'
+    opcode = 0b0100000000
+
+@armtarget.instruction
+class orrregs_ins(regreg_base):
+    mnemonic = 'ORR'
+    opcode = 0b0100001100
+
+@armtarget.instruction
+class cmp_ins(regreg_base):
+    mnemonic = 'CMP'
+    opcode = 0b0100001010
+
 @armtarget.instruction
 class cmpregimm8_ins(ArmInstruction):
     """ cmp Rn, imm8 """
@@ -270,34 +423,37 @@
         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)
+# Jumping:
 
 @armtarget.instruction
 class jmp_ins(ArmInstruction):
-    operands = (Label,)
+    operands = (ALabel,)
     mnemonic = 'jmp'
     def __init__(self, target_label):
+        assert type(target_label) is ALabel
         self.target = target_label
     def fixUp(self):
         pass
     def encode(self):
-        h = 1337 # TODO
+        h = 0 # TODO
         return u16(h)
+    def __repr__(self):
+        return 'B {0}'.format(self.target.name)
+
+@armtarget.instruction
+class beq_ins(ArmInstruction):
+    operands = (ALabel,)
+    mnemonic = 'beq'
+    def __init__(self, target_label):
+        assert type(target_label) is ALabel
+        self.target = target_label
+    def fixUp(self):
+        pass
+    def encode(self):
+        h = 0 # TODO
+        return u16(h)
+    def __repr__(self):
+        return 'BEQ {0}'.format(self.target.name)
 
 @armtarget.instruction
 class push_ins(ArmInstruction):
@@ -341,7 +497,6 @@
                 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):