1// Copyright (c) 2010 ARM Limited
2// All rights reserved
3//
4// The license below extends only to copyright in the software and shall
5// not be construed as granting a license to any other intellectual
6// property including but not limited to intellectual property relating
7// to a hardware implementation of the functionality of the software
8// licensed hereunder. You may use the software subject to the license
9// terms below provided that you ensure that this notice is replicated
10// unmodified and in its entirety in all distributions of the software,
11// modified or unmodified, in source code or in binary form.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Gabe Black
37
38def format ArmDataProcReg() {{
39 pclr = '''
40 return new %(className)ssRegPclr(machInst, %(dest)s,
41 %(op1)s, rm, imm5,
42 type);
43 '''
44 instDecode = '''
45 case %(opcode)#x:
46 if (immShift) {
47 if (setCc) {
48 if (%(dest)s == INTREG_PC) {
49 %(pclr)s
50 } else {
51 return new %(className)sRegCc(machInst, %(dest)s,
52 %(op1)s, rm, imm5, type);
53 }
54 } else {
55 return new %(className)sReg(machInst, %(dest)s, %(op1)s,
56 rm, imm5, type);
57 }
58 } else {
59 if (setCc) {
60 return new %(className)sRegRegCc(machInst, %(dest)s,
61 %(op1)s, rm, rs, type);
62 } else {
63 return new %(className)sRegReg(machInst, %(dest)s,
64 %(op1)s, rm, rs, type);
65 }
66 }
67 break;
68 '''
69
70 def instCode(opcode, mnem, useDest = True, useOp1 = True):
71 global pclr
72 if useDest:
73 dest = "rd"
74 else:
75 dest = "INTREG_ZERO"
76 if useOp1:
77 op1 = "rn"
78 else:
79 op1 = "INTREG_ZERO"
80 global instDecode, pclrCode
81 substDict = { "className": mnem.capitalize(),
82 "opcode": opcode,
83 "dest": dest,
84 "op1": op1 }
85 if useDest:
86 substDict["pclr"] = pclr % substDict
87 else:
88 substDict["pclr"] = ""
89 return instDecode % substDict
90
91 decode_block = '''
92 {
93 const bool immShift = (bits(machInst, 4) == 0);
94 const bool setCc = (bits(machInst, 20) == 1);
95 const uint32_t imm5 = bits(machInst, 11, 7);
96 const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
97 const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
98 const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
99 const IntRegIndex rm = (IntRegIndex)(uint32_t)RM;
100 const IntRegIndex rs = (IntRegIndex)(uint32_t)RS;
101 switch (OPCODE) {
102 '''
103 decode_block += instCode(0x0, "and")
104 decode_block += instCode(0x1, "eor")
105 decode_block += instCode(0x2, "sub")
106 decode_block += instCode(0x3, "rsb")
107 decode_block += instCode(0x4, "add")
108 decode_block += instCode(0x5, "adc")
109 decode_block += instCode(0x6, "sbc")
110 decode_block += instCode(0x7, "rsc")
111 decode_block += instCode(0x8, "tst", useDest = False)
112 decode_block += instCode(0x9, "teq", useDest = False)
113 decode_block += instCode(0xa, "cmp", useDest = False)
114 decode_block += instCode(0xb, "cmn", useDest = False)
115 decode_block += instCode(0xc, "orr")
116 decode_block += instCode(0xd, "mov", useOp1 = False)
117 decode_block += instCode(0xe, "bic")
118 decode_block += instCode(0xf, "mvn", useOp1 = False)
119 decode_block += '''
120 default:
121 return new Unknown(machInst);
122 }
123 }
124 '''
125}};
126
127def format ArmPackUnpackSatReverse() {{
128 decode_block = '''
129 {
130 const uint32_t op1 = bits(machInst, 22, 20);
131 const uint32_t a = bits(machInst, 19, 16);
132 const uint32_t op2 = bits(machInst, 7, 5);
133 if (bits(op2, 0) == 0) {
134 const IntRegIndex rn =
135 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
136 const IntRegIndex rd =
137 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
138 const uint32_t satImm = bits(machInst, 20, 16);
139 const uint32_t imm = bits(machInst, 11, 7);
140 const ArmShiftType type =
141 (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
142 if (op1 == 0) {
143 if (type) {
144 return new PkhtbReg(machInst, rd, (IntRegIndex)a,
145 rn, imm, type);
146 } else {
147 return new PkhbtReg(machInst, rd, (IntRegIndex)a,
148 rn, imm, type);
149 }
150 } else if (bits(op1, 2, 1) == 1) {
151 return new Ssat(machInst, rd, satImm + 1, rn, imm, type);
152 } else if (bits(op1, 2, 1) == 3) {
153 return new Usat(machInst, rd, satImm, rn, imm, type);
154 }
155 return new Unknown(machInst);
156 }
157 switch (op1) {
158 case 0x0:
159 if (op2 == 0x3) {
159 {
160 const IntRegIndex rn =
161 (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
162 const IntRegIndex rd =
163 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
164 const IntRegIndex rm =
165 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
166 const uint32_t rotation =
167 (uint32_t)bits(machInst, 11, 10) << 3;
168 if (a == 0xf) {
169 return new Sxtb16(machInst, rd, rotation, rm);
170 } else {
171 return new Sxtab16(machInst, rd, rn, rm, rotation);
166 if (op2 == 0x3) {
167 const uint32_t rotation =
168 (uint32_t)bits(machInst, 11, 10) << 3;
169 if (a == 0xf) {
170 return new Sxtb16(machInst, rd, rotation, rm);
171 } else {
172 return new Sxtab16(machInst, rd, rn, rm, rotation);
173 }
174 } else if (op2 == 0x5) {
175 return new Sel(machInst, rd, rn, rm);
176 }
173 } else if (op2 == 0x5) {
174 return new WarnUnimplemented("sel", machInst);
177 }
178 break;
179 case 0x2:
180 if (op2 == 0x1) {
181 const IntRegIndex rn =
182 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
183 const IntRegIndex rd =
184 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
185 const uint32_t satImm = bits(machInst, 20, 16);
186 return new Ssat16(machInst, rd, satImm + 1, rn);
187 } else if (op2 == 0x3) {
188 const IntRegIndex rn =
189 (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
190 const IntRegIndex rd =
191 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
192 const IntRegIndex rm =
193 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
194 const uint32_t rotation =
195 (uint32_t)bits(machInst, 11, 10) << 3;
196 if (a == 0xf) {
197 return new Sxtb(machInst, rd, rotation, rm);
198 } else {
199 return new Sxtab(machInst, rd, rn, rm, rotation);
200 }
201 }
202 break;
203 case 0x3:
204 if (op2 == 0x1) {
205 IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
206 IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
207 return new Rev(machInst, rd, rm);
208 } else if (op2 == 0x3) {
209 const IntRegIndex rn =
210 (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
211 const IntRegIndex rd =
212 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
213 const IntRegIndex rm =
214 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
215 const uint32_t rotation =
216 (uint32_t)bits(machInst, 11, 10) << 3;
217 if (a == 0xf) {
218 return new Sxth(machInst, rd, rotation, rm);
219 } else {
220 return new Sxtah(machInst, rd, rn, rm, rotation);
221 }
222 } else if (op2 == 0x5) {
223 IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
224 IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
225 return new Rev16(machInst, rd, rm);
226 }
227 break;
228 case 0x4:
229 if (op2 == 0x3) {
230 const IntRegIndex rn =
231 (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
232 const IntRegIndex rd =
233 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
234 const IntRegIndex rm =
235 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
236 const uint32_t rotation =
237 (uint32_t)bits(machInst, 11, 10) << 3;
238 if (a == 0xf) {
239 return new Uxtb16(machInst, rd, rotation, rm);
240 } else {
241 return new Uxtab16(machInst, rd, rn, rm, rotation);
242 }
243 }
244 break;
245 case 0x6:
246 if (op2 == 0x1) {
247 const IntRegIndex rn =
248 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
249 const IntRegIndex rd =
250 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
251 const uint32_t satImm = bits(machInst, 20, 16);
252 return new Usat16(machInst, rd, satImm, rn);
253 } else if (op2 == 0x3) {
254 const IntRegIndex rn =
255 (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
256 const IntRegIndex rd =
257 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
258 const IntRegIndex rm =
259 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
260 const uint32_t rotation =
261 (uint32_t)bits(machInst, 11, 10) << 3;
262 if (a == 0xf) {
263 return new Uxtb(machInst, rd, rotation, rm);
264 } else {
265 return new Uxtab(machInst, rd, rn, rm, rotation);
266 }
267 }
268 break;
269 case 0x7:
270 if (op2 == 0x1) {
271 return new WarnUnimplemented("rbit", machInst);
272 } else if (op2 == 0x3) {
273 const IntRegIndex rn =
274 (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
275 const IntRegIndex rd =
276 (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
277 const IntRegIndex rm =
278 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
279 const uint32_t rotation =
280 (uint32_t)bits(machInst, 11, 10) << 3;
281 if (a == 0xf) {
282 return new Uxth(machInst, rd, rotation, rm);
283 } else {
284 return new Uxtah(machInst, rd, rn, rm, rotation);
285 }
286 } else if (op2 == 0x5) {
287 IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
288 IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
289 return new Revsh(machInst, rd, rm);
290 }
291 break;
292 }
293 return new Unknown(machInst);
294 }
295 '''
296}};
297
298def format ArmParallelAddSubtract() {{
299 decode_block='''
300 {
301 const uint32_t op1 = bits(machInst, 21, 20);
302 const uint32_t op2 = bits(machInst, 7, 5);
303 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
304 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
305 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
306 if (bits(machInst, 22) == 0) {
307 switch (op1) {
308 case 0x1:
309 switch (op2) {
310 case 0x0:
311 return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL);
312 case 0x1:
313 return new SasxRegCc(machInst, rd, rn, rm, 0, LSL);
314 case 0x2:
315 return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL);
316 case 0x3:
317 return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL);
318 case 0x4:
319 return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL);
320 case 0x7:
321 return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL);
322 }
323 break;
324 case 0x2:
325 switch (op2) {
326 case 0x0:
327 return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
328 case 0x1:
329 return new QasxReg(machInst, rd, rn, rm, 0, LSL);
330 case 0x2:
331 return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
332 case 0x3:
333 return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
334 case 0x4:
335 return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
336 case 0x7:
337 return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
338 }
339 break;
340 case 0x3:
341 switch (op2) {
342 case 0x0:
343 return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL);
344 case 0x1:
345 return new ShasxReg(machInst, rd, rn, rm, 0, LSL);
346 case 0x2:
347 return new ShsaxReg(machInst, rd, rn, rm, 0, LSL);
348 case 0x3:
349 return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL);
350 case 0x4:
351 return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL);
352 case 0x7:
353 return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL);
354 }
355 break;
356 }
357 } else {
358 switch (op1) {
359 case 0x1:
360 switch (op2) {
361 case 0x0:
362 return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL);
363 case 0x1:
364 return new UasxRegCc(machInst, rd, rn, rm, 0, LSL);
365 case 0x2:
366 return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL);
367 case 0x3:
368 return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL);
369 case 0x4:
370 return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL);
371 case 0x7:
372 return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL);
373 }
374 break;
375 case 0x2:
376 switch (op2) {
377 case 0x0:
378 return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
379 case 0x1:
380 return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
381 case 0x2:
382 return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
383 case 0x3:
384 return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
385 case 0x4:
386 return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
387 case 0x7:
388 return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
389 }
390 break;
391 case 0x3:
392 switch (op2) {
393 case 0x0:
394 return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL);
395 case 0x1:
396 return new UhasxReg(machInst, rd, rn, rm, 0, LSL);
397 case 0x2:
398 return new UhsaxReg(machInst, rd, rn, rm, 0, LSL);
399 case 0x3:
400 return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL);
401 case 0x4:
402 return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL);
403 case 0x7:
404 return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL);
405 }
406 break;
407 }
408 }
409 return new Unknown(machInst);
410 }
411 '''
412}};
413
414def format ArmDataProcImm() {{
415 pclr = '''
416 return new %(className)ssImmPclr(machInst, %(dest)s,
417 %(op1)s, imm, false);
418 '''
419 adr = '''
420 return new AdrImm(machInst, %(dest)s, %(add)s,
421 imm, false);
422 '''
423 instDecode = '''
424 case %(opcode)#x:
425 if (setCc) {
426 if (%(pclrInst)s && %(dest)s == INTREG_PC) {
427 %(pclr)s
428 } else {
429 return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
430 imm, rotC);
431 }
432 } else {
433 if (%(adrInst)s && %(op1)s == INTREG_PC) {
434 %(adr)s
435 } else {
436 return new %(className)sImm(machInst, %(dest)s, %(op1)s,
437 imm, rotC);
438 }
439 }
440 break;
441 '''
442
443 def instCode(opcode, mnem, useDest = True, useOp1 = True):
444 global instDecode, pclr, adr
445 if useDest:
446 dest = "rd"
447 else:
448 dest = "INTREG_ZERO"
449 if useOp1:
450 op1 = "rn"
451 else:
452 op1 = "INTREG_ZERO"
453 substDict = { "className": mnem.capitalize(),
454 "opcode": opcode,
455 "dest": dest,
456 "op1": op1,
457 "adr": "",
458 "adrInst": "false" }
459 if useDest:
460 substDict["pclrInst"] = "true"
461 substDict["pclr"] = pclr % substDict
462 else:
463 substDict["pclrInst"] = "false"
464 substDict["pclr"] = ""
465 return instDecode % substDict
466
467 def adrCode(opcode, mnem, add="1"):
468 global instDecode, pclr, adr
469 substDict = { "className": mnem.capitalize(),
470 "opcode": opcode,
471 "dest": "rd",
472 "op1": "rn",
473 "add": add,
474 "pclrInst": "true",
475 "adrInst": "true" }
476 substDict["pclr"] = pclr % substDict
477 substDict["adr"] = adr % substDict
478 return instDecode % substDict
479
480 decode_block = '''
481 {
482 const bool setCc = (bits(machInst, 20) == 1);
483 const uint32_t unrotated = bits(machInst, 7, 0);
484 const uint32_t rotation = (bits(machInst, 11, 8) << 1);
485 const bool rotC = (rotation != 0);
486 const uint32_t imm = rotate_imm(unrotated, rotation);
487 const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
488 const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
489 switch (OPCODE) {
490 '''
491 decode_block += instCode(0x0, "and")
492 decode_block += instCode(0x1, "eor")
493 decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0")
494 decode_block += instCode(0x3, "rsb")
495 decode_block += adrCode(0x4, "add", add="(IntRegIndex)1")
496 decode_block += instCode(0x5, "adc")
497 decode_block += instCode(0x6, "sbc")
498 decode_block += instCode(0x7, "rsc")
499 decode_block += instCode(0x8, "tst", useDest = False)
500 decode_block += instCode(0x9, "teq", useDest = False)
501 decode_block += instCode(0xa, "cmp", useDest = False)
502 decode_block += instCode(0xb, "cmn", useDest = False)
503 decode_block += instCode(0xc, "orr")
504 decode_block += instCode(0xd, "mov", useOp1 = False)
505 decode_block += instCode(0xe, "bic")
506 decode_block += instCode(0xf, "mvn", useOp1 = False)
507 decode_block += '''
508 default:
509 return new Unknown(machInst);
510 }
511 }
512 '''
513}};
514
515def format ArmSatAddSub() {{
516 decode_block = '''
517 {
518 IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
519 IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
520 IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
521 switch (OPCODE) {
522 case 0x8:
523 return new QaddRegCc(machInst, rd, rm, rn, 0, LSL);
524 case 0x9:
525 return new QsubRegCc(machInst, rd, rm, rn, 0, LSL);
526 case 0xa:
527 return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL);
528 case 0xb:
529 return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL);
530 default:
531 return new Unknown(machInst);
532 }
533 }
534 '''
535}};
536
537def format Thumb32DataProcReg() {{
538 decode_block = '''
539 {
540 const uint32_t op1 = bits(machInst, 23, 20);
541 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
542 const uint32_t op2 = bits(machInst, 7, 4);
543 if (bits(op1, 3) != 1) {
544 if (op2 == 0) {
545 IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
546 IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
547 switch (bits(op1, 2, 0)) {
548 case 0x0:
549 return new MovRegReg(machInst, rd,
550 INTREG_ZERO, rn, rm, LSL);
551 case 0x1:
552 return new MovRegRegCc(machInst, rd,
553 INTREG_ZERO, rn, rm, LSL);
554 case 0x2:
555 return new MovRegReg(machInst, rd,
556 INTREG_ZERO, rn, rm, LSR);
557 case 0x3:
558 return new MovRegRegCc(machInst, rd,
559 INTREG_ZERO, rn, rm, LSR);
560 case 0x4:
561 return new MovRegReg(machInst, rd,
562 INTREG_ZERO, rn, rm, ASR);
563 case 0x5:
564 return new MovRegRegCc(machInst, rd,
565 INTREG_ZERO, rn, rm, ASR);
566 case 0x6:
567 return new MovRegReg(machInst, rd,
568 INTREG_ZERO, rn, rm, ROR);
569 case 0x7:
570 return new MovRegRegCc(machInst, rd,
571 INTREG_ZERO, rn, rm, ROR);
572 }
573 }
574 {
575 const IntRegIndex rd =
576 (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
577 const IntRegIndex rm =
578 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
579 const uint32_t rotation =
580 (uint32_t)bits(machInst, 5, 4) << 3;
581 switch (bits(op1, 2, 0)) {
582 case 0x0:
583 if (rn == 0xf) {
584 return new Sxth(machInst, rd, rotation, rm);
585 } else {
586 return new Sxtah(machInst, rd, rn, rm, rotation);
587 }
588 case 0x1:
589 if (rn == 0xf) {
590 return new Uxth(machInst, rd, rotation, rm);
591 } else {
592 return new Uxtah(machInst, rd, rn, rm, rotation);
593 }
594 case 0x2:
595 if (rn == 0xf) {
596 return new Sxtb16(machInst, rd, rotation, rm);
597 } else {
598 return new Sxtab16(machInst, rd, rn, rm, rotation);
599 }
600 case 0x3:
601 if (rn == 0xf) {
602 return new Uxtb16(machInst, rd, rotation, rm);
603 } else {
604 return new Uxtab16(machInst, rd, rn, rm, rotation);
605 }
606 case 0x4:
607 if (rn == 0xf) {
608 return new Sxtb(machInst, rd, rotation, rm);
609 } else {
610 return new Sxtab(machInst, rd, rn, rm, rotation);
611 }
612 case 0x5:
613 if (rn == 0xf) {
614 return new Uxtb(machInst, rd, rotation, rm);
615 } else {
616 return new Uxtab(machInst, rd, rn, rm, rotation);
617 }
618 default:
619 return new Unknown(machInst);
620 }
621 }
622 } else {
623 if (bits(op2, 3) == 0) {
624 const IntRegIndex rd =
625 (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
626 const IntRegIndex rm =
627 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
628 if (bits(op2, 2) == 0x0) {
629 const uint32_t op1 = bits(machInst, 22, 20);
630 const uint32_t op2 = bits(machInst, 5, 4);
631 switch (op2) {
632 case 0x0:
633 switch (op1) {
634 case 0x1:
635 return new Sadd16RegCc(machInst, rd,
636 rn, rm, 0, LSL);
637 case 0x2:
638 return new SasxRegCc(machInst, rd,
639 rn, rm, 0, LSL);
640 case 0x6:
641 return new SsaxRegCc(machInst, rd,
642 rn, rm, 0, LSL);
643 case 0x5:
644 return new Ssub16RegCc(machInst, rd,
645 rn, rm, 0, LSL);
646 case 0x0:
647 return new Sadd8RegCc(machInst, rd,
648 rn, rm, 0, LSL);
649 case 0x4:
650 return new Ssub8RegCc(machInst, rd,
651 rn, rm, 0, LSL);
652 }
653 break;
654 case 0x1:
655 switch (op1) {
656 case 0x1:
657 return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
658 case 0x2:
659 return new QasxReg(machInst, rd, rn, rm, 0, LSL);
660 case 0x6:
661 return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
662 case 0x5:
663 return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
664 case 0x0:
665 return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
666 case 0x4:
667 return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
668 }
669 break;
670 case 0x2:
671 switch (op1) {
672 case 0x1:
673 return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL);
674 case 0x2:
675 return new ShasxReg(machInst, rd, rn, rm, 0, LSL);
676 case 0x6:
677 return new ShsaxReg(machInst, rd, rn, rm, 0, LSL);
678 case 0x5:
679 return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL);
680 case 0x0:
681 return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL);
682 case 0x4:
683 return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL);
684 }
685 break;
686 }
687 } else {
688 const uint32_t op1 = bits(machInst, 22, 20);
689 const uint32_t op2 = bits(machInst, 5, 4);
690 switch (op2) {
691 case 0x0:
692 switch (op1) {
693 case 0x1:
694 return new Uadd16RegCc(machInst, rd,
695 rn, rm, 0, LSL);
696 case 0x2:
697 return new UasxRegCc(machInst, rd,
698 rn, rm, 0, LSL);
699 case 0x6:
700 return new UsaxRegCc(machInst, rd,
701 rn, rm, 0, LSL);
702 case 0x5:
703 return new Usub16RegCc(machInst, rd,
704 rn, rm, 0, LSL);
705 case 0x0:
706 return new Uadd8RegCc(machInst, rd,
707 rn, rm, 0, LSL);
708 case 0x4:
709 return new Usub8RegCc(machInst, rd,
710 rn, rm, 0, LSL);
711 }
712 break;
713 case 0x1:
714 switch (op1) {
715 case 0x1:
716 return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
717 case 0x2:
718 return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
719 case 0x6:
720 return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
721 case 0x5:
722 return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
723 case 0x0:
724 return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
725 case 0x4:
726 return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
727 }
728 break;
729 case 0x2:
730 switch (op1) {
731 case 0x1:
732 return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL);
733 case 0x2:
734 return new UhasxReg(machInst, rd, rn, rm, 0, LSL);
735 case 0x6:
736 return new UhsaxReg(machInst, rd, rn, rm, 0, LSL);
737 case 0x5:
738 return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL);
739 case 0x0:
740 return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL);
741 case 0x4:
742 return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL);
743 }
744 break;
745 }
746 }
747 } else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) {
748 const uint32_t op1 = bits(machInst, 21, 20);
749 const uint32_t op2 = bits(machInst, 5, 4);
750 const IntRegIndex rd =
751 (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
752 const IntRegIndex rm =
753 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
754 switch (op1) {
755 case 0x0:
750 {
751 IntRegIndex rd =
752 (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
753 IntRegIndex rm =
754 (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
755 switch (op2) {
756 case 0x0:
757 return new QaddRegCc(machInst, rd,
758 rm, rn, 0, LSL);
759 case 0x1:
760 return new QdaddRegCc(machInst, rd,
761 rm, rn, 0, LSL);
762 case 0x2:
763 return new QsubRegCc(machInst, rd,
764 rm, rn, 0, LSL);
765 case 0x3:
766 return new QdsubRegCc(machInst, rd,
767 rm, rn, 0, LSL);
768 }
756 switch (op2) {
757 case 0x0:
758 return new QaddRegCc(machInst, rd,
759 rm, rn, 0, LSL);
760 case 0x1:
761 return new QdaddRegCc(machInst, rd,
762 rm, rn, 0, LSL);
763 case 0x2:
764 return new QsubRegCc(machInst, rd,
765 rm, rn, 0, LSL);
766 case 0x3:
767 return new QdsubRegCc(machInst, rd,
768 rm, rn, 0, LSL);
769 }
770 break;
771 case 0x1:
772 {
773 IntRegIndex rd =
774 (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
775 IntRegIndex rm = rn;
776 switch (op2) {
777 case 0x0:
778 return new Rev(machInst, rd, rm);
779 case 0x1:
780 return new Rev16(machInst, rd, rm);
781 case 0x2:
782 return new WarnUnimplemented("rbit", machInst);
783 case 0x3:
784 return new Revsh(machInst, rd, rm);
785 }
772 switch (op2) {
773 case 0x0:
774 return new Rev(machInst, rd, rn);
775 case 0x1:
776 return new Rev16(machInst, rd, rn);
777 case 0x2:
778 return new WarnUnimplemented("rbit", machInst);
779 case 0x3:
780 return new Revsh(machInst, rd, rn);
781 }
782 break;
783 case 0x2:
784 if (op2 == 0) {
790 return new WarnUnimplemented("sel", machInst);
785 return new Sel(machInst, rd, rn, rm);
786 }
787 break;
788 case 0x3:
789 if (op2 == 0) {
790 return new WarnUnimplemented("clz", machInst);
791 }
792 }
793 }
794 return new Unknown(machInst);
795 }
796 }
797 '''
798}};
799
800def format Thumb16ShiftAddSubMoveCmp() {{
801 decode_block = '''
802 {
803 const uint32_t imm5 = bits(machInst, 10, 6);
804 const uint32_t imm3 = bits(machInst, 8, 6);
805 const uint32_t imm8 = bits(machInst, 7, 0);
806 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
807 const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
808 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
809 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
810 switch (bits(machInst, 13, 11)) {
811 case 0x0: // lsl
812 return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
813 case 0x1: // lsr
814 return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
815 case 0x2: // asr
816 return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
817 case 0x3:
818 switch (bits(machInst, 10, 9)) {
819 case 0x0:
820 return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
821 case 0x1:
822 return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
823 case 0x2:
824 return new AddImmCc(machInst, rd, rn, imm3, true);
825 case 0x3:
826 return new SubImmCc(machInst, rd, rn, imm3, true);
827 }
828 case 0x4:
829 return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
830 case 0x5:
831 return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
832 case 0x6:
833 return new AddImmCc(machInst, rd8, rd8, imm8, true);
834 case 0x7:
835 return new SubImmCc(machInst, rd8, rd8, imm8, true);
836 }
837 }
838 '''
839}};
840
841def format Thumb16DataProcessing() {{
842 decode_block = '''
843 {
844 const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
845 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
846 switch (bits(machInst, 9, 6)) {
847 case 0x0:
848 return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
849 case 0x1:
850 return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
851 case 0x2: //lsl
852 return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
853 case 0x3: //lsr
854 return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
855 case 0x4: //asr
856 return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
857 case 0x5:
858 return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
859 case 0x6:
860 return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
861 case 0x7: // ror
862 return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
863 case 0x8:
864 return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
865 case 0x9:
866 return new RsbImmCc(machInst, rdn, rm, 0, true);
867 case 0xa:
868 return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
869 case 0xb:
870 return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
871 case 0xc:
872 return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
873 case 0xd:
874 return new MulCc(machInst, rdn, rm, rdn);
875 case 0xe:
876 return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
877 case 0xf:
878 return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
879 }
880 }
881 '''
882}};
883
884def format Thumb16SpecDataAndBx() {{
885 decode_block = '''
886 {
887 const IntRegIndex rdn =
888 (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
889 (bits(machInst, 7) << 3));
890 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
891 switch (bits(machInst, 9, 8)) {
892 case 0x0:
893 return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
894 case 0x1:
895 return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
896 case 0x2:
897 return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
898 case 0x3:
899 if (bits(machInst, 7) == 0) {
900 return new BxReg(machInst,
901 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
902 COND_UC);
903 } else {
904 return new BlxReg(machInst,
905 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
906 COND_UC);
907 }
908 }
909 }
910 '''
911}};
912
913def format Thumb16Adr() {{
914 decode_block = '''
915 {
916 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
917 const uint32_t imm8 = bits(machInst, 7, 0) << 2;
918 return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false);
919 }
920 '''
921}};
922
923def format Thumb16AddSp() {{
924 decode_block = '''
925 {
926 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
927 const uint32_t imm8 = bits(machInst, 7, 0) << 2;
928 return new AddImm(machInst, rd, INTREG_SP, imm8, true);
929 }
930 '''
931}};
932
933def format Thumb16Misc() {{
934 decode_block = '''
935 {
936 switch (bits(machInst, 11, 8)) {
937 case 0x0:
938 if (bits(machInst, 7)) {
939 return new SubImm(machInst, INTREG_SP, INTREG_SP,
940 bits(machInst, 6, 0) << 2, true);
941 } else {
942 return new AddImm(machInst, INTREG_SP, INTREG_SP,
943 bits(machInst, 6, 0) << 2, true);
944 }
945 case 0x1:
946 return new Cbz(machInst,
947 (bits(machInst, 9) << 6) |
948 (bits(machInst, 7, 3) << 1),
949 (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
950 case 0x2:
951 {
952 const IntRegIndex rd =
953 (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
954 const IntRegIndex rm =
955 (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
956 switch (bits(machInst, 7, 6)) {
957 case 0x0:
958 return new Sxth(machInst, rd, 0, rm);
959 case 0x1:
960 return new Sxtb(machInst, rd, 0, rm);
961 case 0x2:
962 return new Uxth(machInst, rd, 0, rm);
963 case 0x3:
964 return new Uxtb(machInst, rd, 0, rm);
965 }
966 }
967 case 0x3:
968 return new Cbz(machInst,
969 (bits(machInst, 9) << 6) |
970 (bits(machInst, 7, 3) << 1),
971 (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
972 case 0x4:
973 case 0x5:
974 {
975 const uint32_t m = bits(machInst, 8);
976 const uint32_t regList = bits(machInst, 7, 0) | (m << 14);
977 return new LdmStm(machInst, INTREG_SP, false, false, false,
978 true, false, regList);
979 }
980 case 0x6:
981 {
982 const uint32_t opBits = bits(machInst, 7, 5);
983 if (opBits == 2) {
984 return new WarnUnimplemented("setend", machInst);
985 } else if (opBits == 3) {
986 return new WarnUnimplemented("cps", machInst);
987 }
988 }
989 case 0x9:
990 return new Cbnz(machInst,
991 (bits(machInst, 9) << 6) |
992 (bits(machInst, 7, 3) << 1),
993 (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
994 case 0xa:
995 {
996 IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
997 IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
998 switch (bits(machInst, 7, 6)) {
999 case 0x0:
1000 return new Rev(machInst, rd, rm);
1001 case 0x1:
1002 return new Rev16(machInst, rd, rm);
1003 case 0x3:
1004 return new Revsh(machInst, rd, rm);
1005 default:
1006 break;
1007 }
1008 }
1009 break;
1010 case 0xb:
1011 return new Cbnz(machInst,
1012 (bits(machInst, 9) << 6) |
1013 (bits(machInst, 7, 3) << 1),
1014 (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
1015 case 0xc:
1016 case 0xd:
1017 {
1018 const uint32_t p = bits(machInst, 8);
1019 const uint32_t regList = bits(machInst, 7, 0) | (p << 15);
1020 return new LdmStm(machInst, INTREG_SP, true, true, false,
1021 true, true, regList);
1022 }
1023 case 0xe:
1024 return new WarnUnimplemented("bkpt", machInst);
1025 case 0xf:
1026 if (bits(machInst, 3, 0) != 0)
1027 return new WarnUnimplemented("it", machInst);
1028 switch (bits(machInst, 7, 4)) {
1029 case 0x0:
1030 return new WarnUnimplemented("nop", machInst);
1031 case 0x1:
1032 return new WarnUnimplemented("yield", machInst);
1033 case 0x2:
1034 return new WarnUnimplemented("wfe", machInst);
1035 case 0x3:
1036 return new WarnUnimplemented("wfi", machInst);
1037 case 0x4:
1038 return new WarnUnimplemented("sev", machInst);
1039 default:
1040 return new WarnUnimplemented("unallocated_hint", machInst);
1041 }
1042 default:
1043 break;
1044 }
1045 return new Unknown(machInst);
1046 }
1047 '''
1048}};
1049
1050def format Thumb32DataProcModImm() {{
1051
1052 def decInst(mnem, dest="rd", op1="rn"):
1053 return '''
1054 if (s) {
1055 return new %(mnem)sImmCc(machInst, %(dest)s,
1056 %(op1)s, imm, rotC);
1057 } else {
1058 return new %(mnem)sImm(machInst, %(dest)s,
1059 %(op1)s, imm, rotC);
1060 }
1061 ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
1062
1063 decode_block = '''
1064 {
1065 const uint32_t op = bits(machInst, 24, 21);
1066 const bool s = (bits(machInst, 20) == 1);
1067 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1068 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1069 const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
1070 bits(machInst, 14, 12);
1071 const bool rotC = ctrlImm > 3;
1072 const uint32_t dataImm = bits(machInst, 7, 0);
1073 const uint32_t imm = modified_imm(ctrlImm, dataImm);
1074 switch (op) {
1075 case 0x0:
1076 if (rd == INTREG_PC) {
1077 %(tst)s
1078 } else {
1079 %(and)s
1080 }
1081 case 0x1:
1082 %(bic)s
1083 case 0x2:
1084 if (rn == INTREG_PC) {
1085 %(mov)s
1086 } else {
1087 %(orr)s
1088 }
1089 case 0x3:
1090 if (rn == INTREG_PC) {
1091 %(mvn)s
1092 } else {
1093 %(orn)s
1094 }
1095 case 0x4:
1096 if (rd == INTREG_PC) {
1097 %(teq)s
1098 } else {
1099 %(eor)s
1100 }
1101 case 0x8:
1102 if (rd == INTREG_PC) {
1103 %(cmn)s
1104 } else {
1105 %(add)s
1106 }
1107 case 0xa:
1108 %(adc)s
1109 case 0xb:
1110 %(sbc)s
1111 case 0xd:
1112 if (rd == INTREG_PC) {
1113 %(cmp)s
1114 } else {
1115 %(sub)s
1116 }
1117 case 0xe:
1118 %(rsb)s
1119 default:
1120 return new Unknown(machInst);
1121 }
1122 }
1123 ''' % {
1124 "tst" : decInst("Tst", "INTREG_ZERO"),
1125 "and" : decInst("And"),
1126 "bic" : decInst("Bic"),
1127 "mov" : decInst("Mov", op1="INTREG_ZERO"),
1128 "orr" : decInst("Orr"),
1129 "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
1130 "orn" : decInst("Orn"),
1131 "teq" : decInst("Teq", dest="INTREG_ZERO"),
1132 "eor" : decInst("Eor"),
1133 "cmn" : decInst("Cmn", dest="INTREG_ZERO"),
1134 "add" : decInst("Add"),
1135 "adc" : decInst("Adc"),
1136 "sbc" : decInst("Sbc"),
1137 "cmp" : decInst("Cmp", dest="INTREG_ZERO"),
1138 "sub" : decInst("Sub"),
1139 "rsb" : decInst("Rsb")
1140 }
1141}};
1142
1143def format Thumb32DataProcPlainBin() {{
1144 decode_block = '''
1145 {
1146 const uint32_t op = bits(machInst, 24, 20);
1147 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1148 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1149 switch (op) {
1150 case 0x0:
1151 {
1152 const uint32_t imm = bits(machInst, 7, 0) |
1153 (bits(machInst, 14, 12) << 8) |
1154 (bits(machInst, 26) << 11);
1155 if (rn == 0xf) {
1156 return new AdrImm(machInst, rd, (IntRegIndex)1,
1157 imm, false);
1158 } else {
1159 return new AddImm(machInst, rd, rn, imm, true);
1160 }
1161 }
1162 case 0x4:
1163 {
1164 const uint32_t imm = bits(machInst, 7, 0) |
1165 (bits(machInst, 14, 12) << 8) |
1166 (bits(machInst, 26) << 11) |
1167 (bits(machInst, 19, 16) << 12);
1168 return new MovImm(machInst, rd, INTREG_ZERO, imm, true);
1169 }
1170 case 0xa:
1171 {
1172 const uint32_t imm = bits(machInst, 7, 0) |
1173 (bits(machInst, 14, 12) << 8) |
1174 (bits(machInst, 26) << 11);
1175 if (rn == 0xf) {
1176 return new AdrImm(machInst, rd, (IntRegIndex)0,
1177 imm, false);
1178 } else {
1179 return new SubImm(machInst, rd, rn, imm, true);
1180 }
1181 }
1182 case 0xc:
1183 {
1184 const uint32_t imm = bits(machInst, 7, 0) |
1185 (bits(machInst, 14, 12) << 8) |
1186 (bits(machInst, 26) << 11) |
1187 (bits(machInst, 19, 16) << 12);
1188 return new MovtImm(machInst, rd, rd, imm, true);
1189 }
1190 case 0x12:
1191 if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
1192 const uint32_t satImm = bits(machInst, 4, 0);
1193 return new Ssat16(machInst, rd, satImm + 1, rn);
1194 }
1195 // Fall through on purpose...
1196 case 0x10:
1197 {
1198 const uint32_t satImm = bits(machInst, 4, 0);
1199 const uint32_t imm = bits(machInst, 7, 6) |
1200 (bits(machInst, 14, 12) << 2);
1201 const ArmShiftType type =
1202 (ArmShiftType)(uint32_t)bits(machInst, 21, 20);
1203 return new Ssat(machInst, rd, satImm + 1, rn, imm, type);
1204 }
1205 case 0x14:
1206 return new WarnUnimplemented("sbfx", machInst);
1207 case 0x16:
1208 if (rn == 0xf) {
1209 return new WarnUnimplemented("bfc", machInst);
1210 } else {
1211 return new WarnUnimplemented("bfi", machInst);
1212 }
1213 case 0x1a:
1214 if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
1215 const uint32_t satImm = bits(machInst, 4, 0);
1216 return new Usat16(machInst, rd, satImm, rn);
1217 }
1218 // Fall through on purpose...
1219 case 0x18:
1220 {
1221 const uint32_t satImm = bits(machInst, 4, 0);
1222 const uint32_t imm = bits(machInst, 7, 6) |
1223 (bits(machInst, 14, 12) << 2);
1224 const ArmShiftType type =
1225 (ArmShiftType)(uint32_t)bits(machInst, 21, 20);
1226 return new Usat(machInst, rd, satImm, rn, imm, type);
1227 }
1228 case 0x1c:
1229 return new WarnUnimplemented("ubfx", machInst);
1230 default:
1231 return new Unknown(machInst);
1232 }
1233 }
1234 '''
1235}};
1236
1237def format Thumb32DataProcShiftReg() {{
1238
1239 def decInst(mnem, dest="rd", op1="rn"):
1240 return '''
1241 if (s) {
1242 return new %(mnem)sRegCc(machInst, %(dest)s,
1243 %(op1)s, rm, amt, type);
1244 } else {
1245 return new %(mnem)sReg(machInst, %(dest)s,
1246 %(op1)s, rm, amt, type);
1247 }
1248 ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
1249
1250 decode_block = '''
1251 {
1252 const uint32_t op = bits(machInst, 24, 21);
1253 const bool s = (bits(machInst, 20) == 1);
1254 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1255 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1256 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
1257 const uint32_t amt = (bits(machInst, 14, 12) << 2) |
1258 bits(machInst, 7, 6);
1259 const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
1260 switch (op) {
1261 case 0x0:
1262 if (rd == INTREG_PC) {
1263 %(tst)s
1264 } else {
1265 %(and)s
1266 }
1267 case 0x1:
1268 %(bic)s
1269 case 0x2:
1270 if (rn == INTREG_PC) {
1271 %(mov)s
1272 } else {
1273 %(orr)s
1274 }
1275 case 0x3:
1276 if (rn == INTREG_PC) {
1277 %(mvn)s
1278 } else {
1279 %(orn)s
1280 }
1281 case 0x4:
1282 if (rd == INTREG_PC) {
1283 %(teq)s
1284 } else {
1285 %(eor)s
1286 }
1287 case 0x6:
1288 if (type) {
1289 return new PkhtbReg(machInst, rd, rn, rm, amt, type);
1290 } else {
1291 return new PkhbtReg(machInst, rd, rn, rm, amt, type);
1292 }
1293 case 0x8:
1294 if (rd == INTREG_PC) {
1295 %(cmn)s
1296 } else {
1297 %(add)s
1298 }
1299 case 0xa:
1300 %(adc)s
1301 case 0xb:
1302 %(sbc)s
1303 case 0xd:
1304 if (rd == INTREG_PC) {
1305 %(cmp)s
1306 } else {
1307 %(sub)s
1308 }
1309 case 0xe:
1310 %(rsb)s
1311 default:
1312 return new Unknown(machInst);
1313 }
1314 }
1315 ''' % {
1316 "tst" : decInst("Tst", "INTREG_ZERO"),
1317 "and" : decInst("And"),
1318 "bic" : decInst("Bic"),
1319 "mov" : decInst("Mov", op1="INTREG_ZERO"),
1320 "orr" : decInst("Orr"),
1321 "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
1322 "orn" : decInst("Orn"),
1323 "teq" : decInst("Teq", "INTREG_ZERO"),
1324 "eor" : decInst("Eor"),
1325 "cmn" : decInst("Cmn", "INTREG_ZERO"),
1326 "add" : decInst("Add"),
1327 "adc" : decInst("Adc"),
1328 "sbc" : decInst("Sbc"),
1329 "cmp" : decInst("Cmp", "INTREG_ZERO"),
1330 "sub" : decInst("Sub"),
1331 "rsb" : decInst("Rsb")
1332 }
1333}};