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