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