Mercurial > lcfOS
view python/msp430.py @ 279:2ccd57b1d78c
Fix register allocator to do burn2 OK
author | Windel Bouwman |
---|---|
date | Sat, 12 Oct 2013 09:56:23 +0200 |
parents | ca1ea402f6a1 |
children |
line wrap: on
line source
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 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)