diff python/arm_cm3.py @ 206:6c6bf8890d8a

Added push and pop encodings
author Windel Bouwman
date Fri, 28 Jun 2013 16:49:38 +0200
parents d77cb5962cc5
children 8b2f20aae086
line wrap: on
line diff
--- a/python/arm_cm3.py	Sun Jun 23 18:23:18 2013 +0200
+++ b/python/arm_cm3.py	Fri Jun 28 16:49:38 2013 +0200
@@ -1,6 +1,6 @@
 import struct, types
-from target import Register, Instruction, Target
-from asmnodes import ASymbol, ANumber
+from target import Register, Instruction, Target, Imm8, Label, Imm3
+from asmnodes import ASymbol, ANumber, AUnop, ABinop
 from ppci import CompilerError
 import ir
 
@@ -16,14 +16,12 @@
     def __init__(self, num, name):
         super().__init__(name)
         self.num = num
-
-class ArmImm:
-    def __init__(self, i):
-        self.i = i
+    def __repr__(self):
+        return self.name
 
 class RegOp:
     def __init__(self, num):
-        assert num < 8
+        assert num < 16
         self.num = num
 
     @classmethod
@@ -37,44 +35,62 @@
                 r = regs[name]
                 return cls(r.num)
 
-class Label:
-    def __init__(self, name):
-        self.name = name
-
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ASymbol:
-            name = vop.name
-            return cls(name)
-
-class Imm8:
-    def __init__(self, imm):
-        assert imm < 256
-        self.imm = imm
+def getRegNum(n):
+    for r in armtarget.registers:
+        if r.num == n:
+            return r
 
-    @classmethod
-    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
-        assert type(imm) is int
-        self.imm = imm
-
-    @classmethod
-    def Create(cls, vop):
-        if type(vop) is ANumber and vop.number < 8:
-            return cls(vop.number)
+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 RegisterSet:
     def __init__(self, regs):
-        pass
+        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')
@@ -83,17 +99,23 @@
 armtarget.registers.append(r6)
 r7 = ArmReg(7, 'r7')
 armtarget.registers.append(r7)
+# 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
 
-@armtarget.instruction
 class ldr_ins(ArmInstruction):
     mnemonic = 'ldr'
     opcode = 1337
     irpattern = 'todo'
 
-@armtarget.instruction
 class dcd_ins(ArmInstruction):
     mnemonic = 'dcd'
     def __init__(self, expr):
@@ -101,12 +123,6 @@
     def encode(self):
         return u32(self.expr)
 
-class Operand2:
-    def __init__(self, expr):
-        if type(expr) is ANumber:
-            pass
-    pass
-
 @armtarget.instruction
 class mov_ins(ArmInstruction):
     """ mov Rd, imm8, move immediate value into register """
@@ -186,7 +202,7 @@
 
 @armtarget.instruction
 class jmp_ins(ArmInstruction):
-    operands = (Label)
+    operands = (Label,)
     mnemonic = 'jmp'
     def __init__(self, target_label):
         self.target = target_label
@@ -198,20 +214,45 @@
 
 @armtarget.instruction
 class push_ins(ArmInstruction):
-    operands = (RegisterSet)
+    operands = (RegisterSet,)
     mnemonic = 'push'
     def __init__(self, regs):
+        print(self.operands)
+        assert (type(regs),) == self.operands, (type(regs),)
         self.regs = regs
+    def __repr__(self):
+        return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
     def encode(self):
-        return u16(0)
+        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)
+    operands = (RegisterSet,)
     mnemonic = 'pop'
     def __init__(self, regs):
         self.regs = 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
@@ -221,3 +262,5 @@
     def encode(self):
         return u16(0xbf10)
 
+armtarget.check()
+