Mercurial > lcfOS
comparison python/target/arminstructions.py @ 341:4d204f6f7d4e devel
Rewrite of assembler parts
author | Windel Bouwman |
---|---|
date | Fri, 28 Feb 2014 18:07:14 +0100 |
parents | c7cc54c0dfdf |
children |
comparison
equal
deleted
inserted
replaced
340:c7cc54c0dfdf | 341:4d204f6f7d4e |
---|---|
1 import struct | 1 import struct |
2 from ppci.asmnodes import ASymbol, AInstruction, ANumber, AUnop, ABinop | 2 from ppci.asmnodes import ASymbol, AInstruction, ANumber, AUnop, ABinop |
3 from .basetarget import Register, Instruction, Target, Label, LabelRef | 3 from .basetarget import Register, Instruction, Target, Label, LabelRef |
4 from .basetarget import Imm32, Imm8, Imm7, Imm3 | 4 from .basetarget import Imm32, Imm8, Imm7, Imm3 |
5 | 5 |
6 from .armtokens import ThumbToken, ArmToken | 6 from .armtoken import ThumbToken, ArmToken |
7 from .armregisters import R0 | 7 from .armregisters import R0, ArmRegister, SP |
8 | 8 |
9 def add_rule(rhs, f): | 9 |
10 pass | |
11 | 10 |
12 def u16(h): | 11 def u16(h): |
13 return struct.pack('<H', h) | 12 return struct.pack('<H', h) |
14 | 13 |
15 def u32(x): | 14 def u32(x): |
16 return struct.pack('<I', x) | 15 return struct.pack('<I', x) |
17 | 16 |
18 | 17 |
19 thumb_assembly_rules = [] | |
20 arm_assembly_rules = [] | 18 arm_assembly_rules = [] |
21 | 19 |
22 | 20 |
23 # Operands: | 21 # Operands: |
24 | 22 |
53 return y.number | 51 return y.number |
54 elif type(y) is ASymbol and type(x) is ANumber and y.name.upper() == regname: | 52 elif type(y) is ASymbol and type(x) is ANumber and y.name.upper() == regname: |
55 return x.number | 53 return x.number |
56 | 54 |
57 | 55 |
58 class MemRegXRel: | |
59 def __init__(self, offset): | |
60 assert offset % 4 == 0 | |
61 self.offset = offset | |
62 | |
63 def __repr__(self): | |
64 return '[{}, #{}]'.format(self.regname, self.offset) | |
65 | |
66 @classmethod | |
67 def Create(cls, vop): | |
68 if type(vop) is AUnop and vop.operation == '[]' and type(vop.arg) is ABinop and vop.arg.op == '+': | |
69 vop = vop.arg # descent | |
70 offset = isRegOffset(cls.regname, vop.arg1, vop.arg2) | |
71 if type(offset) is int: | |
72 if offset % 4 == 0: | |
73 offset = vop.arg2.number | |
74 return cls(offset) | |
75 elif type(vop) is ASymbol and vop.name.upper() == self.regname: | |
76 return cls(0) | |
77 | |
78 | |
79 class MemSpRel(MemRegXRel): | |
80 regname = 'SP' | |
81 | |
82 | |
83 class MemR8Rel: | |
84 def __init__(self, basereg, offset): | |
85 assert type(basereg) is Reg8Op | |
86 assert type(offset) is int | |
87 self.basereg = basereg | |
88 self.offset = offset | |
89 | |
90 def __repr__(self): | |
91 return '[{}, #{}]'.format(self.basereg, self.offset) | |
92 | |
93 @classmethod | |
94 def Create(cls, vop): | |
95 if type(vop) is AUnop and vop.operation == '[]': | |
96 vop = vop.arg # descent | |
97 if type(vop) is ABinop: | |
98 if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: | |
99 offset = vop.arg2.number | |
100 if offset > 120: | |
101 return | |
102 basereg = Reg8Op.Create(vop.arg1) | |
103 if not basereg: | |
104 return | |
105 else: | |
106 return | |
107 elif type(vop) is ASymbol: | |
108 offset = 0 | |
109 basereg = Reg8Op.Create(vop) | |
110 if not basereg: | |
111 return | |
112 else: | |
113 return | |
114 return cls(getRegNum(basereg.num), offset) | |
115 | |
116 | |
117 class RegisterSet: | |
118 def __init__(self, regs): | |
119 assert type(regs) is set | |
120 self.regs = regs | |
121 | |
122 def __repr__(self): | |
123 return ','.join([str(r) for r in self.regs]) | |
124 | |
125 @classmethod | |
126 def Create(cls, vop): | |
127 assert type(vop) is AUnop and vop.operation == '{}' | |
128 assert type(vop.arg) is list | |
129 regs = set() | |
130 for arg in vop.arg: | |
131 if type(arg) is ASymbol: | |
132 reg = ArmRegister.Create(arg) | |
133 if not reg: | |
134 return | |
135 regs.add(reg) | |
136 elif type(arg) is ABinop and arg.op == '-': | |
137 reg1 = ArmRegister.Create(arg.arg1) | |
138 reg2 = ArmRegister.Create(arg.arg2) | |
139 if not reg1: | |
140 return | |
141 if not reg2: | |
142 return | |
143 for r in getRegisterRange(reg1, reg2): | |
144 regs.add(r) | |
145 else: | |
146 raise Exception('Cannot be') | |
147 return cls(regs) | |
148 | |
149 def registerNumbers(self): | |
150 return [r.num for r in self.regs] | |
151 | |
152 | |
153 | 56 |
154 # Instructions: | 57 # Instructions: |
155 | 58 |
156 class ArmInstruction(Instruction): | 59 class ThumbInstruction(Instruction): |
157 pass | 60 pass |
158 | 61 |
159 | 62 |
160 allins = [] | 63 |
161 | 64 class Dcd(ThumbInstruction): |
162 | |
163 def instruction(i): | |
164 allins.append(i) | |
165 return i | |
166 | |
167 add_rule(['dcd', 'imm32'], lambda rhs: Dcd(rhs[1])) | |
168 | |
169 class Dcd(ArmInstruction): | |
170 mnemonic = 'dcd' | |
171 operands = (Imm32,) | |
172 def __init__(self, expr): | 65 def __init__(self, expr): |
173 if isinstance(expr, Imm32): | 66 if isinstance(expr, Imm32): |
174 self.expr = expr.imm | 67 self.expr = expr.imm |
175 self.label = None | 68 self.label = None |
176 elif isinstance(expr, LabelRef): | 69 elif isinstance(expr, LabelRef): |
191 | 84 |
192 def __repr__(self): | 85 def __repr__(self): |
193 return 'DCD 0x{0:X}'.format(self.expr) | 86 return 'DCD 0x{0:X}'.format(self.expr) |
194 | 87 |
195 | 88 |
196 @instruction | 89 class nop_ins(ThumbInstruction): |
197 class nop_ins(ArmInstruction): | |
198 mnemonic = 'nop' | |
199 operands = tuple() | |
200 | |
201 def encode(self): | 90 def encode(self): |
202 return bytes() | 91 return bytes() |
203 | 92 |
204 def __repr__(self): | 93 def __repr__(self): |
205 return 'NOP' | 94 return 'NOP' |
206 | 95 |
207 | 96 |
208 # Memory related | 97 # Memory related |
209 | 98 |
210 class LS_imm5_base(ArmInstruction): | 99 class LS_imm5_base(ThumbInstruction): |
211 """ ??? Rt, [Rn, imm5] """ | 100 """ ??? Rt, [Rn, imm5] """ |
212 operands = (Reg8Op, MemR8Rel) | 101 def __init__(self, rt, rn, imm5): |
213 def __init__(self, rt, memop): | 102 assert imm5 % 4 == 0 |
214 assert memop.offset % 4 == 0 | 103 self.imm5 = imm5 >> 2 |
215 self.imm5 = memop.offset >> 2 | 104 self.rn = rn |
216 self.rn = memop.basereg.num | |
217 self.rt = rt | 105 self.rt = rt |
218 self.memloc = memop | 106 assert self.rn.num < 8 |
219 assert self.rn < 8 | |
220 assert self.rt.num < 8 | 107 assert self.rt.num < 8 |
221 | 108 self.token = ThumbToken() |
222 def encode(self): | 109 |
223 Rn = self.rn | 110 def encode(self): |
111 Rn = self.rn.num | |
224 Rt = self.rt.num | 112 Rt = self.rt.num |
225 imm5 = self.imm5 | 113 imm5 = self.imm5 |
226 | 114 self.token[0:3] = Rt |
227 h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt | 115 self.token[3:6] = Rn |
228 return u16(h) | 116 self.token[6:11] = imm5 |
229 | 117 self.token[11:16] = self.opcode |
230 | 118 return self.token.encode() |
231 def __repr__(self): | 119 |
232 return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) | 120 def __repr__(self): |
233 | 121 mnemonic = "???" |
234 | 122 return '{} {}, [{}, {}]'.format(mnemonic, self.rt, self.rn, self.imm5) |
235 @instruction | 123 |
124 | |
236 class Str2(LS_imm5_base): | 125 class Str2(LS_imm5_base): |
237 mnemonic = 'STR' | |
238 opcode = 0xC | 126 opcode = 0xC |
239 | 127 |
240 @classmethod | 128 @classmethod |
241 def fromim(cls, im): | 129 def fromim(cls, im): |
242 mem = MemR8Rel(im.src[0], im.others[0]) | 130 return cls(im.src[1], im.src[0], im.others[0]) |
243 return cls(im.src[1], mem) | 131 |
244 | 132 |
245 | |
246 @instruction | |
247 class Ldr2(LS_imm5_base): | 133 class Ldr2(LS_imm5_base): |
248 mnemonic = 'LDR' | |
249 opcode = 0xD | 134 opcode = 0xD |
250 | 135 |
251 @classmethod | 136 @classmethod |
252 def fromim(cls, im): | 137 def fromim(cls, im): |
253 mem = MemR8Rel(im.src[0], im.others[0]) | 138 return cls(im.dst[0], im.src[0], im.others[0]) |
254 return cls(im.dst[0], mem) | 139 |
255 | 140 class ls_sp_base_imm8(ThumbInstruction): |
256 class ls_sp_base_imm8(ArmInstruction): | 141 def __init__(self, rt, offset): |
257 operands = (Reg8Op, MemSpRel) | |
258 def __init__(self, rt, memop): | |
259 self.rt = rt | 142 self.rt = rt |
260 self.offset = memop.offset | 143 self.offset = offset |
261 | 144 |
262 def encode(self): | 145 def encode(self): |
263 rt = self.rt.num | 146 rt = self.rt.num |
264 assert rt < 8 | 147 assert rt < 8 |
265 imm8 = self.offset >> 2 | 148 imm8 = self.offset >> 2 |
266 assert imm8 < 256 | 149 assert imm8 < 256 |
267 h = (self.opcode << 8) | (rt << 8) | imm8 | 150 h = (self.opcode << 8) | (rt << 8) | imm8 |
268 return u16(h) | 151 return u16(h) |
269 | 152 |
270 def __repr__(self): | 153 def __repr__(self): |
271 return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) | 154 mnemonic = self.__class__.__name__ |
155 return '{} {}, [sp,#{}]'.format(mnemonic, self.rt, self.offset) | |
272 | 156 |
273 def align(x, m): | 157 def align(x, m): |
274 while ((x % m) != 0): | 158 while ((x % m) != 0): |
275 x = x + 1 | 159 x = x + 1 |
276 return x | 160 return x |
277 | 161 |
278 | 162 def Ldr(*args): |
279 @instruction | 163 if len(args) == 2 and isinstance(args[0], ArmRegister) \ |
280 class Ldr3(ArmInstruction): | 164 and isinstance(args[1], str): |
165 return Ldr3(*args) | |
166 else: | |
167 raise Exception() | |
168 | |
169 | |
170 class Ldr3(ThumbInstruction): | |
281 """ ldr Rt, LABEL, load value from pc relative position """ | 171 """ ldr Rt, LABEL, load value from pc relative position """ |
282 mnemonic = 'ldr' | 172 mnemonic = 'ldr' |
283 operands = (Reg8Op, LabelRef) | |
284 def __init__(self, rt, label): | 173 def __init__(self, rt, label): |
285 assert isinstance(label, LabelRef) | |
286 self.rt = rt | 174 self.rt = rt |
287 self.label = label | 175 self.label = label |
288 self.offset = 0 | |
289 | 176 |
290 @classmethod | 177 @classmethod |
291 def fromim(cls, im): | 178 def fromim(cls, im): |
292 return cls(im.dst[0], im.others[0]) | 179 return cls(im.dst[0], im.others[0]) |
293 | 180 |
294 def relocations(self): | 181 def relocations(self): |
295 return [(self.label.name, 'lit_add_8')] | 182 return [(self.label, 'lit_add_8')] |
296 | 183 |
297 def encode(self): | 184 def encode(self): |
298 rt = self.rt.num | 185 rt = self.rt.num |
299 assert rt < 8 | 186 assert rt < 8 |
300 assert self.offset % 4 == 0 | 187 imm8 = 0 |
301 imm8 = self.offset >> 2 | |
302 assert imm8 < 256 | |
303 assert imm8 >= 0 | |
304 h = (0x9 << 11) | (rt << 8) | imm8 | 188 h = (0x9 << 11) | (rt << 8) | imm8 |
305 return u16(h) | 189 return u16(h) |
306 | 190 |
307 def __repr__(self): | 191 def __repr__(self): |
308 return 'LDR {}, {}'.format(self.rt, self.label.name) | 192 return 'LDR {}, {}'.format(self.rt, self.label) |
309 | 193 |
310 | 194 |
311 @instruction | |
312 class Ldr1(ls_sp_base_imm8): | 195 class Ldr1(ls_sp_base_imm8): |
313 """ ldr Rt, [SP, imm8] """ | 196 """ ldr Rt, [SP, imm8] """ |
314 mnemonic = 'LDR' | |
315 opcode = 0x98 | 197 opcode = 0x98 |
316 | 198 |
317 | 199 |
318 @instruction | |
319 class Str1(ls_sp_base_imm8): | 200 class Str1(ls_sp_base_imm8): |
320 """ str Rt, [SP, imm8] """ | 201 """ str Rt, [SP, imm8] """ |
321 mnemonic = 'STR' | |
322 opcode = 0x90 | 202 opcode = 0x90 |
323 | 203 |
324 | 204 |
325 @instruction | 205 class Mov3(ThumbInstruction): |
326 class Mov3(ArmInstruction): | |
327 """ mov Rd, imm8, move immediate value into register """ | 206 """ mov Rd, imm8, move immediate value into register """ |
328 mnemonic = 'mov' | |
329 opcode = 4 # 00100 Rd(3) imm8 | 207 opcode = 4 # 00100 Rd(3) imm8 |
330 operands = (Reg8Op, Imm8) | |
331 def __init__(self, rd, imm): | 208 def __init__(self, rd, imm): |
332 if type(imm) is int: | 209 assert imm < 256 |
333 imm = Imm8(imm) | 210 self.imm = imm |
334 assert type(imm) is Imm8 | |
335 self.imm = imm.imm | |
336 assert type(rd) is Reg8Op, str(type(rd)) | |
337 self.rd = rd | 211 self.rd = rd |
212 self.token = ThumbToken() | |
338 | 213 |
339 @classmethod | 214 @classmethod |
340 def fromim(cls, im): | 215 def fromim(cls, im): |
341 return cls(im.dst[0], im.others[0]) | 216 return cls(im.dst[0], im.others[0]) |
342 | 217 |
343 def encode(self): | 218 def encode(self): |
344 rd = self.rd.num | 219 rd = self.rd.num |
345 opcode = self.opcode | 220 self.token[8:11] = rd |
346 imm8 = self.imm | 221 self.token[0:8] = self.imm |
347 h = (opcode << 11) | (rd << 8) | imm8 | 222 self.token[11:16] = self.opcode |
348 return u16(h) | 223 return self.token.encode() |
349 | 224 |
350 def __repr__(self): | 225 def __repr__(self): |
351 return 'MOV {}, {}'.format(self.rd, self.imm) | 226 return 'MOV {}, {}'.format(self.rd, self.imm) |
352 | 227 |
353 | 228 |
354 | 229 |
355 # Arithmatics: | 230 # Arithmatics: |
356 | 231 |
357 | 232 |
358 | 233 |
359 class regregimm3_base(ArmInstruction): | 234 class regregimm3_base(ThumbInstruction): |
360 operands = (Reg8Op, Reg8Op, Imm3) | |
361 def __init__(self, rd, rn, imm3): | 235 def __init__(self, rd, rn, imm3): |
362 self.rd = rd | 236 self.rd = rd |
363 self.rn = rn | 237 self.rn = rn |
364 assert type(imm3) is Imm3 | 238 assert imm3 < 8 |
365 self.imm3 = imm3 | 239 self.imm3 = imm3 |
240 self.token = ThumbToken() | |
366 | 241 |
367 @classmethod | 242 @classmethod |
368 def fromim(cls, im): | 243 def fromim(cls, im): |
369 return cls(im.dst[0], im.src[0], im.others[0]) | 244 return cls(im.dst[0], im.src[0], im.others[0]) |
370 | 245 |
371 def encode(self): | 246 def encode(self): |
372 rd = self.rd.num | 247 rd = self.rd.num |
373 rn = self.rn.num | 248 self.token[0:3] = rd |
374 imm3 = self.imm3.imm | 249 self.token[3:6] = self.rn.num |
375 opcode = self.opcode | 250 self.token[6:9] = self.imm3 |
376 h = (self.opcode << 9) | (imm3 << 6) | (rn << 3) | rd | 251 self.token[9:16] = self.opcode |
377 return u16(h) | 252 return self.token.encode() |
378 | 253 |
379 def __repr__(self): | 254 def __repr__(self): |
380 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.imm3.imm) | 255 mnemonic = self.__class__.__name__ |
381 | 256 return '{} {}, {}, {}'.format(mnemonic, self.rd, self.rn, self.imm3) |
382 | 257 |
383 add_rule(['add', 'r8', ',', 'r8', ',', 'imm3'], lambda rhs: Add2(rhs[1], rhs[3], rhs[5])) | 258 |
384 | 259 |
385 @instruction | |
386 class Add2(regregimm3_base): | 260 class Add2(regregimm3_base): |
387 """ add Rd, Rn, imm3 """ | 261 """ add Rd, Rn, imm3 """ |
388 mnemonic = 'add' | |
389 opcode = 0b0001110 | 262 opcode = 0b0001110 |
390 | 263 |
391 | 264 |
392 @instruction | |
393 class Sub2(regregimm3_base): | 265 class Sub2(regregimm3_base): |
394 """ sub Rd, Rn, imm3 """ | 266 """ sub Rd, Rn, imm3 """ |
395 mnemonic = 'sub' | |
396 opcode = 0b0001111 | 267 opcode = 0b0001111 |
397 | 268 |
398 | 269 |
399 class regregreg_base(ArmInstruction): | 270 def Sub(*args): |
271 if len(args) == 3 and args[0] is SP and args[1] is SP and \ | |
272 isinstance(args[2], int) and args[2] < 256: | |
273 return SubSp(args[2]) | |
274 elif len(args) == 3 and isinstance(args[0], ArmRegister) and \ | |
275 isinstance(args[1], ArmRegister) and isinstance(args[2], int) and \ | |
276 args[2] < 8: | |
277 return Sub2(args[0], args[1], args[2]) | |
278 else: | |
279 raise Exception() | |
280 | |
281 class regregreg_base(ThumbInstruction): | |
400 """ ??? Rd, Rn, Rm """ | 282 """ ??? Rd, Rn, Rm """ |
401 operands = (Reg8Op, Reg8Op, Reg8Op) | |
402 def __init__(self, rd, rn, rm): | 283 def __init__(self, rd, rn, rm): |
403 self.rd = rd | 284 self.rd = rd |
404 self.rn = rn | 285 self.rn = rn |
405 self.rm = rm | 286 self.rm = rm |
406 | 287 |
414 rn = self.rn.num | 295 rn = self.rn.num |
415 rm = self.rm.num | 296 rm = self.rm.num |
416 at[3:6] = rn | 297 at[3:6] = rn |
417 at[6:9] = rm | 298 at[6:9] = rm |
418 at[9:16] = self.opcode | 299 at[9:16] = self.opcode |
419 #h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd | |
420 #return u16(h) | |
421 return at.encode() | 300 return at.encode() |
422 | 301 |
423 def __repr__(self): | 302 def __repr__(self): |
424 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) | 303 return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) |
425 | 304 |
426 | 305 |
427 @instruction | 306 class Add3(regregreg_base): |
428 class Add(regregreg_base): | |
429 mnemonic = 'ADD' | 307 mnemonic = 'ADD' |
430 opcode = 0b0001100 | 308 opcode = 0b0001100 |
431 | 309 |
432 | 310 |
433 @instruction | 311 class Sub3(regregreg_base): |
434 class Sub(regregreg_base): | |
435 mnemonic = 'SUB' | 312 mnemonic = 'SUB' |
436 opcode = 0b0001101 | 313 opcode = 0b0001101 |
437 | 314 |
438 | 315 |
439 @instruction | 316 class Mov2(ThumbInstruction): |
440 class Mov2(ArmInstruction): | |
441 """ mov rd, rm """ | 317 """ mov rd, rm """ |
442 operands = (ArmRegister, ArmRegister) | |
443 mnemonic = 'MOV' | 318 mnemonic = 'MOV' |
444 def __init__(self, rd, rm): | 319 def __init__(self, rd, rm): |
445 self.rd = rd | 320 self.rd = rd |
446 self.rm = rm | 321 self.rm = rm |
447 | 322 |
456 Rm = self.rm.num | 331 Rm = self.rm.num |
457 opcode = 0b01000110 | 332 opcode = 0b01000110 |
458 at[8:16] = opcode | 333 at[8:16] = opcode |
459 at[3:7] = Rm | 334 at[3:7] = Rm |
460 at[7] = D | 335 at[7] = D |
461 return at.encode() # u16((opcode << 8) | (D << 7) |(Rm << 3) | Rd) | 336 return at.encode() |
462 | 337 |
463 def __repr__(self): | 338 def __repr__(self): |
464 return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) | 339 return '{} {}, {}'.format(self.mnemonic, self.rd, self.rm) |
465 | 340 |
466 | 341 |
467 @instruction | 342 class Mul(ThumbInstruction): |
468 class Mul(ArmInstruction): | |
469 """ mul Rn, Rdm """ | 343 """ mul Rn, Rdm """ |
470 operands = (Reg8Op, Reg8Op) | |
471 mnemonic = 'MUL' | 344 mnemonic = 'MUL' |
472 def __init__(self, rn, rdm): | 345 def __init__(self, rn, rdm): |
473 self.rn = rn | 346 self.rn = rn |
474 self.rdm = rdm | 347 self.rdm = rdm |
475 | 348 |
490 | 363 |
491 def __repr__(self): | 364 def __repr__(self): |
492 return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) | 365 return '{} {}, {}'.format(self.mnemonic, self.rn, self.rdm) |
493 | 366 |
494 | 367 |
495 class regreg_base(ArmInstruction): | 368 class regreg_base(ThumbInstruction): |
496 """ ??? Rdn, Rm """ | 369 """ ??? Rdn, Rm """ |
497 operands = (Reg8Op, Reg8Op) | |
498 # TODO: integrate with the code gen interface: | |
499 src = (0, 1) | |
500 dst = (0,) | |
501 def __init__(self, rdn, rm): | 370 def __init__(self, rdn, rm): |
502 self.rdn = rdn | 371 self.rdn = rdn |
503 self.rm = rm | 372 self.rm = rm |
504 | 373 |
505 @classmethod | 374 @classmethod |
513 at[3:6] = rm | 382 at[3:6] = rm |
514 at[6:16] = self.opcode | 383 at[6:16] = self.opcode |
515 return at.encode() | 384 return at.encode() |
516 | 385 |
517 def __repr__(self): | 386 def __repr__(self): |
518 return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) | 387 mnemonic = self.__class__.__name__ |
519 | 388 return '{} {}, {}'.format(mnemonic, self.rdn, self.rm) |
520 | 389 |
521 @instruction | 390 |
522 class movregreg_ins(regreg_base): | 391 class movregreg_ins(regreg_base): |
523 """ mov Rd, Rm (reg8 operands) """ | 392 """ mov Rd, Rm (reg8 operands) """ |
524 mnemonic = 'mov' | |
525 opcode = 0 | 393 opcode = 0 |
526 | 394 |
527 | 395 |
528 @instruction | |
529 class And(regreg_base): | 396 class And(regreg_base): |
530 mnemonic = 'AND' | |
531 opcode = 0b0100000000 | 397 opcode = 0b0100000000 |
532 | 398 |
533 | 399 |
534 @instruction | |
535 class Orr(regreg_base): | 400 class Orr(regreg_base): |
536 mnemonic = 'ORR' | |
537 opcode = 0b0100001100 | 401 opcode = 0b0100001100 |
538 | 402 |
539 | 403 |
540 @instruction | |
541 class Cmp(regreg_base): | 404 class Cmp(regreg_base): |
542 mnemonic = 'CMP' | |
543 opcode = 0b0100001010 | 405 opcode = 0b0100001010 |
544 | 406 |
545 | 407 |
546 @instruction | |
547 class Lsl(regreg_base): | 408 class Lsl(regreg_base): |
548 mnemonic = 'LSL' | |
549 opcode = 0b0100000010 | 409 opcode = 0b0100000010 |
550 | 410 |
551 | 411 |
552 @instruction | 412 class cmpregimm8_ins(ThumbInstruction): |
553 class cmpregimm8_ins(ArmInstruction): | |
554 """ cmp Rn, imm8 """ | 413 """ cmp Rn, imm8 """ |
555 mnemonic = 'cmp' | |
556 opcode = 5 # 00101 | 414 opcode = 5 # 00101 |
557 operands = (Reg8Op, Imm8) | |
558 def __init__(self, rn, imm): | 415 def __init__(self, rn, imm): |
559 self.rn = rn | 416 self.rn = rn |
560 self.imm = imm | 417 self.imm = imm |
561 | 418 |
562 def encode(self): | 419 def encode(self): |
563 rn = self.rn.num | 420 at = ThumbToken() |
564 imm = self.imm.imm | 421 at[0:8] = self.imm.imm |
565 opcode = self.opcode | 422 at[8:11] = self.rn.num |
566 h = (opcode << 11) | (rn << 8) | imm | 423 at[11:16] = self.opcode |
567 return u16(h) | 424 return at.encode() |
568 | 425 |
569 | 426 |
570 # Jumping: | 427 # Jumping: |
571 | 428 |
572 def wrap_negative(x, bits): | 429 class jumpBase_ins(ThumbInstruction): |
573 b = struct.unpack('<I', struct.pack('<i', x))[0] | |
574 mask = (1 << bits) - 1 | |
575 return b & mask | |
576 | |
577 class jumpBase_ins(ArmInstruction): | |
578 operands = (LabelRef,) | |
579 def __init__(self, target_label): | 430 def __init__(self, target_label): |
580 assert type(target_label) is LabelRef | |
581 self.target = target_label | 431 self.target = target_label |
582 self.offset = 0 | 432 self.offset = 0 |
583 | 433 |
584 def __repr__(self): | 434 def __repr__(self): |
585 return '{} {}'.format(self.mnemonic, self.target.name) | 435 mnemonic = self.__class__.__name__ |
586 | 436 return '{} {}'.format(mnemonic, self.target) |
587 | 437 |
588 class Imm11Reloc: | 438 |
589 def apply(self, P, S): | |
590 pass | |
591 | |
592 | |
593 @instruction | |
594 class B(jumpBase_ins): | 439 class B(jumpBase_ins): |
595 mnemonic = 'B' | 440 def encode(self): |
596 def encode(self): | 441 h = (0b11100 << 11) | 0 |
597 imm11 = wrap_negative(self.offset >> 1, 11) | 442 # | 1 # 1 to enable thumb mode |
598 h = (0b11100 << 11) | imm11 # | 1 # 1 to enable thumb mode | |
599 return u16(h) | 443 return u16(h) |
600 | 444 |
601 def relocations(self): | 445 def relocations(self): |
602 return [(self.target.name, 'wrap_new11')] | 446 return [(self.target, 'wrap_new11')] |
603 | 447 |
604 @instruction | |
605 class Bl(jumpBase_ins): | 448 class Bl(jumpBase_ins): |
606 mnemonic = 'BL' | 449 def encode(self): |
607 def encode(self): | 450 imm11 = 0 |
608 imm32 = wrap_negative(self.offset >> 1, 32) | 451 imm10 = 0 |
609 imm11 = imm32 & 0x7FF | |
610 imm10 = (imm32 >> 11) & 0x3FF | |
611 j1 = 1 # TODO: what do these mean? | 452 j1 = 1 # TODO: what do these mean? |
612 j2 = 1 | 453 j2 = 1 |
613 s = (imm32 >> 24) & 0x1 | 454 s = 0 |
614 h1 = (0b11110 << 11) | (s << 10) | imm10 | 455 h1 = (0b11110 << 11) | (s << 10) | imm10 |
615 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 | 456 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | imm11 |
616 return u16(h1) + u16(h2) | 457 return u16(h1) + u16(h2) |
617 | 458 |
618 def relocations(self): | 459 def relocations(self): |
619 return [(self.target.name, 'bl_imm11_imm10')] | 460 return [(self.target, 'bl_imm11_imm10')] |
620 | 461 |
621 | 462 |
622 class cond_base_ins(jumpBase_ins): | 463 class cond_base_ins(jumpBase_ins): |
623 def encode(self): | 464 def encode(self): |
624 imm8 = wrap_negative(self.offset >> 1, 8) | 465 imm8 = 0 |
625 h = (0b1101 << 12) | (self.cond << 8) | imm8 | 466 h = (0b1101 << 12) | (self.cond << 8) | imm8 |
626 return u16(h) | 467 return u16(h) |
627 | 468 |
628 def relocations(self): | 469 def relocations(self): |
629 return [(self.target.name, 'rel8')] | 470 return [(self.target, 'rel8')] |
630 | 471 |
631 | 472 |
632 class cond_base_ins_long(jumpBase_ins): | 473 class cond_base_ins_long(jumpBase_ins): |
633 """ Encoding T3 """ | 474 """ Encoding T3 """ |
634 def encode(self): | 475 def encode(self): |
637 h1 = (0b11110 << 11) | (self.cond << 6) | 478 h1 = (0b11110 << 11) | (self.cond << 6) |
638 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) | 479 h2 = (0b1101 << 12) | (j1 << 13) | (j2 << 11) |
639 return u16(h1) + u16(h2) | 480 return u16(h1) + u16(h2) |
640 | 481 |
641 def relocations(self): | 482 def relocations(self): |
642 return [(self.target.name, 'b_imm11_imm6')] | 483 return [(self.target, 'b_imm11_imm6')] |
643 | 484 |
644 | 485 |
645 @instruction | |
646 class Beq(cond_base_ins): | 486 class Beq(cond_base_ins): |
647 mnemonic = 'beq' | |
648 cond = 0 | 487 cond = 0 |
649 | 488 |
650 | 489 |
651 @instruction | |
652 class Bne(cond_base_ins): | 490 class Bne(cond_base_ins): |
653 mnemonic = 'bne' | |
654 cond = 1 | 491 cond = 1 |
655 | 492 |
656 | 493 |
657 @instruction | |
658 class Blt(cond_base_ins): | 494 class Blt(cond_base_ins): |
659 mnemonic = 'blt' | |
660 cond = 0b1011 | 495 cond = 0b1011 |
661 | 496 |
662 | 497 |
663 @instruction | |
664 class Bgt(cond_base_ins): | 498 class Bgt(cond_base_ins): |
665 mnemonic = 'bgt' | |
666 cond = 0b1100 | 499 cond = 0b1100 |
667 | 500 |
668 | 501 |
669 @instruction | 502 class Push(ThumbInstruction): |
670 class Push(ArmInstruction): | |
671 operands = (RegisterSet,) | |
672 mnemonic = 'push' | |
673 | |
674 def __init__(self, regs): | 503 def __init__(self, regs): |
675 if type(regs) is set: | 504 assert type(regs) is set |
676 regs = RegisterSet(regs) | |
677 assert (type(regs),) == self.operands, (type(regs),) | |
678 self.regs = regs | 505 self.regs = regs |
679 | 506 |
680 def __repr__(self): | 507 def __repr__(self): |
681 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | 508 return 'Push {{{}}}'.format(self.regs) |
682 | 509 |
683 def encode(self): | 510 def encode(self): |
684 reg_list = 0 | 511 at = ThumbToken() |
685 M = 0 | 512 for n in register_numbers(self.regs): |
686 for n in self.regs.registerNumbers(): | |
687 if n < 8: | 513 if n < 8: |
688 reg_list |= (1 << n) | 514 at[n] = 1 |
689 elif n == 14: | 515 elif n == 14: |
690 M = 1 | 516 at[8] = 1 |
517 else: | |
518 raise NotImplementedError('not implemented for {}'.format(n)) | |
519 at[9:16] = 0x5a | |
520 return at.encode() | |
521 | |
522 | |
523 | |
524 def register_numbers(regs): | |
525 for r in regs: | |
526 yield r.num | |
527 | |
528 class Pop(ThumbInstruction): | |
529 def __init__(self, regs): | |
530 assert type(regs) is set | |
531 self.regs = regs | |
532 self.token = ThumbToken() | |
533 | |
534 def __repr__(self): | |
535 return 'Pop {{{}}}'.format(self.regs) | |
536 | |
537 def encode(self): | |
538 for n in register_numbers(self.regs): | |
539 if n < 8: | |
540 self.token[n] = 1 | |
541 elif n == 15: | |
542 self.token[8] = 1 | |
691 else: | 543 else: |
692 raise NotImplementedError('not implemented for this register') | 544 raise NotImplementedError('not implemented for this register') |
693 h = (0x5a << 9) | (M << 8) | reg_list | 545 self.token[9:16] = 0x5E |
694 return u16(h) | 546 return self.token.encode() |
695 | 547 |
696 | 548 |
697 add_rule(['pop', 'reg_list'], lambda rhs: Pop(rhs[1])) | 549 |
698 | 550 class Yield(ThumbInstruction): |
699 @instruction | |
700 class Pop(ArmInstruction): | |
701 operands = (RegisterSet,) | |
702 mnemonic = 'pop' | |
703 | |
704 def __init__(self, regs): | |
705 if type(regs) is set: | |
706 regs = RegisterSet(regs) | |
707 assert (type(regs),) == self.operands, (type(regs),) | |
708 self.regs = regs | |
709 | |
710 def __repr__(self): | |
711 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
712 | |
713 def encode(self): | |
714 reg_list = 0 | |
715 P = 0 | |
716 for n in self.regs.registerNumbers(): | |
717 if n < 8: | |
718 reg_list |= (1 << n) | |
719 elif n == 15: | |
720 P = 1 | |
721 else: | |
722 raise NotImplementedError('not implemented for this register') | |
723 h = (0x5E << 9) | (P << 8) | reg_list | |
724 return u16(h) | |
725 | |
726 | |
727 @instruction | |
728 class Yield(ArmInstruction): | |
729 operands = () | |
730 mnemonic = 'yield' | |
731 | |
732 def encode(self): | 551 def encode(self): |
733 return u16(0xbf10) | 552 return u16(0xbf10) |
734 | 553 |
735 # misc: | 554 # misc: |
736 | 555 |
737 # add/sub SP: | 556 # add/sub SP: |
738 class addspsp_base(ArmInstruction): | 557 class addspsp_base(ThumbInstruction): |
739 operands = (RegSpOp, RegSpOp, Imm7) | 558 def __init__(self, imm7): |
740 def __init__(self, _sp, _sp2, imm7): | 559 self.imm7 = imm7 |
741 self.imm7 = imm7.imm | |
742 assert self.imm7 % 4 == 0 | 560 assert self.imm7 % 4 == 0 |
743 self.imm7 >>= 2 | 561 self.imm7 >>= 2 |
744 | 562 |
745 def encode(self): | 563 def encode(self): |
746 return u16((self.opcode << 7) |self.imm7) | 564 return u16((self.opcode << 7) | self.imm7) |
747 | 565 |
748 def __repr__(self): | 566 def __repr__(self): |
749 return '{} sp, sp, {}'.format(self.mnemonic, self.imm7 << 2) | 567 mnemonic = self.__class__.__name__ |
750 | 568 return '{} sp, sp, {}'.format(mnemonic, self.imm7 << 2) |
751 | 569 |
752 @instruction | 570 |
753 class AddSp(addspsp_base): | 571 class AddSp(addspsp_base): |
754 mnemonic = 'add' | |
755 opcode = 0b101100000 | 572 opcode = 0b101100000 |
756 | 573 |
757 | 574 |
758 @instruction | |
759 class SubSp(addspsp_base): | 575 class SubSp(addspsp_base): |
760 mnemonic = 'sub' | |
761 opcode = 0b101100001 | 576 opcode = 0b101100001 |