292
|
1 from .basetarget import Register, Instruction, Target
|
334
|
2 from ppci.asmnodes import ASymbol, ANumber
|
201
|
3 from ppci import CompilerError
|
290
|
4 import struct
|
|
5 import types
|
201
|
6
|
|
7 # Create the target class (singleton):
|
341
|
8
|
|
9 class Msp430T(Target):
|
|
10 def __init__(self):
|
|
11 super().__init__('msp430')
|
|
12 self.asm_keywords = []
|
|
13 self.assembler_rules = []
|
|
14 self.add_keyword('mov')
|
|
15 self.add_keyword('r13')
|
|
16 self.add_keyword('r14')
|
|
17 self.add_keyword('r15')
|
|
18 R0 = None # TODO
|
|
19 self.add_rule('reg', ['r13'], lambda rhs: r13)
|
|
20 self.add_rule('reg', ['r14'], lambda rhs: r14)
|
|
21 self.add_rule('reg', ['r15'], lambda rhs: r15)
|
|
22 self.add_instruction(['mov', 'reg', ',', 'reg'],
|
|
23 lambda rhs: Mov(rhs[1], rhs[3]))
|
|
24
|
|
25 self.add_keyword('reti')
|
|
26 self.add_instruction(['reti'], lambda rhs: reti_ins())
|
|
27
|
|
28 msp430target = Msp430T()
|
201
|
29
|
|
30 REGISTER_MODE = 1
|
202
|
31 SYMBOLIC_MODE = 3
|
|
32 ABSOLUTE_MODE = 4
|
201
|
33 #TODO: add more modes!
|
|
34 IMMEDIATE_MODE = 7
|
|
35
|
199
|
36 # Target description for the MSP430 processor
|
|
37
|
|
38 class MSP430Reg(Register):
|
|
39 def __init__(self, num, name):
|
|
40 super().__init__(name)
|
|
41 self.num = num
|
|
42
|
200
|
43 # 8 bit registers:
|
199
|
44 PCB = MSP430Reg(0, 'r0')
|
201
|
45 rpc = PCB
|
|
46 r11 = MSP430Reg(11, 'r11')
|
|
47 r12 = MSP430Reg(12, 'r12')
|
200
|
48 r13 = MSP430Reg(13, 'r13')
|
|
49 r14 = MSP430Reg(14, 'r14')
|
|
50 r15 = MSP430Reg(15, 'r15')
|
199
|
51
|
201
|
52 class MSP430Mem:
|
|
53 pass
|
|
54
|
|
55 msp430target.registers.append(r11)
|
|
56 msp430target.registers.append(r12)
|
|
57 msp430target.registers.append(r13)
|
|
58 msp430target.registers.append(r14)
|
|
59 msp430target.registers.append(r15)
|
|
60
|
199
|
61 # .. etc
|
|
62
|
|
63 #GR8 = RegisterClass((PCB, R15B))
|
|
64
|
201
|
65 class MSP430Operand:
|
|
66 def __init__(self, mode, param):
|
|
67 self.mode = mode
|
|
68 self.param = param
|
|
69 def regField(self):
|
|
70 if self.mode == REGISTER_MODE:
|
|
71 return self.param
|
|
72 elif self.mode == IMMEDIATE_MODE:
|
|
73 return rpc.num
|
|
74 def asField(self):
|
|
75 if self.mode == REGISTER_MODE:
|
|
76 return 0
|
|
77 elif self.mode == IMMEDIATE_MODE:
|
|
78 return 3
|
|
79 def adField(self):
|
|
80 if self.mode == REGISTER_MODE:
|
|
81 return 0
|
|
82 elif self.mode == IMMEDIATE_MODE:
|
|
83 raise CompilerError('Cannot use immediate mode for destination operand')
|
|
84 def extraBytes(self):
|
|
85 if self.mode == IMMEDIATE_MODE:
|
|
86 return pack_ins(self.param)
|
|
87 return bytes()
|
203
|
88
|
|
89 @classmethod
|
|
90 def Create(cls, vop):
|
|
91 if type(vop) is ASymbol:
|
|
92 # try to map to register:
|
|
93 regs = {}
|
|
94 for r in msp430target.registers:
|
|
95 regs[r.name] = r
|
|
96 if vop.name in regs:
|
|
97 reg = regs[vop.name]
|
|
98 return cls(REGISTER_MODE, reg.num)
|
|
99 elif type(vop) is ANumber:
|
|
100 # Immediate mode:
|
|
101 return cls(IMMEDIATE_MODE, vop.number)
|
200
|
102
|
201
|
103 def pack_ins(h):
|
|
104 return struct.pack('<H', h)
|
|
105
|
|
106 class MSP430Instruction(Instruction):
|
|
107 b = 0
|
|
108
|
|
109 class BInstruction:
|
|
110 pass
|
|
111
|
|
112 class MSP430CoreInstruction(Instruction):
|
|
113 pass
|
|
114
|
|
115 #########################
|
|
116 # Single operand arithmatic:
|
|
117 #########################
|
|
118
|
|
119 class reti_ins(MSP430Instruction):
|
|
120 mnemonic = 'reti'
|
|
121 def encode(self):
|
|
122 h = 0x1300
|
|
123 return pack_ins(h)
|
|
124
|
|
125 class OneOpArith(MSP430Instruction):
|
|
126 def __init__(self, op1):
|
200
|
127 self.op1 = op1
|
341
|
128
|
200
|
129 def encode(self):
|
|
130 # TODO:
|
201
|
131 bits[15:10] = '00100'
|
|
132 h1 = (self.opcode << 4)
|
|
133 return pack_ins(h1)
|
|
134
|
202
|
135 def oneOpIns(mne, opc):
|
|
136 """ Helper function to define a one operand arithmetic instruction """
|
|
137 members = {'mnemonic': mne, 'opcode': opc}
|
|
138 ins_cls = type(mne + '_ins', (OneOpArith,), members)
|
|
139 msp430target.addInstruction(ins_cls)
|
201
|
140
|
202
|
141 oneOpIns('rrc', 0)
|
|
142 oneOpIns('swpb', 1)
|
|
143 oneOpIns('rra', 2)
|
|
144 oneOpIns('sxt', 3)
|
|
145 oneOpIns('push', 4)
|
|
146 oneOpIns('call', 5)
|
201
|
147
|
|
148 #########################
|
|
149 # Jump instructions:
|
|
150 #########################
|
|
151
|
|
152 class JumpInstruction(Instruction):
|
|
153 def __init__(self, offset):
|
|
154 self.offset = offset
|
|
155
|
|
156 def encode(self):
|
|
157 h = (1 << 13) | (self.condition << 10) | (self.offset)
|
|
158 return pack_ins(h)
|
|
159
|
|
160 class jnz_ins(JumpInstruction):
|
|
161 mnemonic = 'jnz'
|
|
162 condition = 0
|
|
163
|
|
164 class jz_ins(JumpInstruction):
|
|
165 mnemonic = 'jz'
|
|
166 condition = 1
|
|
167
|
|
168 class jnc_ins(JumpInstruction):
|
|
169 mnemonic = 'jnc'
|
|
170 condition = 2
|
199
|
171
|
201
|
172 class jc_ins(JumpInstruction):
|
|
173 mnemonic = 'jc'
|
|
174 condition = 3
|
|
175
|
|
176 class jn_ins(JumpInstruction):
|
|
177 mnemonic = 'jn'
|
|
178 condition = 4
|
|
179
|
|
180 class jge_ins(JumpInstruction):
|
|
181 mnemonic = 'jge'
|
|
182 condition = 5
|
|
183
|
|
184 class jl_ins(JumpInstruction):
|
|
185 mnemonic = 'jl'
|
|
186 condition = 6
|
|
187
|
|
188 class jmp_ins(JumpInstruction):
|
|
189 mnemonic = 'jmp'
|
|
190 condition = 7
|
|
191
|
|
192 #########################
|
|
193 # Two operand arithmatic instructions:
|
|
194 #########################
|
|
195
|
|
196
|
|
197 class TwoOpArith(MSP430Instruction):
|
|
198 def __init__(self, src, dst):
|
|
199 self.op1 = src
|
|
200 self.op2 = dst
|
|
201
|
|
202 def encode(self):
|
|
203 """
|
|
204 Smart things have been done by MSP430 designers.
|
|
205 As (2 bits) is the source addressing mode selector.
|
|
206 Ad (1 bit) is the destination adressing mode selector.
|
|
207 For the source there are 7 different addressing mode.
|
|
208 For the destination there are 4.
|
|
209 The trick is to use also the register to distuingish the
|
|
210 different modes.
|
|
211 """
|
|
212 # TODO: Make memory also possible
|
|
213
|
|
214 As = self.op1.asField() # addressing mode for the source
|
|
215 Ad = self.op2.adField() # Addressing mode for dst
|
|
216 b = self.b # When b=1, the operation is byte mode
|
|
217 source = self.op1.regField()
|
|
218 destination = self.op2.regField()
|
|
219 h = (self.opcode << 12) | (source << 8)
|
|
220 h |= (self.b << 6) | (As << 4) | (Ad << 7) | destination
|
|
221 additions = self.op1.extraBytes() + self.op2.extraBytes()
|
|
222 return pack_ins(h) + additions
|
|
223
|
|
224 def decode(self, data):
|
|
225 pass
|
|
226
|
200
|
227
|
202
|
228 def twoOpIns(mne, opc):
|
|
229 """ Helper function to define a two operand arithmetic instruction """
|
|
230 members = {'mnemonic': mne, 'opcode': opc}
|
|
231 ins_cls = type(mne + '_ins', (TwoOpArith,), members)
|
|
232
|
341
|
233 class Mov(TwoOpArith):
|
|
234 """ Adds the source to the destination """
|
|
235 mnemonic = 'mov'
|
|
236 opcode = 4
|
202
|
237
|
|
238 # This is equivalent to the helper function twoOpIns:
|
200
|
239 class add_ins(TwoOpArith):
|
202
|
240 """ Adds the source to the destination """
|
200
|
241 mnemonic = 'add'
|
|
242 opcode = 5
|
199
|
243
|
202
|
244 def operate(self):
|
|
245 dst.value = dst.value + src.value
|
|
246 setFlags()
|
199
|
247
|
202
|
248 twoOpIns('addc', 6)
|
|
249 twoOpIns('subc', 7)
|
|
250 twoOpIns('sub', 8)
|
|
251 twoOpIns('cmp', 9)
|
|
252 twoOpIns('dadd', 10)
|
|
253 twoOpIns('bit', 11)
|
|
254 twoOpIns('bic', 12)
|
|
255 twoOpIns('bis', 13)
|
|
256 twoOpIns('xor', 14)
|
|
257 twoOpIns('and', 15)
|