342
|
1
|
|
2 from ..basetarget import Register, Instruction, Target
|
|
3 from ..token import Token, u16, bit_range
|
|
4 from .registers import Msp430Register
|
|
5
|
|
6
|
|
7 class Msp430Token(Token):
|
|
8 def __init__(self):
|
|
9 super().__init__(16)
|
|
10
|
|
11 condition = bit_range(10, 13)
|
|
12 opcode = bit_range(12, 16)
|
|
13 register = bit_range(0, 4)
|
|
14 destination = bit_range(0, 4)
|
|
15 source = bit_range(8, 12)
|
|
16 bw = bit_range(6, 7) # TODO: actually a single bit!
|
|
17 Ad = bit_range(7, 8) # TODO: actually a single bit!
|
|
18 As = bit_range(4, 6)
|
|
19
|
|
20 def encode(self):
|
|
21 return u16(self.bit_value)
|
|
22
|
|
23 REGISTER_MODE = 1
|
|
24 SYMBOLIC_MODE = 3
|
|
25 ABSOLUTE_MODE = 4
|
|
26 #TODO: add more modes!
|
|
27 IMMEDIATE_MODE = 7
|
|
28
|
|
29 class Msp430Operand:
|
|
30 pass
|
|
31
|
|
32 class Msp430DestinationOperand(Msp430Operand):
|
|
33 def __init__(self, param):
|
|
34 if isinstance(param, Msp430Register):
|
|
35 self.reg = param.num
|
|
36 self.Ad = 0
|
|
37 else:
|
|
38 raise Exception()
|
|
39
|
|
40
|
|
41 class Msp430SourceOperand(Msp430Operand):
|
|
42 def __init__(self, param):
|
|
43 if isinstance(param, Msp430Register):
|
|
44 self.reg = param.num
|
|
45 self.As = 0
|
|
46 self.extra_bytes = bytes()
|
|
47 elif isinstance(param, int):
|
|
48 self.reg = 0
|
|
49 self.As = 3
|
|
50 self.extra_bytes = u16(param)
|
|
51 else:
|
|
52 raise Exception()
|
|
53
|
|
54
|
|
55 class Msp430Instruction(Instruction):
|
|
56 b = 0
|
|
57 def __init__(self):
|
|
58 self.token = Msp430Token()
|
|
59
|
|
60
|
|
61 class Reti(Msp430Instruction):
|
|
62 def encode(self):
|
|
63 self.token[0:16] = 0x1300
|
|
64 return self.token.encode()
|
|
65
|
|
66
|
|
67 #########################
|
|
68 # Jump instructions:
|
|
69 #########################
|
|
70
|
|
71 class JumpInstruction(Msp430Instruction):
|
|
72 def __init__(self, target):
|
|
73 super().__init__()
|
|
74 self.target = target
|
|
75
|
|
76 def encode(self):
|
|
77 self.token.condition = self.condition
|
|
78 self.token.offset = 0
|
|
79 self.token[13] = 1
|
|
80 return self.token.encode()
|
|
81
|
|
82 def relocations(self):
|
|
83 return [(self.target, 'msp_reloc')]
|
|
84
|
|
85
|
|
86 class Jnz(JumpInstruction):
|
|
87 condition = 0
|
|
88
|
|
89
|
|
90 class Jz(JumpInstruction):
|
|
91 condition = 1
|
|
92
|
|
93
|
|
94 class Jnc(JumpInstruction):
|
|
95 condition = 2
|
|
96
|
|
97
|
|
98 class Jc(JumpInstruction):
|
|
99 condition = 3
|
|
100
|
|
101
|
|
102 class Jn(JumpInstruction):
|
|
103 condition = 4
|
|
104
|
|
105
|
|
106 class Jge(JumpInstruction):
|
|
107 condition = 5
|
|
108
|
|
109
|
|
110 class Jl(JumpInstruction):
|
|
111 condition = 6
|
|
112
|
|
113
|
|
114 class Jmp(JumpInstruction):
|
|
115 condition = 7
|
|
116
|
|
117
|
|
118 #########################
|
|
119 # Single operand arithmatic:
|
|
120 #########################
|
|
121
|
|
122
|
|
123 class OneOpArith(Msp430Instruction):
|
|
124 def __init__(self, op1):
|
|
125 self.op1 = op1
|
|
126
|
|
127 def encode(self):
|
|
128 # TODO:
|
|
129 bits[15:10] = '00100'
|
|
130 h1 = (self.opcode << 4)
|
|
131 return pack_ins(h1)
|
|
132
|
|
133
|
|
134 def oneOpIns(mne, opc):
|
|
135 """ Helper function to define a one operand arithmetic instruction """
|
|
136 members = {'opcode': opc}
|
|
137 ins_cls = type(mne + '_ins', (OneOpArith,), members)
|
|
138
|
|
139
|
|
140 oneOpIns('rrc', 0)
|
|
141 oneOpIns('swpb', 1)
|
|
142 oneOpIns('rra', 2)
|
|
143 oneOpIns('sxt', 3)
|
|
144 oneOpIns('push', 4)
|
|
145 oneOpIns('call', 5)
|
|
146
|
|
147
|
|
148 #########################
|
|
149 # Two operand arithmatic instructions:
|
|
150 #########################
|
|
151
|
|
152
|
|
153 class TwoOpArith(Msp430Instruction):
|
|
154 def __init__(self, src, dst):
|
|
155 super().__init__()
|
|
156 self.src = Msp430SourceOperand(src)
|
|
157 self.dst = Msp430DestinationOperand(dst)
|
|
158
|
|
159 def encode(self):
|
|
160 """
|
|
161 Smart things have been done by MSP430 designers.
|
|
162 As (2 bits) is the source addressing mode selector.
|
|
163 Ad (1 bit) is the destination adressing mode selector.
|
|
164 For the source there are 7 different addressing mode.
|
|
165 For the destination there are 4.
|
|
166 The trick is to use also the register to distuingish the
|
|
167 different modes.
|
|
168 """
|
|
169 # TODO: Make memory also possible
|
|
170 self.token.bw = self.b # When b=1, the operation is byte mode
|
|
171 self.token.As = self.src.As
|
|
172 self.token.Ad = self.dst.Ad
|
|
173 self.token.destination = self.dst.reg
|
|
174 self.token.source = self.src.reg
|
|
175 self.token.opcode = self.opcode
|
|
176 return self.token.encode() + self.src.extra_bytes
|
|
177
|
|
178
|
|
179 def twoOpIns(mne, opc):
|
|
180 """ Helper function to define a two operand arithmetic instruction """
|
|
181 members = {'opcode': opc}
|
|
182 ins_cls = type(mne + '_ins', (TwoOpArith,), members)
|
|
183
|
|
184
|
|
185 class Mov(TwoOpArith):
|
|
186 """ Moves the source to the destination """
|
|
187 opcode = 4
|
|
188
|
|
189
|
|
190 # This is equivalent to the helper function twoOpIns:
|
|
191 class Add(TwoOpArith):
|
|
192 """ Adds the source to the destination """
|
|
193 mnemonic = 'add'
|
|
194 opcode = 5
|
|
195
|
|
196
|
|
197 twoOpIns('addc', 6)
|
|
198 twoOpIns('subc', 7)
|
|
199 twoOpIns('sub', 8)
|
|
200
|
|
201
|
|
202 class Cmp(TwoOpArith):
|
|
203 opcode = 9
|
|
204
|
|
205
|
|
206 twoOpIns('dadd', 10)
|
|
207 twoOpIns('bit', 11)
|
|
208 twoOpIns('bic', 12)
|
|
209 twoOpIns('bis', 13)
|
|
210 twoOpIns('xor', 14)
|
|
211 twoOpIns('and', 15)
|