diff python/msp430.py @ 201:d5debbfc0200

Added all 27 core instructions of msp430
author Windel Bouwman
date Thu, 13 Jun 2013 00:07:28 +0200
parents 5e391d9a3381
children f22b431f4113
line wrap: on
line diff
--- a/python/msp430.py	Sun Jun 09 16:06:49 2013 +0200
+++ b/python/msp430.py	Thu Jun 13 00:07:28 2013 +0200
@@ -1,4 +1,31 @@
 from target import Register, Instruction, Target
+from asmnodes import ASymbol, ANumber
+from ppci import CompilerError
+import struct, types
+
+# Create the target class (singleton):
+msp430target = Target("MSP430")
+
+REGISTER_MODE = 1
+#TODO: add more modes!
+IMMEDIATE_MODE = 7
+
+# Add a custom operand mapping method:
+def mapOp(self, operand):
+    if type(operand) is ASymbol:
+        # try to map to register:
+        regs = {}
+        for r in self.registers:
+            regs[r.name] = r
+        if operand.name in regs:
+            reg = regs[operand.name]
+            return MSP430Operand(REGISTER_MODE, reg.num)
+    elif type(operand) is ANumber:
+        # Immediate mode:
+        return MSP430Operand(IMMEDIATE_MODE, operand.number)
+    raise CompilerError('Cannot map {0}'.format(operand))
+
+msp430target.mapOperand = types.MethodType(mapOp, msp430target)
 
 # Target description for the MSP430 processor
 
@@ -9,41 +36,263 @@
 
 # 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))
 
-# Two operand arithmatic instructions:
+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()
+        
 
-class TwoOpArith(Instruction):
-    operands = (MSP430Reg, MSP430Reg)
-    def __init__(self, op1, op2):
+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
-        self.op2 = op2
     def encode(self):
         # TODO:
-        b1 = (self.opcode << 4)
-        b2 = 0
-        ba = bytearray([b1, b2])
-        return bytes(ba)
+        bits[15:10] = '00100'
+        h1 = (self.opcode << 4)
+        return pack_ins(h1)
+
+@msp430target.instruction
+class rrc_ins(OneOpArith):
+    mnemonic = 'rrc'
+    opcode = 0
+
+@msp430target.instruction
+class swpb_ins(OneOpArith):
+    mnemonic = 'swpb'
+    opcode = 1
+
+@msp430target.instruction
+class rra_ins(OneOpArith):
+    mnemonic = 'rra'
+    opcode = 2
+
+@msp430target.instruction
+class sxt_ins(OneOpArith):
+    mnemonic = 'sxt'
+    opcode = 3
+
+@msp430target.instruction
+class push_ins(OneOpArith):
+    mnemonic = 'push'
+    opcode = 4
+
+@msp430target.instruction
+class call_ins(OneOpArith):
+    mnemonic = 'call'
+    opcode = 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
+
+@msp430target.instruction
 class mov_ins(TwoOpArith):
-    # class variables:
     mnemonic = 'mov'
     opcode = 4
 
+@msp430target.instruction
 class add_ins(TwoOpArith):
     mnemonic = 'add'
     opcode = 5
 
-class MSP430(Target):
-    def __init__(self):
-        self.registers = [PCB, r13, r14, r15]
-        self.instructions = [mov_ins, add_ins]
+@msp430target.instruction
+class addc_ins(TwoOpArith):
+    mnemonic = 'addc'
+    opcode = 6
+
+@msp430target.instruction
+class subc_ins(TwoOpArith):
+    mnemonic = 'subc'
+    opcode = 7
+
+@msp430target.instruction
+class sub_ins(TwoOpArith):
+    mnemonic = 'sub'
+    opcode = 8
+
+@msp430target.instruction
+class cmp_ins(TwoOpArith):
+    """ Compare, substract source from destination """
+    mnemonic = 'cmp'
+    opcode = 9
 
-t = MSP430()
+@msp430target.instruction
+class dadd_ins(TwoOpArith):
+    """ Decimal add source to destination """
+    mnemonic = 'dadd'
+    opcode = 10
+
+@msp430target.instruction
+class bit_ins(TwoOpArith):
+    mnemonic = 'bit'
+    opcode = 11
+
+@msp430target.instruction
+class bic_ins(TwoOpArith):
+    mnemonic = 'bic'
+    opcode = 12
 
+@msp430target.instruction
+class bis_ins(TwoOpArith):
+    mnemonic = 'bis'
+    opcode = 13
+
+@msp430target.instruction
+class xor_ins(TwoOpArith):
+    mnemonic = 'xor'
+    opcode = 14
+
+@msp430target.instruction
+class and_ins(TwoOpArith):
+    mnemonic = 'and'
+    opcode = 15
+