data.isa revision 12258
1// Copyright (c) 2010,2017 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 ArmMiscMedia() {{
39    decode_block = '''
40    {
41        const uint32_t op1 = bits(machInst, 22, 20);
42        const uint32_t op2 = bits(machInst, 7, 5);
43        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
44        const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
45        if (op1 == 0 && op2 == 0) {
46            const IntRegIndex rd =
47                (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
48            const IntRegIndex rm =
49                (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
50            if (ra == 0xf) {
51                return new Usad8(machInst, rd, rn, rm);
52            } else {
53                return new Usada8(machInst, rd, rn, rm, ra);
54            }
55        } else if (bits(op2, 1, 0) == 0x2) {
56            const uint32_t lsb = bits(machInst, 11, 7);
57            const uint32_t msb = lsb + bits(machInst, 20, 16);
58            if (bits(op1, 2, 1) == 0x3) {
59                return new Ubfx(machInst, ra, rn, lsb, msb);
60            } else if (bits(op1, 2, 1) == 0x1) {
61                return new Sbfx(machInst, ra, rn, lsb, msb);
62            }
63        } else if (bits(op2, 1, 0) == 0x0 && bits(op1, 2, 1) == 0x2) {
64            const uint32_t lsb = bits(machInst, 11, 7);
65            const uint32_t msb = bits(machInst, 20, 16);
66            if (rn == 0xf) {
67                return new Bfc(machInst, ra, ra, lsb, msb);
68            } else {
69                return new Bfi(machInst, ra, rn, lsb, msb);
70            }
71        }
72        return new Unknown(machInst);
73    }
74    '''
75}};
76
77def format ArmDataProcReg() {{
78    pclr = '''
79        return new %(className)ssRegPclr(machInst, %(dest)s,
80                                        %(op1)s, rm, imm5,
81                                        type);
82    '''
83    instDecode = '''
84          case %(opcode)#x:
85            if (immShift) {
86                if (setCc) {
87                    if (%(dest)s == INTREG_PC) {
88                        %(pclr)s
89                    } else {
90                        return new %(className)sRegCc(machInst, %(dest)s,
91                                                      %(op1)s, rm, imm5, type);
92                    }
93                } else {
94                    return new %(className)sReg(machInst, %(dest)s, %(op1)s,
95                                                 rm, imm5, type);
96                }
97            } else {
98                if (setCc) {
99                    return new %(className)sRegRegCc(machInst, %(dest)s,
100                                                      %(op1)s, rm, rs, type);
101                } else {
102                    return new %(className)sRegReg(machInst, %(dest)s,
103                                                    %(op1)s, rm, rs, type);
104                }
105            }
106            break;
107    '''
108
109    def instCode(opcode, mnem, useDest = True, useOp1 = True):
110        global pclr
111        if useDest:
112            dest = "rd"
113        else:
114            dest = "INTREG_ZERO"
115        if useOp1:
116            op1 = "rn"
117        else:
118            op1 = "INTREG_ZERO"
119        global instDecode, pclrCode
120        substDict = { "className": mnem.capitalize(),
121                      "opcode": opcode,
122                      "dest": dest,
123                      "op1": op1 }
124        if useDest:
125            substDict["pclr"] = pclr % substDict
126        else:
127            substDict["pclr"] = ""
128        return instDecode % substDict
129
130    decode_block = '''
131    {
132        const bool immShift = (bits(machInst, 4) == 0);
133        const bool setCc = (bits(machInst, 20) == 1);
134        const uint32_t imm5 = bits(machInst, 11, 7);
135        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
136        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
137        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
138        const IntRegIndex rm = (IntRegIndex)(uint32_t)RM;
139        const IntRegIndex rs = (IntRegIndex)(uint32_t)RS;
140        switch (OPCODE) {
141    '''
142    decode_block += instCode(0x0, "and")
143    decode_block += instCode(0x1, "eor")
144    decode_block += instCode(0x2, "sub")
145    decode_block += instCode(0x3, "rsb")
146    decode_block += instCode(0x4, "add")
147    decode_block += instCode(0x5, "adc")
148    decode_block += instCode(0x6, "sbc")
149    decode_block += instCode(0x7, "rsc")
150    decode_block += instCode(0x8, "tst", useDest = False)
151    decode_block += instCode(0x9, "teq", useDest = False)
152    decode_block += instCode(0xa, "cmp", useDest = False)
153    decode_block += instCode(0xb, "cmn", useDest = False)
154    decode_block += instCode(0xc, "orr")
155    decode_block += instCode(0xd, "mov", useOp1 = False)
156    decode_block += instCode(0xe, "bic")
157    decode_block += instCode(0xf, "mvn", useOp1 = False)
158    decode_block += '''
159          default:
160            return new Unknown(machInst);
161        }
162    }
163    '''
164}};
165
166def format ArmPackUnpackSatReverse() {{
167    decode_block = '''
168    {
169        const uint32_t op1 = bits(machInst, 22, 20);
170        const uint32_t a = bits(machInst, 19, 16);
171        const uint32_t op2 = bits(machInst, 7, 5);
172        if (bits(op2, 0) == 0) {
173            const IntRegIndex rn =
174                (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
175            const IntRegIndex rd =
176                (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
177            const uint32_t satImm = bits(machInst, 20, 16);
178            const uint32_t imm = bits(machInst, 11, 7);
179            const ArmShiftType type =
180                (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
181            if (op1 == 0) {
182                if (type) {
183                    return new PkhtbReg(machInst, rd, (IntRegIndex)a,
184                                        rn, imm, type);
185                } else {
186                    return new PkhbtReg(machInst, rd, (IntRegIndex)a,
187                                        rn, imm, type);
188                }
189            } else if (bits(op1, 2, 1) == 1) {
190                return new Ssat(machInst, rd, satImm + 1, rn, imm, type);
191            } else if (bits(op1, 2, 1) == 3) {
192                return new Usat(machInst, rd, satImm, rn, imm, type);
193            }
194            return new Unknown(machInst);
195        }
196        switch (op1) {
197          case 0x0:
198            {
199                const IntRegIndex rn =
200                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
201                const IntRegIndex rd =
202                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
203                const IntRegIndex rm =
204                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
205                if (op2 == 0x3) {
206                    const uint32_t rotation =
207                        (uint32_t)bits(machInst, 11, 10) << 3;
208                    if (a == 0xf) {
209                        return new Sxtb16(machInst, rd, rotation, rm);
210                    } else {
211                        return new Sxtab16(machInst, rd, rn, rm, rotation);
212                    }
213                } else if (op2 == 0x5) {
214                    return new Sel(machInst, rd, rn, rm);
215                }
216            }
217            break;
218          case 0x2:
219            if (op2 == 0x1) {
220                const IntRegIndex rn =
221                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
222                const IntRegIndex rd =
223                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
224                const uint32_t satImm = bits(machInst, 20, 16);
225                return new Ssat16(machInst, rd, satImm + 1, rn);
226            } else if (op2 == 0x3) {
227                const IntRegIndex rn =
228                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
229                const IntRegIndex rd =
230                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
231                const IntRegIndex rm =
232                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
233                const uint32_t rotation =
234                    (uint32_t)bits(machInst, 11, 10) << 3;
235                if (a == 0xf) {
236                    return new Sxtb(machInst, rd, rotation, rm);
237                } else {
238                    return new Sxtab(machInst, rd, rn, rm, rotation);
239                }
240            }
241            break;
242          case 0x3:
243            if (op2 == 0x1) {
244                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
245                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
246                return new Rev(machInst, rd, rm);
247            } else if (op2 == 0x3) {
248                const IntRegIndex rn =
249                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
250                const IntRegIndex rd =
251                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
252                const IntRegIndex rm =
253                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
254                const uint32_t rotation =
255                    (uint32_t)bits(machInst, 11, 10) << 3;
256                if (a == 0xf) {
257                    return new Sxth(machInst, rd, rotation, rm);
258                } else {
259                    return new Sxtah(machInst, rd, rn, rm, rotation);
260                }
261            } else if (op2 == 0x5) {
262                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
263                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
264                return new Rev16(machInst, rd, rm);
265            }
266            break;
267          case 0x4:
268            if (op2 == 0x3) {
269                const IntRegIndex rn =
270                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
271                const IntRegIndex rd =
272                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
273                const IntRegIndex rm =
274                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
275                const uint32_t rotation =
276                    (uint32_t)bits(machInst, 11, 10) << 3;
277                if (a == 0xf) {
278                    return new Uxtb16(machInst, rd, rotation, rm);
279                } else {
280                    return new Uxtab16(machInst, rd, rn, rm, rotation);
281                }
282            }
283            break;
284          case 0x6:
285            if (op2 == 0x1) {
286                const IntRegIndex rn =
287                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
288                const IntRegIndex rd =
289                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
290                const uint32_t satImm = bits(machInst, 20, 16);
291                return new Usat16(machInst, rd, satImm, rn);
292            } else if (op2 == 0x3) {
293                const IntRegIndex rn =
294                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
295                const IntRegIndex rd =
296                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
297                const IntRegIndex rm =
298                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
299                const uint32_t rotation =
300                    (uint32_t)bits(machInst, 11, 10) << 3;
301                if (a == 0xf) {
302                    return new Uxtb(machInst, rd, rotation, rm);
303                } else {
304                    return new Uxtab(machInst, rd, rn, rm, rotation);
305                }
306            }
307            break;
308          case 0x7:
309            {
310                const IntRegIndex rn =
311                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
312                const IntRegIndex rd =
313                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
314                const IntRegIndex rm =
315                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
316                if (op2 == 0x1) {
317                    return new Rbit(machInst, rd, rm);
318                } else if (op2 == 0x3) {
319                    const uint32_t rotation =
320                        (uint32_t)bits(machInst, 11, 10) << 3;
321                    if (a == 0xf) {
322                        return new Uxth(machInst, rd, rotation, rm);
323                    } else {
324                        return new Uxtah(machInst, rd, rn, rm, rotation);
325                    }
326                } else if (op2 == 0x5) {
327                    return new Revsh(machInst, rd, rm);
328                }
329            }
330            break;
331        }
332        return new Unknown(machInst);
333    }
334    '''
335}};
336
337def format ArmParallelAddSubtract() {{
338    decode_block='''
339    {
340        const uint32_t op1 = bits(machInst, 21, 20);
341        const uint32_t op2 = bits(machInst, 7, 5);
342        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
343        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
344        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
345        if (bits(machInst, 22) == 0) {
346            switch (op1) {
347              case 0x1:
348                switch (op2) {
349                  case 0x0:
350                    return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL);
351                  case 0x1:
352                    return new SasxRegCc(machInst, rd, rn, rm, 0, LSL);
353                  case 0x2:
354                    return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL);
355                  case 0x3:
356                    return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL);
357                  case 0x4:
358                    return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL);
359                  case 0x7:
360                    return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL);
361                }
362                break;
363              case 0x2:
364                switch (op2) {
365                  case 0x0:
366                    return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
367                  case 0x1:
368                    return new QasxReg(machInst, rd, rn, rm, 0, LSL);
369                  case 0x2:
370                    return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
371                  case 0x3:
372                    return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
373                  case 0x4:
374                    return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
375                  case 0x7:
376                    return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
377                }
378                break;
379              case 0x3:
380                switch (op2) {
381                  case 0x0:
382                    return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL);
383                  case 0x1:
384                    return new ShasxReg(machInst, rd, rn, rm, 0, LSL);
385                  case 0x2:
386                    return new ShsaxReg(machInst, rd, rn, rm, 0, LSL);
387                  case 0x3:
388                    return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL);
389                  case 0x4:
390                    return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL);
391                  case 0x7:
392                    return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL);
393                }
394                break;
395            }
396        } else {
397            switch (op1) {
398              case 0x1:
399                switch (op2) {
400                  case 0x0:
401                    return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL);
402                  case 0x1:
403                    return new UasxRegCc(machInst, rd, rn, rm, 0, LSL);
404                  case 0x2:
405                    return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL);
406                  case 0x3:
407                    return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL);
408                  case 0x4:
409                    return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL);
410                  case 0x7:
411                    return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL);
412                }
413                break;
414              case 0x2:
415                switch (op2) {
416                  case 0x0:
417                    return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
418                  case 0x1:
419                    return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
420                  case 0x2:
421                    return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
422                  case 0x3:
423                    return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
424                  case 0x4:
425                    return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
426                  case 0x7:
427                    return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
428                }
429                break;
430              case 0x3:
431                switch (op2) {
432                  case 0x0:
433                    return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL);
434                  case 0x1:
435                    return new UhasxReg(machInst, rd, rn, rm, 0, LSL);
436                  case 0x2:
437                    return new UhsaxReg(machInst, rd, rn, rm, 0, LSL);
438                  case 0x3:
439                    return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL);
440                  case 0x4:
441                    return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL);
442                  case 0x7:
443                    return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL);
444                }
445                break;
446            }
447        }
448        return new Unknown(machInst);
449    }
450    '''
451}};
452
453def format ArmDataProcImm() {{
454    pclr = '''
455        return new %(className)ssImmPclr(machInst, %(dest)s,
456                                        %(op1)s, imm, false);
457    '''
458    adr = '''
459        return new AdrImm(machInst, %(dest)s, %(add)s,
460                                     imm, false);
461    '''
462    instDecode = '''
463          case %(opcode)#x:
464            if (setCc) {
465                if (%(pclrInst)s && %(dest)s == INTREG_PC) {
466                    %(pclr)s
467                } else {
468                    return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
469                                                   imm, rotC);
470                }
471            } else {
472                if (%(adrInst)s && %(op1)s == INTREG_PC) {
473                    %(adr)s
474                } else {
475                    return new %(className)sImm(machInst, %(dest)s, %(op1)s,
476                                                 imm, rotC);
477                }
478            }
479            break;
480    '''
481
482    def instCode(opcode, mnem, useDest = True, useOp1 = True):
483        global instDecode, pclr, adr
484        if useDest:
485            dest = "rd"
486        else:
487            dest = "INTREG_ZERO"
488        if useOp1:
489            op1 = "rn"
490        else:
491            op1 = "INTREG_ZERO"
492        substDict = { "className": mnem.capitalize(),
493                      "opcode": opcode,
494                      "dest": dest,
495                      "op1": op1,
496                      "adr": "",
497                      "adrInst": "false" }
498        if useDest:
499            substDict["pclrInst"] = "true"
500            substDict["pclr"] = pclr % substDict
501        else:
502            substDict["pclrInst"] = "false"
503            substDict["pclr"] = ""
504        return instDecode % substDict
505
506    def adrCode(opcode, mnem, add="1"):
507        global instDecode, pclr, adr
508        substDict = { "className": mnem.capitalize(),
509                      "opcode": opcode,
510                      "dest": "rd",
511                      "op1": "rn",
512                      "add": add,
513                      "pclrInst": "true",
514                      "adrInst": "true" }
515        substDict["pclr"] = pclr % substDict
516        substDict["adr"] = adr % substDict
517        return instDecode % substDict
518
519    decode_block = '''
520    {
521        const bool setCc = (bits(machInst, 20) == 1);
522        const uint32_t unrotated = bits(machInst, 7, 0);
523        const uint32_t rotation = (bits(machInst, 11, 8) << 1);
524        const bool rotC = (rotation != 0);
525        const uint32_t imm = rotate_imm(unrotated, rotation);
526        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
527        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
528        switch (OPCODE) {
529    '''
530    decode_block += instCode(0x0, "and")
531    decode_block += instCode(0x1, "eor")
532    decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0")
533    decode_block += instCode(0x3, "rsb")
534    decode_block += adrCode(0x4, "add", add="(IntRegIndex)1")
535    decode_block += instCode(0x5, "adc")
536    decode_block += instCode(0x6, "sbc")
537    decode_block += instCode(0x7, "rsc")
538    decode_block += instCode(0x8, "tst", useDest = False)
539    decode_block += instCode(0x9, "teq", useDest = False)
540    decode_block += instCode(0xa, "cmp", useDest = False)
541    decode_block += instCode(0xb, "cmn", useDest = False)
542    decode_block += instCode(0xc, "orr")
543    decode_block += instCode(0xd, "mov", useOp1 = False)
544    decode_block += instCode(0xe, "bic")
545    decode_block += instCode(0xf, "mvn", useOp1 = False)
546    decode_block += '''
547          default:
548            return new Unknown(machInst);
549        }
550    }
551    '''
552}};
553
554def format ArmSatAddSub() {{
555    decode_block = '''
556    {
557        IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
558        IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
559        IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
560        switch (OPCODE) {
561          case 0x8:
562            return new QaddRegCc(machInst, rd, rm, rn, 0, LSL);
563          case 0x9:
564            return new QsubRegCc(machInst, rd, rm, rn, 0, LSL);
565          case 0xa:
566            return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL);
567          case 0xb:
568            return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL);
569          default:
570            return new Unknown(machInst);
571        }
572    }
573    '''
574}};
575
576def format Thumb32DataProcReg() {{
577    decode_block = '''
578    {
579        const uint32_t op1 = bits(machInst, 23, 20);
580        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
581        const uint32_t op2 = bits(machInst, 7, 4);
582        if (bits(machInst, 15, 12) != 0xf) {
583            return new Unknown(machInst);
584        }
585        if (bits(op1, 3) != 1) {
586            if (op2 == 0) {
587                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
588                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
589                switch (bits(op1, 2, 0)) {
590                  case 0x0:
591                    return new MovRegReg(machInst, rd,
592                            INTREG_ZERO, rn, rm, LSL);
593                  case 0x1:
594                    return new MovRegRegCc(machInst, rd,
595                            INTREG_ZERO, rn, rm, LSL);
596                  case 0x2:
597                    return new MovRegReg(machInst, rd,
598                            INTREG_ZERO, rn, rm, LSR);
599                  case 0x3:
600                    return new MovRegRegCc(machInst, rd,
601                            INTREG_ZERO, rn, rm, LSR);
602                  case 0x4:
603                    return new MovRegReg(machInst, rd,
604                            INTREG_ZERO, rn, rm, ASR);
605                  case 0x5:
606                    return new MovRegRegCc(machInst, rd,
607                            INTREG_ZERO, rn, rm, ASR);
608                  case 0x6:
609                    return new MovRegReg(machInst, rd,
610                            INTREG_ZERO, rn, rm, ROR);
611                  case 0x7:
612                    return new MovRegRegCc(machInst, rd,
613                            INTREG_ZERO, rn, rm, ROR);
614                }
615            } else if (bits(op2, 3) == 0) {
616                return new Unknown(machInst);
617            } else {
618                const IntRegIndex rd =
619                    (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
620                const IntRegIndex rm =
621                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
622                const uint32_t rotation =
623                    (uint32_t)bits(machInst, 5, 4) << 3;
624                switch (bits(op1, 2, 0)) {
625                  case 0x0:
626                    if (rn == 0xf) {
627                        return new Sxth(machInst, rd, rotation, rm);
628                    } else {
629                        return new Sxtah(machInst, rd, rn, rm, rotation);
630                    }
631                  case 0x1:
632                    if (rn == 0xf) {
633                        return new Uxth(machInst, rd, rotation, rm);
634                    } else {
635                        return new Uxtah(machInst, rd, rn, rm, rotation);
636                    }
637                  case 0x2:
638                    if (rn == 0xf) {
639                        return new Sxtb16(machInst, rd, rotation, rm);
640                    } else {
641                        return new Sxtab16(machInst, rd, rn, rm, rotation);
642                    }
643                  case 0x3:
644                    if (rn == 0xf) {
645                        return new Uxtb16(machInst, rd, rotation, rm);
646                    } else {
647                        return new Uxtab16(machInst, rd, rn, rm, rotation);
648                    }
649                  case 0x4:
650                    if (rn == 0xf) {
651                        return new Sxtb(machInst, rd, rotation, rm);
652                    } else {
653                        return new Sxtab(machInst, rd, rn, rm, rotation);
654                    }
655                  case 0x5:
656                    if (rn == 0xf) {
657                        return new Uxtb(machInst, rd, rotation, rm);
658                    } else {
659                        return new Uxtab(machInst, rd, rn, rm, rotation);
660                    }
661                  default:
662                    return new Unknown(machInst);
663                }
664            }
665        } else {
666            if (bits(op2, 3) == 0) {
667                const IntRegIndex rd =
668                    (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
669                const IntRegIndex rm =
670                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
671                if (bits(op2, 2) == 0x0) {
672                    const uint32_t op1 = bits(machInst, 22, 20);
673                    const uint32_t op2 = bits(machInst, 5, 4);
674                    switch (op2) {
675                      case 0x0:
676                        switch (op1) {
677                          case 0x1:
678                            return new Sadd16RegCc(machInst, rd,
679                                                   rn, rm, 0, LSL);
680                          case 0x2:
681                            return new SasxRegCc(machInst, rd,
682                                                 rn, rm, 0, LSL);
683                          case 0x6:
684                            return new SsaxRegCc(machInst, rd,
685                                                 rn, rm, 0, LSL);
686                          case 0x5:
687                            return new Ssub16RegCc(machInst, rd,
688                                                   rn, rm, 0, LSL);
689                          case 0x0:
690                            return new Sadd8RegCc(machInst, rd,
691                                                  rn, rm, 0, LSL);
692                          case 0x4:
693                            return new Ssub8RegCc(machInst, rd,
694                                                  rn, rm, 0, LSL);
695                        }
696                        break;
697                      case 0x1:
698                        switch (op1) {
699                          case 0x1:
700                            return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
701                          case 0x2:
702                            return new QasxReg(machInst, rd, rn, rm, 0, LSL);
703                          case 0x6:
704                            return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
705                          case 0x5:
706                            return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
707                          case 0x0:
708                            return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
709                          case 0x4:
710                            return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
711                        }
712                        break;
713                      case 0x2:
714                        switch (op1) {
715                          case 0x1:
716                            return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL);
717                          case 0x2:
718                            return new ShasxReg(machInst, rd, rn, rm, 0, LSL);
719                          case 0x6:
720                            return new ShsaxReg(machInst, rd, rn, rm, 0, LSL);
721                          case 0x5:
722                            return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL);
723                          case 0x0:
724                            return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL);
725                          case 0x4:
726                            return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL);
727                        }
728                        break;
729                    }
730                } else {
731                    const uint32_t op1 = bits(machInst, 22, 20);
732                    const uint32_t op2 = bits(machInst, 5, 4);
733                    switch (op2) {
734                      case 0x0:
735                        switch (op1) {
736                          case 0x1:
737                            return new Uadd16RegCc(machInst, rd,
738                                                   rn, rm, 0, LSL);
739                          case 0x2:
740                            return new UasxRegCc(machInst, rd,
741                                                 rn, rm, 0, LSL);
742                          case 0x6:
743                            return new UsaxRegCc(machInst, rd,
744                                                 rn, rm, 0, LSL);
745                          case 0x5:
746                            return new Usub16RegCc(machInst, rd,
747                                                   rn, rm, 0, LSL);
748                          case 0x0:
749                            return new Uadd8RegCc(machInst, rd,
750                                                  rn, rm, 0, LSL);
751                          case 0x4:
752                            return new Usub8RegCc(machInst, rd,
753                                                  rn, rm, 0, LSL);
754                        }
755                        break;
756                      case 0x1:
757                        switch (op1) {
758                          case 0x1:
759                            return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
760                          case 0x2:
761                            return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
762                          case 0x6:
763                            return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
764                          case 0x5:
765                            return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
766                          case 0x0:
767                            return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
768                          case 0x4:
769                            return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
770                        }
771                        break;
772                      case 0x2:
773                        switch (op1) {
774                          case 0x1:
775                            return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL);
776                          case 0x2:
777                            return new UhasxReg(machInst, rd, rn, rm, 0, LSL);
778                          case 0x6:
779                            return new UhsaxReg(machInst, rd, rn, rm, 0, LSL);
780                          case 0x5:
781                            return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL);
782                          case 0x0:
783                            return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL);
784                          case 0x4:
785                            return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL);
786                        }
787                        break;
788                    }
789                }
790            } else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) {
791                const uint32_t op1 = bits(machInst, 22, 20);
792                const uint32_t op2 = bits(machInst, 5, 4);
793                const IntRegIndex rd =
794                    (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
795                const IntRegIndex rm =
796                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
797                switch (op1) {
798                  case 0x0:
799                    switch (op2) {
800                      case 0x0:
801                        return new QaddRegCc(machInst, rd,
802                                             rm, rn, 0, LSL);
803                      case 0x1:
804                        return new QdaddRegCc(machInst, rd,
805                                              rm, rn, 0, LSL);
806                      case 0x2:
807                        return new QsubRegCc(machInst, rd,
808                                             rm, rn, 0, LSL);
809                      case 0x3:
810                        return new QdsubRegCc(machInst, rd,
811                                              rm, rn, 0, LSL);
812                    }
813                    break;
814                  case 0x1:
815                    switch (op2) {
816                      case 0x0:
817                        return new Rev(machInst, rd, rn);
818                      case 0x1:
819                        return new Rev16(machInst, rd, rn);
820                      case 0x2:
821                        return new Rbit(machInst, rd, rm);
822                      case 0x3:
823                        return new Revsh(machInst, rd, rn);
824                    }
825                    break;
826                  case 0x2:
827                    if (op2 == 0) {
828                        return new Sel(machInst, rd, rn, rm);
829                    }
830                    break;
831                  case 0x3:
832                    if (op2 == 0) {
833                        return new Clz(machInst, rd, rm);
834                    }
835                    break;
836                  case 0x4:
837                    switch (op2) {
838                      case 0x0:
839                        return new Crc32b(machInst, rd, rn, rm);
840                      case 0x1:
841                        return new Crc32h(machInst, rd, rn, rm);
842                      case 0x2:
843                        return new Crc32w(machInst, rd, rn, rm);
844                    }
845                    break;
846                  case 0x5:
847                    switch (op2) {
848                      case 0x0:
849                        return new Crc32cb(machInst, rd, rn, rm);
850                      case 0x1:
851                        return new Crc32ch(machInst, rd, rn, rm);
852                      case 0x2:
853                        return new Crc32cw(machInst, rd, rn, rm);
854                    }
855                    break;
856                }
857            }
858            return new Unknown(machInst);
859        }
860    }
861    '''
862}};
863
864def format Thumb16ShiftAddSubMoveCmp() {{
865    decode_block = '''
866    {
867        const uint32_t imm5 = bits(machInst, 10, 6);
868        const uint32_t imm3 = bits(machInst, 8, 6);
869        const uint32_t imm8 = bits(machInst, 7, 0);
870        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
871        const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
872        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
873        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
874        switch (bits(machInst, 13, 11)) {
875          case 0x0: // lsl
876            if (machInst.itstateMask) {
877                return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
878            } else {
879                return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
880            }
881          case 0x1: // lsr
882            if (machInst.itstateMask) {
883                return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
884            } else {
885                return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
886            }
887          case 0x2: // asr
888            if (machInst.itstateMask) {
889                return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
890            } else {
891                return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
892            }
893          case 0x3:
894            switch (bits(machInst, 10, 9)) {
895              case 0x0:
896                if (machInst.itstateMask) {
897                    return new AddReg(machInst, rd, rn, rm, 0, LSL);
898                } else {
899                    return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
900                }
901              case 0x1:
902                if (machInst.itstateMask) {
903                    return new SubReg(machInst, rd, rn, rm, 0, LSL);
904                } else {
905                    return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
906                }
907              case 0x2:
908                if (machInst.itstateMask) {
909                    return new AddImm(machInst, rd, rn, imm3, true);
910                } else {
911                    return new AddImmCc(machInst, rd, rn, imm3, true);
912                }
913              case 0x3:
914                if (machInst.itstateMask) {
915                    return new SubImm(machInst, rd, rn, imm3, true);
916                } else {
917                    return new SubImmCc(machInst, rd, rn, imm3, true);
918                }
919            }
920          case 0x4:
921            if (machInst.itstateMask) {
922                return new MovImm(machInst, rd8, INTREG_ZERO, imm8, false);
923            } else {
924                return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
925            }
926          case 0x5:
927            return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
928          case 0x6:
929            if (machInst.itstateMask) {
930                return new AddImm(machInst, rd8, rd8, imm8, true);
931            } else {
932                return new AddImmCc(machInst, rd8, rd8, imm8, true);
933            }
934          case 0x7:
935            if (machInst.itstateMask) {
936                return new SubImm(machInst, rd8, rd8, imm8, true);
937            } else {
938                return new SubImmCc(machInst, rd8, rd8, imm8, true);
939            }
940        }
941    }
942    '''
943}};
944
945def format Thumb16DataProcessing() {{
946    decode_block = '''
947    {
948        const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
949        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
950        switch (bits(machInst, 9, 6)) {
951          case 0x0:
952            if (machInst.itstateMask) {
953                return new AndReg(machInst, rdn, rdn, rm, 0, LSL);
954            } else {
955                return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
956            }
957          case 0x1:
958            if (machInst.itstateMask) {
959                return new EorReg(machInst, rdn, rdn, rm, 0, LSL);
960            } else {
961                return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
962            }
963          case 0x2: //lsl
964            if (machInst.itstateMask) {
965                return new MovRegReg(machInst, rdn,
966                        INTREG_ZERO, rdn, rm, LSL);
967            } else {
968                return new MovRegRegCc(machInst, rdn,
969                        INTREG_ZERO, rdn, rm, LSL);
970            }
971          case 0x3: //lsr
972            if (machInst.itstateMask) {
973                return new MovRegReg(machInst, rdn,
974                        INTREG_ZERO, rdn, rm, LSR);
975            } else {
976                return new MovRegRegCc(machInst, rdn,
977                        INTREG_ZERO, rdn, rm, LSR);
978            }
979          case 0x4: //asr
980            if (machInst.itstateMask) {
981                return new MovRegReg(machInst, rdn,
982                        INTREG_ZERO, rdn, rm, ASR);
983            } else {
984                return new MovRegRegCc(machInst, rdn,
985                        INTREG_ZERO, rdn, rm, ASR);
986            }
987          case 0x5:
988            if (machInst.itstateMask) {
989                return new AdcReg(machInst, rdn, rdn, rm, 0, LSL);
990            } else {
991                return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
992            }
993          case 0x6:
994            if (machInst.itstateMask) {
995                return new SbcReg(machInst, rdn, rdn, rm, 0, LSL);
996            } else {
997                return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
998            }
999          case 0x7: // ror
1000            if (machInst.itstateMask) {
1001                return new MovRegReg(machInst, rdn,
1002                        INTREG_ZERO, rdn, rm, ROR);
1003            } else {
1004                return new MovRegRegCc(machInst, rdn,
1005                        INTREG_ZERO, rdn, rm, ROR);
1006            }
1007          case 0x8:
1008            return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
1009          case 0x9:
1010            if (machInst.itstateMask) {
1011                return new RsbImm(machInst, rdn, rm, 0, true);
1012            } else {
1013                return new RsbImmCc(machInst, rdn, rm, 0, true);
1014            }
1015          case 0xa:
1016            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
1017          case 0xb:
1018            return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
1019          case 0xc:
1020            if (machInst.itstateMask) {
1021                return new OrrReg(machInst, rdn, rdn, rm, 0, LSL);
1022            } else {
1023                return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
1024            }
1025          case 0xd:
1026            if (machInst.itstateMask) {
1027                return new Mul(machInst, rdn, rm, rdn);
1028            } else {
1029                return new MulCc(machInst, rdn, rm, rdn);
1030            }
1031          case 0xe:
1032            if (machInst.itstateMask) {
1033                return new BicReg(machInst, rdn, rdn, rm, 0, LSL);
1034            } else {
1035                return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
1036            }
1037          case 0xf:
1038            if (machInst.itstateMask) {
1039                return new MvnReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
1040            } else {
1041                return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
1042            }
1043        }
1044    }
1045    '''
1046}};
1047
1048def format Thumb16SpecDataAndBx() {{
1049    decode_block = '''
1050    {
1051        const IntRegIndex rdn =
1052            (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
1053                                    (bits(machInst, 7) << 3));
1054        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
1055        switch (bits(machInst, 9, 8)) {
1056          case 0x0:
1057            return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
1058          case 0x1:
1059            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
1060          case 0x2:
1061            return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
1062          case 0x3:
1063            if (bits(machInst, 7) == 0) {
1064                return new BxReg(machInst,
1065                                 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
1066                                 COND_UC);
1067            } else {
1068                return new BlxReg(machInst,
1069                                  (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
1070                                  COND_UC);
1071            }
1072        }
1073    }
1074    '''
1075}};
1076
1077def format Thumb16Adr() {{
1078    decode_block = '''
1079    {
1080        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
1081        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
1082        return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false);
1083    }
1084    '''
1085}};
1086
1087def format Thumb16AddSp() {{
1088    decode_block = '''
1089    {
1090        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
1091        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
1092        return new AddImm(machInst, rd, INTREG_SP, imm8, true);
1093    }
1094    '''
1095}};
1096
1097def format ArmMisc() {{
1098    decode_block = '''
1099    {
1100        const uint32_t unrotated = bits(machInst, 7, 0);
1101        const uint32_t rotation = (bits(machInst, 11, 8) << 1);
1102        const uint32_t imm = rotate_imm(unrotated, rotation);
1103        const uint8_t byteMask = bits(machInst, 19, 16);
1104        switch (OPCODE) {
1105          case 0x8:
1106            return new MovImm(machInst, (IntRegIndex)(uint32_t)RD,
1107                    (IntRegIndex)INTREG_ZERO,
1108                    bits(machInst, 11, 0) | (bits(machInst, 19, 16) << 12),
1109                    false);
1110          case 0x9:
1111            if (RN == 0) {
1112                switch (IMM) {
1113                  case 0x0:
1114                    return new NopInst(machInst);
1115                  case 0x1:
1116                    return new YieldInst(machInst);
1117                  case 0x2:
1118                    return new WfeInst(machInst);
1119                  case 0x3:
1120                    return new WfiInst(machInst);
1121                  case 0x4:
1122                    return new SevInst(machInst);
1123                  default:
1124                    return new Unknown(machInst);
1125                }
1126            } else {
1127                return new MsrCpsrImm(machInst, imm, byteMask);
1128            }
1129          case 0xa:
1130            {
1131                const uint32_t timm = (bits(machInst, 19, 16) << 12) |
1132                                       bits(machInst, 11, 0);
1133                return new MovtImm(machInst, (IntRegIndex)(uint32_t)RD,
1134                                   (IntRegIndex)(uint32_t)RD, timm, true);
1135            }
1136          case 0xb:
1137            return new MsrSpsrImm(machInst, imm, byteMask);
1138          default:
1139            return new Unknown(machInst);
1140        }
1141    }
1142    '''
1143}};
1144
1145def format Thumb16Misc() {{
1146    decode_block = '''
1147    {
1148        switch (bits(machInst, 11, 8)) {
1149          case 0x0:
1150            if (bits(machInst, 7)) {
1151                return new SubImm(machInst, INTREG_SP, INTREG_SP,
1152                                   bits(machInst, 6, 0) << 2, true);
1153            } else {
1154                return new AddImm(machInst, INTREG_SP, INTREG_SP,
1155                                   bits(machInst, 6, 0) << 2, true);
1156            }
1157          case 0x2:
1158            {
1159                const IntRegIndex rd =
1160                    (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
1161                const IntRegIndex rm =
1162                    (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
1163                switch (bits(machInst, 7, 6)) {
1164                  case 0x0:
1165                    return new Sxth(machInst, rd, 0, rm);
1166                  case 0x1:
1167                    return new Sxtb(machInst, rd, 0, rm);
1168                  case 0x2:
1169                    return new Uxth(machInst, rd, 0, rm);
1170                  case 0x3:
1171                    return new Uxtb(machInst, rd, 0, rm);
1172                }
1173            }
1174          case 0x1:
1175          case 0x3:
1176            return new Cbz(machInst,
1177                           (bits(machInst, 9) << 6) |
1178                           (bits(machInst, 7, 3) << 1),
1179                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
1180          case 0x4:
1181          case 0x5:
1182            {
1183                const uint32_t m = bits(machInst, 8);
1184                const uint32_t regList = bits(machInst, 7, 0) | (m << 14);
1185                return new LdmStm(machInst, INTREG_SP, false, false, false,
1186                                  true, false, regList);
1187            }
1188          case 0x6:
1189            {
1190                const uint32_t opBits = bits(machInst, 7, 5);
1191                if (opBits == 2) {
1192                    return new Setend(machInst, bits(machInst, 3));
1193                } else if (opBits == 3) {
1194                    const bool enable = (bits(machInst, 4) == 0);
1195                    const uint32_t mods = (bits(machInst, 2, 0) << 5) |
1196                                          ((enable ? 1 : 0) << 9);
1197                    return new Cps(machInst, mods);
1198                }
1199            }
1200          case 0xa:
1201            {
1202                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
1203                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
1204                switch (bits(machInst, 7, 6)) {
1205                  case 0x0:
1206                    return new Rev(machInst, rd, rm);
1207                  case 0x1:
1208                    return new Rev16(machInst, rd, rm);
1209                  case 0x3:
1210                    return new Revsh(machInst, rd, rm);
1211                  default:
1212                    break;
1213                }
1214            }
1215            break;
1216          case 0x9:
1217          case 0xb:
1218            return new Cbnz(machInst,
1219                            (bits(machInst, 9) << 6) |
1220                            (bits(machInst, 7, 3) << 1),
1221                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
1222          case 0xc:
1223          case 0xd:
1224            {
1225                const uint32_t p = bits(machInst, 8);
1226                const uint32_t regList = bits(machInst, 7, 0) | (p << 15);
1227                return new LdmStm(machInst, INTREG_SP, true, true, false,
1228                                  true, true, regList);
1229            }
1230          case 0xe:
1231            return new BkptInst(machInst);
1232          case 0xf:
1233            if (bits(machInst, 3, 0) != 0)
1234                return new ItInst(machInst);
1235            switch (bits(machInst, 7, 4)) {
1236              case 0x0:
1237                return new NopInst(machInst);
1238              case 0x1:
1239                return new YieldInst(machInst);
1240              case 0x2:
1241                return new WfeInst(machInst);
1242              case 0x3:
1243                return new WfiInst(machInst);
1244              case 0x4:
1245                return new SevInst(machInst);
1246              default:
1247                return new WarnUnimplemented("unallocated_hint", machInst);
1248            }
1249          default:
1250            break;
1251        }
1252        return new Unknown(machInst);
1253    }
1254    '''
1255}};
1256
1257def format Thumb32DataProcModImm() {{
1258
1259    def decInst(mnem, dest="rd", op1="rn"):
1260        return '''
1261            if (s) {
1262                return new %(mnem)sImmCc(machInst, %(dest)s,
1263                                          %(op1)s, imm, rotC);
1264            } else {
1265                return new %(mnem)sImm(machInst, %(dest)s,
1266                                        %(op1)s, imm, rotC);
1267            }
1268        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
1269
1270    decode_block = '''
1271    {
1272        const uint32_t op = bits(machInst, 24, 21);
1273        const bool s = (bits(machInst, 20) == 1);
1274        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1275        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1276        const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
1277                                 bits(machInst, 14, 12);
1278        const bool rotC = ctrlImm > 3;
1279        const uint32_t dataImm = bits(machInst, 7, 0);
1280        const uint32_t imm = modified_imm(ctrlImm, dataImm);
1281        switch (op) {
1282          case 0x0:
1283            if (rd == INTREG_PC) {
1284                %(tst)s
1285            } else {
1286                %(and)s
1287            }
1288          case 0x1:
1289            %(bic)s
1290          case 0x2:
1291            if (rn == INTREG_PC) {
1292                %(mov)s
1293            } else {
1294                %(orr)s
1295            }
1296          case 0x3:
1297            if (rn == INTREG_PC) {
1298                %(mvn)s
1299            } else {
1300                %(orn)s
1301            }
1302          case 0x4:
1303            if (rd == INTREG_PC) {
1304                %(teq)s
1305            } else {
1306                %(eor)s
1307            }
1308          case 0x8:
1309            if (rd == INTREG_PC) {
1310                %(cmn)s
1311            } else {
1312                %(add)s
1313            }
1314          case 0xa:
1315            %(adc)s
1316          case 0xb:
1317            %(sbc)s
1318          case 0xd:
1319            if (rd == INTREG_PC) {
1320                %(cmp)s
1321            } else {
1322                %(sub)s
1323            }
1324          case 0xe:
1325            %(rsb)s
1326          default:
1327            return new Unknown(machInst);
1328        }
1329    }
1330    ''' % {
1331        "tst" : decInst("Tst", "INTREG_ZERO"),
1332        "and" : decInst("And"),
1333        "bic" : decInst("Bic"),
1334        "mov" : decInst("Mov", op1="INTREG_ZERO"),
1335        "orr" : decInst("Orr"),
1336        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
1337        "orn" : decInst("Orn"),
1338        "teq" : decInst("Teq", dest="INTREG_ZERO"),
1339        "eor" : decInst("Eor"),
1340        "cmn" : decInst("Cmn", dest="INTREG_ZERO"),
1341        "add" : decInst("Add"),
1342        "adc" : decInst("Adc"),
1343        "sbc" : decInst("Sbc"),
1344        "cmp" : decInst("Cmp", dest="INTREG_ZERO"),
1345        "sub" : decInst("Sub"),
1346        "rsb" : decInst("Rsb")
1347    }
1348}};
1349
1350def format Thumb32DataProcPlainBin() {{
1351    decode_block = '''
1352    {
1353        const uint32_t op = bits(machInst, 24, 20);
1354        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1355        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1356        switch (op) {
1357          case 0x0:
1358            {
1359                const uint32_t imm = bits(machInst, 7, 0) |
1360                                     (bits(machInst, 14, 12) << 8) |
1361                                     (bits(machInst, 26) << 11);
1362                if (rn == 0xf) {
1363                    return new AdrImm(machInst, rd, (IntRegIndex)1,
1364                                      imm, false);
1365                } else {
1366                    return new AddImm(machInst, rd, rn, imm, true);
1367                }
1368            }
1369          case 0x4:
1370            {
1371                const uint32_t imm = bits(machInst, 7, 0) |
1372                                     (bits(machInst, 14, 12) << 8) |
1373                                     (bits(machInst, 26) << 11) |
1374                                     (bits(machInst, 19, 16) << 12);
1375                return new MovImm(machInst, rd, INTREG_ZERO, imm, true);
1376            }
1377          case 0xa:
1378            {
1379                const uint32_t imm = bits(machInst, 7, 0) |
1380                                     (bits(machInst, 14, 12) << 8) |
1381                                     (bits(machInst, 26) << 11);
1382                if (rn == 0xf) {
1383                    return new AdrImm(machInst, rd, (IntRegIndex)0,
1384                                      imm, false);
1385                } else {
1386                    return new SubImm(machInst, rd, rn, imm, true);
1387                }
1388            }
1389          case 0xc:
1390            {
1391                const uint32_t imm = bits(machInst, 7, 0) |
1392                                     (bits(machInst, 14, 12) << 8) |
1393                                     (bits(machInst, 26) << 11) |
1394                                     (bits(machInst, 19, 16) << 12);
1395                return new MovtImm(machInst, rd, rd, imm, true);
1396            }
1397          case 0x12:
1398            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
1399                const uint32_t satImm = bits(machInst, 4, 0);
1400                return new Ssat16(machInst, rd, satImm + 1, rn);
1401            }
1402            // Fall through on purpose...
1403          case 0x10:
1404            {
1405                const uint32_t satImm = bits(machInst, 4, 0);
1406                const uint32_t imm = bits(machInst, 7, 6) |
1407                                     (bits(machInst, 14, 12) << 2);
1408                const ArmShiftType type =
1409                    (ArmShiftType)(uint32_t)bits(machInst, 21, 20);
1410                return new Ssat(machInst, rd, satImm + 1, rn, imm, type);
1411            }
1412          case 0x14:
1413            {
1414                const uint32_t lsb = bits(machInst, 7, 6) |
1415                                     (bits(machInst, 14, 12) << 2);
1416                const uint32_t msb = lsb + bits(machInst, 4, 0);
1417                return new Sbfx(machInst, rd, rn, lsb, msb);
1418            }
1419          case 0x16:
1420            {
1421                const uint32_t lsb = bits(machInst, 7, 6) |
1422                                     (bits(machInst, 14, 12) << 2);
1423                const uint32_t msb = bits(machInst, 4, 0);
1424                if (rn == 0xf) {
1425                    return new Bfc(machInst, rd, rd, lsb, msb);
1426                } else {
1427                    return new Bfi(machInst, rd, rn, lsb, msb);
1428                }
1429            }
1430          case 0x1a:
1431            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
1432                const uint32_t satImm = bits(machInst, 4, 0);
1433                return new Usat16(machInst, rd, satImm, rn);
1434            }
1435            // Fall through on purpose...
1436          case 0x18:
1437            {
1438                const uint32_t satImm = bits(machInst, 4, 0);
1439                const uint32_t imm = bits(machInst, 7, 6) |
1440                                     (bits(machInst, 14, 12) << 2);
1441                const ArmShiftType type =
1442                    (ArmShiftType)(uint32_t)bits(machInst, 21, 20);
1443                return new Usat(machInst, rd, satImm, rn, imm, type);
1444            }
1445          case 0x1c:
1446            {
1447                const uint32_t lsb = bits(machInst, 7, 6) |
1448                                     (bits(machInst, 14, 12) << 2);
1449                const uint32_t msb = lsb + bits(machInst, 4, 0);
1450                return new Ubfx(machInst, rd, rn, lsb, msb);
1451            }
1452          default:
1453            return new Unknown(machInst);
1454        }
1455    }
1456    '''
1457}};
1458
1459def format Thumb32DataProcShiftReg() {{
1460
1461    def decInst(mnem, dest="rd", op1="rn"):
1462        return '''
1463            if (s) {
1464                return new %(mnem)sRegCc(machInst, %(dest)s,
1465                                          %(op1)s, rm, amt, type);
1466            } else {
1467                return new %(mnem)sReg(machInst, %(dest)s,
1468                                        %(op1)s, rm, amt, type);
1469            }
1470        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
1471
1472    decode_block = '''
1473    {
1474        const uint32_t op = bits(machInst, 24, 21);
1475        const bool s = (bits(machInst, 20) == 1);
1476        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1477        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1478        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
1479        const uint32_t amt = (bits(machInst, 14, 12) << 2) |
1480                              bits(machInst, 7, 6);
1481        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
1482        switch (op) {
1483          case 0x0:
1484            if (rd == INTREG_PC) {
1485                %(tst)s
1486            } else {
1487                %(and)s
1488            }
1489          case 0x1:
1490            %(bic)s
1491          case 0x2:
1492            if (rn == INTREG_PC) {
1493                %(mov)s
1494            } else {
1495                %(orr)s
1496            }
1497          case 0x3:
1498            if (rn == INTREG_PC) {
1499                %(mvn)s
1500            } else {
1501                %(orn)s
1502            }
1503          case 0x4:
1504            if (rd == INTREG_PC) {
1505                %(teq)s
1506            } else {
1507                %(eor)s
1508            }
1509          case 0x6:
1510            if (type) {
1511                return new PkhtbReg(machInst, rd, rn, rm, amt, type);
1512            } else {
1513                return new PkhbtReg(machInst, rd, rn, rm, amt, type);
1514            }
1515          case 0x8:
1516            if (rd == INTREG_PC) {
1517                %(cmn)s
1518            } else {
1519                %(add)s
1520            }
1521          case 0xa:
1522            %(adc)s
1523          case 0xb:
1524            %(sbc)s
1525          case 0xd:
1526            if (rd == INTREG_PC) {
1527                %(cmp)s
1528            } else {
1529                %(sub)s
1530            }
1531          case 0xe:
1532            %(rsb)s
1533          default:
1534            return new Unknown(machInst);
1535        }
1536    }
1537    ''' % {
1538        "tst" : decInst("Tst", "INTREG_ZERO"),
1539        "and" : decInst("And"),
1540        "bic" : decInst("Bic"),
1541        "mov" : decInst("Mov", op1="INTREG_ZERO"),
1542        "orr" : decInst("Orr"),
1543        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
1544        "orn" : decInst("Orn"),
1545        "teq" : decInst("Teq", "INTREG_ZERO"),
1546        "eor" : decInst("Eor"),
1547        "cmn" : decInst("Cmn", "INTREG_ZERO"),
1548        "add" : decInst("Add"),
1549        "adc" : decInst("Adc"),
1550        "sbc" : decInst("Sbc"),
1551        "cmp" : decInst("Cmp", "INTREG_ZERO"),
1552        "sub" : decInst("Sub"),
1553        "rsb" : decInst("Rsb")
1554    }
1555}};
1556