Mercurial > lcfOS
comparison python/ppci/target/arm/instructions.py @ 347:742588fb8cd6 devel
Merge into devel branch
author | Windel Bouwman |
---|---|
date | Fri, 07 Mar 2014 17:10:21 +0100 |
parents | 3bb7dcfe5529 |
children | 2b02bd286fe9 |
comparison
equal
deleted
inserted
replaced
343:11c5a8a70c02 | 347:742588fb8cd6 |
---|---|
1 | |
2 | 1 |
3 from ..basetarget import Instruction | 2 from ..basetarget import Instruction |
3 from ...bitfun import rotate_left | |
4 | 4 |
5 from .token import ArmToken | 5 from .token import ArmToken |
6 from .registers import R0, SP | 6 from .registers import R0, SP, ArmRegister |
7 | 7 |
8 | |
9 def encode_imm32(v): | |
10 """ Bundle 32 bit value into 4 bits rotation and 8 bits value | |
11 """ | |
12 for i in range(0, 16): | |
13 v2 = rotate_left(v, i*2) | |
14 if (v2 & 0xFFFFFF00) == 0: | |
15 rotation = i | |
16 val = v2 & 0xFF | |
17 x = (rotation << 8) | val | |
18 return x | |
19 raise Exception("Invalid value {}".format(v)) | |
8 | 20 |
9 # Instructions: | 21 # Instructions: |
10 | 22 |
11 class ArmInstruction(Instruction): | 23 class ArmInstruction(Instruction): |
12 def __init__(self): | 24 def __init__(self): |
13 self.token = ArmToken() | 25 self.token = ArmToken() |
14 | 26 |
15 | 27 |
16 class Mov(ArmInstruction): | 28 class Dcd(ArmInstruction): |
29 def __init__(self, v): | |
30 super().__init__() | |
31 self.v = v | |
32 | |
33 def encode(self): | |
34 self.token[0:32] = self.v | |
35 return self.token.encode() | |
36 | |
37 | |
38 def Mov(*args): | |
39 if len(args) == 2: | |
40 if isinstance(args[1], int): | |
41 return Mov1(*args) | |
42 elif isinstance(args[1], ArmRegister): | |
43 return Mov2(*args) | |
44 raise Exception() | |
45 | |
46 | |
47 class Mov1(ArmInstruction): | |
17 """ Mov Rd, imm16 """ | 48 """ Mov Rd, imm16 """ |
18 def __init__(self, reg, imm): | 49 def __init__(self, reg, imm): |
19 super().__init__() | 50 super().__init__() |
51 assert type(imm) is int | |
20 self.reg = reg | 52 self.reg = reg |
21 self.imm = imm | 53 self.imm = imm |
22 | 54 |
23 def encode(self): | 55 def encode(self): |
24 self.token[0:12] = self.imm | 56 self.token[0:12] = encode_imm32(self.imm) |
25 self.token[12:16] = self.reg.num | 57 self.token.Rd = self.reg.num |
26 self.token[16:20] = 0 | 58 self.token[16:20] = 0 |
27 self.token[20] = 0 | 59 self.token[20] = 0 # Set flags |
28 self.token[21:28] = 0b0011101 | 60 self.token[21:28] = 0b0011101 |
29 self.token.cond = 0xE # Always! | 61 self.token.cond = AL |
30 return self.token.encode() | 62 return self.token.encode() |
31 | 63 |
32 def relocations(self): | 64 def relocations(self): |
33 return [] | 65 return [] |
34 | 66 |
35 def __repr__(self): | 67 def __repr__(self): |
36 return 'DCD 0x{0:X}'.format(self.expr) | 68 return 'Mov {}, {}'.format(self.reg, self.imm) |
37 | 69 |
70 | |
71 class Mov2(ArmInstruction): | |
72 def __init__(self, rd, rm): | |
73 super().__init__() | |
74 self.rd = rd | |
75 self.rm = rm | |
76 | |
77 def encode(self): | |
78 self.token[0:4] = self.rm.num | |
79 self.token[4:12] = 0 | |
80 self.token[12:16] = self.rd.num | |
81 self.token[16:20] = 0 | |
82 self.token.S = 0 | |
83 self.token[21:28] = 0xD | |
84 self.token.cond = AL | |
85 return self.token.encode() | |
86 | |
87 | |
88 def Add(*args): | |
89 if len(args) == 3 and isinstance(args[0], ArmRegister) and \ | |
90 isinstance(args[1], ArmRegister): | |
91 if isinstance(args[2], ArmRegister): | |
92 return Add1(args[0], args[1], args[2]) | |
93 elif isinstance(args[2], int): | |
94 return Add2(args[0], args[1], args[2]) | |
95 raise Exception() | |
96 | |
97 def Sub(*args): | |
98 if len(args) == 3 and isinstance(args[0], ArmRegister) and \ | |
99 isinstance(args[1], ArmRegister): | |
100 if isinstance(args[2], ArmRegister): | |
101 return Sub1(args[0], args[1], args[2]) | |
102 elif isinstance(args[2], int): | |
103 return Sub2(args[0], args[1], args[2]) | |
104 raise Exception() | |
105 | |
106 def Mul(*args): | |
107 return Mul1(args[0], args[1], args[2]) | |
108 | |
109 | |
110 class Mul(ArmInstruction): | |
111 def __init__(self, rd, rn, rm): | |
112 super().__init__() | |
113 self.rd = rd | |
114 self.rn = rn | |
115 self.rm = rm | |
116 | |
117 def encode(self): | |
118 self.token[0:4] = self.rn.num | |
119 self.token[4:8] = 0b1001 | |
120 self.token[8:12] = self.rm.num | |
121 self.token[16:20] = self.rd.num | |
122 self.token.S = 0 | |
123 self.token.cond = AL | |
124 return self.token.encode() | |
125 | |
126 | |
127 class OpRegRegReg(ArmInstruction): | |
128 """ add rd, rn, rm """ | |
129 def __init__(self, rd, rn, rm, shift=0): | |
130 super().__init__() | |
131 self.rd = rd | |
132 self.rn = rn | |
133 self.rm = rm | |
134 | |
135 def encode(self): | |
136 self.token[0:4] = self.rm.num | |
137 self.token[4] = 0 | |
138 self.token[5:7] = 0 | |
139 self.token[7:12] = 0 # Shift | |
140 self.token.Rd = self.rd.num | |
141 self.token.Rn = self.rn.num | |
142 self.token.S = 0 # Set flags | |
143 self.token[21:28] = self.opcode | |
144 self.token.cond = 0xE # Always! | |
145 return self.token.encode() | |
146 | |
147 def __repr__(self): | |
148 return 'add {}, {}, {}'.format(self.rd, self.rn, self.rm) | |
149 | |
150 | |
151 class Add1(OpRegRegReg): | |
152 opcode = 0b0000100 | |
153 | |
154 | |
155 class Sub1(OpRegRegReg): | |
156 opcode = 0b0000010 | |
157 | |
158 | |
159 class Orr1(OpRegRegReg): | |
160 opcode = 0b0001100 | |
161 | |
162 | |
163 class OpRegRegImm(ArmInstruction): | |
164 """ add rd, rn, imm12 """ | |
165 def __init__(self, rd, rn, imm): | |
166 super().__init__() | |
167 self.rd = rd | |
168 self.rn = rn | |
169 self.imm2 = encode_imm32(imm) | |
170 self.imm = imm | |
171 | |
172 def encode(self): | |
173 self.token[0:12] = self.imm2 | |
174 self.token.Rd = self.rd.num | |
175 self.token.Rn = self.rn.num | |
176 self.token.S = 0 # Set flags | |
177 self.token[21:28] = self.opcode | |
178 self.token.cond = 0xE # Always! | |
179 return self.token.encode() | |
180 | |
181 def __repr__(self): | |
182 return 'add {}, {}, {}'.format(self.rd, self.rn, self.imm) | |
183 | |
184 | |
185 class Add2(OpRegRegImm): | |
186 opcode = 0b0010100 | |
187 | |
188 | |
189 class Sub2(OpRegRegImm): | |
190 opcode = 0b0010010 | |
191 | |
192 | |
193 | |
194 # Branches: | |
195 | |
196 class BranchBaseRoot(ArmInstruction): | |
197 def __init__(self, target): | |
198 super().__init__() | |
199 self.target = target | |
200 | |
201 def encode(self): | |
202 self.token.cond = self.cond | |
203 self.token[24:28] = self.opcode | |
204 return self.token.encode() | |
205 | |
206 def relocations(self): | |
207 return [(self.target, 'b_imm24')] | |
208 | |
209 | |
210 EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL = range(15) | |
211 | |
212 class BranchBase(BranchBaseRoot): | |
213 opcode = 0b1010 | |
214 | |
215 class BranchLinkBase(BranchBaseRoot): | |
216 opcode = 0b1011 | |
217 | |
218 class Bl(BranchLinkBase): | |
219 cond = AL | |
220 | |
221 class B(BranchBase): | |
222 cond = AL | |
223 | |
224 class Beq(BranchBase): | |
225 cond = EQ | |
226 | |
227 class Bgt(BranchBase): | |
228 cond = GT | |
229 | |
230 class Ble(BranchBase): | |
231 cond = LE | |
232 | |
233 class Blt(BranchBase): | |
234 cond = LT | |
235 | |
236 | |
237 # Memory: | |
238 | |
239 def reg_list_to_mask(reg_list): | |
240 mask = 0 | |
241 for reg in reg_list: | |
242 mask |= (1 << reg.num) | |
243 return mask | |
244 | |
245 | |
246 class Push(ArmInstruction): | |
247 def __init__(self, register_set): | |
248 super().__init__() | |
249 self.reg_list = register_set | |
250 | |
251 def encode(self): | |
252 self.token.cond = AL | |
253 self.token[16:28] = 0b100100101101 | |
254 reg_list = 0 | |
255 self.token[0:16] = reg_list_to_mask(self.reg_list) | |
256 return self.token.encode() | |
257 | |
258 class Pop(ArmInstruction): | |
259 def __init__(self, register_set): | |
260 super().__init__() | |
261 self.reg_list = register_set | |
262 | |
263 def encode(self): | |
264 self.token.cond = AL | |
265 self.token[16:28] = 0b100010111101 | |
266 self.token[0:16] = reg_list_to_mask(self.reg_list) | |
267 return self.token.encode() | |
268 | |
269 | |
270 def Ldr(*args): | |
271 if len(args) == 3 and isinstance(args[1], ArmRegister): | |
272 return Ldr1(*args) | |
273 elif len(args) == 2 and isinstance(args[1], ArmRegister): | |
274 return Ldr1(args[0], args[1], 0) | |
275 raise Exception() | |
276 | |
277 def Str(*args): | |
278 if len(args) == 3 and isinstance(args[1], ArmRegister): | |
279 return Str1(*args) | |
280 elif len(args) == 2 and isinstance(args[1], ArmRegister): | |
281 return Str1(args[0], args[1], 0) | |
282 raise Exception() | |
283 | |
284 | |
285 class LdrStrBase(ArmInstruction): | |
286 def __init__(self, rt, rn, offset): | |
287 super().__init__() | |
288 self.rt = rt | |
289 self.rn = rn | |
290 self.offset = offset | |
291 | |
292 def encode(self): | |
293 self.token.cond = AL | |
294 self.token.Rn = self.rn.num | |
295 self.token[25:28] = self.opcode | |
296 self.token[20] = self.bit20 | |
297 self.token[12:16] = self.rt.num | |
298 self.token[24] = 1 # Index | |
299 if self.offset >= 0: | |
300 self.token[23] = 1 # U == 1 'add' | |
301 self.token[0:12] = self.offset | |
302 else: | |
303 self.token[23] = 0 | |
304 self.token[0:12] = -self.offset | |
305 return self.token.encode() | |
306 | |
307 | |
308 class Str1(LdrStrBase): | |
309 opcode = 0b010 | |
310 bit20 = 0 | |
311 | |
312 | |
313 class Ldr1(LdrStrBase): | |
314 opcode = 0b010 | |
315 bit20 = 1 | |
316 | |
317 | |
318 class Ldr3(ArmInstruction): | |
319 """ Load PC relative constant value """ | |
320 def __init__(self, rt, label): | |
321 self.rt = rt | |
322 self.label = label | |
323 |