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