changeset 202:f22b431f4113

Added arm add instruction
author Windel Bouwman
date Sat, 15 Jun 2013 10:02:50 +0200
parents d5debbfc0200
children ca1ea402f6a1
files python/arm_cm3.py python/msp430.py python/target.py python/testasm.py
diffstat 4 files changed, 137 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/arm_cm3.py	Sat Jun 15 10:02:50 2013 +0200
@@ -0,0 +1,75 @@
+from target import Register, Instruction, Target
+from asmnodes import ASymbol, ANumber
+from ppci import CompilerError
+import struct, types
+
+def u16(h):
+    return struct.pack('<H', h)
+
+armtarget = Target('arm')
+
+# 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 reg
+    elif type(operand) is ANumber:
+        return ArmImm(operand.number)
+    raise CompilerError('Cannot map {0}'.format(operand))
+
+armtarget.mapOperand = types.MethodType(mapOp, armtarget)
+
+# Define:
+registers = 'r0,r1,r2,r3,r4,r5'
+
+class ArmReg(Register):
+    def __init__(self, num, name):
+        super().__init__(name)
+        self.num = num
+
+class ArmImm:
+    def __init__(self, i):
+        self.i = i
+
+# 8 bit registers:
+r4 = ArmReg(4, 'r4')
+armtarget.registers.append(r4)
+
+class ArmInstruction(Instruction):
+    pass
+
+@armtarget.instruction
+class ldr_ins(ArmInstruction):
+    mnemonic = 'ldr'
+    opcode = 1337
+
+
+@armtarget.instruction
+class mov_ins(ArmInstruction):
+    """ mov Rd, imm8, move immediate value into register """
+    mnemonic = 'mov'
+    opcode = 4 # 00100
+    operands = (ArmReg, ArmImm)
+    def __init__(self, r, imm):
+        self.imm = imm.i
+        self.r = r.num
+    def encode(self):
+        rd = self.r
+        opcode = self.opcode
+        imm8 = self.imm
+        h = (opcode << 11) | (rd << 8) | imm8
+        return u16(h)
+        
+
+@armtarget.instruction
+class yield_ins(ArmInstruction):
+    operands = ()
+    mnemonic = 'yield'
+    def encode(self):
+        return u16(0xbf10)
+
--- a/python/msp430.py	Thu Jun 13 00:07:28 2013 +0200
+++ b/python/msp430.py	Sat Jun 15 10:02:50 2013 +0200
@@ -7,9 +7,13 @@
 msp430target = Target("MSP430")
 
 REGISTER_MODE = 1
+SYMBOLIC_MODE = 3
+ABSOLUTE_MODE = 4
 #TODO: add more modes!
 IMMEDIATE_MODE = 7
 
+
+
 # Add a custom operand mapping method:
 def mapOp(self, operand):
     if type(operand) is ASymbol:
@@ -115,35 +119,18 @@
         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
+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)
 
-@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
+oneOpIns('rrc', 0)
+oneOpIns('swpb', 1)
+oneOpIns('rra', 2)
+oneOpIns('sxt', 3)
+oneOpIns('push', 4)
+oneOpIns('call', 5)
 
 #########################
 # Jump instructions:
@@ -217,7 +204,6 @@
             For the destination there are 4.
             The trick is to use also the register to distuingish the
             different modes.
-
         """
         # TODO: Make memory also possible
 
@@ -234,65 +220,34 @@
     def decode(self, data):
         pass
 
-@msp430target.instruction
-class mov_ins(TwoOpArith):
-    mnemonic = 'mov'
-    opcode = 4
 
+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
 
-@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
+    def operate(self):
+        dst.value = dst.value + src.value
+        setFlags()
 
-@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
+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)
 
-@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
-
--- a/python/target.py	Thu Jun 13 00:07:28 2013 +0200
+++ b/python/target.py	Sat Jun 15 10:02:50 2013 +0200
@@ -27,9 +27,12 @@
 
     def instruction(self, cls):
         """ Decorator function that registers an instruction to this target """
-        self.instructions.append(cls)
+        self.addInstruction(cls)
         return cls
 
+    def addInstruction(self, ins_class):
+        self.instructions.append(ins_class)
+
     def mapOperand(self, operand):
         """ Try to map an operand to a target type """
         if type(operand) is ASymbol:
--- a/python/testasm.py	Thu Jun 13 00:07:28 2013 +0200
+++ b/python/testasm.py	Sat Jun 15 10:02:50 2013 +0200
@@ -5,6 +5,7 @@
 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber
 from asm import tokenize, Assembler
 import msp430
+import arm_cm3
 
 class AssemblerLexingCase(unittest.TestCase):
     """ Tests the assemblers lexer """
@@ -130,12 +131,12 @@
     def testMov1337(self):
         line1 = "mov 0x1337, r12"
         self.a.assemble_line(line1)
-        self.assertEqual(bytes([0x3C, 0x40, 0x37, 0x13]), self.a.binout)
+        self.assertEqual(bytes.fromhex('3C403713'), self.a.binout)
 
     def testAdd(self):
         line1 = "add r15, r13"
         self.a.assemble_line(line1)
-        self.assertEqual(bytes([0x0D, 0x5F]), self.a.binout)
+        self.assertEqual(bytes.fromhex('0D5F'), self.a.binout)
 
     def testReti(self):
         line1 = "reti"
@@ -147,6 +148,23 @@
         self.assertEqual(27, len(self.t.instructions))
 
 
+class AssemblerARMTestCase(unittest.TestCase):
+    def setUp(self):
+        self.t = arm_cm3.armtarget
+        self.a = Assembler(target=self.t)
+
+    def testMapOperand(self):
+        pass
+
+    def testMovImm8(self):
+        self.a.assemble('mov r4, 100')
+        self.assertEqual(bytes.fromhex('6424'), self.a.binout)
+
+    def testYield(self):
+        self.a.assemble('yield')
+        self.assertEqual(bytes.fromhex('10bf'), self.a.binout)
+
+
 if __name__ == '__main__':
     # cProfile.run('unittest.main()')
     unittest.main()