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