data.isa revision 7210:10d2d0e1e39d
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            if (op1 == 0) {
135                return new WarnUnimplemented("pkh", machInst);
136            } else if (bits(op1, 2, 1) == 1) {
137                return new WarnUnimplemented("ssat", machInst);
138            } else if (bits(op1, 2, 1) == 3) {
139                return new WarnUnimplemented("usat", machInst);
140            }
141            return new Unknown(machInst);
142        }
143        switch (op1) {
144          case 0x0:
145            if (op2 == 0x3) {
146                if (a == 0xf) {
147                    return new WarnUnimplemented("sxtb16", machInst);
148                } else {
149                    return new WarnUnimplemented("sxtab16", machInst);
150                }
151            } else if (op2 == 0x5) {
152                return new WarnUnimplemented("sel", machInst);
153            }
154            break;
155          case 0x2:
156            if (op2 == 0x1) {
157                return new WarnUnimplemented("ssat16", machInst);
158            } else if (op2 == 0x3) {
159                if (a == 0xf) {
160                    return new WarnUnimplemented("sxtb", machInst);
161                } else {
162                    return new WarnUnimplemented("sxtab", machInst);
163                }
164            }
165            break;
166          case 0x3:
167            if (op2 == 0x1) {
168                return new WarnUnimplemented("rev", machInst);
169            } else if (op2 == 0x3) {
170                if (a == 0xf) {
171                    return new WarnUnimplemented("sxth", machInst);
172                } else {
173                    return new WarnUnimplemented("sxtah", machInst);
174                }
175            } else if (op2 == 0x5) {
176                return new WarnUnimplemented("rev16", machInst);
177            }
178            break;
179          case 0x4:
180            if (op2 == 0x3) {
181                if (a == 0xf) {
182                    return new WarnUnimplemented("uxtb16", machInst);
183                } else {
184                    return new WarnUnimplemented("uxtab16", machInst);
185                }
186            }
187            break;
188          case 0x6:
189            if (op2 == 0x1) {
190                return new WarnUnimplemented("usat16", machInst);
191            } else if (op2 == 0x3) {
192                if (a == 0xf) {
193                    return new WarnUnimplemented("uxtb", machInst);
194                } else {
195                    return new WarnUnimplemented("uxtab", machInst);
196                }
197            }
198            break;
199          case 0x7:
200            if (op2 == 0x1) {
201                return new WarnUnimplemented("rbit", machInst);
202            } else if (op2 == 0x3) {
203                if (a == 0xf) {
204                    return new WarnUnimplemented("uxth", machInst);
205                } else {
206                    return new WarnUnimplemented("uxtah", machInst);
207                }
208            } else if (op2 == 0x5) {
209                return new WarnUnimplemented("revsh", machInst);
210            }
211            break;
212        }
213        return new Unknown(machInst);
214    }
215    '''
216}};
217
218def format ArmParallelAddSubtract() {{
219    decode_block='''
220    {
221        const uint32_t op1 = bits(machInst, 21, 20);
222        const uint32_t op2 = bits(machInst, 7, 5);
223        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
224        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
225        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
226        if (bits(machInst, 22) == 0) {
227            switch (op1) {
228              case 0x1:
229                switch (op2) {
230                  case 0x0:
231                    return new WarnUnimplemented("sadd16", machInst);
232                  case 0x1:
233                    return new WarnUnimplemented("sasx", machInst);
234                  case 0x2:
235                    return new WarnUnimplemented("ssax", machInst);
236                  case 0x3:
237                    return new WarnUnimplemented("ssub16", machInst);
238                  case 0x4:
239                    return new WarnUnimplemented("sadd8", machInst);
240                  case 0x7:
241                    return new WarnUnimplemented("ssub8", machInst);
242                }
243                break;
244              case 0x2:
245                switch (op2) {
246                  case 0x0:
247                    return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
248                  case 0x1:
249                    return new QasxReg(machInst, rd, rn, rm, 0, LSL);
250                  case 0x2:
251                    return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
252                  case 0x3:
253                    return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
254                  case 0x4:
255                    return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
256                  case 0x7:
257                    return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
258                }
259                break;
260              case 0x3:
261                switch (op2) {
262                  case 0x0:
263                    return new WarnUnimplemented("shadd16", machInst);
264                  case 0x1:
265                    return new WarnUnimplemented("shasx", machInst);
266                  case 0x2:
267                    return new WarnUnimplemented("shsax", machInst);
268                  case 0x3:
269                    return new WarnUnimplemented("shsub16", machInst);
270                  case 0x4:
271                    return new WarnUnimplemented("shadd8", machInst);
272                  case 0x7:
273                    return new WarnUnimplemented("shsub8", machInst);
274                }
275                break;
276            }
277        } else {
278            switch (op1) {
279              case 0x1:
280                switch (op2) {
281                  case 0x0:
282                    return new WarnUnimplemented("uadd16", machInst);
283                  case 0x1:
284                    return new WarnUnimplemented("uasx", machInst);
285                  case 0x2:
286                    return new WarnUnimplemented("usax", machInst);
287                  case 0x3:
288                    return new WarnUnimplemented("usub16", machInst);
289                  case 0x4:
290                    return new WarnUnimplemented("uadd8", machInst);
291                  case 0x7:
292                    return new WarnUnimplemented("usub8", machInst);
293                }
294                break;
295              case 0x2:
296                switch (op2) {
297                  case 0x0:
298                    return new WarnUnimplemented("uqadd16", machInst);
299                  case 0x1:
300                    return new WarnUnimplemented("uqasx", machInst);
301                  case 0x2:
302                    return new WarnUnimplemented("uqsax", machInst);
303                  case 0x3:
304                    return new WarnUnimplemented("uqsub16", machInst);
305                  case 0x4:
306                    return new WarnUnimplemented("uqadd8", machInst);
307                  case 0x7:
308                    return new WarnUnimplemented("uqsub8", machInst);
309                }
310                break;
311              case 0x3:
312                switch (op2) {
313                  case 0x0:
314                    return new WarnUnimplemented("uhadd16", machInst);
315                  case 0x1:
316                    return new WarnUnimplemented("uhasx", machInst);
317                  case 0x2:
318                    return new WarnUnimplemented("uhsax", machInst);
319                  case 0x3:
320                    return new WarnUnimplemented("uhsub16", machInst);
321                  case 0x4:
322                    return new WarnUnimplemented("uhadd8", machInst);
323                  case 0x7:
324                    return new WarnUnimplemented("uhsub8", machInst);
325                }
326                break;
327            }
328        }
329        return new Unknown(machInst);
330    }
331    '''
332}};
333
334def format ArmDataProcImm() {{
335    pclr = '''
336        return new %(className)ssImmPclr(machInst, %(dest)s,
337                                        %(op1)s, imm, false);
338    '''
339    adr = '''
340        return new AdrImm(machInst, %(dest)s, %(add)s,
341                                     imm, false);
342    '''
343    instDecode = '''
344          case %(opcode)#x:
345            if (setCc) {
346                if (%(pclrInst)s && %(dest)s == INTREG_PC) {
347                    %(pclr)s
348                } else {
349                    return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
350                                                   imm, rotC);
351                }
352            } else {
353                if (%(adrInst)s && %(op1)s == INTREG_PC) {
354                    %(adr)s
355                } else {
356                    return new %(className)sImm(machInst, %(dest)s, %(op1)s,
357                                                 imm, rotC);
358                }
359            }
360            break;
361    '''
362
363    def instCode(opcode, mnem, useDest = True, useOp1 = True):
364        global instDecode, pclr, adr
365        if useDest:
366            dest = "rd"
367        else:
368            dest = "INTREG_ZERO"
369        if useOp1:
370            op1 = "rn"
371        else:
372            op1 = "INTREG_ZERO"
373        substDict = { "className": mnem.capitalize(),
374                      "opcode": opcode,
375                      "dest": dest,
376                      "op1": op1,
377                      "adr": "",
378                      "adrInst": "false" }
379        if useDest:
380            substDict["pclrInst"] = "true"
381            substDict["pclr"] = pclr % substDict
382        else:
383            substDict["pclrInst"] = "false"
384            substDict["pclr"] = ""
385        return instDecode % substDict
386
387    def adrCode(opcode, mnem, add="1"):
388        global instDecode, pclr, adr
389        substDict = { "className": mnem.capitalize(),
390                      "opcode": opcode,
391                      "dest": "rd",
392                      "op1": "rn",
393                      "add": add,
394                      "pclrInst": "true",
395                      "adrInst": "true" }
396        substDict["pclr"] = pclr % substDict
397        substDict["adr"] = adr % substDict
398        return instDecode % substDict
399
400    decode_block = '''
401    {
402        const bool setCc = (bits(machInst, 20) == 1);
403        const uint32_t unrotated = bits(machInst, 7, 0);
404        const uint32_t rotation = (bits(machInst, 11, 8) << 1);
405        const bool rotC = (rotation != 0);
406        const uint32_t imm = rotate_imm(unrotated, rotation);
407        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
408        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
409        switch (OPCODE) {
410    '''
411    decode_block += instCode(0x0, "and")
412    decode_block += instCode(0x1, "eor")
413    decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0")
414    decode_block += instCode(0x3, "rsb")
415    decode_block += adrCode(0x4, "add", add="(IntRegIndex)1")
416    decode_block += instCode(0x5, "adc")
417    decode_block += instCode(0x6, "sbc")
418    decode_block += instCode(0x7, "rsc")
419    decode_block += instCode(0x8, "tst", useDest = False)
420    decode_block += instCode(0x9, "teq", useDest = False)
421    decode_block += instCode(0xa, "cmp", useDest = False)
422    decode_block += instCode(0xb, "cmn", useDest = False)
423    decode_block += instCode(0xc, "orr")
424    decode_block += instCode(0xd, "mov", useOp1 = False)
425    decode_block += instCode(0xe, "bic")
426    decode_block += instCode(0xf, "mvn", useOp1 = False)
427    decode_block += '''
428          default:
429            return new Unknown(machInst);
430        }
431    }
432    '''
433}};
434
435def format ArmSatAddSub() {{
436    decode_block = '''
437    {
438        IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
439        IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
440        IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
441        switch (OPCODE) {
442          case 0x8:
443            return new QaddRegCc(machInst, rd, rm, rn, 0, LSL);
444          case 0x9:
445            return new QsubRegCc(machInst, rd, rm, rn, 0, LSL);
446          case 0xa:
447            return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL);
448          case 0xb:
449            return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL);
450          default:
451            return new Unknown(machInst);
452        }
453    }
454    '''
455}};
456
457def format Thumb16ShiftAddSubMoveCmp() {{
458    decode_block = '''
459    {
460        const uint32_t imm5 = bits(machInst, 10, 6);
461        const uint32_t imm3 = bits(machInst, 8, 6);
462        const uint32_t imm8 = bits(machInst, 7, 0);
463        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
464        const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
465        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
466        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
467        switch (bits(machInst, 13, 11)) {
468          case 0x0: // lsl
469            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
470          case 0x1: // lsr
471            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
472          case 0x2: // asr
473            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
474          case 0x3:
475            switch (bits(machInst, 10, 9)) {
476              case 0x0:
477                return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
478              case 0x1:
479                return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
480              case 0x2:
481                return new AddImmCc(machInst, rd, rn, imm3, true);
482              case 0x3:
483                return new SubImmCc(machInst, rd, rn, imm3, true);
484            }
485          case 0x4:
486            return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
487          case 0x5:
488            return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
489          case 0x6:
490            return new AddImmCc(machInst, rd8, rd8, imm8, true);
491          case 0x7:
492            return new SubImmCc(machInst, rd8, rd8, imm8, true);
493        }
494    }
495    '''
496}};
497
498def format Thumb16DataProcessing() {{
499    decode_block = '''
500    {
501        const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
502        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
503        switch (bits(machInst, 9, 6)) {
504          case 0x0:
505            return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
506          case 0x1:
507            return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
508          case 0x2: //lsl
509            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
510          case 0x3: //lsr
511            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
512          case 0x4: //asr
513            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
514          case 0x5:
515            return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
516          case 0x6:
517            return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
518          case 0x7: // ror
519            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
520          case 0x8:
521            return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
522          case 0x9:
523            return new RsbImmCc(machInst, rdn, rm, 0, true);
524          case 0xa:
525            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
526          case 0xb:
527            return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
528          case 0xc:
529            return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
530          case 0xd:
531            return new MulCc(machInst, rdn, rm, rdn);
532          case 0xe:
533            return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
534          case 0xf:
535            return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
536        }
537    }
538    '''
539}};
540
541def format Thumb16SpecDataAndBx() {{
542    decode_block = '''
543    {
544        const IntRegIndex rdn =
545            (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
546                                    (bits(machInst, 7) << 3));
547        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
548        switch (bits(machInst, 9, 8)) {
549          case 0x0:
550            return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
551          case 0x1:
552            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
553          case 0x2:
554            return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
555          case 0x3:
556            if (bits(machInst, 7) == 0) {
557                return new BxReg(machInst,
558                                 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
559                                 COND_UC);
560            } else {
561                return new BlxReg(machInst,
562                                  (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
563                                  COND_UC);
564            }
565        }
566    }
567    '''
568}};
569
570def format Thumb16Adr() {{
571    decode_block = '''
572    {
573        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
574        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
575        return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false);
576    }
577    '''
578}};
579
580def format Thumb16AddSp() {{
581    decode_block = '''
582    {
583        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
584        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
585        return new AddImm(machInst, rd, INTREG_SP, imm8, true);
586    }
587    '''
588}};
589
590def format Thumb16Misc() {{
591    decode_block = '''
592    {
593        switch (bits(machInst, 11, 8)) {
594          case 0x0:
595            if (bits(machInst, 7)) {
596                return new SubImm(machInst, INTREG_SP, INTREG_SP,
597                                   bits(machInst, 6, 0) << 2, true);
598            } else {
599                return new AddImm(machInst, INTREG_SP, INTREG_SP,
600                                   bits(machInst, 6, 0) << 2, true);
601            }
602          case 0x1:
603            return new Cbz(machInst,
604                           (bits(machInst, 9) << 6) |
605                           (bits(machInst, 7, 3) << 1),
606                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
607          case 0x2:
608            switch (bits(machInst, 7, 6)) {
609              case 0x0:
610                return new WarnUnimplemented("sxth", machInst);
611              case 0x1:
612                return new WarnUnimplemented("sxtb", machInst);
613              case 0x2:
614                return new WarnUnimplemented("uxth", machInst);
615              case 0x3:
616                return new WarnUnimplemented("uxtb", machInst);
617            }
618          case 0x3:
619            return new Cbz(machInst,
620                           (bits(machInst, 9) << 6) |
621                           (bits(machInst, 7, 3) << 1),
622                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
623          case 0x4:
624          case 0x5:
625            {
626                const uint32_t m = bits(machInst, 8);
627                const uint32_t regList = bits(machInst, 7, 0) | (m << 14);
628                return new LdmStm(machInst, INTREG_SP, false, false, false,
629                                  true, false, regList);
630            }
631          case 0x6:
632            {
633                const uint32_t opBits = bits(machInst, 7, 5);
634                if (opBits == 2) {
635                    return new WarnUnimplemented("setend", machInst);
636                } else if (opBits == 3) {
637                    return new WarnUnimplemented("cps", machInst);
638                }
639            }
640          case 0x9:
641            return new Cbnz(machInst,
642                            (bits(machInst, 9) << 6) |
643                            (bits(machInst, 7, 3) << 1),
644                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
645          case 0xa:
646            switch (bits(machInst, 7, 5)) {
647              case 0x0:
648                return new WarnUnimplemented("rev", machInst);
649              case 0x1:
650                return new WarnUnimplemented("rev16", machInst);
651              case 0x3:
652                return new WarnUnimplemented("revsh", machInst);
653              default:
654                break;
655            }
656            break;
657          case 0xb:
658            return new Cbnz(machInst,
659                            (bits(machInst, 9) << 6) |
660                            (bits(machInst, 7, 3) << 1),
661                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
662          case 0xc:
663          case 0xd:
664            {
665                const uint32_t p = bits(machInst, 8);
666                const uint32_t regList = bits(machInst, 7, 0) | (p << 15);
667                return new LdmStm(machInst, INTREG_SP, true, true, false,
668                                  true, true, regList);
669            }
670          case 0xe:
671            return new WarnUnimplemented("bkpt", machInst);
672          case 0xf:
673            if (bits(machInst, 3, 0) != 0)
674                return new WarnUnimplemented("it", machInst);
675            switch (bits(machInst, 7, 4)) {
676              case 0x0:
677                return new WarnUnimplemented("nop", machInst);
678              case 0x1:
679                return new WarnUnimplemented("yield", machInst);
680              case 0x2:
681                return new WarnUnimplemented("wfe", machInst);
682              case 0x3:
683                return new WarnUnimplemented("wfi", machInst);
684              case 0x4:
685                return new WarnUnimplemented("sev", machInst);
686              default:
687                return new WarnUnimplemented("unallocated_hint", machInst);
688            }
689          default:
690            break;
691        }
692        return new Unknown(machInst);
693    }
694    '''
695}};
696
697def format Thumb32DataProcModImm() {{
698
699    def decInst(mnem, dest="rd", op1="rn"):
700        return '''
701            if (s) {
702                return new %(mnem)sImmCc(machInst, %(dest)s,
703                                          %(op1)s, imm, rotC);
704            } else {
705                return new %(mnem)sImm(machInst, %(dest)s,
706                                        %(op1)s, imm, rotC);
707            }
708        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
709
710    decode_block = '''
711    {
712        const uint32_t op = bits(machInst, 24, 21);
713        const bool s = (bits(machInst, 20) == 1);
714        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
715        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
716        const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
717                                 bits(machInst, 14, 12);
718        const bool rotC = ctrlImm > 3;
719        const uint32_t dataImm = bits(machInst, 7, 0);
720        const uint32_t imm = modified_imm(ctrlImm, dataImm);
721        switch (op) {
722          case 0x0:
723            if (rd == INTREG_PC) {
724                %(tst)s
725            } else {
726                %(and)s
727            }
728          case 0x1:
729            %(bic)s
730          case 0x2:
731            if (rn == INTREG_PC) {
732                %(mov)s
733            } else {
734                %(orr)s
735            }
736          case 0x3:
737            if (rn == INTREG_PC) {
738                %(mvn)s
739            } else {
740                %(orn)s
741            }
742          case 0x4:
743            if (rd == INTREG_PC) {
744                %(teq)s
745            } else {
746                %(eor)s
747            }
748          case 0x8:
749            if (rd == INTREG_PC) {
750                %(cmn)s
751            } else {
752                %(add)s
753            }
754          case 0xa:
755            %(adc)s
756          case 0xb:
757            %(sbc)s
758          case 0xd:
759            if (rd == INTREG_PC) {
760                %(cmp)s
761            } else {
762                %(sub)s
763            }
764          case 0xe:
765            %(rsb)s
766          default:
767            return new Unknown(machInst);
768        }
769    }
770    ''' % {
771        "tst" : decInst("Tst", "INTREG_ZERO"),
772        "and" : decInst("And"),
773        "bic" : decInst("Bic"),
774        "mov" : decInst("Mov", op1="INTREG_ZERO"),
775        "orr" : decInst("Orr"),
776        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
777        "orn" : decInst("Orn"),
778        "teq" : decInst("Teq", dest="INTREG_ZERO"),
779        "eor" : decInst("Eor"),
780        "cmn" : decInst("Cmn", dest="INTREG_ZERO"),
781        "add" : decInst("Add"),
782        "adc" : decInst("Adc"),
783        "sbc" : decInst("Sbc"),
784        "cmp" : decInst("Cmp", dest="INTREG_ZERO"),
785        "sub" : decInst("Sub"),
786        "rsb" : decInst("Rsb")
787    }
788}};
789
790def format Thumb32DataProcPlainBin() {{
791    decode_block = '''
792    {
793        const uint32_t op = bits(machInst, 24, 20);
794        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
795        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
796        switch (op) {
797          case 0x0:
798            {
799                const uint32_t imm = bits(machInst, 7, 0) |
800                                     (bits(machInst, 14, 12) << 8) |
801                                     (bits(machInst, 26) << 11);
802                if (rn == 0xf) {
803                    return new AdrImm(machInst, rd, (IntRegIndex)1,
804                                      imm, false);
805                } else {
806                    return new AddImm(machInst, rd, rn, imm, true);
807                }
808            }
809          case 0x4:
810            {
811                const uint32_t imm = bits(machInst, 7, 0) |
812                                     (bits(machInst, 14, 12) << 8) |
813                                     (bits(machInst, 26) << 11) |
814                                     (bits(machInst, 19, 16) << 12);
815                return new MovImm(machInst, rd, INTREG_ZERO, imm, true);
816            }
817          case 0xa:
818            {
819                const uint32_t imm = bits(machInst, 7, 0) |
820                                     (bits(machInst, 14, 12) << 8) |
821                                     (bits(machInst, 26) << 11);
822                if (rn == 0xf) {
823                    return new AdrImm(machInst, rd, (IntRegIndex)0,
824                                      imm, false);
825                } else {
826                    return new SubImm(machInst, rd, rn, imm, true);
827                }
828            }
829          case 0xc:
830            {
831                const uint32_t imm = bits(machInst, 7, 0) |
832                                     (bits(machInst, 14, 12) << 8) |
833                                     (bits(machInst, 26) << 11) |
834                                     (bits(machInst, 19, 16) << 12);
835                return new MovtImm(machInst, rd, rd, imm, true);
836            }
837          case 0x12:
838            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
839                return new WarnUnimplemented("ssat16", machInst);
840            }
841            // Fall through on purpose...
842          case 0x10:
843            return new WarnUnimplemented("ssat", machInst);
844          case 0x14:
845            return new WarnUnimplemented("sbfx", machInst);
846          case 0x16:
847            if (rn == 0xf) {
848                return new WarnUnimplemented("bfc", machInst);
849            } else {
850                return new WarnUnimplemented("bfi", machInst);
851            }
852          case 0x1a:
853            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
854                return new WarnUnimplemented("usat16", machInst);
855            }
856            // Fall through on purpose...
857          case 0x18:
858            return new WarnUnimplemented("usat", machInst);
859          case 0x1c:
860            return new WarnUnimplemented("ubfx", machInst);
861          default:
862            return new Unknown(machInst);
863        }
864    }
865    '''
866}};
867
868def format Thumb32DataProcShiftReg() {{
869
870    def decInst(mnem, dest="rd", op1="rn"):
871        return '''
872            if (s) {
873                return new %(mnem)sRegCc(machInst, %(dest)s,
874                                          %(op1)s, rm, amt, type);
875            } else {
876                return new %(mnem)sReg(machInst, %(dest)s,
877                                        %(op1)s, rm, amt, type);
878            }
879        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
880
881    decode_block = '''
882    {
883        const uint32_t op = bits(machInst, 24, 21);
884        const bool s = (bits(machInst, 20) == 1);
885        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
886        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
887        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
888        const uint32_t amt = (bits(machInst, 14, 12) << 2) |
889                              bits(machInst, 7, 6);
890        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
891        switch (op) {
892          case 0x0:
893            if (rd == INTREG_PC) {
894                %(tst)s
895            } else {
896                %(and)s
897            }
898          case 0x1:
899            %(bic)s
900          case 0x2:
901            if (rn == INTREG_PC) {
902                %(mov)s
903            } else {
904                %(orr)s
905            }
906          case 0x3:
907            if (rn == INTREG_PC) {
908                %(mvn)s
909            } else {
910                %(orn)s
911            }
912          case 0x4:
913            if (rd == INTREG_PC) {
914                %(teq)s
915            } else {
916                %(eor)s
917            }
918          case 0x6:
919            return new WarnUnimplemented("pkh", machInst);
920          case 0x8:
921            if (rd == INTREG_PC) {
922                %(cmn)s
923            } else {
924                %(add)s
925            }
926          case 0xa:
927            %(adc)s
928          case 0xb:
929            %(sbc)s
930          case 0xd:
931            if (rd == INTREG_PC) {
932                %(cmp)s
933            } else {
934                %(sub)s
935            }
936          case 0xe:
937            %(rsb)s
938          default:
939            return new Unknown(machInst);
940        }
941    }
942    ''' % {
943        "tst" : decInst("Tst", "INTREG_ZERO"),
944        "and" : decInst("And"),
945        "bic" : decInst("Bic"),
946        "mov" : decInst("Mov", op1="INTREG_ZERO"),
947        "orr" : decInst("Orr"),
948        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
949        "orn" : decInst("Orn"),
950        "teq" : decInst("Teq", "INTREG_ZERO"),
951        "eor" : decInst("Eor"),
952        "cmn" : decInst("Cmn", "INTREG_ZERO"),
953        "add" : decInst("Add"),
954        "adc" : decInst("Adc"),
955        "sbc" : decInst("Sbc"),
956        "cmp" : decInst("Cmp", "INTREG_ZERO"),
957        "sub" : decInst("Sub"),
958        "rsb" : decInst("Rsb")
959    }
960}};
961