199
|
1 from target import Register, Instruction, Target
|
201
|
2 from asmnodes import ASymbol, ANumber
|
|
3 from ppci import CompilerError
|
|
4 import struct, types
|
|
5
|
|
6 # Create the target class (singleton):
|
|
7 msp430target = Target("MSP430")
|
|
8
|
|
9 REGISTER_MODE = 1
|
|
10 #TODO: add more modes!
|
|
11 IMMEDIATE_MODE = 7
|
|
12
|
|
13 # Add a custom operand mapping method:
|
|
14 def mapOp(self, operand):
|
|
15 if type(operand) is ASymbol:
|
|
16 # try to map to register:
|
|
17 regs = {}
|
|
18 for r in self.registers:
|
|
19 regs[r.name] = r
|
|
20 if operand.name in regs:
|
|
21 reg = regs[operand.name]
|
|
22 return MSP430Operand(REGISTER_MODE, reg.num)
|
|
23 elif type(operand) is ANumber:
|
|
24 # Immediate mode:
|
|
25 return MSP430Operand(IMMEDIATE_MODE, operand.number)
|
|
26 raise CompilerError('Cannot map {0}'.format(operand))
|
|
27
|
|
28 msp430target.mapOperand = types.MethodType(mapOp, msp430target)
|
199
|
29
|
|
30 # Target description for the MSP430 processor
|
|
31
|
|
32 class MSP430Reg(Register):
|
|
33 def __init__(self, num, name):
|
|
34 super().__init__(name)
|
|
35 self.num = num
|
|
36
|
200
|
37 # 8 bit registers:
|
199
|
38 PCB = MSP430Reg(0, 'r0')
|
201
|
39 rpc = PCB
|
|
40 r11 = MSP430Reg(11, 'r11')
|
|
41 r12 = MSP430Reg(12, 'r12')
|
200
|
42 r13 = MSP430Reg(13, 'r13')
|
|
43 r14 = MSP430Reg(14, 'r14')
|
|
44 r15 = MSP430Reg(15, 'r15')
|
199
|
45
|
201
|
46 class MSP430Mem:
|
|
47 pass
|
|
48
|
|
49 msp430target.registers.append(r11)
|
|
50 msp430target.registers.append(r12)
|
|
51 msp430target.registers.append(r13)
|
|
52 msp430target.registers.append(r14)
|
|
53 msp430target.registers.append(r15)
|
|
54
|
199
|
55 # .. etc
|
|
56
|
|
57 #GR8 = RegisterClass((PCB, R15B))
|
|
58
|
201
|
59 class MSP430Operand:
|
|
60 def __init__(self, mode, param):
|
|
61 self.mode = mode
|
|
62 self.param = param
|
|
63 def regField(self):
|
|
64 if self.mode == REGISTER_MODE:
|
|
65 return self.param
|
|
66 elif self.mode == IMMEDIATE_MODE:
|
|
67 return rpc.num
|
|
68 def asField(self):
|
|
69 if self.mode == REGISTER_MODE:
|
|
70 return 0
|
|
71 elif self.mode == IMMEDIATE_MODE:
|
|
72 return 3
|
|
73 def adField(self):
|
|
74 if self.mode == REGISTER_MODE:
|
|
75 return 0
|
|
76 elif self.mode == IMMEDIATE_MODE:
|
|
77 raise CompilerError('Cannot use immediate mode for destination operand')
|
|
78 def extraBytes(self):
|
|
79 if self.mode == IMMEDIATE_MODE:
|
|
80 return pack_ins(self.param)
|
|
81 return bytes()
|
|
82
|
200
|
83
|
201
|
84 def pack_ins(h):
|
|
85 return struct.pack('<H', h)
|
|
86
|
|
87 class MSP430Instruction(Instruction):
|
|
88 b = 0
|
|
89
|
|
90 class BInstruction:
|
|
91 pass
|
|
92
|
|
93 class MSP430CoreInstruction(Instruction):
|
|
94 pass
|
|
95
|
|
96 #########################
|
|
97 # Single operand arithmatic:
|
|
98 #########################
|
|
99
|
|
100 @msp430target.instruction
|
|
101 class reti_ins(MSP430Instruction):
|
|
102 mnemonic = 'reti'
|
|
103 operands = ()
|
|
104 def encode(self):
|
|
105 h = 0x1300
|
|
106 return pack_ins(h)
|
|
107
|
|
108 class OneOpArith(MSP430Instruction):
|
|
109 operands = (MSP430Reg, )
|
|
110 def __init__(self, op1):
|
200
|
111 self.op1 = op1
|
|
112 def encode(self):
|
|
113 # TODO:
|
201
|
114 bits[15:10] = '00100'
|
|
115 h1 = (self.opcode << 4)
|
|
116 return pack_ins(h1)
|
|
117
|
|
118 @msp430target.instruction
|
|
119 class rrc_ins(OneOpArith):
|
|
120 mnemonic = 'rrc'
|
|
121 opcode = 0
|
|
122
|
|
123 @msp430target.instruction
|
|
124 class swpb_ins(OneOpArith):
|
|
125 mnemonic = 'swpb'
|
|
126 opcode = 1
|
|
127
|
|
128 @msp430target.instruction
|
|
129 class rra_ins(OneOpArith):
|
|
130 mnemonic = 'rra'
|
|
131 opcode = 2
|
|
132
|
|
133 @msp430target.instruction
|
|
134 class sxt_ins(OneOpArith):
|
|
135 mnemonic = 'sxt'
|
|
136 opcode = 3
|
|
137
|
|
138 @msp430target.instruction
|
|
139 class push_ins(OneOpArith):
|
|
140 mnemonic = 'push'
|
|
141 opcode = 4
|
|
142
|
|
143 @msp430target.instruction
|
|
144 class call_ins(OneOpArith):
|
|
145 mnemonic = 'call'
|
|
146 opcode = 5
|
|
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 @msp430target.instruction
|
|
161 class jnz_ins(JumpInstruction):
|
|
162 mnemonic = 'jnz'
|
|
163 condition = 0
|
|
164
|
|
165 @msp430target.instruction
|
|
166 class jz_ins(JumpInstruction):
|
|
167 mnemonic = 'jz'
|
|
168 condition = 1
|
|
169
|
|
170 @msp430target.instruction
|
|
171 class jnc_ins(JumpInstruction):
|
|
172 mnemonic = 'jnc'
|
|
173 condition = 2
|
199
|
174
|
201
|
175 @msp430target.instruction
|
|
176 class jc_ins(JumpInstruction):
|
|
177 mnemonic = 'jc'
|
|
178 condition = 3
|
|
179
|
|
180 @msp430target.instruction
|
|
181 class jn_ins(JumpInstruction):
|
|
182 mnemonic = 'jn'
|
|
183 condition = 4
|
|
184
|
|
185 @msp430target.instruction
|
|
186 class jge_ins(JumpInstruction):
|
|
187 mnemonic = 'jge'
|
|
188 condition = 5
|
|
189
|
|
190 @msp430target.instruction
|
|
191 class jl_ins(JumpInstruction):
|
|
192 mnemonic = 'jl'
|
|
193 condition = 6
|
|
194
|
|
195 @msp430target.instruction
|
|
196 class jmp_ins(JumpInstruction):
|
|
197 mnemonic = 'jmp'
|
|
198 condition = 7
|
|
199
|
|
200 #########################
|
|
201 # Two operand arithmatic instructions:
|
|
202 #########################
|
|
203
|
|
204
|
|
205 class TwoOpArith(MSP430Instruction):
|
|
206 operands = (MSP430Operand, MSP430Operand)
|
|
207 def __init__(self, src, dst):
|
|
208 self.op1 = src
|
|
209 self.op2 = dst
|
|
210
|
|
211 def encode(self):
|
|
212 """
|
|
213 Smart things have been done by MSP430 designers.
|
|
214 As (2 bits) is the source addressing mode selector.
|
|
215 Ad (1 bit) is the destination adressing mode selector.
|
|
216 For the source there are 7 different addressing mode.
|
|
217 For the destination there are 4.
|
|
218 The trick is to use also the register to distuingish the
|
|
219 different modes.
|
|
220
|
|
221 """
|
|
222 # TODO: Make memory also possible
|
|
223
|
|
224 As = self.op1.asField() # addressing mode for the source
|
|
225 Ad = self.op2.adField() # Addressing mode for dst
|
|
226 b = self.b # When b=1, the operation is byte mode
|
|
227 source = self.op1.regField()
|
|
228 destination = self.op2.regField()
|
|
229 h = (self.opcode << 12) | (source << 8)
|
|
230 h |= (self.b << 6) | (As << 4) | (Ad << 7) | destination
|
|
231 additions = self.op1.extraBytes() + self.op2.extraBytes()
|
|
232 return pack_ins(h) + additions
|
|
233
|
|
234 def decode(self, data):
|
|
235 pass
|
|
236
|
|
237 @msp430target.instruction
|
200
|
238 class mov_ins(TwoOpArith):
|
|
239 mnemonic = 'mov'
|
|
240 opcode = 4
|
|
241
|
201
|
242 @msp430target.instruction
|
200
|
243 class add_ins(TwoOpArith):
|
|
244 mnemonic = 'add'
|
|
245 opcode = 5
|
199
|
246
|
201
|
247 @msp430target.instruction
|
|
248 class addc_ins(TwoOpArith):
|
|
249 mnemonic = 'addc'
|
|
250 opcode = 6
|
|
251
|
|
252 @msp430target.instruction
|
|
253 class subc_ins(TwoOpArith):
|
|
254 mnemonic = 'subc'
|
|
255 opcode = 7
|
|
256
|
|
257 @msp430target.instruction
|
|
258 class sub_ins(TwoOpArith):
|
|
259 mnemonic = 'sub'
|
|
260 opcode = 8
|
|
261
|
|
262 @msp430target.instruction
|
|
263 class cmp_ins(TwoOpArith):
|
|
264 """ Compare, substract source from destination """
|
|
265 mnemonic = 'cmp'
|
|
266 opcode = 9
|
199
|
267
|
201
|
268 @msp430target.instruction
|
|
269 class dadd_ins(TwoOpArith):
|
|
270 """ Decimal add source to destination """
|
|
271 mnemonic = 'dadd'
|
|
272 opcode = 10
|
|
273
|
|
274 @msp430target.instruction
|
|
275 class bit_ins(TwoOpArith):
|
|
276 mnemonic = 'bit'
|
|
277 opcode = 11
|
|
278
|
|
279 @msp430target.instruction
|
|
280 class bic_ins(TwoOpArith):
|
|
281 mnemonic = 'bic'
|
|
282 opcode = 12
|
199
|
283
|
201
|
284 @msp430target.instruction
|
|
285 class bis_ins(TwoOpArith):
|
|
286 mnemonic = 'bis'
|
|
287 opcode = 13
|
|
288
|
|
289 @msp430target.instruction
|
|
290 class xor_ins(TwoOpArith):
|
|
291 mnemonic = 'xor'
|
|
292 opcode = 14
|
|
293
|
|
294 @msp430target.instruction
|
|
295 class and_ins(TwoOpArith):
|
|
296 mnemonic = 'and'
|
|
297 opcode = 15
|
|
298
|