diff python/target/msp430.py @ 290:7b38782ed496

File moves
author Windel Bouwman
date Sun, 24 Nov 2013 11:24:15 +0100
parents python/msp430.py@ca1ea402f6a1
children 534b94b40aa8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/target/msp430.py	Sun Nov 24 11:24:15 2013 +0100
@@ -0,0 +1,248 @@
+from target import Register, Instruction, Target
+from asmnodes import ASymbol, ANumber
+from ppci import CompilerError
+import struct
+import types
+
+# Create the target class (singleton):
+msp430target = Target("MSP430")
+
+REGISTER_MODE = 1
+SYMBOLIC_MODE = 3
+ABSOLUTE_MODE = 4
+#TODO: add more modes!
+IMMEDIATE_MODE = 7
+
+# Target description for the MSP430 processor
+
+class MSP430Reg(Register):
+    def __init__(self, num, name):
+        super().__init__(name)
+        self.num = num
+
+# 8 bit registers:
+PCB = MSP430Reg(0, 'r0')
+rpc = PCB
+r11 = MSP430Reg(11, 'r11')
+r12 = MSP430Reg(12, 'r12')
+r13 = MSP430Reg(13, 'r13')
+r14 = MSP430Reg(14, 'r14')
+r15 = MSP430Reg(15, 'r15')
+
+class MSP430Mem:
+    pass
+
+msp430target.registers.append(r11)
+msp430target.registers.append(r12)
+msp430target.registers.append(r13)
+msp430target.registers.append(r14)
+msp430target.registers.append(r15)
+
+# .. etc
+
+#GR8 = RegisterClass((PCB, R15B))
+
+class MSP430Operand:
+    def __init__(self, mode, param):
+        self.mode = mode
+        self.param = param
+    def regField(self):
+        if self.mode == REGISTER_MODE:
+            return self.param
+        elif self.mode == IMMEDIATE_MODE:
+            return rpc.num
+    def asField(self):
+        if self.mode == REGISTER_MODE:
+            return 0
+        elif self.mode == IMMEDIATE_MODE:
+            return 3
+    def adField(self):
+        if self.mode == REGISTER_MODE:
+            return 0
+        elif self.mode == IMMEDIATE_MODE:
+            raise CompilerError('Cannot use immediate mode for destination operand')
+    def extraBytes(self):
+        if self.mode == IMMEDIATE_MODE:
+            return pack_ins(self.param)
+        return bytes()
+    
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ASymbol:
+            # try to map to register:
+            regs = {}
+            for r in msp430target.registers:
+                regs[r.name] = r
+            if vop.name in regs:
+                reg = regs[vop.name]
+                return cls(REGISTER_MODE, reg.num)
+        elif type(vop) is ANumber:
+            # Immediate mode:
+            return cls(IMMEDIATE_MODE, vop.number)
+
+def pack_ins(h):
+    return struct.pack('<H', h)
+
+class MSP430Instruction(Instruction):
+    b = 0
+
+class BInstruction:
+    pass
+
+class MSP430CoreInstruction(Instruction):
+    pass
+
+#########################
+# Single operand arithmatic:
+#########################
+
+@msp430target.instruction
+class reti_ins(MSP430Instruction):
+    mnemonic = 'reti'
+    operands = ()
+    def encode(self):
+        h = 0x1300
+        return pack_ins(h)
+
+class OneOpArith(MSP430Instruction):
+    operands = (MSP430Reg, )
+    def __init__(self, op1):
+        self.op1 = op1
+    def encode(self):
+        # TODO:
+        bits[15:10] = '00100'
+        h1 = (self.opcode << 4)
+        return pack_ins(h1)
+
+def oneOpIns(mne, opc):
+    """ Helper function to define a one operand arithmetic instruction """
+    members = {'mnemonic': mne, 'opcode': opc}
+    ins_cls = type(mne + '_ins', (OneOpArith,), members)
+    msp430target.addInstruction(ins_cls)
+
+oneOpIns('rrc', 0)
+oneOpIns('swpb', 1)
+oneOpIns('rra', 2)
+oneOpIns('sxt', 3)
+oneOpIns('push', 4)
+oneOpIns('call', 5)
+
+#########################
+# Jump instructions:
+#########################
+
+class JumpInstruction(Instruction):
+    def __init__(self, offset):
+        self.offset = offset
+
+    def encode(self):
+        h = (1 << 13) | (self.condition << 10) | (self.offset)
+        return pack_ins(h)
+
+@msp430target.instruction
+class jnz_ins(JumpInstruction):
+    mnemonic = 'jnz'
+    condition = 0
+
+@msp430target.instruction
+class jz_ins(JumpInstruction):
+    mnemonic = 'jz'
+    condition = 1
+
+@msp430target.instruction
+class jnc_ins(JumpInstruction):
+    mnemonic = 'jnc'
+    condition = 2
+
+@msp430target.instruction
+class jc_ins(JumpInstruction):
+    mnemonic = 'jc'
+    condition = 3
+
+@msp430target.instruction
+class jn_ins(JumpInstruction):
+    mnemonic = 'jn'
+    condition = 4
+
+@msp430target.instruction
+class jge_ins(JumpInstruction):
+    mnemonic = 'jge'
+    condition = 5
+
+@msp430target.instruction
+class jl_ins(JumpInstruction):
+    mnemonic = 'jl'
+    condition = 6
+
+@msp430target.instruction
+class jmp_ins(JumpInstruction):
+    mnemonic = 'jmp'
+    condition = 7
+
+#########################
+# Two operand arithmatic instructions:
+#########################
+
+
+class TwoOpArith(MSP430Instruction):
+    operands = (MSP430Operand, MSP430Operand)
+    def __init__(self, src, dst):
+        self.op1 = src
+        self.op2 = dst
+
+    def encode(self):
+        """
+            Smart things have been done by MSP430 designers.
+            As (2 bits) is the source addressing mode selector.
+            Ad (1 bit) is the destination adressing mode selector.
+            For the source there are 7 different addressing mode.
+            For the destination there are 4.
+            The trick is to use also the register to distuingish the
+            different modes.
+        """
+        # TODO: Make memory also possible
+
+        As = self.op1.asField() # addressing mode for the source
+        Ad = self.op2.adField() # Addressing mode for dst
+        b = self.b # When b=1, the operation is byte mode
+        source = self.op1.regField()
+        destination = self.op2.regField()
+        h = (self.opcode << 12) | (source << 8)
+        h |= (self.b << 6) | (As << 4) | (Ad << 7) | destination
+        additions = self.op1.extraBytes() + self.op2.extraBytes()
+        return pack_ins(h) + additions
+
+    def decode(self, data):
+        pass
+
+
+def twoOpIns(mne, opc):
+    """ Helper function to define a two operand arithmetic instruction """
+    members = {'mnemonic': mne, 'opcode': opc}
+    ins_cls = type(mne + '_ins', (TwoOpArith,), members)
+    msp430target.addInstruction(ins_cls)
+
+twoOpIns('mov', 4)
+
+# This is equivalent to the helper function twoOpIns:
+@msp430target.instruction
+class add_ins(TwoOpArith):
+    """ Adds the source to the destination """
+    mnemonic = 'add'
+    opcode = 5
+
+    def operate(self):
+        dst.value = dst.value + src.value
+        setFlags()
+
+twoOpIns('addc', 6)
+twoOpIns('subc', 7)
+twoOpIns('sub', 8)
+twoOpIns('cmp', 9)
+twoOpIns('dadd', 10)
+twoOpIns('bit', 11)
+twoOpIns('bic', 12)
+twoOpIns('bis', 13)
+twoOpIns('xor', 14)
+twoOpIns('and', 15)
+