Mercurial > lcfOS
comparison python/msp430.py @ 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 |
comparison
equal
deleted
inserted
replaced
200:5e391d9a3381 | 201:d5debbfc0200 |
---|---|
1 from target import Register, Instruction, Target | 1 from target import Register, Instruction, Target |
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) | |
2 | 29 |
3 # Target description for the MSP430 processor | 30 # Target description for the MSP430 processor |
4 | 31 |
5 class MSP430Reg(Register): | 32 class MSP430Reg(Register): |
6 def __init__(self, num, name): | 33 def __init__(self, num, name): |
7 super().__init__(name) | 34 super().__init__(name) |
8 self.num = num | 35 self.num = num |
9 | 36 |
10 # 8 bit registers: | 37 # 8 bit registers: |
11 PCB = MSP430Reg(0, 'r0') | 38 PCB = MSP430Reg(0, 'r0') |
39 rpc = PCB | |
40 r11 = MSP430Reg(11, 'r11') | |
41 r12 = MSP430Reg(12, 'r12') | |
12 r13 = MSP430Reg(13, 'r13') | 42 r13 = MSP430Reg(13, 'r13') |
13 r14 = MSP430Reg(14, 'r14') | 43 r14 = MSP430Reg(14, 'r14') |
14 r15 = MSP430Reg(15, 'r15') | 44 r15 = MSP430Reg(15, 'r15') |
15 | 45 |
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 | |
16 # .. etc | 55 # .. etc |
17 | 56 |
18 #GR8 = RegisterClass((PCB, R15B)) | 57 #GR8 = RegisterClass((PCB, R15B)) |
19 | 58 |
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 | |
83 | |
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): | |
111 self.op1 = op1 | |
112 def encode(self): | |
113 # TODO: | |
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 | |
174 | |
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 ######################### | |
20 # Two operand arithmatic instructions: | 201 # Two operand arithmatic instructions: |
21 | 202 ######################### |
22 class TwoOpArith(Instruction): | 203 |
23 operands = (MSP430Reg, MSP430Reg) | 204 |
24 def __init__(self, op1, op2): | 205 class TwoOpArith(MSP430Instruction): |
25 self.op1 = op1 | 206 operands = (MSP430Operand, MSP430Operand) |
26 self.op2 = op2 | 207 def __init__(self, src, dst): |
27 def encode(self): | 208 self.op1 = src |
28 # TODO: | 209 self.op2 = dst |
29 b1 = (self.opcode << 4) | 210 |
30 b2 = 0 | 211 def encode(self): |
31 ba = bytearray([b1, b2]) | 212 """ |
32 return bytes(ba) | 213 Smart things have been done by MSP430 designers. |
33 | 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 | |
34 class mov_ins(TwoOpArith): | 238 class mov_ins(TwoOpArith): |
35 # class variables: | |
36 mnemonic = 'mov' | 239 mnemonic = 'mov' |
37 opcode = 4 | 240 opcode = 4 |
38 | 241 |
242 @msp430target.instruction | |
39 class add_ins(TwoOpArith): | 243 class add_ins(TwoOpArith): |
40 mnemonic = 'add' | 244 mnemonic = 'add' |
41 opcode = 5 | 245 opcode = 5 |
42 | 246 |
43 class MSP430(Target): | 247 @msp430target.instruction |
44 def __init__(self): | 248 class addc_ins(TwoOpArith): |
45 self.registers = [PCB, r13, r14, r15] | 249 mnemonic = 'addc' |
46 self.instructions = [mov_ins, add_ins] | 250 opcode = 6 |
47 | 251 |
48 t = MSP430() | 252 @msp430target.instruction |
49 | 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 | |
267 | |
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 | |
283 | |
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 |