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