Mercurial > lcfOS
changeset 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 |
files | python/asmnodes.py python/msp430.py python/target.py python/testasm.py |
diffstat | 4 files changed, 306 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/python/asmnodes.py Sun Jun 09 16:06:49 2013 +0200 +++ b/python/asmnodes.py Thu Jun 13 00:07:28 2013 +0200 @@ -52,6 +52,7 @@ def __init__(self, n): assert type(n) is int self.n = n + self.number = n def __repr__(self): return '{0}'.format(self.n)
--- 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 +
--- a/python/target.py Sun Jun 09 16:06:49 2013 +0200 +++ b/python/target.py Thu Jun 13 00:07:28 2013 +0200 @@ -15,14 +15,21 @@ self.name = name class Instruction: - def __init__(self, opcode): - self.opcode = opcode + def encode(self): + raise NotImplementedError('TODO') class Target: - def __init__(self): + def __init__(self, name, desc=''): + self.name = name + self.desc = desc self.registers = [] self.instructions = [] + def instruction(self, cls): + """ Decorator function that registers an instruction to this target """ + self.instructions.append(cls) + return cls + def mapOperand(self, operand): """ Try to map an operand to a target type """ if type(operand) is ASymbol: @@ -32,8 +39,7 @@ regs[r.name] = r if operand.name in regs: return regs[operand.name] - else: - return + raise CompilerError('Cannot map {0}'.format(operand)) def mapInstruction(self, vi): """ Map ast tree to real instruction for this target """ @@ -47,5 +53,5 @@ if ic.mnemonic == vi.opcode and ic.operands == optypes: ri = ic(*rops) return ri - raise CompilerError('No suitable instruction found') + raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
--- a/python/testasm.py Sun Jun 09 16:06:49 2013 +0200 +++ b/python/testasm.py Thu Jun 13 00:07:28 2013 +0200 @@ -2,7 +2,8 @@ import unittest, cProfile from ppci import CompilerError -from asm import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber, tokenize, Assembler +from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber +from asm import tokenize, Assembler import msp430 class AssemblerLexingCase(unittest.TestCase): @@ -83,6 +84,7 @@ a = Assembler() with self.assertRaises(CompilerError): a.assemble_line('') + @unittest.skip def testX86(self): testsrc = """ ; tst @@ -98,18 +100,24 @@ class AssemblerMSP430TestCase(unittest.TestCase): def setUp(self): - self.t = msp430.MSP430() + self.t = msp430.msp430target self.a = Assembler(target=self.t) - def testMapInstruction(self): + def testMapMovInstruction(self): i = AInstruction('mov', [ASymbol('r14'), ASymbol('r15')]) - self.t.mapInstruction(i) + ri = self.t.mapInstruction(i) + def testMapRetiInstruction(self): + i = AInstruction('reti', []) + ri = self.t.mapInstruction(i) + + @unittest.skip def testMapOperand(self): o = ASymbol('r14') mo = self.t.mapOperand(o) self.assertEqual(mo, msp430.r14) + @unittest.skip def testMapOperandIndirection(self): o = AUnop('[]', ASymbol('r14')) mo = self.t.mapOperand(o) @@ -117,10 +125,26 @@ def testMov(self): line1 = "mov r14, r15" self.a.assemble_line(line1) + self.assertEqual(bytes([0x0F, 0x4E]), self.a.binout) + + def testMov1337(self): + line1 = "mov 0x1337, r12" + self.a.assemble_line(line1) + self.assertEqual(bytes([0x3C, 0x40, 0x37, 0x13]), self.a.binout) def testAdd(self): - line1 = "add r14, r15" + line1 = "add r15, r13" self.a.assemble_line(line1) + self.assertEqual(bytes([0x0D, 0x5F]), self.a.binout) + + def testReti(self): + line1 = "reti" + self.a.assemble_line(line1) + self.assertEqual(bytes([0x0, 0x13]), self.a.binout) + + def testMSPinstructionCount(self): + """ Check that there are 27 instructions """ + self.assertEqual(27, len(self.t.instructions)) if __name__ == '__main__':