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